From 22dfdd2832d46ade8aa350f8747138ea8fde2a41 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 24 Mar 2012 23:39:19 +0100 Subject: [PATCH 0001/1445] Initial commit --- README.md | 10 + audio/CMakeLists.txt | 11 + audio/mixer.cpp | 195 + audio/mixer.h | 41 + audio/wav_read.cpp | 73 + audio/wav_read.h | 7 + base/CMakeLists.txt | 20 + base/LAME.cpp | 7 + base/LAME.h | 27 + base/LAMEApp.cpp | 48 + base/LAMEApp.h | 84 + base/LAMEString.cpp | 411 ++ base/LAMEString.h | 99 + base/basictypes.h | 92 + base/color.h | 43 + base/colorutil.cpp | 86 + base/colorutil.h | 9 + base/error_context.cpp | 39 + base/error_context.h | 18 + base/logging.h | 59 + base/scoped_ptr.h | 28 + base/stats.h | 17 + base/stringutil.h | 18 + base/timeutil.cpp | 80 + base/timeutil.h | 19 + collision/CMakeLists.txt | 9 + collision/collision.cpp | 288 ++ collision/collision.h | 89 + ext/etcpack/CMakeLists.txt | 36 + ext/etcpack/README | 7 + ext/etcpack/etcdec.cpp | 418 ++ ext/etcpack/etcdec.h | 9 + ext/etcpack/etcpack.cpp | 5730 ++++++++++++++++++++++++++ ext/etcpack/etcpack.h | 26 + ext/etcpack/etctool.cpp | 1612 ++++++++ ext/etcpack/image.cpp | 212 + ext/etcpack/image.h | 33 + ext/etcpack/license.txt | 69 + ext/etcpack/version_1_0_6.txt | 49 + ext/libzip/Android.mk | 77 + ext/libzip/CMakeLists.txt | 64 + ext/libzip/config.h | 97 + ext/libzip/libzip.la | 41 + ext/libzip/mkstemp.c | 140 + ext/libzip/zip.h | 230 ++ ext/libzip/zip_add.c | 49 + ext/libzip/zip_add_dir.c | 80 + ext/libzip/zip_close.c | 679 +++ ext/libzip/zip_delete.c | 58 + ext/libzip/zip_dirent.c | 615 +++ ext/libzip/zip_entry_free.c | 52 + ext/libzip/zip_entry_new.c | 78 + ext/libzip/zip_err_str.c | 68 + ext/libzip/zip_error.c | 101 + ext/libzip/zip_error_clear.c | 44 + ext/libzip/zip_error_get.c | 44 + ext/libzip/zip_error_get_sys_type.c | 47 + ext/libzip/zip_error_strerror.c | 90 + ext/libzip/zip_error_to_str.c | 70 + ext/libzip/zip_fclose.c | 71 + ext/libzip/zip_file_error_clear.c | 44 + ext/libzip/zip_file_error_get.c | 44 + ext/libzip/zip_file_get_offset.c | 74 + ext/libzip/zip_file_strerror.c | 44 + ext/libzip/zip_filerange_crc.c | 71 + ext/libzip/zip_fopen.c | 49 + ext/libzip/zip_fopen_index.c | 216 + ext/libzip/zip_fread.c | 130 + ext/libzip/zip_free.c | 81 + ext/libzip/zip_get_archive_comment.c | 60 + ext/libzip/zip_get_archive_flag.c | 48 + ext/libzip/zip_get_file_comment.c | 58 + ext/libzip/zip_get_name.c | 71 + ext/libzip/zip_get_num_files.c | 47 + ext/libzip/zip_memdup.c | 55 + ext/libzip/zip_name_locate.c | 88 + ext/libzip/zip_new.c | 70 + ext/libzip/zip_open.c | 567 +++ ext/libzip/zip_rename.c | 65 + ext/libzip/zip_replace.c | 78 + ext/libzip/zip_set_archive_comment.c | 65 + ext/libzip/zip_set_archive_flag.c | 49 + ext/libzip/zip_set_file_comment.c | 66 + ext/libzip/zip_set_name.c | 75 + ext/libzip/zip_source_buffer.c | 157 + ext/libzip/zip_source_file.c | 55 + ext/libzip/zip_source_filep.c | 216 + ext/libzip/zip_source_free.c | 51 + ext/libzip/zip_source_function.c | 59 + ext/libzip/zip_source_zip.c | 188 + ext/libzip/zip_stat.c | 49 + ext/libzip/zip_stat_index.c | 90 + ext/libzip/zip_stat_init.c | 51 + ext/libzip/zip_strerror.c | 44 + ext/libzip/zip_unchange.c | 82 + ext/libzip/zip_unchange_all.c | 54 + ext/libzip/zip_unchange_archive.c | 52 + ext/libzip/zip_unchange_data.c | 53 + ext/libzip/zipint.h | 264 ++ ext/rapidxml/license.txt | 52 + ext/rapidxml/manual.html | 406 ++ ext/rapidxml/rapidxml.hpp | 2596 ++++++++++++ ext/rapidxml/rapidxml_iterators.hpp | 174 + ext/rapidxml/rapidxml_print.hpp | 421 ++ ext/rapidxml/rapidxml_utils.hpp | 122 + ext/sha1/CMakeLists.txt | 10 + ext/sha1/SHA1.cpp | 259 ++ ext/sha1/sha1.h | 263 ++ ext/stb_vorbis/CMakeLists.txt | 10 + ext/stb_vorbis/stb_vorbis.c | 5045 +++++++++++++++++++++++ ext/stb_vorbis/stb_vorbis.h | 329 ++ ext/vjson/CMakeLists.txt | 10 + ext/vjson/block_allocator.cpp | 50 + ext/vjson/block_allocator.h | 35 + ext/vjson/json.cpp | 620 +++ ext/vjson/json.h | 103 + ext/vjson/main.cpp | 118 + file/CMakeLists.txt | 13 + file/chunk_file.cpp | 274 ++ file/chunk_file.h | 66 + file/easy_file.cpp | 96 + file/easy_file.h | 55 + file/file_util.cpp | 125 + file/file_util.h | 11 + file/vfs.h | 12 + file/zip_read.cpp | 137 + file/zip_read.h | 45 + gfx/CMakeLists.txt | 14 + gfx/gl_debug_log.cpp | 66 + gfx/gl_debug_log.h | 24 + gfx/gl_lost_manager.cpp | 49 + gfx/gl_lost_manager.h | 16 + gfx/texture.cpp | 287 ++ gfx/texture.h | 44 + gfx/texture_atlas.cpp | 2 + gfx/texture_atlas.h | 38 + gfx/texture_dx11.cpp | 272 ++ gfx/texture_gen.cpp | 54 + gfx/texture_gen.h | 11 + gfx_es1/CMakeLists.txt | 10 + gfx_es1/draw_buffer.cpp | 287 ++ gfx_es1/draw_buffer.h | 122 + gfx_es2/CMakeLists.txt | 12 + gfx_es2/draw_buffer.cpp | 287 ++ gfx_es2/draw_buffer.h | 110 + gfx_es2/fbo.cpp | 90 + gfx_es2/fbo.h | 20 + gfx_es2/glsl_program.cpp | 203 + gfx_es2/glsl_program.h | 72 + gfx_es2/vertex_format.cpp | 71 + gfx_es2/vertex_format.h | 49 + image/CMakeLists.txt | 14 + image/build.scons | 15 + image/png_load.cpp | 91 + image/png_load.h | 11 + image/surface.h | 31 + image/zim_load.cpp | 139 + image/zim_load.h | 47 + image/zim_save.cpp | 247 ++ image/zim_save.h | 11 + input/gesture_detector.cpp | 68 + input/gesture_detector.h | 20 + input/input_state.h | 53 + json/CMakeLists.txt | 15 + json/json_writer.cpp | 116 + json/json_writer.h | 55 + json/json_writer_test.cpp | 25 + math/CMakeLists.txt | 13 + math/build.scons | 8 + math/compression.h | 21 + math/lin/aabb.cpp | 272 ++ math/lin/aabb.h | 47 + math/lin/build.scons | 12 + math/lin/matrix4x4.cpp | 276 ++ math/lin/matrix4x4.h | 141 + math/lin/matrix_neon.s | 106 + math/lin/plane.cpp | 13 + math/lin/plane.h | 41 + math/lin/quat.cpp | 124 + math/lin/quat.h | 92 + math/lin/ray.h | 20 + math/lin/vec3.cpp | 28 + math/lin/vec3.h | 158 + math/math_util.cc | 19 + math/math_util.h | 86 + native.vcxproj | 183 + native.vcxproj.filters | 299 ++ profiler/CMakeLists.txt | 11 + profiler/profiler.cpp | 84 + profiler/profiler.h | 37 + util/bits/bits.cc | 40 + util/bits/bits.h | 28 + util/bits/hamming.h | 27 + util/bits/varint.cc | 35 + util/bits/varint.h | 13 + util/build.scons | 20 + util/hash/hash.cc | 65 + util/hash/hash.h | 30 + util/random/perlin.cc | 72 + util/random/perlin.h | 8 + util/random/rng.h | 26 + 201 files changed, 33683 insertions(+) create mode 100644 README.md create mode 100644 audio/CMakeLists.txt create mode 100644 audio/mixer.cpp create mode 100644 audio/mixer.h create mode 100644 audio/wav_read.cpp create mode 100644 audio/wav_read.h create mode 100644 base/CMakeLists.txt create mode 100644 base/LAME.cpp create mode 100644 base/LAME.h create mode 100644 base/LAMEApp.cpp create mode 100644 base/LAMEApp.h create mode 100644 base/LAMEString.cpp create mode 100644 base/LAMEString.h create mode 100644 base/basictypes.h create mode 100644 base/color.h create mode 100644 base/colorutil.cpp create mode 100644 base/colorutil.h create mode 100644 base/error_context.cpp create mode 100644 base/error_context.h create mode 100644 base/logging.h create mode 100644 base/scoped_ptr.h create mode 100644 base/stats.h create mode 100644 base/stringutil.h create mode 100644 base/timeutil.cpp create mode 100644 base/timeutil.h create mode 100644 collision/CMakeLists.txt create mode 100644 collision/collision.cpp create mode 100644 collision/collision.h create mode 100644 ext/etcpack/CMakeLists.txt create mode 100644 ext/etcpack/README create mode 100644 ext/etcpack/etcdec.cpp create mode 100644 ext/etcpack/etcdec.h create mode 100644 ext/etcpack/etcpack.cpp create mode 100644 ext/etcpack/etcpack.h create mode 100644 ext/etcpack/etctool.cpp create mode 100644 ext/etcpack/image.cpp create mode 100644 ext/etcpack/image.h create mode 100644 ext/etcpack/license.txt create mode 100644 ext/etcpack/version_1_0_6.txt create mode 100644 ext/libzip/Android.mk create mode 100644 ext/libzip/CMakeLists.txt create mode 100644 ext/libzip/config.h create mode 100644 ext/libzip/libzip.la create mode 100644 ext/libzip/mkstemp.c create mode 100644 ext/libzip/zip.h create mode 100644 ext/libzip/zip_add.c create mode 100644 ext/libzip/zip_add_dir.c create mode 100644 ext/libzip/zip_close.c create mode 100644 ext/libzip/zip_delete.c create mode 100644 ext/libzip/zip_dirent.c create mode 100644 ext/libzip/zip_entry_free.c create mode 100644 ext/libzip/zip_entry_new.c create mode 100644 ext/libzip/zip_err_str.c create mode 100644 ext/libzip/zip_error.c create mode 100644 ext/libzip/zip_error_clear.c create mode 100644 ext/libzip/zip_error_get.c create mode 100644 ext/libzip/zip_error_get_sys_type.c create mode 100644 ext/libzip/zip_error_strerror.c create mode 100644 ext/libzip/zip_error_to_str.c create mode 100644 ext/libzip/zip_fclose.c create mode 100644 ext/libzip/zip_file_error_clear.c create mode 100644 ext/libzip/zip_file_error_get.c create mode 100644 ext/libzip/zip_file_get_offset.c create mode 100644 ext/libzip/zip_file_strerror.c create mode 100644 ext/libzip/zip_filerange_crc.c create mode 100644 ext/libzip/zip_fopen.c create mode 100644 ext/libzip/zip_fopen_index.c create mode 100644 ext/libzip/zip_fread.c create mode 100644 ext/libzip/zip_free.c create mode 100644 ext/libzip/zip_get_archive_comment.c create mode 100644 ext/libzip/zip_get_archive_flag.c create mode 100644 ext/libzip/zip_get_file_comment.c create mode 100644 ext/libzip/zip_get_name.c create mode 100644 ext/libzip/zip_get_num_files.c create mode 100644 ext/libzip/zip_memdup.c create mode 100644 ext/libzip/zip_name_locate.c create mode 100644 ext/libzip/zip_new.c create mode 100644 ext/libzip/zip_open.c create mode 100644 ext/libzip/zip_rename.c create mode 100644 ext/libzip/zip_replace.c create mode 100644 ext/libzip/zip_set_archive_comment.c create mode 100644 ext/libzip/zip_set_archive_flag.c create mode 100644 ext/libzip/zip_set_file_comment.c create mode 100644 ext/libzip/zip_set_name.c create mode 100644 ext/libzip/zip_source_buffer.c create mode 100644 ext/libzip/zip_source_file.c create mode 100644 ext/libzip/zip_source_filep.c create mode 100644 ext/libzip/zip_source_free.c create mode 100644 ext/libzip/zip_source_function.c create mode 100644 ext/libzip/zip_source_zip.c create mode 100644 ext/libzip/zip_stat.c create mode 100644 ext/libzip/zip_stat_index.c create mode 100644 ext/libzip/zip_stat_init.c create mode 100644 ext/libzip/zip_strerror.c create mode 100644 ext/libzip/zip_unchange.c create mode 100644 ext/libzip/zip_unchange_all.c create mode 100644 ext/libzip/zip_unchange_archive.c create mode 100644 ext/libzip/zip_unchange_data.c create mode 100644 ext/libzip/zipint.h create mode 100644 ext/rapidxml/license.txt create mode 100644 ext/rapidxml/manual.html create mode 100644 ext/rapidxml/rapidxml.hpp create mode 100644 ext/rapidxml/rapidxml_iterators.hpp create mode 100644 ext/rapidxml/rapidxml_print.hpp create mode 100644 ext/rapidxml/rapidxml_utils.hpp create mode 100644 ext/sha1/CMakeLists.txt create mode 100644 ext/sha1/SHA1.cpp create mode 100644 ext/sha1/sha1.h create mode 100644 ext/stb_vorbis/CMakeLists.txt create mode 100644 ext/stb_vorbis/stb_vorbis.c create mode 100644 ext/stb_vorbis/stb_vorbis.h create mode 100644 ext/vjson/CMakeLists.txt create mode 100644 ext/vjson/block_allocator.cpp create mode 100644 ext/vjson/block_allocator.h create mode 100644 ext/vjson/json.cpp create mode 100644 ext/vjson/json.h create mode 100644 ext/vjson/main.cpp create mode 100644 file/CMakeLists.txt create mode 100644 file/chunk_file.cpp create mode 100644 file/chunk_file.h create mode 100644 file/easy_file.cpp create mode 100644 file/easy_file.h create mode 100644 file/file_util.cpp create mode 100644 file/file_util.h create mode 100644 file/vfs.h create mode 100644 file/zip_read.cpp create mode 100644 file/zip_read.h create mode 100644 gfx/CMakeLists.txt create mode 100644 gfx/gl_debug_log.cpp create mode 100644 gfx/gl_debug_log.h create mode 100644 gfx/gl_lost_manager.cpp create mode 100644 gfx/gl_lost_manager.h create mode 100644 gfx/texture.cpp create mode 100644 gfx/texture.h create mode 100644 gfx/texture_atlas.cpp create mode 100644 gfx/texture_atlas.h create mode 100644 gfx/texture_dx11.cpp create mode 100644 gfx/texture_gen.cpp create mode 100644 gfx/texture_gen.h create mode 100644 gfx_es1/CMakeLists.txt create mode 100644 gfx_es1/draw_buffer.cpp create mode 100644 gfx_es1/draw_buffer.h create mode 100644 gfx_es2/CMakeLists.txt create mode 100644 gfx_es2/draw_buffer.cpp create mode 100644 gfx_es2/draw_buffer.h create mode 100644 gfx_es2/fbo.cpp create mode 100644 gfx_es2/fbo.h create mode 100644 gfx_es2/glsl_program.cpp create mode 100644 gfx_es2/glsl_program.h create mode 100644 gfx_es2/vertex_format.cpp create mode 100644 gfx_es2/vertex_format.h create mode 100644 image/CMakeLists.txt create mode 100644 image/build.scons create mode 100644 image/png_load.cpp create mode 100644 image/png_load.h create mode 100644 image/surface.h create mode 100644 image/zim_load.cpp create mode 100644 image/zim_load.h create mode 100644 image/zim_save.cpp create mode 100644 image/zim_save.h create mode 100644 input/gesture_detector.cpp create mode 100644 input/gesture_detector.h create mode 100644 input/input_state.h create mode 100644 json/CMakeLists.txt create mode 100644 json/json_writer.cpp create mode 100644 json/json_writer.h create mode 100644 json/json_writer_test.cpp create mode 100644 math/CMakeLists.txt create mode 100644 math/build.scons create mode 100644 math/compression.h create mode 100644 math/lin/aabb.cpp create mode 100644 math/lin/aabb.h create mode 100644 math/lin/build.scons create mode 100644 math/lin/matrix4x4.cpp create mode 100644 math/lin/matrix4x4.h create mode 100644 math/lin/matrix_neon.s create mode 100644 math/lin/plane.cpp create mode 100644 math/lin/plane.h create mode 100644 math/lin/quat.cpp create mode 100644 math/lin/quat.h create mode 100644 math/lin/ray.h create mode 100644 math/lin/vec3.cpp create mode 100644 math/lin/vec3.h create mode 100644 math/math_util.cc create mode 100644 math/math_util.h create mode 100644 native.vcxproj create mode 100644 native.vcxproj.filters create mode 100644 profiler/CMakeLists.txt create mode 100644 profiler/profiler.cpp create mode 100644 profiler/profiler.h create mode 100644 util/bits/bits.cc create mode 100644 util/bits/bits.h create mode 100644 util/bits/hamming.h create mode 100644 util/bits/varint.cc create mode 100644 util/bits/varint.h create mode 100644 util/build.scons create mode 100644 util/hash/hash.cc create mode 100644 util/hash/hash.h create mode 100644 util/random/perlin.cc create mode 100644 util/random/perlin.h create mode 100644 util/random/rng.h diff --git a/README.md b/README.md new file mode 100644 index 0000000000..e19503015c --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +native +====== + +This is my library of stuff that I use when writing C++ programs, mostly for Android. It has some basic OpenGL utility code, JSON read/write (two libraries that should be made more similar), 2D texture atlases and drawing code, ETC1 texture loading support, basic logging, etc. The associated tools to create ZIM texture files and atlases do not yet live here but I might move them here eventually. + +If you find this useful for your own projects, drop me a line at hrydgard@gmail.com . + +I hereby release this code under the BSD license. + +Henrik Rydgård diff --git a/audio/CMakeLists.txt b/audio/CMakeLists.txt new file mode 100644 index 0000000000..3d742499b2 --- /dev/null +++ b/audio/CMakeLists.txt @@ -0,0 +1,11 @@ +set(SRCS + mixer.cpp + wav_read.cpp) + +set(SRCS ${SRCS}) + +add_library(mixer STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/audio/mixer.cpp b/audio/mixer.cpp new file mode 100644 index 0000000000..f69233de75 --- /dev/null +++ b/audio/mixer.cpp @@ -0,0 +1,195 @@ +#include + +#include "audio/mixer.h" +#include "audio/wav_read.h" +#include "base/logging.h" +#include "ext/stb_vorbis/stb_vorbis.h" +#include "file/vfs.h" + +// TODO: +// * Vorbis streaming playback + +struct ChannelEffectState { + // Filter state +}; + +enum CLIP_TYPE { + CT_PCM16, + CT_SYNTHFX, + CT_VORBIS, + // CT_PHOENIX? +}; + +struct Clip { + int type; + + short *data; + int length; + int num_channels; // this is NOT stereo vs mono + int sample_rate; + int loop_start; + int loop_end; +}; + +// If current_clip == 0, the channel is free. + +enum PlaybackState { + PB_STOPPED = 0, + PB_PLAYING = 1, +}; + + +struct Channel { + const Clip *current_clip; + // Playback state + PlaybackState state; + int pos; + PlayParams params; + // Effect state + ChannelEffectState effect_state; +}; + +struct Mixer { + Channel *channels; + int sample_rate; + int num_channels; + int num_fixed_channels; +}; + +Mixer *mixer_create(int sample_rate, int channels, int fixed_channels) { + Mixer *mixer = new Mixer(); + memset(mixer, 0, sizeof(Mixer)); + mixer->channels = new Channel[channels]; + memset(mixer->channels, 0, sizeof(Channel) * channels); + mixer->sample_rate = sample_rate; + mixer->num_channels = channels; + mixer->num_fixed_channels = fixed_channels; + return mixer; +} + +void mixer_destroy(Mixer *mixer) { + delete [] mixer->channels; + delete mixer; +} + +static int get_free_channel(Mixer *mixer) { + int chan_with_biggest_pos = -1; + int biggest_pos = -1; + for (int i = mixer->num_fixed_channels; i < mixer->num_channels; i++) { + Channel *chan = &mixer->channels[i]; + if (!chan->current_clip) { + return i; + } + if (chan->pos > biggest_pos) { + biggest_pos = chan->pos; + chan_with_biggest_pos = i; + } + } + return chan_with_biggest_pos; +} + +Clip *clip_load(const char *filename) { + short *data; + int num_samples, sample_rate, num_channels; + + if (!strcmp(filename + strlen(filename) - 4, ".ogg")) { + // Ogg file. For now, directly decompress, no streaming support. + uint8_t *filedata; + size_t size; + filedata = VFSReadFile(filename, &size); + num_samples = stb_vorbis_decode_memory(filedata, size, &num_channels, &data); + if (num_samples <= 0) + return NULL; + sample_rate = 44100; + ILOG("read ogg %s, length %i, rate %i", filename, num_samples, sample_rate); + } else { + // Wav file. Easy peasy. + data = wav_read(filename, &num_samples, &sample_rate, &num_channels); + if (!data) { + return NULL; + } + } + + Clip *clip = new Clip(); + clip->type = CT_PCM16; + clip->data = data; + clip->length = num_samples; + clip->num_channels = num_channels; + clip->sample_rate = sample_rate; + clip->loop_start = 0; + clip->loop_end = 0; + return clip; +} + +void clip_destroy(Clip *clip) { + if (clip) { + free(clip->data); + delete clip; + } else { + ELOG("Can't destroy zero clip"); + } +} + +int clip_length(const Clip *clip) { + return clip->length; +} + +void clip_set_loop(Clip *clip, int start, int end) { + clip->loop_start = start; + clip->loop_end = end; +} + +PlayParams *mixer_play_clip(Mixer *mixer, const Clip *clip, int channel) { + if (channel == -1) { + channel = get_free_channel(mixer); + } + + Channel *chan = &mixer->channels[channel]; + // Think about this order and make sure it's thread"safe" (not perfect but should not cause crashes). + chan->pos = 0; + chan->current_clip = clip; + chan->state = PB_PLAYING; + PlayParams *params = &chan->params; + params->volume = 128; + params->pan = 128; + return params; +} + +void mixer_mix(Mixer *mixer, short *buffer, int num_samples) { + // Clear the buffer. + memset(buffer, 0, num_samples * sizeof(short) * 2); + for (int i = 0; i < mixer->num_channels; i++) { + Channel *chan = &mixer->channels[i]; + if (chan->state == PB_PLAYING) { + const Clip *clip = chan->current_clip; + if (clip->type == CT_PCM16) { + // For now, only allow mono PCM + CHECK(clip->num_channels == 1); + if (true || chan->params.delta == 0) { + // Fast playback of non pitched clips + int cnt = num_samples; + if (clip->length - chan->pos < cnt) { + cnt = clip->length - chan->pos; + } + // TODO: Take pan into account. + int left_volume = chan->params.volume; + int right_volume = chan->params.volume; + // TODO: NEONize. Can also make special loops for left_volume == right_volume etc. + for (int s = 0; s < cnt; s++) { + int cdata = clip->data[chan->pos]; + buffer[s * 2 ] += cdata * left_volume >> 8; + buffer[s * 2 + 1] += cdata * right_volume >> 8; + chan->pos++; + } + if (chan->pos >= clip->length) { + chan->state = PB_STOPPED; + chan->current_clip = 0; + break; + } + } + } else if (clip->type == CT_VORBIS) { + // For music + } + } + } +} diff --git a/audio/mixer.h b/audio/mixer.h new file mode 100644 index 0000000000..685b901948 --- /dev/null +++ b/audio/mixer.h @@ -0,0 +1,41 @@ +#include "base/basictypes.h" + +// Simple mixer intended for sound effects for games. +// Intended both for fire and forget sfx (auto channels) and for +// realtime-modifiable sounds like pitched engine noises (fixed channels). + +struct Mixer; +struct Clip; +struct Channel; + +// This struct is public for easy manipulation of running channels. +struct PlayParams { + uint8_t volume; // 0-255 + uint8_t pan; // 0-255, 127 is dead center. + int32_t delta; +}; + +// Mixer +// ========================== +// For now, channels is required to be 2. +Mixer *mixer_create(int sample_rate, int channels, int fixed_channels); +void mixer_destroy(Mixer *mixer); + +// Buffer must be r/w, for efficient mixing +// TODO: Use local buffer instead. +void mixer_mix(Mixer *mixer, short *buffer, int num_samples); + +// Clip +// ========================== +Clip *clip_load(const char *filename); +void clip_destroy(Clip *clip); + +int clip_length(); +void clip_set_loop(int start, int end); + + +// The returned PlayState pointer can be used to set the playback parameters, +// but must not be kept around unless you are using a fixed channel. +// Channel must be either -1 for auto assignment to a free channel, or less +// than the number of fixed channels that the mixer was created with. +PlayParams *mixer_play_clip(Mixer *mixer, const Clip *clip, int channel); diff --git a/audio/wav_read.cpp b/audio/wav_read.cpp new file mode 100644 index 0000000000..0d7c72c9a1 --- /dev/null +++ b/audio/wav_read.cpp @@ -0,0 +1,73 @@ +#include "base/basictypes.h" +#include "base/logging.h" +#include "audio/wav_read.h" +#include "file/chunk_file.h" + +short *wav_read(const char *filename, + int *num_samples, int *sample_rate, + int *num_channels) { + ChunkFile cf(filename, true); + if (cf.failed()) { + WLOG("ERROR: Wave file %s could not be opened", filename); + return 0; + } + + short *data = 0; + int samplesPerSec, avgBytesPerSec,wBlockAlign,wBytesPerSample; + if (cf.descend('RIFF')) { + cf.readInt(); //get past 'WAVE' + if (cf.descend('fmt ')) //enter the format chunk + { + int temp; + temp = cf.readInt(); + int format = temp & 0xFFFF; + if (format != 1) { + cf.ascend(); + cf.ascend(); + ELOG("Error - bad format"); + return NULL; + } + *num_channels = temp >> 16; + samplesPerSec = cf.readInt(); + avgBytesPerSec = cf.readInt(); + + temp = cf.readInt(); + wBlockAlign = temp & 0xFFFF; + wBytesPerSample = temp >> 16; + cf.ascend(); + // ILOG("got fmt data: %i", samplesPerSec); + } else { + ELOG("Error - no format chunk in wav"); + cf.ascend(); + return NULL; + } + + if (cf.descend('data')) //enter the data chunk + { + int numBytes = cf.getCurrentChunkSize(); + int numSamples = numBytes / wBlockAlign; + data = (short *)malloc(sizeof(short) * numSamples * *num_channels); + *num_samples = numSamples; + if (wBlockAlign == 2 && *num_channels == 1) { + cf.readData((uint8*)data,numBytes); + } else { + ELOG("Error - bad blockalign or channels"); + free(data); + return NULL; + } + // ILOG("got wave data: %i", numSamples); + cf.ascend(); + } else { + ELOG("Error - no data chunk in wav"); + cf.ascend(); + return NULL; + } + cf.ascend(); + } else { + ELOG("Could not descend into RIFF file"); + return NULL; + } + *sample_rate = samplesPerSec; + ILOG("read wav %s, length %i, rate %i", filename, *num_samples, *sample_rate); + return data; +} diff --git a/audio/wav_read.h b/audio/wav_read.h new file mode 100644 index 0000000000..a3df5f616d --- /dev/null +++ b/audio/wav_read.h @@ -0,0 +1,7 @@ +#include "base/basictypes.h" + +// Allocates a buffer that should be freed using free(). +short *wav_read(const char *filename, + int *num_samples, int *sample_rate, + int *num_channels); +// TODO: Non-allocating version. diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt new file mode 100644 index 0000000000..060fd25425 --- /dev/null +++ b/base/CMakeLists.txt @@ -0,0 +1,20 @@ +set(SRCS + LAME.cpp + LAMEApp.cpp + LAMEString.cpp + colorutil.cpp + error_context.cpp) + +set(SRCS ${SRCS}) + +add_library(base STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) + +add_library(timeutil STATIC timeutil.cpp) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/base/LAME.cpp b/base/LAME.cpp new file mode 100644 index 0000000000..1e3636fd43 --- /dev/null +++ b/base/LAME.cpp @@ -0,0 +1,7 @@ +#include "LAME.h" +#include "LAMEString.h" + +String getUserName() +{ + return String("user"); +} diff --git a/base/LAME.h b/base/LAME.h new file mode 100644 index 0000000000..892ae6aae6 --- /dev/null +++ b/base/LAME.h @@ -0,0 +1,27 @@ +#ifndef __LAME_H__ +#define __LAME_H__ + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/color.h" + + +#ifndef PI +#define PI 3.141592653589793f +#endif + +template +inline T MIN(T t1, T t2) { + return t1 +inline T MAX(T t1, T t2) { + return t1>t2 ? t1 : t2; +} + +template +inline T ABS(T &t) { + if (t<0) return -t; else return t; +} + +#endif //__LAME_H__ diff --git a/base/LAMEApp.cpp b/base/LAMEApp.cpp new file mode 100644 index 0000000000..3c9240cbc2 --- /dev/null +++ b/base/LAMEApp.cpp @@ -0,0 +1,48 @@ +#ifndef _WIN32 +#include +#endif + +#include "LAMEApp.h" + +LAMEApp::LAMEApp() { + penDown=false; + wannaQuit=false; + active=0; + + TCHAR tmp[256]; +#ifdef _WIN32 + hWnd=0; + GetModuleFileName(0,tmp,255); +#else + char *discard = getcwd(tmp, 256); + discard++; +#endif + + path=tmp; + path=path.getPath()+String(TEXT("/")); +} + +LAMEApp::~LAMEApp() { +} + +bool LAMEApp::init(int width, int height) { + this->width = width; + this->height = height; + return true; +} + +int LAMEApp::run() { + return -1; +} + +void LAMEApp::close() { + wannaQuit = true; +} + +void LAMEApp::startTimer(int ID, int interval) { +// SetTimer(hWnd, ID, interval, 0); +} + +void LAMEApp::stopTimer(int ID) { +// KillTimer(hWnd, ID); +} diff --git a/base/LAMEApp.h b/base/LAMEApp.h new file mode 100644 index 0000000000..77310588cf --- /dev/null +++ b/base/LAMEApp.h @@ -0,0 +1,84 @@ +#pragma once + +//LAME: the Lean And MEan Extensions. + +// #include "gfx/draw_buffer.h" +#include "LAMEString.h" + +class LAMEApp { + protected: + bool wannaQuit; + bool active; + int width; + int height; +#ifndef WINCE + public: +#endif + bool penDown; + protected: + String path; + public: + LAMEApp(); + virtual ~LAMEApp(); + + bool init(int width, int height); + virtual int run(); + void close(); + + void startTimer(int ID, int interval); + void stopTimer(int ID); + + void refresh(); + + virtual void onLoop() { } + + virtual void onButtonDown(int b) {} + virtual void onButtonUp(int b) {} + + virtual void onPenDown(int x, int y) { } + virtual void onPenMove(int x, int y, bool pressed) { } + virtual void onPenUp(int x, int y) { } + + virtual void onKeyDown(int key) { } + virtual void onKeyChar(int key) { } + virtual void onKeyUp(int key) { } + + virtual void onLostFocus() { } + virtual void onGotFocus() { } + + virtual void onCreate() { } + virtual void onDestroy() { } + virtual void onTimer(int timerID) { } + + virtual void draw() { } + + int getWidth() const {return width;} + int getHeight() const { return height;} + String getPath() const { + return path; + } +}; + +inline String getRelativePath(String temp) +{ +#if defined(ANDROID) || defined(SDL) + return temp; +#else + #error TODO: check this + if (!theApp) return temp; +#ifdef WINCE + if (temp[0] != TCHAR('\\')) //if it's a relative path (assume to the program location), then let's expand it to a full path + if (temp.find(theApp->getPath(),0)==-1) + { + return theApp->getPath() + temp; + } +#else + if (temp[2] != TCHAR('\\')) //if it's a relative path (assume to the program location), then let's expand it to a full path + if (temp.find(theApp->getPath(),0)==-1) + { + return theApp->getPath() + temp; + } +#endif + return temp; +#endif +} diff --git a/base/LAMEString.cpp b/base/LAMEString.cpp new file mode 100644 index 0000000000..a5a601a870 --- /dev/null +++ b/base/LAMEString.cpp @@ -0,0 +1,411 @@ +#include +#include +#include +#include "LAMEString.h" + +#define assert(a) + +const int MAX_LENGTH = 1024; // largest size string for input + +#define _tcslen strlen +#define _tcscpy strcpy +#define _tcscmp strcmp +#define _tcsncmp strncmp + + +String::String() +{ + Capacity = 1; + CString = new TCHAR[Capacity]; + CString[0] = '\0'; // make c-style string zero length +} + +String::String(const TCHAR * s) +{ + Capacity = (int)_tcslen(s) + 1; + CString = new TCHAR[Capacity]; + _tcscpy(CString,s); +} + +String::String(const String & str) +{ + Capacity = str.length() + 1; + CString = new TCHAR[Capacity]; + _tcscpy(CString,str.CString); +} + +String::~String() +{ + delete [] CString; // free memory +} + +const String & String::operator = (const String & rhs) +{ + if (this != &rhs) { // check aliasing + if (Capacity < rhs.length() + 1) { // more memory needed? + delete[] CString; // delete old string + Capacity = rhs.length() + 1; // add 1 for '\0' + CString = new TCHAR[Capacity]; + } + _tcscpy(CString,rhs.CString); + } + return *this; +} + + +const String & String::operator = (const TCHAR * s) +{ + int len = 0; // length of newly constructed string + assert(s != 0); // make sure s non-NULL + len = (int)_tcslen(s); // # of characters in string + + // free old string if necessary + + if (Capacity < len + 1) + { + delete[] CString; // delete old string + Capacity = len + 1; // add 1 for '\0' + CString = new TCHAR[Capacity]; + } + _tcscpy(CString,s); + return *this; +} + +const String & String::operator = (TCHAR ch) +{ + if (Capacity < 2) + { + delete [] CString; + Capacity = 2; + CString = new TCHAR[Capacity]; + } + CString[0] = ch; // make string one character long + CString[1] = '\0'; + return *this; +} + +int String::length() const { + int myLength = 0; + while (CString[myLength] != '\0') + myLength++; + return myLength; +} + +TCHAR * String::getPointer() const +{ + return CString; +} + +TCHAR & String::operator [] (int k) +{ + if (k < 0 || (int)_tcslen(CString) <= k) + { + //cerr << "index out of range: " << k << " string: " << CString << endl; + assert(0 <= k && k < _tcslen(CString)); + } + return CString[k]; +} + + +const String & String::operator += (const String & str) +{ + String copystring(str); // copy to avoid aliasing problems + + int newLength = length() + str.length(); // self + added string + int lastLocation = length(); // index of '\0' + + // check to see if local buffer not big enough + if (newLength >= Capacity) + { + Capacity = newLength + 1; + TCHAR * newBuffer = new TCHAR[Capacity]; + _tcscpy(newBuffer,CString); // copy into new buffer + delete [] CString; // delete old string + CString = newBuffer; + } + + // now catenate str (copystring) to end of CString + _tcscpy(CString+lastLocation,copystring.getPointer() ); + + return *this; +} + +const String & String::operator += (const TCHAR * s) +{ + int newLength = length() + (int)_tcslen(s); // self + added string + int lastLocation = length(); // index of '\0' + + // check to see if local buffer not big enough + if (newLength >= Capacity) + { + Capacity = newLength + 1; + TCHAR * newBuffer = new TCHAR[Capacity]; + _tcscpy(newBuffer,CString); // copy into new buffer + delete [] CString; // delete old string + CString = newBuffer; + } + + // now catenate s to end of CString + _tcscpy(CString+lastLocation,s); + + return *this; +} + +const String & String::operator += ( TCHAR ch ) +{ + String temp; // make string equivalent of ch + temp = ch; + *this += temp; + return *this; +} + +String operator + (const String & lhs, const String & rhs) +{ + String result(lhs); // copies lhs to result + result += rhs; // catenate rhs + return result; // returns a copy of result +} + +String operator + ( TCHAR ch, const String & str ) +{ + String result; // make string equivalent of ch + result = ch; + result += str; + return result; +} + +String operator + ( const String & str, TCHAR ch ) +{ + String result(str); + result += ch; + return result; +} + + +String String::subString(int pos, int len) const +{ + String result(*this); // make sure enough space allocated + + if(pos < 0) // start at front when pos < 0 + { + pos = 0; + } + + if(pos >= (int)_tcslen(CString)) + { + result = TEXT(""); // empty string + return result; + } + + int lastIndex = pos + len - 1; // last char's index (to copy) + if(lastIndex >= (int)_tcslen(CString)) { // off end of string? + lastIndex = (int)_tcslen(CString)-1; + } + + int j,k; + for(j=0,k=pos; k <= lastIndex; j++,k++) { + result.CString[j] = CString[k]; + } + result.CString[j] = '\0'; // properly terminate C-string + return result; +} + +int String::find(const String & str, int startpos) const +{ + int len = str.length(); + int lastIndex = length() - len; + int k; + for (k=startpos; k <= lastIndex; k++) { + if (_tcsncmp(CString + k,str.getPointer(),len) == 0) return k; + } + return -1; +} + + +int String::find(TCHAR ch, int startpos) const +{ + int k; + for(k=startpos; k < (int)_tcslen(CString); k++) { + if (CString[k] == ch) { + return k; + } + } + return -1; +} + +int String::findLast(TCHAR ch, int count) +{ + for (int k=length()-1; k; k--) + { + if (CString[k] == ch) + { + if (count==0) + return k; + count--; + } + } + return -1; +} + +int String::parseIntoWords(String *words, int maxWords) +{ + int numWords=0; + String currentWord; + for (int i=0; i0) + { + words[numWords] = currentWord; + currentWord=TEXT(""); + numWords++; + if (numWords == maxWords) + return numWords; + } + } + else + { + currentWord += c; + } + } + return numWords; +} + +void String::toLower() +{ + for (int i=0; i ( const String & lhs, const String & rhs ) +{ + return rhs < lhs; +} + +bool operator >= ( const String & lhs, const String & rhs ) +{ + return rhs <= lhs; +} +/* +int String::convertToInt() const +{ + return(_ttoi(CString)); +}*/ + + +void String::reverseString() +{ + int n = 0, i = 0; + TCHAR *ny = new TCHAR[length()+1]; + + for (i=length()-1; i >= 0; i--, n++) { + ny[i] = CString[n]; + } + + ny[length()]='\0'; + + _tcscpy(CString, ny); + + delete [] ny; +} + + + + +String String::getPath() +{ + int p=find(String(TEXT("\\")),0); + int lastp=-1; + while (p!=-1) { + lastp=p; + p=find(String(TEXT("\\")),p+1); + } + if (lastp!=-1) { + return subString(0,lastp); + } else { + return String(TEXT("")); + } +} + +String String::getFName() +{ + int p=find(String(TEXT("\\")),0); + int lastp=-1; + while (p!=-1) + { + lastp=p; + p=find(String(TEXT("\\")),p+1); + } + if (lastp!=-1) + { + return subString(lastp+1,100); + } + else + { + return String(TEXT("")); + } +} + + +void String::toUnicode(wchar_t *dest) +{ + for (int i=0; i255?' ':i; + } + }; + + int newLength = wideLength(src); + delete [] CString; + Capacity = newLength + 1; + CString = new TCHAR[Capacity]; + + int i; + for (i=0; i +#include + +#include "base/basictypes.h" + +#ifdef UNICODE +typedef wchar_t TCHAR; +#else +typedef char TCHAR; +#endif + +class String +{ +public: + // constructors/destructor + String(); // construct empty string "" + explicit String(const char * s); // construct from string literal + String(const String & str); // copy constructor + ~String(); // destructor + + + // accessors + + int find(const String & str, int startpos=0) const; // index of first occurrence of str + int find(TCHAR ch, int startpos=0) const; // index of first occurrence of ch + int findLast(TCHAR ch,int count=0); + String subString(int pos, int len) const; // substring of len chars + + + int length() const; // number of chars + + // starting at pos + TCHAR * getPointer( ) const; // explicit conversion to char * + const TCHAR *c_str() const { + return getPointer(); + } + + // assignment + const String & operator = ( const String & str ); // assign str + const String & operator = ( const TCHAR * s ); // assign s + const String & operator = ( TCHAR ch ); // assign ch + + //int operator == (String &other); + //int operator != (String &other) {return !(*this == other);} + // indexing + TCHAR & operator [] ( int k ); // range-checked indexing + + // modifiers + const String & operator += ( const String & str ); // append str + const String & operator += ( const TCHAR * s); // append s + const String & operator += ( TCHAR ch ); // append char + + int parseIntoWords(String *words, int maxWords); + int convertToInt() const; + /* + static String fromInt(int i) { + TCHAR temp[15]; + _itot_s(i,temp,15,10); + return String(temp); + }*/ + void reverseString(); + void toUnicode(wchar_t *dest); + void fromUnicode(wchar_t *src); + String getPath(); + String getFName(); + + void toUpper(); + void toLower(); + +private: + int Capacity; // capacity of string + TCHAR * CString; // storage for characters +}; + +// The following free (non-member) functions operate on strings +// +// I/O functions +/* +ostream & operator << ( ostream & os, const String & str ); +istream & operator >> ( istream & is, String & str ); +istream & getline( istream & is, String & str ); +*/ +// comparison operators: + +bool operator == ( const String & lhs, const String & rhs ); +bool operator != ( const String & lhs, const String & rhs ); +bool operator < ( const String & lhs, const String & rhs ); +bool operator <= ( const String & lhs, const String & rhs ); +bool operator > ( const String & lhs, const String & rhs ); +bool operator >= ( const String & lhs, const String & rhs ); + +// concatenation operator + + +String operator + ( const String & lhs, const String & rhs ); +String operator + ( TCHAR ch, const String & str ); +String operator + ( const String & str, TCHAR ch ); + diff --git a/base/basictypes.h b/base/basictypes.h new file mode 100644 index 0000000000..c6da99928c --- /dev/null +++ b/base/basictypes.h @@ -0,0 +1,92 @@ +#ifndef _BASE_BASICTYPES +#define _BASE_BASICTYPES + +#include +#include // for byte swapping + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4996) +#pragma warning(disable:4305) // truncation from double to float +#endif + +#define DISALLOW_COPY_AND_ASSIGN(t) \ + private: \ + t(const t &other); \ + void operator =(const t &other); + + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; +typedef int8_t sint8; +typedef int16_t sint16; +typedef int32_t sint32; +typedef int64_t sint64; +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; + +#ifdef _WIN32 + +#include + +#define ALIGNED16(x) __declspec(align(16)) x +#define ALIGNED32(x) __declspec(align(32)) x +#define ALIGNED64(x) __declspec(align(64)) x +#define ALIGNED16_DECL(x) __declspec(align(16)) x +#define ALIGNED64_DECL(x) __declspec(align(64)) x + +#else + +#define ALIGNED16(x) __attribute__((aligned(16))) x +#define ALIGNED32(x) __attribute__((aligned(32))) x +#define ALIGNED64(x) __attribute__((aligned(64))) x +#define ALIGNED16_DECL(x) __attribute__((aligned(16))) x +#define ALIGNED64_DECL(x) __attribute__((aligned(64))) x + +#endif // _WIN32 + +#ifndef TEXT +#define TEXT(x) x +#endif + +// Byteswapping + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +inline uint8 swap8(uint8 _data) {return _data;} + +#ifdef _WIN32 +inline uint16 swap16(uint16 _data) {return _byteswap_ushort(_data);} +inline uint32 swap32(uint32 _data) {return _byteswap_ulong (_data);} +inline uint64 swap64(uint64 _data) {return _byteswap_uint64(_data);} +#elif __linux__ +#include +#undef swap16 +#undef swap32 +#undef swap64 +inline uint16 swap16(uint16 _data) {return bswap_16(_data);} +inline uint32 swap32(uint32 _data) {return bswap_32(_data);} +inline uint64 swap64(uint64 _data) {return bswap_64(_data);} +#else +// Slow generic implementation. +inline uint16 swap16(uint16 data) {return (data >> 8) | (data << 8);} +inline uint32 swap32(uint32 data) {return (swap16(data) << 16) | swap16(data >> 16);} +inline uint64 swap64(uint64 data) {return ((uint64)swap32(data) << 32) | swap32(data >> 32);} +#endif + +inline uint16 swap16(const uint8* _pData) {return swap16(*(const uint16*)_pData);} +inline uint32 swap32(const uint8* _pData) {return swap32(*(const uint32*)_pData);} +inline uint64 swap64(const uint8* _pData) {return swap64(*(const uint64*)_pData);} + +// Thread local storage +#ifdef _WIN32 +#define __THREAD __declspec( thread ) +#else +#define __THREAD __thread +#endif + +#endif // _BASE_BASICTYPES diff --git a/base/color.h b/base/color.h new file mode 100644 index 0000000000..5042756936 --- /dev/null +++ b/base/color.h @@ -0,0 +1,43 @@ +#pragma once + +// #define COLOR16 + +#ifdef COLOR16 +typedef unsigned short Color; +#else +typedef unsigned int Color; +#endif + + +//have to use a define to ensure constant folding.. with an inline I don't get that, sucks +#ifdef COLOR16 +#error +#define COLOR(i) (short16)(((i&0xF80000)>>8) | ((i&0xFC00)>>5) | ((i&0xF8)>>3)) +inline Color darkenColor(Color color) { + return (color>>1)&0x7BEF; +} +inline Color whitenColor(Color color) { + return ((color>>1)&0x7BEF)+0x7BEF; +} +//single multiplication 16-bit color alpha blending... pretty cool huh? +inline Color colorInterpol(Color x, Color y, int n) +{ + uint32 c1 = (x|(x<<16))&0x7E0F81F; + uint32 c2 = (y|(y<<16))&0x7E0F81F; + uint32 c = (c1 + ((c2 - c1)*n >> 5)) & 0x7E0F81F; + return c | (c >> 16); +} + +#else +#define COLOR(i) (((i << 16) & 0xFF0000) | (i & 0xFF00) | ((i >> 16) & 0xFF) | 0xFF000000) +inline Color darkenColor(Color color) { + return (color & 0xFF000000) | ((color >> 1)&0x7F7F7F); +} +inline Color whitenColor(Color color) { + return ((color & 0xFF000000) | ((color >> 1)&0x7F7F7F)) + 0x7F7F7F; +} +inline Color colorInterpol(Color x, Color y, int n) { + // TODO + return x; +} +#endif \ No newline at end of file diff --git a/base/colorutil.cpp b/base/colorutil.cpp new file mode 100644 index 0000000000..d17310d33f --- /dev/null +++ b/base/colorutil.cpp @@ -0,0 +1,86 @@ +/* hsv2rgb.c +* Convert Hue Saturation Value to Red Green Blue +* +* P.J. 08-Aug-98 +* +* Reference: +* D. F. Rogers +* Procedural Elements for Computer Graphics +* McGraw Hill 1985 +*/ + +#include "base/colorutil.h" + +uint32_t whiteAlpha(float alpha) { + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + uint32_t color = (int)(alpha*255)<<24; + color |= 0xFFFFFF; + return color; +} + +uint32_t blackAlpha(float alpha) { + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + return (int)(alpha*255)<<24; +} + +uint32_t rgba(float r, float g, float b, float alpha) { + uint32_t color = (int)(alpha*255)<<24; + color |= (int)(b*255)<<16; + color |= (int)(g*255)<<8; + color |= (int)(r*255); + return color; +} + +uint32_t rgba_clamp(float r, float g, float b, float a) { + if (r > 1.0f) r = 1.0f; + if (g > 1.0f) g = 1.0f; + if (b > 1.0f) b = 1.0f; + if (a > 1.0f) a = 1.0f; + + if (r < 0.0f) r = 0.0f; + if (g < 0.0f) g = 0.0f; + if (b < 0.0f) b = 0.0f; + if (a < 0.0f) a = 0.0f; + + return rgba(r,g,b,a); +} + +uint32_t hsva(float H, float S, float V, float alpha) { + /* + * Purpose: + * Convert HSV values to RGB values + * All values are in the range [0.0 .. 1.0] + */ + float F, M, N, K; + int I; + float r, g, b; + if ( S == 0.0 ) { + // Achromatic case, set level of grey + return rgba(V, V, V, alpha); + } else { + /* + * Determine levels of primary colours. + */ + if (H >= 1.0) { + H = 0.0; + } else { + H = H * 6; + } + I = (int) H; /* should be in the range 0..5 */ + F = H - I; /* fractional part */ + + M = V * (1 - S); + N = V * (1 - S * F); + K = V * (1 - S * (1 - F)); + + if (I == 0) { r = V; g = K; b = M; } + if (I == 1) { r = N; g = V; b = M; } + if (I == 2) { r = M; g = V; b = K; } + if (I == 3) { r = M; g = N; b = V; } + if (I == 4) { r = K; g = M; b = V; } + if (I == 5) { r = V; g = M; b = N; } + return rgba(r, g, b, alpha); + } +} diff --git a/base/colorutil.h b/base/colorutil.h new file mode 100644 index 0000000000..005b4190bd --- /dev/null +++ b/base/colorutil.h @@ -0,0 +1,9 @@ +#pragma once + +#include "base/basictypes.h" + +uint32_t whiteAlpha(float alpha); +uint32_t blackAlpha(float alpha); +uint32_t rgba(float r, float g, float b, float alpha); +uint32_t rgba_clamp(float r, float g, float b, float alpha); +uint32_t hsva(float h, float s, float v, float alpha); \ No newline at end of file diff --git a/base/error_context.cpp b/base/error_context.cpp new file mode 100644 index 0000000000..0dfc3e5961 --- /dev/null +++ b/base/error_context.cpp @@ -0,0 +1,39 @@ +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/error_context.h" +#include + +#ifndef _WIN32 +#undef __THREAD +#define __THREAD +#endif + +__THREAD std::vector *_error_context_name; +__THREAD std::vector *_error_context_data; + +_ErrorContext::_ErrorContext(const char *name, const char *data) { + if (!_error_context_name) { + _error_context_name = new std::vector(); + _error_context_data = new std::vector(); + _error_context_name->reserve(16); + _error_context_data->reserve(16); + } + _error_context_name->push_back(name); + _error_context_data->push_back(data); +} + +_ErrorContext::~_ErrorContext() { + _error_context_name->pop_back(); + _error_context_data->pop_back(); +} + +void _ErrorContext::Log(const char *message) { + ILOG("EC: %s", message); + for (size_t i = 0; i < _error_context_name->size(); i++) { + if ((*_error_context_data)[i] != 0) { + ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]); + } else { + ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]); + } + } +} diff --git a/base/error_context.h b/base/error_context.h new file mode 100644 index 0000000000..228c714065 --- /dev/null +++ b/base/error_context.h @@ -0,0 +1,18 @@ +#pragma once + +// do not inherit + +// TODO: Have the crash handler investigate the error context. +// Must only be constructed on the stack - DO NOT put these on the heap. +class _ErrorContext +{ +public: + _ErrorContext(const char *name, const char *data = 0); + ~_ErrorContext(); + + // Logs the current context stack. + static void Log(const char *message); +}; + +#define ErrorContext(...) _ErrorContext __ec(__VA_ARGS__) +#define LogErrorContext(msg) _ErrorContext::Log(msg) \ No newline at end of file diff --git a/base/logging.h b/base/logging.h new file mode 100644 index 0000000000..57924d366b --- /dev/null +++ b/base/logging.h @@ -0,0 +1,59 @@ +#pragma once + +#ifdef _MSC_VER +#pragma warning (disable:4996) //strcpy may be dangerous +#endif + +// Logging +#ifdef _WIN32 + +inline void Crash() { __asm { int 3 }; } + +#else + +#ifdef ANDROID + +inline void Crash() { + char *p = (char *)1337; + *p = 1; +} +#else + +inline void Crash() { + asm("int $0x3"); +} +#endif + +#endif + +#ifdef ANDROID + +#include + +#ifndef APP_NAME +#define APP_NAME "Turboviking" +#endif + +#define ILOG(...) __android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__); +#define WLOG(...) __android_log_print(ANDROID_LOG_WARN, APP_NAME, __VA_ARGS__); +#define ELOG(...) __android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__); +#define FLOG(...) { __android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__); Crash(); } + +#define MessageBox(a, b, c, d) __android_log_print(ANDROID_LOG_INFO, APP_NAME, "%s %s", (b), (c)); + +#else + +#include + +#define ILOG(...) {printf("I: %s:%i: ", __FILE__, __LINE__); printf("I: " __VA_ARGS__); printf("\n");} +#define WLOG(...) {printf("W: %s:%i: ", __FILE__, __LINE__); printf("W: " __VA_ARGS__); printf("\n");} +#define ELOG(...) {printf("E: %s:%i: ", __FILE__, __LINE__); printf("E: " __VA_ARGS__); printf("\n");} +#define FLOG(...) {printf("F: %s:%i: ", __FILE__, __LINE__); printf("F: " __VA_ARGS__); printf("\n"); Crash();} + +#ifndef MessageBox +#define MessageBox(a, b, c, d) printf("MSG: %s %s\n", (b), (c)); +#endif + +#endif + +#define CHECK(a) {if (!(a)) {FLOG("CHECK failed");}} diff --git a/base/scoped_ptr.h b/base/scoped_ptr.h new file mode 100644 index 0000000000..1d04d5e36e --- /dev/null +++ b/base/scoped_ptr.h @@ -0,0 +1,28 @@ +#pragma once + +template +class scoped_ptr { + public: + scoped_ptr() : ptr_(0) {} + scoped_ptr(T *p) : ptr_(p) {} + ~scoped_ptr() { + delete ptr_; + } + void reset(T *p) { + delete ptr_; + ptr_ = p; + } + T *release() { + T *p = ptr_; + ptr_ = 0; + return p; + } + T *operator->() { return ptr_; } + const T *operator->() const { return ptr_; } + + private: + // don't copy that floppy + scoped_ptr(const scoped_ptr &other); + void operator=(const scoped_ptr &other); + T *ptr_; +}; diff --git a/base/stats.h b/base/stats.h new file mode 100644 index 0000000000..5b45e7da2e --- /dev/null +++ b/base/stats.h @@ -0,0 +1,17 @@ +#pragma once + + +#define STATS_ENABLE + +#ifdef STATS_ENABLE + +void IncrementStat(const char *name); + +#define INCSTAT(name) IncrementStat(name); + +#else + +#define INCSTAT(name) + +#endif + diff --git a/base/stringutil.h b/base/stringutil.h new file mode 100644 index 0000000000..e5dfa87923 --- /dev/null +++ b/base/stringutil.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include + +class ITOA { +public: + char buffer[16]; + const char *p(int i) { + sprintf(buffer, "%i", i); + return &buffer[0]; + } +}; + +inline bool endsWith(const std::string &str, const std::string &what) { + return str.substr(str.size() - what.size()) == what; +} \ No newline at end of file diff --git a/base/timeutil.cpp b/base/timeutil.cpp new file mode 100644 index 0000000000..3ab3033547 --- /dev/null +++ b/base/timeutil.cpp @@ -0,0 +1,80 @@ +#include "base/basictypes.h" +#include "base/timeutil.h" + +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#include + +static double curtime = 0; +static float curtime_f = 0; + +#ifdef _WIN32 + +__int64 _frequency = 0; +__int64 _starttime = 0; + +double real_time_now(){ + if (_frequency == 0) { + QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); + QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); + curtime=0; + } + __int64 time; + QueryPerformanceCounter((LARGE_INTEGER*)&time); + return ((double) (time - _starttime) / (double) _frequency); +} + +#else + +double real_time_now() { + static time_t start; + struct timeval tv; + gettimeofday(&tv, NULL); + if (start == 0) { + start = tv.tv_sec; + } + tv.tv_sec -= start; + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; +} + +#endif + +void time_update() { + curtime = real_time_now(); + curtime_f = (float)curtime; + + //printf("curtime: %f %f\n", curtime, curtime_f); + // also smooth time. + //curtime+=float((double) (time-_starttime) / (double) _frequency); + //curtime*=0.5f; + //curtime+=1.0f/60.0f; + //lastTime=curtime; + //curtime_f = (float)curtime; +} + +float time_now() { + return curtime_f; +} + +double time_now_d() { + return curtime; +} + +int time_now_ms() { + return int(curtime*1000.0); +} + +void sleep_ms(int ms) { +#ifdef _WIN32 +#ifndef METRO + Sleep(ms); +#endif +#else + usleep(ms * 1000); +#endif +} + diff --git a/base/timeutil.h b/base/timeutil.h new file mode 100644 index 0000000000..388e9a09dc --- /dev/null +++ b/base/timeutil.h @@ -0,0 +1,19 @@ +#pragma once + +// http://linux.die.net/man/3/clock_gettime + +// This time implementation caches the time for max performance (call time_now() as much as you like). +// You need to call time_update() once per frame (or whenever you need the correct time right now). + +void time_update(); + +// Seconds. +float time_now(); +double time_now_d(); + +// Slower than the above cached time functions +double real_time_now(); + +int time_now_ms(); + +void sleep_ms(int ms); diff --git a/collision/CMakeLists.txt b/collision/CMakeLists.txt new file mode 100644 index 0000000000..00af58df88 --- /dev/null +++ b/collision/CMakeLists.txt @@ -0,0 +1,9 @@ +set(SRCS + collision.cpp + ) + +add_library(collision STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/collision/collision.cpp b/collision/collision.cpp new file mode 100644 index 0000000000..b4993562e9 --- /dev/null +++ b/collision/collision.cpp @@ -0,0 +1,288 @@ +#include "base/logging.h" +#include "math/lin/vec3.h" +#include "math/ray_intersections.h" +#include "collision/collision.h" + +#include + +// #define COLLISION_ENABLE_SCALING + +static std::string V(const Vec3 &v) { + char temp[100]; + sprintf(temp, "(%f %f %f)", v.x, v.y, v.z); + return std::string(temp); +} + +Collidable::Collidable() { +} + +Collidable::~Collidable() { +} + +void Collision::Init(const Vec3 &source, const Vec3 &dest, const Vec3 &size) { + this->size = size; + scale.Set(1.0f / size.x, 1.0f / size.y, 1.0f / size.z); + sourcePoint = source.scaledBy(scale); + + velocity = (dest - source).scaledBy(scale); + velocityLength = velocity.length(); + normalizedVelocity = velocity / velocityLength; + + stuck = false; + foundCollision = false; + nearestDistance = velocityLength; +} + +void Collision::BeginTransform(const Matrix4x4 &inverse, const Matrix4x4 &transform) { + this->transform = &transform; + untransformed_sourcePoint = sourcePoint; + untransformed_velocity = velocity; + + sourcePoint = sourcePoint * inverse; + velocity = velocity.rotatedBy(inverse); + + normalizedVelocity = untransformed_velocity.normalized(); +} + +void Collision::EndTransform() { + sourcePoint = untransformed_sourcePoint; + velocity = untransformed_velocity; + + normalizedVelocity = untransformed_velocity.normalized(); + this->transform = 0; +} + +bool Collision::registerCollision(float t, const Vec3 &polyIPoint) { + // Special handling for multiple contact points + if (t < 0.0f) { + return false; + } + Vec3 ipoint; + if (transform) ipoint = polyIPoint * (*transform); + else ipoint = polyIPoint; + + if (t >= -0.0001 && t <= 0.0001 && num_contact_points < MAX_CONTACT_POINTS) { + for (int i = 0; i < num_contact_points; i++) { + // Check if identical - can happen on dupe edges (which we'll later remove). + // TODO: Let's see if we can get rid of this fuzziness. + if (ipoint.distance2To(contact_points[i]) < 0.00001) + goto skip; + } + contact_points[num_contact_points++] = ipoint; + } +skip: + if ((t >= 0.0) && (t <= velocityLength) && (t <= this->nearestDistance)) { + // If we are hit we have a closest hit so far. We save the information + this->nearestDistance = t; + this->nearestPolygonIntersectionPoint = ipoint; + this->foundCollision = true; + //ILOG("Collision registered, t=%f", t); + return true; + } else { + // Already had a closer collision. + return false; + } +} + +bool Collision::Triangle(Vec3 p1, Vec3 p2, Vec3 p3) { + Vec3 pNormal = (p2 - p1) % (p3 - p1); + pNormal.normalize(); + return Triangle(p1, p2, p3, pNormal); +} + +bool Collision::Triangle(Vec3 p1, Vec3 p2, Vec3 p3, const Vec3 &pNormal) { +#ifdef COLLISION_ENABLE_SCALING + p1.scaleBy(scale); + p2.scaleBy(scale); + p3.scaleBy(scale); +#endif + + // Backface + // Early out optimization, lose a square root + if (dot(velocity, pNormal) >= 0.0f) + return false; + + // ILOG("normal. %s", V(pNormal).c_str()); + // find the plane intersection point + float t; + Vec3 polyIPoint, sIPoint = sourcePoint - pNormal; + if (pointPlaneDistance(sIPoint, p1, pNormal) > 0.0f) { + // Plane is embedded in ellipsoid. + // Find plane intersection point by shooting a ray from the sphere intersection + // point along the plane normal. + t = intersectRayPlanePerp(sIPoint, pNormal, p1); + polyIPoint = sIPoint + pNormal * t; // calculate plane intersection point + } else { + // shoot ray along the velocity vector + t = intersectRayPlane(sIPoint, normalizedVelocity, p1, pNormal); + if (t > velocityLength) { + // Did not hit plane. No point in doing triangle tests. + return false; + } + // calculate plane intersection point + polyIPoint = sIPoint + normalizedVelocity * t; + } + + if (isPointInTriangle(polyIPoint, p1, p2, p3)) { + // ILOG("Hit triangle! %s %s %s %s", V(polyIPoint).c_str(), V(p1).c_str(), V(p2).c_str(), V(p3).c_str()); + float depth2 = (polyIPoint - sourcePoint).length2(); + if (depth2 < 0.9999f) { + // Here we do the error checking to see if we got ourself stuck last frame + ELOG("Stuck in triangle! depth2 = %f", depth2); + // ILOG("%s %s %s", V(p1).c_str(), V(p2).c_str(), V(p3).c_str()); + stuck = true; + } + return registerCollision(t, polyIPoint); + } else { + // ILOG("Missed this triangle - returning"); + return false; + } +} + +bool Collision::EdgeLine(Vec3 p1, Vec3 p2) { + // This ellipsoid scaling stuff will result in the edge not being really cylindric. + // Should work for many purposes though. +#ifdef COLLISION_ENABLE_SCALING + p1.scaleBy(scale); + p2.scaleBy(scale); +#endif + float t = 1000000000.0; + Vec3 polyIPoint; + if (intersectCylinder(sourcePoint, normalizedVelocity, + p1, p2, &t, &polyIPoint)) { + polyIPoint = closestPointOnLine(p1, p2, polyIPoint); + return registerCollision(t, polyIPoint); + } else { + return false; + } +} + +bool Collision::Corner(Vec3 p1) { +#ifdef COLLISION_ENABLE_SCALING + p1.scaleBy(scale); +#endif + float t = intersectRayUnitSphere(sourcePoint, normalizedVelocity, p1); + if (t != -1.0f) { + return registerCollision(t, p1); + } else { + return false; + } +} + +bool Collision::Quad(const Vec3 &o, const Vec3 &dx, const Vec3 &dy) { + bool hit = Triangle(o, o + dx, o + dx + dy); + hit |= Triangle(o + dx + dy, o + dy, o); + return hit; +} + +bool Collide(Collision *collision, Collidable *scene, Vec3 *out) { + bool hit_anything = false; + collision->num_contact_points = 0; + collision->lastSafePosition = collision->sourcePoint; + // Process max 8 slides to have a limit if we get into an impossible situation. + int i = 0; + for (i = 0; i < 4; i++) { + // ILOG("Try %i! %s", i, V(collision->sourcePoint).c_str()); + scene->Collide(collision); + if (!collision->foundCollision) { + // Nothing left to do. + collision->sourcePoint += collision->velocity; + collision->velocity.setZero(); + break; + } + hit_anything = true; + if (collision->nearestDistance < 0.0f) { + ILOG("NegHit! %f %f", collision->velocityLength, collision->nearestDistance); + } else { + // ILOG("Hit! %f %f ", collision->velocityLength, collision->nearestDistance); + } + + Vec3 slidePlaneOrigin; + Vec3 slidePlaneNormal; + Vec3 newSourcePoint = collision->sourcePoint; + + float adjusted_hit_distance = collision->nearestDistance - 0.0001f; + if (adjusted_hit_distance < 0) adjusted_hit_distance = 0; + + // Two cases - one where we have multiple contact points, one where we don't. + if (collision->num_contact_points > 1) { + ILOG("Resolve %i-ary collision, velocityLength = %f", + collision->num_contact_points, collision->velocity.length()); + Vec3 avg_contact(0,0,0); + for (int i = 0; i < collision->num_contact_points; i++) { + ILOG("Contact point %s", V(collision->contact_points[i]).c_str()); + avg_contact += collision->contact_points[i]; + } + avg_contact /= (float)collision->num_contact_points; + + // The average of the contact points should be inside the sphere. + float dist = sqrt(avg_contact.distance2To(collision->sourcePoint)); + if (dist > 1.0) { + ILOG("Bogus contact points, for sure: %s vs %s, dist=%f", V(avg_contact).c_str(), V(collision->sourcePoint).c_str(), dist); + } + + Vec3 avg_contact_dir = avg_contact - collision->sourcePoint; + avg_contact_dir.normalize(); + avg_contact = collision->sourcePoint + avg_contact_dir; + + newSourcePoint += collision->normalizedVelocity * adjusted_hit_distance; + slidePlaneOrigin = avg_contact; + slidePlaneNormal = (newSourcePoint - slidePlaneOrigin).normalized(); + + // Push the ball out a bit along the normal to avoid re-collision. + newSourcePoint += slidePlaneNormal * 0.01f; + //collision->velocity += slidePlaneNormal * 0.01; + + //slidePlaneNormal = avg_contact_dir; + } else { + // LOG(INFO) << "Adjusting newsourcepoint to end of collision"; + newSourcePoint += collision->normalizedVelocity * adjusted_hit_distance; + // LOG(INFO) << "s: " << V(collision->sourcePoint); + // LOG(INFO) << "nsp: " << V(newSourcePoint); + // LOG(INFO) << "ip: " << V(collision->nearestPolygonIntersectionPoint); + + // Now we must calculate the sliding plane + slidePlaneOrigin = collision->nearestPolygonIntersectionPoint; + slidePlaneNormal = (newSourcePoint - slidePlaneOrigin).normalized(); + } + + // We now project the destination point onto the sliding plane + Vec3 destinationPoint = collision->sourcePoint + collision->velocity; + float l = intersectRayPlane(destinationPoint, slidePlaneNormal, + slidePlaneOrigin, -slidePlaneNormal); + + // We can now calculate a new destination point on the sliding plane + Vec3 newDestinationPoint = destinationPoint + slidePlaneNormal * l; + + // now we start over with the new position and velocity + + collision->sourcePoint = newSourcePoint; + // Generate the slide vector, which will become our new velocity vector + Vec3 slide = newDestinationPoint - slidePlaneOrigin; + slide += slidePlaneNormal * 0.0001f; + + // LOG(INFO) << "NDP: " << V(newDestinationPoint); + // ILOG("Slide: %s", V(slide).c_str()); + // Recompute to get ready! + collision->velocity = slide; + collision->velocityLength = collision->velocity.length(); + if (collision->velocityLength <= 0.0002) { + //ILOG("Zero-length velocity vector. Break."); + collision->velocity.setZero(); + break; + } else { + // ILOG("Velocity: %s", V(collision->velocity).c_str()); + } + collision->nearestDistance = collision->velocityLength; + collision->normalizedVelocity = collision->velocity / collision->velocityLength; + } + //ILOG("%i tries", i); + + *out = collision->sourcePoint.scaledBy(collision->size); + if (collision->stuck) { + //ILOG("Stuck - resetting"); + // *out = collision->lastSafePosition.scaledBy(collision->size); + } + return hit_anything; +} + diff --git a/collision/collision.h b/collision/collision.h new file mode 100644 index 0000000000..2ff5ba1d47 --- /dev/null +++ b/collision/collision.h @@ -0,0 +1,89 @@ +// Collision detection engine. You pass in a class representing a scene, +// and out comes a nice FPS-like "sliding physics" response. + +// By hrydgard@gmail.com, + + +#ifndef _COLLISION_H +#define _COLLISION_H + +#include "math/lin/vec3.h" +#include "math/lin/matrix4x4.h" + +class Collision; + +class Collidable { + public: + Collidable(); + virtual ~Collidable(); + // Apply the collision functions to collision as appropriate. + virtual void Collide(Collision *collision) = 0; +}; + +class Collision { + public: + void Init(const Vec3 &source, const Vec3 &dest, const Vec3 &size); + + // Collision functions + // These should be called from Collidable::Collide and nowhere else + // except the unit test. + + // To correctly collide with meshes, just apply these in sequence. You MUST + // collide against all external (convex) edges, otherwise you can get + // quite stuck. There's PLENTY of optimization to do here. + + bool Triangle(Vec3 p1, Vec3 p2, Vec3 p3); + bool Triangle(Vec3 p1, Vec3 p2, Vec3 p3, const Vec3 &normal); + bool EdgeLine(Vec3 p1, Vec3 p2); // Cylinder + bool Quad(const Vec3 &origin, const Vec3 &dX, const Vec3 &dY); + bool UnitCube(const Vec3 &origin); + bool Corner(Vec3 p1); // Sphere + bool Corners(Vec3 *p, int count); + + // There's an opportunity to provide hyper optimized versions of + // Edge for axis aligned edges. The cylinder intersection becomes trivial. + + // These cannot be nested! + void BeginTransform(const Matrix4x4 &inverse, const Matrix4x4 &transform); + void EndTransform(); + + private: + bool registerCollision(float t, const Vec3 &polyIPoint); + + public: + Vec3 sourcePoint; + + float velocityLength; + + Vec3 size; + Vec3 scale; + Vec3 velocity; // data about player movement + Vec3 normalizedVelocity; + + Vec3 lastSafePosition; // for error handling + bool stuck; + // data for collision response + bool foundCollision; + float nearestDistance; // nearest distance to hit + Vec3 nearestPolygonIntersectionPoint; // on polygon + + const Matrix4x4 *transform; + + // Saved state during transformed operation + Vec3 untransformed_sourcePoint; + Vec3 untransformed_velocity; + + enum { + MAX_CONTACT_POINTS = 10 + }; + Vec3 contact_points[MAX_CONTACT_POINTS]; + int num_contact_points; +}; + +// Sliding physics. +bool Collide(Collision *collision, Collidable *scene, Vec3 *out); + +// Bouncy physics +// void CollideBouncy( ... ) + +#endif // _COLLISION_H diff --git a/ext/etcpack/CMakeLists.txt b/ext/etcpack/CMakeLists.txt new file mode 100644 index 0000000000..806f4157b0 --- /dev/null +++ b/ext/etcpack/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.6) + +add_library(etcdec etcdec.cpp) +#if UNIX +add_definitions(-PIC) + +add_library(etcpack etcpack.cpp) + +add_definitions(-g) +add_definitions(-O2) +add_definitions(-Wall) +add_definitions(-DSDL) +add_definitions(-Wno-multichar) +# add_definitions(-fno-strict-aliasing) +add_definitions(-fstrict-aliasing) + +set(LIBS ${LIBS}) + +add_executable(etctool etctool.cpp image.cpp) +target_link_libraries(etctool etcdec etcpack) + +#add_executable(zimtool zimtool.cpp) +#target_link_libraries(zimtool png freetype z image file zip) + +#set(SRCS +# draw2d.cpp +# fbo.cpp +# glsl_program.cpp) +# +#set(SRCS ${SRCS}) + +#add_library(gfx_es2 STATIC ${SRCS}) + +#if(UNIX) +# add_definitions(-fPIC) +#endif(UNIX) diff --git a/ext/etcpack/README b/ext/etcpack/README new file mode 100644 index 0000000000..d3fbabb1eb --- /dev/null +++ b/ext/etcpack/README @@ -0,0 +1,7 @@ +This folder contains code adapted from etcpack by ERICSSON ///. + +The license comments have been left at the top of each file, but some code may have moved around. + +See LICENSE.TXT for details. It says that use of the code is limited to applications using the +code to compress textures for use with a Khronos-derived API. This game engine only supports +OpenGL ES 2.0, which certainly qualifies, so there is no issue there. diff --git a/ext/etcpack/etcdec.cpp b/ext/etcpack/etcdec.cpp new file mode 100644 index 0000000000..e19e48d54b --- /dev/null +++ b/ext/etcpack/etcdec.cpp @@ -0,0 +1,418 @@ +/** + +@~English +@page licensing Licensing + +@section etcdec etcdec.cxx License + +etcdec.cxx is made available under the terms and conditions of the following +License Agreement. + +SOFTWARE LICENSE AGREEMENT + +PLEASE REVIEW THE FOLLOWING TERMS AND CONDITIONS PRIOR TO USING THE +ERICSSON TEXTURE COMPRESSION CODEC SOFTWARE (THE "SOFTWARE"). THE USE +OF THE SOFTWARE IS SUBJECT TO THE TERMS AND CONDITIONS OF THE +FOLLOWING LICENSE AGREEMENT (THE "LICENSE AGREEMENT"). IF YOU DO NOT +ACCEPT SUCH TERMS AND CONDITIONS YOU MAY NOT USE THE SOFTWARE. + +Under the terms and conditions of the License Agreement, Licensee +hereby, receives a non-exclusive, non transferable, limited, free of +charge, perpetual and worldwide license, to copy, use, distribute and +modify the Software, but only for the purpose of developing, +manufacturing, selling, using and distributing products including the +Software, which products are used for (i) compression and/or +decompression to create content creation tools for usage with a +Khronos API, and/or (ii) compression and/or decompression for the +purpose of usage with a middleware API that is built on top of a +Khronos API, such as JCPs based on a Khronos API (in particular +"Mobile 3D Graphics API for J2ME" and its future versions and "Java +Bindings for OpenGL ES" and its future versions), and/or (iii) +compression and/or decompression to implement a Khronos specification. + +If Licensee institutes patent litigation against Ericsson or any +licensee of the Software for using the Software for making, +developing, manufacturing, selling, using and/or distributing products +within the scope of the Khronos framework, Ericsson shall have the +right to terminate this License Agreement with immediate +effect. However, should Licensee institute patent litigation against +any other licensee of the Software based on such licenseeŽs use of any +other software distributed together with the Software then Ericsson +shall have no right to terminate this License Agreement. + +The License Agreement does not transfer to Licensee any ownership to +any Ericsson or third party intellectual property rights. + +THE SOFTWARE IS PROVIDED "AS IS". ERICSSON MAKES NO REPRESENTATIONS OF +ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND, EITHER EXPRESS OR +IMPLIED; INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK +AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH THE +LICENSEE. SHOULD THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE ASSUMES +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON +MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, DISTRIBUTION, LEASE, USE +OR IMPORTATION UNDER THE LICENSE AGREEMENT WILL BE FREE FROM +INFRINGEMENT OF PATENTS, COPYRIGHTS OR OTHER INTELLECTUAL PROPERTY +RIGHTS OF OTHERS, AND THE VALIDITY OF THE LICENSE AND THE LICENSE +AGREEMENT IS SUBJECT TO LICENSEE'S SOLE RESPONSIBILITY TO MAKE SUCH +DETERMINATION AND ACQUIRE SUCH LICENSES AS MAY BE NECESSARY WITH +RESPECT TO PATENTS AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES. + +IN NO EVENT WILL ERICSSON BE LIABLE TO THE LICENSEE FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY THE LICENSEE OR THIRD PARTIES OR A FAILURE OF THE +SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR +OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +Licensee acknowledges that "ERICSSON ///" is the corporate trademark +of Telefonaktiebolaget LM Ericsson and that both "Ericsson" and the +figure "///" are important features of the trade names of +Telefonaktiebolaget LM Ericsson. Nothing contained in these terms and +conditions shall be deemed to grant Licensee any right, title or +interest in the word "Ericsson" or the figure "///". + +The parties agree that this License Agreement based on these terms and +conditions is governed by the laws of Sweden, and in the event of any +dispute as a result of this License Agreement, the parties submit +themselves to the exclusive jurisdiction of the Swedish Courts. +*/ + +#include +#include + +#define CLAMP(ll,x,ul) (((x)<(ll)) ? (ll) : (((x)>(ul)) ? (ul) : (x))) +#define GETBITS(source, size, startpos) (( (source) >> ((startpos)-(size)+1) ) & ((1<<(size)) -1)) +#define GETBITSHIGH(source, size, startpos) (( (source) >> (((startpos)-32)-(size)+1) ) & ((1<<(size)) -1)) +#define RED(img,width,x,y) img[3*(y*width+x)+0] +#define GREEN(img,width,x,y) img[3*(y*width+x)+1] +#define BLUE(img,width,x,y) img[3*(y*width+x)+2] + +typedef unsigned char uint8; + +int unscramble[4] = {2, 3, 1, 0}; + +static const int compressParams[16][4] = {{-8, -2, 2, 8}, {-8, -2, 2, 8}, {-17, -5, 5, 17}, {-17, -5, 5, 17}, {-29, -9, 9, 29}, {-29, -9, 9, 29}, {-42, -13, 13, 42}, {-42, -13, 13, 42}, {-60, -18, 18, 60}, {-60, -18, 18, 60}, {-80, -24, 24, 80}, {-80, -24, 24, 80}, {-106, -33, 33, 106}, {-106, -33, 33, 106}, {-183, -47, 47, 183}, {-183, -47, 47, 183}}; + +void decompressBlockDiffFlip(unsigned int block_part1, unsigned int block_part2, uint8 *img,int width,int height,int startx,int starty) +{ + uint8 avg_color[3], enc_color1[3], enc_color2[3]; + char diff[3]; + int table; + int index,shift; + int r,g,b; + int diffbit; + int flipbit; + unsigned int pixel_indices_MSB, pixel_indices_LSB; + int x,y; + + diffbit = (GETBITSHIGH(block_part1, 1, 33)); + flipbit = (GETBITSHIGH(block_part1, 1, 32)); + + if( !diffbit ) + { + + // We have diffbit = 0. + + // First decode left part of block. + avg_color[0]= GETBITSHIGH(block_part1, 4, 63); + avg_color[1]= GETBITSHIGH(block_part1, 4, 55); + avg_color[2]= GETBITSHIGH(block_part1, 4, 47); + + // Here, we should really multiply by 17 instead of 16. This can + // be done by just copying the four lower bits to the upper ones + // while keeping the lower bits. + avg_color[0] |= (avg_color[0] <<4); + avg_color[1] |= (avg_color[1] <<4); + avg_color[2] |= (avg_color[2] <<4); + + table = GETBITSHIGH(block_part1, 3, 39) << 1; + + + + pixel_indices_MSB = GETBITS(block_part2, 16, 31); + pixel_indices_LSB = GETBITS(block_part2, 16, 15); + + if( (flipbit) == 0 ) + { + // We should not flip + shift = 0; + for(x=startx; x> shift) & 1) << 1; + index |= ((pixel_indices_LSB >> shift) & 1); + shift++; + index=unscramble[index]; + + r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); + g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); + b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); + + + } + } + } + else + { + // We should flip + shift = 0; + for(x=startx; x> shift) & 1) << 1; + index |= ((pixel_indices_LSB >> shift) & 1); + shift++; + index=unscramble[index]; + + r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); + g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); + b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); + } + shift+=2; + } + } + + // Now decode other part of block. + avg_color[0]= GETBITSHIGH(block_part1, 4, 59); + avg_color[1]= GETBITSHIGH(block_part1, 4, 51); + avg_color[2]= GETBITSHIGH(block_part1, 4, 43); + + // Here, we should really multiply by 17 instead of 16. This can + // be done by just copying the four lower bits to the upper ones + // while keeping the lower bits. + avg_color[0] |= (avg_color[0] <<4); + avg_color[1] |= (avg_color[1] <<4); + avg_color[2] |= (avg_color[2] <<4); + + table = GETBITSHIGH(block_part1, 3, 36) << 1; + pixel_indices_MSB = GETBITS(block_part2, 16, 31); + pixel_indices_LSB = GETBITS(block_part2, 16, 15); + + if( (flipbit) == 0 ) + { + // We should not flip + shift=8; + for(x=startx+2; x> shift) & 1) << 1; + index |= ((pixel_indices_LSB >> shift) & 1); + shift++; + index=unscramble[index]; + + r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); + g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); + b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); + + } + } + } + else + { + // We should flip + shift=2; + for(x=startx; x> shift) & 1) << 1; + index |= ((pixel_indices_LSB >> shift) & 1); + shift++; + index=unscramble[index]; + + r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); + g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); + b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); + + } + shift += 2; + } + } + + } + else + { + // We have diffbit = 1. + +// 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 +// --------------------------------------------------------------------------------------------------- +// | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| +// | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | +// --------------------------------------------------------------------------------------------------- +// +// +// c) bit layout in bits 31 through 0 (in both cases) +// +// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +// -------------------------------------------------------------------------------------------------- +// | most significant pixel index bits | least significant pixel index bits | +// | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | +// -------------------------------------------------------------------------------------------------- + + + // First decode left part of block. + enc_color1[0]= GETBITSHIGH(block_part1, 5, 63); + enc_color1[1]= GETBITSHIGH(block_part1, 5, 55); + enc_color1[2]= GETBITSHIGH(block_part1, 5, 47); + + + // Expand from 5 to 8 bits + avg_color[0] = (enc_color1[0] <<3) | (enc_color1[0] >> 2); + avg_color[1] = (enc_color1[1] <<3) | (enc_color1[1] >> 2); + avg_color[2] = (enc_color1[2] <<3) | (enc_color1[2] >> 2); + + + table = GETBITSHIGH(block_part1, 3, 39) << 1; + + pixel_indices_MSB = GETBITS(block_part2, 16, 31); + pixel_indices_LSB = GETBITS(block_part2, 16, 15); + + if( (flipbit) == 0 ) + { + // We should not flip + shift = 0; + for(x=startx; x> shift) & 1) << 1; + index |= ((pixel_indices_LSB >> shift) & 1); + shift++; + index=unscramble[index]; + + r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); + g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); + b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); + + + } + } + } + else + { + // We should flip + shift = 0; + for(x=startx; x> shift) & 1) << 1; + index |= ((pixel_indices_LSB >> shift) & 1); + shift++; + index=unscramble[index]; + + r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); + g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); + b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); + } + shift+=2; + } + } + + + // Now decode right part of block. + + + diff[0]= GETBITSHIGH(block_part1, 3, 58); + diff[1]= GETBITSHIGH(block_part1, 3, 50); + diff[2]= GETBITSHIGH(block_part1, 3, 42); + + enc_color2[0]= enc_color1[0] + diff[0]; + enc_color2[1]= enc_color1[1] + diff[1]; + enc_color2[2]= enc_color1[2] + diff[2]; + + // Extend sign bit to entire byte. + diff[0] = (diff[0] << 5); + diff[1] = (diff[1] << 5); + diff[2] = (diff[2] << 5); + diff[0] = diff[0] >> 5; + diff[1] = diff[1] >> 5; + diff[2] = diff[2] >> 5; + + // Calculale second color + enc_color2[0]= enc_color1[0] + diff[0]; + enc_color2[1]= enc_color1[1] + diff[1]; + enc_color2[2]= enc_color1[2] + diff[2]; + + // Expand from 5 to 8 bits + avg_color[0] = (enc_color2[0] <<3) | (enc_color2[0] >> 2); + avg_color[1] = (enc_color2[1] <<3) | (enc_color2[1] >> 2); + avg_color[2] = (enc_color2[2] <<3) | (enc_color2[2] >> 2); + + + table = GETBITSHIGH(block_part1, 3, 36) << 1; + pixel_indices_MSB = GETBITS(block_part2, 16, 31); + pixel_indices_LSB = GETBITS(block_part2, 16, 15); + + if( (flipbit) == 0 ) + { + // We should not flip + shift=8; + for(x=startx+2; x> shift) & 1) << 1; + index |= ((pixel_indices_LSB >> shift) & 1); + shift++; + index=unscramble[index]; + + r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); + g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); + b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); + + } + } + } + else + { + // We should flip + shift=2; + for(x=startx; x> shift) & 1) << 1; + index |= ((pixel_indices_LSB >> shift) & 1); + shift++; + index=unscramble[index]; + + r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); + g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); + b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); + } + shift += 2; + } + } + } +} + +static int bswap(unsigned int x) { + return ((x & 0xFF000000) >> 24) | + ((x & 0x00FF0000) >> 8) | + ((x & 0x0000FF00) << 8) | + ((x & 0x000000FF) << 24); +} + +void DecompressBlock(const uint8 *compressed, uint8 *out, int out_width, int alpha=255) { + uint8 rgb[4*4*3]; + unsigned int block_part1, block_part2; + memcpy(&block_part1, compressed, 4); + memcpy(&block_part2, compressed + 4, 4); + block_part1 = bswap(block_part1); + block_part2 = bswap(block_part2); + decompressBlockDiffFlip(block_part1, block_part2, rgb, 4, 4, 0, 0); + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + out[(y * out_width + x) * 4 + 0] = rgb[(4 * y + x) * 3 + 0]; + out[(y * out_width + x) * 4 + 1] = rgb[(4 * y + x) * 3 + 1]; + out[(y * out_width + x) * 4 + 2] = rgb[(4 * y + x) * 3 + 2]; + out[(y * out_width + x) * 4 + 3] = alpha; + } + } +} diff --git a/ext/etcpack/etcdec.h b/ext/etcpack/etcdec.h new file mode 100644 index 0000000000..5a0ac6e5bb --- /dev/null +++ b/ext/etcpack/etcdec.h @@ -0,0 +1,9 @@ +#pragma once + +typedef unsigned char uint8; + +/* In etcdec.cxx */ +void decompressBlockDiffFlip(unsigned int block_part1, unsigned int block_part2, uint8 *img,int width,int height,int startx,int starty); + +// Writes RGBA output instead of RGB. +void DecompressBlock(const uint8 *compressed, uint8 *out, int out_width, int alpha=255); diff --git a/ext/etcpack/etcpack.cpp b/ext/etcpack/etcpack.cpp new file mode 100644 index 0000000000..3cf9feb7e0 --- /dev/null +++ b/ext/etcpack/etcpack.cpp @@ -0,0 +1,5730 @@ +// Modified by Henrik RydgÃ¥rd: +// +// * Moved many I/O and similar functions to etctool.cpp, this file +// should only concern itself with compression. +// * got rid of readCompress.. + + + +// etcpack.cxx v1.06 +// +// NO WARRANTY +// +// BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, ERICSSON MAKES NO +// REPRESENTATIONS OF ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND; EITHER +// EXPRESS OR IMPLIED; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +// PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME +// THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON +// MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, LEASE, USE OR +// IMPORTATION WILL BE FREE FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR +// OTHER INTELLECTUAL PROPERTY RIGHTS OF OTHERS, AND IT SHALL BE THE SOLE +// RESPONSIBILITY OF THE LICENSEE TO MAKE SUCH DETERMINATION AS IS +// NECESSARY WITH RESPECT TO THE ACQUISITION OF LICENSES UNDER PATENTS +// AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES; +// +// IN NO EVENT WILL ERICSSON, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +// GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF +// THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO +// LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +// YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY +// OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGES. +// +// (C) Ericsson AB 2005. All Rights Reserved. +// + +#include +#include + +#include "etcpack.h" +#include "etcdec.h" + + + +#define CLAMP(ll,x,ul) (((x)<(ll)) ? (ll) : (((x)>(ul)) ? (ul) : (x))) +#define GETBITS(source, size, startpos) (( (source) >> ((startpos)-(size)+1) ) & ((1<<(size)) -1)) +#define GETBITSHIGH(source, size, startpos) (( (source) >> (((startpos)-32)-(size)+1) ) & ((1<<(size)) -1)) + +#define SQUARE(x) ((x)*(x)) +#define JAS_ROUND(x) (((x) < 0.0 ) ? ((int)((x)-0.5)) : ((int)((x)+0.5))) + +#define RED(img,width,x,y) img[3*(y*width+x)+0] +#define GREEN(img,width,x,y) img[3*(y*width+x)+1] +#define BLUE(img,width,x,y) img[3*(y*width+x)+2] + + +// SLOW SCAN RANGE IS -5 to 5 in all three colors +#define SLOW_SCAN_MIN (-5) +#define SLOW_SCAN_MAX (5) +#define SLOW_SCAN_RANGE ((SLOW_SCAN_MAX-(SLOW_SCAN_MIN)+1)) +#define SLOW_SCAN_OFFSET (-(SLOW_SCAN_MIN)) +// We need this to guarrantee that at least one try is valid +#define SLOW_TRY_MIN (-4 - SLOW_SCAN_MAX) +#define SLOW_TRY_MAX (3 - (SLOW_SCAN_MIN)) + + +// MEDIUM SCAN RANGE IS -3 to 3in all three colors +#define MEDIUM_SCAN_MIN (-3) +#define MEDIUM_SCAN_MAX (3) +#define MEDIUM_SCAN_RANGE ((MEDIUM_SCAN_MAX-(MEDIUM_SCAN_MIN)+1)) +#define MEDIUM_SCAN_OFFSET (-(MEDIUM_SCAN_MIN)) + +// We need this to guarrantee that at least one try is valid +#define MEDIUM_TRY_MIN (-4 - MEDIUM_SCAN_MAX) +#define MEDIUM_TRY_MAX (3 - (MEDIUM_SCAN_MIN)) + + +#define PUTBITS( dest, data, size, startpos) dest |= ( (data) & ((1<<(size))-1) ) << ((startpos)-(size)+1) +#define PUTBITSHIGH( dest, data, size, startpos) dest |= ( (data) & ((1<<(size))-1) ) << (((startpos)-32)-(size)+1) + +int scramble[4] = {3, 2, 0, 1}; + +static const int compressParamsEnc[16][4] = { + { -8, -2, 2, 8 }, + { -8, -2, 2, 8 }, + { -17, -5, 5, 17 }, + { -17, -5, 5, 17 }, + { -29, -9, 9, 29 }, + { -29, -9, 9, 29 }, + { -42, -13, 13, 42 }, + { -42, -13, 13, 42 }, + { -60, -18, 18, 60 }, + { -60, -18, 18, 60 }, + { -80, -24, 24, 80 }, + { -80, -24, 24, 80 }, + {-106, -33, 33,106 }, + {-106, -33, 33,106 }, + {-183, -47, 47,183 }, + {-183, -47, 47,183 }, +}; + +void computeAverageColor2x4noQuantFloat(uint8 *img,int width,int height,int startx,int starty,float *avg_color) { + int r=0,g=0,b=0; + for(int y=starty; y> 1), 1, i); + PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); + + i++; + + // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} + // so that first bit is sign bit and the other bit is size bit (4 or 12). + // This means that we have to scramble the bits before storing them. + + + sum_error+=min_error; + } + + } + + *pixel_indices_MSBp = pixel_indices_MSB; + *pixel_indices_LSBp = pixel_indices_LSB; + + return sum_error; +} + +float compressBlockWithTable2x4percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp) +{ + uint8 orig[3],approx[3]; + unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0; + float sum_error=0; + int q, i; + + double wR2 = PERCEPTUAL_WEIGHT_R_SQUARED; + double wG2 = PERCEPTUAL_WEIGHT_G_SQUARED; + double wB2 = PERCEPTUAL_WEIGHT_B_SQUARED; + + i = 0; + for(int x=startx; x> 1), 1, i); + PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); + + i++; + + // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} + // so that first bit is sign bit and the other bit is size bit (4 or 12). + // This means that we have to scramble the bits before storing them. + + + sum_error+=min_error; + } + + } + + *pixel_indices_MSBp = pixel_indices_MSB; + *pixel_indices_LSBp = pixel_indices_LSB; + + return sum_error; +} +int compressBlockWithTable4x2(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp) +{ + uint8 orig[3],approx[3]; + unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0; + int sum_error=0; + int q; + int i; + + + i = 0; + for(int x=startx; x> 1), 1, i); + PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); + i++; + + // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} + // so that first bit is sign bit and the other bit is size bit (4 or 12). + // This means that we have to scramble the bits before storing them. + + sum_error+=min_error; + } + i+=2; + + } + + *pixel_indices_MSBp = pixel_indices_MSB; + *pixel_indices_LSBp = pixel_indices_LSB; + + + return sum_error; +} + +float compressBlockWithTable4x2percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp) +{ + uint8 orig[3],approx[3]; + unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0; + float sum_error=0; + int q; + int i; + float wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED; + float wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED; + float wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED; + + + i = 0; + for(int x=startx; x> 1), 1, i); + PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); + i++; + + // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} + // so that first bit is sign bit and the other bit is size bit (4 or 12). + // This means that we have to scramble the bits before storing them. + + sum_error+=min_error; + } + i+=2; + + } + + *pixel_indices_MSBp = pixel_indices_MSB; + *pixel_indices_LSBp = pixel_indices_LSB; + + + return sum_error; +} + +int tryalltables_3bittable2x4(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) +{ + int min_error = 3*255*255*16; + int q; + int err; + unsigned int pixel_indices_MSB, pixel_indices_LSB; + + for(q=0;q<16;q+=2) // try all the 8 tables. + { + + err=compressBlockWithTable2x4(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); + + if(err> 1; + + } + } + return min_error; +} + +int tryalltables_3bittable2x4percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) +{ + float min_error = 3*255*255*16; + int q; + float err; + unsigned int pixel_indices_MSB, pixel_indices_LSB; + + for(q=0;q<16;q+=2) // try all the 8 tables. + { + + err=compressBlockWithTable2x4percep(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); + + if(err> 1; + + } + } + return (int) min_error; +} + +int tryalltables_3bittable4x2(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) +{ + int min_error = 3*255*255*16; + int q; + int err; + unsigned int pixel_indices_MSB, pixel_indices_LSB; + + for(q=0;q<16;q+=2) // try all the 8 tables. + { + + err=compressBlockWithTable4x2(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); + + if(err> 1; + } + } + + return min_error; +} +int tryalltables_3bittable4x2percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) +{ + float min_error = 3*255*255*16; + int q; + float err; + unsigned int pixel_indices_MSB, pixel_indices_LSB; + + for(q=0;q<16;q+=2) // try all the 8 tables. + { + + err=compressBlockWithTable4x2percep(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); + + if(err> 1; + } + } + + return (int) min_error; +} + +// The below code quantizes a float RGB value to RGB555. +// + +void quantize444ColorCombined(float *avg_col_in, int *enc_color, uint8 *avg_color) +{ + // Detta ar nummer tva + float dr, dg, db; + float kr, kg, kb; + float wR2, wG2, wB2; + uint8 low_color[3]; + uint8 high_color[3]; + float lowhightable[8]; + int q; + float kval = (float) (255.0/15.0); + + + // These are the values that we want to have: + float red_average, green_average, blue_average; + + int red_4bit_low, green_4bit_low, blue_4bit_low; + int red_4bit_high, green_4bit_high, blue_4bit_high; + + // These are the values that we approximate with: + int red_low, green_low, blue_low; + int red_high, green_high, blue_high; + + red_average = avg_col_in[0]; + green_average = avg_col_in[1]; + blue_average = avg_col_in[2]; + + // Find the 5-bit reconstruction levels red_low, red_high + // so that red_average is in interval [red_low, red_high]. + // (The same with green and blue.) + + red_4bit_low = (int) (red_average/kval); + green_4bit_low = (int) (green_average/kval); + blue_4bit_low = (int) (blue_average/kval); + + red_4bit_high = CLAMP(0, red_4bit_low + 1, 15); + green_4bit_high = CLAMP(0, green_4bit_low + 1, 15); + blue_4bit_high = CLAMP(0, blue_4bit_low + 1, 15); + + red_low = (red_4bit_low << 4) | (red_4bit_low >> 0); + green_low = (green_4bit_low << 4) | (green_4bit_low >> 0); + blue_low = (blue_4bit_low << 4) | (blue_4bit_low >> 0); + + red_high = (red_4bit_high << 4) | (red_4bit_high >> 0); + green_high = (green_4bit_high << 4) | (green_4bit_high >> 0); + blue_high = (blue_4bit_high << 4) | (blue_4bit_high >> 0); + + kr = (float)red_high - (float)red_low; + kg = (float)green_high - (float)green_low; + kb = (float)blue_high - (float)blue_low; + + // Note that dr, dg, and db are all negative. + dr = red_low - red_average; + dg = green_low - green_average; + db = blue_low - blue_average; + + // Use straight (nonperceptive) weights. + wR2 = (float) 1.0; + wG2 = (float) 1.0; + wB2 = (float) 1.0; + + lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); + lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); + lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); + lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); + lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); + lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); + lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); + lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); + + float min_value = lowhightable[0]; + int min_index = 0; + + for(q = 1; q<8; q++) + { + if(lowhightable[q] < min_value) + { + min_value = lowhightable[q]; + min_index = q; + } + } + + low_color[0] = red_4bit_low; + low_color[1] = green_4bit_low; + low_color[2] = blue_4bit_low; + + high_color[0] = red_4bit_high; + high_color[1] = green_4bit_high; + high_color[2] = blue_4bit_high; + + switch(min_index) + { + case 0: + // Since the step size is always 17 in RGB444 format (15*17=255), + // kr = kg = kb = 17, which means that case 0 and case 7 will + // always have equal projected error. Choose the one that is + // closer to the desired color. + if(dr*dr + dg*dg + db*db > 3*8*8) + { + enc_color[0] = high_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = high_color[2]; + } + else + { + enc_color[0] = low_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = low_color[2]; + } + break; + case 1: + enc_color[0] = high_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = low_color[2]; + break; + case 2: + enc_color[0] = low_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = low_color[2]; + break; + case 3: + enc_color[0] = low_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = high_color[2]; + break; + case 4: + enc_color[0] = high_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = low_color[2]; + break; + case 5: + enc_color[0] = high_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = high_color[2]; + break; + case 6: + enc_color[0] = low_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = high_color[2]; + break; + case 7: + if(dr*dr + dg*dg + db*db > 3*8*8) + { + enc_color[0] = high_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = high_color[2]; + } + else + { + enc_color[0] = low_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = low_color[2]; + } + break; + } + + // Expand 5-bit encoded color to 8-bit color + avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2); + avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2); + avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2); +} + + +// The below code quantizes a float RGB value to RGB555. +// +void quantize555ColorCombined(float *avg_col_in, int *enc_color, uint8 *avg_color) +{ + float dr, dg, db; + float kr, kg, kb; + float wR2, wG2, wB2; + uint8 low_color[3]; + uint8 high_color[3]; + float lowhightable[8]; + int q; + float kval = (float) (255.0/31.0); + + + // These are the values that we want to have: + float red_average, green_average, blue_average; + + int red_5bit_low, green_5bit_low, blue_5bit_low; + int red_5bit_high, green_5bit_high, blue_5bit_high; + + // These are the values that we approximate with: + int red_low, green_low, blue_low; + int red_high, green_high, blue_high; + + red_average = avg_col_in[0]; + green_average = avg_col_in[1]; + blue_average = avg_col_in[2]; + + // Find the 5-bit reconstruction levels red_low, red_high + // so that red_average is in interval [red_low, red_high]. + // (The same with green and blue.) + + red_5bit_low = (int) (red_average/kval); + green_5bit_low = (int) (green_average/kval); + blue_5bit_low = (int) (blue_average/kval); + + red_5bit_high = CLAMP(0, red_5bit_low + 1, 31); + green_5bit_high = CLAMP(0, green_5bit_low + 1, 31); + blue_5bit_high = CLAMP(0, blue_5bit_low + 1, 31); + + red_low = (red_5bit_low << 3) | (red_5bit_low >> 2); + green_low = (green_5bit_low << 3) | (green_5bit_low >> 2); + blue_low = (blue_5bit_low << 3) | (blue_5bit_low >> 2); + + red_high = (red_5bit_high << 3) | (red_5bit_high >> 2); + green_high = (green_5bit_high << 3) | (green_5bit_high >> 2); + blue_high = (blue_5bit_high << 3) | (blue_5bit_high >> 2); + + kr = (float)red_high - (float)red_low; + kg = (float)green_high - (float)green_low; + kb = (float)blue_high - (float)blue_low; + + // Note that dr, dg, and db are all negative. + + dr = red_low - red_average; + dg = green_low - green_average; + db = blue_low - blue_average; + + // Use straight (nonperceptive) weights. + wR2 = (float) 1.0; + wG2 = (float) 1.0; + wB2 = (float) 1.0; + + lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); + lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); + lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); + lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); + lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); + lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); + lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); + lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); + + + float min_value = lowhightable[0]; + int min_index = 0; + + for(q = 1; q<8; q++) + { + if(lowhightable[q] < min_value) + { + min_value = lowhightable[q]; + min_index = q; + } + } + + low_color[0] = red_5bit_low; + low_color[1] = green_5bit_low; + low_color[2] = blue_5bit_low; + + high_color[0] = red_5bit_high; + high_color[1] = green_5bit_high; + high_color[2] = blue_5bit_high; + + switch(min_index) + { + case 0: + enc_color[0] = low_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = low_color[2]; + break; + case 1: + enc_color[0] = high_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = low_color[2]; + break; + case 2: + enc_color[0] = low_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = low_color[2]; + break; + case 3: + enc_color[0] = low_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = high_color[2]; + break; + case 4: + enc_color[0] = high_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = low_color[2]; + break; + case 5: + enc_color[0] = high_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = high_color[2]; + break; + case 6: + enc_color[0] = low_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = high_color[2]; + break; + case 7: + enc_color[0] = high_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = high_color[2]; + break; + } + + // Expand 5-bit encoded color to 8-bit color + avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2); + avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2); + avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2); + +} + + +// The below code quantizes a float RGB value to RGB444. +// It is thus the same as the above function quantize444ColorCombined(), but it uses a +// weighted error metric instead. +// +void quantize444ColorCombinedPerceptual(float *avg_col_in, int *enc_color, uint8 *avg_color) +{ + float dr, dg, db; + float kr, kg, kb; + float wR2, wG2, wB2; + uint8 low_color[3]; + uint8 high_color[3]; + float lowhightable[8]; + int q; + float kval = (float) (255.0/15.0); + + + // These are the values that we want to have: + float red_average, green_average, blue_average; + + int red_4bit_low, green_4bit_low, blue_4bit_low; + int red_4bit_high, green_4bit_high, blue_4bit_high; + + // These are the values that we approximate with: + int red_low, green_low, blue_low; + int red_high, green_high, blue_high; + + red_average = avg_col_in[0]; + green_average = avg_col_in[1]; + blue_average = avg_col_in[2]; + + // Find the 5-bit reconstruction levels red_low, red_high + // so that red_average is in interval [red_low, red_high]. + // (The same with green and blue.) + + red_4bit_low = (int) (red_average/kval); + green_4bit_low = (int) (green_average/kval); + blue_4bit_low = (int) (blue_average/kval); + + red_4bit_high = CLAMP(0, red_4bit_low + 1, 15); + green_4bit_high = CLAMP(0, green_4bit_low + 1, 15); + blue_4bit_high = CLAMP(0, blue_4bit_low + 1, 15); + + red_low = (red_4bit_low << 4) | (red_4bit_low >> 0); + green_low = (green_4bit_low << 4) | (green_4bit_low >> 0); + blue_low = (blue_4bit_low << 4) | (blue_4bit_low >> 0); + + red_high = (red_4bit_high << 4) | (red_4bit_high >> 0); + green_high = (green_4bit_high << 4) | (green_4bit_high >> 0); + blue_high = (blue_4bit_high << 4) | (blue_4bit_high >> 0); + + low_color[0] = red_4bit_low; + low_color[1] = green_4bit_low; + low_color[2] = blue_4bit_low; + + high_color[0] = red_4bit_high; + high_color[1] = green_4bit_high; + high_color[2] = blue_4bit_high; + + kr = (float)red_high - (float)red_low; + kg = (float)green_high - (float)green_low; + kb = (float)blue_high- (float)blue_low; + + // Note that dr, dg, and db are all negative. + + dr = red_low - red_average; + dg = green_low - green_average; + db = blue_low - blue_average; + + // Perceptual weights to use + wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED; + wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED; + wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED; + + lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); + lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); + lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); + lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); + lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); + lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); + lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); + lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); + + + float min_value = lowhightable[0]; + int min_index = 0; + + for(q = 1; q<8; q++) + { + if(lowhightable[q] < min_value) + { + min_value = lowhightable[q]; + min_index = q; + } + } + + switch(min_index) + { + case 0: + enc_color[0] = low_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = low_color[2]; + break; + case 1: + enc_color[0] = high_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = low_color[2]; + break; + case 2: + enc_color[0] = low_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = low_color[2]; + break; + case 3: + enc_color[0] = low_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = high_color[2]; + break; + case 4: + enc_color[0] = high_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = low_color[2]; + break; + case 5: + enc_color[0] = high_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = high_color[2]; + break; + case 6: + enc_color[0] = low_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = high_color[2]; + break; + case 7: + enc_color[0] = high_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = high_color[2]; + break; + } + + // Expand encoded color to eight bits + avg_color[0] = (enc_color[0] << 4) | enc_color[0]; + avg_color[1] = (enc_color[1] << 4) | enc_color[1]; + avg_color[2] = (enc_color[2] << 4) | enc_color[2]; +} + + +// The below code quantizes a float RGB value to RGB555. +// It is thus the same as the above function quantize555ColorCombined(), but it uses a +// weighted error metric instead. +// +void quantize555ColorCombinedPerceptual(float *avg_col_in, int *enc_color, uint8 *avg_color) +{ + float dr, dg, db; + float kr, kg, kb; + float wR2, wG2, wB2; + uint8 low_color[3]; + uint8 high_color[3]; + float lowhightable[8]; + int q; + float kval = (float) (255.0/31.0); + + + // These are the values that we want to have: + float red_average, green_average, blue_average; + + int red_5bit_low, green_5bit_low, blue_5bit_low; + int red_5bit_high, green_5bit_high, blue_5bit_high; + + // These are the values that we approximate with: + int red_low, green_low, blue_low; + int red_high, green_high, blue_high; + + red_average = avg_col_in[0]; + green_average = avg_col_in[1]; + blue_average = avg_col_in[2]; + + // Find the 5-bit reconstruction levels red_low, red_high + // so that red_average is in interval [red_low, red_high]. + // (The same with green and blue.) + + red_5bit_low = (int) (red_average/kval); + green_5bit_low = (int) (green_average/kval); + blue_5bit_low = (int) (blue_average/kval); + + red_5bit_high = CLAMP(0, red_5bit_low + 1, 31); + green_5bit_high = CLAMP(0, green_5bit_low + 1, 31); + blue_5bit_high = CLAMP(0, blue_5bit_low + 1, 31); + + red_low = (red_5bit_low << 3) | (red_5bit_low >> 2); + green_low = (green_5bit_low << 3) | (green_5bit_low >> 2); + blue_low = (blue_5bit_low << 3) | (blue_5bit_low >> 2); + + red_high = (red_5bit_high << 3) | (red_5bit_high >> 2); + green_high = (green_5bit_high << 3) | (green_5bit_high >> 2); + blue_high = (blue_5bit_high << 3) | (blue_5bit_high >> 2); + + low_color[0] = red_5bit_low; + low_color[1] = green_5bit_low; + low_color[2] = blue_5bit_low; + + high_color[0] = red_5bit_high; + high_color[1] = green_5bit_high; + high_color[2] = blue_5bit_high; + + kr = (float)red_high - (float)red_low; + kg = (float)green_high - (float)green_low; + kb = (float)blue_high - (float)blue_low; + + // Note that dr, dg, and db are all negative. + + dr = red_low - red_average; + dg = green_low - green_average; + db = blue_low - blue_average; + + // Perceptual weights to use + wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED; + wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED; + wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED; + + lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); + lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); + lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); + lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); + lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); + lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); + lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); + lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); + + + float min_value = lowhightable[0]; + int min_index = 0; + + for(q = 1; q<8; q++) + { + if(lowhightable[q] < min_value) + { + min_value = lowhightable[q]; + min_index = q; + } + } + + switch(min_index) + { + case 0: + enc_color[0] = low_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = low_color[2]; + break; + case 1: + enc_color[0] = high_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = low_color[2]; + break; + case 2: + enc_color[0] = low_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = low_color[2]; + break; + case 3: + enc_color[0] = low_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = high_color[2]; + break; + case 4: + enc_color[0] = high_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = low_color[2]; + break; + case 5: + enc_color[0] = high_color[0]; + enc_color[1] = low_color[1]; + enc_color[2] = high_color[2]; + break; + case 6: + enc_color[0] = low_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = high_color[2]; + break; + case 7: + enc_color[0] = high_color[0]; + enc_color[1] = high_color[1]; + enc_color[2] = high_color[2]; + break; + } + + // Expand 5-bit encoded color to 8-bit color + avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2); + avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2); + avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2); + +} + + +void compressBlockDiffFlipSlow(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) +{ + + + unsigned int compressed1_norm_diff, compressed2_norm_diff; + unsigned int compressed1_norm_444, compressed2_norm_444; + unsigned int compressed1_flip_diff, compressed2_flip_diff; + unsigned int compressed1_flip_444, compressed2_flip_444; + unsigned int best_err_norm_diff = 255*255*8*3; + unsigned int best_err_norm_444 = 255*255*8*3; + unsigned int best_err_flip_diff = 255*255*8*3; + unsigned int best_err_flip_444 = 255*255*8*3; + uint8 avg_color_quant1[3], avg_color_quant2[3]; + + float avg_color_float1[3],avg_color_float2[3]; + int enc_color1[3], enc_color2[3], diff[3]; + int enc_base1[3], enc_base2[3]; + int enc_try1[3], enc_try2[3]; + int err; + unsigned int best_pixel_indices1_MSB=0; + unsigned int best_pixel_indices1_LSB=0; + unsigned int best_pixel_indices2_MSB=0; + unsigned int best_pixel_indices2_LSB=0; + + unsigned int best_table1=0, best_table2=0; + int diffbit; + + int norm_err=0; + int flip_err=0; + int minerr; + int dr1, dg1, db1, dr2, dg2, db2; + + // First try normal blocks 2x4: + + computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); + computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); + + // First test if avg_color1 is similar enough to avg_color2 so that + // we can use differential coding of colors. + + enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); + enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); + enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); + enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); + enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); + enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + if( (diff[0] >= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) + { + diffbit = 1; + + enc_base1[0] = enc_color1[0]; + enc_base1[1] = enc_color1[1]; + enc_base1[2] = enc_color1[2]; + enc_base2[0] = enc_color2[0]; + enc_base2[1] = enc_color2[1]; + enc_base2[2] = enc_color2[2]; + + int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; + int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; + + // left part of block + for(dr1 = SLOW_SCAN_MIN; dr1> 2); + avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); + avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); + + // left part of block + err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + } + } + } + + // right part of block + for(dr2 = SLOW_SCAN_MIN; dr2> 2); + avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); + avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); + + // left part of block + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + } + } + } + + // Now see what combinations are both low in error and possible to + // encode differentially. + + minerr = 255*255*3*8*2; + + for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + // The diff is OK, calculate total error: + + err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; + + if(err < minerr) + { + minerr = err; + + enc_color1[0] = enc_try1[0]; + enc_color1[1] = enc_try1[1]; + enc_color1[2] = enc_try1[2]; + enc_color2[0] = enc_try2[0]; + enc_color2[1] = enc_try2[1]; + enc_color2[2] = enc_try2[2]; + } + } + } + } + } + } + } + } + + best_err_norm_diff = minerr; + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + + // Pack bits into the first word. + + + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + compressed1_norm_diff = 0; + PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); + PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); + PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); + + + // left part of block + tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); + + compressed2_norm_diff = 0; + PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); + + } + // We should do this in any case... + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + + // Color for left block + + int besterr = 255*255*3*8; + int bestri = 0, bestgi = 0, bestbi = 0; + int ri, gi, bi; + + for(ri = 0; ri<15; ri++) + { + for(gi = 0; gi<15; gi++) + { + for(bi = 0; bi<15; bi++) + { + enc_color1[0] = ri; + enc_color1[1] = gi; + enc_color1[2] = bi; + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + + // left part of block + err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); + + if(err= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) + { + diffbit = 1; + + enc_base1[0] = enc_color1[0]; + enc_base1[1] = enc_color1[1]; + enc_base1[2] = enc_color1[2]; + enc_base2[0] = enc_color2[0]; + enc_base2[1] = enc_color2[1]; + enc_base2[2] = enc_color2[2]; + + int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; + int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; + + // upper part of block + for(dr1 = SLOW_SCAN_MIN; dr1> 2); + avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); + avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); + + // upper part of block + err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + } + } + } + + // lower part of block + for(dr2 = SLOW_SCAN_MIN; dr2> 2); + avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); + avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); + + // lower part of block + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + } + } + } + + // Now see what combinations are both low in error and possible to + // encode differentially. + + minerr = 255*255*3*8*2; + + for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + // The diff is OK, calculate total error: + + err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; + + if(err < minerr) + { + minerr = err; + + enc_color1[0] = enc_try1[0]; + enc_color1[1] = enc_try1[1]; + enc_color1[2] = enc_try1[2]; + enc_color2[0] = enc_try2[0]; + enc_color2[1] = enc_try2[1]; + enc_color2[2] = enc_try2[2]; + } + } + } + } + } + } + } + } + + + flip_err = minerr; + + best_err_flip_diff = flip_err; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + // Pack bits into the first word. + + compressed1_flip_diff = 0; + PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); + PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); + PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); + + + + + // upper part of block + tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + + PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); + + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + } + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + + // Color for upper block + + int besterr = 255*255*3*8; + int bestri = 0, bestgi = 0, bestbi = 0; + int ri, gi, bi; + + for(ri = 0; ri<15; ri++) + { + for(gi = 0; gi<15; gi++) + { + for(bi = 0; bi<15; bi++) + { + enc_color1[0] = ri; + enc_color1[1] = gi; + enc_color1[2] = bi; + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + + // upper part of block + err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) + { + diffbit = 1; + + enc_base1[0] = enc_color1[0]; + enc_base1[1] = enc_color1[1]; + enc_base1[2] = enc_color1[2]; + enc_base2[0] = enc_color2[0]; + enc_base2[1] = enc_color2[1]; + enc_base2[2] = enc_color2[2]; + + int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; + int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; + + // left part of block + for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); + avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); + avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); + + // left part of block + err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + } + } + } + + // right part of block + for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); + avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); + avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); + + // left part of block + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + } + } + } + + // Now see what combinations are both low in error and possible to + // encode differentially. + + minerr = 255*255*3*8*2; + + for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + // The diff is OK, calculate total error: + + err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; + + if(err < minerr) + { + minerr = err; + + enc_color1[0] = enc_try1[0]; + enc_color1[1] = enc_try1[1]; + enc_color1[2] = enc_try1[2]; + enc_color2[0] = enc_try2[0]; + enc_color2[1] = enc_try2[1]; + enc_color2[2] = enc_try2[2]; + } + } + } + } + } + } + } + } + + best_err_norm_diff = minerr; + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + + // Pack bits into the first word. + + + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + compressed1_norm_diff = 0; + PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); + PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); + PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); + + + // left part of block + tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); + + compressed2_norm_diff = 0; + PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); + + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + + // Color for left block + + int besterr = 255*255*3*8; + int bestri = 0, bestgi = 0, bestbi = 0; + int ri, gi, bi; + + for(ri = 0; ri<15; ri++) + { + for(gi = 0; gi<15; gi++) + { + for(bi = 0; bi<15; bi++) + { + enc_color1[0] = ri; + enc_color1[1] = gi; + enc_color1[2] = bi; + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + + // left part of block + err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); + + if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) + { + diffbit = 1; + + enc_base1[0] = enc_color1[0]; + enc_base1[1] = enc_color1[1]; + enc_base1[2] = enc_color1[2]; + enc_base2[0] = enc_color2[0]; + enc_base2[1] = enc_color2[1]; + enc_base2[2] = enc_color2[2]; + + int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; + int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; + + // upper part of block + for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); + avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); + avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); + + // upper part of block + err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + } + } + } + + // lower part of block + for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); + avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); + avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); + + // lower part of block + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + } + } + } + + // Now see what combinations are both low in error and possible to + // encode differentially. + + minerr = 255*255*3*8*2; + + for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + // The diff is OK, calculate total error: + + err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; + + if(err < minerr) + { + minerr = err; + + enc_color1[0] = enc_try1[0]; + enc_color1[1] = enc_try1[1]; + enc_color1[2] = enc_try1[2]; + enc_color2[0] = enc_try2[0]; + enc_color2[1] = enc_try2[1]; + enc_color2[2] = enc_try2[2]; + } + } + } + } + } + } + } + } + + + flip_err = minerr; + + best_err_flip_diff = flip_err; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + // Pack bits into the first word. + + compressed1_flip_diff = 0; + PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); + PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); + PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); + + + + + // upper part of block + tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + + PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); + + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + + // Color for upper block + + int besterr = 255*255*3*8; + int bestri = 0, bestgi = 0, bestbi = 0; + int ri, gi, bi; + + for(ri = 0; ri<15; ri++) + { + for(gi = 0; gi<15; gi++) + { + for(bi = 0; bi<15; bi++) + { + enc_color1[0] = ri; + enc_color1[1] = gi; + enc_color1[2] = bi; + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + + // upper part of block + err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + if(err= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) + { + diffbit = 1; + + enc_base1[0] = enc_color1[0]; + enc_base1[1] = enc_color1[1]; + enc_base1[2] = enc_color1[2]; + enc_base2[0] = enc_color2[0]; + enc_base2[1] = enc_color2[1]; + enc_base2[2] = enc_color2[2]; + + int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; + int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; + + // left part of block + for(dr1 = SLOW_SCAN_MIN; dr1> 2); + avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); + avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); + + // left part of block + err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + } + } + } + + // right part of block + for(dr2 = SLOW_SCAN_MIN; dr2> 2); + avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); + avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); + + // left part of block + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + } + } + } + + // Now see what combinations are both low in error and possible to + // encode differentially. + + minerr = 255*255*3*8*2; + + for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + // The diff is OK, calculate total error: + + err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; + + if(err < minerr) + { + minerr = err; + + enc_color1[0] = enc_try1[0]; + enc_color1[1] = enc_try1[1]; + enc_color1[2] = enc_try1[2]; + enc_color2[0] = enc_try2[0]; + enc_color2[1] = enc_try2[1]; + enc_color2[2] = enc_try2[2]; + } + } + } + } + } + } + } + } + + best_err_norm_diff = minerr; + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + + // Pack bits into the first word. + + + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + compressed1_norm_diff = 0; + PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); + PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); + PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); + + + // left part of block + tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); + + compressed2_norm_diff = 0; + PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); + + + } + // We should do this in any case... + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + + // Color for left block + + int besterr = 255*255*3*8; + int bestri = 0, bestgi = 0, bestbi = 0; + int ri, gi, bi; + + for(ri = 0; ri<15; ri++) + { + for(gi = 0; gi<15; gi++) + { + for(bi = 0; bi<15; bi++) + { + enc_color1[0] = ri; + enc_color1[1] = gi; + enc_color1[2] = bi; + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + + // left part of block + err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); + + if(err= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) + { + diffbit = 1; + + enc_base1[0] = enc_color1[0]; + enc_base1[1] = enc_color1[1]; + enc_base1[2] = enc_color1[2]; + enc_base2[0] = enc_color2[0]; + enc_base2[1] = enc_color2[1]; + enc_base2[2] = enc_color2[2]; + + int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; + int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; + + // upper part of block + for(dr1 = SLOW_SCAN_MIN; dr1> 2); + avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); + avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); + + // upper part of block + err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + } + } + } + + // lower part of block + for(dr2 = SLOW_SCAN_MIN; dr2> 2); + avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); + avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); + + // lower part of block + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + } + } + } + + // Now see what combinations are both low in error and possible to + // encode differentially. + + minerr = 255*255*3*8*2; + + for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + // The diff is OK, calculate total error: + + err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; + + if(err < minerr) + { + minerr = err; + + enc_color1[0] = enc_try1[0]; + enc_color1[1] = enc_try1[1]; + enc_color1[2] = enc_try1[2]; + enc_color2[0] = enc_try2[0]; + enc_color2[1] = enc_try2[1]; + enc_color2[2] = enc_try2[2]; + } + } + } + } + } + } + } + } + + + flip_err = minerr; + + best_err_flip_diff = flip_err; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + // Pack bits into the first word. + + compressed1_flip_diff = 0; + PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); + PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); + PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); + + + + + // upper part of block + tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + + PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); + + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + } + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + + // Color for upper block + + int besterr = 255*255*3*8; + int bestri = 0, bestgi = 0, bestbi = 0; + int ri, gi, bi; + + for(ri = 0; ri<15; ri++) + { + for(gi = 0; gi<15; gi++) + { + for(bi = 0; bi<15; bi++) + { + enc_color1[0] = ri; + enc_color1[1] = gi; + enc_color1[2] = bi; + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + + // upper part of block + err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) + { + diffbit = 1; + + enc_base1[0] = enc_color1[0]; + enc_base1[1] = enc_color1[1]; + enc_base1[2] = enc_color1[2]; + enc_base2[0] = enc_color2[0]; + enc_base2[1] = enc_color2[1]; + enc_base2[2] = enc_color2[2]; + + int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; + int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; + + // left part of block + for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); + avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); + avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); + + // left part of block + err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + } + } + } + + // right part of block + for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); + avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); + avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); + + // left part of block + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + } + } + } + + // Now see what combinations are both low in error and possible to + // encode differentially. + + minerr = 255*255*3*8*2; + + for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + // The diff is OK, calculate total error: + + err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; + + if(err < minerr) + { + minerr = err; + + enc_color1[0] = enc_try1[0]; + enc_color1[1] = enc_try1[1]; + enc_color1[2] = enc_try1[2]; + enc_color2[0] = enc_try2[0]; + enc_color2[1] = enc_try2[1]; + enc_color2[2] = enc_try2[2]; + } + } + } + } + } + } + } + } + + best_err_norm_diff = minerr; + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + + // Pack bits into the first word. + + + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + compressed1_norm_diff = 0; + PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); + PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); + PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); + + + // left part of block + tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); + + compressed2_norm_diff = 0; + PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); + + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + + // Color for left block + + int besterr = 255*255*3*8; + int bestri = 0, bestgi = 0, bestbi = 0; + int ri, gi, bi; + + for(ri = 0; ri<15; ri++) + { + for(gi = 0; gi<15; gi++) + { + for(bi = 0; bi<15; bi++) + { + enc_color1[0] = ri; + enc_color1[1] = gi; + enc_color1[2] = bi; + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + + // left part of block + err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); + + if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) + { + diffbit = 1; + + enc_base1[0] = enc_color1[0]; + enc_base1[1] = enc_color1[1]; + enc_base1[2] = enc_color1[2]; + enc_base2[0] = enc_color2[0]; + enc_base2[1] = enc_color2[1]; + enc_base2[2] = enc_color2[2]; + + int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; + int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; + + // upper part of block + for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); + avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); + avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); + + // upper part of block + err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + } + } + } + + // lower part of block + for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); + avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); + avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); + + // lower part of block + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + } + } + } + + // Now see what combinations are both low in error and possible to + // encode differentially. + + minerr = 255*255*3*8*2; + + for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + // The diff is OK, calculate total error: + + err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; + + if(err < minerr) + { + minerr = err; + + enc_color1[0] = enc_try1[0]; + enc_color1[1] = enc_try1[1]; + enc_color1[2] = enc_try1[2]; + enc_color2[0] = enc_try2[0]; + enc_color2[1] = enc_try2[1]; + enc_color2[2] = enc_try2[2]; + } + } + } + } + } + } + } + } + + + flip_err = minerr; + + best_err_flip_diff = flip_err; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + // Pack bits into the first word. + + compressed1_flip_diff = 0; + PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); + PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); + PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); + + + + + // upper part of block + tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + + PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); + + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + + // Color for upper block + + int besterr = 255*255*3*8; + int bestri = 0, bestgi = 0, bestbi = 0; + int ri, gi, bi; + + for(ri = 0; ri<15; ri++) + { + for(gi = 0; gi<15; gi++) + { + for(bi = 0; bi<15; bi++) + { + enc_color1[0] = ri; + enc_color1[1] = gi; + enc_color1[2] = bi; + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + + // upper part of block + err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + if(err= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + diffbit = 1; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + // Pack bits into the first word. + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + compressed1_norm = 0; + PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); + PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); + PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + norm_err = 0; + + // left part of block + norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm, 0, 1, 32); + + compressed2_norm = 0; + PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + eps = (float) 0.0001; + + enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); + enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); + enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); + enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); + enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); + enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; + avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; + avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; + + + // Pack bits into the first word. + + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + + compressed1_norm = 0; + PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); + PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); + PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); + PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); + PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); + PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + + // left part of block + norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm, 0, 1, 32); + + compressed2_norm = 0; + PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); + + + } + + // Now try flipped blocks 4x2: + + computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); + computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); + + // First test if avg_color1 is similar enough to avg_color2 so that + // we can use differential coding of colors. + + enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); + enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); + enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); + enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); + enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); + enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + diffbit = 1; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + // Pack bits into the first word. + + compressed1_flip = 0; + PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); + PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); + PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); + + + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + // upper part of block + flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip, 1, 1, 32); + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + eps = (float) 0.0001; + + enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); + enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); + enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); + enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); + enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); + enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; + avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; + avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; + + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + + + // Pack bits into the first word. + + compressed1_flip = 0; + PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); + PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); + PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); + PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); + PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); + PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + // upper part of block + flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip, 1, 1, 32); + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + + } + + // Now lets see which is the best table to use. Only 8 tables are possible. + + if(norm_err <= flip_err) + { + + compressed1 = compressed1_norm | 0; + compressed2 = compressed2_norm; + + } + else + { + + compressed1 = compressed1_flip | 1; + compressed2 = compressed2_flip; + } +} + +void compressBlockDiffFlipCombined(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) +{ + unsigned int compressed1_norm, compressed2_norm; + unsigned int compressed1_flip, compressed2_flip; + uint8 avg_color_quant1[3], avg_color_quant2[3]; + + float avg_color_float1[3],avg_color_float2[3]; + int enc_color1[3], enc_color2[3], diff[3]; + unsigned int best_table1=0, best_table2=0; + int diffbit; + + int norm_err=0; + int flip_err=0; + + // First try normal blocks 2x4: + + computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); + computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); + + // First test if avg_color1 is similar enough to avg_color2 so that + // we can use differential coding of colors. + + float eps; + + uint8 dummy[3]; + + quantize555ColorCombined(avg_color_float1, enc_color1, dummy); + quantize555ColorCombined(avg_color_float2, enc_color2, dummy); + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + diffbit = 1; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + // Pack bits into the first word. + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + compressed1_norm = 0; + PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); + PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); + PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + norm_err = 0; + + // left part of block + norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm, 0, 1, 32); + + compressed2_norm = 0; + PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + eps = (float) 0.0001; + + uint8 dummy[3]; + quantize444ColorCombined(avg_color_float1, enc_color1, dummy); + quantize444ColorCombined(avg_color_float2, enc_color2, dummy); + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; + avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; + avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; + + + // Pack bits into the first word. + + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + + compressed1_norm = 0; + PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); + PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); + PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); + PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); + PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); + PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + + // left part of block + norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm, 0, 1, 32); + + compressed2_norm = 0; + PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); + + + } + + // Now try flipped blocks 4x2: + + computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); + computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); + + // First test if avg_color1 is similar enough to avg_color2 so that + // we can use differential coding of colors. + + quantize555ColorCombined(avg_color_float1, enc_color1, dummy); + quantize555ColorCombined(avg_color_float2, enc_color2, dummy); + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + diffbit = 1; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + // Pack bits into the first word. + + compressed1_flip = 0; + PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); + PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); + PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); + + + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + // upper part of block + flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip, 1, 1, 32); + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + eps = (float) 0.0001; + + uint8 dummy[3]; + quantize444ColorCombined(avg_color_float1, enc_color1, dummy); + quantize444ColorCombined(avg_color_float2, enc_color2, dummy); + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; + avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; + avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; + + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + + + // Pack bits into the first word. + + compressed1_flip = 0; + PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); + PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); + PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); + PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); + PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); + PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + // upper part of block + flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip, 1, 1, 32); + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + + } + + // Now lets see which is the best table to use. Only 8 tables are possible. + + if(norm_err <= flip_err) + { + + compressed1 = compressed1_norm | 0; + compressed2 = compressed2_norm; + + } + else + { + + compressed1 = compressed1_flip | 1; + compressed2 = compressed2_flip; + } +} + +void compressBlockDiffFlipAveragePerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) +{ + + unsigned int compressed1_norm, compressed2_norm; + unsigned int compressed1_flip, compressed2_flip; + uint8 avg_color_quant1[3], avg_color_quant2[3]; + + float avg_color_float1[3],avg_color_float2[3]; + int enc_color1[3], enc_color2[3], diff[3]; + unsigned int best_table1=0, best_table2=0; + int diffbit; + + int norm_err=0; + int flip_err=0; + + // First try normal blocks 2x4: + + computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); + computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); + + // First test if avg_color1 is similar enough to avg_color2 so that + // we can use differential coding of colors. + + + float eps; + + enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); + enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); + enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); + enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); + enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); + enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + diffbit = 1; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + // Pack bits into the first word. + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + compressed1_norm = 0; + PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); + PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); + PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + norm_err = 0; + + // left part of block + norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm, 0, 1, 32); + + compressed2_norm = 0; + PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + eps = (float) 0.0001; + + enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); + enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); + enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); + enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); + enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); + enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; + avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; + avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; + + + // Pack bits into the first word. + + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + + compressed1_norm = 0; + PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); + PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); + PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); + PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); + PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); + PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + + // left part of block + norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm, 0, 1, 32); + + compressed2_norm = 0; + PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); + + + } + + // Now try flipped blocks 4x2: + + computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); + computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); + + // First test if avg_color1 is similar enough to avg_color2 so that + // we can use differential coding of colors. + + enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); + enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); + enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); + enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); + enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); + enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + diffbit = 1; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + // Pack bits into the first word. + + compressed1_flip = 0; + PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); + PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); + PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); + + + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + // upper part of block + flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip, 1, 1, 32); + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + eps = (float) 0.0001; + + enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); + enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); + enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); + enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); + enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); + enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; + avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; + avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; + + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + + + // Pack bits into the first word. + + compressed1_flip = 0; + PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); + PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); + PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); + PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); + PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); + PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + // upper part of block + flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip, 1, 1, 32); + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + + } + + // Now lets see which is the best table to use. Only 8 tables are possible. + + if(norm_err <= flip_err) + { + + compressed1 = compressed1_norm | 0; + compressed2 = compressed2_norm; + + } + else + { + + compressed1 = compressed1_flip | 1; + compressed2 = compressed2_flip; + } +} + +void compressBlockDiffFlipCombinedPerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) +{ + + unsigned int compressed1_norm, compressed2_norm; + unsigned int compressed1_flip, compressed2_flip; + uint8 avg_color_quant1[3], avg_color_quant2[3]; + + float avg_color_float1[3],avg_color_float2[3]; + int enc_color1[3], enc_color2[3], diff[3]; + unsigned int best_table1=0, best_table2=0; + int diffbit; + + int norm_err=0; + int flip_err=0; + + // First try normal blocks 2x4: + + computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); + computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); + + // First test if avg_color1 is similar enough to avg_color2 so that + // we can use differential coding of colors. + + + float eps; + + uint8 dummy[3]; + + quantize555ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); + quantize555ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + diffbit = 1; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + // Pack bits into the first word. + + // ETC1_RGB8_OES: + // + // a) bit layout in bits 63 through 32 if diffbit = 0 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // b) bit layout in bits 63 through 32 if diffbit = 1 + // + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| + // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + // + // c) bit layout in bits 31 through 0 (in both cases) + // + // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + // -------------------------------------------------------------------------------------------------- + // | most significant pixel index bits | least significant pixel index bits | + // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | + // -------------------------------------------------------------------------------------------------- + + + compressed1_norm = 0; + PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); + PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); + PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + norm_err = 0; + + // left part of block + norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm, 0, 1, 32); + + compressed2_norm = 0; + PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + + eps = (float) 0.0001; + + quantize444ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); + quantize444ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; + avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; + avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; + + + // Pack bits into the first word. + + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + + compressed1_norm = 0; + PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); + PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); + PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); + PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); + PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); + PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); + PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + + // left part of block + norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + + // right part of block + norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); + PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); + PUTBITSHIGH( compressed1_norm, 0, 1, 32); + + compressed2_norm = 0; + PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); + PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); + PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); + PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); + + + } + + // Now try flipped blocks 4x2: + + computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); + computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); + + // First test if avg_color1 is similar enough to avg_color2 so that + // we can use differential coding of colors. + + + quantize555ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); + quantize555ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) + { + diffbit = 1; + + // The difference to be coded: + + diff[0] = enc_color2[0]-enc_color1[0]; + diff[1] = enc_color2[1]-enc_color1[1]; + diff[2] = enc_color2[2]-enc_color1[2]; + + avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); + avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); + avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); + avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); + avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); + avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); + + // Pack bits into the first word. + + compressed1_flip = 0; + PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); + PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); + PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); + PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); + PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); + PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); + + + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + // upper part of block + flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip, 1, 1, 32); + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + + } + else + { + diffbit = 0; + // The difference is bigger than what fits in 555 plus delta-333, so we will have + // to deal with 444 444. + eps = (float) 0.0001; + + quantize444ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); + quantize444ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); + + avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; + avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; + avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; + avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; + avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; + avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; + + // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 + // --------------------------------------------------------------------------------------------------- + // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| + // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | + // --------------------------------------------------------------------------------------------------- + + + // Pack bits into the first word. + + compressed1_flip = 0; + PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); + PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); + PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); + PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); + PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); + PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); + PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); + + unsigned int best_pixel_indices1_MSB; + unsigned int best_pixel_indices1_LSB; + unsigned int best_pixel_indices2_MSB; + unsigned int best_pixel_indices2_LSB; + + // upper part of block + flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); + // lower part of block + flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); + + PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); + PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); + PUTBITSHIGH( compressed1_flip, 1, 1, 32); + + best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); + best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); + + compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); + + + } + + // Now lets see which is the best table to use. Only 8 tables are possible. + + if(norm_err <= flip_err) + { + + compressed1 = compressed1_norm | 0; + compressed2 = compressed2_norm; + + } + else + { + + compressed1 = compressed1_flip | 1; + compressed2 = compressed2_flip; + } +} + +double calcBlockErrorRGB(uint8 *img, uint8 *imgdec, int width, int height, int startx, int starty) +{ + int xx,yy; + double err; + + err = 0; + + for(xx = startx; xx< startx+4; xx++) + { + for(yy = starty; yy> 24) | + ((x & 0x00FF0000) >> 8) | + ((x & 0x0000FF00) << 8) | + ((x & 0x000000FF) << 24); +} + +void CompressBlock(const uint8 *in, int in_width, uint8 *output, int quality) { + uint8 rgb[4 * 4 * 3]; + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + rgb[(y * 4 + x) * 3 + 0] = in[(y * in_width + x) * 4 + 0]; + rgb[(y * 4 + x) * 3 + 1] = in[(y * in_width + x) * 4 + 1]; + rgb[(y * 4 + x) * 3 + 2] = in[(y * in_width + x) * 4 + 2]; + } + } + + uint8 imgdec[4 * 4 * 3]={0}; // temporary storage used by some of the functions. + unsigned int compressed1 = 0, compressed2 = 0; + switch (quality) { + case 0: + compressBlockDiffFlipFast(rgb, imgdec, 4, 4, 0, 0, compressed1, compressed2); + break; + case 1: + compressBlockDiffFlipFastPerceptual(rgb, imgdec, 4, 4, 0, 0, compressed1, compressed2); + break; + case 2: + compressBlockDiffFlipMedium(rgb, 4, 4, 0, 0, compressed1, compressed2); + break; + case 3: + compressBlockDiffFlipMediumPerceptual(rgb, 4, 4, 0, 0, compressed1, compressed2); + break; + case 4: + compressBlockDiffFlipSlow(rgb, 4, 4, 0, 0, compressed1, compressed2); + break; + case 5: + compressBlockDiffFlipSlowPerceptual(rgb, 4, 4, 0, 0, compressed1, compressed2); + break; + default: + fprintf(stderr, "ETC1: Compression level %i not defined", quality); + return; + } + compressed1 = bswap(compressed1); + compressed2 = bswap(compressed2); + memcpy(output, &compressed1, 4); + memcpy(output + 4, &compressed2, 4); + memset(rgb, 0, 4 * 4 * 3); +} diff --git a/ext/etcpack/etcpack.h b/ext/etcpack/etcpack.h new file mode 100644 index 0000000000..f8332ad17e --- /dev/null +++ b/ext/etcpack/etcpack.h @@ -0,0 +1,26 @@ +#pragma once + +#define PERCEPTUAL_WEIGHT_R_SQUARED 0.299 +#define PERCEPTUAL_WEIGHT_G_SQUARED 0.587 +#define PERCEPTUAL_WEIGHT_B_SQUARED 0.114 + +typedef unsigned char uint8; + +// These functions take RGB888. +void compressBlockDiffFlipSlow(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); + +void compressBlockDiffFlipMedium(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); + +void compressBlockDiffFlipFast(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); + +void compressBlockDiffFlipSlowPerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); + +void compressBlockDiffFlipMediumPerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); + +void compressBlockDiffFlipFastPerceptual(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); + + +// This one takes RGBA8888 and converts to RGB first. +// Writes 64 bits of compressed data to output[0..7]. +// Quality is 0 to 5. The odd numbers use perceptual metrics. +void CompressBlock(const uint8 *in, int in_width, uint8 *output, int quality); diff --git a/ext/etcpack/etctool.cpp b/ext/etcpack/etctool.cpp new file mode 100644 index 0000000000..6e7692826c --- /dev/null +++ b/ext/etcpack/etctool.cpp @@ -0,0 +1,1612 @@ +// Contains a lot of code from etcpack.cpp. +// Extracted by Henrik RydgÃ¥rd. + + +#include +#include +#include +#include + +#include "etcpack.h" +#include "etcdec.h" +#include "image.h" + +enum{FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0, FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T1}; + +int orientation; + +int ktx_mode; + +typedef struct KTX_header_t +{ + uint8 identifier[12]; + unsigned int endianness; + unsigned int glType; + unsigned int glTypeSize; + unsigned int glFormat; + unsigned int glInternalFormat; + unsigned int glBaseInternalFormat; + unsigned int pixelWidth; + unsigned int pixelHeight; + unsigned int pixelDepth; + unsigned int numberOfArrayElements; + unsigned int numberOfFaces; + unsigned int numberOfMipmapLevels; + unsigned int bytesOfKeyValueData; +} +KTX_header; +#define KTX_IDENTIFIER_REF { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A } + +#define KTX_ENDIAN_REF (0x04030201) +#define KTX_ENDIAN_REF_REV (0x01020304) + +int ktx_identifier[] = KTX_IDENTIFIER_REF; + + +enum {GL_R=0x1903,GL_RG=0x8227,GL_RGB=0x1907,GL_RGBA=0x1908}; +enum {GL_ETC1_RGB8_OES=0x8d64}; + +#define ETC1_RGB_NO_MIPMAPS 0 +#define ETC1_RGBA_NO_MIPMAPS 1 +#define ETC1_RGB_MIPMAPS 2 +#define ETC1_RGBA_MIPMAPS 3 + +// The error metric Wr Wg Wb should be definied so that Wr^2 + Wg^2 + Wb^2 = 1. +// Hence it is easier to first define the squared values and derive the weights +// as their square-roots. + + +// Alternative weights +//#define PERCEPTUAL_WEIGHT_R_SQUARED 0.3086 +//#define PERCEPTUAL_WEIGHT_G_SQUARED 0.6094 +//#define PERCEPTUAL_WEIGHT_B_SQUARED 0.082 + +#define PERCEPTUAL_WEIGHT_R (sqrt(PERCEPTUAL_WEIGHT_R_SQUARED)) +#define PERCEPTUAL_WEIGHT_G (sqrt(PERCEPTUAL_WEIGHT_G_SQUARED)) +#define PERCEPTUAL_WEIGHT_B (sqrt(PERCEPTUAL_WEIGHT_B_SQUARED)) + + +double wR = PERCEPTUAL_WEIGHT_R; +double wG = PERCEPTUAL_WEIGHT_G; +double wB = PERCEPTUAL_WEIGHT_B; + +double wR2 = PERCEPTUAL_WEIGHT_R_SQUARED; +double wG2 = PERCEPTUAL_WEIGHT_G_SQUARED; +double wB2 = PERCEPTUAL_WEIGHT_B_SQUARED; + +void read_big_endian_2byte_word(unsigned short *blockadr, FILE *f) +{ + uint8 bytes[2]; + unsigned short block; + + fread(&bytes[0], 1, 1, f); + fread(&bytes[1], 1, 1, f); + + block = 0; + + block |= bytes[0]; + block = block << 8; + block |= bytes[1]; + + blockadr[0] = block; +} + +void read_big_endian_4byte_word(unsigned int *blockadr, FILE *f) +{ + uint8 bytes[4]; + unsigned int block; + + fread(&bytes[0], 1, 1, f); + fread(&bytes[1], 1, 1, f); + fread(&bytes[2], 1, 1, f); + fread(&bytes[3], 1, 1, f); + + block = 0; + + block |= bytes[0]; + block = block << 8; + block |= bytes[1]; + block = block << 8; + block |= bytes[2]; + block = block << 8; + block |= bytes[3]; + + blockadr[0] = block; +} + + + +bool fileExist(const char *filename) +{ + FILE *f=NULL; + if((f=fopen(filename,"rb"))!=NULL) + { + fclose(f); + return true; + } + return false; +} + +bool expandToWidthDivByFour(uint8 *&img, int width, int height, int &expandedwidth, int &expandedheight) +{ + int wdiv4; + int xx, yy; + uint8 *newimg; + + wdiv4 = width /4; + if( !(wdiv4 *4 == width) ) + { + expandedwidth = (wdiv4 + 1)*4; + expandedheight = height; + newimg=(uint8*)malloc(3*expandedwidth*expandedheight); + if(!newimg) + { + printf("Could not allocate memory to expand width\n"); + return false; + } + + // First copy image + for(yy = 0; yy> 8) & 0xff; + bytes[1] = (block >> 0) & 0xff; + + fwrite(&bytes[0],1,1,f); + fwrite(&bytes[1],1,1,f); +} + +void write_big_endian_4byte_word(unsigned int *blockadr, FILE *f) +{ + uint8 bytes[4]; + unsigned int block; + + block = blockadr[0]; + + bytes[0] = (block >> 24) & 0xff; + bytes[1] = (block >> 16) & 0xff; + bytes[2] = (block >> 8) & 0xff; + bytes[3] = (block >> 0) & 0xff; + + fwrite(&bytes[0],1,1,f); + fwrite(&bytes[1],1,1,f); + fwrite(&bytes[2],1,1,f); + fwrite(&bytes[3],1,1,f); +} + + +int find_pos_of_extension(const char *src) +{ + int q=strlen(src); + while(q>=0) // find file name extension + { + if(src[q]=='.') break; + q--; + } + if(q<0) + return -1; + else + return q; +} + +bool readSrcFile(const char *filename,uint8 *&img,int &width,int &height, int &expandedwidth, int &expandedheight) +{ + int w1,h1; + int wdiv4, hdiv4; + char str[255]; + + + // Delete temp file if it exists. + if(fileExist("tmp.ppm")) + { + sprintf(str, "del tmp.ppm\n"); + system(str); + } + + + int q = find_pos_of_extension(filename); + if(!strcmp(&filename[q],".ppm")) + { + // Already a .ppm file. Just copy. + sprintf(str,"copy %s tmp.ppm \n", filename); + printf("Copying source file %s to tmp.ppm\n", filename); + } + else + { + // Converting from other format to .ppm + // + // Use your favorite command line image converter program, + // for instance Image Magick. Just make sure the syntax can + // be written as below: + // + // C:\imconv source.jpg dest.ppm + // + sprintf(str,"imconv %s tmp.ppm\n", filename); + printf("Converting source file from %s to .ppm\n", filename); + } + // Execute system call + system(str); + + bool FLIP; + if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0) + FLIP = false; + else if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T1) + FLIP = true; + else + { + printf("orientation error\n"); + exit(1); + } + + if(fReadPPM("tmp.ppm",w1,h1,img,FLIP)) + { + width=w1; + height=h1; + system("del tmp.ppm"); + + // Width must be divisible by 2 and height must be + // divisible by 4. Otherwise, we will not compress + // the image. + + wdiv4 = width / 4; + hdiv4 = height / 4; + + expandedwidth = width; + expandedheight = height; + + if( !(wdiv4 * 4 == width) ) + { + printf(" Width = %d is not divisible by four... ", width); + printf(" expanding image in x-dir... "); + if(expandToWidthDivByFour(img, width, height, expandedwidth, expandedheight)) + { + printf("OK.\n"); + } + else + { + printf("\n Error: could not expand image\n"); + return false; + } + } + if( !(hdiv4 * 4 == height)) + { + printf(" Height = %d is not divisible by four... ", height); + printf(" expanding image in y-dir..."); + if(expandToHeightDivByFour(img, expandedwidth, height, expandedwidth, expandedheight)) + { + printf("OK.\n"); + } + else + { + printf("\n Error: could not expand image\n"); + return false; + } + } + if(!(expandedwidth == width && expandedheight == height)) + printf("Active pixels: %dx%d. Expanded image: %dx%d\n",width,height,expandedwidth,expandedheight); + return true; + } + return false; + +} +bool readSrcFileNoExpand(const char *filename,uint8 *&img,int &width,int &height) +{ + int w1,h1; + char str[255]; + + + // Delete temp file if it exists. + if(fileExist("tmp.ppm")) + { + sprintf(str, "del tmp.ppm\n"); + system(str); + } + + + int q = find_pos_of_extension(filename); + if(!strcmp(&filename[q],".ppm")) + { + // Already a .ppm file. Just copy. + sprintf(str,"copy %s tmp.ppm \n", filename); + printf("Copying source file %s to tmp.ppm\n", filename); + } + else + { + // Converting from other format to .ppm + // + // Use your favorite command line image converter program, + // for instance Image Magick. Just make sure the syntax can + // be written as below: + // + // C:\imconv source.jpg dest.ppm + // + sprintf(str,"imconv %s tmp.ppm\n", filename); + printf("Converting source file from %s to .ppm\n", filename); + } + // Execute system call + system(str); + + // The current function is only used when comparing two ppm files --- we don't need to flip them. Hence reverse_y is false + if(fReadPPM("tmp.ppm",w1,h1,img,false)) + { + width=w1; + height=h1; + system("del tmp.ppm"); + + return true; + } + return false; + +} + + +void compressImageFile(uint8 *img,int width,int height,char *dstfile, int expandedwidth, int expandedheight, int action) +{ + FILE *f; + int x,y,w,h; + unsigned int block1, block2; + unsigned short wi, hi; + unsigned char magic[4]; + unsigned char version[2]; + unsigned short texture_type; + uint8 *imgdec; + + imgdec = (unsigned char*) malloc(expandedwidth*expandedheight*3); + if(!imgdec) + { + printf("Could not allocate decompression buffer --- exiting\n"); + exit(1); + } + + magic[0] = 'P'; magic[1] = 'K'; magic[2] = 'M'; magic[3] = ' '; + version[0] = '1'; version[1] = '0'; + texture_type = ETC1_RGB_NO_MIPMAPS; + + if((f=fopen(dstfile,"wb"))) + { + w=expandedwidth/4; w*=4; + h=expandedheight/4; h*=4; + wi = w; + hi = h; + + if(ktx_mode) + { + printf("Outputting to .kxt file...\n"); + //.ktx file: KTX header followed by compressed binary data. + KTX_header header; + //identifier + for(int i=0; i<12; i++) + { + header.identifier[i]=ktx_identifier[i]; + } + //endianess int.. if this comes out reversed, all of the other ints will too. + header.endianness=KTX_ENDIAN_REF; + + //these values are always 0/1 for compressed textures. + header.glType=0; + header.glTypeSize=1; + header.glFormat=0; + + header.pixelWidth=width; + header.pixelHeight=height; + header.pixelDepth=0; + + //we only support single non-mipmapped non-cubemap textures.. + header.numberOfArrayElements=0; + header.numberOfFaces=1; + header.numberOfMipmapLevels=1; + + //and no metadata.. + header.bytesOfKeyValueData=0; + + int halfbytes=1; + //header.glInternalFormat=? + //header.glBaseInternalFormat=? + if(texture_type==ETC1_RGB_NO_MIPMAPS) + { + header.glBaseInternalFormat=GL_RGB; + header.glInternalFormat=GL_ETC1_RGB8_OES; + } + else + { + printf("internal error: bad format!\n"); + exit(1); + } + //write header + fwrite(&header,sizeof(KTX_header),1,f); + + //write size of compressed data.. which depend on the expanded size.. + unsigned int imagesize=(w*h*halfbytes)/2; + fwrite(&imagesize,sizeof(int),1,f); + } + else + { + printf("outputting to .pkm file...\n"); + // Write magic number + fwrite(&magic[0], sizeof(unsigned char), 1, f); + fwrite(&magic[1], sizeof(unsigned char), 1, f); + fwrite(&magic[2], sizeof(unsigned char), 1, f); + fwrite(&magic[3], sizeof(unsigned char), 1, f); + + // Write version + fwrite(&version[0], sizeof(unsigned char), 1, f); + fwrite(&version[1], sizeof(unsigned char), 1, f); + + // Write texture type + write_big_endian_2byte_word(&texture_type, f); + + // Write binary header: the width and height as unsigned 16-bit words + write_big_endian_2byte_word(&wi, f); + write_big_endian_2byte_word(&hi, f); + + // Also write the active pixels. For instance, if we want to compress + // a 128 x 129 image, we have to extend it to 128 x 132 pixels. + // Then the wi and hi written above will be 128 and 132, but the + // additional information that we write below will be 128 and 129, + // to indicate that it is only the top 129 lines of data in the + // decompressed image that will be valid data, and the rest will + // be just garbage. + + unsigned short activew, activeh; + activew = width; + activeh = height; + + write_big_endian_2byte_word(&activew, f); + write_big_endian_2byte_word(&activeh, f); + } + + int totblocks = expandedheight/4 * expandedwidth/4; + int countblocks = 0; + + /// xxx + for(y=0;y.\n",dstfile); + } +} + +double calculatePSNR(uint8 *lossyimg, uint8 *origimg, int width, int height) +{ + // calculate Mean Square Error (MSE) + + int x,y; + double MSE; + double PSNR; + double err; + MSE = 0; + + // Note: This calculation of PSNR uses the formula + // + // PSNR = 10 * log_10 ( 255^2 / MSE ) + // + // where the MSE is calculated as + // + // 1/(N*M) * sum ( 1/3 * ((R' - R)^2 + (G' - G)^2 + (B' - B)^2) ) + // + // The reason for having the 1/3 factor is the following: + // Presume we have a grayscale image, that is acutally just the red component + // of a color image.. The squared error is then (R' - R)^2. + // Assume that we have a certain signal to noise ratio, say 30 dB. If we add + // another two components (say green and blue) with the same signal to noise + // ratio, we want the total signal to noise ratio be the same. For the + // squared error to remain constant we must divide by three after adding + // together the squared errors of the components. + + for(y=0;y.\n",srcfile); + return -1; + } +} + +void compressFile(char *srcfile,char *dstfile, int action) +{ + uint8 *srcimg; + int width,height; + int extendedwidth, extendedheight; + double PSNR; + + printf("\n"); + switch(action) + { + case 0: + printf("Using FAST compression mode and NONPERCEPTUAL error metric\n"); + break; + case 1: + printf("Using MEDIUM-speed compression mode and NONPERCEPTUAL error metric\n"); + break; + case 2: + printf("Using SLOW compression mode and NONPERCEPTUAL error metric\n"); + break; + case 3: + printf("Using FAST compression mode and PERCEPTUAL error metric\n"); + break; + case 4: + printf("Using MEDIUM-speed compression mode and PERCEPTUAL error metric\n"); + break; + case 5: + printf("Using SLOW compression mode and PERCEPTUAL error metric\n"); + break; + } + printf("Using the orientation that maps the first pixel in .ppm file to "); + if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0) + printf("s=0, t=0.\n"); + else if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T1) + printf("s=0, t=1.\n"); + + if(readSrcFile(srcfile,srcimg,width,height,extendedwidth, extendedheight)) + { + printf("Compressing...\n"); + compressImageFile(srcimg,width,height,dstfile,extendedwidth, extendedheight, action); + PSNR = calculatePSNRfile(dstfile, srcimg); + free(srcimg); + printf("PSNR = %f\n",PSNR); + } +} + +double calculatePSNRTwoFiles(char *srcfile1,char *srcfile2) +{ + uint8 *srcimg1; + uint8 *srcimg2; + int width1, height1; + int width2, height2; + double PSNR = 0.0f; + double perceptually_weighted_PSNR; + + if(readSrcFileNoExpand(srcfile1,srcimg1,width1,height1)) + { + if(readSrcFileNoExpand(srcfile2,srcimg2,width2,height2)) + { + if((width1 == width2) && (height1 == height2)) + { + PSNR = calculatePSNR(srcimg1, srcimg2, width1, height1); + printf("PSNR = %f\n",PSNR); + perceptually_weighted_PSNR = calculatePerceptuallyWeightedPSNR(srcimg1, srcimg2, width1, height1); + printf("perceptually weighted PSNR = (%f)\n",perceptually_weighted_PSNR); + + } + else + { + printf("\n Width and height do no not match for image: width, height = (%d, %d) and (%d, %d)\n",width1,height1, width2, height2); + } + } + else + { + printf("Couldn't open file %s.\n",srcfile2); + } + } + else + { + printf("Couldn't open file %s.\n",srcfile1); + } + + return PSNR; +} + + +void uncompressFile(char *srcfile,char *dstfile) +{ + FILE *f; + int width,height; + unsigned int block_part1, block_part2; + uint8 *img, *newimg; + char str[300]; + unsigned short w, h; + int xx, yy; + unsigned char magic[4]; + unsigned char version[2]; + unsigned short texture_type; + int active_width; + int active_height; + int format; + + + + if(f=fopen(srcfile,"rb")) + { + if(ktx_mode) + { + //read ktx header.. + KTX_header header; + fread(&header,sizeof(KTX_header),1,f); + //read size parameter, which we don't actually need.. + unsigned int bitsize; + fread(&bitsize,sizeof(unsigned int),1,f); + + active_width = header.pixelWidth; + active_height = header.pixelHeight; + w = ((active_width+3)/4)*4; + h = ((active_height+3)/4)*4; + width=w; + height=h; + + if(header.glInternalFormat==GL_ETC1_RGB8_OES) + { + format=ETC1_RGB_NO_MIPMAPS; + } + else { + printf("ktx file has unknown glInternalFormat (not etc compressed)!\n"); + exit(1); + } + } + else + { + // Read magic nunmber + fread(&magic[0], sizeof(unsigned char), 1, f); + fread(&magic[1], sizeof(unsigned char), 1, f); + fread(&magic[2], sizeof(unsigned char), 1, f); + fread(&magic[3], sizeof(unsigned char), 1, f); + if(!(magic[0] == 'P' && magic[1] == 'K' && magic[2] == 'M' && magic[3] == ' ')) + { + printf("\n\n The file %s is not a .pkm file.\n",srcfile); + exit(1); + } + + // Read version + fread(&version[0], sizeof(unsigned char), 1, f); + fread(&version[1], sizeof(unsigned char), 1, f); + if(!(version[0] == '1' && version[1] == '0')) + { + printf("\n\n The file %s is not of version 1.0 but of version %c.%c.\n",srcfile, version[0], version[1]); + exit(1); + } + + // Read texture type + read_big_endian_2byte_word(&texture_type, f); + if(!(texture_type == ETC1_RGB_NO_MIPMAPS)) + { + printf("\n\n The file %s does not contain a ETC1_RGB_NO_MIPMAPS texture.\n", srcfile); + exit(1); + } + + // Read how many pixels the blocks make up + + read_big_endian_2byte_word(&w, f); + read_big_endian_2byte_word(&h, f); + width = w; + height = h; + + // Read how many pixels contain active data (the rest are just + // for making sure we have a 2*a x 4*b size). + + read_big_endian_2byte_word(&w, f); + read_big_endian_2byte_word(&h, f); + active_width = w; + active_height = h; + } + + printf("Width = %d, Height = %d\n",width, height); + printf("active pixel area: top left %d x %d area.\n",active_width, active_height); + + img=(uint8*)malloc(3*width*height); + if(!img) + { + printf("Error: could not allocate memory\n"); + exit(0); + } + + + for(int y=0;y.\n",srcfile); + } +} + +int determineAction(int argc,char *argv[],char *dst) +{ + char *src; + int q; + + enum {MODE_COMPRESS, MODE_UNCOMPRESS, MODE_PSNR}; + enum {SPEED_SLOW, SPEED_FAST, SPEED_MEDIUM}; + enum {METRIC_PERCEPTUAL, METRIC_NONPERCEPTUAL}; + + int mode = MODE_COMPRESS; + int speed = SPEED_FAST; + int metric = METRIC_PERCEPTUAL; + + // A bit hackish: First check for the orientation flag. When this flag is set, remove it from the string and proceed with the rest of the arguments as before. + + bool orientation_flag_found = false; + orientation = FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0; + + for(q = 1; q < argc && !orientation_flag_found; q++) + { + src = argv[q]; + if(!strcmp(src, "-o")) + { + orientation_flag_found = true; + src = argv[q+1]; + if(!strcmp(src, "topleftmapsto_s0t0")) + { + orientation = FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0; + } + else if(!strcmp(src, "bottomleftmapsto_s0t0")) + { + orientation = FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T1; + } + else + { + return -1; + } + // At this stage in the code we know we have a valid orientation argument. + // Now remove it from the argument list. + for(int xx=q+2; xx does not exist.\n",srcfile); + exit(0); + } + // 0: compress from .any to .pkm with SPEED_FAST, METRIC_NONPERCEPTUAL, + // 1: compress from .any to .pkm with SPEED_MEDIUM, METRIC_NONPERCEPTUAL, + // 2: compress from .any to .pkm with SPEED_SLOW, METRIC_NONPERCEPTUAL, + // 3: compress from .any to .pkm with SPEED_FAST, METRIC_PERCEPTUAL, + // 4: compress from .any to .pkm with SPEED_MEDIUM, METRIC_PERCEPTUAL, + // 5: compress from .any to .pkm with SPEED_SLOW, METRIC_PERCEPTUAL, + // 6: decompress from .pkm to .any + // 7: calculate PSNR between .any and .any + + if(action == 6) + { + printf("Uncompressing from .pkm file ...\n"); + printf("Using the orientation that maps the first pixel in .ppm file to "); + if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0) + printf("s=0, t=0.\n"); + else if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T1) + printf("s=0, t=1.\n"); + + uncompressFile(srcfile,dstfile); + } + else if(action == 7) + { + printf("Calculating PSNR between files...\n"); + calculatePSNRTwoFiles(srcfile,dstfile); + } + else + { + compressFile(srcfile, dstfile, action); + } + } + } else { + printf("ETCPACK v1.06\n"); + printf("Usage: etcpack srcfile dstfile\n\nCompresses and decompresses images using the Ericsson Texture Compression (ETC) scheme.\n\n"); + printf(" -s {fast|medium|slow} Compression speed. Slow = best quality\n"); + printf(" (default: fast)\n"); + printf(" -e {perceptual|nonperceptual} Error metric: Perceptual (nicest) or \n"); + printf(" nonperceptual (highest PSNR)\n"); + printf(" (default: perceptual)\n"); + printf(" -o {topleftmapsto_s0t0| Orientation: Which pixel (top left or\n"); + printf(" bottomleftmapsto_s0t0} bottom left) that will map to texture\n"); + printf(" coordinates (s=0, t=0). \n"); + printf(" (default: topleftmapsto_s0t0.) For a \n"); + printf(" .ppm file this means that the first \n"); + printf(" pixel in the file will be mapped to \n"); + printf(" s=0, t=0 by default.\n"); + printf(" \n"); + printf("Examples: \n"); + printf(" etcpack img.ppm img.ktx Compresses img.ppm to img.ktx\n"); + printf(" etcpack img.ppm img.pkm Compresses img.ppm to img.pkm\n"); + printf(" etcpack img.ktx img_copy.ppm Decompresses img.ktx to img_copy.ppm\n"); + printf(" etcpack -s slow img.ppm img.ktx Compress using the slow mode.\n"); + printf(" etcpack -p orig.ppm copy.ppm Calculate PSNR between orig and copy\n\n"); + + } + return 0; + +} diff --git a/ext/etcpack/image.cpp b/ext/etcpack/image.cpp new file mode 100644 index 0000000000..61688632b5 --- /dev/null +++ b/ext/etcpack/image.cpp @@ -0,0 +1,212 @@ +// image.cxx +// +// NO WARRANTY +// +// BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, ERICSSON MAKES NO +// REPRESENTATIONS OF ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND; EITHER +// EXPRESS OR IMPLIED; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +// PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME +// THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON +// MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, LEASE, USE OR +// IMPORTATION WILL BE FREE FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR +// OTHER INTELLECTUAL PROPERTY RIGHTS OF OTHERS, AND IT SHALL BE THE SOLE +// RESPONSIBILITY OF THE LICENSEE TO MAKE SUCH DETERMINATION AS IS +// NECESSARY WITH RESPECT TO THE ACQUISITION OF LICENSES UNDER PATENTS +// AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES; +// +// IN NO EVENT WILL ERICSSON, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +// GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF +// THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO +// LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +// YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY +// OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGES. +// +// (C) Ericsson AB 2005. All Rights Reserved. +// +#include +#include +#include +#include "image.h" + +// Removes comments in a .ppm file +// (i.e., lines starting with #) +// +// Written by Jacob Strom +// +void removeComments(FILE *f1) +{ + int c; + + while((c = getc(f1)) == '#') + { + char line[1024]; + fgets(line, 1024, f1); + } + ungetc(c, f1); +} + + +// Removes white spaces in a .ppm file +// +// Written by Jacob Strom +// +void removeSpaces(FILE *f1) +{ + int c; + + c = getc(f1); + while(c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r') + { + c = getc(f1); + } + ungetc(c, f1); +} + +// fReadPPM +// +// Written by Jacob Strom +// +// reads a ppm file with P6 header (meaning binary, as opposed to P5, which is ascII) +// and returns the image in pixels. +// +// The header must look like this: +// +// P6 +// # Comments (not necessary) +// width height +// 255 +// +// after that follows RGBRGBRGB... +// +bool fReadPPM(const char *filename, int &width, int &height, unsigned char *&pixels, bool reverse_y) +{ + FILE *f1; + int mustbe255; + f1 = fopen(filename, "rb"); + + if(f1) + { + char line[255]; + + removeSpaces(f1); + removeComments(f1); + removeSpaces(f1); + + fscanf(f1, "%s", line); + + if(strcmp(line, "P6")!=0) + { + printf("Error: %s is not binary\n"); + printf("(Binary .ppm files start with P6).\n"); + fclose(f1); + return false; + } + removeSpaces(f1); + removeComments(f1); + removeSpaces(f1); + + fscanf(f1, "%d %d", &width, &height); + if( width<=0 || height <=0) + { + printf("Error: width or height negative. File: %s\n",filename); + fclose(f1); + return false; + } + + removeSpaces(f1); + removeComments(f1); + removeSpaces(f1); + + fscanf(f1, "%d", &mustbe255); + if( mustbe255!= 255 ) + { + printf("Error: Color resolution must be 255. File: %s\n",filename); + fclose(f1); + return false; + } + + // We need to remove the newline. + char c = 0; + while(c != '\n') + fscanf(f1, "%c", &c); + + + pixels = (unsigned char*) malloc(3*width*height); + + if(!pixels) + { + printf("Error: Could not allocate memory for image. File: %s\n", filename); + fclose(f1); + return false; + } + + if(reverse_y) + { + for(int yy = 0; yy header file. */ +#define HAVE_DLFCN_H 0 + +/* Define to 1 if you have the `fseeko' function. */ +#define HAVE_FSEEKO 0 + +/* Define to 1 if you have the `ftello' function. */ +#define HAVE_FTELLO 0 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 0 + +/* Define to 1 if you have the `z' library (-lz). */ +#define HAVE_LIBZ 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 0 + +/* Define to 1 if you have the `mkstemp' function. */ +#define HAVE_MKSTEMP 0 + +/* Define to 1 if you have the `MoveFileExA' function. */ +/* #undef HAVE_MOVEFILEEXA */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if `tm_zone' is a member of `struct tm'. */ +#define HAVE_STRUCT_TM_TM_ZONE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use + `HAVE_STRUCT_TM_TM_ZONE' instead. */ +#define HAVE_TM_ZONE 1 + +/* Define to 1 if you don't have `tm_zone' but do have the external array + `tzname'. */ +/* #undef HAVE_TZNAME */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "libzip" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "libzip@nih.at" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libzip" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libzip 0.9.3" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libzip" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.9.3" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Version number of package */ +#define VERSION "0.9.3" diff --git a/ext/libzip/libzip.la b/ext/libzip/libzip.la new file mode 100644 index 0000000000..49b0cd7779 --- /dev/null +++ b/ext/libzip/libzip.la @@ -0,0 +1,41 @@ +# libzip.la - a libtool library file +# Generated by ltmain.sh (GNU libtool) 2.2.6b +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libzip.so.1' + +# Names of this library. +library_names='libzip.so.1.0.0 libzip.so.1 libzip.so' + +# The name of the static archive. +old_library='libzip.a' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs=' -lz' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libzip. +current=1 +age=0 +revision=0 + +# Is this an already installed library? +installed=no + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/usr/local/lib' diff --git a/ext/libzip/mkstemp.c b/ext/libzip/mkstemp.c new file mode 100644 index 0000000000..738a065a09 --- /dev/null +++ b/ext/libzip/mkstemp.c @@ -0,0 +1,140 @@ +/* $NiH: mkstemp.c,v 1.3 2006/04/23 14:51:45 wiz Exp $ */ + +/* Adapted from NetBSB libc by Dieter Baron */ + +/* NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + + + +int +_zip_mkstemp(char *path) +{ + int fd; + char *start, *trv; + struct stat sbuf; + pid_t pid; + + /* To guarantee multiple calls generate unique names even if + the file is not created. 676 different possibilities with 7 + or more X's, 26 with 6 or less. */ + static char xtra[2] = "aa"; + int xcnt = 0; + + pid = getpid(); + + /* Move to end of path and count trailing X's. */ + for (trv = path; *trv; ++trv) + if (*trv == 'X') + xcnt++; + else + xcnt = 0; + + /* Use at least one from xtra. Use 2 if more than 6 X's. */ + if (*(trv - 1) == 'X') + *--trv = xtra[0]; + if (xcnt > 6 && *(trv - 1) == 'X') + *--trv = xtra[1]; + + /* Set remaining X's to pid digits with 0's to the left. */ + while (*--trv == 'X') { + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* update xtra for next call. */ + if (xtra[0] != 'z') + xtra[0]++; + else { + xtra[0] = 'a'; + if (xtra[1] != 'z') + xtra[1]++; + else + xtra[1] = 'a'; + } + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + if (stat(path, &sbuf)) + return (0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return (0); + } + *trv = '/'; + break; + } + } + + for (;;) { + if ((fd=open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0) + return (fd); + if (errno != EEXIST) + return (0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return (0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit((unsigned char)*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +} diff --git a/ext/libzip/zip.h b/ext/libzip/zip.h new file mode 100644 index 0000000000..48431a35c9 --- /dev/null +++ b/ext/libzip/zip.h @@ -0,0 +1,230 @@ +#ifndef _HAD_ZIP_H +#define _HAD_ZIP_H + +/* + zip.h -- exported declarations. + Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#ifndef ZIP_EXTERN +#ifdef _MSC_VER +#define ZIP_EXTERN __declspec(dllexport) +#else +#define ZIP_EXTERN +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* flags for zip_open */ + +#define ZIP_CREATE 1 +#define ZIP_EXCL 2 +#define ZIP_CHECKCONS 4 + + +/* flags for zip_name_locate, zip_fopen, zip_stat, ... */ + +#define ZIP_FL_NOCASE 1 /* ignore case on name lookup */ +#define ZIP_FL_NODIR 2 /* ignore directory component */ +#define ZIP_FL_COMPRESSED 4 /* read compressed data */ +#define ZIP_FL_UNCHANGED 8 /* use original data, ignoring changes */ +#define ZIP_FL_RECOMPRESS 16 /* force recompression of data */ + +/* archive global flags flags */ + +#define ZIP_AFL_TORRENT 1 /* torrent zipped */ + +/* libzip error codes */ + +#define ZIP_ER_OK 0 /* N No error */ +#define ZIP_ER_MULTIDISK 1 /* N Multi-disk zip archives not supported */ +#define ZIP_ER_RENAME 2 /* S Renaming temporary file failed */ +#define ZIP_ER_CLOSE 3 /* S Closing zip archive failed */ +#define ZIP_ER_SEEK 4 /* S Seek error */ +#define ZIP_ER_READ 5 /* S Read error */ +#define ZIP_ER_WRITE 6 /* S Write error */ +#define ZIP_ER_CRC 7 /* N CRC error */ +#define ZIP_ER_ZIPCLOSED 8 /* N Containing zip archive was closed */ +#define ZIP_ER_NOENT 9 /* N No such file */ +#define ZIP_ER_EXISTS 10 /* N File already exists */ +#define ZIP_ER_OPEN 11 /* S Can't open file */ +#define ZIP_ER_TMPOPEN 12 /* S Failure to create temporary file */ +#define ZIP_ER_ZLIB 13 /* Z Zlib error */ +#define ZIP_ER_MEMORY 14 /* N Malloc failure */ +#define ZIP_ER_CHANGED 15 /* N Entry has been changed */ +#define ZIP_ER_COMPNOTSUPP 16 /* N Compression method not supported */ +#define ZIP_ER_EOF 17 /* N Premature EOF */ +#define ZIP_ER_INVAL 18 /* N Invalid argument */ +#define ZIP_ER_NOZIP 19 /* N Not a zip archive */ +#define ZIP_ER_INTERNAL 20 /* N Internal error */ +#define ZIP_ER_INCONS 21 /* N Zip archive inconsistent */ +#define ZIP_ER_REMOVE 22 /* S Can't remove file */ +#define ZIP_ER_DELETED 23 /* N Entry has been deleted */ + + +/* type of system error value */ + +#define ZIP_ET_NONE 0 /* sys_err unused */ +#define ZIP_ET_SYS 1 /* sys_err is errno */ +#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */ + +/* compression methods */ + +#define ZIP_CM_DEFAULT -1 /* better of deflate or store */ +#define ZIP_CM_STORE 0 /* stored (uncompressed) */ +#define ZIP_CM_SHRINK 1 /* shrunk */ +#define ZIP_CM_REDUCE_1 2 /* reduced with factor 1 */ +#define ZIP_CM_REDUCE_2 3 /* reduced with factor 2 */ +#define ZIP_CM_REDUCE_3 4 /* reduced with factor 3 */ +#define ZIP_CM_REDUCE_4 5 /* reduced with factor 4 */ +#define ZIP_CM_IMPLODE 6 /* imploded */ +/* 7 - Reserved for Tokenizing compression algorithm */ +#define ZIP_CM_DEFLATE 8 /* deflated */ +#define ZIP_CM_DEFLATE64 9 /* deflate64 */ +#define ZIP_CM_PKWARE_IMPLODE 10 /* PKWARE imploding */ +/* 11 - Reserved by PKWARE */ +#define ZIP_CM_BZIP2 12 /* compressed using BZIP2 algorithm */ +/* 13 - Reserved by PKWARE */ +#define ZIP_CM_LZMA 14 /* LZMA (EFS) */ +/* 15-17 - Reserved by PKWARE */ +#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */ +#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */ +#define ZIP_CM_WAVPACK 97 /* WavPack compressed data */ +#define ZIP_CM_PPMD 98 /* PPMd version I, Rev 1 */ + +/* encryption methods */ + +#define ZIP_EM_NONE 0 /* not encrypted */ +#define ZIP_EM_TRAD_PKWARE 1 /* traditional PKWARE encryption */ +#if 0 /* Strong Encryption Header not parsed yet */ +#define ZIP_EM_DES 0x6601 /* strong encryption: DES */ +#define ZIP_EM_RC2_OLD 0x6602 /* strong encryption: RC2, version < 5.2 */ +#define ZIP_EM_3DES_168 0x6603 +#define ZIP_EM_3DES_112 0x6609 +#define ZIP_EM_AES_128 0x660e +#define ZIP_EM_AES_192 0x660f +#define ZIP_EM_AES_256 0x6610 +#define ZIP_EM_RC2 0x6702 /* strong encryption: RC2, version >= 5.2 */ +#define ZIP_EM_RC4 0x6801 +#endif +#define ZIP_EM_UNKNOWN 0xffff /* unknown algorithm */ + + + +enum zip_source_cmd { + ZIP_SOURCE_OPEN, /* prepare for reading */ + ZIP_SOURCE_READ, /* read data */ + ZIP_SOURCE_CLOSE, /* reading is done */ + ZIP_SOURCE_STAT, /* get meta information */ + ZIP_SOURCE_ERROR, /* get error information */ + ZIP_SOURCE_FREE /* cleanup and free resources */ +}; + +typedef ssize_t (*zip_source_callback)(void *state, void *data, + size_t len, enum zip_source_cmd cmd); + +struct zip_stat { + const char *name; /* name of the file */ + int index; /* index within archive */ + unsigned int crc; /* crc of file data */ + time_t mtime; /* modification time */ + off_t size; /* size of file (uncompressed) */ + off_t comp_size; /* size of file (compressed) */ + unsigned short comp_method; /* compression method used */ + unsigned short encryption_method; /* encryption method used */ +}; + +struct zip; +struct zip_file; +struct zip_source; + + + +ZIP_EXTERN int zip_add(struct zip *, const char *, struct zip_source *); +ZIP_EXTERN int zip_add_dir(struct zip *, const char *); +ZIP_EXTERN int zip_close(struct zip *); +ZIP_EXTERN int zip_delete(struct zip *, int); +ZIP_EXTERN void zip_error_clear(struct zip *); +ZIP_EXTERN void zip_error_get(struct zip *, int *, int *); +ZIP_EXTERN int zip_error_get_sys_type(int); +ZIP_EXTERN int zip_error_to_str(char *, size_t, int, int); +ZIP_EXTERN int zip_fclose(struct zip_file *); +ZIP_EXTERN void zip_file_error_clear(struct zip_file *); +ZIP_EXTERN void zip_file_error_get(struct zip_file *, int *, int *); +ZIP_EXTERN const char *zip_file_strerror(struct zip_file *); +ZIP_EXTERN struct zip_file *zip_fopen(struct zip *, const char *, int); +ZIP_EXTERN struct zip_file *zip_fopen_index(struct zip *, int, int); +ZIP_EXTERN ssize_t zip_fread(struct zip_file *, void *, size_t); +ZIP_EXTERN const char *zip_get_archive_comment(struct zip *, int *, int); +ZIP_EXTERN int zip_get_archive_flag(struct zip *, int, int); +ZIP_EXTERN const char *zip_get_file_comment(struct zip *, int, int *, int); +ZIP_EXTERN const char *zip_get_name(struct zip *, int, int); +ZIP_EXTERN int zip_get_num_files(struct zip *); +ZIP_EXTERN int zip_name_locate(struct zip *, const char *, int); +ZIP_EXTERN struct zip *zip_open(const char *, int, int *); +ZIP_EXTERN int zip_rename(struct zip *, int, const char *); +ZIP_EXTERN int zip_replace(struct zip *, int, struct zip_source *); +ZIP_EXTERN int zip_set_archive_comment(struct zip *, const char *, int); +ZIP_EXTERN int zip_set_archive_flag(struct zip *, int, int); +ZIP_EXTERN int zip_set_file_comment(struct zip *, int, const char *, int); +ZIP_EXTERN struct zip_source *zip_source_buffer(struct zip *, const void *, + off_t, int); +ZIP_EXTERN struct zip_source *zip_source_file(struct zip *, const char *, + off_t, off_t); +ZIP_EXTERN struct zip_source *zip_source_filep(struct zip *, FILE *, + off_t, off_t); +ZIP_EXTERN void zip_source_free(struct zip_source *); +ZIP_EXTERN struct zip_source *zip_source_function(struct zip *, + zip_source_callback, void *); +ZIP_EXTERN struct zip_source *zip_source_zip(struct zip *, struct zip *, + int, int, off_t, off_t); +ZIP_EXTERN int zip_stat(struct zip *, const char *, int, struct zip_stat *); +ZIP_EXTERN int zip_stat_index(struct zip *, int, int, struct zip_stat *); +ZIP_EXTERN void zip_stat_init(struct zip_stat *); +ZIP_EXTERN const char *zip_strerror(struct zip *); +ZIP_EXTERN int zip_unchange(struct zip *, int); +ZIP_EXTERN int zip_unchange_all(struct zip *); +ZIP_EXTERN int zip_unchange_archive(struct zip *); + +#ifdef __cplusplus +} +#endif + +#endif /* _HAD_ZIP_H */ diff --git a/ext/libzip/zip_add.c b/ext/libzip/zip_add.c new file mode 100644 index 0000000000..f6bdb2ab92 --- /dev/null +++ b/ext/libzip/zip_add.c @@ -0,0 +1,49 @@ +/* + zip_add.c -- add file via callback function + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_add(struct zip *za, const char *name, struct zip_source *source) +{ + if (name == NULL || source == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_replace(za, -1, name, source); +} diff --git a/ext/libzip/zip_add_dir.c b/ext/libzip/zip_add_dir.c new file mode 100644 index 0000000000..493e28ddab --- /dev/null +++ b/ext/libzip/zip_add_dir.c @@ -0,0 +1,80 @@ +/* + zip_add_dir.c -- add directory + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_add_dir(struct zip *za, const char *name) +{ + int len, ret; + char *s; + struct zip_source *source; + + if (name == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + s = NULL; + len = strlen(name); + + if (name[len-1] != '/') { + if ((s=(char *)malloc(len+2)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + strcpy(s, name); + s[len] = '/'; + s[len+1] = '\0'; + } + + if ((source=zip_source_buffer(za, NULL, 0, 0)) == NULL) { + free(s); + return -1; + } + + ret = _zip_replace(za, -1, s ? s : name, source); + + free(s); + if (ret < 0) + zip_source_free(source); + + return ret; +} diff --git a/ext/libzip/zip_close.c b/ext/libzip/zip_close.c new file mode 100644 index 0000000000..c6885d96a9 --- /dev/null +++ b/ext/libzip/zip_close.c @@ -0,0 +1,679 @@ +/* + zip_close.c -- close zip archive and update changes + Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include +#include +#include +#include +#include + +#include "zipint.h" + +static int add_data(struct zip *, struct zip_source *, struct zip_dirent *, + FILE *); +static int add_data_comp(zip_source_callback, void *, struct zip_stat *, + FILE *, struct zip_error *); +static int add_data_uncomp(struct zip *, zip_source_callback, void *, + struct zip_stat *, FILE *); +static void ch_set_error(struct zip_error *, zip_source_callback, void *); +static int copy_data(FILE *, off_t, FILE *, struct zip_error *); +static int write_cdir(struct zip *, struct zip_cdir *, FILE *); +static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *); +static int _zip_changed(struct zip *, int *); +static char *_zip_create_temp_output(struct zip *, FILE **); +static int _zip_torrentzip_cmp(const void *, const void *); + + + +struct filelist { + int idx; + const char *name; +}; + + + +ZIP_EXTERN int +zip_close(struct zip *za) +{ + int survivors; + int i, j, error; + char *temp; + FILE *out; + mode_t mask; + struct zip_cdir *cd; + struct zip_dirent de; + struct filelist *filelist; + int reopen_on_error; + int new_torrentzip; + + reopen_on_error = 0; + + if (za == NULL) + return -1; + + if (!_zip_changed(za, &survivors)) { + _zip_free(za); + return 0; + } + + /* don't create zip files with no entries */ + if (survivors == 0) { + if (za->zn && za->zp) { + if (remove(za->zn) != 0) { + _zip_error_set(&za->error, ZIP_ER_REMOVE, errno); + return -1; + } + } + _zip_free(za); + return 0; + } + + if ((filelist=(struct filelist *)malloc(sizeof(filelist[0])*survivors)) + == NULL) + return -1; + + if ((cd=_zip_cdir_new(survivors, &za->error)) == NULL) { + free(filelist); + return -1; + } + + for (i=0; ientry[i]); + + /* archive comment is special for torrentzip */ + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) { + cd->comment = _zip_memdup(TORRENT_SIG "XXXXXXXX", + TORRENT_SIG_LEN + TORRENT_CRC_LEN, + &za->error); + if (cd->comment == NULL) { + _zip_cdir_free(cd); + free(filelist); + return -1; + } + cd->comment_len = TORRENT_SIG_LEN + TORRENT_CRC_LEN; + } + else if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, ZIP_FL_UNCHANGED) == 0) { + if (_zip_cdir_set_comment(cd, za) == -1) { + _zip_cdir_free(cd); + free(filelist); + return -1; + } + } + + if ((temp=_zip_create_temp_output(za, &out)) == NULL) { + _zip_cdir_free(cd); + free(filelist); + return -1; + } + + + /* create list of files with index into original archive */ + for (i=j=0; inentry; i++) { + if (za->entry[i].state == ZIP_ST_DELETED) + continue; + + filelist[j].idx = i; + filelist[j].name = zip_get_name(za, i, 0); + j++; + } + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) + qsort(filelist, survivors, sizeof(filelist[0]), + _zip_torrentzip_cmp); + + new_torrentzip = (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 1 + && zip_get_archive_flag(za, ZIP_AFL_TORRENT, + ZIP_FL_UNCHANGED) == 0); + error = 0; + for (j=0; jentry+i) || new_torrentzip) { + _zip_dirent_init(&de); + + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) + _zip_dirent_torrent_normalize(&de); + + /* use it as central directory entry */ + memcpy(cd->entry+j, &de, sizeof(cd->entry[j])); + + /* set/update file name */ + if (za->entry[i].ch_filename == NULL) { + if (za->entry[i].state == ZIP_ST_ADDED) { + de.filename = strdup("-"); + de.filename_len = 1; + cd->entry[j].filename = "-"; + cd->entry[j].filename_len = 1; + } + else { + de.filename = strdup(za->cdir->entry[i].filename); + de.filename_len = strlen(de.filename); + cd->entry[j].filename = za->cdir->entry[i].filename; + cd->entry[j].filename_len = de.filename_len; + } + } + } + else { + /* copy existing directory entries */ + if (fseeko(za->zp, za->cdir->entry[i].offset, SEEK_SET) != 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + error = 1; + break; + } + if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1, + &za->error) != 0) { + error = 1; + break; + } + memcpy(cd->entry+j, za->cdir->entry+i, sizeof(cd->entry[j])); + if (de.bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { + de.crc = za->cdir->entry[i].crc; + de.comp_size = za->cdir->entry[i].comp_size; + de.uncomp_size = za->cdir->entry[i].uncomp_size; + de.bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; + cd->entry[j].bitflags &= ~ZIP_GPBF_DATA_DESCRIPTOR; + } + } + + if (za->entry[i].ch_filename) { + free(de.filename); + if ((de.filename=strdup(za->entry[i].ch_filename)) == NULL) { + error = 1; + break; + } + de.filename_len = strlen(de.filename); + cd->entry[j].filename = za->entry[i].ch_filename; + cd->entry[j].filename_len = de.filename_len; + } + + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0 + && za->entry[i].ch_comment_len != -1) { + /* as the rest of cd entries, its malloc/free is done by za */ + cd->entry[j].comment = za->entry[i].ch_comment; + cd->entry[j].comment_len = za->entry[i].ch_comment_len; + } + + cd->entry[j].offset = ftello(out); + + if (ZIP_ENTRY_DATA_CHANGED(za->entry+i) || new_torrentzip) { + struct zip_source *zs; + + zs = NULL; + if (!ZIP_ENTRY_DATA_CHANGED(za->entry+i)) { + if ((zs=zip_source_zip(za, za, i, ZIP_FL_RECOMPRESS, 0, -1)) + == NULL) { + error = 1; + break; + } + } + + if (add_data(za, zs ? zs : za->entry[i].source, &de, out) < 0) { + error = 1; + break; + } + cd->entry[j].last_mod = de.last_mod; + cd->entry[j].comp_method = de.comp_method; + cd->entry[j].comp_size = de.comp_size; + cd->entry[j].uncomp_size = de.uncomp_size; + cd->entry[j].crc = de.crc; + } + else { + if (_zip_dirent_write(&de, out, 1, &za->error) < 0) { + error = 1; + break; + } + /* we just read the local dirent, file is at correct position */ + if (copy_data(za->zp, cd->entry[j].comp_size, out, + &za->error) < 0) { + error = 1; + break; + } + } + + _zip_dirent_finalize(&de); + } + + free(filelist); + + if (!error) { + if (write_cdir(za, cd, out) < 0) + error = 1; + } + + /* pointers in cd entries are owned by za */ + cd->nentry = 0; + _zip_cdir_free(cd); + + if (error) { + _zip_dirent_finalize(&de); + fclose(out); + remove(temp); + free(temp); + return -1; + } + + if (fclose(out) != 0) { + _zip_error_set(&za->error, ZIP_ER_CLOSE, errno); + remove(temp); + free(temp); + return -1; + } + + if (za->zp) { + fclose(za->zp); + za->zp = NULL; + reopen_on_error = 1; + } + if (_zip_rename(temp, za->zn) != 0) { + _zip_error_set(&za->error, ZIP_ER_RENAME, errno); + remove(temp); + free(temp); + if (reopen_on_error) { + /* ignore errors, since we're already in an error case */ + za->zp = fopen(za->zn, "rb"); + } + return -1; + } + mask = umask(0); + umask(mask); + chmod(za->zn, 0666&~mask); + + _zip_free(za); + free(temp); + + return 0; +} + + + +static int +add_data(struct zip *za, struct zip_source *zs, struct zip_dirent *de, FILE *ft) +{ + off_t offstart, offend; + zip_source_callback cb; + void *ud; + struct zip_stat st; + + cb = zs->f; + ud = zs->ud; + + if (cb(ud, &st, sizeof(st), ZIP_SOURCE_STAT) < (ssize_t)sizeof(st)) { + ch_set_error(&za->error, cb, ud); + return -1; + } + + if (cb(ud, NULL, 0, ZIP_SOURCE_OPEN) < 0) { + ch_set_error(&za->error, cb, ud); + return -1; + } + + offstart = ftello(ft); + + if (_zip_dirent_write(de, ft, 1, &za->error) < 0) + return -1; + + if (st.comp_method != ZIP_CM_STORE) { + if (add_data_comp(cb, ud, &st, ft, &za->error) < 0) + return -1; + } + else { + if (add_data_uncomp(za, cb, ud, &st, ft) < 0) + return -1; + } + + if (cb(ud, NULL, 0, ZIP_SOURCE_CLOSE) < 0) { + ch_set_error(&za->error, cb, ud); + return -1; + } + + offend = ftello(ft); + + if (fseeko(ft, offstart, SEEK_SET) < 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } + + + de->last_mod = st.mtime; + de->comp_method = st.comp_method; + de->crc = st.crc; + de->uncomp_size = st.size; + de->comp_size = st.comp_size; + + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) + _zip_dirent_torrent_normalize(de); + + if (_zip_dirent_write(de, ft, 1, &za->error) < 0) + return -1; + + if (fseeko(ft, offend, SEEK_SET) < 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } + + return 0; +} + + + +static int +add_data_comp(zip_source_callback cb, void *ud, struct zip_stat *st,FILE *ft, + struct zip_error *error) +{ + char buf[BUFSIZE]; + ssize_t n; + + st->comp_size = 0; + while ((n=cb(ud, buf, sizeof(buf), ZIP_SOURCE_READ)) > 0) { + if (fwrite(buf, 1, n, ft) != (size_t)n) { + _zip_error_set(error, ZIP_ER_WRITE, errno); + return -1; + } + + st->comp_size += n; + } + if (n < 0) { + ch_set_error(error, cb, ud); + return -1; + } + + return 0; +} + + + +static int +add_data_uncomp(struct zip *za, zip_source_callback cb, void *ud, + struct zip_stat *st, FILE *ft) +{ + char b1[BUFSIZE], b2[BUFSIZE]; + int end, flush, ret; + ssize_t n; + size_t n2; + z_stream zstr; + int mem_level; + + st->comp_method = ZIP_CM_DEFLATE; + st->comp_size = st->size = 0; + st->crc = crc32(0, NULL, 0); + + zstr.zalloc = Z_NULL; + zstr.zfree = Z_NULL; + zstr.opaque = NULL; + zstr.avail_in = 0; + zstr.avail_out = 0; + + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) + mem_level = TORRENT_MEM_LEVEL; + else + mem_level = MAX_MEM_LEVEL; + + /* -MAX_WBITS: undocumented feature of zlib to _not_ write a zlib header */ + deflateInit2(&zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, mem_level, + Z_DEFAULT_STRATEGY); + + zstr.next_out = (Bytef *)b2; + zstr.avail_out = sizeof(b2); + zstr.next_in = NULL; + zstr.avail_in = 0; + + flush = 0; + end = 0; + while (!end) { + if (zstr.avail_in == 0 && !flush) { + if ((n=cb(ud, b1, sizeof(b1), ZIP_SOURCE_READ)) < 0) { + ch_set_error(&za->error, cb, ud); + deflateEnd(&zstr); + return -1; + } + if (n > 0) { + zstr.avail_in = n; + zstr.next_in = (Bytef *)b1; + st->size += n; + st->crc = crc32(st->crc, (Bytef *)b1, n); + } + else + flush = Z_FINISH; + } + + ret = deflate(&zstr, flush); + if (ret != Z_OK && ret != Z_STREAM_END) { + _zip_error_set(&za->error, ZIP_ER_ZLIB, ret); + return -1; + } + + if (zstr.avail_out != sizeof(b2)) { + n2 = sizeof(b2) - zstr.avail_out; + + if (fwrite(b2, 1, n2, ft) != n2) { + _zip_error_set(&za->error, ZIP_ER_WRITE, errno); + return -1; + } + + zstr.next_out = (Bytef *)b2; + zstr.avail_out = sizeof(b2); + st->comp_size += n2; + } + + if (ret == Z_STREAM_END) { + deflateEnd(&zstr); + end = 1; + } + } + + return 0; +} + + + +static void +ch_set_error(struct zip_error *error, zip_source_callback cb, void *ud) +{ + int e[2]; + + if ((cb(ud, e, sizeof(e), ZIP_SOURCE_ERROR)) < (ssize_t)sizeof(e)) { + error->zip_err = ZIP_ER_INTERNAL; + error->sys_err = 0; + } + else { + error->zip_err = e[0]; + error->sys_err = e[1]; + } +} + + + +static int +copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error) +{ + char buf[BUFSIZE]; + int n, nn; + + if (len == 0) + return 0; + + while (len > 0) { + nn = len > sizeof(buf) ? sizeof(buf) : len; + if ((n=fread(buf, 1, nn, fs)) < 0) { + _zip_error_set(error, ZIP_ER_READ, errno); + return -1; + } + else if (n == 0) { + _zip_error_set(error, ZIP_ER_EOF, 0); + return -1; + } + + if (fwrite(buf, 1, n, ft) != (size_t)n) { + _zip_error_set(error, ZIP_ER_WRITE, errno); + return -1; + } + + len -= n; + } + + return 0; +} + + + +static int +write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out) +{ + off_t offset; + uLong crc; + char buf[TORRENT_CRC_LEN+1]; + + if (_zip_cdir_write(cd, out, &za->error) < 0) + return -1; + + if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0) + return 0; + + + /* fix up torrentzip comment */ + + offset = ftello(out); + + if (_zip_filerange_crc(out, cd->offset, cd->size, &crc, &za->error) < 0) + return -1; + + snprintf(buf, sizeof(buf), "%08lX", (long)crc); + + if (fseeko(out, offset-TORRENT_CRC_LEN, SEEK_SET) < 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } + + if (fwrite(buf, TORRENT_CRC_LEN, 1, out) != 1) { + _zip_error_set(&za->error, ZIP_ER_WRITE, errno); + return -1; + } + + return 0; +} + + + +static int +_zip_cdir_set_comment(struct zip_cdir *dest, struct zip *src) +{ + if (src->ch_comment_len != -1) { + dest->comment = _zip_memdup(src->ch_comment, + src->ch_comment_len, &src->error); + if (dest->comment == NULL) + return -1; + dest->comment_len = src->ch_comment_len; + } else { + if (src->cdir && src->cdir->comment) { + dest->comment = _zip_memdup(src->cdir->comment, + src->cdir->comment_len, &src->error); + if (dest->comment == NULL) + return -1; + dest->comment_len = src->cdir->comment_len; + } + } + + return 0; +} + + + +static int +_zip_changed(struct zip *za, int *survivorsp) +{ + int changed, i, survivors; + + changed = survivors = 0; + + if (za->ch_comment_len != -1 + || za->ch_flags != za->flags) + changed = 1; + + for (i=0; inentry; i++) { + if ((za->entry[i].state != ZIP_ST_UNCHANGED) + || (za->entry[i].ch_comment_len != -1)) + changed = 1; + if (za->entry[i].state != ZIP_ST_DELETED) + survivors++; + } + + *survivorsp = survivors; + + return changed; +} + + + +static char * +_zip_create_temp_output(struct zip *za, FILE **outp) +{ + char *temp; + int tfd; + FILE *tfp; + + if ((temp=(char *)malloc(strlen(za->zn)+8)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + sprintf(temp, "%s.XXXXXX", za->zn); + + if ((tfd=mkstemp(temp)) == -1) { + _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); + free(temp); + return NULL; + } + + if ((tfp=fdopen(tfd, "r+b")) == NULL) { + _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); + close(tfd); + remove(temp); + free(temp); + return NULL; + } + + *outp = tfp; + return temp; +} + + + +static int +_zip_torrentzip_cmp(const void *a, const void *b) +{ + return strcasecmp(((const struct filelist *)a)->name, + ((const struct filelist *)b)->name); +} diff --git a/ext/libzip/zip_delete.c b/ext/libzip/zip_delete.c new file mode 100644 index 0000000000..a0545e4b9e --- /dev/null +++ b/ext/libzip/zip_delete.c @@ -0,0 +1,58 @@ +/* + zip_delete.c -- delete file from zip archive + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_delete(struct zip *za, int idx) +{ + if (idx < 0 || idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + /* allow duplicate file names, because the file will + * be removed directly afterwards */ + if (_zip_unchange(za, idx, 1) != 0) + return -1; + + za->entry[idx].state = ZIP_ST_DELETED; + + return 0; +} + + diff --git a/ext/libzip/zip_dirent.c b/ext/libzip/zip_dirent.c new file mode 100644 index 0000000000..d15b376bad --- /dev/null +++ b/ext/libzip/zip_dirent.c @@ -0,0 +1,615 @@ +/* + zip_dirent.c -- read directory entry (local or central), clean dirent + Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include +#include +#include +#include +#include + +#include "zipint.h" + +static time_t _zip_d2u_time(int, int); +static char *_zip_readfpstr(FILE *, unsigned int, int, struct zip_error *); +static char *_zip_readstr(unsigned char **, int, int, struct zip_error *); +static void _zip_u2d_time(time_t, unsigned short *, unsigned short *); +static void _zip_write2(unsigned short, FILE *); +static void _zip_write4(unsigned int, FILE *); + + + +void +_zip_cdir_free(struct zip_cdir *cd) +{ + int i; + + if (!cd) + return; + + for (i=0; inentry; i++) + _zip_dirent_finalize(cd->entry+i); + free(cd->comment); + free(cd->entry); + free(cd); +} + + + +int +_zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error) +{ + struct zip_dirent *entry; + + if (nentry < cd->nentry) { + _zip_error_set(error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((entry=((struct zip_dirent *) + realloc(cd->entry, sizeof(*(cd->entry))*nentry))) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + + cd->nentry = nentry; + cd->entry = entry; + + return 0; +} + + + +struct zip_cdir * +_zip_cdir_new(int nentry, struct zip_error *error) +{ + struct zip_cdir *cd; + + if ((cd=(struct zip_cdir *)malloc(sizeof(*cd))) == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((cd->entry=(struct zip_dirent *)malloc(sizeof(*(cd->entry))*nentry)) + == NULL) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + free(cd); + return NULL; + } + + /* entries must be initialized by caller */ + + cd->nentry = nentry; + cd->size = cd->offset = 0; + cd->comment = NULL; + cd->comment_len = 0; + + return cd; +} + + + +int +_zip_cdir_write(struct zip_cdir *cd, FILE *fp, struct zip_error *error) +{ + int i; + + cd->offset = ftello(fp); + + for (i=0; inentry; i++) { + if (_zip_dirent_write(cd->entry+i, fp, 0, error) != 0) + return -1; + } + + cd->size = ftello(fp) - cd->offset; + + /* clearerr(fp); */ + fwrite(EOCD_MAGIC, 1, 4, fp); + _zip_write4(0, fp); + _zip_write2((unsigned short)cd->nentry, fp); + _zip_write2((unsigned short)cd->nentry, fp); + _zip_write4(cd->size, fp); + _zip_write4(cd->offset, fp); + _zip_write2(cd->comment_len, fp); + fwrite(cd->comment, 1, cd->comment_len, fp); + + if (ferror(fp)) { + _zip_error_set(error, ZIP_ER_WRITE, errno); + return -1; + } + + return 0; +} + + + +void +_zip_dirent_finalize(struct zip_dirent *zde) +{ + free(zde->filename); + zde->filename = NULL; + free(zde->extrafield); + zde->extrafield = NULL; + free(zde->comment); + zde->comment = NULL; +} + + + +void +_zip_dirent_init(struct zip_dirent *de) +{ + de->version_madeby = 0; + de->version_needed = 20; /* 2.0 */ + de->bitflags = 0; + de->comp_method = 0; + de->last_mod = 0; + de->crc = 0; + de->comp_size = 0; + de->uncomp_size = 0; + de->filename = NULL; + de->filename_len = 0; + de->extrafield = NULL; + de->extrafield_len = 0; + de->comment = NULL; + de->comment_len = 0; + de->disk_number = 0; + de->int_attrib = 0; + de->ext_attrib = 0; + de->offset = 0; +} + + + +/* _zip_dirent_read(zde, fp, bufp, left, localp, error): + Fills the zip directory entry zde. + + If bufp is non-NULL, data is taken from there and bufp is advanced + by the amount of data used; otherwise data is read from fp as needed. + + if leftp is non-NULL, no more bytes than specified by it are used, + and *leftp is reduced by the number of bytes used. + + If local != 0, it reads a local header instead of a central + directory entry. + + Returns 0 if successful. On error, error is filled in and -1 is + returned. + + XXX: leftp and file position undefined on error. +*/ + +int +_zip_dirent_read(struct zip_dirent *zde, FILE *fp, + unsigned char **bufp, unsigned int *leftp, int local, + struct zip_error *error) +{ + unsigned char buf[CDENTRYSIZE]; + unsigned char *cur; + unsigned short dostime, dosdate; + unsigned int size; + + if (local) + size = LENTRYSIZE; + else + size = CDENTRYSIZE; + + if (leftp && (*leftp < size)) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + if (bufp) { + /* use data from buffer */ + cur = *bufp; + } + else { + /* read entry from disk */ + if ((fread(buf, 1, size, fp)version_madeby = _zip_read2(&cur); + else + zde->version_madeby = 0; + zde->version_needed = _zip_read2(&cur); + zde->bitflags = _zip_read2(&cur); + zde->comp_method = _zip_read2(&cur); + + /* convert to time_t */ + dostime = _zip_read2(&cur); + dosdate = _zip_read2(&cur); + zde->last_mod = _zip_d2u_time(dostime, dosdate); + + zde->crc = _zip_read4(&cur); + zde->comp_size = _zip_read4(&cur); + zde->uncomp_size = _zip_read4(&cur); + + zde->filename_len = _zip_read2(&cur); + zde->extrafield_len = _zip_read2(&cur); + + if (local) { + zde->comment_len = 0; + zde->disk_number = 0; + zde->int_attrib = 0; + zde->ext_attrib = 0; + zde->offset = 0; + } else { + zde->comment_len = _zip_read2(&cur); + zde->disk_number = _zip_read2(&cur); + zde->int_attrib = _zip_read2(&cur); + zde->ext_attrib = _zip_read4(&cur); + zde->offset = _zip_read4(&cur); + } + + zde->filename = NULL; + zde->extrafield = NULL; + zde->comment = NULL; + + size += zde->filename_len+zde->extrafield_len+zde->comment_len; + + if (leftp && (*leftp < size)) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + if (bufp) { + if (zde->filename_len) { + zde->filename = _zip_readstr(&cur, zde->filename_len, 1, error); + if (!zde->filename) + return -1; + } + + if (zde->extrafield_len) { + zde->extrafield = _zip_readstr(&cur, zde->extrafield_len, 0, + error); + if (!zde->extrafield) + return -1; + } + + if (zde->comment_len) { + zde->comment = _zip_readstr(&cur, zde->comment_len, 0, error); + if (!zde->comment) + return -1; + } + } + else { + if (zde->filename_len) { + zde->filename = _zip_readfpstr(fp, zde->filename_len, 1, error); + if (!zde->filename) + return -1; + } + + if (zde->extrafield_len) { + zde->extrafield = _zip_readfpstr(fp, zde->extrafield_len, 0, + error); + if (!zde->extrafield) + return -1; + } + + if (zde->comment_len) { + zde->comment = _zip_readfpstr(fp, zde->comment_len, 0, error); + if (!zde->comment) + return -1; + } + } + + if (bufp) + *bufp = cur; + if (leftp) + *leftp -= size; + + return 0; +} + + + +/* _zip_dirent_torrent_normalize(de); + Set values suitable for torrentzip. +*/ + +void +_zip_dirent_torrent_normalize(struct zip_dirent *de) +{ + static struct tm torrenttime; + static time_t last_mod = 0; + + if (last_mod == 0) { +#ifdef HAVE_STRUCT_TM_TM_ZONE + time_t now; + struct tm *l; +#endif + + torrenttime.tm_sec = 0; + torrenttime.tm_min = 32; + torrenttime.tm_hour = 23; + torrenttime.tm_mday = 24; + torrenttime.tm_mon = 11; + torrenttime.tm_year = 96; + torrenttime.tm_wday = 0; + torrenttime.tm_yday = 0; + torrenttime.tm_isdst = 0; + +#ifdef HAVE_STRUCT_TM_TM_ZONE + time(&now); + l = localtime(&now); + torrenttime.tm_gmtoff = l->tm_gmtoff; + torrenttime.tm_zone = l->tm_zone; +#endif + + last_mod = mktime(&torrenttime); + } + + de->version_madeby = 0; + de->version_needed = 20; /* 2.0 */ + de->bitflags = 2; /* maximum compression */ + de->comp_method = ZIP_CM_DEFLATE; + de->last_mod = last_mod; + + de->disk_number = 0; + de->int_attrib = 0; + de->ext_attrib = 0; + de->offset = 0; + + free(de->extrafield); + de->extrafield = NULL; + de->extrafield_len = 0; + free(de->comment); + de->comment = NULL; + de->comment_len = 0; +} + + + +/* _zip_dirent_write(zde, fp, localp, error): + Writes zip directory entry zde to file fp. + + If localp != 0, it writes a local header instead of a central + directory entry. + + Returns 0 if successful. On error, error is filled in and -1 is + returned. +*/ + +int +_zip_dirent_write(struct zip_dirent *zde, FILE *fp, int localp, + struct zip_error *error) +{ + unsigned short dostime, dosdate; + + fwrite(localp ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp); + + if (!localp) + _zip_write2(zde->version_madeby, fp); + _zip_write2(zde->version_needed, fp); + _zip_write2(zde->bitflags, fp); + _zip_write2(zde->comp_method, fp); + + _zip_u2d_time(zde->last_mod, &dostime, &dosdate); + _zip_write2(dostime, fp); + _zip_write2(dosdate, fp); + + _zip_write4(zde->crc, fp); + _zip_write4(zde->comp_size, fp); + _zip_write4(zde->uncomp_size, fp); + + _zip_write2(zde->filename_len, fp); + _zip_write2(zde->extrafield_len, fp); + + if (!localp) { + _zip_write2(zde->comment_len, fp); + _zip_write2(zde->disk_number, fp); + _zip_write2(zde->int_attrib, fp); + _zip_write4(zde->ext_attrib, fp); + _zip_write4(zde->offset, fp); + } + + if (zde->filename_len) + fwrite(zde->filename, 1, zde->filename_len, fp); + + if (zde->extrafield_len) + fwrite(zde->extrafield, 1, zde->extrafield_len, fp); + + if (!localp) { + if (zde->comment_len) + fwrite(zde->comment, 1, zde->comment_len, fp); + } + + if (ferror(fp)) { + _zip_error_set(error, ZIP_ER_WRITE, errno); + return -1; + } + + return 0; +} + + + +static time_t +_zip_d2u_time(int dtime, int ddate) +{ + struct tm tm; + + memset(&tm, 0, sizeof(tm)); + + /* let mktime decide if DST is in effect */ + tm.tm_isdst = -1; + + tm.tm_year = ((ddate>>9)&127) + 1980 - 1900; + tm.tm_mon = ((ddate>>5)&15) - 1; + tm.tm_mday = ddate&31; + + tm.tm_hour = (dtime>>11)&31; + tm.tm_min = (dtime>>5)&63; + tm.tm_sec = (dtime<<1)&62; + + return mktime(&tm); +} + + + +unsigned short +_zip_read2(unsigned char **a) +{ + unsigned short ret; + + ret = (*a)[0]+((*a)[1]<<8); + *a += 2; + + return ret; +} + + + +unsigned int +_zip_read4(unsigned char **a) +{ + unsigned int ret; + + ret = ((((((*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; + *a += 4; + + return ret; +} + + + +static char * +_zip_readfpstr(FILE *fp, unsigned int len, int nulp, struct zip_error *error) +{ + char *r, *o; + + r = (char *)malloc(nulp ? len+1 : len); + if (!r) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (fread(r, 1, len, fp)>8)&0xff, fp); + + return; +} + + + +static void +_zip_write4(unsigned int i, FILE *fp) +{ + putc(i&0xff, fp); + putc((i>>8)&0xff, fp); + putc((i>>16)&0xff, fp); + putc((i>>24)&0xff, fp); + + return; +} + + + +static void +_zip_u2d_time(time_t time, unsigned short *dtime, unsigned short *ddate) +{ + struct tm *tm; + + tm = localtime(&time); + *ddate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + + tm->tm_mday; + *dtime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + + ((tm->tm_sec)>>1); + + return; +} diff --git a/ext/libzip/zip_entry_free.c b/ext/libzip/zip_entry_free.c new file mode 100644 index 0000000000..c50c9434bd --- /dev/null +++ b/ext/libzip/zip_entry_free.c @@ -0,0 +1,52 @@ +/* + zip_entry_free.c -- free struct zip_entry + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +void +_zip_entry_free(struct zip_entry *ze) +{ + free(ze->ch_filename); + ze->ch_filename = NULL; + free(ze->ch_comment); + ze->ch_comment = NULL; + ze->ch_comment_len = -1; + + _zip_unchange_data(ze); +} diff --git a/ext/libzip/zip_entry_new.c b/ext/libzip/zip_entry_new.c new file mode 100644 index 0000000000..7059b1b060 --- /dev/null +++ b/ext/libzip/zip_entry_new.c @@ -0,0 +1,78 @@ +/* + zip_entry_new.c -- create and init struct zip_entry + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +struct zip_entry * +_zip_entry_new(struct zip *za) +{ + struct zip_entry *ze; + if (!za) { + ze = (struct zip_entry *)malloc(sizeof(struct zip_entry)); + if (!ze) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + } + else { + if (za->nentry >= za->nentry_alloc-1) { + za->nentry_alloc += 16; + za->entry = (struct zip_entry *)realloc(za->entry, + sizeof(struct zip_entry) + * za->nentry_alloc); + if (!za->entry) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + } + ze = za->entry+za->nentry; + } + + ze->state = ZIP_ST_UNCHANGED; + + ze->ch_filename = NULL; + ze->ch_comment = NULL; + ze->ch_comment_len = -1; + ze->source = NULL; + + if (za) + za->nentry++; + + return ze; +} diff --git a/ext/libzip/zip_err_str.c b/ext/libzip/zip_err_str.c new file mode 100644 index 0000000000..3fcdf1738a --- /dev/null +++ b/ext/libzip/zip_err_str.c @@ -0,0 +1,68 @@ +/* + This file was generated automatically by ./make_zip_err_str.sh + from ./zip.h; make changes there. + */ + +#include "zipint.h" + + + +const char * const _zip_err_str[] = { + "No error", + "Multi-disk zip archives not supported", + "Renaming temporary file failed", + "Closing zip archive failed", + "Seek error", + "Read error", + "Write error", + "CRC error", + "Containing zip archive was closed", + "No such file", + "File already exists", + "Can't open file", + "Failure to create temporary file", + "Zlib error", + "Malloc failure", + "Entry has been changed", + "Compression method not supported", + "Premature EOF", + "Invalid argument", + "Not a zip archive", + "Internal error", + "Zip archive inconsistent", + "Can't remove file", + "Entry has been deleted", +}; + +const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]); + +#define N ZIP_ET_NONE +#define S ZIP_ET_SYS +#define Z ZIP_ET_ZLIB + +const int _zip_err_type[] = { + N, + N, + S, + S, + S, + S, + S, + N, + N, + N, + N, + S, + S, + Z, + N, + N, + N, + N, + N, + N, + N, + N, + S, + N, +}; diff --git a/ext/libzip/zip_error.c b/ext/libzip/zip_error.c new file mode 100644 index 0000000000..aab7079456 --- /dev/null +++ b/ext/libzip/zip_error.c @@ -0,0 +1,101 @@ +/* + zip_error.c -- struct zip_error helper functions + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +void +_zip_error_clear(struct zip_error *err) +{ + err->zip_err = ZIP_ER_OK; + err->sys_err = 0; +} + + + +void +_zip_error_copy(struct zip_error *dst, struct zip_error *src) +{ + dst->zip_err = src->zip_err; + dst->sys_err = src->sys_err; +} + + + +void +_zip_error_fini(struct zip_error *err) +{ + free(err->str); + err->str = NULL; +} + + + +void +_zip_error_get(struct zip_error *err, int *zep, int *sep) +{ + if (zep) + *zep = err->zip_err; + if (sep) { + if (zip_error_get_sys_type(err->zip_err) != ZIP_ET_NONE) + *sep = err->sys_err; + else + *sep = 0; + } +} + + + +void +_zip_error_init(struct zip_error *err) +{ + err->zip_err = ZIP_ER_OK; + err->sys_err = 0; + err->str = NULL; +} + + + +void +_zip_error_set(struct zip_error *err, int ze, int se) +{ + if (err) { + err->zip_err = ze; + err->sys_err = se; + } +} diff --git a/ext/libzip/zip_error_clear.c b/ext/libzip/zip_error_clear.c new file mode 100644 index 0000000000..364383ebe9 --- /dev/null +++ b/ext/libzip/zip_error_clear.c @@ -0,0 +1,44 @@ +/* + zip_error_clear.c -- clear zip error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN void +zip_error_clear(struct zip *za) +{ + _zip_error_clear(&za->error); +} diff --git a/ext/libzip/zip_error_get.c b/ext/libzip/zip_error_get.c new file mode 100644 index 0000000000..6d1c958c17 --- /dev/null +++ b/ext/libzip/zip_error_get.c @@ -0,0 +1,44 @@ +/* + zip_error_get.c -- get zip error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN void +zip_error_get(struct zip *za, int *zep, int *sep) +{ + _zip_error_get(&za->error, zep, sep); +} diff --git a/ext/libzip/zip_error_get_sys_type.c b/ext/libzip/zip_error_get_sys_type.c new file mode 100644 index 0000000000..6c6f380740 --- /dev/null +++ b/ext/libzip/zip_error_get_sys_type.c @@ -0,0 +1,47 @@ +/* + zip_error_get_sys_type.c -- return type of system error code + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_error_get_sys_type(int ze) +{ + if (ze < 0 || ze >= _zip_nerr_str) + return 0; + + return _zip_err_type[ze]; +} diff --git a/ext/libzip/zip_error_strerror.c b/ext/libzip/zip_error_strerror.c new file mode 100644 index 0000000000..3d0951cfb1 --- /dev/null +++ b/ext/libzip/zip_error_strerror.c @@ -0,0 +1,90 @@ +/* + zip_error_sterror.c -- get string representation of struct zip_error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include +#include +#include + +#include "zipint.h" + + + +const char * +_zip_error_strerror(struct zip_error *err) +{ + const char *zs, *ss; + char buf[128], *s; + + _zip_error_fini(err); + + if (err->zip_err < 0 || err->zip_err >= _zip_nerr_str) { + sprintf(buf, "Unknown error %d", err->zip_err); + zs = NULL; + ss = buf; + } + else { + zs = _zip_err_str[err->zip_err]; + + switch (_zip_err_type[err->zip_err]) { + case ZIP_ET_SYS: + ss = strerror(err->sys_err); + break; + + case ZIP_ET_ZLIB: + ss = zError(err->sys_err); + break; + + default: + ss = NULL; + } + } + + if (ss == NULL) + return zs; + else { + if ((s=(char *)malloc(strlen(ss) + + (zs ? strlen(zs)+2 : 0) + 1)) == NULL) + return _zip_err_str[ZIP_ER_MEMORY]; + + sprintf(s, "%s%s%s", + (zs ? zs : ""), + (zs ? ": " : ""), + ss); + err->str = s; + + return s; + } +} diff --git a/ext/libzip/zip_error_to_str.c b/ext/libzip/zip_error_to_str.c new file mode 100644 index 0000000000..bdba41a6cb --- /dev/null +++ b/ext/libzip/zip_error_to_str.c @@ -0,0 +1,70 @@ +/* + zip_error_to_str.c -- get string representation of zip error code + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include +#include +#include + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_error_to_str(char *buf, size_t len, int ze, int se) +{ + const char *zs, *ss; + + if (ze < 0 || ze >= _zip_nerr_str) + return snprintf(buf, len, "Unknown error %d", ze); + + zs = _zip_err_str[ze]; + + switch (_zip_err_type[ze]) { + case ZIP_ET_SYS: + ss = strerror(se); + break; + + case ZIP_ET_ZLIB: + ss = zError(se); + break; + + default: + ss = NULL; + } + + return snprintf(buf, len, "%s%s%s", + zs, (ss ? ": " : ""), (ss ? ss : "")); +} diff --git a/ext/libzip/zip_fclose.c b/ext/libzip/zip_fclose.c new file mode 100644 index 0000000000..8709362d6c --- /dev/null +++ b/ext/libzip/zip_fclose.c @@ -0,0 +1,71 @@ +/* + zip_fclose.c -- close file in zip archive + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_fclose(struct zip_file *zf) +{ + int i, ret; + + if (zf->zstr) + inflateEnd(zf->zstr); + free(zf->buffer); + free(zf->zstr); + + for (i=0; iza->nfile; i++) { + if (zf->za->file[i] == zf) { + zf->za->file[i] = zf->za->file[zf->za->nfile-1]; + zf->za->nfile--; + break; + } + } + + ret = 0; + if (zf->error.zip_err) + ret = zf->error.zip_err; + else if ((zf->flags & ZIP_ZF_CRC) && (zf->flags & ZIP_ZF_EOF)) { + /* if EOF, compare CRC */ + if (zf->crc_orig != zf->crc) + ret = ZIP_ER_CRC; + } + + free(zf); + return ret; +} diff --git a/ext/libzip/zip_file_error_clear.c b/ext/libzip/zip_file_error_clear.c new file mode 100644 index 0000000000..ef6fa10e4d --- /dev/null +++ b/ext/libzip/zip_file_error_clear.c @@ -0,0 +1,44 @@ +/* + zip_file_error_clear.c -- clear zip file error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN void +zip_file_error_clear(struct zip_file *zf) +{ + _zip_error_clear(&zf->error); +} diff --git a/ext/libzip/zip_file_error_get.c b/ext/libzip/zip_file_error_get.c new file mode 100644 index 0000000000..f20e011fc7 --- /dev/null +++ b/ext/libzip/zip_file_error_get.c @@ -0,0 +1,44 @@ +/* + zip_file_error_get.c -- get zip file error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN void +zip_file_error_get(struct zip_file *zf, int *zep, int *sep) +{ + _zip_error_get(&zf->error, zep, sep); +} diff --git a/ext/libzip/zip_file_get_offset.c b/ext/libzip/zip_file_get_offset.c new file mode 100644 index 0000000000..b96fd5e480 --- /dev/null +++ b/ext/libzip/zip_file_get_offset.c @@ -0,0 +1,74 @@ +/* + zip_file_get_offset.c -- get offset of file data in archive. + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include +#include +#include +#include +#include + +#include "zipint.h" + + + +/* _zip_file_get_offset(za, ze): + Returns the offset of the file data for entry ze. + + On error, fills in za->error and returns 0. +*/ + +unsigned int +_zip_file_get_offset(struct zip *za, int idx) +{ + struct zip_dirent de; + unsigned int offset; + + offset = za->cdir->entry[idx].offset; + + if (fseeko(za->zp, offset, SEEK_SET) != 0) { + _zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return 0; + } + + if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1, &za->error) != 0) + return 0; + + offset += LENTRYSIZE + de.filename_len + de.extrafield_len; + + _zip_dirent_finalize(&de); + + return offset; +} diff --git a/ext/libzip/zip_file_strerror.c b/ext/libzip/zip_file_strerror.c new file mode 100644 index 0000000000..9ba70f14ff --- /dev/null +++ b/ext/libzip/zip_file_strerror.c @@ -0,0 +1,44 @@ +/* + zip_file_sterror.c -- get string representation of zip file error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN const char * +zip_file_strerror(struct zip_file *zf) +{ + return _zip_error_strerror(&zf->error); +} diff --git a/ext/libzip/zip_filerange_crc.c b/ext/libzip/zip_filerange_crc.c new file mode 100644 index 0000000000..4d1ad56692 --- /dev/null +++ b/ext/libzip/zip_filerange_crc.c @@ -0,0 +1,71 @@ +/* + zip_filerange_crc.c -- compute CRC32 for a range of a file + Copyright (C) 2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include + +#include "zipint.h" + + + + +int +_zip_filerange_crc(FILE *fp, off_t start, off_t len, uLong *crcp, + struct zip_error *errp) +{ + Bytef buf[BUFSIZE]; + size_t n; + + *crcp = crc32(0L, Z_NULL, 0); + + if (fseeko(fp, start, SEEK_SET) != 0) { + _zip_error_set(errp, ZIP_ER_SEEK, errno); + return -1; + } + + while (len > 0) { + n = len > BUFSIZE ? BUFSIZE : len; + if ((n=fread(buf, 1, n, fp)) <= 0) { + _zip_error_set(errp, ZIP_ER_READ, errno); + return -1; + } + + *crcp = crc32(*crcp, buf, n); + + len-= n; + } + + return 0; +} diff --git a/ext/libzip/zip_fopen.c b/ext/libzip/zip_fopen.c new file mode 100644 index 0000000000..6e2f724127 --- /dev/null +++ b/ext/libzip/zip_fopen.c @@ -0,0 +1,49 @@ +/* + zip_fopen.c -- open file in zip archive for reading + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN struct zip_file * +zip_fopen(struct zip *za, const char *fname, int flags) +{ + int idx; + + if ((idx=zip_name_locate(za, fname, flags)) < 0) + return NULL; + + return zip_fopen_index(za, idx, flags); +} diff --git a/ext/libzip/zip_fopen_index.c b/ext/libzip/zip_fopen_index.c new file mode 100644 index 0000000000..a330d697d2 --- /dev/null +++ b/ext/libzip/zip_fopen_index.c @@ -0,0 +1,216 @@ +/* + zip_fopen_index.c -- open file in zip archive for reading by index + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include +#include + +#include "zipint.h" + +static struct zip_file *_zip_file_new(struct zip *za); + + + +ZIP_EXTERN struct zip_file * +zip_fopen_index(struct zip *za, int fileno, int flags) +{ + int len, ret; + int zfflags; + struct zip_file *zf; + + if ((fileno < 0) || (fileno >= za->nentry)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) == 0 + && ZIP_ENTRY_DATA_CHANGED(za->entry+fileno)) { + _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return NULL; + } + + if (fileno >= za->cdir->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + zfflags = 0; + switch (za->cdir->entry[fileno].comp_method) { + case ZIP_CM_STORE: + zfflags |= ZIP_ZF_CRC; + break; + + case ZIP_CM_DEFLATE: + if ((flags & ZIP_FL_COMPRESSED) == 0) + zfflags |= ZIP_ZF_CRC | ZIP_ZF_DECOMP; + break; + default: + if ((flags & ZIP_FL_COMPRESSED) == 0) { + _zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return NULL; + } + break; + } + + zf = _zip_file_new(za); + + zf->flags = zfflags; + /* zf->name = za->cdir->entry[fileno].filename; */ + zf->method = za->cdir->entry[fileno].comp_method; + zf->bytes_left = za->cdir->entry[fileno].uncomp_size; + zf->cbytes_left = za->cdir->entry[fileno].comp_size; + zf->crc_orig = za->cdir->entry[fileno].crc; + + if ((zf->fpos=_zip_file_get_offset(za, fileno)) == 0) { + zip_fclose(zf); + return NULL; + } + + if ((zf->flags & ZIP_ZF_DECOMP) == 0) + zf->bytes_left = zf->cbytes_left; + else { + if ((zf->buffer=(char *)malloc(BUFSIZE)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_fclose(zf); + return NULL; + } + + len = _zip_file_fillbuf(zf->buffer, BUFSIZE, zf); + if (len <= 0) { + _zip_error_copy(&za->error, &zf->error); + zip_fclose(zf); + return NULL; + } + + if ((zf->zstr = (z_stream *)malloc(sizeof(z_stream))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + zip_fclose(zf); + return NULL; + } + zf->zstr->zalloc = Z_NULL; + zf->zstr->zfree = Z_NULL; + zf->zstr->opaque = NULL; + zf->zstr->next_in = (Bytef *)zf->buffer; + zf->zstr->avail_in = len; + + /* negative value to tell zlib that there is no header */ + if ((ret=inflateInit2(zf->zstr, -MAX_WBITS)) != Z_OK) { + _zip_error_set(&za->error, ZIP_ER_ZLIB, ret); + zip_fclose(zf); + return NULL; + } + } + + return zf; +} + + + +int +_zip_file_fillbuf(void *buf, size_t buflen, struct zip_file *zf) +{ + int i, j; + + if (zf->error.zip_err != ZIP_ER_OK) + return -1; + + if ((zf->flags & ZIP_ZF_EOF) || zf->cbytes_left <= 0 || buflen <= 0) + return 0; + + if (fseeko(zf->za->zp, zf->fpos, SEEK_SET) < 0) { + _zip_error_set(&zf->error, ZIP_ER_SEEK, errno); + return -1; + } + if (buflen < zf->cbytes_left) + i = buflen; + else + i = zf->cbytes_left; + + j = fread(buf, 1, i, zf->za->zp); + if (j == 0) { + _zip_error_set(&zf->error, ZIP_ER_EOF, 0); + j = -1; + } + else if (j < 0) + _zip_error_set(&zf->error, ZIP_ER_READ, errno); + else { + zf->fpos += j; + zf->cbytes_left -= j; + } + + return j; +} + + + +static struct zip_file * +_zip_file_new(struct zip *za) +{ + struct zip_file *zf, **file; + int n; + + if ((zf=(struct zip_file *)malloc(sizeof(struct zip_file))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (za->nfile >= za->nfile_alloc-1) { + n = za->nfile_alloc + 10; + file = (struct zip_file **)realloc(za->file, + n*sizeof(struct zip_file *)); + if (file == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + free(zf); + return NULL; + } + za->nfile_alloc = n; + za->file = file; + } + + za->file[za->nfile++] = zf; + + zf->za = za; + _zip_error_init(&zf->error); + zf->flags = 0; + zf->crc = crc32(0L, Z_NULL, 0); + zf->crc_orig = 0; + zf->method = -1; + zf->bytes_left = zf->cbytes_left = 0; + zf->fpos = 0; + zf->buffer = NULL; + zf->zstr = NULL; + + return zf; +} diff --git a/ext/libzip/zip_fread.c b/ext/libzip/zip_fread.c new file mode 100644 index 0000000000..2a7fb42c78 --- /dev/null +++ b/ext/libzip/zip_fread.c @@ -0,0 +1,130 @@ +/* + zip_fread.c -- read from file + Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN ssize_t +zip_fread(struct zip_file *zf, void *outbuf, size_t toread) +{ + int ret; + size_t out_before, len; + int i; + + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + if ((zf->flags & ZIP_ZF_EOF) || (toread == 0)) + return 0; + + if (zf->bytes_left == 0) { + zf->flags |= ZIP_ZF_EOF; + if (zf->flags & ZIP_ZF_CRC) { + if (zf->crc != zf->crc_orig) { + _zip_error_set(&zf->error, ZIP_ER_CRC, 0); + return -1; + } + } + return 0; + } + + if ((zf->flags & ZIP_ZF_DECOMP) == 0) { + ret = _zip_file_fillbuf(outbuf, toread, zf); + if (ret > 0) { + if (zf->flags & ZIP_ZF_CRC) + zf->crc = crc32(zf->crc, (Bytef *)outbuf, ret); + zf->bytes_left -= ret; + } + return ret; + } + + zf->zstr->next_out = (Bytef *)outbuf; + zf->zstr->avail_out = toread; + out_before = zf->zstr->total_out; + + /* endless loop until something has been accomplished */ + for (;;) { + ret = inflate(zf->zstr, Z_SYNC_FLUSH); + + switch (ret) { + case Z_STREAM_END: + if (zf->zstr->total_out == out_before) { + if (zf->crc != zf->crc_orig) { + _zip_error_set(&zf->error, ZIP_ER_CRC, 0); + return -1; + } + else + return 0; + } + + /* fallthrough */ + + case Z_OK: + len = zf->zstr->total_out - out_before; + if (len >= zf->bytes_left || len >= toread) { + if (zf->flags & ZIP_ZF_CRC) + zf->crc = crc32(zf->crc, (Bytef *)outbuf, len); + zf->bytes_left -= len; + return len; + } + break; + + case Z_BUF_ERROR: + if (zf->zstr->avail_in == 0) { + i = _zip_file_fillbuf(zf->buffer, BUFSIZE, zf); + if (i == 0) { + _zip_error_set(&zf->error, ZIP_ER_INCONS, 0); + return -1; + } + else if (i < 0) + return -1; + zf->zstr->next_in = (Bytef *)zf->buffer; + zf->zstr->avail_in = i; + continue; + } + /* fallthrough */ + case Z_NEED_DICT: + case Z_DATA_ERROR: + case Z_STREAM_ERROR: + case Z_MEM_ERROR: + _zip_error_set(&zf->error, ZIP_ER_ZLIB, ret); + return -1; + } + } +} diff --git a/ext/libzip/zip_free.c b/ext/libzip/zip_free.c new file mode 100644 index 0000000000..76c3a9673f --- /dev/null +++ b/ext/libzip/zip_free.c @@ -0,0 +1,81 @@ +/* + zip_free.c -- free struct zip + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +/* _zip_free: + frees the space allocated to a zipfile struct, and closes the + corresponding file. */ + +void +_zip_free(struct zip *za) +{ + int i; + + if (za == NULL) + return; + + if (za->zn) + free(za->zn); + + if (za->zp) + fclose(za->zp); + + _zip_cdir_free(za->cdir); + + if (za->entry) { + for (i=0; inentry; i++) { + _zip_entry_free(za->entry+i); + } + free(za->entry); + } + + for (i=0; infile; i++) { + if (za->file[i]->error.zip_err == ZIP_ER_OK) { + _zip_error_set(&za->file[i]->error, ZIP_ER_ZIPCLOSED, 0); + za->file[i]->za = NULL; + } + } + + free(za->file); + + free(za); + + return; +} diff --git a/ext/libzip/zip_get_archive_comment.c b/ext/libzip/zip_get_archive_comment.c new file mode 100644 index 0000000000..669eb70216 --- /dev/null +++ b/ext/libzip/zip_get_archive_comment.c @@ -0,0 +1,60 @@ +/* + zip_get_archive_comment.c -- get archive comment + Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN const char * +zip_get_archive_comment(struct zip *za, int *lenp, int flags) +{ + if ((flags & ZIP_FL_UNCHANGED) + || (za->ch_comment_len == -1)) { + if (za->cdir) { + if (lenp != NULL) + *lenp = za->cdir->comment_len; + return za->cdir->comment; + } + else { + if (lenp != NULL) + *lenp = -1; + return NULL; + } + } + + if (lenp != NULL) + *lenp = za->ch_comment_len; + return za->ch_comment; +} diff --git a/ext/libzip/zip_get_archive_flag.c b/ext/libzip/zip_get_archive_flag.c new file mode 100644 index 0000000000..4733d92b58 --- /dev/null +++ b/ext/libzip/zip_get_archive_flag.c @@ -0,0 +1,48 @@ +/* + zip_get_archive_flag.c -- get archive global flag + Copyright (C) 2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_get_archive_flag(struct zip *za, int flag, int flags) +{ + int fl; + + fl = (flags & ZIP_FL_UNCHANGED) ? za->flags : za->ch_flags; + + return (fl & flag) ? 1 : 0; +} diff --git a/ext/libzip/zip_get_file_comment.c b/ext/libzip/zip_get_file_comment.c new file mode 100644 index 0000000000..adace72474 --- /dev/null +++ b/ext/libzip/zip_get_file_comment.c @@ -0,0 +1,58 @@ +/* + zip_get_file_comment.c -- get file comment + Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN const char * +zip_get_file_comment(struct zip *za, int idx, int *lenp, int flags) +{ + if (idx < 0 || idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) + || (za->entry[idx].ch_comment_len == -1)) { + if (lenp != NULL) + *lenp = za->cdir->entry[idx].comment_len; + return za->cdir->entry[idx].comment; + } + + if (lenp != NULL) + *lenp = za->entry[idx].ch_comment_len; + return za->entry[idx].ch_comment; +} diff --git a/ext/libzip/zip_get_name.c b/ext/libzip/zip_get_name.c new file mode 100644 index 0000000000..8f5050bd2e --- /dev/null +++ b/ext/libzip/zip_get_name.c @@ -0,0 +1,71 @@ +/* + zip_get_name.c -- get filename for a file in zip file + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN const char * +zip_get_name(struct zip *za, int idx, int flags) +{ + return _zip_get_name(za, idx, flags, &za->error); +} + + + +const char * +_zip_get_name(struct zip *za, int idx, int flags, struct zip_error *error) +{ + if (idx < 0 || idx >= za->nentry) { + _zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) == 0) { + if (za->entry[idx].state == ZIP_ST_DELETED) { + _zip_error_set(error, ZIP_ER_DELETED, 0); + return NULL; + } + if (za->entry[idx].ch_filename) + return za->entry[idx].ch_filename; + } + + if (za->cdir == NULL || idx >= za->cdir->nentry) { + _zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return za->cdir->entry[idx].filename; +} diff --git a/ext/libzip/zip_get_num_files.c b/ext/libzip/zip_get_num_files.c new file mode 100644 index 0000000000..1d9baa3d65 --- /dev/null +++ b/ext/libzip/zip_get_num_files.c @@ -0,0 +1,47 @@ +/* + zip_get_num_files.c -- get number of files in archive + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_get_num_files(struct zip *za) +{ + if (za == NULL) + return -1; + + return za->nentry; +} diff --git a/ext/libzip/zip_memdup.c b/ext/libzip/zip_memdup.c new file mode 100644 index 0000000000..641125ed2d --- /dev/null +++ b/ext/libzip/zip_memdup.c @@ -0,0 +1,55 @@ +/* + zip_memdup.c -- internal zip function, "strdup" with len + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#include "zipint.h" + + + +void * +_zip_memdup(const void *mem, size_t len, struct zip_error *error) +{ + void *ret; + + ret = malloc(len); + if (!ret) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + memcpy(ret, mem, len); + + return ret; +} diff --git a/ext/libzip/zip_name_locate.c b/ext/libzip/zip_name_locate.c new file mode 100644 index 0000000000..baa6141f67 --- /dev/null +++ b/ext/libzip/zip_name_locate.c @@ -0,0 +1,88 @@ +/* + zip_name_locate.c -- get index by name + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_name_locate(struct zip *za, const char *fname, int flags) +{ + return _zip_name_locate(za, fname, flags, &za->error); +} + + + +int +_zip_name_locate(struct zip *za, const char *fname, int flags, + struct zip_error *error) +{ + int (*cmp)(const char *, const char *); + const char *fn, *p; + int i, n; + + if (fname == NULL) { + _zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp; + + n = (flags & ZIP_FL_UNCHANGED) ? za->cdir->nentry : za->nentry; + for (i=0; icdir->entry[i].filename; + else + fn = _zip_get_name(za, i, flags, error); + + /* newly added (partially filled) entry */ + if (fn == NULL) + continue; + + if (flags & ZIP_FL_NODIR) { + p = strrchr(fn, '/'); + if (p) + fn = p+1; + } + + if (cmp(fname, fn) == 0) + return i; + } + + _zip_error_set(error, ZIP_ER_NOENT, 0); + return -1; +} diff --git a/ext/libzip/zip_new.c b/ext/libzip/zip_new.c new file mode 100644 index 0000000000..3e8ccee644 --- /dev/null +++ b/ext/libzip/zip_new.c @@ -0,0 +1,70 @@ +/* + zip_new.c -- create and init struct zip + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +/* _zip_new: + creates a new zipfile struct, and sets the contents to zero; returns + the new struct. */ + +struct zip * +_zip_new(struct zip_error *error) +{ + struct zip *za; + + za = (struct zip *)malloc(sizeof(struct zip)); + if (!za) { + _zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + za->zn = NULL; + za->zp = NULL; + _zip_error_init(&za->error); + za->cdir = NULL; + za->ch_comment = NULL; + za->ch_comment_len = -1; + za->nentry = za->nentry_alloc = 0; + za->entry = NULL; + za->nfile = za->nfile_alloc = 0; + za->file = NULL; + za->flags = za->ch_flags = 0; + + return za; +} diff --git a/ext/libzip/zip_open.c b/ext/libzip/zip_open.c new file mode 100644 index 0000000000..a65974df95 --- /dev/null +++ b/ext/libzip/zip_open.c @@ -0,0 +1,567 @@ +/* + zip_open.c -- open zip archive + Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include +#include +#include +#include +#include + +#include "zipint.h" + +static void set_error(int *, struct zip_error *, int); +static struct zip *_zip_allocate_new(const char *, int *); +static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *); +static void _zip_check_torrentzip(struct zip *); +static struct zip_cdir *_zip_find_central_dir(FILE *, int, int *, off_t); +static int _zip_file_exists(const char *, int, int *); +static int _zip_headercomp(struct zip_dirent *, int, + struct zip_dirent *, int); +static unsigned char *_zip_memmem(const unsigned char *, int, + const unsigned char *, int); +static struct zip_cdir *_zip_readcdir(FILE *, unsigned char *, unsigned char *, + int, int, struct zip_error *); + + + +ZIP_EXTERN struct zip * +zip_open(const char *fn, int flags, int *zep) +{ + FILE *fp; + struct zip *za; + struct zip_cdir *cdir; + int i; + off_t len; + + switch (_zip_file_exists(fn, flags, zep)) { + case -1: + return NULL; + case 0: + return _zip_allocate_new(fn, zep); + default: + break; + } + + if ((fp=fopen(fn, "rb")) == NULL) { + set_error(zep, NULL, ZIP_ER_OPEN); + return NULL; + } + + fseeko(fp, 0, SEEK_END); + len = ftello(fp); + + /* treat empty files as empty archives */ + if (len == 0) { + if ((za=_zip_allocate_new(fn, zep)) == NULL) + fclose(fp); + else + za->zp = fp; + return za; + } + + cdir = _zip_find_central_dir(fp, flags, zep, len); + if (cdir == NULL) { + fclose(fp); + return NULL; + } + + if ((za=_zip_allocate_new(fn, zep)) == NULL) { + _zip_cdir_free(cdir); + fclose(fp); + return NULL; + } + + za->cdir = cdir; + za->zp = fp; + + if ((za->entry=(struct zip_entry *)malloc(sizeof(*(za->entry)) + * cdir->nentry)) == NULL) { + set_error(zep, NULL, ZIP_ER_MEMORY); + _zip_free(za); + return NULL; + } + for (i=0; inentry; i++) + _zip_entry_new(za); + + _zip_check_torrentzip(za); + za->ch_flags = za->flags; + + return za; +} + + + +static void +set_error(int *zep, struct zip_error *err, int ze) +{ + int se; + + if (err) { + _zip_error_get(err, &ze, &se); + if (zip_error_get_sys_type(ze) == ZIP_ET_SYS) + errno = se; + } + + if (zep) + *zep = ze; +} + + + +/* _zip_readcdir: + tries to find a valid end-of-central-directory at the beginning of + buf, and then the corresponding central directory entries. + Returns a struct zip_cdir which contains the central directory + entries, or NULL if unsuccessful. */ + +static struct zip_cdir * +_zip_readcdir(FILE *fp, unsigned char *buf, unsigned char *eocd, int buflen, + int flags, struct zip_error *error) +{ + struct zip_cdir *cd; + unsigned char *cdp, **bufp; + int i, comlen, nentry; + unsigned int left; + + comlen = buf + buflen - eocd - EOCDLEN; + if (comlen < 0) { + /* not enough bytes left for comment */ + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; + } + + /* check for end-of-central-dir magic */ + if (memcmp(eocd, EOCD_MAGIC, 4) != 0) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; + } + + if (memcmp(eocd+4, "\0\0\0\0", 4) != 0) { + _zip_error_set(error, ZIP_ER_MULTIDISK, 0); + return NULL; + } + + cdp = eocd + 8; + /* number of cdir-entries on this disk */ + i = _zip_read2(&cdp); + /* number of cdir-entries */ + nentry = _zip_read2(&cdp); + + if ((cd=_zip_cdir_new(nentry, error)) == NULL) + return NULL; + + cd->size = _zip_read4(&cdp); + cd->offset = _zip_read4(&cdp); + cd->comment = NULL; + cd->comment_len = _zip_read2(&cdp); + + if ((comlen < cd->comment_len) || (cd->nentry != i)) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + free(cd); + return NULL; + } + if ((flags & ZIP_CHECKCONS) && comlen != cd->comment_len) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + free(cd); + return NULL; + } + + if (cd->comment_len) { + if ((cd->comment=(char *)_zip_memdup(eocd+EOCDLEN, + cd->comment_len, error)) + == NULL) { + free(cd); + return NULL; + } + } + + if (cd->size < (unsigned int)(eocd-buf)) { + /* if buffer already read in, use it */ + cdp = eocd - cd->size; + bufp = &cdp; + } + else { + /* go to start of cdir and read it entry by entry */ + bufp = NULL; + clearerr(fp); + fseeko(fp, cd->offset, SEEK_SET); + /* possible consistency check: cd->offset = + len-(cd->size+cd->comment_len+EOCDLEN) ? */ + if (ferror(fp) || ((unsigned long)ftello(fp) != cd->offset)) { + /* seek error or offset of cdir wrong */ + if (ferror(fp)) + _zip_error_set(error, ZIP_ER_SEEK, errno); + else + _zip_error_set(error, ZIP_ER_NOZIP, 0); + free(cd); + return NULL; + } + } + + left = cd->size; + i=0; + do { + if (i == cd->nentry && left > 0) { + /* Infozip extension for more than 64k entries: + nentries wraps around, size indicates correct EOCD */ + _zip_cdir_grow(cd, cd->nentry+0x10000, error); + } + + if ((_zip_dirent_read(cd->entry+i, fp, bufp, &left, 0, error)) < 0) { + cd->nentry = i; + _zip_cdir_free(cd); + return NULL; + } + i++; + + } while (inentry); + + return cd; +} + + + +/* _zip_checkcons: + Checks the consistency of the central directory by comparing central + directory entries with local headers and checking for plausible + file and header offsets. Returns -1 if not plausible, else the + difference between the lowest and the highest fileposition reached */ + +static int +_zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error) +{ + int i; + unsigned int min, max, j; + struct zip_dirent temp; + + if (cd->nentry) { + max = cd->entry[0].offset; + min = cd->entry[0].offset; + } + else + min = max = 0; + + for (i=0; inentry; i++) { + if (cd->entry[i].offset < min) + min = cd->entry[i].offset; + if (min > cd->offset) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + j = cd->entry[i].offset + cd->entry[i].comp_size + + cd->entry[i].filename_len + LENTRYSIZE; + if (j > max) + max = j; + if (max > cd->offset) { + _zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + if (fseeko(fp, cd->entry[i].offset, SEEK_SET) != 0) { + _zip_error_set(error, ZIP_ER_SEEK, 0); + return -1; + } + + if (_zip_dirent_read(&temp, fp, NULL, NULL, 1, error) == -1) + return -1; + + if (_zip_headercomp(cd->entry+i, 0, &temp, 1) != 0) { + _zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_dirent_finalize(&temp); + return -1; + } + _zip_dirent_finalize(&temp); + } + + return max - min; +} + + + +/* _zip_check_torrentzip: + check wether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */ + +static void +_zip_check_torrentzip(struct zip *za) +{ + uLong crc_got, crc_should; + char buf[8+1]; + char *end; + + if (za->zp == NULL || za->cdir == NULL) + return; + + if (za->cdir->comment_len != TORRENT_SIG_LEN+8 + || strncmp(za->cdir->comment, TORRENT_SIG, TORRENT_SIG_LEN) != 0) + return; + + memcpy(buf, za->cdir->comment+TORRENT_SIG_LEN, 8); + buf[8] = '\0'; + errno = 0; + crc_should = strtoul(buf, &end, 16); + if ((crc_should == UINT_MAX && errno != 0) || (end && *end)) + return; + + if (_zip_filerange_crc(za->zp, za->cdir->offset, za->cdir->size, + &crc_got, NULL) < 0) + return; + + if (crc_got == crc_should) + za->flags |= ZIP_AFL_TORRENT; +} + + + + +/* _zip_headercomp: + compares two headers h1 and h2; if they are local headers, set + local1p or local2p respectively to 1, else 0. Return 0 if they + are identical, -1 if not. */ + +static int +_zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2, + int local2p) +{ + if ((h1->version_needed != h2->version_needed) +#if 0 + /* some zip-files have different values in local + and global headers for the bitflags */ + || (h1->bitflags != h2->bitflags) +#endif + || (h1->comp_method != h2->comp_method) + || (h1->last_mod != h2->last_mod) + || (h1->filename_len != h2->filename_len) + || !h1->filename || !h2->filename + || strcmp(h1->filename, h2->filename)) + return -1; + + /* check that CRC and sizes are zero if data descriptor is used */ + if ((h1->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) && local1p + && (h1->crc != 0 + || h1->comp_size != 0 + || h1->uncomp_size != 0)) + return -1; + if ((h2->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) && local2p + && (h2->crc != 0 + || h2->comp_size != 0 + || h2->uncomp_size != 0)) + return -1; + + /* check that CRC and sizes are equal if no data descriptor is used */ + if (((h1->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local1p == 0) + && ((h2->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local2p == 0)) { + if ((h1->crc != h2->crc) + || (h1->comp_size != h2->comp_size) + || (h1->uncomp_size != h2->uncomp_size)) + return -1; + } + + if ((local1p == local2p) + && ((h1->extrafield_len != h2->extrafield_len) + || (h1->extrafield_len && h2->extrafield + && memcmp(h1->extrafield, h2->extrafield, + h1->extrafield_len)))) + return -1; + + /* if either is local, nothing more to check */ + if (local1p || local2p) + return 0; + + if ((h1->version_madeby != h2->version_madeby) + || (h1->disk_number != h2->disk_number) + || (h1->int_attrib != h2->int_attrib) + || (h1->ext_attrib != h2->ext_attrib) + || (h1->offset != h2->offset) + || (h1->comment_len != h2->comment_len) + || (h1->comment_len && h2->comment + && memcmp(h1->comment, h2->comment, h1->comment_len))) + return -1; + + return 0; +} + + + +static struct zip * +_zip_allocate_new(const char *fn, int *zep) +{ + struct zip *za; + struct zip_error error; + + if ((za=_zip_new(&error)) == NULL) { + set_error(zep, &error, 0); + return NULL; + } + + za->zn = strdup(fn); + if (!za->zn) { + _zip_free(za); + set_error(zep, NULL, ZIP_ER_MEMORY); + return NULL; + } + return za; +} + + + +static int +_zip_file_exists(const char *fn, int flags, int *zep) +{ + struct stat st; + + if (fn == NULL) { + set_error(zep, NULL, ZIP_ER_INVAL); + return -1; + } + + if (stat(fn, &st) != 0) { + if (flags & ZIP_CREATE) + return 0; + else { + set_error(zep, NULL, ZIP_ER_OPEN); + return -1; + } + } + else if ((flags & ZIP_EXCL)) { + set_error(zep, NULL, ZIP_ER_EXISTS); + return -1; + } + /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, + just like open() */ + + return 1; +} + + + +static struct zip_cdir * +_zip_find_central_dir(FILE *fp, int flags, int *zep, off_t len) +{ + struct zip_cdir *cdir, *cdirnew; + unsigned char *buf, *match; + int a, best, buflen, i; + struct zip_error zerr; + + i = fseeko(fp, -(len < CDBUFSIZE ? len : CDBUFSIZE), SEEK_END); + if (i == -1 && errno != EFBIG) { + /* seek before start of file on my machine */ + set_error(zep, NULL, ZIP_ER_SEEK); + return NULL; + } + + /* 64k is too much for stack */ + if ((buf=(unsigned char *)malloc(CDBUFSIZE)) == NULL) { + set_error(zep, NULL, ZIP_ER_MEMORY); + return NULL; + } + + clearerr(fp); + buflen = fread(buf, 1, CDBUFSIZE, fp); + + if (ferror(fp)) { + set_error(zep, NULL, ZIP_ER_READ); + free(buf); + return NULL; + } + + best = -1; + cdir = NULL; + match = buf; + _zip_error_set(&zerr, ZIP_ER_NOZIP, 0); + + while ((match=_zip_memmem(match, buflen-(match-buf)-18, + (const unsigned char *)EOCD_MAGIC, 4))!=NULL) { + /* found match -- check, if good */ + /* to avoid finding the same match all over again */ + match++; + if ((cdirnew=_zip_readcdir(fp, buf, match-1, buflen, flags, + &zerr)) == NULL) + continue; + + if (cdir) { + if (best <= 0) + best = _zip_checkcons(fp, cdir, &zerr); + a = _zip_checkcons(fp, cdirnew, &zerr); + if (best < a) { + _zip_cdir_free(cdir); + cdir = cdirnew; + best = a; + } + else + _zip_cdir_free(cdirnew); + } + else { + cdir = cdirnew; + if (flags & ZIP_CHECKCONS) + best = _zip_checkcons(fp, cdir, &zerr); + else + best = 0; + } + cdirnew = NULL; + } + + free(buf); + + if (best < 0) { + set_error(zep, &zerr, 0); + _zip_cdir_free(cdir); + return NULL; + } + + return cdir; +} + + + +static unsigned char * +_zip_memmem(const unsigned char *big, int biglen, const unsigned char *little, + int littlelen) +{ + const unsigned char *p; + + if ((biglen < littlelen) || (littlelen == 0)) + return NULL; + p = big-1; + while ((p=(const unsigned char *) + memchr(p+1, little[0], (size_t)(big-(p+1)+biglen-littlelen+1))) + != NULL) { + if (memcmp(p+1, little+1, littlelen-1)==0) + return (unsigned char *)p; + } + + return NULL; +} diff --git a/ext/libzip/zip_rename.c b/ext/libzip/zip_rename.c new file mode 100644 index 0000000000..1d056bbe37 --- /dev/null +++ b/ext/libzip/zip_rename.c @@ -0,0 +1,65 @@ +/* + zip_rename.c -- rename file in zip archive + Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_rename(struct zip *za, int idx, const char *name) +{ + const char *old_name; + int old_is_dir, new_is_dir; + + if (idx >= za->nentry || idx < 0 || name[0] == '\0') { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((old_name=zip_get_name(za, idx, 0)) == NULL) + return -1; + + new_is_dir = (name[strlen(name)-1] == '/'); + old_is_dir = (old_name[strlen(old_name)-1] == '/'); + + if (new_is_dir != old_is_dir) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_set_name(za, idx, name); +} diff --git a/ext/libzip/zip_replace.c b/ext/libzip/zip_replace.c new file mode 100644 index 0000000000..6cdb80c503 --- /dev/null +++ b/ext/libzip/zip_replace.c @@ -0,0 +1,78 @@ +/* + zip_replace.c -- replace file via callback function + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_replace(struct zip *za, int idx, struct zip_source *source) +{ + if (idx < 0 || idx >= za->nentry || source == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_replace(za, idx, NULL, source) == -1) + return -1; + + return 0; +} + + + + +int +_zip_replace(struct zip *za, int idx, const char *name, + struct zip_source *source) +{ + if (idx == -1) { + if (_zip_entry_new(za) == NULL) + return -1; + + idx = za->nentry - 1; + } + + _zip_unchange_data(za->entry+idx); + + if (name && _zip_set_name(za, idx, name) != 0) + return -1; + + za->entry[idx].state = ((za->cdir == NULL || idx >= za->cdir->nentry) + ? ZIP_ST_ADDED : ZIP_ST_REPLACED); + za->entry[idx].source = source; + + return idx; +} diff --git a/ext/libzip/zip_set_archive_comment.c b/ext/libzip/zip_set_archive_comment.c new file mode 100644 index 0000000000..343fa5491c --- /dev/null +++ b/ext/libzip/zip_set_archive_comment.c @@ -0,0 +1,65 @@ +/* + zip_set_archive_comment.c -- set archive comment + Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_set_archive_comment(struct zip *za, const char *comment, int len) +{ + char *tmpcom; + + if (len < 0 || len > MAXCOMLEN + || (len > 0 && comment == NULL)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (len > 0) { + if ((tmpcom=(char *)_zip_memdup(comment, len, &za->error)) == NULL) + return -1; + } + else + tmpcom = NULL; + + free(za->ch_comment); + za->ch_comment = tmpcom; + za->ch_comment_len = len; + + return 0; +} diff --git a/ext/libzip/zip_set_archive_flag.c b/ext/libzip/zip_set_archive_flag.c new file mode 100644 index 0000000000..720e1f3508 --- /dev/null +++ b/ext/libzip/zip_set_archive_flag.c @@ -0,0 +1,49 @@ +/* + zip_get_archive_flag.c -- set archive global flag + Copyright (C) 2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_set_archive_flag(struct zip *za, int flag, int value) +{ + if (value) + za->ch_flags |= flag; + else + za->ch_flags &= ~flag; + + return 0; +} diff --git a/ext/libzip/zip_set_file_comment.c b/ext/libzip/zip_set_file_comment.c new file mode 100644 index 0000000000..bc1938e1df --- /dev/null +++ b/ext/libzip/zip_set_file_comment.c @@ -0,0 +1,66 @@ +/* + zip_set_file_comment.c -- set comment for file in archive + Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_set_file_comment(struct zip *za, int idx, const char *comment, int len) +{ + char *tmpcom; + + if (idx < 0 || idx >= za->nentry + || len < 0 || len > MAXCOMLEN + || (len > 0 && comment == NULL)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (len > 0) { + if ((tmpcom=(char *)_zip_memdup(comment, len, &za->error)) == NULL) + return -1; + } + else + tmpcom = NULL; + + free(za->entry[idx].ch_comment); + za->entry[idx].ch_comment = tmpcom; + za->entry[idx].ch_comment_len = len; + + return 0; +} diff --git a/ext/libzip/zip_set_name.c b/ext/libzip/zip_set_name.c new file mode 100644 index 0000000000..5c7da3d7c5 --- /dev/null +++ b/ext/libzip/zip_set_name.c @@ -0,0 +1,75 @@ +/* + zip_set_name.c -- rename helper function + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include + +#include "zipint.h" + + + +int +_zip_set_name(struct zip *za, int idx, const char *name) +{ + char *s; + int i; + + if (idx < 0 || idx >= za->nentry || name == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((i=_zip_name_locate(za, name, 0, NULL)) != -1 && i != idx) { + _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; + } + + /* no effective name change */ + if (i == idx) + return 0; + + if ((s=strdup(name)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + if (za->entry[idx].state == ZIP_ST_UNCHANGED) + za->entry[idx].state = ZIP_ST_RENAMED; + + free(za->entry[idx].ch_filename); + za->entry[idx].ch_filename = s; + + return 0; +} diff --git a/ext/libzip/zip_source_buffer.c b/ext/libzip/zip_source_buffer.c new file mode 100644 index 0000000000..1e9121c560 --- /dev/null +++ b/ext/libzip/zip_source_buffer.c @@ -0,0 +1,157 @@ +/* + zip_source_buffer.c -- create zip data source from buffer + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include + +#include "zipint.h" + +struct read_data { + const char *buf, *data, *end; + time_t mtime; + int freep; +}; + +static ssize_t read_data(void *state, void *data, size_t len, + enum zip_source_cmd cmd); + + + +ZIP_EXTERN struct zip_source * +zip_source_buffer(struct zip *za, const void *data, off_t len, int freep) +{ + struct read_data *f; + struct zip_source *zs; + + if (za == NULL) + return NULL; + + if (len < 0 || (data == NULL && len > 0)) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((f=(struct read_data *)malloc(sizeof(*f))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + f->data = (const char *)data; + f->end = ((const char *)data)+len; + f->freep = freep; + f->mtime = time(NULL); + + if ((zs=zip_source_function(za, read_data, f)) == NULL) { + free(f); + return NULL; + } + + return zs; +} + + + +static ssize_t +read_data(void *state, void *data, size_t len, enum zip_source_cmd cmd) +{ + struct read_data *z; + char *buf; + size_t n; + + z = (struct read_data *)state; + buf = (char *)data; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + z->buf = z->data; + return 0; + + case ZIP_SOURCE_READ: + n = z->end - z->buf; + if (n > len) + n = len; + + if (n) { + memcpy(buf, z->buf, n); + z->buf += n; + } + + return n; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; + + if (len < sizeof(*st)) + return -1; + + st = (struct zip_stat *)data; + + zip_stat_init(st); + st->mtime = z->mtime; + st->size = z->end - z->data; + + return sizeof(*st); + } + + case ZIP_SOURCE_ERROR: + { + int *e; + + if (len < sizeof(int)*2) + return -1; + + e = (int *)data; + e[0] = e[1] = 0; + } + return sizeof(int)*2; + + case ZIP_SOURCE_FREE: + if (z->freep) { + free((void *)z->data); + z->data = NULL; + } + free(z); + return 0; + + default: + ; + } + + return -1; +} diff --git a/ext/libzip/zip_source_file.c b/ext/libzip/zip_source_file.c new file mode 100644 index 0000000000..eb1129a275 --- /dev/null +++ b/ext/libzip/zip_source_file.c @@ -0,0 +1,55 @@ +/* + zip_source_file.c -- create data source from file + Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include + +#include "zipint.h" + + + +ZIP_EXTERN struct zip_source * +zip_source_file(struct zip *za, const char *fname, off_t start, off_t len) +{ + if (za == NULL) + return NULL; + + if (fname == NULL || start < 0 || len < -1) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + return _zip_source_file_or_p(za, fname, NULL, start, len); +} diff --git a/ext/libzip/zip_source_filep.c b/ext/libzip/zip_source_filep.c new file mode 100644 index 0000000000..5373934102 --- /dev/null +++ b/ext/libzip/zip_source_filep.c @@ -0,0 +1,216 @@ +/* + zip_source_filep.c -- create data source from FILE * + Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include +#include +#include +#include + +#include "zipint.h" + +struct read_file { + char *fname; /* name of file to copy from */ + FILE *f; /* file to copy from */ + off_t off; /* start offset of */ + off_t len; /* lengt of data to copy */ + off_t remain; /* bytes remaining to be copied */ + int e[2]; /* error codes */ +}; + +static ssize_t read_file(void *state, void *data, size_t len, + enum zip_source_cmd cmd); + + + +ZIP_EXTERN struct zip_source * +zip_source_filep(struct zip *za, FILE *file, off_t start, off_t len) +{ + if (za == NULL) + return NULL; + + if (file == NULL || start < 0 || len < -1) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + return _zip_source_file_or_p(za, NULL, file, start, len); +} + + + +struct zip_source * +_zip_source_file_or_p(struct zip *za, const char *fname, FILE *file, + off_t start, off_t len) +{ + struct read_file *f; + struct zip_source *zs; + + if (file == NULL && fname == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((f=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + f->fname = NULL; + if (fname) { + if ((f->fname=strdup(fname)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + free(f); + return NULL; + } + } + f->f = file; + f->off = start; + f->len = (len ? len : -1); + + if ((zs=zip_source_function(za, read_file, f)) == NULL) { + free(f); + return NULL; + } + + return zs; +} + + + +static ssize_t +read_file(void *state, void *data, size_t len, enum zip_source_cmd cmd) +{ + struct read_file *z; + char *buf; + int i, n; + + z = (struct read_file *)state; + buf = (char *)data; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + if (z->fname) { + if ((z->f=fopen(z->fname, "rb")) == NULL) { + z->e[0] = ZIP_ER_OPEN; + z->e[1] = errno; + return -1; + } + } + + if (fseeko(z->f, z->off, SEEK_SET) < 0) { + z->e[0] = ZIP_ER_SEEK; + z->e[1] = errno; + return -1; + } + z->remain = z->len; + return 0; + + case ZIP_SOURCE_READ: + if (z->remain != -1) + n = len > z->remain ? z->remain : len; + else + n = len; + + if ((i=fread(buf, 1, n, z->f)) < 0) { + z->e[0] = ZIP_ER_READ; + z->e[1] = errno; + return -1; + } + + if (z->remain != -1) + z->remain -= i; + + return i; + + case ZIP_SOURCE_CLOSE: + if (z->fname) { + fclose(z->f); + z->f = NULL; + } + return 0; + + case ZIP_SOURCE_STAT: + { + struct zip_stat *st; + struct stat fst; + int err; + + if (len < sizeof(*st)) + return -1; + + if (z->f) + err = fstat(fileno(z->f), &fst); + else + err = stat(z->fname, &fst); + + if (err != 0) { + z->e[0] = ZIP_ER_READ; /* best match */ + z->e[1] = errno; + return -1; + } + + st = (struct zip_stat *)data; + + zip_stat_init(st); + st->mtime = fst.st_mtime; + if (z->len != -1) + st->size = z->len; + else if ((fst.st_mode&S_IFMT) == S_IFREG) + st->size = fst.st_size; + + return sizeof(*st); + } + + case ZIP_SOURCE_ERROR: + if (len < sizeof(int)*2) + return -1; + + memcpy(data, z->e, sizeof(int)*2); + return sizeof(int)*2; + + case ZIP_SOURCE_FREE: + free(z->fname); + if (z->f) + fclose(z->f); + free(z); + return 0; + + default: + ; + } + + return -1; +} diff --git a/ext/libzip/zip_source_free.c b/ext/libzip/zip_source_free.c new file mode 100644 index 0000000000..7a1632fbf9 --- /dev/null +++ b/ext/libzip/zip_source_free.c @@ -0,0 +1,51 @@ +/* + zip_source_free.c -- free zip data source + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +ZIP_EXTERN void +zip_source_free(struct zip_source *source) +{ + if (source == NULL) + return; + + (void)source->f(source->ud, NULL, 0, ZIP_SOURCE_FREE); + + free(source); +} diff --git a/ext/libzip/zip_source_function.c b/ext/libzip/zip_source_function.c new file mode 100644 index 0000000000..91b183cb6f --- /dev/null +++ b/ext/libzip/zip_source_function.c @@ -0,0 +1,59 @@ +/* + zip_source_function.c -- create zip data source from callback function + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +ZIP_EXTERN struct zip_source * +zip_source_function(struct zip *za, zip_source_callback zcb, void *ud) +{ + struct zip_source *zs; + + if (za == NULL) + return NULL; + + if ((zs=(struct zip_source *)malloc(sizeof(*zs))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + zs->f = zcb; + zs->ud = ud; + + return zs; +} diff --git a/ext/libzip/zip_source_zip.c b/ext/libzip/zip_source_zip.c new file mode 100644 index 0000000000..3eef552a23 --- /dev/null +++ b/ext/libzip/zip_source_zip.c @@ -0,0 +1,188 @@ +/* + zip_source_zip.c -- create data source from zip file + Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include +#include + +#include "zipint.h" + +struct read_zip { + struct zip_file *zf; + struct zip_stat st; + off_t off, len; +}; + +static ssize_t read_zip(void *st, void *data, size_t len, + enum zip_source_cmd cmd); + + + +ZIP_EXTERN struct zip_source * +zip_source_zip(struct zip *za, struct zip *srcza, int srcidx, int flags, + off_t start, off_t len) +{ + struct zip_error error; + struct zip_source *zs; + struct read_zip *p; + + /* XXX: ZIP_FL_RECOMPRESS */ + + if (za == NULL) + return NULL; + + if (srcza == NULL || start < 0 || len < -1 || srcidx < 0 || srcidx >= srcza->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) == 0 + && ZIP_ENTRY_DATA_CHANGED(srcza->entry+srcidx)) { + _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return NULL; + } + + if (len == 0) + len = -1; + + if (start == 0 && len == -1 && (flags & ZIP_FL_RECOMPRESS) == 0) + flags |= ZIP_FL_COMPRESSED; + else + flags &= ~ZIP_FL_COMPRESSED; + + if ((p=(struct read_zip *)malloc(sizeof(*p))) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + _zip_error_copy(&error, &srcza->error); + + if (zip_stat_index(srcza, srcidx, flags, &p->st) < 0 + || (p->zf=zip_fopen_index(srcza, srcidx, flags)) == NULL) { + free(p); + _zip_error_copy(&za->error, &srcza->error); + _zip_error_copy(&srcza->error, &error); + + return NULL; + } + p->off = start; + p->len = len; + + if ((flags & ZIP_FL_COMPRESSED) == 0) { + p->st.size = p->st.comp_size = len; + p->st.comp_method = ZIP_CM_STORE; + p->st.crc = 0; + } + + if ((zs=zip_source_function(za, read_zip, p)) == NULL) { + free(p); + return NULL; + } + + return zs; +} + + + +static ssize_t +read_zip(void *state, void *data, size_t len, enum zip_source_cmd cmd) +{ + struct read_zip *z; + char b[8192], *buf; + int i, n; + + z = (struct read_zip *)state; + buf = (char *)data; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + for (n=0; noff; n+= i) { + i = (z->off-n > sizeof(b) ? sizeof(b) : z->off-n); + if ((i=zip_fread(z->zf, b, i)) < 0) { + zip_fclose(z->zf); + z->zf = NULL; + return -1; + } + } + return 0; + + case ZIP_SOURCE_READ: + if (z->len != -1) + n = len > z->len ? z->len : len; + else + n = len; + + + if ((i=zip_fread(z->zf, buf, n)) < 0) + return -1; + + if (z->len != -1) + z->len -= i; + + return i; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + if (len < sizeof(z->st)) + return -1; + len = sizeof(z->st); + + memcpy(data, &z->st, len); + return len; + + case ZIP_SOURCE_ERROR: + { + int *e; + + if (len < sizeof(int)*2) + return -1; + + e = (int *)data; + zip_file_error_get(z->zf, e, e+1); + } + return sizeof(int)*2; + + case ZIP_SOURCE_FREE: + zip_fclose(z->zf); + free(z); + return 0; + + default: + ; + } + + return -1; +} diff --git a/ext/libzip/zip_stat.c b/ext/libzip/zip_stat.c new file mode 100644 index 0000000000..df1c0b50b9 --- /dev/null +++ b/ext/libzip/zip_stat.c @@ -0,0 +1,49 @@ +/* + zip_stat.c -- get information about file by name + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_stat(struct zip *za, const char *fname, int flags, struct zip_stat *st) +{ + int idx; + + if ((idx=zip_name_locate(za, fname, flags)) < 0) + return -1; + + return zip_stat_index(za, idx, flags, st); +} diff --git a/ext/libzip/zip_stat_index.c b/ext/libzip/zip_stat_index.c new file mode 100644 index 0000000000..60558e432b --- /dev/null +++ b/ext/libzip/zip_stat_index.c @@ -0,0 +1,90 @@ +/* + zip_stat_index.c -- get information about file by index + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_stat_index(struct zip *za, int index, int flags, struct zip_stat *st) +{ + const char *name; + + if (index < 0 || index >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((name=zip_get_name(za, index, flags)) == NULL) + return -1; + + + if ((flags & ZIP_FL_UNCHANGED) == 0 + && ZIP_ENTRY_DATA_CHANGED(za->entry+index)) { + if (za->entry[index].source->f(za->entry[index].source->ud, + st, sizeof(*st), ZIP_SOURCE_STAT) < 0) { + _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return -1; + } + } + else { + if (za->cdir == NULL || index >= za->cdir->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + st->crc = za->cdir->entry[index].crc; + st->size = za->cdir->entry[index].uncomp_size; + st->mtime = za->cdir->entry[index].last_mod; + st->comp_size = za->cdir->entry[index].comp_size; + st->comp_method = za->cdir->entry[index].comp_method; + if (za->cdir->entry[index].bitflags & ZIP_GPBF_ENCRYPTED) { + if (za->cdir->entry[index].bitflags & ZIP_GPBF_STRONG_ENCRYPTION) { + /* XXX */ + st->encryption_method = ZIP_EM_UNKNOWN; + } + else + st->encryption_method = ZIP_EM_TRAD_PKWARE; + } + else + st->encryption_method = ZIP_EM_NONE; + /* st->bitflags = za->cdir->entry[index].bitflags; */ + } + + st->index = index; + st->name = name; + + return 0; +} diff --git a/ext/libzip/zip_stat_init.c b/ext/libzip/zip_stat_init.c new file mode 100644 index 0000000000..133ad304aa --- /dev/null +++ b/ext/libzip/zip_stat_init.c @@ -0,0 +1,51 @@ +/* + zip_stat_init.c -- initialize struct zip_stat. + Copyright (C) 2006-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN void +zip_stat_init(struct zip_stat *st) +{ + st->name = NULL; + st->index = -1; + st->crc = 0; + st->mtime = (time_t)-1; + st->size = -1; + st->comp_size = -1; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; +} diff --git a/ext/libzip/zip_strerror.c b/ext/libzip/zip_strerror.c new file mode 100644 index 0000000000..9ebee144f9 --- /dev/null +++ b/ext/libzip/zip_strerror.c @@ -0,0 +1,44 @@ +/* + zip_sterror.c -- get string representation of zip error + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include "zipint.h" + + + +ZIP_EXTERN const char * +zip_strerror(struct zip *za) +{ + return _zip_error_strerror(&za->error); +} diff --git a/ext/libzip/zip_unchange.c b/ext/libzip/zip_unchange.c new file mode 100644 index 0000000000..ed0d4de65b --- /dev/null +++ b/ext/libzip/zip_unchange.c @@ -0,0 +1,82 @@ +/* + zip_unchange.c -- undo changes to file in zip archive + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_unchange(struct zip *za, int idx) +{ + return _zip_unchange(za, idx, 0); +} + + + +int +_zip_unchange(struct zip *za, int idx, int allow_duplicates) +{ + int i; + + if (idx < 0 || idx >= za->nentry) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (za->entry[idx].ch_filename) { + if (!allow_duplicates) { + i = _zip_name_locate(za, + _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL), + 0, NULL); + if (i != -1 && i != idx) { + _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; + } + } + + free(za->entry[idx].ch_filename); + za->entry[idx].ch_filename = NULL; + } + + free(za->entry[idx].ch_comment); + za->entry[idx].ch_comment = NULL; + za->entry[idx].ch_comment_len = -1; + + _zip_unchange_data(za->entry+idx); + + return 0; +} diff --git a/ext/libzip/zip_unchange_all.c b/ext/libzip/zip_unchange_all.c new file mode 100644 index 0000000000..54a7a0d2e1 --- /dev/null +++ b/ext/libzip/zip_unchange_all.c @@ -0,0 +1,54 @@ +/* + zip_unchange.c -- undo changes to all files in zip archive + Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_unchange_all(struct zip *za) +{ + int ret, i; + + ret = 0; + for (i=0; inentry; i++) + ret |= _zip_unchange(za, i, 1); + + ret |= zip_unchange_archive(za); + + return ret; +} diff --git a/ext/libzip/zip_unchange_archive.c b/ext/libzip/zip_unchange_archive.c new file mode 100644 index 0000000000..8f9c024c36 --- /dev/null +++ b/ext/libzip/zip_unchange_archive.c @@ -0,0 +1,52 @@ +/* + zip_unchange_archive.c -- undo global changes to ZIP archive + Copyright (C) 2006-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + + + +ZIP_EXTERN int +zip_unchange_archive(struct zip *za) +{ + free(za->ch_comment); + za->ch_comment = NULL; + za->ch_comment_len = -1; + + za->ch_flags = za->flags; + + return 0; +} diff --git a/ext/libzip/zip_unchange_data.c b/ext/libzip/zip_unchange_data.c new file mode 100644 index 0000000000..6fe89f4fb2 --- /dev/null +++ b/ext/libzip/zip_unchange_data.c @@ -0,0 +1,53 @@ +/* + $NiH: zip_unchange_data.c,v 1.14 2004/11/30 23:02:47 wiz Exp $ + + zip_unchange_data.c -- undo helper function + Copyright (C) 1999, 2004 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include + +#include "zipint.h" + +void +_zip_unchange_data(struct zip_entry *ze) +{ + if (ze->source) { + (void)ze->source->f(ze->source->ud, NULL, 0, ZIP_SOURCE_FREE); + free(ze->source); + ze->source = NULL; + } + + ze->state = ze->ch_filename ? ZIP_ST_RENAMED : ZIP_ST_UNCHANGED; +} + diff --git a/ext/libzip/zipint.h b/ext/libzip/zipint.h new file mode 100644 index 0000000000..f5a81b1934 --- /dev/null +++ b/ext/libzip/zipint.h @@ -0,0 +1,264 @@ +#ifndef _HAD_ZIPINT_H +#define _HAD_ZIPINT_H + +/* + zipint.h -- internal declarations. + Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#ifdef _MSC_VER +#define ZIP_EXTERN __declspec(dllimport) +#endif + +#include "zip.h" +#include "config.h" + +#ifndef HAVE_MKSTEMP +int _zip_mkstemp(char *); +#define mkstemp _zip_mkstemp +#endif + +#ifdef HAVE_MOVEFILEEXA +#include +#define _zip_rename(s, t) \ + (!MoveFileExA((s), (t), \ + MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING)) +#else +#define _zip_rename rename +#endif + +#ifndef HAVE_FSEEKO +#define fseeko(s, o, w) (fseek((s), (long int)(o), (w))) +#endif +#ifndef HAVE_FTELLO +#define ftello(s) ((long)ftell((s))) +#endif + + + +#define CENTRAL_MAGIC "PK\1\2" +#define LOCAL_MAGIC "PK\3\4" +#define EOCD_MAGIC "PK\5\6" +#define DATADES_MAGIC "PK\7\8" +#define TORRENT_SIG "TORRENTZIPPED-" +#define TORRENT_SIG_LEN 14 +#define TORRENT_CRC_LEN 8 +#define TORRENT_MEM_LEVEL 8 +#define CDENTRYSIZE 46u +#define LENTRYSIZE 30 +#define MAXCOMLEN 65536 +#define EOCDLEN 22 +#define CDBUFSIZE (MAXCOMLEN+EOCDLEN) +#define BUFSIZE 8192 + + + +/* state of change of a file in zip archive */ + +enum zip_state { ZIP_ST_UNCHANGED, ZIP_ST_DELETED, ZIP_ST_REPLACED, + ZIP_ST_ADDED, ZIP_ST_RENAMED }; + +/* constants for struct zip_file's member flags */ + +#define ZIP_ZF_EOF 1 /* EOF reached */ +#define ZIP_ZF_DECOMP 2 /* decompress data */ +#define ZIP_ZF_CRC 4 /* compute and compare CRC */ + +/* directory entry: general purpose bit flags */ + +#define ZIP_GPBF_ENCRYPTED 0x0001 /* is encrypted */ +#define ZIP_GPBF_DATA_DESCRIPTOR 0x0008 /* crc/size after file data */ +#define ZIP_GPBF_STRONG_ENCRYPTION 0x0040 /* uses strong encryption */ + +/* error information */ + +struct zip_error { + int zip_err; /* libzip error code (ZIP_ER_*) */ + int sys_err; /* copy of errno (E*) or zlib error code */ + char *str; /* string representation or NULL */ +}; + +/* zip archive, part of API */ + +struct zip { + char *zn; /* file name */ + FILE *zp; /* file */ + struct zip_error error; /* error information */ + + unsigned int flags; /* archive global flags */ + unsigned int ch_flags; /* changed archive global flags */ + + struct zip_cdir *cdir; /* central directory */ + char *ch_comment; /* changed archive comment */ + int ch_comment_len; /* length of changed zip archive + * comment, -1 if unchanged */ + int nentry; /* number of entries */ + int nentry_alloc; /* number of entries allocated */ + struct zip_entry *entry; /* entries */ + int nfile; /* number of opened files within archive */ + int nfile_alloc; /* number of files allocated */ + struct zip_file **file; /* opened files within archive */ +}; + +/* file in zip archive, part of API */ + +struct zip_file { + struct zip *za; /* zip archive containing this file */ + struct zip_error error; /* error information */ + int flags; /* -1: eof, >0: error */ + + int method; /* compression method */ + off_t fpos; /* position within zip file (fread/fwrite) */ + unsigned long bytes_left; /* number of bytes left to read */ + unsigned long cbytes_left; /* number of bytes of compressed data left */ + + unsigned long crc; /* CRC so far */ + unsigned long crc_orig; /* CRC recorded in archive */ + + char *buffer; + z_stream *zstr; +}; + +/* zip archive directory entry (central or local) */ + +struct zip_dirent { + unsigned short version_madeby; /* (c) version of creator */ + unsigned short version_needed; /* (cl) version needed to extract */ + unsigned short bitflags; /* (cl) general purpose bit flag */ + unsigned short comp_method; /* (cl) compression method used */ + time_t last_mod; /* (cl) time of last modification */ + unsigned int crc; /* (cl) CRC-32 of uncompressed data */ + unsigned int comp_size; /* (cl) size of commpressed data */ + unsigned int uncomp_size; /* (cl) size of uncommpressed data */ + char *filename; /* (cl) file name (NUL-terminated) */ + unsigned short filename_len; /* (cl) length of filename (w/o NUL) */ + char *extrafield; /* (cl) extra field */ + unsigned short extrafield_len; /* (cl) length of extra field */ + char *comment; /* (c) file comment */ + unsigned short comment_len; /* (c) length of file comment */ + unsigned short disk_number; /* (c) disk number start */ + unsigned short int_attrib; /* (c) internal file attributes */ + unsigned int ext_attrib; /* (c) external file attributes */ + unsigned int offset; /* (c) offset of local header */ +}; + +/* zip archive central directory */ + +struct zip_cdir { + struct zip_dirent *entry; /* directory entries */ + int nentry; /* number of entries */ + + unsigned int size; /* size of central direcotry */ + unsigned int offset; /* offset of central directory in file */ + char *comment; /* zip archive comment */ + unsigned short comment_len; /* length of zip archive comment */ +}; + + + +struct zip_source { + zip_source_callback f; + void *ud; +}; + +/* entry in zip archive directory */ + +struct zip_entry { + enum zip_state state; + struct zip_source *source; + char *ch_filename; + char *ch_comment; + int ch_comment_len; +}; + + + +extern const char * const _zip_err_str[]; +extern const int _zip_nerr_str; +extern const int _zip_err_type[]; + + + +#define ZIP_ENTRY_DATA_CHANGED(x) \ + ((x)->state == ZIP_ST_REPLACED \ + || (x)->state == ZIP_ST_ADDED) + + + +int _zip_cdir_compute_crc(struct zip *, uLong *); +void _zip_cdir_free(struct zip_cdir *); +int _zip_cdir_grow(struct zip_cdir *, int, struct zip_error *); +struct zip_cdir *_zip_cdir_new(int, struct zip_error *); +int _zip_cdir_write(struct zip_cdir *, FILE *, struct zip_error *); + +void _zip_dirent_finalize(struct zip_dirent *); +void _zip_dirent_init(struct zip_dirent *); +int _zip_dirent_read(struct zip_dirent *, FILE *, unsigned char **, + unsigned int *, int, struct zip_error *); +void _zip_dirent_torrent_normalize(struct zip_dirent *); +int _zip_dirent_write(struct zip_dirent *, FILE *, int, struct zip_error *); + +void _zip_entry_free(struct zip_entry *); +void _zip_entry_init(struct zip *, int); +struct zip_entry *_zip_entry_new(struct zip *); + +void _zip_error_clear(struct zip_error *); +void _zip_error_copy(struct zip_error *, struct zip_error *); +void _zip_error_fini(struct zip_error *); +void _zip_error_get(struct zip_error *, int *, int *); +void _zip_error_init(struct zip_error *); +void _zip_error_set(struct zip_error *, int, int); +const char *_zip_error_strerror(struct zip_error *); + +int _zip_file_fillbuf(void *, size_t, struct zip_file *); +unsigned int _zip_file_get_offset(struct zip *, int); + +int _zip_filerange_crc(FILE *, off_t, off_t, uLong *, struct zip_error *); + +struct zip_source *_zip_source_file_or_p(struct zip *, const char *, FILE *, + off_t, off_t); + +void _zip_free(struct zip *); +const char *_zip_get_name(struct zip *, int, int, struct zip_error *); +int _zip_local_header_read(struct zip *, int); +void *_zip_memdup(const void *, size_t, struct zip_error *); +int _zip_name_locate(struct zip *, const char *, int, struct zip_error *); +struct zip *_zip_new(struct zip_error *); +unsigned short _zip_read2(unsigned char **); +unsigned int _zip_read4(unsigned char **); +int _zip_replace(struct zip *, int, const char *, struct zip_source *); +int _zip_set_name(struct zip *, int, const char *); +int _zip_unchange(struct zip *, int, int); +void _zip_unchange_data(struct zip_entry *); + +#endif /* zipint.h */ diff --git a/ext/rapidxml/license.txt b/ext/rapidxml/license.txt new file mode 100644 index 0000000000..140983180b --- /dev/null +++ b/ext/rapidxml/license.txt @@ -0,0 +1,52 @@ +Use of this software is granted under one of the following two licenses, +to be chosen freely by the user. + +1. Boost Software License - Version 1.0 - August 17th, 2003 +=============================================================================== + +Copyright (c) 2006, 2007 Marcin Kalicinski + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +2. The MIT License +=============================================================================== + +Copyright (c) 2006, 2007 Marcin Kalicinski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/ext/rapidxml/manual.html b/ext/rapidxml/manual.html new file mode 100644 index 0000000000..2c422703f4 --- /dev/null +++ b/ext/rapidxml/manual.html @@ -0,0 +1,406 @@ +

RAPIDXML Manual

Version 1.13

Copyright (C) 2006, 2009 Marcin Kalicinski
See accompanying file license.txt for license information.

Table of Contents

1. What is RapidXml?
1.1 Dependencies And Compatibility
1.2 Character Types And Encodings
1.3 Error Handling
1.4 Memory Allocation
1.5 W3C Compliance
1.6 API Design
1.7 Reliability
1.8 Acknowledgements
2. Two Minute Tutorial
2.1 Parsing
2.2 Accessing The DOM Tree
2.3 Modifying The DOM Tree
2.4 Printing XML
3. Differences From Regular XML Parsers
3.1 Lifetime Of Source Text
3.2 Ownership Of Strings
3.3 Destructive Vs Non-Destructive Mode
4. Performance
4.1 Comparison With Other Parsers
5. Reference

1. What is RapidXml?

RapidXml is an attempt to create the fastest XML DOM parser possible, while retaining useability, portability and reasonable W3C compatibility. It is an in-situ parser written in C++, with parsing speed approaching that of strlen() function executed on the same data.

+ Entire parser is contained in a single header file, so no building or linking is neccesary. To use it you just need to copy rapidxml.hpp file to a convenient place (such as your project directory), and include it where needed. You may also want to use printing functions contained in header rapidxml_print.hpp.

1.1 Dependencies And Compatibility

RapidXml has no dependencies other than a very small subset of standard C++ library (<cassert>, <cstdlib>, <new> and <exception>, unless exceptions are disabled). It should compile on any reasonably conformant compiler, and was tested on Visual C++ 2003, Visual C++ 2005, Visual C++ 2008, gcc 3, gcc 4, and Comeau 4.3.3. Care was taken that no warnings are produced on these compilers, even with highest warning levels enabled.

1.2 Character Types And Encodings

RapidXml is character type agnostic, and can work both with narrow and wide characters. Current version does not fully support UTF-16 or UTF-32, so use of wide characters is somewhat incapacitated. However, it should succesfully parse wchar_t strings containing UTF-16 or UTF-32 if endianness of the data matches that of the machine. UTF-8 is fully supported, including all numeric character references, which are expanded into appropriate UTF-8 byte sequences (unless you enable parse_no_utf8 flag).

+ Note that RapidXml performs no decoding - strings returned by name() and value() functions will contain text encoded using the same encoding as source file. Rapidxml understands and expands the following character references: &apos; &amp; &quot; &lt; &gt; &#...; Other character references are not expanded.

1.3 Error Handling

By default, RapidXml uses C++ exceptions to report errors. If this behaviour is undesirable, RAPIDXML_NO_EXCEPTIONS can be defined to suppress exception code. See parse_error class and parse_error_handler() function for more information.

1.4 Memory Allocation

RapidXml uses a special memory pool object to allocate nodes and attributes, because direct allocation using new operator would be far too slow. Underlying memory allocations performed by the pool can be customized by use of memory_pool::set_allocator() function. See class memory_pool for more information.

1.5 W3C Compliance

RapidXml is not a W3C compliant parser, primarily because it ignores DOCTYPE declarations. There is a number of other, minor incompatibilities as well. Still, it can successfully parse and produce complete trees of all valid XML files in W3C conformance suite (over 1000 files specially designed to find flaws in XML processors). In destructive mode it performs whitespace normalization and character entity substitution for a small set of built-in entities.

1.6 API Design

RapidXml API is minimalistic, to reduce code size as much as possible, and facilitate use in embedded environments. Additional convenience functions are provided in separate headers: rapidxml_utils.hpp and rapidxml_print.hpp. Contents of these headers is not an essential part of the library, and is currently not documented (otherwise than with comments in code).

1.7 Reliability

RapidXml is very robust and comes with a large harness of unit tests. Special care has been taken to ensure stability of the parser no matter what source text is thrown at it. One of the unit tests produces 100,000 randomly corrupted variants of XML document, which (when uncorrupted) contains all constructs recognized by RapidXml. RapidXml passes this test when it correctly recognizes that errors have been introduced, and does not crash or loop indefinitely.

+ Another unit test puts RapidXml head-to-head with another, well estabilished XML parser, and verifies that their outputs match across a wide variety of small and large documents.

+ Yet another test feeds RapidXml with over 1000 test files from W3C compliance suite, and verifies that correct results are obtained. There are also additional tests that verify each API function separately, and test that various parsing modes work as expected.

1.8 Acknowledgements

I would like to thank Arseny Kapoulkine for his work on pugixml, which was an inspiration for this project. Additional thanks go to Kristen Wegner for creating pugxml, from which pugixml was derived. Janusz Wohlfeil kindly ran RapidXml speed tests on hardware that I did not have access to, allowing me to expand performance comparison table.

2. Two Minute Tutorial

2.1 Parsing

The following code causes RapidXml to parse a zero-terminated string named text:
using namespace rapidxml;
+xml_document<> doc;    // character type defaults to char
+doc.parse<0>(text);    // 0 means default parse flags
+
doc object is now a root of DOM tree containing representation of the parsed XML. Because all RapidXml interface is contained inside namespace rapidxml, users must either bring contents of this namespace into scope, or fully qualify all the names. Class xml_document represents a root of the DOM hierarchy. By means of public inheritance, it is also an xml_node and a memory_pool. Template parameter of xml_document::parse() function is used to specify parsing flags, with which you can fine-tune behaviour of the parser. Note that flags must be a compile-time constant.

2.2 Accessing The DOM Tree

To access the DOM tree, use methods of xml_node and xml_attribute classes:
cout << "Name of my first node is: " << doc.first_node()->name() << "\n";
+xml_node<> *node = doc.first_node("foobar");
+cout << "Node foobar has value " << node->value() << "\n";
+for (xml_attribute<> *attr = node->first_attribute();
+     attr; attr = attr->next_attribute())
+{
+    cout << "Node foobar has attribute " << attr->name() << " ";
+    cout << "with value " << attr->value() << "\n";
+}
+

2.3 Modifying The DOM Tree

DOM tree produced by the parser is fully modifiable. Nodes and attributes can be added/removed, and their contents changed. The below example creates a HTML document, whose sole contents is a link to google.com website:
xml_document<> doc;
+xml_node<> *node = doc.allocate_node(node_element, "a", "Google");
+doc.append_node(node);
+xml_attribute<> *attr = doc.allocate_attribute("href", "google.com");
+node->append_attribute(attr);
+
One quirk is that nodes and attributes do not own the text of their names and values. This is because normally they only store pointers to the source text. So, when assigning a new name or value to the node, care must be taken to ensure proper lifetime of the string. The easiest way to achieve it is to allocate the string from the xml_document memory pool. In the above example this is not necessary, because we are only assigning character constants. But the code below uses memory_pool::allocate_string() function to allocate node name (which will have the same lifetime as the document), and assigns it to a new node:
xml_document<> doc;
+char *node_name = doc.allocate_string(name);        // Allocate string and copy name into it
+xml_node<> *node = doc.allocate_node(node_element, node_name);  // Set node name to node_name
+
Check Reference section for description of the entire interface.

2.4 Printing XML

You can print xml_document and xml_node objects into an XML string. Use print() function or operator <<, which are defined in rapidxml_print.hpp header.
using namespace rapidxml;
+xml_document<> doc;    // character type defaults to char
+// ... some code to fill the document
+
+// Print to stream using operator <<
+std::cout << doc;   
+
+// Print to stream using print function, specifying printing flags
+print(std::cout, doc, 0);   // 0 means default printing flags
+
+// Print to string using output iterator
+std::string s;
+print(std::back_inserter(s), doc, 0);
+
+// Print to memory buffer using output iterator
+char buffer[4096];                      // You are responsible for making the buffer large enough!
+char *end = print(buffer, doc, 0);      // end contains pointer to character after last printed character
+*end = 0;                               // Add string terminator after XML
+

3. Differences From Regular XML Parsers

RapidXml is an in-situ parser, which allows it to achieve very high parsing speed. In-situ means that parser does not make copies of strings. Instead, it places pointers to the source text in the DOM hierarchy.

3.1 Lifetime Of Source Text

In-situ parsing requires that source text lives at least as long as the document object. If source text is destroyed, names and values of nodes in DOM tree will become destroyed as well. Additionally, whitespace processing, character entity translation, and zero-termination of strings require that source text be modified during parsing (but see non-destructive mode). This makes the text useless for further processing once it was parsed by RapidXml.

+ In many cases however, these are not serious issues.

3.2 Ownership Of Strings

Nodes and attributes produced by RapidXml do not own their name and value strings. They merely hold the pointers to them. This means you have to be careful when setting these values manually, by using xml_base::name(const Ch *) or xml_base::value(const Ch *) functions. Care must be taken to ensure that lifetime of the string passed is at least as long as lifetime of the node/attribute. The easiest way to achieve it is to allocate the string from memory_pool owned by the document. Use memory_pool::allocate_string() function for this purpose.

3.3 Destructive Vs Non-Destructive Mode

By default, the parser modifies source text during the parsing process. This is required to achieve character entity translation, whitespace normalization, and zero-termination of strings.

+ In some cases this behaviour may be undesirable, for example if source text resides in read only memory, or is mapped to memory directly from file. By using appropriate parser flags (parse_non_destructive), source text modifications can be disabled. However, because RapidXml does in-situ parsing, it obviously has the following side-effects:

4. Performance

RapidXml achieves its speed through use of several techniques:
  • In-situ parsing. When building DOM tree, RapidXml does not make copies of string data, such as node names and values. Instead, it stores pointers to interior of the source text.
  • Use of template metaprogramming techniques. This allows it to move much of the work to compile time. Through magic of the templates, C++ compiler generates a separate copy of parsing code for any combination of parser flags you use. In each copy, all possible decisions are made at compile time and all unused code is omitted.
  • Extensive use of lookup tables for parsing.
  • Hand-tuned C++ with profiling done on several most popular CPUs.
This results in a very small and fast code: a parser which is custom tailored to exact needs with each invocation.

4.1 Comparison With Other Parsers

The table below compares speed of RapidXml to some other parsers, and to strlen() function executed on the same data. On a modern CPU (as of 2007), you can expect parsing throughput to be close to 1 GB/s. As a rule of thumb, parsing speed is about 50-100x faster than Xerces DOM, 30-60x faster than TinyXml, 3-12x faster than pugxml, and about 5% - 30% faster than pugixml, the fastest XML parser I know of.
  • The test file is a real-world, 50kB large, moderately dense XML file.
  • All timing is done by using RDTSC instruction present in Pentium-compatible CPUs.
  • No profile-guided optimizations are used.
  • All parsers are running in their fastest modes.
  • The results are given in CPU cycles per character, so frequency of CPUs is irrelevant.
  • The results are minimum values from a large number of runs, to minimize effects of operating system activity, task switching, interrupt handling etc.
  • A single parse of the test file takes about 1/10th of a millisecond, so with large number of runs there is a good chance of hitting at least one no-interrupt streak, and obtaining undisturbed results.
Platform
Compiler
strlen() RapidXml pugixml 0.3 pugxml TinyXml
Pentium 4
MSVC 8.0
2.5
5.4
7.0
61.7
298.8
Pentium 4
gcc 4.1.1
0.8
6.1
9.5
67.0
413.2
Core 2
MSVC 8.0
1.0
4.5
5.0
24.6
154.8
Core 2
gcc 4.1.1
0.6
4.6
5.4
28.3
229.3
Athlon XP
MSVC 8.0
3.1
7.7
8.0
25.5
182.6
Athlon XP
gcc 4.1.1
0.9
8.2
9.2
33.7
265.2
Pentium 3
MSVC 8.0
2.0
6.3
7.0
30.9
211.9
Pentium 3
gcc 4.1.1
1.0
6.7
8.9
35.3
316.0
(*) All results are in CPU cycles per character of source text

5. Reference

This section lists all classes, functions, constants etc. and describes them in detail.
class + template + rapidxml::memory_pool
+ constructor + memory_pool()
+ destructor + ~memory_pool()
function allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)
function allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)
function allocate_string(const Ch *source=0, std::size_t size=0)
function clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0)
function clear()
function set_allocator(alloc_func *af, free_func *ff)

class rapidxml::parse_error
+ constructor + parse_error(const char *what, void *where)
function what() const
function where() const

class + template + rapidxml::xml_attribute
+ constructor + xml_attribute()
function document() const
function previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const

class + template + rapidxml::xml_base
+ constructor + xml_base()
function name() const
function name_size() const
function value() const
function value_size() const
function name(const Ch *name, std::size_t size)
function name(const Ch *name)
function value(const Ch *value, std::size_t size)
function value(const Ch *value)
function parent() const

class + template + rapidxml::xml_document
+ constructor + xml_document()
function parse(Ch *text)
function clear()

class + template + rapidxml::xml_node
+ constructor + xml_node(node_type type)
function type() const
function document() const
function first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function type(node_type type)
function prepend_node(xml_node< Ch > *child)
function append_node(xml_node< Ch > *child)
function insert_node(xml_node< Ch > *where, xml_node< Ch > *child)
function remove_first_node()
function remove_last_node()
function remove_node(xml_node< Ch > *where)
function remove_all_nodes()
function prepend_attribute(xml_attribute< Ch > *attribute)
function append_attribute(xml_attribute< Ch > *attribute)
function insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute)
function remove_first_attribute()
function remove_last_attribute()
function remove_attribute(xml_attribute< Ch > *where)
function remove_all_attributes()

namespace rapidxml
enum node_type
function parse_error_handler(const char *what, void *where)
function print(OutIt out, const xml_node< Ch > &node, int flags=0)
function print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0)
function operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node)
+ constant + parse_no_data_nodes
+ constant + parse_no_element_values
+ constant + parse_no_string_terminators
+ constant + parse_no_entity_translation
+ constant + parse_no_utf8
+ constant + parse_declaration_node
+ constant + parse_comment_nodes
+ constant + parse_doctype_node
+ constant + parse_pi_nodes
+ constant + parse_validate_closing_tags
+ constant + parse_trim_whitespace
+ constant + parse_normalize_whitespace
+ constant + parse_default
+ constant + parse_non_destructive
+ constant + parse_fastest
+ constant + parse_full
+ constant + print_no_indenting


class + template + rapidxml::memory_pool

+ + Defined in rapidxml.hpp
+ Base class for + xml_document

Description

This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. In most cases, you will not need to use this class directly. However, if you need to create nodes manually or modify names/values of nodes, you are encouraged to use memory_pool of relevant xml_document to allocate the memory. Not only is this faster than allocating them by using new operator, but also their lifetime will be tied to the lifetime of document, possibly simplyfing memory management.

+ Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. You can also call allocate_string() function to allocate strings. Such strings can then be used as names or values of nodes without worrying about their lifetime. Note that there is no free() function -- all allocations are freed at once when clear() function is called, or when the pool is destroyed.

+ It is also possible to create a standalone memory_pool, and use it to allocate nodes, whose lifetime will not be tied to any document.

+ Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. Until static memory is exhausted, no dynamic memory allocations are done. When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, by using global new[] and delete[] operators. This behaviour can be changed by setting custom allocation routines. Use set_allocator() function to set them.

+ Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. This value defaults to the size of pointer on target architecture.

+ To obtain absolutely top performance from the parser, it is important that all nodes are allocated from a single, contiguous block of memory. Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT to obtain best wasted memory to performance compromise. To do it, define their values before rapidxml.hpp file is included.

Parameters

Ch
Character type of created nodes.

+ constructor + memory_pool::memory_pool

Synopsis

memory_pool(); +

Description

Constructs empty pool with default allocator functions.

+ destructor + memory_pool::~memory_pool

Synopsis

~memory_pool(); +

Description

Destroys pool and frees all the memory. This causes memory occupied by nodes allocated by the pool to be freed. Nodes allocated from the pool are no longer valid.

function memory_pool::allocate_node

Synopsis

xml_node<Ch>* allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0); +

Description

Allocates a new node from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

Parameters

type
Type of node to create.
name
Name to assign to the node, or 0 to assign no name.
value
Value to assign to the node, or 0 to assign no value.
name_size
Size of name to assign, or 0 to automatically calculate size from name string.
value_size
Size of value to assign, or 0 to automatically calculate size from value string.

Returns

Pointer to allocated node. This pointer will never be NULL.

function memory_pool::allocate_attribute

Synopsis

xml_attribute<Ch>* allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0); +

Description

Allocates a new attribute from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

Parameters

name
Name to assign to the attribute, or 0 to assign no name.
value
Value to assign to the attribute, or 0 to assign no value.
name_size
Size of name to assign, or 0 to automatically calculate size from name string.
value_size
Size of value to assign, or 0 to automatically calculate size from value string.

Returns

Pointer to allocated attribute. This pointer will never be NULL.

function memory_pool::allocate_string

Synopsis

Ch* allocate_string(const Ch *source=0, std::size_t size=0); +

Description

Allocates a char array of given size from the pool, and optionally copies a given string to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

Parameters

source
String to initialize the allocated memory with, or 0 to not initialize it.
size
Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.

Returns

Pointer to allocated char array. This pointer will never be NULL.

function memory_pool::clone_node

Synopsis

xml_node<Ch>* clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0); +

Description

Clones an xml_node and its hierarchy of child nodes and attributes. Nodes and attributes are allocated from this memory pool. Names and values are not cloned, they are shared between the clone and the source. Result node can be optionally specified as a second parameter, in which case its contents will be replaced with cloned source node. This is useful when you want to clone entire document.

Parameters

source
Node to clone.
result
Node to put results in, or 0 to automatically allocate result node

Returns

Pointer to cloned node. This pointer will never be NULL.

function memory_pool::clear

Synopsis

void clear(); +

Description

Clears the pool. This causes memory occupied by nodes allocated by the pool to be freed. Any nodes or strings allocated from the pool will no longer be valid.

function memory_pool::set_allocator

Synopsis

void set_allocator(alloc_func *af, free_func *ff); +

Description

Sets or resets the user-defined memory allocation functions for the pool. This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. Allocation function must not return invalid pointer on failure. It should either throw, stop the program, or use longjmp() function to pass control to other place of program. If it returns invalid pointer, results are undefined.

+ User defined allocation functions must have the following forms:

+void *allocate(std::size_t size);
+void free(void *pointer);

Parameters

af
Allocation function, or 0 to restore default function
ff
Free function, or 0 to restore default function

class rapidxml::parse_error

+ + Defined in rapidxml.hpp

Description

Parse error exception. This exception is thrown by the parser when an error occurs. Use what() function to get human-readable error message. Use where() function to get a pointer to position within source text where error was detected.

+ If throwing exceptions by the parser is undesirable, it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. This function must be defined by the user.

+ This class derives from std::exception class.

+ constructor + parse_error::parse_error

Synopsis

parse_error(const char *what, void *where); +

Description

Constructs parse error.

function parse_error::what

Synopsis

virtual const char* what() const; +

Description

Gets human readable description of error.

Returns

Pointer to null terminated description of the error.

function parse_error::where

Synopsis

Ch* where() const; +

Description

Gets pointer to character data where error happened. Ch should be the same as char type of xml_document that produced the error.

Returns

Pointer to location within the parsed string where error occured.

class + template + rapidxml::xml_attribute

+ + Defined in rapidxml.hpp
+ Inherits from + xml_base

Description

Class representing attribute node of XML document. Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). Note that after parse, both name and value of attribute will point to interior of source text used for parsing. Thus, this text must persist in memory for the lifetime of attribute.

Parameters

Ch
Character type to use.

+ constructor + xml_attribute::xml_attribute

Synopsis

xml_attribute(); +

Description

Constructs an empty attribute with the specified type. Consider using memory_pool of appropriate xml_document if allocating attributes manually.

function xml_attribute::document

Synopsis

xml_document<Ch>* document() const; +

Description

Gets document of which attribute is a child.

Returns

Pointer to document that contains this attribute, or 0 if there is no parent document.

function xml_attribute::previous_attribute

Synopsis

xml_attribute<Ch>* previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

Description

Gets previous attribute, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

function xml_attribute::next_attribute

Synopsis

xml_attribute<Ch>* next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

Description

Gets next attribute, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

class + template + rapidxml::xml_base

+ + Defined in rapidxml.hpp
+ Base class for + xml_attribute xml_node

Description

Base class for xml_node and xml_attribute implementing common functions: name(), name_size(), value(), value_size() and parent().

Parameters

Ch
Character type to use

+ constructor + xml_base::xml_base

Synopsis

xml_base(); +

function xml_base::name

Synopsis

Ch* name() const; +

Description

Gets name of the node. Interpretation of name depends on type of node. Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

+ Use name_size() function to determine length of the name.

Returns

Name of node, or empty string if node has no name.

function xml_base::name_size

Synopsis

std::size_t name_size() const; +

Description

Gets size of node name, not including terminator character. This function works correctly irrespective of whether name is or is not zero terminated.

Returns

Size of node name, in characters.

function xml_base::value

Synopsis

Ch* value() const; +

Description

Gets value of node. Interpretation of value depends on type of node. Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

+ Use value_size() function to determine length of the value.

Returns

Value of node, or empty string if node has no value.

function xml_base::value_size

Synopsis

std::size_t value_size() const; +

Description

Gets size of node value, not including terminator character. This function works correctly irrespective of whether value is or is not zero terminated.

Returns

Size of node value, in characters.

function xml_base::name

Synopsis

void name(const Ch *name, std::size_t size); +

Description

Sets name of node to a non zero-terminated string. See Ownership Of Strings .

+ Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use memory_pool of the document to allocate the string - on destruction of the document the string will be automatically freed.

+ Size of name must be specified separately, because name does not have to be zero terminated. Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).

Parameters

name
Name of node to set. Does not have to be zero terminated.
size
Size of name, in characters. This does not include zero terminator, if one is present.

function xml_base::name

Synopsis

void name(const Ch *name); +

Description

Sets name of node to a zero-terminated string. See also Ownership Of Strings and xml_node::name(const Ch *, std::size_t).

Parameters

name
Name of node to set. Must be zero terminated.

function xml_base::value

Synopsis

void value(const Ch *value, std::size_t size); +

Description

Sets value of node to a non zero-terminated string. See Ownership Of Strings .

+ Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use memory_pool of the document to allocate the string - on destruction of the document the string will be automatically freed.

+ Size of value must be specified separately, because it does not have to be zero terminated. Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).

+ If an element has a child node of type node_data, it will take precedence over element value when printing. If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.

Parameters

value
value of node to set. Does not have to be zero terminated.
size
Size of value, in characters. This does not include zero terminator, if one is present.

function xml_base::value

Synopsis

void value(const Ch *value); +

Description

Sets value of node to a zero-terminated string. See also Ownership Of Strings and xml_node::value(const Ch *, std::size_t).

Parameters

value
Vame of node to set. Must be zero terminated.

function xml_base::parent

Synopsis

xml_node<Ch>* parent() const; +

Description

Gets node parent.

Returns

Pointer to parent node, or 0 if there is no parent.

class + template + rapidxml::xml_document

+ + Defined in rapidxml.hpp
+ Inherits from + xml_node memory_pool

Description

This class represents root of the DOM hierarchy. It is also an xml_node and a memory_pool through public inheritance. Use parse() function to build a DOM tree from a zero-terminated XML text string. parse() function allocates memory for nodes and attributes by using functions of xml_document, which are inherited from memory_pool. To access root node of the document, use the document itself, as if it was an xml_node.

Parameters

Ch
Character type to use.

+ constructor + xml_document::xml_document

Synopsis

xml_document(); +

Description

Constructs empty XML document.

function xml_document::parse

Synopsis

void parse(Ch *text); +

Description

Parses zero-terminated XML string according to given flags. Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. The string must persist for the lifetime of the document. In case of error, rapidxml::parse_error exception will be thrown.

+ If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. Make sure that data is zero-terminated.

+ Document can be parsed into multiple times. Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.

Parameters

text
XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.

function xml_document::clear

Synopsis

void clear(); +

Description

Clears the document by deleting all nodes and clearing the memory pool. All nodes owned by document pool are destroyed.

class + template + rapidxml::xml_node

+ + Defined in rapidxml.hpp
+ Inherits from + xml_base
+ Base class for + xml_document

Description

Class representing a node of XML document. Each node may have associated name and value strings, which are available through name() and value() functions. Interpretation of name and value depends on type of the node. Type of node can be determined by using type() function.

+ Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. Thus, this text must persist in the memory for the lifetime of node.

Parameters

Ch
Character type to use.

+ constructor + xml_node::xml_node

Synopsis

xml_node(node_type type); +

Description

Constructs an empty node with the specified type. Consider using memory_pool of appropriate document to allocate nodes manually.

Parameters

type
Type of node to construct.

function xml_node::type

Synopsis

node_type type() const; +

Description

Gets type of node.

Returns

Type of node.

function xml_node::document

Synopsis

xml_document<Ch>* document() const; +

Description

Gets document of which node is a child.

Returns

Pointer to document that contains this node, or 0 if there is no parent document.

function xml_node::first_node

Synopsis

xml_node<Ch>* first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

Description

Gets first child node, optionally matching node name.

Parameters

name
Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found child, or 0 if not found.

function xml_node::last_node

Synopsis

xml_node<Ch>* last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

Description

Gets last child node, optionally matching node name. Behaviour is undefined if node has no children. Use first_node() to test if node has children.

Parameters

name
Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found child, or 0 if not found.

function xml_node::previous_sibling

Synopsis

xml_node<Ch>* previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

Description

Gets previous sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use parent() to test if node has a parent.

Parameters

name
Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found sibling, or 0 if not found.

function xml_node::next_sibling

Synopsis

xml_node<Ch>* next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

Description

Gets next sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use parent() to test if node has a parent.

Parameters

name
Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found sibling, or 0 if not found.

function xml_node::first_attribute

Synopsis

xml_attribute<Ch>* first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

Description

Gets first attribute of node, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

function xml_node::last_attribute

Synopsis

xml_attribute<Ch>* last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

Description

Gets last attribute of node, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

function xml_node::type

Synopsis

void type(node_type type); +

Description

Sets type of node.

Parameters

type
Type of node to set.

function xml_node::prepend_node

Synopsis

void prepend_node(xml_node< Ch > *child); +

Description

Prepends a new child node. The prepended child becomes the first child, and all existing children are moved one position back.

Parameters

child
Node to prepend.

function xml_node::append_node

Synopsis

void append_node(xml_node< Ch > *child); +

Description

Appends a new child node. The appended child becomes the last child.

Parameters

child
Node to append.

function xml_node::insert_node

Synopsis

void insert_node(xml_node< Ch > *where, xml_node< Ch > *child); +

Description

Inserts a new child node at specified place inside the node. All children after and including the specified node are moved one position back.

Parameters

where
Place where to insert the child, or 0 to insert at the back.
child
Node to insert.

function xml_node::remove_first_node

Synopsis

void remove_first_node(); +

Description

Removes first child node. If node has no children, behaviour is undefined. Use first_node() to test if node has children.

function xml_node::remove_last_node

Synopsis

void remove_last_node(); +

Description

Removes last child of the node. If node has no children, behaviour is undefined. Use first_node() to test if node has children.

function xml_node::remove_node

Synopsis

void remove_node(xml_node< Ch > *where); +

Description

Removes specified child from the node.

function xml_node::remove_all_nodes

Synopsis

void remove_all_nodes(); +

Description

Removes all child nodes (but not attributes).

function xml_node::prepend_attribute

Synopsis

void prepend_attribute(xml_attribute< Ch > *attribute); +

Description

Prepends a new attribute to the node.

Parameters

attribute
Attribute to prepend.

function xml_node::append_attribute

Synopsis

void append_attribute(xml_attribute< Ch > *attribute); +

Description

Appends a new attribute to the node.

Parameters

attribute
Attribute to append.

function xml_node::insert_attribute

Synopsis

void insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute); +

Description

Inserts a new attribute at specified place inside the node. All attributes after and including the specified attribute are moved one position back.

Parameters

where
Place where to insert the attribute, or 0 to insert at the back.
attribute
Attribute to insert.

function xml_node::remove_first_attribute

Synopsis

void remove_first_attribute(); +

Description

Removes first attribute of the node. If node has no attributes, behaviour is undefined. Use first_attribute() to test if node has attributes.

function xml_node::remove_last_attribute

Synopsis

void remove_last_attribute(); +

Description

Removes last attribute of the node. If node has no attributes, behaviour is undefined. Use first_attribute() to test if node has attributes.

function xml_node::remove_attribute

Synopsis

void remove_attribute(xml_attribute< Ch > *where); +

Description

Removes specified attribute from node.

Parameters

where
Pointer to attribute to be removed.

function xml_node::remove_all_attributes

Synopsis

void remove_all_attributes(); +

Description

Removes all attributes of node.

enum node_type

Description

Enumeration listing all node types produced by the parser. Use xml_node::type() function to query node type.

Values

node_document
A document node. Name and value are empty.
node_element
An element node. Name contains element name. Value contains text of first data node.
node_data
A data node. Name is empty. Value contains data text.
node_cdata
A CDATA node. Name is empty. Value contains data text.
node_comment
A comment node. Name is empty. Value contains comment text.
node_declaration
A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
node_doctype
A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
node_pi
A PI node. Name contains target. Value contains instructions.

function parse_error_handler

Synopsis

void rapidxml::parse_error_handler(const char *what, void *where); +

Description

When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function is called to notify user about the error. It must be defined by the user.

+ This function cannot return. If it does, the results are undefined.

+ A very simple definition might look like that: + void rapidxml::parse_error_handler(const char *what, void *where) + { + std::cout << "Parse error: " << what << "\n"; + std::abort(); + } +

Parameters

what
Human readable description of the error.
where
Pointer to character data where error was detected.

function print

Synopsis

OutIt rapidxml::print(OutIt out, const xml_node< Ch > &node, int flags=0); +

Description

Prints XML to given output iterator.

Parameters

out
Output iterator to print to.
node
Node to be printed. Pass xml_document to print entire document.
flags
Flags controlling how XML is printed.

Returns

Output iterator pointing to position immediately after last character of printed text.

function print

Synopsis

std::basic_ostream<Ch>& rapidxml::print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0); +

Description

Prints XML to given output stream.

Parameters

out
Output stream to print to.
node
Node to be printed. Pass xml_document to print entire document.
flags
Flags controlling how XML is printed.

Returns

Output stream.

function operator<<

Synopsis

std::basic_ostream<Ch>& rapidxml::operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node); +

Description

Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.

Parameters

out
Output stream to print to.
node
Node to be printed.

Returns

Output stream.

+ constant + parse_no_data_nodes

Synopsis

const int parse_no_data_nodes + = 0x1; +

Description

Parse flag instructing the parser to not create data nodes. Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_no_element_values

Synopsis

const int parse_no_element_values + = 0x2; +

Description

Parse flag instructing the parser to not use text of first data node as a value of parent element. Can be combined with other flags by use of | operator. Note that child data nodes of element node take precendence over its value when printing. That is, if element has one or more child data nodes and a value, the value will be ignored. Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.

+ See xml_document::parse() function.

+ constant + parse_no_string_terminators

Synopsis

const int parse_no_string_terminators + = 0x4; +

Description

Parse flag instructing the parser to not place zero terminators after strings in the source text. By default zero terminators are placed, modifying source text. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_no_entity_translation

Synopsis

const int parse_no_entity_translation + = 0x8; +

Description

Parse flag instructing the parser to not translate entities in the source text. By default entities are translated, modifying source text. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_no_utf8

Synopsis

const int parse_no_utf8 + = 0x10; +

Description

Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. By default, UTF-8 handling is enabled. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_declaration_node

Synopsis

const int parse_declaration_node + = 0x20; +

Description

Parse flag instructing the parser to create XML declaration node. By default, declaration node is not created. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_comment_nodes

Synopsis

const int parse_comment_nodes + = 0x40; +

Description

Parse flag instructing the parser to create comments nodes. By default, comment nodes are not created. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_doctype_node

Synopsis

const int parse_doctype_node + = 0x80; +

Description

Parse flag instructing the parser to create DOCTYPE node. By default, doctype node is not created. Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_pi_nodes

Synopsis

const int parse_pi_nodes + = 0x100; +

Description

Parse flag instructing the parser to create PI nodes. By default, PI nodes are not created. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_validate_closing_tags

Synopsis

const int parse_validate_closing_tags + = 0x200; +

Description

Parse flag instructing the parser to validate closing tag names. If not set, name inside closing tag is irrelevant to the parser. By default, closing tags are not validated. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_trim_whitespace

Synopsis

const int parse_trim_whitespace + = 0x400; +

Description

Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. By default, whitespace is not trimmed. This flag does not cause the parser to modify source text. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_normalize_whitespace

Synopsis

const int parse_normalize_whitespace + = 0x800; +

Description

Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. By default, whitespace is not normalized. If this flag is specified, source text will be modified. Can be combined with other flags by use of | operator.

+ See xml_document::parse() function.

+ constant + parse_default

Synopsis

const int parse_default + = 0; +

Description

Parse flags which represent default behaviour of the parser. This is always equal to 0, so that all other flags can be simply ored together. Normally there is no need to inconveniently disable flags by anding with their negated (~) values. This also means that meaning of each flag is a negation of the default setting. For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, and using the flag will disable it.

+ See xml_document::parse() function.

+ constant + parse_non_destructive

Synopsis

const int parse_non_destructive + = parse_no_string_terminators | parse_no_entity_translation; +

Description

A combination of parse flags that forbids any modifications of the source text. This also results in faster parsing. However, note that the following will occur:
  • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
  • entities will not be translated
  • whitespace will not be normalized
+See xml_document::parse() function.

+ constant + parse_fastest

Synopsis

const int parse_fastest + = parse_non_destructive | parse_no_data_nodes; +

Description

A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.

+ See xml_document::parse() function.

+ constant + parse_full

Synopsis

const int parse_full + = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; +

Description

A combination of parse flags resulting in largest amount of data being extracted. This usually results in slowest parsing.

+ See xml_document::parse() function.

+ constant + print_no_indenting

Synopsis

const int print_no_indenting + = 0x1; +

Description

Printer flag instructing the printer to suppress indenting of XML. See print() function.

\ No newline at end of file diff --git a/ext/rapidxml/rapidxml.hpp b/ext/rapidxml/rapidxml.hpp new file mode 100644 index 0000000000..ae91e081d0 --- /dev/null +++ b/ext/rapidxml/rapidxml.hpp @@ -0,0 +1,2596 @@ +#ifndef RAPIDXML_HPP_INCLUDED +#define RAPIDXML_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation + +// If standard library is disabled, user must provide implementations of required functions and typedefs +#if !defined(RAPIDXML_NO_STDLIB) + #include // For std::size_t + #include // For assert + #include // For placement new +#endif + +// On MSVC, disable "conditional expression is constant" warning (level 4). +// This warning is almost impossible to avoid with certain types of templated code +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable:4127) // Conditional expression is constant +#endif + +/////////////////////////////////////////////////////////////////////////// +// RAPIDXML_PARSE_ERROR + +#if defined(RAPIDXML_NO_EXCEPTIONS) + +#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } + +namespace rapidxml +{ + //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, + //! this function is called to notify user about the error. + //! It must be defined by the user. + //!

+ //! This function cannot return. If it does, the results are undefined. + //!

+ //! A very simple definition might look like that: + //!

+    //! void %rapidxml::%parse_error_handler(const char *what, void *where)
+    //! {
+    //!     std::cout << "Parse error: " << what << "\n";
+    //!     std::abort();
+    //! }
+    //! 
+ //! \param what Human readable description of the error. + //! \param where Pointer to character data where error was detected. + void parse_error_handler(const char *what, void *where); +} + +#else + +#include // For std::exception + +#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) + +namespace rapidxml +{ + + //! Parse error exception. + //! This exception is thrown by the parser when an error occurs. + //! Use what() function to get human-readable error message. + //! Use where() function to get a pointer to position within source text where error was detected. + //!

+ //! If throwing exceptions by the parser is undesirable, + //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. + //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. + //! This function must be defined by the user. + //!

+ //! This class derives from std::exception class. + class parse_error: public std::exception + { + + public: + + //! Constructs parse error + parse_error(const char *what, void *where) + : m_what(what) + , m_where(where) + { + } + + //! Gets human readable description of error. + //! \return Pointer to null terminated description of the error. + virtual const char *what() const throw() + { + return m_what; + } + + //! Gets pointer to character data where error happened. + //! Ch should be the same as char type of xml_document that produced the error. + //! \return Pointer to location within the parsed string where error occured. + template + Ch *where() const + { + return reinterpret_cast(m_where); + } + + private: + + const char *m_what; + void *m_where; + + }; +} + +#endif + +/////////////////////////////////////////////////////////////////////////// +// Pool sizes + +#ifndef RAPIDXML_STATIC_POOL_SIZE + // Size of static memory block of memory_pool. + // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. + // No dynamic memory allocations are performed by memory_pool until static memory is exhausted. + #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_DYNAMIC_POOL_SIZE + // Size of dynamic memory block of memory_pool. + // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. + // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. + #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_ALIGNMENT + // Memory allocation alignment. + // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. + // All memory allocations for nodes, attributes and strings will be aligned to this value. + // This must be a power of 2 and at least 1, otherwise memory_pool will not work. + #define RAPIDXML_ALIGNMENT sizeof(void *) +#endif + +namespace rapidxml +{ + // Forward declarations + template class xml_node; + template class xml_attribute; + template class xml_document; + + //! Enumeration listing all node types produced by the parser. + //! Use xml_node::type() function to query node type. + enum node_type + { + node_document, //!< A document node. Name and value are empty. + node_element, //!< An element node. Name contains element name. Value contains text of first data node. + node_data, //!< A data node. Name is empty. Value contains data text. + node_cdata, //!< A CDATA node. Name is empty. Value contains data text. + node_comment, //!< A comment node. Name is empty. Value contains comment text. + node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. + node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text. + node_pi //!< A PI node. Name contains target. Value contains instructions. + }; + + /////////////////////////////////////////////////////////////////////// + // Parsing flags + + //! Parse flag instructing the parser to not create data nodes. + //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_no_data_nodes = 0x1; + + //! Parse flag instructing the parser to not use text of first data node as a value of parent element. + //! Can be combined with other flags by use of | operator. + //! Note that child data nodes of element node take precendence over its value when printing. + //! That is, if element has one or more child data nodes and a value, the value will be ignored. + //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. + //!

+ //! See xml_document::parse() function. + const int parse_no_element_values = 0x2; + + //! Parse flag instructing the parser to not place zero terminators after strings in the source text. + //! By default zero terminators are placed, modifying source text. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_no_string_terminators = 0x4; + + //! Parse flag instructing the parser to not translate entities in the source text. + //! By default entities are translated, modifying source text. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_no_entity_translation = 0x8; + + //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. + //! By default, UTF-8 handling is enabled. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_no_utf8 = 0x10; + + //! Parse flag instructing the parser to create XML declaration node. + //! By default, declaration node is not created. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_declaration_node = 0x20; + + //! Parse flag instructing the parser to create comments nodes. + //! By default, comment nodes are not created. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_comment_nodes = 0x40; + + //! Parse flag instructing the parser to create DOCTYPE node. + //! By default, doctype node is not created. + //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_doctype_node = 0x80; + + //! Parse flag instructing the parser to create PI nodes. + //! By default, PI nodes are not created. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_pi_nodes = 0x100; + + //! Parse flag instructing the parser to validate closing tag names. + //! If not set, name inside closing tag is irrelevant to the parser. + //! By default, closing tags are not validated. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_validate_closing_tags = 0x200; + + //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. + //! By default, whitespace is not trimmed. + //! This flag does not cause the parser to modify source text. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_trim_whitespace = 0x400; + + //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. + //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. + //! By default, whitespace is not normalized. + //! If this flag is specified, source text will be modified. + //! Can be combined with other flags by use of | operator. + //!

+ //! See xml_document::parse() function. + const int parse_normalize_whitespace = 0x800; + + // Compound flags + + //! Parse flags which represent default behaviour of the parser. + //! This is always equal to 0, so that all other flags can be simply ored together. + //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values. + //! This also means that meaning of each flag is a negation of the default setting. + //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, + //! and using the flag will disable it. + //!

+ //! See xml_document::parse() function. + const int parse_default = 0; + + //! A combination of parse flags that forbids any modifications of the source text. + //! This also results in faster parsing. However, note that the following will occur: + //!
    + //!
  • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
  • + //!
  • entities will not be translated
  • + //!
  • whitespace will not be normalized
  • + //!
+ //! See xml_document::parse() function. + const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation; + + //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. + //!

+ //! See xml_document::parse() function. + const int parse_fastest = parse_non_destructive | parse_no_data_nodes; + + //! A combination of parse flags resulting in largest amount of data being extracted. + //! This usually results in slowest parsing. + //!

+ //! See xml_document::parse() function. + const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; + + /////////////////////////////////////////////////////////////////////// + // Internals + + //! \cond internal + namespace internal + { + + // Struct that contains lookup tables for the parser + // It must be a template to allow correct linking (because it has static data members, which are defined in a header file). + template + struct lookup_tables + { + static const unsigned char lookup_whitespace[256]; // Whitespace table + static const unsigned char lookup_node_name[256]; // Node name table + static const unsigned char lookup_text[256]; // Text table + static const unsigned char lookup_text_pure_no_ws[256]; // Text table + static const unsigned char lookup_text_pure_with_ws[256]; // Text table + static const unsigned char lookup_attribute_name[256]; // Attribute name table + static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes + static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes + static const unsigned char lookup_digits[256]; // Digits + static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters + }; + + // Find length of the string + template + inline std::size_t measure(const Ch *p) + { + const Ch *tmp = p; + while (*tmp) + ++tmp; + return tmp - p; + } + + // Compare strings for equality + template + inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive) + { + if (size1 != size2) + return false; + if (case_sensitive) + { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (*p1 != *p2) + return false; + } + else + { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] != lookup_tables<0>::lookup_upcase[static_cast(*p2)]) + return false; + } + return true; + } + } + //! \endcond + + /////////////////////////////////////////////////////////////////////// + // Memory pool + + //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. + //! In most cases, you will not need to use this class directly. + //! However, if you need to create nodes manually or modify names/values of nodes, + //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. + //! Not only is this faster than allocating them by using new operator, + //! but also their lifetime will be tied to the lifetime of document, + //! possibly simplyfing memory management. + //!

+ //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. + //! You can also call allocate_string() function to allocate strings. + //! Such strings can then be used as names or values of nodes without worrying about their lifetime. + //! Note that there is no free() function -- all allocations are freed at once when clear() function is called, + //! or when the pool is destroyed. + //!

+ //! It is also possible to create a standalone memory_pool, and use it + //! to allocate nodes, whose lifetime will not be tied to any document. + //!

+ //! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. + //! Until static memory is exhausted, no dynamic memory allocations are done. + //! When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, + //! by using global new[] and delete[] operators. + //! This behaviour can be changed by setting custom allocation routines. + //! Use set_allocator() function to set them. + //!

+ //! Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. + //! This value defaults to the size of pointer on target architecture. + //!

+ //! To obtain absolutely top performance from the parser, + //! it is important that all nodes are allocated from a single, contiguous block of memory. + //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. + //! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT + //! to obtain best wasted memory to performance compromise. + //! To do it, define their values before rapidxml.hpp file is included. + //! \param Ch Character type of created nodes. + template + class memory_pool + { + + public: + + //! \cond internal + typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory + typedef void (free_func)(void *); // Type of user-defined function used to free memory + //! \endcond + + //! Constructs empty pool with default allocator functions. + memory_pool() + : m_alloc_func(0) + , m_free_func(0) + { + init(); + } + + //! Destroys pool and frees all the memory. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Nodes allocated from the pool are no longer valid. + ~memory_pool() + { + clear(); + } + + //! Allocates a new node from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param type Type of node to create. + //! \param name Name to assign to the node, or 0 to assign no name. + //! \param value Value to assign to the node, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated node. This pointer will never be NULL. + xml_node *allocate_node(node_type type, + const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) + { + void *memory = allocate_aligned(sizeof(xml_node)); + xml_node *node = new(memory) xml_node(type); + if (name) + { + if (name_size > 0) + node->name(name, name_size); + else + node->name(name); + } + if (value) + { + if (value_size > 0) + node->value(value, value_size); + else + node->value(value); + } + return node; + } + + //! Allocates a new attribute from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param name Name to assign to the attribute, or 0 to assign no name. + //! \param value Value to assign to the attribute, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated attribute. This pointer will never be NULL. + xml_attribute *allocate_attribute(const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) + { + void *memory = allocate_aligned(sizeof(xml_attribute)); + xml_attribute *attribute = new(memory) xml_attribute; + if (name) + { + if (name_size > 0) + attribute->name(name, name_size); + else + attribute->name(name); + } + if (value) + { + if (value_size > 0) + attribute->value(value, value_size); + else + attribute->value(value); + } + return attribute; + } + + //! Allocates a char array of given size from the pool, and optionally copies a given string to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param source String to initialize the allocated memory with, or 0 to not initialize it. + //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. + //! \return Pointer to allocated char array. This pointer will never be NULL. + Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) + { + assert(source || size); // Either source or size (or both) must be specified + if (size == 0) + size = internal::measure(source) + 1; + Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); + if (source) + for (std::size_t i = 0; i < size; ++i) + result[i] = source[i]; + return result; + } + + //! Clones an xml_node and its hierarchy of child nodes and attributes. + //! Nodes and attributes are allocated from this memory pool. + //! Names and values are not cloned, they are shared between the clone and the source. + //! Result node can be optionally specified as a second parameter, + //! in which case its contents will be replaced with cloned source node. + //! This is useful when you want to clone entire document. + //! \param source Node to clone. + //! \param result Node to put results in, or 0 to automatically allocate result node + //! \return Pointer to cloned node. This pointer will never be NULL. + xml_node *clone_node(const xml_node *source, xml_node *result = 0) + { + // Prepare result node + if (result) + { + result->remove_all_attributes(); + result->remove_all_nodes(); + result->type(source->type()); + } + else + result = allocate_node(source->type()); + + // Clone name and value + result->name(source->name(), source->name_size()); + result->value(source->value(), source->value_size()); + + // Clone child nodes and attributes + for (xml_node *child = source->first_node(); child; child = child->next_sibling()) + result->append_node(clone_node(child)); + for (xml_attribute *attr = source->first_attribute(); attr; attr = attr->next_attribute()) + result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size())); + + return result; + } + + //! Clears the pool. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Any nodes or strings allocated from the pool will no longer be valid. + void clear() + { + while (m_begin != m_static_memory) + { + char *previous_begin = reinterpret_cast
(align(m_begin))->previous_begin; + if (m_free_func) + m_free_func(m_begin); + else + delete[] m_begin; + m_begin = previous_begin; + } + init(); + } + + //! Sets or resets the user-defined memory allocation functions for the pool. + //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. + //! Allocation function must not return invalid pointer on failure. It should either throw, + //! stop the program, or use longjmp() function to pass control to other place of program. + //! If it returns invalid pointer, results are undefined. + //!

+ //! User defined allocation functions must have the following forms: + //!
+ //!
void *allocate(std::size_t size); + //!
void free(void *pointer); + //!

+ //! \param af Allocation function, or 0 to restore default function + //! \param ff Free function, or 0 to restore default function + void set_allocator(alloc_func *af, free_func *ff) + { + assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet + m_alloc_func = af; + m_free_func = ff; + } + + private: + + struct header + { + char *previous_begin; + }; + + void init() + { + m_begin = m_static_memory; + m_ptr = align(m_begin); + m_end = m_static_memory + sizeof(m_static_memory); + } + + char *align(char *ptr) + { + std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1)); + return ptr + alignment; + } + + char *allocate_raw(std::size_t size) + { + // Allocate + void *memory; + if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] + { + memory = m_alloc_func(size); + assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp + } + else + { + memory = new char[size]; +#ifdef RAPIDXML_NO_EXCEPTIONS + if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc + RAPIDXML_PARSE_ERROR("out of memory", 0); +#endif + } + return static_cast(memory); + } + + void *allocate_aligned(std::size_t size) + { + // Calculate aligned pointer + char *result = align(m_ptr); + + // If not enough memory left in current pool, allocate a new pool + if (result + size > m_end) + { + // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) + std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; + if (pool_size < size) + pool_size = size; + + // Allocate + std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation + char *raw_memory = allocate_raw(alloc_size); + + // Setup new pool in allocated memory + char *pool = align(raw_memory); + header *new_header = reinterpret_cast
(pool); + new_header->previous_begin = m_begin; + m_begin = raw_memory; + m_ptr = pool + sizeof(header); + m_end = raw_memory + alloc_size; + + // Calculate aligned pointer again using new pool + result = align(m_ptr); + } + + // Update pool and return aligned pointer + m_ptr = result + size; + return result; + } + + char *m_begin; // Start of raw memory making up current pool + char *m_ptr; // First free byte in current pool + char *m_end; // One past last available byte in current pool + char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory + alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used + free_func *m_free_func; // Free function, or 0 if default is to be used + }; + + /////////////////////////////////////////////////////////////////////////// + // XML base + + //! Base class for xml_node and xml_attribute implementing common functions: + //! name(), name_size(), value(), value_size() and parent(). + //! \param Ch Character type to use + template + class xml_base + { + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + // Construct a base with empty name, value and parent + xml_base() + : m_name(0) + , m_value(0) + , m_parent(0) + { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets name of the node. + //! Interpretation of name depends on type of node. + //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

+ //! Use name_size() function to determine length of the name. + //! \return Name of node, or empty string if node has no name. + Ch *name() const + { + return m_name ? m_name : nullstr(); + } + + //! Gets size of node name, not including terminator character. + //! This function works correctly irrespective of whether name is or is not zero terminated. + //! \return Size of node name, in characters. + std::size_t name_size() const + { + return m_name ? m_name_size : 0; + } + + //! Gets value of node. + //! Interpretation of value depends on type of node. + //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

+ //! Use value_size() function to determine length of the value. + //! \return Value of node, or empty string if node has no value. + Ch *value() const + { + return m_value ? m_value : nullstr(); + } + + //! Gets size of node value, not including terminator character. + //! This function works correctly irrespective of whether value is or is not zero terminated. + //! \return Size of node value, in characters. + std::size_t value_size() const + { + return m_value ? m_value_size : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets name of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

+ //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

+ //! Size of name must be specified separately, because name does not have to be zero terminated. + //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //! \param name Name of node to set. Does not have to be zero terminated. + //! \param size Size of name, in characters. This does not include zero terminator, if one is present. + void name(const Ch *name, std::size_t size) + { + m_name = const_cast(name); + m_name_size = size; + } + + //! Sets name of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). + //! \param name Name of node to set. Must be zero terminated. + void name(const Ch *name) + { + this->name(name, internal::measure(name)); + } + + //! Sets value of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

+ //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

+ //! Size of value must be specified separately, because it does not have to be zero terminated. + //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //!

+ //! If an element has a child node of type node_data, it will take precedence over element value when printing. + //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. + //! \param value value of node to set. Does not have to be zero terminated. + //! \param size Size of value, in characters. This does not include zero terminator, if one is present. + void value(const Ch *value, std::size_t size) + { + m_value = const_cast(value); + m_value_size = size; + } + + //! Sets value of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). + //! \param value Vame of node to set. Must be zero terminated. + void value(const Ch *value) + { + this->value(value, internal::measure(value)); + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets node parent. + //! \return Pointer to parent node, or 0 if there is no parent. + xml_node *parent() const + { + return m_parent; + } + + protected: + + // Return empty string + static Ch *nullstr() + { + static Ch zero = Ch('\0'); + return &zero; + } + + Ch *m_name; // Name of node, or 0 if no name + Ch *m_value; // Value of node, or 0 if no value + std::size_t m_name_size; // Length of node name, or undefined of no name + std::size_t m_value_size; // Length of node value, or undefined if no value + xml_node *m_parent; // Pointer to parent node, or 0 if none + + }; + + //! Class representing attribute node of XML document. + //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). + //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. + //! Thus, this text must persist in memory for the lifetime of attribute. + //! \param Ch Character type to use. + template + class xml_attribute: public xml_base + { + + friend class xml_node; + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty attribute with the specified type. + //! Consider using memory_pool of appropriate xml_document if allocating attributes manually. + xml_attribute() + { + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which attribute is a child. + //! \return Pointer to document that contains this attribute, or 0 if there is no parent document. + xml_document *document() const + { + if (xml_node *node = this->parent()) + { + while (node->parent()) + node = node->parent(); + return node->type() == node_document ? static_cast *>(node) : 0; + } + else + return 0; + } + + //! Gets previous attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return this->m_parent ? m_prev_attribute : 0; + } + + //! Gets next attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return this->m_parent ? m_next_attribute : 0; + } + + private: + + xml_attribute *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero + xml_attribute *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero + + }; + + /////////////////////////////////////////////////////////////////////////// + // XML node + + //! Class representing a node of XML document. + //! Each node may have associated name and value strings, which are available through name() and value() functions. + //! Interpretation of name and value depends on type of the node. + //! Type of node can be determined by using type() function. + //!

+ //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. + //! Thus, this text must persist in the memory for the lifetime of node. + //! \param Ch Character type to use. + template + class xml_node: public xml_base + { + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty node with the specified type. + //! Consider using memory_pool of appropriate document to allocate nodes manually. + //! \param type Type of node to construct. + xml_node(node_type type) + : m_type(type) + , m_first_node(0) + , m_first_attribute(0) + { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets type of node. + //! \return Type of node. + node_type type() const + { + return m_type; + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which node is a child. + //! \return Pointer to document that contains this node, or 0 if there is no parent document. + xml_document *document() const + { + xml_node *node = const_cast *>(this); + while (node->parent()) + node = node->parent(); + return node->type() == node_document ? static_cast *>(node) : 0; + } + + //! Gets first child node, optionally matching node name. + //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *child = m_first_node; child; child = child->next_sibling()) + if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) + return child; + return 0; + } + else + return m_first_node; + } + + //! Gets last child node, optionally matching node name. + //! Behaviour is undefined if node has no children. + //! Use first_node() to test if node has children. + //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(m_first_node); // Cannot query for last child if node has no children + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *child = m_last_node; child; child = child->previous_sibling()) + if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) + return child; + return 0; + } + else + return m_last_node; + } + + //! Gets previous sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + return sibling; + return 0; + } + else + return m_prev_sibling; + } + + //! Gets next sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + return sibling; + return 0; + } + else + return m_next_sibling; + } + + //! Gets first attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return m_first_attribute; + } + + //! Gets last attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return m_first_attribute ? m_last_attribute : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets type of node. + //! \param type Type of node to set. + void type(node_type type) + { + m_type = type; + } + + /////////////////////////////////////////////////////////////////////////// + // Node manipulation + + //! Prepends a new child node. + //! The prepended child becomes the first child, and all existing children are moved one position back. + //! \param child Node to prepend. + void prepend_node(xml_node *child) + { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) + { + child->m_next_sibling = m_first_node; + m_first_node->m_prev_sibling = child; + } + else + { + child->m_next_sibling = 0; + m_last_node = child; + } + m_first_node = child; + child->m_parent = this; + child->m_prev_sibling = 0; + } + + //! Appends a new child node. + //! The appended child becomes the last child. + //! \param child Node to append. + void append_node(xml_node *child) + { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) + { + child->m_prev_sibling = m_last_node; + m_last_node->m_next_sibling = child; + } + else + { + child->m_prev_sibling = 0; + m_first_node = child; + } + m_last_node = child; + child->m_parent = this; + child->m_next_sibling = 0; + } + + //! Inserts a new child node at specified place inside the node. + //! All children after and including the specified node are moved one position back. + //! \param where Place where to insert the child, or 0 to insert at the back. + //! \param child Node to insert. + void insert_node(xml_node *where, xml_node *child) + { + assert(!where || where->parent() == this); + assert(child && !child->parent() && child->type() != node_document); + if (where == m_first_node) + prepend_node(child); + else if (where == 0) + append_node(child); + else + { + child->m_prev_sibling = where->m_prev_sibling; + child->m_next_sibling = where; + where->m_prev_sibling->m_next_sibling = child; + where->m_prev_sibling = child; + child->m_parent = this; + } + } + + //! Removes first child node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_first_node() + { + assert(first_node()); + xml_node *child = m_first_node; + m_first_node = child->m_next_sibling; + if (child->m_next_sibling) + child->m_next_sibling->m_prev_sibling = 0; + else + m_last_node = 0; + child->m_parent = 0; + } + + //! Removes last child of the node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_last_node() + { + assert(first_node()); + xml_node *child = m_last_node; + if (child->m_prev_sibling) + { + m_last_node = child->m_prev_sibling; + child->m_prev_sibling->m_next_sibling = 0; + } + else + m_first_node = 0; + child->m_parent = 0; + } + + //! Removes specified child from the node + // \param where Pointer to child to be removed. + void remove_node(xml_node *where) + { + assert(where && where->parent() == this); + assert(first_node()); + if (where == m_first_node) + remove_first_node(); + else if (where == m_last_node) + remove_last_node(); + else + { + where->m_prev_sibling->m_next_sibling = where->m_next_sibling; + where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; + where->m_parent = 0; + } + } + + //! Removes all child nodes (but not attributes). + void remove_all_nodes() + { + for (xml_node *node = first_node(); node; node = node->m_next_sibling) + node->m_parent = 0; + m_first_node = 0; + } + + //! Prepends a new attribute to the node. + //! \param attribute Attribute to prepend. + void prepend_attribute(xml_attribute *attribute) + { + assert(attribute && !attribute->parent()); + if (first_attribute()) + { + attribute->m_next_attribute = m_first_attribute; + m_first_attribute->m_prev_attribute = attribute; + } + else + { + attribute->m_next_attribute = 0; + m_last_attribute = attribute; + } + m_first_attribute = attribute; + attribute->m_parent = this; + attribute->m_prev_attribute = 0; + } + + //! Appends a new attribute to the node. + //! \param attribute Attribute to append. + void append_attribute(xml_attribute *attribute) + { + assert(attribute && !attribute->parent()); + if (first_attribute()) + { + attribute->m_prev_attribute = m_last_attribute; + m_last_attribute->m_next_attribute = attribute; + } + else + { + attribute->m_prev_attribute = 0; + m_first_attribute = attribute; + } + m_last_attribute = attribute; + attribute->m_parent = this; + attribute->m_next_attribute = 0; + } + + //! Inserts a new attribute at specified place inside the node. + //! All attributes after and including the specified attribute are moved one position back. + //! \param where Place where to insert the attribute, or 0 to insert at the back. + //! \param attribute Attribute to insert. + void insert_attribute(xml_attribute *where, xml_attribute *attribute) + { + assert(!where || where->parent() == this); + assert(attribute && !attribute->parent()); + if (where == m_first_attribute) + prepend_attribute(attribute); + else if (where == 0) + append_attribute(attribute); + else + { + attribute->m_prev_attribute = where->m_prev_attribute; + attribute->m_next_attribute = where; + where->m_prev_attribute->m_next_attribute = attribute; + where->m_prev_attribute = attribute; + attribute->m_parent = this; + } + } + + //! Removes first attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_first_attribute() + { + assert(first_attribute()); + xml_attribute *attribute = m_first_attribute; + if (attribute->m_next_attribute) + { + attribute->m_next_attribute->m_prev_attribute = 0; + } + else + m_last_attribute = 0; + attribute->m_parent = 0; + m_first_attribute = attribute->m_next_attribute; + } + + //! Removes last attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_last_attribute() + { + assert(first_attribute()); + xml_attribute *attribute = m_last_attribute; + if (attribute->m_prev_attribute) + { + attribute->m_prev_attribute->m_next_attribute = 0; + m_last_attribute = attribute->m_prev_attribute; + } + else + m_first_attribute = 0; + attribute->m_parent = 0; + } + + //! Removes specified attribute from node. + //! \param where Pointer to attribute to be removed. + void remove_attribute(xml_attribute *where) + { + assert(first_attribute() && where->parent() == this); + if (where == m_first_attribute) + remove_first_attribute(); + else if (where == m_last_attribute) + remove_last_attribute(); + else + { + where->m_prev_attribute->m_next_attribute = where->m_next_attribute; + where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; + where->m_parent = 0; + } + } + + //! Removes all attributes of node. + void remove_all_attributes() + { + for (xml_attribute *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute) + attribute->m_parent = 0; + m_first_attribute = 0; + } + + private: + + /////////////////////////////////////////////////////////////////////////// + // Restrictions + + // No copying + xml_node(const xml_node &); + void operator =(const xml_node &); + + /////////////////////////////////////////////////////////////////////////// + // Data members + + // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0. + // This is required for maximum performance, as it allows the parser to omit initialization of + // unneded/redundant values. + // + // The rules are as follows: + // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively + // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage + // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage + + node_type m_type; // Type of node; always valid + xml_node *m_first_node; // Pointer to first child node, or 0 if none; always valid + xml_node *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero + xml_attribute *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid + xml_attribute *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero + xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + + }; + + /////////////////////////////////////////////////////////////////////////// + // XML document + + //! This class represents root of the DOM hierarchy. + //! It is also an xml_node and a memory_pool through public inheritance. + //! Use parse() function to build a DOM tree from a zero-terminated XML text string. + //! parse() function allocates memory for nodes and attributes by using functions of xml_document, + //! which are inherited from memory_pool. + //! To access root node of the document, use the document itself, as if it was an xml_node. + //! \param Ch Character type to use. + template + class xml_document: public xml_node, public memory_pool + { + + public: + + //! Constructs empty XML document + xml_document() + : xml_node(node_document) + { + } + + //! Parses zero-terminated XML string according to given flags. + //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. + //! The string must persist for the lifetime of the document. + //! In case of error, rapidxml::parse_error exception will be thrown. + //!

+ //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. + //! Make sure that data is zero-terminated. + //!

+ //! Document can be parsed into multiple times. + //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. + //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. + template + void parse(Ch *text) + { + assert(text); + + // Remove current contents + this->remove_all_nodes(); + this->remove_all_attributes(); + + // Parse BOM, if any + parse_bom(text); + + // Parse children + while (1) + { + // Skip whitespace before node + skip(text); + if (*text == 0) + break; + + // Parse and append new child + if (*text == Ch('<')) + { + ++text; // Skip '<' + if (xml_node *node = parse_node(text)) + this->append_node(node); + } + else + RAPIDXML_PARSE_ERROR("expected <", text); + } + + } + + //! Clears the document by deleting all nodes and clearing the memory pool. + //! All nodes owned by document pool are destroyed. + void clear() + { + this->remove_all_nodes(); + this->remove_all_attributes(); + memory_pool::clear(); + } + + private: + + /////////////////////////////////////////////////////////////////////// + // Internal character utility functions + + // Detect whitespace character + struct whitespace_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_whitespace[static_cast(ch)]; + } + }; + + // Detect node name character + struct node_name_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_node_name[static_cast(ch)]; + } + }; + + // Detect attribute name character + struct attribute_name_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_attribute_name[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) + struct text_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_no_ws_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_with_ws_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast(ch)]; + } + }; + + // Detect attribute value character + template + struct attribute_value_pred + { + static unsigned char test(Ch ch) + { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Detect attribute value character + template + struct attribute_value_pure_pred + { + static unsigned char test(Ch ch) + { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Insert coded character, using UTF8 or 8-bit ASCII + template + static void insert_coded_character(Ch *&text, unsigned long code) + { + if (Flags & parse_no_utf8) + { + // Insert 8-bit ASCII character + // Todo: possibly verify that code is less than 256 and use replacement char otherwise? + text[0] = static_cast(code); + text += 1; + } + else + { + // Insert UTF8 sequence + if (code < 0x80) // 1 byte sequence + { + text[0] = static_cast(code); + text += 1; + } + else if (code < 0x800) // 2 byte sequence + { + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xC0); + text += 2; + } + else if (code < 0x10000) // 3 byte sequence + { + text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xE0); + text += 3; + } + else if (code < 0x110000) // 4 byte sequence + { + text[3] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xF0); + text += 4; + } + else // Invalid, only codes up to 0x10FFFF are allowed in Unicode + { + RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); + } + } + } + + // Skip characters until predicate evaluates to true + template + static void skip(Ch *&text) + { + Ch *tmp = text; + while (StopPred::test(*tmp)) + ++tmp; + text = tmp; + } + + // Skip characters until predicate evaluates to true while doing the following: + // - replacing XML character entity references with proper characters (' & " < > &#...;) + // - condensing whitespace sequences to single space character + template + static Ch *skip_and_expand_character_refs(Ch *&text) + { + // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip + if (Flags & parse_no_entity_translation && + !(Flags & parse_normalize_whitespace) && + !(Flags & parse_trim_whitespace)) + { + skip(text); + return text; + } + + // Use simple skip until first modification is detected + skip(text); + + // Use translation skip + Ch *src = text; + Ch *dest = src; + while (StopPred::test(*src)) + { + // If entity translation is enabled + if (!(Flags & parse_no_entity_translation)) + { + // Test if replacement is needed + if (src[0] == Ch('&')) + { + switch (src[1]) + { + + // & ' + case Ch('a'): + if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) + { + *dest = Ch('&'); + ++dest; + src += 5; + continue; + } + if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';')) + { + *dest = Ch('\''); + ++dest; + src += 6; + continue; + } + break; + + // " + case Ch('q'): + if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';')) + { + *dest = Ch('"'); + ++dest; + src += 6; + continue; + } + break; + + // > + case Ch('g'): + if (src[2] == Ch('t') && src[3] == Ch(';')) + { + *dest = Ch('>'); + ++dest; + src += 4; + continue; + } + break; + + // < + case Ch('l'): + if (src[2] == Ch('t') && src[3] == Ch(';')) + { + *dest = Ch('<'); + ++dest; + src += 4; + continue; + } + break; + + // &#...; - assumes ASCII + case Ch('#'): + if (src[2] == Ch('x')) + { + unsigned long code = 0; + src += 3; // Skip &#x + while (1) + { + unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) + break; + code = code * 16 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } + else + { + unsigned long code = 0; + src += 2; // Skip &# + while (1) + { + unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) + break; + code = code * 10 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } + if (*src == Ch(';')) + ++src; + else + RAPIDXML_PARSE_ERROR("expected ;", src); + continue; + + // Something else + default: + // Ignore, just copy '&' verbatim + break; + + } + } + } + + // If whitespace condensing is enabled + if (Flags & parse_normalize_whitespace) + { + // Test if condensing is needed + if (whitespace_pred::test(*src)) + { + *dest = Ch(' '); ++dest; // Put single space in dest + ++src; // Skip first whitespace char + // Skip remaining whitespace chars + while (whitespace_pred::test(*src)) + ++src; + continue; + } + } + + // No replacement, only copy character + *dest++ = *src++; + + } + + // Return new end + text = src; + return dest; + + } + + /////////////////////////////////////////////////////////////////////// + // Internal parsing functions + + // Parse BOM, if any + template + void parse_bom(Ch *&text) + { + // UTF-8? + if (static_cast(text[0]) == 0xEF && + static_cast(text[1]) == 0xBB && + static_cast(text[2]) == 0xBF) + { + text += 3; // Skup utf-8 bom + } + } + + // Parse XML declaration ( + xml_node *parse_xml_declaration(Ch *&text) + { + // If parsing of declaration is disabled + if (!(Flags & parse_declaration_node)) + { + // Skip until end of declaration + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + + // Create declaration + xml_node *declaration = this->allocate_node(node_declaration); + + // Skip whitespace before attributes or ?> + skip(text); + + // Parse declaration attributes + parse_node_attributes(text, declaration); + + // Skip ?> + if (text[0] != Ch('?') || text[1] != Ch('>')) + RAPIDXML_PARSE_ERROR("expected ?>", text); + text += 2; + + return declaration; + } + + // Parse XML comment (' + return 0; // Do not produce comment node + } + + // Remember value start + Ch *value = text; + + // Skip until end of comment + while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create comment node + xml_node *comment = this->allocate_node(node_comment); + comment->value(value, text - value); + + // Place zero terminator after comment value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 3; // Skip '-->' + return comment; + } + + // Parse DOCTYPE + template + xml_node *parse_doctype(Ch *&text) + { + // Remember value start + Ch *value = text; + + // Skip to > + while (*text != Ch('>')) + { + // Determine character type + switch (*text) + { + + // If '[' encountered, scan for matching ending ']' using naive algorithm with depth + // This works for all W3C test files except for 2 most wicked + case Ch('['): + { + ++text; // Skip '[' + int depth = 1; + while (depth > 0) + { + switch (*text) + { + case Ch('['): ++depth; break; + case Ch(']'): --depth; break; + case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text); + } + ++text; + } + break; + } + + // Error on end of text + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Other character, skip it + default: + ++text; + + } + } + + // If DOCTYPE nodes enabled + if (Flags & parse_doctype_node) + { + // Create a new doctype node + xml_node *doctype = this->allocate_node(node_doctype); + doctype->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 1; // skip '>' + return doctype; + } + else + { + text += 1; // skip '>' + return 0; + } + + } + + // Parse PI + template + xml_node *parse_pi(Ch *&text) + { + // If creation of PI nodes is enabled + if (Flags & parse_pi_nodes) + { + // Create pi node + xml_node *pi = this->allocate_node(node_pi); + + // Extract PI target name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected PI target", text); + pi->name(name, text - name); + + // Skip whitespace between pi target and pi + skip(text); + + // Remember start of pi + Ch *value = text; + + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Set pi value (verbatim, no entity expansion or whitespace normalization) + pi->value(value, text - value); + + // Place zero terminator after name and value + if (!(Flags & parse_no_string_terminators)) + { + pi->name()[pi->name_size()] = Ch('\0'); + pi->value()[pi->value_size()] = Ch('\0'); + } + + text += 2; // Skip '?>' + return pi; + } + else + { + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + } + + // Parse and append data + // Return character that ends data. + // This is necessary because this character might have been overwritten by a terminating 0 + template + Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) + { + // Backup to contents start if whitespace trimming is disabled + if (!(Flags & parse_trim_whitespace)) + text = contents_start; + + // Skip until end of data + Ch *value = text, *end; + if (Flags & parse_normalize_whitespace) + end = skip_and_expand_character_refs(text); + else + end = skip_and_expand_character_refs(text); + + // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > + if (Flags & parse_trim_whitespace) + { + if (Flags & parse_normalize_whitespace) + { + // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end + if (*(end - 1) == Ch(' ')) + --end; + } + else + { + // Backup until non-whitespace character is found + while (whitespace_pred::test(*(end - 1))) + --end; + } + } + + // If characters are still left between end and value (this test is only necessary if normalization is enabled) + // Create new data node + if (!(Flags & parse_no_data_nodes)) + { + xml_node *data = this->allocate_node(node_data); + data->value(value, end - value); + node->append_node(data); + } + + // Add data to parent node if no data exists yet + if (!(Flags & parse_no_element_values)) + if (*node->value() == Ch('\0')) + node->value(value, end - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + { + Ch ch = *text; + *end = Ch('\0'); + return ch; // Return character that ends data; this is required because zero terminator overwritten it + } + + // Return character that ends data + return *text; + } + + // Parse CDATA + template + xml_node *parse_cdata(Ch *&text) + { + // If CDATA is disabled + if (Flags & parse_no_data_nodes) + { + // Skip until end of cdata + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 3; // Skip ]]> + return 0; // Do not produce CDATA node + } + + // Skip until end of cdata + Ch *value = text; + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create new cdata node + xml_node *cdata = this->allocate_node(node_cdata); + cdata->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 3; // Skip ]]> + return cdata; + } + + // Parse element node + template + xml_node *parse_element(Ch *&text) + { + // Create element node + xml_node *element = this->allocate_node(node_element); + + // Extract element name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected element name", text); + element->name(name, text - name); + + // Skip whitespace between element name and attributes or > + skip(text); + + // Parse attributes, if any + parse_node_attributes(text, element); + + // Determine ending type + if (*text == Ch('>')) + { + ++text; + parse_node_contents(text, element); + } + else if (*text == Ch('/')) + { + ++text; + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; + } + else + RAPIDXML_PARSE_ERROR("expected >", text); + + // Place zero terminator after name + if (!(Flags & parse_no_string_terminators)) + element->name()[element->name_size()] = Ch('\0'); + + // Return parsed element + return element; + } + + // Determine node type, and parse it + template + xml_node *parse_node(Ch *&text) + { + // Parse proper node type + switch (text[0]) + { + + // <... + default: + // Parse and append element node + return parse_element(text); + + // (text); + } + else + { + // Parse PI + return parse_pi(text); + } + + // (text); + } + break; + + // (text); + } + break; + + // (text); + } + + } // switch + + // Attempt to skip other, unrecognized node types starting with ')) + { + if (*text == 0) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + ++text; // Skip '>' + return 0; // No node recognized + + } + } + + // Parse contents of the node - children, data etc. + template + void parse_node_contents(Ch *&text, xml_node *node) + { + // For all children and text + while (1) + { + // Skip whitespace between > and node contents + Ch *contents_start = text; // Store start of node contents before whitespace is skipped + skip(text); + Ch next_char = *text; + + // After data nodes, instead of continuing the loop, control jumps here. + // This is because zero termination inside parse_and_append_data() function + // would wreak havoc with the above code. + // Also, skipping whitespace after data nodes is unnecessary. + after_data_node: + + // Determine what comes next: node closing, child node, data node, or 0? + switch (next_char) + { + + // Node closing or child node + case Ch('<'): + if (text[1] == Ch('/')) + { + // Node closing + text += 2; // Skip '(text); + if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true)) + RAPIDXML_PARSE_ERROR("invalid closing tag name", text); + } + else + { + // No validation, just skip name + skip(text); + } + // Skip remaining whitespace after node name + skip(text); + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; // Skip '>' + return; // Node closed, finished parsing contents + } + else + { + // Child node + ++text; // Skip '<' + if (xml_node *child = parse_node(text)) + node->append_node(child); + } + break; + + // End of data - error + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Data node + default: + next_char = parse_and_append_data(node, text, contents_start); + goto after_data_node; // Bypass regular processing after data nodes + + } + } + } + + // Parse XML attributes of the node + template + void parse_node_attributes(Ch *&text, xml_node *node) + { + // For all attributes + while (attribute_name_pred::test(*text)) + { + // Extract attribute name + Ch *name = text; + ++text; // Skip first character of attribute name + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected attribute name", name); + + // Create new attribute + xml_attribute *attribute = this->allocate_attribute(); + attribute->name(name, text - name); + node->append_attribute(attribute); + + // Skip whitespace after attribute name + skip(text); + + // Skip = + if (*text != Ch('=')) + RAPIDXML_PARSE_ERROR("expected =", text); + ++text; + + // Add terminating zero after name + if (!(Flags & parse_no_string_terminators)) + attribute->name()[attribute->name_size()] = 0; + + // Skip whitespace after = + skip(text); + + // Skip quote and remember if it was ' or " + Ch quote = *text; + if (quote != Ch('\'') && quote != Ch('"')) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; + + // Extract attribute value and expand char refs in it + Ch *value = text, *end; + const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes + if (quote == Ch('\'')) + end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); + else + end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); + + // Set attribute value + attribute->value(value, end - value); + + // Make sure that end quote is present + if (*text != quote) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; // Skip quote + + // Add terminating zero after value + if (!(Flags & parse_no_string_terminators)) + attribute->value()[attribute->value_size()] = 0; + + // Skip whitespace after attribute value + skip(text); + } + } + + }; + + //! \cond internal + namespace internal + { + + // Whitespace (space \n \r \t) + template + const unsigned char lookup_tables::lookup_whitespace[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F + }; + + // Node name (anything but space \n \r \t / > ? \0) + template + const unsigned char lookup_tables::lookup_node_name[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) (anything but < \0) + template + const unsigned char lookup_tables::lookup_text[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled + // (anything but < \0 &) + template + const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled + // (anything but < \0 & space \n \r \t) + template + const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute name (anything but space \n \r \t / < > = ? ! \0) + template + const unsigned char lookup_tables::lookup_attribute_name[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with single quote (anything but ' \0) + template + const unsigned char lookup_tables::lookup_attribute_data_1[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with single quote that does not require processing (anything but ' \0 &) + template + const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with double quote (anything but " \0) + template + const unsigned char lookup_tables::lookup_attribute_data_2[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with double quote that does not require processing (anything but " \0 &) + template + const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Digits (dec and hex, 255 denotes end of numeric character reference) + template + const unsigned char lookup_tables::lookup_digits[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3 + 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5 + 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F + }; + + // Upper case conversion + template + const unsigned char lookup_tables::lookup_upcase[256] = + { + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 + 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7 + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8 + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9 + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F + }; + } + //! \endcond + +} + +// Undefine internal macros +#undef RAPIDXML_PARSE_ERROR + +// On MSVC, restore warnings state +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +#endif diff --git a/ext/rapidxml/rapidxml_iterators.hpp b/ext/rapidxml/rapidxml_iterators.hpp new file mode 100644 index 0000000000..52ebc298aa --- /dev/null +++ b/ext/rapidxml/rapidxml_iterators.hpp @@ -0,0 +1,174 @@ +#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED +#define RAPIDXML_ITERATORS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_iterators.hpp This file contains rapidxml iterators + +#include "rapidxml.hpp" + +namespace rapidxml +{ + + //! Iterator of child nodes of xml_node + template + class node_iterator + { + + public: + + typedef typename xml_node value_type; + typedef typename xml_node &reference; + typedef typename xml_node *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + node_iterator() + : m_node(0) + { + } + + node_iterator(xml_node *node) + : m_node(node->first_node()) + { + } + + reference operator *() const + { + assert(m_node); + return *m_node; + } + + pointer operator->() const + { + assert(m_node); + return m_node; + } + + node_iterator& operator++() + { + assert(m_node); + m_node = m_node->next_sibling(); + return *this; + } + + node_iterator operator++(int) + { + node_iterator tmp = *this; + ++this; + return tmp; + } + + node_iterator& operator--() + { + assert(m_node && m_node->previous_sibling()); + m_node = m_node->previous_sibling(); + return *this; + } + + node_iterator operator--(int) + { + node_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const node_iterator &rhs) + { + return m_node == rhs.m_node; + } + + bool operator !=(const node_iterator &rhs) + { + return m_node != rhs.m_node; + } + + private: + + xml_node *m_node; + + }; + + //! Iterator of child attributes of xml_node + template + class attribute_iterator + { + + public: + + typedef typename xml_attribute value_type; + typedef typename xml_attribute &reference; + typedef typename xml_attribute *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + attribute_iterator() + : m_attribute(0) + { + } + + attribute_iterator(xml_node *node) + : m_attribute(node->first_attribute()) + { + } + + reference operator *() const + { + assert(m_attribute); + return *m_attribute; + } + + pointer operator->() const + { + assert(m_attribute); + return m_attribute; + } + + attribute_iterator& operator++() + { + assert(m_attribute); + m_attribute = m_attribute->next_attribute(); + return *this; + } + + attribute_iterator operator++(int) + { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + attribute_iterator& operator--() + { + assert(m_attribute && m_attribute->previous_attribute()); + m_attribute = m_attribute->previous_attribute(); + return *this; + } + + attribute_iterator operator--(int) + { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const attribute_iterator &rhs) + { + return m_attribute == rhs.m_attribute; + } + + bool operator !=(const attribute_iterator &rhs) + { + return m_attribute != rhs.m_attribute; + } + + private: + + xml_attribute *m_attribute; + + }; + +} + +#endif diff --git a/ext/rapidxml/rapidxml_print.hpp b/ext/rapidxml/rapidxml_print.hpp new file mode 100644 index 0000000000..0ae2b14faa --- /dev/null +++ b/ext/rapidxml/rapidxml_print.hpp @@ -0,0 +1,421 @@ +#ifndef RAPIDXML_PRINT_HPP_INCLUDED +#define RAPIDXML_PRINT_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_print.hpp This file contains rapidxml printer implementation + +#include "rapidxml.hpp" + +// Only include streams if not disabled +#ifndef RAPIDXML_NO_STREAMS + #include + #include +#endif + +namespace rapidxml +{ + + /////////////////////////////////////////////////////////////////////// + // Printing flags + + const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. + + /////////////////////////////////////////////////////////////////////// + // Internal + + //! \cond internal + namespace internal + { + + /////////////////////////////////////////////////////////////////////////// + // Internal character operations + + // Copy characters from given range to given output iterator + template + inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) + { + while (begin != end) + *out++ = *begin++; + return out; + } + + // Copy characters from given range to given output iterator and expand + // characters into references (< > ' " &) + template + inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out) + { + while (begin != end) + { + if (*begin == noexpand) + { + *out++ = *begin; // No expansion, copy character + } + else + { + switch (*begin) + { + case Ch('<'): + *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('>'): + *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('\''): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';'); + break; + case Ch('"'): + *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('&'): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); + break; + default: + *out++ = *begin; // No expansion, copy character + } + } + ++begin; // Step to next character + } + return out; + } + + // Fill given output iterator with repetitions of the same character + template + inline OutIt fill_chars(OutIt out, int n, Ch ch) + { + for (int i = 0; i < n; ++i) + *out++ = ch; + return out; + } + + // Find character + template + inline bool find_char(const Ch *begin, const Ch *end) + { + while (begin != end) + if (*begin++ == ch) + return true; + return false; + } + + /////////////////////////////////////////////////////////////////////////// + // Internal printing operations + + // Print node + template + inline OutIt print_node(OutIt out, const xml_node *node, int flags, int indent) + { + // Print proper node type + switch (node->type()) + { + + // Document + case node_document: + out = print_children(out, node, flags, indent); + break; + + // Element + case node_element: + out = print_element_node(out, node, flags, indent); + break; + + // Data + case node_data: + out = print_data_node(out, node, flags, indent); + break; + + // CDATA + case node_cdata: + out = print_cdata_node(out, node, flags, indent); + break; + + // Declaration + case node_declaration: + out = print_declaration_node(out, node, flags, indent); + break; + + // Comment + case node_comment: + out = print_comment_node(out, node, flags, indent); + break; + + // Doctype + case node_doctype: + out = print_doctype_node(out, node, flags, indent); + break; + + // Pi + case node_pi: + out = print_pi_node(out, node, flags, indent); + break; + + // Unknown + default: + assert(0); + break; + } + + // If indenting not disabled, add line break after node + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + + // Return modified iterator + return out; + } + + // Print children of the node + template + inline OutIt print_children(OutIt out, const xml_node *node, int flags, int indent) + { + for (xml_node *child = node->first_node(); child; child = child->next_sibling()) + out = print_node(out, child, flags, indent); + return out; + } + + // Print attributes of the node + template + inline OutIt print_attributes(OutIt out, const xml_node *node, int flags) + { + for (xml_attribute *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute()) + { + if (attribute->name() && attribute->value()) + { + // Print attribute name + *out = Ch(' '), ++out; + out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out); + *out = Ch('='), ++out; + // Print attribute value using appropriate quote type + if (find_char(attribute->value(), attribute->value() + attribute->value_size())) + { + *out = Ch('\''), ++out; + out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out); + *out = Ch('\''), ++out; + } + else + { + *out = Ch('"'), ++out; + out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out); + *out = Ch('"'), ++out; + } + } + } + return out; + } + + // Print data node + template + inline OutIt print_data_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_data); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); + return out; + } + + // Print data node + template + inline OutIt print_cdata_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_cdata); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'); ++out; + *out = Ch('!'); ++out; + *out = Ch('['); ++out; + *out = Ch('C'); ++out; + *out = Ch('D'); ++out; + *out = Ch('A'); ++out; + *out = Ch('T'); ++out; + *out = Ch('A'); ++out; + *out = Ch('['); ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch(']'); ++out; + *out = Ch(']'); ++out; + *out = Ch('>'); ++out; + return out; + } + + // Print element node + template + inline OutIt print_element_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_element); + + // Print element name and attributes, if any + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + out = print_attributes(out, node, flags); + + // If node is childless + if (node->value_size() == 0 && !node->first_node()) + { + // Print childless node tag ending + *out = Ch('/'), ++out; + *out = Ch('>'), ++out; + } + else + { + // Print normal node tag ending + *out = Ch('>'), ++out; + + // Test if node contains a single data node only (and no other nodes) + xml_node *child = node->first_node(); + if (!child) + { + // If node has no children, only print its value without indenting + out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); + } + else if (child->next_sibling() == 0 && child->type() == node_data) + { + // If node has a sole data child, only print its value without indenting + out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out); + } + else + { + // Print all children with full indenting + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + out = print_children(out, node, flags, indent + 1); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + } + + // Print node end + *out = Ch('<'), ++out; + *out = Ch('/'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch('>'), ++out; + } + return out; + } + + // Print declaration node + template + inline OutIt print_declaration_node(OutIt out, const xml_node *node, int flags, int indent) + { + // Print declaration start + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + *out = Ch('x'), ++out; + *out = Ch('m'), ++out; + *out = Ch('l'), ++out; + + // Print attributes + out = print_attributes(out, node, flags); + + // Print declaration end + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + + return out; + } + + // Print comment node + template + inline OutIt print_comment_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_comment); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + *out = Ch('>'), ++out; + return out; + } + + // Print doctype node + template + inline OutIt print_doctype_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_doctype); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('D'), ++out; + *out = Ch('O'), ++out; + *out = Ch('C'), ++out; + *out = Ch('T'), ++out; + *out = Ch('Y'), ++out; + *out = Ch('P'), ++out; + *out = Ch('E'), ++out; + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('>'), ++out; + return out; + } + + // Print pi node + template + inline OutIt print_pi_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_pi); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + return out; + } + + } + //! \endcond + + /////////////////////////////////////////////////////////////////////////// + // Printing + + //! Prints XML to given output iterator. + //! \param out Output iterator to print to. + //! \param node Node to be printed. Pass xml_document to print entire document. + //! \param flags Flags controlling how XML is printed. + //! \return Output iterator pointing to position immediately after last character of printed text. + template + inline OutIt print(OutIt out, const xml_node &node, int flags = 0) + { + return internal::print_node(out, &node, flags, 0); + } + +#ifndef RAPIDXML_NO_STREAMS + + //! Prints XML to given output stream. + //! \param out Output stream to print to. + //! \param node Node to be printed. Pass xml_document to print entire document. + //! \param flags Flags controlling how XML is printed. + //! \return Output stream. + template + inline std::basic_ostream &print(std::basic_ostream &out, const xml_node &node, int flags = 0) + { + print(std::ostream_iterator(out), node, flags); + return out; + } + + //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. + //! \param out Output stream to print to. + //! \param node Node to be printed. + //! \return Output stream. + template + inline std::basic_ostream &operator <<(std::basic_ostream &out, const xml_node &node) + { + return print(out, node); + } + +#endif + +} + +#endif diff --git a/ext/rapidxml/rapidxml_utils.hpp b/ext/rapidxml/rapidxml_utils.hpp new file mode 100644 index 0000000000..37c29535f4 --- /dev/null +++ b/ext/rapidxml/rapidxml_utils.hpp @@ -0,0 +1,122 @@ +#ifndef RAPIDXML_UTILS_HPP_INCLUDED +#define RAPIDXML_UTILS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful +//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. + +#include "rapidxml.hpp" +#include +#include +#include +#include + +namespace rapidxml +{ + + //! Represents data loaded from a file + template + class file + { + + public: + + //! Loads file into the memory. Data will be automatically destroyed by the destructor. + //! \param filename Filename to load. + file(const char *filename) + { + using namespace std; + + // Open stream + basic_ifstream stream(filename, ios::binary); + if (!stream) + throw runtime_error(string("cannot open file ") + filename); + stream.unsetf(ios::skipws); + + // Determine stream size + stream.seekg(0, ios::end); + size_t size = stream.tellg(); + stream.seekg(0); + + // Load data and add terminating 0 + m_data.resize(size + 1); + stream.read(&m_data.front(), static_cast(size)); + m_data[size] = 0; + } + + //! Loads file into the memory. Data will be automatically destroyed by the destructor + //! \param stream Stream to load from + file(std::basic_istream &stream) + { + using namespace std; + + // Load data and add terminating 0 + stream.unsetf(ios::skipws); + m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); + if (stream.fail() || stream.bad()) + throw runtime_error("error reading stream"); + m_data.push_back(0); + } + + //! Gets file data. + //! \return Pointer to data of file. + Ch *data() + { + return &m_data.front(); + } + + //! Gets file data. + //! \return Pointer to data of file. + const Ch *data() const + { + return &m_data.front(); + } + + //! Gets file data size. + //! \return Size of file data, in characters. + std::size_t size() const + { + return m_data.size(); + } + + private: + + std::vector m_data; // File data + + }; + + //! Counts children of node. Time complexity is O(n). + //! \return Number of children of node + template + inline std::size_t count_children(xml_node *node) + { + xml_node *child = node->first_node(); + std::size_t count = 0; + while (child) + { + ++count; + child = child->next_sibling(); + } + return count; + } + + //! Counts attributes of node. Time complexity is O(n). + //! \return Number of attributes of node + template + inline std::size_t count_attributes(xml_node *node) + { + xml_attribute *attr = node->first_attribute(); + std::size_t count = 0; + while (attr) + { + ++count; + attr = attr->next_attribute(); + } + return count; + } + +} + +#endif diff --git a/ext/sha1/CMakeLists.txt b/ext/sha1/CMakeLists.txt new file mode 100644 index 0000000000..b1ac75827e --- /dev/null +++ b/ext/sha1/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.6) + +#if(UNIX) +add_definitions(-PIC) +add_definitions(-g) +add_definitions(-O2) +add_definitions(-Wall) +#endif(UNIX) + +add_library(sha1 sha1.cpp) diff --git a/ext/sha1/SHA1.cpp b/ext/sha1/SHA1.cpp new file mode 100644 index 0000000000..f9c5cdf84c --- /dev/null +++ b/ext/sha1/SHA1.cpp @@ -0,0 +1,259 @@ +/* + 100% free public domain implementation of the SHA-1 algorithm + by Dominik Reichl + Web: http://www.dominik-reichl.de/ + + See header file for version history and test vectors. +*/ + +// If compiling with MFC, you might want to add #include "StdAfx.h" + +#define _CRT_SECURE_NO_WARNINGS +#include "SHA1.h" + +#ifdef SHA1_UTILITY_FUNCTIONS +#define SHA1_MAX_FILE_BUFFER (32 * 20 * 820) +#endif + +// Rotate _val32 by _nBits bits to the left +#ifndef ROL32 +#ifdef _MSC_VER +#define ROL32(_val32,_nBits) _rotl(_val32,_nBits) +#else +#define ROL32(_val32,_nBits) (((_val32)<<(_nBits))|((_val32)>>(32-(_nBits)))) +#endif +#endif + +#ifdef SHA1_LITTLE_ENDIAN +#define SHABLK0(i) (m_block->l[i] = \ + (ROL32(m_block->l[i],24) & 0xFF00FF00) | (ROL32(m_block->l[i],8) & 0x00FF00FF)) +#else +#define SHABLK0(i) (m_block->l[i]) +#endif + +#define SHABLK(i) (m_block->l[i&15] = ROL32(m_block->l[(i+13)&15] ^ \ + m_block->l[(i+8)&15] ^ m_block->l[(i+2)&15] ^ m_block->l[i&15],1)) + +// SHA-1 rounds +#define _R0(v,w,x,y,z,i) {z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5);w=ROL32(w,30);} +#define _R1(v,w,x,y,z,i) {z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5);w=ROL32(w,30);} +#define _R2(v,w,x,y,z,i) {z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5);w=ROL32(w,30);} +#define _R3(v,w,x,y,z,i) {z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5);w=ROL32(w,30);} +#define _R4(v,w,x,y,z,i) {z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5);w=ROL32(w,30);} + +#ifdef _MSC_VER +#pragma warning(push) +// Disable compiler warning 'Conditional expression is constant' +#pragma warning(disable: 4127) +#endif + +CSHA1::CSHA1() +{ + m_block = (SHA1_WORKSPACE_BLOCK*)m_workspace; + + Reset(); +} + +CSHA1::~CSHA1() +{ + Reset(); +} + +void CSHA1::Reset() +{ + // SHA1 initialization constants + m_state[0] = 0x67452301; + m_state[1] = 0xEFCDAB89; + m_state[2] = 0x98BADCFE; + m_state[3] = 0x10325476; + m_state[4] = 0xC3D2E1F0; + + m_count[0] = 0; + m_count[1] = 0; +} + +void CSHA1::Transform(UINT_32* pState, const UINT_8* pBuffer) +{ + UINT_32 a = pState[0], b = pState[1], c = pState[2], d = pState[3], e = pState[4]; + + memcpy(m_block, pBuffer, 64); + + // 4 rounds of 20 operations each, loop unrolled + _R0(a,b,c,d,e, 0); _R0(e,a,b,c,d, 1); _R0(d,e,a,b,c, 2); _R0(c,d,e,a,b, 3); + _R0(b,c,d,e,a, 4); _R0(a,b,c,d,e, 5); _R0(e,a,b,c,d, 6); _R0(d,e,a,b,c, 7); + _R0(c,d,e,a,b, 8); _R0(b,c,d,e,a, 9); _R0(a,b,c,d,e,10); _R0(e,a,b,c,d,11); + _R0(d,e,a,b,c,12); _R0(c,d,e,a,b,13); _R0(b,c,d,e,a,14); _R0(a,b,c,d,e,15); + _R1(e,a,b,c,d,16); _R1(d,e,a,b,c,17); _R1(c,d,e,a,b,18); _R1(b,c,d,e,a,19); + _R2(a,b,c,d,e,20); _R2(e,a,b,c,d,21); _R2(d,e,a,b,c,22); _R2(c,d,e,a,b,23); + _R2(b,c,d,e,a,24); _R2(a,b,c,d,e,25); _R2(e,a,b,c,d,26); _R2(d,e,a,b,c,27); + _R2(c,d,e,a,b,28); _R2(b,c,d,e,a,29); _R2(a,b,c,d,e,30); _R2(e,a,b,c,d,31); + _R2(d,e,a,b,c,32); _R2(c,d,e,a,b,33); _R2(b,c,d,e,a,34); _R2(a,b,c,d,e,35); + _R2(e,a,b,c,d,36); _R2(d,e,a,b,c,37); _R2(c,d,e,a,b,38); _R2(b,c,d,e,a,39); + _R3(a,b,c,d,e,40); _R3(e,a,b,c,d,41); _R3(d,e,a,b,c,42); _R3(c,d,e,a,b,43); + _R3(b,c,d,e,a,44); _R3(a,b,c,d,e,45); _R3(e,a,b,c,d,46); _R3(d,e,a,b,c,47); + _R3(c,d,e,a,b,48); _R3(b,c,d,e,a,49); _R3(a,b,c,d,e,50); _R3(e,a,b,c,d,51); + _R3(d,e,a,b,c,52); _R3(c,d,e,a,b,53); _R3(b,c,d,e,a,54); _R3(a,b,c,d,e,55); + _R3(e,a,b,c,d,56); _R3(d,e,a,b,c,57); _R3(c,d,e,a,b,58); _R3(b,c,d,e,a,59); + _R4(a,b,c,d,e,60); _R4(e,a,b,c,d,61); _R4(d,e,a,b,c,62); _R4(c,d,e,a,b,63); + _R4(b,c,d,e,a,64); _R4(a,b,c,d,e,65); _R4(e,a,b,c,d,66); _R4(d,e,a,b,c,67); + _R4(c,d,e,a,b,68); _R4(b,c,d,e,a,69); _R4(a,b,c,d,e,70); _R4(e,a,b,c,d,71); + _R4(d,e,a,b,c,72); _R4(c,d,e,a,b,73); _R4(b,c,d,e,a,74); _R4(a,b,c,d,e,75); + _R4(e,a,b,c,d,76); _R4(d,e,a,b,c,77); _R4(c,d,e,a,b,78); _R4(b,c,d,e,a,79); + + // Add the working vars back into state + pState[0] += a; + pState[1] += b; + pState[2] += c; + pState[3] += d; + pState[4] += e; + + // Wipe variables +#ifdef SHA1_WIPE_VARIABLES + a = b = c = d = e = 0; +#endif +} + +void CSHA1::Update(const UINT_8* pbData, UINT_32 uLen) +{ + UINT_32 j = ((m_count[0] >> 3) & 0x3F); + + if((m_count[0] += (uLen << 3)) < (uLen << 3)) + ++m_count[1]; // Overflow + + m_count[1] += (uLen >> 29); + + UINT_32 i; + if((j + uLen) > 63) + { + i = 64 - j; + memcpy(&m_buffer[j], pbData, i); + Transform(m_state, m_buffer); + + for( ; (i + 63) < uLen; i += 64) + Transform(m_state, &pbData[i]); + + j = 0; + } + else i = 0; + + if((uLen - i) != 0) + memcpy(&m_buffer[j], &pbData[i], uLen - i); +} + +#ifdef SHA1_UTILITY_FUNCTIONS +bool CSHA1::HashFile(const TCHAR* tszFileName) +{ + if(tszFileName == NULL) return false; + + FILE* fpIn = _tfopen(tszFileName, _T("rb")); + if(fpIn == NULL) return false; + + UINT_8* pbData = new UINT_8[SHA1_MAX_FILE_BUFFER]; + if(pbData == NULL) { fclose(fpIn); return false; } + + bool bSuccess = true; + while(true) + { + const size_t uRead = fread(pbData, 1, SHA1_MAX_FILE_BUFFER, fpIn); + + if(uRead > 0) + Update(pbData, static_cast(uRead)); + + if(uRead < SHA1_MAX_FILE_BUFFER) + { + if(feof(fpIn) == 0) bSuccess = false; + break; + } + } + + fclose(fpIn); + delete[] pbData; + return bSuccess; +} +#endif + +void CSHA1::Final() +{ + UINT_32 i; + + UINT_8 finalcount[8]; + for(i = 0; i < 8; ++i) + finalcount[i] = (UINT_8)((m_count[((i >= 4) ? 0 : 1)] + >> ((3 - (i & 3)) * 8) ) & 255); // Endian independent + + Update((UINT_8*)"\200", 1); + + while ((m_count[0] & 504) != 448) + Update((UINT_8*)"\0", 1); + + Update(finalcount, 8); // Cause a SHA1Transform() + + for(i = 0; i < 20; ++i) + m_digest[i] = (UINT_8)((m_state[i >> 2] >> ((3 - (i & 3)) * 8)) & 0xFF); + + // Wipe variables for security reasons +#ifdef SHA1_WIPE_VARIABLES + memset(m_buffer, 0, 64); + memset(m_state, 0, 20); + memset(m_count, 0, 8); + memset(finalcount, 0, 8); + Transform(m_state, m_buffer); +#endif +} + +#ifdef SHA1_UTILITY_FUNCTIONS +bool CSHA1::ReportHash(TCHAR* tszReport, REPORT_TYPE rtReportType) const +{ + if(tszReport == NULL) return false; + + TCHAR tszTemp[16]; + + if((rtReportType == REPORT_HEX) || (rtReportType == REPORT_HEX_SHORT)) + { + _sntprintf(tszTemp, 15, _T("%02X"), m_digest[0]); + _tcscpy(tszReport, tszTemp); + + const TCHAR* lpFmt = ((rtReportType == REPORT_HEX) ? _T(" %02X") : _T("%02X")); + for(size_t i = 1; i < 20; ++i) + { + _sntprintf(tszTemp, 15, lpFmt, m_digest[i]); + _tcscat(tszReport, tszTemp); + } + } + else if(rtReportType == REPORT_DIGIT) + { + _sntprintf(tszTemp, 15, _T("%u"), m_digest[0]); + _tcscpy(tszReport, tszTemp); + + for(size_t i = 1; i < 20; ++i) + { + _sntprintf(tszTemp, 15, _T(" %u"), m_digest[i]); + _tcscat(tszReport, tszTemp); + } + } + else return false; + + return true; +} +#endif + +#ifdef SHA1_STL_FUNCTIONS +bool CSHA1::ReportHashStl(std::basic_string& strOut, REPORT_TYPE rtReportType) const +{ + TCHAR tszOut[84]; + const bool bResult = ReportHash(tszOut, rtReportType); + if(bResult) strOut = tszOut; + return bResult; +} +#endif + +bool CSHA1::GetHash(UINT_8* pbDest20) const +{ + if(pbDest20 == NULL) return false; + memcpy(pbDest20, m_digest, 20); + return true; +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/ext/sha1/sha1.h b/ext/sha1/sha1.h new file mode 100644 index 0000000000..77f39e6699 --- /dev/null +++ b/ext/sha1/sha1.h @@ -0,0 +1,263 @@ +/* + 100% free public domain implementation of the SHA-1 algorithm + by Dominik Reichl + Web: http://www.dominik-reichl.de/ + + Version 1.9 - 2011-11-10 + - Added Unicode test vectors. + - Improved support for hashing files using the HashFile method that + are larger than 4 GB. + - Improved file hashing performance (by using a larger buffer). + - Disabled unnecessary compiler warnings. + - Internal variables are now private. + + Version 1.8 - 2009-03-16 + - Converted project files to Visual Studio 2008 format. + - Added Unicode support for HashFile utility method. + - Added support for hashing files using the HashFile method that are + larger than 2 GB. + - HashFile now returns an error code instead of copying an error + message into the output buffer. + - GetHash now returns an error code and validates the input parameter. + - Added ReportHashStl STL utility method. + - Added REPORT_HEX_SHORT reporting mode. + - Improved Linux compatibility of test program. + + Version 1.7 - 2006-12-21 + - Fixed buffer underrun warning that appeared when compiling with + Borland C Builder (thanks to Rex Bloom and Tim Gallagher for the + patch). + - Breaking change: ReportHash writes the final hash to the start + of the buffer, i.e. it's not appending it to the string anymore. + - Made some function parameters const. + - Added Visual Studio 2005 project files to demo project. + + Version 1.6 - 2005-02-07 (thanks to Howard Kapustein for patches) + - You can set the endianness in your files, no need to modify the + header file of the CSHA1 class anymore. + - Aligned data support. + - Made support/compilation of the utility functions (ReportHash and + HashFile) optional (useful when bytes count, for example in embedded + environments). + + Version 1.5 - 2005-01-01 + - 64-bit compiler compatibility added. + - Made variable wiping optional (define SHA1_WIPE_VARIABLES). + - Removed unnecessary variable initializations. + - ROL32 improvement for the Microsoft compiler (using _rotl). + + Version 1.4 - 2004-07-22 + - CSHA1 now compiles fine with GCC 3.3 under MacOS X (thanks to Larry + Hastings). + + Version 1.3 - 2003-08-17 + - Fixed a small memory bug and made a buffer array a class member to + ensure correct working when using multiple CSHA1 class instances at + one time. + + Version 1.2 - 2002-11-16 + - Borlands C++ compiler seems to have problems with string addition + using sprintf. Fixed the bug which caused the digest report function + not to work properly. CSHA1 is now Borland compatible. + + Version 1.1 - 2002-10-11 + - Removed two unnecessary header file includes and changed BOOL to + bool. Fixed some minor bugs in the web page contents. + + Version 1.0 - 2002-06-20 + - First official release. + + ================ Test Vectors ================ + + SHA1("abc" in ANSI) = + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + SHA1("abc" in Unicode LE) = + 9F04F41A 84851416 2050E3D6 8C1A7ABB 441DC2B5 + + SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + in ANSI) = + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + in Unicode LE) = + 51D7D876 9AC72C40 9C5B0E3F 69C60ADC 9A039014 + + SHA1(A million repetitions of "a" in ANSI) = + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + SHA1(A million repetitions of "a" in Unicode LE) = + C4609560 A108A0C6 26AA7F2B 38A65566 739353C5 +*/ + +#ifndef ___SHA1_HDR___ +#define ___SHA1_HDR___ + +#if !defined(SHA1_UTILITY_FUNCTIONS) && !defined(SHA1_NO_UTILITY_FUNCTIONS) +#define SHA1_UTILITY_FUNCTIONS +#endif + +#if !defined(SHA1_STL_FUNCTIONS) && !defined(SHA1_NO_STL_FUNCTIONS) +#define SHA1_STL_FUNCTIONS +#if !defined(SHA1_UTILITY_FUNCTIONS) +#error STL functions require SHA1_UTILITY_FUNCTIONS. +#endif +#endif + +#include + +#ifdef SHA1_UTILITY_FUNCTIONS +#include +#include +#endif + +#ifdef SHA1_STL_FUNCTIONS +#include +#endif + +#ifdef _MSC_VER +#include +#endif + +// You can define the endian mode in your files without modifying the SHA-1 +// source files. Just #define SHA1_LITTLE_ENDIAN or #define SHA1_BIG_ENDIAN +// in your files, before including the SHA1.h header file. If you don't +// define anything, the class defaults to little endian. +#if !defined(SHA1_LITTLE_ENDIAN) && !defined(SHA1_BIG_ENDIAN) +#define SHA1_LITTLE_ENDIAN +#endif + +// If you want variable wiping, #define SHA1_WIPE_VARIABLES, if not, +// #define SHA1_NO_WIPE_VARIABLES. If you don't define anything, it +// defaults to wiping. +#if !defined(SHA1_WIPE_VARIABLES) && !defined(SHA1_NO_WIPE_VARIABLES) +#define SHA1_WIPE_VARIABLES +#endif + +#if defined(SHA1_HAS_TCHAR) +#include +#else +#ifdef _MSC_VER +#include +#else +#ifndef TCHAR +#define TCHAR char +#endif +#ifndef _T +#define _T(__x) (__x) +#define _tmain main +#define _tprintf printf +#define _getts gets +#define _tcslen strlen +#define _tfopen fopen +#define _tcscpy strcpy +#define _tcscat strcat +#define _sntprintf snprintf +#endif +#endif +#endif + +/////////////////////////////////////////////////////////////////////////// +// Define variable types + +#ifndef UINT_8 +#ifdef _MSC_VER // Compiling with Microsoft compiler +#define UINT_8 unsigned __int8 +#else // !_MSC_VER +#define UINT_8 unsigned char +#endif // _MSC_VER +#endif + +#ifndef UINT_32 +#ifdef _MSC_VER // Compiling with Microsoft compiler +#define UINT_32 unsigned __int32 +#else // !_MSC_VER +#if (ULONG_MAX == 0xFFFFFFFF) +#define UINT_32 unsigned long +#else +#define UINT_32 unsigned int +#endif +#endif // _MSC_VER +#endif // UINT_32 + +#ifndef INT_64 +#ifdef _MSC_VER // Compiling with Microsoft compiler +#define INT_64 __int64 +#else // !_MSC_VER +#define INT_64 long long +#endif // _MSC_VER +#endif // INT_64 + +#ifndef UINT_64 +#ifdef _MSC_VER // Compiling with Microsoft compiler +#define UINT_64 unsigned __int64 +#else // !_MSC_VER +#define UINT_64 unsigned long long +#endif // _MSC_VER +#endif // UINT_64 + +/////////////////////////////////////////////////////////////////////////// +// Declare SHA-1 workspace + +typedef union +{ + UINT_8 c[64]; + UINT_32 l[16]; +} SHA1_WORKSPACE_BLOCK; + +class CSHA1 +{ +public: +#ifdef SHA1_UTILITY_FUNCTIONS + // Different formats for ReportHash + enum REPORT_TYPE + { + REPORT_HEX = 0, + REPORT_DIGIT = 1, + REPORT_HEX_SHORT = 2 + }; +#endif + + // Constructor and destructor + CSHA1(); + ~CSHA1(); + + void Reset(); + + // Hash in binary data and strings + void Update(const UINT_8* pbData, UINT_32 uLen); + +#ifdef SHA1_UTILITY_FUNCTIONS + // Hash in file contents + bool HashFile(const TCHAR* tszFileName); +#endif + + // Finalize hash, call before using ReportHash(Stl) + void Final(); + +#ifdef SHA1_UTILITY_FUNCTIONS + bool ReportHash(TCHAR* tszReport, REPORT_TYPE rtReportType = REPORT_HEX) const; +#endif + +#ifdef SHA1_STL_FUNCTIONS + bool ReportHashStl(std::basic_string& strOut, REPORT_TYPE rtReportType = + REPORT_HEX) const; +#endif + + // Get the raw message digest (20 bytes) + bool GetHash(UINT_8* pbDest20) const; + +private: + // Private SHA-1 transformation + void Transform(UINT_32* pState, const UINT_8* pBuffer); + + // Member variables + UINT_32 m_state[5]; + UINT_32 m_count[2]; + UINT_32 m_reserved0[1]; // Memory alignment padding + UINT_8 m_buffer[64]; + UINT_8 m_digest[20]; + UINT_32 m_reserved1[3]; // Memory alignment padding + + UINT_8 m_workspace[64]; + SHA1_WORKSPACE_BLOCK* m_block; // SHA1 pointer to the byte array above +}; + +#endif // ___SHA1_HDR___ diff --git a/ext/stb_vorbis/CMakeLists.txt b/ext/stb_vorbis/CMakeLists.txt new file mode 100644 index 0000000000..128e155afc --- /dev/null +++ b/ext/stb_vorbis/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.6) + +#if(UNIX) +add_definitions(-PIC) +add_definitions(-g) +add_definitions(-O2) +add_definitions(-Wall) +#endif(UNIX) + +add_library(stb_vorbis stb_vorbis.c) diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c new file mode 100644 index 0000000000..a51aecc5b7 --- /dev/null +++ b/ext/stb_vorbis/stb_vorbis.c @@ -0,0 +1,5045 @@ +// Ogg Vorbis I audio decoder -- version 0.99996 +// +// Written in April 2007 by Sean Barrett, sponsored by RAD Game Tools. +// +// Placed in the public domain April 2007 by the author: no copyright is +// claimed, and you may use it for any purpose you like. +// +// No warranty for any purpose is expressed or implied by the author (nor +// by RAD Game Tools). Report bugs and send enhancements to the author. +// +// Get the latest version and other information at: +// http://nothings.org/stb_vorbis/ + + +#pragma warning (disable:4996) + +// Todo: +// +// - seeking (note you can seek yourself using the pushdata API) +// +// Limitations: +// +// - floor 0 not supported (used in old ogg vorbis files) +// - lossless sample-truncation at beginning ignored +// - cannot concatenate multiple vorbis streams +// - sample positions are 32-bit, limiting seekable 192Khz +// files to around 6 hours (Ogg supports 64-bit) +// +// All of these limitations may be removed in future versions. + +#include "stb_vorbis.h" + + +#ifndef STB_VORBIS_HEADER_ONLY + +// global configuration settings (e.g. set these in the project/makefile), +// or just set them in this file at the top (although ideally the first few +// should be visible when the header file is compiled too, although it's not +// crucial) + +// STB_VORBIS_NO_PUSHDATA_API +// does not compile the code for the various stb_vorbis_*_pushdata() +// functions +// #define STB_VORBIS_NO_PUSHDATA_API + +// STB_VORBIS_NO_PULLDATA_API +// does not compile the code for the non-pushdata APIs +// #define STB_VORBIS_NO_PULLDATA_API + +// STB_VORBIS_NO_STDIO +// does not compile the code for the APIs that use FILE *s internally +// or externally (implied by STB_VORBIS_NO_PULLDATA_API) +#define STB_VORBIS_NO_STDIO + +// STB_VORBIS_NO_INTEGER_CONVERSION +// does not compile the code for converting audio sample data from +// float to integer (implied by STB_VORBIS_NO_PULLDATA_API) +// #define STB_VORBIS_NO_INTEGER_CONVERSION + +// STB_VORBIS_NO_FAST_SCALED_FLOAT +// does not use a fast float-to-int trick to accelerate float-to-int on +// most platforms which requires endianness be defined correctly. +//#define STB_VORBIS_NO_FAST_SCALED_FLOAT + + +// STB_VORBIS_MAX_CHANNELS [number] +// globally define this to the maximum number of channels you need. +// The spec does not put a restriction on channels except that +// the count is stored in a byte, so 255 is the hard limit. +// Reducing this saves about 16 bytes per value, so using 16 saves +// (255-16)*16 or around 4KB. Plus anything other memory usage +// I forgot to account for. Can probably go as low as 8 (7.1 audio), +// 6 (5.1 audio), or 2 (stereo only). +#ifndef STB_VORBIS_MAX_CHANNELS +#define STB_VORBIS_MAX_CHANNELS 16 // enough for anyone? +#endif + +// STB_VORBIS_PUSHDATA_CRC_COUNT [number] +// after a flush_pushdata(), stb_vorbis begins scanning for the +// next valid page, without backtracking. when it finds something +// that looks like a page, it streams through it and verifies its +// CRC32. Should that validation fail, it keeps scanning. But it's +// possible that _while_ streaming through to check the CRC32 of +// one candidate page, it sees another candidate page. This #define +// determines how many "overlapping" candidate pages it can search +// at once. Note that "real" pages are typically ~4KB to ~8KB, whereas +// garbage pages could be as big as 64KB, but probably average ~16KB. +// So don't hose ourselves by scanning an apparent 64KB page and +// missing a ton of real ones in the interim; so minimum of 2 +#ifndef STB_VORBIS_PUSHDATA_CRC_COUNT +#define STB_VORBIS_PUSHDATA_CRC_COUNT 4 +#endif + +// STB_VORBIS_FAST_HUFFMAN_LENGTH [number] +// sets the log size of the huffman-acceleration table. Maximum +// supported value is 24. with larger numbers, more decodings are O(1), +// but the table size is larger so worse cache missing, so you'll have +// to probe (and try multiple ogg vorbis files) to find the sweet spot. +#ifndef STB_VORBIS_FAST_HUFFMAN_LENGTH +#define STB_VORBIS_FAST_HUFFMAN_LENGTH 10 +#endif + +// STB_VORBIS_FAST_BINARY_LENGTH [number] +// sets the log size of the binary-search acceleration table. this +// is used in similar fashion to the fast-huffman size to set initial +// parameters for the binary search + +// STB_VORBIS_FAST_HUFFMAN_INT +// The fast huffman tables are much more efficient if they can be +// stored as 16-bit results instead of 32-bit results. This restricts +// the codebooks to having only 65535 possible outcomes, though. +// (At least, accelerated by the huffman table.) +#ifndef STB_VORBIS_FAST_HUFFMAN_INT +#define STB_VORBIS_FAST_HUFFMAN_SHORT +#endif + +// STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH +// If the 'fast huffman' search doesn't succeed, then stb_vorbis falls +// back on binary searching for the correct one. This requires storing +// extra tables with the huffman codes in sorted order. Defining this +// symbol trades off space for speed by forcing a linear search in the +// non-fast case, except for "sparse" codebooks. +// #define STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH + +// STB_VORBIS_DIVIDES_IN_RESIDUE +// stb_vorbis precomputes the result of the scalar residue decoding +// that would otherwise require a divide per chunk. you can trade off +// space for time by defining this symbol. +// #define STB_VORBIS_DIVIDES_IN_RESIDUE + +// STB_VORBIS_DIVIDES_IN_CODEBOOK +// vorbis VQ codebooks can be encoded two ways: with every case explicitly +// stored, or with all elements being chosen from a small range of values, +// and all values possible in all elements. By default, stb_vorbis expands +// this latter kind out to look like the former kind for ease of decoding, +// because otherwise an integer divide-per-vector-element is required to +// unpack the index. If you define STB_VORBIS_DIVIDES_IN_CODEBOOK, you can +// trade off storage for speed. +//#define STB_VORBIS_DIVIDES_IN_CODEBOOK + +// STB_VORBIS_CODEBOOK_SHORTS +// The vorbis file format encodes VQ codebook floats as ax+b where a and +// b are floating point per-codebook constants, and x is a 16-bit int. +// Normally, stb_vorbis decodes them to floats rather than leaving them +// as 16-bit ints and computing ax+b while decoding. This is a speed/space +// tradeoff; you can save space by defining this flag. +#ifndef STB_VORBIS_CODEBOOK_SHORTS +#define STB_VORBIS_CODEBOOK_FLOATS +#endif + +// STB_VORBIS_DIVIDE_TABLE +// this replaces small integer divides in the floor decode loop with +// table lookups. made less than 1% difference, so disabled by default. + +// STB_VORBIS_NO_INLINE_DECODE +// disables the inlining of the scalar codebook fast-huffman decode. +// might save a little codespace; useful for debugging +// #define STB_VORBIS_NO_INLINE_DECODE + +// STB_VORBIS_NO_DEFER_FLOOR +// Normally we only decode the floor without synthesizing the actual +// full curve. We can instead synthesize the curve immediately. This +// requires more memory and is very likely slower, so I don't think +// you'd ever want to do it except for debugging. +// #define STB_VORBIS_NO_DEFER_FLOOR + + + + +////////////////////////////////////////////////////////////////////////////// + +#ifdef STB_VORBIS_NO_PULLDATA_API + #define STB_VORBIS_NO_INTEGER_CONVERSION + #define STB_VORBIS_NO_STDIO +#endif + +#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) + #define STB_VORBIS_NO_STDIO 1 +#endif + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT + + // only need endianness for fast-float-to-int, which we don't + // use for pushdata + + #ifndef STB_VORBIS_BIG_ENDIAN + #define STB_VORBIS_ENDIAN 0 + #else + #define STB_VORBIS_ENDIAN 1 + #endif + +#endif +#endif + + +#ifndef STB_VORBIS_NO_STDIO +#include +#endif + +#ifndef STB_VORBIS_NO_CRT +#include +#include +#include +#include +#if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) +#include +#endif +#else +#define NULL 0 +#endif + +#ifndef _MSC_VER + #if __GNUC__ + #define __forceinline inline + #else + #define __forceinline + #endif +#endif + +#if STB_VORBIS_MAX_CHANNELS > 256 +#error "Value of STB_VORBIS_MAX_CHANNELS outside of allowed range" +#endif + +#if STB_VORBIS_FAST_HUFFMAN_LENGTH > 24 +#error "Value of STB_VORBIS_FAST_HUFFMAN_LENGTH outside of allowed range" +#endif + + +#define MAX_BLOCKSIZE_LOG 13 // from specification +#define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG) + + +typedef unsigned char uint8; +typedef signed char int8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifdef STB_VORBIS_CODEBOOK_FLOATS +typedef float codetype; +#else +typedef uint16 codetype; +#endif + +// @NOTE +// +// Some arrays below are tagged "//varies", which means it's actually +// a variable-sized piece of data, but rather than malloc I assume it's +// small enough it's better to just allocate it all together with the +// main thing +// +// Most of the variables are specified with the smallest size I could pack +// them into. It might give better performance to make them all full-sized +// integers. It should be safe to freely rearrange the structures or change +// the sizes larger--nothing relies on silently truncating etc., nor the +// order of variables. + +#define FAST_HUFFMAN_TABLE_SIZE (1 << STB_VORBIS_FAST_HUFFMAN_LENGTH) +#define FAST_HUFFMAN_TABLE_MASK (FAST_HUFFMAN_TABLE_SIZE - 1) + +typedef struct +{ + int dimensions, entries; + uint8 *codeword_lengths; + float minimum_value; + float delta_value; + uint8 value_bits; + uint8 lookup_type; + uint8 sequence_p; + uint8 sparse; + uint32 lookup_values; + codetype *multiplicands; + uint32 *codewords; + #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT + int16 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; + #else + int32 fast_huffman[FAST_HUFFMAN_TABLE_SIZE]; + #endif + uint32 *sorted_codewords; + int *sorted_values; + int sorted_entries; +} Codebook; + +typedef struct +{ + uint8 order; + uint16 rate; + uint16 bark_map_size; + uint8 amplitude_bits; + uint8 amplitude_offset; + uint8 number_of_books; + uint8 book_list[16]; // varies +} Floor0; + +typedef struct +{ + uint8 partitions; + uint8 partition_class_list[32]; // varies + uint8 class_dimensions[16]; // varies + uint8 class_subclasses[16]; // varies + uint8 class_masterbooks[16]; // varies + int16 subclass_books[16][8]; // varies + uint16 Xlist[31*8+2]; // varies + uint8 sorted_order[31*8+2]; + uint8 neighbors[31*8+2][2]; + uint8 floor1_multiplier; + uint8 rangebits; + int values; +} Floor1; + +typedef union +{ + Floor0 floor0; + Floor1 floor1; +} Floor; + +typedef struct +{ + uint32 begin, end; + uint32 part_size; + uint8 classifications; + uint8 classbook; + uint8 **classdata; + int16 (*residue_books)[8]; +} Residue; + +typedef struct +{ + uint8 magnitude; + uint8 angle; + uint8 mux; +} MappingChannel; + +typedef struct +{ + uint16 coupling_steps; + MappingChannel *chan; + uint8 submaps; + uint8 submap_floor[15]; // varies + uint8 submap_residue[15]; // varies +} Mapping; + +typedef struct +{ + uint8 blockflag; + uint8 mapping; + uint16 windowtype; + uint16 transformtype; +} Mode; + +typedef struct +{ + uint32 goal_crc; // expected crc if match + int bytes_left; // bytes left in packet + uint32 crc_so_far; // running crc + int bytes_done; // bytes processed in _current_ chunk + uint32 sample_loc; // granule pos encoded in page +} CRCscan; + +typedef struct +{ + uint32 page_start, page_end; + uint32 after_previous_page_start; + uint32 first_decoded_sample; + uint32 last_decoded_sample; +} ProbedPage; + +struct stb_vorbis +{ + // user-accessible info + unsigned int sample_rate; + int channels; + + unsigned int setup_memory_required; + unsigned int temp_memory_required; + unsigned int setup_temp_memory_required; + + // input config +#ifndef STB_VORBIS_NO_STDIO + FILE *f; + uint32 f_start; + int close_on_free; +#endif + + uint8 *stream; + uint8 *stream_start; + uint8 *stream_end; + + uint32 stream_len; + + uint8 push_mode; + + uint32 first_audio_page_offset; + + ProbedPage p_first, p_last; + + // memory management + stb_vorbis_alloc alloc; + int setup_offset; + int temp_offset; + + // run-time results + int eof; + enum STBVorbisError error; + + // user-useful data + + // header info + int blocksize[2]; + int blocksize_0, blocksize_1; + int codebook_count; + Codebook *codebooks; + int floor_count; + uint16 floor_types[64]; // varies + Floor *floor_config; + int residue_count; + uint16 residue_types[64]; // varies + Residue *residue_config; + int mapping_count; + Mapping *mapping; + int mode_count; + Mode mode_config[64]; // varies + + uint32 total_samples; + + // decode buffer + float *channel_buffers[STB_VORBIS_MAX_CHANNELS]; + float *outputs [STB_VORBIS_MAX_CHANNELS]; + + float *previous_window[STB_VORBIS_MAX_CHANNELS]; + int previous_length; + + #ifndef STB_VORBIS_NO_DEFER_FLOOR + int16 *finalY[STB_VORBIS_MAX_CHANNELS]; + #else + float *floor_buffers[STB_VORBIS_MAX_CHANNELS]; + #endif + + uint32 current_loc; // sample location of next frame to decode + int current_loc_valid; + + // per-blocksize precomputed data + + // twiddle factors + float *A[2],*B[2],*C[2]; + float *window[2]; + uint16 *bit_reverse[2]; + + // current page/packet/segment streaming info + uint32 serial; // stream serial number for verification + int last_page; + int segment_count; + uint8 segments[255]; + uint8 page_flag; + uint8 bytes_in_seg; + uint8 first_decode; + int next_seg; + int last_seg; // flag that we're on the last segment + int last_seg_which; // what was the segment number of the last seg? + uint32 acc; + int valid_bits; + int packet_bytes; + int end_seg_with_known_loc; + uint32 known_loc_for_packet; + int discard_samples_deferred; + uint32 samples_output; + + // push mode scanning + int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching +#ifndef STB_VORBIS_NO_PUSHDATA_API + CRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT]; +#endif + + // sample-access + int channel_buffer_start; + int channel_buffer_end; +}; + +extern int my_prof(int slot); +//#define stb_prof my_prof + +#ifndef stb_prof +#define stb_prof(x) 0 +#endif + +#if defined(STB_VORBIS_NO_PUSHDATA_API) + #define IS_PUSH_MODE(f) FALSE +#elif defined(STB_VORBIS_NO_PULLDATA_API) + #define IS_PUSH_MODE(f) TRUE +#else + #define IS_PUSH_MODE(f) ((f)->push_mode) +#endif + +typedef struct stb_vorbis vorb; + +static int error(vorb *f, enum STBVorbisError e) +{ + f->error = e; + if (!f->eof && e != VORBIS_need_more_data) { + f->error=e; // breakpoint for debugging + } + return 0; +} + + +// these functions are used for allocating temporary memory +// while decoding. if you can afford the stack space, use +// alloca(); otherwise, provide a temp buffer and it will +// allocate out of those. + +#define array_size_required(count,size) (count*(sizeof(void *)+(size))) + +#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size)) +#ifdef dealloca +#define temp_free(f,p) (f->alloc.alloc_buffer ? 0 : dealloca(size)) +#else +#define temp_free(f,p) 0 +#endif +#define temp_alloc_save(f) ((f)->temp_offset) +#define temp_alloc_restore(f,p) ((f)->temp_offset = (p)) + +#define temp_block_array(f,count,size) make_block_array(temp_alloc(f,array_size_required(count,size)), count, size) + +// given a sufficiently large block of memory, make an array of pointers to subblocks of it +static void *make_block_array(void *mem, int count, int size) +{ + int i; + void ** p = (void **) mem; + char *q = (char *) (p + count); + for (i=0; i < count; ++i) { + p[i] = q; + q += size; + } + return p; +} + +static void *setup_malloc(vorb *f, int sz) +{ + sz = (sz+3) & ~3; + f->setup_memory_required += sz; + if (f->alloc.alloc_buffer) { + void *p = (char *) f->alloc.alloc_buffer + f->setup_offset; + if (f->setup_offset + sz > f->temp_offset) return NULL; + f->setup_offset += sz; + return p; + } + return sz ? malloc(sz) : NULL; +} + +static void setup_free(vorb *f, void *p) +{ + if (f->alloc.alloc_buffer) return; // do nothing; setup mem is not a stack + free(p); +} + +static void *setup_temp_malloc(vorb *f, int sz) +{ + sz = (sz+3) & ~3; + if (f->alloc.alloc_buffer) { + if (f->temp_offset - sz < f->setup_offset) return NULL; + f->temp_offset -= sz; + return (char *) f->alloc.alloc_buffer + f->temp_offset; + } + return malloc(sz); +} + +static void setup_temp_free(vorb *f, void *p, size_t sz) +{ + if (f->alloc.alloc_buffer) { + f->temp_offset += (sz+3)&~3; + return; + } + free(p); +} + +#define CRC32_POLY 0x04c11db7 // from spec + +static uint32 crc_table[256]; +static void crc32_init(void) +{ + int i,j; + uint32 s; + for(i=0; i < 256; i++) { + for (s=i<<24, j=0; j < 8; ++j) + s = (s << 1) ^ (s >= (1<<31) ? CRC32_POLY : 0); + crc_table[i] = s; + } +} + +static __forceinline uint32 crc32_update(uint32 crc, uint8 byte) +{ + return (crc << 8) ^ crc_table[byte ^ (crc >> 24)]; +} + + +// used in setup, and for huffman that doesn't go fast path +static unsigned int bit_reverse(unsigned int n) +{ + n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1); + n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2); + n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4); + n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8); + return (n >> 16) | (n << 16); +} + +static float square(float x) +{ + return x*x; +} + +// this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3 +// as required by the specification. fast(?) implementation from stb.h +// @OPTIMIZE: called multiple times per-packet with "constants"; move to setup +static int ilog(int32 n) +{ + static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; + + // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29) + if (n < (1U << 14)) + if (n < (1U << 4)) return 0 + log2_4[n ]; + else if (n < (1U << 9)) return 5 + log2_4[n >> 5]; + else return 10 + log2_4[n >> 10]; + else if (n < (1U << 24)) + if (n < (1U << 19)) return 15 + log2_4[n >> 15]; + else return 20 + log2_4[n >> 20]; + else if (n < (1U << 29)) return 25 + log2_4[n >> 25]; + else if (n < (1U << 31)) return 30 + log2_4[n >> 30]; + else return 0; // signed n returns 0 +} + +#ifndef M_PI + #define M_PI 3.14159265358979323846264f // from CRC +#endif + +// code length assigned to a value with no huffman encoding +#define NO_CODE 255 + +/////////////////////// LEAF SETUP FUNCTIONS ////////////////////////// +// +// these functions are only called at setup, and only a few times +// per file + +static float float32_unpack(uint32 x) +{ + // from the specification + uint32 mantissa = x & 0x1fffff; + uint32 sign = x & 0x80000000; + uint32 exp = (x & 0x7fe00000) >> 21; + double res = sign ? -(double)mantissa : (double)mantissa; + return (float) ldexp((float)res, exp-788); +} + + +// zlib & jpeg huffman tables assume that the output symbols +// can either be arbitrarily arranged, or have monotonically +// increasing frequencies--they rely on the lengths being sorted; +// this makes for a very simple generation algorithm. +// vorbis allows a huffman table with non-sorted lengths. This +// requires a more sophisticated construction, since symbols in +// order do not map to huffman codes "in order". +static void add_entry(Codebook *c, uint32 huff_code, int symbol, int count, int len, uint32 *values) +{ + if (!c->sparse) { + c->codewords [symbol] = huff_code; + } else { + c->codewords [count] = huff_code; + c->codeword_lengths[count] = len; + values [count] = symbol; + } +} + +static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) +{ + int i,k,m=0; + uint32 available[32]; + + memset(available, 0, sizeof(available)); + // find the first entry + for (k=0; k < n; ++k) if (len[k] < NO_CODE) break; + if (k == n) { assert(c->sorted_entries == 0); return TRUE; } + // add to the list + add_entry(c, 0, k, m++, len[k], values); + // add all available leaves + for (i=1; i <= len[k]; ++i) + available[i] = 1 << (32-i); + // note that the above code treats the first case specially, + // but it's really the same as the following code, so they + // could probably be combined (except the initial code is 0, + // and I use 0 in available[] to mean 'empty') + for (i=k+1; i < n; ++i) { + uint32 res; + int z = len[i], y; + if (z == NO_CODE) continue; + // find lowest available leaf (should always be earliest, + // which is what the specification calls for) + // note that this property, and the fact we can never have + // more than one free leaf at a given level, isn't totally + // trivial to prove, but it seems true and the assert never + // fires, so! + while (z > 0 && !available[z]) --z; + if (z == 0) { assert(0); return FALSE; } + res = available[z]; + available[z] = 0; + add_entry(c, bit_reverse(res), i, m++, len[i], values); + // propogate availability up the tree + if (z != len[i]) { + for (y=len[i]; y > z; --y) { + assert(available[y] == 0); + available[y] = res + (1 << (32-y)); + } + } + } + return TRUE; +} + +// accelerated huffman table allows fast O(1) match of all symbols +// of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH +static void compute_accelerated_huffman(Codebook *c) +{ + int i, len; + for (i=0; i < FAST_HUFFMAN_TABLE_SIZE; ++i) + c->fast_huffman[i] = -1; + + len = c->sparse ? c->sorted_entries : c->entries; + #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT + if (len > 32767) len = 32767; // largest possible value we can encode! + #endif + for (i=0; i < len; ++i) { + if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) { + uint32 z = c->sparse ? bit_reverse(c->sorted_codewords[i]) : c->codewords[i]; + // set table entries for all bit combinations in the higher bits + while (z < FAST_HUFFMAN_TABLE_SIZE) { + c->fast_huffman[z] = i; + z += 1 << c->codeword_lengths[i]; + } + } + } +} + +static int uint32_compare(const void *p, const void *q) +{ + uint32 x = * (uint32 *) p; + uint32 y = * (uint32 *) q; + return x < y ? -1 : x > y; +} + +static int include_in_sort(Codebook *c, uint8 len) +{ + if (c->sparse) { assert(len != NO_CODE); return TRUE; } + if (len == NO_CODE) return FALSE; + if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE; + return FALSE; +} + +// if the fast table above doesn't work, we want to binary +// search them... need to reverse the bits +static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values) +{ + int i, len; + // build a list of all the entries + // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN. + // this is kind of a frivolous optimization--I don't see any performance improvement, + // but it's like 4 extra lines of code, so. + if (!c->sparse) { + int k = 0; + for (i=0; i < c->entries; ++i) + if (include_in_sort(c, lengths[i])) + c->sorted_codewords[k++] = bit_reverse(c->codewords[i]); + assert(k == c->sorted_entries); + } else { + for (i=0; i < c->sorted_entries; ++i) + c->sorted_codewords[i] = bit_reverse(c->codewords[i]); + } + + qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), uint32_compare); + c->sorted_codewords[c->sorted_entries] = 0xffffffff; + + len = c->sparse ? c->sorted_entries : c->entries; + // now we need to indicate how they correspond; we could either + // #1: sort a different data structure that says who they correspond to + // #2: for each sorted entry, search the original list to find who corresponds + // #3: for each original entry, find the sorted entry + // #1 requires extra storage, #2 is slow, #3 can use binary search! + for (i=0; i < len; ++i) { + int huff_len = c->sparse ? lengths[values[i]] : lengths[i]; + if (include_in_sort(c,huff_len)) { + uint32 code = bit_reverse(c->codewords[i]); + int x=0, n=c->sorted_entries; + while (n > 1) { + // invariant: sc[x] <= code < sc[x+n] + int m = x + (n >> 1); + if (c->sorted_codewords[m] <= code) { + x = m; + n -= (n>>1); + } else { + n >>= 1; + } + } + assert(c->sorted_codewords[x] == code); + if (c->sparse) { + c->sorted_values[x] = values[i]; + c->codeword_lengths[x] = huff_len; + } else { + c->sorted_values[x] = i; + } + } + } +} + +// only run while parsing the header (3 times) +static int vorbis_validate(uint8 *data) +{ + static uint8 vorbis[6] = { 'v', 'o', 'r', 'b', 'i', 's' }; + return memcmp(data, vorbis, 6) == 0; +} + +// called from setup only, once per code book +// (formula implied by specification) +static int lookup1_values(int entries, int dim) +{ + int r = (int) floor(exp((float) log((float) entries) / dim)); + if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning; + ++r; // floor() to avoid _ftol() when non-CRT + assert(pow((float) r+1, dim) > entries); + assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above + return r; +} + +// called twice per file +static void compute_twiddle_factors(int n, float *A, float *B, float *C) +{ + int n4 = n >> 2, n8 = n >> 3; + int k,k2; + + for (k=k2=0; k < n4; ++k,k2+=2) { + A[k2 ] = (float) cos(4*k*M_PI/n); + A[k2+1] = (float) -sin(4*k*M_PI/n); + B[k2 ] = (float) cos((k2+1)*M_PI/n/2) * 0.5f; + B[k2+1] = (float) sin((k2+1)*M_PI/n/2) * 0.5f; + } + for (k=k2=0; k < n8; ++k,k2+=2) { + C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); + C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); + } +} + +static void compute_window(int n, float *window) +{ + int n2 = n >> 1, i; + for (i=0; i < n2; ++i) + window[i] = (float) sin(0.5 * M_PI * square((float) sin((i - 0 + 0.5) / n2 * 0.5 * M_PI))); +} + +static void compute_bitreverse(int n, uint16 *rev) +{ + int ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + int i, n8 = n >> 3; + for (i=0; i < n8; ++i) + rev[i] = (bit_reverse(i) >> (32-ld+3)) << 2; +} + +static int init_blocksize(vorb *f, int b, int n) +{ + int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3; + f->A[b] = (float *) setup_malloc(f, sizeof(float) * n2); + f->B[b] = (float *) setup_malloc(f, sizeof(float) * n2); + f->C[b] = (float *) setup_malloc(f, sizeof(float) * n4); + if (!f->A[b] || !f->B[b] || !f->C[b]) return error(f, VORBIS_outofmem); + compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]); + f->window[b] = (float *) setup_malloc(f, sizeof(float) * n2); + if (!f->window[b]) return error(f, VORBIS_outofmem); + compute_window(n, f->window[b]); + f->bit_reverse[b] = (uint16 *) setup_malloc(f, sizeof(uint16) * n8); + if (!f->bit_reverse[b]) return error(f, VORBIS_outofmem); + compute_bitreverse(n, f->bit_reverse[b]); + return TRUE; +} + +static void neighbors(uint16 *x, int n, int *plow, int *phigh) +{ + int low = -1; + int high = 65536; + int i; + for (i=0; i < n; ++i) { + if (x[i] > low && x[i] < x[n]) { *plow = i; low = x[i]; } + if (x[i] < high && x[i] > x[n]) { *phigh = i; high = x[i]; } + } +} + +// this has been repurposed so y is now the original index instead of y +typedef struct +{ + uint16 x,y; +} Point; + +int point_compare(const void *p, const void *q) +{ + Point *a = (Point *) p; + Point *b = (Point *) q; + return a->x < b->x ? -1 : a->x > b->x; +} + +// +/////////////////////// END LEAF SETUP FUNCTIONS ////////////////////////// + + +#if defined(STB_VORBIS_NO_STDIO) + #define USE_MEMORY(z) TRUE +#else + #define USE_MEMORY(z) ((z)->stream) +#endif + +static uint8 get8(vorb *z) +{ + if (USE_MEMORY(z)) { + if (z->stream >= z->stream_end) { z->eof = TRUE; return 0; } + return *z->stream++; + } + + #ifndef STB_VORBIS_NO_STDIO + { + int c = fgetc(z->f); + if (c == EOF) { z->eof = TRUE; return 0; } + return c; + } + #endif +} + +static uint32 get32(vorb *f) +{ + uint32 x; + x = get8(f); + x += get8(f) << 8; + x += get8(f) << 16; + x += get8(f) << 24; + return x; +} + +static int getn(vorb *z, uint8 *data, int n) +{ + if (USE_MEMORY(z)) { + if (z->stream+n > z->stream_end) { z->eof = 1; return 0; } + memcpy(data, z->stream, n); + z->stream += n; + return 1; + } + + #ifndef STB_VORBIS_NO_STDIO + if (fread(data, n, 1, z->f) == 1) + return 1; + else { + z->eof = 1; + return 0; + } + #endif +} + +static void skip(vorb *z, int n) +{ + if (USE_MEMORY(z)) { + z->stream += n; + if (z->stream >= z->stream_end) z->eof = 1; + return; + } + #ifndef STB_VORBIS_NO_STDIO + { + long x = ftell(z->f); + fseek(z->f, x+n, SEEK_SET); + } + #endif +} + +static int set_file_offset(stb_vorbis *f, unsigned int loc) +{ + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (f->push_mode) return 0; + #endif + f->eof = 0; + if (USE_MEMORY(f)) { + if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) { + f->stream = f->stream_end; + f->eof = 1; + return 0; + } else { + f->stream = f->stream_start + loc; + return 1; + } + } + #ifndef STB_VORBIS_NO_STDIO + if (loc + f->f_start < loc || loc >= 0x80000000) { + loc = 0x7fffffff; + f->eof = 1; + } else { + loc += f->f_start; + } + if (!fseek(f->f, loc, SEEK_SET)) + return 1; + f->eof = 1; + fseek(f->f, f->f_start, SEEK_END); + return 0; + #endif +} + + +static uint8 ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 }; + +static int capture_pattern(vorb *f) +{ + if (0x4f != get8(f)) return FALSE; + if (0x67 != get8(f)) return FALSE; + if (0x67 != get8(f)) return FALSE; + if (0x53 != get8(f)) return FALSE; + return TRUE; +} + +#define PAGEFLAG_continued_packet 1 +#define PAGEFLAG_first_page 2 +#define PAGEFLAG_last_page 4 + +static int start_page_no_capturepattern(vorb *f) +{ + uint32 loc0,loc1,n,i; + // stream structure version + if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version); + // header flag + f->page_flag = get8(f); + // absolute granule position + loc0 = get32(f); + loc1 = get32(f); + // @TODO: validate loc0,loc1 as valid positions? + // stream serial number -- vorbis doesn't interleave, so discard + get32(f); + //if (f->serial != get32(f)) return error(f, VORBIS_incorrect_stream_serial_number); + // page sequence number + n = get32(f); + f->last_page = n; + // CRC32 + get32(f); + // page_segments + f->segment_count = get8(f); + if (!getn(f, f->segments, f->segment_count)) + return error(f, VORBIS_unexpected_eof); + // assume we _don't_ know any the sample position of any segments + f->end_seg_with_known_loc = -2; + if (loc0 != ~0 || loc1 != ~0) { + // determine which packet is the last one that will complete + for (i=f->segment_count-1; i >= 0; --i) + if (f->segments[i] < 255) + break; + // 'i' is now the index of the _last_ segment of a packet that ends + if (i >= 0) { + f->end_seg_with_known_loc = i; + f->known_loc_for_packet = loc0; + } + } + if (f->first_decode) { + int i,len; + ProbedPage p; + len = 0; + for (i=0; i < f->segment_count; ++i) + len += f->segments[i]; + len += 27 + f->segment_count; + p.page_start = f->first_audio_page_offset; + p.page_end = p.page_start + len; + p.after_previous_page_start = p.page_start; + p.first_decoded_sample = 0; + p.last_decoded_sample = loc0; + f->p_first = p; + } + f->next_seg = 0; + return TRUE; +} + +static int start_page(vorb *f) +{ + if (!capture_pattern(f)) return error(f, VORBIS_missing_capture_pattern); + return start_page_no_capturepattern(f); +} + +static int start_packet(vorb *f) +{ + while (f->next_seg == -1) { + if (!start_page(f)) return FALSE; + if (f->page_flag & PAGEFLAG_continued_packet) + return error(f, VORBIS_continued_packet_flag_invalid); + } + f->last_seg = FALSE; + f->valid_bits = 0; + f->packet_bytes = 0; + f->bytes_in_seg = 0; + // f->next_seg is now valid + return TRUE; +} + +static int maybe_start_packet(vorb *f) +{ + if (f->next_seg == -1) { + int x = get8(f); + if (f->eof) return FALSE; // EOF at page boundary is not an error! + if (0x4f != x ) return error(f, VORBIS_missing_capture_pattern); + if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (0x53 != get8(f)) return error(f, VORBIS_missing_capture_pattern); + if (!start_page_no_capturepattern(f)) return FALSE; + if (f->page_flag & PAGEFLAG_continued_packet) { + // set up enough state that we can read this packet if we want, + // e.g. during recovery + f->last_seg = FALSE; + f->bytes_in_seg = 0; + return error(f, VORBIS_continued_packet_flag_invalid); + } + } + return start_packet(f); +} + +static int next_segment(vorb *f) +{ + int len; + if (f->last_seg) return 0; + if (f->next_seg == -1) { + f->last_seg_which = f->segment_count-1; // in case start_page fails + if (!start_page(f)) { f->last_seg = 1; return 0; } + if (!(f->page_flag & PAGEFLAG_continued_packet)) return error(f, VORBIS_continued_packet_flag_invalid); + } + len = f->segments[f->next_seg++]; + if (len < 255) { + f->last_seg = TRUE; + f->last_seg_which = f->next_seg-1; + } + if (f->next_seg >= f->segment_count) + f->next_seg = -1; + assert(f->bytes_in_seg == 0); + f->bytes_in_seg = len; + return len; +} + +#define EOP (-1) +#define INVALID_BITS (-1) + +static int get8_packet_raw(vorb *f) +{ + if (!f->bytes_in_seg) + if (f->last_seg) return EOP; + else if (!next_segment(f)) return EOP; + assert(f->bytes_in_seg > 0); + --f->bytes_in_seg; + ++f->packet_bytes; + return get8(f); +} + +static int get8_packet(vorb *f) +{ + int x = get8_packet_raw(f); + f->valid_bits = 0; + return x; +} + +static void flush_packet(vorb *f) +{ + while (get8_packet_raw(f) != EOP); +} + +// @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important +// as the huffman decoder? +static uint32 get_bits(vorb *f, int n) +{ + uint32 z; + + if (f->valid_bits < 0) return 0; + if (f->valid_bits < n) { + if (n > 24) { + // the accumulator technique below would not work correctly in this case + z = get_bits(f, 24); + z += get_bits(f, n-24) << 24; + return z; + } + if (f->valid_bits == 0) f->acc = 0; + while (f->valid_bits < n) { + int z = get8_packet_raw(f); + if (z == EOP) { + f->valid_bits = INVALID_BITS; + return 0; + } + f->acc += z << f->valid_bits; + f->valid_bits += 8; + } + } + if (f->valid_bits < 0) return 0; + z = f->acc & ((1 << n)-1); + f->acc >>= n; + f->valid_bits -= n; + return z; +} + +static int32 get_bits_signed(vorb *f, int n) +{ + uint32 z = get_bits(f, n); + if (z & (1 << (n-1))) + z += ~((1 << n) - 1); + return (int32) z; +} + +// @OPTIMIZE: primary accumulator for huffman +// expand the buffer to as many bits as possible without reading off end of packet +// it might be nice to allow f->valid_bits and f->acc to be stored in registers, +// e.g. cache them locally and decode locally +static __forceinline void prep_huffman(vorb *f) +{ + if (f->valid_bits <= 24) { + if (f->valid_bits == 0) f->acc = 0; + do { + int z; + if (f->last_seg && !f->bytes_in_seg) return; + z = get8_packet_raw(f); + if (z == EOP) return; + f->acc += z << f->valid_bits; + f->valid_bits += 8; + } while (f->valid_bits <= 24); + } +} + +enum +{ + VORBIS_packet_id = 1, + VORBIS_packet_comment = 3, + VORBIS_packet_setup = 5, +}; + +static int codebook_decode_scalar_raw(vorb *f, Codebook *c) +{ + int i; + prep_huffman(f); + + assert(c->sorted_codewords || c->codewords); + // cases to use binary search: sorted_codewords && !c->codewords + // sorted_codewords && c->entries > 8 + if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) { + // binary search + uint32 code = bit_reverse(f->acc); + int x=0, n=c->sorted_entries, len; + + while (n > 1) { + // invariant: sc[x] <= code < sc[x+n] + int m = x + (n >> 1); + if (c->sorted_codewords[m] <= code) { + x = m; + n -= (n>>1); + } else { + n >>= 1; + } + } + // x is now the sorted index + if (!c->sparse) x = c->sorted_values[x]; + // x is now sorted index if sparse, or symbol otherwise + len = c->codeword_lengths[x]; + if (f->valid_bits >= len) { + f->acc >>= len; + f->valid_bits -= len; + return x; + } + + f->valid_bits = 0; + return -1; + } + + // if small, linear search + assert(!c->sparse); + for (i=0; i < c->entries; ++i) { + if (c->codeword_lengths[i] == NO_CODE) continue; + if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) { + if (f->valid_bits >= c->codeword_lengths[i]) { + f->acc >>= c->codeword_lengths[i]; + f->valid_bits -= c->codeword_lengths[i]; + return i; + } + f->valid_bits = 0; + return -1; + } + } + + error(f, VORBIS_invalid_stream); + f->valid_bits = 0; + return -1; +} + +static int codebook_decode_scalar(vorb *f, Codebook *c) +{ + int i; + if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) + prep_huffman(f); + // fast huffman table lookup + i = f->acc & FAST_HUFFMAN_TABLE_MASK; + i = c->fast_huffman[i]; + if (i >= 0) { + f->acc >>= c->codeword_lengths[i]; + f->valid_bits -= c->codeword_lengths[i]; + if (f->valid_bits < 0) { f->valid_bits = 0; return -1; } + return i; + } + return codebook_decode_scalar_raw(f,c); +} + +#ifndef STB_VORBIS_NO_INLINE_DECODE + +#define DECODE_RAW(var, f,c) \ + if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) \ + prep_huffman(f); \ + var = f->acc & FAST_HUFFMAN_TABLE_MASK; \ + var = c->fast_huffman[var]; \ + if (var >= 0) { \ + int n = c->codeword_lengths[var]; \ + f->acc >>= n; \ + f->valid_bits -= n; \ + if (f->valid_bits < 0) { f->valid_bits = 0; var = -1; } \ + } else { \ + var = codebook_decode_scalar_raw(f,c); \ + } + +#else + +#define DECODE_RAW(var,f,c) var = codebook_decode_scalar(f,c); + +#endif + +#define DECODE(var,f,c) \ + DECODE_RAW(var,f,c) \ + if (c->sparse) var = c->sorted_values[var]; + +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + #define DECODE_VQ(var,f,c) DECODE_RAW(var,f,c) +#else + #define DECODE_VQ(var,f,c) DECODE(var,f,c) +#endif + + + + + + +// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case +// where we avoid one addition +#ifndef STB_VORBIS_CODEBOOK_FLOATS + #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off] * c->delta_value + c->minimum_value) + #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off] * c->delta_value) + #define CODEBOOK_ELEMENT_BASE(c) (c->minimum_value) +#else + #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) + #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) + #define CODEBOOK_ELEMENT_BASE(c) (0) +#endif + +static int codebook_decode_start(vorb *f, Codebook *c, int len) +{ + int z = -1; + + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) + error(f, VORBIS_invalid_stream); + else { + DECODE_VQ(z,f,c); + if (c->sparse) assert(z < c->sorted_entries); + if (z < 0) { // check for EOP + if (!f->bytes_in_seg) + if (f->last_seg) + return z; + error(f, VORBIS_invalid_stream); + } + } + return z; +} + +static int codebook_decode(vorb *f, Codebook *c, float *output, int len) +{ + int i,z = codebook_decode_start(f,c,len); + if (z < 0) return FALSE; + if (len > c->dimensions) len = c->dimensions; + +#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + float last = CODEBOOK_ELEMENT_BASE(c); + int div = 1; + for (i=0; i < len; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + output[i] += val; + if (c->sequence_p) last = val + c->minimum_value; + div *= c->lookup_values; + } + return TRUE; + } +#endif + + z *= c->dimensions; + if (c->sequence_p) { + float last = CODEBOOK_ELEMENT_BASE(c); + for (i=0; i < len; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + output[i] += val; + last = val + c->minimum_value; + } + } else { + float last = CODEBOOK_ELEMENT_BASE(c); + for (i=0; i < len; ++i) { + output[i] += CODEBOOK_ELEMENT_FAST(c,z+i) + last; + } + } + + return TRUE; +} + +static int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, int step) +{ + int i,z = codebook_decode_start(f,c,len); + float last = CODEBOOK_ELEMENT_BASE(c); + if (z < 0) return FALSE; + if (len > c->dimensions) len = c->dimensions; + +#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int div = 1; + for (i=0; i < len; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + output[i*step] += val; + if (c->sequence_p) last = val; + div *= c->lookup_values; + } + return TRUE; + } +#endif + + z *= c->dimensions; + for (i=0; i < len; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + output[i*step] += val; + if (c->sequence_p) last = val; + } + + return TRUE; +} + +static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode) +{ + int c_inter = *c_inter_p; + int p_inter = *p_inter_p; + int i,z, effective = c->dimensions; + + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); + + while (total_decode > 0) { + float last = CODEBOOK_ELEMENT_BASE(c); + DECODE_VQ(z,f,c); + #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + assert(!c->sparse || z < c->sorted_entries); + #endif + if (z < 0) { + if (!f->bytes_in_seg) + if (f->last_seg) return FALSE; + return error(f, VORBIS_invalid_stream); + } + + // if this will take us off the end of the buffers, stop short! + // we check by computing the length of the virtual interleaved + // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), + // and the length we'll be using (effective) + if (c_inter + p_inter*ch + effective > len * ch) { + effective = len*ch - (p_inter*ch - c_inter); + } + + #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int div = 1; + for (i=0; i < effective; ++i) { + int off = (z / div) % c->lookup_values; + float val = CODEBOOK_ELEMENT_FAST(c,off) + last; + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + if (c->sequence_p) last = val; + div *= c->lookup_values; + } + } else + #endif + { + z *= c->dimensions; + if (c->sequence_p) { + for (i=0; i < effective; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + last = val; + } + } else { + for (i=0; i < effective; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + outputs[c_inter][p_inter] += val; + if (++c_inter == ch) { c_inter = 0; ++p_inter; } + } + } + } + + total_decode -= effective; + } + *c_inter_p = c_inter; + *p_inter_p = p_inter; + return TRUE; +} + +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK +static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **outputs, int *c_inter_p, int *p_inter_p, int len, int total_decode) +{ + int c_inter = *c_inter_p; + int p_inter = *p_inter_p; + int i,z, effective = c->dimensions; + + // type 0 is only legal in a scalar context + if (c->lookup_type == 0) return error(f, VORBIS_invalid_stream); + + while (total_decode > 0) { + float last = CODEBOOK_ELEMENT_BASE(c); + DECODE_VQ(z,f,c); + + if (z < 0) { + if (!f->bytes_in_seg) + if (f->last_seg) return FALSE; + return error(f, VORBIS_invalid_stream); + } + + // if this will take us off the end of the buffers, stop short! + // we check by computing the length of the virtual interleaved + // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter), + // and the length we'll be using (effective) + if (c_inter + p_inter*2 + effective > len * 2) { + effective = len*2 - (p_inter*2 - c_inter); + } + + { + z *= c->dimensions; + stb_prof(11); + if (c->sequence_p) { + // haven't optimized this case because I don't have any examples + for (i=0; i < effective; ++i) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + outputs[c_inter][p_inter] += val; + if (++c_inter == 2) { c_inter = 0; ++p_inter; } + last = val; + } + } else { + i=0; + if (c_inter == 1) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + outputs[c_inter][p_inter] += val; + c_inter = 0; ++p_inter; + ++i; + } + { + float *z0 = outputs[0]; + float *z1 = outputs[1]; + for (; i+1 < effective;) { + z0[p_inter] += CODEBOOK_ELEMENT_FAST(c,z+i) + last; + z1[p_inter] += CODEBOOK_ELEMENT_FAST(c,z+i+1) + last; + ++p_inter; + i += 2; + } + } + if (i < effective) { + float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; + outputs[c_inter][p_inter] += val; + if (++c_inter == 2) { c_inter = 0; ++p_inter; } + } + } + } + + total_decode -= effective; + } + *c_inter_p = c_inter; + *p_inter_p = p_inter; + return TRUE; +} +#endif + +static int predict_point(int x, int x0, int x1, int y0, int y1) +{ + int dy = y1 - y0; + int adx = x1 - x0; + // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86? + int err = abs(dy) * (x - x0); + int off = err / adx; + return dy < 0 ? y0 - off : y0 + off; +} + +// the following table is block-copied from the specification +static float inverse_db_table[256] = +{ + 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, + 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, + 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, + 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, + 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, + 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, + 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, + 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, + 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, + 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, + 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, + 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, + 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, + 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, + 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, + 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, + 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, + 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, + 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, + 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, + 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, + 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, + 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, + 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, + 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, + 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, + 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, + 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, + 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, + 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, + 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, + 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, + 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, + 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, + 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, + 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, + 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, + 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, + 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, + 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, + 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, + 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, + 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, + 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, + 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, + 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, + 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, + 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, + 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, + 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, + 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, + 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, + 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, + 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, + 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, + 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, + 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, + 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, + 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, + 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, + 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, + 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, + 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, + 0.82788260f, 0.88168307f, 0.9389798f, 1.0f +}; + + +// @OPTIMIZE: if you want to replace this bresenham line-drawing routine, +// note that you must produce bit-identical output to decode correctly; +// this specific sequence of operations is specified in the spec (it's +// drawing integer-quantized frequency-space lines that the encoder +// expects to be exactly the same) +// ... also, isn't the whole point of Bresenham's algorithm to NOT +// have to divide in the setup? sigh. +#ifndef STB_VORBIS_NO_DEFER_FLOOR +#define LINE_OP(a,b) a *= b +#else +#define LINE_OP(a,b) a = b +#endif + +#ifdef STB_VORBIS_DIVIDE_TABLE +#define DIVTAB_NUMER 32 +#define DIVTAB_DENOM 64 +int8 integer_divide_table[DIVTAB_NUMER][DIVTAB_DENOM]; // 2KB +#endif + +static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y1, int n) +{ + int dy = y1 - y0; + int adx = x1 - x0; + int ady = abs(dy); + int base; + int x=x0,y=y0; + int err = 0; + int sy; + +#ifdef STB_VORBIS_DIVIDE_TABLE + if (adx < DIVTAB_DENOM && ady < DIVTAB_NUMER) { + if (dy < 0) { + base = -integer_divide_table[ady][adx]; + sy = base-1; + } else { + base = integer_divide_table[ady][adx]; + sy = base+1; + } + } else { + base = dy / adx; + if (dy < 0) + sy = base - 1; + else + sy = base+1; + } +#else + base = dy / adx; + if (dy < 0) + sy = base - 1; + else + sy = base+1; +#endif + ady -= abs(base) * adx; + if (x1 > n) x1 = n; + LINE_OP(output[x], inverse_db_table[y]); + for (++x; x < x1; ++x) { + err += ady; + if (err >= adx) { + err -= adx; + y += sy; + } else + y += base; + LINE_OP(output[x], inverse_db_table[y]); + } +} + +static int residue_decode(vorb *f, Codebook *book, float *target, int offset, int n, int rtype) +{ + int k; + if (rtype == 0) { + int step = n / book->dimensions; + for (k=0; k < step; ++k) + if (!codebook_decode_step(f, book, target+offset+k, n-offset-k, step)) + return FALSE; + } else { + for (k=0; k < n; ) { + if (!codebook_decode(f, book, target+offset, n-k)) + return FALSE; + k += book->dimensions; + offset += book->dimensions; + } + } + return TRUE; +} + +static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) +{ + int i,j,pass; + Residue *r = f->residue_config + rn; + int rtype = f->residue_types[rn]; + int c = r->classbook; + int classwords = f->codebooks[c].dimensions; + int n_read = r->end - r->begin; + int part_read = n_read / r->part_size; + int temp_alloc_point = temp_alloc_save(f); + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + uint8 ***part_classdata = (uint8 ***) temp_block_array(f,f->channels, part_read * sizeof(**part_classdata)); + #else + int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications)); + #endif + + stb_prof(2); + for (i=0; i < ch; ++i) + if (!do_not_decode[i]) + memset(residue_buffers[i], 0, sizeof(float) * n); + + if (rtype == 2 && ch != 1) { + int len = ch * n; + for (j=0; j < ch; ++j) + if (!do_not_decode[j]) + break; + if (j == ch) + goto done; + + stb_prof(3); + for (pass=0; pass < 8; ++pass) { + int pcount = 0, class_set = 0; + if (ch == 2) { + stb_prof(13); + while (pcount < part_read) { + int z = r->begin + pcount*r->part_size; + int c_inter = (z & 1), p_inter = z>>1; + if (pass == 0) { + Codebook *c = f->codebooks+r->classbook; + int q; + DECODE(q,f,c); + if (q == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[0][i+pcount] = q % r->classifications; + q /= r->classifications; + } + #endif + } + stb_prof(5); + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + int z = r->begin + pcount*r->part_size; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; + #else + int c = classifications[0][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + Codebook *book = f->codebooks + b; + stb_prof(20); // accounts for X time + #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + #else + // saves 1% + if (!codebook_decode_deinterleave_repeat_2(f, book, residue_buffers, &c_inter, &p_inter, n, r->part_size)) + goto done; + #endif + stb_prof(7); + } else { + z += r->part_size; + c_inter = z & 1; + p_inter = z >> 1; + } + } + stb_prof(8); + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } else if (ch == 1) { + while (pcount < part_read) { + int z = r->begin + pcount*r->part_size; + int c_inter = 0, p_inter = z; + if (pass == 0) { + Codebook *c = f->codebooks+r->classbook; + int q; + DECODE(q,f,c); + if (q == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[0][i+pcount] = q % r->classifications; + q /= r->classifications; + } + #endif + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + int z = r->begin + pcount*r->part_size; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; + #else + int c = classifications[0][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + Codebook *book = f->codebooks + b; + stb_prof(22); + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + stb_prof(3); + } else { + z += r->part_size; + c_inter = 0; + p_inter = z; + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } else { + while (pcount < part_read) { + int z = r->begin + pcount*r->part_size; + int c_inter = z % ch, p_inter = z/ch; + if (pass == 0) { + Codebook *c = f->codebooks+r->classbook; + int q; + DECODE(q,f,c); + if (q == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[0][class_set] = r->classdata[q]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[0][i+pcount] = q % r->classifications; + q /= r->classifications; + } + #endif + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + int z = r->begin + pcount*r->part_size; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[0][class_set][i]; + #else + int c = classifications[0][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + Codebook *book = f->codebooks + b; + stb_prof(22); + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) + goto done; + stb_prof(3); + } else { + z += r->part_size; + c_inter = z % ch; + p_inter = z / ch; + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } + } + goto done; + } + stb_prof(9); + + for (pass=0; pass < 8; ++pass) { + int pcount = 0, class_set=0; + while (pcount < part_read) { + if (pass == 0) { + for (j=0; j < ch; ++j) { + if (!do_not_decode[j]) { + Codebook *c = f->codebooks+r->classbook; + int temp; + DECODE(temp,f,c); + if (temp == EOP) goto done; + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + part_classdata[j][class_set] = r->classdata[temp]; + #else + for (i=classwords-1; i >= 0; --i) { + classifications[j][i+pcount] = temp % r->classifications; + temp /= r->classifications; + } + #endif + } + } + } + for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { + for (j=0; j < ch; ++j) { + if (!do_not_decode[j]) { + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + int c = part_classdata[j][class_set][i]; + #else + int c = classifications[j][pcount]; + #endif + int b = r->residue_books[c][pass]; + if (b >= 0) { + float *target = residue_buffers[j]; + int offset = r->begin + pcount * r->part_size; + int n = r->part_size; + Codebook *book = f->codebooks + b; + if (!residue_decode(f, book, target, offset, n, rtype)) + goto done; + } + } + } + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + ++class_set; + #endif + } + } + done: + stb_prof(0); + temp_alloc_restore(f,temp_alloc_point); +} + + +#if 0 +// slow way for debugging +void inverse_mdct_slow(float *buffer, int n) +{ + int i,j; + int n2 = n >> 1; + float *x = (float *) malloc(sizeof(*x) * n2); + memcpy(x, buffer, sizeof(*x) * n2); + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n2; ++j) + // formula from paper: + //acc += n/4.0f * x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); + // formula from wikipedia + //acc += 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); + // these are equivalent, except the formula from the paper inverts the multiplier! + // however, what actually works is NO MULTIPLIER!?! + //acc += 64 * 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5)); + acc += x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1)); + buffer[i] = acc; + } + free(x); +} +#elif 0 +// same as above, but just barely able to run in real time on modern machines +void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) +{ + float mcos[16384]; + int i,j; + int n2 = n >> 1, nmask = (n << 2) -1; + float *x = (float *) malloc(sizeof(*x) * n2); + memcpy(x, buffer, sizeof(*x) * n2); + for (i=0; i < 4*n; ++i) + mcos[i] = (float) cos(M_PI / 2 * i / n); + + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n2; ++j) + acc += x[j] * mcos[(2 * i + 1 + n2)*(2*j+1) & nmask]; + buffer[i] = acc; + } + free(x); +} +#else +// transform to use a slow dct-iv; this is STILL basically trivial, +// but only requires half as many ops +void dct_iv_slow(float *buffer, int n) +{ + float mcos[16384]; + float x[2048]; + int i,j; + int n2 = n >> 1, nmask = (n << 3) - 1; + memcpy(x, buffer, sizeof(*x) * n); + for (i=0; i < 8*n; ++i) + mcos[i] = (float) cos(M_PI / 4 * i / n); + for (i=0; i < n; ++i) { + float acc = 0; + for (j=0; j < n; ++j) + acc += x[j] * mcos[((2 * i + 1)*(2*j+1)) & nmask]; + //acc += x[j] * cos(M_PI / n * (i + 0.5) * (j + 0.5)); + buffer[i] = acc; + } + free(x); +} + +void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) +{ + int i, n4 = n >> 2, n2 = n >> 1, n3_4 = n - n4; + float temp[4096]; + + memcpy(temp, buffer, n2 * sizeof(float)); + dct_iv_slow(temp, n2); // returns -c'-d, a-b' + + for (i=0; i < n4 ; ++i) buffer[i] = temp[i+n4]; // a-b' + for ( ; i < n3_4; ++i) buffer[i] = -temp[n3_4 - i - 1]; // b-a', c+d' + for ( ; i < n ; ++i) buffer[i] = -temp[i - n3_4]; // c'+d +} +#endif + +#ifndef LIBVORBIS_MDCT +#define LIBVORBIS_MDCT 0 +#endif + +#if LIBVORBIS_MDCT +// directly call the vorbis MDCT using an interface documented +// by Jeff Roberts... useful for performance comparison +typedef struct +{ + int n; + int log2n; + + float *trig; + int *bitrev; + + float scale; +} mdct_lookup; + +extern void mdct_init(mdct_lookup *lookup, int n); +extern void mdct_clear(mdct_lookup *l); +extern void mdct_backward(mdct_lookup *init, float *in, float *out); + +mdct_lookup M1,M2; + +void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) +{ + mdct_lookup *M; + if (M1.n == n) M = &M1; + else if (M2.n == n) M = &M2; + else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; } + else { + if (M2.n) __asm int 3; + mdct_init(&M2, n); + M = &M2; + } + + mdct_backward(M, buffer, buffer); +} +#endif + + +// the following were split out into separate functions while optimizing; +// they could be pushed back up but eh. __forceinline showed no change; +// they're probably already being inlined. +static void imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A) +{ + float *ee0 = e + i_off; + float *ee2 = ee0 + k_off; + int i; + + assert((n & 3) == 0); + for (i=(n>>2); i > 0; --i) { + float k00_20, k01_21; + k00_20 = ee0[ 0] - ee2[ 0]; + k01_21 = ee0[-1] - ee2[-1]; + ee0[ 0] += ee2[ 0];//ee0[ 0] = ee0[ 0] + ee2[ 0]; + ee0[-1] += ee2[-1];//ee0[-1] = ee0[-1] + ee2[-1]; + ee2[ 0] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-1] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-2] - ee2[-2]; + k01_21 = ee0[-3] - ee2[-3]; + ee0[-2] += ee2[-2];//ee0[-2] = ee0[-2] + ee2[-2]; + ee0[-3] += ee2[-3];//ee0[-3] = ee0[-3] + ee2[-3]; + ee2[-2] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-3] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-4] - ee2[-4]; + k01_21 = ee0[-5] - ee2[-5]; + ee0[-4] += ee2[-4];//ee0[-4] = ee0[-4] + ee2[-4]; + ee0[-5] += ee2[-5];//ee0[-5] = ee0[-5] + ee2[-5]; + ee2[-4] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-5] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + + k00_20 = ee0[-6] - ee2[-6]; + k01_21 = ee0[-7] - ee2[-7]; + ee0[-6] += ee2[-6];//ee0[-6] = ee0[-6] + ee2[-6]; + ee0[-7] += ee2[-7];//ee0[-7] = ee0[-7] + ee2[-7]; + ee2[-6] = k00_20 * A[0] - k01_21 * A[1]; + ee2[-7] = k01_21 * A[0] + k00_20 * A[1]; + A += 8; + ee0 -= 8; + ee2 -= 8; + } +} + +static void imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1) +{ + int i; + float k00_20, k01_21; + + float *e0 = e + d0; + float *e2 = e0 + k_off; + + for (i=lim >> 2; i > 0; --i) { + k00_20 = e0[-0] - e2[-0]; + k01_21 = e0[-1] - e2[-1]; + e0[-0] += e2[-0];//e0[-0] = e0[-0] + e2[-0]; + e0[-1] += e2[-1];//e0[-1] = e0[-1] + e2[-1]; + e2[-0] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-1] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-2] - e2[-2]; + k01_21 = e0[-3] - e2[-3]; + e0[-2] += e2[-2];//e0[-2] = e0[-2] + e2[-2]; + e0[-3] += e2[-3];//e0[-3] = e0[-3] + e2[-3]; + e2[-2] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-3] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-4] - e2[-4]; + k01_21 = e0[-5] - e2[-5]; + e0[-4] += e2[-4];//e0[-4] = e0[-4] + e2[-4]; + e0[-5] += e2[-5];//e0[-5] = e0[-5] + e2[-5]; + e2[-4] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-5] = (k01_21)*A[0] + (k00_20) * A[1]; + + A += k1; + + k00_20 = e0[-6] - e2[-6]; + k01_21 = e0[-7] - e2[-7]; + e0[-6] += e2[-6];//e0[-6] = e0[-6] + e2[-6]; + e0[-7] += e2[-7];//e0[-7] = e0[-7] + e2[-7]; + e2[-6] = (k00_20)*A[0] - (k01_21) * A[1]; + e2[-7] = (k01_21)*A[0] + (k00_20) * A[1]; + + e0 -= 8; + e2 -= 8; + + A += k1; + } +} + +static void imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0) +{ + int i; + float A0 = A[0]; + float A1 = A[0+1]; + float A2 = A[0+a_off]; + float A3 = A[0+a_off+1]; + float A4 = A[0+a_off*2+0]; + float A5 = A[0+a_off*2+1]; + float A6 = A[0+a_off*3+0]; + float A7 = A[0+a_off*3+1]; + + float k00,k11; + + float *ee0 = e +i_off; + float *ee2 = ee0+k_off; + + for (i=n; i > 0; --i) { + k00 = ee0[ 0] - ee2[ 0]; + k11 = ee0[-1] - ee2[-1]; + ee0[ 0] = ee0[ 0] + ee2[ 0]; + ee0[-1] = ee0[-1] + ee2[-1]; + ee2[ 0] = (k00) * A0 - (k11) * A1; + ee2[-1] = (k11) * A0 + (k00) * A1; + + k00 = ee0[-2] - ee2[-2]; + k11 = ee0[-3] - ee2[-3]; + ee0[-2] = ee0[-2] + ee2[-2]; + ee0[-3] = ee0[-3] + ee2[-3]; + ee2[-2] = (k00) * A2 - (k11) * A3; + ee2[-3] = (k11) * A2 + (k00) * A3; + + k00 = ee0[-4] - ee2[-4]; + k11 = ee0[-5] - ee2[-5]; + ee0[-4] = ee0[-4] + ee2[-4]; + ee0[-5] = ee0[-5] + ee2[-5]; + ee2[-4] = (k00) * A4 - (k11) * A5; + ee2[-5] = (k11) * A4 + (k00) * A5; + + k00 = ee0[-6] - ee2[-6]; + k11 = ee0[-7] - ee2[-7]; + ee0[-6] = ee0[-6] + ee2[-6]; + ee0[-7] = ee0[-7] + ee2[-7]; + ee2[-6] = (k00) * A6 - (k11) * A7; + ee2[-7] = (k11) * A6 + (k00) * A7; + + ee0 -= k0; + ee2 -= k0; + } +} + +static __forceinline void iter_54(float *z) +{ + float k00,k11,k22,k33; + float y0,y1,y2,y3; + + k00 = z[ 0] - z[-4]; + y0 = z[ 0] + z[-4]; + y2 = z[-2] + z[-6]; + k22 = z[-2] - z[-6]; + + z[-0] = y0 + y2; // z0 + z4 + z2 + z6 + z[-2] = y0 - y2; // z0 + z4 - z2 - z6 + + // done with y0,y2 + + k33 = z[-3] - z[-7]; + + z[-4] = k00 + k33; // z0 - z4 + z3 - z7 + z[-6] = k00 - k33; // z0 - z4 - z3 + z7 + + // done with k33 + + k11 = z[-1] - z[-5]; + y1 = z[-1] + z[-5]; + y3 = z[-3] + z[-7]; + + z[-1] = y1 + y3; // z1 + z5 + z3 + z7 + z[-3] = y1 - y3; // z1 + z5 - z3 - z7 + z[-5] = k11 - k22; // z1 - z5 + z2 - z6 + z[-7] = k11 + k22; // z1 - z5 - z2 + z6 +} + +static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n) +{ + int k_off = -8; + int a_off = base_n >> 3; + float A2 = A[0+a_off]; + float *z = e + i_off; + float *base = z - 16 * n; + + while (z > base) { + float k00,k11; + + k00 = z[-0] - z[-8]; + k11 = z[-1] - z[-9]; + z[-0] = z[-0] + z[-8]; + z[-1] = z[-1] + z[-9]; + z[-8] = k00; + z[-9] = k11 ; + + k00 = z[ -2] - z[-10]; + k11 = z[ -3] - z[-11]; + z[ -2] = z[ -2] + z[-10]; + z[ -3] = z[ -3] + z[-11]; + z[-10] = (k00+k11) * A2; + z[-11] = (k11-k00) * A2; + + k00 = z[-12] - z[ -4]; // reverse to avoid a unary negation + k11 = z[ -5] - z[-13]; + z[ -4] = z[ -4] + z[-12]; + z[ -5] = z[ -5] + z[-13]; + z[-12] = k11; + z[-13] = k00; + + k00 = z[-14] - z[ -6]; // reverse to avoid a unary negation + k11 = z[ -7] - z[-15]; + z[ -6] = z[ -6] + z[-14]; + z[ -7] = z[ -7] + z[-15]; + z[-14] = (k00+k11) * A2; + z[-15] = (k00-k11) * A2; + + iter_54(z); + iter_54(z-8); + z -= 16; + } +} + +static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) +{ + int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; + int n3_4 = n - n4, ld; + // @OPTIMIZE: reduce register pressure by using fewer variables? + int save_point = temp_alloc_save(f); + float *buf2 = (float *) temp_alloc(f, n2 * sizeof(*buf2)); + float *u=NULL,*v=NULL; + // twiddle factors + float *A = f->A[blocktype]; + + // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" + // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function. + + // kernel from paper + + + // merged: + // copy and reflect spectral data + // step 0 + + // note that it turns out that the items added together during + // this step are, in fact, being added to themselves (as reflected + // by step 0). inexplicable inefficiency! this became obvious + // once I combined the passes. + + // so there's a missing 'times 2' here (for adding X to itself). + // this propogates through linearly to the end, where the numbers + // are 1/2 too small, and need to be compensated for. + + { + float *d,*e, *AA, *e_stop; + d = &buf2[n2-2]; + AA = A; + e = &buffer[0]; + e_stop = &buffer[n2]; + while (e != e_stop) { + d[1] = (e[0] * AA[0] - e[2]*AA[1]); + d[0] = (e[0] * AA[1] + e[2]*AA[0]); + d -= 2; + AA += 2; + e += 4; + } + + e = &buffer[n2-3]; + while (d >= buf2) { + d[1] = (-e[2] * AA[0] - -e[0]*AA[1]); + d[0] = (-e[2] * AA[1] + -e[0]*AA[0]); + d -= 2; + AA += 2; + e -= 4; + } + } + + // now we use symbolic names for these, so that we can + // possibly swap their meaning as we change which operations + // are in place + + u = buffer; + v = buf2; + + // step 2 (paper output is w, now u) + // this could be in place, but the data ends up in the wrong + // place... _somebody_'s got to swap it, so this is nominated + { + float *AA = &A[n2-8]; + float *d0,*d1, *e0, *e1; + + e0 = &v[n4]; + e1 = &v[0]; + + d0 = &u[n4]; + d1 = &u[0]; + + while (AA >= A) { + float v40_20, v41_21; + + v41_21 = e0[1] - e1[1]; + v40_20 = e0[0] - e1[0]; + d0[1] = e0[1] + e1[1]; + d0[0] = e0[0] + e1[0]; + d1[1] = v41_21*AA[4] - v40_20*AA[5]; + d1[0] = v40_20*AA[4] + v41_21*AA[5]; + + v41_21 = e0[3] - e1[3]; + v40_20 = e0[2] - e1[2]; + d0[3] = e0[3] + e1[3]; + d0[2] = e0[2] + e1[2]; + d1[3] = v41_21*AA[0] - v40_20*AA[1]; + d1[2] = v40_20*AA[0] + v41_21*AA[1]; + + AA -= 8; + + d0 += 4; + d1 += 4; + e0 += 4; + e1 += 4; + } + } + + // step 3 + ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + + // optimized step 3: + + // the original step3 loop can be nested r inside s or s inside r; + // it's written originally as s inside r, but this is dumb when r + // iterates many times, and s few. So I have two copies of it and + // switch between them halfway. + + // this is iteration 0 of step 3 + imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n >> 3), A); + imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n >> 3), A); + + // this is iteration 1 of step 3 + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n >> 4), A, 16); + imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n >> 4), A, 16); + + l=2; + for (; l < (ld-3)>>1; ++l) { + int k0 = n >> (l+2), k0_2 = k0>>1; + int lim = 1 << (l+1); + int i; + for (i=0; i < lim; ++i) + imdct_step3_inner_r_loop(n >> (l+4), u, n2-1 - k0*i, -k0_2, A, 1 << (l+3)); + } + + for (; l < ld-6; ++l) { + int k0 = n >> (l+2), k1 = 1 << (l+3), k0_2 = k0>>1; + int rlim = n >> (l+6), r; + int lim = 1 << (l+1); + int i_off; + float *A0 = A; + i_off = n2-1; + for (r=rlim; r > 0; --r) { + imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0); + A0 += k1*4; + i_off -= 8; + } + } + + // iterations with count: + // ld-6,-5,-4 all interleaved together + // the big win comes from getting rid of needless flops + // due to the constants on pass 5 & 4 being all 1 and 0; + // combining them to be simultaneous to improve cache made little difference + imdct_step3_inner_s_loop_ld654(n >> 5, u, n2-1, A, n); + + // output is u + + // step 4, 5, and 6 + // cannot be in-place because of step 5 + { + uint16 *bitrev = f->bit_reverse[blocktype]; + // weirdly, I'd have thought reading sequentially and writing + // erratically would have been better than vice-versa, but in + // fact that's not what my testing showed. (That is, with + // j = bitreverse(i), do you read i and write j, or read j and write i.) + + float *d0 = &v[n4-4]; + float *d1 = &v[n2-4]; + while (d0 >= v) { + int k4; + + k4 = bitrev[0]; + d1[3] = u[k4+0]; + d1[2] = u[k4+1]; + d0[3] = u[k4+2]; + d0[2] = u[k4+3]; + + k4 = bitrev[1]; + d1[1] = u[k4+0]; + d1[0] = u[k4+1]; + d0[1] = u[k4+2]; + d0[0] = u[k4+3]; + + d0 -= 4; + d1 -= 4; + bitrev += 2; + } + } + // (paper output is u, now v) + + + // data must be in buf2 + assert(v == buf2); + + // step 7 (paper output is v, now v) + // this is now in place + { + float *C = f->C[blocktype]; + float *d, *e; + + d = v; + e = v + n2 - 4; + + while (d < e) { + float a02,a11,b0,b1,b2,b3; + + a02 = d[0] - e[2]; + a11 = d[1] + e[3]; + + b0 = C[1]*a02 + C[0]*a11; + b1 = C[1]*a11 - C[0]*a02; + + b2 = d[0] + e[ 2]; + b3 = d[1] - e[ 3]; + + d[0] = b2 + b0; + d[1] = b3 + b1; + e[2] = b2 - b0; + e[3] = b1 - b3; + + a02 = d[2] - e[0]; + a11 = d[3] + e[1]; + + b0 = C[3]*a02 + C[2]*a11; + b1 = C[3]*a11 - C[2]*a02; + + b2 = d[2] + e[ 0]; + b3 = d[3] - e[ 1]; + + d[2] = b2 + b0; + d[3] = b3 + b1; + e[0] = b2 - b0; + e[1] = b1 - b3; + + C += 4; + d += 4; + e -= 4; + } + } + + // data must be in buf2 + + + // step 8+decode (paper output is X, now buffer) + // this generates pairs of data a la 8 and pushes them directly through + // the decode kernel (pushing rather than pulling) to avoid having + // to make another pass later + + // this cannot POSSIBLY be in place, so we refer to the buffers directly + + { + float *d0,*d1,*d2,*d3; + + float *B = f->B[blocktype] + n2 - 8; + float *e = buf2 + n2 - 8; + d0 = &buffer[0]; + d1 = &buffer[n2-4]; + d2 = &buffer[n2]; + d3 = &buffer[n-4]; + while (e >= v) { + float p0,p1,p2,p3; + + p3 = e[6]*B[7] - e[7]*B[6]; + p2 = -e[6]*B[6] - e[7]*B[7]; + + d0[0] = p3; + d1[3] = - p3; + d2[0] = p2; + d3[3] = p2; + + p1 = e[4]*B[5] - e[5]*B[4]; + p0 = -e[4]*B[4] - e[5]*B[5]; + + d0[1] = p1; + d1[2] = - p1; + d2[1] = p0; + d3[2] = p0; + + p3 = e[2]*B[3] - e[3]*B[2]; + p2 = -e[2]*B[2] - e[3]*B[3]; + + d0[2] = p3; + d1[1] = - p3; + d2[2] = p2; + d3[1] = p2; + + p1 = e[0]*B[1] - e[1]*B[0]; + p0 = -e[0]*B[0] - e[1]*B[1]; + + d0[3] = p1; + d1[0] = - p1; + d2[3] = p0; + d3[0] = p0; + + B -= 8; + e -= 8; + d0 += 4; + d2 += 4; + d1 -= 4; + d3 -= 4; + } + } + + temp_alloc_restore(f,save_point); +} + +#if 0 +// this is the original version of the above code, if you want to optimize it from scratch +void inverse_mdct_naive(float *buffer, int n) +{ + float s; + float A[1 << 12], B[1 << 12], C[1 << 11]; + int i,k,k2,k4, n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l; + int n3_4 = n - n4, ld; + // how can they claim this only uses N words?! + // oh, because they're only used sparsely, whoops + float u[1 << 13], X[1 << 13], v[1 << 13], w[1 << 13]; + // set up twiddle factors + + for (k=k2=0; k < n4; ++k,k2+=2) { + A[k2 ] = (float) cos(4*k*M_PI/n); + A[k2+1] = (float) -sin(4*k*M_PI/n); + B[k2 ] = (float) cos((k2+1)*M_PI/n/2); + B[k2+1] = (float) sin((k2+1)*M_PI/n/2); + } + for (k=k2=0; k < n8; ++k,k2+=2) { + C[k2 ] = (float) cos(2*(k2+1)*M_PI/n); + C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n); + } + + // IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio" + // Note there are bugs in that pseudocode, presumably due to them attempting + // to rename the arrays nicely rather than representing the way their actual + // implementation bounces buffers back and forth. As a result, even in the + // "some formulars corrected" version, a direct implementation fails. These + // are noted below as "paper bug". + + // copy and reflect spectral data + for (k=0; k < n2; ++k) u[k] = buffer[k]; + for ( ; k < n ; ++k) u[k] = -buffer[n - k - 1]; + // kernel from paper + // step 1 + for (k=k2=k4=0; k < n4; k+=1, k2+=2, k4+=4) { + v[n-k4-1] = (u[k4] - u[n-k4-1]) * A[k2] - (u[k4+2] - u[n-k4-3])*A[k2+1]; + v[n-k4-3] = (u[k4] - u[n-k4-1]) * A[k2+1] + (u[k4+2] - u[n-k4-3])*A[k2]; + } + // step 2 + for (k=k4=0; k < n8; k+=1, k4+=4) { + w[n2+3+k4] = v[n2+3+k4] + v[k4+3]; + w[n2+1+k4] = v[n2+1+k4] + v[k4+1]; + w[k4+3] = (v[n2+3+k4] - v[k4+3])*A[n2-4-k4] - (v[n2+1+k4]-v[k4+1])*A[n2-3-k4]; + w[k4+1] = (v[n2+1+k4] - v[k4+1])*A[n2-4-k4] + (v[n2+3+k4]-v[k4+3])*A[n2-3-k4]; + } + // step 3 + ld = ilog(n) - 1; // ilog is off-by-one from normal definitions + for (l=0; l < ld-3; ++l) { + int k0 = n >> (l+2), k1 = 1 << (l+3); + int rlim = n >> (l+4), r4, r; + int s2lim = 1 << (l+2), s2; + for (r=r4=0; r < rlim; r4+=4,++r) { + for (s2=0; s2 < s2lim; s2+=2) { + u[n-1-k0*s2-r4] = w[n-1-k0*s2-r4] + w[n-1-k0*(s2+1)-r4]; + u[n-3-k0*s2-r4] = w[n-3-k0*s2-r4] + w[n-3-k0*(s2+1)-r4]; + u[n-1-k0*(s2+1)-r4] = (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1] + - (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1+1]; + u[n-3-k0*(s2+1)-r4] = (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1] + + (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1+1]; + } + } + if (l+1 < ld-3) { + // paper bug: ping-ponging of u&w here is omitted + memcpy(w, u, sizeof(u)); + } + } + + // step 4 + for (i=0; i < n8; ++i) { + int j = bit_reverse(i) >> (32-ld+3); + assert(j < n8); + if (i == j) { + // paper bug: original code probably swapped in place; if copying, + // need to directly copy in this case + int i8 = i << 3; + v[i8+1] = u[i8+1]; + v[i8+3] = u[i8+3]; + v[i8+5] = u[i8+5]; + v[i8+7] = u[i8+7]; + } else if (i < j) { + int i8 = i << 3, j8 = j << 3; + v[j8+1] = u[i8+1], v[i8+1] = u[j8 + 1]; + v[j8+3] = u[i8+3], v[i8+3] = u[j8 + 3]; + v[j8+5] = u[i8+5], v[i8+5] = u[j8 + 5]; + v[j8+7] = u[i8+7], v[i8+7] = u[j8 + 7]; + } + } + // step 5 + for (k=0; k < n2; ++k) { + w[k] = v[k*2+1]; + } + // step 6 + for (k=k2=k4=0; k < n8; ++k, k2 += 2, k4 += 4) { + u[n-1-k2] = w[k4]; + u[n-2-k2] = w[k4+1]; + u[n3_4 - 1 - k2] = w[k4+2]; + u[n3_4 - 2 - k2] = w[k4+3]; + } + // step 7 + for (k=k2=0; k < n8; ++k, k2 += 2) { + v[n2 + k2 ] = ( u[n2 + k2] + u[n-2-k2] + C[k2+1]*(u[n2+k2]-u[n-2-k2]) + C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; + v[n-2 - k2] = ( u[n2 + k2] + u[n-2-k2] - C[k2+1]*(u[n2+k2]-u[n-2-k2]) - C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2; + v[n2+1+ k2] = ( u[n2+1+k2] - u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; + v[n-1 - k2] = (-u[n2+1+k2] + u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2; + } + // step 8 + for (k=k2=0; k < n4; ++k,k2 += 2) { + X[k] = v[k2+n2]*B[k2 ] + v[k2+1+n2]*B[k2+1]; + X[n2-1-k] = v[k2+n2]*B[k2+1] - v[k2+1+n2]*B[k2 ]; + } + + // decode kernel to output + // determined the following value experimentally + // (by first figuring out what made inverse_mdct_slow work); then matching that here + // (probably vorbis encoder premultiplies by n or n/2, to save it on the decoder?) + s = 0.5; // theoretically would be n4 + + // [[[ note! the s value of 0.5 is compensated for by the B[] in the current code, + // so it needs to use the "old" B values to behave correctly, or else + // set s to 1.0 ]]] + for (i=0; i < n4 ; ++i) buffer[i] = s * X[i+n4]; + for ( ; i < n3_4; ++i) buffer[i] = -s * X[n3_4 - i - 1]; + for ( ; i < n ; ++i) buffer[i] = -s * X[i - n3_4]; +} +#endif + +static float *get_window(vorb *f, int len) +{ + len <<= 1; + if (len == f->blocksize_0) return f->window[0]; + if (len == f->blocksize_1) return f->window[1]; + assert(0); + return NULL; +} + +#ifndef STB_VORBIS_NO_DEFER_FLOOR +typedef int16 YTYPE; +#else +typedef int YTYPE; +#endif +static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *finalY, uint8 *step2_flag) +{ + int n2 = n >> 1; + int s = map->chan[i].mux, floor; + floor = map->submap_floor[s]; + if (f->floor_types[floor] == 0) { + return error(f, VORBIS_invalid_stream); + } else { + Floor1 *g = &f->floor_config[floor].floor1; + int j,q; + int lx = 0, ly = finalY[0] * g->floor1_multiplier; + for (q=1; q < g->values; ++q) { + j = g->sorted_order[q]; + #ifndef STB_VORBIS_NO_DEFER_FLOOR + if (finalY[j] >= 0) + #else + if (step2_flag[j]) + #endif + { + int hy = finalY[j] * g->floor1_multiplier; + int hx = g->Xlist[j]; + draw_line(target, lx,ly, hx,hy, n2); + lx = hx, ly = hy; + } + } + if (lx < n2) + // optimization of: draw_line(target, lx,ly, n,ly, n2); + for (j=lx; j < n2; ++j) + LINE_OP(target[j], inverse_db_table[ly]); + } + return TRUE; +} + +static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) +{ + Mode *m; + int i, n, prev, next, window_center; + f->channel_buffer_start = f->channel_buffer_end = 0; + + retry: + if (f->eof) return FALSE; + if (!maybe_start_packet(f)) + return FALSE; + // check packet type + if (get_bits(f,1) != 0) { + if (IS_PUSH_MODE(f)) + return error(f,VORBIS_bad_packet_type); + while (EOP != get8_packet(f)); + goto retry; + } + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + + i = get_bits(f, ilog(f->mode_count-1)); + if (i == EOP) return FALSE; + if (i >= f->mode_count) return FALSE; + *mode = i; + m = f->mode_config + i; + if (m->blockflag) { + n = f->blocksize_1; + prev = get_bits(f,1); + next = get_bits(f,1); + } else { + prev = next = 0; + n = f->blocksize_0; + } + +// WINDOWING + + window_center = n >> 1; + if (m->blockflag && !prev) { + *p_left_start = (n - f->blocksize_0) >> 2; + *p_left_end = (n + f->blocksize_0) >> 2; + } else { + *p_left_start = 0; + *p_left_end = window_center; + } + if (m->blockflag && !next) { + *p_right_start = (n*3 - f->blocksize_0) >> 2; + *p_right_end = (n*3 + f->blocksize_0) >> 2; + } else { + *p_right_start = window_center; + *p_right_end = n; + } + return TRUE; +} + +static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, int left_end, int right_start, int right_end, int *p_left) +{ + Mapping *map; + int i,j,k,n,n2; + int zero_channel[256]; + int really_zero_channel[256]; + int window_center; + +// WINDOWING + + n = f->blocksize[m->blockflag]; + window_center = n >> 1; + + map = &f->mapping[m->mapping]; + +// FLOORS + n2 = n >> 1; + + stb_prof(1); + for (i=0; i < f->channels; ++i) { + int s = map->chan[i].mux, floor; + zero_channel[i] = FALSE; + floor = map->submap_floor[s]; + if (f->floor_types[floor] == 0) { + return error(f, VORBIS_invalid_stream); + } else { + Floor1 *g = &f->floor_config[floor].floor1; + if (get_bits(f, 1)) { + short *finalY; + uint8 step2_flag[256]; + static int range_list[4] = { 256, 128, 86, 64 }; + int range = range_list[g->floor1_multiplier-1]; + int offset = 2; + finalY = f->finalY[i]; + finalY[0] = get_bits(f, ilog(range)-1); + finalY[1] = get_bits(f, ilog(range)-1); + for (j=0; j < g->partitions; ++j) { + int pclass = g->partition_class_list[j]; + int cdim = g->class_dimensions[pclass]; + int cbits = g->class_subclasses[pclass]; + int csub = (1 << cbits)-1; + int cval = 0; + if (cbits) { + Codebook *c = f->codebooks + g->class_masterbooks[pclass]; + DECODE(cval,f,c); + } + for (k=0; k < cdim; ++k) { + int book = g->subclass_books[pclass][cval & csub]; + cval = cval >> cbits; + if (book >= 0) { + int temp; + Codebook *c = f->codebooks + book; + DECODE(temp,f,c); + finalY[offset++] = temp; + } else + finalY[offset++] = 0; + } + } + if (f->valid_bits == INVALID_BITS) goto error; // behavior according to spec + step2_flag[0] = step2_flag[1] = 1; + for (j=2; j < g->values; ++j) { + int low, high, pred, highroom, lowroom, room, val; + low = g->neighbors[j][0]; + high = g->neighbors[j][1]; + //neighbors(g->Xlist, j, &low, &high); + pred = predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]); + val = finalY[j]; + highroom = range - pred; + lowroom = pred; + if (highroom < lowroom) + room = highroom * 2; + else + room = lowroom * 2; + if (val) { + step2_flag[low] = step2_flag[high] = 1; + step2_flag[j] = 1; + if (val >= room) + if (highroom > lowroom) + finalY[j] = val - lowroom + pred; + else + finalY[j] = pred - val + highroom - 1; + else + if (val & 1) + finalY[j] = pred - ((val+1)>>1); + else + finalY[j] = pred + (val>>1); + } else { + step2_flag[j] = 0; + finalY[j] = pred; + } + } + +#ifdef STB_VORBIS_NO_DEFER_FLOOR + do_floor(f, map, i, n, f->floor_buffers[i], finalY, step2_flag); +#else + // defer final floor computation until _after_ residue + for (j=0; j < g->values; ++j) { + if (!step2_flag[j]) + finalY[j] = -1; + } +#endif + } else { + error: + zero_channel[i] = TRUE; + } + // So we just defer everything else to later + + // at this point we've decoded the floor into buffer + } + } + stb_prof(0); + // at this point we've decoded all floors + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + + // re-enable coupled channels if necessary + memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels); + for (i=0; i < map->coupling_steps; ++i) + if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) { + zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE; + } + +// RESIDUE DECODE + for (i=0; i < map->submaps; ++i) { + float *residue_buffers[STB_VORBIS_MAX_CHANNELS]; + int r,t; + uint8 do_not_decode[256]; + int ch = 0; + for (j=0; j < f->channels; ++j) { + if (map->chan[j].mux == i) { + if (zero_channel[j]) { + do_not_decode[ch] = TRUE; + residue_buffers[ch] = NULL; + } else { + do_not_decode[ch] = FALSE; + residue_buffers[ch] = f->channel_buffers[j]; + } + ++ch; + } + } + r = map->submap_residue[i]; + t = f->residue_types[r]; + decode_residue(f, residue_buffers, ch, n2, r, do_not_decode); + } + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + +// INVERSE COUPLING + stb_prof(14); + for (i = map->coupling_steps-1; i >= 0; --i) { + int n2 = n >> 1; + float *m = f->channel_buffers[map->chan[i].magnitude]; + float *a = f->channel_buffers[map->chan[i].angle ]; + for (j=0; j < n2; ++j) { + float a2,m2; + if (m[j] > 0) + if (a[j] > 0) + m2 = m[j], a2 = m[j] - a[j]; + else + a2 = m[j], m2 = m[j] + a[j]; + else + if (a[j] > 0) + m2 = m[j], a2 = m[j] + a[j]; + else + a2 = m[j], m2 = m[j] - a[j]; + m[j] = m2; + a[j] = a2; + } + } + + // finish decoding the floors +#ifndef STB_VORBIS_NO_DEFER_FLOOR + stb_prof(15); + for (i=0; i < f->channels; ++i) { + if (really_zero_channel[i]) { + memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); + } else { + do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL); + } + } +#else + for (i=0; i < f->channels; ++i) { + if (really_zero_channel[i]) { + memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); + } else { + for (j=0; j < n2; ++j) + f->channel_buffers[i][j] *= f->floor_buffers[i][j]; + } + } +#endif + +// INVERSE MDCT + stb_prof(16); + for (i=0; i < f->channels; ++i) + inverse_mdct(f->channel_buffers[i], n, f, m->blockflag); + stb_prof(0); + + // this shouldn't be necessary, unless we exited on an error + // and want to flush to get to the next packet + flush_packet(f); + + if (f->first_decode) { + // assume we start so first non-discarded sample is sample 0 + // this isn't to spec, but spec would require us to read ahead + // and decode the size of all current frames--could be done, + // but presumably it's not a commonly used feature + f->current_loc = -n2; // start of first frame is positioned for discard + // we might have to discard samples "from" the next frame too, + // if we're lapping a large block then a small at the start? + f->discard_samples_deferred = n - right_end; + f->current_loc_valid = TRUE; + f->first_decode = FALSE; + } else if (f->discard_samples_deferred) { + left_start += f->discard_samples_deferred; + *p_left = left_start; + f->discard_samples_deferred = 0; + } else if (f->previous_length == 0 && f->current_loc_valid) { + // we're recovering from a seek... that means we're going to discard + // the samples from this packet even though we know our position from + // the last page header, so we need to update the position based on + // the discarded samples here + // but wait, the code below is going to add this in itself even + // on a discard, so we don't need to do it here... + } + + // check if we have ogg information about the sample # for this packet + if (f->last_seg_which == f->end_seg_with_known_loc) { + // if we have a valid current loc, and this is final: + if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { + uint32 current_end = f->known_loc_for_packet - (n-right_end); + // then let's infer the size of the (probably) short final frame + if (current_end < f->current_loc + right_end) { + if (current_end < f->current_loc) { + // negative truncation, that's impossible! + *len = 0; + } else { + *len = current_end - f->current_loc; + } + *len += left_start; + f->current_loc += *len; + return TRUE; + } + } + // otherwise, just set our sample loc + // guess that the ogg granule pos refers to the _middle_ of the + // last frame? + // set f->current_loc to the position of left_start + f->current_loc = f->known_loc_for_packet - (n2-left_start); + f->current_loc_valid = TRUE; + } + if (f->current_loc_valid) + f->current_loc += (right_start - left_start); + + if (f->alloc.alloc_buffer) + assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + *len = right_end; // ignore samples after the window goes to 0 + return TRUE; +} + +static int vorbis_decode_packet(vorb *f, int *len, int *p_left, int *p_right) +{ + int mode, left_end, right_end; + if (!vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0; + return vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left); +} + +static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right) +{ + int prev,i,j; + // we use right&left (the start of the right- and left-window sin()-regions) + // to determine how much to return, rather than inferring from the rules + // (same result, clearer code); 'left' indicates where our sin() window + // starts, therefore where the previous window's right edge starts, and + // therefore where to start mixing from the previous buffer. 'right' + // indicates where our sin() ending-window starts, therefore that's where + // we start saving, and where our returned-data ends. + + // mixin from previous window + if (f->previous_length) { + int i,j, n = f->previous_length; + float *w = get_window(f, n); + for (i=0; i < f->channels; ++i) { + for (j=0; j < n; ++j) + f->channel_buffers[i][left+j] = + f->channel_buffers[i][left+j]*w[ j] + + f->previous_window[i][ j]*w[n-1-j]; + } + } + + prev = f->previous_length; + + // last half of this data becomes previous window + f->previous_length = len - right; + + // @OPTIMIZE: could avoid this copy by double-buffering the + // output (flipping previous_window with channel_buffers), but + // then previous_window would have to be 2x as large, and + // channel_buffers couldn't be temp mem (although they're NOT + // currently temp mem, they could be (unless we want to level + // performance by spreading out the computation)) + for (i=0; i < f->channels; ++i) + for (j=0; right+j < len; ++j) + f->previous_window[i][j] = f->channel_buffers[i][right+j]; + + if (!prev) + // there was no previous packet, so this data isn't valid... + // this isn't entirely true, only the would-have-overlapped data + // isn't valid, but this seems to be what the spec requires + return 0; + + // truncate a short frame + if (len < right) right = len; + + f->samples_output += right-left; + + return right - left; +} + +static void vorbis_pump_first_frame(stb_vorbis *f) +{ + int len, right, left; + if (vorbis_decode_packet(f, &len, &left, &right)) + vorbis_finish_frame(f, len, left, right); +} + +#ifndef STB_VORBIS_NO_PUSHDATA_API +static int is_whole_packet_present(stb_vorbis *f, int end_page) +{ + // make sure that we have the packet available before continuing... + // this requires a full ogg parse, but we know we can fetch from f->stream + + // instead of coding this out explicitly, we could save the current read state, + // read the next packet with get8() until end-of-packet, check f->eof, then + // reset the state? but that would be slower, esp. since we'd have over 256 bytes + // of state to restore (primarily the page segment table) + + int s = f->next_seg, first = TRUE; + uint8 *p = f->stream; + + if (s != -1) { // if we're not starting the packet with a 'continue on next page' flag + for (; s < f->segment_count; ++s) { + p += f->segments[s]; + if (f->segments[s] < 255) // stop at first short segment + break; + } + // either this continues, or it ends it... + if (end_page) + if (s < f->segment_count-1) return error(f, VORBIS_invalid_stream); + if (s == f->segment_count) + s = -1; // set 'crosses page' flag + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + first = FALSE; + } + for (; s == -1;) { + uint8 *q; + int n; + + // check that we have the page header ready + if (p + 26 >= f->stream_end) return error(f, VORBIS_need_more_data); + // validate the page + if (memcmp(p, ogg_page_header, 4)) return error(f, VORBIS_invalid_stream); + if (p[4] != 0) return error(f, VORBIS_invalid_stream); + if (first) { // the first segment must NOT have 'continued_packet', later ones MUST + if (f->previous_length) + if ((p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); + // if no previous length, we're resynching, so we can come in on a continued-packet, + // which we'll just drop + } else { + if (!(p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream); + } + n = p[26]; // segment counts + q = p+27; // q points to segment table + p = q + n; // advance past header + // make sure we've read the segment table + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + for (s=0; s < n; ++s) { + p += q[s]; + if (q[s] < 255) + break; + } + if (end_page) + if (s < n-1) return error(f, VORBIS_invalid_stream); + if (s == f->segment_count) + s = -1; // set 'crosses page' flag + if (p > f->stream_end) return error(f, VORBIS_need_more_data); + first = FALSE; + } + return TRUE; +} +#endif // !STB_VORBIS_NO_PUSHDATA_API + +static int start_decoder(vorb *f) +{ + uint8 header[6], x,y; + int len,i,j,k, max_submaps = 0; + int longest_floorlist=0; + + // first page, first packet + + if (!start_page(f)) return FALSE; + // validate page flag + if (!(f->page_flag & PAGEFLAG_first_page)) return error(f, VORBIS_invalid_first_page); + if (f->page_flag & PAGEFLAG_last_page) return error(f, VORBIS_invalid_first_page); + if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page); + // check for expected packet length + if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page); + if (f->segments[0] != 30) return error(f, VORBIS_invalid_first_page); + // read packet + // check packet header + if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page); + if (!getn(f, header, 6)) return error(f, VORBIS_unexpected_eof); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_first_page); + // vorbis_version + if (get32(f) != 0) return error(f, VORBIS_invalid_first_page); + f->channels = get8(f); if (!f->channels) return error(f, VORBIS_invalid_first_page); + if (f->channels > STB_VORBIS_MAX_CHANNELS) return error(f, VORBIS_too_many_channels); + f->sample_rate = get32(f); if (!f->sample_rate) return error(f, VORBIS_invalid_first_page); + get32(f); // bitrate_maximum + get32(f); // bitrate_nominal + get32(f); // bitrate_minimum + x = get8(f); + { int log0,log1; + log0 = x & 15; + log1 = x >> 4; + f->blocksize_0 = 1 << log0; + f->blocksize_1 = 1 << log1; + if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup); + if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup); + if (log0 > log1) return error(f, VORBIS_invalid_setup); + } + + // framing_flag + x = get8(f); + if (!(x & 1)) return error(f, VORBIS_invalid_first_page); + + // second packet! + if (!start_page(f)) return FALSE; + + if (!start_packet(f)) return FALSE; + do { + len = next_segment(f); + skip(f, len); + f->bytes_in_seg = 0; + } while (len); + + // third packet! + if (!start_packet(f)) return FALSE; + + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (IS_PUSH_MODE(f)) { + if (!is_whole_packet_present(f, TRUE)) { + // convert error in ogg header to write type + if (f->error == VORBIS_invalid_stream) + f->error = VORBIS_invalid_setup; + return FALSE; + } + } + #endif + + crc32_init(); // always init it, to avoid multithread race conditions + + if (get8_packet(f) != VORBIS_packet_setup) return error(f, VORBIS_invalid_setup); + for (i=0; i < 6; ++i) header[i] = get8_packet(f); + if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup); + + // codebooks + + f->codebook_count = get_bits(f,8) + 1; + f->codebooks = (Codebook *) setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count); + if (f->codebooks == NULL) return error(f, VORBIS_outofmem); + memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count); + for (i=0; i < f->codebook_count; ++i) { + uint32 *values; + int ordered, sorted_count; + int total=0; + uint8 *lengths; + Codebook *c = f->codebooks+i; + x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup); + x = get_bits(f, 8); + c->dimensions = (get_bits(f, 8)<<8) + x; + x = get_bits(f, 8); + y = get_bits(f, 8); + c->entries = (get_bits(f, 8)<<16) + (y<<8) + x; + ordered = get_bits(f,1); + c->sparse = ordered ? 0 : get_bits(f,1); + + if (c->sparse) + lengths = (uint8 *) setup_temp_malloc(f, c->entries); + else + lengths = c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); + + if (!lengths) return error(f, VORBIS_outofmem); + + if (ordered) { + int current_entry = 0; + int current_length = get_bits(f,5) + 1; + while (current_entry < c->entries) { + int limit = c->entries - current_entry; + int n = get_bits(f, ilog(limit)); + if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); } + memset(lengths + current_entry, current_length, n); + current_entry += n; + ++current_length; + } + } else { + for (j=0; j < c->entries; ++j) { + int present = c->sparse ? get_bits(f,1) : 1; + if (present) { + lengths[j] = get_bits(f, 5) + 1; + ++total; + } else { + lengths[j] = NO_CODE; + } + } + } + + if (c->sparse && total >= c->entries >> 2) { + // convert sparse items to non-sparse! + if (c->entries > (int) f->setup_temp_memory_required) + f->setup_temp_memory_required = c->entries; + + c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries); + memcpy(c->codeword_lengths, lengths, c->entries); + setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs! + lengths = c->codeword_lengths; + c->sparse = 0; + } + + // compute the size of the sorted tables + if (c->sparse) { + sorted_count = total; + //assert(total != 0); + } else { + sorted_count = 0; + #ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH + for (j=0; j < c->entries; ++j) + if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE) + ++sorted_count; + #endif + } + + c->sorted_entries = sorted_count; + values = NULL; + + if (!c->sparse) { + c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries); + if (!c->codewords) return error(f, VORBIS_outofmem); + } else { + unsigned int size; + if (c->sorted_entries) { + c->codeword_lengths = (uint8 *) setup_malloc(f, c->sorted_entries); + if (!c->codeword_lengths) return error(f, VORBIS_outofmem); + c->codewords = (uint32 *) setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries); + if (!c->codewords) return error(f, VORBIS_outofmem); + values = (uint32 *) setup_temp_malloc(f, sizeof(*values) * c->sorted_entries); + if (!values) return error(f, VORBIS_outofmem); + } + size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries; + if (size > f->setup_temp_memory_required) + f->setup_temp_memory_required = size; + } + + if (!compute_codewords(c, lengths, c->entries, values)) { + if (c->sparse) setup_temp_free(f, values, 0); + return error(f, VORBIS_invalid_setup); + } + + if (c->sorted_entries) { + // allocate an extra slot for sentinels + c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1)); + // allocate an extra slot at the front so that c->sorted_values[-1] is defined + // so that we can catch that case without an extra if + c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1)); + if (c->sorted_values) { ++c->sorted_values; c->sorted_values[-1] = -1; } + compute_sorted_huffman(c, lengths, values); + } + + if (c->sparse) { + setup_temp_free(f, values, sizeof(*values)*c->sorted_entries); + setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries); + setup_temp_free(f, lengths, c->entries); + c->codewords = NULL; + } + + compute_accelerated_huffman(c); + + c->lookup_type = get_bits(f, 4); + if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup); + if (c->lookup_type > 0) { + uint16 *mults; + c->minimum_value = float32_unpack(get_bits(f, 32)); + c->delta_value = float32_unpack(get_bits(f, 32)); + c->value_bits = get_bits(f, 4)+1; + c->sequence_p = get_bits(f,1); + if (c->lookup_type == 1) { + c->lookup_values = lookup1_values(c->entries, c->dimensions); + } else { + c->lookup_values = c->entries * c->dimensions; + } + mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values); + if (mults == NULL) return error(f, VORBIS_outofmem); + for (j=0; j < (int) c->lookup_values; ++j) { + int q = get_bits(f, c->value_bits); + if (q == EOP) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); } + mults[j] = q; + } + +#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK + if (c->lookup_type == 1) { + int len, sparse = c->sparse; + // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop + if (sparse) { + if (c->sorted_entries == 0) goto skip; + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions); + } else + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions); + if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } + len = sparse ? c->sorted_entries : c->entries; + for (j=0; j < len; ++j) { + int z = sparse ? c->sorted_values[j] : j, div=1; + for (k=0; k < c->dimensions; ++k) { + int off = (z / div) % c->lookup_values; + c->multiplicands[j*c->dimensions + k] = + #ifndef STB_VORBIS_CODEBOOK_FLOATS + mults[off]; + #else + mults[off]*c->delta_value + c->minimum_value; + // in this case (and this case only) we could pre-expand c->sequence_p, + // and throw away the decode logic for it; have to ALSO do + // it in the case below, but it can only be done if + // STB_VORBIS_CODEBOOK_FLOATS + // !STB_VORBIS_DIVIDES_IN_CODEBOOK + #endif + div *= c->lookup_values; + } + } + setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); + c->lookup_type = 2; + } + else +#endif + { + c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); + #ifndef STB_VORBIS_CODEBOOK_FLOATS + memcpy(c->multiplicands, mults, sizeof(c->multiplicands[0]) * c->lookup_values); + #else + for (j=0; j < (int) c->lookup_values; ++j) + c->multiplicands[j] = mults[j] * c->delta_value + c->minimum_value; + setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); + #endif + } + skip:; + + #ifdef STB_VORBIS_CODEBOOK_FLOATS + if (c->lookup_type == 2 && c->sequence_p) { + for (j=1; j < (int) c->lookup_values; ++j) + c->multiplicands[j] = c->multiplicands[j-1]; + c->sequence_p = 0; + } + #endif + } + } + + // time domain transfers (notused) + + x = get_bits(f, 6) + 1; + for (i=0; i < x; ++i) { + uint32 z = get_bits(f, 16); + if (z != 0) return error(f, VORBIS_invalid_setup); + } + + // Floors + f->floor_count = get_bits(f, 6)+1; + f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config)); + for (i=0; i < f->floor_count; ++i) { + f->floor_types[i] = get_bits(f, 16); + if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup); + if (f->floor_types[i] == 0) { + Floor0 *g = &f->floor_config[i].floor0; + g->order = get_bits(f,8); + g->rate = get_bits(f,16); + g->bark_map_size = get_bits(f,16); + g->amplitude_bits = get_bits(f,6); + g->amplitude_offset = get_bits(f,8); + g->number_of_books = get_bits(f,4) + 1; + for (j=0; j < g->number_of_books; ++j) + g->book_list[j] = get_bits(f,8); + return error(f, VORBIS_feature_not_supported); + } else { + Point p[31*8+2]; + Floor1 *g = &f->floor_config[i].floor1; + int max_class = -1; + g->partitions = get_bits(f, 5); + for (j=0; j < g->partitions; ++j) { + g->partition_class_list[j] = get_bits(f, 4); + if (g->partition_class_list[j] > max_class) + max_class = g->partition_class_list[j]; + } + for (j=0; j <= max_class; ++j) { + g->class_dimensions[j] = get_bits(f, 3)+1; + g->class_subclasses[j] = get_bits(f, 2); + if (g->class_subclasses[j]) { + g->class_masterbooks[j] = get_bits(f, 8); + if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + for (k=0; k < 1 << g->class_subclasses[j]; ++k) { + g->subclass_books[j][k] = get_bits(f,8)-1; + if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } + } + g->floor1_multiplier = get_bits(f,2)+1; + g->rangebits = get_bits(f,4); + g->Xlist[0] = 0; + g->Xlist[1] = 1 << g->rangebits; + g->values = 2; + for (j=0; j < g->partitions; ++j) { + int c = g->partition_class_list[j]; + for (k=0; k < g->class_dimensions[c]; ++k) { + g->Xlist[g->values] = get_bits(f, g->rangebits); + ++g->values; + } + } + // precompute the sorting + for (j=0; j < g->values; ++j) { + p[j].x = g->Xlist[j]; + p[j].y = j; + } + qsort(p, g->values, sizeof(p[0]), point_compare); + for (j=0; j < g->values; ++j) + g->sorted_order[j] = (uint8) p[j].y; + // precompute the neighbors + for (j=2; j < g->values; ++j) { + int low,hi; + neighbors(g->Xlist, j, &low,&hi); + g->neighbors[j][0] = low; + g->neighbors[j][1] = hi; + } + + if (g->values > longest_floorlist) + longest_floorlist = g->values; + } + } + + // Residue + f->residue_count = get_bits(f, 6)+1; + f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(*f->residue_config)); + for (i=0; i < f->residue_count; ++i) { + uint8 residue_cascade[64]; + Residue *r = f->residue_config+i; + f->residue_types[i] = get_bits(f, 16); + if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup); + r->begin = get_bits(f, 24); + r->end = get_bits(f, 24); + r->part_size = get_bits(f,24)+1; + r->classifications = get_bits(f,6)+1; + r->classbook = get_bits(f,8); + for (j=0; j < r->classifications; ++j) { + uint8 high_bits=0; + uint8 low_bits=get_bits(f,3); + if (get_bits(f,1)) + high_bits = get_bits(f,5); + residue_cascade[j] = high_bits*8 + low_bits; + } + r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications); + for (j=0; j < r->classifications; ++j) { + for (k=0; k < 8; ++k) { + if (residue_cascade[j] & (1 << k)) { + r->residue_books[j][k] = get_bits(f, 8); + if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup); + } else { + r->residue_books[j][k] = -1; + } + } + } + // precompute the classifications[] array to avoid inner-loop mod/divide + // call it 'classdata' since we already have r->classifications + r->classdata = (uint8 **) setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); + if (!r->classdata) return error(f, VORBIS_outofmem); + memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries); + for (j=0; j < f->codebooks[r->classbook].entries; ++j) { + int classwords = f->codebooks[r->classbook].dimensions; + int temp = j; + r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords); + for (k=classwords-1; k >= 0; --k) { + r->classdata[j][k] = temp % r->classifications; + temp /= r->classifications; + } + } + } + + f->mapping_count = get_bits(f,6)+1; + f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping)); + for (i=0; i < f->mapping_count; ++i) { + Mapping *m = f->mapping + i; + int mapping_type = get_bits(f,16); + if (mapping_type != 0) return error(f, VORBIS_invalid_setup); + m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan)); + if (get_bits(f,1)) + m->submaps = get_bits(f,4); + else + m->submaps = 1; + if (m->submaps > max_submaps) + max_submaps = m->submaps; + if (get_bits(f,1)) { + m->coupling_steps = get_bits(f,8)+1; + for (k=0; k < m->coupling_steps; ++k) { + m->chan[k].magnitude = get_bits(f, ilog(f->channels)-1); + m->chan[k].angle = get_bits(f, ilog(f->channels)-1); + if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup); + if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup); + if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup); + } + } else + m->coupling_steps = 0; + + // reserved field + if (get_bits(f,2)) return error(f, VORBIS_invalid_setup); + if (m->submaps > 1) { + for (j=0; j < f->channels; ++j) { + m->chan[j].mux = get_bits(f, 4); + if (m->chan[j].mux >= m->submaps) return error(f, VORBIS_invalid_setup); + } + } else + // @SPECIFICATION: this case is missing from the spec + for (j=0; j < f->channels; ++j) + m->chan[j].mux = 0; + + for (j=0; j < m->submaps; ++j) { + get_bits(f,8); // discard + m->submap_floor[j] = get_bits(f,8); + m->submap_residue[j] = get_bits(f,8); + if (m->submap_floor[j] >= f->floor_count) return error(f, VORBIS_invalid_setup); + if (m->submap_residue[j] >= f->residue_count) return error(f, VORBIS_invalid_setup); + } + } + + // Modes + f->mode_count = get_bits(f, 6)+1; + for (i=0; i < f->mode_count; ++i) { + Mode *m = f->mode_config+i; + m->blockflag = get_bits(f,1); + m->windowtype = get_bits(f,16); + m->transformtype = get_bits(f,16); + m->mapping = get_bits(f,8); + if (m->windowtype != 0) return error(f, VORBIS_invalid_setup); + if (m->transformtype != 0) return error(f, VORBIS_invalid_setup); + if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup); + } + + flush_packet(f); + + f->previous_length = 0; + + for (i=0; i < f->channels; ++i) { + f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1); + f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); + f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist); + #ifdef STB_VORBIS_NO_DEFER_FLOOR + f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); + #endif + } + + if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE; + if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE; + f->blocksize[0] = f->blocksize_0; + f->blocksize[1] = f->blocksize_1; + +#ifdef STB_VORBIS_DIVIDE_TABLE + if (integer_divide_table[1][1]==0) + for (i=0; i < DIVTAB_NUMER; ++i) + for (j=1; j < DIVTAB_DENOM; ++j) + integer_divide_table[i][j] = i / j; +#endif + + // compute how much temporary memory is needed + + // 1. + { + uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1); + uint32 classify_mem; + int i,max_part_read=0; + for (i=0; i < f->residue_count; ++i) { + Residue *r = f->residue_config + i; + int n_read = r->end - r->begin; + int part_read = n_read / r->part_size; + if (part_read > max_part_read) + max_part_read = part_read; + } + #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE + classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8 *)); + #else + classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); + #endif + + f->temp_memory_required = classify_mem; + if (imdct_mem > f->temp_memory_required) + f->temp_memory_required = imdct_mem; + } + + f->first_decode = TRUE; + + if (f->alloc.alloc_buffer) { + assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes); + // check if there's enough temp memory so we don't error later + if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset) + return error(f, VORBIS_outofmem); + } + + f->first_audio_page_offset = stb_vorbis_get_file_offset(f); + + return TRUE; +} + +static void vorbis_deinit(stb_vorbis *p) +{ + int i,j; + for (i=0; i < p->residue_count; ++i) { + Residue *r = p->residue_config+i; + if (r->classdata) { + for (j=0; j < p->codebooks[r->classbook].entries; ++j) + setup_free(p, r->classdata[j]); + setup_free(p, r->classdata); + } + setup_free(p, r->residue_books); + } + + if (p->codebooks) { + for (i=0; i < p->codebook_count; ++i) { + Codebook *c = p->codebooks + i; + setup_free(p, c->codeword_lengths); + setup_free(p, c->multiplicands); + setup_free(p, c->codewords); + setup_free(p, c->sorted_codewords); + // c->sorted_values[-1] is the first entry in the array + setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL); + } + setup_free(p, p->codebooks); + } + setup_free(p, p->floor_config); + setup_free(p, p->residue_config); + for (i=0; i < p->mapping_count; ++i) + setup_free(p, p->mapping[i].chan); + setup_free(p, p->mapping); + for (i=0; i < p->channels; ++i) { + setup_free(p, p->channel_buffers[i]); + setup_free(p, p->previous_window[i]); + #ifdef STB_VORBIS_NO_DEFER_FLOOR + setup_free(p, p->floor_buffers[i]); + #endif + setup_free(p, p->finalY[i]); + } + for (i=0; i < 2; ++i) { + setup_free(p, p->A[i]); + setup_free(p, p->B[i]); + setup_free(p, p->C[i]); + setup_free(p, p->window[i]); + } + #ifndef STB_VORBIS_NO_STDIO + if (p->close_on_free) fclose(p->f); + #endif +} + +void stb_vorbis_close(stb_vorbis *p) +{ + if (p == NULL) return; + vorbis_deinit(p); + setup_free(p,p); +} + +static void vorbis_init(stb_vorbis *p, stb_vorbis_alloc *z) +{ + memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start + if (z) { + p->alloc = *z; + p->alloc.alloc_buffer_length_in_bytes = (p->alloc.alloc_buffer_length_in_bytes+3) & ~3; + p->temp_offset = p->alloc.alloc_buffer_length_in_bytes; + } + p->eof = 0; + p->error = VORBIS__no_error; + p->stream = NULL; + p->codebooks = NULL; + p->page_crc_tests = -1; + #ifndef STB_VORBIS_NO_STDIO + p->close_on_free = FALSE; + p->f = NULL; + #endif +} + +int stb_vorbis_get_sample_offset(stb_vorbis *f) +{ + if (f->current_loc_valid) + return f->current_loc; + else + return -1; +} + +stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f) +{ + stb_vorbis_info d; + d.channels = f->channels; + d.sample_rate = f->sample_rate; + d.setup_memory_required = f->setup_memory_required; + d.setup_temp_memory_required = f->setup_temp_memory_required; + d.temp_memory_required = f->temp_memory_required; + d.max_frame_size = f->blocksize_1 >> 1; + return d; +} + +int stb_vorbis_get_error(stb_vorbis *f) +{ + int e = f->error; + f->error = VORBIS__no_error; + return e; +} + +static stb_vorbis * vorbis_alloc(stb_vorbis *f) +{ + stb_vorbis *p = (stb_vorbis *) setup_malloc(f, sizeof(*p)); + return p; +} + +#ifndef STB_VORBIS_NO_PUSHDATA_API + +void stb_vorbis_flush_pushdata(stb_vorbis *f) +{ + f->previous_length = 0; + f->page_crc_tests = 0; + f->discard_samples_deferred = 0; + f->current_loc_valid = FALSE; + f->first_decode = FALSE; + f->samples_output = 0; + f->channel_buffer_start = 0; + f->channel_buffer_end = 0; +} + +static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len) +{ + int i,n; + for (i=0; i < f->page_crc_tests; ++i) + f->scan[i].bytes_done = 0; + + // if we have room for more scans, search for them first, because + // they may cause us to stop early if their header is incomplete + if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) { + if (data_len < 4) return 0; + data_len -= 3; // need to look for 4-byte sequence, so don't miss + // one that straddles a boundary + for (i=0; i < data_len; ++i) { + if (data[i] == 0x4f) { + if (0==memcmp(data+i, ogg_page_header, 4)) { + int j,len; + uint32 crc; + // make sure we have the whole page header + if (i+26 >= data_len || i+27+data[i+26] >= data_len) { + // only read up to this page start, so hopefully we'll + // have the whole page header start next time + data_len = i; + break; + } + // ok, we have it all; compute the length of the page + len = 27 + data[i+26]; + for (j=0; j < data[i+26]; ++j) + len += data[i+27+j]; + // scan everything up to the embedded crc (which we must 0) + crc = 0; + for (j=0; j < 22; ++j) + crc = crc32_update(crc, data[i+j]); + // now process 4 0-bytes + for ( ; j < 26; ++j) + crc = crc32_update(crc, 0); + // len is the total number of bytes we need to scan + n = f->page_crc_tests++; + f->scan[n].bytes_left = len-j; + f->scan[n].crc_so_far = crc; + f->scan[n].goal_crc = data[i+22] + (data[i+23] << 8) + (data[i+24]<<16) + (data[i+25]<<24); + // if the last frame on a page is continued to the next, then + // we can't recover the sample_loc immediately + if (data[i+27+data[i+26]-1] == 255) + f->scan[n].sample_loc = ~0; + else + f->scan[n].sample_loc = data[i+6] + (data[i+7] << 8) + (data[i+ 8]<<16) + (data[i+ 9]<<24); + f->scan[n].bytes_done = i+j; + if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT) + break; + // keep going if we still have room for more + } + } + } + } + + for (i=0; i < f->page_crc_tests;) { + uint32 crc; + int j; + int n = f->scan[i].bytes_done; + int m = f->scan[i].bytes_left; + if (m > data_len - n) m = data_len - n; + // m is the bytes to scan in the current chunk + crc = f->scan[i].crc_so_far; + for (j=0; j < m; ++j) + crc = crc32_update(crc, data[n+j]); + f->scan[i].bytes_left -= m; + f->scan[i].crc_so_far = crc; + if (f->scan[i].bytes_left == 0) { + // does it match? + if (f->scan[i].crc_so_far == f->scan[i].goal_crc) { + // Houston, we have page + data_len = n+m; // consumption amount is wherever that scan ended + f->page_crc_tests = -1; // drop out of page scan mode + f->previous_length = 0; // decode-but-don't-output one frame + f->next_seg = -1; // start a new page + f->current_loc = f->scan[i].sample_loc; // set the current sample location + // to the amount we'd have decoded had we decoded this page + f->current_loc_valid = f->current_loc != ~0; + return data_len; + } + // delete entry + f->scan[i] = f->scan[--f->page_crc_tests]; + } else { + ++i; + } + } + + return data_len; +} + +// return value: number of bytes we used +int stb_vorbis_decode_frame_pushdata( + stb_vorbis *f, // the file we're decoding + uint8 *data, int data_len, // the memory available for decoding + int *channels, // place to write number of float * buffers + float ***output, // place to write float ** array of float * buffers + int *samples // place to write number of output samples + ) +{ + int i; + int len,right,left; + + if (!IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + if (f->page_crc_tests >= 0) { + *samples = 0; + return vorbis_search_for_page_pushdata(f, data, data_len); + } + + f->stream = data; + f->stream_end = data + data_len; + f->error = VORBIS__no_error; + + // check that we have the entire packet in memory + if (!is_whole_packet_present(f, FALSE)) { + *samples = 0; + return 0; + } + + if (!vorbis_decode_packet(f, &len, &left, &right)) { + // save the actual error we encountered + enum STBVorbisError error = f->error; + if (error == VORBIS_bad_packet_type) { + // flush and resynch + f->error = VORBIS__no_error; + while (get8_packet(f) != EOP) + if (f->eof) break; + *samples = 0; + return f->stream - data; + } + if (error == VORBIS_continued_packet_flag_invalid) { + if (f->previous_length == 0) { + // we may be resynching, in which case it's ok to hit one + // of these; just discard the packet + f->error = VORBIS__no_error; + while (get8_packet(f) != EOP) + if (f->eof) break; + *samples = 0; + return f->stream - data; + } + } + // if we get an error while parsing, what to do? + // well, it DEFINITELY won't work to continue from where we are! + stb_vorbis_flush_pushdata(f); + // restore the error that actually made us bail + f->error = error; + *samples = 0; + return 1; + } + + // success! + len = vorbis_finish_frame(f, len, left, right); + for (i=0; i < f->channels; ++i) + f->outputs[i] = f->channel_buffers[i] + left; + + if (channels) *channels = f->channels; + *samples = len; + *output = f->outputs; + return f->stream - data; +} + +stb_vorbis *stb_vorbis_open_pushdata( + unsigned char *data, int data_len, // the memory available for decoding + int *data_used, // only defined if result is not NULL + int *error, stb_vorbis_alloc *alloc) +{ + stb_vorbis *f, p; + vorbis_init(&p, alloc); + p.stream = data; + p.stream_end = data + data_len; + p.push_mode = TRUE; + if (!start_decoder(&p)) { + if (p.eof) + *error = VORBIS_need_more_data; + else + *error = p.error; + return NULL; + } + f = vorbis_alloc(&p); + if (f) { + *f = p; + *data_used = f->stream - data; + *error = 0; + return f; + } else { + vorbis_deinit(&p); + return NULL; + } +} +#endif // STB_VORBIS_NO_PUSHDATA_API + +unsigned int stb_vorbis_get_file_offset(stb_vorbis *f) +{ + #ifndef STB_VORBIS_NO_PUSHDATA_API + if (f->push_mode) return 0; + #endif + if (USE_MEMORY(f)) return f->stream - f->stream_start; + #ifndef STB_VORBIS_NO_STDIO + return ftell(f->f) - f->f_start; + #endif +} + +#ifndef STB_VORBIS_NO_PULLDATA_API +// +// DATA-PULLING API +// + +static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) +{ + for(;;) { + int n; + if (f->eof) return 0; + n = get8(f); + if (n == 0x4f) { // page header + unsigned int retry_loc = stb_vorbis_get_file_offset(f); + int i; + // check if we're off the end of a file_section stream + if (retry_loc - 25 > f->stream_len) + return 0; + // check the rest of the header + for (i=1; i < 4; ++i) + if (get8(f) != ogg_page_header[i]) + break; + if (f->eof) return 0; + if (i == 4) { + uint8 header[27]; + uint32 i, crc, goal, len; + for (i=0; i < 4; ++i) + header[i] = ogg_page_header[i]; + for (; i < 27; ++i) + header[i] = get8(f); + if (f->eof) return 0; + if (header[4] != 0) goto invalid; + goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24); + for (i=22; i < 26; ++i) + header[i] = 0; + crc = 0; + for (i=0; i < 27; ++i) + crc = crc32_update(crc, header[i]); + len = 0; + for (i=0; i < header[26]; ++i) { + int s = get8(f); + crc = crc32_update(crc, s); + len += s; + } + if (len && f->eof) return 0; + for (i=0; i < len; ++i) + crc = crc32_update(crc, get8(f)); + // finished parsing probable page + if (crc == goal) { + // we could now check that it's either got the last + // page flag set, OR it's followed by the capture + // pattern, but I guess TECHNICALLY you could have + // a file with garbage between each ogg page and recover + // from it automatically? So even though that paranoia + // might decrease the chance of an invalid decode by + // another 2^32, not worth it since it would hose those + // invalid-but-useful files? + if (end) + *end = stb_vorbis_get_file_offset(f); + if (last) + if (header[5] & 0x04) + *last = 1; + else + *last = 0; + set_file_offset(f, retry_loc-1); + return 1; + } + } + invalid: + // not a valid page, so rewind and look for next one + set_file_offset(f, retry_loc); + } + } +} + +// seek is implemented with 'interpolation search'--this is like +// binary search, but we use the data values to estimate the likely +// location of the data item (plus a bit of a bias so when the +// estimation is wrong we don't waste overly much time) + +#define SAMPLE_unknown 0xffffffff + + +// ogg vorbis, in its insane infinite wisdom, only provides +// information about the sample at the END of the page. +// therefore we COULD have the data we need in the current +// page, and not know it. we could just use the end location +// as our only knowledge for bounds, seek back, and eventually +// the binary search finds it. or we can try to be smart and +// not waste time trying to locate more pages. we try to be +// smart, since this data is already in memory anyway, so +// doing needless I/O would be crazy! +static int vorbis_analyze_page(stb_vorbis *f, ProbedPage *z) +{ + uint8 header[27], lacing[255]; + uint8 packet_type[255]; + int num_packet, packet_start, previous =0; + int i,len; + uint32 samples; + + // record where the page starts + z->page_start = stb_vorbis_get_file_offset(f); + + // parse the header + getn(f, header, 27); + assert(header[0] == 'O' && header[1] == 'g' && header[2] == 'g' && header[3] == 'S'); + getn(f, lacing, header[26]); + + // determine the length of the payload + len = 0; + for (i=0; i < header[26]; ++i) + len += lacing[i]; + + // this implies where the page ends + z->page_end = z->page_start + 27 + header[26] + len; + + // read the last-decoded sample out of the data + z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 16); + + if (header[5] & 4) { + // if this is the last page, it's not possible to work + // backwards to figure out the first sample! whoops! fuck. + z->first_decoded_sample = SAMPLE_unknown; + set_file_offset(f, z->page_start); + return 1; + } + + // scan through the frames to determine the sample-count of each one... + // our goal is the sample # of the first fully-decoded sample on the + // page, which is the first decoded sample of the 2nd page + + num_packet=0; + + packet_start = ((header[5] & 1) == 0); + + for (i=0; i < header[26]; ++i) { + if (packet_start) { + uint8 n,b,m; + if (lacing[i] == 0) goto bail; // trying to read from zero-length packet + n = get8(f); + // if bottom bit is non-zero, we've got corruption + if (n & 1) goto bail; + n >>= 1; + b = ilog(f->mode_count-1); + m = n >> b; + n &= (1 << b)-1; + if (n >= f->mode_count) goto bail; + if (num_packet == 0 && f->mode_config[n].blockflag) + previous = (m & 1); + packet_type[num_packet++] = f->mode_config[n].blockflag; + skip(f, lacing[i]-1); + } else + skip(f, lacing[i]); + packet_start = (lacing[i] < 255); + } + + // now that we know the sizes of all the pages, we can start determining + // how much sample data there is. + + samples = 0; + + // for the last packet, we step by its whole length, because the definition + // is that we encoded the end sample loc of the 'last packet completed', + // where 'completed' refers to packets being split, and we are left to guess + // what 'end sample loc' means. we assume it means ignoring the fact that + // the last half of the data is useless without windowing against the next + // packet... (so it's not REALLY complete in that sense) + if (num_packet > 1) + samples += f->blocksize[packet_type[num_packet-1]]; + + for (i=num_packet-2; i >= 1; --i) { + // now, for this packet, how many samples do we have that + // do not overlap the following packet? + if (packet_type[i] == 1) + if (packet_type[i+1] == 1) + samples += f->blocksize_1 >> 1; + else + samples += ((f->blocksize_1 - f->blocksize_0) >> 2) + (f->blocksize_0 >> 1); + else + samples += f->blocksize_0 >> 1; + } + // now, at this point, we've rewound to the very beginning of the + // _second_ packet. if we entirely discard the first packet after + // a seek, this will be exactly the right sample number. HOWEVER! + // we can't as easily compute this number for the LAST page. The + // only way to get the sample offset of the LAST page is to use + // the end loc from the previous page. But what that returns us + // is _exactly_ the place where we get our first non-overlapped + // sample. (I think. Stupid spec for being ambiguous.) So for + // consistency it's better to do that here, too. However, that + // will then require us to NOT discard all of the first frame we + // decode, in some cases, which means an even weirder frame size + // and extra code. what a fucking pain. + + // we're going to discard the first packet if we + // start the seek here, so we don't care about it. (we could actually + // do better; if the first packet is long, and the previous packet + // is short, there's actually data in the first half of the first + // packet that doesn't need discarding... but not worth paying the + // effort of tracking that of that here and in the seeking logic) + // except crap, if we infer it from the _previous_ packet's end + // location, we DO need to use that definition... and we HAVE to + // infer the start loc of the LAST packet from the previous packet's + // end location. fuck you, ogg vorbis. + + z->first_decoded_sample = z->last_decoded_sample - samples; + + // restore file state to where we were + set_file_offset(f, z->page_start); + return 1; + + // restore file state to where we were + bail: + set_file_offset(f, z->page_start); + return 0; +} + +static int vorbis_seek_frame_from_page(stb_vorbis *f, uint32 page_start, uint32 first_sample, uint32 target_sample, int fine) +{ + int left_start, left_end, right_start, right_end, mode,i; + int frame=0; + uint32 frame_start; + int frames_to_skip, data_to_skip; + + // first_sample is the sample # of the first sample that doesn't + // overlap the previous page... note that this requires us to + // _partially_ discard the first packet! bleh. + set_file_offset(f, page_start); + + f->next_seg = -1; // force page resync + + frame_start = first_sample; + // frame start is where the previous packet's last decoded sample + // was, which corresponds to left_end... EXCEPT if the previous + // packet was long and this packet is short? Probably a bug here. + + + // now, we can start decoding frames... we'll only FAKE decode them, + // until we find the frame that contains our sample; then we'll rewind, + // and try again + for (;;) { + int start; + + if (!vorbis_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) + return error(f, VORBIS_seek_failed); + + if (frame == 0) + start = left_end; + else + start = left_start; + + // the window starts at left_start; the last valid sample we generate + // before the next frame's window start is right_start-1 + if (target_sample < frame_start + right_start-start) + break; + + flush_packet(f); + if (f->eof) + return error(f, VORBIS_seek_failed); + + frame_start += right_start - start; + + ++frame; + } + + // ok, at this point, the sample we want is contained in frame #'frame' + + // to decode frame #'frame' normally, we have to decode the + // previous frame first... but if it's the FIRST frame of the page + // we can't. if it's the first frame, it means it falls in the part + // of the first frame that doesn't overlap either of the other frames. + // so, if we have to handle that case for the first frame, we might + // as well handle it for all of them, so: + if (target_sample > frame_start + (left_end - left_start)) { + // so what we want to do is go ahead and just immediately decode + // this frame, but then make it so the next get_frame_float() uses + // this already-decoded data? or do we want to go ahead and rewind, + // and leave a flag saying to skip the first N data? let's do that + frames_to_skip = frame; // if this is frame #1, skip 1 frame (#0) + data_to_skip = left_end - left_start; + } else { + // otherwise, we want to skip frames 0, 1, 2, ... frame-2 + // (which means frame-2+1 total frames) then decode frame-1, + // then leave frame pending + frames_to_skip = frame - 1; + assert(frames_to_skip >= 0); + data_to_skip = -1; + } + + set_file_offset(f, page_start); + f->next_seg = - 1; // force page resync + + for (i=0; i < frames_to_skip; ++i) { + maybe_start_packet(f); + flush_packet(f); + } + + if (data_to_skip >= 0) { + int i,j,n = f->blocksize_0 >> 1; + f->discard_samples_deferred = data_to_skip; + for (i=0; i < f->channels; ++i) + for (j=0; j < n; ++j) + f->previous_window[i][j] = 0; + f->previous_length = n; + frame_start += data_to_skip; + } else { + f->previous_length = 0; + vorbis_pump_first_frame(f); + } + + // at this point, the NEXT decoded frame will generate the desired sample + if (fine) { + // so if we're doing sample accurate streaming, we want to go ahead and decode it! + if (target_sample != frame_start) { + int n; + stb_vorbis_get_frame_float(f, &n, NULL); + assert(target_sample > frame_start); + assert(f->channel_buffer_start + (int) (target_sample-frame_start) < f->channel_buffer_end); + f->channel_buffer_start += (target_sample - frame_start); + } + } + + return 0; +} + +static int vorbis_seek_base(stb_vorbis *f, unsigned int sample_number, int fine) +{ + ProbedPage p[2],q; + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + // do we know the location of the last page? + if (f->p_last.page_start == 0) { + uint32 z = stb_vorbis_stream_length_in_samples(f); + if (z == 0) return error(f, VORBIS_cant_find_last_page); + } + + p[0] = f->p_first; + p[1] = f->p_last; + + if (sample_number >= f->p_last.last_decoded_sample) + sample_number = f->p_last.last_decoded_sample-1; + + if (sample_number < f->p_first.last_decoded_sample) { + vorbis_seek_frame_from_page(f, p[0].page_start, 0, sample_number, fine); + return 0; + } else { + int attempts=0; + while (p[0].page_end < p[1].page_start) { + uint32 probe; + uint32 start_offset, end_offset; + uint32 start_sample, end_sample; + + // copy these into local variables so we can tweak them + // if any are unknown + start_offset = p[0].page_end; + end_offset = p[1].after_previous_page_start; // an address known to seek to page p[1] + start_sample = p[0].last_decoded_sample; + end_sample = p[1].last_decoded_sample; + + // currently there is no such tweaking logic needed/possible? + if (start_sample == SAMPLE_unknown || end_sample == SAMPLE_unknown) + return error(f, VORBIS_seek_failed); + + // now we want to lerp between these for the target samples... + + // step 1: we need to bias towards the page start... + if (start_offset + 4000 < end_offset) + end_offset -= 4000; + + // now compute an interpolated search loc + probe = start_offset + (int) floor((float) (end_offset - start_offset) / (end_sample - start_sample) * (sample_number - start_sample)); + + // next we need to bias towards binary search... + // code is a little wonky to allow for full 32-bit unsigned values + if (attempts >= 4) { + uint32 probe2 = start_offset + ((end_offset - start_offset) >> 1); + if (attempts >= 8) + probe = probe2; + else if (probe < probe2) + probe = probe + ((probe2 - probe) >> 1); + else + probe = probe2 + ((probe - probe2) >> 1); + } + ++attempts; + + set_file_offset(f, probe); + if (!vorbis_find_page(f, NULL, NULL)) return error(f, VORBIS_seek_failed); + if (!vorbis_analyze_page(f, &q)) return error(f, VORBIS_seek_failed); + q.after_previous_page_start = probe; + + // it's possible we've just found the last page again + if (q.page_start == p[1].page_start) { + p[1] = q; + continue; + } + + if (sample_number < q.last_decoded_sample) + p[1] = q; + else + p[0] = q; + } + + if (p[0].last_decoded_sample <= sample_number && sample_number < p[1].last_decoded_sample) { + vorbis_seek_frame_from_page(f, p[1].page_start, p[0].last_decoded_sample, sample_number, fine); + return 0; + } + return error(f, VORBIS_seek_failed); + } +} + +int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) +{ + return vorbis_seek_base(f, sample_number, FALSE); +} + +int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) +{ + return vorbis_seek_base(f, sample_number, TRUE); +} + +void stb_vorbis_seek_start(stb_vorbis *f) +{ + if (IS_PUSH_MODE(f)) { error(f, VORBIS_invalid_api_mixing); return; } + set_file_offset(f, f->first_audio_page_offset); + f->previous_length = 0; + f->first_decode = TRUE; + f->next_seg = -1; + vorbis_pump_first_frame(f); +} + +unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) +{ + unsigned int restore_offset, previous_safe; + unsigned int end, last_page_loc; + + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + if (!f->total_samples) { + int last; + uint32 lo,hi; + char header[6]; + + // first, store the current decode position so we can restore it + restore_offset = stb_vorbis_get_file_offset(f); + + // now we want to seek back 64K from the end (the last page must + // be at most a little less than 64K, but let's allow a little slop) + if (f->stream_len >= 65536 && f->stream_len-65536 >= f->first_audio_page_offset) + previous_safe = f->stream_len - 65536; + else + previous_safe = f->first_audio_page_offset; + + set_file_offset(f, previous_safe); + // previous_safe is now our candidate 'earliest known place that seeking + // to will lead to the final page' + + if (!vorbis_find_page(f, &end, (int unsigned *)&last)) { + // if we can't find a page, we're hosed! + f->error = VORBIS_cant_find_last_page; + f->total_samples = 0xffffffff; + goto done; + } + + // check if there are more pages + last_page_loc = stb_vorbis_get_file_offset(f); + + // stop when the last_page flag is set, not when we reach eof; + // this allows us to stop short of a 'file_section' end without + // explicitly checking the length of the section + while (!last) { + set_file_offset(f, end); + if (!vorbis_find_page(f, &end, (int unsigned *)&last)) { + // the last page we found didn't have the 'last page' flag + // set. whoops! + break; + } + previous_safe = last_page_loc+1; + last_page_loc = stb_vorbis_get_file_offset(f); + } + + set_file_offset(f, last_page_loc); + + // parse the header + getn(f, (unsigned char *)header, 6); + // extract the absolute granule position + lo = get32(f); + hi = get32(f); + if (lo == 0xffffffff && hi == 0xffffffff) { + f->error = VORBIS_cant_find_last_page; + f->total_samples = SAMPLE_unknown; + goto done; + } + if (hi) + lo = 0xfffffffe; // saturate + f->total_samples = lo; + + f->p_last.page_start = last_page_loc; + f->p_last.page_end = end; + f->p_last.last_decoded_sample = lo; + f->p_last.first_decoded_sample = SAMPLE_unknown; + f->p_last.after_previous_page_start = previous_safe; + + done: + set_file_offset(f, restore_offset); + } + return f->total_samples == SAMPLE_unknown ? 0 : f->total_samples; +} + +float stb_vorbis_stream_length_in_seconds(stb_vorbis *f) +{ + return stb_vorbis_stream_length_in_samples(f) / (float) f->sample_rate; +} + + + +int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output) +{ + int len, right,left,i; + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + + if (!vorbis_decode_packet(f, &len, &left, &right)) { + f->channel_buffer_start = f->channel_buffer_end = 0; + return 0; + } + + len = vorbis_finish_frame(f, len, left, right); + for (i=0; i < f->channels; ++i) + f->outputs[i] = f->channel_buffers[i] + left; + + f->channel_buffer_start = left; + f->channel_buffer_end = left+len; + + if (channels) *channels = f->channels; + if (output) *output = f->outputs; + return len; +} + +#ifndef STB_VORBIS_NO_STDIO + +stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc, unsigned int length) +{ + stb_vorbis *f, p; + vorbis_init(&p, alloc); + p.f = file; + p.f_start = ftell(file); + p.stream_len = length; + p.close_on_free = close_on_free; + if (start_decoder(&p)) { + f = vorbis_alloc(&p); + if (f) { + *f = p; + vorbis_pump_first_frame(f); + return f; + } + } + if (error) *error = p.error; + vorbis_deinit(&p); + return NULL; +} + +stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc) +{ + unsigned int len, start; + start = ftell(file); + fseek(file, 0, SEEK_END); + len = ftell(file) - start; + fseek(file, start, SEEK_SET); + return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); +} + +stb_vorbis * stb_vorbis_open_filename(char *filename, int *error, stb_vorbis_alloc *alloc) +{ + FILE *f = fopen(filename, "rb"); + if (f) + return stb_vorbis_open_file(f, TRUE, error, alloc); + if (error) *error = VORBIS_file_open_failure; + return NULL; +} +#endif // STB_VORBIS_NO_STDIO + +stb_vorbis * stb_vorbis_open_memory(unsigned char *data, int len, int *error, stb_vorbis_alloc *alloc) +{ + stb_vorbis *f, p; + if (data == NULL) return NULL; + vorbis_init(&p, alloc); + p.stream = data; + p.stream_end = data + len; + p.stream_start = p.stream; + p.stream_len = len; + p.push_mode = FALSE; + if (start_decoder(&p)) { + f = vorbis_alloc(&p); + if (f) { + *f = p; + vorbis_pump_first_frame(f); + return f; + } + } + if (error) *error = p.error; + vorbis_deinit(&p); + return NULL; +} + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +#define PLAYBACK_MONO 1 +#define PLAYBACK_LEFT 2 +#define PLAYBACK_RIGHT 4 + +#define L (PLAYBACK_LEFT | PLAYBACK_MONO) +#define C (PLAYBACK_LEFT | PLAYBACK_RIGHT | PLAYBACK_MONO) +#define R (PLAYBACK_RIGHT | PLAYBACK_MONO) + +static int8 channel_position[7][6] = +{ + { 0 }, + { C }, + { L, R }, + { L, C, R }, + { L, R, L, R }, + { L, C, R, L, R }, + { L, C, R, L, R, C }, +}; + + +#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT + typedef union { + float f; + int i; + } float_conv; + typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4]; + #define FASTDEF(x) float_conv x + // add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round + #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT)) + #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22)) + #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s)) + #define check_endianness() +#else + #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s)))) + #define check_endianness() + #define FASTDEF(x) +#endif + +static void copy_samples(short *dest, float *src, int len) +{ + int i; + check_endianness(); + for (i=0; i < len; ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + dest[i] = v; + } +} + +static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len) +{ + #define BUFFER_SIZE 32 + float buffer[BUFFER_SIZE]; + int i,j,o,n = BUFFER_SIZE; + check_endianness(); + for (o = 0; o < len; o += BUFFER_SIZE) { + memset(buffer, 0, sizeof(buffer)); + if (o + n > len) n = len - o; + for (j=0; j < num_c; ++j) { + if (channel_position[num_c][j] & mask) { + for (i=0; i < n; ++i) + buffer[i] += data[j][d_offset+o+i]; + } + } + for (i=0; i < n; ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + output[o+i] = v; + } + } +} + +static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} }; +static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len) +{ + #define BUFFER_SIZE 32 + float buffer[BUFFER_SIZE]; + int i,j,o,n = BUFFER_SIZE >> 1; + // o is the offset in the source data + check_endianness(); + for (o = 0; o < len; o += BUFFER_SIZE >> 1) { + // o2 is the offset in the output data + int o2 = o << 1; + memset(buffer, 0, sizeof(buffer)); + if (o + n > len) n = len - o; + for (j=0; j < num_c; ++j) { + int m = channel_position[num_c][j] & (PLAYBACK_LEFT | PLAYBACK_RIGHT); + if (m == (PLAYBACK_LEFT | PLAYBACK_RIGHT)) { + for (i=0; i < n; ++i) { + buffer[i*2+0] += data[j][d_offset+o+i]; + buffer[i*2+1] += data[j][d_offset+o+i]; + } + } else if (m == PLAYBACK_LEFT) { + for (i=0; i < n; ++i) { + buffer[i*2+0] += data[j][d_offset+o+i]; + } + } else if (m == PLAYBACK_RIGHT) { + for (i=0; i < n; ++i) { + buffer[i*2+1] += data[j][d_offset+o+i]; + } + } + } + for (i=0; i < (n<<1); ++i) { + FASTDEF(temp); + int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + output[o2+i] = v; + } + } +} + +static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples) +{ + int i; + if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { + static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} }; + for (i=0; i < buf_c; ++i) + compute_samples(channel_selector[buf_c][i], buffer[i]+b_offset, data_c, data, d_offset, samples); + } else { + int limit = buf_c < data_c ? buf_c : data_c; + for (i=0; i < limit; ++i) + copy_samples(buffer[i]+b_offset, data[i], samples); + for ( ; i < buf_c; ++i) + memset(buffer[i]+b_offset, 0, sizeof(short) * samples); + } +} + +int stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples) +{ + float **output; + int len = stb_vorbis_get_frame_float(f, NULL, &output); + if (len > num_samples) len = num_samples; + if (len) + convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len); + return len; +} + +static void convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len) +{ + int i; + check_endianness(); + if (buf_c != data_c && buf_c <= 2 && data_c <= 6) { + assert(buf_c == 2); + for (i=0; i < buf_c; ++i) + compute_stereo_samples(buffer, data_c, data, d_offset, len); + } else { + int limit = buf_c < data_c ? buf_c : data_c; + int j; + for (j=0; j < len; ++j) { + for (i=0; i < limit; ++i) { + FASTDEF(temp); + float f = data[i][d_offset+j]; + int v = FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15); + if ((unsigned int) (v + 32768) > 65535) + v = v < 0 ? -32768 : 32767; + *buffer++ = v; + } + for ( ; i < buf_c; ++i) + *buffer++ = 0; + } + } +} + +int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts) +{ + float **output; + int len; + if (num_c == 1) return stb_vorbis_get_frame_short(f,num_c,&buffer, num_shorts); + len = stb_vorbis_get_frame_float(f, NULL, &output); + if (len) { + if (len*num_c > num_shorts) len = num_shorts / num_c; + convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len); + } + return len; +} + +int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts) +{ + float **outputs; + int len = num_shorts / channels; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) { + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + if (k) + convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, k); + buffer += k*channels; + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; +} + +int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len) +{ + float **outputs; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) { + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + if (k) + convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k); + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; +} + +#ifndef STB_VORBIS_NO_STDIO +int stb_vorbis_decode_filename(char *filename, int *channels, short **output) +{ + int data_len, offset, total, limit, error; + short *data; + stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL); + if (v == NULL) return -1; + limit = v->channels * 4096; + *channels = v->channels; + offset = data_len = 0; + total = limit; + data = (short *) malloc(total * sizeof(*data)); + if (data == NULL) { + stb_vorbis_close(v); + return -2; + } + for (;;) { + int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); + if (n == 0) break; + data_len += n; + offset += n * v->channels; + if (offset + limit > total) { + short *data2; + total *= 2; + data2 = (short *) realloc(data, total * sizeof(*data)); + if (data2 == NULL) { + free(data); + stb_vorbis_close(v); + return -2; + } + data = data2; + } + } + *output = data; + return data_len; +} +#endif // NO_STDIO + +int stb_vorbis_decode_memory(uint8 *mem, int len, int *channels, short **output) +{ + int data_len, offset, total, limit, error; + short *data; + stb_vorbis *v = stb_vorbis_open_memory(mem, len, &error, NULL); + if (v == NULL) return -1; + limit = v->channels * 4096; + *channels = v->channels; + offset = data_len = 0; + total = limit; + data = (short *) malloc(total * sizeof(*data)); + if (data == NULL) { + stb_vorbis_close(v); + return -2; + } + for (;;) { + int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset); + if (n == 0) break; + data_len += n; + offset += n * v->channels; + if (offset + limit > total) { + short *data2; + total *= 2; + data2 = (short *) realloc(data, total * sizeof(*data)); + if (data2 == NULL) { + free(data); + stb_vorbis_close(v); + return -2; + } + data = data2; + } + } + *output = data; + return data_len; +} +#endif + +int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats) +{ + float **outputs; + int len = num_floats / channels; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < len) { + int i,j; + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= len) k = len - n; + for (j=0; j < k; ++j) { + for (i=0; i < z; ++i) + *buffer++ = f->channel_buffers[i][f->channel_buffer_start+j]; + for ( ; i < channels; ++i) + *buffer++ = 0; + } + n += k; + f->channel_buffer_start += k; + if (n == len) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; +} + +int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples) +{ + float **outputs; + int n=0; + int z = f->channels; + if (z > channels) z = channels; + while (n < num_samples) { + int i; + int k = f->channel_buffer_end - f->channel_buffer_start; + if (n+k >= num_samples) k = num_samples - n; + if (k) { + for (i=0; i < z; ++i) + memcpy(buffer[i]+n, f->channel_buffers+f->channel_buffer_start, sizeof(float)*k); + for ( ; i < channels; ++i) + memset(buffer[i]+n, 0, sizeof(float) * k); + } + n += k; + f->channel_buffer_start += k; + if (n == num_samples) break; + if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break; + } + return n; +} +#endif // STB_VORBIS_NO_PULLDATA_API + +#endif // STB_VORBIS_HEADER_ONLY diff --git a/ext/stb_vorbis/stb_vorbis.h b/ext/stb_vorbis/stb_vorbis.h new file mode 100644 index 0000000000..16ccc10036 --- /dev/null +++ b/ext/stb_vorbis/stb_vorbis.h @@ -0,0 +1,329 @@ +////////////////////////////////////////////////////////////////////////////// +// +// HEADER BEGINS HERE +// + +#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H +#define STB_VORBIS_INCLUDE_STB_VORBIS_H + +#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO) +#define STB_VORBIS_NO_STDIO 1 +#endif + +#ifndef STB_VORBIS_NO_STDIO +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/////////// THREAD SAFETY + +// Individual stb_vorbis* handles are not thread-safe; you cannot decode from +// them from multiple threads at the same time. However, you can have multiple +// stb_vorbis* handles and decode from them independently in multiple thrads. + + +/////////// MEMORY ALLOCATION + +// normally stb_vorbis uses malloc() to allocate memory at startup, +// and alloca() to allocate temporary memory during a frame on the +// stack. (Memory consumption will depend on the amount of setup +// data in the file and how you set the compile flags for speed +// vs. size. In my test files the maximal-size usage is ~150KB.) +// +// You can modify the wrapper functions in the source (setup_malloc, +// setup_temp_malloc, temp_malloc) to change this behavior, or you +// can use a simpler allocation model: you pass in a buffer from +// which stb_vorbis will allocate _all_ its memory (including the +// temp memory). "open" may fail with a VORBIS_outofmem if you +// do not pass in enough data; there is no way to determine how +// much you do need except to succeed (at which point you can +// query get_info to find the exact amount required. yes I know +// this is lame). +// +// If you pass in a non-NULL buffer of the type below, allocation +// will occur from it as described above. Otherwise just pass NULL +// to use malloc()/alloca() + +typedef struct +{ + char *alloc_buffer; + int alloc_buffer_length_in_bytes; +} stb_vorbis_alloc; + + +/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES + +typedef struct stb_vorbis stb_vorbis; + +typedef struct +{ + unsigned int sample_rate; + int channels; + + unsigned int setup_memory_required; + unsigned int setup_temp_memory_required; + unsigned int temp_memory_required; + + int max_frame_size; +} stb_vorbis_info; + +// get general information about the file +extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f); + +// get the last error detected (clears it, too) +extern int stb_vorbis_get_error(stb_vorbis *f); + +// close an ogg vorbis file and free all memory in use +extern void stb_vorbis_close(stb_vorbis *f); + +// this function returns the offset (in samples) from the beginning of the +// file that will be returned by the next decode, if it is known, or -1 +// otherwise. after a flush_pushdata() call, this may take a while before +// it becomes valid again. +// NOT WORKING YET after a seek with PULLDATA API +extern int stb_vorbis_get_sample_offset(stb_vorbis *f); + +// returns the current seek point within the file, or offset from the beginning +// of the memory buffer. In pushdata mode it returns 0. +extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f); + +/////////// PUSHDATA API + +#ifndef STB_VORBIS_NO_PUSHDATA_API + +// this API allows you to get blocks of data from any source and hand +// them to stb_vorbis. you have to buffer them; stb_vorbis will tell +// you how much it used, and you have to give it the rest next time; +// and stb_vorbis may not have enough data to work with and you will +// need to give it the same data again PLUS more. Note that the Vorbis +// specification does not bound the size of an individual frame. + +extern stb_vorbis *stb_vorbis_open_pushdata( + unsigned char *datablock, int datablock_length_in_bytes, + int *datablock_memory_consumed_in_bytes, + int *error, + stb_vorbis_alloc *alloc_buffer); +// create a vorbis decoder by passing in the initial data block containing +// the ogg&vorbis headers (you don't need to do parse them, just provide +// the first N bytes of the file--you're told if it's not enough, see below) +// on success, returns an stb_vorbis *, does not set error, returns the amount of +// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes; +// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed +// if returns NULL and *error is VORBIS_need_more_data, then the input block was +// incomplete and you need to pass in a larger block from the start of the file + +extern int stb_vorbis_decode_frame_pushdata( + stb_vorbis *f, unsigned char *datablock, int datablock_length_in_bytes, + int *channels, // place to write number of float * buffers + float ***output, // place to write float ** array of float * buffers + int *samples // place to write number of output samples + ); +// decode a frame of audio sample data if possible from the passed-in data block +// +// return value: number of bytes we used from datablock +// possible cases: +// 0 bytes used, 0 samples output (need more data) +// N bytes used, 0 samples output (resynching the stream, keep going) +// N bytes used, M samples output (one frame of data) +// note that after opening a file, you will ALWAYS get one N-bytes,0-sample +// frame, because Vorbis always "discards" the first frame. +// +// Note that on resynch, stb_vorbis will rarely consume all of the buffer, +// instead only datablock_length_in_bytes-3 or less. This is because it wants +// to avoid missing parts of a page header if they cross a datablock boundary, +// without writing state-machiney code to record a partial detection. +// +// The number of channels returned are stored in *channels (which can be +// NULL--it is always the same as the number of channels reported by +// get_info). *output will contain an array of float* buffers, one per +// channel. In other words, (*output)[0][0] contains the first sample from +// the first channel, and (*output)[1][0] contains the first sample from +// the second channel. + +extern void stb_vorbis_flush_pushdata(stb_vorbis *f); +// inform stb_vorbis that your next datablock will not be contiguous with +// previous ones (e.g. you've seeked in the data); future attempts to decode +// frames will cause stb_vorbis to resynchronize (as noted above), and +// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it +// will begin decoding the _next_ frame. +// +// if you want to seek using pushdata, you need to seek in your file, then +// call stb_vorbis_flush_pushdata(), then start calling decoding, then once +// decoding is returning you data, call stb_vorbis_get_sample_offset, and +// if you don't like the result, seek your file again and repeat. +#endif + + +////////// PULLING INPUT API + +#ifndef STB_VORBIS_NO_PULLDATA_API +// This API assumes stb_vorbis is allowed to pull data from a source-- +// either a block of memory containing the _entire_ vorbis stream, or a +// FILE * that you or it create, or possibly some other reading mechanism +// if you go modify the source to replace the FILE * case with some kind +// of callback to your code. (But if you don't support seeking, you may +// just want to go ahead and use pushdata.) + +#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION) +extern int stb_vorbis_decode_filename(char *filename, int *channels, short **output); +#endif +extern int stb_vorbis_decode_memory(unsigned char *mem, int len, int *channels, short **output); +// decode an entire file and output the data interleaved into a malloc()ed +// buffer stored in *output. The return value is the number of samples +// decoded, or -1 if the file could not be opened or was not an ogg vorbis file. +// When you're done with it, just free() the pointer returned in *output. + +extern stb_vorbis * stb_vorbis_open_memory(unsigned char *data, int len, + int *error, stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from an ogg vorbis stream in memory (note +// this must be the entire stream!). on failure, returns NULL and sets *error + +#ifndef STB_VORBIS_NO_STDIO +extern stb_vorbis * stb_vorbis_open_filename(char *filename, + int *error, stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from a filename via fopen(). on failure, +// returns NULL and sets *error (possibly to VORBIS_file_open_failure). + +extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, + int *error, stb_vorbis_alloc *alloc_buffer); +// create an ogg vorbis decoder from an open FILE *, looking for a stream at +// the _current_ seek point (ftell). on failure, returns NULL and sets *error. +// note that stb_vorbis must "own" this stream; if you seek it in between +// calls to stb_vorbis, it will become confused. Morever, if you attempt to +// perform stb_vorbis_seek_*() operations on this file, it will assume it +// owns the _entire_ rest of the file after the start point. Use the next +// function, stb_vorbis_open_file_section(), to limit it. + +extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close, + int *error, stb_vorbis_alloc *alloc_buffer, unsigned int len); +// create an ogg vorbis decoder from an open FILE *, looking for a stream at +// the _current_ seek point (ftell); the stream will be of length 'len' bytes. +// on failure, returns NULL and sets *error. note that stb_vorbis must "own" +// this stream; if you seek it in between calls to stb_vorbis, it will become +// confused. +#endif + +extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number); +extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); +// NOT WORKING YET +// these functions seek in the Vorbis file to (approximately) 'sample_number'. +// after calling seek_frame(), the next call to get_frame_*() will include +// the specified sample. after calling stb_vorbis_seek(), the next call to +// stb_vorbis_get_samples_* will start with the specified sample. If you +// do not need to seek to EXACTLY the target sample when using get_samples_*, +// you can also use seek_frame(). + +extern void stb_vorbis_seek_start(stb_vorbis *f); +// this function is equivalent to stb_vorbis_seek(f,0), but it +// actually works + +extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f); +extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f); +// these functions return the total length of the vorbis stream + +extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output); +// decode the next frame and return the number of samples. the number of +// channels returned are stored in *channels (which can be NULL--it is always +// the same as the number of channels reported by get_info). *output will +// contain an array of float* buffers, one per channel. These outputs will +// be overwritten on the next call to stb_vorbis_get_frame_*. +// +// You generally should not intermix calls to stb_vorbis_get_frame_*() +// and stb_vorbis_get_samples_*(), since the latter calls the former. + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts); +extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples); +#endif +// decode the next frame and return the number of samples per channel. the +// data is coerced to the number of channels you request according to the +// channel coercion rules (see below). You must pass in the size of your +// buffer(s) so that stb_vorbis will not overwrite the end of the buffer. +// The maximum buffer size needed can be gotten from get_info(); however, +// the Vorbis I specification implies an absolute maximum of 4096 samples +// per channel. Note that for interleaved data, you pass in the number of +// shorts (the size of your array), but the return value is the number of +// samples per channel, not the total number of samples. + +// Channel coercion rules: +// Let M be the number of channels requested, and N the number of channels present, +// and Cn be the nth channel; let stereo L be the sum of all L and center channels, +// and stereo R be the sum of all R and center channels (channel assignment from the +// vorbis spec). +// M N output +// 1 k sum(Ck) for all k +// 2 * stereo L, stereo R +// k l k > l, the first l channels, then 0s +// k l k <= l, the first k channels +// Note that this is not _good_ surround etc. mixing at all! It's just so +// you get something useful. + +extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats); +extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples); +// gets num_samples samples, not necessarily on a frame boundary--this requires +// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES. +// Returns the number of samples stored per channel; it may be less than requested +// at the end of the file. If there are no more samples in the file, returns 0. + +#ifndef STB_VORBIS_NO_INTEGER_CONVERSION +extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts); +extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples); +#endif +// gets num_samples samples, not necessarily on a frame boundary--this requires +// buffering so you have to supply the buffers. Applies the coercion rules above +// to produce 'channels' channels. Returns the number of samples stored per channel; +// it may be less than requested at the end of the file. If there are no more +// samples in the file, returns 0. + +#endif + +//////// ERROR CODES + +enum STBVorbisError +{ + VORBIS__no_error, + + VORBIS_need_more_data=1, // not a real error + + VORBIS_invalid_api_mixing, // can't mix API modes + VORBIS_outofmem, // not enough memory + VORBIS_feature_not_supported, // uses floor 0 + VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small + VORBIS_file_open_failure, // fopen() failed + VORBIS_seek_without_length, // can't seek in unknown-length file + + VORBIS_unexpected_eof=10, // file is truncated? + VORBIS_seek_invalid, // seek past EOF + + // decoding errors (corrupt/invalid stream) -- you probably + // don't care about the exact details of these + + // vorbis errors: + VORBIS_invalid_setup=20, + VORBIS_invalid_stream, + + // ogg errors: + VORBIS_missing_capture_pattern=30, + VORBIS_invalid_stream_structure_version, + VORBIS_continued_packet_flag_invalid, + VORBIS_incorrect_stream_serial_number, + VORBIS_invalid_first_page, + VORBIS_bad_packet_type, + VORBIS_cant_find_last_page, + VORBIS_seek_failed, +}; + + +#ifdef __cplusplus +} +#endif + +#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H +// +// HEADER ENDS HERE +// +////////////////////////////////////////////////////////////////////////////// + diff --git a/ext/vjson/CMakeLists.txt b/ext/vjson/CMakeLists.txt new file mode 100644 index 0000000000..97ea0d4876 --- /dev/null +++ b/ext/vjson/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.6) + +#if(UNIX) +add_definitions(-PIC) +add_definitions(-g) +add_definitions(-O2) +add_definitions(-Wall) +#endif(UNIX) + +add_library(vjson json.cpp block_allocator.cpp) diff --git a/ext/vjson/block_allocator.cpp b/ext/vjson/block_allocator.cpp new file mode 100644 index 0000000000..83bd02110c --- /dev/null +++ b/ext/vjson/block_allocator.cpp @@ -0,0 +1,50 @@ +#include +#include +#include "block_allocator.h" + +block_allocator::block_allocator(size_t blocksize): m_head(0), m_blocksize(blocksize) +{ +} + +block_allocator::~block_allocator() +{ + while (m_head) + { + block *temp = m_head->next; + ::free(m_head); + m_head = temp; + } +} + +void block_allocator::swap(block_allocator &rhs) +{ + std::swap(m_blocksize, rhs.m_blocksize); + std::swap(m_head, rhs.m_head); +} + +void *block_allocator::malloc(size_t size) +{ + if ((m_head && m_head->used + size > m_head->size) || !m_head) + { + // calc needed size for allocation + size_t alloc_size = std::max(sizeof(block) + size, m_blocksize); + + // create new block + char *buffer = (char *)::malloc(alloc_size); + block *b = reinterpret_cast(buffer); + b->size = alloc_size; + b->used = sizeof(block); + b->buffer = buffer; + b->next = m_head; + m_head = b; + } + + void *ptr = m_head->buffer + m_head->used; + m_head->used += size; + return ptr; +} + +void block_allocator::free() +{ + block_allocator(0).swap(*this); +} diff --git a/ext/vjson/block_allocator.h b/ext/vjson/block_allocator.h new file mode 100644 index 0000000000..90a81814f6 --- /dev/null +++ b/ext/vjson/block_allocator.h @@ -0,0 +1,35 @@ +#ifndef BLOCK_ALLOCATOR_H +#define BLOCK_ALLOCATOR_H + +class block_allocator +{ +public: + block_allocator(size_t blocksize); + ~block_allocator(); + + // exchange contents with rhs + void swap(block_allocator &rhs); + + // allocate memory + void *malloc(size_t size); + + // free all allocated blocks + void free(); + +private: + struct block + { + size_t size; + size_t used; + char *buffer; + block *next; + }; + + block *m_head; + size_t m_blocksize; + + block_allocator(const block_allocator &); + block_allocator &operator=(block_allocator &); +}; + +#endif diff --git a/ext/vjson/json.cpp b/ext/vjson/json.cpp new file mode 100644 index 0000000000..cc6dfd5ed7 --- /dev/null +++ b/ext/vjson/json.cpp @@ -0,0 +1,620 @@ +#include +#include +#include +#include "json.h" +#include "file/easy_file.h" + +// true if character represent a digit +#define IS_DIGIT(c) (c >= '0' && c <= '9') + +int json_value::numChildren() const { + int count = 0; + const json_value *c = first_child; + while (c) { + count++; + c = c->next_sibling; + } + return count; +} + +// only works right for first child. includes itself in count. +int json_value::numSiblings() const { + const json_value *s = next_sibling; + int count = 1; + while (s) { + count++; + s = s->next_sibling; + } + return count; +} + +const json_value *json_value::get(const char *child_name) const { + const json_value *c = first_child; + while (c) { + if (!strcmp(c->name, child_name)) { + return c; + } + c = c->next_sibling; + } + return 0; +} + +const json_value *json_value::get(const char *child_name, json_type type) const { + const json_value *v = get(child_name); + if (v && type == v->type) + return v; + else + return 0; +} + +const char *json_value::getString(const char *child_name) const { + return get(child_name, JSON_STRING)->string_value; +} + +const char *json_value::getString(const char *child_name, const char *default_value) const { + const json_value *val = get(child_name, JSON_STRING); + if (!val) + return default_value; + return val->string_value; +} + +bool json_value::getStringVector(std::vector *vec) const { + vec->clear(); + if (type == JSON_ARRAY) { + json_value *val = first_child; + while (val) { + if (val->type == JSON_STRING) { + vec->push_back(val->string_value); + } + } + return true; + } else { + return false; + } +} + +float json_value::getFloat(const char *child_name) const { + return get(child_name, JSON_FLOAT)->float_value; +} + +float json_value::getFloat(const char *child_name, float default_value) const { + const json_value *val = get(child_name, JSON_FLOAT); + if (!val) + return default_value; + return val->float_value; +} + +int json_value::getInt(const char *child_name) const { + return get(child_name, JSON_INT)->int_value; +} + +int json_value::getInt(const char *child_name, int default_value) const { + const json_value *val = get(child_name, JSON_INT); + if (!val) + return default_value; + return val->int_value; +} + +bool json_value::getBool(const char *child_name) const { + return get(child_name, JSON_BOOL)->int_value != 0 ? true : false; +} + +bool json_value::getBool(const char *child_name, bool default_value) const { + const json_value *val = get(child_name, JSON_BOOL); + if (!val) + return default_value; + return val->int_value != 0 ? true : false; +} + + +// convert string to integer +char *atoi(char *first, char *last, int *out) +{ + int sign = 1; + if (first != last) + { + if (*first == '-') + { + sign = -1; + ++first; + } + else if (*first == '+') + { + ++first; + } + } + + int result = 0; + for (; first != last && IS_DIGIT(*first); ++first) + { + result = 10 * result + (*first - '0'); + } + *out = result * sign; + + return first; +} + +// convert hexadecimal string to unsigned integer +char *hatoui(char *first, char *last, unsigned int *out) +{ + unsigned int result = 0; + for (; first != last; ++first) + { + int digit; + if (IS_DIGIT(*first)) + { + digit = *first - '0'; + } + else if (*first >= 'a' && *first <= 'f') + { + digit = *first - 'a' + 10; + } + else if (*first >= 'A' && *first <= 'F') + { + digit = *first - 'A' + 10; + } + else + { + break; + } + result = 16 * result + digit; + } + *out = result; + + return first; +} + +// convert string to floating point +char *atof(char *first, char *last, float *out) +{ + // sign + float sign = 1; + if (first != last) + { + if (*first == '-') + { + sign = -1; + ++first; + } + else if (*first == '+') + { + ++first; + } + } + + // integer part + float result = 0; + for (; first != last && IS_DIGIT(*first); ++first) + { + result = 10 * result + (*first - '0'); + } + + // fraction part + if (first != last && *first == '.') + { + ++first; + + float inv_base = 0.1f; + for (; first != last && IS_DIGIT(*first); ++first) + { + result += (*first - '0') * inv_base; + inv_base *= 0.1f; + } + } + + // result w\o exponent + result *= sign; + + // exponent + bool exponent_negative = false; + int exponent = 0; + if (first != last && (*first == 'e' || *first == 'E')) + { + ++first; + + if (*first == '-') + { + exponent_negative = true; + ++first; + } + else if (*first == '+') + { + ++first; + } + + for (; first != last && IS_DIGIT(*first); ++first) + { + exponent = 10 * exponent + (*first - '0'); + } + } + + if (exponent) + { + float power_of_ten = 10; + for (; exponent > 1; exponent--) + { + power_of_ten *= 10; + } + + if (exponent_negative) + { + result /= power_of_ten; + } + else + { + result *= power_of_ten; + } + } + + *out = result; + + return first; +} + +json_value *json_alloc(block_allocator *allocator) +{ + json_value *value = (json_value *)allocator->malloc(sizeof(json_value)); + memset(value, 0, sizeof(json_value)); + return value; +} + +void json_append(json_value *lhs, json_value *rhs) +{ + rhs->parent = lhs; + if (lhs->last_child) + { + lhs->last_child = lhs->last_child->next_sibling = rhs; + } + else + { + lhs->first_child = lhs->last_child = rhs; + } +} + +#define ERROR(it, desc)\ + *error_pos = it;\ + *error_desc = (char *)desc;\ + *error_line = 1 - escaped_newlines;\ + for (char *c = it; c != source; --c)\ + if (*c == '\n') ++*error_line;\ + return 0 + +#define CHECK_TOP() if (!top) {ERROR(it, "Unexpected character");} + +json_value *json_parse(char *source, char **error_pos, char **error_desc, int *error_line, block_allocator *allocator) +{ + json_value *root = 0; + json_value *top = 0; + + char *name = 0; + char *it = source; + + int escaped_newlines = 0; + + while (*it) + { + switch (*it) + { + case '{': + case '[': + { + // create new value + json_value *object = json_alloc(allocator); + + // name + object->name = name; + name = 0; + + // type + object->type = (*it == '{') ? JSON_OBJECT : JSON_ARRAY; + + // skip open character + ++it; + + // set top and root + if (top) + { + json_append(top, object); + } + else if (!root) + { + root = object; + } + else + { + ERROR(it, "Second root. Only one root allowed"); + } + top = object; + } + break; + + case '}': + case ']': + { + if (!top || top->type != ((*it == '}') ? JSON_OBJECT : JSON_ARRAY)) + { + ERROR(it, "Mismatch closing brace/bracket"); + } + + // skip close character + ++it; + + // set top + top = top->parent; + } + break; + + case ':': + if (!top || top->type != JSON_OBJECT) + { + ERROR(it, "Unexpected character"); + } + ++it; + break; + + case ',': + CHECK_TOP(); + ++it; + break; + + case '"': + { + CHECK_TOP(); + + // skip '"' character + ++it; + + char *first = it; + char *last = it; + while (*it) + { + if ((unsigned char)*it < '\x20') + { + ERROR(first, "Control characters not allowed in strings"); + } + else if (*it == '\\') + { + switch (it[1]) + { + case '"': + *last = '"'; + break; + case '\\': + *last = '\\'; + break; + case '/': + *last = '/'; + break; + case 'b': + *last = '\b'; + break; + case 'f': + *last = '\f'; + break; + case 'n': + *last = '\n'; + ++escaped_newlines; + break; + case 'r': + *last = '\r'; + break; + case 't': + *last = '\t'; + break; + case 'u': + { + unsigned int codepoint; + if (hatoui(it + 2, it + 6, &codepoint) != it + 6) + { + ERROR(it, "Bad unicode codepoint"); + } + + if (codepoint <= 0x7F) + { + *last = (char)codepoint; + } + else if (codepoint <= 0x7FF) + { + *last++ = (char)(0xC0 | (codepoint >> 6)); + *last = (char)(0x80 | (codepoint & 0x3F)); + } + else if (codepoint <= 0xFFFF) + { + *last++ = (char)(0xE0 | (codepoint >> 12)); + *last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F)); + *last = (char)(0x80 | (codepoint & 0x3F)); + } + } + it += 4; + break; + default: + ERROR(first, "Unrecognized escape sequence"); + } + + ++last; + it += 2; + } + else if (*it == '"') + { + *last = 0; + ++it; + break; + } + else + { + *last++ = *it++; + } + } + + if (!name && top->type == JSON_OBJECT) + { + // field name in object + name = first; + } + else + { + // new string value + json_value *object = json_alloc(allocator); + + object->name = name; + name = 0; + + object->type = JSON_STRING; + object->string_value = first; + + json_append(top, object); + } + } + break; + + case 'n': + case 't': + case 'f': + { + CHECK_TOP(); + + // new null/bool value + json_value *object = json_alloc(allocator); + + object->name = name; + name = 0; + + // null + if (it[0] == 'n' && it[1] == 'u' && it[2] == 'l' && it[3] == 'l') + { + object->type = JSON_NULL; + it += 4; + } + // true + else if (it[0] == 't' && it[1] == 'r' && it[2] == 'u' && it[3] == 'e') + { + object->type = JSON_BOOL; + object->int_value = 1; + it += 4; + } + // false + else if (it[0] == 'f' && it[1] == 'a' && it[2] == 'l' && it[3] == 's' && it[4] == 'e') + { + object->type = JSON_BOOL; + object->int_value = 0; + it += 5; + } + else + { + ERROR(it, "Unknown identifier"); + } + + json_append(top, object); + } + break; + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + CHECK_TOP(); + + // new number value + json_value *object = json_alloc(allocator); + + object->name = name; + name = 0; + + object->type = JSON_INT; + + char *first = it; + while (*it != '\x20' && *it != '\x9' && *it != '\xD' && *it != '\xA' && *it != ',' && *it != ']' && *it != '}') + { + if (*it == '.' || *it == 'e' || *it == 'E') + { + object->type = JSON_FLOAT; + } + ++it; + } + + if (object->type == JSON_INT && atoi(first, it, &object->int_value) != it) + { + ERROR(first, "Bad integer number"); + } + + if (object->type == JSON_FLOAT && atof(first, it, &object->float_value) != it) + { + ERROR(first, "Bad float number"); + } + + json_append(top, object); + } + break; + + default: + ERROR(it, "Unexpected character"); + } + + // skip white space + while (*it == '\x20' || *it == '\x9' || *it == '\xD' || *it == '\xA') + { + ++it; + } + } + + if (top) + { + ERROR(it, "Not all objects/arrays have been properly closed"); + } + + return root; +} + +#define IDENT(n) for (int i = 0; i < n; ++i) printf(" ") + +void json_print(json_value *value, int ident) +{ + IDENT(ident); + if (value->name) printf("\"%s\" = ", value->name); + switch(value->type) + { + case JSON_NULL: + printf("null\n"); + break; + case JSON_OBJECT: + case JSON_ARRAY: + printf(value->type == JSON_OBJECT ? "{\n" : "[\n"); + for (json_value *it = value->first_child; it; it = it->next_sibling) + { + json_print(it, ident + 1); + } + IDENT(ident); + printf(value->type == JSON_OBJECT ? "}\n" : "]\n"); + break; + case JSON_STRING: + printf("\"%s\"\n", value->string_value); + break; + case JSON_INT: + printf("%d\n", value->int_value); + break; + case JSON_FLOAT: + printf("%f\n", value->float_value); + break; + case JSON_BOOL: + printf(value->int_value ? "true\n" : "false\n"); + break; + } +} + +JsonReader::JsonReader(const std::string &filename) : alloc_(1 << 12), root_(0) { + size_t buf_size; + buffer_ = (char *)VFSReadFile(filename.c_str(), &buf_size); + if (buffer_) { + parse(); + } else { + ELOG("Failed to read json %s", filename.c_str()); + } +} diff --git a/ext/vjson/json.h b/ext/vjson/json.h new file mode 100644 index 0000000000..08c4ba8b7a --- /dev/null +++ b/ext/vjson/json.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include +#include +#include "base/logging.h" +#include "block_allocator.h" +#include "file/vfs.h" + +enum json_type +{ + JSON_NULL, + JSON_OBJECT, + JSON_ARRAY, + JSON_STRING, + JSON_INT, + JSON_FLOAT, + JSON_BOOL, +}; + +struct json_value +{ + json_value() {} + + json_value *parent; + json_value *next_sibling; + json_value *first_child; + json_value *last_child; + + char *name; + union + { + char *string_value; + int int_value; + float float_value; + }; + + json_type type; + + int numChildren() const; + int numSiblings() const; // num siblings *after* this one only + const json_value *get(const char *child_name) const; + const json_value *get(const char *child_name, json_type type) const; + const char *getString(const char *child_name) const; + const char *getString(const char *child_name, const char *default_value) const; + bool getStringVector(std::vector *vec) const; + float getFloat(const char *child_name) const; + float getFloat(const char *child_name, float default_value) const; + int getInt(const char *child_name) const; + int getInt(const char *child_name, int default_value) const; + bool getBool(const char *child_name) const; + bool getBool(const char *child_name, bool default_value) const; + +private: + DISALLOW_COPY_AND_ASSIGN(json_value); +}; + +// low level interface +json_value *json_parse(char *source, char **error_pos, char **error_desc, int *error_line, block_allocator *allocator); +void json_print(json_value *value, int ident = 0); + + +// Easy-wrapper +class JsonReader { +public: + JsonReader(const std::string &filename); + JsonReader(const char *data, size_t size) : alloc_(1 << 12) { + buffer_ = (char *)malloc(size + 1); + memcpy(buffer_, data, size); + buffer_[size] = 0; + parse(); + } + + ~JsonReader() { + free(buffer_); + } + + void parse() { + char *error_pos; + char *error_desc; + int error_line; + root_ = json_parse((char *)buffer_, &error_pos, &error_desc, &error_line, &alloc_); + if (!root_) { + ELOG("Error at (%i): %s\n%s\n\n", error_line, error_desc, error_pos); + } + } + + bool ok() const { return root_ != 0; } + + json_value *root() { return root_; } + const json_value *root() const { return root_; } + + void print() { + json_print(root_); + } + +private: + char *buffer_; + block_allocator alloc_; + json_value *root_; + + DISALLOW_COPY_AND_ASSIGN(JsonReader); +}; diff --git a/ext/vjson/main.cpp b/ext/vjson/main.cpp new file mode 100644 index 0000000000..c0658c3ae0 --- /dev/null +++ b/ext/vjson/main.cpp @@ -0,0 +1,118 @@ +#include +#include +#include "json.h" + +void populate_sources(const char *filter, std::vector > &sources) +{ + char filename[256]; + for (int i = 1; i < 64; ++i) + { + sprintf(filename, filter, i); + FILE *fp = fopen(filename, "rb"); + if (fp) + { + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + fseek(fp, 0, SEEK_SET); + std::vector buffer(size + 1); + fread (&buffer[0], 1, size, fp); + fclose(fp); + sources.push_back(buffer); + } + else + { + break; + } + } + + printf("Loaded %d json files\n", sources.size()); +} + +#define IDENT(n) for (int i = 0; i < n; ++i) printf(" ") + +void print(json_value *value, int ident = 0) +{ + IDENT(ident); + if (value->name) printf("\"%s\" = ", value->name); + switch(value->type) + { + case JSON_NULL: + printf("null\n"); + break; + case JSON_OBJECT: + case JSON_ARRAY: + printf(value->type == JSON_OBJECT ? "{\n" : "[\n"); + for (json_value *it = value->first_child; it; it = it->next_sibling) + { + print(it, ident + 1); + } + IDENT(ident); + printf(value->type == JSON_OBJECT ? "}\n" : "]\n"); + break; + case JSON_STRING: + printf("\"%s\"\n", value->string_value); + break; + case JSON_INT: + printf("%d\n", value->int_value); + break; + case JSON_FLOAT: + printf("%f\n", value->float_value); + break; + case JSON_BOOL: + printf(value->int_value ? "true\n" : "false\n"); + break; + } +} + +bool parse(char *source) +{ + char *errorPos = 0; + char *errorDesc = 0; + int errorLine = 0; + block_allocator allocator(1 << 10); + + json_value *root = json_parse(source, &errorPos, &errorDesc, &errorLine, &allocator); + if (root) + { + print(root); + return true; + } + + printf("Error at line %d: %s\n%s\n\n", errorLine, errorDesc, errorPos); + return false; +} + +int main(int argc, char **argv) +{ + // Fail + printf("===FAIL===\n\n"); + std::vector > sources; + populate_sources("test/fail%d.json", sources); + int passed = 0; + for (size_t i = 0; i < sources.size(); ++i) + { + printf("Parsing %d\n", i + 1); + if (parse(&sources[i][0])) + { + ++passed; + } + } + printf("Passed %d from %d tests\n", passed, sources.size()); + + // Pass + sources.clear(); + printf("\n===PASS===\n\n"); + populate_sources("test/pass%d.json", sources); + passed = 0; + for (size_t i = 0; i < sources.size(); ++i) + { + printf("Parsing %d\n", i + 1); + if (parse(&sources[i][0])) + { + ++passed; + } + } + printf("Passed %d from %d tests\n", passed, sources.size()); + + return 0; +} diff --git a/file/CMakeLists.txt b/file/CMakeLists.txt new file mode 100644 index 0000000000..e0b552014a --- /dev/null +++ b/file/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SRCS + easy_file.cpp + chunk_file.cpp + zip_read.cpp + file_util.cpp) + +set(SRCS ${SRCS}) + +add_library(file STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp new file mode 100644 index 0000000000..9417a98ecc --- /dev/null +++ b/file/chunk_file.cpp @@ -0,0 +1,274 @@ +#include "base/logging.h" +#include "file/chunk_file.h" +#include "file/zip_read.h" + +//#define CHUNKDEBUG + +ChunkFile::ChunkFile(const char *filename, bool _read) { + data=0; + fn = filename; + fastMode=false; + numLevels=0; + read=_read; + pos=0; + didFail=false; + + fastMode = read ? true : false; + + if (fastMode) { + size_t size; + data = (uint8 *)VFSReadFile(filename, &size); + if (!data) { + ELOG("Chunkfile fail: %s", filename); + didFail = true; + return; + } + eof = size; + return; + } + + if (file.open(filename, FILE_WRITE)) { + didFail=false; + eof=file.fileSize(); + } else { + didFail=true; + return; + } +} + +ChunkFile::~ChunkFile() { + if (fastMode && data) + delete [] data; + else + file.close(); +} + +int ChunkFile::readInt() { + if (pos>8, id>>16, id>>24); +#endif + stack[numLevels]=temp; + seekTo(stack[numLevels].parentStartLocation); + return false; + } + + //descend into it + //pos was set inside the loop above + eof = stack[numLevels].startLocation + stack[numLevels].length; + numLevels++; +#ifdef CHUNKDEBUG + ILOG("Descended into %c%c%c%c", id, id>>8, id>>16, id>>24); +#endif + return true; + } else { +#ifndef DEMO_VERSION //if this is missing.. heheh + //write a chunk id, and prepare for filling in length later + writeInt(id); + writeInt(0); //will be filled in by Ascend + stack[numLevels].startLocation=pos; + numLevels++; + return true; +#else + return true; +#endif + } +} + +void ChunkFile::seekTo(int _pos) { + if (!fastMode) + file.seekBeg(_pos); + pos=_pos; +} + +//let's ascend out +void ChunkFile::ascend() { + if (read) { + //ascend, and restore information + numLevels--; + seekTo(stack[numLevels].parentStartLocation); + eof = stack[numLevels].parentEOF; +#ifdef CHUNKDEBUG + int id = stack[numLevels].ID; + ILOG("Ascended out of %c%c%c%c", id, id>>8, id>>16, id>>24); +#endif + } else { + numLevels--; + //now fill in the written length automatically + int posNow = pos; + seekTo(stack[numLevels].startLocation - 4); + writeInt(posNow-stack[numLevels].startLocation); + seekTo(posNow); + } +} + +//read a block +void ChunkFile::readData(void *what, int count) { + if (fastMode) + memcpy(what, data + pos, count); + else + file.read(what,count); + + pos+=count; + char temp[4]; //discarded + count &= 3; + if (count) { + count=4-count; + if (!fastMode) + file.read(temp,count); + pos+=count; + } +} + +//write a block +void ChunkFile::writeData(const void *what, int count) { + file.write(what, count); + pos+=count; + char temp[5]={0,0,0,0,0}; + count &= 3; + if (count) + { + count=4-count; + file.write(temp,count); + pos+=count; + } +} + +void ChunkFile::writeWString(String str) { + wchar_t *text; + int len=str.length(); +#ifdef UNICODE + text = str.getPointer(); +#else + text=new wchar_t[len+1]; + str.toUnicode(text); +#endif + writeInt(len); + writeData((char *)text,len*sizeof(wchar_t)); +#ifndef UNICODE + delete [] text; +#endif +} + +String ChunkFile::readWString() { + int len=readInt(); + wchar_t *text = new wchar_t[len+1]; + readData((char *)text,len*sizeof(wchar_t)); + text[len]=0; +#ifdef UNICODE + String s(text); + delete [] text; + return s; +#else + String temp; + temp.fromUnicode(text); + delete [] text; + return temp; +#endif +} + +static void toUnicode(const std::string &str, uint16 *t) { + for (int i=0; i<(int)str.size(); i++) { + *t++ = str[i]; + } + *t++ = '\0'; +} + +static std::string fromUnicode(const uint16 *src, int len) { + struct Local { + static int clamp(int i) { + return i>255?' ':i; + } + }; + + std::string str; + str.resize(len); + + for (int i=0; i + +#include "base/basictypes.h" +#include "base/LAMEString.h" +#include "file/easy_file.h" + +// TO REMEMBER WHEN USING: + +// EITHER a chunk contains ONLY data +// OR it contains ONLY other chunks +// otherwise the scheme breaks... +// hm.. or come to think about it, some data at the beginning of a chunk with subchunks WOULD work.. +// but not safely, so don't try +inline uint32 flipID(uint32 id) { + return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000); +} + +class ChunkFile { +public: + ChunkFile(const char *filename, bool _read); + ~ChunkFile(); + + bool descend(uint32 id); + void ascend(); + + int readInt(); + void readInt(int &i) {i = readInt();} + void readData(void *data, int count); + String readWString(); + + void writeString(const std::string &str); + std::string readString(); + + void writeInt(int i); + void writeWString(String str); + void writeData(const void *data, int count); + + int getCurrentChunkSize(); + bool failed() const {return didFail;} + std::string filename() const { return fn; } + +private: + std::string fn; + LAMEFile file; + struct ChunkInfo { + int startLocation; + int parentStartLocation; + int parentEOF; + unsigned int ID; + int length; + }; + ChunkInfo stack[8]; + int numLevels; + + uint8 *data; + int pos,eof; + bool fastMode; + bool read; + bool didFail; + + void seekTo(int _pos); + int getPos() const {return pos;} +}; + diff --git a/file/easy_file.cpp b/file/easy_file.cpp new file mode 100644 index 0000000000..6256bead04 --- /dev/null +++ b/file/easy_file.cpp @@ -0,0 +1,96 @@ +#include + +#include "base/basictypes.h" +#include "base/LAMEString.h" +#include "file/easy_file.h" + +LAMEFile::LAMEFile() : file_(NULL) { + isOpen = false; +} + +LAMEFile::~LAMEFile() { } + +bool LAMEFile::open(const char *filename, eFileMode mode) { + //for easier access if we want to expand the path.. + // String temp=filename; + // temp = getRelativePath(temp); + + //it's time to open the file + file_ = fopen(filename, mode == FILE_READ ? "rb" : "wb"); + + if (!file_) { + isOpen = false; + } else { + isOpen = true; + if (mode == FILE_READ) { + fseek(file_, 0, SEEK_END); + size_ = ftell(file_); + fseek(file_, 0, SEEK_SET); + } + } + return isOpen; +} + +void LAMEFile::close() { + if (isOpen) { + //close the file and reset variables + fclose(file_); + file_ = NULL; + isOpen=false; + } +} + +int LAMEFile::fileSize() { + if (!isOpen) //of course + return 0; + else + return size_; +} + +std::string LAMEFile::readAll() { + std::string s; + size_t size = fileSize(); + s.resize(size); + read(&s[0], size); + return s; +} + +int LAMEFile::write(const void *data, int size) { + if (isOpen) { + return fwrite(data, 1, size, file_); //we return the number of bytes that actually got written + } else { + return 0; + } +} + +int LAMEFile::read(void *data, int size) { + if (isOpen) { + return fread(data, 1, size, file_); + } else { + return 0; + } +} + +int LAMEFile::readInt() { + int temp; + if (read(&temp, sizeof(int))) + return temp; + else + return 0; +} + +void LAMEFile::writeInt(int i) { + write(&i, sizeof(int)); +} + +char LAMEFile::readChar() { + char temp; + if (read(&temp, sizeof(char))) + return temp; + else + return 0; +} + +void LAMEFile::writeChar(char i) { + write(&i,sizeof(char)); +} diff --git a/file/easy_file.h b/file/easy_file.h new file mode 100644 index 0000000000..a0c4d24074 --- /dev/null +++ b/file/easy_file.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include + +#include "base/basictypes.h" + + +// Raw file paths, does not go through VFS. + +enum eFileMode { + FILE_READ=5, + FILE_WRITE=6 +}; + +class LAMEFile { +public: + LAMEFile(); + virtual ~LAMEFile(); + + bool open(const char *filename, eFileMode mode); + bool open(std::string filename, eFileMode mode) { + return open(filename.c_str(), mode); + } + void close(); + + void writeInt(int i); + void writeChar(char i); + int write(const void *data, int size); + void write(const std::string &str) { + write((void *)str.data(), str.size()); + } + + int readInt(); + char readChar(); + int read(void *data, int size); + + std::string readAll(); + + int fileSize(); + + void seekBeg(int pos) { + if (isOpen) fseek(file_,pos,SEEK_SET); + } + void seekEnd(int pos) { + if (isOpen) fseek(file_,pos,SEEK_END); + } + void seekCurrent(int pos) { + if (isOpen) fseek(file_,pos,SEEK_CUR); + } +private: + FILE *file_; + bool isOpen; + int size_; +}; diff --git a/file/file_util.cpp b/file/file_util.cpp new file mode 100644 index 0000000000..51e9684e07 --- /dev/null +++ b/file/file_util.cpp @@ -0,0 +1,125 @@ +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#include +#endif +#include +#include +#include "base/logging.h" +#include "base/basictypes.h" +#include "file/file_util.h" +#include + +bool WriteStringToFile(bool text_file, const std::string &str, const char *filename) +{ + FILE *f = fopen(filename, text_file ? "w" : "wb"); + if (!f) + return false; + size_t len = str.size(); + if (len != fwrite(str.data(), 1, str.size(), f)) + { + fclose(f); + return false; + } + fclose(f); + return true; +} + +// Overloaded GetSize, accepts FILE* +uint64_t GetSize(FILE *f) +{ + // can't use off_t here because it can be 32-bit + uint64_t pos = ftell(f); + if (fseek(f, 0, SEEK_END) != 0) { + return 0; + } + uint64_t size = ftell(f); + if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) { + return 0; + } + return size; +} + +bool ReadFileToString(bool text_file, const char *filename, std::string &str) +{ + FILE *f = fopen(filename, text_file ? "r" : "rb"); + if (!f) + return false; + size_t len = (size_t)GetSize(f); + char *buf = new char[len + 1]; + buf[fread(buf, 1, len, f)] = 0; + str = std::string(buf, len); + fclose(f); + delete [] buf; + return true; +} + +#define DIR_SEP "/" + +#ifndef METRO + +size_t getFilesInDir(const char *directory, std::vector *files) +{ + size_t foundEntries = 0; +#ifdef _WIN32 + // Find the first file in the directory. + WIN32_FIND_DATA ffd; +#ifdef UNICODE + HANDLE hFind = FindFirstFile((std::wstring(directory) + "\\*").c_str(), &ffd); +#else + HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd); +#endif + if (hFind == INVALID_HANDLE_VALUE) + { + FindClose(hFind); + return foundEntries; + } + // windows loop + do + { + const std::string virtualName(ffd.cFileName); +#else + struct dirent dirent, *result = NULL; + + DIR *dirp = opendir(directory); + if (!dirp) + return 0; + + // non windows loop + while (!readdir_r(dirp, &dirent, &result) && result) + { + const std::string virtualName(result->d_name); +#endif + // check for "." and ".." + if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || + ((virtualName[0] == '.') && (virtualName[1] == '.') && + (virtualName[2] == '\0'))) + continue; + + files->push_back(std::string(directory) + virtualName); +#ifdef _WIN32 + } while (FindNextFile(hFind, &ffd) != 0); + FindClose(hFind); +#else + } + closedir(dirp); +#endif + return foundEntries; +} + +void deleteFile(const char *file) +{ +#ifdef _WIN32 + if (!DeleteFile(file)) { + ELOG("Error deleting %s: %i", file, GetLastError()); + } +#else + int err = unlink(file); + if (err) { + ELOG("Error unlinking %s: %i", file, err); + } +#endif +} +#endif \ No newline at end of file diff --git a/file/file_util.h b/file/file_util.h new file mode 100644 index 0000000000..06ed549824 --- /dev/null +++ b/file/file_util.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +bool writeStringToFile(bool text_file, const std::string &str, const char *filename); +bool readFileToString(bool text_file, const char *filename, std::string &str); + + +size_t getFilesInDir(const char *directory, std::vector *files); +void deleteFile(const char *file); \ No newline at end of file diff --git a/file/vfs.h b/file/vfs.h new file mode 100644 index 0000000000..552eb6dbc1 --- /dev/null +++ b/file/vfs.h @@ -0,0 +1,12 @@ +#include "base/basictypes.h" + +class AssetReader; +// Virtual file system. + +void VFSRegister(const char *prefix, AssetReader *reader); +void VFSShutdown(); + +// Use delete [] to release the memory. +// Always allocates an extra '\0' at the end, so that it +// can be used for text like shader sources. +uint8_t *VFSReadFile(const char *filename, size_t *size); diff --git a/file/zip_read.cpp b/file/zip_read.cpp new file mode 100644 index 0000000000..71b6e2617f --- /dev/null +++ b/file/zip_read.cpp @@ -0,0 +1,137 @@ +#include + +#ifndef _WIN32 +#include +#endif + +#include "base/basictypes.h" +#include "base/logging.h" +#include "file/zip_read.h" + +#ifndef _WIN32 +uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { + // Figure out the file size first. + struct zip_stat zstat; + zip_stat(archive, filename, ZIP_FL_NOCASE, &zstat); + + uint8_t *contents = new uint8_t[zstat.size + 1]; + + zip_file *file = zip_fopen(archive, filename, 0); + if (!file) { + ELOG("Error opening %s from ZIP", filename); + delete [] contents; + return 0; + } + zip_fread(file, contents, zstat.size); + zip_fclose(file); + contents[zstat.size] = 0; + + *size = zstat.size; + return contents; +} + +#endif + +// The return is non-const because - why not? +uint8_t *ReadLocalFile(const char *filename, size_t *size) { + FILE *file = fopen(filename, "rb"); + if (!file) { + return 0; + } + fseek(file, 0, SEEK_END); + size_t f_size = ftell(file); + fseek(file, 0, SEEK_SET); + uint8_t *contents = new uint8_t[f_size+1]; + fread(contents, 1, f_size, file); + fclose(file); + contents[f_size] = 0; + *size = f_size; + return contents; +} + +#ifndef _WIN32 + +ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { + zip_file_ = zip_open(zip_file, 0, NULL); + strcpy(in_zip_path_, in_zip_path); + if (!zip_file_) { + ELOG("Failed to open %s as a zip file", zip_file); + } + // This is not really necessary. + int numFiles = zip_get_num_files(zip_file_); + for (int i = 0; i < numFiles; i++) { + const char* name = zip_get_name(zip_file_, i, 0); + if (name == NULL) { + ELOG("Error reading zip file name at index %i : %s", i, zip_strerror(zip_file_)); + return; + } + // ILOG("File %i : %s\n", i, name); + } +} + +ZipAssetReader::~ZipAssetReader() { + zip_close(zip_file_); +} + +uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { + char temp_path[256]; + strcpy(temp_path, in_zip_path_); + strcat(temp_path, path); + return ReadFromZip(zip_file_, temp_path, size); +} + +#endif + +uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { + char new_path[256] = {0}; + // Check if it already contains the path + if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { + } + else { + strcpy(new_path, path_); + } + strcat(new_path, path); + // ILOG("New path: %s", new_path); + return ReadLocalFile(new_path, size); +} + +struct VFSEntry { + const char *prefix; + AssetReader *reader; +}; + +static VFSEntry entries[16]; +static int num_entries = 0; + +void VFSRegister(const char *prefix, AssetReader *reader) { + entries[num_entries].prefix = prefix; + entries[num_entries].reader = reader; + ILOG("Registered VFS for %s", prefix); + num_entries++; +} + +void VFSShutdown() { + for (int i = 0; i < num_entries; i++) { + delete entries[i].reader; + } + num_entries = 0; +} + +uint8_t *VFSReadFile(const char *filename, size_t *size) { + int fn_len = strlen(filename); + for (int i = 0; i < num_entries; i++) { + int prefix_len = strlen(entries[i].prefix); + if (prefix_len >= fn_len) continue; + if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { + // ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); + uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); + if (data) + return data; + else + continue; + // Else try the other registered file systems. + } + } + ELOG("Missing filesystem for %s", filename); + return 0; +} diff --git a/file/zip_read.h b/file/zip_read.h new file mode 100644 index 0000000000..4194b5fd26 --- /dev/null +++ b/file/zip_read.h @@ -0,0 +1,45 @@ +#ifndef _WIN32 +#include +#endif + +#include + +#include "base/basictypes.h" +#include "file/vfs.h" + +// Direct readers. deallocate using delete []. +uint8_t *ReadLocalFile(const char *filename, size_t *size); + +class AssetReader { +public: + // use delete[] + virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; +}; + +#ifndef _WIN32 +uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size); +class ZipAssetReader : public AssetReader { +public: + ZipAssetReader(const char *zip_file, const char *in_zip_path); + ~ZipAssetReader(); + // use delete[] + virtual uint8_t *ReadAsset(const char *path, size_t *size); + +private: + zip *zip_file_; + char in_zip_path_[256]; +}; +#endif + +class DirectoryAssetReader : public AssetReader { +public: + DirectoryAssetReader(const char *path) { + strcpy(path_, path); + } + // use delete[] + virtual uint8_t *ReadAsset(const char *path, size_t *size); + +private: + char path_[512]; +}; + diff --git a/gfx/CMakeLists.txt b/gfx/CMakeLists.txt new file mode 100644 index 0000000000..97264f7d85 --- /dev/null +++ b/gfx/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SRCS + gl_debug_log.cpp + gl_lost_manager.cpp + texture.cpp + texture_atlas.cpp + texture_gen.cpp) + +set(SRCS ${SRCS}) + +add_library(gfx STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/gfx/gl_debug_log.cpp b/gfx/gl_debug_log.cpp new file mode 100644 index 0000000000..3bcfb80f4d --- /dev/null +++ b/gfx/gl_debug_log.cpp @@ -0,0 +1,66 @@ +#if defined(ANDROID) +#include +#include +typedef char GLchar; +#else +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif + +#include "base/logging.h" + +void glCheckzor(const char *file, int line) { + GLenum err = glGetError(); + if (err != GL_NO_ERROR) { + ELOG("GL error on line %i in %s: %i (%04x)", line, file, (int)err, (int)err); + } +} + +#ifndef ANDROID +#if 0 +void log_callback(GLenum source, GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + GLvoid* userParam) { + const char *src = "unknown"; + switch (source) { + case GL_DEBUG_SOURCE_API_GL_ARB: + src = "GL"; + break; + case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: + src = "GLSL"; + break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: + src = "X"; + break; + default: + break; + } + switch (type) { + case GL_DEBUG_TYPE_ERROR_ARB: + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: + ELOG("%s: %s", src, message); + break; + default: + ILOG("%s: %s", src, message); + break; + } +} +#endif +#endif + +void gl_log_enable() { +#ifndef ANDROID +#if 0 + glEnable(DEBUG_OUTPUT_SYNCHRONOUS_ARB); // TODO: Look into disabling, for more perf + glDebugMessageCallback(&log_callback, 0); + glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); +#endif +#endif +} diff --git a/gfx/gl_debug_log.h b/gfx/gl_debug_log.h new file mode 100644 index 0000000000..115a393d1a --- /dev/null +++ b/gfx/gl_debug_log.h @@ -0,0 +1,24 @@ +#pragma once + +// New skool debugging +void gl_log_enable(); + +// Old skool debugging + +#ifndef ANDROID +//#define DEBUG_OPENGL +#endif + +#if defined(DEBUG_OPENGL) + +void glCheckzor(const char *file, int line); +#define GL_CHECK() glCheckzor(__FILE__, __LINE__) + +#else + +#define GL_CHECK() + +#endif + + + diff --git a/gfx/gl_lost_manager.cpp b/gfx/gl_lost_manager.cpp new file mode 100644 index 0000000000..0ed6854d92 --- /dev/null +++ b/gfx/gl_lost_manager.cpp @@ -0,0 +1,49 @@ +#include + +#include "base/logging.h" +#include "gfx/gl_lost_manager.h" + +std::list *holders; + +GfxResourceHolder::~GfxResourceHolder() {} + +void register_gl_resource_holder(GfxResourceHolder *holder) { + if (holders) { + holders->push_back(holder); + } else { + WLOG("GL resource holder not initialized, cannot register resource"); + } +} +void unregister_gl_resource_holder(GfxResourceHolder *holder) { + if (holders) { + holders->remove(holder); + } else { + WLOG("GL resource holder not initialized, cannot unregister resource"); + } +} + +void gl_lost() { + if (!holders) { + WLOG("GL resource holder not initialized, cannot process lost request"); + return; + } + for (std::list::iterator iter = holders->begin(); + iter != holders->end(); ++iter) { + (*iter)->GLLost(); + } +} + +void gl_lost_manager_init() { + if (holders) { + FLOG("Double GL lost manager init"); + } + holders = new std::list(); +} + +void gl_lost_manager_shutdown() { + if (!holders) { + FLOG("Lost manager already shutdown"); + } + delete holders; + holders = 0; +} diff --git a/gfx/gl_lost_manager.h b/gfx/gl_lost_manager.h new file mode 100644 index 0000000000..fbcc4165ce --- /dev/null +++ b/gfx/gl_lost_manager.h @@ -0,0 +1,16 @@ +#pragma once + +class GfxResourceHolder { + public: + virtual ~GfxResourceHolder(); + virtual void GLLost() = 0; +}; + +void gl_lost_manager_init(); +void gl_lost_manager_shutdown(); + +void register_gl_resource_holder(GfxResourceHolder *holder); +void unregister_gl_resource_holder(GfxResourceHolder *holder); + +// Notifies all objects about the loss. +void gl_lost(); diff --git a/gfx/texture.cpp b/gfx/texture.cpp new file mode 100644 index 0000000000..a36041392c --- /dev/null +++ b/gfx/texture.cpp @@ -0,0 +1,287 @@ +#ifdef ANDROID +#ifdef USE_GLES2 +#include +#include +#else +#include +#include +#endif +#else +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif + +#include +#include +#include + +#ifndef ANDROID +#include "image/png_load.h" +#include "ext/etcpack/etcdec.h" +#endif + +#include "image/zim_load.h" +#include "base/logging.h" +#include "texture.h" +#include "gfx/texture_gen.h" +#include "gfx/gl_debug_log.h" +#include "gfx/gl_lost_manager.h" + +Texture::Texture() : id_(0) { + register_gl_resource_holder(this); +} + +void Texture::Destroy() { + if (id_) { + glDeleteTextures(1, &id_); + id_ = 0; + } +} + +void Texture::GLLost() { + ILOG("Reloading lost texture %s", filename_.c_str()); + Load(filename_.c_str()); +} + +Texture::~Texture() { + unregister_gl_resource_holder(this); + Destroy(); +} + +static void SetTextureParameters(int zim_flags) { + GLenum wrap = GL_REPEAT; + if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); + GL_CHECK(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + GL_CHECK(); +} + +bool Texture::Load(const char *filename) { + // hook for generated textures + if (!memcmp(filename, "gen:", 4)) { + // TODO + // return false; + int bpp, w, h; + bool clamp; + uint8_t *data = generateTexture(filename, bpp, w, h, clamp); + if (!data) + return false; + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + if (bpp == 1) { + + #ifdef ANDROID + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + #else + glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + #endif + } else { + FLOG("unsupported"); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + delete [] data; + return true; + } + + filename_ = filename; + // Currently contains many Rollerball-specific workarounds. + // They shouldn't really hurt anything else very much though. + int len = strlen(filename); + char fn[256]; + strcpy(fn, filename); + bool zim = false; + if (!strcmp("dds", &filename[len-3])) { + strcpy(&fn[len-3], "zim"); + zim = true; + } + if (!strcmp("6TX", &filename[len-3]) || !strcmp("6tx", &filename[len-3])) { + ILOG("Detected 6TX %s", filename); + strcpy(&fn[len-3], "zim"); + zim = true; + } + for (int i = 0; i < (int)strlen(fn); i++) { + if (fn[i] == '\\') fn[i] = '/'; + } + + if (fn[0] == 'm') fn[0] = 'M'; + const char *name = fn; + if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); + len = strlen(name); + #ifndef ANDROID + if (!strcmp("png", &name[len-3]) || + !strcmp("PNG", &name[len-3])) { + if (!LoadPNG(fn)) { + LoadXOR(); + return false; + } else { + return true; + } + } else + #endif + if (!strcmp("zim", &name[len-3])) { + if (!LoadZIM(name)) { + LoadXOR(); + return false; + } else { + return true; + } + } + LoadXOR(); + return false; +} + +#ifndef ANDROID +bool Texture::LoadPNG(const char *filename) { + unsigned char *image_data; + if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { + return false; + } + GL_CHECK(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(ZIM_GEN_MIPS); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image_data); + glGenerateMipmap(GL_TEXTURE_2D); + GL_CHECK(); + free(image_data); + return true; +} +#endif + +bool Texture::LoadXOR() { + width_ = height_ = 256; + unsigned char *buf = new unsigned char[width_*height_*4]; + for (int y = 0; y < 256; y++) { + for (int x = 0; x < 256; x++) { + buf[(y*width_ + x)*4 + 0] = x^y; + buf[(y*width_ + x)*4 + 1] = x^y; + buf[(y*width_ + x)*4 + 2] = x^y; + buf[(y*width_ + x)*4 + 3] = 0xFF; + } + } + GL_CHECK(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(ZIM_GEN_MIPS); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, + GL_RGBA, GL_UNSIGNED_BYTE, buf); + glGenerateMipmap(GL_TEXTURE_2D); + GL_CHECK(); + delete [] buf; + return true; +} + + +#ifndef ANDROID + +// Allocates using new[], doesn't free. +uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { + uint8_t *rgba = new uint8_t[width * height * 4]; + memset(rgba, 0xFF, width * height * 4); + for (int y = 0; y < height; y += 4) { + for (int x = 0; x < width; x += 4) { + DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8, + rgba + (y * width + x) * 4, width, 255); + } + } + return rgba; +} + +#endif + +bool Texture::LoadZIM(const char *filename) { + uint8_t *image_data[ZIM_MAX_MIP_LEVELS]; + int width[ZIM_MAX_MIP_LEVELS]; + int height[ZIM_MAX_MIP_LEVELS]; + + int flags; + int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]); + if (!num_levels) + return false; + width_ = width[0]; + height_ = height[0]; + int data_type = GL_UNSIGNED_BYTE; + int colors = GL_RGBA; + int storage = GL_RGBA; + bool compressed = false; + switch (flags & ZIM_FORMAT_MASK) { + case ZIM_RGBA8888: + data_type = GL_UNSIGNED_BYTE; + break; + case ZIM_RGBA4444: + data_type = GL_UNSIGNED_SHORT_4_4_4_4; + break; + case ZIM_RGB565: + data_type = GL_UNSIGNED_SHORT_5_6_5; + colors = GL_RGB; + storage = GL_RGB; + break; + case ZIM_ETC1: + compressed = true; + break; + } + + GL_CHECK(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(flags); + + if (compressed) { + for (int l = 0; l < num_levels; l++) { + int data_w = width[l]; + int data_h = height[l]; + if (data_w < 4) data_w = 4; + if (data_h < 4) data_h = 4; +#if defined(ANDROID) + int compressed_image_bytes = data_w * data_h / 2; + glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); + GL_CHECK(); +#else + image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h); + glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0, + GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]); +#endif + } + GL_CHECK(); +#if !defined(ANDROID) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); +#endif + } else { + for (int l = 0; l < num_levels; l++) { + glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0, + colors, data_type, image_data[l]); + } + if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) { + glGenerateMipmap(GL_TEXTURE_2D); + } + } + SetTextureParameters(flags); + + GL_CHECK(); + // Only free the top level, since the allocation is used for all of them. + delete [] image_data[0]; + return true; +} + +void Texture::Bind(int stage) { + GL_CHECK(); + if (stage != -1) + glActiveTexture(GL_TEXTURE0 + stage); + glBindTexture(GL_TEXTURE_2D, id_); + GL_CHECK(); +} diff --git a/gfx/texture.h b/gfx/texture.h new file mode 100644 index 0000000000..ffc7a05cb2 --- /dev/null +++ b/gfx/texture.h @@ -0,0 +1,44 @@ +#ifndef _TEXTURE_H +#define _TEXTURE_H + +#include + +#include "gfx/gl_lost_manager.h" + +class Texture : public GfxResourceHolder { + public: + Texture(); + ~Texture(); + + bool LoadZIM(const char *filename); +#ifndef ANDROID + bool LoadPNG(const char *filename); +#endif + bool LoadXOR(); // Loads a placeholder texture. + + // Deduces format from the filename. + // If loading fails, will load a 256x256 XOR texture. + // If filename begins with "gen:", will defer to texture_gen.cpp/h. + bool Load(const char *filename); + + void Bind(int stage = -1); + + void Destroy(); + + unsigned int Handle() const { + return id_; + } + + virtual void GLLost(); + std::string filename() const { return filename_; } + + private: + std::string filename_; +#ifdef METRO + ID3D11Texture2D *tex_; +#endif + unsigned int id_; + int width_, height_; +}; + +#endif diff --git a/gfx/texture_atlas.cpp b/gfx/texture_atlas.cpp new file mode 100644 index 0000000000..146aa615b4 --- /dev/null +++ b/gfx/texture_atlas.cpp @@ -0,0 +1,2 @@ +#include "gfx/texture_atlas.h" + diff --git a/gfx/texture_atlas.h b/gfx/texture_atlas.h new file mode 100644 index 0000000000..8dd9c4b746 --- /dev/null +++ b/gfx/texture_atlas.h @@ -0,0 +1,38 @@ +#pragma once + +struct AtlasChar { + // texcoords + float sx, sy, ex, ey; + // offset from the origin + float ox, oy; + // distance to move the origin forward + float wx; + // size in pixels + unsigned short pw, ph; +}; + +struct AtlasFont { + float padding; + float height; + float ascend; + float distslope; + AtlasChar chars[96]; +}; + +struct AtlasImage { + float u1, v1, u2, v2; + int w, h; +}; + +struct Atlas { + const char *filename; + const AtlasFont **fonts; + int num_fonts; + const AtlasImage *images; + int num_images; +}; + +enum { + PRINT_RIGHT = 1, + PRINT_CENTER = 2, +}; diff --git a/gfx/texture_dx11.cpp b/gfx/texture_dx11.cpp new file mode 100644 index 0000000000..bec73980c4 --- /dev/null +++ b/gfx/texture_dx11.cpp @@ -0,0 +1,272 @@ +#include "gfx/texture.h" + +#include + +#include +#include +#include + +#ifndef ANDROID +#include "image/png_load.h" +#include "ext/etcpack/etcdec.h" +#endif + +#include "image/zim_load.h" +#include "base/logging.h" +#include "texture.h" +#include "gfx/texture_gen.h" +#include "gfx/gl_debug_log.h" +#include "gfx/gl_lost_manager.h" + +Texture::Texture() : tex_(0) { + register_gl_resource_holder(this); + + + +} + +void Texture::Destroy() { + if (tex_) { + tex_->Release(); + tex_ = 0; + } +} + +void Texture::GLLost() { + ILOG("Reloading lost texture %s", filename_.c_str()); + Load(filename_.c_str()); +} + +Texture::~Texture() { + unregister_gl_resource_holder(this); + Destroy(); +} + +static void SetTextureParameters(int zim_flags) { +/* + GLenum wrap = GL_REPEAT; + if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); + GL_CHECK(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + GL_CHECK();*/ +} + +bool Texture::Load(const char *filename) { + // hook for generated textures + if (!memcmp(filename, "gen:", 4)) { + // TODO + // return false; + tex_ = (LPVOID)generateTexture(filename); + if (tex_) { + this->filename_ = filename; + } + return true; + } + + filename_ = filename; + // Currently contains many Rollerball-specific workarounds. + // They shouldn't really hurt anything else very much though. + int len = strlen(filename); + char fn[256]; + strcpy(fn, filename); + bool zim = false; + if (!strcmp("dds", &filename[len-3])) { + strcpy(&fn[len-3], "zim"); + zim = true; + } + if (!strcmp("6TX", &filename[len-3]) || !strcmp("6tx", &filename[len-3])) { + ILOG("Detected 6TX %s", filename); + strcpy(&fn[len-3], "zim"); + zim = true; + } + for (int i = 0; i < (int)strlen(fn); i++) { + if (fn[i] == '\\') fn[i] = '/'; + } + + if (fn[0] == 'm') fn[0] = 'M'; + const char *name = fn; + if (zim && 0 == memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); + len = strlen(name); + #ifndef ANDROID + if (!strcmp("png", &name[len-3]) || + !strcmp("PNG", &name[len-3])) { + if (!LoadPNG(fn)) { + LoadXOR(); + return false; + } else { + return true; + } + } else + #endif + if (!strcmp("zim", &name[len-3])) { + if (!LoadZIM(name)) { + LoadXOR(); + return false; + } else { + return true; + } + } + LoadXOR(); + return false; +} + +#ifndef METRO +#ifndef ANDROID +bool Texture::LoadPNG(const char *filename) { + unsigned char *image_data; + if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { + return false; + } + GL_CHECK(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(ZIM_GEN_MIPS); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image_data); + glGenerateMipmap(GL_TEXTURE_2D); + GL_CHECK(); + free(image_data); + return true; +} +#endif +#endif + +bool Texture::LoadXOR() { + width_ = height_ = 256; + unsigned char *buf = new unsigned char[width_*height_*4]; + for (int y = 0; y < 256; y++) { + for (int x = 0; x < 256; x++) { + buf[(y*width_ + x)*4 + 0] = x^y; + buf[(y*width_ + x)*4 + 1] = x^y; + buf[(y*width_ + x)*4 + 2] = x^y; + buf[(y*width_ + x)*4 + 3] = 0xFF; + } + } + GL_CHECK(); + ID3D11Device *ctx; + D3D11_TEXTURE2D_DESC desc; + desc.Width = width_; + desc.Height = height_; + desc.MipLevels = 0; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + if (FAILED(ctx->CreateTexture2D(&desc, 0, &tex_))) { + FLOG("Failed creating XOR texture"); + } + SetTextureParameters(ZIM_GEN_MIPS); + GL_CHECK(); + delete [] buf; + return true; +} + + +#ifndef ANDROID + +// Allocates using new[], doesn't free. +uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { + uint8_t *rgba = new uint8_t[width * height * 4]; + memset(rgba, 0xFF, width * height * 4); + for (int y = 0; y < height; y += 4) { + for (int x = 0; x < width; x += 4) { + DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8, + rgba + (y * width + x) * 4, width, 255); + } + } + return rgba; +} + +#endif + +bool Texture::LoadZIM(const char *filename) { + uint8_t *image_data[ZIM_MAX_MIP_LEVELS]; + int width[ZIM_MAX_MIP_LEVELS]; + int height[ZIM_MAX_MIP_LEVELS]; + + int flags; + int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]); + if (!num_levels) + return false; + width_ = width[0]; + height_ = height[0]; + int data_type = GL_UNSIGNED_BYTE; + int colors = GL_RGBA; + int storage = GL_RGBA; + bool compressed = false; + switch (flags & ZIM_FORMAT_MASK) { + case ZIM_RGBA8888: + data_type = GL_UNSIGNED_BYTE; + break; + case ZIM_RGBA4444: + data_type = DXGI_FORMAT_B4G4R4A4_UNORM; + break; + case ZIM_RGB565: + data_type = DXGI_FORMAT_B5G6R5_UNORM; + colors = GL_RGB; + storage = GL_RGB; + break; + case ZIM_ETC1: + compressed = true; + break; + } + + GL_CHECK(); + //glGenTextures(1, &id_); + //glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(flags); + + if (compressed) { + for (int l = 0; l < num_levels; l++) { + int data_w = width[l]; + int data_h = height[l]; + if (data_w < 4) data_w = 4; + if (data_h < 4) data_h = 4; +#if defined(ANDROID) + int compressed_image_bytes = data_w * data_h / 2; + glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); + GL_CHECK(); +#else + //image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h); + //glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0, + // GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]); +#endif + } + GL_CHECK(); +#if !defined(ANDROID) + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); +#endif + } else { + for (int l = 0; l < num_levels; l++) { + //glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0, + // colors, data_type, image_data[l]); + } + if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) { + //glGenerateMipmap(GL_TEXTURE_2D); + } + } + SetTextureParameters(flags); + + GL_CHECK(); + // Only free the top level, since the allocation is used for all of them. + delete [] image_data[0]; + return true; +} + +void Texture::Bind(int stage) { + GL_CHECK(); + //if (stage != -1) + // glActiveTexture(GL_TEXTURE0 + stage); + // glBindTexture(GL_TEXTURE_2D, id_); + GL_CHECK(); +} diff --git a/gfx/texture_gen.cpp b/gfx/texture_gen.cpp new file mode 100644 index 0000000000..dd02e0079b --- /dev/null +++ b/gfx/texture_gen.cpp @@ -0,0 +1,54 @@ +// Minimal procedural texture generator to generate some usual textures like circles. +// "Gen" textures have filenames like this: "gen:256:256:vignette:0.1" +// +// These must be VERY VERY fast to not slow down loading. Could multicore this in the +// future. +// TODO: Rewrite to make more portable (should not use gfx api in here) + +#include +#include + +#include "base/basictypes.h" +#include "gfx/texture.h" + + +uint8_t *generateTexture(const char *filename, int &bpp, int &w, int &h, bool &clamp) { + char name_and_params[256]; + // security check :) + if (strlen(filename) > 200) + return 0; + sscanf(filename, "gen:%i:%i:%s", &w, &h, name_and_params); + + bool mip = false; + uint8_t *data; + if (!strcmp(name_and_params, "vignette")) { + bpp = 1; + data = new uint8_t[w*h]; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; x++) { + float dx = (float)(x - w/2) / (w/2); + float dy = (float)(y - h/2) / (h/2); + float dist = sqrtf(dx * dx + dy * dy); + dist /= 1.414f; + float val = 1.0 - powf(dist, 1.4f); + data[y*w + x] = val * 255; + } + } + } else if (!strcmp(name_and_params, "circle")) { + bpp = 1; + // TODO + data = new uint8_t[w*h]; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; x++) { + float dx = (float)(x - w/2) / (w/2); + float dy = (float)(y - h/2) / (h/2); + float dist = sqrtf(dx * dx + dy * dy); + dist /= 1.414f; + float val = 1.0 - powf(dist, 1.4f); + data[y*w + x] = val * 255; + } + } + } + + return data; +} diff --git a/gfx/texture_gen.h b/gfx/texture_gen.h new file mode 100644 index 0000000000..f5653b6f48 --- /dev/null +++ b/gfx/texture_gen.h @@ -0,0 +1,11 @@ +// Minimal procedural texture generator to generate some useful but unnecessary-to-store textures like circles. +// "Gen" textures have filenames like this: "gen:256:256:4444:vignette:0.1" + +#include "gfx/texture.h" + +// Returns an OpenGL ID for now. + +uint8_t *generateTexture(const char *filename, int &bpp, int &w, int &h, bool &clamp); + + + diff --git a/gfx_es1/CMakeLists.txt b/gfx_es1/CMakeLists.txt new file mode 100644 index 0000000000..f618a2598c --- /dev/null +++ b/gfx_es1/CMakeLists.txt @@ -0,0 +1,10 @@ +set(SRCS + draw_buffer.cpp +) +set(SRCS ${SRCS}) + +add_library(gfx_es1 STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/gfx_es1/draw_buffer.cpp b/gfx_es1/draw_buffer.cpp new file mode 100644 index 0000000000..8c8b956933 --- /dev/null +++ b/gfx_es1/draw_buffer.cpp @@ -0,0 +1,287 @@ +// OpenGL ES 1.1 + +#ifdef ANDROID +#include +#else +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif +#include +#include + +#include "gfx_es1/draw_buffer.h" +#include "gfx/texture_atlas.h" + +#include "main_atlas.h" + +LAMEBuffer buffer; +LAMEBuffer topbuffer; + +#define MAX_VERTS 16384 + +LAMEBuffer::LAMEBuffer() { + verts = new Vertex[MAX_VERTS]; + vcount = 0; + xoffset = 0; + yoffset = 0; + fontscalex = 0.37f; + fontscaley = 0.37f; +} + +LAMEBuffer::~LAMEBuffer() { + delete [] verts; + verts = 0; +} + +void LAMEBuffer::Setup() { + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_TEXTURE_2D); +} + +void LAMEBuffer::Finish() { + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +// Draws what we have collected so far, so that we can change blend modes etc. +// TODO: Collect states and then blast at the end? +void LAMEBuffer::Flush() { + if (vcount > 0) { + glVertexPointer (3, GL_FLOAT, sizeof(Vertex), (void *)&verts[0].x); + glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(Vertex), (void *)&verts[0].rgba); + glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void *)&verts[0].u); + glDrawArrays(GL_TRIANGLES, 0, vcount); + // printf("Drawing %i triangles\n", vcount / 3); + } + vcount = 0; +} + +void LAMEBuffer::V(float x, float y, uint32 color, float u, float v) { +#ifndef ANDROID + if (vcount >= MAX_VERTS) { + printf("Hit max # verts\n"); + } +#endif + verts[vcount].x = x + xoffset; + verts[vcount].y = y + yoffset; + verts[vcount].z = 0.0; + verts[vcount].rgba = color; + verts[vcount].u = u; + verts[vcount].v = v; + vcount++; +} + +void LAMEBuffer::rectFill(int x1, int y1, int x2, int y2, Color color) { + rectFillFaded(x1, y1, x2, y2, color, color); +} + +void LAMEBuffer::rectFillFaded(int x1, int y1, int x2, int y2, Color color1, Color color2) { + V(x1, y1, color1, 0, 0); + V(x2, y1, color1, 1, 0); + V(x2, y2, color2, 1, 1); + V(x1, y1, color1, 0, 0); + V(x2, y2, color2, 1, 1); + V(x1, y2, color2, 0, 1); +} + +void LAMEBuffer::MeasureImage(int atlas_image, float *w, float *h) { + const AtlasImage &image = atlas->images[atlas_image]; + *w = image.w; + *h = image.h; +} + +void LAMEBuffer::DrawImage(int atlas_image, float x, float y, Color color) { + const AtlasImage &image = atlas->images[atlas_image]; + float w = image.w; + float h = image.h; + DrawImageStretch(atlas_image, x, y, x + w, y + h, color); +} + +void LAMEBuffer::DrawImageCenter(int atlas_image, float x, float y, Color color) { + const AtlasImage &image = atlas->images[atlas_image]; + DrawImage(atlas_image, x - image.w/2, y - image.h/2, color); +} + +void LAMEBuffer::DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color) { + const AtlasImage &image = atlas->images[atlas_image]; + V(x1, y1, color, image.u1, image.v1); + V(x2, y1, color, image.u2, image.v1); + V(x2, y2, color, image.u2, image.v2); + V(x1, y1, color, image.u1, image.v1); + V(x2, y2, color, image.u2, image.v2); + V(x1, y2, color, image.u1, image.v2); +} + +void LAMEBuffer::DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color) { + V(x1, y1, color, u1, v1); + V(x2, y1, color, u2, v1); + V(x2, y2, color, u2, v2); + V(x1, y1, color, u1, v1); + V(x2, y2, color, u2, v2); + V(x1, y2, color, u1, v2); +} + +void LAMEBuffer::DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color, float corner_scale) { + const AtlasImage &image = atlas->images[atlas_image]; + + float um = (image.u2 - image.u1) * 0.5f; + float vm = (image.v2 - image.v1) * 0.5f; + float iw2 = (image.w * 0.5f) * corner_scale; + float ih2 = (image.h * 0.5f) * corner_scale; + float xa = x1 + iw2; + float xb = x2 - iw2; + float ya = y1 + ih2; + float yb = y2 - ih2; + float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; + // Top row + DrawTexRect(x1, y1, xa, ya, u1, v1, um, vm, color); + DrawTexRect(xa, y1, xb, ya, um, v1, um, vm, color); + DrawTexRect(xb, y1, x2, ya, um, v1, u2, vm, color); + // Middle row + DrawTexRect(x1, ya, xa, yb, u1, vm, um, vm, color); + DrawTexRect(xa, ya, xb, yb, um, vm, um, vm, color); + DrawTexRect(xb, ya, x2, yb, um, vm, u2, vm, color); + // Bottom row + DrawTexRect(x1, yb, xa, y2, u1, vm, um, v2, color); + DrawTexRect(xa, yb, xb, y2, um, vm, um, v2, color); + DrawTexRect(xb, yb, x2, y2, um, vm, u2, v2, color); +} + +void LAMEBuffer::DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color, float corner_scale) { + const AtlasImage &image = atlas->images[atlas_image]; + float um = (image.u2 - image.u1) * 0.5f; + float iw2 = (image.w * 0.5f) * corner_scale; + float xa = x1 + iw2; + float xb = x2 - iw2; + float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; + float y2 = y1 + image.h; + DrawTexRect(x1, y1, xa, y2, u1, v1, um, v2, color); + DrawTexRect(xa, y1, xb, y2, um, v1, um, v2, color); + DrawTexRect(xb, y1, x2, y2, um, v1, u2, v2, color); +} + +void LAMEBuffer::MeasureText(int font, const char *text, float *w, float *h) { + const AtlasFont &atlasfont = *atlas->fonts[font]; + unsigned char cval; + float wacc = 0, maxh = 0; + while ((cval = *text++) != '\0') { + if (cval < 32) continue; + if (cval > 127) continue; + AtlasChar c = atlasfont.chars[cval - 32]; + wacc += c.wx * fontscalex; + maxh = 10.0; + } + *w = wacc; + *h = maxh; +} + +void LAMEBuffer::DrawText(int font, const char *text, float x, float y, Color color, int flags) { + const AtlasFont &atlasfont = *atlas->fonts[font]; + unsigned char cval; + if (flags) { + float w, h; + MeasureText(font, text, &w, &h); + if (flags & TEXT_HCENTER) x -= w / 2; + if (flags & TEXT_RIGHT) x -= w; + if (flags & TEXT_VCENTER) y -= h / 2; + } + float sx = x; + while ((cval = *text++) != '\0') { + if (cval == '\n') { + y += 10; + x = sx; + continue; + } + if (cval < 32) continue; + if (cval > 127) continue; + AtlasChar c = atlasfont.chars[cval - 32]; + float cx1 = x + c.ox * fontscalex; + float cy1 = y + c.oy * fontscaley; + float cx2 = x + (c.ox + c.pw) * fontscalex; + float cy2 = y + (c.oy + c.ph) * fontscaley; + V(cx1, cy1, color, c.sx, c.sy); + V(cx2, cy1, color, c.ex, c.sy); + V(cx2, cy2, color, c.ex, c.ey); + V(cx1, cy1, color, c.sx, c.sy); + V(cx2, cy2, color, c.ex, c.ey); + V(cx1, cy2, color, c.sx, c.ey); + x += c.wx * fontscalex; + } +} + + +void LAMEBuffer::hLine(int x1, int y, int x2, Color color) { + rectFill(x1, y, x2, y + 1, color | 0xFF000000); +} + +void LAMEBuffer::hLineDarken(int x1, int y, int x2) { + rectFill(x1, y, x2, y + 1, 0x80000000); +} + +void LAMEBuffer::vLine(int x, int y1, int y2, Color color) { + rectFill(x, y1, x + 1, y2, color); +} + +void LAMEBuffer::vLineAlpha50(int x, int y1, int y2, Color color) { + vLine(x, y1, y2, (color & 0x00FFFFFF) | 0x80); +} + +void LAMEBuffer::rect(int x1, int y1, int x2, int y2, Color color) { + hLine(x1, y1, x2, color); + hLine(x1, y2, x2, color); + vLine(x1, y1, y2, color); + vLine(x2, y1, y2, color); +} + +void LAMEBuffer::rectFillDarken(int x1, int y1, int x2, int y2) { + rectFill(x1, y1, x2, y2, 0x80000000); +} + +void LAMEBuffer::RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color) { + // TODO - will be good for knobs + /* + float c = cos(angle + PI/4); + float s = sin(angle + PI/4); + + float x1 = x + c * scale; + float y1 = y + s * scale; + + float x2 = x + c * scale; + float y2 = y + s * scale; + + float x3 = x + c * scale; + float y3 = y + s * scale; + + V(x1, y1, color1, 0, 0); + V(x2, y1, color1, 1, 0); + V(x2, y2, color2, 1, 1); + V(x1, y1, color1, 0, 0); + V(x2, y2, color2, 1, 1); + V(x1, y2, color2, 0, 1); +*/ +} + +void LAMEBuffer::drawText(const TCHAR *text, int x, int y, Color color, int font) { + DrawText(UBUNTU24, text, x, y+3, color); +} +void LAMEBuffer::drawTextCenter(const TCHAR *text, int x, int y, Color color, int font) { + DrawText(UBUNTU24, text, x, y+3, color, TEXT_HCENTER); +} +void LAMEBuffer::drawTextShadow(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { + DrawText(UBUNTU24, text, x, y+3, color); +} +void LAMEBuffer::drawTextShadowCenter(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { + DrawText(UBUNTU24, text, x, y+3, color, TEXT_HCENTER); +} +void LAMEBuffer::drawTextContrastCenter(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { + DrawText(UBUNTU24, text, x, y+3, color, TEXT_HCENTER); +} +void LAMEBuffer::drawTextContrast(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { + DrawText(UBUNTU24, text, x, y+3, color); +} diff --git a/gfx_es1/draw_buffer.h b/gfx_es1/draw_buffer.h new file mode 100644 index 0000000000..8796f85447 --- /dev/null +++ b/gfx_es1/draw_buffer.h @@ -0,0 +1,122 @@ +#ifndef __LAMEBUFFER_H__ +#define __LAMEBUFFER_H__ + +#include "base/basictypes.h" +#include "base/color.h" + +class Atlas; + +enum { + TEXT_LEFT = 0, + TEXT_BASELINE = 0, + TEXT_TOP = 1, + TEXT_BOTTOM = 2, + TEXT_HCENTER = 4, + TEXT_VCENTER = 8, + TEXT_RIGHT = 16, +}; + +// OpenGL-based 2D primitive buffer. For GLES 1.1. +// Do not inherit from this class. +class LAMEBuffer { + public: + LAMEBuffer(); + ~LAMEBuffer(); + + void SetAtlas(const Atlas *_atlas) { + atlas = _atlas; + } + + void hLine(int x1, int y, int x2, Color color); + void hLineDarken(int x1, int y, int x2); + void vLine(int x, int y1, int y2, Color color); + void vLineAlpha50(int x, int y1, int y2, Color color); + + void rect(int x1, int y1, int x2, int y2, Color color); + void rectFill(int x1, int y1, int x2, int y2, Color color); + void rectRectFill(int x1, int y1, int x2, int y2, Color border, Color fill) { + rectFill(x1,y1,x2,y2,fill); + rect(x1,y1,x2,y2,border); + } + void rectFillFaded(int x1, int y1, int x2, int y2, Color color1, Color color2); + void rectFillDarkFaded(int x1, int y1, int x2, int y2, Color color) { + rectFillFaded(x1,y1,x2,y2,color, darkenColor(color)); + } + + void rectFillDarken(int x1, int y1, int x2, int y2); + + // New drawing APIs + void MeasureImage(int atlas_image, float *w, float *h); + void DrawImage(int atlas_image, float x, float y, Color color = COLOR(0xFFFFFF)); + void DrawImageCenter(int atlas_image, float x, float y, Color color = COLOR(0xFFFFFF)); + void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); + void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); + // Results in 18 triangles. Kind of expensive for a button. + void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); + // This is only 6 triangles, much cheaper. + void DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); + + void MeasureText(int font, const char *text, float *w, float *h); + void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); + + void RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color); + + void drawText(const TCHAR *text, int x, int y, Color color = 0, int font=0); + void drawTextCenter(const TCHAR *text, int x, int y, Color color, int font=0); + void drawTextShadow(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font=0); + void drawTextShadowCenter(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font=0); + void drawTextContrastCenter(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font=0); + void drawTextContrast(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font=0); + + void SetFontScale(float xs, float ys) { + fontscalex = xs; + fontscaley = ys; + } + + // Offset management, for easier hierarchical drawing + void PushOffset(int xoff, int yoff) { + // TODO: Use a stack + xoffset = xoff; yoffset = yoff; + } + void PopOffset(int xoff, int yoff) { + xoffset = 0; yoffset = 0; + } + + // Only use in bunches of three. To draw triangles. + inline void V(float x, float y, uint32 color, float u, float v); + + // Call these around all Flush calls of drawbuffers. More than one flush call + // is fine. + static void Setup(); // Enables client state. + static void Finish(); // Disables client state + + // Draws what we have collected so far, so that we can change blend modes etc. + void Flush(); + + private: + const Atlas *atlas; + + float xoffset, yoffset; + + float fontscalex; + float fontscaley; + + struct Vertex { + float x, y, z; + uint32 rgba; + float u, v; + }; + int vcount; + Vertex *verts; +}; + +// For regular non blended drawing. No alpha, no alpha test. +extern LAMEBuffer buffer; + +// The two blend buffers could be combined using premultiplied alpha. +// But who cares. + +// For regular blended drawing. Standard alpha, no alpha test. +extern LAMEBuffer topbuffer; + +#endif //__LAMEBUFFER_H__ diff --git a/gfx_es2/CMakeLists.txt b/gfx_es2/CMakeLists.txt new file mode 100644 index 0000000000..d412efb163 --- /dev/null +++ b/gfx_es2/CMakeLists.txt @@ -0,0 +1,12 @@ +set(SRCS + draw_buffer.cpp + fbo.cpp + glsl_program.cpp) + +set(SRCS ${SRCS}) + +add_library(gfx_es2 STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp new file mode 100644 index 0000000000..6b92bf6b3e --- /dev/null +++ b/gfx_es2/draw_buffer.cpp @@ -0,0 +1,287 @@ +#ifdef ANDROID +#include +#include +#else +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif + +#include +#include "base/logging.h" +#include "math/math_util.h" +#include "gfx_es2/draw_buffer.h" +#include "gfx_es2/glsl_program.h" +#include "gfx/texture_atlas.h" +#include "gfx/gl_debug_log.h" + +DrawBuffer::DrawBuffer() : count_(0) { + // Enough? + verts_ = new Vertex[5000]; + fontscalex = 1.0f; + fontscaley = 1.0f; +} +DrawBuffer::~DrawBuffer() { + delete [] verts_; +} + +void DrawBuffer::Begin(DrawBufferMode dbmode) { + count_ = 0; + mode_ = dbmode; +} + +void DrawBuffer::End() { + // Currently does nothing, but call it! +} + +void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { + if (count_ == 0) + return; + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + if (set_blend_state) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + glUniform1i(program->sampler0, 0); + glEnableVertexAttribArray(program->a_position); + glEnableVertexAttribArray(program->a_color); + if (program->a_texcoord0 != -1) + glEnableVertexAttribArray(program->a_texcoord0); + GL_CHECK(); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].x); + glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &verts_[0].r); + if (program->a_texcoord0 != -1) + glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].u); + glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_); + GL_CHECK(); + glDisableVertexAttribArray(program->a_position); + glDisableVertexAttribArray(program->a_color); + if (program->a_texcoord0 != -1) + glDisableVertexAttribArray(program->a_texcoord0); + GL_CHECK(); + + count_ = 0; +} + +void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) { + Vertex *vert = &verts_[count_++]; + vert->x = x; + vert->y = y; + vert->z = z; + // todo: speedup rgba here + vert->r = color & 0xFF; + vert->g = (color >> 8) & 0xFF; + vert->b = (color >> 16) & 0xFF; + vert->a = (color >> 24) & 0xFF; + vert->u = u; + vert->v = v; +} + +void DrawBuffer::Rect(float x, float y, float w, float h, uint32 color, int align) { + DoAlign(align, &x, &y, w, h); + RectVGradient(x, y, w, h, color, color); +} + +void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom) { + V(x, y, 0, colorTop, 0, 0); + V(x + w, y, 0, colorTop, 1, 0); + V(x + w, y + h, 0, colorBottom, 1, 1); + V(x, y, 0, colorTop, 0, 0); + V(x + w, y + h, 0, colorBottom, 1, 1); + V(x, y + h, 0, colorBottom, 0, 1); +} + +void DrawBuffer::MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops) { + for (int i = 0; i < numStops - 1; i++) { + float t0 = stops[i].t, t1 = stops[i+1].t; + uint32_t c0 = stops[i].t, c1 = stops[i+1].t; + RectVGradient(x, y + h * t0, w, h * (t1 - t0), c0, c1); + } +} + +void DrawBuffer::Rect(float x, float y, float w, float h, + float u, float v, float uw, float uh, + uint32 color) { + V(x, y, 0, color, u, v); + V(x + w, y, 0, color, u + uw, v); + V(x + w, y + h, 0, color, u + uw, v + uh); + V(x, y, 0, color, u, v); + V(x + w, y + h, 0, color, u + uw, v + uh); + V(x, y + h, 0, color, u, v + uh); +} + +void DrawBuffer::MeasureImage(int atlas_image, float *w, float *h) { + const AtlasImage &image = atlas->images[atlas_image]; + *w = (float)image.w; + *h = (float)image.h; +} + +void DrawBuffer::DrawImage(int atlas_image, float x, float y, float scale, Color color, int align) { + const AtlasImage &image = atlas->images[atlas_image]; + float w = (float)image.w * scale; + float h = (float)image.h * scale; + if (align & ALIGN_HCENTER) x -= w / 2; + if (align & ALIGN_RIGHT) x -= w; + if (align & ALIGN_VCENTER) y -= h / 2; + if (align & ALIGN_BOTTOM) y -= h; + DrawImageStretch(atlas_image, x, y, x + w, y + h, color); +} + +void DrawBuffer::DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color) { + const AtlasImage &image = atlas->images[atlas_image]; + V(x1, y1, color, image.u1, image.v1); + V(x2, y1, color, image.u2, image.v1); + V(x2, y2, color, image.u2, image.v2); + V(x1, y1, color, image.u1, image.v1); + V(x2, y2, color, image.u2, image.v2); + V(x1, y2, color, image.u1, image.v2); +} + +// TODO: make into arc +void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul) { + float angleDelta = PI * 2 / segments; + float uDelta = 1.0f / segments; + float t2 = thickness / 2.0f; + float r1 = radius + t2; + float r2 = radius - t2; + for (int i = 0; i < segments + 1; i++) { + float angle1 = i * angleDelta; + float angle2 = (i + 1) * angleDelta; + float u1 = u_mul * i * uDelta; + float u2 = u_mul * (i + 1) * uDelta; + // TODO: get rid of one pair of cos/sin per loop, can reuse + float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2); + const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc}; + const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc}; + V(x[0], y[0], color, u1, 0); + V(x[1], y[1], color, u2, 0); + V(x[2], y[2], color, u1, 1); + V(x[1], y[1], color, u2, 0); + V(x[3], y[3], color, u2, 1); + V(x[2], y[2], color, u1, 1); + } +} + +void DrawBuffer::DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color) { + V(x1, y1, color, u1, v1); + V(x2, y1, color, u2, v1); + V(x2, y2, color, u2, v2); + V(x1, y1, color, u1, v1); + V(x2, y2, color, u2, v2); + V(x1, y2, color, u1, v2); +} + +void DrawBuffer::DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color, float corner_scale) { + const AtlasImage &image = atlas->images[atlas_image]; + + float um = (image.u2 - image.u1) * 0.5f; + float vm = (image.v2 - image.v1) * 0.5f; + float iw2 = (image.w * 0.5f) * corner_scale; + float ih2 = (image.h * 0.5f) * corner_scale; + float xa = x1 + iw2; + float xb = x2 - iw2; + float ya = y1 + ih2; + float yb = y2 - ih2; + float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; + // Top row + DrawTexRect(x1, y1, xa, ya, u1, v1, um, vm, color); + DrawTexRect(xa, y1, xb, ya, um, v1, um, vm, color); + DrawTexRect(xb, y1, x2, ya, um, v1, u2, vm, color); + // Middle row + DrawTexRect(x1, ya, xa, yb, u1, vm, um, vm, color); + DrawTexRect(xa, ya, xb, yb, um, vm, um, vm, color); + DrawTexRect(xb, ya, x2, yb, um, vm, u2, vm, color); + // Bottom row + DrawTexRect(x1, yb, xa, y2, u1, vm, um, v2, color); + DrawTexRect(xa, yb, xb, y2, um, vm, um, v2, color); + DrawTexRect(xb, yb, x2, y2, um, vm, u2, v2, color); +} + +void DrawBuffer::DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color, float corner_scale) { + const AtlasImage &image = atlas->images[atlas_image]; + float um = (image.u1 + image.u2) * 0.5f; + float iw2 = (image.w * 0.5f) * corner_scale; + float xa = x1 + iw2; + float xb = x2 - iw2; + float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; + float y2 = y1 + image.h; + DrawTexRect(x1, y1, xa, y2, u1, v1, um, v2, color); + DrawTexRect(xa, y1, xb, y2, um, v1, um, v2, color); + DrawTexRect(xb, y1, x2, y2, um, v1, u2, v2, color); +} + +void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { + const AtlasFont &atlasfont = *atlas->fonts[font]; + unsigned char cval; + float wacc = 0, maxh = 0; + int lines = 1; + while ((cval = *text++) != '\0') { + if (cval < 32) continue; + if (cval > 127) continue; + if (cval == '\n') { + wacc = 0; + lines++; + } + AtlasChar c = atlasfont.chars[cval - 32]; + wacc += c.wx * fontscalex; + } + *w = wacc; + *h = atlasfont.height * fontscaley * lines; +} + +void DrawBuffer::DrawTextShadow(int font, const char *text, float x, float y, Color color, int flags) { + uint32_t alpha = (color >> 1) & 0xFF000000; + DrawText(font, text, x + 2, y + 2, alpha, flags); + DrawText(font, text, x, y, color, flags); +} + +void DrawBuffer::DoAlign(int align, float *x, float *y, float w, float h) { + if (align & ALIGN_HCENTER) *x -= w / 2; + if (align & ALIGN_RIGHT) *x -= w; + if (align & ALIGN_VCENTER) *y -= h / 2; + if (align & ALIGN_BOTTOM) *y -= h; +} + +void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int flags) { + const AtlasFont &atlasfont = *atlas->fonts[font]; + unsigned char cval; + float w, h; + MeasureText(font, text, &w, &h); + if (flags) { + DoAlign(flags, &x, &y, w, h); + } + y+=atlasfont.ascend*fontscaley; + float sx = x; + while ((cval = *text++) != '\0') { + if (cval == '\n') { + y += atlasfont.height * fontscaley; + x = sx; + continue; + } + if (cval < 32) continue; + if (cval > 127) continue; + AtlasChar c = atlasfont.chars[cval - 32]; + float cx1 = x + c.ox * fontscalex; + float cy1 = y + c.oy * fontscaley; + float cx2 = x + (c.ox + c.pw) * fontscalex; + float cy2 = y + (c.oy + c.ph) * fontscaley; + V(cx1, cy1, color, c.sx, c.sy); + V(cx2, cy1, color, c.ex, c.sy); + V(cx2, cy2, color, c.ex, c.ey); + V(cx1, cy1, color, c.sx, c.sy); + V(cx2, cy2, color, c.ex, c.ey); + V(cx1, cy2, color, c.sx, c.ey); + x += c.wx * fontscalex; + } +} + +void DrawBuffer::EnableBlend(bool enable) { + if (enable) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); +} \ No newline at end of file diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h new file mode 100644 index 0000000000..89ea949f4e --- /dev/null +++ b/gfx_es2/draw_buffer.h @@ -0,0 +1,110 @@ +#pragma once + +#include "base/basictypes.h" +#include "base/color.h" + +struct Atlas; + +enum { + ALIGN_LEFT = 0, + ALIGN_RIGHT = 16, + ALIGN_TOP = 0, + ALIGN_BOTTOM = 1, + ALIGN_HCENTER = 4, + ALIGN_VCENTER = 8, + ALIGN_VBASELINE = 32, // text only, possibly not yet working + + ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT, + ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT, + ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT, + ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT, +}; + +struct GLSLProgram; + +enum DrawBufferMode { + DBMODE_NORMAL = 0, + DBMODE_LINES = 1 +}; + +struct GradientStop +{ + float t; + uint32_t color; +}; + +// Similar to QuadBuffer but only uses a vertex array that it keeps +// around. +class DrawBuffer { + public: + DrawBuffer(); + ~DrawBuffer(); + + void Begin(DrawBufferMode mode = DBMODE_NORMAL); + void End(); // Currently does nothing, but call it! + + int Count() const { return count_; } + + void Flush(const GLSLProgram *program, bool set_blend_state=true); + void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); + void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom); + + void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops); + + void RectCenter(float x, float y, float w, float h, uint32 color) { + Rect(x - w/2, y - h/2, w, h, color); + } + void Rect(float x, float y, float w, float h, + float u, float v, float uw, float uh, uint32 color); + void V(float x, float y, float z, uint32 color, float u, float v); + void V(float x, float y, uint32 color, float u, float v) { + V(x, y, 0.0f, color, u, v); + } + + void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul); + + // New drawing APIs + + // Must call this before you use any functions with atlas_image etc. + void SetAtlas(const Atlas *_atlas) { + atlas = _atlas; + } + void MeasureImage(int atlas_image, float *w, float *h); + void DrawImage(int atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT); + void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); + void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); + // Results in 18 triangles. Kind of expensive for a button. + void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); + // This is only 6 triangles, much cheaper. + void DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); + + void MeasureText(int font, const char *text, float *w, float *h); + void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); + void DrawTextShadow(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); + + void RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color); + void SetFontScale(float xs, float ys) { + fontscalex = xs; + fontscaley = ys; + } + + // Utility to avoid having to include gl.h just for this in UI code. + void EnableBlend(bool enable); + + private: + void DoAlign(int align, float *x, float *y, float w, float h); + struct Vertex { + float x, y, z; + uint8 r, g, b, a; + float u, v; + }; + + Vertex *verts_; + int count_; + DrawBufferMode mode_; + const Atlas *atlas; + + float fontscalex; + float fontscaley; +}; + diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp new file mode 100644 index 0000000000..311abc3cd0 --- /dev/null +++ b/gfx_es2/fbo.cpp @@ -0,0 +1,90 @@ +#ifdef ANDROID +#include +#include +#else +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif + +#include "base/logging.h" +#include "gfx_es2/fbo.h" + +struct FBO { + GLuint handle; + GLuint color_texture; + GLuint z_stencil_buffer; + + int width; + int height; +}; + +FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { + FBO *fbo = new FBO(); + fbo->width = width; + fbo->height = height; + glGenFramebuffers(1, &fbo->handle); + glGenTextures(1, &fbo->color_texture); + glGenRenderbuffers(1, &fbo->z_stencil_buffer); + + // Create the surfaces. + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); + + // Bind it all together + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + switch(status) { + case GL_FRAMEBUFFER_COMPLETE_EXT: + ILOG("Framebuffer verified complete."); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + ELOG("Framebuffer format not supported"); + break; + default: + FLOG("Other framebuffer error: %i", status); + break; + } + // Unbind state we don't need + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + return fbo; +} + +void fbo_unbind() { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} + +void fbo_bind_as_render_target(FBO *fbo) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); +} + +void fbo_bind_for_read(FBO *fbo) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); +} + +void fbo_bind_color_as_texture(FBO *fbo, int color) { + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); +} + +void fbo_destroy(FBO *fbo) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &fbo->handle); + glDeleteTextures(1, &fbo->color_texture); + glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); +} diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h new file mode 100644 index 0000000000..648d255366 --- /dev/null +++ b/gfx_es2/fbo.h @@ -0,0 +1,20 @@ +#pragma once + +// Simple wrapper around FBO functionality. + +struct FBO; + +// Creates a simple FBO with a RGBA32 color buffer stored in a texture, and +// optionally an accompanying Z/stencil buffer. +// No mipmap support. +// num_color_textures must be 1 for now. +// you lose bound texture state. +FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil); + +// These functions should be self explanatory. +void fbo_bind_as_render_target(FBO *fbo); +// color must be 0, for now. +void fbo_bind_color_as_texture(FBO *fbo, int color); +void fbo_bind_for_read(FBO *fbo); +void fbo_unbind(); +void fbo_destroy(FBO *fbo); diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp new file mode 100644 index 0000000000..20b340f3bb --- /dev/null +++ b/gfx_es2/glsl_program.cpp @@ -0,0 +1,203 @@ +#if defined(ANDROID) +#include +#include +typedef char GLchar; +#else +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif + +#include + +#include +#include +#include + +#include "base/logging.h" +#include "file/vfs.h" +#include "gfx_es2/glsl_program.h" + +static std::set active_programs; + +bool CompileShader(const char *source, GLuint shader, const char *filename) { + glShaderSource(shader, 1, &source, NULL); + glCompileShader(shader); + GLint success; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) { +#define MAX_INFO_LOG_SIZE 2048 + GLchar infoLog[MAX_INFO_LOG_SIZE]; + GLsizei len; + glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog); + infoLog[len] = '\0'; + ELOG("Error in shader compilation of %s!\n", filename); + ELOG("Info log: %s\n", infoLog); + ELOG("Shader source:\n%s\n", (const char *)source); + exit(1); + return false; + } + return true; +} + +GLSLProgram *glsl_create(const char *vshader, const char *fshader) { + GLSLProgram *program = new GLSLProgram(); + program->program_ = 0; + program->vsh_ = 0; + program->fsh_ = 0; + strcpy(program->name, vshader + strlen(vshader) - 16); + strcpy(program->vshader_filename, vshader); + strcpy(program->fshader_filename, fshader); + if (glsl_recompile(program)) { + active_programs.insert(program); + } + register_gl_resource_holder(program); + return program; +} + +bool glsl_up_to_date(GLSLProgram *program) { + struct stat vs, fs; + stat(program->vshader_filename, &vs); + stat(program->fshader_filename, &fs); + if (vs.st_mtime != program->vshader_mtime || + fs.st_mtime != program->fshader_mtime) { + return false; + } else { + return true; + } +} + +void glsl_refresh() { + ILOG("glsl_refresh()"); + for (std::set::const_iterator iter = active_programs.begin(); + iter != active_programs.end(); ++iter) { + if (!glsl_up_to_date(*iter)) { + glsl_recompile(*iter); + } + } +} + +bool glsl_recompile(GLSLProgram *program) { + struct stat vs, fs; + stat(program->vshader_filename, &vs); + stat(program->fshader_filename, &fs); + program->vshader_mtime = vs.st_mtime; + program->fshader_mtime = fs.st_mtime; + + size_t sz; + char *vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz); + if (!vsh_src) { + ELOG("File missing: %s", vsh_src); + return false; + } + char *fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz); + if (!fsh_src) { + ELOG("File missing: %s", fsh_src); + delete [] vsh_src; + return false; + } + + GLuint vsh = glCreateShader(GL_VERTEX_SHADER); + const GLchar *vsh_str = (const GLchar *)(vsh_src); + if (!CompileShader(vsh_str, vsh, program->vshader_filename)) { + return false; + } + delete [] vsh_src; + + const GLchar *fsh_str = (const GLchar *)(fsh_src); + GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); + if (!CompileShader(fsh_str, fsh, program->fshader_filename)) { + glDeleteShader(vsh); + return false; + } + delete [] fsh_src; + + GLuint prog = glCreateProgram(); + glAttachShader(prog, vsh); + glAttachShader(prog, fsh); + + glLinkProgram(prog); + + GLint linkStatus; + glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) { + GLint bufLength = 0; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength); + if (bufLength) { + char* buf = new char[bufLength]; + glGetProgramInfoLog(prog, bufLength, NULL, buf); + FLOG("Could not link program:\n %s", buf); + delete [] buf; // we're dead! + } + glDeleteShader(vsh); + glDeleteShader(fsh); + return false; + } + + // Destroy the old program, if any. + if (program->program_) { + glDeleteProgram(program->program_); + } + + program->program_ = prog; + program->vsh_ = vsh; + program->fsh_ = vsh; + + program->sampler0 = glGetUniformLocation(program->program_, "sampler0"); + program->sampler1 = glGetUniformLocation(program->program_, "sampler1"); + + program->a_position = glGetAttribLocation(program->program_, "a_position"); + program->a_color = glGetAttribLocation(program->program_, "a_color"); + program->a_normal = glGetAttribLocation(program->program_, "a_normal"); + program->a_texcoord0 = glGetAttribLocation(program->program_, "a_texcoord0"); + program->a_texcoord1 = glGetAttribLocation(program->program_, "a_texcoord1"); + + program->u_worldviewproj = glGetUniformLocation(program->program_, "u_worldviewproj"); + program->u_world = glGetUniformLocation(program->program_, "u_world"); + program->u_viewproj = glGetUniformLocation(program->program_, "u_viewproj"); + program->u_fog = glGetUniformLocation(program->program_, "u_fog"); + program->u_sundir = glGetUniformLocation(program->program_, "u_sundir"); + program->u_camerapos = glGetUniformLocation(program->program_, "u_camerapos"); + + //ILOG("Shader compilation success: %s %s", + // program->vshader_filename, + // program->fshader_filename); + return true; +} + +void GLSLProgram::GLLost() { + ILOG("Restoring GLSL program %s/%s", this->vshader_filename, this->fshader_filename); + this->program_ = 0; + this->vsh_ = 0; + this->fsh_ = 0; + glsl_recompile(this); +} + + +int glsl_attrib_loc(const GLSLProgram *program, const char *name) { + return glGetAttribLocation(program->program_, name); +} + +int glsl_uniform_loc(const GLSLProgram *program, const char *name) { + return glGetUniformLocation(program->program_, name); +} + +void glsl_destroy(GLSLProgram *program) { + unregister_gl_resource_holder(program); + glDeleteShader(program->vsh_); + glDeleteShader(program->fsh_); + glDeleteProgram(program->program_); + active_programs.erase(program); + delete program; +} + +void glsl_bind(const GLSLProgram *program) { + glUseProgram(program->program_); +} + +void glsl_unbind() { + glUseProgram(0); +} diff --git a/gfx_es2/glsl_program.h b/gfx_es2/glsl_program.h new file mode 100644 index 0000000000..55d3531d2e --- /dev/null +++ b/gfx_es2/glsl_program.h @@ -0,0 +1,72 @@ +#ifndef _RENDER_UTIL +#define _RENDER_UTIL + +#ifdef ANDROID +#include +#include +#else +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif + +#include + +#include "gfx/gl_lost_manager.h" + +// Represent a compiled and linked vshader/fshader pair. +// A just-constructed object is valid but cannot be used as a shader program, meaning that +// yes, you can declare these as globals if you like. +struct GLSLProgram : public GfxResourceHolder { + char name[16]; + char vshader_filename[256]; + char fshader_filename[256]; + time_t vshader_mtime; + time_t fshader_mtime; + + // Locations to some common uniforms. Hardcoded for speed. + GLint sampler0; + GLint sampler1; + GLint u_worldviewproj; + GLint u_world; + GLint u_viewproj; + GLint u_fog; // rgb = color, a = density + GLint u_sundir; + GLint u_camerapos; + + GLint a_position; + GLint a_color; + GLint a_normal; + GLint a_texcoord0; + GLint a_texcoord1; + + // Private to the implementation, do not touch + GLuint vsh_; + GLuint fsh_; + GLuint program_; + + void GLLost(); +}; + +GLSLProgram *glsl_create(const char *vshader_file, const char *fshader_file); +void glsl_destroy(GLSLProgram *program); + +// If recompilation of the program fails, the program is untouched and error messages +// are logged and the function returns false. +bool glsl_recompile(GLSLProgram *program); +void glsl_bind(const GLSLProgram *program); +void glsl_unbind(); +int glsl_attrib_loc(const GLSLProgram *program, const char *name); +int glsl_uniform_loc(const GLSLProgram *program, const char *name); + +// Expensive, try to only call this once per second or so and only when developing. +// fstat-s all the source files of all the shaders to see if they +// should be recompiled, and recompiles them if so. +void glsl_refresh(); + +// Use glUseProgramObjectARB(NULL); to unset. + +#endif // _RENDER_UTIL diff --git a/gfx_es2/vertex_format.cpp b/gfx_es2/vertex_format.cpp new file mode 100644 index 0000000000..335029437d --- /dev/null +++ b/gfx_es2/vertex_format.cpp @@ -0,0 +1,71 @@ +#include "base/logging.h" +#include "gfx_es2/glsl_program.h" +#include "gfx_es2/vertex_format.h" + +static const GLuint formatLookup[16] = { + GL_FLOAT, + 0, //GL_HALF_FLOAT_EXT, + GL_UNSIGNED_SHORT, + GL_UNSIGNED_BYTE, + 0, //GL_UNSIGNED_INT_10_10_10_2, + 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +void SetVertexFormat(const GLSLProgram *program, uint32_t vertexFormat) { + // First special case our favorites + if (vertexFormat == (POS_FLOAT | NRM_FLOAT | UV0_FLOAT)) { + const int vertexSize = 3*4 + 3*4 + 2*4; + glUniform1i(program->sampler0, 0); + glEnableVertexAttribArray(program->a_position); + glEnableVertexAttribArray(program->a_normal); + glEnableVertexAttribArray(program->a_texcoord0); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0); + glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12); + glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); + return; + } + + // Then have generic code here. + + + int vertexSize = 0; + + FLOG("TODO: Write generic code."); + + if (vertexFormat & UV0_MASK) { + glUniform1i(program->sampler0, 0); + } + + glEnableVertexAttribArray(program->a_position); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0); + if (vertexFormat & NRM_MASK) { + glEnableVertexAttribArray(program->a_normal); + glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12); + } + if (vertexFormat & UV0_MASK) { + glEnableVertexAttribArray(program->a_texcoord0); + glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); + } + if (vertexFormat & UV1_MASK) { + glEnableVertexAttribArray(program->a_texcoord1); + glVertexAttribPointer(program->a_texcoord1, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); + } + if (vertexFormat & RGBA_MASK) { + glEnableVertexAttribArray(program->a_color); + glVertexAttribPointer(program->a_color, 4, GL_FLOAT, GL_FALSE, vertexSize, (void *)28); + } +} + +// TODO: Save state so that we can get rid of this. +void UnsetVertexFormat(const GLSLProgram *program, uint32 vertexFormat) { + glDisableVertexAttribArray(program->a_position); + if (vertexFormat & NRM_MASK) + glDisableVertexAttribArray(program->a_normal); + if (vertexFormat & UV0_MASK) + glDisableVertexAttribArray(program->a_texcoord0); + if (vertexFormat & UV1_MASK) + glDisableVertexAttribArray(program->a_texcoord1); + if (vertexFormat & RGBA_MASK) + glDisableVertexAttribArray(program->a_color); +} diff --git a/gfx_es2/vertex_format.h b/gfx_es2/vertex_format.h new file mode 100644 index 0000000000..d4c844c0ba --- /dev/null +++ b/gfx_es2/vertex_format.h @@ -0,0 +1,49 @@ +#pragma once + +#include "base/basictypes.h" + +// Vertex format flags +enum VtxFmt { + POS_FLOAT = 1, + POS_FLOAT16 = 2, + POS_UINT16 = 3, + POS_UINT8 = 4, + POS_101010 = 5, + + NRM_FLOAT = 1 << 4, + NRM_FLOAT16 = 2 << 4, + NRM_SINT16 = 3 << 4, + NRM_UINT8 = 4 << 4, + NRM_101010 = 5 << 4, + + TANGENT_FLOAT = 1 << 8, + //.... + + UV0_NONE = 1 << 12, + UV0_FLOAT = 1 << 12, + // .... + UV1_NONE = 1 << 16, + UV1_FLOAT = 1 << 16, + + RGBA_NONE = 0 << 20, + RGBA_FLOAT = 1 << 20, + RGBA_FLOAT16 = 2 << 20, + RGBA_UINT16 = 3 << 20, + RGBA_UINT8 = 4 << 20, + RGBA_101010 = 5 << 20, + + POS_MASK = 0x0000000F, + NRM_MASK = 0x000000F0, + TANGENT_MASK = 0x00000F00, + UV0_MASK = 0x0000F000, + UV1_MASK = 0x000F0000, + RGBA_MASK = 0x00F00000, + + // Can add more here, such as a generic AUX or something. Don't know what to use it for though. Hardness for cloth sim? +}; + +struct GLSLProgram; + +// When calling this, the relevant vertex buffer must be bound to GL_ARRAY_BUFFER. +void SetVertexFormat(const GLSLProgram *program, uint32_t format); +void UnsetVertexFormat(const GLSLProgram *program, uint32_t format); diff --git a/image/CMakeLists.txt b/image/CMakeLists.txt new file mode 100644 index 0000000000..c835ef7134 --- /dev/null +++ b/image/CMakeLists.txt @@ -0,0 +1,14 @@ +set(SRCS + png_load.cpp + zim_load.cpp + zim_save.cpp +) + +set(SRCS ${SRCS}) + +add_library(image STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) + diff --git a/image/build.scons b/image/build.scons new file mode 100644 index 0000000000..edc7163ec3 --- /dev/null +++ b/image/build.scons @@ -0,0 +1,15 @@ +# Bring in the environment to use for this component (boilerplate). +Import('env') + +# This is the list of input source files to the mandelbrot_gen library. Headers +# will be detected automatically. +inputs = ['png_load.cpp', + 'zim_load.cpp', + ] + +# Build these into a library. +env.ComponentLibrary('image', inputs) + +env.Append(LIBS = [ 'base', 'png', 'image', 'z', 'glog' ]) +inputs = ['zimagetool.cpp'] +env.ComponentProgram('zimagetool', inputs) diff --git a/image/png_load.cpp b/image/png_load.cpp new file mode 100644 index 0000000000..8be085d624 --- /dev/null +++ b/image/png_load.cpp @@ -0,0 +1,91 @@ +#include +#include +#include + +int pngLoad(const char *file, int *pwidth, + int *pheight, unsigned char **image_data_ptr, + bool flip) { + FILE *infile = fopen(file, "rb"); + if (!infile) { + printf("No such file: %s\n", file); + return 0; + } + /* Check for the 8-byte signature */ + char sig[8]; /* PNG signature array */ + int len = fread(sig, 1, 8, infile); + if (len != 8 || !png_check_sig((unsigned char *) sig, 8)) { + fclose(infile); + return 0; + } + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fclose(infile); + return 4; /* out of memory */ + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + fclose(infile); + return 4; /* out of memory */ + } + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(infile); + return 0; + } + + png_init_io(png_ptr, infile); + png_set_sig_bytes(png_ptr, 8); // we already checked the sig bytes + png_read_info(png_ptr, info_ptr); + int bit_depth=0; + int color_type=0; + png_uint_32 width=0, height=0; + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + *pwidth = (int)width; + *pheight = (int)height; + // Set up some transforms. Always load RGBA. + if (color_type & PNG_COLOR_MASK_ALPHA) { + // png_set_strip_alpha(png_ptr); + } + if (bit_depth > 8) { + png_set_strip_16(png_ptr); + } + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + } + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + } + if (color_type == PNG_COLOR_TYPE_RGB) { + png_set_filler(png_ptr, 255, PNG_FILLER_AFTER); + } + + // Update the png info struct. + png_read_update_info(png_ptr, info_ptr); + unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr); + unsigned char *image_data = NULL; /* raw png image data */ + if ((image_data = (unsigned char *) malloc(rowbytes * height))==NULL) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return 4; + } + png_bytepp row_pointers = NULL; + if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + free(image_data); + image_data = NULL; + return 4; + } + if (flip) { + for (unsigned long i = 0; i < height; ++i) + row_pointers[height - 1 - i] = (png_byte *)(image_data + i*rowbytes); + } else { + for (unsigned long i = 0; i < height; ++i) + row_pointers[i] = (png_byte *)(image_data + i*rowbytes); + } + png_read_image(png_ptr, row_pointers); + free(row_pointers); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(infile); + *image_data_ptr = image_data; + return 1; +} diff --git a/image/png_load.h b/image/png_load.h new file mode 100644 index 0000000000..5a4ee08c54 --- /dev/null +++ b/image/png_load.h @@ -0,0 +1,11 @@ +#ifndef _PNG_LOAD_H +#define _PNG_LOAD_H + +// *image_data_ptr should be deleted with free() +// return value of 1 == success. +int pngLoad(const char *file, int *pwidth, + int *pheight, unsigned char **image_data_ptr, bool flip); + + + +#endif // _PNG_LOAD_H diff --git a/image/surface.h b/image/surface.h new file mode 100644 index 0000000000..39377b3864 --- /dev/null +++ b/image/surface.h @@ -0,0 +1,31 @@ +#ifndef _GFX_SURFACE +#define _GFX_SURFACE + +enum SurfaceFormats { + SURF_ARGB, + SURF_YUV, +}; + +struct cairo_surface_t; + +class Surface { + public: + Surface(int width, int height); + + // In case of YUV, U and V channels have half size, rounded UP. + int height() const { return height_; } + int width() const { return width_; } + int pitch() const { return pitch_; } + + int half_width() const { return (width_ + 1) >> 1; } + int half_height() const { return (height_ + 1) >> 1; } + + cairo_surface_t *CreateCairoSurface(); + private: + uint8 *data_; + int width_; + int height_; + int pitch_; +}; + +#endif diff --git a/image/zim_load.cpp b/image/zim_load.cpp new file mode 100644 index 0000000000..1cc2c406bf --- /dev/null +++ b/image/zim_load.cpp @@ -0,0 +1,139 @@ +#include +#include +#include + +#include "base/logging.h" +#include "zlib.h" +#include "image/zim_load.h" +#include "file/vfs.h" + +int ezuncompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) { + z_stream stream; + stream.next_in = (Bytef*)pSrc; + stream.avail_in = (uInt)nSrcLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != (uLong)nSrcLen) return Z_BUF_ERROR; + + uInt destlen = (uInt)*pnDestLen; + if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + int err = inflateInit(&stream); + if (err != Z_OK) return err; + + int nExtraChunks = 0; + do { + stream.next_out = pDest; + stream.avail_out = destlen; + err = inflate(&stream, Z_FINISH); + if (err == Z_STREAM_END ) + break; + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + err = Z_DATA_ERROR; + if (err != Z_BUF_ERROR) { + inflateEnd(&stream); + return err; + } + nExtraChunks += 1; + } while (stream.avail_out == 0); + + *pnDestLen = stream.total_out; + + err = inflateEnd(&stream); + if (err != Z_OK) return err; + + return nExtraChunks ? Z_BUF_ERROR : Z_OK; +} + +static const char magic[5] = "ZIMG"; + +static unsigned int log2i(unsigned int val) { + unsigned int ret = -1; + while (val != 0) { + val >>= 1; ret++; + } + return ret; +} + +int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, uint8 **image) { + if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') { + ELOG("Not a ZIM file"); + return 0; + } + memcpy(width, zim + 4, 4); + memcpy(height, zim + 8, 4); + memcpy(flags, zim + 12, 4); + + int num_levels = 1; + int image_data_size[ZIM_MAX_MIP_LEVELS]; + if (*flags & ZIM_HAS_MIPS) { + num_levels = log2i(*width < *height ? *width : *height) + 1; + } + int total_data_size = 0; + for (int i = 0; i < num_levels; i++) { + if (i > 0) { + width[i] = width[i-1] / 2; + height[i] = height[i-1] / 2; + } + switch (*flags & ZIM_FORMAT_MASK) { + case ZIM_RGBA8888: + image_data_size[i] = width[i] * height[i] * 4; + break; + case ZIM_RGBA4444: + case ZIM_RGB565: + image_data_size[i] = width[i] * height[i] * 2; + break; + case ZIM_ETC1: + { + int data_width = width[i]; + int data_height = height[i]; + if (data_width < 4) data_width = 4; + if (data_height < 4) data_height = 4; + image_data_size[i] = data_width * data_height / 2; + break; + } + default: + ELOG("Invalid ZIM format %i", *flags & ZIM_FORMAT_MASK); + return 0; + } + total_data_size += image_data_size[i]; + } + + image[0] = (uint8 *)malloc(total_data_size); + for (int i = 1; i < num_levels; i++) { + image[i] = image[i-1] + image_data_size[i-1]; + } + + if (*flags & ZIM_ZLIB_COMPRESSED) { + long outlen = total_data_size; + if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), datasize - 16)) { + free(*image); + *image = 0; + return 0; + } + if (outlen != total_data_size) { + ELOG("Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size); + } + } else { + memcpy(*image, zim + 16, datasize - 16); + if (datasize - 16 != total_data_size) { + ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size); + } + } + return num_levels; +} + +int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t **image) { + size_t size; + uint8_t *buffer = VFSReadFile(filename, &size); + if (!buffer) { + return 0; + } + int retval = LoadZIMPtr(buffer, size, width, height, format, image); + if (!retval) { + ELOG("Not a valid ZIM file: %s", filename); + } + delete [] buffer; + return retval; +} diff --git a/image/zim_load.h b/image/zim_load.h new file mode 100644 index 0000000000..b76fdc2ee3 --- /dev/null +++ b/image/zim_load.h @@ -0,0 +1,47 @@ +#pragma once + +#include "base/basictypes.h" + +// LoadZIM's responsibility: +// * Parse the ZIM format +// * Extract all mip levels so they can be uploaded to GPU +// +// * NOT convert formats to anything, except converting ETC1 to RGBA8888 when running on the PC + +// ZIM format: +// 4 byte ZIMG +// 4 byte width +// 4 byte height +// 4 byte flags +// The rest is zlibbed data. If multiple mips, they are zlibbed separately. + +// Defined flags: + +enum { + ZIM_RGBA8888 = 0, // Assumed format if no other format is set + ZIM_RGBA4444 = 1, // GL_UNSIGNED_SHORT_4_4_4_4 + ZIM_RGB565 = 2, // GL_UNSIGNED_SHORT_5_6_5 + ZIM_ETC1 = 3, + ZIM_RGB888 = 4, + ZIM_LUMINANCE_ALPHA = 5, + ZIM_LUMINANCE = 6, + ZIM_ALPHA = 7, + // There's space for plenty more formats. + ZIM_FORMAT_MASK = 15, + ZIM_HAS_MIPS = 16, // If set, assumes that a full mip chain is present. Mips are zlib-compressed individually and stored in sequence. Always half sized. + ZIM_GEN_MIPS = 32, // If set, the caller is advised to automatically generate mips. (maybe later, the ZIM lib will generate the mips for you). + ZIM_DITHER = 64, // If set, dithers during save if color reduction is necessary. + ZIM_CLAMP = 128, // Texture should default to clamp instead of wrap. + ZIM_ZLIB_COMPRESSED = 256, +}; + +// ZIM will only ever support up to 12 levels (4096x4096 max). +enum { + ZIM_MAX_MIP_LEVELS = 12, +}; + +// Delete the returned pointer using free() +// Watch out! If the image has mipmaps, multiple values will be written +// to width, height, and image, as if they were arrays, up to 12 (max texture size is 4096 which is 2^12). +int LoadZIM(const char *filename, int *width, int *height, int *flags, uint8_t **image); +int LoadZIMPtr(char *zim, int datasize, int *width, int *height, int *flags, uint8_t **image); diff --git a/image/zim_save.cpp b/image/zim_save.cpp new file mode 100644 index 0000000000..91305eed02 --- /dev/null +++ b/image/zim_save.cpp @@ -0,0 +1,247 @@ +#include +#include +#include "base/logging.h" +#include "ext/etcpack/etcpack.h" +#include "image/zim_save.h" +#include "zlib.h" + +static const char magic[5] = "ZIMG"; + +/*int num_levels = 1; + if (flags & ZIM_HAS_MIPS) { + num_levels = log2i(width > height ? width : height); + }*/ +static unsigned int log2i(unsigned int val) { + unsigned int ret = -1; + while (val != 0) { + val >>= 1; ret++; + } + return ret; +} + + +int ezcompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) { + z_stream stream; + int err; + + int nExtraChunks; + uInt destlen; + + stream.next_in = (Bytef*)pSrc; + stream.avail_in = (uInt)nSrcLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != nSrcLen) return Z_BUF_ERROR; +#endif + destlen = (uInt)*pnDestLen; + if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, Z_DEFAULT_COMPRESSION); + if (err != Z_OK) return err; + nExtraChunks = 0; + do { + stream.next_out = pDest; + stream.avail_out = destlen; + err = deflate(&stream, Z_FINISH); + if (err == Z_STREAM_END ) + break; + if (err != Z_OK) { + deflateEnd(&stream); + return err; + } + nExtraChunks += 1; + } while (stream.avail_out == 0); + + *pnDestLen = stream.total_out; + + err = deflateEnd(&stream); + if (err != Z_OK) return err; + + return nExtraChunks ? Z_BUF_ERROR : Z_OK; +} + +inline int clamp16(int x) { if (x < 0) return 0; if (x > 15) return 15; return x; } +inline int clamp32(int x) { if (x < 0) return 0; if (x > 31) return 31; return x; } +inline int clamp64(int x) { if (x < 0) return 0; if (x > 63) return 63; return x; } + + +bool ispowerof2 (int x) { + if (!x || (x&(x-1))) + return false; + else + return true; +} + + + +void Convert(const uint8_t *image_data, int width, int height, int pitch, int flags, + uint8_t **data, int *data_size) { + // For 4444 and 565. Ordered dither matrix. looks really surprisingly good on cell phone screens at 4444. + int dith[16] = { + 1, 9, 3, 11, + 13, 5, 15, 7, + 4, 12, 2, 10, + 16, 8, 14, 6 + }; + if ((flags & ZIM_DITHER) == 0) { + for (int i = 0; i < 16; i++) { dith[i] = 8; } + } + switch (flags & ZIM_FORMAT_MASK) { + case ZIM_RGBA8888: + { + *data_size = width * height * 4; + *data = new uint8_t[width * height * 4]; + for (int y = 0; y < height; y++) { + memcpy((*data) + y * width * 4, image_data + y * pitch, width * 4); + } + break; + } + case ZIM_ETC1: { + // Check for power of 2 + if (!ispowerof2(width) || !ispowerof2(height)) { + FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height); + } + // Convert RGBX to ETC1 before saving. + int blockw = width/4; + int blockh = height/4; + *data_size = blockw * blockh * 8; + *data = new uint8_t[*data_size]; +#pragma omp parallel for + for (int y = 0; y < blockh; y++) { + for (int x = 0; x < blockw; x++) { + CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width, + (*data) + (blockw * y + x) * 8, 1); + } + } + width = blockw * 4; + height = blockh * 4; + break; + } + case ZIM_RGBA4444: + { + *data_size = width * height * 2; + *data = new uint8_t[*data_size]; + uint16_t *dst = (uint16_t *)(*data); + int i = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int dithval = dith[(x&3)+((y&0x3)<<2)] - 8; + int r = clamp16((image_data[i * 4] + dithval) >> 4); + int g = clamp16((image_data[i * 4 + 1] + dithval) >> 4); + int b = clamp16((image_data[i * 4 + 2] + dithval) >> 4); + int a = clamp16((image_data[i * 4 + 3] + dithval) >> 4); // really dither alpha? + // Note: GL_UNSIGNED_SHORT_4_4_4_4, not GL_UNSIGNED_SHORT_4_4_4_4_REV + *dst++ = (r << 12) | (g << 8) | (b << 4) | (a << 0); + i++; + } + } + break; + } + case ZIM_RGB565: + { + *data_size = width * height * 2; + *data = new uint8_t[*data_size]; + uint16_t *dst = (uint16_t *)(*data); + int i = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int dithval = dith[(x&3)+((y&0x3)<<2)] - 8; + dithval = 0; + int r = clamp32((image_data[i * 4] + dithval/2) >> 3); + int g = clamp64((image_data[i * 4 + 1] + dithval/4) >> 2); + int b = clamp32((image_data[i * 4 + 2] + dithval/2) >> 3); + // Note: GL_UNSIGNED_SHORT_5_6_5, not GL_UNSIGNED_SHORT_5_6_5_REV + *dst++ = (r << 11) | (g << 5) | (b); + i++; + } + } + } + break; + + default: + ELOG("Unhandled ZIM format %i", flags & ZIM_FORMAT_MASK); + *data = 0; + *data_size = 0; + return; + } +} + +// Deletes the old buffer. +uint8_t *DownsampleBy2(const uint8_t *image, int width, int height, int pitch) { + uint8_t *out = new uint8_t[(width/2) * (height/2) * 4]; + + int degamma[256]; + int gamma[32768]; + for (int i =0; i < 256; i++) { + degamma[i] = powf((float)i / 255.0f, 1.0f/2.2f) * 8191.0f; + } + for (int i = 0; i < 32768; i++) { + gamma[i] = powf((float)i / 32764.0f, 2.2f) * 255.0f; + } + + // Let's start with something really stupid. + for (int y = 0; y < height; y+=2) { + for (int x = 0; x < width; x+=2) { + const uint8_t *tl = image + pitch * y + x*4; + const uint8_t *tr = tl + 4; + const uint8_t *bl = tl + pitch; + const uint8_t *br = bl + 4; + uint8_t *d = out + ((y/2) * ((width/2)) + x / 2) * 4; + for (int c = 0; c < 4; c++) { + d[c] = gamma[degamma[tl[c]] + degamma[tr[c]] + degamma[bl[c]] + degamma[br[c]]]; + } + } + } + return out; +} + +void SaveZIM(const char *filename, int width, int height, int pitch, int flags, const uint8_t *image_data) { + FILE *f = fopen(filename, "wb"); + fwrite(magic, 1, 4, f); + fwrite(&width, 1, 4, f); + fwrite(&height, 1, 4, f); + fwrite(&flags, 1, 4, f); + + int num_levels = 1; + if (flags & ZIM_HAS_MIPS) { + num_levels = log2i(width > height ? height : width) + 1; + } + for (int i = 0; i < num_levels; i++) { + uint8_t *data = 0; + int data_size; + Convert(image_data, width, height, pitch, flags, &data, &data_size); + if (flags & ZIM_ZLIB_COMPRESSED) { + long dest_len = data_size * 2; + uint8_t *dest = new uint8_t[dest_len]; + if (Z_OK == ezcompress(dest, &dest_len, data, data_size)) { + fwrite(dest, 1, dest_len, f); + } else { + ELOG("Zlib compression failed.\n"); + } + delete [] dest; + } else { + fwrite(data, 1, data_size, f); + } + delete [] data; + + if (i != num_levels - 1) { + uint8_t *smaller = DownsampleBy2(image_data, width, height, pitch); + if (i != 0) { + delete [] image_data; + } + image_data = smaller; + width /= 2; + height /= 2; + if ((flags & ZIM_FORMAT_MASK) == ZIM_ETC1) { + if (width < 4) width = 4; + if (height < 4) height = 4; + } + pitch = width * 4; + } + } + delete [] image_data; + fclose(f); +} diff --git a/image/zim_save.h b/image/zim_save.h new file mode 100644 index 0000000000..5b79b85149 --- /dev/null +++ b/image/zim_save.h @@ -0,0 +1,11 @@ +#pragma once + +#include "base/basictypes.h" +#include "image/zim_load.h" + +// SaveZIM's responsibility: +// * Write the ZIM format +// * Generate mipmaps if requested +// * Convert images to the requested format +// Input image is always 8888 RGBA. SaveZIM takes care of downsampling and mipmap generation. +void SaveZIM(const char *filename, int width, int height, int pitch, int format, const uint8_t *image); diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp new file mode 100644 index 0000000000..44c92b614d --- /dev/null +++ b/input/gesture_detector.cpp @@ -0,0 +1,68 @@ +// Unfinished. +// TODO: +// Zoom gesture a la http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-6-implementing-the-pinch-zoom-gesture/1847 + +#include "input/gesture_detector.h" + +namespace GestureDetector { + +struct Finger { + bool down; + float X; + float Y; + float lastX; + float lastY; + float downX; + float downY; + float deltaX; + float deltaY; + float smoothDeltaX; + float smoothDeltaY; +}; + +// State +#define MAX_FINGERS 4 + +static Finger fingers[MAX_FINGERS]; + +void update(const InputState &state) { + // Mouse / 1-finger-touch control. + if (state.mouse_buttons_down & 1) { + fingers[0].down = true; + fingers[0].downX = state.mouse_x; + fingers[0].downY = state.mouse_y; + } else { + fingers[0].down = false; + } + + fingers[0].lastX = fingers[0].X; + fingers[0].lastY = fingers[0].Y; + + // TODO: real multitouch +} + +bool down(int i, float *xdelta, float *ydelta) { + if (!fingers[i].down) { + return false; + } + *xdelta = fingers[i].downX; + *ydelta = fingers[i].downY; +} + +bool dragDistance(int i, float *xdelta, float *ydelta) { + if (!fingers[i].down) + return false; + + *xdelta = fingers[i].X - fingers[i].downX; + *ydelta = fingers[i].Y - fingers[i].downY; +} + +bool dragDelta(int i, float *xdelta, float *ydelta) { + if (!fingers[i].down) + return false; + + *xdelta = fingers[i].X - fingers[i].lastX; + *ydelta = fingers[i].Y - fingers[i].lastY; +} + +} \ No newline at end of file diff --git a/input/gesture_detector.h b/input/gesture_detector.h new file mode 100644 index 0000000000..d34bbc9159 --- /dev/null +++ b/input/gesture_detector.h @@ -0,0 +1,20 @@ +#include "input/input_state.h" + +// Mainly for detecting (multi-)touch gestures but also useable for left button mouse dragging etc. + +namespace GestureDetector +{ + void update(const InputState &state); + + bool down(int finger, float *xdown, float *ydown); + + // x/ydelta is difference from current location to the start of the drag. + // Returns true if button/finger is down, for convenience. + bool dragDistance(int finger, float *xdelta, float *ydelta); + + // x/ydelta is (smoothed?) difference from current location to the position from the last frame. + // Returns true if button/finger is down, for convenience. + bool dragDelta(int finger, float *xdelta, float *ydelta); + + +}; \ No newline at end of file diff --git a/input/input_state.h b/input/input_state.h new file mode 100644 index 0000000000..d663d52dbd --- /dev/null +++ b/input/input_state.h @@ -0,0 +1,53 @@ +#pragma once + +#include "math/lin/vec3.h" + +enum { + PAD_BUTTON_A = 1, + PAD_BUTTON_B = 2, + PAD_BUTTON_X = 4, + PAD_BUTTON_Y = 8, + PAD_BUTTON_LBUMPER = 16, + PAD_BUTTON_RBUMPER = 32, + PAD_BUTTON_START = 64, + PAD_BUTTON_BACK = 128, + PAD_BUTTON_UP = 256, + PAD_BUTTON_DOWN = 512, + PAD_BUTTON_LEFT = 1024, + PAD_BUTTON_RIGHT = 2048, +}; + +// Agglomeration of all possible inputs, and automatically computed +// deltas where applicable. +struct InputState { + // Gamepad style input + int pad_buttons; // bitfield + int pad_last_buttons; + int pad_buttons_down; // buttons just pressed this frame + int pad_buttons_up; // buttons just pressed last frame + float pad_lstick_x; + float pad_lstick_y; + float pad_rstick_x; + float pad_rstick_y; + float pad_ltrigger; + float pad_rtrigger; + + // Mouse/singletouch style input + volatile bool mouse_valid; + int mouse_x; + int mouse_y; + int mouse_buttons; + int mouse_buttons_down; + int mouse_buttons_up; + int mouse_last_buttons; + + // Accelerometer + bool accelerometer_valid; + Vec3 acc; +}; + +inline void UpdateInputState(InputState *input) { + input->pad_buttons_down = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_buttons; + input->pad_buttons_up = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_last_buttons; + input->pad_last_buttons = input->pad_buttons; +} diff --git a/json/CMakeLists.txt b/json/CMakeLists.txt new file mode 100644 index 0000000000..9c3ec2f57f --- /dev/null +++ b/json/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SRCS + json_writer.cpp) + +set(SRCS ${SRCS}) + +add_library(jsonwriter STATIC ${SRCS}) + + + +add_executable(json_writer_test json_writer_test.cpp) +target_link_libraries(json_writer_test jsonwriter) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/json/json_writer.cpp b/json/json_writer.cpp new file mode 100644 index 0000000000..d626feb92d --- /dev/null +++ b/json/json_writer.cpp @@ -0,0 +1,116 @@ +#include "json/json_writer.h" + +JsonWriter::JsonWriter() { +} + +JsonWriter::~JsonWriter() { + +} + +void JsonWriter::begin() { + str_ << "{"; + stack_.push_back(StackEntry(DICT)); +} + +void JsonWriter::end() { + pop(); + str_ << "\n"; +} + +const char *JsonWriter::indent(int n) const { + static const char * const whitespace = " "; + return whitespace + (32 - n); +} + +const char *JsonWriter::indent() const { + int amount = (int)stack_.size() + 1; + amount *= 2; // 2-space indent. + return indent(amount); +} + +const char *JsonWriter::arrayIndent() const { + int amount = (int)stack_.size() + 1; + amount *= 2; // 2-space indent. + return stack_.back().first ? indent(amount) : ""; +} + +const char *JsonWriter::comma() const { + if (stack_.back().first) { + return ""; + } else { + return ","; + } +} + +const char *JsonWriter::arrayComma() const { + if (stack_.back().first) { + return "\n"; + } else { + return ", "; + } +} + +void JsonWriter::pushDict(const char *name) { + str_ << comma() << "\n" << indent() << "\"" << name << "\": {"; + stack_.push_back(StackEntry(DICT)); +} + +void JsonWriter::pushArray(const char *name) { + str_ << comma() << "\n" << indent() << "\"" << name << "\": ["; + stack_.push_back(StackEntry(ARRAY)); +} + +void JsonWriter::writeBool(bool value) { + str_ << arrayComma() << arrayIndent() << (value ? "true" : "false"); + stack_.back().first = false; +} + +void JsonWriter::writeBool(const char *name, bool value) { + str_ << comma() << "\n" << indent() << "\"" << name << "\": " << (value ? "true" : "false"); + stack_.back().first = false; +} + +void JsonWriter::writeInt(int value) { + str_ << arrayComma() << arrayIndent() << value; + stack_.back().first = false; +} + +void JsonWriter::writeInt(const char *name, int value) { + str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value; + stack_.back().first = false; +} + +void JsonWriter::writeFloat(double value) { + str_ << arrayComma() << arrayIndent() << value; + stack_.back().first = false; +} + +void JsonWriter::writeFloat(const char *name, double value) { + str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value; + stack_.back().first = false; +} + +void JsonWriter::writeString(const char *value) { + str_ << arrayComma() << arrayIndent() << "\"" << value << "\""; + stack_.back().first = false; +} + +void JsonWriter::writeString(const char *name, const char *value) { + str_ << comma() << "\n" << indent() << "\"" << name << "\": \"" << value << "\""; + stack_.back().first = false; +} + +void JsonWriter::pop() { + BlockType type = stack_.back().type; + stack_.pop_back(); + switch (type) { + case ARRAY: + str_ << "\n" << indent() << "]"; + break; + case DICT: + str_ << "\n" << indent() << "}"; + break; + } + if (stack_.size() > 0) + stack_.back().first = false; +} diff --git a/json/json_writer.h b/json/json_writer.h new file mode 100644 index 0000000000..5c714c15d4 --- /dev/null +++ b/json/json_writer.h @@ -0,0 +1,55 @@ +// Minimal-state ultra-minimal JSON writer. Consumes almost no memory +// apart from the string being built-up, which could easily be replaced +// with a file stream (although I've chosen not to do that just yet). +// +// Zero dependencies apart from stdlib. +// Public domain. + +#include +#include +#include + +#include "base/basictypes.h" + +class JsonWriter { + public: + JsonWriter(); + ~JsonWriter(); + void begin(); + void end(); + void pushDict(const char *name); + void pushArray(const char *name); + void writeBool(bool value); + void writeBool(const char *name, bool value); + void writeInt(int value); + void writeInt(const char *name, int value); + void writeFloat(double value); + void writeFloat(const char *name, double value); + void writeString(const char *value); + void writeString(const char *name, const char *value); + void pop(); + + std::string str() const { + return str_.str(); + } + + private: + const char *indent(int n) const; + const char *comma() const; + const char *arrayComma() const; + const char *indent() const; + const char *arrayIndent() const; + enum BlockType { + ARRAY, + DICT, + }; + struct StackEntry { + StackEntry(BlockType t) : type(t), first(true) {} + BlockType type; + bool first; + }; + std::vector stack_; + std::ostringstream str_; + + DISALLOW_COPY_AND_ASSIGN(JsonWriter); +}; diff --git a/json/json_writer_test.cpp b/json/json_writer_test.cpp new file mode 100644 index 0000000000..46875ac12b --- /dev/null +++ b/json/json_writer_test.cpp @@ -0,0 +1,25 @@ +#include "json/json_writer.h" +#include + +int main() { + JsonWriter j; + j.begin(); + j.pushDict("settings"); + j.writeInt("volume", 50); + j.writeInt("sound", 60); + j.pop(); + j.pushDict("user"); + j.writeFloat("level", 1.5); + j.writeString("name", "hello"); + j.pop(); + j.writeInt("outer", 3); + j.pushArray("ints"); + j.writeInt(3); + j.writeInt(4); + j.writeInt(6); + j.pop(); + j.writeString("yo!", "yo"); + j.end(); + std::cout << j.str(); + return 0; +} diff --git a/math/CMakeLists.txt b/math/CMakeLists.txt new file mode 100644 index 0000000000..b05acac409 --- /dev/null +++ b/math/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SRCS + lin/matrix4x4.cpp + lin/vec3.cpp + lin/quat.cpp + ) + +set(SRCS ${SRCS}) + +add_library(lin STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/math/build.scons b/math/build.scons new file mode 100644 index 0000000000..17d6c4ff4c --- /dev/null +++ b/math/build.scons @@ -0,0 +1,8 @@ +Import('env') + +inputs = [ + 'math_util.cc', +] + +env.Append(LIBS = ['gflags', 'glog', ]) +env.ComponentLibrary('math_util', inputs, COMPONENT_STATIC=True) diff --git a/math/compression.h b/math/compression.h new file mode 100644 index 0000000000..8200e52ea9 --- /dev/null +++ b/math/compression.h @@ -0,0 +1,21 @@ +#pragma once + +// WARNING : Do not use these with floating point data, especially not float16... + +template +inline void delta(T *data, int length) { + T prev = data[0]; + for (int i = 1; i < length; i++) { + T temp = data[i] - prev; + prev = data[i]; + data[i] = temp; + } +} + +template +inline void dedelta(T *data, int length) { + for (int i = 1; i < length; i++) { + data[i] += data[i - 1]; + } +} + diff --git a/math/lin/aabb.cpp b/math/lin/aabb.cpp new file mode 100644 index 0000000000..4e73b512a0 --- /dev/null +++ b/math/lin/aabb.cpp @@ -0,0 +1,272 @@ +#include "math/lin/aabb.h" +#include "math/lin/ray.h" +#include "math/lin/plane.h" + +#define NUMDIM 3 +#define RIGHT 0 +#define LEFT 1 +#define MIDDLE 2 + +namespace lin { + +static const float flt_plus_inf = -logf(0); // let's keep C and C++ compilers happy. + +AABB::AABB() : minB(0,0,0),maxB(0,0,0) { + +} + +void AABB::Add(const Vec3 &pt) { + for (int i=0; i<3; i++) + { + if (pt[i] < minB[i]) + minB[i] = pt[i]; + if (pt[i] > maxB[i]) + maxB[i] = pt[i]; + } +} + +bool AABB::Contains(const Vec3 &pt) const { + for (int i=0; i<3; i++) + { + if (pt[i] < minB[i]) + return false; + if (pt[i] > maxB[i]) + return false; + } + return true; +} + + +bool AABB::IntersectRay(const Ray &ray, float &tnear, float &tfar) const { + float tNear=-flt_plus_inf, tFar=flt_plus_inf; +//For each pair of planes P associated with X, Y, and Z do: +//(example using X planes) + for (int i=0; i<3; i++) + { + float min = minB[i]; + float max = maxB[i]; + + if (ray.dir[i] == 0.0f) //parallell! ARGH! + if (ray.origin[i] < min || ray.origin[i] > max) + return false; + //Intersect with slab + float T1 = (min - ray.origin[i]) * ray.invdir[i]; + float T2 = (max - ray.origin[i]) * ray.invdir[i]; + //Swap if necessary + if (T1 > T2) + { + float temp=T1; T1=T2; T2=temp; + } + //Save closest/farthest hits + if (T1 > tNear) tNear = T1; + if (T2 < tFar) tFar = T2; + } + + if (tNear > tFar) + return false; //missed the box + else + { + if (tFar < 0) + return false; //behind camera + tnear = tNear; + tfar = tFar; + } + return true; +} + + +// Possible orientation of the splitting plane in the interior node of the kd-tree, +// ”No axis” denotes a leaf. +enum Axes +{ + Xaxis, + Yaxis, + Zaxis, + Noaxis +}; + + + +int AABB::GetShortestAxis() const +{ + Vec3 delta = maxB-minB; + if (delta.yfabs(delta.x)) + { + if (fabs(delta.z)>fabs(delta.y)) + return 2; + else + return 1; + } + else + { + if (fabs(delta.z)>fabs(delta.x)) + return 2; + else + return 0; + } +} + + + +inline void FINDMINMAX(float x0, float x1, float x2, float &min, float &max ) +{ + min = max = x0; + if(x1max) + max=x1; + if(x2max) + max=x2; +} + +// X-tests +#define AXISTEST_X01( a, b, fa, fb ) \ + p0 = a * v0[1] - b * v0[2], p2 = a * v2[1] - b * v2[2]; \ + if (p0 < p2) { min = p0; max = p2;} else { min = p2; max = p0; } \ + rad = fa * a_BoxHalfsize[1] + fb * a_BoxHalfsize[2]; \ + if (min > rad || max < -rad) return 0; + +#define AXISTEST_X2( a, b, fa, fb ) \ + p0 = a * v0[1] - b * v0[2], p1 = a * v1[1] - b * v1[2]; \ + if (p0 < p1) { min = p0; max = p1; } else { min = p1; max = p0;} \ + rad = fa * a_BoxHalfsize[1] + fb * a_BoxHalfsize[2]; \ + if(min>rad || max<-rad) return 0; +// Y-tests +#define AXISTEST_Y02( a, b, fa, fb ) \ + p0 = -a * v0[0] + b * v0[2], p2 = -a * v2[0] + b * v2[2]; \ + if(p0 < p2) { min = p0; max = p2; } else { min = p2; max = p0; } \ + rad = fa * a_BoxHalfsize[0] + fb * a_BoxHalfsize[2]; \ + if (min > rad || max < -rad) return 0; +#define AXISTEST_Y1( a, b, fa, fb ) \ + p0 = -a * v0[0] + b * v0[2], p1 = -a * v1[0] + b * v1[2]; \ + if (p0 < p1) { min = p0; max = p1; } else { min = p1; max = p0; } \ + rad = fa * a_BoxHalfsize[0] + fb * a_BoxHalfsize[2]; \ + if (min > rad || max < -rad) return 0; +// Z-tests +#define AXISTEST_Z12( a, b, fa, fb ) \ + p1 = a * v1[0] - b * v1[1], p2 = a * v2[0] - b * v2[1]; \ + if(p2 < p1) { min = p2; max = p1; } else { min = p1; max = p2; } \ + rad = fa * a_BoxHalfsize[0] + fb * a_BoxHalfsize[1]; \ + if (min > rad || max < -rad) return 0; +#define AXISTEST_Z0( a, b, fa, fb ) \ + p0 = a * v0[0] - b * v0[1], p1 = a * v1[0] - b * v1[1]; \ + if(p0 < p1) { min = p0; max = p1; } else { min = p1; max = p0; } \ + rad = fa * a_BoxHalfsize[0] + fb * a_BoxHalfsize[1]; \ + if (min > rad || max < -rad) return 0; + +bool PlaneBoxOverlap(const Vec3& a_Normal, const Vec3& a_Vert, const Vec3& a_MaxBox ) +{ + Vec3 vmin, vmax; + for (int q = 0; q < 3; q++) + { + float v = a_Vert[q]; + if (a_Normal[q] > 0.0f) + { + vmin[q] = -a_MaxBox[q] - v; + vmax[q] = a_MaxBox[q] - v; + } + else + { + vmin[q] = a_MaxBox[q] - v; + vmax[q] = -a_MaxBox[q] - v; + } + } + if (( a_Normal * vmin) > 0.0f) + return false; + if (( a_Normal * vmax) >= 0.0f) + return true; + + return false; +} + + +bool AABB::IntersectsTriangle(const Vec3& a_V0, const Vec3& a_V1, const Vec3& a_V2 ) const +{ + Vec3 a_BoxCentre = GetMidpoint(); + Vec3 a_BoxHalfsize = GetExtents() / 2.0f; + Vec3 v0, v1, v2, normal, e0, e1, e2; + float min, max, p0, p1, p2, rad, fex, fey, fez; + v0 = a_V0 - a_BoxCentre; + v1 = a_V1 - a_BoxCentre; + v2 = a_V2 - a_BoxCentre; + e0 = v1 - v0, e1 = v2 - v1, e2 = v0 - v2; + fex = fabs(e0[0]); + fey = fabs(e0[1]); + fez = fabs(e0[2]); + AXISTEST_X01( e0[2], e0[1], fez, fey ); + AXISTEST_Y02( e0[2], e0[0], fez, fex ); + AXISTEST_Z12( e0[1], e0[0], fey, fex ); + fex = fabs(e1[0]); + fey = fabs(e1[1]); + fez = fabs(e1[2]); + AXISTEST_X01( e1[2], e1[1], fez, fey ); + AXISTEST_Y02( e1[2], e1[0], fez, fex ); + AXISTEST_Z0 ( e1[1], e1[0], fey, fex ); + fex = fabs(e2[0]); + fey = fabs(e2[1]); + fez = fabs(e2[2]); + AXISTEST_X2 ( e2[2], e2[1], fez, fey ); + AXISTEST_Y1 ( e2[2], e2[0], fez, fex ); + AXISTEST_Z12( e2[1], e2[0], fey, fex ); + FINDMINMAX( v0[0], v1[0], v2[0], min, max ); + if (min > a_BoxHalfsize[0] || max < -a_BoxHalfsize[0]) + return false; + FINDMINMAX( v0[1], v1[1], v2[1], min, max ); + if (min > a_BoxHalfsize[1] || max < -a_BoxHalfsize[1]) + return false; + FINDMINMAX( v0[2], v1[2], v2[2], min, max ); + if (min > a_BoxHalfsize[2] || max < -a_BoxHalfsize[2]) + return false; + normal = e0 % e1; + if (!PlaneBoxOverlap( normal, v0, a_BoxHalfsize )) + return false; + return true; +} + + +bool AABB::BehindPlane(const Plane &plane) const { + if (plane.Distance(minB) > 0) + return false; + if (plane.Distance(maxB) > 0) + return false; + + if (plane.Distance(maxB.x, minB.y, minB.z) > 0) + return false; + if (plane.Distance(maxB.x, maxB.y, minB.z) > 0) + return false; + if (plane.Distance(maxB.x, minB.y, maxB.z) > 0) + return false; + + if (plane.Distance(minB.x, maxB.y, minB.z) > 0) + return false; + if (plane.Distance(minB.x, minB.y, maxB.z) > 0) + return false; + if (plane.Distance(minB.x, maxB.y, maxB.z) > 0) + return false; + + return true; +} + +} // namespace lin diff --git a/math/lin/aabb.h b/math/lin/aabb.h new file mode 100644 index 0000000000..22f2a7b80d --- /dev/null +++ b/math/lin/aabb.h @@ -0,0 +1,47 @@ +#ifndef _MATH_LIN_AABB +#define _MATH_LIN_AABB + +#include "math/lin/vec3.h" + +namespace lin { + +class Ray; +class Plane; + +struct AABB { + Vec3 minB; + int pad; + Vec3 maxB; + int pad2; + + AABB(); + bool Contains(const Vec3 &pt) const; + bool IntersectRay(const Ray &ray, float &tnear, float &tfar) const; + + // Doesn't currently work. + bool IntersectRay2(const Ray &ray, float &tnear, float &tfar) const; + + bool IntersectsTriangle(const Vec3& a_V0, const Vec3& a_V1, const Vec3& a_V2) const; + void Add(const Vec3 &pt); + int GetShortestAxis() const; + int GetLongestAxis() const; + + float GetSize(int axis) const { + return maxB[axis] - minB[axis]; + } + float GetMidpoint(int axis) const { + return (minB[axis] + maxB[axis]) / 2; + } + Vec3 GetMidpoint() const { + return (minB + maxB) / 2; + } + Vec3 GetExtents() const { + return maxB - minB; + } + + bool BehindPlane(const Plane &plane) const; +}; + +} // namespace lin + +#endif // _MATH_LIN_AABB diff --git a/math/lin/build.scons b/math/lin/build.scons new file mode 100644 index 0000000000..41b0cf46c2 --- /dev/null +++ b/math/lin/build.scons @@ -0,0 +1,12 @@ +Import('env') + +inputs = [ + 'aabb.cc', + 'matrix4x4.cc', + 'vec3.cc', + 'quat.cc', + 'ray_intersections.cc', +] + +env.Append(LIBS = ['gflags', 'glog', ]) +env.ComponentLibrary('lin', inputs, COMPONENT_STATIC=True) diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp new file mode 100644 index 0000000000..a2e7f32c93 --- /dev/null +++ b/math/lin/matrix4x4.cpp @@ -0,0 +1,276 @@ +#include "math/lin/matrix4x4.h" + +#include + +#include "math/lin/vec3.h" +#include "math/lin/quat.h" + +// See http://code.google.com/p/oolongengine/source/browse/trunk/Oolong+Engine2/Math/neonmath/neon_matrix_impl.cpp?spec=svn143&r=143 when we need speed +// no wait. http://code.google.com/p/math-neon/ + +void matrix_mul_4x4(Matrix4x4 &res, const Matrix4x4 &inA, const Matrix4x4 &inB) { + res.xx = inA.xx*inB.xx + inA.xy*inB.yx + inA.xz*inB.zx + inA.xw*inB.wx; + res.xy = inA.xx*inB.xy + inA.xy*inB.yy + inA.xz*inB.zy + inA.xw*inB.wy; + res.xz = inA.xx*inB.xz + inA.xy*inB.yz + inA.xz*inB.zz + inA.xw*inB.wz; + res.xw = inA.xx*inB.xw + inA.xy*inB.yw + inA.xz*inB.zw + inA.xw*inB.ww; + + res.yx = inA.yx*inB.xx + inA.yy*inB.yx + inA.yz*inB.zx + inA.yw*inB.wx; + res.yy = inA.yx*inB.xy + inA.yy*inB.yy + inA.yz*inB.zy + inA.yw*inB.wy; + res.yz = inA.yx*inB.xz + inA.yy*inB.yz + inA.yz*inB.zz + inA.yw*inB.wz; + res.yw = inA.yx*inB.xw + inA.yy*inB.yw + inA.yz*inB.zw + inA.yw*inB.ww; + + res.zx = inA.zx*inB.xx + inA.zy*inB.yx + inA.zz*inB.zx + inA.zw*inB.wx; + res.zy = inA.zx*inB.xy + inA.zy*inB.yy + inA.zz*inB.zy + inA.zw*inB.wy; + res.zz = inA.zx*inB.xz + inA.zy*inB.yz + inA.zz*inB.zz + inA.zw*inB.wz; + res.zw = inA.zx*inB.xw + inA.zy*inB.yw + inA.zz*inB.zw + inA.zw*inB.ww; + + res.wx = inA.wx*inB.xx + inA.wy*inB.yx + inA.wz*inB.zx + inA.ww*inB.wx; + res.wy = inA.wx*inB.xy + inA.wy*inB.yy + inA.wz*inB.zy + inA.ww*inB.wy; + res.wz = inA.wx*inB.xz + inA.wy*inB.yz + inA.wz*inB.zz + inA.ww*inB.wz; + res.ww = inA.wx*inB.xw + inA.wy*inB.yw + inA.wz*inB.zw + inA.ww*inB.ww; +} + +Matrix4x4 Matrix4x4::simpleInverse() const { + Matrix4x4 out; + out.xx = xx; + out.xy = yx; + out.xz = zx; + + out.yx = xy; + out.yy = yy; + out.yz = zy; + + out.zx = xz; + out.zy = yz; + out.zz = zz; + + out.wx = -(xx * wx + xy * wy + xz * wz); + out.wy = -(yx * wx + yy * wy + yz * wz); + out.wz = -(zx * wx + zy * wy + zz * wz); + + out.xw = 0.0f; + out.yw = 0.0f; + out.zw = 0.0f; + out.ww = 1.0f; + + return out; +} +Matrix4x4 Matrix4x4::transpose() const +{ + Matrix4x4 out; + out.xx = xx;out.xy = yx;out.xz = zx;out.xw = wx; + out.yx = xy;out.yy = yy;out.yz = zy;out.yw = wy; + out.zx = xz;out.zy = yz;out.zz = zz;out.zw = wz; + out.wx = xw;out.wy = yw;out.wz = zw;out.ww = ww; + return out; +} + +Matrix4x4 Matrix4x4::operator * (const Matrix4x4 &other) const +{ + Matrix4x4 temp; + matrix_mul_4x4(temp, *this, other); + return temp; +} + +Matrix4x4 Matrix4x4::inverse() const { + Matrix4x4 temp; + float dW = 1.0f / (xx*(yy*zz - yz*zy) - xy*(yx*zz - yz*zx) - xz*(yy*zx - yx*zy)); + + temp.xx = (yy*zz - yz*zy) * dW; + temp.xy = (xz*zy - xy*zz) * dW; + temp.xz = (xy*yz - xz*yy) * dW; + temp.xw = xw; + + temp.yx = (yz*zx - yx*zz) * dW; + temp.yy = (xx*zz - xz*zx) * dW; + temp.yz = (xz*yx - xx*zx) * dW; + temp.yw = yw; + + temp.zx = (yx*zy - yy*zx) * dW; + temp.zy = (xy*zx - xx*zy) * dW; + temp.zz = (xx*yy - xy*yx) * dW; + temp.zw = zw; + + temp.wx = (yy*(zx*wz - zz*wx) + yz*(zy*wx - zx*wy) - yx*(zy*wz - zz*wy)) * dW; + temp.wy = (xx*(zy*wz - zz*wy) + xy*(zz*wx - zx*wz) + xz*(zx*wy - zy*wx)) * dW; + temp.wz = (xy*(yx*wz - yz*wx) + xz*(yy*wx - yx*wy) - xx*(yy*wz - yz*wy)) * dW; + temp.ww = ww; + + return temp; +} + +void Matrix4x4::setViewLookAt(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 &vWorldUp) { + Vec3 vView = vFrom - vAt; // OpenGL, sigh... + vView.normalize(); + float DotProduct = vWorldUp * vView; + Vec3 vUp = vWorldUp - vView * DotProduct; + float Length = vUp.length(); + + if (1e-6f > Length) { + // EMERGENCY + vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; + // If we still have near-zero length, resort to a different axis. + Length = vUp.length(); + if (1e-6f > Length) + { + vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z; + Length = vUp.length(); + if (1e-6f > Length) + return; + } + } + vUp.normalize(); + Vec3 vRight = vUp % vView; + empty(); + + xx = vRight.x; xy = vUp.x; xz=vView.x; + yx = vRight.y; yy = vUp.y; yz=vView.y; + zx = vRight.z; zy = vUp.z; zz=vView.z; + + wx = -vFrom * vRight; + wy = -vFrom * vUp; + wz = -vFrom * vView; + ww = 1.0f; +} + +void Matrix4x4::setViewLookAtD3D(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 &vWorldUp) { + Vec3 vView = vAt - vFrom; + vView.normalize(); + float DotProduct = vWorldUp * vView; + Vec3 vUp = vWorldUp - vView * DotProduct; + float Length = vUp.length(); + + if (1e-6f > Length) { + // EMERGENCY + vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; + // If we still have near-zero length, resort to a different axis. + Length = vUp.length(); + if (1e-6f > Length) + { + vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z; + Length = vUp.length(); + if (1e-6f > Length) + return; + } + } + vUp.normalize(); + Vec3 vRight = vUp % vView; + empty(); + + xx = vRight.x; xy = vUp.x; xz=vView.x; + yx = vRight.y; yy = vUp.y; yz=vView.y; + zx = vRight.z; zy = vUp.z; zz=vView.z; + + wx = -vFrom * vRight; + wy = -vFrom * vUp; + wz = -vFrom * vView; + ww = 1.0f; +} + + +void Matrix4x4::setViewFrame(const Vec3 &pos, const Vec3 &vRight, const Vec3 &vView, const Vec3 &vUp) { + xx = vRight.x; xy = vUp.x; xz=vView.x; xw = 0.0f; + yx = vRight.y; yy = vUp.y; yz=vView.y; yw = 0.0f; + zx = vRight.z; zy = vUp.z; zz=vView.z; zw = 0.0f; + + wx = -pos * vRight; + wy = -pos * vUp; + wz = -pos * vView; + ww = 1.0f; +} + +//YXZ euler angles +void Matrix4x4::setRotation(float x,float y, float z) +{ + setRotationY(y); + Matrix4x4 temp; + temp.setRotationX(x); + *this *= temp; + temp.setRotationZ(z); + *this *= temp; +} + +void Matrix4x4::setProjection(float near, float far, float fov_horiz, float aspect) { + // Now OpenGL style. + empty(); + + float xFac = tanf(fov_horiz * 3.14f/360); + float yFac = xFac * aspect; + xx = 1.0f / xFac; + yy = 1.0f / yFac; + zz = -(far+near)/(far-near); + zw = -1.0f; + wz = -(2*far*near)/(far-near); +} + +void Matrix4x4::setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect) { + empty(); + float Q, f; + + f = fov_horiz*0.5f; + Q = far_plane / (far_plane - near_plane); + + xx = (float)(1.0f / tanf(f));; + yy = (float)(1.0f / tanf(f*aspect)); + zz = Q; + wz = -Q * near_plane; + zw = 1.0f; +} + +void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float near, float far) { + setIdentity(); + xx = 2.0f / (right - left); + yy = 2.0f / (top - bottom); + zz = 2.0f / (far - near); + wx = -(right + left) / (right - left); + wy = -(top + bottom) / (top - bottom); + wz = -(far + near) / (far - near); +} + +// This is a D3D style matrix. +void Matrix4x4::setProjectionInf(const float near_plane, const float fov_horiz, const float aspect) { + empty(); + float f = fov_horiz*0.5f; + xx = 1.0f / tanf(f); + yy = 1.0f / tanf(f*aspect); + zz = 1; + wz = -near_plane; + zw = 1.0f; +} + +void Matrix4x4::setRotationAxisAngle(const Vec3 &axis, float angle) { + Quaternion quat; + quat.setRotation(axis, angle); + quat.toMatrix(this); +} + +// from a (Position, Rotation, Scale) vec3 quat vec3 tuple +Matrix4x4 Matrix4x4::fromPRS(const Vec3 &positionv, const Quaternion &rotv, const Vec3 &scalev) { + Matrix4x4 newM; + newM.setIdentity(); + Matrix4x4 rot, scale; + rotv.toMatrix(&rot); + scale.setScaling(scalev); + newM = rot * scale; + newM.wx = positionv.x; + newM.wy = positionv.y; + newM.wz = positionv.z; + return newM; +} +#if _MSC_VER +#define snprintf _snprintf +#endif +void Matrix4x4::toText(char *buffer, int len) const { + snprintf(buffer, len, "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", + xx,xy,xz,xw, + yx,yy,yz,yw, + zx,zy,zz,zw, + wx,wy,wz,ww); + buffer[len - 1] = '\0'; +} + +void Matrix4x4::print() const { + char buffer[256]; + toText(buffer, 256); + puts(buffer); +} diff --git a/math/lin/matrix4x4.h b/math/lin/matrix4x4.h new file mode 100644 index 0000000000..b64b31a28d --- /dev/null +++ b/math/lin/matrix4x4.h @@ -0,0 +1,141 @@ +#ifndef _MATH_LIN_MATRIX4X4_H +#define _MATH_LIN_MATRIX4X4_H + +#include "math/lin/vec3.h" + +class Quaternion; + +class Matrix4x4 { + public: + float xx, xy, xz, xw; + float yx, yy, yz, yw; + float zx, zy, zz, zw; + float wx, wy, wz, ww; + + const Vec3 right() const {return Vec3(xx, xy, xz);} + const Vec3 up() const {return Vec3(yx, yy, yz);} + const Vec3 front() const {return Vec3(zx, zy, zz);} + const Vec3 move() const {return Vec3(wx, wy, wz);} + + void setRight(const Vec3 &v) { + xx = v.x; xy = v.y; xz = v.z; + } + void setUp(const Vec3 &v) { + yx = v.x; yy = v.y; yz = v.z; + } + void setFront(const Vec3 &v) { + zx = v.x; zy = v.y; zz = v.z; + } + void setMove(const Vec3 &v) { + wx = v.x; wy = v.y; wz = v.z; + } + + + const float &operator[](int i) const { + return *(((const float *)this) + i); + } + float &operator[](int i) { + return *(((float *)this) + i); + } + Matrix4x4 operator * (const Matrix4x4 &other) const ; + void operator *= (const Matrix4x4 &other) { + *this = *this * other; + } + const float *getReadPtr() const { + return (const float *)this; + } + void empty() { + memset(this, 0, 16 * sizeof(float)); + } + void setScaling(const float f) { + empty(); + xx=yy=zz=f; ww=1.0f; + } + void setScaling(const Vec3 f) { + empty(); + xx=f.x; + yy=f.y; + zz=f.z; + ww=1.0f; + } + + void setIdentity() { + setScaling(1.0f); + } + void setTranslation(const Vec3 &trans) { + setIdentity(); + wx = trans.x; + wy = trans.y; + wz = trans.z; + } + Matrix4x4 inverse() const; + Matrix4x4 simpleInverse() const; + Matrix4x4 transpose() const; + + void setRotationX(const float a) { + empty(); + float c=cosf(a); + float s=sinf(a); + xx = 1.0f; + yy = c; yz = s; + zy = -s; zz = c; + ww = 1.0f; + } + void setRotationY(const float a) { + empty(); + float c=cosf(a); + float s=sinf(a); + xx = c; xz = -s; + yy = 1.0f; + zx = s; zz = c ; + ww = 1.0f; + } + void setRotationZ(const float a) { + empty(); + float c=cosf(a); + float s=sinf(a); + xx = c; xy = s; + yx = -s; yy = c; + zz = 1.0f; + ww = 1.0f; + } + void setRotationAxisAngle(const Vec3 &axis, float angle); + + + void setRotation(float x,float y, float z); + void setProjection(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); + void setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); + void setProjectionInf(float near_plane, float fov_horiz, float aspect = 0.75f); + void setOrtho(float left, float right, float bottom, float top, float near, float far); + void setShadow(float Lx, float Ly, float Lz, float Lw) { + float Pa=0; + float Pb=1; + float Pc=0; + float Pd=0; + //P = normalize(Plane); + float d = (Pa*Lx + Pb*Ly + Pc*Lz + Pd*Lw); + + xx=Pa * Lx + d; xy=Pa * Ly; xz=Pa * Lz; xw=Pa * Lw; + yx=Pb * Lx; yy=Pb * Ly + d; yz=Pb * Lz; yw=Pb * Lw; + zx=Pc * Lx; zy=Pc * Ly; zz=Pc * Lz + d; zw=Pc * Lw; + wx=Pd * Lx; wy=Pd * Ly; wz=Pd * Lz; ww=Pd * Lw + d; + } + + void setViewLookAt(const Vec3 &from, const Vec3 &at, const Vec3 &worldup); + void setViewLookAtD3D(const Vec3 &from, const Vec3 &at, const Vec3 &worldup); + void setViewFrame(const Vec3 &pos, const Vec3 &right, const Vec3 &forward, const Vec3 &up); + void stabilizeOrtho() { + /* + front().normalize(); + right().normalize(); + up() = front() % right(); + right() = up() % front(); + */ + } + void toText(char *buffer, int len) const; + void print() const; + static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale); +}; + +#endif // _MATH_LIN_MATRIX4X4_H + diff --git a/math/lin/matrix_neon.s b/math/lin/matrix_neon.s new file mode 100644 index 0000000000..a663ffe956 --- /dev/null +++ b/math/lin/matrix_neon.s @@ -0,0 +1,106 @@ +@ +@ NEON matrix multiplication examples +@ + +.syntax unified + +@ +@ matrix_mul_float: +@ Calculate 4x4 (matrix 0) * (matrix 1) and store to result 4x4 matrix. +@ matrix 0, matrix 1 and result pointers can be the same, +@ ie. my_matrix = my_matrix * my_matrix is possible. +@ +@ r0 = pointer to 4x4 result matrix, single precision floats, column major order +@ r1 = pointer to 4x4 matrix 0, single precision floats, column major order +@ r2 = pointer to 4x4 matrix 1, single precision floats, column major order +@ + + .global matrix_mul_float +matrix_mul_float: + vld1.32 {d16-d19}, [r1]! @ load first eight elements of matrix 0 + vld1.32 {d20-d23}, [r1]! @ load second eight elements of matrix 0 + vld1.32 {d0-d3}, [r2]! @ load first eight elements of matrix 1 + vld1.32 {d4-d7}, [r2]! @ load second eight elements of matrix 1 + + vmul.f32 q12, q8, d0[0] @ rslt col0 = (mat0 col0) * (mat1 col0 elt0) + vmul.f32 q13, q8, d2[0] @ rslt col1 = (mat0 col0) * (mat1 col1 elt0) + vmul.f32 q14, q8, d4[0] @ rslt col2 = (mat0 col0) * (mat1 col2 elt0) + vmul.f32 q15, q8, d6[0] @ rslt col3 = (mat0 col0) * (mat1 col3 elt0) + + vmla.f32 q12, q9, d0[1] @ rslt col0 += (mat0 col1) * (mat1 col0 elt1) + vmla.f32 q13, q9, d2[1] @ rslt col1 += (mat0 col1) * (mat1 col1 elt1) + vmla.f32 q14, q9, d4[1] @ rslt col2 += (mat0 col1) * (mat1 col2 elt1) + vmla.f32 q15, q9, d6[1] @ rslt col3 += (mat0 col1) * (mat1 col3 elt1) + + vmla.f32 q12, q10, d1[0] @ rslt col0 += (mat0 col2) * (mat1 col0 elt2) + vmla.f32 q13, q10, d3[0] @ rslt col1 += (mat0 col2) * (mat1 col1 elt2) + vmla.f32 q14, q10, d5[0] @ rslt col2 += (mat0 col2) * (mat1 col2 elt2) + vmla.f32 q15, q10, d7[0] @ rslt col3 += (mat0 col2) * (mat1 col2 elt2) + + vmla.f32 q12, q11, d1[1] @ rslt col0 += (mat0 col3) * (mat1 col0 elt3) + vmla.f32 q13, q11, d3[1] @ rslt col1 += (mat0 col3) * (mat1 col1 elt3) + vmla.f32 q14, q11, d5[1] @ rslt col2 += (mat0 col3) * (mat1 col2 elt3) + vmla.f32 q15, q11, d7[1] @ rslt col3 += (mat0 col3) * (mat1 col3 elt3) + + vst1.32 {d24-d27}, [r0]! @ store first eight elements of result + vst1.32 {d28-d31}, [r0]! @ store second eight elements of result + + mov pc, lr @ return to caller + + + + + +@ Macro: mul_col_s16 +@ +@ Multiply a four s16 element column of a matrix by the columns of a second matrix +@ to give a column of results. Elements are assumed to be in Q1.14 format. +@ Inputs: col_d - d register containing a column of the matrix +@ Outputs: res_d - d register containing the column of results +@ Corrupts: register q12 +@ Assumes: the second matrix columns are in registers d16-d19 in column major order +@ + + .macro mul_col_s16 res_d, col_d + vmull.s16 q12, d16, \col_d[0] @ multiply col element 0 by matrix col 0 + vmlal.s16 q12, d17, \col_d[1] @ multiply-acc col element 1 by matrix col 1 + vmlal.s16 q12, d18, \col_d[2] @ multiply-acc col element 2 by matrix col 2 + vmlal.s16 q12, d19, \col_d[3] @ multiply-acc col element 3 by matrix col 3 + vqrshrn.s32 \res_d, q12, #14 @ shift right and narrow accumulator into + @ Q1.14 fixed point format, with saturation + .endm + +@ +@ matrix_mul_fixed: +@ Calculate 4x4 (matrix 0) * (matrix 1) and store to result 4x4 matrix. +@ matrix 0, matrix 1 and result pointers can be the same, +@ ie. my_matrix = my_matrix * my_matrix is possible +@ +@ r0 = pointer to 4x4 result matrix, Q1.14 fixed point, column major order +@ r1 = pointer to 4x4 matrix 0, Q1.14 fixed point, column major order +@ r2 = pointer to 4x4 matrix 1, Q1.14 fixed point, column major order +@ + + .global matrix_mul_fixed +matrix_mul_fixed: + vld1.16 {d16-d19}, [r1] @ load sixteen elements of matrix 0 + vld1.16 {d0-d3}, [r2] @ load sixteen elements of matrix 1 + + mul_col_s16 d4, d0 @ matrix 0 * matrix 1 col 0 + mul_col_s16 d5, d1 @ matrix 0 * matrix 1 col 1 + mul_col_s16 d6, d2 @ matrix 0 * matrix 1 col 2 + mul_col_s16 d7, d3 @ matrix 0 * matrix 1 col 3 + + vst1.16 {d4-d7}, [r0] @ store sixteen elements of result + + mov pc, lr @ return to caller + + + + + + + + + + diff --git a/math/lin/plane.cpp b/math/lin/plane.cpp new file mode 100644 index 0000000000..31b52fa00d --- /dev/null +++ b/math/lin/plane.cpp @@ -0,0 +1,13 @@ +#include "math/lin/matrix4x4.h" +#include "math/lin/plane.h" + +namespace lin { + +Plane Plane::TransformByIT(const Matrix4x4 &m, Plane *out) { + out->x = x * m.xx + y * m.yx + z * m.zx + d * m.wx; + out->y = x * m.xy + y * m.yy + z * m.zy + d * m.wy; + out->z = x * m.xz + y * m.yz + z * m.zz + d * m.wz; + out->d = x * m.xw + y * m.yw + z * m.zw + d * m.ww; +} + +} diff --git a/math/lin/plane.h b/math/lin/plane.h new file mode 100644 index 0000000000..02c7ad22da --- /dev/null +++ b/math/lin/plane.h @@ -0,0 +1,41 @@ +#ifndef _PLANE_H +#define _PLANE_H + +#include "math/lin/vec3.h" + +namespace lin { + +class Matrix4x4; + +class Plane { + public: + float x, y, z, d; + Plane() {} + Plane(float x_, float y_, float z_, float d_) + : x(x_), y(y_), z(z_), d(d_) { } + ~Plane() {} + + float Distance(const Vec3 &v) const { + return x * v.x + y * v.y + z * v.z + d; + } + + float Distance(float px, float py, float pz) const { + return x * px + y * py + z * pz + d; + } + + void Normalize() { + float inv_length = 1.0 * sqrtf(x * x + y * y + z * z); + x *= inv_length; + y *= inv_length; + z *= inv_length; + d *= inv_length; + } + + // Matrix is the inverse transpose of the wanted transform. + // out cannot be equal to this. + Plane TransformByIT(const Matrix4x4 &matrix, Plane *out); +}; + +} + +#endif diff --git a/math/lin/quat.cpp b/math/lin/quat.cpp new file mode 100644 index 0000000000..b869aa6b87 --- /dev/null +++ b/math/lin/quat.cpp @@ -0,0 +1,124 @@ +#include "math/lin/quat.h" +#include "math/lin/matrix4x4.h" + +void Quaternion::toMatrix(Matrix4x4 *out) const { + Matrix4x4 temp; + temp.setIdentity(); + float ww, xx, yy, zz, wx, wy, wz, xy, xz, yz; + ww = w*w; xx = x*x; yy = y*y; zz = z*z; + wx = w*x*2; wy = w*y*2; wz = w*z*2; + xy = x*y*2; xz = x*z*2; yz = y*z*2; + + temp.xx = ww + xx - yy - zz; + temp.xy = xy + wz; + temp.xz = xz - wy; + + temp.yx = xy - wz; + temp.yy = ww - xx + yy - zz; + temp.yz = yz + wx; + + temp.zx = xz + wy; + temp.zy = yz - wx; + temp.zz = ww - xx - yy + zz; + + *out = temp; +} + +Quaternion Quaternion::fromMatrix(Matrix4x4 &m) +{ + // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes + // article "Quaternion Calculus and Fast Animation". + Quaternion q(0,0,0,1); + /* + float fTrace = m[0][0] + m[1][1] + m[2][2]; + float fRoot; + + if( fTrace > 0.0 ) + { + fRoot = sqrtf( fTrace + 1.0f ); + + q.w = 0.5f * fRoot; + + fRoot = 0.5f / fRoot; + + q.x = ( m[2][1] - m[1][2] ) * fRoot; + q.y = ( m[0][2] - m[2][0] ) * fRoot; + q.z = ( m[1][0] - m[0][1] ) * fRoot; + } + else + { + int iNext[3] = { 1, 2, 0 }; + + int i = 0; + if( m[1][1] > m[0][0] ) + i = 1; + + if( m[2][2] > m[i][i] ) + i = 2; + + int j = iNext[i]; + int k = iNext[j]; + + fRoot = sqrtf( m[i][i] - m[j][j] - m[k][k] + 1.0f ); + + float *apfQuat = &q.x; + + apfQuat[i] = 0.5f * fRoot; + + fRoot = 0.5f / fRoot; + + q.w = ( m[k][j] - m[j][k] ) * fRoot; + + apfQuat[j] = ( m[j][i] + m[i][j] ) * fRoot; + apfQuat[k] = ( m[k][i] + m[i][k] ) * fRoot; + } + q.normalize(); */ + return q; +}; + +Quaternion Quaternion::slerp(const Quaternion &to, const float a) const { + Quaternion to2; + float angle, cos_angle, scale_from, scale_to, sin_angle; + + cos_angle = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); //4D dot product + + if (cos_angle < 0.0f) + { + cos_angle = -cos_angle; + to2.w = -to.w; to2.x = -to.x; to2.y = -to.y; to2.z = -to.z; + } + else + { + to2 = to; + } + + if ((1.0f - fabsf(cos_angle)) > 0.00001f) + { + /* spherical linear interpolation (SLERP) */ + angle = acosf(cos_angle); + sin_angle = sinf(angle); + scale_from = sinf((1.0f - a) * angle) / sin_angle; + scale_to = sinf(a * angle) / sin_angle; + } + else + { + /* to prevent divide-by-zero, resort to linear interpolation */ + // This is okay in 99% of cases anyway, maybe should be the default? + scale_from = 1.0f - a; + scale_to = a; + } + + return Quaternion( + scale_from*x + scale_to*to2.x, + scale_from*y + scale_to*to2.y, + scale_from*z + scale_to*to2.z, + scale_from*w + scale_to*to2.w + ); +} + +Quaternion Quaternion::multiply(const Quaternion &q) const { + return Quaternion((w * q.x) + (x * q.w) + (y * q.z) - (z * q.y), + (w * q.y) + (y * q.w) + (z * q.x) - (x * q.z), + (w * q.z) + (z * q.w) + (x * q.y) - (y * q.x), + (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z)); +} diff --git a/math/lin/quat.h b/math/lin/quat.h new file mode 100644 index 0000000000..2bedd59733 --- /dev/null +++ b/math/lin/quat.h @@ -0,0 +1,92 @@ +#ifndef _MATH_LIN_QUAT_H +#define _MATH_LIN_QUAT_H + +#include "math/lin/vec3.h" + +class Matrix4x4; + +class Quaternion +{ +public: + float x,y,z,w; + + Quaternion() { } + Quaternion(const float _x, const float _y, const float _z, const float _w) { + x=_x; y=_y; z=_z; w=_w; + } + void setIdentity() + { + x=y=z=0; w=1.0f; + } + void setXRotation(const float r) { w = cosf(r / 2); x = sinf(r / 2); y = z = 0; } + void setYRotation(const float r) { w = cosf(r / 2); y = sinf(r / 2); x = z = 0; } + void setZRotation(const float r) { w = cosf(r / 2); z = sinf(r / 2); x = y = 0; } + void toMatrix(Matrix4x4 *out) const; + static Quaternion fromMatrix(Matrix4x4 &m); + + Quaternion operator *(Quaternion &q) const + { + return Quaternion( + (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z), + (w * q.x) + (x * q.w) + (y * q.z) - (z * q.y), + (w * q.y) + (y * q.w) + (z * q.x) - (x * q.z), + (w * q.z) + (z * q.w) + (x * q.y) - (y * q.x) + ); + } + Quaternion operator -() + { + return Quaternion(-x,-y,-z,-w); + } + void setRotation(Vec3 axis, float angle) + { + axis /= axis.length(); + angle *= .5f; + float sine = sinf(angle); + w = cosf(angle); + x = sine * axis.x; + y = sine * axis.y; + z = sine * axis.z; + } + void toAxisAngle(Vec3 &v, float &angle) + { + normalize(); + if (w==1.0f && x==0.0f && y==0.0f && z==0.0f) + { + v = Vec3(0,1,0); + angle = 0.0f; + return; + } + float cos_a = w; + angle = acosf(cos_a) * 2; + float sin_a = sqrtf( 1.0f - cos_a * cos_a ); + if (fabsf(sin_a) < 0.00005f) sin_a = 1; + float inv_sin_a=1.0f/sin_a; + v.x = x * inv_sin_a; + v.y = y * inv_sin_a; + v.z = z * inv_sin_a; + } + enum { + QUAT_SHORT, + QUAT_LONG, + QUAT_CW, + QUAT_CCW + }; + Quaternion slerp(const Quaternion &to, const float a) const; + Quaternion multiply(const Quaternion &q) const; + float &operator [] (int i) { + return *((&x) + i); + } + const float operator [] (int i) const { + return *((&x) + i); + } + //not sure about this, maybe mag is supposed to sqrt + float magnitude() const { + return x*x + y*y + z*z + w*w; + } + void normalize() { + float f = 1.0f/sqrtf(magnitude()); + x*=f; y*=f; z*=f; w*=f; + } +}; + +#endif // _MATH_LIN_QUAT_H diff --git a/math/lin/ray.h b/math/lin/ray.h new file mode 100644 index 0000000000..5c9a5e91e0 --- /dev/null +++ b/math/lin/ray.h @@ -0,0 +1,20 @@ +#ifndef _MATH_LIN_RAY_H +#define _MATH_LIN_RAY_H + +#include "vec3.h" + +namespace lin { + +/* __declspec(align(16)) */ struct Ray +{ + Vec3 origin; + int pad; + Vec3 dir; + int pad2; + Vec3 invdir; + int pad3; +}; + +} // namespace lin + +#endif // _MATH_LIN_RAY_H diff --git a/math/lin/vec3.cpp b/math/lin/vec3.cpp new file mode 100644 index 0000000000..bf35ea5118 --- /dev/null +++ b/math/lin/vec3.cpp @@ -0,0 +1,28 @@ +#include + +#include "math/lin/vec3.h" +#include "math/lin/matrix4x4.h" + +Vec3 Vec3::operator *(const Matrix4x4 &m) const { + return Vec3(x*m.xx + y*m.yx + z*m.zx + m.wx, + x*m.xy + y*m.yy + z*m.zy + m.wy, + x*m.xz + y*m.yz + z*m.zz + m.wz); +} +Vec4 Vec3::multiply4D(const Matrix4x4 &m) const { + return Vec4(x*m.xx + y*m.yx + z*m.zx + m.wx, + x*m.xy + y*m.yy + z*m.zy + m.wy, + x*m.xz + y*m.yz + z*m.zz + m.wz, + x*m.xw + y*m.yw + z*m.zw + m.ww); +} +Vec4 Vec4::multiply4D(Matrix4x4 &m) const { + return Vec4(x*m.xx + y*m.yx + z*m.zx + w*m.wx, + x*m.xy + y*m.yy + z*m.zy + w*m.wy, + x*m.xz + y*m.yz + z*m.zz + w*m.wz, + x*m.xw + y*m.yw + z*m.zw + w*m.ww); +} + +Vec3 Vec3::rotatedBy(const Matrix4x4 &m) const { + return Vec3(x*m.xx + y*m.yx + z*m.zx, + x*m.xy + y*m.yy + z*m.zy, + x*m.xz + y*m.yz + z*m.zz); +} diff --git a/math/lin/vec3.h b/math/lin/vec3.h new file mode 100644 index 0000000000..92badf89f9 --- /dev/null +++ b/math/lin/vec3.h @@ -0,0 +1,158 @@ +#ifndef _MATH_LIN_VEC3 +#define _MATH_LIN_VEC3 + +#include +#include // memset + +inline float sqr(float f) {return f*f;} +inline float sqr_signed(float f) {return f<0 ? -f*f : f*f;} + +#ifndef PI +#define PI (3.141592654f) +#endif +#define PI_INV (0.318309886f) + +class Matrix4x4; +// class Quaternion; + +// Hm, doesn't belong in this file. +class Vec4 { +public: + float x,y,z,w; + Vec4(){} + Vec4(float a, float b, float c, float d) {x=a;y=b;z=c;w=d;} + Vec4 multiply4D(Matrix4x4 &m) const; +}; + +class Vec3 { +public: + float x,y,z; + + Vec3() { } + explicit Vec3(float f) {x=y=z=f;} + + Vec3(const float _x, const float _y, const float _z) { + x=_x; y=_y; z=_z; + } + void Set(float _x, float _y, float _z) { + x=_x; y=_y; z=_z; + } + Vec3 operator + (const Vec3 &other) const { + return Vec3(x+other.x, y+other.y, z+other.z); + } + void operator += (const Vec3 &other) { + x+=other.x; y+=other.y; z+=other.z; + } + Vec3 operator -(const Vec3 &v) const { + return Vec3(x-v.x,y-v.y,z-v.z); + } + void operator -= (const Vec3 &other) + { + x-=other.x; y-=other.y; z-=other.z; + } + Vec3 operator -() const { + return Vec3(-x,-y,-z); + } + + Vec3 operator * (const float f) const { + return Vec3(x*f,y*f,z*f); + } + Vec3 operator / (const float f) const { + float invf = (1.0f/f); + return Vec3(x*invf,y*invf,z*invf); + } + void operator /= (const float f) + { + *this = *this / f; + } + float operator * (const Vec3 &other) const { + return x*other.x + y*other.y + z*other.z; + } + void operator *= (const float f) { + *this = *this * f; + } + void scaleBy(const Vec3 &other) { + x *= other.x; y *= other.y; z *= other.z; + } + Vec3 scaledBy(const Vec3 &other) const { + return Vec3(x*other.x, y*other.y, z*other.z); + } + Vec3 scaledByInv(const Vec3 &other) const { + return Vec3(x/other.x, y/other.y, z/other.z); + } + Vec3 operator *(const Matrix4x4 &m) const; + void operator *=(const Matrix4x4 &m) { + *this = *this * m; + } + Vec4 multiply4D(const Matrix4x4 &m) const; + Vec3 rotatedBy(const Matrix4x4 &m) const; + Vec3 operator %(const Vec3 &v) const { + return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); + } + float length2() const { + return x*x + y*y + z*z; + } + float length() const { + return sqrtf(length2()); + } + void setLength(const float l) { + (*this) *= l/length(); + } + Vec3 withLength(const float l) const { + return (*this) * l / length(); + } + float distance2To(const Vec3 &other) const { + return Vec3(other-(*this)).length2(); + } + Vec3 normalized() const { + return (*this) / length(); + } + float normalize() { //returns the previous length, is often useful + float len = length(); + (*this) = (*this)/len; + return len; + } + /* + float &operator [] (int i) { //allow vector[2] = 3 (vector.z=3) + return *((&x) + i); + } + const float operator [] (const int i) const { + return *((&x) + i); + }*/ + bool operator == (const Vec3 &other) const { + if (x==other.x && y==other.y && z==other.z) + return true; + else + return false; + } + Vec3 lerp(const Vec3 &other, const float t) const { + return (*this)*(1-t) + other*t; + } + void setZero() { + memset((void *)this,0,sizeof(float)*3); + } +}; + +inline Vec3 operator * (const float f, const Vec3 &v) {return v * f;} + +// In new code, prefer these to the operators. + +inline float dot(const Vec3 &a, const Vec3 &b) { + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +inline Vec3 cross(const Vec3 &a, const Vec3 &b) { + return a % b; +} + +inline float sqr(const Vec3 &v) { + return dot(v, v); +} + +class AABBox { +public: + Vec3 min; + Vec3 max; +}; + +#endif // _MATH_LIN_VEC3 diff --git a/math/math_util.cc b/math/math_util.cc new file mode 100644 index 0000000000..9454df7750 --- /dev/null +++ b/math/math_util.cc @@ -0,0 +1,19 @@ +#include "math/math_util.h" +#include +#include + +/* +static unsigned int randSeed = 22222; // Change this for different random sequences. + +void SetSeed(unsigned int seed) { + randSeed = seed * 382792592; +} + +unsigned int GenerateRandomNumber() { + randSeed = (randSeed * 196314165) + 907633515; + randSeed ^= _rotl(randSeed, 13); + return randSeed; +}*/ + +#include + diff --git a/math/math_util.h b/math/math_util.h new file mode 100644 index 0000000000..573a7e864d --- /dev/null +++ b/math/math_util.h @@ -0,0 +1,86 @@ +#ifndef _MATHUTILS_H +#define _MATHUTILS_H + +#include +#include + +typedef unsigned short float16; + +// This ain't a 1.5.10 float16, no sire, it's a stupid hack format where we chop 16 bits off a float. +// This choice is subject to change. +inline float16 FloatToFloat16(float x) { + int ix; + memcpy(&ix, &x, sizeof(float)); + return ix >> 16; +} + +inline float Float16ToFloat(float16 ix) { + float x; + memcpy(&x, &ix, sizeof(float)); + return x; +} + + +#define PI 3.141592653589793f + +// The stuff in this file is from all over the web, esp. dspmusic.org. I think it's all public domain. +// In any case, very little of it is used anywhere at the moment. + +inline float sine(float t,float f,float ph,float fm) { + return sinf((t*f+ph)*2*PI + 0.5f*PI*fm*(1 - sqrt(f*2))); +} + +//fb := feedback (0 to 1) (1 max saw) + +inline float saw(float t,float f,float ph, float fm, float fb = 1.0f) +{ + return sine(t,f,ph,fb*sine(t-1.0f,f,ph,fm)); +} + +// pm := pulse mod (0 to 1) (1 max pulse) +// pw := pulse width (0 to 1) (1 square) +inline float pulse(float t,float f,float ph,float fm,float fb,float pm,float pw) { + return saw(t,f,ph,fm,fb) - saw(t,f,ph+0.5f*pw,fm,fb) * pm; +} + +// Calculate pseudo-random 32 bit number based on linear congruential method. +void SetSeed(unsigned int seed); +unsigned int GenerateRandomNumber(); +inline float GenerateRandomFloat01() { + return (float)((double)GenerateRandomNumber() / 0xFFFFFFFF); +} +inline float GenerateRandomSignedFloat() { + return (float)((double)GenerateRandomNumber() / 0x80000000) - 1.0f; +} + + +inline float GaussRand() +{ + float R1 = GenerateRandomFloat01(); + float R2 = GenerateRandomFloat01(); + + float X = sqrtf( -2.0f * logf(R1)) * cosf(2.0f * PI * R2); + if (X > 4.0f) X = 4.0f; + if (X < -4.0f) X = -4.0f; + return X; +} + +// Accuracy unknown +inline double atan_fast(double x) { + return (x / (1.0 + 0.28 * (x * x))); +} + + +// linear -> dB conversion +inline float lin2dB(float lin) { + const float LOG_2_DB = 8.6858896380650365530225783783321f; // 20 / ln( 10 ) + return log(lin) * LOG_2_DB; +} + +// dB -> linear conversion +inline float dB2lin(float dB) { + const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20 + return exp(dB * DB_2_LOG); +} + +#endif diff --git a/native.vcxproj b/native.vcxproj new file mode 100644 index 0000000000..a03612b9a5 --- /dev/null +++ b/native.vcxproj @@ -0,0 +1,183 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {E8B58922-9827-493D-81E0-4B6E6BD77171} + Win32Proj + native + + + + StaticLibrary + true + MultiByte + + + StaticLibrary + false + false + MultiByte + + + + + + + + + + + + + D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + + + D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib + + + D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + + + D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\zlib;..\native;..\RollerballGL;..\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\zlib;..\native;..\RollerballGL;..\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/native.vcxproj.filters b/native.vcxproj.filters new file mode 100644 index 0000000000..d0b324b401 --- /dev/null +++ b/native.vcxproj.filters @@ -0,0 +1,299 @@ + + + + + + file + + + + + + + gfx + + + image + + + image + + + image + + + image + + + math + + + math + + + math + + + gfx + + + gfx + + + gfx + + + ext + + + audio + + + audio + + + profiler + + + input + + + file + + + file + + + file + + + file + + + collision + + + base + + + base + + + base + + + base + + + gfx + + + gfx + + + math + + + math + + + ext + + + base + + + base + + + ext + + + ext + + + gfx + + + audio + + + input + + + base + + + ext + + + base + + + gfx + + + json + + + file + + + math + + + gfx + + + + + gfx + + + image + + + image + + + image + + + math + + + math + + + math + + + gfx + + + gfx + + + gfx + + + ext + + + audio + + + audio + + + profiler + + + file + + + file + + + file + + + collision + + + base + + + gfx + + + gfx + + + math + + + math + + + ext + + + base + + + base + + + ext + + + ext + + + ext + + + gfx + + + audio + + + input + + + ext + + + base + + + gfx + + + json + + + file + + + gfx + + + + + {9da89505-72a1-40e6-86e5-705372db1608} + + + {828bddaf-63e5-4311-985b-bf377f86ff00} + + + {f3f83007-7c3b-473f-a2f7-423c5087fbfa} + + + {5c54b5e2-1bb2-4783-9df6-de4ff7105570} + + + {4ea45f6c-de87-44a9-95b2-e1ec7e3601d0} + + + {c57b41dd-cc33-46ac-b479-19676455ae54} + + + {4ba4474c-b80f-40da-95e8-2de57eb1b327} + + + {49afd06e-eb44-41ac-b038-e109e444a834} + + + {a52d761c-4c72-4261-be17-50d071bd5cc8} + + + {95e41110-57a2-497f-a938-b4c8e9dd6a27} + + + {cda27e9f-5763-4bf2-b6bc-85a377f7020e} + + + \ No newline at end of file diff --git a/profiler/CMakeLists.txt b/profiler/CMakeLists.txt new file mode 100644 index 0000000000..f3f9673dac --- /dev/null +++ b/profiler/CMakeLists.txt @@ -0,0 +1,11 @@ +set(SRCS + profiler.cpp +) + +# LGUIFileList.cpp + +add_library(profiler STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp new file mode 100644 index 0000000000..28d400cb99 --- /dev/null +++ b/profiler/profiler.cpp @@ -0,0 +1,84 @@ +// UNFINISHED but kinda working + +#include +#include +#include + +#include + +#include "base/logging.h" +#include "gfx_es2/draw_buffer.h" +#include "base/timeutil.h" + +using namespace std; + + +struct Section { + const char *name; + int level; + double start; + double end; +}; +static vector
current_frame; + +static double frame_start; +#define NUM_LEVELS 16 +static Section cur_section[NUM_LEVELS]; + +static int level; + +void _profiler_init() { + level = 0; +} + +void _profiler_enter(const char *section_name) { + cur_section[level].name = section_name; + cur_section[level].start = real_time_now(); + level++; +} + +void _profiler_leave(const char *section_name) { + --level; + cur_section[level].end = real_time_now(); + if (strcmp(section_name, cur_section[level].name)) { + FLOG("Can't enter %s when %s is active, only one at a time!", + section_name, cur_section[level].name); + } + cur_section[level].level = level; + current_frame.push_back(cur_section[level]); +} + +void _profiler_begin_frame() { + frame_start = real_time_now(); +} + +void _profiler_end_frame() { + current_frame.clear(); +} + +void _profiler_log() { + const char *spaces = " "; + ILOG("Profiler output ===================="); + for (int i = 0; i < (int)current_frame.size(); i++) { + double start = current_frame[i].start - frame_start; + double elapsed = current_frame[i].end - current_frame[i].start; + double start_ms = (start*1000); + double elapsed_ms = (elapsed*1000); + ILOG("%s%s: %0.3f ms", spaces + 15-current_frame[i].level, current_frame[i].name, elapsed_ms); + } +} + +void _profiler_draw(DrawBuffer *draw2d, int font) { + uint32_t colors[4] = { 0xFFc0a030, 0xFF30a0c0, 0xFF30C050, 0xFFc02080 }; + for (int i = 0; i < (int)current_frame.size(); i++) { + const Section §ion = current_frame[i]; + double start = section.start - frame_start; + double elapsed = section.end - current_frame[i].start; + + uint32_t color = colors[i&3]; + float y1 = i * 32, y2 = (i+1)*32; + float x1 = start / 0.0166666; + float x2 = (start + elapsed) / 0.01666666; + draw2d->Rect(x1, y1, x2, y2, color); + } +} diff --git a/profiler/profiler.h b/profiler/profiler.h new file mode 100644 index 0000000000..2eb52c6586 --- /dev/null +++ b/profiler/profiler.h @@ -0,0 +1,37 @@ +#pragma once + +// #define USE_PROFILER + +#ifdef USE_PROFILER + +class DrawBuffer; + +void _profiler_init(); +void _profiler_begin_frame(); +void _profiler_end_frame(); + +void _profiler_log(); +void _profiler_draw(DrawBuffer *draw2d, int font); + +void _profiler_enter(const char *section); +void _profiler_leave(const char *section); + +#define PROFILER_INIT() _profiler_init(); +#define PROFILER_ENTER(section) _profiler_enter(section); +#define PROFILER_LEAVE(section) _profiler_leave(section); +#define PROFILER_LOG() _profiler_log(); +#define PROFILER_DRAW(draw, font) _profiler_draw(draw, font); +#define PROFILER_BEGIN_FRAME() _profiler_begin_frame(); +#define PROFILER_END_FRAME() _profiler_end_frame(); + +#else + +#define PROFILER_INIT() +#define PROFILER_ENTER(section) +#define PROFILER_LEAVE(section) +#define PROFILER_LOG() +#define PROFILER_DRAW(draw, font) +#define PROFILER_BEGIN_FRAME() +#define PROFILER_END_FRAME() + +#endif diff --git a/util/bits/bits.cc b/util/bits/bits.cc new file mode 100644 index 0000000000..5267078abe --- /dev/null +++ b/util/bits/bits.cc @@ -0,0 +1,40 @@ +#include "util/bits/bits.h" + +namespace bits { + +// See http://graphics.stanford.edu/~seander/bithacks.html + +static const unsigned char BitsSetTable256[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 +}; + +int CountBits8(uint8 v) { + return BitsSetTable256[v]; +} + +int CountBits16(uint16 v) { + return BitsSetTable256[v & 0xFF] + BitsSetTable256[v >> 8]; +} + +int CountBits32(uint32 v) { + v = v - ((v >> 1) & 0x55555555); // reuse input as temporary + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count +} + +} // namespace bits diff --git a/util/bits/bits.h b/util/bits/bits.h new file mode 100644 index 0000000000..5afab5a8fe --- /dev/null +++ b/util/bits/bits.h @@ -0,0 +1,28 @@ +#ifndef _UTIL_BITS_BITS +#define _UTil_BITS_BITS + +#include "base/basictypes.h" + +namespace bits { + +int CountBits8(uint8 v); +int CountBits16(uint16 v); +int CountBits32(uint32 v); + +// where mask is 0, the result is a. +// where mask is 1, the result is b. +inline uint32 MixBits(uint32 a, uint32 b, uint32 mask) { + return a ^ ((a ^ b) & mask); +} + +inline uint32 ComputeParity(uint32 v) { + v ^= v >> 16; + v ^= v >> 8; + v ^= v >> 4; + v &= 0xf; + return (0x6996 >> v) & 1; +} + +} // namespace bits + +#endif diff --git a/util/bits/hamming.h b/util/bits/hamming.h new file mode 100644 index 0000000000..82217a8376 --- /dev/null +++ b/util/bits/hamming.h @@ -0,0 +1,27 @@ +#ifndef _UTIL_BITS_HAMMING +#define _UTIL_BITS_HAMMING + +#include + +#include "base/logging.h" + +inline int Hamming(const std::string &a, const std::string &b) { + CHECK_EQ(a.size(), b.size()); + int hamming = 0; + for (size_t i = 0; i < a.size(); i++) + hamming += a[i] == b[i]; + return hamming; +} + +inline int Hamming4(const std::string &a, const std::string &b) { + CHECK_EQ(a.size(), b.size()); + int hamming = 0; + const uint32 *au = (const uint32 *)a.data(); + const uint32 *bu = (const uint32 *)b.data(); + for (size_t i = 0; i < a.size() / 4; i++) + hamming += au[i] == bu[i]; + return hamming * 4; +} + + +#endif // _UTIL_BITS_HAMMING diff --git a/util/bits/varint.cc b/util/bits/varint.cc new file mode 100644 index 0000000000..8cd94d052c --- /dev/null +++ b/util/bits/varint.cc @@ -0,0 +1,35 @@ +#include "util/bits/varint.h" + +namespace varint { + +void Encode32(uint32 value, char **dest) { + // Simple varint + char *p = *dest; + while (value > 127) { + *p++ = (value & 127); + value >>= 7; + } + *p++ = value | 0x80; + *dest = p; +} + +uint32 Decode32(const char **ptr) { + uint32 value = 0; + const char *p = *ptr; + while (true) { + uint8 b = *p++; + if (b & 0x80) { + *ptr = p; + return value | (b & 0x7F); + } else { + value |= *p++; + value <<= 7; + } + } + *ptr = p; + return value; +} + +} // namespace varint + + diff --git a/util/bits/varint.h b/util/bits/varint.h new file mode 100644 index 0000000000..aa7d3e8788 --- /dev/null +++ b/util/bits/varint.h @@ -0,0 +1,13 @@ +#ifndef _UTIL_BITS_VARINT +#define _UTIL_BITS_VARINT + +#include "base/base.h" + +namespace varint { + +void Encode32(uint32 value, char **dest); +uint32 Decode32(const char **ptr); + +} // namespace varint + +#endif // _UTIL_BITS_VARINT diff --git a/util/build.scons b/util/build.scons new file mode 100644 index 0000000000..1f668a08f7 --- /dev/null +++ b/util/build.scons @@ -0,0 +1,20 @@ +# Bring in the environment to use for this component (boilerplate). +Import('env') + +# This is the list of input source files to the mandelbrot_gen library. Headers +# will be detected automatically. +inputs = ['hash/hash.cc', + 'hash/minhash.cc'] + +# Build these into a library. +env.ComponentLibrary('hash', inputs) + +inputs = ['bits/varint.cc', + 'bits/bits.cc' ] + +env.ComponentLibrary('bits', inputs) + +inputs = ['random/perlin.cc', + ] + +env.ComponentLibrary('random', inputs) diff --git a/util/hash/hash.cc b/util/hash/hash.cc new file mode 100644 index 0000000000..264450dabe --- /dev/null +++ b/util/hash/hash.cc @@ -0,0 +1,65 @@ +#include "base/base.h" +#include "util/hash/hash.h" + +namespace hash { + +// uint32_t +// WARNING - may read one more byte! +// Implementation from Wikipedia. +uint32 HashFletcher(const uint8 *data_uint8, size_t length) { + const uint16 *data = (const uint16 *)data_uint8; + size_t len = (length + 1) / 2; + uint32 sum1 = 0xffff, sum2 = 0xffff; + + while (len) { + size_t tlen = len > 360 ? 360 : len; + len -= tlen; + + do { + sum1 += *data++; + sum2 += sum1; + } while (--tlen); + + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + } + + /* Second reduction step to reduce sums to 16 bits */ + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + return sum2 << 16 | sum1; +} + +// Implementation from Wikipedia +// Slightly slower than Fletcher above, but slighly more reliable. +#define MOD_ADLER 65521 +// data: Pointer to the data to be summed; len is in bytes +uint32 HashAdler32(const uint8 *data, size_t len) { + uint32 a = 1, b = 0; + while (len) { + size_t tlen = len > 5550 ? 5550 : len; + len -= tlen; + do { + a += *data++; + b += a; + } while (--tlen); + + a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER); + b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); + } + + // It can be shown that a <= 0x1013a here, so a single subtract will do. + if (a >= MOD_ADLER) { + a -= MOD_ADLER; + } + + // It can be shown that b can reach 0xfff87 here. + b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); + + if (b >= MOD_ADLER) { + b -= MOD_ADLER; + } + return (b << 16) | a; +} + +} // namespace hash diff --git a/util/hash/hash.h b/util/hash/hash.h new file mode 100644 index 0000000000..3f80714185 --- /dev/null +++ b/util/hash/hash.h @@ -0,0 +1,30 @@ +#ifndef _UTIL_HASH_HASH_H +#define _UTIL_HASH_HASH_H + +#include + +#include "base/basictypes.h" + +namespace hash { + +uint32 Fletcher(const uint8 *data_u8, size_t length); // FAST. Length & 1 == 0. +uint32 Adler32(const uint8 *data, size_t len); // Fairly accurate, slightly slower + +// WTF is this for? +class ConsistentHasher { + public: + ConsistentHasher() { + // TODO: really need a better seed here. + uint32 orig_seed = rand(); + seed = Fletcher((const uint8 *)&orig_seed, 4); + } + uint32 Hash(uint32 value) { + return value ^ seed; + } + private: + uint32 seed; +}; + +} // namespace hash + +#endif diff --git a/util/random/perlin.cc b/util/random/perlin.cc new file mode 100644 index 0000000000..d0ee8a9fa4 --- /dev/null +++ b/util/random/perlin.cc @@ -0,0 +1,72 @@ +#include "util/random/perlin.h" + +#include + +// This should go in the const section of the binary. +static const int p[512] = { + 151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, + 151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, +}; + +inline float fade(float t) { + return t * t * t * (t * (t * 6 - 15) + 10); +} + +inline float lerp(float t, float a, float b) { + return a + t * (b - a); +} + +inline float grad(int hash, float x, float y, float z) { + int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE + float u = h < 8 ? x : y; // INTO 12 GRADIENT DIRECTIONS. + float v = h < 4 ? y : (h == 12 || h == 14 ? x : z); + return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); +} + +float Noise(double z, double y, double x) { + double fx = floor(x), fy = floor(y), fz = floor(z); + int X = (int)fx & 255, // FIND UNIT CUBE THAT + Y = (int)fy & 255, // CONTAINS POINT. + Z = (int)fz & 255; + x -= fx; // FIND RELATIVE X,Y,Z + y -= fy; // OF POINT IN CUBE. + z -= fz; + float u = fade(x); // COMPUTE FADE CURVES + float v = fade(y); // FOR EACH OF X,Y,Z. + float w = fade(z); + int A = p[X ]+Y, B = p[X+1]+Y; + int AA = p[A]+Z, AB = p[A+1]+Z; // HASH COORDINATES OF + int BA = p[B]+Z, BB = p[B+1]+Z; // THE 8 CUBE CORNERS, + return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD + grad(p[BA ], x-1, y , z )), // BLENDED + lerp(u, grad(p[AB ], x , y-1, z ), // RESULTS + grad(p[BB ], x-1, y-1, z ))), // FROM 8 + lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), // CORNERS + grad(p[BA+1], x-1, y , z-1 )), // OF CUBE + lerp(u, grad(p[AB+1], x , y-1, z-1 ), + grad(p[BB+1], x-1, y-1, z-1 )))); +} diff --git a/util/random/perlin.h b/util/random/perlin.h new file mode 100644 index 0000000000..ace8c521d3 --- /dev/null +++ b/util/random/perlin.h @@ -0,0 +1,8 @@ +#ifndef _PERLIN_H +#define _PERLIN_H + +// Implementation of "Improved Noise" +// http://mrl.nyu.edu/~perlin/noise/ +float Noise(double x, double y, double z); + +#endif // _PERLIN_H diff --git a/util/random/rng.h b/util/random/rng.h new file mode 100644 index 0000000000..28369196a6 --- /dev/null +++ b/util/random/rng.h @@ -0,0 +1,26 @@ +#ifndef _RNG_H +#define _RNG_H + +#include "base/basictypes.h" + +// George Marsaglia-style random number generator. +class GMRng { + public: + void Init(int seed) { + m_w = seed ^ (seed << 16); + if (!m_w) m_w = 1337; + m_z = ~seed; + if (!m_z) m_z = 31337; + } + uint32 R32() { + m_z = 36969 * (m_z & 65535) + (m_z >> 16); + m_w = 18000 * (m_w & 65535) + (m_w >> 16); + return (m_z << 16) + m_w; + } + + private: + uint32 m_w; + uint32 m_z; +}; + +#endif From 04b9e6d16cf6563bd3d80fa4548112666914a7cc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 25 Mar 2012 00:09:51 +0100 Subject: [PATCH 0002/1445] This shouldn't have been here. --- collision/collision.cpp | 4 ++-- native.vcxproj | 4 ---- native.vcxproj.filters | 12 ------------ 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/collision/collision.cpp b/collision/collision.cpp index b4993562e9..d019dd1b78 100644 --- a/collision/collision.cpp +++ b/collision/collision.cpp @@ -1,7 +1,7 @@ #include "base/logging.h" #include "math/lin/vec3.h" -#include "math/ray_intersections.h" -#include "collision/collision.h" +#include "ray_intersections.h" +#include "collision.h" #include diff --git a/native.vcxproj b/native.vcxproj index a03612b9a5..4b76b5a8c1 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -98,7 +98,6 @@ - @@ -131,7 +130,6 @@ - @@ -141,7 +139,6 @@ - @@ -174,7 +171,6 @@ - diff --git a/native.vcxproj.filters b/native.vcxproj.filters index d0b324b401..8f38a59f84 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -69,9 +69,6 @@ file - - collision - base @@ -93,9 +90,6 @@ math - - math - ext @@ -197,9 +191,6 @@ file - - collision - base @@ -212,9 +203,6 @@ math - - math - ext From 8c3a48df74dfb7d90b3340c55bdcd0adb402d9b2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 25 Mar 2012 00:13:34 +0100 Subject: [PATCH 0003/1445] Doesn't belong here either --- collision/CMakeLists.txt | 9 -- collision/collision.cpp | 288 --------------------------------------- collision/collision.h | 89 ------------ 3 files changed, 386 deletions(-) delete mode 100644 collision/CMakeLists.txt delete mode 100644 collision/collision.cpp delete mode 100644 collision/collision.h diff --git a/collision/CMakeLists.txt b/collision/CMakeLists.txt deleted file mode 100644 index 00af58df88..0000000000 --- a/collision/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(SRCS - collision.cpp - ) - -add_library(collision STATIC ${SRCS}) - -if(UNIX) - add_definitions(-fPIC) -endif(UNIX) diff --git a/collision/collision.cpp b/collision/collision.cpp deleted file mode 100644 index d019dd1b78..0000000000 --- a/collision/collision.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "base/logging.h" -#include "math/lin/vec3.h" -#include "ray_intersections.h" -#include "collision.h" - -#include - -// #define COLLISION_ENABLE_SCALING - -static std::string V(const Vec3 &v) { - char temp[100]; - sprintf(temp, "(%f %f %f)", v.x, v.y, v.z); - return std::string(temp); -} - -Collidable::Collidable() { -} - -Collidable::~Collidable() { -} - -void Collision::Init(const Vec3 &source, const Vec3 &dest, const Vec3 &size) { - this->size = size; - scale.Set(1.0f / size.x, 1.0f / size.y, 1.0f / size.z); - sourcePoint = source.scaledBy(scale); - - velocity = (dest - source).scaledBy(scale); - velocityLength = velocity.length(); - normalizedVelocity = velocity / velocityLength; - - stuck = false; - foundCollision = false; - nearestDistance = velocityLength; -} - -void Collision::BeginTransform(const Matrix4x4 &inverse, const Matrix4x4 &transform) { - this->transform = &transform; - untransformed_sourcePoint = sourcePoint; - untransformed_velocity = velocity; - - sourcePoint = sourcePoint * inverse; - velocity = velocity.rotatedBy(inverse); - - normalizedVelocity = untransformed_velocity.normalized(); -} - -void Collision::EndTransform() { - sourcePoint = untransformed_sourcePoint; - velocity = untransformed_velocity; - - normalizedVelocity = untransformed_velocity.normalized(); - this->transform = 0; -} - -bool Collision::registerCollision(float t, const Vec3 &polyIPoint) { - // Special handling for multiple contact points - if (t < 0.0f) { - return false; - } - Vec3 ipoint; - if (transform) ipoint = polyIPoint * (*transform); - else ipoint = polyIPoint; - - if (t >= -0.0001 && t <= 0.0001 && num_contact_points < MAX_CONTACT_POINTS) { - for (int i = 0; i < num_contact_points; i++) { - // Check if identical - can happen on dupe edges (which we'll later remove). - // TODO: Let's see if we can get rid of this fuzziness. - if (ipoint.distance2To(contact_points[i]) < 0.00001) - goto skip; - } - contact_points[num_contact_points++] = ipoint; - } -skip: - if ((t >= 0.0) && (t <= velocityLength) && (t <= this->nearestDistance)) { - // If we are hit we have a closest hit so far. We save the information - this->nearestDistance = t; - this->nearestPolygonIntersectionPoint = ipoint; - this->foundCollision = true; - //ILOG("Collision registered, t=%f", t); - return true; - } else { - // Already had a closer collision. - return false; - } -} - -bool Collision::Triangle(Vec3 p1, Vec3 p2, Vec3 p3) { - Vec3 pNormal = (p2 - p1) % (p3 - p1); - pNormal.normalize(); - return Triangle(p1, p2, p3, pNormal); -} - -bool Collision::Triangle(Vec3 p1, Vec3 p2, Vec3 p3, const Vec3 &pNormal) { -#ifdef COLLISION_ENABLE_SCALING - p1.scaleBy(scale); - p2.scaleBy(scale); - p3.scaleBy(scale); -#endif - - // Backface - // Early out optimization, lose a square root - if (dot(velocity, pNormal) >= 0.0f) - return false; - - // ILOG("normal. %s", V(pNormal).c_str()); - // find the plane intersection point - float t; - Vec3 polyIPoint, sIPoint = sourcePoint - pNormal; - if (pointPlaneDistance(sIPoint, p1, pNormal) > 0.0f) { - // Plane is embedded in ellipsoid. - // Find plane intersection point by shooting a ray from the sphere intersection - // point along the plane normal. - t = intersectRayPlanePerp(sIPoint, pNormal, p1); - polyIPoint = sIPoint + pNormal * t; // calculate plane intersection point - } else { - // shoot ray along the velocity vector - t = intersectRayPlane(sIPoint, normalizedVelocity, p1, pNormal); - if (t > velocityLength) { - // Did not hit plane. No point in doing triangle tests. - return false; - } - // calculate plane intersection point - polyIPoint = sIPoint + normalizedVelocity * t; - } - - if (isPointInTriangle(polyIPoint, p1, p2, p3)) { - // ILOG("Hit triangle! %s %s %s %s", V(polyIPoint).c_str(), V(p1).c_str(), V(p2).c_str(), V(p3).c_str()); - float depth2 = (polyIPoint - sourcePoint).length2(); - if (depth2 < 0.9999f) { - // Here we do the error checking to see if we got ourself stuck last frame - ELOG("Stuck in triangle! depth2 = %f", depth2); - // ILOG("%s %s %s", V(p1).c_str(), V(p2).c_str(), V(p3).c_str()); - stuck = true; - } - return registerCollision(t, polyIPoint); - } else { - // ILOG("Missed this triangle - returning"); - return false; - } -} - -bool Collision::EdgeLine(Vec3 p1, Vec3 p2) { - // This ellipsoid scaling stuff will result in the edge not being really cylindric. - // Should work for many purposes though. -#ifdef COLLISION_ENABLE_SCALING - p1.scaleBy(scale); - p2.scaleBy(scale); -#endif - float t = 1000000000.0; - Vec3 polyIPoint; - if (intersectCylinder(sourcePoint, normalizedVelocity, - p1, p2, &t, &polyIPoint)) { - polyIPoint = closestPointOnLine(p1, p2, polyIPoint); - return registerCollision(t, polyIPoint); - } else { - return false; - } -} - -bool Collision::Corner(Vec3 p1) { -#ifdef COLLISION_ENABLE_SCALING - p1.scaleBy(scale); -#endif - float t = intersectRayUnitSphere(sourcePoint, normalizedVelocity, p1); - if (t != -1.0f) { - return registerCollision(t, p1); - } else { - return false; - } -} - -bool Collision::Quad(const Vec3 &o, const Vec3 &dx, const Vec3 &dy) { - bool hit = Triangle(o, o + dx, o + dx + dy); - hit |= Triangle(o + dx + dy, o + dy, o); - return hit; -} - -bool Collide(Collision *collision, Collidable *scene, Vec3 *out) { - bool hit_anything = false; - collision->num_contact_points = 0; - collision->lastSafePosition = collision->sourcePoint; - // Process max 8 slides to have a limit if we get into an impossible situation. - int i = 0; - for (i = 0; i < 4; i++) { - // ILOG("Try %i! %s", i, V(collision->sourcePoint).c_str()); - scene->Collide(collision); - if (!collision->foundCollision) { - // Nothing left to do. - collision->sourcePoint += collision->velocity; - collision->velocity.setZero(); - break; - } - hit_anything = true; - if (collision->nearestDistance < 0.0f) { - ILOG("NegHit! %f %f", collision->velocityLength, collision->nearestDistance); - } else { - // ILOG("Hit! %f %f ", collision->velocityLength, collision->nearestDistance); - } - - Vec3 slidePlaneOrigin; - Vec3 slidePlaneNormal; - Vec3 newSourcePoint = collision->sourcePoint; - - float adjusted_hit_distance = collision->nearestDistance - 0.0001f; - if (adjusted_hit_distance < 0) adjusted_hit_distance = 0; - - // Two cases - one where we have multiple contact points, one where we don't. - if (collision->num_contact_points > 1) { - ILOG("Resolve %i-ary collision, velocityLength = %f", - collision->num_contact_points, collision->velocity.length()); - Vec3 avg_contact(0,0,0); - for (int i = 0; i < collision->num_contact_points; i++) { - ILOG("Contact point %s", V(collision->contact_points[i]).c_str()); - avg_contact += collision->contact_points[i]; - } - avg_contact /= (float)collision->num_contact_points; - - // The average of the contact points should be inside the sphere. - float dist = sqrt(avg_contact.distance2To(collision->sourcePoint)); - if (dist > 1.0) { - ILOG("Bogus contact points, for sure: %s vs %s, dist=%f", V(avg_contact).c_str(), V(collision->sourcePoint).c_str(), dist); - } - - Vec3 avg_contact_dir = avg_contact - collision->sourcePoint; - avg_contact_dir.normalize(); - avg_contact = collision->sourcePoint + avg_contact_dir; - - newSourcePoint += collision->normalizedVelocity * adjusted_hit_distance; - slidePlaneOrigin = avg_contact; - slidePlaneNormal = (newSourcePoint - slidePlaneOrigin).normalized(); - - // Push the ball out a bit along the normal to avoid re-collision. - newSourcePoint += slidePlaneNormal * 0.01f; - //collision->velocity += slidePlaneNormal * 0.01; - - //slidePlaneNormal = avg_contact_dir; - } else { - // LOG(INFO) << "Adjusting newsourcepoint to end of collision"; - newSourcePoint += collision->normalizedVelocity * adjusted_hit_distance; - // LOG(INFO) << "s: " << V(collision->sourcePoint); - // LOG(INFO) << "nsp: " << V(newSourcePoint); - // LOG(INFO) << "ip: " << V(collision->nearestPolygonIntersectionPoint); - - // Now we must calculate the sliding plane - slidePlaneOrigin = collision->nearestPolygonIntersectionPoint; - slidePlaneNormal = (newSourcePoint - slidePlaneOrigin).normalized(); - } - - // We now project the destination point onto the sliding plane - Vec3 destinationPoint = collision->sourcePoint + collision->velocity; - float l = intersectRayPlane(destinationPoint, slidePlaneNormal, - slidePlaneOrigin, -slidePlaneNormal); - - // We can now calculate a new destination point on the sliding plane - Vec3 newDestinationPoint = destinationPoint + slidePlaneNormal * l; - - // now we start over with the new position and velocity - - collision->sourcePoint = newSourcePoint; - // Generate the slide vector, which will become our new velocity vector - Vec3 slide = newDestinationPoint - slidePlaneOrigin; - slide += slidePlaneNormal * 0.0001f; - - // LOG(INFO) << "NDP: " << V(newDestinationPoint); - // ILOG("Slide: %s", V(slide).c_str()); - // Recompute to get ready! - collision->velocity = slide; - collision->velocityLength = collision->velocity.length(); - if (collision->velocityLength <= 0.0002) { - //ILOG("Zero-length velocity vector. Break."); - collision->velocity.setZero(); - break; - } else { - // ILOG("Velocity: %s", V(collision->velocity).c_str()); - } - collision->nearestDistance = collision->velocityLength; - collision->normalizedVelocity = collision->velocity / collision->velocityLength; - } - //ILOG("%i tries", i); - - *out = collision->sourcePoint.scaledBy(collision->size); - if (collision->stuck) { - //ILOG("Stuck - resetting"); - // *out = collision->lastSafePosition.scaledBy(collision->size); - } - return hit_anything; -} - diff --git a/collision/collision.h b/collision/collision.h deleted file mode 100644 index 2ff5ba1d47..0000000000 --- a/collision/collision.h +++ /dev/null @@ -1,89 +0,0 @@ -// Collision detection engine. You pass in a class representing a scene, -// and out comes a nice FPS-like "sliding physics" response. - -// By hrydgard@gmail.com, - - -#ifndef _COLLISION_H -#define _COLLISION_H - -#include "math/lin/vec3.h" -#include "math/lin/matrix4x4.h" - -class Collision; - -class Collidable { - public: - Collidable(); - virtual ~Collidable(); - // Apply the collision functions to collision as appropriate. - virtual void Collide(Collision *collision) = 0; -}; - -class Collision { - public: - void Init(const Vec3 &source, const Vec3 &dest, const Vec3 &size); - - // Collision functions - // These should be called from Collidable::Collide and nowhere else - // except the unit test. - - // To correctly collide with meshes, just apply these in sequence. You MUST - // collide against all external (convex) edges, otherwise you can get - // quite stuck. There's PLENTY of optimization to do here. - - bool Triangle(Vec3 p1, Vec3 p2, Vec3 p3); - bool Triangle(Vec3 p1, Vec3 p2, Vec3 p3, const Vec3 &normal); - bool EdgeLine(Vec3 p1, Vec3 p2); // Cylinder - bool Quad(const Vec3 &origin, const Vec3 &dX, const Vec3 &dY); - bool UnitCube(const Vec3 &origin); - bool Corner(Vec3 p1); // Sphere - bool Corners(Vec3 *p, int count); - - // There's an opportunity to provide hyper optimized versions of - // Edge for axis aligned edges. The cylinder intersection becomes trivial. - - // These cannot be nested! - void BeginTransform(const Matrix4x4 &inverse, const Matrix4x4 &transform); - void EndTransform(); - - private: - bool registerCollision(float t, const Vec3 &polyIPoint); - - public: - Vec3 sourcePoint; - - float velocityLength; - - Vec3 size; - Vec3 scale; - Vec3 velocity; // data about player movement - Vec3 normalizedVelocity; - - Vec3 lastSafePosition; // for error handling - bool stuck; - // data for collision response - bool foundCollision; - float nearestDistance; // nearest distance to hit - Vec3 nearestPolygonIntersectionPoint; // on polygon - - const Matrix4x4 *transform; - - // Saved state during transformed operation - Vec3 untransformed_sourcePoint; - Vec3 untransformed_velocity; - - enum { - MAX_CONTACT_POINTS = 10 - }; - Vec3 contact_points[MAX_CONTACT_POINTS]; - int num_contact_points; -}; - -// Sliding physics. -bool Collide(Collision *collision, Collidable *scene, Vec3 *out); - -// Bouncy physics -// void CollideBouncy( ... ) - -#endif // _COLLISION_H From 2e561248b861ddbdc79337e4c9bffa523b765829 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 27 Mar 2012 22:54:58 +0200 Subject: [PATCH 0004/1445] parseHex --- base/stringutil.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ base/stringutil.h | 5 ++++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 base/stringutil.cpp diff --git a/base/stringutil.cpp b/base/stringutil.cpp new file mode 100644 index 0000000000..3e977ba9b6 --- /dev/null +++ b/base/stringutil.cpp @@ -0,0 +1,41 @@ +#include +#include "base/stringutil.h" + +unsigned int parseHex(const char *_szValue) +{ + DWORD Count, Value = 0; + size_t Finish = strlen(_szValue); + if (Finish > 8 ) { Finish = 8; } + + for (Count = 0; Count < Finish; Count++) { + Value = (Value << 4); + switch( _szValue[Count] ) { + case '0': break; + case '1': Value += 1; break; + case '2': Value += 2; break; + case '3': Value += 3; break; + case '4': Value += 4; break; + case '5': Value += 5; break; + case '6': Value += 6; break; + case '7': Value += 7; break; + case '8': Value += 8; break; + case '9': Value += 9; break; + case 'A': Value += 10; break; + case 'a': Value += 10; break; + case 'B': Value += 11; break; + case 'b': Value += 11; break; + case 'C': Value += 12; break; + case 'c': Value += 12; break; + case 'D': Value += 13; break; + case 'd': Value += 13; break; + case 'E': Value += 14; break; + case 'e': Value += 14; break; + case 'F': Value += 15; break; + case 'f': Value += 15; break; + default: + Value = (Value >> 4); + Count = Finish; + } + } + return Value; +} \ No newline at end of file diff --git a/base/stringutil.h b/base/stringutil.h index e5dfa87923..17048fd05f 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -15,4 +15,7 @@ public: inline bool endsWith(const std::string &str, const std::string &what) { return str.substr(str.size() - what.size()) == what; -} \ No newline at end of file +} + +// highly unsafe and not recommended. +unsigned int parseHex(const char* _szValue); \ No newline at end of file From 315e22568452b77c9e779f30195675c8d6becbbd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 27 Mar 2012 23:25:04 +0200 Subject: [PATCH 0005/1445] Add glew --- .gitignore | 3 + README.md | 17 +- ext/glew/GL/glew.h | 15507 +++++++++++++++++++++++++++++++++++++++ ext/glew/GL/glxew.h | 1568 ++++ ext/glew/GL/wglew.h | 1361 ++++ ext/glew/glew.c | 15485 ++++++++++++++++++++++++++++++++++++++ ext/glew/glewinfo.c | 9081 +++++++++++++++++++++++ ext/glew/visualinfo.c | 1176 +++ json/json_writer.h | 9 +- native.vcxproj | 6 +- native.vcxproj.filters | 2 +- 11 files changed, 44208 insertions(+), 7 deletions(-) create mode 100644 .gitignore create mode 100644 ext/glew/GL/glew.h create mode 100644 ext/glew/GL/glxew.h create mode 100644 ext/glew/GL/wglew.h create mode 100644 ext/glew/glew.c create mode 100644 ext/glew/glewinfo.c create mode 100644 ext/glew/visualinfo.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..9e9e916ebb --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +Release +Debug +*.vcxproj.user diff --git a/README.md b/README.md index e19503015c..1dc72121f6 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,23 @@ native This is my library of stuff that I use when writing C++ programs, mostly for Android. It has some basic OpenGL utility code, JSON read/write (two libraries that should be made more similar), 2D texture atlases and drawing code, ETC1 texture loading support, basic logging, etc. The associated tools to create ZIM texture files and atlases do not yet live here but I might move them here eventually. + +This project incorporates code from a variety of public domain or similarly-licensed code. This is the list: + +etcpack by Ericsson, in a cleaned up form. public domain? +sha1, public domain implementation by Dominik Reichl +json_writer by me (Henrik Rydgård) +vjson in a heavily modified form, originally by ??? (TODO) +libzip with attribution "Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner" +stb_vorbis, public domain by Sean Barrett of RAD Tools + +If you're not okay with the licenses above, don't use this code. + If you find this useful for your own projects, drop me a line at hrydgard@gmail.com . -I hereby release this code under the BSD license. +I hereby release all code here not under the licenses above to the public domain. Henrik Rydgård + + + diff --git a/ext/glew/GL/glew.h b/ext/glew/GL/glew.h new file mode 100644 index 0000000000..f70103d118 --- /dev/null +++ b/ext/glew/GL/glew.h @@ -0,0 +1,15507 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __glew_h__ +#define __glew_h__ +#define __GLEW_H__ + +#if defined(__gl_h_) || defined(__GL_H__) || defined(__X_GL_H) +#error gl.h included before glew.h +#endif +#if defined(__glext_h_) || defined(__GLEXT_H_) +#error glext.h included before glew.h +#endif +#if defined(__gl_ATI_h_) +#error glATI.h included before glew.h +#endif + +#define __gl_h_ +#define __GL_H__ +#define __X_GL_H +#define __glext_h_ +#define __GLEXT_H_ +#define __gl_ATI_h_ + +#if defined(_WIN32) + +/* + * GLEW does not include to avoid name space pollution. + * GL needs GLAPI and GLAPIENTRY, GLU needs APIENTRY, CALLBACK, and wchar_t + * defined properly. + */ +/* */ +#ifndef APIENTRY +#define GLEW_APIENTRY_DEFINED +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define APIENTRY __stdcall +# elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +#endif +#ifndef GLAPI +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define GLAPI extern +# endif +#endif +/* */ +#ifndef CALLBACK +#define GLEW_CALLBACK_DEFINED +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define CALLBACK __attribute__ ((__stdcall__)) +# elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +#endif +/* and */ +#ifndef WINGDIAPI +#define GLEW_WINGDIAPI_DEFINED +#define WINGDIAPI __declspec(dllimport) +#endif +/* */ +#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(_WCHAR_T_DEFINED) +typedef unsigned short wchar_t; +# define _WCHAR_T_DEFINED +#endif +/* */ +#if !defined(_W64) +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && defined(_MSC_VER) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif +#if !defined(_PTRDIFF_T_DEFINED) && !defined(_PTRDIFF_T_) && !defined(__MINGW64__) +# ifdef _WIN64 +typedef __int64 ptrdiff_t; +# else +typedef _W64 int ptrdiff_t; +# endif +# define _PTRDIFF_T_DEFINED +# define _PTRDIFF_T_ +#endif + +#ifndef GLAPI +# if defined(__MINGW32__) || defined(__CYGWIN__) +# define GLAPI extern +# else +# define GLAPI WINGDIAPI +# endif +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY APIENTRY +#endif + +/* + * GLEW_STATIC is defined for static library. + * GLEW_BUILD is defined for building the DLL library. + */ + +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# ifdef GLEW_BUILD +# define GLEWAPI extern __declspec(dllexport) +# else +# define GLEWAPI extern __declspec(dllimport) +# endif +#endif + +#else /* _UNIX */ + +/* + * Needed for ptrdiff_t in turn needed by VBO. This is defined by ISO + * C. On my system, this amounts to _3 lines_ of included code, all of + * them pretty much harmless. If you know of a way of detecting 32 vs + * 64 _targets_ at compile time you are free to replace this with + * something that's portable. For now, _this_ is the portable solution. + * (mem, 2004-01-04) + */ + +#include + +/* SGI MIPSPro doesn't like stdint.h in C++ mode */ + +#if defined(__sgi) && !defined(__GNUC__) +#include +#else +#include +#endif + +#define GLEW_APIENTRY_DEFINED +#define APIENTRY + +/* + * GLEW_STATIC is defined for static library. + */ + +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# if defined(__GNUC__) && __GNUC__>=4 +# define GLEWAPI extern __attribute__ ((visibility("default"))) +# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# define GLEWAPI extern __global +# else +# define GLEWAPI extern +# endif +#endif + +/* */ +#ifndef GLAPI +#define GLAPI extern +#endif +#ifndef GLAPIENTRY +#define GLAPIENTRY +#endif + +#endif /* _WIN32 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------- GL_VERSION_1_1 ---------------------------- */ + +#ifndef GL_VERSION_1_1 +#define GL_VERSION_1_1 1 + +typedef unsigned int GLenum; +typedef unsigned int GLbitfield; +typedef unsigned int GLuint; +typedef int GLint; +typedef int GLsizei; +typedef unsigned char GLboolean; +typedef signed char GLbyte; +typedef short GLshort; +typedef unsigned char GLubyte; +typedef unsigned short GLushort; +typedef unsigned long GLulong; +typedef float GLfloat; +typedef float GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef void GLvoid; +#if defined(_MSC_VER) && _MSC_VER < 1400 +typedef __int64 GLint64EXT; +typedef unsigned __int64 GLuint64EXT; +#elif defined(_MSC_VER) || defined(__BORLANDC__) +typedef signed long long GLint64EXT; +typedef unsigned long long GLuint64EXT; +#else +# if defined(__MINGW32__) || defined(__CYGWIN__) +#include +# endif +typedef int64_t GLint64EXT; +typedef uint64_t GLuint64EXT; +#endif +typedef GLint64EXT GLint64; +typedef GLuint64EXT GLuint64; +typedef struct __GLsync *GLsync; + +typedef char GLchar; + +#define GL_ZERO 0 +#define GL_FALSE 0 +#define GL_LOGIC_OP 0x0BF1 +#define GL_NONE 0 +#define GL_TEXTURE_COMPONENTS 0x1003 +#define GL_NO_ERROR 0 +#define GL_POINTS 0x0000 +#define GL_CURRENT_BIT 0x00000001 +#define GL_TRUE 1 +#define GL_ONE 1 +#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_POINT_BIT 0x00000002 +#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 +#define GL_LINE_STRIP 0x0003 +#define GL_LINE_BIT 0x00000004 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_QUADS 0x0007 +#define GL_QUAD_STRIP 0x0008 +#define GL_POLYGON_BIT 0x00000008 +#define GL_POLYGON 0x0009 +#define GL_POLYGON_STIPPLE_BIT 0x00000010 +#define GL_PIXEL_MODE_BIT 0x00000020 +#define GL_LIGHTING_BIT 0x00000040 +#define GL_FOG_BIT 0x00000080 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_ACCUM 0x0100 +#define GL_LOAD 0x0101 +#define GL_RETURN 0x0102 +#define GL_MULT 0x0103 +#define GL_ADD 0x0104 +#define GL_NEVER 0x0200 +#define GL_ACCUM_BUFFER_BIT 0x00000200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_AUX0 0x0409 +#define GL_AUX1 0x040A +#define GL_AUX2 0x040B +#define GL_AUX3 0x040C +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_2D 0x0600 +#define GL_3D 0x0601 +#define GL_3D_COLOR 0x0602 +#define GL_3D_COLOR_TEXTURE 0x0603 +#define GL_4D_COLOR_TEXTURE 0x0604 +#define GL_PASS_THROUGH_TOKEN 0x0700 +#define GL_POINT_TOKEN 0x0701 +#define GL_LINE_TOKEN 0x0702 +#define GL_POLYGON_TOKEN 0x0703 +#define GL_BITMAP_TOKEN 0x0704 +#define GL_DRAW_PIXEL_TOKEN 0x0705 +#define GL_COPY_PIXEL_TOKEN 0x0706 +#define GL_LINE_RESET_TOKEN 0x0707 +#define GL_EXP 0x0800 +#define GL_VIEWPORT_BIT 0x00000800 +#define GL_EXP2 0x0801 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_COEFF 0x0A00 +#define GL_ORDER 0x0A01 +#define GL_DOMAIN 0x0A02 +#define GL_CURRENT_COLOR 0x0B00 +#define GL_CURRENT_INDEX 0x0B01 +#define GL_CURRENT_NORMAL 0x0B02 +#define GL_CURRENT_TEXTURE_COORDS 0x0B03 +#define GL_CURRENT_RASTER_COLOR 0x0B04 +#define GL_CURRENT_RASTER_INDEX 0x0B05 +#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 +#define GL_CURRENT_RASTER_POSITION 0x0B07 +#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 +#define GL_CURRENT_RASTER_DISTANCE 0x0B09 +#define GL_POINT_SMOOTH 0x0B10 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_STIPPLE 0x0B24 +#define GL_LINE_STIPPLE_PATTERN 0x0B25 +#define GL_LINE_STIPPLE_REPEAT 0x0B26 +#define GL_LIST_MODE 0x0B30 +#define GL_MAX_LIST_NESTING 0x0B31 +#define GL_LIST_BASE 0x0B32 +#define GL_LIST_INDEX 0x0B33 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_STIPPLE 0x0B42 +#define GL_EDGE_FLAG 0x0B43 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_LIGHTING 0x0B50 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_SHADE_MODEL 0x0B54 +#define GL_COLOR_MATERIAL_FACE 0x0B55 +#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_FOG 0x0B60 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_COLOR 0x0B66 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_ACCUM_CLEAR_VALUE 0x0B80 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_MATRIX_MODE 0x0BA0 +#define GL_NORMALIZE 0x0BA1 +#define GL_VIEWPORT 0x0BA2 +#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 +#define GL_PROJECTION_STACK_DEPTH 0x0BA4 +#define GL_TEXTURE_STACK_DEPTH 0x0BA5 +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_ATTRIB_STACK_DEPTH 0x0BB0 +#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 +#define GL_ALPHA_TEST 0x0BC0 +#define GL_ALPHA_TEST_FUNC 0x0BC1 +#define GL_ALPHA_TEST_REF 0x0BC2 +#define GL_DITHER 0x0BD0 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND 0x0BE2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_INDEX_LOGIC_OP 0x0BF1 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_AUX_BUFFERS 0x0C00 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_READ_BUFFER 0x0C02 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_INDEX_CLEAR_VALUE 0x0C20 +#define GL_INDEX_WRITEMASK 0x0C21 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_INDEX_MODE 0x0C30 +#define GL_RGBA_MODE 0x0C31 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_RENDER_MODE 0x0C40 +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_FOG_HINT 0x0C54 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_Q 0x0C63 +#define GL_PIXEL_MAP_I_TO_I 0x0C70 +#define GL_PIXEL_MAP_S_TO_S 0x0C71 +#define GL_PIXEL_MAP_I_TO_R 0x0C72 +#define GL_PIXEL_MAP_I_TO_G 0x0C73 +#define GL_PIXEL_MAP_I_TO_B 0x0C74 +#define GL_PIXEL_MAP_I_TO_A 0x0C75 +#define GL_PIXEL_MAP_R_TO_R 0x0C76 +#define GL_PIXEL_MAP_G_TO_G 0x0C77 +#define GL_PIXEL_MAP_B_TO_B 0x0C78 +#define GL_PIXEL_MAP_A_TO_A 0x0C79 +#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 +#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 +#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 +#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 +#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 +#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 +#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 +#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 +#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 +#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAP_COLOR 0x0D10 +#define GL_MAP_STENCIL 0x0D11 +#define GL_INDEX_SHIFT 0x0D12 +#define GL_INDEX_OFFSET 0x0D13 +#define GL_RED_SCALE 0x0D14 +#define GL_RED_BIAS 0x0D15 +#define GL_ZOOM_X 0x0D16 +#define GL_ZOOM_Y 0x0D17 +#define GL_GREEN_SCALE 0x0D18 +#define GL_GREEN_BIAS 0x0D19 +#define GL_BLUE_SCALE 0x0D1A +#define GL_BLUE_BIAS 0x0D1B +#define GL_ALPHA_SCALE 0x0D1C +#define GL_ALPHA_BIAS 0x0D1D +#define GL_DEPTH_SCALE 0x0D1E +#define GL_DEPTH_BIAS 0x0D1F +#define GL_MAX_EVAL_ORDER 0x0D30 +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 +#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_NAME_STACK_DEPTH 0x0D37 +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_INDEX_BITS 0x0D51 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_ACCUM_RED_BITS 0x0D58 +#define GL_ACCUM_GREEN_BITS 0x0D59 +#define GL_ACCUM_BLUE_BITS 0x0D5A +#define GL_ACCUM_ALPHA_BITS 0x0D5B +#define GL_NAME_STACK_DEPTH 0x0D70 +#define GL_AUTO_NORMAL 0x0D80 +#define GL_MAP1_COLOR_4 0x0D90 +#define GL_MAP1_INDEX 0x0D91 +#define GL_MAP1_NORMAL 0x0D92 +#define GL_MAP1_TEXTURE_COORD_1 0x0D93 +#define GL_MAP1_TEXTURE_COORD_2 0x0D94 +#define GL_MAP1_TEXTURE_COORD_3 0x0D95 +#define GL_MAP1_TEXTURE_COORD_4 0x0D96 +#define GL_MAP1_VERTEX_3 0x0D97 +#define GL_MAP1_VERTEX_4 0x0D98 +#define GL_MAP2_COLOR_4 0x0DB0 +#define GL_MAP2_INDEX 0x0DB1 +#define GL_MAP2_NORMAL 0x0DB2 +#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 +#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 +#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 +#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 +#define GL_MAP2_VERTEX_3 0x0DB7 +#define GL_MAP2_VERTEX_4 0x0DB8 +#define GL_MAP1_GRID_DOMAIN 0x0DD0 +#define GL_MAP1_GRID_SEGMENTS 0x0DD1 +#define GL_MAP2_GRID_DOMAIN 0x0DD2 +#define GL_MAP2_GRID_SEGMENTS 0x0DD3 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 +#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 +#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 +#define GL_SELECTION_BUFFER_POINTER 0x0DF3 +#define GL_SELECTION_BUFFER_SIZE 0x0DF4 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TRANSFORM_BIT 0x00001000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_BORDER 0x1005 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_AMBIENT 0x1200 +#define GL_DIFFUSE 0x1201 +#define GL_SPECULAR 0x1202 +#define GL_POSITION 0x1203 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_QUADRATIC_ATTENUATION 0x1209 +#define GL_COMPILE 0x1300 +#define GL_COMPILE_AND_EXECUTE 0x1301 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_2_BYTES 0x1407 +#define GL_3_BYTES 0x1408 +#define GL_4_BYTES 0x1409 +#define GL_DOUBLE 0x140A +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F +#define GL_EMISSION 0x1600 +#define GL_SHININESS 0x1601 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_COLOR_INDEXES 0x1603 +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_COLOR_INDEX 0x1900 +#define GL_STENCIL_INDEX 0x1901 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_BITMAP 0x1A00 +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_RENDER 0x1C00 +#define GL_FEEDBACK 0x1C01 +#define GL_SELECT 0x1C02 +#define GL_FLAT 0x1D00 +#define GL_SMOOTH 0x1D01 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_S 0x2000 +#define GL_ENABLE_BIT 0x00002000 +#define GL_T 0x2001 +#define GL_R 0x2002 +#define GL_Q 0x2003 +#define GL_MODULATE 0x2100 +#define GL_DECAL 0x2101 +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_ENV_COLOR 0x2201 +#define GL_TEXTURE_ENV 0x2300 +#define GL_EYE_LINEAR 0x2400 +#define GL_OBJECT_LINEAR 0x2401 +#define GL_SPHERE_MAP 0x2402 +#define GL_TEXTURE_GEN_MODE 0x2500 +#define GL_OBJECT_PLANE 0x2501 +#define GL_EYE_PLANE 0x2502 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_CLAMP 0x2900 +#define GL_REPEAT 0x2901 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_R3_G3_B2 0x2A10 +#define GL_V2F 0x2A20 +#define GL_V3F 0x2A21 +#define GL_C4UB_V2F 0x2A22 +#define GL_C4UB_V3F 0x2A23 +#define GL_C3F_V3F 0x2A24 +#define GL_N3F_V3F 0x2A25 +#define GL_C4F_N3F_V3F 0x2A26 +#define GL_T2F_V3F 0x2A27 +#define GL_T4F_V4F 0x2A28 +#define GL_T2F_C4UB_V3F 0x2A29 +#define GL_T2F_C3F_V3F 0x2A2A +#define GL_T2F_N3F_V3F 0x2A2B +#define GL_T2F_C4F_N3F_V3F 0x2A2C +#define GL_T4F_C4F_N3F_V4F 0x2A2D +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 +#define GL_LIGHT0 0x4000 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 +#define GL_HINT_BIT 0x00008000 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_ALPHA4 0x803B +#define GL_ALPHA8 0x803C +#define GL_ALPHA12 0x803D +#define GL_ALPHA16 0x803E +#define GL_LUMINANCE4 0x803F +#define GL_LUMINANCE8 0x8040 +#define GL_LUMINANCE12 0x8041 +#define GL_LUMINANCE16 0x8042 +#define GL_LUMINANCE4_ALPHA4 0x8043 +#define GL_LUMINANCE6_ALPHA2 0x8044 +#define GL_LUMINANCE8_ALPHA8 0x8045 +#define GL_LUMINANCE12_ALPHA4 0x8046 +#define GL_LUMINANCE12_ALPHA12 0x8047 +#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_INTENSITY 0x8049 +#define GL_INTENSITY4 0x804A +#define GL_INTENSITY8 0x804B +#define GL_INTENSITY12 0x804C +#define GL_INTENSITY16 0x804D +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE 0x8061 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_TEXTURE_PRIORITY 0x8066 +#define GL_TEXTURE_RESIDENT 0x8067 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_VERTEX_ARRAY 0x8074 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_COLOR_ARRAY 0x8076 +#define GL_INDEX_ARRAY 0x8077 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_EDGE_FLAG_ARRAY 0x8079 +#define GL_VERTEX_ARRAY_SIZE 0x807A +#define GL_VERTEX_ARRAY_TYPE 0x807B +#define GL_VERTEX_ARRAY_STRIDE 0x807C +#define GL_NORMAL_ARRAY_TYPE 0x807E +#define GL_NORMAL_ARRAY_STRIDE 0x807F +#define GL_COLOR_ARRAY_SIZE 0x8081 +#define GL_COLOR_ARRAY_TYPE 0x8082 +#define GL_COLOR_ARRAY_STRIDE 0x8083 +#define GL_INDEX_ARRAY_TYPE 0x8085 +#define GL_INDEX_ARRAY_STRIDE 0x8086 +#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C +#define GL_VERTEX_ARRAY_POINTER 0x808E +#define GL_NORMAL_ARRAY_POINTER 0x808F +#define GL_COLOR_ARRAY_POINTER 0x8090 +#define GL_INDEX_ARRAY_POINTER 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_EVAL_BIT 0x00010000 +#define GL_LIST_BIT 0x00020000 +#define GL_TEXTURE_BIT 0x00040000 +#define GL_SCISSOR_BIT 0x00080000 +#define GL_ALL_ATTRIB_BITS 0x000fffff +#define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff + +GLAPI void GLAPIENTRY glAccum (GLenum op, GLfloat value); +GLAPI void GLAPIENTRY glAlphaFunc (GLenum func, GLclampf ref); +GLAPI GLboolean GLAPIENTRY glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences); +GLAPI void GLAPIENTRY glArrayElement (GLint i); +GLAPI void GLAPIENTRY glBegin (GLenum mode); +GLAPI void GLAPIENTRY glBindTexture (GLenum target, GLuint texture); +GLAPI void GLAPIENTRY glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +GLAPI void GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GLAPI void GLAPIENTRY glCallList (GLuint list); +GLAPI void GLAPIENTRY glCallLists (GLsizei n, GLenum type, const GLvoid *lists); +GLAPI void GLAPIENTRY glClear (GLbitfield mask); +GLAPI void GLAPIENTRY glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GLAPI void GLAPIENTRY glClearDepth (GLclampd depth); +GLAPI void GLAPIENTRY glClearIndex (GLfloat c); +GLAPI void GLAPIENTRY glClearStencil (GLint s); +GLAPI void GLAPIENTRY glClipPlane (GLenum plane, const GLdouble *equation); +GLAPI void GLAPIENTRY glColor3b (GLbyte red, GLbyte green, GLbyte blue); +GLAPI void GLAPIENTRY glColor3bv (const GLbyte *v); +GLAPI void GLAPIENTRY glColor3d (GLdouble red, GLdouble green, GLdouble blue); +GLAPI void GLAPIENTRY glColor3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glColor3f (GLfloat red, GLfloat green, GLfloat blue); +GLAPI void GLAPIENTRY glColor3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glColor3i (GLint red, GLint green, GLint blue); +GLAPI void GLAPIENTRY glColor3iv (const GLint *v); +GLAPI void GLAPIENTRY glColor3s (GLshort red, GLshort green, GLshort blue); +GLAPI void GLAPIENTRY glColor3sv (const GLshort *v); +GLAPI void GLAPIENTRY glColor3ub (GLubyte red, GLubyte green, GLubyte blue); +GLAPI void GLAPIENTRY glColor3ubv (const GLubyte *v); +GLAPI void GLAPIENTRY glColor3ui (GLuint red, GLuint green, GLuint blue); +GLAPI void GLAPIENTRY glColor3uiv (const GLuint *v); +GLAPI void GLAPIENTRY glColor3us (GLushort red, GLushort green, GLushort blue); +GLAPI void GLAPIENTRY glColor3usv (const GLushort *v); +GLAPI void GLAPIENTRY glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +GLAPI void GLAPIENTRY glColor4bv (const GLbyte *v); +GLAPI void GLAPIENTRY glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +GLAPI void GLAPIENTRY glColor4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void GLAPIENTRY glColor4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glColor4i (GLint red, GLint green, GLint blue, GLint alpha); +GLAPI void GLAPIENTRY glColor4iv (const GLint *v); +GLAPI void GLAPIENTRY glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha); +GLAPI void GLAPIENTRY glColor4sv (const GLshort *v); +GLAPI void GLAPIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +GLAPI void GLAPIENTRY glColor4ubv (const GLubyte *v); +GLAPI void GLAPIENTRY glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha); +GLAPI void GLAPIENTRY glColor4uiv (const GLuint *v); +GLAPI void GLAPIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha); +GLAPI void GLAPIENTRY glColor4usv (const GLushort *v); +GLAPI void GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GLAPI void GLAPIENTRY glColorMaterial (GLenum face, GLenum mode); +GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +GLAPI void GLAPIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void GLAPIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void GLAPIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void GLAPIENTRY glCullFace (GLenum mode); +GLAPI void GLAPIENTRY glDeleteLists (GLuint list, GLsizei range); +GLAPI void GLAPIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); +GLAPI void GLAPIENTRY glDepthFunc (GLenum func); +GLAPI void GLAPIENTRY glDepthMask (GLboolean flag); +GLAPI void GLAPIENTRY glDepthRange (GLclampd zNear, GLclampd zFar); +GLAPI void GLAPIENTRY glDisable (GLenum cap); +GLAPI void GLAPIENTRY glDisableClientState (GLenum array); +GLAPI void GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GLAPI void GLAPIENTRY glDrawBuffer (GLenum mode); +GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +GLAPI void GLAPIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glEdgeFlag (GLboolean flag); +GLAPI void GLAPIENTRY glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glEdgeFlagv (const GLboolean *flag); +GLAPI void GLAPIENTRY glEnable (GLenum cap); +GLAPI void GLAPIENTRY glEnableClientState (GLenum array); +GLAPI void GLAPIENTRY glEnd (void); +GLAPI void GLAPIENTRY glEndList (void); +GLAPI void GLAPIENTRY glEvalCoord1d (GLdouble u); +GLAPI void GLAPIENTRY glEvalCoord1dv (const GLdouble *u); +GLAPI void GLAPIENTRY glEvalCoord1f (GLfloat u); +GLAPI void GLAPIENTRY glEvalCoord1fv (const GLfloat *u); +GLAPI void GLAPIENTRY glEvalCoord2d (GLdouble u, GLdouble v); +GLAPI void GLAPIENTRY glEvalCoord2dv (const GLdouble *u); +GLAPI void GLAPIENTRY glEvalCoord2f (GLfloat u, GLfloat v); +GLAPI void GLAPIENTRY glEvalCoord2fv (const GLfloat *u); +GLAPI void GLAPIENTRY glEvalMesh1 (GLenum mode, GLint i1, GLint i2); +GLAPI void GLAPIENTRY glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +GLAPI void GLAPIENTRY glEvalPoint1 (GLint i); +GLAPI void GLAPIENTRY glEvalPoint2 (GLint i, GLint j); +GLAPI void GLAPIENTRY glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer); +GLAPI void GLAPIENTRY glFinish (void); +GLAPI void GLAPIENTRY glFlush (void); +GLAPI void GLAPIENTRY glFogf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glFogfv (GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glFogi (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glFogiv (GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glFrontFace (GLenum mode); +GLAPI void GLAPIENTRY glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI GLuint GLAPIENTRY glGenLists (GLsizei range); +GLAPI void GLAPIENTRY glGenTextures (GLsizei n, GLuint *textures); +GLAPI void GLAPIENTRY glGetBooleanv (GLenum pname, GLboolean *params); +GLAPI void GLAPIENTRY glGetClipPlane (GLenum plane, GLdouble *equation); +GLAPI void GLAPIENTRY glGetDoublev (GLenum pname, GLdouble *params); +GLAPI GLenum GLAPIENTRY glGetError (void); +GLAPI void GLAPIENTRY glGetFloatv (GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetIntegerv (GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetLightiv (GLenum light, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetMapdv (GLenum target, GLenum query, GLdouble *v); +GLAPI void GLAPIENTRY glGetMapfv (GLenum target, GLenum query, GLfloat *v); +GLAPI void GLAPIENTRY glGetMapiv (GLenum target, GLenum query, GLint *v); +GLAPI void GLAPIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetMaterialiv (GLenum face, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetPixelMapfv (GLenum map, GLfloat *values); +GLAPI void GLAPIENTRY glGetPixelMapuiv (GLenum map, GLuint *values); +GLAPI void GLAPIENTRY glGetPixelMapusv (GLenum map, GLushort *values); +GLAPI void GLAPIENTRY glGetPointerv (GLenum pname, GLvoid* *params); +GLAPI void GLAPIENTRY glGetPolygonStipple (GLubyte *mask); +GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name); +GLAPI void GLAPIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params); +GLAPI void GLAPIENTRY glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexGeniv (GLenum coord, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +GLAPI void GLAPIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); +GLAPI void GLAPIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); +GLAPI void GLAPIENTRY glHint (GLenum target, GLenum mode); +GLAPI void GLAPIENTRY glIndexMask (GLuint mask); +GLAPI void GLAPIENTRY glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glIndexd (GLdouble c); +GLAPI void GLAPIENTRY glIndexdv (const GLdouble *c); +GLAPI void GLAPIENTRY glIndexf (GLfloat c); +GLAPI void GLAPIENTRY glIndexfv (const GLfloat *c); +GLAPI void GLAPIENTRY glIndexi (GLint c); +GLAPI void GLAPIENTRY glIndexiv (const GLint *c); +GLAPI void GLAPIENTRY glIndexs (GLshort c); +GLAPI void GLAPIENTRY glIndexsv (const GLshort *c); +GLAPI void GLAPIENTRY glIndexub (GLubyte c); +GLAPI void GLAPIENTRY glIndexubv (const GLubyte *c); +GLAPI void GLAPIENTRY glInitNames (void); +GLAPI void GLAPIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer); +GLAPI GLboolean GLAPIENTRY glIsEnabled (GLenum cap); +GLAPI GLboolean GLAPIENTRY glIsList (GLuint list); +GLAPI GLboolean GLAPIENTRY glIsTexture (GLuint texture); +GLAPI void GLAPIENTRY glLightModelf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glLightModelfv (GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glLightModeli (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glLightModeliv (GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glLightf (GLenum light, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glLighti (GLenum light, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glLightiv (GLenum light, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glLineStipple (GLint factor, GLushort pattern); +GLAPI void GLAPIENTRY glLineWidth (GLfloat width); +GLAPI void GLAPIENTRY glListBase (GLuint base); +GLAPI void GLAPIENTRY glLoadIdentity (void); +GLAPI void GLAPIENTRY glLoadMatrixd (const GLdouble *m); +GLAPI void GLAPIENTRY glLoadMatrixf (const GLfloat *m); +GLAPI void GLAPIENTRY glLoadName (GLuint name); +GLAPI void GLAPIENTRY glLogicOp (GLenum opcode); +GLAPI void GLAPIENTRY glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +GLAPI void GLAPIENTRY glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +GLAPI void GLAPIENTRY glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +GLAPI void GLAPIENTRY glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +GLAPI void GLAPIENTRY glMapGrid1d (GLint un, GLdouble u1, GLdouble u2); +GLAPI void GLAPIENTRY glMapGrid1f (GLint un, GLfloat u1, GLfloat u2); +GLAPI void GLAPIENTRY glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +GLAPI void GLAPIENTRY glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +GLAPI void GLAPIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glMateriali (GLenum face, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glMaterialiv (GLenum face, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glMatrixMode (GLenum mode); +GLAPI void GLAPIENTRY glMultMatrixd (const GLdouble *m); +GLAPI void GLAPIENTRY glMultMatrixf (const GLfloat *m); +GLAPI void GLAPIENTRY glNewList (GLuint list, GLenum mode); +GLAPI void GLAPIENTRY glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz); +GLAPI void GLAPIENTRY glNormal3bv (const GLbyte *v); +GLAPI void GLAPIENTRY glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz); +GLAPI void GLAPIENTRY glNormal3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); +GLAPI void GLAPIENTRY glNormal3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glNormal3i (GLint nx, GLint ny, GLint nz); +GLAPI void GLAPIENTRY glNormal3iv (const GLint *v); +GLAPI void GLAPIENTRY glNormal3s (GLshort nx, GLshort ny, GLshort nz); +GLAPI void GLAPIENTRY glNormal3sv (const GLshort *v); +GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +GLAPI void GLAPIENTRY glPassThrough (GLfloat token); +GLAPI void GLAPIENTRY glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values); +GLAPI void GLAPIENTRY glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values); +GLAPI void GLAPIENTRY glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values); +GLAPI void GLAPIENTRY glPixelStoref (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glPixelStorei (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glPixelTransferf (GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glPixelTransferi (GLenum pname, GLint param); +GLAPI void GLAPIENTRY glPixelZoom (GLfloat xfactor, GLfloat yfactor); +GLAPI void GLAPIENTRY glPointSize (GLfloat size); +GLAPI void GLAPIENTRY glPolygonMode (GLenum face, GLenum mode); +GLAPI void GLAPIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GLAPI void GLAPIENTRY glPolygonStipple (const GLubyte *mask); +GLAPI void GLAPIENTRY glPopAttrib (void); +GLAPI void GLAPIENTRY glPopClientAttrib (void); +GLAPI void GLAPIENTRY glPopMatrix (void); +GLAPI void GLAPIENTRY glPopName (void); +GLAPI void GLAPIENTRY glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities); +GLAPI void GLAPIENTRY glPushAttrib (GLbitfield mask); +GLAPI void GLAPIENTRY glPushClientAttrib (GLbitfield mask); +GLAPI void GLAPIENTRY glPushMatrix (void); +GLAPI void GLAPIENTRY glPushName (GLuint name); +GLAPI void GLAPIENTRY glRasterPos2d (GLdouble x, GLdouble y); +GLAPI void GLAPIENTRY glRasterPos2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos2f (GLfloat x, GLfloat y); +GLAPI void GLAPIENTRY glRasterPos2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos2i (GLint x, GLint y); +GLAPI void GLAPIENTRY glRasterPos2iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos2s (GLshort x, GLshort y); +GLAPI void GLAPIENTRY glRasterPos2sv (const GLshort *v); +GLAPI void GLAPIENTRY glRasterPos3d (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glRasterPos3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos3f (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glRasterPos3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos3i (GLint x, GLint y, GLint z); +GLAPI void GLAPIENTRY glRasterPos3iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos3s (GLshort x, GLshort y, GLshort z); +GLAPI void GLAPIENTRY glRasterPos3sv (const GLshort *v); +GLAPI void GLAPIENTRY glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void GLAPIENTRY glRasterPos4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void GLAPIENTRY glRasterPos4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glRasterPos4i (GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glRasterPos4iv (const GLint *v); +GLAPI void GLAPIENTRY glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void GLAPIENTRY glRasterPos4sv (const GLshort *v); +GLAPI void GLAPIENTRY glReadBuffer (GLenum mode); +GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +GLAPI void GLAPIENTRY glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +GLAPI void GLAPIENTRY glRectdv (const GLdouble *v1, const GLdouble *v2); +GLAPI void GLAPIENTRY glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +GLAPI void GLAPIENTRY glRectfv (const GLfloat *v1, const GLfloat *v2); +GLAPI void GLAPIENTRY glRecti (GLint x1, GLint y1, GLint x2, GLint y2); +GLAPI void GLAPIENTRY glRectiv (const GLint *v1, const GLint *v2); +GLAPI void GLAPIENTRY glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2); +GLAPI void GLAPIENTRY glRectsv (const GLshort *v1, const GLshort *v2); +GLAPI GLint GLAPIENTRY glRenderMode (GLenum mode); +GLAPI void GLAPIENTRY glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glScaled (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void GLAPIENTRY glSelectBuffer (GLsizei size, GLuint *buffer); +GLAPI void GLAPIENTRY glShadeModel (GLenum mode); +GLAPI void GLAPIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GLAPI void GLAPIENTRY glStencilMask (GLuint mask); +GLAPI void GLAPIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GLAPI void GLAPIENTRY glTexCoord1d (GLdouble s); +GLAPI void GLAPIENTRY glTexCoord1dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord1f (GLfloat s); +GLAPI void GLAPIENTRY glTexCoord1fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord1i (GLint s); +GLAPI void GLAPIENTRY glTexCoord1iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord1s (GLshort s); +GLAPI void GLAPIENTRY glTexCoord1sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord2d (GLdouble s, GLdouble t); +GLAPI void GLAPIENTRY glTexCoord2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord2f (GLfloat s, GLfloat t); +GLAPI void GLAPIENTRY glTexCoord2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord2i (GLint s, GLint t); +GLAPI void GLAPIENTRY glTexCoord2iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord2s (GLshort s, GLshort t); +GLAPI void GLAPIENTRY glTexCoord2sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord3d (GLdouble s, GLdouble t, GLdouble r); +GLAPI void GLAPIENTRY glTexCoord3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord3f (GLfloat s, GLfloat t, GLfloat r); +GLAPI void GLAPIENTRY glTexCoord3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord3i (GLint s, GLint t, GLint r); +GLAPI void GLAPIENTRY glTexCoord3iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord3s (GLshort s, GLshort t, GLshort r); +GLAPI void GLAPIENTRY glTexCoord3sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q); +GLAPI void GLAPIENTRY glTexCoord4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q); +GLAPI void GLAPIENTRY glTexCoord4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glTexCoord4i (GLint s, GLint t, GLint r, GLint q); +GLAPI void GLAPIENTRY glTexCoord4iv (const GLint *v); +GLAPI void GLAPIENTRY glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q); +GLAPI void GLAPIENTRY glTexCoord4sv (const GLshort *v); +GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexGend (GLenum coord, GLenum pname, GLdouble param); +GLAPI void GLAPIENTRY glTexGendv (GLenum coord, GLenum pname, const GLdouble *params); +GLAPI void GLAPIENTRY glTexGenf (GLenum coord, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexGeniv (GLenum coord, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GLAPI void GLAPIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GLAPI void GLAPIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GLAPI void GLAPIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); +GLAPI void GLAPIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTranslated (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glVertex2d (GLdouble x, GLdouble y); +GLAPI void GLAPIENTRY glVertex2dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex2f (GLfloat x, GLfloat y); +GLAPI void GLAPIENTRY glVertex2fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex2i (GLint x, GLint y); +GLAPI void GLAPIENTRY glVertex2iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex2s (GLshort x, GLshort y); +GLAPI void GLAPIENTRY glVertex2sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertex3d (GLdouble x, GLdouble y, GLdouble z); +GLAPI void GLAPIENTRY glVertex3dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex3f (GLfloat x, GLfloat y, GLfloat z); +GLAPI void GLAPIENTRY glVertex3fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex3i (GLint x, GLint y, GLint z); +GLAPI void GLAPIENTRY glVertex3iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex3s (GLshort x, GLshort y, GLshort z); +GLAPI void GLAPIENTRY glVertex3sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI void GLAPIENTRY glVertex4dv (const GLdouble *v); +GLAPI void GLAPIENTRY glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI void GLAPIENTRY glVertex4fv (const GLfloat *v); +GLAPI void GLAPIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w); +GLAPI void GLAPIENTRY glVertex4iv (const GLint *v); +GLAPI void GLAPIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI void GLAPIENTRY glVertex4sv (const GLshort *v); +GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +#define GLEW_VERSION_1_1 GLEW_GET_VAR(__GLEW_VERSION_1_1) + +#endif /* GL_VERSION_1_1 */ + +/* ---------------------------------- GLU ---------------------------------- */ + +#ifndef GLEW_NO_GLU +/* this is where we can safely include GLU */ +# if defined(__APPLE__) && defined(__MACH__) +# include +# else +# include +# endif +#endif + +/* ----------------------------- GL_VERSION_1_2 ---------------------------- */ + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 + +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_RESCALE_NORMAL 0x803A +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E + +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + +#define glCopyTexSubImage3D GLEW_GET_FUN(__glewCopyTexSubImage3D) +#define glDrawRangeElements GLEW_GET_FUN(__glewDrawRangeElements) +#define glTexImage3D GLEW_GET_FUN(__glewTexImage3D) +#define glTexSubImage3D GLEW_GET_FUN(__glewTexSubImage3D) + +#define GLEW_VERSION_1_2 GLEW_GET_VAR(__GLEW_VERSION_1_2) + +#endif /* GL_VERSION_1_2 */ + +/* ---------------------------- GL_VERSION_1_2_1 --------------------------- */ + +#ifndef GL_VERSION_1_2_1 +#define GL_VERSION_1_2_1 1 + +#define GLEW_VERSION_1_2_1 GLEW_GET_VAR(__GLEW_VERSION_1_2_1) + +#endif /* GL_VERSION_1_2_1 */ + +/* ----------------------------- GL_VERSION_1_3 ---------------------------- */ + +#ifndef GL_VERSION_1_3 +#define GL_VERSION_1_3 1 + +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_SUBTRACT 0x84E7 +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +#define GL_MULTISAMPLE_BIT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLvoid *img); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert); + +#define glActiveTexture GLEW_GET_FUN(__glewActiveTexture) +#define glClientActiveTexture GLEW_GET_FUN(__glewClientActiveTexture) +#define glCompressedTexImage1D GLEW_GET_FUN(__glewCompressedTexImage1D) +#define glCompressedTexImage2D GLEW_GET_FUN(__glewCompressedTexImage2D) +#define glCompressedTexImage3D GLEW_GET_FUN(__glewCompressedTexImage3D) +#define glCompressedTexSubImage1D GLEW_GET_FUN(__glewCompressedTexSubImage1D) +#define glCompressedTexSubImage2D GLEW_GET_FUN(__glewCompressedTexSubImage2D) +#define glCompressedTexSubImage3D GLEW_GET_FUN(__glewCompressedTexSubImage3D) +#define glGetCompressedTexImage GLEW_GET_FUN(__glewGetCompressedTexImage) +#define glLoadTransposeMatrixd GLEW_GET_FUN(__glewLoadTransposeMatrixd) +#define glLoadTransposeMatrixf GLEW_GET_FUN(__glewLoadTransposeMatrixf) +#define glMultTransposeMatrixd GLEW_GET_FUN(__glewMultTransposeMatrixd) +#define glMultTransposeMatrixf GLEW_GET_FUN(__glewMultTransposeMatrixf) +#define glMultiTexCoord1d GLEW_GET_FUN(__glewMultiTexCoord1d) +#define glMultiTexCoord1dv GLEW_GET_FUN(__glewMultiTexCoord1dv) +#define glMultiTexCoord1f GLEW_GET_FUN(__glewMultiTexCoord1f) +#define glMultiTexCoord1fv GLEW_GET_FUN(__glewMultiTexCoord1fv) +#define glMultiTexCoord1i GLEW_GET_FUN(__glewMultiTexCoord1i) +#define glMultiTexCoord1iv GLEW_GET_FUN(__glewMultiTexCoord1iv) +#define glMultiTexCoord1s GLEW_GET_FUN(__glewMultiTexCoord1s) +#define glMultiTexCoord1sv GLEW_GET_FUN(__glewMultiTexCoord1sv) +#define glMultiTexCoord2d GLEW_GET_FUN(__glewMultiTexCoord2d) +#define glMultiTexCoord2dv GLEW_GET_FUN(__glewMultiTexCoord2dv) +#define glMultiTexCoord2f GLEW_GET_FUN(__glewMultiTexCoord2f) +#define glMultiTexCoord2fv GLEW_GET_FUN(__glewMultiTexCoord2fv) +#define glMultiTexCoord2i GLEW_GET_FUN(__glewMultiTexCoord2i) +#define glMultiTexCoord2iv GLEW_GET_FUN(__glewMultiTexCoord2iv) +#define glMultiTexCoord2s GLEW_GET_FUN(__glewMultiTexCoord2s) +#define glMultiTexCoord2sv GLEW_GET_FUN(__glewMultiTexCoord2sv) +#define glMultiTexCoord3d GLEW_GET_FUN(__glewMultiTexCoord3d) +#define glMultiTexCoord3dv GLEW_GET_FUN(__glewMultiTexCoord3dv) +#define glMultiTexCoord3f GLEW_GET_FUN(__glewMultiTexCoord3f) +#define glMultiTexCoord3fv GLEW_GET_FUN(__glewMultiTexCoord3fv) +#define glMultiTexCoord3i GLEW_GET_FUN(__glewMultiTexCoord3i) +#define glMultiTexCoord3iv GLEW_GET_FUN(__glewMultiTexCoord3iv) +#define glMultiTexCoord3s GLEW_GET_FUN(__glewMultiTexCoord3s) +#define glMultiTexCoord3sv GLEW_GET_FUN(__glewMultiTexCoord3sv) +#define glMultiTexCoord4d GLEW_GET_FUN(__glewMultiTexCoord4d) +#define glMultiTexCoord4dv GLEW_GET_FUN(__glewMultiTexCoord4dv) +#define glMultiTexCoord4f GLEW_GET_FUN(__glewMultiTexCoord4f) +#define glMultiTexCoord4fv GLEW_GET_FUN(__glewMultiTexCoord4fv) +#define glMultiTexCoord4i GLEW_GET_FUN(__glewMultiTexCoord4i) +#define glMultiTexCoord4iv GLEW_GET_FUN(__glewMultiTexCoord4iv) +#define glMultiTexCoord4s GLEW_GET_FUN(__glewMultiTexCoord4s) +#define glMultiTexCoord4sv GLEW_GET_FUN(__glewMultiTexCoord4sv) +#define glSampleCoverage GLEW_GET_FUN(__glewSampleCoverage) + +#define GLEW_VERSION_1_3 GLEW_GET_VAR(__GLEW_VERSION_1_3) + +#endif /* GL_VERSION_1_3 */ + +/* ----------------------------- GL_VERSION_1_4 ---------------------------- */ + +#ifndef GL_VERSION_1_4 +#define GL_VERSION_1_4 1 + +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORDINATE 0x8451 +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY 0x8457 +#define GL_COLOR_SUM 0x8458 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY 0x845E +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_DEPTH_TEXTURE_MODE 0x884B +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_COMPARE_R_TO_TEXTURE 0x884E + +typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVPROC) (const GLdouble *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVPROC) (const GLfloat *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVPROC) (const GLint *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVPROC) (const GLshort *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVPROC) (const GLdouble *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVPROC) (const GLfloat *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVPROC) (const GLint *p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVPROC) (const GLshort *p); + +#define glBlendColor GLEW_GET_FUN(__glewBlendColor) +#define glBlendEquation GLEW_GET_FUN(__glewBlendEquation) +#define glBlendFuncSeparate GLEW_GET_FUN(__glewBlendFuncSeparate) +#define glFogCoordPointer GLEW_GET_FUN(__glewFogCoordPointer) +#define glFogCoordd GLEW_GET_FUN(__glewFogCoordd) +#define glFogCoorddv GLEW_GET_FUN(__glewFogCoorddv) +#define glFogCoordf GLEW_GET_FUN(__glewFogCoordf) +#define glFogCoordfv GLEW_GET_FUN(__glewFogCoordfv) +#define glMultiDrawArrays GLEW_GET_FUN(__glewMultiDrawArrays) +#define glMultiDrawElements GLEW_GET_FUN(__glewMultiDrawElements) +#define glPointParameterf GLEW_GET_FUN(__glewPointParameterf) +#define glPointParameterfv GLEW_GET_FUN(__glewPointParameterfv) +#define glPointParameteri GLEW_GET_FUN(__glewPointParameteri) +#define glPointParameteriv GLEW_GET_FUN(__glewPointParameteriv) +#define glSecondaryColor3b GLEW_GET_FUN(__glewSecondaryColor3b) +#define glSecondaryColor3bv GLEW_GET_FUN(__glewSecondaryColor3bv) +#define glSecondaryColor3d GLEW_GET_FUN(__glewSecondaryColor3d) +#define glSecondaryColor3dv GLEW_GET_FUN(__glewSecondaryColor3dv) +#define glSecondaryColor3f GLEW_GET_FUN(__glewSecondaryColor3f) +#define glSecondaryColor3fv GLEW_GET_FUN(__glewSecondaryColor3fv) +#define glSecondaryColor3i GLEW_GET_FUN(__glewSecondaryColor3i) +#define glSecondaryColor3iv GLEW_GET_FUN(__glewSecondaryColor3iv) +#define glSecondaryColor3s GLEW_GET_FUN(__glewSecondaryColor3s) +#define glSecondaryColor3sv GLEW_GET_FUN(__glewSecondaryColor3sv) +#define glSecondaryColor3ub GLEW_GET_FUN(__glewSecondaryColor3ub) +#define glSecondaryColor3ubv GLEW_GET_FUN(__glewSecondaryColor3ubv) +#define glSecondaryColor3ui GLEW_GET_FUN(__glewSecondaryColor3ui) +#define glSecondaryColor3uiv GLEW_GET_FUN(__glewSecondaryColor3uiv) +#define glSecondaryColor3us GLEW_GET_FUN(__glewSecondaryColor3us) +#define glSecondaryColor3usv GLEW_GET_FUN(__glewSecondaryColor3usv) +#define glSecondaryColorPointer GLEW_GET_FUN(__glewSecondaryColorPointer) +#define glWindowPos2d GLEW_GET_FUN(__glewWindowPos2d) +#define glWindowPos2dv GLEW_GET_FUN(__glewWindowPos2dv) +#define glWindowPos2f GLEW_GET_FUN(__glewWindowPos2f) +#define glWindowPos2fv GLEW_GET_FUN(__glewWindowPos2fv) +#define glWindowPos2i GLEW_GET_FUN(__glewWindowPos2i) +#define glWindowPos2iv GLEW_GET_FUN(__glewWindowPos2iv) +#define glWindowPos2s GLEW_GET_FUN(__glewWindowPos2s) +#define glWindowPos2sv GLEW_GET_FUN(__glewWindowPos2sv) +#define glWindowPos3d GLEW_GET_FUN(__glewWindowPos3d) +#define glWindowPos3dv GLEW_GET_FUN(__glewWindowPos3dv) +#define glWindowPos3f GLEW_GET_FUN(__glewWindowPos3f) +#define glWindowPos3fv GLEW_GET_FUN(__glewWindowPos3fv) +#define glWindowPos3i GLEW_GET_FUN(__glewWindowPos3i) +#define glWindowPos3iv GLEW_GET_FUN(__glewWindowPos3iv) +#define glWindowPos3s GLEW_GET_FUN(__glewWindowPos3s) +#define glWindowPos3sv GLEW_GET_FUN(__glewWindowPos3sv) + +#define GLEW_VERSION_1_4 GLEW_GET_VAR(__GLEW_VERSION_1_4) + +#endif /* GL_VERSION_1_4 */ + +/* ----------------------------- GL_VERSION_1_5 ---------------------------- */ + +#ifndef GL_VERSION_1_5 +#define GL_VERSION_1_5 1 + +#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE +#define GL_FOG_COORD GL_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY +#define GL_SRC0_RGB GL_SOURCE0_RGB +#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER +#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE +#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA +#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE +#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA +#define GL_SRC1_RGB GL_SOURCE1_RGB +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING +#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA +#define GL_SRC2_RGB GL_SOURCE2_RGB +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 + +typedef ptrdiff_t GLintptr; +typedef ptrdiff_t GLsizeiptr; + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer); +typedef GLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id); +typedef GLvoid* (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERPROC) (GLenum target); + +#define glBeginQuery GLEW_GET_FUN(__glewBeginQuery) +#define glBindBuffer GLEW_GET_FUN(__glewBindBuffer) +#define glBufferData GLEW_GET_FUN(__glewBufferData) +#define glBufferSubData GLEW_GET_FUN(__glewBufferSubData) +#define glDeleteBuffers GLEW_GET_FUN(__glewDeleteBuffers) +#define glDeleteQueries GLEW_GET_FUN(__glewDeleteQueries) +#define glEndQuery GLEW_GET_FUN(__glewEndQuery) +#define glGenBuffers GLEW_GET_FUN(__glewGenBuffers) +#define glGenQueries GLEW_GET_FUN(__glewGenQueries) +#define glGetBufferParameteriv GLEW_GET_FUN(__glewGetBufferParameteriv) +#define glGetBufferPointerv GLEW_GET_FUN(__glewGetBufferPointerv) +#define glGetBufferSubData GLEW_GET_FUN(__glewGetBufferSubData) +#define glGetQueryObjectiv GLEW_GET_FUN(__glewGetQueryObjectiv) +#define glGetQueryObjectuiv GLEW_GET_FUN(__glewGetQueryObjectuiv) +#define glGetQueryiv GLEW_GET_FUN(__glewGetQueryiv) +#define glIsBuffer GLEW_GET_FUN(__glewIsBuffer) +#define glIsQuery GLEW_GET_FUN(__glewIsQuery) +#define glMapBuffer GLEW_GET_FUN(__glewMapBuffer) +#define glUnmapBuffer GLEW_GET_FUN(__glewUnmapBuffer) + +#define GLEW_VERSION_1_5 GLEW_GET_VAR(__GLEW_VERSION_1_5) + +#endif /* GL_VERSION_1_5 */ + +/* ----------------------------- GL_VERSION_2_0 ---------------------------- */ + +#ifndef GL_VERSION_2_0 +#define GL_VERSION_2_0 1 + +#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 + +typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum, GLenum); +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum* bufs); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders); +typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); +typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEPROC) (GLuint obj, GLsizei maxLength, GLsizei* length, GLchar* source); +typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param); +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint, GLenum, GLvoid**); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVPROC) (GLuint, GLenum, GLdouble*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint, GLenum, GLfloat*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint, GLenum, GLint*); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader); +typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths); +typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); + +#define glAttachShader GLEW_GET_FUN(__glewAttachShader) +#define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation) +#define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate) +#define glCompileShader GLEW_GET_FUN(__glewCompileShader) +#define glCreateProgram GLEW_GET_FUN(__glewCreateProgram) +#define glCreateShader GLEW_GET_FUN(__glewCreateShader) +#define glDeleteProgram GLEW_GET_FUN(__glewDeleteProgram) +#define glDeleteShader GLEW_GET_FUN(__glewDeleteShader) +#define glDetachShader GLEW_GET_FUN(__glewDetachShader) +#define glDisableVertexAttribArray GLEW_GET_FUN(__glewDisableVertexAttribArray) +#define glDrawBuffers GLEW_GET_FUN(__glewDrawBuffers) +#define glEnableVertexAttribArray GLEW_GET_FUN(__glewEnableVertexAttribArray) +#define glGetActiveAttrib GLEW_GET_FUN(__glewGetActiveAttrib) +#define glGetActiveUniform GLEW_GET_FUN(__glewGetActiveUniform) +#define glGetAttachedShaders GLEW_GET_FUN(__glewGetAttachedShaders) +#define glGetAttribLocation GLEW_GET_FUN(__glewGetAttribLocation) +#define glGetProgramInfoLog GLEW_GET_FUN(__glewGetProgramInfoLog) +#define glGetProgramiv GLEW_GET_FUN(__glewGetProgramiv) +#define glGetShaderInfoLog GLEW_GET_FUN(__glewGetShaderInfoLog) +#define glGetShaderSource GLEW_GET_FUN(__glewGetShaderSource) +#define glGetShaderiv GLEW_GET_FUN(__glewGetShaderiv) +#define glGetUniformLocation GLEW_GET_FUN(__glewGetUniformLocation) +#define glGetUniformfv GLEW_GET_FUN(__glewGetUniformfv) +#define glGetUniformiv GLEW_GET_FUN(__glewGetUniformiv) +#define glGetVertexAttribPointerv GLEW_GET_FUN(__glewGetVertexAttribPointerv) +#define glGetVertexAttribdv GLEW_GET_FUN(__glewGetVertexAttribdv) +#define glGetVertexAttribfv GLEW_GET_FUN(__glewGetVertexAttribfv) +#define glGetVertexAttribiv GLEW_GET_FUN(__glewGetVertexAttribiv) +#define glIsProgram GLEW_GET_FUN(__glewIsProgram) +#define glIsShader GLEW_GET_FUN(__glewIsShader) +#define glLinkProgram GLEW_GET_FUN(__glewLinkProgram) +#define glShaderSource GLEW_GET_FUN(__glewShaderSource) +#define glStencilFuncSeparate GLEW_GET_FUN(__glewStencilFuncSeparate) +#define glStencilMaskSeparate GLEW_GET_FUN(__glewStencilMaskSeparate) +#define glStencilOpSeparate GLEW_GET_FUN(__glewStencilOpSeparate) +#define glUniform1f GLEW_GET_FUN(__glewUniform1f) +#define glUniform1fv GLEW_GET_FUN(__glewUniform1fv) +#define glUniform1i GLEW_GET_FUN(__glewUniform1i) +#define glUniform1iv GLEW_GET_FUN(__glewUniform1iv) +#define glUniform2f GLEW_GET_FUN(__glewUniform2f) +#define glUniform2fv GLEW_GET_FUN(__glewUniform2fv) +#define glUniform2i GLEW_GET_FUN(__glewUniform2i) +#define glUniform2iv GLEW_GET_FUN(__glewUniform2iv) +#define glUniform3f GLEW_GET_FUN(__glewUniform3f) +#define glUniform3fv GLEW_GET_FUN(__glewUniform3fv) +#define glUniform3i GLEW_GET_FUN(__glewUniform3i) +#define glUniform3iv GLEW_GET_FUN(__glewUniform3iv) +#define glUniform4f GLEW_GET_FUN(__glewUniform4f) +#define glUniform4fv GLEW_GET_FUN(__glewUniform4fv) +#define glUniform4i GLEW_GET_FUN(__glewUniform4i) +#define glUniform4iv GLEW_GET_FUN(__glewUniform4iv) +#define glUniformMatrix2fv GLEW_GET_FUN(__glewUniformMatrix2fv) +#define glUniformMatrix3fv GLEW_GET_FUN(__glewUniformMatrix3fv) +#define glUniformMatrix4fv GLEW_GET_FUN(__glewUniformMatrix4fv) +#define glUseProgram GLEW_GET_FUN(__glewUseProgram) +#define glValidateProgram GLEW_GET_FUN(__glewValidateProgram) +#define glVertexAttrib1d GLEW_GET_FUN(__glewVertexAttrib1d) +#define glVertexAttrib1dv GLEW_GET_FUN(__glewVertexAttrib1dv) +#define glVertexAttrib1f GLEW_GET_FUN(__glewVertexAttrib1f) +#define glVertexAttrib1fv GLEW_GET_FUN(__glewVertexAttrib1fv) +#define glVertexAttrib1s GLEW_GET_FUN(__glewVertexAttrib1s) +#define glVertexAttrib1sv GLEW_GET_FUN(__glewVertexAttrib1sv) +#define glVertexAttrib2d GLEW_GET_FUN(__glewVertexAttrib2d) +#define glVertexAttrib2dv GLEW_GET_FUN(__glewVertexAttrib2dv) +#define glVertexAttrib2f GLEW_GET_FUN(__glewVertexAttrib2f) +#define glVertexAttrib2fv GLEW_GET_FUN(__glewVertexAttrib2fv) +#define glVertexAttrib2s GLEW_GET_FUN(__glewVertexAttrib2s) +#define glVertexAttrib2sv GLEW_GET_FUN(__glewVertexAttrib2sv) +#define glVertexAttrib3d GLEW_GET_FUN(__glewVertexAttrib3d) +#define glVertexAttrib3dv GLEW_GET_FUN(__glewVertexAttrib3dv) +#define glVertexAttrib3f GLEW_GET_FUN(__glewVertexAttrib3f) +#define glVertexAttrib3fv GLEW_GET_FUN(__glewVertexAttrib3fv) +#define glVertexAttrib3s GLEW_GET_FUN(__glewVertexAttrib3s) +#define glVertexAttrib3sv GLEW_GET_FUN(__glewVertexAttrib3sv) +#define glVertexAttrib4Nbv GLEW_GET_FUN(__glewVertexAttrib4Nbv) +#define glVertexAttrib4Niv GLEW_GET_FUN(__glewVertexAttrib4Niv) +#define glVertexAttrib4Nsv GLEW_GET_FUN(__glewVertexAttrib4Nsv) +#define glVertexAttrib4Nub GLEW_GET_FUN(__glewVertexAttrib4Nub) +#define glVertexAttrib4Nubv GLEW_GET_FUN(__glewVertexAttrib4Nubv) +#define glVertexAttrib4Nuiv GLEW_GET_FUN(__glewVertexAttrib4Nuiv) +#define glVertexAttrib4Nusv GLEW_GET_FUN(__glewVertexAttrib4Nusv) +#define glVertexAttrib4bv GLEW_GET_FUN(__glewVertexAttrib4bv) +#define glVertexAttrib4d GLEW_GET_FUN(__glewVertexAttrib4d) +#define glVertexAttrib4dv GLEW_GET_FUN(__glewVertexAttrib4dv) +#define glVertexAttrib4f GLEW_GET_FUN(__glewVertexAttrib4f) +#define glVertexAttrib4fv GLEW_GET_FUN(__glewVertexAttrib4fv) +#define glVertexAttrib4iv GLEW_GET_FUN(__glewVertexAttrib4iv) +#define glVertexAttrib4s GLEW_GET_FUN(__glewVertexAttrib4s) +#define glVertexAttrib4sv GLEW_GET_FUN(__glewVertexAttrib4sv) +#define glVertexAttrib4ubv GLEW_GET_FUN(__glewVertexAttrib4ubv) +#define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv) +#define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv) +#define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer) + +#define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0) + +#endif /* GL_VERSION_2_0 */ + +/* ----------------------------- GL_VERSION_2_1 ---------------------------- */ + +#ifndef GL_VERSION_2_1 +#define GL_VERSION_2_1 1 + +#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SLUMINANCE_ALPHA 0x8C44 +#define GL_SLUMINANCE8_ALPHA8 0x8C45 +#define GL_SLUMINANCE 0x8C46 +#define GL_SLUMINANCE8 0x8C47 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPRESSED_SLUMINANCE 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B + +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + +#define glUniformMatrix2x3fv GLEW_GET_FUN(__glewUniformMatrix2x3fv) +#define glUniformMatrix2x4fv GLEW_GET_FUN(__glewUniformMatrix2x4fv) +#define glUniformMatrix3x2fv GLEW_GET_FUN(__glewUniformMatrix3x2fv) +#define glUniformMatrix3x4fv GLEW_GET_FUN(__glewUniformMatrix3x4fv) +#define glUniformMatrix4x2fv GLEW_GET_FUN(__glewUniformMatrix4x2fv) +#define glUniformMatrix4x3fv GLEW_GET_FUN(__glewUniformMatrix4x3fv) + +#define GLEW_VERSION_2_1 GLEW_GET_VAR(__GLEW_VERSION_2_1) + +#endif /* GL_VERSION_2_1 */ + +/* ----------------------------- GL_VERSION_3_0 ---------------------------- */ + +#ifndef GL_VERSION_3_0 +#define GL_VERSION_3_0 1 + +#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES +#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5 +#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1 +#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3 +#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB +#define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0 +#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4 +#define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2 +#define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_DEPTH_BUFFER 0x8223 +#define GL_STENCIL_BUFFER 0x8224 +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_VERTEX_COLOR 0x891A +#define GL_CLAMP_FRAGMENT_COLOR 0x891B +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_ALPHA_INTEGER 0x8D97 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 + +typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERPROC) (GLuint, GLenum); +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum); +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONPROC) (GLuint, GLuint, const GLchar*); +typedef void (GLAPIENTRY * PFNGLCLAMPCOLORPROC) (GLenum, GLenum); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum, GLint, GLfloat, GLint); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum, GLint, const GLfloat*); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum, GLint, const GLint*); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum, GLint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLCOLORMASKIPROC) (GLuint, GLboolean, GLboolean, GLboolean, GLboolean); +typedef void (GLAPIENTRY * PFNGLDISABLEIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLENABLEIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERPROC) (void); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETBOOLEANI_VPROC) (GLenum, GLuint, GLboolean*); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONPROC) (GLuint, const GLchar*); +typedef const GLubyte* (GLAPIENTRY * PFNGLGETSTRINGIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVPROC) (GLenum, GLenum, GLint*); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVPROC) (GLenum, GLenum, GLuint*); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVPROC) (GLuint, GLint, GLuint*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVPROC) (GLuint, GLenum, GLint*); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint, GLenum, GLuint*); +typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDIPROC) (GLenum, GLuint); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVPROC) (GLenum, GLenum, const GLint*); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVPROC) (GLenum, GLenum, const GLuint*); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint, GLsizei, const GLchar **, GLenum); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIPROC) (GLint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIPROC) (GLint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIPROC) (GLint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIPROC) (GLint, GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVPROC) (GLint, GLsizei, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IPROC) (GLuint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIPROC) (GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IPROC) (GLuint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIPROC) (GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IPROC) (GLuint, GLint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIPROC) (GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVPROC) (GLuint, const GLbyte*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IPROC) (GLuint, GLint, GLint, GLint, GLint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVPROC) (GLuint, const GLint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVPROC) (GLuint, const GLshort*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVPROC) (GLuint, const GLubyte*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIPROC) (GLuint, GLuint, GLuint, GLuint, GLuint); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVPROC) (GLuint, const GLuint*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVPROC) (GLuint, const GLushort*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint, GLint, GLenum, GLsizei, const GLvoid*); + +#define glBeginConditionalRender GLEW_GET_FUN(__glewBeginConditionalRender) +#define glBeginTransformFeedback GLEW_GET_FUN(__glewBeginTransformFeedback) +#define glBindFragDataLocation GLEW_GET_FUN(__glewBindFragDataLocation) +#define glClampColor GLEW_GET_FUN(__glewClampColor) +#define glClearBufferfi GLEW_GET_FUN(__glewClearBufferfi) +#define glClearBufferfv GLEW_GET_FUN(__glewClearBufferfv) +#define glClearBufferiv GLEW_GET_FUN(__glewClearBufferiv) +#define glClearBufferuiv GLEW_GET_FUN(__glewClearBufferuiv) +#define glColorMaski GLEW_GET_FUN(__glewColorMaski) +#define glDisablei GLEW_GET_FUN(__glewDisablei) +#define glEnablei GLEW_GET_FUN(__glewEnablei) +#define glEndConditionalRender GLEW_GET_FUN(__glewEndConditionalRender) +#define glEndTransformFeedback GLEW_GET_FUN(__glewEndTransformFeedback) +#define glGetBooleani_v GLEW_GET_FUN(__glewGetBooleani_v) +#define glGetFragDataLocation GLEW_GET_FUN(__glewGetFragDataLocation) +#define glGetStringi GLEW_GET_FUN(__glewGetStringi) +#define glGetTexParameterIiv GLEW_GET_FUN(__glewGetTexParameterIiv) +#define glGetTexParameterIuiv GLEW_GET_FUN(__glewGetTexParameterIuiv) +#define glGetTransformFeedbackVarying GLEW_GET_FUN(__glewGetTransformFeedbackVarying) +#define glGetUniformuiv GLEW_GET_FUN(__glewGetUniformuiv) +#define glGetVertexAttribIiv GLEW_GET_FUN(__glewGetVertexAttribIiv) +#define glGetVertexAttribIuiv GLEW_GET_FUN(__glewGetVertexAttribIuiv) +#define glIsEnabledi GLEW_GET_FUN(__glewIsEnabledi) +#define glTexParameterIiv GLEW_GET_FUN(__glewTexParameterIiv) +#define glTexParameterIuiv GLEW_GET_FUN(__glewTexParameterIuiv) +#define glTransformFeedbackVaryings GLEW_GET_FUN(__glewTransformFeedbackVaryings) +#define glUniform1ui GLEW_GET_FUN(__glewUniform1ui) +#define glUniform1uiv GLEW_GET_FUN(__glewUniform1uiv) +#define glUniform2ui GLEW_GET_FUN(__glewUniform2ui) +#define glUniform2uiv GLEW_GET_FUN(__glewUniform2uiv) +#define glUniform3ui GLEW_GET_FUN(__glewUniform3ui) +#define glUniform3uiv GLEW_GET_FUN(__glewUniform3uiv) +#define glUniform4ui GLEW_GET_FUN(__glewUniform4ui) +#define glUniform4uiv GLEW_GET_FUN(__glewUniform4uiv) +#define glVertexAttribI1i GLEW_GET_FUN(__glewVertexAttribI1i) +#define glVertexAttribI1iv GLEW_GET_FUN(__glewVertexAttribI1iv) +#define glVertexAttribI1ui GLEW_GET_FUN(__glewVertexAttribI1ui) +#define glVertexAttribI1uiv GLEW_GET_FUN(__glewVertexAttribI1uiv) +#define glVertexAttribI2i GLEW_GET_FUN(__glewVertexAttribI2i) +#define glVertexAttribI2iv GLEW_GET_FUN(__glewVertexAttribI2iv) +#define glVertexAttribI2ui GLEW_GET_FUN(__glewVertexAttribI2ui) +#define glVertexAttribI2uiv GLEW_GET_FUN(__glewVertexAttribI2uiv) +#define glVertexAttribI3i GLEW_GET_FUN(__glewVertexAttribI3i) +#define glVertexAttribI3iv GLEW_GET_FUN(__glewVertexAttribI3iv) +#define glVertexAttribI3ui GLEW_GET_FUN(__glewVertexAttribI3ui) +#define glVertexAttribI3uiv GLEW_GET_FUN(__glewVertexAttribI3uiv) +#define glVertexAttribI4bv GLEW_GET_FUN(__glewVertexAttribI4bv) +#define glVertexAttribI4i GLEW_GET_FUN(__glewVertexAttribI4i) +#define glVertexAttribI4iv GLEW_GET_FUN(__glewVertexAttribI4iv) +#define glVertexAttribI4sv GLEW_GET_FUN(__glewVertexAttribI4sv) +#define glVertexAttribI4ubv GLEW_GET_FUN(__glewVertexAttribI4ubv) +#define glVertexAttribI4ui GLEW_GET_FUN(__glewVertexAttribI4ui) +#define glVertexAttribI4uiv GLEW_GET_FUN(__glewVertexAttribI4uiv) +#define glVertexAttribI4usv GLEW_GET_FUN(__glewVertexAttribI4usv) +#define glVertexAttribIPointer GLEW_GET_FUN(__glewVertexAttribIPointer) + +#define GLEW_VERSION_3_0 GLEW_GET_VAR(__GLEW_VERSION_3_0) + +#endif /* GL_VERSION_3_0 */ + +/* ----------------------------- GL_VERSION_3_1 ---------------------------- */ + +#ifndef GL_VERSION_3_1 +#define GL_VERSION_3_1 1 + +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT 0x8C2E +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_RED_SNORM 0x8F90 +#define GL_RG_SNORM 0x8F91 +#define GL_RGB_SNORM 0x8F92 +#define GL_RGBA_SNORM 0x8F93 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum, GLint, GLsizei, GLsizei); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum, GLsizei, GLenum, const GLvoid*, GLsizei); +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint); +typedef void (GLAPIENTRY * PFNGLTEXBUFFERPROC) (GLenum, GLenum, GLuint); + +#define glDrawArraysInstanced GLEW_GET_FUN(__glewDrawArraysInstanced) +#define glDrawElementsInstanced GLEW_GET_FUN(__glewDrawElementsInstanced) +#define glPrimitiveRestartIndex GLEW_GET_FUN(__glewPrimitiveRestartIndex) +#define glTexBuffer GLEW_GET_FUN(__glewTexBuffer) + +#define GLEW_VERSION_3_1 GLEW_GET_VAR(__GLEW_VERSION_3_1) + +#endif /* GL_VERSION_3_1 */ + +/* ----------------------------- GL_VERSION_3_2 ---------------------------- */ + +#ifndef GL_VERSION_3_2 +#define GL_VERSION_3_2 1 + +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_CONTEXT_PROFILE_MASK 0x9126 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum, GLenum, GLuint, GLint); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum, GLenum, GLint64 *); +typedef void (GLAPIENTRY * PFNGLGETINTEGER64I_VPROC) (GLenum, GLuint, GLint64 *); + +#define glFramebufferTexture GLEW_GET_FUN(__glewFramebufferTexture) +#define glGetBufferParameteri64v GLEW_GET_FUN(__glewGetBufferParameteri64v) +#define glGetInteger64i_v GLEW_GET_FUN(__glewGetInteger64i_v) + +#define GLEW_VERSION_3_2 GLEW_GET_VAR(__GLEW_VERSION_3_2) + +#endif /* GL_VERSION_3_2 */ + +/* ----------------------------- GL_VERSION_3_3 ---------------------------- */ + +#ifndef GL_VERSION_3_3 +#define GL_VERSION_3_3 1 + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_RGB10_A2UI 0x906F + +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); + +#define glVertexAttribDivisor GLEW_GET_FUN(__glewVertexAttribDivisor) + +#define GLEW_VERSION_3_3 GLEW_GET_VAR(__GLEW_VERSION_3_3) + +#endif /* GL_VERSION_3_3 */ + +/* ----------------------------- GL_VERSION_4_0 ---------------------------- */ + +#ifndef GL_VERSION_4_0 +#define GL_VERSION_4_0 1 + +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGPROC) (GLclampf value); + +#define glBlendEquationSeparatei GLEW_GET_FUN(__glewBlendEquationSeparatei) +#define glBlendEquationi GLEW_GET_FUN(__glewBlendEquationi) +#define glBlendFuncSeparatei GLEW_GET_FUN(__glewBlendFuncSeparatei) +#define glBlendFunci GLEW_GET_FUN(__glewBlendFunci) +#define glMinSampleShading GLEW_GET_FUN(__glewMinSampleShading) + +#define GLEW_VERSION_4_0 GLEW_GET_VAR(__GLEW_VERSION_4_0) + +#endif /* GL_VERSION_4_0 */ + +/* ----------------------------- GL_VERSION_4_1 ---------------------------- */ + +#ifndef GL_VERSION_4_1 +#define GL_VERSION_4_1 1 + +#define GLEW_VERSION_4_1 GLEW_GET_VAR(__GLEW_VERSION_4_1) + +#endif /* GL_VERSION_4_1 */ + +/* -------------------------- GL_3DFX_multisample -------------------------- */ + +#ifndef GL_3DFX_multisample +#define GL_3DFX_multisample 1 + +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 + +#define GLEW_3DFX_multisample GLEW_GET_VAR(__GLEW_3DFX_multisample) + +#endif /* GL_3DFX_multisample */ + +/* ---------------------------- GL_3DFX_tbuffer ---------------------------- */ + +#ifndef GL_3DFX_tbuffer +#define GL_3DFX_tbuffer 1 + +typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); + +#define glTbufferMask3DFX GLEW_GET_FUN(__glewTbufferMask3DFX) + +#define GLEW_3DFX_tbuffer GLEW_GET_VAR(__GLEW_3DFX_tbuffer) + +#endif /* GL_3DFX_tbuffer */ + +/* -------------------- GL_3DFX_texture_compression_FXT1 ------------------- */ + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_3DFX_texture_compression_FXT1 1 + +#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 +#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 + +#define GLEW_3DFX_texture_compression_FXT1 GLEW_GET_VAR(__GLEW_3DFX_texture_compression_FXT1) + +#endif /* GL_3DFX_texture_compression_FXT1 */ + +/* ----------------------- GL_AMD_blend_minmax_factor ---------------------- */ + +#ifndef GL_AMD_blend_minmax_factor +#define GL_AMD_blend_minmax_factor 1 + +#define GL_FACTOR_MIN_AMD 0x901C +#define GL_FACTOR_MAX_AMD 0x901D + +#define GLEW_AMD_blend_minmax_factor GLEW_GET_VAR(__GLEW_AMD_blend_minmax_factor) + +#endif /* GL_AMD_blend_minmax_factor */ + +/* ----------------------- GL_AMD_conservative_depth ----------------------- */ + +#ifndef GL_AMD_conservative_depth +#define GL_AMD_conservative_depth 1 + +#define GLEW_AMD_conservative_depth GLEW_GET_VAR(__GLEW_AMD_conservative_depth) + +#endif /* GL_AMD_conservative_depth */ + +/* -------------------------- GL_AMD_debug_output -------------------------- */ + +#ifndef GL_AMD_debug_output +#define GL_AMD_debug_output 1 + +#define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147 +#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148 +#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149 +#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A +#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B +#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C +#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D +#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E +#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F +#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150 + +typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); + +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void* userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const char* buf); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, char* message); + +#define glDebugMessageCallbackAMD GLEW_GET_FUN(__glewDebugMessageCallbackAMD) +#define glDebugMessageEnableAMD GLEW_GET_FUN(__glewDebugMessageEnableAMD) +#define glDebugMessageInsertAMD GLEW_GET_FUN(__glewDebugMessageInsertAMD) +#define glGetDebugMessageLogAMD GLEW_GET_FUN(__glewGetDebugMessageLogAMD) + +#define GLEW_AMD_debug_output GLEW_GET_VAR(__GLEW_AMD_debug_output) + +#endif /* GL_AMD_debug_output */ + +/* ---------------------- GL_AMD_depth_clamp_separate ---------------------- */ + +#ifndef GL_AMD_depth_clamp_separate +#define GL_AMD_depth_clamp_separate 1 + +#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E +#define GL_DEPTH_CLAMP_FAR_AMD 0x901F + +#define GLEW_AMD_depth_clamp_separate GLEW_GET_VAR(__GLEW_AMD_depth_clamp_separate) + +#endif /* GL_AMD_depth_clamp_separate */ + +/* ----------------------- GL_AMD_draw_buffers_blend ----------------------- */ + +#ifndef GL_AMD_draw_buffers_blend +#define GL_AMD_draw_buffers_blend 1 + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + +#define glBlendEquationIndexedAMD GLEW_GET_FUN(__glewBlendEquationIndexedAMD) +#define glBlendEquationSeparateIndexedAMD GLEW_GET_FUN(__glewBlendEquationSeparateIndexedAMD) +#define glBlendFuncIndexedAMD GLEW_GET_FUN(__glewBlendFuncIndexedAMD) +#define glBlendFuncSeparateIndexedAMD GLEW_GET_FUN(__glewBlendFuncSeparateIndexedAMD) + +#define GLEW_AMD_draw_buffers_blend GLEW_GET_VAR(__GLEW_AMD_draw_buffers_blend) + +#endif /* GL_AMD_draw_buffers_blend */ + +/* ------------------------- GL_AMD_name_gen_delete ------------------------ */ + +#ifndef GL_AMD_name_gen_delete +#define GL_AMD_name_gen_delete 1 + +#define GL_DATA_BUFFER_AMD 0x9151 +#define GL_PERFORMANCE_MONITOR_AMD 0x9152 +#define GL_QUERY_OBJECT_AMD 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154 +#define GL_SAMPLER_OBJECT_AMD 0x9155 + +typedef void (GLAPIENTRY * PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint* names); +typedef void (GLAPIENTRY * PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint* names); +typedef GLboolean (GLAPIENTRY * PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name); + +#define glDeleteNamesAMD GLEW_GET_FUN(__glewDeleteNamesAMD) +#define glGenNamesAMD GLEW_GET_FUN(__glewGenNamesAMD) +#define glIsNameAMD GLEW_GET_FUN(__glewIsNameAMD) + +#define GLEW_AMD_name_gen_delete GLEW_GET_VAR(__GLEW_AMD_name_gen_delete) + +#endif /* GL_AMD_name_gen_delete */ + +/* ----------------------- GL_AMD_performance_monitor ---------------------- */ + +#ifndef GL_AMD_performance_monitor +#define GL_AMD_performance_monitor 1 + +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_COUNTER_TYPE_AMD 0x8BC0 +#define GL_COUNTER_RANGE_AMD 0x8BC1 +#define GL_UNSIGNED_INT64_AMD 0x8BC2 +#define GL_PERCENTAGE_AMD 0x8BC3 +#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 +#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 +#define GL_PERFMON_RESULT_AMD 0x8BC6 + +typedef void (GLAPIENTRY * PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors); +typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void* data); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, char *counterString); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, char *groupString); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint* numGroups, GLsizei groupsSize, GLuint *groups); +typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint* counterList); + +#define glBeginPerfMonitorAMD GLEW_GET_FUN(__glewBeginPerfMonitorAMD) +#define glDeletePerfMonitorsAMD GLEW_GET_FUN(__glewDeletePerfMonitorsAMD) +#define glEndPerfMonitorAMD GLEW_GET_FUN(__glewEndPerfMonitorAMD) +#define glGenPerfMonitorsAMD GLEW_GET_FUN(__glewGenPerfMonitorsAMD) +#define glGetPerfMonitorCounterDataAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterDataAMD) +#define glGetPerfMonitorCounterInfoAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterInfoAMD) +#define glGetPerfMonitorCounterStringAMD GLEW_GET_FUN(__glewGetPerfMonitorCounterStringAMD) +#define glGetPerfMonitorCountersAMD GLEW_GET_FUN(__glewGetPerfMonitorCountersAMD) +#define glGetPerfMonitorGroupStringAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupStringAMD) +#define glGetPerfMonitorGroupsAMD GLEW_GET_FUN(__glewGetPerfMonitorGroupsAMD) +#define glSelectPerfMonitorCountersAMD GLEW_GET_FUN(__glewSelectPerfMonitorCountersAMD) + +#define GLEW_AMD_performance_monitor GLEW_GET_VAR(__GLEW_AMD_performance_monitor) + +#endif /* GL_AMD_performance_monitor */ + +/* ------------------------ GL_AMD_sample_positions ------------------------ */ + +#ifndef GL_AMD_sample_positions +#define GL_AMD_sample_positions 1 + +#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F + +typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat* val); + +#define glSetMultisamplefvAMD GLEW_GET_FUN(__glewSetMultisamplefvAMD) + +#define GLEW_AMD_sample_positions GLEW_GET_VAR(__GLEW_AMD_sample_positions) + +#endif /* GL_AMD_sample_positions */ + +/* ------------------ GL_AMD_seamless_cubemap_per_texture ------------------ */ + +#ifndef GL_AMD_seamless_cubemap_per_texture +#define GL_AMD_seamless_cubemap_per_texture 1 + +#define GL_TEXTURE_CUBE_MAP_SEAMLESS_ARB 0x884F + +#define GLEW_AMD_seamless_cubemap_per_texture GLEW_GET_VAR(__GLEW_AMD_seamless_cubemap_per_texture) + +#endif /* GL_AMD_seamless_cubemap_per_texture */ + +/* ---------------------- GL_AMD_shader_stencil_export --------------------- */ + +#ifndef GL_AMD_shader_stencil_export +#define GL_AMD_shader_stencil_export 1 + +#define GLEW_AMD_shader_stencil_export GLEW_GET_VAR(__GLEW_AMD_shader_stencil_export) + +#endif /* GL_AMD_shader_stencil_export */ + +/* ------------------------ GL_AMD_texture_texture4 ------------------------ */ + +#ifndef GL_AMD_texture_texture4 +#define GL_AMD_texture_texture4 1 + +#define GLEW_AMD_texture_texture4 GLEW_GET_VAR(__GLEW_AMD_texture_texture4) + +#endif /* GL_AMD_texture_texture4 */ + +/* --------------- GL_AMD_transform_feedback3_lines_triangles -------------- */ + +#ifndef GL_AMD_transform_feedback3_lines_triangles +#define GL_AMD_transform_feedback3_lines_triangles 1 + +#define GLEW_AMD_transform_feedback3_lines_triangles GLEW_GET_VAR(__GLEW_AMD_transform_feedback3_lines_triangles) + +#endif /* GL_AMD_transform_feedback3_lines_triangles */ + +/* -------------------- GL_AMD_vertex_shader_tessellator ------------------- */ + +#ifndef GL_AMD_vertex_shader_tessellator +#define GL_AMD_vertex_shader_tessellator 1 + +#define GL_SAMPLER_BUFFER_AMD 0x9001 +#define GL_INT_SAMPLER_BUFFER_AMD 0x9002 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003 +#define GL_TESSELLATION_MODE_AMD 0x9004 +#define GL_TESSELLATION_FACTOR_AMD 0x9005 +#define GL_DISCRETE_AMD 0x9006 +#define GL_CONTINUOUS_AMD 0x9007 + +typedef void (GLAPIENTRY * PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor); +typedef void (GLAPIENTRY * PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode); + +#define glTessellationFactorAMD GLEW_GET_FUN(__glewTessellationFactorAMD) +#define glTessellationModeAMD GLEW_GET_FUN(__glewTessellationModeAMD) + +#define GLEW_AMD_vertex_shader_tessellator GLEW_GET_VAR(__GLEW_AMD_vertex_shader_tessellator) + +#endif /* GL_AMD_vertex_shader_tessellator */ + +/* ----------------------- GL_APPLE_aux_depth_stencil ---------------------- */ + +#ifndef GL_APPLE_aux_depth_stencil +#define GL_APPLE_aux_depth_stencil 1 + +#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14 + +#define GLEW_APPLE_aux_depth_stencil GLEW_GET_VAR(__GLEW_APPLE_aux_depth_stencil) + +#endif /* GL_APPLE_aux_depth_stencil */ + +/* ------------------------ GL_APPLE_client_storage ------------------------ */ + +#ifndef GL_APPLE_client_storage +#define GL_APPLE_client_storage 1 + +#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 + +#define GLEW_APPLE_client_storage GLEW_GET_VAR(__GLEW_APPLE_client_storage) + +#endif /* GL_APPLE_client_storage */ + +/* ------------------------- GL_APPLE_element_array ------------------------ */ + +#ifndef GL_APPLE_element_array +#define GL_APPLE_element_array 1 + +#define GL_ELEMENT_ARRAY_APPLE 0x8A0C +#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D +#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void* pointer); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount); + +#define glDrawElementArrayAPPLE GLEW_GET_FUN(__glewDrawElementArrayAPPLE) +#define glDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewDrawRangeElementArrayAPPLE) +#define glElementPointerAPPLE GLEW_GET_FUN(__glewElementPointerAPPLE) +#define glMultiDrawElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawElementArrayAPPLE) +#define glMultiDrawRangeElementArrayAPPLE GLEW_GET_FUN(__glewMultiDrawRangeElementArrayAPPLE) + +#define GLEW_APPLE_element_array GLEW_GET_VAR(__GLEW_APPLE_element_array) + +#endif /* GL_APPLE_element_array */ + +/* ----------------------------- GL_APPLE_fence ---------------------------- */ + +#ifndef GL_APPLE_fence +#define GL_APPLE_fence 1 + +#define GL_DRAW_PIXELS_APPLE 0x8A0A +#define GL_FENCE_APPLE 0x8A0B + +typedef void (GLAPIENTRY * PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint* fences); +typedef void (GLAPIENTRY * PFNGLFINISHFENCEAPPLEPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); +typedef void (GLAPIENTRY * PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint* fences); +typedef GLboolean (GLAPIENTRY * PFNGLISFENCEAPPLEPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLSETFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (GLAPIENTRY * PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); + +#define glDeleteFencesAPPLE GLEW_GET_FUN(__glewDeleteFencesAPPLE) +#define glFinishFenceAPPLE GLEW_GET_FUN(__glewFinishFenceAPPLE) +#define glFinishObjectAPPLE GLEW_GET_FUN(__glewFinishObjectAPPLE) +#define glGenFencesAPPLE GLEW_GET_FUN(__glewGenFencesAPPLE) +#define glIsFenceAPPLE GLEW_GET_FUN(__glewIsFenceAPPLE) +#define glSetFenceAPPLE GLEW_GET_FUN(__glewSetFenceAPPLE) +#define glTestFenceAPPLE GLEW_GET_FUN(__glewTestFenceAPPLE) +#define glTestObjectAPPLE GLEW_GET_FUN(__glewTestObjectAPPLE) + +#define GLEW_APPLE_fence GLEW_GET_VAR(__GLEW_APPLE_fence) + +#endif /* GL_APPLE_fence */ + +/* ------------------------- GL_APPLE_float_pixels ------------------------- */ + +#ifndef GL_APPLE_float_pixels +#define GL_APPLE_float_pixels 1 + +#define GL_HALF_APPLE 0x140B +#define GL_RGBA_FLOAT32_APPLE 0x8814 +#define GL_RGB_FLOAT32_APPLE 0x8815 +#define GL_ALPHA_FLOAT32_APPLE 0x8816 +#define GL_INTENSITY_FLOAT32_APPLE 0x8817 +#define GL_LUMINANCE_FLOAT32_APPLE 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819 +#define GL_RGBA_FLOAT16_APPLE 0x881A +#define GL_RGB_FLOAT16_APPLE 0x881B +#define GL_ALPHA_FLOAT16_APPLE 0x881C +#define GL_INTENSITY_FLOAT16_APPLE 0x881D +#define GL_LUMINANCE_FLOAT16_APPLE 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F +#define GL_COLOR_FLOAT_APPLE 0x8A0F + +#define GLEW_APPLE_float_pixels GLEW_GET_VAR(__GLEW_APPLE_float_pixels) + +#endif /* GL_APPLE_float_pixels */ + +/* ---------------------- GL_APPLE_flush_buffer_range ---------------------- */ + +#ifndef GL_APPLE_flush_buffer_range +#define GL_APPLE_flush_buffer_range 1 + +#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 +#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 + +typedef void (GLAPIENTRY * PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size); + +#define glBufferParameteriAPPLE GLEW_GET_FUN(__glewBufferParameteriAPPLE) +#define glFlushMappedBufferRangeAPPLE GLEW_GET_FUN(__glewFlushMappedBufferRangeAPPLE) + +#define GLEW_APPLE_flush_buffer_range GLEW_GET_VAR(__GLEW_APPLE_flush_buffer_range) + +#endif /* GL_APPLE_flush_buffer_range */ + +/* ----------------------- GL_APPLE_object_purgeable ----------------------- */ + +#ifndef GL_APPLE_object_purgeable +#define GL_APPLE_object_purgeable 1 + +#define GL_BUFFER_OBJECT_APPLE 0x85B3 +#define GL_RELEASED_APPLE 0x8A19 +#define GL_VOLATILE_APPLE 0x8A1A +#define GL_RETAINED_APPLE 0x8A1B +#define GL_UNDEFINED_APPLE 0x8A1C +#define GL_PURGEABLE_APPLE 0x8A1D + +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint* params); +typedef GLenum (GLAPIENTRY * PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); +typedef GLenum (GLAPIENTRY * PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option); + +#define glGetObjectParameterivAPPLE GLEW_GET_FUN(__glewGetObjectParameterivAPPLE) +#define glObjectPurgeableAPPLE GLEW_GET_FUN(__glewObjectPurgeableAPPLE) +#define glObjectUnpurgeableAPPLE GLEW_GET_FUN(__glewObjectUnpurgeableAPPLE) + +#define GLEW_APPLE_object_purgeable GLEW_GET_VAR(__GLEW_APPLE_object_purgeable) + +#endif /* GL_APPLE_object_purgeable */ + +/* ------------------------- GL_APPLE_pixel_buffer ------------------------- */ + +#ifndef GL_APPLE_pixel_buffer +#define GL_APPLE_pixel_buffer 1 + +#define GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE 0x8A10 + +#define GLEW_APPLE_pixel_buffer GLEW_GET_VAR(__GLEW_APPLE_pixel_buffer) + +#endif /* GL_APPLE_pixel_buffer */ + +/* ---------------------------- GL_APPLE_rgb_422 --------------------------- */ + +#ifndef GL_APPLE_rgb_422 +#define GL_APPLE_rgb_422 1 + +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#define GL_RGB_422_APPLE 0x8A1F + +#define GLEW_APPLE_rgb_422 GLEW_GET_VAR(__GLEW_APPLE_rgb_422) + +#endif /* GL_APPLE_rgb_422 */ + +/* --------------------------- GL_APPLE_row_bytes -------------------------- */ + +#ifndef GL_APPLE_row_bytes +#define GL_APPLE_row_bytes 1 + +#define GL_PACK_ROW_BYTES_APPLE 0x8A15 +#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16 + +#define GLEW_APPLE_row_bytes GLEW_GET_VAR(__GLEW_APPLE_row_bytes) + +#endif /* GL_APPLE_row_bytes */ + +/* ------------------------ GL_APPLE_specular_vector ----------------------- */ + +#ifndef GL_APPLE_specular_vector +#define GL_APPLE_specular_vector 1 + +#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 + +#define GLEW_APPLE_specular_vector GLEW_GET_VAR(__GLEW_APPLE_specular_vector) + +#endif /* GL_APPLE_specular_vector */ + +/* ------------------------- GL_APPLE_texture_range ------------------------ */ + +#ifndef GL_APPLE_texture_range +#define GL_APPLE_texture_range 1 + +#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7 +#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8 +#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC +#define GL_STORAGE_PRIVATE_APPLE 0x85BD +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF + +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid **params); +typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer); + +#define glGetTexParameterPointervAPPLE GLEW_GET_FUN(__glewGetTexParameterPointervAPPLE) +#define glTextureRangeAPPLE GLEW_GET_FUN(__glewTextureRangeAPPLE) + +#define GLEW_APPLE_texture_range GLEW_GET_VAR(__GLEW_APPLE_texture_range) + +#endif /* GL_APPLE_texture_range */ + +/* ------------------------ GL_APPLE_transform_hint ------------------------ */ + +#ifndef GL_APPLE_transform_hint +#define GL_APPLE_transform_hint 1 + +#define GL_TRANSFORM_HINT_APPLE 0x85B1 + +#define GLEW_APPLE_transform_hint GLEW_GET_VAR(__GLEW_APPLE_transform_hint) + +#endif /* GL_APPLE_transform_hint */ + +/* ---------------------- GL_APPLE_vertex_array_object --------------------- */ + +#ifndef GL_APPLE_vertex_array_object +#define GL_APPLE_vertex_array_object 1 + +#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 + +typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); +typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint* arrays); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); + +#define glBindVertexArrayAPPLE GLEW_GET_FUN(__glewBindVertexArrayAPPLE) +#define glDeleteVertexArraysAPPLE GLEW_GET_FUN(__glewDeleteVertexArraysAPPLE) +#define glGenVertexArraysAPPLE GLEW_GET_FUN(__glewGenVertexArraysAPPLE) +#define glIsVertexArrayAPPLE GLEW_GET_FUN(__glewIsVertexArrayAPPLE) + +#define GLEW_APPLE_vertex_array_object GLEW_GET_VAR(__GLEW_APPLE_vertex_array_object) + +#endif /* GL_APPLE_vertex_array_object */ + +/* ---------------------- GL_APPLE_vertex_array_range ---------------------- */ + +#ifndef GL_APPLE_vertex_array_range +#define GL_APPLE_vertex_array_range 1 + +#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E +#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 +#define GL_STORAGE_CLIENT_APPLE 0x85B4 +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF + +typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); + +#define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE) +#define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE) +#define glVertexArrayRangeAPPLE GLEW_GET_FUN(__glewVertexArrayRangeAPPLE) + +#define GLEW_APPLE_vertex_array_range GLEW_GET_VAR(__GLEW_APPLE_vertex_array_range) + +#endif /* GL_APPLE_vertex_array_range */ + +/* ------------------- GL_APPLE_vertex_program_evaluators ------------------ */ + +#ifndef GL_APPLE_vertex_program_evaluators +#define GL_APPLE_vertex_program_evaluators 1 + +#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00 +#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01 +#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02 +#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03 +#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04 +#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05 +#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06 +#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07 +#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08 +#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09 + +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble* points); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble* points); +typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat* points); + +#define glDisableVertexAttribAPPLE GLEW_GET_FUN(__glewDisableVertexAttribAPPLE) +#define glEnableVertexAttribAPPLE GLEW_GET_FUN(__glewEnableVertexAttribAPPLE) +#define glIsVertexAttribEnabledAPPLE GLEW_GET_FUN(__glewIsVertexAttribEnabledAPPLE) +#define glMapVertexAttrib1dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1dAPPLE) +#define glMapVertexAttrib1fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib1fAPPLE) +#define glMapVertexAttrib2dAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2dAPPLE) +#define glMapVertexAttrib2fAPPLE GLEW_GET_FUN(__glewMapVertexAttrib2fAPPLE) + +#define GLEW_APPLE_vertex_program_evaluators GLEW_GET_VAR(__GLEW_APPLE_vertex_program_evaluators) + +#endif /* GL_APPLE_vertex_program_evaluators */ + +/* --------------------------- GL_APPLE_ycbcr_422 -------------------------- */ + +#ifndef GL_APPLE_ycbcr_422 +#define GL_APPLE_ycbcr_422 1 + +#define GL_YCBCR_422_APPLE 0x85B9 +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB + +#define GLEW_APPLE_ycbcr_422 GLEW_GET_VAR(__GLEW_APPLE_ycbcr_422) + +#endif /* GL_APPLE_ycbcr_422 */ + +/* ------------------------ GL_ARB_ES2_compatibility ----------------------- */ + +#ifndef GL_ARB_ES2_compatibility +#define GL_ARB_ES2_compatibility 1 + +#define GL_FIXED 0x140C +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf d); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f); +typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint *precision); +typedef void (GLAPIENTRY * PFNGLRELEASESHADERCOMPILERPROC) (void); +typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* shaders, GLenum binaryformat, const GLvoid*binary, GLsizei length); + +#define glClearDepthf GLEW_GET_FUN(__glewClearDepthf) +#define glDepthRangef GLEW_GET_FUN(__glewDepthRangef) +#define glGetShaderPrecisionFormat GLEW_GET_FUN(__glewGetShaderPrecisionFormat) +#define glReleaseShaderCompiler GLEW_GET_FUN(__glewReleaseShaderCompiler) +#define glShaderBinary GLEW_GET_FUN(__glewShaderBinary) + +#define GLEW_ARB_ES2_compatibility GLEW_GET_VAR(__GLEW_ARB_ES2_compatibility) + +#endif /* GL_ARB_ES2_compatibility */ + +/* ----------------------- GL_ARB_blend_func_extended ---------------------- */ + +#ifndef GL_ARB_blend_func_extended +#define GL_ARB_blend_func_extended 1 + +#define GL_SRC1_COLOR 0x88F9 +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC + +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const char * name); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const char * name); + +#define glBindFragDataLocationIndexed GLEW_GET_FUN(__glewBindFragDataLocationIndexed) +#define glGetFragDataIndex GLEW_GET_FUN(__glewGetFragDataIndex) + +#define GLEW_ARB_blend_func_extended GLEW_GET_VAR(__GLEW_ARB_blend_func_extended) + +#endif /* GL_ARB_blend_func_extended */ + +/* ---------------------------- GL_ARB_cl_event ---------------------------- */ + +#ifndef GL_ARB_cl_event +#define GL_ARB_cl_event 1 + +#define GL_SYNC_CL_EVENT_ARB 0x8240 +#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241 + +typedef struct _cl_context *cl_context; +typedef struct _cl_event *cl_event; + +typedef GLsync (GLAPIENTRY * PFNGLCREATESYNCFROMCLEVENTARBPROC) (cl_context context, cl_event event, GLbitfield flags); + +#define glCreateSyncFromCLeventARB GLEW_GET_FUN(__glewCreateSyncFromCLeventARB) + +#define GLEW_ARB_cl_event GLEW_GET_VAR(__GLEW_ARB_cl_event) + +#endif /* GL_ARB_cl_event */ + +/* ----------------------- GL_ARB_color_buffer_float ----------------------- */ + +#ifndef GL_ARB_color_buffer_float +#define GL_ARB_color_buffer_float 1 + +#define GL_RGBA_FLOAT_MODE_ARB 0x8820 +#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A +#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B +#define GL_CLAMP_READ_COLOR_ARB 0x891C +#define GL_FIXED_ONLY_ARB 0x891D + +typedef void (GLAPIENTRY * PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); + +#define glClampColorARB GLEW_GET_FUN(__glewClampColorARB) + +#define GLEW_ARB_color_buffer_float GLEW_GET_VAR(__GLEW_ARB_color_buffer_float) + +#endif /* GL_ARB_color_buffer_float */ + +/* -------------------------- GL_ARB_compatibility ------------------------- */ + +#ifndef GL_ARB_compatibility +#define GL_ARB_compatibility 1 + +#define GLEW_ARB_compatibility GLEW_GET_VAR(__GLEW_ARB_compatibility) + +#endif /* GL_ARB_compatibility */ + +/* --------------------------- GL_ARB_copy_buffer -------------------------- */ + +#ifndef GL_ARB_copy_buffer +#define GL_ARB_copy_buffer 1 + +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 + +typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size); + +#define glCopyBufferSubData GLEW_GET_FUN(__glewCopyBufferSubData) + +#define GLEW_ARB_copy_buffer GLEW_GET_VAR(__GLEW_ARB_copy_buffer) + +#endif /* GL_ARB_copy_buffer */ + +/* -------------------------- GL_ARB_debug_output -------------------------- */ + +#ifndef GL_ARB_debug_output +#define GL_ARB_debug_output 1 + +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 +#define GL_DEBUG_SOURCE_API_ARB 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A +#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B +#define GL_DEBUG_TYPE_ERROR_ARB 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E +#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 +#define GL_DEBUG_TYPE_OTHER_ARB 0x8251 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145 +#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 +#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 + +typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); + +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, void* userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, char* messageLog); + +#define glDebugMessageCallbackARB GLEW_GET_FUN(__glewDebugMessageCallbackARB) +#define glDebugMessageControlARB GLEW_GET_FUN(__glewDebugMessageControlARB) +#define glDebugMessageInsertARB GLEW_GET_FUN(__glewDebugMessageInsertARB) +#define glGetDebugMessageLogARB GLEW_GET_FUN(__glewGetDebugMessageLogARB) + +#define GLEW_ARB_debug_output GLEW_GET_VAR(__GLEW_ARB_debug_output) + +#endif /* GL_ARB_debug_output */ + +/* ----------------------- GL_ARB_depth_buffer_float ----------------------- */ + +#ifndef GL_ARB_depth_buffer_float +#define GL_ARB_depth_buffer_float 1 + +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD + +#define GLEW_ARB_depth_buffer_float GLEW_GET_VAR(__GLEW_ARB_depth_buffer_float) + +#endif /* GL_ARB_depth_buffer_float */ + +/* --------------------------- GL_ARB_depth_clamp -------------------------- */ + +#ifndef GL_ARB_depth_clamp +#define GL_ARB_depth_clamp 1 + +#define GL_DEPTH_CLAMP 0x864F + +#define GLEW_ARB_depth_clamp GLEW_GET_VAR(__GLEW_ARB_depth_clamp) + +#endif /* GL_ARB_depth_clamp */ + +/* -------------------------- GL_ARB_depth_texture ------------------------- */ + +#ifndef GL_ARB_depth_texture +#define GL_ARB_depth_texture 1 + +#define GL_DEPTH_COMPONENT16_ARB 0x81A5 +#define GL_DEPTH_COMPONENT24_ARB 0x81A6 +#define GL_DEPTH_COMPONENT32_ARB 0x81A7 +#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A +#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B + +#define GLEW_ARB_depth_texture GLEW_GET_VAR(__GLEW_ARB_depth_texture) + +#endif /* GL_ARB_depth_texture */ + +/* -------------------------- GL_ARB_draw_buffers -------------------------- */ + +#ifndef GL_ARB_draw_buffers +#define GL_ARB_draw_buffers 1 + +#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 +#define GL_DRAW_BUFFER0_ARB 0x8825 +#define GL_DRAW_BUFFER1_ARB 0x8826 +#define GL_DRAW_BUFFER2_ARB 0x8827 +#define GL_DRAW_BUFFER3_ARB 0x8828 +#define GL_DRAW_BUFFER4_ARB 0x8829 +#define GL_DRAW_BUFFER5_ARB 0x882A +#define GL_DRAW_BUFFER6_ARB 0x882B +#define GL_DRAW_BUFFER7_ARB 0x882C +#define GL_DRAW_BUFFER8_ARB 0x882D +#define GL_DRAW_BUFFER9_ARB 0x882E +#define GL_DRAW_BUFFER10_ARB 0x882F +#define GL_DRAW_BUFFER11_ARB 0x8830 +#define GL_DRAW_BUFFER12_ARB 0x8831 +#define GL_DRAW_BUFFER13_ARB 0x8832 +#define GL_DRAW_BUFFER14_ARB 0x8833 +#define GL_DRAW_BUFFER15_ARB 0x8834 + +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum* bufs); + +#define glDrawBuffersARB GLEW_GET_FUN(__glewDrawBuffersARB) + +#define GLEW_ARB_draw_buffers GLEW_GET_VAR(__GLEW_ARB_draw_buffers) + +#endif /* GL_ARB_draw_buffers */ + +/* ----------------------- GL_ARB_draw_buffers_blend ----------------------- */ + +#ifndef GL_ARB_draw_buffers_blend +#define GL_ARB_draw_buffers_blend 1 + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GLAPIENTRY * PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst); + +#define glBlendEquationSeparateiARB GLEW_GET_FUN(__glewBlendEquationSeparateiARB) +#define glBlendEquationiARB GLEW_GET_FUN(__glewBlendEquationiARB) +#define glBlendFuncSeparateiARB GLEW_GET_FUN(__glewBlendFuncSeparateiARB) +#define glBlendFunciARB GLEW_GET_FUN(__glewBlendFunciARB) + +#define GLEW_ARB_draw_buffers_blend GLEW_GET_VAR(__GLEW_ARB_draw_buffers_blend) + +#endif /* GL_ARB_draw_buffers_blend */ + +/* -------------------- GL_ARB_draw_elements_base_vertex ------------------- */ + +#ifndef GL_ARB_draw_elements_base_vertex +#define GL_ARB_draw_elements_base_vertex 1 + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, void* indices, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void* indices, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei* count, GLenum type, GLvoid**indices, GLsizei primcount, GLint *basevertex); + +#define glDrawElementsBaseVertex GLEW_GET_FUN(__glewDrawElementsBaseVertex) +#define glDrawElementsInstancedBaseVertex GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertex) +#define glDrawRangeElementsBaseVertex GLEW_GET_FUN(__glewDrawRangeElementsBaseVertex) +#define glMultiDrawElementsBaseVertex GLEW_GET_FUN(__glewMultiDrawElementsBaseVertex) + +#define GLEW_ARB_draw_elements_base_vertex GLEW_GET_VAR(__GLEW_ARB_draw_elements_base_vertex) + +#endif /* GL_ARB_draw_elements_base_vertex */ + +/* -------------------------- GL_ARB_draw_indirect ------------------------- */ + +#ifndef GL_ARB_draw_indirect +#define GL_ARB_draw_indirect 1 + +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void* indirect); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void* indirect); + +#define glDrawArraysIndirect GLEW_GET_FUN(__glewDrawArraysIndirect) +#define glDrawElementsIndirect GLEW_GET_FUN(__glewDrawElementsIndirect) + +#define GLEW_ARB_draw_indirect GLEW_GET_VAR(__GLEW_ARB_draw_indirect) + +#endif /* GL_ARB_draw_indirect */ + +/* ------------------------- GL_ARB_draw_instanced ------------------------- */ + +#ifndef GL_ARB_draw_instanced +#define GL_ARB_draw_instanced 1 + +#define GLEW_ARB_draw_instanced GLEW_GET_VAR(__GLEW_ARB_draw_instanced) + +#endif /* GL_ARB_draw_instanced */ + +/* -------------------- GL_ARB_explicit_attrib_location -------------------- */ + +#ifndef GL_ARB_explicit_attrib_location +#define GL_ARB_explicit_attrib_location 1 + +#define GLEW_ARB_explicit_attrib_location GLEW_GET_VAR(__GLEW_ARB_explicit_attrib_location) + +#endif /* GL_ARB_explicit_attrib_location */ + +/* ------------------- GL_ARB_fragment_coord_conventions ------------------- */ + +#ifndef GL_ARB_fragment_coord_conventions +#define GL_ARB_fragment_coord_conventions 1 + +#define GLEW_ARB_fragment_coord_conventions GLEW_GET_VAR(__GLEW_ARB_fragment_coord_conventions) + +#endif /* GL_ARB_fragment_coord_conventions */ + +/* ------------------------ GL_ARB_fragment_program ------------------------ */ + +#ifndef GL_ARB_fragment_program +#define GL_ARB_fragment_program 1 + +#define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 +#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 +#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 +#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 +#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 +#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A +#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B +#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C +#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D +#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E +#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F +#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 +#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 + +#define GLEW_ARB_fragment_program GLEW_GET_VAR(__GLEW_ARB_fragment_program) + +#endif /* GL_ARB_fragment_program */ + +/* --------------------- GL_ARB_fragment_program_shadow -------------------- */ + +#ifndef GL_ARB_fragment_program_shadow +#define GL_ARB_fragment_program_shadow 1 + +#define GLEW_ARB_fragment_program_shadow GLEW_GET_VAR(__GLEW_ARB_fragment_program_shadow) + +#endif /* GL_ARB_fragment_program_shadow */ + +/* ------------------------- GL_ARB_fragment_shader ------------------------ */ + +#ifndef GL_ARB_fragment_shader +#define GL_ARB_fragment_shader 1 + +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B + +#define GLEW_ARB_fragment_shader GLEW_GET_VAR(__GLEW_ARB_fragment_shader) + +#endif /* GL_ARB_fragment_shader */ + +/* ----------------------- GL_ARB_framebuffer_object ----------------------- */ + +#ifndef GL_ARB_framebuffer_object +#define GL_ARB_framebuffer_object 1 + +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_INDEX 0x8222 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_SRGB 0x8C40 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 + +typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); +typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target,GLenum attachment, GLuint texture,GLint level,GLint layer); +typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); +typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glBindFramebuffer GLEW_GET_FUN(__glewBindFramebuffer) +#define glBindRenderbuffer GLEW_GET_FUN(__glewBindRenderbuffer) +#define glBlitFramebuffer GLEW_GET_FUN(__glewBlitFramebuffer) +#define glCheckFramebufferStatus GLEW_GET_FUN(__glewCheckFramebufferStatus) +#define glDeleteFramebuffers GLEW_GET_FUN(__glewDeleteFramebuffers) +#define glDeleteRenderbuffers GLEW_GET_FUN(__glewDeleteRenderbuffers) +#define glFramebufferRenderbuffer GLEW_GET_FUN(__glewFramebufferRenderbuffer) +#define glFramebufferTexture1D GLEW_GET_FUN(__glewFramebufferTexture1D) +#define glFramebufferTexture2D GLEW_GET_FUN(__glewFramebufferTexture2D) +#define glFramebufferTexture3D GLEW_GET_FUN(__glewFramebufferTexture3D) +#define glFramebufferTextureLayer GLEW_GET_FUN(__glewFramebufferTextureLayer) +#define glGenFramebuffers GLEW_GET_FUN(__glewGenFramebuffers) +#define glGenRenderbuffers GLEW_GET_FUN(__glewGenRenderbuffers) +#define glGenerateMipmap GLEW_GET_FUN(__glewGenerateMipmap) +#define glGetFramebufferAttachmentParameteriv GLEW_GET_FUN(__glewGetFramebufferAttachmentParameteriv) +#define glGetRenderbufferParameteriv GLEW_GET_FUN(__glewGetRenderbufferParameteriv) +#define glIsFramebuffer GLEW_GET_FUN(__glewIsFramebuffer) +#define glIsRenderbuffer GLEW_GET_FUN(__glewIsRenderbuffer) +#define glRenderbufferStorage GLEW_GET_FUN(__glewRenderbufferStorage) +#define glRenderbufferStorageMultisample GLEW_GET_FUN(__glewRenderbufferStorageMultisample) + +#define GLEW_ARB_framebuffer_object GLEW_GET_VAR(__GLEW_ARB_framebuffer_object) + +#endif /* GL_ARB_framebuffer_object */ + +/* ------------------------ GL_ARB_framebuffer_sRGB ------------------------ */ + +#ifndef GL_ARB_framebuffer_sRGB +#define GL_ARB_framebuffer_sRGB 1 + +#define GL_FRAMEBUFFER_SRGB 0x8DB9 + +#define GLEW_ARB_framebuffer_sRGB GLEW_GET_VAR(__GLEW_ARB_framebuffer_sRGB) + +#endif /* GL_ARB_framebuffer_sRGB */ + +/* ------------------------ GL_ARB_geometry_shader4 ------------------------ */ + +#ifndef GL_ARB_geometry_shader4 +#define GL_ARB_geometry_shader4 1 + +#define GL_LINES_ADJACENCY_ARB 0xA +#define GL_LINE_STRIP_ADJACENCY_ARB 0xB +#define GL_TRIANGLES_ADJACENCY_ARB 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0xD +#define GL_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 +#define GL_GEOMETRY_SHADER_ARB 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value); + +#define glFramebufferTextureARB GLEW_GET_FUN(__glewFramebufferTextureARB) +#define glFramebufferTextureFaceARB GLEW_GET_FUN(__glewFramebufferTextureFaceARB) +#define glFramebufferTextureLayerARB GLEW_GET_FUN(__glewFramebufferTextureLayerARB) +#define glProgramParameteriARB GLEW_GET_FUN(__glewProgramParameteriARB) + +#define GLEW_ARB_geometry_shader4 GLEW_GET_VAR(__GLEW_ARB_geometry_shader4) + +#endif /* GL_ARB_geometry_shader4 */ + +/* ----------------------- GL_ARB_get_program_binary ----------------------- */ + +#ifndef GL_ARB_get_program_binary +#define GL_ARB_get_program_binary 1 + +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF + +typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary); +typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLsizei length); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); + +#define glGetProgramBinary GLEW_GET_FUN(__glewGetProgramBinary) +#define glProgramBinary GLEW_GET_FUN(__glewProgramBinary) +#define glProgramParameteri GLEW_GET_FUN(__glewProgramParameteri) + +#define GLEW_ARB_get_program_binary GLEW_GET_VAR(__GLEW_ARB_get_program_binary) + +#endif /* GL_ARB_get_program_binary */ + +/* --------------------------- GL_ARB_gpu_shader5 -------------------------- */ + +#ifndef GL_ARB_gpu_shader5 +#define GL_ARB_gpu_shader5 1 + +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_MAX_VERTEX_STREAMS 0x8E71 + +#define GLEW_ARB_gpu_shader5 GLEW_GET_VAR(__GLEW_ARB_gpu_shader5) + +#endif /* GL_ARB_gpu_shader5 */ + +/* ------------------------- GL_ARB_gpu_shader_fp64 ------------------------ */ + +#ifndef GL_ARB_gpu_shader_fp64 +#define GL_ARB_gpu_shader_fp64 1 + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +typedef void (GLAPIENTRY * PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1DPROC) (GLint location, GLdouble x); +typedef void (GLAPIENTRY * PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); + +#define glGetUniformdv GLEW_GET_FUN(__glewGetUniformdv) +#define glProgramUniform1dEXT GLEW_GET_FUN(__glewProgramUniform1dEXT) +#define glProgramUniform1dvEXT GLEW_GET_FUN(__glewProgramUniform1dvEXT) +#define glProgramUniform2dEXT GLEW_GET_FUN(__glewProgramUniform2dEXT) +#define glProgramUniform2dvEXT GLEW_GET_FUN(__glewProgramUniform2dvEXT) +#define glProgramUniform3dEXT GLEW_GET_FUN(__glewProgramUniform3dEXT) +#define glProgramUniform3dvEXT GLEW_GET_FUN(__glewProgramUniform3dvEXT) +#define glProgramUniform4dEXT GLEW_GET_FUN(__glewProgramUniform4dEXT) +#define glProgramUniform4dvEXT GLEW_GET_FUN(__glewProgramUniform4dvEXT) +#define glProgramUniformMatrix2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2dvEXT) +#define glProgramUniformMatrix2x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3dvEXT) +#define glProgramUniformMatrix2x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4dvEXT) +#define glProgramUniformMatrix3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3dvEXT) +#define glProgramUniformMatrix3x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2dvEXT) +#define glProgramUniformMatrix3x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4dvEXT) +#define glProgramUniformMatrix4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4dvEXT) +#define glProgramUniformMatrix4x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2dvEXT) +#define glProgramUniformMatrix4x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3dvEXT) +#define glUniform1d GLEW_GET_FUN(__glewUniform1d) +#define glUniform1dv GLEW_GET_FUN(__glewUniform1dv) +#define glUniform2d GLEW_GET_FUN(__glewUniform2d) +#define glUniform2dv GLEW_GET_FUN(__glewUniform2dv) +#define glUniform3d GLEW_GET_FUN(__glewUniform3d) +#define glUniform3dv GLEW_GET_FUN(__glewUniform3dv) +#define glUniform4d GLEW_GET_FUN(__glewUniform4d) +#define glUniform4dv GLEW_GET_FUN(__glewUniform4dv) +#define glUniformMatrix2dv GLEW_GET_FUN(__glewUniformMatrix2dv) +#define glUniformMatrix2x3dv GLEW_GET_FUN(__glewUniformMatrix2x3dv) +#define glUniformMatrix2x4dv GLEW_GET_FUN(__glewUniformMatrix2x4dv) +#define glUniformMatrix3dv GLEW_GET_FUN(__glewUniformMatrix3dv) +#define glUniformMatrix3x2dv GLEW_GET_FUN(__glewUniformMatrix3x2dv) +#define glUniformMatrix3x4dv GLEW_GET_FUN(__glewUniformMatrix3x4dv) +#define glUniformMatrix4dv GLEW_GET_FUN(__glewUniformMatrix4dv) +#define glUniformMatrix4x2dv GLEW_GET_FUN(__glewUniformMatrix4x2dv) +#define glUniformMatrix4x3dv GLEW_GET_FUN(__glewUniformMatrix4x3dv) + +#define GLEW_ARB_gpu_shader_fp64 GLEW_GET_VAR(__GLEW_ARB_gpu_shader_fp64) + +#endif /* GL_ARB_gpu_shader_fp64 */ + +/* ------------------------ GL_ARB_half_float_pixel ------------------------ */ + +#ifndef GL_ARB_half_float_pixel +#define GL_ARB_half_float_pixel 1 + +#define GL_HALF_FLOAT_ARB 0x140B + +#define GLEW_ARB_half_float_pixel GLEW_GET_VAR(__GLEW_ARB_half_float_pixel) + +#endif /* GL_ARB_half_float_pixel */ + +/* ------------------------ GL_ARB_half_float_vertex ----------------------- */ + +#ifndef GL_ARB_half_float_vertex +#define GL_ARB_half_float_vertex 1 + +#define GL_HALF_FLOAT 0x140B + +#define GLEW_ARB_half_float_vertex GLEW_GET_VAR(__GLEW_ARB_half_float_vertex) + +#endif /* GL_ARB_half_float_vertex */ + +/* ----------------------------- GL_ARB_imaging ---------------------------- */ + +#ifndef GL_ARB_imaging +#define GL_ARB_imaging 1 + +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BLEND_EQUATION 0x8009 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_IGNORE_BORDER 0x8150 +#define GL_CONSTANT_BORDER 0x8151 +#define GL_WRAP_BORDER 0x8152 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 + +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (GLAPIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLRESETMINMAXPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); + +#define glColorSubTable GLEW_GET_FUN(__glewColorSubTable) +#define glColorTable GLEW_GET_FUN(__glewColorTable) +#define glColorTableParameterfv GLEW_GET_FUN(__glewColorTableParameterfv) +#define glColorTableParameteriv GLEW_GET_FUN(__glewColorTableParameteriv) +#define glConvolutionFilter1D GLEW_GET_FUN(__glewConvolutionFilter1D) +#define glConvolutionFilter2D GLEW_GET_FUN(__glewConvolutionFilter2D) +#define glConvolutionParameterf GLEW_GET_FUN(__glewConvolutionParameterf) +#define glConvolutionParameterfv GLEW_GET_FUN(__glewConvolutionParameterfv) +#define glConvolutionParameteri GLEW_GET_FUN(__glewConvolutionParameteri) +#define glConvolutionParameteriv GLEW_GET_FUN(__glewConvolutionParameteriv) +#define glCopyColorSubTable GLEW_GET_FUN(__glewCopyColorSubTable) +#define glCopyColorTable GLEW_GET_FUN(__glewCopyColorTable) +#define glCopyConvolutionFilter1D GLEW_GET_FUN(__glewCopyConvolutionFilter1D) +#define glCopyConvolutionFilter2D GLEW_GET_FUN(__glewCopyConvolutionFilter2D) +#define glGetColorTable GLEW_GET_FUN(__glewGetColorTable) +#define glGetColorTableParameterfv GLEW_GET_FUN(__glewGetColorTableParameterfv) +#define glGetColorTableParameteriv GLEW_GET_FUN(__glewGetColorTableParameteriv) +#define glGetConvolutionFilter GLEW_GET_FUN(__glewGetConvolutionFilter) +#define glGetConvolutionParameterfv GLEW_GET_FUN(__glewGetConvolutionParameterfv) +#define glGetConvolutionParameteriv GLEW_GET_FUN(__glewGetConvolutionParameteriv) +#define glGetHistogram GLEW_GET_FUN(__glewGetHistogram) +#define glGetHistogramParameterfv GLEW_GET_FUN(__glewGetHistogramParameterfv) +#define glGetHistogramParameteriv GLEW_GET_FUN(__glewGetHistogramParameteriv) +#define glGetMinmax GLEW_GET_FUN(__glewGetMinmax) +#define glGetMinmaxParameterfv GLEW_GET_FUN(__glewGetMinmaxParameterfv) +#define glGetMinmaxParameteriv GLEW_GET_FUN(__glewGetMinmaxParameteriv) +#define glGetSeparableFilter GLEW_GET_FUN(__glewGetSeparableFilter) +#define glHistogram GLEW_GET_FUN(__glewHistogram) +#define glMinmax GLEW_GET_FUN(__glewMinmax) +#define glResetHistogram GLEW_GET_FUN(__glewResetHistogram) +#define glResetMinmax GLEW_GET_FUN(__glewResetMinmax) +#define glSeparableFilter2D GLEW_GET_FUN(__glewSeparableFilter2D) + +#define GLEW_ARB_imaging GLEW_GET_VAR(__GLEW_ARB_imaging) + +#endif /* GL_ARB_imaging */ + +/* ------------------------ GL_ARB_instanced_arrays ------------------------ */ + +#ifndef GL_ARB_instanced_arrays +#define GL_ARB_instanced_arrays 1 + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor); + +#define glDrawArraysInstancedARB GLEW_GET_FUN(__glewDrawArraysInstancedARB) +#define glDrawElementsInstancedARB GLEW_GET_FUN(__glewDrawElementsInstancedARB) +#define glVertexAttribDivisorARB GLEW_GET_FUN(__glewVertexAttribDivisorARB) + +#define GLEW_ARB_instanced_arrays GLEW_GET_VAR(__GLEW_ARB_instanced_arrays) + +#endif /* GL_ARB_instanced_arrays */ + +/* ------------------------ GL_ARB_map_buffer_range ------------------------ */ + +#ifndef GL_ARB_map_buffer_range +#define GL_ARB_map_buffer_range 1 + +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 + +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + +#define glFlushMappedBufferRange GLEW_GET_FUN(__glewFlushMappedBufferRange) +#define glMapBufferRange GLEW_GET_FUN(__glewMapBufferRange) + +#define GLEW_ARB_map_buffer_range GLEW_GET_VAR(__GLEW_ARB_map_buffer_range) + +#endif /* GL_ARB_map_buffer_range */ + +/* ------------------------- GL_ARB_matrix_palette ------------------------- */ + +#ifndef GL_ARB_matrix_palette +#define GL_ARB_matrix_palette 1 + +#define GL_MATRIX_PALETTE_ARB 0x8840 +#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 +#define GL_MAX_PALETTE_MATRICES_ARB 0x8842 +#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 +#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 +#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 +#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 +#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 +#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 +#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 + +typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUBVARBPROC) (GLint size, GLubyte *indices); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUIVARBPROC) (GLint size, GLuint *indices); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *indices); + +#define glCurrentPaletteMatrixARB GLEW_GET_FUN(__glewCurrentPaletteMatrixARB) +#define glMatrixIndexPointerARB GLEW_GET_FUN(__glewMatrixIndexPointerARB) +#define glMatrixIndexubvARB GLEW_GET_FUN(__glewMatrixIndexubvARB) +#define glMatrixIndexuivARB GLEW_GET_FUN(__glewMatrixIndexuivARB) +#define glMatrixIndexusvARB GLEW_GET_FUN(__glewMatrixIndexusvARB) + +#define GLEW_ARB_matrix_palette GLEW_GET_VAR(__GLEW_ARB_matrix_palette) + +#endif /* GL_ARB_matrix_palette */ + +/* --------------------------- GL_ARB_multisample -------------------------- */ + +#ifndef GL_ARB_multisample +#define GL_ARB_multisample 1 + +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); + +#define glSampleCoverageARB GLEW_GET_FUN(__glewSampleCoverageARB) + +#define GLEW_ARB_multisample GLEW_GET_VAR(__GLEW_ARB_multisample) + +#endif /* GL_ARB_multisample */ + +/* -------------------------- GL_ARB_multitexture -------------------------- */ + +#ifndef GL_ARB_multitexture +#define GL_ARB_multitexture 1 + +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 + +typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); + +#define glActiveTextureARB GLEW_GET_FUN(__glewActiveTextureARB) +#define glClientActiveTextureARB GLEW_GET_FUN(__glewClientActiveTextureARB) +#define glMultiTexCoord1dARB GLEW_GET_FUN(__glewMultiTexCoord1dARB) +#define glMultiTexCoord1dvARB GLEW_GET_FUN(__glewMultiTexCoord1dvARB) +#define glMultiTexCoord1fARB GLEW_GET_FUN(__glewMultiTexCoord1fARB) +#define glMultiTexCoord1fvARB GLEW_GET_FUN(__glewMultiTexCoord1fvARB) +#define glMultiTexCoord1iARB GLEW_GET_FUN(__glewMultiTexCoord1iARB) +#define glMultiTexCoord1ivARB GLEW_GET_FUN(__glewMultiTexCoord1ivARB) +#define glMultiTexCoord1sARB GLEW_GET_FUN(__glewMultiTexCoord1sARB) +#define glMultiTexCoord1svARB GLEW_GET_FUN(__glewMultiTexCoord1svARB) +#define glMultiTexCoord2dARB GLEW_GET_FUN(__glewMultiTexCoord2dARB) +#define glMultiTexCoord2dvARB GLEW_GET_FUN(__glewMultiTexCoord2dvARB) +#define glMultiTexCoord2fARB GLEW_GET_FUN(__glewMultiTexCoord2fARB) +#define glMultiTexCoord2fvARB GLEW_GET_FUN(__glewMultiTexCoord2fvARB) +#define glMultiTexCoord2iARB GLEW_GET_FUN(__glewMultiTexCoord2iARB) +#define glMultiTexCoord2ivARB GLEW_GET_FUN(__glewMultiTexCoord2ivARB) +#define glMultiTexCoord2sARB GLEW_GET_FUN(__glewMultiTexCoord2sARB) +#define glMultiTexCoord2svARB GLEW_GET_FUN(__glewMultiTexCoord2svARB) +#define glMultiTexCoord3dARB GLEW_GET_FUN(__glewMultiTexCoord3dARB) +#define glMultiTexCoord3dvARB GLEW_GET_FUN(__glewMultiTexCoord3dvARB) +#define glMultiTexCoord3fARB GLEW_GET_FUN(__glewMultiTexCoord3fARB) +#define glMultiTexCoord3fvARB GLEW_GET_FUN(__glewMultiTexCoord3fvARB) +#define glMultiTexCoord3iARB GLEW_GET_FUN(__glewMultiTexCoord3iARB) +#define glMultiTexCoord3ivARB GLEW_GET_FUN(__glewMultiTexCoord3ivARB) +#define glMultiTexCoord3sARB GLEW_GET_FUN(__glewMultiTexCoord3sARB) +#define glMultiTexCoord3svARB GLEW_GET_FUN(__glewMultiTexCoord3svARB) +#define glMultiTexCoord4dARB GLEW_GET_FUN(__glewMultiTexCoord4dARB) +#define glMultiTexCoord4dvARB GLEW_GET_FUN(__glewMultiTexCoord4dvARB) +#define glMultiTexCoord4fARB GLEW_GET_FUN(__glewMultiTexCoord4fARB) +#define glMultiTexCoord4fvARB GLEW_GET_FUN(__glewMultiTexCoord4fvARB) +#define glMultiTexCoord4iARB GLEW_GET_FUN(__glewMultiTexCoord4iARB) +#define glMultiTexCoord4ivARB GLEW_GET_FUN(__glewMultiTexCoord4ivARB) +#define glMultiTexCoord4sARB GLEW_GET_FUN(__glewMultiTexCoord4sARB) +#define glMultiTexCoord4svARB GLEW_GET_FUN(__glewMultiTexCoord4svARB) + +#define GLEW_ARB_multitexture GLEW_GET_VAR(__GLEW_ARB_multitexture) + +#endif /* GL_ARB_multitexture */ + +/* ------------------------- GL_ARB_occlusion_query ------------------------ */ + +#ifndef GL_ARB_occlusion_query +#define GL_ARB_occlusion_query 1 + +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 +#define GL_SAMPLES_PASSED_ARB 0x8914 + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDQUERYARBPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISQUERYARBPROC) (GLuint id); + +#define glBeginQueryARB GLEW_GET_FUN(__glewBeginQueryARB) +#define glDeleteQueriesARB GLEW_GET_FUN(__glewDeleteQueriesARB) +#define glEndQueryARB GLEW_GET_FUN(__glewEndQueryARB) +#define glGenQueriesARB GLEW_GET_FUN(__glewGenQueriesARB) +#define glGetQueryObjectivARB GLEW_GET_FUN(__glewGetQueryObjectivARB) +#define glGetQueryObjectuivARB GLEW_GET_FUN(__glewGetQueryObjectuivARB) +#define glGetQueryivARB GLEW_GET_FUN(__glewGetQueryivARB) +#define glIsQueryARB GLEW_GET_FUN(__glewIsQueryARB) + +#define GLEW_ARB_occlusion_query GLEW_GET_VAR(__GLEW_ARB_occlusion_query) + +#endif /* GL_ARB_occlusion_query */ + +/* ------------------------ GL_ARB_occlusion_query2 ------------------------ */ + +#ifndef GL_ARB_occlusion_query2 +#define GL_ARB_occlusion_query2 1 + +#define GL_ANY_SAMPLES_PASSED 0x8C2F + +#define GLEW_ARB_occlusion_query2 GLEW_GET_VAR(__GLEW_ARB_occlusion_query2) + +#endif /* GL_ARB_occlusion_query2 */ + +/* ----------------------- GL_ARB_pixel_buffer_object ---------------------- */ + +#ifndef GL_ARB_pixel_buffer_object +#define GL_ARB_pixel_buffer_object 1 + +#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF + +#define GLEW_ARB_pixel_buffer_object GLEW_GET_VAR(__GLEW_ARB_pixel_buffer_object) + +#endif /* GL_ARB_pixel_buffer_object */ + +/* ------------------------ GL_ARB_point_parameters ------------------------ */ + +#ifndef GL_ARB_point_parameters +#define GL_ARB_point_parameters 1 + +#define GL_POINT_SIZE_MIN_ARB 0x8126 +#define GL_POINT_SIZE_MAX_ARB 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat* params); + +#define glPointParameterfARB GLEW_GET_FUN(__glewPointParameterfARB) +#define glPointParameterfvARB GLEW_GET_FUN(__glewPointParameterfvARB) + +#define GLEW_ARB_point_parameters GLEW_GET_VAR(__GLEW_ARB_point_parameters) + +#endif /* GL_ARB_point_parameters */ + +/* -------------------------- GL_ARB_point_sprite -------------------------- */ + +#ifndef GL_ARB_point_sprite +#define GL_ARB_point_sprite 1 + +#define GL_POINT_SPRITE_ARB 0x8861 +#define GL_COORD_REPLACE_ARB 0x8862 + +#define GLEW_ARB_point_sprite GLEW_GET_VAR(__GLEW_ARB_point_sprite) + +#endif /* GL_ARB_point_sprite */ + +/* ------------------------ GL_ARB_provoking_vertex ------------------------ */ + +#ifndef GL_ARB_provoking_vertex +#define GL_ARB_provoking_vertex 1 + +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F + +typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXPROC) (GLenum mode); + +#define glProvokingVertex GLEW_GET_FUN(__glewProvokingVertex) + +#define GLEW_ARB_provoking_vertex GLEW_GET_VAR(__GLEW_ARB_provoking_vertex) + +#endif /* GL_ARB_provoking_vertex */ + +/* --------------------------- GL_ARB_robustness --------------------------- */ + +#ifndef GL_ARB_robustness +#define GL_ARB_robustness 1 + +#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253 +#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255 +#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GL_NO_RESET_NOTIFICATION_ARB 0x8261 + +typedef void (GLAPIENTRY * PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* table); +typedef void (GLAPIENTRY * PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void* img); +typedef void (GLAPIENTRY * PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* image); +typedef void (GLAPIENTRY * PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values); +typedef void (GLAPIENTRY * PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble* v); +typedef void (GLAPIENTRY * PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat* v); +typedef void (GLAPIENTRY * PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint* v); +typedef void (GLAPIENTRY * PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values); +typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat* values); +typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint* values); +typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort* values); +typedef void (GLAPIENTRY * PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte* pattern); +typedef void (GLAPIENTRY * PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void* row, GLsizei columnBufSize, GLvoid*column, GLvoid*span); +typedef void (GLAPIENTRY * PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* img); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint* params); +typedef void (GLAPIENTRY * PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void* data); + +#define glGetnColorTableARB GLEW_GET_FUN(__glewGetnColorTableARB) +#define glGetnCompressedTexImageARB GLEW_GET_FUN(__glewGetnCompressedTexImageARB) +#define glGetnConvolutionFilterARB GLEW_GET_FUN(__glewGetnConvolutionFilterARB) +#define glGetnHistogramARB GLEW_GET_FUN(__glewGetnHistogramARB) +#define glGetnMapdvARB GLEW_GET_FUN(__glewGetnMapdvARB) +#define glGetnMapfvARB GLEW_GET_FUN(__glewGetnMapfvARB) +#define glGetnMapivARB GLEW_GET_FUN(__glewGetnMapivARB) +#define glGetnMinmaxARB GLEW_GET_FUN(__glewGetnMinmaxARB) +#define glGetnPixelMapfvARB GLEW_GET_FUN(__glewGetnPixelMapfvARB) +#define glGetnPixelMapuivARB GLEW_GET_FUN(__glewGetnPixelMapuivARB) +#define glGetnPixelMapusvARB GLEW_GET_FUN(__glewGetnPixelMapusvARB) +#define glGetnPolygonStippleARB GLEW_GET_FUN(__glewGetnPolygonStippleARB) +#define glGetnSeparableFilterARB GLEW_GET_FUN(__glewGetnSeparableFilterARB) +#define glGetnTexImageARB GLEW_GET_FUN(__glewGetnTexImageARB) +#define glGetnUniformdvARB GLEW_GET_FUN(__glewGetnUniformdvARB) +#define glGetnUniformfvARB GLEW_GET_FUN(__glewGetnUniformfvARB) +#define glGetnUniformivARB GLEW_GET_FUN(__glewGetnUniformivARB) +#define glGetnUniformuivARB GLEW_GET_FUN(__glewGetnUniformuivARB) +#define glReadnPixelsARB GLEW_GET_FUN(__glewReadnPixelsARB) + +#define GLEW_ARB_robustness GLEW_GET_VAR(__GLEW_ARB_robustness) + +#endif /* GL_ARB_robustness */ + +/* ------------------------- GL_ARB_sample_shading ------------------------- */ + +#ifndef GL_ARB_sample_shading +#define GL_ARB_sample_shading 1 + +#define GL_SAMPLE_SHADING_ARB 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37 + +typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGARBPROC) (GLclampf value); + +#define glMinSampleShadingARB GLEW_GET_FUN(__glewMinSampleShadingARB) + +#define GLEW_ARB_sample_shading GLEW_GET_VAR(__GLEW_ARB_sample_shading) + +#endif /* GL_ARB_sample_shading */ + +/* ------------------------- GL_ARB_sampler_objects ------------------------ */ + +#ifndef GL_ARB_sampler_objects +#define GL_ARB_sampler_objects 1 + +#define GL_SAMPLER_BINDING 0x8919 + +typedef void (GLAPIENTRY * PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (GLAPIENTRY * PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint * samplers); +typedef void (GLAPIENTRY * PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint* samplers); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISSAMPLERPROC) (GLuint sampler); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint* params); + +#define glBindSampler GLEW_GET_FUN(__glewBindSampler) +#define glDeleteSamplers GLEW_GET_FUN(__glewDeleteSamplers) +#define glGenSamplers GLEW_GET_FUN(__glewGenSamplers) +#define glGetSamplerParameterIiv GLEW_GET_FUN(__glewGetSamplerParameterIiv) +#define glGetSamplerParameterIuiv GLEW_GET_FUN(__glewGetSamplerParameterIuiv) +#define glGetSamplerParameterfv GLEW_GET_FUN(__glewGetSamplerParameterfv) +#define glGetSamplerParameteriv GLEW_GET_FUN(__glewGetSamplerParameteriv) +#define glIsSampler GLEW_GET_FUN(__glewIsSampler) +#define glSamplerParameterIiv GLEW_GET_FUN(__glewSamplerParameterIiv) +#define glSamplerParameterIuiv GLEW_GET_FUN(__glewSamplerParameterIuiv) +#define glSamplerParameterf GLEW_GET_FUN(__glewSamplerParameterf) +#define glSamplerParameterfv GLEW_GET_FUN(__glewSamplerParameterfv) +#define glSamplerParameteri GLEW_GET_FUN(__glewSamplerParameteri) +#define glSamplerParameteriv GLEW_GET_FUN(__glewSamplerParameteriv) + +#define GLEW_ARB_sampler_objects GLEW_GET_VAR(__GLEW_ARB_sampler_objects) + +#endif /* GL_ARB_sampler_objects */ + +/* ------------------------ GL_ARB_seamless_cube_map ----------------------- */ + +#ifndef GL_ARB_seamless_cube_map +#define GL_ARB_seamless_cube_map 1 + +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F + +#define GLEW_ARB_seamless_cube_map GLEW_GET_VAR(__GLEW_ARB_seamless_cube_map) + +#endif /* GL_ARB_seamless_cube_map */ + +/* --------------------- GL_ARB_separate_shader_objects -------------------- */ + +#ifndef GL_ARB_separate_shader_objects +#define GL_ARB_separate_shader_objects 1 + +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_GEOMETRY_SHADER_BIT 0x00000004 +#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_ALL_SHADER_BITS 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const char ** strings); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, char *infoLog); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint x, GLuint y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); + +#define glActiveShaderProgram GLEW_GET_FUN(__glewActiveShaderProgram) +#define glBindProgramPipeline GLEW_GET_FUN(__glewBindProgramPipeline) +#define glCreateShaderProgramv GLEW_GET_FUN(__glewCreateShaderProgramv) +#define glDeleteProgramPipelines GLEW_GET_FUN(__glewDeleteProgramPipelines) +#define glGenProgramPipelines GLEW_GET_FUN(__glewGenProgramPipelines) +#define glGetProgramPipelineInfoLog GLEW_GET_FUN(__glewGetProgramPipelineInfoLog) +#define glGetProgramPipelineiv GLEW_GET_FUN(__glewGetProgramPipelineiv) +#define glIsProgramPipeline GLEW_GET_FUN(__glewIsProgramPipeline) +#define glProgramUniform1d GLEW_GET_FUN(__glewProgramUniform1d) +#define glProgramUniform1dv GLEW_GET_FUN(__glewProgramUniform1dv) +#define glProgramUniform1f GLEW_GET_FUN(__glewProgramUniform1f) +#define glProgramUniform1fv GLEW_GET_FUN(__glewProgramUniform1fv) +#define glProgramUniform1i GLEW_GET_FUN(__glewProgramUniform1i) +#define glProgramUniform1iv GLEW_GET_FUN(__glewProgramUniform1iv) +#define glProgramUniform1ui GLEW_GET_FUN(__glewProgramUniform1ui) +#define glProgramUniform1uiv GLEW_GET_FUN(__glewProgramUniform1uiv) +#define glProgramUniform2d GLEW_GET_FUN(__glewProgramUniform2d) +#define glProgramUniform2dv GLEW_GET_FUN(__glewProgramUniform2dv) +#define glProgramUniform2f GLEW_GET_FUN(__glewProgramUniform2f) +#define glProgramUniform2fv GLEW_GET_FUN(__glewProgramUniform2fv) +#define glProgramUniform2i GLEW_GET_FUN(__glewProgramUniform2i) +#define glProgramUniform2iv GLEW_GET_FUN(__glewProgramUniform2iv) +#define glProgramUniform2ui GLEW_GET_FUN(__glewProgramUniform2ui) +#define glProgramUniform2uiv GLEW_GET_FUN(__glewProgramUniform2uiv) +#define glProgramUniform3d GLEW_GET_FUN(__glewProgramUniform3d) +#define glProgramUniform3dv GLEW_GET_FUN(__glewProgramUniform3dv) +#define glProgramUniform3f GLEW_GET_FUN(__glewProgramUniform3f) +#define glProgramUniform3fv GLEW_GET_FUN(__glewProgramUniform3fv) +#define glProgramUniform3i GLEW_GET_FUN(__glewProgramUniform3i) +#define glProgramUniform3iv GLEW_GET_FUN(__glewProgramUniform3iv) +#define glProgramUniform3ui GLEW_GET_FUN(__glewProgramUniform3ui) +#define glProgramUniform3uiv GLEW_GET_FUN(__glewProgramUniform3uiv) +#define glProgramUniform4d GLEW_GET_FUN(__glewProgramUniform4d) +#define glProgramUniform4dv GLEW_GET_FUN(__glewProgramUniform4dv) +#define glProgramUniform4f GLEW_GET_FUN(__glewProgramUniform4f) +#define glProgramUniform4fv GLEW_GET_FUN(__glewProgramUniform4fv) +#define glProgramUniform4i GLEW_GET_FUN(__glewProgramUniform4i) +#define glProgramUniform4iv GLEW_GET_FUN(__glewProgramUniform4iv) +#define glProgramUniform4ui GLEW_GET_FUN(__glewProgramUniform4ui) +#define glProgramUniform4uiv GLEW_GET_FUN(__glewProgramUniform4uiv) +#define glProgramUniformMatrix2dv GLEW_GET_FUN(__glewProgramUniformMatrix2dv) +#define glProgramUniformMatrix2fv GLEW_GET_FUN(__glewProgramUniformMatrix2fv) +#define glProgramUniformMatrix2x3dv GLEW_GET_FUN(__glewProgramUniformMatrix2x3dv) +#define glProgramUniformMatrix2x3fv GLEW_GET_FUN(__glewProgramUniformMatrix2x3fv) +#define glProgramUniformMatrix2x4dv GLEW_GET_FUN(__glewProgramUniformMatrix2x4dv) +#define glProgramUniformMatrix2x4fv GLEW_GET_FUN(__glewProgramUniformMatrix2x4fv) +#define glProgramUniformMatrix3dv GLEW_GET_FUN(__glewProgramUniformMatrix3dv) +#define glProgramUniformMatrix3fv GLEW_GET_FUN(__glewProgramUniformMatrix3fv) +#define glProgramUniformMatrix3x2dv GLEW_GET_FUN(__glewProgramUniformMatrix3x2dv) +#define glProgramUniformMatrix3x2fv GLEW_GET_FUN(__glewProgramUniformMatrix3x2fv) +#define glProgramUniformMatrix3x4dv GLEW_GET_FUN(__glewProgramUniformMatrix3x4dv) +#define glProgramUniformMatrix3x4fv GLEW_GET_FUN(__glewProgramUniformMatrix3x4fv) +#define glProgramUniformMatrix4dv GLEW_GET_FUN(__glewProgramUniformMatrix4dv) +#define glProgramUniformMatrix4fv GLEW_GET_FUN(__glewProgramUniformMatrix4fv) +#define glProgramUniformMatrix4x2dv GLEW_GET_FUN(__glewProgramUniformMatrix4x2dv) +#define glProgramUniformMatrix4x2fv GLEW_GET_FUN(__glewProgramUniformMatrix4x2fv) +#define glProgramUniformMatrix4x3dv GLEW_GET_FUN(__glewProgramUniformMatrix4x3dv) +#define glProgramUniformMatrix4x3fv GLEW_GET_FUN(__glewProgramUniformMatrix4x3fv) +#define glUseProgramStages GLEW_GET_FUN(__glewUseProgramStages) +#define glValidateProgramPipeline GLEW_GET_FUN(__glewValidateProgramPipeline) + +#define GLEW_ARB_separate_shader_objects GLEW_GET_VAR(__GLEW_ARB_separate_shader_objects) + +#endif /* GL_ARB_separate_shader_objects */ + +/* ----------------------- GL_ARB_shader_bit_encoding ---------------------- */ + +#ifndef GL_ARB_shader_bit_encoding +#define GL_ARB_shader_bit_encoding 1 + +#define GLEW_ARB_shader_bit_encoding GLEW_GET_VAR(__GLEW_ARB_shader_bit_encoding) + +#endif /* GL_ARB_shader_bit_encoding */ + +/* ------------------------- GL_ARB_shader_objects ------------------------- */ + +#ifndef GL_ARB_shader_objects +#define GL_ARB_shader_objects 1 + +#define GL_PROGRAM_OBJECT_ARB 0x8B40 +#define GL_SHADER_OBJECT_ARB 0x8B48 +#define GL_OBJECT_TYPE_ARB 0x8B4E +#define GL_OBJECT_SUBTYPE_ARB 0x8B4F +#define GL_FLOAT_VEC2_ARB 0x8B50 +#define GL_FLOAT_VEC3_ARB 0x8B51 +#define GL_FLOAT_VEC4_ARB 0x8B52 +#define GL_INT_VEC2_ARB 0x8B53 +#define GL_INT_VEC3_ARB 0x8B54 +#define GL_INT_VEC4_ARB 0x8B55 +#define GL_BOOL_ARB 0x8B56 +#define GL_BOOL_VEC2_ARB 0x8B57 +#define GL_BOOL_VEC3_ARB 0x8B58 +#define GL_BOOL_VEC4_ARB 0x8B59 +#define GL_FLOAT_MAT2_ARB 0x8B5A +#define GL_FLOAT_MAT3_ARB 0x8B5B +#define GL_FLOAT_MAT4_ARB 0x8B5C +#define GL_SAMPLER_1D_ARB 0x8B5D +#define GL_SAMPLER_2D_ARB 0x8B5E +#define GL_SAMPLER_3D_ARB 0x8B5F +#define GL_SAMPLER_CUBE_ARB 0x8B60 +#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 +#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 +#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 +#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 +#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 + +typedef char GLcharARB; +typedef unsigned int GLhandleARB; + +typedef void (GLAPIENTRY * PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); +typedef GLhandleARB (GLAPIENTRY * PFNGLCREATEPROGRAMOBJECTARBPROC) (void); +typedef GLhandleARB (GLAPIENTRY * PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); +typedef void (GLAPIENTRY * PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); +typedef void (GLAPIENTRY * PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name); +typedef void (GLAPIENTRY * PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei* count, GLhandleARB *obj); +typedef GLhandleARB (GLAPIENTRY * PFNGLGETHANDLEARBPROC) (GLenum pname); +typedef void (GLAPIENTRY * PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *infoLog); +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB *source); +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint* params); +typedef void (GLAPIENTRY * PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRY * PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint *length); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); +typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); + +#define glAttachObjectARB GLEW_GET_FUN(__glewAttachObjectARB) +#define glCompileShaderARB GLEW_GET_FUN(__glewCompileShaderARB) +#define glCreateProgramObjectARB GLEW_GET_FUN(__glewCreateProgramObjectARB) +#define glCreateShaderObjectARB GLEW_GET_FUN(__glewCreateShaderObjectARB) +#define glDeleteObjectARB GLEW_GET_FUN(__glewDeleteObjectARB) +#define glDetachObjectARB GLEW_GET_FUN(__glewDetachObjectARB) +#define glGetActiveUniformARB GLEW_GET_FUN(__glewGetActiveUniformARB) +#define glGetAttachedObjectsARB GLEW_GET_FUN(__glewGetAttachedObjectsARB) +#define glGetHandleARB GLEW_GET_FUN(__glewGetHandleARB) +#define glGetInfoLogARB GLEW_GET_FUN(__glewGetInfoLogARB) +#define glGetObjectParameterfvARB GLEW_GET_FUN(__glewGetObjectParameterfvARB) +#define glGetObjectParameterivARB GLEW_GET_FUN(__glewGetObjectParameterivARB) +#define glGetShaderSourceARB GLEW_GET_FUN(__glewGetShaderSourceARB) +#define glGetUniformLocationARB GLEW_GET_FUN(__glewGetUniformLocationARB) +#define glGetUniformfvARB GLEW_GET_FUN(__glewGetUniformfvARB) +#define glGetUniformivARB GLEW_GET_FUN(__glewGetUniformivARB) +#define glLinkProgramARB GLEW_GET_FUN(__glewLinkProgramARB) +#define glShaderSourceARB GLEW_GET_FUN(__glewShaderSourceARB) +#define glUniform1fARB GLEW_GET_FUN(__glewUniform1fARB) +#define glUniform1fvARB GLEW_GET_FUN(__glewUniform1fvARB) +#define glUniform1iARB GLEW_GET_FUN(__glewUniform1iARB) +#define glUniform1ivARB GLEW_GET_FUN(__glewUniform1ivARB) +#define glUniform2fARB GLEW_GET_FUN(__glewUniform2fARB) +#define glUniform2fvARB GLEW_GET_FUN(__glewUniform2fvARB) +#define glUniform2iARB GLEW_GET_FUN(__glewUniform2iARB) +#define glUniform2ivARB GLEW_GET_FUN(__glewUniform2ivARB) +#define glUniform3fARB GLEW_GET_FUN(__glewUniform3fARB) +#define glUniform3fvARB GLEW_GET_FUN(__glewUniform3fvARB) +#define glUniform3iARB GLEW_GET_FUN(__glewUniform3iARB) +#define glUniform3ivARB GLEW_GET_FUN(__glewUniform3ivARB) +#define glUniform4fARB GLEW_GET_FUN(__glewUniform4fARB) +#define glUniform4fvARB GLEW_GET_FUN(__glewUniform4fvARB) +#define glUniform4iARB GLEW_GET_FUN(__glewUniform4iARB) +#define glUniform4ivARB GLEW_GET_FUN(__glewUniform4ivARB) +#define glUniformMatrix2fvARB GLEW_GET_FUN(__glewUniformMatrix2fvARB) +#define glUniformMatrix3fvARB GLEW_GET_FUN(__glewUniformMatrix3fvARB) +#define glUniformMatrix4fvARB GLEW_GET_FUN(__glewUniformMatrix4fvARB) +#define glUseProgramObjectARB GLEW_GET_FUN(__glewUseProgramObjectARB) +#define glValidateProgramARB GLEW_GET_FUN(__glewValidateProgramARB) + +#define GLEW_ARB_shader_objects GLEW_GET_VAR(__GLEW_ARB_shader_objects) + +#endif /* GL_ARB_shader_objects */ + +/* ------------------------ GL_ARB_shader_precision ------------------------ */ + +#ifndef GL_ARB_shader_precision +#define GL_ARB_shader_precision 1 + +#define GLEW_ARB_shader_precision GLEW_GET_VAR(__GLEW_ARB_shader_precision) + +#endif /* GL_ARB_shader_precision */ + +/* ---------------------- GL_ARB_shader_stencil_export --------------------- */ + +#ifndef GL_ARB_shader_stencil_export +#define GL_ARB_shader_stencil_export 1 + +#define GLEW_ARB_shader_stencil_export GLEW_GET_VAR(__GLEW_ARB_shader_stencil_export) + +#endif /* GL_ARB_shader_stencil_export */ + +/* ------------------------ GL_ARB_shader_subroutine ----------------------- */ + +#ifndef GL_ARB_shader_subroutine +#define GL_ARB_shader_subroutine 1 + +#define GL_ACTIVE_SUBROUTINES 0x8DE5 +#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6 +#define GL_MAX_SUBROUTINES 0x8DE7 +#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47 +#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49 +#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A +#define GL_COMPATIBLE_SUBROUTINES 0x8E4B + +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name); +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name); +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint* values); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint* values); +typedef GLuint (GLAPIENTRY * PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const char* name); +typedef GLint (GLAPIENTRY * PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const char* name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint* params); +typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint* indices); + +#define glGetActiveSubroutineName GLEW_GET_FUN(__glewGetActiveSubroutineName) +#define glGetActiveSubroutineUniformName GLEW_GET_FUN(__glewGetActiveSubroutineUniformName) +#define glGetActiveSubroutineUniformiv GLEW_GET_FUN(__glewGetActiveSubroutineUniformiv) +#define glGetProgramStageiv GLEW_GET_FUN(__glewGetProgramStageiv) +#define glGetSubroutineIndex GLEW_GET_FUN(__glewGetSubroutineIndex) +#define glGetSubroutineUniformLocation GLEW_GET_FUN(__glewGetSubroutineUniformLocation) +#define glGetUniformSubroutineuiv GLEW_GET_FUN(__glewGetUniformSubroutineuiv) +#define glUniformSubroutinesuiv GLEW_GET_FUN(__glewUniformSubroutinesuiv) + +#define GLEW_ARB_shader_subroutine GLEW_GET_VAR(__GLEW_ARB_shader_subroutine) + +#endif /* GL_ARB_shader_subroutine */ + +/* ----------------------- GL_ARB_shader_texture_lod ----------------------- */ + +#ifndef GL_ARB_shader_texture_lod +#define GL_ARB_shader_texture_lod 1 + +#define GLEW_ARB_shader_texture_lod GLEW_GET_VAR(__GLEW_ARB_shader_texture_lod) + +#endif /* GL_ARB_shader_texture_lod */ + +/* ---------------------- GL_ARB_shading_language_100 ---------------------- */ + +#ifndef GL_ARB_shading_language_100 +#define GL_ARB_shading_language_100 1 + +#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C + +#define GLEW_ARB_shading_language_100 GLEW_GET_VAR(__GLEW_ARB_shading_language_100) + +#endif /* GL_ARB_shading_language_100 */ + +/* -------------------- GL_ARB_shading_language_include -------------------- */ + +#ifndef GL_ARB_shading_language_include +#define GL_ARB_shading_language_include 1 + +#define GL_SHADER_INCLUDE_ARB 0x8DAE +#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9 +#define GL_NAMED_STRING_TYPE_ARB 0x8DEA + +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const char ** path, const GLint *length); +typedef void (GLAPIENTRY * PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const char* name); +typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const char* name, GLsizei bufSize, GLint *stringlen, char *string); +typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const char* name, GLenum pname, GLint *params); +typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const char* name); +typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const char* name, GLint stringlen, const char *string); + +#define glCompileShaderIncludeARB GLEW_GET_FUN(__glewCompileShaderIncludeARB) +#define glDeleteNamedStringARB GLEW_GET_FUN(__glewDeleteNamedStringARB) +#define glGetNamedStringARB GLEW_GET_FUN(__glewGetNamedStringARB) +#define glGetNamedStringivARB GLEW_GET_FUN(__glewGetNamedStringivARB) +#define glIsNamedStringARB GLEW_GET_FUN(__glewIsNamedStringARB) +#define glNamedStringARB GLEW_GET_FUN(__glewNamedStringARB) + +#define GLEW_ARB_shading_language_include GLEW_GET_VAR(__GLEW_ARB_shading_language_include) + +#endif /* GL_ARB_shading_language_include */ + +/* ----------------------------- GL_ARB_shadow ----------------------------- */ + +#ifndef GL_ARB_shadow +#define GL_ARB_shadow 1 + +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E + +#define GLEW_ARB_shadow GLEW_GET_VAR(__GLEW_ARB_shadow) + +#endif /* GL_ARB_shadow */ + +/* ------------------------- GL_ARB_shadow_ambient ------------------------- */ + +#ifndef GL_ARB_shadow_ambient +#define GL_ARB_shadow_ambient 1 + +#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF + +#define GLEW_ARB_shadow_ambient GLEW_GET_VAR(__GLEW_ARB_shadow_ambient) + +#endif /* GL_ARB_shadow_ambient */ + +/* ------------------------------ GL_ARB_sync ------------------------------ */ + +#ifndef GL_ARB_sync +#define GL_ARB_sync 1 + +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF + +typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout); +typedef void (GLAPIENTRY * PFNGLDELETESYNCPROC) (GLsync GLsync); +typedef GLsync (GLAPIENTRY * PFNGLFENCESYNCPROC) (GLenum condition,GLbitfield flags); +typedef void (GLAPIENTRY * PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64* params); +typedef void (GLAPIENTRY * PFNGLGETSYNCIVPROC) (GLsync GLsync,GLenum pname,GLsizei bufSize,GLsizei* length, GLint *values); +typedef GLboolean (GLAPIENTRY * PFNGLISSYNCPROC) (GLsync GLsync); +typedef void (GLAPIENTRY * PFNGLWAITSYNCPROC) (GLsync GLsync,GLbitfield flags,GLuint64 timeout); + +#define glClientWaitSync GLEW_GET_FUN(__glewClientWaitSync) +#define glDeleteSync GLEW_GET_FUN(__glewDeleteSync) +#define glFenceSync GLEW_GET_FUN(__glewFenceSync) +#define glGetInteger64v GLEW_GET_FUN(__glewGetInteger64v) +#define glGetSynciv GLEW_GET_FUN(__glewGetSynciv) +#define glIsSync GLEW_GET_FUN(__glewIsSync) +#define glWaitSync GLEW_GET_FUN(__glewWaitSync) + +#define GLEW_ARB_sync GLEW_GET_VAR(__GLEW_ARB_sync) + +#endif /* GL_ARB_sync */ + +/* ----------------------- GL_ARB_tessellation_shader ---------------------- */ + +#ifndef GL_ARB_tessellation_shader +#define GL_ARB_tessellation_shader 1 + +#define GL_PATCHES 0xE +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1 +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F +#define GL_PATCH_VERTICES 0x8E72 +#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 +#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 +#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 +#define GL_TESS_GEN_MODE 0x8E76 +#define GL_TESS_GEN_SPACING 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 +#define GL_TESS_GEN_POINT_MODE 0x8E79 +#define GL_ISOLINES 0x8E7A +#define GL_FRACTIONAL_ODD 0x8E7B +#define GL_FRACTIONAL_EVEN 0x8E7C +#define GL_MAX_PATCH_VERTICES 0x8E7D +#define GL_MAX_TESS_GEN_LEVEL 0x8E7E +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 +#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#define GL_TESS_CONTROL_SHADER 0x8E88 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A + +typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat* values); +typedef void (GLAPIENTRY * PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value); + +#define glPatchParameterfv GLEW_GET_FUN(__glewPatchParameterfv) +#define glPatchParameteri GLEW_GET_FUN(__glewPatchParameteri) + +#define GLEW_ARB_tessellation_shader GLEW_GET_VAR(__GLEW_ARB_tessellation_shader) + +#endif /* GL_ARB_tessellation_shader */ + +/* ---------------------- GL_ARB_texture_border_clamp ---------------------- */ + +#ifndef GL_ARB_texture_border_clamp +#define GL_ARB_texture_border_clamp 1 + +#define GL_CLAMP_TO_BORDER_ARB 0x812D + +#define GLEW_ARB_texture_border_clamp GLEW_GET_VAR(__GLEW_ARB_texture_border_clamp) + +#endif /* GL_ARB_texture_border_clamp */ + +/* ---------------------- GL_ARB_texture_buffer_object --------------------- */ + +#ifndef GL_ARB_texture_buffer_object +#define GL_ARB_texture_buffer_object 1 + +#define GL_TEXTURE_BUFFER_ARB 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E + +typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer); + +#define glTexBufferARB GLEW_GET_FUN(__glewTexBufferARB) + +#define GLEW_ARB_texture_buffer_object GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object) + +#endif /* GL_ARB_texture_buffer_object */ + +/* ------------------- GL_ARB_texture_buffer_object_rgb32 ------------------ */ + +#ifndef GL_ARB_texture_buffer_object_rgb32 +#define GL_ARB_texture_buffer_object_rgb32 1 + +#define GLEW_ARB_texture_buffer_object_rgb32 GLEW_GET_VAR(__GLEW_ARB_texture_buffer_object_rgb32) + +#endif /* GL_ARB_texture_buffer_object_rgb32 */ + +/* ----------------------- GL_ARB_texture_compression ---------------------- */ + +#ifndef GL_ARB_texture_compression +#define GL_ARB_texture_compression 1 + +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 + +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void* img); + +#define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB) +#define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB) +#define glCompressedTexImage3DARB GLEW_GET_FUN(__glewCompressedTexImage3DARB) +#define glCompressedTexSubImage1DARB GLEW_GET_FUN(__glewCompressedTexSubImage1DARB) +#define glCompressedTexSubImage2DARB GLEW_GET_FUN(__glewCompressedTexSubImage2DARB) +#define glCompressedTexSubImage3DARB GLEW_GET_FUN(__glewCompressedTexSubImage3DARB) +#define glGetCompressedTexImageARB GLEW_GET_FUN(__glewGetCompressedTexImageARB) + +#define GLEW_ARB_texture_compression GLEW_GET_VAR(__GLEW_ARB_texture_compression) + +#endif /* GL_ARB_texture_compression */ + +/* -------------------- GL_ARB_texture_compression_bptc -------------------- */ + +#ifndef GL_ARB_texture_compression_bptc +#define GL_ARB_texture_compression_bptc 1 + +#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F + +#define GLEW_ARB_texture_compression_bptc GLEW_GET_VAR(__GLEW_ARB_texture_compression_bptc) + +#endif /* GL_ARB_texture_compression_bptc */ + +/* -------------------- GL_ARB_texture_compression_rgtc -------------------- */ + +#ifndef GL_ARB_texture_compression_rgtc +#define GL_ARB_texture_compression_rgtc 1 + +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE + +#define GLEW_ARB_texture_compression_rgtc GLEW_GET_VAR(__GLEW_ARB_texture_compression_rgtc) + +#endif /* GL_ARB_texture_compression_rgtc */ + +/* ------------------------ GL_ARB_texture_cube_map ------------------------ */ + +#ifndef GL_ARB_texture_cube_map +#define GL_ARB_texture_cube_map 1 + +#define GL_NORMAL_MAP_ARB 0x8511 +#define GL_REFLECTION_MAP_ARB 0x8512 +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C + +#define GLEW_ARB_texture_cube_map GLEW_GET_VAR(__GLEW_ARB_texture_cube_map) + +#endif /* GL_ARB_texture_cube_map */ + +/* --------------------- GL_ARB_texture_cube_map_array --------------------- */ + +#ifndef GL_ARB_texture_cube_map_array +#define GL_ARB_texture_cube_map_array 1 + +#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F + +#define GLEW_ARB_texture_cube_map_array GLEW_GET_VAR(__GLEW_ARB_texture_cube_map_array) + +#endif /* GL_ARB_texture_cube_map_array */ + +/* ------------------------- GL_ARB_texture_env_add ------------------------ */ + +#ifndef GL_ARB_texture_env_add +#define GL_ARB_texture_env_add 1 + +#define GLEW_ARB_texture_env_add GLEW_GET_VAR(__GLEW_ARB_texture_env_add) + +#endif /* GL_ARB_texture_env_add */ + +/* ----------------------- GL_ARB_texture_env_combine ---------------------- */ + +#ifndef GL_ARB_texture_env_combine +#define GL_ARB_texture_env_combine 1 + +#define GL_SUBTRACT_ARB 0x84E7 +#define GL_COMBINE_ARB 0x8570 +#define GL_COMBINE_RGB_ARB 0x8571 +#define GL_COMBINE_ALPHA_ARB 0x8572 +#define GL_RGB_SCALE_ARB 0x8573 +#define GL_ADD_SIGNED_ARB 0x8574 +#define GL_INTERPOLATE_ARB 0x8575 +#define GL_CONSTANT_ARB 0x8576 +#define GL_PRIMARY_COLOR_ARB 0x8577 +#define GL_PREVIOUS_ARB 0x8578 +#define GL_SOURCE0_RGB_ARB 0x8580 +#define GL_SOURCE1_RGB_ARB 0x8581 +#define GL_SOURCE2_RGB_ARB 0x8582 +#define GL_SOURCE0_ALPHA_ARB 0x8588 +#define GL_SOURCE1_ALPHA_ARB 0x8589 +#define GL_SOURCE2_ALPHA_ARB 0x858A +#define GL_OPERAND0_RGB_ARB 0x8590 +#define GL_OPERAND1_RGB_ARB 0x8591 +#define GL_OPERAND2_RGB_ARB 0x8592 +#define GL_OPERAND0_ALPHA_ARB 0x8598 +#define GL_OPERAND1_ALPHA_ARB 0x8599 +#define GL_OPERAND2_ALPHA_ARB 0x859A + +#define GLEW_ARB_texture_env_combine GLEW_GET_VAR(__GLEW_ARB_texture_env_combine) + +#endif /* GL_ARB_texture_env_combine */ + +/* ---------------------- GL_ARB_texture_env_crossbar ---------------------- */ + +#ifndef GL_ARB_texture_env_crossbar +#define GL_ARB_texture_env_crossbar 1 + +#define GLEW_ARB_texture_env_crossbar GLEW_GET_VAR(__GLEW_ARB_texture_env_crossbar) + +#endif /* GL_ARB_texture_env_crossbar */ + +/* ------------------------ GL_ARB_texture_env_dot3 ------------------------ */ + +#ifndef GL_ARB_texture_env_dot3 +#define GL_ARB_texture_env_dot3 1 + +#define GL_DOT3_RGB_ARB 0x86AE +#define GL_DOT3_RGBA_ARB 0x86AF + +#define GLEW_ARB_texture_env_dot3 GLEW_GET_VAR(__GLEW_ARB_texture_env_dot3) + +#endif /* GL_ARB_texture_env_dot3 */ + +/* -------------------------- GL_ARB_texture_float ------------------------- */ + +#ifndef GL_ARB_texture_float +#define GL_ARB_texture_float 1 + +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGB32F_ARB 0x8815 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_INTENSITY32F_ARB 0x8817 +#define GL_LUMINANCE32F_ARB 0x8818 +#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 +#define GL_RGBA16F_ARB 0x881A +#define GL_RGB16F_ARB 0x881B +#define GL_ALPHA16F_ARB 0x881C +#define GL_INTENSITY16F_ARB 0x881D +#define GL_LUMINANCE16F_ARB 0x881E +#define GL_LUMINANCE_ALPHA16F_ARB 0x881F +#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 +#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 +#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 +#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 + +#define GLEW_ARB_texture_float GLEW_GET_VAR(__GLEW_ARB_texture_float) + +#endif /* GL_ARB_texture_float */ + +/* ------------------------- GL_ARB_texture_gather ------------------------- */ + +#ifndef GL_ARB_texture_gather +#define GL_ARB_texture_gather 1 + +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F +#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F + +#define GLEW_ARB_texture_gather GLEW_GET_VAR(__GLEW_ARB_texture_gather) + +#endif /* GL_ARB_texture_gather */ + +/* --------------------- GL_ARB_texture_mirrored_repeat -------------------- */ + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_ARB_texture_mirrored_repeat 1 + +#define GL_MIRRORED_REPEAT_ARB 0x8370 + +#define GLEW_ARB_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_ARB_texture_mirrored_repeat) + +#endif /* GL_ARB_texture_mirrored_repeat */ + +/* ----------------------- GL_ARB_texture_multisample ---------------------- */ + +#ifndef GL_ARB_texture_multisample +#define GL_ARB_texture_multisample 1 + +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 + +typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat* val); +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); + +#define glGetMultisamplefv GLEW_GET_FUN(__glewGetMultisamplefv) +#define glSampleMaski GLEW_GET_FUN(__glewSampleMaski) +#define glTexImage2DMultisample GLEW_GET_FUN(__glewTexImage2DMultisample) +#define glTexImage3DMultisample GLEW_GET_FUN(__glewTexImage3DMultisample) + +#define GLEW_ARB_texture_multisample GLEW_GET_VAR(__GLEW_ARB_texture_multisample) + +#endif /* GL_ARB_texture_multisample */ + +/* -------------------- GL_ARB_texture_non_power_of_two -------------------- */ + +#ifndef GL_ARB_texture_non_power_of_two +#define GL_ARB_texture_non_power_of_two 1 + +#define GLEW_ARB_texture_non_power_of_two GLEW_GET_VAR(__GLEW_ARB_texture_non_power_of_two) + +#endif /* GL_ARB_texture_non_power_of_two */ + +/* ------------------------ GL_ARB_texture_query_lod ----------------------- */ + +#ifndef GL_ARB_texture_query_lod +#define GL_ARB_texture_query_lod 1 + +#define GLEW_ARB_texture_query_lod GLEW_GET_VAR(__GLEW_ARB_texture_query_lod) + +#endif /* GL_ARB_texture_query_lod */ + +/* ------------------------ GL_ARB_texture_rectangle ----------------------- */ + +#ifndef GL_ARB_texture_rectangle +#define GL_ARB_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 + +#define GLEW_ARB_texture_rectangle GLEW_GET_VAR(__GLEW_ARB_texture_rectangle) + +#endif /* GL_ARB_texture_rectangle */ + +/* --------------------------- GL_ARB_texture_rg --------------------------- */ + +#ifndef GL_ARB_texture_rg +#define GL_ARB_texture_rg 1 + +#define GL_RED 0x1903 +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C + +#define GLEW_ARB_texture_rg GLEW_GET_VAR(__GLEW_ARB_texture_rg) + +#endif /* GL_ARB_texture_rg */ + +/* ----------------------- GL_ARB_texture_rgb10_a2ui ----------------------- */ + +#ifndef GL_ARB_texture_rgb10_a2ui +#define GL_ARB_texture_rgb10_a2ui 1 + +#define GL_RGB10_A2UI 0x906F + +#define GLEW_ARB_texture_rgb10_a2ui GLEW_GET_VAR(__GLEW_ARB_texture_rgb10_a2ui) + +#endif /* GL_ARB_texture_rgb10_a2ui */ + +/* ------------------------- GL_ARB_texture_swizzle ------------------------ */ + +#ifndef GL_ARB_texture_swizzle +#define GL_ARB_texture_swizzle 1 + +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 + +#define GLEW_ARB_texture_swizzle GLEW_GET_VAR(__GLEW_ARB_texture_swizzle) + +#endif /* GL_ARB_texture_swizzle */ + +/* --------------------------- GL_ARB_timer_query -------------------------- */ + +#ifndef GL_ARB_timer_query +#define GL_ARB_timer_query 1 + +#define GL_TIME_ELAPSED 0x88BF +#define GL_TIMESTAMP 0x8E28 + +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params); +typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target); + +#define glGetQueryObjecti64v GLEW_GET_FUN(__glewGetQueryObjecti64v) +#define glGetQueryObjectui64v GLEW_GET_FUN(__glewGetQueryObjectui64v) +#define glQueryCounter GLEW_GET_FUN(__glewQueryCounter) + +#define GLEW_ARB_timer_query GLEW_GET_VAR(__GLEW_ARB_timer_query) + +#endif /* GL_ARB_timer_query */ + +/* ----------------------- GL_ARB_transform_feedback2 ---------------------- */ + +#ifndef GL_ARB_transform_feedback2 +#define GL_ARB_transform_feedback2 1 + +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 + +typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id); +typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids); +typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKPROC) (void); +typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKPROC) (void); + +#define glBindTransformFeedback GLEW_GET_FUN(__glewBindTransformFeedback) +#define glDeleteTransformFeedbacks GLEW_GET_FUN(__glewDeleteTransformFeedbacks) +#define glDrawTransformFeedback GLEW_GET_FUN(__glewDrawTransformFeedback) +#define glGenTransformFeedbacks GLEW_GET_FUN(__glewGenTransformFeedbacks) +#define glIsTransformFeedback GLEW_GET_FUN(__glewIsTransformFeedback) +#define glPauseTransformFeedback GLEW_GET_FUN(__glewPauseTransformFeedback) +#define glResumeTransformFeedback GLEW_GET_FUN(__glewResumeTransformFeedback) + +#define GLEW_ARB_transform_feedback2 GLEW_GET_VAR(__GLEW_ARB_transform_feedback2) + +#endif /* GL_ARB_transform_feedback2 */ + +/* ----------------------- GL_ARB_transform_feedback3 ---------------------- */ + +#ifndef GL_ARB_transform_feedback3 +#define GL_ARB_transform_feedback3 1 + +#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70 +#define GL_MAX_VERTEX_STREAMS 0x8E71 + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id); +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream); +typedef void (GLAPIENTRY * PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); + +#define glBeginQueryIndexed GLEW_GET_FUN(__glewBeginQueryIndexed) +#define glDrawTransformFeedbackStream GLEW_GET_FUN(__glewDrawTransformFeedbackStream) +#define glEndQueryIndexed GLEW_GET_FUN(__glewEndQueryIndexed) +#define glGetQueryIndexediv GLEW_GET_FUN(__glewGetQueryIndexediv) + +#define GLEW_ARB_transform_feedback3 GLEW_GET_VAR(__GLEW_ARB_transform_feedback3) + +#endif /* GL_ARB_transform_feedback3 */ + +/* ------------------------ GL_ARB_transpose_matrix ------------------------ */ + +#ifndef GL_ARB_transpose_matrix +#define GL_ARB_transpose_matrix 1 + +#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 + +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDARBPROC) (GLdouble m[16]); +typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); + +#define glLoadTransposeMatrixdARB GLEW_GET_FUN(__glewLoadTransposeMatrixdARB) +#define glLoadTransposeMatrixfARB GLEW_GET_FUN(__glewLoadTransposeMatrixfARB) +#define glMultTransposeMatrixdARB GLEW_GET_FUN(__glewMultTransposeMatrixdARB) +#define glMultTransposeMatrixfARB GLEW_GET_FUN(__glewMultTransposeMatrixfARB) + +#define GLEW_ARB_transpose_matrix GLEW_GET_VAR(__GLEW_ARB_transpose_matrix) + +#endif /* GL_ARB_transpose_matrix */ + +/* ---------------------- GL_ARB_uniform_buffer_object --------------------- */ + +#ifndef GL_ARB_uniform_buffer_object +#define GL_ARB_uniform_buffer_object 1 + +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, char* uniformBlockName); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, char* uniformName); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint* data); +typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const char* uniformBlockName); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const char** uniformNames, GLuint* uniformIndices); +typedef void (GLAPIENTRY * PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); + +#define glBindBufferBase GLEW_GET_FUN(__glewBindBufferBase) +#define glBindBufferRange GLEW_GET_FUN(__glewBindBufferRange) +#define glGetActiveUniformBlockName GLEW_GET_FUN(__glewGetActiveUniformBlockName) +#define glGetActiveUniformBlockiv GLEW_GET_FUN(__glewGetActiveUniformBlockiv) +#define glGetActiveUniformName GLEW_GET_FUN(__glewGetActiveUniformName) +#define glGetActiveUniformsiv GLEW_GET_FUN(__glewGetActiveUniformsiv) +#define glGetIntegeri_v GLEW_GET_FUN(__glewGetIntegeri_v) +#define glGetUniformBlockIndex GLEW_GET_FUN(__glewGetUniformBlockIndex) +#define glGetUniformIndices GLEW_GET_FUN(__glewGetUniformIndices) +#define glUniformBlockBinding GLEW_GET_FUN(__glewUniformBlockBinding) + +#define GLEW_ARB_uniform_buffer_object GLEW_GET_VAR(__GLEW_ARB_uniform_buffer_object) + +#endif /* GL_ARB_uniform_buffer_object */ + +/* ------------------------ GL_ARB_vertex_array_bgra ----------------------- */ + +#ifndef GL_ARB_vertex_array_bgra +#define GL_ARB_vertex_array_bgra 1 + +#define GL_BGRA 0x80E1 + +#define GLEW_ARB_vertex_array_bgra GLEW_GET_VAR(__GLEW_ARB_vertex_array_bgra) + +#endif /* GL_ARB_vertex_array_bgra */ + +/* ----------------------- GL_ARB_vertex_array_object ---------------------- */ + +#ifndef GL_ARB_vertex_array_object +#define GL_ARB_vertex_array_object 1 + +#define GL_VERTEX_ARRAY_BINDING 0x85B5 + +typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays); +typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays); +typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYPROC) (GLuint array); + +#define glBindVertexArray GLEW_GET_FUN(__glewBindVertexArray) +#define glDeleteVertexArrays GLEW_GET_FUN(__glewDeleteVertexArrays) +#define glGenVertexArrays GLEW_GET_FUN(__glewGenVertexArrays) +#define glIsVertexArray GLEW_GET_FUN(__glewIsVertexArray) + +#define GLEW_ARB_vertex_array_object GLEW_GET_VAR(__GLEW_ARB_vertex_array_object) + +#endif /* GL_ARB_vertex_array_object */ + +/* ----------------------- GL_ARB_vertex_attrib_64bit ---------------------- */ + +#ifndef GL_ARB_vertex_attrib_64bit +#define GL_ARB_vertex_attrib_64bit 1 + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); + +#define glGetVertexAttribLdv GLEW_GET_FUN(__glewGetVertexAttribLdv) +#define glVertexAttribL1d GLEW_GET_FUN(__glewVertexAttribL1d) +#define glVertexAttribL1dv GLEW_GET_FUN(__glewVertexAttribL1dv) +#define glVertexAttribL2d GLEW_GET_FUN(__glewVertexAttribL2d) +#define glVertexAttribL2dv GLEW_GET_FUN(__glewVertexAttribL2dv) +#define glVertexAttribL3d GLEW_GET_FUN(__glewVertexAttribL3d) +#define glVertexAttribL3dv GLEW_GET_FUN(__glewVertexAttribL3dv) +#define glVertexAttribL4d GLEW_GET_FUN(__glewVertexAttribL4d) +#define glVertexAttribL4dv GLEW_GET_FUN(__glewVertexAttribL4dv) +#define glVertexAttribLPointer GLEW_GET_FUN(__glewVertexAttribLPointer) + +#define GLEW_ARB_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_ARB_vertex_attrib_64bit) + +#endif /* GL_ARB_vertex_attrib_64bit */ + +/* -------------------------- GL_ARB_vertex_blend -------------------------- */ + +#ifndef GL_ARB_vertex_blend +#define GL_ARB_vertex_blend 1 + +#define GL_MODELVIEW0_ARB 0x1700 +#define GL_MODELVIEW1_ARB 0x850A +#define GL_MAX_VERTEX_UNITS_ARB 0x86A4 +#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 +#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 +#define GL_VERTEX_BLEND_ARB 0x86A7 +#define GL_CURRENT_WEIGHT_ARB 0x86A8 +#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 +#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA +#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB +#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC +#define GL_WEIGHT_ARRAY_ARB 0x86AD +#define GL_MODELVIEW2_ARB 0x8722 +#define GL_MODELVIEW3_ARB 0x8723 +#define GL_MODELVIEW4_ARB 0x8724 +#define GL_MODELVIEW5_ARB 0x8725 +#define GL_MODELVIEW6_ARB 0x8726 +#define GL_MODELVIEW7_ARB 0x8727 +#define GL_MODELVIEW8_ARB 0x8728 +#define GL_MODELVIEW9_ARB 0x8729 +#define GL_MODELVIEW10_ARB 0x872A +#define GL_MODELVIEW11_ARB 0x872B +#define GL_MODELVIEW12_ARB 0x872C +#define GL_MODELVIEW13_ARB 0x872D +#define GL_MODELVIEW14_ARB 0x872E +#define GL_MODELVIEW15_ARB 0x872F +#define GL_MODELVIEW16_ARB 0x8730 +#define GL_MODELVIEW17_ARB 0x8731 +#define GL_MODELVIEW18_ARB 0x8732 +#define GL_MODELVIEW19_ARB 0x8733 +#define GL_MODELVIEW20_ARB 0x8734 +#define GL_MODELVIEW21_ARB 0x8735 +#define GL_MODELVIEW22_ARB 0x8736 +#define GL_MODELVIEW23_ARB 0x8737 +#define GL_MODELVIEW24_ARB 0x8738 +#define GL_MODELVIEW25_ARB 0x8739 +#define GL_MODELVIEW26_ARB 0x873A +#define GL_MODELVIEW27_ARB 0x873B +#define GL_MODELVIEW28_ARB 0x873C +#define GL_MODELVIEW29_ARB 0x873D +#define GL_MODELVIEW30_ARB 0x873E +#define GL_MODELVIEW31_ARB 0x873F + +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDARBPROC) (GLint count); +typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLWEIGHTBVARBPROC) (GLint size, GLbyte *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTDVARBPROC) (GLint size, GLdouble *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTFVARBPROC) (GLint size, GLfloat *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTIVARBPROC) (GLint size, GLint *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTSVARBPROC) (GLint size, GLshort *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUBVARBPROC) (GLint size, GLubyte *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUIVARBPROC) (GLint size, GLuint *weights); +typedef void (GLAPIENTRY * PFNGLWEIGHTUSVARBPROC) (GLint size, GLushort *weights); + +#define glVertexBlendARB GLEW_GET_FUN(__glewVertexBlendARB) +#define glWeightPointerARB GLEW_GET_FUN(__glewWeightPointerARB) +#define glWeightbvARB GLEW_GET_FUN(__glewWeightbvARB) +#define glWeightdvARB GLEW_GET_FUN(__glewWeightdvARB) +#define glWeightfvARB GLEW_GET_FUN(__glewWeightfvARB) +#define glWeightivARB GLEW_GET_FUN(__glewWeightivARB) +#define glWeightsvARB GLEW_GET_FUN(__glewWeightsvARB) +#define glWeightubvARB GLEW_GET_FUN(__glewWeightubvARB) +#define glWeightuivARB GLEW_GET_FUN(__glewWeightuivARB) +#define glWeightusvARB GLEW_GET_FUN(__glewWeightusvARB) + +#define GLEW_ARB_vertex_blend GLEW_GET_VAR(__GLEW_ARB_vertex_blend) + +#endif /* GL_ARB_vertex_blend */ + +/* ---------------------- GL_ARB_vertex_buffer_object ---------------------- */ + +#ifndef GL_ARB_vertex_buffer_object +#define GL_ARB_vertex_buffer_object 1 + +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_READ_WRITE_ARB 0x88BA +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_DYNAMIC_COPY_ARB 0x88EA + +typedef ptrdiff_t GLintptrARB; +typedef ptrdiff_t GLsizeiptrARB; + +typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target); + +#define glBindBufferARB GLEW_GET_FUN(__glewBindBufferARB) +#define glBufferDataARB GLEW_GET_FUN(__glewBufferDataARB) +#define glBufferSubDataARB GLEW_GET_FUN(__glewBufferSubDataARB) +#define glDeleteBuffersARB GLEW_GET_FUN(__glewDeleteBuffersARB) +#define glGenBuffersARB GLEW_GET_FUN(__glewGenBuffersARB) +#define glGetBufferParameterivARB GLEW_GET_FUN(__glewGetBufferParameterivARB) +#define glGetBufferPointervARB GLEW_GET_FUN(__glewGetBufferPointervARB) +#define glGetBufferSubDataARB GLEW_GET_FUN(__glewGetBufferSubDataARB) +#define glIsBufferARB GLEW_GET_FUN(__glewIsBufferARB) +#define glMapBufferARB GLEW_GET_FUN(__glewMapBufferARB) +#define glUnmapBufferARB GLEW_GET_FUN(__glewUnmapBufferARB) + +#define GLEW_ARB_vertex_buffer_object GLEW_GET_VAR(__GLEW_ARB_vertex_buffer_object) + +#endif /* GL_ARB_vertex_buffer_object */ + +/* ------------------------- GL_ARB_vertex_program ------------------------- */ + +#ifndef GL_ARB_vertex_program +#define GL_ARB_vertex_program 1 + +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF + +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint* programs); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint* programs); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void* string); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); + +#define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB) +#define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB) +#define glDisableVertexAttribArrayARB GLEW_GET_FUN(__glewDisableVertexAttribArrayARB) +#define glEnableVertexAttribArrayARB GLEW_GET_FUN(__glewEnableVertexAttribArrayARB) +#define glGenProgramsARB GLEW_GET_FUN(__glewGenProgramsARB) +#define glGetProgramEnvParameterdvARB GLEW_GET_FUN(__glewGetProgramEnvParameterdvARB) +#define glGetProgramEnvParameterfvARB GLEW_GET_FUN(__glewGetProgramEnvParameterfvARB) +#define glGetProgramLocalParameterdvARB GLEW_GET_FUN(__glewGetProgramLocalParameterdvARB) +#define glGetProgramLocalParameterfvARB GLEW_GET_FUN(__glewGetProgramLocalParameterfvARB) +#define glGetProgramStringARB GLEW_GET_FUN(__glewGetProgramStringARB) +#define glGetProgramivARB GLEW_GET_FUN(__glewGetProgramivARB) +#define glGetVertexAttribPointervARB GLEW_GET_FUN(__glewGetVertexAttribPointervARB) +#define glGetVertexAttribdvARB GLEW_GET_FUN(__glewGetVertexAttribdvARB) +#define glGetVertexAttribfvARB GLEW_GET_FUN(__glewGetVertexAttribfvARB) +#define glGetVertexAttribivARB GLEW_GET_FUN(__glewGetVertexAttribivARB) +#define glIsProgramARB GLEW_GET_FUN(__glewIsProgramARB) +#define glProgramEnvParameter4dARB GLEW_GET_FUN(__glewProgramEnvParameter4dARB) +#define glProgramEnvParameter4dvARB GLEW_GET_FUN(__glewProgramEnvParameter4dvARB) +#define glProgramEnvParameter4fARB GLEW_GET_FUN(__glewProgramEnvParameter4fARB) +#define glProgramEnvParameter4fvARB GLEW_GET_FUN(__glewProgramEnvParameter4fvARB) +#define glProgramLocalParameter4dARB GLEW_GET_FUN(__glewProgramLocalParameter4dARB) +#define glProgramLocalParameter4dvARB GLEW_GET_FUN(__glewProgramLocalParameter4dvARB) +#define glProgramLocalParameter4fARB GLEW_GET_FUN(__glewProgramLocalParameter4fARB) +#define glProgramLocalParameter4fvARB GLEW_GET_FUN(__glewProgramLocalParameter4fvARB) +#define glProgramStringARB GLEW_GET_FUN(__glewProgramStringARB) +#define glVertexAttrib1dARB GLEW_GET_FUN(__glewVertexAttrib1dARB) +#define glVertexAttrib1dvARB GLEW_GET_FUN(__glewVertexAttrib1dvARB) +#define glVertexAttrib1fARB GLEW_GET_FUN(__glewVertexAttrib1fARB) +#define glVertexAttrib1fvARB GLEW_GET_FUN(__glewVertexAttrib1fvARB) +#define glVertexAttrib1sARB GLEW_GET_FUN(__glewVertexAttrib1sARB) +#define glVertexAttrib1svARB GLEW_GET_FUN(__glewVertexAttrib1svARB) +#define glVertexAttrib2dARB GLEW_GET_FUN(__glewVertexAttrib2dARB) +#define glVertexAttrib2dvARB GLEW_GET_FUN(__glewVertexAttrib2dvARB) +#define glVertexAttrib2fARB GLEW_GET_FUN(__glewVertexAttrib2fARB) +#define glVertexAttrib2fvARB GLEW_GET_FUN(__glewVertexAttrib2fvARB) +#define glVertexAttrib2sARB GLEW_GET_FUN(__glewVertexAttrib2sARB) +#define glVertexAttrib2svARB GLEW_GET_FUN(__glewVertexAttrib2svARB) +#define glVertexAttrib3dARB GLEW_GET_FUN(__glewVertexAttrib3dARB) +#define glVertexAttrib3dvARB GLEW_GET_FUN(__glewVertexAttrib3dvARB) +#define glVertexAttrib3fARB GLEW_GET_FUN(__glewVertexAttrib3fARB) +#define glVertexAttrib3fvARB GLEW_GET_FUN(__glewVertexAttrib3fvARB) +#define glVertexAttrib3sARB GLEW_GET_FUN(__glewVertexAttrib3sARB) +#define glVertexAttrib3svARB GLEW_GET_FUN(__glewVertexAttrib3svARB) +#define glVertexAttrib4NbvARB GLEW_GET_FUN(__glewVertexAttrib4NbvARB) +#define glVertexAttrib4NivARB GLEW_GET_FUN(__glewVertexAttrib4NivARB) +#define glVertexAttrib4NsvARB GLEW_GET_FUN(__glewVertexAttrib4NsvARB) +#define glVertexAttrib4NubARB GLEW_GET_FUN(__glewVertexAttrib4NubARB) +#define glVertexAttrib4NubvARB GLEW_GET_FUN(__glewVertexAttrib4NubvARB) +#define glVertexAttrib4NuivARB GLEW_GET_FUN(__glewVertexAttrib4NuivARB) +#define glVertexAttrib4NusvARB GLEW_GET_FUN(__glewVertexAttrib4NusvARB) +#define glVertexAttrib4bvARB GLEW_GET_FUN(__glewVertexAttrib4bvARB) +#define glVertexAttrib4dARB GLEW_GET_FUN(__glewVertexAttrib4dARB) +#define glVertexAttrib4dvARB GLEW_GET_FUN(__glewVertexAttrib4dvARB) +#define glVertexAttrib4fARB GLEW_GET_FUN(__glewVertexAttrib4fARB) +#define glVertexAttrib4fvARB GLEW_GET_FUN(__glewVertexAttrib4fvARB) +#define glVertexAttrib4ivARB GLEW_GET_FUN(__glewVertexAttrib4ivARB) +#define glVertexAttrib4sARB GLEW_GET_FUN(__glewVertexAttrib4sARB) +#define glVertexAttrib4svARB GLEW_GET_FUN(__glewVertexAttrib4svARB) +#define glVertexAttrib4ubvARB GLEW_GET_FUN(__glewVertexAttrib4ubvARB) +#define glVertexAttrib4uivARB GLEW_GET_FUN(__glewVertexAttrib4uivARB) +#define glVertexAttrib4usvARB GLEW_GET_FUN(__glewVertexAttrib4usvARB) +#define glVertexAttribPointerARB GLEW_GET_FUN(__glewVertexAttribPointerARB) + +#define GLEW_ARB_vertex_program GLEW_GET_VAR(__GLEW_ARB_vertex_program) + +#endif /* GL_ARB_vertex_program */ + +/* -------------------------- GL_ARB_vertex_shader ------------------------- */ + +#ifndef GL_ARB_vertex_shader +#define GL_ARB_vertex_shader 1 + +#define GL_VERTEX_SHADER_ARB 0x8B31 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A +#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D +#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 +#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A + +typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB* name); +typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei* length, GLint *size, GLenum *type, GLcharARB *name); +typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB* name); + +#define glBindAttribLocationARB GLEW_GET_FUN(__glewBindAttribLocationARB) +#define glGetActiveAttribARB GLEW_GET_FUN(__glewGetActiveAttribARB) +#define glGetAttribLocationARB GLEW_GET_FUN(__glewGetAttribLocationARB) + +#define GLEW_ARB_vertex_shader GLEW_GET_VAR(__GLEW_ARB_vertex_shader) + +#endif /* GL_ARB_vertex_shader */ + +/* ------------------- GL_ARB_vertex_type_2_10_10_10_rev ------------------- */ + +#ifndef GL_ARB_vertex_type_2_10_10_10_rev +#define GL_ARB_vertex_type_2_10_10_10_rev 1 + +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_INT_2_10_10_10_REV 0x8D9F + +typedef void (GLAPIENTRY * PFNGLCOLORP3UIPROC) (GLenum type, GLuint color); +typedef void (GLAPIENTRY * PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint* color); +typedef void (GLAPIENTRY * PFNGLCOLORP4UIPROC) (GLenum type, GLuint color); +typedef void (GLAPIENTRY * PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint* color); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint* color); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords); +typedef void (GLAPIENTRY * PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint* coords); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value); +typedef void (GLAPIENTRY * PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint* value); + +#define glColorP3ui GLEW_GET_FUN(__glewColorP3ui) +#define glColorP3uiv GLEW_GET_FUN(__glewColorP3uiv) +#define glColorP4ui GLEW_GET_FUN(__glewColorP4ui) +#define glColorP4uiv GLEW_GET_FUN(__glewColorP4uiv) +#define glMultiTexCoordP1ui GLEW_GET_FUN(__glewMultiTexCoordP1ui) +#define glMultiTexCoordP1uiv GLEW_GET_FUN(__glewMultiTexCoordP1uiv) +#define glMultiTexCoordP2ui GLEW_GET_FUN(__glewMultiTexCoordP2ui) +#define glMultiTexCoordP2uiv GLEW_GET_FUN(__glewMultiTexCoordP2uiv) +#define glMultiTexCoordP3ui GLEW_GET_FUN(__glewMultiTexCoordP3ui) +#define glMultiTexCoordP3uiv GLEW_GET_FUN(__glewMultiTexCoordP3uiv) +#define glMultiTexCoordP4ui GLEW_GET_FUN(__glewMultiTexCoordP4ui) +#define glMultiTexCoordP4uiv GLEW_GET_FUN(__glewMultiTexCoordP4uiv) +#define glNormalP3ui GLEW_GET_FUN(__glewNormalP3ui) +#define glNormalP3uiv GLEW_GET_FUN(__glewNormalP3uiv) +#define glSecondaryColorP3ui GLEW_GET_FUN(__glewSecondaryColorP3ui) +#define glSecondaryColorP3uiv GLEW_GET_FUN(__glewSecondaryColorP3uiv) +#define glTexCoordP1ui GLEW_GET_FUN(__glewTexCoordP1ui) +#define glTexCoordP1uiv GLEW_GET_FUN(__glewTexCoordP1uiv) +#define glTexCoordP2ui GLEW_GET_FUN(__glewTexCoordP2ui) +#define glTexCoordP2uiv GLEW_GET_FUN(__glewTexCoordP2uiv) +#define glTexCoordP3ui GLEW_GET_FUN(__glewTexCoordP3ui) +#define glTexCoordP3uiv GLEW_GET_FUN(__glewTexCoordP3uiv) +#define glTexCoordP4ui GLEW_GET_FUN(__glewTexCoordP4ui) +#define glTexCoordP4uiv GLEW_GET_FUN(__glewTexCoordP4uiv) +#define glVertexAttribP1ui GLEW_GET_FUN(__glewVertexAttribP1ui) +#define glVertexAttribP1uiv GLEW_GET_FUN(__glewVertexAttribP1uiv) +#define glVertexAttribP2ui GLEW_GET_FUN(__glewVertexAttribP2ui) +#define glVertexAttribP2uiv GLEW_GET_FUN(__glewVertexAttribP2uiv) +#define glVertexAttribP3ui GLEW_GET_FUN(__glewVertexAttribP3ui) +#define glVertexAttribP3uiv GLEW_GET_FUN(__glewVertexAttribP3uiv) +#define glVertexAttribP4ui GLEW_GET_FUN(__glewVertexAttribP4ui) +#define glVertexAttribP4uiv GLEW_GET_FUN(__glewVertexAttribP4uiv) +#define glVertexP2ui GLEW_GET_FUN(__glewVertexP2ui) +#define glVertexP2uiv GLEW_GET_FUN(__glewVertexP2uiv) +#define glVertexP3ui GLEW_GET_FUN(__glewVertexP3ui) +#define glVertexP3uiv GLEW_GET_FUN(__glewVertexP3uiv) +#define glVertexP4ui GLEW_GET_FUN(__glewVertexP4ui) +#define glVertexP4uiv GLEW_GET_FUN(__glewVertexP4uiv) + +#define GLEW_ARB_vertex_type_2_10_10_10_rev GLEW_GET_VAR(__GLEW_ARB_vertex_type_2_10_10_10_rev) + +#endif /* GL_ARB_vertex_type_2_10_10_10_rev */ + +/* ------------------------- GL_ARB_viewport_array ------------------------- */ + +#ifndef GL_ARB_viewport_array +#define GL_ARB_viewport_array 1 + +#define GL_DEPTH_RANGE 0x0B70 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_MAX_VIEWPORTS 0x825B +#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C +#define GL_VIEWPORT_BOUNDS_RANGE 0x825D +#define GL_LAYER_PROVOKING_VERTEX 0x825E +#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F +#define GL_UNDEFINED_VERTEX 0x8260 +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F + +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLclampd * v); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLclampd n, GLclampd f); +typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble* data); +typedef void (GLAPIENTRY * PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat* data); +typedef void (GLAPIENTRY * PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint * v); +typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint * v); +typedef void (GLAPIENTRY * PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat * v); +typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +typedef void (GLAPIENTRY * PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat * v); + +#define glDepthRangeArrayv GLEW_GET_FUN(__glewDepthRangeArrayv) +#define glDepthRangeIndexed GLEW_GET_FUN(__glewDepthRangeIndexed) +#define glGetDoublei_v GLEW_GET_FUN(__glewGetDoublei_v) +#define glGetFloati_v GLEW_GET_FUN(__glewGetFloati_v) +#define glScissorArrayv GLEW_GET_FUN(__glewScissorArrayv) +#define glScissorIndexed GLEW_GET_FUN(__glewScissorIndexed) +#define glScissorIndexedv GLEW_GET_FUN(__glewScissorIndexedv) +#define glViewportArrayv GLEW_GET_FUN(__glewViewportArrayv) +#define glViewportIndexedf GLEW_GET_FUN(__glewViewportIndexedf) +#define glViewportIndexedfv GLEW_GET_FUN(__glewViewportIndexedfv) + +#define GLEW_ARB_viewport_array GLEW_GET_VAR(__GLEW_ARB_viewport_array) + +#endif /* GL_ARB_viewport_array */ + +/* --------------------------- GL_ARB_window_pos --------------------------- */ + +#ifndef GL_ARB_window_pos +#define GL_ARB_window_pos 1 + +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVARBPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVARBPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVARBPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVARBPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVARBPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVARBPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVARBPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVARBPROC) (const GLshort* p); + +#define glWindowPos2dARB GLEW_GET_FUN(__glewWindowPos2dARB) +#define glWindowPos2dvARB GLEW_GET_FUN(__glewWindowPos2dvARB) +#define glWindowPos2fARB GLEW_GET_FUN(__glewWindowPos2fARB) +#define glWindowPos2fvARB GLEW_GET_FUN(__glewWindowPos2fvARB) +#define glWindowPos2iARB GLEW_GET_FUN(__glewWindowPos2iARB) +#define glWindowPos2ivARB GLEW_GET_FUN(__glewWindowPos2ivARB) +#define glWindowPos2sARB GLEW_GET_FUN(__glewWindowPos2sARB) +#define glWindowPos2svARB GLEW_GET_FUN(__glewWindowPos2svARB) +#define glWindowPos3dARB GLEW_GET_FUN(__glewWindowPos3dARB) +#define glWindowPos3dvARB GLEW_GET_FUN(__glewWindowPos3dvARB) +#define glWindowPos3fARB GLEW_GET_FUN(__glewWindowPos3fARB) +#define glWindowPos3fvARB GLEW_GET_FUN(__glewWindowPos3fvARB) +#define glWindowPos3iARB GLEW_GET_FUN(__glewWindowPos3iARB) +#define glWindowPos3ivARB GLEW_GET_FUN(__glewWindowPos3ivARB) +#define glWindowPos3sARB GLEW_GET_FUN(__glewWindowPos3sARB) +#define glWindowPos3svARB GLEW_GET_FUN(__glewWindowPos3svARB) + +#define GLEW_ARB_window_pos GLEW_GET_VAR(__GLEW_ARB_window_pos) + +#endif /* GL_ARB_window_pos */ + +/* ------------------------- GL_ATIX_point_sprites ------------------------- */ + +#ifndef GL_ATIX_point_sprites +#define GL_ATIX_point_sprites 1 + +#define GL_TEXTURE_POINT_MODE_ATIX 0x60B0 +#define GL_TEXTURE_POINT_ONE_COORD_ATIX 0x60B1 +#define GL_TEXTURE_POINT_SPRITE_ATIX 0x60B2 +#define GL_POINT_SPRITE_CULL_MODE_ATIX 0x60B3 +#define GL_POINT_SPRITE_CULL_CENTER_ATIX 0x60B4 +#define GL_POINT_SPRITE_CULL_CLIP_ATIX 0x60B5 + +#define GLEW_ATIX_point_sprites GLEW_GET_VAR(__GLEW_ATIX_point_sprites) + +#endif /* GL_ATIX_point_sprites */ + +/* ---------------------- GL_ATIX_texture_env_combine3 --------------------- */ + +#ifndef GL_ATIX_texture_env_combine3 +#define GL_ATIX_texture_env_combine3 1 + +#define GL_MODULATE_ADD_ATIX 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATIX 0x8745 +#define GL_MODULATE_SUBTRACT_ATIX 0x8746 + +#define GLEW_ATIX_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATIX_texture_env_combine3) + +#endif /* GL_ATIX_texture_env_combine3 */ + +/* ----------------------- GL_ATIX_texture_env_route ----------------------- */ + +#ifndef GL_ATIX_texture_env_route +#define GL_ATIX_texture_env_route 1 + +#define GL_SECONDARY_COLOR_ATIX 0x8747 +#define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748 +#define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749 + +#define GLEW_ATIX_texture_env_route GLEW_GET_VAR(__GLEW_ATIX_texture_env_route) + +#endif /* GL_ATIX_texture_env_route */ + +/* ---------------- GL_ATIX_vertex_shader_output_point_size ---------------- */ + +#ifndef GL_ATIX_vertex_shader_output_point_size +#define GL_ATIX_vertex_shader_output_point_size 1 + +#define GL_OUTPUT_POINT_SIZE_ATIX 0x610E + +#define GLEW_ATIX_vertex_shader_output_point_size GLEW_GET_VAR(__GLEW_ATIX_vertex_shader_output_point_size) + +#endif /* GL_ATIX_vertex_shader_output_point_size */ + +/* -------------------------- GL_ATI_draw_buffers -------------------------- */ + +#ifndef GL_ATI_draw_buffers +#define GL_ATI_draw_buffers 1 + +#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 +#define GL_DRAW_BUFFER0_ATI 0x8825 +#define GL_DRAW_BUFFER1_ATI 0x8826 +#define GL_DRAW_BUFFER2_ATI 0x8827 +#define GL_DRAW_BUFFER3_ATI 0x8828 +#define GL_DRAW_BUFFER4_ATI 0x8829 +#define GL_DRAW_BUFFER5_ATI 0x882A +#define GL_DRAW_BUFFER6_ATI 0x882B +#define GL_DRAW_BUFFER7_ATI 0x882C +#define GL_DRAW_BUFFER8_ATI 0x882D +#define GL_DRAW_BUFFER9_ATI 0x882E +#define GL_DRAW_BUFFER10_ATI 0x882F +#define GL_DRAW_BUFFER11_ATI 0x8830 +#define GL_DRAW_BUFFER12_ATI 0x8831 +#define GL_DRAW_BUFFER13_ATI 0x8832 +#define GL_DRAW_BUFFER14_ATI 0x8833 +#define GL_DRAW_BUFFER15_ATI 0x8834 + +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bufs); + +#define glDrawBuffersATI GLEW_GET_FUN(__glewDrawBuffersATI) + +#define GLEW_ATI_draw_buffers GLEW_GET_VAR(__GLEW_ATI_draw_buffers) + +#endif /* GL_ATI_draw_buffers */ + +/* -------------------------- GL_ATI_element_array ------------------------- */ + +#ifndef GL_ATI_element_array +#define GL_ATI_element_array 1 + +#define GL_ELEMENT_ARRAY_ATI 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A + +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void* pointer); + +#define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI) +#define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI) +#define glElementPointerATI GLEW_GET_FUN(__glewElementPointerATI) + +#define GLEW_ATI_element_array GLEW_GET_VAR(__GLEW_ATI_element_array) + +#endif /* GL_ATI_element_array */ + +/* ------------------------- GL_ATI_envmap_bumpmap ------------------------- */ + +#ifndef GL_ATI_envmap_bumpmap +#define GL_ATI_envmap_bumpmap 1 + +#define GL_BUMP_ROT_MATRIX_ATI 0x8775 +#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 +#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 +#define GL_BUMP_TEX_UNITS_ATI 0x8778 +#define GL_DUDV_ATI 0x8779 +#define GL_DU8DV8_ATI 0x877A +#define GL_BUMP_ENVMAP_ATI 0x877B +#define GL_BUMP_TARGET_ATI 0x877C + +typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +typedef void (GLAPIENTRY * PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); +typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); + +#define glGetTexBumpParameterfvATI GLEW_GET_FUN(__glewGetTexBumpParameterfvATI) +#define glGetTexBumpParameterivATI GLEW_GET_FUN(__glewGetTexBumpParameterivATI) +#define glTexBumpParameterfvATI GLEW_GET_FUN(__glewTexBumpParameterfvATI) +#define glTexBumpParameterivATI GLEW_GET_FUN(__glewTexBumpParameterivATI) + +#define GLEW_ATI_envmap_bumpmap GLEW_GET_VAR(__GLEW_ATI_envmap_bumpmap) + +#endif /* GL_ATI_envmap_bumpmap */ + +/* ------------------------- GL_ATI_fragment_shader ------------------------ */ + +#ifndef GL_ATI_fragment_shader +#define GL_ATI_fragment_shader 1 + +#define GL_RED_BIT_ATI 0x00000001 +#define GL_2X_BIT_ATI 0x00000001 +#define GL_4X_BIT_ATI 0x00000002 +#define GL_GREEN_BIT_ATI 0x00000002 +#define GL_COMP_BIT_ATI 0x00000002 +#define GL_BLUE_BIT_ATI 0x00000004 +#define GL_8X_BIT_ATI 0x00000004 +#define GL_NEGATE_BIT_ATI 0x00000004 +#define GL_BIAS_BIT_ATI 0x00000008 +#define GL_HALF_BIT_ATI 0x00000008 +#define GL_QUARTER_BIT_ATI 0x00000010 +#define GL_EIGHTH_BIT_ATI 0x00000020 +#define GL_SATURATE_BIT_ATI 0x00000040 +#define GL_FRAGMENT_SHADER_ATI 0x8920 +#define GL_REG_0_ATI 0x8921 +#define GL_REG_1_ATI 0x8922 +#define GL_REG_2_ATI 0x8923 +#define GL_REG_3_ATI 0x8924 +#define GL_REG_4_ATI 0x8925 +#define GL_REG_5_ATI 0x8926 +#define GL_CON_0_ATI 0x8941 +#define GL_CON_1_ATI 0x8942 +#define GL_CON_2_ATI 0x8943 +#define GL_CON_3_ATI 0x8944 +#define GL_CON_4_ATI 0x8945 +#define GL_CON_5_ATI 0x8946 +#define GL_CON_6_ATI 0x8947 +#define GL_CON_7_ATI 0x8948 +#define GL_MOV_ATI 0x8961 +#define GL_ADD_ATI 0x8963 +#define GL_MUL_ATI 0x8964 +#define GL_SUB_ATI 0x8965 +#define GL_DOT3_ATI 0x8966 +#define GL_DOT4_ATI 0x8967 +#define GL_MAD_ATI 0x8968 +#define GL_LERP_ATI 0x8969 +#define GL_CND_ATI 0x896A +#define GL_CND0_ATI 0x896B +#define GL_DOT2_ADD_ATI 0x896C +#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D +#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E +#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F +#define GL_NUM_PASSES_ATI 0x8970 +#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 +#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 +#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 +#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 +#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 +#define GL_SWIZZLE_STR_ATI 0x8976 +#define GL_SWIZZLE_STQ_ATI 0x8977 +#define GL_SWIZZLE_STR_DR_ATI 0x8978 +#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 +#define GL_SWIZZLE_STRQ_ATI 0x897A +#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B + +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (GLAPIENTRY * PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (GLAPIENTRY * PFNGLBEGINFRAGMENTSHADERATIPROC) (void); +typedef void (GLAPIENTRY * PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (GLAPIENTRY * PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (GLAPIENTRY * PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENDFRAGMENTSHADERATIPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); +typedef void (GLAPIENTRY * PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); +typedef void (GLAPIENTRY * PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); +typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat* value); + +#define glAlphaFragmentOp1ATI GLEW_GET_FUN(__glewAlphaFragmentOp1ATI) +#define glAlphaFragmentOp2ATI GLEW_GET_FUN(__glewAlphaFragmentOp2ATI) +#define glAlphaFragmentOp3ATI GLEW_GET_FUN(__glewAlphaFragmentOp3ATI) +#define glBeginFragmentShaderATI GLEW_GET_FUN(__glewBeginFragmentShaderATI) +#define glBindFragmentShaderATI GLEW_GET_FUN(__glewBindFragmentShaderATI) +#define glColorFragmentOp1ATI GLEW_GET_FUN(__glewColorFragmentOp1ATI) +#define glColorFragmentOp2ATI GLEW_GET_FUN(__glewColorFragmentOp2ATI) +#define glColorFragmentOp3ATI GLEW_GET_FUN(__glewColorFragmentOp3ATI) +#define glDeleteFragmentShaderATI GLEW_GET_FUN(__glewDeleteFragmentShaderATI) +#define glEndFragmentShaderATI GLEW_GET_FUN(__glewEndFragmentShaderATI) +#define glGenFragmentShadersATI GLEW_GET_FUN(__glewGenFragmentShadersATI) +#define glPassTexCoordATI GLEW_GET_FUN(__glewPassTexCoordATI) +#define glSampleMapATI GLEW_GET_FUN(__glewSampleMapATI) +#define glSetFragmentShaderConstantATI GLEW_GET_FUN(__glewSetFragmentShaderConstantATI) + +#define GLEW_ATI_fragment_shader GLEW_GET_VAR(__GLEW_ATI_fragment_shader) + +#endif /* GL_ATI_fragment_shader */ + +/* ------------------------ GL_ATI_map_object_buffer ----------------------- */ + +#ifndef GL_ATI_map_object_buffer +#define GL_ATI_map_object_buffer 1 + +typedef void* (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); + +#define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI) +#define glUnmapObjectBufferATI GLEW_GET_FUN(__glewUnmapObjectBufferATI) + +#define GLEW_ATI_map_object_buffer GLEW_GET_VAR(__GLEW_ATI_map_object_buffer) + +#endif /* GL_ATI_map_object_buffer */ + +/* ----------------------------- GL_ATI_meminfo ---------------------------- */ + +#ifndef GL_ATI_meminfo +#define GL_ATI_meminfo 1 + +#define GL_VBO_FREE_MEMORY_ATI 0x87FB +#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC +#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD + +#define GLEW_ATI_meminfo GLEW_GET_VAR(__GLEW_ATI_meminfo) + +#endif /* GL_ATI_meminfo */ + +/* -------------------------- GL_ATI_pn_triangles -------------------------- */ + +#ifndef GL_ATI_pn_triangles +#define GL_ATI_pn_triangles 1 + +#define GL_PN_TRIANGLES_ATI 0x87F0 +#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 +#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 +#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 +#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 +#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 +#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 +#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 +#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 + +typedef void (GLAPIENTRY * PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); + +#define glPNTrianglesfATI GLEW_GET_FUN(__glewPNTrianglesfATI) +#define glPNTrianglesiATI GLEW_GET_FUN(__glewPNTrianglesiATI) + +#define GLEW_ATI_pn_triangles GLEW_GET_VAR(__GLEW_ATI_pn_triangles) + +#endif /* GL_ATI_pn_triangles */ + +/* ------------------------ GL_ATI_separate_stencil ------------------------ */ + +#ifndef GL_ATI_separate_stencil +#define GL_ATI_separate_stencil 1 + +#define GL_STENCIL_BACK_FUNC_ATI 0x8800 +#define GL_STENCIL_BACK_FAIL_ATI 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 + +typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + +#define glStencilFuncSeparateATI GLEW_GET_FUN(__glewStencilFuncSeparateATI) +#define glStencilOpSeparateATI GLEW_GET_FUN(__glewStencilOpSeparateATI) + +#define GLEW_ATI_separate_stencil GLEW_GET_VAR(__GLEW_ATI_separate_stencil) + +#endif /* GL_ATI_separate_stencil */ + +/* ----------------------- GL_ATI_shader_texture_lod ----------------------- */ + +#ifndef GL_ATI_shader_texture_lod +#define GL_ATI_shader_texture_lod 1 + +#define GLEW_ATI_shader_texture_lod GLEW_GET_VAR(__GLEW_ATI_shader_texture_lod) + +#endif /* GL_ATI_shader_texture_lod */ + +/* ---------------------- GL_ATI_text_fragment_shader ---------------------- */ + +#ifndef GL_ATI_text_fragment_shader +#define GL_ATI_text_fragment_shader 1 + +#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 + +#define GLEW_ATI_text_fragment_shader GLEW_GET_VAR(__GLEW_ATI_text_fragment_shader) + +#endif /* GL_ATI_text_fragment_shader */ + +/* --------------------- GL_ATI_texture_compression_3dc -------------------- */ + +#ifndef GL_ATI_texture_compression_3dc +#define GL_ATI_texture_compression_3dc 1 + +#define GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837 + +#define GLEW_ATI_texture_compression_3dc GLEW_GET_VAR(__GLEW_ATI_texture_compression_3dc) + +#endif /* GL_ATI_texture_compression_3dc */ + +/* ---------------------- GL_ATI_texture_env_combine3 ---------------------- */ + +#ifndef GL_ATI_texture_env_combine3 +#define GL_ATI_texture_env_combine3 1 + +#define GL_MODULATE_ADD_ATI 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATI 0x8745 +#define GL_MODULATE_SUBTRACT_ATI 0x8746 + +#define GLEW_ATI_texture_env_combine3 GLEW_GET_VAR(__GLEW_ATI_texture_env_combine3) + +#endif /* GL_ATI_texture_env_combine3 */ + +/* -------------------------- GL_ATI_texture_float ------------------------- */ + +#ifndef GL_ATI_texture_float +#define GL_ATI_texture_float 1 + +#define GL_RGBA_FLOAT32_ATI 0x8814 +#define GL_RGB_FLOAT32_ATI 0x8815 +#define GL_ALPHA_FLOAT32_ATI 0x8816 +#define GL_INTENSITY_FLOAT32_ATI 0x8817 +#define GL_LUMINANCE_FLOAT32_ATI 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 +#define GL_RGBA_FLOAT16_ATI 0x881A +#define GL_RGB_FLOAT16_ATI 0x881B +#define GL_ALPHA_FLOAT16_ATI 0x881C +#define GL_INTENSITY_FLOAT16_ATI 0x881D +#define GL_LUMINANCE_FLOAT16_ATI 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F + +#define GLEW_ATI_texture_float GLEW_GET_VAR(__GLEW_ATI_texture_float) + +#endif /* GL_ATI_texture_float */ + +/* ----------------------- GL_ATI_texture_mirror_once ---------------------- */ + +#ifndef GL_ATI_texture_mirror_once +#define GL_ATI_texture_mirror_once 1 + +#define GL_MIRROR_CLAMP_ATI 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 + +#define GLEW_ATI_texture_mirror_once GLEW_GET_VAR(__GLEW_ATI_texture_mirror_once) + +#endif /* GL_ATI_texture_mirror_once */ + +/* ----------------------- GL_ATI_vertex_array_object ---------------------- */ + +#ifndef GL_ATI_vertex_array_object +#define GL_ATI_vertex_array_object 1 + +#define GL_STATIC_ATI 0x8760 +#define GL_DYNAMIC_ATI 0x8761 +#define GL_PRESERVE_ATI 0x8762 +#define GL_DISCARD_ATI 0x8763 +#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 +#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 +#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 +#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 + +typedef void (GLAPIENTRY * PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (GLAPIENTRY * PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); +typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void* pointer, GLenum usage); +typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void* pointer, GLenum preserve); +typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + +#define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI) +#define glFreeObjectBufferATI GLEW_GET_FUN(__glewFreeObjectBufferATI) +#define glGetArrayObjectfvATI GLEW_GET_FUN(__glewGetArrayObjectfvATI) +#define glGetArrayObjectivATI GLEW_GET_FUN(__glewGetArrayObjectivATI) +#define glGetObjectBufferfvATI GLEW_GET_FUN(__glewGetObjectBufferfvATI) +#define glGetObjectBufferivATI GLEW_GET_FUN(__glewGetObjectBufferivATI) +#define glGetVariantArrayObjectfvATI GLEW_GET_FUN(__glewGetVariantArrayObjectfvATI) +#define glGetVariantArrayObjectivATI GLEW_GET_FUN(__glewGetVariantArrayObjectivATI) +#define glIsObjectBufferATI GLEW_GET_FUN(__glewIsObjectBufferATI) +#define glNewObjectBufferATI GLEW_GET_FUN(__glewNewObjectBufferATI) +#define glUpdateObjectBufferATI GLEW_GET_FUN(__glewUpdateObjectBufferATI) +#define glVariantArrayObjectATI GLEW_GET_FUN(__glewVariantArrayObjectATI) + +#define GLEW_ATI_vertex_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_array_object) + +#endif /* GL_ATI_vertex_array_object */ + +/* ------------------- GL_ATI_vertex_attrib_array_object ------------------- */ + +#ifndef GL_ATI_vertex_attrib_array_object +#define GL_ATI_vertex_attrib_array_object 1 + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); + +#define glGetVertexAttribArrayObjectfvATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectfvATI) +#define glGetVertexAttribArrayObjectivATI GLEW_GET_FUN(__glewGetVertexAttribArrayObjectivATI) +#define glVertexAttribArrayObjectATI GLEW_GET_FUN(__glewVertexAttribArrayObjectATI) + +#define GLEW_ATI_vertex_attrib_array_object GLEW_GET_VAR(__GLEW_ATI_vertex_attrib_array_object) + +#endif /* GL_ATI_vertex_attrib_array_object */ + +/* ------------------------- GL_ATI_vertex_streams ------------------------- */ + +#ifndef GL_ATI_vertex_streams +#define GL_ATI_vertex_streams 1 + +#define GL_MAX_VERTEX_STREAMS_ATI 0x876B +#define GL_VERTEX_SOURCE_ATI 0x876C +#define GL_VERTEX_STREAM0_ATI 0x876D +#define GL_VERTEX_STREAM1_ATI 0x876E +#define GL_VERTEX_STREAM2_ATI 0x876F +#define GL_VERTEX_STREAM3_ATI 0x8770 +#define GL_VERTEX_STREAM4_ATI 0x8771 +#define GL_VERTEX_STREAM5_ATI 0x8772 +#define GL_VERTEX_STREAM6_ATI 0x8773 +#define GL_VERTEX_STREAM7_ATI 0x8774 + +typedef void (GLAPIENTRY * PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte x, GLbyte y, GLbyte z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *v); + +#define glClientActiveVertexStreamATI GLEW_GET_FUN(__glewClientActiveVertexStreamATI) +#define glNormalStream3bATI GLEW_GET_FUN(__glewNormalStream3bATI) +#define glNormalStream3bvATI GLEW_GET_FUN(__glewNormalStream3bvATI) +#define glNormalStream3dATI GLEW_GET_FUN(__glewNormalStream3dATI) +#define glNormalStream3dvATI GLEW_GET_FUN(__glewNormalStream3dvATI) +#define glNormalStream3fATI GLEW_GET_FUN(__glewNormalStream3fATI) +#define glNormalStream3fvATI GLEW_GET_FUN(__glewNormalStream3fvATI) +#define glNormalStream3iATI GLEW_GET_FUN(__glewNormalStream3iATI) +#define glNormalStream3ivATI GLEW_GET_FUN(__glewNormalStream3ivATI) +#define glNormalStream3sATI GLEW_GET_FUN(__glewNormalStream3sATI) +#define glNormalStream3svATI GLEW_GET_FUN(__glewNormalStream3svATI) +#define glVertexBlendEnvfATI GLEW_GET_FUN(__glewVertexBlendEnvfATI) +#define glVertexBlendEnviATI GLEW_GET_FUN(__glewVertexBlendEnviATI) +#define glVertexStream2dATI GLEW_GET_FUN(__glewVertexStream2dATI) +#define glVertexStream2dvATI GLEW_GET_FUN(__glewVertexStream2dvATI) +#define glVertexStream2fATI GLEW_GET_FUN(__glewVertexStream2fATI) +#define glVertexStream2fvATI GLEW_GET_FUN(__glewVertexStream2fvATI) +#define glVertexStream2iATI GLEW_GET_FUN(__glewVertexStream2iATI) +#define glVertexStream2ivATI GLEW_GET_FUN(__glewVertexStream2ivATI) +#define glVertexStream2sATI GLEW_GET_FUN(__glewVertexStream2sATI) +#define glVertexStream2svATI GLEW_GET_FUN(__glewVertexStream2svATI) +#define glVertexStream3dATI GLEW_GET_FUN(__glewVertexStream3dATI) +#define glVertexStream3dvATI GLEW_GET_FUN(__glewVertexStream3dvATI) +#define glVertexStream3fATI GLEW_GET_FUN(__glewVertexStream3fATI) +#define glVertexStream3fvATI GLEW_GET_FUN(__glewVertexStream3fvATI) +#define glVertexStream3iATI GLEW_GET_FUN(__glewVertexStream3iATI) +#define glVertexStream3ivATI GLEW_GET_FUN(__glewVertexStream3ivATI) +#define glVertexStream3sATI GLEW_GET_FUN(__glewVertexStream3sATI) +#define glVertexStream3svATI GLEW_GET_FUN(__glewVertexStream3svATI) +#define glVertexStream4dATI GLEW_GET_FUN(__glewVertexStream4dATI) +#define glVertexStream4dvATI GLEW_GET_FUN(__glewVertexStream4dvATI) +#define glVertexStream4fATI GLEW_GET_FUN(__glewVertexStream4fATI) +#define glVertexStream4fvATI GLEW_GET_FUN(__glewVertexStream4fvATI) +#define glVertexStream4iATI GLEW_GET_FUN(__glewVertexStream4iATI) +#define glVertexStream4ivATI GLEW_GET_FUN(__glewVertexStream4ivATI) +#define glVertexStream4sATI GLEW_GET_FUN(__glewVertexStream4sATI) +#define glVertexStream4svATI GLEW_GET_FUN(__glewVertexStream4svATI) + +#define GLEW_ATI_vertex_streams GLEW_GET_VAR(__GLEW_ATI_vertex_streams) + +#endif /* GL_ATI_vertex_streams */ + +/* --------------------------- GL_EXT_422_pixels --------------------------- */ + +#ifndef GL_EXT_422_pixels +#define GL_EXT_422_pixels 1 + +#define GL_422_EXT 0x80CC +#define GL_422_REV_EXT 0x80CD +#define GL_422_AVERAGE_EXT 0x80CE +#define GL_422_REV_AVERAGE_EXT 0x80CF + +#define GLEW_EXT_422_pixels GLEW_GET_VAR(__GLEW_EXT_422_pixels) + +#endif /* GL_EXT_422_pixels */ + +/* ---------------------------- GL_EXT_Cg_shader --------------------------- */ + +#ifndef GL_EXT_Cg_shader +#define GL_EXT_Cg_shader 1 + +#define GL_CG_VERTEX_SHADER_EXT 0x890E +#define GL_CG_FRAGMENT_SHADER_EXT 0x890F + +#define GLEW_EXT_Cg_shader GLEW_GET_VAR(__GLEW_EXT_Cg_shader) + +#endif /* GL_EXT_Cg_shader */ + +/* ------------------------------ GL_EXT_abgr ------------------------------ */ + +#ifndef GL_EXT_abgr +#define GL_EXT_abgr 1 + +#define GL_ABGR_EXT 0x8000 + +#define GLEW_EXT_abgr GLEW_GET_VAR(__GLEW_EXT_abgr) + +#endif /* GL_EXT_abgr */ + +/* ------------------------------ GL_EXT_bgra ------------------------------ */ + +#ifndef GL_EXT_bgra +#define GL_EXT_bgra 1 + +#define GL_BGR_EXT 0x80E0 +#define GL_BGRA_EXT 0x80E1 + +#define GLEW_EXT_bgra GLEW_GET_VAR(__GLEW_EXT_bgra) + +#endif /* GL_EXT_bgra */ + +/* ------------------------ GL_EXT_bindable_uniform ------------------------ */ + +#ifndef GL_EXT_bindable_uniform +#define GL_EXT_bindable_uniform 1 + +#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2 +#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3 +#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 +#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED +#define GL_UNIFORM_BUFFER_EXT 0x8DEE +#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF + +typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location); +typedef GLintptr (GLAPIENTRY * PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location); +typedef void (GLAPIENTRY * PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer); + +#define glGetUniformBufferSizeEXT GLEW_GET_FUN(__glewGetUniformBufferSizeEXT) +#define glGetUniformOffsetEXT GLEW_GET_FUN(__glewGetUniformOffsetEXT) +#define glUniformBufferEXT GLEW_GET_FUN(__glewUniformBufferEXT) + +#define GLEW_EXT_bindable_uniform GLEW_GET_VAR(__GLEW_EXT_bindable_uniform) + +#endif /* GL_EXT_bindable_uniform */ + +/* --------------------------- GL_EXT_blend_color -------------------------- */ + +#ifndef GL_EXT_blend_color +#define GL_EXT_blend_color 1 + +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_BLEND_COLOR_EXT 0x8005 + +typedef void (GLAPIENTRY * PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + +#define glBlendColorEXT GLEW_GET_FUN(__glewBlendColorEXT) + +#define GLEW_EXT_blend_color GLEW_GET_VAR(__GLEW_EXT_blend_color) + +#endif /* GL_EXT_blend_color */ + +/* --------------------- GL_EXT_blend_equation_separate -------------------- */ + +#ifndef GL_EXT_blend_equation_separate +#define GL_EXT_blend_equation_separate 1 + +#define GL_BLEND_EQUATION_RGB_EXT 0x8009 +#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); + +#define glBlendEquationSeparateEXT GLEW_GET_FUN(__glewBlendEquationSeparateEXT) + +#define GLEW_EXT_blend_equation_separate GLEW_GET_VAR(__GLEW_EXT_blend_equation_separate) + +#endif /* GL_EXT_blend_equation_separate */ + +/* ----------------------- GL_EXT_blend_func_separate ---------------------- */ + +#ifndef GL_EXT_blend_func_separate +#define GL_EXT_blend_func_separate 1 + +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB + +typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + +#define glBlendFuncSeparateEXT GLEW_GET_FUN(__glewBlendFuncSeparateEXT) + +#define GLEW_EXT_blend_func_separate GLEW_GET_VAR(__GLEW_EXT_blend_func_separate) + +#endif /* GL_EXT_blend_func_separate */ + +/* ------------------------- GL_EXT_blend_logic_op ------------------------- */ + +#ifndef GL_EXT_blend_logic_op +#define GL_EXT_blend_logic_op 1 + +#define GLEW_EXT_blend_logic_op GLEW_GET_VAR(__GLEW_EXT_blend_logic_op) + +#endif /* GL_EXT_blend_logic_op */ + +/* -------------------------- GL_EXT_blend_minmax -------------------------- */ + +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 + +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#define GL_BLEND_EQUATION_EXT 0x8009 + +typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); + +#define glBlendEquationEXT GLEW_GET_FUN(__glewBlendEquationEXT) + +#define GLEW_EXT_blend_minmax GLEW_GET_VAR(__GLEW_EXT_blend_minmax) + +#endif /* GL_EXT_blend_minmax */ + +/* ------------------------- GL_EXT_blend_subtract ------------------------- */ + +#ifndef GL_EXT_blend_subtract +#define GL_EXT_blend_subtract 1 + +#define GL_FUNC_SUBTRACT_EXT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B + +#define GLEW_EXT_blend_subtract GLEW_GET_VAR(__GLEW_EXT_blend_subtract) + +#endif /* GL_EXT_blend_subtract */ + +/* ------------------------ GL_EXT_clip_volume_hint ------------------------ */ + +#ifndef GL_EXT_clip_volume_hint +#define GL_EXT_clip_volume_hint 1 + +#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 + +#define GLEW_EXT_clip_volume_hint GLEW_GET_VAR(__GLEW_EXT_clip_volume_hint) + +#endif /* GL_EXT_clip_volume_hint */ + +/* ------------------------------ GL_EXT_cmyka ----------------------------- */ + +#ifndef GL_EXT_cmyka +#define GL_EXT_cmyka 1 + +#define GL_CMYK_EXT 0x800C +#define GL_CMYKA_EXT 0x800D +#define GL_PACK_CMYK_HINT_EXT 0x800E +#define GL_UNPACK_CMYK_HINT_EXT 0x800F + +#define GLEW_EXT_cmyka GLEW_GET_VAR(__GLEW_EXT_cmyka) + +#endif /* GL_EXT_cmyka */ + +/* ------------------------- GL_EXT_color_subtable ------------------------- */ + +#ifndef GL_EXT_color_subtable +#define GL_EXT_color_subtable 1 + +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void* data); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + +#define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT) +#define glCopyColorSubTableEXT GLEW_GET_FUN(__glewCopyColorSubTableEXT) + +#define GLEW_EXT_color_subtable GLEW_GET_VAR(__GLEW_EXT_color_subtable) + +#endif /* GL_EXT_color_subtable */ + +/* ---------------------- GL_EXT_compiled_vertex_array --------------------- */ + +#ifndef GL_EXT_compiled_vertex_array +#define GL_EXT_compiled_vertex_array 1 + +#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 +#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 + +typedef void (GLAPIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); + +#define glLockArraysEXT GLEW_GET_FUN(__glewLockArraysEXT) +#define glUnlockArraysEXT GLEW_GET_FUN(__glewUnlockArraysEXT) + +#define GLEW_EXT_compiled_vertex_array GLEW_GET_VAR(__GLEW_EXT_compiled_vertex_array) + +#endif /* GL_EXT_compiled_vertex_array */ + +/* --------------------------- GL_EXT_convolution -------------------------- */ + +#ifndef GL_EXT_convolution +#define GL_EXT_convolution 1 + +#define GL_CONVOLUTION_1D_EXT 0x8010 +#define GL_CONVOLUTION_2D_EXT 0x8011 +#define GL_SEPARABLE_2D_EXT 0x8012 +#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 +#define GL_REDUCE_EXT 0x8016 +#define GL_CONVOLUTION_FORMAT_EXT 0x8017 +#define GL_CONVOLUTION_WIDTH_EXT 0x8018 +#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 + +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* row, void* column, void* span); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* row, const void* column); + +#define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT) +#define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT) +#define glConvolutionParameterfEXT GLEW_GET_FUN(__glewConvolutionParameterfEXT) +#define glConvolutionParameterfvEXT GLEW_GET_FUN(__glewConvolutionParameterfvEXT) +#define glConvolutionParameteriEXT GLEW_GET_FUN(__glewConvolutionParameteriEXT) +#define glConvolutionParameterivEXT GLEW_GET_FUN(__glewConvolutionParameterivEXT) +#define glCopyConvolutionFilter1DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter1DEXT) +#define glCopyConvolutionFilter2DEXT GLEW_GET_FUN(__glewCopyConvolutionFilter2DEXT) +#define glGetConvolutionFilterEXT GLEW_GET_FUN(__glewGetConvolutionFilterEXT) +#define glGetConvolutionParameterfvEXT GLEW_GET_FUN(__glewGetConvolutionParameterfvEXT) +#define glGetConvolutionParameterivEXT GLEW_GET_FUN(__glewGetConvolutionParameterivEXT) +#define glGetSeparableFilterEXT GLEW_GET_FUN(__glewGetSeparableFilterEXT) +#define glSeparableFilter2DEXT GLEW_GET_FUN(__glewSeparableFilter2DEXT) + +#define GLEW_EXT_convolution GLEW_GET_VAR(__GLEW_EXT_convolution) + +#endif /* GL_EXT_convolution */ + +/* ------------------------ GL_EXT_coordinate_frame ------------------------ */ + +#ifndef GL_EXT_coordinate_frame +#define GL_EXT_coordinate_frame 1 + +#define GL_TANGENT_ARRAY_EXT 0x8439 +#define GL_BINORMAL_ARRAY_EXT 0x843A +#define GL_CURRENT_TANGENT_EXT 0x843B +#define GL_CURRENT_BINORMAL_EXT 0x843C +#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E +#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F +#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 +#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 +#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 +#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 +#define GL_MAP1_TANGENT_EXT 0x8444 +#define GL_MAP2_TANGENT_EXT 0x8445 +#define GL_MAP1_BINORMAL_EXT 0x8446 +#define GL_MAP2_BINORMAL_EXT 0x8447 + +typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); +typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); + +#define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT) +#define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT) + +#define GLEW_EXT_coordinate_frame GLEW_GET_VAR(__GLEW_EXT_coordinate_frame) + +#endif /* GL_EXT_coordinate_frame */ + +/* -------------------------- GL_EXT_copy_texture -------------------------- */ + +#ifndef GL_EXT_copy_texture +#define GL_EXT_copy_texture 1 + +typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + +#define glCopyTexImage1DEXT GLEW_GET_FUN(__glewCopyTexImage1DEXT) +#define glCopyTexImage2DEXT GLEW_GET_FUN(__glewCopyTexImage2DEXT) +#define glCopyTexSubImage1DEXT GLEW_GET_FUN(__glewCopyTexSubImage1DEXT) +#define glCopyTexSubImage2DEXT GLEW_GET_FUN(__glewCopyTexSubImage2DEXT) +#define glCopyTexSubImage3DEXT GLEW_GET_FUN(__glewCopyTexSubImage3DEXT) + +#define GLEW_EXT_copy_texture GLEW_GET_VAR(__GLEW_EXT_copy_texture) + +#endif /* GL_EXT_copy_texture */ + +/* --------------------------- GL_EXT_cull_vertex -------------------------- */ + +#ifndef GL_EXT_cull_vertex +#define GL_EXT_cull_vertex 1 + +#define GL_CULL_VERTEX_EXT 0x81AA +#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB +#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC + +typedef void (GLAPIENTRY * PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat* params); + +#define glCullParameterdvEXT GLEW_GET_FUN(__glewCullParameterdvEXT) +#define glCullParameterfvEXT GLEW_GET_FUN(__glewCullParameterfvEXT) + +#define GLEW_EXT_cull_vertex GLEW_GET_VAR(__GLEW_EXT_cull_vertex) + +#endif /* GL_EXT_cull_vertex */ + +/* ------------------------ GL_EXT_depth_bounds_test ----------------------- */ + +#ifndef GL_EXT_depth_bounds_test +#define GL_EXT_depth_bounds_test 1 + +#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 +#define GL_DEPTH_BOUNDS_EXT 0x8891 + +typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); + +#define glDepthBoundsEXT GLEW_GET_FUN(__glewDepthBoundsEXT) + +#define GLEW_EXT_depth_bounds_test GLEW_GET_VAR(__GLEW_EXT_depth_bounds_test) + +#endif /* GL_EXT_depth_bounds_test */ + +/* ----------------------- GL_EXT_direct_state_access ---------------------- */ + +#ifndef GL_EXT_direct_state_access +#define GL_EXT_direct_state_access 1 + +#define GL_PROGRAM_MATRIX_EXT 0x8E2D +#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E +#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F + +typedef void (GLAPIENTRY * PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); +typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); +typedef void (GLAPIENTRY * PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLDISABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); +typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); +typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array); +typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum* bufs); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); +typedef void (GLAPIENTRY * PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); +typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, void* img); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, void* img); +typedef void (GLAPIENTRY * PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void** params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void* data); +typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void* string); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, GLvoid** params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); +typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint* param); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLvoid** param); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, GLvoid** param); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GLAPIENTRY * PFNGLMATRIXFRUSTUMEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXLOADFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTDEXTPROC) (GLenum matrixMode, const GLdouble* m); +typedef void (GLAPIENTRY * PFNGLMATRIXMULTFEXTPROC) (GLenum matrixMode, const GLfloat* m); +typedef void (GLAPIENTRY * PFNGLMATRIXORTHOEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); +typedef void (GLAPIENTRY * PFNGLMATRIXPOPEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXPUSHEXTPROC) (GLenum matrixMode); +typedef void (GLAPIENTRY * PFNGLMATRIXROTATEDEXTPROC) (GLenum matrixMode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXROTATEFEXTPROC) (GLenum matrixMode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMATRIXSCALEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXSCALEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* param); +typedef void (GLAPIENTRY * PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data); +typedef void (GLAPIENTRY * PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint* params); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat* param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* param); +typedef void (GLAPIENTRY * PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); + +#define glBindMultiTextureEXT GLEW_GET_FUN(__glewBindMultiTextureEXT) +#define glCheckNamedFramebufferStatusEXT GLEW_GET_FUN(__glewCheckNamedFramebufferStatusEXT) +#define glClientAttribDefaultEXT GLEW_GET_FUN(__glewClientAttribDefaultEXT) +#define glCompressedMultiTexImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage1DEXT) +#define glCompressedMultiTexImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage2DEXT) +#define glCompressedMultiTexImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexImage3DEXT) +#define glCompressedMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage1DEXT) +#define glCompressedMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage2DEXT) +#define glCompressedMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCompressedMultiTexSubImage3DEXT) +#define glCompressedTextureImage1DEXT GLEW_GET_FUN(__glewCompressedTextureImage1DEXT) +#define glCompressedTextureImage2DEXT GLEW_GET_FUN(__glewCompressedTextureImage2DEXT) +#define glCompressedTextureImage3DEXT GLEW_GET_FUN(__glewCompressedTextureImage3DEXT) +#define glCompressedTextureSubImage1DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage1DEXT) +#define glCompressedTextureSubImage2DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage2DEXT) +#define glCompressedTextureSubImage3DEXT GLEW_GET_FUN(__glewCompressedTextureSubImage3DEXT) +#define glCopyMultiTexImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexImage1DEXT) +#define glCopyMultiTexImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexImage2DEXT) +#define glCopyMultiTexSubImage1DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage1DEXT) +#define glCopyMultiTexSubImage2DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage2DEXT) +#define glCopyMultiTexSubImage3DEXT GLEW_GET_FUN(__glewCopyMultiTexSubImage3DEXT) +#define glCopyTextureImage1DEXT GLEW_GET_FUN(__glewCopyTextureImage1DEXT) +#define glCopyTextureImage2DEXT GLEW_GET_FUN(__glewCopyTextureImage2DEXT) +#define glCopyTextureSubImage1DEXT GLEW_GET_FUN(__glewCopyTextureSubImage1DEXT) +#define glCopyTextureSubImage2DEXT GLEW_GET_FUN(__glewCopyTextureSubImage2DEXT) +#define glCopyTextureSubImage3DEXT GLEW_GET_FUN(__glewCopyTextureSubImage3DEXT) +#define glDisableClientStateIndexedEXT GLEW_GET_FUN(__glewDisableClientStateIndexedEXT) +#define glDisableClientStateiEXT GLEW_GET_FUN(__glewDisableClientStateiEXT) +#define glDisableVertexArrayAttribEXT GLEW_GET_FUN(__glewDisableVertexArrayAttribEXT) +#define glDisableVertexArrayEXT GLEW_GET_FUN(__glewDisableVertexArrayEXT) +#define glEnableClientStateIndexedEXT GLEW_GET_FUN(__glewEnableClientStateIndexedEXT) +#define glEnableClientStateiEXT GLEW_GET_FUN(__glewEnableClientStateiEXT) +#define glEnableVertexArrayAttribEXT GLEW_GET_FUN(__glewEnableVertexArrayAttribEXT) +#define glEnableVertexArrayEXT GLEW_GET_FUN(__glewEnableVertexArrayEXT) +#define glFlushMappedNamedBufferRangeEXT GLEW_GET_FUN(__glewFlushMappedNamedBufferRangeEXT) +#define glFramebufferDrawBufferEXT GLEW_GET_FUN(__glewFramebufferDrawBufferEXT) +#define glFramebufferDrawBuffersEXT GLEW_GET_FUN(__glewFramebufferDrawBuffersEXT) +#define glFramebufferReadBufferEXT GLEW_GET_FUN(__glewFramebufferReadBufferEXT) +#define glGenerateMultiTexMipmapEXT GLEW_GET_FUN(__glewGenerateMultiTexMipmapEXT) +#define glGenerateTextureMipmapEXT GLEW_GET_FUN(__glewGenerateTextureMipmapEXT) +#define glGetCompressedMultiTexImageEXT GLEW_GET_FUN(__glewGetCompressedMultiTexImageEXT) +#define glGetCompressedTextureImageEXT GLEW_GET_FUN(__glewGetCompressedTextureImageEXT) +#define glGetDoubleIndexedvEXT GLEW_GET_FUN(__glewGetDoubleIndexedvEXT) +#define glGetDoublei_vEXT GLEW_GET_FUN(__glewGetDoublei_vEXT) +#define glGetFloatIndexedvEXT GLEW_GET_FUN(__glewGetFloatIndexedvEXT) +#define glGetFloati_vEXT GLEW_GET_FUN(__glewGetFloati_vEXT) +#define glGetFramebufferParameterivEXT GLEW_GET_FUN(__glewGetFramebufferParameterivEXT) +#define glGetMultiTexEnvfvEXT GLEW_GET_FUN(__glewGetMultiTexEnvfvEXT) +#define glGetMultiTexEnvivEXT GLEW_GET_FUN(__glewGetMultiTexEnvivEXT) +#define glGetMultiTexGendvEXT GLEW_GET_FUN(__glewGetMultiTexGendvEXT) +#define glGetMultiTexGenfvEXT GLEW_GET_FUN(__glewGetMultiTexGenfvEXT) +#define glGetMultiTexGenivEXT GLEW_GET_FUN(__glewGetMultiTexGenivEXT) +#define glGetMultiTexImageEXT GLEW_GET_FUN(__glewGetMultiTexImageEXT) +#define glGetMultiTexLevelParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterfvEXT) +#define glGetMultiTexLevelParameterivEXT GLEW_GET_FUN(__glewGetMultiTexLevelParameterivEXT) +#define glGetMultiTexParameterIivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIivEXT) +#define glGetMultiTexParameterIuivEXT GLEW_GET_FUN(__glewGetMultiTexParameterIuivEXT) +#define glGetMultiTexParameterfvEXT GLEW_GET_FUN(__glewGetMultiTexParameterfvEXT) +#define glGetMultiTexParameterivEXT GLEW_GET_FUN(__glewGetMultiTexParameterivEXT) +#define glGetNamedBufferParameterivEXT GLEW_GET_FUN(__glewGetNamedBufferParameterivEXT) +#define glGetNamedBufferPointervEXT GLEW_GET_FUN(__glewGetNamedBufferPointervEXT) +#define glGetNamedBufferSubDataEXT GLEW_GET_FUN(__glewGetNamedBufferSubDataEXT) +#define glGetNamedFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetNamedFramebufferAttachmentParameterivEXT) +#define glGetNamedProgramLocalParameterIivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIivEXT) +#define glGetNamedProgramLocalParameterIuivEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterIuivEXT) +#define glGetNamedProgramLocalParameterdvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterdvEXT) +#define glGetNamedProgramLocalParameterfvEXT GLEW_GET_FUN(__glewGetNamedProgramLocalParameterfvEXT) +#define glGetNamedProgramStringEXT GLEW_GET_FUN(__glewGetNamedProgramStringEXT) +#define glGetNamedProgramivEXT GLEW_GET_FUN(__glewGetNamedProgramivEXT) +#define glGetNamedRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetNamedRenderbufferParameterivEXT) +#define glGetPointerIndexedvEXT GLEW_GET_FUN(__glewGetPointerIndexedvEXT) +#define glGetPointeri_vEXT GLEW_GET_FUN(__glewGetPointeri_vEXT) +#define glGetTextureImageEXT GLEW_GET_FUN(__glewGetTextureImageEXT) +#define glGetTextureLevelParameterfvEXT GLEW_GET_FUN(__glewGetTextureLevelParameterfvEXT) +#define glGetTextureLevelParameterivEXT GLEW_GET_FUN(__glewGetTextureLevelParameterivEXT) +#define glGetTextureParameterIivEXT GLEW_GET_FUN(__glewGetTextureParameterIivEXT) +#define glGetTextureParameterIuivEXT GLEW_GET_FUN(__glewGetTextureParameterIuivEXT) +#define glGetTextureParameterfvEXT GLEW_GET_FUN(__glewGetTextureParameterfvEXT) +#define glGetTextureParameterivEXT GLEW_GET_FUN(__glewGetTextureParameterivEXT) +#define glGetVertexArrayIntegeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayIntegeri_vEXT) +#define glGetVertexArrayIntegervEXT GLEW_GET_FUN(__glewGetVertexArrayIntegervEXT) +#define glGetVertexArrayPointeri_vEXT GLEW_GET_FUN(__glewGetVertexArrayPointeri_vEXT) +#define glGetVertexArrayPointervEXT GLEW_GET_FUN(__glewGetVertexArrayPointervEXT) +#define glMapNamedBufferEXT GLEW_GET_FUN(__glewMapNamedBufferEXT) +#define glMapNamedBufferRangeEXT GLEW_GET_FUN(__glewMapNamedBufferRangeEXT) +#define glMatrixFrustumEXT GLEW_GET_FUN(__glewMatrixFrustumEXT) +#define glMatrixLoadIdentityEXT GLEW_GET_FUN(__glewMatrixLoadIdentityEXT) +#define glMatrixLoadTransposedEXT GLEW_GET_FUN(__glewMatrixLoadTransposedEXT) +#define glMatrixLoadTransposefEXT GLEW_GET_FUN(__glewMatrixLoadTransposefEXT) +#define glMatrixLoaddEXT GLEW_GET_FUN(__glewMatrixLoaddEXT) +#define glMatrixLoadfEXT GLEW_GET_FUN(__glewMatrixLoadfEXT) +#define glMatrixMultTransposedEXT GLEW_GET_FUN(__glewMatrixMultTransposedEXT) +#define glMatrixMultTransposefEXT GLEW_GET_FUN(__glewMatrixMultTransposefEXT) +#define glMatrixMultdEXT GLEW_GET_FUN(__glewMatrixMultdEXT) +#define glMatrixMultfEXT GLEW_GET_FUN(__glewMatrixMultfEXT) +#define glMatrixOrthoEXT GLEW_GET_FUN(__glewMatrixOrthoEXT) +#define glMatrixPopEXT GLEW_GET_FUN(__glewMatrixPopEXT) +#define glMatrixPushEXT GLEW_GET_FUN(__glewMatrixPushEXT) +#define glMatrixRotatedEXT GLEW_GET_FUN(__glewMatrixRotatedEXT) +#define glMatrixRotatefEXT GLEW_GET_FUN(__glewMatrixRotatefEXT) +#define glMatrixScaledEXT GLEW_GET_FUN(__glewMatrixScaledEXT) +#define glMatrixScalefEXT GLEW_GET_FUN(__glewMatrixScalefEXT) +#define glMatrixTranslatedEXT GLEW_GET_FUN(__glewMatrixTranslatedEXT) +#define glMatrixTranslatefEXT GLEW_GET_FUN(__glewMatrixTranslatefEXT) +#define glMultiTexBufferEXT GLEW_GET_FUN(__glewMultiTexBufferEXT) +#define glMultiTexCoordPointerEXT GLEW_GET_FUN(__glewMultiTexCoordPointerEXT) +#define glMultiTexEnvfEXT GLEW_GET_FUN(__glewMultiTexEnvfEXT) +#define glMultiTexEnvfvEXT GLEW_GET_FUN(__glewMultiTexEnvfvEXT) +#define glMultiTexEnviEXT GLEW_GET_FUN(__glewMultiTexEnviEXT) +#define glMultiTexEnvivEXT GLEW_GET_FUN(__glewMultiTexEnvivEXT) +#define glMultiTexGendEXT GLEW_GET_FUN(__glewMultiTexGendEXT) +#define glMultiTexGendvEXT GLEW_GET_FUN(__glewMultiTexGendvEXT) +#define glMultiTexGenfEXT GLEW_GET_FUN(__glewMultiTexGenfEXT) +#define glMultiTexGenfvEXT GLEW_GET_FUN(__glewMultiTexGenfvEXT) +#define glMultiTexGeniEXT GLEW_GET_FUN(__glewMultiTexGeniEXT) +#define glMultiTexGenivEXT GLEW_GET_FUN(__glewMultiTexGenivEXT) +#define glMultiTexImage1DEXT GLEW_GET_FUN(__glewMultiTexImage1DEXT) +#define glMultiTexImage2DEXT GLEW_GET_FUN(__glewMultiTexImage2DEXT) +#define glMultiTexImage3DEXT GLEW_GET_FUN(__glewMultiTexImage3DEXT) +#define glMultiTexParameterIivEXT GLEW_GET_FUN(__glewMultiTexParameterIivEXT) +#define glMultiTexParameterIuivEXT GLEW_GET_FUN(__glewMultiTexParameterIuivEXT) +#define glMultiTexParameterfEXT GLEW_GET_FUN(__glewMultiTexParameterfEXT) +#define glMultiTexParameterfvEXT GLEW_GET_FUN(__glewMultiTexParameterfvEXT) +#define glMultiTexParameteriEXT GLEW_GET_FUN(__glewMultiTexParameteriEXT) +#define glMultiTexParameterivEXT GLEW_GET_FUN(__glewMultiTexParameterivEXT) +#define glMultiTexRenderbufferEXT GLEW_GET_FUN(__glewMultiTexRenderbufferEXT) +#define glMultiTexSubImage1DEXT GLEW_GET_FUN(__glewMultiTexSubImage1DEXT) +#define glMultiTexSubImage2DEXT GLEW_GET_FUN(__glewMultiTexSubImage2DEXT) +#define glMultiTexSubImage3DEXT GLEW_GET_FUN(__glewMultiTexSubImage3DEXT) +#define glNamedBufferDataEXT GLEW_GET_FUN(__glewNamedBufferDataEXT) +#define glNamedBufferSubDataEXT GLEW_GET_FUN(__glewNamedBufferSubDataEXT) +#define glNamedCopyBufferSubDataEXT GLEW_GET_FUN(__glewNamedCopyBufferSubDataEXT) +#define glNamedFramebufferRenderbufferEXT GLEW_GET_FUN(__glewNamedFramebufferRenderbufferEXT) +#define glNamedFramebufferTexture1DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture1DEXT) +#define glNamedFramebufferTexture2DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture2DEXT) +#define glNamedFramebufferTexture3DEXT GLEW_GET_FUN(__glewNamedFramebufferTexture3DEXT) +#define glNamedFramebufferTextureEXT GLEW_GET_FUN(__glewNamedFramebufferTextureEXT) +#define glNamedFramebufferTextureFaceEXT GLEW_GET_FUN(__glewNamedFramebufferTextureFaceEXT) +#define glNamedFramebufferTextureLayerEXT GLEW_GET_FUN(__glewNamedFramebufferTextureLayerEXT) +#define glNamedProgramLocalParameter4dEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dEXT) +#define glNamedProgramLocalParameter4dvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4dvEXT) +#define glNamedProgramLocalParameter4fEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fEXT) +#define glNamedProgramLocalParameter4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameter4fvEXT) +#define glNamedProgramLocalParameterI4iEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4iEXT) +#define glNamedProgramLocalParameterI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4ivEXT) +#define glNamedProgramLocalParameterI4uiEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uiEXT) +#define glNamedProgramLocalParameterI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParameterI4uivEXT) +#define glNamedProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewNamedProgramLocalParameters4fvEXT) +#define glNamedProgramLocalParametersI4ivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4ivEXT) +#define glNamedProgramLocalParametersI4uivEXT GLEW_GET_FUN(__glewNamedProgramLocalParametersI4uivEXT) +#define glNamedProgramStringEXT GLEW_GET_FUN(__glewNamedProgramStringEXT) +#define glNamedRenderbufferStorageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageEXT) +#define glNamedRenderbufferStorageMultisampleCoverageEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleCoverageEXT) +#define glNamedRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewNamedRenderbufferStorageMultisampleEXT) +#define glProgramUniform1fEXT GLEW_GET_FUN(__glewProgramUniform1fEXT) +#define glProgramUniform1fvEXT GLEW_GET_FUN(__glewProgramUniform1fvEXT) +#define glProgramUniform1iEXT GLEW_GET_FUN(__glewProgramUniform1iEXT) +#define glProgramUniform1ivEXT GLEW_GET_FUN(__glewProgramUniform1ivEXT) +#define glProgramUniform1uiEXT GLEW_GET_FUN(__glewProgramUniform1uiEXT) +#define glProgramUniform1uivEXT GLEW_GET_FUN(__glewProgramUniform1uivEXT) +#define glProgramUniform2fEXT GLEW_GET_FUN(__glewProgramUniform2fEXT) +#define glProgramUniform2fvEXT GLEW_GET_FUN(__glewProgramUniform2fvEXT) +#define glProgramUniform2iEXT GLEW_GET_FUN(__glewProgramUniform2iEXT) +#define glProgramUniform2ivEXT GLEW_GET_FUN(__glewProgramUniform2ivEXT) +#define glProgramUniform2uiEXT GLEW_GET_FUN(__glewProgramUniform2uiEXT) +#define glProgramUniform2uivEXT GLEW_GET_FUN(__glewProgramUniform2uivEXT) +#define glProgramUniform3fEXT GLEW_GET_FUN(__glewProgramUniform3fEXT) +#define glProgramUniform3fvEXT GLEW_GET_FUN(__glewProgramUniform3fvEXT) +#define glProgramUniform3iEXT GLEW_GET_FUN(__glewProgramUniform3iEXT) +#define glProgramUniform3ivEXT GLEW_GET_FUN(__glewProgramUniform3ivEXT) +#define glProgramUniform3uiEXT GLEW_GET_FUN(__glewProgramUniform3uiEXT) +#define glProgramUniform3uivEXT GLEW_GET_FUN(__glewProgramUniform3uivEXT) +#define glProgramUniform4fEXT GLEW_GET_FUN(__glewProgramUniform4fEXT) +#define glProgramUniform4fvEXT GLEW_GET_FUN(__glewProgramUniform4fvEXT) +#define glProgramUniform4iEXT GLEW_GET_FUN(__glewProgramUniform4iEXT) +#define glProgramUniform4ivEXT GLEW_GET_FUN(__glewProgramUniform4ivEXT) +#define glProgramUniform4uiEXT GLEW_GET_FUN(__glewProgramUniform4uiEXT) +#define glProgramUniform4uivEXT GLEW_GET_FUN(__glewProgramUniform4uivEXT) +#define glProgramUniformMatrix2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2fvEXT) +#define glProgramUniformMatrix2x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3fvEXT) +#define glProgramUniformMatrix2x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4fvEXT) +#define glProgramUniformMatrix3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3fvEXT) +#define glProgramUniformMatrix3x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2fvEXT) +#define glProgramUniformMatrix3x4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4fvEXT) +#define glProgramUniformMatrix4fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4fvEXT) +#define glProgramUniformMatrix4x2fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2fvEXT) +#define glProgramUniformMatrix4x3fvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3fvEXT) +#define glPushClientAttribDefaultEXT GLEW_GET_FUN(__glewPushClientAttribDefaultEXT) +#define glTextureBufferEXT GLEW_GET_FUN(__glewTextureBufferEXT) +#define glTextureImage1DEXT GLEW_GET_FUN(__glewTextureImage1DEXT) +#define glTextureImage2DEXT GLEW_GET_FUN(__glewTextureImage2DEXT) +#define glTextureImage3DEXT GLEW_GET_FUN(__glewTextureImage3DEXT) +#define glTextureParameterIivEXT GLEW_GET_FUN(__glewTextureParameterIivEXT) +#define glTextureParameterIuivEXT GLEW_GET_FUN(__glewTextureParameterIuivEXT) +#define glTextureParameterfEXT GLEW_GET_FUN(__glewTextureParameterfEXT) +#define glTextureParameterfvEXT GLEW_GET_FUN(__glewTextureParameterfvEXT) +#define glTextureParameteriEXT GLEW_GET_FUN(__glewTextureParameteriEXT) +#define glTextureParameterivEXT GLEW_GET_FUN(__glewTextureParameterivEXT) +#define glTextureRenderbufferEXT GLEW_GET_FUN(__glewTextureRenderbufferEXT) +#define glTextureSubImage1DEXT GLEW_GET_FUN(__glewTextureSubImage1DEXT) +#define glTextureSubImage2DEXT GLEW_GET_FUN(__glewTextureSubImage2DEXT) +#define glTextureSubImage3DEXT GLEW_GET_FUN(__glewTextureSubImage3DEXT) +#define glUnmapNamedBufferEXT GLEW_GET_FUN(__glewUnmapNamedBufferEXT) +#define glVertexArrayColorOffsetEXT GLEW_GET_FUN(__glewVertexArrayColorOffsetEXT) +#define glVertexArrayEdgeFlagOffsetEXT GLEW_GET_FUN(__glewVertexArrayEdgeFlagOffsetEXT) +#define glVertexArrayFogCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayFogCoordOffsetEXT) +#define glVertexArrayIndexOffsetEXT GLEW_GET_FUN(__glewVertexArrayIndexOffsetEXT) +#define glVertexArrayMultiTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayMultiTexCoordOffsetEXT) +#define glVertexArrayNormalOffsetEXT GLEW_GET_FUN(__glewVertexArrayNormalOffsetEXT) +#define glVertexArraySecondaryColorOffsetEXT GLEW_GET_FUN(__glewVertexArraySecondaryColorOffsetEXT) +#define glVertexArrayTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayTexCoordOffsetEXT) +#define glVertexArrayVertexAttribIOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribIOffsetEXT) +#define glVertexArrayVertexAttribOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribOffsetEXT) +#define glVertexArrayVertexOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexOffsetEXT) + +#define GLEW_EXT_direct_state_access GLEW_GET_VAR(__GLEW_EXT_direct_state_access) + +#endif /* GL_EXT_direct_state_access */ + +/* -------------------------- GL_EXT_draw_buffers2 ------------------------- */ + +#ifndef GL_EXT_draw_buffers2 +#define GL_EXT_draw_buffers2 1 + +typedef void (GLAPIENTRY * PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint buf, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (GLAPIENTRY * PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index); +typedef void (GLAPIENTRY * PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum value, GLuint index, GLboolean* data); +typedef void (GLAPIENTRY * PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum value, GLuint index, GLint* data); +typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index); + +#define glColorMaskIndexedEXT GLEW_GET_FUN(__glewColorMaskIndexedEXT) +#define glDisableIndexedEXT GLEW_GET_FUN(__glewDisableIndexedEXT) +#define glEnableIndexedEXT GLEW_GET_FUN(__glewEnableIndexedEXT) +#define glGetBooleanIndexedvEXT GLEW_GET_FUN(__glewGetBooleanIndexedvEXT) +#define glGetIntegerIndexedvEXT GLEW_GET_FUN(__glewGetIntegerIndexedvEXT) +#define glIsEnabledIndexedEXT GLEW_GET_FUN(__glewIsEnabledIndexedEXT) + +#define GLEW_EXT_draw_buffers2 GLEW_GET_VAR(__GLEW_EXT_draw_buffers2) + +#endif /* GL_EXT_draw_buffers2 */ + +/* ------------------------- GL_EXT_draw_instanced ------------------------- */ + +#ifndef GL_EXT_draw_instanced +#define GL_EXT_draw_instanced 1 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); + +#define glDrawArraysInstancedEXT GLEW_GET_FUN(__glewDrawArraysInstancedEXT) +#define glDrawElementsInstancedEXT GLEW_GET_FUN(__glewDrawElementsInstancedEXT) + +#define GLEW_EXT_draw_instanced GLEW_GET_VAR(__GLEW_EXT_draw_instanced) + +#endif /* GL_EXT_draw_instanced */ + +/* ----------------------- GL_EXT_draw_range_elements ---------------------- */ + +#ifndef GL_EXT_draw_range_elements +#define GL_EXT_draw_range_elements 1 + +#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 +#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 + +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); + +#define glDrawRangeElementsEXT GLEW_GET_FUN(__glewDrawRangeElementsEXT) + +#define GLEW_EXT_draw_range_elements GLEW_GET_VAR(__GLEW_EXT_draw_range_elements) + +#endif /* GL_EXT_draw_range_elements */ + +/* ---------------------------- GL_EXT_fog_coord --------------------------- */ + +#ifndef GL_EXT_fog_coord +#define GL_EXT_fog_coord 1 + +#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 +#define GL_FOG_COORDINATE_EXT 0x8451 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 +#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 +#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 + +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); + +#define glFogCoordPointerEXT GLEW_GET_FUN(__glewFogCoordPointerEXT) +#define glFogCoorddEXT GLEW_GET_FUN(__glewFogCoorddEXT) +#define glFogCoorddvEXT GLEW_GET_FUN(__glewFogCoorddvEXT) +#define glFogCoordfEXT GLEW_GET_FUN(__glewFogCoordfEXT) +#define glFogCoordfvEXT GLEW_GET_FUN(__glewFogCoordfvEXT) + +#define GLEW_EXT_fog_coord GLEW_GET_VAR(__GLEW_EXT_fog_coord) + +#endif /* GL_EXT_fog_coord */ + +/* ------------------------ GL_EXT_fragment_lighting ----------------------- */ + +#ifndef GL_EXT_fragment_lighting +#define GL_EXT_fragment_lighting 1 + +#define GL_FRAGMENT_LIGHTING_EXT 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_EXT 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_EXT 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_EXT 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_EXT 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_EXT 0x8405 +#define GL_CURRENT_RASTER_NORMAL_EXT 0x8406 +#define GL_LIGHT_ENV_MODE_EXT 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_EXT 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_EXT 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_EXT 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_EXT 0x840B +#define GL_FRAGMENT_LIGHT0_EXT 0x840C +#define GL_FRAGMENT_LIGHT7_EXT 0x8413 + +typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALEXTPROC) (GLenum face, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFEXTPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVEXTPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIEXTPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVEXTPROC) (GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFEXTPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIEXTPROC) (GLenum light, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFEXTPROC) (GLenum face, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIEXTPROC) (GLenum face, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVEXTPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVEXTPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVEXTPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVEXTPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLLIGHTENVIEXTPROC) (GLenum pname, GLint param); + +#define glFragmentColorMaterialEXT GLEW_GET_FUN(__glewFragmentColorMaterialEXT) +#define glFragmentLightModelfEXT GLEW_GET_FUN(__glewFragmentLightModelfEXT) +#define glFragmentLightModelfvEXT GLEW_GET_FUN(__glewFragmentLightModelfvEXT) +#define glFragmentLightModeliEXT GLEW_GET_FUN(__glewFragmentLightModeliEXT) +#define glFragmentLightModelivEXT GLEW_GET_FUN(__glewFragmentLightModelivEXT) +#define glFragmentLightfEXT GLEW_GET_FUN(__glewFragmentLightfEXT) +#define glFragmentLightfvEXT GLEW_GET_FUN(__glewFragmentLightfvEXT) +#define glFragmentLightiEXT GLEW_GET_FUN(__glewFragmentLightiEXT) +#define glFragmentLightivEXT GLEW_GET_FUN(__glewFragmentLightivEXT) +#define glFragmentMaterialfEXT GLEW_GET_FUN(__glewFragmentMaterialfEXT) +#define glFragmentMaterialfvEXT GLEW_GET_FUN(__glewFragmentMaterialfvEXT) +#define glFragmentMaterialiEXT GLEW_GET_FUN(__glewFragmentMaterialiEXT) +#define glFragmentMaterialivEXT GLEW_GET_FUN(__glewFragmentMaterialivEXT) +#define glGetFragmentLightfvEXT GLEW_GET_FUN(__glewGetFragmentLightfvEXT) +#define glGetFragmentLightivEXT GLEW_GET_FUN(__glewGetFragmentLightivEXT) +#define glGetFragmentMaterialfvEXT GLEW_GET_FUN(__glewGetFragmentMaterialfvEXT) +#define glGetFragmentMaterialivEXT GLEW_GET_FUN(__glewGetFragmentMaterialivEXT) +#define glLightEnviEXT GLEW_GET_FUN(__glewLightEnviEXT) + +#define GLEW_EXT_fragment_lighting GLEW_GET_VAR(__GLEW_EXT_fragment_lighting) + +#endif /* GL_EXT_fragment_lighting */ + +/* ------------------------ GL_EXT_framebuffer_blit ------------------------ */ + +#ifndef GL_EXT_framebuffer_blit +#define GL_EXT_framebuffer_blit 1 + +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA + +typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + +#define glBlitFramebufferEXT GLEW_GET_FUN(__glewBlitFramebufferEXT) + +#define GLEW_EXT_framebuffer_blit GLEW_GET_VAR(__GLEW_EXT_framebuffer_blit) + +#endif /* GL_EXT_framebuffer_blit */ + +/* --------------------- GL_EXT_framebuffer_multisample -------------------- */ + +#ifndef GL_EXT_framebuffer_multisample +#define GL_EXT_framebuffer_multisample 1 + +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 + +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glRenderbufferStorageMultisampleEXT GLEW_GET_FUN(__glewRenderbufferStorageMultisampleEXT) + +#define GLEW_EXT_framebuffer_multisample GLEW_GET_VAR(__GLEW_EXT_framebuffer_multisample) + +#endif /* GL_EXT_framebuffer_multisample */ + +/* ----------------------- GL_EXT_framebuffer_object ----------------------- */ + +#ifndef GL_EXT_framebuffer_object +#define GL_EXT_framebuffer_object 1 + +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 +#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 +#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 +#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 +#define GL_STENCIL_INDEX1_EXT 0x8D46 +#define GL_STENCIL_INDEX4_EXT 0x8D47 +#define GL_STENCIL_INDEX8_EXT 0x8D48 +#define GL_STENCIL_INDEX16_EXT 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 + +typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); +typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); +typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint* framebuffers); +typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint* renderbuffers); +typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer); +typedef GLboolean (GLAPIENTRY * PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer); +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + +#define glBindFramebufferEXT GLEW_GET_FUN(__glewBindFramebufferEXT) +#define glBindRenderbufferEXT GLEW_GET_FUN(__glewBindRenderbufferEXT) +#define glCheckFramebufferStatusEXT GLEW_GET_FUN(__glewCheckFramebufferStatusEXT) +#define glDeleteFramebuffersEXT GLEW_GET_FUN(__glewDeleteFramebuffersEXT) +#define glDeleteRenderbuffersEXT GLEW_GET_FUN(__glewDeleteRenderbuffersEXT) +#define glFramebufferRenderbufferEXT GLEW_GET_FUN(__glewFramebufferRenderbufferEXT) +#define glFramebufferTexture1DEXT GLEW_GET_FUN(__glewFramebufferTexture1DEXT) +#define glFramebufferTexture2DEXT GLEW_GET_FUN(__glewFramebufferTexture2DEXT) +#define glFramebufferTexture3DEXT GLEW_GET_FUN(__glewFramebufferTexture3DEXT) +#define glGenFramebuffersEXT GLEW_GET_FUN(__glewGenFramebuffersEXT) +#define glGenRenderbuffersEXT GLEW_GET_FUN(__glewGenRenderbuffersEXT) +#define glGenerateMipmapEXT GLEW_GET_FUN(__glewGenerateMipmapEXT) +#define glGetFramebufferAttachmentParameterivEXT GLEW_GET_FUN(__glewGetFramebufferAttachmentParameterivEXT) +#define glGetRenderbufferParameterivEXT GLEW_GET_FUN(__glewGetRenderbufferParameterivEXT) +#define glIsFramebufferEXT GLEW_GET_FUN(__glewIsFramebufferEXT) +#define glIsRenderbufferEXT GLEW_GET_FUN(__glewIsRenderbufferEXT) +#define glRenderbufferStorageEXT GLEW_GET_FUN(__glewRenderbufferStorageEXT) + +#define GLEW_EXT_framebuffer_object GLEW_GET_VAR(__GLEW_EXT_framebuffer_object) + +#endif /* GL_EXT_framebuffer_object */ + +/* ------------------------ GL_EXT_framebuffer_sRGB ------------------------ */ + +#ifndef GL_EXT_framebuffer_sRGB +#define GL_EXT_framebuffer_sRGB 1 + +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 +#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA + +#define GLEW_EXT_framebuffer_sRGB GLEW_GET_VAR(__GLEW_EXT_framebuffer_sRGB) + +#endif /* GL_EXT_framebuffer_sRGB */ + +/* ------------------------ GL_EXT_geometry_shader4 ------------------------ */ + +#ifndef GL_EXT_geometry_shader4 +#define GL_EXT_geometry_shader4 1 + +#define GL_LINES_ADJACENCY_EXT 0xA +#define GL_LINE_STRIP_ADJACENCY_EXT 0xB +#define GL_TRIANGLES_ADJACENCY_EXT 0xC +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD +#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD +#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); + +#define glFramebufferTextureEXT GLEW_GET_FUN(__glewFramebufferTextureEXT) +#define glFramebufferTextureFaceEXT GLEW_GET_FUN(__glewFramebufferTextureFaceEXT) +#define glProgramParameteriEXT GLEW_GET_FUN(__glewProgramParameteriEXT) + +#define GLEW_EXT_geometry_shader4 GLEW_GET_VAR(__GLEW_EXT_geometry_shader4) + +#endif /* GL_EXT_geometry_shader4 */ + +/* --------------------- GL_EXT_gpu_program_parameters --------------------- */ + +#ifndef GL_EXT_gpu_program_parameters +#define GL_EXT_gpu_program_parameters 1 + +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat* params); + +#define glProgramEnvParameters4fvEXT GLEW_GET_FUN(__glewProgramEnvParameters4fvEXT) +#define glProgramLocalParameters4fvEXT GLEW_GET_FUN(__glewProgramLocalParameters4fvEXT) + +#define GLEW_EXT_gpu_program_parameters GLEW_GET_VAR(__GLEW_EXT_gpu_program_parameters) + +#endif /* GL_EXT_gpu_program_parameters */ + +/* --------------------------- GL_EXT_gpu_shader4 -------------------------- */ + +#ifndef GL_EXT_gpu_shader4 +#define GL_EXT_gpu_shader4 1 + +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD +#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 +#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 +#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 +#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 +#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 +#define GL_INT_SAMPLER_1D_EXT 0x8DC9 +#define GL_INT_SAMPLER_2D_EXT 0x8DCA +#define GL_INT_SAMPLER_3D_EXT 0x8DCB +#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC +#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD +#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 + +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + +#define glBindFragDataLocationEXT GLEW_GET_FUN(__glewBindFragDataLocationEXT) +#define glGetFragDataLocationEXT GLEW_GET_FUN(__glewGetFragDataLocationEXT) +#define glGetUniformuivEXT GLEW_GET_FUN(__glewGetUniformuivEXT) +#define glGetVertexAttribIivEXT GLEW_GET_FUN(__glewGetVertexAttribIivEXT) +#define glGetVertexAttribIuivEXT GLEW_GET_FUN(__glewGetVertexAttribIuivEXT) +#define glUniform1uiEXT GLEW_GET_FUN(__glewUniform1uiEXT) +#define glUniform1uivEXT GLEW_GET_FUN(__glewUniform1uivEXT) +#define glUniform2uiEXT GLEW_GET_FUN(__glewUniform2uiEXT) +#define glUniform2uivEXT GLEW_GET_FUN(__glewUniform2uivEXT) +#define glUniform3uiEXT GLEW_GET_FUN(__glewUniform3uiEXT) +#define glUniform3uivEXT GLEW_GET_FUN(__glewUniform3uivEXT) +#define glUniform4uiEXT GLEW_GET_FUN(__glewUniform4uiEXT) +#define glUniform4uivEXT GLEW_GET_FUN(__glewUniform4uivEXT) +#define glVertexAttribI1iEXT GLEW_GET_FUN(__glewVertexAttribI1iEXT) +#define glVertexAttribI1ivEXT GLEW_GET_FUN(__glewVertexAttribI1ivEXT) +#define glVertexAttribI1uiEXT GLEW_GET_FUN(__glewVertexAttribI1uiEXT) +#define glVertexAttribI1uivEXT GLEW_GET_FUN(__glewVertexAttribI1uivEXT) +#define glVertexAttribI2iEXT GLEW_GET_FUN(__glewVertexAttribI2iEXT) +#define glVertexAttribI2ivEXT GLEW_GET_FUN(__glewVertexAttribI2ivEXT) +#define glVertexAttribI2uiEXT GLEW_GET_FUN(__glewVertexAttribI2uiEXT) +#define glVertexAttribI2uivEXT GLEW_GET_FUN(__glewVertexAttribI2uivEXT) +#define glVertexAttribI3iEXT GLEW_GET_FUN(__glewVertexAttribI3iEXT) +#define glVertexAttribI3ivEXT GLEW_GET_FUN(__glewVertexAttribI3ivEXT) +#define glVertexAttribI3uiEXT GLEW_GET_FUN(__glewVertexAttribI3uiEXT) +#define glVertexAttribI3uivEXT GLEW_GET_FUN(__glewVertexAttribI3uivEXT) +#define glVertexAttribI4bvEXT GLEW_GET_FUN(__glewVertexAttribI4bvEXT) +#define glVertexAttribI4iEXT GLEW_GET_FUN(__glewVertexAttribI4iEXT) +#define glVertexAttribI4ivEXT GLEW_GET_FUN(__glewVertexAttribI4ivEXT) +#define glVertexAttribI4svEXT GLEW_GET_FUN(__glewVertexAttribI4svEXT) +#define glVertexAttribI4ubvEXT GLEW_GET_FUN(__glewVertexAttribI4ubvEXT) +#define glVertexAttribI4uiEXT GLEW_GET_FUN(__glewVertexAttribI4uiEXT) +#define glVertexAttribI4uivEXT GLEW_GET_FUN(__glewVertexAttribI4uivEXT) +#define glVertexAttribI4usvEXT GLEW_GET_FUN(__glewVertexAttribI4usvEXT) +#define glVertexAttribIPointerEXT GLEW_GET_FUN(__glewVertexAttribIPointerEXT) + +#define GLEW_EXT_gpu_shader4 GLEW_GET_VAR(__GLEW_EXT_gpu_shader4) + +#endif /* GL_EXT_gpu_shader4 */ + +/* ---------------------------- GL_EXT_histogram --------------------------- */ + +#ifndef GL_EXT_histogram +#define GL_EXT_histogram 1 + +#define GL_HISTOGRAM_EXT 0x8024 +#define GL_PROXY_HISTOGRAM_EXT 0x8025 +#define GL_HISTOGRAM_WIDTH_EXT 0x8026 +#define GL_HISTOGRAM_FORMAT_EXT 0x8027 +#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C +#define GL_HISTOGRAM_SINK_EXT 0x802D +#define GL_MINMAX_EXT 0x802E +#define GL_MINMAX_FORMAT_EXT 0x802F +#define GL_MINMAX_SINK_EXT 0x8030 + +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLRESETMINMAXEXTPROC) (GLenum target); + +#define glGetHistogramEXT GLEW_GET_FUN(__glewGetHistogramEXT) +#define glGetHistogramParameterfvEXT GLEW_GET_FUN(__glewGetHistogramParameterfvEXT) +#define glGetHistogramParameterivEXT GLEW_GET_FUN(__glewGetHistogramParameterivEXT) +#define glGetMinmaxEXT GLEW_GET_FUN(__glewGetMinmaxEXT) +#define glGetMinmaxParameterfvEXT GLEW_GET_FUN(__glewGetMinmaxParameterfvEXT) +#define glGetMinmaxParameterivEXT GLEW_GET_FUN(__glewGetMinmaxParameterivEXT) +#define glHistogramEXT GLEW_GET_FUN(__glewHistogramEXT) +#define glMinmaxEXT GLEW_GET_FUN(__glewMinmaxEXT) +#define glResetHistogramEXT GLEW_GET_FUN(__glewResetHistogramEXT) +#define glResetMinmaxEXT GLEW_GET_FUN(__glewResetMinmaxEXT) + +#define GLEW_EXT_histogram GLEW_GET_VAR(__GLEW_EXT_histogram) + +#endif /* GL_EXT_histogram */ + +/* ----------------------- GL_EXT_index_array_formats ---------------------- */ + +#ifndef GL_EXT_index_array_formats +#define GL_EXT_index_array_formats 1 + +#define GLEW_EXT_index_array_formats GLEW_GET_VAR(__GLEW_EXT_index_array_formats) + +#endif /* GL_EXT_index_array_formats */ + +/* --------------------------- GL_EXT_index_func --------------------------- */ + +#ifndef GL_EXT_index_func +#define GL_EXT_index_func 1 + +typedef void (GLAPIENTRY * PFNGLINDEXFUNCEXTPROC) (GLenum func, GLfloat ref); + +#define glIndexFuncEXT GLEW_GET_FUN(__glewIndexFuncEXT) + +#define GLEW_EXT_index_func GLEW_GET_VAR(__GLEW_EXT_index_func) + +#endif /* GL_EXT_index_func */ + +/* ------------------------- GL_EXT_index_material ------------------------- */ + +#ifndef GL_EXT_index_material +#define GL_EXT_index_material 1 + +typedef void (GLAPIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); + +#define glIndexMaterialEXT GLEW_GET_FUN(__glewIndexMaterialEXT) + +#define GLEW_EXT_index_material GLEW_GET_VAR(__GLEW_EXT_index_material) + +#endif /* GL_EXT_index_material */ + +/* -------------------------- GL_EXT_index_texture ------------------------- */ + +#ifndef GL_EXT_index_texture +#define GL_EXT_index_texture 1 + +#define GLEW_EXT_index_texture GLEW_GET_VAR(__GLEW_EXT_index_texture) + +#endif /* GL_EXT_index_texture */ + +/* -------------------------- GL_EXT_light_texture ------------------------- */ + +#ifndef GL_EXT_light_texture +#define GL_EXT_light_texture 1 + +#define GL_FRAGMENT_MATERIAL_EXT 0x8349 +#define GL_FRAGMENT_NORMAL_EXT 0x834A +#define GL_FRAGMENT_COLOR_EXT 0x834C +#define GL_ATTENUATION_EXT 0x834D +#define GL_SHADOW_ATTENUATION_EXT 0x834E +#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F +#define GL_TEXTURE_LIGHT_EXT 0x8350 +#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 +#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 + +typedef void (GLAPIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); +typedef void (GLAPIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); +typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); + +#define glApplyTextureEXT GLEW_GET_FUN(__glewApplyTextureEXT) +#define glTextureLightEXT GLEW_GET_FUN(__glewTextureLightEXT) +#define glTextureMaterialEXT GLEW_GET_FUN(__glewTextureMaterialEXT) + +#define GLEW_EXT_light_texture GLEW_GET_VAR(__GLEW_EXT_light_texture) + +#endif /* GL_EXT_light_texture */ + +/* ------------------------- GL_EXT_misc_attribute ------------------------- */ + +#ifndef GL_EXT_misc_attribute +#define GL_EXT_misc_attribute 1 + +#define GLEW_EXT_misc_attribute GLEW_GET_VAR(__GLEW_EXT_misc_attribute) + +#endif /* GL_EXT_misc_attribute */ + +/* ------------------------ GL_EXT_multi_draw_arrays ----------------------- */ + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 + +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount); + +#define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT) +#define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT) + +#define GLEW_EXT_multi_draw_arrays GLEW_GET_VAR(__GLEW_EXT_multi_draw_arrays) + +#endif /* GL_EXT_multi_draw_arrays */ + +/* --------------------------- GL_EXT_multisample -------------------------- */ + +#ifndef GL_EXT_multisample +#define GL_EXT_multisample 1 + +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#define GL_SAMPLE_MASK_EXT 0x80A0 +#define GL_1PASS_EXT 0x80A1 +#define GL_2PASS_0_EXT 0x80A2 +#define GL_2PASS_1_EXT 0x80A3 +#define GL_4PASS_0_EXT 0x80A4 +#define GL_4PASS_1_EXT 0x80A5 +#define GL_4PASS_2_EXT 0x80A6 +#define GL_4PASS_3_EXT 0x80A7 +#define GL_SAMPLE_BUFFERS_EXT 0x80A8 +#define GL_SAMPLES_EXT 0x80A9 +#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA +#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB +#define GL_SAMPLE_PATTERN_EXT 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); + +#define glSampleMaskEXT GLEW_GET_FUN(__glewSampleMaskEXT) +#define glSamplePatternEXT GLEW_GET_FUN(__glewSamplePatternEXT) + +#define GLEW_EXT_multisample GLEW_GET_VAR(__GLEW_EXT_multisample) + +#endif /* GL_EXT_multisample */ + +/* ---------------------- GL_EXT_packed_depth_stencil ---------------------- */ + +#ifndef GL_EXT_packed_depth_stencil +#define GL_EXT_packed_depth_stencil 1 + +#define GL_DEPTH_STENCIL_EXT 0x84F9 +#define GL_UNSIGNED_INT_24_8_EXT 0x84FA +#define GL_DEPTH24_STENCIL8_EXT 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 + +#define GLEW_EXT_packed_depth_stencil GLEW_GET_VAR(__GLEW_EXT_packed_depth_stencil) + +#endif /* GL_EXT_packed_depth_stencil */ + +/* -------------------------- GL_EXT_packed_float -------------------------- */ + +#ifndef GL_EXT_packed_float +#define GL_EXT_packed_float 1 + +#define GL_R11F_G11F_B10F_EXT 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B +#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C + +#define GLEW_EXT_packed_float GLEW_GET_VAR(__GLEW_EXT_packed_float) + +#endif /* GL_EXT_packed_float */ + +/* -------------------------- GL_EXT_packed_pixels ------------------------- */ + +#ifndef GL_EXT_packed_pixels +#define GL_EXT_packed_pixels 1 + +#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 + +#define GLEW_EXT_packed_pixels GLEW_GET_VAR(__GLEW_EXT_packed_pixels) + +#endif /* GL_EXT_packed_pixels */ + +/* ------------------------ GL_EXT_paletted_texture ------------------------ */ + +#ifndef GL_EXT_paletted_texture +#define GL_EXT_paletted_texture 1 + +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8 +#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B + +typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void* data); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void* data); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); + +#define glColorTableEXT GLEW_GET_FUN(__glewColorTableEXT) +#define glGetColorTableEXT GLEW_GET_FUN(__glewGetColorTableEXT) +#define glGetColorTableParameterfvEXT GLEW_GET_FUN(__glewGetColorTableParameterfvEXT) +#define glGetColorTableParameterivEXT GLEW_GET_FUN(__glewGetColorTableParameterivEXT) + +#define GLEW_EXT_paletted_texture GLEW_GET_VAR(__GLEW_EXT_paletted_texture) + +#endif /* GL_EXT_paletted_texture */ + +/* ----------------------- GL_EXT_pixel_buffer_object ---------------------- */ + +#ifndef GL_EXT_pixel_buffer_object +#define GL_EXT_pixel_buffer_object 1 + +#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF + +#define GLEW_EXT_pixel_buffer_object GLEW_GET_VAR(__GLEW_EXT_pixel_buffer_object) + +#endif /* GL_EXT_pixel_buffer_object */ + +/* ------------------------- GL_EXT_pixel_transform ------------------------ */ + +#ifndef GL_EXT_pixel_transform +#define GL_EXT_pixel_transform 1 + +#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 +#define GL_PIXEL_MAG_FILTER_EXT 0x8331 +#define GL_PIXEL_MIN_FILTER_EXT 0x8332 +#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 +#define GL_CUBIC_EXT 0x8334 +#define GL_AVERAGE_EXT 0x8335 +#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 +#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 +#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 + +typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glGetPixelTransformParameterfvEXT GLEW_GET_FUN(__glewGetPixelTransformParameterfvEXT) +#define glGetPixelTransformParameterivEXT GLEW_GET_FUN(__glewGetPixelTransformParameterivEXT) +#define glPixelTransformParameterfEXT GLEW_GET_FUN(__glewPixelTransformParameterfEXT) +#define glPixelTransformParameterfvEXT GLEW_GET_FUN(__glewPixelTransformParameterfvEXT) +#define glPixelTransformParameteriEXT GLEW_GET_FUN(__glewPixelTransformParameteriEXT) +#define glPixelTransformParameterivEXT GLEW_GET_FUN(__glewPixelTransformParameterivEXT) + +#define GLEW_EXT_pixel_transform GLEW_GET_VAR(__GLEW_EXT_pixel_transform) + +#endif /* GL_EXT_pixel_transform */ + +/* ------------------- GL_EXT_pixel_transform_color_table ------------------ */ + +#ifndef GL_EXT_pixel_transform_color_table +#define GL_EXT_pixel_transform_color_table 1 + +#define GLEW_EXT_pixel_transform_color_table GLEW_GET_VAR(__GLEW_EXT_pixel_transform_color_table) + +#endif /* GL_EXT_pixel_transform_color_table */ + +/* ------------------------ GL_EXT_point_parameters ------------------------ */ + +#ifndef GL_EXT_point_parameters +#define GL_EXT_point_parameters 1 + +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat* params); + +#define glPointParameterfEXT GLEW_GET_FUN(__glewPointParameterfEXT) +#define glPointParameterfvEXT GLEW_GET_FUN(__glewPointParameterfvEXT) + +#define GLEW_EXT_point_parameters GLEW_GET_VAR(__GLEW_EXT_point_parameters) + +#endif /* GL_EXT_point_parameters */ + +/* ------------------------- GL_EXT_polygon_offset ------------------------- */ + +#ifndef GL_EXT_polygon_offset +#define GL_EXT_polygon_offset 1 + +#define GL_POLYGON_OFFSET_EXT 0x8037 +#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 +#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 + +typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); + +#define glPolygonOffsetEXT GLEW_GET_FUN(__glewPolygonOffsetEXT) + +#define GLEW_EXT_polygon_offset GLEW_GET_VAR(__GLEW_EXT_polygon_offset) + +#endif /* GL_EXT_polygon_offset */ + +/* ------------------------ GL_EXT_provoking_vertex ------------------------ */ + +#ifndef GL_EXT_provoking_vertex +#define GL_EXT_provoking_vertex 1 + +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D +#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E +#define GL_PROVOKING_VERTEX_EXT 0x8E4F + +typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode); + +#define glProvokingVertexEXT GLEW_GET_FUN(__glewProvokingVertexEXT) + +#define GLEW_EXT_provoking_vertex GLEW_GET_VAR(__GLEW_EXT_provoking_vertex) + +#endif /* GL_EXT_provoking_vertex */ + +/* ------------------------- GL_EXT_rescale_normal ------------------------- */ + +#ifndef GL_EXT_rescale_normal +#define GL_EXT_rescale_normal 1 + +#define GL_RESCALE_NORMAL_EXT 0x803A + +#define GLEW_EXT_rescale_normal GLEW_GET_VAR(__GLEW_EXT_rescale_normal) + +#endif /* GL_EXT_rescale_normal */ + +/* -------------------------- GL_EXT_scene_marker -------------------------- */ + +#ifndef GL_EXT_scene_marker +#define GL_EXT_scene_marker 1 + +typedef void (GLAPIENTRY * PFNGLBEGINSCENEEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLENDSCENEEXTPROC) (void); + +#define glBeginSceneEXT GLEW_GET_FUN(__glewBeginSceneEXT) +#define glEndSceneEXT GLEW_GET_FUN(__glewEndSceneEXT) + +#define GLEW_EXT_scene_marker GLEW_GET_VAR(__GLEW_EXT_scene_marker) + +#endif /* GL_EXT_scene_marker */ + +/* ------------------------- GL_EXT_secondary_color ------------------------ */ + +#ifndef GL_EXT_secondary_color +#define GL_EXT_secondary_color 1 + +#define GL_COLOR_SUM_EXT 0x8458 +#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D +#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E + +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + +#define glSecondaryColor3bEXT GLEW_GET_FUN(__glewSecondaryColor3bEXT) +#define glSecondaryColor3bvEXT GLEW_GET_FUN(__glewSecondaryColor3bvEXT) +#define glSecondaryColor3dEXT GLEW_GET_FUN(__glewSecondaryColor3dEXT) +#define glSecondaryColor3dvEXT GLEW_GET_FUN(__glewSecondaryColor3dvEXT) +#define glSecondaryColor3fEXT GLEW_GET_FUN(__glewSecondaryColor3fEXT) +#define glSecondaryColor3fvEXT GLEW_GET_FUN(__glewSecondaryColor3fvEXT) +#define glSecondaryColor3iEXT GLEW_GET_FUN(__glewSecondaryColor3iEXT) +#define glSecondaryColor3ivEXT GLEW_GET_FUN(__glewSecondaryColor3ivEXT) +#define glSecondaryColor3sEXT GLEW_GET_FUN(__glewSecondaryColor3sEXT) +#define glSecondaryColor3svEXT GLEW_GET_FUN(__glewSecondaryColor3svEXT) +#define glSecondaryColor3ubEXT GLEW_GET_FUN(__glewSecondaryColor3ubEXT) +#define glSecondaryColor3ubvEXT GLEW_GET_FUN(__glewSecondaryColor3ubvEXT) +#define glSecondaryColor3uiEXT GLEW_GET_FUN(__glewSecondaryColor3uiEXT) +#define glSecondaryColor3uivEXT GLEW_GET_FUN(__glewSecondaryColor3uivEXT) +#define glSecondaryColor3usEXT GLEW_GET_FUN(__glewSecondaryColor3usEXT) +#define glSecondaryColor3usvEXT GLEW_GET_FUN(__glewSecondaryColor3usvEXT) +#define glSecondaryColorPointerEXT GLEW_GET_FUN(__glewSecondaryColorPointerEXT) + +#define GLEW_EXT_secondary_color GLEW_GET_VAR(__GLEW_EXT_secondary_color) + +#endif /* GL_EXT_secondary_color */ + +/* --------------------- GL_EXT_separate_shader_objects -------------------- */ + +#ifndef GL_EXT_separate_shader_objects +#define GL_EXT_separate_shader_objects 1 + +#define GL_ACTIVE_PROGRAM_EXT 0x8B8D + +typedef void (GLAPIENTRY * PFNGLACTIVEPROGRAMEXTPROC) (GLuint program); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const char* string); +typedef void (GLAPIENTRY * PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program); + +#define glActiveProgramEXT GLEW_GET_FUN(__glewActiveProgramEXT) +#define glCreateShaderProgramEXT GLEW_GET_FUN(__glewCreateShaderProgramEXT) +#define glUseShaderProgramEXT GLEW_GET_FUN(__glewUseShaderProgramEXT) + +#define GLEW_EXT_separate_shader_objects GLEW_GET_VAR(__GLEW_EXT_separate_shader_objects) + +#endif /* GL_EXT_separate_shader_objects */ + +/* --------------------- GL_EXT_separate_specular_color -------------------- */ + +#ifndef GL_EXT_separate_specular_color +#define GL_EXT_separate_specular_color 1 + +#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 +#define GL_SINGLE_COLOR_EXT 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA + +#define GLEW_EXT_separate_specular_color GLEW_GET_VAR(__GLEW_EXT_separate_specular_color) + +#endif /* GL_EXT_separate_specular_color */ + +/* --------------------- GL_EXT_shader_image_load_store -------------------- */ + +#ifndef GL_EXT_shader_image_load_store +#define GL_EXT_shader_image_load_store 1 + +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020 +#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000 +#define GL_MAX_IMAGE_UNITS_EXT 0x8F38 +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39 +#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A +#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B +#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C +#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D +#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E +#define GL_IMAGE_1D_EXT 0x904C +#define GL_IMAGE_2D_EXT 0x904D +#define GL_IMAGE_3D_EXT 0x904E +#define GL_IMAGE_2D_RECT_EXT 0x904F +#define GL_IMAGE_CUBE_EXT 0x9050 +#define GL_IMAGE_BUFFER_EXT 0x9051 +#define GL_IMAGE_1D_ARRAY_EXT 0x9052 +#define GL_IMAGE_2D_ARRAY_EXT 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056 +#define GL_INT_IMAGE_1D_EXT 0x9057 +#define GL_INT_IMAGE_2D_EXT 0x9058 +#define GL_INT_IMAGE_3D_EXT 0x9059 +#define GL_INT_IMAGE_2D_RECT_EXT 0x905A +#define GL_INT_IMAGE_CUBE_EXT 0x905B +#define GL_INT_IMAGE_BUFFER_EXT 0x905C +#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D +#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C +#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D +#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E +#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format); +typedef void (GLAPIENTRY * PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers); + +#define glBindImageTextureEXT GLEW_GET_FUN(__glewBindImageTextureEXT) +#define glMemoryBarrierEXT GLEW_GET_FUN(__glewMemoryBarrierEXT) + +#define GLEW_EXT_shader_image_load_store GLEW_GET_VAR(__GLEW_EXT_shader_image_load_store) + +#endif /* GL_EXT_shader_image_load_store */ + +/* -------------------------- GL_EXT_shadow_funcs -------------------------- */ + +#ifndef GL_EXT_shadow_funcs +#define GL_EXT_shadow_funcs 1 + +#define GLEW_EXT_shadow_funcs GLEW_GET_VAR(__GLEW_EXT_shadow_funcs) + +#endif /* GL_EXT_shadow_funcs */ + +/* --------------------- GL_EXT_shared_texture_palette --------------------- */ + +#ifndef GL_EXT_shared_texture_palette +#define GL_EXT_shared_texture_palette 1 + +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB + +#define GLEW_EXT_shared_texture_palette GLEW_GET_VAR(__GLEW_EXT_shared_texture_palette) + +#endif /* GL_EXT_shared_texture_palette */ + +/* ------------------------ GL_EXT_stencil_clear_tag ----------------------- */ + +#ifndef GL_EXT_stencil_clear_tag +#define GL_EXT_stencil_clear_tag 1 + +#define GL_STENCIL_TAG_BITS_EXT 0x88F2 +#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3 + +#define GLEW_EXT_stencil_clear_tag GLEW_GET_VAR(__GLEW_EXT_stencil_clear_tag) + +#endif /* GL_EXT_stencil_clear_tag */ + +/* ------------------------ GL_EXT_stencil_two_side ------------------------ */ + +#ifndef GL_EXT_stencil_two_side +#define GL_EXT_stencil_two_side 1 + +#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 +#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 + +typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); + +#define glActiveStencilFaceEXT GLEW_GET_FUN(__glewActiveStencilFaceEXT) + +#define GLEW_EXT_stencil_two_side GLEW_GET_VAR(__GLEW_EXT_stencil_two_side) + +#endif /* GL_EXT_stencil_two_side */ + +/* -------------------------- GL_EXT_stencil_wrap -------------------------- */ + +#ifndef GL_EXT_stencil_wrap +#define GL_EXT_stencil_wrap 1 + +#define GL_INCR_WRAP_EXT 0x8507 +#define GL_DECR_WRAP_EXT 0x8508 + +#define GLEW_EXT_stencil_wrap GLEW_GET_VAR(__GLEW_EXT_stencil_wrap) + +#endif /* GL_EXT_stencil_wrap */ + +/* --------------------------- GL_EXT_subtexture --------------------------- */ + +#ifndef GL_EXT_subtexture +#define GL_EXT_subtexture 1 + +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); + +#define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT) +#define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT) +#define glTexSubImage3DEXT GLEW_GET_FUN(__glewTexSubImage3DEXT) + +#define GLEW_EXT_subtexture GLEW_GET_VAR(__GLEW_EXT_subtexture) + +#endif /* GL_EXT_subtexture */ + +/* ----------------------------- GL_EXT_texture ---------------------------- */ + +#ifndef GL_EXT_texture +#define GL_EXT_texture 1 + +#define GL_ALPHA4_EXT 0x803B +#define GL_ALPHA8_EXT 0x803C +#define GL_ALPHA12_EXT 0x803D +#define GL_ALPHA16_EXT 0x803E +#define GL_LUMINANCE4_EXT 0x803F +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE12_EXT 0x8041 +#define GL_LUMINANCE16_EXT 0x8042 +#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 +#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 +#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 +#define GL_INTENSITY_EXT 0x8049 +#define GL_INTENSITY4_EXT 0x804A +#define GL_INTENSITY8_EXT 0x804B +#define GL_INTENSITY12_EXT 0x804C +#define GL_INTENSITY16_EXT 0x804D +#define GL_RGB2_EXT 0x804E +#define GL_RGB4_EXT 0x804F +#define GL_RGB5_EXT 0x8050 +#define GL_RGB8_EXT 0x8051 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB12_EXT 0x8053 +#define GL_RGB16_EXT 0x8054 +#define GL_RGBA2_EXT 0x8055 +#define GL_RGBA4_EXT 0x8056 +#define GL_RGB5_A1_EXT 0x8057 +#define GL_RGBA8_EXT 0x8058 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA12_EXT 0x805A +#define GL_RGBA16_EXT 0x805B +#define GL_TEXTURE_RED_SIZE_EXT 0x805C +#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D +#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E +#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 +#define GL_REPLACE_EXT 0x8062 +#define GL_PROXY_TEXTURE_1D_EXT 0x8063 +#define GL_PROXY_TEXTURE_2D_EXT 0x8064 + +#define GLEW_EXT_texture GLEW_GET_VAR(__GLEW_EXT_texture) + +#endif /* GL_EXT_texture */ + +/* ---------------------------- GL_EXT_texture3D --------------------------- */ + +#ifndef GL_EXT_texture3D +#define GL_EXT_texture3D 1 + +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); + +#define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT) + +#define GLEW_EXT_texture3D GLEW_GET_VAR(__GLEW_EXT_texture3D) + +#endif /* GL_EXT_texture3D */ + +/* -------------------------- GL_EXT_texture_array ------------------------- */ + +#ifndef GL_EXT_texture_array +#define GL_EXT_texture_array 1 + +#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E +#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF +#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 +#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); + +#define glFramebufferTextureLayerEXT GLEW_GET_FUN(__glewFramebufferTextureLayerEXT) + +#define GLEW_EXT_texture_array GLEW_GET_VAR(__GLEW_EXT_texture_array) + +#endif /* GL_EXT_texture_array */ + +/* ---------------------- GL_EXT_texture_buffer_object --------------------- */ + +#ifndef GL_EXT_texture_buffer_object +#define GL_EXT_texture_buffer_object 1 + +#define GL_TEXTURE_BUFFER_EXT 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E + +typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); + +#define glTexBufferEXT GLEW_GET_FUN(__glewTexBufferEXT) + +#define GLEW_EXT_texture_buffer_object GLEW_GET_VAR(__GLEW_EXT_texture_buffer_object) + +#endif /* GL_EXT_texture_buffer_object */ + +/* -------------------- GL_EXT_texture_compression_dxt1 -------------------- */ + +#ifndef GL_EXT_texture_compression_dxt1 +#define GL_EXT_texture_compression_dxt1 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 + +#define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1) + +#endif /* GL_EXT_texture_compression_dxt1 */ + +/* -------------------- GL_EXT_texture_compression_latc -------------------- */ + +#ifndef GL_EXT_texture_compression_latc +#define GL_EXT_texture_compression_latc 1 + +#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 +#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 +#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 +#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 + +#define GLEW_EXT_texture_compression_latc GLEW_GET_VAR(__GLEW_EXT_texture_compression_latc) + +#endif /* GL_EXT_texture_compression_latc */ + +/* -------------------- GL_EXT_texture_compression_rgtc -------------------- */ + +#ifndef GL_EXT_texture_compression_rgtc +#define GL_EXT_texture_compression_rgtc 1 + +#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC +#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE + +#define GLEW_EXT_texture_compression_rgtc GLEW_GET_VAR(__GLEW_EXT_texture_compression_rgtc) + +#endif /* GL_EXT_texture_compression_rgtc */ + +/* -------------------- GL_EXT_texture_compression_s3tc -------------------- */ + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_EXT_texture_compression_s3tc 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 + +#define GLEW_EXT_texture_compression_s3tc GLEW_GET_VAR(__GLEW_EXT_texture_compression_s3tc) + +#endif /* GL_EXT_texture_compression_s3tc */ + +/* ------------------------ GL_EXT_texture_cube_map ------------------------ */ + +#ifndef GL_EXT_texture_cube_map +#define GL_EXT_texture_cube_map 1 + +#define GL_NORMAL_MAP_EXT 0x8511 +#define GL_REFLECTION_MAP_EXT 0x8512 +#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C + +#define GLEW_EXT_texture_cube_map GLEW_GET_VAR(__GLEW_EXT_texture_cube_map) + +#endif /* GL_EXT_texture_cube_map */ + +/* ----------------------- GL_EXT_texture_edge_clamp ----------------------- */ + +#ifndef GL_EXT_texture_edge_clamp +#define GL_EXT_texture_edge_clamp 1 + +#define GL_CLAMP_TO_EDGE_EXT 0x812F + +#define GLEW_EXT_texture_edge_clamp GLEW_GET_VAR(__GLEW_EXT_texture_edge_clamp) + +#endif /* GL_EXT_texture_edge_clamp */ + +/* --------------------------- GL_EXT_texture_env -------------------------- */ + +#ifndef GL_EXT_texture_env +#define GL_EXT_texture_env 1 + +#define GL_TEXTURE_ENV0_EXT 0 +#define GL_ENV_BLEND_EXT 0 +#define GL_TEXTURE_ENV_SHIFT_EXT 0 +#define GL_ENV_REPLACE_EXT 0 +#define GL_ENV_ADD_EXT 0 +#define GL_ENV_SUBTRACT_EXT 0 +#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0 +#define GL_ENV_REVERSE_SUBTRACT_EXT 0 +#define GL_ENV_REVERSE_BLEND_EXT 0 +#define GL_ENV_COPY_EXT 0 +#define GL_ENV_MODULATE_EXT 0 + +#define GLEW_EXT_texture_env GLEW_GET_VAR(__GLEW_EXT_texture_env) + +#endif /* GL_EXT_texture_env */ + +/* ------------------------- GL_EXT_texture_env_add ------------------------ */ + +#ifndef GL_EXT_texture_env_add +#define GL_EXT_texture_env_add 1 + +#define GLEW_EXT_texture_env_add GLEW_GET_VAR(__GLEW_EXT_texture_env_add) + +#endif /* GL_EXT_texture_env_add */ + +/* ----------------------- GL_EXT_texture_env_combine ---------------------- */ + +#ifndef GL_EXT_texture_env_combine +#define GL_EXT_texture_env_combine 1 + +#define GL_COMBINE_EXT 0x8570 +#define GL_COMBINE_RGB_EXT 0x8571 +#define GL_COMBINE_ALPHA_EXT 0x8572 +#define GL_RGB_SCALE_EXT 0x8573 +#define GL_ADD_SIGNED_EXT 0x8574 +#define GL_INTERPOLATE_EXT 0x8575 +#define GL_CONSTANT_EXT 0x8576 +#define GL_PRIMARY_COLOR_EXT 0x8577 +#define GL_PREVIOUS_EXT 0x8578 +#define GL_SOURCE0_RGB_EXT 0x8580 +#define GL_SOURCE1_RGB_EXT 0x8581 +#define GL_SOURCE2_RGB_EXT 0x8582 +#define GL_SOURCE0_ALPHA_EXT 0x8588 +#define GL_SOURCE1_ALPHA_EXT 0x8589 +#define GL_SOURCE2_ALPHA_EXT 0x858A +#define GL_OPERAND0_RGB_EXT 0x8590 +#define GL_OPERAND1_RGB_EXT 0x8591 +#define GL_OPERAND2_RGB_EXT 0x8592 +#define GL_OPERAND0_ALPHA_EXT 0x8598 +#define GL_OPERAND1_ALPHA_EXT 0x8599 +#define GL_OPERAND2_ALPHA_EXT 0x859A + +#define GLEW_EXT_texture_env_combine GLEW_GET_VAR(__GLEW_EXT_texture_env_combine) + +#endif /* GL_EXT_texture_env_combine */ + +/* ------------------------ GL_EXT_texture_env_dot3 ------------------------ */ + +#ifndef GL_EXT_texture_env_dot3 +#define GL_EXT_texture_env_dot3 1 + +#define GL_DOT3_RGB_EXT 0x8740 +#define GL_DOT3_RGBA_EXT 0x8741 + +#define GLEW_EXT_texture_env_dot3 GLEW_GET_VAR(__GLEW_EXT_texture_env_dot3) + +#endif /* GL_EXT_texture_env_dot3 */ + +/* ------------------- GL_EXT_texture_filter_anisotropic ------------------- */ + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 + +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF + +#define GLEW_EXT_texture_filter_anisotropic GLEW_GET_VAR(__GLEW_EXT_texture_filter_anisotropic) + +#endif /* GL_EXT_texture_filter_anisotropic */ + +/* ------------------------- GL_EXT_texture_integer ------------------------ */ + +#ifndef GL_EXT_texture_integer +#define GL_EXT_texture_integer 1 + +#define GL_RGBA32UI_EXT 0x8D70 +#define GL_RGB32UI_EXT 0x8D71 +#define GL_ALPHA32UI_EXT 0x8D72 +#define GL_INTENSITY32UI_EXT 0x8D73 +#define GL_LUMINANCE32UI_EXT 0x8D74 +#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 +#define GL_RGBA16UI_EXT 0x8D76 +#define GL_RGB16UI_EXT 0x8D77 +#define GL_ALPHA16UI_EXT 0x8D78 +#define GL_INTENSITY16UI_EXT 0x8D79 +#define GL_LUMINANCE16UI_EXT 0x8D7A +#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B +#define GL_RGBA8UI_EXT 0x8D7C +#define GL_RGB8UI_EXT 0x8D7D +#define GL_ALPHA8UI_EXT 0x8D7E +#define GL_INTENSITY8UI_EXT 0x8D7F +#define GL_LUMINANCE8UI_EXT 0x8D80 +#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 +#define GL_RGBA32I_EXT 0x8D82 +#define GL_RGB32I_EXT 0x8D83 +#define GL_ALPHA32I_EXT 0x8D84 +#define GL_INTENSITY32I_EXT 0x8D85 +#define GL_LUMINANCE32I_EXT 0x8D86 +#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 +#define GL_RGBA16I_EXT 0x8D88 +#define GL_RGB16I_EXT 0x8D89 +#define GL_ALPHA16I_EXT 0x8D8A +#define GL_INTENSITY16I_EXT 0x8D8B +#define GL_LUMINANCE16I_EXT 0x8D8C +#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D +#define GL_RGBA8I_EXT 0x8D8E +#define GL_RGB8I_EXT 0x8D8F +#define GL_ALPHA8I_EXT 0x8D90 +#define GL_INTENSITY8I_EXT 0x8D91 +#define GL_LUMINANCE8I_EXT 0x8D92 +#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 +#define GL_RED_INTEGER_EXT 0x8D94 +#define GL_GREEN_INTEGER_EXT 0x8D95 +#define GL_BLUE_INTEGER_EXT 0x8D96 +#define GL_ALPHA_INTEGER_EXT 0x8D97 +#define GL_RGB_INTEGER_EXT 0x8D98 +#define GL_RGBA_INTEGER_EXT 0x8D99 +#define GL_BGR_INTEGER_EXT 0x8D9A +#define GL_BGRA_INTEGER_EXT 0x8D9B +#define GL_LUMINANCE_INTEGER_EXT 0x8D9C +#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D +#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E + +typedef void (GLAPIENTRY * PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha); +typedef void (GLAPIENTRY * PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); + +#define glClearColorIiEXT GLEW_GET_FUN(__glewClearColorIiEXT) +#define glClearColorIuiEXT GLEW_GET_FUN(__glewClearColorIuiEXT) +#define glGetTexParameterIivEXT GLEW_GET_FUN(__glewGetTexParameterIivEXT) +#define glGetTexParameterIuivEXT GLEW_GET_FUN(__glewGetTexParameterIuivEXT) +#define glTexParameterIivEXT GLEW_GET_FUN(__glewTexParameterIivEXT) +#define glTexParameterIuivEXT GLEW_GET_FUN(__glewTexParameterIuivEXT) + +#define GLEW_EXT_texture_integer GLEW_GET_VAR(__GLEW_EXT_texture_integer) + +#endif /* GL_EXT_texture_integer */ + +/* ------------------------ GL_EXT_texture_lod_bias ------------------------ */ + +#ifndef GL_EXT_texture_lod_bias +#define GL_EXT_texture_lod_bias 1 + +#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD +#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 +#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 + +#define GLEW_EXT_texture_lod_bias GLEW_GET_VAR(__GLEW_EXT_texture_lod_bias) + +#endif /* GL_EXT_texture_lod_bias */ + +/* ---------------------- GL_EXT_texture_mirror_clamp ---------------------- */ + +#ifndef GL_EXT_texture_mirror_clamp +#define GL_EXT_texture_mirror_clamp 1 + +#define GL_MIRROR_CLAMP_EXT 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 +#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 + +#define GLEW_EXT_texture_mirror_clamp GLEW_GET_VAR(__GLEW_EXT_texture_mirror_clamp) + +#endif /* GL_EXT_texture_mirror_clamp */ + +/* ------------------------- GL_EXT_texture_object ------------------------- */ + +#ifndef GL_EXT_texture_object +#define GL_EXT_texture_object 1 + +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_3D_BINDING_EXT 0x806A + +typedef GLboolean (GLAPIENTRY * PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint* textures, GLboolean* residences); +typedef void (GLAPIENTRY * PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); +typedef void (GLAPIENTRY * PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint* textures); +typedef void (GLAPIENTRY * PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint* textures); +typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREEXTPROC) (GLuint texture); +typedef void (GLAPIENTRY * PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint* textures, const GLclampf* priorities); + +#define glAreTexturesResidentEXT GLEW_GET_FUN(__glewAreTexturesResidentEXT) +#define glBindTextureEXT GLEW_GET_FUN(__glewBindTextureEXT) +#define glDeleteTexturesEXT GLEW_GET_FUN(__glewDeleteTexturesEXT) +#define glGenTexturesEXT GLEW_GET_FUN(__glewGenTexturesEXT) +#define glIsTextureEXT GLEW_GET_FUN(__glewIsTextureEXT) +#define glPrioritizeTexturesEXT GLEW_GET_FUN(__glewPrioritizeTexturesEXT) + +#define GLEW_EXT_texture_object GLEW_GET_VAR(__GLEW_EXT_texture_object) + +#endif /* GL_EXT_texture_object */ + +/* --------------------- GL_EXT_texture_perturb_normal --------------------- */ + +#ifndef GL_EXT_texture_perturb_normal +#define GL_EXT_texture_perturb_normal 1 + +#define GL_PERTURB_EXT 0x85AE +#define GL_TEXTURE_NORMAL_EXT 0x85AF + +typedef void (GLAPIENTRY * PFNGLTEXTURENORMALEXTPROC) (GLenum mode); + +#define glTextureNormalEXT GLEW_GET_FUN(__glewTextureNormalEXT) + +#define GLEW_EXT_texture_perturb_normal GLEW_GET_VAR(__GLEW_EXT_texture_perturb_normal) + +#endif /* GL_EXT_texture_perturb_normal */ + +/* ------------------------ GL_EXT_texture_rectangle ----------------------- */ + +#ifndef GL_EXT_texture_rectangle +#define GL_EXT_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_EXT 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_EXT 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_EXT 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT 0x84F8 + +#define GLEW_EXT_texture_rectangle GLEW_GET_VAR(__GLEW_EXT_texture_rectangle) + +#endif /* GL_EXT_texture_rectangle */ + +/* -------------------------- GL_EXT_texture_sRGB -------------------------- */ + +#ifndef GL_EXT_texture_sRGB +#define GL_EXT_texture_sRGB 1 + +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB8_EXT 0x8C41 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 +#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 +#define GL_SLUMINANCE_EXT 0x8C46 +#define GL_SLUMINANCE8_EXT 0x8C47 +#define GL_COMPRESSED_SRGB_EXT 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 +#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B +#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F + +#define GLEW_EXT_texture_sRGB GLEW_GET_VAR(__GLEW_EXT_texture_sRGB) + +#endif /* GL_EXT_texture_sRGB */ + +/* ----------------------- GL_EXT_texture_sRGB_decode ---------------------- */ + +#ifndef GL_EXT_texture_sRGB_decode +#define GL_EXT_texture_sRGB_decode 1 + +#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 +#define GL_DECODE_EXT 0x8A49 +#define GL_SKIP_DECODE_EXT 0x8A4A + +#define GLEW_EXT_texture_sRGB_decode GLEW_GET_VAR(__GLEW_EXT_texture_sRGB_decode) + +#endif /* GL_EXT_texture_sRGB_decode */ + +/* --------------------- GL_EXT_texture_shared_exponent -------------------- */ + +#ifndef GL_EXT_texture_shared_exponent +#define GL_EXT_texture_shared_exponent 1 + +#define GL_RGB9_E5_EXT 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E +#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F + +#define GLEW_EXT_texture_shared_exponent GLEW_GET_VAR(__GLEW_EXT_texture_shared_exponent) + +#endif /* GL_EXT_texture_shared_exponent */ + +/* -------------------------- GL_EXT_texture_snorm ------------------------- */ + +#ifndef GL_EXT_texture_snorm +#define GL_EXT_texture_snorm 1 + +#define GL_RED_SNORM 0x8F90 +#define GL_RG_SNORM 0x8F91 +#define GL_RGB_SNORM 0x8F92 +#define GL_RGBA_SNORM 0x8F93 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_ALPHA_SNORM 0x9010 +#define GL_LUMINANCE_SNORM 0x9011 +#define GL_LUMINANCE_ALPHA_SNORM 0x9012 +#define GL_INTENSITY_SNORM 0x9013 +#define GL_ALPHA8_SNORM 0x9014 +#define GL_LUMINANCE8_SNORM 0x9015 +#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016 +#define GL_INTENSITY8_SNORM 0x9017 +#define GL_ALPHA16_SNORM 0x9018 +#define GL_LUMINANCE16_SNORM 0x9019 +#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A +#define GL_INTENSITY16_SNORM 0x901B + +#define GLEW_EXT_texture_snorm GLEW_GET_VAR(__GLEW_EXT_texture_snorm) + +#endif /* GL_EXT_texture_snorm */ + +/* ------------------------- GL_EXT_texture_swizzle ------------------------ */ + +#ifndef GL_EXT_texture_swizzle +#define GL_EXT_texture_swizzle 1 + +#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42 +#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43 +#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44 +#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46 + +#define GLEW_EXT_texture_swizzle GLEW_GET_VAR(__GLEW_EXT_texture_swizzle) + +#endif /* GL_EXT_texture_swizzle */ + +/* --------------------------- GL_EXT_timer_query -------------------------- */ + +#ifndef GL_EXT_timer_query +#define GL_EXT_timer_query 1 + +#define GL_TIME_ELAPSED_EXT 0x88BF + +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64EXT *params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64EXT *params); + +#define glGetQueryObjecti64vEXT GLEW_GET_FUN(__glewGetQueryObjecti64vEXT) +#define glGetQueryObjectui64vEXT GLEW_GET_FUN(__glewGetQueryObjectui64vEXT) + +#define GLEW_EXT_timer_query GLEW_GET_VAR(__GLEW_EXT_timer_query) + +#endif /* GL_EXT_timer_query */ + +/* ----------------------- GL_EXT_transform_feedback ----------------------- */ + +#ifndef GL_EXT_transform_feedback +#define GL_EXT_transform_feedback 1 + +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 +#define GL_RASTERIZER_DISCARD_EXT 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C +#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F + +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, char *name); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode); + +#define glBeginTransformFeedbackEXT GLEW_GET_FUN(__glewBeginTransformFeedbackEXT) +#define glBindBufferBaseEXT GLEW_GET_FUN(__glewBindBufferBaseEXT) +#define glBindBufferOffsetEXT GLEW_GET_FUN(__glewBindBufferOffsetEXT) +#define glBindBufferRangeEXT GLEW_GET_FUN(__glewBindBufferRangeEXT) +#define glEndTransformFeedbackEXT GLEW_GET_FUN(__glewEndTransformFeedbackEXT) +#define glGetTransformFeedbackVaryingEXT GLEW_GET_FUN(__glewGetTransformFeedbackVaryingEXT) +#define glTransformFeedbackVaryingsEXT GLEW_GET_FUN(__glewTransformFeedbackVaryingsEXT) + +#define GLEW_EXT_transform_feedback GLEW_GET_VAR(__GLEW_EXT_transform_feedback) + +#endif /* GL_EXT_transform_feedback */ + +/* -------------------------- GL_EXT_vertex_array -------------------------- */ + +#ifndef GL_EXT_vertex_array +#define GL_EXT_vertex_array 1 + +#define GL_DOUBLE_EXT 0x140A +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 + +typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i); +typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); + +#define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT) +#define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT) +#define glDrawArraysEXT GLEW_GET_FUN(__glewDrawArraysEXT) +#define glEdgeFlagPointerEXT GLEW_GET_FUN(__glewEdgeFlagPointerEXT) +#define glIndexPointerEXT GLEW_GET_FUN(__glewIndexPointerEXT) +#define glNormalPointerEXT GLEW_GET_FUN(__glewNormalPointerEXT) +#define glTexCoordPointerEXT GLEW_GET_FUN(__glewTexCoordPointerEXT) +#define glVertexPointerEXT GLEW_GET_FUN(__glewVertexPointerEXT) + +#define GLEW_EXT_vertex_array GLEW_GET_VAR(__GLEW_EXT_vertex_array) + +#endif /* GL_EXT_vertex_array */ + +/* ------------------------ GL_EXT_vertex_array_bgra ----------------------- */ + +#ifndef GL_EXT_vertex_array_bgra +#define GL_EXT_vertex_array_bgra 1 + +#define GL_BGRA 0x80E1 + +#define GLEW_EXT_vertex_array_bgra GLEW_GET_VAR(__GLEW_EXT_vertex_array_bgra) + +#endif /* GL_EXT_vertex_array_bgra */ + +/* ----------------------- GL_EXT_vertex_attrib_64bit ---------------------- */ + +#ifndef GL_EXT_vertex_attrib_64bit +#define GL_EXT_vertex_attrib_64bit 1 + +#define GL_DOUBLE_MAT2_EXT 0x8F46 +#define GL_DOUBLE_MAT3_EXT 0x8F47 +#define GL_DOUBLE_MAT4_EXT 0x8F48 +#define GL_DOUBLE_MAT2x3_EXT 0x8F49 +#define GL_DOUBLE_MAT2x4_EXT 0x8F4A +#define GL_DOUBLE_MAT3x2_EXT 0x8F4B +#define GL_DOUBLE_MAT3x4_EXT 0x8F4C +#define GL_DOUBLE_MAT4x2_EXT 0x8F4D +#define GL_DOUBLE_MAT4x3_EXT 0x8F4E +#define GL_DOUBLE_VEC2_EXT 0x8FFC +#define GL_DOUBLE_VEC3_EXT 0x8FFD +#define GL_DOUBLE_VEC4_EXT 0x8FFE + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); + +#define glGetVertexAttribLdvEXT GLEW_GET_FUN(__glewGetVertexAttribLdvEXT) +#define glVertexArrayVertexAttribLOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribLOffsetEXT) +#define glVertexAttribL1dEXT GLEW_GET_FUN(__glewVertexAttribL1dEXT) +#define glVertexAttribL1dvEXT GLEW_GET_FUN(__glewVertexAttribL1dvEXT) +#define glVertexAttribL2dEXT GLEW_GET_FUN(__glewVertexAttribL2dEXT) +#define glVertexAttribL2dvEXT GLEW_GET_FUN(__glewVertexAttribL2dvEXT) +#define glVertexAttribL3dEXT GLEW_GET_FUN(__glewVertexAttribL3dEXT) +#define glVertexAttribL3dvEXT GLEW_GET_FUN(__glewVertexAttribL3dvEXT) +#define glVertexAttribL4dEXT GLEW_GET_FUN(__glewVertexAttribL4dEXT) +#define glVertexAttribL4dvEXT GLEW_GET_FUN(__glewVertexAttribL4dvEXT) +#define glVertexAttribLPointerEXT GLEW_GET_FUN(__glewVertexAttribLPointerEXT) + +#define GLEW_EXT_vertex_attrib_64bit GLEW_GET_VAR(__GLEW_EXT_vertex_attrib_64bit) + +#endif /* GL_EXT_vertex_attrib_64bit */ + +/* -------------------------- GL_EXT_vertex_shader ------------------------- */ + +#ifndef GL_EXT_vertex_shader +#define GL_EXT_vertex_shader 1 + +#define GL_VERTEX_SHADER_EXT 0x8780 +#define GL_VERTEX_SHADER_BINDING_EXT 0x8781 +#define GL_OP_INDEX_EXT 0x8782 +#define GL_OP_NEGATE_EXT 0x8783 +#define GL_OP_DOT3_EXT 0x8784 +#define GL_OP_DOT4_EXT 0x8785 +#define GL_OP_MUL_EXT 0x8786 +#define GL_OP_ADD_EXT 0x8787 +#define GL_OP_MADD_EXT 0x8788 +#define GL_OP_FRAC_EXT 0x8789 +#define GL_OP_MAX_EXT 0x878A +#define GL_OP_MIN_EXT 0x878B +#define GL_OP_SET_GE_EXT 0x878C +#define GL_OP_SET_LT_EXT 0x878D +#define GL_OP_CLAMP_EXT 0x878E +#define GL_OP_FLOOR_EXT 0x878F +#define GL_OP_ROUND_EXT 0x8790 +#define GL_OP_EXP_BASE_2_EXT 0x8791 +#define GL_OP_LOG_BASE_2_EXT 0x8792 +#define GL_OP_POWER_EXT 0x8793 +#define GL_OP_RECIP_EXT 0x8794 +#define GL_OP_RECIP_SQRT_EXT 0x8795 +#define GL_OP_SUB_EXT 0x8796 +#define GL_OP_CROSS_PRODUCT_EXT 0x8797 +#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 +#define GL_OP_MOV_EXT 0x8799 +#define GL_OUTPUT_VERTEX_EXT 0x879A +#define GL_OUTPUT_COLOR0_EXT 0x879B +#define GL_OUTPUT_COLOR1_EXT 0x879C +#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D +#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E +#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F +#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 +#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 +#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 +#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 +#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 +#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 +#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 +#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 +#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 +#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 +#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA +#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB +#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC +#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD +#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE +#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF +#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 +#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 +#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 +#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 +#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 +#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 +#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 +#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 +#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 +#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 +#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA +#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB +#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC +#define GL_OUTPUT_FOG_EXT 0x87BD +#define GL_SCALAR_EXT 0x87BE +#define GL_VECTOR_EXT 0x87BF +#define GL_MATRIX_EXT 0x87C0 +#define GL_VARIANT_EXT 0x87C1 +#define GL_INVARIANT_EXT 0x87C2 +#define GL_LOCAL_CONSTANT_EXT 0x87C3 +#define GL_LOCAL_EXT 0x87C4 +#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 +#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 +#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 +#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 +#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CC +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CD +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE +#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF +#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 +#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 +#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 +#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 +#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 +#define GL_X_EXT 0x87D5 +#define GL_Y_EXT 0x87D6 +#define GL_Z_EXT 0x87D7 +#define GL_W_EXT 0x87D8 +#define GL_NEGATIVE_X_EXT 0x87D9 +#define GL_NEGATIVE_Y_EXT 0x87DA +#define GL_NEGATIVE_Z_EXT 0x87DB +#define GL_NEGATIVE_W_EXT 0x87DC +#define GL_ZERO_EXT 0x87DD +#define GL_ONE_EXT 0x87DE +#define GL_NEGATIVE_ONE_EXT 0x87DF +#define GL_NORMALIZED_RANGE_EXT 0x87E0 +#define GL_FULL_RANGE_EXT 0x87E1 +#define GL_CURRENT_VERTEX_EXT 0x87E2 +#define GL_MVP_MATRIX_EXT 0x87E3 +#define GL_VARIANT_VALUE_EXT 0x87E4 +#define GL_VARIANT_DATATYPE_EXT 0x87E5 +#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 +#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 +#define GL_VARIANT_ARRAY_EXT 0x87E8 +#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 +#define GL_INVARIANT_VALUE_EXT 0x87EA +#define GL_INVARIANT_DATATYPE_EXT 0x87EB +#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC +#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED + +typedef void (GLAPIENTRY * PFNGLBEGINVERTEXSHADEREXTPROC) (void); +typedef GLuint (GLAPIENTRY * PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDPARAMETEREXTPROC) (GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); +typedef GLuint (GLAPIENTRY * PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); +typedef void (GLAPIENTRY * PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENDVERTEXSHADEREXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLuint (GLAPIENTRY * PFNGLGENSYMBOLSEXTPROC) (GLenum dataType, GLenum storageType, GLenum range, GLuint components); +typedef GLuint (GLAPIENTRY * PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid **data); +typedef void (GLAPIENTRY * PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLboolean (GLAPIENTRY * PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); +typedef void (GLAPIENTRY * PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); +typedef void (GLAPIENTRY * PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); +typedef void (GLAPIENTRY * PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); +typedef void (GLAPIENTRY * PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +typedef void (GLAPIENTRY * PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTBVEXTPROC) (GLuint id, GLbyte *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTDVEXTPROC) (GLuint id, GLdouble *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTFVEXTPROC) (GLuint id, GLfloat *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTIVEXTPROC) (GLuint id, GLint *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTSVEXTPROC) (GLuint id, GLshort *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUBVEXTPROC) (GLuint id, GLubyte *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUIVEXTPROC) (GLuint id, GLuint *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTUSVEXTPROC) (GLuint id, GLushort *addr); +typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + +#define glBeginVertexShaderEXT GLEW_GET_FUN(__glewBeginVertexShaderEXT) +#define glBindLightParameterEXT GLEW_GET_FUN(__glewBindLightParameterEXT) +#define glBindMaterialParameterEXT GLEW_GET_FUN(__glewBindMaterialParameterEXT) +#define glBindParameterEXT GLEW_GET_FUN(__glewBindParameterEXT) +#define glBindTexGenParameterEXT GLEW_GET_FUN(__glewBindTexGenParameterEXT) +#define glBindTextureUnitParameterEXT GLEW_GET_FUN(__glewBindTextureUnitParameterEXT) +#define glBindVertexShaderEXT GLEW_GET_FUN(__glewBindVertexShaderEXT) +#define glDeleteVertexShaderEXT GLEW_GET_FUN(__glewDeleteVertexShaderEXT) +#define glDisableVariantClientStateEXT GLEW_GET_FUN(__glewDisableVariantClientStateEXT) +#define glEnableVariantClientStateEXT GLEW_GET_FUN(__glewEnableVariantClientStateEXT) +#define glEndVertexShaderEXT GLEW_GET_FUN(__glewEndVertexShaderEXT) +#define glExtractComponentEXT GLEW_GET_FUN(__glewExtractComponentEXT) +#define glGenSymbolsEXT GLEW_GET_FUN(__glewGenSymbolsEXT) +#define glGenVertexShadersEXT GLEW_GET_FUN(__glewGenVertexShadersEXT) +#define glGetInvariantBooleanvEXT GLEW_GET_FUN(__glewGetInvariantBooleanvEXT) +#define glGetInvariantFloatvEXT GLEW_GET_FUN(__glewGetInvariantFloatvEXT) +#define glGetInvariantIntegervEXT GLEW_GET_FUN(__glewGetInvariantIntegervEXT) +#define glGetLocalConstantBooleanvEXT GLEW_GET_FUN(__glewGetLocalConstantBooleanvEXT) +#define glGetLocalConstantFloatvEXT GLEW_GET_FUN(__glewGetLocalConstantFloatvEXT) +#define glGetLocalConstantIntegervEXT GLEW_GET_FUN(__glewGetLocalConstantIntegervEXT) +#define glGetVariantBooleanvEXT GLEW_GET_FUN(__glewGetVariantBooleanvEXT) +#define glGetVariantFloatvEXT GLEW_GET_FUN(__glewGetVariantFloatvEXT) +#define glGetVariantIntegervEXT GLEW_GET_FUN(__glewGetVariantIntegervEXT) +#define glGetVariantPointervEXT GLEW_GET_FUN(__glewGetVariantPointervEXT) +#define glInsertComponentEXT GLEW_GET_FUN(__glewInsertComponentEXT) +#define glIsVariantEnabledEXT GLEW_GET_FUN(__glewIsVariantEnabledEXT) +#define glSetInvariantEXT GLEW_GET_FUN(__glewSetInvariantEXT) +#define glSetLocalConstantEXT GLEW_GET_FUN(__glewSetLocalConstantEXT) +#define glShaderOp1EXT GLEW_GET_FUN(__glewShaderOp1EXT) +#define glShaderOp2EXT GLEW_GET_FUN(__glewShaderOp2EXT) +#define glShaderOp3EXT GLEW_GET_FUN(__glewShaderOp3EXT) +#define glSwizzleEXT GLEW_GET_FUN(__glewSwizzleEXT) +#define glVariantPointerEXT GLEW_GET_FUN(__glewVariantPointerEXT) +#define glVariantbvEXT GLEW_GET_FUN(__glewVariantbvEXT) +#define glVariantdvEXT GLEW_GET_FUN(__glewVariantdvEXT) +#define glVariantfvEXT GLEW_GET_FUN(__glewVariantfvEXT) +#define glVariantivEXT GLEW_GET_FUN(__glewVariantivEXT) +#define glVariantsvEXT GLEW_GET_FUN(__glewVariantsvEXT) +#define glVariantubvEXT GLEW_GET_FUN(__glewVariantubvEXT) +#define glVariantuivEXT GLEW_GET_FUN(__glewVariantuivEXT) +#define glVariantusvEXT GLEW_GET_FUN(__glewVariantusvEXT) +#define glWriteMaskEXT GLEW_GET_FUN(__glewWriteMaskEXT) + +#define GLEW_EXT_vertex_shader GLEW_GET_VAR(__GLEW_EXT_vertex_shader) + +#endif /* GL_EXT_vertex_shader */ + +/* ------------------------ GL_EXT_vertex_weighting ------------------------ */ + +#ifndef GL_EXT_vertex_weighting +#define GL_EXT_vertex_weighting 1 + +#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3 +#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6 +#define GL_MODELVIEW0_EXT 0x1700 +#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 +#define GL_MODELVIEW1_MATRIX_EXT 0x8506 +#define GL_VERTEX_WEIGHTING_EXT 0x8509 +#define GL_MODELVIEW1_EXT 0x850A +#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B +#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C +#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D +#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E +#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F +#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 + +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight); + +#define glVertexWeightPointerEXT GLEW_GET_FUN(__glewVertexWeightPointerEXT) +#define glVertexWeightfEXT GLEW_GET_FUN(__glewVertexWeightfEXT) +#define glVertexWeightfvEXT GLEW_GET_FUN(__glewVertexWeightfvEXT) + +#define GLEW_EXT_vertex_weighting GLEW_GET_VAR(__GLEW_EXT_vertex_weighting) + +#endif /* GL_EXT_vertex_weighting */ + +/* ------------------------- GL_EXT_x11_sync_object ------------------------ */ + +#ifndef GL_EXT_x11_sync_object +#define GL_EXT_x11_sync_object 1 + +#define GL_SYNC_X11_FENCE_EXT 0x90E1 + +typedef GLsync (GLAPIENTRY * PFNGLIMPORTSYNCEXTPROC) (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags); + +#define glImportSyncEXT GLEW_GET_FUN(__glewImportSyncEXT) + +#define GLEW_EXT_x11_sync_object GLEW_GET_VAR(__GLEW_EXT_x11_sync_object) + +#endif /* GL_EXT_x11_sync_object */ + +/* ---------------------- GL_GREMEDY_frame_terminator ---------------------- */ + +#ifndef GL_GREMEDY_frame_terminator +#define GL_GREMEDY_frame_terminator 1 + +typedef void (GLAPIENTRY * PFNGLFRAMETERMINATORGREMEDYPROC) (void); + +#define glFrameTerminatorGREMEDY GLEW_GET_FUN(__glewFrameTerminatorGREMEDY) + +#define GLEW_GREMEDY_frame_terminator GLEW_GET_VAR(__GLEW_GREMEDY_frame_terminator) + +#endif /* GL_GREMEDY_frame_terminator */ + +/* ------------------------ GL_GREMEDY_string_marker ----------------------- */ + +#ifndef GL_GREMEDY_string_marker +#define GL_GREMEDY_string_marker 1 + +typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void* string); + +#define glStringMarkerGREMEDY GLEW_GET_FUN(__glewStringMarkerGREMEDY) + +#define GLEW_GREMEDY_string_marker GLEW_GET_VAR(__GLEW_GREMEDY_string_marker) + +#endif /* GL_GREMEDY_string_marker */ + +/* --------------------- GL_HP_convolution_border_modes -------------------- */ + +#ifndef GL_HP_convolution_border_modes +#define GL_HP_convolution_border_modes 1 + +#define GLEW_HP_convolution_border_modes GLEW_GET_VAR(__GLEW_HP_convolution_border_modes) + +#endif /* GL_HP_convolution_border_modes */ + +/* ------------------------- GL_HP_image_transform ------------------------- */ + +#ifndef GL_HP_image_transform +#define GL_HP_image_transform 1 + +typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glGetImageTransformParameterfvHP GLEW_GET_FUN(__glewGetImageTransformParameterfvHP) +#define glGetImageTransformParameterivHP GLEW_GET_FUN(__glewGetImageTransformParameterivHP) +#define glImageTransformParameterfHP GLEW_GET_FUN(__glewImageTransformParameterfHP) +#define glImageTransformParameterfvHP GLEW_GET_FUN(__glewImageTransformParameterfvHP) +#define glImageTransformParameteriHP GLEW_GET_FUN(__glewImageTransformParameteriHP) +#define glImageTransformParameterivHP GLEW_GET_FUN(__glewImageTransformParameterivHP) + +#define GLEW_HP_image_transform GLEW_GET_VAR(__GLEW_HP_image_transform) + +#endif /* GL_HP_image_transform */ + +/* -------------------------- GL_HP_occlusion_test ------------------------- */ + +#ifndef GL_HP_occlusion_test +#define GL_HP_occlusion_test 1 + +#define GL_OCCLUSION_TEST_HP 0x8165 +#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 + +#define GLEW_HP_occlusion_test GLEW_GET_VAR(__GLEW_HP_occlusion_test) + +#endif /* GL_HP_occlusion_test */ + +/* ------------------------- GL_HP_texture_lighting ------------------------ */ + +#ifndef GL_HP_texture_lighting +#define GL_HP_texture_lighting 1 + +#define GLEW_HP_texture_lighting GLEW_GET_VAR(__GLEW_HP_texture_lighting) + +#endif /* GL_HP_texture_lighting */ + +/* --------------------------- GL_IBM_cull_vertex -------------------------- */ + +#ifndef GL_IBM_cull_vertex +#define GL_IBM_cull_vertex 1 + +#define GL_CULL_VERTEX_IBM 103050 + +#define GLEW_IBM_cull_vertex GLEW_GET_VAR(__GLEW_IBM_cull_vertex) + +#endif /* GL_IBM_cull_vertex */ + +/* ---------------------- GL_IBM_multimode_draw_arrays --------------------- */ + +#ifndef GL_IBM_multimode_draw_arrays +#define GL_IBM_multimode_draw_arrays 1 + +typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum* mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); +typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, GLint modestride); + +#define glMultiModeDrawArraysIBM GLEW_GET_FUN(__glewMultiModeDrawArraysIBM) +#define glMultiModeDrawElementsIBM GLEW_GET_FUN(__glewMultiModeDrawElementsIBM) + +#define GLEW_IBM_multimode_draw_arrays GLEW_GET_VAR(__GLEW_IBM_multimode_draw_arrays) + +#endif /* GL_IBM_multimode_draw_arrays */ + +/* ------------------------- GL_IBM_rasterpos_clip ------------------------- */ + +#ifndef GL_IBM_rasterpos_clip +#define GL_IBM_rasterpos_clip 1 + +#define GL_RASTER_POSITION_UNCLIPPED_IBM 103010 + +#define GLEW_IBM_rasterpos_clip GLEW_GET_VAR(__GLEW_IBM_rasterpos_clip) + +#endif /* GL_IBM_rasterpos_clip */ + +/* --------------------------- GL_IBM_static_data -------------------------- */ + +#ifndef GL_IBM_static_data +#define GL_IBM_static_data 1 + +#define GL_ALL_STATIC_DATA_IBM 103060 +#define GL_STATIC_VERTEX_ARRAY_IBM 103061 + +#define GLEW_IBM_static_data GLEW_GET_VAR(__GLEW_IBM_static_data) + +#endif /* GL_IBM_static_data */ + +/* --------------------- GL_IBM_texture_mirrored_repeat -------------------- */ + +#ifndef GL_IBM_texture_mirrored_repeat +#define GL_IBM_texture_mirrored_repeat 1 + +#define GL_MIRRORED_REPEAT_IBM 0x8370 + +#define GLEW_IBM_texture_mirrored_repeat GLEW_GET_VAR(__GLEW_IBM_texture_mirrored_repeat) + +#endif /* GL_IBM_texture_mirrored_repeat */ + +/* ----------------------- GL_IBM_vertex_array_lists ----------------------- */ + +#ifndef GL_IBM_vertex_array_lists +#define GL_IBM_vertex_array_lists 1 + +#define GL_VERTEX_ARRAY_LIST_IBM 103070 +#define GL_NORMAL_ARRAY_LIST_IBM 103071 +#define GL_COLOR_ARRAY_LIST_IBM 103072 +#define GL_INDEX_ARRAY_LIST_IBM 103073 +#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 +#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 +#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 +#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 +#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 +#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 +#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 +#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 +#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 +#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 +#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 +#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 + +typedef void (GLAPIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); + +#define glColorPointerListIBM GLEW_GET_FUN(__glewColorPointerListIBM) +#define glEdgeFlagPointerListIBM GLEW_GET_FUN(__glewEdgeFlagPointerListIBM) +#define glFogCoordPointerListIBM GLEW_GET_FUN(__glewFogCoordPointerListIBM) +#define glIndexPointerListIBM GLEW_GET_FUN(__glewIndexPointerListIBM) +#define glNormalPointerListIBM GLEW_GET_FUN(__glewNormalPointerListIBM) +#define glSecondaryColorPointerListIBM GLEW_GET_FUN(__glewSecondaryColorPointerListIBM) +#define glTexCoordPointerListIBM GLEW_GET_FUN(__glewTexCoordPointerListIBM) +#define glVertexPointerListIBM GLEW_GET_FUN(__glewVertexPointerListIBM) + +#define GLEW_IBM_vertex_array_lists GLEW_GET_VAR(__GLEW_IBM_vertex_array_lists) + +#endif /* GL_IBM_vertex_array_lists */ + +/* -------------------------- GL_INGR_color_clamp -------------------------- */ + +#ifndef GL_INGR_color_clamp +#define GL_INGR_color_clamp 1 + +#define GL_RED_MIN_CLAMP_INGR 0x8560 +#define GL_GREEN_MIN_CLAMP_INGR 0x8561 +#define GL_BLUE_MIN_CLAMP_INGR 0x8562 +#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 +#define GL_RED_MAX_CLAMP_INGR 0x8564 +#define GL_GREEN_MAX_CLAMP_INGR 0x8565 +#define GL_BLUE_MAX_CLAMP_INGR 0x8566 +#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 + +#define GLEW_INGR_color_clamp GLEW_GET_VAR(__GLEW_INGR_color_clamp) + +#endif /* GL_INGR_color_clamp */ + +/* ------------------------- GL_INGR_interlace_read ------------------------ */ + +#ifndef GL_INGR_interlace_read +#define GL_INGR_interlace_read 1 + +#define GL_INTERLACE_READ_INGR 0x8568 + +#define GLEW_INGR_interlace_read GLEW_GET_VAR(__GLEW_INGR_interlace_read) + +#endif /* GL_INGR_interlace_read */ + +/* ------------------------ GL_INTEL_parallel_arrays ----------------------- */ + +#ifndef GL_INTEL_parallel_arrays +#define GL_INTEL_parallel_arrays 1 + +#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 +#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 +#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 +#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 +#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 + +typedef void (GLAPIENTRY * PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void** pointer); + +#define glColorPointervINTEL GLEW_GET_FUN(__glewColorPointervINTEL) +#define glNormalPointervINTEL GLEW_GET_FUN(__glewNormalPointervINTEL) +#define glTexCoordPointervINTEL GLEW_GET_FUN(__glewTexCoordPointervINTEL) +#define glVertexPointervINTEL GLEW_GET_FUN(__glewVertexPointervINTEL) + +#define GLEW_INTEL_parallel_arrays GLEW_GET_VAR(__GLEW_INTEL_parallel_arrays) + +#endif /* GL_INTEL_parallel_arrays */ + +/* ------------------------ GL_INTEL_texture_scissor ----------------------- */ + +#ifndef GL_INTEL_texture_scissor +#define GL_INTEL_texture_scissor 1 + +typedef void (GLAPIENTRY * PFNGLTEXSCISSORFUNCINTELPROC) (GLenum target, GLenum lfunc, GLenum hfunc); +typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tlow, GLclampf thigh); + +#define glTexScissorFuncINTEL GLEW_GET_FUN(__glewTexScissorFuncINTEL) +#define glTexScissorINTEL GLEW_GET_FUN(__glewTexScissorINTEL) + +#define GLEW_INTEL_texture_scissor GLEW_GET_VAR(__GLEW_INTEL_texture_scissor) + +#endif /* GL_INTEL_texture_scissor */ + +/* -------------------------- GL_KTX_buffer_region ------------------------- */ + +#ifndef GL_KTX_buffer_region +#define GL_KTX_buffer_region 1 + +#define GL_KTX_FRONT_REGION 0x0 +#define GL_KTX_BACK_REGION 0x1 +#define GL_KTX_Z_REGION 0x2 +#define GL_KTX_STENCIL_REGION 0x3 + +typedef GLuint (GLAPIENTRY * PFNGLBUFFERREGIONENABLEDEXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERREGIONEXTPROC) (GLenum region); +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height, GLint xDest, GLint yDest); +typedef GLuint (GLAPIENTRY * PFNGLNEWBUFFERREGIONEXTPROC) (GLenum region); +typedef void (GLAPIENTRY * PFNGLREADBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height); + +#define glBufferRegionEnabledEXT GLEW_GET_FUN(__glewBufferRegionEnabledEXT) +#define glDeleteBufferRegionEXT GLEW_GET_FUN(__glewDeleteBufferRegionEXT) +#define glDrawBufferRegionEXT GLEW_GET_FUN(__glewDrawBufferRegionEXT) +#define glNewBufferRegionEXT GLEW_GET_FUN(__glewNewBufferRegionEXT) +#define glReadBufferRegionEXT GLEW_GET_FUN(__glewReadBufferRegionEXT) + +#define GLEW_KTX_buffer_region GLEW_GET_VAR(__GLEW_KTX_buffer_region) + +#endif /* GL_KTX_buffer_region */ + +/* ------------------------- GL_MESAX_texture_stack ------------------------ */ + +#ifndef GL_MESAX_texture_stack +#define GL_MESAX_texture_stack 1 + +#define GL_TEXTURE_1D_STACK_MESAX 0x8759 +#define GL_TEXTURE_2D_STACK_MESAX 0x875A +#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B +#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C +#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D +#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E + +#define GLEW_MESAX_texture_stack GLEW_GET_VAR(__GLEW_MESAX_texture_stack) + +#endif /* GL_MESAX_texture_stack */ + +/* -------------------------- GL_MESA_pack_invert -------------------------- */ + +#ifndef GL_MESA_pack_invert +#define GL_MESA_pack_invert 1 + +#define GL_PACK_INVERT_MESA 0x8758 + +#define GLEW_MESA_pack_invert GLEW_GET_VAR(__GLEW_MESA_pack_invert) + +#endif /* GL_MESA_pack_invert */ + +/* ------------------------- GL_MESA_resize_buffers ------------------------ */ + +#ifndef GL_MESA_resize_buffers +#define GL_MESA_resize_buffers 1 + +typedef void (GLAPIENTRY * PFNGLRESIZEBUFFERSMESAPROC) (void); + +#define glResizeBuffersMESA GLEW_GET_FUN(__glewResizeBuffersMESA) + +#define GLEW_MESA_resize_buffers GLEW_GET_VAR(__GLEW_MESA_resize_buffers) + +#endif /* GL_MESA_resize_buffers */ + +/* --------------------------- GL_MESA_window_pos -------------------------- */ + +#ifndef GL_MESA_window_pos +#define GL_MESA_window_pos 1 + +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS2SVMESAPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVMESAPROC) (const GLshort* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4IVMESAPROC) (const GLint* p); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p); + +#define glWindowPos2dMESA GLEW_GET_FUN(__glewWindowPos2dMESA) +#define glWindowPos2dvMESA GLEW_GET_FUN(__glewWindowPos2dvMESA) +#define glWindowPos2fMESA GLEW_GET_FUN(__glewWindowPos2fMESA) +#define glWindowPos2fvMESA GLEW_GET_FUN(__glewWindowPos2fvMESA) +#define glWindowPos2iMESA GLEW_GET_FUN(__glewWindowPos2iMESA) +#define glWindowPos2ivMESA GLEW_GET_FUN(__glewWindowPos2ivMESA) +#define glWindowPos2sMESA GLEW_GET_FUN(__glewWindowPos2sMESA) +#define glWindowPos2svMESA GLEW_GET_FUN(__glewWindowPos2svMESA) +#define glWindowPos3dMESA GLEW_GET_FUN(__glewWindowPos3dMESA) +#define glWindowPos3dvMESA GLEW_GET_FUN(__glewWindowPos3dvMESA) +#define glWindowPos3fMESA GLEW_GET_FUN(__glewWindowPos3fMESA) +#define glWindowPos3fvMESA GLEW_GET_FUN(__glewWindowPos3fvMESA) +#define glWindowPos3iMESA GLEW_GET_FUN(__glewWindowPos3iMESA) +#define glWindowPos3ivMESA GLEW_GET_FUN(__glewWindowPos3ivMESA) +#define glWindowPos3sMESA GLEW_GET_FUN(__glewWindowPos3sMESA) +#define glWindowPos3svMESA GLEW_GET_FUN(__glewWindowPos3svMESA) +#define glWindowPos4dMESA GLEW_GET_FUN(__glewWindowPos4dMESA) +#define glWindowPos4dvMESA GLEW_GET_FUN(__glewWindowPos4dvMESA) +#define glWindowPos4fMESA GLEW_GET_FUN(__glewWindowPos4fMESA) +#define glWindowPos4fvMESA GLEW_GET_FUN(__glewWindowPos4fvMESA) +#define glWindowPos4iMESA GLEW_GET_FUN(__glewWindowPos4iMESA) +#define glWindowPos4ivMESA GLEW_GET_FUN(__glewWindowPos4ivMESA) +#define glWindowPos4sMESA GLEW_GET_FUN(__glewWindowPos4sMESA) +#define glWindowPos4svMESA GLEW_GET_FUN(__glewWindowPos4svMESA) + +#define GLEW_MESA_window_pos GLEW_GET_VAR(__GLEW_MESA_window_pos) + +#endif /* GL_MESA_window_pos */ + +/* ------------------------- GL_MESA_ycbcr_texture ------------------------- */ + +#ifndef GL_MESA_ycbcr_texture +#define GL_MESA_ycbcr_texture 1 + +#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB +#define GL_YCBCR_MESA 0x8757 + +#define GLEW_MESA_ycbcr_texture GLEW_GET_VAR(__GLEW_MESA_ycbcr_texture) + +#endif /* GL_MESA_ycbcr_texture */ + +/* ------------------------- GL_NVX_gpu_memory_info ------------------------ */ + +#ifndef GL_NVX_gpu_memory_info +#define GL_NVX_gpu_memory_info 1 + +#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 +#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 +#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 +#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A +#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B + +#define GLEW_NVX_gpu_memory_info GLEW_GET_VAR(__GLEW_NVX_gpu_memory_info) + +#endif /* GL_NVX_gpu_memory_info */ + +/* --------------------------- GL_NV_blend_square -------------------------- */ + +#ifndef GL_NV_blend_square +#define GL_NV_blend_square 1 + +#define GLEW_NV_blend_square GLEW_GET_VAR(__GLEW_NV_blend_square) + +#endif /* GL_NV_blend_square */ + +/* ------------------------ GL_NV_conditional_render ----------------------- */ + +#ifndef GL_NV_conditional_render +#define GL_NV_conditional_render 1 + +#define GL_QUERY_WAIT_NV 0x8E13 +#define GL_QUERY_NO_WAIT_NV 0x8E14 +#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 + +typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); +typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVPROC) (void); + +#define glBeginConditionalRenderNV GLEW_GET_FUN(__glewBeginConditionalRenderNV) +#define glEndConditionalRenderNV GLEW_GET_FUN(__glewEndConditionalRenderNV) + +#define GLEW_NV_conditional_render GLEW_GET_VAR(__GLEW_NV_conditional_render) + +#endif /* GL_NV_conditional_render */ + +/* ----------------------- GL_NV_copy_depth_to_color ----------------------- */ + +#ifndef GL_NV_copy_depth_to_color +#define GL_NV_copy_depth_to_color 1 + +#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E +#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F + +#define GLEW_NV_copy_depth_to_color GLEW_GET_VAR(__GLEW_NV_copy_depth_to_color) + +#endif /* GL_NV_copy_depth_to_color */ + +/* ---------------------------- GL_NV_copy_image --------------------------- */ + +#ifndef GL_NV_copy_image +#define GL_NV_copy_image 1 + +typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); + +#define glCopyImageSubDataNV GLEW_GET_FUN(__glewCopyImageSubDataNV) + +#define GLEW_NV_copy_image GLEW_GET_VAR(__GLEW_NV_copy_image) + +#endif /* GL_NV_copy_image */ + +/* ------------------------ GL_NV_depth_buffer_float ----------------------- */ + +#ifndef GL_NV_depth_buffer_float +#define GL_NV_depth_buffer_float 1 + +#define GL_DEPTH_COMPONENT32F_NV 0x8DAB +#define GL_DEPTH32F_STENCIL8_NV 0x8DAC +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD +#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHDNVPROC) (GLdouble depth); +typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar); + +#define glClearDepthdNV GLEW_GET_FUN(__glewClearDepthdNV) +#define glDepthBoundsdNV GLEW_GET_FUN(__glewDepthBoundsdNV) +#define glDepthRangedNV GLEW_GET_FUN(__glewDepthRangedNV) + +#define GLEW_NV_depth_buffer_float GLEW_GET_VAR(__GLEW_NV_depth_buffer_float) + +#endif /* GL_NV_depth_buffer_float */ + +/* --------------------------- GL_NV_depth_clamp --------------------------- */ + +#ifndef GL_NV_depth_clamp +#define GL_NV_depth_clamp 1 + +#define GL_DEPTH_CLAMP_NV 0x864F + +#define GLEW_NV_depth_clamp GLEW_GET_VAR(__GLEW_NV_depth_clamp) + +#endif /* GL_NV_depth_clamp */ + +/* ---------------------- GL_NV_depth_range_unclamped ---------------------- */ + +#ifndef GL_NV_depth_range_unclamped +#define GL_NV_depth_range_unclamped 1 + +#define GL_SAMPLE_COUNT_BITS_NV 0x8864 +#define GL_CURRENT_SAMPLE_COUNT_QUERY_NV 0x8865 +#define GL_QUERY_RESULT_NV 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_NV 0x8867 +#define GL_SAMPLE_COUNT_NV 0x8914 + +#define GLEW_NV_depth_range_unclamped GLEW_GET_VAR(__GLEW_NV_depth_range_unclamped) + +#endif /* GL_NV_depth_range_unclamped */ + +/* ---------------------------- GL_NV_evaluators --------------------------- */ + +#ifndef GL_NV_evaluators +#define GL_NV_evaluators 1 + +#define GL_EVAL_2D_NV 0x86C0 +#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 +#define GL_MAP_TESSELLATION_NV 0x86C2 +#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 +#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 +#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 +#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 +#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 +#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 +#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 +#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA +#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB +#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC +#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD +#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE +#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF +#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 +#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 +#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 +#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 +#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 +#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 +#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 +#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 + +typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); +typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void* points); +typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void* points); +typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params); + +#define glEvalMapsNV GLEW_GET_FUN(__glewEvalMapsNV) +#define glGetMapAttribParameterfvNV GLEW_GET_FUN(__glewGetMapAttribParameterfvNV) +#define glGetMapAttribParameterivNV GLEW_GET_FUN(__glewGetMapAttribParameterivNV) +#define glGetMapControlPointsNV GLEW_GET_FUN(__glewGetMapControlPointsNV) +#define glGetMapParameterfvNV GLEW_GET_FUN(__glewGetMapParameterfvNV) +#define glGetMapParameterivNV GLEW_GET_FUN(__glewGetMapParameterivNV) +#define glMapControlPointsNV GLEW_GET_FUN(__glewMapControlPointsNV) +#define glMapParameterfvNV GLEW_GET_FUN(__glewMapParameterfvNV) +#define glMapParameterivNV GLEW_GET_FUN(__glewMapParameterivNV) + +#define GLEW_NV_evaluators GLEW_GET_VAR(__GLEW_NV_evaluators) + +#endif /* GL_NV_evaluators */ + +/* ----------------------- GL_NV_explicit_multisample ---------------------- */ + +#ifndef GL_NV_explicit_multisample +#define GL_NV_explicit_multisample 1 + +#define GL_SAMPLE_POSITION_NV 0x8E50 +#define GL_SAMPLE_MASK_NV 0x8E51 +#define GL_SAMPLE_MASK_VALUE_NV 0x8E52 +#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53 +#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54 +#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55 +#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56 +#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57 +#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58 +#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59 + +typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat* val); +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask); +typedef void (GLAPIENTRY * PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer); + +#define glGetMultisamplefvNV GLEW_GET_FUN(__glewGetMultisamplefvNV) +#define glSampleMaskIndexedNV GLEW_GET_FUN(__glewSampleMaskIndexedNV) +#define glTexRenderbufferNV GLEW_GET_FUN(__glewTexRenderbufferNV) + +#define GLEW_NV_explicit_multisample GLEW_GET_VAR(__GLEW_NV_explicit_multisample) + +#endif /* GL_NV_explicit_multisample */ + +/* ------------------------------ GL_NV_fence ------------------------------ */ + +#ifndef GL_NV_fence +#define GL_NV_fence 1 + +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 + +typedef void (GLAPIENTRY * PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint* fences); +typedef void (GLAPIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint* fences); +typedef void (GLAPIENTRY * PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISFENCENVPROC) (GLuint fence); +typedef void (GLAPIENTRY * PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +typedef GLboolean (GLAPIENTRY * PFNGLTESTFENCENVPROC) (GLuint fence); + +#define glDeleteFencesNV GLEW_GET_FUN(__glewDeleteFencesNV) +#define glFinishFenceNV GLEW_GET_FUN(__glewFinishFenceNV) +#define glGenFencesNV GLEW_GET_FUN(__glewGenFencesNV) +#define glGetFenceivNV GLEW_GET_FUN(__glewGetFenceivNV) +#define glIsFenceNV GLEW_GET_FUN(__glewIsFenceNV) +#define glSetFenceNV GLEW_GET_FUN(__glewSetFenceNV) +#define glTestFenceNV GLEW_GET_FUN(__glewTestFenceNV) + +#define GLEW_NV_fence GLEW_GET_VAR(__GLEW_NV_fence) + +#endif /* GL_NV_fence */ + +/* --------------------------- GL_NV_float_buffer -------------------------- */ + +#ifndef GL_NV_float_buffer +#define GL_NV_float_buffer 1 + +#define GL_FLOAT_R_NV 0x8880 +#define GL_FLOAT_RG_NV 0x8881 +#define GL_FLOAT_RGB_NV 0x8882 +#define GL_FLOAT_RGBA_NV 0x8883 +#define GL_FLOAT_R16_NV 0x8884 +#define GL_FLOAT_R32_NV 0x8885 +#define GL_FLOAT_RG16_NV 0x8886 +#define GL_FLOAT_RG32_NV 0x8887 +#define GL_FLOAT_RGB16_NV 0x8888 +#define GL_FLOAT_RGB32_NV 0x8889 +#define GL_FLOAT_RGBA16_NV 0x888A +#define GL_FLOAT_RGBA32_NV 0x888B +#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C +#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D +#define GL_FLOAT_RGBA_MODE_NV 0x888E + +#define GLEW_NV_float_buffer GLEW_GET_VAR(__GLEW_NV_float_buffer) + +#endif /* GL_NV_float_buffer */ + +/* --------------------------- GL_NV_fog_distance -------------------------- */ + +#ifndef GL_NV_fog_distance +#define GL_NV_fog_distance 1 + +#define GL_FOG_DISTANCE_MODE_NV 0x855A +#define GL_EYE_RADIAL_NV 0x855B +#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C + +#define GLEW_NV_fog_distance GLEW_GET_VAR(__GLEW_NV_fog_distance) + +#endif /* GL_NV_fog_distance */ + +/* ------------------------- GL_NV_fragment_program ------------------------ */ + +#ifndef GL_NV_fragment_program +#define GL_NV_fragment_program 1 + +#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 +#define GL_FRAGMENT_PROGRAM_NV 0x8870 +#define GL_MAX_TEXTURE_COORDS_NV 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 +#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 +#define GL_PROGRAM_ERROR_STRING_NV 0x8874 + +typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble *params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLdouble v[]); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte* name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte* name, const GLfloat v[]); + +#define glGetProgramNamedParameterdvNV GLEW_GET_FUN(__glewGetProgramNamedParameterdvNV) +#define glGetProgramNamedParameterfvNV GLEW_GET_FUN(__glewGetProgramNamedParameterfvNV) +#define glProgramNamedParameter4dNV GLEW_GET_FUN(__glewProgramNamedParameter4dNV) +#define glProgramNamedParameter4dvNV GLEW_GET_FUN(__glewProgramNamedParameter4dvNV) +#define glProgramNamedParameter4fNV GLEW_GET_FUN(__glewProgramNamedParameter4fNV) +#define glProgramNamedParameter4fvNV GLEW_GET_FUN(__glewProgramNamedParameter4fvNV) + +#define GLEW_NV_fragment_program GLEW_GET_VAR(__GLEW_NV_fragment_program) + +#endif /* GL_NV_fragment_program */ + +/* ------------------------ GL_NV_fragment_program2 ------------------------ */ + +#ifndef GL_NV_fragment_program2 +#define GL_NV_fragment_program2 1 + +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 +#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 +#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 +#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 + +#define GLEW_NV_fragment_program2 GLEW_GET_VAR(__GLEW_NV_fragment_program2) + +#endif /* GL_NV_fragment_program2 */ + +/* ------------------------ GL_NV_fragment_program4 ------------------------ */ + +#ifndef GL_NV_fragment_program4 +#define GL_NV_fragment_program4 1 + +#define GLEW_NV_fragment_program4 GLEW_GET_VAR(__GLEW_NV_fragment_program4) + +#endif /* GL_NV_fragment_program4 */ + +/* --------------------- GL_NV_fragment_program_option --------------------- */ + +#ifndef GL_NV_fragment_program_option +#define GL_NV_fragment_program_option 1 + +#define GLEW_NV_fragment_program_option GLEW_GET_VAR(__GLEW_NV_fragment_program_option) + +#endif /* GL_NV_fragment_program_option */ + +/* ----------------- GL_NV_framebuffer_multisample_coverage ---------------- */ + +#ifndef GL_NV_framebuffer_multisample_coverage +#define GL_NV_framebuffer_multisample_coverage 1 + +#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB +#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 +#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11 +#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12 + +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glRenderbufferStorageMultisampleCoverageNV GLEW_GET_FUN(__glewRenderbufferStorageMultisampleCoverageNV) + +#define GLEW_NV_framebuffer_multisample_coverage GLEW_GET_VAR(__GLEW_NV_framebuffer_multisample_coverage) + +#endif /* GL_NV_framebuffer_multisample_coverage */ + +/* ------------------------ GL_NV_geometry_program4 ------------------------ */ + +#ifndef GL_NV_geometry_program4 +#define GL_NV_geometry_program4 1 + +#define GL_GEOMETRY_PROGRAM_NV 0x8C26 +#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 +#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 + +typedef void (GLAPIENTRY * PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit); + +#define glProgramVertexLimitNV GLEW_GET_FUN(__glewProgramVertexLimitNV) + +#define GLEW_NV_geometry_program4 GLEW_GET_VAR(__GLEW_NV_geometry_program4) + +#endif /* GL_NV_geometry_program4 */ + +/* ------------------------- GL_NV_geometry_shader4 ------------------------ */ + +#ifndef GL_NV_geometry_shader4 +#define GL_NV_geometry_shader4 1 + +#define GLEW_NV_geometry_shader4 GLEW_GET_VAR(__GLEW_NV_geometry_shader4) + +#endif /* GL_NV_geometry_shader4 */ + +/* --------------------------- GL_NV_gpu_program4 -------------------------- */ + +#ifndef GL_NV_gpu_program4 +#define GL_NV_gpu_program4 1 + +#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905 +#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906 +#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907 +#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908 +#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909 +#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5 +#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6 + +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params); + +#define glProgramEnvParameterI4iNV GLEW_GET_FUN(__glewProgramEnvParameterI4iNV) +#define glProgramEnvParameterI4ivNV GLEW_GET_FUN(__glewProgramEnvParameterI4ivNV) +#define glProgramEnvParameterI4uiNV GLEW_GET_FUN(__glewProgramEnvParameterI4uiNV) +#define glProgramEnvParameterI4uivNV GLEW_GET_FUN(__glewProgramEnvParameterI4uivNV) +#define glProgramEnvParametersI4ivNV GLEW_GET_FUN(__glewProgramEnvParametersI4ivNV) +#define glProgramEnvParametersI4uivNV GLEW_GET_FUN(__glewProgramEnvParametersI4uivNV) +#define glProgramLocalParameterI4iNV GLEW_GET_FUN(__glewProgramLocalParameterI4iNV) +#define glProgramLocalParameterI4ivNV GLEW_GET_FUN(__glewProgramLocalParameterI4ivNV) +#define glProgramLocalParameterI4uiNV GLEW_GET_FUN(__glewProgramLocalParameterI4uiNV) +#define glProgramLocalParameterI4uivNV GLEW_GET_FUN(__glewProgramLocalParameterI4uivNV) +#define glProgramLocalParametersI4ivNV GLEW_GET_FUN(__glewProgramLocalParametersI4ivNV) +#define glProgramLocalParametersI4uivNV GLEW_GET_FUN(__glewProgramLocalParametersI4uivNV) + +#define GLEW_NV_gpu_program4 GLEW_GET_VAR(__GLEW_NV_gpu_program4) + +#endif /* GL_NV_gpu_program4 */ + +/* --------------------------- GL_NV_gpu_program5 -------------------------- */ + +#ifndef GL_NV_gpu_program5 +#define GL_NV_gpu_program5 1 + +#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C +#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F + +#define GLEW_NV_gpu_program5 GLEW_GET_VAR(__GLEW_NV_gpu_program5) + +#endif /* GL_NV_gpu_program5 */ + +/* ------------------------- GL_NV_gpu_program_fp64 ------------------------ */ + +#ifndef GL_NV_gpu_program_fp64 +#define GL_NV_gpu_program_fp64 1 + +#define GLEW_NV_gpu_program_fp64 GLEW_GET_VAR(__GLEW_NV_gpu_program_fp64) + +#endif /* GL_NV_gpu_program_fp64 */ + +/* --------------------------- GL_NV_gpu_shader5 --------------------------- */ + +#ifndef GL_NV_gpu_shader5 +#define GL_NV_gpu_shader5 1 + +#define GL_INT64_NV 0x140E +#define GL_UNSIGNED_INT64_NV 0x140F +#define GL_INT8_NV 0x8FE0 +#define GL_INT8_VEC2_NV 0x8FE1 +#define GL_INT8_VEC3_NV 0x8FE2 +#define GL_INT8_VEC4_NV 0x8FE3 +#define GL_INT16_NV 0x8FE4 +#define GL_INT16_VEC2_NV 0x8FE5 +#define GL_INT16_VEC3_NV 0x8FE6 +#define GL_INT16_VEC4_NV 0x8FE7 +#define GL_INT64_VEC2_NV 0x8FE9 +#define GL_INT64_VEC3_NV 0x8FEA +#define GL_INT64_VEC4_NV 0x8FEB +#define GL_UNSIGNED_INT8_NV 0x8FEC +#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED +#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE +#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF +#define GL_UNSIGNED_INT16_NV 0x8FF0 +#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1 +#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2 +#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3 +#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5 +#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6 +#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB + +typedef void (GLAPIENTRY * PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x); +typedef void (GLAPIENTRY * PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x); +typedef void (GLAPIENTRY * PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y); +typedef void (GLAPIENTRY * PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y); +typedef void (GLAPIENTRY * PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (GLAPIENTRY * PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (GLAPIENTRY * PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (GLAPIENTRY * PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (GLAPIENTRY * PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); + +#define glGetUniformi64vNV GLEW_GET_FUN(__glewGetUniformi64vNV) +#define glGetUniformui64vNV GLEW_GET_FUN(__glewGetUniformui64vNV) +#define glProgramUniform1i64NV GLEW_GET_FUN(__glewProgramUniform1i64NV) +#define glProgramUniform1i64vNV GLEW_GET_FUN(__glewProgramUniform1i64vNV) +#define glProgramUniform1ui64NV GLEW_GET_FUN(__glewProgramUniform1ui64NV) +#define glProgramUniform1ui64vNV GLEW_GET_FUN(__glewProgramUniform1ui64vNV) +#define glProgramUniform2i64NV GLEW_GET_FUN(__glewProgramUniform2i64NV) +#define glProgramUniform2i64vNV GLEW_GET_FUN(__glewProgramUniform2i64vNV) +#define glProgramUniform2ui64NV GLEW_GET_FUN(__glewProgramUniform2ui64NV) +#define glProgramUniform2ui64vNV GLEW_GET_FUN(__glewProgramUniform2ui64vNV) +#define glProgramUniform3i64NV GLEW_GET_FUN(__glewProgramUniform3i64NV) +#define glProgramUniform3i64vNV GLEW_GET_FUN(__glewProgramUniform3i64vNV) +#define glProgramUniform3ui64NV GLEW_GET_FUN(__glewProgramUniform3ui64NV) +#define glProgramUniform3ui64vNV GLEW_GET_FUN(__glewProgramUniform3ui64vNV) +#define glProgramUniform4i64NV GLEW_GET_FUN(__glewProgramUniform4i64NV) +#define glProgramUniform4i64vNV GLEW_GET_FUN(__glewProgramUniform4i64vNV) +#define glProgramUniform4ui64NV GLEW_GET_FUN(__glewProgramUniform4ui64NV) +#define glProgramUniform4ui64vNV GLEW_GET_FUN(__glewProgramUniform4ui64vNV) +#define glUniform1i64NV GLEW_GET_FUN(__glewUniform1i64NV) +#define glUniform1i64vNV GLEW_GET_FUN(__glewUniform1i64vNV) +#define glUniform1ui64NV GLEW_GET_FUN(__glewUniform1ui64NV) +#define glUniform1ui64vNV GLEW_GET_FUN(__glewUniform1ui64vNV) +#define glUniform2i64NV GLEW_GET_FUN(__glewUniform2i64NV) +#define glUniform2i64vNV GLEW_GET_FUN(__glewUniform2i64vNV) +#define glUniform2ui64NV GLEW_GET_FUN(__glewUniform2ui64NV) +#define glUniform2ui64vNV GLEW_GET_FUN(__glewUniform2ui64vNV) +#define glUniform3i64NV GLEW_GET_FUN(__glewUniform3i64NV) +#define glUniform3i64vNV GLEW_GET_FUN(__glewUniform3i64vNV) +#define glUniform3ui64NV GLEW_GET_FUN(__glewUniform3ui64NV) +#define glUniform3ui64vNV GLEW_GET_FUN(__glewUniform3ui64vNV) +#define glUniform4i64NV GLEW_GET_FUN(__glewUniform4i64NV) +#define glUniform4i64vNV GLEW_GET_FUN(__glewUniform4i64vNV) +#define glUniform4ui64NV GLEW_GET_FUN(__glewUniform4ui64NV) +#define glUniform4ui64vNV GLEW_GET_FUN(__glewUniform4ui64vNV) + +#define GLEW_NV_gpu_shader5 GLEW_GET_VAR(__GLEW_NV_gpu_shader5) + +#endif /* GL_NV_gpu_shader5 */ + +/* ---------------------------- GL_NV_half_float --------------------------- */ + +#ifndef GL_NV_half_float +#define GL_NV_half_float 1 + +#define GL_HALF_FLOAT_NV 0x140B + +typedef unsigned short GLhalf; + +typedef void (GLAPIENTRY * PFNGLCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue); +typedef void (GLAPIENTRY * PFNGLCOLOR3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLCOLOR4HNVPROC) (GLhalf red, GLhalf green, GLhalf blue, GLhalf alpha); +typedef void (GLAPIENTRY * PFNGLCOLOR4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLFOGCOORDHNVPROC) (GLhalf fog); +typedef void (GLAPIENTRY * PFNGLFOGCOORDHVNVPROC) (const GLhalf* fog); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalf s); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalf s, GLhalf t); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalf s, GLhalf t, GLhalf r, GLhalf q); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLNORMAL3HNVPROC) (GLhalf nx, GLhalf ny, GLhalf nz); +typedef void (GLAPIENTRY * PFNGLNORMAL3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HNVPROC) (GLhalf red, GLhalf green, GLhalf blue); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD1HNVPROC) (GLhalf s); +typedef void (GLAPIENTRY * PFNGLTEXCOORD1HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2HNVPROC) (GLhalf s, GLhalf t); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD3HNVPROC) (GLhalf s, GLhalf t, GLhalf r); +typedef void (GLAPIENTRY * PFNGLTEXCOORD3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4HNVPROC) (GLhalf s, GLhalf t, GLhalf r, GLhalf q); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX2HNVPROC) (GLhalf x, GLhalf y); +typedef void (GLAPIENTRY * PFNGLVERTEX2HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX3HNVPROC) (GLhalf x, GLhalf y, GLhalf z); +typedef void (GLAPIENTRY * PFNGLVERTEX3HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEX4HNVPROC) (GLhalf x, GLhalf y, GLhalf z, GLhalf w); +typedef void (GLAPIENTRY * PFNGLVERTEX4HVNVPROC) (const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalf x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalf x, GLhalf y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalf x, GLhalf y, GLhalf z, GLhalf w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalf* v); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHNVPROC) (GLhalf weight); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalf* weight); + +#define glColor3hNV GLEW_GET_FUN(__glewColor3hNV) +#define glColor3hvNV GLEW_GET_FUN(__glewColor3hvNV) +#define glColor4hNV GLEW_GET_FUN(__glewColor4hNV) +#define glColor4hvNV GLEW_GET_FUN(__glewColor4hvNV) +#define glFogCoordhNV GLEW_GET_FUN(__glewFogCoordhNV) +#define glFogCoordhvNV GLEW_GET_FUN(__glewFogCoordhvNV) +#define glMultiTexCoord1hNV GLEW_GET_FUN(__glewMultiTexCoord1hNV) +#define glMultiTexCoord1hvNV GLEW_GET_FUN(__glewMultiTexCoord1hvNV) +#define glMultiTexCoord2hNV GLEW_GET_FUN(__glewMultiTexCoord2hNV) +#define glMultiTexCoord2hvNV GLEW_GET_FUN(__glewMultiTexCoord2hvNV) +#define glMultiTexCoord3hNV GLEW_GET_FUN(__glewMultiTexCoord3hNV) +#define glMultiTexCoord3hvNV GLEW_GET_FUN(__glewMultiTexCoord3hvNV) +#define glMultiTexCoord4hNV GLEW_GET_FUN(__glewMultiTexCoord4hNV) +#define glMultiTexCoord4hvNV GLEW_GET_FUN(__glewMultiTexCoord4hvNV) +#define glNormal3hNV GLEW_GET_FUN(__glewNormal3hNV) +#define glNormal3hvNV GLEW_GET_FUN(__glewNormal3hvNV) +#define glSecondaryColor3hNV GLEW_GET_FUN(__glewSecondaryColor3hNV) +#define glSecondaryColor3hvNV GLEW_GET_FUN(__glewSecondaryColor3hvNV) +#define glTexCoord1hNV GLEW_GET_FUN(__glewTexCoord1hNV) +#define glTexCoord1hvNV GLEW_GET_FUN(__glewTexCoord1hvNV) +#define glTexCoord2hNV GLEW_GET_FUN(__glewTexCoord2hNV) +#define glTexCoord2hvNV GLEW_GET_FUN(__glewTexCoord2hvNV) +#define glTexCoord3hNV GLEW_GET_FUN(__glewTexCoord3hNV) +#define glTexCoord3hvNV GLEW_GET_FUN(__glewTexCoord3hvNV) +#define glTexCoord4hNV GLEW_GET_FUN(__glewTexCoord4hNV) +#define glTexCoord4hvNV GLEW_GET_FUN(__glewTexCoord4hvNV) +#define glVertex2hNV GLEW_GET_FUN(__glewVertex2hNV) +#define glVertex2hvNV GLEW_GET_FUN(__glewVertex2hvNV) +#define glVertex3hNV GLEW_GET_FUN(__glewVertex3hNV) +#define glVertex3hvNV GLEW_GET_FUN(__glewVertex3hvNV) +#define glVertex4hNV GLEW_GET_FUN(__glewVertex4hNV) +#define glVertex4hvNV GLEW_GET_FUN(__glewVertex4hvNV) +#define glVertexAttrib1hNV GLEW_GET_FUN(__glewVertexAttrib1hNV) +#define glVertexAttrib1hvNV GLEW_GET_FUN(__glewVertexAttrib1hvNV) +#define glVertexAttrib2hNV GLEW_GET_FUN(__glewVertexAttrib2hNV) +#define glVertexAttrib2hvNV GLEW_GET_FUN(__glewVertexAttrib2hvNV) +#define glVertexAttrib3hNV GLEW_GET_FUN(__glewVertexAttrib3hNV) +#define glVertexAttrib3hvNV GLEW_GET_FUN(__glewVertexAttrib3hvNV) +#define glVertexAttrib4hNV GLEW_GET_FUN(__glewVertexAttrib4hNV) +#define glVertexAttrib4hvNV GLEW_GET_FUN(__glewVertexAttrib4hvNV) +#define glVertexAttribs1hvNV GLEW_GET_FUN(__glewVertexAttribs1hvNV) +#define glVertexAttribs2hvNV GLEW_GET_FUN(__glewVertexAttribs2hvNV) +#define glVertexAttribs3hvNV GLEW_GET_FUN(__glewVertexAttribs3hvNV) +#define glVertexAttribs4hvNV GLEW_GET_FUN(__glewVertexAttribs4hvNV) +#define glVertexWeighthNV GLEW_GET_FUN(__glewVertexWeighthNV) +#define glVertexWeighthvNV GLEW_GET_FUN(__glewVertexWeighthvNV) + +#define GLEW_NV_half_float GLEW_GET_VAR(__GLEW_NV_half_float) + +#endif /* GL_NV_half_float */ + +/* ------------------------ GL_NV_light_max_exponent ----------------------- */ + +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent 1 + +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 + +#define GLEW_NV_light_max_exponent GLEW_GET_VAR(__GLEW_NV_light_max_exponent) + +#endif /* GL_NV_light_max_exponent */ + +/* ----------------------- GL_NV_multisample_coverage ---------------------- */ + +#ifndef GL_NV_multisample_coverage +#define GL_NV_multisample_coverage 1 + +#define GL_COVERAGE_SAMPLES_NV 0x80A9 +#define GL_COLOR_SAMPLES_NV 0x8E20 + +#define GLEW_NV_multisample_coverage GLEW_GET_VAR(__GLEW_NV_multisample_coverage) + +#endif /* GL_NV_multisample_coverage */ + +/* --------------------- GL_NV_multisample_filter_hint --------------------- */ + +#ifndef GL_NV_multisample_filter_hint +#define GL_NV_multisample_filter_hint 1 + +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 + +#define GLEW_NV_multisample_filter_hint GLEW_GET_VAR(__GLEW_NV_multisample_filter_hint) + +#endif /* GL_NV_multisample_filter_hint */ + +/* ------------------------- GL_NV_occlusion_query ------------------------- */ + +#ifndef GL_NV_occlusion_query +#define GL_NV_occlusion_query 1 + +#define GL_PIXEL_COUNTER_BITS_NV 0x8864 +#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 +#define GL_PIXEL_COUNT_NV 0x8866 +#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 + +typedef void (GLAPIENTRY * PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDOCCLUSIONQUERYNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); + +#define glBeginOcclusionQueryNV GLEW_GET_FUN(__glewBeginOcclusionQueryNV) +#define glDeleteOcclusionQueriesNV GLEW_GET_FUN(__glewDeleteOcclusionQueriesNV) +#define glEndOcclusionQueryNV GLEW_GET_FUN(__glewEndOcclusionQueryNV) +#define glGenOcclusionQueriesNV GLEW_GET_FUN(__glewGenOcclusionQueriesNV) +#define glGetOcclusionQueryivNV GLEW_GET_FUN(__glewGetOcclusionQueryivNV) +#define glGetOcclusionQueryuivNV GLEW_GET_FUN(__glewGetOcclusionQueryuivNV) +#define glIsOcclusionQueryNV GLEW_GET_FUN(__glewIsOcclusionQueryNV) + +#define GLEW_NV_occlusion_query GLEW_GET_VAR(__GLEW_NV_occlusion_query) + +#endif /* GL_NV_occlusion_query */ + +/* ----------------------- GL_NV_packed_depth_stencil ---------------------- */ + +#ifndef GL_NV_packed_depth_stencil +#define GL_NV_packed_depth_stencil 1 + +#define GL_DEPTH_STENCIL_NV 0x84F9 +#define GL_UNSIGNED_INT_24_8_NV 0x84FA + +#define GLEW_NV_packed_depth_stencil GLEW_GET_VAR(__GLEW_NV_packed_depth_stencil) + +#endif /* GL_NV_packed_depth_stencil */ + +/* --------------------- GL_NV_parameter_buffer_object --------------------- */ + +#ifndef GL_NV_parameter_buffer_object +#define GL_NV_parameter_buffer_object 1 + +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0 +#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1 +#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2 +#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3 +#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4 + +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLuint *params); +typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint buffer, GLuint index, GLsizei count, const GLfloat *params); + +#define glProgramBufferParametersIivNV GLEW_GET_FUN(__glewProgramBufferParametersIivNV) +#define glProgramBufferParametersIuivNV GLEW_GET_FUN(__glewProgramBufferParametersIuivNV) +#define glProgramBufferParametersfvNV GLEW_GET_FUN(__glewProgramBufferParametersfvNV) + +#define GLEW_NV_parameter_buffer_object GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object) + +#endif /* GL_NV_parameter_buffer_object */ + +/* --------------------- GL_NV_parameter_buffer_object2 -------------------- */ + +#ifndef GL_NV_parameter_buffer_object2 +#define GL_NV_parameter_buffer_object2 1 + +#define GLEW_NV_parameter_buffer_object2 GLEW_GET_VAR(__GLEW_NV_parameter_buffer_object2) + +#endif /* GL_NV_parameter_buffer_object2 */ + +/* ------------------------- GL_NV_pixel_data_range ------------------------ */ + +#ifndef GL_NV_pixel_data_range +#define GL_NV_pixel_data_range 1 + +#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 +#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 +#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A +#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B +#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C +#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D + +typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void* pointer); + +#define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV) +#define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV) + +#define GLEW_NV_pixel_data_range GLEW_GET_VAR(__GLEW_NV_pixel_data_range) + +#endif /* GL_NV_pixel_data_range */ + +/* --------------------------- GL_NV_point_sprite -------------------------- */ + +#ifndef GL_NV_point_sprite +#define GL_NV_point_sprite 1 + +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 + +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint* params); + +#define glPointParameteriNV GLEW_GET_FUN(__glewPointParameteriNV) +#define glPointParameterivNV GLEW_GET_FUN(__glewPointParameterivNV) + +#define GLEW_NV_point_sprite GLEW_GET_VAR(__GLEW_NV_point_sprite) + +#endif /* GL_NV_point_sprite */ + +/* -------------------------- GL_NV_present_video -------------------------- */ + +#ifndef GL_NV_present_video +#define GL_NV_present_video 1 + +#define GL_FRAME_NV 0x8E26 +#define GL_FIELDS_NV 0x8E27 +#define GL_CURRENT_TIME_NV 0x8E28 +#define GL_NUM_FILL_STREAMS_NV 0x8E29 +#define GL_PRESENT_TIME_NV 0x8E2A +#define GL_PRESENT_DURATION_NV 0x8E2B + +typedef void (GLAPIENTRY * PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3); +typedef void (GLAPIENTRY * PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1); + +#define glGetVideoi64vNV GLEW_GET_FUN(__glewGetVideoi64vNV) +#define glGetVideoivNV GLEW_GET_FUN(__glewGetVideoivNV) +#define glGetVideoui64vNV GLEW_GET_FUN(__glewGetVideoui64vNV) +#define glGetVideouivNV GLEW_GET_FUN(__glewGetVideouivNV) +#define glPresentFrameDualFillNV GLEW_GET_FUN(__glewPresentFrameDualFillNV) +#define glPresentFrameKeyedNV GLEW_GET_FUN(__glewPresentFrameKeyedNV) + +#define GLEW_NV_present_video GLEW_GET_VAR(__GLEW_NV_present_video) + +#endif /* GL_NV_present_video */ + +/* ------------------------ GL_NV_primitive_restart ------------------------ */ + +#ifndef GL_NV_primitive_restart +#define GL_NV_primitive_restart 1 + +#define GL_PRIMITIVE_RESTART_NV 0x8558 +#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 + +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); +typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTNVPROC) (void); + +#define glPrimitiveRestartIndexNV GLEW_GET_FUN(__glewPrimitiveRestartIndexNV) +#define glPrimitiveRestartNV GLEW_GET_FUN(__glewPrimitiveRestartNV) + +#define GLEW_NV_primitive_restart GLEW_GET_VAR(__GLEW_NV_primitive_restart) + +#endif /* GL_NV_primitive_restart */ + +/* ------------------------ GL_NV_register_combiners ----------------------- */ + +#ifndef GL_NV_register_combiners +#define GL_NV_register_combiners 1 + +#define GL_REGISTER_COMBINERS_NV 0x8522 +#define GL_VARIABLE_A_NV 0x8523 +#define GL_VARIABLE_B_NV 0x8524 +#define GL_VARIABLE_C_NV 0x8525 +#define GL_VARIABLE_D_NV 0x8526 +#define GL_VARIABLE_E_NV 0x8527 +#define GL_VARIABLE_F_NV 0x8528 +#define GL_VARIABLE_G_NV 0x8529 +#define GL_CONSTANT_COLOR0_NV 0x852A +#define GL_CONSTANT_COLOR1_NV 0x852B +#define GL_PRIMARY_COLOR_NV 0x852C +#define GL_SECONDARY_COLOR_NV 0x852D +#define GL_SPARE0_NV 0x852E +#define GL_SPARE1_NV 0x852F +#define GL_DISCARD_NV 0x8530 +#define GL_E_TIMES_F_NV 0x8531 +#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 +#define GL_UNSIGNED_IDENTITY_NV 0x8536 +#define GL_UNSIGNED_INVERT_NV 0x8537 +#define GL_EXPAND_NORMAL_NV 0x8538 +#define GL_EXPAND_NEGATE_NV 0x8539 +#define GL_HALF_BIAS_NORMAL_NV 0x853A +#define GL_HALF_BIAS_NEGATE_NV 0x853B +#define GL_SIGNED_IDENTITY_NV 0x853C +#define GL_SIGNED_NEGATE_NV 0x853D +#define GL_SCALE_BY_TWO_NV 0x853E +#define GL_SCALE_BY_FOUR_NV 0x853F +#define GL_SCALE_BY_ONE_HALF_NV 0x8540 +#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 +#define GL_COMBINER_INPUT_NV 0x8542 +#define GL_COMBINER_MAPPING_NV 0x8543 +#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 +#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 +#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 +#define GL_COMBINER_MUX_SUM_NV 0x8547 +#define GL_COMBINER_SCALE_NV 0x8548 +#define GL_COMBINER_BIAS_NV 0x8549 +#define GL_COMBINER_AB_OUTPUT_NV 0x854A +#define GL_COMBINER_CD_OUTPUT_NV 0x854B +#define GL_COMBINER_SUM_OUTPUT_NV 0x854C +#define GL_MAX_GENERAL_COMBINERS_NV 0x854D +#define GL_NUM_GENERAL_COMBINERS_NV 0x854E +#define GL_COLOR_SUM_CLAMP_NV 0x854F +#define GL_COMBINER0_NV 0x8550 +#define GL_COMBINER1_NV 0x8551 +#define GL_COMBINER2_NV 0x8552 +#define GL_COMBINER3_NV 0x8553 +#define GL_COMBINER4_NV 0x8554 +#define GL_COMBINER5_NV 0x8555 +#define GL_COMBINER6_NV 0x8556 +#define GL_COMBINER7_NV 0x8557 + +typedef void (GLAPIENTRY * PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (GLAPIENTRY * PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint* params); + +#define glCombinerInputNV GLEW_GET_FUN(__glewCombinerInputNV) +#define glCombinerOutputNV GLEW_GET_FUN(__glewCombinerOutputNV) +#define glCombinerParameterfNV GLEW_GET_FUN(__glewCombinerParameterfNV) +#define glCombinerParameterfvNV GLEW_GET_FUN(__glewCombinerParameterfvNV) +#define glCombinerParameteriNV GLEW_GET_FUN(__glewCombinerParameteriNV) +#define glCombinerParameterivNV GLEW_GET_FUN(__glewCombinerParameterivNV) +#define glFinalCombinerInputNV GLEW_GET_FUN(__glewFinalCombinerInputNV) +#define glGetCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetCombinerInputParameterfvNV) +#define glGetCombinerInputParameterivNV GLEW_GET_FUN(__glewGetCombinerInputParameterivNV) +#define glGetCombinerOutputParameterfvNV GLEW_GET_FUN(__glewGetCombinerOutputParameterfvNV) +#define glGetCombinerOutputParameterivNV GLEW_GET_FUN(__glewGetCombinerOutputParameterivNV) +#define glGetFinalCombinerInputParameterfvNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterfvNV) +#define glGetFinalCombinerInputParameterivNV GLEW_GET_FUN(__glewGetFinalCombinerInputParameterivNV) + +#define GLEW_NV_register_combiners GLEW_GET_VAR(__GLEW_NV_register_combiners) + +#endif /* GL_NV_register_combiners */ + +/* ----------------------- GL_NV_register_combiners2 ----------------------- */ + +#ifndef GL_NV_register_combiners2 +#define GL_NV_register_combiners2 1 + +#define GL_PER_STAGE_CONSTANTS_NV 0x8535 + +typedef void (GLAPIENTRY * PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat* params); + +#define glCombinerStageParameterfvNV GLEW_GET_FUN(__glewCombinerStageParameterfvNV) +#define glGetCombinerStageParameterfvNV GLEW_GET_FUN(__glewGetCombinerStageParameterfvNV) + +#define GLEW_NV_register_combiners2 GLEW_GET_VAR(__GLEW_NV_register_combiners2) + +#endif /* GL_NV_register_combiners2 */ + +/* ------------------------ GL_NV_shader_buffer_load ----------------------- */ + +#ifndef GL_NV_shader_buffer_load +#define GL_NV_shader_buffer_load 1 + +#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D +#define GL_GPU_ADDRESS_NV 0x8F34 +#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35 + +typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT* result); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT* params); +typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERRESIDENTNVPROC) (GLenum target); +typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access); +typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT* value); +typedef void (GLAPIENTRY * PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value); +typedef void (GLAPIENTRY * PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT* value); + +#define glGetBufferParameterui64vNV GLEW_GET_FUN(__glewGetBufferParameterui64vNV) +#define glGetIntegerui64vNV GLEW_GET_FUN(__glewGetIntegerui64vNV) +#define glGetNamedBufferParameterui64vNV GLEW_GET_FUN(__glewGetNamedBufferParameterui64vNV) +#define glIsBufferResidentNV GLEW_GET_FUN(__glewIsBufferResidentNV) +#define glIsNamedBufferResidentNV GLEW_GET_FUN(__glewIsNamedBufferResidentNV) +#define glMakeBufferNonResidentNV GLEW_GET_FUN(__glewMakeBufferNonResidentNV) +#define glMakeBufferResidentNV GLEW_GET_FUN(__glewMakeBufferResidentNV) +#define glMakeNamedBufferNonResidentNV GLEW_GET_FUN(__glewMakeNamedBufferNonResidentNV) +#define glMakeNamedBufferResidentNV GLEW_GET_FUN(__glewMakeNamedBufferResidentNV) +#define glProgramUniformui64NV GLEW_GET_FUN(__glewProgramUniformui64NV) +#define glProgramUniformui64vNV GLEW_GET_FUN(__glewProgramUniformui64vNV) +#define glUniformui64NV GLEW_GET_FUN(__glewUniformui64NV) +#define glUniformui64vNV GLEW_GET_FUN(__glewUniformui64vNV) + +#define GLEW_NV_shader_buffer_load GLEW_GET_VAR(__GLEW_NV_shader_buffer_load) + +#endif /* GL_NV_shader_buffer_load */ + +/* ---------------------- GL_NV_tessellation_program5 ---------------------- */ + +#ifndef GL_NV_tessellation_program5 +#define GL_NV_tessellation_program5 1 + +#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8 +#define GL_TESS_CONTROL_PROGRAM_NV 0x891E +#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F +#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74 +#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75 + +#define GLEW_NV_tessellation_program5 GLEW_GET_VAR(__GLEW_NV_tessellation_program5) + +#endif /* GL_NV_tessellation_program5 */ + +/* -------------------------- GL_NV_texgen_emboss -------------------------- */ + +#ifndef GL_NV_texgen_emboss +#define GL_NV_texgen_emboss 1 + +#define GL_EMBOSS_LIGHT_NV 0x855D +#define GL_EMBOSS_CONSTANT_NV 0x855E +#define GL_EMBOSS_MAP_NV 0x855F + +#define GLEW_NV_texgen_emboss GLEW_GET_VAR(__GLEW_NV_texgen_emboss) + +#endif /* GL_NV_texgen_emboss */ + +/* ------------------------ GL_NV_texgen_reflection ------------------------ */ + +#ifndef GL_NV_texgen_reflection +#define GL_NV_texgen_reflection 1 + +#define GL_NORMAL_MAP_NV 0x8511 +#define GL_REFLECTION_MAP_NV 0x8512 + +#define GLEW_NV_texgen_reflection GLEW_GET_VAR(__GLEW_NV_texgen_reflection) + +#endif /* GL_NV_texgen_reflection */ + +/* ------------------------- GL_NV_texture_barrier ------------------------- */ + +#ifndef GL_NV_texture_barrier +#define GL_NV_texture_barrier 1 + +typedef void (GLAPIENTRY * PFNGLTEXTUREBARRIERNVPROC) (void); + +#define glTextureBarrierNV GLEW_GET_FUN(__glewTextureBarrierNV) + +#define GLEW_NV_texture_barrier GLEW_GET_VAR(__GLEW_NV_texture_barrier) + +#endif /* GL_NV_texture_barrier */ + +/* --------------------- GL_NV_texture_compression_vtc --------------------- */ + +#ifndef GL_NV_texture_compression_vtc +#define GL_NV_texture_compression_vtc 1 + +#define GLEW_NV_texture_compression_vtc GLEW_GET_VAR(__GLEW_NV_texture_compression_vtc) + +#endif /* GL_NV_texture_compression_vtc */ + +/* ----------------------- GL_NV_texture_env_combine4 ---------------------- */ + +#ifndef GL_NV_texture_env_combine4 +#define GL_NV_texture_env_combine4 1 + +#define GL_COMBINE4_NV 0x8503 +#define GL_SOURCE3_RGB_NV 0x8583 +#define GL_SOURCE3_ALPHA_NV 0x858B +#define GL_OPERAND3_RGB_NV 0x8593 +#define GL_OPERAND3_ALPHA_NV 0x859B + +#define GLEW_NV_texture_env_combine4 GLEW_GET_VAR(__GLEW_NV_texture_env_combine4) + +#endif /* GL_NV_texture_env_combine4 */ + +/* ---------------------- GL_NV_texture_expand_normal ---------------------- */ + +#ifndef GL_NV_texture_expand_normal +#define GL_NV_texture_expand_normal 1 + +#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F + +#define GLEW_NV_texture_expand_normal GLEW_GET_VAR(__GLEW_NV_texture_expand_normal) + +#endif /* GL_NV_texture_expand_normal */ + +/* ----------------------- GL_NV_texture_multisample ----------------------- */ + +#ifndef GL_NV_texture_multisample +#define GL_NV_texture_multisample 1 + +#define GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045 +#define GL_TEXTURE_COLOR_SAMPLES_NV 0x9046 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); + +#define glTexImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage2DMultisampleCoverageNV) +#define glTexImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTexImage3DMultisampleCoverageNV) +#define glTextureImage2DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage2DMultisampleCoverageNV) +#define glTextureImage2DMultisampleNV GLEW_GET_FUN(__glewTextureImage2DMultisampleNV) +#define glTextureImage3DMultisampleCoverageNV GLEW_GET_FUN(__glewTextureImage3DMultisampleCoverageNV) +#define glTextureImage3DMultisampleNV GLEW_GET_FUN(__glewTextureImage3DMultisampleNV) + +#define GLEW_NV_texture_multisample GLEW_GET_VAR(__GLEW_NV_texture_multisample) + +#endif /* GL_NV_texture_multisample */ + +/* ------------------------ GL_NV_texture_rectangle ------------------------ */ + +#ifndef GL_NV_texture_rectangle +#define GL_NV_texture_rectangle 1 + +#define GL_TEXTURE_RECTANGLE_NV 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 + +#define GLEW_NV_texture_rectangle GLEW_GET_VAR(__GLEW_NV_texture_rectangle) + +#endif /* GL_NV_texture_rectangle */ + +/* -------------------------- GL_NV_texture_shader ------------------------- */ + +#ifndef GL_NV_texture_shader +#define GL_NV_texture_shader 1 + +#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C +#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D +#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E +#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_SHADER_CONSISTENT_NV 0x86DD +#define GL_TEXTURE_SHADER_NV 0x86DE +#define GL_SHADER_OPERATION_NV 0x86DF +#define GL_CULL_MODES_NV 0x86E0 +#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3 +#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 +#define GL_CONST_EYE_NV 0x86E5 +#define GL_PASS_THROUGH_NV 0x86E6 +#define GL_CULL_FRAGMENT_NV 0x86E7 +#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 +#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 +#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA +#define GL_DOT_PRODUCT_NV 0x86EC +#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED +#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE +#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 +#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 +#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 +#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D +#define GL_HI_SCALE_NV 0x870E +#define GL_LO_SCALE_NV 0x870F +#define GL_DS_SCALE_NV 0x8710 +#define GL_DT_SCALE_NV 0x8711 +#define GL_MAGNITUDE_SCALE_NV 0x8712 +#define GL_VIBRANCE_SCALE_NV 0x8713 +#define GL_HI_BIAS_NV 0x8714 +#define GL_LO_BIAS_NV 0x8715 +#define GL_DS_BIAS_NV 0x8716 +#define GL_DT_BIAS_NV 0x8717 +#define GL_MAGNITUDE_BIAS_NV 0x8718 +#define GL_VIBRANCE_BIAS_NV 0x8719 +#define GL_TEXTURE_BORDER_VALUES_NV 0x871A +#define GL_TEXTURE_HI_SIZE_NV 0x871B +#define GL_TEXTURE_LO_SIZE_NV 0x871C +#define GL_TEXTURE_DS_SIZE_NV 0x871D +#define GL_TEXTURE_DT_SIZE_NV 0x871E +#define GL_TEXTURE_MAG_SIZE_NV 0x871F + +#define GLEW_NV_texture_shader GLEW_GET_VAR(__GLEW_NV_texture_shader) + +#endif /* GL_NV_texture_shader */ + +/* ------------------------- GL_NV_texture_shader2 ------------------------- */ + +#ifndef GL_NV_texture_shader2 +#define GL_NV_texture_shader2 1 + +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D + +#define GLEW_NV_texture_shader2 GLEW_GET_VAR(__GLEW_NV_texture_shader2) + +#endif /* GL_NV_texture_shader2 */ + +/* ------------------------- GL_NV_texture_shader3 ------------------------- */ + +#ifndef GL_NV_texture_shader3 +#define GL_NV_texture_shader3 1 + +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 +#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 +#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 +#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 +#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 +#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A +#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B +#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C +#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D +#define GL_HILO8_NV 0x885E +#define GL_SIGNED_HILO8_NV 0x885F +#define GL_FORCE_BLUE_TO_ONE_NV 0x8860 + +#define GLEW_NV_texture_shader3 GLEW_GET_VAR(__GLEW_NV_texture_shader3) + +#endif /* GL_NV_texture_shader3 */ + +/* ------------------------ GL_NV_transform_feedback ----------------------- */ + +#ifndef GL_NV_transform_feedback +#define GL_NV_transform_feedback 1 + +#define GL_BACK_PRIMARY_COLOR_NV 0x8C77 +#define GL_BACK_SECONDARY_COLOR_NV 0x8C78 +#define GL_TEXTURE_COORD_NV 0x8C79 +#define GL_CLIP_DISTANCE_NV 0x8C7A +#define GL_VERTEX_ID_NV 0x8C7B +#define GL_PRIMITIVE_ID_NV 0x8C7C +#define GL_GENERIC_ATTRIB_NV 0x8C7D +#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 +#define GL_ACTIVE_VARYINGS_NV 0x8C81 +#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 +#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 +#define GL_PRIMITIVES_GENERATED_NV 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 +#define GL_RASTERIZER_DISCARD_NV 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B +#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C +#define GL_SEPARATE_ATTRIBS_NV 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F + +typedef void (GLAPIENTRY * PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location); +typedef GLint (GLAPIENTRY * PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode); + +#define glActiveVaryingNV GLEW_GET_FUN(__glewActiveVaryingNV) +#define glBeginTransformFeedbackNV GLEW_GET_FUN(__glewBeginTransformFeedbackNV) +#define glBindBufferBaseNV GLEW_GET_FUN(__glewBindBufferBaseNV) +#define glBindBufferOffsetNV GLEW_GET_FUN(__glewBindBufferOffsetNV) +#define glBindBufferRangeNV GLEW_GET_FUN(__glewBindBufferRangeNV) +#define glEndTransformFeedbackNV GLEW_GET_FUN(__glewEndTransformFeedbackNV) +#define glGetActiveVaryingNV GLEW_GET_FUN(__glewGetActiveVaryingNV) +#define glGetTransformFeedbackVaryingNV GLEW_GET_FUN(__glewGetTransformFeedbackVaryingNV) +#define glGetVaryingLocationNV GLEW_GET_FUN(__glewGetVaryingLocationNV) +#define glTransformFeedbackAttribsNV GLEW_GET_FUN(__glewTransformFeedbackAttribsNV) +#define glTransformFeedbackVaryingsNV GLEW_GET_FUN(__glewTransformFeedbackVaryingsNV) + +#define GLEW_NV_transform_feedback GLEW_GET_VAR(__GLEW_NV_transform_feedback) + +#endif /* GL_NV_transform_feedback */ + +/* ----------------------- GL_NV_transform_feedback2 ----------------------- */ + +#ifndef GL_NV_transform_feedback2 +#define GL_NV_transform_feedback2 1 + +#define GL_TRANSFORM_FEEDBACK_NV 0x8E22 +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25 + +typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id); +typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint* ids); +typedef GLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void); + +#define glBindTransformFeedbackNV GLEW_GET_FUN(__glewBindTransformFeedbackNV) +#define glDeleteTransformFeedbacksNV GLEW_GET_FUN(__glewDeleteTransformFeedbacksNV) +#define glDrawTransformFeedbackNV GLEW_GET_FUN(__glewDrawTransformFeedbackNV) +#define glGenTransformFeedbacksNV GLEW_GET_FUN(__glewGenTransformFeedbacksNV) +#define glIsTransformFeedbackNV GLEW_GET_FUN(__glewIsTransformFeedbackNV) +#define glPauseTransformFeedbackNV GLEW_GET_FUN(__glewPauseTransformFeedbackNV) +#define glResumeTransformFeedbackNV GLEW_GET_FUN(__glewResumeTransformFeedbackNV) + +#define GLEW_NV_transform_feedback2 GLEW_GET_VAR(__GLEW_NV_transform_feedback2) + +#endif /* GL_NV_transform_feedback2 */ + +/* -------------------------- GL_NV_vdpau_interop -------------------------- */ + +#ifndef GL_NV_vdpau_interop +#define GL_NV_vdpau_interop 1 + +#define GL_SURFACE_STATE_NV 0x86EB +#define GL_SURFACE_REGISTERED_NV 0x86FD +#define GL_SURFACE_MAPPED_NV 0x8700 +#define GL_WRITE_DISCARD_NV 0x88BE + +typedef GLintptr GLvdpauSurfaceNV; + +typedef void (GLAPIENTRY * PFNGLVDPAUFININVPROC) (void); +typedef void (GLAPIENTRY * PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei* length, GLint *values); +typedef void (GLAPIENTRY * PFNGLVDPAUINITNVPROC) (const void* vdpDevice, const GLvoid*getProcAddress); +typedef void (GLAPIENTRY * PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface); +typedef void (GLAPIENTRY * PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV* surfaces); +typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); +typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); +typedef void (GLAPIENTRY * PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access); +typedef void (GLAPIENTRY * PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV* surfaces); +typedef void (GLAPIENTRY * PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface); + +#define glVDPAUFiniNV GLEW_GET_FUN(__glewVDPAUFiniNV) +#define glVDPAUGetSurfaceivNV GLEW_GET_FUN(__glewVDPAUGetSurfaceivNV) +#define glVDPAUInitNV GLEW_GET_FUN(__glewVDPAUInitNV) +#define glVDPAUIsSurfaceNV GLEW_GET_FUN(__glewVDPAUIsSurfaceNV) +#define glVDPAUMapSurfacesNV GLEW_GET_FUN(__glewVDPAUMapSurfacesNV) +#define glVDPAURegisterOutputSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterOutputSurfaceNV) +#define glVDPAURegisterVideoSurfaceNV GLEW_GET_FUN(__glewVDPAURegisterVideoSurfaceNV) +#define glVDPAUSurfaceAccessNV GLEW_GET_FUN(__glewVDPAUSurfaceAccessNV) +#define glVDPAUUnmapSurfacesNV GLEW_GET_FUN(__glewVDPAUUnmapSurfacesNV) +#define glVDPAUUnregisterSurfaceNV GLEW_GET_FUN(__glewVDPAUUnregisterSurfaceNV) + +#define GLEW_NV_vdpau_interop GLEW_GET_VAR(__GLEW_NV_vdpau_interop) + +#endif /* GL_NV_vdpau_interop */ + +/* ------------------------ GL_NV_vertex_array_range ----------------------- */ + +#ifndef GL_NV_vertex_array_range +#define GL_NV_vertex_array_range 1 + +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 + +typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void* pointer); + +#define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV) +#define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV) + +#define GLEW_NV_vertex_array_range GLEW_GET_VAR(__GLEW_NV_vertex_array_range) + +#endif /* GL_NV_vertex_array_range */ + +/* ----------------------- GL_NV_vertex_array_range2 ----------------------- */ + +#ifndef GL_NV_vertex_array_range2 +#define GL_NV_vertex_array_range2 1 + +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 + +#define GLEW_NV_vertex_array_range2 GLEW_GET_VAR(__GLEW_NV_vertex_array_range2) + +#endif /* GL_NV_vertex_array_range2 */ + +/* ------------------- GL_NV_vertex_attrib_integer_64bit ------------------- */ + +#ifndef GL_NV_vertex_attrib_integer_64bit +#define GL_NV_vertex_attrib_integer_64bit 1 + +#define GL_INT64_NV 0x140E +#define GL_UNSIGNED_INT64_NV 0x140F + +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT* params); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); + +#define glGetVertexAttribLi64vNV GLEW_GET_FUN(__glewGetVertexAttribLi64vNV) +#define glGetVertexAttribLui64vNV GLEW_GET_FUN(__glewGetVertexAttribLui64vNV) +#define glVertexAttribL1i64NV GLEW_GET_FUN(__glewVertexAttribL1i64NV) +#define glVertexAttribL1i64vNV GLEW_GET_FUN(__glewVertexAttribL1i64vNV) +#define glVertexAttribL1ui64NV GLEW_GET_FUN(__glewVertexAttribL1ui64NV) +#define glVertexAttribL1ui64vNV GLEW_GET_FUN(__glewVertexAttribL1ui64vNV) +#define glVertexAttribL2i64NV GLEW_GET_FUN(__glewVertexAttribL2i64NV) +#define glVertexAttribL2i64vNV GLEW_GET_FUN(__glewVertexAttribL2i64vNV) +#define glVertexAttribL2ui64NV GLEW_GET_FUN(__glewVertexAttribL2ui64NV) +#define glVertexAttribL2ui64vNV GLEW_GET_FUN(__glewVertexAttribL2ui64vNV) +#define glVertexAttribL3i64NV GLEW_GET_FUN(__glewVertexAttribL3i64NV) +#define glVertexAttribL3i64vNV GLEW_GET_FUN(__glewVertexAttribL3i64vNV) +#define glVertexAttribL3ui64NV GLEW_GET_FUN(__glewVertexAttribL3ui64NV) +#define glVertexAttribL3ui64vNV GLEW_GET_FUN(__glewVertexAttribL3ui64vNV) +#define glVertexAttribL4i64NV GLEW_GET_FUN(__glewVertexAttribL4i64NV) +#define glVertexAttribL4i64vNV GLEW_GET_FUN(__glewVertexAttribL4i64vNV) +#define glVertexAttribL4ui64NV GLEW_GET_FUN(__glewVertexAttribL4ui64NV) +#define glVertexAttribL4ui64vNV GLEW_GET_FUN(__glewVertexAttribL4ui64vNV) +#define glVertexAttribLFormatNV GLEW_GET_FUN(__glewVertexAttribLFormatNV) + +#define GLEW_NV_vertex_attrib_integer_64bit GLEW_GET_VAR(__GLEW_NV_vertex_attrib_integer_64bit) + +#endif /* GL_NV_vertex_attrib_integer_64bit */ + +/* ------------------- GL_NV_vertex_buffer_unified_memory ------------------ */ + +#ifndef GL_NV_vertex_buffer_unified_memory +#define GL_NV_vertex_buffer_unified_memory 1 + +#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E +#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F +#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20 +#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21 +#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22 +#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23 +#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24 +#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25 +#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26 +#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27 +#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28 +#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29 +#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A +#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B +#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C +#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D +#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E +#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F +#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30 +#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31 +#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32 +#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33 +#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40 +#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41 +#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42 + +typedef void (GLAPIENTRY * PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length); +typedef void (GLAPIENTRY * PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride); +typedef void (GLAPIENTRY * PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT result[]); +typedef void (GLAPIENTRY * PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride); + +#define glBufferAddressRangeNV GLEW_GET_FUN(__glewBufferAddressRangeNV) +#define glColorFormatNV GLEW_GET_FUN(__glewColorFormatNV) +#define glEdgeFlagFormatNV GLEW_GET_FUN(__glewEdgeFlagFormatNV) +#define glFogCoordFormatNV GLEW_GET_FUN(__glewFogCoordFormatNV) +#define glGetIntegerui64i_vNV GLEW_GET_FUN(__glewGetIntegerui64i_vNV) +#define glIndexFormatNV GLEW_GET_FUN(__glewIndexFormatNV) +#define glNormalFormatNV GLEW_GET_FUN(__glewNormalFormatNV) +#define glSecondaryColorFormatNV GLEW_GET_FUN(__glewSecondaryColorFormatNV) +#define glTexCoordFormatNV GLEW_GET_FUN(__glewTexCoordFormatNV) +#define glVertexAttribFormatNV GLEW_GET_FUN(__glewVertexAttribFormatNV) +#define glVertexAttribIFormatNV GLEW_GET_FUN(__glewVertexAttribIFormatNV) +#define glVertexFormatNV GLEW_GET_FUN(__glewVertexFormatNV) + +#define GLEW_NV_vertex_buffer_unified_memory GLEW_GET_VAR(__GLEW_NV_vertex_buffer_unified_memory) + +#endif /* GL_NV_vertex_buffer_unified_memory */ + +/* -------------------------- GL_NV_vertex_program ------------------------- */ + +#ifndef GL_NV_vertex_program +#define GL_NV_vertex_program 1 + +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_IDENTITY_NV 0x862A +#define GL_INVERSE_NV 0x862B +#define GL_TRANSPOSE_NV 0x862C +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_NV 0x8637 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F + +typedef GLboolean (GLAPIENTRY * PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint* ids, GLboolean *residences); +typedef void (GLAPIENTRY * PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte* program); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid** pointer); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMNVPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte* program); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei num, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei n, const GLubyte* v); + +#define glAreProgramsResidentNV GLEW_GET_FUN(__glewAreProgramsResidentNV) +#define glBindProgramNV GLEW_GET_FUN(__glewBindProgramNV) +#define glDeleteProgramsNV GLEW_GET_FUN(__glewDeleteProgramsNV) +#define glExecuteProgramNV GLEW_GET_FUN(__glewExecuteProgramNV) +#define glGenProgramsNV GLEW_GET_FUN(__glewGenProgramsNV) +#define glGetProgramParameterdvNV GLEW_GET_FUN(__glewGetProgramParameterdvNV) +#define glGetProgramParameterfvNV GLEW_GET_FUN(__glewGetProgramParameterfvNV) +#define glGetProgramStringNV GLEW_GET_FUN(__glewGetProgramStringNV) +#define glGetProgramivNV GLEW_GET_FUN(__glewGetProgramivNV) +#define glGetTrackMatrixivNV GLEW_GET_FUN(__glewGetTrackMatrixivNV) +#define glGetVertexAttribPointervNV GLEW_GET_FUN(__glewGetVertexAttribPointervNV) +#define glGetVertexAttribdvNV GLEW_GET_FUN(__glewGetVertexAttribdvNV) +#define glGetVertexAttribfvNV GLEW_GET_FUN(__glewGetVertexAttribfvNV) +#define glGetVertexAttribivNV GLEW_GET_FUN(__glewGetVertexAttribivNV) +#define glIsProgramNV GLEW_GET_FUN(__glewIsProgramNV) +#define glLoadProgramNV GLEW_GET_FUN(__glewLoadProgramNV) +#define glProgramParameter4dNV GLEW_GET_FUN(__glewProgramParameter4dNV) +#define glProgramParameter4dvNV GLEW_GET_FUN(__glewProgramParameter4dvNV) +#define glProgramParameter4fNV GLEW_GET_FUN(__glewProgramParameter4fNV) +#define glProgramParameter4fvNV GLEW_GET_FUN(__glewProgramParameter4fvNV) +#define glProgramParameters4dvNV GLEW_GET_FUN(__glewProgramParameters4dvNV) +#define glProgramParameters4fvNV GLEW_GET_FUN(__glewProgramParameters4fvNV) +#define glRequestResidentProgramsNV GLEW_GET_FUN(__glewRequestResidentProgramsNV) +#define glTrackMatrixNV GLEW_GET_FUN(__glewTrackMatrixNV) +#define glVertexAttrib1dNV GLEW_GET_FUN(__glewVertexAttrib1dNV) +#define glVertexAttrib1dvNV GLEW_GET_FUN(__glewVertexAttrib1dvNV) +#define glVertexAttrib1fNV GLEW_GET_FUN(__glewVertexAttrib1fNV) +#define glVertexAttrib1fvNV GLEW_GET_FUN(__glewVertexAttrib1fvNV) +#define glVertexAttrib1sNV GLEW_GET_FUN(__glewVertexAttrib1sNV) +#define glVertexAttrib1svNV GLEW_GET_FUN(__glewVertexAttrib1svNV) +#define glVertexAttrib2dNV GLEW_GET_FUN(__glewVertexAttrib2dNV) +#define glVertexAttrib2dvNV GLEW_GET_FUN(__glewVertexAttrib2dvNV) +#define glVertexAttrib2fNV GLEW_GET_FUN(__glewVertexAttrib2fNV) +#define glVertexAttrib2fvNV GLEW_GET_FUN(__glewVertexAttrib2fvNV) +#define glVertexAttrib2sNV GLEW_GET_FUN(__glewVertexAttrib2sNV) +#define glVertexAttrib2svNV GLEW_GET_FUN(__glewVertexAttrib2svNV) +#define glVertexAttrib3dNV GLEW_GET_FUN(__glewVertexAttrib3dNV) +#define glVertexAttrib3dvNV GLEW_GET_FUN(__glewVertexAttrib3dvNV) +#define glVertexAttrib3fNV GLEW_GET_FUN(__glewVertexAttrib3fNV) +#define glVertexAttrib3fvNV GLEW_GET_FUN(__glewVertexAttrib3fvNV) +#define glVertexAttrib3sNV GLEW_GET_FUN(__glewVertexAttrib3sNV) +#define glVertexAttrib3svNV GLEW_GET_FUN(__glewVertexAttrib3svNV) +#define glVertexAttrib4dNV GLEW_GET_FUN(__glewVertexAttrib4dNV) +#define glVertexAttrib4dvNV GLEW_GET_FUN(__glewVertexAttrib4dvNV) +#define glVertexAttrib4fNV GLEW_GET_FUN(__glewVertexAttrib4fNV) +#define glVertexAttrib4fvNV GLEW_GET_FUN(__glewVertexAttrib4fvNV) +#define glVertexAttrib4sNV GLEW_GET_FUN(__glewVertexAttrib4sNV) +#define glVertexAttrib4svNV GLEW_GET_FUN(__glewVertexAttrib4svNV) +#define glVertexAttrib4ubNV GLEW_GET_FUN(__glewVertexAttrib4ubNV) +#define glVertexAttrib4ubvNV GLEW_GET_FUN(__glewVertexAttrib4ubvNV) +#define glVertexAttribPointerNV GLEW_GET_FUN(__glewVertexAttribPointerNV) +#define glVertexAttribs1dvNV GLEW_GET_FUN(__glewVertexAttribs1dvNV) +#define glVertexAttribs1fvNV GLEW_GET_FUN(__glewVertexAttribs1fvNV) +#define glVertexAttribs1svNV GLEW_GET_FUN(__glewVertexAttribs1svNV) +#define glVertexAttribs2dvNV GLEW_GET_FUN(__glewVertexAttribs2dvNV) +#define glVertexAttribs2fvNV GLEW_GET_FUN(__glewVertexAttribs2fvNV) +#define glVertexAttribs2svNV GLEW_GET_FUN(__glewVertexAttribs2svNV) +#define glVertexAttribs3dvNV GLEW_GET_FUN(__glewVertexAttribs3dvNV) +#define glVertexAttribs3fvNV GLEW_GET_FUN(__glewVertexAttribs3fvNV) +#define glVertexAttribs3svNV GLEW_GET_FUN(__glewVertexAttribs3svNV) +#define glVertexAttribs4dvNV GLEW_GET_FUN(__glewVertexAttribs4dvNV) +#define glVertexAttribs4fvNV GLEW_GET_FUN(__glewVertexAttribs4fvNV) +#define glVertexAttribs4svNV GLEW_GET_FUN(__glewVertexAttribs4svNV) +#define glVertexAttribs4ubvNV GLEW_GET_FUN(__glewVertexAttribs4ubvNV) + +#define GLEW_NV_vertex_program GLEW_GET_VAR(__GLEW_NV_vertex_program) + +#endif /* GL_NV_vertex_program */ + +/* ------------------------ GL_NV_vertex_program1_1 ------------------------ */ + +#ifndef GL_NV_vertex_program1_1 +#define GL_NV_vertex_program1_1 1 + +#define GLEW_NV_vertex_program1_1 GLEW_GET_VAR(__GLEW_NV_vertex_program1_1) + +#endif /* GL_NV_vertex_program1_1 */ + +/* ------------------------- GL_NV_vertex_program2 ------------------------- */ + +#ifndef GL_NV_vertex_program2 +#define GL_NV_vertex_program2 1 + +#define GLEW_NV_vertex_program2 GLEW_GET_VAR(__GLEW_NV_vertex_program2) + +#endif /* GL_NV_vertex_program2 */ + +/* ---------------------- GL_NV_vertex_program2_option --------------------- */ + +#ifndef GL_NV_vertex_program2_option +#define GL_NV_vertex_program2_option 1 + +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 + +#define GLEW_NV_vertex_program2_option GLEW_GET_VAR(__GLEW_NV_vertex_program2_option) + +#endif /* GL_NV_vertex_program2_option */ + +/* ------------------------- GL_NV_vertex_program3 ------------------------- */ + +#ifndef GL_NV_vertex_program3 +#define GL_NV_vertex_program3 1 + +#define MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C + +#define GLEW_NV_vertex_program3 GLEW_GET_VAR(__GLEW_NV_vertex_program3) + +#endif /* GL_NV_vertex_program3 */ + +/* ------------------------- GL_NV_vertex_program4 ------------------------- */ + +#ifndef GL_NV_vertex_program4 +#define GL_NV_vertex_program4 1 + +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD + +#define GLEW_NV_vertex_program4 GLEW_GET_VAR(__GLEW_NV_vertex_program4) + +#endif /* GL_NV_vertex_program4 */ + +/* -------------------------- GL_NV_video_capture -------------------------- */ + +#ifndef GL_NV_video_capture +#define GL_NV_video_capture 1 + +#define GL_VIDEO_BUFFER_NV 0x9020 +#define GL_VIDEO_BUFFER_BINDING_NV 0x9021 +#define GL_FIELD_UPPER_NV 0x9022 +#define GL_FIELD_LOWER_NV 0x9023 +#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024 +#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025 +#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026 +#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027 +#define GL_VIDEO_BUFFER_PITCH_NV 0x9028 +#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029 +#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A +#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B +#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C +#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D +#define GL_PARTIAL_SUCCESS_NV 0x902E +#define GL_SUCCESS_NV 0x902F +#define GL_FAILURE_NV 0x9030 +#define GL_YCBYCR8_422_NV 0x9031 +#define GL_YCBAYCR8A_4224_NV 0x9032 +#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033 +#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034 +#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035 +#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036 +#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037 +#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038 +#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039 +#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A +#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B +#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C + +typedef void (GLAPIENTRY * PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot); +typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset); +typedef void (GLAPIENTRY * PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture); +typedef void (GLAPIENTRY * PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint* params); +typedef GLenum (GLAPIENTRY * PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint* sequence_num, GLuint64EXT *capture_time); +typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble* params); +typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint* params); + +#define glBeginVideoCaptureNV GLEW_GET_FUN(__glewBeginVideoCaptureNV) +#define glBindVideoCaptureStreamBufferNV GLEW_GET_FUN(__glewBindVideoCaptureStreamBufferNV) +#define glBindVideoCaptureStreamTextureNV GLEW_GET_FUN(__glewBindVideoCaptureStreamTextureNV) +#define glEndVideoCaptureNV GLEW_GET_FUN(__glewEndVideoCaptureNV) +#define glGetVideoCaptureStreamdvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamdvNV) +#define glGetVideoCaptureStreamfvNV GLEW_GET_FUN(__glewGetVideoCaptureStreamfvNV) +#define glGetVideoCaptureStreamivNV GLEW_GET_FUN(__glewGetVideoCaptureStreamivNV) +#define glGetVideoCaptureivNV GLEW_GET_FUN(__glewGetVideoCaptureivNV) +#define glVideoCaptureNV GLEW_GET_FUN(__glewVideoCaptureNV) +#define glVideoCaptureStreamParameterdvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterdvNV) +#define glVideoCaptureStreamParameterfvNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterfvNV) +#define glVideoCaptureStreamParameterivNV GLEW_GET_FUN(__glewVideoCaptureStreamParameterivNV) + +#define GLEW_NV_video_capture GLEW_GET_VAR(__GLEW_NV_video_capture) + +#endif /* GL_NV_video_capture */ + +/* ------------------------ GL_OES_byte_coordinates ------------------------ */ + +#ifndef GL_OES_byte_coordinates +#define GL_OES_byte_coordinates 1 + +#define GL_BYTE 0x1400 + +#define GLEW_OES_byte_coordinates GLEW_GET_VAR(__GLEW_OES_byte_coordinates) + +#endif /* GL_OES_byte_coordinates */ + +/* ------------------- GL_OES_compressed_paletted_texture ------------------ */ + +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 + +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 + +#define GLEW_OES_compressed_paletted_texture GLEW_GET_VAR(__GLEW_OES_compressed_paletted_texture) + +#endif /* GL_OES_compressed_paletted_texture */ + +/* --------------------------- GL_OES_read_format -------------------------- */ + +#ifndef GL_OES_read_format +#define GL_OES_read_format 1 + +#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B + +#define GLEW_OES_read_format GLEW_GET_VAR(__GLEW_OES_read_format) + +#endif /* GL_OES_read_format */ + +/* ------------------------ GL_OES_single_precision ------------------------ */ + +#ifndef GL_OES_single_precision +#define GL_OES_single_precision 1 + +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFOESPROC) (GLclampd depth); +typedef void (GLAPIENTRY * PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat* equation); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f); +typedef void (GLAPIENTRY * PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); +typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat* equation); +typedef void (GLAPIENTRY * PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); + +#define glClearDepthfOES GLEW_GET_FUN(__glewClearDepthfOES) +#define glClipPlanefOES GLEW_GET_FUN(__glewClipPlanefOES) +#define glDepthRangefOES GLEW_GET_FUN(__glewDepthRangefOES) +#define glFrustumfOES GLEW_GET_FUN(__glewFrustumfOES) +#define glGetClipPlanefOES GLEW_GET_FUN(__glewGetClipPlanefOES) +#define glOrthofOES GLEW_GET_FUN(__glewOrthofOES) + +#define GLEW_OES_single_precision GLEW_GET_VAR(__GLEW_OES_single_precision) + +#endif /* GL_OES_single_precision */ + +/* ---------------------------- GL_OML_interlace --------------------------- */ + +#ifndef GL_OML_interlace +#define GL_OML_interlace 1 + +#define GL_INTERLACE_OML 0x8980 +#define GL_INTERLACE_READ_OML 0x8981 + +#define GLEW_OML_interlace GLEW_GET_VAR(__GLEW_OML_interlace) + +#endif /* GL_OML_interlace */ + +/* ---------------------------- GL_OML_resample ---------------------------- */ + +#ifndef GL_OML_resample +#define GL_OML_resample 1 + +#define GL_PACK_RESAMPLE_OML 0x8984 +#define GL_UNPACK_RESAMPLE_OML 0x8985 +#define GL_RESAMPLE_REPLICATE_OML 0x8986 +#define GL_RESAMPLE_ZERO_FILL_OML 0x8987 +#define GL_RESAMPLE_AVERAGE_OML 0x8988 +#define GL_RESAMPLE_DECIMATE_OML 0x8989 + +#define GLEW_OML_resample GLEW_GET_VAR(__GLEW_OML_resample) + +#endif /* GL_OML_resample */ + +/* ---------------------------- GL_OML_subsample --------------------------- */ + +#ifndef GL_OML_subsample +#define GL_OML_subsample 1 + +#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 +#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 + +#define GLEW_OML_subsample GLEW_GET_VAR(__GLEW_OML_subsample) + +#endif /* GL_OML_subsample */ + +/* --------------------------- GL_PGI_misc_hints --------------------------- */ + +#ifndef GL_PGI_misc_hints +#define GL_PGI_misc_hints 1 + +#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 107000 +#define GL_CONSERVE_MEMORY_HINT_PGI 107005 +#define GL_RECLAIM_MEMORY_HINT_PGI 107006 +#define GL_NATIVE_GRAPHICS_HANDLE_PGI 107010 +#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 107011 +#define GL_NATIVE_GRAPHICS_END_HINT_PGI 107012 +#define GL_ALWAYS_FAST_HINT_PGI 107020 +#define GL_ALWAYS_SOFT_HINT_PGI 107021 +#define GL_ALLOW_DRAW_OBJ_HINT_PGI 107022 +#define GL_ALLOW_DRAW_WIN_HINT_PGI 107023 +#define GL_ALLOW_DRAW_FRG_HINT_PGI 107024 +#define GL_ALLOW_DRAW_MEM_HINT_PGI 107025 +#define GL_STRICT_DEPTHFUNC_HINT_PGI 107030 +#define GL_STRICT_LIGHTING_HINT_PGI 107031 +#define GL_STRICT_SCISSOR_HINT_PGI 107032 +#define GL_FULL_STIPPLE_HINT_PGI 107033 +#define GL_CLIP_NEAR_HINT_PGI 107040 +#define GL_CLIP_FAR_HINT_PGI 107041 +#define GL_WIDE_LINE_HINT_PGI 107042 +#define GL_BACK_NORMALS_HINT_PGI 107043 + +#define GLEW_PGI_misc_hints GLEW_GET_VAR(__GLEW_PGI_misc_hints) + +#endif /* GL_PGI_misc_hints */ + +/* -------------------------- GL_PGI_vertex_hints -------------------------- */ + +#ifndef GL_PGI_vertex_hints +#define GL_PGI_vertex_hints 1 + +#define GL_VERTEX23_BIT_PGI 0x00000004 +#define GL_VERTEX4_BIT_PGI 0x00000008 +#define GL_COLOR3_BIT_PGI 0x00010000 +#define GL_COLOR4_BIT_PGI 0x00020000 +#define GL_EDGEFLAG_BIT_PGI 0x00040000 +#define GL_INDEX_BIT_PGI 0x00080000 +#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 +#define GL_VERTEX_DATA_HINT_PGI 107050 +#define GL_VERTEX_CONSISTENT_HINT_PGI 107051 +#define GL_MATERIAL_SIDE_HINT_PGI 107052 +#define GL_MAX_VERTEX_HINT_PGI 107053 +#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 +#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 +#define GL_MAT_EMISSION_BIT_PGI 0x00800000 +#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 +#define GL_MAT_SHININESS_BIT_PGI 0x02000000 +#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 +#define GL_NORMAL_BIT_PGI 0x08000000 +#define GL_TEXCOORD1_BIT_PGI 0x10000000 +#define GL_TEXCOORD2_BIT_PGI 0x20000000 +#define GL_TEXCOORD3_BIT_PGI 0x40000000 +#define GL_TEXCOORD4_BIT_PGI 0x80000000 + +#define GLEW_PGI_vertex_hints GLEW_GET_VAR(__GLEW_PGI_vertex_hints) + +#endif /* GL_PGI_vertex_hints */ + +/* ----------------------- GL_REND_screen_coordinates ---------------------- */ + +#ifndef GL_REND_screen_coordinates +#define GL_REND_screen_coordinates 1 + +#define GL_SCREEN_COORDINATES_REND 0x8490 +#define GL_INVERTED_SCREEN_W_REND 0x8491 + +#define GLEW_REND_screen_coordinates GLEW_GET_VAR(__GLEW_REND_screen_coordinates) + +#endif /* GL_REND_screen_coordinates */ + +/* ------------------------------- GL_S3_s3tc ------------------------------ */ + +#ifndef GL_S3_s3tc +#define GL_S3_s3tc 1 + +#define GL_RGB_S3TC 0x83A0 +#define GL_RGB4_S3TC 0x83A1 +#define GL_RGBA_S3TC 0x83A2 +#define GL_RGBA4_S3TC 0x83A3 +#define GL_RGBA_DXT5_S3TC 0x83A4 +#define GL_RGBA4_DXT5_S3TC 0x83A5 + +#define GLEW_S3_s3tc GLEW_GET_VAR(__GLEW_S3_s3tc) + +#endif /* GL_S3_s3tc */ + +/* -------------------------- GL_SGIS_color_range -------------------------- */ + +#ifndef GL_SGIS_color_range +#define GL_SGIS_color_range 1 + +#define GL_EXTENDED_RANGE_SGIS 0x85A5 +#define GL_MIN_RED_SGIS 0x85A6 +#define GL_MAX_RED_SGIS 0x85A7 +#define GL_MIN_GREEN_SGIS 0x85A8 +#define GL_MAX_GREEN_SGIS 0x85A9 +#define GL_MIN_BLUE_SGIS 0x85AA +#define GL_MAX_BLUE_SGIS 0x85AB +#define GL_MIN_ALPHA_SGIS 0x85AC +#define GL_MAX_ALPHA_SGIS 0x85AD + +#define GLEW_SGIS_color_range GLEW_GET_VAR(__GLEW_SGIS_color_range) + +#endif /* GL_SGIS_color_range */ + +/* ------------------------- GL_SGIS_detail_texture ------------------------ */ + +#ifndef GL_SGIS_detail_texture +#define GL_SGIS_detail_texture 1 + +typedef void (GLAPIENTRY * PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat* points); + +#define glDetailTexFuncSGIS GLEW_GET_FUN(__glewDetailTexFuncSGIS) +#define glGetDetailTexFuncSGIS GLEW_GET_FUN(__glewGetDetailTexFuncSGIS) + +#define GLEW_SGIS_detail_texture GLEW_GET_VAR(__GLEW_SGIS_detail_texture) + +#endif /* GL_SGIS_detail_texture */ + +/* -------------------------- GL_SGIS_fog_function ------------------------- */ + +#ifndef GL_SGIS_fog_function +#define GL_SGIS_fog_function 1 + +typedef void (GLAPIENTRY * PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat* points); +typedef void (GLAPIENTRY * PFNGLGETFOGFUNCSGISPROC) (GLfloat* points); + +#define glFogFuncSGIS GLEW_GET_FUN(__glewFogFuncSGIS) +#define glGetFogFuncSGIS GLEW_GET_FUN(__glewGetFogFuncSGIS) + +#define GLEW_SGIS_fog_function GLEW_GET_VAR(__GLEW_SGIS_fog_function) + +#endif /* GL_SGIS_fog_function */ + +/* ------------------------ GL_SGIS_generate_mipmap ------------------------ */ + +#ifndef GL_SGIS_generate_mipmap +#define GL_SGIS_generate_mipmap 1 + +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 + +#define GLEW_SGIS_generate_mipmap GLEW_GET_VAR(__GLEW_SGIS_generate_mipmap) + +#endif /* GL_SGIS_generate_mipmap */ + +/* -------------------------- GL_SGIS_multisample -------------------------- */ + +#ifndef GL_SGIS_multisample +#define GL_SGIS_multisample 1 + +#define GL_MULTISAMPLE_SGIS 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F +#define GL_SAMPLE_MASK_SGIS 0x80A0 +#define GL_1PASS_SGIS 0x80A1 +#define GL_2PASS_0_SGIS 0x80A2 +#define GL_2PASS_1_SGIS 0x80A3 +#define GL_4PASS_0_SGIS 0x80A4 +#define GL_4PASS_1_SGIS 0x80A5 +#define GL_4PASS_2_SGIS 0x80A6 +#define GL_4PASS_3_SGIS 0x80A7 +#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 +#define GL_SAMPLES_SGIS 0x80A9 +#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA +#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB +#define GL_SAMPLE_PATTERN_SGIS 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 + +typedef void (GLAPIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); +typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); + +#define glSampleMaskSGIS GLEW_GET_FUN(__glewSampleMaskSGIS) +#define glSamplePatternSGIS GLEW_GET_FUN(__glewSamplePatternSGIS) + +#define GLEW_SGIS_multisample GLEW_GET_VAR(__GLEW_SGIS_multisample) + +#endif /* GL_SGIS_multisample */ + +/* ------------------------- GL_SGIS_pixel_texture ------------------------- */ + +#ifndef GL_SGIS_pixel_texture +#define GL_SGIS_pixel_texture 1 + +#define GLEW_SGIS_pixel_texture GLEW_GET_VAR(__GLEW_SGIS_pixel_texture) + +#endif /* GL_SGIS_pixel_texture */ + +/* ----------------------- GL_SGIS_point_line_texgen ----------------------- */ + +#ifndef GL_SGIS_point_line_texgen +#define GL_SGIS_point_line_texgen 1 + +#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 +#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 +#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 +#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 +#define GL_EYE_POINT_SGIS 0x81F4 +#define GL_OBJECT_POINT_SGIS 0x81F5 +#define GL_EYE_LINE_SGIS 0x81F6 +#define GL_OBJECT_LINE_SGIS 0x81F7 + +#define GLEW_SGIS_point_line_texgen GLEW_GET_VAR(__GLEW_SGIS_point_line_texgen) + +#endif /* GL_SGIS_point_line_texgen */ + +/* ------------------------ GL_SGIS_sharpen_texture ------------------------ */ + +#ifndef GL_SGIS_sharpen_texture +#define GL_SGIS_sharpen_texture 1 + +typedef void (GLAPIENTRY * PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat* points); +typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat* points); + +#define glGetSharpenTexFuncSGIS GLEW_GET_FUN(__glewGetSharpenTexFuncSGIS) +#define glSharpenTexFuncSGIS GLEW_GET_FUN(__glewSharpenTexFuncSGIS) + +#define GLEW_SGIS_sharpen_texture GLEW_GET_VAR(__GLEW_SGIS_sharpen_texture) + +#endif /* GL_SGIS_sharpen_texture */ + +/* --------------------------- GL_SGIS_texture4D --------------------------- */ + +#ifndef GL_SGIS_texture4D +#define GL_SGIS_texture4D 1 + +typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void* pixels); + +#define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS) +#define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS) + +#define GLEW_SGIS_texture4D GLEW_GET_VAR(__GLEW_SGIS_texture4D) + +#endif /* GL_SGIS_texture4D */ + +/* ---------------------- GL_SGIS_texture_border_clamp --------------------- */ + +#ifndef GL_SGIS_texture_border_clamp +#define GL_SGIS_texture_border_clamp 1 + +#define GL_CLAMP_TO_BORDER_SGIS 0x812D + +#define GLEW_SGIS_texture_border_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_border_clamp) + +#endif /* GL_SGIS_texture_border_clamp */ + +/* ----------------------- GL_SGIS_texture_edge_clamp ---------------------- */ + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_SGIS_texture_edge_clamp 1 + +#define GL_CLAMP_TO_EDGE_SGIS 0x812F + +#define GLEW_SGIS_texture_edge_clamp GLEW_GET_VAR(__GLEW_SGIS_texture_edge_clamp) + +#endif /* GL_SGIS_texture_edge_clamp */ + +/* ------------------------ GL_SGIS_texture_filter4 ------------------------ */ + +#ifndef GL_SGIS_texture_filter4 +#define GL_SGIS_texture_filter4 1 + +typedef void (GLAPIENTRY * PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat* weights); +typedef void (GLAPIENTRY * PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat* weights); + +#define glGetTexFilterFuncSGIS GLEW_GET_FUN(__glewGetTexFilterFuncSGIS) +#define glTexFilterFuncSGIS GLEW_GET_FUN(__glewTexFilterFuncSGIS) + +#define GLEW_SGIS_texture_filter4 GLEW_GET_VAR(__GLEW_SGIS_texture_filter4) + +#endif /* GL_SGIS_texture_filter4 */ + +/* -------------------------- GL_SGIS_texture_lod -------------------------- */ + +#ifndef GL_SGIS_texture_lod +#define GL_SGIS_texture_lod 1 + +#define GL_TEXTURE_MIN_LOD_SGIS 0x813A +#define GL_TEXTURE_MAX_LOD_SGIS 0x813B +#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C +#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D + +#define GLEW_SGIS_texture_lod GLEW_GET_VAR(__GLEW_SGIS_texture_lod) + +#endif /* GL_SGIS_texture_lod */ + +/* ------------------------- GL_SGIS_texture_select ------------------------ */ + +#ifndef GL_SGIS_texture_select +#define GL_SGIS_texture_select 1 + +#define GLEW_SGIS_texture_select GLEW_GET_VAR(__GLEW_SGIS_texture_select) + +#endif /* GL_SGIS_texture_select */ + +/* ----------------------------- GL_SGIX_async ----------------------------- */ + +#ifndef GL_SGIX_async +#define GL_SGIX_async 1 + +#define GL_ASYNC_MARKER_SGIX 0x8329 + +typedef void (GLAPIENTRY * PFNGLASYNCMARKERSGIXPROC) (GLuint marker); +typedef void (GLAPIENTRY * PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); +typedef GLint (GLAPIENTRY * PFNGLFINISHASYNCSGIXPROC) (GLuint* markerp); +typedef GLuint (GLAPIENTRY * PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); +typedef GLboolean (GLAPIENTRY * PFNGLISASYNCMARKERSGIXPROC) (GLuint marker); +typedef GLint (GLAPIENTRY * PFNGLPOLLASYNCSGIXPROC) (GLuint* markerp); + +#define glAsyncMarkerSGIX GLEW_GET_FUN(__glewAsyncMarkerSGIX) +#define glDeleteAsyncMarkersSGIX GLEW_GET_FUN(__glewDeleteAsyncMarkersSGIX) +#define glFinishAsyncSGIX GLEW_GET_FUN(__glewFinishAsyncSGIX) +#define glGenAsyncMarkersSGIX GLEW_GET_FUN(__glewGenAsyncMarkersSGIX) +#define glIsAsyncMarkerSGIX GLEW_GET_FUN(__glewIsAsyncMarkerSGIX) +#define glPollAsyncSGIX GLEW_GET_FUN(__glewPollAsyncSGIX) + +#define GLEW_SGIX_async GLEW_GET_VAR(__GLEW_SGIX_async) + +#endif /* GL_SGIX_async */ + +/* ------------------------ GL_SGIX_async_histogram ------------------------ */ + +#ifndef GL_SGIX_async_histogram +#define GL_SGIX_async_histogram 1 + +#define GL_ASYNC_HISTOGRAM_SGIX 0x832C +#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D + +#define GLEW_SGIX_async_histogram GLEW_GET_VAR(__GLEW_SGIX_async_histogram) + +#endif /* GL_SGIX_async_histogram */ + +/* -------------------------- GL_SGIX_async_pixel -------------------------- */ + +#ifndef GL_SGIX_async_pixel +#define GL_SGIX_async_pixel 1 + +#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C +#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D +#define GL_ASYNC_READ_PIXELS_SGIX 0x835E +#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F +#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 +#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 + +#define GLEW_SGIX_async_pixel GLEW_GET_VAR(__GLEW_SGIX_async_pixel) + +#endif /* GL_SGIX_async_pixel */ + +/* ----------------------- GL_SGIX_blend_alpha_minmax ---------------------- */ + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_SGIX_blend_alpha_minmax 1 + +#define GL_ALPHA_MIN_SGIX 0x8320 +#define GL_ALPHA_MAX_SGIX 0x8321 + +#define GLEW_SGIX_blend_alpha_minmax GLEW_GET_VAR(__GLEW_SGIX_blend_alpha_minmax) + +#endif /* GL_SGIX_blend_alpha_minmax */ + +/* ---------------------------- GL_SGIX_clipmap ---------------------------- */ + +#ifndef GL_SGIX_clipmap +#define GL_SGIX_clipmap 1 + +#define GLEW_SGIX_clipmap GLEW_GET_VAR(__GLEW_SGIX_clipmap) + +#endif /* GL_SGIX_clipmap */ + +/* ---------------------- GL_SGIX_convolution_accuracy --------------------- */ + +#ifndef GL_SGIX_convolution_accuracy +#define GL_SGIX_convolution_accuracy 1 + +#define GL_CONVOLUTION_HINT_SGIX 0x8316 + +#define GLEW_SGIX_convolution_accuracy GLEW_GET_VAR(__GLEW_SGIX_convolution_accuracy) + +#endif /* GL_SGIX_convolution_accuracy */ + +/* ------------------------- GL_SGIX_depth_texture ------------------------- */ + +#ifndef GL_SGIX_depth_texture +#define GL_SGIX_depth_texture 1 + +#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 +#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 +#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 + +#define GLEW_SGIX_depth_texture GLEW_GET_VAR(__GLEW_SGIX_depth_texture) + +#endif /* GL_SGIX_depth_texture */ + +/* -------------------------- GL_SGIX_flush_raster ------------------------- */ + +#ifndef GL_SGIX_flush_raster +#define GL_SGIX_flush_raster 1 + +typedef void (GLAPIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void); + +#define glFlushRasterSGIX GLEW_GET_FUN(__glewFlushRasterSGIX) + +#define GLEW_SGIX_flush_raster GLEW_GET_VAR(__GLEW_SGIX_flush_raster) + +#endif /* GL_SGIX_flush_raster */ + +/* --------------------------- GL_SGIX_fog_offset -------------------------- */ + +#ifndef GL_SGIX_fog_offset +#define GL_SGIX_fog_offset 1 + +#define GL_FOG_OFFSET_SGIX 0x8198 +#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 + +#define GLEW_SGIX_fog_offset GLEW_GET_VAR(__GLEW_SGIX_fog_offset) + +#endif /* GL_SGIX_fog_offset */ + +/* -------------------------- GL_SGIX_fog_texture -------------------------- */ + +#ifndef GL_SGIX_fog_texture +#define GL_SGIX_fog_texture 1 + +#define GL_TEXTURE_FOG_SGIX 0 +#define GL_FOG_PATCHY_FACTOR_SGIX 0 +#define GL_FRAGMENT_FOG_SGIX 0 + +typedef void (GLAPIENTRY * PFNGLTEXTUREFOGSGIXPROC) (GLenum pname); + +#define glTextureFogSGIX GLEW_GET_FUN(__glewTextureFogSGIX) + +#define GLEW_SGIX_fog_texture GLEW_GET_VAR(__GLEW_SGIX_fog_texture) + +#endif /* GL_SGIX_fog_texture */ + +/* ------------------- GL_SGIX_fragment_specular_lighting ------------------ */ + +#ifndef GL_SGIX_fragment_specular_lighting +#define GL_SGIX_fragment_specular_lighting 1 + +typedef void (GLAPIENTRY * PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, const GLfloat param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, const GLint param); +typedef void (GLAPIENTRY * PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum value, GLfloat* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum value, GLint* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat* data); +typedef void (GLAPIENTRY * PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint* data); + +#define glFragmentColorMaterialSGIX GLEW_GET_FUN(__glewFragmentColorMaterialSGIX) +#define glFragmentLightModelfSGIX GLEW_GET_FUN(__glewFragmentLightModelfSGIX) +#define glFragmentLightModelfvSGIX GLEW_GET_FUN(__glewFragmentLightModelfvSGIX) +#define glFragmentLightModeliSGIX GLEW_GET_FUN(__glewFragmentLightModeliSGIX) +#define glFragmentLightModelivSGIX GLEW_GET_FUN(__glewFragmentLightModelivSGIX) +#define glFragmentLightfSGIX GLEW_GET_FUN(__glewFragmentLightfSGIX) +#define glFragmentLightfvSGIX GLEW_GET_FUN(__glewFragmentLightfvSGIX) +#define glFragmentLightiSGIX GLEW_GET_FUN(__glewFragmentLightiSGIX) +#define glFragmentLightivSGIX GLEW_GET_FUN(__glewFragmentLightivSGIX) +#define glFragmentMaterialfSGIX GLEW_GET_FUN(__glewFragmentMaterialfSGIX) +#define glFragmentMaterialfvSGIX GLEW_GET_FUN(__glewFragmentMaterialfvSGIX) +#define glFragmentMaterialiSGIX GLEW_GET_FUN(__glewFragmentMaterialiSGIX) +#define glFragmentMaterialivSGIX GLEW_GET_FUN(__glewFragmentMaterialivSGIX) +#define glGetFragmentLightfvSGIX GLEW_GET_FUN(__glewGetFragmentLightfvSGIX) +#define glGetFragmentLightivSGIX GLEW_GET_FUN(__glewGetFragmentLightivSGIX) +#define glGetFragmentMaterialfvSGIX GLEW_GET_FUN(__glewGetFragmentMaterialfvSGIX) +#define glGetFragmentMaterialivSGIX GLEW_GET_FUN(__glewGetFragmentMaterialivSGIX) + +#define GLEW_SGIX_fragment_specular_lighting GLEW_GET_VAR(__GLEW_SGIX_fragment_specular_lighting) + +#endif /* GL_SGIX_fragment_specular_lighting */ + +/* --------------------------- GL_SGIX_framezoom --------------------------- */ + +#ifndef GL_SGIX_framezoom +#define GL_SGIX_framezoom 1 + +typedef void (GLAPIENTRY * PFNGLFRAMEZOOMSGIXPROC) (GLint factor); + +#define glFrameZoomSGIX GLEW_GET_FUN(__glewFrameZoomSGIX) + +#define GLEW_SGIX_framezoom GLEW_GET_VAR(__GLEW_SGIX_framezoom) + +#endif /* GL_SGIX_framezoom */ + +/* --------------------------- GL_SGIX_interlace --------------------------- */ + +#ifndef GL_SGIX_interlace +#define GL_SGIX_interlace 1 + +#define GL_INTERLACE_SGIX 0x8094 + +#define GLEW_SGIX_interlace GLEW_GET_VAR(__GLEW_SGIX_interlace) + +#endif /* GL_SGIX_interlace */ + +/* ------------------------- GL_SGIX_ir_instrument1 ------------------------ */ + +#ifndef GL_SGIX_ir_instrument1 +#define GL_SGIX_ir_instrument1 1 + +#define GLEW_SGIX_ir_instrument1 GLEW_GET_VAR(__GLEW_SGIX_ir_instrument1) + +#endif /* GL_SGIX_ir_instrument1 */ + +/* ------------------------- GL_SGIX_list_priority ------------------------- */ + +#ifndef GL_SGIX_list_priority +#define GL_SGIX_list_priority 1 + +#define GLEW_SGIX_list_priority GLEW_GET_VAR(__GLEW_SGIX_list_priority) + +#endif /* GL_SGIX_list_priority */ + +/* ------------------------- GL_SGIX_pixel_texture ------------------------- */ + +#ifndef GL_SGIX_pixel_texture +#define GL_SGIX_pixel_texture 1 + +typedef void (GLAPIENTRY * PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); + +#define glPixelTexGenSGIX GLEW_GET_FUN(__glewPixelTexGenSGIX) + +#define GLEW_SGIX_pixel_texture GLEW_GET_VAR(__GLEW_SGIX_pixel_texture) + +#endif /* GL_SGIX_pixel_texture */ + +/* ----------------------- GL_SGIX_pixel_texture_bits ---------------------- */ + +#ifndef GL_SGIX_pixel_texture_bits +#define GL_SGIX_pixel_texture_bits 1 + +#define GLEW_SGIX_pixel_texture_bits GLEW_GET_VAR(__GLEW_SGIX_pixel_texture_bits) + +#endif /* GL_SGIX_pixel_texture_bits */ + +/* ------------------------ GL_SGIX_reference_plane ------------------------ */ + +#ifndef GL_SGIX_reference_plane +#define GL_SGIX_reference_plane 1 + +typedef void (GLAPIENTRY * PFNGLREFERENCEPLANESGIXPROC) (const GLdouble* equation); + +#define glReferencePlaneSGIX GLEW_GET_FUN(__glewReferencePlaneSGIX) + +#define GLEW_SGIX_reference_plane GLEW_GET_VAR(__GLEW_SGIX_reference_plane) + +#endif /* GL_SGIX_reference_plane */ + +/* ---------------------------- GL_SGIX_resample --------------------------- */ + +#ifndef GL_SGIX_resample +#define GL_SGIX_resample 1 + +#define GL_PACK_RESAMPLE_SGIX 0x842E +#define GL_UNPACK_RESAMPLE_SGIX 0x842F +#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 +#define GL_RESAMPLE_REPLICATE_SGIX 0x8433 +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x8434 + +#define GLEW_SGIX_resample GLEW_GET_VAR(__GLEW_SGIX_resample) + +#endif /* GL_SGIX_resample */ + +/* ----------------------------- GL_SGIX_shadow ---------------------------- */ + +#ifndef GL_SGIX_shadow +#define GL_SGIX_shadow 1 + +#define GL_TEXTURE_COMPARE_SGIX 0x819A +#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B +#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C +#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D + +#define GLEW_SGIX_shadow GLEW_GET_VAR(__GLEW_SGIX_shadow) + +#endif /* GL_SGIX_shadow */ + +/* ------------------------- GL_SGIX_shadow_ambient ------------------------ */ + +#ifndef GL_SGIX_shadow_ambient +#define GL_SGIX_shadow_ambient 1 + +#define GL_SHADOW_AMBIENT_SGIX 0x80BF + +#define GLEW_SGIX_shadow_ambient GLEW_GET_VAR(__GLEW_SGIX_shadow_ambient) + +#endif /* GL_SGIX_shadow_ambient */ + +/* ----------------------------- GL_SGIX_sprite ---------------------------- */ + +#ifndef GL_SGIX_sprite +#define GL_SGIX_sprite 1 + +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, GLint* params); + +#define glSpriteParameterfSGIX GLEW_GET_FUN(__glewSpriteParameterfSGIX) +#define glSpriteParameterfvSGIX GLEW_GET_FUN(__glewSpriteParameterfvSGIX) +#define glSpriteParameteriSGIX GLEW_GET_FUN(__glewSpriteParameteriSGIX) +#define glSpriteParameterivSGIX GLEW_GET_FUN(__glewSpriteParameterivSGIX) + +#define GLEW_SGIX_sprite GLEW_GET_VAR(__GLEW_SGIX_sprite) + +#endif /* GL_SGIX_sprite */ + +/* ----------------------- GL_SGIX_tag_sample_buffer ----------------------- */ + +#ifndef GL_SGIX_tag_sample_buffer +#define GL_SGIX_tag_sample_buffer 1 + +typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); + +#define glTagSampleBufferSGIX GLEW_GET_FUN(__glewTagSampleBufferSGIX) + +#define GLEW_SGIX_tag_sample_buffer GLEW_GET_VAR(__GLEW_SGIX_tag_sample_buffer) + +#endif /* GL_SGIX_tag_sample_buffer */ + +/* ------------------------ GL_SGIX_texture_add_env ------------------------ */ + +#ifndef GL_SGIX_texture_add_env +#define GL_SGIX_texture_add_env 1 + +#define GLEW_SGIX_texture_add_env GLEW_GET_VAR(__GLEW_SGIX_texture_add_env) + +#endif /* GL_SGIX_texture_add_env */ + +/* -------------------- GL_SGIX_texture_coordinate_clamp ------------------- */ + +#ifndef GL_SGIX_texture_coordinate_clamp +#define GL_SGIX_texture_coordinate_clamp 1 + +#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 +#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A +#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B + +#define GLEW_SGIX_texture_coordinate_clamp GLEW_GET_VAR(__GLEW_SGIX_texture_coordinate_clamp) + +#endif /* GL_SGIX_texture_coordinate_clamp */ + +/* ------------------------ GL_SGIX_texture_lod_bias ----------------------- */ + +#ifndef GL_SGIX_texture_lod_bias +#define GL_SGIX_texture_lod_bias 1 + +#define GLEW_SGIX_texture_lod_bias GLEW_GET_VAR(__GLEW_SGIX_texture_lod_bias) + +#endif /* GL_SGIX_texture_lod_bias */ + +/* ---------------------- GL_SGIX_texture_multi_buffer --------------------- */ + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_SGIX_texture_multi_buffer 1 + +#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E + +#define GLEW_SGIX_texture_multi_buffer GLEW_GET_VAR(__GLEW_SGIX_texture_multi_buffer) + +#endif /* GL_SGIX_texture_multi_buffer */ + +/* ------------------------- GL_SGIX_texture_range ------------------------- */ + +#ifndef GL_SGIX_texture_range +#define GL_SGIX_texture_range 1 + +#define GL_RGB_SIGNED_SGIX 0x85E0 +#define GL_RGBA_SIGNED_SGIX 0x85E1 +#define GL_ALPHA_SIGNED_SGIX 0x85E2 +#define GL_LUMINANCE_SIGNED_SGIX 0x85E3 +#define GL_INTENSITY_SIGNED_SGIX 0x85E4 +#define GL_LUMINANCE_ALPHA_SIGNED_SGIX 0x85E5 +#define GL_RGB16_SIGNED_SGIX 0x85E6 +#define GL_RGBA16_SIGNED_SGIX 0x85E7 +#define GL_ALPHA16_SIGNED_SGIX 0x85E8 +#define GL_LUMINANCE16_SIGNED_SGIX 0x85E9 +#define GL_INTENSITY16_SIGNED_SGIX 0x85EA +#define GL_LUMINANCE16_ALPHA16_SIGNED_SGIX 0x85EB +#define GL_RGB_EXTENDED_RANGE_SGIX 0x85EC +#define GL_RGBA_EXTENDED_RANGE_SGIX 0x85ED +#define GL_ALPHA_EXTENDED_RANGE_SGIX 0x85EE +#define GL_LUMINANCE_EXTENDED_RANGE_SGIX 0x85EF +#define GL_INTENSITY_EXTENDED_RANGE_SGIX 0x85F0 +#define GL_LUMINANCE_ALPHA_EXTENDED_RANGE_SGIX 0x85F1 +#define GL_RGB16_EXTENDED_RANGE_SGIX 0x85F2 +#define GL_RGBA16_EXTENDED_RANGE_SGIX 0x85F3 +#define GL_ALPHA16_EXTENDED_RANGE_SGIX 0x85F4 +#define GL_LUMINANCE16_EXTENDED_RANGE_SGIX 0x85F5 +#define GL_INTENSITY16_EXTENDED_RANGE_SGIX 0x85F6 +#define GL_LUMINANCE16_ALPHA16_EXTENDED_RANGE_SGIX 0x85F7 +#define GL_MIN_LUMINANCE_SGIS 0x85F8 +#define GL_MAX_LUMINANCE_SGIS 0x85F9 +#define GL_MIN_INTENSITY_SGIS 0x85FA +#define GL_MAX_INTENSITY_SGIS 0x85FB + +#define GLEW_SGIX_texture_range GLEW_GET_VAR(__GLEW_SGIX_texture_range) + +#endif /* GL_SGIX_texture_range */ + +/* ----------------------- GL_SGIX_texture_scale_bias ---------------------- */ + +#ifndef GL_SGIX_texture_scale_bias +#define GL_SGIX_texture_scale_bias 1 + +#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 +#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A +#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B +#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C + +#define GLEW_SGIX_texture_scale_bias GLEW_GET_VAR(__GLEW_SGIX_texture_scale_bias) + +#endif /* GL_SGIX_texture_scale_bias */ + +/* ------------------------- GL_SGIX_vertex_preclip ------------------------ */ + +#ifndef GL_SGIX_vertex_preclip +#define GL_SGIX_vertex_preclip 1 + +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF + +#define GLEW_SGIX_vertex_preclip GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip) + +#endif /* GL_SGIX_vertex_preclip */ + +/* ---------------------- GL_SGIX_vertex_preclip_hint ---------------------- */ + +#ifndef GL_SGIX_vertex_preclip_hint +#define GL_SGIX_vertex_preclip_hint 1 + +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF + +#define GLEW_SGIX_vertex_preclip_hint GLEW_GET_VAR(__GLEW_SGIX_vertex_preclip_hint) + +#endif /* GL_SGIX_vertex_preclip_hint */ + +/* ----------------------------- GL_SGIX_ycrcb ----------------------------- */ + +#ifndef GL_SGIX_ycrcb +#define GL_SGIX_ycrcb 1 + +#define GLEW_SGIX_ycrcb GLEW_GET_VAR(__GLEW_SGIX_ycrcb) + +#endif /* GL_SGIX_ycrcb */ + +/* -------------------------- GL_SGI_color_matrix -------------------------- */ + +#ifndef GL_SGI_color_matrix +#define GL_SGI_color_matrix 1 + +#define GL_COLOR_MATRIX_SGI 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB + +#define GLEW_SGI_color_matrix GLEW_GET_VAR(__GLEW_SGI_color_matrix) + +#endif /* GL_SGI_color_matrix */ + +/* --------------------------- GL_SGI_color_table -------------------------- */ + +#ifndef GL_SGI_color_table +#define GL_SGI_color_table 1 + +#define GL_COLOR_TABLE_SGI 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 +#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 +#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 +#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 +#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 +#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF + +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params); +typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* table); +typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void* table); + +#define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI) +#define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI) +#define glColorTableSGI GLEW_GET_FUN(__glewColorTableSGI) +#define glCopyColorTableSGI GLEW_GET_FUN(__glewCopyColorTableSGI) +#define glGetColorTableParameterfvSGI GLEW_GET_FUN(__glewGetColorTableParameterfvSGI) +#define glGetColorTableParameterivSGI GLEW_GET_FUN(__glewGetColorTableParameterivSGI) +#define glGetColorTableSGI GLEW_GET_FUN(__glewGetColorTableSGI) + +#define GLEW_SGI_color_table GLEW_GET_VAR(__GLEW_SGI_color_table) + +#endif /* GL_SGI_color_table */ + +/* ----------------------- GL_SGI_texture_color_table ---------------------- */ + +#ifndef GL_SGI_texture_color_table +#define GL_SGI_texture_color_table 1 + +#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC +#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD + +#define GLEW_SGI_texture_color_table GLEW_GET_VAR(__GLEW_SGI_texture_color_table) + +#endif /* GL_SGI_texture_color_table */ + +/* ------------------------- GL_SUNX_constant_data ------------------------- */ + +#ifndef GL_SUNX_constant_data +#define GL_SUNX_constant_data 1 + +#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 +#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 + +typedef void (GLAPIENTRY * PFNGLFINISHTEXTURESUNXPROC) (void); + +#define glFinishTextureSUNX GLEW_GET_FUN(__glewFinishTextureSUNX) + +#define GLEW_SUNX_constant_data GLEW_GET_VAR(__GLEW_SUNX_constant_data) + +#endif /* GL_SUNX_constant_data */ + +/* -------------------- GL_SUN_convolution_border_modes -------------------- */ + +#ifndef GL_SUN_convolution_border_modes +#define GL_SUN_convolution_border_modes 1 + +#define GL_WRAP_BORDER_SUN 0x81D4 + +#define GLEW_SUN_convolution_border_modes GLEW_GET_VAR(__GLEW_SUN_convolution_border_modes) + +#endif /* GL_SUN_convolution_border_modes */ + +/* -------------------------- GL_SUN_global_alpha -------------------------- */ + +#ifndef GL_SUN_global_alpha +#define GL_SUN_global_alpha 1 + +#define GL_GLOBAL_ALPHA_SUN 0x81D9 +#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA + +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); +typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); + +#define glGlobalAlphaFactorbSUN GLEW_GET_FUN(__glewGlobalAlphaFactorbSUN) +#define glGlobalAlphaFactordSUN GLEW_GET_FUN(__glewGlobalAlphaFactordSUN) +#define glGlobalAlphaFactorfSUN GLEW_GET_FUN(__glewGlobalAlphaFactorfSUN) +#define glGlobalAlphaFactoriSUN GLEW_GET_FUN(__glewGlobalAlphaFactoriSUN) +#define glGlobalAlphaFactorsSUN GLEW_GET_FUN(__glewGlobalAlphaFactorsSUN) +#define glGlobalAlphaFactorubSUN GLEW_GET_FUN(__glewGlobalAlphaFactorubSUN) +#define glGlobalAlphaFactoruiSUN GLEW_GET_FUN(__glewGlobalAlphaFactoruiSUN) +#define glGlobalAlphaFactorusSUN GLEW_GET_FUN(__glewGlobalAlphaFactorusSUN) + +#define GLEW_SUN_global_alpha GLEW_GET_VAR(__GLEW_SUN_global_alpha) + +#endif /* GL_SUN_global_alpha */ + +/* --------------------------- GL_SUN_mesh_array --------------------------- */ + +#ifndef GL_SUN_mesh_array +#define GL_SUN_mesh_array 1 + +#define GL_QUAD_MESH_SUN 0x8614 +#define GL_TRIANGLE_MESH_SUN 0x8615 + +#define GLEW_SUN_mesh_array GLEW_GET_VAR(__GLEW_SUN_mesh_array) + +#endif /* GL_SUN_mesh_array */ + +/* ------------------------ GL_SUN_read_video_pixels ----------------------- */ + +#ifndef GL_SUN_read_video_pixels +#define GL_SUN_read_video_pixels 1 + +typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); + +#define glReadVideoPixelsSUN GLEW_GET_FUN(__glewReadVideoPixelsSUN) + +#define GLEW_SUN_read_video_pixels GLEW_GET_VAR(__GLEW_SUN_read_video_pixels) + +#endif /* GL_SUN_read_video_pixels */ + +/* --------------------------- GL_SUN_slice_accum -------------------------- */ + +#ifndef GL_SUN_slice_accum +#define GL_SUN_slice_accum 1 + +#define GL_SLICE_ACCUM_SUN 0x85CC + +#define GLEW_SUN_slice_accum GLEW_GET_VAR(__GLEW_SUN_slice_accum) + +#endif /* GL_SUN_slice_accum */ + +/* -------------------------- GL_SUN_triangle_list ------------------------- */ + +#ifndef GL_SUN_triangle_list +#define GL_SUN_triangle_list 1 + +#define GL_RESTART_SUN 0x01 +#define GL_REPLACE_MIDDLE_SUN 0x02 +#define GL_REPLACE_OLDEST_SUN 0x03 +#define GL_TRIANGLE_LIST_SUN 0x81D7 +#define GL_REPLACEMENT_CODE_SUN 0x81D8 +#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 +#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 +#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 +#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 +#define GL_R1UI_V3F_SUN 0x85C4 +#define GL_R1UI_C4UB_V3F_SUN 0x85C5 +#define GL_R1UI_C3F_V3F_SUN 0x85C6 +#define GL_R1UI_N3F_V3F_SUN 0x85C7 +#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 +#define GL_R1UI_T2F_V3F_SUN 0x85C9 +#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA +#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB + +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint* code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort* code); + +#define glReplacementCodePointerSUN GLEW_GET_FUN(__glewReplacementCodePointerSUN) +#define glReplacementCodeubSUN GLEW_GET_FUN(__glewReplacementCodeubSUN) +#define glReplacementCodeubvSUN GLEW_GET_FUN(__glewReplacementCodeubvSUN) +#define glReplacementCodeuiSUN GLEW_GET_FUN(__glewReplacementCodeuiSUN) +#define glReplacementCodeuivSUN GLEW_GET_FUN(__glewReplacementCodeuivSUN) +#define glReplacementCodeusSUN GLEW_GET_FUN(__glewReplacementCodeusSUN) +#define glReplacementCodeusvSUN GLEW_GET_FUN(__glewReplacementCodeusvSUN) + +#define GLEW_SUN_triangle_list GLEW_GET_VAR(__GLEW_SUN_triangle_list) + +#endif /* GL_SUN_triangle_list */ + +/* ----------------------------- GL_SUN_vertex ----------------------------- */ + +#ifndef GL_SUN_vertex +#define GL_SUN_vertex 1 + +typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte* c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint* rc, const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *tc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint* rc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat* tc, const GLubyte *c, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAPIENTRY * PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat* tc, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY * PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat* tc, const GLfloat *v); + +#define glColor3fVertex3fSUN GLEW_GET_FUN(__glewColor3fVertex3fSUN) +#define glColor3fVertex3fvSUN GLEW_GET_FUN(__glewColor3fVertex3fvSUN) +#define glColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fSUN) +#define glColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewColor4fNormal3fVertex3fvSUN) +#define glColor4ubVertex2fSUN GLEW_GET_FUN(__glewColor4ubVertex2fSUN) +#define glColor4ubVertex2fvSUN GLEW_GET_FUN(__glewColor4ubVertex2fvSUN) +#define glColor4ubVertex3fSUN GLEW_GET_FUN(__glewColor4ubVertex3fSUN) +#define glColor4ubVertex3fvSUN GLEW_GET_FUN(__glewColor4ubVertex3fvSUN) +#define glNormal3fVertex3fSUN GLEW_GET_FUN(__glewNormal3fVertex3fSUN) +#define glNormal3fVertex3fvSUN GLEW_GET_FUN(__glewNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fSUN) +#define glReplacementCodeuiColor3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor3fVertex3fvSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor4ubVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fSUN) +#define glReplacementCodeuiColor4ubVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiColor4ubVertex3fvSUN) +#define glReplacementCodeuiNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fSUN) +#define glReplacementCodeuiNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiTexCoord2fVertex3fvSUN) +#define glReplacementCodeuiVertex3fSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fSUN) +#define glReplacementCodeuiVertex3fvSUN GLEW_GET_FUN(__glewReplacementCodeuiVertex3fvSUN) +#define glTexCoord2fColor3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fSUN) +#define glTexCoord2fColor3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor3fVertex3fvSUN) +#define glTexCoord2fColor4fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fSUN) +#define glTexCoord2fColor4fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glTexCoord2fColor4ubVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fSUN) +#define glTexCoord2fColor4ubVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fColor4ubVertex3fvSUN) +#define glTexCoord2fNormal3fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fSUN) +#define glTexCoord2fNormal3fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fNormal3fVertex3fvSUN) +#define glTexCoord2fVertex3fSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fSUN) +#define glTexCoord2fVertex3fvSUN GLEW_GET_FUN(__glewTexCoord2fVertex3fvSUN) +#define glTexCoord4fColor4fNormal3fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fSUN) +#define glTexCoord4fColor4fNormal3fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fColor4fNormal3fVertex4fvSUN) +#define glTexCoord4fVertex4fSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fSUN) +#define glTexCoord4fVertex4fvSUN GLEW_GET_FUN(__glewTexCoord4fVertex4fvSUN) + +#define GLEW_SUN_vertex GLEW_GET_VAR(__GLEW_SUN_vertex) + +#endif /* GL_SUN_vertex */ + +/* -------------------------- GL_WIN_phong_shading ------------------------- */ + +#ifndef GL_WIN_phong_shading +#define GL_WIN_phong_shading 1 + +#define GL_PHONG_WIN 0x80EA +#define GL_PHONG_HINT_WIN 0x80EB + +#define GLEW_WIN_phong_shading GLEW_GET_VAR(__GLEW_WIN_phong_shading) + +#endif /* GL_WIN_phong_shading */ + +/* -------------------------- GL_WIN_specular_fog -------------------------- */ + +#ifndef GL_WIN_specular_fog +#define GL_WIN_specular_fog 1 + +#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC + +#define GLEW_WIN_specular_fog GLEW_GET_VAR(__GLEW_WIN_specular_fog) + +#endif /* GL_WIN_specular_fog */ + +/* ---------------------------- GL_WIN_swap_hint --------------------------- */ + +#ifndef GL_WIN_swap_hint +#define GL_WIN_swap_hint 1 + +typedef void (GLAPIENTRY * PFNGLADDSWAPHINTRECTWINPROC) (GLint x, GLint y, GLsizei width, GLsizei height); + +#define glAddSwapHintRectWIN GLEW_GET_FUN(__glewAddSwapHintRectWIN) + +#define GLEW_WIN_swap_hint GLEW_GET_VAR(__GLEW_WIN_swap_hint) + +#endif /* GL_WIN_swap_hint */ + +/* ------------------------------------------------------------------------- */ + +#if defined(GLEW_MX) && defined(_WIN32) +#define GLEW_FUN_EXPORT +#else +#define GLEW_FUN_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#if defined(GLEW_MX) +#define GLEW_VAR_EXPORT +#else +#define GLEW_VAR_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#if defined(GLEW_MX) && defined(_WIN32) +struct GLEWContextStruct +{ +#endif /* GLEW_MX */ + +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements; +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DPROC __glewTexImage3D; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D; + +GLEW_FUN_EXPORT PFNGLACTIVETEXTUREPROC __glewActiveTexture; +GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv; +GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage; + +GLEW_FUN_EXPORT PFNGLBLENDCOLORPROC __glewBlendColor; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONPROC __glewBlendEquation; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate; +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer; +GLEW_FUN_EXPORT PFNGLFOGCOORDDPROC __glewFogCoordd; +GLEW_FUN_EXPORT PFNGLFOGCOORDDVPROC __glewFogCoorddv; +GLEW_FUN_EXPORT PFNGLFOGCOORDFPROC __glewFogCoordf; +GLEW_FUN_EXPORT PFNGLFOGCOORDFVPROC __glewFogCoordfv; +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFPROC __glewPointParameterf; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIPROC __glewPointParameteri; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DPROC __glewWindowPos2d; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FPROC __glewWindowPos2f; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IPROC __glewWindowPos2i; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SPROC __glewWindowPos2s; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DPROC __glewWindowPos3d; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FPROC __glewWindowPos3f; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IPROC __glewWindowPos3i; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SPROC __glewWindowPos3s; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYPROC __glewBeginQuery; +GLEW_FUN_EXPORT PFNGLBINDBUFFERPROC __glewBindBuffer; +GLEW_FUN_EXPORT PFNGLBUFFERDATAPROC __glewBufferData; +GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAPROC __glewBufferSubData; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERSPROC __glewDeleteBuffers; +GLEW_FUN_EXPORT PFNGLDELETEQUERIESPROC __glewDeleteQueries; +GLEW_FUN_EXPORT PFNGLENDQUERYPROC __glewEndQuery; +GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers; +GLEW_FUN_EXPORT PFNGLGENQUERIESPROC __glewGenQueries; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv; +GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv; +GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv; +GLEW_FUN_EXPORT PFNGLGETQUERYIVPROC __glewGetQueryiv; +GLEW_FUN_EXPORT PFNGLISBUFFERPROC __glewIsBuffer; +GLEW_FUN_EXPORT PFNGLISQUERYPROC __glewIsQuery; +GLEW_FUN_EXPORT PFNGLMAPBUFFERPROC __glewMapBuffer; +GLEW_FUN_EXPORT PFNGLUNMAPBUFFERPROC __glewUnmapBuffer; + +GLEW_FUN_EXPORT PFNGLATTACHSHADERPROC __glewAttachShader; +GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate; +GLEW_FUN_EXPORT PFNGLCOMPILESHADERPROC __glewCompileShader; +GLEW_FUN_EXPORT PFNGLCREATEPROGRAMPROC __glewCreateProgram; +GLEW_FUN_EXPORT PFNGLCREATESHADERPROC __glewCreateShader; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPROC __glewDeleteProgram; +GLEW_FUN_EXPORT PFNGLDELETESHADERPROC __glewDeleteShader; +GLEW_FUN_EXPORT PFNGLDETACHSHADERPROC __glewDetachShader; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray; +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSPROC __glewDrawBuffers; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray; +GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform; +GLEW_FUN_EXPORT PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders; +GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation; +GLEW_FUN_EXPORT PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVPROC __glewGetProgramiv; +GLEW_FUN_EXPORT PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog; +GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEPROC __glewGetShaderSource; +GLEW_FUN_EXPORT PFNGLGETSHADERIVPROC __glewGetShaderiv; +GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation; +GLEW_FUN_EXPORT PFNGLGETUNIFORMFVPROC __glewGetUniformfv; +GLEW_FUN_EXPORT PFNGLGETUNIFORMIVPROC __glewGetUniformiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv; +GLEW_FUN_EXPORT PFNGLISPROGRAMPROC __glewIsProgram; +GLEW_FUN_EXPORT PFNGLISSHADERPROC __glewIsShader; +GLEW_FUN_EXPORT PFNGLLINKPROGRAMPROC __glewLinkProgram; +GLEW_FUN_EXPORT PFNGLSHADERSOURCEPROC __glewShaderSource; +GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate; +GLEW_FUN_EXPORT PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate; +GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate; +GLEW_FUN_EXPORT PFNGLUNIFORM1FPROC __glewUniform1f; +GLEW_FUN_EXPORT PFNGLUNIFORM1FVPROC __glewUniform1fv; +GLEW_FUN_EXPORT PFNGLUNIFORM1IPROC __glewUniform1i; +GLEW_FUN_EXPORT PFNGLUNIFORM1IVPROC __glewUniform1iv; +GLEW_FUN_EXPORT PFNGLUNIFORM2FPROC __glewUniform2f; +GLEW_FUN_EXPORT PFNGLUNIFORM2FVPROC __glewUniform2fv; +GLEW_FUN_EXPORT PFNGLUNIFORM2IPROC __glewUniform2i; +GLEW_FUN_EXPORT PFNGLUNIFORM2IVPROC __glewUniform2iv; +GLEW_FUN_EXPORT PFNGLUNIFORM3FPROC __glewUniform3f; +GLEW_FUN_EXPORT PFNGLUNIFORM3FVPROC __glewUniform3fv; +GLEW_FUN_EXPORT PFNGLUNIFORM3IPROC __glewUniform3i; +GLEW_FUN_EXPORT PFNGLUNIFORM3IVPROC __glewUniform3iv; +GLEW_FUN_EXPORT PFNGLUNIFORM4FPROC __glewUniform4f; +GLEW_FUN_EXPORT PFNGLUNIFORM4FVPROC __glewUniform4fv; +GLEW_FUN_EXPORT PFNGLUNIFORM4IPROC __glewUniform4i; +GLEW_FUN_EXPORT PFNGLUNIFORM4IVPROC __glewUniform4iv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMPROC __glewUseProgram; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPROC __glewValidateProgram; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer; + +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv; + +GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERPROC __glewBeginConditionalRender; +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKPROC __glewBeginTransformFeedback; +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONPROC __glewBindFragDataLocation; +GLEW_FUN_EXPORT PFNGLCLAMPCOLORPROC __glewClampColor; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERFIPROC __glewClearBufferfi; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERFVPROC __glewClearBufferfv; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERIVPROC __glewClearBufferiv; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERUIVPROC __glewClearBufferuiv; +GLEW_FUN_EXPORT PFNGLCOLORMASKIPROC __glewColorMaski; +GLEW_FUN_EXPORT PFNGLDISABLEIPROC __glewDisablei; +GLEW_FUN_EXPORT PFNGLENABLEIPROC __glewEnablei; +GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERPROC __glewEndConditionalRender; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKPROC __glewEndTransformFeedback; +GLEW_FUN_EXPORT PFNGLGETBOOLEANI_VPROC __glewGetBooleani_v; +GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONPROC __glewGetFragDataLocation; +GLEW_FUN_EXPORT PFNGLGETSTRINGIPROC __glewGetStringi; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVPROC __glewGetTexParameterIiv; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVPROC __glewGetTexParameterIuiv; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGPROC __glewGetTransformFeedbackVarying; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVPROC __glewGetUniformuiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVPROC __glewGetVertexAttribIiv; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVPROC __glewGetVertexAttribIuiv; +GLEW_FUN_EXPORT PFNGLISENABLEDIPROC __glewIsEnabledi; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVPROC __glewTexParameterIiv; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVPROC __glewTexParameterIuiv; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSPROC __glewTransformFeedbackVaryings; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIPROC __glewUniform1ui; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIVPROC __glewUniform1uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIPROC __glewUniform2ui; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIVPROC __glewUniform2uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIPROC __glewUniform3ui; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIVPROC __glewUniform3uiv; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIPROC __glewUniform4ui; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIVPROC __glewUniform4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IPROC __glewVertexAttribI1i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVPROC __glewVertexAttribI1iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIPROC __glewVertexAttribI1ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVPROC __glewVertexAttribI1uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IPROC __glewVertexAttribI2i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVPROC __glewVertexAttribI2iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIPROC __glewVertexAttribI2ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVPROC __glewVertexAttribI2uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IPROC __glewVertexAttribI3i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVPROC __glewVertexAttribI3iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIPROC __glewVertexAttribI3ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVPROC __glewVertexAttribI3uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVPROC __glewVertexAttribI4bv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IPROC __glewVertexAttribI4i; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVPROC __glewVertexAttribI4iv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVPROC __glewVertexAttribI4sv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVPROC __glewVertexAttribI4ubv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIPROC __glewVertexAttribI4ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVPROC __glewVertexAttribI4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVPROC __glewVertexAttribI4usv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTERPROC __glewVertexAttribIPointer; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDPROC __glewDrawArraysInstanced; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDPROC __glewDrawElementsInstanced; +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXPROC __glewPrimitiveRestartIndex; +GLEW_FUN_EXPORT PFNGLTEXBUFFERPROC __glewTexBuffer; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREPROC __glewFramebufferTexture; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERI64VPROC __glewGetBufferParameteri64v; +GLEW_FUN_EXPORT PFNGLGETINTEGER64I_VPROC __glewGetInteger64i_v; + +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORPROC __glewVertexAttribDivisor; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIPROC __glewBlendEquationSeparatei; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIPROC __glewBlendEquationi; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIPROC __glewBlendFuncSeparatei; +GLEW_FUN_EXPORT PFNGLBLENDFUNCIPROC __glewBlendFunci; +GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGPROC __glewMinSampleShading; + +GLEW_FUN_EXPORT PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX; + +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKAMDPROC __glewDebugMessageCallbackAMD; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEENABLEAMDPROC __glewDebugMessageEnableAMD; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTAMDPROC __glewDebugMessageInsertAMD; +GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGAMDPROC __glewGetDebugMessageLogAMD; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONINDEXEDAMDPROC __glewBlendEquationIndexedAMD; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSeparateIndexedAMD; +GLEW_FUN_EXPORT PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD; + +GLEW_FUN_EXPORT PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD; +GLEW_FUN_EXPORT PFNGLGENNAMESAMDPROC __glewGenNamesAMD; +GLEW_FUN_EXPORT PFNGLISNAMEAMDPROC __glewIsNameAMD; + +GLEW_FUN_EXPORT PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD; +GLEW_FUN_EXPORT PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD; +GLEW_FUN_EXPORT PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD; +GLEW_FUN_EXPORT PFNGLGENPERFMONITORSAMDPROC __glewGenPerfMonitorsAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERDATAAMDPROC __glewGetPerfMonitorCounterDataAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERINFOAMDPROC __glewGetPerfMonitorCounterInfoAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC __glewGetPerfMonitorCounterStringAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORCOUNTERSAMDPROC __glewGetPerfMonitorCountersAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSTRINGAMDPROC __glewGetPerfMonitorGroupStringAMD; +GLEW_FUN_EXPORT PFNGLGETPERFMONITORGROUPSAMDPROC __glewGetPerfMonitorGroupsAMD; +GLEW_FUN_EXPORT PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD; + +GLEW_FUN_EXPORT PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD; + +GLEW_FUN_EXPORT PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD; +GLEW_FUN_EXPORT PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE; +GLEW_FUN_EXPORT PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE; + +GLEW_FUN_EXPORT PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE; +GLEW_FUN_EXPORT PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE; +GLEW_FUN_EXPORT PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE; +GLEW_FUN_EXPORT PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE; +GLEW_FUN_EXPORT PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE; +GLEW_FUN_EXPORT PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE; +GLEW_FUN_EXPORT PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE; +GLEW_FUN_EXPORT PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE; + +GLEW_FUN_EXPORT PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE; +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVAPPLEPROC __glewGetObjectParameterivAPPLE; +GLEW_FUN_EXPORT PFNGLOBJECTPURGEABLEAPPLEPROC __glewObjectPurgeableAPPLE; +GLEW_FUN_EXPORT PFNGLOBJECTUNPURGEABLEAPPLEPROC __glewObjectUnpurgeableAPPLE; + +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE; +GLEW_FUN_EXPORT PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE; +GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE; +GLEW_FUN_EXPORT PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE; + +GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE; + +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBAPPLEPROC __glewDisableVertexAttribAPPLE; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBAPPLEPROC __glewEnableVertexAttribAPPLE; +GLEW_FUN_EXPORT PFNGLISVERTEXATTRIBENABLEDAPPLEPROC __glewIsVertexAttribEnabledAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1DAPPLEPROC __glewMapVertexAttrib1dAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB1FAPPLEPROC __glewMapVertexAttrib1fAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2DAPPLEPROC __glewMapVertexAttrib2dAPPLE; +GLEW_FUN_EXPORT PFNGLMAPVERTEXATTRIB2FAPPLEPROC __glewMapVertexAttrib2fAPPLE; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHFPROC __glewClearDepthf; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEFPROC __glewDepthRangef; +GLEW_FUN_EXPORT PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat; +GLEW_FUN_EXPORT PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler; +GLEW_FUN_EXPORT PFNGLSHADERBINARYPROC __glewShaderBinary; + +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed; +GLEW_FUN_EXPORT PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex; + +GLEW_FUN_EXPORT PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB; + +GLEW_FUN_EXPORT PFNGLCLAMPCOLORARBPROC __glewClampColorARB; + +GLEW_FUN_EXPORT PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData; + +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB; +GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGARBPROC __glewGetDebugMessageLogARB; + +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEIARBPROC __glewBlendEquationSeparateiARB; +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONIARBPROC __glewBlendEquationiARB; +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEIARBPROC __glewBlendFuncSeparateiARB; +GLEW_FUN_EXPORT PFNGLBLENDFUNCIARBPROC __glewBlendFunciARB; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSBASEVERTEXPROC __glewDrawElementsBaseVertex; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC __glewDrawElementsInstancedBaseVertex; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC __glewDrawRangeElementsBaseVertex; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBaseVertex; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect; + +GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer; +GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer; +GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer; +GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus; +GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers; +GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DPROC __glewFramebufferTexture1D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DPROC __glewFramebufferTexture3D; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERPROC __glewFramebufferTextureLayer; +GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers; +GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers; +GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv; +GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv; +GLEW_FUN_EXPORT PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer; +GLEW_FUN_EXPORT PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __glewRenderbufferStorageMultisample; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREARBPROC __glewFramebufferTextureARB; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEARBPROC __glewFramebufferTextureFaceARB; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYERARBPROC __glewFramebufferTextureLayerARB; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIARBPROC __glewProgramParameteriARB; + +GLEW_FUN_EXPORT PFNGLGETPROGRAMBINARYPROC __glewGetProgramBinary; +GLEW_FUN_EXPORT PFNGLPROGRAMBINARYPROC __glewProgramBinary; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri; + +GLEW_FUN_EXPORT PFNGLGETUNIFORMDVPROC __glewGetUniformdv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1DPROC __glewUniform1d; +GLEW_FUN_EXPORT PFNGLUNIFORM1DVPROC __glewUniform1dv; +GLEW_FUN_EXPORT PFNGLUNIFORM2DPROC __glewUniform2d; +GLEW_FUN_EXPORT PFNGLUNIFORM2DVPROC __glewUniform2dv; +GLEW_FUN_EXPORT PFNGLUNIFORM3DPROC __glewUniform3d; +GLEW_FUN_EXPORT PFNGLUNIFORM3DVPROC __glewUniform3dv; +GLEW_FUN_EXPORT PFNGLUNIFORM4DPROC __glewUniform4d; +GLEW_FUN_EXPORT PFNGLUNIFORM4DVPROC __glewUniform4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2DVPROC __glewUniformMatrix2dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X3DVPROC __glewUniformMatrix2x3dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2X4DVPROC __glewUniformMatrix2x4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3DVPROC __glewUniformMatrix3dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X2DVPROC __glewUniformMatrix3x2dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3X4DVPROC __glewUniformMatrix3x4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4DVPROC __glewUniformMatrix4dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X2DVPROC __glewUniformMatrix4x2dv; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4X3DVPROC __glewUniformMatrix4x3dv; + +GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEPROC __glewColorSubTable; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPROC __glewColorTable; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv; +GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable; +GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPROC __glewGetColorTable; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPROC __glewGetHistogram; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv; +GLEW_FUN_EXPORT PFNGLGETMINMAXPROC __glewGetMinmax; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv; +GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter; +GLEW_FUN_EXPORT PFNGLHISTOGRAMPROC __glewHistogram; +GLEW_FUN_EXPORT PFNGLMINMAXPROC __glewMinmax; +GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMPROC __glewResetHistogram; +GLEW_FUN_EXPORT PFNGLRESETMINMAXPROC __glewResetMinmax; +GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB; + +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange; +GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange; + +GLEW_FUN_EXPORT PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB; +GLEW_FUN_EXPORT PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB; + +GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB; + +GLEW_FUN_EXPORT PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB; +GLEW_FUN_EXPORT PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYARBPROC __glewBeginQueryARB; +GLEW_FUN_EXPORT PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB; +GLEW_FUN_EXPORT PFNGLENDQUERYARBPROC __glewEndQueryARB; +GLEW_FUN_EXPORT PFNGLGENQUERIESARBPROC __glewGenQueriesARB; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB; +GLEW_FUN_EXPORT PFNGLGETQUERYIVARBPROC __glewGetQueryivARB; +GLEW_FUN_EXPORT PFNGLISQUERYARBPROC __glewIsQueryARB; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB; + +GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex; + +GLEW_FUN_EXPORT PFNGLGETNCOLORTABLEARBPROC __glewGetnColorTableARB; +GLEW_FUN_EXPORT PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC __glewGetnCompressedTexImageARB; +GLEW_FUN_EXPORT PFNGLGETNCONVOLUTIONFILTERARBPROC __glewGetnConvolutionFilterARB; +GLEW_FUN_EXPORT PFNGLGETNHISTOGRAMARBPROC __glewGetnHistogramARB; +GLEW_FUN_EXPORT PFNGLGETNMAPDVARBPROC __glewGetnMapdvARB; +GLEW_FUN_EXPORT PFNGLGETNMAPFVARBPROC __glewGetnMapfvARB; +GLEW_FUN_EXPORT PFNGLGETNMAPIVARBPROC __glewGetnMapivARB; +GLEW_FUN_EXPORT PFNGLGETNMINMAXARBPROC __glewGetnMinmaxARB; +GLEW_FUN_EXPORT PFNGLGETNPIXELMAPFVARBPROC __glewGetnPixelMapfvARB; +GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUIVARBPROC __glewGetnPixelMapuivARB; +GLEW_FUN_EXPORT PFNGLGETNPIXELMAPUSVARBPROC __glewGetnPixelMapusvARB; +GLEW_FUN_EXPORT PFNGLGETNPOLYGONSTIPPLEARBPROC __glewGetnPolygonStippleARB; +GLEW_FUN_EXPORT PFNGLGETNSEPARABLEFILTERARBPROC __glewGetnSeparableFilterARB; +GLEW_FUN_EXPORT PFNGLGETNTEXIMAGEARBPROC __glewGetnTexImageARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMDVARBPROC __glewGetnUniformdvARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMFVARBPROC __glewGetnUniformfvARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMIVARBPROC __glewGetnUniformivARB; +GLEW_FUN_EXPORT PFNGLGETNUNIFORMUIVARBPROC __glewGetnUniformuivARB; +GLEW_FUN_EXPORT PFNGLREADNPIXELSARBPROC __glewReadnPixelsARB; + +GLEW_FUN_EXPORT PFNGLMINSAMPLESHADINGARBPROC __glewMinSampleShadingARB; + +GLEW_FUN_EXPORT PFNGLBINDSAMPLERPROC __glewBindSampler; +GLEW_FUN_EXPORT PFNGLDELETESAMPLERSPROC __glewDeleteSamplers; +GLEW_FUN_EXPORT PFNGLGENSAMPLERSPROC __glewGenSamplers; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIIVPROC __glewGetSamplerParameterIiv; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIUIVPROC __glewGetSamplerParameterIuiv; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERFVPROC __glewGetSamplerParameterfv; +GLEW_FUN_EXPORT PFNGLGETSAMPLERPARAMETERIVPROC __glewGetSamplerParameteriv; +GLEW_FUN_EXPORT PFNGLISSAMPLERPROC __glewIsSampler; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIIVPROC __glewSamplerParameterIiv; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIUIVPROC __glewSamplerParameterIuiv; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFPROC __glewSamplerParameterf; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERFVPROC __glewSamplerParameterfv; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIPROC __glewSamplerParameteri; +GLEW_FUN_EXPORT PFNGLSAMPLERPARAMETERIVPROC __glewSamplerParameteriv; + +GLEW_FUN_EXPORT PFNGLACTIVESHADERPROGRAMPROC __glewActiveShaderProgram; +GLEW_FUN_EXPORT PFNGLBINDPROGRAMPIPELINEPROC __glewBindProgramPipeline; +GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMVPROC __glewCreateShaderProgramv; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMPIPELINESPROC __glewDeleteProgramPipelines; +GLEW_FUN_EXPORT PFNGLGENPROGRAMPIPELINESPROC __glewGenProgramPipelines; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEINFOLOGPROC __glewGetProgramPipelineInfoLog; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPIPELINEIVPROC __glewGetProgramPipelineiv; +GLEW_FUN_EXPORT PFNGLISPROGRAMPIPELINEPROC __glewIsProgramPipeline; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DPROC __glewProgramUniform1d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVPROC __glewProgramUniform1dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FPROC __glewProgramUniform1f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVPROC __glewProgramUniform1fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IPROC __glewProgramUniform1i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVPROC __glewProgramUniform1iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIPROC __glewProgramUniform1ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVPROC __glewProgramUniform1uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DPROC __glewProgramUniform2d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVPROC __glewProgramUniform2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FPROC __glewProgramUniform2f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVPROC __glewProgramUniform2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IPROC __glewProgramUniform2i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVPROC __glewProgramUniform2iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIPROC __glewProgramUniform2ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVPROC __glewProgramUniform2uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DPROC __glewProgramUniform3d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVPROC __glewProgramUniform3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FPROC __glewProgramUniform3f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVPROC __glewProgramUniform3fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IPROC __glewProgramUniform3i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVPROC __glewProgramUniform3iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIPROC __glewProgramUniform3ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVPROC __glewProgramUniform3uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DPROC __glewProgramUniform4d; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVPROC __glewProgramUniform4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FPROC __glewProgramUniform4f; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVPROC __glewProgramUniform4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IPROC __glewProgramUniform4i; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVPROC __glewProgramUniform4iv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIPROC __glewProgramUniform4ui; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVPROC __glewProgramUniform4uiv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVPROC __glewProgramUniformMatrix2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVPROC __glewProgramUniformMatrix2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC __glewProgramUniformMatrix2x3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC __glewProgramUniformMatrix2x3fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC __glewProgramUniformMatrix2x4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC __glewProgramUniformMatrix2x4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVPROC __glewProgramUniformMatrix3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVPROC __glewProgramUniformMatrix3fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC __glewProgramUniformMatrix3x2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC __glewProgramUniformMatrix3x2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC __glewProgramUniformMatrix3x4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC __glewProgramUniformMatrix3x4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVPROC __glewProgramUniformMatrix4dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVPROC __glewProgramUniformMatrix4fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC __glewProgramUniformMatrix4x2dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC __glewProgramUniformMatrix4x2fv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC __glewProgramUniformMatrix4x3dv; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC __glewProgramUniformMatrix4x3fv; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMSTAGESPROC __glewUseProgramStages; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPIPELINEPROC __glewValidateProgramPipeline; + +GLEW_FUN_EXPORT PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB; +GLEW_FUN_EXPORT PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB; +GLEW_FUN_EXPORT PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB; +GLEW_FUN_EXPORT PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB; +GLEW_FUN_EXPORT PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB; +GLEW_FUN_EXPORT PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB; +GLEW_FUN_EXPORT PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB; +GLEW_FUN_EXPORT PFNGLGETHANDLEARBPROC __glewGetHandleARB; +GLEW_FUN_EXPORT PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB; +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB; +GLEW_FUN_EXPORT PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB; +GLEW_FUN_EXPORT PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB; +GLEW_FUN_EXPORT PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB; +GLEW_FUN_EXPORT PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1FARBPROC __glewUniform1fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1IARBPROC __glewUniform1iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2FARBPROC __glewUniform2fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2IARBPROC __glewUniform2iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3FARBPROC __glewUniform3fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3IARBPROC __glewUniform3iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4FARBPROC __glewUniform4fARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4IARBPROC __glewUniform4iARB; +GLEW_FUN_EXPORT PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB; +GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB; +GLEW_FUN_EXPORT PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB; +GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB; + +GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName; +GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName; +GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTAGEIVPROC __glewGetProgramStageiv; +GLEW_FUN_EXPORT PFNGLGETSUBROUTINEINDEXPROC __glewGetSubroutineIndex; +GLEW_FUN_EXPORT PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC __glewGetSubroutineUniformLocation; +GLEW_FUN_EXPORT PFNGLGETUNIFORMSUBROUTINEUIVPROC __glewGetUniformSubroutineuiv; +GLEW_FUN_EXPORT PFNGLUNIFORMSUBROUTINESUIVPROC __glewUniformSubroutinesuiv; + +GLEW_FUN_EXPORT PFNGLCOMPILESHADERINCLUDEARBPROC __glewCompileShaderIncludeARB; +GLEW_FUN_EXPORT PFNGLDELETENAMEDSTRINGARBPROC __glewDeleteNamedStringARB; +GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGARBPROC __glewGetNamedStringARB; +GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB; +GLEW_FUN_EXPORT PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB; +GLEW_FUN_EXPORT PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB; + +GLEW_FUN_EXPORT PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync; +GLEW_FUN_EXPORT PFNGLDELETESYNCPROC __glewDeleteSync; +GLEW_FUN_EXPORT PFNGLFENCESYNCPROC __glewFenceSync; +GLEW_FUN_EXPORT PFNGLGETINTEGER64VPROC __glewGetInteger64v; +GLEW_FUN_EXPORT PFNGLGETSYNCIVPROC __glewGetSynciv; +GLEW_FUN_EXPORT PFNGLISSYNCPROC __glewIsSync; +GLEW_FUN_EXPORT PFNGLWAITSYNCPROC __glewWaitSync; + +GLEW_FUN_EXPORT PFNGLPATCHPARAMETERFVPROC __glewPatchParameterfv; +GLEW_FUN_EXPORT PFNGLPATCHPARAMETERIPROC __glewPatchParameteri; + +GLEW_FUN_EXPORT PFNGLTEXBUFFERARBPROC __glewTexBufferARB; + +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB; + +GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVPROC __glewGetMultisamplefv; +GLEW_FUN_EXPORT PFNGLSAMPLEMASKIPROC __glewSampleMaski; +GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLEPROC __glewTexImage2DMultisample; +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLEPROC __glewTexImage3DMultisample; + +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v; +GLEW_FUN_EXPORT PFNGLQUERYCOUNTERPROC __glewQueryCounter; + +GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKPROC __glewBindTransformFeedback; +GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSPROC __glewDeleteTransformFeedbacks; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKPROC __glewDrawTransformFeedback; +GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSPROC __glewGenTransformFeedbacks; +GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKPROC __glewIsTransformFeedback; +GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKPROC __glewPauseTransformFeedback; +GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKPROC __glewResumeTransformFeedback; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYINDEXEDPROC __glewBeginQueryIndexed; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC __glewDrawTransformFeedbackStream; +GLEW_FUN_EXPORT PFNGLENDQUERYINDEXEDPROC __glewEndQueryIndexed; +GLEW_FUN_EXPORT PFNGLGETQUERYINDEXEDIVPROC __glewGetQueryIndexediv; + +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB; +GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB; +GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB; + +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEPROC __glewBindBufferBase; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEPROC __glewBindBufferRange; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC __glewGetActiveUniformBlockName; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMBLOCKIVPROC __glewGetActiveUniformBlockiv; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMNAMEPROC __glewGetActiveUniformName; +GLEW_FUN_EXPORT PFNGLGETACTIVEUNIFORMSIVPROC __glewGetActiveUniformsiv; +GLEW_FUN_EXPORT PFNGLGETINTEGERI_VPROC __glewGetIntegeri_v; +GLEW_FUN_EXPORT PFNGLGETUNIFORMBLOCKINDEXPROC __glewGetUniformBlockIndex; +GLEW_FUN_EXPORT PFNGLGETUNIFORMINDICESPROC __glewGetUniformIndices; +GLEW_FUN_EXPORT PFNGLUNIFORMBLOCKBINDINGPROC __glewUniformBlockBinding; + +GLEW_FUN_EXPORT PFNGLBINDVERTEXARRAYPROC __glewBindVertexArray; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXARRAYSPROC __glewDeleteVertexArrays; +GLEW_FUN_EXPORT PFNGLGENVERTEXARRAYSPROC __glewGenVertexArrays; +GLEW_FUN_EXPORT PFNGLISVERTEXARRAYPROC __glewIsVertexArray; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVPROC __glewGetVertexAttribLdv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DPROC __glewVertexAttribL1d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVPROC __glewVertexAttribL1dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DPROC __glewVertexAttribL2d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVPROC __glewVertexAttribL2dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DPROC __glewVertexAttribL3d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVPROC __glewVertexAttribL3dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer; + +GLEW_FUN_EXPORT PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB; +GLEW_FUN_EXPORT PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB; +GLEW_FUN_EXPORT PFNGLWEIGHTBVARBPROC __glewWeightbvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTDVARBPROC __glewWeightdvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTFVARBPROC __glewWeightfvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTIVARBPROC __glewWeightivARB; +GLEW_FUN_EXPORT PFNGLWEIGHTSVARBPROC __glewWeightsvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUBVARBPROC __glewWeightubvARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUIVARBPROC __glewWeightuivARB; +GLEW_FUN_EXPORT PFNGLWEIGHTUSVARBPROC __glewWeightusvARB; + +GLEW_FUN_EXPORT PFNGLBINDBUFFERARBPROC __glewBindBufferARB; +GLEW_FUN_EXPORT PFNGLBUFFERDATAARBPROC __glewBufferDataARB; +GLEW_FUN_EXPORT PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB; +GLEW_FUN_EXPORT PFNGLGENBUFFERSARBPROC __glewGenBuffersARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB; +GLEW_FUN_EXPORT PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB; +GLEW_FUN_EXPORT PFNGLISBUFFERARBPROC __glewIsBufferARB; +GLEW_FUN_EXPORT PFNGLMAPBUFFERARBPROC __glewMapBufferARB; +GLEW_FUN_EXPORT PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB; + +GLEW_FUN_EXPORT PFNGLBINDPROGRAMARBPROC __glewBindProgramARB; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB; +GLEW_FUN_EXPORT PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB; +GLEW_FUN_EXPORT PFNGLISPROGRAMARBPROC __glewIsProgramARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB; +GLEW_FUN_EXPORT PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB; + +GLEW_FUN_EXPORT PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB; +GLEW_FUN_EXPORT PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB; +GLEW_FUN_EXPORT PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB; + +GLEW_FUN_EXPORT PFNGLCOLORP3UIPROC __glewColorP3ui; +GLEW_FUN_EXPORT PFNGLCOLORP3UIVPROC __glewColorP3uiv; +GLEW_FUN_EXPORT PFNGLCOLORP4UIPROC __glewColorP4ui; +GLEW_FUN_EXPORT PFNGLCOLORP4UIVPROC __glewColorP4uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIPROC __glewMultiTexCoordP1ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP1UIVPROC __glewMultiTexCoordP1uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIPROC __glewMultiTexCoordP2ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP2UIVPROC __glewMultiTexCoordP2uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIPROC __glewMultiTexCoordP3ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP3UIVPROC __glewMultiTexCoordP3uiv; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIPROC __glewMultiTexCoordP4ui; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDP4UIVPROC __glewMultiTexCoordP4uiv; +GLEW_FUN_EXPORT PFNGLNORMALP3UIPROC __glewNormalP3ui; +GLEW_FUN_EXPORT PFNGLNORMALP3UIVPROC __glewNormalP3uiv; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIPROC __glewSecondaryColorP3ui; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORP3UIVPROC __glewSecondaryColorP3uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIPROC __glewTexCoordP1ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP1UIVPROC __glewTexCoordP1uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIPROC __glewTexCoordP2ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP2UIVPROC __glewTexCoordP2uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIPROC __glewTexCoordP3ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP3UIVPROC __glewTexCoordP3uiv; +GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIPROC __glewTexCoordP4ui; +GLEW_FUN_EXPORT PFNGLTEXCOORDP4UIVPROC __glewTexCoordP4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIPROC __glewVertexAttribP1ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP1UIVPROC __glewVertexAttribP1uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIPROC __glewVertexAttribP2ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP2UIVPROC __glewVertexAttribP2uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIPROC __glewVertexAttribP3ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP3UIVPROC __glewVertexAttribP3uiv; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIPROC __glewVertexAttribP4ui; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBP4UIVPROC __glewVertexAttribP4uiv; +GLEW_FUN_EXPORT PFNGLVERTEXP2UIPROC __glewVertexP2ui; +GLEW_FUN_EXPORT PFNGLVERTEXP2UIVPROC __glewVertexP2uiv; +GLEW_FUN_EXPORT PFNGLVERTEXP3UIPROC __glewVertexP3ui; +GLEW_FUN_EXPORT PFNGLVERTEXP3UIVPROC __glewVertexP3uiv; +GLEW_FUN_EXPORT PFNGLVERTEXP4UIPROC __glewVertexP4ui; +GLEW_FUN_EXPORT PFNGLVERTEXP4UIVPROC __glewVertexP4uiv; + +GLEW_FUN_EXPORT PFNGLDEPTHRANGEARRAYVPROC __glewDepthRangeArrayv; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEINDEXEDPROC __glewDepthRangeIndexed; +GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VPROC __glewGetDoublei_v; +GLEW_FUN_EXPORT PFNGLGETFLOATI_VPROC __glewGetFloati_v; +GLEW_FUN_EXPORT PFNGLSCISSORARRAYVPROC __glewScissorArrayv; +GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDPROC __glewScissorIndexed; +GLEW_FUN_EXPORT PFNGLSCISSORINDEXEDVPROC __glewScissorIndexedv; +GLEW_FUN_EXPORT PFNGLVIEWPORTARRAYVPROC __glewViewportArrayv; +GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFPROC __glewViewportIndexedf; +GLEW_FUN_EXPORT PFNGLVIEWPORTINDEXEDFVPROC __glewViewportIndexedfv; + +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB; + +GLEW_FUN_EXPORT PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI; + +GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI; +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI; +GLEW_FUN_EXPORT PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI; + +GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI; +GLEW_FUN_EXPORT PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI; +GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI; +GLEW_FUN_EXPORT PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI; + +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI; +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI; +GLEW_FUN_EXPORT PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI; +GLEW_FUN_EXPORT PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI; +GLEW_FUN_EXPORT PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI; +GLEW_FUN_EXPORT PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI; +GLEW_FUN_EXPORT PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI; +GLEW_FUN_EXPORT PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI; +GLEW_FUN_EXPORT PFNGLSAMPLEMAPATIPROC __glewSampleMapATI; +GLEW_FUN_EXPORT PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI; + +GLEW_FUN_EXPORT PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI; +GLEW_FUN_EXPORT PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI; + +GLEW_FUN_EXPORT PFNGLPNTRIANGLESFATIPROC __glewPNTrianglesfATI; +GLEW_FUN_EXPORT PFNGLPNTRIANGLESIATIPROC __glewPNTrianglesiATI; + +GLEW_FUN_EXPORT PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI; +GLEW_FUN_EXPORT PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI; + +GLEW_FUN_EXPORT PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI; +GLEW_FUN_EXPORT PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI; +GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI; +GLEW_FUN_EXPORT PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI; +GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI; +GLEW_FUN_EXPORT PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI; +GLEW_FUN_EXPORT PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI; +GLEW_FUN_EXPORT PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI; + +GLEW_FUN_EXPORT PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI; +GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI; +GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI; +GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI; + +GLEW_FUN_EXPORT PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT; +GLEW_FUN_EXPORT PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT; +GLEW_FUN_EXPORT PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT; + +GLEW_FUN_EXPORT PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT; + +GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT; + +GLEW_FUN_EXPORT PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT; + +GLEW_FUN_EXPORT PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT; +GLEW_FUN_EXPORT PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT; + +GLEW_FUN_EXPORT PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT; +GLEW_FUN_EXPORT PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT; + +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT; +GLEW_FUN_EXPORT PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT; +GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT; + +GLEW_FUN_EXPORT PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT; +GLEW_FUN_EXPORT PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT; + +GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT; + +GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT; +GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT; + +GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT; + +GLEW_FUN_EXPORT PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT; +GLEW_FUN_EXPORT PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC __glewCheckNamedFramebufferStatusEXT; +GLEW_FUN_EXPORT PFNGLCLIENTATTRIBDEFAULTEXTPROC __glewClientAttribDefaultEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC __glewCompressedMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC __glewCompressedMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC __glewCompressedMultiTexImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC __glewCompressedMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC __glewCompressedMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC __glewCompressedMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC __glewCompressedTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC __glewCompressedTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC __glewCompressedTextureImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC __glewCompressedTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC __glewCompressedTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC __glewCompressedTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE1DEXTPROC __glewCopyMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXIMAGE2DEXTPROC __glewCopyMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC __glewCopyMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC __glewCopyMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC __glewCopyMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE1DEXTPROC __glewCopyTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTUREIMAGE2DEXTPROC __glewCopyTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC __glewCopyTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC __glewCopyTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC __glewCopyTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC __glewDisableClientStateIndexedEXT; +GLEW_FUN_EXPORT PFNGLDISABLECLIENTSTATEIEXTPROC __glewDisableClientStateiEXT; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC __glewDisableVertexArrayAttribEXT; +GLEW_FUN_EXPORT PFNGLDISABLEVERTEXARRAYEXTPROC __glewDisableVertexArrayEXT; +GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEINDEXEDEXTPROC __glewEnableClientStateIndexedEXT; +GLEW_FUN_EXPORT PFNGLENABLECLIENTSTATEIEXTPROC __glewEnableClientStateiEXT; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYATTRIBEXTPROC __glewEnableVertexArrayAttribEXT; +GLEW_FUN_EXPORT PFNGLENABLEVERTEXARRAYEXTPROC __glewEnableVertexArrayEXT; +GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC __glewFlushMappedNamedBufferRangeEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC __glewFramebufferDrawBufferEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC __glewFramebufferDrawBuffersEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERREADBUFFEREXTPROC __glewFramebufferReadBufferEXT; +GLEW_FUN_EXPORT PFNGLGENERATEMULTITEXMIPMAPEXTPROC __glewGenerateMultiTexMipmapEXT; +GLEW_FUN_EXPORT PFNGLGENERATETEXTUREMIPMAPEXTPROC __glewGenerateTextureMipmapEXT; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC __glewGetCompressedMultiTexImageEXT; +GLEW_FUN_EXPORT PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC __glewGetCompressedTextureImageEXT; +GLEW_FUN_EXPORT PFNGLGETDOUBLEINDEXEDVEXTPROC __glewGetDoubleIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETDOUBLEI_VEXTPROC __glewGetDoublei_vEXT; +GLEW_FUN_EXPORT PFNGLGETFLOATINDEXEDVEXTPROC __glewGetFloatIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETFLOATI_VEXTPROC __glewGetFloati_vEXT; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC __glewGetFramebufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXENVFVEXTPROC __glewGetMultiTexEnvfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXENVIVEXTPROC __glewGetMultiTexEnvivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENDVEXTPROC __glewGetMultiTexGendvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENFVEXTPROC __glewGetMultiTexGenfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXGENIVEXTPROC __glewGetMultiTexGenivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXIMAGEEXTPROC __glewGetMultiTexImageEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC __glewGetMultiTexLevelParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC __glewGetMultiTexLevelParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIIVEXTPROC __glewGetMultiTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIUIVEXTPROC __glewGetMultiTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERFVEXTPROC __glewGetMultiTexParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMULTITEXPARAMETERIVEXTPROC __glewGetMultiTexParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC __glewGetNamedBufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPOINTERVEXTPROC __glewGetNamedBufferPointervEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERSUBDATAEXTPROC __glewGetNamedBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetNamedFramebufferAttachmentParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC __glewGetNamedProgramLocalParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC __glewGetNamedProgramLocalParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC __glewGetNamedProgramLocalParameterdvEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC __glewGetNamedProgramLocalParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMSTRINGEXTPROC __glewGetNamedProgramStringEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDPROGRAMIVEXTPROC __glewGetNamedProgramivEXT; +GLEW_FUN_EXPORT PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC __glewGetNamedRenderbufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETPOINTERINDEXEDVEXTPROC __glewGetPointerIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETPOINTERI_VEXTPROC __glewGetPointeri_vEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREIMAGEEXTPROC __glewGetTextureImageEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC __glewGetTextureLevelParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC __glewGetTextureLevelParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIIVEXTPROC __glewGetTextureParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIUIVEXTPROC __glewGetTextureParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERFVEXTPROC __glewGetTextureParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETTEXTUREPARAMETERIVEXTPROC __glewGetTextureParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC __glewGetVertexArrayIntegeri_vEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYINTEGERVEXTPROC __glewGetVertexArrayIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC __glewGetVertexArrayPointeri_vEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXARRAYPOINTERVEXTPROC __glewGetVertexArrayPointervEXT; +GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFEREXTPROC __glewMapNamedBufferEXT; +GLEW_FUN_EXPORT PFNGLMAPNAMEDBUFFERRANGEEXTPROC __glewMapNamedBufferRangeEXT; +GLEW_FUN_EXPORT PFNGLMATRIXFRUSTUMEXTPROC __glewMatrixFrustumEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADIDENTITYEXTPROC __glewMatrixLoadIdentityEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEDEXTPROC __glewMatrixLoadTransposedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADTRANSPOSEFEXTPROC __glewMatrixLoadTransposefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADDEXTPROC __glewMatrixLoaddEXT; +GLEW_FUN_EXPORT PFNGLMATRIXLOADFEXTPROC __glewMatrixLoadfEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEDEXTPROC __glewMatrixMultTransposedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTTRANSPOSEFEXTPROC __glewMatrixMultTransposefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTDEXTPROC __glewMatrixMultdEXT; +GLEW_FUN_EXPORT PFNGLMATRIXMULTFEXTPROC __glewMatrixMultfEXT; +GLEW_FUN_EXPORT PFNGLMATRIXORTHOEXTPROC __glewMatrixOrthoEXT; +GLEW_FUN_EXPORT PFNGLMATRIXPOPEXTPROC __glewMatrixPopEXT; +GLEW_FUN_EXPORT PFNGLMATRIXPUSHEXTPROC __glewMatrixPushEXT; +GLEW_FUN_EXPORT PFNGLMATRIXROTATEDEXTPROC __glewMatrixRotatedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXROTATEFEXTPROC __glewMatrixRotatefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXSCALEDEXTPROC __glewMatrixScaledEXT; +GLEW_FUN_EXPORT PFNGLMATRIXSCALEFEXTPROC __glewMatrixScalefEXT; +GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEDEXTPROC __glewMatrixTranslatedEXT; +GLEW_FUN_EXPORT PFNGLMATRIXTRANSLATEFEXTPROC __glewMatrixTranslatefEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXBUFFEREXTPROC __glewMultiTexBufferEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORDPOINTEREXTPROC __glewMultiTexCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVFEXTPROC __glewMultiTexEnvfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVFVEXTPROC __glewMultiTexEnvfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVIEXTPROC __glewMultiTexEnviEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXENVIVEXTPROC __glewMultiTexEnvivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENDEXTPROC __glewMultiTexGendEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENDVEXTPROC __glewMultiTexGendvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENFEXTPROC __glewMultiTexGenfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENFVEXTPROC __glewMultiTexGenfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENIEXTPROC __glewMultiTexGeniEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXGENIVEXTPROC __glewMultiTexGenivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE1DEXTPROC __glewMultiTexImage1DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE2DEXTPROC __glewMultiTexImage2DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXIMAGE3DEXTPROC __glewMultiTexImage3DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIIVEXTPROC __glewMultiTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIUIVEXTPROC __glewMultiTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFEXTPROC __glewMultiTexParameterfEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERFVEXTPROC __glewMultiTexParameterfvEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIEXTPROC __glewMultiTexParameteriEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXPARAMETERIVEXTPROC __glewMultiTexParameterivEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXRENDERBUFFEREXTPROC __glewMultiTexRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE1DEXTPROC __glewMultiTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE2DEXTPROC __glewMultiTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLMULTITEXSUBIMAGE3DEXTPROC __glewMultiTexSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDBUFFERDATAEXTPROC __glewNamedBufferDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDBUFFERSUBDATAEXTPROC __glewNamedBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC __glewNamedCopyBufferSubDataEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC __glewNamedFramebufferRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC __glewNamedFramebufferTexture1DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC __glewNamedFramebufferTexture2DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC __glewNamedFramebufferTexture3DEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC __glewNamedFramebufferTextureEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC __glewNamedFramebufferTextureFaceEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC __glewNamedFramebufferTextureLayerEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC __glewNamedProgramLocalParameter4dEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC __glewNamedProgramLocalParameter4dvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC __glewNamedProgramLocalParameter4fEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC __glewNamedProgramLocalParameter4fvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC __glewNamedProgramLocalParameterI4iEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC __glewNamedProgramLocalParameterI4ivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC __glewNamedProgramLocalParameterI4uiEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC __glewNamedProgramLocalParameterI4uivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC __glewNamedProgramLocalParameters4fvEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC __glewNamedProgramLocalParametersI4ivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC __glewNamedProgramLocalParametersI4uivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDPROGRAMSTRINGEXTPROC __glewNamedProgramStringEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC __glewNamedRenderbufferStorageEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC __glewNamedRenderbufferStorageMultisampleCoverageEXT; +GLEW_FUN_EXPORT PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewNamedRenderbufferStorageMultisampleEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIEXTPROC __glewProgramUniform1uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UIVEXTPROC __glewProgramUniform1uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIEXTPROC __glewProgramUniform2uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UIVEXTPROC __glewProgramUniform2uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIEXTPROC __glewProgramUniform3uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UIVEXTPROC __glewProgramUniform3uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIEXTPROC __glewProgramUniform4uiEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UIVEXTPROC __glewProgramUniform4uivEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __glewProgramUniformMatrix2x3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __glewProgramUniformMatrix2x4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __glewProgramUniformMatrix3x2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __glewProgramUniformMatrix3x4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __glewProgramUniformMatrix4x2fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __glewProgramUniformMatrix4x3fvEXT; +GLEW_FUN_EXPORT PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC __glewPushClientAttribDefaultEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREBUFFEREXTPROC __glewTextureBufferEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE1DEXTPROC __glewTextureImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DEXTPROC __glewTextureImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DEXTPROC __glewTextureImage3DEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIIVEXTPROC __glewTextureParameterIivEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIUIVEXTPROC __glewTextureParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFEXTPROC __glewTextureParameterfEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERFVEXTPROC __glewTextureParameterfvEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIEXTPROC __glewTextureParameteriEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREPARAMETERIVEXTPROC __glewTextureParameterivEXT; +GLEW_FUN_EXPORT PFNGLTEXTURERENDERBUFFEREXTPROC __glewTextureRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE1DEXTPROC __glewTextureSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE2DEXTPROC __glewTextureSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESUBIMAGE3DEXTPROC __glewTextureSubImage3DEXT; +GLEW_FUN_EXPORT PFNGLUNMAPNAMEDBUFFEREXTPROC __glewUnmapNamedBufferEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYCOLOROFFSETEXTPROC __glewVertexArrayColorOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC __glewVertexArrayEdgeFlagOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC __glewVertexArrayFogCoordOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYINDEXOFFSETEXTPROC __glewVertexArrayIndexOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC __glewVertexArrayMultiTexCoordOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYNORMALOFFSETEXTPROC __glewVertexArrayNormalOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC __glewVertexArraySecondaryColorOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC __glewVertexArrayTexCoordOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC __glewVertexArrayVertexAttribIOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC __glewVertexArrayVertexAttribOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC __glewVertexArrayVertexOffsetEXT; + +GLEW_FUN_EXPORT PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT; +GLEW_FUN_EXPORT PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT; +GLEW_FUN_EXPORT PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT; +GLEW_FUN_EXPORT PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT; +GLEW_FUN_EXPORT PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT; +GLEW_FUN_EXPORT PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT; + +GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT; + +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT; +GLEW_FUN_EXPORT PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT; + +GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT; +GLEW_FUN_EXPORT PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT; + +GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT; + +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT; + +GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT; +GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT; +GLEW_FUN_EXPORT PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT; +GLEW_FUN_EXPORT PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT; +GLEW_FUN_EXPORT PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT; +GLEW_FUN_EXPORT PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT; +GLEW_FUN_EXPORT PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT; +GLEW_FUN_EXPORT PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT; +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT; + +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT; + +GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT; +GLEW_FUN_EXPORT PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT; +GLEW_FUN_EXPORT PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT; + +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT; +GLEW_FUN_EXPORT PFNGLHISTOGRAMEXTPROC __glewHistogramEXT; +GLEW_FUN_EXPORT PFNGLMINMAXEXTPROC __glewMinmaxEXT; +GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT; +GLEW_FUN_EXPORT PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT; + +GLEW_FUN_EXPORT PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT; + +GLEW_FUN_EXPORT PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT; + +GLEW_FUN_EXPORT PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT; +GLEW_FUN_EXPORT PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT; +GLEW_FUN_EXPORT PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT; + +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT; + +GLEW_FUN_EXPORT PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT; +GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT; + +GLEW_FUN_EXPORT PFNGLCOLORTABLEEXTPROC __glewColorTableEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT; + +GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT; +GLEW_FUN_EXPORT PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT; + +GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT; + +GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXEXTPROC __glewProvokingVertexEXT; + +GLEW_FUN_EXPORT PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT; +GLEW_FUN_EXPORT PFNGLENDSCENEEXTPROC __glewEndSceneEXT; + +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT; + +GLEW_FUN_EXPORT PFNGLACTIVEPROGRAMEXTPROC __glewActiveProgramEXT; +GLEW_FUN_EXPORT PFNGLCREATESHADERPROGRAMEXTPROC __glewCreateShaderProgramEXT; +GLEW_FUN_EXPORT PFNGLUSESHADERPROGRAMEXTPROC __glewUseShaderProgramEXT; + +GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTUREEXTPROC __glewBindImageTextureEXT; +GLEW_FUN_EXPORT PFNGLMEMORYBARRIEREXTPROC __glewMemoryBarrierEXT; + +GLEW_FUN_EXPORT PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT; + +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT; + +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT; + +GLEW_FUN_EXPORT PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT; + +GLEW_FUN_EXPORT PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT; +GLEW_FUN_EXPORT PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT; + +GLEW_FUN_EXPORT PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT; +GLEW_FUN_EXPORT PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT; +GLEW_FUN_EXPORT PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT; +GLEW_FUN_EXPORT PFNGLISTEXTUREEXTPROC __glewIsTextureEXT; +GLEW_FUN_EXPORT PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT; + +GLEW_FUN_EXPORT PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT; + +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT; + +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKEXTPROC __glewBeginTransformFeedbackEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASEEXTPROC __glewBindBufferBaseEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETEXTPROC __glewBindBufferOffsetEXT; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGEEXTPROC __glewBindBufferRangeEXT; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKEXTPROC __glewEndTransformFeedbackEXT; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC __glewGetTransformFeedbackVaryingEXT; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC __glewTransformFeedbackVaryingsEXT; + +GLEW_FUN_EXPORT PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT; +GLEW_FUN_EXPORT PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT; +GLEW_FUN_EXPORT PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT; +GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT; +GLEW_FUN_EXPORT PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT; +GLEW_FUN_EXPORT PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLDVEXTPROC __glewGetVertexAttribLdvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC __glewVertexArrayVertexAttribLOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DEXTPROC __glewVertexAttribL1dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1DVEXTPROC __glewVertexAttribL1dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DEXTPROC __glewVertexAttribL2dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2DVEXTPROC __glewVertexAttribL2dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DEXTPROC __glewVertexAttribL3dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3DVEXTPROC __glewVertexAttribL3dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DEXTPROC __glewVertexAttribL4dEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVEXTPROC __glewVertexAttribL4dvEXT; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTEREXTPROC __glewVertexAttribLPointerEXT; + +GLEW_FUN_EXPORT PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT; +GLEW_FUN_EXPORT PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT; +GLEW_FUN_EXPORT PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT; +GLEW_FUN_EXPORT PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT; +GLEW_FUN_EXPORT PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT; +GLEW_FUN_EXPORT PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT; +GLEW_FUN_EXPORT PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT; +GLEW_FUN_EXPORT PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT; +GLEW_FUN_EXPORT PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT; +GLEW_FUN_EXPORT PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT; +GLEW_FUN_EXPORT PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT; +GLEW_FUN_EXPORT PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT; +GLEW_FUN_EXPORT PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT; +GLEW_FUN_EXPORT PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT; +GLEW_FUN_EXPORT PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT; +GLEW_FUN_EXPORT PFNGLSWIZZLEEXTPROC __glewSwizzleEXT; +GLEW_FUN_EXPORT PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT; +GLEW_FUN_EXPORT PFNGLVARIANTBVEXTPROC __glewVariantbvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTDVEXTPROC __glewVariantdvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTFVEXTPROC __glewVariantfvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTIVEXTPROC __glewVariantivEXT; +GLEW_FUN_EXPORT PFNGLVARIANTSVEXTPROC __glewVariantsvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT; +GLEW_FUN_EXPORT PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT; +GLEW_FUN_EXPORT PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT; + +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT; + +GLEW_FUN_EXPORT PFNGLIMPORTSYNCEXTPROC __glewImportSyncEXT; + +GLEW_FUN_EXPORT PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY; + +GLEW_FUN_EXPORT PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY; + +GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP; +GLEW_FUN_EXPORT PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP; +GLEW_FUN_EXPORT PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP; + +GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM; +GLEW_FUN_EXPORT PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM; + +GLEW_FUN_EXPORT PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM; +GLEW_FUN_EXPORT PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM; +GLEW_FUN_EXPORT PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM; +GLEW_FUN_EXPORT PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM; +GLEW_FUN_EXPORT PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM; + +GLEW_FUN_EXPORT PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL; +GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL; +GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL; +GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL; + +GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL; +GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL; + +GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT; + +GLEW_FUN_EXPORT PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA; + +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA; +GLEW_FUN_EXPORT PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA; + +GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV; +GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV; + +GLEW_FUN_EXPORT PFNGLCOPYIMAGESUBDATANVPROC __glewCopyImageSubDataNV; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV; +GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV; + +GLEW_FUN_EXPORT PFNGLEVALMAPSNVPROC __glewEvalMapsNV; +GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV; +GLEW_FUN_EXPORT PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV; +GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV; +GLEW_FUN_EXPORT PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV; +GLEW_FUN_EXPORT PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV; +GLEW_FUN_EXPORT PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV; + +GLEW_FUN_EXPORT PFNGLGETMULTISAMPLEFVNVPROC __glewGetMultisamplefvNV; +GLEW_FUN_EXPORT PFNGLSAMPLEMASKINDEXEDNVPROC __glewSampleMaskIndexedNV; +GLEW_FUN_EXPORT PFNGLTEXRENDERBUFFERNVPROC __glewTexRenderbufferNV; + +GLEW_FUN_EXPORT PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV; +GLEW_FUN_EXPORT PFNGLFINISHFENCENVPROC __glewFinishFenceNV; +GLEW_FUN_EXPORT PFNGLGENFENCESNVPROC __glewGenFencesNV; +GLEW_FUN_EXPORT PFNGLGETFENCEIVNVPROC __glewGetFenceivNV; +GLEW_FUN_EXPORT PFNGLISFENCENVPROC __glewIsFenceNV; +GLEW_FUN_EXPORT PFNGLSETFENCENVPROC __glewSetFenceNV; +GLEW_FUN_EXPORT PFNGLTESTFENCENVPROC __glewTestFenceNV; + +GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV; +GLEW_FUN_EXPORT PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV; + +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV; + +GLEW_FUN_EXPORT PFNGLGETUNIFORMI64VNVPROC __glewGetUniformi64vNV; +GLEW_FUN_EXPORT PFNGLGETUNIFORMUI64VNVPROC __glewGetUniformui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64NVPROC __glewProgramUniform1i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1I64VNVPROC __glewProgramUniform1i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64NVPROC __glewProgramUniform1ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1UI64VNVPROC __glewProgramUniform1ui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64NVPROC __glewProgramUniform2i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2I64VNVPROC __glewProgramUniform2i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64NVPROC __glewProgramUniform2ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2UI64VNVPROC __glewProgramUniform2ui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64NVPROC __glewProgramUniform3i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3I64VNVPROC __glewProgramUniform3i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64NVPROC __glewProgramUniform3ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3UI64VNVPROC __glewProgramUniform3ui64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64NVPROC __glewProgramUniform4i64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4I64VNVPROC __glewProgramUniform4i64vNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64NVPROC __glewProgramUniform4ui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4UI64VNVPROC __glewProgramUniform4ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM1I64NVPROC __glewUniform1i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM1I64VNVPROC __glewUniform1i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM1UI64NVPROC __glewUniform1ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM1UI64VNVPROC __glewUniform1ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM2I64NVPROC __glewUniform2i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM2I64VNVPROC __glewUniform2i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM2UI64NVPROC __glewUniform2ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM2UI64VNVPROC __glewUniform2ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM3I64NVPROC __glewUniform3i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM3I64VNVPROC __glewUniform3i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM3UI64NVPROC __glewUniform3ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM3UI64VNVPROC __glewUniform3ui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM4I64NVPROC __glewUniform4i64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM4I64VNVPROC __glewUniform4i64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORM4UI64NVPROC __glewUniform4ui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORM4UI64VNVPROC __glewUniform4ui64vNV; + +GLEW_FUN_EXPORT PFNGLCOLOR3HNVPROC __glewColor3hNV; +GLEW_FUN_EXPORT PFNGLCOLOR3HVNVPROC __glewColor3hvNV; +GLEW_FUN_EXPORT PFNGLCOLOR4HNVPROC __glewColor4hNV; +GLEW_FUN_EXPORT PFNGLCOLOR4HVNVPROC __glewColor4hvNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDHNVPROC __glewFogCoordhNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV; +GLEW_FUN_EXPORT PFNGLNORMAL3HNVPROC __glewNormal3hNV; +GLEW_FUN_EXPORT PFNGLNORMAL3HVNVPROC __glewNormal3hvNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV; +GLEW_FUN_EXPORT PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX2HNVPROC __glewVertex2hNV; +GLEW_FUN_EXPORT PFNGLVERTEX2HVNVPROC __glewVertex2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX3HNVPROC __glewVertex3hNV; +GLEW_FUN_EXPORT PFNGLVERTEX3HVNVPROC __glewVertex3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEX4HNVPROC __glewVertex4hNV; +GLEW_FUN_EXPORT PFNGLVERTEX4HVNVPROC __glewVertex4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV; +GLEW_FUN_EXPORT PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV; + +GLEW_FUN_EXPORT PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV; +GLEW_FUN_EXPORT PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV; +GLEW_FUN_EXPORT PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV; +GLEW_FUN_EXPORT PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV; +GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV; +GLEW_FUN_EXPORT PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV; +GLEW_FUN_EXPORT PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV; + +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV; +GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV; + +GLEW_FUN_EXPORT PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV; +GLEW_FUN_EXPORT PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV; + +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV; + +GLEW_FUN_EXPORT PFNGLGETVIDEOI64VNVPROC __glewGetVideoi64vNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOIVNVPROC __glewGetVideoivNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOUI64VNVPROC __glewGetVideoui64vNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOUIVNVPROC __glewGetVideouivNV; +GLEW_FUN_EXPORT PFNGLPRESENTFRAMEDUALFILLNVPROC __glewPresentFrameDualFillNV; +GLEW_FUN_EXPORT PFNGLPRESENTFRAMEKEYEDNVPROC __glewPresentFrameKeyedNV; + +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV; +GLEW_FUN_EXPORT PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV; + +GLEW_FUN_EXPORT PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV; +GLEW_FUN_EXPORT PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV; +GLEW_FUN_EXPORT PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV; +GLEW_FUN_EXPORT PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV; +GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV; + +GLEW_FUN_EXPORT PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV; + +GLEW_FUN_EXPORT PFNGLGETBUFFERPARAMETERUI64VNVPROC __glewGetBufferParameterui64vNV; +GLEW_FUN_EXPORT PFNGLGETINTEGERUI64VNVPROC __glewGetIntegerui64vNV; +GLEW_FUN_EXPORT PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC __glewGetNamedBufferParameterui64vNV; +GLEW_FUN_EXPORT PFNGLISBUFFERRESIDENTNVPROC __glewIsBufferResidentNV; +GLEW_FUN_EXPORT PFNGLISNAMEDBUFFERRESIDENTNVPROC __glewIsNamedBufferResidentNV; +GLEW_FUN_EXPORT PFNGLMAKEBUFFERNONRESIDENTNVPROC __glewMakeBufferNonResidentNV; +GLEW_FUN_EXPORT PFNGLMAKEBUFFERRESIDENTNVPROC __glewMakeBufferResidentNV; +GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC __glewMakeNamedBufferNonResidentNV; +GLEW_FUN_EXPORT PFNGLMAKENAMEDBUFFERRESIDENTNVPROC __glewMakeNamedBufferResidentNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64NVPROC __glewProgramUniformui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMUI64VNVPROC __glewProgramUniformui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORMUI64NVPROC __glewUniformui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORMUI64VNVPROC __glewUniformui64vNV; + +GLEW_FUN_EXPORT PFNGLTEXTUREBARRIERNVPROC __glewTextureBarrierNV; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTexImage2DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTexImage3DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTextureImage2DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC __glewTextureImage2DMultisampleNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTextureImage3DMultisampleCoverageNV; +GLEW_FUN_EXPORT PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC __glewTextureImage3DMultisampleNV; + +GLEW_FUN_EXPORT PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV; +GLEW_FUN_EXPORT PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV; +GLEW_FUN_EXPORT PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV; +GLEW_FUN_EXPORT PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV; +GLEW_FUN_EXPORT PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV; +GLEW_FUN_EXPORT PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV; +GLEW_FUN_EXPORT PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV; + +GLEW_FUN_EXPORT PFNGLBINDTRANSFORMFEEDBACKNVPROC __glewBindTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLDELETETRANSFORMFEEDBACKSNVPROC __glewDeleteTransformFeedbacksNV; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKNVPROC __glewDrawTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLGENTRANSFORMFEEDBACKSNVPROC __glewGenTransformFeedbacksNV; +GLEW_FUN_EXPORT PFNGLISTRANSFORMFEEDBACKNVPROC __glewIsTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLPAUSETRANSFORMFEEDBACKNVPROC __glewPauseTransformFeedbackNV; +GLEW_FUN_EXPORT PFNGLRESUMETRANSFORMFEEDBACKNVPROC __glewResumeTransformFeedbackNV; + +GLEW_FUN_EXPORT PFNGLVDPAUFININVPROC __glewVDPAUFiniNV; +GLEW_FUN_EXPORT PFNGLVDPAUGETSURFACEIVNVPROC __glewVDPAUGetSurfaceivNV; +GLEW_FUN_EXPORT PFNGLVDPAUINITNVPROC __glewVDPAUInitNV; +GLEW_FUN_EXPORT PFNGLVDPAUISSURFACENVPROC __glewVDPAUIsSurfaceNV; +GLEW_FUN_EXPORT PFNGLVDPAUMAPSURFACESNVPROC __glewVDPAUMapSurfacesNV; +GLEW_FUN_EXPORT PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC __glewVDPAURegisterOutputSurfaceNV; +GLEW_FUN_EXPORT PFNGLVDPAUREGISTERVIDEOSURFACENVPROC __glewVDPAURegisterVideoSurfaceNV; +GLEW_FUN_EXPORT PFNGLVDPAUSURFACEACCESSNVPROC __glewVDPAUSurfaceAccessNV; +GLEW_FUN_EXPORT PFNGLVDPAUUNMAPSURFACESNVPROC __glewVDPAUUnmapSurfacesNV; +GLEW_FUN_EXPORT PFNGLVDPAUUNREGISTERSURFACENVPROC __glewVDPAUUnregisterSurfaceNV; + +GLEW_FUN_EXPORT PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV; + +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLI64VNVPROC __glewGetVertexAttribLi64vNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLUI64VNVPROC __glewGetVertexAttribLui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64NVPROC __glewVertexAttribL1i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1I64VNVPROC __glewVertexAttribL1i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64NVPROC __glewVertexAttribL1ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64VNVPROC __glewVertexAttribL1ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64NVPROC __glewVertexAttribL2i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2I64VNVPROC __glewVertexAttribL2i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64NVPROC __glewVertexAttribL2ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL2UI64VNVPROC __glewVertexAttribL2ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64NVPROC __glewVertexAttribL3i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3I64VNVPROC __glewVertexAttribL3i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64NVPROC __glewVertexAttribL3ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL3UI64VNVPROC __glewVertexAttribL3ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64NVPROC __glewVertexAttribL4i64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4I64VNVPROC __glewVertexAttribL4i64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64NVPROC __glewVertexAttribL4ui64NV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4UI64VNVPROC __glewVertexAttribL4ui64vNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLFORMATNVPROC __glewVertexAttribLFormatNV; + +GLEW_FUN_EXPORT PFNGLBUFFERADDRESSRANGENVPROC __glewBufferAddressRangeNV; +GLEW_FUN_EXPORT PFNGLCOLORFORMATNVPROC __glewColorFormatNV; +GLEW_FUN_EXPORT PFNGLEDGEFLAGFORMATNVPROC __glewEdgeFlagFormatNV; +GLEW_FUN_EXPORT PFNGLFOGCOORDFORMATNVPROC __glewFogCoordFormatNV; +GLEW_FUN_EXPORT PFNGLGETINTEGERUI64I_VNVPROC __glewGetIntegerui64i_vNV; +GLEW_FUN_EXPORT PFNGLINDEXFORMATNVPROC __glewIndexFormatNV; +GLEW_FUN_EXPORT PFNGLNORMALFORMATNVPROC __glewNormalFormatNV; +GLEW_FUN_EXPORT PFNGLSECONDARYCOLORFORMATNVPROC __glewSecondaryColorFormatNV; +GLEW_FUN_EXPORT PFNGLTEXCOORDFORMATNVPROC __glewTexCoordFormatNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBFORMATNVPROC __glewVertexAttribFormatNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIFORMATNVPROC __glewVertexAttribIFormatNV; +GLEW_FUN_EXPORT PFNGLVERTEXFORMATNVPROC __glewVertexFormatNV; + +GLEW_FUN_EXPORT PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV; +GLEW_FUN_EXPORT PFNGLBINDPROGRAMNVPROC __glewBindProgramNV; +GLEW_FUN_EXPORT PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV; +GLEW_FUN_EXPORT PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV; +GLEW_FUN_EXPORT PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV; +GLEW_FUN_EXPORT PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV; +GLEW_FUN_EXPORT PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV; +GLEW_FUN_EXPORT PFNGLISPROGRAMNVPROC __glewIsProgramNV; +GLEW_FUN_EXPORT PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV; +GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV; +GLEW_FUN_EXPORT PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV; +GLEW_FUN_EXPORT PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV; + +GLEW_FUN_EXPORT PFNGLBEGINVIDEOCAPTURENVPROC __glewBeginVideoCaptureNV; +GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC __glewBindVideoCaptureStreamBufferNV; +GLEW_FUN_EXPORT PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC __glewBindVideoCaptureStreamTextureNV; +GLEW_FUN_EXPORT PFNGLENDVIDEOCAPTURENVPROC __glewEndVideoCaptureNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMDVNVPROC __glewGetVideoCaptureStreamdvNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMFVNVPROC __glewGetVideoCaptureStreamfvNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTURESTREAMIVNVPROC __glewGetVideoCaptureStreamivNV; +GLEW_FUN_EXPORT PFNGLGETVIDEOCAPTUREIVNVPROC __glewGetVideoCaptureivNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURENVPROC __glewVideoCaptureNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC __glewVideoCaptureStreamParameterdvNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC __glewVideoCaptureStreamParameterfvNV; +GLEW_FUN_EXPORT PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC __glewVideoCaptureStreamParameterivNV; + +GLEW_FUN_EXPORT PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES; +GLEW_FUN_EXPORT PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES; +GLEW_FUN_EXPORT PFNGLFRUSTUMFOESPROC __glewFrustumfOES; +GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES; +GLEW_FUN_EXPORT PFNGLORTHOFOESPROC __glewOrthofOES; + +GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS; +GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS; + +GLEW_FUN_EXPORT PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS; +GLEW_FUN_EXPORT PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS; + +GLEW_FUN_EXPORT PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS; +GLEW_FUN_EXPORT PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS; + +GLEW_FUN_EXPORT PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS; +GLEW_FUN_EXPORT PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS; + +GLEW_FUN_EXPORT PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS; +GLEW_FUN_EXPORT PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS; + +GLEW_FUN_EXPORT PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS; +GLEW_FUN_EXPORT PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS; + +GLEW_FUN_EXPORT PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX; +GLEW_FUN_EXPORT PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX; +GLEW_FUN_EXPORT PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX; +GLEW_FUN_EXPORT PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX; +GLEW_FUN_EXPORT PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX; +GLEW_FUN_EXPORT PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX; + +GLEW_FUN_EXPORT PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX; + +GLEW_FUN_EXPORT PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX; + +GLEW_FUN_EXPORT PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX; +GLEW_FUN_EXPORT PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX; +GLEW_FUN_EXPORT PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX; + +GLEW_FUN_EXPORT PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX; + +GLEW_FUN_EXPORT PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX; + +GLEW_FUN_EXPORT PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX; + +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX; +GLEW_FUN_EXPORT PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX; + +GLEW_FUN_EXPORT PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX; + +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI; +GLEW_FUN_EXPORT PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI; +GLEW_FUN_EXPORT PFNGLCOLORTABLESGIPROC __glewColorTableSGI; +GLEW_FUN_EXPORT PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI; +GLEW_FUN_EXPORT PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI; + +GLEW_FUN_EXPORT PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX; + +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN; +GLEW_FUN_EXPORT PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN; + +GLEW_FUN_EXPORT PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN; + +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN; + +GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN; +GLEW_FUN_EXPORT PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN; +GLEW_FUN_EXPORT PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN; + +GLEW_FUN_EXPORT PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN; + +#if defined(GLEW_MX) && !defined(_WIN32) +struct GLEWContextStruct +{ +#endif /* GLEW_MX */ + +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_3; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_4; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_5; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_0; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_2_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_0; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_2; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_3; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_0; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_1; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_tbuffer; +GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_texture_compression_FXT1; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_blend_minmax_factor; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_conservative_depth; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_debug_output; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_depth_clamp_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_draw_buffers_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_name_gen_delete; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_performance_monitor; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sample_positions; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_seamless_cubemap_per_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_stencil_export; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_texture_texture4; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_transform_feedback3_lines_triangles; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_tessellator; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_aux_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_client_storage; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_element_array; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_fence; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_float_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_flush_buffer_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_object_purgeable; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_pixel_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_rgb_422; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_row_bytes; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_specular_vector; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_texture_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_transform_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_range; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_program_evaluators; +GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_ycbcr_422; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES2_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_blend_func_extended; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_cl_event; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_color_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_debug_output; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_elements_base_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_indirect; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_instanced; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_attrib_location; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_coord_conventions; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_get_program_binary; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader5; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader_fp64; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_pixel; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_imaging; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_instanced_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_range; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_matrix_palette; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multitexture; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query2; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_pixel_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_provoking_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sample_shading; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sampler_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_seamless_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_separate_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_bit_encoding; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_precision; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_stencil_export; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_subroutine; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_100; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_include; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow_ambient; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sync; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_tessellation_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_border_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object_rgb32; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_bptc; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_rgtc; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_cube_map_array; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_add; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_combine; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_crossbar; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_dot3; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_gather; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirrored_repeat; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_non_power_of_two; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rg; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rgb10_a2ui; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_swizzle; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_timer_query; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback2; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback3; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transpose_matrix; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_uniform_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_64bit; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_program; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_viewport_array; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_window_pos; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_point_sprites; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_combine3; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_texture_env_route; +GLEW_VAR_EXPORT GLboolean __GLEW_ATIX_vertex_shader_output_point_size; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_draw_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_element_array; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_envmap_bumpmap; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_map_object_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_meminfo; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_pn_triangles; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_separate_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_shader_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_text_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_compression_3dc; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_env_combine3; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_float; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_texture_mirror_once; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_attrib_array_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ATI_vertex_streams; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_422_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_Cg_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_abgr; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_bindable_uniform; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_equation_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_func_separate; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_logic_op; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_minmax; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_blend_subtract; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_clip_volume_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cmyka; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_color_subtable; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_compiled_vertex_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_direct_state_access; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_buffers2; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_instanced; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_range_elements; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fog_coord; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fragment_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_blit; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_program_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_gpu_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_histogram; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_array_formats; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_func; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_material; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_index_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_light_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_misc_attribute; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multi_draw_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_float; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_packed_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_paletted_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_pixel_transform_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_point_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_polygon_offset; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_provoking_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_rescale_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_scene_marker; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_secondary_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_specular_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_image_load_store; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_funcs; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shared_texture_palette; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_clear_tag; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_two_side; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_wrap; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_subtexture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture3D; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_dxt1; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_latc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_rgtc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_compression_s3tc; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_edge_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_add; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_combine; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_env_dot3; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_filter_anisotropic; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_integer; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_lod_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_mirror_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_object; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_perturb_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_sRGB_decode; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_shared_exponent; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_snorm; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_texture_swizzle; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_timer_query; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_transform_feedback; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_array_bgra; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_attrib_64bit; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_vertex_weighting; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_x11_sync_object; +GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_frame_terminator; +GLEW_VAR_EXPORT GLboolean __GLEW_GREMEDY_string_marker; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_convolution_border_modes; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_image_transform; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_occlusion_test; +GLEW_VAR_EXPORT GLboolean __GLEW_HP_texture_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_cull_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_multimode_draw_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_rasterpos_clip; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_static_data; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat; +GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists; +GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor; +GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region; +GLEW_VAR_EXPORT GLboolean __GLEW_MESAX_texture_stack; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_pack_invert; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_resize_buffers; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_window_pos; +GLEW_VAR_EXPORT GLboolean __GLEW_MESA_ycbcr_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_NVX_gpu_memory_info; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_square; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_conditional_render; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_depth_to_color; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_image; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_buffer_float; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_range_unclamped; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_evaluators; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_explicit_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_float_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fog_distance; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_fragment_program_option; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_framebuffer_multisample_coverage; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_shader4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program5; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program_fp64; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_shader5; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_half_float; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_light_max_exponent; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_coverage; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_multisample_filter_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_occlusion_query; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_depth_stencil; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_data_range; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_point_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_present_video; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_primitive_restart; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_buffer_load; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_tessellation_program5; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_barrier; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_compression_vtc; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_env_combine4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_expand_normal; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_rectangle; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_texture_shader3; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_transform_feedback2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vdpau_interop; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_array_range2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_attrib_integer_64bit; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_buffer_unified_memory; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program1_1; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program2_option; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program3; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_vertex_program4; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_video_capture; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_byte_coordinates; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_compressed_paletted_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_read_format; +GLEW_VAR_EXPORT GLboolean __GLEW_OES_single_precision; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_interlace; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_resample; +GLEW_VAR_EXPORT GLboolean __GLEW_OML_subsample; +GLEW_VAR_EXPORT GLboolean __GLEW_PGI_misc_hints; +GLEW_VAR_EXPORT GLboolean __GLEW_PGI_vertex_hints; +GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates; +GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_detail_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_fog_function; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_generate_mipmap; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_pixel_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_point_line_texgen; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_sharpen_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture4D; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_border_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_edge_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_filter4; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_lod; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_texture_select; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_histogram; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_async_pixel; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_blend_alpha_minmax; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_clipmap; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_convolution_accuracy; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_depth_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_flush_raster; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_offset; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fog_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_fragment_specular_lighting; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_framezoom; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_interlace; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ir_instrument1; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_list_priority; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_pixel_texture_bits; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_reference_plane; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_resample; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_shadow_ambient; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_tag_sample_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_add_env; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_coordinate_clamp; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_lod_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_multi_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_range; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_texture_scale_bias; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_vertex_preclip_hint; +GLEW_VAR_EXPORT GLboolean __GLEW_SGIX_ycrcb; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_matrix; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_SGI_texture_color_table; +GLEW_VAR_EXPORT GLboolean __GLEW_SUNX_constant_data; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_convolution_border_modes; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_global_alpha; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_mesh_array; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_read_video_pixels; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_slice_accum; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_triangle_list; +GLEW_VAR_EXPORT GLboolean __GLEW_SUN_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_phong_shading; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_specular_fog; +GLEW_VAR_EXPORT GLboolean __GLEW_WIN_swap_hint; + +#ifdef GLEW_MX +}; /* GLEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------- */ + +/* error codes */ +#define GLEW_OK 0 +#define GLEW_NO_ERROR 0 +#define GLEW_ERROR_NO_GL_VERSION 1 /* missing GL version */ +#define GLEW_ERROR_GL_VERSION_10_ONLY 2 /* Need at least OpenGL 1.1 */ +#define GLEW_ERROR_GLX_VERSION_11_ONLY 3 /* Need at least GLX 1.2 */ + +/* string codes */ +#define GLEW_VERSION 1 +#define GLEW_VERSION_MAJOR 2 +#define GLEW_VERSION_MINOR 3 +#define GLEW_VERSION_MICRO 4 + +/* API */ +#ifdef GLEW_MX + +typedef struct GLEWContextStruct GLEWContext; +GLEWAPI GLenum glewContextInit (GLEWContext* ctx); +GLEWAPI GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name); + +#define glewInit() glewContextInit(glewGetContext()) +#define glewIsSupported(x) glewContextIsSupported(glewGetContext(), x) +#define glewIsExtensionSupported(x) glewIsSupported(x) + +#define GLEW_GET_VAR(x) (*(const GLboolean*)&(glewGetContext()->x)) +#ifdef _WIN32 +# define GLEW_GET_FUN(x) glewGetContext()->x +#else +# define GLEW_GET_FUN(x) x +#endif + +#else /* GLEW_MX */ + +GLEWAPI GLenum glewInit (); +GLEWAPI GLboolean glewIsSupported (const char* name); +#define glewIsExtensionSupported(x) glewIsSupported(x) + +#define GLEW_GET_VAR(x) (*(const GLboolean*)&x) +#define GLEW_GET_FUN(x) x + +#endif /* GLEW_MX */ + +GLEWAPI GLboolean glewExperimental; +GLEWAPI GLboolean glewGetExtension (const char* name); +GLEWAPI const GLubyte* glewGetErrorString (GLenum error); +GLEWAPI const GLubyte* glewGetString (GLenum name); + +#ifdef __cplusplus +} +#endif + +#ifdef GLEW_APIENTRY_DEFINED +#undef GLEW_APIENTRY_DEFINED +#undef APIENTRY +#undef GLAPIENTRY +#define GLAPIENTRY +#endif + +#ifdef GLEW_CALLBACK_DEFINED +#undef GLEW_CALLBACK_DEFINED +#undef CALLBACK +#endif + +#ifdef GLEW_WINGDIAPI_DEFINED +#undef GLEW_WINGDIAPI_DEFINED +#undef WINGDIAPI +#endif + +#undef GLAPI +/* #undef GLEWAPI */ + +#endif /* __glew_h__ */ diff --git a/ext/glew/GL/glxew.h b/ext/glew/GL/glxew.h new file mode 100644 index 0000000000..2995318f69 --- /dev/null +++ b/ext/glew/GL/glxew.h @@ -0,0 +1,1568 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __glxew_h__ +#define __glxew_h__ +#define __GLXEW_H__ + +#ifdef __glxext_h_ +#error glxext.h included before glxew.h +#endif + +#if defined(GLX_H) || defined(__GLX_glx_h__) || defined(__glx_h__) +#error glx.h included before glxew.h +#endif + +#define __glxext_h_ + +#define GLX_H +#define __GLX_glx_h__ +#define __glx_h__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------------------------- GLX_VERSION_1_0 --------------------------- */ + +#ifndef GLX_VERSION_1_0 +#define GLX_VERSION_1_0 1 + +#define GLX_USE_GL 1 +#define GLX_BUFFER_SIZE 2 +#define GLX_LEVEL 3 +#define GLX_RGBA 4 +#define GLX_DOUBLEBUFFER 5 +#define GLX_STEREO 6 +#define GLX_AUX_BUFFERS 7 +#define GLX_RED_SIZE 8 +#define GLX_GREEN_SIZE 9 +#define GLX_BLUE_SIZE 10 +#define GLX_ALPHA_SIZE 11 +#define GLX_DEPTH_SIZE 12 +#define GLX_STENCIL_SIZE 13 +#define GLX_ACCUM_RED_SIZE 14 +#define GLX_ACCUM_GREEN_SIZE 15 +#define GLX_ACCUM_BLUE_SIZE 16 +#define GLX_ACCUM_ALPHA_SIZE 17 +#define GLX_BAD_SCREEN 1 +#define GLX_BAD_ATTRIBUTE 2 +#define GLX_NO_EXTENSION 3 +#define GLX_BAD_VISUAL 4 +#define GLX_BAD_CONTEXT 5 +#define GLX_BAD_VALUE 6 +#define GLX_BAD_ENUM 7 + +typedef XID GLXDrawable; +typedef XID GLXPixmap; +#ifdef __sun +typedef struct __glXContextRec *GLXContext; +#else +typedef struct __GLXcontextRec *GLXContext; +#endif + +typedef unsigned int GLXVideoDeviceNV; + +extern Bool glXQueryExtension (Display *dpy, int *errorBase, int *eventBase); +extern Bool glXQueryVersion (Display *dpy, int *major, int *minor); +extern int glXGetConfig (Display *dpy, XVisualInfo *vis, int attrib, int *value); +extern XVisualInfo* glXChooseVisual (Display *dpy, int screen, int *attribList); +extern GLXPixmap glXCreateGLXPixmap (Display *dpy, XVisualInfo *vis, Pixmap pixmap); +extern void glXDestroyGLXPixmap (Display *dpy, GLXPixmap pix); +extern GLXContext glXCreateContext (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct); +extern void glXDestroyContext (Display *dpy, GLXContext ctx); +extern Bool glXIsDirect (Display *dpy, GLXContext ctx); +extern void glXCopyContext (Display *dpy, GLXContext src, GLXContext dst, GLulong mask); +extern Bool glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx); +extern GLXContext glXGetCurrentContext (void); +extern GLXDrawable glXGetCurrentDrawable (void); +extern void glXWaitGL (void); +extern void glXWaitX (void); +extern void glXSwapBuffers (Display *dpy, GLXDrawable drawable); +extern void glXUseXFont (Font font, int first, int count, int listBase); + +#define GLXEW_VERSION_1_0 GLXEW_GET_VAR(__GLXEW_VERSION_1_0) + +#endif /* GLX_VERSION_1_0 */ + +/* ---------------------------- GLX_VERSION_1_1 --------------------------- */ + +#ifndef GLX_VERSION_1_1 +#define GLX_VERSION_1_1 + +#define GLX_VENDOR 0x1 +#define GLX_VERSION 0x2 +#define GLX_EXTENSIONS 0x3 + +extern const char* glXQueryExtensionsString (Display *dpy, int screen); +extern const char* glXGetClientString (Display *dpy, int name); +extern const char* glXQueryServerString (Display *dpy, int screen, int name); + +#define GLXEW_VERSION_1_1 GLXEW_GET_VAR(__GLXEW_VERSION_1_1) + +#endif /* GLX_VERSION_1_1 */ + +/* ---------------------------- GLX_VERSION_1_2 ---------------------------- */ + +#ifndef GLX_VERSION_1_2 +#define GLX_VERSION_1_2 1 + +typedef Display* ( * PFNGLXGETCURRENTDISPLAYPROC) (void); + +#define glXGetCurrentDisplay GLXEW_GET_FUN(__glewXGetCurrentDisplay) + +#define GLXEW_VERSION_1_2 GLXEW_GET_VAR(__GLXEW_VERSION_1_2) + +#endif /* GLX_VERSION_1_2 */ + +/* ---------------------------- GLX_VERSION_1_3 ---------------------------- */ + +#ifndef GLX_VERSION_1_3 +#define GLX_VERSION_1_3 1 + +#define GLX_RGBA_BIT 0x00000001 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 +#define GLX_DONT_CARE 0xFFFFFFFF + +typedef XID GLXFBConfigID; +typedef XID GLXPbuffer; +typedef XID GLXWindow; +typedef struct __GLXFBConfigRec *GLXFBConfig; + +typedef struct { + int event_type; + int draw_type; + unsigned long serial; + Bool send_event; + Display *display; + GLXDrawable drawable; + unsigned int buffer_mask; + unsigned int aux_buffer; + int x, y; + int width, height; + int count; +} GLXPbufferClobberEvent; +typedef union __GLXEvent { + GLXPbufferClobberEvent glxpbufferclobber; + long pad[24]; +} GLXEvent; + +typedef GLXFBConfig* ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list); +typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); +typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); +typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap); +typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win); +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void); +typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value); +typedef GLXFBConfig* ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements); +typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask); +typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); +typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value); +typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask); + +#define glXChooseFBConfig GLXEW_GET_FUN(__glewXChooseFBConfig) +#define glXCreateNewContext GLXEW_GET_FUN(__glewXCreateNewContext) +#define glXCreatePbuffer GLXEW_GET_FUN(__glewXCreatePbuffer) +#define glXCreatePixmap GLXEW_GET_FUN(__glewXCreatePixmap) +#define glXCreateWindow GLXEW_GET_FUN(__glewXCreateWindow) +#define glXDestroyPbuffer GLXEW_GET_FUN(__glewXDestroyPbuffer) +#define glXDestroyPixmap GLXEW_GET_FUN(__glewXDestroyPixmap) +#define glXDestroyWindow GLXEW_GET_FUN(__glewXDestroyWindow) +#define glXGetCurrentReadDrawable GLXEW_GET_FUN(__glewXGetCurrentReadDrawable) +#define glXGetFBConfigAttrib GLXEW_GET_FUN(__glewXGetFBConfigAttrib) +#define glXGetFBConfigs GLXEW_GET_FUN(__glewXGetFBConfigs) +#define glXGetSelectedEvent GLXEW_GET_FUN(__glewXGetSelectedEvent) +#define glXGetVisualFromFBConfig GLXEW_GET_FUN(__glewXGetVisualFromFBConfig) +#define glXMakeContextCurrent GLXEW_GET_FUN(__glewXMakeContextCurrent) +#define glXQueryContext GLXEW_GET_FUN(__glewXQueryContext) +#define glXQueryDrawable GLXEW_GET_FUN(__glewXQueryDrawable) +#define glXSelectEvent GLXEW_GET_FUN(__glewXSelectEvent) + +#define GLXEW_VERSION_1_3 GLXEW_GET_VAR(__GLXEW_VERSION_1_3) + +#endif /* GLX_VERSION_1_3 */ + +/* ---------------------------- GLX_VERSION_1_4 ---------------------------- */ + +#ifndef GLX_VERSION_1_4 +#define GLX_VERSION_1_4 1 + +#define GLX_SAMPLE_BUFFERS 100000 +#define GLX_SAMPLES 100001 + +extern void ( * glXGetProcAddress (const GLubyte *procName)) (void); + +#define GLXEW_VERSION_1_4 GLXEW_GET_VAR(__GLXEW_VERSION_1_4) + +#endif /* GLX_VERSION_1_4 */ + +/* -------------------------- GLX_3DFX_multisample ------------------------- */ + +#ifndef GLX_3DFX_multisample +#define GLX_3DFX_multisample 1 + +#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 +#define GLX_SAMPLES_3DFX 0x8051 + +#define GLXEW_3DFX_multisample GLXEW_GET_VAR(__GLXEW_3DFX_multisample) + +#endif /* GLX_3DFX_multisample */ + +/* ------------------------ GLX_AMD_gpu_association ------------------------ */ + +#ifndef GLX_AMD_gpu_association +#define GLX_AMD_gpu_association 1 + +#define GLX_GPU_VENDOR_AMD 0x1F00 +#define GLX_GPU_RENDERER_STRING_AMD 0x1F01 +#define GLX_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 +#define GLX_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 +#define GLX_GPU_RAM_AMD 0x21A3 +#define GLX_GPU_CLOCK_AMD 0x21A4 +#define GLX_GPU_NUM_PIPES_AMD 0x21A5 +#define GLX_GPU_NUM_SIMD_AMD 0x21A6 +#define GLX_GPU_NUM_RB_AMD 0x21A7 +#define GLX_GPU_NUM_SPI_AMD 0x21A8 + +#define GLXEW_AMD_gpu_association GLXEW_GET_VAR(__GLXEW_AMD_gpu_association) + +#endif /* GLX_AMD_gpu_association */ + +/* ------------------------- GLX_ARB_create_context ------------------------ */ + +#ifndef GLX_ARB_create_context +#define GLX_ARB_create_context 1 + +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 + +typedef GLXContext ( * PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); + +#define glXCreateContextAttribsARB GLXEW_GET_FUN(__glewXCreateContextAttribsARB) + +#define GLXEW_ARB_create_context GLXEW_GET_VAR(__GLXEW_ARB_create_context) + +#endif /* GLX_ARB_create_context */ + +/* --------------------- GLX_ARB_create_context_profile -------------------- */ + +#ifndef GLX_ARB_create_context_profile +#define GLX_ARB_create_context_profile 1 + +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 + +#define GLXEW_ARB_create_context_profile GLXEW_GET_VAR(__GLXEW_ARB_create_context_profile) + +#endif /* GLX_ARB_create_context_profile */ + +/* ------------------- GLX_ARB_create_context_robustness ------------------- */ + +#ifndef GLX_ARB_create_context_robustness +#define GLX_ARB_create_context_robustness 1 + +#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 + +#define GLXEW_ARB_create_context_robustness GLXEW_GET_VAR(__GLXEW_ARB_create_context_robustness) + +#endif /* GLX_ARB_create_context_robustness */ + +/* ------------------------- GLX_ARB_fbconfig_float ------------------------ */ + +#ifndef GLX_ARB_fbconfig_float +#define GLX_ARB_fbconfig_float 1 + +#define GLX_RGBA_FLOAT_BIT 0x00000004 +#define GLX_RGBA_FLOAT_TYPE 0x20B9 + +#define GLXEW_ARB_fbconfig_float GLXEW_GET_VAR(__GLXEW_ARB_fbconfig_float) + +#endif /* GLX_ARB_fbconfig_float */ + +/* ------------------------ GLX_ARB_framebuffer_sRGB ----------------------- */ + +#ifndef GLX_ARB_framebuffer_sRGB +#define GLX_ARB_framebuffer_sRGB 1 + +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2 + +#define GLXEW_ARB_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_ARB_framebuffer_sRGB) + +#endif /* GLX_ARB_framebuffer_sRGB */ + +/* ------------------------ GLX_ARB_get_proc_address ----------------------- */ + +#ifndef GLX_ARB_get_proc_address +#define GLX_ARB_get_proc_address 1 + +extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void); + +#define GLXEW_ARB_get_proc_address GLXEW_GET_VAR(__GLXEW_ARB_get_proc_address) + +#endif /* GLX_ARB_get_proc_address */ + +/* -------------------------- GLX_ARB_multisample -------------------------- */ + +#ifndef GLX_ARB_multisample +#define GLX_ARB_multisample 1 + +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 + +#define GLXEW_ARB_multisample GLXEW_GET_VAR(__GLXEW_ARB_multisample) + +#endif /* GLX_ARB_multisample */ + +/* ---------------------- GLX_ARB_vertex_buffer_object --------------------- */ + +#ifndef GLX_ARB_vertex_buffer_object +#define GLX_ARB_vertex_buffer_object 1 + +#define GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095 + +#define GLXEW_ARB_vertex_buffer_object GLXEW_GET_VAR(__GLXEW_ARB_vertex_buffer_object) + +#endif /* GLX_ARB_vertex_buffer_object */ + +/* ----------------------- GLX_ATI_pixel_format_float ---------------------- */ + +#ifndef GLX_ATI_pixel_format_float +#define GLX_ATI_pixel_format_float 1 + +#define GLX_RGBA_FLOAT_ATI_BIT 0x00000100 + +#define GLXEW_ATI_pixel_format_float GLXEW_GET_VAR(__GLXEW_ATI_pixel_format_float) + +#endif /* GLX_ATI_pixel_format_float */ + +/* ------------------------- GLX_ATI_render_texture ------------------------ */ + +#ifndef GLX_ATI_render_texture +#define GLX_ATI_render_texture 1 + +#define GLX_BIND_TO_TEXTURE_RGB_ATI 0x9800 +#define GLX_BIND_TO_TEXTURE_RGBA_ATI 0x9801 +#define GLX_TEXTURE_FORMAT_ATI 0x9802 +#define GLX_TEXTURE_TARGET_ATI 0x9803 +#define GLX_MIPMAP_TEXTURE_ATI 0x9804 +#define GLX_TEXTURE_RGB_ATI 0x9805 +#define GLX_TEXTURE_RGBA_ATI 0x9806 +#define GLX_NO_TEXTURE_ATI 0x9807 +#define GLX_TEXTURE_CUBE_MAP_ATI 0x9808 +#define GLX_TEXTURE_1D_ATI 0x9809 +#define GLX_TEXTURE_2D_ATI 0x980A +#define GLX_MIPMAP_LEVEL_ATI 0x980B +#define GLX_CUBE_MAP_FACE_ATI 0x980C +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_X_ATI 0x980D +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_X_ATI 0x980E +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Y_ATI 0x980F +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Y_ATI 0x9810 +#define GLX_TEXTURE_CUBE_MAP_POSITIVE_Z_ATI 0x9811 +#define GLX_TEXTURE_CUBE_MAP_NEGATIVE_Z_ATI 0x9812 +#define GLX_FRONT_LEFT_ATI 0x9813 +#define GLX_FRONT_RIGHT_ATI 0x9814 +#define GLX_BACK_LEFT_ATI 0x9815 +#define GLX_BACK_RIGHT_ATI 0x9816 +#define GLX_AUX0_ATI 0x9817 +#define GLX_AUX1_ATI 0x9818 +#define GLX_AUX2_ATI 0x9819 +#define GLX_AUX3_ATI 0x981A +#define GLX_AUX4_ATI 0x981B +#define GLX_AUX5_ATI 0x981C +#define GLX_AUX6_ATI 0x981D +#define GLX_AUX7_ATI 0x981E +#define GLX_AUX8_ATI 0x981F +#define GLX_AUX9_ATI 0x9820 +#define GLX_BIND_TO_TEXTURE_LUMINANCE_ATI 0x9821 +#define GLX_BIND_TO_TEXTURE_INTENSITY_ATI 0x9822 + +typedef void ( * PFNGLXBINDTEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer); +typedef void ( * PFNGLXDRAWABLEATTRIBATIPROC) (Display *dpy, GLXDrawable draw, const int *attrib_list); +typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, int buffer); + +#define glXBindTexImageATI GLXEW_GET_FUN(__glewXBindTexImageATI) +#define glXDrawableAttribATI GLXEW_GET_FUN(__glewXDrawableAttribATI) +#define glXReleaseTexImageATI GLXEW_GET_FUN(__glewXReleaseTexImageATI) + +#define GLXEW_ATI_render_texture GLXEW_GET_VAR(__GLXEW_ATI_render_texture) + +#endif /* GLX_ATI_render_texture */ + +/* ------------------- GLX_EXT_create_context_es2_profile ------------------ */ + +#ifndef GLX_EXT_create_context_es2_profile +#define GLX_EXT_create_context_es2_profile 1 + +#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 + +#define GLXEW_EXT_create_context_es2_profile GLXEW_GET_VAR(__GLXEW_EXT_create_context_es2_profile) + +#endif /* GLX_EXT_create_context_es2_profile */ + +/* --------------------- GLX_EXT_fbconfig_packed_float --------------------- */ + +#ifndef GLX_EXT_fbconfig_packed_float +#define GLX_EXT_fbconfig_packed_float 1 + +#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008 +#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1 + +#define GLXEW_EXT_fbconfig_packed_float GLXEW_GET_VAR(__GLXEW_EXT_fbconfig_packed_float) + +#endif /* GLX_EXT_fbconfig_packed_float */ + +/* ------------------------ GLX_EXT_framebuffer_sRGB ----------------------- */ + +#ifndef GLX_EXT_framebuffer_sRGB +#define GLX_EXT_framebuffer_sRGB 1 + +#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2 + +#define GLXEW_EXT_framebuffer_sRGB GLXEW_GET_VAR(__GLXEW_EXT_framebuffer_sRGB) + +#endif /* GLX_EXT_framebuffer_sRGB */ + +/* ------------------------- GLX_EXT_import_context ------------------------ */ + +#ifndef GLX_EXT_import_context +#define GLX_EXT_import_context 1 + +#define GLX_SHARE_CONTEXT_EXT 0x800A +#define GLX_VISUAL_ID_EXT 0x800B +#define GLX_SCREEN_EXT 0x800C + +typedef XID GLXContextID; + +typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display* dpy, GLXContext context); +typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context); +typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display* dpy, GLXContextID contextID); +typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display* dpy, GLXContext context, int attribute,int *value); + +#define glXFreeContextEXT GLXEW_GET_FUN(__glewXFreeContextEXT) +#define glXGetContextIDEXT GLXEW_GET_FUN(__glewXGetContextIDEXT) +#define glXImportContextEXT GLXEW_GET_FUN(__glewXImportContextEXT) +#define glXQueryContextInfoEXT GLXEW_GET_FUN(__glewXQueryContextInfoEXT) + +#define GLXEW_EXT_import_context GLXEW_GET_VAR(__GLXEW_EXT_import_context) + +#endif /* GLX_EXT_import_context */ + +/* -------------------------- GLX_EXT_scene_marker ------------------------- */ + +#ifndef GLX_EXT_scene_marker +#define GLX_EXT_scene_marker 1 + +#define GLXEW_EXT_scene_marker GLXEW_GET_VAR(__GLXEW_EXT_scene_marker) + +#endif /* GLX_EXT_scene_marker */ + +/* -------------------------- GLX_EXT_swap_control ------------------------- */ + +#ifndef GLX_EXT_swap_control +#define GLX_EXT_swap_control 1 + +#define GLX_SWAP_INTERVAL_EXT 0x20F1 +#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2 + +typedef void ( * PFNGLXSWAPINTERVALEXTPROC) (Display* dpy, GLXDrawable drawable, int interval); + +#define glXSwapIntervalEXT GLXEW_GET_FUN(__glewXSwapIntervalEXT) + +#define GLXEW_EXT_swap_control GLXEW_GET_VAR(__GLXEW_EXT_swap_control) + +#endif /* GLX_EXT_swap_control */ + +/* ---------------------- GLX_EXT_texture_from_pixmap ---------------------- */ + +#ifndef GLX_EXT_texture_from_pixmap +#define GLX_EXT_texture_from_pixmap 1 + +#define GLX_TEXTURE_1D_BIT_EXT 0x00000001 +#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 +#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 +#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 +#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 +#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 +#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 +#define GLX_Y_INVERTED_EXT 0x20D4 +#define GLX_TEXTURE_FORMAT_EXT 0x20D5 +#define GLX_TEXTURE_TARGET_EXT 0x20D6 +#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 +#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 +#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 +#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA +#define GLX_TEXTURE_1D_EXT 0x20DB +#define GLX_TEXTURE_2D_EXT 0x20DC +#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD +#define GLX_FRONT_LEFT_EXT 0x20DE +#define GLX_FRONT_RIGHT_EXT 0x20DF +#define GLX_BACK_LEFT_EXT 0x20E0 +#define GLX_BACK_RIGHT_EXT 0x20E1 +#define GLX_AUX0_EXT 0x20E2 +#define GLX_AUX1_EXT 0x20E3 +#define GLX_AUX2_EXT 0x20E4 +#define GLX_AUX3_EXT 0x20E5 +#define GLX_AUX4_EXT 0x20E6 +#define GLX_AUX5_EXT 0x20E7 +#define GLX_AUX6_EXT 0x20E8 +#define GLX_AUX7_EXT 0x20E9 +#define GLX_AUX8_EXT 0x20EA +#define GLX_AUX9_EXT 0x20EB + +typedef void ( * PFNGLXBINDTEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer, const int *attrib_list); +typedef void ( * PFNGLXRELEASETEXIMAGEEXTPROC) (Display* display, GLXDrawable drawable, int buffer); + +#define glXBindTexImageEXT GLXEW_GET_FUN(__glewXBindTexImageEXT) +#define glXReleaseTexImageEXT GLXEW_GET_FUN(__glewXReleaseTexImageEXT) + +#define GLXEW_EXT_texture_from_pixmap GLXEW_GET_VAR(__GLXEW_EXT_texture_from_pixmap) + +#endif /* GLX_EXT_texture_from_pixmap */ + +/* -------------------------- GLX_EXT_visual_info -------------------------- */ + +#ifndef GLX_EXT_visual_info +#define GLX_EXT_visual_info 1 + +#define GLX_X_VISUAL_TYPE_EXT 0x22 +#define GLX_TRANSPARENT_TYPE_EXT 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 +#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 + +#define GLXEW_EXT_visual_info GLXEW_GET_VAR(__GLXEW_EXT_visual_info) + +#endif /* GLX_EXT_visual_info */ + +/* ------------------------- GLX_EXT_visual_rating ------------------------- */ + +#ifndef GLX_EXT_visual_rating +#define GLX_EXT_visual_rating 1 + +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#define GLX_SLOW_VISUAL_EXT 0x8001 +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D + +#define GLXEW_EXT_visual_rating GLXEW_GET_VAR(__GLXEW_EXT_visual_rating) + +#endif /* GLX_EXT_visual_rating */ + +/* -------------------------- GLX_INTEL_swap_event ------------------------- */ + +#ifndef GLX_INTEL_swap_event +#define GLX_INTEL_swap_event 1 + +#define GLX_EXCHANGE_COMPLETE_INTEL 0x8180 +#define GLX_COPY_COMPLETE_INTEL 0x8181 +#define GLX_FLIP_COMPLETE_INTEL 0x8182 +#define GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000 + +#define GLXEW_INTEL_swap_event GLXEW_GET_VAR(__GLXEW_INTEL_swap_event) + +#endif /* GLX_INTEL_swap_event */ + +/* -------------------------- GLX_MESA_agp_offset -------------------------- */ + +#ifndef GLX_MESA_agp_offset +#define GLX_MESA_agp_offset 1 + +typedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void* pointer); + +#define glXGetAGPOffsetMESA GLXEW_GET_FUN(__glewXGetAGPOffsetMESA) + +#define GLXEW_MESA_agp_offset GLXEW_GET_VAR(__GLXEW_MESA_agp_offset) + +#endif /* GLX_MESA_agp_offset */ + +/* ------------------------ GLX_MESA_copy_sub_buffer ----------------------- */ + +#ifndef GLX_MESA_copy_sub_buffer +#define GLX_MESA_copy_sub_buffer 1 + +typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display* dpy, GLXDrawable drawable, int x, int y, int width, int height); + +#define glXCopySubBufferMESA GLXEW_GET_FUN(__glewXCopySubBufferMESA) + +#define GLXEW_MESA_copy_sub_buffer GLXEW_GET_VAR(__GLXEW_MESA_copy_sub_buffer) + +#endif /* GLX_MESA_copy_sub_buffer */ + +/* ------------------------ GLX_MESA_pixmap_colormap ----------------------- */ + +#ifndef GLX_MESA_pixmap_colormap +#define GLX_MESA_pixmap_colormap 1 + +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display* dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); + +#define glXCreateGLXPixmapMESA GLXEW_GET_FUN(__glewXCreateGLXPixmapMESA) + +#define GLXEW_MESA_pixmap_colormap GLXEW_GET_VAR(__GLXEW_MESA_pixmap_colormap) + +#endif /* GLX_MESA_pixmap_colormap */ + +/* ------------------------ GLX_MESA_release_buffers ----------------------- */ + +#ifndef GLX_MESA_release_buffers +#define GLX_MESA_release_buffers 1 + +typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display* dpy, GLXDrawable d); + +#define glXReleaseBuffersMESA GLXEW_GET_FUN(__glewXReleaseBuffersMESA) + +#define GLXEW_MESA_release_buffers GLXEW_GET_VAR(__GLXEW_MESA_release_buffers) + +#endif /* GLX_MESA_release_buffers */ + +/* ------------------------- GLX_MESA_set_3dfx_mode ------------------------ */ + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_MESA_set_3dfx_mode 1 + +#define GLX_3DFX_WINDOW_MODE_MESA 0x1 +#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 + +typedef GLboolean ( * PFNGLXSET3DFXMODEMESAPROC) (GLint mode); + +#define glXSet3DfxModeMESA GLXEW_GET_FUN(__glewXSet3DfxModeMESA) + +#define GLXEW_MESA_set_3dfx_mode GLXEW_GET_VAR(__GLXEW_MESA_set_3dfx_mode) + +#endif /* GLX_MESA_set_3dfx_mode */ + +/* --------------------------- GLX_NV_copy_image --------------------------- */ + +#ifndef GLX_NV_copy_image +#define GLX_NV_copy_image 1 + +typedef void ( * PFNGLXCOPYIMAGESUBDATANVPROC) (Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); + +#define glXCopyImageSubDataNV GLXEW_GET_FUN(__glewXCopyImageSubDataNV) + +#define GLXEW_NV_copy_image GLXEW_GET_VAR(__GLXEW_NV_copy_image) + +#endif /* GLX_NV_copy_image */ + +/* -------------------------- GLX_NV_float_buffer -------------------------- */ + +#ifndef GLX_NV_float_buffer +#define GLX_NV_float_buffer 1 + +#define GLX_FLOAT_COMPONENTS_NV 0x20B0 + +#define GLXEW_NV_float_buffer GLXEW_GET_VAR(__GLXEW_NV_float_buffer) + +#endif /* GLX_NV_float_buffer */ + +/* ---------------------- GLX_NV_multisample_coverage ---------------------- */ + +#ifndef GLX_NV_multisample_coverage +#define GLX_NV_multisample_coverage 1 + +#define GLX_COLOR_SAMPLES_NV 0x20B3 +#define GLX_COVERAGE_SAMPLES_NV 100001 + +#define GLXEW_NV_multisample_coverage GLXEW_GET_VAR(__GLXEW_NV_multisample_coverage) + +#endif /* GLX_NV_multisample_coverage */ + +/* -------------------------- GLX_NV_present_video ------------------------- */ + +#ifndef GLX_NV_present_video +#define GLX_NV_present_video 1 + +#define GLX_NUM_VIDEO_SLOTS_NV 0x20F0 + +typedef int ( * PFNGLXBINDVIDEODEVICENVPROC) (Display* dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list); +typedef unsigned int* ( * PFNGLXENUMERATEVIDEODEVICESNVPROC) (Display *dpy, int screen, int *nelements); + +#define glXBindVideoDeviceNV GLXEW_GET_FUN(__glewXBindVideoDeviceNV) +#define glXEnumerateVideoDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoDevicesNV) + +#define GLXEW_NV_present_video GLXEW_GET_VAR(__GLXEW_NV_present_video) + +#endif /* GLX_NV_present_video */ + +/* --------------------------- GLX_NV_swap_group --------------------------- */ + +#ifndef GLX_NV_swap_group +#define GLX_NV_swap_group 1 + +typedef Bool ( * PFNGLXBINDSWAPBARRIERNVPROC) (Display* dpy, GLuint group, GLuint barrier); +typedef Bool ( * PFNGLXJOINSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint group); +typedef Bool ( * PFNGLXQUERYFRAMECOUNTNVPROC) (Display* dpy, int screen, GLuint *count); +typedef Bool ( * PFNGLXQUERYMAXSWAPGROUPSNVPROC) (Display* dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers); +typedef Bool ( * PFNGLXQUERYSWAPGROUPNVPROC) (Display* dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier); +typedef Bool ( * PFNGLXRESETFRAMECOUNTNVPROC) (Display* dpy, int screen); + +#define glXBindSwapBarrierNV GLXEW_GET_FUN(__glewXBindSwapBarrierNV) +#define glXJoinSwapGroupNV GLXEW_GET_FUN(__glewXJoinSwapGroupNV) +#define glXQueryFrameCountNV GLXEW_GET_FUN(__glewXQueryFrameCountNV) +#define glXQueryMaxSwapGroupsNV GLXEW_GET_FUN(__glewXQueryMaxSwapGroupsNV) +#define glXQuerySwapGroupNV GLXEW_GET_FUN(__glewXQuerySwapGroupNV) +#define glXResetFrameCountNV GLXEW_GET_FUN(__glewXResetFrameCountNV) + +#define GLXEW_NV_swap_group GLXEW_GET_VAR(__GLXEW_NV_swap_group) + +#endif /* GLX_NV_swap_group */ + +/* ----------------------- GLX_NV_vertex_array_range ----------------------- */ + +#ifndef GLX_NV_vertex_array_range +#define GLX_NV_vertex_array_range 1 + +typedef void * ( * PFNGLXALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); +typedef void ( * PFNGLXFREEMEMORYNVPROC) (void *pointer); + +#define glXAllocateMemoryNV GLXEW_GET_FUN(__glewXAllocateMemoryNV) +#define glXFreeMemoryNV GLXEW_GET_FUN(__glewXFreeMemoryNV) + +#define GLXEW_NV_vertex_array_range GLXEW_GET_VAR(__GLXEW_NV_vertex_array_range) + +#endif /* GLX_NV_vertex_array_range */ + +/* -------------------------- GLX_NV_video_capture ------------------------- */ + +#ifndef GLX_NV_video_capture +#define GLX_NV_video_capture 1 + +#define GLX_DEVICE_ID_NV 0x20CD +#define GLX_UNIQUE_ID_NV 0x20CE +#define GLX_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF + +typedef XID GLXVideoCaptureDeviceNV; + +typedef int ( * PFNGLXBINDVIDEOCAPTUREDEVICENVPROC) (Display* dpy, unsigned int video_capture_slot, GLXVideoCaptureDeviceNV device); +typedef GLXVideoCaptureDeviceNV * ( * PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC) (Display* dpy, int screen, int *nelements); +typedef void ( * PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device); +typedef int ( * PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device, int attribute, int *value); +typedef void ( * PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoCaptureDeviceNV device); + +#define glXBindVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXBindVideoCaptureDeviceNV) +#define glXEnumerateVideoCaptureDevicesNV GLXEW_GET_FUN(__glewXEnumerateVideoCaptureDevicesNV) +#define glXLockVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXLockVideoCaptureDeviceNV) +#define glXQueryVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXQueryVideoCaptureDeviceNV) +#define glXReleaseVideoCaptureDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoCaptureDeviceNV) + +#define GLXEW_NV_video_capture GLXEW_GET_VAR(__GLXEW_NV_video_capture) + +#endif /* GLX_NV_video_capture */ + +/* -------------------------- GLX_NV_video_output -------------------------- */ + +#ifndef GLX_NV_video_output +#define GLX_NV_video_output 1 + +#define GLX_VIDEO_OUT_COLOR_NV 0x20C3 +#define GLX_VIDEO_OUT_ALPHA_NV 0x20C4 +#define GLX_VIDEO_OUT_DEPTH_NV 0x20C5 +#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define GLX_VIDEO_OUT_FRAME_NV 0x20C8 +#define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9 +#define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA +#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB +#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC + +typedef int ( * PFNGLXBINDVIDEOIMAGENVPROC) (Display* dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer); +typedef int ( * PFNGLXGETVIDEODEVICENVPROC) (Display* dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice); +typedef int ( * PFNGLXGETVIDEOINFONVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +typedef int ( * PFNGLXRELEASEVIDEODEVICENVPROC) (Display* dpy, int screen, GLXVideoDeviceNV VideoDevice); +typedef int ( * PFNGLXRELEASEVIDEOIMAGENVPROC) (Display* dpy, GLXPbuffer pbuf); +typedef int ( * PFNGLXSENDPBUFFERTOVIDEONVPROC) (Display* dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock); + +#define glXBindVideoImageNV GLXEW_GET_FUN(__glewXBindVideoImageNV) +#define glXGetVideoDeviceNV GLXEW_GET_FUN(__glewXGetVideoDeviceNV) +#define glXGetVideoInfoNV GLXEW_GET_FUN(__glewXGetVideoInfoNV) +#define glXReleaseVideoDeviceNV GLXEW_GET_FUN(__glewXReleaseVideoDeviceNV) +#define glXReleaseVideoImageNV GLXEW_GET_FUN(__glewXReleaseVideoImageNV) +#define glXSendPbufferToVideoNV GLXEW_GET_FUN(__glewXSendPbufferToVideoNV) + +#define GLXEW_NV_video_output GLXEW_GET_VAR(__GLXEW_NV_video_output) + +#endif /* GLX_NV_video_output */ + +/* -------------------------- GLX_OML_swap_method -------------------------- */ + +#ifndef GLX_OML_swap_method +#define GLX_OML_swap_method 1 + +#define GLX_SWAP_METHOD_OML 0x8060 +#define GLX_SWAP_EXCHANGE_OML 0x8061 +#define GLX_SWAP_COPY_OML 0x8062 +#define GLX_SWAP_UNDEFINED_OML 0x8063 + +#define GLXEW_OML_swap_method GLXEW_GET_VAR(__GLXEW_OML_swap_method) + +#endif /* GLX_OML_swap_method */ + +/* -------------------------- GLX_OML_sync_control ------------------------- */ + +#ifndef GLX_OML_sync_control +#define GLX_OML_sync_control 1 + +typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator); +typedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc); +typedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder); +typedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc); +typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, int64_t target_sbc, int64_t* ust, int64_t* msc, int64_t* sbc); + +#define glXGetMscRateOML GLXEW_GET_FUN(__glewXGetMscRateOML) +#define glXGetSyncValuesOML GLXEW_GET_FUN(__glewXGetSyncValuesOML) +#define glXSwapBuffersMscOML GLXEW_GET_FUN(__glewXSwapBuffersMscOML) +#define glXWaitForMscOML GLXEW_GET_FUN(__glewXWaitForMscOML) +#define glXWaitForSbcOML GLXEW_GET_FUN(__glewXWaitForSbcOML) + +#define GLXEW_OML_sync_control GLXEW_GET_VAR(__GLXEW_OML_sync_control) + +#endif /* GLX_OML_sync_control */ + +/* ------------------------ GLX_SGIS_blended_overlay ----------------------- */ + +#ifndef GLX_SGIS_blended_overlay +#define GLX_SGIS_blended_overlay 1 + +#define GLX_BLENDED_RGBA_SGIS 0x8025 + +#define GLXEW_SGIS_blended_overlay GLXEW_GET_VAR(__GLXEW_SGIS_blended_overlay) + +#endif /* GLX_SGIS_blended_overlay */ + +/* -------------------------- GLX_SGIS_color_range ------------------------- */ + +#ifndef GLX_SGIS_color_range +#define GLX_SGIS_color_range 1 + +#define GLX_MIN_RED_SGIS 0 +#define GLX_MAX_GREEN_SGIS 0 +#define GLX_MIN_BLUE_SGIS 0 +#define GLX_MAX_ALPHA_SGIS 0 +#define GLX_MIN_GREEN_SGIS 0 +#define GLX_MIN_ALPHA_SGIS 0 +#define GLX_MAX_RED_SGIS 0 +#define GLX_EXTENDED_RANGE_SGIS 0 +#define GLX_MAX_BLUE_SGIS 0 + +#define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range) + +#endif /* GLX_SGIS_color_range */ + +/* -------------------------- GLX_SGIS_multisample ------------------------- */ + +#ifndef GLX_SGIS_multisample +#define GLX_SGIS_multisample 1 + +#define GLX_SAMPLE_BUFFERS_SGIS 100000 +#define GLX_SAMPLES_SGIS 100001 + +#define GLXEW_SGIS_multisample GLXEW_GET_VAR(__GLXEW_SGIS_multisample) + +#endif /* GLX_SGIS_multisample */ + +/* ---------------------- GLX_SGIS_shared_multisample ---------------------- */ + +#ifndef GLX_SGIS_shared_multisample +#define GLX_SGIS_shared_multisample 1 + +#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 +#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 + +#define GLXEW_SGIS_shared_multisample GLXEW_GET_VAR(__GLXEW_SGIS_shared_multisample) + +#endif /* GLX_SGIS_shared_multisample */ + +/* --------------------------- GLX_SGIX_fbconfig --------------------------- */ + +#ifndef GLX_SGIX_fbconfig +#define GLX_SGIX_fbconfig 1 + +#define GLX_WINDOW_BIT_SGIX 0x00000001 +#define GLX_RGBA_BIT_SGIX 0x00000001 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_SCREEN_EXT 0x800C +#define GLX_DRAWABLE_TYPE_SGIX 0x8010 +#define GLX_RENDER_TYPE_SGIX 0x8011 +#define GLX_X_RENDERABLE_SGIX 0x8012 +#define GLX_FBCONFIG_ID_SGIX 0x8013 +#define GLX_RGBA_TYPE_SGIX 0x8014 +#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 + +typedef XID GLXFBConfigIDSGIX; +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; + +typedef GLXFBConfigSGIX* ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display* dpy, GLXFBConfig config, Pixmap pixmap); +typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display* dpy, GLXFBConfigSGIX config, int attribute, int *value); +typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display* dpy, XVisualInfo *vis); +typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfig config); + +#define glXChooseFBConfigSGIX GLXEW_GET_FUN(__glewXChooseFBConfigSGIX) +#define glXCreateContextWithConfigSGIX GLXEW_GET_FUN(__glewXCreateContextWithConfigSGIX) +#define glXCreateGLXPixmapWithConfigSGIX GLXEW_GET_FUN(__glewXCreateGLXPixmapWithConfigSGIX) +#define glXGetFBConfigAttribSGIX GLXEW_GET_FUN(__glewXGetFBConfigAttribSGIX) +#define glXGetFBConfigFromVisualSGIX GLXEW_GET_FUN(__glewXGetFBConfigFromVisualSGIX) +#define glXGetVisualFromFBConfigSGIX GLXEW_GET_FUN(__glewXGetVisualFromFBConfigSGIX) + +#define GLXEW_SGIX_fbconfig GLXEW_GET_VAR(__GLXEW_SGIX_fbconfig) + +#endif /* GLX_SGIX_fbconfig */ + +/* --------------------------- GLX_SGIX_hyperpipe -------------------------- */ + +#ifndef GLX_SGIX_hyperpipe +#define GLX_SGIX_hyperpipe 1 + +#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 +#define GLX_PIPE_RECT_SGIX 0x00000001 +#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 +#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 +#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003 +#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 +#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 +#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91 +#define GLX_BAD_HYPERPIPE_SGIX 92 +#define GLX_HYPERPIPE_ID_SGIX 0x8030 + +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int networkId; +} GLXHyperpipeNetworkSGIX; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int XOrigin; + int YOrigin; + int maxHeight; + int maxWidth; +} GLXPipeRectLimits; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int channel; + unsigned int participationType; + int timeSlice; +} GLXHyperpipeConfigSGIX; +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int srcXOrigin; + int srcYOrigin; + int srcWidth; + int srcHeight; + int destXOrigin; + int destYOrigin; + int destWidth; + int destHeight; +} GLXPipeRect; + +typedef int ( * PFNGLXBINDHYPERPIPESGIXPROC) (Display *dpy, int hpId); +typedef int ( * PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId); +typedef int ( * PFNGLXHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList); +typedef int ( * PFNGLXHYPERPIPECONFIGSGIXPROC) (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId); +typedef int ( * PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList); +typedef int ( * PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList); +typedef GLXHyperpipeConfigSGIX * ( * PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId, int *npipes); +typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display *dpy, int *npipes); + +#define glXBindHyperpipeSGIX GLXEW_GET_FUN(__glewXBindHyperpipeSGIX) +#define glXDestroyHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXDestroyHyperpipeConfigSGIX) +#define glXHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXHyperpipeAttribSGIX) +#define glXHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXHyperpipeConfigSGIX) +#define glXQueryHyperpipeAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeAttribSGIX) +#define glXQueryHyperpipeBestAttribSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeBestAttribSGIX) +#define glXQueryHyperpipeConfigSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeConfigSGIX) +#define glXQueryHyperpipeNetworkSGIX GLXEW_GET_FUN(__glewXQueryHyperpipeNetworkSGIX) + +#define GLXEW_SGIX_hyperpipe GLXEW_GET_VAR(__GLXEW_SGIX_hyperpipe) + +#endif /* GLX_SGIX_hyperpipe */ + +/* ---------------------------- GLX_SGIX_pbuffer --------------------------- */ + +#ifndef GLX_SGIX_pbuffer +#define GLX_SGIX_pbuffer 1 + +#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 +#define GLX_PBUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 +#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 +#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 +#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 +#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 +#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 +#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 +#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 +#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 +#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A +#define GLX_PRESERVED_CONTENTS_SGIX 0x801B +#define GLX_LARGEST_PBUFFER_SGIX 0x801C +#define GLX_WIDTH_SGIX 0x801D +#define GLX_HEIGHT_SGIX 0x801E +#define GLX_EVENT_MASK_SGIX 0x801F +#define GLX_DAMAGED_SGIX 0x8020 +#define GLX_SAVED_SGIX 0x8021 +#define GLX_WINDOW_SGIX 0x8022 +#define GLX_PBUFFER_SGIX 0x8023 +#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 + +typedef XID GLXPbufferSGIX; +typedef struct { int type; unsigned long serial; Bool send_event; Display *display; GLXDrawable drawable; int event_type; int draw_type; unsigned int mask; int x, y; int width, height; int count; } GLXBufferClobberEventSGIX; + +typedef GLXPbuffer ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display* dpy, GLXFBConfig config, unsigned int width, unsigned int height, int *attrib_list); +typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long *mask); +typedef void ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display* dpy, GLXPbuffer pbuf, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display* dpy, GLXDrawable drawable, unsigned long mask); + +#define glXCreateGLXPbufferSGIX GLXEW_GET_FUN(__glewXCreateGLXPbufferSGIX) +#define glXDestroyGLXPbufferSGIX GLXEW_GET_FUN(__glewXDestroyGLXPbufferSGIX) +#define glXGetSelectedEventSGIX GLXEW_GET_FUN(__glewXGetSelectedEventSGIX) +#define glXQueryGLXPbufferSGIX GLXEW_GET_FUN(__glewXQueryGLXPbufferSGIX) +#define glXSelectEventSGIX GLXEW_GET_FUN(__glewXSelectEventSGIX) + +#define GLXEW_SGIX_pbuffer GLXEW_GET_VAR(__GLXEW_SGIX_pbuffer) + +#endif /* GLX_SGIX_pbuffer */ + +/* ------------------------- GLX_SGIX_swap_barrier ------------------------- */ + +#ifndef GLX_SGIX_swap_barrier +#define GLX_SGIX_swap_barrier 1 + +typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier); +typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max); + +#define glXBindSwapBarrierSGIX GLXEW_GET_FUN(__glewXBindSwapBarrierSGIX) +#define glXQueryMaxSwapBarriersSGIX GLXEW_GET_FUN(__glewXQueryMaxSwapBarriersSGIX) + +#define GLXEW_SGIX_swap_barrier GLXEW_GET_VAR(__GLXEW_SGIX_swap_barrier) + +#endif /* GLX_SGIX_swap_barrier */ + +/* -------------------------- GLX_SGIX_swap_group -------------------------- */ + +#ifndef GLX_SGIX_swap_group +#define GLX_SGIX_swap_group 1 + +typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member); + +#define glXJoinSwapGroupSGIX GLXEW_GET_FUN(__glewXJoinSwapGroupSGIX) + +#define GLXEW_SGIX_swap_group GLXEW_GET_VAR(__GLXEW_SGIX_swap_group) + +#endif /* GLX_SGIX_swap_group */ + +/* ------------------------- GLX_SGIX_video_resize ------------------------- */ + +#ifndef GLX_SGIX_video_resize +#define GLX_SGIX_video_resize 1 + +#define GLX_SYNC_FRAME_SGIX 0x00000000 +#define GLX_SYNC_SWAP_SGIX 0x00000001 + +typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display* display, int screen, int channel, Window window); +typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int x, int y, int w, int h); +typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display* display, int screen, int channel, GLenum synctype); +typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display* display, int screen, int channel, int *x, int *y, int *w, int *h); +typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display* display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); + +#define glXBindChannelToWindowSGIX GLXEW_GET_FUN(__glewXBindChannelToWindowSGIX) +#define glXChannelRectSGIX GLXEW_GET_FUN(__glewXChannelRectSGIX) +#define glXChannelRectSyncSGIX GLXEW_GET_FUN(__glewXChannelRectSyncSGIX) +#define glXQueryChannelDeltasSGIX GLXEW_GET_FUN(__glewXQueryChannelDeltasSGIX) +#define glXQueryChannelRectSGIX GLXEW_GET_FUN(__glewXQueryChannelRectSGIX) + +#define GLXEW_SGIX_video_resize GLXEW_GET_VAR(__GLXEW_SGIX_video_resize) + +#endif /* GLX_SGIX_video_resize */ + +/* ---------------------- GLX_SGIX_visual_select_group --------------------- */ + +#ifndef GLX_SGIX_visual_select_group +#define GLX_SGIX_visual_select_group 1 + +#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028 + +#define GLXEW_SGIX_visual_select_group GLXEW_GET_VAR(__GLXEW_SGIX_visual_select_group) + +#endif /* GLX_SGIX_visual_select_group */ + +/* ---------------------------- GLX_SGI_cushion ---------------------------- */ + +#ifndef GLX_SGI_cushion +#define GLX_SGI_cushion 1 + +typedef void ( * PFNGLXCUSHIONSGIPROC) (Display* dpy, Window window, float cushion); + +#define glXCushionSGI GLXEW_GET_FUN(__glewXCushionSGI) + +#define GLXEW_SGI_cushion GLXEW_GET_VAR(__GLXEW_SGI_cushion) + +#endif /* GLX_SGI_cushion */ + +/* ----------------------- GLX_SGI_make_current_read ----------------------- */ + +#ifndef GLX_SGI_make_current_read +#define GLX_SGI_make_current_read 1 + +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void); +typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display* dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + +#define glXGetCurrentReadDrawableSGI GLXEW_GET_FUN(__glewXGetCurrentReadDrawableSGI) +#define glXMakeCurrentReadSGI GLXEW_GET_FUN(__glewXMakeCurrentReadSGI) + +#define GLXEW_SGI_make_current_read GLXEW_GET_VAR(__GLXEW_SGI_make_current_read) + +#endif /* GLX_SGI_make_current_read */ + +/* -------------------------- GLX_SGI_swap_control ------------------------- */ + +#ifndef GLX_SGI_swap_control +#define GLX_SGI_swap_control 1 + +typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval); + +#define glXSwapIntervalSGI GLXEW_GET_FUN(__glewXSwapIntervalSGI) + +#define GLXEW_SGI_swap_control GLXEW_GET_VAR(__GLXEW_SGI_swap_control) + +#endif /* GLX_SGI_swap_control */ + +/* --------------------------- GLX_SGI_video_sync -------------------------- */ + +#ifndef GLX_SGI_video_sync +#define GLX_SGI_video_sync 1 + +typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int* count); +typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int* count); + +#define glXGetVideoSyncSGI GLXEW_GET_FUN(__glewXGetVideoSyncSGI) +#define glXWaitVideoSyncSGI GLXEW_GET_FUN(__glewXWaitVideoSyncSGI) + +#define GLXEW_SGI_video_sync GLXEW_GET_VAR(__GLXEW_SGI_video_sync) + +#endif /* GLX_SGI_video_sync */ + +/* --------------------- GLX_SUN_get_transparent_index --------------------- */ + +#ifndef GLX_SUN_get_transparent_index +#define GLX_SUN_get_transparent_index 1 + +typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display* dpy, Window overlay, Window underlay, unsigned long *pTransparentIndex); + +#define glXGetTransparentIndexSUN GLXEW_GET_FUN(__glewXGetTransparentIndexSUN) + +#define GLXEW_SUN_get_transparent_index GLXEW_GET_VAR(__GLXEW_SUN_get_transparent_index) + +#endif /* GLX_SUN_get_transparent_index */ + +/* -------------------------- GLX_SUN_video_resize ------------------------- */ + +#ifndef GLX_SUN_video_resize +#define GLX_SUN_video_resize 1 + +#define GLX_VIDEO_RESIZE_SUN 0x8171 +#define GL_VIDEO_RESIZE_COMPENSATION_SUN 0x85CD + +typedef int ( * PFNGLXGETVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float* factor); +typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, float factor); + +#define glXGetVideoResizeSUN GLXEW_GET_FUN(__glewXGetVideoResizeSUN) +#define glXVideoResizeSUN GLXEW_GET_FUN(__glewXVideoResizeSUN) + +#define GLXEW_SUN_video_resize GLXEW_GET_VAR(__GLXEW_SUN_video_resize) + +#endif /* GLX_SUN_video_resize */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX +#define GLXEW_EXPORT +#else +#define GLXEW_EXPORT extern +#endif /* GLEW_MX */ + +extern PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay; + +extern PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig; +extern PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext; +extern PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer; +extern PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap; +extern PFNGLXCREATEWINDOWPROC __glewXCreateWindow; +extern PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer; +extern PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap; +extern PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow; +extern PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable; +extern PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib; +extern PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs; +extern PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent; +extern PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig; +extern PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent; +extern PFNGLXQUERYCONTEXTPROC __glewXQueryContext; +extern PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable; +extern PFNGLXSELECTEVENTPROC __glewXSelectEvent; + +extern PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB; + +extern PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI; +extern PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI; +extern PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI; + +extern PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT; +extern PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT; +extern PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT; +extern PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT; + +extern PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT; + +extern PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT; +extern PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT; + +extern PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA; + +extern PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA; + +extern PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA; + +extern PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA; + +extern PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA; + +extern PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV; + +extern PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV; +extern PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV; + +extern PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV; +extern PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV; +extern PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV; +extern PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV; +extern PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV; +extern PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV; + +extern PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV; +extern PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV; + +extern PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV; +extern PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV; +extern PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV; +extern PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV; +extern PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV; + +extern PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV; +extern PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV; +extern PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV; +extern PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV; +extern PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV; +extern PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV; + +extern PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML; +extern PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML; +extern PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML; +extern PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML; +extern PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML; + +extern PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX; +extern PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX; +extern PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX; +extern PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX; +extern PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX; +extern PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX; + +extern PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX; +extern PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX; +extern PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX; +extern PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX; +extern PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX; +extern PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX; +extern PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX; +extern PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX; + +extern PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX; +extern PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX; +extern PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX; +extern PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX; +extern PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX; + +extern PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX; +extern PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX; + +extern PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX; + +extern PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX; +extern PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX; +extern PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX; +extern PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX; +extern PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX; + +extern PFNGLXCUSHIONSGIPROC __glewXCushionSGI; + +extern PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI; +extern PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI; + +extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI; + +extern PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI; +extern PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI; + +extern PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN; + +extern PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN; +extern PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN; + +#if defined(GLEW_MX) +struct GLXEWContextStruct +{ +#endif /* GLEW_MX */ + +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_0; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_1; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_2; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_3; +GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_4; +GLXEW_EXPORT GLboolean __GLXEW_3DFX_multisample; +GLXEW_EXPORT GLboolean __GLXEW_AMD_gpu_association; +GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context; +GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_profile; +GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_robustness; +GLXEW_EXPORT GLboolean __GLXEW_ARB_fbconfig_float; +GLXEW_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB; +GLXEW_EXPORT GLboolean __GLXEW_ARB_get_proc_address; +GLXEW_EXPORT GLboolean __GLXEW_ARB_multisample; +GLXEW_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object; +GLXEW_EXPORT GLboolean __GLXEW_ATI_pixel_format_float; +GLXEW_EXPORT GLboolean __GLXEW_ATI_render_texture; +GLXEW_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile; +GLXEW_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float; +GLXEW_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB; +GLXEW_EXPORT GLboolean __GLXEW_EXT_import_context; +GLXEW_EXPORT GLboolean __GLXEW_EXT_scene_marker; +GLXEW_EXPORT GLboolean __GLXEW_EXT_swap_control; +GLXEW_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap; +GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_info; +GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_rating; +GLXEW_EXPORT GLboolean __GLXEW_INTEL_swap_event; +GLXEW_EXPORT GLboolean __GLXEW_MESA_agp_offset; +GLXEW_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer; +GLXEW_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap; +GLXEW_EXPORT GLboolean __GLXEW_MESA_release_buffers; +GLXEW_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode; +GLXEW_EXPORT GLboolean __GLXEW_NV_copy_image; +GLXEW_EXPORT GLboolean __GLXEW_NV_float_buffer; +GLXEW_EXPORT GLboolean __GLXEW_NV_multisample_coverage; +GLXEW_EXPORT GLboolean __GLXEW_NV_present_video; +GLXEW_EXPORT GLboolean __GLXEW_NV_swap_group; +GLXEW_EXPORT GLboolean __GLXEW_NV_vertex_array_range; +GLXEW_EXPORT GLboolean __GLXEW_NV_video_capture; +GLXEW_EXPORT GLboolean __GLXEW_NV_video_output; +GLXEW_EXPORT GLboolean __GLXEW_OML_swap_method; +GLXEW_EXPORT GLboolean __GLXEW_OML_sync_control; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_blended_overlay; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_color_range; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_multisample; +GLXEW_EXPORT GLboolean __GLXEW_SGIS_shared_multisample; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_fbconfig; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_hyperpipe; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_pbuffer; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_barrier; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_group; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_video_resize; +GLXEW_EXPORT GLboolean __GLXEW_SGIX_visual_select_group; +GLXEW_EXPORT GLboolean __GLXEW_SGI_cushion; +GLXEW_EXPORT GLboolean __GLXEW_SGI_make_current_read; +GLXEW_EXPORT GLboolean __GLXEW_SGI_swap_control; +GLXEW_EXPORT GLboolean __GLXEW_SGI_video_sync; +GLXEW_EXPORT GLboolean __GLXEW_SUN_get_transparent_index; +GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize; + +#ifdef GLEW_MX +}; /* GLXEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------ */ + +#ifdef GLEW_MX + +typedef struct GLXEWContextStruct GLXEWContext; +extern GLenum glxewContextInit (GLXEWContext* ctx); +extern GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name); + +#define glxewInit() glxewContextInit(glxewGetContext()) +#define glxewIsSupported(x) glxewContextIsSupported(glxewGetContext(), x) + +#define GLXEW_GET_VAR(x) (*(const GLboolean*)&(glxewGetContext()->x)) +#define GLXEW_GET_FUN(x) x + +#else /* GLEW_MX */ + +#define GLXEW_GET_VAR(x) (*(const GLboolean*)&x) +#define GLXEW_GET_FUN(x) x + +extern GLboolean glxewIsSupported (const char* name); + +#endif /* GLEW_MX */ + +extern GLboolean glxewGetExtension (const char* name); + +#ifdef __cplusplus +} +#endif + +#endif /* __glxew_h__ */ diff --git a/ext/glew/GL/wglew.h b/ext/glew/GL/wglew.h new file mode 100644 index 0000000000..deb6468281 --- /dev/null +++ b/ext/glew/GL/wglew.h @@ -0,0 +1,1361 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* +** Copyright (c) 2007 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __wglew_h__ +#define __wglew_h__ +#define __WGLEW_H__ + +#ifdef __wglext_h_ +#error wglext.h included before wglew.h +#endif + +#define __wglext_h_ + +#if !defined(WINAPI) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +#include +# undef WIN32_LEAN_AND_MEAN +#endif + +/* + * GLEW_STATIC needs to be set when using the static version. + * GLEW_BUILD is set when building the DLL version. + */ +#ifdef GLEW_STATIC +# define GLEWAPI extern +#else +# ifdef GLEW_BUILD +# define GLEWAPI extern __declspec(dllexport) +# else +# define GLEWAPI extern __declspec(dllimport) +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* -------------------------- WGL_3DFX_multisample ------------------------- */ + +#ifndef WGL_3DFX_multisample +#define WGL_3DFX_multisample 1 + +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 + +#define WGLEW_3DFX_multisample WGLEW_GET_VAR(__WGLEW_3DFX_multisample) + +#endif /* WGL_3DFX_multisample */ + +/* ------------------------- WGL_3DL_stereo_control ------------------------ */ + +#ifndef WGL_3DL_stereo_control +#define WGL_3DL_stereo_control 1 + +#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 +#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 +#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 +#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 + +typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState); + +#define wglSetStereoEmitterState3DL WGLEW_GET_FUN(__wglewSetStereoEmitterState3DL) + +#define WGLEW_3DL_stereo_control WGLEW_GET_VAR(__WGLEW_3DL_stereo_control) + +#endif /* WGL_3DL_stereo_control */ + +/* ------------------------ WGL_AMD_gpu_association ------------------------ */ + +#ifndef WGL_AMD_gpu_association +#define WGL_AMD_gpu_association 1 + +#define WGL_GPU_VENDOR_AMD 0x1F00 +#define WGL_GPU_RENDERER_STRING_AMD 0x1F01 +#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 +#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 +#define WGL_GPU_RAM_AMD 0x21A3 +#define WGL_GPU_CLOCK_AMD 0x21A4 +#define WGL_GPU_NUM_PIPES_AMD 0x21A5 +#define WGL_GPU_NUM_SIMD_AMD 0x21A6 +#define WGL_GPU_NUM_RB_AMD 0x21A7 +#define WGL_GPU_NUM_SPI_AMD 0x21A8 + +typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id); +typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int* attribList); +typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc); +typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc); +typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void); +typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT* ids); +typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, INT property, GLenum dataType, UINT size, void* data); +typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc); + +#define wglBlitContextFramebufferAMD WGLEW_GET_FUN(__wglewBlitContextFramebufferAMD) +#define wglCreateAssociatedContextAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAMD) +#define wglCreateAssociatedContextAttribsAMD WGLEW_GET_FUN(__wglewCreateAssociatedContextAttribsAMD) +#define wglDeleteAssociatedContextAMD WGLEW_GET_FUN(__wglewDeleteAssociatedContextAMD) +#define wglGetContextGPUIDAMD WGLEW_GET_FUN(__wglewGetContextGPUIDAMD) +#define wglGetCurrentAssociatedContextAMD WGLEW_GET_FUN(__wglewGetCurrentAssociatedContextAMD) +#define wglGetGPUIDsAMD WGLEW_GET_FUN(__wglewGetGPUIDsAMD) +#define wglGetGPUInfoAMD WGLEW_GET_FUN(__wglewGetGPUInfoAMD) +#define wglMakeAssociatedContextCurrentAMD WGLEW_GET_FUN(__wglewMakeAssociatedContextCurrentAMD) + +#define WGLEW_AMD_gpu_association WGLEW_GET_VAR(__WGLEW_AMD_gpu_association) + +#endif /* WGL_AMD_gpu_association */ + +/* ------------------------- WGL_ARB_buffer_region ------------------------- */ + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 + +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 + +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); + +#define wglCreateBufferRegionARB WGLEW_GET_FUN(__wglewCreateBufferRegionARB) +#define wglDeleteBufferRegionARB WGLEW_GET_FUN(__wglewDeleteBufferRegionARB) +#define wglRestoreBufferRegionARB WGLEW_GET_FUN(__wglewRestoreBufferRegionARB) +#define wglSaveBufferRegionARB WGLEW_GET_FUN(__wglewSaveBufferRegionARB) + +#define WGLEW_ARB_buffer_region WGLEW_GET_VAR(__WGLEW_ARB_buffer_region) + +#endif /* WGL_ARB_buffer_region */ + +/* ------------------------- WGL_ARB_create_context ------------------------ */ + +#ifndef WGL_ARB_create_context +#define WGL_ARB_create_context 1 + +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 + +typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList); + +#define wglCreateContextAttribsARB WGLEW_GET_FUN(__wglewCreateContextAttribsARB) + +#define WGLEW_ARB_create_context WGLEW_GET_VAR(__WGLEW_ARB_create_context) + +#endif /* WGL_ARB_create_context */ + +/* --------------------- WGL_ARB_create_context_profile -------------------- */ + +#ifndef WGL_ARB_create_context_profile +#define WGL_ARB_create_context_profile 1 + +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 + +#define WGLEW_ARB_create_context_profile WGLEW_GET_VAR(__WGLEW_ARB_create_context_profile) + +#endif /* WGL_ARB_create_context_profile */ + +/* ------------------- WGL_ARB_create_context_robustness ------------------- */ + +#ifndef WGL_ARB_create_context_robustness +#define WGL_ARB_create_context_robustness 1 + +#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 + +#define WGLEW_ARB_create_context_robustness WGLEW_GET_VAR(__WGLEW_ARB_create_context_robustness) + +#endif /* WGL_ARB_create_context_robustness */ + +/* ----------------------- WGL_ARB_extensions_string ----------------------- */ + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 + +typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); + +#define wglGetExtensionsStringARB WGLEW_GET_FUN(__wglewGetExtensionsStringARB) + +#define WGLEW_ARB_extensions_string WGLEW_GET_VAR(__WGLEW_ARB_extensions_string) + +#endif /* WGL_ARB_extensions_string */ + +/* ------------------------ WGL_ARB_framebuffer_sRGB ----------------------- */ + +#ifndef WGL_ARB_framebuffer_sRGB +#define WGL_ARB_framebuffer_sRGB 1 + +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 + +#define WGLEW_ARB_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_ARB_framebuffer_sRGB) + +#endif /* WGL_ARB_framebuffer_sRGB */ + +/* ----------------------- WGL_ARB_make_current_read ----------------------- */ + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 + +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 + +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + +#define wglGetCurrentReadDCARB WGLEW_GET_FUN(__wglewGetCurrentReadDCARB) +#define wglMakeContextCurrentARB WGLEW_GET_FUN(__wglewMakeContextCurrentARB) + +#define WGLEW_ARB_make_current_read WGLEW_GET_VAR(__WGLEW_ARB_make_current_read) + +#endif /* WGL_ARB_make_current_read */ + +/* -------------------------- WGL_ARB_multisample -------------------------- */ + +#ifndef WGL_ARB_multisample +#define WGL_ARB_multisample 1 + +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 + +#define WGLEW_ARB_multisample WGLEW_GET_VAR(__WGLEW_ARB_multisample) + +#endif /* WGL_ARB_multisample */ + +/* ---------------------------- WGL_ARB_pbuffer ---------------------------- */ + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 + +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 + +DECLARE_HANDLE(HPBUFFERARB); + +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int* piValue); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); + +#define wglCreatePbufferARB WGLEW_GET_FUN(__wglewCreatePbufferARB) +#define wglDestroyPbufferARB WGLEW_GET_FUN(__wglewDestroyPbufferARB) +#define wglGetPbufferDCARB WGLEW_GET_FUN(__wglewGetPbufferDCARB) +#define wglQueryPbufferARB WGLEW_GET_FUN(__wglewQueryPbufferARB) +#define wglReleasePbufferDCARB WGLEW_GET_FUN(__wglewReleasePbufferDCARB) + +#define WGLEW_ARB_pbuffer WGLEW_GET_VAR(__WGLEW_ARB_pbuffer) + +#endif /* WGL_ARB_pbuffer */ + +/* -------------------------- WGL_ARB_pixel_format ------------------------- */ + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 + +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B + +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int* piAttributes, int *piValues); + +#define wglChoosePixelFormatARB WGLEW_GET_FUN(__wglewChoosePixelFormatARB) +#define wglGetPixelFormatAttribfvARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvARB) +#define wglGetPixelFormatAttribivARB WGLEW_GET_FUN(__wglewGetPixelFormatAttribivARB) + +#define WGLEW_ARB_pixel_format WGLEW_GET_VAR(__WGLEW_ARB_pixel_format) + +#endif /* WGL_ARB_pixel_format */ + +/* ----------------------- WGL_ARB_pixel_format_float ---------------------- */ + +#ifndef WGL_ARB_pixel_format_float +#define WGL_ARB_pixel_format_float 1 + +#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 + +#define WGLEW_ARB_pixel_format_float WGLEW_GET_VAR(__WGLEW_ARB_pixel_format_float) + +#endif /* WGL_ARB_pixel_format_float */ + +/* ------------------------- WGL_ARB_render_texture ------------------------ */ + +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 + +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 + +typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int* piAttribList); + +#define wglBindTexImageARB WGLEW_GET_FUN(__wglewBindTexImageARB) +#define wglReleaseTexImageARB WGLEW_GET_FUN(__wglewReleaseTexImageARB) +#define wglSetPbufferAttribARB WGLEW_GET_FUN(__wglewSetPbufferAttribARB) + +#define WGLEW_ARB_render_texture WGLEW_GET_VAR(__WGLEW_ARB_render_texture) + +#endif /* WGL_ARB_render_texture */ + +/* ----------------------- WGL_ATI_pixel_format_float ---------------------- */ + +#ifndef WGL_ATI_pixel_format_float +#define WGL_ATI_pixel_format_float 1 + +#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 +#define GL_RGBA_FLOAT_MODE_ATI 0x8820 +#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 + +#define WGLEW_ATI_pixel_format_float WGLEW_GET_VAR(__WGLEW_ATI_pixel_format_float) + +#endif /* WGL_ATI_pixel_format_float */ + +/* -------------------- WGL_ATI_render_texture_rectangle ------------------- */ + +#ifndef WGL_ATI_render_texture_rectangle +#define WGL_ATI_render_texture_rectangle 1 + +#define WGL_TEXTURE_RECTANGLE_ATI 0x21A5 + +#define WGLEW_ATI_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_ATI_render_texture_rectangle) + +#endif /* WGL_ATI_render_texture_rectangle */ + +/* ------------------- WGL_EXT_create_context_es2_profile ------------------ */ + +#ifndef WGL_EXT_create_context_es2_profile +#define WGL_EXT_create_context_es2_profile 1 + +#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 + +#define WGLEW_EXT_create_context_es2_profile WGLEW_GET_VAR(__WGLEW_EXT_create_context_es2_profile) + +#endif /* WGL_EXT_create_context_es2_profile */ + +/* -------------------------- WGL_EXT_depth_float -------------------------- */ + +#ifndef WGL_EXT_depth_float +#define WGL_EXT_depth_float 1 + +#define WGL_DEPTH_FLOAT_EXT 0x2040 + +#define WGLEW_EXT_depth_float WGLEW_GET_VAR(__WGLEW_EXT_depth_float) + +#endif /* WGL_EXT_depth_float */ + +/* ---------------------- WGL_EXT_display_color_table ---------------------- */ + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 + +typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef void (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (GLushort* table, GLuint length); + +#define wglBindDisplayColorTableEXT WGLEW_GET_FUN(__wglewBindDisplayColorTableEXT) +#define wglCreateDisplayColorTableEXT WGLEW_GET_FUN(__wglewCreateDisplayColorTableEXT) +#define wglDestroyDisplayColorTableEXT WGLEW_GET_FUN(__wglewDestroyDisplayColorTableEXT) +#define wglLoadDisplayColorTableEXT WGLEW_GET_FUN(__wglewLoadDisplayColorTableEXT) + +#define WGLEW_EXT_display_color_table WGLEW_GET_VAR(__WGLEW_EXT_display_color_table) + +#endif /* WGL_EXT_display_color_table */ + +/* ----------------------- WGL_EXT_extensions_string ----------------------- */ + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 + +typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); + +#define wglGetExtensionsStringEXT WGLEW_GET_FUN(__wglewGetExtensionsStringEXT) + +#define WGLEW_EXT_extensions_string WGLEW_GET_VAR(__WGLEW_EXT_extensions_string) + +#endif /* WGL_EXT_extensions_string */ + +/* ------------------------ WGL_EXT_framebuffer_sRGB ----------------------- */ + +#ifndef WGL_EXT_framebuffer_sRGB +#define WGL_EXT_framebuffer_sRGB 1 + +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 + +#define WGLEW_EXT_framebuffer_sRGB WGLEW_GET_VAR(__WGLEW_EXT_framebuffer_sRGB) + +#endif /* WGL_EXT_framebuffer_sRGB */ + +/* ----------------------- WGL_EXT_make_current_read ----------------------- */ + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 + +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 + +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + +#define wglGetCurrentReadDCEXT WGLEW_GET_FUN(__wglewGetCurrentReadDCEXT) +#define wglMakeContextCurrentEXT WGLEW_GET_FUN(__wglewMakeContextCurrentEXT) + +#define WGLEW_EXT_make_current_read WGLEW_GET_VAR(__WGLEW_EXT_make_current_read) + +#endif /* WGL_EXT_make_current_read */ + +/* -------------------------- WGL_EXT_multisample -------------------------- */ + +#ifndef WGL_EXT_multisample +#define WGL_EXT_multisample 1 + +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 + +#define WGLEW_EXT_multisample WGLEW_GET_VAR(__WGLEW_EXT_multisample) + +#endif /* WGL_EXT_multisample */ + +/* ---------------------------- WGL_EXT_pbuffer ---------------------------- */ + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 + +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 + +DECLARE_HANDLE(HPBUFFEREXT); + +typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int* piValue); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); + +#define wglCreatePbufferEXT WGLEW_GET_FUN(__wglewCreatePbufferEXT) +#define wglDestroyPbufferEXT WGLEW_GET_FUN(__wglewDestroyPbufferEXT) +#define wglGetPbufferDCEXT WGLEW_GET_FUN(__wglewGetPbufferDCEXT) +#define wglQueryPbufferEXT WGLEW_GET_FUN(__wglewQueryPbufferEXT) +#define wglReleasePbufferDCEXT WGLEW_GET_FUN(__wglewReleasePbufferDCEXT) + +#define WGLEW_EXT_pbuffer WGLEW_GET_VAR(__WGLEW_EXT_pbuffer) + +#endif /* WGL_EXT_pbuffer */ + +/* -------------------------- WGL_EXT_pixel_format ------------------------- */ + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 + +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C + +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues); + +#define wglChoosePixelFormatEXT WGLEW_GET_FUN(__wglewChoosePixelFormatEXT) +#define wglGetPixelFormatAttribfvEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribfvEXT) +#define wglGetPixelFormatAttribivEXT WGLEW_GET_FUN(__wglewGetPixelFormatAttribivEXT) + +#define WGLEW_EXT_pixel_format WGLEW_GET_VAR(__WGLEW_EXT_pixel_format) + +#endif /* WGL_EXT_pixel_format */ + +/* ------------------- WGL_EXT_pixel_format_packed_float ------------------- */ + +#ifndef WGL_EXT_pixel_format_packed_float +#define WGL_EXT_pixel_format_packed_float 1 + +#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 + +#define WGLEW_EXT_pixel_format_packed_float WGLEW_GET_VAR(__WGLEW_EXT_pixel_format_packed_float) + +#endif /* WGL_EXT_pixel_format_packed_float */ + +/* -------------------------- WGL_EXT_swap_control ------------------------- */ + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 + +typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); + +#define wglGetSwapIntervalEXT WGLEW_GET_FUN(__wglewGetSwapIntervalEXT) +#define wglSwapIntervalEXT WGLEW_GET_FUN(__wglewSwapIntervalEXT) + +#define WGLEW_EXT_swap_control WGLEW_GET_VAR(__WGLEW_EXT_swap_control) + +#endif /* WGL_EXT_swap_control */ + +/* --------------------- WGL_I3D_digital_video_control --------------------- */ + +#ifndef WGL_I3D_digital_video_control +#define WGL_I3D_digital_video_control 1 + +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 + +typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue); + +#define wglGetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewGetDigitalVideoParametersI3D) +#define wglSetDigitalVideoParametersI3D WGLEW_GET_FUN(__wglewSetDigitalVideoParametersI3D) + +#define WGLEW_I3D_digital_video_control WGLEW_GET_VAR(__WGLEW_I3D_digital_video_control) + +#endif /* WGL_I3D_digital_video_control */ + +/* ----------------------------- WGL_I3D_gamma ----------------------------- */ + +#ifndef WGL_I3D_gamma +#define WGL_I3D_gamma 1 + +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F + +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT* puRed, USHORT *puGreen, USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT* puRed, const USHORT *puGreen, const USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int* piValue); + +#define wglGetGammaTableI3D WGLEW_GET_FUN(__wglewGetGammaTableI3D) +#define wglGetGammaTableParametersI3D WGLEW_GET_FUN(__wglewGetGammaTableParametersI3D) +#define wglSetGammaTableI3D WGLEW_GET_FUN(__wglewSetGammaTableI3D) +#define wglSetGammaTableParametersI3D WGLEW_GET_FUN(__wglewSetGammaTableParametersI3D) + +#define WGLEW_I3D_gamma WGLEW_GET_VAR(__WGLEW_I3D_gamma) + +#endif /* WGL_I3D_gamma */ + +/* ---------------------------- WGL_I3D_genlock ---------------------------- */ + +#ifndef WGL_I3D_genlock +#define WGL_I3D_genlock 1 + +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C + +typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT* uRate); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT* uDelay); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT* uEdge); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT* uSource); +typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL* pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT* uMaxLineDelay, UINT *uMaxPixelDelay); + +#define wglDisableGenlockI3D WGLEW_GET_FUN(__wglewDisableGenlockI3D) +#define wglEnableGenlockI3D WGLEW_GET_FUN(__wglewEnableGenlockI3D) +#define wglGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGenlockSampleRateI3D) +#define wglGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGenlockSourceDelayI3D) +#define wglGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGenlockSourceEdgeI3D) +#define wglGenlockSourceI3D WGLEW_GET_FUN(__wglewGenlockSourceI3D) +#define wglGetGenlockSampleRateI3D WGLEW_GET_FUN(__wglewGetGenlockSampleRateI3D) +#define wglGetGenlockSourceDelayI3D WGLEW_GET_FUN(__wglewGetGenlockSourceDelayI3D) +#define wglGetGenlockSourceEdgeI3D WGLEW_GET_FUN(__wglewGetGenlockSourceEdgeI3D) +#define wglGetGenlockSourceI3D WGLEW_GET_FUN(__wglewGetGenlockSourceI3D) +#define wglIsEnabledGenlockI3D WGLEW_GET_FUN(__wglewIsEnabledGenlockI3D) +#define wglQueryGenlockMaxSourceDelayI3D WGLEW_GET_FUN(__wglewQueryGenlockMaxSourceDelayI3D) + +#define WGLEW_I3D_genlock WGLEW_GET_VAR(__WGLEW_I3D_genlock) + +#endif /* WGL_I3D_genlock */ + +/* -------------------------- WGL_I3D_image_buffer ------------------------- */ + +#ifndef WGL_I3D_image_buffer +#define WGL_I3D_image_buffer 1 + +#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 +#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 + +typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, HANDLE* pEvent, LPVOID *pAddress, DWORD *pSize, UINT count); +typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); +typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); +typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hdc, LPVOID* pAddress, UINT count); + +#define wglAssociateImageBufferEventsI3D WGLEW_GET_FUN(__wglewAssociateImageBufferEventsI3D) +#define wglCreateImageBufferI3D WGLEW_GET_FUN(__wglewCreateImageBufferI3D) +#define wglDestroyImageBufferI3D WGLEW_GET_FUN(__wglewDestroyImageBufferI3D) +#define wglReleaseImageBufferEventsI3D WGLEW_GET_FUN(__wglewReleaseImageBufferEventsI3D) + +#define WGLEW_I3D_image_buffer WGLEW_GET_VAR(__WGLEW_I3D_image_buffer) + +#endif /* WGL_I3D_image_buffer */ + +/* ------------------------ WGL_I3D_swap_frame_lock ------------------------ */ + +#ifndef WGL_I3D_swap_frame_lock +#define WGL_I3D_swap_frame_lock 1 + +typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (VOID); +typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL* pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL* pFlag); + +#define wglDisableFrameLockI3D WGLEW_GET_FUN(__wglewDisableFrameLockI3D) +#define wglEnableFrameLockI3D WGLEW_GET_FUN(__wglewEnableFrameLockI3D) +#define wglIsEnabledFrameLockI3D WGLEW_GET_FUN(__wglewIsEnabledFrameLockI3D) +#define wglQueryFrameLockMasterI3D WGLEW_GET_FUN(__wglewQueryFrameLockMasterI3D) + +#define WGLEW_I3D_swap_frame_lock WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_lock) + +#endif /* WGL_I3D_swap_frame_lock */ + +/* ------------------------ WGL_I3D_swap_frame_usage ----------------------- */ + +#ifndef WGL_I3D_swap_frame_usage +#define WGL_I3D_swap_frame_usage 1 + +typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float* pUsage); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD* pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); + +#define wglBeginFrameTrackingI3D WGLEW_GET_FUN(__wglewBeginFrameTrackingI3D) +#define wglEndFrameTrackingI3D WGLEW_GET_FUN(__wglewEndFrameTrackingI3D) +#define wglGetFrameUsageI3D WGLEW_GET_FUN(__wglewGetFrameUsageI3D) +#define wglQueryFrameTrackingI3D WGLEW_GET_FUN(__wglewQueryFrameTrackingI3D) + +#define WGLEW_I3D_swap_frame_usage WGLEW_GET_VAR(__WGLEW_I3D_swap_frame_usage) + +#endif /* WGL_I3D_swap_frame_usage */ + +/* --------------------------- WGL_NV_DX_interop --------------------------- */ + +#ifndef WGL_NV_DX_interop +#define WGL_NV_DX_interop 1 + +#define WGL_ACCESS_READ_ONLY_NV 0x0000 +#define WGL_ACCESS_READ_WRITE_NV 0x0001 +#define WGL_ACCESS_WRITE_DISCARD_NV 0x0002 + +typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice); +typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); +typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access); +typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void* dxDevice); +typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access); +typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void* dxObject, HANDLE shareHandle); +typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); +typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject); + +#define wglDXCloseDeviceNV WGLEW_GET_FUN(__wglewDXCloseDeviceNV) +#define wglDXLockObjectsNV WGLEW_GET_FUN(__wglewDXLockObjectsNV) +#define wglDXObjectAccessNV WGLEW_GET_FUN(__wglewDXObjectAccessNV) +#define wglDXOpenDeviceNV WGLEW_GET_FUN(__wglewDXOpenDeviceNV) +#define wglDXRegisterObjectNV WGLEW_GET_FUN(__wglewDXRegisterObjectNV) +#define wglDXSetResourceShareHandleNV WGLEW_GET_FUN(__wglewDXSetResourceShareHandleNV) +#define wglDXUnlockObjectsNV WGLEW_GET_FUN(__wglewDXUnlockObjectsNV) +#define wglDXUnregisterObjectNV WGLEW_GET_FUN(__wglewDXUnregisterObjectNV) + +#define WGLEW_NV_DX_interop WGLEW_GET_VAR(__WGLEW_NV_DX_interop) + +#endif /* WGL_NV_DX_interop */ + +/* --------------------------- WGL_NV_copy_image --------------------------- */ + +#ifndef WGL_NV_copy_image +#define WGL_NV_copy_image 1 + +typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); + +#define wglCopyImageSubDataNV WGLEW_GET_FUN(__wglewCopyImageSubDataNV) + +#define WGLEW_NV_copy_image WGLEW_GET_VAR(__WGLEW_NV_copy_image) + +#endif /* WGL_NV_copy_image */ + +/* -------------------------- WGL_NV_float_buffer -------------------------- */ + +#ifndef WGL_NV_float_buffer +#define WGL_NV_float_buffer 1 + +#define WGL_FLOAT_COMPONENTS_NV 0x20B0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 +#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 +#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 +#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 +#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 + +#define WGLEW_NV_float_buffer WGLEW_GET_VAR(__WGLEW_NV_float_buffer) + +#endif /* WGL_NV_float_buffer */ + +/* -------------------------- WGL_NV_gpu_affinity -------------------------- */ + +#ifndef WGL_NV_gpu_affinity +#define WGL_NV_gpu_affinity 1 + +#define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 +#define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 + +DECLARE_HANDLE(HGPUNV); +typedef struct _GPU_DEVICE { + DWORD cb; + CHAR DeviceName[32]; + CHAR DeviceString[128]; + DWORD Flags; + RECT rcVirtualScreen; +} GPU_DEVICE, *PGPU_DEVICE; + +typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList); +typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc); +typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); +typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); +typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu); + +#define wglCreateAffinityDCNV WGLEW_GET_FUN(__wglewCreateAffinityDCNV) +#define wglDeleteDCNV WGLEW_GET_FUN(__wglewDeleteDCNV) +#define wglEnumGpuDevicesNV WGLEW_GET_FUN(__wglewEnumGpuDevicesNV) +#define wglEnumGpusFromAffinityDCNV WGLEW_GET_FUN(__wglewEnumGpusFromAffinityDCNV) +#define wglEnumGpusNV WGLEW_GET_FUN(__wglewEnumGpusNV) + +#define WGLEW_NV_gpu_affinity WGLEW_GET_VAR(__WGLEW_NV_gpu_affinity) + +#endif /* WGL_NV_gpu_affinity */ + +/* ---------------------- WGL_NV_multisample_coverage ---------------------- */ + +#ifndef WGL_NV_multisample_coverage +#define WGL_NV_multisample_coverage 1 + +#define WGL_COVERAGE_SAMPLES_NV 0x2042 +#define WGL_COLOR_SAMPLES_NV 0x20B9 + +#define WGLEW_NV_multisample_coverage WGLEW_GET_VAR(__WGLEW_NV_multisample_coverage) + +#endif /* WGL_NV_multisample_coverage */ + +/* -------------------------- WGL_NV_present_video ------------------------- */ + +#ifndef WGL_NV_present_video +#define WGL_NV_present_video 1 + +#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 + +DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDc, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int* piAttribList); +typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDc, HVIDEOOUTPUTDEVICENV* phDeviceList); +typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int* piValue); + +#define wglBindVideoDeviceNV WGLEW_GET_FUN(__wglewBindVideoDeviceNV) +#define wglEnumerateVideoDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoDevicesNV) +#define wglQueryCurrentContextNV WGLEW_GET_FUN(__wglewQueryCurrentContextNV) + +#define WGLEW_NV_present_video WGLEW_GET_VAR(__WGLEW_NV_present_video) + +#endif /* WGL_NV_present_video */ + +/* ---------------------- WGL_NV_render_depth_texture ---------------------- */ + +#ifndef WGL_NV_render_depth_texture +#define WGL_NV_render_depth_texture 1 + +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 + +#define WGLEW_NV_render_depth_texture WGLEW_GET_VAR(__WGLEW_NV_render_depth_texture) + +#endif /* WGL_NV_render_depth_texture */ + +/* -------------------- WGL_NV_render_texture_rectangle -------------------- */ + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_NV_render_texture_rectangle 1 + +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 + +#define WGLEW_NV_render_texture_rectangle WGLEW_GET_VAR(__WGLEW_NV_render_texture_rectangle) + +#endif /* WGL_NV_render_texture_rectangle */ + +/* --------------------------- WGL_NV_swap_group --------------------------- */ + +#ifndef WGL_NV_swap_group +#define WGL_NV_swap_group 1 + +typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); +typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint* count); +typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint* maxGroups, GLuint *maxBarriers); +typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint* group, GLuint *barrier); +typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); + +#define wglBindSwapBarrierNV WGLEW_GET_FUN(__wglewBindSwapBarrierNV) +#define wglJoinSwapGroupNV WGLEW_GET_FUN(__wglewJoinSwapGroupNV) +#define wglQueryFrameCountNV WGLEW_GET_FUN(__wglewQueryFrameCountNV) +#define wglQueryMaxSwapGroupsNV WGLEW_GET_FUN(__wglewQueryMaxSwapGroupsNV) +#define wglQuerySwapGroupNV WGLEW_GET_FUN(__wglewQuerySwapGroupNV) +#define wglResetFrameCountNV WGLEW_GET_FUN(__wglewResetFrameCountNV) + +#define WGLEW_NV_swap_group WGLEW_GET_VAR(__WGLEW_NV_swap_group) + +#endif /* WGL_NV_swap_group */ + +/* ----------------------- WGL_NV_vertex_array_range ----------------------- */ + +#ifndef WGL_NV_vertex_array_range +#define WGL_NV_vertex_array_range 1 + +typedef void * (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); +typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); + +#define wglAllocateMemoryNV WGLEW_GET_FUN(__wglewAllocateMemoryNV) +#define wglFreeMemoryNV WGLEW_GET_FUN(__wglewFreeMemoryNV) + +#define WGLEW_NV_vertex_array_range WGLEW_GET_VAR(__WGLEW_NV_vertex_array_range) + +#endif /* WGL_NV_vertex_array_range */ + +/* -------------------------- WGL_NV_video_capture ------------------------- */ + +#ifndef WGL_NV_video_capture +#define WGL_NV_video_capture 1 + +#define WGL_UNIQUE_ID_NV 0x20CE +#define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF + +DECLARE_HANDLE(HVIDEOINPUTDEVICENV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice); +typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV* phDeviceList); +typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); +typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int* piValue); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); + +#define wglBindVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewBindVideoCaptureDeviceNV) +#define wglEnumerateVideoCaptureDevicesNV WGLEW_GET_FUN(__wglewEnumerateVideoCaptureDevicesNV) +#define wglLockVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewLockVideoCaptureDeviceNV) +#define wglQueryVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewQueryVideoCaptureDeviceNV) +#define wglReleaseVideoCaptureDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoCaptureDeviceNV) + +#define WGLEW_NV_video_capture WGLEW_GET_VAR(__WGLEW_NV_video_capture) + +#endif /* WGL_NV_video_capture */ + +/* -------------------------- WGL_NV_video_output -------------------------- */ + +#ifndef WGL_NV_video_output +#define WGL_NV_video_output 1 + +#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 +#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 +#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 +#define WGL_VIDEO_OUT_COLOR_NV 0x20C3 +#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 +#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 +#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 +#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 +#define WGL_VIDEO_OUT_FRAME 0x20C8 +#define WGL_VIDEO_OUT_FIELD_1 0x20C9 +#define WGL_VIDEO_OUT_FIELD_2 0x20CA +#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB +#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC + +DECLARE_HANDLE(HPVIDEODEV); + +typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV* hVideoDevice); +typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long* pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); +typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); +typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long* pulCounterPbuffer, BOOL bBlock); + +#define wglBindVideoImageNV WGLEW_GET_FUN(__wglewBindVideoImageNV) +#define wglGetVideoDeviceNV WGLEW_GET_FUN(__wglewGetVideoDeviceNV) +#define wglGetVideoInfoNV WGLEW_GET_FUN(__wglewGetVideoInfoNV) +#define wglReleaseVideoDeviceNV WGLEW_GET_FUN(__wglewReleaseVideoDeviceNV) +#define wglReleaseVideoImageNV WGLEW_GET_FUN(__wglewReleaseVideoImageNV) +#define wglSendPbufferToVideoNV WGLEW_GET_FUN(__wglewSendPbufferToVideoNV) + +#define WGLEW_NV_video_output WGLEW_GET_VAR(__WGLEW_NV_video_output) + +#endif /* WGL_NV_video_output */ + +/* -------------------------- WGL_OML_sync_control ------------------------- */ + +#ifndef WGL_OML_sync_control +#define WGL_OML_sync_control 1 + +typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32* numerator, INT32 *denominator); +typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64* ust, INT64 *msc, INT64 *sbc); +typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64* ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64* ust, INT64 *msc, INT64 *sbc); + +#define wglGetMscRateOML WGLEW_GET_FUN(__wglewGetMscRateOML) +#define wglGetSyncValuesOML WGLEW_GET_FUN(__wglewGetSyncValuesOML) +#define wglSwapBuffersMscOML WGLEW_GET_FUN(__wglewSwapBuffersMscOML) +#define wglSwapLayerBuffersMscOML WGLEW_GET_FUN(__wglewSwapLayerBuffersMscOML) +#define wglWaitForMscOML WGLEW_GET_FUN(__wglewWaitForMscOML) +#define wglWaitForSbcOML WGLEW_GET_FUN(__wglewWaitForSbcOML) + +#define WGLEW_OML_sync_control WGLEW_GET_VAR(__WGLEW_OML_sync_control) + +#endif /* WGL_OML_sync_control */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX +#define WGLEW_EXPORT +#else +#define WGLEW_EXPORT GLEWAPI +#endif /* GLEW_MX */ + +#ifdef GLEW_MX +struct WGLEWContextStruct +{ +#endif /* GLEW_MX */ + +WGLEW_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL; + +WGLEW_EXPORT PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD; +WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD; +WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD; +WGLEW_EXPORT PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD; +WGLEW_EXPORT PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD; +WGLEW_EXPORT PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD; +WGLEW_EXPORT PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD; +WGLEW_EXPORT PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD; +WGLEW_EXPORT PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD; + +WGLEW_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB; +WGLEW_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB; +WGLEW_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB; +WGLEW_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB; + +WGLEW_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB; + +WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB; + +WGLEW_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB; +WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB; + +WGLEW_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB; +WGLEW_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB; +WGLEW_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB; +WGLEW_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB; +WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB; + +WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB; + +WGLEW_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB; +WGLEW_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB; +WGLEW_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB; + +WGLEW_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT; +WGLEW_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT; + +WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT; + +WGLEW_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT; +WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT; + +WGLEW_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT; +WGLEW_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT; +WGLEW_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT; +WGLEW_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT; +WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT; + +WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT; +WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT; + +WGLEW_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT; +WGLEW_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT; + +WGLEW_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D; +WGLEW_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D; + +WGLEW_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D; +WGLEW_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D; +WGLEW_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D; +WGLEW_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D; + +WGLEW_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D; +WGLEW_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D; +WGLEW_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D; +WGLEW_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D; +WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D; +WGLEW_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D; +WGLEW_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D; + +WGLEW_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D; +WGLEW_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D; +WGLEW_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D; +WGLEW_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D; + +WGLEW_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D; +WGLEW_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D; +WGLEW_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D; +WGLEW_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D; + +WGLEW_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D; +WGLEW_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D; +WGLEW_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D; +WGLEW_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D; + +WGLEW_EXPORT PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV; +WGLEW_EXPORT PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV; +WGLEW_EXPORT PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV; +WGLEW_EXPORT PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV; +WGLEW_EXPORT PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV; +WGLEW_EXPORT PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV; +WGLEW_EXPORT PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV; +WGLEW_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV; + +WGLEW_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV; + +WGLEW_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV; +WGLEW_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV; +WGLEW_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV; +WGLEW_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV; +WGLEW_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV; + +WGLEW_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV; +WGLEW_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV; +WGLEW_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV; + +WGLEW_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV; +WGLEW_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV; +WGLEW_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV; +WGLEW_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV; +WGLEW_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV; +WGLEW_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV; + +WGLEW_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV; +WGLEW_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV; + +WGLEW_EXPORT PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV; +WGLEW_EXPORT PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV; +WGLEW_EXPORT PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV; +WGLEW_EXPORT PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV; + +WGLEW_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV; +WGLEW_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV; +WGLEW_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV; +WGLEW_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV; +WGLEW_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV; + +WGLEW_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML; +WGLEW_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML; +WGLEW_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML; +WGLEW_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML; +WGLEW_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML; +WGLEW_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML; +WGLEW_EXPORT GLboolean __WGLEW_3DFX_multisample; +WGLEW_EXPORT GLboolean __WGLEW_3DL_stereo_control; +WGLEW_EXPORT GLboolean __WGLEW_AMD_gpu_association; +WGLEW_EXPORT GLboolean __WGLEW_ARB_buffer_region; +WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context; +WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_profile; +WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_robustness; +WGLEW_EXPORT GLboolean __WGLEW_ARB_extensions_string; +WGLEW_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB; +WGLEW_EXPORT GLboolean __WGLEW_ARB_make_current_read; +WGLEW_EXPORT GLboolean __WGLEW_ARB_multisample; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pbuffer; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format; +WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format_float; +WGLEW_EXPORT GLboolean __WGLEW_ARB_render_texture; +WGLEW_EXPORT GLboolean __WGLEW_ATI_pixel_format_float; +WGLEW_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle; +WGLEW_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile; +WGLEW_EXPORT GLboolean __WGLEW_EXT_depth_float; +WGLEW_EXPORT GLboolean __WGLEW_EXT_display_color_table; +WGLEW_EXPORT GLboolean __WGLEW_EXT_extensions_string; +WGLEW_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB; +WGLEW_EXPORT GLboolean __WGLEW_EXT_make_current_read; +WGLEW_EXPORT GLboolean __WGLEW_EXT_multisample; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pbuffer; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format; +WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float; +WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control; +WGLEW_EXPORT GLboolean __WGLEW_I3D_digital_video_control; +WGLEW_EXPORT GLboolean __WGLEW_I3D_gamma; +WGLEW_EXPORT GLboolean __WGLEW_I3D_genlock; +WGLEW_EXPORT GLboolean __WGLEW_I3D_image_buffer; +WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock; +WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage; +WGLEW_EXPORT GLboolean __WGLEW_NV_DX_interop; +WGLEW_EXPORT GLboolean __WGLEW_NV_copy_image; +WGLEW_EXPORT GLboolean __WGLEW_NV_float_buffer; +WGLEW_EXPORT GLboolean __WGLEW_NV_gpu_affinity; +WGLEW_EXPORT GLboolean __WGLEW_NV_multisample_coverage; +WGLEW_EXPORT GLboolean __WGLEW_NV_present_video; +WGLEW_EXPORT GLboolean __WGLEW_NV_render_depth_texture; +WGLEW_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle; +WGLEW_EXPORT GLboolean __WGLEW_NV_swap_group; +WGLEW_EXPORT GLboolean __WGLEW_NV_vertex_array_range; +WGLEW_EXPORT GLboolean __WGLEW_NV_video_capture; +WGLEW_EXPORT GLboolean __WGLEW_NV_video_output; +WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control; + +#ifdef GLEW_MX +}; /* WGLEWContextStruct */ +#endif /* GLEW_MX */ + +/* ------------------------------------------------------------------------- */ + +#ifdef GLEW_MX + +typedef struct WGLEWContextStruct WGLEWContext; +GLEWAPI GLenum wglewContextInit (WGLEWContext* ctx); +GLEWAPI GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name); + +#define wglewInit() wglewContextInit(wglewGetContext()) +#define wglewIsSupported(x) wglewContextIsSupported(wglewGetContext(), x) + +#define WGLEW_GET_VAR(x) (*(const GLboolean*)&(wglewGetContext()->x)) +#define WGLEW_GET_FUN(x) wglewGetContext()->x + +#else /* GLEW_MX */ + +#define WGLEW_GET_VAR(x) (*(const GLboolean*)&x) +#define WGLEW_GET_FUN(x) x + +GLEWAPI GLboolean wglewIsSupported (const char* name); + +#endif /* GLEW_MX */ + +GLEWAPI GLboolean wglewGetExtension (const char* name); + +#ifdef __cplusplus +} +#endif + +#undef GLEWAPI + +#endif /* __wglew_h__ */ diff --git a/ext/glew/glew.c b/ext/glew/glew.c new file mode 100644 index 0000000000..72a81fef53 --- /dev/null +++ b/ext/glew/glew.c @@ -0,0 +1,15485 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#if defined(_WIN32) +# include +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +# include +#endif + +#pragma warning(disable:4273) + +/* + * Define glewGetContext and related helper macros. + */ +#ifdef GLEW_MX +# define glewGetContext() ctx +# ifdef _WIN32 +# define GLEW_CONTEXT_ARG_DEF_INIT GLEWContext* ctx +# define GLEW_CONTEXT_ARG_VAR_INIT ctx +# define wglewGetContext() ctx +# define WGLEW_CONTEXT_ARG_DEF_INIT WGLEWContext* ctx +# define WGLEW_CONTEXT_ARG_DEF_LIST WGLEWContext* ctx +# else /* _WIN32 */ +# define GLEW_CONTEXT_ARG_DEF_INIT void +# define GLEW_CONTEXT_ARG_VAR_INIT +# define glxewGetContext() ctx +# define GLXEW_CONTEXT_ARG_DEF_INIT void +# define GLXEW_CONTEXT_ARG_DEF_LIST GLXEWContext* ctx +# endif /* _WIN32 */ +# define GLEW_CONTEXT_ARG_DEF_LIST GLEWContext* ctx +#else /* GLEW_MX */ +# define GLEW_CONTEXT_ARG_DEF_INIT void +# define GLEW_CONTEXT_ARG_VAR_INIT +# define GLEW_CONTEXT_ARG_DEF_LIST void +# define WGLEW_CONTEXT_ARG_DEF_INIT void +# define WGLEW_CONTEXT_ARG_DEF_LIST void +# define GLXEW_CONTEXT_ARG_DEF_INIT void +# define GLXEW_CONTEXT_ARG_DEF_LIST void +#endif /* GLEW_MX */ + +#if defined(__sgi) || defined (__sun) || defined(GLEW_APPLE_GLX) +#include +#include +#include + +void* dlGetProcAddress (const GLubyte* name) +{ + static void* h = NULL; + static void* gpa; + + if (h == NULL) + { + if ((h = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL)) == NULL) return NULL; + gpa = dlsym(h, "glXGetProcAddress"); + } + + if (gpa != NULL) + return ((void*(*)(const GLubyte*))gpa)(name); + else + return dlsym(h, (const char*)name); +} +#endif /* __sgi || __sun || GLEW_APPLE_GLX */ + +#if defined(__APPLE__) +#include +#include +#include + +#ifdef MAC_OS_X_VERSION_10_3 + +#include + +void* NSGLGetProcAddress (const GLubyte *name) +{ + static void* image = NULL; + if (NULL == image) + { + image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); + } + if( !image ) return NULL; + void* addr = dlsym(image, (const char*)name); + if( addr ) return addr; +#ifdef GLEW_APPLE_GLX + return dlGetProcAddress( name ); // try next for glx symbols +#else + return NULL; +#endif +} +#else + +#include + +void* NSGLGetProcAddress (const GLubyte *name) +{ + static const struct mach_header* image = NULL; + NSSymbol symbol; + char* symbolName; + if (NULL == image) + { + image = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", NSADDIMAGE_OPTION_RETURN_ON_ERROR); + } + /* prepend a '_' for the Unix C symbol mangling convention */ + symbolName = malloc(strlen((const char*)name) + 2); + strcpy(symbolName+1, (const char*)name); + symbolName[0] = '_'; + symbol = NULL; + /* if (NSIsSymbolNameDefined(symbolName)) + symbol = NSLookupAndBindSymbol(symbolName); */ + symbol = image ? NSLookupSymbolInImage(image, symbolName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) : NULL; + free(symbolName); + if( symbol ) return NSAddressOfSymbol(symbol); +#ifdef GLEW_APPLE_GLX + return dlGetProcAddress( name ); // try next for glx symbols +#else + return NULL; +#endif +} +#endif /* MAC_OS_X_VERSION_10_3 */ +#endif /* __APPLE__ */ + +/* + * Define glewGetProcAddress. + */ +#if defined(_WIN32) +# define glewGetProcAddress(name) wglGetProcAddress((LPCSTR)name) +#else +# if defined(__APPLE__) +# define glewGetProcAddress(name) NSGLGetProcAddress(name) +# else +# if defined(__sgi) || defined(__sun) +# define glewGetProcAddress(name) dlGetProcAddress(name) +# else /* __linux */ +# define glewGetProcAddress(name) (*glXGetProcAddressARB)(name) +# endif +# endif +#endif + +/* + * Define GLboolean const cast. + */ +#define CONST_CAST(x) (*(GLboolean*)&x) + +/* + * GLEW, just like OpenGL or GLU, does not rely on the standard C library. + * These functions implement the functionality required in this file. + */ +static GLuint _glewStrLen (const GLubyte* s) +{ + GLuint i=0; + if (s == NULL) return 0; + while (s[i] != '\0') i++; + return i; +} + +static GLuint _glewStrCLen (const GLubyte* s, GLubyte c) +{ + GLuint i=0; + if (s == NULL) return 0; + while (s[i] != '\0' && s[i] != c) i++; + return (s[i] == '\0' || s[i] == c) ? i : 0; +} + +static GLboolean _glewStrSame (const GLubyte* a, const GLubyte* b, GLuint n) +{ + GLuint i=0; + if(a == NULL || b == NULL) + return (a == NULL && b == NULL && n == 0) ? GL_TRUE : GL_FALSE; + while (i < n && a[i] != '\0' && b[i] != '\0' && a[i] == b[i]) i++; + return i == n ? GL_TRUE : GL_FALSE; +} + +static GLboolean _glewStrSame1 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb) +{ + while (*na > 0 && (**a == ' ' || **a == '\n' || **a == '\r' || **a == '\t')) + { + (*a)++; + (*na)--; + } + if(*na >= nb) + { + GLuint i=0; + while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++; + if(i == nb) + { + *a = *a + nb; + *na = *na - nb; + return GL_TRUE; + } + } + return GL_FALSE; +} + +static GLboolean _glewStrSame2 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb) +{ + if(*na >= nb) + { + GLuint i=0; + while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++; + if(i == nb) + { + *a = *a + nb; + *na = *na - nb; + return GL_TRUE; + } + } + return GL_FALSE; +} + +static GLboolean _glewStrSame3 (GLubyte** a, GLuint* na, const GLubyte* b, GLuint nb) +{ + if(*na >= nb) + { + GLuint i=0; + while (i < nb && (*a)+i != NULL && b+i != NULL && (*a)[i] == b[i]) i++; + if (i == nb && (*na == nb || (*a)[i] == ' ' || (*a)[i] == '\n' || (*a)[i] == '\r' || (*a)[i] == '\t')) + { + *a = *a + nb; + *na = *na - nb; + return GL_TRUE; + } + } + return GL_FALSE; +} + +/* + * Search for name in the extensions string. Use of strstr() + * is not sufficient because extension names can be prefixes of + * other extension names. Could use strtok() but the constant + * string returned by glGetString might be in read-only memory. + */ +static GLboolean _glewSearchExtension (const char* name, const GLubyte *start, const GLubyte *end) +{ + const GLubyte* p; + GLuint len = _glewStrLen((const GLubyte*)name); + p = start; + while (p < end) + { + GLuint n = _glewStrCLen(p, ' '); + if (len == n && _glewStrSame((const GLubyte*)name, p, n)) return GL_TRUE; + p += n+1; + } + return GL_FALSE; +} + +#if !defined(_WIN32) || !defined(GLEW_MX) + +PFNGLCOPYTEXSUBIMAGE3DPROC __glewCopyTexSubImage3D = NULL; +PFNGLDRAWRANGEELEMENTSPROC __glewDrawRangeElements = NULL; +PFNGLTEXIMAGE3DPROC __glewTexImage3D = NULL; +PFNGLTEXSUBIMAGE3DPROC __glewTexSubImage3D = NULL; + +PFNGLACTIVETEXTUREPROC __glewActiveTexture = NULL; +PFNGLCLIENTACTIVETEXTUREPROC __glewClientActiveTexture = NULL; +PFNGLCOMPRESSEDTEXIMAGE1DPROC __glewCompressedTexImage1D = NULL; +PFNGLCOMPRESSEDTEXIMAGE2DPROC __glewCompressedTexImage2D = NULL; +PFNGLCOMPRESSEDTEXIMAGE3DPROC __glewCompressedTexImage3D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC __glewCompressedTexSubImage1D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC __glewCompressedTexSubImage2D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC __glewCompressedTexSubImage3D = NULL; +PFNGLGETCOMPRESSEDTEXIMAGEPROC __glewGetCompressedTexImage = NULL; +PFNGLLOADTRANSPOSEMATRIXDPROC __glewLoadTransposeMatrixd = NULL; +PFNGLLOADTRANSPOSEMATRIXFPROC __glewLoadTransposeMatrixf = NULL; +PFNGLMULTTRANSPOSEMATRIXDPROC __glewMultTransposeMatrixd = NULL; +PFNGLMULTTRANSPOSEMATRIXFPROC __glewMultTransposeMatrixf = NULL; +PFNGLMULTITEXCOORD1DPROC __glewMultiTexCoord1d = NULL; +PFNGLMULTITEXCOORD1DVPROC __glewMultiTexCoord1dv = NULL; +PFNGLMULTITEXCOORD1FPROC __glewMultiTexCoord1f = NULL; +PFNGLMULTITEXCOORD1FVPROC __glewMultiTexCoord1fv = NULL; +PFNGLMULTITEXCOORD1IPROC __glewMultiTexCoord1i = NULL; +PFNGLMULTITEXCOORD1IVPROC __glewMultiTexCoord1iv = NULL; +PFNGLMULTITEXCOORD1SPROC __glewMultiTexCoord1s = NULL; +PFNGLMULTITEXCOORD1SVPROC __glewMultiTexCoord1sv = NULL; +PFNGLMULTITEXCOORD2DPROC __glewMultiTexCoord2d = NULL; +PFNGLMULTITEXCOORD2DVPROC __glewMultiTexCoord2dv = NULL; +PFNGLMULTITEXCOORD2FPROC __glewMultiTexCoord2f = NULL; +PFNGLMULTITEXCOORD2FVPROC __glewMultiTexCoord2fv = NULL; +PFNGLMULTITEXCOORD2IPROC __glewMultiTexCoord2i = NULL; +PFNGLMULTITEXCOORD2IVPROC __glewMultiTexCoord2iv = NULL; +PFNGLMULTITEXCOORD2SPROC __glewMultiTexCoord2s = NULL; +PFNGLMULTITEXCOORD2SVPROC __glewMultiTexCoord2sv = NULL; +PFNGLMULTITEXCOORD3DPROC __glewMultiTexCoord3d = NULL; +PFNGLMULTITEXCOORD3DVPROC __glewMultiTexCoord3dv = NULL; +PFNGLMULTITEXCOORD3FPROC __glewMultiTexCoord3f = NULL; +PFNGLMULTITEXCOORD3FVPROC __glewMultiTexCoord3fv = NULL; +PFNGLMULTITEXCOORD3IPROC __glewMultiTexCoord3i = NULL; +PFNGLMULTITEXCOORD3IVPROC __glewMultiTexCoord3iv = NULL; +PFNGLMULTITEXCOORD3SPROC __glewMultiTexCoord3s = NULL; +PFNGLMULTITEXCOORD3SVPROC __glewMultiTexCoord3sv = NULL; +PFNGLMULTITEXCOORD4DPROC __glewMultiTexCoord4d = NULL; +PFNGLMULTITEXCOORD4DVPROC __glewMultiTexCoord4dv = NULL; +PFNGLMULTITEXCOORD4FPROC __glewMultiTexCoord4f = NULL; +PFNGLMULTITEXCOORD4FVPROC __glewMultiTexCoord4fv = NULL; +PFNGLMULTITEXCOORD4IPROC __glewMultiTexCoord4i = NULL; +PFNGLMULTITEXCOORD4IVPROC __glewMultiTexCoord4iv = NULL; +PFNGLMULTITEXCOORD4SPROC __glewMultiTexCoord4s = NULL; +PFNGLMULTITEXCOORD4SVPROC __glewMultiTexCoord4sv = NULL; +PFNGLSAMPLECOVERAGEPROC __glewSampleCoverage = NULL; + +PFNGLBLENDCOLORPROC __glewBlendColor = NULL; +PFNGLBLENDEQUATIONPROC __glewBlendEquation = NULL; +PFNGLBLENDFUNCSEPARATEPROC __glewBlendFuncSeparate = NULL; +PFNGLFOGCOORDPOINTERPROC __glewFogCoordPointer = NULL; +PFNGLFOGCOORDDPROC __glewFogCoordd = NULL; +PFNGLFOGCOORDDVPROC __glewFogCoorddv = NULL; +PFNGLFOGCOORDFPROC __glewFogCoordf = NULL; +PFNGLFOGCOORDFVPROC __glewFogCoordfv = NULL; +PFNGLMULTIDRAWARRAYSPROC __glewMultiDrawArrays = NULL; +PFNGLMULTIDRAWELEMENTSPROC __glewMultiDrawElements = NULL; +PFNGLPOINTPARAMETERFPROC __glewPointParameterf = NULL; +PFNGLPOINTPARAMETERFVPROC __glewPointParameterfv = NULL; +PFNGLPOINTPARAMETERIPROC __glewPointParameteri = NULL; +PFNGLPOINTPARAMETERIVPROC __glewPointParameteriv = NULL; +PFNGLSECONDARYCOLOR3BPROC __glewSecondaryColor3b = NULL; +PFNGLSECONDARYCOLOR3BVPROC __glewSecondaryColor3bv = NULL; +PFNGLSECONDARYCOLOR3DPROC __glewSecondaryColor3d = NULL; +PFNGLSECONDARYCOLOR3DVPROC __glewSecondaryColor3dv = NULL; +PFNGLSECONDARYCOLOR3FPROC __glewSecondaryColor3f = NULL; +PFNGLSECONDARYCOLOR3FVPROC __glewSecondaryColor3fv = NULL; +PFNGLSECONDARYCOLOR3IPROC __glewSecondaryColor3i = NULL; +PFNGLSECONDARYCOLOR3IVPROC __glewSecondaryColor3iv = NULL; +PFNGLSECONDARYCOLOR3SPROC __glewSecondaryColor3s = NULL; +PFNGLSECONDARYCOLOR3SVPROC __glewSecondaryColor3sv = NULL; +PFNGLSECONDARYCOLOR3UBPROC __glewSecondaryColor3ub = NULL; +PFNGLSECONDARYCOLOR3UBVPROC __glewSecondaryColor3ubv = NULL; +PFNGLSECONDARYCOLOR3UIPROC __glewSecondaryColor3ui = NULL; +PFNGLSECONDARYCOLOR3UIVPROC __glewSecondaryColor3uiv = NULL; +PFNGLSECONDARYCOLOR3USPROC __glewSecondaryColor3us = NULL; +PFNGLSECONDARYCOLOR3USVPROC __glewSecondaryColor3usv = NULL; +PFNGLSECONDARYCOLORPOINTERPROC __glewSecondaryColorPointer = NULL; +PFNGLWINDOWPOS2DPROC __glewWindowPos2d = NULL; +PFNGLWINDOWPOS2DVPROC __glewWindowPos2dv = NULL; +PFNGLWINDOWPOS2FPROC __glewWindowPos2f = NULL; +PFNGLWINDOWPOS2FVPROC __glewWindowPos2fv = NULL; +PFNGLWINDOWPOS2IPROC __glewWindowPos2i = NULL; +PFNGLWINDOWPOS2IVPROC __glewWindowPos2iv = NULL; +PFNGLWINDOWPOS2SPROC __glewWindowPos2s = NULL; +PFNGLWINDOWPOS2SVPROC __glewWindowPos2sv = NULL; +PFNGLWINDOWPOS3DPROC __glewWindowPos3d = NULL; +PFNGLWINDOWPOS3DVPROC __glewWindowPos3dv = NULL; +PFNGLWINDOWPOS3FPROC __glewWindowPos3f = NULL; +PFNGLWINDOWPOS3FVPROC __glewWindowPos3fv = NULL; +PFNGLWINDOWPOS3IPROC __glewWindowPos3i = NULL; +PFNGLWINDOWPOS3IVPROC __glewWindowPos3iv = NULL; +PFNGLWINDOWPOS3SPROC __glewWindowPos3s = NULL; +PFNGLWINDOWPOS3SVPROC __glewWindowPos3sv = NULL; + +PFNGLBEGINQUERYPROC __glewBeginQuery = NULL; +PFNGLBINDBUFFERPROC __glewBindBuffer = NULL; +PFNGLBUFFERDATAPROC __glewBufferData = NULL; +PFNGLBUFFERSUBDATAPROC __glewBufferSubData = NULL; +PFNGLDELETEBUFFERSPROC __glewDeleteBuffers = NULL; +PFNGLDELETEQUERIESPROC __glewDeleteQueries = NULL; +PFNGLENDQUERYPROC __glewEndQuery = NULL; +PFNGLGENBUFFERSPROC __glewGenBuffers = NULL; +PFNGLGENQUERIESPROC __glewGenQueries = NULL; +PFNGLGETBUFFERPARAMETERIVPROC __glewGetBufferParameteriv = NULL; +PFNGLGETBUFFERPOINTERVPROC __glewGetBufferPointerv = NULL; +PFNGLGETBUFFERSUBDATAPROC __glewGetBufferSubData = NULL; +PFNGLGETQUERYOBJECTIVPROC __glewGetQueryObjectiv = NULL; +PFNGLGETQUERYOBJECTUIVPROC __glewGetQueryObjectuiv = NULL; +PFNGLGETQUERYIVPROC __glewGetQueryiv = NULL; +PFNGLISBUFFERPROC __glewIsBuffer = NULL; +PFNGLISQUERYPROC __glewIsQuery = NULL; +PFNGLMAPBUFFERPROC __glewMapBuffer = NULL; +PFNGLUNMAPBUFFERPROC __glewUnmapBuffer = NULL; + +PFNGLATTACHSHADERPROC __glewAttachShader = NULL; +PFNGLBINDATTRIBLOCATIONPROC __glewBindAttribLocation = NULL; +PFNGLBLENDEQUATIONSEPARATEPROC __glewBlendEquationSeparate = NULL; +PFNGLCOMPILESHADERPROC __glewCompileShader = NULL; +PFNGLCREATEPROGRAMPROC __glewCreateProgram = NULL; +PFNGLCREATESHADERPROC __glewCreateShader = NULL; +PFNGLDELETEPROGRAMPROC __glewDeleteProgram = NULL; +PFNGLDELETESHADERPROC __glewDeleteShader = NULL; +PFNGLDETACHSHADERPROC __glewDetachShader = NULL; +PFNGLDISABLEVERTEXATTRIBARRAYPROC __glewDisableVertexAttribArray = NULL; +PFNGLDRAWBUFFERSPROC __glewDrawBuffers = NULL; +PFNGLENABLEVERTEXATTRIBARRAYPROC __glewEnableVertexAttribArray = NULL; +PFNGLGETACTIVEATTRIBPROC __glewGetActiveAttrib = NULL; +PFNGLGETACTIVEUNIFORMPROC __glewGetActiveUniform = NULL; +PFNGLGETATTACHEDSHADERSPROC __glewGetAttachedShaders = NULL; +PFNGLGETATTRIBLOCATIONPROC __glewGetAttribLocation = NULL; +PFNGLGETPROGRAMINFOLOGPROC __glewGetProgramInfoLog = NULL; +PFNGLGETPROGRAMIVPROC __glewGetProgramiv = NULL; +PFNGLGETSHADERINFOLOGPROC __glewGetShaderInfoLog = NULL; +PFNGLGETSHADERSOURCEPROC __glewGetShaderSource = NULL; +PFNGLGETSHADERIVPROC __glewGetShaderiv = NULL; +PFNGLGETUNIFORMLOCATIONPROC __glewGetUniformLocation = NULL; +PFNGLGETUNIFORMFVPROC __glewGetUniformfv = NULL; +PFNGLGETUNIFORMIVPROC __glewGetUniformiv = NULL; +PFNGLGETVERTEXATTRIBPOINTERVPROC __glewGetVertexAttribPointerv = NULL; +PFNGLGETVERTEXATTRIBDVPROC __glewGetVertexAttribdv = NULL; +PFNGLGETVERTEXATTRIBFVPROC __glewGetVertexAttribfv = NULL; +PFNGLGETVERTEXATTRIBIVPROC __glewGetVertexAttribiv = NULL; +PFNGLISPROGRAMPROC __glewIsProgram = NULL; +PFNGLISSHADERPROC __glewIsShader = NULL; +PFNGLLINKPROGRAMPROC __glewLinkProgram = NULL; +PFNGLSHADERSOURCEPROC __glewShaderSource = NULL; +PFNGLSTENCILFUNCSEPARATEPROC __glewStencilFuncSeparate = NULL; +PFNGLSTENCILMASKSEPARATEPROC __glewStencilMaskSeparate = NULL; +PFNGLSTENCILOPSEPARATEPROC __glewStencilOpSeparate = NULL; +PFNGLUNIFORM1FPROC __glewUniform1f = NULL; +PFNGLUNIFORM1FVPROC __glewUniform1fv = NULL; +PFNGLUNIFORM1IPROC __glewUniform1i = NULL; +PFNGLUNIFORM1IVPROC __glewUniform1iv = NULL; +PFNGLUNIFORM2FPROC __glewUniform2f = NULL; +PFNGLUNIFORM2FVPROC __glewUniform2fv = NULL; +PFNGLUNIFORM2IPROC __glewUniform2i = NULL; +PFNGLUNIFORM2IVPROC __glewUniform2iv = NULL; +PFNGLUNIFORM3FPROC __glewUniform3f = NULL; +PFNGLUNIFORM3FVPROC __glewUniform3fv = NULL; +PFNGLUNIFORM3IPROC __glewUniform3i = NULL; +PFNGLUNIFORM3IVPROC __glewUniform3iv = NULL; +PFNGLUNIFORM4FPROC __glewUniform4f = NULL; +PFNGLUNIFORM4FVPROC __glewUniform4fv = NULL; +PFNGLUNIFORM4IPROC __glewUniform4i = NULL; +PFNGLUNIFORM4IVPROC __glewUniform4iv = NULL; +PFNGLUNIFORMMATRIX2FVPROC __glewUniformMatrix2fv = NULL; +PFNGLUNIFORMMATRIX3FVPROC __glewUniformMatrix3fv = NULL; +PFNGLUNIFORMMATRIX4FVPROC __glewUniformMatrix4fv = NULL; +PFNGLUSEPROGRAMPROC __glewUseProgram = NULL; +PFNGLVALIDATEPROGRAMPROC __glewValidateProgram = NULL; +PFNGLVERTEXATTRIB1DPROC __glewVertexAttrib1d = NULL; +PFNGLVERTEXATTRIB1DVPROC __glewVertexAttrib1dv = NULL; +PFNGLVERTEXATTRIB1FPROC __glewVertexAttrib1f = NULL; +PFNGLVERTEXATTRIB1FVPROC __glewVertexAttrib1fv = NULL; +PFNGLVERTEXATTRIB1SPROC __glewVertexAttrib1s = NULL; +PFNGLVERTEXATTRIB1SVPROC __glewVertexAttrib1sv = NULL; +PFNGLVERTEXATTRIB2DPROC __glewVertexAttrib2d = NULL; +PFNGLVERTEXATTRIB2DVPROC __glewVertexAttrib2dv = NULL; +PFNGLVERTEXATTRIB2FPROC __glewVertexAttrib2f = NULL; +PFNGLVERTEXATTRIB2FVPROC __glewVertexAttrib2fv = NULL; +PFNGLVERTEXATTRIB2SPROC __glewVertexAttrib2s = NULL; +PFNGLVERTEXATTRIB2SVPROC __glewVertexAttrib2sv = NULL; +PFNGLVERTEXATTRIB3DPROC __glewVertexAttrib3d = NULL; +PFNGLVERTEXATTRIB3DVPROC __glewVertexAttrib3dv = NULL; +PFNGLVERTEXATTRIB3FPROC __glewVertexAttrib3f = NULL; +PFNGLVERTEXATTRIB3FVPROC __glewVertexAttrib3fv = NULL; +PFNGLVERTEXATTRIB3SPROC __glewVertexAttrib3s = NULL; +PFNGLVERTEXATTRIB3SVPROC __glewVertexAttrib3sv = NULL; +PFNGLVERTEXATTRIB4NBVPROC __glewVertexAttrib4Nbv = NULL; +PFNGLVERTEXATTRIB4NIVPROC __glewVertexAttrib4Niv = NULL; +PFNGLVERTEXATTRIB4NSVPROC __glewVertexAttrib4Nsv = NULL; +PFNGLVERTEXATTRIB4NUBPROC __glewVertexAttrib4Nub = NULL; +PFNGLVERTEXATTRIB4NUBVPROC __glewVertexAttrib4Nubv = NULL; +PFNGLVERTEXATTRIB4NUIVPROC __glewVertexAttrib4Nuiv = NULL; +PFNGLVERTEXATTRIB4NUSVPROC __glewVertexAttrib4Nusv = NULL; +PFNGLVERTEXATTRIB4BVPROC __glewVertexAttrib4bv = NULL; +PFNGLVERTEXATTRIB4DPROC __glewVertexAttrib4d = NULL; +PFNGLVERTEXATTRIB4DVPROC __glewVertexAttrib4dv = NULL; +PFNGLVERTEXATTRIB4FPROC __glewVertexAttrib4f = NULL; +PFNGLVERTEXATTRIB4FVPROC __glewVertexAttrib4fv = NULL; +PFNGLVERTEXATTRIB4IVPROC __glewVertexAttrib4iv = NULL; +PFNGLVERTEXATTRIB4SPROC __glewVertexAttrib4s = NULL; +PFNGLVERTEXATTRIB4SVPROC __glewVertexAttrib4sv = NULL; +PFNGLVERTEXATTRIB4UBVPROC __glewVertexAttrib4ubv = NULL; +PFNGLVERTEXATTRIB4UIVPROC __glewVertexAttrib4uiv = NULL; +PFNGLVERTEXATTRIB4USVPROC __glewVertexAttrib4usv = NULL; +PFNGLVERTEXATTRIBPOINTERPROC __glewVertexAttribPointer = NULL; + +PFNGLUNIFORMMATRIX2X3FVPROC __glewUniformMatrix2x3fv = NULL; +PFNGLUNIFORMMATRIX2X4FVPROC __glewUniformMatrix2x4fv = NULL; +PFNGLUNIFORMMATRIX3X2FVPROC __glewUniformMatrix3x2fv = NULL; +PFNGLUNIFORMMATRIX3X4FVPROC __glewUniformMatrix3x4fv = NULL; +PFNGLUNIFORMMATRIX4X2FVPROC __glewUniformMatrix4x2fv = NULL; +PFNGLUNIFORMMATRIX4X3FVPROC __glewUniformMatrix4x3fv = NULL; + +PFNGLBEGINCONDITIONALRENDERPROC __glewBeginConditionalRender = NULL; +PFNGLBEGINTRANSFORMFEEDBACKPROC __glewBeginTransformFeedback = NULL; +PFNGLBINDFRAGDATALOCATIONPROC __glewBindFragDataLocation = NULL; +PFNGLCLAMPCOLORPROC __glewClampColor = NULL; +PFNGLCLEARBUFFERFIPROC __glewClearBufferfi = NULL; +PFNGLCLEARBUFFERFVPROC __glewClearBufferfv = NULL; +PFNGLCLEARBUFFERIVPROC __glewClearBufferiv = NULL; +PFNGLCLEARBUFFERUIVPROC __glewClearBufferuiv = NULL; +PFNGLCOLORMASKIPROC __glewColorMaski = NULL; +PFNGLDISABLEIPROC __glewDisablei = NULL; +PFNGLENABLEIPROC __glewEnablei = NULL; +PFNGLENDCONDITIONALRENDERPROC __glewEndConditionalRender = NULL; +PFNGLENDTRANSFORMFEEDBACKPROC __glewEndTransformFeedback = NULL; +PFNGLGETBOOLEANI_VPROC __glewGetBooleani_v = NULL; +PFNGLGETFRAGDATALOCATIONPROC __glewGetFragDataLocation = NULL; +PFNGLGETSTRINGIPROC __glewGetStringi = NULL; +PFNGLGETTEXPARAMETERIIVPROC __glewGetTexParameterIiv = NULL; +PFNGLGETTEXPARAMETERIUIVPROC __glewGetTexParameterIuiv = NULL; +PFNGLGETTRANSFORMFEEDBACKVARYINGPROC __glewGetTransformFeedbackVarying = NULL; +PFNGLGETUNIFORMUIVPROC __glewGetUniformuiv = NULL; +PFNGLGETVERTEXATTRIBIIVPROC __glewGetVertexAttribIiv = NULL; +PFNGLGETVERTEXATTRIBIUIVPROC __glewGetVertexAttribIuiv = NULL; +PFNGLISENABLEDIPROC __glewIsEnabledi = NULL; +PFNGLTEXPARAMETERIIVPROC __glewTexParameterIiv = NULL; +PFNGLTEXPARAMETERIUIVPROC __glewTexParameterIuiv = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSPROC __glewTransformFeedbackVaryings = NULL; +PFNGLUNIFORM1UIPROC __glewUniform1ui = NULL; +PFNGLUNIFORM1UIVPROC __glewUniform1uiv = NULL; +PFNGLUNIFORM2UIPROC __glewUniform2ui = NULL; +PFNGLUNIFORM2UIVPROC __glewUniform2uiv = NULL; +PFNGLUNIFORM3UIPROC __glewUniform3ui = NULL; +PFNGLUNIFORM3UIVPROC __glewUniform3uiv = NULL; +PFNGLUNIFORM4UIPROC __glewUniform4ui = NULL; +PFNGLUNIFORM4UIVPROC __glewUniform4uiv = NULL; +PFNGLVERTEXATTRIBI1IPROC __glewVertexAttribI1i = NULL; +PFNGLVERTEXATTRIBI1IVPROC __glewVertexAttribI1iv = NULL; +PFNGLVERTEXATTRIBI1UIPROC __glewVertexAttribI1ui = NULL; +PFNGLVERTEXATTRIBI1UIVPROC __glewVertexAttribI1uiv = NULL; +PFNGLVERTEXATTRIBI2IPROC __glewVertexAttribI2i = NULL; +PFNGLVERTEXATTRIBI2IVPROC __glewVertexAttribI2iv = NULL; +PFNGLVERTEXATTRIBI2UIPROC __glewVertexAttribI2ui = NULL; +PFNGLVERTEXATTRIBI2UIVPROC __glewVertexAttribI2uiv = NULL; +PFNGLVERTEXATTRIBI3IPROC __glewVertexAttribI3i = NULL; +PFNGLVERTEXATTRIBI3IVPROC __glewVertexAttribI3iv = NULL; +PFNGLVERTEXATTRIBI3UIPROC __glewVertexAttribI3ui = NULL; +PFNGLVERTEXATTRIBI3UIVPROC __glewVertexAttribI3uiv = NULL; +PFNGLVERTEXATTRIBI4BVPROC __glewVertexAttribI4bv = NULL; +PFNGLVERTEXATTRIBI4IPROC __glewVertexAttribI4i = NULL; +PFNGLVERTEXATTRIBI4IVPROC __glewVertexAttribI4iv = NULL; +PFNGLVERTEXATTRIBI4SVPROC __glewVertexAttribI4sv = NULL; +PFNGLVERTEXATTRIBI4UBVPROC __glewVertexAttribI4ubv = NULL; +PFNGLVERTEXATTRIBI4UIPROC __glewVertexAttribI4ui = NULL; +PFNGLVERTEXATTRIBI4UIVPROC __glewVertexAttribI4uiv = NULL; +PFNGLVERTEXATTRIBI4USVPROC __glewVertexAttribI4usv = NULL; +PFNGLVERTEXATTRIBIPOINTERPROC __glewVertexAttribIPointer = NULL; + +PFNGLDRAWARRAYSINSTANCEDPROC __glewDrawArraysInstanced = NULL; +PFNGLDRAWELEMENTSINSTANCEDPROC __glewDrawElementsInstanced = NULL; +PFNGLPRIMITIVERESTARTINDEXPROC __glewPrimitiveRestartIndex = NULL; +PFNGLTEXBUFFERPROC __glewTexBuffer = NULL; + +PFNGLFRAMEBUFFERTEXTUREPROC __glewFramebufferTexture = NULL; +PFNGLGETBUFFERPARAMETERI64VPROC __glewGetBufferParameteri64v = NULL; +PFNGLGETINTEGER64I_VPROC __glewGetInteger64i_v = NULL; + +PFNGLVERTEXATTRIBDIVISORPROC __glewVertexAttribDivisor = NULL; + +PFNGLBLENDEQUATIONSEPARATEIPROC __glewBlendEquationSeparatei = NULL; +PFNGLBLENDEQUATIONIPROC __glewBlendEquationi = NULL; +PFNGLBLENDFUNCSEPARATEIPROC __glewBlendFuncSeparatei = NULL; +PFNGLBLENDFUNCIPROC __glewBlendFunci = NULL; +PFNGLMINSAMPLESHADINGPROC __glewMinSampleShading = NULL; + +PFNGLTBUFFERMASK3DFXPROC __glewTbufferMask3DFX = NULL; + +PFNGLDEBUGMESSAGECALLBACKAMDPROC __glewDebugMessageCallbackAMD = NULL; +PFNGLDEBUGMESSAGEENABLEAMDPROC __glewDebugMessageEnableAMD = NULL; +PFNGLDEBUGMESSAGEINSERTAMDPROC __glewDebugMessageInsertAMD = NULL; +PFNGLGETDEBUGMESSAGELOGAMDPROC __glewGetDebugMessageLogAMD = NULL; + +PFNGLBLENDEQUATIONINDEXEDAMDPROC __glewBlendEquationIndexedAMD = NULL; +PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSeparateIndexedAMD = NULL; +PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD = NULL; +PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD = NULL; + +PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD = NULL; +PFNGLGENNAMESAMDPROC __glewGenNamesAMD = NULL; +PFNGLISNAMEAMDPROC __glewIsNameAMD = NULL; + +PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD = NULL; +PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD = NULL; +PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD = NULL; +PFNGLGENPERFMONITORSAMDPROC __glewGenPerfMonitorsAMD = NULL; +PFNGLGETPERFMONITORCOUNTERDATAAMDPROC __glewGetPerfMonitorCounterDataAMD = NULL; +PFNGLGETPERFMONITORCOUNTERINFOAMDPROC __glewGetPerfMonitorCounterInfoAMD = NULL; +PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC __glewGetPerfMonitorCounterStringAMD = NULL; +PFNGLGETPERFMONITORCOUNTERSAMDPROC __glewGetPerfMonitorCountersAMD = NULL; +PFNGLGETPERFMONITORGROUPSTRINGAMDPROC __glewGetPerfMonitorGroupStringAMD = NULL; +PFNGLGETPERFMONITORGROUPSAMDPROC __glewGetPerfMonitorGroupsAMD = NULL; +PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD = NULL; + +PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD = NULL; + +PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD = NULL; +PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD = NULL; + +PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE = NULL; +PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE = NULL; +PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE = NULL; +PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC __glewMultiDrawElementArrayAPPLE = NULL; +PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC __glewMultiDrawRangeElementArrayAPPLE = NULL; + +PFNGLDELETEFENCESAPPLEPROC __glewDeleteFencesAPPLE = NULL; +PFNGLFINISHFENCEAPPLEPROC __glewFinishFenceAPPLE = NULL; +PFNGLFINISHOBJECTAPPLEPROC __glewFinishObjectAPPLE = NULL; +PFNGLGENFENCESAPPLEPROC __glewGenFencesAPPLE = NULL; +PFNGLISFENCEAPPLEPROC __glewIsFenceAPPLE = NULL; +PFNGLSETFENCEAPPLEPROC __glewSetFenceAPPLE = NULL; +PFNGLTESTFENCEAPPLEPROC __glewTestFenceAPPLE = NULL; +PFNGLTESTOBJECTAPPLEPROC __glewTestObjectAPPLE = NULL; + +PFNGLBUFFERPARAMETERIAPPLEPROC __glewBufferParameteriAPPLE = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC __glewFlushMappedBufferRangeAPPLE = NULL; + +PFNGLGETOBJECTPARAMETERIVAPPLEPROC __glewGetObjectParameterivAPPLE = NULL; +PFNGLOBJECTPURGEABLEAPPLEPROC __glewObjectPurgeableAPPLE = NULL; +PFNGLOBJECTUNPURGEABLEAPPLEPROC __glewObjectUnpurgeableAPPLE = NULL; + +PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC __glewGetTexParameterPointervAPPLE = NULL; +PFNGLTEXTURERANGEAPPLEPROC __glewTextureRangeAPPLE = NULL; + +PFNGLBINDVERTEXARRAYAPPLEPROC __glewBindVertexArrayAPPLE = NULL; +PFNGLDELETEVERTEXARRAYSAPPLEPROC __glewDeleteVertexArraysAPPLE = NULL; +PFNGLGENVERTEXARRAYSAPPLEPROC __glewGenVertexArraysAPPLE = NULL; +PFNGLISVERTEXARRAYAPPLEPROC __glewIsVertexArrayAPPLE = NULL; + +PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC __glewFlushVertexArrayRangeAPPLE = NULL; +PFNGLVERTEXARRAYPARAMETERIAPPLEPROC __glewVertexArrayParameteriAPPLE = NULL; +PFNGLVERTEXARRAYRANGEAPPLEPROC __glewVertexArrayRangeAPPLE = NULL; + +PFNGLDISABLEVERTEXATTRIBAPPLEPROC __glewDisableVertexAttribAPPLE = NULL; +PFNGLENABLEVERTEXATTRIBAPPLEPROC __glewEnableVertexAttribAPPLE = NULL; +PFNGLISVERTEXATTRIBENABLEDAPPLEPROC __glewIsVertexAttribEnabledAPPLE = NULL; +PFNGLMAPVERTEXATTRIB1DAPPLEPROC __glewMapVertexAttrib1dAPPLE = NULL; +PFNGLMAPVERTEXATTRIB1FAPPLEPROC __glewMapVertexAttrib1fAPPLE = NULL; +PFNGLMAPVERTEXATTRIB2DAPPLEPROC __glewMapVertexAttrib2dAPPLE = NULL; +PFNGLMAPVERTEXATTRIB2FAPPLEPROC __glewMapVertexAttrib2fAPPLE = NULL; + +PFNGLCLEARDEPTHFPROC __glewClearDepthf = NULL; +PFNGLDEPTHRANGEFPROC __glewDepthRangef = NULL; +PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat = NULL; +PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler = NULL; +PFNGLSHADERBINARYPROC __glewShaderBinary = NULL; + +PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed = NULL; +PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex = NULL; + +PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB = NULL; + +PFNGLCLAMPCOLORARBPROC __glewClampColorARB = NULL; + +PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData = NULL; + +PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB = NULL; +PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB = NULL; +PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB = NULL; +PFNGLGETDEBUGMESSAGELOGARBPROC __glewGetDebugMessageLogARB = NULL; + +PFNGLDRAWBUFFERSARBPROC __glewDrawBuffersARB = NULL; + +PFNGLBLENDEQUATIONSEPARATEIARBPROC __glewBlendEquationSeparateiARB = NULL; +PFNGLBLENDEQUATIONIARBPROC __glewBlendEquationiARB = NULL; +PFNGLBLENDFUNCSEPARATEIARBPROC __glewBlendFuncSeparateiARB = NULL; +PFNGLBLENDFUNCIARBPROC __glewBlendFunciARB = NULL; + +PFNGLDRAWELEMENTSBASEVERTEXPROC __glewDrawElementsBaseVertex = NULL; +PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC __glewDrawElementsInstancedBaseVertex = NULL; +PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC __glewDrawRangeElementsBaseVertex = NULL; +PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBaseVertex = NULL; + +PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect = NULL; +PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect = NULL; + +PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer = NULL; +PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer = NULL; +PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSPROC __glewCheckFramebufferStatus = NULL; +PFNGLDELETEFRAMEBUFFERSPROC __glewDeleteFramebuffers = NULL; +PFNGLDELETERENDERBUFFERSPROC __glewDeleteRenderbuffers = NULL; +PFNGLFRAMEBUFFERRENDERBUFFERPROC __glewFramebufferRenderbuffer = NULL; +PFNGLFRAMEBUFFERTEXTURE1DPROC __glewFramebufferTexture1D = NULL; +PFNGLFRAMEBUFFERTEXTURE2DPROC __glewFramebufferTexture2D = NULL; +PFNGLFRAMEBUFFERTEXTURE3DPROC __glewFramebufferTexture3D = NULL; +PFNGLFRAMEBUFFERTEXTURELAYERPROC __glewFramebufferTextureLayer = NULL; +PFNGLGENFRAMEBUFFERSPROC __glewGenFramebuffers = NULL; +PFNGLGENRENDERBUFFERSPROC __glewGenRenderbuffers = NULL; +PFNGLGENERATEMIPMAPPROC __glewGenerateMipmap = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC __glewGetFramebufferAttachmentParameteriv = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVPROC __glewGetRenderbufferParameteriv = NULL; +PFNGLISFRAMEBUFFERPROC __glewIsFramebuffer = NULL; +PFNGLISRENDERBUFFERPROC __glewIsRenderbuffer = NULL; +PFNGLRENDERBUFFERSTORAGEPROC __glewRenderbufferStorage = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC __glewRenderbufferStorageMultisample = NULL; + +PFNGLFRAMEBUFFERTEXTUREARBPROC __glewFramebufferTextureARB = NULL; +PFNGLFRAMEBUFFERTEXTUREFACEARBPROC __glewFramebufferTextureFaceARB = NULL; +PFNGLFRAMEBUFFERTEXTURELAYERARBPROC __glewFramebufferTextureLayerARB = NULL; +PFNGLPROGRAMPARAMETERIARBPROC __glewProgramParameteriARB = NULL; + +PFNGLGETPROGRAMBINARYPROC __glewGetProgramBinary = NULL; +PFNGLPROGRAMBINARYPROC __glewProgramBinary = NULL; +PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri = NULL; + +PFNGLGETUNIFORMDVPROC __glewGetUniformdv = NULL; +PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT = NULL; +PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT = NULL; +PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT = NULL; +PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT = NULL; +PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT = NULL; +PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT = NULL; +PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT = NULL; +PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT = NULL; +PFNGLUNIFORM1DPROC __glewUniform1d = NULL; +PFNGLUNIFORM1DVPROC __glewUniform1dv = NULL; +PFNGLUNIFORM2DPROC __glewUniform2d = NULL; +PFNGLUNIFORM2DVPROC __glewUniform2dv = NULL; +PFNGLUNIFORM3DPROC __glewUniform3d = NULL; +PFNGLUNIFORM3DVPROC __glewUniform3dv = NULL; +PFNGLUNIFORM4DPROC __glewUniform4d = NULL; +PFNGLUNIFORM4DVPROC __glewUniform4dv = NULL; +PFNGLUNIFORMMATRIX2DVPROC __glewUniformMatrix2dv = NULL; +PFNGLUNIFORMMATRIX2X3DVPROC __glewUniformMatrix2x3dv = NULL; +PFNGLUNIFORMMATRIX2X4DVPROC __glewUniformMatrix2x4dv = NULL; +PFNGLUNIFORMMATRIX3DVPROC __glewUniformMatrix3dv = NULL; +PFNGLUNIFORMMATRIX3X2DVPROC __glewUniformMatrix3x2dv = NULL; +PFNGLUNIFORMMATRIX3X4DVPROC __glewUniformMatrix3x4dv = NULL; +PFNGLUNIFORMMATRIX4DVPROC __glewUniformMatrix4dv = NULL; +PFNGLUNIFORMMATRIX4X2DVPROC __glewUniformMatrix4x2dv = NULL; +PFNGLUNIFORMMATRIX4X3DVPROC __glewUniformMatrix4x3dv = NULL; + +PFNGLCOLORSUBTABLEPROC __glewColorSubTable = NULL; +PFNGLCOLORTABLEPROC __glewColorTable = NULL; +PFNGLCOLORTABLEPARAMETERFVPROC __glewColorTableParameterfv = NULL; +PFNGLCOLORTABLEPARAMETERIVPROC __glewColorTableParameteriv = NULL; +PFNGLCONVOLUTIONFILTER1DPROC __glewConvolutionFilter1D = NULL; +PFNGLCONVOLUTIONFILTER2DPROC __glewConvolutionFilter2D = NULL; +PFNGLCONVOLUTIONPARAMETERFPROC __glewConvolutionParameterf = NULL; +PFNGLCONVOLUTIONPARAMETERFVPROC __glewConvolutionParameterfv = NULL; +PFNGLCONVOLUTIONPARAMETERIPROC __glewConvolutionParameteri = NULL; +PFNGLCONVOLUTIONPARAMETERIVPROC __glewConvolutionParameteriv = NULL; +PFNGLCOPYCOLORSUBTABLEPROC __glewCopyColorSubTable = NULL; +PFNGLCOPYCOLORTABLEPROC __glewCopyColorTable = NULL; +PFNGLCOPYCONVOLUTIONFILTER1DPROC __glewCopyConvolutionFilter1D = NULL; +PFNGLCOPYCONVOLUTIONFILTER2DPROC __glewCopyConvolutionFilter2D = NULL; +PFNGLGETCOLORTABLEPROC __glewGetColorTable = NULL; +PFNGLGETCOLORTABLEPARAMETERFVPROC __glewGetColorTableParameterfv = NULL; +PFNGLGETCOLORTABLEPARAMETERIVPROC __glewGetColorTableParameteriv = NULL; +PFNGLGETCONVOLUTIONFILTERPROC __glewGetConvolutionFilter = NULL; +PFNGLGETCONVOLUTIONPARAMETERFVPROC __glewGetConvolutionParameterfv = NULL; +PFNGLGETCONVOLUTIONPARAMETERIVPROC __glewGetConvolutionParameteriv = NULL; +PFNGLGETHISTOGRAMPROC __glewGetHistogram = NULL; +PFNGLGETHISTOGRAMPARAMETERFVPROC __glewGetHistogramParameterfv = NULL; +PFNGLGETHISTOGRAMPARAMETERIVPROC __glewGetHistogramParameteriv = NULL; +PFNGLGETMINMAXPROC __glewGetMinmax = NULL; +PFNGLGETMINMAXPARAMETERFVPROC __glewGetMinmaxParameterfv = NULL; +PFNGLGETMINMAXPARAMETERIVPROC __glewGetMinmaxParameteriv = NULL; +PFNGLGETSEPARABLEFILTERPROC __glewGetSeparableFilter = NULL; +PFNGLHISTOGRAMPROC __glewHistogram = NULL; +PFNGLMINMAXPROC __glewMinmax = NULL; +PFNGLRESETHISTOGRAMPROC __glewResetHistogram = NULL; +PFNGLRESETMINMAXPROC __glewResetMinmax = NULL; +PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D = NULL; + +PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB = NULL; +PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB = NULL; +PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB = NULL; + +PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange = NULL; +PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange = NULL; + +PFNGLCURRENTPALETTEMATRIXARBPROC __glewCurrentPaletteMatrixARB = NULL; +PFNGLMATRIXINDEXPOINTERARBPROC __glewMatrixIndexPointerARB = NULL; +PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB = NULL; +PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB = NULL; +PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB = NULL; + +PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB = NULL; + +PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB = NULL; +PFNGLCLIENTACTIVETEXTUREARBPROC __glewClientActiveTextureARB = NULL; +PFNGLMULTITEXCOORD1DARBPROC __glewMultiTexCoord1dARB = NULL; +PFNGLMULTITEXCOORD1DVARBPROC __glewMultiTexCoord1dvARB = NULL; +PFNGLMULTITEXCOORD1FARBPROC __glewMultiTexCoord1fARB = NULL; +PFNGLMULTITEXCOORD1FVARBPROC __glewMultiTexCoord1fvARB = NULL; +PFNGLMULTITEXCOORD1IARBPROC __glewMultiTexCoord1iARB = NULL; +PFNGLMULTITEXCOORD1IVARBPROC __glewMultiTexCoord1ivARB = NULL; +PFNGLMULTITEXCOORD1SARBPROC __glewMultiTexCoord1sARB = NULL; +PFNGLMULTITEXCOORD1SVARBPROC __glewMultiTexCoord1svARB = NULL; +PFNGLMULTITEXCOORD2DARBPROC __glewMultiTexCoord2dARB = NULL; +PFNGLMULTITEXCOORD2DVARBPROC __glewMultiTexCoord2dvARB = NULL; +PFNGLMULTITEXCOORD2FARBPROC __glewMultiTexCoord2fARB = NULL; +PFNGLMULTITEXCOORD2FVARBPROC __glewMultiTexCoord2fvARB = NULL; +PFNGLMULTITEXCOORD2IARBPROC __glewMultiTexCoord2iARB = NULL; +PFNGLMULTITEXCOORD2IVARBPROC __glewMultiTexCoord2ivARB = NULL; +PFNGLMULTITEXCOORD2SARBPROC __glewMultiTexCoord2sARB = NULL; +PFNGLMULTITEXCOORD2SVARBPROC __glewMultiTexCoord2svARB = NULL; +PFNGLMULTITEXCOORD3DARBPROC __glewMultiTexCoord3dARB = NULL; +PFNGLMULTITEXCOORD3DVARBPROC __glewMultiTexCoord3dvARB = NULL; +PFNGLMULTITEXCOORD3FARBPROC __glewMultiTexCoord3fARB = NULL; +PFNGLMULTITEXCOORD3FVARBPROC __glewMultiTexCoord3fvARB = NULL; +PFNGLMULTITEXCOORD3IARBPROC __glewMultiTexCoord3iARB = NULL; +PFNGLMULTITEXCOORD3IVARBPROC __glewMultiTexCoord3ivARB = NULL; +PFNGLMULTITEXCOORD3SARBPROC __glewMultiTexCoord3sARB = NULL; +PFNGLMULTITEXCOORD3SVARBPROC __glewMultiTexCoord3svARB = NULL; +PFNGLMULTITEXCOORD4DARBPROC __glewMultiTexCoord4dARB = NULL; +PFNGLMULTITEXCOORD4DVARBPROC __glewMultiTexCoord4dvARB = NULL; +PFNGLMULTITEXCOORD4FARBPROC __glewMultiTexCoord4fARB = NULL; +PFNGLMULTITEXCOORD4FVARBPROC __glewMultiTexCoord4fvARB = NULL; +PFNGLMULTITEXCOORD4IARBPROC __glewMultiTexCoord4iARB = NULL; +PFNGLMULTITEXCOORD4IVARBPROC __glewMultiTexCoord4ivARB = NULL; +PFNGLMULTITEXCOORD4SARBPROC __glewMultiTexCoord4sARB = NULL; +PFNGLMULTITEXCOORD4SVARBPROC __glewMultiTexCoord4svARB = NULL; + +PFNGLBEGINQUERYARBPROC __glewBeginQueryARB = NULL; +PFNGLDELETEQUERIESARBPROC __glewDeleteQueriesARB = NULL; +PFNGLENDQUERYARBPROC __glewEndQueryARB = NULL; +PFNGLGENQUERIESARBPROC __glewGenQueriesARB = NULL; +PFNGLGETQUERYOBJECTIVARBPROC __glewGetQueryObjectivARB = NULL; +PFNGLGETQUERYOBJECTUIVARBPROC __glewGetQueryObjectuivARB = NULL; +PFNGLGETQUERYIVARBPROC __glewGetQueryivARB = NULL; +PFNGLISQUERYARBPROC __glewIsQueryARB = NULL; + +PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB = NULL; +PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB = NULL; + +PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex = NULL; + +PFNGLGETNCOLORTABLEARBPROC __glewGetnColorTableARB = NULL; +PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC __glewGetnCompressedTexImageARB = NULL; +PFNGLGETNCONVOLUTIONFILTERARBPROC __glewGetnConvolutionFilterARB = NULL; +PFNGLGETNHISTOGRAMARBPROC __glewGetnHistogramARB = NULL; +PFNGLGETNMAPDVARBPROC __glewGetnMapdvARB = NULL; +PFNGLGETNMAPFVARBPROC __glewGetnMapfvARB = NULL; +PFNGLGETNMAPIVARBPROC __glewGetnMapivARB = NULL; +PFNGLGETNMINMAXARBPROC __glewGetnMinmaxARB = NULL; +PFNGLGETNPIXELMAPFVARBPROC __glewGetnPixelMapfvARB = NULL; +PFNGLGETNPIXELMAPUIVARBPROC __glewGetnPixelMapuivARB = NULL; +PFNGLGETNPIXELMAPUSVARBPROC __glewGetnPixelMapusvARB = NULL; +PFNGLGETNPOLYGONSTIPPLEARBPROC __glewGetnPolygonStippleARB = NULL; +PFNGLGETNSEPARABLEFILTERARBPROC __glewGetnSeparableFilterARB = NULL; +PFNGLGETNTEXIMAGEARBPROC __glewGetnTexImageARB = NULL; +PFNGLGETNUNIFORMDVARBPROC __glewGetnUniformdvARB = NULL; +PFNGLGETNUNIFORMFVARBPROC __glewGetnUniformfvARB = NULL; +PFNGLGETNUNIFORMIVARBPROC __glewGetnUniformivARB = NULL; +PFNGLGETNUNIFORMUIVARBPROC __glewGetnUniformuivARB = NULL; +PFNGLREADNPIXELSARBPROC __glewReadnPixelsARB = NULL; + +PFNGLMINSAMPLESHADINGARBPROC __glewMinSampleShadingARB = NULL; + +PFNGLBINDSAMPLERPROC __glewBindSampler = NULL; +PFNGLDELETESAMPLERSPROC __glewDeleteSamplers = NULL; +PFNGLGENSAMPLERSPROC __glewGenSamplers = NULL; +PFNGLGETSAMPLERPARAMETERIIVPROC __glewGetSamplerParameterIiv = NULL; +PFNGLGETSAMPLERPARAMETERIUIVPROC __glewGetSamplerParameterIuiv = NULL; +PFNGLGETSAMPLERPARAMETERFVPROC __glewGetSamplerParameterfv = NULL; +PFNGLGETSAMPLERPARAMETERIVPROC __glewGetSamplerParameteriv = NULL; +PFNGLISSAMPLERPROC __glewIsSampler = NULL; +PFNGLSAMPLERPARAMETERIIVPROC __glewSamplerParameterIiv = NULL; +PFNGLSAMPLERPARAMETERIUIVPROC __glewSamplerParameterIuiv = NULL; +PFNGLSAMPLERPARAMETERFPROC __glewSamplerParameterf = NULL; +PFNGLSAMPLERPARAMETERFVPROC __glewSamplerParameterfv = NULL; +PFNGLSAMPLERPARAMETERIPROC __glewSamplerParameteri = NULL; +PFNGLSAMPLERPARAMETERIVPROC __glewSamplerParameteriv = NULL; + +PFNGLACTIVESHADERPROGRAMPROC __glewActiveShaderProgram = NULL; +PFNGLBINDPROGRAMPIPELINEPROC __glewBindProgramPipeline = NULL; +PFNGLCREATESHADERPROGRAMVPROC __glewCreateShaderProgramv = NULL; +PFNGLDELETEPROGRAMPIPELINESPROC __glewDeleteProgramPipelines = NULL; +PFNGLGENPROGRAMPIPELINESPROC __glewGenProgramPipelines = NULL; +PFNGLGETPROGRAMPIPELINEINFOLOGPROC __glewGetProgramPipelineInfoLog = NULL; +PFNGLGETPROGRAMPIPELINEIVPROC __glewGetProgramPipelineiv = NULL; +PFNGLISPROGRAMPIPELINEPROC __glewIsProgramPipeline = NULL; +PFNGLPROGRAMUNIFORM1DPROC __glewProgramUniform1d = NULL; +PFNGLPROGRAMUNIFORM1DVPROC __glewProgramUniform1dv = NULL; +PFNGLPROGRAMUNIFORM1FPROC __glewProgramUniform1f = NULL; +PFNGLPROGRAMUNIFORM1FVPROC __glewProgramUniform1fv = NULL; +PFNGLPROGRAMUNIFORM1IPROC __glewProgramUniform1i = NULL; +PFNGLPROGRAMUNIFORM1IVPROC __glewProgramUniform1iv = NULL; +PFNGLPROGRAMUNIFORM1UIPROC __glewProgramUniform1ui = NULL; +PFNGLPROGRAMUNIFORM1UIVPROC __glewProgramUniform1uiv = NULL; +PFNGLPROGRAMUNIFORM2DPROC __glewProgramUniform2d = NULL; +PFNGLPROGRAMUNIFORM2DVPROC __glewProgramUniform2dv = NULL; +PFNGLPROGRAMUNIFORM2FPROC __glewProgramUniform2f = NULL; +PFNGLPROGRAMUNIFORM2FVPROC __glewProgramUniform2fv = NULL; +PFNGLPROGRAMUNIFORM2IPROC __glewProgramUniform2i = NULL; +PFNGLPROGRAMUNIFORM2IVPROC __glewProgramUniform2iv = NULL; +PFNGLPROGRAMUNIFORM2UIPROC __glewProgramUniform2ui = NULL; +PFNGLPROGRAMUNIFORM2UIVPROC __glewProgramUniform2uiv = NULL; +PFNGLPROGRAMUNIFORM3DPROC __glewProgramUniform3d = NULL; +PFNGLPROGRAMUNIFORM3DVPROC __glewProgramUniform3dv = NULL; +PFNGLPROGRAMUNIFORM3FPROC __glewProgramUniform3f = NULL; +PFNGLPROGRAMUNIFORM3FVPROC __glewProgramUniform3fv = NULL; +PFNGLPROGRAMUNIFORM3IPROC __glewProgramUniform3i = NULL; +PFNGLPROGRAMUNIFORM3IVPROC __glewProgramUniform3iv = NULL; +PFNGLPROGRAMUNIFORM3UIPROC __glewProgramUniform3ui = NULL; +PFNGLPROGRAMUNIFORM3UIVPROC __glewProgramUniform3uiv = NULL; +PFNGLPROGRAMUNIFORM4DPROC __glewProgramUniform4d = NULL; +PFNGLPROGRAMUNIFORM4DVPROC __glewProgramUniform4dv = NULL; +PFNGLPROGRAMUNIFORM4FPROC __glewProgramUniform4f = NULL; +PFNGLPROGRAMUNIFORM4FVPROC __glewProgramUniform4fv = NULL; +PFNGLPROGRAMUNIFORM4IPROC __glewProgramUniform4i = NULL; +PFNGLPROGRAMUNIFORM4IVPROC __glewProgramUniform4iv = NULL; +PFNGLPROGRAMUNIFORM4UIPROC __glewProgramUniform4ui = NULL; +PFNGLPROGRAMUNIFORM4UIVPROC __glewProgramUniform4uiv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2DVPROC __glewProgramUniformMatrix2dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2FVPROC __glewProgramUniformMatrix2fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC __glewProgramUniformMatrix2x3dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC __glewProgramUniformMatrix2x3fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC __glewProgramUniformMatrix2x4dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC __glewProgramUniformMatrix2x4fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3DVPROC __glewProgramUniformMatrix3dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3FVPROC __glewProgramUniformMatrix3fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC __glewProgramUniformMatrix3x2dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC __glewProgramUniformMatrix3x2fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC __glewProgramUniformMatrix3x4dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC __glewProgramUniformMatrix3x4fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4DVPROC __glewProgramUniformMatrix4dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4FVPROC __glewProgramUniformMatrix4fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC __glewProgramUniformMatrix4x2dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC __glewProgramUniformMatrix4x2fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC __glewProgramUniformMatrix4x3dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC __glewProgramUniformMatrix4x3fv = NULL; +PFNGLUSEPROGRAMSTAGESPROC __glewUseProgramStages = NULL; +PFNGLVALIDATEPROGRAMPIPELINEPROC __glewValidateProgramPipeline = NULL; + +PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB = NULL; +PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB = NULL; +PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB = NULL; +PFNGLCREATESHADEROBJECTARBPROC __glewCreateShaderObjectARB = NULL; +PFNGLDELETEOBJECTARBPROC __glewDeleteObjectARB = NULL; +PFNGLDETACHOBJECTARBPROC __glewDetachObjectARB = NULL; +PFNGLGETACTIVEUNIFORMARBPROC __glewGetActiveUniformARB = NULL; +PFNGLGETATTACHEDOBJECTSARBPROC __glewGetAttachedObjectsARB = NULL; +PFNGLGETHANDLEARBPROC __glewGetHandleARB = NULL; +PFNGLGETINFOLOGARBPROC __glewGetInfoLogARB = NULL; +PFNGLGETOBJECTPARAMETERFVARBPROC __glewGetObjectParameterfvARB = NULL; +PFNGLGETOBJECTPARAMETERIVARBPROC __glewGetObjectParameterivARB = NULL; +PFNGLGETSHADERSOURCEARBPROC __glewGetShaderSourceARB = NULL; +PFNGLGETUNIFORMLOCATIONARBPROC __glewGetUniformLocationARB = NULL; +PFNGLGETUNIFORMFVARBPROC __glewGetUniformfvARB = NULL; +PFNGLGETUNIFORMIVARBPROC __glewGetUniformivARB = NULL; +PFNGLLINKPROGRAMARBPROC __glewLinkProgramARB = NULL; +PFNGLSHADERSOURCEARBPROC __glewShaderSourceARB = NULL; +PFNGLUNIFORM1FARBPROC __glewUniform1fARB = NULL; +PFNGLUNIFORM1FVARBPROC __glewUniform1fvARB = NULL; +PFNGLUNIFORM1IARBPROC __glewUniform1iARB = NULL; +PFNGLUNIFORM1IVARBPROC __glewUniform1ivARB = NULL; +PFNGLUNIFORM2FARBPROC __glewUniform2fARB = NULL; +PFNGLUNIFORM2FVARBPROC __glewUniform2fvARB = NULL; +PFNGLUNIFORM2IARBPROC __glewUniform2iARB = NULL; +PFNGLUNIFORM2IVARBPROC __glewUniform2ivARB = NULL; +PFNGLUNIFORM3FARBPROC __glewUniform3fARB = NULL; +PFNGLUNIFORM3FVARBPROC __glewUniform3fvARB = NULL; +PFNGLUNIFORM3IARBPROC __glewUniform3iARB = NULL; +PFNGLUNIFORM3IVARBPROC __glewUniform3ivARB = NULL; +PFNGLUNIFORM4FARBPROC __glewUniform4fARB = NULL; +PFNGLUNIFORM4FVARBPROC __glewUniform4fvARB = NULL; +PFNGLUNIFORM4IARBPROC __glewUniform4iARB = NULL; +PFNGLUNIFORM4IVARBPROC __glewUniform4ivARB = NULL; +PFNGLUNIFORMMATRIX2FVARBPROC __glewUniformMatrix2fvARB = NULL; +PFNGLUNIFORMMATRIX3FVARBPROC __glewUniformMatrix3fvARB = NULL; +PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB = NULL; +PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB = NULL; +PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB = NULL; + +PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName = NULL; +PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName = NULL; +PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv = NULL; +PFNGLGETPROGRAMSTAGEIVPROC __glewGetProgramStageiv = NULL; +PFNGLGETSUBROUTINEINDEXPROC __glewGetSubroutineIndex = NULL; +PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC __glewGetSubroutineUniformLocation = NULL; +PFNGLGETUNIFORMSUBROUTINEUIVPROC __glewGetUniformSubroutineuiv = NULL; +PFNGLUNIFORMSUBROUTINESUIVPROC __glewUniformSubroutinesuiv = NULL; + +PFNGLCOMPILESHADERINCLUDEARBPROC __glewCompileShaderIncludeARB = NULL; +PFNGLDELETENAMEDSTRINGARBPROC __glewDeleteNamedStringARB = NULL; +PFNGLGETNAMEDSTRINGARBPROC __glewGetNamedStringARB = NULL; +PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB = NULL; +PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB = NULL; +PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB = NULL; + +PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync = NULL; +PFNGLDELETESYNCPROC __glewDeleteSync = NULL; +PFNGLFENCESYNCPROC __glewFenceSync = NULL; +PFNGLGETINTEGER64VPROC __glewGetInteger64v = NULL; +PFNGLGETSYNCIVPROC __glewGetSynciv = NULL; +PFNGLISSYNCPROC __glewIsSync = NULL; +PFNGLWAITSYNCPROC __glewWaitSync = NULL; + +PFNGLPATCHPARAMETERFVPROC __glewPatchParameterfv = NULL; +PFNGLPATCHPARAMETERIPROC __glewPatchParameteri = NULL; + +PFNGLTEXBUFFERARBPROC __glewTexBufferARB = NULL; + +PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB = NULL; +PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB = NULL; +PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC __glewCompressedTexSubImage1DARB = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC __glewCompressedTexSubImage2DARB = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC __glewCompressedTexSubImage3DARB = NULL; +PFNGLGETCOMPRESSEDTEXIMAGEARBPROC __glewGetCompressedTexImageARB = NULL; + +PFNGLGETMULTISAMPLEFVPROC __glewGetMultisamplefv = NULL; +PFNGLSAMPLEMASKIPROC __glewSampleMaski = NULL; +PFNGLTEXIMAGE2DMULTISAMPLEPROC __glewTexImage2DMultisample = NULL; +PFNGLTEXIMAGE3DMULTISAMPLEPROC __glewTexImage3DMultisample = NULL; + +PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v = NULL; +PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v = NULL; +PFNGLQUERYCOUNTERPROC __glewQueryCounter = NULL; + +PFNGLBINDTRANSFORMFEEDBACKPROC __glewBindTransformFeedback = NULL; +PFNGLDELETETRANSFORMFEEDBACKSPROC __glewDeleteTransformFeedbacks = NULL; +PFNGLDRAWTRANSFORMFEEDBACKPROC __glewDrawTransformFeedback = NULL; +PFNGLGENTRANSFORMFEEDBACKSPROC __glewGenTransformFeedbacks = NULL; +PFNGLISTRANSFORMFEEDBACKPROC __glewIsTransformFeedback = NULL; +PFNGLPAUSETRANSFORMFEEDBACKPROC __glewPauseTransformFeedback = NULL; +PFNGLRESUMETRANSFORMFEEDBACKPROC __glewResumeTransformFeedback = NULL; + +PFNGLBEGINQUERYINDEXEDPROC __glewBeginQueryIndexed = NULL; +PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC __glewDrawTransformFeedbackStream = NULL; +PFNGLENDQUERYINDEXEDPROC __glewEndQueryIndexed = NULL; +PFNGLGETQUERYINDEXEDIVPROC __glewGetQueryIndexediv = NULL; + +PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB = NULL; +PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB = NULL; +PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB = NULL; +PFNGLMULTTRANSPOSEMATRIXFARBPROC __glewMultTransposeMatrixfARB = NULL; + +PFNGLBINDBUFFERBASEPROC __glewBindBufferBase = NULL; +PFNGLBINDBUFFERRANGEPROC __glewBindBufferRange = NULL; +PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC __glewGetActiveUniformBlockName = NULL; +PFNGLGETACTIVEUNIFORMBLOCKIVPROC __glewGetActiveUniformBlockiv = NULL; +PFNGLGETACTIVEUNIFORMNAMEPROC __glewGetActiveUniformName = NULL; +PFNGLGETACTIVEUNIFORMSIVPROC __glewGetActiveUniformsiv = NULL; +PFNGLGETINTEGERI_VPROC __glewGetIntegeri_v = NULL; +PFNGLGETUNIFORMBLOCKINDEXPROC __glewGetUniformBlockIndex = NULL; +PFNGLGETUNIFORMINDICESPROC __glewGetUniformIndices = NULL; +PFNGLUNIFORMBLOCKBINDINGPROC __glewUniformBlockBinding = NULL; + +PFNGLBINDVERTEXARRAYPROC __glewBindVertexArray = NULL; +PFNGLDELETEVERTEXARRAYSPROC __glewDeleteVertexArrays = NULL; +PFNGLGENVERTEXARRAYSPROC __glewGenVertexArrays = NULL; +PFNGLISVERTEXARRAYPROC __glewIsVertexArray = NULL; + +PFNGLGETVERTEXATTRIBLDVPROC __glewGetVertexAttribLdv = NULL; +PFNGLVERTEXATTRIBL1DPROC __glewVertexAttribL1d = NULL; +PFNGLVERTEXATTRIBL1DVPROC __glewVertexAttribL1dv = NULL; +PFNGLVERTEXATTRIBL2DPROC __glewVertexAttribL2d = NULL; +PFNGLVERTEXATTRIBL2DVPROC __glewVertexAttribL2dv = NULL; +PFNGLVERTEXATTRIBL3DPROC __glewVertexAttribL3d = NULL; +PFNGLVERTEXATTRIBL3DVPROC __glewVertexAttribL3dv = NULL; +PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d = NULL; +PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv = NULL; +PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer = NULL; + +PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB = NULL; +PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB = NULL; +PFNGLWEIGHTBVARBPROC __glewWeightbvARB = NULL; +PFNGLWEIGHTDVARBPROC __glewWeightdvARB = NULL; +PFNGLWEIGHTFVARBPROC __glewWeightfvARB = NULL; +PFNGLWEIGHTIVARBPROC __glewWeightivARB = NULL; +PFNGLWEIGHTSVARBPROC __glewWeightsvARB = NULL; +PFNGLWEIGHTUBVARBPROC __glewWeightubvARB = NULL; +PFNGLWEIGHTUIVARBPROC __glewWeightuivARB = NULL; +PFNGLWEIGHTUSVARBPROC __glewWeightusvARB = NULL; + +PFNGLBINDBUFFERARBPROC __glewBindBufferARB = NULL; +PFNGLBUFFERDATAARBPROC __glewBufferDataARB = NULL; +PFNGLBUFFERSUBDATAARBPROC __glewBufferSubDataARB = NULL; +PFNGLDELETEBUFFERSARBPROC __glewDeleteBuffersARB = NULL; +PFNGLGENBUFFERSARBPROC __glewGenBuffersARB = NULL; +PFNGLGETBUFFERPARAMETERIVARBPROC __glewGetBufferParameterivARB = NULL; +PFNGLGETBUFFERPOINTERVARBPROC __glewGetBufferPointervARB = NULL; +PFNGLGETBUFFERSUBDATAARBPROC __glewGetBufferSubDataARB = NULL; +PFNGLISBUFFERARBPROC __glewIsBufferARB = NULL; +PFNGLMAPBUFFERARBPROC __glewMapBufferARB = NULL; +PFNGLUNMAPBUFFERARBPROC __glewUnmapBufferARB = NULL; + +PFNGLBINDPROGRAMARBPROC __glewBindProgramARB = NULL; +PFNGLDELETEPROGRAMSARBPROC __glewDeleteProgramsARB = NULL; +PFNGLDISABLEVERTEXATTRIBARRAYARBPROC __glewDisableVertexAttribArrayARB = NULL; +PFNGLENABLEVERTEXATTRIBARRAYARBPROC __glewEnableVertexAttribArrayARB = NULL; +PFNGLGENPROGRAMSARBPROC __glewGenProgramsARB = NULL; +PFNGLGETPROGRAMENVPARAMETERDVARBPROC __glewGetProgramEnvParameterdvARB = NULL; +PFNGLGETPROGRAMENVPARAMETERFVARBPROC __glewGetProgramEnvParameterfvARB = NULL; +PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC __glewGetProgramLocalParameterdvARB = NULL; +PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC __glewGetProgramLocalParameterfvARB = NULL; +PFNGLGETPROGRAMSTRINGARBPROC __glewGetProgramStringARB = NULL; +PFNGLGETPROGRAMIVARBPROC __glewGetProgramivARB = NULL; +PFNGLGETVERTEXATTRIBPOINTERVARBPROC __glewGetVertexAttribPointervARB = NULL; +PFNGLGETVERTEXATTRIBDVARBPROC __glewGetVertexAttribdvARB = NULL; +PFNGLGETVERTEXATTRIBFVARBPROC __glewGetVertexAttribfvARB = NULL; +PFNGLGETVERTEXATTRIBIVARBPROC __glewGetVertexAttribivARB = NULL; +PFNGLISPROGRAMARBPROC __glewIsProgramARB = NULL; +PFNGLPROGRAMENVPARAMETER4DARBPROC __glewProgramEnvParameter4dARB = NULL; +PFNGLPROGRAMENVPARAMETER4DVARBPROC __glewProgramEnvParameter4dvARB = NULL; +PFNGLPROGRAMENVPARAMETER4FARBPROC __glewProgramEnvParameter4fARB = NULL; +PFNGLPROGRAMENVPARAMETER4FVARBPROC __glewProgramEnvParameter4fvARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4DARBPROC __glewProgramLocalParameter4dARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4DVARBPROC __glewProgramLocalParameter4dvARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4FARBPROC __glewProgramLocalParameter4fARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4FVARBPROC __glewProgramLocalParameter4fvARB = NULL; +PFNGLPROGRAMSTRINGARBPROC __glewProgramStringARB = NULL; +PFNGLVERTEXATTRIB1DARBPROC __glewVertexAttrib1dARB = NULL; +PFNGLVERTEXATTRIB1DVARBPROC __glewVertexAttrib1dvARB = NULL; +PFNGLVERTEXATTRIB1FARBPROC __glewVertexAttrib1fARB = NULL; +PFNGLVERTEXATTRIB1FVARBPROC __glewVertexAttrib1fvARB = NULL; +PFNGLVERTEXATTRIB1SARBPROC __glewVertexAttrib1sARB = NULL; +PFNGLVERTEXATTRIB1SVARBPROC __glewVertexAttrib1svARB = NULL; +PFNGLVERTEXATTRIB2DARBPROC __glewVertexAttrib2dARB = NULL; +PFNGLVERTEXATTRIB2DVARBPROC __glewVertexAttrib2dvARB = NULL; +PFNGLVERTEXATTRIB2FARBPROC __glewVertexAttrib2fARB = NULL; +PFNGLVERTEXATTRIB2FVARBPROC __glewVertexAttrib2fvARB = NULL; +PFNGLVERTEXATTRIB2SARBPROC __glewVertexAttrib2sARB = NULL; +PFNGLVERTEXATTRIB2SVARBPROC __glewVertexAttrib2svARB = NULL; +PFNGLVERTEXATTRIB3DARBPROC __glewVertexAttrib3dARB = NULL; +PFNGLVERTEXATTRIB3DVARBPROC __glewVertexAttrib3dvARB = NULL; +PFNGLVERTEXATTRIB3FARBPROC __glewVertexAttrib3fARB = NULL; +PFNGLVERTEXATTRIB3FVARBPROC __glewVertexAttrib3fvARB = NULL; +PFNGLVERTEXATTRIB3SARBPROC __glewVertexAttrib3sARB = NULL; +PFNGLVERTEXATTRIB3SVARBPROC __glewVertexAttrib3svARB = NULL; +PFNGLVERTEXATTRIB4NBVARBPROC __glewVertexAttrib4NbvARB = NULL; +PFNGLVERTEXATTRIB4NIVARBPROC __glewVertexAttrib4NivARB = NULL; +PFNGLVERTEXATTRIB4NSVARBPROC __glewVertexAttrib4NsvARB = NULL; +PFNGLVERTEXATTRIB4NUBARBPROC __glewVertexAttrib4NubARB = NULL; +PFNGLVERTEXATTRIB4NUBVARBPROC __glewVertexAttrib4NubvARB = NULL; +PFNGLVERTEXATTRIB4NUIVARBPROC __glewVertexAttrib4NuivARB = NULL; +PFNGLVERTEXATTRIB4NUSVARBPROC __glewVertexAttrib4NusvARB = NULL; +PFNGLVERTEXATTRIB4BVARBPROC __glewVertexAttrib4bvARB = NULL; +PFNGLVERTEXATTRIB4DARBPROC __glewVertexAttrib4dARB = NULL; +PFNGLVERTEXATTRIB4DVARBPROC __glewVertexAttrib4dvARB = NULL; +PFNGLVERTEXATTRIB4FARBPROC __glewVertexAttrib4fARB = NULL; +PFNGLVERTEXATTRIB4FVARBPROC __glewVertexAttrib4fvARB = NULL; +PFNGLVERTEXATTRIB4IVARBPROC __glewVertexAttrib4ivARB = NULL; +PFNGLVERTEXATTRIB4SARBPROC __glewVertexAttrib4sARB = NULL; +PFNGLVERTEXATTRIB4SVARBPROC __glewVertexAttrib4svARB = NULL; +PFNGLVERTEXATTRIB4UBVARBPROC __glewVertexAttrib4ubvARB = NULL; +PFNGLVERTEXATTRIB4UIVARBPROC __glewVertexAttrib4uivARB = NULL; +PFNGLVERTEXATTRIB4USVARBPROC __glewVertexAttrib4usvARB = NULL; +PFNGLVERTEXATTRIBPOINTERARBPROC __glewVertexAttribPointerARB = NULL; + +PFNGLBINDATTRIBLOCATIONARBPROC __glewBindAttribLocationARB = NULL; +PFNGLGETACTIVEATTRIBARBPROC __glewGetActiveAttribARB = NULL; +PFNGLGETATTRIBLOCATIONARBPROC __glewGetAttribLocationARB = NULL; + +PFNGLCOLORP3UIPROC __glewColorP3ui = NULL; +PFNGLCOLORP3UIVPROC __glewColorP3uiv = NULL; +PFNGLCOLORP4UIPROC __glewColorP4ui = NULL; +PFNGLCOLORP4UIVPROC __glewColorP4uiv = NULL; +PFNGLMULTITEXCOORDP1UIPROC __glewMultiTexCoordP1ui = NULL; +PFNGLMULTITEXCOORDP1UIVPROC __glewMultiTexCoordP1uiv = NULL; +PFNGLMULTITEXCOORDP2UIPROC __glewMultiTexCoordP2ui = NULL; +PFNGLMULTITEXCOORDP2UIVPROC __glewMultiTexCoordP2uiv = NULL; +PFNGLMULTITEXCOORDP3UIPROC __glewMultiTexCoordP3ui = NULL; +PFNGLMULTITEXCOORDP3UIVPROC __glewMultiTexCoordP3uiv = NULL; +PFNGLMULTITEXCOORDP4UIPROC __glewMultiTexCoordP4ui = NULL; +PFNGLMULTITEXCOORDP4UIVPROC __glewMultiTexCoordP4uiv = NULL; +PFNGLNORMALP3UIPROC __glewNormalP3ui = NULL; +PFNGLNORMALP3UIVPROC __glewNormalP3uiv = NULL; +PFNGLSECONDARYCOLORP3UIPROC __glewSecondaryColorP3ui = NULL; +PFNGLSECONDARYCOLORP3UIVPROC __glewSecondaryColorP3uiv = NULL; +PFNGLTEXCOORDP1UIPROC __glewTexCoordP1ui = NULL; +PFNGLTEXCOORDP1UIVPROC __glewTexCoordP1uiv = NULL; +PFNGLTEXCOORDP2UIPROC __glewTexCoordP2ui = NULL; +PFNGLTEXCOORDP2UIVPROC __glewTexCoordP2uiv = NULL; +PFNGLTEXCOORDP3UIPROC __glewTexCoordP3ui = NULL; +PFNGLTEXCOORDP3UIVPROC __glewTexCoordP3uiv = NULL; +PFNGLTEXCOORDP4UIPROC __glewTexCoordP4ui = NULL; +PFNGLTEXCOORDP4UIVPROC __glewTexCoordP4uiv = NULL; +PFNGLVERTEXATTRIBP1UIPROC __glewVertexAttribP1ui = NULL; +PFNGLVERTEXATTRIBP1UIVPROC __glewVertexAttribP1uiv = NULL; +PFNGLVERTEXATTRIBP2UIPROC __glewVertexAttribP2ui = NULL; +PFNGLVERTEXATTRIBP2UIVPROC __glewVertexAttribP2uiv = NULL; +PFNGLVERTEXATTRIBP3UIPROC __glewVertexAttribP3ui = NULL; +PFNGLVERTEXATTRIBP3UIVPROC __glewVertexAttribP3uiv = NULL; +PFNGLVERTEXATTRIBP4UIPROC __glewVertexAttribP4ui = NULL; +PFNGLVERTEXATTRIBP4UIVPROC __glewVertexAttribP4uiv = NULL; +PFNGLVERTEXP2UIPROC __glewVertexP2ui = NULL; +PFNGLVERTEXP2UIVPROC __glewVertexP2uiv = NULL; +PFNGLVERTEXP3UIPROC __glewVertexP3ui = NULL; +PFNGLVERTEXP3UIVPROC __glewVertexP3uiv = NULL; +PFNGLVERTEXP4UIPROC __glewVertexP4ui = NULL; +PFNGLVERTEXP4UIVPROC __glewVertexP4uiv = NULL; + +PFNGLDEPTHRANGEARRAYVPROC __glewDepthRangeArrayv = NULL; +PFNGLDEPTHRANGEINDEXEDPROC __glewDepthRangeIndexed = NULL; +PFNGLGETDOUBLEI_VPROC __glewGetDoublei_v = NULL; +PFNGLGETFLOATI_VPROC __glewGetFloati_v = NULL; +PFNGLSCISSORARRAYVPROC __glewScissorArrayv = NULL; +PFNGLSCISSORINDEXEDPROC __glewScissorIndexed = NULL; +PFNGLSCISSORINDEXEDVPROC __glewScissorIndexedv = NULL; +PFNGLVIEWPORTARRAYVPROC __glewViewportArrayv = NULL; +PFNGLVIEWPORTINDEXEDFPROC __glewViewportIndexedf = NULL; +PFNGLVIEWPORTINDEXEDFVPROC __glewViewportIndexedfv = NULL; + +PFNGLWINDOWPOS2DARBPROC __glewWindowPos2dARB = NULL; +PFNGLWINDOWPOS2DVARBPROC __glewWindowPos2dvARB = NULL; +PFNGLWINDOWPOS2FARBPROC __glewWindowPos2fARB = NULL; +PFNGLWINDOWPOS2FVARBPROC __glewWindowPos2fvARB = NULL; +PFNGLWINDOWPOS2IARBPROC __glewWindowPos2iARB = NULL; +PFNGLWINDOWPOS2IVARBPROC __glewWindowPos2ivARB = NULL; +PFNGLWINDOWPOS2SARBPROC __glewWindowPos2sARB = NULL; +PFNGLWINDOWPOS2SVARBPROC __glewWindowPos2svARB = NULL; +PFNGLWINDOWPOS3DARBPROC __glewWindowPos3dARB = NULL; +PFNGLWINDOWPOS3DVARBPROC __glewWindowPos3dvARB = NULL; +PFNGLWINDOWPOS3FARBPROC __glewWindowPos3fARB = NULL; +PFNGLWINDOWPOS3FVARBPROC __glewWindowPos3fvARB = NULL; +PFNGLWINDOWPOS3IARBPROC __glewWindowPos3iARB = NULL; +PFNGLWINDOWPOS3IVARBPROC __glewWindowPos3ivARB = NULL; +PFNGLWINDOWPOS3SARBPROC __glewWindowPos3sARB = NULL; +PFNGLWINDOWPOS3SVARBPROC __glewWindowPos3svARB = NULL; + +PFNGLDRAWBUFFERSATIPROC __glewDrawBuffersATI = NULL; + +PFNGLDRAWELEMENTARRAYATIPROC __glewDrawElementArrayATI = NULL; +PFNGLDRAWRANGEELEMENTARRAYATIPROC __glewDrawRangeElementArrayATI = NULL; +PFNGLELEMENTPOINTERATIPROC __glewElementPointerATI = NULL; + +PFNGLGETTEXBUMPPARAMETERFVATIPROC __glewGetTexBumpParameterfvATI = NULL; +PFNGLGETTEXBUMPPARAMETERIVATIPROC __glewGetTexBumpParameterivATI = NULL; +PFNGLTEXBUMPPARAMETERFVATIPROC __glewTexBumpParameterfvATI = NULL; +PFNGLTEXBUMPPARAMETERIVATIPROC __glewTexBumpParameterivATI = NULL; + +PFNGLALPHAFRAGMENTOP1ATIPROC __glewAlphaFragmentOp1ATI = NULL; +PFNGLALPHAFRAGMENTOP2ATIPROC __glewAlphaFragmentOp2ATI = NULL; +PFNGLALPHAFRAGMENTOP3ATIPROC __glewAlphaFragmentOp3ATI = NULL; +PFNGLBEGINFRAGMENTSHADERATIPROC __glewBeginFragmentShaderATI = NULL; +PFNGLBINDFRAGMENTSHADERATIPROC __glewBindFragmentShaderATI = NULL; +PFNGLCOLORFRAGMENTOP1ATIPROC __glewColorFragmentOp1ATI = NULL; +PFNGLCOLORFRAGMENTOP2ATIPROC __glewColorFragmentOp2ATI = NULL; +PFNGLCOLORFRAGMENTOP3ATIPROC __glewColorFragmentOp3ATI = NULL; +PFNGLDELETEFRAGMENTSHADERATIPROC __glewDeleteFragmentShaderATI = NULL; +PFNGLENDFRAGMENTSHADERATIPROC __glewEndFragmentShaderATI = NULL; +PFNGLGENFRAGMENTSHADERSATIPROC __glewGenFragmentShadersATI = NULL; +PFNGLPASSTEXCOORDATIPROC __glewPassTexCoordATI = NULL; +PFNGLSAMPLEMAPATIPROC __glewSampleMapATI = NULL; +PFNGLSETFRAGMENTSHADERCONSTANTATIPROC __glewSetFragmentShaderConstantATI = NULL; + +PFNGLMAPOBJECTBUFFERATIPROC __glewMapObjectBufferATI = NULL; +PFNGLUNMAPOBJECTBUFFERATIPROC __glewUnmapObjectBufferATI = NULL; + +PFNGLPNTRIANGLESFATIPROC __glewPNTrianglesfATI = NULL; +PFNGLPNTRIANGLESIATIPROC __glewPNTrianglesiATI = NULL; + +PFNGLSTENCILFUNCSEPARATEATIPROC __glewStencilFuncSeparateATI = NULL; +PFNGLSTENCILOPSEPARATEATIPROC __glewStencilOpSeparateATI = NULL; + +PFNGLARRAYOBJECTATIPROC __glewArrayObjectATI = NULL; +PFNGLFREEOBJECTBUFFERATIPROC __glewFreeObjectBufferATI = NULL; +PFNGLGETARRAYOBJECTFVATIPROC __glewGetArrayObjectfvATI = NULL; +PFNGLGETARRAYOBJECTIVATIPROC __glewGetArrayObjectivATI = NULL; +PFNGLGETOBJECTBUFFERFVATIPROC __glewGetObjectBufferfvATI = NULL; +PFNGLGETOBJECTBUFFERIVATIPROC __glewGetObjectBufferivATI = NULL; +PFNGLGETVARIANTARRAYOBJECTFVATIPROC __glewGetVariantArrayObjectfvATI = NULL; +PFNGLGETVARIANTARRAYOBJECTIVATIPROC __glewGetVariantArrayObjectivATI = NULL; +PFNGLISOBJECTBUFFERATIPROC __glewIsObjectBufferATI = NULL; +PFNGLNEWOBJECTBUFFERATIPROC __glewNewObjectBufferATI = NULL; +PFNGLUPDATEOBJECTBUFFERATIPROC __glewUpdateObjectBufferATI = NULL; +PFNGLVARIANTARRAYOBJECTATIPROC __glewVariantArrayObjectATI = NULL; + +PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC __glewGetVertexAttribArrayObjectfvATI = NULL; +PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC __glewGetVertexAttribArrayObjectivATI = NULL; +PFNGLVERTEXATTRIBARRAYOBJECTATIPROC __glewVertexAttribArrayObjectATI = NULL; + +PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC __glewClientActiveVertexStreamATI = NULL; +PFNGLNORMALSTREAM3BATIPROC __glewNormalStream3bATI = NULL; +PFNGLNORMALSTREAM3BVATIPROC __glewNormalStream3bvATI = NULL; +PFNGLNORMALSTREAM3DATIPROC __glewNormalStream3dATI = NULL; +PFNGLNORMALSTREAM3DVATIPROC __glewNormalStream3dvATI = NULL; +PFNGLNORMALSTREAM3FATIPROC __glewNormalStream3fATI = NULL; +PFNGLNORMALSTREAM3FVATIPROC __glewNormalStream3fvATI = NULL; +PFNGLNORMALSTREAM3IATIPROC __glewNormalStream3iATI = NULL; +PFNGLNORMALSTREAM3IVATIPROC __glewNormalStream3ivATI = NULL; +PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI = NULL; +PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI = NULL; +PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI = NULL; +PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI = NULL; +PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI = NULL; +PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI = NULL; +PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI = NULL; +PFNGLVERTEXSTREAM2FVATIPROC __glewVertexStream2fvATI = NULL; +PFNGLVERTEXSTREAM2IATIPROC __glewVertexStream2iATI = NULL; +PFNGLVERTEXSTREAM2IVATIPROC __glewVertexStream2ivATI = NULL; +PFNGLVERTEXSTREAM2SATIPROC __glewVertexStream2sATI = NULL; +PFNGLVERTEXSTREAM2SVATIPROC __glewVertexStream2svATI = NULL; +PFNGLVERTEXSTREAM3DATIPROC __glewVertexStream3dATI = NULL; +PFNGLVERTEXSTREAM3DVATIPROC __glewVertexStream3dvATI = NULL; +PFNGLVERTEXSTREAM3FATIPROC __glewVertexStream3fATI = NULL; +PFNGLVERTEXSTREAM3FVATIPROC __glewVertexStream3fvATI = NULL; +PFNGLVERTEXSTREAM3IATIPROC __glewVertexStream3iATI = NULL; +PFNGLVERTEXSTREAM3IVATIPROC __glewVertexStream3ivATI = NULL; +PFNGLVERTEXSTREAM3SATIPROC __glewVertexStream3sATI = NULL; +PFNGLVERTEXSTREAM3SVATIPROC __glewVertexStream3svATI = NULL; +PFNGLVERTEXSTREAM4DATIPROC __glewVertexStream4dATI = NULL; +PFNGLVERTEXSTREAM4DVATIPROC __glewVertexStream4dvATI = NULL; +PFNGLVERTEXSTREAM4FATIPROC __glewVertexStream4fATI = NULL; +PFNGLVERTEXSTREAM4FVATIPROC __glewVertexStream4fvATI = NULL; +PFNGLVERTEXSTREAM4IATIPROC __glewVertexStream4iATI = NULL; +PFNGLVERTEXSTREAM4IVATIPROC __glewVertexStream4ivATI = NULL; +PFNGLVERTEXSTREAM4SATIPROC __glewVertexStream4sATI = NULL; +PFNGLVERTEXSTREAM4SVATIPROC __glewVertexStream4svATI = NULL; + +PFNGLGETUNIFORMBUFFERSIZEEXTPROC __glewGetUniformBufferSizeEXT = NULL; +PFNGLGETUNIFORMOFFSETEXTPROC __glewGetUniformOffsetEXT = NULL; +PFNGLUNIFORMBUFFEREXTPROC __glewUniformBufferEXT = NULL; + +PFNGLBLENDCOLOREXTPROC __glewBlendColorEXT = NULL; + +PFNGLBLENDEQUATIONSEPARATEEXTPROC __glewBlendEquationSeparateEXT = NULL; + +PFNGLBLENDFUNCSEPARATEEXTPROC __glewBlendFuncSeparateEXT = NULL; + +PFNGLBLENDEQUATIONEXTPROC __glewBlendEquationEXT = NULL; + +PFNGLCOLORSUBTABLEEXTPROC __glewColorSubTableEXT = NULL; +PFNGLCOPYCOLORSUBTABLEEXTPROC __glewCopyColorSubTableEXT = NULL; + +PFNGLLOCKARRAYSEXTPROC __glewLockArraysEXT = NULL; +PFNGLUNLOCKARRAYSEXTPROC __glewUnlockArraysEXT = NULL; + +PFNGLCONVOLUTIONFILTER1DEXTPROC __glewConvolutionFilter1DEXT = NULL; +PFNGLCONVOLUTIONFILTER2DEXTPROC __glewConvolutionFilter2DEXT = NULL; +PFNGLCONVOLUTIONPARAMETERFEXTPROC __glewConvolutionParameterfEXT = NULL; +PFNGLCONVOLUTIONPARAMETERFVEXTPROC __glewConvolutionParameterfvEXT = NULL; +PFNGLCONVOLUTIONPARAMETERIEXTPROC __glewConvolutionParameteriEXT = NULL; +PFNGLCONVOLUTIONPARAMETERIVEXTPROC __glewConvolutionParameterivEXT = NULL; +PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC __glewCopyConvolutionFilter1DEXT = NULL; +PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC __glewCopyConvolutionFilter2DEXT = NULL; +PFNGLGETCONVOLUTIONFILTEREXTPROC __glewGetConvolutionFilterEXT = NULL; +PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC __glewGetConvolutionParameterfvEXT = NULL; +PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC __glewGetConvolutionParameterivEXT = NULL; +PFNGLGETSEPARABLEFILTEREXTPROC __glewGetSeparableFilterEXT = NULL; +PFNGLSEPARABLEFILTER2DEXTPROC __glewSeparableFilter2DEXT = NULL; + +PFNGLBINORMALPOINTEREXTPROC __glewBinormalPointerEXT = NULL; +PFNGLTANGENTPOINTEREXTPROC __glewTangentPointerEXT = NULL; + +PFNGLCOPYTEXIMAGE1DEXTPROC __glewCopyTexImage1DEXT = NULL; +PFNGLCOPYTEXIMAGE2DEXTPROC __glewCopyTexImage2DEXT = NULL; +PFNGLCOPYTEXSUBIMAGE1DEXTPROC __glewCopyTexSubImage1DEXT = NULL; +PFNGLCOPYTEXSUBIMAGE2DEXTPROC __glewCopyTexSubImage2DEXT = NULL; +PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT = NULL; + +PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT = NULL; +PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT = NULL; + +PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT = NULL; + +PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT = NULL; +PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC __glewCheckNamedFramebufferStatusEXT = NULL; +PFNGLCLIENTATTRIBDEFAULTEXTPROC __glewClientAttribDefaultEXT = NULL; +PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC __glewCompressedMultiTexImage1DEXT = NULL; +PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC __glewCompressedMultiTexImage2DEXT = NULL; +PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC __glewCompressedMultiTexImage3DEXT = NULL; +PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC __glewCompressedMultiTexSubImage1DEXT = NULL; +PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC __glewCompressedMultiTexSubImage2DEXT = NULL; +PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC __glewCompressedMultiTexSubImage3DEXT = NULL; +PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC __glewCompressedTextureImage1DEXT = NULL; +PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC __glewCompressedTextureImage2DEXT = NULL; +PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC __glewCompressedTextureImage3DEXT = NULL; +PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC __glewCompressedTextureSubImage1DEXT = NULL; +PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC __glewCompressedTextureSubImage2DEXT = NULL; +PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC __glewCompressedTextureSubImage3DEXT = NULL; +PFNGLCOPYMULTITEXIMAGE1DEXTPROC __glewCopyMultiTexImage1DEXT = NULL; +PFNGLCOPYMULTITEXIMAGE2DEXTPROC __glewCopyMultiTexImage2DEXT = NULL; +PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC __glewCopyMultiTexSubImage1DEXT = NULL; +PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC __glewCopyMultiTexSubImage2DEXT = NULL; +PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC __glewCopyMultiTexSubImage3DEXT = NULL; +PFNGLCOPYTEXTUREIMAGE1DEXTPROC __glewCopyTextureImage1DEXT = NULL; +PFNGLCOPYTEXTUREIMAGE2DEXTPROC __glewCopyTextureImage2DEXT = NULL; +PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC __glewCopyTextureSubImage1DEXT = NULL; +PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC __glewCopyTextureSubImage2DEXT = NULL; +PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC __glewCopyTextureSubImage3DEXT = NULL; +PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC __glewDisableClientStateIndexedEXT = NULL; +PFNGLDISABLECLIENTSTATEIEXTPROC __glewDisableClientStateiEXT = NULL; +PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC __glewDisableVertexArrayAttribEXT = NULL; +PFNGLDISABLEVERTEXARRAYEXTPROC __glewDisableVertexArrayEXT = NULL; +PFNGLENABLECLIENTSTATEINDEXEDEXTPROC __glewEnableClientStateIndexedEXT = NULL; +PFNGLENABLECLIENTSTATEIEXTPROC __glewEnableClientStateiEXT = NULL; +PFNGLENABLEVERTEXARRAYATTRIBEXTPROC __glewEnableVertexArrayAttribEXT = NULL; +PFNGLENABLEVERTEXARRAYEXTPROC __glewEnableVertexArrayEXT = NULL; +PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC __glewFlushMappedNamedBufferRangeEXT = NULL; +PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC __glewFramebufferDrawBufferEXT = NULL; +PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC __glewFramebufferDrawBuffersEXT = NULL; +PFNGLFRAMEBUFFERREADBUFFEREXTPROC __glewFramebufferReadBufferEXT = NULL; +PFNGLGENERATEMULTITEXMIPMAPEXTPROC __glewGenerateMultiTexMipmapEXT = NULL; +PFNGLGENERATETEXTUREMIPMAPEXTPROC __glewGenerateTextureMipmapEXT = NULL; +PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC __glewGetCompressedMultiTexImageEXT = NULL; +PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC __glewGetCompressedTextureImageEXT = NULL; +PFNGLGETDOUBLEINDEXEDVEXTPROC __glewGetDoubleIndexedvEXT = NULL; +PFNGLGETDOUBLEI_VEXTPROC __glewGetDoublei_vEXT = NULL; +PFNGLGETFLOATINDEXEDVEXTPROC __glewGetFloatIndexedvEXT = NULL; +PFNGLGETFLOATI_VEXTPROC __glewGetFloati_vEXT = NULL; +PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC __glewGetFramebufferParameterivEXT = NULL; +PFNGLGETMULTITEXENVFVEXTPROC __glewGetMultiTexEnvfvEXT = NULL; +PFNGLGETMULTITEXENVIVEXTPROC __glewGetMultiTexEnvivEXT = NULL; +PFNGLGETMULTITEXGENDVEXTPROC __glewGetMultiTexGendvEXT = NULL; +PFNGLGETMULTITEXGENFVEXTPROC __glewGetMultiTexGenfvEXT = NULL; +PFNGLGETMULTITEXGENIVEXTPROC __glewGetMultiTexGenivEXT = NULL; +PFNGLGETMULTITEXIMAGEEXTPROC __glewGetMultiTexImageEXT = NULL; +PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC __glewGetMultiTexLevelParameterfvEXT = NULL; +PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC __glewGetMultiTexLevelParameterivEXT = NULL; +PFNGLGETMULTITEXPARAMETERIIVEXTPROC __glewGetMultiTexParameterIivEXT = NULL; +PFNGLGETMULTITEXPARAMETERIUIVEXTPROC __glewGetMultiTexParameterIuivEXT = NULL; +PFNGLGETMULTITEXPARAMETERFVEXTPROC __glewGetMultiTexParameterfvEXT = NULL; +PFNGLGETMULTITEXPARAMETERIVEXTPROC __glewGetMultiTexParameterivEXT = NULL; +PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC __glewGetNamedBufferParameterivEXT = NULL; +PFNGLGETNAMEDBUFFERPOINTERVEXTPROC __glewGetNamedBufferPointervEXT = NULL; +PFNGLGETNAMEDBUFFERSUBDATAEXTPROC __glewGetNamedBufferSubDataEXT = NULL; +PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetNamedFramebufferAttachmentParameterivEXT = NULL; +PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC __glewGetNamedProgramLocalParameterIivEXT = NULL; +PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC __glewGetNamedProgramLocalParameterIuivEXT = NULL; +PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC __glewGetNamedProgramLocalParameterdvEXT = NULL; +PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC __glewGetNamedProgramLocalParameterfvEXT = NULL; +PFNGLGETNAMEDPROGRAMSTRINGEXTPROC __glewGetNamedProgramStringEXT = NULL; +PFNGLGETNAMEDPROGRAMIVEXTPROC __glewGetNamedProgramivEXT = NULL; +PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC __glewGetNamedRenderbufferParameterivEXT = NULL; +PFNGLGETPOINTERINDEXEDVEXTPROC __glewGetPointerIndexedvEXT = NULL; +PFNGLGETPOINTERI_VEXTPROC __glewGetPointeri_vEXT = NULL; +PFNGLGETTEXTUREIMAGEEXTPROC __glewGetTextureImageEXT = NULL; +PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC __glewGetTextureLevelParameterfvEXT = NULL; +PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC __glewGetTextureLevelParameterivEXT = NULL; +PFNGLGETTEXTUREPARAMETERIIVEXTPROC __glewGetTextureParameterIivEXT = NULL; +PFNGLGETTEXTUREPARAMETERIUIVEXTPROC __glewGetTextureParameterIuivEXT = NULL; +PFNGLGETTEXTUREPARAMETERFVEXTPROC __glewGetTextureParameterfvEXT = NULL; +PFNGLGETTEXTUREPARAMETERIVEXTPROC __glewGetTextureParameterivEXT = NULL; +PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC __glewGetVertexArrayIntegeri_vEXT = NULL; +PFNGLGETVERTEXARRAYINTEGERVEXTPROC __glewGetVertexArrayIntegervEXT = NULL; +PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC __glewGetVertexArrayPointeri_vEXT = NULL; +PFNGLGETVERTEXARRAYPOINTERVEXTPROC __glewGetVertexArrayPointervEXT = NULL; +PFNGLMAPNAMEDBUFFEREXTPROC __glewMapNamedBufferEXT = NULL; +PFNGLMAPNAMEDBUFFERRANGEEXTPROC __glewMapNamedBufferRangeEXT = NULL; +PFNGLMATRIXFRUSTUMEXTPROC __glewMatrixFrustumEXT = NULL; +PFNGLMATRIXLOADIDENTITYEXTPROC __glewMatrixLoadIdentityEXT = NULL; +PFNGLMATRIXLOADTRANSPOSEDEXTPROC __glewMatrixLoadTransposedEXT = NULL; +PFNGLMATRIXLOADTRANSPOSEFEXTPROC __glewMatrixLoadTransposefEXT = NULL; +PFNGLMATRIXLOADDEXTPROC __glewMatrixLoaddEXT = NULL; +PFNGLMATRIXLOADFEXTPROC __glewMatrixLoadfEXT = NULL; +PFNGLMATRIXMULTTRANSPOSEDEXTPROC __glewMatrixMultTransposedEXT = NULL; +PFNGLMATRIXMULTTRANSPOSEFEXTPROC __glewMatrixMultTransposefEXT = NULL; +PFNGLMATRIXMULTDEXTPROC __glewMatrixMultdEXT = NULL; +PFNGLMATRIXMULTFEXTPROC __glewMatrixMultfEXT = NULL; +PFNGLMATRIXORTHOEXTPROC __glewMatrixOrthoEXT = NULL; +PFNGLMATRIXPOPEXTPROC __glewMatrixPopEXT = NULL; +PFNGLMATRIXPUSHEXTPROC __glewMatrixPushEXT = NULL; +PFNGLMATRIXROTATEDEXTPROC __glewMatrixRotatedEXT = NULL; +PFNGLMATRIXROTATEFEXTPROC __glewMatrixRotatefEXT = NULL; +PFNGLMATRIXSCALEDEXTPROC __glewMatrixScaledEXT = NULL; +PFNGLMATRIXSCALEFEXTPROC __glewMatrixScalefEXT = NULL; +PFNGLMATRIXTRANSLATEDEXTPROC __glewMatrixTranslatedEXT = NULL; +PFNGLMATRIXTRANSLATEFEXTPROC __glewMatrixTranslatefEXT = NULL; +PFNGLMULTITEXBUFFEREXTPROC __glewMultiTexBufferEXT = NULL; +PFNGLMULTITEXCOORDPOINTEREXTPROC __glewMultiTexCoordPointerEXT = NULL; +PFNGLMULTITEXENVFEXTPROC __glewMultiTexEnvfEXT = NULL; +PFNGLMULTITEXENVFVEXTPROC __glewMultiTexEnvfvEXT = NULL; +PFNGLMULTITEXENVIEXTPROC __glewMultiTexEnviEXT = NULL; +PFNGLMULTITEXENVIVEXTPROC __glewMultiTexEnvivEXT = NULL; +PFNGLMULTITEXGENDEXTPROC __glewMultiTexGendEXT = NULL; +PFNGLMULTITEXGENDVEXTPROC __glewMultiTexGendvEXT = NULL; +PFNGLMULTITEXGENFEXTPROC __glewMultiTexGenfEXT = NULL; +PFNGLMULTITEXGENFVEXTPROC __glewMultiTexGenfvEXT = NULL; +PFNGLMULTITEXGENIEXTPROC __glewMultiTexGeniEXT = NULL; +PFNGLMULTITEXGENIVEXTPROC __glewMultiTexGenivEXT = NULL; +PFNGLMULTITEXIMAGE1DEXTPROC __glewMultiTexImage1DEXT = NULL; +PFNGLMULTITEXIMAGE2DEXTPROC __glewMultiTexImage2DEXT = NULL; +PFNGLMULTITEXIMAGE3DEXTPROC __glewMultiTexImage3DEXT = NULL; +PFNGLMULTITEXPARAMETERIIVEXTPROC __glewMultiTexParameterIivEXT = NULL; +PFNGLMULTITEXPARAMETERIUIVEXTPROC __glewMultiTexParameterIuivEXT = NULL; +PFNGLMULTITEXPARAMETERFEXTPROC __glewMultiTexParameterfEXT = NULL; +PFNGLMULTITEXPARAMETERFVEXTPROC __glewMultiTexParameterfvEXT = NULL; +PFNGLMULTITEXPARAMETERIEXTPROC __glewMultiTexParameteriEXT = NULL; +PFNGLMULTITEXPARAMETERIVEXTPROC __glewMultiTexParameterivEXT = NULL; +PFNGLMULTITEXRENDERBUFFEREXTPROC __glewMultiTexRenderbufferEXT = NULL; +PFNGLMULTITEXSUBIMAGE1DEXTPROC __glewMultiTexSubImage1DEXT = NULL; +PFNGLMULTITEXSUBIMAGE2DEXTPROC __glewMultiTexSubImage2DEXT = NULL; +PFNGLMULTITEXSUBIMAGE3DEXTPROC __glewMultiTexSubImage3DEXT = NULL; +PFNGLNAMEDBUFFERDATAEXTPROC __glewNamedBufferDataEXT = NULL; +PFNGLNAMEDBUFFERSUBDATAEXTPROC __glewNamedBufferSubDataEXT = NULL; +PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC __glewNamedCopyBufferSubDataEXT = NULL; +PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC __glewNamedFramebufferRenderbufferEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC __glewNamedFramebufferTexture1DEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC __glewNamedFramebufferTexture2DEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC __glewNamedFramebufferTexture3DEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC __glewNamedFramebufferTextureEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC __glewNamedFramebufferTextureFaceEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC __glewNamedFramebufferTextureLayerEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC __glewNamedProgramLocalParameter4dEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC __glewNamedProgramLocalParameter4dvEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC __glewNamedProgramLocalParameter4fEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC __glewNamedProgramLocalParameter4fvEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC __glewNamedProgramLocalParameterI4iEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC __glewNamedProgramLocalParameterI4ivEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC __glewNamedProgramLocalParameterI4uiEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC __glewNamedProgramLocalParameterI4uivEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC __glewNamedProgramLocalParameters4fvEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC __glewNamedProgramLocalParametersI4ivEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC __glewNamedProgramLocalParametersI4uivEXT = NULL; +PFNGLNAMEDPROGRAMSTRINGEXTPROC __glewNamedProgramStringEXT = NULL; +PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC __glewNamedRenderbufferStorageEXT = NULL; +PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC __glewNamedRenderbufferStorageMultisampleCoverageEXT = NULL; +PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewNamedRenderbufferStorageMultisampleEXT = NULL; +PFNGLPROGRAMUNIFORM1FEXTPROC __glewProgramUniform1fEXT = NULL; +PFNGLPROGRAMUNIFORM1FVEXTPROC __glewProgramUniform1fvEXT = NULL; +PFNGLPROGRAMUNIFORM1IEXTPROC __glewProgramUniform1iEXT = NULL; +PFNGLPROGRAMUNIFORM1IVEXTPROC __glewProgramUniform1ivEXT = NULL; +PFNGLPROGRAMUNIFORM1UIEXTPROC __glewProgramUniform1uiEXT = NULL; +PFNGLPROGRAMUNIFORM1UIVEXTPROC __glewProgramUniform1uivEXT = NULL; +PFNGLPROGRAMUNIFORM2FEXTPROC __glewProgramUniform2fEXT = NULL; +PFNGLPROGRAMUNIFORM2FVEXTPROC __glewProgramUniform2fvEXT = NULL; +PFNGLPROGRAMUNIFORM2IEXTPROC __glewProgramUniform2iEXT = NULL; +PFNGLPROGRAMUNIFORM2IVEXTPROC __glewProgramUniform2ivEXT = NULL; +PFNGLPROGRAMUNIFORM2UIEXTPROC __glewProgramUniform2uiEXT = NULL; +PFNGLPROGRAMUNIFORM2UIVEXTPROC __glewProgramUniform2uivEXT = NULL; +PFNGLPROGRAMUNIFORM3FEXTPROC __glewProgramUniform3fEXT = NULL; +PFNGLPROGRAMUNIFORM3FVEXTPROC __glewProgramUniform3fvEXT = NULL; +PFNGLPROGRAMUNIFORM3IEXTPROC __glewProgramUniform3iEXT = NULL; +PFNGLPROGRAMUNIFORM3IVEXTPROC __glewProgramUniform3ivEXT = NULL; +PFNGLPROGRAMUNIFORM3UIEXTPROC __glewProgramUniform3uiEXT = NULL; +PFNGLPROGRAMUNIFORM3UIVEXTPROC __glewProgramUniform3uivEXT = NULL; +PFNGLPROGRAMUNIFORM4FEXTPROC __glewProgramUniform4fEXT = NULL; +PFNGLPROGRAMUNIFORM4FVEXTPROC __glewProgramUniform4fvEXT = NULL; +PFNGLPROGRAMUNIFORM4IEXTPROC __glewProgramUniform4iEXT = NULL; +PFNGLPROGRAMUNIFORM4IVEXTPROC __glewProgramUniform4ivEXT = NULL; +PFNGLPROGRAMUNIFORM4UIEXTPROC __glewProgramUniform4uiEXT = NULL; +PFNGLPROGRAMUNIFORM4UIVEXTPROC __glewProgramUniform4uivEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC __glewProgramUniformMatrix2fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC __glewProgramUniformMatrix2x3fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC __glewProgramUniformMatrix2x4fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC __glewProgramUniformMatrix3fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC __glewProgramUniformMatrix3x2fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC __glewProgramUniformMatrix3x4fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC __glewProgramUniformMatrix4fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC __glewProgramUniformMatrix4x2fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC __glewProgramUniformMatrix4x3fvEXT = NULL; +PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC __glewPushClientAttribDefaultEXT = NULL; +PFNGLTEXTUREBUFFEREXTPROC __glewTextureBufferEXT = NULL; +PFNGLTEXTUREIMAGE1DEXTPROC __glewTextureImage1DEXT = NULL; +PFNGLTEXTUREIMAGE2DEXTPROC __glewTextureImage2DEXT = NULL; +PFNGLTEXTUREIMAGE3DEXTPROC __glewTextureImage3DEXT = NULL; +PFNGLTEXTUREPARAMETERIIVEXTPROC __glewTextureParameterIivEXT = NULL; +PFNGLTEXTUREPARAMETERIUIVEXTPROC __glewTextureParameterIuivEXT = NULL; +PFNGLTEXTUREPARAMETERFEXTPROC __glewTextureParameterfEXT = NULL; +PFNGLTEXTUREPARAMETERFVEXTPROC __glewTextureParameterfvEXT = NULL; +PFNGLTEXTUREPARAMETERIEXTPROC __glewTextureParameteriEXT = NULL; +PFNGLTEXTUREPARAMETERIVEXTPROC __glewTextureParameterivEXT = NULL; +PFNGLTEXTURERENDERBUFFEREXTPROC __glewTextureRenderbufferEXT = NULL; +PFNGLTEXTURESUBIMAGE1DEXTPROC __glewTextureSubImage1DEXT = NULL; +PFNGLTEXTURESUBIMAGE2DEXTPROC __glewTextureSubImage2DEXT = NULL; +PFNGLTEXTURESUBIMAGE3DEXTPROC __glewTextureSubImage3DEXT = NULL; +PFNGLUNMAPNAMEDBUFFEREXTPROC __glewUnmapNamedBufferEXT = NULL; +PFNGLVERTEXARRAYCOLOROFFSETEXTPROC __glewVertexArrayColorOffsetEXT = NULL; +PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC __glewVertexArrayEdgeFlagOffsetEXT = NULL; +PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC __glewVertexArrayFogCoordOffsetEXT = NULL; +PFNGLVERTEXARRAYINDEXOFFSETEXTPROC __glewVertexArrayIndexOffsetEXT = NULL; +PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC __glewVertexArrayMultiTexCoordOffsetEXT = NULL; +PFNGLVERTEXARRAYNORMALOFFSETEXTPROC __glewVertexArrayNormalOffsetEXT = NULL; +PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC __glewVertexArraySecondaryColorOffsetEXT = NULL; +PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC __glewVertexArrayTexCoordOffsetEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC __glewVertexArrayVertexAttribIOffsetEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC __glewVertexArrayVertexAttribOffsetEXT = NULL; +PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC __glewVertexArrayVertexOffsetEXT = NULL; + +PFNGLCOLORMASKINDEXEDEXTPROC __glewColorMaskIndexedEXT = NULL; +PFNGLDISABLEINDEXEDEXTPROC __glewDisableIndexedEXT = NULL; +PFNGLENABLEINDEXEDEXTPROC __glewEnableIndexedEXT = NULL; +PFNGLGETBOOLEANINDEXEDVEXTPROC __glewGetBooleanIndexedvEXT = NULL; +PFNGLGETINTEGERINDEXEDVEXTPROC __glewGetIntegerIndexedvEXT = NULL; +PFNGLISENABLEDINDEXEDEXTPROC __glewIsEnabledIndexedEXT = NULL; + +PFNGLDRAWARRAYSINSTANCEDEXTPROC __glewDrawArraysInstancedEXT = NULL; +PFNGLDRAWELEMENTSINSTANCEDEXTPROC __glewDrawElementsInstancedEXT = NULL; + +PFNGLDRAWRANGEELEMENTSEXTPROC __glewDrawRangeElementsEXT = NULL; + +PFNGLFOGCOORDPOINTEREXTPROC __glewFogCoordPointerEXT = NULL; +PFNGLFOGCOORDDEXTPROC __glewFogCoorddEXT = NULL; +PFNGLFOGCOORDDVEXTPROC __glewFogCoorddvEXT = NULL; +PFNGLFOGCOORDFEXTPROC __glewFogCoordfEXT = NULL; +PFNGLFOGCOORDFVEXTPROC __glewFogCoordfvEXT = NULL; + +PFNGLFRAGMENTCOLORMATERIALEXTPROC __glewFragmentColorMaterialEXT = NULL; +PFNGLFRAGMENTLIGHTMODELFEXTPROC __glewFragmentLightModelfEXT = NULL; +PFNGLFRAGMENTLIGHTMODELFVEXTPROC __glewFragmentLightModelfvEXT = NULL; +PFNGLFRAGMENTLIGHTMODELIEXTPROC __glewFragmentLightModeliEXT = NULL; +PFNGLFRAGMENTLIGHTMODELIVEXTPROC __glewFragmentLightModelivEXT = NULL; +PFNGLFRAGMENTLIGHTFEXTPROC __glewFragmentLightfEXT = NULL; +PFNGLFRAGMENTLIGHTFVEXTPROC __glewFragmentLightfvEXT = NULL; +PFNGLFRAGMENTLIGHTIEXTPROC __glewFragmentLightiEXT = NULL; +PFNGLFRAGMENTLIGHTIVEXTPROC __glewFragmentLightivEXT = NULL; +PFNGLFRAGMENTMATERIALFEXTPROC __glewFragmentMaterialfEXT = NULL; +PFNGLFRAGMENTMATERIALFVEXTPROC __glewFragmentMaterialfvEXT = NULL; +PFNGLFRAGMENTMATERIALIEXTPROC __glewFragmentMaterialiEXT = NULL; +PFNGLFRAGMENTMATERIALIVEXTPROC __glewFragmentMaterialivEXT = NULL; +PFNGLGETFRAGMENTLIGHTFVEXTPROC __glewGetFragmentLightfvEXT = NULL; +PFNGLGETFRAGMENTLIGHTIVEXTPROC __glewGetFragmentLightivEXT = NULL; +PFNGLGETFRAGMENTMATERIALFVEXTPROC __glewGetFragmentMaterialfvEXT = NULL; +PFNGLGETFRAGMENTMATERIALIVEXTPROC __glewGetFragmentMaterialivEXT = NULL; +PFNGLLIGHTENVIEXTPROC __glewLightEnviEXT = NULL; + +PFNGLBLITFRAMEBUFFEREXTPROC __glewBlitFramebufferEXT = NULL; + +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC __glewRenderbufferStorageMultisampleEXT = NULL; + +PFNGLBINDFRAMEBUFFEREXTPROC __glewBindFramebufferEXT = NULL; +PFNGLBINDRENDERBUFFEREXTPROC __glewBindRenderbufferEXT = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC __glewCheckFramebufferStatusEXT = NULL; +PFNGLDELETEFRAMEBUFFERSEXTPROC __glewDeleteFramebuffersEXT = NULL; +PFNGLDELETERENDERBUFFERSEXTPROC __glewDeleteRenderbuffersEXT = NULL; +PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC __glewFramebufferRenderbufferEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE1DEXTPROC __glewFramebufferTexture1DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE2DEXTPROC __glewFramebufferTexture2DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE3DEXTPROC __glewFramebufferTexture3DEXT = NULL; +PFNGLGENFRAMEBUFFERSEXTPROC __glewGenFramebuffersEXT = NULL; +PFNGLGENRENDERBUFFERSEXTPROC __glewGenRenderbuffersEXT = NULL; +PFNGLGENERATEMIPMAPEXTPROC __glewGenerateMipmapEXT = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC __glewGetFramebufferAttachmentParameterivEXT = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC __glewGetRenderbufferParameterivEXT = NULL; +PFNGLISFRAMEBUFFEREXTPROC __glewIsFramebufferEXT = NULL; +PFNGLISRENDERBUFFEREXTPROC __glewIsRenderbufferEXT = NULL; +PFNGLRENDERBUFFERSTORAGEEXTPROC __glewRenderbufferStorageEXT = NULL; + +PFNGLFRAMEBUFFERTEXTUREEXTPROC __glewFramebufferTextureEXT = NULL; +PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC __glewFramebufferTextureFaceEXT = NULL; +PFNGLPROGRAMPARAMETERIEXTPROC __glewProgramParameteriEXT = NULL; + +PFNGLPROGRAMENVPARAMETERS4FVEXTPROC __glewProgramEnvParameters4fvEXT = NULL; +PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC __glewProgramLocalParameters4fvEXT = NULL; + +PFNGLBINDFRAGDATALOCATIONEXTPROC __glewBindFragDataLocationEXT = NULL; +PFNGLGETFRAGDATALOCATIONEXTPROC __glewGetFragDataLocationEXT = NULL; +PFNGLGETUNIFORMUIVEXTPROC __glewGetUniformuivEXT = NULL; +PFNGLGETVERTEXATTRIBIIVEXTPROC __glewGetVertexAttribIivEXT = NULL; +PFNGLGETVERTEXATTRIBIUIVEXTPROC __glewGetVertexAttribIuivEXT = NULL; +PFNGLUNIFORM1UIEXTPROC __glewUniform1uiEXT = NULL; +PFNGLUNIFORM1UIVEXTPROC __glewUniform1uivEXT = NULL; +PFNGLUNIFORM2UIEXTPROC __glewUniform2uiEXT = NULL; +PFNGLUNIFORM2UIVEXTPROC __glewUniform2uivEXT = NULL; +PFNGLUNIFORM3UIEXTPROC __glewUniform3uiEXT = NULL; +PFNGLUNIFORM3UIVEXTPROC __glewUniform3uivEXT = NULL; +PFNGLUNIFORM4UIEXTPROC __glewUniform4uiEXT = NULL; +PFNGLUNIFORM4UIVEXTPROC __glewUniform4uivEXT = NULL; +PFNGLVERTEXATTRIBI1IEXTPROC __glewVertexAttribI1iEXT = NULL; +PFNGLVERTEXATTRIBI1IVEXTPROC __glewVertexAttribI1ivEXT = NULL; +PFNGLVERTEXATTRIBI1UIEXTPROC __glewVertexAttribI1uiEXT = NULL; +PFNGLVERTEXATTRIBI1UIVEXTPROC __glewVertexAttribI1uivEXT = NULL; +PFNGLVERTEXATTRIBI2IEXTPROC __glewVertexAttribI2iEXT = NULL; +PFNGLVERTEXATTRIBI2IVEXTPROC __glewVertexAttribI2ivEXT = NULL; +PFNGLVERTEXATTRIBI2UIEXTPROC __glewVertexAttribI2uiEXT = NULL; +PFNGLVERTEXATTRIBI2UIVEXTPROC __glewVertexAttribI2uivEXT = NULL; +PFNGLVERTEXATTRIBI3IEXTPROC __glewVertexAttribI3iEXT = NULL; +PFNGLVERTEXATTRIBI3IVEXTPROC __glewVertexAttribI3ivEXT = NULL; +PFNGLVERTEXATTRIBI3UIEXTPROC __glewVertexAttribI3uiEXT = NULL; +PFNGLVERTEXATTRIBI3UIVEXTPROC __glewVertexAttribI3uivEXT = NULL; +PFNGLVERTEXATTRIBI4BVEXTPROC __glewVertexAttribI4bvEXT = NULL; +PFNGLVERTEXATTRIBI4IEXTPROC __glewVertexAttribI4iEXT = NULL; +PFNGLVERTEXATTRIBI4IVEXTPROC __glewVertexAttribI4ivEXT = NULL; +PFNGLVERTEXATTRIBI4SVEXTPROC __glewVertexAttribI4svEXT = NULL; +PFNGLVERTEXATTRIBI4UBVEXTPROC __glewVertexAttribI4ubvEXT = NULL; +PFNGLVERTEXATTRIBI4UIEXTPROC __glewVertexAttribI4uiEXT = NULL; +PFNGLVERTEXATTRIBI4UIVEXTPROC __glewVertexAttribI4uivEXT = NULL; +PFNGLVERTEXATTRIBI4USVEXTPROC __glewVertexAttribI4usvEXT = NULL; +PFNGLVERTEXATTRIBIPOINTEREXTPROC __glewVertexAttribIPointerEXT = NULL; + +PFNGLGETHISTOGRAMEXTPROC __glewGetHistogramEXT = NULL; +PFNGLGETHISTOGRAMPARAMETERFVEXTPROC __glewGetHistogramParameterfvEXT = NULL; +PFNGLGETHISTOGRAMPARAMETERIVEXTPROC __glewGetHistogramParameterivEXT = NULL; +PFNGLGETMINMAXEXTPROC __glewGetMinmaxEXT = NULL; +PFNGLGETMINMAXPARAMETERFVEXTPROC __glewGetMinmaxParameterfvEXT = NULL; +PFNGLGETMINMAXPARAMETERIVEXTPROC __glewGetMinmaxParameterivEXT = NULL; +PFNGLHISTOGRAMEXTPROC __glewHistogramEXT = NULL; +PFNGLMINMAXEXTPROC __glewMinmaxEXT = NULL; +PFNGLRESETHISTOGRAMEXTPROC __glewResetHistogramEXT = NULL; +PFNGLRESETMINMAXEXTPROC __glewResetMinmaxEXT = NULL; + +PFNGLINDEXFUNCEXTPROC __glewIndexFuncEXT = NULL; + +PFNGLINDEXMATERIALEXTPROC __glewIndexMaterialEXT = NULL; + +PFNGLAPPLYTEXTUREEXTPROC __glewApplyTextureEXT = NULL; +PFNGLTEXTURELIGHTEXTPROC __glewTextureLightEXT = NULL; +PFNGLTEXTUREMATERIALEXTPROC __glewTextureMaterialEXT = NULL; + +PFNGLMULTIDRAWARRAYSEXTPROC __glewMultiDrawArraysEXT = NULL; +PFNGLMULTIDRAWELEMENTSEXTPROC __glewMultiDrawElementsEXT = NULL; + +PFNGLSAMPLEMASKEXTPROC __glewSampleMaskEXT = NULL; +PFNGLSAMPLEPATTERNEXTPROC __glewSamplePatternEXT = NULL; + +PFNGLCOLORTABLEEXTPROC __glewColorTableEXT = NULL; +PFNGLGETCOLORTABLEEXTPROC __glewGetColorTableEXT = NULL; +PFNGLGETCOLORTABLEPARAMETERFVEXTPROC __glewGetColorTableParameterfvEXT = NULL; +PFNGLGETCOLORTABLEPARAMETERIVEXTPROC __glewGetColorTableParameterivEXT = NULL; + +PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC __glewGetPixelTransformParameterfvEXT = NULL; +PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC __glewGetPixelTransformParameterivEXT = NULL; +PFNGLPIXELTRANSFORMPARAMETERFEXTPROC __glewPixelTransformParameterfEXT = NULL; +PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC __glewPixelTransformParameterfvEXT = NULL; +PFNGLPIXELTRANSFORMPARAMETERIEXTPROC __glewPixelTransformParameteriEXT = NULL; +PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC __glewPixelTransformParameterivEXT = NULL; + +PFNGLPOINTPARAMETERFEXTPROC __glewPointParameterfEXT = NULL; +PFNGLPOINTPARAMETERFVEXTPROC __glewPointParameterfvEXT = NULL; + +PFNGLPOLYGONOFFSETEXTPROC __glewPolygonOffsetEXT = NULL; + +PFNGLPROVOKINGVERTEXEXTPROC __glewProvokingVertexEXT = NULL; + +PFNGLBEGINSCENEEXTPROC __glewBeginSceneEXT = NULL; +PFNGLENDSCENEEXTPROC __glewEndSceneEXT = NULL; + +PFNGLSECONDARYCOLOR3BEXTPROC __glewSecondaryColor3bEXT = NULL; +PFNGLSECONDARYCOLOR3BVEXTPROC __glewSecondaryColor3bvEXT = NULL; +PFNGLSECONDARYCOLOR3DEXTPROC __glewSecondaryColor3dEXT = NULL; +PFNGLSECONDARYCOLOR3DVEXTPROC __glewSecondaryColor3dvEXT = NULL; +PFNGLSECONDARYCOLOR3FEXTPROC __glewSecondaryColor3fEXT = NULL; +PFNGLSECONDARYCOLOR3FVEXTPROC __glewSecondaryColor3fvEXT = NULL; +PFNGLSECONDARYCOLOR3IEXTPROC __glewSecondaryColor3iEXT = NULL; +PFNGLSECONDARYCOLOR3IVEXTPROC __glewSecondaryColor3ivEXT = NULL; +PFNGLSECONDARYCOLOR3SEXTPROC __glewSecondaryColor3sEXT = NULL; +PFNGLSECONDARYCOLOR3SVEXTPROC __glewSecondaryColor3svEXT = NULL; +PFNGLSECONDARYCOLOR3UBEXTPROC __glewSecondaryColor3ubEXT = NULL; +PFNGLSECONDARYCOLOR3UBVEXTPROC __glewSecondaryColor3ubvEXT = NULL; +PFNGLSECONDARYCOLOR3UIEXTPROC __glewSecondaryColor3uiEXT = NULL; +PFNGLSECONDARYCOLOR3UIVEXTPROC __glewSecondaryColor3uivEXT = NULL; +PFNGLSECONDARYCOLOR3USEXTPROC __glewSecondaryColor3usEXT = NULL; +PFNGLSECONDARYCOLOR3USVEXTPROC __glewSecondaryColor3usvEXT = NULL; +PFNGLSECONDARYCOLORPOINTEREXTPROC __glewSecondaryColorPointerEXT = NULL; + +PFNGLACTIVEPROGRAMEXTPROC __glewActiveProgramEXT = NULL; +PFNGLCREATESHADERPROGRAMEXTPROC __glewCreateShaderProgramEXT = NULL; +PFNGLUSESHADERPROGRAMEXTPROC __glewUseShaderProgramEXT = NULL; + +PFNGLBINDIMAGETEXTUREEXTPROC __glewBindImageTextureEXT = NULL; +PFNGLMEMORYBARRIEREXTPROC __glewMemoryBarrierEXT = NULL; + +PFNGLACTIVESTENCILFACEEXTPROC __glewActiveStencilFaceEXT = NULL; + +PFNGLTEXSUBIMAGE1DEXTPROC __glewTexSubImage1DEXT = NULL; +PFNGLTEXSUBIMAGE2DEXTPROC __glewTexSubImage2DEXT = NULL; +PFNGLTEXSUBIMAGE3DEXTPROC __glewTexSubImage3DEXT = NULL; + +PFNGLTEXIMAGE3DEXTPROC __glewTexImage3DEXT = NULL; + +PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC __glewFramebufferTextureLayerEXT = NULL; + +PFNGLTEXBUFFEREXTPROC __glewTexBufferEXT = NULL; + +PFNGLCLEARCOLORIIEXTPROC __glewClearColorIiEXT = NULL; +PFNGLCLEARCOLORIUIEXTPROC __glewClearColorIuiEXT = NULL; +PFNGLGETTEXPARAMETERIIVEXTPROC __glewGetTexParameterIivEXT = NULL; +PFNGLGETTEXPARAMETERIUIVEXTPROC __glewGetTexParameterIuivEXT = NULL; +PFNGLTEXPARAMETERIIVEXTPROC __glewTexParameterIivEXT = NULL; +PFNGLTEXPARAMETERIUIVEXTPROC __glewTexParameterIuivEXT = NULL; + +PFNGLARETEXTURESRESIDENTEXTPROC __glewAreTexturesResidentEXT = NULL; +PFNGLBINDTEXTUREEXTPROC __glewBindTextureEXT = NULL; +PFNGLDELETETEXTURESEXTPROC __glewDeleteTexturesEXT = NULL; +PFNGLGENTEXTURESEXTPROC __glewGenTexturesEXT = NULL; +PFNGLISTEXTUREEXTPROC __glewIsTextureEXT = NULL; +PFNGLPRIORITIZETEXTURESEXTPROC __glewPrioritizeTexturesEXT = NULL; + +PFNGLTEXTURENORMALEXTPROC __glewTextureNormalEXT = NULL; + +PFNGLGETQUERYOBJECTI64VEXTPROC __glewGetQueryObjecti64vEXT = NULL; +PFNGLGETQUERYOBJECTUI64VEXTPROC __glewGetQueryObjectui64vEXT = NULL; + +PFNGLBEGINTRANSFORMFEEDBACKEXTPROC __glewBeginTransformFeedbackEXT = NULL; +PFNGLBINDBUFFERBASEEXTPROC __glewBindBufferBaseEXT = NULL; +PFNGLBINDBUFFEROFFSETEXTPROC __glewBindBufferOffsetEXT = NULL; +PFNGLBINDBUFFERRANGEEXTPROC __glewBindBufferRangeEXT = NULL; +PFNGLENDTRANSFORMFEEDBACKEXTPROC __glewEndTransformFeedbackEXT = NULL; +PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC __glewGetTransformFeedbackVaryingEXT = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC __glewTransformFeedbackVaryingsEXT = NULL; + +PFNGLARRAYELEMENTEXTPROC __glewArrayElementEXT = NULL; +PFNGLCOLORPOINTEREXTPROC __glewColorPointerEXT = NULL; +PFNGLDRAWARRAYSEXTPROC __glewDrawArraysEXT = NULL; +PFNGLEDGEFLAGPOINTEREXTPROC __glewEdgeFlagPointerEXT = NULL; +PFNGLINDEXPOINTEREXTPROC __glewIndexPointerEXT = NULL; +PFNGLNORMALPOINTEREXTPROC __glewNormalPointerEXT = NULL; +PFNGLTEXCOORDPOINTEREXTPROC __glewTexCoordPointerEXT = NULL; +PFNGLVERTEXPOINTEREXTPROC __glewVertexPointerEXT = NULL; + +PFNGLGETVERTEXATTRIBLDVEXTPROC __glewGetVertexAttribLdvEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC __glewVertexArrayVertexAttribLOffsetEXT = NULL; +PFNGLVERTEXATTRIBL1DEXTPROC __glewVertexAttribL1dEXT = NULL; +PFNGLVERTEXATTRIBL1DVEXTPROC __glewVertexAttribL1dvEXT = NULL; +PFNGLVERTEXATTRIBL2DEXTPROC __glewVertexAttribL2dEXT = NULL; +PFNGLVERTEXATTRIBL2DVEXTPROC __glewVertexAttribL2dvEXT = NULL; +PFNGLVERTEXATTRIBL3DEXTPROC __glewVertexAttribL3dEXT = NULL; +PFNGLVERTEXATTRIBL3DVEXTPROC __glewVertexAttribL3dvEXT = NULL; +PFNGLVERTEXATTRIBL4DEXTPROC __glewVertexAttribL4dEXT = NULL; +PFNGLVERTEXATTRIBL4DVEXTPROC __glewVertexAttribL4dvEXT = NULL; +PFNGLVERTEXATTRIBLPOINTEREXTPROC __glewVertexAttribLPointerEXT = NULL; + +PFNGLBEGINVERTEXSHADEREXTPROC __glewBeginVertexShaderEXT = NULL; +PFNGLBINDLIGHTPARAMETEREXTPROC __glewBindLightParameterEXT = NULL; +PFNGLBINDMATERIALPARAMETEREXTPROC __glewBindMaterialParameterEXT = NULL; +PFNGLBINDPARAMETEREXTPROC __glewBindParameterEXT = NULL; +PFNGLBINDTEXGENPARAMETEREXTPROC __glewBindTexGenParameterEXT = NULL; +PFNGLBINDTEXTUREUNITPARAMETEREXTPROC __glewBindTextureUnitParameterEXT = NULL; +PFNGLBINDVERTEXSHADEREXTPROC __glewBindVertexShaderEXT = NULL; +PFNGLDELETEVERTEXSHADEREXTPROC __glewDeleteVertexShaderEXT = NULL; +PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC __glewDisableVariantClientStateEXT = NULL; +PFNGLENABLEVARIANTCLIENTSTATEEXTPROC __glewEnableVariantClientStateEXT = NULL; +PFNGLENDVERTEXSHADEREXTPROC __glewEndVertexShaderEXT = NULL; +PFNGLEXTRACTCOMPONENTEXTPROC __glewExtractComponentEXT = NULL; +PFNGLGENSYMBOLSEXTPROC __glewGenSymbolsEXT = NULL; +PFNGLGENVERTEXSHADERSEXTPROC __glewGenVertexShadersEXT = NULL; +PFNGLGETINVARIANTBOOLEANVEXTPROC __glewGetInvariantBooleanvEXT = NULL; +PFNGLGETINVARIANTFLOATVEXTPROC __glewGetInvariantFloatvEXT = NULL; +PFNGLGETINVARIANTINTEGERVEXTPROC __glewGetInvariantIntegervEXT = NULL; +PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC __glewGetLocalConstantBooleanvEXT = NULL; +PFNGLGETLOCALCONSTANTFLOATVEXTPROC __glewGetLocalConstantFloatvEXT = NULL; +PFNGLGETLOCALCONSTANTINTEGERVEXTPROC __glewGetLocalConstantIntegervEXT = NULL; +PFNGLGETVARIANTBOOLEANVEXTPROC __glewGetVariantBooleanvEXT = NULL; +PFNGLGETVARIANTFLOATVEXTPROC __glewGetVariantFloatvEXT = NULL; +PFNGLGETVARIANTINTEGERVEXTPROC __glewGetVariantIntegervEXT = NULL; +PFNGLGETVARIANTPOINTERVEXTPROC __glewGetVariantPointervEXT = NULL; +PFNGLINSERTCOMPONENTEXTPROC __glewInsertComponentEXT = NULL; +PFNGLISVARIANTENABLEDEXTPROC __glewIsVariantEnabledEXT = NULL; +PFNGLSETINVARIANTEXTPROC __glewSetInvariantEXT = NULL; +PFNGLSETLOCALCONSTANTEXTPROC __glewSetLocalConstantEXT = NULL; +PFNGLSHADEROP1EXTPROC __glewShaderOp1EXT = NULL; +PFNGLSHADEROP2EXTPROC __glewShaderOp2EXT = NULL; +PFNGLSHADEROP3EXTPROC __glewShaderOp3EXT = NULL; +PFNGLSWIZZLEEXTPROC __glewSwizzleEXT = NULL; +PFNGLVARIANTPOINTEREXTPROC __glewVariantPointerEXT = NULL; +PFNGLVARIANTBVEXTPROC __glewVariantbvEXT = NULL; +PFNGLVARIANTDVEXTPROC __glewVariantdvEXT = NULL; +PFNGLVARIANTFVEXTPROC __glewVariantfvEXT = NULL; +PFNGLVARIANTIVEXTPROC __glewVariantivEXT = NULL; +PFNGLVARIANTSVEXTPROC __glewVariantsvEXT = NULL; +PFNGLVARIANTUBVEXTPROC __glewVariantubvEXT = NULL; +PFNGLVARIANTUIVEXTPROC __glewVariantuivEXT = NULL; +PFNGLVARIANTUSVEXTPROC __glewVariantusvEXT = NULL; +PFNGLWRITEMASKEXTPROC __glewWriteMaskEXT = NULL; + +PFNGLVERTEXWEIGHTPOINTEREXTPROC __glewVertexWeightPointerEXT = NULL; +PFNGLVERTEXWEIGHTFEXTPROC __glewVertexWeightfEXT = NULL; +PFNGLVERTEXWEIGHTFVEXTPROC __glewVertexWeightfvEXT = NULL; + +PFNGLIMPORTSYNCEXTPROC __glewImportSyncEXT = NULL; + +PFNGLFRAMETERMINATORGREMEDYPROC __glewFrameTerminatorGREMEDY = NULL; + +PFNGLSTRINGMARKERGREMEDYPROC __glewStringMarkerGREMEDY = NULL; + +PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC __glewGetImageTransformParameterfvHP = NULL; +PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC __glewGetImageTransformParameterivHP = NULL; +PFNGLIMAGETRANSFORMPARAMETERFHPPROC __glewImageTransformParameterfHP = NULL; +PFNGLIMAGETRANSFORMPARAMETERFVHPPROC __glewImageTransformParameterfvHP = NULL; +PFNGLIMAGETRANSFORMPARAMETERIHPPROC __glewImageTransformParameteriHP = NULL; +PFNGLIMAGETRANSFORMPARAMETERIVHPPROC __glewImageTransformParameterivHP = NULL; + +PFNGLMULTIMODEDRAWARRAYSIBMPROC __glewMultiModeDrawArraysIBM = NULL; +PFNGLMULTIMODEDRAWELEMENTSIBMPROC __glewMultiModeDrawElementsIBM = NULL; + +PFNGLCOLORPOINTERLISTIBMPROC __glewColorPointerListIBM = NULL; +PFNGLEDGEFLAGPOINTERLISTIBMPROC __glewEdgeFlagPointerListIBM = NULL; +PFNGLFOGCOORDPOINTERLISTIBMPROC __glewFogCoordPointerListIBM = NULL; +PFNGLINDEXPOINTERLISTIBMPROC __glewIndexPointerListIBM = NULL; +PFNGLNORMALPOINTERLISTIBMPROC __glewNormalPointerListIBM = NULL; +PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM = NULL; +PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM = NULL; +PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM = NULL; + +PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL = NULL; +PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL = NULL; +PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL = NULL; +PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL = NULL; + +PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL = NULL; +PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL = NULL; + +PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT = NULL; +PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT = NULL; +PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT = NULL; +PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT = NULL; +PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT = NULL; + +PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA = NULL; + +PFNGLWINDOWPOS2DMESAPROC __glewWindowPos2dMESA = NULL; +PFNGLWINDOWPOS2DVMESAPROC __glewWindowPos2dvMESA = NULL; +PFNGLWINDOWPOS2FMESAPROC __glewWindowPos2fMESA = NULL; +PFNGLWINDOWPOS2FVMESAPROC __glewWindowPos2fvMESA = NULL; +PFNGLWINDOWPOS2IMESAPROC __glewWindowPos2iMESA = NULL; +PFNGLWINDOWPOS2IVMESAPROC __glewWindowPos2ivMESA = NULL; +PFNGLWINDOWPOS2SMESAPROC __glewWindowPos2sMESA = NULL; +PFNGLWINDOWPOS2SVMESAPROC __glewWindowPos2svMESA = NULL; +PFNGLWINDOWPOS3DMESAPROC __glewWindowPos3dMESA = NULL; +PFNGLWINDOWPOS3DVMESAPROC __glewWindowPos3dvMESA = NULL; +PFNGLWINDOWPOS3FMESAPROC __glewWindowPos3fMESA = NULL; +PFNGLWINDOWPOS3FVMESAPROC __glewWindowPos3fvMESA = NULL; +PFNGLWINDOWPOS3IMESAPROC __glewWindowPos3iMESA = NULL; +PFNGLWINDOWPOS3IVMESAPROC __glewWindowPos3ivMESA = NULL; +PFNGLWINDOWPOS3SMESAPROC __glewWindowPos3sMESA = NULL; +PFNGLWINDOWPOS3SVMESAPROC __glewWindowPos3svMESA = NULL; +PFNGLWINDOWPOS4DMESAPROC __glewWindowPos4dMESA = NULL; +PFNGLWINDOWPOS4DVMESAPROC __glewWindowPos4dvMESA = NULL; +PFNGLWINDOWPOS4FMESAPROC __glewWindowPos4fMESA = NULL; +PFNGLWINDOWPOS4FVMESAPROC __glewWindowPos4fvMESA = NULL; +PFNGLWINDOWPOS4IMESAPROC __glewWindowPos4iMESA = NULL; +PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA = NULL; +PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA = NULL; +PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA = NULL; + +PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV = NULL; +PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV = NULL; + +PFNGLCOPYIMAGESUBDATANVPROC __glewCopyImageSubDataNV = NULL; + +PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV = NULL; +PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV = NULL; +PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV = NULL; + +PFNGLEVALMAPSNVPROC __glewEvalMapsNV = NULL; +PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV = NULL; +PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV = NULL; +PFNGLGETMAPCONTROLPOINTSNVPROC __glewGetMapControlPointsNV = NULL; +PFNGLGETMAPPARAMETERFVNVPROC __glewGetMapParameterfvNV = NULL; +PFNGLGETMAPPARAMETERIVNVPROC __glewGetMapParameterivNV = NULL; +PFNGLMAPCONTROLPOINTSNVPROC __glewMapControlPointsNV = NULL; +PFNGLMAPPARAMETERFVNVPROC __glewMapParameterfvNV = NULL; +PFNGLMAPPARAMETERIVNVPROC __glewMapParameterivNV = NULL; + +PFNGLGETMULTISAMPLEFVNVPROC __glewGetMultisamplefvNV = NULL; +PFNGLSAMPLEMASKINDEXEDNVPROC __glewSampleMaskIndexedNV = NULL; +PFNGLTEXRENDERBUFFERNVPROC __glewTexRenderbufferNV = NULL; + +PFNGLDELETEFENCESNVPROC __glewDeleteFencesNV = NULL; +PFNGLFINISHFENCENVPROC __glewFinishFenceNV = NULL; +PFNGLGENFENCESNVPROC __glewGenFencesNV = NULL; +PFNGLGETFENCEIVNVPROC __glewGetFenceivNV = NULL; +PFNGLISFENCENVPROC __glewIsFenceNV = NULL; +PFNGLSETFENCENVPROC __glewSetFenceNV = NULL; +PFNGLTESTFENCENVPROC __glewTestFenceNV = NULL; + +PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC __glewGetProgramNamedParameterdvNV = NULL; +PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC __glewGetProgramNamedParameterfvNV = NULL; +PFNGLPROGRAMNAMEDPARAMETER4DNVPROC __glewProgramNamedParameter4dNV = NULL; +PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC __glewProgramNamedParameter4dvNV = NULL; +PFNGLPROGRAMNAMEDPARAMETER4FNVPROC __glewProgramNamedParameter4fNV = NULL; +PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC __glewProgramNamedParameter4fvNV = NULL; + +PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC __glewRenderbufferStorageMultisampleCoverageNV = NULL; + +PFNGLPROGRAMVERTEXLIMITNVPROC __glewProgramVertexLimitNV = NULL; + +PFNGLPROGRAMENVPARAMETERI4INVPROC __glewProgramEnvParameterI4iNV = NULL; +PFNGLPROGRAMENVPARAMETERI4IVNVPROC __glewProgramEnvParameterI4ivNV = NULL; +PFNGLPROGRAMENVPARAMETERI4UINVPROC __glewProgramEnvParameterI4uiNV = NULL; +PFNGLPROGRAMENVPARAMETERI4UIVNVPROC __glewProgramEnvParameterI4uivNV = NULL; +PFNGLPROGRAMENVPARAMETERSI4IVNVPROC __glewProgramEnvParametersI4ivNV = NULL; +PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC __glewProgramEnvParametersI4uivNV = NULL; +PFNGLPROGRAMLOCALPARAMETERI4INVPROC __glewProgramLocalParameterI4iNV = NULL; +PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC __glewProgramLocalParameterI4ivNV = NULL; +PFNGLPROGRAMLOCALPARAMETERI4UINVPROC __glewProgramLocalParameterI4uiNV = NULL; +PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC __glewProgramLocalParameterI4uivNV = NULL; +PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC __glewProgramLocalParametersI4ivNV = NULL; +PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC __glewProgramLocalParametersI4uivNV = NULL; + +PFNGLGETUNIFORMI64VNVPROC __glewGetUniformi64vNV = NULL; +PFNGLGETUNIFORMUI64VNVPROC __glewGetUniformui64vNV = NULL; +PFNGLPROGRAMUNIFORM1I64NVPROC __glewProgramUniform1i64NV = NULL; +PFNGLPROGRAMUNIFORM1I64VNVPROC __glewProgramUniform1i64vNV = NULL; +PFNGLPROGRAMUNIFORM1UI64NVPROC __glewProgramUniform1ui64NV = NULL; +PFNGLPROGRAMUNIFORM1UI64VNVPROC __glewProgramUniform1ui64vNV = NULL; +PFNGLPROGRAMUNIFORM2I64NVPROC __glewProgramUniform2i64NV = NULL; +PFNGLPROGRAMUNIFORM2I64VNVPROC __glewProgramUniform2i64vNV = NULL; +PFNGLPROGRAMUNIFORM2UI64NVPROC __glewProgramUniform2ui64NV = NULL; +PFNGLPROGRAMUNIFORM2UI64VNVPROC __glewProgramUniform2ui64vNV = NULL; +PFNGLPROGRAMUNIFORM3I64NVPROC __glewProgramUniform3i64NV = NULL; +PFNGLPROGRAMUNIFORM3I64VNVPROC __glewProgramUniform3i64vNV = NULL; +PFNGLPROGRAMUNIFORM3UI64NVPROC __glewProgramUniform3ui64NV = NULL; +PFNGLPROGRAMUNIFORM3UI64VNVPROC __glewProgramUniform3ui64vNV = NULL; +PFNGLPROGRAMUNIFORM4I64NVPROC __glewProgramUniform4i64NV = NULL; +PFNGLPROGRAMUNIFORM4I64VNVPROC __glewProgramUniform4i64vNV = NULL; +PFNGLPROGRAMUNIFORM4UI64NVPROC __glewProgramUniform4ui64NV = NULL; +PFNGLPROGRAMUNIFORM4UI64VNVPROC __glewProgramUniform4ui64vNV = NULL; +PFNGLUNIFORM1I64NVPROC __glewUniform1i64NV = NULL; +PFNGLUNIFORM1I64VNVPROC __glewUniform1i64vNV = NULL; +PFNGLUNIFORM1UI64NVPROC __glewUniform1ui64NV = NULL; +PFNGLUNIFORM1UI64VNVPROC __glewUniform1ui64vNV = NULL; +PFNGLUNIFORM2I64NVPROC __glewUniform2i64NV = NULL; +PFNGLUNIFORM2I64VNVPROC __glewUniform2i64vNV = NULL; +PFNGLUNIFORM2UI64NVPROC __glewUniform2ui64NV = NULL; +PFNGLUNIFORM2UI64VNVPROC __glewUniform2ui64vNV = NULL; +PFNGLUNIFORM3I64NVPROC __glewUniform3i64NV = NULL; +PFNGLUNIFORM3I64VNVPROC __glewUniform3i64vNV = NULL; +PFNGLUNIFORM3UI64NVPROC __glewUniform3ui64NV = NULL; +PFNGLUNIFORM3UI64VNVPROC __glewUniform3ui64vNV = NULL; +PFNGLUNIFORM4I64NVPROC __glewUniform4i64NV = NULL; +PFNGLUNIFORM4I64VNVPROC __glewUniform4i64vNV = NULL; +PFNGLUNIFORM4UI64NVPROC __glewUniform4ui64NV = NULL; +PFNGLUNIFORM4UI64VNVPROC __glewUniform4ui64vNV = NULL; + +PFNGLCOLOR3HNVPROC __glewColor3hNV = NULL; +PFNGLCOLOR3HVNVPROC __glewColor3hvNV = NULL; +PFNGLCOLOR4HNVPROC __glewColor4hNV = NULL; +PFNGLCOLOR4HVNVPROC __glewColor4hvNV = NULL; +PFNGLFOGCOORDHNVPROC __glewFogCoordhNV = NULL; +PFNGLFOGCOORDHVNVPROC __glewFogCoordhvNV = NULL; +PFNGLMULTITEXCOORD1HNVPROC __glewMultiTexCoord1hNV = NULL; +PFNGLMULTITEXCOORD1HVNVPROC __glewMultiTexCoord1hvNV = NULL; +PFNGLMULTITEXCOORD2HNVPROC __glewMultiTexCoord2hNV = NULL; +PFNGLMULTITEXCOORD2HVNVPROC __glewMultiTexCoord2hvNV = NULL; +PFNGLMULTITEXCOORD3HNVPROC __glewMultiTexCoord3hNV = NULL; +PFNGLMULTITEXCOORD3HVNVPROC __glewMultiTexCoord3hvNV = NULL; +PFNGLMULTITEXCOORD4HNVPROC __glewMultiTexCoord4hNV = NULL; +PFNGLMULTITEXCOORD4HVNVPROC __glewMultiTexCoord4hvNV = NULL; +PFNGLNORMAL3HNVPROC __glewNormal3hNV = NULL; +PFNGLNORMAL3HVNVPROC __glewNormal3hvNV = NULL; +PFNGLSECONDARYCOLOR3HNVPROC __glewSecondaryColor3hNV = NULL; +PFNGLSECONDARYCOLOR3HVNVPROC __glewSecondaryColor3hvNV = NULL; +PFNGLTEXCOORD1HNVPROC __glewTexCoord1hNV = NULL; +PFNGLTEXCOORD1HVNVPROC __glewTexCoord1hvNV = NULL; +PFNGLTEXCOORD2HNVPROC __glewTexCoord2hNV = NULL; +PFNGLTEXCOORD2HVNVPROC __glewTexCoord2hvNV = NULL; +PFNGLTEXCOORD3HNVPROC __glewTexCoord3hNV = NULL; +PFNGLTEXCOORD3HVNVPROC __glewTexCoord3hvNV = NULL; +PFNGLTEXCOORD4HNVPROC __glewTexCoord4hNV = NULL; +PFNGLTEXCOORD4HVNVPROC __glewTexCoord4hvNV = NULL; +PFNGLVERTEX2HNVPROC __glewVertex2hNV = NULL; +PFNGLVERTEX2HVNVPROC __glewVertex2hvNV = NULL; +PFNGLVERTEX3HNVPROC __glewVertex3hNV = NULL; +PFNGLVERTEX3HVNVPROC __glewVertex3hvNV = NULL; +PFNGLVERTEX4HNVPROC __glewVertex4hNV = NULL; +PFNGLVERTEX4HVNVPROC __glewVertex4hvNV = NULL; +PFNGLVERTEXATTRIB1HNVPROC __glewVertexAttrib1hNV = NULL; +PFNGLVERTEXATTRIB1HVNVPROC __glewVertexAttrib1hvNV = NULL; +PFNGLVERTEXATTRIB2HNVPROC __glewVertexAttrib2hNV = NULL; +PFNGLVERTEXATTRIB2HVNVPROC __glewVertexAttrib2hvNV = NULL; +PFNGLVERTEXATTRIB3HNVPROC __glewVertexAttrib3hNV = NULL; +PFNGLVERTEXATTRIB3HVNVPROC __glewVertexAttrib3hvNV = NULL; +PFNGLVERTEXATTRIB4HNVPROC __glewVertexAttrib4hNV = NULL; +PFNGLVERTEXATTRIB4HVNVPROC __glewVertexAttrib4hvNV = NULL; +PFNGLVERTEXATTRIBS1HVNVPROC __glewVertexAttribs1hvNV = NULL; +PFNGLVERTEXATTRIBS2HVNVPROC __glewVertexAttribs2hvNV = NULL; +PFNGLVERTEXATTRIBS3HVNVPROC __glewVertexAttribs3hvNV = NULL; +PFNGLVERTEXATTRIBS4HVNVPROC __glewVertexAttribs4hvNV = NULL; +PFNGLVERTEXWEIGHTHNVPROC __glewVertexWeighthNV = NULL; +PFNGLVERTEXWEIGHTHVNVPROC __glewVertexWeighthvNV = NULL; + +PFNGLBEGINOCCLUSIONQUERYNVPROC __glewBeginOcclusionQueryNV = NULL; +PFNGLDELETEOCCLUSIONQUERIESNVPROC __glewDeleteOcclusionQueriesNV = NULL; +PFNGLENDOCCLUSIONQUERYNVPROC __glewEndOcclusionQueryNV = NULL; +PFNGLGENOCCLUSIONQUERIESNVPROC __glewGenOcclusionQueriesNV = NULL; +PFNGLGETOCCLUSIONQUERYIVNVPROC __glewGetOcclusionQueryivNV = NULL; +PFNGLGETOCCLUSIONQUERYUIVNVPROC __glewGetOcclusionQueryuivNV = NULL; +PFNGLISOCCLUSIONQUERYNVPROC __glewIsOcclusionQueryNV = NULL; + +PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV = NULL; +PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV = NULL; +PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV = NULL; + +PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV = NULL; +PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV = NULL; + +PFNGLPOINTPARAMETERINVPROC __glewPointParameteriNV = NULL; +PFNGLPOINTPARAMETERIVNVPROC __glewPointParameterivNV = NULL; + +PFNGLGETVIDEOI64VNVPROC __glewGetVideoi64vNV = NULL; +PFNGLGETVIDEOIVNVPROC __glewGetVideoivNV = NULL; +PFNGLGETVIDEOUI64VNVPROC __glewGetVideoui64vNV = NULL; +PFNGLGETVIDEOUIVNVPROC __glewGetVideouivNV = NULL; +PFNGLPRESENTFRAMEDUALFILLNVPROC __glewPresentFrameDualFillNV = NULL; +PFNGLPRESENTFRAMEKEYEDNVPROC __glewPresentFrameKeyedNV = NULL; + +PFNGLPRIMITIVERESTARTINDEXNVPROC __glewPrimitiveRestartIndexNV = NULL; +PFNGLPRIMITIVERESTARTNVPROC __glewPrimitiveRestartNV = NULL; + +PFNGLCOMBINERINPUTNVPROC __glewCombinerInputNV = NULL; +PFNGLCOMBINEROUTPUTNVPROC __glewCombinerOutputNV = NULL; +PFNGLCOMBINERPARAMETERFNVPROC __glewCombinerParameterfNV = NULL; +PFNGLCOMBINERPARAMETERFVNVPROC __glewCombinerParameterfvNV = NULL; +PFNGLCOMBINERPARAMETERINVPROC __glewCombinerParameteriNV = NULL; +PFNGLCOMBINERPARAMETERIVNVPROC __glewCombinerParameterivNV = NULL; +PFNGLFINALCOMBINERINPUTNVPROC __glewFinalCombinerInputNV = NULL; +PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC __glewGetCombinerInputParameterfvNV = NULL; +PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC __glewGetCombinerInputParameterivNV = NULL; +PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC __glewGetCombinerOutputParameterfvNV = NULL; +PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC __glewGetCombinerOutputParameterivNV = NULL; +PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC __glewGetFinalCombinerInputParameterfvNV = NULL; +PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC __glewGetFinalCombinerInputParameterivNV = NULL; + +PFNGLCOMBINERSTAGEPARAMETERFVNVPROC __glewCombinerStageParameterfvNV = NULL; +PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC __glewGetCombinerStageParameterfvNV = NULL; + +PFNGLGETBUFFERPARAMETERUI64VNVPROC __glewGetBufferParameterui64vNV = NULL; +PFNGLGETINTEGERUI64VNVPROC __glewGetIntegerui64vNV = NULL; +PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC __glewGetNamedBufferParameterui64vNV = NULL; +PFNGLISBUFFERRESIDENTNVPROC __glewIsBufferResidentNV = NULL; +PFNGLISNAMEDBUFFERRESIDENTNVPROC __glewIsNamedBufferResidentNV = NULL; +PFNGLMAKEBUFFERNONRESIDENTNVPROC __glewMakeBufferNonResidentNV = NULL; +PFNGLMAKEBUFFERRESIDENTNVPROC __glewMakeBufferResidentNV = NULL; +PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC __glewMakeNamedBufferNonResidentNV = NULL; +PFNGLMAKENAMEDBUFFERRESIDENTNVPROC __glewMakeNamedBufferResidentNV = NULL; +PFNGLPROGRAMUNIFORMUI64NVPROC __glewProgramUniformui64NV = NULL; +PFNGLPROGRAMUNIFORMUI64VNVPROC __glewProgramUniformui64vNV = NULL; +PFNGLUNIFORMUI64NVPROC __glewUniformui64NV = NULL; +PFNGLUNIFORMUI64VNVPROC __glewUniformui64vNV = NULL; + +PFNGLTEXTUREBARRIERNVPROC __glewTextureBarrierNV = NULL; + +PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTexImage2DMultisampleCoverageNV = NULL; +PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTexImage3DMultisampleCoverageNV = NULL; +PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC __glewTextureImage2DMultisampleCoverageNV = NULL; +PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC __glewTextureImage2DMultisampleNV = NULL; +PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC __glewTextureImage3DMultisampleCoverageNV = NULL; +PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC __glewTextureImage3DMultisampleNV = NULL; + +PFNGLACTIVEVARYINGNVPROC __glewActiveVaryingNV = NULL; +PFNGLBEGINTRANSFORMFEEDBACKNVPROC __glewBeginTransformFeedbackNV = NULL; +PFNGLBINDBUFFERBASENVPROC __glewBindBufferBaseNV = NULL; +PFNGLBINDBUFFEROFFSETNVPROC __glewBindBufferOffsetNV = NULL; +PFNGLBINDBUFFERRANGENVPROC __glewBindBufferRangeNV = NULL; +PFNGLENDTRANSFORMFEEDBACKNVPROC __glewEndTransformFeedbackNV = NULL; +PFNGLGETACTIVEVARYINGNVPROC __glewGetActiveVaryingNV = NULL; +PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC __glewGetTransformFeedbackVaryingNV = NULL; +PFNGLGETVARYINGLOCATIONNVPROC __glewGetVaryingLocationNV = NULL; +PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC __glewTransformFeedbackAttribsNV = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC __glewTransformFeedbackVaryingsNV = NULL; + +PFNGLBINDTRANSFORMFEEDBACKNVPROC __glewBindTransformFeedbackNV = NULL; +PFNGLDELETETRANSFORMFEEDBACKSNVPROC __glewDeleteTransformFeedbacksNV = NULL; +PFNGLDRAWTRANSFORMFEEDBACKNVPROC __glewDrawTransformFeedbackNV = NULL; +PFNGLGENTRANSFORMFEEDBACKSNVPROC __glewGenTransformFeedbacksNV = NULL; +PFNGLISTRANSFORMFEEDBACKNVPROC __glewIsTransformFeedbackNV = NULL; +PFNGLPAUSETRANSFORMFEEDBACKNVPROC __glewPauseTransformFeedbackNV = NULL; +PFNGLRESUMETRANSFORMFEEDBACKNVPROC __glewResumeTransformFeedbackNV = NULL; + +PFNGLVDPAUFININVPROC __glewVDPAUFiniNV = NULL; +PFNGLVDPAUGETSURFACEIVNVPROC __glewVDPAUGetSurfaceivNV = NULL; +PFNGLVDPAUINITNVPROC __glewVDPAUInitNV = NULL; +PFNGLVDPAUISSURFACENVPROC __glewVDPAUIsSurfaceNV = NULL; +PFNGLVDPAUMAPSURFACESNVPROC __glewVDPAUMapSurfacesNV = NULL; +PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC __glewVDPAURegisterOutputSurfaceNV = NULL; +PFNGLVDPAUREGISTERVIDEOSURFACENVPROC __glewVDPAURegisterVideoSurfaceNV = NULL; +PFNGLVDPAUSURFACEACCESSNVPROC __glewVDPAUSurfaceAccessNV = NULL; +PFNGLVDPAUUNMAPSURFACESNVPROC __glewVDPAUUnmapSurfacesNV = NULL; +PFNGLVDPAUUNREGISTERSURFACENVPROC __glewVDPAUUnregisterSurfaceNV = NULL; + +PFNGLFLUSHVERTEXARRAYRANGENVPROC __glewFlushVertexArrayRangeNV = NULL; +PFNGLVERTEXARRAYRANGENVPROC __glewVertexArrayRangeNV = NULL; + +PFNGLGETVERTEXATTRIBLI64VNVPROC __glewGetVertexAttribLi64vNV = NULL; +PFNGLGETVERTEXATTRIBLUI64VNVPROC __glewGetVertexAttribLui64vNV = NULL; +PFNGLVERTEXATTRIBL1I64NVPROC __glewVertexAttribL1i64NV = NULL; +PFNGLVERTEXATTRIBL1I64VNVPROC __glewVertexAttribL1i64vNV = NULL; +PFNGLVERTEXATTRIBL1UI64NVPROC __glewVertexAttribL1ui64NV = NULL; +PFNGLVERTEXATTRIBL1UI64VNVPROC __glewVertexAttribL1ui64vNV = NULL; +PFNGLVERTEXATTRIBL2I64NVPROC __glewVertexAttribL2i64NV = NULL; +PFNGLVERTEXATTRIBL2I64VNVPROC __glewVertexAttribL2i64vNV = NULL; +PFNGLVERTEXATTRIBL2UI64NVPROC __glewVertexAttribL2ui64NV = NULL; +PFNGLVERTEXATTRIBL2UI64VNVPROC __glewVertexAttribL2ui64vNV = NULL; +PFNGLVERTEXATTRIBL3I64NVPROC __glewVertexAttribL3i64NV = NULL; +PFNGLVERTEXATTRIBL3I64VNVPROC __glewVertexAttribL3i64vNV = NULL; +PFNGLVERTEXATTRIBL3UI64NVPROC __glewVertexAttribL3ui64NV = NULL; +PFNGLVERTEXATTRIBL3UI64VNVPROC __glewVertexAttribL3ui64vNV = NULL; +PFNGLVERTEXATTRIBL4I64NVPROC __glewVertexAttribL4i64NV = NULL; +PFNGLVERTEXATTRIBL4I64VNVPROC __glewVertexAttribL4i64vNV = NULL; +PFNGLVERTEXATTRIBL4UI64NVPROC __glewVertexAttribL4ui64NV = NULL; +PFNGLVERTEXATTRIBL4UI64VNVPROC __glewVertexAttribL4ui64vNV = NULL; +PFNGLVERTEXATTRIBLFORMATNVPROC __glewVertexAttribLFormatNV = NULL; + +PFNGLBUFFERADDRESSRANGENVPROC __glewBufferAddressRangeNV = NULL; +PFNGLCOLORFORMATNVPROC __glewColorFormatNV = NULL; +PFNGLEDGEFLAGFORMATNVPROC __glewEdgeFlagFormatNV = NULL; +PFNGLFOGCOORDFORMATNVPROC __glewFogCoordFormatNV = NULL; +PFNGLGETINTEGERUI64I_VNVPROC __glewGetIntegerui64i_vNV = NULL; +PFNGLINDEXFORMATNVPROC __glewIndexFormatNV = NULL; +PFNGLNORMALFORMATNVPROC __glewNormalFormatNV = NULL; +PFNGLSECONDARYCOLORFORMATNVPROC __glewSecondaryColorFormatNV = NULL; +PFNGLTEXCOORDFORMATNVPROC __glewTexCoordFormatNV = NULL; +PFNGLVERTEXATTRIBFORMATNVPROC __glewVertexAttribFormatNV = NULL; +PFNGLVERTEXATTRIBIFORMATNVPROC __glewVertexAttribIFormatNV = NULL; +PFNGLVERTEXFORMATNVPROC __glewVertexFormatNV = NULL; + +PFNGLAREPROGRAMSRESIDENTNVPROC __glewAreProgramsResidentNV = NULL; +PFNGLBINDPROGRAMNVPROC __glewBindProgramNV = NULL; +PFNGLDELETEPROGRAMSNVPROC __glewDeleteProgramsNV = NULL; +PFNGLEXECUTEPROGRAMNVPROC __glewExecuteProgramNV = NULL; +PFNGLGENPROGRAMSNVPROC __glewGenProgramsNV = NULL; +PFNGLGETPROGRAMPARAMETERDVNVPROC __glewGetProgramParameterdvNV = NULL; +PFNGLGETPROGRAMPARAMETERFVNVPROC __glewGetProgramParameterfvNV = NULL; +PFNGLGETPROGRAMSTRINGNVPROC __glewGetProgramStringNV = NULL; +PFNGLGETPROGRAMIVNVPROC __glewGetProgramivNV = NULL; +PFNGLGETTRACKMATRIXIVNVPROC __glewGetTrackMatrixivNV = NULL; +PFNGLGETVERTEXATTRIBPOINTERVNVPROC __glewGetVertexAttribPointervNV = NULL; +PFNGLGETVERTEXATTRIBDVNVPROC __glewGetVertexAttribdvNV = NULL; +PFNGLGETVERTEXATTRIBFVNVPROC __glewGetVertexAttribfvNV = NULL; +PFNGLGETVERTEXATTRIBIVNVPROC __glewGetVertexAttribivNV = NULL; +PFNGLISPROGRAMNVPROC __glewIsProgramNV = NULL; +PFNGLLOADPROGRAMNVPROC __glewLoadProgramNV = NULL; +PFNGLPROGRAMPARAMETER4DNVPROC __glewProgramParameter4dNV = NULL; +PFNGLPROGRAMPARAMETER4DVNVPROC __glewProgramParameter4dvNV = NULL; +PFNGLPROGRAMPARAMETER4FNVPROC __glewProgramParameter4fNV = NULL; +PFNGLPROGRAMPARAMETER4FVNVPROC __glewProgramParameter4fvNV = NULL; +PFNGLPROGRAMPARAMETERS4DVNVPROC __glewProgramParameters4dvNV = NULL; +PFNGLPROGRAMPARAMETERS4FVNVPROC __glewProgramParameters4fvNV = NULL; +PFNGLREQUESTRESIDENTPROGRAMSNVPROC __glewRequestResidentProgramsNV = NULL; +PFNGLTRACKMATRIXNVPROC __glewTrackMatrixNV = NULL; +PFNGLVERTEXATTRIB1DNVPROC __glewVertexAttrib1dNV = NULL; +PFNGLVERTEXATTRIB1DVNVPROC __glewVertexAttrib1dvNV = NULL; +PFNGLVERTEXATTRIB1FNVPROC __glewVertexAttrib1fNV = NULL; +PFNGLVERTEXATTRIB1FVNVPROC __glewVertexAttrib1fvNV = NULL; +PFNGLVERTEXATTRIB1SNVPROC __glewVertexAttrib1sNV = NULL; +PFNGLVERTEXATTRIB1SVNVPROC __glewVertexAttrib1svNV = NULL; +PFNGLVERTEXATTRIB2DNVPROC __glewVertexAttrib2dNV = NULL; +PFNGLVERTEXATTRIB2DVNVPROC __glewVertexAttrib2dvNV = NULL; +PFNGLVERTEXATTRIB2FNVPROC __glewVertexAttrib2fNV = NULL; +PFNGLVERTEXATTRIB2FVNVPROC __glewVertexAttrib2fvNV = NULL; +PFNGLVERTEXATTRIB2SNVPROC __glewVertexAttrib2sNV = NULL; +PFNGLVERTEXATTRIB2SVNVPROC __glewVertexAttrib2svNV = NULL; +PFNGLVERTEXATTRIB3DNVPROC __glewVertexAttrib3dNV = NULL; +PFNGLVERTEXATTRIB3DVNVPROC __glewVertexAttrib3dvNV = NULL; +PFNGLVERTEXATTRIB3FNVPROC __glewVertexAttrib3fNV = NULL; +PFNGLVERTEXATTRIB3FVNVPROC __glewVertexAttrib3fvNV = NULL; +PFNGLVERTEXATTRIB3SNVPROC __glewVertexAttrib3sNV = NULL; +PFNGLVERTEXATTRIB3SVNVPROC __glewVertexAttrib3svNV = NULL; +PFNGLVERTEXATTRIB4DNVPROC __glewVertexAttrib4dNV = NULL; +PFNGLVERTEXATTRIB4DVNVPROC __glewVertexAttrib4dvNV = NULL; +PFNGLVERTEXATTRIB4FNVPROC __glewVertexAttrib4fNV = NULL; +PFNGLVERTEXATTRIB4FVNVPROC __glewVertexAttrib4fvNV = NULL; +PFNGLVERTEXATTRIB4SNVPROC __glewVertexAttrib4sNV = NULL; +PFNGLVERTEXATTRIB4SVNVPROC __glewVertexAttrib4svNV = NULL; +PFNGLVERTEXATTRIB4UBNVPROC __glewVertexAttrib4ubNV = NULL; +PFNGLVERTEXATTRIB4UBVNVPROC __glewVertexAttrib4ubvNV = NULL; +PFNGLVERTEXATTRIBPOINTERNVPROC __glewVertexAttribPointerNV = NULL; +PFNGLVERTEXATTRIBS1DVNVPROC __glewVertexAttribs1dvNV = NULL; +PFNGLVERTEXATTRIBS1FVNVPROC __glewVertexAttribs1fvNV = NULL; +PFNGLVERTEXATTRIBS1SVNVPROC __glewVertexAttribs1svNV = NULL; +PFNGLVERTEXATTRIBS2DVNVPROC __glewVertexAttribs2dvNV = NULL; +PFNGLVERTEXATTRIBS2FVNVPROC __glewVertexAttribs2fvNV = NULL; +PFNGLVERTEXATTRIBS2SVNVPROC __glewVertexAttribs2svNV = NULL; +PFNGLVERTEXATTRIBS3DVNVPROC __glewVertexAttribs3dvNV = NULL; +PFNGLVERTEXATTRIBS3FVNVPROC __glewVertexAttribs3fvNV = NULL; +PFNGLVERTEXATTRIBS3SVNVPROC __glewVertexAttribs3svNV = NULL; +PFNGLVERTEXATTRIBS4DVNVPROC __glewVertexAttribs4dvNV = NULL; +PFNGLVERTEXATTRIBS4FVNVPROC __glewVertexAttribs4fvNV = NULL; +PFNGLVERTEXATTRIBS4SVNVPROC __glewVertexAttribs4svNV = NULL; +PFNGLVERTEXATTRIBS4UBVNVPROC __glewVertexAttribs4ubvNV = NULL; + +PFNGLBEGINVIDEOCAPTURENVPROC __glewBeginVideoCaptureNV = NULL; +PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC __glewBindVideoCaptureStreamBufferNV = NULL; +PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC __glewBindVideoCaptureStreamTextureNV = NULL; +PFNGLENDVIDEOCAPTURENVPROC __glewEndVideoCaptureNV = NULL; +PFNGLGETVIDEOCAPTURESTREAMDVNVPROC __glewGetVideoCaptureStreamdvNV = NULL; +PFNGLGETVIDEOCAPTURESTREAMFVNVPROC __glewGetVideoCaptureStreamfvNV = NULL; +PFNGLGETVIDEOCAPTURESTREAMIVNVPROC __glewGetVideoCaptureStreamivNV = NULL; +PFNGLGETVIDEOCAPTUREIVNVPROC __glewGetVideoCaptureivNV = NULL; +PFNGLVIDEOCAPTURENVPROC __glewVideoCaptureNV = NULL; +PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC __glewVideoCaptureStreamParameterdvNV = NULL; +PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC __glewVideoCaptureStreamParameterfvNV = NULL; +PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC __glewVideoCaptureStreamParameterivNV = NULL; + +PFNGLCLEARDEPTHFOESPROC __glewClearDepthfOES = NULL; +PFNGLCLIPPLANEFOESPROC __glewClipPlanefOES = NULL; +PFNGLDEPTHRANGEFOESPROC __glewDepthRangefOES = NULL; +PFNGLFRUSTUMFOESPROC __glewFrustumfOES = NULL; +PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES = NULL; +PFNGLORTHOFOESPROC __glewOrthofOES = NULL; + +PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS = NULL; +PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS = NULL; + +PFNGLFOGFUNCSGISPROC __glewFogFuncSGIS = NULL; +PFNGLGETFOGFUNCSGISPROC __glewGetFogFuncSGIS = NULL; + +PFNGLSAMPLEMASKSGISPROC __glewSampleMaskSGIS = NULL; +PFNGLSAMPLEPATTERNSGISPROC __glewSamplePatternSGIS = NULL; + +PFNGLGETSHARPENTEXFUNCSGISPROC __glewGetSharpenTexFuncSGIS = NULL; +PFNGLSHARPENTEXFUNCSGISPROC __glewSharpenTexFuncSGIS = NULL; + +PFNGLTEXIMAGE4DSGISPROC __glewTexImage4DSGIS = NULL; +PFNGLTEXSUBIMAGE4DSGISPROC __glewTexSubImage4DSGIS = NULL; + +PFNGLGETTEXFILTERFUNCSGISPROC __glewGetTexFilterFuncSGIS = NULL; +PFNGLTEXFILTERFUNCSGISPROC __glewTexFilterFuncSGIS = NULL; + +PFNGLASYNCMARKERSGIXPROC __glewAsyncMarkerSGIX = NULL; +PFNGLDELETEASYNCMARKERSSGIXPROC __glewDeleteAsyncMarkersSGIX = NULL; +PFNGLFINISHASYNCSGIXPROC __glewFinishAsyncSGIX = NULL; +PFNGLGENASYNCMARKERSSGIXPROC __glewGenAsyncMarkersSGIX = NULL; +PFNGLISASYNCMARKERSGIXPROC __glewIsAsyncMarkerSGIX = NULL; +PFNGLPOLLASYNCSGIXPROC __glewPollAsyncSGIX = NULL; + +PFNGLFLUSHRASTERSGIXPROC __glewFlushRasterSGIX = NULL; + +PFNGLTEXTUREFOGSGIXPROC __glewTextureFogSGIX = NULL; + +PFNGLFRAGMENTCOLORMATERIALSGIXPROC __glewFragmentColorMaterialSGIX = NULL; +PFNGLFRAGMENTLIGHTMODELFSGIXPROC __glewFragmentLightModelfSGIX = NULL; +PFNGLFRAGMENTLIGHTMODELFVSGIXPROC __glewFragmentLightModelfvSGIX = NULL; +PFNGLFRAGMENTLIGHTMODELISGIXPROC __glewFragmentLightModeliSGIX = NULL; +PFNGLFRAGMENTLIGHTMODELIVSGIXPROC __glewFragmentLightModelivSGIX = NULL; +PFNGLFRAGMENTLIGHTFSGIXPROC __glewFragmentLightfSGIX = NULL; +PFNGLFRAGMENTLIGHTFVSGIXPROC __glewFragmentLightfvSGIX = NULL; +PFNGLFRAGMENTLIGHTISGIXPROC __glewFragmentLightiSGIX = NULL; +PFNGLFRAGMENTLIGHTIVSGIXPROC __glewFragmentLightivSGIX = NULL; +PFNGLFRAGMENTMATERIALFSGIXPROC __glewFragmentMaterialfSGIX = NULL; +PFNGLFRAGMENTMATERIALFVSGIXPROC __glewFragmentMaterialfvSGIX = NULL; +PFNGLFRAGMENTMATERIALISGIXPROC __glewFragmentMaterialiSGIX = NULL; +PFNGLFRAGMENTMATERIALIVSGIXPROC __glewFragmentMaterialivSGIX = NULL; +PFNGLGETFRAGMENTLIGHTFVSGIXPROC __glewGetFragmentLightfvSGIX = NULL; +PFNGLGETFRAGMENTLIGHTIVSGIXPROC __glewGetFragmentLightivSGIX = NULL; +PFNGLGETFRAGMENTMATERIALFVSGIXPROC __glewGetFragmentMaterialfvSGIX = NULL; +PFNGLGETFRAGMENTMATERIALIVSGIXPROC __glewGetFragmentMaterialivSGIX = NULL; + +PFNGLFRAMEZOOMSGIXPROC __glewFrameZoomSGIX = NULL; + +PFNGLPIXELTEXGENSGIXPROC __glewPixelTexGenSGIX = NULL; + +PFNGLREFERENCEPLANESGIXPROC __glewReferencePlaneSGIX = NULL; + +PFNGLSPRITEPARAMETERFSGIXPROC __glewSpriteParameterfSGIX = NULL; +PFNGLSPRITEPARAMETERFVSGIXPROC __glewSpriteParameterfvSGIX = NULL; +PFNGLSPRITEPARAMETERISGIXPROC __glewSpriteParameteriSGIX = NULL; +PFNGLSPRITEPARAMETERIVSGIXPROC __glewSpriteParameterivSGIX = NULL; + +PFNGLTAGSAMPLEBUFFERSGIXPROC __glewTagSampleBufferSGIX = NULL; + +PFNGLCOLORTABLEPARAMETERFVSGIPROC __glewColorTableParameterfvSGI = NULL; +PFNGLCOLORTABLEPARAMETERIVSGIPROC __glewColorTableParameterivSGI = NULL; +PFNGLCOLORTABLESGIPROC __glewColorTableSGI = NULL; +PFNGLCOPYCOLORTABLESGIPROC __glewCopyColorTableSGI = NULL; +PFNGLGETCOLORTABLEPARAMETERFVSGIPROC __glewGetColorTableParameterfvSGI = NULL; +PFNGLGETCOLORTABLEPARAMETERIVSGIPROC __glewGetColorTableParameterivSGI = NULL; +PFNGLGETCOLORTABLESGIPROC __glewGetColorTableSGI = NULL; + +PFNGLFINISHTEXTURESUNXPROC __glewFinishTextureSUNX = NULL; + +PFNGLGLOBALALPHAFACTORBSUNPROC __glewGlobalAlphaFactorbSUN = NULL; +PFNGLGLOBALALPHAFACTORDSUNPROC __glewGlobalAlphaFactordSUN = NULL; +PFNGLGLOBALALPHAFACTORFSUNPROC __glewGlobalAlphaFactorfSUN = NULL; +PFNGLGLOBALALPHAFACTORISUNPROC __glewGlobalAlphaFactoriSUN = NULL; +PFNGLGLOBALALPHAFACTORSSUNPROC __glewGlobalAlphaFactorsSUN = NULL; +PFNGLGLOBALALPHAFACTORUBSUNPROC __glewGlobalAlphaFactorubSUN = NULL; +PFNGLGLOBALALPHAFACTORUISUNPROC __glewGlobalAlphaFactoruiSUN = NULL; +PFNGLGLOBALALPHAFACTORUSSUNPROC __glewGlobalAlphaFactorusSUN = NULL; + +PFNGLREADVIDEOPIXELSSUNPROC __glewReadVideoPixelsSUN = NULL; + +PFNGLREPLACEMENTCODEPOINTERSUNPROC __glewReplacementCodePointerSUN = NULL; +PFNGLREPLACEMENTCODEUBSUNPROC __glewReplacementCodeubSUN = NULL; +PFNGLREPLACEMENTCODEUBVSUNPROC __glewReplacementCodeubvSUN = NULL; +PFNGLREPLACEMENTCODEUISUNPROC __glewReplacementCodeuiSUN = NULL; +PFNGLREPLACEMENTCODEUIVSUNPROC __glewReplacementCodeuivSUN = NULL; +PFNGLREPLACEMENTCODEUSSUNPROC __glewReplacementCodeusSUN = NULL; +PFNGLREPLACEMENTCODEUSVSUNPROC __glewReplacementCodeusvSUN = NULL; + +PFNGLCOLOR3FVERTEX3FSUNPROC __glewColor3fVertex3fSUN = NULL; +PFNGLCOLOR3FVERTEX3FVSUNPROC __glewColor3fVertex3fvSUN = NULL; +PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewColor4fNormal3fVertex3fSUN = NULL; +PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewColor4fNormal3fVertex3fvSUN = NULL; +PFNGLCOLOR4UBVERTEX2FSUNPROC __glewColor4ubVertex2fSUN = NULL; +PFNGLCOLOR4UBVERTEX2FVSUNPROC __glewColor4ubVertex2fvSUN = NULL; +PFNGLCOLOR4UBVERTEX3FSUNPROC __glewColor4ubVertex3fSUN = NULL; +PFNGLCOLOR4UBVERTEX3FVSUNPROC __glewColor4ubVertex3fvSUN = NULL; +PFNGLNORMAL3FVERTEX3FSUNPROC __glewNormal3fVertex3fSUN = NULL; +PFNGLNORMAL3FVERTEX3FVSUNPROC __glewNormal3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC __glewReplacementCodeuiColor3fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiColor4fNormal3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC __glewReplacementCodeuiColor4ubVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC __glewReplacementCodeuiColor4ubVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiNormal3fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiNormal3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC __glewReplacementCodeuiTexCoord2fVertex3fvSUN = NULL; +PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC __glewReplacementCodeuiVertex3fSUN = NULL; +PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC __glewReplacementCodeuiVertex3fvSUN = NULL; +PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC __glewTexCoord2fColor3fVertex3fSUN = NULL; +PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC __glewTexCoord2fColor3fVertex3fvSUN = NULL; +PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fSUN = NULL; +PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fColor4fNormal3fVertex3fvSUN = NULL; +PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC __glewTexCoord2fColor4ubVertex3fSUN = NULL; +PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC __glewTexCoord2fColor4ubVertex3fvSUN = NULL; +PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC __glewTexCoord2fNormal3fVertex3fSUN = NULL; +PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC __glewTexCoord2fNormal3fVertex3fvSUN = NULL; +PFNGLTEXCOORD2FVERTEX3FSUNPROC __glewTexCoord2fVertex3fSUN = NULL; +PFNGLTEXCOORD2FVERTEX3FVSUNPROC __glewTexCoord2fVertex3fvSUN = NULL; +PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fSUN = NULL; +PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC __glewTexCoord4fColor4fNormal3fVertex4fvSUN = NULL; +PFNGLTEXCOORD4FVERTEX4FSUNPROC __glewTexCoord4fVertex4fSUN = NULL; +PFNGLTEXCOORD4FVERTEX4FVSUNPROC __glewTexCoord4fVertex4fvSUN = NULL; + +PFNGLADDSWAPHINTRECTWINPROC __glewAddSwapHintRectWIN = NULL; + +#endif /* !WIN32 || !GLEW_MX */ + +#if !defined(GLEW_MX) + +GLboolean __GLEW_VERSION_1_1 = GL_FALSE; +GLboolean __GLEW_VERSION_1_2 = GL_FALSE; +GLboolean __GLEW_VERSION_1_2_1 = GL_FALSE; +GLboolean __GLEW_VERSION_1_3 = GL_FALSE; +GLboolean __GLEW_VERSION_1_4 = GL_FALSE; +GLboolean __GLEW_VERSION_1_5 = GL_FALSE; +GLboolean __GLEW_VERSION_2_0 = GL_FALSE; +GLboolean __GLEW_VERSION_2_1 = GL_FALSE; +GLboolean __GLEW_VERSION_3_0 = GL_FALSE; +GLboolean __GLEW_VERSION_3_1 = GL_FALSE; +GLboolean __GLEW_VERSION_3_2 = GL_FALSE; +GLboolean __GLEW_VERSION_3_3 = GL_FALSE; +GLboolean __GLEW_VERSION_4_0 = GL_FALSE; +GLboolean __GLEW_VERSION_4_1 = GL_FALSE; +GLboolean __GLEW_3DFX_multisample = GL_FALSE; +GLboolean __GLEW_3DFX_tbuffer = GL_FALSE; +GLboolean __GLEW_3DFX_texture_compression_FXT1 = GL_FALSE; +GLboolean __GLEW_AMD_blend_minmax_factor = GL_FALSE; +GLboolean __GLEW_AMD_conservative_depth = GL_FALSE; +GLboolean __GLEW_AMD_debug_output = GL_FALSE; +GLboolean __GLEW_AMD_depth_clamp_separate = GL_FALSE; +GLboolean __GLEW_AMD_draw_buffers_blend = GL_FALSE; +GLboolean __GLEW_AMD_name_gen_delete = GL_FALSE; +GLboolean __GLEW_AMD_performance_monitor = GL_FALSE; +GLboolean __GLEW_AMD_sample_positions = GL_FALSE; +GLboolean __GLEW_AMD_seamless_cubemap_per_texture = GL_FALSE; +GLboolean __GLEW_AMD_shader_stencil_export = GL_FALSE; +GLboolean __GLEW_AMD_texture_texture4 = GL_FALSE; +GLboolean __GLEW_AMD_transform_feedback3_lines_triangles = GL_FALSE; +GLboolean __GLEW_AMD_vertex_shader_tessellator = GL_FALSE; +GLboolean __GLEW_APPLE_aux_depth_stencil = GL_FALSE; +GLboolean __GLEW_APPLE_client_storage = GL_FALSE; +GLboolean __GLEW_APPLE_element_array = GL_FALSE; +GLboolean __GLEW_APPLE_fence = GL_FALSE; +GLboolean __GLEW_APPLE_float_pixels = GL_FALSE; +GLboolean __GLEW_APPLE_flush_buffer_range = GL_FALSE; +GLboolean __GLEW_APPLE_object_purgeable = GL_FALSE; +GLboolean __GLEW_APPLE_pixel_buffer = GL_FALSE; +GLboolean __GLEW_APPLE_rgb_422 = GL_FALSE; +GLboolean __GLEW_APPLE_row_bytes = GL_FALSE; +GLboolean __GLEW_APPLE_specular_vector = GL_FALSE; +GLboolean __GLEW_APPLE_texture_range = GL_FALSE; +GLboolean __GLEW_APPLE_transform_hint = GL_FALSE; +GLboolean __GLEW_APPLE_vertex_array_object = GL_FALSE; +GLboolean __GLEW_APPLE_vertex_array_range = GL_FALSE; +GLboolean __GLEW_APPLE_vertex_program_evaluators = GL_FALSE; +GLboolean __GLEW_APPLE_ycbcr_422 = GL_FALSE; +GLboolean __GLEW_ARB_ES2_compatibility = GL_FALSE; +GLboolean __GLEW_ARB_blend_func_extended = GL_FALSE; +GLboolean __GLEW_ARB_cl_event = GL_FALSE; +GLboolean __GLEW_ARB_color_buffer_float = GL_FALSE; +GLboolean __GLEW_ARB_compatibility = GL_FALSE; +GLboolean __GLEW_ARB_copy_buffer = GL_FALSE; +GLboolean __GLEW_ARB_debug_output = GL_FALSE; +GLboolean __GLEW_ARB_depth_buffer_float = GL_FALSE; +GLboolean __GLEW_ARB_depth_clamp = GL_FALSE; +GLboolean __GLEW_ARB_depth_texture = GL_FALSE; +GLboolean __GLEW_ARB_draw_buffers = GL_FALSE; +GLboolean __GLEW_ARB_draw_buffers_blend = GL_FALSE; +GLboolean __GLEW_ARB_draw_elements_base_vertex = GL_FALSE; +GLboolean __GLEW_ARB_draw_indirect = GL_FALSE; +GLboolean __GLEW_ARB_draw_instanced = GL_FALSE; +GLboolean __GLEW_ARB_explicit_attrib_location = GL_FALSE; +GLboolean __GLEW_ARB_fragment_coord_conventions = GL_FALSE; +GLboolean __GLEW_ARB_fragment_program = GL_FALSE; +GLboolean __GLEW_ARB_fragment_program_shadow = GL_FALSE; +GLboolean __GLEW_ARB_fragment_shader = GL_FALSE; +GLboolean __GLEW_ARB_framebuffer_object = GL_FALSE; +GLboolean __GLEW_ARB_framebuffer_sRGB = GL_FALSE; +GLboolean __GLEW_ARB_geometry_shader4 = GL_FALSE; +GLboolean __GLEW_ARB_get_program_binary = GL_FALSE; +GLboolean __GLEW_ARB_gpu_shader5 = GL_FALSE; +GLboolean __GLEW_ARB_gpu_shader_fp64 = GL_FALSE; +GLboolean __GLEW_ARB_half_float_pixel = GL_FALSE; +GLboolean __GLEW_ARB_half_float_vertex = GL_FALSE; +GLboolean __GLEW_ARB_imaging = GL_FALSE; +GLboolean __GLEW_ARB_instanced_arrays = GL_FALSE; +GLboolean __GLEW_ARB_map_buffer_range = GL_FALSE; +GLboolean __GLEW_ARB_matrix_palette = GL_FALSE; +GLboolean __GLEW_ARB_multisample = GL_FALSE; +GLboolean __GLEW_ARB_multitexture = GL_FALSE; +GLboolean __GLEW_ARB_occlusion_query = GL_FALSE; +GLboolean __GLEW_ARB_occlusion_query2 = GL_FALSE; +GLboolean __GLEW_ARB_pixel_buffer_object = GL_FALSE; +GLboolean __GLEW_ARB_point_parameters = GL_FALSE; +GLboolean __GLEW_ARB_point_sprite = GL_FALSE; +GLboolean __GLEW_ARB_provoking_vertex = GL_FALSE; +GLboolean __GLEW_ARB_robustness = GL_FALSE; +GLboolean __GLEW_ARB_sample_shading = GL_FALSE; +GLboolean __GLEW_ARB_sampler_objects = GL_FALSE; +GLboolean __GLEW_ARB_seamless_cube_map = GL_FALSE; +GLboolean __GLEW_ARB_separate_shader_objects = GL_FALSE; +GLboolean __GLEW_ARB_shader_bit_encoding = GL_FALSE; +GLboolean __GLEW_ARB_shader_objects = GL_FALSE; +GLboolean __GLEW_ARB_shader_precision = GL_FALSE; +GLboolean __GLEW_ARB_shader_stencil_export = GL_FALSE; +GLboolean __GLEW_ARB_shader_subroutine = GL_FALSE; +GLboolean __GLEW_ARB_shader_texture_lod = GL_FALSE; +GLboolean __GLEW_ARB_shading_language_100 = GL_FALSE; +GLboolean __GLEW_ARB_shading_language_include = GL_FALSE; +GLboolean __GLEW_ARB_shadow = GL_FALSE; +GLboolean __GLEW_ARB_shadow_ambient = GL_FALSE; +GLboolean __GLEW_ARB_sync = GL_FALSE; +GLboolean __GLEW_ARB_tessellation_shader = GL_FALSE; +GLboolean __GLEW_ARB_texture_border_clamp = GL_FALSE; +GLboolean __GLEW_ARB_texture_buffer_object = GL_FALSE; +GLboolean __GLEW_ARB_texture_buffer_object_rgb32 = GL_FALSE; +GLboolean __GLEW_ARB_texture_compression = GL_FALSE; +GLboolean __GLEW_ARB_texture_compression_bptc = GL_FALSE; +GLboolean __GLEW_ARB_texture_compression_rgtc = GL_FALSE; +GLboolean __GLEW_ARB_texture_cube_map = GL_FALSE; +GLboolean __GLEW_ARB_texture_cube_map_array = GL_FALSE; +GLboolean __GLEW_ARB_texture_env_add = GL_FALSE; +GLboolean __GLEW_ARB_texture_env_combine = GL_FALSE; +GLboolean __GLEW_ARB_texture_env_crossbar = GL_FALSE; +GLboolean __GLEW_ARB_texture_env_dot3 = GL_FALSE; +GLboolean __GLEW_ARB_texture_float = GL_FALSE; +GLboolean __GLEW_ARB_texture_gather = GL_FALSE; +GLboolean __GLEW_ARB_texture_mirrored_repeat = GL_FALSE; +GLboolean __GLEW_ARB_texture_multisample = GL_FALSE; +GLboolean __GLEW_ARB_texture_non_power_of_two = GL_FALSE; +GLboolean __GLEW_ARB_texture_query_lod = GL_FALSE; +GLboolean __GLEW_ARB_texture_rectangle = GL_FALSE; +GLboolean __GLEW_ARB_texture_rg = GL_FALSE; +GLboolean __GLEW_ARB_texture_rgb10_a2ui = GL_FALSE; +GLboolean __GLEW_ARB_texture_swizzle = GL_FALSE; +GLboolean __GLEW_ARB_timer_query = GL_FALSE; +GLboolean __GLEW_ARB_transform_feedback2 = GL_FALSE; +GLboolean __GLEW_ARB_transform_feedback3 = GL_FALSE; +GLboolean __GLEW_ARB_transpose_matrix = GL_FALSE; +GLboolean __GLEW_ARB_uniform_buffer_object = GL_FALSE; +GLboolean __GLEW_ARB_vertex_array_bgra = GL_FALSE; +GLboolean __GLEW_ARB_vertex_array_object = GL_FALSE; +GLboolean __GLEW_ARB_vertex_attrib_64bit = GL_FALSE; +GLboolean __GLEW_ARB_vertex_blend = GL_FALSE; +GLboolean __GLEW_ARB_vertex_buffer_object = GL_FALSE; +GLboolean __GLEW_ARB_vertex_program = GL_FALSE; +GLboolean __GLEW_ARB_vertex_shader = GL_FALSE; +GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev = GL_FALSE; +GLboolean __GLEW_ARB_viewport_array = GL_FALSE; +GLboolean __GLEW_ARB_window_pos = GL_FALSE; +GLboolean __GLEW_ATIX_point_sprites = GL_FALSE; +GLboolean __GLEW_ATIX_texture_env_combine3 = GL_FALSE; +GLboolean __GLEW_ATIX_texture_env_route = GL_FALSE; +GLboolean __GLEW_ATIX_vertex_shader_output_point_size = GL_FALSE; +GLboolean __GLEW_ATI_draw_buffers = GL_FALSE; +GLboolean __GLEW_ATI_element_array = GL_FALSE; +GLboolean __GLEW_ATI_envmap_bumpmap = GL_FALSE; +GLboolean __GLEW_ATI_fragment_shader = GL_FALSE; +GLboolean __GLEW_ATI_map_object_buffer = GL_FALSE; +GLboolean __GLEW_ATI_meminfo = GL_FALSE; +GLboolean __GLEW_ATI_pn_triangles = GL_FALSE; +GLboolean __GLEW_ATI_separate_stencil = GL_FALSE; +GLboolean __GLEW_ATI_shader_texture_lod = GL_FALSE; +GLboolean __GLEW_ATI_text_fragment_shader = GL_FALSE; +GLboolean __GLEW_ATI_texture_compression_3dc = GL_FALSE; +GLboolean __GLEW_ATI_texture_env_combine3 = GL_FALSE; +GLboolean __GLEW_ATI_texture_float = GL_FALSE; +GLboolean __GLEW_ATI_texture_mirror_once = GL_FALSE; +GLboolean __GLEW_ATI_vertex_array_object = GL_FALSE; +GLboolean __GLEW_ATI_vertex_attrib_array_object = GL_FALSE; +GLboolean __GLEW_ATI_vertex_streams = GL_FALSE; +GLboolean __GLEW_EXT_422_pixels = GL_FALSE; +GLboolean __GLEW_EXT_Cg_shader = GL_FALSE; +GLboolean __GLEW_EXT_abgr = GL_FALSE; +GLboolean __GLEW_EXT_bgra = GL_FALSE; +GLboolean __GLEW_EXT_bindable_uniform = GL_FALSE; +GLboolean __GLEW_EXT_blend_color = GL_FALSE; +GLboolean __GLEW_EXT_blend_equation_separate = GL_FALSE; +GLboolean __GLEW_EXT_blend_func_separate = GL_FALSE; +GLboolean __GLEW_EXT_blend_logic_op = GL_FALSE; +GLboolean __GLEW_EXT_blend_minmax = GL_FALSE; +GLboolean __GLEW_EXT_blend_subtract = GL_FALSE; +GLboolean __GLEW_EXT_clip_volume_hint = GL_FALSE; +GLboolean __GLEW_EXT_cmyka = GL_FALSE; +GLboolean __GLEW_EXT_color_subtable = GL_FALSE; +GLboolean __GLEW_EXT_compiled_vertex_array = GL_FALSE; +GLboolean __GLEW_EXT_convolution = GL_FALSE; +GLboolean __GLEW_EXT_coordinate_frame = GL_FALSE; +GLboolean __GLEW_EXT_copy_texture = GL_FALSE; +GLboolean __GLEW_EXT_cull_vertex = GL_FALSE; +GLboolean __GLEW_EXT_depth_bounds_test = GL_FALSE; +GLboolean __GLEW_EXT_direct_state_access = GL_FALSE; +GLboolean __GLEW_EXT_draw_buffers2 = GL_FALSE; +GLboolean __GLEW_EXT_draw_instanced = GL_FALSE; +GLboolean __GLEW_EXT_draw_range_elements = GL_FALSE; +GLboolean __GLEW_EXT_fog_coord = GL_FALSE; +GLboolean __GLEW_EXT_fragment_lighting = GL_FALSE; +GLboolean __GLEW_EXT_framebuffer_blit = GL_FALSE; +GLboolean __GLEW_EXT_framebuffer_multisample = GL_FALSE; +GLboolean __GLEW_EXT_framebuffer_object = GL_FALSE; +GLboolean __GLEW_EXT_framebuffer_sRGB = GL_FALSE; +GLboolean __GLEW_EXT_geometry_shader4 = GL_FALSE; +GLboolean __GLEW_EXT_gpu_program_parameters = GL_FALSE; +GLboolean __GLEW_EXT_gpu_shader4 = GL_FALSE; +GLboolean __GLEW_EXT_histogram = GL_FALSE; +GLboolean __GLEW_EXT_index_array_formats = GL_FALSE; +GLboolean __GLEW_EXT_index_func = GL_FALSE; +GLboolean __GLEW_EXT_index_material = GL_FALSE; +GLboolean __GLEW_EXT_index_texture = GL_FALSE; +GLboolean __GLEW_EXT_light_texture = GL_FALSE; +GLboolean __GLEW_EXT_misc_attribute = GL_FALSE; +GLboolean __GLEW_EXT_multi_draw_arrays = GL_FALSE; +GLboolean __GLEW_EXT_multisample = GL_FALSE; +GLboolean __GLEW_EXT_packed_depth_stencil = GL_FALSE; +GLboolean __GLEW_EXT_packed_float = GL_FALSE; +GLboolean __GLEW_EXT_packed_pixels = GL_FALSE; +GLboolean __GLEW_EXT_paletted_texture = GL_FALSE; +GLboolean __GLEW_EXT_pixel_buffer_object = GL_FALSE; +GLboolean __GLEW_EXT_pixel_transform = GL_FALSE; +GLboolean __GLEW_EXT_pixel_transform_color_table = GL_FALSE; +GLboolean __GLEW_EXT_point_parameters = GL_FALSE; +GLboolean __GLEW_EXT_polygon_offset = GL_FALSE; +GLboolean __GLEW_EXT_provoking_vertex = GL_FALSE; +GLboolean __GLEW_EXT_rescale_normal = GL_FALSE; +GLboolean __GLEW_EXT_scene_marker = GL_FALSE; +GLboolean __GLEW_EXT_secondary_color = GL_FALSE; +GLboolean __GLEW_EXT_separate_shader_objects = GL_FALSE; +GLboolean __GLEW_EXT_separate_specular_color = GL_FALSE; +GLboolean __GLEW_EXT_shader_image_load_store = GL_FALSE; +GLboolean __GLEW_EXT_shadow_funcs = GL_FALSE; +GLboolean __GLEW_EXT_shared_texture_palette = GL_FALSE; +GLboolean __GLEW_EXT_stencil_clear_tag = GL_FALSE; +GLboolean __GLEW_EXT_stencil_two_side = GL_FALSE; +GLboolean __GLEW_EXT_stencil_wrap = GL_FALSE; +GLboolean __GLEW_EXT_subtexture = GL_FALSE; +GLboolean __GLEW_EXT_texture = GL_FALSE; +GLboolean __GLEW_EXT_texture3D = GL_FALSE; +GLboolean __GLEW_EXT_texture_array = GL_FALSE; +GLboolean __GLEW_EXT_texture_buffer_object = GL_FALSE; +GLboolean __GLEW_EXT_texture_compression_dxt1 = GL_FALSE; +GLboolean __GLEW_EXT_texture_compression_latc = GL_FALSE; +GLboolean __GLEW_EXT_texture_compression_rgtc = GL_FALSE; +GLboolean __GLEW_EXT_texture_compression_s3tc = GL_FALSE; +GLboolean __GLEW_EXT_texture_cube_map = GL_FALSE; +GLboolean __GLEW_EXT_texture_edge_clamp = GL_FALSE; +GLboolean __GLEW_EXT_texture_env = GL_FALSE; +GLboolean __GLEW_EXT_texture_env_add = GL_FALSE; +GLboolean __GLEW_EXT_texture_env_combine = GL_FALSE; +GLboolean __GLEW_EXT_texture_env_dot3 = GL_FALSE; +GLboolean __GLEW_EXT_texture_filter_anisotropic = GL_FALSE; +GLboolean __GLEW_EXT_texture_integer = GL_FALSE; +GLboolean __GLEW_EXT_texture_lod_bias = GL_FALSE; +GLboolean __GLEW_EXT_texture_mirror_clamp = GL_FALSE; +GLboolean __GLEW_EXT_texture_object = GL_FALSE; +GLboolean __GLEW_EXT_texture_perturb_normal = GL_FALSE; +GLboolean __GLEW_EXT_texture_rectangle = GL_FALSE; +GLboolean __GLEW_EXT_texture_sRGB = GL_FALSE; +GLboolean __GLEW_EXT_texture_sRGB_decode = GL_FALSE; +GLboolean __GLEW_EXT_texture_shared_exponent = GL_FALSE; +GLboolean __GLEW_EXT_texture_snorm = GL_FALSE; +GLboolean __GLEW_EXT_texture_swizzle = GL_FALSE; +GLboolean __GLEW_EXT_timer_query = GL_FALSE; +GLboolean __GLEW_EXT_transform_feedback = GL_FALSE; +GLboolean __GLEW_EXT_vertex_array = GL_FALSE; +GLboolean __GLEW_EXT_vertex_array_bgra = GL_FALSE; +GLboolean __GLEW_EXT_vertex_attrib_64bit = GL_FALSE; +GLboolean __GLEW_EXT_vertex_shader = GL_FALSE; +GLboolean __GLEW_EXT_vertex_weighting = GL_FALSE; +GLboolean __GLEW_EXT_x11_sync_object = GL_FALSE; +GLboolean __GLEW_GREMEDY_frame_terminator = GL_FALSE; +GLboolean __GLEW_GREMEDY_string_marker = GL_FALSE; +GLboolean __GLEW_HP_convolution_border_modes = GL_FALSE; +GLboolean __GLEW_HP_image_transform = GL_FALSE; +GLboolean __GLEW_HP_occlusion_test = GL_FALSE; +GLboolean __GLEW_HP_texture_lighting = GL_FALSE; +GLboolean __GLEW_IBM_cull_vertex = GL_FALSE; +GLboolean __GLEW_IBM_multimode_draw_arrays = GL_FALSE; +GLboolean __GLEW_IBM_rasterpos_clip = GL_FALSE; +GLboolean __GLEW_IBM_static_data = GL_FALSE; +GLboolean __GLEW_IBM_texture_mirrored_repeat = GL_FALSE; +GLboolean __GLEW_IBM_vertex_array_lists = GL_FALSE; +GLboolean __GLEW_INGR_color_clamp = GL_FALSE; +GLboolean __GLEW_INGR_interlace_read = GL_FALSE; +GLboolean __GLEW_INTEL_parallel_arrays = GL_FALSE; +GLboolean __GLEW_INTEL_texture_scissor = GL_FALSE; +GLboolean __GLEW_KTX_buffer_region = GL_FALSE; +GLboolean __GLEW_MESAX_texture_stack = GL_FALSE; +GLboolean __GLEW_MESA_pack_invert = GL_FALSE; +GLboolean __GLEW_MESA_resize_buffers = GL_FALSE; +GLboolean __GLEW_MESA_window_pos = GL_FALSE; +GLboolean __GLEW_MESA_ycbcr_texture = GL_FALSE; +GLboolean __GLEW_NVX_gpu_memory_info = GL_FALSE; +GLboolean __GLEW_NV_blend_square = GL_FALSE; +GLboolean __GLEW_NV_conditional_render = GL_FALSE; +GLboolean __GLEW_NV_copy_depth_to_color = GL_FALSE; +GLboolean __GLEW_NV_copy_image = GL_FALSE; +GLboolean __GLEW_NV_depth_buffer_float = GL_FALSE; +GLboolean __GLEW_NV_depth_clamp = GL_FALSE; +GLboolean __GLEW_NV_depth_range_unclamped = GL_FALSE; +GLboolean __GLEW_NV_evaluators = GL_FALSE; +GLboolean __GLEW_NV_explicit_multisample = GL_FALSE; +GLboolean __GLEW_NV_fence = GL_FALSE; +GLboolean __GLEW_NV_float_buffer = GL_FALSE; +GLboolean __GLEW_NV_fog_distance = GL_FALSE; +GLboolean __GLEW_NV_fragment_program = GL_FALSE; +GLboolean __GLEW_NV_fragment_program2 = GL_FALSE; +GLboolean __GLEW_NV_fragment_program4 = GL_FALSE; +GLboolean __GLEW_NV_fragment_program_option = GL_FALSE; +GLboolean __GLEW_NV_framebuffer_multisample_coverage = GL_FALSE; +GLboolean __GLEW_NV_geometry_program4 = GL_FALSE; +GLboolean __GLEW_NV_geometry_shader4 = GL_FALSE; +GLboolean __GLEW_NV_gpu_program4 = GL_FALSE; +GLboolean __GLEW_NV_gpu_program5 = GL_FALSE; +GLboolean __GLEW_NV_gpu_program_fp64 = GL_FALSE; +GLboolean __GLEW_NV_gpu_shader5 = GL_FALSE; +GLboolean __GLEW_NV_half_float = GL_FALSE; +GLboolean __GLEW_NV_light_max_exponent = GL_FALSE; +GLboolean __GLEW_NV_multisample_coverage = GL_FALSE; +GLboolean __GLEW_NV_multisample_filter_hint = GL_FALSE; +GLboolean __GLEW_NV_occlusion_query = GL_FALSE; +GLboolean __GLEW_NV_packed_depth_stencil = GL_FALSE; +GLboolean __GLEW_NV_parameter_buffer_object = GL_FALSE; +GLboolean __GLEW_NV_parameter_buffer_object2 = GL_FALSE; +GLboolean __GLEW_NV_pixel_data_range = GL_FALSE; +GLboolean __GLEW_NV_point_sprite = GL_FALSE; +GLboolean __GLEW_NV_present_video = GL_FALSE; +GLboolean __GLEW_NV_primitive_restart = GL_FALSE; +GLboolean __GLEW_NV_register_combiners = GL_FALSE; +GLboolean __GLEW_NV_register_combiners2 = GL_FALSE; +GLboolean __GLEW_NV_shader_buffer_load = GL_FALSE; +GLboolean __GLEW_NV_tessellation_program5 = GL_FALSE; +GLboolean __GLEW_NV_texgen_emboss = GL_FALSE; +GLboolean __GLEW_NV_texgen_reflection = GL_FALSE; +GLboolean __GLEW_NV_texture_barrier = GL_FALSE; +GLboolean __GLEW_NV_texture_compression_vtc = GL_FALSE; +GLboolean __GLEW_NV_texture_env_combine4 = GL_FALSE; +GLboolean __GLEW_NV_texture_expand_normal = GL_FALSE; +GLboolean __GLEW_NV_texture_multisample = GL_FALSE; +GLboolean __GLEW_NV_texture_rectangle = GL_FALSE; +GLboolean __GLEW_NV_texture_shader = GL_FALSE; +GLboolean __GLEW_NV_texture_shader2 = GL_FALSE; +GLboolean __GLEW_NV_texture_shader3 = GL_FALSE; +GLboolean __GLEW_NV_transform_feedback = GL_FALSE; +GLboolean __GLEW_NV_transform_feedback2 = GL_FALSE; +GLboolean __GLEW_NV_vdpau_interop = GL_FALSE; +GLboolean __GLEW_NV_vertex_array_range = GL_FALSE; +GLboolean __GLEW_NV_vertex_array_range2 = GL_FALSE; +GLboolean __GLEW_NV_vertex_attrib_integer_64bit = GL_FALSE; +GLboolean __GLEW_NV_vertex_buffer_unified_memory = GL_FALSE; +GLboolean __GLEW_NV_vertex_program = GL_FALSE; +GLboolean __GLEW_NV_vertex_program1_1 = GL_FALSE; +GLboolean __GLEW_NV_vertex_program2 = GL_FALSE; +GLboolean __GLEW_NV_vertex_program2_option = GL_FALSE; +GLboolean __GLEW_NV_vertex_program3 = GL_FALSE; +GLboolean __GLEW_NV_vertex_program4 = GL_FALSE; +GLboolean __GLEW_NV_video_capture = GL_FALSE; +GLboolean __GLEW_OES_byte_coordinates = GL_FALSE; +GLboolean __GLEW_OES_compressed_paletted_texture = GL_FALSE; +GLboolean __GLEW_OES_read_format = GL_FALSE; +GLboolean __GLEW_OES_single_precision = GL_FALSE; +GLboolean __GLEW_OML_interlace = GL_FALSE; +GLboolean __GLEW_OML_resample = GL_FALSE; +GLboolean __GLEW_OML_subsample = GL_FALSE; +GLboolean __GLEW_PGI_misc_hints = GL_FALSE; +GLboolean __GLEW_PGI_vertex_hints = GL_FALSE; +GLboolean __GLEW_REND_screen_coordinates = GL_FALSE; +GLboolean __GLEW_S3_s3tc = GL_FALSE; +GLboolean __GLEW_SGIS_color_range = GL_FALSE; +GLboolean __GLEW_SGIS_detail_texture = GL_FALSE; +GLboolean __GLEW_SGIS_fog_function = GL_FALSE; +GLboolean __GLEW_SGIS_generate_mipmap = GL_FALSE; +GLboolean __GLEW_SGIS_multisample = GL_FALSE; +GLboolean __GLEW_SGIS_pixel_texture = GL_FALSE; +GLboolean __GLEW_SGIS_point_line_texgen = GL_FALSE; +GLboolean __GLEW_SGIS_sharpen_texture = GL_FALSE; +GLboolean __GLEW_SGIS_texture4D = GL_FALSE; +GLboolean __GLEW_SGIS_texture_border_clamp = GL_FALSE; +GLboolean __GLEW_SGIS_texture_edge_clamp = GL_FALSE; +GLboolean __GLEW_SGIS_texture_filter4 = GL_FALSE; +GLboolean __GLEW_SGIS_texture_lod = GL_FALSE; +GLboolean __GLEW_SGIS_texture_select = GL_FALSE; +GLboolean __GLEW_SGIX_async = GL_FALSE; +GLboolean __GLEW_SGIX_async_histogram = GL_FALSE; +GLboolean __GLEW_SGIX_async_pixel = GL_FALSE; +GLboolean __GLEW_SGIX_blend_alpha_minmax = GL_FALSE; +GLboolean __GLEW_SGIX_clipmap = GL_FALSE; +GLboolean __GLEW_SGIX_convolution_accuracy = GL_FALSE; +GLboolean __GLEW_SGIX_depth_texture = GL_FALSE; +GLboolean __GLEW_SGIX_flush_raster = GL_FALSE; +GLboolean __GLEW_SGIX_fog_offset = GL_FALSE; +GLboolean __GLEW_SGIX_fog_texture = GL_FALSE; +GLboolean __GLEW_SGIX_fragment_specular_lighting = GL_FALSE; +GLboolean __GLEW_SGIX_framezoom = GL_FALSE; +GLboolean __GLEW_SGIX_interlace = GL_FALSE; +GLboolean __GLEW_SGIX_ir_instrument1 = GL_FALSE; +GLboolean __GLEW_SGIX_list_priority = GL_FALSE; +GLboolean __GLEW_SGIX_pixel_texture = GL_FALSE; +GLboolean __GLEW_SGIX_pixel_texture_bits = GL_FALSE; +GLboolean __GLEW_SGIX_reference_plane = GL_FALSE; +GLboolean __GLEW_SGIX_resample = GL_FALSE; +GLboolean __GLEW_SGIX_shadow = GL_FALSE; +GLboolean __GLEW_SGIX_shadow_ambient = GL_FALSE; +GLboolean __GLEW_SGIX_sprite = GL_FALSE; +GLboolean __GLEW_SGIX_tag_sample_buffer = GL_FALSE; +GLboolean __GLEW_SGIX_texture_add_env = GL_FALSE; +GLboolean __GLEW_SGIX_texture_coordinate_clamp = GL_FALSE; +GLboolean __GLEW_SGIX_texture_lod_bias = GL_FALSE; +GLboolean __GLEW_SGIX_texture_multi_buffer = GL_FALSE; +GLboolean __GLEW_SGIX_texture_range = GL_FALSE; +GLboolean __GLEW_SGIX_texture_scale_bias = GL_FALSE; +GLboolean __GLEW_SGIX_vertex_preclip = GL_FALSE; +GLboolean __GLEW_SGIX_vertex_preclip_hint = GL_FALSE; +GLboolean __GLEW_SGIX_ycrcb = GL_FALSE; +GLboolean __GLEW_SGI_color_matrix = GL_FALSE; +GLboolean __GLEW_SGI_color_table = GL_FALSE; +GLboolean __GLEW_SGI_texture_color_table = GL_FALSE; +GLboolean __GLEW_SUNX_constant_data = GL_FALSE; +GLboolean __GLEW_SUN_convolution_border_modes = GL_FALSE; +GLboolean __GLEW_SUN_global_alpha = GL_FALSE; +GLboolean __GLEW_SUN_mesh_array = GL_FALSE; +GLboolean __GLEW_SUN_read_video_pixels = GL_FALSE; +GLboolean __GLEW_SUN_slice_accum = GL_FALSE; +GLboolean __GLEW_SUN_triangle_list = GL_FALSE; +GLboolean __GLEW_SUN_vertex = GL_FALSE; +GLboolean __GLEW_WIN_phong_shading = GL_FALSE; +GLboolean __GLEW_WIN_specular_fog = GL_FALSE; +GLboolean __GLEW_WIN_swap_hint = GL_FALSE; + +#endif /* !GLEW_MX */ + +#ifdef GL_VERSION_1_2 + +static GLboolean _glewInit_GL_VERSION_1_2 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage3D")) == NULL) || r; + r = ((glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElements")) == NULL) || r; + r = ((glTexImage3D = (PFNGLTEXIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glTexImage3D")) == NULL) || r; + r = ((glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage3D")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_1_2 */ + +#ifdef GL_VERSION_1_2_1 + +#endif /* GL_VERSION_1_2_1 */ + +#ifdef GL_VERSION_1_3 + +static GLboolean _glewInit_GL_VERSION_1_3 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glActiveTexture = (PFNGLACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glActiveTexture")) == NULL) || r; + r = ((glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glClientActiveTexture")) == NULL) || r; + r = ((glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage1D")) == NULL) || r; + r = ((glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage2D")) == NULL) || r; + r = ((glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage3D")) == NULL) || r; + r = ((glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage1D")) == NULL) || r; + r = ((glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage2D")) == NULL) || r; + r = ((glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage3D")) == NULL) || r; + r = ((glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTexImage")) == NULL) || r; + r = ((glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixd")) == NULL) || r; + r = ((glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixf")) == NULL) || r; + r = ((glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixd")) == NULL) || r; + r = ((glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixf")) == NULL) || r; + r = ((glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1d")) == NULL) || r; + r = ((glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dv")) == NULL) || r; + r = ((glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1f")) == NULL) || r; + r = ((glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fv")) == NULL) || r; + r = ((glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1i")) == NULL) || r; + r = ((glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1iv")) == NULL) || r; + r = ((glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1s")) == NULL) || r; + r = ((glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1sv")) == NULL) || r; + r = ((glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2d")) == NULL) || r; + r = ((glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dv")) == NULL) || r; + r = ((glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2f")) == NULL) || r; + r = ((glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fv")) == NULL) || r; + r = ((glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2i")) == NULL) || r; + r = ((glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2iv")) == NULL) || r; + r = ((glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2s")) == NULL) || r; + r = ((glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2sv")) == NULL) || r; + r = ((glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3d")) == NULL) || r; + r = ((glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dv")) == NULL) || r; + r = ((glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3f")) == NULL) || r; + r = ((glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fv")) == NULL) || r; + r = ((glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3i")) == NULL) || r; + r = ((glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3iv")) == NULL) || r; + r = ((glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3s")) == NULL) || r; + r = ((glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3sv")) == NULL) || r; + r = ((glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4d")) == NULL) || r; + r = ((glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dv")) == NULL) || r; + r = ((glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4f")) == NULL) || r; + r = ((glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fv")) == NULL) || r; + r = ((glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4i")) == NULL) || r; + r = ((glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4iv")) == NULL) || r; + r = ((glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4s")) == NULL) || r; + r = ((glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4sv")) == NULL) || r; + r = ((glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)glewGetProcAddress((const GLubyte*)"glSampleCoverage")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_1_3 */ + +#ifdef GL_VERSION_1_4 + +static GLboolean _glewInit_GL_VERSION_1_4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendColor = (PFNGLBLENDCOLORPROC)glewGetProcAddress((const GLubyte*)"glBlendColor")) == NULL) || r; + r = ((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)"glBlendEquation")) == NULL) || r; + r = ((glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparate")) == NULL) || r; + r = ((glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointer")) == NULL) || r; + r = ((glFogCoordd = (PFNGLFOGCOORDDPROC)glewGetProcAddress((const GLubyte*)"glFogCoordd")) == NULL) || r; + r = ((glFogCoorddv = (PFNGLFOGCOORDDVPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddv")) == NULL) || r; + r = ((glFogCoordf = (PFNGLFOGCOORDFPROC)glewGetProcAddress((const GLubyte*)"glFogCoordf")) == NULL) || r; + r = ((glFogCoordfv = (PFNGLFOGCOORDFVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfv")) == NULL) || r; + r = ((glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArrays")) == NULL) || r; + r = ((glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElements")) == NULL) || r; + r = ((glPointParameterf = (PFNGLPOINTPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glPointParameterf")) == NULL) || r; + r = ((glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfv")) == NULL) || r; + r = ((glPointParameteri = (PFNGLPOINTPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glPointParameteri")) == NULL) || r; + r = ((glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glPointParameteriv")) == NULL) || r; + r = ((glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3b")) == NULL) || r; + r = ((glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bv")) == NULL) || r; + r = ((glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3d")) == NULL) || r; + r = ((glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dv")) == NULL) || r; + r = ((glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3f")) == NULL) || r; + r = ((glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fv")) == NULL) || r; + r = ((glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3i")) == NULL) || r; + r = ((glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3iv")) == NULL) || r; + r = ((glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3s")) == NULL) || r; + r = ((glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3sv")) == NULL) || r; + r = ((glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ub")) == NULL) || r; + r = ((glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubv")) == NULL) || r; + r = ((glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ui")) == NULL) || r; + r = ((glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uiv")) == NULL) || r; + r = ((glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3us")) == NULL) || r; + r = ((glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usv")) == NULL) || r; + r = ((glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointer")) == NULL) || r; + r = ((glWindowPos2d = (PFNGLWINDOWPOS2DPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2d")) == NULL) || r; + r = ((glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dv")) == NULL) || r; + r = ((glWindowPos2f = (PFNGLWINDOWPOS2FPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2f")) == NULL) || r; + r = ((glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fv")) == NULL) || r; + r = ((glWindowPos2i = (PFNGLWINDOWPOS2IPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2i")) == NULL) || r; + r = ((glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iv")) == NULL) || r; + r = ((glWindowPos2s = (PFNGLWINDOWPOS2SPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2s")) == NULL) || r; + r = ((glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sv")) == NULL) || r; + r = ((glWindowPos3d = (PFNGLWINDOWPOS3DPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3d")) == NULL) || r; + r = ((glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dv")) == NULL) || r; + r = ((glWindowPos3f = (PFNGLWINDOWPOS3FPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3f")) == NULL) || r; + r = ((glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fv")) == NULL) || r; + r = ((glWindowPos3i = (PFNGLWINDOWPOS3IPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3i")) == NULL) || r; + r = ((glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iv")) == NULL) || r; + r = ((glWindowPos3s = (PFNGLWINDOWPOS3SPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3s")) == NULL) || r; + r = ((glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sv")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_1_4 */ + +#ifdef GL_VERSION_1_5 + +static GLboolean _glewInit_GL_VERSION_1_5 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginQuery = (PFNGLBEGINQUERYPROC)glewGetProcAddress((const GLubyte*)"glBeginQuery")) == NULL) || r; + r = ((glBindBuffer = (PFNGLBINDBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindBuffer")) == NULL) || r; + r = ((glBufferData = (PFNGLBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferData")) == NULL) || r; + r = ((glBufferSubData = (PFNGLBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glBufferSubData")) == NULL) || r; + r = ((glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteBuffers")) == NULL) || r; + r = ((glDeleteQueries = (PFNGLDELETEQUERIESPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueries")) == NULL) || r; + r = ((glEndQuery = (PFNGLENDQUERYPROC)glewGetProcAddress((const GLubyte*)"glEndQuery")) == NULL) || r; + r = ((glGenBuffers = (PFNGLGENBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenBuffers")) == NULL) || r; + r = ((glGenQueries = (PFNGLGENQUERIESPROC)glewGetProcAddress((const GLubyte*)"glGenQueries")) == NULL) || r; + r = ((glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameteriv")) == NULL) || r; + r = ((glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferPointerv")) == NULL) || r; + r = ((glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glGetBufferSubData")) == NULL) || r; + r = ((glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectiv")) == NULL) || r; + r = ((glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuiv")) == NULL) || r; + r = ((glGetQueryiv = (PFNGLGETQUERYIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryiv")) == NULL) || r; + r = ((glIsBuffer = (PFNGLISBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsBuffer")) == NULL) || r; + r = ((glIsQuery = (PFNGLISQUERYPROC)glewGetProcAddress((const GLubyte*)"glIsQuery")) == NULL) || r; + r = ((glMapBuffer = (PFNGLMAPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glMapBuffer")) == NULL) || r; + r = ((glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glUnmapBuffer")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_1_5 */ + +#ifdef GL_VERSION_2_0 + +static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAttachShader = (PFNGLATTACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glAttachShader")) == NULL) || r; + r = ((glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocation")) == NULL) || r; + r = ((glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparate")) == NULL) || r; + r = ((glCompileShader = (PFNGLCOMPILESHADERPROC)glewGetProcAddress((const GLubyte*)"glCompileShader")) == NULL) || r; + r = ((glCreateProgram = (PFNGLCREATEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glCreateProgram")) == NULL) || r; + r = ((glCreateShader = (PFNGLCREATESHADERPROC)glewGetProcAddress((const GLubyte*)"glCreateShader")) == NULL) || r; + r = ((glDeleteProgram = (PFNGLDELETEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgram")) == NULL) || r; + r = ((glDeleteShader = (PFNGLDELETESHADERPROC)glewGetProcAddress((const GLubyte*)"glDeleteShader")) == NULL) || r; + r = ((glDetachShader = (PFNGLDETACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glDetachShader")) == NULL) || r; + r = ((glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribArray")) == NULL) || r; + r = ((glDrawBuffers = (PFNGLDRAWBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffers")) == NULL) || r; + r = ((glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribArray")) == NULL) || r; + r = ((glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAttrib")) == NULL) || r; + r = ((glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniform")) == NULL) || r; + r = ((glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)glewGetProcAddress((const GLubyte*)"glGetAttachedShaders")) == NULL) || r; + r = ((glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetAttribLocation")) == NULL) || r; + r = ((glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetProgramInfoLog")) == NULL) || r; + r = ((glGetProgramiv = (PFNGLGETPROGRAMIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramiv")) == NULL) || r; + r = ((glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetShaderInfoLog")) == NULL) || r; + r = ((glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)glewGetProcAddress((const GLubyte*)"glGetShaderSource")) == NULL) || r; + r = ((glGetShaderiv = (PFNGLGETSHADERIVPROC)glewGetProcAddress((const GLubyte*)"glGetShaderiv")) == NULL) || r; + r = ((glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetUniformLocation")) == NULL) || r; + r = ((glGetUniformfv = (PFNGLGETUNIFORMFVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformfv")) == NULL) || r; + r = ((glGetUniformiv = (PFNGLGETUNIFORMIVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformiv")) == NULL) || r; + r = ((glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointerv")) == NULL) || r; + r = ((glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdv")) == NULL) || r; + r = ((glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfv")) == NULL) || r; + r = ((glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribiv")) == NULL) || r; + r = ((glIsProgram = (PFNGLISPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glIsProgram")) == NULL) || r; + r = ((glIsShader = (PFNGLISSHADERPROC)glewGetProcAddress((const GLubyte*)"glIsShader")) == NULL) || r; + r = ((glLinkProgram = (PFNGLLINKPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glLinkProgram")) == NULL) || r; + r = ((glShaderSource = (PFNGLSHADERSOURCEPROC)glewGetProcAddress((const GLubyte*)"glShaderSource")) == NULL) || r; + r = ((glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilFuncSeparate")) == NULL) || r; + r = ((glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilMaskSeparate")) == NULL) || r; + r = ((glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glStencilOpSeparate")) == NULL) || r; + r = ((glUniform1f = (PFNGLUNIFORM1FPROC)glewGetProcAddress((const GLubyte*)"glUniform1f")) == NULL) || r; + r = ((glUniform1fv = (PFNGLUNIFORM1FVPROC)glewGetProcAddress((const GLubyte*)"glUniform1fv")) == NULL) || r; + r = ((glUniform1i = (PFNGLUNIFORM1IPROC)glewGetProcAddress((const GLubyte*)"glUniform1i")) == NULL) || r; + r = ((glUniform1iv = (PFNGLUNIFORM1IVPROC)glewGetProcAddress((const GLubyte*)"glUniform1iv")) == NULL) || r; + r = ((glUniform2f = (PFNGLUNIFORM2FPROC)glewGetProcAddress((const GLubyte*)"glUniform2f")) == NULL) || r; + r = ((glUniform2fv = (PFNGLUNIFORM2FVPROC)glewGetProcAddress((const GLubyte*)"glUniform2fv")) == NULL) || r; + r = ((glUniform2i = (PFNGLUNIFORM2IPROC)glewGetProcAddress((const GLubyte*)"glUniform2i")) == NULL) || r; + r = ((glUniform2iv = (PFNGLUNIFORM2IVPROC)glewGetProcAddress((const GLubyte*)"glUniform2iv")) == NULL) || r; + r = ((glUniform3f = (PFNGLUNIFORM3FPROC)glewGetProcAddress((const GLubyte*)"glUniform3f")) == NULL) || r; + r = ((glUniform3fv = (PFNGLUNIFORM3FVPROC)glewGetProcAddress((const GLubyte*)"glUniform3fv")) == NULL) || r; + r = ((glUniform3i = (PFNGLUNIFORM3IPROC)glewGetProcAddress((const GLubyte*)"glUniform3i")) == NULL) || r; + r = ((glUniform3iv = (PFNGLUNIFORM3IVPROC)glewGetProcAddress((const GLubyte*)"glUniform3iv")) == NULL) || r; + r = ((glUniform4f = (PFNGLUNIFORM4FPROC)glewGetProcAddress((const GLubyte*)"glUniform4f")) == NULL) || r; + r = ((glUniform4fv = (PFNGLUNIFORM4FVPROC)glewGetProcAddress((const GLubyte*)"glUniform4fv")) == NULL) || r; + r = ((glUniform4i = (PFNGLUNIFORM4IPROC)glewGetProcAddress((const GLubyte*)"glUniform4i")) == NULL) || r; + r = ((glUniform4iv = (PFNGLUNIFORM4IVPROC)glewGetProcAddress((const GLubyte*)"glUniform4iv")) == NULL) || r; + r = ((glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2fv")) == NULL) || r; + r = ((glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3fv")) == NULL) || r; + r = ((glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4fv")) == NULL) || r; + r = ((glUseProgram = (PFNGLUSEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glUseProgram")) == NULL) || r; + r = ((glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glValidateProgram")) == NULL) || r; + r = ((glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1d")) == NULL) || r; + r = ((glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dv")) == NULL) || r; + r = ((glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1f")) == NULL) || r; + r = ((glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fv")) == NULL) || r; + r = ((glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1s")) == NULL) || r; + r = ((glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sv")) == NULL) || r; + r = ((glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2d")) == NULL) || r; + r = ((glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dv")) == NULL) || r; + r = ((glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2f")) == NULL) || r; + r = ((glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fv")) == NULL) || r; + r = ((glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2s")) == NULL) || r; + r = ((glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sv")) == NULL) || r; + r = ((glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3d")) == NULL) || r; + r = ((glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dv")) == NULL) || r; + r = ((glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3f")) == NULL) || r; + r = ((glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fv")) == NULL) || r; + r = ((glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3s")) == NULL) || r; + r = ((glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sv")) == NULL) || r; + r = ((glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nbv")) == NULL) || r; + r = ((glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Niv")) == NULL) || r; + r = ((glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nsv")) == NULL) || r; + r = ((glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nub")) == NULL) || r; + r = ((glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nubv")) == NULL) || r; + r = ((glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nuiv")) == NULL) || r; + r = ((glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4Nusv")) == NULL) || r; + r = ((glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4bv")) == NULL) || r; + r = ((glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4d")) == NULL) || r; + r = ((glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dv")) == NULL) || r; + r = ((glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4f")) == NULL) || r; + r = ((glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fv")) == NULL) || r; + r = ((glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4iv")) == NULL) || r; + r = ((glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4s")) == NULL) || r; + r = ((glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sv")) == NULL) || r; + r = ((glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubv")) == NULL) || r; + r = ((glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uiv")) == NULL) || r; + r = ((glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usv")) == NULL) || r; + r = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointer")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_2_0 */ + +#ifdef GL_VERSION_2_1 + +static GLboolean _glewInit_GL_VERSION_2_1 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x3fv")) == NULL) || r; + r = ((glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x4fv")) == NULL) || r; + r = ((glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x2fv")) == NULL) || r; + r = ((glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x4fv")) == NULL) || r; + r = ((glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x2fv")) == NULL) || r; + r = ((glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x3fv")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_2_1 */ + +#ifdef GL_VERSION_3_0 + +static GLboolean _glewInit_GL_VERSION_3_0 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC)glewGetProcAddress((const GLubyte*)"glBeginConditionalRender")) == NULL) || r; + r = ((glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glBeginTransformFeedback")) == NULL) || r; + r = ((glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindFragDataLocation")) == NULL) || r; + r = ((glClampColor = (PFNGLCLAMPCOLORPROC)glewGetProcAddress((const GLubyte*)"glClampColor")) == NULL) || r; + r = ((glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)glewGetProcAddress((const GLubyte*)"glClearBufferfi")) == NULL) || r; + r = ((glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)glewGetProcAddress((const GLubyte*)"glClearBufferfv")) == NULL) || r; + r = ((glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)glewGetProcAddress((const GLubyte*)"glClearBufferiv")) == NULL) || r; + r = ((glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)glewGetProcAddress((const GLubyte*)"glClearBufferuiv")) == NULL) || r; + r = ((glColorMaski = (PFNGLCOLORMASKIPROC)glewGetProcAddress((const GLubyte*)"glColorMaski")) == NULL) || r; + r = ((glDisablei = (PFNGLDISABLEIPROC)glewGetProcAddress((const GLubyte*)"glDisablei")) == NULL) || r; + r = ((glEnablei = (PFNGLENABLEIPROC)glewGetProcAddress((const GLubyte*)"glEnablei")) == NULL) || r; + r = ((glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)glewGetProcAddress((const GLubyte*)"glEndConditionalRender")) == NULL) || r; + r = ((glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glEndTransformFeedback")) == NULL) || r; + r = ((glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC)glewGetProcAddress((const GLubyte*)"glGetBooleani_v")) == NULL) || r; + r = ((glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetFragDataLocation")) == NULL) || r; + r = ((glGetStringi = (PFNGLGETSTRINGIPROC)glewGetProcAddress((const GLubyte*)"glGetStringi")) == NULL) || r; + r = ((glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIiv")) == NULL) || r; + r = ((glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIuiv")) == NULL) || r; + r = ((glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)glewGetProcAddress((const GLubyte*)"glGetTransformFeedbackVarying")) == NULL) || r; + r = ((glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformuiv")) == NULL) || r; + r = ((glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIiv")) == NULL) || r; + r = ((glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIuiv")) == NULL) || r; + r = ((glIsEnabledi = (PFNGLISENABLEDIPROC)glewGetProcAddress((const GLubyte*)"glIsEnabledi")) == NULL) || r; + r = ((glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIiv")) == NULL) || r; + r = ((glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIuiv")) == NULL) || r; + r = ((glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackVaryings")) == NULL) || r; + r = ((glUniform1ui = (PFNGLUNIFORM1UIPROC)glewGetProcAddress((const GLubyte*)"glUniform1ui")) == NULL) || r; + r = ((glUniform1uiv = (PFNGLUNIFORM1UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform1uiv")) == NULL) || r; + r = ((glUniform2ui = (PFNGLUNIFORM2UIPROC)glewGetProcAddress((const GLubyte*)"glUniform2ui")) == NULL) || r; + r = ((glUniform2uiv = (PFNGLUNIFORM2UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform2uiv")) == NULL) || r; + r = ((glUniform3ui = (PFNGLUNIFORM3UIPROC)glewGetProcAddress((const GLubyte*)"glUniform3ui")) == NULL) || r; + r = ((glUniform3uiv = (PFNGLUNIFORM3UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform3uiv")) == NULL) || r; + r = ((glUniform4ui = (PFNGLUNIFORM4UIPROC)glewGetProcAddress((const GLubyte*)"glUniform4ui")) == NULL) || r; + r = ((glUniform4uiv = (PFNGLUNIFORM4UIVPROC)glewGetProcAddress((const GLubyte*)"glUniform4uiv")) == NULL) || r; + r = ((glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1i")) == NULL) || r; + r = ((glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1iv")) == NULL) || r; + r = ((glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1ui")) == NULL) || r; + r = ((glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uiv")) == NULL) || r; + r = ((glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2i")) == NULL) || r; + r = ((glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2iv")) == NULL) || r; + r = ((glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2ui")) == NULL) || r; + r = ((glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uiv")) == NULL) || r; + r = ((glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3i")) == NULL) || r; + r = ((glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3iv")) == NULL) || r; + r = ((glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3ui")) == NULL) || r; + r = ((glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uiv")) == NULL) || r; + r = ((glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4bv")) == NULL) || r; + r = ((glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4i")) == NULL) || r; + r = ((glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4iv")) == NULL) || r; + r = ((glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4sv")) == NULL) || r; + r = ((glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ubv")) == NULL) || r; + r = ((glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ui")) == NULL) || r; + r = ((glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uiv")) == NULL) || r; + r = ((glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4usv")) == NULL) || r; + r = ((glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIPointer")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_3_0 */ + +#ifdef GL_VERSION_3_1 + +static GLboolean _glewInit_GL_VERSION_3_1 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstanced")) == NULL) || r; + r = ((glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstanced")) == NULL) || r; + r = ((glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)glewGetProcAddress((const GLubyte*)"glPrimitiveRestartIndex")) == NULL) || r; + r = ((glTexBuffer = (PFNGLTEXBUFFERPROC)glewGetProcAddress((const GLubyte*)"glTexBuffer")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_3_1 */ + +#ifdef GL_VERSION_3_2 + +static GLboolean _glewInit_GL_VERSION_3_2 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture")) == NULL) || r; + r = ((glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameteri64v")) == NULL) || r; + r = ((glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC)glewGetProcAddress((const GLubyte*)"glGetInteger64i_v")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_3_2 */ + +#ifdef GL_VERSION_3_3 + +static GLboolean _glewInit_GL_VERSION_3_3 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribDivisor")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_3_3 */ + +#ifdef GL_VERSION_4_0 + +static GLboolean _glewInit_GL_VERSION_4_0 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendEquationSeparatei = (PFNGLBLENDEQUATIONSEPARATEIPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparatei")) == NULL) || r; + r = ((glBlendEquationi = (PFNGLBLENDEQUATIONIPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationi")) == NULL) || r; + r = ((glBlendFuncSeparatei = (PFNGLBLENDFUNCSEPARATEIPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparatei")) == NULL) || r; + r = ((glBlendFunci = (PFNGLBLENDFUNCIPROC)glewGetProcAddress((const GLubyte*)"glBlendFunci")) == NULL) || r; + r = ((glMinSampleShading = (PFNGLMINSAMPLESHADINGPROC)glewGetProcAddress((const GLubyte*)"glMinSampleShading")) == NULL) || r; + + return r; +} + +#endif /* GL_VERSION_4_0 */ + +#ifdef GL_VERSION_4_1 + +#endif /* GL_VERSION_4_1 */ + +#ifdef GL_3DFX_multisample + +#endif /* GL_3DFX_multisample */ + +#ifdef GL_3DFX_tbuffer + +static GLboolean _glewInit_GL_3DFX_tbuffer (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTbufferMask3DFX = (PFNGLTBUFFERMASK3DFXPROC)glewGetProcAddress((const GLubyte*)"glTbufferMask3DFX")) == NULL) || r; + + return r; +} + +#endif /* GL_3DFX_tbuffer */ + +#ifdef GL_3DFX_texture_compression_FXT1 + +#endif /* GL_3DFX_texture_compression_FXT1 */ + +#ifdef GL_AMD_blend_minmax_factor + +#endif /* GL_AMD_blend_minmax_factor */ + +#ifdef GL_AMD_conservative_depth + +#endif /* GL_AMD_conservative_depth */ + +#ifdef GL_AMD_debug_output + +static GLboolean _glewInit_GL_AMD_debug_output (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDebugMessageCallbackAMD = (PFNGLDEBUGMESSAGECALLBACKAMDPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageCallbackAMD")) == NULL) || r; + r = ((glDebugMessageEnableAMD = (PFNGLDEBUGMESSAGEENABLEAMDPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageEnableAMD")) == NULL) || r; + r = ((glDebugMessageInsertAMD = (PFNGLDEBUGMESSAGEINSERTAMDPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageInsertAMD")) == NULL) || r; + r = ((glGetDebugMessageLogAMD = (PFNGLGETDEBUGMESSAGELOGAMDPROC)glewGetProcAddress((const GLubyte*)"glGetDebugMessageLogAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_debug_output */ + +#ifdef GL_AMD_depth_clamp_separate + +#endif /* GL_AMD_depth_clamp_separate */ + +#ifdef GL_AMD_draw_buffers_blend + +static GLboolean _glewInit_GL_AMD_draw_buffers_blend (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendEquationIndexedAMD = (PFNGLBLENDEQUATIONINDEXEDAMDPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationIndexedAMD")) == NULL) || r; + r = ((glBlendEquationSeparateIndexedAMD = (PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparateIndexedAMD")) == NULL) || r; + r = ((glBlendFuncIndexedAMD = (PFNGLBLENDFUNCINDEXEDAMDPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncIndexedAMD")) == NULL) || r; + r = ((glBlendFuncSeparateIndexedAMD = (PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparateIndexedAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_draw_buffers_blend */ + +#ifdef GL_AMD_name_gen_delete + +static GLboolean _glewInit_GL_AMD_name_gen_delete (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDeleteNamesAMD = (PFNGLDELETENAMESAMDPROC)glewGetProcAddress((const GLubyte*)"glDeleteNamesAMD")) == NULL) || r; + r = ((glGenNamesAMD = (PFNGLGENNAMESAMDPROC)glewGetProcAddress((const GLubyte*)"glGenNamesAMD")) == NULL) || r; + r = ((glIsNameAMD = (PFNGLISNAMEAMDPROC)glewGetProcAddress((const GLubyte*)"glIsNameAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_name_gen_delete */ + +#ifdef GL_AMD_performance_monitor + +static GLboolean _glewInit_GL_AMD_performance_monitor (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginPerfMonitorAMD = (PFNGLBEGINPERFMONITORAMDPROC)glewGetProcAddress((const GLubyte*)"glBeginPerfMonitorAMD")) == NULL) || r; + r = ((glDeletePerfMonitorsAMD = (PFNGLDELETEPERFMONITORSAMDPROC)glewGetProcAddress((const GLubyte*)"glDeletePerfMonitorsAMD")) == NULL) || r; + r = ((glEndPerfMonitorAMD = (PFNGLENDPERFMONITORAMDPROC)glewGetProcAddress((const GLubyte*)"glEndPerfMonitorAMD")) == NULL) || r; + r = ((glGenPerfMonitorsAMD = (PFNGLGENPERFMONITORSAMDPROC)glewGetProcAddress((const GLubyte*)"glGenPerfMonitorsAMD")) == NULL) || r; + r = ((glGetPerfMonitorCounterDataAMD = (PFNGLGETPERFMONITORCOUNTERDATAAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorCounterDataAMD")) == NULL) || r; + r = ((glGetPerfMonitorCounterInfoAMD = (PFNGLGETPERFMONITORCOUNTERINFOAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorCounterInfoAMD")) == NULL) || r; + r = ((glGetPerfMonitorCounterStringAMD = (PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorCounterStringAMD")) == NULL) || r; + r = ((glGetPerfMonitorCountersAMD = (PFNGLGETPERFMONITORCOUNTERSAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorCountersAMD")) == NULL) || r; + r = ((glGetPerfMonitorGroupStringAMD = (PFNGLGETPERFMONITORGROUPSTRINGAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorGroupStringAMD")) == NULL) || r; + r = ((glGetPerfMonitorGroupsAMD = (PFNGLGETPERFMONITORGROUPSAMDPROC)glewGetProcAddress((const GLubyte*)"glGetPerfMonitorGroupsAMD")) == NULL) || r; + r = ((glSelectPerfMonitorCountersAMD = (PFNGLSELECTPERFMONITORCOUNTERSAMDPROC)glewGetProcAddress((const GLubyte*)"glSelectPerfMonitorCountersAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_performance_monitor */ + +#ifdef GL_AMD_sample_positions + +static GLboolean _glewInit_GL_AMD_sample_positions (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSetMultisamplefvAMD = (PFNGLSETMULTISAMPLEFVAMDPROC)glewGetProcAddress((const GLubyte*)"glSetMultisamplefvAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_sample_positions */ + +#ifdef GL_AMD_seamless_cubemap_per_texture + +#endif /* GL_AMD_seamless_cubemap_per_texture */ + +#ifdef GL_AMD_shader_stencil_export + +#endif /* GL_AMD_shader_stencil_export */ + +#ifdef GL_AMD_texture_texture4 + +#endif /* GL_AMD_texture_texture4 */ + +#ifdef GL_AMD_transform_feedback3_lines_triangles + +#endif /* GL_AMD_transform_feedback3_lines_triangles */ + +#ifdef GL_AMD_vertex_shader_tessellator + +static GLboolean _glewInit_GL_AMD_vertex_shader_tessellator (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTessellationFactorAMD = (PFNGLTESSELLATIONFACTORAMDPROC)glewGetProcAddress((const GLubyte*)"glTessellationFactorAMD")) == NULL) || r; + r = ((glTessellationModeAMD = (PFNGLTESSELLATIONMODEAMDPROC)glewGetProcAddress((const GLubyte*)"glTessellationModeAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_vertex_shader_tessellator */ + +#ifdef GL_APPLE_aux_depth_stencil + +#endif /* GL_APPLE_aux_depth_stencil */ + +#ifdef GL_APPLE_client_storage + +#endif /* GL_APPLE_client_storage */ + +#ifdef GL_APPLE_element_array + +static GLboolean _glewInit_GL_APPLE_element_array (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawElementArrayAPPLE = (PFNGLDRAWELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementArrayAPPLE")) == NULL) || r; + r = ((glDrawRangeElementArrayAPPLE = (PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementArrayAPPLE")) == NULL) || r; + r = ((glElementPointerAPPLE = (PFNGLELEMENTPOINTERAPPLEPROC)glewGetProcAddress((const GLubyte*)"glElementPointerAPPLE")) == NULL) || r; + r = ((glMultiDrawElementArrayAPPLE = (PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementArrayAPPLE")) == NULL) || r; + r = ((glMultiDrawRangeElementArrayAPPLE = (PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawRangeElementArrayAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_element_array */ + +#ifdef GL_APPLE_fence + +static GLboolean _glewInit_GL_APPLE_fence (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDeleteFencesAPPLE = (PFNGLDELETEFENCESAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteFencesAPPLE")) == NULL) || r; + r = ((glFinishFenceAPPLE = (PFNGLFINISHFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFinishFenceAPPLE")) == NULL) || r; + r = ((glFinishObjectAPPLE = (PFNGLFINISHOBJECTAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFinishObjectAPPLE")) == NULL) || r; + r = ((glGenFencesAPPLE = (PFNGLGENFENCESAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGenFencesAPPLE")) == NULL) || r; + r = ((glIsFenceAPPLE = (PFNGLISFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsFenceAPPLE")) == NULL) || r; + r = ((glSetFenceAPPLE = (PFNGLSETFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glSetFenceAPPLE")) == NULL) || r; + r = ((glTestFenceAPPLE = (PFNGLTESTFENCEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTestFenceAPPLE")) == NULL) || r; + r = ((glTestObjectAPPLE = (PFNGLTESTOBJECTAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTestObjectAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_fence */ + +#ifdef GL_APPLE_float_pixels + +#endif /* GL_APPLE_float_pixels */ + +#ifdef GL_APPLE_flush_buffer_range + +static GLboolean _glewInit_GL_APPLE_flush_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBufferParameteriAPPLE = (PFNGLBUFFERPARAMETERIAPPLEPROC)glewGetProcAddress((const GLubyte*)"glBufferParameteriAPPLE")) == NULL) || r; + r = ((glFlushMappedBufferRangeAPPLE = (PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFlushMappedBufferRangeAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_flush_buffer_range */ + +#ifdef GL_APPLE_object_purgeable + +static GLboolean _glewInit_GL_APPLE_object_purgeable (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetObjectParameterivAPPLE = (PFNGLGETOBJECTPARAMETERIVAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGetObjectParameterivAPPLE")) == NULL) || r; + r = ((glObjectPurgeableAPPLE = (PFNGLOBJECTPURGEABLEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glObjectPurgeableAPPLE")) == NULL) || r; + r = ((glObjectUnpurgeableAPPLE = (PFNGLOBJECTUNPURGEABLEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glObjectUnpurgeableAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_object_purgeable */ + +#ifdef GL_APPLE_pixel_buffer + +#endif /* GL_APPLE_pixel_buffer */ + +#ifdef GL_APPLE_rgb_422 + +#endif /* GL_APPLE_rgb_422 */ + +#ifdef GL_APPLE_row_bytes + +#endif /* GL_APPLE_row_bytes */ + +#ifdef GL_APPLE_specular_vector + +#endif /* GL_APPLE_specular_vector */ + +#ifdef GL_APPLE_texture_range + +static GLboolean _glewInit_GL_APPLE_texture_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetTexParameterPointervAPPLE = (PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterPointervAPPLE")) == NULL) || r; + r = ((glTextureRangeAPPLE = (PFNGLTEXTURERANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glTextureRangeAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_texture_range */ + +#ifdef GL_APPLE_transform_hint + +#endif /* GL_APPLE_transform_hint */ + +#ifdef GL_APPLE_vertex_array_object + +static GLboolean _glewInit_GL_APPLE_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindVertexArrayAPPLE = (PFNGLBINDVERTEXARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glBindVertexArrayAPPLE")) == NULL) || r; + r = ((glDeleteVertexArraysAPPLE = (PFNGLDELETEVERTEXARRAYSAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexArraysAPPLE")) == NULL) || r; + r = ((glGenVertexArraysAPPLE = (PFNGLGENVERTEXARRAYSAPPLEPROC)glewGetProcAddress((const GLubyte*)"glGenVertexArraysAPPLE")) == NULL) || r; + r = ((glIsVertexArrayAPPLE = (PFNGLISVERTEXARRAYAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsVertexArrayAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_vertex_array_object */ + +#ifdef GL_APPLE_vertex_array_range + +static GLboolean _glewInit_GL_APPLE_vertex_array_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFlushVertexArrayRangeAPPLE = (PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glFlushVertexArrayRangeAPPLE")) == NULL) || r; + r = ((glVertexArrayParameteriAPPLE = (PFNGLVERTEXARRAYPARAMETERIAPPLEPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayParameteriAPPLE")) == NULL) || r; + r = ((glVertexArrayRangeAPPLE = (PFNGLVERTEXARRAYRANGEAPPLEPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayRangeAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_vertex_array_range */ + +#ifdef GL_APPLE_vertex_program_evaluators + +static GLboolean _glewInit_GL_APPLE_vertex_program_evaluators (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDisableVertexAttribAPPLE = (PFNGLDISABLEVERTEXATTRIBAPPLEPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribAPPLE")) == NULL) || r; + r = ((glEnableVertexAttribAPPLE = (PFNGLENABLEVERTEXATTRIBAPPLEPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribAPPLE")) == NULL) || r; + r = ((glIsVertexAttribEnabledAPPLE = (PFNGLISVERTEXATTRIBENABLEDAPPLEPROC)glewGetProcAddress((const GLubyte*)"glIsVertexAttribEnabledAPPLE")) == NULL) || r; + r = ((glMapVertexAttrib1dAPPLE = (PFNGLMAPVERTEXATTRIB1DAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMapVertexAttrib1dAPPLE")) == NULL) || r; + r = ((glMapVertexAttrib1fAPPLE = (PFNGLMAPVERTEXATTRIB1FAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMapVertexAttrib1fAPPLE")) == NULL) || r; + r = ((glMapVertexAttrib2dAPPLE = (PFNGLMAPVERTEXATTRIB2DAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMapVertexAttrib2dAPPLE")) == NULL) || r; + r = ((glMapVertexAttrib2fAPPLE = (PFNGLMAPVERTEXATTRIB2FAPPLEPROC)glewGetProcAddress((const GLubyte*)"glMapVertexAttrib2fAPPLE")) == NULL) || r; + + return r; +} + +#endif /* GL_APPLE_vertex_program_evaluators */ + +#ifdef GL_APPLE_ycbcr_422 + +#endif /* GL_APPLE_ycbcr_422 */ + +#ifdef GL_ARB_ES2_compatibility + +static GLboolean _glewInit_GL_ARB_ES2_compatibility (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClearDepthf = (PFNGLCLEARDEPTHFPROC)glewGetProcAddress((const GLubyte*)"glClearDepthf")) == NULL) || r; + r = ((glDepthRangef = (PFNGLDEPTHRANGEFPROC)glewGetProcAddress((const GLubyte*)"glDepthRangef")) == NULL) || r; + r = ((glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC)glewGetProcAddress((const GLubyte*)"glGetShaderPrecisionFormat")) == NULL) || r; + r = ((glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC)glewGetProcAddress((const GLubyte*)"glReleaseShaderCompiler")) == NULL) || r; + r = ((glShaderBinary = (PFNGLSHADERBINARYPROC)glewGetProcAddress((const GLubyte*)"glShaderBinary")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_ES2_compatibility */ + +#ifdef GL_ARB_blend_func_extended + +static GLboolean _glewInit_GL_ARB_blend_func_extended (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)glewGetProcAddress((const GLubyte*)"glBindFragDataLocationIndexed")) == NULL) || r; + r = ((glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetFragDataIndex")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_blend_func_extended */ + +#ifdef GL_ARB_cl_event + +static GLboolean _glewInit_GL_ARB_cl_event (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCreateSyncFromCLeventARB = (PFNGLCREATESYNCFROMCLEVENTARBPROC)glewGetProcAddress((const GLubyte*)"glCreateSyncFromCLeventARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_cl_event */ + +#ifdef GL_ARB_color_buffer_float + +static GLboolean _glewInit_GL_ARB_color_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClampColorARB = (PFNGLCLAMPCOLORARBPROC)glewGetProcAddress((const GLubyte*)"glClampColorARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_color_buffer_float */ + +#ifdef GL_ARB_compatibility + +#endif /* GL_ARB_compatibility */ + +#ifdef GL_ARB_copy_buffer + +static GLboolean _glewInit_GL_ARB_copy_buffer (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glCopyBufferSubData")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_copy_buffer */ + +#ifdef GL_ARB_debug_output + +static GLboolean _glewInit_GL_ARB_debug_output (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageCallbackARB")) == NULL) || r; + r = ((glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageControlARB")) == NULL) || r; + r = ((glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageInsertARB")) == NULL) || r; + r = ((glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC)glewGetProcAddress((const GLubyte*)"glGetDebugMessageLogARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_debug_output */ + +#ifdef GL_ARB_depth_buffer_float + +#endif /* GL_ARB_depth_buffer_float */ + +#ifdef GL_ARB_depth_clamp + +#endif /* GL_ARB_depth_clamp */ + +#ifdef GL_ARB_depth_texture + +#endif /* GL_ARB_depth_texture */ + +#ifdef GL_ARB_draw_buffers + +static GLboolean _glewInit_GL_ARB_draw_buffers (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffersARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_draw_buffers */ + +#ifdef GL_ARB_draw_buffers_blend + +static GLboolean _glewInit_GL_ARB_draw_buffers_blend (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendEquationSeparateiARB = (PFNGLBLENDEQUATIONSEPARATEIARBPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparateiARB")) == NULL) || r; + r = ((glBlendEquationiARB = (PFNGLBLENDEQUATIONIARBPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationiARB")) == NULL) || r; + r = ((glBlendFuncSeparateiARB = (PFNGLBLENDFUNCSEPARATEIARBPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparateiARB")) == NULL) || r; + r = ((glBlendFunciARB = (PFNGLBLENDFUNCIARBPROC)glewGetProcAddress((const GLubyte*)"glBlendFunciARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_draw_buffers_blend */ + +#ifdef GL_ARB_draw_elements_base_vertex + +static GLboolean _glewInit_GL_ARB_draw_elements_base_vertex (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsBaseVertex")) == NULL) || r; + r = ((glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedBaseVertex")) == NULL) || r; + r = ((glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementsBaseVertex")) == NULL) || r; + r = ((glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsBaseVertex")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_draw_elements_base_vertex */ + +#ifdef GL_ARB_draw_indirect + +static GLboolean _glewInit_GL_ARB_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawArraysIndirect = (PFNGLDRAWARRAYSINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysIndirect")) == NULL) || r; + r = ((glDrawElementsIndirect = (PFNGLDRAWELEMENTSINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsIndirect")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_draw_indirect */ + +#ifdef GL_ARB_draw_instanced + +#endif /* GL_ARB_draw_instanced */ + +#ifdef GL_ARB_explicit_attrib_location + +#endif /* GL_ARB_explicit_attrib_location */ + +#ifdef GL_ARB_fragment_coord_conventions + +#endif /* GL_ARB_fragment_coord_conventions */ + +#ifdef GL_ARB_fragment_program + +#endif /* GL_ARB_fragment_program */ + +#ifdef GL_ARB_fragment_program_shadow + +#endif /* GL_ARB_fragment_program_shadow */ + +#ifdef GL_ARB_fragment_shader + +#endif /* GL_ARB_fragment_shader */ + +#ifdef GL_ARB_framebuffer_object + +static GLboolean _glewInit_GL_ARB_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindFramebuffer")) == NULL) || r; + r = ((glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbuffer")) == NULL) || r; + r = ((glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebuffer")) == NULL) || r; + r = ((glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatus")) == NULL) || r; + r = ((glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteFramebuffers")) == NULL) || r; + r = ((glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteRenderbuffers")) == NULL) || r; + r = ((glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glFramebufferRenderbuffer")) == NULL) || r; + r = ((glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture1D")) == NULL) || r; + r = ((glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2D")) == NULL) || r; + r = ((glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture3D")) == NULL) || r; + r = ((glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayer")) == NULL) || r; + r = ((glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenFramebuffers")) == NULL) || r; + r = ((glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glGenRenderbuffers")) == NULL) || r; + r = ((glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)glewGetProcAddress((const GLubyte*)"glGenerateMipmap")) == NULL) || r; + r = ((glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferAttachmentParameteriv")) == NULL) || r; + r = ((glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetRenderbufferParameteriv")) == NULL) || r; + r = ((glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsFramebuffer")) == NULL) || r; + r = ((glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glIsRenderbuffer")) == NULL) || r; + r = ((glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorage")) == NULL) || r; + r = ((glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisample")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_framebuffer_object */ + +#ifdef GL_ARB_framebuffer_sRGB + +#endif /* GL_ARB_framebuffer_sRGB */ + +#ifdef GL_ARB_geometry_shader4 + +static GLboolean _glewInit_GL_ARB_geometry_shader4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFramebufferTextureARB = (PFNGLFRAMEBUFFERTEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureARB")) == NULL) || r; + r = ((glFramebufferTextureFaceARB = (PFNGLFRAMEBUFFERTEXTUREFACEARBPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureFaceARB")) == NULL) || r; + r = ((glFramebufferTextureLayerARB = (PFNGLFRAMEBUFFERTEXTURELAYERARBPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayerARB")) == NULL) || r; + r = ((glProgramParameteriARB = (PFNGLPROGRAMPARAMETERIARBPROC)glewGetProcAddress((const GLubyte*)"glProgramParameteriARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_geometry_shader4 */ + +#ifdef GL_ARB_get_program_binary + +static GLboolean _glewInit_GL_ARB_get_program_binary (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC)glewGetProcAddress((const GLubyte*)"glGetProgramBinary")) == NULL) || r; + r = ((glProgramBinary = (PFNGLPROGRAMBINARYPROC)glewGetProcAddress((const GLubyte*)"glProgramBinary")) == NULL) || r; + r = ((glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glProgramParameteri")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_get_program_binary */ + +#ifdef GL_ARB_gpu_shader5 + +#endif /* GL_ARB_gpu_shader5 */ + +#ifdef GL_ARB_gpu_shader_fp64 + +static GLboolean _glewInit_GL_ARB_gpu_shader_fp64 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetUniformdv = (PFNGLGETUNIFORMDVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformdv")) == NULL) || r; + r = ((glProgramUniform1dEXT = (PFNGLPROGRAMUNIFORM1DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1dEXT")) == NULL) || r; + r = ((glProgramUniform1dvEXT = (PFNGLPROGRAMUNIFORM1DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1dvEXT")) == NULL) || r; + r = ((glProgramUniform2dEXT = (PFNGLPROGRAMUNIFORM2DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2dEXT")) == NULL) || r; + r = ((glProgramUniform2dvEXT = (PFNGLPROGRAMUNIFORM2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2dvEXT")) == NULL) || r; + r = ((glProgramUniform3dEXT = (PFNGLPROGRAMUNIFORM3DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3dEXT")) == NULL) || r; + r = ((glProgramUniform3dvEXT = (PFNGLPROGRAMUNIFORM3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3dvEXT")) == NULL) || r; + r = ((glProgramUniform4dEXT = (PFNGLPROGRAMUNIFORM4DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4dEXT")) == NULL) || r; + r = ((glProgramUniform4dvEXT = (PFNGLPROGRAMUNIFORM4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4dvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2dvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix2x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3dvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix2x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4dvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3dvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix3x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2dvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix3x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4dvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4dvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix4x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2dvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix4x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3dvEXT")) == NULL) || r; + r = ((glUniform1d = (PFNGLUNIFORM1DPROC)glewGetProcAddress((const GLubyte*)"glUniform1d")) == NULL) || r; + r = ((glUniform1dv = (PFNGLUNIFORM1DVPROC)glewGetProcAddress((const GLubyte*)"glUniform1dv")) == NULL) || r; + r = ((glUniform2d = (PFNGLUNIFORM2DPROC)glewGetProcAddress((const GLubyte*)"glUniform2d")) == NULL) || r; + r = ((glUniform2dv = (PFNGLUNIFORM2DVPROC)glewGetProcAddress((const GLubyte*)"glUniform2dv")) == NULL) || r; + r = ((glUniform3d = (PFNGLUNIFORM3DPROC)glewGetProcAddress((const GLubyte*)"glUniform3d")) == NULL) || r; + r = ((glUniform3dv = (PFNGLUNIFORM3DVPROC)glewGetProcAddress((const GLubyte*)"glUniform3dv")) == NULL) || r; + r = ((glUniform4d = (PFNGLUNIFORM4DPROC)glewGetProcAddress((const GLubyte*)"glUniform4d")) == NULL) || r; + r = ((glUniform4dv = (PFNGLUNIFORM4DVPROC)glewGetProcAddress((const GLubyte*)"glUniform4dv")) == NULL) || r; + r = ((glUniformMatrix2dv = (PFNGLUNIFORMMATRIX2DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2dv")) == NULL) || r; + r = ((glUniformMatrix2x3dv = (PFNGLUNIFORMMATRIX2X3DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x3dv")) == NULL) || r; + r = ((glUniformMatrix2x4dv = (PFNGLUNIFORMMATRIX2X4DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2x4dv")) == NULL) || r; + r = ((glUniformMatrix3dv = (PFNGLUNIFORMMATRIX3DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3dv")) == NULL) || r; + r = ((glUniformMatrix3x2dv = (PFNGLUNIFORMMATRIX3X2DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x2dv")) == NULL) || r; + r = ((glUniformMatrix3x4dv = (PFNGLUNIFORMMATRIX3X4DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3x4dv")) == NULL) || r; + r = ((glUniformMatrix4dv = (PFNGLUNIFORMMATRIX4DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4dv")) == NULL) || r; + r = ((glUniformMatrix4x2dv = (PFNGLUNIFORMMATRIX4X2DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x2dv")) == NULL) || r; + r = ((glUniformMatrix4x3dv = (PFNGLUNIFORMMATRIX4X3DVPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4x3dv")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_gpu_shader_fp64 */ + +#ifdef GL_ARB_half_float_pixel + +#endif /* GL_ARB_half_float_pixel */ + +#ifdef GL_ARB_half_float_vertex + +#endif /* GL_ARB_half_float_vertex */ + +#ifdef GL_ARB_imaging + +static GLboolean _glewInit_GL_ARB_imaging (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)"glBlendEquation")) == NULL) || r; + r = ((glColorSubTable = (PFNGLCOLORSUBTABLEPROC)glewGetProcAddress((const GLubyte*)"glColorSubTable")) == NULL) || r; + r = ((glColorTable = (PFNGLCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glColorTable")) == NULL) || r; + r = ((glColorTableParameterfv = (PFNGLCOLORTABLEPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterfv")) == NULL) || r; + r = ((glColorTableParameteriv = (PFNGLCOLORTABLEPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameteriv")) == NULL) || r; + r = ((glConvolutionFilter1D = (PFNGLCONVOLUTIONFILTER1DPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter1D")) == NULL) || r; + r = ((glConvolutionFilter2D = (PFNGLCONVOLUTIONFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter2D")) == NULL) || r; + r = ((glConvolutionParameterf = (PFNGLCONVOLUTIONPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterf")) == NULL) || r; + r = ((glConvolutionParameterfv = (PFNGLCONVOLUTIONPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfv")) == NULL) || r; + r = ((glConvolutionParameteri = (PFNGLCONVOLUTIONPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteri")) == NULL) || r; + r = ((glConvolutionParameteriv = (PFNGLCONVOLUTIONPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteriv")) == NULL) || r; + r = ((glCopyColorSubTable = (PFNGLCOPYCOLORSUBTABLEPROC)glewGetProcAddress((const GLubyte*)"glCopyColorSubTable")) == NULL) || r; + r = ((glCopyColorTable = (PFNGLCOPYCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glCopyColorTable")) == NULL) || r; + r = ((glCopyConvolutionFilter1D = (PFNGLCOPYCONVOLUTIONFILTER1DPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter1D")) == NULL) || r; + r = ((glCopyConvolutionFilter2D = (PFNGLCOPYCONVOLUTIONFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter2D")) == NULL) || r; + r = ((glGetColorTable = (PFNGLGETCOLORTABLEPROC)glewGetProcAddress((const GLubyte*)"glGetColorTable")) == NULL) || r; + r = ((glGetColorTableParameterfv = (PFNGLGETCOLORTABLEPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfv")) == NULL) || r; + r = ((glGetColorTableParameteriv = (PFNGLGETCOLORTABLEPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameteriv")) == NULL) || r; + r = ((glGetConvolutionFilter = (PFNGLGETCONVOLUTIONFILTERPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionFilter")) == NULL) || r; + r = ((glGetConvolutionParameterfv = (PFNGLGETCONVOLUTIONPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterfv")) == NULL) || r; + r = ((glGetConvolutionParameteriv = (PFNGLGETCONVOLUTIONPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameteriv")) == NULL) || r; + r = ((glGetHistogram = (PFNGLGETHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glGetHistogram")) == NULL) || r; + r = ((glGetHistogramParameterfv = (PFNGLGETHISTOGRAMPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterfv")) == NULL) || r; + r = ((glGetHistogramParameteriv = (PFNGLGETHISTOGRAMPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameteriv")) == NULL) || r; + r = ((glGetMinmax = (PFNGLGETMINMAXPROC)glewGetProcAddress((const GLubyte*)"glGetMinmax")) == NULL) || r; + r = ((glGetMinmaxParameterfv = (PFNGLGETMINMAXPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterfv")) == NULL) || r; + r = ((glGetMinmaxParameteriv = (PFNGLGETMINMAXPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameteriv")) == NULL) || r; + r = ((glGetSeparableFilter = (PFNGLGETSEPARABLEFILTERPROC)glewGetProcAddress((const GLubyte*)"glGetSeparableFilter")) == NULL) || r; + r = ((glHistogram = (PFNGLHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glHistogram")) == NULL) || r; + r = ((glMinmax = (PFNGLMINMAXPROC)glewGetProcAddress((const GLubyte*)"glMinmax")) == NULL) || r; + r = ((glResetHistogram = (PFNGLRESETHISTOGRAMPROC)glewGetProcAddress((const GLubyte*)"glResetHistogram")) == NULL) || r; + r = ((glResetMinmax = (PFNGLRESETMINMAXPROC)glewGetProcAddress((const GLubyte*)"glResetMinmax")) == NULL) || r; + r = ((glSeparableFilter2D = (PFNGLSEPARABLEFILTER2DPROC)glewGetProcAddress((const GLubyte*)"glSeparableFilter2D")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_imaging */ + +#ifdef GL_ARB_instanced_arrays + +static GLboolean _glewInit_GL_ARB_instanced_arrays (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawArraysInstancedARB = (PFNGLDRAWARRAYSINSTANCEDARBPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedARB")) == NULL) || r; + r = ((glDrawElementsInstancedARB = (PFNGLDRAWELEMENTSINSTANCEDARBPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedARB")) == NULL) || r; + r = ((glVertexAttribDivisorARB = (PFNGLVERTEXATTRIBDIVISORARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribDivisorARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_instanced_arrays */ + +#ifdef GL_ARB_map_buffer_range + +static GLboolean _glewInit_GL_ARB_map_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glFlushMappedBufferRange")) == NULL) || r; + r = ((glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glMapBufferRange")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_map_buffer_range */ + +#ifdef GL_ARB_matrix_palette + +static GLboolean _glewInit_GL_ARB_matrix_palette (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCurrentPaletteMatrixARB = (PFNGLCURRENTPALETTEMATRIXARBPROC)glewGetProcAddress((const GLubyte*)"glCurrentPaletteMatrixARB")) == NULL) || r; + r = ((glMatrixIndexPointerARB = (PFNGLMATRIXINDEXPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexPointerARB")) == NULL) || r; + r = ((glMatrixIndexubvARB = (PFNGLMATRIXINDEXUBVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexubvARB")) == NULL) || r; + r = ((glMatrixIndexuivARB = (PFNGLMATRIXINDEXUIVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexuivARB")) == NULL) || r; + r = ((glMatrixIndexusvARB = (PFNGLMATRIXINDEXUSVARBPROC)glewGetProcAddress((const GLubyte*)"glMatrixIndexusvARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_matrix_palette */ + +#ifdef GL_ARB_multisample + +static GLboolean _glewInit_GL_ARB_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSampleCoverageARB = (PFNGLSAMPLECOVERAGEARBPROC)glewGetProcAddress((const GLubyte*)"glSampleCoverageARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_multisample */ + +#ifdef GL_ARB_multitexture + +static GLboolean _glewInit_GL_ARB_multitexture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glActiveTextureARB")) == NULL) || r; + r = ((glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)glewGetProcAddress((const GLubyte*)"glClientActiveTextureARB")) == NULL) || r; + r = ((glMultiTexCoord1dARB = (PFNGLMULTITEXCOORD1DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dARB")) == NULL) || r; + r = ((glMultiTexCoord1dvARB = (PFNGLMULTITEXCOORD1DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1dvARB")) == NULL) || r; + r = ((glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fARB")) == NULL) || r; + r = ((glMultiTexCoord1fvARB = (PFNGLMULTITEXCOORD1FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1fvARB")) == NULL) || r; + r = ((glMultiTexCoord1iARB = (PFNGLMULTITEXCOORD1IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1iARB")) == NULL) || r; + r = ((glMultiTexCoord1ivARB = (PFNGLMULTITEXCOORD1IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1ivARB")) == NULL) || r; + r = ((glMultiTexCoord1sARB = (PFNGLMULTITEXCOORD1SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1sARB")) == NULL) || r; + r = ((glMultiTexCoord1svARB = (PFNGLMULTITEXCOORD1SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1svARB")) == NULL) || r; + r = ((glMultiTexCoord2dARB = (PFNGLMULTITEXCOORD2DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dARB")) == NULL) || r; + r = ((glMultiTexCoord2dvARB = (PFNGLMULTITEXCOORD2DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2dvARB")) == NULL) || r; + r = ((glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fARB")) == NULL) || r; + r = ((glMultiTexCoord2fvARB = (PFNGLMULTITEXCOORD2FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2fvARB")) == NULL) || r; + r = ((glMultiTexCoord2iARB = (PFNGLMULTITEXCOORD2IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2iARB")) == NULL) || r; + r = ((glMultiTexCoord2ivARB = (PFNGLMULTITEXCOORD2IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2ivARB")) == NULL) || r; + r = ((glMultiTexCoord2sARB = (PFNGLMULTITEXCOORD2SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2sARB")) == NULL) || r; + r = ((glMultiTexCoord2svARB = (PFNGLMULTITEXCOORD2SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2svARB")) == NULL) || r; + r = ((glMultiTexCoord3dARB = (PFNGLMULTITEXCOORD3DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dARB")) == NULL) || r; + r = ((glMultiTexCoord3dvARB = (PFNGLMULTITEXCOORD3DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3dvARB")) == NULL) || r; + r = ((glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fARB")) == NULL) || r; + r = ((glMultiTexCoord3fvARB = (PFNGLMULTITEXCOORD3FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3fvARB")) == NULL) || r; + r = ((glMultiTexCoord3iARB = (PFNGLMULTITEXCOORD3IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3iARB")) == NULL) || r; + r = ((glMultiTexCoord3ivARB = (PFNGLMULTITEXCOORD3IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3ivARB")) == NULL) || r; + r = ((glMultiTexCoord3sARB = (PFNGLMULTITEXCOORD3SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3sARB")) == NULL) || r; + r = ((glMultiTexCoord3svARB = (PFNGLMULTITEXCOORD3SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3svARB")) == NULL) || r; + r = ((glMultiTexCoord4dARB = (PFNGLMULTITEXCOORD4DARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dARB")) == NULL) || r; + r = ((glMultiTexCoord4dvARB = (PFNGLMULTITEXCOORD4DVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4dvARB")) == NULL) || r; + r = ((glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fARB")) == NULL) || r; + r = ((glMultiTexCoord4fvARB = (PFNGLMULTITEXCOORD4FVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4fvARB")) == NULL) || r; + r = ((glMultiTexCoord4iARB = (PFNGLMULTITEXCOORD4IARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4iARB")) == NULL) || r; + r = ((glMultiTexCoord4ivARB = (PFNGLMULTITEXCOORD4IVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4ivARB")) == NULL) || r; + r = ((glMultiTexCoord4sARB = (PFNGLMULTITEXCOORD4SARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4sARB")) == NULL) || r; + r = ((glMultiTexCoord4svARB = (PFNGLMULTITEXCOORD4SVARBPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4svARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_multitexture */ + +#ifdef GL_ARB_occlusion_query + +static GLboolean _glewInit_GL_ARB_occlusion_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glBeginQueryARB")) == NULL) || r; + r = ((glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueriesARB")) == NULL) || r; + r = ((glEndQueryARB = (PFNGLENDQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glEndQueryARB")) == NULL) || r; + r = ((glGenQueriesARB = (PFNGLGENQUERIESARBPROC)glewGetProcAddress((const GLubyte*)"glGenQueriesARB")) == NULL) || r; + r = ((glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectivARB")) == NULL) || r; + r = ((glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuivARB")) == NULL) || r; + r = ((glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetQueryivARB")) == NULL) || r; + r = ((glIsQueryARB = (PFNGLISQUERYARBPROC)glewGetProcAddress((const GLubyte*)"glIsQueryARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_occlusion_query */ + +#ifdef GL_ARB_occlusion_query2 + +#endif /* GL_ARB_occlusion_query2 */ + +#ifdef GL_ARB_pixel_buffer_object + +#endif /* GL_ARB_pixel_buffer_object */ + +#ifdef GL_ARB_point_parameters + +static GLboolean _glewInit_GL_ARB_point_parameters (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfARB")) == NULL) || r; + r = ((glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfvARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_point_parameters */ + +#ifdef GL_ARB_point_sprite + +#endif /* GL_ARB_point_sprite */ + +#ifdef GL_ARB_provoking_vertex + +static GLboolean _glewInit_GL_ARB_provoking_vertex (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC)glewGetProcAddress((const GLubyte*)"glProvokingVertex")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_provoking_vertex */ + +#ifdef GL_ARB_robustness + +static GLboolean _glewInit_GL_ARB_robustness (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetnColorTableARB = (PFNGLGETNCOLORTABLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetnColorTableARB")) == NULL) || r; + r = ((glGetnCompressedTexImageARB = (PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"glGetnCompressedTexImageARB")) == NULL) || r; + r = ((glGetnConvolutionFilterARB = (PFNGLGETNCONVOLUTIONFILTERARBPROC)glewGetProcAddress((const GLubyte*)"glGetnConvolutionFilterARB")) == NULL) || r; + r = ((glGetnHistogramARB = (PFNGLGETNHISTOGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glGetnHistogramARB")) == NULL) || r; + r = ((glGetnMapdvARB = (PFNGLGETNMAPDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnMapdvARB")) == NULL) || r; + r = ((glGetnMapfvARB = (PFNGLGETNMAPFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnMapfvARB")) == NULL) || r; + r = ((glGetnMapivARB = (PFNGLGETNMAPIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnMapivARB")) == NULL) || r; + r = ((glGetnMinmaxARB = (PFNGLGETNMINMAXARBPROC)glewGetProcAddress((const GLubyte*)"glGetnMinmaxARB")) == NULL) || r; + r = ((glGetnPixelMapfvARB = (PFNGLGETNPIXELMAPFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnPixelMapfvARB")) == NULL) || r; + r = ((glGetnPixelMapuivARB = (PFNGLGETNPIXELMAPUIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnPixelMapuivARB")) == NULL) || r; + r = ((glGetnPixelMapusvARB = (PFNGLGETNPIXELMAPUSVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnPixelMapusvARB")) == NULL) || r; + r = ((glGetnPolygonStippleARB = (PFNGLGETNPOLYGONSTIPPLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetnPolygonStippleARB")) == NULL) || r; + r = ((glGetnSeparableFilterARB = (PFNGLGETNSEPARABLEFILTERARBPROC)glewGetProcAddress((const GLubyte*)"glGetnSeparableFilterARB")) == NULL) || r; + r = ((glGetnTexImageARB = (PFNGLGETNTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"glGetnTexImageARB")) == NULL) || r; + r = ((glGetnUniformdvARB = (PFNGLGETNUNIFORMDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnUniformdvARB")) == NULL) || r; + r = ((glGetnUniformfvARB = (PFNGLGETNUNIFORMFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnUniformfvARB")) == NULL) || r; + r = ((glGetnUniformivARB = (PFNGLGETNUNIFORMIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnUniformivARB")) == NULL) || r; + r = ((glGetnUniformuivARB = (PFNGLGETNUNIFORMUIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetnUniformuivARB")) == NULL) || r; + r = ((glReadnPixelsARB = (PFNGLREADNPIXELSARBPROC)glewGetProcAddress((const GLubyte*)"glReadnPixelsARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_robustness */ + +#ifdef GL_ARB_sample_shading + +static GLboolean _glewInit_GL_ARB_sample_shading (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMinSampleShadingARB = (PFNGLMINSAMPLESHADINGARBPROC)glewGetProcAddress((const GLubyte*)"glMinSampleShadingARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_sample_shading */ + +#ifdef GL_ARB_sampler_objects + +static GLboolean _glewInit_GL_ARB_sampler_objects (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindSampler = (PFNGLBINDSAMPLERPROC)glewGetProcAddress((const GLubyte*)"glBindSampler")) == NULL) || r; + r = ((glDeleteSamplers = (PFNGLDELETESAMPLERSPROC)glewGetProcAddress((const GLubyte*)"glDeleteSamplers")) == NULL) || r; + r = ((glGenSamplers = (PFNGLGENSAMPLERSPROC)glewGetProcAddress((const GLubyte*)"glGenSamplers")) == NULL) || r; + r = ((glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC)glewGetProcAddress((const GLubyte*)"glGetSamplerParameterIiv")) == NULL) || r; + r = ((glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC)glewGetProcAddress((const GLubyte*)"glGetSamplerParameterIuiv")) == NULL) || r; + r = ((glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glGetSamplerParameterfv")) == NULL) || r; + r = ((glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetSamplerParameteriv")) == NULL) || r; + r = ((glIsSampler = (PFNGLISSAMPLERPROC)glewGetProcAddress((const GLubyte*)"glIsSampler")) == NULL) || r; + r = ((glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameterIiv")) == NULL) || r; + r = ((glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameterIuiv")) == NULL) || r; + r = ((glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameterf")) == NULL) || r; + r = ((glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameterfv")) == NULL) || r; + r = ((glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameteri")) == NULL) || r; + r = ((glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glSamplerParameteriv")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_sampler_objects */ + +#ifdef GL_ARB_seamless_cube_map + +#endif /* GL_ARB_seamless_cube_map */ + +#ifdef GL_ARB_separate_shader_objects + +static GLboolean _glewInit_GL_ARB_separate_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glActiveShaderProgram = (PFNGLACTIVESHADERPROGRAMPROC)glewGetProcAddress((const GLubyte*)"glActiveShaderProgram")) == NULL) || r; + r = ((glBindProgramPipeline = (PFNGLBINDPROGRAMPIPELINEPROC)glewGetProcAddress((const GLubyte*)"glBindProgramPipeline")) == NULL) || r; + r = ((glCreateShaderProgramv = (PFNGLCREATESHADERPROGRAMVPROC)glewGetProcAddress((const GLubyte*)"glCreateShaderProgramv")) == NULL) || r; + r = ((glDeleteProgramPipelines = (PFNGLDELETEPROGRAMPIPELINESPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgramPipelines")) == NULL) || r; + r = ((glGenProgramPipelines = (PFNGLGENPROGRAMPIPELINESPROC)glewGetProcAddress((const GLubyte*)"glGenProgramPipelines")) == NULL) || r; + r = ((glGetProgramPipelineInfoLog = (PFNGLGETPROGRAMPIPELINEINFOLOGPROC)glewGetProcAddress((const GLubyte*)"glGetProgramPipelineInfoLog")) == NULL) || r; + r = ((glGetProgramPipelineiv = (PFNGLGETPROGRAMPIPELINEIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramPipelineiv")) == NULL) || r; + r = ((glIsProgramPipeline = (PFNGLISPROGRAMPIPELINEPROC)glewGetProcAddress((const GLubyte*)"glIsProgramPipeline")) == NULL) || r; + r = ((glProgramUniform1d = (PFNGLPROGRAMUNIFORM1DPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1d")) == NULL) || r; + r = ((glProgramUniform1dv = (PFNGLPROGRAMUNIFORM1DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1dv")) == NULL) || r; + r = ((glProgramUniform1f = (PFNGLPROGRAMUNIFORM1FPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1f")) == NULL) || r; + r = ((glProgramUniform1fv = (PFNGLPROGRAMUNIFORM1FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1fv")) == NULL) || r; + r = ((glProgramUniform1i = (PFNGLPROGRAMUNIFORM1IPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1i")) == NULL) || r; + r = ((glProgramUniform1iv = (PFNGLPROGRAMUNIFORM1IVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1iv")) == NULL) || r; + r = ((glProgramUniform1ui = (PFNGLPROGRAMUNIFORM1UIPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1ui")) == NULL) || r; + r = ((glProgramUniform1uiv = (PFNGLPROGRAMUNIFORM1UIVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1uiv")) == NULL) || r; + r = ((glProgramUniform2d = (PFNGLPROGRAMUNIFORM2DPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2d")) == NULL) || r; + r = ((glProgramUniform2dv = (PFNGLPROGRAMUNIFORM2DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2dv")) == NULL) || r; + r = ((glProgramUniform2f = (PFNGLPROGRAMUNIFORM2FPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2f")) == NULL) || r; + r = ((glProgramUniform2fv = (PFNGLPROGRAMUNIFORM2FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2fv")) == NULL) || r; + r = ((glProgramUniform2i = (PFNGLPROGRAMUNIFORM2IPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2i")) == NULL) || r; + r = ((glProgramUniform2iv = (PFNGLPROGRAMUNIFORM2IVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2iv")) == NULL) || r; + r = ((glProgramUniform2ui = (PFNGLPROGRAMUNIFORM2UIPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2ui")) == NULL) || r; + r = ((glProgramUniform2uiv = (PFNGLPROGRAMUNIFORM2UIVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2uiv")) == NULL) || r; + r = ((glProgramUniform3d = (PFNGLPROGRAMUNIFORM3DPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3d")) == NULL) || r; + r = ((glProgramUniform3dv = (PFNGLPROGRAMUNIFORM3DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3dv")) == NULL) || r; + r = ((glProgramUniform3f = (PFNGLPROGRAMUNIFORM3FPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3f")) == NULL) || r; + r = ((glProgramUniform3fv = (PFNGLPROGRAMUNIFORM3FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3fv")) == NULL) || r; + r = ((glProgramUniform3i = (PFNGLPROGRAMUNIFORM3IPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3i")) == NULL) || r; + r = ((glProgramUniform3iv = (PFNGLPROGRAMUNIFORM3IVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3iv")) == NULL) || r; + r = ((glProgramUniform3ui = (PFNGLPROGRAMUNIFORM3UIPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3ui")) == NULL) || r; + r = ((glProgramUniform3uiv = (PFNGLPROGRAMUNIFORM3UIVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3uiv")) == NULL) || r; + r = ((glProgramUniform4d = (PFNGLPROGRAMUNIFORM4DPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4d")) == NULL) || r; + r = ((glProgramUniform4dv = (PFNGLPROGRAMUNIFORM4DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4dv")) == NULL) || r; + r = ((glProgramUniform4f = (PFNGLPROGRAMUNIFORM4FPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4f")) == NULL) || r; + r = ((glProgramUniform4fv = (PFNGLPROGRAMUNIFORM4FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4fv")) == NULL) || r; + r = ((glProgramUniform4i = (PFNGLPROGRAMUNIFORM4IPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4i")) == NULL) || r; + r = ((glProgramUniform4iv = (PFNGLPROGRAMUNIFORM4IVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4iv")) == NULL) || r; + r = ((glProgramUniform4ui = (PFNGLPROGRAMUNIFORM4UIPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4ui")) == NULL) || r; + r = ((glProgramUniform4uiv = (PFNGLPROGRAMUNIFORM4UIVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4uiv")) == NULL) || r; + r = ((glProgramUniformMatrix2dv = (PFNGLPROGRAMUNIFORMMATRIX2DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2dv")) == NULL) || r; + r = ((glProgramUniformMatrix2fv = (PFNGLPROGRAMUNIFORMMATRIX2FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2fv")) == NULL) || r; + r = ((glProgramUniformMatrix2x3dv = (PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3dv")) == NULL) || r; + r = ((glProgramUniformMatrix2x3fv = (PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3fv")) == NULL) || r; + r = ((glProgramUniformMatrix2x4dv = (PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4dv")) == NULL) || r; + r = ((glProgramUniformMatrix2x4fv = (PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4fv")) == NULL) || r; + r = ((glProgramUniformMatrix3dv = (PFNGLPROGRAMUNIFORMMATRIX3DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3dv")) == NULL) || r; + r = ((glProgramUniformMatrix3fv = (PFNGLPROGRAMUNIFORMMATRIX3FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3fv")) == NULL) || r; + r = ((glProgramUniformMatrix3x2dv = (PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2dv")) == NULL) || r; + r = ((glProgramUniformMatrix3x2fv = (PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2fv")) == NULL) || r; + r = ((glProgramUniformMatrix3x4dv = (PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4dv")) == NULL) || r; + r = ((glProgramUniformMatrix3x4fv = (PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4fv")) == NULL) || r; + r = ((glProgramUniformMatrix4dv = (PFNGLPROGRAMUNIFORMMATRIX4DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4dv")) == NULL) || r; + r = ((glProgramUniformMatrix4fv = (PFNGLPROGRAMUNIFORMMATRIX4FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4fv")) == NULL) || r; + r = ((glProgramUniformMatrix4x2dv = (PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2dv")) == NULL) || r; + r = ((glProgramUniformMatrix4x2fv = (PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2fv")) == NULL) || r; + r = ((glProgramUniformMatrix4x3dv = (PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3dv")) == NULL) || r; + r = ((glProgramUniformMatrix4x3fv = (PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3fv")) == NULL) || r; + r = ((glUseProgramStages = (PFNGLUSEPROGRAMSTAGESPROC)glewGetProcAddress((const GLubyte*)"glUseProgramStages")) == NULL) || r; + r = ((glValidateProgramPipeline = (PFNGLVALIDATEPROGRAMPIPELINEPROC)glewGetProcAddress((const GLubyte*)"glValidateProgramPipeline")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_separate_shader_objects */ + +#ifdef GL_ARB_shader_bit_encoding + +#endif /* GL_ARB_shader_bit_encoding */ + +#ifdef GL_ARB_shader_objects + +static GLboolean _glewInit_GL_ARB_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glAttachObjectARB")) == NULL) || r; + r = ((glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)glewGetProcAddress((const GLubyte*)"glCompileShaderARB")) == NULL) || r; + r = ((glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glCreateProgramObjectARB")) == NULL) || r; + r = ((glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glCreateShaderObjectARB")) == NULL) || r; + r = ((glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteObjectARB")) == NULL) || r; + r = ((glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glDetachObjectARB")) == NULL) || r; + r = ((glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformARB")) == NULL) || r; + r = ((glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC)glewGetProcAddress((const GLubyte*)"glGetAttachedObjectsARB")) == NULL) || r; + r = ((glGetHandleARB = (PFNGLGETHANDLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetHandleARB")) == NULL) || r; + r = ((glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)glewGetProcAddress((const GLubyte*)"glGetInfoLogARB")) == NULL) || r; + r = ((glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetObjectParameterfvARB")) == NULL) || r; + r = ((glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetObjectParameterivARB")) == NULL) || r; + r = ((glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC)glewGetProcAddress((const GLubyte*)"glGetShaderSourceARB")) == NULL) || r; + r = ((glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformLocationARB")) == NULL) || r; + r = ((glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformfvARB")) == NULL) || r; + r = ((glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetUniformivARB")) == NULL) || r; + r = ((glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glLinkProgramARB")) == NULL) || r; + r = ((glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)glewGetProcAddress((const GLubyte*)"glShaderSourceARB")) == NULL) || r; + r = ((glUniform1fARB = (PFNGLUNIFORM1FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1fARB")) == NULL) || r; + r = ((glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1fvARB")) == NULL) || r; + r = ((glUniform1iARB = (PFNGLUNIFORM1IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1iARB")) == NULL) || r; + r = ((glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform1ivARB")) == NULL) || r; + r = ((glUniform2fARB = (PFNGLUNIFORM2FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2fARB")) == NULL) || r; + r = ((glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2fvARB")) == NULL) || r; + r = ((glUniform2iARB = (PFNGLUNIFORM2IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2iARB")) == NULL) || r; + r = ((glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform2ivARB")) == NULL) || r; + r = ((glUniform3fARB = (PFNGLUNIFORM3FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3fARB")) == NULL) || r; + r = ((glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3fvARB")) == NULL) || r; + r = ((glUniform3iARB = (PFNGLUNIFORM3IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3iARB")) == NULL) || r; + r = ((glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform3ivARB")) == NULL) || r; + r = ((glUniform4fARB = (PFNGLUNIFORM4FARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4fARB")) == NULL) || r; + r = ((glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4fvARB")) == NULL) || r; + r = ((glUniform4iARB = (PFNGLUNIFORM4IARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4iARB")) == NULL) || r; + r = ((glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC)glewGetProcAddress((const GLubyte*)"glUniform4ivARB")) == NULL) || r; + r = ((glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix2fvARB")) == NULL) || r; + r = ((glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix3fvARB")) == NULL) || r; + r = ((glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC)glewGetProcAddress((const GLubyte*)"glUniformMatrix4fvARB")) == NULL) || r; + r = ((glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)glewGetProcAddress((const GLubyte*)"glUseProgramObjectARB")) == NULL) || r; + r = ((glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glValidateProgramARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_shader_objects */ + +#ifdef GL_ARB_shader_precision + +#endif /* GL_ARB_shader_precision */ + +#ifdef GL_ARB_shader_stencil_export + +#endif /* GL_ARB_shader_stencil_export */ + +#ifdef GL_ARB_shader_subroutine + +static GLboolean _glewInit_GL_ARB_shader_subroutine (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetActiveSubroutineName = (PFNGLGETACTIVESUBROUTINENAMEPROC)glewGetProcAddress((const GLubyte*)"glGetActiveSubroutineName")) == NULL) || r; + r = ((glGetActiveSubroutineUniformName = (PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC)glewGetProcAddress((const GLubyte*)"glGetActiveSubroutineUniformName")) == NULL) || r; + r = ((glGetActiveSubroutineUniformiv = (PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveSubroutineUniformiv")) == NULL) || r; + r = ((glGetProgramStageiv = (PFNGLGETPROGRAMSTAGEIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramStageiv")) == NULL) || r; + r = ((glGetSubroutineIndex = (PFNGLGETSUBROUTINEINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetSubroutineIndex")) == NULL) || r; + r = ((glGetSubroutineUniformLocation = (PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetSubroutineUniformLocation")) == NULL) || r; + r = ((glGetUniformSubroutineuiv = (PFNGLGETUNIFORMSUBROUTINEUIVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformSubroutineuiv")) == NULL) || r; + r = ((glUniformSubroutinesuiv = (PFNGLUNIFORMSUBROUTINESUIVPROC)glewGetProcAddress((const GLubyte*)"glUniformSubroutinesuiv")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_shader_subroutine */ + +#ifdef GL_ARB_shader_texture_lod + +#endif /* GL_ARB_shader_texture_lod */ + +#ifdef GL_ARB_shading_language_100 + +#endif /* GL_ARB_shading_language_100 */ + +#ifdef GL_ARB_shading_language_include + +static GLboolean _glewInit_GL_ARB_shading_language_include (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCompileShaderIncludeARB = (PFNGLCOMPILESHADERINCLUDEARBPROC)glewGetProcAddress((const GLubyte*)"glCompileShaderIncludeARB")) == NULL) || r; + r = ((glDeleteNamedStringARB = (PFNGLDELETENAMEDSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteNamedStringARB")) == NULL) || r; + r = ((glGetNamedStringARB = (PFNGLGETNAMEDSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glGetNamedStringARB")) == NULL) || r; + r = ((glGetNamedStringivARB = (PFNGLGETNAMEDSTRINGIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetNamedStringivARB")) == NULL) || r; + r = ((glIsNamedStringARB = (PFNGLISNAMEDSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glIsNamedStringARB")) == NULL) || r; + r = ((glNamedStringARB = (PFNGLNAMEDSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glNamedStringARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_shading_language_include */ + +#ifdef GL_ARB_shadow + +#endif /* GL_ARB_shadow */ + +#ifdef GL_ARB_shadow_ambient + +#endif /* GL_ARB_shadow_ambient */ + +#ifdef GL_ARB_sync + +static GLboolean _glewInit_GL_ARB_sync (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)glewGetProcAddress((const GLubyte*)"glClientWaitSync")) == NULL) || r; + r = ((glDeleteSync = (PFNGLDELETESYNCPROC)glewGetProcAddress((const GLubyte*)"glDeleteSync")) == NULL) || r; + r = ((glFenceSync = (PFNGLFENCESYNCPROC)glewGetProcAddress((const GLubyte*)"glFenceSync")) == NULL) || r; + r = ((glGetInteger64v = (PFNGLGETINTEGER64VPROC)glewGetProcAddress((const GLubyte*)"glGetInteger64v")) == NULL) || r; + r = ((glGetSynciv = (PFNGLGETSYNCIVPROC)glewGetProcAddress((const GLubyte*)"glGetSynciv")) == NULL) || r; + r = ((glIsSync = (PFNGLISSYNCPROC)glewGetProcAddress((const GLubyte*)"glIsSync")) == NULL) || r; + r = ((glWaitSync = (PFNGLWAITSYNCPROC)glewGetProcAddress((const GLubyte*)"glWaitSync")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_sync */ + +#ifdef GL_ARB_tessellation_shader + +static GLboolean _glewInit_GL_ARB_tessellation_shader (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPatchParameterfv = (PFNGLPATCHPARAMETERFVPROC)glewGetProcAddress((const GLubyte*)"glPatchParameterfv")) == NULL) || r; + r = ((glPatchParameteri = (PFNGLPATCHPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glPatchParameteri")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_tessellation_shader */ + +#ifdef GL_ARB_texture_border_clamp + +#endif /* GL_ARB_texture_border_clamp */ + +#ifdef GL_ARB_texture_buffer_object + +static GLboolean _glewInit_GL_ARB_texture_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexBufferARB = (PFNGLTEXBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glTexBufferARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_texture_buffer_object */ + +#ifdef GL_ARB_texture_buffer_object_rgb32 + +#endif /* GL_ARB_texture_buffer_object_rgb32 */ + +#ifdef GL_ARB_texture_compression + +static GLboolean _glewInit_GL_ARB_texture_compression (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCompressedTexImage1DARB = (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage1DARB")) == NULL) || r; + r = ((glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage2DARB")) == NULL) || r; + r = ((glCompressedTexImage3DARB = (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexImage3DARB")) == NULL) || r; + r = ((glCompressedTexSubImage1DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage1DARB")) == NULL) || r; + r = ((glCompressedTexSubImage2DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage2DARB")) == NULL) || r; + r = ((glCompressedTexSubImage3DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)glewGetProcAddress((const GLubyte*)"glCompressedTexSubImage3DARB")) == NULL) || r; + r = ((glGetCompressedTexImageARB = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTexImageARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_texture_compression */ + +#ifdef GL_ARB_texture_compression_bptc + +#endif /* GL_ARB_texture_compression_bptc */ + +#ifdef GL_ARB_texture_compression_rgtc + +#endif /* GL_ARB_texture_compression_rgtc */ + +#ifdef GL_ARB_texture_cube_map + +#endif /* GL_ARB_texture_cube_map */ + +#ifdef GL_ARB_texture_cube_map_array + +#endif /* GL_ARB_texture_cube_map_array */ + +#ifdef GL_ARB_texture_env_add + +#endif /* GL_ARB_texture_env_add */ + +#ifdef GL_ARB_texture_env_combine + +#endif /* GL_ARB_texture_env_combine */ + +#ifdef GL_ARB_texture_env_crossbar + +#endif /* GL_ARB_texture_env_crossbar */ + +#ifdef GL_ARB_texture_env_dot3 + +#endif /* GL_ARB_texture_env_dot3 */ + +#ifdef GL_ARB_texture_float + +#endif /* GL_ARB_texture_float */ + +#ifdef GL_ARB_texture_gather + +#endif /* GL_ARB_texture_gather */ + +#ifdef GL_ARB_texture_mirrored_repeat + +#endif /* GL_ARB_texture_mirrored_repeat */ + +#ifdef GL_ARB_texture_multisample + +static GLboolean _glewInit_GL_ARB_texture_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC)glewGetProcAddress((const GLubyte*)"glGetMultisamplefv")) == NULL) || r; + r = ((glSampleMaski = (PFNGLSAMPLEMASKIPROC)glewGetProcAddress((const GLubyte*)"glSampleMaski")) == NULL) || r; + r = ((glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glTexImage2DMultisample")) == NULL) || r; + r = ((glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glTexImage3DMultisample")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_texture_multisample */ + +#ifdef GL_ARB_texture_non_power_of_two + +#endif /* GL_ARB_texture_non_power_of_two */ + +#ifdef GL_ARB_texture_query_lod + +#endif /* GL_ARB_texture_query_lod */ + +#ifdef GL_ARB_texture_rectangle + +#endif /* GL_ARB_texture_rectangle */ + +#ifdef GL_ARB_texture_rg + +#endif /* GL_ARB_texture_rg */ + +#ifdef GL_ARB_texture_rgb10_a2ui + +#endif /* GL_ARB_texture_rgb10_a2ui */ + +#ifdef GL_ARB_texture_swizzle + +#endif /* GL_ARB_texture_swizzle */ + +#ifdef GL_ARB_timer_query + +static GLboolean _glewInit_GL_ARB_timer_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjecti64v")) == NULL) || r; + r = ((glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectui64v")) == NULL) || r; + r = ((glQueryCounter = (PFNGLQUERYCOUNTERPROC)glewGetProcAddress((const GLubyte*)"glQueryCounter")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_timer_query */ + +#ifdef GL_ARB_transform_feedback2 + +static GLboolean _glewInit_GL_ARB_transform_feedback2 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindTransformFeedback = (PFNGLBINDTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glBindTransformFeedback")) == NULL) || r; + r = ((glDeleteTransformFeedbacks = (PFNGLDELETETRANSFORMFEEDBACKSPROC)glewGetProcAddress((const GLubyte*)"glDeleteTransformFeedbacks")) == NULL) || r; + r = ((glDrawTransformFeedback = (PFNGLDRAWTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glDrawTransformFeedback")) == NULL) || r; + r = ((glGenTransformFeedbacks = (PFNGLGENTRANSFORMFEEDBACKSPROC)glewGetProcAddress((const GLubyte*)"glGenTransformFeedbacks")) == NULL) || r; + r = ((glIsTransformFeedback = (PFNGLISTRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glIsTransformFeedback")) == NULL) || r; + r = ((glPauseTransformFeedback = (PFNGLPAUSETRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glPauseTransformFeedback")) == NULL) || r; + r = ((glResumeTransformFeedback = (PFNGLRESUMETRANSFORMFEEDBACKPROC)glewGetProcAddress((const GLubyte*)"glResumeTransformFeedback")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_transform_feedback2 */ + +#ifdef GL_ARB_transform_feedback3 + +static GLboolean _glewInit_GL_ARB_transform_feedback3 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginQueryIndexed = (PFNGLBEGINQUERYINDEXEDPROC)glewGetProcAddress((const GLubyte*)"glBeginQueryIndexed")) == NULL) || r; + r = ((glDrawTransformFeedbackStream = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC)glewGetProcAddress((const GLubyte*)"glDrawTransformFeedbackStream")) == NULL) || r; + r = ((glEndQueryIndexed = (PFNGLENDQUERYINDEXEDPROC)glewGetProcAddress((const GLubyte*)"glEndQueryIndexed")) == NULL) || r; + r = ((glGetQueryIndexediv = (PFNGLGETQUERYINDEXEDIVPROC)glewGetProcAddress((const GLubyte*)"glGetQueryIndexediv")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_transform_feedback3 */ + +#ifdef GL_ARB_transpose_matrix + +static GLboolean _glewInit_GL_ARB_transpose_matrix (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glLoadTransposeMatrixdARB = (PFNGLLOADTRANSPOSEMATRIXDARBPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixdARB")) == NULL) || r; + r = ((glLoadTransposeMatrixfARB = (PFNGLLOADTRANSPOSEMATRIXFARBPROC)glewGetProcAddress((const GLubyte*)"glLoadTransposeMatrixfARB")) == NULL) || r; + r = ((glMultTransposeMatrixdARB = (PFNGLMULTTRANSPOSEMATRIXDARBPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixdARB")) == NULL) || r; + r = ((glMultTransposeMatrixfARB = (PFNGLMULTTRANSPOSEMATRIXFARBPROC)glewGetProcAddress((const GLubyte*)"glMultTransposeMatrixfARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_transpose_matrix */ + +#ifdef GL_ARB_uniform_buffer_object + +static GLboolean _glewInit_GL_ARB_uniform_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)glewGetProcAddress((const GLubyte*)"glBindBufferBase")) == NULL) || r; + r = ((glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glBindBufferRange")) == NULL) || r; + r = ((glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformBlockName")) == NULL) || r; + r = ((glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformBlockiv")) == NULL) || r; + r = ((glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformName")) == NULL) || r; + r = ((glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveUniformsiv")) == NULL) || r; + r = ((glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)glewGetProcAddress((const GLubyte*)"glGetIntegeri_v")) == NULL) || r; + r = ((glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetUniformBlockIndex")) == NULL) || r; + r = ((glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)glewGetProcAddress((const GLubyte*)"glGetUniformIndices")) == NULL) || r; + r = ((glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)glewGetProcAddress((const GLubyte*)"glUniformBlockBinding")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_uniform_buffer_object */ + +#ifdef GL_ARB_vertex_array_bgra + +#endif /* GL_ARB_vertex_array_bgra */ + +#ifdef GL_ARB_vertex_array_object + +static GLboolean _glewInit_GL_ARB_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)glewGetProcAddress((const GLubyte*)"glBindVertexArray")) == NULL) || r; + r = ((glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexArrays")) == NULL) || r; + r = ((glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)glewGetProcAddress((const GLubyte*)"glGenVertexArrays")) == NULL) || r; + r = ((glIsVertexArray = (PFNGLISVERTEXARRAYPROC)glewGetProcAddress((const GLubyte*)"glIsVertexArray")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_array_object */ + +#ifdef GL_ARB_vertex_attrib_64bit + +static GLboolean _glewInit_GL_ARB_vertex_attrib_64bit (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetVertexAttribLdv = (PFNGLGETVERTEXATTRIBLDVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribLdv")) == NULL) || r; + r = ((glVertexAttribL1d = (PFNGLVERTEXATTRIBL1DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1d")) == NULL) || r; + r = ((glVertexAttribL1dv = (PFNGLVERTEXATTRIBL1DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1dv")) == NULL) || r; + r = ((glVertexAttribL2d = (PFNGLVERTEXATTRIBL2DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2d")) == NULL) || r; + r = ((glVertexAttribL2dv = (PFNGLVERTEXATTRIBL2DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2dv")) == NULL) || r; + r = ((glVertexAttribL3d = (PFNGLVERTEXATTRIBL3DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3d")) == NULL) || r; + r = ((glVertexAttribL3dv = (PFNGLVERTEXATTRIBL3DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3dv")) == NULL) || r; + r = ((glVertexAttribL4d = (PFNGLVERTEXATTRIBL4DPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4d")) == NULL) || r; + r = ((glVertexAttribL4dv = (PFNGLVERTEXATTRIBL4DVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4dv")) == NULL) || r; + r = ((glVertexAttribLPointer = (PFNGLVERTEXATTRIBLPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribLPointer")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_attrib_64bit */ + +#ifdef GL_ARB_vertex_blend + +static GLboolean _glewInit_GL_ARB_vertex_blend (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glVertexBlendARB = (PFNGLVERTEXBLENDARBPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendARB")) == NULL) || r; + r = ((glWeightPointerARB = (PFNGLWEIGHTPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glWeightPointerARB")) == NULL) || r; + r = ((glWeightbvARB = (PFNGLWEIGHTBVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightbvARB")) == NULL) || r; + r = ((glWeightdvARB = (PFNGLWEIGHTDVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightdvARB")) == NULL) || r; + r = ((glWeightfvARB = (PFNGLWEIGHTFVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightfvARB")) == NULL) || r; + r = ((glWeightivARB = (PFNGLWEIGHTIVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightivARB")) == NULL) || r; + r = ((glWeightsvARB = (PFNGLWEIGHTSVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightsvARB")) == NULL) || r; + r = ((glWeightubvARB = (PFNGLWEIGHTUBVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightubvARB")) == NULL) || r; + r = ((glWeightuivARB = (PFNGLWEIGHTUIVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightuivARB")) == NULL) || r; + r = ((glWeightusvARB = (PFNGLWEIGHTUSVARBPROC)glewGetProcAddress((const GLubyte*)"glWeightusvARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_blend */ + +#ifdef GL_ARB_vertex_buffer_object + +static GLboolean _glewInit_GL_ARB_vertex_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindBufferARB = (PFNGLBINDBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glBindBufferARB")) == NULL) || r; + r = ((glBufferDataARB = (PFNGLBUFFERDATAARBPROC)glewGetProcAddress((const GLubyte*)"glBufferDataARB")) == NULL) || r; + r = ((glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)glewGetProcAddress((const GLubyte*)"glBufferSubDataARB")) == NULL) || r; + r = ((glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteBuffersARB")) == NULL) || r; + r = ((glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)glewGetProcAddress((const GLubyte*)"glGenBuffersARB")) == NULL) || r; + r = ((glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameterivARB")) == NULL) || r; + r = ((glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferPointervARB")) == NULL) || r; + r = ((glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)glewGetProcAddress((const GLubyte*)"glGetBufferSubDataARB")) == NULL) || r; + r = ((glIsBufferARB = (PFNGLISBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glIsBufferARB")) == NULL) || r; + r = ((glMapBufferARB = (PFNGLMAPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glMapBufferARB")) == NULL) || r; + r = ((glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"glUnmapBufferARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_buffer_object */ + +#ifdef GL_ARB_vertex_program + +static GLboolean _glewInit_GL_ARB_vertex_program (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindProgramARB = (PFNGLBINDPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glBindProgramARB")) == NULL) || r; + r = ((glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgramsARB")) == NULL) || r; + r = ((glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexAttribArrayARB")) == NULL) || r; + r = ((glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexAttribArrayARB")) == NULL) || r; + r = ((glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)glewGetProcAddress((const GLubyte*)"glGenProgramsARB")) == NULL) || r; + r = ((glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramEnvParameterdvARB")) == NULL) || r; + r = ((glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramEnvParameterfvARB")) == NULL) || r; + r = ((glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramLocalParameterdvARB")) == NULL) || r; + r = ((glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramLocalParameterfvARB")) == NULL) || r; + r = ((glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramStringARB")) == NULL) || r; + r = ((glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetProgramivARB")) == NULL) || r; + r = ((glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointervARB")) == NULL) || r; + r = ((glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdvARB")) == NULL) || r; + r = ((glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfvARB")) == NULL) || r; + r = ((glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribivARB")) == NULL) || r; + r = ((glIsProgramARB = (PFNGLISPROGRAMARBPROC)glewGetProcAddress((const GLubyte*)"glIsProgramARB")) == NULL) || r; + r = ((glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4dARB")) == NULL) || r; + r = ((glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4dvARB")) == NULL) || r; + r = ((glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4fARB")) == NULL) || r; + r = ((glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameter4fvARB")) == NULL) || r; + r = ((glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4dARB")) == NULL) || r; + r = ((glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4dvARB")) == NULL) || r; + r = ((glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4fARB")) == NULL) || r; + r = ((glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameter4fvARB")) == NULL) || r; + r = ((glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"glProgramStringARB")) == NULL) || r; + r = ((glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dARB")) == NULL) || r; + r = ((glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dvARB")) == NULL) || r; + r = ((glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fARB")) == NULL) || r; + r = ((glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fvARB")) == NULL) || r; + r = ((glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sARB")) == NULL) || r; + r = ((glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1svARB")) == NULL) || r; + r = ((glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dARB")) == NULL) || r; + r = ((glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dvARB")) == NULL) || r; + r = ((glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fARB")) == NULL) || r; + r = ((glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fvARB")) == NULL) || r; + r = ((glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sARB")) == NULL) || r; + r = ((glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2svARB")) == NULL) || r; + r = ((glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dARB")) == NULL) || r; + r = ((glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dvARB")) == NULL) || r; + r = ((glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fARB")) == NULL) || r; + r = ((glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fvARB")) == NULL) || r; + r = ((glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sARB")) == NULL) || r; + r = ((glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3svARB")) == NULL) || r; + r = ((glVertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NbvARB")) == NULL) || r; + r = ((glVertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NivARB")) == NULL) || r; + r = ((glVertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NsvARB")) == NULL) || r; + r = ((glVertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NubARB")) == NULL) || r; + r = ((glVertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NubvARB")) == NULL) || r; + r = ((glVertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NuivARB")) == NULL) || r; + r = ((glVertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4NusvARB")) == NULL) || r; + r = ((glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4bvARB")) == NULL) || r; + r = ((glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dARB")) == NULL) || r; + r = ((glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dvARB")) == NULL) || r; + r = ((glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fARB")) == NULL) || r; + r = ((glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fvARB")) == NULL) || r; + r = ((glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ivARB")) == NULL) || r; + r = ((glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sARB")) == NULL) || r; + r = ((glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4svARB")) == NULL) || r; + r = ((glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubvARB")) == NULL) || r; + r = ((glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uivARB")) == NULL) || r; + r = ((glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usvARB")) == NULL) || r; + r = ((glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointerARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_program */ + +#ifdef GL_ARB_vertex_shader + +static GLboolean _glewInit_GL_ARB_vertex_shader (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocationARB")) == NULL) || r; + r = ((glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAttribARB")) == NULL) || r; + r = ((glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC)glewGetProcAddress((const GLubyte*)"glGetAttribLocationARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_shader */ + +#ifdef GL_ARB_vertex_type_2_10_10_10_rev + +static GLboolean _glewInit_GL_ARB_vertex_type_2_10_10_10_rev (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorP3ui = (PFNGLCOLORP3UIPROC)glewGetProcAddress((const GLubyte*)"glColorP3ui")) == NULL) || r; + r = ((glColorP3uiv = (PFNGLCOLORP3UIVPROC)glewGetProcAddress((const GLubyte*)"glColorP3uiv")) == NULL) || r; + r = ((glColorP4ui = (PFNGLCOLORP4UIPROC)glewGetProcAddress((const GLubyte*)"glColorP4ui")) == NULL) || r; + r = ((glColorP4uiv = (PFNGLCOLORP4UIVPROC)glewGetProcAddress((const GLubyte*)"glColorP4uiv")) == NULL) || r; + r = ((glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP1ui")) == NULL) || r; + r = ((glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP1uiv")) == NULL) || r; + r = ((glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP2ui")) == NULL) || r; + r = ((glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP2uiv")) == NULL) || r; + r = ((glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP3ui")) == NULL) || r; + r = ((glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP3uiv")) == NULL) || r; + r = ((glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP4ui")) == NULL) || r; + r = ((glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordP4uiv")) == NULL) || r; + r = ((glNormalP3ui = (PFNGLNORMALP3UIPROC)glewGetProcAddress((const GLubyte*)"glNormalP3ui")) == NULL) || r; + r = ((glNormalP3uiv = (PFNGLNORMALP3UIVPROC)glewGetProcAddress((const GLubyte*)"glNormalP3uiv")) == NULL) || r; + r = ((glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorP3ui")) == NULL) || r; + r = ((glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorP3uiv")) == NULL) || r; + r = ((glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP1ui")) == NULL) || r; + r = ((glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP1uiv")) == NULL) || r; + r = ((glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP2ui")) == NULL) || r; + r = ((glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP2uiv")) == NULL) || r; + r = ((glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP3ui")) == NULL) || r; + r = ((glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP3uiv")) == NULL) || r; + r = ((glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP4ui")) == NULL) || r; + r = ((glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC)glewGetProcAddress((const GLubyte*)"glTexCoordP4uiv")) == NULL) || r; + r = ((glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP1ui")) == NULL) || r; + r = ((glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP1uiv")) == NULL) || r; + r = ((glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP2ui")) == NULL) || r; + r = ((glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP2uiv")) == NULL) || r; + r = ((glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP3ui")) == NULL) || r; + r = ((glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP3uiv")) == NULL) || r; + r = ((glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP4ui")) == NULL) || r; + r = ((glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribP4uiv")) == NULL) || r; + r = ((glVertexP2ui = (PFNGLVERTEXP2UIPROC)glewGetProcAddress((const GLubyte*)"glVertexP2ui")) == NULL) || r; + r = ((glVertexP2uiv = (PFNGLVERTEXP2UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexP2uiv")) == NULL) || r; + r = ((glVertexP3ui = (PFNGLVERTEXP3UIPROC)glewGetProcAddress((const GLubyte*)"glVertexP3ui")) == NULL) || r; + r = ((glVertexP3uiv = (PFNGLVERTEXP3UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexP3uiv")) == NULL) || r; + r = ((glVertexP4ui = (PFNGLVERTEXP4UIPROC)glewGetProcAddress((const GLubyte*)"glVertexP4ui")) == NULL) || r; + r = ((glVertexP4uiv = (PFNGLVERTEXP4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexP4uiv")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_type_2_10_10_10_rev */ + +#ifdef GL_ARB_viewport_array + +static GLboolean _glewInit_GL_ARB_viewport_array (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDepthRangeArrayv = (PFNGLDEPTHRANGEARRAYVPROC)glewGetProcAddress((const GLubyte*)"glDepthRangeArrayv")) == NULL) || r; + r = ((glDepthRangeIndexed = (PFNGLDEPTHRANGEINDEXEDPROC)glewGetProcAddress((const GLubyte*)"glDepthRangeIndexed")) == NULL) || r; + r = ((glGetDoublei_v = (PFNGLGETDOUBLEI_VPROC)glewGetProcAddress((const GLubyte*)"glGetDoublei_v")) == NULL) || r; + r = ((glGetFloati_v = (PFNGLGETFLOATI_VPROC)glewGetProcAddress((const GLubyte*)"glGetFloati_v")) == NULL) || r; + r = ((glScissorArrayv = (PFNGLSCISSORARRAYVPROC)glewGetProcAddress((const GLubyte*)"glScissorArrayv")) == NULL) || r; + r = ((glScissorIndexed = (PFNGLSCISSORINDEXEDPROC)glewGetProcAddress((const GLubyte*)"glScissorIndexed")) == NULL) || r; + r = ((glScissorIndexedv = (PFNGLSCISSORINDEXEDVPROC)glewGetProcAddress((const GLubyte*)"glScissorIndexedv")) == NULL) || r; + r = ((glViewportArrayv = (PFNGLVIEWPORTARRAYVPROC)glewGetProcAddress((const GLubyte*)"glViewportArrayv")) == NULL) || r; + r = ((glViewportIndexedf = (PFNGLVIEWPORTINDEXEDFPROC)glewGetProcAddress((const GLubyte*)"glViewportIndexedf")) == NULL) || r; + r = ((glViewportIndexedfv = (PFNGLVIEWPORTINDEXEDFVPROC)glewGetProcAddress((const GLubyte*)"glViewportIndexedfv")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_viewport_array */ + +#ifdef GL_ARB_window_pos + +static GLboolean _glewInit_GL_ARB_window_pos (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glWindowPos2dARB = (PFNGLWINDOWPOS2DARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dARB")) == NULL) || r; + r = ((glWindowPos2dvARB = (PFNGLWINDOWPOS2DVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dvARB")) == NULL) || r; + r = ((glWindowPos2fARB = (PFNGLWINDOWPOS2FARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fARB")) == NULL) || r; + r = ((glWindowPos2fvARB = (PFNGLWINDOWPOS2FVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fvARB")) == NULL) || r; + r = ((glWindowPos2iARB = (PFNGLWINDOWPOS2IARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iARB")) == NULL) || r; + r = ((glWindowPos2ivARB = (PFNGLWINDOWPOS2IVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2ivARB")) == NULL) || r; + r = ((glWindowPos2sARB = (PFNGLWINDOWPOS2SARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sARB")) == NULL) || r; + r = ((glWindowPos2svARB = (PFNGLWINDOWPOS2SVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2svARB")) == NULL) || r; + r = ((glWindowPos3dARB = (PFNGLWINDOWPOS3DARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dARB")) == NULL) || r; + r = ((glWindowPos3dvARB = (PFNGLWINDOWPOS3DVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dvARB")) == NULL) || r; + r = ((glWindowPos3fARB = (PFNGLWINDOWPOS3FARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fARB")) == NULL) || r; + r = ((glWindowPos3fvARB = (PFNGLWINDOWPOS3FVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fvARB")) == NULL) || r; + r = ((glWindowPos3iARB = (PFNGLWINDOWPOS3IARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iARB")) == NULL) || r; + r = ((glWindowPos3ivARB = (PFNGLWINDOWPOS3IVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3ivARB")) == NULL) || r; + r = ((glWindowPos3sARB = (PFNGLWINDOWPOS3SARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sARB")) == NULL) || r; + r = ((glWindowPos3svARB = (PFNGLWINDOWPOS3SVARBPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3svARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_window_pos */ + +#ifdef GL_ATIX_point_sprites + +#endif /* GL_ATIX_point_sprites */ + +#ifdef GL_ATIX_texture_env_combine3 + +#endif /* GL_ATIX_texture_env_combine3 */ + +#ifdef GL_ATIX_texture_env_route + +#endif /* GL_ATIX_texture_env_route */ + +#ifdef GL_ATIX_vertex_shader_output_point_size + +#endif /* GL_ATIX_vertex_shader_output_point_size */ + +#ifdef GL_ATI_draw_buffers + +static GLboolean _glewInit_GL_ATI_draw_buffers (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawBuffersATI = (PFNGLDRAWBUFFERSATIPROC)glewGetProcAddress((const GLubyte*)"glDrawBuffersATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_draw_buffers */ + +#ifdef GL_ATI_element_array + +static GLboolean _glewInit_GL_ATI_element_array (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawElementArrayATI = (PFNGLDRAWELEMENTARRAYATIPROC)glewGetProcAddress((const GLubyte*)"glDrawElementArrayATI")) == NULL) || r; + r = ((glDrawRangeElementArrayATI = (PFNGLDRAWRANGEELEMENTARRAYATIPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementArrayATI")) == NULL) || r; + r = ((glElementPointerATI = (PFNGLELEMENTPOINTERATIPROC)glewGetProcAddress((const GLubyte*)"glElementPointerATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_element_array */ + +#ifdef GL_ATI_envmap_bumpmap + +static GLboolean _glewInit_GL_ATI_envmap_bumpmap (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetTexBumpParameterfvATI = (PFNGLGETTEXBUMPPARAMETERFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetTexBumpParameterfvATI")) == NULL) || r; + r = ((glGetTexBumpParameterivATI = (PFNGLGETTEXBUMPPARAMETERIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetTexBumpParameterivATI")) == NULL) || r; + r = ((glTexBumpParameterfvATI = (PFNGLTEXBUMPPARAMETERFVATIPROC)glewGetProcAddress((const GLubyte*)"glTexBumpParameterfvATI")) == NULL) || r; + r = ((glTexBumpParameterivATI = (PFNGLTEXBUMPPARAMETERIVATIPROC)glewGetProcAddress((const GLubyte*)"glTexBumpParameterivATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_envmap_bumpmap */ + +#ifdef GL_ATI_fragment_shader + +static GLboolean _glewInit_GL_ATI_fragment_shader (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAlphaFragmentOp1ATI = (PFNGLALPHAFRAGMENTOP1ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp1ATI")) == NULL) || r; + r = ((glAlphaFragmentOp2ATI = (PFNGLALPHAFRAGMENTOP2ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp2ATI")) == NULL) || r; + r = ((glAlphaFragmentOp3ATI = (PFNGLALPHAFRAGMENTOP3ATIPROC)glewGetProcAddress((const GLubyte*)"glAlphaFragmentOp3ATI")) == NULL) || r; + r = ((glBeginFragmentShaderATI = (PFNGLBEGINFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glBeginFragmentShaderATI")) == NULL) || r; + r = ((glBindFragmentShaderATI = (PFNGLBINDFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glBindFragmentShaderATI")) == NULL) || r; + r = ((glColorFragmentOp1ATI = (PFNGLCOLORFRAGMENTOP1ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp1ATI")) == NULL) || r; + r = ((glColorFragmentOp2ATI = (PFNGLCOLORFRAGMENTOP2ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp2ATI")) == NULL) || r; + r = ((glColorFragmentOp3ATI = (PFNGLCOLORFRAGMENTOP3ATIPROC)glewGetProcAddress((const GLubyte*)"glColorFragmentOp3ATI")) == NULL) || r; + r = ((glDeleteFragmentShaderATI = (PFNGLDELETEFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glDeleteFragmentShaderATI")) == NULL) || r; + r = ((glEndFragmentShaderATI = (PFNGLENDFRAGMENTSHADERATIPROC)glewGetProcAddress((const GLubyte*)"glEndFragmentShaderATI")) == NULL) || r; + r = ((glGenFragmentShadersATI = (PFNGLGENFRAGMENTSHADERSATIPROC)glewGetProcAddress((const GLubyte*)"glGenFragmentShadersATI")) == NULL) || r; + r = ((glPassTexCoordATI = (PFNGLPASSTEXCOORDATIPROC)glewGetProcAddress((const GLubyte*)"glPassTexCoordATI")) == NULL) || r; + r = ((glSampleMapATI = (PFNGLSAMPLEMAPATIPROC)glewGetProcAddress((const GLubyte*)"glSampleMapATI")) == NULL) || r; + r = ((glSetFragmentShaderConstantATI = (PFNGLSETFRAGMENTSHADERCONSTANTATIPROC)glewGetProcAddress((const GLubyte*)"glSetFragmentShaderConstantATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_fragment_shader */ + +#ifdef GL_ATI_map_object_buffer + +static GLboolean _glewInit_GL_ATI_map_object_buffer (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMapObjectBufferATI = (PFNGLMAPOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glMapObjectBufferATI")) == NULL) || r; + r = ((glUnmapObjectBufferATI = (PFNGLUNMAPOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glUnmapObjectBufferATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_map_object_buffer */ + +#ifdef GL_ATI_meminfo + +#endif /* GL_ATI_meminfo */ + +#ifdef GL_ATI_pn_triangles + +static GLboolean _glewInit_GL_ATI_pn_triangles (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPNTrianglesfATI = (PFNGLPNTRIANGLESFATIPROC)glewGetProcAddress((const GLubyte*)"glPNTrianglesfATI")) == NULL) || r; + r = ((glPNTrianglesiATI = (PFNGLPNTRIANGLESIATIPROC)glewGetProcAddress((const GLubyte*)"glPNTrianglesiATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_pn_triangles */ + +#ifdef GL_ATI_separate_stencil + +static GLboolean _glewInit_GL_ATI_separate_stencil (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glStencilFuncSeparateATI = (PFNGLSTENCILFUNCSEPARATEATIPROC)glewGetProcAddress((const GLubyte*)"glStencilFuncSeparateATI")) == NULL) || r; + r = ((glStencilOpSeparateATI = (PFNGLSTENCILOPSEPARATEATIPROC)glewGetProcAddress((const GLubyte*)"glStencilOpSeparateATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_separate_stencil */ + +#ifdef GL_ATI_shader_texture_lod + +#endif /* GL_ATI_shader_texture_lod */ + +#ifdef GL_ATI_text_fragment_shader + +#endif /* GL_ATI_text_fragment_shader */ + +#ifdef GL_ATI_texture_compression_3dc + +#endif /* GL_ATI_texture_compression_3dc */ + +#ifdef GL_ATI_texture_env_combine3 + +#endif /* GL_ATI_texture_env_combine3 */ + +#ifdef GL_ATI_texture_float + +#endif /* GL_ATI_texture_float */ + +#ifdef GL_ATI_texture_mirror_once + +#endif /* GL_ATI_texture_mirror_once */ + +#ifdef GL_ATI_vertex_array_object + +static GLboolean _glewInit_GL_ATI_vertex_array_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glArrayObjectATI = (PFNGLARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glArrayObjectATI")) == NULL) || r; + r = ((glFreeObjectBufferATI = (PFNGLFREEOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glFreeObjectBufferATI")) == NULL) || r; + r = ((glGetArrayObjectfvATI = (PFNGLGETARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetArrayObjectfvATI")) == NULL) || r; + r = ((glGetArrayObjectivATI = (PFNGLGETARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetArrayObjectivATI")) == NULL) || r; + r = ((glGetObjectBufferfvATI = (PFNGLGETOBJECTBUFFERFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetObjectBufferfvATI")) == NULL) || r; + r = ((glGetObjectBufferivATI = (PFNGLGETOBJECTBUFFERIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetObjectBufferivATI")) == NULL) || r; + r = ((glGetVariantArrayObjectfvATI = (PFNGLGETVARIANTARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVariantArrayObjectfvATI")) == NULL) || r; + r = ((glGetVariantArrayObjectivATI = (PFNGLGETVARIANTARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVariantArrayObjectivATI")) == NULL) || r; + r = ((glIsObjectBufferATI = (PFNGLISOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glIsObjectBufferATI")) == NULL) || r; + r = ((glNewObjectBufferATI = (PFNGLNEWOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glNewObjectBufferATI")) == NULL) || r; + r = ((glUpdateObjectBufferATI = (PFNGLUPDATEOBJECTBUFFERATIPROC)glewGetProcAddress((const GLubyte*)"glUpdateObjectBufferATI")) == NULL) || r; + r = ((glVariantArrayObjectATI = (PFNGLVARIANTARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glVariantArrayObjectATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_vertex_array_object */ + +#ifdef GL_ATI_vertex_attrib_array_object + +static GLboolean _glewInit_GL_ATI_vertex_attrib_array_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetVertexAttribArrayObjectfvATI = (PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribArrayObjectfvATI")) == NULL) || r; + r = ((glGetVertexAttribArrayObjectivATI = (PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribArrayObjectivATI")) == NULL) || r; + r = ((glVertexAttribArrayObjectATI = (PFNGLVERTEXATTRIBARRAYOBJECTATIPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribArrayObjectATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_vertex_attrib_array_object */ + +#ifdef GL_ATI_vertex_streams + +static GLboolean _glewInit_GL_ATI_vertex_streams (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClientActiveVertexStreamATI = (PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC)glewGetProcAddress((const GLubyte*)"glClientActiveVertexStreamATI")) == NULL) || r; + r = ((glNormalStream3bATI = (PFNGLNORMALSTREAM3BATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3bATI")) == NULL) || r; + r = ((glNormalStream3bvATI = (PFNGLNORMALSTREAM3BVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3bvATI")) == NULL) || r; + r = ((glNormalStream3dATI = (PFNGLNORMALSTREAM3DATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3dATI")) == NULL) || r; + r = ((glNormalStream3dvATI = (PFNGLNORMALSTREAM3DVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3dvATI")) == NULL) || r; + r = ((glNormalStream3fATI = (PFNGLNORMALSTREAM3FATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3fATI")) == NULL) || r; + r = ((glNormalStream3fvATI = (PFNGLNORMALSTREAM3FVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3fvATI")) == NULL) || r; + r = ((glNormalStream3iATI = (PFNGLNORMALSTREAM3IATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3iATI")) == NULL) || r; + r = ((glNormalStream3ivATI = (PFNGLNORMALSTREAM3IVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3ivATI")) == NULL) || r; + r = ((glNormalStream3sATI = (PFNGLNORMALSTREAM3SATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3sATI")) == NULL) || r; + r = ((glNormalStream3svATI = (PFNGLNORMALSTREAM3SVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3svATI")) == NULL) || r; + r = ((glVertexBlendEnvfATI = (PFNGLVERTEXBLENDENVFATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnvfATI")) == NULL) || r; + r = ((glVertexBlendEnviATI = (PFNGLVERTEXBLENDENVIATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnviATI")) == NULL) || r; + r = ((glVertexStream2dATI = (PFNGLVERTEXSTREAM2DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dATI")) == NULL) || r; + r = ((glVertexStream2dvATI = (PFNGLVERTEXSTREAM2DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dvATI")) == NULL) || r; + r = ((glVertexStream2fATI = (PFNGLVERTEXSTREAM2FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2fATI")) == NULL) || r; + r = ((glVertexStream2fvATI = (PFNGLVERTEXSTREAM2FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2fvATI")) == NULL) || r; + r = ((glVertexStream2iATI = (PFNGLVERTEXSTREAM2IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2iATI")) == NULL) || r; + r = ((glVertexStream2ivATI = (PFNGLVERTEXSTREAM2IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2ivATI")) == NULL) || r; + r = ((glVertexStream2sATI = (PFNGLVERTEXSTREAM2SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2sATI")) == NULL) || r; + r = ((glVertexStream2svATI = (PFNGLVERTEXSTREAM2SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2svATI")) == NULL) || r; + r = ((glVertexStream3dATI = (PFNGLVERTEXSTREAM3DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3dATI")) == NULL) || r; + r = ((glVertexStream3dvATI = (PFNGLVERTEXSTREAM3DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3dvATI")) == NULL) || r; + r = ((glVertexStream3fATI = (PFNGLVERTEXSTREAM3FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3fATI")) == NULL) || r; + r = ((glVertexStream3fvATI = (PFNGLVERTEXSTREAM3FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3fvATI")) == NULL) || r; + r = ((glVertexStream3iATI = (PFNGLVERTEXSTREAM3IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3iATI")) == NULL) || r; + r = ((glVertexStream3ivATI = (PFNGLVERTEXSTREAM3IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3ivATI")) == NULL) || r; + r = ((glVertexStream3sATI = (PFNGLVERTEXSTREAM3SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3sATI")) == NULL) || r; + r = ((glVertexStream3svATI = (PFNGLVERTEXSTREAM3SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream3svATI")) == NULL) || r; + r = ((glVertexStream4dATI = (PFNGLVERTEXSTREAM4DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4dATI")) == NULL) || r; + r = ((glVertexStream4dvATI = (PFNGLVERTEXSTREAM4DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4dvATI")) == NULL) || r; + r = ((glVertexStream4fATI = (PFNGLVERTEXSTREAM4FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4fATI")) == NULL) || r; + r = ((glVertexStream4fvATI = (PFNGLVERTEXSTREAM4FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4fvATI")) == NULL) || r; + r = ((glVertexStream4iATI = (PFNGLVERTEXSTREAM4IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4iATI")) == NULL) || r; + r = ((glVertexStream4ivATI = (PFNGLVERTEXSTREAM4IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4ivATI")) == NULL) || r; + r = ((glVertexStream4sATI = (PFNGLVERTEXSTREAM4SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4sATI")) == NULL) || r; + r = ((glVertexStream4svATI = (PFNGLVERTEXSTREAM4SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream4svATI")) == NULL) || r; + + return r; +} + +#endif /* GL_ATI_vertex_streams */ + +#ifdef GL_EXT_422_pixels + +#endif /* GL_EXT_422_pixels */ + +#ifdef GL_EXT_Cg_shader + +#endif /* GL_EXT_Cg_shader */ + +#ifdef GL_EXT_abgr + +#endif /* GL_EXT_abgr */ + +#ifdef GL_EXT_bgra + +#endif /* GL_EXT_bgra */ + +#ifdef GL_EXT_bindable_uniform + +static GLboolean _glewInit_GL_EXT_bindable_uniform (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetUniformBufferSizeEXT = (PFNGLGETUNIFORMBUFFERSIZEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformBufferSizeEXT")) == NULL) || r; + r = ((glGetUniformOffsetEXT = (PFNGLGETUNIFORMOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformOffsetEXT")) == NULL) || r; + r = ((glUniformBufferEXT = (PFNGLUNIFORMBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glUniformBufferEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_bindable_uniform */ + +#ifdef GL_EXT_blend_color + +static GLboolean _glewInit_GL_EXT_blend_color (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendColorEXT = (PFNGLBLENDCOLOREXTPROC)glewGetProcAddress((const GLubyte*)"glBlendColorEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_blend_color */ + +#ifdef GL_EXT_blend_equation_separate + +static GLboolean _glewInit_GL_EXT_blend_equation_separate (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendEquationSeparateEXT = (PFNGLBLENDEQUATIONSEPARATEEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparateEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_blend_equation_separate */ + +#ifdef GL_EXT_blend_func_separate + +static GLboolean _glewInit_GL_EXT_blend_func_separate (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendFuncSeparateEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_blend_func_separate */ + +#ifdef GL_EXT_blend_logic_op + +#endif /* GL_EXT_blend_logic_op */ + +#ifdef GL_EXT_blend_minmax + +static GLboolean _glewInit_GL_EXT_blend_minmax (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendEquationEXT = (PFNGLBLENDEQUATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_blend_minmax */ + +#ifdef GL_EXT_blend_subtract + +#endif /* GL_EXT_blend_subtract */ + +#ifdef GL_EXT_clip_volume_hint + +#endif /* GL_EXT_clip_volume_hint */ + +#ifdef GL_EXT_cmyka + +#endif /* GL_EXT_cmyka */ + +#ifdef GL_EXT_color_subtable + +static GLboolean _glewInit_GL_EXT_color_subtable (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorSubTableEXT = (PFNGLCOLORSUBTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glColorSubTableEXT")) == NULL) || r; + r = ((glCopyColorSubTableEXT = (PFNGLCOPYCOLORSUBTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyColorSubTableEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_color_subtable */ + +#ifdef GL_EXT_compiled_vertex_array + +static GLboolean _glewInit_GL_EXT_compiled_vertex_array (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glLockArraysEXT")) == NULL) || r; + r = ((glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glUnlockArraysEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_compiled_vertex_array */ + +#ifdef GL_EXT_convolution + +static GLboolean _glewInit_GL_EXT_convolution (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glConvolutionFilter1DEXT = (PFNGLCONVOLUTIONFILTER1DEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter1DEXT")) == NULL) || r; + r = ((glConvolutionFilter2DEXT = (PFNGLCONVOLUTIONFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionFilter2DEXT")) == NULL) || r; + r = ((glConvolutionParameterfEXT = (PFNGLCONVOLUTIONPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfEXT")) == NULL) || r; + r = ((glConvolutionParameterfvEXT = (PFNGLCONVOLUTIONPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterfvEXT")) == NULL) || r; + r = ((glConvolutionParameteriEXT = (PFNGLCONVOLUTIONPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameteriEXT")) == NULL) || r; + r = ((glConvolutionParameterivEXT = (PFNGLCONVOLUTIONPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glConvolutionParameterivEXT")) == NULL) || r; + r = ((glCopyConvolutionFilter1DEXT = (PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter1DEXT")) == NULL) || r; + r = ((glCopyConvolutionFilter2DEXT = (PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyConvolutionFilter2DEXT")) == NULL) || r; + r = ((glGetConvolutionFilterEXT = (PFNGLGETCONVOLUTIONFILTEREXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionFilterEXT")) == NULL) || r; + r = ((glGetConvolutionParameterfvEXT = (PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterfvEXT")) == NULL) || r; + r = ((glGetConvolutionParameterivEXT = (PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetConvolutionParameterivEXT")) == NULL) || r; + r = ((glGetSeparableFilterEXT = (PFNGLGETSEPARABLEFILTEREXTPROC)glewGetProcAddress((const GLubyte*)"glGetSeparableFilterEXT")) == NULL) || r; + r = ((glSeparableFilter2DEXT = (PFNGLSEPARABLEFILTER2DEXTPROC)glewGetProcAddress((const GLubyte*)"glSeparableFilter2DEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_convolution */ + +#ifdef GL_EXT_coordinate_frame + +static GLboolean _glewInit_GL_EXT_coordinate_frame (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBinormalPointerEXT = (PFNGLBINORMALPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glBinormalPointerEXT")) == NULL) || r; + r = ((glTangentPointerEXT = (PFNGLTANGENTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glTangentPointerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_coordinate_frame */ + +#ifdef GL_EXT_copy_texture + +static GLboolean _glewInit_GL_EXT_copy_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCopyTexImage1DEXT = (PFNGLCOPYTEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexImage1DEXT")) == NULL) || r; + r = ((glCopyTexImage2DEXT = (PFNGLCOPYTEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexImage2DEXT")) == NULL) || r; + r = ((glCopyTexSubImage1DEXT = (PFNGLCOPYTEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage1DEXT")) == NULL) || r; + r = ((glCopyTexSubImage2DEXT = (PFNGLCOPYTEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage2DEXT")) == NULL) || r; + r = ((glCopyTexSubImage3DEXT = (PFNGLCOPYTEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTexSubImage3DEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_copy_texture */ + +#ifdef GL_EXT_cull_vertex + +static GLboolean _glewInit_GL_EXT_cull_vertex (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCullParameterdvEXT = (PFNGLCULLPARAMETERDVEXTPROC)glewGetProcAddress((const GLubyte*)"glCullParameterdvEXT")) == NULL) || r; + r = ((glCullParameterfvEXT = (PFNGLCULLPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glCullParameterfvEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_cull_vertex */ + +#ifdef GL_EXT_depth_bounds_test + +static GLboolean _glewInit_GL_EXT_depth_bounds_test (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDepthBoundsEXT = (PFNGLDEPTHBOUNDSEXTPROC)glewGetProcAddress((const GLubyte*)"glDepthBoundsEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_depth_bounds_test */ + +#ifdef GL_EXT_direct_state_access + +static GLboolean _glewInit_GL_EXT_direct_state_access (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindMultiTextureEXT = (PFNGLBINDMULTITEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glBindMultiTextureEXT")) == NULL) || r; + r = ((glCheckNamedFramebufferStatusEXT = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC)glewGetProcAddress((const GLubyte*)"glCheckNamedFramebufferStatusEXT")) == NULL) || r; + r = ((glClientAttribDefaultEXT = (PFNGLCLIENTATTRIBDEFAULTEXTPROC)glewGetProcAddress((const GLubyte*)"glClientAttribDefaultEXT")) == NULL) || r; + r = ((glCompressedMultiTexImage1DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexImage1DEXT")) == NULL) || r; + r = ((glCompressedMultiTexImage2DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexImage2DEXT")) == NULL) || r; + r = ((glCompressedMultiTexImage3DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexImage3DEXT")) == NULL) || r; + r = ((glCompressedMultiTexSubImage1DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexSubImage1DEXT")) == NULL) || r; + r = ((glCompressedMultiTexSubImage2DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexSubImage2DEXT")) == NULL) || r; + r = ((glCompressedMultiTexSubImage3DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedMultiTexSubImage3DEXT")) == NULL) || r; + r = ((glCompressedTextureImage1DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureImage1DEXT")) == NULL) || r; + r = ((glCompressedTextureImage2DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureImage2DEXT")) == NULL) || r; + r = ((glCompressedTextureImage3DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureImage3DEXT")) == NULL) || r; + r = ((glCompressedTextureSubImage1DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureSubImage1DEXT")) == NULL) || r; + r = ((glCompressedTextureSubImage2DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureSubImage2DEXT")) == NULL) || r; + r = ((glCompressedTextureSubImage3DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCompressedTextureSubImage3DEXT")) == NULL) || r; + r = ((glCopyMultiTexImage1DEXT = (PFNGLCOPYMULTITEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexImage1DEXT")) == NULL) || r; + r = ((glCopyMultiTexImage2DEXT = (PFNGLCOPYMULTITEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexImage2DEXT")) == NULL) || r; + r = ((glCopyMultiTexSubImage1DEXT = (PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexSubImage1DEXT")) == NULL) || r; + r = ((glCopyMultiTexSubImage2DEXT = (PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexSubImage2DEXT")) == NULL) || r; + r = ((glCopyMultiTexSubImage3DEXT = (PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyMultiTexSubImage3DEXT")) == NULL) || r; + r = ((glCopyTextureImage1DEXT = (PFNGLCOPYTEXTUREIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureImage1DEXT")) == NULL) || r; + r = ((glCopyTextureImage2DEXT = (PFNGLCOPYTEXTUREIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureImage2DEXT")) == NULL) || r; + r = ((glCopyTextureSubImage1DEXT = (PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureSubImage1DEXT")) == NULL) || r; + r = ((glCopyTextureSubImage2DEXT = (PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureSubImage2DEXT")) == NULL) || r; + r = ((glCopyTextureSubImage3DEXT = (PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glCopyTextureSubImage3DEXT")) == NULL) || r; + r = ((glDisableClientStateIndexedEXT = (PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableClientStateIndexedEXT")) == NULL) || r; + r = ((glDisableClientStateiEXT = (PFNGLDISABLECLIENTSTATEIEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableClientStateiEXT")) == NULL) || r; + r = ((glDisableVertexArrayAttribEXT = (PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexArrayAttribEXT")) == NULL) || r; + r = ((glDisableVertexArrayEXT = (PFNGLDISABLEVERTEXARRAYEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableVertexArrayEXT")) == NULL) || r; + r = ((glEnableClientStateIndexedEXT = (PFNGLENABLECLIENTSTATEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableClientStateIndexedEXT")) == NULL) || r; + r = ((glEnableClientStateiEXT = (PFNGLENABLECLIENTSTATEIEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableClientStateiEXT")) == NULL) || r; + r = ((glEnableVertexArrayAttribEXT = (PFNGLENABLEVERTEXARRAYATTRIBEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexArrayAttribEXT")) == NULL) || r; + r = ((glEnableVertexArrayEXT = (PFNGLENABLEVERTEXARRAYEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableVertexArrayEXT")) == NULL) || r; + r = ((glFlushMappedNamedBufferRangeEXT = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glFlushMappedNamedBufferRangeEXT")) == NULL) || r; + r = ((glFramebufferDrawBufferEXT = (PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferDrawBufferEXT")) == NULL) || r; + r = ((glFramebufferDrawBuffersEXT = (PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferDrawBuffersEXT")) == NULL) || r; + r = ((glFramebufferReadBufferEXT = (PFNGLFRAMEBUFFERREADBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferReadBufferEXT")) == NULL) || r; + r = ((glGenerateMultiTexMipmapEXT = (PFNGLGENERATEMULTITEXMIPMAPEXTPROC)glewGetProcAddress((const GLubyte*)"glGenerateMultiTexMipmapEXT")) == NULL) || r; + r = ((glGenerateTextureMipmapEXT = (PFNGLGENERATETEXTUREMIPMAPEXTPROC)glewGetProcAddress((const GLubyte*)"glGenerateTextureMipmapEXT")) == NULL) || r; + r = ((glGetCompressedMultiTexImageEXT = (PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedMultiTexImageEXT")) == NULL) || r; + r = ((glGetCompressedTextureImageEXT = (PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetCompressedTextureImageEXT")) == NULL) || r; + r = ((glGetDoubleIndexedvEXT = (PFNGLGETDOUBLEINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetDoubleIndexedvEXT")) == NULL) || r; + r = ((glGetDoublei_vEXT = (PFNGLGETDOUBLEI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetDoublei_vEXT")) == NULL) || r; + r = ((glGetFloatIndexedvEXT = (PFNGLGETFLOATINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFloatIndexedvEXT")) == NULL) || r; + r = ((glGetFloati_vEXT = (PFNGLGETFLOATI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFloati_vEXT")) == NULL) || r; + r = ((glGetFramebufferParameterivEXT = (PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferParameterivEXT")) == NULL) || r; + r = ((glGetMultiTexEnvfvEXT = (PFNGLGETMULTITEXENVFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexEnvfvEXT")) == NULL) || r; + r = ((glGetMultiTexEnvivEXT = (PFNGLGETMULTITEXENVIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexEnvivEXT")) == NULL) || r; + r = ((glGetMultiTexGendvEXT = (PFNGLGETMULTITEXGENDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexGendvEXT")) == NULL) || r; + r = ((glGetMultiTexGenfvEXT = (PFNGLGETMULTITEXGENFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexGenfvEXT")) == NULL) || r; + r = ((glGetMultiTexGenivEXT = (PFNGLGETMULTITEXGENIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexGenivEXT")) == NULL) || r; + r = ((glGetMultiTexImageEXT = (PFNGLGETMULTITEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexImageEXT")) == NULL) || r; + r = ((glGetMultiTexLevelParameterfvEXT = (PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexLevelParameterfvEXT")) == NULL) || r; + r = ((glGetMultiTexLevelParameterivEXT = (PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexLevelParameterivEXT")) == NULL) || r; + r = ((glGetMultiTexParameterIivEXT = (PFNGLGETMULTITEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterIivEXT")) == NULL) || r; + r = ((glGetMultiTexParameterIuivEXT = (PFNGLGETMULTITEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterIuivEXT")) == NULL) || r; + r = ((glGetMultiTexParameterfvEXT = (PFNGLGETMULTITEXPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterfvEXT")) == NULL) || r; + r = ((glGetMultiTexParameterivEXT = (PFNGLGETMULTITEXPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMultiTexParameterivEXT")) == NULL) || r; + r = ((glGetNamedBufferParameterivEXT = (PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferParameterivEXT")) == NULL) || r; + r = ((glGetNamedBufferPointervEXT = (PFNGLGETNAMEDBUFFERPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferPointervEXT")) == NULL) || r; + r = ((glGetNamedBufferSubDataEXT = (PFNGLGETNAMEDBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferSubDataEXT")) == NULL) || r; + r = ((glGetNamedFramebufferAttachmentParameterivEXT = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedFramebufferAttachmentParameterivEXT")) == NULL) || r; + r = ((glGetNamedProgramLocalParameterIivEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterIivEXT")) == NULL) || r; + r = ((glGetNamedProgramLocalParameterIuivEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterIuivEXT")) == NULL) || r; + r = ((glGetNamedProgramLocalParameterdvEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterdvEXT")) == NULL) || r; + r = ((glGetNamedProgramLocalParameterfvEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramLocalParameterfvEXT")) == NULL) || r; + r = ((glGetNamedProgramStringEXT = (PFNGLGETNAMEDPROGRAMSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramStringEXT")) == NULL) || r; + r = ((glGetNamedProgramivEXT = (PFNGLGETNAMEDPROGRAMIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedProgramivEXT")) == NULL) || r; + r = ((glGetNamedRenderbufferParameterivEXT = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedRenderbufferParameterivEXT")) == NULL) || r; + r = ((glGetPointerIndexedvEXT = (PFNGLGETPOINTERINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPointerIndexedvEXT")) == NULL) || r; + r = ((glGetPointeri_vEXT = (PFNGLGETPOINTERI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPointeri_vEXT")) == NULL) || r; + r = ((glGetTextureImageEXT = (PFNGLGETTEXTUREIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureImageEXT")) == NULL) || r; + r = ((glGetTextureLevelParameterfvEXT = (PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureLevelParameterfvEXT")) == NULL) || r; + r = ((glGetTextureLevelParameterivEXT = (PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureLevelParameterivEXT")) == NULL) || r; + r = ((glGetTextureParameterIivEXT = (PFNGLGETTEXTUREPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterIivEXT")) == NULL) || r; + r = ((glGetTextureParameterIuivEXT = (PFNGLGETTEXTUREPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterIuivEXT")) == NULL) || r; + r = ((glGetTextureParameterfvEXT = (PFNGLGETTEXTUREPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterfvEXT")) == NULL) || r; + r = ((glGetTextureParameterivEXT = (PFNGLGETTEXTUREPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTextureParameterivEXT")) == NULL) || r; + r = ((glGetVertexArrayIntegeri_vEXT = (PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexArrayIntegeri_vEXT")) == NULL) || r; + r = ((glGetVertexArrayIntegervEXT = (PFNGLGETVERTEXARRAYINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexArrayIntegervEXT")) == NULL) || r; + r = ((glGetVertexArrayPointeri_vEXT = (PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexArrayPointeri_vEXT")) == NULL) || r; + r = ((glGetVertexArrayPointervEXT = (PFNGLGETVERTEXARRAYPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexArrayPointervEXT")) == NULL) || r; + r = ((glMapNamedBufferEXT = (PFNGLMAPNAMEDBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glMapNamedBufferEXT")) == NULL) || r; + r = ((glMapNamedBufferRangeEXT = (PFNGLMAPNAMEDBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glMapNamedBufferRangeEXT")) == NULL) || r; + r = ((glMatrixFrustumEXT = (PFNGLMATRIXFRUSTUMEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixFrustumEXT")) == NULL) || r; + r = ((glMatrixLoadIdentityEXT = (PFNGLMATRIXLOADIDENTITYEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadIdentityEXT")) == NULL) || r; + r = ((glMatrixLoadTransposedEXT = (PFNGLMATRIXLOADTRANSPOSEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadTransposedEXT")) == NULL) || r; + r = ((glMatrixLoadTransposefEXT = (PFNGLMATRIXLOADTRANSPOSEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadTransposefEXT")) == NULL) || r; + r = ((glMatrixLoaddEXT = (PFNGLMATRIXLOADDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoaddEXT")) == NULL) || r; + r = ((glMatrixLoadfEXT = (PFNGLMATRIXLOADFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixLoadfEXT")) == NULL) || r; + r = ((glMatrixMultTransposedEXT = (PFNGLMATRIXMULTTRANSPOSEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultTransposedEXT")) == NULL) || r; + r = ((glMatrixMultTransposefEXT = (PFNGLMATRIXMULTTRANSPOSEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultTransposefEXT")) == NULL) || r; + r = ((glMatrixMultdEXT = (PFNGLMATRIXMULTDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultdEXT")) == NULL) || r; + r = ((glMatrixMultfEXT = (PFNGLMATRIXMULTFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixMultfEXT")) == NULL) || r; + r = ((glMatrixOrthoEXT = (PFNGLMATRIXORTHOEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixOrthoEXT")) == NULL) || r; + r = ((glMatrixPopEXT = (PFNGLMATRIXPOPEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixPopEXT")) == NULL) || r; + r = ((glMatrixPushEXT = (PFNGLMATRIXPUSHEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixPushEXT")) == NULL) || r; + r = ((glMatrixRotatedEXT = (PFNGLMATRIXROTATEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixRotatedEXT")) == NULL) || r; + r = ((glMatrixRotatefEXT = (PFNGLMATRIXROTATEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixRotatefEXT")) == NULL) || r; + r = ((glMatrixScaledEXT = (PFNGLMATRIXSCALEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixScaledEXT")) == NULL) || r; + r = ((glMatrixScalefEXT = (PFNGLMATRIXSCALEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixScalefEXT")) == NULL) || r; + r = ((glMatrixTranslatedEXT = (PFNGLMATRIXTRANSLATEDEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixTranslatedEXT")) == NULL) || r; + r = ((glMatrixTranslatefEXT = (PFNGLMATRIXTRANSLATEFEXTPROC)glewGetProcAddress((const GLubyte*)"glMatrixTranslatefEXT")) == NULL) || r; + r = ((glMultiTexBufferEXT = (PFNGLMULTITEXBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexBufferEXT")) == NULL) || r; + r = ((glMultiTexCoordPointerEXT = (PFNGLMULTITEXCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoordPointerEXT")) == NULL) || r; + r = ((glMultiTexEnvfEXT = (PFNGLMULTITEXENVFEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnvfEXT")) == NULL) || r; + r = ((glMultiTexEnvfvEXT = (PFNGLMULTITEXENVFVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnvfvEXT")) == NULL) || r; + r = ((glMultiTexEnviEXT = (PFNGLMULTITEXENVIEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnviEXT")) == NULL) || r; + r = ((glMultiTexEnvivEXT = (PFNGLMULTITEXENVIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexEnvivEXT")) == NULL) || r; + r = ((glMultiTexGendEXT = (PFNGLMULTITEXGENDEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGendEXT")) == NULL) || r; + r = ((glMultiTexGendvEXT = (PFNGLMULTITEXGENDVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGendvEXT")) == NULL) || r; + r = ((glMultiTexGenfEXT = (PFNGLMULTITEXGENFEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGenfEXT")) == NULL) || r; + r = ((glMultiTexGenfvEXT = (PFNGLMULTITEXGENFVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGenfvEXT")) == NULL) || r; + r = ((glMultiTexGeniEXT = (PFNGLMULTITEXGENIEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGeniEXT")) == NULL) || r; + r = ((glMultiTexGenivEXT = (PFNGLMULTITEXGENIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexGenivEXT")) == NULL) || r; + r = ((glMultiTexImage1DEXT = (PFNGLMULTITEXIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexImage1DEXT")) == NULL) || r; + r = ((glMultiTexImage2DEXT = (PFNGLMULTITEXIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexImage2DEXT")) == NULL) || r; + r = ((glMultiTexImage3DEXT = (PFNGLMULTITEXIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexImage3DEXT")) == NULL) || r; + r = ((glMultiTexParameterIivEXT = (PFNGLMULTITEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterIivEXT")) == NULL) || r; + r = ((glMultiTexParameterIuivEXT = (PFNGLMULTITEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterIuivEXT")) == NULL) || r; + r = ((glMultiTexParameterfEXT = (PFNGLMULTITEXPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterfEXT")) == NULL) || r; + r = ((glMultiTexParameterfvEXT = (PFNGLMULTITEXPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterfvEXT")) == NULL) || r; + r = ((glMultiTexParameteriEXT = (PFNGLMULTITEXPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameteriEXT")) == NULL) || r; + r = ((glMultiTexParameterivEXT = (PFNGLMULTITEXPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexParameterivEXT")) == NULL) || r; + r = ((glMultiTexRenderbufferEXT = (PFNGLMULTITEXRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexRenderbufferEXT")) == NULL) || r; + r = ((glMultiTexSubImage1DEXT = (PFNGLMULTITEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexSubImage1DEXT")) == NULL) || r; + r = ((glMultiTexSubImage2DEXT = (PFNGLMULTITEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexSubImage2DEXT")) == NULL) || r; + r = ((glMultiTexSubImage3DEXT = (PFNGLMULTITEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiTexSubImage3DEXT")) == NULL) || r; + r = ((glNamedBufferDataEXT = (PFNGLNAMEDBUFFERDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedBufferDataEXT")) == NULL) || r; + r = ((glNamedBufferSubDataEXT = (PFNGLNAMEDBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedBufferSubDataEXT")) == NULL) || r; + r = ((glNamedCopyBufferSubDataEXT = (PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedCopyBufferSubDataEXT")) == NULL) || r; + r = ((glNamedFramebufferRenderbufferEXT = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferRenderbufferEXT")) == NULL) || r; + r = ((glNamedFramebufferTexture1DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTexture1DEXT")) == NULL) || r; + r = ((glNamedFramebufferTexture2DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTexture2DEXT")) == NULL) || r; + r = ((glNamedFramebufferTexture3DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTexture3DEXT")) == NULL) || r; + r = ((glNamedFramebufferTextureEXT = (PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTextureEXT")) == NULL) || r; + r = ((glNamedFramebufferTextureFaceEXT = (PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTextureFaceEXT")) == NULL) || r; + r = ((glNamedFramebufferTextureLayerEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferTextureLayerEXT")) == NULL) || r; + r = ((glNamedProgramLocalParameter4dEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4dEXT")) == NULL) || r; + r = ((glNamedProgramLocalParameter4dvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4dvEXT")) == NULL) || r; + r = ((glNamedProgramLocalParameter4fEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4fEXT")) == NULL) || r; + r = ((glNamedProgramLocalParameter4fvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameter4fvEXT")) == NULL) || r; + r = ((glNamedProgramLocalParameterI4iEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4iEXT")) == NULL) || r; + r = ((glNamedProgramLocalParameterI4ivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4ivEXT")) == NULL) || r; + r = ((glNamedProgramLocalParameterI4uiEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4uiEXT")) == NULL) || r; + r = ((glNamedProgramLocalParameterI4uivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameterI4uivEXT")) == NULL) || r; + r = ((glNamedProgramLocalParameters4fvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParameters4fvEXT")) == NULL) || r; + r = ((glNamedProgramLocalParametersI4ivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParametersI4ivEXT")) == NULL) || r; + r = ((glNamedProgramLocalParametersI4uivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramLocalParametersI4uivEXT")) == NULL) || r; + r = ((glNamedProgramStringEXT = (PFNGLNAMEDPROGRAMSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedProgramStringEXT")) == NULL) || r; + r = ((glNamedRenderbufferStorageEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedRenderbufferStorageEXT")) == NULL) || r; + r = ((glNamedRenderbufferStorageMultisampleCoverageEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedRenderbufferStorageMultisampleCoverageEXT")) == NULL) || r; + r = ((glNamedRenderbufferStorageMultisampleEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedRenderbufferStorageMultisampleEXT")) == NULL) || r; + r = ((glProgramUniform1fEXT = (PFNGLPROGRAMUNIFORM1FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1fEXT")) == NULL) || r; + r = ((glProgramUniform1fvEXT = (PFNGLPROGRAMUNIFORM1FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1fvEXT")) == NULL) || r; + r = ((glProgramUniform1iEXT = (PFNGLPROGRAMUNIFORM1IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1iEXT")) == NULL) || r; + r = ((glProgramUniform1ivEXT = (PFNGLPROGRAMUNIFORM1IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1ivEXT")) == NULL) || r; + r = ((glProgramUniform1uiEXT = (PFNGLPROGRAMUNIFORM1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1uiEXT")) == NULL) || r; + r = ((glProgramUniform1uivEXT = (PFNGLPROGRAMUNIFORM1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1uivEXT")) == NULL) || r; + r = ((glProgramUniform2fEXT = (PFNGLPROGRAMUNIFORM2FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2fEXT")) == NULL) || r; + r = ((glProgramUniform2fvEXT = (PFNGLPROGRAMUNIFORM2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2fvEXT")) == NULL) || r; + r = ((glProgramUniform2iEXT = (PFNGLPROGRAMUNIFORM2IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2iEXT")) == NULL) || r; + r = ((glProgramUniform2ivEXT = (PFNGLPROGRAMUNIFORM2IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2ivEXT")) == NULL) || r; + r = ((glProgramUniform2uiEXT = (PFNGLPROGRAMUNIFORM2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2uiEXT")) == NULL) || r; + r = ((glProgramUniform2uivEXT = (PFNGLPROGRAMUNIFORM2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2uivEXT")) == NULL) || r; + r = ((glProgramUniform3fEXT = (PFNGLPROGRAMUNIFORM3FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3fEXT")) == NULL) || r; + r = ((glProgramUniform3fvEXT = (PFNGLPROGRAMUNIFORM3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3fvEXT")) == NULL) || r; + r = ((glProgramUniform3iEXT = (PFNGLPROGRAMUNIFORM3IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3iEXT")) == NULL) || r; + r = ((glProgramUniform3ivEXT = (PFNGLPROGRAMUNIFORM3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3ivEXT")) == NULL) || r; + r = ((glProgramUniform3uiEXT = (PFNGLPROGRAMUNIFORM3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3uiEXT")) == NULL) || r; + r = ((glProgramUniform3uivEXT = (PFNGLPROGRAMUNIFORM3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3uivEXT")) == NULL) || r; + r = ((glProgramUniform4fEXT = (PFNGLPROGRAMUNIFORM4FEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4fEXT")) == NULL) || r; + r = ((glProgramUniform4fvEXT = (PFNGLPROGRAMUNIFORM4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4fvEXT")) == NULL) || r; + r = ((glProgramUniform4iEXT = (PFNGLPROGRAMUNIFORM4IEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4iEXT")) == NULL) || r; + r = ((glProgramUniform4ivEXT = (PFNGLPROGRAMUNIFORM4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4ivEXT")) == NULL) || r; + r = ((glProgramUniform4uiEXT = (PFNGLPROGRAMUNIFORM4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4uiEXT")) == NULL) || r; + r = ((glProgramUniform4uivEXT = (PFNGLPROGRAMUNIFORM4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4uivEXT")) == NULL) || r; + r = ((glProgramUniformMatrix2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2fvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix2x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3fvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix2x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4fvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3fvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix3x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2fvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix3x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4fvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4fvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix4x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2fvEXT")) == NULL) || r; + r = ((glProgramUniformMatrix4x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3fvEXT")) == NULL) || r; + r = ((glPushClientAttribDefaultEXT = (PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC)glewGetProcAddress((const GLubyte*)"glPushClientAttribDefaultEXT")) == NULL) || r; + r = ((glTextureBufferEXT = (PFNGLTEXTUREBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glTextureBufferEXT")) == NULL) || r; + r = ((glTextureImage1DEXT = (PFNGLTEXTUREIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureImage1DEXT")) == NULL) || r; + r = ((glTextureImage2DEXT = (PFNGLTEXTUREIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureImage2DEXT")) == NULL) || r; + r = ((glTextureImage3DEXT = (PFNGLTEXTUREIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureImage3DEXT")) == NULL) || r; + r = ((glTextureParameterIivEXT = (PFNGLTEXTUREPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterIivEXT")) == NULL) || r; + r = ((glTextureParameterIuivEXT = (PFNGLTEXTUREPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterIuivEXT")) == NULL) || r; + r = ((glTextureParameterfEXT = (PFNGLTEXTUREPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterfEXT")) == NULL) || r; + r = ((glTextureParameterfvEXT = (PFNGLTEXTUREPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterfvEXT")) == NULL) || r; + r = ((glTextureParameteriEXT = (PFNGLTEXTUREPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameteriEXT")) == NULL) || r; + r = ((glTextureParameterivEXT = (PFNGLTEXTUREPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureParameterivEXT")) == NULL) || r; + r = ((glTextureRenderbufferEXT = (PFNGLTEXTURERENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glTextureRenderbufferEXT")) == NULL) || r; + r = ((glTextureSubImage1DEXT = (PFNGLTEXTURESUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureSubImage1DEXT")) == NULL) || r; + r = ((glTextureSubImage2DEXT = (PFNGLTEXTURESUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureSubImage2DEXT")) == NULL) || r; + r = ((glTextureSubImage3DEXT = (PFNGLTEXTURESUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureSubImage3DEXT")) == NULL) || r; + r = ((glUnmapNamedBufferEXT = (PFNGLUNMAPNAMEDBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glUnmapNamedBufferEXT")) == NULL) || r; + r = ((glVertexArrayColorOffsetEXT = (PFNGLVERTEXARRAYCOLOROFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayColorOffsetEXT")) == NULL) || r; + r = ((glVertexArrayEdgeFlagOffsetEXT = (PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayEdgeFlagOffsetEXT")) == NULL) || r; + r = ((glVertexArrayFogCoordOffsetEXT = (PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayFogCoordOffsetEXT")) == NULL) || r; + r = ((glVertexArrayIndexOffsetEXT = (PFNGLVERTEXARRAYINDEXOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayIndexOffsetEXT")) == NULL) || r; + r = ((glVertexArrayMultiTexCoordOffsetEXT = (PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayMultiTexCoordOffsetEXT")) == NULL) || r; + r = ((glVertexArrayNormalOffsetEXT = (PFNGLVERTEXARRAYNORMALOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayNormalOffsetEXT")) == NULL) || r; + r = ((glVertexArraySecondaryColorOffsetEXT = (PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArraySecondaryColorOffsetEXT")) == NULL) || r; + r = ((glVertexArrayTexCoordOffsetEXT = (PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayTexCoordOffsetEXT")) == NULL) || r; + r = ((glVertexArrayVertexAttribIOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribIOffsetEXT")) == NULL) || r; + r = ((glVertexArrayVertexAttribOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribOffsetEXT")) == NULL) || r; + r = ((glVertexArrayVertexOffsetEXT = (PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexOffsetEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_direct_state_access */ + +#ifdef GL_EXT_draw_buffers2 + +static GLboolean _glewInit_GL_EXT_draw_buffers2 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorMaskIndexedEXT = (PFNGLCOLORMASKINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glColorMaskIndexedEXT")) == NULL) || r; + r = ((glDisableIndexedEXT = (PFNGLDISABLEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableIndexedEXT")) == NULL) || r; + r = ((glEnableIndexedEXT = (PFNGLENABLEINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableIndexedEXT")) == NULL) || r; + r = ((glGetBooleanIndexedvEXT = (PFNGLGETBOOLEANINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetBooleanIndexedvEXT")) == NULL) || r; + r = ((glGetIntegerIndexedvEXT = (PFNGLGETINTEGERINDEXEDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetIntegerIndexedvEXT")) == NULL) || r; + r = ((glIsEnabledIndexedEXT = (PFNGLISENABLEDINDEXEDEXTPROC)glewGetProcAddress((const GLubyte*)"glIsEnabledIndexedEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_draw_buffers2 */ + +#ifdef GL_EXT_draw_instanced + +static GLboolean _glewInit_GL_EXT_draw_instanced (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedEXT")) == NULL) || r; + r = ((glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_draw_instanced */ + +#ifdef GL_EXT_draw_range_elements + +static GLboolean _glewInit_GL_EXT_draw_range_elements (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawRangeElementsEXT = (PFNGLDRAWRANGEELEMENTSEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawRangeElementsEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_draw_range_elements */ + +#ifdef GL_EXT_fog_coord + +static GLboolean _glewInit_GL_EXT_fog_coord (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFogCoordPointerEXT = (PFNGLFOGCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointerEXT")) == NULL) || r; + r = ((glFogCoorddEXT = (PFNGLFOGCOORDDEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddEXT")) == NULL) || r; + r = ((glFogCoorddvEXT = (PFNGLFOGCOORDDVEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoorddvEXT")) == NULL) || r; + r = ((glFogCoordfEXT = (PFNGLFOGCOORDFEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfEXT")) == NULL) || r; + r = ((glFogCoordfvEXT = (PFNGLFOGCOORDFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFogCoordfvEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_fog_coord */ + +#ifdef GL_EXT_fragment_lighting + +static GLboolean _glewInit_GL_EXT_fragment_lighting (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFragmentColorMaterialEXT = (PFNGLFRAGMENTCOLORMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentColorMaterialEXT")) == NULL) || r; + r = ((glFragmentLightModelfEXT = (PFNGLFRAGMENTLIGHTMODELFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfEXT")) == NULL) || r; + r = ((glFragmentLightModelfvEXT = (PFNGLFRAGMENTLIGHTMODELFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfvEXT")) == NULL) || r; + r = ((glFragmentLightModeliEXT = (PFNGLFRAGMENTLIGHTMODELIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModeliEXT")) == NULL) || r; + r = ((glFragmentLightModelivEXT = (PFNGLFRAGMENTLIGHTMODELIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelivEXT")) == NULL) || r; + r = ((glFragmentLightfEXT = (PFNGLFRAGMENTLIGHTFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfEXT")) == NULL) || r; + r = ((glFragmentLightfvEXT = (PFNGLFRAGMENTLIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfvEXT")) == NULL) || r; + r = ((glFragmentLightiEXT = (PFNGLFRAGMENTLIGHTIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightiEXT")) == NULL) || r; + r = ((glFragmentLightivEXT = (PFNGLFRAGMENTLIGHTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightivEXT")) == NULL) || r; + r = ((glFragmentMaterialfEXT = (PFNGLFRAGMENTMATERIALFEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfEXT")) == NULL) || r; + r = ((glFragmentMaterialfvEXT = (PFNGLFRAGMENTMATERIALFVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfvEXT")) == NULL) || r; + r = ((glFragmentMaterialiEXT = (PFNGLFRAGMENTMATERIALIEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialiEXT")) == NULL) || r; + r = ((glFragmentMaterialivEXT = (PFNGLFRAGMENTMATERIALIVEXTPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialivEXT")) == NULL) || r; + r = ((glGetFragmentLightfvEXT = (PFNGLGETFRAGMENTLIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightfvEXT")) == NULL) || r; + r = ((glGetFragmentLightivEXT = (PFNGLGETFRAGMENTLIGHTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightivEXT")) == NULL) || r; + r = ((glGetFragmentMaterialfvEXT = (PFNGLGETFRAGMENTMATERIALFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialfvEXT")) == NULL) || r; + r = ((glGetFragmentMaterialivEXT = (PFNGLGETFRAGMENTMATERIALIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialivEXT")) == NULL) || r; + r = ((glLightEnviEXT = (PFNGLLIGHTENVIEXTPROC)glewGetProcAddress((const GLubyte*)"glLightEnviEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_fragment_lighting */ + +#ifdef GL_EXT_framebuffer_blit + +static GLboolean _glewInit_GL_EXT_framebuffer_blit (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebufferEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_framebuffer_blit */ + +#ifdef GL_EXT_framebuffer_multisample + +static GLboolean _glewInit_GL_EXT_framebuffer_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_framebuffer_multisample */ + +#ifdef GL_EXT_framebuffer_object + +static GLboolean _glewInit_GL_EXT_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindFramebufferEXT")) == NULL) || r; + r = ((glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbufferEXT")) == NULL) || r; + r = ((glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatusEXT")) == NULL) || r; + r = ((glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteFramebuffersEXT")) == NULL) || r; + r = ((glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteRenderbuffersEXT")) == NULL) || r; + r = ((glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferRenderbufferEXT")) == NULL) || r; + r = ((glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture1DEXT")) == NULL) || r; + r = ((glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture2DEXT")) == NULL) || r; + r = ((glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTexture3DEXT")) == NULL) || r; + r = ((glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenFramebuffersEXT")) == NULL) || r; + r = ((glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenRenderbuffersEXT")) == NULL) || r; + r = ((glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)glewGetProcAddress((const GLubyte*)"glGenerateMipmapEXT")) == NULL) || r; + r = ((glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferAttachmentParameterivEXT")) == NULL) || r; + r = ((glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetRenderbufferParameterivEXT")) == NULL) || r; + r = ((glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glIsFramebufferEXT")) == NULL) || r; + r = ((glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glIsRenderbufferEXT")) == NULL) || r; + r = ((glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_framebuffer_object */ + +#ifdef GL_EXT_framebuffer_sRGB + +#endif /* GL_EXT_framebuffer_sRGB */ + +#ifdef GL_EXT_geometry_shader4 + +static GLboolean _glewInit_GL_EXT_geometry_shader4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureEXT")) == NULL) || r; + r = ((glFramebufferTextureFaceEXT = (PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureFaceEXT")) == NULL) || r; + r = ((glProgramParameteriEXT = (PFNGLPROGRAMPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramParameteriEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_geometry_shader4 */ + +#ifdef GL_EXT_gpu_program_parameters + +static GLboolean _glewInit_GL_EXT_gpu_program_parameters (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glProgramEnvParameters4fvEXT = (PFNGLPROGRAMENVPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameters4fvEXT")) == NULL) || r; + r = ((glProgramLocalParameters4fvEXT = (PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameters4fvEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_gpu_program_parameters */ + +#ifdef GL_EXT_gpu_shader4 + +static GLboolean _glewInit_GL_EXT_gpu_shader4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindFragDataLocationEXT = (PFNGLBINDFRAGDATALOCATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glBindFragDataLocationEXT")) == NULL) || r; + r = ((glGetFragDataLocationEXT = (PFNGLGETFRAGDATALOCATIONEXTPROC)glewGetProcAddress((const GLubyte*)"glGetFragDataLocationEXT")) == NULL) || r; + r = ((glGetUniformuivEXT = (PFNGLGETUNIFORMUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetUniformuivEXT")) == NULL) || r; + r = ((glGetVertexAttribIivEXT = (PFNGLGETVERTEXATTRIBIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIivEXT")) == NULL) || r; + r = ((glGetVertexAttribIuivEXT = (PFNGLGETVERTEXATTRIBIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribIuivEXT")) == NULL) || r; + r = ((glUniform1uiEXT = (PFNGLUNIFORM1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform1uiEXT")) == NULL) || r; + r = ((glUniform1uivEXT = (PFNGLUNIFORM1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform1uivEXT")) == NULL) || r; + r = ((glUniform2uiEXT = (PFNGLUNIFORM2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform2uiEXT")) == NULL) || r; + r = ((glUniform2uivEXT = (PFNGLUNIFORM2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform2uivEXT")) == NULL) || r; + r = ((glUniform3uiEXT = (PFNGLUNIFORM3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform3uiEXT")) == NULL) || r; + r = ((glUniform3uivEXT = (PFNGLUNIFORM3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform3uivEXT")) == NULL) || r; + r = ((glUniform4uiEXT = (PFNGLUNIFORM4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform4uiEXT")) == NULL) || r; + r = ((glUniform4uivEXT = (PFNGLUNIFORM4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glUniform4uivEXT")) == NULL) || r; + r = ((glVertexAttribI1iEXT = (PFNGLVERTEXATTRIBI1IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1iEXT")) == NULL) || r; + r = ((glVertexAttribI1ivEXT = (PFNGLVERTEXATTRIBI1IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1ivEXT")) == NULL) || r; + r = ((glVertexAttribI1uiEXT = (PFNGLVERTEXATTRIBI1UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uiEXT")) == NULL) || r; + r = ((glVertexAttribI1uivEXT = (PFNGLVERTEXATTRIBI1UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI1uivEXT")) == NULL) || r; + r = ((glVertexAttribI2iEXT = (PFNGLVERTEXATTRIBI2IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2iEXT")) == NULL) || r; + r = ((glVertexAttribI2ivEXT = (PFNGLVERTEXATTRIBI2IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2ivEXT")) == NULL) || r; + r = ((glVertexAttribI2uiEXT = (PFNGLVERTEXATTRIBI2UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uiEXT")) == NULL) || r; + r = ((glVertexAttribI2uivEXT = (PFNGLVERTEXATTRIBI2UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI2uivEXT")) == NULL) || r; + r = ((glVertexAttribI3iEXT = (PFNGLVERTEXATTRIBI3IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3iEXT")) == NULL) || r; + r = ((glVertexAttribI3ivEXT = (PFNGLVERTEXATTRIBI3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3ivEXT")) == NULL) || r; + r = ((glVertexAttribI3uiEXT = (PFNGLVERTEXATTRIBI3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uiEXT")) == NULL) || r; + r = ((glVertexAttribI3uivEXT = (PFNGLVERTEXATTRIBI3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI3uivEXT")) == NULL) || r; + r = ((glVertexAttribI4bvEXT = (PFNGLVERTEXATTRIBI4BVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4bvEXT")) == NULL) || r; + r = ((glVertexAttribI4iEXT = (PFNGLVERTEXATTRIBI4IEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4iEXT")) == NULL) || r; + r = ((glVertexAttribI4ivEXT = (PFNGLVERTEXATTRIBI4IVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ivEXT")) == NULL) || r; + r = ((glVertexAttribI4svEXT = (PFNGLVERTEXATTRIBI4SVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4svEXT")) == NULL) || r; + r = ((glVertexAttribI4ubvEXT = (PFNGLVERTEXATTRIBI4UBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4ubvEXT")) == NULL) || r; + r = ((glVertexAttribI4uiEXT = (PFNGLVERTEXATTRIBI4UIEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uiEXT")) == NULL) || r; + r = ((glVertexAttribI4uivEXT = (PFNGLVERTEXATTRIBI4UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4uivEXT")) == NULL) || r; + r = ((glVertexAttribI4usvEXT = (PFNGLVERTEXATTRIBI4USVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribI4usvEXT")) == NULL) || r; + r = ((glVertexAttribIPointerEXT = (PFNGLVERTEXATTRIBIPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIPointerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_gpu_shader4 */ + +#ifdef GL_EXT_histogram + +static GLboolean _glewInit_GL_EXT_histogram (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetHistogramEXT = (PFNGLGETHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramEXT")) == NULL) || r; + r = ((glGetHistogramParameterfvEXT = (PFNGLGETHISTOGRAMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterfvEXT")) == NULL) || r; + r = ((glGetHistogramParameterivEXT = (PFNGLGETHISTOGRAMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetHistogramParameterivEXT")) == NULL) || r; + r = ((glGetMinmaxEXT = (PFNGLGETMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxEXT")) == NULL) || r; + r = ((glGetMinmaxParameterfvEXT = (PFNGLGETMINMAXPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterfvEXT")) == NULL) || r; + r = ((glGetMinmaxParameterivEXT = (PFNGLGETMINMAXPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetMinmaxParameterivEXT")) == NULL) || r; + r = ((glHistogramEXT = (PFNGLHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glHistogramEXT")) == NULL) || r; + r = ((glMinmaxEXT = (PFNGLMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glMinmaxEXT")) == NULL) || r; + r = ((glResetHistogramEXT = (PFNGLRESETHISTOGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glResetHistogramEXT")) == NULL) || r; + r = ((glResetMinmaxEXT = (PFNGLRESETMINMAXEXTPROC)glewGetProcAddress((const GLubyte*)"glResetMinmaxEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_histogram */ + +#ifdef GL_EXT_index_array_formats + +#endif /* GL_EXT_index_array_formats */ + +#ifdef GL_EXT_index_func + +static GLboolean _glewInit_GL_EXT_index_func (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glIndexFuncEXT = (PFNGLINDEXFUNCEXTPROC)glewGetProcAddress((const GLubyte*)"glIndexFuncEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_index_func */ + +#ifdef GL_EXT_index_material + +static GLboolean _glewInit_GL_EXT_index_material (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glIndexMaterialEXT = (PFNGLINDEXMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glIndexMaterialEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_index_material */ + +#ifdef GL_EXT_index_texture + +#endif /* GL_EXT_index_texture */ + +#ifdef GL_EXT_light_texture + +static GLboolean _glewInit_GL_EXT_light_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glApplyTextureEXT = (PFNGLAPPLYTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glApplyTextureEXT")) == NULL) || r; + r = ((glTextureLightEXT = (PFNGLTEXTURELIGHTEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureLightEXT")) == NULL) || r; + r = ((glTextureMaterialEXT = (PFNGLTEXTUREMATERIALEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureMaterialEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_light_texture */ + +#ifdef GL_EXT_misc_attribute + +#endif /* GL_EXT_misc_attribute */ + +#ifdef GL_EXT_multi_draw_arrays + +static GLboolean _glewInit_GL_EXT_multi_draw_arrays (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysEXT")) == NULL) || r; + r = ((glMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_multi_draw_arrays */ + +#ifdef GL_EXT_multisample + +static GLboolean _glewInit_GL_EXT_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSampleMaskEXT = (PFNGLSAMPLEMASKEXTPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskEXT")) == NULL) || r; + r = ((glSamplePatternEXT = (PFNGLSAMPLEPATTERNEXTPROC)glewGetProcAddress((const GLubyte*)"glSamplePatternEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_multisample */ + +#ifdef GL_EXT_packed_depth_stencil + +#endif /* GL_EXT_packed_depth_stencil */ + +#ifdef GL_EXT_packed_float + +#endif /* GL_EXT_packed_float */ + +#ifdef GL_EXT_packed_pixels + +#endif /* GL_EXT_packed_pixels */ + +#ifdef GL_EXT_paletted_texture + +static GLboolean _glewInit_GL_EXT_paletted_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorTableEXT = (PFNGLCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glColorTableEXT")) == NULL) || r; + r = ((glGetColorTableEXT = (PFNGLGETCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableEXT")) == NULL) || r; + r = ((glGetColorTableParameterfvEXT = (PFNGLGETCOLORTABLEPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfvEXT")) == NULL) || r; + r = ((glGetColorTableParameterivEXT = (PFNGLGETCOLORTABLEPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterivEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_paletted_texture */ + +#ifdef GL_EXT_pixel_buffer_object + +#endif /* GL_EXT_pixel_buffer_object */ + +#ifdef GL_EXT_pixel_transform + +static GLboolean _glewInit_GL_EXT_pixel_transform (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetPixelTransformParameterfvEXT = (PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPixelTransformParameterfvEXT")) == NULL) || r; + r = ((glGetPixelTransformParameterivEXT = (PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetPixelTransformParameterivEXT")) == NULL) || r; + r = ((glPixelTransformParameterfEXT = (PFNGLPIXELTRANSFORMPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterfEXT")) == NULL) || r; + r = ((glPixelTransformParameterfvEXT = (PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterfvEXT")) == NULL) || r; + r = ((glPixelTransformParameteriEXT = (PFNGLPIXELTRANSFORMPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameteriEXT")) == NULL) || r; + r = ((glPixelTransformParameterivEXT = (PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glPixelTransformParameterivEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_pixel_transform */ + +#ifdef GL_EXT_pixel_transform_color_table + +#endif /* GL_EXT_pixel_transform_color_table */ + +#ifdef GL_EXT_point_parameters + +static GLboolean _glewInit_GL_EXT_point_parameters (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPointParameterfEXT = (PFNGLPOINTPARAMETERFEXTPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfEXT")) == NULL) || r; + r = ((glPointParameterfvEXT = (PFNGLPOINTPARAMETERFVEXTPROC)glewGetProcAddress((const GLubyte*)"glPointParameterfvEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_point_parameters */ + +#ifdef GL_EXT_polygon_offset + +static GLboolean _glewInit_GL_EXT_polygon_offset (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPolygonOffsetEXT = (PFNGLPOLYGONOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glPolygonOffsetEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_polygon_offset */ + +#ifdef GL_EXT_provoking_vertex + +static GLboolean _glewInit_GL_EXT_provoking_vertex (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glProvokingVertexEXT = (PFNGLPROVOKINGVERTEXEXTPROC)glewGetProcAddress((const GLubyte*)"glProvokingVertexEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_provoking_vertex */ + +#ifdef GL_EXT_rescale_normal + +#endif /* GL_EXT_rescale_normal */ + +#ifdef GL_EXT_scene_marker + +static GLboolean _glewInit_GL_EXT_scene_marker (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginSceneEXT = (PFNGLBEGINSCENEEXTPROC)glewGetProcAddress((const GLubyte*)"glBeginSceneEXT")) == NULL) || r; + r = ((glEndSceneEXT = (PFNGLENDSCENEEXTPROC)glewGetProcAddress((const GLubyte*)"glEndSceneEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_scene_marker */ + +#ifdef GL_EXT_secondary_color + +static GLboolean _glewInit_GL_EXT_secondary_color (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSecondaryColor3bEXT = (PFNGLSECONDARYCOLOR3BEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bEXT")) == NULL) || r; + r = ((glSecondaryColor3bvEXT = (PFNGLSECONDARYCOLOR3BVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3bvEXT")) == NULL) || r; + r = ((glSecondaryColor3dEXT = (PFNGLSECONDARYCOLOR3DEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dEXT")) == NULL) || r; + r = ((glSecondaryColor3dvEXT = (PFNGLSECONDARYCOLOR3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3dvEXT")) == NULL) || r; + r = ((glSecondaryColor3fEXT = (PFNGLSECONDARYCOLOR3FEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fEXT")) == NULL) || r; + r = ((glSecondaryColor3fvEXT = (PFNGLSECONDARYCOLOR3FVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3fvEXT")) == NULL) || r; + r = ((glSecondaryColor3iEXT = (PFNGLSECONDARYCOLOR3IEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3iEXT")) == NULL) || r; + r = ((glSecondaryColor3ivEXT = (PFNGLSECONDARYCOLOR3IVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ivEXT")) == NULL) || r; + r = ((glSecondaryColor3sEXT = (PFNGLSECONDARYCOLOR3SEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3sEXT")) == NULL) || r; + r = ((glSecondaryColor3svEXT = (PFNGLSECONDARYCOLOR3SVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3svEXT")) == NULL) || r; + r = ((glSecondaryColor3ubEXT = (PFNGLSECONDARYCOLOR3UBEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubEXT")) == NULL) || r; + r = ((glSecondaryColor3ubvEXT = (PFNGLSECONDARYCOLOR3UBVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3ubvEXT")) == NULL) || r; + r = ((glSecondaryColor3uiEXT = (PFNGLSECONDARYCOLOR3UIEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uiEXT")) == NULL) || r; + r = ((glSecondaryColor3uivEXT = (PFNGLSECONDARYCOLOR3UIVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3uivEXT")) == NULL) || r; + r = ((glSecondaryColor3usEXT = (PFNGLSECONDARYCOLOR3USEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usEXT")) == NULL) || r; + r = ((glSecondaryColor3usvEXT = (PFNGLSECONDARYCOLOR3USVEXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3usvEXT")) == NULL) || r; + r = ((glSecondaryColorPointerEXT = (PFNGLSECONDARYCOLORPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_secondary_color */ + +#ifdef GL_EXT_separate_shader_objects + +static GLboolean _glewInit_GL_EXT_separate_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glActiveProgramEXT = (PFNGLACTIVEPROGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glActiveProgramEXT")) == NULL) || r; + r = ((glCreateShaderProgramEXT = (PFNGLCREATESHADERPROGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glCreateShaderProgramEXT")) == NULL) || r; + r = ((glUseShaderProgramEXT = (PFNGLUSESHADERPROGRAMEXTPROC)glewGetProcAddress((const GLubyte*)"glUseShaderProgramEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_separate_shader_objects */ + +#ifdef GL_EXT_separate_specular_color + +#endif /* GL_EXT_separate_specular_color */ + +#ifdef GL_EXT_shader_image_load_store + +static GLboolean _glewInit_GL_EXT_shader_image_load_store (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindImageTextureEXT = (PFNGLBINDIMAGETEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glBindImageTextureEXT")) == NULL) || r; + r = ((glMemoryBarrierEXT = (PFNGLMEMORYBARRIEREXTPROC)glewGetProcAddress((const GLubyte*)"glMemoryBarrierEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_shader_image_load_store */ + +#ifdef GL_EXT_shadow_funcs + +#endif /* GL_EXT_shadow_funcs */ + +#ifdef GL_EXT_shared_texture_palette + +#endif /* GL_EXT_shared_texture_palette */ + +#ifdef GL_EXT_stencil_clear_tag + +#endif /* GL_EXT_stencil_clear_tag */ + +#ifdef GL_EXT_stencil_two_side + +static GLboolean _glewInit_GL_EXT_stencil_two_side (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC)glewGetProcAddress((const GLubyte*)"glActiveStencilFaceEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_stencil_two_side */ + +#ifdef GL_EXT_stencil_wrap + +#endif /* GL_EXT_stencil_wrap */ + +#ifdef GL_EXT_subtexture + +static GLboolean _glewInit_GL_EXT_subtexture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexSubImage1DEXT = (PFNGLTEXSUBIMAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage1DEXT")) == NULL) || r; + r = ((glTexSubImage2DEXT = (PFNGLTEXSUBIMAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage2DEXT")) == NULL) || r; + r = ((glTexSubImage3DEXT = (PFNGLTEXSUBIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage3DEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_subtexture */ + +#ifdef GL_EXT_texture + +#endif /* GL_EXT_texture */ + +#ifdef GL_EXT_texture3D + +static GLboolean _glewInit_GL_EXT_texture3D (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexImage3DEXT = (PFNGLTEXIMAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTexImage3DEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture3D */ + +#ifdef GL_EXT_texture_array + +static GLboolean _glewInit_GL_EXT_texture_array (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC)glewGetProcAddress((const GLubyte*)"glFramebufferTextureLayerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture_array */ + +#ifdef GL_EXT_texture_buffer_object + +static GLboolean _glewInit_GL_EXT_texture_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexBufferEXT = (PFNGLTEXBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glTexBufferEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture_buffer_object */ + +#ifdef GL_EXT_texture_compression_dxt1 + +#endif /* GL_EXT_texture_compression_dxt1 */ + +#ifdef GL_EXT_texture_compression_latc + +#endif /* GL_EXT_texture_compression_latc */ + +#ifdef GL_EXT_texture_compression_rgtc + +#endif /* GL_EXT_texture_compression_rgtc */ + +#ifdef GL_EXT_texture_compression_s3tc + +#endif /* GL_EXT_texture_compression_s3tc */ + +#ifdef GL_EXT_texture_cube_map + +#endif /* GL_EXT_texture_cube_map */ + +#ifdef GL_EXT_texture_edge_clamp + +#endif /* GL_EXT_texture_edge_clamp */ + +#ifdef GL_EXT_texture_env + +#endif /* GL_EXT_texture_env */ + +#ifdef GL_EXT_texture_env_add + +#endif /* GL_EXT_texture_env_add */ + +#ifdef GL_EXT_texture_env_combine + +#endif /* GL_EXT_texture_env_combine */ + +#ifdef GL_EXT_texture_env_dot3 + +#endif /* GL_EXT_texture_env_dot3 */ + +#ifdef GL_EXT_texture_filter_anisotropic + +#endif /* GL_EXT_texture_filter_anisotropic */ + +#ifdef GL_EXT_texture_integer + +static GLboolean _glewInit_GL_EXT_texture_integer (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClearColorIiEXT = (PFNGLCLEARCOLORIIEXTPROC)glewGetProcAddress((const GLubyte*)"glClearColorIiEXT")) == NULL) || r; + r = ((glClearColorIuiEXT = (PFNGLCLEARCOLORIUIEXTPROC)glewGetProcAddress((const GLubyte*)"glClearColorIuiEXT")) == NULL) || r; + r = ((glGetTexParameterIivEXT = (PFNGLGETTEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIivEXT")) == NULL) || r; + r = ((glGetTexParameterIuivEXT = (PFNGLGETTEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterIuivEXT")) == NULL) || r; + r = ((glTexParameterIivEXT = (PFNGLTEXPARAMETERIIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIivEXT")) == NULL) || r; + r = ((glTexParameterIuivEXT = (PFNGLTEXPARAMETERIUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glTexParameterIuivEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture_integer */ + +#ifdef GL_EXT_texture_lod_bias + +#endif /* GL_EXT_texture_lod_bias */ + +#ifdef GL_EXT_texture_mirror_clamp + +#endif /* GL_EXT_texture_mirror_clamp */ + +#ifdef GL_EXT_texture_object + +static GLboolean _glewInit_GL_EXT_texture_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAreTexturesResidentEXT = (PFNGLARETEXTURESRESIDENTEXTPROC)glewGetProcAddress((const GLubyte*)"glAreTexturesResidentEXT")) == NULL) || r; + r = ((glBindTextureEXT = (PFNGLBINDTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glBindTextureEXT")) == NULL) || r; + r = ((glDeleteTexturesEXT = (PFNGLDELETETEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteTexturesEXT")) == NULL) || r; + r = ((glGenTexturesEXT = (PFNGLGENTEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glGenTexturesEXT")) == NULL) || r; + r = ((glIsTextureEXT = (PFNGLISTEXTUREEXTPROC)glewGetProcAddress((const GLubyte*)"glIsTextureEXT")) == NULL) || r; + r = ((glPrioritizeTexturesEXT = (PFNGLPRIORITIZETEXTURESEXTPROC)glewGetProcAddress((const GLubyte*)"glPrioritizeTexturesEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture_object */ + +#ifdef GL_EXT_texture_perturb_normal + +static GLboolean _glewInit_GL_EXT_texture_perturb_normal (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTextureNormalEXT = (PFNGLTEXTURENORMALEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureNormalEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_texture_perturb_normal */ + +#ifdef GL_EXT_texture_rectangle + +#endif /* GL_EXT_texture_rectangle */ + +#ifdef GL_EXT_texture_sRGB + +#endif /* GL_EXT_texture_sRGB */ + +#ifdef GL_EXT_texture_sRGB_decode + +#endif /* GL_EXT_texture_sRGB_decode */ + +#ifdef GL_EXT_texture_shared_exponent + +#endif /* GL_EXT_texture_shared_exponent */ + +#ifdef GL_EXT_texture_snorm + +#endif /* GL_EXT_texture_snorm */ + +#ifdef GL_EXT_texture_swizzle + +#endif /* GL_EXT_texture_swizzle */ + +#ifdef GL_EXT_timer_query + +static GLboolean _glewInit_GL_EXT_timer_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetQueryObjecti64vEXT = (PFNGLGETQUERYOBJECTI64VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjecti64vEXT")) == NULL) || r; + r = ((glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectui64vEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_timer_query */ + +#ifdef GL_EXT_transform_feedback + +static GLboolean _glewInit_GL_EXT_transform_feedback (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginTransformFeedbackEXT = (PFNGLBEGINTRANSFORMFEEDBACKEXTPROC)glewGetProcAddress((const GLubyte*)"glBeginTransformFeedbackEXT")) == NULL) || r; + r = ((glBindBufferBaseEXT = (PFNGLBINDBUFFERBASEEXTPROC)glewGetProcAddress((const GLubyte*)"glBindBufferBaseEXT")) == NULL) || r; + r = ((glBindBufferOffsetEXT = (PFNGLBINDBUFFEROFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glBindBufferOffsetEXT")) == NULL) || r; + r = ((glBindBufferRangeEXT = (PFNGLBINDBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glBindBufferRangeEXT")) == NULL) || r; + r = ((glEndTransformFeedbackEXT = (PFNGLENDTRANSFORMFEEDBACKEXTPROC)glewGetProcAddress((const GLubyte*)"glEndTransformFeedbackEXT")) == NULL) || r; + r = ((glGetTransformFeedbackVaryingEXT = (PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC)glewGetProcAddress((const GLubyte*)"glGetTransformFeedbackVaryingEXT")) == NULL) || r; + r = ((glTransformFeedbackVaryingsEXT = (PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackVaryingsEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_transform_feedback */ + +#ifdef GL_EXT_vertex_array + +static GLboolean _glewInit_GL_EXT_vertex_array (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glArrayElementEXT = (PFNGLARRAYELEMENTEXTPROC)glewGetProcAddress((const GLubyte*)"glArrayElementEXT")) == NULL) || r; + r = ((glColorPointerEXT = (PFNGLCOLORPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glColorPointerEXT")) == NULL) || r; + r = ((glDrawArraysEXT = (PFNGLDRAWARRAYSEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysEXT")) == NULL) || r; + r = ((glEdgeFlagPointerEXT = (PFNGLEDGEFLAGPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagPointerEXT")) == NULL) || r; + r = ((glIndexPointerEXT = (PFNGLINDEXPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glIndexPointerEXT")) == NULL) || r; + r = ((glNormalPointerEXT = (PFNGLNORMALPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glNormalPointerEXT")) == NULL) || r; + r = ((glTexCoordPointerEXT = (PFNGLTEXCOORDPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointerEXT")) == NULL) || r; + r = ((glVertexPointerEXT = (PFNGLVERTEXPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexPointerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_vertex_array */ + +#ifdef GL_EXT_vertex_array_bgra + +#endif /* GL_EXT_vertex_array_bgra */ + +#ifdef GL_EXT_vertex_attrib_64bit + +static GLboolean _glewInit_GL_EXT_vertex_attrib_64bit (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetVertexAttribLdvEXT = (PFNGLGETVERTEXATTRIBLDVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribLdvEXT")) == NULL) || r; + r = ((glVertexArrayVertexAttribLOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribLOffsetEXT")) == NULL) || r; + r = ((glVertexAttribL1dEXT = (PFNGLVERTEXATTRIBL1DEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1dEXT")) == NULL) || r; + r = ((glVertexAttribL1dvEXT = (PFNGLVERTEXATTRIBL1DVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1dvEXT")) == NULL) || r; + r = ((glVertexAttribL2dEXT = (PFNGLVERTEXATTRIBL2DEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2dEXT")) == NULL) || r; + r = ((glVertexAttribL2dvEXT = (PFNGLVERTEXATTRIBL2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2dvEXT")) == NULL) || r; + r = ((glVertexAttribL3dEXT = (PFNGLVERTEXATTRIBL3DEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3dEXT")) == NULL) || r; + r = ((glVertexAttribL3dvEXT = (PFNGLVERTEXATTRIBL3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3dvEXT")) == NULL) || r; + r = ((glVertexAttribL4dEXT = (PFNGLVERTEXATTRIBL4DEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4dEXT")) == NULL) || r; + r = ((glVertexAttribL4dvEXT = (PFNGLVERTEXATTRIBL4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4dvEXT")) == NULL) || r; + r = ((glVertexAttribLPointerEXT = (PFNGLVERTEXATTRIBLPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribLPointerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_vertex_attrib_64bit */ + +#ifdef GL_EXT_vertex_shader + +static GLboolean _glewInit_GL_EXT_vertex_shader (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginVertexShaderEXT = (PFNGLBEGINVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glBeginVertexShaderEXT")) == NULL) || r; + r = ((glBindLightParameterEXT = (PFNGLBINDLIGHTPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindLightParameterEXT")) == NULL) || r; + r = ((glBindMaterialParameterEXT = (PFNGLBINDMATERIALPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindMaterialParameterEXT")) == NULL) || r; + r = ((glBindParameterEXT = (PFNGLBINDPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindParameterEXT")) == NULL) || r; + r = ((glBindTexGenParameterEXT = (PFNGLBINDTEXGENPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindTexGenParameterEXT")) == NULL) || r; + r = ((glBindTextureUnitParameterEXT = (PFNGLBINDTEXTUREUNITPARAMETEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindTextureUnitParameterEXT")) == NULL) || r; + r = ((glBindVertexShaderEXT = (PFNGLBINDVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glBindVertexShaderEXT")) == NULL) || r; + r = ((glDeleteVertexShaderEXT = (PFNGLDELETEVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteVertexShaderEXT")) == NULL) || r; + r = ((glDisableVariantClientStateEXT = (PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC)glewGetProcAddress((const GLubyte*)"glDisableVariantClientStateEXT")) == NULL) || r; + r = ((glEnableVariantClientStateEXT = (PFNGLENABLEVARIANTCLIENTSTATEEXTPROC)glewGetProcAddress((const GLubyte*)"glEnableVariantClientStateEXT")) == NULL) || r; + r = ((glEndVertexShaderEXT = (PFNGLENDVERTEXSHADEREXTPROC)glewGetProcAddress((const GLubyte*)"glEndVertexShaderEXT")) == NULL) || r; + r = ((glExtractComponentEXT = (PFNGLEXTRACTCOMPONENTEXTPROC)glewGetProcAddress((const GLubyte*)"glExtractComponentEXT")) == NULL) || r; + r = ((glGenSymbolsEXT = (PFNGLGENSYMBOLSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenSymbolsEXT")) == NULL) || r; + r = ((glGenVertexShadersEXT = (PFNGLGENVERTEXSHADERSEXTPROC)glewGetProcAddress((const GLubyte*)"glGenVertexShadersEXT")) == NULL) || r; + r = ((glGetInvariantBooleanvEXT = (PFNGLGETINVARIANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantBooleanvEXT")) == NULL) || r; + r = ((glGetInvariantFloatvEXT = (PFNGLGETINVARIANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantFloatvEXT")) == NULL) || r; + r = ((glGetInvariantIntegervEXT = (PFNGLGETINVARIANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetInvariantIntegervEXT")) == NULL) || r; + r = ((glGetLocalConstantBooleanvEXT = (PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantBooleanvEXT")) == NULL) || r; + r = ((glGetLocalConstantFloatvEXT = (PFNGLGETLOCALCONSTANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantFloatvEXT")) == NULL) || r; + r = ((glGetLocalConstantIntegervEXT = (PFNGLGETLOCALCONSTANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetLocalConstantIntegervEXT")) == NULL) || r; + r = ((glGetVariantBooleanvEXT = (PFNGLGETVARIANTBOOLEANVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantBooleanvEXT")) == NULL) || r; + r = ((glGetVariantFloatvEXT = (PFNGLGETVARIANTFLOATVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantFloatvEXT")) == NULL) || r; + r = ((glGetVariantIntegervEXT = (PFNGLGETVARIANTINTEGERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantIntegervEXT")) == NULL) || r; + r = ((glGetVariantPointervEXT = (PFNGLGETVARIANTPOINTERVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetVariantPointervEXT")) == NULL) || r; + r = ((glInsertComponentEXT = (PFNGLINSERTCOMPONENTEXTPROC)glewGetProcAddress((const GLubyte*)"glInsertComponentEXT")) == NULL) || r; + r = ((glIsVariantEnabledEXT = (PFNGLISVARIANTENABLEDEXTPROC)glewGetProcAddress((const GLubyte*)"glIsVariantEnabledEXT")) == NULL) || r; + r = ((glSetInvariantEXT = (PFNGLSETINVARIANTEXTPROC)glewGetProcAddress((const GLubyte*)"glSetInvariantEXT")) == NULL) || r; + r = ((glSetLocalConstantEXT = (PFNGLSETLOCALCONSTANTEXTPROC)glewGetProcAddress((const GLubyte*)"glSetLocalConstantEXT")) == NULL) || r; + r = ((glShaderOp1EXT = (PFNGLSHADEROP1EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp1EXT")) == NULL) || r; + r = ((glShaderOp2EXT = (PFNGLSHADEROP2EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp2EXT")) == NULL) || r; + r = ((glShaderOp3EXT = (PFNGLSHADEROP3EXTPROC)glewGetProcAddress((const GLubyte*)"glShaderOp3EXT")) == NULL) || r; + r = ((glSwizzleEXT = (PFNGLSWIZZLEEXTPROC)glewGetProcAddress((const GLubyte*)"glSwizzleEXT")) == NULL) || r; + r = ((glVariantPointerEXT = (PFNGLVARIANTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVariantPointerEXT")) == NULL) || r; + r = ((glVariantbvEXT = (PFNGLVARIANTBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantbvEXT")) == NULL) || r; + r = ((glVariantdvEXT = (PFNGLVARIANTDVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantdvEXT")) == NULL) || r; + r = ((glVariantfvEXT = (PFNGLVARIANTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantfvEXT")) == NULL) || r; + r = ((glVariantivEXT = (PFNGLVARIANTIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantivEXT")) == NULL) || r; + r = ((glVariantsvEXT = (PFNGLVARIANTSVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantsvEXT")) == NULL) || r; + r = ((glVariantubvEXT = (PFNGLVARIANTUBVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantubvEXT")) == NULL) || r; + r = ((glVariantuivEXT = (PFNGLVARIANTUIVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantuivEXT")) == NULL) || r; + r = ((glVariantusvEXT = (PFNGLVARIANTUSVEXTPROC)glewGetProcAddress((const GLubyte*)"glVariantusvEXT")) == NULL) || r; + r = ((glWriteMaskEXT = (PFNGLWRITEMASKEXTPROC)glewGetProcAddress((const GLubyte*)"glWriteMaskEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_vertex_shader */ + +#ifdef GL_EXT_vertex_weighting + +static GLboolean _glewInit_GL_EXT_vertex_weighting (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glVertexWeightPointerEXT = (PFNGLVERTEXWEIGHTPOINTEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightPointerEXT")) == NULL) || r; + r = ((glVertexWeightfEXT = (PFNGLVERTEXWEIGHTFEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightfEXT")) == NULL) || r; + r = ((glVertexWeightfvEXT = (PFNGLVERTEXWEIGHTFVEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexWeightfvEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_vertex_weighting */ + +#ifdef GL_EXT_x11_sync_object + +static GLboolean _glewInit_GL_EXT_x11_sync_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glImportSyncEXT = (PFNGLIMPORTSYNCEXTPROC)glewGetProcAddress((const GLubyte*)"glImportSyncEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_x11_sync_object */ + +#ifdef GL_GREMEDY_frame_terminator + +static GLboolean _glewInit_GL_GREMEDY_frame_terminator (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFrameTerminatorGREMEDY = (PFNGLFRAMETERMINATORGREMEDYPROC)glewGetProcAddress((const GLubyte*)"glFrameTerminatorGREMEDY")) == NULL) || r; + + return r; +} + +#endif /* GL_GREMEDY_frame_terminator */ + +#ifdef GL_GREMEDY_string_marker + +static GLboolean _glewInit_GL_GREMEDY_string_marker (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glStringMarkerGREMEDY = (PFNGLSTRINGMARKERGREMEDYPROC)glewGetProcAddress((const GLubyte*)"glStringMarkerGREMEDY")) == NULL) || r; + + return r; +} + +#endif /* GL_GREMEDY_string_marker */ + +#ifdef GL_HP_convolution_border_modes + +#endif /* GL_HP_convolution_border_modes */ + +#ifdef GL_HP_image_transform + +static GLboolean _glewInit_GL_HP_image_transform (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetImageTransformParameterfvHP = (PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC)glewGetProcAddress((const GLubyte*)"glGetImageTransformParameterfvHP")) == NULL) || r; + r = ((glGetImageTransformParameterivHP = (PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC)glewGetProcAddress((const GLubyte*)"glGetImageTransformParameterivHP")) == NULL) || r; + r = ((glImageTransformParameterfHP = (PFNGLIMAGETRANSFORMPARAMETERFHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterfHP")) == NULL) || r; + r = ((glImageTransformParameterfvHP = (PFNGLIMAGETRANSFORMPARAMETERFVHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterfvHP")) == NULL) || r; + r = ((glImageTransformParameteriHP = (PFNGLIMAGETRANSFORMPARAMETERIHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameteriHP")) == NULL) || r; + r = ((glImageTransformParameterivHP = (PFNGLIMAGETRANSFORMPARAMETERIVHPPROC)glewGetProcAddress((const GLubyte*)"glImageTransformParameterivHP")) == NULL) || r; + + return r; +} + +#endif /* GL_HP_image_transform */ + +#ifdef GL_HP_occlusion_test + +#endif /* GL_HP_occlusion_test */ + +#ifdef GL_HP_texture_lighting + +#endif /* GL_HP_texture_lighting */ + +#ifdef GL_IBM_cull_vertex + +#endif /* GL_IBM_cull_vertex */ + +#ifdef GL_IBM_multimode_draw_arrays + +static GLboolean _glewInit_GL_IBM_multimode_draw_arrays (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMultiModeDrawArraysIBM = (PFNGLMULTIMODEDRAWARRAYSIBMPROC)glewGetProcAddress((const GLubyte*)"glMultiModeDrawArraysIBM")) == NULL) || r; + r = ((glMultiModeDrawElementsIBM = (PFNGLMULTIMODEDRAWELEMENTSIBMPROC)glewGetProcAddress((const GLubyte*)"glMultiModeDrawElementsIBM")) == NULL) || r; + + return r; +} + +#endif /* GL_IBM_multimode_draw_arrays */ + +#ifdef GL_IBM_rasterpos_clip + +#endif /* GL_IBM_rasterpos_clip */ + +#ifdef GL_IBM_static_data + +#endif /* GL_IBM_static_data */ + +#ifdef GL_IBM_texture_mirrored_repeat + +#endif /* GL_IBM_texture_mirrored_repeat */ + +#ifdef GL_IBM_vertex_array_lists + +static GLboolean _glewInit_GL_IBM_vertex_array_lists (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorPointerListIBM = (PFNGLCOLORPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glColorPointerListIBM")) == NULL) || r; + r = ((glEdgeFlagPointerListIBM = (PFNGLEDGEFLAGPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagPointerListIBM")) == NULL) || r; + r = ((glFogCoordPointerListIBM = (PFNGLFOGCOORDPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glFogCoordPointerListIBM")) == NULL) || r; + r = ((glIndexPointerListIBM = (PFNGLINDEXPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glIndexPointerListIBM")) == NULL) || r; + r = ((glNormalPointerListIBM = (PFNGLNORMALPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glNormalPointerListIBM")) == NULL) || r; + r = ((glSecondaryColorPointerListIBM = (PFNGLSECONDARYCOLORPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorPointerListIBM")) == NULL) || r; + r = ((glTexCoordPointerListIBM = (PFNGLTEXCOORDPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointerListIBM")) == NULL) || r; + r = ((glVertexPointerListIBM = (PFNGLVERTEXPOINTERLISTIBMPROC)glewGetProcAddress((const GLubyte*)"glVertexPointerListIBM")) == NULL) || r; + + return r; +} + +#endif /* GL_IBM_vertex_array_lists */ + +#ifdef GL_INGR_color_clamp + +#endif /* GL_INGR_color_clamp */ + +#ifdef GL_INGR_interlace_read + +#endif /* GL_INGR_interlace_read */ + +#ifdef GL_INTEL_parallel_arrays + +static GLboolean _glewInit_GL_INTEL_parallel_arrays (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorPointervINTEL = (PFNGLCOLORPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glColorPointervINTEL")) == NULL) || r; + r = ((glNormalPointervINTEL = (PFNGLNORMALPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glNormalPointervINTEL")) == NULL) || r; + r = ((glTexCoordPointervINTEL = (PFNGLTEXCOORDPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glTexCoordPointervINTEL")) == NULL) || r; + r = ((glVertexPointervINTEL = (PFNGLVERTEXPOINTERVINTELPROC)glewGetProcAddress((const GLubyte*)"glVertexPointervINTEL")) == NULL) || r; + + return r; +} + +#endif /* GL_INTEL_parallel_arrays */ + +#ifdef GL_INTEL_texture_scissor + +static GLboolean _glewInit_GL_INTEL_texture_scissor (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexScissorFuncINTEL = (PFNGLTEXSCISSORFUNCINTELPROC)glewGetProcAddress((const GLubyte*)"glTexScissorFuncINTEL")) == NULL) || r; + r = ((glTexScissorINTEL = (PFNGLTEXSCISSORINTELPROC)glewGetProcAddress((const GLubyte*)"glTexScissorINTEL")) == NULL) || r; + + return r; +} + +#endif /* GL_INTEL_texture_scissor */ + +#ifdef GL_KTX_buffer_region + +static GLboolean _glewInit_GL_KTX_buffer_region (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBufferRegionEnabledEXT = (PFNGLBUFFERREGIONENABLEDEXTPROC)glewGetProcAddress((const GLubyte*)"glBufferRegionEnabledEXT")) == NULL) || r; + r = ((glDeleteBufferRegionEXT = (PFNGLDELETEBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteBufferRegionEXT")) == NULL) || r; + r = ((glDrawBufferRegionEXT = (PFNGLDRAWBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawBufferRegionEXT")) == NULL) || r; + r = ((glNewBufferRegionEXT = (PFNGLNEWBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glNewBufferRegionEXT")) == NULL) || r; + r = ((glReadBufferRegionEXT = (PFNGLREADBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glReadBufferRegionEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_KTX_buffer_region */ + +#ifdef GL_MESAX_texture_stack + +#endif /* GL_MESAX_texture_stack */ + +#ifdef GL_MESA_pack_invert + +#endif /* GL_MESA_pack_invert */ + +#ifdef GL_MESA_resize_buffers + +static GLboolean _glewInit_GL_MESA_resize_buffers (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glResizeBuffersMESA = (PFNGLRESIZEBUFFERSMESAPROC)glewGetProcAddress((const GLubyte*)"glResizeBuffersMESA")) == NULL) || r; + + return r; +} + +#endif /* GL_MESA_resize_buffers */ + +#ifdef GL_MESA_window_pos + +static GLboolean _glewInit_GL_MESA_window_pos (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glWindowPos2dMESA = (PFNGLWINDOWPOS2DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dMESA")) == NULL) || r; + r = ((glWindowPos2dvMESA = (PFNGLWINDOWPOS2DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2dvMESA")) == NULL) || r; + r = ((glWindowPos2fMESA = (PFNGLWINDOWPOS2FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fMESA")) == NULL) || r; + r = ((glWindowPos2fvMESA = (PFNGLWINDOWPOS2FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2fvMESA")) == NULL) || r; + r = ((glWindowPos2iMESA = (PFNGLWINDOWPOS2IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2iMESA")) == NULL) || r; + r = ((glWindowPos2ivMESA = (PFNGLWINDOWPOS2IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2ivMESA")) == NULL) || r; + r = ((glWindowPos2sMESA = (PFNGLWINDOWPOS2SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2sMESA")) == NULL) || r; + r = ((glWindowPos2svMESA = (PFNGLWINDOWPOS2SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos2svMESA")) == NULL) || r; + r = ((glWindowPos3dMESA = (PFNGLWINDOWPOS3DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dMESA")) == NULL) || r; + r = ((glWindowPos3dvMESA = (PFNGLWINDOWPOS3DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3dvMESA")) == NULL) || r; + r = ((glWindowPos3fMESA = (PFNGLWINDOWPOS3FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fMESA")) == NULL) || r; + r = ((glWindowPos3fvMESA = (PFNGLWINDOWPOS3FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3fvMESA")) == NULL) || r; + r = ((glWindowPos3iMESA = (PFNGLWINDOWPOS3IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3iMESA")) == NULL) || r; + r = ((glWindowPos3ivMESA = (PFNGLWINDOWPOS3IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3ivMESA")) == NULL) || r; + r = ((glWindowPos3sMESA = (PFNGLWINDOWPOS3SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3sMESA")) == NULL) || r; + r = ((glWindowPos3svMESA = (PFNGLWINDOWPOS3SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos3svMESA")) == NULL) || r; + r = ((glWindowPos4dMESA = (PFNGLWINDOWPOS4DMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4dMESA")) == NULL) || r; + r = ((glWindowPos4dvMESA = (PFNGLWINDOWPOS4DVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4dvMESA")) == NULL) || r; + r = ((glWindowPos4fMESA = (PFNGLWINDOWPOS4FMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4fMESA")) == NULL) || r; + r = ((glWindowPos4fvMESA = (PFNGLWINDOWPOS4FVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4fvMESA")) == NULL) || r; + r = ((glWindowPos4iMESA = (PFNGLWINDOWPOS4IMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4iMESA")) == NULL) || r; + r = ((glWindowPos4ivMESA = (PFNGLWINDOWPOS4IVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4ivMESA")) == NULL) || r; + r = ((glWindowPos4sMESA = (PFNGLWINDOWPOS4SMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4sMESA")) == NULL) || r; + r = ((glWindowPos4svMESA = (PFNGLWINDOWPOS4SVMESAPROC)glewGetProcAddress((const GLubyte*)"glWindowPos4svMESA")) == NULL) || r; + + return r; +} + +#endif /* GL_MESA_window_pos */ + +#ifdef GL_MESA_ycbcr_texture + +#endif /* GL_MESA_ycbcr_texture */ + +#ifdef GL_NVX_gpu_memory_info + +#endif /* GL_NVX_gpu_memory_info */ + +#ifdef GL_NV_blend_square + +#endif /* GL_NV_blend_square */ + +#ifdef GL_NV_conditional_render + +static GLboolean _glewInit_GL_NV_conditional_render (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginConditionalRenderNV = (PFNGLBEGINCONDITIONALRENDERNVPROC)glewGetProcAddress((const GLubyte*)"glBeginConditionalRenderNV")) == NULL) || r; + r = ((glEndConditionalRenderNV = (PFNGLENDCONDITIONALRENDERNVPROC)glewGetProcAddress((const GLubyte*)"glEndConditionalRenderNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_conditional_render */ + +#ifdef GL_NV_copy_depth_to_color + +#endif /* GL_NV_copy_depth_to_color */ + +#ifdef GL_NV_copy_image + +static GLboolean _glewInit_GL_NV_copy_image (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)glewGetProcAddress((const GLubyte*)"glCopyImageSubDataNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_copy_image */ + +#ifdef GL_NV_depth_buffer_float + +static GLboolean _glewInit_GL_NV_depth_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClearDepthdNV = (PFNGLCLEARDEPTHDNVPROC)glewGetProcAddress((const GLubyte*)"glClearDepthdNV")) == NULL) || r; + r = ((glDepthBoundsdNV = (PFNGLDEPTHBOUNDSDNVPROC)glewGetProcAddress((const GLubyte*)"glDepthBoundsdNV")) == NULL) || r; + r = ((glDepthRangedNV = (PFNGLDEPTHRANGEDNVPROC)glewGetProcAddress((const GLubyte*)"glDepthRangedNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_depth_buffer_float */ + +#ifdef GL_NV_depth_clamp + +#endif /* GL_NV_depth_clamp */ + +#ifdef GL_NV_depth_range_unclamped + +#endif /* GL_NV_depth_range_unclamped */ + +#ifdef GL_NV_evaluators + +static GLboolean _glewInit_GL_NV_evaluators (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glEvalMapsNV = (PFNGLEVALMAPSNVPROC)glewGetProcAddress((const GLubyte*)"glEvalMapsNV")) == NULL) || r; + r = ((glGetMapAttribParameterfvNV = (PFNGLGETMAPATTRIBPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapAttribParameterfvNV")) == NULL) || r; + r = ((glGetMapAttribParameterivNV = (PFNGLGETMAPATTRIBPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapAttribParameterivNV")) == NULL) || r; + r = ((glGetMapControlPointsNV = (PFNGLGETMAPCONTROLPOINTSNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapControlPointsNV")) == NULL) || r; + r = ((glGetMapParameterfvNV = (PFNGLGETMAPPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapParameterfvNV")) == NULL) || r; + r = ((glGetMapParameterivNV = (PFNGLGETMAPPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMapParameterivNV")) == NULL) || r; + r = ((glMapControlPointsNV = (PFNGLMAPCONTROLPOINTSNVPROC)glewGetProcAddress((const GLubyte*)"glMapControlPointsNV")) == NULL) || r; + r = ((glMapParameterfvNV = (PFNGLMAPPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glMapParameterfvNV")) == NULL) || r; + r = ((glMapParameterivNV = (PFNGLMAPPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glMapParameterivNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_evaluators */ + +#ifdef GL_NV_explicit_multisample + +static GLboolean _glewInit_GL_NV_explicit_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetMultisamplefvNV = (PFNGLGETMULTISAMPLEFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetMultisamplefvNV")) == NULL) || r; + r = ((glSampleMaskIndexedNV = (PFNGLSAMPLEMASKINDEXEDNVPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskIndexedNV")) == NULL) || r; + r = ((glTexRenderbufferNV = (PFNGLTEXRENDERBUFFERNVPROC)glewGetProcAddress((const GLubyte*)"glTexRenderbufferNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_explicit_multisample */ + +#ifdef GL_NV_fence + +static GLboolean _glewInit_GL_NV_fence (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDeleteFencesNV = (PFNGLDELETEFENCESNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteFencesNV")) == NULL) || r; + r = ((glFinishFenceNV = (PFNGLFINISHFENCENVPROC)glewGetProcAddress((const GLubyte*)"glFinishFenceNV")) == NULL) || r; + r = ((glGenFencesNV = (PFNGLGENFENCESNVPROC)glewGetProcAddress((const GLubyte*)"glGenFencesNV")) == NULL) || r; + r = ((glGetFenceivNV = (PFNGLGETFENCEIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFenceivNV")) == NULL) || r; + r = ((glIsFenceNV = (PFNGLISFENCENVPROC)glewGetProcAddress((const GLubyte*)"glIsFenceNV")) == NULL) || r; + r = ((glSetFenceNV = (PFNGLSETFENCENVPROC)glewGetProcAddress((const GLubyte*)"glSetFenceNV")) == NULL) || r; + r = ((glTestFenceNV = (PFNGLTESTFENCENVPROC)glewGetProcAddress((const GLubyte*)"glTestFenceNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_fence */ + +#ifdef GL_NV_float_buffer + +#endif /* GL_NV_float_buffer */ + +#ifdef GL_NV_fog_distance + +#endif /* GL_NV_fog_distance */ + +#ifdef GL_NV_fragment_program + +static GLboolean _glewInit_GL_NV_fragment_program (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetProgramNamedParameterdvNV = (PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramNamedParameterdvNV")) == NULL) || r; + r = ((glGetProgramNamedParameterfvNV = (PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramNamedParameterfvNV")) == NULL) || r; + r = ((glProgramNamedParameter4dNV = (PFNGLPROGRAMNAMEDPARAMETER4DNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4dNV")) == NULL) || r; + r = ((glProgramNamedParameter4dvNV = (PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4dvNV")) == NULL) || r; + r = ((glProgramNamedParameter4fNV = (PFNGLPROGRAMNAMEDPARAMETER4FNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4fNV")) == NULL) || r; + r = ((glProgramNamedParameter4fvNV = (PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramNamedParameter4fvNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_fragment_program */ + +#ifdef GL_NV_fragment_program2 + +#endif /* GL_NV_fragment_program2 */ + +#ifdef GL_NV_fragment_program4 + +#endif /* GL_NV_fragment_program4 */ + +#ifdef GL_NV_fragment_program_option + +#endif /* GL_NV_fragment_program_option */ + +#ifdef GL_NV_framebuffer_multisample_coverage + +static GLboolean _glewInit_GL_NV_framebuffer_multisample_coverage (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glRenderbufferStorageMultisampleCoverageNV = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleCoverageNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_framebuffer_multisample_coverage */ + +#ifdef GL_NV_geometry_program4 + +static GLboolean _glewInit_GL_NV_geometry_program4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glProgramVertexLimitNV = (PFNGLPROGRAMVERTEXLIMITNVPROC)glewGetProcAddress((const GLubyte*)"glProgramVertexLimitNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_geometry_program4 */ + +#ifdef GL_NV_geometry_shader4 + +#endif /* GL_NV_geometry_shader4 */ + +#ifdef GL_NV_gpu_program4 + +static GLboolean _glewInit_GL_NV_gpu_program4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glProgramEnvParameterI4iNV = (PFNGLPROGRAMENVPARAMETERI4INVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4iNV")) == NULL) || r; + r = ((glProgramEnvParameterI4ivNV = (PFNGLPROGRAMENVPARAMETERI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4ivNV")) == NULL) || r; + r = ((glProgramEnvParameterI4uiNV = (PFNGLPROGRAMENVPARAMETERI4UINVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4uiNV")) == NULL) || r; + r = ((glProgramEnvParameterI4uivNV = (PFNGLPROGRAMENVPARAMETERI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParameterI4uivNV")) == NULL) || r; + r = ((glProgramEnvParametersI4ivNV = (PFNGLPROGRAMENVPARAMETERSI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParametersI4ivNV")) == NULL) || r; + r = ((glProgramEnvParametersI4uivNV = (PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramEnvParametersI4uivNV")) == NULL) || r; + r = ((glProgramLocalParameterI4iNV = (PFNGLPROGRAMLOCALPARAMETERI4INVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4iNV")) == NULL) || r; + r = ((glProgramLocalParameterI4ivNV = (PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4ivNV")) == NULL) || r; + r = ((glProgramLocalParameterI4uiNV = (PFNGLPROGRAMLOCALPARAMETERI4UINVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4uiNV")) == NULL) || r; + r = ((glProgramLocalParameterI4uivNV = (PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParameterI4uivNV")) == NULL) || r; + r = ((glProgramLocalParametersI4ivNV = (PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParametersI4ivNV")) == NULL) || r; + r = ((glProgramLocalParametersI4uivNV = (PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramLocalParametersI4uivNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_gpu_program4 */ + +#ifdef GL_NV_gpu_program5 + +#endif /* GL_NV_gpu_program5 */ + +#ifdef GL_NV_gpu_program_fp64 + +#endif /* GL_NV_gpu_program_fp64 */ + +#ifdef GL_NV_gpu_shader5 + +static GLboolean _glewInit_GL_NV_gpu_shader5 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetUniformi64vNV = (PFNGLGETUNIFORMI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformi64vNV")) == NULL) || r; + r = ((glGetUniformui64vNV = (PFNGLGETUNIFORMUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformui64vNV")) == NULL) || r; + r = ((glProgramUniform1i64NV = (PFNGLPROGRAMUNIFORM1I64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1i64NV")) == NULL) || r; + r = ((glProgramUniform1i64vNV = (PFNGLPROGRAMUNIFORM1I64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1i64vNV")) == NULL) || r; + r = ((glProgramUniform1ui64NV = (PFNGLPROGRAMUNIFORM1UI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1ui64NV")) == NULL) || r; + r = ((glProgramUniform1ui64vNV = (PFNGLPROGRAMUNIFORM1UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1ui64vNV")) == NULL) || r; + r = ((glProgramUniform2i64NV = (PFNGLPROGRAMUNIFORM2I64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2i64NV")) == NULL) || r; + r = ((glProgramUniform2i64vNV = (PFNGLPROGRAMUNIFORM2I64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2i64vNV")) == NULL) || r; + r = ((glProgramUniform2ui64NV = (PFNGLPROGRAMUNIFORM2UI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2ui64NV")) == NULL) || r; + r = ((glProgramUniform2ui64vNV = (PFNGLPROGRAMUNIFORM2UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2ui64vNV")) == NULL) || r; + r = ((glProgramUniform3i64NV = (PFNGLPROGRAMUNIFORM3I64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3i64NV")) == NULL) || r; + r = ((glProgramUniform3i64vNV = (PFNGLPROGRAMUNIFORM3I64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3i64vNV")) == NULL) || r; + r = ((glProgramUniform3ui64NV = (PFNGLPROGRAMUNIFORM3UI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3ui64NV")) == NULL) || r; + r = ((glProgramUniform3ui64vNV = (PFNGLPROGRAMUNIFORM3UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3ui64vNV")) == NULL) || r; + r = ((glProgramUniform4i64NV = (PFNGLPROGRAMUNIFORM4I64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4i64NV")) == NULL) || r; + r = ((glProgramUniform4i64vNV = (PFNGLPROGRAMUNIFORM4I64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4i64vNV")) == NULL) || r; + r = ((glProgramUniform4ui64NV = (PFNGLPROGRAMUNIFORM4UI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4ui64NV")) == NULL) || r; + r = ((glProgramUniform4ui64vNV = (PFNGLPROGRAMUNIFORM4UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4ui64vNV")) == NULL) || r; + r = ((glUniform1i64NV = (PFNGLUNIFORM1I64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform1i64NV")) == NULL) || r; + r = ((glUniform1i64vNV = (PFNGLUNIFORM1I64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform1i64vNV")) == NULL) || r; + r = ((glUniform1ui64NV = (PFNGLUNIFORM1UI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform1ui64NV")) == NULL) || r; + r = ((glUniform1ui64vNV = (PFNGLUNIFORM1UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform1ui64vNV")) == NULL) || r; + r = ((glUniform2i64NV = (PFNGLUNIFORM2I64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform2i64NV")) == NULL) || r; + r = ((glUniform2i64vNV = (PFNGLUNIFORM2I64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform2i64vNV")) == NULL) || r; + r = ((glUniform2ui64NV = (PFNGLUNIFORM2UI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform2ui64NV")) == NULL) || r; + r = ((glUniform2ui64vNV = (PFNGLUNIFORM2UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform2ui64vNV")) == NULL) || r; + r = ((glUniform3i64NV = (PFNGLUNIFORM3I64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform3i64NV")) == NULL) || r; + r = ((glUniform3i64vNV = (PFNGLUNIFORM3I64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform3i64vNV")) == NULL) || r; + r = ((glUniform3ui64NV = (PFNGLUNIFORM3UI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform3ui64NV")) == NULL) || r; + r = ((glUniform3ui64vNV = (PFNGLUNIFORM3UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform3ui64vNV")) == NULL) || r; + r = ((glUniform4i64NV = (PFNGLUNIFORM4I64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform4i64NV")) == NULL) || r; + r = ((glUniform4i64vNV = (PFNGLUNIFORM4I64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform4i64vNV")) == NULL) || r; + r = ((glUniform4ui64NV = (PFNGLUNIFORM4UI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniform4ui64NV")) == NULL) || r; + r = ((glUniform4ui64vNV = (PFNGLUNIFORM4UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniform4ui64vNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_gpu_shader5 */ + +#ifdef GL_NV_half_float + +static GLboolean _glewInit_GL_NV_half_float (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColor3hNV = (PFNGLCOLOR3HNVPROC)glewGetProcAddress((const GLubyte*)"glColor3hNV")) == NULL) || r; + r = ((glColor3hvNV = (PFNGLCOLOR3HVNVPROC)glewGetProcAddress((const GLubyte*)"glColor3hvNV")) == NULL) || r; + r = ((glColor4hNV = (PFNGLCOLOR4HNVPROC)glewGetProcAddress((const GLubyte*)"glColor4hNV")) == NULL) || r; + r = ((glColor4hvNV = (PFNGLCOLOR4HVNVPROC)glewGetProcAddress((const GLubyte*)"glColor4hvNV")) == NULL) || r; + r = ((glFogCoordhNV = (PFNGLFOGCOORDHNVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordhNV")) == NULL) || r; + r = ((glFogCoordhvNV = (PFNGLFOGCOORDHVNVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordhvNV")) == NULL) || r; + r = ((glMultiTexCoord1hNV = (PFNGLMULTITEXCOORD1HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1hNV")) == NULL) || r; + r = ((glMultiTexCoord1hvNV = (PFNGLMULTITEXCOORD1HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord1hvNV")) == NULL) || r; + r = ((glMultiTexCoord2hNV = (PFNGLMULTITEXCOORD2HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2hNV")) == NULL) || r; + r = ((glMultiTexCoord2hvNV = (PFNGLMULTITEXCOORD2HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord2hvNV")) == NULL) || r; + r = ((glMultiTexCoord3hNV = (PFNGLMULTITEXCOORD3HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3hNV")) == NULL) || r; + r = ((glMultiTexCoord3hvNV = (PFNGLMULTITEXCOORD3HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord3hvNV")) == NULL) || r; + r = ((glMultiTexCoord4hNV = (PFNGLMULTITEXCOORD4HNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4hNV")) == NULL) || r; + r = ((glMultiTexCoord4hvNV = (PFNGLMULTITEXCOORD4HVNVPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4hvNV")) == NULL) || r; + r = ((glNormal3hNV = (PFNGLNORMAL3HNVPROC)glewGetProcAddress((const GLubyte*)"glNormal3hNV")) == NULL) || r; + r = ((glNormal3hvNV = (PFNGLNORMAL3HVNVPROC)glewGetProcAddress((const GLubyte*)"glNormal3hvNV")) == NULL) || r; + r = ((glSecondaryColor3hNV = (PFNGLSECONDARYCOLOR3HNVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3hNV")) == NULL) || r; + r = ((glSecondaryColor3hvNV = (PFNGLSECONDARYCOLOR3HVNVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColor3hvNV")) == NULL) || r; + r = ((glTexCoord1hNV = (PFNGLTEXCOORD1HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1hNV")) == NULL) || r; + r = ((glTexCoord1hvNV = (PFNGLTEXCOORD1HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord1hvNV")) == NULL) || r; + r = ((glTexCoord2hNV = (PFNGLTEXCOORD2HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2hNV")) == NULL) || r; + r = ((glTexCoord2hvNV = (PFNGLTEXCOORD2HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2hvNV")) == NULL) || r; + r = ((glTexCoord3hNV = (PFNGLTEXCOORD3HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3hNV")) == NULL) || r; + r = ((glTexCoord3hvNV = (PFNGLTEXCOORD3HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord3hvNV")) == NULL) || r; + r = ((glTexCoord4hNV = (PFNGLTEXCOORD4HNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4hNV")) == NULL) || r; + r = ((glTexCoord4hvNV = (PFNGLTEXCOORD4HVNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4hvNV")) == NULL) || r; + r = ((glVertex2hNV = (PFNGLVERTEX2HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex2hNV")) == NULL) || r; + r = ((glVertex2hvNV = (PFNGLVERTEX2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex2hvNV")) == NULL) || r; + r = ((glVertex3hNV = (PFNGLVERTEX3HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex3hNV")) == NULL) || r; + r = ((glVertex3hvNV = (PFNGLVERTEX3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex3hvNV")) == NULL) || r; + r = ((glVertex4hNV = (PFNGLVERTEX4HNVPROC)glewGetProcAddress((const GLubyte*)"glVertex4hNV")) == NULL) || r; + r = ((glVertex4hvNV = (PFNGLVERTEX4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertex4hvNV")) == NULL) || r; + r = ((glVertexAttrib1hNV = (PFNGLVERTEXATTRIB1HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1hNV")) == NULL) || r; + r = ((glVertexAttrib1hvNV = (PFNGLVERTEXATTRIB1HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1hvNV")) == NULL) || r; + r = ((glVertexAttrib2hNV = (PFNGLVERTEXATTRIB2HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2hNV")) == NULL) || r; + r = ((glVertexAttrib2hvNV = (PFNGLVERTEXATTRIB2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2hvNV")) == NULL) || r; + r = ((glVertexAttrib3hNV = (PFNGLVERTEXATTRIB3HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3hNV")) == NULL) || r; + r = ((glVertexAttrib3hvNV = (PFNGLVERTEXATTRIB3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3hvNV")) == NULL) || r; + r = ((glVertexAttrib4hNV = (PFNGLVERTEXATTRIB4HNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4hNV")) == NULL) || r; + r = ((glVertexAttrib4hvNV = (PFNGLVERTEXATTRIB4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4hvNV")) == NULL) || r; + r = ((glVertexAttribs1hvNV = (PFNGLVERTEXATTRIBS1HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1hvNV")) == NULL) || r; + r = ((glVertexAttribs2hvNV = (PFNGLVERTEXATTRIBS2HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2hvNV")) == NULL) || r; + r = ((glVertexAttribs3hvNV = (PFNGLVERTEXATTRIBS3HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3hvNV")) == NULL) || r; + r = ((glVertexAttribs4hvNV = (PFNGLVERTEXATTRIBS4HVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4hvNV")) == NULL) || r; + r = ((glVertexWeighthNV = (PFNGLVERTEXWEIGHTHNVPROC)glewGetProcAddress((const GLubyte*)"glVertexWeighthNV")) == NULL) || r; + r = ((glVertexWeighthvNV = (PFNGLVERTEXWEIGHTHVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexWeighthvNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_half_float */ + +#ifdef GL_NV_light_max_exponent + +#endif /* GL_NV_light_max_exponent */ + +#ifdef GL_NV_multisample_coverage + +#endif /* GL_NV_multisample_coverage */ + +#ifdef GL_NV_multisample_filter_hint + +#endif /* GL_NV_multisample_filter_hint */ + +#ifdef GL_NV_occlusion_query + +static GLboolean _glewInit_GL_NV_occlusion_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glBeginOcclusionQueryNV")) == NULL) || r; + r = ((glDeleteOcclusionQueriesNV = (PFNGLDELETEOCCLUSIONQUERIESNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteOcclusionQueriesNV")) == NULL) || r; + r = ((glEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glEndOcclusionQueryNV")) == NULL) || r; + r = ((glGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC)glewGetProcAddress((const GLubyte*)"glGenOcclusionQueriesNV")) == NULL) || r; + r = ((glGetOcclusionQueryivNV = (PFNGLGETOCCLUSIONQUERYIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetOcclusionQueryivNV")) == NULL) || r; + r = ((glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetOcclusionQueryuivNV")) == NULL) || r; + r = ((glIsOcclusionQueryNV = (PFNGLISOCCLUSIONQUERYNVPROC)glewGetProcAddress((const GLubyte*)"glIsOcclusionQueryNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_occlusion_query */ + +#ifdef GL_NV_packed_depth_stencil + +#endif /* GL_NV_packed_depth_stencil */ + +#ifdef GL_NV_parameter_buffer_object + +static GLboolean _glewInit_GL_NV_parameter_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glProgramBufferParametersIivNV = (PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersIivNV")) == NULL) || r; + r = ((glProgramBufferParametersIuivNV = (PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersIuivNV")) == NULL) || r; + r = ((glProgramBufferParametersfvNV = (PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramBufferParametersfvNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_parameter_buffer_object */ + +#ifdef GL_NV_parameter_buffer_object2 + +#endif /* GL_NV_parameter_buffer_object2 */ + +#ifdef GL_NV_pixel_data_range + +static GLboolean _glewInit_GL_NV_pixel_data_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFlushPixelDataRangeNV = (PFNGLFLUSHPIXELDATARANGENVPROC)glewGetProcAddress((const GLubyte*)"glFlushPixelDataRangeNV")) == NULL) || r; + r = ((glPixelDataRangeNV = (PFNGLPIXELDATARANGENVPROC)glewGetProcAddress((const GLubyte*)"glPixelDataRangeNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_pixel_data_range */ + +#ifdef GL_NV_point_sprite + +static GLboolean _glewInit_GL_NV_point_sprite (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPointParameteriNV = (PFNGLPOINTPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glPointParameteriNV")) == NULL) || r; + r = ((glPointParameterivNV = (PFNGLPOINTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterivNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_point_sprite */ + +#ifdef GL_NV_present_video + +static GLboolean _glewInit_GL_NV_present_video (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetVideoi64vNV = (PFNGLGETVIDEOI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoi64vNV")) == NULL) || r; + r = ((glGetVideoivNV = (PFNGLGETVIDEOIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoivNV")) == NULL) || r; + r = ((glGetVideoui64vNV = (PFNGLGETVIDEOUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoui64vNV")) == NULL) || r; + r = ((glGetVideouivNV = (PFNGLGETVIDEOUIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideouivNV")) == NULL) || r; + r = ((glPresentFrameDualFillNV = (PFNGLPRESENTFRAMEDUALFILLNVPROC)glewGetProcAddress((const GLubyte*)"glPresentFrameDualFillNV")) == NULL) || r; + r = ((glPresentFrameKeyedNV = (PFNGLPRESENTFRAMEKEYEDNVPROC)glewGetProcAddress((const GLubyte*)"glPresentFrameKeyedNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_present_video */ + +#ifdef GL_NV_primitive_restart + +static GLboolean _glewInit_GL_NV_primitive_restart (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPrimitiveRestartIndexNV = (PFNGLPRIMITIVERESTARTINDEXNVPROC)glewGetProcAddress((const GLubyte*)"glPrimitiveRestartIndexNV")) == NULL) || r; + r = ((glPrimitiveRestartNV = (PFNGLPRIMITIVERESTARTNVPROC)glewGetProcAddress((const GLubyte*)"glPrimitiveRestartNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_primitive_restart */ + +#ifdef GL_NV_register_combiners + +static GLboolean _glewInit_GL_NV_register_combiners (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCombinerInputNV = (PFNGLCOMBINERINPUTNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerInputNV")) == NULL) || r; + r = ((glCombinerOutputNV = (PFNGLCOMBINEROUTPUTNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerOutputNV")) == NULL) || r; + r = ((glCombinerParameterfNV = (PFNGLCOMBINERPARAMETERFNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterfNV")) == NULL) || r; + r = ((glCombinerParameterfvNV = (PFNGLCOMBINERPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterfvNV")) == NULL) || r; + r = ((glCombinerParameteriNV = (PFNGLCOMBINERPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameteriNV")) == NULL) || r; + r = ((glCombinerParameterivNV = (PFNGLCOMBINERPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerParameterivNV")) == NULL) || r; + r = ((glFinalCombinerInputNV = (PFNGLFINALCOMBINERINPUTNVPROC)glewGetProcAddress((const GLubyte*)"glFinalCombinerInputNV")) == NULL) || r; + r = ((glGetCombinerInputParameterfvNV = (PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerInputParameterfvNV")) == NULL) || r; + r = ((glGetCombinerInputParameterivNV = (PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerInputParameterivNV")) == NULL) || r; + r = ((glGetCombinerOutputParameterfvNV = (PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerOutputParameterfvNV")) == NULL) || r; + r = ((glGetCombinerOutputParameterivNV = (PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerOutputParameterivNV")) == NULL) || r; + r = ((glGetFinalCombinerInputParameterfvNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFinalCombinerInputParameterfvNV")) == NULL) || r; + r = ((glGetFinalCombinerInputParameterivNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetFinalCombinerInputParameterivNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_register_combiners */ + +#ifdef GL_NV_register_combiners2 + +static GLboolean _glewInit_GL_NV_register_combiners2 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCombinerStageParameterfvNV = (PFNGLCOMBINERSTAGEPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glCombinerStageParameterfvNV")) == NULL) || r; + r = ((glGetCombinerStageParameterfvNV = (PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetCombinerStageParameterfvNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_register_combiners2 */ + +#ifdef GL_NV_shader_buffer_load + +static GLboolean _glewInit_GL_NV_shader_buffer_load (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetBufferParameterui64vNV = (PFNGLGETBUFFERPARAMETERUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetBufferParameterui64vNV")) == NULL) || r; + r = ((glGetIntegerui64vNV = (PFNGLGETINTEGERUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetIntegerui64vNV")) == NULL) || r; + r = ((glGetNamedBufferParameterui64vNV = (PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetNamedBufferParameterui64vNV")) == NULL) || r; + r = ((glIsBufferResidentNV = (PFNGLISBUFFERRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glIsBufferResidentNV")) == NULL) || r; + r = ((glIsNamedBufferResidentNV = (PFNGLISNAMEDBUFFERRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glIsNamedBufferResidentNV")) == NULL) || r; + r = ((glMakeBufferNonResidentNV = (PFNGLMAKEBUFFERNONRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeBufferNonResidentNV")) == NULL) || r; + r = ((glMakeBufferResidentNV = (PFNGLMAKEBUFFERRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeBufferResidentNV")) == NULL) || r; + r = ((glMakeNamedBufferNonResidentNV = (PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeNamedBufferNonResidentNV")) == NULL) || r; + r = ((glMakeNamedBufferResidentNV = (PFNGLMAKENAMEDBUFFERRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeNamedBufferResidentNV")) == NULL) || r; + r = ((glProgramUniformui64NV = (PFNGLPROGRAMUNIFORMUI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformui64NV")) == NULL) || r; + r = ((glProgramUniformui64vNV = (PFNGLPROGRAMUNIFORMUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformui64vNV")) == NULL) || r; + r = ((glUniformui64NV = (PFNGLUNIFORMUI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniformui64NV")) == NULL) || r; + r = ((glUniformui64vNV = (PFNGLUNIFORMUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniformui64vNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_shader_buffer_load */ + +#ifdef GL_NV_tessellation_program5 + +#endif /* GL_NV_tessellation_program5 */ + +#ifdef GL_NV_texgen_emboss + +#endif /* GL_NV_texgen_emboss */ + +#ifdef GL_NV_texgen_reflection + +#endif /* GL_NV_texgen_reflection */ + +#ifdef GL_NV_texture_barrier + +static GLboolean _glewInit_GL_NV_texture_barrier (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTextureBarrierNV = (PFNGLTEXTUREBARRIERNVPROC)glewGetProcAddress((const GLubyte*)"glTextureBarrierNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_texture_barrier */ + +#ifdef GL_NV_texture_compression_vtc + +#endif /* GL_NV_texture_compression_vtc */ + +#ifdef GL_NV_texture_env_combine4 + +#endif /* GL_NV_texture_env_combine4 */ + +#ifdef GL_NV_texture_expand_normal + +#endif /* GL_NV_texture_expand_normal */ + +#ifdef GL_NV_texture_multisample + +static GLboolean _glewInit_GL_NV_texture_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexImage2DMultisampleCoverageNV = (PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glTexImage2DMultisampleCoverageNV")) == NULL) || r; + r = ((glTexImage3DMultisampleCoverageNV = (PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glTexImage3DMultisampleCoverageNV")) == NULL) || r; + r = ((glTextureImage2DMultisampleCoverageNV = (PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glTextureImage2DMultisampleCoverageNV")) == NULL) || r; + r = ((glTextureImage2DMultisampleNV = (PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC)glewGetProcAddress((const GLubyte*)"glTextureImage2DMultisampleNV")) == NULL) || r; + r = ((glTextureImage3DMultisampleCoverageNV = (PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC)glewGetProcAddress((const GLubyte*)"glTextureImage3DMultisampleCoverageNV")) == NULL) || r; + r = ((glTextureImage3DMultisampleNV = (PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC)glewGetProcAddress((const GLubyte*)"glTextureImage3DMultisampleNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_texture_multisample */ + +#ifdef GL_NV_texture_rectangle + +#endif /* GL_NV_texture_rectangle */ + +#ifdef GL_NV_texture_shader + +#endif /* GL_NV_texture_shader */ + +#ifdef GL_NV_texture_shader2 + +#endif /* GL_NV_texture_shader2 */ + +#ifdef GL_NV_texture_shader3 + +#endif /* GL_NV_texture_shader3 */ + +#ifdef GL_NV_transform_feedback + +static GLboolean _glewInit_GL_NV_transform_feedback (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glActiveVaryingNV = (PFNGLACTIVEVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glActiveVaryingNV")) == NULL) || r; + r = ((glBeginTransformFeedbackNV = (PFNGLBEGINTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glBeginTransformFeedbackNV")) == NULL) || r; + r = ((glBindBufferBaseNV = (PFNGLBINDBUFFERBASENVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferBaseNV")) == NULL) || r; + r = ((glBindBufferOffsetNV = (PFNGLBINDBUFFEROFFSETNVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferOffsetNV")) == NULL) || r; + r = ((glBindBufferRangeNV = (PFNGLBINDBUFFERRANGENVPROC)glewGetProcAddress((const GLubyte*)"glBindBufferRangeNV")) == NULL) || r; + r = ((glEndTransformFeedbackNV = (PFNGLENDTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glEndTransformFeedbackNV")) == NULL) || r; + r = ((glGetActiveVaryingNV = (PFNGLGETACTIVEVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveVaryingNV")) == NULL) || r; + r = ((glGetTransformFeedbackVaryingNV = (PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetTransformFeedbackVaryingNV")) == NULL) || r; + r = ((glGetVaryingLocationNV = (PFNGLGETVARYINGLOCATIONNVPROC)glewGetProcAddress((const GLubyte*)"glGetVaryingLocationNV")) == NULL) || r; + r = ((glTransformFeedbackAttribsNV = (PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackAttribsNV")) == NULL) || r; + r = ((glTransformFeedbackVaryingsNV = (PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC)glewGetProcAddress((const GLubyte*)"glTransformFeedbackVaryingsNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_transform_feedback */ + +#ifdef GL_NV_transform_feedback2 + +static GLboolean _glewInit_GL_NV_transform_feedback2 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindTransformFeedbackNV = (PFNGLBINDTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glBindTransformFeedbackNV")) == NULL) || r; + r = ((glDeleteTransformFeedbacksNV = (PFNGLDELETETRANSFORMFEEDBACKSNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteTransformFeedbacksNV")) == NULL) || r; + r = ((glDrawTransformFeedbackNV = (PFNGLDRAWTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glDrawTransformFeedbackNV")) == NULL) || r; + r = ((glGenTransformFeedbacksNV = (PFNGLGENTRANSFORMFEEDBACKSNVPROC)glewGetProcAddress((const GLubyte*)"glGenTransformFeedbacksNV")) == NULL) || r; + r = ((glIsTransformFeedbackNV = (PFNGLISTRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glIsTransformFeedbackNV")) == NULL) || r; + r = ((glPauseTransformFeedbackNV = (PFNGLPAUSETRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glPauseTransformFeedbackNV")) == NULL) || r; + r = ((glResumeTransformFeedbackNV = (PFNGLRESUMETRANSFORMFEEDBACKNVPROC)glewGetProcAddress((const GLubyte*)"glResumeTransformFeedbackNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_transform_feedback2 */ + +#ifdef GL_NV_vdpau_interop + +static GLboolean _glewInit_GL_NV_vdpau_interop (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glVDPAUFiniNV = (PFNGLVDPAUFININVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUFiniNV")) == NULL) || r; + r = ((glVDPAUGetSurfaceivNV = (PFNGLVDPAUGETSURFACEIVNVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUGetSurfaceivNV")) == NULL) || r; + r = ((glVDPAUInitNV = (PFNGLVDPAUINITNVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUInitNV")) == NULL) || r; + r = ((glVDPAUIsSurfaceNV = (PFNGLVDPAUISSURFACENVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUIsSurfaceNV")) == NULL) || r; + r = ((glVDPAUMapSurfacesNV = (PFNGLVDPAUMAPSURFACESNVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUMapSurfacesNV")) == NULL) || r; + r = ((glVDPAURegisterOutputSurfaceNV = (PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC)glewGetProcAddress((const GLubyte*)"glVDPAURegisterOutputSurfaceNV")) == NULL) || r; + r = ((glVDPAURegisterVideoSurfaceNV = (PFNGLVDPAUREGISTERVIDEOSURFACENVPROC)glewGetProcAddress((const GLubyte*)"glVDPAURegisterVideoSurfaceNV")) == NULL) || r; + r = ((glVDPAUSurfaceAccessNV = (PFNGLVDPAUSURFACEACCESSNVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUSurfaceAccessNV")) == NULL) || r; + r = ((glVDPAUUnmapSurfacesNV = (PFNGLVDPAUUNMAPSURFACESNVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUUnmapSurfacesNV")) == NULL) || r; + r = ((glVDPAUUnregisterSurfaceNV = (PFNGLVDPAUUNREGISTERSURFACENVPROC)glewGetProcAddress((const GLubyte*)"glVDPAUUnregisterSurfaceNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_vdpau_interop */ + +#ifdef GL_NV_vertex_array_range + +static GLboolean _glewInit_GL_NV_vertex_array_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFlushVertexArrayRangeNV = (PFNGLFLUSHVERTEXARRAYRANGENVPROC)glewGetProcAddress((const GLubyte*)"glFlushVertexArrayRangeNV")) == NULL) || r; + r = ((glVertexArrayRangeNV = (PFNGLVERTEXARRAYRANGENVPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayRangeNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_vertex_array_range */ + +#ifdef GL_NV_vertex_array_range2 + +#endif /* GL_NV_vertex_array_range2 */ + +#ifdef GL_NV_vertex_attrib_integer_64bit + +static GLboolean _glewInit_GL_NV_vertex_attrib_integer_64bit (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetVertexAttribLi64vNV = (PFNGLGETVERTEXATTRIBLI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribLi64vNV")) == NULL) || r; + r = ((glGetVertexAttribLui64vNV = (PFNGLGETVERTEXATTRIBLUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribLui64vNV")) == NULL) || r; + r = ((glVertexAttribL1i64NV = (PFNGLVERTEXATTRIBL1I64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1i64NV")) == NULL) || r; + r = ((glVertexAttribL1i64vNV = (PFNGLVERTEXATTRIBL1I64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1i64vNV")) == NULL) || r; + r = ((glVertexAttribL1ui64NV = (PFNGLVERTEXATTRIBL1UI64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1ui64NV")) == NULL) || r; + r = ((glVertexAttribL1ui64vNV = (PFNGLVERTEXATTRIBL1UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1ui64vNV")) == NULL) || r; + r = ((glVertexAttribL2i64NV = (PFNGLVERTEXATTRIBL2I64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2i64NV")) == NULL) || r; + r = ((glVertexAttribL2i64vNV = (PFNGLVERTEXATTRIBL2I64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2i64vNV")) == NULL) || r; + r = ((glVertexAttribL2ui64NV = (PFNGLVERTEXATTRIBL2UI64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2ui64NV")) == NULL) || r; + r = ((glVertexAttribL2ui64vNV = (PFNGLVERTEXATTRIBL2UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL2ui64vNV")) == NULL) || r; + r = ((glVertexAttribL3i64NV = (PFNGLVERTEXATTRIBL3I64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3i64NV")) == NULL) || r; + r = ((glVertexAttribL3i64vNV = (PFNGLVERTEXATTRIBL3I64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3i64vNV")) == NULL) || r; + r = ((glVertexAttribL3ui64NV = (PFNGLVERTEXATTRIBL3UI64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3ui64NV")) == NULL) || r; + r = ((glVertexAttribL3ui64vNV = (PFNGLVERTEXATTRIBL3UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL3ui64vNV")) == NULL) || r; + r = ((glVertexAttribL4i64NV = (PFNGLVERTEXATTRIBL4I64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4i64NV")) == NULL) || r; + r = ((glVertexAttribL4i64vNV = (PFNGLVERTEXATTRIBL4I64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4i64vNV")) == NULL) || r; + r = ((glVertexAttribL4ui64NV = (PFNGLVERTEXATTRIBL4UI64NVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4ui64NV")) == NULL) || r; + r = ((glVertexAttribL4ui64vNV = (PFNGLVERTEXATTRIBL4UI64VNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL4ui64vNV")) == NULL) || r; + r = ((glVertexAttribLFormatNV = (PFNGLVERTEXATTRIBLFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribLFormatNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_vertex_attrib_integer_64bit */ + +#ifdef GL_NV_vertex_buffer_unified_memory + +static GLboolean _glewInit_GL_NV_vertex_buffer_unified_memory (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBufferAddressRangeNV = (PFNGLBUFFERADDRESSRANGENVPROC)glewGetProcAddress((const GLubyte*)"glBufferAddressRangeNV")) == NULL) || r; + r = ((glColorFormatNV = (PFNGLCOLORFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glColorFormatNV")) == NULL) || r; + r = ((glEdgeFlagFormatNV = (PFNGLEDGEFLAGFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glEdgeFlagFormatNV")) == NULL) || r; + r = ((glFogCoordFormatNV = (PFNGLFOGCOORDFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glFogCoordFormatNV")) == NULL) || r; + r = ((glGetIntegerui64i_vNV = (PFNGLGETINTEGERUI64I_VNVPROC)glewGetProcAddress((const GLubyte*)"glGetIntegerui64i_vNV")) == NULL) || r; + r = ((glIndexFormatNV = (PFNGLINDEXFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glIndexFormatNV")) == NULL) || r; + r = ((glNormalFormatNV = (PFNGLNORMALFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glNormalFormatNV")) == NULL) || r; + r = ((glSecondaryColorFormatNV = (PFNGLSECONDARYCOLORFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glSecondaryColorFormatNV")) == NULL) || r; + r = ((glTexCoordFormatNV = (PFNGLTEXCOORDFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glTexCoordFormatNV")) == NULL) || r; + r = ((glVertexAttribFormatNV = (PFNGLVERTEXATTRIBFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribFormatNV")) == NULL) || r; + r = ((glVertexAttribIFormatNV = (PFNGLVERTEXATTRIBIFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIFormatNV")) == NULL) || r; + r = ((glVertexFormatNV = (PFNGLVERTEXFORMATNVPROC)glewGetProcAddress((const GLubyte*)"glVertexFormatNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_vertex_buffer_unified_memory */ + +#ifdef GL_NV_vertex_program + +static GLboolean _glewInit_GL_NV_vertex_program (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAreProgramsResidentNV = (PFNGLAREPROGRAMSRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glAreProgramsResidentNV")) == NULL) || r; + r = ((glBindProgramNV = (PFNGLBINDPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glBindProgramNV")) == NULL) || r; + r = ((glDeleteProgramsNV = (PFNGLDELETEPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glDeleteProgramsNV")) == NULL) || r; + r = ((glExecuteProgramNV = (PFNGLEXECUTEPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glExecuteProgramNV")) == NULL) || r; + r = ((glGenProgramsNV = (PFNGLGENPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glGenProgramsNV")) == NULL) || r; + r = ((glGetProgramParameterdvNV = (PFNGLGETPROGRAMPARAMETERDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramParameterdvNV")) == NULL) || r; + r = ((glGetProgramParameterfvNV = (PFNGLGETPROGRAMPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramParameterfvNV")) == NULL) || r; + r = ((glGetProgramStringNV = (PFNGLGETPROGRAMSTRINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramStringNV")) == NULL) || r; + r = ((glGetProgramivNV = (PFNGLGETPROGRAMIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramivNV")) == NULL) || r; + r = ((glGetTrackMatrixivNV = (PFNGLGETTRACKMATRIXIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetTrackMatrixivNV")) == NULL) || r; + r = ((glGetVertexAttribPointervNV = (PFNGLGETVERTEXATTRIBPOINTERVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribPointervNV")) == NULL) || r; + r = ((glGetVertexAttribdvNV = (PFNGLGETVERTEXATTRIBDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribdvNV")) == NULL) || r; + r = ((glGetVertexAttribfvNV = (PFNGLGETVERTEXATTRIBFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribfvNV")) == NULL) || r; + r = ((glGetVertexAttribivNV = (PFNGLGETVERTEXATTRIBIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribivNV")) == NULL) || r; + r = ((glIsProgramNV = (PFNGLISPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glIsProgramNV")) == NULL) || r; + r = ((glLoadProgramNV = (PFNGLLOADPROGRAMNVPROC)glewGetProcAddress((const GLubyte*)"glLoadProgramNV")) == NULL) || r; + r = ((glProgramParameter4dNV = (PFNGLPROGRAMPARAMETER4DNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4dNV")) == NULL) || r; + r = ((glProgramParameter4dvNV = (PFNGLPROGRAMPARAMETER4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4dvNV")) == NULL) || r; + r = ((glProgramParameter4fNV = (PFNGLPROGRAMPARAMETER4FNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4fNV")) == NULL) || r; + r = ((glProgramParameter4fvNV = (PFNGLPROGRAMPARAMETER4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameter4fvNV")) == NULL) || r; + r = ((glProgramParameters4dvNV = (PFNGLPROGRAMPARAMETERS4DVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameters4dvNV")) == NULL) || r; + r = ((glProgramParameters4fvNV = (PFNGLPROGRAMPARAMETERS4FVNVPROC)glewGetProcAddress((const GLubyte*)"glProgramParameters4fvNV")) == NULL) || r; + r = ((glRequestResidentProgramsNV = (PFNGLREQUESTRESIDENTPROGRAMSNVPROC)glewGetProcAddress((const GLubyte*)"glRequestResidentProgramsNV")) == NULL) || r; + r = ((glTrackMatrixNV = (PFNGLTRACKMATRIXNVPROC)glewGetProcAddress((const GLubyte*)"glTrackMatrixNV")) == NULL) || r; + r = ((glVertexAttrib1dNV = (PFNGLVERTEXATTRIB1DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dNV")) == NULL) || r; + r = ((glVertexAttrib1dvNV = (PFNGLVERTEXATTRIB1DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1dvNV")) == NULL) || r; + r = ((glVertexAttrib1fNV = (PFNGLVERTEXATTRIB1FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fNV")) == NULL) || r; + r = ((glVertexAttrib1fvNV = (PFNGLVERTEXATTRIB1FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1fvNV")) == NULL) || r; + r = ((glVertexAttrib1sNV = (PFNGLVERTEXATTRIB1SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1sNV")) == NULL) || r; + r = ((glVertexAttrib1svNV = (PFNGLVERTEXATTRIB1SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib1svNV")) == NULL) || r; + r = ((glVertexAttrib2dNV = (PFNGLVERTEXATTRIB2DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dNV")) == NULL) || r; + r = ((glVertexAttrib2dvNV = (PFNGLVERTEXATTRIB2DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2dvNV")) == NULL) || r; + r = ((glVertexAttrib2fNV = (PFNGLVERTEXATTRIB2FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fNV")) == NULL) || r; + r = ((glVertexAttrib2fvNV = (PFNGLVERTEXATTRIB2FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2fvNV")) == NULL) || r; + r = ((glVertexAttrib2sNV = (PFNGLVERTEXATTRIB2SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2sNV")) == NULL) || r; + r = ((glVertexAttrib2svNV = (PFNGLVERTEXATTRIB2SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib2svNV")) == NULL) || r; + r = ((glVertexAttrib3dNV = (PFNGLVERTEXATTRIB3DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dNV")) == NULL) || r; + r = ((glVertexAttrib3dvNV = (PFNGLVERTEXATTRIB3DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3dvNV")) == NULL) || r; + r = ((glVertexAttrib3fNV = (PFNGLVERTEXATTRIB3FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fNV")) == NULL) || r; + r = ((glVertexAttrib3fvNV = (PFNGLVERTEXATTRIB3FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3fvNV")) == NULL) || r; + r = ((glVertexAttrib3sNV = (PFNGLVERTEXATTRIB3SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3sNV")) == NULL) || r; + r = ((glVertexAttrib3svNV = (PFNGLVERTEXATTRIB3SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib3svNV")) == NULL) || r; + r = ((glVertexAttrib4dNV = (PFNGLVERTEXATTRIB4DNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dNV")) == NULL) || r; + r = ((glVertexAttrib4dvNV = (PFNGLVERTEXATTRIB4DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4dvNV")) == NULL) || r; + r = ((glVertexAttrib4fNV = (PFNGLVERTEXATTRIB4FNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fNV")) == NULL) || r; + r = ((glVertexAttrib4fvNV = (PFNGLVERTEXATTRIB4FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4fvNV")) == NULL) || r; + r = ((glVertexAttrib4sNV = (PFNGLVERTEXATTRIB4SNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4sNV")) == NULL) || r; + r = ((glVertexAttrib4svNV = (PFNGLVERTEXATTRIB4SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4svNV")) == NULL) || r; + r = ((glVertexAttrib4ubNV = (PFNGLVERTEXATTRIB4UBNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubNV")) == NULL) || r; + r = ((glVertexAttrib4ubvNV = (PFNGLVERTEXATTRIB4UBVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4ubvNV")) == NULL) || r; + r = ((glVertexAttribPointerNV = (PFNGLVERTEXATTRIBPOINTERNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointerNV")) == NULL) || r; + r = ((glVertexAttribs1dvNV = (PFNGLVERTEXATTRIBS1DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1dvNV")) == NULL) || r; + r = ((glVertexAttribs1fvNV = (PFNGLVERTEXATTRIBS1FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1fvNV")) == NULL) || r; + r = ((glVertexAttribs1svNV = (PFNGLVERTEXATTRIBS1SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs1svNV")) == NULL) || r; + r = ((glVertexAttribs2dvNV = (PFNGLVERTEXATTRIBS2DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2dvNV")) == NULL) || r; + r = ((glVertexAttribs2fvNV = (PFNGLVERTEXATTRIBS2FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2fvNV")) == NULL) || r; + r = ((glVertexAttribs2svNV = (PFNGLVERTEXATTRIBS2SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs2svNV")) == NULL) || r; + r = ((glVertexAttribs3dvNV = (PFNGLVERTEXATTRIBS3DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3dvNV")) == NULL) || r; + r = ((glVertexAttribs3fvNV = (PFNGLVERTEXATTRIBS3FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3fvNV")) == NULL) || r; + r = ((glVertexAttribs3svNV = (PFNGLVERTEXATTRIBS3SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs3svNV")) == NULL) || r; + r = ((glVertexAttribs4dvNV = (PFNGLVERTEXATTRIBS4DVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4dvNV")) == NULL) || r; + r = ((glVertexAttribs4fvNV = (PFNGLVERTEXATTRIBS4FVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4fvNV")) == NULL) || r; + r = ((glVertexAttribs4svNV = (PFNGLVERTEXATTRIBS4SVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4svNV")) == NULL) || r; + r = ((glVertexAttribs4ubvNV = (PFNGLVERTEXATTRIBS4UBVNVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribs4ubvNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_vertex_program */ + +#ifdef GL_NV_vertex_program1_1 + +#endif /* GL_NV_vertex_program1_1 */ + +#ifdef GL_NV_vertex_program2 + +#endif /* GL_NV_vertex_program2 */ + +#ifdef GL_NV_vertex_program2_option + +#endif /* GL_NV_vertex_program2_option */ + +#ifdef GL_NV_vertex_program3 + +#endif /* GL_NV_vertex_program3 */ + +#ifdef GL_NV_vertex_program4 + +#endif /* GL_NV_vertex_program4 */ + +#ifdef GL_NV_video_capture + +static GLboolean _glewInit_GL_NV_video_capture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginVideoCaptureNV = (PFNGLBEGINVIDEOCAPTURENVPROC)glewGetProcAddress((const GLubyte*)"glBeginVideoCaptureNV")) == NULL) || r; + r = ((glBindVideoCaptureStreamBufferNV = (PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC)glewGetProcAddress((const GLubyte*)"glBindVideoCaptureStreamBufferNV")) == NULL) || r; + r = ((glBindVideoCaptureStreamTextureNV = (PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC)glewGetProcAddress((const GLubyte*)"glBindVideoCaptureStreamTextureNV")) == NULL) || r; + r = ((glEndVideoCaptureNV = (PFNGLENDVIDEOCAPTURENVPROC)glewGetProcAddress((const GLubyte*)"glEndVideoCaptureNV")) == NULL) || r; + r = ((glGetVideoCaptureStreamdvNV = (PFNGLGETVIDEOCAPTURESTREAMDVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoCaptureStreamdvNV")) == NULL) || r; + r = ((glGetVideoCaptureStreamfvNV = (PFNGLGETVIDEOCAPTURESTREAMFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoCaptureStreamfvNV")) == NULL) || r; + r = ((glGetVideoCaptureStreamivNV = (PFNGLGETVIDEOCAPTURESTREAMIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoCaptureStreamivNV")) == NULL) || r; + r = ((glGetVideoCaptureivNV = (PFNGLGETVIDEOCAPTUREIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetVideoCaptureivNV")) == NULL) || r; + r = ((glVideoCaptureNV = (PFNGLVIDEOCAPTURENVPROC)glewGetProcAddress((const GLubyte*)"glVideoCaptureNV")) == NULL) || r; + r = ((glVideoCaptureStreamParameterdvNV = (PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC)glewGetProcAddress((const GLubyte*)"glVideoCaptureStreamParameterdvNV")) == NULL) || r; + r = ((glVideoCaptureStreamParameterfvNV = (PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glVideoCaptureStreamParameterfvNV")) == NULL) || r; + r = ((glVideoCaptureStreamParameterivNV = (PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glVideoCaptureStreamParameterivNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_video_capture */ + +#ifdef GL_OES_byte_coordinates + +#endif /* GL_OES_byte_coordinates */ + +#ifdef GL_OES_compressed_paletted_texture + +#endif /* GL_OES_compressed_paletted_texture */ + +#ifdef GL_OES_read_format + +#endif /* GL_OES_read_format */ + +#ifdef GL_OES_single_precision + +static GLboolean _glewInit_GL_OES_single_precision (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClearDepthfOES = (PFNGLCLEARDEPTHFOESPROC)glewGetProcAddress((const GLubyte*)"glClearDepthfOES")) == NULL) || r; + r = ((glClipPlanefOES = (PFNGLCLIPPLANEFOESPROC)glewGetProcAddress((const GLubyte*)"glClipPlanefOES")) == NULL) || r; + r = ((glDepthRangefOES = (PFNGLDEPTHRANGEFOESPROC)glewGetProcAddress((const GLubyte*)"glDepthRangefOES")) == NULL) || r; + r = ((glFrustumfOES = (PFNGLFRUSTUMFOESPROC)glewGetProcAddress((const GLubyte*)"glFrustumfOES")) == NULL) || r; + r = ((glGetClipPlanefOES = (PFNGLGETCLIPPLANEFOESPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlanefOES")) == NULL) || r; + r = ((glOrthofOES = (PFNGLORTHOFOESPROC)glewGetProcAddress((const GLubyte*)"glOrthofOES")) == NULL) || r; + + return r; +} + +#endif /* GL_OES_single_precision */ + +#ifdef GL_OML_interlace + +#endif /* GL_OML_interlace */ + +#ifdef GL_OML_resample + +#endif /* GL_OML_resample */ + +#ifdef GL_OML_subsample + +#endif /* GL_OML_subsample */ + +#ifdef GL_PGI_misc_hints + +#endif /* GL_PGI_misc_hints */ + +#ifdef GL_PGI_vertex_hints + +#endif /* GL_PGI_vertex_hints */ + +#ifdef GL_REND_screen_coordinates + +#endif /* GL_REND_screen_coordinates */ + +#ifdef GL_S3_s3tc + +#endif /* GL_S3_s3tc */ + +#ifdef GL_SGIS_color_range + +#endif /* GL_SGIS_color_range */ + +#ifdef GL_SGIS_detail_texture + +static GLboolean _glewInit_GL_SGIS_detail_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDetailTexFuncSGIS = (PFNGLDETAILTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glDetailTexFuncSGIS")) == NULL) || r; + r = ((glGetDetailTexFuncSGIS = (PFNGLGETDETAILTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetDetailTexFuncSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_detail_texture */ + +#ifdef GL_SGIS_fog_function + +static GLboolean _glewInit_GL_SGIS_fog_function (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFogFuncSGIS = (PFNGLFOGFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glFogFuncSGIS")) == NULL) || r; + r = ((glGetFogFuncSGIS = (PFNGLGETFOGFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetFogFuncSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_fog_function */ + +#ifdef GL_SGIS_generate_mipmap + +#endif /* GL_SGIS_generate_mipmap */ + +#ifdef GL_SGIS_multisample + +static GLboolean _glewInit_GL_SGIS_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSampleMaskSGIS = (PFNGLSAMPLEMASKSGISPROC)glewGetProcAddress((const GLubyte*)"glSampleMaskSGIS")) == NULL) || r; + r = ((glSamplePatternSGIS = (PFNGLSAMPLEPATTERNSGISPROC)glewGetProcAddress((const GLubyte*)"glSamplePatternSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_multisample */ + +#ifdef GL_SGIS_pixel_texture + +#endif /* GL_SGIS_pixel_texture */ + +#ifdef GL_SGIS_point_line_texgen + +#endif /* GL_SGIS_point_line_texgen */ + +#ifdef GL_SGIS_sharpen_texture + +static GLboolean _glewInit_GL_SGIS_sharpen_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetSharpenTexFuncSGIS = (PFNGLGETSHARPENTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetSharpenTexFuncSGIS")) == NULL) || r; + r = ((glSharpenTexFuncSGIS = (PFNGLSHARPENTEXFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glSharpenTexFuncSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_sharpen_texture */ + +#ifdef GL_SGIS_texture4D + +static GLboolean _glewInit_GL_SGIS_texture4D (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexImage4DSGIS = (PFNGLTEXIMAGE4DSGISPROC)glewGetProcAddress((const GLubyte*)"glTexImage4DSGIS")) == NULL) || r; + r = ((glTexSubImage4DSGIS = (PFNGLTEXSUBIMAGE4DSGISPROC)glewGetProcAddress((const GLubyte*)"glTexSubImage4DSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_texture4D */ + +#ifdef GL_SGIS_texture_border_clamp + +#endif /* GL_SGIS_texture_border_clamp */ + +#ifdef GL_SGIS_texture_edge_clamp + +#endif /* GL_SGIS_texture_edge_clamp */ + +#ifdef GL_SGIS_texture_filter4 + +static GLboolean _glewInit_GL_SGIS_texture_filter4 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetTexFilterFuncSGIS = (PFNGLGETTEXFILTERFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glGetTexFilterFuncSGIS")) == NULL) || r; + r = ((glTexFilterFuncSGIS = (PFNGLTEXFILTERFUNCSGISPROC)glewGetProcAddress((const GLubyte*)"glTexFilterFuncSGIS")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIS_texture_filter4 */ + +#ifdef GL_SGIS_texture_lod + +#endif /* GL_SGIS_texture_lod */ + +#ifdef GL_SGIS_texture_select + +#endif /* GL_SGIS_texture_select */ + +#ifdef GL_SGIX_async + +static GLboolean _glewInit_GL_SGIX_async (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAsyncMarkerSGIX = (PFNGLASYNCMARKERSGIXPROC)glewGetProcAddress((const GLubyte*)"glAsyncMarkerSGIX")) == NULL) || r; + r = ((glDeleteAsyncMarkersSGIX = (PFNGLDELETEASYNCMARKERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glDeleteAsyncMarkersSGIX")) == NULL) || r; + r = ((glFinishAsyncSGIX = (PFNGLFINISHASYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glFinishAsyncSGIX")) == NULL) || r; + r = ((glGenAsyncMarkersSGIX = (PFNGLGENASYNCMARKERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glGenAsyncMarkersSGIX")) == NULL) || r; + r = ((glIsAsyncMarkerSGIX = (PFNGLISASYNCMARKERSGIXPROC)glewGetProcAddress((const GLubyte*)"glIsAsyncMarkerSGIX")) == NULL) || r; + r = ((glPollAsyncSGIX = (PFNGLPOLLASYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glPollAsyncSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_async */ + +#ifdef GL_SGIX_async_histogram + +#endif /* GL_SGIX_async_histogram */ + +#ifdef GL_SGIX_async_pixel + +#endif /* GL_SGIX_async_pixel */ + +#ifdef GL_SGIX_blend_alpha_minmax + +#endif /* GL_SGIX_blend_alpha_minmax */ + +#ifdef GL_SGIX_clipmap + +#endif /* GL_SGIX_clipmap */ + +#ifdef GL_SGIX_convolution_accuracy + +#endif /* GL_SGIX_convolution_accuracy */ + +#ifdef GL_SGIX_depth_texture + +#endif /* GL_SGIX_depth_texture */ + +#ifdef GL_SGIX_flush_raster + +static GLboolean _glewInit_GL_SGIX_flush_raster (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFlushRasterSGIX = (PFNGLFLUSHRASTERSGIXPROC)glewGetProcAddress((const GLubyte*)"glFlushRasterSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_flush_raster */ + +#ifdef GL_SGIX_fog_offset + +#endif /* GL_SGIX_fog_offset */ + +#ifdef GL_SGIX_fog_texture + +static GLboolean _glewInit_GL_SGIX_fog_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTextureFogSGIX = (PFNGLTEXTUREFOGSGIXPROC)glewGetProcAddress((const GLubyte*)"glTextureFogSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_fog_texture */ + +#ifdef GL_SGIX_fragment_specular_lighting + +static GLboolean _glewInit_GL_SGIX_fragment_specular_lighting (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFragmentColorMaterialSGIX = (PFNGLFRAGMENTCOLORMATERIALSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentColorMaterialSGIX")) == NULL) || r; + r = ((glFragmentLightModelfSGIX = (PFNGLFRAGMENTLIGHTMODELFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfSGIX")) == NULL) || r; + r = ((glFragmentLightModelfvSGIX = (PFNGLFRAGMENTLIGHTMODELFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelfvSGIX")) == NULL) || r; + r = ((glFragmentLightModeliSGIX = (PFNGLFRAGMENTLIGHTMODELISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModeliSGIX")) == NULL) || r; + r = ((glFragmentLightModelivSGIX = (PFNGLFRAGMENTLIGHTMODELIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightModelivSGIX")) == NULL) || r; + r = ((glFragmentLightfSGIX = (PFNGLFRAGMENTLIGHTFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfSGIX")) == NULL) || r; + r = ((glFragmentLightfvSGIX = (PFNGLFRAGMENTLIGHTFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightfvSGIX")) == NULL) || r; + r = ((glFragmentLightiSGIX = (PFNGLFRAGMENTLIGHTISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightiSGIX")) == NULL) || r; + r = ((glFragmentLightivSGIX = (PFNGLFRAGMENTLIGHTIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentLightivSGIX")) == NULL) || r; + r = ((glFragmentMaterialfSGIX = (PFNGLFRAGMENTMATERIALFSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfSGIX")) == NULL) || r; + r = ((glFragmentMaterialfvSGIX = (PFNGLFRAGMENTMATERIALFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialfvSGIX")) == NULL) || r; + r = ((glFragmentMaterialiSGIX = (PFNGLFRAGMENTMATERIALISGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialiSGIX")) == NULL) || r; + r = ((glFragmentMaterialivSGIX = (PFNGLFRAGMENTMATERIALIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glFragmentMaterialivSGIX")) == NULL) || r; + r = ((glGetFragmentLightfvSGIX = (PFNGLGETFRAGMENTLIGHTFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightfvSGIX")) == NULL) || r; + r = ((glGetFragmentLightivSGIX = (PFNGLGETFRAGMENTLIGHTIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentLightivSGIX")) == NULL) || r; + r = ((glGetFragmentMaterialfvSGIX = (PFNGLGETFRAGMENTMATERIALFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialfvSGIX")) == NULL) || r; + r = ((glGetFragmentMaterialivSGIX = (PFNGLGETFRAGMENTMATERIALIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glGetFragmentMaterialivSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_fragment_specular_lighting */ + +#ifdef GL_SGIX_framezoom + +static GLboolean _glewInit_GL_SGIX_framezoom (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFrameZoomSGIX = (PFNGLFRAMEZOOMSGIXPROC)glewGetProcAddress((const GLubyte*)"glFrameZoomSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_framezoom */ + +#ifdef GL_SGIX_interlace + +#endif /* GL_SGIX_interlace */ + +#ifdef GL_SGIX_ir_instrument1 + +#endif /* GL_SGIX_ir_instrument1 */ + +#ifdef GL_SGIX_list_priority + +#endif /* GL_SGIX_list_priority */ + +#ifdef GL_SGIX_pixel_texture + +static GLboolean _glewInit_GL_SGIX_pixel_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glPixelTexGenSGIX = (PFNGLPIXELTEXGENSGIXPROC)glewGetProcAddress((const GLubyte*)"glPixelTexGenSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_pixel_texture */ + +#ifdef GL_SGIX_pixel_texture_bits + +#endif /* GL_SGIX_pixel_texture_bits */ + +#ifdef GL_SGIX_reference_plane + +static GLboolean _glewInit_GL_SGIX_reference_plane (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glReferencePlaneSGIX = (PFNGLREFERENCEPLANESGIXPROC)glewGetProcAddress((const GLubyte*)"glReferencePlaneSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_reference_plane */ + +#ifdef GL_SGIX_resample + +#endif /* GL_SGIX_resample */ + +#ifdef GL_SGIX_shadow + +#endif /* GL_SGIX_shadow */ + +#ifdef GL_SGIX_shadow_ambient + +#endif /* GL_SGIX_shadow_ambient */ + +#ifdef GL_SGIX_sprite + +static GLboolean _glewInit_GL_SGIX_sprite (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glSpriteParameterfSGIX = (PFNGLSPRITEPARAMETERFSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterfSGIX")) == NULL) || r; + r = ((glSpriteParameterfvSGIX = (PFNGLSPRITEPARAMETERFVSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterfvSGIX")) == NULL) || r; + r = ((glSpriteParameteriSGIX = (PFNGLSPRITEPARAMETERISGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameteriSGIX")) == NULL) || r; + r = ((glSpriteParameterivSGIX = (PFNGLSPRITEPARAMETERIVSGIXPROC)glewGetProcAddress((const GLubyte*)"glSpriteParameterivSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_sprite */ + +#ifdef GL_SGIX_tag_sample_buffer + +static GLboolean _glewInit_GL_SGIX_tag_sample_buffer (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTagSampleBufferSGIX = (PFNGLTAGSAMPLEBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glTagSampleBufferSGIX")) == NULL) || r; + + return r; +} + +#endif /* GL_SGIX_tag_sample_buffer */ + +#ifdef GL_SGIX_texture_add_env + +#endif /* GL_SGIX_texture_add_env */ + +#ifdef GL_SGIX_texture_coordinate_clamp + +#endif /* GL_SGIX_texture_coordinate_clamp */ + +#ifdef GL_SGIX_texture_lod_bias + +#endif /* GL_SGIX_texture_lod_bias */ + +#ifdef GL_SGIX_texture_multi_buffer + +#endif /* GL_SGIX_texture_multi_buffer */ + +#ifdef GL_SGIX_texture_range + +#endif /* GL_SGIX_texture_range */ + +#ifdef GL_SGIX_texture_scale_bias + +#endif /* GL_SGIX_texture_scale_bias */ + +#ifdef GL_SGIX_vertex_preclip + +#endif /* GL_SGIX_vertex_preclip */ + +#ifdef GL_SGIX_vertex_preclip_hint + +#endif /* GL_SGIX_vertex_preclip_hint */ + +#ifdef GL_SGIX_ycrcb + +#endif /* GL_SGIX_ycrcb */ + +#ifdef GL_SGI_color_matrix + +#endif /* GL_SGI_color_matrix */ + +#ifdef GL_SGI_color_table + +static GLboolean _glewInit_GL_SGI_color_table (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColorTableParameterfvSGI = (PFNGLCOLORTABLEPARAMETERFVSGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterfvSGI")) == NULL) || r; + r = ((glColorTableParameterivSGI = (PFNGLCOLORTABLEPARAMETERIVSGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableParameterivSGI")) == NULL) || r; + r = ((glColorTableSGI = (PFNGLCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glColorTableSGI")) == NULL) || r; + r = ((glCopyColorTableSGI = (PFNGLCOPYCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glCopyColorTableSGI")) == NULL) || r; + r = ((glGetColorTableParameterfvSGI = (PFNGLGETCOLORTABLEPARAMETERFVSGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterfvSGI")) == NULL) || r; + r = ((glGetColorTableParameterivSGI = (PFNGLGETCOLORTABLEPARAMETERIVSGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableParameterivSGI")) == NULL) || r; + r = ((glGetColorTableSGI = (PFNGLGETCOLORTABLESGIPROC)glewGetProcAddress((const GLubyte*)"glGetColorTableSGI")) == NULL) || r; + + return r; +} + +#endif /* GL_SGI_color_table */ + +#ifdef GL_SGI_texture_color_table + +#endif /* GL_SGI_texture_color_table */ + +#ifdef GL_SUNX_constant_data + +static GLboolean _glewInit_GL_SUNX_constant_data (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFinishTextureSUNX = (PFNGLFINISHTEXTURESUNXPROC)glewGetProcAddress((const GLubyte*)"glFinishTextureSUNX")) == NULL) || r; + + return r; +} + +#endif /* GL_SUNX_constant_data */ + +#ifdef GL_SUN_convolution_border_modes + +#endif /* GL_SUN_convolution_border_modes */ + +#ifdef GL_SUN_global_alpha + +static GLboolean _glewInit_GL_SUN_global_alpha (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGlobalAlphaFactorbSUN = (PFNGLGLOBALALPHAFACTORBSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorbSUN")) == NULL) || r; + r = ((glGlobalAlphaFactordSUN = (PFNGLGLOBALALPHAFACTORDSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactordSUN")) == NULL) || r; + r = ((glGlobalAlphaFactorfSUN = (PFNGLGLOBALALPHAFACTORFSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorfSUN")) == NULL) || r; + r = ((glGlobalAlphaFactoriSUN = (PFNGLGLOBALALPHAFACTORISUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactoriSUN")) == NULL) || r; + r = ((glGlobalAlphaFactorsSUN = (PFNGLGLOBALALPHAFACTORSSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorsSUN")) == NULL) || r; + r = ((glGlobalAlphaFactorubSUN = (PFNGLGLOBALALPHAFACTORUBSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorubSUN")) == NULL) || r; + r = ((glGlobalAlphaFactoruiSUN = (PFNGLGLOBALALPHAFACTORUISUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactoruiSUN")) == NULL) || r; + r = ((glGlobalAlphaFactorusSUN = (PFNGLGLOBALALPHAFACTORUSSUNPROC)glewGetProcAddress((const GLubyte*)"glGlobalAlphaFactorusSUN")) == NULL) || r; + + return r; +} + +#endif /* GL_SUN_global_alpha */ + +#ifdef GL_SUN_mesh_array + +#endif /* GL_SUN_mesh_array */ + +#ifdef GL_SUN_read_video_pixels + +static GLboolean _glewInit_GL_SUN_read_video_pixels (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glReadVideoPixelsSUN = (PFNGLREADVIDEOPIXELSSUNPROC)glewGetProcAddress((const GLubyte*)"glReadVideoPixelsSUN")) == NULL) || r; + + return r; +} + +#endif /* GL_SUN_read_video_pixels */ + +#ifdef GL_SUN_slice_accum + +#endif /* GL_SUN_slice_accum */ + +#ifdef GL_SUN_triangle_list + +static GLboolean _glewInit_GL_SUN_triangle_list (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glReplacementCodePointerSUN = (PFNGLREPLACEMENTCODEPOINTERSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodePointerSUN")) == NULL) || r; + r = ((glReplacementCodeubSUN = (PFNGLREPLACEMENTCODEUBSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeubSUN")) == NULL) || r; + r = ((glReplacementCodeubvSUN = (PFNGLREPLACEMENTCODEUBVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeubvSUN")) == NULL) || r; + r = ((glReplacementCodeuiSUN = (PFNGLREPLACEMENTCODEUISUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiSUN")) == NULL) || r; + r = ((glReplacementCodeuivSUN = (PFNGLREPLACEMENTCODEUIVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuivSUN")) == NULL) || r; + r = ((glReplacementCodeusSUN = (PFNGLREPLACEMENTCODEUSSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeusSUN")) == NULL) || r; + r = ((glReplacementCodeusvSUN = (PFNGLREPLACEMENTCODEUSVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeusvSUN")) == NULL) || r; + + return r; +} + +#endif /* GL_SUN_triangle_list */ + +#ifdef GL_SUN_vertex + +static GLboolean _glewInit_GL_SUN_vertex (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glColor3fVertex3fSUN = (PFNGLCOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor3fVertex3fSUN")) == NULL) || r; + r = ((glColor3fVertex3fvSUN = (PFNGLCOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor3fVertex3fvSUN")) == NULL) || r; + r = ((glColor4fNormal3fVertex3fSUN = (PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glColor4fNormal3fVertex3fvSUN = (PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glColor4ubVertex2fSUN = (PFNGLCOLOR4UBVERTEX2FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex2fSUN")) == NULL) || r; + r = ((glColor4ubVertex2fvSUN = (PFNGLCOLOR4UBVERTEX2FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex2fvSUN")) == NULL) || r; + r = ((glColor4ubVertex3fSUN = (PFNGLCOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex3fSUN")) == NULL) || r; + r = ((glColor4ubVertex3fvSUN = (PFNGLCOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glColor4ubVertex3fvSUN")) == NULL) || r; + r = ((glNormal3fVertex3fSUN = (PFNGLNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glNormal3fVertex3fSUN")) == NULL) || r; + r = ((glNormal3fVertex3fvSUN = (PFNGLNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor3fVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor3fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor4fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor4fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor4ubVertex3fSUN = (PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4ubVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiColor4ubVertex3fvSUN = (PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiColor4ubVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiNormal3fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fVertex3fSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiTexCoord2fVertex3fvSUN = (PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiTexCoord2fVertex3fvSUN")) == NULL) || r; + r = ((glReplacementCodeuiVertex3fSUN = (PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiVertex3fSUN")) == NULL) || r; + r = ((glReplacementCodeuiVertex3fvSUN = (PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glReplacementCodeuiVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord2fColor3fVertex3fSUN = (PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor3fVertex3fSUN")) == NULL) || r; + r = ((glTexCoord2fColor3fVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor3fVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord2fColor4fNormal3fVertex3fSUN = (PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glTexCoord2fColor4fNormal3fVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord2fColor4ubVertex3fSUN = (PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4ubVertex3fSUN")) == NULL) || r; + r = ((glTexCoord2fColor4ubVertex3fvSUN = (PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fColor4ubVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord2fNormal3fVertex3fSUN = (PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fNormal3fVertex3fSUN")) == NULL) || r; + r = ((glTexCoord2fNormal3fVertex3fvSUN = (PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fNormal3fVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord2fVertex3fSUN = (PFNGLTEXCOORD2FVERTEX3FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fVertex3fSUN")) == NULL) || r; + r = ((glTexCoord2fVertex3fvSUN = (PFNGLTEXCOORD2FVERTEX3FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord2fVertex3fvSUN")) == NULL) || r; + r = ((glTexCoord4fColor4fNormal3fVertex4fSUN = (PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fColor4fNormal3fVertex4fSUN")) == NULL) || r; + r = ((glTexCoord4fColor4fNormal3fVertex4fvSUN = (PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fColor4fNormal3fVertex4fvSUN")) == NULL) || r; + r = ((glTexCoord4fVertex4fSUN = (PFNGLTEXCOORD4FVERTEX4FSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fVertex4fSUN")) == NULL) || r; + r = ((glTexCoord4fVertex4fvSUN = (PFNGLTEXCOORD4FVERTEX4FVSUNPROC)glewGetProcAddress((const GLubyte*)"glTexCoord4fVertex4fvSUN")) == NULL) || r; + + return r; +} + +#endif /* GL_SUN_vertex */ + +#ifdef GL_WIN_phong_shading + +#endif /* GL_WIN_phong_shading */ + +#ifdef GL_WIN_specular_fog + +#endif /* GL_WIN_specular_fog */ + +#ifdef GL_WIN_swap_hint + +static GLboolean _glewInit_GL_WIN_swap_hint (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAddSwapHintRectWIN = (PFNGLADDSWAPHINTRECTWINPROC)glewGetProcAddress((const GLubyte*)"glAddSwapHintRectWIN")) == NULL) || r; + + return r; +} + +#endif /* GL_WIN_swap_hint */ + +/* ------------------------------------------------------------------------- */ + +GLboolean glewGetExtension (const char* name) +{ + const GLubyte* start; + const GLubyte* end; + start = (const GLubyte*)glGetString(GL_EXTENSIONS); + if (start == 0) + return GL_FALSE; + end = start + _glewStrLen(start); + return _glewSearchExtension(name, start, end); +} + +/* ------------------------------------------------------------------------- */ + +#ifndef GLEW_MX +static +#endif +GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) +{ + const GLubyte* s; + GLuint dot; + GLint major, minor; + const GLubyte* extStart; + const GLubyte* extEnd; + /* query opengl version */ + s = glGetString(GL_VERSION); + dot = _glewStrCLen(s, '.'); + if (dot == 0) + return GLEW_ERROR_NO_GL_VERSION; + + major = s[dot-1]-'0'; + minor = s[dot+1]-'0'; + + if (minor < 0 || minor > 9) + minor = 0; + if (major<0 || major>9) + return GLEW_ERROR_NO_GL_VERSION; + + + if (major == 1 && minor == 0) + { + return GLEW_ERROR_GL_VERSION_10_ONLY; + } + else + { + CONST_CAST(GLEW_VERSION_4_1) = ( major > 4 ) || ( major == 4 && minor >= 1 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_4_0) = GLEW_VERSION_4_1 == GL_TRUE || ( major == 4 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_3_3) = GLEW_VERSION_4_0 == GL_TRUE || ( major == 3 && minor >= 3 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_3_2) = GLEW_VERSION_3_3 == GL_TRUE || ( major == 3 && minor >= 2 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_3_1) = GLEW_VERSION_3_2 == GL_TRUE || ( major == 3 && minor >= 1 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_3_0) = GLEW_VERSION_3_1 == GL_TRUE || ( major == 3 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_2_1) = GLEW_VERSION_3_0 == GL_TRUE || ( major == 2 && minor >= 1 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_2_0) = GLEW_VERSION_2_1 == GL_TRUE || ( major == 2 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_1_5) = GLEW_VERSION_2_0 == GL_TRUE || ( major == 1 && minor >= 5 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_1_4) = GLEW_VERSION_1_5 == GL_TRUE || ( major == 1 && minor >= 4 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_1_3) = GLEW_VERSION_1_4 == GL_TRUE || ( major == 1 && minor >= 3 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_1_2_1) = GLEW_VERSION_1_3 == GL_TRUE ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_1_2) = GLEW_VERSION_1_2_1 == GL_TRUE || ( major == 1 && minor >= 2 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_1_1) = GLEW_VERSION_1_2 == GL_TRUE || ( major == 1 && minor >= 1 ) ? GL_TRUE : GL_FALSE; + } + + /* query opengl extensions string */ + extStart = glGetString(GL_EXTENSIONS); + if (extStart == 0) + extStart = (const GLubyte*)""; + extEnd = extStart + _glewStrLen(extStart); + + /* initialize extensions */ +#ifdef GL_VERSION_1_2 + if (glewExperimental || GLEW_VERSION_1_2) CONST_CAST(GLEW_VERSION_1_2) = !_glewInit_GL_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_1_2 */ +#ifdef GL_VERSION_1_2_1 +#endif /* GL_VERSION_1_2_1 */ +#ifdef GL_VERSION_1_3 + if (glewExperimental || GLEW_VERSION_1_3) CONST_CAST(GLEW_VERSION_1_3) = !_glewInit_GL_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_1_3 */ +#ifdef GL_VERSION_1_4 + if (glewExperimental || GLEW_VERSION_1_4) CONST_CAST(GLEW_VERSION_1_4) = !_glewInit_GL_VERSION_1_4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_1_4 */ +#ifdef GL_VERSION_1_5 + if (glewExperimental || GLEW_VERSION_1_5) CONST_CAST(GLEW_VERSION_1_5) = !_glewInit_GL_VERSION_1_5(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_1_5 */ +#ifdef GL_VERSION_2_0 + if (glewExperimental || GLEW_VERSION_2_0) CONST_CAST(GLEW_VERSION_2_0) = !_glewInit_GL_VERSION_2_0(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_2_0 */ +#ifdef GL_VERSION_2_1 + if (glewExperimental || GLEW_VERSION_2_1) CONST_CAST(GLEW_VERSION_2_1) = !_glewInit_GL_VERSION_2_1(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_2_1 */ +#ifdef GL_VERSION_3_0 + if (glewExperimental || GLEW_VERSION_3_0) CONST_CAST(GLEW_VERSION_3_0) = !_glewInit_GL_VERSION_3_0(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_3_0 */ +#ifdef GL_VERSION_3_1 + if (glewExperimental || GLEW_VERSION_3_1) CONST_CAST(GLEW_VERSION_3_1) = !_glewInit_GL_VERSION_3_1(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_3_1 */ +#ifdef GL_VERSION_3_2 + if (glewExperimental || GLEW_VERSION_3_2) CONST_CAST(GLEW_VERSION_3_2) = !_glewInit_GL_VERSION_3_2(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_3_2 */ +#ifdef GL_VERSION_3_3 + if (glewExperimental || GLEW_VERSION_3_3) CONST_CAST(GLEW_VERSION_3_3) = !_glewInit_GL_VERSION_3_3(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_3_3 */ +#ifdef GL_VERSION_4_0 + if (glewExperimental || GLEW_VERSION_4_0) CONST_CAST(GLEW_VERSION_4_0) = !_glewInit_GL_VERSION_4_0(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_VERSION_4_0 */ +#ifdef GL_VERSION_4_1 +#endif /* GL_VERSION_4_1 */ +#ifdef GL_3DFX_multisample + CONST_CAST(GLEW_3DFX_multisample) = _glewSearchExtension("GL_3DFX_multisample", extStart, extEnd); +#endif /* GL_3DFX_multisample */ +#ifdef GL_3DFX_tbuffer + CONST_CAST(GLEW_3DFX_tbuffer) = _glewSearchExtension("GL_3DFX_tbuffer", extStart, extEnd); + if (glewExperimental || GLEW_3DFX_tbuffer) CONST_CAST(GLEW_3DFX_tbuffer) = !_glewInit_GL_3DFX_tbuffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_3DFX_tbuffer */ +#ifdef GL_3DFX_texture_compression_FXT1 + CONST_CAST(GLEW_3DFX_texture_compression_FXT1) = _glewSearchExtension("GL_3DFX_texture_compression_FXT1", extStart, extEnd); +#endif /* GL_3DFX_texture_compression_FXT1 */ +#ifdef GL_AMD_blend_minmax_factor + CONST_CAST(GLEW_AMD_blend_minmax_factor) = _glewSearchExtension("GL_AMD_blend_minmax_factor", extStart, extEnd); +#endif /* GL_AMD_blend_minmax_factor */ +#ifdef GL_AMD_conservative_depth + CONST_CAST(GLEW_AMD_conservative_depth) = _glewSearchExtension("GL_AMD_conservative_depth", extStart, extEnd); +#endif /* GL_AMD_conservative_depth */ +#ifdef GL_AMD_debug_output + CONST_CAST(GLEW_AMD_debug_output) = _glewSearchExtension("GL_AMD_debug_output", extStart, extEnd); + if (glewExperimental || GLEW_AMD_debug_output) CONST_CAST(GLEW_AMD_debug_output) = !_glewInit_GL_AMD_debug_output(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_debug_output */ +#ifdef GL_AMD_depth_clamp_separate + CONST_CAST(GLEW_AMD_depth_clamp_separate) = _glewSearchExtension("GL_AMD_depth_clamp_separate", extStart, extEnd); +#endif /* GL_AMD_depth_clamp_separate */ +#ifdef GL_AMD_draw_buffers_blend + CONST_CAST(GLEW_AMD_draw_buffers_blend) = _glewSearchExtension("GL_AMD_draw_buffers_blend", extStart, extEnd); + if (glewExperimental || GLEW_AMD_draw_buffers_blend) CONST_CAST(GLEW_AMD_draw_buffers_blend) = !_glewInit_GL_AMD_draw_buffers_blend(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_draw_buffers_blend */ +#ifdef GL_AMD_name_gen_delete + CONST_CAST(GLEW_AMD_name_gen_delete) = _glewSearchExtension("GL_AMD_name_gen_delete", extStart, extEnd); + if (glewExperimental || GLEW_AMD_name_gen_delete) CONST_CAST(GLEW_AMD_name_gen_delete) = !_glewInit_GL_AMD_name_gen_delete(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_name_gen_delete */ +#ifdef GL_AMD_performance_monitor + CONST_CAST(GLEW_AMD_performance_monitor) = _glewSearchExtension("GL_AMD_performance_monitor", extStart, extEnd); + if (glewExperimental || GLEW_AMD_performance_monitor) CONST_CAST(GLEW_AMD_performance_monitor) = !_glewInit_GL_AMD_performance_monitor(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_performance_monitor */ +#ifdef GL_AMD_sample_positions + CONST_CAST(GLEW_AMD_sample_positions) = _glewSearchExtension("GL_AMD_sample_positions", extStart, extEnd); + if (glewExperimental || GLEW_AMD_sample_positions) CONST_CAST(GLEW_AMD_sample_positions) = !_glewInit_GL_AMD_sample_positions(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_sample_positions */ +#ifdef GL_AMD_seamless_cubemap_per_texture + CONST_CAST(GLEW_AMD_seamless_cubemap_per_texture) = _glewSearchExtension("GL_AMD_seamless_cubemap_per_texture", extStart, extEnd); +#endif /* GL_AMD_seamless_cubemap_per_texture */ +#ifdef GL_AMD_shader_stencil_export + CONST_CAST(GLEW_AMD_shader_stencil_export) = _glewSearchExtension("GL_AMD_shader_stencil_export", extStart, extEnd); +#endif /* GL_AMD_shader_stencil_export */ +#ifdef GL_AMD_texture_texture4 + CONST_CAST(GLEW_AMD_texture_texture4) = _glewSearchExtension("GL_AMD_texture_texture4", extStart, extEnd); +#endif /* GL_AMD_texture_texture4 */ +#ifdef GL_AMD_transform_feedback3_lines_triangles + CONST_CAST(GLEW_AMD_transform_feedback3_lines_triangles) = _glewSearchExtension("GL_AMD_transform_feedback3_lines_triangles", extStart, extEnd); +#endif /* GL_AMD_transform_feedback3_lines_triangles */ +#ifdef GL_AMD_vertex_shader_tessellator + CONST_CAST(GLEW_AMD_vertex_shader_tessellator) = _glewSearchExtension("GL_AMD_vertex_shader_tessellator", extStart, extEnd); + if (glewExperimental || GLEW_AMD_vertex_shader_tessellator) CONST_CAST(GLEW_AMD_vertex_shader_tessellator) = !_glewInit_GL_AMD_vertex_shader_tessellator(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_vertex_shader_tessellator */ +#ifdef GL_APPLE_aux_depth_stencil + CONST_CAST(GLEW_APPLE_aux_depth_stencil) = _glewSearchExtension("GL_APPLE_aux_depth_stencil", extStart, extEnd); +#endif /* GL_APPLE_aux_depth_stencil */ +#ifdef GL_APPLE_client_storage + CONST_CAST(GLEW_APPLE_client_storage) = _glewSearchExtension("GL_APPLE_client_storage", extStart, extEnd); +#endif /* GL_APPLE_client_storage */ +#ifdef GL_APPLE_element_array + CONST_CAST(GLEW_APPLE_element_array) = _glewSearchExtension("GL_APPLE_element_array", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_element_array) CONST_CAST(GLEW_APPLE_element_array) = !_glewInit_GL_APPLE_element_array(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_element_array */ +#ifdef GL_APPLE_fence + CONST_CAST(GLEW_APPLE_fence) = _glewSearchExtension("GL_APPLE_fence", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_fence) CONST_CAST(GLEW_APPLE_fence) = !_glewInit_GL_APPLE_fence(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_fence */ +#ifdef GL_APPLE_float_pixels + CONST_CAST(GLEW_APPLE_float_pixels) = _glewSearchExtension("GL_APPLE_float_pixels", extStart, extEnd); +#endif /* GL_APPLE_float_pixels */ +#ifdef GL_APPLE_flush_buffer_range + CONST_CAST(GLEW_APPLE_flush_buffer_range) = _glewSearchExtension("GL_APPLE_flush_buffer_range", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_flush_buffer_range) CONST_CAST(GLEW_APPLE_flush_buffer_range) = !_glewInit_GL_APPLE_flush_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_flush_buffer_range */ +#ifdef GL_APPLE_object_purgeable + CONST_CAST(GLEW_APPLE_object_purgeable) = _glewSearchExtension("GL_APPLE_object_purgeable", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_object_purgeable) CONST_CAST(GLEW_APPLE_object_purgeable) = !_glewInit_GL_APPLE_object_purgeable(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_object_purgeable */ +#ifdef GL_APPLE_pixel_buffer + CONST_CAST(GLEW_APPLE_pixel_buffer) = _glewSearchExtension("GL_APPLE_pixel_buffer", extStart, extEnd); +#endif /* GL_APPLE_pixel_buffer */ +#ifdef GL_APPLE_rgb_422 + CONST_CAST(GLEW_APPLE_rgb_422) = _glewSearchExtension("GL_APPLE_rgb_422", extStart, extEnd); +#endif /* GL_APPLE_rgb_422 */ +#ifdef GL_APPLE_row_bytes + CONST_CAST(GLEW_APPLE_row_bytes) = _glewSearchExtension("GL_APPLE_row_bytes", extStart, extEnd); +#endif /* GL_APPLE_row_bytes */ +#ifdef GL_APPLE_specular_vector + CONST_CAST(GLEW_APPLE_specular_vector) = _glewSearchExtension("GL_APPLE_specular_vector", extStart, extEnd); +#endif /* GL_APPLE_specular_vector */ +#ifdef GL_APPLE_texture_range + CONST_CAST(GLEW_APPLE_texture_range) = _glewSearchExtension("GL_APPLE_texture_range", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_texture_range) CONST_CAST(GLEW_APPLE_texture_range) = !_glewInit_GL_APPLE_texture_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_texture_range */ +#ifdef GL_APPLE_transform_hint + CONST_CAST(GLEW_APPLE_transform_hint) = _glewSearchExtension("GL_APPLE_transform_hint", extStart, extEnd); +#endif /* GL_APPLE_transform_hint */ +#ifdef GL_APPLE_vertex_array_object + CONST_CAST(GLEW_APPLE_vertex_array_object) = _glewSearchExtension("GL_APPLE_vertex_array_object", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_vertex_array_object) CONST_CAST(GLEW_APPLE_vertex_array_object) = !_glewInit_GL_APPLE_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_vertex_array_object */ +#ifdef GL_APPLE_vertex_array_range + CONST_CAST(GLEW_APPLE_vertex_array_range) = _glewSearchExtension("GL_APPLE_vertex_array_range", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_vertex_array_range) CONST_CAST(GLEW_APPLE_vertex_array_range) = !_glewInit_GL_APPLE_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_vertex_array_range */ +#ifdef GL_APPLE_vertex_program_evaluators + CONST_CAST(GLEW_APPLE_vertex_program_evaluators) = _glewSearchExtension("GL_APPLE_vertex_program_evaluators", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_vertex_program_evaluators) CONST_CAST(GLEW_APPLE_vertex_program_evaluators) = !_glewInit_GL_APPLE_vertex_program_evaluators(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_APPLE_vertex_program_evaluators */ +#ifdef GL_APPLE_ycbcr_422 + CONST_CAST(GLEW_APPLE_ycbcr_422) = _glewSearchExtension("GL_APPLE_ycbcr_422", extStart, extEnd); +#endif /* GL_APPLE_ycbcr_422 */ +#ifdef GL_ARB_ES2_compatibility + CONST_CAST(GLEW_ARB_ES2_compatibility) = _glewSearchExtension("GL_ARB_ES2_compatibility", extStart, extEnd); + if (glewExperimental || GLEW_ARB_ES2_compatibility) CONST_CAST(GLEW_ARB_ES2_compatibility) = !_glewInit_GL_ARB_ES2_compatibility(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_ES2_compatibility */ +#ifdef GL_ARB_blend_func_extended + CONST_CAST(GLEW_ARB_blend_func_extended) = _glewSearchExtension("GL_ARB_blend_func_extended", extStart, extEnd); + if (glewExperimental || GLEW_ARB_blend_func_extended) CONST_CAST(GLEW_ARB_blend_func_extended) = !_glewInit_GL_ARB_blend_func_extended(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_blend_func_extended */ +#ifdef GL_ARB_cl_event + CONST_CAST(GLEW_ARB_cl_event) = _glewSearchExtension("GL_ARB_cl_event", extStart, extEnd); + if (glewExperimental || GLEW_ARB_cl_event) CONST_CAST(GLEW_ARB_cl_event) = !_glewInit_GL_ARB_cl_event(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_cl_event */ +#ifdef GL_ARB_color_buffer_float + CONST_CAST(GLEW_ARB_color_buffer_float) = _glewSearchExtension("GL_ARB_color_buffer_float", extStart, extEnd); + if (glewExperimental || GLEW_ARB_color_buffer_float) CONST_CAST(GLEW_ARB_color_buffer_float) = !_glewInit_GL_ARB_color_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_color_buffer_float */ +#ifdef GL_ARB_compatibility + CONST_CAST(GLEW_ARB_compatibility) = _glewSearchExtension("GL_ARB_compatibility", extStart, extEnd); +#endif /* GL_ARB_compatibility */ +#ifdef GL_ARB_copy_buffer + CONST_CAST(GLEW_ARB_copy_buffer) = _glewSearchExtension("GL_ARB_copy_buffer", extStart, extEnd); + if (glewExperimental || GLEW_ARB_copy_buffer) CONST_CAST(GLEW_ARB_copy_buffer) = !_glewInit_GL_ARB_copy_buffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_copy_buffer */ +#ifdef GL_ARB_debug_output + CONST_CAST(GLEW_ARB_debug_output) = _glewSearchExtension("GL_ARB_debug_output", extStart, extEnd); + if (glewExperimental || GLEW_ARB_debug_output) CONST_CAST(GLEW_ARB_debug_output) = !_glewInit_GL_ARB_debug_output(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_debug_output */ +#ifdef GL_ARB_depth_buffer_float + CONST_CAST(GLEW_ARB_depth_buffer_float) = _glewSearchExtension("GL_ARB_depth_buffer_float", extStart, extEnd); +#endif /* GL_ARB_depth_buffer_float */ +#ifdef GL_ARB_depth_clamp + CONST_CAST(GLEW_ARB_depth_clamp) = _glewSearchExtension("GL_ARB_depth_clamp", extStart, extEnd); +#endif /* GL_ARB_depth_clamp */ +#ifdef GL_ARB_depth_texture + CONST_CAST(GLEW_ARB_depth_texture) = _glewSearchExtension("GL_ARB_depth_texture", extStart, extEnd); +#endif /* GL_ARB_depth_texture */ +#ifdef GL_ARB_draw_buffers + CONST_CAST(GLEW_ARB_draw_buffers) = _glewSearchExtension("GL_ARB_draw_buffers", extStart, extEnd); + if (glewExperimental || GLEW_ARB_draw_buffers) CONST_CAST(GLEW_ARB_draw_buffers) = !_glewInit_GL_ARB_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_draw_buffers */ +#ifdef GL_ARB_draw_buffers_blend + CONST_CAST(GLEW_ARB_draw_buffers_blend) = _glewSearchExtension("GL_ARB_draw_buffers_blend", extStart, extEnd); + if (glewExperimental || GLEW_ARB_draw_buffers_blend) CONST_CAST(GLEW_ARB_draw_buffers_blend) = !_glewInit_GL_ARB_draw_buffers_blend(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_draw_buffers_blend */ +#ifdef GL_ARB_draw_elements_base_vertex + CONST_CAST(GLEW_ARB_draw_elements_base_vertex) = _glewSearchExtension("GL_ARB_draw_elements_base_vertex", extStart, extEnd); + if (glewExperimental || GLEW_ARB_draw_elements_base_vertex) CONST_CAST(GLEW_ARB_draw_elements_base_vertex) = !_glewInit_GL_ARB_draw_elements_base_vertex(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_draw_elements_base_vertex */ +#ifdef GL_ARB_draw_indirect + CONST_CAST(GLEW_ARB_draw_indirect) = _glewSearchExtension("GL_ARB_draw_indirect", extStart, extEnd); + if (glewExperimental || GLEW_ARB_draw_indirect) CONST_CAST(GLEW_ARB_draw_indirect) = !_glewInit_GL_ARB_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_draw_indirect */ +#ifdef GL_ARB_draw_instanced + CONST_CAST(GLEW_ARB_draw_instanced) = _glewSearchExtension("GL_ARB_draw_instanced", extStart, extEnd); +#endif /* GL_ARB_draw_instanced */ +#ifdef GL_ARB_explicit_attrib_location + CONST_CAST(GLEW_ARB_explicit_attrib_location) = _glewSearchExtension("GL_ARB_explicit_attrib_location", extStart, extEnd); +#endif /* GL_ARB_explicit_attrib_location */ +#ifdef GL_ARB_fragment_coord_conventions + CONST_CAST(GLEW_ARB_fragment_coord_conventions) = _glewSearchExtension("GL_ARB_fragment_coord_conventions", extStart, extEnd); +#endif /* GL_ARB_fragment_coord_conventions */ +#ifdef GL_ARB_fragment_program + CONST_CAST(GLEW_ARB_fragment_program) = _glewSearchExtension("GL_ARB_fragment_program", extStart, extEnd); +#endif /* GL_ARB_fragment_program */ +#ifdef GL_ARB_fragment_program_shadow + CONST_CAST(GLEW_ARB_fragment_program_shadow) = _glewSearchExtension("GL_ARB_fragment_program_shadow", extStart, extEnd); +#endif /* GL_ARB_fragment_program_shadow */ +#ifdef GL_ARB_fragment_shader + CONST_CAST(GLEW_ARB_fragment_shader) = _glewSearchExtension("GL_ARB_fragment_shader", extStart, extEnd); +#endif /* GL_ARB_fragment_shader */ +#ifdef GL_ARB_framebuffer_object + CONST_CAST(GLEW_ARB_framebuffer_object) = _glewSearchExtension("GL_ARB_framebuffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_framebuffer_object) CONST_CAST(GLEW_ARB_framebuffer_object) = !_glewInit_GL_ARB_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_framebuffer_object */ +#ifdef GL_ARB_framebuffer_sRGB + CONST_CAST(GLEW_ARB_framebuffer_sRGB) = _glewSearchExtension("GL_ARB_framebuffer_sRGB", extStart, extEnd); +#endif /* GL_ARB_framebuffer_sRGB */ +#ifdef GL_ARB_geometry_shader4 + CONST_CAST(GLEW_ARB_geometry_shader4) = _glewSearchExtension("GL_ARB_geometry_shader4", extStart, extEnd); + if (glewExperimental || GLEW_ARB_geometry_shader4) CONST_CAST(GLEW_ARB_geometry_shader4) = !_glewInit_GL_ARB_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_geometry_shader4 */ +#ifdef GL_ARB_get_program_binary + CONST_CAST(GLEW_ARB_get_program_binary) = _glewSearchExtension("GL_ARB_get_program_binary", extStart, extEnd); + if (glewExperimental || GLEW_ARB_get_program_binary) CONST_CAST(GLEW_ARB_get_program_binary) = !_glewInit_GL_ARB_get_program_binary(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_get_program_binary */ +#ifdef GL_ARB_gpu_shader5 + CONST_CAST(GLEW_ARB_gpu_shader5) = _glewSearchExtension("GL_ARB_gpu_shader5", extStart, extEnd); +#endif /* GL_ARB_gpu_shader5 */ +#ifdef GL_ARB_gpu_shader_fp64 + CONST_CAST(GLEW_ARB_gpu_shader_fp64) = _glewSearchExtension("GL_ARB_gpu_shader_fp64", extStart, extEnd); + if (glewExperimental || GLEW_ARB_gpu_shader_fp64) CONST_CAST(GLEW_ARB_gpu_shader_fp64) = !_glewInit_GL_ARB_gpu_shader_fp64(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_gpu_shader_fp64 */ +#ifdef GL_ARB_half_float_pixel + CONST_CAST(GLEW_ARB_half_float_pixel) = _glewSearchExtension("GL_ARB_half_float_pixel", extStart, extEnd); +#endif /* GL_ARB_half_float_pixel */ +#ifdef GL_ARB_half_float_vertex + CONST_CAST(GLEW_ARB_half_float_vertex) = _glewSearchExtension("GL_ARB_half_float_vertex", extStart, extEnd); +#endif /* GL_ARB_half_float_vertex */ +#ifdef GL_ARB_imaging + CONST_CAST(GLEW_ARB_imaging) = _glewSearchExtension("GL_ARB_imaging", extStart, extEnd); + if (glewExperimental || GLEW_ARB_imaging) CONST_CAST(GLEW_ARB_imaging) = !_glewInit_GL_ARB_imaging(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_imaging */ +#ifdef GL_ARB_instanced_arrays + CONST_CAST(GLEW_ARB_instanced_arrays) = _glewSearchExtension("GL_ARB_instanced_arrays", extStart, extEnd); + if (glewExperimental || GLEW_ARB_instanced_arrays) CONST_CAST(GLEW_ARB_instanced_arrays) = !_glewInit_GL_ARB_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_instanced_arrays */ +#ifdef GL_ARB_map_buffer_range + CONST_CAST(GLEW_ARB_map_buffer_range) = _glewSearchExtension("GL_ARB_map_buffer_range", extStart, extEnd); + if (glewExperimental || GLEW_ARB_map_buffer_range) CONST_CAST(GLEW_ARB_map_buffer_range) = !_glewInit_GL_ARB_map_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_map_buffer_range */ +#ifdef GL_ARB_matrix_palette + CONST_CAST(GLEW_ARB_matrix_palette) = _glewSearchExtension("GL_ARB_matrix_palette", extStart, extEnd); + if (glewExperimental || GLEW_ARB_matrix_palette) CONST_CAST(GLEW_ARB_matrix_palette) = !_glewInit_GL_ARB_matrix_palette(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_matrix_palette */ +#ifdef GL_ARB_multisample + CONST_CAST(GLEW_ARB_multisample) = _glewSearchExtension("GL_ARB_multisample", extStart, extEnd); + if (glewExperimental || GLEW_ARB_multisample) CONST_CAST(GLEW_ARB_multisample) = !_glewInit_GL_ARB_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_multisample */ +#ifdef GL_ARB_multitexture + CONST_CAST(GLEW_ARB_multitexture) = _glewSearchExtension("GL_ARB_multitexture", extStart, extEnd); + if (glewExperimental || GLEW_ARB_multitexture) CONST_CAST(GLEW_ARB_multitexture) = !_glewInit_GL_ARB_multitexture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_multitexture */ +#ifdef GL_ARB_occlusion_query + CONST_CAST(GLEW_ARB_occlusion_query) = _glewSearchExtension("GL_ARB_occlusion_query", extStart, extEnd); + if (glewExperimental || GLEW_ARB_occlusion_query) CONST_CAST(GLEW_ARB_occlusion_query) = !_glewInit_GL_ARB_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_occlusion_query */ +#ifdef GL_ARB_occlusion_query2 + CONST_CAST(GLEW_ARB_occlusion_query2) = _glewSearchExtension("GL_ARB_occlusion_query2", extStart, extEnd); +#endif /* GL_ARB_occlusion_query2 */ +#ifdef GL_ARB_pixel_buffer_object + CONST_CAST(GLEW_ARB_pixel_buffer_object) = _glewSearchExtension("GL_ARB_pixel_buffer_object", extStart, extEnd); +#endif /* GL_ARB_pixel_buffer_object */ +#ifdef GL_ARB_point_parameters + CONST_CAST(GLEW_ARB_point_parameters) = _glewSearchExtension("GL_ARB_point_parameters", extStart, extEnd); + if (glewExperimental || GLEW_ARB_point_parameters) CONST_CAST(GLEW_ARB_point_parameters) = !_glewInit_GL_ARB_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_point_parameters */ +#ifdef GL_ARB_point_sprite + CONST_CAST(GLEW_ARB_point_sprite) = _glewSearchExtension("GL_ARB_point_sprite", extStart, extEnd); +#endif /* GL_ARB_point_sprite */ +#ifdef GL_ARB_provoking_vertex + CONST_CAST(GLEW_ARB_provoking_vertex) = _glewSearchExtension("GL_ARB_provoking_vertex", extStart, extEnd); + if (glewExperimental || GLEW_ARB_provoking_vertex) CONST_CAST(GLEW_ARB_provoking_vertex) = !_glewInit_GL_ARB_provoking_vertex(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_provoking_vertex */ +#ifdef GL_ARB_robustness + CONST_CAST(GLEW_ARB_robustness) = _glewSearchExtension("GL_ARB_robustness", extStart, extEnd); + if (glewExperimental || GLEW_ARB_robustness) CONST_CAST(GLEW_ARB_robustness) = !_glewInit_GL_ARB_robustness(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_robustness */ +#ifdef GL_ARB_sample_shading + CONST_CAST(GLEW_ARB_sample_shading) = _glewSearchExtension("GL_ARB_sample_shading", extStart, extEnd); + if (glewExperimental || GLEW_ARB_sample_shading) CONST_CAST(GLEW_ARB_sample_shading) = !_glewInit_GL_ARB_sample_shading(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_sample_shading */ +#ifdef GL_ARB_sampler_objects + CONST_CAST(GLEW_ARB_sampler_objects) = _glewSearchExtension("GL_ARB_sampler_objects", extStart, extEnd); + if (glewExperimental || GLEW_ARB_sampler_objects) CONST_CAST(GLEW_ARB_sampler_objects) = !_glewInit_GL_ARB_sampler_objects(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_sampler_objects */ +#ifdef GL_ARB_seamless_cube_map + CONST_CAST(GLEW_ARB_seamless_cube_map) = _glewSearchExtension("GL_ARB_seamless_cube_map", extStart, extEnd); +#endif /* GL_ARB_seamless_cube_map */ +#ifdef GL_ARB_separate_shader_objects + CONST_CAST(GLEW_ARB_separate_shader_objects) = _glewSearchExtension("GL_ARB_separate_shader_objects", extStart, extEnd); + if (glewExperimental || GLEW_ARB_separate_shader_objects) CONST_CAST(GLEW_ARB_separate_shader_objects) = !_glewInit_GL_ARB_separate_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_separate_shader_objects */ +#ifdef GL_ARB_shader_bit_encoding + CONST_CAST(GLEW_ARB_shader_bit_encoding) = _glewSearchExtension("GL_ARB_shader_bit_encoding", extStart, extEnd); +#endif /* GL_ARB_shader_bit_encoding */ +#ifdef GL_ARB_shader_objects + CONST_CAST(GLEW_ARB_shader_objects) = _glewSearchExtension("GL_ARB_shader_objects", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shader_objects) CONST_CAST(GLEW_ARB_shader_objects) = !_glewInit_GL_ARB_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_shader_objects */ +#ifdef GL_ARB_shader_precision + CONST_CAST(GLEW_ARB_shader_precision) = _glewSearchExtension("GL_ARB_shader_precision", extStart, extEnd); +#endif /* GL_ARB_shader_precision */ +#ifdef GL_ARB_shader_stencil_export + CONST_CAST(GLEW_ARB_shader_stencil_export) = _glewSearchExtension("GL_ARB_shader_stencil_export", extStart, extEnd); +#endif /* GL_ARB_shader_stencil_export */ +#ifdef GL_ARB_shader_subroutine + CONST_CAST(GLEW_ARB_shader_subroutine) = _glewSearchExtension("GL_ARB_shader_subroutine", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shader_subroutine) CONST_CAST(GLEW_ARB_shader_subroutine) = !_glewInit_GL_ARB_shader_subroutine(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_shader_subroutine */ +#ifdef GL_ARB_shader_texture_lod + CONST_CAST(GLEW_ARB_shader_texture_lod) = _glewSearchExtension("GL_ARB_shader_texture_lod", extStart, extEnd); +#endif /* GL_ARB_shader_texture_lod */ +#ifdef GL_ARB_shading_language_100 + CONST_CAST(GLEW_ARB_shading_language_100) = _glewSearchExtension("GL_ARB_shading_language_100", extStart, extEnd); +#endif /* GL_ARB_shading_language_100 */ +#ifdef GL_ARB_shading_language_include + CONST_CAST(GLEW_ARB_shading_language_include) = _glewSearchExtension("GL_ARB_shading_language_include", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shading_language_include) CONST_CAST(GLEW_ARB_shading_language_include) = !_glewInit_GL_ARB_shading_language_include(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_shading_language_include */ +#ifdef GL_ARB_shadow + CONST_CAST(GLEW_ARB_shadow) = _glewSearchExtension("GL_ARB_shadow", extStart, extEnd); +#endif /* GL_ARB_shadow */ +#ifdef GL_ARB_shadow_ambient + CONST_CAST(GLEW_ARB_shadow_ambient) = _glewSearchExtension("GL_ARB_shadow_ambient", extStart, extEnd); +#endif /* GL_ARB_shadow_ambient */ +#ifdef GL_ARB_sync + CONST_CAST(GLEW_ARB_sync) = _glewSearchExtension("GL_ARB_sync", extStart, extEnd); + if (glewExperimental || GLEW_ARB_sync) CONST_CAST(GLEW_ARB_sync) = !_glewInit_GL_ARB_sync(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_sync */ +#ifdef GL_ARB_tessellation_shader + CONST_CAST(GLEW_ARB_tessellation_shader) = _glewSearchExtension("GL_ARB_tessellation_shader", extStart, extEnd); + if (glewExperimental || GLEW_ARB_tessellation_shader) CONST_CAST(GLEW_ARB_tessellation_shader) = !_glewInit_GL_ARB_tessellation_shader(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_tessellation_shader */ +#ifdef GL_ARB_texture_border_clamp + CONST_CAST(GLEW_ARB_texture_border_clamp) = _glewSearchExtension("GL_ARB_texture_border_clamp", extStart, extEnd); +#endif /* GL_ARB_texture_border_clamp */ +#ifdef GL_ARB_texture_buffer_object + CONST_CAST(GLEW_ARB_texture_buffer_object) = _glewSearchExtension("GL_ARB_texture_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_buffer_object) CONST_CAST(GLEW_ARB_texture_buffer_object) = !_glewInit_GL_ARB_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_texture_buffer_object */ +#ifdef GL_ARB_texture_buffer_object_rgb32 + CONST_CAST(GLEW_ARB_texture_buffer_object_rgb32) = _glewSearchExtension("GL_ARB_texture_buffer_object_rgb32", extStart, extEnd); +#endif /* GL_ARB_texture_buffer_object_rgb32 */ +#ifdef GL_ARB_texture_compression + CONST_CAST(GLEW_ARB_texture_compression) = _glewSearchExtension("GL_ARB_texture_compression", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_compression) CONST_CAST(GLEW_ARB_texture_compression) = !_glewInit_GL_ARB_texture_compression(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_texture_compression */ +#ifdef GL_ARB_texture_compression_bptc + CONST_CAST(GLEW_ARB_texture_compression_bptc) = _glewSearchExtension("GL_ARB_texture_compression_bptc", extStart, extEnd); +#endif /* GL_ARB_texture_compression_bptc */ +#ifdef GL_ARB_texture_compression_rgtc + CONST_CAST(GLEW_ARB_texture_compression_rgtc) = _glewSearchExtension("GL_ARB_texture_compression_rgtc", extStart, extEnd); +#endif /* GL_ARB_texture_compression_rgtc */ +#ifdef GL_ARB_texture_cube_map + CONST_CAST(GLEW_ARB_texture_cube_map) = _glewSearchExtension("GL_ARB_texture_cube_map", extStart, extEnd); +#endif /* GL_ARB_texture_cube_map */ +#ifdef GL_ARB_texture_cube_map_array + CONST_CAST(GLEW_ARB_texture_cube_map_array) = _glewSearchExtension("GL_ARB_texture_cube_map_array", extStart, extEnd); +#endif /* GL_ARB_texture_cube_map_array */ +#ifdef GL_ARB_texture_env_add + CONST_CAST(GLEW_ARB_texture_env_add) = _glewSearchExtension("GL_ARB_texture_env_add", extStart, extEnd); +#endif /* GL_ARB_texture_env_add */ +#ifdef GL_ARB_texture_env_combine + CONST_CAST(GLEW_ARB_texture_env_combine) = _glewSearchExtension("GL_ARB_texture_env_combine", extStart, extEnd); +#endif /* GL_ARB_texture_env_combine */ +#ifdef GL_ARB_texture_env_crossbar + CONST_CAST(GLEW_ARB_texture_env_crossbar) = _glewSearchExtension("GL_ARB_texture_env_crossbar", extStart, extEnd); +#endif /* GL_ARB_texture_env_crossbar */ +#ifdef GL_ARB_texture_env_dot3 + CONST_CAST(GLEW_ARB_texture_env_dot3) = _glewSearchExtension("GL_ARB_texture_env_dot3", extStart, extEnd); +#endif /* GL_ARB_texture_env_dot3 */ +#ifdef GL_ARB_texture_float + CONST_CAST(GLEW_ARB_texture_float) = _glewSearchExtension("GL_ARB_texture_float", extStart, extEnd); +#endif /* GL_ARB_texture_float */ +#ifdef GL_ARB_texture_gather + CONST_CAST(GLEW_ARB_texture_gather) = _glewSearchExtension("GL_ARB_texture_gather", extStart, extEnd); +#endif /* GL_ARB_texture_gather */ +#ifdef GL_ARB_texture_mirrored_repeat + CONST_CAST(GLEW_ARB_texture_mirrored_repeat) = _glewSearchExtension("GL_ARB_texture_mirrored_repeat", extStart, extEnd); +#endif /* GL_ARB_texture_mirrored_repeat */ +#ifdef GL_ARB_texture_multisample + CONST_CAST(GLEW_ARB_texture_multisample) = _glewSearchExtension("GL_ARB_texture_multisample", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_multisample) CONST_CAST(GLEW_ARB_texture_multisample) = !_glewInit_GL_ARB_texture_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_texture_multisample */ +#ifdef GL_ARB_texture_non_power_of_two + CONST_CAST(GLEW_ARB_texture_non_power_of_two) = _glewSearchExtension("GL_ARB_texture_non_power_of_two", extStart, extEnd); +#endif /* GL_ARB_texture_non_power_of_two */ +#ifdef GL_ARB_texture_query_lod + CONST_CAST(GLEW_ARB_texture_query_lod) = _glewSearchExtension("GL_ARB_texture_query_lod", extStart, extEnd); +#endif /* GL_ARB_texture_query_lod */ +#ifdef GL_ARB_texture_rectangle + CONST_CAST(GLEW_ARB_texture_rectangle) = _glewSearchExtension("GL_ARB_texture_rectangle", extStart, extEnd); +#endif /* GL_ARB_texture_rectangle */ +#ifdef GL_ARB_texture_rg + CONST_CAST(GLEW_ARB_texture_rg) = _glewSearchExtension("GL_ARB_texture_rg", extStart, extEnd); +#endif /* GL_ARB_texture_rg */ +#ifdef GL_ARB_texture_rgb10_a2ui + CONST_CAST(GLEW_ARB_texture_rgb10_a2ui) = _glewSearchExtension("GL_ARB_texture_rgb10_a2ui", extStart, extEnd); +#endif /* GL_ARB_texture_rgb10_a2ui */ +#ifdef GL_ARB_texture_swizzle + CONST_CAST(GLEW_ARB_texture_swizzle) = _glewSearchExtension("GL_ARB_texture_swizzle", extStart, extEnd); +#endif /* GL_ARB_texture_swizzle */ +#ifdef GL_ARB_timer_query + CONST_CAST(GLEW_ARB_timer_query) = _glewSearchExtension("GL_ARB_timer_query", extStart, extEnd); + if (glewExperimental || GLEW_ARB_timer_query) CONST_CAST(GLEW_ARB_timer_query) = !_glewInit_GL_ARB_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_timer_query */ +#ifdef GL_ARB_transform_feedback2 + CONST_CAST(GLEW_ARB_transform_feedback2) = _glewSearchExtension("GL_ARB_transform_feedback2", extStart, extEnd); + if (glewExperimental || GLEW_ARB_transform_feedback2) CONST_CAST(GLEW_ARB_transform_feedback2) = !_glewInit_GL_ARB_transform_feedback2(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_transform_feedback2 */ +#ifdef GL_ARB_transform_feedback3 + CONST_CAST(GLEW_ARB_transform_feedback3) = _glewSearchExtension("GL_ARB_transform_feedback3", extStart, extEnd); + if (glewExperimental || GLEW_ARB_transform_feedback3) CONST_CAST(GLEW_ARB_transform_feedback3) = !_glewInit_GL_ARB_transform_feedback3(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_transform_feedback3 */ +#ifdef GL_ARB_transpose_matrix + CONST_CAST(GLEW_ARB_transpose_matrix) = _glewSearchExtension("GL_ARB_transpose_matrix", extStart, extEnd); + if (glewExperimental || GLEW_ARB_transpose_matrix) CONST_CAST(GLEW_ARB_transpose_matrix) = !_glewInit_GL_ARB_transpose_matrix(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_transpose_matrix */ +#ifdef GL_ARB_uniform_buffer_object + CONST_CAST(GLEW_ARB_uniform_buffer_object) = _glewSearchExtension("GL_ARB_uniform_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_uniform_buffer_object) CONST_CAST(GLEW_ARB_uniform_buffer_object) = !_glewInit_GL_ARB_uniform_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_uniform_buffer_object */ +#ifdef GL_ARB_vertex_array_bgra + CONST_CAST(GLEW_ARB_vertex_array_bgra) = _glewSearchExtension("GL_ARB_vertex_array_bgra", extStart, extEnd); +#endif /* GL_ARB_vertex_array_bgra */ +#ifdef GL_ARB_vertex_array_object + CONST_CAST(GLEW_ARB_vertex_array_object) = _glewSearchExtension("GL_ARB_vertex_array_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_array_object) CONST_CAST(GLEW_ARB_vertex_array_object) = !_glewInit_GL_ARB_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_array_object */ +#ifdef GL_ARB_vertex_attrib_64bit + CONST_CAST(GLEW_ARB_vertex_attrib_64bit) = _glewSearchExtension("GL_ARB_vertex_attrib_64bit", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_attrib_64bit) CONST_CAST(GLEW_ARB_vertex_attrib_64bit) = !_glewInit_GL_ARB_vertex_attrib_64bit(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_attrib_64bit */ +#ifdef GL_ARB_vertex_blend + CONST_CAST(GLEW_ARB_vertex_blend) = _glewSearchExtension("GL_ARB_vertex_blend", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_blend) CONST_CAST(GLEW_ARB_vertex_blend) = !_glewInit_GL_ARB_vertex_blend(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_blend */ +#ifdef GL_ARB_vertex_buffer_object + CONST_CAST(GLEW_ARB_vertex_buffer_object) = _glewSearchExtension("GL_ARB_vertex_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_buffer_object) CONST_CAST(GLEW_ARB_vertex_buffer_object) = !_glewInit_GL_ARB_vertex_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_buffer_object */ +#ifdef GL_ARB_vertex_program + CONST_CAST(GLEW_ARB_vertex_program) = _glewSearchExtension("GL_ARB_vertex_program", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_program) CONST_CAST(GLEW_ARB_vertex_program) = !_glewInit_GL_ARB_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_program */ +#ifdef GL_ARB_vertex_shader + CONST_CAST(GLEW_ARB_vertex_shader) = _glewSearchExtension("GL_ARB_vertex_shader", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_shader) CONST_CAST(GLEW_ARB_vertex_shader) = !_glewInit_GL_ARB_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_shader */ +#ifdef GL_ARB_vertex_type_2_10_10_10_rev + CONST_CAST(GLEW_ARB_vertex_type_2_10_10_10_rev) = _glewSearchExtension("GL_ARB_vertex_type_2_10_10_10_rev", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_type_2_10_10_10_rev) CONST_CAST(GLEW_ARB_vertex_type_2_10_10_10_rev) = !_glewInit_GL_ARB_vertex_type_2_10_10_10_rev(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_type_2_10_10_10_rev */ +#ifdef GL_ARB_viewport_array + CONST_CAST(GLEW_ARB_viewport_array) = _glewSearchExtension("GL_ARB_viewport_array", extStart, extEnd); + if (glewExperimental || GLEW_ARB_viewport_array) CONST_CAST(GLEW_ARB_viewport_array) = !_glewInit_GL_ARB_viewport_array(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_viewport_array */ +#ifdef GL_ARB_window_pos + CONST_CAST(GLEW_ARB_window_pos) = _glewSearchExtension("GL_ARB_window_pos", extStart, extEnd); + if (glewExperimental || GLEW_ARB_window_pos) CONST_CAST(GLEW_ARB_window_pos) = !_glewInit_GL_ARB_window_pos(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_window_pos */ +#ifdef GL_ATIX_point_sprites + CONST_CAST(GLEW_ATIX_point_sprites) = _glewSearchExtension("GL_ATIX_point_sprites", extStart, extEnd); +#endif /* GL_ATIX_point_sprites */ +#ifdef GL_ATIX_texture_env_combine3 + CONST_CAST(GLEW_ATIX_texture_env_combine3) = _glewSearchExtension("GL_ATIX_texture_env_combine3", extStart, extEnd); +#endif /* GL_ATIX_texture_env_combine3 */ +#ifdef GL_ATIX_texture_env_route + CONST_CAST(GLEW_ATIX_texture_env_route) = _glewSearchExtension("GL_ATIX_texture_env_route", extStart, extEnd); +#endif /* GL_ATIX_texture_env_route */ +#ifdef GL_ATIX_vertex_shader_output_point_size + CONST_CAST(GLEW_ATIX_vertex_shader_output_point_size) = _glewSearchExtension("GL_ATIX_vertex_shader_output_point_size", extStart, extEnd); +#endif /* GL_ATIX_vertex_shader_output_point_size */ +#ifdef GL_ATI_draw_buffers + CONST_CAST(GLEW_ATI_draw_buffers) = _glewSearchExtension("GL_ATI_draw_buffers", extStart, extEnd); + if (glewExperimental || GLEW_ATI_draw_buffers) CONST_CAST(GLEW_ATI_draw_buffers) = !_glewInit_GL_ATI_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_draw_buffers */ +#ifdef GL_ATI_element_array + CONST_CAST(GLEW_ATI_element_array) = _glewSearchExtension("GL_ATI_element_array", extStart, extEnd); + if (glewExperimental || GLEW_ATI_element_array) CONST_CAST(GLEW_ATI_element_array) = !_glewInit_GL_ATI_element_array(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_element_array */ +#ifdef GL_ATI_envmap_bumpmap + CONST_CAST(GLEW_ATI_envmap_bumpmap) = _glewSearchExtension("GL_ATI_envmap_bumpmap", extStart, extEnd); + if (glewExperimental || GLEW_ATI_envmap_bumpmap) CONST_CAST(GLEW_ATI_envmap_bumpmap) = !_glewInit_GL_ATI_envmap_bumpmap(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_envmap_bumpmap */ +#ifdef GL_ATI_fragment_shader + CONST_CAST(GLEW_ATI_fragment_shader) = _glewSearchExtension("GL_ATI_fragment_shader", extStart, extEnd); + if (glewExperimental || GLEW_ATI_fragment_shader) CONST_CAST(GLEW_ATI_fragment_shader) = !_glewInit_GL_ATI_fragment_shader(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_fragment_shader */ +#ifdef GL_ATI_map_object_buffer + CONST_CAST(GLEW_ATI_map_object_buffer) = _glewSearchExtension("GL_ATI_map_object_buffer", extStart, extEnd); + if (glewExperimental || GLEW_ATI_map_object_buffer) CONST_CAST(GLEW_ATI_map_object_buffer) = !_glewInit_GL_ATI_map_object_buffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_map_object_buffer */ +#ifdef GL_ATI_meminfo + CONST_CAST(GLEW_ATI_meminfo) = _glewSearchExtension("GL_ATI_meminfo", extStart, extEnd); +#endif /* GL_ATI_meminfo */ +#ifdef GL_ATI_pn_triangles + CONST_CAST(GLEW_ATI_pn_triangles) = _glewSearchExtension("GL_ATI_pn_triangles", extStart, extEnd); + if (glewExperimental || GLEW_ATI_pn_triangles) CONST_CAST(GLEW_ATI_pn_triangles) = !_glewInit_GL_ATI_pn_triangles(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_pn_triangles */ +#ifdef GL_ATI_separate_stencil + CONST_CAST(GLEW_ATI_separate_stencil) = _glewSearchExtension("GL_ATI_separate_stencil", extStart, extEnd); + if (glewExperimental || GLEW_ATI_separate_stencil) CONST_CAST(GLEW_ATI_separate_stencil) = !_glewInit_GL_ATI_separate_stencil(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_separate_stencil */ +#ifdef GL_ATI_shader_texture_lod + CONST_CAST(GLEW_ATI_shader_texture_lod) = _glewSearchExtension("GL_ATI_shader_texture_lod", extStart, extEnd); +#endif /* GL_ATI_shader_texture_lod */ +#ifdef GL_ATI_text_fragment_shader + CONST_CAST(GLEW_ATI_text_fragment_shader) = _glewSearchExtension("GL_ATI_text_fragment_shader", extStart, extEnd); +#endif /* GL_ATI_text_fragment_shader */ +#ifdef GL_ATI_texture_compression_3dc + CONST_CAST(GLEW_ATI_texture_compression_3dc) = _glewSearchExtension("GL_ATI_texture_compression_3dc", extStart, extEnd); +#endif /* GL_ATI_texture_compression_3dc */ +#ifdef GL_ATI_texture_env_combine3 + CONST_CAST(GLEW_ATI_texture_env_combine3) = _glewSearchExtension("GL_ATI_texture_env_combine3", extStart, extEnd); +#endif /* GL_ATI_texture_env_combine3 */ +#ifdef GL_ATI_texture_float + CONST_CAST(GLEW_ATI_texture_float) = _glewSearchExtension("GL_ATI_texture_float", extStart, extEnd); +#endif /* GL_ATI_texture_float */ +#ifdef GL_ATI_texture_mirror_once + CONST_CAST(GLEW_ATI_texture_mirror_once) = _glewSearchExtension("GL_ATI_texture_mirror_once", extStart, extEnd); +#endif /* GL_ATI_texture_mirror_once */ +#ifdef GL_ATI_vertex_array_object + CONST_CAST(GLEW_ATI_vertex_array_object) = _glewSearchExtension("GL_ATI_vertex_array_object", extStart, extEnd); + if (glewExperimental || GLEW_ATI_vertex_array_object) CONST_CAST(GLEW_ATI_vertex_array_object) = !_glewInit_GL_ATI_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_vertex_array_object */ +#ifdef GL_ATI_vertex_attrib_array_object + CONST_CAST(GLEW_ATI_vertex_attrib_array_object) = _glewSearchExtension("GL_ATI_vertex_attrib_array_object", extStart, extEnd); + if (glewExperimental || GLEW_ATI_vertex_attrib_array_object) CONST_CAST(GLEW_ATI_vertex_attrib_array_object) = !_glewInit_GL_ATI_vertex_attrib_array_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_vertex_attrib_array_object */ +#ifdef GL_ATI_vertex_streams + CONST_CAST(GLEW_ATI_vertex_streams) = _glewSearchExtension("GL_ATI_vertex_streams", extStart, extEnd); + if (glewExperimental || GLEW_ATI_vertex_streams) CONST_CAST(GLEW_ATI_vertex_streams) = !_glewInit_GL_ATI_vertex_streams(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ATI_vertex_streams */ +#ifdef GL_EXT_422_pixels + CONST_CAST(GLEW_EXT_422_pixels) = _glewSearchExtension("GL_EXT_422_pixels", extStart, extEnd); +#endif /* GL_EXT_422_pixels */ +#ifdef GL_EXT_Cg_shader + CONST_CAST(GLEW_EXT_Cg_shader) = _glewSearchExtension("GL_EXT_Cg_shader", extStart, extEnd); +#endif /* GL_EXT_Cg_shader */ +#ifdef GL_EXT_abgr + CONST_CAST(GLEW_EXT_abgr) = _glewSearchExtension("GL_EXT_abgr", extStart, extEnd); +#endif /* GL_EXT_abgr */ +#ifdef GL_EXT_bgra + CONST_CAST(GLEW_EXT_bgra) = _glewSearchExtension("GL_EXT_bgra", extStart, extEnd); +#endif /* GL_EXT_bgra */ +#ifdef GL_EXT_bindable_uniform + CONST_CAST(GLEW_EXT_bindable_uniform) = _glewSearchExtension("GL_EXT_bindable_uniform", extStart, extEnd); + if (glewExperimental || GLEW_EXT_bindable_uniform) CONST_CAST(GLEW_EXT_bindable_uniform) = !_glewInit_GL_EXT_bindable_uniform(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_bindable_uniform */ +#ifdef GL_EXT_blend_color + CONST_CAST(GLEW_EXT_blend_color) = _glewSearchExtension("GL_EXT_blend_color", extStart, extEnd); + if (glewExperimental || GLEW_EXT_blend_color) CONST_CAST(GLEW_EXT_blend_color) = !_glewInit_GL_EXT_blend_color(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_blend_color */ +#ifdef GL_EXT_blend_equation_separate + CONST_CAST(GLEW_EXT_blend_equation_separate) = _glewSearchExtension("GL_EXT_blend_equation_separate", extStart, extEnd); + if (glewExperimental || GLEW_EXT_blend_equation_separate) CONST_CAST(GLEW_EXT_blend_equation_separate) = !_glewInit_GL_EXT_blend_equation_separate(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_blend_equation_separate */ +#ifdef GL_EXT_blend_func_separate + CONST_CAST(GLEW_EXT_blend_func_separate) = _glewSearchExtension("GL_EXT_blend_func_separate", extStart, extEnd); + if (glewExperimental || GLEW_EXT_blend_func_separate) CONST_CAST(GLEW_EXT_blend_func_separate) = !_glewInit_GL_EXT_blend_func_separate(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_blend_func_separate */ +#ifdef GL_EXT_blend_logic_op + CONST_CAST(GLEW_EXT_blend_logic_op) = _glewSearchExtension("GL_EXT_blend_logic_op", extStart, extEnd); +#endif /* GL_EXT_blend_logic_op */ +#ifdef GL_EXT_blend_minmax + CONST_CAST(GLEW_EXT_blend_minmax) = _glewSearchExtension("GL_EXT_blend_minmax", extStart, extEnd); + if (glewExperimental || GLEW_EXT_blend_minmax) CONST_CAST(GLEW_EXT_blend_minmax) = !_glewInit_GL_EXT_blend_minmax(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_blend_minmax */ +#ifdef GL_EXT_blend_subtract + CONST_CAST(GLEW_EXT_blend_subtract) = _glewSearchExtension("GL_EXT_blend_subtract", extStart, extEnd); +#endif /* GL_EXT_blend_subtract */ +#ifdef GL_EXT_clip_volume_hint + CONST_CAST(GLEW_EXT_clip_volume_hint) = _glewSearchExtension("GL_EXT_clip_volume_hint", extStart, extEnd); +#endif /* GL_EXT_clip_volume_hint */ +#ifdef GL_EXT_cmyka + CONST_CAST(GLEW_EXT_cmyka) = _glewSearchExtension("GL_EXT_cmyka", extStart, extEnd); +#endif /* GL_EXT_cmyka */ +#ifdef GL_EXT_color_subtable + CONST_CAST(GLEW_EXT_color_subtable) = _glewSearchExtension("GL_EXT_color_subtable", extStart, extEnd); + if (glewExperimental || GLEW_EXT_color_subtable) CONST_CAST(GLEW_EXT_color_subtable) = !_glewInit_GL_EXT_color_subtable(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_color_subtable */ +#ifdef GL_EXT_compiled_vertex_array + CONST_CAST(GLEW_EXT_compiled_vertex_array) = _glewSearchExtension("GL_EXT_compiled_vertex_array", extStart, extEnd); + if (glewExperimental || GLEW_EXT_compiled_vertex_array) CONST_CAST(GLEW_EXT_compiled_vertex_array) = !_glewInit_GL_EXT_compiled_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_compiled_vertex_array */ +#ifdef GL_EXT_convolution + CONST_CAST(GLEW_EXT_convolution) = _glewSearchExtension("GL_EXT_convolution", extStart, extEnd); + if (glewExperimental || GLEW_EXT_convolution) CONST_CAST(GLEW_EXT_convolution) = !_glewInit_GL_EXT_convolution(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_convolution */ +#ifdef GL_EXT_coordinate_frame + CONST_CAST(GLEW_EXT_coordinate_frame) = _glewSearchExtension("GL_EXT_coordinate_frame", extStart, extEnd); + if (glewExperimental || GLEW_EXT_coordinate_frame) CONST_CAST(GLEW_EXT_coordinate_frame) = !_glewInit_GL_EXT_coordinate_frame(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_coordinate_frame */ +#ifdef GL_EXT_copy_texture + CONST_CAST(GLEW_EXT_copy_texture) = _glewSearchExtension("GL_EXT_copy_texture", extStart, extEnd); + if (glewExperimental || GLEW_EXT_copy_texture) CONST_CAST(GLEW_EXT_copy_texture) = !_glewInit_GL_EXT_copy_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_copy_texture */ +#ifdef GL_EXT_cull_vertex + CONST_CAST(GLEW_EXT_cull_vertex) = _glewSearchExtension("GL_EXT_cull_vertex", extStart, extEnd); + if (glewExperimental || GLEW_EXT_cull_vertex) CONST_CAST(GLEW_EXT_cull_vertex) = !_glewInit_GL_EXT_cull_vertex(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_cull_vertex */ +#ifdef GL_EXT_depth_bounds_test + CONST_CAST(GLEW_EXT_depth_bounds_test) = _glewSearchExtension("GL_EXT_depth_bounds_test", extStart, extEnd); + if (glewExperimental || GLEW_EXT_depth_bounds_test) CONST_CAST(GLEW_EXT_depth_bounds_test) = !_glewInit_GL_EXT_depth_bounds_test(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_depth_bounds_test */ +#ifdef GL_EXT_direct_state_access + CONST_CAST(GLEW_EXT_direct_state_access) = _glewSearchExtension("GL_EXT_direct_state_access", extStart, extEnd); + if (glewExperimental || GLEW_EXT_direct_state_access) CONST_CAST(GLEW_EXT_direct_state_access) = !_glewInit_GL_EXT_direct_state_access(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_direct_state_access */ +#ifdef GL_EXT_draw_buffers2 + CONST_CAST(GLEW_EXT_draw_buffers2) = _glewSearchExtension("GL_EXT_draw_buffers2", extStart, extEnd); + if (glewExperimental || GLEW_EXT_draw_buffers2) CONST_CAST(GLEW_EXT_draw_buffers2) = !_glewInit_GL_EXT_draw_buffers2(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_draw_buffers2 */ +#ifdef GL_EXT_draw_instanced + CONST_CAST(GLEW_EXT_draw_instanced) = _glewSearchExtension("GL_EXT_draw_instanced", extStart, extEnd); + if (glewExperimental || GLEW_EXT_draw_instanced) CONST_CAST(GLEW_EXT_draw_instanced) = !_glewInit_GL_EXT_draw_instanced(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_draw_instanced */ +#ifdef GL_EXT_draw_range_elements + CONST_CAST(GLEW_EXT_draw_range_elements) = _glewSearchExtension("GL_EXT_draw_range_elements", extStart, extEnd); + if (glewExperimental || GLEW_EXT_draw_range_elements) CONST_CAST(GLEW_EXT_draw_range_elements) = !_glewInit_GL_EXT_draw_range_elements(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_draw_range_elements */ +#ifdef GL_EXT_fog_coord + CONST_CAST(GLEW_EXT_fog_coord) = _glewSearchExtension("GL_EXT_fog_coord", extStart, extEnd); + if (glewExperimental || GLEW_EXT_fog_coord) CONST_CAST(GLEW_EXT_fog_coord) = !_glewInit_GL_EXT_fog_coord(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_fog_coord */ +#ifdef GL_EXT_fragment_lighting + CONST_CAST(GLEW_EXT_fragment_lighting) = _glewSearchExtension("GL_EXT_fragment_lighting", extStart, extEnd); + if (glewExperimental || GLEW_EXT_fragment_lighting) CONST_CAST(GLEW_EXT_fragment_lighting) = !_glewInit_GL_EXT_fragment_lighting(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_fragment_lighting */ +#ifdef GL_EXT_framebuffer_blit + CONST_CAST(GLEW_EXT_framebuffer_blit) = _glewSearchExtension("GL_EXT_framebuffer_blit", extStart, extEnd); + if (glewExperimental || GLEW_EXT_framebuffer_blit) CONST_CAST(GLEW_EXT_framebuffer_blit) = !_glewInit_GL_EXT_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_framebuffer_blit */ +#ifdef GL_EXT_framebuffer_multisample + CONST_CAST(GLEW_EXT_framebuffer_multisample) = _glewSearchExtension("GL_EXT_framebuffer_multisample", extStart, extEnd); + if (glewExperimental || GLEW_EXT_framebuffer_multisample) CONST_CAST(GLEW_EXT_framebuffer_multisample) = !_glewInit_GL_EXT_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_framebuffer_multisample */ +#ifdef GL_EXT_framebuffer_object + CONST_CAST(GLEW_EXT_framebuffer_object) = _glewSearchExtension("GL_EXT_framebuffer_object", extStart, extEnd); + if (glewExperimental || GLEW_EXT_framebuffer_object) CONST_CAST(GLEW_EXT_framebuffer_object) = !_glewInit_GL_EXT_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_framebuffer_object */ +#ifdef GL_EXT_framebuffer_sRGB + CONST_CAST(GLEW_EXT_framebuffer_sRGB) = _glewSearchExtension("GL_EXT_framebuffer_sRGB", extStart, extEnd); +#endif /* GL_EXT_framebuffer_sRGB */ +#ifdef GL_EXT_geometry_shader4 + CONST_CAST(GLEW_EXT_geometry_shader4) = _glewSearchExtension("GL_EXT_geometry_shader4", extStart, extEnd); + if (glewExperimental || GLEW_EXT_geometry_shader4) CONST_CAST(GLEW_EXT_geometry_shader4) = !_glewInit_GL_EXT_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_geometry_shader4 */ +#ifdef GL_EXT_gpu_program_parameters + CONST_CAST(GLEW_EXT_gpu_program_parameters) = _glewSearchExtension("GL_EXT_gpu_program_parameters", extStart, extEnd); + if (glewExperimental || GLEW_EXT_gpu_program_parameters) CONST_CAST(GLEW_EXT_gpu_program_parameters) = !_glewInit_GL_EXT_gpu_program_parameters(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_gpu_program_parameters */ +#ifdef GL_EXT_gpu_shader4 + CONST_CAST(GLEW_EXT_gpu_shader4) = _glewSearchExtension("GL_EXT_gpu_shader4", extStart, extEnd); + if (glewExperimental || GLEW_EXT_gpu_shader4) CONST_CAST(GLEW_EXT_gpu_shader4) = !_glewInit_GL_EXT_gpu_shader4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_gpu_shader4 */ +#ifdef GL_EXT_histogram + CONST_CAST(GLEW_EXT_histogram) = _glewSearchExtension("GL_EXT_histogram", extStart, extEnd); + if (glewExperimental || GLEW_EXT_histogram) CONST_CAST(GLEW_EXT_histogram) = !_glewInit_GL_EXT_histogram(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_histogram */ +#ifdef GL_EXT_index_array_formats + CONST_CAST(GLEW_EXT_index_array_formats) = _glewSearchExtension("GL_EXT_index_array_formats", extStart, extEnd); +#endif /* GL_EXT_index_array_formats */ +#ifdef GL_EXT_index_func + CONST_CAST(GLEW_EXT_index_func) = _glewSearchExtension("GL_EXT_index_func", extStart, extEnd); + if (glewExperimental || GLEW_EXT_index_func) CONST_CAST(GLEW_EXT_index_func) = !_glewInit_GL_EXT_index_func(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_index_func */ +#ifdef GL_EXT_index_material + CONST_CAST(GLEW_EXT_index_material) = _glewSearchExtension("GL_EXT_index_material", extStart, extEnd); + if (glewExperimental || GLEW_EXT_index_material) CONST_CAST(GLEW_EXT_index_material) = !_glewInit_GL_EXT_index_material(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_index_material */ +#ifdef GL_EXT_index_texture + CONST_CAST(GLEW_EXT_index_texture) = _glewSearchExtension("GL_EXT_index_texture", extStart, extEnd); +#endif /* GL_EXT_index_texture */ +#ifdef GL_EXT_light_texture + CONST_CAST(GLEW_EXT_light_texture) = _glewSearchExtension("GL_EXT_light_texture", extStart, extEnd); + if (glewExperimental || GLEW_EXT_light_texture) CONST_CAST(GLEW_EXT_light_texture) = !_glewInit_GL_EXT_light_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_light_texture */ +#ifdef GL_EXT_misc_attribute + CONST_CAST(GLEW_EXT_misc_attribute) = _glewSearchExtension("GL_EXT_misc_attribute", extStart, extEnd); +#endif /* GL_EXT_misc_attribute */ +#ifdef GL_EXT_multi_draw_arrays + CONST_CAST(GLEW_EXT_multi_draw_arrays) = _glewSearchExtension("GL_EXT_multi_draw_arrays", extStart, extEnd); + if (glewExperimental || GLEW_EXT_multi_draw_arrays) CONST_CAST(GLEW_EXT_multi_draw_arrays) = !_glewInit_GL_EXT_multi_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_multi_draw_arrays */ +#ifdef GL_EXT_multisample + CONST_CAST(GLEW_EXT_multisample) = _glewSearchExtension("GL_EXT_multisample", extStart, extEnd); + if (glewExperimental || GLEW_EXT_multisample) CONST_CAST(GLEW_EXT_multisample) = !_glewInit_GL_EXT_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_multisample */ +#ifdef GL_EXT_packed_depth_stencil + CONST_CAST(GLEW_EXT_packed_depth_stencil) = _glewSearchExtension("GL_EXT_packed_depth_stencil", extStart, extEnd); +#endif /* GL_EXT_packed_depth_stencil */ +#ifdef GL_EXT_packed_float + CONST_CAST(GLEW_EXT_packed_float) = _glewSearchExtension("GL_EXT_packed_float", extStart, extEnd); +#endif /* GL_EXT_packed_float */ +#ifdef GL_EXT_packed_pixels + CONST_CAST(GLEW_EXT_packed_pixels) = _glewSearchExtension("GL_EXT_packed_pixels", extStart, extEnd); +#endif /* GL_EXT_packed_pixels */ +#ifdef GL_EXT_paletted_texture + CONST_CAST(GLEW_EXT_paletted_texture) = _glewSearchExtension("GL_EXT_paletted_texture", extStart, extEnd); + if (glewExperimental || GLEW_EXT_paletted_texture) CONST_CAST(GLEW_EXT_paletted_texture) = !_glewInit_GL_EXT_paletted_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_paletted_texture */ +#ifdef GL_EXT_pixel_buffer_object + CONST_CAST(GLEW_EXT_pixel_buffer_object) = _glewSearchExtension("GL_EXT_pixel_buffer_object", extStart, extEnd); +#endif /* GL_EXT_pixel_buffer_object */ +#ifdef GL_EXT_pixel_transform + CONST_CAST(GLEW_EXT_pixel_transform) = _glewSearchExtension("GL_EXT_pixel_transform", extStart, extEnd); + if (glewExperimental || GLEW_EXT_pixel_transform) CONST_CAST(GLEW_EXT_pixel_transform) = !_glewInit_GL_EXT_pixel_transform(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_pixel_transform */ +#ifdef GL_EXT_pixel_transform_color_table + CONST_CAST(GLEW_EXT_pixel_transform_color_table) = _glewSearchExtension("GL_EXT_pixel_transform_color_table", extStart, extEnd); +#endif /* GL_EXT_pixel_transform_color_table */ +#ifdef GL_EXT_point_parameters + CONST_CAST(GLEW_EXT_point_parameters) = _glewSearchExtension("GL_EXT_point_parameters", extStart, extEnd); + if (glewExperimental || GLEW_EXT_point_parameters) CONST_CAST(GLEW_EXT_point_parameters) = !_glewInit_GL_EXT_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_point_parameters */ +#ifdef GL_EXT_polygon_offset + CONST_CAST(GLEW_EXT_polygon_offset) = _glewSearchExtension("GL_EXT_polygon_offset", extStart, extEnd); + if (glewExperimental || GLEW_EXT_polygon_offset) CONST_CAST(GLEW_EXT_polygon_offset) = !_glewInit_GL_EXT_polygon_offset(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_polygon_offset */ +#ifdef GL_EXT_provoking_vertex + CONST_CAST(GLEW_EXT_provoking_vertex) = _glewSearchExtension("GL_EXT_provoking_vertex", extStart, extEnd); + if (glewExperimental || GLEW_EXT_provoking_vertex) CONST_CAST(GLEW_EXT_provoking_vertex) = !_glewInit_GL_EXT_provoking_vertex(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_provoking_vertex */ +#ifdef GL_EXT_rescale_normal + CONST_CAST(GLEW_EXT_rescale_normal) = _glewSearchExtension("GL_EXT_rescale_normal", extStart, extEnd); +#endif /* GL_EXT_rescale_normal */ +#ifdef GL_EXT_scene_marker + CONST_CAST(GLEW_EXT_scene_marker) = _glewSearchExtension("GL_EXT_scene_marker", extStart, extEnd); + if (glewExperimental || GLEW_EXT_scene_marker) CONST_CAST(GLEW_EXT_scene_marker) = !_glewInit_GL_EXT_scene_marker(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_scene_marker */ +#ifdef GL_EXT_secondary_color + CONST_CAST(GLEW_EXT_secondary_color) = _glewSearchExtension("GL_EXT_secondary_color", extStart, extEnd); + if (glewExperimental || GLEW_EXT_secondary_color) CONST_CAST(GLEW_EXT_secondary_color) = !_glewInit_GL_EXT_secondary_color(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_secondary_color */ +#ifdef GL_EXT_separate_shader_objects + CONST_CAST(GLEW_EXT_separate_shader_objects) = _glewSearchExtension("GL_EXT_separate_shader_objects", extStart, extEnd); + if (glewExperimental || GLEW_EXT_separate_shader_objects) CONST_CAST(GLEW_EXT_separate_shader_objects) = !_glewInit_GL_EXT_separate_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_separate_shader_objects */ +#ifdef GL_EXT_separate_specular_color + CONST_CAST(GLEW_EXT_separate_specular_color) = _glewSearchExtension("GL_EXT_separate_specular_color", extStart, extEnd); +#endif /* GL_EXT_separate_specular_color */ +#ifdef GL_EXT_shader_image_load_store + CONST_CAST(GLEW_EXT_shader_image_load_store) = _glewSearchExtension("GL_EXT_shader_image_load_store", extStart, extEnd); + if (glewExperimental || GLEW_EXT_shader_image_load_store) CONST_CAST(GLEW_EXT_shader_image_load_store) = !_glewInit_GL_EXT_shader_image_load_store(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_shader_image_load_store */ +#ifdef GL_EXT_shadow_funcs + CONST_CAST(GLEW_EXT_shadow_funcs) = _glewSearchExtension("GL_EXT_shadow_funcs", extStart, extEnd); +#endif /* GL_EXT_shadow_funcs */ +#ifdef GL_EXT_shared_texture_palette + CONST_CAST(GLEW_EXT_shared_texture_palette) = _glewSearchExtension("GL_EXT_shared_texture_palette", extStart, extEnd); +#endif /* GL_EXT_shared_texture_palette */ +#ifdef GL_EXT_stencil_clear_tag + CONST_CAST(GLEW_EXT_stencil_clear_tag) = _glewSearchExtension("GL_EXT_stencil_clear_tag", extStart, extEnd); +#endif /* GL_EXT_stencil_clear_tag */ +#ifdef GL_EXT_stencil_two_side + CONST_CAST(GLEW_EXT_stencil_two_side) = _glewSearchExtension("GL_EXT_stencil_two_side", extStart, extEnd); + if (glewExperimental || GLEW_EXT_stencil_two_side) CONST_CAST(GLEW_EXT_stencil_two_side) = !_glewInit_GL_EXT_stencil_two_side(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_stencil_two_side */ +#ifdef GL_EXT_stencil_wrap + CONST_CAST(GLEW_EXT_stencil_wrap) = _glewSearchExtension("GL_EXT_stencil_wrap", extStart, extEnd); +#endif /* GL_EXT_stencil_wrap */ +#ifdef GL_EXT_subtexture + CONST_CAST(GLEW_EXT_subtexture) = _glewSearchExtension("GL_EXT_subtexture", extStart, extEnd); + if (glewExperimental || GLEW_EXT_subtexture) CONST_CAST(GLEW_EXT_subtexture) = !_glewInit_GL_EXT_subtexture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_subtexture */ +#ifdef GL_EXT_texture + CONST_CAST(GLEW_EXT_texture) = _glewSearchExtension("GL_EXT_texture", extStart, extEnd); +#endif /* GL_EXT_texture */ +#ifdef GL_EXT_texture3D + CONST_CAST(GLEW_EXT_texture3D) = _glewSearchExtension("GL_EXT_texture3D", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture3D) CONST_CAST(GLEW_EXT_texture3D) = !_glewInit_GL_EXT_texture3D(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture3D */ +#ifdef GL_EXT_texture_array + CONST_CAST(GLEW_EXT_texture_array) = _glewSearchExtension("GL_EXT_texture_array", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture_array) CONST_CAST(GLEW_EXT_texture_array) = !_glewInit_GL_EXT_texture_array(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture_array */ +#ifdef GL_EXT_texture_buffer_object + CONST_CAST(GLEW_EXT_texture_buffer_object) = _glewSearchExtension("GL_EXT_texture_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture_buffer_object) CONST_CAST(GLEW_EXT_texture_buffer_object) = !_glewInit_GL_EXT_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture_buffer_object */ +#ifdef GL_EXT_texture_compression_dxt1 + CONST_CAST(GLEW_EXT_texture_compression_dxt1) = _glewSearchExtension("GL_EXT_texture_compression_dxt1", extStart, extEnd); +#endif /* GL_EXT_texture_compression_dxt1 */ +#ifdef GL_EXT_texture_compression_latc + CONST_CAST(GLEW_EXT_texture_compression_latc) = _glewSearchExtension("GL_EXT_texture_compression_latc", extStart, extEnd); +#endif /* GL_EXT_texture_compression_latc */ +#ifdef GL_EXT_texture_compression_rgtc + CONST_CAST(GLEW_EXT_texture_compression_rgtc) = _glewSearchExtension("GL_EXT_texture_compression_rgtc", extStart, extEnd); +#endif /* GL_EXT_texture_compression_rgtc */ +#ifdef GL_EXT_texture_compression_s3tc + CONST_CAST(GLEW_EXT_texture_compression_s3tc) = _glewSearchExtension("GL_EXT_texture_compression_s3tc", extStart, extEnd); +#endif /* GL_EXT_texture_compression_s3tc */ +#ifdef GL_EXT_texture_cube_map + CONST_CAST(GLEW_EXT_texture_cube_map) = _glewSearchExtension("GL_EXT_texture_cube_map", extStart, extEnd); +#endif /* GL_EXT_texture_cube_map */ +#ifdef GL_EXT_texture_edge_clamp + CONST_CAST(GLEW_EXT_texture_edge_clamp) = _glewSearchExtension("GL_EXT_texture_edge_clamp", extStart, extEnd); +#endif /* GL_EXT_texture_edge_clamp */ +#ifdef GL_EXT_texture_env + CONST_CAST(GLEW_EXT_texture_env) = _glewSearchExtension("GL_EXT_texture_env", extStart, extEnd); +#endif /* GL_EXT_texture_env */ +#ifdef GL_EXT_texture_env_add + CONST_CAST(GLEW_EXT_texture_env_add) = _glewSearchExtension("GL_EXT_texture_env_add", extStart, extEnd); +#endif /* GL_EXT_texture_env_add */ +#ifdef GL_EXT_texture_env_combine + CONST_CAST(GLEW_EXT_texture_env_combine) = _glewSearchExtension("GL_EXT_texture_env_combine", extStart, extEnd); +#endif /* GL_EXT_texture_env_combine */ +#ifdef GL_EXT_texture_env_dot3 + CONST_CAST(GLEW_EXT_texture_env_dot3) = _glewSearchExtension("GL_EXT_texture_env_dot3", extStart, extEnd); +#endif /* GL_EXT_texture_env_dot3 */ +#ifdef GL_EXT_texture_filter_anisotropic + CONST_CAST(GLEW_EXT_texture_filter_anisotropic) = _glewSearchExtension("GL_EXT_texture_filter_anisotropic", extStart, extEnd); +#endif /* GL_EXT_texture_filter_anisotropic */ +#ifdef GL_EXT_texture_integer + CONST_CAST(GLEW_EXT_texture_integer) = _glewSearchExtension("GL_EXT_texture_integer", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture_integer) CONST_CAST(GLEW_EXT_texture_integer) = !_glewInit_GL_EXT_texture_integer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture_integer */ +#ifdef GL_EXT_texture_lod_bias + CONST_CAST(GLEW_EXT_texture_lod_bias) = _glewSearchExtension("GL_EXT_texture_lod_bias", extStart, extEnd); +#endif /* GL_EXT_texture_lod_bias */ +#ifdef GL_EXT_texture_mirror_clamp + CONST_CAST(GLEW_EXT_texture_mirror_clamp) = _glewSearchExtension("GL_EXT_texture_mirror_clamp", extStart, extEnd); +#endif /* GL_EXT_texture_mirror_clamp */ +#ifdef GL_EXT_texture_object + CONST_CAST(GLEW_EXT_texture_object) = _glewSearchExtension("GL_EXT_texture_object", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture_object) CONST_CAST(GLEW_EXT_texture_object) = !_glewInit_GL_EXT_texture_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture_object */ +#ifdef GL_EXT_texture_perturb_normal + CONST_CAST(GLEW_EXT_texture_perturb_normal) = _glewSearchExtension("GL_EXT_texture_perturb_normal", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture_perturb_normal) CONST_CAST(GLEW_EXT_texture_perturb_normal) = !_glewInit_GL_EXT_texture_perturb_normal(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_texture_perturb_normal */ +#ifdef GL_EXT_texture_rectangle + CONST_CAST(GLEW_EXT_texture_rectangle) = _glewSearchExtension("GL_EXT_texture_rectangle", extStart, extEnd); +#endif /* GL_EXT_texture_rectangle */ +#ifdef GL_EXT_texture_sRGB + CONST_CAST(GLEW_EXT_texture_sRGB) = _glewSearchExtension("GL_EXT_texture_sRGB", extStart, extEnd); +#endif /* GL_EXT_texture_sRGB */ +#ifdef GL_EXT_texture_sRGB_decode + CONST_CAST(GLEW_EXT_texture_sRGB_decode) = _glewSearchExtension("GL_EXT_texture_sRGB_decode", extStart, extEnd); +#endif /* GL_EXT_texture_sRGB_decode */ +#ifdef GL_EXT_texture_shared_exponent + CONST_CAST(GLEW_EXT_texture_shared_exponent) = _glewSearchExtension("GL_EXT_texture_shared_exponent", extStart, extEnd); +#endif /* GL_EXT_texture_shared_exponent */ +#ifdef GL_EXT_texture_snorm + CONST_CAST(GLEW_EXT_texture_snorm) = _glewSearchExtension("GL_EXT_texture_snorm", extStart, extEnd); +#endif /* GL_EXT_texture_snorm */ +#ifdef GL_EXT_texture_swizzle + CONST_CAST(GLEW_EXT_texture_swizzle) = _glewSearchExtension("GL_EXT_texture_swizzle", extStart, extEnd); +#endif /* GL_EXT_texture_swizzle */ +#ifdef GL_EXT_timer_query + CONST_CAST(GLEW_EXT_timer_query) = _glewSearchExtension("GL_EXT_timer_query", extStart, extEnd); + if (glewExperimental || GLEW_EXT_timer_query) CONST_CAST(GLEW_EXT_timer_query) = !_glewInit_GL_EXT_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_timer_query */ +#ifdef GL_EXT_transform_feedback + CONST_CAST(GLEW_EXT_transform_feedback) = _glewSearchExtension("GL_EXT_transform_feedback", extStart, extEnd); + if (glewExperimental || GLEW_EXT_transform_feedback) CONST_CAST(GLEW_EXT_transform_feedback) = !_glewInit_GL_EXT_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_transform_feedback */ +#ifdef GL_EXT_vertex_array + CONST_CAST(GLEW_EXT_vertex_array) = _glewSearchExtension("GL_EXT_vertex_array", extStart, extEnd); + if (glewExperimental || GLEW_EXT_vertex_array) CONST_CAST(GLEW_EXT_vertex_array) = !_glewInit_GL_EXT_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_vertex_array */ +#ifdef GL_EXT_vertex_array_bgra + CONST_CAST(GLEW_EXT_vertex_array_bgra) = _glewSearchExtension("GL_EXT_vertex_array_bgra", extStart, extEnd); +#endif /* GL_EXT_vertex_array_bgra */ +#ifdef GL_EXT_vertex_attrib_64bit + CONST_CAST(GLEW_EXT_vertex_attrib_64bit) = _glewSearchExtension("GL_EXT_vertex_attrib_64bit", extStart, extEnd); + if (glewExperimental || GLEW_EXT_vertex_attrib_64bit) CONST_CAST(GLEW_EXT_vertex_attrib_64bit) = !_glewInit_GL_EXT_vertex_attrib_64bit(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_vertex_attrib_64bit */ +#ifdef GL_EXT_vertex_shader + CONST_CAST(GLEW_EXT_vertex_shader) = _glewSearchExtension("GL_EXT_vertex_shader", extStart, extEnd); + if (glewExperimental || GLEW_EXT_vertex_shader) CONST_CAST(GLEW_EXT_vertex_shader) = !_glewInit_GL_EXT_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_vertex_shader */ +#ifdef GL_EXT_vertex_weighting + CONST_CAST(GLEW_EXT_vertex_weighting) = _glewSearchExtension("GL_EXT_vertex_weighting", extStart, extEnd); + if (glewExperimental || GLEW_EXT_vertex_weighting) CONST_CAST(GLEW_EXT_vertex_weighting) = !_glewInit_GL_EXT_vertex_weighting(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_vertex_weighting */ +#ifdef GL_EXT_x11_sync_object + CONST_CAST(GLEW_EXT_x11_sync_object) = _glewSearchExtension("GL_EXT_x11_sync_object", extStart, extEnd); + if (glewExperimental || GLEW_EXT_x11_sync_object) CONST_CAST(GLEW_EXT_x11_sync_object) = !_glewInit_GL_EXT_x11_sync_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_x11_sync_object */ +#ifdef GL_GREMEDY_frame_terminator + CONST_CAST(GLEW_GREMEDY_frame_terminator) = _glewSearchExtension("GL_GREMEDY_frame_terminator", extStart, extEnd); + if (glewExperimental || GLEW_GREMEDY_frame_terminator) CONST_CAST(GLEW_GREMEDY_frame_terminator) = !_glewInit_GL_GREMEDY_frame_terminator(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_GREMEDY_frame_terminator */ +#ifdef GL_GREMEDY_string_marker + CONST_CAST(GLEW_GREMEDY_string_marker) = _glewSearchExtension("GL_GREMEDY_string_marker", extStart, extEnd); + if (glewExperimental || GLEW_GREMEDY_string_marker) CONST_CAST(GLEW_GREMEDY_string_marker) = !_glewInit_GL_GREMEDY_string_marker(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_GREMEDY_string_marker */ +#ifdef GL_HP_convolution_border_modes + CONST_CAST(GLEW_HP_convolution_border_modes) = _glewSearchExtension("GL_HP_convolution_border_modes", extStart, extEnd); +#endif /* GL_HP_convolution_border_modes */ +#ifdef GL_HP_image_transform + CONST_CAST(GLEW_HP_image_transform) = _glewSearchExtension("GL_HP_image_transform", extStart, extEnd); + if (glewExperimental || GLEW_HP_image_transform) CONST_CAST(GLEW_HP_image_transform) = !_glewInit_GL_HP_image_transform(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_HP_image_transform */ +#ifdef GL_HP_occlusion_test + CONST_CAST(GLEW_HP_occlusion_test) = _glewSearchExtension("GL_HP_occlusion_test", extStart, extEnd); +#endif /* GL_HP_occlusion_test */ +#ifdef GL_HP_texture_lighting + CONST_CAST(GLEW_HP_texture_lighting) = _glewSearchExtension("GL_HP_texture_lighting", extStart, extEnd); +#endif /* GL_HP_texture_lighting */ +#ifdef GL_IBM_cull_vertex + CONST_CAST(GLEW_IBM_cull_vertex) = _glewSearchExtension("GL_IBM_cull_vertex", extStart, extEnd); +#endif /* GL_IBM_cull_vertex */ +#ifdef GL_IBM_multimode_draw_arrays + CONST_CAST(GLEW_IBM_multimode_draw_arrays) = _glewSearchExtension("GL_IBM_multimode_draw_arrays", extStart, extEnd); + if (glewExperimental || GLEW_IBM_multimode_draw_arrays) CONST_CAST(GLEW_IBM_multimode_draw_arrays) = !_glewInit_GL_IBM_multimode_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_IBM_multimode_draw_arrays */ +#ifdef GL_IBM_rasterpos_clip + CONST_CAST(GLEW_IBM_rasterpos_clip) = _glewSearchExtension("GL_IBM_rasterpos_clip", extStart, extEnd); +#endif /* GL_IBM_rasterpos_clip */ +#ifdef GL_IBM_static_data + CONST_CAST(GLEW_IBM_static_data) = _glewSearchExtension("GL_IBM_static_data", extStart, extEnd); +#endif /* GL_IBM_static_data */ +#ifdef GL_IBM_texture_mirrored_repeat + CONST_CAST(GLEW_IBM_texture_mirrored_repeat) = _glewSearchExtension("GL_IBM_texture_mirrored_repeat", extStart, extEnd); +#endif /* GL_IBM_texture_mirrored_repeat */ +#ifdef GL_IBM_vertex_array_lists + CONST_CAST(GLEW_IBM_vertex_array_lists) = _glewSearchExtension("GL_IBM_vertex_array_lists", extStart, extEnd); + if (glewExperimental || GLEW_IBM_vertex_array_lists) CONST_CAST(GLEW_IBM_vertex_array_lists) = !_glewInit_GL_IBM_vertex_array_lists(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_IBM_vertex_array_lists */ +#ifdef GL_INGR_color_clamp + CONST_CAST(GLEW_INGR_color_clamp) = _glewSearchExtension("GL_INGR_color_clamp", extStart, extEnd); +#endif /* GL_INGR_color_clamp */ +#ifdef GL_INGR_interlace_read + CONST_CAST(GLEW_INGR_interlace_read) = _glewSearchExtension("GL_INGR_interlace_read", extStart, extEnd); +#endif /* GL_INGR_interlace_read */ +#ifdef GL_INTEL_parallel_arrays + CONST_CAST(GLEW_INTEL_parallel_arrays) = _glewSearchExtension("GL_INTEL_parallel_arrays", extStart, extEnd); + if (glewExperimental || GLEW_INTEL_parallel_arrays) CONST_CAST(GLEW_INTEL_parallel_arrays) = !_glewInit_GL_INTEL_parallel_arrays(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_INTEL_parallel_arrays */ +#ifdef GL_INTEL_texture_scissor + CONST_CAST(GLEW_INTEL_texture_scissor) = _glewSearchExtension("GL_INTEL_texture_scissor", extStart, extEnd); + if (glewExperimental || GLEW_INTEL_texture_scissor) CONST_CAST(GLEW_INTEL_texture_scissor) = !_glewInit_GL_INTEL_texture_scissor(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_INTEL_texture_scissor */ +#ifdef GL_KTX_buffer_region + CONST_CAST(GLEW_KTX_buffer_region) = _glewSearchExtension("GL_KTX_buffer_region", extStart, extEnd); + if (glewExperimental || GLEW_KTX_buffer_region) CONST_CAST(GLEW_KTX_buffer_region) = !_glewInit_GL_KTX_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_KTX_buffer_region */ +#ifdef GL_MESAX_texture_stack + CONST_CAST(GLEW_MESAX_texture_stack) = _glewSearchExtension("GL_MESAX_texture_stack", extStart, extEnd); +#endif /* GL_MESAX_texture_stack */ +#ifdef GL_MESA_pack_invert + CONST_CAST(GLEW_MESA_pack_invert) = _glewSearchExtension("GL_MESA_pack_invert", extStart, extEnd); +#endif /* GL_MESA_pack_invert */ +#ifdef GL_MESA_resize_buffers + CONST_CAST(GLEW_MESA_resize_buffers) = _glewSearchExtension("GL_MESA_resize_buffers", extStart, extEnd); + if (glewExperimental || GLEW_MESA_resize_buffers) CONST_CAST(GLEW_MESA_resize_buffers) = !_glewInit_GL_MESA_resize_buffers(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_MESA_resize_buffers */ +#ifdef GL_MESA_window_pos + CONST_CAST(GLEW_MESA_window_pos) = _glewSearchExtension("GL_MESA_window_pos", extStart, extEnd); + if (glewExperimental || GLEW_MESA_window_pos) CONST_CAST(GLEW_MESA_window_pos) = !_glewInit_GL_MESA_window_pos(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_MESA_window_pos */ +#ifdef GL_MESA_ycbcr_texture + CONST_CAST(GLEW_MESA_ycbcr_texture) = _glewSearchExtension("GL_MESA_ycbcr_texture", extStart, extEnd); +#endif /* GL_MESA_ycbcr_texture */ +#ifdef GL_NVX_gpu_memory_info + CONST_CAST(GLEW_NVX_gpu_memory_info) = _glewSearchExtension("GL_NVX_gpu_memory_info", extStart, extEnd); +#endif /* GL_NVX_gpu_memory_info */ +#ifdef GL_NV_blend_square + CONST_CAST(GLEW_NV_blend_square) = _glewSearchExtension("GL_NV_blend_square", extStart, extEnd); +#endif /* GL_NV_blend_square */ +#ifdef GL_NV_conditional_render + CONST_CAST(GLEW_NV_conditional_render) = _glewSearchExtension("GL_NV_conditional_render", extStart, extEnd); + if (glewExperimental || GLEW_NV_conditional_render) CONST_CAST(GLEW_NV_conditional_render) = !_glewInit_GL_NV_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_conditional_render */ +#ifdef GL_NV_copy_depth_to_color + CONST_CAST(GLEW_NV_copy_depth_to_color) = _glewSearchExtension("GL_NV_copy_depth_to_color", extStart, extEnd); +#endif /* GL_NV_copy_depth_to_color */ +#ifdef GL_NV_copy_image + CONST_CAST(GLEW_NV_copy_image) = _glewSearchExtension("GL_NV_copy_image", extStart, extEnd); + if (glewExperimental || GLEW_NV_copy_image) CONST_CAST(GLEW_NV_copy_image) = !_glewInit_GL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_copy_image */ +#ifdef GL_NV_depth_buffer_float + CONST_CAST(GLEW_NV_depth_buffer_float) = _glewSearchExtension("GL_NV_depth_buffer_float", extStart, extEnd); + if (glewExperimental || GLEW_NV_depth_buffer_float) CONST_CAST(GLEW_NV_depth_buffer_float) = !_glewInit_GL_NV_depth_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_depth_buffer_float */ +#ifdef GL_NV_depth_clamp + CONST_CAST(GLEW_NV_depth_clamp) = _glewSearchExtension("GL_NV_depth_clamp", extStart, extEnd); +#endif /* GL_NV_depth_clamp */ +#ifdef GL_NV_depth_range_unclamped + CONST_CAST(GLEW_NV_depth_range_unclamped) = _glewSearchExtension("GL_NV_depth_range_unclamped", extStart, extEnd); +#endif /* GL_NV_depth_range_unclamped */ +#ifdef GL_NV_evaluators + CONST_CAST(GLEW_NV_evaluators) = _glewSearchExtension("GL_NV_evaluators", extStart, extEnd); + if (glewExperimental || GLEW_NV_evaluators) CONST_CAST(GLEW_NV_evaluators) = !_glewInit_GL_NV_evaluators(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_evaluators */ +#ifdef GL_NV_explicit_multisample + CONST_CAST(GLEW_NV_explicit_multisample) = _glewSearchExtension("GL_NV_explicit_multisample", extStart, extEnd); + if (glewExperimental || GLEW_NV_explicit_multisample) CONST_CAST(GLEW_NV_explicit_multisample) = !_glewInit_GL_NV_explicit_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_explicit_multisample */ +#ifdef GL_NV_fence + CONST_CAST(GLEW_NV_fence) = _glewSearchExtension("GL_NV_fence", extStart, extEnd); + if (glewExperimental || GLEW_NV_fence) CONST_CAST(GLEW_NV_fence) = !_glewInit_GL_NV_fence(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_fence */ +#ifdef GL_NV_float_buffer + CONST_CAST(GLEW_NV_float_buffer) = _glewSearchExtension("GL_NV_float_buffer", extStart, extEnd); +#endif /* GL_NV_float_buffer */ +#ifdef GL_NV_fog_distance + CONST_CAST(GLEW_NV_fog_distance) = _glewSearchExtension("GL_NV_fog_distance", extStart, extEnd); +#endif /* GL_NV_fog_distance */ +#ifdef GL_NV_fragment_program + CONST_CAST(GLEW_NV_fragment_program) = _glewSearchExtension("GL_NV_fragment_program", extStart, extEnd); + if (glewExperimental || GLEW_NV_fragment_program) CONST_CAST(GLEW_NV_fragment_program) = !_glewInit_GL_NV_fragment_program(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_fragment_program */ +#ifdef GL_NV_fragment_program2 + CONST_CAST(GLEW_NV_fragment_program2) = _glewSearchExtension("GL_NV_fragment_program2", extStart, extEnd); +#endif /* GL_NV_fragment_program2 */ +#ifdef GL_NV_fragment_program4 + CONST_CAST(GLEW_NV_fragment_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); +#endif /* GL_NV_fragment_program4 */ +#ifdef GL_NV_fragment_program_option + CONST_CAST(GLEW_NV_fragment_program_option) = _glewSearchExtension("GL_NV_fragment_program_option", extStart, extEnd); +#endif /* GL_NV_fragment_program_option */ +#ifdef GL_NV_framebuffer_multisample_coverage + CONST_CAST(GLEW_NV_framebuffer_multisample_coverage) = _glewSearchExtension("GL_NV_framebuffer_multisample_coverage", extStart, extEnd); + if (glewExperimental || GLEW_NV_framebuffer_multisample_coverage) CONST_CAST(GLEW_NV_framebuffer_multisample_coverage) = !_glewInit_GL_NV_framebuffer_multisample_coverage(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_framebuffer_multisample_coverage */ +#ifdef GL_NV_geometry_program4 + CONST_CAST(GLEW_NV_geometry_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); + if (glewExperimental || GLEW_NV_geometry_program4) CONST_CAST(GLEW_NV_geometry_program4) = !_glewInit_GL_NV_geometry_program4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_geometry_program4 */ +#ifdef GL_NV_geometry_shader4 + CONST_CAST(GLEW_NV_geometry_shader4) = _glewSearchExtension("GL_NV_geometry_shader4", extStart, extEnd); +#endif /* GL_NV_geometry_shader4 */ +#ifdef GL_NV_gpu_program4 + CONST_CAST(GLEW_NV_gpu_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); + if (glewExperimental || GLEW_NV_gpu_program4) CONST_CAST(GLEW_NV_gpu_program4) = !_glewInit_GL_NV_gpu_program4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_gpu_program4 */ +#ifdef GL_NV_gpu_program5 + CONST_CAST(GLEW_NV_gpu_program5) = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd); +#endif /* GL_NV_gpu_program5 */ +#ifdef GL_NV_gpu_program_fp64 + CONST_CAST(GLEW_NV_gpu_program_fp64) = _glewSearchExtension("GL_NV_gpu_program_fp64", extStart, extEnd); +#endif /* GL_NV_gpu_program_fp64 */ +#ifdef GL_NV_gpu_shader5 + CONST_CAST(GLEW_NV_gpu_shader5) = _glewSearchExtension("GL_NV_gpu_shader5", extStart, extEnd); + if (glewExperimental || GLEW_NV_gpu_shader5) CONST_CAST(GLEW_NV_gpu_shader5) = !_glewInit_GL_NV_gpu_shader5(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_gpu_shader5 */ +#ifdef GL_NV_half_float + CONST_CAST(GLEW_NV_half_float) = _glewSearchExtension("GL_NV_half_float", extStart, extEnd); + if (glewExperimental || GLEW_NV_half_float) CONST_CAST(GLEW_NV_half_float) = !_glewInit_GL_NV_half_float(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_half_float */ +#ifdef GL_NV_light_max_exponent + CONST_CAST(GLEW_NV_light_max_exponent) = _glewSearchExtension("GL_NV_light_max_exponent", extStart, extEnd); +#endif /* GL_NV_light_max_exponent */ +#ifdef GL_NV_multisample_coverage + CONST_CAST(GLEW_NV_multisample_coverage) = _glewSearchExtension("GL_NV_multisample_coverage", extStart, extEnd); +#endif /* GL_NV_multisample_coverage */ +#ifdef GL_NV_multisample_filter_hint + CONST_CAST(GLEW_NV_multisample_filter_hint) = _glewSearchExtension("GL_NV_multisample_filter_hint", extStart, extEnd); +#endif /* GL_NV_multisample_filter_hint */ +#ifdef GL_NV_occlusion_query + CONST_CAST(GLEW_NV_occlusion_query) = _glewSearchExtension("GL_NV_occlusion_query", extStart, extEnd); + if (glewExperimental || GLEW_NV_occlusion_query) CONST_CAST(GLEW_NV_occlusion_query) = !_glewInit_GL_NV_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_occlusion_query */ +#ifdef GL_NV_packed_depth_stencil + CONST_CAST(GLEW_NV_packed_depth_stencil) = _glewSearchExtension("GL_NV_packed_depth_stencil", extStart, extEnd); +#endif /* GL_NV_packed_depth_stencil */ +#ifdef GL_NV_parameter_buffer_object + CONST_CAST(GLEW_NV_parameter_buffer_object) = _glewSearchExtension("GL_NV_parameter_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_NV_parameter_buffer_object) CONST_CAST(GLEW_NV_parameter_buffer_object) = !_glewInit_GL_NV_parameter_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_parameter_buffer_object */ +#ifdef GL_NV_parameter_buffer_object2 + CONST_CAST(GLEW_NV_parameter_buffer_object2) = _glewSearchExtension("GL_NV_parameter_buffer_object2", extStart, extEnd); +#endif /* GL_NV_parameter_buffer_object2 */ +#ifdef GL_NV_pixel_data_range + CONST_CAST(GLEW_NV_pixel_data_range) = _glewSearchExtension("GL_NV_pixel_data_range", extStart, extEnd); + if (glewExperimental || GLEW_NV_pixel_data_range) CONST_CAST(GLEW_NV_pixel_data_range) = !_glewInit_GL_NV_pixel_data_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_pixel_data_range */ +#ifdef GL_NV_point_sprite + CONST_CAST(GLEW_NV_point_sprite) = _glewSearchExtension("GL_NV_point_sprite", extStart, extEnd); + if (glewExperimental || GLEW_NV_point_sprite) CONST_CAST(GLEW_NV_point_sprite) = !_glewInit_GL_NV_point_sprite(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_point_sprite */ +#ifdef GL_NV_present_video + CONST_CAST(GLEW_NV_present_video) = _glewSearchExtension("GL_NV_present_video", extStart, extEnd); + if (glewExperimental || GLEW_NV_present_video) CONST_CAST(GLEW_NV_present_video) = !_glewInit_GL_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_present_video */ +#ifdef GL_NV_primitive_restart + CONST_CAST(GLEW_NV_primitive_restart) = _glewSearchExtension("GL_NV_primitive_restart", extStart, extEnd); + if (glewExperimental || GLEW_NV_primitive_restart) CONST_CAST(GLEW_NV_primitive_restart) = !_glewInit_GL_NV_primitive_restart(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_primitive_restart */ +#ifdef GL_NV_register_combiners + CONST_CAST(GLEW_NV_register_combiners) = _glewSearchExtension("GL_NV_register_combiners", extStart, extEnd); + if (glewExperimental || GLEW_NV_register_combiners) CONST_CAST(GLEW_NV_register_combiners) = !_glewInit_GL_NV_register_combiners(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_register_combiners */ +#ifdef GL_NV_register_combiners2 + CONST_CAST(GLEW_NV_register_combiners2) = _glewSearchExtension("GL_NV_register_combiners2", extStart, extEnd); + if (glewExperimental || GLEW_NV_register_combiners2) CONST_CAST(GLEW_NV_register_combiners2) = !_glewInit_GL_NV_register_combiners2(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_register_combiners2 */ +#ifdef GL_NV_shader_buffer_load + CONST_CAST(GLEW_NV_shader_buffer_load) = _glewSearchExtension("GL_NV_shader_buffer_load", extStart, extEnd); + if (glewExperimental || GLEW_NV_shader_buffer_load) CONST_CAST(GLEW_NV_shader_buffer_load) = !_glewInit_GL_NV_shader_buffer_load(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_shader_buffer_load */ +#ifdef GL_NV_tessellation_program5 + CONST_CAST(GLEW_NV_tessellation_program5) = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd); +#endif /* GL_NV_tessellation_program5 */ +#ifdef GL_NV_texgen_emboss + CONST_CAST(GLEW_NV_texgen_emboss) = _glewSearchExtension("GL_NV_texgen_emboss", extStart, extEnd); +#endif /* GL_NV_texgen_emboss */ +#ifdef GL_NV_texgen_reflection + CONST_CAST(GLEW_NV_texgen_reflection) = _glewSearchExtension("GL_NV_texgen_reflection", extStart, extEnd); +#endif /* GL_NV_texgen_reflection */ +#ifdef GL_NV_texture_barrier + CONST_CAST(GLEW_NV_texture_barrier) = _glewSearchExtension("GL_NV_texture_barrier", extStart, extEnd); + if (glewExperimental || GLEW_NV_texture_barrier) CONST_CAST(GLEW_NV_texture_barrier) = !_glewInit_GL_NV_texture_barrier(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_texture_barrier */ +#ifdef GL_NV_texture_compression_vtc + CONST_CAST(GLEW_NV_texture_compression_vtc) = _glewSearchExtension("GL_NV_texture_compression_vtc", extStart, extEnd); +#endif /* GL_NV_texture_compression_vtc */ +#ifdef GL_NV_texture_env_combine4 + CONST_CAST(GLEW_NV_texture_env_combine4) = _glewSearchExtension("GL_NV_texture_env_combine4", extStart, extEnd); +#endif /* GL_NV_texture_env_combine4 */ +#ifdef GL_NV_texture_expand_normal + CONST_CAST(GLEW_NV_texture_expand_normal) = _glewSearchExtension("GL_NV_texture_expand_normal", extStart, extEnd); +#endif /* GL_NV_texture_expand_normal */ +#ifdef GL_NV_texture_multisample + CONST_CAST(GLEW_NV_texture_multisample) = _glewSearchExtension("GL_NV_texture_multisample", extStart, extEnd); + if (glewExperimental || GLEW_NV_texture_multisample) CONST_CAST(GLEW_NV_texture_multisample) = !_glewInit_GL_NV_texture_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_texture_multisample */ +#ifdef GL_NV_texture_rectangle + CONST_CAST(GLEW_NV_texture_rectangle) = _glewSearchExtension("GL_NV_texture_rectangle", extStart, extEnd); +#endif /* GL_NV_texture_rectangle */ +#ifdef GL_NV_texture_shader + CONST_CAST(GLEW_NV_texture_shader) = _glewSearchExtension("GL_NV_texture_shader", extStart, extEnd); +#endif /* GL_NV_texture_shader */ +#ifdef GL_NV_texture_shader2 + CONST_CAST(GLEW_NV_texture_shader2) = _glewSearchExtension("GL_NV_texture_shader2", extStart, extEnd); +#endif /* GL_NV_texture_shader2 */ +#ifdef GL_NV_texture_shader3 + CONST_CAST(GLEW_NV_texture_shader3) = _glewSearchExtension("GL_NV_texture_shader3", extStart, extEnd); +#endif /* GL_NV_texture_shader3 */ +#ifdef GL_NV_transform_feedback + CONST_CAST(GLEW_NV_transform_feedback) = _glewSearchExtension("GL_NV_transform_feedback", extStart, extEnd); + if (glewExperimental || GLEW_NV_transform_feedback) CONST_CAST(GLEW_NV_transform_feedback) = !_glewInit_GL_NV_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_transform_feedback */ +#ifdef GL_NV_transform_feedback2 + CONST_CAST(GLEW_NV_transform_feedback2) = _glewSearchExtension("GL_NV_transform_feedback2", extStart, extEnd); + if (glewExperimental || GLEW_NV_transform_feedback2) CONST_CAST(GLEW_NV_transform_feedback2) = !_glewInit_GL_NV_transform_feedback2(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_transform_feedback2 */ +#ifdef GL_NV_vdpau_interop + CONST_CAST(GLEW_NV_vdpau_interop) = _glewSearchExtension("GL_NV_vdpau_interop", extStart, extEnd); + if (glewExperimental || GLEW_NV_vdpau_interop) CONST_CAST(GLEW_NV_vdpau_interop) = !_glewInit_GL_NV_vdpau_interop(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_vdpau_interop */ +#ifdef GL_NV_vertex_array_range + CONST_CAST(GLEW_NV_vertex_array_range) = _glewSearchExtension("GL_NV_vertex_array_range", extStart, extEnd); + if (glewExperimental || GLEW_NV_vertex_array_range) CONST_CAST(GLEW_NV_vertex_array_range) = !_glewInit_GL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_vertex_array_range */ +#ifdef GL_NV_vertex_array_range2 + CONST_CAST(GLEW_NV_vertex_array_range2) = _glewSearchExtension("GL_NV_vertex_array_range2", extStart, extEnd); +#endif /* GL_NV_vertex_array_range2 */ +#ifdef GL_NV_vertex_attrib_integer_64bit + CONST_CAST(GLEW_NV_vertex_attrib_integer_64bit) = _glewSearchExtension("GL_NV_vertex_attrib_integer_64bit", extStart, extEnd); + if (glewExperimental || GLEW_NV_vertex_attrib_integer_64bit) CONST_CAST(GLEW_NV_vertex_attrib_integer_64bit) = !_glewInit_GL_NV_vertex_attrib_integer_64bit(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_vertex_attrib_integer_64bit */ +#ifdef GL_NV_vertex_buffer_unified_memory + CONST_CAST(GLEW_NV_vertex_buffer_unified_memory) = _glewSearchExtension("GL_NV_vertex_buffer_unified_memory", extStart, extEnd); + if (glewExperimental || GLEW_NV_vertex_buffer_unified_memory) CONST_CAST(GLEW_NV_vertex_buffer_unified_memory) = !_glewInit_GL_NV_vertex_buffer_unified_memory(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_vertex_buffer_unified_memory */ +#ifdef GL_NV_vertex_program + CONST_CAST(GLEW_NV_vertex_program) = _glewSearchExtension("GL_NV_vertex_program", extStart, extEnd); + if (glewExperimental || GLEW_NV_vertex_program) CONST_CAST(GLEW_NV_vertex_program) = !_glewInit_GL_NV_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_vertex_program */ +#ifdef GL_NV_vertex_program1_1 + CONST_CAST(GLEW_NV_vertex_program1_1) = _glewSearchExtension("GL_NV_vertex_program1_1", extStart, extEnd); +#endif /* GL_NV_vertex_program1_1 */ +#ifdef GL_NV_vertex_program2 + CONST_CAST(GLEW_NV_vertex_program2) = _glewSearchExtension("GL_NV_vertex_program2", extStart, extEnd); +#endif /* GL_NV_vertex_program2 */ +#ifdef GL_NV_vertex_program2_option + CONST_CAST(GLEW_NV_vertex_program2_option) = _glewSearchExtension("GL_NV_vertex_program2_option", extStart, extEnd); +#endif /* GL_NV_vertex_program2_option */ +#ifdef GL_NV_vertex_program3 + CONST_CAST(GLEW_NV_vertex_program3) = _glewSearchExtension("GL_NV_vertex_program3", extStart, extEnd); +#endif /* GL_NV_vertex_program3 */ +#ifdef GL_NV_vertex_program4 + CONST_CAST(GLEW_NV_vertex_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); +#endif /* GL_NV_vertex_program4 */ +#ifdef GL_NV_video_capture + CONST_CAST(GLEW_NV_video_capture) = _glewSearchExtension("GL_NV_video_capture", extStart, extEnd); + if (glewExperimental || GLEW_NV_video_capture) CONST_CAST(GLEW_NV_video_capture) = !_glewInit_GL_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_video_capture */ +#ifdef GL_OES_byte_coordinates + CONST_CAST(GLEW_OES_byte_coordinates) = _glewSearchExtension("GL_OES_byte_coordinates", extStart, extEnd); +#endif /* GL_OES_byte_coordinates */ +#ifdef GL_OES_compressed_paletted_texture + CONST_CAST(GLEW_OES_compressed_paletted_texture) = _glewSearchExtension("GL_OES_compressed_paletted_texture", extStart, extEnd); +#endif /* GL_OES_compressed_paletted_texture */ +#ifdef GL_OES_read_format + CONST_CAST(GLEW_OES_read_format) = _glewSearchExtension("GL_OES_read_format", extStart, extEnd); +#endif /* GL_OES_read_format */ +#ifdef GL_OES_single_precision + CONST_CAST(GLEW_OES_single_precision) = _glewSearchExtension("GL_OES_single_precision", extStart, extEnd); + if (glewExperimental || GLEW_OES_single_precision) CONST_CAST(GLEW_OES_single_precision) = !_glewInit_GL_OES_single_precision(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_OES_single_precision */ +#ifdef GL_OML_interlace + CONST_CAST(GLEW_OML_interlace) = _glewSearchExtension("GL_OML_interlace", extStart, extEnd); +#endif /* GL_OML_interlace */ +#ifdef GL_OML_resample + CONST_CAST(GLEW_OML_resample) = _glewSearchExtension("GL_OML_resample", extStart, extEnd); +#endif /* GL_OML_resample */ +#ifdef GL_OML_subsample + CONST_CAST(GLEW_OML_subsample) = _glewSearchExtension("GL_OML_subsample", extStart, extEnd); +#endif /* GL_OML_subsample */ +#ifdef GL_PGI_misc_hints + CONST_CAST(GLEW_PGI_misc_hints) = _glewSearchExtension("GL_PGI_misc_hints", extStart, extEnd); +#endif /* GL_PGI_misc_hints */ +#ifdef GL_PGI_vertex_hints + CONST_CAST(GLEW_PGI_vertex_hints) = _glewSearchExtension("GL_PGI_vertex_hints", extStart, extEnd); +#endif /* GL_PGI_vertex_hints */ +#ifdef GL_REND_screen_coordinates + CONST_CAST(GLEW_REND_screen_coordinates) = _glewSearchExtension("GL_REND_screen_coordinates", extStart, extEnd); +#endif /* GL_REND_screen_coordinates */ +#ifdef GL_S3_s3tc + CONST_CAST(GLEW_S3_s3tc) = _glewSearchExtension("GL_S3_s3tc", extStart, extEnd); +#endif /* GL_S3_s3tc */ +#ifdef GL_SGIS_color_range + CONST_CAST(GLEW_SGIS_color_range) = _glewSearchExtension("GL_SGIS_color_range", extStart, extEnd); +#endif /* GL_SGIS_color_range */ +#ifdef GL_SGIS_detail_texture + CONST_CAST(GLEW_SGIS_detail_texture) = _glewSearchExtension("GL_SGIS_detail_texture", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_detail_texture) CONST_CAST(GLEW_SGIS_detail_texture) = !_glewInit_GL_SGIS_detail_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_detail_texture */ +#ifdef GL_SGIS_fog_function + CONST_CAST(GLEW_SGIS_fog_function) = _glewSearchExtension("GL_SGIS_fog_function", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_fog_function) CONST_CAST(GLEW_SGIS_fog_function) = !_glewInit_GL_SGIS_fog_function(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_fog_function */ +#ifdef GL_SGIS_generate_mipmap + CONST_CAST(GLEW_SGIS_generate_mipmap) = _glewSearchExtension("GL_SGIS_generate_mipmap", extStart, extEnd); +#endif /* GL_SGIS_generate_mipmap */ +#ifdef GL_SGIS_multisample + CONST_CAST(GLEW_SGIS_multisample) = _glewSearchExtension("GL_SGIS_multisample", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_multisample) CONST_CAST(GLEW_SGIS_multisample) = !_glewInit_GL_SGIS_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_multisample */ +#ifdef GL_SGIS_pixel_texture + CONST_CAST(GLEW_SGIS_pixel_texture) = _glewSearchExtension("GL_SGIS_pixel_texture", extStart, extEnd); +#endif /* GL_SGIS_pixel_texture */ +#ifdef GL_SGIS_point_line_texgen + CONST_CAST(GLEW_SGIS_point_line_texgen) = _glewSearchExtension("GL_SGIS_point_line_texgen", extStart, extEnd); +#endif /* GL_SGIS_point_line_texgen */ +#ifdef GL_SGIS_sharpen_texture + CONST_CAST(GLEW_SGIS_sharpen_texture) = _glewSearchExtension("GL_SGIS_sharpen_texture", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_sharpen_texture) CONST_CAST(GLEW_SGIS_sharpen_texture) = !_glewInit_GL_SGIS_sharpen_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_sharpen_texture */ +#ifdef GL_SGIS_texture4D + CONST_CAST(GLEW_SGIS_texture4D) = _glewSearchExtension("GL_SGIS_texture4D", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_texture4D) CONST_CAST(GLEW_SGIS_texture4D) = !_glewInit_GL_SGIS_texture4D(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_texture4D */ +#ifdef GL_SGIS_texture_border_clamp + CONST_CAST(GLEW_SGIS_texture_border_clamp) = _glewSearchExtension("GL_SGIS_texture_border_clamp", extStart, extEnd); +#endif /* GL_SGIS_texture_border_clamp */ +#ifdef GL_SGIS_texture_edge_clamp + CONST_CAST(GLEW_SGIS_texture_edge_clamp) = _glewSearchExtension("GL_SGIS_texture_edge_clamp", extStart, extEnd); +#endif /* GL_SGIS_texture_edge_clamp */ +#ifdef GL_SGIS_texture_filter4 + CONST_CAST(GLEW_SGIS_texture_filter4) = _glewSearchExtension("GL_SGIS_texture_filter4", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_texture_filter4) CONST_CAST(GLEW_SGIS_texture_filter4) = !_glewInit_GL_SGIS_texture_filter4(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIS_texture_filter4 */ +#ifdef GL_SGIS_texture_lod + CONST_CAST(GLEW_SGIS_texture_lod) = _glewSearchExtension("GL_SGIS_texture_lod", extStart, extEnd); +#endif /* GL_SGIS_texture_lod */ +#ifdef GL_SGIS_texture_select + CONST_CAST(GLEW_SGIS_texture_select) = _glewSearchExtension("GL_SGIS_texture_select", extStart, extEnd); +#endif /* GL_SGIS_texture_select */ +#ifdef GL_SGIX_async + CONST_CAST(GLEW_SGIX_async) = _glewSearchExtension("GL_SGIX_async", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_async) CONST_CAST(GLEW_SGIX_async) = !_glewInit_GL_SGIX_async(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_async */ +#ifdef GL_SGIX_async_histogram + CONST_CAST(GLEW_SGIX_async_histogram) = _glewSearchExtension("GL_SGIX_async_histogram", extStart, extEnd); +#endif /* GL_SGIX_async_histogram */ +#ifdef GL_SGIX_async_pixel + CONST_CAST(GLEW_SGIX_async_pixel) = _glewSearchExtension("GL_SGIX_async_pixel", extStart, extEnd); +#endif /* GL_SGIX_async_pixel */ +#ifdef GL_SGIX_blend_alpha_minmax + CONST_CAST(GLEW_SGIX_blend_alpha_minmax) = _glewSearchExtension("GL_SGIX_blend_alpha_minmax", extStart, extEnd); +#endif /* GL_SGIX_blend_alpha_minmax */ +#ifdef GL_SGIX_clipmap + CONST_CAST(GLEW_SGIX_clipmap) = _glewSearchExtension("GL_SGIX_clipmap", extStart, extEnd); +#endif /* GL_SGIX_clipmap */ +#ifdef GL_SGIX_convolution_accuracy + CONST_CAST(GLEW_SGIX_convolution_accuracy) = _glewSearchExtension("GL_SGIX_convolution_accuracy", extStart, extEnd); +#endif /* GL_SGIX_convolution_accuracy */ +#ifdef GL_SGIX_depth_texture + CONST_CAST(GLEW_SGIX_depth_texture) = _glewSearchExtension("GL_SGIX_depth_texture", extStart, extEnd); +#endif /* GL_SGIX_depth_texture */ +#ifdef GL_SGIX_flush_raster + CONST_CAST(GLEW_SGIX_flush_raster) = _glewSearchExtension("GL_SGIX_flush_raster", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_flush_raster) CONST_CAST(GLEW_SGIX_flush_raster) = !_glewInit_GL_SGIX_flush_raster(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_flush_raster */ +#ifdef GL_SGIX_fog_offset + CONST_CAST(GLEW_SGIX_fog_offset) = _glewSearchExtension("GL_SGIX_fog_offset", extStart, extEnd); +#endif /* GL_SGIX_fog_offset */ +#ifdef GL_SGIX_fog_texture + CONST_CAST(GLEW_SGIX_fog_texture) = _glewSearchExtension("GL_SGIX_fog_texture", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_fog_texture) CONST_CAST(GLEW_SGIX_fog_texture) = !_glewInit_GL_SGIX_fog_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_fog_texture */ +#ifdef GL_SGIX_fragment_specular_lighting + CONST_CAST(GLEW_SGIX_fragment_specular_lighting) = _glewSearchExtension("GL_SGIX_fragment_specular_lighting", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_fragment_specular_lighting) CONST_CAST(GLEW_SGIX_fragment_specular_lighting) = !_glewInit_GL_SGIX_fragment_specular_lighting(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_fragment_specular_lighting */ +#ifdef GL_SGIX_framezoom + CONST_CAST(GLEW_SGIX_framezoom) = _glewSearchExtension("GL_SGIX_framezoom", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_framezoom) CONST_CAST(GLEW_SGIX_framezoom) = !_glewInit_GL_SGIX_framezoom(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_framezoom */ +#ifdef GL_SGIX_interlace + CONST_CAST(GLEW_SGIX_interlace) = _glewSearchExtension("GL_SGIX_interlace", extStart, extEnd); +#endif /* GL_SGIX_interlace */ +#ifdef GL_SGIX_ir_instrument1 + CONST_CAST(GLEW_SGIX_ir_instrument1) = _glewSearchExtension("GL_SGIX_ir_instrument1", extStart, extEnd); +#endif /* GL_SGIX_ir_instrument1 */ +#ifdef GL_SGIX_list_priority + CONST_CAST(GLEW_SGIX_list_priority) = _glewSearchExtension("GL_SGIX_list_priority", extStart, extEnd); +#endif /* GL_SGIX_list_priority */ +#ifdef GL_SGIX_pixel_texture + CONST_CAST(GLEW_SGIX_pixel_texture) = _glewSearchExtension("GL_SGIX_pixel_texture", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_pixel_texture) CONST_CAST(GLEW_SGIX_pixel_texture) = !_glewInit_GL_SGIX_pixel_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_pixel_texture */ +#ifdef GL_SGIX_pixel_texture_bits + CONST_CAST(GLEW_SGIX_pixel_texture_bits) = _glewSearchExtension("GL_SGIX_pixel_texture_bits", extStart, extEnd); +#endif /* GL_SGIX_pixel_texture_bits */ +#ifdef GL_SGIX_reference_plane + CONST_CAST(GLEW_SGIX_reference_plane) = _glewSearchExtension("GL_SGIX_reference_plane", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_reference_plane) CONST_CAST(GLEW_SGIX_reference_plane) = !_glewInit_GL_SGIX_reference_plane(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_reference_plane */ +#ifdef GL_SGIX_resample + CONST_CAST(GLEW_SGIX_resample) = _glewSearchExtension("GL_SGIX_resample", extStart, extEnd); +#endif /* GL_SGIX_resample */ +#ifdef GL_SGIX_shadow + CONST_CAST(GLEW_SGIX_shadow) = _glewSearchExtension("GL_SGIX_shadow", extStart, extEnd); +#endif /* GL_SGIX_shadow */ +#ifdef GL_SGIX_shadow_ambient + CONST_CAST(GLEW_SGIX_shadow_ambient) = _glewSearchExtension("GL_SGIX_shadow_ambient", extStart, extEnd); +#endif /* GL_SGIX_shadow_ambient */ +#ifdef GL_SGIX_sprite + CONST_CAST(GLEW_SGIX_sprite) = _glewSearchExtension("GL_SGIX_sprite", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_sprite) CONST_CAST(GLEW_SGIX_sprite) = !_glewInit_GL_SGIX_sprite(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_sprite */ +#ifdef GL_SGIX_tag_sample_buffer + CONST_CAST(GLEW_SGIX_tag_sample_buffer) = _glewSearchExtension("GL_SGIX_tag_sample_buffer", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_tag_sample_buffer) CONST_CAST(GLEW_SGIX_tag_sample_buffer) = !_glewInit_GL_SGIX_tag_sample_buffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGIX_tag_sample_buffer */ +#ifdef GL_SGIX_texture_add_env + CONST_CAST(GLEW_SGIX_texture_add_env) = _glewSearchExtension("GL_SGIX_texture_add_env", extStart, extEnd); +#endif /* GL_SGIX_texture_add_env */ +#ifdef GL_SGIX_texture_coordinate_clamp + CONST_CAST(GLEW_SGIX_texture_coordinate_clamp) = _glewSearchExtension("GL_SGIX_texture_coordinate_clamp", extStart, extEnd); +#endif /* GL_SGIX_texture_coordinate_clamp */ +#ifdef GL_SGIX_texture_lod_bias + CONST_CAST(GLEW_SGIX_texture_lod_bias) = _glewSearchExtension("GL_SGIX_texture_lod_bias", extStart, extEnd); +#endif /* GL_SGIX_texture_lod_bias */ +#ifdef GL_SGIX_texture_multi_buffer + CONST_CAST(GLEW_SGIX_texture_multi_buffer) = _glewSearchExtension("GL_SGIX_texture_multi_buffer", extStart, extEnd); +#endif /* GL_SGIX_texture_multi_buffer */ +#ifdef GL_SGIX_texture_range + CONST_CAST(GLEW_SGIX_texture_range) = _glewSearchExtension("GL_SGIX_texture_range", extStart, extEnd); +#endif /* GL_SGIX_texture_range */ +#ifdef GL_SGIX_texture_scale_bias + CONST_CAST(GLEW_SGIX_texture_scale_bias) = _glewSearchExtension("GL_SGIX_texture_scale_bias", extStart, extEnd); +#endif /* GL_SGIX_texture_scale_bias */ +#ifdef GL_SGIX_vertex_preclip + CONST_CAST(GLEW_SGIX_vertex_preclip) = _glewSearchExtension("GL_SGIX_vertex_preclip", extStart, extEnd); +#endif /* GL_SGIX_vertex_preclip */ +#ifdef GL_SGIX_vertex_preclip_hint + CONST_CAST(GLEW_SGIX_vertex_preclip_hint) = _glewSearchExtension("GL_SGIX_vertex_preclip_hint", extStart, extEnd); +#endif /* GL_SGIX_vertex_preclip_hint */ +#ifdef GL_SGIX_ycrcb + CONST_CAST(GLEW_SGIX_ycrcb) = _glewSearchExtension("GL_SGIX_ycrcb", extStart, extEnd); +#endif /* GL_SGIX_ycrcb */ +#ifdef GL_SGI_color_matrix + CONST_CAST(GLEW_SGI_color_matrix) = _glewSearchExtension("GL_SGI_color_matrix", extStart, extEnd); +#endif /* GL_SGI_color_matrix */ +#ifdef GL_SGI_color_table + CONST_CAST(GLEW_SGI_color_table) = _glewSearchExtension("GL_SGI_color_table", extStart, extEnd); + if (glewExperimental || GLEW_SGI_color_table) CONST_CAST(GLEW_SGI_color_table) = !_glewInit_GL_SGI_color_table(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SGI_color_table */ +#ifdef GL_SGI_texture_color_table + CONST_CAST(GLEW_SGI_texture_color_table) = _glewSearchExtension("GL_SGI_texture_color_table", extStart, extEnd); +#endif /* GL_SGI_texture_color_table */ +#ifdef GL_SUNX_constant_data + CONST_CAST(GLEW_SUNX_constant_data) = _glewSearchExtension("GL_SUNX_constant_data", extStart, extEnd); + if (glewExperimental || GLEW_SUNX_constant_data) CONST_CAST(GLEW_SUNX_constant_data) = !_glewInit_GL_SUNX_constant_data(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SUNX_constant_data */ +#ifdef GL_SUN_convolution_border_modes + CONST_CAST(GLEW_SUN_convolution_border_modes) = _glewSearchExtension("GL_SUN_convolution_border_modes", extStart, extEnd); +#endif /* GL_SUN_convolution_border_modes */ +#ifdef GL_SUN_global_alpha + CONST_CAST(GLEW_SUN_global_alpha) = _glewSearchExtension("GL_SUN_global_alpha", extStart, extEnd); + if (glewExperimental || GLEW_SUN_global_alpha) CONST_CAST(GLEW_SUN_global_alpha) = !_glewInit_GL_SUN_global_alpha(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SUN_global_alpha */ +#ifdef GL_SUN_mesh_array + CONST_CAST(GLEW_SUN_mesh_array) = _glewSearchExtension("GL_SUN_mesh_array", extStart, extEnd); +#endif /* GL_SUN_mesh_array */ +#ifdef GL_SUN_read_video_pixels + CONST_CAST(GLEW_SUN_read_video_pixels) = _glewSearchExtension("GL_SUN_read_video_pixels", extStart, extEnd); + if (glewExperimental || GLEW_SUN_read_video_pixels) CONST_CAST(GLEW_SUN_read_video_pixels) = !_glewInit_GL_SUN_read_video_pixels(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SUN_read_video_pixels */ +#ifdef GL_SUN_slice_accum + CONST_CAST(GLEW_SUN_slice_accum) = _glewSearchExtension("GL_SUN_slice_accum", extStart, extEnd); +#endif /* GL_SUN_slice_accum */ +#ifdef GL_SUN_triangle_list + CONST_CAST(GLEW_SUN_triangle_list) = _glewSearchExtension("GL_SUN_triangle_list", extStart, extEnd); + if (glewExperimental || GLEW_SUN_triangle_list) CONST_CAST(GLEW_SUN_triangle_list) = !_glewInit_GL_SUN_triangle_list(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SUN_triangle_list */ +#ifdef GL_SUN_vertex + CONST_CAST(GLEW_SUN_vertex) = _glewSearchExtension("GL_SUN_vertex", extStart, extEnd); + if (glewExperimental || GLEW_SUN_vertex) CONST_CAST(GLEW_SUN_vertex) = !_glewInit_GL_SUN_vertex(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_SUN_vertex */ +#ifdef GL_WIN_phong_shading + CONST_CAST(GLEW_WIN_phong_shading) = _glewSearchExtension("GL_WIN_phong_shading", extStart, extEnd); +#endif /* GL_WIN_phong_shading */ +#ifdef GL_WIN_specular_fog + CONST_CAST(GLEW_WIN_specular_fog) = _glewSearchExtension("GL_WIN_specular_fog", extStart, extEnd); +#endif /* GL_WIN_specular_fog */ +#ifdef GL_WIN_swap_hint + CONST_CAST(GLEW_WIN_swap_hint) = _glewSearchExtension("GL_WIN_swap_hint", extStart, extEnd); + if (glewExperimental || GLEW_WIN_swap_hint) CONST_CAST(GLEW_WIN_swap_hint) = !_glewInit_GL_WIN_swap_hint(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_WIN_swap_hint */ + + return GLEW_OK; +} + + +#if defined(_WIN32) + +#if !defined(GLEW_MX) + +PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL = NULL; + +PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD = NULL; +PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD = NULL; +PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD = NULL; +PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD = NULL; +PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD = NULL; +PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD = NULL; +PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD = NULL; +PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD = NULL; +PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD = NULL; + +PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB = NULL; +PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB = NULL; +PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB = NULL; +PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB = NULL; + +PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB = NULL; + +PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB = NULL; + +PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB = NULL; +PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB = NULL; + +PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB = NULL; +PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB = NULL; +PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB = NULL; +PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB = NULL; +PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB = NULL; + +PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB = NULL; +PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB = NULL; +PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB = NULL; + +PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB = NULL; +PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB = NULL; +PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB = NULL; + +PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT = NULL; +PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT = NULL; +PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT = NULL; +PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT = NULL; + +PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT = NULL; + +PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT = NULL; +PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT = NULL; + +PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT = NULL; +PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT = NULL; +PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT = NULL; +PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT = NULL; +PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT = NULL; + +PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT = NULL; +PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT = NULL; +PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT = NULL; + +PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT = NULL; +PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT = NULL; + +PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D = NULL; +PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D = NULL; + +PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D = NULL; +PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D = NULL; +PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D = NULL; +PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D = NULL; + +PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D = NULL; +PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D = NULL; +PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D = NULL; +PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D = NULL; +PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D = NULL; +PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D = NULL; +PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D = NULL; +PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D = NULL; +PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D = NULL; +PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D = NULL; +PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D = NULL; +PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D = NULL; + +PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D = NULL; +PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D = NULL; +PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D = NULL; +PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D = NULL; + +PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D = NULL; +PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D = NULL; +PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D = NULL; +PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D = NULL; + +PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D = NULL; +PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D = NULL; +PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D = NULL; +PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D = NULL; + +PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV = NULL; +PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV = NULL; +PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV = NULL; +PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV = NULL; +PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV = NULL; +PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV = NULL; +PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV = NULL; +PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV = NULL; + +PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV = NULL; + +PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV = NULL; +PFNWGLDELETEDCNVPROC __wglewDeleteDCNV = NULL; +PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV = NULL; +PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV = NULL; +PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV = NULL; + +PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV = NULL; +PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV = NULL; +PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV = NULL; + +PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV = NULL; +PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV = NULL; +PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV = NULL; +PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV = NULL; +PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV = NULL; +PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV = NULL; + +PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV = NULL; +PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV = NULL; + +PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV = NULL; +PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV = NULL; +PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV = NULL; +PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV = NULL; +PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV = NULL; + +PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV = NULL; +PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV = NULL; +PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV = NULL; +PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV = NULL; +PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV = NULL; +PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV = NULL; + +PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML = NULL; +PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML = NULL; +PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML = NULL; +PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML = NULL; +PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML = NULL; +PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML = NULL; +GLboolean __WGLEW_3DFX_multisample = GL_FALSE; +GLboolean __WGLEW_3DL_stereo_control = GL_FALSE; +GLboolean __WGLEW_AMD_gpu_association = GL_FALSE; +GLboolean __WGLEW_ARB_buffer_region = GL_FALSE; +GLboolean __WGLEW_ARB_create_context = GL_FALSE; +GLboolean __WGLEW_ARB_create_context_profile = GL_FALSE; +GLboolean __WGLEW_ARB_create_context_robustness = GL_FALSE; +GLboolean __WGLEW_ARB_extensions_string = GL_FALSE; +GLboolean __WGLEW_ARB_framebuffer_sRGB = GL_FALSE; +GLboolean __WGLEW_ARB_make_current_read = GL_FALSE; +GLboolean __WGLEW_ARB_multisample = GL_FALSE; +GLboolean __WGLEW_ARB_pbuffer = GL_FALSE; +GLboolean __WGLEW_ARB_pixel_format = GL_FALSE; +GLboolean __WGLEW_ARB_pixel_format_float = GL_FALSE; +GLboolean __WGLEW_ARB_render_texture = GL_FALSE; +GLboolean __WGLEW_ATI_pixel_format_float = GL_FALSE; +GLboolean __WGLEW_ATI_render_texture_rectangle = GL_FALSE; +GLboolean __WGLEW_EXT_create_context_es2_profile = GL_FALSE; +GLboolean __WGLEW_EXT_depth_float = GL_FALSE; +GLboolean __WGLEW_EXT_display_color_table = GL_FALSE; +GLboolean __WGLEW_EXT_extensions_string = GL_FALSE; +GLboolean __WGLEW_EXT_framebuffer_sRGB = GL_FALSE; +GLboolean __WGLEW_EXT_make_current_read = GL_FALSE; +GLboolean __WGLEW_EXT_multisample = GL_FALSE; +GLboolean __WGLEW_EXT_pbuffer = GL_FALSE; +GLboolean __WGLEW_EXT_pixel_format = GL_FALSE; +GLboolean __WGLEW_EXT_pixel_format_packed_float = GL_FALSE; +GLboolean __WGLEW_EXT_swap_control = GL_FALSE; +GLboolean __WGLEW_I3D_digital_video_control = GL_FALSE; +GLboolean __WGLEW_I3D_gamma = GL_FALSE; +GLboolean __WGLEW_I3D_genlock = GL_FALSE; +GLboolean __WGLEW_I3D_image_buffer = GL_FALSE; +GLboolean __WGLEW_I3D_swap_frame_lock = GL_FALSE; +GLboolean __WGLEW_I3D_swap_frame_usage = GL_FALSE; +GLboolean __WGLEW_NV_DX_interop = GL_FALSE; +GLboolean __WGLEW_NV_copy_image = GL_FALSE; +GLboolean __WGLEW_NV_float_buffer = GL_FALSE; +GLboolean __WGLEW_NV_gpu_affinity = GL_FALSE; +GLboolean __WGLEW_NV_multisample_coverage = GL_FALSE; +GLboolean __WGLEW_NV_present_video = GL_FALSE; +GLboolean __WGLEW_NV_render_depth_texture = GL_FALSE; +GLboolean __WGLEW_NV_render_texture_rectangle = GL_FALSE; +GLboolean __WGLEW_NV_swap_group = GL_FALSE; +GLboolean __WGLEW_NV_vertex_array_range = GL_FALSE; +GLboolean __WGLEW_NV_video_capture = GL_FALSE; +GLboolean __WGLEW_NV_video_output = GL_FALSE; +GLboolean __WGLEW_OML_sync_control = GL_FALSE; + +#endif /* !GLEW_MX */ + +#ifdef WGL_3DFX_multisample + +#endif /* WGL_3DFX_multisample */ + +#ifdef WGL_3DL_stereo_control + +static GLboolean _glewInit_WGL_3DL_stereo_control (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglSetStereoEmitterState3DL = (PFNWGLSETSTEREOEMITTERSTATE3DLPROC)glewGetProcAddress((const GLubyte*)"wglSetStereoEmitterState3DL")) == NULL) || r; + + return r; +} + +#endif /* WGL_3DL_stereo_control */ + +#ifdef WGL_AMD_gpu_association + +static GLboolean _glewInit_WGL_AMD_gpu_association (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBlitContextFramebufferAMD = (PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC)glewGetProcAddress((const GLubyte*)"wglBlitContextFramebufferAMD")) == NULL) || r; + r = ((wglCreateAssociatedContextAMD = (PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"wglCreateAssociatedContextAMD")) == NULL) || r; + r = ((wglCreateAssociatedContextAttribsAMD = (PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC)glewGetProcAddress((const GLubyte*)"wglCreateAssociatedContextAttribsAMD")) == NULL) || r; + r = ((wglDeleteAssociatedContextAMD = (PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"wglDeleteAssociatedContextAMD")) == NULL) || r; + r = ((wglGetContextGPUIDAMD = (PFNWGLGETCONTEXTGPUIDAMDPROC)glewGetProcAddress((const GLubyte*)"wglGetContextGPUIDAMD")) == NULL) || r; + r = ((wglGetCurrentAssociatedContextAMD = (PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"wglGetCurrentAssociatedContextAMD")) == NULL) || r; + r = ((wglGetGPUIDsAMD = (PFNWGLGETGPUIDSAMDPROC)glewGetProcAddress((const GLubyte*)"wglGetGPUIDsAMD")) == NULL) || r; + r = ((wglGetGPUInfoAMD = (PFNWGLGETGPUINFOAMDPROC)glewGetProcAddress((const GLubyte*)"wglGetGPUInfoAMD")) == NULL) || r; + r = ((wglMakeAssociatedContextCurrentAMD = (PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC)glewGetProcAddress((const GLubyte*)"wglMakeAssociatedContextCurrentAMD")) == NULL) || r; + + return r; +} + +#endif /* WGL_AMD_gpu_association */ + +#ifdef WGL_ARB_buffer_region + +static GLboolean _glewInit_WGL_ARB_buffer_region (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglCreateBufferRegionARB = (PFNWGLCREATEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglCreateBufferRegionARB")) == NULL) || r; + r = ((wglDeleteBufferRegionARB = (PFNWGLDELETEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglDeleteBufferRegionARB")) == NULL) || r; + r = ((wglRestoreBufferRegionARB = (PFNWGLRESTOREBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglRestoreBufferRegionARB")) == NULL) || r; + r = ((wglSaveBufferRegionARB = (PFNWGLSAVEBUFFERREGIONARBPROC)glewGetProcAddress((const GLubyte*)"wglSaveBufferRegionARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_buffer_region */ + +#ifdef WGL_ARB_create_context + +static GLboolean _glewInit_WGL_ARB_create_context (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)glewGetProcAddress((const GLubyte*)"wglCreateContextAttribsARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_create_context */ + +#ifdef WGL_ARB_create_context_profile + +#endif /* WGL_ARB_create_context_profile */ + +#ifdef WGL_ARB_create_context_robustness + +#endif /* WGL_ARB_create_context_robustness */ + +#ifdef WGL_ARB_extensions_string + +static GLboolean _glewInit_WGL_ARB_extensions_string (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_extensions_string */ + +#ifdef WGL_ARB_framebuffer_sRGB + +#endif /* WGL_ARB_framebuffer_sRGB */ + +#ifdef WGL_ARB_make_current_read + +static GLboolean _glewInit_WGL_ARB_make_current_read (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetCurrentReadDCARB = (PFNWGLGETCURRENTREADDCARBPROC)glewGetProcAddress((const GLubyte*)"wglGetCurrentReadDCARB")) == NULL) || r; + r = ((wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)glewGetProcAddress((const GLubyte*)"wglMakeContextCurrentARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_make_current_read */ + +#ifdef WGL_ARB_multisample + +#endif /* WGL_ARB_multisample */ + +#ifdef WGL_ARB_pbuffer + +static GLboolean _glewInit_WGL_ARB_pbuffer (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglCreatePbufferARB")) == NULL) || r; + r = ((wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglDestroyPbufferARB")) == NULL) || r; + r = ((wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPbufferDCARB")) == NULL) || r; + r = ((wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC)glewGetProcAddress((const GLubyte*)"wglQueryPbufferARB")) == NULL) || r; + r = ((wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)glewGetProcAddress((const GLubyte*)"wglReleasePbufferDCARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_pbuffer */ + +#ifdef WGL_ARB_pixel_format + +static GLboolean _glewInit_WGL_ARB_pixel_format (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)glewGetProcAddress((const GLubyte*)"wglChoosePixelFormatARB")) == NULL) || r; + r = ((wglGetPixelFormatAttribfvARB = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribfvARB")) == NULL) || r; + r = ((wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribivARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_pixel_format */ + +#ifdef WGL_ARB_pixel_format_float + +#endif /* WGL_ARB_pixel_format_float */ + +#ifdef WGL_ARB_render_texture + +static GLboolean _glewInit_WGL_ARB_render_texture (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBindTexImageARB = (PFNWGLBINDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"wglBindTexImageARB")) == NULL) || r; + r = ((wglReleaseTexImageARB = (PFNWGLRELEASETEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"wglReleaseTexImageARB")) == NULL) || r; + r = ((wglSetPbufferAttribARB = (PFNWGLSETPBUFFERATTRIBARBPROC)glewGetProcAddress((const GLubyte*)"wglSetPbufferAttribARB")) == NULL) || r; + + return r; +} + +#endif /* WGL_ARB_render_texture */ + +#ifdef WGL_ATI_pixel_format_float + +#endif /* WGL_ATI_pixel_format_float */ + +#ifdef WGL_ATI_render_texture_rectangle + +#endif /* WGL_ATI_render_texture_rectangle */ + +#ifdef WGL_EXT_create_context_es2_profile + +#endif /* WGL_EXT_create_context_es2_profile */ + +#ifdef WGL_EXT_depth_float + +#endif /* WGL_EXT_depth_float */ + +#ifdef WGL_EXT_display_color_table + +static GLboolean _glewInit_WGL_EXT_display_color_table (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBindDisplayColorTableEXT = (PFNWGLBINDDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglBindDisplayColorTableEXT")) == NULL) || r; + r = ((wglCreateDisplayColorTableEXT = (PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglCreateDisplayColorTableEXT")) == NULL) || r; + r = ((wglDestroyDisplayColorTableEXT = (PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglDestroyDisplayColorTableEXT")) == NULL) || r; + r = ((wglLoadDisplayColorTableEXT = (PFNWGLLOADDISPLAYCOLORTABLEEXTPROC)glewGetProcAddress((const GLubyte*)"wglLoadDisplayColorTableEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_display_color_table */ + +#ifdef WGL_EXT_extensions_string + +static GLboolean _glewInit_WGL_EXT_extensions_string (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_extensions_string */ + +#ifdef WGL_EXT_framebuffer_sRGB + +#endif /* WGL_EXT_framebuffer_sRGB */ + +#ifdef WGL_EXT_make_current_read + +static GLboolean _glewInit_WGL_EXT_make_current_read (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetCurrentReadDCEXT = (PFNWGLGETCURRENTREADDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetCurrentReadDCEXT")) == NULL) || r; + r = ((wglMakeContextCurrentEXT = (PFNWGLMAKECONTEXTCURRENTEXTPROC)glewGetProcAddress((const GLubyte*)"wglMakeContextCurrentEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_make_current_read */ + +#ifdef WGL_EXT_multisample + +#endif /* WGL_EXT_multisample */ + +#ifdef WGL_EXT_pbuffer + +static GLboolean _glewInit_WGL_EXT_pbuffer (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglCreatePbufferEXT = (PFNWGLCREATEPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglCreatePbufferEXT")) == NULL) || r; + r = ((wglDestroyPbufferEXT = (PFNWGLDESTROYPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglDestroyPbufferEXT")) == NULL) || r; + r = ((wglGetPbufferDCEXT = (PFNWGLGETPBUFFERDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPbufferDCEXT")) == NULL) || r; + r = ((wglQueryPbufferEXT = (PFNWGLQUERYPBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"wglQueryPbufferEXT")) == NULL) || r; + r = ((wglReleasePbufferDCEXT = (PFNWGLRELEASEPBUFFERDCEXTPROC)glewGetProcAddress((const GLubyte*)"wglReleasePbufferDCEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_pbuffer */ + +#ifdef WGL_EXT_pixel_format + +static GLboolean _glewInit_WGL_EXT_pixel_format (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglChoosePixelFormatEXT = (PFNWGLCHOOSEPIXELFORMATEXTPROC)glewGetProcAddress((const GLubyte*)"wglChoosePixelFormatEXT")) == NULL) || r; + r = ((wglGetPixelFormatAttribfvEXT = (PFNWGLGETPIXELFORMATATTRIBFVEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribfvEXT")) == NULL) || r; + r = ((wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetPixelFormatAttribivEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_pixel_format */ + +#ifdef WGL_EXT_pixel_format_packed_float + +#endif /* WGL_EXT_pixel_format_packed_float */ + +#ifdef WGL_EXT_swap_control + +static GLboolean _glewInit_WGL_EXT_swap_control (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetSwapIntervalEXT")) == NULL) || r; + r = ((wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)glewGetProcAddress((const GLubyte*)"wglSwapIntervalEXT")) == NULL) || r; + + return r; +} + +#endif /* WGL_EXT_swap_control */ + +#ifdef WGL_I3D_digital_video_control + +static GLboolean _glewInit_WGL_I3D_digital_video_control (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetDigitalVideoParametersI3D = (PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetDigitalVideoParametersI3D")) == NULL) || r; + r = ((wglSetDigitalVideoParametersI3D = (PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetDigitalVideoParametersI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_digital_video_control */ + +#ifdef WGL_I3D_gamma + +static GLboolean _glewInit_WGL_I3D_gamma (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetGammaTableI3D = (PFNWGLGETGAMMATABLEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGammaTableI3D")) == NULL) || r; + r = ((wglGetGammaTableParametersI3D = (PFNWGLGETGAMMATABLEPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGammaTableParametersI3D")) == NULL) || r; + r = ((wglSetGammaTableI3D = (PFNWGLSETGAMMATABLEI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetGammaTableI3D")) == NULL) || r; + r = ((wglSetGammaTableParametersI3D = (PFNWGLSETGAMMATABLEPARAMETERSI3DPROC)glewGetProcAddress((const GLubyte*)"wglSetGammaTableParametersI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_gamma */ + +#ifdef WGL_I3D_genlock + +static GLboolean _glewInit_WGL_I3D_genlock (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglDisableGenlockI3D = (PFNWGLDISABLEGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglDisableGenlockI3D")) == NULL) || r; + r = ((wglEnableGenlockI3D = (PFNWGLENABLEGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglEnableGenlockI3D")) == NULL) || r; + r = ((wglGenlockSampleRateI3D = (PFNWGLGENLOCKSAMPLERATEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSampleRateI3D")) == NULL) || r; + r = ((wglGenlockSourceDelayI3D = (PFNWGLGENLOCKSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceDelayI3D")) == NULL) || r; + r = ((wglGenlockSourceEdgeI3D = (PFNWGLGENLOCKSOURCEEDGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceEdgeI3D")) == NULL) || r; + r = ((wglGenlockSourceI3D = (PFNWGLGENLOCKSOURCEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGenlockSourceI3D")) == NULL) || r; + r = ((wglGetGenlockSampleRateI3D = (PFNWGLGETGENLOCKSAMPLERATEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSampleRateI3D")) == NULL) || r; + r = ((wglGetGenlockSourceDelayI3D = (PFNWGLGETGENLOCKSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceDelayI3D")) == NULL) || r; + r = ((wglGetGenlockSourceEdgeI3D = (PFNWGLGETGENLOCKSOURCEEDGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceEdgeI3D")) == NULL) || r; + r = ((wglGetGenlockSourceI3D = (PFNWGLGETGENLOCKSOURCEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetGenlockSourceI3D")) == NULL) || r; + r = ((wglIsEnabledGenlockI3D = (PFNWGLISENABLEDGENLOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglIsEnabledGenlockI3D")) == NULL) || r; + r = ((wglQueryGenlockMaxSourceDelayI3D = (PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryGenlockMaxSourceDelayI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_genlock */ + +#ifdef WGL_I3D_image_buffer + +static GLboolean _glewInit_WGL_I3D_image_buffer (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglAssociateImageBufferEventsI3D = (PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC)glewGetProcAddress((const GLubyte*)"wglAssociateImageBufferEventsI3D")) == NULL) || r; + r = ((wglCreateImageBufferI3D = (PFNWGLCREATEIMAGEBUFFERI3DPROC)glewGetProcAddress((const GLubyte*)"wglCreateImageBufferI3D")) == NULL) || r; + r = ((wglDestroyImageBufferI3D = (PFNWGLDESTROYIMAGEBUFFERI3DPROC)glewGetProcAddress((const GLubyte*)"wglDestroyImageBufferI3D")) == NULL) || r; + r = ((wglReleaseImageBufferEventsI3D = (PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC)glewGetProcAddress((const GLubyte*)"wglReleaseImageBufferEventsI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_image_buffer */ + +#ifdef WGL_I3D_swap_frame_lock + +static GLboolean _glewInit_WGL_I3D_swap_frame_lock (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglDisableFrameLockI3D = (PFNWGLDISABLEFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglDisableFrameLockI3D")) == NULL) || r; + r = ((wglEnableFrameLockI3D = (PFNWGLENABLEFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglEnableFrameLockI3D")) == NULL) || r; + r = ((wglIsEnabledFrameLockI3D = (PFNWGLISENABLEDFRAMELOCKI3DPROC)glewGetProcAddress((const GLubyte*)"wglIsEnabledFrameLockI3D")) == NULL) || r; + r = ((wglQueryFrameLockMasterI3D = (PFNWGLQUERYFRAMELOCKMASTERI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameLockMasterI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_swap_frame_lock */ + +#ifdef WGL_I3D_swap_frame_usage + +static GLboolean _glewInit_WGL_I3D_swap_frame_usage (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBeginFrameTrackingI3D = (PFNWGLBEGINFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglBeginFrameTrackingI3D")) == NULL) || r; + r = ((wglEndFrameTrackingI3D = (PFNWGLENDFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglEndFrameTrackingI3D")) == NULL) || r; + r = ((wglGetFrameUsageI3D = (PFNWGLGETFRAMEUSAGEI3DPROC)glewGetProcAddress((const GLubyte*)"wglGetFrameUsageI3D")) == NULL) || r; + r = ((wglQueryFrameTrackingI3D = (PFNWGLQUERYFRAMETRACKINGI3DPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameTrackingI3D")) == NULL) || r; + + return r; +} + +#endif /* WGL_I3D_swap_frame_usage */ + +#ifdef WGL_NV_DX_interop + +static GLboolean _glewInit_WGL_NV_DX_interop (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglDXCloseDeviceNV = (PFNWGLDXCLOSEDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglDXCloseDeviceNV")) == NULL) || r; + r = ((wglDXLockObjectsNV = (PFNWGLDXLOCKOBJECTSNVPROC)glewGetProcAddress((const GLubyte*)"wglDXLockObjectsNV")) == NULL) || r; + r = ((wglDXObjectAccessNV = (PFNWGLDXOBJECTACCESSNVPROC)glewGetProcAddress((const GLubyte*)"wglDXObjectAccessNV")) == NULL) || r; + r = ((wglDXOpenDeviceNV = (PFNWGLDXOPENDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglDXOpenDeviceNV")) == NULL) || r; + r = ((wglDXRegisterObjectNV = (PFNWGLDXREGISTEROBJECTNVPROC)glewGetProcAddress((const GLubyte*)"wglDXRegisterObjectNV")) == NULL) || r; + r = ((wglDXSetResourceShareHandleNV = (PFNWGLDXSETRESOURCESHAREHANDLENVPROC)glewGetProcAddress((const GLubyte*)"wglDXSetResourceShareHandleNV")) == NULL) || r; + r = ((wglDXUnlockObjectsNV = (PFNWGLDXUNLOCKOBJECTSNVPROC)glewGetProcAddress((const GLubyte*)"wglDXUnlockObjectsNV")) == NULL) || r; + r = ((wglDXUnregisterObjectNV = (PFNWGLDXUNREGISTEROBJECTNVPROC)glewGetProcAddress((const GLubyte*)"wglDXUnregisterObjectNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_DX_interop */ + +#ifdef WGL_NV_copy_image + +static GLboolean _glewInit_WGL_NV_copy_image (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglCopyImageSubDataNV = (PFNWGLCOPYIMAGESUBDATANVPROC)glewGetProcAddress((const GLubyte*)"wglCopyImageSubDataNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_copy_image */ + +#ifdef WGL_NV_float_buffer + +#endif /* WGL_NV_float_buffer */ + +#ifdef WGL_NV_gpu_affinity + +static GLboolean _glewInit_WGL_NV_gpu_affinity (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglCreateAffinityDCNV = (PFNWGLCREATEAFFINITYDCNVPROC)glewGetProcAddress((const GLubyte*)"wglCreateAffinityDCNV")) == NULL) || r; + r = ((wglDeleteDCNV = (PFNWGLDELETEDCNVPROC)glewGetProcAddress((const GLubyte*)"wglDeleteDCNV")) == NULL) || r; + r = ((wglEnumGpuDevicesNV = (PFNWGLENUMGPUDEVICESNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpuDevicesNV")) == NULL) || r; + r = ((wglEnumGpusFromAffinityDCNV = (PFNWGLENUMGPUSFROMAFFINITYDCNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpusFromAffinityDCNV")) == NULL) || r; + r = ((wglEnumGpusNV = (PFNWGLENUMGPUSNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumGpusNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_gpu_affinity */ + +#ifdef WGL_NV_multisample_coverage + +#endif /* WGL_NV_multisample_coverage */ + +#ifdef WGL_NV_present_video + +static GLboolean _glewInit_WGL_NV_present_video (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBindVideoDeviceNV = (PFNWGLBINDVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglBindVideoDeviceNV")) == NULL) || r; + r = ((wglEnumerateVideoDevicesNV = (PFNWGLENUMERATEVIDEODEVICESNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumerateVideoDevicesNV")) == NULL) || r; + r = ((wglQueryCurrentContextNV = (PFNWGLQUERYCURRENTCONTEXTNVPROC)glewGetProcAddress((const GLubyte*)"wglQueryCurrentContextNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_present_video */ + +#ifdef WGL_NV_render_depth_texture + +#endif /* WGL_NV_render_depth_texture */ + +#ifdef WGL_NV_render_texture_rectangle + +#endif /* WGL_NV_render_texture_rectangle */ + +#ifdef WGL_NV_swap_group + +static GLboolean _glewInit_WGL_NV_swap_group (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBindSwapBarrierNV = (PFNWGLBINDSWAPBARRIERNVPROC)glewGetProcAddress((const GLubyte*)"wglBindSwapBarrierNV")) == NULL) || r; + r = ((wglJoinSwapGroupNV = (PFNWGLJOINSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"wglJoinSwapGroupNV")) == NULL) || r; + r = ((wglQueryFrameCountNV = (PFNWGLQUERYFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"wglQueryFrameCountNV")) == NULL) || r; + r = ((wglQueryMaxSwapGroupsNV = (PFNWGLQUERYMAXSWAPGROUPSNVPROC)glewGetProcAddress((const GLubyte*)"wglQueryMaxSwapGroupsNV")) == NULL) || r; + r = ((wglQuerySwapGroupNV = (PFNWGLQUERYSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"wglQuerySwapGroupNV")) == NULL) || r; + r = ((wglResetFrameCountNV = (PFNWGLRESETFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"wglResetFrameCountNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_swap_group */ + +#ifdef WGL_NV_vertex_array_range + +static GLboolean _glewInit_WGL_NV_vertex_array_range (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"wglAllocateMemoryNV")) == NULL) || r; + r = ((wglFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"wglFreeMemoryNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_vertex_array_range */ + +#ifdef WGL_NV_video_capture + +static GLboolean _glewInit_WGL_NV_video_capture (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBindVideoCaptureDeviceNV = (PFNWGLBINDVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglBindVideoCaptureDeviceNV")) == NULL) || r; + r = ((wglEnumerateVideoCaptureDevicesNV = (PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC)glewGetProcAddress((const GLubyte*)"wglEnumerateVideoCaptureDevicesNV")) == NULL) || r; + r = ((wglLockVideoCaptureDeviceNV = (PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglLockVideoCaptureDeviceNV")) == NULL) || r; + r = ((wglQueryVideoCaptureDeviceNV = (PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglQueryVideoCaptureDeviceNV")) == NULL) || r; + r = ((wglReleaseVideoCaptureDeviceNV = (PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglReleaseVideoCaptureDeviceNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_video_capture */ + +#ifdef WGL_NV_video_output + +static GLboolean _glewInit_WGL_NV_video_output (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglBindVideoImageNV = (PFNWGLBINDVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"wglBindVideoImageNV")) == NULL) || r; + r = ((wglGetVideoDeviceNV = (PFNWGLGETVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglGetVideoDeviceNV")) == NULL) || r; + r = ((wglGetVideoInfoNV = (PFNWGLGETVIDEOINFONVPROC)glewGetProcAddress((const GLubyte*)"wglGetVideoInfoNV")) == NULL) || r; + r = ((wglReleaseVideoDeviceNV = (PFNWGLRELEASEVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"wglReleaseVideoDeviceNV")) == NULL) || r; + r = ((wglReleaseVideoImageNV = (PFNWGLRELEASEVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"wglReleaseVideoImageNV")) == NULL) || r; + r = ((wglSendPbufferToVideoNV = (PFNWGLSENDPBUFFERTOVIDEONVPROC)glewGetProcAddress((const GLubyte*)"wglSendPbufferToVideoNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_video_output */ + +#ifdef WGL_OML_sync_control + +static GLboolean _glewInit_WGL_OML_sync_control (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglGetMscRateOML = (PFNWGLGETMSCRATEOMLPROC)glewGetProcAddress((const GLubyte*)"wglGetMscRateOML")) == NULL) || r; + r = ((wglGetSyncValuesOML = (PFNWGLGETSYNCVALUESOMLPROC)glewGetProcAddress((const GLubyte*)"wglGetSyncValuesOML")) == NULL) || r; + r = ((wglSwapBuffersMscOML = (PFNWGLSWAPBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglSwapBuffersMscOML")) == NULL) || r; + r = ((wglSwapLayerBuffersMscOML = (PFNWGLSWAPLAYERBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglSwapLayerBuffersMscOML")) == NULL) || r; + r = ((wglWaitForMscOML = (PFNWGLWAITFORMSCOMLPROC)glewGetProcAddress((const GLubyte*)"wglWaitForMscOML")) == NULL) || r; + r = ((wglWaitForSbcOML = (PFNWGLWAITFORSBCOMLPROC)glewGetProcAddress((const GLubyte*)"wglWaitForSbcOML")) == NULL) || r; + + return r; +} + +#endif /* WGL_OML_sync_control */ + +/* ------------------------------------------------------------------------- */ + +static PFNWGLGETEXTENSIONSSTRINGARBPROC _wglewGetExtensionsStringARB = NULL; +static PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglewGetExtensionsStringEXT = NULL; + +GLboolean wglewGetExtension (const char* name) +{ + const GLubyte* start; + const GLubyte* end; + if (_wglewGetExtensionsStringARB == NULL) + if (_wglewGetExtensionsStringEXT == NULL) + return GL_FALSE; + else + start = (const GLubyte*)_wglewGetExtensionsStringEXT(); + else + start = (const GLubyte*)_wglewGetExtensionsStringARB(wglGetCurrentDC()); + if (start == 0) + return GL_FALSE; + end = start + _glewStrLen(start); + return _glewSearchExtension(name, start, end); +} + +GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST) +{ + GLboolean crippled; + const GLubyte* extStart; + const GLubyte* extEnd; + /* find wgl extension string query functions */ + _wglewGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringARB"); + _wglewGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringEXT"); + /* query wgl extension string */ + if (_wglewGetExtensionsStringARB == NULL) + if (_wglewGetExtensionsStringEXT == NULL) + extStart = (const GLubyte*)""; + else + extStart = (const GLubyte*)_wglewGetExtensionsStringEXT(); + else + extStart = (const GLubyte*)_wglewGetExtensionsStringARB(wglGetCurrentDC()); + extEnd = extStart + _glewStrLen(extStart); + /* initialize extensions */ + crippled = _wglewGetExtensionsStringARB == NULL && _wglewGetExtensionsStringEXT == NULL; +#ifdef WGL_3DFX_multisample + CONST_CAST(WGLEW_3DFX_multisample) = _glewSearchExtension("WGL_3DFX_multisample", extStart, extEnd); +#endif /* WGL_3DFX_multisample */ +#ifdef WGL_3DL_stereo_control + CONST_CAST(WGLEW_3DL_stereo_control) = _glewSearchExtension("WGL_3DL_stereo_control", extStart, extEnd); + if (glewExperimental || WGLEW_3DL_stereo_control|| crippled) CONST_CAST(WGLEW_3DL_stereo_control)= !_glewInit_WGL_3DL_stereo_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_3DL_stereo_control */ +#ifdef WGL_AMD_gpu_association + CONST_CAST(WGLEW_AMD_gpu_association) = _glewSearchExtension("WGL_AMD_gpu_association", extStart, extEnd); + if (glewExperimental || WGLEW_AMD_gpu_association|| crippled) CONST_CAST(WGLEW_AMD_gpu_association)= !_glewInit_WGL_AMD_gpu_association(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_AMD_gpu_association */ +#ifdef WGL_ARB_buffer_region + CONST_CAST(WGLEW_ARB_buffer_region) = _glewSearchExtension("WGL_ARB_buffer_region", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_buffer_region|| crippled) CONST_CAST(WGLEW_ARB_buffer_region)= !_glewInit_WGL_ARB_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_buffer_region */ +#ifdef WGL_ARB_create_context + CONST_CAST(WGLEW_ARB_create_context) = _glewSearchExtension("WGL_ARB_create_context", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_create_context|| crippled) CONST_CAST(WGLEW_ARB_create_context)= !_glewInit_WGL_ARB_create_context(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_create_context */ +#ifdef WGL_ARB_create_context_profile + CONST_CAST(WGLEW_ARB_create_context_profile) = _glewSearchExtension("WGL_ARB_create_context_profile", extStart, extEnd); +#endif /* WGL_ARB_create_context_profile */ +#ifdef WGL_ARB_create_context_robustness + CONST_CAST(WGLEW_ARB_create_context_robustness) = _glewSearchExtension("WGL_ARB_create_context_robustness", extStart, extEnd); +#endif /* WGL_ARB_create_context_robustness */ +#ifdef WGL_ARB_extensions_string + CONST_CAST(WGLEW_ARB_extensions_string) = _glewSearchExtension("WGL_ARB_extensions_string", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_extensions_string|| crippled) CONST_CAST(WGLEW_ARB_extensions_string)= !_glewInit_WGL_ARB_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_extensions_string */ +#ifdef WGL_ARB_framebuffer_sRGB + CONST_CAST(WGLEW_ARB_framebuffer_sRGB) = _glewSearchExtension("WGL_ARB_framebuffer_sRGB", extStart, extEnd); +#endif /* WGL_ARB_framebuffer_sRGB */ +#ifdef WGL_ARB_make_current_read + CONST_CAST(WGLEW_ARB_make_current_read) = _glewSearchExtension("WGL_ARB_make_current_read", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_make_current_read|| crippled) CONST_CAST(WGLEW_ARB_make_current_read)= !_glewInit_WGL_ARB_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_make_current_read */ +#ifdef WGL_ARB_multisample + CONST_CAST(WGLEW_ARB_multisample) = _glewSearchExtension("WGL_ARB_multisample", extStart, extEnd); +#endif /* WGL_ARB_multisample */ +#ifdef WGL_ARB_pbuffer + CONST_CAST(WGLEW_ARB_pbuffer) = _glewSearchExtension("WGL_ARB_pbuffer", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_pbuffer|| crippled) CONST_CAST(WGLEW_ARB_pbuffer)= !_glewInit_WGL_ARB_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_pbuffer */ +#ifdef WGL_ARB_pixel_format + CONST_CAST(WGLEW_ARB_pixel_format) = _glewSearchExtension("WGL_ARB_pixel_format", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_pixel_format|| crippled) CONST_CAST(WGLEW_ARB_pixel_format)= !_glewInit_WGL_ARB_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_pixel_format */ +#ifdef WGL_ARB_pixel_format_float + CONST_CAST(WGLEW_ARB_pixel_format_float) = _glewSearchExtension("WGL_ARB_pixel_format_float", extStart, extEnd); +#endif /* WGL_ARB_pixel_format_float */ +#ifdef WGL_ARB_render_texture + CONST_CAST(WGLEW_ARB_render_texture) = _glewSearchExtension("WGL_ARB_render_texture", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_render_texture|| crippled) CONST_CAST(WGLEW_ARB_render_texture)= !_glewInit_WGL_ARB_render_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_ARB_render_texture */ +#ifdef WGL_ATI_pixel_format_float + CONST_CAST(WGLEW_ATI_pixel_format_float) = _glewSearchExtension("WGL_ATI_pixel_format_float", extStart, extEnd); +#endif /* WGL_ATI_pixel_format_float */ +#ifdef WGL_ATI_render_texture_rectangle + CONST_CAST(WGLEW_ATI_render_texture_rectangle) = _glewSearchExtension("WGL_ATI_render_texture_rectangle", extStart, extEnd); +#endif /* WGL_ATI_render_texture_rectangle */ +#ifdef WGL_EXT_create_context_es2_profile + CONST_CAST(WGLEW_EXT_create_context_es2_profile) = _glewSearchExtension("WGL_EXT_create_context_es2_profile", extStart, extEnd); +#endif /* WGL_EXT_create_context_es2_profile */ +#ifdef WGL_EXT_depth_float + CONST_CAST(WGLEW_EXT_depth_float) = _glewSearchExtension("WGL_EXT_depth_float", extStart, extEnd); +#endif /* WGL_EXT_depth_float */ +#ifdef WGL_EXT_display_color_table + CONST_CAST(WGLEW_EXT_display_color_table) = _glewSearchExtension("WGL_EXT_display_color_table", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_display_color_table|| crippled) CONST_CAST(WGLEW_EXT_display_color_table)= !_glewInit_WGL_EXT_display_color_table(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_display_color_table */ +#ifdef WGL_EXT_extensions_string + CONST_CAST(WGLEW_EXT_extensions_string) = _glewSearchExtension("WGL_EXT_extensions_string", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_extensions_string|| crippled) CONST_CAST(WGLEW_EXT_extensions_string)= !_glewInit_WGL_EXT_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_extensions_string */ +#ifdef WGL_EXT_framebuffer_sRGB + CONST_CAST(WGLEW_EXT_framebuffer_sRGB) = _glewSearchExtension("WGL_EXT_framebuffer_sRGB", extStart, extEnd); +#endif /* WGL_EXT_framebuffer_sRGB */ +#ifdef WGL_EXT_make_current_read + CONST_CAST(WGLEW_EXT_make_current_read) = _glewSearchExtension("WGL_EXT_make_current_read", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_make_current_read|| crippled) CONST_CAST(WGLEW_EXT_make_current_read)= !_glewInit_WGL_EXT_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_make_current_read */ +#ifdef WGL_EXT_multisample + CONST_CAST(WGLEW_EXT_multisample) = _glewSearchExtension("WGL_EXT_multisample", extStart, extEnd); +#endif /* WGL_EXT_multisample */ +#ifdef WGL_EXT_pbuffer + CONST_CAST(WGLEW_EXT_pbuffer) = _glewSearchExtension("WGL_EXT_pbuffer", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_pbuffer|| crippled) CONST_CAST(WGLEW_EXT_pbuffer)= !_glewInit_WGL_EXT_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_pbuffer */ +#ifdef WGL_EXT_pixel_format + CONST_CAST(WGLEW_EXT_pixel_format) = _glewSearchExtension("WGL_EXT_pixel_format", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_pixel_format|| crippled) CONST_CAST(WGLEW_EXT_pixel_format)= !_glewInit_WGL_EXT_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_pixel_format */ +#ifdef WGL_EXT_pixel_format_packed_float + CONST_CAST(WGLEW_EXT_pixel_format_packed_float) = _glewSearchExtension("WGL_EXT_pixel_format_packed_float", extStart, extEnd); +#endif /* WGL_EXT_pixel_format_packed_float */ +#ifdef WGL_EXT_swap_control + CONST_CAST(WGLEW_EXT_swap_control) = _glewSearchExtension("WGL_EXT_swap_control", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_swap_control|| crippled) CONST_CAST(WGLEW_EXT_swap_control)= !_glewInit_WGL_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_EXT_swap_control */ +#ifdef WGL_I3D_digital_video_control + CONST_CAST(WGLEW_I3D_digital_video_control) = _glewSearchExtension("WGL_I3D_digital_video_control", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_digital_video_control|| crippled) CONST_CAST(WGLEW_I3D_digital_video_control)= !_glewInit_WGL_I3D_digital_video_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_digital_video_control */ +#ifdef WGL_I3D_gamma + CONST_CAST(WGLEW_I3D_gamma) = _glewSearchExtension("WGL_I3D_gamma", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_gamma|| crippled) CONST_CAST(WGLEW_I3D_gamma)= !_glewInit_WGL_I3D_gamma(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_gamma */ +#ifdef WGL_I3D_genlock + CONST_CAST(WGLEW_I3D_genlock) = _glewSearchExtension("WGL_I3D_genlock", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_genlock|| crippled) CONST_CAST(WGLEW_I3D_genlock)= !_glewInit_WGL_I3D_genlock(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_genlock */ +#ifdef WGL_I3D_image_buffer + CONST_CAST(WGLEW_I3D_image_buffer) = _glewSearchExtension("WGL_I3D_image_buffer", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_image_buffer|| crippled) CONST_CAST(WGLEW_I3D_image_buffer)= !_glewInit_WGL_I3D_image_buffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_image_buffer */ +#ifdef WGL_I3D_swap_frame_lock + CONST_CAST(WGLEW_I3D_swap_frame_lock) = _glewSearchExtension("WGL_I3D_swap_frame_lock", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_swap_frame_lock|| crippled) CONST_CAST(WGLEW_I3D_swap_frame_lock)= !_glewInit_WGL_I3D_swap_frame_lock(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_swap_frame_lock */ +#ifdef WGL_I3D_swap_frame_usage + CONST_CAST(WGLEW_I3D_swap_frame_usage) = _glewSearchExtension("WGL_I3D_swap_frame_usage", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_swap_frame_usage|| crippled) CONST_CAST(WGLEW_I3D_swap_frame_usage)= !_glewInit_WGL_I3D_swap_frame_usage(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_I3D_swap_frame_usage */ +#ifdef WGL_NV_DX_interop + CONST_CAST(WGLEW_NV_DX_interop) = _glewSearchExtension("WGL_NV_DX_interop", extStart, extEnd); + if (glewExperimental || WGLEW_NV_DX_interop|| crippled) CONST_CAST(WGLEW_NV_DX_interop)= !_glewInit_WGL_NV_DX_interop(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_DX_interop */ +#ifdef WGL_NV_copy_image + CONST_CAST(WGLEW_NV_copy_image) = _glewSearchExtension("WGL_NV_copy_image", extStart, extEnd); + if (glewExperimental || WGLEW_NV_copy_image|| crippled) CONST_CAST(WGLEW_NV_copy_image)= !_glewInit_WGL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_copy_image */ +#ifdef WGL_NV_float_buffer + CONST_CAST(WGLEW_NV_float_buffer) = _glewSearchExtension("WGL_NV_float_buffer", extStart, extEnd); +#endif /* WGL_NV_float_buffer */ +#ifdef WGL_NV_gpu_affinity + CONST_CAST(WGLEW_NV_gpu_affinity) = _glewSearchExtension("WGL_NV_gpu_affinity", extStart, extEnd); + if (glewExperimental || WGLEW_NV_gpu_affinity|| crippled) CONST_CAST(WGLEW_NV_gpu_affinity)= !_glewInit_WGL_NV_gpu_affinity(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_gpu_affinity */ +#ifdef WGL_NV_multisample_coverage + CONST_CAST(WGLEW_NV_multisample_coverage) = _glewSearchExtension("WGL_NV_multisample_coverage", extStart, extEnd); +#endif /* WGL_NV_multisample_coverage */ +#ifdef WGL_NV_present_video + CONST_CAST(WGLEW_NV_present_video) = _glewSearchExtension("WGL_NV_present_video", extStart, extEnd); + if (glewExperimental || WGLEW_NV_present_video|| crippled) CONST_CAST(WGLEW_NV_present_video)= !_glewInit_WGL_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_present_video */ +#ifdef WGL_NV_render_depth_texture + CONST_CAST(WGLEW_NV_render_depth_texture) = _glewSearchExtension("WGL_NV_render_depth_texture", extStart, extEnd); +#endif /* WGL_NV_render_depth_texture */ +#ifdef WGL_NV_render_texture_rectangle + CONST_CAST(WGLEW_NV_render_texture_rectangle) = _glewSearchExtension("WGL_NV_render_texture_rectangle", extStart, extEnd); +#endif /* WGL_NV_render_texture_rectangle */ +#ifdef WGL_NV_swap_group + CONST_CAST(WGLEW_NV_swap_group) = _glewSearchExtension("WGL_NV_swap_group", extStart, extEnd); + if (glewExperimental || WGLEW_NV_swap_group|| crippled) CONST_CAST(WGLEW_NV_swap_group)= !_glewInit_WGL_NV_swap_group(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_swap_group */ +#ifdef WGL_NV_vertex_array_range + CONST_CAST(WGLEW_NV_vertex_array_range) = _glewSearchExtension("WGL_NV_vertex_array_range", extStart, extEnd); + if (glewExperimental || WGLEW_NV_vertex_array_range|| crippled) CONST_CAST(WGLEW_NV_vertex_array_range)= !_glewInit_WGL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_vertex_array_range */ +#ifdef WGL_NV_video_capture + CONST_CAST(WGLEW_NV_video_capture) = _glewSearchExtension("WGL_NV_video_capture", extStart, extEnd); + if (glewExperimental || WGLEW_NV_video_capture|| crippled) CONST_CAST(WGLEW_NV_video_capture)= !_glewInit_WGL_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_video_capture */ +#ifdef WGL_NV_video_output + CONST_CAST(WGLEW_NV_video_output) = _glewSearchExtension("WGL_NV_video_output", extStart, extEnd); + if (glewExperimental || WGLEW_NV_video_output|| crippled) CONST_CAST(WGLEW_NV_video_output)= !_glewInit_WGL_NV_video_output(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_video_output */ +#ifdef WGL_OML_sync_control + CONST_CAST(WGLEW_OML_sync_control) = _glewSearchExtension("WGL_OML_sync_control", extStart, extEnd); + if (glewExperimental || WGLEW_OML_sync_control|| crippled) CONST_CAST(WGLEW_OML_sync_control)= !_glewInit_WGL_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_OML_sync_control */ + + return GLEW_OK; +} + +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) + +PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay = NULL; + +PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig = NULL; +PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext = NULL; +PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer = NULL; +PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap = NULL; +PFNGLXCREATEWINDOWPROC __glewXCreateWindow = NULL; +PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer = NULL; +PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap = NULL; +PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow = NULL; +PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable = NULL; +PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib = NULL; +PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs = NULL; +PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent = NULL; +PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig = NULL; +PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent = NULL; +PFNGLXQUERYCONTEXTPROC __glewXQueryContext = NULL; +PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable = NULL; +PFNGLXSELECTEVENTPROC __glewXSelectEvent = NULL; + +PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB = NULL; + +PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI = NULL; +PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI = NULL; +PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI = NULL; + +PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT = NULL; +PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT = NULL; +PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT = NULL; +PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT = NULL; + +PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT = NULL; + +PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT = NULL; +PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT = NULL; + +PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA = NULL; + +PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA = NULL; + +PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA = NULL; + +PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA = NULL; + +PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA = NULL; + +PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV = NULL; + +PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV = NULL; +PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV = NULL; + +PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV = NULL; +PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV = NULL; +PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV = NULL; +PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV = NULL; +PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV = NULL; +PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV = NULL; + +PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV = NULL; +PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV = NULL; + +PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV = NULL; +PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV = NULL; +PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV = NULL; +PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV = NULL; +PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV = NULL; + +PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV = NULL; +PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV = NULL; +PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV = NULL; +PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV = NULL; +PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV = NULL; +PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV = NULL; + +PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML = NULL; +PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML = NULL; +PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML = NULL; +PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML = NULL; +PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML = NULL; + +PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX = NULL; +PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX = NULL; +PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX = NULL; +PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX = NULL; +PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX = NULL; +PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX = NULL; + +PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX = NULL; +PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX = NULL; +PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX = NULL; +PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX = NULL; +PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX = NULL; +PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX = NULL; +PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX = NULL; +PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX = NULL; + +PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX = NULL; +PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX = NULL; +PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX = NULL; +PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX = NULL; +PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX = NULL; + +PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX = NULL; +PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX = NULL; + +PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX = NULL; + +PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX = NULL; +PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX = NULL; +PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX = NULL; +PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX = NULL; +PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX = NULL; + +PFNGLXCUSHIONSGIPROC __glewXCushionSGI = NULL; + +PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI = NULL; +PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI = NULL; + +PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI = NULL; + +PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI = NULL; +PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI = NULL; + +PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN = NULL; + +PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN = NULL; +PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN = NULL; + +#if !defined(GLEW_MX) + +GLboolean __GLXEW_VERSION_1_0 = GL_FALSE; +GLboolean __GLXEW_VERSION_1_1 = GL_FALSE; +GLboolean __GLXEW_VERSION_1_2 = GL_FALSE; +GLboolean __GLXEW_VERSION_1_3 = GL_FALSE; +GLboolean __GLXEW_VERSION_1_4 = GL_FALSE; +GLboolean __GLXEW_3DFX_multisample = GL_FALSE; +GLboolean __GLXEW_AMD_gpu_association = GL_FALSE; +GLboolean __GLXEW_ARB_create_context = GL_FALSE; +GLboolean __GLXEW_ARB_create_context_profile = GL_FALSE; +GLboolean __GLXEW_ARB_create_context_robustness = GL_FALSE; +GLboolean __GLXEW_ARB_fbconfig_float = GL_FALSE; +GLboolean __GLXEW_ARB_framebuffer_sRGB = GL_FALSE; +GLboolean __GLXEW_ARB_get_proc_address = GL_FALSE; +GLboolean __GLXEW_ARB_multisample = GL_FALSE; +GLboolean __GLXEW_ARB_vertex_buffer_object = GL_FALSE; +GLboolean __GLXEW_ATI_pixel_format_float = GL_FALSE; +GLboolean __GLXEW_ATI_render_texture = GL_FALSE; +GLboolean __GLXEW_EXT_create_context_es2_profile = GL_FALSE; +GLboolean __GLXEW_EXT_fbconfig_packed_float = GL_FALSE; +GLboolean __GLXEW_EXT_framebuffer_sRGB = GL_FALSE; +GLboolean __GLXEW_EXT_import_context = GL_FALSE; +GLboolean __GLXEW_EXT_scene_marker = GL_FALSE; +GLboolean __GLXEW_EXT_swap_control = GL_FALSE; +GLboolean __GLXEW_EXT_texture_from_pixmap = GL_FALSE; +GLboolean __GLXEW_EXT_visual_info = GL_FALSE; +GLboolean __GLXEW_EXT_visual_rating = GL_FALSE; +GLboolean __GLXEW_INTEL_swap_event = GL_FALSE; +GLboolean __GLXEW_MESA_agp_offset = GL_FALSE; +GLboolean __GLXEW_MESA_copy_sub_buffer = GL_FALSE; +GLboolean __GLXEW_MESA_pixmap_colormap = GL_FALSE; +GLboolean __GLXEW_MESA_release_buffers = GL_FALSE; +GLboolean __GLXEW_MESA_set_3dfx_mode = GL_FALSE; +GLboolean __GLXEW_NV_copy_image = GL_FALSE; +GLboolean __GLXEW_NV_float_buffer = GL_FALSE; +GLboolean __GLXEW_NV_multisample_coverage = GL_FALSE; +GLboolean __GLXEW_NV_present_video = GL_FALSE; +GLboolean __GLXEW_NV_swap_group = GL_FALSE; +GLboolean __GLXEW_NV_vertex_array_range = GL_FALSE; +GLboolean __GLXEW_NV_video_capture = GL_FALSE; +GLboolean __GLXEW_NV_video_output = GL_FALSE; +GLboolean __GLXEW_OML_swap_method = GL_FALSE; +GLboolean __GLXEW_OML_sync_control = GL_FALSE; +GLboolean __GLXEW_SGIS_blended_overlay = GL_FALSE; +GLboolean __GLXEW_SGIS_color_range = GL_FALSE; +GLboolean __GLXEW_SGIS_multisample = GL_FALSE; +GLboolean __GLXEW_SGIS_shared_multisample = GL_FALSE; +GLboolean __GLXEW_SGIX_fbconfig = GL_FALSE; +GLboolean __GLXEW_SGIX_hyperpipe = GL_FALSE; +GLboolean __GLXEW_SGIX_pbuffer = GL_FALSE; +GLboolean __GLXEW_SGIX_swap_barrier = GL_FALSE; +GLboolean __GLXEW_SGIX_swap_group = GL_FALSE; +GLboolean __GLXEW_SGIX_video_resize = GL_FALSE; +GLboolean __GLXEW_SGIX_visual_select_group = GL_FALSE; +GLboolean __GLXEW_SGI_cushion = GL_FALSE; +GLboolean __GLXEW_SGI_make_current_read = GL_FALSE; +GLboolean __GLXEW_SGI_swap_control = GL_FALSE; +GLboolean __GLXEW_SGI_video_sync = GL_FALSE; +GLboolean __GLXEW_SUN_get_transparent_index = GL_FALSE; +GLboolean __GLXEW_SUN_video_resize = GL_FALSE; + +#endif /* !GLEW_MX */ + +#ifdef GLX_VERSION_1_2 + +static GLboolean _glewInit_GLX_VERSION_1_2 (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetCurrentDisplay = (PFNGLXGETCURRENTDISPLAYPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentDisplay")) == NULL) || r; + + return r; +} + +#endif /* GLX_VERSION_1_2 */ + +#ifdef GLX_VERSION_1_3 + +static GLboolean _glewInit_GLX_VERSION_1_3 (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glewGetProcAddress((const GLubyte*)"glXChooseFBConfig")) == NULL) || r; + r = ((glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC)glewGetProcAddress((const GLubyte*)"glXCreateNewContext")) == NULL) || r; + r = ((glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glXCreatePbuffer")) == NULL) || r; + r = ((glXCreatePixmap = (PFNGLXCREATEPIXMAPPROC)glewGetProcAddress((const GLubyte*)"glXCreatePixmap")) == NULL) || r; + r = ((glXCreateWindow = (PFNGLXCREATEWINDOWPROC)glewGetProcAddress((const GLubyte*)"glXCreateWindow")) == NULL) || r; + r = ((glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC)glewGetProcAddress((const GLubyte*)"glXDestroyPbuffer")) == NULL) || r; + r = ((glXDestroyPixmap = (PFNGLXDESTROYPIXMAPPROC)glewGetProcAddress((const GLubyte*)"glXDestroyPixmap")) == NULL) || r; + r = ((glXDestroyWindow = (PFNGLXDESTROYWINDOWPROC)glewGetProcAddress((const GLubyte*)"glXDestroyWindow")) == NULL) || r; + r = ((glXGetCurrentReadDrawable = (PFNGLXGETCURRENTREADDRAWABLEPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentReadDrawable")) == NULL) || r; + r = ((glXGetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigAttrib")) == NULL) || r; + r = ((glXGetFBConfigs = (PFNGLXGETFBCONFIGSPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigs")) == NULL) || r; + r = ((glXGetSelectedEvent = (PFNGLXGETSELECTEDEVENTPROC)glewGetProcAddress((const GLubyte*)"glXGetSelectedEvent")) == NULL) || r; + r = ((glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)glewGetProcAddress((const GLubyte*)"glXGetVisualFromFBConfig")) == NULL) || r; + r = ((glXMakeContextCurrent = (PFNGLXMAKECONTEXTCURRENTPROC)glewGetProcAddress((const GLubyte*)"glXMakeContextCurrent")) == NULL) || r; + r = ((glXQueryContext = (PFNGLXQUERYCONTEXTPROC)glewGetProcAddress((const GLubyte*)"glXQueryContext")) == NULL) || r; + r = ((glXQueryDrawable = (PFNGLXQUERYDRAWABLEPROC)glewGetProcAddress((const GLubyte*)"glXQueryDrawable")) == NULL) || r; + r = ((glXSelectEvent = (PFNGLXSELECTEVENTPROC)glewGetProcAddress((const GLubyte*)"glXSelectEvent")) == NULL) || r; + + return r; +} + +#endif /* GLX_VERSION_1_3 */ + +#ifdef GLX_VERSION_1_4 + +#endif /* GLX_VERSION_1_4 */ + +#ifdef GLX_3DFX_multisample + +#endif /* GLX_3DFX_multisample */ + +#ifdef GLX_AMD_gpu_association + +#endif /* GLX_AMD_gpu_association */ + +#ifdef GLX_ARB_create_context + +static GLboolean _glewInit_GLX_ARB_create_context (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glewGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB")) == NULL) || r; + + return r; +} + +#endif /* GLX_ARB_create_context */ + +#ifdef GLX_ARB_create_context_profile + +#endif /* GLX_ARB_create_context_profile */ + +#ifdef GLX_ARB_create_context_robustness + +#endif /* GLX_ARB_create_context_robustness */ + +#ifdef GLX_ARB_fbconfig_float + +#endif /* GLX_ARB_fbconfig_float */ + +#ifdef GLX_ARB_framebuffer_sRGB + +#endif /* GLX_ARB_framebuffer_sRGB */ + +#ifdef GLX_ARB_get_proc_address + +#endif /* GLX_ARB_get_proc_address */ + +#ifdef GLX_ARB_multisample + +#endif /* GLX_ARB_multisample */ + +#ifdef GLX_ARB_vertex_buffer_object + +#endif /* GLX_ARB_vertex_buffer_object */ + +#ifdef GLX_ATI_pixel_format_float + +#endif /* GLX_ATI_pixel_format_float */ + +#ifdef GLX_ATI_render_texture + +static GLboolean _glewInit_GLX_ATI_render_texture (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindTexImageATI = (PFNGLXBINDTEXIMAGEATIPROC)glewGetProcAddress((const GLubyte*)"glXBindTexImageATI")) == NULL) || r; + r = ((glXDrawableAttribATI = (PFNGLXDRAWABLEATTRIBATIPROC)glewGetProcAddress((const GLubyte*)"glXDrawableAttribATI")) == NULL) || r; + r = ((glXReleaseTexImageATI = (PFNGLXRELEASETEXIMAGEATIPROC)glewGetProcAddress((const GLubyte*)"glXReleaseTexImageATI")) == NULL) || r; + + return r; +} + +#endif /* GLX_ATI_render_texture */ + +#ifdef GLX_EXT_create_context_es2_profile + +#endif /* GLX_EXT_create_context_es2_profile */ + +#ifdef GLX_EXT_fbconfig_packed_float + +#endif /* GLX_EXT_fbconfig_packed_float */ + +#ifdef GLX_EXT_framebuffer_sRGB + +#endif /* GLX_EXT_framebuffer_sRGB */ + +#ifdef GLX_EXT_import_context + +static GLboolean _glewInit_GLX_EXT_import_context (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXFreeContextEXT = (PFNGLXFREECONTEXTEXTPROC)glewGetProcAddress((const GLubyte*)"glXFreeContextEXT")) == NULL) || r; + r = ((glXGetContextIDEXT = (PFNGLXGETCONTEXTIDEXTPROC)glewGetProcAddress((const GLubyte*)"glXGetContextIDEXT")) == NULL) || r; + r = ((glXImportContextEXT = (PFNGLXIMPORTCONTEXTEXTPROC)glewGetProcAddress((const GLubyte*)"glXImportContextEXT")) == NULL) || r; + r = ((glXQueryContextInfoEXT = (PFNGLXQUERYCONTEXTINFOEXTPROC)glewGetProcAddress((const GLubyte*)"glXQueryContextInfoEXT")) == NULL) || r; + + return r; +} + +#endif /* GLX_EXT_import_context */ + +#ifdef GLX_EXT_scene_marker + +#endif /* GLX_EXT_scene_marker */ + +#ifdef GLX_EXT_swap_control + +static GLboolean _glewInit_GLX_EXT_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glewGetProcAddress((const GLubyte*)"glXSwapIntervalEXT")) == NULL) || r; + + return r; +} + +#endif /* GLX_EXT_swap_control */ + +#ifdef GLX_EXT_texture_from_pixmap + +static GLboolean _glewInit_GLX_EXT_texture_from_pixmap (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glXBindTexImageEXT")) == NULL) || r; + r = ((glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glXReleaseTexImageEXT")) == NULL) || r; + + return r; +} + +#endif /* GLX_EXT_texture_from_pixmap */ + +#ifdef GLX_EXT_visual_info + +#endif /* GLX_EXT_visual_info */ + +#ifdef GLX_EXT_visual_rating + +#endif /* GLX_EXT_visual_rating */ + +#ifdef GLX_INTEL_swap_event + +#endif /* GLX_INTEL_swap_event */ + +#ifdef GLX_MESA_agp_offset + +static GLboolean _glewInit_GLX_MESA_agp_offset (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetAGPOffsetMESA = (PFNGLXGETAGPOFFSETMESAPROC)glewGetProcAddress((const GLubyte*)"glXGetAGPOffsetMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_agp_offset */ + +#ifdef GLX_MESA_copy_sub_buffer + +static GLboolean _glewInit_GLX_MESA_copy_sub_buffer (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXCopySubBufferMESA = (PFNGLXCOPYSUBBUFFERMESAPROC)glewGetProcAddress((const GLubyte*)"glXCopySubBufferMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_copy_sub_buffer */ + +#ifdef GLX_MESA_pixmap_colormap + +static GLboolean _glewInit_GLX_MESA_pixmap_colormap (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXCreateGLXPixmapMESA = (PFNGLXCREATEGLXPIXMAPMESAPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPixmapMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_pixmap_colormap */ + +#ifdef GLX_MESA_release_buffers + +static GLboolean _glewInit_GLX_MESA_release_buffers (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXReleaseBuffersMESA = (PFNGLXRELEASEBUFFERSMESAPROC)glewGetProcAddress((const GLubyte*)"glXReleaseBuffersMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_release_buffers */ + +#ifdef GLX_MESA_set_3dfx_mode + +static GLboolean _glewInit_GLX_MESA_set_3dfx_mode (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXSet3DfxModeMESA = (PFNGLXSET3DFXMODEMESAPROC)glewGetProcAddress((const GLubyte*)"glXSet3DfxModeMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_set_3dfx_mode */ + +#ifdef GLX_NV_copy_image + +static GLboolean _glewInit_GLX_NV_copy_image (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXCopyImageSubDataNV = (PFNGLXCOPYIMAGESUBDATANVPROC)glewGetProcAddress((const GLubyte*)"glXCopyImageSubDataNV")) == NULL) || r; + + return r; +} + +#endif /* GLX_NV_copy_image */ + +#ifdef GLX_NV_float_buffer + +#endif /* GLX_NV_float_buffer */ + +#ifdef GLX_NV_multisample_coverage + +#endif /* GLX_NV_multisample_coverage */ + +#ifdef GLX_NV_present_video + +static GLboolean _glewInit_GLX_NV_present_video (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindVideoDeviceNV = (PFNGLXBINDVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXBindVideoDeviceNV")) == NULL) || r; + r = ((glXEnumerateVideoDevicesNV = (PFNGLXENUMERATEVIDEODEVICESNVPROC)glewGetProcAddress((const GLubyte*)"glXEnumerateVideoDevicesNV")) == NULL) || r; + + return r; +} + +#endif /* GLX_NV_present_video */ + +#ifdef GLX_NV_swap_group + +static GLboolean _glewInit_GLX_NV_swap_group (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindSwapBarrierNV = (PFNGLXBINDSWAPBARRIERNVPROC)glewGetProcAddress((const GLubyte*)"glXBindSwapBarrierNV")) == NULL) || r; + r = ((glXJoinSwapGroupNV = (PFNGLXJOINSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"glXJoinSwapGroupNV")) == NULL) || r; + r = ((glXQueryFrameCountNV = (PFNGLXQUERYFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"glXQueryFrameCountNV")) == NULL) || r; + r = ((glXQueryMaxSwapGroupsNV = (PFNGLXQUERYMAXSWAPGROUPSNVPROC)glewGetProcAddress((const GLubyte*)"glXQueryMaxSwapGroupsNV")) == NULL) || r; + r = ((glXQuerySwapGroupNV = (PFNGLXQUERYSWAPGROUPNVPROC)glewGetProcAddress((const GLubyte*)"glXQuerySwapGroupNV")) == NULL) || r; + r = ((glXResetFrameCountNV = (PFNGLXRESETFRAMECOUNTNVPROC)glewGetProcAddress((const GLubyte*)"glXResetFrameCountNV")) == NULL) || r; + + return r; +} + +#endif /* GLX_NV_swap_group */ + +#ifdef GLX_NV_vertex_array_range + +static GLboolean _glewInit_GLX_NV_vertex_array_range (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXAllocateMemoryNV = (PFNGLXALLOCATEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"glXAllocateMemoryNV")) == NULL) || r; + r = ((glXFreeMemoryNV = (PFNGLXFREEMEMORYNVPROC)glewGetProcAddress((const GLubyte*)"glXFreeMemoryNV")) == NULL) || r; + + return r; +} + +#endif /* GLX_NV_vertex_array_range */ + +#ifdef GLX_NV_video_capture + +static GLboolean _glewInit_GLX_NV_video_capture (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindVideoCaptureDeviceNV = (PFNGLXBINDVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXBindVideoCaptureDeviceNV")) == NULL) || r; + r = ((glXEnumerateVideoCaptureDevicesNV = (PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC)glewGetProcAddress((const GLubyte*)"glXEnumerateVideoCaptureDevicesNV")) == NULL) || r; + r = ((glXLockVideoCaptureDeviceNV = (PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXLockVideoCaptureDeviceNV")) == NULL) || r; + r = ((glXQueryVideoCaptureDeviceNV = (PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXQueryVideoCaptureDeviceNV")) == NULL) || r; + r = ((glXReleaseVideoCaptureDeviceNV = (PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXReleaseVideoCaptureDeviceNV")) == NULL) || r; + + return r; +} + +#endif /* GLX_NV_video_capture */ + +#ifdef GLX_NV_video_output + +static GLboolean _glewInit_GLX_NV_video_output (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindVideoImageNV = (PFNGLXBINDVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"glXBindVideoImageNV")) == NULL) || r; + r = ((glXGetVideoDeviceNV = (PFNGLXGETVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoDeviceNV")) == NULL) || r; + r = ((glXGetVideoInfoNV = (PFNGLXGETVIDEOINFONVPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoInfoNV")) == NULL) || r; + r = ((glXReleaseVideoDeviceNV = (PFNGLXRELEASEVIDEODEVICENVPROC)glewGetProcAddress((const GLubyte*)"glXReleaseVideoDeviceNV")) == NULL) || r; + r = ((glXReleaseVideoImageNV = (PFNGLXRELEASEVIDEOIMAGENVPROC)glewGetProcAddress((const GLubyte*)"glXReleaseVideoImageNV")) == NULL) || r; + r = ((glXSendPbufferToVideoNV = (PFNGLXSENDPBUFFERTOVIDEONVPROC)glewGetProcAddress((const GLubyte*)"glXSendPbufferToVideoNV")) == NULL) || r; + + return r; +} + +#endif /* GLX_NV_video_output */ + +#ifdef GLX_OML_swap_method + +#endif /* GLX_OML_swap_method */ + +#ifdef GLX_OML_sync_control + +static GLboolean _glewInit_GLX_OML_sync_control (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetMscRateOML = (PFNGLXGETMSCRATEOMLPROC)glewGetProcAddress((const GLubyte*)"glXGetMscRateOML")) == NULL) || r; + r = ((glXGetSyncValuesOML = (PFNGLXGETSYNCVALUESOMLPROC)glewGetProcAddress((const GLubyte*)"glXGetSyncValuesOML")) == NULL) || r; + r = ((glXSwapBuffersMscOML = (PFNGLXSWAPBUFFERSMSCOMLPROC)glewGetProcAddress((const GLubyte*)"glXSwapBuffersMscOML")) == NULL) || r; + r = ((glXWaitForMscOML = (PFNGLXWAITFORMSCOMLPROC)glewGetProcAddress((const GLubyte*)"glXWaitForMscOML")) == NULL) || r; + r = ((glXWaitForSbcOML = (PFNGLXWAITFORSBCOMLPROC)glewGetProcAddress((const GLubyte*)"glXWaitForSbcOML")) == NULL) || r; + + return r; +} + +#endif /* GLX_OML_sync_control */ + +#ifdef GLX_SGIS_blended_overlay + +#endif /* GLX_SGIS_blended_overlay */ + +#ifdef GLX_SGIS_color_range + +#endif /* GLX_SGIS_color_range */ + +#ifdef GLX_SGIS_multisample + +#endif /* GLX_SGIS_multisample */ + +#ifdef GLX_SGIS_shared_multisample + +#endif /* GLX_SGIS_shared_multisample */ + +#ifdef GLX_SGIX_fbconfig + +static GLboolean _glewInit_GLX_SGIX_fbconfig (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChooseFBConfigSGIX")) == NULL) || r; + r = ((glXCreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateContextWithConfigSGIX")) == NULL) || r; + r = ((glXCreateGLXPixmapWithConfigSGIX = (PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPixmapWithConfigSGIX")) == NULL) || r; + r = ((glXGetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigAttribSGIX")) == NULL) || r; + r = ((glXGetFBConfigFromVisualSGIX = (PFNGLXGETFBCONFIGFROMVISUALSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetFBConfigFromVisualSGIX")) == NULL) || r; + r = ((glXGetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetVisualFromFBConfigSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_fbconfig */ + +#ifdef GLX_SGIX_hyperpipe + +static GLboolean _glewInit_GLX_SGIX_hyperpipe (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindHyperpipeSGIX = (PFNGLXBINDHYPERPIPESGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindHyperpipeSGIX")) == NULL) || r; + r = ((glXDestroyHyperpipeConfigSGIX = (PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXDestroyHyperpipeConfigSGIX")) == NULL) || r; + r = ((glXHyperpipeAttribSGIX = (PFNGLXHYPERPIPEATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXHyperpipeAttribSGIX")) == NULL) || r; + r = ((glXHyperpipeConfigSGIX = (PFNGLXHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXHyperpipeConfigSGIX")) == NULL) || r; + r = ((glXQueryHyperpipeAttribSGIX = (PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeAttribSGIX")) == NULL) || r; + r = ((glXQueryHyperpipeBestAttribSGIX = (PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeBestAttribSGIX")) == NULL) || r; + r = ((glXQueryHyperpipeConfigSGIX = (PFNGLXQUERYHYPERPIPECONFIGSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeConfigSGIX")) == NULL) || r; + r = ((glXQueryHyperpipeNetworkSGIX = (PFNGLXQUERYHYPERPIPENETWORKSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryHyperpipeNetworkSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_hyperpipe */ + +#ifdef GLX_SGIX_pbuffer + +static GLboolean _glewInit_GLX_SGIX_pbuffer (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXCreateGLXPbufferSGIX = (PFNGLXCREATEGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXCreateGLXPbufferSGIX")) == NULL) || r; + r = ((glXDestroyGLXPbufferSGIX = (PFNGLXDESTROYGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXDestroyGLXPbufferSGIX")) == NULL) || r; + r = ((glXGetSelectedEventSGIX = (PFNGLXGETSELECTEDEVENTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXGetSelectedEventSGIX")) == NULL) || r; + r = ((glXQueryGLXPbufferSGIX = (PFNGLXQUERYGLXPBUFFERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryGLXPbufferSGIX")) == NULL) || r; + r = ((glXSelectEventSGIX = (PFNGLXSELECTEVENTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXSelectEventSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_pbuffer */ + +#ifdef GLX_SGIX_swap_barrier + +static GLboolean _glewInit_GLX_SGIX_swap_barrier (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindSwapBarrierSGIX = (PFNGLXBINDSWAPBARRIERSGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindSwapBarrierSGIX")) == NULL) || r; + r = ((glXQueryMaxSwapBarriersSGIX = (PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryMaxSwapBarriersSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_swap_barrier */ + +#ifdef GLX_SGIX_swap_group + +static GLboolean _glewInit_GLX_SGIX_swap_group (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXJoinSwapGroupSGIX = (PFNGLXJOINSWAPGROUPSGIXPROC)glewGetProcAddress((const GLubyte*)"glXJoinSwapGroupSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_swap_group */ + +#ifdef GLX_SGIX_video_resize + +static GLboolean _glewInit_GLX_SGIX_video_resize (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBindChannelToWindowSGIX = (PFNGLXBINDCHANNELTOWINDOWSGIXPROC)glewGetProcAddress((const GLubyte*)"glXBindChannelToWindowSGIX")) == NULL) || r; + r = ((glXChannelRectSGIX = (PFNGLXCHANNELRECTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChannelRectSGIX")) == NULL) || r; + r = ((glXChannelRectSyncSGIX = (PFNGLXCHANNELRECTSYNCSGIXPROC)glewGetProcAddress((const GLubyte*)"glXChannelRectSyncSGIX")) == NULL) || r; + r = ((glXQueryChannelDeltasSGIX = (PFNGLXQUERYCHANNELDELTASSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryChannelDeltasSGIX")) == NULL) || r; + r = ((glXQueryChannelRectSGIX = (PFNGLXQUERYCHANNELRECTSGIXPROC)glewGetProcAddress((const GLubyte*)"glXQueryChannelRectSGIX")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGIX_video_resize */ + +#ifdef GLX_SGIX_visual_select_group + +#endif /* GLX_SGIX_visual_select_group */ + +#ifdef GLX_SGI_cushion + +static GLboolean _glewInit_GLX_SGI_cushion (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXCushionSGI = (PFNGLXCUSHIONSGIPROC)glewGetProcAddress((const GLubyte*)"glXCushionSGI")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGI_cushion */ + +#ifdef GLX_SGI_make_current_read + +static GLboolean _glewInit_GLX_SGI_make_current_read (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetCurrentReadDrawableSGI = (PFNGLXGETCURRENTREADDRAWABLESGIPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentReadDrawableSGI")) == NULL) || r; + r = ((glXMakeCurrentReadSGI = (PFNGLXMAKECURRENTREADSGIPROC)glewGetProcAddress((const GLubyte*)"glXMakeCurrentReadSGI")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGI_make_current_read */ + +#ifdef GLX_SGI_swap_control + +static GLboolean _glewInit_GLX_SGI_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glewGetProcAddress((const GLubyte*)"glXSwapIntervalSGI")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGI_swap_control */ + +#ifdef GLX_SGI_video_sync + +static GLboolean _glewInit_GLX_SGI_video_sync (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoSyncSGI")) == NULL) || r; + r = ((glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)glewGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI")) == NULL) || r; + + return r; +} + +#endif /* GLX_SGI_video_sync */ + +#ifdef GLX_SUN_get_transparent_index + +static GLboolean _glewInit_GLX_SUN_get_transparent_index (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetTransparentIndexSUN = (PFNGLXGETTRANSPARENTINDEXSUNPROC)glewGetProcAddress((const GLubyte*)"glXGetTransparentIndexSUN")) == NULL) || r; + + return r; +} + +#endif /* GLX_SUN_get_transparent_index */ + +#ifdef GLX_SUN_video_resize + +static GLboolean _glewInit_GLX_SUN_video_resize (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetVideoResizeSUN = (PFNGLXGETVIDEORESIZESUNPROC)glewGetProcAddress((const GLubyte*)"glXGetVideoResizeSUN")) == NULL) || r; + r = ((glXVideoResizeSUN = (PFNGLXVIDEORESIZESUNPROC)glewGetProcAddress((const GLubyte*)"glXVideoResizeSUN")) == NULL) || r; + + return r; +} + +#endif /* GLX_SUN_video_resize */ + +/* ------------------------------------------------------------------------ */ + +GLboolean glxewGetExtension (const char* name) +{ + const GLubyte* start; + const GLubyte* end; + + if (glXGetCurrentDisplay == NULL) return GL_FALSE; + start = (const GLubyte*)glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS); + if (0 == start) return GL_FALSE; + end = start + _glewStrLen(start); + return _glewSearchExtension(name, start, end); +} + +GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) +{ + int major, minor; + const GLubyte* extStart; + const GLubyte* extEnd; + /* initialize core GLX 1.2 */ + if (_glewInit_GLX_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT)) return GLEW_ERROR_GLX_VERSION_11_ONLY; + /* initialize flags */ + CONST_CAST(GLXEW_VERSION_1_0) = GL_TRUE; + CONST_CAST(GLXEW_VERSION_1_1) = GL_TRUE; + CONST_CAST(GLXEW_VERSION_1_2) = GL_TRUE; + CONST_CAST(GLXEW_VERSION_1_3) = GL_TRUE; + CONST_CAST(GLXEW_VERSION_1_4) = GL_TRUE; + /* query GLX version */ + glXQueryVersion(glXGetCurrentDisplay(), &major, &minor); + if (major == 1 && minor <= 3) + { + switch (minor) + { + case 3: + CONST_CAST(GLXEW_VERSION_1_4) = GL_FALSE; + break; + case 2: + CONST_CAST(GLXEW_VERSION_1_4) = GL_FALSE; + CONST_CAST(GLXEW_VERSION_1_3) = GL_FALSE; + break; + default: + return GLEW_ERROR_GLX_VERSION_11_ONLY; + break; + } + } + /* query GLX extension string */ + extStart = 0; + if (glXGetCurrentDisplay != NULL) + extStart = (const GLubyte*)glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS); + if (extStart == 0) + extStart = (const GLubyte *)""; + extEnd = extStart + _glewStrLen(extStart); + /* initialize extensions */ +#ifdef GLX_VERSION_1_3 + if (glewExperimental || GLXEW_VERSION_1_3) CONST_CAST(GLXEW_VERSION_1_3) = !_glewInit_GLX_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_VERSION_1_3 */ +#ifdef GLX_3DFX_multisample + CONST_CAST(GLXEW_3DFX_multisample) = _glewSearchExtension("GLX_3DFX_multisample", extStart, extEnd); +#endif /* GLX_3DFX_multisample */ +#ifdef GLX_AMD_gpu_association + CONST_CAST(GLXEW_AMD_gpu_association) = _glewSearchExtension("GLX_AMD_gpu_association", extStart, extEnd); +#endif /* GLX_AMD_gpu_association */ +#ifdef GLX_ARB_create_context + CONST_CAST(GLXEW_ARB_create_context) = _glewSearchExtension("GLX_ARB_create_context", extStart, extEnd); + if (glewExperimental || GLXEW_ARB_create_context) CONST_CAST(GLXEW_ARB_create_context) = !_glewInit_GLX_ARB_create_context(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_ARB_create_context */ +#ifdef GLX_ARB_create_context_profile + CONST_CAST(GLXEW_ARB_create_context_profile) = _glewSearchExtension("GLX_ARB_create_context_profile", extStart, extEnd); +#endif /* GLX_ARB_create_context_profile */ +#ifdef GLX_ARB_create_context_robustness + CONST_CAST(GLXEW_ARB_create_context_robustness) = _glewSearchExtension("GLX_ARB_create_context_robustness", extStart, extEnd); +#endif /* GLX_ARB_create_context_robustness */ +#ifdef GLX_ARB_fbconfig_float + CONST_CAST(GLXEW_ARB_fbconfig_float) = _glewSearchExtension("GLX_ARB_fbconfig_float", extStart, extEnd); +#endif /* GLX_ARB_fbconfig_float */ +#ifdef GLX_ARB_framebuffer_sRGB + CONST_CAST(GLXEW_ARB_framebuffer_sRGB) = _glewSearchExtension("GLX_ARB_framebuffer_sRGB", extStart, extEnd); +#endif /* GLX_ARB_framebuffer_sRGB */ +#ifdef GLX_ARB_get_proc_address + CONST_CAST(GLXEW_ARB_get_proc_address) = _glewSearchExtension("GLX_ARB_get_proc_address", extStart, extEnd); +#endif /* GLX_ARB_get_proc_address */ +#ifdef GLX_ARB_multisample + CONST_CAST(GLXEW_ARB_multisample) = _glewSearchExtension("GLX_ARB_multisample", extStart, extEnd); +#endif /* GLX_ARB_multisample */ +#ifdef GLX_ARB_vertex_buffer_object + CONST_CAST(GLXEW_ARB_vertex_buffer_object) = _glewSearchExtension("GLX_ARB_vertex_buffer_object", extStart, extEnd); +#endif /* GLX_ARB_vertex_buffer_object */ +#ifdef GLX_ATI_pixel_format_float + CONST_CAST(GLXEW_ATI_pixel_format_float) = _glewSearchExtension("GLX_ATI_pixel_format_float", extStart, extEnd); +#endif /* GLX_ATI_pixel_format_float */ +#ifdef GLX_ATI_render_texture + CONST_CAST(GLXEW_ATI_render_texture) = _glewSearchExtension("GLX_ATI_render_texture", extStart, extEnd); + if (glewExperimental || GLXEW_ATI_render_texture) CONST_CAST(GLXEW_ATI_render_texture) = !_glewInit_GLX_ATI_render_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_ATI_render_texture */ +#ifdef GLX_EXT_create_context_es2_profile + CONST_CAST(GLXEW_EXT_create_context_es2_profile) = _glewSearchExtension("GLX_EXT_create_context_es2_profile", extStart, extEnd); +#endif /* GLX_EXT_create_context_es2_profile */ +#ifdef GLX_EXT_fbconfig_packed_float + CONST_CAST(GLXEW_EXT_fbconfig_packed_float) = _glewSearchExtension("GLX_EXT_fbconfig_packed_float", extStart, extEnd); +#endif /* GLX_EXT_fbconfig_packed_float */ +#ifdef GLX_EXT_framebuffer_sRGB + CONST_CAST(GLXEW_EXT_framebuffer_sRGB) = _glewSearchExtension("GLX_EXT_framebuffer_sRGB", extStart, extEnd); +#endif /* GLX_EXT_framebuffer_sRGB */ +#ifdef GLX_EXT_import_context + CONST_CAST(GLXEW_EXT_import_context) = _glewSearchExtension("GLX_EXT_import_context", extStart, extEnd); + if (glewExperimental || GLXEW_EXT_import_context) CONST_CAST(GLXEW_EXT_import_context) = !_glewInit_GLX_EXT_import_context(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_EXT_import_context */ +#ifdef GLX_EXT_scene_marker + CONST_CAST(GLXEW_EXT_scene_marker) = _glewSearchExtension("GLX_EXT_scene_marker", extStart, extEnd); +#endif /* GLX_EXT_scene_marker */ +#ifdef GLX_EXT_swap_control + CONST_CAST(GLXEW_EXT_swap_control) = _glewSearchExtension("GLX_EXT_swap_control", extStart, extEnd); + if (glewExperimental || GLXEW_EXT_swap_control) CONST_CAST(GLXEW_EXT_swap_control) = !_glewInit_GLX_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_EXT_swap_control */ +#ifdef GLX_EXT_texture_from_pixmap + CONST_CAST(GLXEW_EXT_texture_from_pixmap) = _glewSearchExtension("GLX_EXT_texture_from_pixmap", extStart, extEnd); + if (glewExperimental || GLXEW_EXT_texture_from_pixmap) CONST_CAST(GLXEW_EXT_texture_from_pixmap) = !_glewInit_GLX_EXT_texture_from_pixmap(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_EXT_texture_from_pixmap */ +#ifdef GLX_EXT_visual_info + CONST_CAST(GLXEW_EXT_visual_info) = _glewSearchExtension("GLX_EXT_visual_info", extStart, extEnd); +#endif /* GLX_EXT_visual_info */ +#ifdef GLX_EXT_visual_rating + CONST_CAST(GLXEW_EXT_visual_rating) = _glewSearchExtension("GLX_EXT_visual_rating", extStart, extEnd); +#endif /* GLX_EXT_visual_rating */ +#ifdef GLX_INTEL_swap_event + CONST_CAST(GLXEW_INTEL_swap_event) = _glewSearchExtension("GLX_INTEL_swap_event", extStart, extEnd); +#endif /* GLX_INTEL_swap_event */ +#ifdef GLX_MESA_agp_offset + CONST_CAST(GLXEW_MESA_agp_offset) = _glewSearchExtension("GLX_MESA_agp_offset", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_agp_offset) CONST_CAST(GLXEW_MESA_agp_offset) = !_glewInit_GLX_MESA_agp_offset(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_agp_offset */ +#ifdef GLX_MESA_copy_sub_buffer + CONST_CAST(GLXEW_MESA_copy_sub_buffer) = _glewSearchExtension("GLX_MESA_copy_sub_buffer", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_copy_sub_buffer) CONST_CAST(GLXEW_MESA_copy_sub_buffer) = !_glewInit_GLX_MESA_copy_sub_buffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_copy_sub_buffer */ +#ifdef GLX_MESA_pixmap_colormap + CONST_CAST(GLXEW_MESA_pixmap_colormap) = _glewSearchExtension("GLX_MESA_pixmap_colormap", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_pixmap_colormap) CONST_CAST(GLXEW_MESA_pixmap_colormap) = !_glewInit_GLX_MESA_pixmap_colormap(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_pixmap_colormap */ +#ifdef GLX_MESA_release_buffers + CONST_CAST(GLXEW_MESA_release_buffers) = _glewSearchExtension("GLX_MESA_release_buffers", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_release_buffers) CONST_CAST(GLXEW_MESA_release_buffers) = !_glewInit_GLX_MESA_release_buffers(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_release_buffers */ +#ifdef GLX_MESA_set_3dfx_mode + CONST_CAST(GLXEW_MESA_set_3dfx_mode) = _glewSearchExtension("GLX_MESA_set_3dfx_mode", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_set_3dfx_mode) CONST_CAST(GLXEW_MESA_set_3dfx_mode) = !_glewInit_GLX_MESA_set_3dfx_mode(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_set_3dfx_mode */ +#ifdef GLX_NV_copy_image + CONST_CAST(GLXEW_NV_copy_image) = _glewSearchExtension("GLX_NV_copy_image", extStart, extEnd); + if (glewExperimental || GLXEW_NV_copy_image) CONST_CAST(GLXEW_NV_copy_image) = !_glewInit_GLX_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_NV_copy_image */ +#ifdef GLX_NV_float_buffer + CONST_CAST(GLXEW_NV_float_buffer) = _glewSearchExtension("GLX_NV_float_buffer", extStart, extEnd); +#endif /* GLX_NV_float_buffer */ +#ifdef GLX_NV_multisample_coverage + CONST_CAST(GLXEW_NV_multisample_coverage) = _glewSearchExtension("GLX_NV_multisample_coverage", extStart, extEnd); +#endif /* GLX_NV_multisample_coverage */ +#ifdef GLX_NV_present_video + CONST_CAST(GLXEW_NV_present_video) = _glewSearchExtension("GLX_NV_present_video", extStart, extEnd); + if (glewExperimental || GLXEW_NV_present_video) CONST_CAST(GLXEW_NV_present_video) = !_glewInit_GLX_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_NV_present_video */ +#ifdef GLX_NV_swap_group + CONST_CAST(GLXEW_NV_swap_group) = _glewSearchExtension("GLX_NV_swap_group", extStart, extEnd); + if (glewExperimental || GLXEW_NV_swap_group) CONST_CAST(GLXEW_NV_swap_group) = !_glewInit_GLX_NV_swap_group(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_NV_swap_group */ +#ifdef GLX_NV_vertex_array_range + CONST_CAST(GLXEW_NV_vertex_array_range) = _glewSearchExtension("GLX_NV_vertex_array_range", extStart, extEnd); + if (glewExperimental || GLXEW_NV_vertex_array_range) CONST_CAST(GLXEW_NV_vertex_array_range) = !_glewInit_GLX_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_NV_vertex_array_range */ +#ifdef GLX_NV_video_capture + CONST_CAST(GLXEW_NV_video_capture) = _glewSearchExtension("GLX_NV_video_capture", extStart, extEnd); + if (glewExperimental || GLXEW_NV_video_capture) CONST_CAST(GLXEW_NV_video_capture) = !_glewInit_GLX_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_NV_video_capture */ +#ifdef GLX_NV_video_output + CONST_CAST(GLXEW_NV_video_output) = _glewSearchExtension("GLX_NV_video_output", extStart, extEnd); + if (glewExperimental || GLXEW_NV_video_output) CONST_CAST(GLXEW_NV_video_output) = !_glewInit_GLX_NV_video_output(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_NV_video_output */ +#ifdef GLX_OML_swap_method + CONST_CAST(GLXEW_OML_swap_method) = _glewSearchExtension("GLX_OML_swap_method", extStart, extEnd); +#endif /* GLX_OML_swap_method */ +#ifdef GLX_OML_sync_control + CONST_CAST(GLXEW_OML_sync_control) = _glewSearchExtension("GLX_OML_sync_control", extStart, extEnd); + if (glewExperimental || GLXEW_OML_sync_control) CONST_CAST(GLXEW_OML_sync_control) = !_glewInit_GLX_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_OML_sync_control */ +#ifdef GLX_SGIS_blended_overlay + CONST_CAST(GLXEW_SGIS_blended_overlay) = _glewSearchExtension("GLX_SGIS_blended_overlay", extStart, extEnd); +#endif /* GLX_SGIS_blended_overlay */ +#ifdef GLX_SGIS_color_range + CONST_CAST(GLXEW_SGIS_color_range) = _glewSearchExtension("GLX_SGIS_color_range", extStart, extEnd); +#endif /* GLX_SGIS_color_range */ +#ifdef GLX_SGIS_multisample + CONST_CAST(GLXEW_SGIS_multisample) = _glewSearchExtension("GLX_SGIS_multisample", extStart, extEnd); +#endif /* GLX_SGIS_multisample */ +#ifdef GLX_SGIS_shared_multisample + CONST_CAST(GLXEW_SGIS_shared_multisample) = _glewSearchExtension("GLX_SGIS_shared_multisample", extStart, extEnd); +#endif /* GLX_SGIS_shared_multisample */ +#ifdef GLX_SGIX_fbconfig + CONST_CAST(GLXEW_SGIX_fbconfig) = _glewSearchExtension("GLX_SGIX_fbconfig", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_fbconfig) CONST_CAST(GLXEW_SGIX_fbconfig) = !_glewInit_GLX_SGIX_fbconfig(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_fbconfig */ +#ifdef GLX_SGIX_hyperpipe + CONST_CAST(GLXEW_SGIX_hyperpipe) = _glewSearchExtension("GLX_SGIX_hyperpipe", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_hyperpipe) CONST_CAST(GLXEW_SGIX_hyperpipe) = !_glewInit_GLX_SGIX_hyperpipe(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_hyperpipe */ +#ifdef GLX_SGIX_pbuffer + CONST_CAST(GLXEW_SGIX_pbuffer) = _glewSearchExtension("GLX_SGIX_pbuffer", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_pbuffer) CONST_CAST(GLXEW_SGIX_pbuffer) = !_glewInit_GLX_SGIX_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_pbuffer */ +#ifdef GLX_SGIX_swap_barrier + CONST_CAST(GLXEW_SGIX_swap_barrier) = _glewSearchExtension("GLX_SGIX_swap_barrier", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_swap_barrier) CONST_CAST(GLXEW_SGIX_swap_barrier) = !_glewInit_GLX_SGIX_swap_barrier(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_swap_barrier */ +#ifdef GLX_SGIX_swap_group + CONST_CAST(GLXEW_SGIX_swap_group) = _glewSearchExtension("GLX_SGIX_swap_group", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_swap_group) CONST_CAST(GLXEW_SGIX_swap_group) = !_glewInit_GLX_SGIX_swap_group(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_swap_group */ +#ifdef GLX_SGIX_video_resize + CONST_CAST(GLXEW_SGIX_video_resize) = _glewSearchExtension("GLX_SGIX_video_resize", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_video_resize) CONST_CAST(GLXEW_SGIX_video_resize) = !_glewInit_GLX_SGIX_video_resize(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGIX_video_resize */ +#ifdef GLX_SGIX_visual_select_group + CONST_CAST(GLXEW_SGIX_visual_select_group) = _glewSearchExtension("GLX_SGIX_visual_select_group", extStart, extEnd); +#endif /* GLX_SGIX_visual_select_group */ +#ifdef GLX_SGI_cushion + CONST_CAST(GLXEW_SGI_cushion) = _glewSearchExtension("GLX_SGI_cushion", extStart, extEnd); + if (glewExperimental || GLXEW_SGI_cushion) CONST_CAST(GLXEW_SGI_cushion) = !_glewInit_GLX_SGI_cushion(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGI_cushion */ +#ifdef GLX_SGI_make_current_read + CONST_CAST(GLXEW_SGI_make_current_read) = _glewSearchExtension("GLX_SGI_make_current_read", extStart, extEnd); + if (glewExperimental || GLXEW_SGI_make_current_read) CONST_CAST(GLXEW_SGI_make_current_read) = !_glewInit_GLX_SGI_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGI_make_current_read */ +#ifdef GLX_SGI_swap_control + CONST_CAST(GLXEW_SGI_swap_control) = _glewSearchExtension("GLX_SGI_swap_control", extStart, extEnd); + if (glewExperimental || GLXEW_SGI_swap_control) CONST_CAST(GLXEW_SGI_swap_control) = !_glewInit_GLX_SGI_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGI_swap_control */ +#ifdef GLX_SGI_video_sync + CONST_CAST(GLXEW_SGI_video_sync) = _glewSearchExtension("GLX_SGI_video_sync", extStart, extEnd); + if (glewExperimental || GLXEW_SGI_video_sync) CONST_CAST(GLXEW_SGI_video_sync) = !_glewInit_GLX_SGI_video_sync(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SGI_video_sync */ +#ifdef GLX_SUN_get_transparent_index + CONST_CAST(GLXEW_SUN_get_transparent_index) = _glewSearchExtension("GLX_SUN_get_transparent_index", extStart, extEnd); + if (glewExperimental || GLXEW_SUN_get_transparent_index) CONST_CAST(GLXEW_SUN_get_transparent_index) = !_glewInit_GLX_SUN_get_transparent_index(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SUN_get_transparent_index */ +#ifdef GLX_SUN_video_resize + CONST_CAST(GLXEW_SUN_video_resize) = _glewSearchExtension("GLX_SUN_video_resize", extStart, extEnd); + if (glewExperimental || GLXEW_SUN_video_resize) CONST_CAST(GLXEW_SUN_video_resize) = !_glewInit_GLX_SUN_video_resize(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_SUN_video_resize */ + + return GLEW_OK; +} + +#endif /* !__APPLE__ || GLEW_APPLE_GLX */ + +/* ------------------------------------------------------------------------ */ + +const GLubyte* glewGetErrorString (GLenum error) +{ + static const GLubyte* _glewErrorString[] = + { + (const GLubyte*)"No error", + (const GLubyte*)"Missing GL version", + (const GLubyte*)"GL 1.1 and up are not supported", + (const GLubyte*)"GLX 1.2 and up are not supported", + (const GLubyte*)"Unknown error" + }; + const int max_error = sizeof(_glewErrorString)/sizeof(*_glewErrorString) - 1; + return _glewErrorString[(int)error > max_error ? max_error : (int)error]; +} + +const GLubyte* glewGetString (GLenum name) +{ + static const GLubyte* _glewString[] = + { + (const GLubyte*)NULL, + (const GLubyte*)"1.6.0", + (const GLubyte*)"1", + (const GLubyte*)"6", + (const GLubyte*)"0" + }; + const int max_string = sizeof(_glewString)/sizeof(*_glewString) - 1; + return _glewString[(int)name > max_string ? 0 : (int)name]; +} + +/* ------------------------------------------------------------------------ */ + +GLboolean glewExperimental = GL_FALSE; + +#if !defined(GLEW_MX) + +#if defined(_WIN32) +extern GLenum wglewContextInit (void); +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */ +extern GLenum glxewContextInit (void); +#endif /* _WIN32 */ + +GLenum glewInit () +{ + GLenum r; + if ( (r = glewContextInit()) ) return r; +#if defined(_WIN32) + return wglewContextInit(); +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */ + return glxewContextInit(); +#else + return r; +#endif /* _WIN32 */ +} + +#endif /* !GLEW_MX */ +#ifdef GLEW_MX +GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name) +#else +GLboolean glewIsSupported (const char* name) +#endif +{ + GLubyte* pos = (GLubyte*)name; + GLuint len = _glewStrLen(pos); + GLboolean ret = GL_TRUE; + while (ret && len > 0) + { + if (_glewStrSame1(&pos, &len, (const GLubyte*)"GL_", 3)) + { + if (_glewStrSame2(&pos, &len, (const GLubyte*)"VERSION_", 8)) + { +#ifdef GL_VERSION_1_2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2", 3)) + { + ret = GLEW_VERSION_1_2; + continue; + } +#endif +#ifdef GL_VERSION_1_2_1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2_1", 5)) + { + ret = GLEW_VERSION_1_2_1; + continue; + } +#endif +#ifdef GL_VERSION_1_3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_3", 3)) + { + ret = GLEW_VERSION_1_3; + continue; + } +#endif +#ifdef GL_VERSION_1_4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_4", 3)) + { + ret = GLEW_VERSION_1_4; + continue; + } +#endif +#ifdef GL_VERSION_1_5 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_5", 3)) + { + ret = GLEW_VERSION_1_5; + continue; + } +#endif +#ifdef GL_VERSION_2_0 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"2_0", 3)) + { + ret = GLEW_VERSION_2_0; + continue; + } +#endif +#ifdef GL_VERSION_2_1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"2_1", 3)) + { + ret = GLEW_VERSION_2_1; + continue; + } +#endif +#ifdef GL_VERSION_3_0 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"3_0", 3)) + { + ret = GLEW_VERSION_3_0; + continue; + } +#endif +#ifdef GL_VERSION_3_1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"3_1", 3)) + { + ret = GLEW_VERSION_3_1; + continue; + } +#endif +#ifdef GL_VERSION_3_2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"3_2", 3)) + { + ret = GLEW_VERSION_3_2; + continue; + } +#endif +#ifdef GL_VERSION_3_3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"3_3", 3)) + { + ret = GLEW_VERSION_3_3; + continue; + } +#endif +#ifdef GL_VERSION_4_0 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"4_0", 3)) + { + ret = GLEW_VERSION_4_0; + continue; + } +#endif +#ifdef GL_VERSION_4_1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"4_1", 3)) + { + ret = GLEW_VERSION_4_1; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5)) + { +#ifdef GL_3DFX_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLEW_3DFX_multisample; + continue; + } +#endif +#ifdef GL_3DFX_tbuffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"tbuffer", 7)) + { + ret = GLEW_3DFX_tbuffer; + continue; + } +#endif +#ifdef GL_3DFX_texture_compression_FXT1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_FXT1", 24)) + { + ret = GLEW_3DFX_texture_compression_FXT1; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"AMD_", 4)) + { +#ifdef GL_AMD_blend_minmax_factor + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_minmax_factor", 19)) + { + ret = GLEW_AMD_blend_minmax_factor; + continue; + } +#endif +#ifdef GL_AMD_conservative_depth + if (_glewStrSame3(&pos, &len, (const GLubyte*)"conservative_depth", 18)) + { + ret = GLEW_AMD_conservative_depth; + continue; + } +#endif +#ifdef GL_AMD_debug_output + if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_output", 12)) + { + ret = GLEW_AMD_debug_output; + continue; + } +#endif +#ifdef GL_AMD_depth_clamp_separate + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_clamp_separate", 20)) + { + ret = GLEW_AMD_depth_clamp_separate; + continue; + } +#endif +#ifdef GL_AMD_draw_buffers_blend + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers_blend", 18)) + { + ret = GLEW_AMD_draw_buffers_blend; + continue; + } +#endif +#ifdef GL_AMD_name_gen_delete + if (_glewStrSame3(&pos, &len, (const GLubyte*)"name_gen_delete", 15)) + { + ret = GLEW_AMD_name_gen_delete; + continue; + } +#endif +#ifdef GL_AMD_performance_monitor + if (_glewStrSame3(&pos, &len, (const GLubyte*)"performance_monitor", 19)) + { + ret = GLEW_AMD_performance_monitor; + continue; + } +#endif +#ifdef GL_AMD_sample_positions + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sample_positions", 16)) + { + ret = GLEW_AMD_sample_positions; + continue; + } +#endif +#ifdef GL_AMD_seamless_cubemap_per_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"seamless_cubemap_per_texture", 28)) + { + ret = GLEW_AMD_seamless_cubemap_per_texture; + continue; + } +#endif +#ifdef GL_AMD_shader_stencil_export + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_stencil_export", 21)) + { + ret = GLEW_AMD_shader_stencil_export; + continue; + } +#endif +#ifdef GL_AMD_texture_texture4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_texture4", 16)) + { + ret = GLEW_AMD_texture_texture4; + continue; + } +#endif +#ifdef GL_AMD_transform_feedback3_lines_triangles + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback3_lines_triangles", 35)) + { + ret = GLEW_AMD_transform_feedback3_lines_triangles; + continue; + } +#endif +#ifdef GL_AMD_vertex_shader_tessellator + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_tessellator", 25)) + { + ret = GLEW_AMD_vertex_shader_tessellator; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"APPLE_", 6)) + { +#ifdef GL_APPLE_aux_depth_stencil + if (_glewStrSame3(&pos, &len, (const GLubyte*)"aux_depth_stencil", 17)) + { + ret = GLEW_APPLE_aux_depth_stencil; + continue; + } +#endif +#ifdef GL_APPLE_client_storage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"client_storage", 14)) + { + ret = GLEW_APPLE_client_storage; + continue; + } +#endif +#ifdef GL_APPLE_element_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"element_array", 13)) + { + ret = GLEW_APPLE_element_array; + continue; + } +#endif +#ifdef GL_APPLE_fence + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fence", 5)) + { + ret = GLEW_APPLE_fence; + continue; + } +#endif +#ifdef GL_APPLE_float_pixels + if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_pixels", 12)) + { + ret = GLEW_APPLE_float_pixels; + continue; + } +#endif +#ifdef GL_APPLE_flush_buffer_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"flush_buffer_range", 18)) + { + ret = GLEW_APPLE_flush_buffer_range; + continue; + } +#endif +#ifdef GL_APPLE_object_purgeable + if (_glewStrSame3(&pos, &len, (const GLubyte*)"object_purgeable", 16)) + { + ret = GLEW_APPLE_object_purgeable; + continue; + } +#endif +#ifdef GL_APPLE_pixel_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer", 12)) + { + ret = GLEW_APPLE_pixel_buffer; + continue; + } +#endif +#ifdef GL_APPLE_rgb_422 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"rgb_422", 7)) + { + ret = GLEW_APPLE_rgb_422; + continue; + } +#endif +#ifdef GL_APPLE_row_bytes + if (_glewStrSame3(&pos, &len, (const GLubyte*)"row_bytes", 9)) + { + ret = GLEW_APPLE_row_bytes; + continue; + } +#endif +#ifdef GL_APPLE_specular_vector + if (_glewStrSame3(&pos, &len, (const GLubyte*)"specular_vector", 15)) + { + ret = GLEW_APPLE_specular_vector; + continue; + } +#endif +#ifdef GL_APPLE_texture_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_range", 13)) + { + ret = GLEW_APPLE_texture_range; + continue; + } +#endif +#ifdef GL_APPLE_transform_hint + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_hint", 14)) + { + ret = GLEW_APPLE_transform_hint; + continue; + } +#endif +#ifdef GL_APPLE_vertex_array_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19)) + { + ret = GLEW_APPLE_vertex_array_object; + continue; + } +#endif +#ifdef GL_APPLE_vertex_array_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18)) + { + ret = GLEW_APPLE_vertex_array_range; + continue; + } +#endif +#ifdef GL_APPLE_vertex_program_evaluators + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program_evaluators", 25)) + { + ret = GLEW_APPLE_vertex_program_evaluators; + continue; + } +#endif +#ifdef GL_APPLE_ycbcr_422 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycbcr_422", 9)) + { + ret = GLEW_APPLE_ycbcr_422; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4)) + { +#ifdef GL_ARB_ES2_compatibility + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ES2_compatibility", 17)) + { + ret = GLEW_ARB_ES2_compatibility; + continue; + } +#endif +#ifdef GL_ARB_blend_func_extended + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_func_extended", 19)) + { + ret = GLEW_ARB_blend_func_extended; + continue; + } +#endif +#ifdef GL_ARB_cl_event + if (_glewStrSame3(&pos, &len, (const GLubyte*)"cl_event", 8)) + { + ret = GLEW_ARB_cl_event; + continue; + } +#endif +#ifdef GL_ARB_color_buffer_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_buffer_float", 18)) + { + ret = GLEW_ARB_color_buffer_float; + continue; + } +#endif +#ifdef GL_ARB_compatibility + if (_glewStrSame3(&pos, &len, (const GLubyte*)"compatibility", 13)) + { + ret = GLEW_ARB_compatibility; + continue; + } +#endif +#ifdef GL_ARB_copy_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_buffer", 11)) + { + ret = GLEW_ARB_copy_buffer; + continue; + } +#endif +#ifdef GL_ARB_debug_output + if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_output", 12)) + { + ret = GLEW_ARB_debug_output; + continue; + } +#endif +#ifdef GL_ARB_depth_buffer_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_buffer_float", 18)) + { + ret = GLEW_ARB_depth_buffer_float; + continue; + } +#endif +#ifdef GL_ARB_depth_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_clamp", 11)) + { + ret = GLEW_ARB_depth_clamp; + continue; + } +#endif +#ifdef GL_ARB_depth_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13)) + { + ret = GLEW_ARB_depth_texture; + continue; + } +#endif +#ifdef GL_ARB_draw_buffers + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers", 12)) + { + ret = GLEW_ARB_draw_buffers; + continue; + } +#endif +#ifdef GL_ARB_draw_buffers_blend + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers_blend", 18)) + { + ret = GLEW_ARB_draw_buffers_blend; + continue; + } +#endif +#ifdef GL_ARB_draw_elements_base_vertex + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_elements_base_vertex", 25)) + { + ret = GLEW_ARB_draw_elements_base_vertex; + continue; + } +#endif +#ifdef GL_ARB_draw_indirect + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_indirect", 13)) + { + ret = GLEW_ARB_draw_indirect; + continue; + } +#endif +#ifdef GL_ARB_draw_instanced + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_instanced", 14)) + { + ret = GLEW_ARB_draw_instanced; + continue; + } +#endif +#ifdef GL_ARB_explicit_attrib_location + if (_glewStrSame3(&pos, &len, (const GLubyte*)"explicit_attrib_location", 24)) + { + ret = GLEW_ARB_explicit_attrib_location; + continue; + } +#endif +#ifdef GL_ARB_fragment_coord_conventions + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_coord_conventions", 26)) + { + ret = GLEW_ARB_fragment_coord_conventions; + continue; + } +#endif +#ifdef GL_ARB_fragment_program + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program", 16)) + { + ret = GLEW_ARB_fragment_program; + continue; + } +#endif +#ifdef GL_ARB_fragment_program_shadow + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program_shadow", 23)) + { + ret = GLEW_ARB_fragment_program_shadow; + continue; + } +#endif +#ifdef GL_ARB_fragment_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_shader", 15)) + { + ret = GLEW_ARB_fragment_shader; + continue; + } +#endif +#ifdef GL_ARB_framebuffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18)) + { + ret = GLEW_ARB_framebuffer_object; + continue; + } +#endif +#ifdef GL_ARB_framebuffer_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16)) + { + ret = GLEW_ARB_framebuffer_sRGB; + continue; + } +#endif +#ifdef GL_ARB_geometry_shader4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16)) + { + ret = GLEW_ARB_geometry_shader4; + continue; + } +#endif +#ifdef GL_ARB_get_program_binary + if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_program_binary", 18)) + { + ret = GLEW_ARB_get_program_binary; + continue; + } +#endif +#ifdef GL_ARB_gpu_shader5 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader5", 11)) + { + ret = GLEW_ARB_gpu_shader5; + continue; + } +#endif +#ifdef GL_ARB_gpu_shader_fp64 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader_fp64", 15)) + { + ret = GLEW_ARB_gpu_shader_fp64; + continue; + } +#endif +#ifdef GL_ARB_half_float_pixel + if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float_pixel", 16)) + { + ret = GLEW_ARB_half_float_pixel; + continue; + } +#endif +#ifdef GL_ARB_half_float_vertex + if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float_vertex", 17)) + { + ret = GLEW_ARB_half_float_vertex; + continue; + } +#endif +#ifdef GL_ARB_imaging + if (_glewStrSame3(&pos, &len, (const GLubyte*)"imaging", 7)) + { + ret = GLEW_ARB_imaging; + continue; + } +#endif +#ifdef GL_ARB_instanced_arrays + if (_glewStrSame3(&pos, &len, (const GLubyte*)"instanced_arrays", 16)) + { + ret = GLEW_ARB_instanced_arrays; + continue; + } +#endif +#ifdef GL_ARB_map_buffer_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_buffer_range", 16)) + { + ret = GLEW_ARB_map_buffer_range; + continue; + } +#endif +#ifdef GL_ARB_matrix_palette + if (_glewStrSame3(&pos, &len, (const GLubyte*)"matrix_palette", 14)) + { + ret = GLEW_ARB_matrix_palette; + continue; + } +#endif +#ifdef GL_ARB_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLEW_ARB_multisample; + continue; + } +#endif +#ifdef GL_ARB_multitexture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multitexture", 12)) + { + ret = GLEW_ARB_multitexture; + continue; + } +#endif +#ifdef GL_ARB_occlusion_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query", 15)) + { + ret = GLEW_ARB_occlusion_query; + continue; + } +#endif +#ifdef GL_ARB_occlusion_query2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query2", 16)) + { + ret = GLEW_ARB_occlusion_query2; + continue; + } +#endif +#ifdef GL_ARB_pixel_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer_object", 19)) + { + ret = GLEW_ARB_pixel_buffer_object; + continue; + } +#endif +#ifdef GL_ARB_point_parameters + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_parameters", 16)) + { + ret = GLEW_ARB_point_parameters; + continue; + } +#endif +#ifdef GL_ARB_point_sprite + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprite", 12)) + { + ret = GLEW_ARB_point_sprite; + continue; + } +#endif +#ifdef GL_ARB_provoking_vertex + if (_glewStrSame3(&pos, &len, (const GLubyte*)"provoking_vertex", 16)) + { + ret = GLEW_ARB_provoking_vertex; + continue; + } +#endif +#ifdef GL_ARB_robustness + if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness", 10)) + { + ret = GLEW_ARB_robustness; + continue; + } +#endif +#ifdef GL_ARB_sample_shading + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sample_shading", 14)) + { + ret = GLEW_ARB_sample_shading; + continue; + } +#endif +#ifdef GL_ARB_sampler_objects + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sampler_objects", 15)) + { + ret = GLEW_ARB_sampler_objects; + continue; + } +#endif +#ifdef GL_ARB_seamless_cube_map + if (_glewStrSame3(&pos, &len, (const GLubyte*)"seamless_cube_map", 17)) + { + ret = GLEW_ARB_seamless_cube_map; + continue; + } +#endif +#ifdef GL_ARB_separate_shader_objects + if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_shader_objects", 23)) + { + ret = GLEW_ARB_separate_shader_objects; + continue; + } +#endif +#ifdef GL_ARB_shader_bit_encoding + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_bit_encoding", 19)) + { + ret = GLEW_ARB_shader_bit_encoding; + continue; + } +#endif +#ifdef GL_ARB_shader_objects + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_objects", 14)) + { + ret = GLEW_ARB_shader_objects; + continue; + } +#endif +#ifdef GL_ARB_shader_precision + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_precision", 16)) + { + ret = GLEW_ARB_shader_precision; + continue; + } +#endif +#ifdef GL_ARB_shader_stencil_export + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_stencil_export", 21)) + { + ret = GLEW_ARB_shader_stencil_export; + continue; + } +#endif +#ifdef GL_ARB_shader_subroutine + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_subroutine", 17)) + { + ret = GLEW_ARB_shader_subroutine; + continue; + } +#endif +#ifdef GL_ARB_shader_texture_lod + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_texture_lod", 18)) + { + ret = GLEW_ARB_shader_texture_lod; + continue; + } +#endif +#ifdef GL_ARB_shading_language_100 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_100", 20)) + { + ret = GLEW_ARB_shading_language_100; + continue; + } +#endif +#ifdef GL_ARB_shading_language_include + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_include", 24)) + { + ret = GLEW_ARB_shading_language_include; + continue; + } +#endif +#ifdef GL_ARB_shadow + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow", 6)) + { + ret = GLEW_ARB_shadow; + continue; + } +#endif +#ifdef GL_ARB_shadow_ambient + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_ambient", 14)) + { + ret = GLEW_ARB_shadow_ambient; + continue; + } +#endif +#ifdef GL_ARB_sync + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync", 4)) + { + ret = GLEW_ARB_sync; + continue; + } +#endif +#ifdef GL_ARB_tessellation_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"tessellation_shader", 19)) + { + ret = GLEW_ARB_tessellation_shader; + continue; + } +#endif +#ifdef GL_ARB_texture_border_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_border_clamp", 20)) + { + ret = GLEW_ARB_texture_border_clamp; + continue; + } +#endif +#ifdef GL_ARB_texture_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_object", 21)) + { + ret = GLEW_ARB_texture_buffer_object; + continue; + } +#endif +#ifdef GL_ARB_texture_buffer_object_rgb32 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_object_rgb32", 27)) + { + ret = GLEW_ARB_texture_buffer_object_rgb32; + continue; + } +#endif +#ifdef GL_ARB_texture_compression + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression", 19)) + { + ret = GLEW_ARB_texture_compression; + continue; + } +#endif +#ifdef GL_ARB_texture_compression_bptc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_bptc", 24)) + { + ret = GLEW_ARB_texture_compression_bptc; + continue; + } +#endif +#ifdef GL_ARB_texture_compression_rgtc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_rgtc", 24)) + { + ret = GLEW_ARB_texture_compression_rgtc; + continue; + } +#endif +#ifdef GL_ARB_texture_cube_map + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map", 16)) + { + ret = GLEW_ARB_texture_cube_map; + continue; + } +#endif +#ifdef GL_ARB_texture_cube_map_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map_array", 22)) + { + ret = GLEW_ARB_texture_cube_map_array; + continue; + } +#endif +#ifdef GL_ARB_texture_env_add + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_add", 15)) + { + ret = GLEW_ARB_texture_env_add; + continue; + } +#endif +#ifdef GL_ARB_texture_env_combine + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine", 19)) + { + ret = GLEW_ARB_texture_env_combine; + continue; + } +#endif +#ifdef GL_ARB_texture_env_crossbar + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_crossbar", 20)) + { + ret = GLEW_ARB_texture_env_crossbar; + continue; + } +#endif +#ifdef GL_ARB_texture_env_dot3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_dot3", 16)) + { + ret = GLEW_ARB_texture_env_dot3; + continue; + } +#endif +#ifdef GL_ARB_texture_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_float", 13)) + { + ret = GLEW_ARB_texture_float; + continue; + } +#endif +#ifdef GL_ARB_texture_gather + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_gather", 14)) + { + ret = GLEW_ARB_texture_gather; + continue; + } +#endif +#ifdef GL_ARB_texture_mirrored_repeat + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23)) + { + ret = GLEW_ARB_texture_mirrored_repeat; + continue; + } +#endif +#ifdef GL_ARB_texture_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_multisample", 19)) + { + ret = GLEW_ARB_texture_multisample; + continue; + } +#endif +#ifdef GL_ARB_texture_non_power_of_two + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_non_power_of_two", 24)) + { + ret = GLEW_ARB_texture_non_power_of_two; + continue; + } +#endif +#ifdef GL_ARB_texture_query_lod + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_query_lod", 17)) + { + ret = GLEW_ARB_texture_query_lod; + continue; + } +#endif +#ifdef GL_ARB_texture_rectangle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17)) + { + ret = GLEW_ARB_texture_rectangle; + continue; + } +#endif +#ifdef GL_ARB_texture_rg + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rg", 10)) + { + ret = GLEW_ARB_texture_rg; + continue; + } +#endif +#ifdef GL_ARB_texture_rgb10_a2ui + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rgb10_a2ui", 18)) + { + ret = GLEW_ARB_texture_rgb10_a2ui; + continue; + } +#endif +#ifdef GL_ARB_texture_swizzle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_swizzle", 15)) + { + ret = GLEW_ARB_texture_swizzle; + continue; + } +#endif +#ifdef GL_ARB_timer_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"timer_query", 11)) + { + ret = GLEW_ARB_timer_query; + continue; + } +#endif +#ifdef GL_ARB_transform_feedback2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback2", 19)) + { + ret = GLEW_ARB_transform_feedback2; + continue; + } +#endif +#ifdef GL_ARB_transform_feedback3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback3", 19)) + { + ret = GLEW_ARB_transform_feedback3; + continue; + } +#endif +#ifdef GL_ARB_transpose_matrix + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transpose_matrix", 16)) + { + ret = GLEW_ARB_transpose_matrix; + continue; + } +#endif +#ifdef GL_ARB_uniform_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"uniform_buffer_object", 21)) + { + ret = GLEW_ARB_uniform_buffer_object; + continue; + } +#endif +#ifdef GL_ARB_vertex_array_bgra + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_bgra", 17)) + { + ret = GLEW_ARB_vertex_array_bgra; + continue; + } +#endif +#ifdef GL_ARB_vertex_array_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19)) + { + ret = GLEW_ARB_vertex_array_object; + continue; + } +#endif +#ifdef GL_ARB_vertex_attrib_64bit + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_64bit", 19)) + { + ret = GLEW_ARB_vertex_attrib_64bit; + continue; + } +#endif +#ifdef GL_ARB_vertex_blend + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_blend", 12)) + { + ret = GLEW_ARB_vertex_blend; + continue; + } +#endif +#ifdef GL_ARB_vertex_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_buffer_object", 20)) + { + ret = GLEW_ARB_vertex_buffer_object; + continue; + } +#endif +#ifdef GL_ARB_vertex_program + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program", 14)) + { + ret = GLEW_ARB_vertex_program; + continue; + } +#endif +#ifdef GL_ARB_vertex_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader", 13)) + { + ret = GLEW_ARB_vertex_shader; + continue; + } +#endif +#ifdef GL_ARB_vertex_type_2_10_10_10_rev + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_type_2_10_10_10_rev", 26)) + { + ret = GLEW_ARB_vertex_type_2_10_10_10_rev; + continue; + } +#endif +#ifdef GL_ARB_viewport_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"viewport_array", 14)) + { + ret = GLEW_ARB_viewport_array; + continue; + } +#endif +#ifdef GL_ARB_window_pos + if (_glewStrSame3(&pos, &len, (const GLubyte*)"window_pos", 10)) + { + ret = GLEW_ARB_window_pos; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATIX_", 5)) + { +#ifdef GL_ATIX_point_sprites + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprites", 13)) + { + ret = GLEW_ATIX_point_sprites; + continue; + } +#endif +#ifdef GL_ATIX_texture_env_combine3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine3", 20)) + { + ret = GLEW_ATIX_texture_env_combine3; + continue; + } +#endif +#ifdef GL_ATIX_texture_env_route + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_route", 17)) + { + ret = GLEW_ATIX_texture_env_route; + continue; + } +#endif +#ifdef GL_ATIX_vertex_shader_output_point_size + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_output_point_size", 31)) + { + ret = GLEW_ATIX_vertex_shader_output_point_size; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4)) + { +#ifdef GL_ATI_draw_buffers + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers", 12)) + { + ret = GLEW_ATI_draw_buffers; + continue; + } +#endif +#ifdef GL_ATI_element_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"element_array", 13)) + { + ret = GLEW_ATI_element_array; + continue; + } +#endif +#ifdef GL_ATI_envmap_bumpmap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"envmap_bumpmap", 14)) + { + ret = GLEW_ATI_envmap_bumpmap; + continue; + } +#endif +#ifdef GL_ATI_fragment_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_shader", 15)) + { + ret = GLEW_ATI_fragment_shader; + continue; + } +#endif +#ifdef GL_ATI_map_object_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_object_buffer", 17)) + { + ret = GLEW_ATI_map_object_buffer; + continue; + } +#endif +#ifdef GL_ATI_meminfo + if (_glewStrSame3(&pos, &len, (const GLubyte*)"meminfo", 7)) + { + ret = GLEW_ATI_meminfo; + continue; + } +#endif +#ifdef GL_ATI_pn_triangles + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pn_triangles", 12)) + { + ret = GLEW_ATI_pn_triangles; + continue; + } +#endif +#ifdef GL_ATI_separate_stencil + if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_stencil", 16)) + { + ret = GLEW_ATI_separate_stencil; + continue; + } +#endif +#ifdef GL_ATI_shader_texture_lod + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_texture_lod", 18)) + { + ret = GLEW_ATI_shader_texture_lod; + continue; + } +#endif +#ifdef GL_ATI_text_fragment_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"text_fragment_shader", 20)) + { + ret = GLEW_ATI_text_fragment_shader; + continue; + } +#endif +#ifdef GL_ATI_texture_compression_3dc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_3dc", 23)) + { + ret = GLEW_ATI_texture_compression_3dc; + continue; + } +#endif +#ifdef GL_ATI_texture_env_combine3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine3", 20)) + { + ret = GLEW_ATI_texture_env_combine3; + continue; + } +#endif +#ifdef GL_ATI_texture_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_float", 13)) + { + ret = GLEW_ATI_texture_float; + continue; + } +#endif +#ifdef GL_ATI_texture_mirror_once + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirror_once", 19)) + { + ret = GLEW_ATI_texture_mirror_once; + continue; + } +#endif +#ifdef GL_ATI_vertex_array_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_object", 19)) + { + ret = GLEW_ATI_vertex_array_object; + continue; + } +#endif +#ifdef GL_ATI_vertex_attrib_array_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_array_object", 26)) + { + ret = GLEW_ATI_vertex_attrib_array_object; + continue; + } +#endif +#ifdef GL_ATI_vertex_streams + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_streams", 14)) + { + ret = GLEW_ATI_vertex_streams; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4)) + { +#ifdef GL_EXT_422_pixels + if (_glewStrSame3(&pos, &len, (const GLubyte*)"422_pixels", 10)) + { + ret = GLEW_EXT_422_pixels; + continue; + } +#endif +#ifdef GL_EXT_Cg_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"Cg_shader", 9)) + { + ret = GLEW_EXT_Cg_shader; + continue; + } +#endif +#ifdef GL_EXT_abgr + if (_glewStrSame3(&pos, &len, (const GLubyte*)"abgr", 4)) + { + ret = GLEW_EXT_abgr; + continue; + } +#endif +#ifdef GL_EXT_bgra + if (_glewStrSame3(&pos, &len, (const GLubyte*)"bgra", 4)) + { + ret = GLEW_EXT_bgra; + continue; + } +#endif +#ifdef GL_EXT_bindable_uniform + if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindable_uniform", 16)) + { + ret = GLEW_EXT_bindable_uniform; + continue; + } +#endif +#ifdef GL_EXT_blend_color + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_color", 11)) + { + ret = GLEW_EXT_blend_color; + continue; + } +#endif +#ifdef GL_EXT_blend_equation_separate + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_equation_separate", 23)) + { + ret = GLEW_EXT_blend_equation_separate; + continue; + } +#endif +#ifdef GL_EXT_blend_func_separate + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_func_separate", 19)) + { + ret = GLEW_EXT_blend_func_separate; + continue; + } +#endif +#ifdef GL_EXT_blend_logic_op + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_logic_op", 14)) + { + ret = GLEW_EXT_blend_logic_op; + continue; + } +#endif +#ifdef GL_EXT_blend_minmax + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_minmax", 12)) + { + ret = GLEW_EXT_blend_minmax; + continue; + } +#endif +#ifdef GL_EXT_blend_subtract + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_subtract", 14)) + { + ret = GLEW_EXT_blend_subtract; + continue; + } +#endif +#ifdef GL_EXT_clip_volume_hint + if (_glewStrSame3(&pos, &len, (const GLubyte*)"clip_volume_hint", 16)) + { + ret = GLEW_EXT_clip_volume_hint; + continue; + } +#endif +#ifdef GL_EXT_cmyka + if (_glewStrSame3(&pos, &len, (const GLubyte*)"cmyka", 5)) + { + ret = GLEW_EXT_cmyka; + continue; + } +#endif +#ifdef GL_EXT_color_subtable + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_subtable", 14)) + { + ret = GLEW_EXT_color_subtable; + continue; + } +#endif +#ifdef GL_EXT_compiled_vertex_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"compiled_vertex_array", 21)) + { + ret = GLEW_EXT_compiled_vertex_array; + continue; + } +#endif +#ifdef GL_EXT_convolution + if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution", 11)) + { + ret = GLEW_EXT_convolution; + continue; + } +#endif +#ifdef GL_EXT_coordinate_frame + if (_glewStrSame3(&pos, &len, (const GLubyte*)"coordinate_frame", 16)) + { + ret = GLEW_EXT_coordinate_frame; + continue; + } +#endif +#ifdef GL_EXT_copy_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_texture", 12)) + { + ret = GLEW_EXT_copy_texture; + continue; + } +#endif +#ifdef GL_EXT_cull_vertex + if (_glewStrSame3(&pos, &len, (const GLubyte*)"cull_vertex", 11)) + { + ret = GLEW_EXT_cull_vertex; + continue; + } +#endif +#ifdef GL_EXT_depth_bounds_test + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_bounds_test", 17)) + { + ret = GLEW_EXT_depth_bounds_test; + continue; + } +#endif +#ifdef GL_EXT_direct_state_access + if (_glewStrSame3(&pos, &len, (const GLubyte*)"direct_state_access", 19)) + { + ret = GLEW_EXT_direct_state_access; + continue; + } +#endif +#ifdef GL_EXT_draw_buffers2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_buffers2", 13)) + { + ret = GLEW_EXT_draw_buffers2; + continue; + } +#endif +#ifdef GL_EXT_draw_instanced + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_instanced", 14)) + { + ret = GLEW_EXT_draw_instanced; + continue; + } +#endif +#ifdef GL_EXT_draw_range_elements + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_range_elements", 19)) + { + ret = GLEW_EXT_draw_range_elements; + continue; + } +#endif +#ifdef GL_EXT_fog_coord + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_coord", 9)) + { + ret = GLEW_EXT_fog_coord; + continue; + } +#endif +#ifdef GL_EXT_fragment_lighting + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_lighting", 17)) + { + ret = GLEW_EXT_fragment_lighting; + continue; + } +#endif +#ifdef GL_EXT_framebuffer_blit + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_blit", 16)) + { + ret = GLEW_EXT_framebuffer_blit; + continue; + } +#endif +#ifdef GL_EXT_framebuffer_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample", 23)) + { + ret = GLEW_EXT_framebuffer_multisample; + continue; + } +#endif +#ifdef GL_EXT_framebuffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18)) + { + ret = GLEW_EXT_framebuffer_object; + continue; + } +#endif +#ifdef GL_EXT_framebuffer_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16)) + { + ret = GLEW_EXT_framebuffer_sRGB; + continue; + } +#endif +#ifdef GL_EXT_geometry_shader4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16)) + { + ret = GLEW_EXT_geometry_shader4; + continue; + } +#endif +#ifdef GL_EXT_gpu_program_parameters + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program_parameters", 22)) + { + ret = GLEW_EXT_gpu_program_parameters; + continue; + } +#endif +#ifdef GL_EXT_gpu_shader4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader4", 11)) + { + ret = GLEW_EXT_gpu_shader4; + continue; + } +#endif +#ifdef GL_EXT_histogram + if (_glewStrSame3(&pos, &len, (const GLubyte*)"histogram", 9)) + { + ret = GLEW_EXT_histogram; + continue; + } +#endif +#ifdef GL_EXT_index_array_formats + if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_array_formats", 19)) + { + ret = GLEW_EXT_index_array_formats; + continue; + } +#endif +#ifdef GL_EXT_index_func + if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_func", 10)) + { + ret = GLEW_EXT_index_func; + continue; + } +#endif +#ifdef GL_EXT_index_material + if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_material", 14)) + { + ret = GLEW_EXT_index_material; + continue; + } +#endif +#ifdef GL_EXT_index_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"index_texture", 13)) + { + ret = GLEW_EXT_index_texture; + continue; + } +#endif +#ifdef GL_EXT_light_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"light_texture", 13)) + { + ret = GLEW_EXT_light_texture; + continue; + } +#endif +#ifdef GL_EXT_misc_attribute + if (_glewStrSame3(&pos, &len, (const GLubyte*)"misc_attribute", 14)) + { + ret = GLEW_EXT_misc_attribute; + continue; + } +#endif +#ifdef GL_EXT_multi_draw_arrays + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_arrays", 17)) + { + ret = GLEW_EXT_multi_draw_arrays; + continue; + } +#endif +#ifdef GL_EXT_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLEW_EXT_multisample; + continue; + } +#endif +#ifdef GL_EXT_packed_depth_stencil + if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_depth_stencil", 20)) + { + ret = GLEW_EXT_packed_depth_stencil; + continue; + } +#endif +#ifdef GL_EXT_packed_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_float", 12)) + { + ret = GLEW_EXT_packed_float; + continue; + } +#endif +#ifdef GL_EXT_packed_pixels + if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_pixels", 13)) + { + ret = GLEW_EXT_packed_pixels; + continue; + } +#endif +#ifdef GL_EXT_paletted_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"paletted_texture", 16)) + { + ret = GLEW_EXT_paletted_texture; + continue; + } +#endif +#ifdef GL_EXT_pixel_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_buffer_object", 19)) + { + ret = GLEW_EXT_pixel_buffer_object; + continue; + } +#endif +#ifdef GL_EXT_pixel_transform + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_transform", 15)) + { + ret = GLEW_EXT_pixel_transform; + continue; + } +#endif +#ifdef GL_EXT_pixel_transform_color_table + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_transform_color_table", 27)) + { + ret = GLEW_EXT_pixel_transform_color_table; + continue; + } +#endif +#ifdef GL_EXT_point_parameters + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_parameters", 16)) + { + ret = GLEW_EXT_point_parameters; + continue; + } +#endif +#ifdef GL_EXT_polygon_offset + if (_glewStrSame3(&pos, &len, (const GLubyte*)"polygon_offset", 14)) + { + ret = GLEW_EXT_polygon_offset; + continue; + } +#endif +#ifdef GL_EXT_provoking_vertex + if (_glewStrSame3(&pos, &len, (const GLubyte*)"provoking_vertex", 16)) + { + ret = GLEW_EXT_provoking_vertex; + continue; + } +#endif +#ifdef GL_EXT_rescale_normal + if (_glewStrSame3(&pos, &len, (const GLubyte*)"rescale_normal", 14)) + { + ret = GLEW_EXT_rescale_normal; + continue; + } +#endif +#ifdef GL_EXT_scene_marker + if (_glewStrSame3(&pos, &len, (const GLubyte*)"scene_marker", 12)) + { + ret = GLEW_EXT_scene_marker; + continue; + } +#endif +#ifdef GL_EXT_secondary_color + if (_glewStrSame3(&pos, &len, (const GLubyte*)"secondary_color", 15)) + { + ret = GLEW_EXT_secondary_color; + continue; + } +#endif +#ifdef GL_EXT_separate_shader_objects + if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_shader_objects", 23)) + { + ret = GLEW_EXT_separate_shader_objects; + continue; + } +#endif +#ifdef GL_EXT_separate_specular_color + if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_specular_color", 23)) + { + ret = GLEW_EXT_separate_specular_color; + continue; + } +#endif +#ifdef GL_EXT_shader_image_load_store + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_image_load_store", 23)) + { + ret = GLEW_EXT_shader_image_load_store; + continue; + } +#endif +#ifdef GL_EXT_shadow_funcs + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_funcs", 12)) + { + ret = GLEW_EXT_shadow_funcs; + continue; + } +#endif +#ifdef GL_EXT_shared_texture_palette + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shared_texture_palette", 22)) + { + ret = GLEW_EXT_shared_texture_palette; + continue; + } +#endif +#ifdef GL_EXT_stencil_clear_tag + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_clear_tag", 17)) + { + ret = GLEW_EXT_stencil_clear_tag; + continue; + } +#endif +#ifdef GL_EXT_stencil_two_side + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_two_side", 16)) + { + ret = GLEW_EXT_stencil_two_side; + continue; + } +#endif +#ifdef GL_EXT_stencil_wrap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_wrap", 12)) + { + ret = GLEW_EXT_stencil_wrap; + continue; + } +#endif +#ifdef GL_EXT_subtexture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"subtexture", 10)) + { + ret = GLEW_EXT_subtexture; + continue; + } +#endif +#ifdef GL_EXT_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture", 7)) + { + ret = GLEW_EXT_texture; + continue; + } +#endif +#ifdef GL_EXT_texture3D + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture3D", 9)) + { + ret = GLEW_EXT_texture3D; + continue; + } +#endif +#ifdef GL_EXT_texture_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_array", 13)) + { + ret = GLEW_EXT_texture_array; + continue; + } +#endif +#ifdef GL_EXT_texture_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_object", 21)) + { + ret = GLEW_EXT_texture_buffer_object; + continue; + } +#endif +#ifdef GL_EXT_texture_compression_dxt1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt1", 24)) + { + ret = GLEW_EXT_texture_compression_dxt1; + continue; + } +#endif +#ifdef GL_EXT_texture_compression_latc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_latc", 24)) + { + ret = GLEW_EXT_texture_compression_latc; + continue; + } +#endif +#ifdef GL_EXT_texture_compression_rgtc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_rgtc", 24)) + { + ret = GLEW_EXT_texture_compression_rgtc; + continue; + } +#endif +#ifdef GL_EXT_texture_compression_s3tc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_s3tc", 24)) + { + ret = GLEW_EXT_texture_compression_s3tc; + continue; + } +#endif +#ifdef GL_EXT_texture_cube_map + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_cube_map", 16)) + { + ret = GLEW_EXT_texture_cube_map; + continue; + } +#endif +#ifdef GL_EXT_texture_edge_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_edge_clamp", 18)) + { + ret = GLEW_EXT_texture_edge_clamp; + continue; + } +#endif +#ifdef GL_EXT_texture_env + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env", 11)) + { + ret = GLEW_EXT_texture_env; + continue; + } +#endif +#ifdef GL_EXT_texture_env_add + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_add", 15)) + { + ret = GLEW_EXT_texture_env_add; + continue; + } +#endif +#ifdef GL_EXT_texture_env_combine + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine", 19)) + { + ret = GLEW_EXT_texture_env_combine; + continue; + } +#endif +#ifdef GL_EXT_texture_env_dot3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_dot3", 16)) + { + ret = GLEW_EXT_texture_env_dot3; + continue; + } +#endif +#ifdef GL_EXT_texture_filter_anisotropic + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_filter_anisotropic", 26)) + { + ret = GLEW_EXT_texture_filter_anisotropic; + continue; + } +#endif +#ifdef GL_EXT_texture_integer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_integer", 15)) + { + ret = GLEW_EXT_texture_integer; + continue; + } +#endif +#ifdef GL_EXT_texture_lod_bias + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod_bias", 16)) + { + ret = GLEW_EXT_texture_lod_bias; + continue; + } +#endif +#ifdef GL_EXT_texture_mirror_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirror_clamp", 20)) + { + ret = GLEW_EXT_texture_mirror_clamp; + continue; + } +#endif +#ifdef GL_EXT_texture_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_object", 14)) + { + ret = GLEW_EXT_texture_object; + continue; + } +#endif +#ifdef GL_EXT_texture_perturb_normal + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_perturb_normal", 22)) + { + ret = GLEW_EXT_texture_perturb_normal; + continue; + } +#endif +#ifdef GL_EXT_texture_rectangle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17)) + { + ret = GLEW_EXT_texture_rectangle; + continue; + } +#endif +#ifdef GL_EXT_texture_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_sRGB", 12)) + { + ret = GLEW_EXT_texture_sRGB; + continue; + } +#endif +#ifdef GL_EXT_texture_sRGB_decode + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_sRGB_decode", 19)) + { + ret = GLEW_EXT_texture_sRGB_decode; + continue; + } +#endif +#ifdef GL_EXT_texture_shared_exponent + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shared_exponent", 23)) + { + ret = GLEW_EXT_texture_shared_exponent; + continue; + } +#endif +#ifdef GL_EXT_texture_snorm + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_snorm", 13)) + { + ret = GLEW_EXT_texture_snorm; + continue; + } +#endif +#ifdef GL_EXT_texture_swizzle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_swizzle", 15)) + { + ret = GLEW_EXT_texture_swizzle; + continue; + } +#endif +#ifdef GL_EXT_timer_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"timer_query", 11)) + { + ret = GLEW_EXT_timer_query; + continue; + } +#endif +#ifdef GL_EXT_transform_feedback + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback", 18)) + { + ret = GLEW_EXT_transform_feedback; + continue; + } +#endif +#ifdef GL_EXT_vertex_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array", 12)) + { + ret = GLEW_EXT_vertex_array; + continue; + } +#endif +#ifdef GL_EXT_vertex_array_bgra + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_bgra", 17)) + { + ret = GLEW_EXT_vertex_array_bgra; + continue; + } +#endif +#ifdef GL_EXT_vertex_attrib_64bit + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_64bit", 19)) + { + ret = GLEW_EXT_vertex_attrib_64bit; + continue; + } +#endif +#ifdef GL_EXT_vertex_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader", 13)) + { + ret = GLEW_EXT_vertex_shader; + continue; + } +#endif +#ifdef GL_EXT_vertex_weighting + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_weighting", 16)) + { + ret = GLEW_EXT_vertex_weighting; + continue; + } +#endif +#ifdef GL_EXT_x11_sync_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"x11_sync_object", 15)) + { + ret = GLEW_EXT_x11_sync_object; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"GREMEDY_", 8)) + { +#ifdef GL_GREMEDY_frame_terminator + if (_glewStrSame3(&pos, &len, (const GLubyte*)"frame_terminator", 16)) + { + ret = GLEW_GREMEDY_frame_terminator; + continue; + } +#endif +#ifdef GL_GREMEDY_string_marker + if (_glewStrSame3(&pos, &len, (const GLubyte*)"string_marker", 13)) + { + ret = GLEW_GREMEDY_string_marker; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"HP_", 3)) + { +#ifdef GL_HP_convolution_border_modes + if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_border_modes", 24)) + { + ret = GLEW_HP_convolution_border_modes; + continue; + } +#endif +#ifdef GL_HP_image_transform + if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_transform", 15)) + { + ret = GLEW_HP_image_transform; + continue; + } +#endif +#ifdef GL_HP_occlusion_test + if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_test", 14)) + { + ret = GLEW_HP_occlusion_test; + continue; + } +#endif +#ifdef GL_HP_texture_lighting + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lighting", 16)) + { + ret = GLEW_HP_texture_lighting; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"IBM_", 4)) + { +#ifdef GL_IBM_cull_vertex + if (_glewStrSame3(&pos, &len, (const GLubyte*)"cull_vertex", 11)) + { + ret = GLEW_IBM_cull_vertex; + continue; + } +#endif +#ifdef GL_IBM_multimode_draw_arrays + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multimode_draw_arrays", 21)) + { + ret = GLEW_IBM_multimode_draw_arrays; + continue; + } +#endif +#ifdef GL_IBM_rasterpos_clip + if (_glewStrSame3(&pos, &len, (const GLubyte*)"rasterpos_clip", 14)) + { + ret = GLEW_IBM_rasterpos_clip; + continue; + } +#endif +#ifdef GL_IBM_static_data + if (_glewStrSame3(&pos, &len, (const GLubyte*)"static_data", 11)) + { + ret = GLEW_IBM_static_data; + continue; + } +#endif +#ifdef GL_IBM_texture_mirrored_repeat + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23)) + { + ret = GLEW_IBM_texture_mirrored_repeat; + continue; + } +#endif +#ifdef GL_IBM_vertex_array_lists + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_lists", 18)) + { + ret = GLEW_IBM_vertex_array_lists; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"INGR_", 5)) + { +#ifdef GL_INGR_color_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_clamp", 11)) + { + ret = GLEW_INGR_color_clamp; + continue; + } +#endif +#ifdef GL_INGR_interlace_read + if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace_read", 14)) + { + ret = GLEW_INGR_interlace_read; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"INTEL_", 6)) + { +#ifdef GL_INTEL_parallel_arrays + if (_glewStrSame3(&pos, &len, (const GLubyte*)"parallel_arrays", 15)) + { + ret = GLEW_INTEL_parallel_arrays; + continue; + } +#endif +#ifdef GL_INTEL_texture_scissor + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_scissor", 15)) + { + ret = GLEW_INTEL_texture_scissor; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"KTX_", 4)) + { +#ifdef GL_KTX_buffer_region + if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_region", 13)) + { + ret = GLEW_KTX_buffer_region; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESAX_", 6)) + { +#ifdef GL_MESAX_texture_stack + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_stack", 13)) + { + ret = GLEW_MESAX_texture_stack; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESA_", 5)) + { +#ifdef GL_MESA_pack_invert + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pack_invert", 11)) + { + ret = GLEW_MESA_pack_invert; + continue; + } +#endif +#ifdef GL_MESA_resize_buffers + if (_glewStrSame3(&pos, &len, (const GLubyte*)"resize_buffers", 14)) + { + ret = GLEW_MESA_resize_buffers; + continue; + } +#endif +#ifdef GL_MESA_window_pos + if (_glewStrSame3(&pos, &len, (const GLubyte*)"window_pos", 10)) + { + ret = GLEW_MESA_window_pos; + continue; + } +#endif +#ifdef GL_MESA_ycbcr_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycbcr_texture", 13)) + { + ret = GLEW_MESA_ycbcr_texture; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"NVX_", 4)) + { +#ifdef GL_NVX_gpu_memory_info + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_memory_info", 15)) + { + ret = GLEW_NVX_gpu_memory_info; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3)) + { +#ifdef GL_NV_blend_square + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_square", 12)) + { + ret = GLEW_NV_blend_square; + continue; + } +#endif +#ifdef GL_NV_conditional_render + if (_glewStrSame3(&pos, &len, (const GLubyte*)"conditional_render", 18)) + { + ret = GLEW_NV_conditional_render; + continue; + } +#endif +#ifdef GL_NV_copy_depth_to_color + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_depth_to_color", 19)) + { + ret = GLEW_NV_copy_depth_to_color; + continue; + } +#endif +#ifdef GL_NV_copy_image + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10)) + { + ret = GLEW_NV_copy_image; + continue; + } +#endif +#ifdef GL_NV_depth_buffer_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_buffer_float", 18)) + { + ret = GLEW_NV_depth_buffer_float; + continue; + } +#endif +#ifdef GL_NV_depth_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_clamp", 11)) + { + ret = GLEW_NV_depth_clamp; + continue; + } +#endif +#ifdef GL_NV_depth_range_unclamped + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_range_unclamped", 21)) + { + ret = GLEW_NV_depth_range_unclamped; + continue; + } +#endif +#ifdef GL_NV_evaluators + if (_glewStrSame3(&pos, &len, (const GLubyte*)"evaluators", 10)) + { + ret = GLEW_NV_evaluators; + continue; + } +#endif +#ifdef GL_NV_explicit_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"explicit_multisample", 20)) + { + ret = GLEW_NV_explicit_multisample; + continue; + } +#endif +#ifdef GL_NV_fence + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fence", 5)) + { + ret = GLEW_NV_fence; + continue; + } +#endif +#ifdef GL_NV_float_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12)) + { + ret = GLEW_NV_float_buffer; + continue; + } +#endif +#ifdef GL_NV_fog_distance + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_distance", 12)) + { + ret = GLEW_NV_fog_distance; + continue; + } +#endif +#ifdef GL_NV_fragment_program + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program", 16)) + { + ret = GLEW_NV_fragment_program; + continue; + } +#endif +#ifdef GL_NV_fragment_program2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program2", 17)) + { + ret = GLEW_NV_fragment_program2; + continue; + } +#endif +#ifdef GL_NV_fragment_program4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program4", 17)) + { + ret = GLEW_NV_fragment_program4; + continue; + } +#endif +#ifdef GL_NV_fragment_program_option + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program_option", 23)) + { + ret = GLEW_NV_fragment_program_option; + continue; + } +#endif +#ifdef GL_NV_framebuffer_multisample_coverage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample_coverage", 32)) + { + ret = GLEW_NV_framebuffer_multisample_coverage; + continue; + } +#endif +#ifdef GL_NV_geometry_program4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_program4", 17)) + { + ret = GLEW_NV_geometry_program4; + continue; + } +#endif +#ifdef GL_NV_geometry_shader4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"geometry_shader4", 16)) + { + ret = GLEW_NV_geometry_shader4; + continue; + } +#endif +#ifdef GL_NV_gpu_program4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program4", 12)) + { + ret = GLEW_NV_gpu_program4; + continue; + } +#endif +#ifdef GL_NV_gpu_program5 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program5", 12)) + { + ret = GLEW_NV_gpu_program5; + continue; + } +#endif +#ifdef GL_NV_gpu_program_fp64 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program_fp64", 16)) + { + ret = GLEW_NV_gpu_program_fp64; + continue; + } +#endif +#ifdef GL_NV_gpu_shader5 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader5", 11)) + { + ret = GLEW_NV_gpu_shader5; + continue; + } +#endif +#ifdef GL_NV_half_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"half_float", 10)) + { + ret = GLEW_NV_half_float; + continue; + } +#endif +#ifdef GL_NV_light_max_exponent + if (_glewStrSame3(&pos, &len, (const GLubyte*)"light_max_exponent", 18)) + { + ret = GLEW_NV_light_max_exponent; + continue; + } +#endif +#ifdef GL_NV_multisample_coverage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample_coverage", 20)) + { + ret = GLEW_NV_multisample_coverage; + continue; + } +#endif +#ifdef GL_NV_multisample_filter_hint + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample_filter_hint", 23)) + { + ret = GLEW_NV_multisample_filter_hint; + continue; + } +#endif +#ifdef GL_NV_occlusion_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query", 15)) + { + ret = GLEW_NV_occlusion_query; + continue; + } +#endif +#ifdef GL_NV_packed_depth_stencil + if (_glewStrSame3(&pos, &len, (const GLubyte*)"packed_depth_stencil", 20)) + { + ret = GLEW_NV_packed_depth_stencil; + continue; + } +#endif +#ifdef GL_NV_parameter_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"parameter_buffer_object", 23)) + { + ret = GLEW_NV_parameter_buffer_object; + continue; + } +#endif +#ifdef GL_NV_parameter_buffer_object2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"parameter_buffer_object2", 24)) + { + ret = GLEW_NV_parameter_buffer_object2; + continue; + } +#endif +#ifdef GL_NV_pixel_data_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_data_range", 16)) + { + ret = GLEW_NV_pixel_data_range; + continue; + } +#endif +#ifdef GL_NV_point_sprite + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_sprite", 12)) + { + ret = GLEW_NV_point_sprite; + continue; + } +#endif +#ifdef GL_NV_present_video + if (_glewStrSame3(&pos, &len, (const GLubyte*)"present_video", 13)) + { + ret = GLEW_NV_present_video; + continue; + } +#endif +#ifdef GL_NV_primitive_restart + if (_glewStrSame3(&pos, &len, (const GLubyte*)"primitive_restart", 17)) + { + ret = GLEW_NV_primitive_restart; + continue; + } +#endif +#ifdef GL_NV_register_combiners + if (_glewStrSame3(&pos, &len, (const GLubyte*)"register_combiners", 18)) + { + ret = GLEW_NV_register_combiners; + continue; + } +#endif +#ifdef GL_NV_register_combiners2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"register_combiners2", 19)) + { + ret = GLEW_NV_register_combiners2; + continue; + } +#endif +#ifdef GL_NV_shader_buffer_load + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_buffer_load", 18)) + { + ret = GLEW_NV_shader_buffer_load; + continue; + } +#endif +#ifdef GL_NV_tessellation_program5 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"tessellation_program5", 21)) + { + ret = GLEW_NV_tessellation_program5; + continue; + } +#endif +#ifdef GL_NV_texgen_emboss + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texgen_emboss", 13)) + { + ret = GLEW_NV_texgen_emboss; + continue; + } +#endif +#ifdef GL_NV_texgen_reflection + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texgen_reflection", 17)) + { + ret = GLEW_NV_texgen_reflection; + continue; + } +#endif +#ifdef GL_NV_texture_barrier + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_barrier", 15)) + { + ret = GLEW_NV_texture_barrier; + continue; + } +#endif +#ifdef GL_NV_texture_compression_vtc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_vtc", 23)) + { + ret = GLEW_NV_texture_compression_vtc; + continue; + } +#endif +#ifdef GL_NV_texture_env_combine4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_env_combine4", 20)) + { + ret = GLEW_NV_texture_env_combine4; + continue; + } +#endif +#ifdef GL_NV_texture_expand_normal + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_expand_normal", 21)) + { + ret = GLEW_NV_texture_expand_normal; + continue; + } +#endif +#ifdef GL_NV_texture_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_multisample", 19)) + { + ret = GLEW_NV_texture_multisample; + continue; + } +#endif +#ifdef GL_NV_texture_rectangle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_rectangle", 17)) + { + ret = GLEW_NV_texture_rectangle; + continue; + } +#endif +#ifdef GL_NV_texture_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader", 14)) + { + ret = GLEW_NV_texture_shader; + continue; + } +#endif +#ifdef GL_NV_texture_shader2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader2", 15)) + { + ret = GLEW_NV_texture_shader2; + continue; + } +#endif +#ifdef GL_NV_texture_shader3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_shader3", 15)) + { + ret = GLEW_NV_texture_shader3; + continue; + } +#endif +#ifdef GL_NV_transform_feedback + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback", 18)) + { + ret = GLEW_NV_transform_feedback; + continue; + } +#endif +#ifdef GL_NV_transform_feedback2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback2", 19)) + { + ret = GLEW_NV_transform_feedback2; + continue; + } +#endif +#ifdef GL_NV_vdpau_interop + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vdpau_interop", 13)) + { + ret = GLEW_NV_vdpau_interop; + continue; + } +#endif +#ifdef GL_NV_vertex_array_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18)) + { + ret = GLEW_NV_vertex_array_range; + continue; + } +#endif +#ifdef GL_NV_vertex_array_range2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range2", 19)) + { + ret = GLEW_NV_vertex_array_range2; + continue; + } +#endif +#ifdef GL_NV_vertex_attrib_integer_64bit + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_integer_64bit", 27)) + { + ret = GLEW_NV_vertex_attrib_integer_64bit; + continue; + } +#endif +#ifdef GL_NV_vertex_buffer_unified_memory + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_buffer_unified_memory", 28)) + { + ret = GLEW_NV_vertex_buffer_unified_memory; + continue; + } +#endif +#ifdef GL_NV_vertex_program + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program", 14)) + { + ret = GLEW_NV_vertex_program; + continue; + } +#endif +#ifdef GL_NV_vertex_program1_1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program1_1", 17)) + { + ret = GLEW_NV_vertex_program1_1; + continue; + } +#endif +#ifdef GL_NV_vertex_program2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program2", 15)) + { + ret = GLEW_NV_vertex_program2; + continue; + } +#endif +#ifdef GL_NV_vertex_program2_option + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program2_option", 22)) + { + ret = GLEW_NV_vertex_program2_option; + continue; + } +#endif +#ifdef GL_NV_vertex_program3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program3", 15)) + { + ret = GLEW_NV_vertex_program3; + continue; + } +#endif +#ifdef GL_NV_vertex_program4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_program4", 15)) + { + ret = GLEW_NV_vertex_program4; + continue; + } +#endif +#ifdef GL_NV_video_capture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_capture", 13)) + { + ret = GLEW_NV_video_capture; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"OES_", 4)) + { +#ifdef GL_OES_byte_coordinates + if (_glewStrSame3(&pos, &len, (const GLubyte*)"byte_coordinates", 16)) + { + ret = GLEW_OES_byte_coordinates; + continue; + } +#endif +#ifdef GL_OES_compressed_paletted_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"compressed_paletted_texture", 27)) + { + ret = GLEW_OES_compressed_paletted_texture; + continue; + } +#endif +#ifdef GL_OES_read_format + if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_format", 11)) + { + ret = GLEW_OES_read_format; + continue; + } +#endif +#ifdef GL_OES_single_precision + if (_glewStrSame3(&pos, &len, (const GLubyte*)"single_precision", 16)) + { + ret = GLEW_OES_single_precision; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4)) + { +#ifdef GL_OML_interlace + if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace", 9)) + { + ret = GLEW_OML_interlace; + continue; + } +#endif +#ifdef GL_OML_resample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"resample", 8)) + { + ret = GLEW_OML_resample; + continue; + } +#endif +#ifdef GL_OML_subsample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"subsample", 9)) + { + ret = GLEW_OML_subsample; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"PGI_", 4)) + { +#ifdef GL_PGI_misc_hints + if (_glewStrSame3(&pos, &len, (const GLubyte*)"misc_hints", 10)) + { + ret = GLEW_PGI_misc_hints; + continue; + } +#endif +#ifdef GL_PGI_vertex_hints + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_hints", 12)) + { + ret = GLEW_PGI_vertex_hints; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"REND_", 5)) + { +#ifdef GL_REND_screen_coordinates + if (_glewStrSame3(&pos, &len, (const GLubyte*)"screen_coordinates", 18)) + { + ret = GLEW_REND_screen_coordinates; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"S3_", 3)) + { +#ifdef GL_S3_s3tc + if (_glewStrSame3(&pos, &len, (const GLubyte*)"s3tc", 4)) + { + ret = GLEW_S3_s3tc; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIS_", 5)) + { +#ifdef GL_SGIS_color_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_range", 11)) + { + ret = GLEW_SGIS_color_range; + continue; + } +#endif +#ifdef GL_SGIS_detail_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"detail_texture", 14)) + { + ret = GLEW_SGIS_detail_texture; + continue; + } +#endif +#ifdef GL_SGIS_fog_function + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_function", 12)) + { + ret = GLEW_SGIS_fog_function; + continue; + } +#endif +#ifdef GL_SGIS_generate_mipmap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"generate_mipmap", 15)) + { + ret = GLEW_SGIS_generate_mipmap; + continue; + } +#endif +#ifdef GL_SGIS_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLEW_SGIS_multisample; + continue; + } +#endif +#ifdef GL_SGIS_pixel_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture", 13)) + { + ret = GLEW_SGIS_pixel_texture; + continue; + } +#endif +#ifdef GL_SGIS_point_line_texgen + if (_glewStrSame3(&pos, &len, (const GLubyte*)"point_line_texgen", 17)) + { + ret = GLEW_SGIS_point_line_texgen; + continue; + } +#endif +#ifdef GL_SGIS_sharpen_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sharpen_texture", 15)) + { + ret = GLEW_SGIS_sharpen_texture; + continue; + } +#endif +#ifdef GL_SGIS_texture4D + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture4D", 9)) + { + ret = GLEW_SGIS_texture4D; + continue; + } +#endif +#ifdef GL_SGIS_texture_border_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_border_clamp", 20)) + { + ret = GLEW_SGIS_texture_border_clamp; + continue; + } +#endif +#ifdef GL_SGIS_texture_edge_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_edge_clamp", 18)) + { + ret = GLEW_SGIS_texture_edge_clamp; + continue; + } +#endif +#ifdef GL_SGIS_texture_filter4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_filter4", 15)) + { + ret = GLEW_SGIS_texture_filter4; + continue; + } +#endif +#ifdef GL_SGIS_texture_lod + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod", 11)) + { + ret = GLEW_SGIS_texture_lod; + continue; + } +#endif +#ifdef GL_SGIS_texture_select + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_select", 14)) + { + ret = GLEW_SGIS_texture_select; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIX_", 5)) + { +#ifdef GL_SGIX_async + if (_glewStrSame3(&pos, &len, (const GLubyte*)"async", 5)) + { + ret = GLEW_SGIX_async; + continue; + } +#endif +#ifdef GL_SGIX_async_histogram + if (_glewStrSame3(&pos, &len, (const GLubyte*)"async_histogram", 15)) + { + ret = GLEW_SGIX_async_histogram; + continue; + } +#endif +#ifdef GL_SGIX_async_pixel + if (_glewStrSame3(&pos, &len, (const GLubyte*)"async_pixel", 11)) + { + ret = GLEW_SGIX_async_pixel; + continue; + } +#endif +#ifdef GL_SGIX_blend_alpha_minmax + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_alpha_minmax", 18)) + { + ret = GLEW_SGIX_blend_alpha_minmax; + continue; + } +#endif +#ifdef GL_SGIX_clipmap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"clipmap", 7)) + { + ret = GLEW_SGIX_clipmap; + continue; + } +#endif +#ifdef GL_SGIX_convolution_accuracy + if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_accuracy", 20)) + { + ret = GLEW_SGIX_convolution_accuracy; + continue; + } +#endif +#ifdef GL_SGIX_depth_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13)) + { + ret = GLEW_SGIX_depth_texture; + continue; + } +#endif +#ifdef GL_SGIX_flush_raster + if (_glewStrSame3(&pos, &len, (const GLubyte*)"flush_raster", 12)) + { + ret = GLEW_SGIX_flush_raster; + continue; + } +#endif +#ifdef GL_SGIX_fog_offset + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_offset", 10)) + { + ret = GLEW_SGIX_fog_offset; + continue; + } +#endif +#ifdef GL_SGIX_fog_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fog_texture", 11)) + { + ret = GLEW_SGIX_fog_texture; + continue; + } +#endif +#ifdef GL_SGIX_fragment_specular_lighting + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_specular_lighting", 26)) + { + ret = GLEW_SGIX_fragment_specular_lighting; + continue; + } +#endif +#ifdef GL_SGIX_framezoom + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framezoom", 9)) + { + ret = GLEW_SGIX_framezoom; + continue; + } +#endif +#ifdef GL_SGIX_interlace + if (_glewStrSame3(&pos, &len, (const GLubyte*)"interlace", 9)) + { + ret = GLEW_SGIX_interlace; + continue; + } +#endif +#ifdef GL_SGIX_ir_instrument1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ir_instrument1", 14)) + { + ret = GLEW_SGIX_ir_instrument1; + continue; + } +#endif +#ifdef GL_SGIX_list_priority + if (_glewStrSame3(&pos, &len, (const GLubyte*)"list_priority", 13)) + { + ret = GLEW_SGIX_list_priority; + continue; + } +#endif +#ifdef GL_SGIX_pixel_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture", 13)) + { + ret = GLEW_SGIX_pixel_texture; + continue; + } +#endif +#ifdef GL_SGIX_pixel_texture_bits + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_texture_bits", 18)) + { + ret = GLEW_SGIX_pixel_texture_bits; + continue; + } +#endif +#ifdef GL_SGIX_reference_plane + if (_glewStrSame3(&pos, &len, (const GLubyte*)"reference_plane", 15)) + { + ret = GLEW_SGIX_reference_plane; + continue; + } +#endif +#ifdef GL_SGIX_resample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"resample", 8)) + { + ret = GLEW_SGIX_resample; + continue; + } +#endif +#ifdef GL_SGIX_shadow + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow", 6)) + { + ret = GLEW_SGIX_shadow; + continue; + } +#endif +#ifdef GL_SGIX_shadow_ambient + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_ambient", 14)) + { + ret = GLEW_SGIX_shadow_ambient; + continue; + } +#endif +#ifdef GL_SGIX_sprite + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sprite", 6)) + { + ret = GLEW_SGIX_sprite; + continue; + } +#endif +#ifdef GL_SGIX_tag_sample_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"tag_sample_buffer", 17)) + { + ret = GLEW_SGIX_tag_sample_buffer; + continue; + } +#endif +#ifdef GL_SGIX_texture_add_env + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_add_env", 15)) + { + ret = GLEW_SGIX_texture_add_env; + continue; + } +#endif +#ifdef GL_SGIX_texture_coordinate_clamp + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_coordinate_clamp", 24)) + { + ret = GLEW_SGIX_texture_coordinate_clamp; + continue; + } +#endif +#ifdef GL_SGIX_texture_lod_bias + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_lod_bias", 16)) + { + ret = GLEW_SGIX_texture_lod_bias; + continue; + } +#endif +#ifdef GL_SGIX_texture_multi_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_multi_buffer", 20)) + { + ret = GLEW_SGIX_texture_multi_buffer; + continue; + } +#endif +#ifdef GL_SGIX_texture_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_range", 13)) + { + ret = GLEW_SGIX_texture_range; + continue; + } +#endif +#ifdef GL_SGIX_texture_scale_bias + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_scale_bias", 18)) + { + ret = GLEW_SGIX_texture_scale_bias; + continue; + } +#endif +#ifdef GL_SGIX_vertex_preclip + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_preclip", 14)) + { + ret = GLEW_SGIX_vertex_preclip; + continue; + } +#endif +#ifdef GL_SGIX_vertex_preclip_hint + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_preclip_hint", 19)) + { + ret = GLEW_SGIX_vertex_preclip_hint; + continue; + } +#endif +#ifdef GL_SGIX_ycrcb + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ycrcb", 5)) + { + ret = GLEW_SGIX_ycrcb; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGI_", 4)) + { +#ifdef GL_SGI_color_matrix + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_matrix", 12)) + { + ret = GLEW_SGI_color_matrix; + continue; + } +#endif +#ifdef GL_SGI_color_table + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_table", 11)) + { + ret = GLEW_SGI_color_table; + continue; + } +#endif +#ifdef GL_SGI_texture_color_table + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_color_table", 19)) + { + ret = GLEW_SGI_texture_color_table; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUNX_", 5)) + { +#ifdef GL_SUNX_constant_data + if (_glewStrSame3(&pos, &len, (const GLubyte*)"constant_data", 13)) + { + ret = GLEW_SUNX_constant_data; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUN_", 4)) + { +#ifdef GL_SUN_convolution_border_modes + if (_glewStrSame3(&pos, &len, (const GLubyte*)"convolution_border_modes", 24)) + { + ret = GLEW_SUN_convolution_border_modes; + continue; + } +#endif +#ifdef GL_SUN_global_alpha + if (_glewStrSame3(&pos, &len, (const GLubyte*)"global_alpha", 12)) + { + ret = GLEW_SUN_global_alpha; + continue; + } +#endif +#ifdef GL_SUN_mesh_array + if (_glewStrSame3(&pos, &len, (const GLubyte*)"mesh_array", 10)) + { + ret = GLEW_SUN_mesh_array; + continue; + } +#endif +#ifdef GL_SUN_read_video_pixels + if (_glewStrSame3(&pos, &len, (const GLubyte*)"read_video_pixels", 17)) + { + ret = GLEW_SUN_read_video_pixels; + continue; + } +#endif +#ifdef GL_SUN_slice_accum + if (_glewStrSame3(&pos, &len, (const GLubyte*)"slice_accum", 11)) + { + ret = GLEW_SUN_slice_accum; + continue; + } +#endif +#ifdef GL_SUN_triangle_list + if (_glewStrSame3(&pos, &len, (const GLubyte*)"triangle_list", 13)) + { + ret = GLEW_SUN_triangle_list; + continue; + } +#endif +#ifdef GL_SUN_vertex + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex", 6)) + { + ret = GLEW_SUN_vertex; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"WIN_", 4)) + { +#ifdef GL_WIN_phong_shading + if (_glewStrSame3(&pos, &len, (const GLubyte*)"phong_shading", 13)) + { + ret = GLEW_WIN_phong_shading; + continue; + } +#endif +#ifdef GL_WIN_specular_fog + if (_glewStrSame3(&pos, &len, (const GLubyte*)"specular_fog", 12)) + { + ret = GLEW_WIN_specular_fog; + continue; + } +#endif +#ifdef GL_WIN_swap_hint + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_hint", 9)) + { + ret = GLEW_WIN_swap_hint; + continue; + } +#endif + } + } + ret = (len == 0); + } + return ret; +} + +#if defined(_WIN32) + +#if defined(GLEW_MX) +GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name) +#else +GLboolean wglewIsSupported (const char* name) +#endif +{ + GLubyte* pos = (GLubyte*)name; + GLuint len = _glewStrLen(pos); + GLboolean ret = GL_TRUE; + while (ret && len > 0) + { + if (_glewStrSame1(&pos, &len, (const GLubyte*)"WGL_", 4)) + { + if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5)) + { +#ifdef WGL_3DFX_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = WGLEW_3DFX_multisample; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DL_", 4)) + { +#ifdef WGL_3DL_stereo_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stereo_control", 14)) + { + ret = WGLEW_3DL_stereo_control; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"AMD_", 4)) + { +#ifdef WGL_AMD_gpu_association + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_association", 15)) + { + ret = WGLEW_AMD_gpu_association; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4)) + { +#ifdef WGL_ARB_buffer_region + if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_region", 13)) + { + ret = WGLEW_ARB_buffer_region; + continue; + } +#endif +#ifdef WGL_ARB_create_context + if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context", 14)) + { + ret = WGLEW_ARB_create_context; + continue; + } +#endif +#ifdef WGL_ARB_create_context_profile + if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_profile", 22)) + { + ret = WGLEW_ARB_create_context_profile; + continue; + } +#endif +#ifdef WGL_ARB_create_context_robustness + if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_robustness", 25)) + { + ret = WGLEW_ARB_create_context_robustness; + continue; + } +#endif +#ifdef WGL_ARB_extensions_string + if (_glewStrSame3(&pos, &len, (const GLubyte*)"extensions_string", 17)) + { + ret = WGLEW_ARB_extensions_string; + continue; + } +#endif +#ifdef WGL_ARB_framebuffer_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16)) + { + ret = WGLEW_ARB_framebuffer_sRGB; + continue; + } +#endif +#ifdef WGL_ARB_make_current_read + if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17)) + { + ret = WGLEW_ARB_make_current_read; + continue; + } +#endif +#ifdef WGL_ARB_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = WGLEW_ARB_multisample; + continue; + } +#endif +#ifdef WGL_ARB_pbuffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7)) + { + ret = WGLEW_ARB_pbuffer; + continue; + } +#endif +#ifdef WGL_ARB_pixel_format + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format", 12)) + { + ret = WGLEW_ARB_pixel_format; + continue; + } +#endif +#ifdef WGL_ARB_pixel_format_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18)) + { + ret = WGLEW_ARB_pixel_format_float; + continue; + } +#endif +#ifdef WGL_ARB_render_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture", 14)) + { + ret = WGLEW_ARB_render_texture; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4)) + { +#ifdef WGL_ATI_pixel_format_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18)) + { + ret = WGLEW_ATI_pixel_format_float; + continue; + } +#endif +#ifdef WGL_ATI_render_texture_rectangle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture_rectangle", 24)) + { + ret = WGLEW_ATI_render_texture_rectangle; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4)) + { +#ifdef WGL_EXT_create_context_es2_profile + if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es2_profile", 26)) + { + ret = WGLEW_EXT_create_context_es2_profile; + continue; + } +#endif +#ifdef WGL_EXT_depth_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_float", 11)) + { + ret = WGLEW_EXT_depth_float; + continue; + } +#endif +#ifdef WGL_EXT_display_color_table + if (_glewStrSame3(&pos, &len, (const GLubyte*)"display_color_table", 19)) + { + ret = WGLEW_EXT_display_color_table; + continue; + } +#endif +#ifdef WGL_EXT_extensions_string + if (_glewStrSame3(&pos, &len, (const GLubyte*)"extensions_string", 17)) + { + ret = WGLEW_EXT_extensions_string; + continue; + } +#endif +#ifdef WGL_EXT_framebuffer_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16)) + { + ret = WGLEW_EXT_framebuffer_sRGB; + continue; + } +#endif +#ifdef WGL_EXT_make_current_read + if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17)) + { + ret = WGLEW_EXT_make_current_read; + continue; + } +#endif +#ifdef WGL_EXT_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = WGLEW_EXT_multisample; + continue; + } +#endif +#ifdef WGL_EXT_pbuffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7)) + { + ret = WGLEW_EXT_pbuffer; + continue; + } +#endif +#ifdef WGL_EXT_pixel_format + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format", 12)) + { + ret = WGLEW_EXT_pixel_format; + continue; + } +#endif +#ifdef WGL_EXT_pixel_format_packed_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_packed_float", 25)) + { + ret = WGLEW_EXT_pixel_format_packed_float; + continue; + } +#endif +#ifdef WGL_EXT_swap_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12)) + { + ret = WGLEW_EXT_swap_control; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"I3D_", 4)) + { +#ifdef WGL_I3D_digital_video_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"digital_video_control", 21)) + { + ret = WGLEW_I3D_digital_video_control; + continue; + } +#endif +#ifdef WGL_I3D_gamma + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gamma", 5)) + { + ret = WGLEW_I3D_gamma; + continue; + } +#endif +#ifdef WGL_I3D_genlock + if (_glewStrSame3(&pos, &len, (const GLubyte*)"genlock", 7)) + { + ret = WGLEW_I3D_genlock; + continue; + } +#endif +#ifdef WGL_I3D_image_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"image_buffer", 12)) + { + ret = WGLEW_I3D_image_buffer; + continue; + } +#endif +#ifdef WGL_I3D_swap_frame_lock + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_frame_lock", 15)) + { + ret = WGLEW_I3D_swap_frame_lock; + continue; + } +#endif +#ifdef WGL_I3D_swap_frame_usage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_frame_usage", 16)) + { + ret = WGLEW_I3D_swap_frame_usage; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3)) + { +#ifdef WGL_NV_DX_interop + if (_glewStrSame3(&pos, &len, (const GLubyte*)"DX_interop", 10)) + { + ret = WGLEW_NV_DX_interop; + continue; + } +#endif +#ifdef WGL_NV_copy_image + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10)) + { + ret = WGLEW_NV_copy_image; + continue; + } +#endif +#ifdef WGL_NV_float_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12)) + { + ret = WGLEW_NV_float_buffer; + continue; + } +#endif +#ifdef WGL_NV_gpu_affinity + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_affinity", 12)) + { + ret = WGLEW_NV_gpu_affinity; + continue; + } +#endif +#ifdef WGL_NV_multisample_coverage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample_coverage", 20)) + { + ret = WGLEW_NV_multisample_coverage; + continue; + } +#endif +#ifdef WGL_NV_present_video + if (_glewStrSame3(&pos, &len, (const GLubyte*)"present_video", 13)) + { + ret = WGLEW_NV_present_video; + continue; + } +#endif +#ifdef WGL_NV_render_depth_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_depth_texture", 20)) + { + ret = WGLEW_NV_render_depth_texture; + continue; + } +#endif +#ifdef WGL_NV_render_texture_rectangle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture_rectangle", 24)) + { + ret = WGLEW_NV_render_texture_rectangle; + continue; + } +#endif +#ifdef WGL_NV_swap_group + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_group", 10)) + { + ret = WGLEW_NV_swap_group; + continue; + } +#endif +#ifdef WGL_NV_vertex_array_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18)) + { + ret = WGLEW_NV_vertex_array_range; + continue; + } +#endif +#ifdef WGL_NV_video_capture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_capture", 13)) + { + ret = WGLEW_NV_video_capture; + continue; + } +#endif +#ifdef WGL_NV_video_output + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_output", 12)) + { + ret = WGLEW_NV_video_output; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4)) + { +#ifdef WGL_OML_sync_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync_control", 12)) + { + ret = WGLEW_OML_sync_control; + continue; + } +#endif + } + } + ret = (len == 0); + } + return ret; +} + +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) + +#if defined(GLEW_MX) +GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name) +#else +GLboolean glxewIsSupported (const char* name) +#endif +{ + GLubyte* pos = (GLubyte*)name; + GLuint len = _glewStrLen(pos); + GLboolean ret = GL_TRUE; + while (ret && len > 0) + { + if(_glewStrSame1(&pos, &len, (const GLubyte*)"GLX_", 4)) + { + if (_glewStrSame2(&pos, &len, (const GLubyte*)"VERSION_", 8)) + { +#ifdef GLX_VERSION_1_2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_2", 3)) + { + ret = GLXEW_VERSION_1_2; + continue; + } +#endif +#ifdef GLX_VERSION_1_3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_3", 3)) + { + ret = GLXEW_VERSION_1_3; + continue; + } +#endif +#ifdef GLX_VERSION_1_4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"1_4", 3)) + { + ret = GLXEW_VERSION_1_4; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5)) + { +#ifdef GLX_3DFX_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLXEW_3DFX_multisample; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"AMD_", 4)) + { +#ifdef GLX_AMD_gpu_association + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_association", 15)) + { + ret = GLXEW_AMD_gpu_association; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ARB_", 4)) + { +#ifdef GLX_ARB_create_context + if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context", 14)) + { + ret = GLXEW_ARB_create_context; + continue; + } +#endif +#ifdef GLX_ARB_create_context_profile + if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_profile", 22)) + { + ret = GLXEW_ARB_create_context_profile; + continue; + } +#endif +#ifdef GLX_ARB_create_context_robustness + if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_robustness", 25)) + { + ret = GLXEW_ARB_create_context_robustness; + continue; + } +#endif +#ifdef GLX_ARB_fbconfig_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig_float", 14)) + { + ret = GLXEW_ARB_fbconfig_float; + continue; + } +#endif +#ifdef GLX_ARB_framebuffer_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16)) + { + ret = GLXEW_ARB_framebuffer_sRGB; + continue; + } +#endif +#ifdef GLX_ARB_get_proc_address + if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_proc_address", 16)) + { + ret = GLXEW_ARB_get_proc_address; + continue; + } +#endif +#ifdef GLX_ARB_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLXEW_ARB_multisample; + continue; + } +#endif +#ifdef GLX_ARB_vertex_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_buffer_object", 20)) + { + ret = GLXEW_ARB_vertex_buffer_object; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4)) + { +#ifdef GLX_ATI_pixel_format_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_format_float", 18)) + { + ret = GLXEW_ATI_pixel_format_float; + continue; + } +#endif +#ifdef GLX_ATI_render_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"render_texture", 14)) + { + ret = GLXEW_ATI_render_texture; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4)) + { +#ifdef GLX_EXT_create_context_es2_profile + if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es2_profile", 26)) + { + ret = GLXEW_EXT_create_context_es2_profile; + continue; + } +#endif +#ifdef GLX_EXT_fbconfig_packed_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig_packed_float", 21)) + { + ret = GLXEW_EXT_fbconfig_packed_float; + continue; + } +#endif +#ifdef GLX_EXT_framebuffer_sRGB + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_sRGB", 16)) + { + ret = GLXEW_EXT_framebuffer_sRGB; + continue; + } +#endif +#ifdef GLX_EXT_import_context + if (_glewStrSame3(&pos, &len, (const GLubyte*)"import_context", 14)) + { + ret = GLXEW_EXT_import_context; + continue; + } +#endif +#ifdef GLX_EXT_scene_marker + if (_glewStrSame3(&pos, &len, (const GLubyte*)"scene_marker", 12)) + { + ret = GLXEW_EXT_scene_marker; + continue; + } +#endif +#ifdef GLX_EXT_swap_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12)) + { + ret = GLXEW_EXT_swap_control; + continue; + } +#endif +#ifdef GLX_EXT_texture_from_pixmap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_from_pixmap", 19)) + { + ret = GLXEW_EXT_texture_from_pixmap; + continue; + } +#endif +#ifdef GLX_EXT_visual_info + if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_info", 11)) + { + ret = GLXEW_EXT_visual_info; + continue; + } +#endif +#ifdef GLX_EXT_visual_rating + if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_rating", 13)) + { + ret = GLXEW_EXT_visual_rating; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"INTEL_", 6)) + { +#ifdef GLX_INTEL_swap_event + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_event", 10)) + { + ret = GLXEW_INTEL_swap_event; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"MESA_", 5)) + { +#ifdef GLX_MESA_agp_offset + if (_glewStrSame3(&pos, &len, (const GLubyte*)"agp_offset", 10)) + { + ret = GLXEW_MESA_agp_offset; + continue; + } +#endif +#ifdef GLX_MESA_copy_sub_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_sub_buffer", 15)) + { + ret = GLXEW_MESA_copy_sub_buffer; + continue; + } +#endif +#ifdef GLX_MESA_pixmap_colormap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixmap_colormap", 15)) + { + ret = GLXEW_MESA_pixmap_colormap; + continue; + } +#endif +#ifdef GLX_MESA_release_buffers + if (_glewStrSame3(&pos, &len, (const GLubyte*)"release_buffers", 15)) + { + ret = GLXEW_MESA_release_buffers; + continue; + } +#endif +#ifdef GLX_MESA_set_3dfx_mode + if (_glewStrSame3(&pos, &len, (const GLubyte*)"set_3dfx_mode", 13)) + { + ret = GLXEW_MESA_set_3dfx_mode; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3)) + { +#ifdef GLX_NV_copy_image + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10)) + { + ret = GLXEW_NV_copy_image; + continue; + } +#endif +#ifdef GLX_NV_float_buffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12)) + { + ret = GLXEW_NV_float_buffer; + continue; + } +#endif +#ifdef GLX_NV_multisample_coverage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample_coverage", 20)) + { + ret = GLXEW_NV_multisample_coverage; + continue; + } +#endif +#ifdef GLX_NV_present_video + if (_glewStrSame3(&pos, &len, (const GLubyte*)"present_video", 13)) + { + ret = GLXEW_NV_present_video; + continue; + } +#endif +#ifdef GLX_NV_swap_group + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_group", 10)) + { + ret = GLXEW_NV_swap_group; + continue; + } +#endif +#ifdef GLX_NV_vertex_array_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_array_range", 18)) + { + ret = GLXEW_NV_vertex_array_range; + continue; + } +#endif +#ifdef GLX_NV_video_capture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_capture", 13)) + { + ret = GLXEW_NV_video_capture; + continue; + } +#endif +#ifdef GLX_NV_video_output + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_output", 12)) + { + ret = GLXEW_NV_video_output; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"OML_", 4)) + { +#ifdef GLX_OML_swap_method + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_method", 11)) + { + ret = GLXEW_OML_swap_method; + continue; + } +#endif +#ifdef GLX_OML_sync_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync_control", 12)) + { + ret = GLXEW_OML_sync_control; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIS_", 5)) + { +#ifdef GLX_SGIS_blended_overlay + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blended_overlay", 15)) + { + ret = GLXEW_SGIS_blended_overlay; + continue; + } +#endif +#ifdef GLX_SGIS_color_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_range", 11)) + { + ret = GLXEW_SGIS_color_range; + continue; + } +#endif +#ifdef GLX_SGIS_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) + { + ret = GLXEW_SGIS_multisample; + continue; + } +#endif +#ifdef GLX_SGIS_shared_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shared_multisample", 18)) + { + ret = GLXEW_SGIS_shared_multisample; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGIX_", 5)) + { +#ifdef GLX_SGIX_fbconfig + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig", 8)) + { + ret = GLXEW_SGIX_fbconfig; + continue; + } +#endif +#ifdef GLX_SGIX_hyperpipe + if (_glewStrSame3(&pos, &len, (const GLubyte*)"hyperpipe", 9)) + { + ret = GLXEW_SGIX_hyperpipe; + continue; + } +#endif +#ifdef GLX_SGIX_pbuffer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pbuffer", 7)) + { + ret = GLXEW_SGIX_pbuffer; + continue; + } +#endif +#ifdef GLX_SGIX_swap_barrier + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_barrier", 12)) + { + ret = GLXEW_SGIX_swap_barrier; + continue; + } +#endif +#ifdef GLX_SGIX_swap_group + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_group", 10)) + { + ret = GLXEW_SGIX_swap_group; + continue; + } +#endif +#ifdef GLX_SGIX_video_resize + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_resize", 12)) + { + ret = GLXEW_SGIX_video_resize; + continue; + } +#endif +#ifdef GLX_SGIX_visual_select_group + if (_glewStrSame3(&pos, &len, (const GLubyte*)"visual_select_group", 19)) + { + ret = GLXEW_SGIX_visual_select_group; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SGI_", 4)) + { +#ifdef GLX_SGI_cushion + if (_glewStrSame3(&pos, &len, (const GLubyte*)"cushion", 7)) + { + ret = GLXEW_SGI_cushion; + continue; + } +#endif +#ifdef GLX_SGI_make_current_read + if (_glewStrSame3(&pos, &len, (const GLubyte*)"make_current_read", 17)) + { + ret = GLXEW_SGI_make_current_read; + continue; + } +#endif +#ifdef GLX_SGI_swap_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12)) + { + ret = GLXEW_SGI_swap_control; + continue; + } +#endif +#ifdef GLX_SGI_video_sync + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_sync", 10)) + { + ret = GLXEW_SGI_video_sync; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"SUN_", 4)) + { +#ifdef GLX_SUN_get_transparent_index + if (_glewStrSame3(&pos, &len, (const GLubyte*)"get_transparent_index", 21)) + { + ret = GLXEW_SUN_get_transparent_index; + continue; + } +#endif +#ifdef GLX_SUN_video_resize + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_resize", 12)) + { + ret = GLXEW_SUN_video_resize; + continue; + } +#endif + } + } + ret = (len == 0); + } + return ret; +} + +#endif /* _WIN32 */ diff --git a/ext/glew/glewinfo.c b/ext/glew/glewinfo.c new file mode 100644 index 0000000000..7f22c560b1 --- /dev/null +++ b/ext/glew/glewinfo.c @@ -0,0 +1,9081 @@ +/* +** The OpenGL Extension Wrangler Library +** Copyright (C) 2002-2008, Milan Ikits +** Copyright (C) 2002-2008, Marcelo E. Magallon +** Copyright (C) 2002, Lev Povalahev +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** * The name of the author may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +** THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#if defined(_WIN32) +#include +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +#include +#endif + +static FILE* f; + +#ifdef GLEW_MX +GLEWContext _glewctx; +#define glewGetContext() (&_glewctx) +#ifdef _WIN32 +WGLEWContext _wglewctx; +#define wglewGetContext() (&_wglewctx) +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +GLXEWContext _glxewctx; +#define glxewGetContext() (&_glxewctx) +#endif +#endif + +#if defined(_WIN32) +GLboolean glewCreateContext (int* pixelformat); +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +GLboolean glewCreateContext (const char* display, int* visual); +#else +GLboolean glewCreateContext (); +#endif + +#if defined(_WIN32) || !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +GLboolean glewParseArgs (int argc, char** argv, char** display, int* visual); +#endif + +void glewDestroyContext (); + +/* ------------------------------------------------------------------------- */ + +static void glewPrintExt (const char* name, GLboolean def1, GLboolean def2, GLboolean def3) +{ + unsigned int i; + fprintf(f, "\n%s:", name); + for (i=0; i<62-strlen(name); i++) fprintf(f, " "); + fprintf(f, "%s ", def1 ? "OK" : "MISSING"); + if (def1 != def2) + fprintf(f, "[%s] ", def2 ? "OK" : "MISSING"); + if (def1 != def3) + fprintf(f, "[%s]\n", def3 ? "OK" : "MISSING"); + else + fprintf(f, "\n"); + for (i=0; i]\n"); +#else + fprintf(stderr, "Usage: glewinfo [-display ] [-visual ]\n"); +#endif + return 1; + } +#endif + +#if defined(_WIN32) + if (GL_TRUE == glewCreateContext(&visual)) +#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) + if (GL_TRUE == glewCreateContext()) +#else + if (GL_TRUE == glewCreateContext(display, &visual)) +#endif + { + fprintf(stderr, "Error: glewCreateContext failed\n"); + glewDestroyContext(); + return 1; + } + glewExperimental = GL_TRUE; +#ifdef GLEW_MX + err = glewContextInit(glewGetContext()); +#ifdef _WIN32 + err = err || wglewContextInit(wglewGetContext()); +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) + err = err || glxewContextInit(glxewGetContext()); +#endif + +#else + err = glewInit(); +#endif + if (GLEW_OK != err) + { + fprintf(stderr, "Error [main]: glewInit failed: %s\n", glewGetErrorString(err)); + glewDestroyContext(); + return 1; + } +#if defined(_WIN32) + f = fopen("glewinfo.txt", "w"); + if (f == NULL) f = stdout; +#else + f = stdout; +#endif + fprintf(f, "---------------------------\n"); + fprintf(f, " GLEW Extension Info\n"); + fprintf(f, "---------------------------\n\n"); + fprintf(f, "GLEW version %s\n", glewGetString(GLEW_VERSION)); +#if defined(_WIN32) + fprintf(f, "Reporting capabilities of pixelformat %d\n", visual); +#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) + fprintf(f, "Reporting capabilities of display %s, visual 0x%x\n", + display == NULL ? getenv("DISPLAY") : display, visual); +#endif + fprintf(f, "Running on a %s from %s\n", + glGetString(GL_RENDERER), glGetString(GL_VENDOR)); + fprintf(f, "OpenGL version %s is supported\n", glGetString(GL_VERSION)); + glewInfo(); +#if defined(_WIN32) + wglewInfo(); +#else + glxewInfo(); +#endif + if (f != stdout) fclose(f); + glewDestroyContext(); + return 0; +} + +/* ------------------------------------------------------------------------ */ + +#if defined(_WIN32) || !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +GLboolean glewParseArgs (int argc, char** argv, char** display, int* visual) +{ + int p = 0; + while (p < argc) + { +#if defined(_WIN32) + if (!strcmp(argv[p], "-pf") || !strcmp(argv[p], "-pixelformat")) + { + if (++p >= argc) return GL_TRUE; + *display = 0; + *visual = strtol(argv[p++], NULL, 0); + } + else + return GL_TRUE; +#else + if (!strcmp(argv[p], "-display")) + { + if (++p >= argc) return GL_TRUE; + *display = argv[p++]; + } + else if (!strcmp(argv[p], "-visual")) + { + if (++p >= argc) return GL_TRUE; + *visual = (int)strtol(argv[p++], NULL, 0); + } + else + return GL_TRUE; +#endif + } + return GL_FALSE; +} +#endif + +/* ------------------------------------------------------------------------ */ + +#if defined(_WIN32) + +HWND wnd = NULL; +HDC dc = NULL; +HGLRC rc = NULL; + +GLboolean glewCreateContext (int* pixelformat) +{ + WNDCLASS wc; + PIXELFORMATDESCRIPTOR pfd; + /* register window class */ + ZeroMemory(&wc, sizeof(WNDCLASS)); + wc.hInstance = GetModuleHandle(NULL); + wc.lpfnWndProc = DefWindowProc; + wc.lpszClassName = "GLEW"; + if (0 == RegisterClass(&wc)) return GL_TRUE; + /* create window */ + wnd = CreateWindow("GLEW", "GLEW", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL); + if (NULL == wnd) return GL_TRUE; + /* get the device context */ + dc = GetDC(wnd); + if (NULL == dc) return GL_TRUE; + /* find pixel format */ + ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); + if (*pixelformat == -1) /* find default */ + { + pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + *pixelformat = ChoosePixelFormat(dc, &pfd); + if (*pixelformat == 0) return GL_TRUE; + } + /* set the pixel format for the dc */ + if (FALSE == SetPixelFormat(dc, *pixelformat, &pfd)) return GL_TRUE; + /* create rendering context */ + rc = wglCreateContext(dc); + if (NULL == rc) return GL_TRUE; + if (FALSE == wglMakeCurrent(dc, rc)) return GL_TRUE; + return GL_FALSE; +} + +void glewDestroyContext () +{ + if (NULL != rc) wglMakeCurrent(NULL, NULL); + if (NULL != rc) wglDeleteContext(rc); + if (NULL != wnd && NULL != dc) ReleaseDC(wnd, dc); + if (NULL != wnd) DestroyWindow(wnd); + UnregisterClass("GLEW", GetModuleHandle(NULL)); +} + +/* ------------------------------------------------------------------------ */ + +#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) + +#include + +AGLContext ctx, octx; + +GLboolean glewCreateContext () +{ + int attrib[] = { AGL_RGBA, AGL_NONE }; + AGLPixelFormat pf; + /*int major, minor; + SetPortWindowPort(wnd); + aglGetVersion(&major, &minor); + fprintf(stderr, "GL %d.%d\n", major, minor);*/ + pf = aglChoosePixelFormat(NULL, 0, attrib); + if (NULL == pf) return GL_TRUE; + ctx = aglCreateContext(pf, NULL); + if (NULL == ctx || AGL_NO_ERROR != aglGetError()) return GL_TRUE; + aglDestroyPixelFormat(pf); + /*aglSetDrawable(ctx, GetWindowPort(wnd));*/ + octx = aglGetCurrentContext(); + if (GL_FALSE == aglSetCurrentContext(ctx)) return GL_TRUE; + return GL_FALSE; +} + +void glewDestroyContext () +{ + aglSetCurrentContext(octx); + if (NULL != ctx) aglDestroyContext(ctx); +} + +/* ------------------------------------------------------------------------ */ + +#else /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */ + +Display* dpy = NULL; +XVisualInfo* vi = NULL; +XVisualInfo* vis = NULL; +GLXContext ctx = NULL; +Window wnd = 0; +Colormap cmap = 0; + +GLboolean glewCreateContext (const char* display, int* visual) +{ + int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None }; + int erb, evb; + XSetWindowAttributes swa; + /* open display */ + dpy = XOpenDisplay(display); + if (NULL == dpy) return GL_TRUE; + /* query for glx */ + if (!glXQueryExtension(dpy, &erb, &evb)) return GL_TRUE; + /* choose visual */ + if (*visual == -1) + { + vi = glXChooseVisual(dpy, DefaultScreen(dpy), attrib); + if (NULL == vi) return GL_TRUE; + *visual = (int)XVisualIDFromVisual(vi->visual); + } + else + { + int n_vis, i; + vis = XGetVisualInfo(dpy, 0, NULL, &n_vis); + for (i=0; iscreen), 0, 0, 1, 1, 1, 0, 0);*/ + cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone); + swa.border_pixel = 0; + swa.colormap = cmap; + wnd = XCreateWindow(dpy, RootWindow(dpy, vi->screen), + 0, 0, 1, 1, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap, &swa); + /* make context current */ + if (!glXMakeCurrent(dpy, wnd, ctx)) return GL_TRUE; + return GL_FALSE; +} + +void glewDestroyContext () +{ + if (NULL != dpy && NULL != ctx) glXDestroyContext(dpy, ctx); + if (NULL != dpy && 0 != wnd) XDestroyWindow(dpy, wnd); + if (NULL != dpy && 0 != cmap) XFreeColormap(dpy, cmap); + if (NULL != vis) + XFree(vis); + else if (NULL != vi) + XFree(vi); + if (NULL != dpy) XCloseDisplay(dpy); +} + +#endif /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */ diff --git a/ext/glew/visualinfo.c b/ext/glew/visualinfo.c new file mode 100644 index 0000000000..52839c5d2a --- /dev/null +++ b/ext/glew/visualinfo.c @@ -0,0 +1,1176 @@ +/* +** visualinfo.c +** +** Copyright (C) Nate Robins, 1997 +** Michael Wimmer, 1999 +** Milan Ikits, 2002-2008 +** +** visualinfo is a small utility that displays all available visuals, +** aka. pixelformats, in an OpenGL system along with renderer version +** information. It shows a table of all the visuals that support OpenGL +** along with their capabilities. The format of the table is similar to +** that of glxinfo on Unix systems: +** +** visual ~= pixel format descriptor +** id = visual id (integer from 1 - max visuals) +** tp = type (wn: window, pb: pbuffer, wp: window & pbuffer, bm: bitmap) +** ac = acceleration (ge: generic, fu: full, no: none) +** fm = format (i: integer, f: float, c: color index) +** db = double buffer (y = yes) +** sw = swap method (x: exchange, c: copy, u: undefined) +** st = stereo (y = yes) +** sz = total # bits +** r = # bits of red +** g = # bits of green +** b = # bits of blue +** a = # bits of alpha +** axbf = # aux buffers +** dpth = # bits of depth +** stcl = # bits of stencil +*/ + +#include +#include +#include +#include +#if defined(_WIN32) +#include +#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) +#include +#else +#include +#endif + +#ifdef GLEW_MX +GLEWContext _glewctx; +# define glewGetContext() (&_glewctx) +# ifdef _WIN32 +WGLEWContext _wglewctx; +# define wglewGetContext() (&_wglewctx) +# elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +GLXEWContext _glxewctx; +# define glxewGetContext() (&_glxewctx) +# endif +#endif /* GLEW_MX */ + +typedef struct GLContextStruct +{ +#ifdef _WIN32 + HWND wnd; + HDC dc; + HGLRC rc; +#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) + AGLContext ctx, octx; +#else + Display* dpy; + XVisualInfo* vi; + GLXContext ctx; + Window wnd; + Colormap cmap; +#endif +} GLContext; + +void InitContext (GLContext* ctx); +GLboolean CreateContext (GLContext* ctx); +void DestroyContext (GLContext* ctx); +void VisualInfo (GLContext* ctx); +void PrintExtensions (const char* s); +GLboolean ParseArgs (int argc, char** argv); + +int showall = 0; +int displaystdout = 0; +int verbose = 0; +int drawableonly = 0; + +char* display = NULL; +int visual = -1; + +FILE* file = 0; + +int +main (int argc, char** argv) +{ + GLenum err; + GLContext ctx; + + /* ---------------------------------------------------------------------- */ + /* parse arguments */ + if (GL_TRUE == ParseArgs(argc-1, argv+1)) + { +#if defined(_WIN32) + fprintf(stderr, "Usage: visualinfo [-a] [-s] [-h] [-pf ]\n"); + fprintf(stderr, " -a: show all visuals\n"); + fprintf(stderr, " -s: display to stdout instead of visualinfo.txt\n"); + fprintf(stderr, " -pf : use given pixelformat\n"); + fprintf(stderr, " -h: this screen\n"); +#else + fprintf(stderr, "Usage: visualinfo [-h] [-display ] [-visual ]\n"); + fprintf(stderr, " -h: this screen\n"); + fprintf(stderr, " -display : use given display\n"); + fprintf(stderr, " -visual : use given visual\n"); +#endif + return 1; + } + + /* ---------------------------------------------------------------------- */ + /* create OpenGL rendering context */ + InitContext(&ctx); + if (GL_TRUE == CreateContext(&ctx)) + { + fprintf(stderr, "Error: CreateContext failed\n"); + DestroyContext(&ctx); + return 1; + } + + /* ---------------------------------------------------------------------- */ + /* initialize GLEW */ + glewExperimental = GL_TRUE; +#ifdef GLEW_MX + err = glewContextInit(glewGetContext()); +# ifdef _WIN32 + err = err || wglewContextInit(wglewGetContext()); +# elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) + err = err || glxewContextInit(glxewGetContext()); +# endif +#else + err = glewInit(); +#endif + if (GLEW_OK != err) + { + fprintf(stderr, "Error [main]: glewInit failed: %s\n", glewGetErrorString(err)); + DestroyContext(&ctx); + return 1; + } + + /* ---------------------------------------------------------------------- */ + /* open file */ +#if defined(_WIN32) + if (!displaystdout) + file = fopen("visualinfo.txt", "w"); + if (file == NULL) + file = stdout; +#else + file = stdout; +#endif + + /* ---------------------------------------------------------------------- */ + /* output header information */ + /* OpenGL extensions */ + fprintf(file, "OpenGL vendor string: %s\n", glGetString(GL_VENDOR)); + fprintf(file, "OpenGL renderer string: %s\n", glGetString(GL_RENDERER)); + fprintf(file, "OpenGL version string: %s\n", glGetString(GL_VERSION)); + fprintf(file, "OpenGL extensions (GL_): \n"); + PrintExtensions((char*)glGetString(GL_EXTENSIONS)); + +#ifndef GLEW_NO_GLU + /* GLU extensions */ + fprintf(file, "GLU version string: %s\n", gluGetString(GLU_VERSION)); + fprintf(file, "GLU extensions (GLU_): \n"); + PrintExtensions((char*)gluGetString(GLU_EXTENSIONS)); +#endif + + /* ---------------------------------------------------------------------- */ + /* extensions string */ +#if defined(_WIN32) + /* WGL extensions */ + if (WGLEW_ARB_extensions_string || WGLEW_EXT_extensions_string) + { + fprintf(file, "WGL extensions (WGL_): \n"); + PrintExtensions(wglGetExtensionsStringARB ? + (char*)wglGetExtensionsStringARB(ctx.dc) : + (char*)wglGetExtensionsStringEXT()); + } +#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) + +#else + /* GLX extensions */ + fprintf(file, "GLX extensions (GLX_): \n"); + PrintExtensions(glXQueryExtensionsString(glXGetCurrentDisplay(), + DefaultScreen(glXGetCurrentDisplay()))); +#endif + + /* ---------------------------------------------------------------------- */ + /* enumerate all the formats */ + VisualInfo(&ctx); + + /* ---------------------------------------------------------------------- */ + /* release resources */ + DestroyContext(&ctx); + if (file != stdout) + fclose(file); + return 0; +} + +/* do the magic to separate all extensions with comma's, except + for the last one that _may_ terminate in a space. */ +void PrintExtensions (const char* s) +{ + char t[80]; + int i=0; + char* p=0; + + t[79] = '\0'; + while (*s) + { + t[i++] = *s; + if(*s == ' ') + { + if (*(s+1) != '\0') { + t[i-1] = ','; + t[i] = ' '; + p = &t[i++]; + } + else /* zoinks! last one terminated in a space! */ + { + t[i-1] = '\0'; + } + } + if(i > 80 - 5) + { + *p = t[i] = '\0'; + fprintf(file, " %s\n", t); + p++; + i = (int)strlen(p); + strcpy(t, p); + } + s++; + } + t[i] = '\0'; + fprintf(file, " %s.\n", t); +} + +/* ---------------------------------------------------------------------- */ + +#if defined(_WIN32) + +void +VisualInfoARB (GLContext* ctx) +{ + int attrib[32], value[32], n_attrib, n_pbuffer=0, n_float=0; + int i, pf, maxpf; + unsigned int c; + + /* to get pbuffer capable pixel formats */ + attrib[0] = WGL_DRAW_TO_PBUFFER_ARB; + attrib[1] = GL_TRUE; + attrib[2] = 0; + wglChoosePixelFormatARB(ctx->dc, attrib, 0, 1, &pf, &c); + /* query number of pixel formats */ + attrib[0] = WGL_NUMBER_PIXEL_FORMATS_ARB; + wglGetPixelFormatAttribivARB(ctx->dc, 0, 0, 1, attrib, value); + maxpf = value[0]; + for (i=0; i<32; i++) + value[i] = 0; + + attrib[0] = WGL_SUPPORT_OPENGL_ARB; + attrib[1] = WGL_DRAW_TO_WINDOW_ARB; + attrib[2] = WGL_DRAW_TO_BITMAP_ARB; + attrib[3] = WGL_ACCELERATION_ARB; + /* WGL_NO_ACCELERATION_ARB, WGL_GENERIC_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB */ + attrib[4] = WGL_SWAP_METHOD_ARB; + /* WGL_SWAP_EXCHANGE_ARB, WGL_SWAP_COPY_ARB, WGL_SWAP_UNDEFINED_ARB */ + attrib[5] = WGL_DOUBLE_BUFFER_ARB; + attrib[6] = WGL_STEREO_ARB; + attrib[7] = WGL_PIXEL_TYPE_ARB; + /* WGL_TYPE_RGBA_ARB, WGL_TYPE_COLORINDEX_ARB, + WGL_TYPE_RGBA_FLOAT_ATI (WGL_ATI_pixel_format_float) */ + /* Color buffer information */ + attrib[8] = WGL_COLOR_BITS_ARB; + attrib[9] = WGL_RED_BITS_ARB; + attrib[10] = WGL_GREEN_BITS_ARB; + attrib[11] = WGL_BLUE_BITS_ARB; + attrib[12] = WGL_ALPHA_BITS_ARB; + /* Accumulation buffer information */ + attrib[13] = WGL_ACCUM_BITS_ARB; + attrib[14] = WGL_ACCUM_RED_BITS_ARB; + attrib[15] = WGL_ACCUM_GREEN_BITS_ARB; + attrib[16] = WGL_ACCUM_BLUE_BITS_ARB; + attrib[17] = WGL_ACCUM_ALPHA_BITS_ARB; + /* Depth, stencil, and aux buffer information */ + attrib[18] = WGL_DEPTH_BITS_ARB; + attrib[19] = WGL_STENCIL_BITS_ARB; + attrib[20] = WGL_AUX_BUFFERS_ARB; + /* Layer information */ + attrib[21] = WGL_NUMBER_OVERLAYS_ARB; + attrib[22] = WGL_NUMBER_UNDERLAYS_ARB; + attrib[23] = WGL_SWAP_LAYER_BUFFERS_ARB; + attrib[24] = WGL_SAMPLES_ARB; + attrib[25] = WGL_SUPPORT_GDI_ARB; + n_attrib = 26; + if (WGLEW_ARB_pbuffer) + { + attrib[n_attrib] = WGL_DRAW_TO_PBUFFER_ARB; + n_pbuffer = n_attrib; + n_attrib++; + } + if (WGLEW_NV_float_buffer) + { + attrib[n_attrib] = WGL_FLOAT_COMPONENTS_NV; + n_float = n_attrib; + n_attrib++; + } + + if (!verbose) + { + /* print table header */ + fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); + fprintf(file, " | | visual | color | ax dp st | accum | layer |\n"); + fprintf(file, " | id | tp ac gd fm db sw st ms | sz r g b a | bf th cl | sz r g b a | ov un sw |\n"); + fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); + /* loop through all the pixel formats */ + for(i = 1; i <= maxpf; i++) + { + wglGetPixelFormatAttribivARB(ctx->dc, i, 0, n_attrib, attrib, value); + /* only describe this format if it supports OpenGL */ + if (!value[0]) continue; + /* by default show only fully accelerated window or pbuffer capable visuals */ + if (!showall + && ((value[2] && !value[1]) + || (!WGLEW_ARB_pbuffer || !value[n_pbuffer]) + || (value[3] != WGL_FULL_ACCELERATION_ARB))) continue; + /* print out the information for this visual */ + /* visual id */ + fprintf(file, " |% 4d | ", i); + /* visual type */ + if (value[1]) + { + if (WGLEW_ARB_pbuffer && value[n_pbuffer]) fprintf(file, "wp "); + else fprintf(file, "wn "); + } + else + { + if (value[2]) fprintf(file, "bm "); + else if (WGLEW_ARB_pbuffer && value[n_pbuffer]) fprintf(file, "pb "); + } + /* acceleration */ + fprintf(file, "%s ", value[3] == WGL_FULL_ACCELERATION_ARB ? "fu" : + value[3] == WGL_GENERIC_ACCELERATION_ARB ? "ge" : + value[3] == WGL_NO_ACCELERATION_ARB ? "no" : ". "); + /* gdi support */ + fprintf(file, " %c ", value[25] ? 'y' : '.'); + /* format */ + if (WGLEW_NV_float_buffer && value[n_float]) fprintf(file, " f "); + else if (WGLEW_ATI_pixel_format_float && value[7] == WGL_TYPE_RGBA_FLOAT_ATI) fprintf(file, " f "); + else if (value[7] == WGL_TYPE_RGBA_ARB) fprintf(file, " i "); + else if (value[7] == WGL_TYPE_COLORINDEX_ARB) fprintf(file, " c "); + /* double buffer */ + fprintf(file, " %c ", value[5] ? 'y' : '.'); + /* swap method */ + if (value[4] == WGL_SWAP_EXCHANGE_ARB) fprintf(file, " x "); + else if (value[4] == WGL_SWAP_COPY_ARB) fprintf(file, " c "); + else if (value[4] == WGL_SWAP_UNDEFINED_ARB) fprintf(file, " . "); + else fprintf(file, " . "); + /* stereo */ + fprintf(file, " %c ", value[6] ? 'y' : '.'); + /* multisample */ + if (value[24] > 0) + fprintf(file, "%2d | ", value[24]); + else + fprintf(file, " . | "); + /* color size */ + if (value[8]) fprintf(file, "%3d ", value[8]); + else fprintf(file, " . "); + /* red */ + if (value[9]) fprintf(file, "%2d ", value[9]); + else fprintf(file, " . "); + /* green */ + if (value[10]) fprintf(file, "%2d ", value[10]); + else fprintf(file, " . "); + /* blue */ + if (value[11]) fprintf(file, "%2d ", value[11]); + else fprintf(file, " . "); + /* alpha */ + if (value[12]) fprintf(file, "%2d | ", value[12]); + else fprintf(file, " . | "); + /* aux buffers */ + if (value[20]) fprintf(file, "%2d ", value[20]); + else fprintf(file, " . "); + /* depth */ + if (value[18]) fprintf(file, "%2d ", value[18]); + else fprintf(file, " . "); + /* stencil */ + if (value[19]) fprintf(file, "%2d | ", value[19]); + else fprintf(file, " . | "); + /* accum size */ + if (value[13]) fprintf(file, "%3d ", value[13]); + else fprintf(file, " . "); + /* accum red */ + if (value[14]) fprintf(file, "%2d ", value[14]); + else fprintf(file, " . "); + /* accum green */ + if (value[15]) fprintf(file, "%2d ", value[15]); + else fprintf(file, " . "); + /* accum blue */ + if (value[16]) fprintf(file, "%2d ", value[16]); + else fprintf(file, " . "); + /* accum alpha */ + if (value[17]) fprintf(file, "%2d | ", value[17]); + else fprintf(file, " . | "); + /* overlay */ + if (value[21]) fprintf(file, "%2d ", value[21]); + else fprintf(file, " . "); + /* underlay */ + if (value[22]) fprintf(file, "%2d ", value[22]); + else fprintf(file, " . "); + /* layer swap */ + if (value[23]) fprintf(file, "y "); + else fprintf(file, " . "); + fprintf(file, "|\n"); + } + /* print table footer */ + fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); + fprintf(file, " | | visual | color | ax dp st | accum | layer |\n"); + fprintf(file, " | id | tp ac gd fm db sw st ms | sz r g b a | bf th cl | sz r g b a | ov un sw |\n"); + fprintf(file, " +-----+-------------------------+-----------------+----------+-----------------+----------+\n"); + } + else /* verbose */ + { +#if 0 + fprintf(file, "\n"); + /* loop through all the pixel formats */ + for(i = 1; i <= maxpf; i++) + { + DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + /* only describe this format if it supports OpenGL */ + if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL) + || (drawableonly && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))) continue; + fprintf(file, "Visual ID: %2d depth=%d class=%s\n", i, pfd.cDepthBits, + pfd.cColorBits <= 8 ? "PseudoColor" : "TrueColor"); + fprintf(file, " bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n", pfd.cColorBits, pfd.bReserved, pfd.iPixelType == PFD_TYPE_RGBA ? "rgba" : "ci", pfd.dwFlags & PFD_DOUBLEBUFFER, pfd.dwFlags & PFD_STEREO); + fprintf(file, " generic=%d generic accelerated=%d\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) == PFD_GENERIC_FORMAT, (pfd.dwFlags & PFD_GENERIC_ACCELERATED) == PFD_GENERIC_ACCELERATED); + fprintf(file, " rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits); + fprintf(file, " auxBuffers=%d depthSize=%d stencilSize=%d\n", pfd.cAuxBuffers, pfd.cDepthBits, pfd.cStencilBits); + fprintf(file, " accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cAccumRedBits, pfd.cAccumGreenBits, pfd.cAccumBlueBits, pfd.cAccumAlphaBits); + fprintf(file, " multiSample=%d multisampleBuffers=%d\n", 0, 0); + fprintf(file, " Opaque.\n"); + } +#endif + } +} + +void +VisualInfoGDI (GLContext* ctx) +{ + int i, maxpf; + PIXELFORMATDESCRIPTOR pfd; + + /* calling DescribePixelFormat() with NULL pfd (!!!) return maximum + number of pixel formats */ + maxpf = DescribePixelFormat(ctx->dc, 1, 0, NULL); + + if (!verbose) + { + fprintf(file, "-----------------------------------------------------------------------------\n"); + fprintf(file, " visual x bf lv rg d st ge ge r g b a ax dp st accum buffs ms \n"); + fprintf(file, " id dep tp sp sz l ci b ro ne ac sz sz sz sz bf th cl sz r g b a ns b\n"); + fprintf(file, "-----------------------------------------------------------------------------\n"); + + /* loop through all the pixel formats */ + for(i = 1; i <= maxpf; i++) + { + DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + /* only describe this format if it supports OpenGL */ + if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL) + || (drawableonly && (pfd.dwFlags & PFD_DRAW_TO_BITMAP))) continue; + /* other criteria could be tested here for actual pixel format + choosing in an application: + + for (...each pixel format...) { + if (pfd.dwFlags & PFD_SUPPORT_OPENGL && + pfd.dwFlags & PFD_DOUBLEBUFFER && + pfd.cDepthBits >= 24 && + pfd.cColorBits >= 24) + { + goto found; + } + } + ... not found so exit ... + found: + ... found so use it ... + */ + /* print out the information for this pixel format */ + fprintf(file, "0x%02x ", i); + fprintf(file, "%3d ", pfd.cColorBits); + if(pfd.dwFlags & PFD_DRAW_TO_WINDOW) fprintf(file, "wn "); + else if(pfd.dwFlags & PFD_DRAW_TO_BITMAP) fprintf(file, "bm "); + else fprintf(file, "pb "); + /* should find transparent pixel from LAYERPLANEDESCRIPTOR */ + fprintf(file, " . "); + fprintf(file, "%3d ", pfd.cColorBits); + /* bReserved field indicates number of over/underlays */ + if(pfd.bReserved) fprintf(file, " %d ", pfd.bReserved); + else fprintf(file, " . "); + fprintf(file, " %c ", pfd.iPixelType == PFD_TYPE_RGBA ? 'r' : 'c'); + fprintf(file, "%c ", pfd.dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.'); + fprintf(file, " %c ", pfd.dwFlags & PFD_STEREO ? 'y' : '.'); + /* added: */ + fprintf(file, " %c ", pfd.dwFlags & PFD_GENERIC_FORMAT ? 'y' : '.'); + fprintf(file, " %c ", pfd.dwFlags & PFD_GENERIC_ACCELERATED ? 'y' : '.'); + if(pfd.cRedBits && pfd.iPixelType == PFD_TYPE_RGBA) + fprintf(file, "%2d ", pfd.cRedBits); + else fprintf(file, " . "); + if(pfd.cGreenBits && pfd.iPixelType == PFD_TYPE_RGBA) + fprintf(file, "%2d ", pfd.cGreenBits); + else fprintf(file, " . "); + if(pfd.cBlueBits && pfd.iPixelType == PFD_TYPE_RGBA) + fprintf(file, "%2d ", pfd.cBlueBits); + else fprintf(file, " . "); + if(pfd.cAlphaBits && pfd.iPixelType == PFD_TYPE_RGBA) + fprintf(file, "%2d ", pfd.cAlphaBits); + else fprintf(file, " . "); + if(pfd.cAuxBuffers) fprintf(file, "%2d ", pfd.cAuxBuffers); + else fprintf(file, " . "); + if(pfd.cDepthBits) fprintf(file, "%2d ", pfd.cDepthBits); + else fprintf(file, " . "); + if(pfd.cStencilBits) fprintf(file, "%2d ", pfd.cStencilBits); + else fprintf(file, " . "); + if(pfd.cAccumBits) fprintf(file, "%3d ", pfd.cAccumBits); + else fprintf(file, " . "); + if(pfd.cAccumRedBits) fprintf(file, "%2d ", pfd.cAccumRedBits); + else fprintf(file, " . "); + if(pfd.cAccumGreenBits) fprintf(file, "%2d ", pfd.cAccumGreenBits); + else fprintf(file, " . "); + if(pfd.cAccumBlueBits) fprintf(file, "%2d ", pfd.cAccumBlueBits); + else fprintf(file, " . "); + if(pfd.cAccumAlphaBits) fprintf(file, "%2d ", pfd.cAccumAlphaBits); + else fprintf(file, " . "); + /* no multisample in win32 */ + fprintf(file, " . .\n"); + } + /* print table footer */ + fprintf(file, "-----------------------------------------------------------------------------\n"); + fprintf(file, " visual x bf lv rg d st ge ge r g b a ax dp st accum buffs ms \n"); + fprintf(file, " id dep tp sp sz l ci b ro ne ac sz sz sz sz bf th cl sz r g b a ns b\n"); + fprintf(file, "-----------------------------------------------------------------------------\n"); + } + else /* verbose */ + { + fprintf(file, "\n"); + /* loop through all the pixel formats */ + for(i = 1; i <= maxpf; i++) + { + DescribePixelFormat(ctx->dc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + /* only describe this format if it supports OpenGL */ + if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL) + || (drawableonly && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))) continue; + fprintf(file, "Visual ID: %2d depth=%d class=%s\n", i, pfd.cDepthBits, + pfd.cColorBits <= 8 ? "PseudoColor" : "TrueColor"); + fprintf(file, " bufferSize=%d level=%d renderType=%s doubleBuffer=%ld stereo=%ld\n", pfd.cColorBits, pfd.bReserved, pfd.iPixelType == PFD_TYPE_RGBA ? "rgba" : "ci", pfd.dwFlags & PFD_DOUBLEBUFFER, pfd.dwFlags & PFD_STEREO); + fprintf(file, " generic=%d generic accelerated=%d\n", (pfd.dwFlags & PFD_GENERIC_FORMAT) == PFD_GENERIC_FORMAT, (pfd.dwFlags & PFD_GENERIC_ACCELERATED) == PFD_GENERIC_ACCELERATED); + fprintf(file, " rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits); + fprintf(file, " auxBuffers=%d depthSize=%d stencilSize=%d\n", pfd.cAuxBuffers, pfd.cDepthBits, pfd.cStencilBits); + fprintf(file, " accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", pfd.cAccumRedBits, pfd.cAccumGreenBits, pfd.cAccumBlueBits, pfd.cAccumAlphaBits); + fprintf(file, " multiSample=%d multisampleBuffers=%d\n", 0, 0); + fprintf(file, " Opaque.\n"); + } + } +} + +void +VisualInfo (GLContext* ctx) +{ + if (WGLEW_ARB_pixel_format) + VisualInfoARB(ctx); + else + VisualInfoGDI(ctx); +} + +/* ---------------------------------------------------------------------- */ + +#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) + +void +VisualInfo (GLContext* ctx) +{ +/* + int attrib[] = { AGL_RGBA, AGL_NONE }; + AGLPixelFormat pf; + GLint value; + pf = aglChoosePixelFormat(NULL, 0, attrib); + while (pf != NULL) + { + aglDescribePixelFormat(pf, GL_RGBA, &value); + fprintf(stderr, "%d\n", value); + pf = aglNextPixelFormat(pf); + } +*/ +} + +#else /* GLX */ + +void +VisualInfo (GLContext* ctx) +{ + int n_fbc; + GLXFBConfig* fbc; + int value, ret, i; + + fbc = glXGetFBConfigs(ctx->dpy, DefaultScreen(ctx->dpy), &n_fbc); + + if (fbc) + { + if (!verbose) + { + /* print table header */ + fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); + fprintf(file, " | | visual | color | ax dp st | accum | ms | cav |\n"); + fprintf(file, " | id | tp xr cl fm db st lv xp | sz r g b a | bf th cl | r g b a | ns b | eat |\n"); + fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); + /* loop through all the fbcs */ + for (i=0; idpy, fbc[i], GLX_FBCONFIG_ID, &value); + if (ret != Success) + { + fprintf(file, "| ? |"); + } + else + { + fprintf(file, " |% 4d | ", value); + } + /* visual type */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DRAWABLE_TYPE, &value); + if (ret != Success) + { + fprintf(file, " ? "); + } + else + { + if (value & GLX_WINDOW_BIT) + { + if (value & GLX_PBUFFER_BIT) + { + fprintf(file, "wp "); + } + else + { + fprintf(file, "wn "); + } + } + else + { + if (value & GLX_PBUFFER_BIT) + { + fprintf(file, "pb "); + } + else if (value & GLX_PIXMAP_BIT) + { + fprintf(file, "pm "); + } + else + { + fprintf(file, " ? "); + } + } + } + /* x renderable */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_X_RENDERABLE, &value); + if (ret != Success) + { + fprintf(file, " ? "); + } + else + { + fprintf(file, value ? " y " : " n "); + } + /* class */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_X_VISUAL_TYPE, &value); + if (ret != Success) + { + fprintf(file, " ? "); + } + else + { + if (GLX_TRUE_COLOR == value) + fprintf(file, "tc "); + else if (GLX_DIRECT_COLOR == value) + fprintf(file, "dc "); + else if (GLX_PSEUDO_COLOR == value) + fprintf(file, "pc "); + else if (GLX_STATIC_COLOR == value) + fprintf(file, "sc "); + else if (GLX_GRAY_SCALE == value) + fprintf(file, "gs "); + else if (GLX_STATIC_GRAY == value) + fprintf(file, "sg "); + else if (GLX_X_VISUAL_TYPE == value) + fprintf(file, " . "); + else + fprintf(file, " ? "); + } + /* format */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_RENDER_TYPE, &value); + if (ret != Success) + { + fprintf(file, " ? "); + } + else + { + if (GLXEW_NV_float_buffer) + { + int ret2, value2; + ret2 = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_FLOAT_COMPONENTS_NV, &value2); + if (Success == ret2 && GL_TRUE == value2) + { + fprintf(file, " f "); + } + else if (value & GLX_RGBA_BIT) + fprintf(file, " i "); + else if (value & GLX_COLOR_INDEX_BIT) + fprintf(file, " c "); + else + fprintf(file, " ? "); + } + else + { + if (value & GLX_RGBA_FLOAT_ATI_BIT) + fprintf(file, " f "); + else if (value & GLX_RGBA_BIT) + fprintf(file, " i "); + else if (value & GLX_COLOR_INDEX_BIT) + fprintf(file, " c "); + else + fprintf(file, " ? "); + } + } + /* double buffer */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DOUBLEBUFFER, &value); + fprintf(file, " %c ", Success != ret ? '?' : (value ? 'y' : '.')); + /* stereo */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_STEREO, &value); + fprintf(file, " %c ", Success != ret ? '?' : (value ? 'y' : '.')); + /* level */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_LEVEL, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + fprintf(file, "%2d ", value); + } + /* transparency */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_TRANSPARENT_TYPE, &value); + if (Success != ret) + { + fprintf(file, " ? | "); + } + else + { + if (GLX_TRANSPARENT_RGB == value) + fprintf(file, " r | "); + else if (GLX_TRANSPARENT_INDEX == value) + fprintf(file, " i | "); + else if (GLX_NONE == value) + fprintf(file, " . | "); + else + fprintf(file, " ? | "); + } + /* color size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_BUFFER_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + if (value) + fprintf(file, "%3d ", value); + else + fprintf(file, " . "); + } + /* red size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_RED_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + if (value) + fprintf(file, "%2d ", value); + else + fprintf(file, " . "); + } + /* green size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_GREEN_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + if (value) + fprintf(file, "%2d ", value); + else + fprintf(file, " . "); + } + /* blue size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_BLUE_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + if (value) + fprintf(file, "%2d ", value); + else + fprintf(file, " . "); + } + /* alpha size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ALPHA_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? | "); + } + else + { + if (value) + fprintf(file, "%2d | ", value); + else + fprintf(file, " . | "); + } + /* aux buffers */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_AUX_BUFFERS, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + if (value) + fprintf(file, "%2d ", value); + else + fprintf(file, " . "); + } + /* depth size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_DEPTH_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + if (value) + fprintf(file, "%2d ", value); + else + fprintf(file, " . "); + } + /* stencil size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_STENCIL_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? | "); + } + else + { + if (value) + fprintf(file, "%2d | ", value); + else + fprintf(file, " . | "); + } + /* accum red size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_RED_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + if (value) + fprintf(file, "%2d ", value); + else + fprintf(file, " . "); + } + /* accum green size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_GREEN_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + if (value) + fprintf(file, "%2d ", value); + else + fprintf(file, " . "); + } + /* accum blue size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_BLUE_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + if (value) + fprintf(file, "%2d ", value); + else + fprintf(file, " . "); + } + /* accum alpha size */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_ACCUM_ALPHA_SIZE, &value); + if (Success != ret) + { + fprintf(file, " ? | "); + } + else + { + if (value) + fprintf(file, "%2d | ", value); + else + fprintf(file, " . | "); + } + /* multisample */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_SAMPLES, &value); + if (Success != ret) + { + fprintf(file, " ? "); + } + else + { + fprintf(file, "%2d ", value); + } + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_SAMPLE_BUFFERS, &value); + if (Success != ret) + { + fprintf(file, " ? | "); + } + else + { + fprintf(file, "%2d | ", value); + } + /* caveat */ + ret = glXGetFBConfigAttrib(ctx->dpy, fbc[i], GLX_CONFIG_CAVEAT, &value); + if (Success != ret) + { + fprintf(file, "???? |"); + } + else + { + if (GLX_NONE == value) + fprintf(file, "none |\n"); + else if (GLX_SLOW_CONFIG == value) + fprintf(file, "slow |\n"); + else if (GLX_NON_CONFORMANT_CONFIG == value) + fprintf(file, "ncft |\n"); + else + fprintf(file, "???? |\n"); + } + } + /* print table footer */ + fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); + fprintf(file, " | id | tp xr cl fm db st lv xp | sz r g b a | bf th cl | r g b a | ns b | eat |\n"); + fprintf(file, " | | visual | color | ax dp st | accum | ms | cav |\n"); + fprintf(file, " +-----+-------------------------+-----------------+----------+-------------+-------+------+\n"); + } + } +} + +#endif + +/* ------------------------------------------------------------------------ */ + +#if defined(_WIN32) + +void InitContext (GLContext* ctx) +{ + ctx->wnd = NULL; + ctx->dc = NULL; + ctx->rc = NULL; +} + +GLboolean CreateContext (GLContext* ctx) +{ + WNDCLASS wc; + PIXELFORMATDESCRIPTOR pfd; + /* check for input */ + if (NULL == ctx) return GL_TRUE; + /* register window class */ + ZeroMemory(&wc, sizeof(WNDCLASS)); + wc.hInstance = GetModuleHandle(NULL); + wc.lpfnWndProc = DefWindowProc; + wc.lpszClassName = "GLEW"; + if (0 == RegisterClass(&wc)) return GL_TRUE; + /* create window */ + ctx->wnd = CreateWindow("GLEW", "GLEW", 0, CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, + GetModuleHandle(NULL), NULL); + if (NULL == ctx->wnd) return GL_TRUE; + /* get the device context */ + ctx->dc = GetDC(ctx->wnd); + if (NULL == ctx->dc) return GL_TRUE; + /* find pixel format */ + ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); + if (visual == -1) /* find default */ + { + pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + visual = ChoosePixelFormat(ctx->dc, &pfd); + if (0 == visual) return GL_TRUE; + } + /* set the pixel format for the dc */ + if (FALSE == SetPixelFormat(ctx->dc, visual, &pfd)) return GL_TRUE; + /* create rendering context */ + ctx->rc = wglCreateContext(ctx->dc); + if (NULL == ctx->rc) return GL_TRUE; + if (FALSE == wglMakeCurrent(ctx->dc, ctx->rc)) return GL_TRUE; + return GL_FALSE; +} + +void DestroyContext (GLContext* ctx) +{ + if (NULL == ctx) return; + if (NULL != ctx->rc) wglMakeCurrent(NULL, NULL); + if (NULL != ctx->rc) wglDeleteContext(wglGetCurrentContext()); + if (NULL != ctx->wnd && NULL != ctx->dc) ReleaseDC(ctx->wnd, ctx->dc); + if (NULL != ctx->wnd) DestroyWindow(ctx->wnd); + UnregisterClass("GLEW", GetModuleHandle(NULL)); +} + +/* ------------------------------------------------------------------------ */ + +#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) + +void InitContext (GLContext* ctx) +{ + ctx->ctx = NULL; + ctx->octx = NULL; +} + +GLboolean CreateContext (GLContext* ctx) +{ + int attrib[] = { AGL_RGBA, AGL_NONE }; + AGLPixelFormat pf; + /* check input */ + if (NULL == ctx) return GL_TRUE; + /*int major, minor; + SetPortWindowPort(wnd); + aglGetVersion(&major, &minor); + fprintf(stderr, "GL %d.%d\n", major, minor);*/ + pf = aglChoosePixelFormat(NULL, 0, attrib); + if (NULL == pf) return GL_TRUE; + ctx->ctx = aglCreateContext(pf, NULL); + if (NULL == ctx->ctx || AGL_NO_ERROR != aglGetError()) return GL_TRUE; + aglDestroyPixelFormat(pf); + /*aglSetDrawable(ctx, GetWindowPort(wnd));*/ + ctx->octx = aglGetCurrentContext(); + if (GL_FALSE == aglSetCurrentContext(ctx->ctx)) return GL_TRUE; + return GL_FALSE; +} + +void DestroyContext (GLContext* ctx) +{ + if (NULL == ctx) return; + aglSetCurrentContext(ctx->octx); + if (NULL != ctx->ctx) aglDestroyContext(ctx->ctx); +} + +/* ------------------------------------------------------------------------ */ + +#else /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */ + +void InitContext (GLContext* ctx) +{ + ctx->dpy = NULL; + ctx->vi = NULL; + ctx->ctx = NULL; + ctx->wnd = 0; + ctx->cmap = 0; +} + +GLboolean CreateContext (GLContext* ctx) +{ + int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None }; + int erb, evb; + XSetWindowAttributes swa; + /* check input */ + if (NULL == ctx) return GL_TRUE; + /* open display */ + ctx->dpy = XOpenDisplay(display); + if (NULL == ctx->dpy) return GL_TRUE; + /* query for glx */ + if (!glXQueryExtension(ctx->dpy, &erb, &evb)) return GL_TRUE; + /* choose visual */ + ctx->vi = glXChooseVisual(ctx->dpy, DefaultScreen(ctx->dpy), attrib); + if (NULL == ctx->vi) return GL_TRUE; + /* create context */ + ctx->ctx = glXCreateContext(ctx->dpy, ctx->vi, None, True); + if (NULL == ctx->ctx) return GL_TRUE; + /* create window */ + /*wnd = XCreateSimpleWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 1, 1, 1, 0, 0);*/ + ctx->cmap = XCreateColormap(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen), + ctx->vi->visual, AllocNone); + swa.border_pixel = 0; + swa.colormap = ctx->cmap; + ctx->wnd = XCreateWindow(ctx->dpy, RootWindow(ctx->dpy, ctx->vi->screen), + 0, 0, 1, 1, 0, ctx->vi->depth, InputOutput, ctx->vi->visual, + CWBorderPixel | CWColormap, &swa); + /* make context current */ + if (!glXMakeCurrent(ctx->dpy, ctx->wnd, ctx->ctx)) return GL_TRUE; + return GL_FALSE; +} + +void DestroyContext (GLContext* ctx) +{ + if (NULL != ctx->dpy && NULL != ctx->ctx) glXDestroyContext(ctx->dpy, ctx->ctx); + if (NULL != ctx->dpy && 0 != ctx->wnd) XDestroyWindow(ctx->dpy, ctx->wnd); + if (NULL != ctx->dpy && 0 != ctx->cmap) XFreeColormap(ctx->dpy, ctx->cmap); + if (NULL != ctx->vi) XFree(ctx->vi); + if (NULL != ctx->dpy) XCloseDisplay(ctx->dpy); +} + +#endif /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */ + +GLboolean ParseArgs (int argc, char** argv) +{ + int p = 0; + while (p < argc) + { +#if defined(_WIN32) + if (!strcmp(argv[p], "-pf") || !strcmp(argv[p], "-pixelformat")) + { + if (++p >= argc) return GL_TRUE; + display = NULL; + visual = strtol(argv[p], NULL, 0); + } + else if (!strcmp(argv[p], "-a")) + { + showall = 1; + } + else if (!strcmp(argv[p], "-s")) + { + displaystdout = 1; + } + else if (!strcmp(argv[p], "-h")) + { + return GL_TRUE; + } + else + return GL_TRUE; +#else + if (!strcmp(argv[p], "-display")) + { + if (++p >= argc) return GL_TRUE; + display = argv[p]; + } + else if (!strcmp(argv[p], "-visual")) + { + if (++p >= argc) return GL_TRUE; + visual = (int)strtol(argv[p], NULL, 0); + } + else if (!strcmp(argv[p], "-h")) + { + return GL_TRUE; + } + else + return GL_TRUE; +#endif + p++; + } + return GL_FALSE; +} diff --git a/json/json_writer.h b/json/json_writer.h index 5c714c15d4..63de1d1260 100644 --- a/json/json_writer.h +++ b/json/json_writer.h @@ -2,8 +2,13 @@ // apart from the string being built-up, which could easily be replaced // with a file stream (although I've chosen not to do that just yet). // +// Writes nicely 2-spade indented output with correct comma-placement +// in arrays and dictionaries. +// +// Does not deal with encodings in any way. +// // Zero dependencies apart from stdlib. -// Public domain. +// Public domain by Henrik Rydgård. #include #include @@ -19,6 +24,7 @@ class JsonWriter { void end(); void pushDict(const char *name); void pushArray(const char *name); + void pop(); void writeBool(bool value); void writeBool(const char *name, bool value); void writeInt(int value); @@ -27,7 +33,6 @@ class JsonWriter { void writeFloat(const char *name, double value); void writeString(const char *value); void writeString(const char *name, const char *value); - void pop(); std::string str() const { return str_.str(); diff --git a/native.vcxproj b/native.vcxproj index 4b76b5a8c1..ec9e00b9d9 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -56,7 +56,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\native;..\RollerballGL;..\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); Windows @@ -72,7 +72,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\native;..\RollerballGL;..\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); Windows @@ -83,7 +83,7 @@ - + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 8f38a59f84..0dae95bf12 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -1,10 +1,10 @@  - file + From a4b7a0cb1363b911c41dad977e0820202a766efc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 27 Mar 2012 23:39:13 +0200 Subject: [PATCH 0006/1445] Add code to set the thread name --- base/threadutil.cpp | 35 +++++++++++++++++++++++++++++++++++ base/threadutil.h | 3 +++ 2 files changed, 38 insertions(+) create mode 100644 base/threadutil.cpp create mode 100644 base/threadutil.h diff --git a/base/threadutil.cpp b/base/threadutil.cpp new file mode 100644 index 0000000000..d8447e039e --- /dev/null +++ b/base/threadutil.cpp @@ -0,0 +1,35 @@ +#ifdef _WIN32 +#include +#endif +#include "base/threadutil.h" + +void setCurrentThreadName(const char* szThreadName) +{ +#ifdef _WIN32 + static const DWORD MS_VC_EXCEPTION = 0x406D1388; + +#pragma pack(push,8) + struct THREADNAME_INFO + { + DWORD dwType; // must be 0x1000 + LPCSTR szName; // pointer to name (in user addr space) + DWORD dwThreadID; // thread ID (-1=caller thread) + DWORD dwFlags; // reserved for future use, must be zero + } info; +#pragma pack(pop) + + info.dwType = 0x1000; + info.szName = szThreadName; + info.dwThreadID = -1; //dwThreadID; + info.dwFlags = 0; + + __try + { + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except(EXCEPTION_CONTINUE_EXECUTION) + {} +#else + // Do nothing +#endif +} diff --git a/base/threadutil.h b/base/threadutil.h new file mode 100644 index 0000000000..15e6a477d1 --- /dev/null +++ b/base/threadutil.h @@ -0,0 +1,3 @@ +#pragma once + +void setCurrentThreadName(const char *name); \ No newline at end of file From b86a912752df9a792525e0c2d3c148fcdd12cd15 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 30 Mar 2012 00:45:16 +0200 Subject: [PATCH 0007/1445] Tweaks --- gfx_es2/glsl_program.cpp | 15 ++++++++++----- math/lin/matrix4x4.cpp | 5 +++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 20b340f3bb..3cc6bad08a 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -48,7 +48,7 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader) { program->program_ = 0; program->vsh_ = 0; program->fsh_ = 0; - strcpy(program->name, vshader + strlen(vshader) - 16); + strcpy(program->name, vshader + strlen(vshader) - 15); strcpy(program->vshader_filename, vshader); strcpy(program->fshader_filename, fshader); if (glsl_recompile(program)) { @@ -82,10 +82,15 @@ void glsl_refresh() { bool glsl_recompile(GLSLProgram *program) { struct stat vs, fs; - stat(program->vshader_filename, &vs); - stat(program->fshader_filename, &fs); - program->vshader_mtime = vs.st_mtime; - program->fshader_mtime = fs.st_mtime; + if (0 == stat(program->vshader_filename, &vs)) + program->vshader_mtime = vs.st_mtime; + else + program->vshader_mtime = 0; + + if (0 == stat(program->fshader_filename, &fs)) + program->fshader_mtime = fs.st_mtime; + else + program->fshader_mtime = 0; size_t sz; char *vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz); diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp index a2e7f32c93..14c1140760 100644 --- a/math/lin/matrix4x4.cpp +++ b/math/lin/matrix4x4.cpp @@ -5,6 +5,11 @@ #include "math/lin/vec3.h" #include "math/lin/quat.h" +#ifdef _WIN32 +#undef far +#undef near +#endif + // See http://code.google.com/p/oolongengine/source/browse/trunk/Oolong+Engine2/Math/neonmath/neon_matrix_impl.cpp?spec=svn143&r=143 when we need speed // no wait. http://code.google.com/p/math-neon/ From dc7c033a3ceaa4770ff96df910d40b686875ebea Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 31 Mar 2012 10:32:57 +0200 Subject: [PATCH 0008/1445] Update README and add LICENSE --- LICENSE.TXT | 9 +++++++++ README.md | 13 ++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 LICENSE.TXT diff --git a/LICENSE.TXT b/LICENSE.TXT new file mode 100644 index 0000000000..e92ab68fef --- /dev/null +++ b/LICENSE.TXT @@ -0,0 +1,9 @@ +Copyright (C) 2012 Henrik Rydgard + +This applies to all the code here not covered under other licenses, see README.md. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 1dc72121f6..ec38905550 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,17 @@ This is my library of stuff that I use when writing C++ programs, mostly for And This project incorporates code from a variety of public domain or similarly-licensed code. This is the list: -etcpack by Ericsson, in a cleaned up form. public domain? -sha1, public domain implementation by Dominik Reichl -json_writer by me (Henrik Rydgård) -vjson in a heavily modified form, originally by ??? (TODO) -libzip with attribution "Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner" -stb_vorbis, public domain by Sean Barrett of RAD Tools +* etcpack by Ericsson, in a cleaned up form. Has strange license but not very limiting - you can only use the code for making textures for hardware supporting ETC1, or something like that. Don't think it affects the rest of the code in any way. +* sha1, public domain implementation by Dominik Reichl +* vjson in a heavily modified form, originally by Ivan Vashchaev (TODO: break out into its own repo?) +* libzip with attribution "Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner" +* stb_vorbis, public domain by Sean Barrett of RAD Tools If you're not okay with the licenses above, don't use this code. If you find this useful for your own projects, drop me a line at hrydgard@gmail.com . -I hereby release all code here not under the licenses above to the public domain. +I hereby release all code here not under the licenses above under the MIT license. Henrik Rydgård From 8b076c5b88217c58449bbed9b265d3c6016414ed Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 31 Mar 2012 11:16:13 +0200 Subject: [PATCH 0009/1445] Cleanup --- README.md | 22 +++++++++- audio/mixer.h | 6 +-- audio/wav_read.cpp | 1 - base/LAME.cpp | 7 ---- base/LAME.h | 27 ------------ base/LAMEApp.cpp | 48 ---------------------- base/LAMEApp.h | 84 -------------------------------------- base/LAMEString.cpp | 3 ++ base/LAMEString.h | 4 ++ base/error_context.cpp | 1 + base/logging.h | 14 ++++++- base/scoped_ptr.h | 3 +- base/stats.h | 1 + base/stringutil.h | 7 +++- base/timeutil.h | 4 +- file/chunk_file.h | 15 +++---- file/easy_file.cpp | 5 --- file/easy_file.h | 3 ++ file/file_util.cpp | 5 ++- file/file_util.h | 5 ++- file/vfs.h | 9 ++-- file/zip_read.h | 2 + gfx/gl_debug_log.h | 7 ++-- gfx/gl_lost_manager.h | 3 ++ gfx/texture.cpp | 4 +- gfx/texture.h | 3 ++ gfx/texture_dx11.cpp | 4 ++ gfx/texture_gen.cpp | 3 +- gfx/texture_gen.h | 5 --- gfx_es1/draw_buffer.h | 4 +- gfx_es2/draw_buffer.cpp | 14 ++++--- gfx_es2/draw_buffer.h | 6 +-- gfx_es2/glsl_program.h | 3 ++ gfx_es2/vertex_format.h | 2 + image/build.scons | 15 ------- image/surface.h | 3 ++ image/zim_load.h | 2 +- image/zim_save.cpp | 2 +- input/gesture_detector.cpp | 2 +- input/gesture_detector.h | 3 +- input/input_state.h | 2 + json/json_writer.cpp | 1 - json/json_writer.h | 6 +-- math/build.scons | 8 ---- math/compression.h | 1 + math/lin/build.scons | 12 ------ math/lin/matrix4x4.cpp | 1 - math/lin/quat.cpp | 1 + math/lin/vec3.h | 7 ---- math/math_util.h | 5 ++- native.vcxproj | 2 +- profiler/profiler.h | 1 + util/bits/bits.cc | 40 ------------------ util/bits/varint.cc | 35 ---------------- util/build.scons | 20 --------- util/hash/hash.cc | 65 ----------------------------- util/hash/hash.h | 15 ------- util/random/perlin.cc | 72 -------------------------------- 58 files changed, 136 insertions(+), 519 deletions(-) delete mode 100644 base/LAME.cpp delete mode 100644 base/LAME.h delete mode 100644 base/LAMEApp.cpp delete mode 100644 base/LAMEApp.h delete mode 100644 image/build.scons delete mode 100644 math/build.scons delete mode 100644 math/lin/build.scons delete mode 100644 util/bits/bits.cc delete mode 100644 util/bits/varint.cc delete mode 100644 util/build.scons delete mode 100644 util/hash/hash.cc delete mode 100644 util/random/perlin.cc diff --git a/README.md b/README.md index ec38905550..54e111af82 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,29 @@ native ====== -This is my library of stuff that I use when writing C++ programs, mostly for Android. It has some basic OpenGL utility code, JSON read/write (two libraries that should be made more similar), 2D texture atlases and drawing code, ETC1 texture loading support, basic logging, etc. The associated tools to create ZIM texture files and atlases do not yet live here but I might move them here eventually. +This is my library of stuff that I use when writing C++ programs, mostly for Android but it's all written to enable easy portability between Android, Linux, Windows and MacOSX. + +It contains: +* JSON read/write (two libraries that should be made more similar) +* basic OpenGL utility code, like compressed texture loading +* 2D texture atlases and drawing code +* ETC1 texture loading support +* basic logging +* Really simple audio mixer with OGG sample support +* RIFF file read/write + +The associated tools to create ZIM texture files and atlases do not yet live here but I might move them here eventually. + +This library is not really meant to be a public library but I see no reason not to set it free. + +Note that the included VS project is probably not very useful for you and you're likely better off making your own. + +Don't complain about inconsistent naming etc - this consists of code that has been cobbled together from a variety of my projects through the years. Fashions come and go. -This project incorporates code from a variety of public domain or similarly-licensed code. This is the list: +This library, for my convenience, incorporates code from a variety of public domain or similarly-licensed code. This is the list: +* glew (GL extension wrangler), MIT license. TODO: should just use a submodule. * etcpack by Ericsson, in a cleaned up form. Has strange license but not very limiting - you can only use the code for making textures for hardware supporting ETC1, or something like that. Don't think it affects the rest of the code in any way. * sha1, public domain implementation by Dominik Reichl * vjson in a heavily modified form, originally by Ivan Vashchaev (TODO: break out into its own repo?) diff --git a/audio/mixer.h b/audio/mixer.h index 685b901948..18d70e0ac0 100644 --- a/audio/mixer.h +++ b/audio/mixer.h @@ -17,14 +17,14 @@ struct PlayParams { // Mixer // ========================== -// For now, channels is required to be 2. +// For now, channels is required to be 2 (it specifies L/R, not mixing channels) Mixer *mixer_create(int sample_rate, int channels, int fixed_channels); void mixer_destroy(Mixer *mixer); -// Buffer must be r/w, for efficient mixing -// TODO: Use local buffer instead. +// Buffer must be r/w. void mixer_mix(Mixer *mixer, short *buffer, int num_samples); + // Clip // ========================== Clip *clip_load(const char *filename); diff --git a/audio/wav_read.cpp b/audio/wav_read.cpp index 0d7c72c9a1..53e5052ed3 100644 --- a/audio/wav_read.cpp +++ b/audio/wav_read.cpp @@ -55,7 +55,6 @@ short *wav_read(const char *filename, free(data); return NULL; } - // ILOG("got wave data: %i", numSamples); cf.ascend(); } else { ELOG("Error - no data chunk in wav"); diff --git a/base/LAME.cpp b/base/LAME.cpp deleted file mode 100644 index 1e3636fd43..0000000000 --- a/base/LAME.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "LAME.h" -#include "LAMEString.h" - -String getUserName() -{ - return String("user"); -} diff --git a/base/LAME.h b/base/LAME.h deleted file mode 100644 index 892ae6aae6..0000000000 --- a/base/LAME.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __LAME_H__ -#define __LAME_H__ - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/color.h" - - -#ifndef PI -#define PI 3.141592653589793f -#endif - -template -inline T MIN(T t1, T t2) { - return t1 -inline T MAX(T t1, T t2) { - return t1>t2 ? t1 : t2; -} - -template -inline T ABS(T &t) { - if (t<0) return -t; else return t; -} - -#endif //__LAME_H__ diff --git a/base/LAMEApp.cpp b/base/LAMEApp.cpp deleted file mode 100644 index 3c9240cbc2..0000000000 --- a/base/LAMEApp.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef _WIN32 -#include -#endif - -#include "LAMEApp.h" - -LAMEApp::LAMEApp() { - penDown=false; - wannaQuit=false; - active=0; - - TCHAR tmp[256]; -#ifdef _WIN32 - hWnd=0; - GetModuleFileName(0,tmp,255); -#else - char *discard = getcwd(tmp, 256); - discard++; -#endif - - path=tmp; - path=path.getPath()+String(TEXT("/")); -} - -LAMEApp::~LAMEApp() { -} - -bool LAMEApp::init(int width, int height) { - this->width = width; - this->height = height; - return true; -} - -int LAMEApp::run() { - return -1; -} - -void LAMEApp::close() { - wannaQuit = true; -} - -void LAMEApp::startTimer(int ID, int interval) { -// SetTimer(hWnd, ID, interval, 0); -} - -void LAMEApp::stopTimer(int ID) { -// KillTimer(hWnd, ID); -} diff --git a/base/LAMEApp.h b/base/LAMEApp.h deleted file mode 100644 index 77310588cf..0000000000 --- a/base/LAMEApp.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -//LAME: the Lean And MEan Extensions. - -// #include "gfx/draw_buffer.h" -#include "LAMEString.h" - -class LAMEApp { - protected: - bool wannaQuit; - bool active; - int width; - int height; -#ifndef WINCE - public: -#endif - bool penDown; - protected: - String path; - public: - LAMEApp(); - virtual ~LAMEApp(); - - bool init(int width, int height); - virtual int run(); - void close(); - - void startTimer(int ID, int interval); - void stopTimer(int ID); - - void refresh(); - - virtual void onLoop() { } - - virtual void onButtonDown(int b) {} - virtual void onButtonUp(int b) {} - - virtual void onPenDown(int x, int y) { } - virtual void onPenMove(int x, int y, bool pressed) { } - virtual void onPenUp(int x, int y) { } - - virtual void onKeyDown(int key) { } - virtual void onKeyChar(int key) { } - virtual void onKeyUp(int key) { } - - virtual void onLostFocus() { } - virtual void onGotFocus() { } - - virtual void onCreate() { } - virtual void onDestroy() { } - virtual void onTimer(int timerID) { } - - virtual void draw() { } - - int getWidth() const {return width;} - int getHeight() const { return height;} - String getPath() const { - return path; - } -}; - -inline String getRelativePath(String temp) -{ -#if defined(ANDROID) || defined(SDL) - return temp; -#else - #error TODO: check this - if (!theApp) return temp; -#ifdef WINCE - if (temp[0] != TCHAR('\\')) //if it's a relative path (assume to the program location), then let's expand it to a full path - if (temp.find(theApp->getPath(),0)==-1) - { - return theApp->getPath() + temp; - } -#else - if (temp[2] != TCHAR('\\')) //if it's a relative path (assume to the program location), then let's expand it to a full path - if (temp.find(theApp->getPath(),0)==-1) - { - return theApp->getPath() + temp; - } -#endif - return temp; -#endif -} diff --git a/base/LAMEString.cpp b/base/LAMEString.cpp index a5a601a870..9f395e511c 100644 --- a/base/LAMEString.cpp +++ b/base/LAMEString.cpp @@ -1,3 +1,6 @@ +// NOTE: See warning in header. + + #include #include #include diff --git a/base/LAMEString.h b/base/LAMEString.h index 1cdd6542e5..12f12839bb 100644 --- a/base/LAMEString.h +++ b/base/LAMEString.h @@ -1,3 +1,7 @@ +// NOTE: This is only here for legacy reasons. +// In new code, please use std::string. + + #pragma once #include diff --git a/base/error_context.cpp b/base/error_context.cpp index 0dfc3e5961..da27668b4e 100644 --- a/base/error_context.cpp +++ b/base/error_context.cpp @@ -3,6 +3,7 @@ #include "base/error_context.h" #include +// TODO: Fix this threadery #ifndef _WIN32 #undef __THREAD #define __THREAD diff --git a/base/logging.h b/base/logging.h index 57924d366b..4357a8084e 100644 --- a/base/logging.h +++ b/base/logging.h @@ -1,5 +1,10 @@ #pragma once +// Simple wrapper around Android's logging interface that also allows other +// implementations, and also some misc utilities. + + +// Disable annoying warnings in VS #ifdef _MSC_VER #pragma warning (disable:4996) //strcpy may be dangerous #endif @@ -18,7 +23,7 @@ inline void Crash() { *p = 1; } #else - +// TODO: 64-bit version inline void Crash() { asm("int $0x3"); } @@ -30,8 +35,9 @@ inline void Crash() { #include +// Must only be used for logging #ifndef APP_NAME -#define APP_NAME "Turboviking" +#define APP_NAME "NativeApp" #endif #define ILOG(...) __android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__); @@ -43,6 +49,8 @@ inline void Crash() { #else +// TODO: Win32 version using OutputDebugString + #include #define ILOG(...) {printf("I: %s:%i: ", __FILE__, __LINE__); printf("I: " __VA_ARGS__); printf("\n");} @@ -57,3 +65,5 @@ inline void Crash() { #endif #define CHECK(a) {if (!(a)) {FLOG("CHECK failed");}} +#define CHECK_EQ(a, b) CHECK((a) == (b)); +#define CHECK_NE(a, b) CHECK((a) != (b)); diff --git a/base/scoped_ptr.h b/base/scoped_ptr.h index 1d04d5e36e..3c66eedc3b 100644 --- a/base/scoped_ptr.h +++ b/base/scoped_ptr.h @@ -1,5 +1,7 @@ #pragma once +// Trivial implementation of boost::scoped_ptr, in a way that I prefer. + template class scoped_ptr { public: @@ -21,7 +23,6 @@ class scoped_ptr { const T *operator->() const { return ptr_; } private: - // don't copy that floppy scoped_ptr(const scoped_ptr &other); void operator=(const scoped_ptr &other); T *ptr_; diff --git a/base/stats.h b/base/stats.h index 5b45e7da2e..b111a01dc8 100644 --- a/base/stats.h +++ b/base/stats.h @@ -1,5 +1,6 @@ #pragma once +// Statistics collection. Not very developed. #define STATS_ENABLE diff --git a/base/stringutil.h b/base/stringutil.h index e5dfa87923..9871027515 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -4,6 +4,7 @@ #include #include +// Dumb wrapper around itoa, providing a buffer. Declare this on the stack. class ITOA { public: char buffer[16]; @@ -12,7 +13,9 @@ public: return &buffer[0]; } }; - + +// Other simple string utilities. + inline bool endsWith(const std::string &str, const std::string &what) { return str.substr(str.size() - what.size()) == what; -} \ No newline at end of file +} diff --git a/base/timeutil.h b/base/timeutil.h index 388e9a09dc..14dee0151b 100644 --- a/base/timeutil.h +++ b/base/timeutil.h @@ -11,9 +11,11 @@ void time_update(); float time_now(); double time_now_d(); -// Slower than the above cached time functions +// Uncached time. Slower than the above cached time functions. Does not update cached time, call time_update for that. double real_time_now(); int time_now_ms(); + +// Sleep. Does not necessarily have millisecond granularity, especially on Windows. void sleep_ms(int ms); diff --git a/file/chunk_file.h b/file/chunk_file.h index 67f4c947f1..ea184d79b8 100644 --- a/file/chunk_file.h +++ b/file/chunk_file.h @@ -1,18 +1,19 @@ #pragma once +// RIFF file format reader/writer. Very old code, basically a total mess but it still works. + +// TO REMEMBER WHEN USING: + +// EITHER a chunk contains ONLY data +// OR it contains ONLY other chunks +// otherwise the scheme breakes. + #include #include "base/basictypes.h" #include "base/LAMEString.h" #include "file/easy_file.h" -// TO REMEMBER WHEN USING: - -// EITHER a chunk contains ONLY data -// OR it contains ONLY other chunks -// otherwise the scheme breaks... -// hm.. or come to think about it, some data at the beginning of a chunk with subchunks WOULD work.. -// but not safely, so don't try inline uint32 flipID(uint32 id) { return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000); } diff --git a/file/easy_file.cpp b/file/easy_file.cpp index 6256bead04..20c0b51c1c 100644 --- a/file/easy_file.cpp +++ b/file/easy_file.cpp @@ -11,11 +11,6 @@ LAMEFile::LAMEFile() : file_(NULL) { LAMEFile::~LAMEFile() { } bool LAMEFile::open(const char *filename, eFileMode mode) { - //for easier access if we want to expand the path.. - // String temp=filename; - // temp = getRelativePath(temp); - - //it's time to open the file file_ = fopen(filename, mode == FILE_READ ? "rb" : "wb"); if (!file_) { diff --git a/file/easy_file.h b/file/easy_file.h index a0c4d24074..019ea0c2ab 100644 --- a/file/easy_file.h +++ b/file/easy_file.h @@ -1,5 +1,7 @@ #pragma once +// A dumb wrapper around stdio, for convenience. Very old. + #include #include @@ -13,6 +15,7 @@ enum eFileMode { FILE_WRITE=6 }; +// TODO: Rename. class LAMEFile { public: LAMEFile(); diff --git a/file/file_util.cpp b/file/file_util.cpp index 51e9684e07..ba9d8ef073 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -27,7 +27,6 @@ bool WriteStringToFile(bool text_file, const std::string &str, const char *filen return true; } -// Overloaded GetSize, accepts FILE* uint64_t GetSize(FILE *f) { // can't use off_t here because it can be 32-bit @@ -36,7 +35,9 @@ uint64_t GetSize(FILE *f) return 0; } uint64_t size = ftell(f); + // Reset the seek position to where it was when we started. if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) { + // Should error here return 0; } return size; @@ -122,4 +123,4 @@ void deleteFile(const char *file) } #endif } -#endif \ No newline at end of file +#endif diff --git a/file/file_util.h b/file/file_util.h index 06ed549824..8b2e985894 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -3,9 +3,10 @@ #include #include +// Whole-file reading/writing bool writeStringToFile(bool text_file, const std::string &str, const char *filename); bool readFileToString(bool text_file, const char *filename, std::string &str); - +// Beginnings of a directory utility system. TODO: Improve. size_t getFilesInDir(const char *directory, std::vector *files); -void deleteFile(const char *file); \ No newline at end of file +void deleteFile(const char *file); diff --git a/file/vfs.h b/file/vfs.h index 552eb6dbc1..b5a5643c8e 100644 --- a/file/vfs.h +++ b/file/vfs.h @@ -1,12 +1,15 @@ #include "base/basictypes.h" +// Basic virtual file system. Used to manage assets on Android, where we have to +// read them manually out of the APK zipfile, while being able to run on other +// platforms as well with the appropriate directory set-up. + class AssetReader; -// Virtual file system. void VFSRegister(const char *prefix, AssetReader *reader); void VFSShutdown(); -// Use delete [] to release the memory. -// Always allocates an extra '\0' at the end, so that it +// Use delete [] to release the returned memory. +// Always allocates an extra zero byte at the end, so that it // can be used for text like shader sources. uint8_t *VFSReadFile(const char *filename, size_t *size); diff --git a/file/zip_read.h b/file/zip_read.h index 4194b5fd26..33c0752cdc 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -1,3 +1,5 @@ +// TODO: Move much of this code to vfs.cpp + #ifndef _WIN32 #include #endif diff --git a/gfx/gl_debug_log.h b/gfx/gl_debug_log.h index 115a393d1a..f6cc7f2f4e 100644 --- a/gfx/gl_debug_log.h +++ b/gfx/gl_debug_log.h @@ -1,9 +1,10 @@ #pragma once -// New skool debugging -void gl_log_enable(); +// Utility to be able to liberally sprinkle GL error checks around your code +// and easily disable them all in release builds - just undefine DEBUG_OPENGL. -// Old skool debugging + +void gl_log_enable(); #ifndef ANDROID //#define DEBUG_OPENGL diff --git a/gfx/gl_lost_manager.h b/gfx/gl_lost_manager.h index fbcc4165ce..699d17075f 100644 --- a/gfx/gl_lost_manager.h +++ b/gfx/gl_lost_manager.h @@ -1,5 +1,8 @@ #pragma once +// On Android, even OpenGL can lose allocated resources. This is a utility to keep +// track of them. + class GfxResourceHolder { public: virtual ~GfxResourceHolder(); diff --git a/gfx/texture.cpp b/gfx/texture.cpp index a36041392c..0132fe49d8 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -98,8 +98,10 @@ bool Texture::Load(const char *filename) { } filename_ = filename; - // Currently contains many Rollerball-specific workarounds. + + // Currently here are a bunch of project-specific workarounds. // They shouldn't really hurt anything else very much though. + int len = strlen(filename); char fn[256]; strcpy(fn, filename); diff --git a/gfx/texture.h b/gfx/texture.h index ffc7a05cb2..8704026284 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -1,6 +1,9 @@ #ifndef _TEXTURE_H #define _TEXTURE_H +// Load and manage OpenGL textures easily. Supports ETC1 compressed texture with mipmaps. + + #include #include "gfx/gl_lost_manager.h" diff --git a/gfx/texture_dx11.cpp b/gfx/texture_dx11.cpp index bec73980c4..8dd0f6a9ce 100644 --- a/gfx/texture_dx11.cpp +++ b/gfx/texture_dx11.cpp @@ -1,3 +1,7 @@ +// WIP, please ignore + + + #include "gfx/texture.h" #include diff --git a/gfx/texture_gen.cpp b/gfx/texture_gen.cpp index dd02e0079b..59226408f0 100644 --- a/gfx/texture_gen.cpp +++ b/gfx/texture_gen.cpp @@ -1,9 +1,8 @@ -// Minimal procedural texture generator to generate some usual textures like circles. +// Minimal procedural texture generator to generate some usual textures like circles and vignette textures. // "Gen" textures have filenames like this: "gen:256:256:vignette:0.1" // // These must be VERY VERY fast to not slow down loading. Could multicore this in the // future. -// TODO: Rewrite to make more portable (should not use gfx api in here) #include #include diff --git a/gfx/texture_gen.h b/gfx/texture_gen.h index f5653b6f48..063aeae8cb 100644 --- a/gfx/texture_gen.h +++ b/gfx/texture_gen.h @@ -3,9 +3,4 @@ #include "gfx/texture.h" -// Returns an OpenGL ID for now. - uint8_t *generateTexture(const char *filename, int &bpp, int &w, int &h, bool &clamp); - - - diff --git a/gfx_es1/draw_buffer.h b/gfx_es1/draw_buffer.h index 8796f85447..a1ba53f481 100644 --- a/gfx_es1/draw_buffer.h +++ b/gfx_es1/draw_buffer.h @@ -1,3 +1,5 @@ +// OpenGL-based 2D primitive buffer. For GLES 1.1. + #ifndef __LAMEBUFFER_H__ #define __LAMEBUFFER_H__ @@ -16,7 +18,6 @@ enum { TEXT_RIGHT = 16, }; -// OpenGL-based 2D primitive buffer. For GLES 1.1. // Do not inherit from this class. class LAMEBuffer { public: @@ -45,7 +46,6 @@ class LAMEBuffer { void rectFillDarken(int x1, int y1, int x2, int y2); - // New drawing APIs void MeasureImage(int atlas_image, float *w, float *h); void DrawImage(int atlas_image, float x, float y, Color color = COLOR(0xFFFFFF)); void DrawImageCenter(int atlas_image, float x, float y, Color color = COLOR(0xFFFFFF)); diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 6b92bf6b3e..7c82788255 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -18,9 +18,13 @@ #include "gfx/texture_atlas.h" #include "gfx/gl_debug_log.h" -DrawBuffer::DrawBuffer() : count_(0) { +enum { // Enough? - verts_ = new Vertex[5000]; + MAX_VERTS = 5000, +}; + +DrawBuffer::DrawBuffer() : count_(0) { + verts_ = new Vertex[MAX_VERTS]; fontscalex = 1.0f; fontscaley = 1.0f; } @@ -141,7 +145,7 @@ void DrawBuffer::DrawImageStretch(int atlas_image, float x1, float y1, float x2, V(x1, y2, color, image.u1, image.v2); } -// TODO: make into arc +// TODO: add arc support void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul) { float angleDelta = PI * 2 / segments; float uDelta = 1.0f / segments; @@ -153,7 +157,7 @@ void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int s float angle2 = (i + 1) * angleDelta; float u1 = u_mul * i * uDelta; float u2 = u_mul * (i + 1) * uDelta; - // TODO: get rid of one pair of cos/sin per loop, can reuse + // TODO: get rid of one pair of cos/sin per loop, can reuse from last iteration float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2); const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc}; const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc}; @@ -284,4 +288,4 @@ void DrawBuffer::EnableBlend(bool enable) { glEnable(GL_BLEND); else glDisable(GL_BLEND); -} \ No newline at end of file +} diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 89ea949f4e..81bc503a7a 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -1,5 +1,7 @@ #pragma once +// "Immediate mode"-lookalike buffered drawing. Very fast way to draw 2D. + #include "base/basictypes.h" #include "base/color.h" @@ -33,15 +35,13 @@ struct GradientStop uint32_t color; }; -// Similar to QuadBuffer but only uses a vertex array that it keeps -// around. class DrawBuffer { public: DrawBuffer(); ~DrawBuffer(); void Begin(DrawBufferMode mode = DBMODE_NORMAL); - void End(); // Currently does nothing, but call it! + void End(); int Count() const { return count_; } diff --git a/gfx_es2/glsl_program.h b/gfx_es2/glsl_program.h index 55d3531d2e..58392f64d2 100644 --- a/gfx_es2/glsl_program.h +++ b/gfx_es2/glsl_program.h @@ -1,3 +1,6 @@ +// Utility code for loading GLSL shaders. +// Has support for auto-reload, see glsl_refresh + #ifndef _RENDER_UTIL #define _RENDER_UTIL diff --git a/gfx_es2/vertex_format.h b/gfx_es2/vertex_format.h index d4c844c0ba..edaac48145 100644 --- a/gfx_es2/vertex_format.h +++ b/gfx_es2/vertex_format.h @@ -1,5 +1,7 @@ #pragma once +// TODO: Actually use for something :) + #include "base/basictypes.h" // Vertex format flags diff --git a/image/build.scons b/image/build.scons deleted file mode 100644 index edc7163ec3..0000000000 --- a/image/build.scons +++ /dev/null @@ -1,15 +0,0 @@ -# Bring in the environment to use for this component (boilerplate). -Import('env') - -# This is the list of input source files to the mandelbrot_gen library. Headers -# will be detected automatically. -inputs = ['png_load.cpp', - 'zim_load.cpp', - ] - -# Build these into a library. -env.ComponentLibrary('image', inputs) - -env.Append(LIBS = [ 'base', 'png', 'image', 'z', 'glog' ]) -inputs = ['zimagetool.cpp'] -env.ComponentProgram('zimagetool', inputs) diff --git a/image/surface.h b/image/surface.h index 39377b3864..2434f1c38c 100644 --- a/image/surface.h +++ b/image/surface.h @@ -1,6 +1,9 @@ #ifndef _GFX_SURFACE #define _GFX_SURFACE +// UNUSED + + enum SurfaceFormats { SURF_ARGB, SURF_YUV, diff --git a/image/zim_load.h b/image/zim_load.h index b76fdc2ee3..cc4eb925ed 100644 --- a/image/zim_load.h +++ b/image/zim_load.h @@ -13,7 +13,7 @@ // 4 byte width // 4 byte height // 4 byte flags -// The rest is zlibbed data. If multiple mips, they are zlibbed separately. +// Uncompressed or ZLibbed data. If multiple mips, zlibbed separately. // Defined flags: diff --git a/image/zim_save.cpp b/image/zim_save.cpp index 91305eed02..52e3c9c400 100644 --- a/image/zim_save.cpp +++ b/image/zim_save.cpp @@ -182,7 +182,7 @@ uint8_t *DownsampleBy2(const uint8_t *image, int width, int height, int pitch) { gamma[i] = powf((float)i / 32764.0f, 2.2f) * 255.0f; } - // Let's start with something really stupid. + // Really stupid mipmap downsampling - at least it does gamma though. for (int y = 0; y < height; y+=2) { for (int x = 0; x < width; x+=2) { const uint8_t *tl = image + pitch * y + x*4; diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 44c92b614d..69fbad52b8 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -65,4 +65,4 @@ bool dragDelta(int i, float *xdelta, float *ydelta) { *ydelta = fingers[i].Y - fingers[i].lastY; } -} \ No newline at end of file +} diff --git a/input/gesture_detector.h b/input/gesture_detector.h index d34bbc9159..e8cea6933f 100644 --- a/input/gesture_detector.h +++ b/input/gesture_detector.h @@ -1,5 +1,6 @@ #include "input/input_state.h" +// WIP - doesn't do much yet // Mainly for detecting (multi-)touch gestures but also useable for left button mouse dragging etc. namespace GestureDetector @@ -17,4 +18,4 @@ namespace GestureDetector bool dragDelta(int finger, float *xdelta, float *ydelta); -}; \ No newline at end of file +}; diff --git a/input/input_state.h b/input/input_state.h index d663d52dbd..333972ff55 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -41,6 +41,8 @@ struct InputState { int mouse_buttons_up; int mouse_last_buttons; + // TODO: Multitouch + // Accelerometer bool accelerometer_valid; Vec3 acc; diff --git a/json/json_writer.cpp b/json/json_writer.cpp index d626feb92d..750c4ee8f1 100644 --- a/json/json_writer.cpp +++ b/json/json_writer.cpp @@ -4,7 +4,6 @@ JsonWriter::JsonWriter() { } JsonWriter::~JsonWriter() { - } void JsonWriter::begin() { diff --git a/json/json_writer.h b/json/json_writer.h index 63de1d1260..5b339b359c 100644 --- a/json/json_writer.h +++ b/json/json_writer.h @@ -1,14 +1,14 @@ -// Minimal-state ultra-minimal JSON writer. Consumes almost no memory +// Minimal-state JSON writer. Consumes almost no memory // apart from the string being built-up, which could easily be replaced // with a file stream (although I've chosen not to do that just yet). // -// Writes nicely 2-spade indented output with correct comma-placement +// Writes nicely 2-space indented output with correct comma-placement // in arrays and dictionaries. // // Does not deal with encodings in any way. // // Zero dependencies apart from stdlib. -// Public domain by Henrik Rydgård. +// See json_writer_test.cpp for usage. #include #include diff --git a/math/build.scons b/math/build.scons deleted file mode 100644 index 17d6c4ff4c..0000000000 --- a/math/build.scons +++ /dev/null @@ -1,8 +0,0 @@ -Import('env') - -inputs = [ - 'math_util.cc', -] - -env.Append(LIBS = ['gflags', 'glog', ]) -env.ComponentLibrary('math_util', inputs, COMPONENT_STATIC=True) diff --git a/math/compression.h b/math/compression.h index 8200e52ea9..f9e457c8d0 100644 --- a/math/compression.h +++ b/math/compression.h @@ -1,5 +1,6 @@ #pragma once +// Delta encoding/decoding - many formats benefit from a pass of this before zlibbing. // WARNING : Do not use these with floating point data, especially not float16... template diff --git a/math/lin/build.scons b/math/lin/build.scons deleted file mode 100644 index 41b0cf46c2..0000000000 --- a/math/lin/build.scons +++ /dev/null @@ -1,12 +0,0 @@ -Import('env') - -inputs = [ - 'aabb.cc', - 'matrix4x4.cc', - 'vec3.cc', - 'quat.cc', - 'ray_intersections.cc', -] - -env.Append(LIBS = ['gflags', 'glog', ]) -env.ComponentLibrary('lin', inputs, COMPONENT_STATIC=True) diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp index a2e7f32c93..78312aab00 100644 --- a/math/lin/matrix4x4.cpp +++ b/math/lin/matrix4x4.cpp @@ -141,7 +141,6 @@ void Matrix4x4::setViewLookAtD3D(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 float Length = vUp.length(); if (1e-6f > Length) { - // EMERGENCY vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; // If we still have near-zero length, resort to a different axis. Length = vUp.length(); diff --git a/math/lin/quat.cpp b/math/lin/quat.cpp index b869aa6b87..cf17735634 100644 --- a/math/lin/quat.cpp +++ b/math/lin/quat.cpp @@ -76,6 +76,7 @@ Quaternion Quaternion::fromMatrix(Matrix4x4 &m) return q; }; +// TODO: Allegedly, lerp + normalize can achieve almost as good results. Quaternion Quaternion::slerp(const Quaternion &to, const float a) const { Quaternion to2; float angle, cos_angle, scale_from, scale_to, sin_angle; diff --git a/math/lin/vec3.h b/math/lin/vec3.h index 92badf89f9..546d035f82 100644 --- a/math/lin/vec3.h +++ b/math/lin/vec3.h @@ -112,13 +112,6 @@ public: (*this) = (*this)/len; return len; } - /* - float &operator [] (int i) { //allow vector[2] = 3 (vector.z=3) - return *((&x) + i); - } - const float operator [] (const int i) const { - return *((&x) + i); - }*/ bool operator == (const Vec3 &other) const { if (x==other.x && y==other.y && z==other.z) return true; diff --git a/math/math_util.h b/math/math_util.h index 573a7e864d..9ff895d7bf 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -6,8 +6,8 @@ typedef unsigned short float16; -// This ain't a 1.5.10 float16, no sire, it's a stupid hack format where we chop 16 bits off a float. -// This choice is subject to change. +// This ain't a 1.5.10 float16, it's a stupid hack format where we chop 16 bits off a float. +// This choice is subject to change. Don't think I'm using this for anything at all now anyway. inline float16 FloatToFloat16(float x) { int ix; memcpy(&ix, &x, sizeof(float)); @@ -26,6 +26,7 @@ inline float Float16ToFloat(float16 ix) { // The stuff in this file is from all over the web, esp. dspmusic.org. I think it's all public domain. // In any case, very little of it is used anywhere at the moment. +// PM modulated sine inline float sine(float t,float f,float ph,float fm) { return sinf((t*f+ph)*2*PI + 0.5f*PI*fm*(1 - sqrt(f*2))); } diff --git a/native.vcxproj b/native.vcxproj index ec9e00b9d9..4a4506782e 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -176,4 +176,4 @@ - \ No newline at end of file + diff --git a/profiler/profiler.h b/profiler/profiler.h index 2eb52c6586..a1ed0bd2c0 100644 --- a/profiler/profiler.h +++ b/profiler/profiler.h @@ -1,5 +1,6 @@ #pragma once +// WIP - very preliminary. // #define USE_PROFILER #ifdef USE_PROFILER diff --git a/util/bits/bits.cc b/util/bits/bits.cc deleted file mode 100644 index 5267078abe..0000000000 --- a/util/bits/bits.cc +++ /dev/null @@ -1,40 +0,0 @@ -#include "util/bits/bits.h" - -namespace bits { - -// See http://graphics.stanford.edu/~seander/bithacks.html - -static const unsigned char BitsSetTable256[] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 -}; - -int CountBits8(uint8 v) { - return BitsSetTable256[v]; -} - -int CountBits16(uint16 v) { - return BitsSetTable256[v & 0xFF] + BitsSetTable256[v >> 8]; -} - -int CountBits32(uint32 v) { - v = v - ((v >> 1) & 0x55555555); // reuse input as temporary - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp - return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count -} - -} // namespace bits diff --git a/util/bits/varint.cc b/util/bits/varint.cc deleted file mode 100644 index 8cd94d052c..0000000000 --- a/util/bits/varint.cc +++ /dev/null @@ -1,35 +0,0 @@ -#include "util/bits/varint.h" - -namespace varint { - -void Encode32(uint32 value, char **dest) { - // Simple varint - char *p = *dest; - while (value > 127) { - *p++ = (value & 127); - value >>= 7; - } - *p++ = value | 0x80; - *dest = p; -} - -uint32 Decode32(const char **ptr) { - uint32 value = 0; - const char *p = *ptr; - while (true) { - uint8 b = *p++; - if (b & 0x80) { - *ptr = p; - return value | (b & 0x7F); - } else { - value |= *p++; - value <<= 7; - } - } - *ptr = p; - return value; -} - -} // namespace varint - - diff --git a/util/build.scons b/util/build.scons deleted file mode 100644 index 1f668a08f7..0000000000 --- a/util/build.scons +++ /dev/null @@ -1,20 +0,0 @@ -# Bring in the environment to use for this component (boilerplate). -Import('env') - -# This is the list of input source files to the mandelbrot_gen library. Headers -# will be detected automatically. -inputs = ['hash/hash.cc', - 'hash/minhash.cc'] - -# Build these into a library. -env.ComponentLibrary('hash', inputs) - -inputs = ['bits/varint.cc', - 'bits/bits.cc' ] - -env.ComponentLibrary('bits', inputs) - -inputs = ['random/perlin.cc', - ] - -env.ComponentLibrary('random', inputs) diff --git a/util/hash/hash.cc b/util/hash/hash.cc deleted file mode 100644 index 264450dabe..0000000000 --- a/util/hash/hash.cc +++ /dev/null @@ -1,65 +0,0 @@ -#include "base/base.h" -#include "util/hash/hash.h" - -namespace hash { - -// uint32_t -// WARNING - may read one more byte! -// Implementation from Wikipedia. -uint32 HashFletcher(const uint8 *data_uint8, size_t length) { - const uint16 *data = (const uint16 *)data_uint8; - size_t len = (length + 1) / 2; - uint32 sum1 = 0xffff, sum2 = 0xffff; - - while (len) { - size_t tlen = len > 360 ? 360 : len; - len -= tlen; - - do { - sum1 += *data++; - sum2 += sum1; - } while (--tlen); - - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - } - - /* Second reduction step to reduce sums to 16 bits */ - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - return sum2 << 16 | sum1; -} - -// Implementation from Wikipedia -// Slightly slower than Fletcher above, but slighly more reliable. -#define MOD_ADLER 65521 -// data: Pointer to the data to be summed; len is in bytes -uint32 HashAdler32(const uint8 *data, size_t len) { - uint32 a = 1, b = 0; - while (len) { - size_t tlen = len > 5550 ? 5550 : len; - len -= tlen; - do { - a += *data++; - b += a; - } while (--tlen); - - a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER); - b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); - } - - // It can be shown that a <= 0x1013a here, so a single subtract will do. - if (a >= MOD_ADLER) { - a -= MOD_ADLER; - } - - // It can be shown that b can reach 0xfff87 here. - b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); - - if (b >= MOD_ADLER) { - b -= MOD_ADLER; - } - return (b << 16) | a; -} - -} // namespace hash diff --git a/util/hash/hash.h b/util/hash/hash.h index 3f80714185..1091990534 100644 --- a/util/hash/hash.h +++ b/util/hash/hash.h @@ -10,21 +10,6 @@ namespace hash { uint32 Fletcher(const uint8 *data_u8, size_t length); // FAST. Length & 1 == 0. uint32 Adler32(const uint8 *data, size_t len); // Fairly accurate, slightly slower -// WTF is this for? -class ConsistentHasher { - public: - ConsistentHasher() { - // TODO: really need a better seed here. - uint32 orig_seed = rand(); - seed = Fletcher((const uint8 *)&orig_seed, 4); - } - uint32 Hash(uint32 value) { - return value ^ seed; - } - private: - uint32 seed; -}; - } // namespace hash #endif diff --git a/util/random/perlin.cc b/util/random/perlin.cc deleted file mode 100644 index d0ee8a9fa4..0000000000 --- a/util/random/perlin.cc +++ /dev/null @@ -1,72 +0,0 @@ -#include "util/random/perlin.h" - -#include - -// This should go in the const section of the binary. -static const int p[512] = { - 151,160,137,91,90,15, - 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, - 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, - 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, - 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, - 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, - 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, - 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, - 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, - 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, - 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, - 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, - 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, - 151,160,137,91,90,15, - 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, - 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, - 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, - 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, - 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, - 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, - 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, - 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, - 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, - 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, - 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, - 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, -}; - -inline float fade(float t) { - return t * t * t * (t * (t * 6 - 15) + 10); -} - -inline float lerp(float t, float a, float b) { - return a + t * (b - a); -} - -inline float grad(int hash, float x, float y, float z) { - int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE - float u = h < 8 ? x : y; // INTO 12 GRADIENT DIRECTIONS. - float v = h < 4 ? y : (h == 12 || h == 14 ? x : z); - return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); -} - -float Noise(double z, double y, double x) { - double fx = floor(x), fy = floor(y), fz = floor(z); - int X = (int)fx & 255, // FIND UNIT CUBE THAT - Y = (int)fy & 255, // CONTAINS POINT. - Z = (int)fz & 255; - x -= fx; // FIND RELATIVE X,Y,Z - y -= fy; // OF POINT IN CUBE. - z -= fz; - float u = fade(x); // COMPUTE FADE CURVES - float v = fade(y); // FOR EACH OF X,Y,Z. - float w = fade(z); - int A = p[X ]+Y, B = p[X+1]+Y; - int AA = p[A]+Z, AB = p[A+1]+Z; // HASH COORDINATES OF - int BA = p[B]+Z, BB = p[B+1]+Z; // THE 8 CUBE CORNERS, - return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD - grad(p[BA ], x-1, y , z )), // BLENDED - lerp(u, grad(p[AB ], x , y-1, z ), // RESULTS - grad(p[BB ], x-1, y-1, z ))), // FROM 8 - lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), // CORNERS - grad(p[BA+1], x-1, y , z-1 )), // OF CUBE - lerp(u, grad(p[AB+1], x , y-1, z-1 ), - grad(p[BB+1], x-1, y-1, z-1 )))); -} From 4b4e6e1acf7aaa487168a2a7b687d74b76e7bb79 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 31 Mar 2012 11:17:15 +0200 Subject: [PATCH 0010/1445] Forgot to add these --- util/bits/bits.cpp | 40 +++++++++++++++++++++++ util/bits/varint.cpp | 35 ++++++++++++++++++++ util/hash/hash.cpp | 65 ++++++++++++++++++++++++++++++++++++++ util/random/perlin.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 212 insertions(+) create mode 100644 util/bits/bits.cpp create mode 100644 util/bits/varint.cpp create mode 100644 util/hash/hash.cpp create mode 100644 util/random/perlin.cpp diff --git a/util/bits/bits.cpp b/util/bits/bits.cpp new file mode 100644 index 0000000000..5267078abe --- /dev/null +++ b/util/bits/bits.cpp @@ -0,0 +1,40 @@ +#include "util/bits/bits.h" + +namespace bits { + +// See http://graphics.stanford.edu/~seander/bithacks.html + +static const unsigned char BitsSetTable256[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 +}; + +int CountBits8(uint8 v) { + return BitsSetTable256[v]; +} + +int CountBits16(uint16 v) { + return BitsSetTable256[v & 0xFF] + BitsSetTable256[v >> 8]; +} + +int CountBits32(uint32 v) { + v = v - ((v >> 1) & 0x55555555); // reuse input as temporary + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count +} + +} // namespace bits diff --git a/util/bits/varint.cpp b/util/bits/varint.cpp new file mode 100644 index 0000000000..8cd94d052c --- /dev/null +++ b/util/bits/varint.cpp @@ -0,0 +1,35 @@ +#include "util/bits/varint.h" + +namespace varint { + +void Encode32(uint32 value, char **dest) { + // Simple varint + char *p = *dest; + while (value > 127) { + *p++ = (value & 127); + value >>= 7; + } + *p++ = value | 0x80; + *dest = p; +} + +uint32 Decode32(const char **ptr) { + uint32 value = 0; + const char *p = *ptr; + while (true) { + uint8 b = *p++; + if (b & 0x80) { + *ptr = p; + return value | (b & 0x7F); + } else { + value |= *p++; + value <<= 7; + } + } + *ptr = p; + return value; +} + +} // namespace varint + + diff --git a/util/hash/hash.cpp b/util/hash/hash.cpp new file mode 100644 index 0000000000..264450dabe --- /dev/null +++ b/util/hash/hash.cpp @@ -0,0 +1,65 @@ +#include "base/base.h" +#include "util/hash/hash.h" + +namespace hash { + +// uint32_t +// WARNING - may read one more byte! +// Implementation from Wikipedia. +uint32 HashFletcher(const uint8 *data_uint8, size_t length) { + const uint16 *data = (const uint16 *)data_uint8; + size_t len = (length + 1) / 2; + uint32 sum1 = 0xffff, sum2 = 0xffff; + + while (len) { + size_t tlen = len > 360 ? 360 : len; + len -= tlen; + + do { + sum1 += *data++; + sum2 += sum1; + } while (--tlen); + + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + } + + /* Second reduction step to reduce sums to 16 bits */ + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + return sum2 << 16 | sum1; +} + +// Implementation from Wikipedia +// Slightly slower than Fletcher above, but slighly more reliable. +#define MOD_ADLER 65521 +// data: Pointer to the data to be summed; len is in bytes +uint32 HashAdler32(const uint8 *data, size_t len) { + uint32 a = 1, b = 0; + while (len) { + size_t tlen = len > 5550 ? 5550 : len; + len -= tlen; + do { + a += *data++; + b += a; + } while (--tlen); + + a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER); + b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); + } + + // It can be shown that a <= 0x1013a here, so a single subtract will do. + if (a >= MOD_ADLER) { + a -= MOD_ADLER; + } + + // It can be shown that b can reach 0xfff87 here. + b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); + + if (b >= MOD_ADLER) { + b -= MOD_ADLER; + } + return (b << 16) | a; +} + +} // namespace hash diff --git a/util/random/perlin.cpp b/util/random/perlin.cpp new file mode 100644 index 0000000000..d0ee8a9fa4 --- /dev/null +++ b/util/random/perlin.cpp @@ -0,0 +1,72 @@ +#include "util/random/perlin.h" + +#include + +// This should go in the const section of the binary. +static const int p[512] = { + 151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, + 151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, + 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, + 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, + 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, + 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, + 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, + 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, + 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, + 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, + 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, + 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, + 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, +}; + +inline float fade(float t) { + return t * t * t * (t * (t * 6 - 15) + 10); +} + +inline float lerp(float t, float a, float b) { + return a + t * (b - a); +} + +inline float grad(int hash, float x, float y, float z) { + int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE + float u = h < 8 ? x : y; // INTO 12 GRADIENT DIRECTIONS. + float v = h < 4 ? y : (h == 12 || h == 14 ? x : z); + return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); +} + +float Noise(double z, double y, double x) { + double fx = floor(x), fy = floor(y), fz = floor(z); + int X = (int)fx & 255, // FIND UNIT CUBE THAT + Y = (int)fy & 255, // CONTAINS POINT. + Z = (int)fz & 255; + x -= fx; // FIND RELATIVE X,Y,Z + y -= fy; // OF POINT IN CUBE. + z -= fz; + float u = fade(x); // COMPUTE FADE CURVES + float v = fade(y); // FOR EACH OF X,Y,Z. + float w = fade(z); + int A = p[X ]+Y, B = p[X+1]+Y; + int AA = p[A]+Z, AB = p[A+1]+Z; // HASH COORDINATES OF + int BA = p[B]+Z, BB = p[B+1]+Z; // THE 8 CUBE CORNERS, + return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD + grad(p[BA ], x-1, y , z )), // BLENDED + lerp(u, grad(p[AB ], x , y-1, z ), // RESULTS + grad(p[BB ], x-1, y-1, z ))), // FROM 8 + lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), // CORNERS + grad(p[BA+1], x-1, y , z-1 )), // OF CUBE + lerp(u, grad(p[AB+1], x , y-1, z-1 ), + grad(p[BB+1], x-1, y-1, z-1 )))); +} From af2245c612cb294569e123ee23429549b46747fd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 31 Mar 2012 12:43:27 +0200 Subject: [PATCH 0011/1445] README update --- README.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 54e111af82..da381e280e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ native ====== -This is my library of stuff that I use when writing C++ programs, mostly for Android but it's all written to enable easy portability between Android, Linux, Windows and MacOSX. +This is my library of stuff that I use when writing C++ programs, mostly for Android but it's all written to enable easy portability between Android, Linux, Windows and MacOSX. The code is part ugly, part inconsistent but quite useful. + +Features +-------- -It contains: * JSON read/write (two libraries that should be made more similar) * basic OpenGL utility code, like compressed texture loading * 2D texture atlases and drawing code @@ -12,14 +14,16 @@ It contains: * Really simple audio mixer with OGG sample support * RIFF file read/write -The associated tools to create ZIM texture files and atlases do not yet live here but I might move them here eventually. +Notes +----- -This library is not really meant to be a public library but I see no reason not to set it free. - -Note that the included VS project is probably not very useful for you and you're likely better off making your own. - -Don't complain about inconsistent naming etc - this consists of code that has been cobbled together from a variety of my projects through the years. Fashions come and go. +* The associated tools to create ZIM texture files and atlases do not yet live here but I might move them here eventually. +* This library is not really meant to be a public library but I see no reason not to set it free. +* Note that the included VS project is probably not very useful for you and you're likely better off making your own. +* Don't complain about inconsistent naming etc - this consists of code that has been cobbled together from a variety of my projects through the years. Fashions come and go. +Licenses +-------- This library, for my convenience, incorporates code from a variety of public domain or similarly-licensed code. This is the list: @@ -32,10 +36,13 @@ This library, for my convenience, incorporates code from a variety of public dom If you're not okay with the licenses above, don't use this code. -If you find this useful for your own projects, drop me a line at hrydgard@gmail.com . - I hereby release all code here not under the licenses above under the MIT license. +Contact +------- + +If you find this useful for your own projects, drop me a line at hrydgard@gmail.com . + Henrik Rydgård From a893d5cdc2f1ea6f444f6bf9052080c96a4ed6a2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 31 Mar 2012 22:07:33 +0200 Subject: [PATCH 0012/1445] Misc --- file/file_util.cpp | 13 +++++++++++++ file/file_util.h | 2 ++ gfx_es2/glsl_program.cpp | 4 +++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index ba9d8ef073..f18d78a95c 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -124,3 +124,16 @@ void deleteFile(const char *file) #endif } #endif + +std::string getDir(const std::string &path) +{ + int n = path.size() - 1; + while (n >= 0 && path[n] != '\\' && path[n] != '/') + n--; + std::string cutpath = path.substr(0, n); + for (int i = 0; i < cutpath.size(); i++) + { + if (cutpath[i] == '\\') cutpath[i] = '/'; + } + return cutpath; +} \ No newline at end of file diff --git a/file/file_util.h b/file/file_util.h index 8b2e985894..d5d3e4450d 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -10,3 +10,5 @@ bool readFileToString(bool text_file, const char *filename, std::string &str); // Beginnings of a directory utility system. TODO: Improve. size_t getFilesInDir(const char *directory, std::vector *files); void deleteFile(const char *file); + +std::string getDir(const std::string &path); diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 3cc6bad08a..be93cdfca3 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -37,7 +37,9 @@ bool CompileShader(const char *source, GLuint shader, const char *filename) { ELOG("Error in shader compilation of %s!\n", filename); ELOG("Info log: %s\n", infoLog); ELOG("Shader source:\n%s\n", (const char *)source); - exit(1); +#ifdef ANDROID + exit(1); +#endif return false; } return true; From cb7e3e62e7fb7843460c014164f598fede664c6f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 6 Apr 2012 16:59:39 +0200 Subject: [PATCH 0013/1445] Don't reference removed files --- base/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 060fd25425..ab9db52bed 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -1,6 +1,4 @@ set(SRCS - LAME.cpp - LAMEApp.cpp LAMEString.cpp colorutil.cpp error_context.cpp) From 0983adb05275347832cfc21b2d540e7c17c45a86 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 10 Apr 2012 00:05:51 +0200 Subject: [PATCH 0014/1445] Move the Android Java wrapper code in here. --- android/.classpath | 8 + android/.gitignore | 2 + android/.project | 33 ++ android/AndroidManifest.xml | 14 + android/proguard-project.txt | 20 + android/project.properties | 15 + android/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 9397 bytes android/res/drawable-ldpi/ic_launcher.png | Bin 0 -> 2729 bytes android/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 5237 bytes android/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 14383 bytes android/res/layout/main.xml | 12 + android/res/values/strings.xml | 7 + .../turboviking/libnative/NativeActivity.java | 449 ++++++++++++++++++ .../com/turboviking/libnative/NativeApp.java | 18 + 14 files changed, 578 insertions(+) create mode 100644 android/.classpath create mode 100644 android/.gitignore create mode 100644 android/.project create mode 100644 android/AndroidManifest.xml create mode 100644 android/proguard-project.txt create mode 100644 android/project.properties create mode 100644 android/res/drawable-hdpi/ic_launcher.png create mode 100644 android/res/drawable-ldpi/ic_launcher.png create mode 100644 android/res/drawable-mdpi/ic_launcher.png create mode 100644 android/res/drawable-xhdpi/ic_launcher.png create mode 100644 android/res/layout/main.xml create mode 100644 android/res/values/strings.xml create mode 100644 android/src/com/turboviking/libnative/NativeActivity.java create mode 100644 android/src/com/turboviking/libnative/NativeApp.java diff --git a/android/.classpath b/android/.classpath new file mode 100644 index 0000000000..a4763d1eec --- /dev/null +++ b/android/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000000..021b4205f9 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,2 @@ +gen +bin diff --git a/android/.project b/android/.project new file mode 100644 index 0000000000..790a38db49 --- /dev/null +++ b/android/.project @@ -0,0 +1,33 @@ + + + libnative + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml new file mode 100644 index 0000000000..d2dd97c058 --- /dev/null +++ b/android/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/android/proguard-project.txt b/android/proguard-project.txt new file mode 100644 index 0000000000..f2fe1559a2 --- /dev/null +++ b/android/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/android/project.properties b/android/project.properties new file mode 100644 index 0000000000..8061f9c3fe --- /dev/null +++ b/android/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt + +# Project target. +target=android-8 +android.library=true diff --git a/android/res/drawable-hdpi/ic_launcher.png b/android/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..96a442e5b8e9394ccf50bab9988cb2316026245d GIT binary patch literal 9397 zcmV;mBud+fP)L`9r|n3#ts(U@pVoQ)(ZPc(6i z8k}N`MvWQ78F(rhG(?6FnFXYo>28{yZ}%O}TvdDT_5P?j=iW=V`8=UNc_}`JbG!ST zs@lK(TWkH+P**sB$A`cEY%Y53cQ}1&6`x-M$Cz&{o9bLU^M-%^mY?+vedlvt$RT-^ zu|w7}IaWaljBq#|I%Mpo!Wc2bbZF3KF9|D%wZe{YFM=hJAv$>j>nhx`=Wis#KG!cJA5x!4)f) zezMz1?Vn$GnZNjbFXH(pK83nn!^3=+^*kTTs5rV9Dq^XS(IKO!mKt5!dSmb3IVCxZ z8TTk5IE)F1V29$G7v#j9d-hy&_pdg8?kT4)zqr>?`}I%W>(?GO%*C&}?Fp|bI*~2&KZ$%^B6R&1~2kA{`CWy+>F-x=z-f{_&vyu_3yp{jtw(*syi% zu3t2|4{c~LJXRt2m>rMg2V_kLltCZ<`m>qcI?BPP?6hf``|e!rZEFszeYQ3f-*nAS zZ+h1$mFwy+7156lkB(k6)!1fUbJCxgIBK38$jj5cC$r&YXN)nr#PY=tJaLc?C_o?j+8H3Q>891JJ9&$l-r+-SG#q)*;r52% z@nlKflb65o%s*Jt)!pw1k{vIoQIvoJ0Y&Msiw0X!qJ)_47G*?aJ6bJFLh_4b$5&1k5wN>du*>6#i7R9T8; z7>EHOV=ue7mo77SJPwER4(A+s?n0JjYK)b}Om6n>ke?0JR=jTI+RFBg_iwb7k%n*2 zR_M0DJ9x+0zxba4(B1y^JQ_Nj6dlP5PGXvSq8fF#mxrFYj3d9(V#jJwt+IqU9+8+D z6C6Us1OI$d8OF!3+Hm1 zW5in zXV^%U35HooOpSmeqlG6e0kUMYNonKp1vr|My9}4-WO+uOxe_c-o&}%voNYHkqtle% z5yQ_^oozSUUNu30EQSAl!Q%(%3G1NXENSMjCL*Vx-Td2~rk(}d z8pT!HZe>1r5EGuz`pgsg@^yQEi=BIa#meLq0!?{TZ}q#}=7UC9_l=w|wv+pP!g4#! zRys6EN$Jv}#U47$k&)pDzvks}LGfPku6P9p!56Py)~1)W(11n7n}`Wx!=;_JTiu#d zpCqx=hEk@t4sp?!j{W}wP@V-=Pd=T^>6IKBy;#mLA7hCe{V7B3@I7Ipa}L`MbF|YQ z)$BNWsiEnoNHrtJli|n8cOnn4NyF=8MbVxgof0>Uv%wM_j94a;8(LMjlL~E(99gJ*2%JtNtAkD@j;^ za~Y~&j6uY{=Rv5S4joH*RW_m9N{ZSN0HhAwFyJNok zS9kx$>wMf%tUi&Eb`6u0lWJ|k?A-42(lp2UmS(PrAc(24wexRiHUieMwf$o%m6$xs zp#-SdBUu2D5`v;(9-sm&kN2M74c&AvKe_v@tQ|dzJ2qSgQHpnUP(iQ?J%Il;Jdyp# z7}cpq6Kdm+FS~zS4Eo;fuO=DFP*UlpO|_CNt5&NUqBvQWxmg7#ARvMf=%#H@p%RZ` zjK$hMbNb+vVP3UlkfIt&ptJ<00Ic{Ka+lF+&w;OEs1O2#V8~O|R*Gq9TIgM&UqM&bZOXBwnbC? zDr))NR&g>lwVgcmnx`K1$)PTTw3m}-T11^ZkY{}jQ@lGD$XzJIcVFkYBBW=o_}TUU zt@yd{Jz;@~72x#!RG(#ira6}v-*J#<{@@^OI-Q2T^}=IKLubsa&V-%WwlF1s7fz~u zMdQTV7SnRet#^`VO0V7H(?59X{uy+S`(sorO@2-+qioUdo9+6r4#|jb=?t50oh42R z{}I>Krut|YKkOc|O|M>y#(3YA;I(i+MiHSfwbJA$jIUr$Y2i|u)*>@2eUYk`j4C5r z>61dKu!AqM_E7#DoDzbd-bfT%AYXUUB{SS|{b{`5^?wz1{PVQgTlvyqOX8(#GTz(U zNPhnj>$lC`xaD56`TjW&uW8p~qikP*F8kHFM0frzdk%UNGjb1O$%uLK`0-)2UsZ3L z#+j+CI_8k4VslL%$aVR@joX>M-@odbX!os$xY$HDIOCokY?{Q0v2kQErf|ZlN>D9w zC+2}E&?rDdi#%))$p%P4C_xGXu=@U~_<|V4L|{>TP$XBp$5pCPXLzK3!;gP>7=QNi zkNOur`>xY=@VSpB#LsN9JKpOz({ANcdv>?K+D_*_HZ<;9>kplj^Ph5!e&&a#?(3vK z_Q@}D_M5kGcx^AuaI~qKYUnb1Mj-n;MURXa)+x7~e2gbMW|gw?5Rg zTOMlo>6zIJ$VNVgn(@kTSL0eP)nR35IHpoHM2W#h6cNmTm@-9`dFJ$;k(S`7Lg@RY zp!hNmb9un!O4Wt05ANDGirv(B14gW| zwjP}C9bK{J`qZ_S2o)b`RonR-b8~y8)$H0`+gg6>#^wu8eCp9xA9B>>8(KRizI?+^ zAJ#i>*({qM-c4gBB~5dzg(wj!HA`hkh!aDl5>u&J;>2K#Ax2)2wt|L!9X;(=*jy!`r4_FhCBoRxNjXNv(~jGQ|%<}%K6RimaBJcP0v}oCgRN3B;oiM)opj? zXm;;tv3q-yy}NqMOr^~3&1lW$w3}UK_IT2sCrkYx5$&6e2A%g;QZUX~A&L!2rFd0p z5%men@^zN_Xw2|v%*c2|wQfkN4r6u&k;LxYY+w3{KY#cie)!iz>(yAgt=&-+Sy2V& z9BJxI+VMKQ%dvY~x>gmEijj3ss_*NAT(8d1@DQ6e&#Ln&6Qk>wHrh>;V2nvomC`8& z(w?`?*_^3u-TJrMzv2~7dH(XLJvUOXk4U8oW6Ol)YsawhIB{GdvIzu1hzMTrE)cvB z%2GxMpaF89<9uF(?cfN(BNR?wwWvCZ6e62+G_{$+;`yjgLj{(^z*zzwd;K3RElb*%=??P zm+lLY0@Y}^kVdMYX5M)YJ~8h=i(S{q#NfU0xPTao4WPDQL=Y_;vg=p%iay1_`<0Ga zMG&<(pOU+bI2u9_g8IJBTqGX*3@G$Zc`pj0f@)vd2?Aj`ms>DHg>;w~p}HXV(*VJX zphd;fht9qL3E)D8h$$A;SGl22Ygv>`iU=A)z=1ZYN$|2`*$`R)?KD>$tw_e9h_x~eX_udS~Q%yz?48i*aIa+_wx|j{B zsG7mwZ)6M3dmvgMC3K-66;ML(9o2xU!F8+qF)>v{1;ip)6v_I)6law|rd_Dx2oV|n z(Qm_PUnTTuKFG)w%s|)lS!w~Lm$k|Al=0djocyHU;>1H=!N}0E0lSV^b2^6~^lUco zyoH+|_!li3#euHd4TJS8=CLaHG9H8g&h3Xm z#>BkpUBAmae(#)qO3)ZMG3irM=5IzA^s+)w86=tIMT{&?Awux<(k2>U#n`c&@Z?u= z%=#BoO-9Nc^?)hz*YW~~tU8rLR-MZBJsY_7fp2r~mY>q-O;L%5Fp?}V6CK=F(18U3 znxB8ZR0TT{)T64RDt!+yFgp!JXGP0|It0Hz2Em#YfRv>O>8A?J=Sz!nq<|{&mW=?~ zDQT{S6PH0|jwy37t+0Ob6izz)JdRlNEUbyk>-K?}FOT=Dj9SuS_0nTFd+A^D?Bo83 zTkicXcW=IuZoZd(Dl;&#`LI;_s?e;OH9quf?*XuV0O$Qh0j~HWKpA|PXV4&b2zs z@W5<)dtovIRZ@gvsi$^s;v05(XwF3$lJ;wzYfE`46fnT7>!qt|hWHRE>yQP)i8= zVbC|O{Ud6%kwGcch>>|pE-=?cW;TDR0lE5Nw7l66lr-zIYT3bj^ujCn$b0{ZO;gwK z#}}W(*T3~in$6ZCpbB98pftPTo;!K>U;H*7_}t4m;;4i9#^2t`pS<=jsnx198);d3 z-M6Mx{7-c0A-jhJQ`5mBy8TBnfbr2~sER5E5oz}=so34cg)GYarRWi8w#W$%G{?Z*4xDb#LX1B1 zg!4G{m~*)H_J8J^SNt`XU-fxjea`>p_$Qyn*Dn18*WdPCp8oWw^XU)%kfRQHMgfQh z1j_ua@O4G%QK;&YH3Y9(q!hkgOUCkcVH5N0Ug(EPX%H6qCfPqg))qrd#ec^47dBu- z=sRkmjGS>3K(tfRTo;zCXO-74hV;y1!vCN}v|w?AWR$YpYXs@Dr?iNLKD9s|2)0aHY!TKTYhwMI z7b#54h!H6rUU9+xnL$g6h?t?Li5guXPY1g)$bI$~rHWP%QkYJ6Y-U^0C(@*$ruN2*zn0QRBOeVpgMFbT%k!Dn1*u#%J^y)enX1K;0~ z%3Q zP(b%}P!Loj6M{v96(Qa~K!bq-V-P89U_K)0zHC_F#L==3IPh2hHG6&?rxvQ%|EljR zfGIDyu=rIrl1dyjuMfwuh?pXZmARwNZ?GbW;5BH5D#nN|WbGm+UGAh7_AcG>4&|{0 zrg?k@h8zm!0A|5Zo%X%g|2tBPKHHB6`~4h?I@bepDe6?^f8w zBnzfOf|j{kR5m6BLRr0$!RZ$PHSk*)tyjkws*DpyHIiiL*8o(Smx(OKT7@D&Y3OI^ zEUMtKa2*SLjt(eJsZsLsrgV`A+xL(~JN#JU6+L)gCe%VuSNbCzTr09w>eZ#779SKV z)m)@#TNVy|q3Tz_U`^7MY`l}`GU~OlQi|*cprX?tm@tIV+8kOGkaa=9Y<{N|RZ)ns zHlgnz2S%qwK9wXjest~Ux$YNNA{0?6Xpv{_mqYt8D`g&7Yb~>lX+HP&AK<=+Zl_kO z6a2g`^4=9W92GQ3e9Mk6?DlzlkIM`iOzwk*5L81TcuyYkI-<3^@49_+^XC7&N}SL1 zh$kIBxb`9+v}acfV?FQ zN#04eHe0*j{pz=zOj3#EHLrT3e)O;3xqpCWrl$e)PcD9jQ4P-8_zyZg^M7i|*kOuj znsvlwNUsy5+01^P_sqMOjXjxKwHn4)$87t-MWZZ*5Dbit4|D9vL+spsJ0JPd?{Ms) zFW^<@yqjZ=IvG%$ck_Cu9|b8CvoV%5P5IZWzs>i4`~`N+-p`7a6RbLHJ;nxtSB#Mb z`1I552=9DrYWFNZ{-=Mt;SVo5@3cmv`IZT@@>#~zCe-=qENxsn+uHfL`e?SbT3IQ_ zt~e)Lcirs_S5^X#?hDYmgV%8QQDe+?>*1&0e^BnaeZz(&D~3<)#QuUL8h*NlXgtr| z&a{_Z)o9FK_U5<0!E3N|yY1P2g%J9s*?!zF78+NSb%!ix)tbQ09oO&|U$~Bwk35^- zec9VN^xz{043e^xD}WEmzh8d^-~Pd8**bEfd+I?HuO~n4SksoN8LRPUy={E<@BjRMUh?X71Xaey>t^$&Eq2B7)u_r$ z|IQwpG52G!F$J5fRo1LqLB7iKz_!bI@27skX~+Eze|Y}IBuRp?hR7z|eA~7B<99#7 zrX4r2a_tCDUb_}Cg)g!OEVeJ5AEVRyb!9~f4OL68qhZZRP0l*>MdkxvxXeGWx$T>+ zI^X!wnYQDnwK9?i)j)eLXJU2Cw>~>R?72@MecvT7;h~2gATow_cbc)$Ws+xNSB{++ zo^tTp^y*(-Y-XF=$XyoBJnMN9+p!Qrep1)%ym_v7zZH{;u~L>T=4XP!f^?uC4ULUR zdl`>x+DVkHVd;|9#N*oubBFQEyRT#UK^0c7T}l)eEEFS)qvZl%f>#I;iCwAWb=kW0 z(e#lm51o?d>D|kgtTscVQCNDAXMAjxSX&{_Qf)T((wMHWWLbz6WpPXP0(3_SBWwI19Vx?$i6WUqP$4O|wjNbYzst$z{58`cBhm z&F(N-KeXFzo#aC|6BbC($As#B8X=}ggpDyQUp|Q>9cG$47#>TQn%T(eHA`5se7KnZ zF_dj_6NN0xS-oZ%Nj%PTpK=MC zw*4IMGls_v)mokI)Dph*pD<)7prEF|j6I$2=XF=Ua3z;BN^yt&H@G%7& zWnL7*e0S9svjSP>kuc;VCbZXUN3G7D8`G@!Qnjt=p=7yC?QH0tsa@RsuPMLj@wf-c z|LV)H$Auga+MTAU#>)eeuh_L`!qC=Ls|{m}Cy)|w6#aP}w6_-ya~9LF z{dQAPa-|&ME858gIK=}lVK7MLT~Oye&UM9y?0X=8Qmvb*)=X}iv%Me)Gqav+FWdGT zuk&#ak~?2Kzf}w)xZuKGx%+`1?Ecoq?*H@EjFm%C6OT577vWKoJB z$A^sIasm!5TGOFFGmHkKNTE7KW3nveUq1bt4Uj)!1_6BJ zU6=EoPrjVdk+pQX+j-GTpQS&&^43tT43kuRlvE8fGdYc!1|m)3WCuwlqB>NeQc0** zYE&wTj*QpuPLfJ)j2$(`sI@k@oR!^9d(3&Kd6r3*<)pooPNzq=)1%#NQ;nAsF*5VR zOYXQC;B^4*Sik--jy?J`uDj-! zSep}9YT4*SOrT2I6MF4H+EZFRPh+}^b4@i8OYk9Y&86o*Y4(`Ax1W4#tX^5m6LjZPb61LF2?qBy?B_?1YE!nej)R5c8qG`2s_uF`Cu+ z`X_$#2Ur#!Pw0WVd60fYG8A#y55LDyJ!Yt$5G6Efb<6Nr%-BTC_|llMB?%*A5%rOX z`fyBbD5g@4Ns^)P;F7zjv{t6u?k1J0kR*v#Dhair3iXjH^^qz=!xd`vm`W`oN-Wj_ zNML7~t!rRbc|9I0mUjpEgOJ9XGg2;vjDZ;b~V638P!uVuejytg~ci-I(n9#M6AR=mQG0YjoLKGPgFp(jS4Pn7UJR)Et z-8ZsqWsRLXri#f_BSeWIat3P+Q3Td1#ws={2CLGpDdvrgP#KD7 z&SnaR^#_Bsq;Xt;kyI^}iX~1WYzdHamc$tH1#Mz6f<2(WuH^s%^yXK78Gyg}{;LNA zoW%$)#R!a0wv&q%qj%+~i3^k&1jY!ljfi82Vr$~W5G6u&$Wp0VqR3*bDIWLE4Y64K ze08)CmeFrq2>QGFSDAk%Rhs}$r*rJVNuoO(~AJ!PG{T~d_i(dQ;OsQc+q&twwlJV|`Bv$N}R$K=uxCPyc!RBBXfRjRcZi5yAQk|YKj*>d`|Xw~ckP!!SW%^gsH z4oDR1AJt?S?}B;<&e0TPFsNAMQwxCt69o{uA>=K^qd1+MST3tptj8GHnN(upgb*ji zq`i%b+{{=o7ByB78@8!x_Gs&uqLOKv_6{gO2b4jbc8YT@EEzqBp!v_c?XXFx9Dq zb{!I|Nu<;4kZbyl3*LDg#$f7`nKwT9p9|2|t&fmAe64Of^c3TKI%Q?_^+uxaj|?xL zw5U4G#YlpQDngbfM)q85qt=DJt|y5nG){VqE;V8I&WBCAH+|pe@QT+};^BWB8(lGB zqe!DD7GqI`0pj%h;hm z;n?F&(5YS1X4{T?Hf24&;~ic?rDC*Zgk;*ga9b~Je`?R%gBQy3U5$!cEi-#s>T+d# zWH}Mbv|6p1R<`wiiPB32Gn*u}EQxC^LGJIR?H}~g*|#s5IQY`pJzcYP=0El5RWIen z8*k;5(^qldFJ}(enhxl1pnB_vPi5uu!@1|-9|Owd=%J>WPwQ>dkLW|!5WV<$<73Xb z{0CRJT1OpP567)vYea*J7*!3_M-nC`C)l*@dKzsw^5El5v)K$c-nf?sZ)?i>Gc=yt zg{xL=urnv{!j}h=hh{KFAjIS@=h9CPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L02dMf02dMgXP?qi00007bV*G`2ipt~ z7YY(F`_Sb8017EdL_t(o!?l=uuwPYm$3JVI^ZWho?|E--5|R`W6G$K=z*GYY6wr=V zEHLAs& zdz|M!d-acV?}e00xbt)P@m$z^s#fV*k#SgXB4;4pFT(w@xz)o_l~EwJ+$tL zNA}&l{N}CqzO8^B)M@;g^aHT<;0E84yNhu{N${eJ-?VeV-AUA6q$<9trt}a{U45TFsn9Sc6zfp($j8t2s@dE zQIjAUBn)CY?J)11fS?@`1`%Nx6NL#$Z0Usk7(Wr4STgIdiMw7!!ptNtBYrmL$nY(+rzsSZg&+Q(Pts z$DVsczi`HH^ri&>wJ9FAf9p&De1OdZH!;t<6V-n!4>5RGht>sq2l{?Fa6~?LaQm$9 z9qH`6yjb)4PhAIa?cbkttcHHF=ZgDOlWSCc`VaTB=hp)doVH}{g9J0z z{OG}rx?{_LG>2kT!Sf8oqKD@j#DD_oG}lq0#F53O8AgO^qo8w6oGP^*|D}1SXUk7K zb?V*KdY9iC3G_f;Tb_CB@TqH89N00=&{%tU%c0Z4WB~ApI*tQ-I@60@=bck#y}*T6 z_R1w!Pet&si6M<0X$&@1Z04|OhSLnh!5CX8&N-6E$;g1?;NIcJ!9M@ET6asjDj{j& zq&1Y$9Lh>#7>)s?>Lr;~P$jdD%&Hf*{8+t^cGKb)1Y-;$qr{4!>WIP!krE;qzA0ie zH@2QMam0}lG!0Rtu2d9Jhk!tC3eGyD1bu2t1_*& znD@VXDUHfZeztiTyAJ-0ENzq8EH4L{qM4F8hdRitic@fz!#TyN5{GdxF+&jQ7@$l6 zDL9*@Sw_A%6O4hL>RjG2?L1CC{!f_IyJ&pj%>v_aJj(1 zDV}G@zl}MeEcR)=MBzMj!s=}<^ zGdSzCOStu`m-76U#|fg&xSoPB<%f3P={hr%`p}{nf+USozR$hK7$G3*$9{2!b{no?XWStM8y#?82#n6GW?7)Zsa` zwL!I2XXA1vS#2G_6uFg)uUPcjE9|${UC9d@_w0xRuPYew-0*;GI=nx){rvMUu(54@ z+`1-W3}TdRyVvvF=0|BZ+svA_fYc`R9sDKlJoSV8^oiAcd+nE5_tZVqd%^b&f>BQz zGBTL-|M&8(H=O;xQ=e^A=e^iz^4+6@yKlSf%8Tv#hqkcmS4VRN-hS^#_`+wt2f#&F zoaoiN8`U^;=?_+H4ewj^5AQhK+SC`?KJ^PeVnke)?{!I}B<(sU&3He<>2?MWWu%2Z z{8ENr@N(U$qFI3=v-$PTS07#Z@0&k3QOG}i+j)HBi%%Z=`tcW^UCejx+4hFXpTF~> z6_NH`)m1V01y2Phns1H@BEv%=rBZ<`6)ly05y^ASTBkN~;?g=vr9P;=m7CX$|G)Zgm+aiXZ~uaNy+(I$oqD4|rBaJZ zrIPx7!4u>8HcdFJC#TdexmzBje$|6hQ{z`W;j zcxEL`omomE>(d+x8Qd8VhX=5+`P#GV58evMdoP*&lTI}9fl8%JsjEQ2FXPkIUzaTk zaNk#c^;wYqAW|>-DX%0C?1}#Zoic`Di%g1kcS7qn!=Ut&(rcy6c zEP5*Vl6GWL2O9olCKpP^6ib5fJT(SUCo~-tix$s^a?N*TuSl&?#P^M4X@Pb!L1}-x z&WA*#CC1=+BE_;txmKWDDTfD-_Gz_Ib&Z~KTI()QX%w`p;#2A}c%F3r-vD)*@$xL` zN{seU@}^QO)(>T_xfWpdaeovRE7^CZPMr}#|!d*|R6{H=+M{MV$Mp3LNPKT_t5 z(-+S5yz=?J*A+!U{KSTh8xFttSbqQdFU>bSjT8Q$)Ky#JnbOd}k;7ZR_W37=|NQzh jFn-Lp|K;W1YU6(Zg`N}+zmb=x00000NkvXXu0mjf_|!_9 literal 0 HcmV?d00001 diff --git a/android/res/drawable-mdpi/ic_launcher.png b/android/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..359047dfa4ed206e41e2354f9c6b307e713efe32 GIT binary patch literal 5237 zcmV-*6pHJKP)!xJWW@nmR0Ns^Wrk)72_X;&VM@qLNZyn;-h1m-)j4PH{!#b7fObo=TF+Xw z)_t{JRqgNW{e9m)=MZ*rJl6A%IHK!gcqM)U)>TjF8ytMTRLpN39jns9J?@oOe47l4 z1dw7d06;*nuu_+V$6Qs4K>#PCRHVFExV^duw#+4>?(j) z*AHP%*L5@qEpM#j?*@5nOq@HlBR^5M@^_J9)U!&MV7N?QAAfFbdJaGWPgRws)6~+R z-NrZmx0V*7Od$!{dkY1w*wll3j_1b``)C%NHS6N>yBU998+?y%)4SU2YA} zA%$NKSGVi)4!sVH=l1lla~XcBLKrfnO2~CXCa>$GlX_p?dYsM`3%)hidhs()bzlDL zr7zEG>kK#SwpW`1YyR;!pa1&-`0t?)V)3FnK7V~pCo%hYIQUj+f?7Oh#@-(|a?XKA zr;?n->{Mx?{fOYn3n4;UD5a5kBx9Z>DQ1SETOzUjjZ`HF0&e`i-6T<17qM|ec7?fBc z;0k&%hz+o?+KMG>1)PSqUSqTR@!luCa_YiGo3TkPUp^w8T}r$YFf$gPyy|ZYU`={9 z3c4MNG|FgE6ETxVuw_~St-lefEMgF+NTdzZD8wWJ0s<69@frs3IxH*_A4`(dIZhJT z)TwApTxD36oOSS>-?;UKV^n{)k!mFpfWRL3*Rxl@V_bS?f`4@I!*C2lX%(H}L=`CT z0BxGtLQ@`yX#0U)3`bO@9NHBjM^*Gw64K=(1QdKEK*p+u<&qTSoUzKhfO`4Wz>@z)uK^Aw6m!k{QPq@f~bd?t)6?} z1bJ=k7!E&fDxUmP-(QVQ?F@i8a-dv4%Gg64haX`yNv^E%Ea<=YJ4SdqH4e{1~Sk?qbu|M;*f zbqpYh(szvQ9ev=Amrj8q0@9+|SbxTQw)=Lr&Hm@e_hY2mXXchai5dBmusvCYf%>!X zK>#8PKtTjx&+y*EIR|SkT*`=|2>VPq0kb=fM~F#u|GG<9sj?zc-#-8BqmC*-%N5t% z3v1um65bJjO9}`JV*qzjs9O-*vCma1qq%z0=Thg*sPtm8u4CiyU5H^JCTU0mH2?_M zGn{jci{Y)p`kvomV&MR6*th{{opqpyh3Ux4m)!GykUSWKMk@t>>SyNTwj2L%XZ{Nn z>Xv_j0zm+HA-wSFCJ4n;tqux{Z<*M!+ghP`mh}};q{({$d;y{&M#518E{~{H2e(KJ+~I! z(QA0${wLzt8F#!r1DoX%bYVIIT!6Y1 zJctN_2;>9AahjEz5Cm@p&;a2*ykj`$0UrSH$QJ^n3By@S!UCJh5jS2|HIuruyXF34 zRDv0v?9yEOYVFWR0jftU~yzAQIFKu_~N!vxLSpD zIxEmBpAwnRC3gEyg%Yon(xeEA2t*11fhfB~8i^HvMIcQOp5dF9V>l7DZ+tS31TC`?6B2!P-{Ai`NS%8sfWFCh_# z2!sJ<26G0;dxnUBNT3Wrj-j+52u(2zc*4ieoxAxfi_hFMD8$Dt*t4hHU+Z6a>y4`) z-dgRJ&wT2GICjQeJ24|X4P=?_kA+q7QY|L{F) z>E#!CslTU!sFuPzhBSJAZ4?NAGFdr600O~tQ;`JDd9Vkv#1X>KptUV8Q)hHgp)4=n zf7k1aF8a|v_e`5zKCDz~Nuz3ARYohScS~Kpws!0=fL0XBO0`T-YycqYn}yY@ZV?g2 zlnDnM86|@t(hM=mC6W&G)j}8N_Fwtr#>s`2R4qD9xuZ_o&BU=o5&`up5LX5DnnxN7 z(!|510_PdtJ9u$`Fq8(A0!#>KLogu_1c1^6@0sdRitRngzWe^er2PiAMIqpkE7Xj4 zqSD0i@PNn2cHaUJ;)tnGEM^?Y2OX%5fOPNhi#0IY;la!zy_Gm@B#Lw#(Mo_^%= znu44{7-|HeMy{k$Y%?&%Kq&>KG_*4CK85oRio&-@sE4y2Y3h;2*%j9ragC&24JaC` z`!uzlS%RjYWaMg=C2{s!Ax`QU03w3c0Yn(2{;azYNJdU3mn!CrxI&4*JCC^T#}y}2 zA`QzFa=EsmQ0RGvftbU zQ>{c90A|-98)Xj4nT0b0yyJf8t%xIraRd)QQ&z*I6o?d@PmrXe$eT_q-0f@}wCCAq zEl$Ss8*j&&jkjWZGSHg|Kx;aNPWFa9~0$jGSbWOU>XjH6xDc0w(iTEtcE6dO3#5TC{ScvW=I(b=Nv*)M5VtC-7j0@OiMO};u|K_aA+ua&Wy|G z0O?p6>sL7#>4bE^@$`cedW&;pHYGbq)cE=gVUygN~?!_hF|0teV`9}~ml+s!M!x_o7(s*;* zCVc-VU&If8em*{M)JJgGyiZ}QGSUDFC<*}~u!v@1)yzPXBMKoDa!^zNBmjHLN~pCo z86Fi-BjwE?n=_NmIA?K7liV3M;v_;xTNl23?ow=ga}EA*-%{NFA9)Ej6(HYiJs85m`CL9ANNz_7Wfw>}W{H&o zhy)^>0cdZXg2B-WvL1};5P}FJQvqpeDFK{}*W_F4Q?l}yJ$-+C<-Fxs|HfnZ?SC!9 z1CQT|j+S@fx%Cg={YRgO&z2Z>i~diz*O?*BnAkIbU{QcAP}Z33z=$xNR5+KgfMs35xDG&i*Vb0Kg44zZ^zZ& zc>uXE4-p1))`B-&1MC}R(r5-n0MAaC)!S!3D{E#4D+*c5&ME_7bO-`vnhuJ0%rG^y z*MSI{U{o_J!WqGvFVAW?BdzlmMhBQRZ2?B+Z$U21!?_gN1W=^F4PGQ^jHW1{`Cb9o zLx~8DXBkZ|AhymqMH-oHxQxU~>&7f9WD8o#QYOvxW(yKUdVH3~XXbxdwyFjxt+lAv zZaWSag=@ z=8P$&K}1lbY?iX@ee4?s0wKUBJ964=H$0STaA3T?n~R$9CTTo$W*+}*eEXdRL>ghx z0ulvhz0Z>9A)>e;5?WE{3wn~(Mxl@k5Z8vY60)g)Z7AM`NMj7L0~nqG?*MV$0cj#* zg?t%+Zb&IZs~iSLH{&P2T8vGbH$W*3fW~XQxiirODk4xy!&-;m-f<)T^zbbx6J$2bI!+g&Q(Tb>mTpfw(MhPbbX*24YD+xC~pjzlg4B?I0>ZG1eo;$GZ-@3q)Ayc(TT%9uB8CcO9K>t$rJ4+!Ga!{2blb3*{mJ?rAx;e_@g zW=}sb8SURhsg02gkr06Qo;))H{@ois2J0*E-a_ku;$#FwS}J2z^z{y5!Tf{u-m?$! zW7XmPw~xK}Y|U*DV-zVxM2Z?xn6(ROnxdy?JIXW%Qzy=WHv^~-wPRiPJ(xPPjP?m_ zU@!3AH)Mt2y@NuFGk%)cvT4gxH~;vV!~gKarE2vv&(f8P@Ag++xft8kE4o&xvN3^V zhgKTPzIFc&iMV*lvDmVC6ReMr3kzh>qKs;xT2uwI^KCQwiCuxGcI>;nX1mYH6|D_I zV?e$kJ`M5;L7M=zY84}cF$$#|Dx-Bwp4xT+U;&*D<@0j8tMo%x5%Tg?~5R?T=3cv%@lt|5rbf!U~$$KWHR3?Xk zu&I|c5%P}XIIb@4XrJ=aC`y!W*}^Y88R7A}hVa+MJ05U+?`P+M8rvjM6j3edroqA2 zxm4Kuj7oLnm$`fxbar$}K3^bGfWT*$Wd5R*hEfJ52%w-LATTp*YNZ}ksTNg7J=bnd z-Pkqa!RO=D(kYB&|Wjqg0rvF8kum{NfucTYqrP z`5U%u**G!G6{S=zQMp`3K3_yWUyzoz^2Q(tmC>3+s5Oq`4(BY=)S@2MFgiNo;u?&k zg`0}`37-~9P0%vHiA@+H2!cEy8o#>wuOImB)G_Pj7yce!TXGVt#ORn z(=jFB*q2Zp6$}lGp?}+$um^#4QjKaSEI75c$z6AAYL348>#uKEccl>fFbuUZ0R$d} zZ~}6sT!$|qC`YPurgrtQ76=RC$YS~T-}$t1r_YJ6x+vSq`|xwOl@gGLU>BhcFBv~FMie-ahi$Rz-LINpu0Hu~Za`}LYEdk2y0hQVU6k7}mB|~9e!x(}I6ii4k;VvE0 z?|KG+Oj%0Bi3m(dlp;$c5Cu`1CM@ypLV(%bX9 zr_WVSKiJ10x1!vdPr`gLXF?@f1r%~#N8UkH?XgO1p%e>?-DLnfb z=86?7j~f~sKElT8lSw^&-{|PJ_Z)D@o-cw6^yvN1aY@hS38meM!r|M7s_XW%93Aak za$IUh=gpcu=jzR`4$^18^F8_11#h4-#Jd^}{s&{CB`(>qac=+s03~!qSaf7zbY(hY za%Ew3WdJfTF)=MLIW00WR4_R@Gcr0eGA%GSIxsM(l48sN001R)MObuXVRU6WZEs|0 vW_bWIFflPLFgYzTHdHV-Ix;spGd3+SH##sdcWUue00000NkvXXu0mjfB?gph literal 0 HcmV?d00001 diff --git a/android/res/drawable-xhdpi/ic_launcher.png b/android/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..71c6d760f05183ef8a47c614d8d13380c8528499 GIT binary patch literal 14383 zcmV+~IMBz5P)>IR{Zx9EA~4K?jU8DyU!%BVu|c#=(H1 zIAFva(2=Yn8AKWhO=@Vm>As!A%_mpwu-+fLs?Ir051^0kZ=Q9(`cB=t=bYMm<@H-@ z?@QQC#}7(lHuiOKOg-hI-&yJQ@X z>38Dx`mgcs{{O@!m2+^EdNUPDF+a6!8!8*d@!BI^jeED=gH;btqEI5d{e*jVDP7bq z{q~MSBE(fsoQg6}7k95+Ji!s3$poDp-qlOkXAwnM{3JB1P1P!!MLkm@C24>Si7~v(J@mNzG-t<6(_#~IP~Z}QN`;~#%u^^ zBv=E1KsZ>EXwWhEA%MjWSj+&p1YiKMScFGKjPH_0g9QS9!hVpahud$BNHq6km8f&$y)VmTQ`qJPd+?0zVd*nDN_N;fDC>PCKgkkd- zF&a`~zS4LCy*S)Om}M0r157c%Vz&|}g=6?|;XWKwAQT*MxQ#H?lrYWC!I5q;pTUZZ zoF|S^mMxt;_qPCIXf(txX5a0Ww;uk~=vd{jwJXPI%UbvK`FqRT9{O`bUiO)BJM_2% z(XOY!tbcIB+EHv;)4J*BV9|&y5&#Sa0{{$SB&foHK?p!lAcP=9mJn^Q zEdF4f`u+CiwmYVjr%WuN^Du#n`yU&B^3IJzBL_Zu-$?zTyBfz|`{R*^-t)z|a`kd+ z3q1~f(k6y5Nm3x1Yb_kKdg+KYV*sjIe!V z{5>Bz^<6`n@li*u;}T2+4lyJ`2oxNk906cBFdVfoiU|zCpa} z1i&zeF@X)3#Clk0*p&E|Ev$2}*1}l_W2{Z$7(q~!&ar*`feE?ciQuhsm(q`Gl}fN+ z@eJbtu1z-J9Kjlg^G?2Vm(yjpIN`_LzXAXv^r3($xF(p5y?b9P1*F-Cr~YXsj=g)| zS$n>$x7f>y=ZgXCM@>wqVLVI>hXL%1sn{O{%!kA@0KEW80E%#MFwm*p_a{B zD)9ll)VtgP1B?cSF@g0+Q1@mB1{Ma^85pZ!tc5iO#u!-ZV6}xY4oPBJCzg_?K&wta zn%L5Rj?vAeG*Bm!j&+Mc0?>)WhhMvFm(gdJCt~yENoevA*5h{EDh@*#(_{(r%m&=? zu|e$lr34M$iU-{w?Joo(Y{qhgD4~QIkSM}}!O$?MLZbI-s18e=OF&ai&7-M0rh0zYyI+(=47^@pK8?@?t)yRhO zzs%pSswcJ+l9+kcqH%0n*9V;dpM3NE&pVBFsSjxAt=MWGLVz-sxL2ty_6bwL*y%l( z^9>+yo3UI7lth3j7{MAa0$2!WSj1?ejxkiQ4K<7-K?@ef2cKYAaNFUg(T{h&499@8 zfO7ildBY909A~mi5d(n62vetXrh7` z4HzV;U3Zyv?>JqX@EIcrL17PGz;pl_gtaW`qV2(}?K z7!zhaTCssiN~pzE)ZG|bt^v&&Iw!VCuMKp5YG@e$;~cE9-qBhIYucx?3~Lx{30fye zS{fl{!|4FcxRUz?fTWbfM0}x+#ep9=eVP@JqE)w;wWx(pTzXQP1!_hCDgS-E@^?9S!F42HJ_S_#uc_5Su zs5YV8=8;EdD(d~XBf)i7k@eOjOu}f!6L8G}mPQ{ykK7Z1=*K{C7^dQQG~*hqW*BXt zwShMNOtkjDYl9@w(22=Uqtnw^7;U{qm`pPmt+!FL;E8XQ{Y&G*#ZExj-eADv1EkRiA9p=HbW9mXn&pE zx6s<=(T*{$-anb}*Q^f2@NW}!Ypi#4-44eZ5;wFGR z2l-#ffa_PC34p;4_~V9Ch1H=Mop@k2T=ZsZ95ER2~w$V2Qwf@K~R83 zvJIQ6w*fXxCEOy(CETXcuAvj1GDN3@H|;ZhZ>JU*V<1q%=E-}pVf-!#5kQI%P6I0* zTLpFk*7~tCJ3&MYqC=<6ZM^c6Z@7>dv20Zp<}9uM?_~fH0U)$$1VND)+d76o^q=A^ zEr^rEHJg*7*_`x*)CPi!7_L8n$2VUEYYnzlmg6rQKZCm73TFhg)~N(r7^9)J_GT#Y z=E!J+L>qrUGe4>H>r4xD=7=p^O5i)6{5&4r@Eg=yoNE;R%JeoxjiXN3-XX0XM8Z3x+2kseod+K#}a>@yV^%M}^*#iQp1F zAst%zV+r1|H5(QIra@x@LRv&YFN9=BDFGr7sAH&E#DX-22b|;do=c^e;n;zlgR|aA zyY$*QZ{k|5CRq1iVqyY?LIkChclb`g8G$6Wu3oE&%0x0;uh6maSl?4UGb=(U=b9CT zAAD)W^Fp)dRRgSbAYouM5g5E}`|w<2-3dk;YPD)2(M=f5sbl0cDunQcOk3Ku&N5x^1FSJ=M3mZon=-*VILENo0tgU=eUPES)PX*zAoL7o z=^+bdICcU=mYo}9XOEjc^IkZoMNjft0EE-uvH$-*2E<7n^$EZlD+Y?kfE~ZUXxp14 zEf*&Z@EgTT(Y7k=$iK(SA|BR=ybI5Z(;@VwCMZ!$sa_=8wT7h@fN5QG4U zvlvfCab)odtTZ3MLn~IoCYzzuBK6l5SDPdEd-X-eRX!@EFbu5#2NG>lLPR;HL-}yh z`_wi&MC5}HqLgS1BLC{41#goav%lv!HA~s6mwsoR&nay7yEk7xf5)QejjzT(&AaOVO#?>xa{z!6%4qPn@N-<8|7}ThG@fYqze_s}1$89iq|O`10Jds> zYaEiem4=mV>361M;_0g=f=i>8)OmJ>lG;J1CPwF4k%DWP#OL>1TN^ShV9rgEXOi~~ zo@v>AmuiBAwT9R;XvwTawOIhrs)H{7(gpbBM@FC!BA{L{Kms92D$+oBAOK+VhGBg7 zc3)5U{+-ADeGFL39|7~7nBW-O`9f^QpHak8ybYhG0{W>$Q)!!B3u9_nx2~CC?^LgC zw{LpU1qHTp&{+jz9CbniodoVWt?PyotcB^iXFaoWV!JN0<83{suyab>OdC2+=C-z^ z*N%~DOvW?==a`rY)^SNHJ^KfD&w!Ai3aa?hC9_FWO<7cBACBb`&gR+lG2YO;P7w)N z$40Dvd?O~u8W0k=P_IuBrh5qCR6NJtRo;Uu{YcZwM}hWjy#XVYoCUvLpd zn?q7ah~9Dw)-ffue$<-Vr!$MGYy)F7V6=nL-sT&_xx^dO37}>6x)aZ_usS8a%cMPf zzwKh0F>OY;)b6|VyE8_(G-_&JBaQvN3G>W?H+4=hAT(PCWA*%fj=K_LBQ@Gqt;@M| z0ZT|@FlvE~(|`wNGT+_rM8!xctgZCX?71^U5PB0x1YCU0kH~j9c;9A zYgg6?07kd90N`nW-cG@|S^K;O3l@!{FPe@H@;ShX>*$mw_$j6^H?+9E=;4JzVe!A@_?7{ll9hUq1mbgaVweTVAJ>>5RxDy zfyg`1+@W^8a!MHF63fmz-L`Zicf>A}NqK&zoP2oG6*0z51&Nt7Xq#*6oY5hmlvF>Uo>Ti(<_Xtp)F~;ksPsCeiHJgq7 zn$5=R4m)V>q0WihPCt1@ef7GAsEk=IlmzNki#xB|p40kiCCT4D^jduClFfL-Sv@e^ zq6;hk={{Bbz?2dOzty0|8!a3{^g%#iL_dXUZG5(F%43_g;A~0i{de7X?|+~1_Lqu} z|7ndFoN~|&f4=+SEz(T;R$MDCC9*6F4U%CCGKx{`Arwmi!h%2$3aF4ga|D3|00Km= zqm;J_I=921Ib{Opzk;3UNYv8Prgq*kOu|TFhq%dTH7uHSz{U}59Kkd~#0`PT>R4;r z*3qB6=(O->fBDloG%$^<-m+w9!-M}_oKl}V(7!?8r*DX#7%u# zqiRa;J8#t~r@W!xW`h%=JMerO17z636 z>Mb-fJc&3q&`AQ4jHsXxMuey+Q78!%N`#<5P)Z>xNCcroSP&p$2q6&!5-MaMt^Vc| zPeWE~7&-y0wP4542_uOu;-<%xlGq|?IJ|60S##{G0sLlSv?cqe2e#FWpP2z*0cQeKM=O$hoZYsudfZqvbY?RiHsquN31R{S z0>CNg*igOhM72^+CdV655EMRErtjZ%@l}86Iq1lP-m}kvi!p0H>ql3u3HDgW*t#yn z)(sXTTY<6dEliBY7#@kytXt?9ND{yq_^zwxbnKYQFtUpAP7eV{38;XeLZDCx5EUhQ z`T~@D6^gwAJ^dOzQ=dY)M{-|ZKNTkJ85`G@zCy6ewr-p}R9j}CAtu5EK^OvzHZ~P& zv|0v9lWAf^^R`XRg8}?z+r}m>+`HE&c+bRu=EMLn8`!d8f@lwkiS6ouM!Z2XVnZZ} zg!InY5u5{zwn$nAjYgtc4ab!+w-}&k-kf6x*RNUKSE+8n)c*Nu!QvU%V{eOMG!^U^ z^=1XFra|0vXw`w*q(;4(pjowO)HLd~1dUpPxMh*F99k`pjQY$u%^949O_Q+9JP83v zMUYBBDFGFD^A;5(!h-Z#6%nF>M4==R6@+I-Kv03VcSd^?Rj)d7Y^-%mlES^`(fP~X z`^AHcjk>1VWK1eFkTUTo1_RDGXzjddYd9n=qGp}>?Ju|ouQ_`GKKQD?;zM6O@R=Fl zbO;b5X+)SoAHa`qeOsYf6CCRVQYe6QZgVrcYP3V#vZz-yRmNighLdVfZ>5UU7AU}H@0rcd5CEg?Gc!Pt!ZA}W!(}(TI#qBn!3=VaL7hz@xpV7?oe3bJ zdJa5tR(}-sRpORy7`8oOBALjM3)zi_o|!!u`^Dj6v?Eq9p-V)oXiw-F^3s( zGX_Y(8W2ebDg9`PDDC6-s_6;lnFH5NW$#Km9BhYhfe8eO#59oT7@;ad$pDTmIw`?u z19cu|KzBaC$g^SR+Cs(-IW&>YlaNb@;PybeXpvLjKQB`Nk&PJuv}<(Jc}K$MQ>Gn| z$j(4JpIye)lw2u7sf`AlXgf>mCCs`G>9a1yW_B=TopzMlh^Axq!)1v$X<=+~8x#*> z-jo->B!r2|b{Jy-R_(+sBeLrzen!~LbaDsrokMPDIlX2NOL%&ue{6q$N8;E;CZA#w zaXtGW05mJzGXFnoKn@VMO;}oV$|Z`snBY<(k#9wosn*!G84wn5zQ5Mn^z?hY4@jTm z+FIb!=Tn-Mwc{J2UW1DA?tu3mx$H*`L^tI?Z91X>{FLJiu_yR&#Cwa5{Qs25|buw&r+a zojE^m|EX=`vJ8(D3BP!vJblLWa-a&W_FxFPjn3@1OY0pXv$fncA!a}d1?L=MU4hmH z1LeJN+<~vh{tHh=Pia~%2s5VciBpgLERGs~6PB<3Z#=sGT1+;!BMM6hgJMd2(`B1G zCAU+_^WY|py4pS^P4t{`%*u!2sbEo;eeC!O-<3yz@6H1}2KFo(&|%a3@0C;vsQnCX zzb};*4=WJ>mMS1Aq-4&K#Y{ajtx0_W5yE!VDZ{PF;$ZANesHv+rAR|EeqT*t+X5T3LfYMTmlO%4pjaGG=pN&O+S| zMsyICJZwfp6nV*ZkR4H2Zk*HWP9M^FIM;pe=}?3SQi=9Bog~@tlSH0yWISNUd4!S) z2{Tyhn4Pu649X_!Z6KweNkh-{b0j3?N1!?Da?|o37v?^|T#kh>!=~ zUj1WZoFtOH{yC1AWgdBTa-i*yI|7N!S>st4(B@EHIuvcKXb&N-H!g^JRGvOpLO^F|o(F{~cf1z(-Y(%2 zIFgPtZS5lWj)P}*sTax1NZK z6_m6>1a0l;kd}PHOh`-<{iOw1IQT+b^!>Ns%y%A!>;Lc@z)46U(~gGc42^aj)>#k{ zq*SO^8~DLbzkyTE+zXfe_>0(Q?kSKc!dQdOfFf;8L=g0#RG6NVh#>LU(5>X0>7I92 zMvR=HnWJ{8>B(MgHx#t9k|bmL)J0xB0T3t#$Z?KMba1{SBkYj6Ac$1ZzS*5McNWBv zI^7xl2jC4SeG?a5a4qI7nTpSU`*k?yBQM2Wci-$WAt6#mSUlU20dUL=DJ1Ik27YtZ z6?oHm$KaAHK7gZ+J_J50^Tlr|C9HAy{Y_Wm zSJz&Qr#9b%Lk>I!A9>$ZIPS1hA%wtWWgPXYfeYFhaCd@5I}DR}-Npw)A_}u`)@SBf zCeUFOoC6R*$*?2(Nyp3G<9-?g-uR-+ap6y2;E_lGBs!em4){nH@zV)p4N&L`gR?9& zjhHe%r0_yBo&*3`XAr0eFFxu`IO@QE#!bt9u>+An5<56z-;4V+ z3C)tn6uTmcdOXoX5arHbvK_{DV2IPJub;JAZdhnw&H4z9oLyZGouSK;XW z-+;HA@nI}kvZw#7wZ4fLz+aZ#fh&IXpLlfbAF#(>3-G~rei<)1;*A*SpOrI>h;pE@ zv$&r})|o>S?SV3bo#j|c(FO&&61G&xkY&~kcs+I6#Ib+2;SSn7GXwg2r)496ps>M= zI)J{6xw$lVG9pt{-(^4mEC8FosUyiD+3mnOQBNO9wHYxubs^4t`4@4*p>M)X_kIW0 z-E;-s@$sMIWk;WbH=KSh7A{w#>;o zN+}=20uVx2fUFPAkcVM;5u`%}DXmsXNdiCuxOz6X9A4QWjN3`Jz5^qCb~|^*zIf{^ zFUE<7zZKWtekrcH;hVT^*_Bv4=TQ9h;Tth9vw#nr_bI&mgnz}%X^XogUW)&DJ$jCa zb_hSa)S|$*!XWiIl;xzkx8|JaT|&mlg{a+%p9M9~;sg94+Tj$7E=07WD$^DFrbJ@^ zLQ$!dt3y|I$UePy+>!P0(_-UpMx@zo%7}%t55c)-eiyGe;a&LNl^?^hzg~;ePk$rM zKI@AZoH{QhssWMABf0`z++;^%uafT zm}kV@W7=tFoDd?X4~aCx$`Gbbsofz=aE_UX5EY^V5rI2805Ubrq^%3YdJcIOrP;7! z3u85w%sm`0I^th2cX0`?dBr&xoH`H2Bw%(BLOm_xeERpbr8PgSc0 zr0O1Mra4`5n1OlOrSlwXW4=3LzdM_x5RhpK9)&%1BGf4j>pN?qS?2+zgUudntxx-; z2)ca*x79vpBA$~1>~JuMgl~&63@NEyxqA+u1%Otofkva|%@lX~HqL!nXVFPW!Oo>E z8qYB9_MAM(Xmr*vmc4e9e5VZPTpWQk3T~I&IOlYyA8l6$JpKQBskgK1zm0pelY8Fa2xLiE_7`ioC6%Bo zLCq`xfE~cb6q;iJfOQh3~E(;W$QhLqV%s3Q#Pd=|I0WrxYP z{m9>^18IQ$_kEnuZjVWCWOEWE(V?pVV488gW)ddnI+4hoJf5?%E5TXT8qyPXR6fXP4Cm>~aQT~4j z8T^cv|JtYelpFKR-nQA^q8;*?1Gx4Y8y>s7AOR5*)4CvSmvGFs)m^mjC_2 z(^0QKOGy#{nstk!801$Rf4EeYqKzB0-dRD;S!bQi2;DJ5z%e_c8F7>AI;QmiP>6aM zP{Dw2}f>-}+^|?~^CtC%^tW>h&t5^x5olDZ)IH8OjJRrNZ`+E%^H7pTOB4 zd>L-N`!^^Si@t^+(BX_TEXQM8k?IE=u~JgC^q7X}`E;Wy!Dc{(G*b)iw{X1QFST{U2Bp$xAj>lInhY-&J4ZZj7hcNxrSt!yX_njL)g!;Jp z>g0s@X9!sigGg)J63+QGw8juyExB0>s5)t7qvpPS)G;$3zWJ(ED3zw#vY7_s>hL=q zrZ@@OOS8egIcv$%`Pj5>3_rg56ZqrpKfxLQ{9e5L#s7k0v6xoT9Au8|WKMYJqMt1{ zl~O`Vh0(F?xcc`$!f&ttE+*@nF=N&M=Jw7(5F$lqvj*f8OUN-Sh7vun7E~w%4Anr= zto=$BsaTuTUo3}n=9Ef)Pq`#XP}3FY=A^WVS=WpwKODw;-F)t+PY{>?$6a=^au67d zD0&VWaLq68#@+YbjHm~0*#mbHK=(E)!CB+m-L~3jIdJv)GM*R|wb6c2AMKOX;j*et zkZ4rRw>Phz_>>b<6#yuyxWBvrf&yf%dU@1}4!a3PSYXUuI2DH;y#%U%8!r3R`|!R` zy#jx_?YACb71F~U&UK0W4l!1WfcmOfv(>=QfBS8md;ZDz@$Wu|zCn!x4q1qqb9+$g zZ!gH$5tO1GmOruMdZXE>UGVV_!3igw!xi=B@QK4?YtEmn4FA5>sy(W8^ATfOH&|Ey z=t%v+7dk_~?U`8<{pFbs0M32Wr6?9kxb5l<&#nRQIsbJ0||h!8Pz&|T}y%N2P2E8mafjyef|-+GMNnIb?L7UiI1 zfFy}=Q$4R`fm%d zeLdXL!=wW9DnY&f`RQ}6x@e!*Lrw1o?)omw`!76^ozqYe$-Va8!*1HR38%h&0bY3Q z3wNrmJJoNat{I(=7_D2kO@LaNTG1co!8*pkG&FK`~JDG;YJ*A=mN}`-3J*m zWI%rTQa}g-0j2!91V(2Ucsn`+$aisrw<2F zz(N2Z3n47#FPee<4w;4Z{yQXJ7XL(^U#w+TVe)CAma7wwnA&` zNEq|A-|fw(op>-#J7IrRDn~F0ZP*45>`>~nSTg+}%$dFiuDo<;r*wYCH0J#OJQcSt zy8(MI+7HD-8A53M*B9=`8RyO=Ye51bw22vE%&s;S);TO$v?mtru~68!=z`E3;AH*& zYP?n%H!6h827}nA{zB3uKmd>TzJ`AaMa-k;?_UkDrOJvbK_zCGqG zS_LkU%CBS;J1kY&ktmtD%F}%AScAn1!`rH8H4Wx0=*Pr(4Xvs`-_#<6wCM`TZ0%Xc zGcvoL<}P`1$bR{h)*8e`L~=G@3Z`1Es%^t-Rwx;~xY`;XE(e1!PIGm#g`0n~>A8^Z zS&zRHO5FLeeB0%??zeX$Dg6~Lp5Mj_)1LKZ3X`Rw+)CR1vh9DUz34tQm3ct0m>)7j`{o*_J`~IhWHtD(n@@Liu zIJfs&uKV^1Yquf(mfpYqG4sR>4^bYXo%SD_(3%E{zF1W8SQ#SnDmYJ(pMhr_w6?cnyrMj9+v}s zdu(OaS81acCULxf94EpU$AU`~1yd2KUJyrMr@*WL4&ZD`C|1a`X_f#Kh!uzeND4s| zK!^~6B1joRsRATLkTQax2!sL%5r`rXhX99Qr{J7|(*o8guu~3BS#4X=*qQ+8$AU0? z%kc2J-wEmyM;vj2tJfdHjVmfR<&b~DPcOaYd866$zIE{}*FTIGzIX zSQwP#o{JW_&%XCsocNlB*mrOaEXMKhJS=J!VWPSbjxDB7St7QL zuB38tx;^Q*vuECT>rYp09eupF+#7IM2&owLAPW0Y2>PH@(RW6BY|`UFWWjJCB1Z&H zyY$mMK&0y#gdk*#yJbgdwG)G~a8AS67>TZPyTsKTCFNtdIGT-hjvvsZUMqUN&zJUgsK2R0ZCC1 zp(;?IN))ORML~%IRiHvtLaA6rp-@B=MF^t+Dj*2u;JAf2nMAcViqX-n*tBs2#Cmj8MC|07kNe(W+0 z$d2>B{7TH3GaqB46PPl!k3R6`%lVJXzB~Q)yRLm=<*NIqwHlV2bwf$)7i*C4n`{J; zL=Z`Yp@32fg<=s>f%~VH?+-#XDM(EbLKcM}_Bn-O9lIrsMy+IxL!y&>3*#g+3ui(IzkR{wpI^Sq=(EfJ zhs>8gdL6#`%d_!+-uDZ9``70J0KzDAK_s|XR#1u%MgltBpTQ)))uh#MXjVDhhMo}x z7Ol8pbwj>u`8}KOKmH7arD@<0ply@je?RlTrd)mfFK>SA$p;T4NGAjdAMPrTiYf^y zebf|20x}?k5s_d{65FZ|&KR&O?p=+s%~NpjOCnS^7ZAtIT}pglH~kwcsnS&bTbS2@EKBEdP1Bn0PBgumxA@4T2xe)}9)BAIuB z`>yAoU4F-Iqsea3fD8i2@b^|SPErX{fj|_c8z~hf3h7zuktp^kL`5&LA_dWe^hEsn z$Nmbf8IB9+EzII`PP&GcF4?yZLL&v*Sf&}V3R3hl5(o|k;nk!v?nz)7gBm@m5MkF0!SIyT4SR6 z+ViGBn--t;wncE%0#EU+9-Y~5?gPSQ2=9tbG}TKf6@A2H8% z>^2`zES69#^kHb|N%;0vvVw?h+QdlA;B5aOmu_urvpO*#IYJ;E*ITP%1OTH9KtU?v z*PgPEWOhzU)d~W|5RQXTLInaUkRG&{{iLudV|?5HV-I`rAPkF$qB07F9z=z*D@46$ z#^V&*;ct_`q_IY9cqHcj8M~GKyEhZ=Db7bweU05~;Tkbz8g3t6MgPu>i~DmseyDp`}_M6@#}p zXMfV)Gjmp{)C=okM?$bv3W5}@WzneDMI{*#QpBGh-n{vHhaI+`KtbF6j_*gSx_c9W z-KGIj5=JH-!%=)57S4Ey+p=XuY#)2#8;yGF)x*PEme(qpgc(o)&r$);PznPIt{}8d zwiw%Ze^OlW?nYeT-o65yW$q~~M%-$`I*lZ0V%4fgU92aBl;S24Brj?tTYeNL6SXib zik{Md>?ux@g|Jr=gt4x5j}xuaO{4tjB}?}cebXhMwDcWVH#C7;ezj${GGLd((VfRt zk9-#Q-SPlV*!Ln_bI+U5)Z1lTW81Xb3Xz(2VlkR}Tp{XTq+}==Zd0OL_f1xZZYqaM z$80m8n72X(f|FK)sZ-~pS{cEdh5fK@9HXNXsMa@O!Mwwz3}Rcbi!oxB&F?QSIIdWj zx>(6VaVGmk*5<(bg6N3tnEv$EiVjmlm zKuU#5Wh;L1&Bp-%AN|S+IN+dtu>8SW;MiEQQXoi>G#VR3kNlOA0hCa%=}ubL{Rw#g z8>O^z*aor(V1b*ij4|}&n%zkb0KoqRbb1&ct<2Ko0000bbVXQnWMOn=I%9HWVRU5x zGB7bQEigGPGBQ*!IXW{kIx{jYFgH3dFsPDZ%m4rYC3HntbYx+4WjbwdWNBu305UK! pF)c7TEipD!FgH3fH###mEigAaFfey&@l*f+002ovPDHLkV1iQC3p)S+ literal 0 HcmV?d00001 diff --git a/android/res/layout/main.xml b/android/res/layout/main.xml new file mode 100644 index 0000000000..bc12cd8231 --- /dev/null +++ b/android/res/layout/main.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml new file mode 100644 index 0000000000..6a272c9cf2 --- /dev/null +++ b/android/res/values/strings.xml @@ -0,0 +1,7 @@ + + + + Hello World! + libnative + + \ No newline at end of file diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java new file mode 100644 index 0000000000..701a73e2d2 --- /dev/null +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -0,0 +1,449 @@ +package com.turboviking.libnative; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.UUID; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.app.Activity; +import android.app.ActivityManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.ConfigurationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Configuration; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.media.AudioFormat; +import android.media.AudioManager; +import android.media.AudioTrack; +import android.net.Uri; +import android.opengl.GLSurfaceView; +import android.os.Bundle; +import android.os.Environment; +import android.util.Log; +import android.view.Display; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.Window; +import android.view.WindowManager; +import android.widget.Toast; + +class NativeRenderer implements GLSurfaceView.Renderer { + private static String TAG = "RollerballRenderer"; + NativeActivity mActivity; + + NativeRenderer(NativeActivity act) { + mActivity = act; + } + + @Override + public void onSurfaceCreated(GL10 unused, EGLConfig config) { + Log.i(TAG, "onSurfaceCreated"); + displayInit(); + } + + @Override + public void onDrawFrame(GL10 unused /*use GLES20*/) { + displayRender(); + } + + @Override + public void onSurfaceChanged(GL10 unused, int width, int height) { + Log.i(TAG, "onSurfaceChanged"); + displayResize(width, height); + } + + + // NATIVE METHODS + + public native void displayInit(); + // Note: This also means "device lost" and you should reload + // all buffered objects. + public native void displayResize(int w, int h); + public native void displayRender(); + + // called by the C++ code through JNI. Dispatch anything we can't directly handle + // on the gfx thread to the UI thread. + public void postCommand(String command, String parameter) { + final String cmd = command; + final String param = parameter; + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + NativeRenderer.this.mActivity.processCommand(cmd, param); + } + }); + } +} + +// Touch- and sensor-enabled GLSurfaceView. +class NativeGLView extends GLSurfaceView implements SensorEventListener { + private static String TAG = "NativeGLView"; + private SensorManager mSensorManager; + private Sensor mAccelerometer; + + public NativeGLView(NativeActivity activity) { + super(activity); + setEGLContextClientVersion(2); + // setEGLConfigChooser(5, 5, 5, 0, 16, 0); + // setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); + mSensorManager = (SensorManager)activity.getSystemService(Activity.SENSOR_SERVICE); + mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + } + + // This needs fleshing out. A lot. + // Going to want multitouch eventually. + public boolean onTouchEvent(final MotionEvent event) { + int code = 0; + if (event.getAction() == MotionEvent.ACTION_DOWN) { + code = 1; + } else if (event.getAction() == MotionEvent.ACTION_UP) { + code = 2; + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + code = 3; + } else { + return true; + } + NativeApp.touch((int)event.getRawX(), (int)event.getRawY(), code); + return true; + } + + // Sensor management + @Override + public void onAccuracyChanged(Sensor sensor, int arg1) { + Log.i(TAG, "onAccuracyChanged"); + } + + @Override + public void onSensorChanged(SensorEvent event) { + if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) { + return; + } + // Can also look at event.timestamp for accuracy magic + NativeApp.accelerometer(event.values[0], event.values[1], event.values[2]); + } + + @Override + public void onPause() { + super.onPause(); + mSensorManager.unregisterListener(this); + } + + @Override + public void onResume() { + super.onResume(); + mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); + } +} + + +class NativeAudioPlayer { + private String TAG = "NativeAudioPlayer"; + private Thread thread; + private boolean playing_; + + // Calling stop() is allowed at any time, whether stopped or not. + // If playing, blocks until not. + public synchronized void stop() { + if (thread != null) { + waitUntilDone(); + } else { + Log.e(TAG, "Was already stopped"); + } + } + + // If not playing, make sure we're playing. + public synchronized void play() { + if (thread == null) { + playStreaming(); + } else { + Log.e(TAG, "Was already playing"); + } + } + + private void playStreaming() { + playing_ = true; + thread = new Thread(new Runnable() { + public void run() { + playThread(); + } + }); + thread.start(); + } + + private void waitUntilDone() { + if (!playing_) { + Log.i(TAG, "not playing."); + } + try { + playing_ = false; + Log.e(TAG, "waitUntilDone: Joining audio thread."); + thread.join(); + } catch (InterruptedException e) { + Log.e(TAG, "INterrupted!"); + e.printStackTrace(); + } + thread = null; + Log.i(TAG, "Finished waitUntilDone"); + } + + private void playThread() { + try { + Log.i(TAG, "Thread started."); + // Get the smallest possible buffer size (which is annoyingly huge). + int buffer_size_bytes = AudioTrack.getMinBufferSize( + 44100, + AudioFormat.CHANNEL_CONFIGURATION_STEREO, + AudioFormat.ENCODING_PCM_16BIT); + + // Round buffer_size_bytes up to an even multiple of 128 for convenience. + buffer_size_bytes = (buffer_size_bytes + 127) & ~127; + + AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, + 44100, + AudioFormat.CHANNEL_CONFIGURATION_STEREO, + AudioFormat.ENCODING_PCM_16BIT, + buffer_size_bytes, + AudioTrack.MODE_STREAM); + + int buffer_size = buffer_size_bytes / 2; + short [] buffer = new short[buffer_size]; + audioTrack.play(); + Log.i(TAG, "Playing... minBuffersize = " + buffer_size); + while (playing_) { + NativeApp.audioRender(buffer); + audioTrack.write(buffer, 0, buffer_size); + } + audioTrack.stop(); + audioTrack.release(); + Log.i(TAG, "Stopped playing."); + } catch (Throwable t) { + Log.e(TAG, "Playback Failed"); + t.printStackTrace(); + Log.e(TAG, t.toString()); + } + } +} + +class Installation { + private static String sID = null; + private static final String INSTALLATION = "INSTALLATION"; + + public synchronized static String id(Context context) { + if (sID == null) { + File installation = new File(context.getFilesDir(), INSTALLATION); + try { + if (!installation.exists()) + writeInstallationFile(installation); + sID = readInstallationFile(installation); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return sID; + } + + private static String readInstallationFile(File installation) throws IOException { + RandomAccessFile f = new RandomAccessFile(installation, "r"); + byte[] bytes = new byte[(int) f.length()]; + f.readFully(bytes); + f.close(); + return new String(bytes); + } + + private static void writeInstallationFile(File installation) throws IOException { + FileOutputStream out = new FileOutputStream(installation); + String id = UUID.randomUUID().toString(); + out.write(id.getBytes()); + out.close(); + } +} + + +public class NativeActivity extends Activity { + // Remember to loadLibrary your JNI .so in a static {} block + + // Adjust these as necessary + private static String TAG = "NativeActivity"; + String packageName = "com.turboviking.rollerball"; + + // Graphics and audio interfaces + private GLSurfaceView mGLSurfaceView; + private NativeAudioPlayer audioPlayer; + + + public static String runCommand; + public static String commandParameter; + + public static String installID; + + @Override + public void onCreate(Bundle savedInstanceState) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + super.onCreate(savedInstanceState); + Log.i(TAG, "onCreate"); + installID = Installation.id(this); + // Get system information + ApplicationInfo appInfo = null; + PackageManager packMgmr = getPackageManager(); + try { + appInfo = packMgmr.getApplicationInfo(packageName, 0); + } catch (NameNotFoundException e) { + e.printStackTrace(); + throw new RuntimeException("Unable to locate assets, aborting..."); + } + File sdcard = Environment.getExternalStorageDirectory(); + Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); + int scrPixelFormat = display.getPixelFormat(); + int scrWidth = display.getWidth(); + int scrHeight = display.getHeight(); + float scrRefreshRate = (float)display.getRefreshRate(); + String externalStorageDir = sdcard.getAbsolutePath(); + String dataDir = this.getFilesDir().getAbsolutePath(); + String apkFilePath = appInfo.sourceDir; + NativeApp.init(scrWidth, scrHeight, apkFilePath, dataDir, externalStorageDir, installID); + + // Keep the screen bright - very annoying if it goes dark when tilting away + Window window = this.getWindow(); + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + setVolumeControlStream(AudioManager.STREAM_MUSIC); + Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat); + + // Initialize Graphics + if (!detectOpenGLES20()) { + throw new RuntimeException("Application requires OpenGL ES 2.0."); + } else { + Log.i(TAG, "OpenGL ES 2.0 detected."); + } + + mGLSurfaceView = new NativeGLView(this); + mGLSurfaceView.setRenderer(new NativeRenderer(this)); + setContentView(mGLSurfaceView); + audioPlayer = new NativeAudioPlayer(); + } + + private boolean detectOpenGLES20() { + ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); + ConfigurationInfo info = am.getDeviceConfigurationInfo(); + return info.reqGlEsVersion >= 0x20000; + } + + + @Override + protected void onPause() { + super.onPause(); + Log.i(TAG, "onPause"); + if (audioPlayer != null) { + audioPlayer.stop(); + } + mGLSurfaceView.onPause(); + } + + @Override + protected void onResume() { + super.onResume(); + Log.i(TAG, "onResume"); + mGLSurfaceView.onResume(); + if (audioPlayer != null) { + audioPlayer.play(); + } + } + + @Override + protected void onStop() { + super.onStop(); + Log.i(TAG, "onStop"); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + Log.e(TAG, "onDestroy"); + NativeApp.shutdown(); + audioPlayer = null; + mGLSurfaceView = null; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + // Eat these keys, to avoid accidental exits / other screwups. + // Maybe there's even more we need to eat on tablets? + if (keyCode == KeyEvent.KEYCODE_BACK) { + NativeApp.keyDown(1); + return true; + } + else if (keyCode == KeyEvent.KEYCODE_MENU) { + NativeApp.keyDown(2); + return true; + } + else if (keyCode == KeyEvent.KEYCODE_SEARCH) { + NativeApp.keyDown(3); + return true; + } + // Don't process any other keys. + return false; + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + // Eat these keys, to avoid accidental exits / other screwups. + // Maybe there's even more we need to eat on tablets? + if (keyCode == KeyEvent.KEYCODE_BACK) { + NativeApp.keyUp(1); + return true; + } + else if (keyCode == KeyEvent.KEYCODE_MENU) { + // Menu should be ignored from android 3 forwards + NativeApp.keyUp(2); + return true; + } + else if (keyCode == KeyEvent.KEYCODE_SEARCH) { + // Search probably should also be ignored. + NativeApp.keyUp(3); + return true; + } + return false; + } + + // Prevent destroying and recreating the main activity when the device rotates etc, + // since this would stop the sound. + @Override + public void onConfigurationChanged(Configuration newConfig) { + // Ignore orientation change + super.onConfigurationChanged(newConfig); + } + + public void processCommand(String command, String params) { + if (command.equals("launchBrowser")) { + Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); + startActivity(i); + } else if (command.equals("launchEmail")) { + Intent send = new Intent(Intent.ACTION_SENDTO); + String uriText; + uriText = "mailto:email@gmail.com" + + "?subject=Rollfish is..." + + "&body=great! Or?"; + uriText = uriText.replace(" ", "%20"); + Uri uri = Uri.parse(uriText); + send.setData(uri); + startActivity(Intent.createChooser(send, "E-mail Henrik!")); + } else if (command.equals("launchMarket")) { + // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app + // http://developer.android.com/guide/publishing/publishing.html#marketintent + } else if (command.equals("toast")) { + Toast toast = Toast.makeText(this, params, 2000); + toast.show(); + } else { + Log.e(TAG, "Unsupported command " + command + " , param: " + params); + } + } +} diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/turboviking/libnative/NativeApp.java new file mode 100644 index 0000000000..5366a22c14 --- /dev/null +++ b/android/src/com/turboviking/libnative/NativeApp.java @@ -0,0 +1,18 @@ +package com.turboviking.libnative; + +public class NativeApp { + public static native void init( + int xxres, int yyres, String apkPath, + String dataDir, String externalDir, String installID); + public static native void shutdown(); + + public static native void keyDown(int key); + public static native void keyUp(int key); + + // will only be called between init() and shutdown() + public static native void audioRender(short [] buffer); + + // Sensor/input data. These are asynchronous, beware! + public static native void touch(int x, int y, int data); + public static native void accelerometer(float x, float y, float z); +} \ No newline at end of file From 1e398d4269320d7cbb3ea26e6ba8a70acc10b227 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 10 Apr 2012 00:35:22 +0200 Subject: [PATCH 0015/1445] Move the C++ part of the android wrapping here. --- android/NativeApp.h | 46 ++++++++ android/app-android.cpp | 244 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 290 insertions(+) create mode 100644 android/NativeApp.h create mode 100644 android/app-android.cpp diff --git a/android/NativeApp.h b/android/NativeApp.h new file mode 100644 index 0000000000..4ca2409ac3 --- /dev/null +++ b/android/NativeApp.h @@ -0,0 +1,46 @@ +#pragma once + +// The Native App API. +// +// Implement these functions and you've got a native app. These are called +// from app-android, which exposes the native JNI api which is a bit +// more complicated. + +// This is defined in input/input_state.h. +struct InputState; + +// The very first function to be called. Even NativeMix is not called +// before this, although it may be called at any point in time afterwards. +// Must not call OpenGL. Main thread. +void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *installID); + +// Runs after NativeInit() at some point. Can call OpenGL. +void NativeInitGraphics(); + +// Signals that you need to recreate all buffered OpenGL resources, +// like textures, vbo etc. Main thread. +void NativeDeviceLost(); + +// Called ~sixty times a second, delivers the current input state. +// Main thread. +void NativeUpdate(const InputState &input); + +// Called when it's time to render. If the device can keep up, this +// will also be called sixty times per second. Main thread. +void NativeRender(); + +// This should render num_samples 44khz stereo samples. +// Try not to make too many assumptions on the granularity +// of num_samples. +// This function may be called from a totally separate thread from +// the rest of the game. +void NativeMix(short *audio, int num_samples); + +// Called when it's time to shutdown. After this has been called, +// no more calls to any other function will be made from the framework +// before process exit. +// The graphics context should still be active when calling this, as freeing +// of graphics resources happens here. +// Main thread. +void NativeShutdownGraphics(); +void NativeShutdown(); diff --git a/android/app-android.cpp b/android/app-android.cpp new file mode 100644 index 0000000000..c5354f9589 --- /dev/null +++ b/android/app-android.cpp @@ -0,0 +1,244 @@ +// This is generic code that is included in all Android apps that use the +// Native framework by Henrik Rydgård (https://github.com/hrydgard/native). + +// It calls a set of methods defined in NativeApp.h. These should be implemented +// by your game or app. + + +#include +#include +#include +#include +#include +#include + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/timeutil.h" +#include "file/zip_read.h" +#include "input/input_state.h" +#include "audio/mixer.h" +#include "android/NativeApp.h" +#include "Globals.h" + +#define coord_xres 800 +#define coord_yres 480 + +static JNIEnv *jniEnvUI; + +std::string frameCommand; +std::string frameCommandParam; + +// Android implementation of callbacks to the Java part of the app +void SystemToast(const char *text) { + frameCommand = "toast"; + frameCommandParam = text; +} + +// TODO: need a Hide or bool show; +void ShowAd(int x, int y, bool center_x) { + ELOG("TODO! ShowAd!"); +} + +void Vibrate(int length_ms) { + frameCommand = "vibrate"; + frameCommandParam = "100"; +} + +void LaunchBrowser(const char *url) +{ + frameCommand = "launchBrowser"; + frameCommandParam = url; +} + +void LaunchMarket(const char *url) +{ + frameCommand = "launchMarket"; + frameCommandParam = url; +} + +void LaunchEmail(const char *email_address) +{ + frameCommand = "launchEmail"; + frameCommandParam = email_address; +} + + +// Remember that all of these need initialization on init! The process +// may be reused when restarting the game. Globals are DANGEROUS. +int xres, yres; + +// Used for touch. (TODO) +float xscale = 1; +float yscale = 1; + +InputState input_state; + +static bool renderer_inited = false; +static bool first_lost = true; + +extern "C" void Java_com_turboviking_libnative_NativeApp_init + (JNIEnv *env, jclass, jint xxres, jint yyres, jstring apkpath, + jstring dataDir, jstring externalDir, jstring jinstallID) { + jniEnvUI = env; + xres = xxres; + yres = yyres; + g_xres = xres; + g_yres = yres; + xscale = (float)coord_xres / xres; + yscale = (float)coord_yres / yres; + memset(&input_state, 0, sizeof(input_state)); + renderer_inited = false; + first_lost = true; + + jboolean isCopy; + const char *str = env->GetStringUTFChars(apkpath, &isCopy); + ILOG("APK path: %s", str); + VFSRegister("", new ZipAssetReader(str, "assets/")); + + str = env->GetStringUTFChars(externalDir, &isCopy); + ILOG("External storage path: %s", str); + + str = env->GetStringUTFChars(dataDir, &isCopy); + user_data_path = std::string(str) + "/"; + settings_file = user_data_path + "settings.json"; + ILOG("Settings file: %s", settings_file.c_str()); + + str = env->GetStringUTFChars(jinstallID, &isCopy); + std::string installID = std::string(str); + + const char *app_name = "rollerball"; + NativeInit(1, &app_name, user_data_path.c_str(), installID.c_str()); +} + +extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown + (JNIEnv *, jclass) { + ILOG("RollerBallMainShutdown - calling NativeShutdown."); + if (renderer_inited) { + NativeShutdownGraphics(); + } + NativeShutdown(); + ILOG("RollerBallMainShutdown - calling VFSShutdown."); + VFSShutdown(); +} + +static jmethodID postCommand; + +extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { + if (!renderer_inited) { + ILOG("Calling NativeInitGraphics();"); + NativeInitGraphics(); + } else { + ILOG("Calling NativeDeviceLost();"); + } + renderer_inited = true; + jclass cls = env->GetObjectClass(obj); + postCommand = env->GetMethodID( + cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); + ILOG("MethodID: %i", (int)postCommand); +} + +extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize + (JNIEnv *, jobject clazz, jint w, jint h) { + ILOG("nativeResize (%i, %i), device lost!", w, h); + if (first_lost) { + first_lost = false; + } else { + NativeDeviceLost(); + } +} + +extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender + (JNIEnv *env, jobject obj) { + if (renderer_inited) { + UpdateInputState(&input_state); + NativeUpdate(input_state); + NativeRender(); + time_update(); + } else { + ELOG("Ended up in nativeRender even though app has quit.%s", ""); + // Shouldn't really get here. + glClearColor(1.0, 0.0, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + if (!frameCommand.empty()) { + ILOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str()); + jstring cmd = env->NewStringUTF(frameCommand.c_str()); + jstring param = env->NewStringUTF(frameCommandParam.c_str()); + + env->CallVoidMethod(obj, postCommand, cmd, param); + + frameCommand = ""; + frameCommandParam = ""; + } +} + +extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { + int buf_size = env->GetArrayLength(array); + if (buf_size) { + short *data = env->GetShortArrayElements(array, 0); + int samples = buf_size / 2; + NativeMix(data, samples); + env->ReleaseShortArrayElements(array, data, 0); + } +} + +extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch + (JNIEnv *, jclass, int x, int y, int code) { + // This really does require locking :/ + input_state.mouse_valid = false; + input_state.mouse_x = x; + input_state.mouse_y = y; + if (code == 1) { + input_state.mouse_buttons = 1; + } else if (code == 2) { + input_state.mouse_buttons = 0; + } + input_state.mouse_valid = true; +} + +extern "C" void Java_com_turboviking_libnative_NativeApp_keyDown + (JNIEnv *, jclass, jint key) { + ILOG("Keydown %i", key); + // Need a mechanism to release these. + switch (key) { + case 1: // Back + input_state.pad_buttons |= PAD_BUTTON_BACK; + break; + case 2: // Menu + input_state.pad_buttons |= PAD_BUTTON_START; + break; + case 3: // Search + input_state.pad_buttons |= PAD_BUTTON_A; + break; + } +} + +extern "C" void Java_com_turboviking_libnative_NativeApp_keyUp + (JNIEnv *, jclass, jint key) { + ILOG("Keyup %i", key); + // Need a mechanism to release these. + switch (key) { + case 1: // Back + input_state.pad_buttons &= ~PAD_BUTTON_BACK; + break; + case 2: // Menu + input_state.pad_buttons &= ~PAD_BUTTON_START; + break; + case 3: // Search + input_state.pad_buttons &= ~PAD_BUTTON_A; + break; + } +} + +extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_accelerometer + (JNIEnv *, jclass, float x, float y, float z) { + // Theoretically this needs locking but I doubt it matters. Worst case, the X + // from one "sensor frame" will be used together with Y from the next. + // Should look into quantization though, for compressed movement storage. + input_state.accelerometer_valid = true; + input_state.acc.x = x; + input_state.acc.y = y; + input_state.acc.z = z; +} From fc886b23e66e4e96535183506714da47411e6247 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 10 Apr 2012 11:59:57 +0200 Subject: [PATCH 0016/1445] Move the SDL C++ wrapper code into the native project as well. --- android/README.md | 8 + android/app-android.cpp | 8 +- android/res/layout/main.xml | 12 -- android/res/values/strings.xml | 7 - {android => base}/NativeApp.h | 23 ++- base/PCMain.cpp | 270 +++++++++++++++++++++++++++++++++ base/display.cpp | 4 + base/display.h | 7 + native.vcxproj | 5 +- native.vcxproj.filters | 9 ++ 10 files changed, 324 insertions(+), 29 deletions(-) create mode 100644 android/README.md delete mode 100644 android/res/layout/main.xml delete mode 100644 android/res/values/strings.xml rename {android => base}/NativeApp.h (64%) create mode 100644 base/PCMain.cpp create mode 100644 base/display.cpp create mode 100644 base/display.h diff --git a/android/README.md b/android/README.md new file mode 100644 index 0000000000..61612db953 --- /dev/null +++ b/android/README.md @@ -0,0 +1,8 @@ +Here's an Android library project. Add this to your eclipse workspace +and add a dependency to it, then just inherit from NativeActivity, +write your C++ code, and Bob's your uncle. + + +Contact: hrydgard@gmail.com + + diff --git a/android/app-android.cpp b/android/app-android.cpp index c5354f9589..ba33634a5e 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -13,13 +13,13 @@ #include #include "base/basictypes.h" +#include "base/display.h" +#include "base/NativeApp.h" #include "base/logging.h" #include "base/timeutil.h" #include "file/zip_read.h" #include "input/input_state.h" #include "audio/mixer.h" -#include "android/NativeApp.h" -#include "Globals.h" #define coord_xres 800 #define coord_yres 480 @@ -100,9 +100,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init ILOG("External storage path: %s", str); str = env->GetStringUTFChars(dataDir, &isCopy); - user_data_path = std::string(str) + "/"; - settings_file = user_data_path + "settings.json"; - ILOG("Settings file: %s", settings_file.c_str()); + std::string user_data_path = std::string(str) + "/"; str = env->GetStringUTFChars(jinstallID, &isCopy); std::string installID = std::string(str); diff --git a/android/res/layout/main.xml b/android/res/layout/main.xml deleted file mode 100644 index bc12cd8231..0000000000 --- a/android/res/layout/main.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml deleted file mode 100644 index 6a272c9cf2..0000000000 --- a/android/res/values/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - Hello World! - libnative - - \ No newline at end of file diff --git a/android/NativeApp.h b/base/NativeApp.h similarity index 64% rename from android/NativeApp.h rename to base/NativeApp.h index 4ca2409ac3..72ffc952c0 100644 --- a/android/NativeApp.h +++ b/base/NativeApp.h @@ -1,5 +1,7 @@ #pragma once +#include + // The Native App API. // // Implement these functions and you've got a native app. These are called @@ -9,12 +11,15 @@ // This is defined in input/input_state.h. struct InputState; -// The very first function to be called. Even NativeMix is not called -// before this, although it may be called at any point in time afterwards. -// Must not call OpenGL. Main thread. +// You must implement this. The first function to get called, just write strings to the two pointers. +void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name); + +// The very first function to be called after NativeGetAppInfo. Even NativeMix is not called +// before this, although it may be called at any point in time afterwards (on any thread!) +// This functions must NOT call OpenGL. Main thread. void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *installID); -// Runs after NativeInit() at some point. Can call OpenGL. +// Runs after NativeInit() at some point. May (and probably should) call OpenGL. void NativeInitGraphics(); // Signals that you need to recreate all buffered OpenGL resources, @@ -44,3 +49,13 @@ void NativeMix(short *audio, int num_samples); // Main thread. void NativeShutdownGraphics(); void NativeShutdown(); + +// Calls back into Java / SDL +// These APIs must be implemented by every port (for example app-android.cpp, PCMain.cpp). +// You are free to call these. +void SystemToast(const char *text); +void ShowAd(int x, int y, bool center_x); +void Vibrate(int length_ms); +void LaunchBrowser(const char *url); +void LaunchMarket(const char *url); +void LaunchEmail(const char *email_address); diff --git a/base/PCMain.cpp b/base/PCMain.cpp new file mode 100644 index 0000000000..f6fbd87fd3 --- /dev/null +++ b/base/PCMain.cpp @@ -0,0 +1,270 @@ +// Bare bones SDL main. + +// Marble Madness +// Marble Mania +// Marbeliciuos +// Ballsy +// Rollerball +// Crash +// Cowball (with cowbell noises at the menu!) +// Rollfish + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#endif + +#include + +#include "SDL/SDL.h" +#include "SDL/SDL_timer.h" +#include "SDL/SDL_audio.h" + +#include "base/display.h" +#include "base/logging.h" +#include "base/timeutil.h" +#include "gfx_es2/glsl_program.h" +#include "file/zip_read.h" +#include "input/input_state.h" +#include "base/NativeApp.h" + + +// Simple implementations of System functions + +void SystemToast(const char *text) { + MessageBox(0, text, "Toast!", MB_ICONINFORMATION); +} + + +void ShowAd(int x, int y, bool center_x) { + // Ignore ads on PC +} + +void Vibrate(int length_ms) { + // Ignore on PC +} + +void LaunchBrowser(const char *url) +{ +#ifdef _WIN32 + ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); +#else +#endif +} + +void LaunchMarket(const char *url) +{ +#ifdef _WIN32 + ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); +#else +#endif +} + +void LaunchEmail(const char *email_address) +{ +#ifdef _WIN32 + ShellExecute(NULL, "open", (std::string("mailto:") + email_address).c_str(), NULL, NULL, SW_SHOWNORMAL); +#else +#endif +} + + + +const int buttonMappings[12] = { + SDLK_x, //A + SDLK_s, //B + SDLK_z, //X + SDLK_a, //Y + SDLK_w, //LBUMPER + SDLK_q, //RBUMPER + SDLK_1, //START + SDLK_2, //BACK + SDLK_UP, //UP + SDLK_DOWN, //DOWN + SDLK_LEFT, //LEFT + SDLK_RIGHT, //RIGHT +}; + +void SimulateGamepad(const uint8 *keys, InputState *input) { + input->pad_buttons = 0; + input->pad_lstick_x = 0; + input->pad_lstick_y = 0; + input->pad_rstick_x = 0; + input->pad_rstick_y = 0; + for (int b = 0; b < 12; b++) { + if (keys[buttonMappings[b]]) + input->pad_buttons |= (1<pad_lstick_y=32000; + else if (keys['K']) input->pad_lstick_y=-32000; + if (keys['J']) input->pad_lstick_x=-32000; + else if (keys['L']) input->pad_lstick_x=32000; + if (keys['8']) input->pad_rstick_y=32000; + else if (keys['2']) input->pad_rstick_y=-32000; + if (keys['4']) input->pad_rstick_x=-32000; + else if (keys['6']) input->pad_rstick_x=32000; +} + +extern void mixaudio(void *userdata, Uint8 *stream, int len) { + NativeMix((short *)stream, len / 4); +} + +#ifdef _WIN32 +#undef main +#endif +int main(int argc, char *argv[]) { + /* // Xoom resolution. Other common tablet resolutions: 1024x600 , 1366x768 + g_xres = 1280; + g_yres = 800; + */ + g_xres = 800; + g_yres = 480; + + std::string app_name; + std::string app_name_nice; + NativeGetAppInfo(&app_name, &app_name_nice); + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); + + if (SDL_SetVideoMode(g_xres, g_yres, 0, SDL_OPENGL) == NULL) { + fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); + SDL_Quit(); + return(2); + } + SDL_WM_SetCaption(app_name_nice.c_str(), NULL); + + if (GLEW_OK != glewInit()) { + printf("Failed to initialize glew!\n"); + return 1; + } + + if (GLEW_VERSION_2_0) { + printf("OpenGL 2.0 or higher.\n"); + } else { + printf("Sorry, this program requires OpenGL 2.0.\n"); + return 1; + } + + + +#ifdef _MSC_VER + // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); + TCHAR path[MAX_PATH]; + SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path); + PathAppend(path, (app_name + "\\").c_str()); +#else + // Mac - what about linux? Also, ugly hardcoding. + const char *path = getenv("HOME"); + if (!homeDir) { + struct passwd* pwd = getpwuid(getuid()); + if (pwd) + path = pwd->pw_dir; + } + +#endif + + NativeInit(argc, (const char **)argv, path, "BADCOFFEE"); + NativeInitGraphics(); + + SDL_AudioSpec fmt; + fmt.freq = 44100; + fmt.format = AUDIO_S16; + fmt.channels = 2; + fmt.samples = 512; + fmt.callback = &mixaudio; + fmt.userdata = (void *)0; + + if (SDL_OpenAudio(&fmt, NULL) < 0) { + ELOG("Failed to open audio: %s", SDL_GetError()); + return 1; + } + + // Audio must be unpaused _after_ NativeInit() + SDL_PauseAudio(0); + + InputState input_state = {0}; + int framecount = 0; + + while (true) { + SDL_Event event; + + input_state.accelerometer_valid = false; + input_state.mouse_valid = true; + int done = 0; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) { + done = 1; + } else if (event.type == SDL_KEYDOWN) { + if (event.key.keysym.sym == SDLK_ESCAPE) { + done = 1; + } + } else if (event.type == SDL_MOUSEMOTION) { + input_state.mouse_x = event.motion.x; + input_state.mouse_y = event.motion.y; + } else if (event.type == SDL_MOUSEBUTTONDOWN) { + if (event.button.button == SDL_BUTTON_LEFT) { + input_state.mouse_buttons_down = 1; + input_state.mouse_buttons = 1; + } + } else if (event.type == SDL_MOUSEBUTTONUP) { + if (event.button.button == SDL_BUTTON_LEFT) { + input_state.mouse_buttons = 0; + input_state.mouse_buttons_up = 1; + } + } + } + + if (done) break; + + input_state.mouse_last_buttons = input_state.mouse_buttons; + uint8 *keys = (uint8 *)SDL_GetKeyState(NULL); + if (keys[SDLK_ESCAPE]) { + break; + } + SimulateGamepad(keys, &input_state); + UpdateInputState(&input_state); + NativeUpdate(input_state); + NativeRender(); + if (framecount % 60 == 0) { + // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. + } + + SDL_GL_SwapBuffers(); + + // Simple framerate limiting + static float t=0; + while (time_now() < t+1.0f/60.0f) { + sleep_ms(0); + time_update(); + } + time_update(); + t = time_now(); + framecount++; + } + // Faster exit, thanks to the OS. Remove this if you want to debug shutdown + exit(0); + + NativeShutdownGraphics(); + SDL_PauseAudio(1); + NativeShutdown(); + SDL_CloseAudio(); + SDL_Quit(); + return 0; +} diff --git a/base/display.cpp b/base/display.cpp new file mode 100644 index 0000000000..b84f2dd604 --- /dev/null +++ b/base/display.cpp @@ -0,0 +1,4 @@ +#include "base/display.h" + +int g_xres; +int g_yres; diff --git a/base/display.h b/base/display.h new file mode 100644 index 0000000000..8dae4a6bb2 --- /dev/null +++ b/base/display.h @@ -0,0 +1,7 @@ +#pragma once + +// This is meant to be a framework for handling DPI scaling etc. +// For now, it just consists of these two ugly globals. + +extern int g_xres; +extern int g_yres; diff --git a/native.vcxproj b/native.vcxproj index 4a4506782e..1eed63f384 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -91,9 +91,11 @@ + + @@ -136,6 +138,7 @@ + @@ -176,4 +179,4 @@ - + \ No newline at end of file diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 0dae95bf12..1de7570a8d 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -138,6 +138,12 @@ gfx + + base + + + base + @@ -248,6 +254,9 @@ gfx + + base + From ddf4165e4cf01c7c67b65e0e3e313e077f118c35 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 10 Apr 2012 12:03:30 +0200 Subject: [PATCH 0017/1445] ... --- base/PCMain.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index f6fbd87fd3..0e4f1a7147 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -1,13 +1,4 @@ -// Bare bones SDL main. - -// Marble Madness -// Marble Mania -// Marbeliciuos -// Ballsy -// Rollerball -// Crash -// Cowball (with cowbell noises at the menu!) -// Rollfish +// PC implementation of the framework. #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN From 12f7b7904b3172d3d8387d089356898af8966105 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 10 Apr 2012 12:36:38 +0200 Subject: [PATCH 0018/1445] Move my horrible IMGUI code here. --- gfx/texture_atlas.h | 5 - native.vcxproj | 2 + native.vcxproj.filters | 9 ++ ui/CMakeLists.txt | 12 ++ ui/ui.cpp | 292 +++++++++++++++++++++++++++++++++++++++++ ui/ui.h | 131 ++++++++++++++++++ 6 files changed, 446 insertions(+), 5 deletions(-) create mode 100644 ui/CMakeLists.txt create mode 100644 ui/ui.cpp create mode 100644 ui/ui.h diff --git a/gfx/texture_atlas.h b/gfx/texture_atlas.h index 8dd9c4b746..a75dc4de8a 100644 --- a/gfx/texture_atlas.h +++ b/gfx/texture_atlas.h @@ -31,8 +31,3 @@ struct Atlas { const AtlasImage *images; int num_images; }; - -enum { - PRINT_RIGHT = 1, - PRINT_CENTER = 2, -}; diff --git a/native.vcxproj b/native.vcxproj index 1eed63f384..e0928be39d 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -133,6 +133,7 @@ + @@ -175,6 +176,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 1de7570a8d..a9dc4e2a7e 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -144,6 +144,9 @@ base + + ui + @@ -257,6 +260,9 @@ base + + ui + @@ -292,5 +298,8 @@ {cda27e9f-5763-4bf2-b6bc-85a377f7020e} + + {d738c2d1-749d-4b60-b98f-f3da0bbbf40c} + \ No newline at end of file diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt new file mode 100644 index 0000000000..9a98c118d9 --- /dev/null +++ b/ui/CMakeLists.txt @@ -0,0 +1,12 @@ +set(SRCS + ui.cpp +) + +set(SRCS ${SRCS}) + +add_library(ui STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) + diff --git a/ui/ui.cpp b/ui/ui.cpp new file mode 100644 index 0000000000..b1d419c89a --- /dev/null +++ b/ui/ui.cpp @@ -0,0 +1,292 @@ +// See header for documentation. + +#include +#include + +#include "ui/ui.h" +#include "gfx/texture_atlas.h" +#include "gfx_es2/draw_buffer.h" + +DrawBuffer ui_draw2d; +UIState uistate; + +// Theme. +static const Atlas *themeAtlas; +static int themeUIFont; +static int themeButtonImage; +static int themeCheckOnImage; +static int themeCheckOffImage; + +void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int checkOff) { + ui_draw2d.SetAtlas(atlas); + themeAtlas = atlas; + themeUIFont = uiFont; + themeButtonImage = buttonImage; + themeCheckOnImage = checkOn; + themeCheckOffImage = checkOff; +} + +void UIUpdateMouse(float x, float y, int buttons) { + uistate.mousex = x; + uistate.mousey = y; + uistate.mousedown = buttons; +} + +bool regionhit(int x, int y, int w, int h, int margin) { + if (uistate.mousex < x - margin || + uistate.mousey < y - margin || + uistate.mousex >= x + w + margin || + uistate.mousey >= y + h + margin) { + return false; + } else { + return true; + } +} + +void UIBegin() { + uistate.hotitem = 0; + ui_draw2d.Begin(); +} + +void UIEnd() { + if (uistate.mousedown == 0) { + uistate.activeitem = 0; + } else { + if (uistate.activeitem == 0) { + uistate.activeitem = -1; + } + } + ui_draw2d.End(); + + uistate.lastx = uistate.mousex; + uistate.lasty = uistate.mousey; +} + +void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) { + ui_draw2d.SetFontScale(scale, scale); + ui_draw2d.DrawTextShadow(themeUIFont, text, x, y, color, align); + ui_draw2d.SetFontScale(1.0f, 1.0f); +} + +int UIButton(int id, int x, int y, int w, const char *text, int button_align) { + const int h = 64; + if (button_align & ALIGN_HCENTER) x -= w / 2; + if (button_align & ALIGN_VCENTER) y -= h / 2; + if (button_align & ALIGN_RIGHT) x -= w; + if (button_align & ALIGN_BOTTOMRIGHT) y -= h; + + // Check whether the button should be hot, use a generous margin for touch ease + if (regionhit(x, y, w, h, 8)) { + uistate.hotitem = id; + if (uistate.activeitem == 0 && uistate.mousedown) + uistate.activeitem = id; + } + + // Render button + + int txOffset = 0; + if (uistate.hotitem == id) { + if (uistate.activeitem == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); + ui_draw2d.DrawTextShadow(themeUIFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); + + int clicked = 0; + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown == 0 && + uistate.hotitem == id && + uistate.activeitem == id) { + clicked = 1; + } + + uistate.lastwidget = id; + return clicked; +} + +int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { + const int h = 64; + float tw, th; + ui_draw2d.MeasureText(themeUIFont, text, &tw, &th); + int w = themeAtlas->images[themeCheckOnImage].w + UI_SPACE + tw; + if (align & ALIGN_HCENTER) x -= w / 2; + if (align & ALIGN_VCENTER) y -= h / 2; + if (align & ALIGN_RIGHT) x -= w; + if (align & ALIGN_BOTTOMRIGHT) y -= h; + + // Check whether the button should be hot + if (regionhit(x, y, w, h, 8)) { + uistate.hotitem = id; + if (uistate.activeitem == 0 && uistate.mousedown) + uistate.activeitem = id; + } + + // Render button + + int txOffset = 0; + if (uistate.hotitem == id) { + if (uistate.activeitem == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + + ui_draw2d.DrawImage((*value) ? themeCheckOnImage : themeCheckOffImage, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + ui_draw2d.DrawTextShadow(themeUIFont, text, x + themeAtlas->images[themeCheckOnImage].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + + int clicked = 0; + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown == 0 && + uistate.hotitem == id && + uistate.activeitem == id) { + *value = !(*value); + clicked = 1; + } + + uistate.lastwidget = id; + return clicked; +} + +void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, bool selected) const +{ + ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); + ui_draw2d.DrawTextShadow(themeUIFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); +} + +int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListState *state) { + const int item_h = 64; + + // Check whether the button should be hot + if (regionhit(x, y, w, h, 0)) { + uistate.hotitem = id; + if (uistate.activeitem == 0 && uistate.mousedown) + uistate.activeitem = id; + } + + // render items + int itemHeight = adapter->itemHeight(0); + int numItems = adapter->getCount(); + for (int i = 0; i < numItems; i++) { + int item_y = y + i * itemHeight - state->scrollY; + if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h && regionhit(x, item_y, w, h, 0)) { + // ultra fast touch response + state->selected = i; + } + adapter->drawItem(i, x, item_y, w, itemHeight, i == state->selected); + } + + int clicked = 0; + + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown == 0 && + uistate.hotitem == id && + uistate.activeitem == id && + state->selected != -1) { + clicked = 1; + } + + uistate.lastwidget = id; + + // Otherwise, no clicky. + return clicked; +} + +/* +struct SlideItem { + const char *text; + int image; + uint32_t bgColor; +}; + +struct SlideState +{ + float scroll; + +}; + +void UISlideChoice(int id, int y, const SlideItem *items, int numItems, SlideState *state) + +}*/ + +// TODO +int UIHSlider(int id, int x, int y, int w, int max, int *value) { + // Calculate mouse cursor's relative y offset + int xpos = ((256 - 16) * *value) / max; + + // Check for hotness + if (regionhit(x+8, y+8, 16, 255, 0)) { + uistate.hotitem = id; + if (uistate.activeitem == 0 && uistate.mousedown) + uistate.activeitem = id; + } + // Render the scrollbar + ui_draw2d.Rect(x, y, 32, 256+16, 0x777777); + + if (uistate.activeitem == id || uistate.hotitem == id) { + ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xffffff); + } else { + ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xaaaaaa); + } + + // Update widget value + if (uistate.activeitem == id) { + int mousepos = uistate.mousey - (y + 8); + if (mousepos < 0) mousepos = 0; + if (mousepos > 255) mousepos = 255; + int v = (mousepos * max) / 255; + if (v != *value) { + *value = v; + return 1; + } + } + + return 0; +} + +// TODO +int UIVSlider(int id, int x, int y, int h, int max, int *value) { + // Calculate mouse cursor's relative y offset + int ypos = ((256 - 16) * *value) / max; + + // Check for hotness + if (regionhit(x+8, y+8, 16, 255, 0)) { + uistate.hotitem = id; + if (uistate.activeitem == 0 && uistate.mousedown) + uistate.activeitem = id; + } + // Render the scrollbar + ui_draw2d.Rect(x, y, 32, 256+16, 0x777777); + + if (uistate.activeitem == id || uistate.hotitem == id) { + ui_draw2d.Rect(x+8, y+8 + ypos, 16, 16, 0xffffff); + } else { + ui_draw2d.Rect(x+8, y+8 + ypos, 16, 16, 0xaaaaaa); + } + + // Update widget value + if (uistate.activeitem == id) { + int mousepos = uistate.mousey - (y + 8); + if (mousepos < 0) mousepos = 0; + if (mousepos > 255) mousepos = 255; + int v = (mousepos * max) / 255; + if (v != *value) { + *value = v; + return 1; + } + } + + return 0; +} diff --git a/ui/ui.h b/ui/ui.h new file mode 100644 index 0000000000..55c538bff2 --- /dev/null +++ b/ui/ui.h @@ -0,0 +1,131 @@ +// Simple immediate mode UI implementation. +// +// Heavily inspired by Sol's tutorial at http://sol.gfxile.net/imgui/. +// +// A common pattern is Adapter classes for changing how things are drawn +// in lists, for example. +// +// hrydgard@gmail.com + +#pragma once + +// Simple ID generators. Absolutely no guarantee of collision avoidance if you implement +// multiple parts of a single screen of UI over multiple files unless you use IMGUI_SRC_ID. +#ifdef IMGUI_SRC_ID +#define GEN_ID ((IMGUI_SRC_ID) + (__LINE__)) +#else +#define GEN_ID (__LINE__) +#endif + +#include "gfx_es2/draw_buffer.h" + +#include + +// Mouse out of habit, applies just as well to touch events. +// UI does not yet support multitouch. +struct UIState { + int mousex; + int mousey; + int mousedown; + + int lastx; + int lasty; + + int deltax; + int deltay; + + int hotitem; + int activeitem; + + // keyboard focus, not currently used + int kbdwidget; + int lastwidget; +}; + +// This needs to be extern so that additional UI controls can be developed outside this file. +extern UIState uistate; + +struct Atlas; + +// This is the drawbuffer used for UI. Remember to flush it at the end of the frame. +// TODO: One should probably pass it in through UIInit. +extern DrawBuffer ui_draw2d; + +void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int checkOff); + +// TODO: These don't really belong here. +const int UI_SPACE = 32; +const int SMALL_BUTTON_WIDTH = 128; +const int LARGE_BUTTON_WIDTH = 192; +const int BUTTON_HEIGHT = 72; + +struct SlideItem { + const char *text; + int image; + uint32_t bgColor; +}; + +struct UISlideState { + float scroll; +}; + +// Implement this interface to style your lists +class UIListAdapter { +public: + virtual size_t getCount() const = 0; + virtual void drawItem(int item, int x, int y, int w, int h, bool active) const = 0; + virtual float itemHeight(int itemIndex) const { return 64; } + virtual bool itemEnabled(int itemIndex) const { return true; } +}; + +class StringVectorListAdapter : public UIListAdapter { +public: + StringVectorListAdapter(std::vector *items) : items_(items) {} + virtual size_t getCount() const { return items_->size(); } + virtual void drawItem(int item, int x, int y, int w, int h, bool active) const; + +private: + std::vector *items_; +}; + +struct UIListState { + UIListState() : scrollY(0.0f), selected(-1) {} + float scrollY; + int selected; +}; + +// Call at start of frame +void UIBegin(); + +void UIUpdateMouse(float x, float y, int buttons); + +// Returns 1 if clicked +int UIButton(int id, int x, int y, int w, const char *text, int button_align); + +// Returns 1 if clicked, puts the value in *value (where it also gets the current state). +int UICheckBox(int id, int x, int y, const char *text, int align, bool *value); + +// Just like a button, but with an image, doh. +int UIImageButton(int id, int x, int y, int w, int image_id, int button_align); // uses current UI atlas for fetching images. + +// Vertical slider. Not yet working. +int UIVSlider(int id, int x, int y, int h, int max, int *value); + +// Horizontal slider. Not yet working. +int UIHSlider(int id, int x, int y, int w, int max, int *value); + +// Draws static text, that does not participate in any focusing scheme etc, it just is. +void UIText(int x, int y, const char *text, uint32_t color, float scale = 1.0f, int align = ALIGN_TOPLEFT); + +// Slide choice, like the Angry Birds level selector. Not yet working. +void UISlideChoice(int id, int y, const SlideItem *items, int numItems, UISlideState *state); + +// List view. +// return -1 = no selection +int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListState *state); + +// Call at end of frame. +// Do this afterwards (or similar): +// ShaderManager::SetUIProgram(); +// ui_draw2d.Flush(ShaderManager::Program()); +void UIEnd(); From 1f669609ae90938dcb7fe664d5fd9809d7889431 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 10 Apr 2012 14:22:23 +0200 Subject: [PATCH 0019/1445] Record the start of drags --- ui/ui.cpp | 5 +++++ ui/ui.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/ui/ui.cpp b/ui/ui.cpp index b1d419c89a..623d2274bf 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -27,6 +27,11 @@ void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int ch } void UIUpdateMouse(float x, float y, int buttons) { + if ((buttons & 1) && !uistate.mousedown) + { + uistate.mouseStartX = x; + uistate.mouseStartY = y; + } uistate.mousex = x; uistate.mousey = y; uistate.mousedown = buttons; diff --git a/ui/ui.h b/ui/ui.h index 55c538bff2..c33ad36ee0 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -27,6 +27,8 @@ struct UIState { int mousex; int mousey; int mousedown; + int mouseStartX; + int mouseStartY; int lastx; int lasty; From 888b973bf33283effc77a51f1f84efdb154c95ad Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 10 Apr 2012 15:44:58 +0200 Subject: [PATCH 0020/1445] Apps can now request portrait mode if desired --- android/app-android.cpp | 15 +++++++++++++-- .../com/turboviking/libnative/NativeActivity.java | 6 +++++- .../src/com/turboviking/libnative/NativeApp.java | 1 + base/NativeApp.h | 7 ++++--- base/PCMain.cpp | 14 ++++++++++---- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index ba33634a5e..b6fb8f0a0d 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -77,6 +77,13 @@ InputState input_state; static bool renderer_inited = false; static bool first_lost = true; +extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) { + std::string app_name, app_nice_name; + bool landscape; + NativeGetAppInfo(&app_name, &app_nice_name, &landscape); + return landscape; +} + extern "C" void Java_com_turboviking_libnative_NativeApp_init (JNIEnv *env, jclass, jint xxres, jint yyres, jstring apkpath, jstring dataDir, jstring externalDir, jstring jinstallID) { @@ -105,8 +112,12 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init str = env->GetStringUTFChars(jinstallID, &isCopy); std::string installID = std::string(str); - const char *app_name = "rollerball"; - NativeInit(1, &app_name, user_data_path.c_str(), installID.c_str()); + std::string app_name, app_nice_name; + bool landscape; + + NativeGetAppInfo(&app_name, &app_nice_name, &landscape); + const char *argv[2] = {app_name.c_str(), 0}; + NativeInit(1, argv, user_data_path.c_str(), installID.c_str()); } extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 701a73e2d2..767bb6e275 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -288,7 +288,11 @@ public class NativeActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + if (NativeApp.isLandscape()) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } super.onCreate(savedInstanceState); Log.i(TAG, "onCreate"); installID = Installation.id(this); diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/turboviking/libnative/NativeApp.java index 5366a22c14..51b9654a59 100644 --- a/android/src/com/turboviking/libnative/NativeApp.java +++ b/android/src/com/turboviking/libnative/NativeApp.java @@ -1,6 +1,7 @@ package com.turboviking.libnative; public class NativeApp { + public static native boolean isLandscape(); public static native void init( int xxres, int yyres, String apkPath, String dataDir, String externalDir, String installID); diff --git a/base/NativeApp.h b/base/NativeApp.h index 72ffc952c0..d19eee64bb 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -5,14 +5,15 @@ // The Native App API. // // Implement these functions and you've got a native app. These are called -// from app-android, which exposes the native JNI api which is a bit +// from the framework, which exposes the native JNI api which is a bit // more complicated. // This is defined in input/input_state.h. struct InputState; // You must implement this. The first function to get called, just write strings to the two pointers. -void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name); +// This might get called multiple times in some implementations, you must be able to handle that. +void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape); // The very first function to be called after NativeGetAppInfo. Even NativeMix is not called // before this, although it may be called at any point in time afterwards (on any thread!) @@ -38,7 +39,7 @@ void NativeRender(); // Try not to make too many assumptions on the granularity // of num_samples. // This function may be called from a totally separate thread from -// the rest of the game. +// the rest of the game, so be careful with synchronization. void NativeMix(short *audio, int num_samples); // Called when it's time to shutdown. After this has been called, diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 0e4f1a7147..6353922a50 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -112,12 +112,18 @@ int main(int argc, char *argv[]) { g_xres = 1280; g_yres = 800; */ - g_xres = 800; - g_yres = 480; - std::string app_name; std::string app_name_nice; - NativeGetAppInfo(&app_name, &app_name_nice); + bool landscape; + NativeGetAppInfo(&app_name, &app_name_nice, &landscape); + + if (landscape) { + g_xres = 800; + g_yres = 480; + } else { + g_xres = 480; + g_yres = 800; + } if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); From 2e6adc24638124b9d40b4896d39979c816023a28 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 11 Apr 2012 17:07:28 +0200 Subject: [PATCH 0021/1445] UI and drawing (rotate image) --- gfx_es2/draw_buffer.cpp | 47 +++++++++++++++++++++++++++++++++++++++++ gfx_es2/draw_buffer.h | 1 + ui/ui.cpp | 22 ++++++++++--------- ui/ui.h | 9 ++++++++ 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 7c82788255..5a87b86e11 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -145,6 +145,53 @@ void DrawBuffer::DrawImageStretch(int atlas_image, float x1, float y1, float x2, V(x1, y2, color, image.u1, image.v2); } + +inline void rot(float *v, float angle, float xc,float yc) +{ + v[0]-=xc; + v[1]-=yc; + + float ca=cosf(angle),sa=sinf(angle); + + float t0 = v[0] * ca + v[1] * -sa; + float t1 = v[0] * sa + v[1] * ca; + + v[0] = t0 + xc; + v[1] = t1 + yc; +} + + +void DrawBuffer::DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color) { + const AtlasImage &image = atlas->images[atlas_image]; + float w = (float)image.w * scale; + float h = (float)image.h * scale; + float x1 = x - w / 2; + float x2 = x + w / 2; + float y1 = y - h / 2; + float y2 = y + h / 2; + float v[6][2] = { + {x1, y1}, + {x2, y1}, + {x2, y2}, + {x1, y1}, + {x2, y2}, + {x1, y2}, + }; + const float uv[6][2] = { + {image.u1, image.v1}, + {image.u2, image.v1}, + {image.u2, image.v2}, + {image.u1, image.v1}, + {image.u2, image.v2}, + {image.u1, image.v2}, + }; + for (int i = 0; i < 6; i++) { + rot(v[i], angle, x, y); + V(v[i][0], v[i][1], 0, color, uv[i][0], uv[i][1]); + } +} + + // TODO: add arc support void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul) { float angleDelta = PI * 2 / segments; diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 81bc503a7a..36405c15ab 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -72,6 +72,7 @@ class DrawBuffer { void MeasureImage(int atlas_image, float *w, float *h); void DrawImage(int atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT); void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); + void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF)); // Always centers void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); // Results in 18 triangles. Kind of expensive for a button. void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); diff --git a/ui/ui.cpp b/ui/ui.cpp index 623d2274bf..ec72b54ef7 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -27,17 +27,19 @@ void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int ch } void UIUpdateMouse(float x, float y, int buttons) { - if ((buttons & 1) && !uistate.mousedown) - { + if ((buttons & 1) && !uistate.mousedown) { + uistate.mousepressed = 1; uistate.mouseStartX = x; uistate.mouseStartY = y; + } else { + uistate.mousepressed = 0; } uistate.mousex = x; uistate.mousey = y; - uistate.mousedown = buttons; + uistate.mousedown = buttons & 1; } -bool regionhit(int x, int y, int w, int h, int margin) { +bool UIRegionHit(int x, int y, int w, int h, int margin) { if (uistate.mousex < x - margin || uistate.mousey < y - margin || uistate.mousex >= x + w + margin || @@ -81,7 +83,7 @@ int UIButton(int id, int x, int y, int w, const char *text, int button_align) { if (button_align & ALIGN_BOTTOMRIGHT) y -= h; // Check whether the button should be hot, use a generous margin for touch ease - if (regionhit(x, y, w, h, 8)) { + if (UIRegionHit(x, y, w, h, 8)) { uistate.hotitem = id; if (uistate.activeitem == 0 && uistate.mousedown) uistate.activeitem = id; @@ -127,7 +129,7 @@ int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { if (align & ALIGN_BOTTOMRIGHT) y -= h; // Check whether the button should be hot - if (regionhit(x, y, w, h, 8)) { + if (UIRegionHit(x, y, w, h, 8)) { uistate.hotitem = id; if (uistate.activeitem == 0 && uistate.mousedown) uistate.activeitem = id; @@ -174,7 +176,7 @@ int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListSta const int item_h = 64; // Check whether the button should be hot - if (regionhit(x, y, w, h, 0)) { + if (UIRegionHit(x, y, w, h, 0)) { uistate.hotitem = id; if (uistate.activeitem == 0 && uistate.mousedown) uistate.activeitem = id; @@ -185,7 +187,7 @@ int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListSta int numItems = adapter->getCount(); for (int i = 0; i < numItems; i++) { int item_y = y + i * itemHeight - state->scrollY; - if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h && regionhit(x, item_y, w, h, 0)) { + if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h && UIRegionHit(x, item_y, w, h, 0)) { // ultra fast touch response state->selected = i; } @@ -232,7 +234,7 @@ int UIHSlider(int id, int x, int y, int w, int max, int *value) { int xpos = ((256 - 16) * *value) / max; // Check for hotness - if (regionhit(x+8, y+8, 16, 255, 0)) { + if (UIRegionHit(x+8, y+8, 16, 255, 0)) { uistate.hotitem = id; if (uistate.activeitem == 0 && uistate.mousedown) uistate.activeitem = id; @@ -267,7 +269,7 @@ int UIVSlider(int id, int x, int y, int h, int max, int *value) { int ypos = ((256 - 16) * *value) / max; // Check for hotness - if (regionhit(x+8, y+8, 16, 255, 0)) { + if (UIRegionHit(x+8, y+8, 16, 255, 0)) { uistate.hotitem = id; if (uistate.activeitem == 0 && uistate.mousedown) uistate.activeitem = id; diff --git a/ui/ui.h b/ui/ui.h index c33ad36ee0..f41969b83b 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -27,6 +27,7 @@ struct UIState { int mousex; int mousey; int mousedown; + int mousepressed; int mouseStartX; int mouseStartY; @@ -42,6 +43,10 @@ struct UIState { // keyboard focus, not currently used int kbdwidget; int lastwidget; + + // Used by controls that need to keep track of the initial value for drags, for example. + // Should probably be indexed by finger - would be neat to be able to move two knobs at the same time. + float tempfloat; }; // This needs to be extern so that additional UI controls can be developed outside this file. @@ -96,6 +101,10 @@ struct UIListState { int selected; }; + +// Utility functions, useful when implementing your own controls +bool UIRegionHit(int x, int y, int w, int h, int margin); + // Call at start of frame void UIBegin(); From cfbc3dbbaa712f19edb537739c14b5fd76967df1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 11 Apr 2012 19:13:54 +0200 Subject: [PATCH 0022/1445] Missing include. --- ui/ui.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/ui.h b/ui/ui.h index f41969b83b..6118ebef68 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -19,6 +19,7 @@ #include "gfx_es2/draw_buffer.h" +#include #include // Mouse out of habit, applies just as well to touch events. From 97ea3356a925311ed4f58e8c002fa6092664f1a5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 11 Apr 2012 20:26:56 +0200 Subject: [PATCH 0023/1445] Minor fixes. --- .../com/turboviking/libnative/NativeActivity.java | 10 ++++++++-- gfx_es2/draw_buffer.cpp | 4 ++-- ui/ui.h | 2 +- util/bits/bits.h | 14 ++++++++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 767bb6e275..275f1af9c9 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -376,9 +376,15 @@ public class NativeActivity extends Activity { audioPlayer = null; mGLSurfaceView = null; } - + + public boolean overrideKeys() { + return true; + } + @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (!overrideKeys()) + return false; // Eat these keys, to avoid accidental exits / other screwups. // Maybe there's even more we need to eat on tablets? if (keyCode == KeyEvent.KEYCODE_BACK) { diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 5a87b86e11..af4419c936 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -280,8 +280,8 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { AtlasChar c = atlasfont.chars[cval - 32]; wacc += c.wx * fontscalex; } - *w = wacc; - *h = atlasfont.height * fontscaley * lines; + if (w) *w = wacc; + if (h) *h = atlasfont.height * fontscaley * lines; } void DrawBuffer::DrawTextShadow(int font, const char *text, float x, float y, Color color, int flags) { diff --git a/ui/ui.h b/ui/ui.h index 6118ebef68..f5cd4cc923 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -19,7 +19,7 @@ #include "gfx_es2/draw_buffer.h" -#include +#include #include // Mouse out of habit, applies just as well to touch events. diff --git a/util/bits/bits.h b/util/bits/bits.h index 5afab5a8fe..1729761e2b 100644 --- a/util/bits/bits.h +++ b/util/bits/bits.h @@ -25,4 +25,18 @@ inline uint32 ComputeParity(uint32 v) { } // namespace bits +#ifndef _MSC_VER + +// These are built-ins in MSVC, let's define them for other OS:es as well. + +inline uint32_t _rotl(uint32_t val, int shift) { + return (val << shift) | (val >> (31 - shift)); +} + +inline uint32_t _rotr(uint32_t val, int shift) { + return (val << shift) | (val >> (31 - shift)); +} + +#endif + #endif From 9684be3257e8072eeb6a88488717f010ddc6a5cf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 12:52:55 +0200 Subject: [PATCH 0024/1445] Add MIDI Input support (Windows only). --- README.md | 1 + base/PCMain.cpp | 2 +- midi/CMakeLists.txt | 12 +++++++ midi/midi_input.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++ midi/midi_input.h | 23 +++++++++++++ native.vcxproj | 2 ++ native.vcxproj.filters | 9 +++++ ui/ui.cpp | 6 +++- ui/ui.h | 3 +- 9 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 midi/CMakeLists.txt create mode 100644 midi/midi_input.cpp create mode 100644 midi/midi_input.h diff --git a/README.md b/README.md index da381e280e..0e2cd18456 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Features * basic logging * Really simple audio mixer with OGG sample support * RIFF file read/write +* MIDI Input (only on Windows) Notes ----- diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 6353922a50..2936f9cc98 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -121,7 +121,7 @@ int main(int argc, char *argv[]) { g_xres = 800; g_yres = 480; } else { - g_xres = 480; + g_xres = 1480; g_yres = 800; } diff --git a/midi/CMakeLists.txt b/midi/CMakeLists.txt new file mode 100644 index 0000000000..22f0fde28e --- /dev/null +++ b/midi/CMakeLists.txt @@ -0,0 +1,12 @@ +set(SRCS + midi_input.cpp +) + +set(SRCS ${SRCS}) + +add_library(midi STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) + diff --git a/midi/midi_input.cpp b/midi/midi_input.cpp new file mode 100644 index 0000000000..61405e7359 --- /dev/null +++ b/midi/midi_input.cpp @@ -0,0 +1,77 @@ +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "base/basictypes.h" +#include "base/logging.h" +#include "midi/midi_input.h" + + +std::vector MidiInGetDevices() { + int numDevs = midiInGetNumDevs(); + std::vector devices; + for (int i = 0; i < numDevs; i++) { + MIDIINCAPS caps; + midiInGetDevCaps(i, &caps, sizeof(caps)); + devices.push_back(caps.szPname); + } + return devices; +} + +static void CALLBACK MidiCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, + DWORD_PTR dwParam1, DWORD_PTR dwParam2) { + MidiListener *listener = (MidiListener*)dwInstance; + uint8_t cmd[3] = {0}; + + switch (wMsg) { + case MM_MIM_OPEN: + ILOG("Got MIDI Open message"); + break; + case MM_MIM_CLOSE: + ILOG("Got MIDI Close message"); + break; + case MM_MIM_DATA: + cmd[0] = dwParam2 & 0xFF; + cmd[1] = (dwParam2 >> 8) & 0xFF; + cmd[2] = (dwParam2 >> 16) & 0xFF; + ILOG("Got MIDI Data: %02x %02x %02x", cmd[0], cmd[1], cmd[2]); + listener->midiEvent(cmd); + break; + default: + WLOG("Got unexpected MIDI message: %08x", (uint32_t)wMsg); + break; + } +} + +MidiDevice MidiInStart(int deviceID, MidiListener *listener) { + HMIDIIN hMidiIn; + MMRESULT result = midiInOpen(&hMidiIn, deviceID, (DWORD_PTR)(&MidiCallback), (DWORD_PTR)listener, CALLBACK_FUNCTION); + midiInStart(hMidiIn); + return (MidiDevice)hMidiIn; +} + +void MidiInStop(MidiDevice device) { + HMIDIIN hMidiIn = (HMIDIIN)device; + midiInStop(hMidiIn); + midiInClose(hMidiIn); +} + +#else + +// Stubs for other platforms. + +std::vector MidiInGetDevices() { + return std::vector(); +} + +MidiDevice MidiInStart(int deviceID, MidiListener *listener) { + FLOG("Invalid MIDI device"); +} + +void MidiInStop(MidiDevice device) { + FLOG("Invalid MIDI device"); +} + +#endif \ No newline at end of file diff --git a/midi/midi_input.h b/midi/midi_input.h new file mode 100644 index 0000000000..ac794cc43a --- /dev/null +++ b/midi/midi_input.h @@ -0,0 +1,23 @@ +// MIDI input utilities. +// +// Currently, this is just a platform-clean wrapper around the Win32 MIDI input facilities. +// Thus, it only supports Windows. Other platforms will get an empty list of midi in devices. + +#include +#include + + +typedef void *MidiDevice; + +// Listeners inherit from this. Pass them into MidiInStart. +class MidiListener +{ +public: + virtual void midiEvent(const uint8_t *cmd); +}; + +// Gets the names of the devices in a vector. The device identifier is the index in the vector. +std::vector MidiInGetDevices(); + +MidiDevice MidiInStart(int deviceID, MidiListener *listener); +void MidiInStop(MidiDevice device); \ No newline at end of file diff --git a/native.vcxproj b/native.vcxproj index e0928be39d..867891b517 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -132,6 +132,7 @@ + @@ -175,6 +176,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index a9dc4e2a7e..2c9e258425 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -147,6 +147,9 @@ ui + + midi + @@ -263,6 +266,9 @@ ui + + midi + @@ -301,5 +307,8 @@ {d738c2d1-749d-4b60-b98f-f3da0bbbf40c} + + {4710a9a2-d1fa-4920-ba1b-a7527902be53} + \ No newline at end of file diff --git a/ui/ui.cpp b/ui/ui.cpp index ec72b54ef7..68efbb0d49 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -70,8 +70,12 @@ void UIEnd() { } void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) { + UIText(themeUIFont, x, y, text, color, scale, align); +} + +void UIText(int font, int x, int y, const char *text, uint32_t color, float scale, int align) { ui_draw2d.SetFontScale(scale, scale); - ui_draw2d.DrawTextShadow(themeUIFont, text, x, y, color, align); + ui_draw2d.DrawTextShadow(font, text, x, y, color, align); ui_draw2d.SetFontScale(1.0f, 1.0f); } diff --git a/ui/ui.h b/ui/ui.h index f5cd4cc923..83b6db1188 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -19,7 +19,7 @@ #include "gfx_es2/draw_buffer.h" -#include +#include #include // Mouse out of habit, applies just as well to touch events. @@ -127,6 +127,7 @@ int UIVSlider(int id, int x, int y, int h, int max, int *value); int UIHSlider(int id, int x, int y, int w, int max, int *value); // Draws static text, that does not participate in any focusing scheme etc, it just is. +void UIText(int font, int x, int y, const char *text, uint32_t color, float scale = 1.0f, int align = ALIGN_TOPLEFT); void UIText(int x, int y, const char *text, uint32_t color, float scale = 1.0f, int align = ALIGN_TOPLEFT); // Slide choice, like the Angry Birds level selector. Not yet working. From 0f050d50f08966364a7bb2422820ed9fe5d7e9e7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 13:22:13 +0200 Subject: [PATCH 0025/1445] Fix bugs in MIDI In --- midi/midi_input.cpp | 19 +++++++++++++++---- midi/midi_input.h | 7 +++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/midi/midi_input.cpp b/midi/midi_input.cpp index 61405e7359..20e323d33a 100644 --- a/midi/midi_input.cpp +++ b/midi/midi_input.cpp @@ -1,14 +1,17 @@ #ifdef _WIN32 +// Windows implementation. #define WIN32_LEAN_AND_MEAN #include #include +#include +#include + #include "base/basictypes.h" #include "base/logging.h" #include "midi/midi_input.h" - std::vector MidiInGetDevices() { int numDevs = midiInGetNumDevs(); std::vector devices; @@ -33,9 +36,10 @@ static void CALLBACK MidiCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstan ILOG("Got MIDI Close message"); break; case MM_MIM_DATA: - cmd[0] = dwParam2 & 0xFF; - cmd[1] = (dwParam2 >> 8) & 0xFF; - cmd[2] = (dwParam2 >> 16) & 0xFF; + cmd[0] = dwParam1 & 0xFF; + cmd[1] = (dwParam1 >> 8) & 0xFF; + cmd[2] = (dwParam1 >> 16) & 0xFF; + // time = dwParam2 & 0xFFFF; ILOG("Got MIDI Data: %02x %02x %02x", cmd[0], cmd[1], cmd[2]); listener->midiEvent(cmd); break; @@ -60,6 +64,13 @@ void MidiInStop(MidiDevice device) { #else +#include +#include + +#include "base/basictypes.h" +#include "base/logging.h" +#include "midi/midi_input.h" + // Stubs for other platforms. std::vector MidiInGetDevices() { diff --git a/midi/midi_input.h b/midi/midi_input.h index ac794cc43a..125e22f7cd 100644 --- a/midi/midi_input.h +++ b/midi/midi_input.h @@ -1,11 +1,14 @@ -// MIDI input utilities. +// MIDI input. // // Currently, this is just a platform-clean wrapper around the Win32 MIDI input facilities. // Thus, it only supports Windows. Other platforms will get an empty list of midi in devices. +#pragma once + #include #include +#include "base/basictypes.h" typedef void *MidiDevice; @@ -13,7 +16,7 @@ typedef void *MidiDevice; class MidiListener { public: - virtual void midiEvent(const uint8_t *cmd); + virtual void midiEvent(const uint8_t *cmd) = 0; }; // Gets the names of the devices in a vector. The device identifier is the index in the vector. From 2993ff1a7b296dc2cdf738e127f667812c913141 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 13:28:38 +0200 Subject: [PATCH 0026/1445] Increase buffer size to avoid drops --- base/PCMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 2936f9cc98..3517a8c90c 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -184,7 +184,7 @@ int main(int argc, char *argv[]) { fmt.freq = 44100; fmt.format = AUDIO_S16; fmt.channels = 2; - fmt.samples = 512; + fmt.samples = 1024; fmt.callback = &mixaudio; fmt.userdata = (void *)0; From 371c4db1ae2202654f0b502f9b79ba3e41d0a445 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 15:18:43 +0200 Subject: [PATCH 0027/1445] Image buttons, file dialogs (win only) --- file/CMakeLists.txt | 3 +- file/dialog.cpp | 8 +++++ file/dialog.h | 73 ++++++++++++++++++++++++++++++++++++++++++ file/file_util.cpp | 2 +- native.vcxproj | 2 ++ native.vcxproj.filters | 6 ++++ ui/ui.cpp | 44 +++++++++++++++++++++++++ 7 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 file/dialog.cpp create mode 100644 file/dialog.h diff --git a/file/CMakeLists.txt b/file/CMakeLists.txt index e0b552014a..b1d9b09122 100644 --- a/file/CMakeLists.txt +++ b/file/CMakeLists.txt @@ -2,7 +2,8 @@ set(SRCS easy_file.cpp chunk_file.cpp zip_read.cpp - file_util.cpp) + file_util.cpp + dialog.cpp) set(SRCS ${SRCS}) diff --git a/file/dialog.cpp b/file/dialog.cpp new file mode 100644 index 0000000000..c2b0565c3c --- /dev/null +++ b/file/dialog.cpp @@ -0,0 +1,8 @@ +#pragma once + +#include + +#include "file/dialog.h" + +bool OpenFileDialog(const char *title, const char *extension, std::string *filename); +bool SaveFileDialog(const char *title, const char *extension, std::string *filename); diff --git a/file/dialog.h b/file/dialog.h new file mode 100644 index 0000000000..bbf5abd252 --- /dev/null +++ b/file/dialog.h @@ -0,0 +1,73 @@ +#pragma once + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include + +// For desktop operating systems only. Stubbed out on Android. +// Simplified as this will only be used in utilities / temp code. +// An false returned means cancel; +bool OpenFileDialog(const char *title, const char *extension, std::string *filename) +{ + OPENFILENAME of; + memset(&of, 0, sizeof(of)); + char buffer[512] = {0}; + of.lStructSize = sizeof(OPENFILENAME); + of.hInstance = 0; + of.hwndOwner = GetActiveWindow(); + + of.lpstrFilter = "All files (*.*)\0*.*\0\0"; + of.lpstrDefExt = extension; + of.lpstrFile = buffer; + + of.nMaxFile = 511; + + of.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + if (!GetOpenFileName(&of)) return false; + *filename = of.lpstrFile; + return true; +} + +bool SaveFileDialog(const char *title, const char *extension, std::string *filename) +{ + OPENFILENAME of; + memset(&of, 0, sizeof(of)); + char buffer[512] = {0}; + of.lStructSize = sizeof(OPENFILENAME); + of.hInstance = 0; + of.hwndOwner = GetActiveWindow(); + + of.lpstrFilter = "All files (*.*)\0*.*\0\0"; + of.lpstrDefExt = extension; + of.lpstrFile = buffer; + + of.nMaxFile = 511; + + of.Flags = OFN_HIDEREADONLY; + if (!GetSaveFileName(&of)) + return false; + *filename = of.lpstrFile; + return true; +} + +#else + +#include +#include "base/basictypes.h" + +bool OpenFileDialog(const char *title, const char *extension, std::string *filename) +{ + ELOG("Asked for OpenFileDialog, not present on this platform."); + return false; +} + +bool SaveFileDialog(const char *title, const char *extension, std::string *filename) +{ + ELOG("Asked for SaveFileDialog, not present on this platform."); + return false; +} + +#endif \ No newline at end of file diff --git a/file/file_util.cpp b/file/file_util.cpp index f18d78a95c..4200dbc551 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -12,7 +12,7 @@ #include "file/file_util.h" #include -bool WriteStringToFile(bool text_file, const std::string &str, const char *filename) +bool writeStringToFile(bool text_file, const std::string &str, const char *filename) { FILE *f = fopen(filename, text_file ? "w" : "wb"); if (!f) diff --git a/native.vcxproj b/native.vcxproj index 867891b517..39ef385443 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -107,6 +107,7 @@ + @@ -155,6 +156,7 @@ true + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 2c9e258425..fa24d4ac78 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -150,6 +150,9 @@ midi + + file + @@ -269,6 +272,9 @@ midi + + file + diff --git a/ui/ui.cpp b/ui/ui.cpp index 68efbb0d49..e4a8b50217 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -122,6 +122,50 @@ int UIButton(int id, int x, int y, int w, const char *text, int button_align) { return clicked; } +int UIImageButton(int id, int x, int y, int w, int image, int button_align) { + const int h = 64; + if (button_align & ALIGN_HCENTER) x -= w / 2; + if (button_align & ALIGN_VCENTER) y -= h / 2; + if (button_align & ALIGN_RIGHT) x -= w; + if (button_align & ALIGN_BOTTOMRIGHT) y -= h; + + // Check whether the button should be hot, use a generous margin for touch ease + if (UIRegionHit(x, y, w, h, 8)) { + uistate.hotitem = id; + if (uistate.activeitem == 0 && uistate.mousedown) + uistate.activeitem = id; + } + + // Render button + + int txOffset = 0; + if (uistate.hotitem == id) { + if (uistate.activeitem == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); + ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); + + int clicked = 0; + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown == 0 && + uistate.hotitem == id && + uistate.activeitem == id) { + clicked = 1; + } + + uistate.lastwidget = id; + return clicked; +} + + int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { const int h = 64; float tw, th; From 3ca42c11a69e3bd6866796484ae27d63d7f0c858 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 15:39:12 +0200 Subject: [PATCH 0028/1445] Fix file dialog code --- file/dialog.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++--- file/dialog.h | 71 +++---------------------------------------- 2 files changed, 81 insertions(+), 71 deletions(-) diff --git a/file/dialog.cpp b/file/dialog.cpp index c2b0565c3c..e662030885 100644 --- a/file/dialog.cpp +++ b/file/dialog.cpp @@ -1,8 +1,81 @@ -#pragma once +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include #include -#include "file/dialog.h" +// For desktop operating systems only. Stubbed out on Android. +// Simplified as this will only be used in utilities / temp code. +// An false returned means cancel; +bool OpenFileDialog(const char *title, const char *extension, std::string *filename) +{ + OPENFILENAME of; + memset(&of, 0, sizeof(of)); + char buffer[512] = {0}; + of.lStructSize = sizeof(OPENFILENAME); + of.hInstance = 0; + of.hwndOwner = GetActiveWindow(); -bool OpenFileDialog(const char *title, const char *extension, std::string *filename); -bool SaveFileDialog(const char *title, const char *extension, std::string *filename); + // These weird strings with zeroes in them can't be dealt with using normal string + // functions, so here we go - evil hackery. + char filter[256] = "XXX files\0*.XXX\0\0"; + memcpy(filter, extension, 3); + memcpy(filter + 12, extension, 3); + of.lpstrFilter = filter; + + of.lpstrDefExt = extension; + of.lpstrFile = buffer; + of.nMaxFile = 511; + + of.Flags = OFN_FILEMUSTEXIST; + if (!GetOpenFileName(&of)) return false; + *filename = of.lpstrFile; + return true; +} + +bool SaveFileDialog(const char *title, const char *extension, std::string *filename) +{ + OPENFILENAME of; + memset(&of, 0, sizeof(of)); + char buffer[512] = {0}; + of.lStructSize = sizeof(OPENFILENAME); + of.hInstance = 0; + of.hwndOwner = GetActiveWindow(); + + // These weird strings with zeroes in them can't be dealt with using normal string + // functions, so here we go - evil hackery. + char filter[256] = "XXX files\0*.XXX\0\0"; + memcpy(filter, extension, 3); + memcpy(filter + 12, extension, 3); + of.lpstrFilter = filter; + + of.lpstrDefExt = extension; + of.lpstrFile = buffer; + of.nMaxFile = 511; + + of.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; + if (!GetSaveFileName(&of)) + return false; + *filename = of.lpstrFile; + return true; +} + +#else + +#include +#include "base/basictypes.h" + +bool OpenFileDialog(const char *title, const char *extension, std::string *filename) +{ + ELOG("Asked for OpenFileDialog, not present on this platform."); + return false; +} + +bool SaveFileDialog(const char *title, const char *extension, std::string *filename) +{ + ELOG("Asked for SaveFileDialog, not present on this platform."); + return false; +} + +#endif \ No newline at end of file diff --git a/file/dialog.h b/file/dialog.h index bbf5abd252..018b503e70 100644 --- a/file/dialog.h +++ b/file/dialog.h @@ -1,73 +1,10 @@ #pragma once -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include +#pragma once #include -// For desktop operating systems only. Stubbed out on Android. -// Simplified as this will only be used in utilities / temp code. -// An false returned means cancel; -bool OpenFileDialog(const char *title, const char *extension, std::string *filename) -{ - OPENFILENAME of; - memset(&of, 0, sizeof(of)); - char buffer[512] = {0}; - of.lStructSize = sizeof(OPENFILENAME); - of.hInstance = 0; - of.hwndOwner = GetActiveWindow(); +#include "file/dialog.h" - of.lpstrFilter = "All files (*.*)\0*.*\0\0"; - of.lpstrDefExt = extension; - of.lpstrFile = buffer; - - of.nMaxFile = 511; - - of.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; - if (!GetOpenFileName(&of)) return false; - *filename = of.lpstrFile; - return true; -} - -bool SaveFileDialog(const char *title, const char *extension, std::string *filename) -{ - OPENFILENAME of; - memset(&of, 0, sizeof(of)); - char buffer[512] = {0}; - of.lStructSize = sizeof(OPENFILENAME); - of.hInstance = 0; - of.hwndOwner = GetActiveWindow(); - - of.lpstrFilter = "All files (*.*)\0*.*\0\0"; - of.lpstrDefExt = extension; - of.lpstrFile = buffer; - - of.nMaxFile = 511; - - of.Flags = OFN_HIDEREADONLY; - if (!GetSaveFileName(&of)) - return false; - *filename = of.lpstrFile; - return true; -} - -#else - -#include -#include "base/basictypes.h" - -bool OpenFileDialog(const char *title, const char *extension, std::string *filename) -{ - ELOG("Asked for OpenFileDialog, not present on this platform."); - return false; -} - -bool SaveFileDialog(const char *title, const char *extension, std::string *filename) -{ - ELOG("Asked for SaveFileDialog, not present on this platform."); - return false; -} - -#endif \ No newline at end of file +bool OpenFileDialog(const char *title, const char *extension, std::string *filename); +bool SaveFileDialog(const char *title, const char *extension, std::string *filename); From 3f40c740e2044ff232b5027c00a17cce8c3ce66b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 17:26:56 +0200 Subject: [PATCH 0029/1445] Make vjson look in the local file system if it can't find it in the VFS. --- ext/vjson/json.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ext/vjson/json.cpp b/ext/vjson/json.cpp index cc6dfd5ed7..81dea38070 100644 --- a/ext/vjson/json.cpp +++ b/ext/vjson/json.cpp @@ -3,6 +3,8 @@ #include #include "json.h" #include "file/easy_file.h" +#include "file/zip_read.h" +#include "file/vfs.h" // true if character represent a digit #define IS_DIGIT(c) (c >= '0' && c <= '9') @@ -615,6 +617,12 @@ JsonReader::JsonReader(const std::string &filename) : alloc_(1 << 12), root_(0) if (buffer_) { parse(); } else { - ELOG("Failed to read json %s", filename.c_str()); + // Okay, try to read on the local file system + buffer_ = (char *)ReadLocalFile(filename.c_str(), &buf_size); + if (buffer_) { + parse(); + } else { + ELOG("Failed to read json %s", filename.c_str()); + } } } From 95f09bf393abc346861834a466547cf2d1ab4e90 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 17:31:00 +0200 Subject: [PATCH 0030/1445] Add stub that detects the OS version --- android/src/com/turboviking/libnative/NativeActivity.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 275f1af9c9..37e7c9dba9 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -27,6 +27,7 @@ import android.media.AudioManager; import android.media.AudioTrack; import android.net.Uri; import android.opengl.GLSurfaceView; +import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.util.Log; @@ -332,6 +333,10 @@ public class NativeActivity extends Activity { mGLSurfaceView = new NativeGLView(this); mGLSurfaceView.setRenderer(new NativeRenderer(this)); setContentView(mGLSurfaceView); + if (Build.VERSION.SDK_INT >= 9) { + // Native OpenSL is available. Let's not use the Java player in the future. + // TODO: code for that. + } audioPlayer = new NativeAudioPlayer(); } From 7772433257b0a85166c1a4989551a55f2fc4f96c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 17:46:02 +0200 Subject: [PATCH 0031/1445] Floats may look like ints in json. --- ext/vjson/json.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ext/vjson/json.cpp b/ext/vjson/json.cpp index 81dea38070..a08d2ba60f 100644 --- a/ext/vjson/json.cpp +++ b/ext/vjson/json.cpp @@ -81,8 +81,13 @@ float json_value::getFloat(const char *child_name) const { float json_value::getFloat(const char *child_name, float default_value) const { const json_value *val = get(child_name, JSON_FLOAT); - if (!val) - return default_value; + if (!val) { + // Let's try int. + val = get(child_name, JSON_INT); + if (!val) + return default_value; + return val->int_value; + } return val->float_value; } From 8656ec051c40e7e00e8dde1eb99127e7612cc04e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 19:45:21 +0200 Subject: [PATCH 0032/1445] LayoutManager --- ui/ui.cpp | 15 +++++++++++---- ui/ui.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index e4a8b50217..402d3b8bc6 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -79,8 +79,12 @@ void UIText(int font, int x, int y, const char *text, uint32_t color, float scal ui_draw2d.SetFontScale(1.0f, 1.0f); } -int UIButton(int id, int x, int y, int w, const char *text, int button_align) { - const int h = 64; +int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align) { + float h = themeAtlas->images[themeButtonImage].h; + + float x, y; + layout.GetPos(&w, &h, &x, &y); + if (button_align & ALIGN_HCENTER) x -= w / 2; if (button_align & ALIGN_VCENTER) y -= h / 2; if (button_align & ALIGN_RIGHT) x -= w; @@ -122,8 +126,11 @@ int UIButton(int id, int x, int y, int w, const char *text, int button_align) { return clicked; } -int UIImageButton(int id, int x, int y, int w, int image, int button_align) { - const int h = 64; +int UIImageButton(int id, const LayoutManager &layout, float w, int image, int button_align) { + float h = 64; + float x, y; + layout.GetPos(&w, &h, &x, &y); + if (button_align & ALIGN_HCENTER) x -= w / 2; if (button_align & ALIGN_VCENTER) y -= h / 2; if (button_align & ALIGN_RIGHT) x -= w; diff --git a/ui/ui.h b/ui/ui.h index 83b6db1188..4eddbbfbf5 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -13,8 +13,10 @@ // multiple parts of a single screen of UI over multiple files unless you use IMGUI_SRC_ID. #ifdef IMGUI_SRC_ID #define GEN_ID ((IMGUI_SRC_ID) + (__LINE__)) +#define GEN_ID_LOOP(i) ((IMGUI_SRC_ID) + (__LINE__) + (i) * 1000) #else #define GEN_ID (__LINE__) +#define GEN_ID_LOOP(i) ((__LINE__) + (i) * 1000) #endif #include "gfx_es2/draw_buffer.h" @@ -22,6 +24,54 @@ #include #include + +class LayoutManager { +public: + virtual void GetPos(float *w, float *h, float *x, float *y) const = 0; +}; + +class Pos : public LayoutManager { +public: + Pos(float x, float y) : x_(x), y_(y) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + } +private: + float x_; + float y_; +}; + +class HLinear : public LayoutManager { +public: + HLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + x_ += *w + spacing_; + } + +private: + mutable float x_; + float y_; + float spacing_; +}; + +class VLinear : public LayoutManager { +public: + VLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + y_ += *h + spacing_; + } + +private: + float x_; + mutable float y_; + float spacing_; +}; + // Mouse out of habit, applies just as well to touch events. // UI does not yet support multitouch. struct UIState { @@ -112,14 +162,12 @@ void UIBegin(); void UIUpdateMouse(float x, float y, int buttons); // Returns 1 if clicked -int UIButton(int id, int x, int y, int w, const char *text, int button_align); +int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align); +int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images. // Returns 1 if clicked, puts the value in *value (where it also gets the current state). int UICheckBox(int id, int x, int y, const char *text, int align, bool *value); -// Just like a button, but with an image, doh. -int UIImageButton(int id, int x, int y, int w, int image_id, int button_align); // uses current UI atlas for fetching images. - // Vertical slider. Not yet working. int UIVSlider(int id, int x, int y, int h, int max, int *value); From 35ed4e02d1d4bab4f31ce9f03ceb887a79a03d0c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 22:16:30 +0200 Subject: [PATCH 0033/1445] Add front drawing layer for UI --- ui/ui.cpp | 8 ++++++-- ui/ui.h | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index 402d3b8bc6..c50d5b1655 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -8,6 +8,7 @@ #include "gfx_es2/draw_buffer.h" DrawBuffer ui_draw2d; +DrawBuffer ui_draw2d_front; UIState uistate; // Theme. @@ -18,7 +19,8 @@ static int themeCheckOnImage; static int themeCheckOffImage; void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int checkOff) { - ui_draw2d.SetAtlas(atlas); + ui_draw2d.SetAtlas(atlas); + ui_draw2d_front.SetAtlas(atlas); themeAtlas = atlas; themeUIFont = uiFont; themeButtonImage = buttonImage; @@ -53,6 +55,7 @@ bool UIRegionHit(int x, int y, int w, int h, int margin) { void UIBegin() { uistate.hotitem = 0; ui_draw2d.Begin(); + ui_draw2d_front.Begin(); } void UIEnd() { @@ -63,7 +66,8 @@ void UIEnd() { uistate.activeitem = -1; } } - ui_draw2d.End(); + ui_draw2d.End(); + ui_draw2d_front.End(); uistate.lastx = uistate.mousex; uistate.lasty = uistate.mousey; diff --git a/ui/ui.h b/ui/ui.h index 4eddbbfbf5..70976de9be 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -108,6 +108,7 @@ struct Atlas; // This is the drawbuffer used for UI. Remember to flush it at the end of the frame. // TODO: One should probably pass it in through UIInit. extern DrawBuffer ui_draw2d; +extern DrawBuffer ui_draw2d_front; // for things that need to be on top of the rest void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int checkOff); @@ -189,4 +190,6 @@ int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListSta // Do this afterwards (or similar): // ShaderManager::SetUIProgram(); // ui_draw2d.Flush(ShaderManager::Program()); +// ui_draw2d_front.Flush(ShaderManager::Program()); + void UIEnd(); From dee2062012ce3803fbabd284821a5eafda3da7cc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 22:56:39 +0200 Subject: [PATCH 0034/1445] Increase size of drawbuffer buffer. --- gfx_es2/draw_buffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index af4419c936..ac4b323bf6 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -20,7 +20,7 @@ enum { // Enough? - MAX_VERTS = 5000, + MAX_VERTS = 15000, }; DrawBuffer::DrawBuffer() : count_(0) { From 34f5b7abb323d4b802836e71520e121245e4165a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Apr 2012 23:19:44 +0200 Subject: [PATCH 0035/1445] naive improvement of ID generation --- file/dialog.cpp | 1 + ui/ui.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/file/dialog.cpp b/file/dialog.cpp index e662030885..f67d90ef2e 100644 --- a/file/dialog.cpp +++ b/file/dialog.cpp @@ -65,6 +65,7 @@ bool SaveFileDialog(const char *title, const char *extension, std::string *filen #include #include "base/basictypes.h" +#include "base/logging.h" bool OpenFileDialog(const char *title, const char *extension, std::string *filename) { diff --git a/ui/ui.h b/ui/ui.h index 70976de9be..9a101f0c12 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -13,10 +13,10 @@ // multiple parts of a single screen of UI over multiple files unless you use IMGUI_SRC_ID. #ifdef IMGUI_SRC_ID #define GEN_ID ((IMGUI_SRC_ID) + (__LINE__)) -#define GEN_ID_LOOP(i) ((IMGUI_SRC_ID) + (__LINE__) + (i) * 1000) +#define GEN_ID_LOOP(i) ((IMGUI_SRC_ID) + (__LINE__) + (i) * 13612) #else #define GEN_ID (__LINE__) -#define GEN_ID_LOOP(i) ((__LINE__) + (i) * 1000) +#define GEN_ID_LOOP(i) ((__LINE__) + (i) * 13612) #endif #include "gfx_es2/draw_buffer.h" From a9087ea47ce1de4ffa22d13fff80e1a86a32772e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 13 Apr 2012 12:17:01 +0200 Subject: [PATCH 0036/1445] Buildfix --- android/AndroidManifest.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index d2dd97c058..cd288649c3 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -7,8 +7,7 @@ + android:icon="@drawable/ic_launcher" > \ No newline at end of file From dccb7bafdd78cac8a51ac4e69b211dd05a0cfb71 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 14 Apr 2012 07:39:22 +0200 Subject: [PATCH 0037/1445] Bugfixes --- android/app-android.cpp | 4 ++-- android/src/com/turboviking/libnative/NativeActivity.java | 4 ++-- file/zip_read.cpp | 2 +- file/zip_read.h | 8 ++++++++ ui/ui.cpp | 3 ++- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index b6fb8f0a0d..ce31495304 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -122,12 +122,12 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown (JNIEnv *, jclass) { - ILOG("RollerBallMainShutdown - calling NativeShutdown."); + ILOG("NativeShutdown."); if (renderer_inited) { NativeShutdownGraphics(); } NativeShutdown(); - ILOG("RollerBallMainShutdown - calling VFSShutdown."); + ILOG("VFSShutdown."); VFSShutdown(); } diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 37e7c9dba9..f30c8dc9af 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -275,7 +275,6 @@ public class NativeActivity extends Activity { // Adjust these as necessary private static String TAG = "NativeActivity"; - String packageName = "com.turboviking.rollerball"; // Graphics and audio interfaces private GLSurfaceView mGLSurfaceView; @@ -300,6 +299,7 @@ public class NativeActivity extends Activity { // Get system information ApplicationInfo appInfo = null; PackageManager packMgmr = getPackageManager(); + String packageName = getPackageName(); try { appInfo = packMgmr.getApplicationInfo(packageName, 0); } catch (NameNotFoundException e) { @@ -344,7 +344,7 @@ public class NativeActivity extends Activity { ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); ConfigurationInfo info = am.getDeviceConfigurationInfo(); return info.reqGlEsVersion >= 0x20000; - } + } @Override diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 71b6e2617f..04869154f5 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -106,7 +106,7 @@ static int num_entries = 0; void VFSRegister(const char *prefix, AssetReader *reader) { entries[num_entries].prefix = prefix; entries[num_entries].reader = reader; - ILOG("Registered VFS for %s", prefix); + ILOG("Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); num_entries++; } diff --git a/file/zip_read.h b/file/zip_read.h index 33c0752cdc..d42d1fec77 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -5,6 +5,7 @@ #endif #include +#include #include "base/basictypes.h" #include "file/vfs.h" @@ -16,6 +17,7 @@ class AssetReader { public: // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; + virtual std::string toString() const = 0; }; #ifndef _WIN32 @@ -26,6 +28,9 @@ public: ~ZipAssetReader(); // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size); + virtual std::string toString() const { + return in_zip_path_; + } private: zip *zip_file_; @@ -40,6 +45,9 @@ public: } // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size); + virtual std::string toString() const { + return path_; + } private: char path_[512]; diff --git a/ui/ui.cpp b/ui/ui.cpp index c50d5b1655..fb20b6a0b6 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -160,8 +160,9 @@ int UIImageButton(int id, const LayoutManager &layout, float w, int image, int b } else { // button is not hot, but it may be active } + ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); - ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); + ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); int clicked = 0; // If button is hot and active, but mouse button is not From bc3f6ee57a90375040b0ecd438e50f6065366db9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 16 Apr 2012 00:35:11 +0200 Subject: [PATCH 0038/1445] Buildfix --- base/CMakeLists.txt | 3 ++- base/PCMain.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index ab9db52bed..2c4d0c99aa 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -1,7 +1,8 @@ set(SRCS LAMEString.cpp colorutil.cpp - error_context.cpp) + error_context.cpp + display.cpp) set(SRCS ${SRCS}) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 3517a8c90c..8ad3ebd509 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -6,6 +6,8 @@ #include #include #include +#else +#include #endif #include @@ -169,7 +171,7 @@ int main(int argc, char *argv[]) { #else // Mac - what about linux? Also, ugly hardcoding. const char *path = getenv("HOME"); - if (!homeDir) { + if (!path) { struct passwd* pwd = getpwuid(getuid()); if (pwd) path = pwd->pw_dir; From 45846e4c95da5082e88db1a6371eb73324aad604 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 16 Apr 2012 23:30:13 +0200 Subject: [PATCH 0039/1445] Keyboard support prep --- android/app-android.cpp | 5 +++++ base/NativeApp.h | 1 + base/PCMain.cpp | 4 ++++ native.vcxproj | 4 ++++ native.vcxproj.filters | 3 +++ 5 files changed, 17 insertions(+) diff --git a/android/app-android.cpp b/android/app-android.cpp index ce31495304..b6c4257c02 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -40,6 +40,11 @@ void ShowAd(int x, int y, bool center_x) { ELOG("TODO! ShowAd!"); } +void ShowKeyboard() { + frameCommand = "showkeyboard"; + frameCommandParam = ""; +} + void Vibrate(int length_ms) { frameCommand = "vibrate"; frameCommandParam = "100"; diff --git a/base/NativeApp.h b/base/NativeApp.h index d19eee64bb..b66667302e 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -55,6 +55,7 @@ void NativeShutdown(); // These APIs must be implemented by every port (for example app-android.cpp, PCMain.cpp). // You are free to call these. void SystemToast(const char *text); +void ShowKeyboard(); void ShowAd(int x, int y, bool center_x); void Vibrate(int length_ms); void LaunchBrowser(const char *url); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 3517a8c90c..71ce4bc511 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -34,6 +34,10 @@ void ShowAd(int x, int y, bool center_x) { // Ignore ads on PC } +void ShowKeyboard() { + // Irrelevant on PC +} + void Vibrate(int length_ms) { // Ignore on PC } diff --git a/native.vcxproj b/native.vcxproj index 39ef385443..4420e3028b 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -138,6 +138,10 @@ + + true + true + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index fa24d4ac78..99c577b707 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -275,6 +275,9 @@ file + + base + From 71a266fa2f4a0047fc12b5d1a5e6ab82ae781818 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 17 Apr 2012 23:14:03 +0200 Subject: [PATCH 0040/1445] Mutex. start work on keyboard support --- .../turboviking/libnative/NativeActivity.java | 4 ++ base/mutex.h | 66 +++++++++++++++++++ native.vcxproj | 1 + native.vcxproj.filters | 3 + 4 files changed, 74 insertions(+) create mode 100644 base/mutex.h diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index f30c8dc9af..9625856850 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -36,6 +36,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Window; import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; import android.widget.Toast; class NativeRenderer implements GLSurfaceView.Renderer { @@ -457,6 +458,9 @@ public class NativeActivity extends Activity { } else if (command.equals("toast")) { Toast toast = Toast.makeText(this, params, 2000); toast.show(); + } else if (command.equals("showkeyboard")) { + InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.toggleSoftInputFromWindow(this, InputMethodManager.SHOW_FORCED, 0); } else { Log.e(TAG, "Unsupported command " + command + " , param: " + params); } diff --git a/base/mutex.h b/base/mutex.h new file mode 100644 index 0000000000..6fe7dc79bc --- /dev/null +++ b/base/mutex.h @@ -0,0 +1,66 @@ +#pragma once +// Simple cross platform mutex implementation. +// Similar to the new C++11 api. +// Windows and pthreads implementations in one. + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#include +#endif + + +class recursive_mutex { +#ifdef _WIN32 + typedef CRITICAL_SECTION mutexType; +#else + typedef pthread_mutex_t mutexType; +#endif +public: + recursive_mutex() { +#ifdef _WIN32 + InitializeCriticalSection(&mut_); +#else + pthread_mutex_init(&mut_, NULL); +#endif + } + ~recursive_mutex() { +#ifdef _WIN32 + DeleteCriticalSection(&mut_); +#else + pthread_mutex_destroy(&mut_); +#endif + } + bool trylock() { +#ifdef _WIN32 + return TryEnterCriticalSection(&mut_) == TRUE; +#else + return pthread_mutex_trylock(&mut_) != EBUSY; +#endif + } + void lock() { +#ifdef _WIN32 + EnterCriticalSection(&mut_); +#else + pthread_mutex_lock(&mut_); +#endif + } + void unlock() { +#ifdef _WIN32 + LeaveCriticalSection(&mut_); +#else + pthread_mutex_unlock(&mut_); +#endif + } + +private: + mutexType mut_; +}; + +// TODO +class event { +public: + +}; \ No newline at end of file diff --git a/native.vcxproj b/native.vcxproj index 4420e3028b..df5929eb76 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -95,6 +95,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 99c577b707..82845e359b 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -153,6 +153,9 @@ file + + base + From 5616ba99f01c92119376b6593e6ae44096aaa877 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 18 Apr 2012 00:22:32 +0200 Subject: [PATCH 0041/1445] add lock_guard --- base/mutex.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index 6fe7dc79bc..e80cfa23ec 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -59,8 +59,10 @@ private: mutexType mut_; }; -// TODO -class event { +class lock_guard { public: - + lock_guard(recursive_mutex &mtx) : mtx_(mtx) {mtx_.lock();} + ~lock_guard() {mtx_.unlock();} +private: + recursive_mutex &mtx_; }; \ No newline at end of file From fe1c7d2cdf713bc81964eff8eac4d106dbe38ebb Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 27 Apr 2012 00:48:30 +0200 Subject: [PATCH 0042/1445] Add initial multitouch support --- android/app-android.cpp | 23 +- .../turboviking/libnative/NativeActivity.java | 199 +---------- .../com/turboviking/libnative/NativeApp.java | 4 +- .../libnative/NativeAudioPlayer.java | 95 +++++ .../turboviking/libnative/NativeGLView.java | 91 +++++ .../turboviking/libnative/NativeRenderer.java | 56 +++ base/LAMEString.cpp | 16 +- base/PCMain.cpp | 16 +- base/basictypes.h | 4 - base/logging.h | 4 - base/mutex.h | 11 +- base/stringutil.h | 4 + file/file_util.cpp | 2 +- input/gesture_detector.cpp | 6 +- input/input_state.h | 32 +- ui/ui.cpp | 335 +++++++++--------- ui/ui.h | 31 +- 17 files changed, 507 insertions(+), 422 deletions(-) create mode 100644 android/src/com/turboviking/libnative/NativeAudioPlayer.java create mode 100644 android/src/com/turboviking/libnative/NativeGLView.java create mode 100644 android/src/com/turboviking/libnative/NativeRenderer.java diff --git a/android/app-android.cpp b/android/app-android.cpp index b6c4257c02..21d3298614 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -199,15 +199,24 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* en } extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch - (JNIEnv *, jclass, int x, int y, int code) { - // This really does require locking :/ - input_state.mouse_valid = false; - input_state.mouse_x = x; - input_state.mouse_y = y; + (JNIEnv *, jclass, float x, float y, int code, int pointerId) { + lock_guard guard(input_state.lock); + if (pointerId >= MAX_POINTERS) + { + ELOG("Too many pointers: %i", pointerId); + return; // We ignore 8+ pointers entirely. + } + + input_state.mouse_x[pointerId] = (int)x; + input_state.mouse_y[pointerId] = (int)y; if (code == 1) { - input_state.mouse_buttons = 1; + ILOG("Down: %i %f %f", pointerId, x, y); + input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; + input_state.mouse_down[pointerId] = true; } else if (code == 2) { - input_state.mouse_buttons = 0; + ILOG("Up: %i %f %f", pointerId, x, y); + input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; + input_state.mouse_down[pointerId] = false; } input_state.mouse_valid = true; } diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 9625856850..7a2bc9b6f8 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -39,202 +39,7 @@ import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.Toast; -class NativeRenderer implements GLSurfaceView.Renderer { - private static String TAG = "RollerballRenderer"; - NativeActivity mActivity; - - NativeRenderer(NativeActivity act) { - mActivity = act; - } - - @Override - public void onSurfaceCreated(GL10 unused, EGLConfig config) { - Log.i(TAG, "onSurfaceCreated"); - displayInit(); - } - - @Override - public void onDrawFrame(GL10 unused /*use GLES20*/) { - displayRender(); - } - - @Override - public void onSurfaceChanged(GL10 unused, int width, int height) { - Log.i(TAG, "onSurfaceChanged"); - displayResize(width, height); - } - - - // NATIVE METHODS - public native void displayInit(); - // Note: This also means "device lost" and you should reload - // all buffered objects. - public native void displayResize(int w, int h); - public native void displayRender(); - - // called by the C++ code through JNI. Dispatch anything we can't directly handle - // on the gfx thread to the UI thread. - public void postCommand(String command, String parameter) { - final String cmd = command; - final String param = parameter; - mActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - NativeRenderer.this.mActivity.processCommand(cmd, param); - } - }); - } -} - -// Touch- and sensor-enabled GLSurfaceView. -class NativeGLView extends GLSurfaceView implements SensorEventListener { - private static String TAG = "NativeGLView"; - private SensorManager mSensorManager; - private Sensor mAccelerometer; - - public NativeGLView(NativeActivity activity) { - super(activity); - setEGLContextClientVersion(2); - // setEGLConfigChooser(5, 5, 5, 0, 16, 0); - // setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); - mSensorManager = (SensorManager)activity.getSystemService(Activity.SENSOR_SERVICE); - mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - } - - // This needs fleshing out. A lot. - // Going to want multitouch eventually. - public boolean onTouchEvent(final MotionEvent event) { - int code = 0; - if (event.getAction() == MotionEvent.ACTION_DOWN) { - code = 1; - } else if (event.getAction() == MotionEvent.ACTION_UP) { - code = 2; - } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - code = 3; - } else { - return true; - } - NativeApp.touch((int)event.getRawX(), (int)event.getRawY(), code); - return true; - } - - // Sensor management - @Override - public void onAccuracyChanged(Sensor sensor, int arg1) { - Log.i(TAG, "onAccuracyChanged"); - } - - @Override - public void onSensorChanged(SensorEvent event) { - if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) { - return; - } - // Can also look at event.timestamp for accuracy magic - NativeApp.accelerometer(event.values[0], event.values[1], event.values[2]); - } - - @Override - public void onPause() { - super.onPause(); - mSensorManager.unregisterListener(this); - } - - @Override - public void onResume() { - super.onResume(); - mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); - } -} - - -class NativeAudioPlayer { - private String TAG = "NativeAudioPlayer"; - private Thread thread; - private boolean playing_; - - // Calling stop() is allowed at any time, whether stopped or not. - // If playing, blocks until not. - public synchronized void stop() { - if (thread != null) { - waitUntilDone(); - } else { - Log.e(TAG, "Was already stopped"); - } - } - - // If not playing, make sure we're playing. - public synchronized void play() { - if (thread == null) { - playStreaming(); - } else { - Log.e(TAG, "Was already playing"); - } - } - - private void playStreaming() { - playing_ = true; - thread = new Thread(new Runnable() { - public void run() { - playThread(); - } - }); - thread.start(); - } - - private void waitUntilDone() { - if (!playing_) { - Log.i(TAG, "not playing."); - } - try { - playing_ = false; - Log.e(TAG, "waitUntilDone: Joining audio thread."); - thread.join(); - } catch (InterruptedException e) { - Log.e(TAG, "INterrupted!"); - e.printStackTrace(); - } - thread = null; - Log.i(TAG, "Finished waitUntilDone"); - } - - private void playThread() { - try { - Log.i(TAG, "Thread started."); - // Get the smallest possible buffer size (which is annoyingly huge). - int buffer_size_bytes = AudioTrack.getMinBufferSize( - 44100, - AudioFormat.CHANNEL_CONFIGURATION_STEREO, - AudioFormat.ENCODING_PCM_16BIT); - - // Round buffer_size_bytes up to an even multiple of 128 for convenience. - buffer_size_bytes = (buffer_size_bytes + 127) & ~127; - - AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, - 44100, - AudioFormat.CHANNEL_CONFIGURATION_STEREO, - AudioFormat.ENCODING_PCM_16BIT, - buffer_size_bytes, - AudioTrack.MODE_STREAM); - - int buffer_size = buffer_size_bytes / 2; - short [] buffer = new short[buffer_size]; - audioTrack.play(); - Log.i(TAG, "Playing... minBuffersize = " + buffer_size); - while (playing_) { - NativeApp.audioRender(buffer); - audioTrack.write(buffer, 0, buffer_size); - } - audioTrack.stop(); - audioTrack.release(); - Log.i(TAG, "Stopped playing."); - } catch (Throwable t) { - Log.e(TAG, "Playback Failed"); - t.printStackTrace(); - Log.e(TAG, t.toString()); - } - } -} class Installation { private static String sID = null; @@ -459,8 +264,8 @@ public class NativeActivity extends Activity { Toast toast = Toast.makeText(this, params, 2000); toast.show(); } else if (command.equals("showkeyboard")) { - InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); - inputMethodManager.toggleSoftInputFromWindow(this, InputMethodManager.SHOW_FORCED, 0); + //InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + //inputMethodManager.toggleSoftInputFromWindow(this, InputMethodManager.SHOW_FORCED, 0); } else { Log.e(TAG, "Unsupported command " + command + " , param: " + params); } diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/turboviking/libnative/NativeApp.java index 51b9654a59..b15e981451 100644 --- a/android/src/com/turboviking/libnative/NativeApp.java +++ b/android/src/com/turboviking/libnative/NativeApp.java @@ -14,6 +14,6 @@ public class NativeApp { public static native void audioRender(short [] buffer); // Sensor/input data. These are asynchronous, beware! - public static native void touch(int x, int y, int data); + public static native void touch(float x, float y, int data, int pointerId); public static native void accelerometer(float x, float y, float z); -} \ No newline at end of file +} \ No newline at end of file diff --git a/android/src/com/turboviking/libnative/NativeAudioPlayer.java b/android/src/com/turboviking/libnative/NativeAudioPlayer.java new file mode 100644 index 0000000000..d12c6447c4 --- /dev/null +++ b/android/src/com/turboviking/libnative/NativeAudioPlayer.java @@ -0,0 +1,95 @@ +package com.turboviking.libnative; + +import android.media.AudioFormat; +import android.media.AudioManager; +import android.media.AudioTrack; +import android.util.Log; + + +public class NativeAudioPlayer { + private String TAG = "NativeAudioPlayer"; + private Thread thread; + private boolean playing_; + + // Calling stop() is allowed at any time, whether stopped or not. + // If playing, blocks until not. + public synchronized void stop() { + if (thread != null) { + waitUntilDone(); + } else { + Log.e(TAG, "Was already stopped"); + } + } + + // If not playing, make sure we're playing. + public synchronized void play() { + if (thread == null) { + playStreaming(); + } else { + Log.e(TAG, "Was already playing"); + } + } + + private void playStreaming() { + playing_ = true; + thread = new Thread(new Runnable() { + public void run() { + playThread(); + } + }); + thread.start(); + } + + private void waitUntilDone() { + if (!playing_) { + Log.i(TAG, "not playing."); + } + try { + playing_ = false; + Log.e(TAG, "waitUntilDone: Joining audio thread."); + thread.join(); + } catch (InterruptedException e) { + Log.e(TAG, "INterrupted!"); + e.printStackTrace(); + } + thread = null; + Log.i(TAG, "Finished waitUntilDone"); + } + + private void playThread() { + try { + Log.i(TAG, "Thread started."); + // Get the smallest possible buffer size (which is annoyingly huge). + int buffer_size_bytes = AudioTrack.getMinBufferSize( + 44100, + AudioFormat.CHANNEL_CONFIGURATION_STEREO, + AudioFormat.ENCODING_PCM_16BIT); + + // Round buffer_size_bytes up to an even multiple of 128 for convenience. + buffer_size_bytes = (buffer_size_bytes + 127) & ~127; + + AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, + 44100, + AudioFormat.CHANNEL_CONFIGURATION_STEREO, + AudioFormat.ENCODING_PCM_16BIT, + buffer_size_bytes, + AudioTrack.MODE_STREAM); + + int buffer_size = buffer_size_bytes / 2; + short [] buffer = new short[buffer_size]; + audioTrack.play(); + Log.i(TAG, "Playing... minBuffersize = " + buffer_size); + while (playing_) { + NativeApp.audioRender(buffer); + audioTrack.write(buffer, 0, buffer_size); + } + audioTrack.stop(); + audioTrack.release(); + Log.i(TAG, "Stopped playing."); + } catch (Throwable t) { + Log.e(TAG, "Playback Failed"); + t.printStackTrace(); + Log.e(TAG, t.toString()); + } + } +} \ No newline at end of file diff --git a/android/src/com/turboviking/libnative/NativeGLView.java b/android/src/com/turboviking/libnative/NativeGLView.java new file mode 100644 index 0000000000..2709191f9d --- /dev/null +++ b/android/src/com/turboviking/libnative/NativeGLView.java @@ -0,0 +1,91 @@ +package com.turboviking.libnative; + +// Touch- and sensor-enabled GLSurfaceView. +// Supports simple multitouch and pressure. + +import android.app.Activity; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.opengl.GLSurfaceView; +import android.util.Log; +import android.view.MotionEvent; + +public class NativeGLView extends GLSurfaceView implements SensorEventListener { + private static String TAG = "NativeGLView"; + private SensorManager mSensorManager; + private Sensor mAccelerometer; + + public NativeGLView(NativeActivity activity) { + super(activity); + setEGLContextClientVersion(2); + // setEGLConfigChooser(5, 5, 5, 0, 16, 0); + // setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); + mSensorManager = (SensorManager)activity.getSystemService(Activity.SENSOR_SERVICE); + mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + } + + // This needs fleshing out. A lot. + // Going to want multitouch eventually. + public boolean onTouchEvent(final MotionEvent ev) { + for (int i = 0; i < ev.getPointerCount(); i++) { + int pid = ev.getPointerId(i); + int code = 0; + + final int action = ev.getActionMasked(); + + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_POINTER_DOWN: + if (ev.getActionIndex() == i) + code = 1; + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_UP: + if (ev.getActionIndex() == i) + code = 2; + break; + case MotionEvent.ACTION_MOVE: + code = 3; + break; + default: + break; + } + if (code != 0) + { + float x = ev.getX(i); + float y = ev.getY(i); + NativeApp.touch(x, y, code, pid); + } + } + return true; + } + + // Sensor management + @Override + public void onAccuracyChanged(Sensor sensor, int arg1) { + Log.i(TAG, "onAccuracyChanged"); + } + + @Override + public void onSensorChanged(SensorEvent event) { + if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) { + return; + } + // Can also look at event.timestamp for accuracy magic + NativeApp.accelerometer(event.values[0], event.values[1], event.values[2]); + } + + @Override + public void onPause() { + super.onPause(); + mSensorManager.unregisterListener(this); + } + + @Override + public void onResume() { + super.onResume(); + mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); + } +} diff --git a/android/src/com/turboviking/libnative/NativeRenderer.java b/android/src/com/turboviking/libnative/NativeRenderer.java new file mode 100644 index 0000000000..e4f741f474 --- /dev/null +++ b/android/src/com/turboviking/libnative/NativeRenderer.java @@ -0,0 +1,56 @@ +package com.turboviking.libnative; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView; +import android.util.Log; + + +public class NativeRenderer implements GLSurfaceView.Renderer { + private static String TAG = "RollerballRenderer"; + NativeActivity mActivity; + + NativeRenderer(NativeActivity act) { + mActivity = act; + } + + @Override + public void onSurfaceCreated(GL10 unused, EGLConfig config) { + Log.i(TAG, "onSurfaceCreated"); + displayInit(); + } + + @Override + public void onDrawFrame(GL10 unused /*use GLES20*/) { + displayRender(); + } + + @Override + public void onSurfaceChanged(GL10 unused, int width, int height) { + Log.i(TAG, "onSurfaceChanged"); + displayResize(width, height); + } + + + // NATIVE METHODS + + public native void displayInit(); + // Note: This also means "device lost" and you should reload + // all buffered objects. + public native void displayResize(int w, int h); + public native void displayRender(); + + // called by the C++ code through JNI. Dispatch anything we can't directly handle + // on the gfx thread to the UI thread. + public void postCommand(String command, String parameter) { + final String cmd = command; + final String param = parameter; + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + NativeRenderer.this.mActivity.processCommand(cmd, param); + } + }); + } +} \ No newline at end of file diff --git a/base/LAMEString.cpp b/base/LAMEString.cpp index 9f395e511c..8383b0e141 100644 --- a/base/LAMEString.cpp +++ b/base/LAMEString.cpp @@ -196,7 +196,7 @@ String String::subString(int pos, int len) const if(pos >= (int)_tcslen(CString)) { - result = TEXT(""); // empty string + result = ""; // empty string return result; } @@ -262,7 +262,7 @@ int String::parseIntoWords(String *words, int maxWords) if (currentWord.length()>0) { words[numWords] = currentWord; - currentWord=TEXT(""); + currentWord=""; numWords++; if (numWords == maxWords) return numWords; @@ -343,27 +343,27 @@ void String::reverseString() String String::getPath() { - int p=find(String(TEXT("\\")),0); + int p=find(String("\\"),0); int lastp=-1; while (p!=-1) { lastp=p; - p=find(String(TEXT("\\")),p+1); + p=find(String("\\"),p+1); } if (lastp!=-1) { return subString(0,lastp); } else { - return String(TEXT("")); + return String(""); } } String String::getFName() { - int p=find(String(TEXT("\\")),0); + int p=find(String("\\"),0); int lastp=-1; while (p!=-1) { lastp=p; - p=find(String(TEXT("\\")),p+1); + p=find(String("\\"),p+1); } if (lastp!=-1) { @@ -371,7 +371,7 @@ String String::getFName() } else { - return String(TEXT("")); + return String(""); } } diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 7f12614d19..fc5759b1ef 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -202,7 +202,7 @@ int main(int argc, char *argv[]) { // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); - InputState input_state = {0}; + InputState input_state; int framecount = 0; while (true) { @@ -219,24 +219,24 @@ int main(int argc, char *argv[]) { done = 1; } } else if (event.type == SDL_MOUSEMOTION) { - input_state.mouse_x = event.motion.x; - input_state.mouse_y = event.motion.y; + input_state.mouse_x[0] = event.motion.x; + input_state.mouse_y[0] = event.motion.y; } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { - input_state.mouse_buttons_down = 1; - input_state.mouse_buttons = 1; + ///input_state.mouse_buttons_down = 1; + input_state.mouse_down[0] = true; } } else if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { - input_state.mouse_buttons = 0; - input_state.mouse_buttons_up = 1; + input_state.mouse_down[0] = false; + //input_state.mouse_buttons_up = 1; } } } if (done) break; - input_state.mouse_last_buttons = input_state.mouse_buttons; + input_state.mouse_last[0] = input_state.mouse_down[0]; uint8 *keys = (uint8 *)SDL_GetKeyState(NULL); if (keys[SDLK_ESCAPE]) { break; diff --git a/base/basictypes.h b/base/basictypes.h index c6da99928c..ee9e88a1b2 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -49,10 +49,6 @@ typedef int64_t int64; #endif // _WIN32 -#ifndef TEXT -#define TEXT(x) x -#endif - // Byteswapping #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) diff --git a/base/logging.h b/base/logging.h index 4357a8084e..f660844e74 100644 --- a/base/logging.h +++ b/base/logging.h @@ -58,10 +58,6 @@ inline void Crash() { #define ELOG(...) {printf("E: %s:%i: ", __FILE__, __LINE__); printf("E: " __VA_ARGS__); printf("\n");} #define FLOG(...) {printf("F: %s:%i: ", __FILE__, __LINE__); printf("F: " __VA_ARGS__); printf("\n"); Crash();} -#ifndef MessageBox -#define MessageBox(a, b, c, d) printf("MSG: %s %s\n", (b), (c)); -#endif - #endif #define CHECK(a) {if (!(a)) {FLOG("CHECK failed");}} diff --git a/base/mutex.h b/base/mutex.h index e80cfa23ec..80bca45dfd 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -63,6 +63,15 @@ class lock_guard { public: lock_guard(recursive_mutex &mtx) : mtx_(mtx) {mtx_.lock();} ~lock_guard() {mtx_.unlock();} + private: recursive_mutex &mtx_; -}; \ No newline at end of file +}; + +#undef p +#undef MIN +#undef MAX +#undef min +#undef max +#undef DrawText +#undef itoa \ No newline at end of file diff --git a/base/stringutil.h b/base/stringutil.h index 08e94f742d..e055f089d2 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -4,6 +4,10 @@ #include #include +#ifdef _MSC_VER +#pragma warning (disable:4996) +#endif + // Dumb wrapper around itoa, providing a buffer. Declare this on the stack. class ITOA { public: diff --git a/file/file_util.cpp b/file/file_util.cpp index 4200dbc551..0726224ee4 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -131,7 +131,7 @@ std::string getDir(const std::string &path) while (n >= 0 && path[n] != '\\' && path[n] != '/') n--; std::string cutpath = path.substr(0, n); - for (int i = 0; i < cutpath.size(); i++) + for (size_t i = 0; i < cutpath.size(); i++) { if (cutpath[i] == '\\') cutpath[i] = '/'; } diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 69fbad52b8..44fafeebbf 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -27,10 +27,10 @@ static Finger fingers[MAX_FINGERS]; void update(const InputState &state) { // Mouse / 1-finger-touch control. - if (state.mouse_buttons_down & 1) { + if (state.mouse_down[0]) { fingers[0].down = true; - fingers[0].downX = state.mouse_x; - fingers[0].downY = state.mouse_y; + fingers[0].downX = state.mouse_x[0]; + fingers[0].downY = state.mouse_y[0]; } else { fingers[0].down = false; } diff --git a/input/input_state.h b/input/input_state.h index 333972ff55..2a0e49c20a 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -1,6 +1,7 @@ #pragma once #include "math/lin/vec3.h" +#include "base/mutex.h" enum { PAD_BUTTON_A = 1, @@ -17,9 +18,26 @@ enum { PAD_BUTTON_RIGHT = 2048, }; +#ifndef MAX_POINTERS +#define MAX_POINTERS 8 +#endif + // Agglomeration of all possible inputs, and automatically computed // deltas where applicable. struct InputState { + // Lock this whenever you access the data in this struct. + mutable recursive_mutex lock; + InputState() + : pad_buttons(0), + pad_last_buttons(0), + pad_buttons_down(0), + pad_buttons_up(0), + mouse_valid(false), + accelerometer_valid(false) { + memset(mouse_down, 0, sizeof(mouse_down)); + memset(mouse_last, 0, sizeof(mouse_last)); + } + // Gamepad style input int pad_buttons; // bitfield int pad_last_buttons; @@ -32,16 +50,14 @@ struct InputState { float pad_ltrigger; float pad_rtrigger; - // Mouse/singletouch style input + // Mouse/touch style input + // There are up to 8 mice / fingers. volatile bool mouse_valid; - int mouse_x; - int mouse_y; - int mouse_buttons; - int mouse_buttons_down; - int mouse_buttons_up; - int mouse_last_buttons; - // TODO: Multitouch + int mouse_x[MAX_POINTERS]; + int mouse_y[MAX_POINTERS]; + bool mouse_down[MAX_POINTERS]; + bool mouse_last[MAX_POINTERS]; // Accelerometer bool accelerometer_valid; diff --git a/ui/ui.cpp b/ui/ui.cpp index fb20b6a0b6..e60bbb8439 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -28,24 +28,26 @@ void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int ch themeCheckOffImage = checkOff; } -void UIUpdateMouse(float x, float y, int buttons) { - if ((buttons & 1) && !uistate.mousedown) { - uistate.mousepressed = 1; - uistate.mouseStartX = x; - uistate.mouseStartY = y; +void UIUpdateMouse(int i, float x, float y, bool down) { + if (down && !uistate.mousedown[i]) { + uistate.mousepressed[i] = 1; + uistate.mouseStartX[i] = x; + uistate.mouseStartY[i] = y; } else { - uistate.mousepressed = 0; + uistate.mousepressed[i] = 0; } - uistate.mousex = x; - uistate.mousey = y; - uistate.mousedown = buttons & 1; + + uistate.mousex[i] = x; + uistate.mousey[i] = y; + uistate.mousedown[i] = down; } -bool UIRegionHit(int x, int y, int w, int h, int margin) { - if (uistate.mousex < x - margin || - uistate.mousey < y - margin || - uistate.mousex >= x + w + margin || - uistate.mousey >= y + h + margin) { +bool UIRegionHit(int i, int x, int y, int w, int h, int margin) { + // Input handling + if (uistate.mousex[i] < x - margin || + uistate.mousey[i] < y - margin || + uistate.mousex[i] >= x + w + margin || + uistate.mousey[i] >= y + h + margin) { return false; } else { return true; @@ -53,24 +55,24 @@ bool UIRegionHit(int x, int y, int w, int h, int margin) { } void UIBegin() { - uistate.hotitem = 0; + for (int i = 0; i < MAX_POINTERS; i++) + uistate.hotitem[i] = 0; ui_draw2d.Begin(); ui_draw2d_front.Begin(); } void UIEnd() { - if (uistate.mousedown == 0) { - uistate.activeitem = 0; - } else { - if (uistate.activeitem == 0) { - uistate.activeitem = -1; - } - } + for (int i = 0; i < MAX_POINTERS; i++) { + if (uistate.mousedown[i] == 0) { + uistate.activeitem[i] = 0; + } else { + if (uistate.activeitem[i] == 0) { + uistate.activeitem[i] = -1; + } + } + } ui_draw2d.End(); ui_draw2d_front.End(); - - uistate.lastx = uistate.mousex; - uistate.lasty = uistate.mousey; } void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) { @@ -94,38 +96,42 @@ int UIButton(int id, const LayoutManager &layout, float w, const char *text, int if (button_align & ALIGN_RIGHT) x -= w; if (button_align & ALIGN_BOTTOMRIGHT) y -= h; - // Check whether the button should be hot, use a generous margin for touch ease - if (UIRegionHit(x, y, w, h, 8)) { - uistate.hotitem = id; - if (uistate.activeitem == 0 && uistate.mousedown) - uistate.activeitem = id; - } + int txOffset = 0; + + int clicked = 0; + for (int i = 0; i < MAX_POINTERS; i++) { + // Check whether the button should be hot, use a generous margin for touch ease + if (UIRegionHit(i, x, y, w, h, 8)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } + + if (uistate.hotitem[i] == id) { + if (uistate.activeitem[i] == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id) { + clicked = 1; + } + } // Render button - int txOffset = 0; - if (uistate.hotitem == id) { - if (uistate.activeitem == id) { - // Button is both 'hot' and 'active' - txOffset = 2; - } else { - // Button is merely 'hot' - } - } else { - // button is not hot, but it may be active - } ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); ui_draw2d.DrawTextShadow(themeUIFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); - int clicked = 0; - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown == 0 && - uistate.hotitem == id && - uistate.activeitem == id) { - clicked = 1; - } - uistate.lastwidget = id; return clicked; } @@ -140,39 +146,41 @@ int UIImageButton(int id, const LayoutManager &layout, float w, int image, int b if (button_align & ALIGN_RIGHT) x -= w; if (button_align & ALIGN_BOTTOMRIGHT) y -= h; - // Check whether the button should be hot, use a generous margin for touch ease - if (UIRegionHit(x, y, w, h, 8)) { - uistate.hotitem = id; - if (uistate.activeitem == 0 && uistate.mousedown) - uistate.activeitem = id; + int txOffset = 0; + int clicked = 0; + for (int i = 0; i < MAX_POINTERS; i++) { + // Check whether the button should be hot, use a generous margin for touch ease + if (UIRegionHit(i, x, y, w, h, 8)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } + + if (uistate.hotitem[i] == id) { + if (uistate.activeitem[i] == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id) { + clicked = 1; + } } // Render button - int txOffset = 0; - if (uistate.hotitem == id) { - if (uistate.activeitem == id) { - // Button is both 'hot' and 'active' - txOffset = 2; - } else { - // Button is merely 'hot' - } - } else { - // button is not hot, but it may be active - } - ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); - int clicked = 0; - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown == 0 && - uistate.hotitem == id && - uistate.activeitem == id) { - clicked = 1; - } - uistate.lastwidget = id; return clicked; } @@ -188,39 +196,42 @@ int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { if (align & ALIGN_RIGHT) x -= w; if (align & ALIGN_BOTTOMRIGHT) y -= h; - // Check whether the button should be hot - if (UIRegionHit(x, y, w, h, 8)) { - uistate.hotitem = id; - if (uistate.activeitem == 0 && uistate.mousedown) - uistate.activeitem = id; - } - - // Render button + int txOffset = 0; + int clicked = 0; + for (int i = 0; i < MAX_POINTERS; i++) { - int txOffset = 0; - if (uistate.hotitem == id) { - if (uistate.activeitem == id) { - // Button is both 'hot' and 'active' - txOffset = 2; - } else { - // Button is merely 'hot' - } - } else { - // button is not hot, but it may be active - } + // Check whether the button should be hot + if (UIRegionHit(i, x, y, w, h, 8)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } + + // Render button + + if (uistate.hotitem[i] == id) { + if (uistate.activeitem[i] == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id) { + *value = !(*value); + clicked = 1; + } + } ui_draw2d.DrawImage((*value) ? themeCheckOnImage : themeCheckOffImage, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); ui_draw2d.DrawTextShadow(themeUIFont, text, x + themeAtlas->images[themeCheckOnImage].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); - int clicked = 0; - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown == 0 && - uistate.hotitem == id && - uistate.activeitem == id) { - *value = !(*value); - clicked = 1; - } uistate.lastwidget = id; return clicked; @@ -235,36 +246,38 @@ void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, boo int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListState *state) { const int item_h = 64; - // Check whether the button should be hot - if (UIRegionHit(x, y, w, h, 0)) { - uistate.hotitem = id; - if (uistate.activeitem == 0 && uistate.mousedown) - uistate.activeitem = id; - } + int clicked = 0; + + for (int i = 0; i < MAX_POINTERS; i++) { + // Check whether the button should be hot + if (UIRegionHit(i, x, y, w, h, 0)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } + + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id && + state->selected != -1) { + clicked = 1; + } + } // render items int itemHeight = adapter->itemHeight(0); int numItems = adapter->getCount(); for (int i = 0; i < numItems; i++) { int item_y = y + i * itemHeight - state->scrollY; - if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h && UIRegionHit(x, item_y, w, h, 0)) { + if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h && + UIRegionHit(i, x, item_y, w, h, 0)) { // ultra fast touch response state->selected = i; } adapter->drawItem(i, x, item_y, w, itemHeight, i == state->selected); } - - int clicked = 0; - - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown == 0 && - uistate.hotitem == id && - uistate.activeitem == id && - state->selected != -1) { - clicked = 1; - } - uistate.lastwidget = id; // Otherwise, no clicky. @@ -293,36 +306,35 @@ int UIHSlider(int id, int x, int y, int w, int max, int *value) { // Calculate mouse cursor's relative y offset int xpos = ((256 - 16) * *value) / max; - // Check for hotness - if (UIRegionHit(x+8, y+8, 16, 255, 0)) { - uistate.hotitem = id; - if (uistate.activeitem == 0 && uistate.mousedown) - uistate.activeitem = id; - } + for (int i = 0; i < MAX_POINTERS; i++) { + // Check for hotness + if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } + + // Update widget value + if (uistate.activeitem[i] == id) { + int mousepos = uistate.mousey[i] - (y + 8); + if (mousepos < 0) mousepos = 0; + if (mousepos > 255) mousepos = 255; + int v = (mousepos * max) / 255; + if (v != *value) { + *value = v; + return 1; + } + } + } // Render the scrollbar ui_draw2d.Rect(x, y, 32, 256+16, 0x777777); - if (uistate.activeitem == id || uistate.hotitem == id) { - ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xffffff); - } else { - ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xaaaaaa); - } + ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xffffff); - // Update widget value - if (uistate.activeitem == id) { - int mousepos = uistate.mousey - (y + 8); - if (mousepos < 0) mousepos = 0; - if (mousepos > 255) mousepos = 255; - int v = (mousepos * max) / 255; - if (v != *value) { - *value = v; - return 1; - } - } - return 0; } +/* // TODO int UIVSlider(int id, int x, int y, int h, int max, int *value) { // Calculate mouse cursor's relative y offset @@ -334,26 +346,23 @@ int UIVSlider(int id, int x, int y, int h, int max, int *value) { if (uistate.activeitem == 0 && uistate.mousedown) uistate.activeitem = id; } + // Update widget value + if (uistate.activeitem == id) { + int mousepos = uistate.mousey - (y + 8); + if (mousepos < 0) mousepos = 0; + if (mousepos > 255) mousepos = 255; + int v = (mousepos * max) / 255; + if (v != *value) { + *value = v; + return 1; + } + } // Render the scrollbar ui_draw2d.Rect(x, y, 32, 256+16, 0x777777); - if (uistate.activeitem == id || uistate.hotitem == id) { - ui_draw2d.Rect(x+8, y+8 + ypos, 16, 16, 0xffffff); - } else { - ui_draw2d.Rect(x+8, y+8 + ypos, 16, 16, 0xaaaaaa); - } + ui_draw2d.Rect(x+8, y+8 + ypos, 16, 16, 0xffffff); - // Update widget value - if (uistate.activeitem == id) { - int mousepos = uistate.mousey - (y + 8); - if (mousepos < 0) mousepos = 0; - if (mousepos > 255) mousepos = 255; - int v = (mousepos * max) / 255; - if (v != *value) { - *value = v; - return 1; - } - } return 0; } +*/ diff --git a/ui/ui.h b/ui/ui.h index 9a101f0c12..0d790ea4eb 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -72,24 +72,23 @@ private: float spacing_; }; +#ifndef MAX_POINTERS +#define MAX_POINTERS 8 +#endif + // Mouse out of habit, applies just as well to touch events. // UI does not yet support multitouch. struct UIState { - int mousex; - int mousey; - int mousedown; - int mousepressed; - int mouseStartX; - int mouseStartY; + int mousex[MAX_POINTERS]; + int mousey[MAX_POINTERS]; + int mousedown[MAX_POINTERS]; + int mousepressed[MAX_POINTERS]; - int lastx; - int lasty; + int mouseStartX[MAX_POINTERS]; + int mouseStartY[MAX_POINTERS]; - int deltax; - int deltay; - - int hotitem; - int activeitem; + int hotitem[MAX_POINTERS]; + int activeitem[MAX_POINTERS]; // keyboard focus, not currently used int kbdwidget; @@ -155,12 +154,12 @@ struct UIListState { // Utility functions, useful when implementing your own controls -bool UIRegionHit(int x, int y, int w, int h, int margin); +bool UIRegionHit(int pointerId, int x, int y, int w, int h, int margin); // Call at start of frame void UIBegin(); -void UIUpdateMouse(float x, float y, int buttons); +void UIUpdateMouse(int i, float x, float y, bool down); // Returns 1 if clicked int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align); @@ -170,7 +169,7 @@ int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, in int UICheckBox(int id, int x, int y, const char *text, int align, bool *value); // Vertical slider. Not yet working. -int UIVSlider(int id, int x, int y, int h, int max, int *value); +// int UIVSlider(int id, int x, int y, int h, int max, int *value); // Horizontal slider. Not yet working. int UIHSlider(int id, int x, int y, int w, int max, int *value); From def79c018083ebc525cb3616831b9b5459abca72 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 27 Apr 2012 23:00:48 +0200 Subject: [PATCH 0043/1445] Allow retreiving audio clip data --- audio/mixer.cpp | 5 +++++ audio/mixer.h | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/audio/mixer.cpp b/audio/mixer.cpp index f69233de75..8b06d34416 100644 --- a/audio/mixer.cpp +++ b/audio/mixer.cpp @@ -130,6 +130,11 @@ void clip_destroy(Clip *clip) { } } +const short *clip_data(const Clip *clip) +{ + return clip->data; +} + int clip_length(const Clip *clip) { return clip->length; } diff --git a/audio/mixer.h b/audio/mixer.h index 18d70e0ac0..68f4833b3e 100644 --- a/audio/mixer.h +++ b/audio/mixer.h @@ -1,3 +1,5 @@ +#pragma once + #include "base/basictypes.h" // Simple mixer intended for sound effects for games. @@ -30,7 +32,8 @@ void mixer_mix(Mixer *mixer, short *buffer, int num_samples); Clip *clip_load(const char *filename); void clip_destroy(Clip *clip); -int clip_length(); +const short *clip_data(const Clip *clip); +int clip_length(const Clip *clip); void clip_set_loop(int start, int end); From ab96a3fc70b6a172826702c34d3aa129c3d70d07 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 28 Apr 2012 00:02:55 +0200 Subject: [PATCH 0044/1445] Count frames the pointer has been held. --- ui/ui.cpp | 4 ++++ ui/ui.h | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index e60bbb8439..99075d99fe 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -36,6 +36,10 @@ void UIUpdateMouse(int i, float x, float y, bool down) { } else { uistate.mousepressed[i] = 0; } + if (uistate.mousedown[i]) + uistate.mouseframesdown[i]++; + else + uistate.mouseframesdown[i] = 0; uistate.mousex[i] = x; uistate.mousey[i] = y; diff --git a/ui/ui.h b/ui/ui.h index 0d790ea4eb..fa4da75820 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -81,8 +81,9 @@ private: struct UIState { int mousex[MAX_POINTERS]; int mousey[MAX_POINTERS]; - int mousedown[MAX_POINTERS]; - int mousepressed[MAX_POINTERS]; + bool mousedown[MAX_POINTERS]; + bool mousepressed[MAX_POINTERS]; + short mouseframesdown[MAX_POINTERS]; int mouseStartX[MAX_POINTERS]; int mouseStartY[MAX_POINTERS]; From 9d158fcf2d0929a2dfdfc2a524ec8a31f8e5c9d1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 5 May 2012 21:16:03 +0200 Subject: [PATCH 0045/1445] vjson: Add simple accessors for getting arrays and dicts --- ext/vjson/json.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ext/vjson/json.h b/ext/vjson/json.h index 08c4ba8b7a..5c56ee10cf 100644 --- a/ext/vjson/json.h +++ b/ext/vjson/json.h @@ -41,6 +41,12 @@ struct json_value int numSiblings() const; // num siblings *after* this one only const json_value *get(const char *child_name) const; const json_value *get(const char *child_name, json_type type) const; + const json_value *getArray(const char *child_name) const { + return get(child_name, JSON_ARRAY); + } + const json_value *getDict(const char *child_name) const { + return get(child_name, JSON_OBJECT); + } const char *getString(const char *child_name) const; const char *getString(const char *child_name, const char *default_value) const; bool getStringVector(std::vector *vec) const; @@ -50,7 +56,7 @@ struct json_value int getInt(const char *child_name, int default_value) const; bool getBool(const char *child_name) const; bool getBool(const char *child_name, bool default_value) const; - + private: DISALLOW_COPY_AND_ASSIGN(json_value); }; From a8eda0db12b4ff2c77b3e2cc826f5093ab433d3e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 May 2012 12:45:59 +0200 Subject: [PATCH 0046/1445] Minor stuff --- audio/mixer.cpp | 2 +- audio/mixer.h | 2 +- ext/vjson/json.cpp | 7 ++++++- ext/vjson/json.h | 7 +++++++ midi/midi_input.h | 1 + 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/audio/mixer.cpp b/audio/mixer.cpp index 8b06d34416..483221bffe 100644 --- a/audio/mixer.cpp +++ b/audio/mixer.cpp @@ -135,7 +135,7 @@ const short *clip_data(const Clip *clip) return clip->data; } -int clip_length(const Clip *clip) { +size_t clip_length(const Clip *clip) { return clip->length; } diff --git a/audio/mixer.h b/audio/mixer.h index 68f4833b3e..99b140aad4 100644 --- a/audio/mixer.h +++ b/audio/mixer.h @@ -33,7 +33,7 @@ Clip *clip_load(const char *filename); void clip_destroy(Clip *clip); const short *clip_data(const Clip *clip); -int clip_length(const Clip *clip); +size_t clip_length(const Clip *clip); void clip_set_loop(int start, int end); diff --git a/ext/vjson/json.cpp b/ext/vjson/json.cpp index a08d2ba60f..8e375af951 100644 --- a/ext/vjson/json.cpp +++ b/ext/vjson/json.cpp @@ -50,7 +50,12 @@ const json_value *json_value::get(const char *child_name, json_type type) const } const char *json_value::getString(const char *child_name) const { - return get(child_name, JSON_STRING)->string_value; + const json_value *val = get(child_name, JSON_STRING); + if (val) + return val->string_value; + else + FLOG("String %s missing from node %s", child_name, this->name); + return 0; } const char *json_value::getString(const char *child_name, const char *default_value) const { diff --git a/ext/vjson/json.h b/ext/vjson/json.h index 5c56ee10cf..a6b9bed80e 100644 --- a/ext/vjson/json.h +++ b/ext/vjson/json.h @@ -107,3 +107,10 @@ private: DISALLOW_COPY_AND_ASSIGN(JsonReader); }; + +// TODO: Make this a push/pop interface similar to JsonWriter. Maybe +// we can get to the point where reading and writing is near identical or the same code. +class JsonCursor { +public: + +}; \ No newline at end of file diff --git a/midi/midi_input.h b/midi/midi_input.h index 125e22f7cd..371a749799 100644 --- a/midi/midi_input.h +++ b/midi/midi_input.h @@ -16,6 +16,7 @@ typedef void *MidiDevice; class MidiListener { public: + virtual ~MidiListener() {} virtual void midiEvent(const uint8_t *cmd) = 0; }; From 8e775751fc194204e072ec7155ff69d4463691e8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 May 2012 20:37:28 +0200 Subject: [PATCH 0047/1445] Undef CHECK --- base/logging.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/logging.h b/base/logging.h index f660844e74..15fcba2a6d 100644 --- a/base/logging.h +++ b/base/logging.h @@ -60,6 +60,8 @@ inline void Crash() { #endif +#undef CHECK + #define CHECK(a) {if (!(a)) {FLOG("CHECK failed");}} #define CHECK_EQ(a, b) CHECK((a) == (b)); #define CHECK_NE(a, b) CHECK((a) != (b)); From ec57b692eba09e65ba56f26dcc959d076b387e8f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 May 2012 23:21:26 +0200 Subject: [PATCH 0048/1445] Misc --- android/app-android.cpp | 4 ++-- base/PCMain.cpp | 14 +++++++++--- gfx_es2/draw_buffer.cpp | 50 ++++++++++++++++++++++++++++++----------- gfx_es2/draw_buffer.h | 9 ++++++-- native.vcxproj | 2 ++ native.vcxproj.filters | 9 ++++++++ util/bits/bits.h | 23 +++++++++++++++++++ 7 files changed, 91 insertions(+), 20 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 21d3298614..d2e6fdd31d 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -210,11 +210,11 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch input_state.mouse_x[pointerId] = (int)x; input_state.mouse_y[pointerId] = (int)y; if (code == 1) { - ILOG("Down: %i %f %f", pointerId, x, y); + //ILOG("Down: %i %f %f", pointerId, x, y); input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; input_state.mouse_down[pointerId] = true; } else if (code == 2) { - ILOG("Up: %i %f %f", pointerId, x, y); + //ILOG("Up: %i %f %f", pointerId, x, y); input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; input_state.mouse_down[pointerId] = false; } diff --git a/base/PCMain.cpp b/base/PCMain.cpp index fc5759b1ef..0c10212882 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -204,13 +204,15 @@ int main(int argc, char *argv[]) { InputState input_state; int framecount = 0; - + bool nextFrameMD = 0; while (true) { SDL_Event event; input_state.accelerometer_valid = false; input_state.mouse_valid = true; int done = 0; + + // input_state.mouse_down[1] = nextFrameMD; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { done = 1; @@ -221,19 +223,25 @@ int main(int argc, char *argv[]) { } else if (event.type == SDL_MOUSEMOTION) { input_state.mouse_x[0] = event.motion.x; input_state.mouse_y[0] = event.motion.y; + input_state.mouse_x[1] = event.motion.x + 150; + input_state.mouse_y[1] = event.motion.y; } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { ///input_state.mouse_buttons_down = 1; - input_state.mouse_down[0] = true; + input_state.mouse_down[0] = true; + nextFrameMD = true; } } else if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { - input_state.mouse_down[0] = false; + input_state.mouse_down[0] = false; + nextFrameMD = false; //input_state.mouse_buttons_up = 1; } } } + + if (done) break; input_state.mouse_last[0] = input_state.mouse_down[0]; diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index ac4b323bf6..dee035db8a 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -10,7 +10,9 @@ #endif #endif +#include #include + #include "base/logging.h" #include "math/math_util.h" #include "gfx_es2/draw_buffer.h" @@ -86,7 +88,7 @@ void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) { } void DrawBuffer::Rect(float x, float y, float w, float h, uint32 color, int align) { - DoAlign(align, &x, &y, w, h); + DoAlign(align, &x, &y, &w, &h); RectVGradient(x, y, w, h, color, color); } @@ -290,22 +292,33 @@ void DrawBuffer::DrawTextShadow(int font, const char *text, float x, float y, Co DrawText(font, text, x, y, color, flags); } -void DrawBuffer::DoAlign(int align, float *x, float *y, float w, float h) { - if (align & ALIGN_HCENTER) *x -= w / 2; - if (align & ALIGN_RIGHT) *x -= w; - if (align & ALIGN_VCENTER) *y -= h / 2; - if (align & ALIGN_BOTTOM) *y -= h; +void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) { + if (flags & ALIGN_HCENTER) *x -= *w / 2; + if (flags & ALIGN_RIGHT) *x -= *w; + if (flags & ALIGN_VCENTER) *y -= *h / 2; + if (flags & ALIGN_BOTTOM) *y -= *h; + if (flags & (ROTATE_90DEG_LEFT | ROTATE_90DEG_RIGHT)) { + std::swap(*w, *h); + std::swap(*x, *y); + } } +// ROTATE_* doesn't yet work right. void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int flags) { const AtlasFont &atlasfont = *atlas->fonts[font]; unsigned char cval; float w, h; MeasureText(font, text, &w, &h); if (flags) { - DoAlign(flags, &x, &y, w, h); + DoAlign(flags, &x, &y, &w, &h); } - y+=atlasfont.ascend*fontscaley; + + if (flags & ROTATE_90DEG_LEFT) { + x -= atlasfont.ascend*fontscaley; + // y += h; + } + else + y += atlasfont.ascend*fontscaley; float sx = x; while ((cval = *text++) != '\0') { if (cval == '\n') { @@ -316,17 +329,28 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co if (cval < 32) continue; if (cval > 127) continue; AtlasChar c = atlasfont.chars[cval - 32]; - float cx1 = x + c.ox * fontscalex; - float cy1 = y + c.oy * fontscaley; - float cx2 = x + (c.ox + c.pw) * fontscalex; - float cy2 = y + (c.oy + c.ph) * fontscaley; + float cx1, cy1, cx2, cy2; + if (flags & ROTATE_90DEG_LEFT) { + cy1 = y - c.ox * fontscalex; + cx1 = x + c.oy * fontscaley; + cy2 = y - (c.ox + c.pw) * fontscalex; + cx2 = x + (c.oy + c.ph) * fontscaley; + } else { + cx1 = x + c.ox * fontscalex; + cy1 = y + c.oy * fontscaley; + cx2 = x + (c.ox + c.pw) * fontscalex; + cy2 = y + (c.oy + c.ph) * fontscaley; + } V(cx1, cy1, color, c.sx, c.sy); V(cx2, cy1, color, c.ex, c.sy); V(cx2, cy2, color, c.ex, c.ey); V(cx1, cy1, color, c.sx, c.sy); V(cx2, cy2, color, c.ex, c.ey); V(cx1, cy2, color, c.sx, c.ey); - x += c.wx * fontscalex; + if (flags & ROTATE_90DEG_LEFT) + y -= c.wx * fontscalex; + else + x += c.wx * fontscalex; } } diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 36405c15ab..e79da5e56c 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -20,6 +20,11 @@ enum { ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT, ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT, ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT, + + // Only for text drawing + ROTATE_90DEG_LEFT = 256, + ROTATE_90DEG_RIGHT = 512, + ROTATE_180DEG = 1024, }; struct GLSLProgram; @@ -80,7 +85,7 @@ class DrawBuffer { void DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); void MeasureText(int font, const char *text, float *w, float *h); - void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); + void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); void DrawTextShadow(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); void RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color); @@ -93,7 +98,7 @@ class DrawBuffer { void EnableBlend(bool enable); private: - void DoAlign(int align, float *x, float *y, float w, float h); + void DoAlign(int flags, float *x, float *y, float *w, float *h); struct Vertex { float x, y, z; uint8 r, g, b, a; diff --git a/native.vcxproj b/native.vcxproj index df5929eb76..b5bbbc1f44 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -137,6 +137,7 @@ + @@ -186,6 +187,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 82845e359b..ea338768b4 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -156,6 +156,9 @@ base + + util + @@ -281,6 +284,9 @@ base + + util + @@ -322,5 +328,8 @@ {4710a9a2-d1fa-4920-ba1b-a7527902be53} + + {e36ca540-863c-496b-b0f4-b1ece3e72feb} + \ No newline at end of file diff --git a/util/bits/bits.h b/util/bits/bits.h index 1729761e2b..d5c3d7eac6 100644 --- a/util/bits/bits.h +++ b/util/bits/bits.h @@ -37,6 +37,29 @@ inline uint32_t _rotr(uint32_t val, int shift) { return (val << shift) | (val >> (31 - shift)); } +/* +template +class BitArray { +public: + BitArray() { + memset(data, 0, sizeof(data)); + } + + BitArray And(const BitArray &other) { + BitArray retVal; + for (int i = 0; i < DATACOUNT; i++) { + retVal.data[i] = data[i] & other.data[i]; + } + } + +private: + uint32 data[(SZ + 31) / 32]; + enum { + DATACOUNT = (SZ + 31) / 32; + }; +}; +*/ + #endif #endif From f03ec57c172d0d703f27db240f1ed3f9b2adca5c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 7 May 2012 18:27:09 +0200 Subject: [PATCH 0049/1445] DrawBuffer: Basic scissor support. --- gfx_es2/draw_buffer.cpp | 13 +++++++++++++ gfx_es2/draw_buffer.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index dee035db8a..ae94e870c3 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -13,6 +13,7 @@ #include #include +#include "base/display.h" #include "base/logging.h" #include "math/math_util.h" #include "gfx_es2/draw_buffer.h" @@ -360,3 +361,15 @@ void DrawBuffer::EnableBlend(bool enable) { else glDisable(GL_BLEND); } + +void DrawBuffer::SetClipRect(float x, float y, float w, float h) +{ + // Sigh, OpenGL is upside down. + glScissor(x, g_yres - y, w, h); + glEnable(GL_SCISSOR_TEST); +} + +void DrawBuffer::NoClip() +{ + glDisable(GL_SCISSOR_TEST); +} diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index e79da5e56c..c7ad3d4776 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -97,6 +97,13 @@ class DrawBuffer { // Utility to avoid having to include gl.h just for this in UI code. void EnableBlend(bool enable); + + // Rectangular clipping, implemented using scissoring. + // Must flush before and after. + void SetClipRect(float x1, float y1, float x2, float y2); + void NoClip(); + + private: void DoAlign(int flags, float *x, float *y, float *w, float *h); struct Vertex { From eda90061f9fba551ecc909a72b7d91114b2cbe3b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 7 May 2012 20:27:43 +0200 Subject: [PATCH 0050/1445] ... --- ui/ui.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/ui.h b/ui/ui.h index fa4da75820..42f173757a 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -50,6 +50,9 @@ public: *y = y_; x_ += *w + spacing_; } + void Space(float x) { + x_ += x; + } private: mutable float x_; From 950a6b65e872dfd868b5acfe50db531be21d2ab3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 7 May 2012 22:45:43 +0200 Subject: [PATCH 0051/1445] Minor optimization --- gfx_es2/draw_buffer.cpp | 8 ++------ gfx_es2/draw_buffer.h | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index ae94e870c3..7a3a687b98 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -60,7 +60,7 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { glEnableVertexAttribArray(program->a_texcoord0); GL_CHECK(); glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].x); - glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &verts_[0].r); + glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &verts_[0].rgba); if (program->a_texcoord0 != -1) glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].u); glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_); @@ -79,11 +79,7 @@ void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) { vert->x = x; vert->y = y; vert->z = z; - // todo: speedup rgba here - vert->r = color & 0xFF; - vert->g = (color >> 8) & 0xFF; - vert->b = (color >> 16) & 0xFF; - vert->a = (color >> 24) & 0xFF; + vert->rgba = color; vert->u = u; vert->v = v; } diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index c7ad3d4776..36a16b6c00 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -108,7 +108,7 @@ class DrawBuffer { void DoAlign(int flags, float *x, float *y, float *w, float *h); struct Vertex { float x, y, z; - uint8 r, g, b, a; + uint32_t rgba; float u, v; }; From caf0580c382af91de1f699e953a9ea516688c559 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 8 May 2012 22:04:24 +0200 Subject: [PATCH 0052/1445] Tabs unification --- audio/mixer.cpp | 38 ++-- audio/mixer.h | 3 +- audio/wav_read.cpp | 14 +- base/LAMEString.h | 5 +- base/colorutil.cpp | 143 +++++++------ base/error_context.cpp | 28 +-- base/error_context.h | 8 +- base/mutex.h | 52 ++--- base/scoped_ptr.h | 24 +-- base/stringutil.h | 12 +- base/timeutil.cpp | 36 ++-- gfx/gl_debug_log.cpp | 20 +- gfx/gl_lost_manager.cpp | 2 +- gfx/texture.cpp | 126 +++++------ gfx/texture.h | 10 +- gfx/texture_gen.cpp | 72 +++---- gfx_es2/draw_buffer.cpp | 262 ++++++++++++----------- gfx_es2/draw_buffer.h | 58 +++--- gfx_es2/fbo.cpp | 18 +- gfx_es2/glsl_program.cpp | 140 ++++++------- gfx_es2/vertex_format.cpp | 94 ++++----- gfx_es2/vertex_format.h | 60 +++--- image/surface.h | 34 --- image/zim_load.cpp | 140 ++++++------- image/zim_save.cpp | 268 ++++++++++++------------ json/json_writer.cpp | 16 +- json/json_writer.h | 8 +- math/compression.h | 18 +- math/lin/matrix4x4.cpp | 362 ++++++++++++++++---------------- math/lin/matrix4x4.h | 212 +++++++++---------- math/lin/quat.cpp | 190 ++++++++--------- math/lin/quat.h | 156 +++++++------- math/lin/vec3.cpp | 28 +-- math/lin/vec3.h | 204 +++++++++--------- math/math_util.h | 45 ++-- midi/midi_input.cpp | 81 ++++---- midi/midi_input.h | 4 +- native.vcxproj | 1 - native.vcxproj.filters | 1 - profiler/profiler.cpp | 2 +- ui/ui.cpp | 424 +++++++++++++++++++------------------- ui/ui.h | 110 +++++----- 42 files changed, 1744 insertions(+), 1785 deletions(-) delete mode 100644 image/surface.h diff --git a/audio/mixer.cpp b/audio/mixer.cpp index 483221bffe..09743fa9b6 100644 --- a/audio/mixer.cpp +++ b/audio/mixer.cpp @@ -89,26 +89,26 @@ static int get_free_channel(Mixer *mixer) { } Clip *clip_load(const char *filename) { - short *data; + short *data; int num_samples, sample_rate, num_channels; - if (!strcmp(filename + strlen(filename) - 4, ".ogg")) { - // Ogg file. For now, directly decompress, no streaming support. - uint8_t *filedata; - size_t size; - filedata = VFSReadFile(filename, &size); - num_samples = stb_vorbis_decode_memory(filedata, size, &num_channels, &data); - if (num_samples <= 0) - return NULL; - sample_rate = 44100; - ILOG("read ogg %s, length %i, rate %i", filename, num_samples, sample_rate); - } else { - // Wav file. Easy peasy. - data = wav_read(filename, &num_samples, &sample_rate, &num_channels); - if (!data) { - return NULL; - } - } + if (!strcmp(filename + strlen(filename) - 4, ".ogg")) { + // Ogg file. For now, directly decompress, no streaming support. + uint8_t *filedata; + size_t size; + filedata = VFSReadFile(filename, &size); + num_samples = stb_vorbis_decode_memory(filedata, size, &num_channels, &data); + if (num_samples <= 0) + return NULL; + sample_rate = 44100; + ILOG("read ogg %s, length %i, rate %i", filename, num_samples, sample_rate); + } else { + // Wav file. Easy peasy. + data = wav_read(filename, &num_samples, &sample_rate, &num_channels); + if (!data) { + return NULL; + } + } Clip *clip = new Clip(); clip->type = CT_PCM16; @@ -132,7 +132,7 @@ void clip_destroy(Clip *clip) { const short *clip_data(const Clip *clip) { - return clip->data; + return clip->data; } size_t clip_length(const Clip *clip) { diff --git a/audio/mixer.h b/audio/mixer.h index 99b140aad4..99948f18af 100644 --- a/audio/mixer.h +++ b/audio/mixer.h @@ -3,8 +3,7 @@ #include "base/basictypes.h" // Simple mixer intended for sound effects for games. -// Intended both for fire and forget sfx (auto channels) and for -// realtime-modifiable sounds like pitched engine noises (fixed channels). +// The clip loading code supports ogg SFX. struct Mixer; struct Clip; diff --git a/audio/wav_read.cpp b/audio/wav_read.cpp index 53e5052ed3..437ced9208 100644 --- a/audio/wav_read.cpp +++ b/audio/wav_read.cpp @@ -4,8 +4,9 @@ #include "file/chunk_file.h" short *wav_read(const char *filename, - int *num_samples, int *sample_rate, - int *num_channels) { + int *num_samples, int *sample_rate, + int *num_channels) +{ ChunkFile cf(filename, true); if (cf.failed()) { WLOG("ERROR: Wave file %s could not be opened", filename); @@ -16,10 +17,8 @@ short *wav_read(const char *filename, int samplesPerSec, avgBytesPerSec,wBlockAlign,wBytesPerSample; if (cf.descend('RIFF')) { cf.readInt(); //get past 'WAVE' - if (cf.descend('fmt ')) //enter the format chunk - { - int temp; - temp = cf.readInt(); + if (cf.descend('fmt ')) { //enter the format chunk + int temp = cf.readInt(); int format = temp & 0xFFFF; if (format != 1) { cf.ascend(); @@ -42,8 +41,7 @@ short *wav_read(const char *filename, return NULL; } - if (cf.descend('data')) //enter the data chunk - { + if (cf.descend('data')) { //enter the data chunk int numBytes = cf.getCurrentChunkSize(); int numSamples = numBytes / wBlockAlign; data = (short *)malloc(sizeof(short) * numSamples * *num_channels); diff --git a/base/LAMEString.h b/base/LAMEString.h index 12f12839bb..22d17b3815 100644 --- a/base/LAMEString.h +++ b/base/LAMEString.h @@ -1,6 +1,7 @@ -// NOTE: This is only here for legacy reasons. -// In new code, please use std::string. +// DEPRECATED +// This is only here for legacy reasons. +// In new code, please use std::string. #pragma once diff --git a/base/colorutil.cpp b/base/colorutil.cpp index d17310d33f..12e1d1755e 100644 --- a/base/colorutil.cpp +++ b/base/colorutil.cpp @@ -1,3 +1,41 @@ +#include "base/colorutil.h" + +uint32_t whiteAlpha(float alpha) { + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + uint32_t color = (int)(alpha*255) << 24; + color |= 0xFFFFFF; + return color; +} + +uint32_t blackAlpha(float alpha) { + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + return (int)(alpha*255)<<24; +} + +uint32_t rgba(float r, float g, float b, float alpha) { + uint32_t color = (int)(alpha*255)<<24; + color |= (int)(b*255)<<16; + color |= (int)(g*255)<<8; + color |= (int)(r*255); + return color; +} + +uint32_t rgba_clamp(float r, float g, float b, float a) { + if (r > 1.0f) r = 1.0f; + if (g > 1.0f) g = 1.0f; + if (b > 1.0f) b = 1.0f; + if (a > 1.0f) a = 1.0f; + + if (r < 0.0f) r = 0.0f; + if (g < 0.0f) g = 0.0f; + if (b < 0.0f) b = 0.0f; + if (a < 0.0f) a = 0.0f; + + return rgba(r,g,b,a); +} + /* hsv2rgb.c * Convert Hue Saturation Value to Red Green Blue * @@ -8,79 +46,40 @@ * Procedural Elements for Computer Graphics * McGraw Hill 1985 */ - -#include "base/colorutil.h" - -uint32_t whiteAlpha(float alpha) { - if (alpha < 0.0f) alpha = 0.0f; - if (alpha > 1.0f) alpha = 1.0f; - uint32_t color = (int)(alpha*255)<<24; - color |= 0xFFFFFF; - return color; -} - -uint32_t blackAlpha(float alpha) { - if (alpha < 0.0f) alpha = 0.0f; - if (alpha > 1.0f) alpha = 1.0f; - return (int)(alpha*255)<<24; -} - -uint32_t rgba(float r, float g, float b, float alpha) { - uint32_t color = (int)(alpha*255)<<24; - color |= (int)(b*255)<<16; - color |= (int)(g*255)<<8; - color |= (int)(r*255); - return color; -} - -uint32_t rgba_clamp(float r, float g, float b, float a) { - if (r > 1.0f) r = 1.0f; - if (g > 1.0f) g = 1.0f; - if (b > 1.0f) b = 1.0f; - if (a > 1.0f) a = 1.0f; - - if (r < 0.0f) r = 0.0f; - if (g < 0.0f) g = 0.0f; - if (b < 0.0f) b = 0.0f; - if (a < 0.0f) a = 0.0f; - - return rgba(r,g,b,a); -} - uint32_t hsva(float H, float S, float V, float alpha) { - /* - * Purpose: - * Convert HSV values to RGB values - * All values are in the range [0.0 .. 1.0] - */ - float F, M, N, K; - int I; - float r, g, b; - if ( S == 0.0 ) { - // Achromatic case, set level of grey - return rgba(V, V, V, alpha); - } else { - /* - * Determine levels of primary colours. - */ - if (H >= 1.0) { - H = 0.0; - } else { - H = H * 6; - } - I = (int) H; /* should be in the range 0..5 */ - F = H - I; /* fractional part */ + /* + * Purpose: + * Convert HSV values to RGB values + * All values are in the range [0.0 .. 1.0] + */ + float F, M, N, K; + int I; + float r, g, b; + if ( S == 0.0 ) { + // Achromatic case, set level of grey + return rgba(V, V, V, alpha); + } else { + /* + * Determine levels of primary colours. + */ + if (H >= 1.0) { + H = 0.0; + } else { + H = H * 6; + } + I = (int) H; /* should be in the range 0..5 */ + F = H - I; /* fractional part */ - M = V * (1 - S); - N = V * (1 - S * F); - K = V * (1 - S * (1 - F)); + M = V * (1 - S); + N = V * (1 - S * F); + K = V * (1 - S * (1 - F)); - if (I == 0) { r = V; g = K; b = M; } - if (I == 1) { r = N; g = V; b = M; } - if (I == 2) { r = M; g = V; b = K; } - if (I == 3) { r = M; g = N; b = V; } - if (I == 4) { r = K; g = M; b = V; } - if (I == 5) { r = V; g = M; b = N; } - return rgba(r, g, b, alpha); - } + if (I == 0) { r = V; g = K; b = M; } + if (I == 1) { r = N; g = V; b = M; } + if (I == 2) { r = M; g = V; b = K; } + if (I == 3) { r = M; g = N; b = V; } + if (I == 4) { r = K; g = M; b = V; } + if (I == 5) { r = V; g = M; b = N; } + return rgba(r, g, b, alpha); + } } diff --git a/base/error_context.cpp b/base/error_context.cpp index da27668b4e..61afa713dd 100644 --- a/base/error_context.cpp +++ b/base/error_context.cpp @@ -13,12 +13,12 @@ __THREAD std::vector *_error_context_name; __THREAD std::vector *_error_context_data; _ErrorContext::_ErrorContext(const char *name, const char *data) { - if (!_error_context_name) { - _error_context_name = new std::vector(); - _error_context_data = new std::vector(); - _error_context_name->reserve(16); - _error_context_data->reserve(16); - } + if (!_error_context_name) { + _error_context_name = new std::vector(); + _error_context_data = new std::vector(); + _error_context_name->reserve(16); + _error_context_data->reserve(16); + } _error_context_name->push_back(name); _error_context_data->push_back(data); } @@ -29,12 +29,12 @@ _ErrorContext::~_ErrorContext() { } void _ErrorContext::Log(const char *message) { - ILOG("EC: %s", message); - for (size_t i = 0; i < _error_context_name->size(); i++) { - if ((*_error_context_data)[i] != 0) { - ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]); - } else { - ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]); - } - } + ILOG("EC: %s", message); + for (size_t i = 0; i < _error_context_name->size(); i++) { + if ((*_error_context_data)[i] != 0) { + ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]); + } else { + ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]); + } + } } diff --git a/base/error_context.h b/base/error_context.h index 228c714065..ef53e9b52d 100644 --- a/base/error_context.h +++ b/base/error_context.h @@ -7,11 +7,11 @@ class _ErrorContext { public: - _ErrorContext(const char *name, const char *data = 0); - ~_ErrorContext(); + _ErrorContext(const char *name, const char *data = 0); + ~_ErrorContext(); - // Logs the current context stack. - static void Log(const char *message); + // Logs the current context stack. + static void Log(const char *message); }; #define ErrorContext(...) _ErrorContext __ec(__VA_ARGS__) diff --git a/base/mutex.h b/base/mutex.h index 80bca45dfd..6700cc7f1f 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -14,58 +14,58 @@ class recursive_mutex { #ifdef _WIN32 - typedef CRITICAL_SECTION mutexType; + typedef CRITICAL_SECTION mutexType; #else - typedef pthread_mutex_t mutexType; + typedef pthread_mutex_t mutexType; #endif public: - recursive_mutex() { + recursive_mutex() { #ifdef _WIN32 - InitializeCriticalSection(&mut_); + InitializeCriticalSection(&mut_); #else - pthread_mutex_init(&mut_, NULL); + pthread_mutex_init(&mut_, NULL); #endif - } - ~recursive_mutex() { + } + ~recursive_mutex() { #ifdef _WIN32 - DeleteCriticalSection(&mut_); + DeleteCriticalSection(&mut_); #else - pthread_mutex_destroy(&mut_); + pthread_mutex_destroy(&mut_); #endif - } - bool trylock() { + } + bool trylock() { #ifdef _WIN32 - return TryEnterCriticalSection(&mut_) == TRUE; + return TryEnterCriticalSection(&mut_) == TRUE; #else - return pthread_mutex_trylock(&mut_) != EBUSY; + return pthread_mutex_trylock(&mut_) != EBUSY; #endif - } - void lock() { + } + void lock() { #ifdef _WIN32 - EnterCriticalSection(&mut_); + EnterCriticalSection(&mut_); #else - pthread_mutex_lock(&mut_); + pthread_mutex_lock(&mut_); #endif - } - void unlock() { + } + void unlock() { #ifdef _WIN32 - LeaveCriticalSection(&mut_); + LeaveCriticalSection(&mut_); #else - pthread_mutex_unlock(&mut_); + pthread_mutex_unlock(&mut_); #endif - } + } private: - mutexType mut_; + mutexType mut_; }; class lock_guard { public: - lock_guard(recursive_mutex &mtx) : mtx_(mtx) {mtx_.lock();} - ~lock_guard() {mtx_.unlock();} + lock_guard(recursive_mutex &mtx) : mtx_(mtx) {mtx_.lock();} + ~lock_guard() {mtx_.unlock();} private: - recursive_mutex &mtx_; + recursive_mutex &mtx_; }; #undef p diff --git a/base/scoped_ptr.h b/base/scoped_ptr.h index 3c66eedc3b..0dff0fd038 100644 --- a/base/scoped_ptr.h +++ b/base/scoped_ptr.h @@ -4,26 +4,26 @@ template class scoped_ptr { - public: +public: scoped_ptr() : ptr_(0) {} scoped_ptr(T *p) : ptr_(p) {} ~scoped_ptr() { delete ptr_; } void reset(T *p) { - delete ptr_; + delete ptr_; ptr_ = p; } - T *release() { - T *p = ptr_; - ptr_ = 0; - return p; - } - T *operator->() { return ptr_; } - const T *operator->() const { return ptr_; } + T *release() { + T *p = ptr_; + ptr_ = 0; + return p; + } + T *operator->() { return ptr_; } + const T *operator->() const { return ptr_; } - private: - scoped_ptr(const scoped_ptr &other); - void operator=(const scoped_ptr &other); +private: + scoped_ptr(const scoped_ptr &other); + void operator=(const scoped_ptr &other); T *ptr_; }; diff --git a/base/stringutil.h b/base/stringutil.h index e055f089d2..04cb824d57 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -11,17 +11,17 @@ // Dumb wrapper around itoa, providing a buffer. Declare this on the stack. class ITOA { public: - char buffer[16]; - const char *p(int i) { - sprintf(buffer, "%i", i); - return &buffer[0]; - } + char buffer[16]; + const char *p(int i) { + sprintf(buffer, "%i", i); + return &buffer[0]; + } }; // Other simple string utilities. inline bool endsWith(const std::string &str, const std::string &what) { - return str.substr(str.size() - what.size()) == what; + return str.substr(str.size() - what.size()) == what; } // highly unsafe and not recommended. diff --git a/base/timeutil.cpp b/base/timeutil.cpp index 3ab3033547..36a29bea4d 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -18,14 +18,14 @@ __int64 _frequency = 0; __int64 _starttime = 0; double real_time_now(){ - if (_frequency == 0) { - QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); - QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); - curtime=0; - } - __int64 time; - QueryPerformanceCounter((LARGE_INTEGER*)&time); - return ((double) (time - _starttime) / (double) _frequency); + if (_frequency == 0) { + QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); + QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); + curtime=0; + } + __int64 time; + QueryPerformanceCounter((LARGE_INTEGER*)&time); + return ((double) (time - _starttime) / (double) _frequency); } #else @@ -47,17 +47,17 @@ void time_update() { curtime = real_time_now(); curtime_f = (float)curtime; - //printf("curtime: %f %f\n", curtime, curtime_f); - // also smooth time. - //curtime+=float((double) (time-_starttime) / (double) _frequency); - //curtime*=0.5f; - //curtime+=1.0f/60.0f; - //lastTime=curtime; + //printf("curtime: %f %f\n", curtime, curtime_f); + // also smooth time. + //curtime+=float((double) (time-_starttime) / (double) _frequency); + //curtime*=0.5f; + //curtime+=1.0f/60.0f; + //lastTime=curtime; //curtime_f = (float)curtime; } float time_now() { - return curtime_f; + return curtime_f; } double time_now_d() { @@ -65,16 +65,16 @@ double time_now_d() { } int time_now_ms() { - return int(curtime*1000.0); + return int(curtime*1000.0); } void sleep_ms(int ms) { #ifdef _WIN32 #ifndef METRO - Sleep(ms); + Sleep(ms); #endif #else - usleep(ms * 1000); + usleep(ms * 1000); #endif } diff --git a/gfx/gl_debug_log.cpp b/gfx/gl_debug_log.cpp index 3bcfb80f4d..39f2cacb58 100644 --- a/gfx/gl_debug_log.cpp +++ b/gfx/gl_debug_log.cpp @@ -23,13 +23,13 @@ void glCheckzor(const char *file, int line) { #ifndef ANDROID #if 0 void log_callback(GLenum source, GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - GLvoid* userParam) { - const char *src = "unknown"; - switch (source) { + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + GLvoid* userParam) { + const char *src = "unknown"; + switch (source) { case GL_DEBUG_SOURCE_API_GL_ARB: src = "GL"; break; @@ -41,8 +41,8 @@ void log_callback(GLenum source, GLenum type, break; default: break; - } - switch (type) { + } + switch (type) { case GL_DEBUG_TYPE_ERROR_ARB: case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: ELOG("%s: %s", src, message); @@ -50,7 +50,7 @@ void log_callback(GLenum source, GLenum type, default: ILOG("%s: %s", src, message); break; - } + } } #endif #endif diff --git a/gfx/gl_lost_manager.cpp b/gfx/gl_lost_manager.cpp index 0ed6854d92..3d87a204e9 100644 --- a/gfx/gl_lost_manager.cpp +++ b/gfx/gl_lost_manager.cpp @@ -28,7 +28,7 @@ void gl_lost() { return; } for (std::list::iterator iter = holders->begin(); - iter != holders->end(); ++iter) { + iter != holders->end(); ++iter) { (*iter)->GLLost(); } } diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 0132fe49d8..af668de98c 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -68,34 +68,34 @@ static void SetTextureParameters(int zim_flags) { } bool Texture::Load(const char *filename) { - // hook for generated textures - if (!memcmp(filename, "gen:", 4)) { - // TODO - // return false; - int bpp, w, h; - bool clamp; - uint8_t *data = generateTexture(filename, bpp, w, h, clamp); - if (!data) - return false; - glGenTextures(1, &id_); - glBindTexture(GL_TEXTURE_2D, id_); - if (bpp == 1) { + // hook for generated textures + if (!memcmp(filename, "gen:", 4)) { + // TODO + // return false; + int bpp, w, h; + bool clamp; + uint8_t *data = generateTexture(filename, bpp, w, h, clamp); + if (!data) + return false; + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + if (bpp == 1) { - #ifdef ANDROID - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); - #else - glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); - #endif - } else { - FLOG("unsupported"); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - delete [] data; - return true; - } +#ifdef ANDROID + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); +#else + glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); +#endif + } else { + FLOG("unsupported"); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + delete [] data; + return true; + } filename_ = filename; @@ -123,27 +123,27 @@ bool Texture::Load(const char *filename) { const char *name = fn; if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); len = strlen(name); - #ifndef ANDROID +#ifndef ANDROID if (!strcmp("png", &name[len-3]) || - !strcmp("PNG", &name[len-3])) { - if (!LoadPNG(fn)) { - LoadXOR(); - return false; - } else { - return true; - } + !strcmp("PNG", &name[len-3])) { + if (!LoadPNG(fn)) { + LoadXOR(); + return false; + } else { + return true; + } } else - #endif - if (!strcmp("zim", &name[len-3])) { - if (!LoadZIM(name)) { - LoadXOR(); - return false; - } else { - return true; +#endif + if (!strcmp("zim", &name[len-3])) { + if (!LoadZIM(name)) { + LoadXOR(); + return false; + } else { + return true; + } } - } - LoadXOR(); - return false; + LoadXOR(); + return false; } #ifndef ANDROID @@ -157,7 +157,7 @@ bool Texture::LoadPNG(const char *filename) { glBindTexture(GL_TEXTURE_2D, id_); SetTextureParameters(ZIM_GEN_MIPS); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image_data); + GL_RGBA, GL_UNSIGNED_BYTE, image_data); glGenerateMipmap(GL_TEXTURE_2D); GL_CHECK(); free(image_data); @@ -166,22 +166,22 @@ bool Texture::LoadPNG(const char *filename) { #endif bool Texture::LoadXOR() { - width_ = height_ = 256; - unsigned char *buf = new unsigned char[width_*height_*4]; - for (int y = 0; y < 256; y++) { - for (int x = 0; x < 256; x++) { - buf[(y*width_ + x)*4 + 0] = x^y; - buf[(y*width_ + x)*4 + 1] = x^y; - buf[(y*width_ + x)*4 + 2] = x^y; - buf[(y*width_ + x)*4 + 3] = 0xFF; - } - } + width_ = height_ = 256; + unsigned char *buf = new unsigned char[width_*height_*4]; + for (int y = 0; y < 256; y++) { + for (int x = 0; x < 256; x++) { + buf[(y*width_ + x)*4 + 0] = x^y; + buf[(y*width_ + x)*4 + 1] = x^y; + buf[(y*width_ + x)*4 + 2] = x^y; + buf[(y*width_ + x)*4 + 3] = 0xFF; + } + } GL_CHECK(); - glGenTextures(1, &id_); + glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); SetTextureParameters(ZIM_GEN_MIPS); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, - GL_RGBA, GL_UNSIGNED_BYTE, buf); + GL_RGBA, GL_UNSIGNED_BYTE, buf); glGenerateMipmap(GL_TEXTURE_2D); GL_CHECK(); delete [] buf; @@ -198,7 +198,7 @@ uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { for (int y = 0; y < height; y += 4) { for (int x = 0; x < width; x += 4) { DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8, - rgba + (y * width + x) * 4, width, 255); + rgba + (y * width + x) * 4, width, 255); } } return rgba; @@ -256,7 +256,7 @@ bool Texture::LoadZIM(const char *filename) { #else image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h); glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0, - GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]); + GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]); #endif } GL_CHECK(); @@ -266,7 +266,7 @@ bool Texture::LoadZIM(const char *filename) { } else { for (int l = 0; l < num_levels; l++) { glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0, - colors, data_type, image_data[l]); + colors, data_type, image_data[l]); } if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) { glGenerateMipmap(GL_TEXTURE_2D); @@ -282,8 +282,8 @@ bool Texture::LoadZIM(const char *filename) { void Texture::Bind(int stage) { GL_CHECK(); - if (stage != -1) - glActiveTexture(GL_TEXTURE0 + stage); + if (stage != -1) + glActiveTexture(GL_TEXTURE0 + stage); glBindTexture(GL_TEXTURE_2D, id_); GL_CHECK(); } diff --git a/gfx/texture.h b/gfx/texture.h index 8704026284..dbb1e3d30e 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -9,7 +9,7 @@ #include "gfx/gl_lost_manager.h" class Texture : public GfxResourceHolder { - public: +public: Texture(); ~Texture(); @@ -18,10 +18,10 @@ class Texture : public GfxResourceHolder { bool LoadPNG(const char *filename); #endif bool LoadXOR(); // Loads a placeholder texture. - + // Deduces format from the filename. // If loading fails, will load a 256x256 XOR texture. - // If filename begins with "gen:", will defer to texture_gen.cpp/h. + // If filename begins with "gen:", will defer to texture_gen.cpp/h. bool Load(const char *filename); void Bind(int stage = -1); @@ -35,10 +35,10 @@ class Texture : public GfxResourceHolder { virtual void GLLost(); std::string filename() const { return filename_; } - private: +private: std::string filename_; #ifdef METRO - ID3D11Texture2D *tex_; + ID3D11Texture2D *tex_; #endif unsigned int id_; int width_, height_; diff --git a/gfx/texture_gen.cpp b/gfx/texture_gen.cpp index 59226408f0..78545030b0 100644 --- a/gfx/texture_gen.cpp +++ b/gfx/texture_gen.cpp @@ -12,42 +12,42 @@ uint8_t *generateTexture(const char *filename, int &bpp, int &w, int &h, bool &clamp) { - char name_and_params[256]; - // security check :) - if (strlen(filename) > 200) - return 0; - sscanf(filename, "gen:%i:%i:%s", &w, &h, name_and_params); + char name_and_params[256]; + // security check :) + if (strlen(filename) > 200) + return 0; + sscanf(filename, "gen:%i:%i:%s", &w, &h, name_and_params); - bool mip = false; - uint8_t *data; - if (!strcmp(name_and_params, "vignette")) { - bpp = 1; - data = new uint8_t[w*h]; - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; x++) { - float dx = (float)(x - w/2) / (w/2); - float dy = (float)(y - h/2) / (h/2); - float dist = sqrtf(dx * dx + dy * dy); - dist /= 1.414f; - float val = 1.0 - powf(dist, 1.4f); - data[y*w + x] = val * 255; - } - } - } else if (!strcmp(name_and_params, "circle")) { - bpp = 1; - // TODO - data = new uint8_t[w*h]; - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; x++) { - float dx = (float)(x - w/2) / (w/2); - float dy = (float)(y - h/2) / (h/2); - float dist = sqrtf(dx * dx + dy * dy); - dist /= 1.414f; - float val = 1.0 - powf(dist, 1.4f); - data[y*w + x] = val * 255; - } - } - } + bool mip = false; + uint8_t *data; + if (!strcmp(name_and_params, "vignette")) { + bpp = 1; + data = new uint8_t[w*h]; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; x++) { + float dx = (float)(x - w/2) / (w/2); + float dy = (float)(y - h/2) / (h/2); + float dist = sqrtf(dx * dx + dy * dy); + dist /= 1.414f; + float val = 1.0 - powf(dist, 1.4f); + data[y*w + x] = val * 255; + } + } + } else if (!strcmp(name_and_params, "circle")) { + bpp = 1; + // TODO + data = new uint8_t[w*h]; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; x++) { + float dx = (float)(x - w/2) / (w/2); + float dy = (float)(y - h/2) / (h/2); + float dist = sqrtf(dx * dx + dy * dy); + dist /= 1.414f; + float val = 1.0 - powf(dist, 1.4f); + data[y*w + x] = val * 255; + } + } + } - return data; + return data; } diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 7a3a687b98..b4b3694c6f 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -41,7 +41,7 @@ void DrawBuffer::Begin(DrawBufferMode dbmode) { } void DrawBuffer::End() { - // Currently does nothing, but call it! + // Currently does nothing, but call it! } void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { @@ -49,10 +49,10 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { return; glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - if (set_blend_state) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } + if (set_blend_state) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } glUniform1i(program->sampler0, 0); glEnableVertexAttribArray(program->a_position); glEnableVertexAttribArray(program->a_color); @@ -71,11 +71,11 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { glDisableVertexAttribArray(program->a_texcoord0); GL_CHECK(); - count_ = 0; + count_ = 0; } void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) { - Vertex *vert = &verts_[count_++]; + Vertex *vert = &verts_[count_++]; vert->x = x; vert->y = y; vert->z = z; @@ -85,36 +85,36 @@ void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) { } void DrawBuffer::Rect(float x, float y, float w, float h, uint32 color, int align) { - DoAlign(align, &x, &y, &w, &h); + DoAlign(align, &x, &y, &w, &h); RectVGradient(x, y, w, h, color, color); } void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom) { - V(x, y, 0, colorTop, 0, 0); - V(x + w, y, 0, colorTop, 1, 0); - V(x + w, y + h, 0, colorBottom, 1, 1); - V(x, y, 0, colorTop, 0, 0); - V(x + w, y + h, 0, colorBottom, 1, 1); - V(x, y + h, 0, colorBottom, 0, 1); + V(x, y, 0, colorTop, 0, 0); + V(x + w, y, 0, colorTop, 1, 0); + V(x + w, y + h, 0, colorBottom, 1, 1); + V(x, y, 0, colorTop, 0, 0); + V(x + w, y + h, 0, colorBottom, 1, 1); + V(x, y + h, 0, colorBottom, 0, 1); } void DrawBuffer::MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops) { - for (int i = 0; i < numStops - 1; i++) { - float t0 = stops[i].t, t1 = stops[i+1].t; - uint32_t c0 = stops[i].t, c1 = stops[i+1].t; - RectVGradient(x, y + h * t0, w, h * (t1 - t0), c0, c1); - } + for (int i = 0; i < numStops - 1; i++) { + float t0 = stops[i].t, t1 = stops[i+1].t; + uint32_t c0 = stops[i].t, c1 = stops[i+1].t; + RectVGradient(x, y + h * t0, w, h * (t1 - t0), c0, c1); + } } void DrawBuffer::Rect(float x, float y, float w, float h, - float u, float v, float uw, float uh, - uint32 color) { - V(x, y, 0, color, u, v); - V(x + w, y, 0, color, u + uw, v); - V(x + w, y + h, 0, color, u + uw, v + uh); - V(x, y, 0, color, u, v); - V(x + w, y + h, 0, color, u + uw, v + uh); - V(x, y + h, 0, color, u, v + uh); + float u, float v, float uw, float uh, + uint32 color) { + V(x, y, 0, color, u, v); + V(x + w, y, 0, color, u + uw, v); + V(x + w, y + h, 0, color, u + uw, v + uh); + V(x, y, 0, color, u, v); + V(x + w, y + h, 0, color, u + uw, v + uh); + V(x, y + h, 0, color, u, v + uh); } void DrawBuffer::MeasureImage(int atlas_image, float *w, float *h) { @@ -127,10 +127,10 @@ void DrawBuffer::DrawImage(int atlas_image, float x, float y, float scale, Color const AtlasImage &image = atlas->images[atlas_image]; float w = (float)image.w * scale; float h = (float)image.h * scale; - if (align & ALIGN_HCENTER) x -= w / 2; - if (align & ALIGN_RIGHT) x -= w; - if (align & ALIGN_VCENTER) y -= h / 2; - if (align & ALIGN_BOTTOM) y -= h; + if (align & ALIGN_HCENTER) x -= w / 2; + if (align & ALIGN_RIGHT) x -= w; + if (align & ALIGN_VCENTER) y -= h / 2; + if (align & ALIGN_BOTTOM) y -= h; DrawImageStretch(atlas_image, x, y, x + w, y + h, color); } @@ -144,76 +144,74 @@ void DrawBuffer::DrawImageStretch(int atlas_image, float x1, float y1, float x2, V(x1, y2, color, image.u1, image.v2); } +inline void rot(float *v, float angle, float xc, float yc) { + v[0]-=xc; + v[1]-=yc; -inline void rot(float *v, float angle, float xc,float yc) -{ - v[0]-=xc; - v[1]-=yc; + float ca=cosf(angle),sa=sinf(angle); - float ca=cosf(angle),sa=sinf(angle); + float t0 = v[0] * ca + v[1] * -sa; + float t1 = v[0] * sa + v[1] * ca; - float t0 = v[0] * ca + v[1] * -sa; - float t1 = v[0] * sa + v[1] * ca; - - v[0] = t0 + xc; - v[1] = t1 + yc; + v[0] = t0 + xc; + v[1] = t1 + yc; } void DrawBuffer::DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color) { - const AtlasImage &image = atlas->images[atlas_image]; - float w = (float)image.w * scale; - float h = (float)image.h * scale; - float x1 = x - w / 2; - float x2 = x + w / 2; - float y1 = y - h / 2; - float y2 = y + h / 2; - float v[6][2] = { - {x1, y1}, - {x2, y1}, - {x2, y2}, - {x1, y1}, - {x2, y2}, - {x1, y2}, - }; - const float uv[6][2] = { - {image.u1, image.v1}, - {image.u2, image.v1}, - {image.u2, image.v2}, - {image.u1, image.v1}, - {image.u2, image.v2}, - {image.u1, image.v2}, - }; - for (int i = 0; i < 6; i++) { - rot(v[i], angle, x, y); - V(v[i][0], v[i][1], 0, color, uv[i][0], uv[i][1]); - } + const AtlasImage &image = atlas->images[atlas_image]; + float w = (float)image.w * scale; + float h = (float)image.h * scale; + float x1 = x - w / 2; + float x2 = x + w / 2; + float y1 = y - h / 2; + float y2 = y + h / 2; + float v[6][2] = { + {x1, y1}, + {x2, y1}, + {x2, y2}, + {x1, y1}, + {x2, y2}, + {x1, y2}, + }; + const float uv[6][2] = { + {image.u1, image.v1}, + {image.u2, image.v1}, + {image.u2, image.v2}, + {image.u1, image.v1}, + {image.u2, image.v2}, + {image.u1, image.v2}, + }; + for (int i = 0; i < 6; i++) { + rot(v[i], angle, x, y); + V(v[i][0], v[i][1], 0, color, uv[i][0], uv[i][1]); + } } // TODO: add arc support void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul) { - float angleDelta = PI * 2 / segments; - float uDelta = 1.0f / segments; - float t2 = thickness / 2.0f; - float r1 = radius + t2; - float r2 = radius - t2; - for (int i = 0; i < segments + 1; i++) { - float angle1 = i * angleDelta; - float angle2 = (i + 1) * angleDelta; - float u1 = u_mul * i * uDelta; - float u2 = u_mul * (i + 1) * uDelta; - // TODO: get rid of one pair of cos/sin per loop, can reuse from last iteration - float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2); - const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc}; - const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc}; - V(x[0], y[0], color, u1, 0); - V(x[1], y[1], color, u2, 0); - V(x[2], y[2], color, u1, 1); - V(x[1], y[1], color, u2, 0); - V(x[3], y[3], color, u2, 1); - V(x[2], y[2], color, u1, 1); - } + float angleDelta = PI * 2 / segments; + float uDelta = 1.0f / segments; + float t2 = thickness / 2.0f; + float r1 = radius + t2; + float r2 = radius - t2; + for (int i = 0; i < segments + 1; i++) { + float angle1 = i * angleDelta; + float angle2 = (i + 1) * angleDelta; + float u1 = u_mul * i * uDelta; + float u2 = u_mul * (i + 1) * uDelta; + // TODO: get rid of one pair of cos/sin per loop, can reuse from last iteration + float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2); + const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc}; + const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc}; + V(x[0], y[0], color, u1, 0); + V(x[1], y[1], color, u2, 0); + V(x[2], y[2], color, u1, 1); + V(x[1], y[1], color, u2, 0); + V(x[3], y[3], color, u2, 1); + V(x[2], y[2], color, u1, 1); + } } void DrawBuffer::DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color) { @@ -268,14 +266,14 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { const AtlasFont &atlasfont = *atlas->fonts[font]; unsigned char cval; float wacc = 0, maxh = 0; - int lines = 1; + int lines = 1; while ((cval = *text++) != '\0') { if (cval < 32) continue; if (cval > 127) continue; - if (cval == '\n') { - wacc = 0; - lines++; - } + if (cval == '\n') { + wacc = 0; + lines++; + } AtlasChar c = atlasfont.chars[cval - 32]; wacc += c.wx * fontscalex; } @@ -284,20 +282,20 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { } void DrawBuffer::DrawTextShadow(int font, const char *text, float x, float y, Color color, int flags) { - uint32_t alpha = (color >> 1) & 0xFF000000; + uint32_t alpha = (color >> 1) & 0xFF000000; DrawText(font, text, x + 2, y + 2, alpha, flags); DrawText(font, text, x, y, color, flags); } void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) { - if (flags & ALIGN_HCENTER) *x -= *w / 2; - if (flags & ALIGN_RIGHT) *x -= *w; - if (flags & ALIGN_VCENTER) *y -= *h / 2; - if (flags & ALIGN_BOTTOM) *y -= *h; - if (flags & (ROTATE_90DEG_LEFT | ROTATE_90DEG_RIGHT)) { - std::swap(*w, *h); - std::swap(*x, *y); - } + if (flags & ALIGN_HCENTER) *x -= *w / 2; + if (flags & ALIGN_RIGHT) *x -= *w; + if (flags & ALIGN_VCENTER) *y -= *h / 2; + if (flags & ALIGN_BOTTOM) *y -= *h; + if (flags & (ROTATE_90DEG_LEFT | ROTATE_90DEG_RIGHT)) { + std::swap(*w, *h); + std::swap(*x, *y); + } } // ROTATE_* doesn't yet work right. @@ -307,15 +305,15 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co float w, h; MeasureText(font, text, &w, &h); if (flags) { - DoAlign(flags, &x, &y, &w, &h); + DoAlign(flags, &x, &y, &w, &h); } - - if (flags & ROTATE_90DEG_LEFT) { - x -= atlasfont.ascend*fontscaley; - // y += h; - } - else - y += atlasfont.ascend*fontscaley; + + if (flags & ROTATE_90DEG_LEFT) { + x -= atlasfont.ascend*fontscaley; + // y += h; + } + else + y += atlasfont.ascend*fontscaley; float sx = x; while ((cval = *text++) != '\0') { if (cval == '\n') { @@ -326,46 +324,46 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co if (cval < 32) continue; if (cval > 127) continue; AtlasChar c = atlasfont.chars[cval - 32]; - float cx1, cy1, cx2, cy2; - if (flags & ROTATE_90DEG_LEFT) { - cy1 = y - c.ox * fontscalex; - cx1 = x + c.oy * fontscaley; - cy2 = y - (c.ox + c.pw) * fontscalex; - cx2 = x + (c.oy + c.ph) * fontscaley; - } else { - cx1 = x + c.ox * fontscalex; + float cx1, cy1, cx2, cy2; + if (flags & ROTATE_90DEG_LEFT) { + cy1 = y - c.ox * fontscalex; + cx1 = x + c.oy * fontscaley; + cy2 = y - (c.ox + c.pw) * fontscalex; + cx2 = x + (c.oy + c.ph) * fontscaley; + } else { + cx1 = x + c.ox * fontscalex; cy1 = y + c.oy * fontscaley; cx2 = x + (c.ox + c.pw) * fontscalex; cy2 = y + (c.oy + c.ph) * fontscaley; - } + } V(cx1, cy1, color, c.sx, c.sy); V(cx2, cy1, color, c.ex, c.sy); V(cx2, cy2, color, c.ex, c.ey); V(cx1, cy1, color, c.sx, c.sy); V(cx2, cy2, color, c.ex, c.ey); V(cx1, cy2, color, c.sx, c.ey); - if (flags & ROTATE_90DEG_LEFT) - y -= c.wx * fontscalex; - else - x += c.wx * fontscalex; + if (flags & ROTATE_90DEG_LEFT) + y -= c.wx * fontscalex; + else + x += c.wx * fontscalex; } } void DrawBuffer::EnableBlend(bool enable) { - if (enable) - glEnable(GL_BLEND); - else - glDisable(GL_BLEND); + if (enable) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); } void DrawBuffer::SetClipRect(float x, float y, float w, float h) { - // Sigh, OpenGL is upside down. - glScissor(x, g_yres - y, w, h); - glEnable(GL_SCISSOR_TEST); + // Sigh, OpenGL is upside down. + glScissor(x, g_yres - y, w, h); + glEnable(GL_SCISSOR_TEST); } void DrawBuffer::NoClip() { - glDisable(GL_SCISSOR_TEST); + glDisable(GL_SCISSOR_TEST); } diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 36a16b6c00..9e65bb3df9 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -9,22 +9,22 @@ struct Atlas; enum { ALIGN_LEFT = 0, - ALIGN_RIGHT = 16, - ALIGN_TOP = 0, - ALIGN_BOTTOM = 1, + ALIGN_RIGHT = 16, + ALIGN_TOP = 0, + ALIGN_BOTTOM = 1, ALIGN_HCENTER = 4, ALIGN_VCENTER = 8, - ALIGN_VBASELINE = 32, // text only, possibly not yet working + ALIGN_VBASELINE = 32, // text only, possibly not yet working - ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT, - ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT, - ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT, - ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT, + ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT, + ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT, + ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT, + ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT, - // Only for text drawing - ROTATE_90DEG_LEFT = 256, - ROTATE_90DEG_RIGHT = 512, - ROTATE_180DEG = 1024, + // Only for text drawing + ROTATE_90DEG_LEFT = 256, + ROTATE_90DEG_RIGHT = 512, + ROTATE_180DEG = 1024, }; struct GLSLProgram; @@ -36,12 +36,12 @@ enum DrawBufferMode { struct GradientStop { - float t; - uint32_t color; + float t; + uint32_t color; }; class DrawBuffer { - public: +public: DrawBuffer(); ~DrawBuffer(); @@ -52,21 +52,21 @@ class DrawBuffer { void Flush(const GLSLProgram *program, bool set_blend_state=true); void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); - void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom); + void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom); - void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops); + void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops); void RectCenter(float x, float y, float w, float h, uint32 color) { Rect(x - w/2, y - h/2, w, h, color); } void Rect(float x, float y, float w, float h, - float u, float v, float uw, float uh, uint32 color); + float u, float v, float uw, float uh, uint32 color); void V(float x, float y, float z, uint32 color, float u, float v); void V(float x, float y, uint32 color, float u, float v) { V(x, y, 0.0f, color, u, v); } - void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul); + void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul); // New drawing APIs @@ -77,7 +77,7 @@ class DrawBuffer { void MeasureImage(int atlas_image, float *w, float *h); void DrawImage(int atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT); void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); - void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF)); // Always centers + void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF)); // Always centers void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); // Results in 18 triangles. Kind of expensive for a button. void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); @@ -85,7 +85,7 @@ class DrawBuffer { void DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); void MeasureText(int font, const char *text, float *w, float *h); - void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); + void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); void DrawTextShadow(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); void RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color); @@ -94,18 +94,18 @@ class DrawBuffer { fontscaley = ys; } - // Utility to avoid having to include gl.h just for this in UI code. - void EnableBlend(bool enable); + // Utility to avoid having to include gl.h just for this in UI code. + void EnableBlend(bool enable); - // Rectangular clipping, implemented using scissoring. - // Must flush before and after. - void SetClipRect(float x1, float y1, float x2, float y2); - void NoClip(); + // Rectangular clipping, implemented using scissoring. + // Must flush before and after. + void SetClipRect(float x1, float y1, float x2, float y2); + void NoClip(); - private: - void DoAlign(int flags, float *x, float *y, float *w, float *h); +private: + void DoAlign(int flags, float *x, float *y, float *w, float *h); struct Vertex { float x, y, z; uint32_t rgba; diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 311abc3cd0..6b1759e945 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -47,15 +47,15 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); switch(status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: - ILOG("Framebuffer verified complete."); - break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - ELOG("Framebuffer format not supported"); - break; - default: - FLOG("Other framebuffer error: %i", status); - break; + case GL_FRAMEBUFFER_COMPLETE_EXT: + ILOG("Framebuffer verified complete."); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + ELOG("Framebuffer format not supported"); + break; + default: + FLOG("Other framebuffer error: %i", status); + break; } // Unbind state we don't need glBindRenderbuffer(GL_RENDERBUFFER, 0); diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index be93cdfca3..74b6f108d1 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -24,25 +24,25 @@ typedef char GLchar; static std::set active_programs; bool CompileShader(const char *source, GLuint shader, const char *filename) { - glShaderSource(shader, 1, &source, NULL); - glCompileShader(shader); - GLint success; - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (!success) { + glShaderSource(shader, 1, &source, NULL); + glCompileShader(shader); + GLint success; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) { #define MAX_INFO_LOG_SIZE 2048 - GLchar infoLog[MAX_INFO_LOG_SIZE]; + GLchar infoLog[MAX_INFO_LOG_SIZE]; GLsizei len; - glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog); + glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog); infoLog[len] = '\0'; - ELOG("Error in shader compilation of %s!\n", filename); - ELOG("Info log: %s\n", infoLog); - ELOG("Shader source:\n%s\n", (const char *)source); + ELOG("Error in shader compilation of %s!\n", filename); + ELOG("Info log: %s\n", infoLog); + ELOG("Shader source:\n%s\n", (const char *)source); #ifdef ANDROID - exit(1); + exit(1); #endif - return false; - } - return true; + return false; + } + return true; } GLSLProgram *glsl_create(const char *vshader, const char *fshader) { @@ -50,7 +50,7 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader) { program->program_ = 0; program->vsh_ = 0; program->fsh_ = 0; - strcpy(program->name, vshader + strlen(vshader) - 15); + strcpy(program->name, vshader + strlen(vshader) - 15); strcpy(program->vshader_filename, vshader); strcpy(program->fshader_filename, fshader); if (glsl_recompile(program)) { @@ -65,8 +65,8 @@ bool glsl_up_to_date(GLSLProgram *program) { stat(program->vshader_filename, &vs); stat(program->fshader_filename, &fs); if (vs.st_mtime != program->vshader_mtime || - fs.st_mtime != program->fshader_mtime) { - return false; + fs.st_mtime != program->fshader_mtime) { + return false; } else { return true; } @@ -75,74 +75,74 @@ bool glsl_up_to_date(GLSLProgram *program) { void glsl_refresh() { ILOG("glsl_refresh()"); for (std::set::const_iterator iter = active_programs.begin(); - iter != active_programs.end(); ++iter) { - if (!glsl_up_to_date(*iter)) { - glsl_recompile(*iter); - } + iter != active_programs.end(); ++iter) { + if (!glsl_up_to_date(*iter)) { + glsl_recompile(*iter); + } } } bool glsl_recompile(GLSLProgram *program) { struct stat vs, fs; if (0 == stat(program->vshader_filename, &vs)) - program->vshader_mtime = vs.st_mtime; - else - program->vshader_mtime = 0; + program->vshader_mtime = vs.st_mtime; + else + program->vshader_mtime = 0; if (0 == stat(program->fshader_filename, &fs)) - program->fshader_mtime = fs.st_mtime; - else - program->fshader_mtime = 0; + program->fshader_mtime = fs.st_mtime; + else + program->fshader_mtime = 0; size_t sz; - char *vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz); + char *vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz); if (!vsh_src) { ELOG("File missing: %s", vsh_src); return false; } - char *fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz); + char *fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz); if (!fsh_src) { ELOG("File missing: %s", fsh_src); delete [] vsh_src; return false; } - GLuint vsh = glCreateShader(GL_VERTEX_SHADER); - const GLchar *vsh_str = (const GLchar *)(vsh_src); - if (!CompileShader(vsh_str, vsh, program->vshader_filename)) { + GLuint vsh = glCreateShader(GL_VERTEX_SHADER); + const GLchar *vsh_str = (const GLchar *)(vsh_src); + if (!CompileShader(vsh_str, vsh, program->vshader_filename)) { return false; } delete [] vsh_src; - const GLchar *fsh_str = (const GLchar *)(fsh_src); - GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); + const GLchar *fsh_str = (const GLchar *)(fsh_src); + GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); if (!CompileShader(fsh_str, fsh, program->fshader_filename)) { glDeleteShader(vsh); return false; } - delete [] fsh_src; + delete [] fsh_src; GLuint prog = glCreateProgram(); - glAttachShader(prog, vsh); - glAttachShader(prog, fsh); + glAttachShader(prog, vsh); + glAttachShader(prog, fsh); - glLinkProgram(prog); + glLinkProgram(prog); - GLint linkStatus; - glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint bufLength = 0; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength); - if (bufLength) { - char* buf = new char[bufLength]; - glGetProgramInfoLog(prog, bufLength, NULL, buf); - FLOG("Could not link program:\n %s", buf); - delete [] buf; // we're dead! - } + GLint linkStatus; + glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) { + GLint bufLength = 0; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength); + if (bufLength) { + char* buf = new char[bufLength]; + glGetProgramInfoLog(prog, bufLength, NULL, buf); + FLOG("Could not link program:\n %s", buf); + delete [] buf; // we're dead! + } glDeleteShader(vsh); glDeleteShader(fsh); - return false; - } + return false; + } // Destroy the old program, if any. if (program->program_) { @@ -153,23 +153,23 @@ bool glsl_recompile(GLSLProgram *program) { program->vsh_ = vsh; program->fsh_ = vsh; - program->sampler0 = glGetUniformLocation(program->program_, "sampler0"); - program->sampler1 = glGetUniformLocation(program->program_, "sampler1"); + program->sampler0 = glGetUniformLocation(program->program_, "sampler0"); + program->sampler1 = glGetUniformLocation(program->program_, "sampler1"); - program->a_position = glGetAttribLocation(program->program_, "a_position"); - program->a_color = glGetAttribLocation(program->program_, "a_color"); - program->a_normal = glGetAttribLocation(program->program_, "a_normal"); - program->a_texcoord0 = glGetAttribLocation(program->program_, "a_texcoord0"); - program->a_texcoord1 = glGetAttribLocation(program->program_, "a_texcoord1"); + program->a_position = glGetAttribLocation(program->program_, "a_position"); + program->a_color = glGetAttribLocation(program->program_, "a_color"); + program->a_normal = glGetAttribLocation(program->program_, "a_normal"); + program->a_texcoord0 = glGetAttribLocation(program->program_, "a_texcoord0"); + program->a_texcoord1 = glGetAttribLocation(program->program_, "a_texcoord1"); - program->u_worldviewproj = glGetUniformLocation(program->program_, "u_worldviewproj"); - program->u_world = glGetUniformLocation(program->program_, "u_world"); - program->u_viewproj = glGetUniformLocation(program->program_, "u_viewproj"); - program->u_fog = glGetUniformLocation(program->program_, "u_fog"); - program->u_sundir = glGetUniformLocation(program->program_, "u_sundir"); - program->u_camerapos = glGetUniformLocation(program->program_, "u_camerapos"); + program->u_worldviewproj = glGetUniformLocation(program->program_, "u_worldviewproj"); + program->u_world = glGetUniformLocation(program->program_, "u_world"); + program->u_viewproj = glGetUniformLocation(program->program_, "u_viewproj"); + program->u_fog = glGetUniformLocation(program->program_, "u_fog"); + program->u_sundir = glGetUniformLocation(program->program_, "u_sundir"); + program->u_camerapos = glGetUniformLocation(program->program_, "u_camerapos"); - //ILOG("Shader compilation success: %s %s", + //ILOG("Shader compilation success: %s %s", // program->vshader_filename, // program->fshader_filename); return true; @@ -194,17 +194,17 @@ int glsl_uniform_loc(const GLSLProgram *program, const char *name) { void glsl_destroy(GLSLProgram *program) { unregister_gl_resource_holder(program); - glDeleteShader(program->vsh_); - glDeleteShader(program->fsh_); - glDeleteProgram(program->program_); + glDeleteShader(program->vsh_); + glDeleteShader(program->fsh_); + glDeleteProgram(program->program_); active_programs.erase(program); delete program; } void glsl_bind(const GLSLProgram *program) { - glUseProgram(program->program_); + glUseProgram(program->program_); } void glsl_unbind() { - glUseProgram(0); + glUseProgram(0); } diff --git a/gfx_es2/vertex_format.cpp b/gfx_es2/vertex_format.cpp index 335029437d..2823901c12 100644 --- a/gfx_es2/vertex_format.cpp +++ b/gfx_es2/vertex_format.cpp @@ -3,69 +3,69 @@ #include "gfx_es2/vertex_format.h" static const GLuint formatLookup[16] = { - GL_FLOAT, - 0, //GL_HALF_FLOAT_EXT, - GL_UNSIGNED_SHORT, - GL_UNSIGNED_BYTE, - 0, //GL_UNSIGNED_INT_10_10_10_2, - 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + GL_FLOAT, + 0, //GL_HALF_FLOAT_EXT, + GL_UNSIGNED_SHORT, + GL_UNSIGNED_BYTE, + 0, //GL_UNSIGNED_INT_10_10_10_2, + 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; void SetVertexFormat(const GLSLProgram *program, uint32_t vertexFormat) { - // First special case our favorites - if (vertexFormat == (POS_FLOAT | NRM_FLOAT | UV0_FLOAT)) { - const int vertexSize = 3*4 + 3*4 + 2*4; - glUniform1i(program->sampler0, 0); - glEnableVertexAttribArray(program->a_position); - glEnableVertexAttribArray(program->a_normal); - glEnableVertexAttribArray(program->a_texcoord0); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0); - glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12); - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); - return; - } - - // Then have generic code here. + // First special case our favorites + if (vertexFormat == (POS_FLOAT | NRM_FLOAT | UV0_FLOAT)) { + const int vertexSize = 3*4 + 3*4 + 2*4; + glUniform1i(program->sampler0, 0); + glEnableVertexAttribArray(program->a_position); + glEnableVertexAttribArray(program->a_normal); + glEnableVertexAttribArray(program->a_texcoord0); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0); + glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12); + glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); + return; + } + + // Then have generic code here. - int vertexSize = 0; + int vertexSize = 0; - FLOG("TODO: Write generic code."); + FLOG("TODO: Write generic code."); - if (vertexFormat & UV0_MASK) { - glUniform1i(program->sampler0, 0); - } + if (vertexFormat & UV0_MASK) { + glUniform1i(program->sampler0, 0); + } glEnableVertexAttribArray(program->a_position); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0); - if (vertexFormat & NRM_MASK) { - glEnableVertexAttribArray(program->a_normal); - glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12); - } - if (vertexFormat & UV0_MASK) { - glEnableVertexAttribArray(program->a_texcoord0); - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); - } - if (vertexFormat & UV1_MASK) { - glEnableVertexAttribArray(program->a_texcoord1); - glVertexAttribPointer(program->a_texcoord1, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); - } - if (vertexFormat & RGBA_MASK) { - glEnableVertexAttribArray(program->a_color); - glVertexAttribPointer(program->a_color, 4, GL_FLOAT, GL_FALSE, vertexSize, (void *)28); - } + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0); + if (vertexFormat & NRM_MASK) { + glEnableVertexAttribArray(program->a_normal); + glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12); + } + if (vertexFormat & UV0_MASK) { + glEnableVertexAttribArray(program->a_texcoord0); + glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); + } + if (vertexFormat & UV1_MASK) { + glEnableVertexAttribArray(program->a_texcoord1); + glVertexAttribPointer(program->a_texcoord1, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); + } + if (vertexFormat & RGBA_MASK) { + glEnableVertexAttribArray(program->a_color); + glVertexAttribPointer(program->a_color, 4, GL_FLOAT, GL_FALSE, vertexSize, (void *)28); + } } // TODO: Save state so that we can get rid of this. void UnsetVertexFormat(const GLSLProgram *program, uint32 vertexFormat) { glDisableVertexAttribArray(program->a_position); if (vertexFormat & NRM_MASK) - glDisableVertexAttribArray(program->a_normal); + glDisableVertexAttribArray(program->a_normal); if (vertexFormat & UV0_MASK) - glDisableVertexAttribArray(program->a_texcoord0); + glDisableVertexAttribArray(program->a_texcoord0); if (vertexFormat & UV1_MASK) - glDisableVertexAttribArray(program->a_texcoord1); + glDisableVertexAttribArray(program->a_texcoord1); if (vertexFormat & RGBA_MASK) - glDisableVertexAttribArray(program->a_color); + glDisableVertexAttribArray(program->a_color); } diff --git a/gfx_es2/vertex_format.h b/gfx_es2/vertex_format.h index edaac48145..8a0b0aed11 100644 --- a/gfx_es2/vertex_format.h +++ b/gfx_es2/vertex_format.h @@ -6,42 +6,42 @@ // Vertex format flags enum VtxFmt { - POS_FLOAT = 1, - POS_FLOAT16 = 2, - POS_UINT16 = 3, - POS_UINT8 = 4, - POS_101010 = 5, + POS_FLOAT = 1, + POS_FLOAT16 = 2, + POS_UINT16 = 3, + POS_UINT8 = 4, + POS_101010 = 5, - NRM_FLOAT = 1 << 4, - NRM_FLOAT16 = 2 << 4, - NRM_SINT16 = 3 << 4, - NRM_UINT8 = 4 << 4, - NRM_101010 = 5 << 4, + NRM_FLOAT = 1 << 4, + NRM_FLOAT16 = 2 << 4, + NRM_SINT16 = 3 << 4, + NRM_UINT8 = 4 << 4, + NRM_101010 = 5 << 4, - TANGENT_FLOAT = 1 << 8, - //.... + TANGENT_FLOAT = 1 << 8, + //.... - UV0_NONE = 1 << 12, - UV0_FLOAT = 1 << 12, - // .... - UV1_NONE = 1 << 16, - UV1_FLOAT = 1 << 16, + UV0_NONE = 1 << 12, + UV0_FLOAT = 1 << 12, + // .... + UV1_NONE = 1 << 16, + UV1_FLOAT = 1 << 16, - RGBA_NONE = 0 << 20, - RGBA_FLOAT = 1 << 20, - RGBA_FLOAT16 = 2 << 20, - RGBA_UINT16 = 3 << 20, - RGBA_UINT8 = 4 << 20, - RGBA_101010 = 5 << 20, + RGBA_NONE = 0 << 20, + RGBA_FLOAT = 1 << 20, + RGBA_FLOAT16 = 2 << 20, + RGBA_UINT16 = 3 << 20, + RGBA_UINT8 = 4 << 20, + RGBA_101010 = 5 << 20, - POS_MASK = 0x0000000F, - NRM_MASK = 0x000000F0, - TANGENT_MASK = 0x00000F00, - UV0_MASK = 0x0000F000, - UV1_MASK = 0x000F0000, - RGBA_MASK = 0x00F00000, + POS_MASK = 0x0000000F, + NRM_MASK = 0x000000F0, + TANGENT_MASK = 0x00000F00, + UV0_MASK = 0x0000F000, + UV1_MASK = 0x000F0000, + RGBA_MASK = 0x00F00000, - // Can add more here, such as a generic AUX or something. Don't know what to use it for though. Hardness for cloth sim? + // Can add more here, such as a generic AUX or something. Don't know what to use it for though. Hardness for cloth sim? }; struct GLSLProgram; diff --git a/image/surface.h b/image/surface.h deleted file mode 100644 index 2434f1c38c..0000000000 --- a/image/surface.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _GFX_SURFACE -#define _GFX_SURFACE - -// UNUSED - - -enum SurfaceFormats { - SURF_ARGB, - SURF_YUV, -}; - -struct cairo_surface_t; - -class Surface { - public: - Surface(int width, int height); - - // In case of YUV, U and V channels have half size, rounded UP. - int height() const { return height_; } - int width() const { return width_; } - int pitch() const { return pitch_; } - - int half_width() const { return (width_ + 1) >> 1; } - int half_height() const { return (height_ + 1) >> 1; } - - cairo_surface_t *CreateCairoSurface(); - private: - uint8 *data_; - int width_; - int height_; - int pitch_; -}; - -#endif diff --git a/image/zim_load.cpp b/image/zim_load.cpp index 1cc2c406bf..23b2693cd3 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -8,42 +8,42 @@ #include "file/vfs.h" int ezuncompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) { - z_stream stream; - stream.next_in = (Bytef*)pSrc; - stream.avail_in = (uInt)nSrcLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != (uLong)nSrcLen) return Z_BUF_ERROR; + z_stream stream; + stream.next_in = (Bytef*)pSrc; + stream.avail_in = (uInt)nSrcLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != (uLong)nSrcLen) return Z_BUF_ERROR; - uInt destlen = (uInt)*pnDestLen; - if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; + uInt destlen = (uInt)*pnDestLen; + if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; - int err = inflateInit(&stream); - if (err != Z_OK) return err; + int err = inflateInit(&stream); + if (err != Z_OK) return err; - int nExtraChunks = 0; - do { - stream.next_out = pDest; - stream.avail_out = destlen; - err = inflate(&stream, Z_FINISH); - if (err == Z_STREAM_END ) - break; - if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) - err = Z_DATA_ERROR; - if (err != Z_BUF_ERROR) { - inflateEnd(&stream); - return err; - } - nExtraChunks += 1; - } while (stream.avail_out == 0); + int nExtraChunks = 0; + do { + stream.next_out = pDest; + stream.avail_out = destlen; + err = inflate(&stream, Z_FINISH); + if (err == Z_STREAM_END ) + break; + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + err = Z_DATA_ERROR; + if (err != Z_BUF_ERROR) { + inflateEnd(&stream); + return err; + } + nExtraChunks += 1; + } while (stream.avail_out == 0); - *pnDestLen = stream.total_out; + *pnDestLen = stream.total_out; - err = inflateEnd(&stream); - if (err != Z_OK) return err; + err = inflateEnd(&stream); + if (err != Z_OK) return err; - return nExtraChunks ? Z_BUF_ERROR : Z_OK; + return nExtraChunks ? Z_BUF_ERROR : Z_OK; } static const char magic[5] = "ZIMG"; @@ -57,13 +57,13 @@ static unsigned int log2i(unsigned int val) { } int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, uint8 **image) { - if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') { - ELOG("Not a ZIM file"); + if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') { + ELOG("Not a ZIM file"); return 0; - } - memcpy(width, zim + 4, 4); - memcpy(height, zim + 8, 4); - memcpy(flags, zim + 12, 4); + } + memcpy(width, zim + 4, 4); + memcpy(height, zim + 8, 4); + memcpy(flags, zim + 12, 4); int num_levels = 1; int image_data_size[ZIM_MAX_MIP_LEVELS]; @@ -76,14 +76,14 @@ int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, width[i] = width[i-1] / 2; height[i] = height[i-1] / 2; } - switch (*flags & ZIM_FORMAT_MASK) { - case ZIM_RGBA8888: - image_data_size[i] = width[i] * height[i] * 4; - break; - case ZIM_RGBA4444: + switch (*flags & ZIM_FORMAT_MASK) { + case ZIM_RGBA8888: + image_data_size[i] = width[i] * height[i] * 4; + break; + case ZIM_RGBA4444: case ZIM_RGB565: - image_data_size[i] = width[i] * height[i] * 2; - break; + image_data_size[i] = width[i] * height[i] * 2; + break; case ZIM_ETC1: { int data_width = width[i]; @@ -93,47 +93,47 @@ int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, image_data_size[i] = data_width * data_height / 2; break; } - default: - ELOG("Invalid ZIM format %i", *flags & ZIM_FORMAT_MASK); - return 0; - } + default: + ELOG("Invalid ZIM format %i", *flags & ZIM_FORMAT_MASK); + return 0; + } total_data_size += image_data_size[i]; } - image[0] = (uint8 *)malloc(total_data_size); + image[0] = (uint8 *)malloc(total_data_size); for (int i = 1; i < num_levels; i++) { image[i] = image[i-1] + image_data_size[i-1]; } if (*flags & ZIM_ZLIB_COMPRESSED) { - long outlen = total_data_size; - if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), datasize - 16)) { - free(*image); - *image = 0; - return 0; - } - if (outlen != total_data_size) { - ELOG("Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size); - } + long outlen = total_data_size; + if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), datasize - 16)) { + free(*image); + *image = 0; + return 0; + } + if (outlen != total_data_size) { + ELOG("Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size); + } } else { memcpy(*image, zim + 16, datasize - 16); if (datasize - 16 != total_data_size) { - ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size); + ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size); } } - return num_levels; + return num_levels; } int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t **image) { - size_t size; - uint8_t *buffer = VFSReadFile(filename, &size); - if (!buffer) { - return 0; - } - int retval = LoadZIMPtr(buffer, size, width, height, format, image); - if (!retval) { - ELOG("Not a valid ZIM file: %s", filename); - } - delete [] buffer; - return retval; + size_t size; + uint8_t *buffer = VFSReadFile(filename, &size); + if (!buffer) { + return 0; + } + int retval = LoadZIMPtr(buffer, size, width, height, format, image); + if (!retval) { + ELOG("Not a valid ZIM file: %s", filename); + } + delete [] buffer; + return retval; } diff --git a/image/zim_save.cpp b/image/zim_save.cpp index 52e3c9c400..c4a06b2565 100644 --- a/image/zim_save.cpp +++ b/image/zim_save.cpp @@ -8,9 +8,9 @@ static const char magic[5] = "ZIMG"; /*int num_levels = 1; - if (flags & ZIM_HAS_MIPS) { - num_levels = log2i(width > height ? width : height); - }*/ +if (flags & ZIM_HAS_MIPS) { +num_levels = log2i(width > height ? width : height); +}*/ static unsigned int log2i(unsigned int val) { unsigned int ret = -1; while (val != 0) { @@ -21,46 +21,46 @@ static unsigned int log2i(unsigned int val) { int ezcompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) { - z_stream stream; - int err; + z_stream stream; + int err; - int nExtraChunks; - uInt destlen; + int nExtraChunks; + uInt destlen; - stream.next_in = (Bytef*)pSrc; - stream.avail_in = (uInt)nSrcLen; + stream.next_in = (Bytef*)pSrc; + stream.avail_in = (uInt)nSrcLen; #ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != nSrcLen) return Z_BUF_ERROR; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != nSrcLen) return Z_BUF_ERROR; #endif - destlen = (uInt)*pnDestLen; - if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; + destlen = (uInt)*pnDestLen; + if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; - err = deflateInit(&stream, Z_DEFAULT_COMPRESSION); - if (err != Z_OK) return err; - nExtraChunks = 0; - do { - stream.next_out = pDest; - stream.avail_out = destlen; - err = deflate(&stream, Z_FINISH); - if (err == Z_STREAM_END ) - break; - if (err != Z_OK) { - deflateEnd(&stream); - return err; - } - nExtraChunks += 1; - } while (stream.avail_out == 0); + err = deflateInit(&stream, Z_DEFAULT_COMPRESSION); + if (err != Z_OK) return err; + nExtraChunks = 0; + do { + stream.next_out = pDest; + stream.avail_out = destlen; + err = deflate(&stream, Z_FINISH); + if (err == Z_STREAM_END ) + break; + if (err != Z_OK) { + deflateEnd(&stream); + return err; + } + nExtraChunks += 1; + } while (stream.avail_out == 0); - *pnDestLen = stream.total_out; + *pnDestLen = stream.total_out; - err = deflateEnd(&stream); - if (err != Z_OK) return err; + err = deflateEnd(&stream); + if (err != Z_OK) return err; - return nExtraChunks ? Z_BUF_ERROR : Z_OK; + return nExtraChunks ? Z_BUF_ERROR : Z_OK; } inline int clamp16(int x) { if (x < 0) return 0; if (x > 15) return 15; return x; } @@ -78,95 +78,95 @@ bool ispowerof2 (int x) { void Convert(const uint8_t *image_data, int width, int height, int pitch, int flags, - uint8_t **data, int *data_size) { - // For 4444 and 565. Ordered dither matrix. looks really surprisingly good on cell phone screens at 4444. - int dith[16] = { - 1, 9, 3, 11, - 13, 5, 15, 7, - 4, 12, 2, 10, - 16, 8, 14, 6 - }; - if ((flags & ZIM_DITHER) == 0) { - for (int i = 0; i < 16; i++) { dith[i] = 8; } - } - switch (flags & ZIM_FORMAT_MASK) { - case ZIM_RGBA8888: - { - *data_size = width * height * 4; - *data = new uint8_t[width * height * 4]; - for (int y = 0; y < height; y++) { - memcpy((*data) + y * width * 4, image_data + y * pitch, width * 4); + uint8_t **data, int *data_size) { + // For 4444 and 565. Ordered dither matrix. looks really surprisingly good on cell phone screens at 4444. + int dith[16] = { + 1, 9, 3, 11, + 13, 5, 15, 7, + 4, 12, 2, 10, + 16, 8, 14, 6 + }; + if ((flags & ZIM_DITHER) == 0) { + for (int i = 0; i < 16; i++) { dith[i] = 8; } } - break; - } - case ZIM_ETC1: { - // Check for power of 2 - if (!ispowerof2(width) || !ispowerof2(height)) { - FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height); - } - // Convert RGBX to ETC1 before saving. - int blockw = width/4; - int blockh = height/4; - *data_size = blockw * blockh * 8; - *data = new uint8_t[*data_size]; -#pragma omp parallel for - for (int y = 0; y < blockh; y++) { - for (int x = 0; x < blockw; x++) { - CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width, - (*data) + (blockw * y + x) * 8, 1); + switch (flags & ZIM_FORMAT_MASK) { + case ZIM_RGBA8888: + { + *data_size = width * height * 4; + *data = new uint8_t[width * height * 4]; + for (int y = 0; y < height; y++) { + memcpy((*data) + y * width * 4, image_data + y * pitch, width * 4); + } + break; } - } - width = blockw * 4; - height = blockh * 4; - break; - } - case ZIM_RGBA4444: - { - *data_size = width * height * 2; - *data = new uint8_t[*data_size]; - uint16_t *dst = (uint16_t *)(*data); - int i = 0; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int dithval = dith[(x&3)+((y&0x3)<<2)] - 8; - int r = clamp16((image_data[i * 4] + dithval) >> 4); - int g = clamp16((image_data[i * 4 + 1] + dithval) >> 4); - int b = clamp16((image_data[i * 4 + 2] + dithval) >> 4); - int a = clamp16((image_data[i * 4 + 3] + dithval) >> 4); // really dither alpha? - // Note: GL_UNSIGNED_SHORT_4_4_4_4, not GL_UNSIGNED_SHORT_4_4_4_4_REV - *dst++ = (r << 12) | (g << 8) | (b << 4) | (a << 0); - i++; - } - } - break; - } - case ZIM_RGB565: - { - *data_size = width * height * 2; + case ZIM_ETC1: { + // Check for power of 2 + if (!ispowerof2(width) || !ispowerof2(height)) { + FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height); + } + // Convert RGBX to ETC1 before saving. + int blockw = width/4; + int blockh = height/4; + *data_size = blockw * blockh * 8; *data = new uint8_t[*data_size]; - uint16_t *dst = (uint16_t *)(*data); - int i = 0; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int dithval = dith[(x&3)+((y&0x3)<<2)] - 8; - dithval = 0; - int r = clamp32((image_data[i * 4] + dithval/2) >> 3); - int g = clamp64((image_data[i * 4 + 1] + dithval/4) >> 2); - int b = clamp32((image_data[i * 4 + 2] + dithval/2) >> 3); - // Note: GL_UNSIGNED_SHORT_5_6_5, not GL_UNSIGNED_SHORT_5_6_5_REV - *dst++ = (r << 11) | (g << 5) | (b); - i++; +#pragma omp parallel for + for (int y = 0; y < blockh; y++) { + for (int x = 0; x < blockw; x++) { + CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width, + (*data) + (blockw * y + x) * 8, 1); } - } - } - break; - - default: - ELOG("Unhandled ZIM format %i", flags & ZIM_FORMAT_MASK); - *data = 0; - *data_size = 0; - return; - } + } + width = blockw * 4; + height = blockh * 4; + break; + } + case ZIM_RGBA4444: + { + *data_size = width * height * 2; + *data = new uint8_t[*data_size]; + uint16_t *dst = (uint16_t *)(*data); + int i = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int dithval = dith[(x&3)+((y&0x3)<<2)] - 8; + int r = clamp16((image_data[i * 4] + dithval) >> 4); + int g = clamp16((image_data[i * 4 + 1] + dithval) >> 4); + int b = clamp16((image_data[i * 4 + 2] + dithval) >> 4); + int a = clamp16((image_data[i * 4 + 3] + dithval) >> 4); // really dither alpha? + // Note: GL_UNSIGNED_SHORT_4_4_4_4, not GL_UNSIGNED_SHORT_4_4_4_4_REV + *dst++ = (r << 12) | (g << 8) | (b << 4) | (a << 0); + i++; + } + } + break; + } + case ZIM_RGB565: + { + *data_size = width * height * 2; + *data = new uint8_t[*data_size]; + uint16_t *dst = (uint16_t *)(*data); + int i = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int dithval = dith[(x&3)+((y&0x3)<<2)] - 8; + dithval = 0; + int r = clamp32((image_data[i * 4] + dithval/2) >> 3); + int g = clamp64((image_data[i * 4 + 1] + dithval/4) >> 2); + int b = clamp32((image_data[i * 4 + 2] + dithval/2) >> 3); + // Note: GL_UNSIGNED_SHORT_5_6_5, not GL_UNSIGNED_SHORT_5_6_5_REV + *dst++ = (r << 11) | (g << 5) | (b); + i++; + } + } + } + break; + + default: + ELOG("Unhandled ZIM format %i", flags & ZIM_FORMAT_MASK); + *data = 0; + *data_size = 0; + return; + } } // Deletes the old buffer. @@ -199,28 +199,28 @@ uint8_t *DownsampleBy2(const uint8_t *image, int width, int height, int pitch) { } void SaveZIM(const char *filename, int width, int height, int pitch, int flags, const uint8_t *image_data) { - FILE *f = fopen(filename, "wb"); - fwrite(magic, 1, 4, f); - fwrite(&width, 1, 4, f); - fwrite(&height, 1, 4, f); - fwrite(&flags, 1, 4, f); + FILE *f = fopen(filename, "wb"); + fwrite(magic, 1, 4, f); + fwrite(&width, 1, 4, f); + fwrite(&height, 1, 4, f); + fwrite(&flags, 1, 4, f); int num_levels = 1; if (flags & ZIM_HAS_MIPS) { num_levels = log2i(width > height ? height : width) + 1; } for (int i = 0; i < num_levels; i++) { - uint8_t *data = 0; + uint8_t *data = 0; int data_size; Convert(image_data, width, height, pitch, flags, &data, &data_size); if (flags & ZIM_ZLIB_COMPRESSED) { - long dest_len = data_size * 2; - uint8_t *dest = new uint8_t[dest_len]; - if (Z_OK == ezcompress(dest, &dest_len, data, data_size)) { - fwrite(dest, 1, dest_len, f); - } else { - ELOG("Zlib compression failed.\n"); - } + long dest_len = data_size * 2; + uint8_t *dest = new uint8_t[dest_len]; + if (Z_OK == ezcompress(dest, &dest_len, data, data_size)) { + fwrite(dest, 1, dest_len, f); + } else { + ELOG("Zlib compression failed.\n"); + } delete [] dest; } else { fwrite(data, 1, data_size, f); @@ -243,5 +243,5 @@ void SaveZIM(const char *filename, int width, int height, int pitch, int flags, } } delete [] image_data; - fclose(f); + fclose(f); } diff --git a/json/json_writer.cpp b/json/json_writer.cpp index 750c4ee8f1..3657129cda 100644 --- a/json/json_writer.cpp +++ b/json/json_writer.cpp @@ -103,13 +103,13 @@ void JsonWriter::pop() { BlockType type = stack_.back().type; stack_.pop_back(); switch (type) { - case ARRAY: - str_ << "\n" << indent() << "]"; - break; - case DICT: - str_ << "\n" << indent() << "}"; - break; + case ARRAY: + str_ << "\n" << indent() << "]"; + break; + case DICT: + str_ << "\n" << indent() << "}"; + break; } - if (stack_.size() > 0) - stack_.back().first = false; + if (stack_.size() > 0) + stack_.back().first = false; } diff --git a/json/json_writer.h b/json/json_writer.h index 5b339b359c..55f2608c1c 100644 --- a/json/json_writer.h +++ b/json/json_writer.h @@ -17,14 +17,14 @@ #include "base/basictypes.h" class JsonWriter { - public: +public: JsonWriter(); ~JsonWriter(); void begin(); void end(); void pushDict(const char *name); void pushArray(const char *name); - void pop(); + void pop(); void writeBool(bool value); void writeBool(const char *name, bool value); void writeInt(int value); @@ -38,7 +38,7 @@ class JsonWriter { return str_.str(); } - private: +private: const char *indent(int n) const; const char *comma() const; const char *arrayComma() const; @@ -56,5 +56,5 @@ class JsonWriter { std::vector stack_; std::ostringstream str_; - DISALLOW_COPY_AND_ASSIGN(JsonWriter); + DISALLOW_COPY_AND_ASSIGN(JsonWriter); }; diff --git a/math/compression.h b/math/compression.h index f9e457c8d0..3d96cc6eee 100644 --- a/math/compression.h +++ b/math/compression.h @@ -5,18 +5,18 @@ template inline void delta(T *data, int length) { - T prev = data[0]; - for (int i = 1; i < length; i++) { - T temp = data[i] - prev; - prev = data[i]; - data[i] = temp; - } + T prev = data[0]; + for (int i = 1; i < length; i++) { + T temp = data[i] - prev; + prev = data[i]; + data[i] = temp; + } } template inline void dedelta(T *data, int length) { - for (int i = 1; i < length; i++) { - data[i] += data[i - 1]; - } + for (int i = 1; i < length; i++) { + data[i] += data[i - 1]; + } } diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp index 01ccf5d432..2d3ce84299 100644 --- a/math/lin/matrix4x4.cpp +++ b/math/lin/matrix4x4.cpp @@ -14,189 +14,189 @@ // no wait. http://code.google.com/p/math-neon/ void matrix_mul_4x4(Matrix4x4 &res, const Matrix4x4 &inA, const Matrix4x4 &inB) { - res.xx = inA.xx*inB.xx + inA.xy*inB.yx + inA.xz*inB.zx + inA.xw*inB.wx; - res.xy = inA.xx*inB.xy + inA.xy*inB.yy + inA.xz*inB.zy + inA.xw*inB.wy; - res.xz = inA.xx*inB.xz + inA.xy*inB.yz + inA.xz*inB.zz + inA.xw*inB.wz; - res.xw = inA.xx*inB.xw + inA.xy*inB.yw + inA.xz*inB.zw + inA.xw*inB.ww; - - res.yx = inA.yx*inB.xx + inA.yy*inB.yx + inA.yz*inB.zx + inA.yw*inB.wx; - res.yy = inA.yx*inB.xy + inA.yy*inB.yy + inA.yz*inB.zy + inA.yw*inB.wy; - res.yz = inA.yx*inB.xz + inA.yy*inB.yz + inA.yz*inB.zz + inA.yw*inB.wz; - res.yw = inA.yx*inB.xw + inA.yy*inB.yw + inA.yz*inB.zw + inA.yw*inB.ww; - - res.zx = inA.zx*inB.xx + inA.zy*inB.yx + inA.zz*inB.zx + inA.zw*inB.wx; - res.zy = inA.zx*inB.xy + inA.zy*inB.yy + inA.zz*inB.zy + inA.zw*inB.wy; - res.zz = inA.zx*inB.xz + inA.zy*inB.yz + inA.zz*inB.zz + inA.zw*inB.wz; - res.zw = inA.zx*inB.xw + inA.zy*inB.yw + inA.zz*inB.zw + inA.zw*inB.ww; - - res.wx = inA.wx*inB.xx + inA.wy*inB.yx + inA.wz*inB.zx + inA.ww*inB.wx; - res.wy = inA.wx*inB.xy + inA.wy*inB.yy + inA.wz*inB.zy + inA.ww*inB.wy; - res.wz = inA.wx*inB.xz + inA.wy*inB.yz + inA.wz*inB.zz + inA.ww*inB.wz; - res.ww = inA.wx*inB.xw + inA.wy*inB.yw + inA.wz*inB.zw + inA.ww*inB.ww; + res.xx = inA.xx*inB.xx + inA.xy*inB.yx + inA.xz*inB.zx + inA.xw*inB.wx; + res.xy = inA.xx*inB.xy + inA.xy*inB.yy + inA.xz*inB.zy + inA.xw*inB.wy; + res.xz = inA.xx*inB.xz + inA.xy*inB.yz + inA.xz*inB.zz + inA.xw*inB.wz; + res.xw = inA.xx*inB.xw + inA.xy*inB.yw + inA.xz*inB.zw + inA.xw*inB.ww; + + res.yx = inA.yx*inB.xx + inA.yy*inB.yx + inA.yz*inB.zx + inA.yw*inB.wx; + res.yy = inA.yx*inB.xy + inA.yy*inB.yy + inA.yz*inB.zy + inA.yw*inB.wy; + res.yz = inA.yx*inB.xz + inA.yy*inB.yz + inA.yz*inB.zz + inA.yw*inB.wz; + res.yw = inA.yx*inB.xw + inA.yy*inB.yw + inA.yz*inB.zw + inA.yw*inB.ww; + + res.zx = inA.zx*inB.xx + inA.zy*inB.yx + inA.zz*inB.zx + inA.zw*inB.wx; + res.zy = inA.zx*inB.xy + inA.zy*inB.yy + inA.zz*inB.zy + inA.zw*inB.wy; + res.zz = inA.zx*inB.xz + inA.zy*inB.yz + inA.zz*inB.zz + inA.zw*inB.wz; + res.zw = inA.zx*inB.xw + inA.zy*inB.yw + inA.zz*inB.zw + inA.zw*inB.ww; + + res.wx = inA.wx*inB.xx + inA.wy*inB.yx + inA.wz*inB.zx + inA.ww*inB.wx; + res.wy = inA.wx*inB.xy + inA.wy*inB.yy + inA.wz*inB.zy + inA.ww*inB.wy; + res.wz = inA.wx*inB.xz + inA.wy*inB.yz + inA.wz*inB.zz + inA.ww*inB.wz; + res.ww = inA.wx*inB.xw + inA.wy*inB.yw + inA.wz*inB.zw + inA.ww*inB.ww; } Matrix4x4 Matrix4x4::simpleInverse() const { - Matrix4x4 out; - out.xx = xx; - out.xy = yx; - out.xz = zx; - - out.yx = xy; - out.yy = yy; - out.yz = zy; - - out.zx = xz; - out.zy = yz; - out.zz = zz; - - out.wx = -(xx * wx + xy * wy + xz * wz); - out.wy = -(yx * wx + yy * wy + yz * wz); - out.wz = -(zx * wx + zy * wy + zz * wz); - - out.xw = 0.0f; - out.yw = 0.0f; - out.zw = 0.0f; - out.ww = 1.0f; + Matrix4x4 out; + out.xx = xx; + out.xy = yx; + out.xz = zx; - return out; + out.yx = xy; + out.yy = yy; + out.yz = zy; + + out.zx = xz; + out.zy = yz; + out.zz = zz; + + out.wx = -(xx * wx + xy * wy + xz * wz); + out.wy = -(yx * wx + yy * wy + yz * wz); + out.wz = -(zx * wx + zy * wy + zz * wz); + + out.xw = 0.0f; + out.yw = 0.0f; + out.zw = 0.0f; + out.ww = 1.0f; + + return out; } Matrix4x4 Matrix4x4::transpose() const { - Matrix4x4 out; - out.xx = xx;out.xy = yx;out.xz = zx;out.xw = wx; - out.yx = xy;out.yy = yy;out.yz = zy;out.yw = wy; - out.zx = xz;out.zy = yz;out.zz = zz;out.zw = wz; - out.wx = xw;out.wy = yw;out.wz = zw;out.ww = ww; - return out; + Matrix4x4 out; + out.xx = xx;out.xy = yx;out.xz = zx;out.xw = wx; + out.yx = xy;out.yy = yy;out.yz = zy;out.yw = wy; + out.zx = xz;out.zy = yz;out.zz = zz;out.zw = wz; + out.wx = xw;out.wy = yw;out.wz = zw;out.ww = ww; + return out; } Matrix4x4 Matrix4x4::operator * (const Matrix4x4 &other) const { - Matrix4x4 temp; - matrix_mul_4x4(temp, *this, other); - return temp; + Matrix4x4 temp; + matrix_mul_4x4(temp, *this, other); + return temp; } Matrix4x4 Matrix4x4::inverse() const { - Matrix4x4 temp; - float dW = 1.0f / (xx*(yy*zz - yz*zy) - xy*(yx*zz - yz*zx) - xz*(yy*zx - yx*zy)); - - temp.xx = (yy*zz - yz*zy) * dW; - temp.xy = (xz*zy - xy*zz) * dW; - temp.xz = (xy*yz - xz*yy) * dW; - temp.xw = xw; - - temp.yx = (yz*zx - yx*zz) * dW; - temp.yy = (xx*zz - xz*zx) * dW; - temp.yz = (xz*yx - xx*zx) * dW; - temp.yw = yw; - - temp.zx = (yx*zy - yy*zx) * dW; - temp.zy = (xy*zx - xx*zy) * dW; - temp.zz = (xx*yy - xy*yx) * dW; - temp.zw = zw; - - temp.wx = (yy*(zx*wz - zz*wx) + yz*(zy*wx - zx*wy) - yx*(zy*wz - zz*wy)) * dW; - temp.wy = (xx*(zy*wz - zz*wy) + xy*(zz*wx - zx*wz) + xz*(zx*wy - zy*wx)) * dW; - temp.wz = (xy*(yx*wz - yz*wx) + xz*(yy*wx - yx*wy) - xx*(yy*wz - yz*wy)) * dW; - temp.ww = ww; - - return temp; + Matrix4x4 temp; + float dW = 1.0f / (xx*(yy*zz - yz*zy) - xy*(yx*zz - yz*zx) - xz*(yy*zx - yx*zy)); + + temp.xx = (yy*zz - yz*zy) * dW; + temp.xy = (xz*zy - xy*zz) * dW; + temp.xz = (xy*yz - xz*yy) * dW; + temp.xw = xw; + + temp.yx = (yz*zx - yx*zz) * dW; + temp.yy = (xx*zz - xz*zx) * dW; + temp.yz = (xz*yx - xx*zx) * dW; + temp.yw = yw; + + temp.zx = (yx*zy - yy*zx) * dW; + temp.zy = (xy*zx - xx*zy) * dW; + temp.zz = (xx*yy - xy*yx) * dW; + temp.zw = zw; + + temp.wx = (yy*(zx*wz - zz*wx) + yz*(zy*wx - zx*wy) - yx*(zy*wz - zz*wy)) * dW; + temp.wy = (xx*(zy*wz - zz*wy) + xy*(zz*wx - zx*wz) + xz*(zx*wy - zy*wx)) * dW; + temp.wz = (xy*(yx*wz - yz*wx) + xz*(yy*wx - yx*wy) - xx*(yy*wz - yz*wy)) * dW; + temp.ww = ww; + + return temp; } void Matrix4x4::setViewLookAt(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 &vWorldUp) { - Vec3 vView = vFrom - vAt; // OpenGL, sigh... - vView.normalize(); - float DotProduct = vWorldUp * vView; - Vec3 vUp = vWorldUp - vView * DotProduct; - float Length = vUp.length(); + Vec3 vView = vFrom - vAt; // OpenGL, sigh... + vView.normalize(); + float DotProduct = vWorldUp * vView; + Vec3 vUp = vWorldUp - vView * DotProduct; + float Length = vUp.length(); - if (1e-6f > Length) { + if (1e-6f > Length) { // EMERGENCY - vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; - // If we still have near-zero length, resort to a different axis. - Length = vUp.length(); - if (1e-6f > Length) - { - vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z; - Length = vUp.length(); - if (1e-6f > Length) - return; - } - } - vUp.normalize(); - Vec3 vRight = vUp % vView; - empty(); - - xx = vRight.x; xy = vUp.x; xz=vView.x; - yx = vRight.y; yy = vUp.y; yz=vView.y; - zx = vRight.z; zy = vUp.z; zz=vView.z; - - wx = -vFrom * vRight; - wy = -vFrom * vUp; - wz = -vFrom * vView; - ww = 1.0f; + vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; + // If we still have near-zero length, resort to a different axis. + Length = vUp.length(); + if (1e-6f > Length) + { + vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z; + Length = vUp.length(); + if (1e-6f > Length) + return; + } + } + vUp.normalize(); + Vec3 vRight = vUp % vView; + empty(); + + xx = vRight.x; xy = vUp.x; xz=vView.x; + yx = vRight.y; yy = vUp.y; yz=vView.y; + zx = vRight.z; zy = vUp.z; zz=vView.z; + + wx = -vFrom * vRight; + wy = -vFrom * vUp; + wz = -vFrom * vView; + ww = 1.0f; } void Matrix4x4::setViewLookAtD3D(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 &vWorldUp) { - Vec3 vView = vAt - vFrom; - vView.normalize(); - float DotProduct = vWorldUp * vView; - Vec3 vUp = vWorldUp - vView * DotProduct; - float Length = vUp.length(); + Vec3 vView = vAt - vFrom; + vView.normalize(); + float DotProduct = vWorldUp * vView; + Vec3 vUp = vWorldUp - vView * DotProduct; + float Length = vUp.length(); - if (1e-6f > Length) { - vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; - // If we still have near-zero length, resort to a different axis. - Length = vUp.length(); - if (1e-6f > Length) - { - vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z; - Length = vUp.length(); - if (1e-6f > Length) - return; - } - } - vUp.normalize(); - Vec3 vRight = vUp % vView; - empty(); - - xx = vRight.x; xy = vUp.x; xz=vView.x; - yx = vRight.y; yy = vUp.y; yz=vView.y; - zx = vRight.z; zy = vUp.z; zz=vView.z; - - wx = -vFrom * vRight; - wy = -vFrom * vUp; - wz = -vFrom * vView; - ww = 1.0f; + if (1e-6f > Length) { + vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; + // If we still have near-zero length, resort to a different axis. + Length = vUp.length(); + if (1e-6f > Length) + { + vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z; + Length = vUp.length(); + if (1e-6f > Length) + return; + } + } + vUp.normalize(); + Vec3 vRight = vUp % vView; + empty(); + + xx = vRight.x; xy = vUp.x; xz=vView.x; + yx = vRight.y; yy = vUp.y; yz=vView.y; + zx = vRight.z; zy = vUp.z; zz=vView.z; + + wx = -vFrom * vRight; + wy = -vFrom * vUp; + wz = -vFrom * vView; + ww = 1.0f; } void Matrix4x4::setViewFrame(const Vec3 &pos, const Vec3 &vRight, const Vec3 &vView, const Vec3 &vUp) { - xx = vRight.x; xy = vUp.x; xz=vView.x; xw = 0.0f; - yx = vRight.y; yy = vUp.y; yz=vView.y; yw = 0.0f; - zx = vRight.z; zy = vUp.z; zz=vView.z; zw = 0.0f; - - wx = -pos * vRight; - wy = -pos * vUp; - wz = -pos * vView; - ww = 1.0f; + xx = vRight.x; xy = vUp.x; xz=vView.x; xw = 0.0f; + yx = vRight.y; yy = vUp.y; yz=vView.y; yw = 0.0f; + zx = vRight.z; zy = vUp.z; zz=vView.z; zw = 0.0f; + + wx = -pos * vRight; + wy = -pos * vUp; + wz = -pos * vView; + ww = 1.0f; } //YXZ euler angles void Matrix4x4::setRotation(float x,float y, float z) { - setRotationY(y); - Matrix4x4 temp; - temp.setRotationX(x); - *this *= temp; - temp.setRotationZ(z); - *this *= temp; + setRotationY(y); + Matrix4x4 temp; + temp.setRotationX(x); + *this *= temp; + temp.setRotationZ(z); + *this *= temp; } void Matrix4x4::setProjection(float near, float far, float fov_horiz, float aspect) { // Now OpenGL style. - empty(); + empty(); float xFac = tanf(fov_horiz * 3.14f/360); float yFac = xFac * aspect; @@ -208,17 +208,17 @@ void Matrix4x4::setProjection(float near, float far, float fov_horiz, float aspe } void Matrix4x4::setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect) { - empty(); - float Q, f; - - f = fov_horiz*0.5f; - Q = far_plane / (far_plane - near_plane); - - xx = (float)(1.0f / tanf(f));; - yy = (float)(1.0f / tanf(f*aspect)); - zz = Q; - wz = -Q * near_plane; - zw = 1.0f; + empty(); + float Q, f; + + f = fov_horiz*0.5f; + Q = far_plane / (far_plane - near_plane); + + xx = (float)(1.0f / tanf(f));; + yy = (float)(1.0f / tanf(f*aspect)); + zz = Q; + wz = -Q * near_plane; + zw = 1.0f; } void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float near, float far) { @@ -233,43 +233,43 @@ void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float // This is a D3D style matrix. void Matrix4x4::setProjectionInf(const float near_plane, const float fov_horiz, const float aspect) { - empty(); - float f = fov_horiz*0.5f; - xx = 1.0f / tanf(f); - yy = 1.0f / tanf(f*aspect); - zz = 1; - wz = -near_plane; - zw = 1.0f; + empty(); + float f = fov_horiz*0.5f; + xx = 1.0f / tanf(f); + yy = 1.0f / tanf(f*aspect); + zz = 1; + wz = -near_plane; + zw = 1.0f; } void Matrix4x4::setRotationAxisAngle(const Vec3 &axis, float angle) { - Quaternion quat; - quat.setRotation(axis, angle); - quat.toMatrix(this); + Quaternion quat; + quat.setRotation(axis, angle); + quat.toMatrix(this); } // from a (Position, Rotation, Scale) vec3 quat vec3 tuple Matrix4x4 Matrix4x4::fromPRS(const Vec3 &positionv, const Quaternion &rotv, const Vec3 &scalev) { - Matrix4x4 newM; - newM.setIdentity(); - Matrix4x4 rot, scale; - rotv.toMatrix(&rot); - scale.setScaling(scalev); - newM = rot * scale; - newM.wx = positionv.x; + Matrix4x4 newM; + newM.setIdentity(); + Matrix4x4 rot, scale; + rotv.toMatrix(&rot); + scale.setScaling(scalev); + newM = rot * scale; + newM.wx = positionv.x; newM.wy = positionv.y; newM.wz = positionv.z; - return newM; + return newM; } #if _MSC_VER #define snprintf _snprintf #endif void Matrix4x4::toText(char *buffer, int len) const { - snprintf(buffer, len, "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", - xx,xy,xz,xw, - yx,yy,yz,yw, - zx,zy,zz,zw, - wx,wy,wz,ww); + snprintf(buffer, len, "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", + xx,xy,xz,xw, + yx,yy,yz,yw, + zx,zy,zz,zw, + wx,wy,wz,ww); buffer[len - 1] = '\0'; } diff --git a/math/lin/matrix4x4.h b/math/lin/matrix4x4.h index b64b31a28d..8e058ce09f 100644 --- a/math/lin/matrix4x4.h +++ b/math/lin/matrix4x4.h @@ -6,17 +6,17 @@ class Quaternion; class Matrix4x4 { - public: - float xx, xy, xz, xw; - float yx, yy, yz, yw; - float zx, zy, zz, zw; - float wx, wy, wz, ww; +public: + float xx, xy, xz, xw; + float yx, yy, yz, yw; + float zx, zy, zz, zw; + float wx, wy, wz, ww; + + const Vec3 right() const {return Vec3(xx, xy, xz);} + const Vec3 up() const {return Vec3(yx, yy, yz);} + const Vec3 front() const {return Vec3(zx, zy, zz);} + const Vec3 move() const {return Vec3(wx, wy, wz);} - const Vec3 right() const {return Vec3(xx, xy, xz);} - const Vec3 up() const {return Vec3(yx, yy, yz);} - const Vec3 front() const {return Vec3(zx, zy, zz);} - const Vec3 move() const {return Vec3(wx, wy, wz);} - void setRight(const Vec3 &v) { xx = v.x; xy = v.y; xz = v.z; } @@ -31,110 +31,110 @@ class Matrix4x4 { } - const float &operator[](int i) const { - return *(((const float *)this) + i); - } - float &operator[](int i) { - return *(((float *)this) + i); - } - Matrix4x4 operator * (const Matrix4x4 &other) const ; - void operator *= (const Matrix4x4 &other) { - *this = *this * other; - } + const float &operator[](int i) const { + return *(((const float *)this) + i); + } + float &operator[](int i) { + return *(((float *)this) + i); + } + Matrix4x4 operator * (const Matrix4x4 &other) const ; + void operator *= (const Matrix4x4 &other) { + *this = *this * other; + } const float *getReadPtr() const { return (const float *)this; } - void empty() { - memset(this, 0, 16 * sizeof(float)); - } - void setScaling(const float f) { - empty(); - xx=yy=zz=f; ww=1.0f; - } - void setScaling(const Vec3 f) { - empty(); - xx=f.x; - yy=f.y; - zz=f.z; - ww=1.0f; - } - - void setIdentity() { - setScaling(1.0f); - } - void setTranslation(const Vec3 &trans) { - setIdentity(); - wx = trans.x; + void empty() { + memset(this, 0, 16 * sizeof(float)); + } + void setScaling(const float f) { + empty(); + xx=yy=zz=f; ww=1.0f; + } + void setScaling(const Vec3 f) { + empty(); + xx=f.x; + yy=f.y; + zz=f.z; + ww=1.0f; + } + + void setIdentity() { + setScaling(1.0f); + } + void setTranslation(const Vec3 &trans) { + setIdentity(); + wx = trans.x; wy = trans.y; wz = trans.z; - } - Matrix4x4 inverse() const; - Matrix4x4 simpleInverse() const; - Matrix4x4 transpose() const; - - void setRotationX(const float a) { - empty(); - float c=cosf(a); - float s=sinf(a); - xx = 1.0f; - yy = c; yz = s; - zy = -s; zz = c; - ww = 1.0f; - } - void setRotationY(const float a) { - empty(); - float c=cosf(a); - float s=sinf(a); - xx = c; xz = -s; - yy = 1.0f; - zx = s; zz = c ; - ww = 1.0f; - } - void setRotationZ(const float a) { - empty(); - float c=cosf(a); - float s=sinf(a); - xx = c; xy = s; - yx = -s; yy = c; - zz = 1.0f; - ww = 1.0f; - } - void setRotationAxisAngle(const Vec3 &axis, float angle); - - - void setRotation(float x,float y, float z); - void setProjection(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); - void setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); - void setProjectionInf(float near_plane, float fov_horiz, float aspect = 0.75f); - void setOrtho(float left, float right, float bottom, float top, float near, float far); - void setShadow(float Lx, float Ly, float Lz, float Lw) { - float Pa=0; - float Pb=1; - float Pc=0; - float Pd=0; - //P = normalize(Plane); - float d = (Pa*Lx + Pb*Ly + Pc*Lz + Pd*Lw); + } + Matrix4x4 inverse() const; + Matrix4x4 simpleInverse() const; + Matrix4x4 transpose() const; - xx=Pa * Lx + d; xy=Pa * Ly; xz=Pa * Lz; xw=Pa * Lw; - yx=Pb * Lx; yy=Pb * Ly + d; yz=Pb * Lz; yw=Pb * Lw; - zx=Pc * Lx; zy=Pc * Ly; zz=Pc * Lz + d; zw=Pc * Lw; - wx=Pd * Lx; wy=Pd * Ly; wz=Pd * Lz; ww=Pd * Lw + d; - } + void setRotationX(const float a) { + empty(); + float c=cosf(a); + float s=sinf(a); + xx = 1.0f; + yy = c; yz = s; + zy = -s; zz = c; + ww = 1.0f; + } + void setRotationY(const float a) { + empty(); + float c=cosf(a); + float s=sinf(a); + xx = c; xz = -s; + yy = 1.0f; + zx = s; zz = c ; + ww = 1.0f; + } + void setRotationZ(const float a) { + empty(); + float c=cosf(a); + float s=sinf(a); + xx = c; xy = s; + yx = -s; yy = c; + zz = 1.0f; + ww = 1.0f; + } + void setRotationAxisAngle(const Vec3 &axis, float angle); - void setViewLookAt(const Vec3 &from, const Vec3 &at, const Vec3 &worldup); - void setViewLookAtD3D(const Vec3 &from, const Vec3 &at, const Vec3 &worldup); - void setViewFrame(const Vec3 &pos, const Vec3 &right, const Vec3 &forward, const Vec3 &up); - void stabilizeOrtho() { - /* - front().normalize(); - right().normalize(); - up() = front() % right(); - right() = up() % front(); - */ - } - void toText(char *buffer, int len) const; + + void setRotation(float x,float y, float z); + void setProjection(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); + void setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); + void setProjectionInf(float near_plane, float fov_horiz, float aspect = 0.75f); + void setOrtho(float left, float right, float bottom, float top, float near, float far); + void setShadow(float Lx, float Ly, float Lz, float Lw) { + float Pa=0; + float Pb=1; + float Pc=0; + float Pd=0; + //P = normalize(Plane); + float d = (Pa*Lx + Pb*Ly + Pc*Lz + Pd*Lw); + + xx=Pa * Lx + d; xy=Pa * Ly; xz=Pa * Lz; xw=Pa * Lw; + yx=Pb * Lx; yy=Pb * Ly + d; yz=Pb * Lz; yw=Pb * Lw; + zx=Pc * Lx; zy=Pc * Ly; zz=Pc * Lz + d; zw=Pc * Lw; + wx=Pd * Lx; wy=Pd * Ly; wz=Pd * Lz; ww=Pd * Lw + d; + } + + void setViewLookAt(const Vec3 &from, const Vec3 &at, const Vec3 &worldup); + void setViewLookAtD3D(const Vec3 &from, const Vec3 &at, const Vec3 &worldup); + void setViewFrame(const Vec3 &pos, const Vec3 &right, const Vec3 &forward, const Vec3 &up); + void stabilizeOrtho() { + /* + front().normalize(); + right().normalize(); + up() = front() % right(); + right() = up() % front(); + */ + } + void toText(char *buffer, int len) const; void print() const; - static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale); + static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale); }; #endif // _MATH_LIN_MATRIX4X4_H diff --git a/math/lin/quat.cpp b/math/lin/quat.cpp index cf17735634..3c1900ebcc 100644 --- a/math/lin/quat.cpp +++ b/math/lin/quat.cpp @@ -2,124 +2,124 @@ #include "math/lin/matrix4x4.h" void Quaternion::toMatrix(Matrix4x4 *out) const { - Matrix4x4 temp; - temp.setIdentity(); - float ww, xx, yy, zz, wx, wy, wz, xy, xz, yz; - ww = w*w; xx = x*x; yy = y*y; zz = z*z; - wx = w*x*2; wy = w*y*2; wz = w*z*2; - xy = x*y*2; xz = x*z*2; yz = y*z*2; - - temp.xx = ww + xx - yy - zz; - temp.xy = xy + wz; - temp.xz = xz - wy; - - temp.yx = xy - wz; - temp.yy = ww - xx + yy - zz; - temp.yz = yz + wx; - - temp.zx = xz + wy; - temp.zy = yz - wx; - temp.zz = ww - xx - yy + zz; - - *out = temp; + Matrix4x4 temp; + temp.setIdentity(); + float ww, xx, yy, zz, wx, wy, wz, xy, xz, yz; + ww = w*w; xx = x*x; yy = y*y; zz = z*z; + wx = w*x*2; wy = w*y*2; wz = w*z*2; + xy = x*y*2; xz = x*z*2; yz = y*z*2; + + temp.xx = ww + xx - yy - zz; + temp.xy = xy + wz; + temp.xz = xz - wy; + + temp.yx = xy - wz; + temp.yy = ww - xx + yy - zz; + temp.yz = yz + wx; + + temp.zx = xz + wy; + temp.zy = yz - wx; + temp.zz = ww - xx - yy + zz; + + *out = temp; } Quaternion Quaternion::fromMatrix(Matrix4x4 &m) { - // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes - // article "Quaternion Calculus and Fast Animation". - Quaternion q(0,0,0,1); + // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes + // article "Quaternion Calculus and Fast Animation". + Quaternion q(0,0,0,1); /* - float fTrace = m[0][0] + m[1][1] + m[2][2]; - float fRoot; + float fTrace = m[0][0] + m[1][1] + m[2][2]; + float fRoot; - if( fTrace > 0.0 ) - { - fRoot = sqrtf( fTrace + 1.0f ); + if( fTrace > 0.0 ) + { + fRoot = sqrtf( fTrace + 1.0f ); - q.w = 0.5f * fRoot; + q.w = 0.5f * fRoot; - fRoot = 0.5f / fRoot; + fRoot = 0.5f / fRoot; - q.x = ( m[2][1] - m[1][2] ) * fRoot; - q.y = ( m[0][2] - m[2][0] ) * fRoot; - q.z = ( m[1][0] - m[0][1] ) * fRoot; - } - else - { - int iNext[3] = { 1, 2, 0 }; + q.x = ( m[2][1] - m[1][2] ) * fRoot; + q.y = ( m[0][2] - m[2][0] ) * fRoot; + q.z = ( m[1][0] - m[0][1] ) * fRoot; + } + else + { + int iNext[3] = { 1, 2, 0 }; - int i = 0; - if( m[1][1] > m[0][0] ) - i = 1; + int i = 0; + if( m[1][1] > m[0][0] ) + i = 1; - if( m[2][2] > m[i][i] ) - i = 2; + if( m[2][2] > m[i][i] ) + i = 2; - int j = iNext[i]; - int k = iNext[j]; + int j = iNext[i]; + int k = iNext[j]; - fRoot = sqrtf( m[i][i] - m[j][j] - m[k][k] + 1.0f ); + fRoot = sqrtf( m[i][i] - m[j][j] - m[k][k] + 1.0f ); - float *apfQuat = &q.x; + float *apfQuat = &q.x; - apfQuat[i] = 0.5f * fRoot; + apfQuat[i] = 0.5f * fRoot; - fRoot = 0.5f / fRoot; + fRoot = 0.5f / fRoot; - q.w = ( m[k][j] - m[j][k] ) * fRoot; + q.w = ( m[k][j] - m[j][k] ) * fRoot; - apfQuat[j] = ( m[j][i] + m[i][j] ) * fRoot; - apfQuat[k] = ( m[k][i] + m[i][k] ) * fRoot; - } - q.normalize(); */ - return q; + apfQuat[j] = ( m[j][i] + m[i][j] ) * fRoot; + apfQuat[k] = ( m[k][i] + m[i][k] ) * fRoot; + } + q.normalize(); */ + return q; }; // TODO: Allegedly, lerp + normalize can achieve almost as good results. Quaternion Quaternion::slerp(const Quaternion &to, const float a) const { - Quaternion to2; - float angle, cos_angle, scale_from, scale_to, sin_angle; - - cos_angle = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); //4D dot product - - if (cos_angle < 0.0f) - { - cos_angle = -cos_angle; - to2.w = -to.w; to2.x = -to.x; to2.y = -to.y; to2.z = -to.z; - } - else - { - to2 = to; - } - - if ((1.0f - fabsf(cos_angle)) > 0.00001f) - { - /* spherical linear interpolation (SLERP) */ - angle = acosf(cos_angle); - sin_angle = sinf(angle); - scale_from = sinf((1.0f - a) * angle) / sin_angle; - scale_to = sinf(a * angle) / sin_angle; - } - else - { - /* to prevent divide-by-zero, resort to linear interpolation */ - // This is okay in 99% of cases anyway, maybe should be the default? - scale_from = 1.0f - a; - scale_to = a; - } - - return Quaternion( - scale_from*x + scale_to*to2.x, - scale_from*y + scale_to*to2.y, - scale_from*z + scale_to*to2.z, - scale_from*w + scale_to*to2.w - ); + Quaternion to2; + float angle, cos_angle, scale_from, scale_to, sin_angle; + + cos_angle = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); //4D dot product + + if (cos_angle < 0.0f) + { + cos_angle = -cos_angle; + to2.w = -to.w; to2.x = -to.x; to2.y = -to.y; to2.z = -to.z; + } + else + { + to2 = to; + } + + if ((1.0f - fabsf(cos_angle)) > 0.00001f) + { + /* spherical linear interpolation (SLERP) */ + angle = acosf(cos_angle); + sin_angle = sinf(angle); + scale_from = sinf((1.0f - a) * angle) / sin_angle; + scale_to = sinf(a * angle) / sin_angle; + } + else + { + /* to prevent divide-by-zero, resort to linear interpolation */ + // This is okay in 99% of cases anyway, maybe should be the default? + scale_from = 1.0f - a; + scale_to = a; + } + + return Quaternion( + scale_from*x + scale_to*to2.x, + scale_from*y + scale_to*to2.y, + scale_from*z + scale_to*to2.z, + scale_from*w + scale_to*to2.w + ); } Quaternion Quaternion::multiply(const Quaternion &q) const { - return Quaternion((w * q.x) + (x * q.w) + (y * q.z) - (z * q.y), - (w * q.y) + (y * q.w) + (z * q.x) - (x * q.z), - (w * q.z) + (z * q.w) + (x * q.y) - (y * q.x), - (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z)); + return Quaternion((w * q.x) + (x * q.w) + (y * q.z) - (z * q.y), + (w * q.y) + (y * q.w) + (z * q.x) - (x * q.z), + (w * q.z) + (z * q.w) + (x * q.y) - (y * q.x), + (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z)); } diff --git a/math/lin/quat.h b/math/lin/quat.h index 2bedd59733..4352e95bc8 100644 --- a/math/lin/quat.h +++ b/math/lin/quat.h @@ -8,85 +8,85 @@ class Matrix4x4; class Quaternion { public: - float x,y,z,w; - - Quaternion() { } - Quaternion(const float _x, const float _y, const float _z, const float _w) { - x=_x; y=_y; z=_z; w=_w; - } - void setIdentity() - { - x=y=z=0; w=1.0f; - } - void setXRotation(const float r) { w = cosf(r / 2); x = sinf(r / 2); y = z = 0; } - void setYRotation(const float r) { w = cosf(r / 2); y = sinf(r / 2); x = z = 0; } - void setZRotation(const float r) { w = cosf(r / 2); z = sinf(r / 2); x = y = 0; } - void toMatrix(Matrix4x4 *out) const; - static Quaternion fromMatrix(Matrix4x4 &m); + float x,y,z,w; - Quaternion operator *(Quaternion &q) const - { - return Quaternion( - (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z), - (w * q.x) + (x * q.w) + (y * q.z) - (z * q.y), - (w * q.y) + (y * q.w) + (z * q.x) - (x * q.z), - (w * q.z) + (z * q.w) + (x * q.y) - (y * q.x) - ); - } - Quaternion operator -() - { - return Quaternion(-x,-y,-z,-w); - } - void setRotation(Vec3 axis, float angle) - { - axis /= axis.length(); - angle *= .5f; - float sine = sinf(angle); - w = cosf(angle); - x = sine * axis.x; - y = sine * axis.y; - z = sine * axis.z; - } - void toAxisAngle(Vec3 &v, float &angle) - { - normalize(); - if (w==1.0f && x==0.0f && y==0.0f && z==0.0f) - { - v = Vec3(0,1,0); - angle = 0.0f; - return; - } - float cos_a = w; - angle = acosf(cos_a) * 2; - float sin_a = sqrtf( 1.0f - cos_a * cos_a ); - if (fabsf(sin_a) < 0.00005f) sin_a = 1; - float inv_sin_a=1.0f/sin_a; - v.x = x * inv_sin_a; - v.y = y * inv_sin_a; - v.z = z * inv_sin_a; - } - enum { - QUAT_SHORT, - QUAT_LONG, - QUAT_CW, - QUAT_CCW - }; - Quaternion slerp(const Quaternion &to, const float a) const; - Quaternion multiply(const Quaternion &q) const; - float &operator [] (int i) { - return *((&x) + i); - } - const float operator [] (int i) const { - return *((&x) + i); - } - //not sure about this, maybe mag is supposed to sqrt - float magnitude() const { - return x*x + y*y + z*z + w*w; - } - void normalize() { - float f = 1.0f/sqrtf(magnitude()); - x*=f; y*=f; z*=f; w*=f; - } + Quaternion() { } + Quaternion(const float _x, const float _y, const float _z, const float _w) { + x=_x; y=_y; z=_z; w=_w; + } + void setIdentity() + { + x=y=z=0; w=1.0f; + } + void setXRotation(const float r) { w = cosf(r / 2); x = sinf(r / 2); y = z = 0; } + void setYRotation(const float r) { w = cosf(r / 2); y = sinf(r / 2); x = z = 0; } + void setZRotation(const float r) { w = cosf(r / 2); z = sinf(r / 2); x = y = 0; } + void toMatrix(Matrix4x4 *out) const; + static Quaternion fromMatrix(Matrix4x4 &m); + + Quaternion operator *(Quaternion &q) const + { + return Quaternion( + (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z), + (w * q.x) + (x * q.w) + (y * q.z) - (z * q.y), + (w * q.y) + (y * q.w) + (z * q.x) - (x * q.z), + (w * q.z) + (z * q.w) + (x * q.y) - (y * q.x) + ); + } + Quaternion operator -() + { + return Quaternion(-x,-y,-z,-w); + } + void setRotation(Vec3 axis, float angle) + { + axis /= axis.length(); + angle *= .5f; + float sine = sinf(angle); + w = cosf(angle); + x = sine * axis.x; + y = sine * axis.y; + z = sine * axis.z; + } + void toAxisAngle(Vec3 &v, float &angle) + { + normalize(); + if (w==1.0f && x==0.0f && y==0.0f && z==0.0f) + { + v = Vec3(0,1,0); + angle = 0.0f; + return; + } + float cos_a = w; + angle = acosf(cos_a) * 2; + float sin_a = sqrtf( 1.0f - cos_a * cos_a ); + if (fabsf(sin_a) < 0.00005f) sin_a = 1; + float inv_sin_a=1.0f/sin_a; + v.x = x * inv_sin_a; + v.y = y * inv_sin_a; + v.z = z * inv_sin_a; + } + enum { + QUAT_SHORT, + QUAT_LONG, + QUAT_CW, + QUAT_CCW + }; + Quaternion slerp(const Quaternion &to, const float a) const; + Quaternion multiply(const Quaternion &q) const; + float &operator [] (int i) { + return *((&x) + i); + } + const float operator [] (int i) const { + return *((&x) + i); + } + //not sure about this, maybe mag is supposed to sqrt + float magnitude() const { + return x*x + y*y + z*z + w*w; + } + void normalize() { + float f = 1.0f/sqrtf(magnitude()); + x*=f; y*=f; z*=f; w*=f; + } }; #endif // _MATH_LIN_QUAT_H diff --git a/math/lin/vec3.cpp b/math/lin/vec3.cpp index bf35ea5118..4b817ad98b 100644 --- a/math/lin/vec3.cpp +++ b/math/lin/vec3.cpp @@ -4,25 +4,25 @@ #include "math/lin/matrix4x4.h" Vec3 Vec3::operator *(const Matrix4x4 &m) const { - return Vec3(x*m.xx + y*m.yx + z*m.zx + m.wx, - x*m.xy + y*m.yy + z*m.zy + m.wy, - x*m.xz + y*m.yz + z*m.zz + m.wz); + return Vec3(x*m.xx + y*m.yx + z*m.zx + m.wx, + x*m.xy + y*m.yy + z*m.zy + m.wy, + x*m.xz + y*m.yz + z*m.zz + m.wz); } Vec4 Vec3::multiply4D(const Matrix4x4 &m) const { - return Vec4(x*m.xx + y*m.yx + z*m.zx + m.wx, - x*m.xy + y*m.yy + z*m.zy + m.wy, - x*m.xz + y*m.yz + z*m.zz + m.wz, - x*m.xw + y*m.yw + z*m.zw + m.ww); + return Vec4(x*m.xx + y*m.yx + z*m.zx + m.wx, + x*m.xy + y*m.yy + z*m.zy + m.wy, + x*m.xz + y*m.yz + z*m.zz + m.wz, + x*m.xw + y*m.yw + z*m.zw + m.ww); } Vec4 Vec4::multiply4D(Matrix4x4 &m) const { - return Vec4(x*m.xx + y*m.yx + z*m.zx + w*m.wx, - x*m.xy + y*m.yy + z*m.zy + w*m.wy, - x*m.xz + y*m.yz + z*m.zz + w*m.wz, - x*m.xw + y*m.yw + z*m.zw + w*m.ww); + return Vec4(x*m.xx + y*m.yx + z*m.zx + w*m.wx, + x*m.xy + y*m.yy + z*m.zy + w*m.wy, + x*m.xz + y*m.yz + z*m.zz + w*m.wz, + x*m.xw + y*m.yw + z*m.zw + w*m.ww); } Vec3 Vec3::rotatedBy(const Matrix4x4 &m) const { - return Vec3(x*m.xx + y*m.yx + z*m.zx, - x*m.xy + y*m.yy + z*m.zy, - x*m.xz + y*m.yz + z*m.zz); + return Vec3(x*m.xx + y*m.yx + z*m.zx, + x*m.xy + y*m.yy + z*m.zy, + x*m.xz + y*m.yz + z*m.zz); } diff --git a/math/lin/vec3.h b/math/lin/vec3.h index 546d035f82..ac346a7f76 100644 --- a/math/lin/vec3.h +++ b/math/lin/vec3.h @@ -18,112 +18,112 @@ class Matrix4x4; // Hm, doesn't belong in this file. class Vec4 { public: - float x,y,z,w; - Vec4(){} - Vec4(float a, float b, float c, float d) {x=a;y=b;z=c;w=d;} - Vec4 multiply4D(Matrix4x4 &m) const; + float x,y,z,w; + Vec4(){} + Vec4(float a, float b, float c, float d) {x=a;y=b;z=c;w=d;} + Vec4 multiply4D(Matrix4x4 &m) const; }; class Vec3 { public: - float x,y,z; - - Vec3() { } - explicit Vec3(float f) {x=y=z=f;} + float x,y,z; - Vec3(const float _x, const float _y, const float _z) { - x=_x; y=_y; z=_z; - } - void Set(float _x, float _y, float _z) { - x=_x; y=_y; z=_z; - } - Vec3 operator + (const Vec3 &other) const { - return Vec3(x+other.x, y+other.y, z+other.z); - } - void operator += (const Vec3 &other) { - x+=other.x; y+=other.y; z+=other.z; - } - Vec3 operator -(const Vec3 &v) const { - return Vec3(x-v.x,y-v.y,z-v.z); - } - void operator -= (const Vec3 &other) - { - x-=other.x; y-=other.y; z-=other.z; - } - Vec3 operator -() const { - return Vec3(-x,-y,-z); - } + Vec3() { } + explicit Vec3(float f) {x=y=z=f;} - Vec3 operator * (const float f) const { - return Vec3(x*f,y*f,z*f); - } - Vec3 operator / (const float f) const { - float invf = (1.0f/f); - return Vec3(x*invf,y*invf,z*invf); - } - void operator /= (const float f) - { - *this = *this / f; - } - float operator * (const Vec3 &other) const { - return x*other.x + y*other.y + z*other.z; - } - void operator *= (const float f) { - *this = *this * f; - } - void scaleBy(const Vec3 &other) { - x *= other.x; y *= other.y; z *= other.z; - } - Vec3 scaledBy(const Vec3 &other) const { - return Vec3(x*other.x, y*other.y, z*other.z); - } - Vec3 scaledByInv(const Vec3 &other) const { - return Vec3(x/other.x, y/other.y, z/other.z); - } - Vec3 operator *(const Matrix4x4 &m) const; - void operator *=(const Matrix4x4 &m) { - *this = *this * m; - } - Vec4 multiply4D(const Matrix4x4 &m) const; - Vec3 rotatedBy(const Matrix4x4 &m) const; - Vec3 operator %(const Vec3 &v) const { - return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); - } - float length2() const { - return x*x + y*y + z*z; - } - float length() const { - return sqrtf(length2()); - } - void setLength(const float l) { - (*this) *= l/length(); - } - Vec3 withLength(const float l) const { - return (*this) * l / length(); - } - float distance2To(const Vec3 &other) const { - return Vec3(other-(*this)).length2(); - } - Vec3 normalized() const { - return (*this) / length(); - } - float normalize() { //returns the previous length, is often useful - float len = length(); - (*this) = (*this)/len; - return len; - } - bool operator == (const Vec3 &other) const { - if (x==other.x && y==other.y && z==other.z) - return true; - else - return false; - } - Vec3 lerp(const Vec3 &other, const float t) const { - return (*this)*(1-t) + other*t; - } - void setZero() { - memset((void *)this,0,sizeof(float)*3); - } + Vec3(const float _x, const float _y, const float _z) { + x=_x; y=_y; z=_z; + } + void Set(float _x, float _y, float _z) { + x=_x; y=_y; z=_z; + } + Vec3 operator + (const Vec3 &other) const { + return Vec3(x+other.x, y+other.y, z+other.z); + } + void operator += (const Vec3 &other) { + x+=other.x; y+=other.y; z+=other.z; + } + Vec3 operator -(const Vec3 &v) const { + return Vec3(x-v.x,y-v.y,z-v.z); + } + void operator -= (const Vec3 &other) + { + x-=other.x; y-=other.y; z-=other.z; + } + Vec3 operator -() const { + return Vec3(-x,-y,-z); + } + + Vec3 operator * (const float f) const { + return Vec3(x*f,y*f,z*f); + } + Vec3 operator / (const float f) const { + float invf = (1.0f/f); + return Vec3(x*invf,y*invf,z*invf); + } + void operator /= (const float f) + { + *this = *this / f; + } + float operator * (const Vec3 &other) const { + return x*other.x + y*other.y + z*other.z; + } + void operator *= (const float f) { + *this = *this * f; + } + void scaleBy(const Vec3 &other) { + x *= other.x; y *= other.y; z *= other.z; + } + Vec3 scaledBy(const Vec3 &other) const { + return Vec3(x*other.x, y*other.y, z*other.z); + } + Vec3 scaledByInv(const Vec3 &other) const { + return Vec3(x/other.x, y/other.y, z/other.z); + } + Vec3 operator *(const Matrix4x4 &m) const; + void operator *=(const Matrix4x4 &m) { + *this = *this * m; + } + Vec4 multiply4D(const Matrix4x4 &m) const; + Vec3 rotatedBy(const Matrix4x4 &m) const; + Vec3 operator %(const Vec3 &v) const { + return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); + } + float length2() const { + return x*x + y*y + z*z; + } + float length() const { + return sqrtf(length2()); + } + void setLength(const float l) { + (*this) *= l/length(); + } + Vec3 withLength(const float l) const { + return (*this) * l / length(); + } + float distance2To(const Vec3 &other) const { + return Vec3(other-(*this)).length2(); + } + Vec3 normalized() const { + return (*this) / length(); + } + float normalize() { //returns the previous length, is often useful + float len = length(); + (*this) = (*this)/len; + return len; + } + bool operator == (const Vec3 &other) const { + if (x==other.x && y==other.y && z==other.z) + return true; + else + return false; + } + Vec3 lerp(const Vec3 &other, const float t) const { + return (*this)*(1-t) + other*t; + } + void setZero() { + memset((void *)this,0,sizeof(float)*3); + } }; inline Vec3 operator * (const float f, const Vec3 &v) {return v * f;} @@ -144,8 +144,8 @@ inline float sqr(const Vec3 &v) { class AABBox { public: - Vec3 min; - Vec3 max; + Vec3 min; + Vec3 max; }; #endif // _MATH_LIN_VEC3 diff --git a/math/math_util.h b/math/math_util.h index 9ff895d7bf..67847ce78b 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -8,16 +8,17 @@ typedef unsigned short float16; // This ain't a 1.5.10 float16, it's a stupid hack format where we chop 16 bits off a float. // This choice is subject to change. Don't think I'm using this for anything at all now anyway. +// DEPRECATED inline float16 FloatToFloat16(float x) { - int ix; - memcpy(&ix, &x, sizeof(float)); - return ix >> 16; + int ix; + memcpy(&ix, &x, sizeof(float)); + return ix >> 16; } inline float Float16ToFloat(float16 ix) { - float x; - memcpy(&x, &ix, sizeof(float)); - return x; + float x; + memcpy(&x, &ix, sizeof(float)); + return x; } @@ -28,60 +29,60 @@ inline float Float16ToFloat(float16 ix) { // PM modulated sine inline float sine(float t,float f,float ph,float fm) { - return sinf((t*f+ph)*2*PI + 0.5f*PI*fm*(1 - sqrt(f*2))); + return sinf((t*f+ph)*2*PI + 0.5f*PI*fm*(1 - sqrt(f*2))); } //fb := feedback (0 to 1) (1 max saw) inline float saw(float t,float f,float ph, float fm, float fb = 1.0f) { - return sine(t,f,ph,fb*sine(t-1.0f,f,ph,fm)); + return sine(t,f,ph,fb*sine(t-1.0f,f,ph,fm)); } // pm := pulse mod (0 to 1) (1 max pulse) // pw := pulse width (0 to 1) (1 square) inline float pulse(float t,float f,float ph,float fm,float fb,float pm,float pw) { - return saw(t,f,ph,fm,fb) - saw(t,f,ph+0.5f*pw,fm,fb) * pm; + return saw(t,f,ph,fm,fb) - saw(t,f,ph+0.5f*pw,fm,fb) * pm; } // Calculate pseudo-random 32 bit number based on linear congruential method. void SetSeed(unsigned int seed); unsigned int GenerateRandomNumber(); inline float GenerateRandomFloat01() { - return (float)((double)GenerateRandomNumber() / 0xFFFFFFFF); + return (float)((double)GenerateRandomNumber() / 0xFFFFFFFF); } inline float GenerateRandomSignedFloat() { - return (float)((double)GenerateRandomNumber() / 0x80000000) - 1.0f; + return (float)((double)GenerateRandomNumber() / 0x80000000) - 1.0f; } inline float GaussRand() { - float R1 = GenerateRandomFloat01(); - float R2 = GenerateRandomFloat01(); + float R1 = GenerateRandomFloat01(); + float R2 = GenerateRandomFloat01(); - float X = sqrtf( -2.0f * logf(R1)) * cosf(2.0f * PI * R2); - if (X > 4.0f) X = 4.0f; - if (X < -4.0f) X = -4.0f; - return X; + float X = sqrtf( -2.0f * logf(R1)) * cosf(2.0f * PI * R2); + if (X > 4.0f) X = 4.0f; + if (X < -4.0f) X = -4.0f; + return X; } // Accuracy unknown inline double atan_fast(double x) { - return (x / (1.0 + 0.28 * (x * x))); + return (x / (1.0 + 0.28 * (x * x))); } // linear -> dB conversion inline float lin2dB(float lin) { - const float LOG_2_DB = 8.6858896380650365530225783783321f; // 20 / ln( 10 ) - return log(lin) * LOG_2_DB; + const float LOG_2_DB = 8.6858896380650365530225783783321f; // 20 / ln( 10 ) + return log(lin) * LOG_2_DB; } // dB -> linear conversion inline float dB2lin(float dB) { - const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20 - return exp(dB * DB_2_LOG); + const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20 + return exp(dB * DB_2_LOG); } #endif diff --git a/midi/midi_input.cpp b/midi/midi_input.cpp index 20e323d33a..143ac12013 100644 --- a/midi/midi_input.cpp +++ b/midi/midi_input.cpp @@ -13,53 +13,52 @@ #include "midi/midi_input.h" std::vector MidiInGetDevices() { - int numDevs = midiInGetNumDevs(); - std::vector devices; - for (int i = 0; i < numDevs; i++) { - MIDIINCAPS caps; - midiInGetDevCaps(i, &caps, sizeof(caps)); - devices.push_back(caps.szPname); - } - return devices; + int numDevs = midiInGetNumDevs(); + std::vector devices; + for (int i = 0; i < numDevs; i++) { + MIDIINCAPS caps; + midiInGetDevCaps(i, &caps, sizeof(caps)); + devices.push_back(caps.szPname); + } + return devices; } -static void CALLBACK MidiCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, - DWORD_PTR dwParam1, DWORD_PTR dwParam2) { - MidiListener *listener = (MidiListener*)dwInstance; - uint8_t cmd[3] = {0}; +static void CALLBACK MidiCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { + MidiListener *listener = (MidiListener*)dwInstance; + uint8_t cmd[3] = {0}; - switch (wMsg) { - case MM_MIM_OPEN: - ILOG("Got MIDI Open message"); - break; - case MM_MIM_CLOSE: - ILOG("Got MIDI Close message"); - break; - case MM_MIM_DATA: - cmd[0] = dwParam1 & 0xFF; - cmd[1] = (dwParam1 >> 8) & 0xFF; - cmd[2] = (dwParam1 >> 16) & 0xFF; - // time = dwParam2 & 0xFFFF; - ILOG("Got MIDI Data: %02x %02x %02x", cmd[0], cmd[1], cmd[2]); - listener->midiEvent(cmd); - break; - default: - WLOG("Got unexpected MIDI message: %08x", (uint32_t)wMsg); - break; - } + switch (wMsg) { + case MM_MIM_OPEN: + ILOG("Got MIDI Open message"); + break; + case MM_MIM_CLOSE: + ILOG("Got MIDI Close message"); + break; + case MM_MIM_DATA: + cmd[0] = dwParam1 & 0xFF; + cmd[1] = (dwParam1 >> 8) & 0xFF; + cmd[2] = (dwParam1 >> 16) & 0xFF; + // time = dwParam2 & 0xFFFF; + ILOG("Got MIDI Data: %02x %02x %02x", cmd[0], cmd[1], cmd[2]); + listener->midiEvent(cmd); + break; + default: + WLOG("Got unexpected MIDI message: %08x", (uint32_t)wMsg); + break; + } } MidiDevice MidiInStart(int deviceID, MidiListener *listener) { - HMIDIIN hMidiIn; - MMRESULT result = midiInOpen(&hMidiIn, deviceID, (DWORD_PTR)(&MidiCallback), (DWORD_PTR)listener, CALLBACK_FUNCTION); - midiInStart(hMidiIn); - return (MidiDevice)hMidiIn; + HMIDIIN hMidiIn; + MMRESULT result = midiInOpen(&hMidiIn, deviceID, (DWORD_PTR)(&MidiCallback), (DWORD_PTR)listener, CALLBACK_FUNCTION); + midiInStart(hMidiIn); + return (MidiDevice)hMidiIn; } void MidiInStop(MidiDevice device) { - HMIDIIN hMidiIn = (HMIDIIN)device; - midiInStop(hMidiIn); - midiInClose(hMidiIn); + HMIDIIN hMidiIn = (HMIDIIN)device; + midiInStop(hMidiIn); + midiInClose(hMidiIn); } #else @@ -74,15 +73,15 @@ void MidiInStop(MidiDevice device) { // Stubs for other platforms. std::vector MidiInGetDevices() { - return std::vector(); + return std::vector(); } MidiDevice MidiInStart(int deviceID, MidiListener *listener) { - FLOG("Invalid MIDI device"); + FLOG("Invalid MIDI device"); } void MidiInStop(MidiDevice device) { - FLOG("Invalid MIDI device"); + FLOG("Invalid MIDI device"); } #endif \ No newline at end of file diff --git a/midi/midi_input.h b/midi/midi_input.h index 371a749799..acfa3a4eb6 100644 --- a/midi/midi_input.h +++ b/midi/midi_input.h @@ -16,8 +16,8 @@ typedef void *MidiDevice; class MidiListener { public: - virtual ~MidiListener() {} - virtual void midiEvent(const uint8_t *cmd) = 0; + virtual ~MidiListener() {} + virtual void midiEvent(const uint8_t *cmd) = 0; }; // Gets the names of the devices in a vector. The device identifier is the index in the vector. diff --git a/native.vcxproj b/native.vcxproj index b5bbbc1f44..da95fada22 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -123,7 +123,6 @@ - diff --git a/native.vcxproj.filters b/native.vcxproj.filters index ea338768b4..912d7a7eef 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -8,7 +8,6 @@ - gfx diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index 28d400cb99..a8f84befae 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -42,7 +42,7 @@ void _profiler_leave(const char *section_name) { cur_section[level].end = real_time_now(); if (strcmp(section_name, cur_section[level].name)) { FLOG("Can't enter %s when %s is active, only one at a time!", - section_name, cur_section[level].name); + section_name, cur_section[level].name); } cur_section[level].level = level; current_frame.push_back(cur_section[level]); diff --git a/ui/ui.cpp b/ui/ui.cpp index 99075d99fe..8e29e9be8f 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -19,35 +19,35 @@ static int themeCheckOnImage; static int themeCheckOffImage; void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int checkOff) { - ui_draw2d.SetAtlas(atlas); + ui_draw2d.SetAtlas(atlas); ui_draw2d_front.SetAtlas(atlas); - themeAtlas = atlas; - themeUIFont = uiFont; - themeButtonImage = buttonImage; - themeCheckOnImage = checkOn; - themeCheckOffImage = checkOff; + themeAtlas = atlas; + themeUIFont = uiFont; + themeButtonImage = buttonImage; + themeCheckOnImage = checkOn; + themeCheckOffImage = checkOff; } void UIUpdateMouse(int i, float x, float y, bool down) { - if (down && !uistate.mousedown[i]) { - uistate.mousepressed[i] = 1; - uistate.mouseStartX[i] = x; - uistate.mouseStartY[i] = y; - } else { - uistate.mousepressed[i] = 0; - } - if (uistate.mousedown[i]) - uistate.mouseframesdown[i]++; - else - uistate.mouseframesdown[i] = 0; + if (down && !uistate.mousedown[i]) { + uistate.mousepressed[i] = 1; + uistate.mouseStartX[i] = x; + uistate.mouseStartY[i] = y; + } else { + uistate.mousepressed[i] = 0; + } + if (uistate.mousedown[i]) + uistate.mouseframesdown[i]++; + else + uistate.mouseframesdown[i] = 0; - uistate.mousex[i] = x; - uistate.mousey[i] = y; - uistate.mousedown[i] = down; + uistate.mousex[i] = x; + uistate.mousey[i] = y; + uistate.mousedown[i] = down; } bool UIRegionHit(int i, int x, int y, int w, int h, int margin) { - // Input handling + // Input handling if (uistate.mousex[i] < x - margin || uistate.mousey[i] < y - margin || uistate.mousex[i] >= x + w + margin || @@ -59,245 +59,245 @@ bool UIRegionHit(int i, int x, int y, int w, int h, int margin) { } void UIBegin() { - for (int i = 0; i < MAX_POINTERS; i++) - uistate.hotitem[i] = 0; + for (int i = 0; i < MAX_POINTERS; i++) + uistate.hotitem[i] = 0; ui_draw2d.Begin(); - ui_draw2d_front.Begin(); + ui_draw2d_front.Begin(); } void UIEnd() { - for (int i = 0; i < MAX_POINTERS; i++) { - if (uistate.mousedown[i] == 0) { - uistate.activeitem[i] = 0; - } else { - if (uistate.activeitem[i] == 0) { - uistate.activeitem[i] = -1; - } - } - } - ui_draw2d.End(); + for (int i = 0; i < MAX_POINTERS; i++) { + if (uistate.mousedown[i] == 0) { + uistate.activeitem[i] = 0; + } else { + if (uistate.activeitem[i] == 0) { + uistate.activeitem[i] = -1; + } + } + } + ui_draw2d.End(); ui_draw2d_front.End(); } void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) { - UIText(themeUIFont, x, y, text, color, scale, align); + UIText(themeUIFont, x, y, text, color, scale, align); } void UIText(int font, int x, int y, const char *text, uint32_t color, float scale, int align) { - ui_draw2d.SetFontScale(scale, scale); - ui_draw2d.DrawTextShadow(font, text, x, y, color, align); - ui_draw2d.SetFontScale(1.0f, 1.0f); + ui_draw2d.SetFontScale(scale, scale); + ui_draw2d.DrawTextShadow(font, text, x, y, color, align); + ui_draw2d.SetFontScale(1.0f, 1.0f); } int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align) { float h = themeAtlas->images[themeButtonImage].h; - - float x, y; - layout.GetPos(&w, &h, &x, &y); - if (button_align & ALIGN_HCENTER) x -= w / 2; - if (button_align & ALIGN_VCENTER) y -= h / 2; - if (button_align & ALIGN_RIGHT) x -= w; - if (button_align & ALIGN_BOTTOMRIGHT) y -= h; + float x, y; + layout.GetPos(&w, &h, &x, &y); - int txOffset = 0; + if (button_align & ALIGN_HCENTER) x -= w / 2; + if (button_align & ALIGN_VCENTER) y -= h / 2; + if (button_align & ALIGN_RIGHT) x -= w; + if (button_align & ALIGN_BOTTOMRIGHT) y -= h; - int clicked = 0; - for (int i = 0; i < MAX_POINTERS; i++) { - // Check whether the button should be hot, use a generous margin for touch ease - if (UIRegionHit(i, x, y, w, h, 8)) { - uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) - uistate.activeitem[i] = id; - } + int txOffset = 0; - if (uistate.hotitem[i] == id) { - if (uistate.activeitem[i] == id) { - // Button is both 'hot' and 'active' - txOffset = 2; - } else { - // Button is merely 'hot' - } - } else { - // button is not hot, but it may be active - } + int clicked = 0; + for (int i = 0; i < MAX_POINTERS; i++) { + // Check whether the button should be hot, use a generous margin for touch ease + if (UIRegionHit(i, x, y, w, h, 8)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } + + if (uistate.hotitem[i] == id) { + if (uistate.activeitem[i] == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id) { + clicked = 1; + } + } - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && - uistate.activeitem[i] == id) { - clicked = 1; - } - } - // Render button ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); ui_draw2d.DrawTextShadow(themeUIFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); - uistate.lastwidget = id; - return clicked; + uistate.lastwidget = id; + return clicked; } int UIImageButton(int id, const LayoutManager &layout, float w, int image, int button_align) { - float h = 64; - float x, y; - layout.GetPos(&w, &h, &x, &y); + float h = 64; + float x, y; + layout.GetPos(&w, &h, &x, &y); - if (button_align & ALIGN_HCENTER) x -= w / 2; - if (button_align & ALIGN_VCENTER) y -= h / 2; - if (button_align & ALIGN_RIGHT) x -= w; - if (button_align & ALIGN_BOTTOMRIGHT) y -= h; + if (button_align & ALIGN_HCENTER) x -= w / 2; + if (button_align & ALIGN_VCENTER) y -= h / 2; + if (button_align & ALIGN_RIGHT) x -= w; + if (button_align & ALIGN_BOTTOMRIGHT) y -= h; - int txOffset = 0; - int clicked = 0; - for (int i = 0; i < MAX_POINTERS; i++) { - // Check whether the button should be hot, use a generous margin for touch ease - if (UIRegionHit(i, x, y, w, h, 8)) { - uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) - uistate.activeitem[i] = id; - } + int txOffset = 0; + int clicked = 0; + for (int i = 0; i < MAX_POINTERS; i++) { + // Check whether the button should be hot, use a generous margin for touch ease + if (UIRegionHit(i, x, y, w, h, 8)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } - if (uistate.hotitem[i] == id) { - if (uistate.activeitem[i] == id) { - // Button is both 'hot' and 'active' - txOffset = 2; - } else { - // Button is merely 'hot' - } - } else { - // button is not hot, but it may be active - } + if (uistate.hotitem[i] == id) { + if (uistate.activeitem[i] == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && - uistate.activeitem[i] == id) { - clicked = 1; - } - } + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id) { + clicked = 1; + } + } - // Render button + // Render button - ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); - ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); + ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); + ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); - uistate.lastwidget = id; - return clicked; + uistate.lastwidget = id; + return clicked; } int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { const int h = 64; - float tw, th; - ui_draw2d.MeasureText(themeUIFont, text, &tw, &th); - int w = themeAtlas->images[themeCheckOnImage].w + UI_SPACE + tw; - if (align & ALIGN_HCENTER) x -= w / 2; - if (align & ALIGN_VCENTER) y -= h / 2; - if (align & ALIGN_RIGHT) x -= w; - if (align & ALIGN_BOTTOMRIGHT) y -= h; + float tw, th; + ui_draw2d.MeasureText(themeUIFont, text, &tw, &th); + int w = themeAtlas->images[themeCheckOnImage].w + UI_SPACE + tw; + if (align & ALIGN_HCENTER) x -= w / 2; + if (align & ALIGN_VCENTER) y -= h / 2; + if (align & ALIGN_RIGHT) x -= w; + if (align & ALIGN_BOTTOMRIGHT) y -= h; - int txOffset = 0; - int clicked = 0; - for (int i = 0; i < MAX_POINTERS; i++) { + int txOffset = 0; + int clicked = 0; + for (int i = 0; i < MAX_POINTERS; i++) { - // Check whether the button should be hot - if (UIRegionHit(i, x, y, w, h, 8)) { - uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) - uistate.activeitem[i] = id; - } - - // Render button + // Check whether the button should be hot + if (UIRegionHit(i, x, y, w, h, 8)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } - if (uistate.hotitem[i] == id) { - if (uistate.activeitem[i] == id) { - // Button is both 'hot' and 'active' - txOffset = 2; - } else { - // Button is merely 'hot' - } - } else { - // button is not hot, but it may be active - } - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && - uistate.activeitem[i] == id) { - *value = !(*value); - clicked = 1; - } - } + // Render button - ui_draw2d.DrawImage((*value) ? themeCheckOnImage : themeCheckOffImage, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + if (uistate.hotitem[i] == id) { + if (uistate.activeitem[i] == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id) { + *value = !(*value); + clicked = 1; + } + } + + ui_draw2d.DrawImage((*value) ? themeCheckOnImage : themeCheckOffImage, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); ui_draw2d.DrawTextShadow(themeUIFont, text, x + themeAtlas->images[themeCheckOnImage].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); - uistate.lastwidget = id; - return clicked; + uistate.lastwidget = id; + return clicked; } void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, bool selected) const { - ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); - ui_draw2d.DrawTextShadow(themeUIFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); + ui_draw2d.DrawTextShadow(themeUIFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); } int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListState *state) { const int item_h = 64; - - int clicked = 0; - for (int i = 0; i < MAX_POINTERS; i++) { - // Check whether the button should be hot - if (UIRegionHit(i, x, y, w, h, 0)) { - uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) - uistate.activeitem[i] = id; - } + int clicked = 0; - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && - uistate.activeitem[i] == id && - state->selected != -1) { - clicked = 1; - } - } + for (int i = 0; i < MAX_POINTERS; i++) { + // Check whether the button should be hot + if (UIRegionHit(i, x, y, w, h, 0)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } - // render items - int itemHeight = adapter->itemHeight(0); - int numItems = adapter->getCount(); - for (int i = 0; i < numItems; i++) { - int item_y = y + i * itemHeight - state->scrollY; - if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h && - UIRegionHit(i, x, item_y, w, h, 0)) { - // ultra fast touch response - state->selected = i; - } - adapter->drawItem(i, x, item_y, w, itemHeight, i == state->selected); - } - uistate.lastwidget = id; + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id && + state->selected != -1) { + clicked = 1; + } + } - // Otherwise, no clicky. + // render items + int itemHeight = adapter->itemHeight(0); + int numItems = adapter->getCount(); + for (int i = 0; i < numItems; i++) { + int item_y = y + i * itemHeight - state->scrollY; + if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h && + UIRegionHit(i, x, item_y, w, h, 0)) { + // ultra fast touch response + state->selected = i; + } + adapter->drawItem(i, x, item_y, w, itemHeight, i == state->selected); + } + uistate.lastwidget = id; + + // Otherwise, no clicky. return clicked; } /* struct SlideItem { - const char *text; - int image; - uint32_t bgColor; +const char *text; +int image; +uint32_t bgColor; }; struct SlideState { - float scroll; +float scroll; }; @@ -310,29 +310,29 @@ int UIHSlider(int id, int x, int y, int w, int max, int *value) { // Calculate mouse cursor's relative y offset int xpos = ((256 - 16) * *value) / max; - for (int i = 0; i < MAX_POINTERS; i++) { - // Check for hotness - if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) { - uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) - uistate.activeitem[i] = id; - } + for (int i = 0; i < MAX_POINTERS; i++) { + // Check for hotness + if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } - // Update widget value - if (uistate.activeitem[i] == id) { - int mousepos = uistate.mousey[i] - (y + 8); - if (mousepos < 0) mousepos = 0; - if (mousepos > 255) mousepos = 255; - int v = (mousepos * max) / 255; - if (v != *value) { - *value = v; - return 1; - } - } - } + // Update widget value + if (uistate.activeitem[i] == id) { + int mousepos = uistate.mousey[i] - (y + 8); + if (mousepos < 0) mousepos = 0; + if (mousepos > 255) mousepos = 255; + int v = (mousepos * max) / 255; + if (v != *value) { + *value = v; + return 1; + } + } + } // Render the scrollbar ui_draw2d.Rect(x, y, 32, 256+16, 0x777777); - + ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xffffff); return 0; diff --git a/ui/ui.h b/ui/ui.h index 42f173757a..248956a0de 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -27,52 +27,52 @@ class LayoutManager { public: - virtual void GetPos(float *w, float *h, float *x, float *y) const = 0; + virtual void GetPos(float *w, float *h, float *x, float *y) const = 0; }; class Pos : public LayoutManager { public: - Pos(float x, float y) : x_(x), y_(y) {} - virtual void GetPos(float *w, float *h, float *x, float *y) const { - *x = x_; - *y = y_; - } + Pos(float x, float y) : x_(x), y_(y) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + } private: - float x_; - float y_; + float x_; + float y_; }; class HLinear : public LayoutManager { public: - HLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {} - virtual void GetPos(float *w, float *h, float *x, float *y) const { - *x = x_; - *y = y_; - x_ += *w + spacing_; - } - void Space(float x) { - x_ += x; - } + HLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + x_ += *w + spacing_; + } + void Space(float x) { + x_ += x; + } private: - mutable float x_; - float y_; - float spacing_; + mutable float x_; + float y_; + float spacing_; }; class VLinear : public LayoutManager { public: - VLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {} - virtual void GetPos(float *w, float *h, float *x, float *y) const { - *x = x_; - *y = y_; - y_ += *h + spacing_; - } + VLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + y_ += *h + spacing_; + } private: - float x_; - mutable float y_; - float spacing_; + float x_; + mutable float y_; + float spacing_; }; #ifndef MAX_POINTERS @@ -85,22 +85,22 @@ struct UIState { int mousex[MAX_POINTERS]; int mousey[MAX_POINTERS]; bool mousedown[MAX_POINTERS]; - bool mousepressed[MAX_POINTERS]; - short mouseframesdown[MAX_POINTERS]; + bool mousepressed[MAX_POINTERS]; + short mouseframesdown[MAX_POINTERS]; - int mouseStartX[MAX_POINTERS]; - int mouseStartY[MAX_POINTERS]; + int mouseStartX[MAX_POINTERS]; + int mouseStartY[MAX_POINTERS]; - int hotitem[MAX_POINTERS]; + int hotitem[MAX_POINTERS]; int activeitem[MAX_POINTERS]; - // keyboard focus, not currently used - int kbdwidget; - int lastwidget; + // keyboard focus, not currently used + int kbdwidget; + int lastwidget; - // Used by controls that need to keep track of the initial value for drags, for example. - // Should probably be indexed by finger - would be neat to be able to move two knobs at the same time. - float tempfloat; + // Used by controls that need to keep track of the initial value for drags, for example. + // Should probably be indexed by finger - would be neat to be able to move two knobs at the same time. + float tempfloat; }; // This needs to be extern so that additional UI controls can be developed outside this file. @@ -122,38 +122,38 @@ const int LARGE_BUTTON_WIDTH = 192; const int BUTTON_HEIGHT = 72; struct SlideItem { - const char *text; - int image; - uint32_t bgColor; + const char *text; + int image; + uint32_t bgColor; }; struct UISlideState { - float scroll; + float scroll; }; // Implement this interface to style your lists class UIListAdapter { public: - virtual size_t getCount() const = 0; - virtual void drawItem(int item, int x, int y, int w, int h, bool active) const = 0; - virtual float itemHeight(int itemIndex) const { return 64; } - virtual bool itemEnabled(int itemIndex) const { return true; } + virtual size_t getCount() const = 0; + virtual void drawItem(int item, int x, int y, int w, int h, bool active) const = 0; + virtual float itemHeight(int itemIndex) const { return 64; } + virtual bool itemEnabled(int itemIndex) const { return true; } }; class StringVectorListAdapter : public UIListAdapter { public: - StringVectorListAdapter(std::vector *items) : items_(items) {} - virtual size_t getCount() const { return items_->size(); } - virtual void drawItem(int item, int x, int y, int w, int h, bool active) const; + StringVectorListAdapter(std::vector *items) : items_(items) {} + virtual size_t getCount() const { return items_->size(); } + virtual void drawItem(int item, int x, int y, int w, int h, bool active) const; private: - std::vector *items_; + std::vector *items_; }; struct UIListState { - UIListState() : scrollY(0.0f), selected(-1) {} - float scrollY; - int selected; + UIListState() : scrollY(0.0f), selected(-1) {} + float scrollY; + int selected; }; From 17f1e71da2e182cd8db93a052777aa47091493bc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 8 May 2012 22:29:28 +0200 Subject: [PATCH 0053/1445] More tabs unification --- file/chunk_file.cpp | 348 ++++++++++++++++++------------------- file/chunk_file.h | 66 +++---- file/dialog.cpp | 86 ++++----- file/easy_file.cpp | 100 +++++------ file/easy_file.h | 64 +++---- file/file_util.cpp | 158 ++++++++--------- file/zip_read.cpp | 22 +-- input/gesture_detector.cpp | 70 ++++---- input/gesture_detector.h | 18 +- input/input_state.h | 28 +-- 10 files changed, 480 insertions(+), 480 deletions(-) diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index 9417a98ecc..402299081c 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -5,270 +5,270 @@ //#define CHUNKDEBUG ChunkFile::ChunkFile(const char *filename, bool _read) { - data=0; + data=0; fn = filename; - fastMode=false; - numLevels=0; - read=_read; - pos=0; - didFail=false; + fastMode=false; + numLevels=0; + read=_read; + pos=0; + didFail=false; fastMode = read ? true : false; - if (fastMode) { + if (fastMode) { size_t size; - data = (uint8 *)VFSReadFile(filename, &size); - if (!data) { - ELOG("Chunkfile fail: %s", filename); - didFail = true; + data = (uint8 *)VFSReadFile(filename, &size); + if (!data) { + ELOG("Chunkfile fail: %s", filename); + didFail = true; return; } eof = size; return; } - if (file.open(filename, FILE_WRITE)) { - didFail=false; - eof=file.fileSize(); - } else { - didFail=true; - return; - } + if (file.open(filename, FILE_WRITE)) { + didFail=false; + eof=file.fileSize(); + } else { + didFail=true; + return; + } } ChunkFile::~ChunkFile() { - if (fastMode && data) - delete [] data; - else - file.close(); + if (fastMode && data) + delete [] data; + else + file.close(); } int ChunkFile::readInt() { - if (pos>8, id>>16, id>>24); #endif - stack[numLevels]=temp; - seekTo(stack[numLevels].parentStartLocation); - return false; - } + stack[numLevels]=temp; + seekTo(stack[numLevels].parentStartLocation); + return false; + } - //descend into it - //pos was set inside the loop above - eof = stack[numLevels].startLocation + stack[numLevels].length; - numLevels++; + //descend into it + //pos was set inside the loop above + eof = stack[numLevels].startLocation + stack[numLevels].length; + numLevels++; #ifdef CHUNKDEBUG ILOG("Descended into %c%c%c%c", id, id>>8, id>>16, id>>24); #endif - return true; - } else { + return true; + } else { #ifndef DEMO_VERSION //if this is missing.. heheh - //write a chunk id, and prepare for filling in length later - writeInt(id); - writeInt(0); //will be filled in by Ascend - stack[numLevels].startLocation=pos; - numLevels++; - return true; + //write a chunk id, and prepare for filling in length later + writeInt(id); + writeInt(0); //will be filled in by Ascend + stack[numLevels].startLocation=pos; + numLevels++; + return true; #else - return true; + return true; #endif - } + } } void ChunkFile::seekTo(int _pos) { - if (!fastMode) - file.seekBeg(_pos); - pos=_pos; + if (!fastMode) + file.seekBeg(_pos); + pos=_pos; } //let's ascend out void ChunkFile::ascend() { - if (read) { - //ascend, and restore information - numLevels--; - seekTo(stack[numLevels].parentStartLocation); - eof = stack[numLevels].parentEOF; + if (read) { + //ascend, and restore information + numLevels--; + seekTo(stack[numLevels].parentStartLocation); + eof = stack[numLevels].parentEOF; #ifdef CHUNKDEBUG int id = stack[numLevels].ID; ILOG("Ascended out of %c%c%c%c", id, id>>8, id>>16, id>>24); #endif - } else { - numLevels--; - //now fill in the written length automatically - int posNow = pos; - seekTo(stack[numLevels].startLocation - 4); - writeInt(posNow-stack[numLevels].startLocation); - seekTo(posNow); - } + } else { + numLevels--; + //now fill in the written length automatically + int posNow = pos; + seekTo(stack[numLevels].startLocation - 4); + writeInt(posNow-stack[numLevels].startLocation); + seekTo(posNow); + } } //read a block void ChunkFile::readData(void *what, int count) { - if (fastMode) - memcpy(what, data + pos, count); - else - file.read(what,count); + if (fastMode) + memcpy(what, data + pos, count); + else + file.read(what,count); - pos+=count; - char temp[4]; //discarded - count &= 3; - if (count) { - count=4-count; - if (!fastMode) - file.read(temp,count); - pos+=count; - } + pos+=count; + char temp[4]; //discarded + count &= 3; + if (count) { + count=4-count; + if (!fastMode) + file.read(temp,count); + pos+=count; + } } //write a block void ChunkFile::writeData(const void *what, int count) { - file.write(what, count); - pos+=count; - char temp[5]={0,0,0,0,0}; - count &= 3; - if (count) - { - count=4-count; - file.write(temp,count); - pos+=count; - } + file.write(what, count); + pos+=count; + char temp[5]={0,0,0,0,0}; + count &= 3; + if (count) + { + count=4-count; + file.write(temp,count); + pos+=count; + } } void ChunkFile::writeWString(String str) { - wchar_t *text; - int len=str.length(); + wchar_t *text; + int len=str.length(); #ifdef UNICODE - text = str.getPointer(); + text = str.getPointer(); #else - text=new wchar_t[len+1]; - str.toUnicode(text); + text=new wchar_t[len+1]; + str.toUnicode(text); #endif - writeInt(len); - writeData((char *)text,len*sizeof(wchar_t)); + writeInt(len); + writeData((char *)text,len*sizeof(wchar_t)); #ifndef UNICODE - delete [] text; + delete [] text; #endif } String ChunkFile::readWString() { - int len=readInt(); - wchar_t *text = new wchar_t[len+1]; - readData((char *)text,len*sizeof(wchar_t)); - text[len]=0; + int len=readInt(); + wchar_t *text = new wchar_t[len+1]; + readData((char *)text,len*sizeof(wchar_t)); + text[len]=0; #ifdef UNICODE - String s(text); - delete [] text; - return s; + String s(text); + delete [] text; + return s; #else - String temp; - temp.fromUnicode(text); - delete [] text; - return temp; + String temp; + temp.fromUnicode(text); + delete [] text; + return temp; #endif } static void toUnicode(const std::string &str, uint16 *t) { - for (int i=0; i<(int)str.size(); i++) { - *t++ = str[i]; - } - *t++ = '\0'; + for (int i=0; i<(int)str.size(); i++) { + *t++ = str[i]; + } + *t++ = '\0'; } static std::string fromUnicode(const uint16 *src, int len) { - struct Local { - static int clamp(int i) { - return i>255?' ':i; - } - }; + struct Local { + static int clamp(int i) { + return i>255?' ':i; + } + }; - std::string str; - str.resize(len); + std::string str; + str.resize(len); - for (int i=0; i>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000); + return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000); } class ChunkFile { public: - ChunkFile(const char *filename, bool _read); - ~ChunkFile(); + ChunkFile(const char *filename, bool _read); + ~ChunkFile(); - bool descend(uint32 id); - void ascend(); + bool descend(uint32 id); + void ascend(); - int readInt(); - void readInt(int &i) {i = readInt();} - void readData(void *data, int count); - String readWString(); + int readInt(); + void readInt(int &i) {i = readInt();} + void readData(void *data, int count); + String readWString(); void writeString(const std::string &str); std::string readString(); - void writeInt(int i); - void writeWString(String str); - void writeData(const void *data, int count); + void writeInt(int i); + void writeWString(String str); + void writeData(const void *data, int count); - int getCurrentChunkSize(); - bool failed() const {return didFail;} + int getCurrentChunkSize(); + bool failed() const {return didFail;} std::string filename() const { return fn; } private: std::string fn; - LAMEFile file; - struct ChunkInfo { - int startLocation; - int parentStartLocation; - int parentEOF; - unsigned int ID; - int length; - }; - ChunkInfo stack[8]; - int numLevels; - - uint8 *data; - int pos,eof; - bool fastMode; - bool read; - bool didFail; - - void seekTo(int _pos); - int getPos() const {return pos;} + LAMEFile file; + struct ChunkInfo { + int startLocation; + int parentStartLocation; + int parentEOF; + unsigned int ID; + int length; + }; + ChunkInfo stack[8]; + int numLevels; + + uint8 *data; + int pos,eof; + bool fastMode; + bool read; + bool didFail; + + void seekTo(int _pos); + int getPos() const {return pos;} }; diff --git a/file/dialog.cpp b/file/dialog.cpp index f67d90ef2e..6a41e81be6 100644 --- a/file/dialog.cpp +++ b/file/dialog.cpp @@ -10,55 +10,55 @@ // An false returned means cancel; bool OpenFileDialog(const char *title, const char *extension, std::string *filename) { - OPENFILENAME of; - memset(&of, 0, sizeof(of)); - char buffer[512] = {0}; - of.lStructSize = sizeof(OPENFILENAME); - of.hInstance = 0; - of.hwndOwner = GetActiveWindow(); + OPENFILENAME of; + memset(&of, 0, sizeof(of)); + char buffer[512] = {0}; + of.lStructSize = sizeof(OPENFILENAME); + of.hInstance = 0; + of.hwndOwner = GetActiveWindow(); - // These weird strings with zeroes in them can't be dealt with using normal string - // functions, so here we go - evil hackery. - char filter[256] = "XXX files\0*.XXX\0\0"; - memcpy(filter, extension, 3); - memcpy(filter + 12, extension, 3); - of.lpstrFilter = filter; + // These weird strings with zeroes in them can't be dealt with using normal string + // functions, so here we go - evil hackery. + char filter[256] = "XXX files\0*.XXX\0\0"; + memcpy(filter, extension, 3); + memcpy(filter + 12, extension, 3); + of.lpstrFilter = filter; - of.lpstrDefExt = extension; - of.lpstrFile = buffer; - of.nMaxFile = 511; + of.lpstrDefExt = extension; + of.lpstrFile = buffer; + of.nMaxFile = 511; - of.Flags = OFN_FILEMUSTEXIST; - if (!GetOpenFileName(&of)) return false; - *filename = of.lpstrFile; - return true; + of.Flags = OFN_FILEMUSTEXIST; + if (!GetOpenFileName(&of)) return false; + *filename = of.lpstrFile; + return true; } bool SaveFileDialog(const char *title, const char *extension, std::string *filename) { - OPENFILENAME of; - memset(&of, 0, sizeof(of)); - char buffer[512] = {0}; - of.lStructSize = sizeof(OPENFILENAME); - of.hInstance = 0; - of.hwndOwner = GetActiveWindow(); + OPENFILENAME of; + memset(&of, 0, sizeof(of)); + char buffer[512] = {0}; + of.lStructSize = sizeof(OPENFILENAME); + of.hInstance = 0; + of.hwndOwner = GetActiveWindow(); - // These weird strings with zeroes in them can't be dealt with using normal string - // functions, so here we go - evil hackery. - char filter[256] = "XXX files\0*.XXX\0\0"; - memcpy(filter, extension, 3); - memcpy(filter + 12, extension, 3); - of.lpstrFilter = filter; + // These weird strings with zeroes in them can't be dealt with using normal string + // functions, so here we go - evil hackery. + char filter[256] = "XXX files\0*.XXX\0\0"; + memcpy(filter, extension, 3); + memcpy(filter + 12, extension, 3); + of.lpstrFilter = filter; - of.lpstrDefExt = extension; - of.lpstrFile = buffer; - of.nMaxFile = 511; + of.lpstrDefExt = extension; + of.lpstrFile = buffer; + of.nMaxFile = 511; - of.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; - if (!GetSaveFileName(&of)) - return false; - *filename = of.lpstrFile; - return true; + of.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; + if (!GetSaveFileName(&of)) + return false; + *filename = of.lpstrFile; + return true; } #else @@ -69,14 +69,14 @@ bool SaveFileDialog(const char *title, const char *extension, std::string *filen bool OpenFileDialog(const char *title, const char *extension, std::string *filename) { - ELOG("Asked for OpenFileDialog, not present on this platform."); - return false; + ELOG("Asked for OpenFileDialog, not present on this platform."); + return false; } bool SaveFileDialog(const char *title, const char *extension, std::string *filename) { - ELOG("Asked for SaveFileDialog, not present on this platform."); - return false; + ELOG("Asked for SaveFileDialog, not present on this platform."); + return false; } #endif \ No newline at end of file diff --git a/file/easy_file.cpp b/file/easy_file.cpp index 20c0b51c1c..21d8935b98 100644 --- a/file/easy_file.cpp +++ b/file/easy_file.cpp @@ -5,87 +5,87 @@ #include "file/easy_file.h" LAMEFile::LAMEFile() : file_(NULL) { - isOpen = false; + isOpen = false; } LAMEFile::~LAMEFile() { } bool LAMEFile::open(const char *filename, eFileMode mode) { - file_ = fopen(filename, mode == FILE_READ ? "rb" : "wb"); + file_ = fopen(filename, mode == FILE_READ ? "rb" : "wb"); - if (!file_) { - isOpen = false; - } else { - isOpen = true; - if (mode == FILE_READ) { - fseek(file_, 0, SEEK_END); - size_ = ftell(file_); - fseek(file_, 0, SEEK_SET); - } - } - return isOpen; + if (!file_) { + isOpen = false; + } else { + isOpen = true; + if (mode == FILE_READ) { + fseek(file_, 0, SEEK_END); + size_ = ftell(file_); + fseek(file_, 0, SEEK_SET); + } + } + return isOpen; } void LAMEFile::close() { - if (isOpen) { - //close the file and reset variables - fclose(file_); - file_ = NULL; - isOpen=false; - } + if (isOpen) { + //close the file and reset variables + fclose(file_); + file_ = NULL; + isOpen=false; + } } int LAMEFile::fileSize() { - if (!isOpen) //of course - return 0; - else - return size_; + if (!isOpen) //of course + return 0; + else + return size_; } std::string LAMEFile::readAll() { - std::string s; - size_t size = fileSize(); - s.resize(size); - read(&s[0], size); - return s; + std::string s; + size_t size = fileSize(); + s.resize(size); + read(&s[0], size); + return s; } int LAMEFile::write(const void *data, int size) { - if (isOpen) { - return fwrite(data, 1, size, file_); //we return the number of bytes that actually got written - } else { - return 0; - } + if (isOpen) { + return fwrite(data, 1, size, file_); //we return the number of bytes that actually got written + } else { + return 0; + } } int LAMEFile::read(void *data, int size) { - if (isOpen) { - return fread(data, 1, size, file_); - } else { - return 0; - } + if (isOpen) { + return fread(data, 1, size, file_); + } else { + return 0; + } } int LAMEFile::readInt() { - int temp; - if (read(&temp, sizeof(int))) - return temp; - else - return 0; + int temp; + if (read(&temp, sizeof(int))) + return temp; + else + return 0; } void LAMEFile::writeInt(int i) { - write(&i, sizeof(int)); + write(&i, sizeof(int)); } char LAMEFile::readChar() { - char temp; - if (read(&temp, sizeof(char))) - return temp; - else - return 0; + char temp; + if (read(&temp, sizeof(char))) + return temp; + else + return 0; } void LAMEFile::writeChar(char i) { - write(&i,sizeof(char)); + write(&i,sizeof(char)); } diff --git a/file/easy_file.h b/file/easy_file.h index 019ea0c2ab..9eed47abd7 100644 --- a/file/easy_file.h +++ b/file/easy_file.h @@ -11,48 +11,48 @@ // Raw file paths, does not go through VFS. enum eFileMode { - FILE_READ=5, - FILE_WRITE=6 + FILE_READ=5, + FILE_WRITE=6 }; // TODO: Rename. class LAMEFile { public: - LAMEFile(); - virtual ~LAMEFile(); + LAMEFile(); + virtual ~LAMEFile(); - bool open(const char *filename, eFileMode mode); - bool open(std::string filename, eFileMode mode) { - return open(filename.c_str(), mode); - } - void close(); + bool open(const char *filename, eFileMode mode); + bool open(std::string filename, eFileMode mode) { + return open(filename.c_str(), mode); + } + void close(); - void writeInt(int i); - void writeChar(char i); - int write(const void *data, int size); - void write(const std::string &str) { - write((void *)str.data(), str.size()); - } + void writeInt(int i); + void writeChar(char i); + int write(const void *data, int size); + void write(const std::string &str) { + write((void *)str.data(), str.size()); + } - int readInt(); - char readChar(); - int read(void *data, int size); + int readInt(); + char readChar(); + int read(void *data, int size); - std::string readAll(); + std::string readAll(); - int fileSize(); + int fileSize(); - void seekBeg(int pos) { - if (isOpen) fseek(file_,pos,SEEK_SET); - } - void seekEnd(int pos) { - if (isOpen) fseek(file_,pos,SEEK_END); - } - void seekCurrent(int pos) { - if (isOpen) fseek(file_,pos,SEEK_CUR); - } + void seekBeg(int pos) { + if (isOpen) fseek(file_,pos,SEEK_SET); + } + void seekEnd(int pos) { + if (isOpen) fseek(file_,pos,SEEK_END); + } + void seekCurrent(int pos) { + if (isOpen) fseek(file_,pos,SEEK_CUR); + } private: - FILE *file_; - bool isOpen; - int size_; + FILE *file_; + bool isOpen; + int size_; }; diff --git a/file/file_util.cpp b/file/file_util.cpp index 0726224ee4..3741bdbdf3 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -14,47 +14,47 @@ bool writeStringToFile(bool text_file, const std::string &str, const char *filename) { - FILE *f = fopen(filename, text_file ? "w" : "wb"); - if (!f) - return false; - size_t len = str.size(); - if (len != fwrite(str.data(), 1, str.size(), f)) - { - fclose(f); - return false; - } - fclose(f); - return true; + FILE *f = fopen(filename, text_file ? "w" : "wb"); + if (!f) + return false; + size_t len = str.size(); + if (len != fwrite(str.data(), 1, str.size(), f)) + { + fclose(f); + return false; + } + fclose(f); + return true; } uint64_t GetSize(FILE *f) { - // can't use off_t here because it can be 32-bit - uint64_t pos = ftell(f); - if (fseek(f, 0, SEEK_END) != 0) { - return 0; - } - uint64_t size = ftell(f); + // can't use off_t here because it can be 32-bit + uint64_t pos = ftell(f); + if (fseek(f, 0, SEEK_END) != 0) { + return 0; + } + uint64_t size = ftell(f); // Reset the seek position to where it was when we started. - if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) { + if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) { // Should error here - return 0; - } - return size; + return 0; + } + return size; } bool ReadFileToString(bool text_file, const char *filename, std::string &str) { - FILE *f = fopen(filename, text_file ? "r" : "rb"); - if (!f) - return false; - size_t len = (size_t)GetSize(f); - char *buf = new char[len + 1]; - buf[fread(buf, 1, len, f)] = 0; - str = std::string(buf, len); - fclose(f); - delete [] buf; - return true; + FILE *f = fopen(filename, text_file ? "r" : "rb"); + if (!f) + return false; + size_t len = (size_t)GetSize(f); + char *buf = new char[len + 1]; + buf[fread(buf, 1, len, f)] = 0; + str = std::string(buf, len); + fclose(f); + delete [] buf; + return true; } #define DIR_SEP "/" @@ -63,77 +63,77 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str) size_t getFilesInDir(const char *directory, std::vector *files) { - size_t foundEntries = 0; + size_t foundEntries = 0; #ifdef _WIN32 - // Find the first file in the directory. - WIN32_FIND_DATA ffd; + // Find the first file in the directory. + WIN32_FIND_DATA ffd; #ifdef UNICODE - HANDLE hFind = FindFirstFile((std::wstring(directory) + "\\*").c_str(), &ffd); + HANDLE hFind = FindFirstFile((std::wstring(directory) + "\\*").c_str(), &ffd); #else - HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd); + HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd); #endif - if (hFind == INVALID_HANDLE_VALUE) - { - FindClose(hFind); - return foundEntries; - } - // windows loop - do - { - const std::string virtualName(ffd.cFileName); + if (hFind == INVALID_HANDLE_VALUE) + { + FindClose(hFind); + return foundEntries; + } + // windows loop + do + { + const std::string virtualName(ffd.cFileName); #else - struct dirent dirent, *result = NULL; + struct dirent dirent, *result = NULL; - DIR *dirp = opendir(directory); - if (!dirp) - return 0; + DIR *dirp = opendir(directory); + if (!dirp) + return 0; - // non windows loop - while (!readdir_r(dirp, &dirent, &result) && result) - { - const std::string virtualName(result->d_name); + // non windows loop + while (!readdir_r(dirp, &dirent, &result) && result) + { + const std::string virtualName(result->d_name); #endif - // check for "." and ".." - if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || - ((virtualName[0] == '.') && (virtualName[1] == '.') && - (virtualName[2] == '\0'))) - continue; + // check for "." and ".." + if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || + ((virtualName[0] == '.') && (virtualName[1] == '.') && + (virtualName[2] == '\0'))) + continue; - files->push_back(std::string(directory) + virtualName); + files->push_back(std::string(directory) + virtualName); #ifdef _WIN32 - } while (FindNextFile(hFind, &ffd) != 0); - FindClose(hFind); + } while (FindNextFile(hFind, &ffd) != 0); + FindClose(hFind); #else - } + } closedir(dirp); #endif - return foundEntries; + return foundEntries; } void deleteFile(const char *file) { #ifdef _WIN32 - if (!DeleteFile(file)) { - ELOG("Error deleting %s: %i", file, GetLastError()); - } + if (!DeleteFile(file)) { + ELOG("Error deleting %s: %i", file, GetLastError()); + } #else - int err = unlink(file); - if (err) { - ELOG("Error unlinking %s: %i", file, err); - } + int err = unlink(file); + if (err) { + ELOG("Error unlinking %s: %i", file, err); + } #endif } #endif std::string getDir(const std::string &path) { - int n = path.size() - 1; - while (n >= 0 && path[n] != '\\' && path[n] != '/') - n--; - std::string cutpath = path.substr(0, n); - for (size_t i = 0; i < cutpath.size(); i++) - { - if (cutpath[i] == '\\') cutpath[i] = '/'; - } - return cutpath; + int n = path.size() - 1; + while (n >= 0 && path[n] != '\\' && path[n] != '/') + n--; + std::string cutpath = path.substr(0, n); + for (size_t i = 0; i < cutpath.size(); i++) + { + if (cutpath[i] == '\\') cutpath[i] = '/'; + } + return cutpath; } \ No newline at end of file diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 04869154f5..c5f436901a 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -83,13 +83,13 @@ uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { #endif uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { - char new_path[256] = {0}; - // Check if it already contains the path + char new_path[256] = {0}; + // Check if it already contains the path if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { - } - else { - strcpy(new_path, path_); - } + } + else { + strcpy(new_path, path_); + } strcat(new_path, path); // ILOG("New path: %s", new_path); return ReadLocalFile(new_path, size); @@ -125,11 +125,11 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { // ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); - if (data) - return data; - else - continue; - // Else try the other registered file systems. + if (data) + return data; + else + continue; + // Else try the other registered file systems. } } ELOG("Missing filesystem for %s", filename); diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 44fafeebbf..01b2098bb7 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -7,17 +7,17 @@ namespace GestureDetector { struct Finger { - bool down; - float X; - float Y; - float lastX; - float lastY; - float downX; - float downY; - float deltaX; - float deltaY; - float smoothDeltaX; - float smoothDeltaY; + bool down; + float X; + float Y; + float lastX; + float lastY; + float downX; + float downY; + float deltaX; + float deltaY; + float smoothDeltaX; + float smoothDeltaY; }; // State @@ -26,43 +26,43 @@ struct Finger { static Finger fingers[MAX_FINGERS]; void update(const InputState &state) { - // Mouse / 1-finger-touch control. - if (state.mouse_down[0]) { - fingers[0].down = true; - fingers[0].downX = state.mouse_x[0]; - fingers[0].downY = state.mouse_y[0]; - } else { - fingers[0].down = false; - } + // Mouse / 1-finger-touch control. + if (state.mouse_down[0]) { + fingers[0].down = true; + fingers[0].downX = state.mouse_x[0]; + fingers[0].downY = state.mouse_y[0]; + } else { + fingers[0].down = false; + } - fingers[0].lastX = fingers[0].X; - fingers[0].lastY = fingers[0].Y; + fingers[0].lastX = fingers[0].X; + fingers[0].lastY = fingers[0].Y; - // TODO: real multitouch + // TODO: real multitouch } bool down(int i, float *xdelta, float *ydelta) { - if (!fingers[i].down) { - return false; - } - *xdelta = fingers[i].downX; - *ydelta = fingers[i].downY; + if (!fingers[i].down) { + return false; + } + *xdelta = fingers[i].downX; + *ydelta = fingers[i].downY; } bool dragDistance(int i, float *xdelta, float *ydelta) { - if (!fingers[i].down) - return false; + if (!fingers[i].down) + return false; - *xdelta = fingers[i].X - fingers[i].downX; - *ydelta = fingers[i].Y - fingers[i].downY; + *xdelta = fingers[i].X - fingers[i].downX; + *ydelta = fingers[i].Y - fingers[i].downY; } bool dragDelta(int i, float *xdelta, float *ydelta) { - if (!fingers[i].down) - return false; + if (!fingers[i].down) + return false; - *xdelta = fingers[i].X - fingers[i].lastX; - *ydelta = fingers[i].Y - fingers[i].lastY; + *xdelta = fingers[i].X - fingers[i].lastX; + *ydelta = fingers[i].Y - fingers[i].lastY; } } diff --git a/input/gesture_detector.h b/input/gesture_detector.h index e8cea6933f..9f5ea36658 100644 --- a/input/gesture_detector.h +++ b/input/gesture_detector.h @@ -5,17 +5,17 @@ namespace GestureDetector { - void update(const InputState &state); + void update(const InputState &state); - bool down(int finger, float *xdown, float *ydown); + bool down(int finger, float *xdown, float *ydown); - // x/ydelta is difference from current location to the start of the drag. - // Returns true if button/finger is down, for convenience. - bool dragDistance(int finger, float *xdelta, float *ydelta); - - // x/ydelta is (smoothed?) difference from current location to the position from the last frame. - // Returns true if button/finger is down, for convenience. - bool dragDelta(int finger, float *xdelta, float *ydelta); + // x/ydelta is difference from current location to the start of the drag. + // Returns true if button/finger is down, for convenience. + bool dragDistance(int finger, float *xdelta, float *ydelta); + + // x/ydelta is (smoothed?) difference from current location to the position from the last frame. + // Returns true if button/finger is down, for convenience. + bool dragDelta(int finger, float *xdelta, float *ydelta); }; diff --git a/input/input_state.h b/input/input_state.h index 2a0e49c20a..8cce30920e 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -21,22 +21,22 @@ enum { #ifndef MAX_POINTERS #define MAX_POINTERS 8 #endif - + // Agglomeration of all possible inputs, and automatically computed // deltas where applicable. struct InputState { - // Lock this whenever you access the data in this struct. - mutable recursive_mutex lock; - InputState() - : pad_buttons(0), - pad_last_buttons(0), - pad_buttons_down(0), - pad_buttons_up(0), - mouse_valid(false), - accelerometer_valid(false) { - memset(mouse_down, 0, sizeof(mouse_down)); - memset(mouse_last, 0, sizeof(mouse_last)); - } + // Lock this whenever you access the data in this struct. + mutable recursive_mutex lock; + InputState() + : pad_buttons(0), + pad_last_buttons(0), + pad_buttons_down(0), + pad_buttons_up(0), + mouse_valid(false), + accelerometer_valid(false) { + memset(mouse_down, 0, sizeof(mouse_down)); + memset(mouse_last, 0, sizeof(mouse_last)); + } // Gamepad style input int pad_buttons; // bitfield @@ -51,7 +51,7 @@ struct InputState { float pad_rtrigger; // Mouse/touch style input - // There are up to 8 mice / fingers. + // There are up to 8 mice / fingers. volatile bool mouse_valid; int mouse_x[MAX_POINTERS]; From ba8e5be264435ab993b22bcf1d71b3972be2b24b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 9 May 2012 00:33:43 +0200 Subject: [PATCH 0054/1445] Rename math_util.cc to cpp, cleanup. --- android/app-android.cpp | 4 ++++ math/math_util.cc | 19 --------------- math/math_util.cpp | 53 +++++++++++++++++++++++++++++++++++++++++ math/math_util.h | 29 +++++++--------------- native.vcxproj | 2 +- native.vcxproj.filters | 6 ++--- 6 files changed, 69 insertions(+), 44 deletions(-) delete mode 100644 math/math_util.cc create mode 100644 math/math_util.cpp diff --git a/android/app-android.cpp b/android/app-android.cpp index d2e6fdd31d..5e7920d5fc 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -20,6 +20,7 @@ #include "file/zip_read.h" #include "input/input_state.h" #include "audio/mixer.h" +#include "math/math_util.h" #define coord_xres 800 #define coord_yres 480 @@ -189,6 +190,9 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender } extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { + // The audio thread can pretty safely enable Flush-to-Zero mode on the FPU. + EnableFZ(); + int buf_size = env->GetArrayLength(array); if (buf_size) { short *data = env->GetShortArrayElements(array, 0); diff --git a/math/math_util.cc b/math/math_util.cc deleted file mode 100644 index 9454df7750..0000000000 --- a/math/math_util.cc +++ /dev/null @@ -1,19 +0,0 @@ -#include "math/math_util.h" -#include -#include - -/* -static unsigned int randSeed = 22222; // Change this for different random sequences. - -void SetSeed(unsigned int seed) { - randSeed = seed * 382792592; -} - -unsigned int GenerateRandomNumber() { - randSeed = (randSeed * 196314165) + 907633515; - randSeed ^= _rotl(randSeed, 13); - return randSeed; -}*/ - -#include - diff --git a/math/math_util.cpp b/math/math_util.cpp new file mode 100644 index 0000000000..29fe6a902e --- /dev/null +++ b/math/math_util.cpp @@ -0,0 +1,53 @@ +#include "math/math_util.h" +#include +#include + +/* +static unsigned int randSeed = 22222; // Change this for different random sequences. + +void SetSeed(unsigned int seed) { + randSeed = seed * 382792592; +} + +unsigned int GenerateRandomNumber() { + randSeed = (randSeed * 196314165) + 907633515; + randSeed ^= _rotl(randSeed, 13); + return randSeed; +}*/ + +#include + +#ifdef ANDROID + +void EnableFZ() +{ + int x; + asm( + "fmrx %[result],FPSCR \r\n" + "orr %[result],%[result],#16777216 \r\n" + "fmxr FPSCR,%[result]" + :[result] "=r" (x) : : + ); + //printf("ARM FPSCR: %08x\n",x); +} + +void DisableFZ( ) +{ + __asm__ volatile( + "fmrx r0, fpscr\n" + "bic r0, $(1 << 24)\n" + "fmxr fpscr, r0" : : : "r0"); +} +#else + +void EnableFZ() +{ + + +} +void DisableFZ() +{ + +} + +#endif \ No newline at end of file diff --git a/math/math_util.h b/math/math_util.h index 67847ce78b..9ee89d6e99 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -27,24 +27,6 @@ inline float Float16ToFloat(float16 ix) { // The stuff in this file is from all over the web, esp. dspmusic.org. I think it's all public domain. // In any case, very little of it is used anywhere at the moment. -// PM modulated sine -inline float sine(float t,float f,float ph,float fm) { - return sinf((t*f+ph)*2*PI + 0.5f*PI*fm*(1 - sqrt(f*2))); -} - -//fb := feedback (0 to 1) (1 max saw) - -inline float saw(float t,float f,float ph, float fm, float fb = 1.0f) -{ - return sine(t,f,ph,fb*sine(t-1.0f,f,ph,fm)); -} - -// pm := pulse mod (0 to 1) (1 max pulse) -// pw := pulse width (0 to 1) (1 square) -inline float pulse(float t,float f,float ph,float fm,float fb,float pm,float pw) { - return saw(t,f,ph,fm,fb) - saw(t,f,ph+0.5f*pw,fm,fb) * pm; -} - // Calculate pseudo-random 32 bit number based on linear congruential method. void SetSeed(unsigned int seed); unsigned int GenerateRandomNumber(); @@ -61,7 +43,7 @@ inline float GaussRand() float R1 = GenerateRandomFloat01(); float R2 = GenerateRandomFloat01(); - float X = sqrtf( -2.0f * logf(R1)) * cosf(2.0f * PI * R2); + float X = sqrtf(-2.0f * logf(R1)) * cosf(2.0f * PI * R2); if (X > 4.0f) X = 4.0f; if (X < -4.0f) X = -4.0f; return X; @@ -76,13 +58,18 @@ inline double atan_fast(double x) { // linear -> dB conversion inline float lin2dB(float lin) { const float LOG_2_DB = 8.6858896380650365530225783783321f; // 20 / ln( 10 ) - return log(lin) * LOG_2_DB; + return logf(lin) * LOG_2_DB; } // dB -> linear conversion inline float dB2lin(float dB) { const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20 - return exp(dB * DB_2_LOG); + return expf(dB * DB_2_LOG); } + +// FPU control. +void EnableFZ(); +void DisableFZ(); + #endif diff --git a/native.vcxproj b/native.vcxproj index da95fada22..bb1c322ab3 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -182,7 +182,7 @@ - + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 912d7a7eef..99a6e411eb 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -220,9 +220,6 @@ gfx - - math - ext @@ -286,6 +283,9 @@ util + + math + From e8ccae22661130b7d9b0e8188b990b61c3bae078 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 14 May 2012 00:42:42 +0200 Subject: [PATCH 0055/1445] Add "Listable" --- data/listable.h | 38 ++++++++++++++++++++++++++++++++++++++ native.vcxproj | 1 + native.vcxproj.filters | 6 ++++++ ui/ui.cpp | 5 +++++ ui/ui.h | 3 +++ 5 files changed, 53 insertions(+) create mode 100644 data/listable.h diff --git a/data/listable.h b/data/listable.h new file mode 100644 index 0000000000..ce6f0b2489 --- /dev/null +++ b/data/listable.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +class Listable +{ +public: + virtual ~Listable() {} + virtual const char *getItem(size_t i) const = 0; + virtual size_t numItems() const = 0; +}; + +class ArrayListable : public Listable +{ +public: + ArrayListable(const char **arr, size_t count) : arr_(arr), count_(count) {} + virtual ~ArrayListable() {} + + virtual const char *getItem(size_t i) const { return arr_[i]; } + virtual size_t numItems() const { return count_; } + +private: + const char **arr_; + size_t count_; +}; + +class VectorListable : public Listable +{ + VectorListable(const std::vector &vec) : vec_(vec) {} + virtual ~VectorListable() {} + + virtual const char *getItem(size_t i) const { return vec_[i].c_str(); } + virtual size_t numItems() const { return vec_.size(); } + +private: + const std::vector &vec_; +}; \ No newline at end of file diff --git a/native.vcxproj b/native.vcxproj index bb1c322ab3..d38abed3ab 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -101,6 +101,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 99a6e411eb..bd0bb8639f 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -158,6 +158,9 @@ util + + data + @@ -330,5 +333,8 @@ {e36ca540-863c-496b-b0f4-b1ece3e72feb} + + {d5fa3d62-88bf-4dc4-9814-28f3c0444e62} + \ No newline at end of file diff --git a/ui/ui.cpp b/ui/ui.cpp index 8e29e9be8f..14a134bacd 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -7,6 +7,7 @@ #include "gfx/texture_atlas.h" #include "gfx_es2/draw_buffer.h" +// TODO: UI should probably not own these. DrawBuffer ui_draw2d; DrawBuffer ui_draw2d_front; UIState uistate; @@ -26,6 +27,7 @@ void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int ch themeButtonImage = buttonImage; themeCheckOnImage = checkOn; themeCheckOffImage = checkOff; + memset(&uistate, 0, sizeof(uistate)); } void UIUpdateMouse(int i, float x, float y, bool down) { @@ -77,6 +79,9 @@ void UIEnd() { } ui_draw2d.End(); ui_draw2d_front.End(); + + if (uistate.ui_tick > 0) + uistate.ui_tick--; } void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) { diff --git a/ui/ui.h b/ui/ui.h index 248956a0de..4ff3f4776a 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -81,6 +81,7 @@ private: // Mouse out of habit, applies just as well to touch events. // UI does not yet support multitouch. +// This struct is zeroed on init, so should be valid at that state. struct UIState { int mousex[MAX_POINTERS]; int mousey[MAX_POINTERS]; @@ -101,6 +102,8 @@ struct UIState { // Used by controls that need to keep track of the initial value for drags, for example. // Should probably be indexed by finger - would be neat to be able to move two knobs at the same time. float tempfloat; + + int ui_tick; }; // This needs to be extern so that additional UI controls can be developed outside this file. From e7bf0303e240c66780e455ec32a654301b53d0e1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 14 May 2012 22:07:40 +0200 Subject: [PATCH 0056/1445] Basic DPI scaling hack. --- android/app-android.cpp | 15 +++++++++++---- .../src/com/turboviking/libnative/NativeApp.java | 2 +- base/colorutil.cpp | 6 ++++++ base/colorutil.h | 1 + 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 5e7920d5fc..578a72fbef 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -22,8 +22,8 @@ #include "audio/mixer.h" #include "math/math_util.h" -#define coord_xres 800 -#define coord_yres 480 +#define coord_xres 480 +#define coord_yres 800 static JNIEnv *jniEnvUI; @@ -98,6 +98,13 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init yres = yyres; g_xres = xres; g_yres = yres; + + if (g_xres < g_yres) + { + // Portrait - let's force the imaginary resolution we want + g_xres = coord_xres; + g_yres = coord_yres; + } xscale = (float)coord_xres / xres; yscale = (float)coord_yres / yres; memset(&input_state, 0, sizeof(input_state)); @@ -211,8 +218,8 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch return; // We ignore 8+ pointers entirely. } - input_state.mouse_x[pointerId] = (int)x; - input_state.mouse_y[pointerId] = (int)y; + input_state.mouse_x[pointerId] = (int)(x * xscale); + input_state.mouse_y[pointerId] = (int)(y * yscale); if (code == 1) { //ILOG("Down: %i %f %f", pointerId, x, y); input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/turboviking/libnative/NativeApp.java index b15e981451..8b5e81b097 100644 --- a/android/src/com/turboviking/libnative/NativeApp.java +++ b/android/src/com/turboviking/libnative/NativeApp.java @@ -16,4 +16,4 @@ public class NativeApp { // Sensor/input data. These are asynchronous, beware! public static native void touch(float x, float y, int data, int pointerId); public static native void accelerometer(float x, float y, float z); -} \ No newline at end of file +} \ No newline at end of file diff --git a/base/colorutil.cpp b/base/colorutil.cpp index 12e1d1755e..9152d78a3d 100644 --- a/base/colorutil.cpp +++ b/base/colorutil.cpp @@ -14,6 +14,12 @@ uint32_t blackAlpha(float alpha) { return (int)(alpha*255)<<24; } +uint32_t colorAlpha(uint32_t color, float alpha) { + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + return ((int)(alpha*255)<<24) | (color & 0xFFFFFF); +} + uint32_t rgba(float r, float g, float b, float alpha) { uint32_t color = (int)(alpha*255)<<24; color |= (int)(b*255)<<16; diff --git a/base/colorutil.h b/base/colorutil.h index 005b4190bd..41f5a94ba7 100644 --- a/base/colorutil.h +++ b/base/colorutil.h @@ -4,6 +4,7 @@ uint32_t whiteAlpha(float alpha); uint32_t blackAlpha(float alpha); +uint32_t colorAlpha(uint32_t color, float alpha); uint32_t rgba(float r, float g, float b, float alpha); uint32_t rgba_clamp(float r, float g, float b, float alpha); uint32_t hsva(float h, float s, float v, float alpha); \ No newline at end of file From a1f8b7e6e13b3e39421d5f0fafc636ec1c93cac5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 3 Jun 2012 17:24:33 +0200 Subject: [PATCH 0057/1445] Listable, json tweaks --- audio/mixer.cpp | 4 ++-- data/listable.h | 15 +++++++++++++-- ext/vjson/json.h | 4 ++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/audio/mixer.cpp b/audio/mixer.cpp index 09743fa9b6..2b3ed7490d 100644 --- a/audio/mixer.cpp +++ b/audio/mixer.cpp @@ -33,7 +33,7 @@ struct Clip { // If current_clip == 0, the channel is free. -enum PlaybackState { +enum ClipPlaybackState { PB_STOPPED = 0, PB_PLAYING = 1, }; @@ -42,7 +42,7 @@ enum PlaybackState { struct Channel { const Clip *current_clip; // Playback state - PlaybackState state; + ClipPlaybackState state; int pos; PlayParams params; // Effect state diff --git a/data/listable.h b/data/listable.h index ce6f0b2489..017cacf1b9 100644 --- a/data/listable.h +++ b/data/listable.h @@ -9,19 +9,30 @@ public: virtual ~Listable() {} virtual const char *getItem(size_t i) const = 0; virtual size_t numItems() const = 0; + + // Returns -1 for not found. + // Child classes are meant to specialize this if they have a faster way + // than brute force search. + virtual int getIndex(const char *text) { + for (size_t i = 0; i < numItems(); i++) { + if (!strcmp(getItem(i), text)) + return i; + } + return -1; + } }; class ArrayListable : public Listable { public: - ArrayListable(const char **arr, size_t count) : arr_(arr), count_(count) {} + ArrayListable(const char * const*arr, size_t count) : arr_(arr), count_(count) {} virtual ~ArrayListable() {} virtual const char *getItem(size_t i) const { return arr_[i]; } virtual size_t numItems() const { return count_; } private: - const char **arr_; + const char *const*arr_; size_t count_; }; diff --git a/ext/vjson/json.h b/ext/vjson/json.h index a6b9bed80e..f798aec0d8 100644 --- a/ext/vjson/json.h +++ b/ext/vjson/json.h @@ -57,6 +57,10 @@ struct json_value bool getBool(const char *child_name) const; bool getBool(const char *child_name, bool default_value) const; + bool hasChild(const char *child_name, json_type child_type) const { + return get(child_name, child_type) != 0; + } + private: DISALLOW_COPY_AND_ASSIGN(json_value); }; From 5dbea730168257e475c9f5a9aae6c3e688f1247b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 3 Jun 2012 19:01:08 +0200 Subject: [PATCH 0058/1445] Add some old HTTP client code, just for kicks. --- base/CMakeLists.txt | 3 +- base/PCMain.cpp | 3 + base/basictypes.h | 2 + base/buffer.cpp | 148 +++++++++++++++++++++++++++++++++++++++++ base/buffer.h | 81 ++++++++++++++++++++++ base/colorutil.cpp | 13 ++-- base/logging.h | 5 ++ base/stringutil.cpp | 14 +++- base/stringutil.h | 8 +++ file/fd_util.cpp | 121 +++++++++++++++++++++++++++++++++ file/fd_util.h | 27 ++++++++ native.vcxproj | 15 +++++ native.vcxproj.filters | 37 ++++++++++- net/CMakeLists.txt | 11 +++ net/http_client.cpp | 147 ++++++++++++++++++++++++++++++++++++++++ net/http_client.h | 66 ++++++++++++++++++ net/resolve.cpp | 48 +++++++++++++ net/resolve.h | 12 ++++ 18 files changed, 752 insertions(+), 9 deletions(-) create mode 100644 base/buffer.cpp create mode 100644 base/buffer.h create mode 100644 file/fd_util.cpp create mode 100644 file/fd_util.h create mode 100644 net/CMakeLists.txt create mode 100644 net/http_client.cpp create mode 100644 net/http_client.h create mode 100644 net/resolve.cpp create mode 100644 net/resolve.h diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 2c4d0c99aa..cb067cad0a 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -2,7 +2,8 @@ set(SRCS LAMEString.cpp colorutil.cpp error_context.cpp - display.cpp) + display.cpp + buffer.cpp) set(SRCS ${SRCS}) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 0c10212882..cf4fdb8597 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -23,6 +23,7 @@ #include "file/zip_read.h" #include "input/input_state.h" #include "base/NativeApp.h" +#include "net/resolve.h" // Simple implementations of System functions @@ -131,6 +132,8 @@ int main(int argc, char *argv[]) { g_yres = 800; } + net::Init(); + if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; diff --git a/base/basictypes.h b/base/basictypes.h index ee9e88a1b2..421d69aa88 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -31,6 +31,8 @@ typedef int64_t int64; #ifdef _WIN32 +typedef intptr_t ssize_t; + #include #define ALIGNED16(x) __declspec(align(16)) x diff --git a/base/buffer.cpp b/base/buffer.cpp new file mode 100644 index 0000000000..5b3dabe77b --- /dev/null +++ b/base/buffer.cpp @@ -0,0 +1,148 @@ +#include "base/buffer.h" + +#include +#include +#include + +#ifdef _WIN32 +#include +#undef min +#undef max +#else +#include +#endif + +#include "base/logging.h" +#include "file/fd_util.h" + +Buffer::Buffer() { } +Buffer::~Buffer() { } + +char *Buffer::Append(ssize_t length) { + size_t old_size = data_.size(); + data_.resize(old_size + length); + return &data_[0] + old_size; +} + +void Buffer::Append(const std::string &str) { + char *ptr = Append(str.size()); + memcpy(ptr, str.data(), str.size()); +} + +void Buffer::Append(const char *str) { + size_t len = strlen(str); + char *dest = Append(len); + memcpy(dest, str, len); +} + +void Buffer::AppendValue(int value) { + char buf[16]; + // This is slow. + sprintf(buf, "%i", value); + Append(buf); +} + +void Buffer::Take(size_t length, std::string *dest) { + CHECK_LE(length, data_.size()); + dest->resize(length); + memcpy(&(*dest)[0], &data_[0], length); + data_.erase(data_.begin(), data_.begin() + length); +} + +int Buffer::TakeLineCRLF(std::string *dest) { + int after_next_line = OffsetToAfterNextCRLF(); + if (after_next_line < 0) + return after_next_line; + else { + Take(after_next_line - 2, dest); + Skip(2); // Skip the CRLF + return after_next_line - 2; + } +} + +void Buffer::Skip(size_t length) { + data_.erase(data_.begin(), data_.begin() + length); +} + +int Buffer::SkipLineCRLF() { + int after_next_line = OffsetToAfterNextCRLF(); + if (after_next_line < 0) + return after_next_line; + else { + Skip(after_next_line); + return after_next_line - 2; + } +} + +int Buffer::OffsetToAfterNextCRLF() { + for (size_t i = 0; i < data_.size() - 1; i++) { + if (data_[i] == '\r' && data_[i + 1] == '\n') { + return i + 2; + } + } + return -1; +} + +void Buffer::Printf(const char *fmt, ...) { + char buffer[512]; + va_list vl; + va_start(vl, fmt); + ssize_t retval = vsnprintf(buffer, sizeof(buffer), fmt, vl); + if (retval >= (ssize_t)sizeof(buffer)) { + // Output was truncated. TODO: Do something. + FLOG("Buffer::Printf truncated output"); + } + CHECK_GE(retval, 0); + va_end(vl); + char *ptr = Append(retval); + CHECK(ptr); + memcpy(ptr, buffer, retval); +} + +bool Buffer::Flush(int fd) { + // Look into using send() directly. + bool success = (ssize_t)data_.size() == fd_util::WriteLine(fd, &data_[0], data_.size()); + if (success) { + data_.resize(0); + } + return success; +} + +bool Buffer::FlushSocket(uintptr_t sock) { + // TODO: send may need retries! + size_t sent = send(sock, &data_[0], data_.size(), 0); + // bool success = fd_util::WriteLine(fd, data_.data(), data_.size()); + if (sent == data_.size()) { + data_.resize(0); + return true; + } else { + ELOG("FlushSocket failed"); + return false; + } +} + +void Buffer::ReadAll(int fd) { + char buf[1024]; + int retval; + while ((retval = recv(fd, buf, sizeof(buf), 0)) > 0) { + char *p = Append((size_t)retval); + memcpy(p, buf, retval); + } +} + +void Buffer::Read(int fd, size_t sz) { + char buf[1024]; + int retval; + while ((retval = recv(fd, buf, std::min(sz, sizeof(buf)), 0)) > 0) { + char *p = Append((size_t)retval); + memcpy(p, buf, retval); + sz -= retval; + if (sz == 0) + break; + } +} + +void Buffer::PeekAll(std::string *dest) { + dest->resize(data_.size()); + memcpy(&(*dest)[0], &data_[0], data_.size()); +} \ No newline at end of file diff --git a/base/buffer.h b/base/buffer.h new file mode 100644 index 0000000000..5f716edbb6 --- /dev/null +++ b/base/buffer.h @@ -0,0 +1,81 @@ +#ifndef _IO_BUFFER_H +#define _IO_BUFFER_H + +#include +#include + +#include "base/basictypes.h" +#include "base/logging.h" + +// Acts as a queue. Intended to be as fast as possible for most uses. +// Does not do synchronization, must use external mutexes. +class Buffer { + public: + Buffer(); + ~Buffer(); + + // Write max [length] bytes to the returned pointer. + // Any other operation on this Buffer invalidates the pointer. + char *Append(ssize_t length); + char *Append(size_t length) { return Append((ssize_t)length); } + + // These work pretty much like you'd expect. + void Append(const char *str); // str null-terminated. The null is not copied. + void Append(const std::string &str); + + // Various types. Useful for varz etc. Appends a string representation of the + // value, rather than a binary representation. + void AppendValue(int value); + + // Parsing Helpers + + // Use for easy line skipping. If no CRLF within the buffer, returns -1. + // If parsing HTML headers, this indicates that you should probably buffer up + // more data. + int OffsetToAfterNextCRLF(); + + // Takers + + void Take(size_t length, std::string *dest); + void TakeAll(std::string *dest) { Take(size(), dest); } + // On failure, return value < 0 and *dest is unchanged. + // Strips off the actual CRLF from the result. + int TakeLineCRLF(std::string *dest); + + // Skippers + void Skip(size_t length); + // Returns -1 on failure (no CRLF within sight). + // Otherwise returns the length of the line skipped, not including CRLF. Can be 0. + int SkipLineCRLF(); + + // Utility functions. + void Printf(const char *fmt, ...); + + // Dumps the entire buffer to the string, but keeps it around. + // Only to be used for debugging, since it might not be fast at all. + void PeekAll(std::string *dest); + + // Simple I/O. + + // Writes the entire buffer to the file descriptor. Also resets the + // size to zero. On failure, data remains in buffer and nothing is + // written. + bool Flush(int fd); + bool FlushSocket(uintptr_t sock); // Windows portability + + void ReadAll(int fd); + void Read(int fd, size_t sz); + + // Utilities. Try to avoid checking for size. + size_t size() const { return data_.size(); } + bool empty() const { return size() == 0; } + void clear() { data_.resize(0); } + + private: + // TODO: Find a better internal representation, like a cord. + std::vector data_; + + DISALLOW_COPY_AND_ASSIGN(Buffer); +}; + +#endif // _IO_BUFFER_H diff --git a/base/colorutil.cpp b/base/colorutil.cpp index 9152d78a3d..a41f50c388 100644 --- a/base/colorutil.cpp +++ b/base/colorutil.cpp @@ -60,7 +60,6 @@ uint32_t hsva(float H, float S, float V, float alpha) { */ float F, M, N, K; int I; - float r, g, b; if ( S == 0.0 ) { // Achromatic case, set level of grey return rgba(V, V, V, alpha); @@ -80,12 +79,14 @@ uint32_t hsva(float H, float S, float V, float alpha) { N = V * (1 - S * F); K = V * (1 - S * (1 - F)); + float r, g, b; if (I == 0) { r = V; g = K; b = M; } - if (I == 1) { r = N; g = V; b = M; } - if (I == 2) { r = M; g = V; b = K; } - if (I == 3) { r = M; g = N; b = V; } - if (I == 4) { r = K; g = M; b = V; } - if (I == 5) { r = V; g = M; b = N; } + else if (I == 1) { r = N; g = V; b = M; } + else if (I == 2) { r = M; g = V; b = K; } + else if (I == 3) { r = M; g = N; b = V; } + else if (I == 4) { r = K; g = M; b = V; } + else if (I == 5) { r = V; g = M; b = N; } + else return 0; return rgba(r, g, b, alpha); } } diff --git a/base/logging.h b/base/logging.h index 15fcba2a6d..435e72a8a5 100644 --- a/base/logging.h +++ b/base/logging.h @@ -63,5 +63,10 @@ inline void Crash() { #undef CHECK #define CHECK(a) {if (!(a)) {FLOG("CHECK failed");}} +#define CHECK_P(a, ...) {if (!(a)) {FLOG("CHECK failed: " __VA_ARGS__);}} #define CHECK_EQ(a, b) CHECK((a) == (b)); #define CHECK_NE(a, b) CHECK((a) != (b)); +#define CHECK_GT(a, b) CHECK((a) > (b)); +#define CHECK_GE(a, b) CHECK((a) >= (b)); +#define CHECK_LT(a, b) CHECK((a) < (b)); +#define CHECK_LE(a, b) CHECK((a) <= (b)); diff --git a/base/stringutil.cpp b/base/stringutil.cpp index 3e977ba9b6..229a8a7e89 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -1,9 +1,11 @@ #include + +#include "base/buffer.h" #include "base/stringutil.h" unsigned int parseHex(const char *_szValue) { - DWORD Count, Value = 0; + int Count, Value = 0; size_t Finish = strlen(_szValue); if (Finish > 8 ) { Finish = 8; } @@ -38,4 +40,14 @@ unsigned int parseHex(const char *_szValue) } } return Value; +} + +void DataToHexString(const uint8 *data, size_t size, std::string *output) { + Buffer buffer; + for (size_t i = 0; i < size; i++) { + buffer.Printf("%02x ", data[i]); + if (i && !(i & 15)) + buffer.Printf("\n"); + } + buffer.TakeAll(output); } \ No newline at end of file diff --git a/base/stringutil.h b/base/stringutil.h index 04cb824d57..59b1d0d03d 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -4,6 +4,8 @@ #include #include +#include "base/basictypes.h" + #ifdef _MSC_VER #pragma warning (disable:4996) #endif @@ -24,5 +26,11 @@ inline bool endsWith(const std::string &str, const std::string &what) { return str.substr(str.size() - what.size()) == what; } +void DataToHexString(const uint8 *data, size_t size, std::string *output); +inline void StringToHexString(const std::string &data, std::string *output) { + DataToHexString((uint8_t *)(&data[0]), data.size(), output); +} + + // highly unsafe and not recommended. unsigned int parseHex(const char* _szValue); diff --git a/file/fd_util.cpp b/file/fd_util.cpp new file mode 100644 index 0000000000..cccb400167 --- /dev/null +++ b/file/fd_util.cpp @@ -0,0 +1,121 @@ +#include "file/fd_util.h" + +#include +#include +#include +#ifndef _WIN32 +#include +#else +#include +#include +#endif +#include + +#include "base/logging.h" + +namespace fd_util { + +// Slow as hell and should only be used for prototyping. +// Reads from a socket, up to an '\n'. This means that if the line ends +// with '\r', the '\r' will be returned. +ssize_t ReadLine(int fd, char *vptr, size_t buf_size) { + char *buffer = vptr; + size_t n; + for (n = 1; n < buf_size; n++) { + char c; + ssize_t rc; + if ((rc = read(fd, &c, 1)) == 1) { + *buffer++ = c; + if (c == '\n') + break; + } + else if (rc == 0) { + if (n == 1) + return 0; + else + break; + } + else { + if (errno == EINTR) + continue; + FLOG("Error in Readline()"); + } + } + + *buffer = 0; + return n; +} + +// Misnamed, it just writes raw data in a retry loop. +ssize_t WriteLine(int fd, const char *vptr, size_t n) { + const char *buffer = vptr; + size_t nleft = n; + + while (nleft > 0) { + ssize_t nwritten; + if ((nwritten = write(fd, buffer, nleft)) <= 0) { + if (errno == EINTR) + nwritten = 0; + else + FLOG("Error in Writeline()"); + } + nleft -= nwritten; + buffer += nwritten; + } + + return n; +} + +ssize_t WriteLine(int fd, const char *buffer) { + return WriteLine(fd, buffer, strlen(buffer)); +} + +ssize_t Write(int fd, const std::string &str) { + return WriteLine(fd, str.c_str(), str.size()); +} + +bool WaitUntilReady(int fd, double timeout) { + struct timeval tv; + tv.tv_sec = floor(timeout); + tv.tv_usec = (timeout - floor(timeout)) * 1000000.0; + + fd_set fds; + FD_ZERO(&fds); + FD_SET(fd, &fds); + // First argument to select is the highest socket in the set + 1. + int rval = select(fd + 1, &fds, NULL, NULL, &tv); + if (rval < 0) { + // Error calling select. + return false; + } else if (rval == 0) { + // Timeout. + return false; + } else { + // Socket is ready. + return true; + } +} + +void SetNonBlocking(int sock, bool non_blocking) { +#ifndef _WIN32 + int opts = fcntl(sock, F_GETFL); + if (opts < 0) { + perror("fcntl(F_GETFL)"); + exit(EXIT_FAILURE); + } + if (non_blocking) { + opts = (opts | O_NONBLOCK); + } else { + opts = (opts & ~O_NONBLOCK); + } + + if (fcntl(sock, F_SETFL, opts) < 0) { + perror("fcntl(F_SETFL)"); + exit(EXIT_FAILURE); + } +#else + WLOG("NonBlocking mode not supported on Win32"); +#endif +} + +} // fd_util diff --git a/file/fd_util.h b/file/fd_util.h new file mode 100644 index 0000000000..a38e59b357 --- /dev/null +++ b/file/fd_util.h @@ -0,0 +1,27 @@ +#ifndef _FD_UTIL +#define _FD_UTIL + +#include +#include + +#include "base/basictypes.h" + +namespace fd_util { + +// Slow as hell and should only be used for prototyping. +ssize_t ReadLine(int fd, char *buffer, size_t buf_size); + +// Decently fast. +ssize_t WriteLine(int fd, const char *buffer, size_t buf_size); +ssize_t WriteLine(int fd, const char *buffer); +ssize_t Write(int fd, const std::string &str); + +// Returns true if the fd became ready, false if it didn't or +// if there was another error. +bool WaitUntilReady(int fd, double timeout); + +void SetNonBlocking(int fd, bool non_blocking); + +} // fd_util + +#endif // _FD_UTIL diff --git a/native.vcxproj b/native.vcxproj index d38abed3ab..fbf66942d2 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -62,6 +62,9 @@ Windows true + + Ws2_32.lib + @@ -80,6 +83,9 @@ true true + + Ws2_32.lib + @@ -89,6 +95,7 @@ + @@ -111,6 +118,7 @@ + @@ -135,6 +143,8 @@ + + @@ -146,10 +156,12 @@ + + @@ -164,6 +176,7 @@ + @@ -185,6 +198,8 @@ + + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index bd0bb8639f..a27c2d5378 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -7,7 +7,6 @@ - gfx @@ -161,6 +160,21 @@ data + + base + + + net + + + base + + + file + + + net + @@ -289,6 +303,21 @@ math + + net + + + base + + + file + + + base + + + net + @@ -336,5 +365,11 @@ {d5fa3d62-88bf-4dc4-9814-28f3c0444e62} + + {1e85f968-7106-483c-ae7d-77d0ef58d787} + + + {6a548b3d-3a4c-4114-aa2f-0b42bf7bf2ce} + \ No newline at end of file diff --git a/net/CMakeLists.txt b/net/CMakeLists.txt new file mode 100644 index 0000000000..10d69f4d51 --- /dev/null +++ b/net/CMakeLists.txt @@ -0,0 +1,11 @@ +set(SRCS + http_client.cpp + resolve.cpp) + +set(SRCS ${SRCS}) + +add_library(net STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/net/http_client.cpp b/net/http_client.cpp new file mode 100644 index 0000000000..8e982d5824 --- /dev/null +++ b/net/http_client.cpp @@ -0,0 +1,147 @@ +#include "net/http_client.h" + +// for inet_pton +#define _WIN32_WINNT 0x600 + +#ifndef _WIN32 +#include +#include +#include +#define closesocket close +#else +#include +#include +#include +#endif + +#include +#include + +#include "base/logging.h" +#include "base/buffer.h" +#include "base/stringutil.h" +#include "net/resolve.h" +// #include "strings/strutil.h" + +namespace net { + +Connection::Connection() + : port_(-1), sock_(-1) { +} + +Connection::~Connection() { + Disconnect(); +} + +bool Connection::Resolve(const char *host, int port) { + CHECK_EQ(-1, sock_); + host_ = host; + port_ = port; + + const char *ip = net::DNSResolve(host); + // VLOG(1) << "Resolved " << host << " to " << ip; + remote_.sin_family = AF_INET; + int tmpres = inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr))); + CHECK_GE(tmpres, 0); // << "inet_pton failed"; + CHECK_NE(0, tmpres); // << ip << " not a valid IP address"; + remote_.sin_port = htons(port); + return true; +} + +void Connection::Connect() { + CHECK_GE(port_, 0); + sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + CHECK_GE(sock_, 0); + //VLOG(1) << "Connecting to " << host_ << ":" << port_; + + // poll once per second.. should find a way to do this blocking. + int retval = -1; + while (retval < 0) { + retval = connect(sock_, (sockaddr *)&remote_, sizeof(struct sockaddr)); + if (retval >= 0) break; +#ifdef _WIN32 + Sleep(1); +#else + sleep(1); +#endif + } +} + +void Connection::Disconnect() { + if (sock_ != -1) { + closesocket(sock_); + sock_ = -1; + } else { + WLOG("Socket was already disconnected."); + } +} + +void Connection::Reconnect() { + Disconnect(); + Connect(); +} + +} // net + +namespace http { + +Client::Client() { +} +Client::~Client() { +} + +#define USERAGENT "METAGET 1.0" + +void Client::GET(const char *resource, Buffer *output) { + Buffer buffer; + const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n"; + buffer.Printf(tpl, resource, host_.c_str()); + CHECK(buffer.FlushSocket(sock())); + + // Snarf all the data we can. + output->ReadAll(sock()); + + // Skip the header. + while (output->SkipLineCRLF() > 0) + ; + + // output now contains the rest of the reply. +} + +int Client::POST(const char *resource, const std::string &data, Buffer *output) { + Buffer buffer; + const char *tpl = "POST %s HTTP/1.0\r\nContent-Length: %d\r\n\r\n"; + buffer.Printf(tpl, resource, (int)data.size()); + buffer.Append(data); + CHECK(buffer.Flush(sock())); + + // I guess we could add a deadline here. + output->ReadAll(sock()); + + if (output->size() == 0) { + // The connection was closed. + ELOG("POST failed."); + return -1; + } + + std::string debug_data; + output->PeekAll(&debug_data); + + //VLOG(1) << "Reply size (before stripping headers): " << debug_data.size(); + std::string debug_str; + StringToHexString(debug_data, &debug_str); + // Tear off the http headers, leaving the actual response data. + std::string firstline; + CHECK_GT(output->TakeLineCRLF(&firstline), 0); + int code = atoi(&firstline[9]); // ugggly hardcoding + //VLOG(1) << "HTTP result code: " << code; + while (true) { + int skipped = output->SkipLineCRLF(); + if (skipped == 0) + break; + } + output->PeekAll(&debug_data); + return code; +} + +} // http diff --git a/net/http_client.h b/net/http_client.h new file mode 100644 index 0000000000..05cd0f2bd0 --- /dev/null +++ b/net/http_client.h @@ -0,0 +1,66 @@ +#ifndef _NET_HTTP_HTTP_CLIENT +#define _NET_HTTP_HTTP_CLIENT + +#include "base/basictypes.h" +#include "base/buffer.h" + +#ifndef _WIN32 +#include +#include +#else +#include +#endif + +namespace net { + +class Connection { + public: + Connection(); + virtual ~Connection(); + + // Inits the sockaddr_in. + bool Resolve(const char *host, int port); + + void Connect(); + void Disconnect(); + + // Disconnects, and connects. Doesn't re-resolve. + void Reconnect(); + + // Only to be used for bring-up and debugging. + uintptr_t sock() const { return sock_; } + + protected: + // Store the remote host here, so we can send it along through HTTP/1.1 requests. + // TODO: Move to http::client? + std::string host_; + int port_; + + sockaddr_in remote_; + + private: + uintptr_t sock_; + +}; + +} // namespace net + +namespace http { + +class Client : public net::Connection { + public: + Client(); + ~Client(); + + void GET(const char *resource, Buffer *output); + + // Return value is the HTTP return code. + int POST(const char *resource, const std::string &data, Buffer *output); + + // HEAD, PUT, DELETE aren't implemented yet. +}; + +} // http + +#endif // _NET_HTTP_HTTP_CLIENT + diff --git a/net/resolve.cpp b/net/resolve.cpp new file mode 100644 index 0000000000..db70db9be4 --- /dev/null +++ b/net/resolve.cpp @@ -0,0 +1,48 @@ +#include "net/resolve.h" + +#include +#include +#include +#include + + +#ifndef _WIN32 +#include +#include // gethostbyname +#else +#include +#include +#endif + + +namespace net { + + +void Init() +{ +#ifdef _WIN32 + WSADATA wsaData = {0}; + WSAStartup(MAKEWORD(2, 2), &wsaData); +#endif +} + +char *DNSResolve(const char *host) +{ + struct hostent *hent; + if((hent = gethostbyname(host)) == NULL) + { + perror("Can't get IP"); + exit(1); + } + int iplen = 15; //XXX.XXX.XXX.XXX + char *ip = (char *)malloc(iplen+1); + memset(ip, 0, iplen+1); + if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL) + { + perror("Can't resolve host"); + exit(1); + } + return ip; +} + +} diff --git a/net/resolve.h b/net/resolve.h new file mode 100644 index 0000000000..70e8b3e6cc --- /dev/null +++ b/net/resolve.h @@ -0,0 +1,12 @@ +#ifndef _NET_RESOLVE_H +#define _NET_RESOLVE_H + +namespace net { + +// Required on Win32 +void Init(); + +// use free() to free the returned string. +char *DNSResolve(const char *host); +} // namespace net +#endif From d0d004fb6f28f6b7f0768adbec18ad5c4d38a77a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 11 Jun 2012 23:26:17 +0200 Subject: [PATCH 0059/1445] ... --- base/PCMain.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index cf4fdb8597..ed7fc50bf5 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -128,8 +128,10 @@ int main(int argc, char *argv[]) { g_xres = 800; g_yres = 480; } else { - g_xres = 1480; - g_yres = 800; +#ifdef _WIN32 + g_xres = 1580; + g_yres = 1000; +#endif } net::Init(); From 6e81b46ee07add18975311132a4f1b88708f774a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Jun 2012 19:53:36 +0200 Subject: [PATCH 0060/1445] Set max priority for audio thread. --- android/src/com/turboviking/libnative/NativeAudioPlayer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/src/com/turboviking/libnative/NativeAudioPlayer.java b/android/src/com/turboviking/libnative/NativeAudioPlayer.java index d12c6447c4..ede5ebc375 100644 --- a/android/src/com/turboviking/libnative/NativeAudioPlayer.java +++ b/android/src/com/turboviking/libnative/NativeAudioPlayer.java @@ -37,6 +37,7 @@ public class NativeAudioPlayer { playThread(); } }); + thread.setPriority(Thread.MAX_PRIORITY); thread.start(); } From 0c038bb43e57c146f65fed280e277481b390feec Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Jun 2012 22:54:26 +0200 Subject: [PATCH 0061/1445] Avoid naming collision --- gfx_es1/CMakeLists.txt | 2 +- gfx_es1/{draw_buffer.cpp => lame_buffer.cpp} | 20 +++++++++++--------- gfx_es1/{draw_buffer.h => lame_buffer.h} | 17 ++++++++++------- native.vcxproj | 2 ++ native.vcxproj.filters | 6 ++++++ 5 files changed, 30 insertions(+), 17 deletions(-) rename gfx_es1/{draw_buffer.cpp => lame_buffer.cpp} (94%) rename gfx_es1/{draw_buffer.h => lame_buffer.h} (91%) diff --git a/gfx_es1/CMakeLists.txt b/gfx_es1/CMakeLists.txt index f618a2598c..a0357bae75 100644 --- a/gfx_es1/CMakeLists.txt +++ b/gfx_es1/CMakeLists.txt @@ -1,5 +1,5 @@ set(SRCS - draw_buffer.cpp + lame_buffer.cpp ) set(SRCS ${SRCS}) diff --git a/gfx_es1/draw_buffer.cpp b/gfx_es1/lame_buffer.cpp similarity index 94% rename from gfx_es1/draw_buffer.cpp rename to gfx_es1/lame_buffer.cpp index 8c8b956933..0f2fb8a18e 100644 --- a/gfx_es1/draw_buffer.cpp +++ b/gfx_es1/lame_buffer.cpp @@ -3,20 +3,21 @@ #ifdef ANDROID #include #else +#include #if defined(__APPLE__) #include #else #include #endif #endif + + #include #include -#include "gfx_es1/draw_buffer.h" +#include "gfx_es1/lame_buffer.h" #include "gfx/texture_atlas.h" -#include "main_atlas.h" - LAMEBuffer buffer; LAMEBuffer topbuffer; @@ -167,6 +168,7 @@ void LAMEBuffer::DrawImage2GridH(int atlas_image, float x1, float y1, float x2, } void LAMEBuffer::MeasureText(int font, const char *text, float *w, float *h) { + if (!font) font = defaultFont; const AtlasFont &atlasfont = *atlas->fonts[font]; unsigned char cval; float wacc = 0, maxh = 0; @@ -268,20 +270,20 @@ void LAMEBuffer::RotateSprite(int atlas_entry, float x, float y, float angle, fl } void LAMEBuffer::drawText(const TCHAR *text, int x, int y, Color color, int font) { - DrawText(UBUNTU24, text, x, y+3, color); + DrawText(font == 0 ? defaultFont : font, text, x, y+3, color); } void LAMEBuffer::drawTextCenter(const TCHAR *text, int x, int y, Color color, int font) { - DrawText(UBUNTU24, text, x, y+3, color, TEXT_HCENTER); + DrawText(font == 0 ? defaultFont : font, text, x, y+3, color, TEXT_HCENTER); } void LAMEBuffer::drawTextShadow(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { - DrawText(UBUNTU24, text, x, y+3, color); + DrawText(font == 0 ? defaultFont : font, text, x, y+3, color); } void LAMEBuffer::drawTextShadowCenter(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { - DrawText(UBUNTU24, text, x, y+3, color, TEXT_HCENTER); + DrawText(font == 0 ? defaultFont : font, text, x, y+3, color, TEXT_HCENTER); } void LAMEBuffer::drawTextContrastCenter(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { - DrawText(UBUNTU24, text, x, y+3, color, TEXT_HCENTER); + DrawText(font == 0 ? defaultFont : font, text, x, y+3, color, TEXT_HCENTER); } void LAMEBuffer::drawTextContrast(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { - DrawText(UBUNTU24, text, x, y+3, color); + DrawText(font == 0 ? defaultFont : font, text, x, y+3, color); } diff --git a/gfx_es1/draw_buffer.h b/gfx_es1/lame_buffer.h similarity index 91% rename from gfx_es1/draw_buffer.h rename to gfx_es1/lame_buffer.h index a1ba53f481..9f8e214dfe 100644 --- a/gfx_es1/draw_buffer.h +++ b/gfx_es1/lame_buffer.h @@ -6,7 +6,7 @@ #include "base/basictypes.h" #include "base/color.h" -class Atlas; +struct Atlas; enum { TEXT_LEFT = 0, @@ -61,12 +61,12 @@ class LAMEBuffer { void RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color); - void drawText(const TCHAR *text, int x, int y, Color color = 0, int font=0); - void drawTextCenter(const TCHAR *text, int x, int y, Color color, int font=0); - void drawTextShadow(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font=0); - void drawTextShadowCenter(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font=0); - void drawTextContrastCenter(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font=0); - void drawTextContrast(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font=0); + void drawText(const TCHAR *text, int x, int y, Color color = 0, int font = 0); + void drawTextCenter(const TCHAR *text, int x, int y, Color color, int font = 0); + void drawTextShadow(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font = 0); + void drawTextShadowCenter(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font = 0); + void drawTextContrastCenter(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font = 0); + void drawTextContrast(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font = 0); void SetFontScale(float xs, float ys) { fontscalex = xs; @@ -93,11 +93,14 @@ class LAMEBuffer { // Draws what we have collected so far, so that we can change blend modes etc. void Flush(); + void SetDefaultFont(int defFont) {defaultFont = defFont;} + private: const Atlas *atlas; float xoffset, yoffset; + int defaultFont; float fontscalex; float fontscaley; diff --git a/native.vcxproj b/native.vcxproj index fbf66942d2..998622508f 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -127,6 +127,7 @@ + @@ -184,6 +185,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index a27c2d5378..457b2b84ae 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -175,6 +175,9 @@ net + + gfx + @@ -318,6 +321,9 @@ net + + gfx + From 79450753a0d52cc802d21f08a7252f3275f19e7b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Jun 2012 23:31:09 +0200 Subject: [PATCH 0062/1445] Remove GLES1.0 code --- gfx_es1/CMakeLists.txt | 10 -- gfx_es1/lame_buffer.cpp | 289 ---------------------------------------- gfx_es1/lame_buffer.h | 125 ----------------- native.vcxproj | 2 - native.vcxproj.filters | 6 - 5 files changed, 432 deletions(-) delete mode 100644 gfx_es1/CMakeLists.txt delete mode 100644 gfx_es1/lame_buffer.cpp delete mode 100644 gfx_es1/lame_buffer.h diff --git a/gfx_es1/CMakeLists.txt b/gfx_es1/CMakeLists.txt deleted file mode 100644 index a0357bae75..0000000000 --- a/gfx_es1/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(SRCS - lame_buffer.cpp -) -set(SRCS ${SRCS}) - -add_library(gfx_es1 STATIC ${SRCS}) - -if(UNIX) - add_definitions(-fPIC) -endif(UNIX) diff --git a/gfx_es1/lame_buffer.cpp b/gfx_es1/lame_buffer.cpp deleted file mode 100644 index 0f2fb8a18e..0000000000 --- a/gfx_es1/lame_buffer.cpp +++ /dev/null @@ -1,289 +0,0 @@ -// OpenGL ES 1.1 - -#ifdef ANDROID -#include -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - - -#include -#include - -#include "gfx_es1/lame_buffer.h" -#include "gfx/texture_atlas.h" - -LAMEBuffer buffer; -LAMEBuffer topbuffer; - -#define MAX_VERTS 16384 - -LAMEBuffer::LAMEBuffer() { - verts = new Vertex[MAX_VERTS]; - vcount = 0; - xoffset = 0; - yoffset = 0; - fontscalex = 0.37f; - fontscaley = 0.37f; -} - -LAMEBuffer::~LAMEBuffer() { - delete [] verts; - verts = 0; -} - -void LAMEBuffer::Setup() { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); -} - -void LAMEBuffer::Finish() { - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -} - -// Draws what we have collected so far, so that we can change blend modes etc. -// TODO: Collect states and then blast at the end? -void LAMEBuffer::Flush() { - if (vcount > 0) { - glVertexPointer (3, GL_FLOAT, sizeof(Vertex), (void *)&verts[0].x); - glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(Vertex), (void *)&verts[0].rgba); - glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void *)&verts[0].u); - glDrawArrays(GL_TRIANGLES, 0, vcount); - // printf("Drawing %i triangles\n", vcount / 3); - } - vcount = 0; -} - -void LAMEBuffer::V(float x, float y, uint32 color, float u, float v) { -#ifndef ANDROID - if (vcount >= MAX_VERTS) { - printf("Hit max # verts\n"); - } -#endif - verts[vcount].x = x + xoffset; - verts[vcount].y = y + yoffset; - verts[vcount].z = 0.0; - verts[vcount].rgba = color; - verts[vcount].u = u; - verts[vcount].v = v; - vcount++; -} - -void LAMEBuffer::rectFill(int x1, int y1, int x2, int y2, Color color) { - rectFillFaded(x1, y1, x2, y2, color, color); -} - -void LAMEBuffer::rectFillFaded(int x1, int y1, int x2, int y2, Color color1, Color color2) { - V(x1, y1, color1, 0, 0); - V(x2, y1, color1, 1, 0); - V(x2, y2, color2, 1, 1); - V(x1, y1, color1, 0, 0); - V(x2, y2, color2, 1, 1); - V(x1, y2, color2, 0, 1); -} - -void LAMEBuffer::MeasureImage(int atlas_image, float *w, float *h) { - const AtlasImage &image = atlas->images[atlas_image]; - *w = image.w; - *h = image.h; -} - -void LAMEBuffer::DrawImage(int atlas_image, float x, float y, Color color) { - const AtlasImage &image = atlas->images[atlas_image]; - float w = image.w; - float h = image.h; - DrawImageStretch(atlas_image, x, y, x + w, y + h, color); -} - -void LAMEBuffer::DrawImageCenter(int atlas_image, float x, float y, Color color) { - const AtlasImage &image = atlas->images[atlas_image]; - DrawImage(atlas_image, x - image.w/2, y - image.h/2, color); -} - -void LAMEBuffer::DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color) { - const AtlasImage &image = atlas->images[atlas_image]; - V(x1, y1, color, image.u1, image.v1); - V(x2, y1, color, image.u2, image.v1); - V(x2, y2, color, image.u2, image.v2); - V(x1, y1, color, image.u1, image.v1); - V(x2, y2, color, image.u2, image.v2); - V(x1, y2, color, image.u1, image.v2); -} - -void LAMEBuffer::DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color) { - V(x1, y1, color, u1, v1); - V(x2, y1, color, u2, v1); - V(x2, y2, color, u2, v2); - V(x1, y1, color, u1, v1); - V(x2, y2, color, u2, v2); - V(x1, y2, color, u1, v2); -} - -void LAMEBuffer::DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color, float corner_scale) { - const AtlasImage &image = atlas->images[atlas_image]; - - float um = (image.u2 - image.u1) * 0.5f; - float vm = (image.v2 - image.v1) * 0.5f; - float iw2 = (image.w * 0.5f) * corner_scale; - float ih2 = (image.h * 0.5f) * corner_scale; - float xa = x1 + iw2; - float xb = x2 - iw2; - float ya = y1 + ih2; - float yb = y2 - ih2; - float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; - // Top row - DrawTexRect(x1, y1, xa, ya, u1, v1, um, vm, color); - DrawTexRect(xa, y1, xb, ya, um, v1, um, vm, color); - DrawTexRect(xb, y1, x2, ya, um, v1, u2, vm, color); - // Middle row - DrawTexRect(x1, ya, xa, yb, u1, vm, um, vm, color); - DrawTexRect(xa, ya, xb, yb, um, vm, um, vm, color); - DrawTexRect(xb, ya, x2, yb, um, vm, u2, vm, color); - // Bottom row - DrawTexRect(x1, yb, xa, y2, u1, vm, um, v2, color); - DrawTexRect(xa, yb, xb, y2, um, vm, um, v2, color); - DrawTexRect(xb, yb, x2, y2, um, vm, u2, v2, color); -} - -void LAMEBuffer::DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color, float corner_scale) { - const AtlasImage &image = atlas->images[atlas_image]; - float um = (image.u2 - image.u1) * 0.5f; - float iw2 = (image.w * 0.5f) * corner_scale; - float xa = x1 + iw2; - float xb = x2 - iw2; - float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; - float y2 = y1 + image.h; - DrawTexRect(x1, y1, xa, y2, u1, v1, um, v2, color); - DrawTexRect(xa, y1, xb, y2, um, v1, um, v2, color); - DrawTexRect(xb, y1, x2, y2, um, v1, u2, v2, color); -} - -void LAMEBuffer::MeasureText(int font, const char *text, float *w, float *h) { - if (!font) font = defaultFont; - const AtlasFont &atlasfont = *atlas->fonts[font]; - unsigned char cval; - float wacc = 0, maxh = 0; - while ((cval = *text++) != '\0') { - if (cval < 32) continue; - if (cval > 127) continue; - AtlasChar c = atlasfont.chars[cval - 32]; - wacc += c.wx * fontscalex; - maxh = 10.0; - } - *w = wacc; - *h = maxh; -} - -void LAMEBuffer::DrawText(int font, const char *text, float x, float y, Color color, int flags) { - const AtlasFont &atlasfont = *atlas->fonts[font]; - unsigned char cval; - if (flags) { - float w, h; - MeasureText(font, text, &w, &h); - if (flags & TEXT_HCENTER) x -= w / 2; - if (flags & TEXT_RIGHT) x -= w; - if (flags & TEXT_VCENTER) y -= h / 2; - } - float sx = x; - while ((cval = *text++) != '\0') { - if (cval == '\n') { - y += 10; - x = sx; - continue; - } - if (cval < 32) continue; - if (cval > 127) continue; - AtlasChar c = atlasfont.chars[cval - 32]; - float cx1 = x + c.ox * fontscalex; - float cy1 = y + c.oy * fontscaley; - float cx2 = x + (c.ox + c.pw) * fontscalex; - float cy2 = y + (c.oy + c.ph) * fontscaley; - V(cx1, cy1, color, c.sx, c.sy); - V(cx2, cy1, color, c.ex, c.sy); - V(cx2, cy2, color, c.ex, c.ey); - V(cx1, cy1, color, c.sx, c.sy); - V(cx2, cy2, color, c.ex, c.ey); - V(cx1, cy2, color, c.sx, c.ey); - x += c.wx * fontscalex; - } -} - - -void LAMEBuffer::hLine(int x1, int y, int x2, Color color) { - rectFill(x1, y, x2, y + 1, color | 0xFF000000); -} - -void LAMEBuffer::hLineDarken(int x1, int y, int x2) { - rectFill(x1, y, x2, y + 1, 0x80000000); -} - -void LAMEBuffer::vLine(int x, int y1, int y2, Color color) { - rectFill(x, y1, x + 1, y2, color); -} - -void LAMEBuffer::vLineAlpha50(int x, int y1, int y2, Color color) { - vLine(x, y1, y2, (color & 0x00FFFFFF) | 0x80); -} - -void LAMEBuffer::rect(int x1, int y1, int x2, int y2, Color color) { - hLine(x1, y1, x2, color); - hLine(x1, y2, x2, color); - vLine(x1, y1, y2, color); - vLine(x2, y1, y2, color); -} - -void LAMEBuffer::rectFillDarken(int x1, int y1, int x2, int y2) { - rectFill(x1, y1, x2, y2, 0x80000000); -} - -void LAMEBuffer::RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color) { - // TODO - will be good for knobs - /* - float c = cos(angle + PI/4); - float s = sin(angle + PI/4); - - float x1 = x + c * scale; - float y1 = y + s * scale; - - float x2 = x + c * scale; - float y2 = y + s * scale; - - float x3 = x + c * scale; - float y3 = y + s * scale; - - V(x1, y1, color1, 0, 0); - V(x2, y1, color1, 1, 0); - V(x2, y2, color2, 1, 1); - V(x1, y1, color1, 0, 0); - V(x2, y2, color2, 1, 1); - V(x1, y2, color2, 0, 1); -*/ -} - -void LAMEBuffer::drawText(const TCHAR *text, int x, int y, Color color, int font) { - DrawText(font == 0 ? defaultFont : font, text, x, y+3, color); -} -void LAMEBuffer::drawTextCenter(const TCHAR *text, int x, int y, Color color, int font) { - DrawText(font == 0 ? defaultFont : font, text, x, y+3, color, TEXT_HCENTER); -} -void LAMEBuffer::drawTextShadow(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { - DrawText(font == 0 ? defaultFont : font, text, x, y+3, color); -} -void LAMEBuffer::drawTextShadowCenter(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { - DrawText(font == 0 ? defaultFont : font, text, x, y+3, color, TEXT_HCENTER); -} -void LAMEBuffer::drawTextContrastCenter(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { - DrawText(font == 0 ? defaultFont : font, text, x, y+3, color, TEXT_HCENTER); -} -void LAMEBuffer::drawTextContrast(const TCHAR *text, int x, int y, Color color, Color shadowColor, int font) { - DrawText(font == 0 ? defaultFont : font, text, x, y+3, color); -} diff --git a/gfx_es1/lame_buffer.h b/gfx_es1/lame_buffer.h deleted file mode 100644 index 9f8e214dfe..0000000000 --- a/gfx_es1/lame_buffer.h +++ /dev/null @@ -1,125 +0,0 @@ -// OpenGL-based 2D primitive buffer. For GLES 1.1. - -#ifndef __LAMEBUFFER_H__ -#define __LAMEBUFFER_H__ - -#include "base/basictypes.h" -#include "base/color.h" - -struct Atlas; - -enum { - TEXT_LEFT = 0, - TEXT_BASELINE = 0, - TEXT_TOP = 1, - TEXT_BOTTOM = 2, - TEXT_HCENTER = 4, - TEXT_VCENTER = 8, - TEXT_RIGHT = 16, -}; - -// Do not inherit from this class. -class LAMEBuffer { - public: - LAMEBuffer(); - ~LAMEBuffer(); - - void SetAtlas(const Atlas *_atlas) { - atlas = _atlas; - } - - void hLine(int x1, int y, int x2, Color color); - void hLineDarken(int x1, int y, int x2); - void vLine(int x, int y1, int y2, Color color); - void vLineAlpha50(int x, int y1, int y2, Color color); - - void rect(int x1, int y1, int x2, int y2, Color color); - void rectFill(int x1, int y1, int x2, int y2, Color color); - void rectRectFill(int x1, int y1, int x2, int y2, Color border, Color fill) { - rectFill(x1,y1,x2,y2,fill); - rect(x1,y1,x2,y2,border); - } - void rectFillFaded(int x1, int y1, int x2, int y2, Color color1, Color color2); - void rectFillDarkFaded(int x1, int y1, int x2, int y2, Color color) { - rectFillFaded(x1,y1,x2,y2,color, darkenColor(color)); - } - - void rectFillDarken(int x1, int y1, int x2, int y2); - - void MeasureImage(int atlas_image, float *w, float *h); - void DrawImage(int atlas_image, float x, float y, Color color = COLOR(0xFFFFFF)); - void DrawImageCenter(int atlas_image, float x, float y, Color color = COLOR(0xFFFFFF)); - void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); - void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); - // Results in 18 triangles. Kind of expensive for a button. - void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); - // This is only 6 triangles, much cheaper. - void DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); - - void MeasureText(int font, const char *text, float *w, float *h); - void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); - - void RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color); - - void drawText(const TCHAR *text, int x, int y, Color color = 0, int font = 0); - void drawTextCenter(const TCHAR *text, int x, int y, Color color, int font = 0); - void drawTextShadow(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font = 0); - void drawTextShadowCenter(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font = 0); - void drawTextContrastCenter(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font = 0); - void drawTextContrast(const TCHAR *text, int x, int y, Color color=0xffffffff, Color shadowColor=0xFF000000, int font = 0); - - void SetFontScale(float xs, float ys) { - fontscalex = xs; - fontscaley = ys; - } - - // Offset management, for easier hierarchical drawing - void PushOffset(int xoff, int yoff) { - // TODO: Use a stack - xoffset = xoff; yoffset = yoff; - } - void PopOffset(int xoff, int yoff) { - xoffset = 0; yoffset = 0; - } - - // Only use in bunches of three. To draw triangles. - inline void V(float x, float y, uint32 color, float u, float v); - - // Call these around all Flush calls of drawbuffers. More than one flush call - // is fine. - static void Setup(); // Enables client state. - static void Finish(); // Disables client state - - // Draws what we have collected so far, so that we can change blend modes etc. - void Flush(); - - void SetDefaultFont(int defFont) {defaultFont = defFont;} - - private: - const Atlas *atlas; - - float xoffset, yoffset; - - int defaultFont; - float fontscalex; - float fontscaley; - - struct Vertex { - float x, y, z; - uint32 rgba; - float u, v; - }; - int vcount; - Vertex *verts; -}; - -// For regular non blended drawing. No alpha, no alpha test. -extern LAMEBuffer buffer; - -// The two blend buffers could be combined using premultiplied alpha. -// But who cares. - -// For regular blended drawing. Standard alpha, no alpha test. -extern LAMEBuffer topbuffer; - -#endif //__LAMEBUFFER_H__ diff --git a/native.vcxproj b/native.vcxproj index 998622508f..fbf66942d2 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -127,7 +127,6 @@ - @@ -185,7 +184,6 @@ - diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 457b2b84ae..a27c2d5378 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -175,9 +175,6 @@ net - - gfx - @@ -321,9 +318,6 @@ net - - gfx - From 3c818e0af7647af95fd1770a5599c08618886d19 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 1 Jul 2012 11:38:18 +0200 Subject: [PATCH 0063/1445] Cleanup, add some wrappers for compat with some old code I have --- base/color.h | 29 +---------------------------- gfx_es2/draw_buffer.h | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/base/color.h b/base/color.h index 5042756936..3206c7f75a 100644 --- a/base/color.h +++ b/base/color.h @@ -1,34 +1,8 @@ #pragma once -// #define COLOR16 - -#ifdef COLOR16 -typedef unsigned short Color; -#else typedef unsigned int Color; -#endif - //have to use a define to ensure constant folding.. with an inline I don't get that, sucks -#ifdef COLOR16 -#error -#define COLOR(i) (short16)(((i&0xF80000)>>8) | ((i&0xFC00)>>5) | ((i&0xF8)>>3)) -inline Color darkenColor(Color color) { - return (color>>1)&0x7BEF; -} -inline Color whitenColor(Color color) { - return ((color>>1)&0x7BEF)+0x7BEF; -} -//single multiplication 16-bit color alpha blending... pretty cool huh? -inline Color colorInterpol(Color x, Color y, int n) -{ - uint32 c1 = (x|(x<<16))&0x7E0F81F; - uint32 c2 = (y|(y<<16))&0x7E0F81F; - uint32 c = (c1 + ((c2 - c1)*n >> 5)) & 0x7E0F81F; - return c | (c >> 16); -} - -#else #define COLOR(i) (((i << 16) & 0xFF0000) | (i & 0xFF00) | ((i >> 16) & 0xFF) | 0xFF000000) inline Color darkenColor(Color color) { return (color & 0xFF000000) | ((color >> 1)&0x7F7F7F); @@ -39,5 +13,4 @@ inline Color whitenColor(Color color) { inline Color colorInterpol(Color x, Color y, int n) { // TODO return x; -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 9e65bb3df9..c62458ade3 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -16,6 +16,7 @@ enum { ALIGN_VCENTER = 8, ALIGN_VBASELINE = 32, // text only, possibly not yet working + ALIGN_CENTER = ALIGN_HCENTER | ALIGN_VCENTER, ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT, ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT, ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT, @@ -51,16 +52,32 @@ public: int Count() const { return count_; } void Flush(const GLSLProgram *program, bool set_blend_state=true); + void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); + void hLine(float x1, float y, float x2, uint32 color) { Rect(x1, y, x2 - x1, 1, color); } + void vLine(float x, float y1, float y2, uint32 color) { Rect(x, y1, 1, y2 - y1, color); } + void vLineAlpha50(float x, float y1, float y2, uint32 color) { Rect(x, y1, 1, y2 - y1, (color | 0xFF000000) & 0x7F000000); } + + void RectOutline(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT) { + hLine(x, y, x + w + 1, color); + hLine(x, y + h, x + w + 1, color); + + vLine(x, y, y + h + 1, color); + vLine(x + w, y, y + h + 1, color); + } + void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom); + void RectVDarkFaded(float x, float y, float w, float h, uint32 colorTop) { + RectVGradient(x, y, w, h, colorTop, darkenColor(colorTop)); + } void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops); void RectCenter(float x, float y, float w, float h, uint32 color) { Rect(x - w/2, y - h/2, w, h, color); } - void Rect(float x, float y, float w, float h, - float u, float v, float uw, float uh, uint32 color); + void Rect(float x, float y, float w, float h, float u, float v, float uw, float uh, uint32 color); + void V(float x, float y, float z, uint32 color, float u, float v); void V(float x, float y, uint32 color, float u, float v) { V(x, y, 0.0f, color, u, v); @@ -85,8 +102,8 @@ public: void DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); void MeasureText(int font, const char *text, float *w, float *h); - void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); - void DrawTextShadow(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int flags = 0); + void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); + void DrawTextShadow(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); void RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color); void SetFontScale(float xs, float ys) { From 90dc94a0ac3c7dd4e095c6b47c347e9f1022d9b3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 5 Jul 2012 23:30:35 +0200 Subject: [PATCH 0064/1445] Portafix --- base/PCMain.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index fc5759b1ef..d6c621e91d 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -28,7 +28,11 @@ // Simple implementations of System functions void SystemToast(const char *text) { - MessageBox(0, text, "Toast!", MB_ICONINFORMATION); +#ifdef _WIN32 + MessageBox(0, text, "Toast!", MB_ICONINFORMATION); +#else + puts(text); +#endif } From 26da3ea198d64ffd5ceaf7761a499d11e0fa092b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 5 Jul 2012 23:42:47 +0200 Subject: [PATCH 0065/1445] mac fixes --- gfx_es2/CMakeLists.txt | 3 ++- net/resolve.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx_es2/CMakeLists.txt b/gfx_es2/CMakeLists.txt index d412efb163..fdf0dbfb71 100644 --- a/gfx_es2/CMakeLists.txt +++ b/gfx_es2/CMakeLists.txt @@ -1,7 +1,8 @@ set(SRCS draw_buffer.cpp fbo.cpp - glsl_program.cpp) + glsl_program.cpp + vertex_format.cpp) set(SRCS ${SRCS}) diff --git a/net/resolve.cpp b/net/resolve.cpp index db70db9be4..0dcd6870c8 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -2,7 +2,6 @@ #include #include -#include #include From aaa15177e0c9030271d0452e74c9490237e4b06e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 6 Jul 2012 22:32:32 +0200 Subject: [PATCH 0066/1445] some basic zoom/dpi stuff, to be improved --- android/app-android.cpp | 17 ++-- base/PCMain.cpp | 166 +++++++++++++++++++++------------------- base/display.cpp | 2 + base/display.h | 2 + 4 files changed, 98 insertions(+), 89 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 578a72fbef..97eff63e5c 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -72,7 +72,6 @@ void LaunchEmail(const char *email_address) // Remember that all of these need initialization on init! The process // may be reused when restarting the game. Globals are DANGEROUS. -int xres, yres; // Used for touch. (TODO) float xscale = 1; @@ -94,19 +93,19 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init (JNIEnv *env, jclass, jint xxres, jint yyres, jstring apkpath, jstring dataDir, jstring externalDir, jstring jinstallID) { jniEnvUI = env; - xres = xxres; - yres = yyres; - g_xres = xres; - g_yres = yres; + pixel_xres = xxres; + pixel_yres = yyres; + g_xres = xxres; + g_yres = yyres; if (g_xres < g_yres) { // Portrait - let's force the imaginary resolution we want - g_xres = coord_xres; - g_yres = coord_yres; + g_xres = pixel_xres; + g_yres = pixel_yres; } - xscale = (float)coord_xres / xres; - yscale = (float)coord_yres / yres; + xscale = (float)g_xres / pixel_xres; + yscale = (float)g_yres / pixel_yres; memset(&input_state, 0, sizeof(input_state)); renderer_inited = false; first_lost = true; diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 35b3b8a067..84240f8f11 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -30,9 +30,9 @@ void SystemToast(const char *text) { #ifdef _WIN32 - MessageBox(0, text, "Toast!", MB_ICONINFORMATION); + MessageBox(0, text, "Toast!", MB_ICONINFORMATION); #else - puts(text); + puts(text); #endif } @@ -76,69 +76,79 @@ void LaunchEmail(const char *email_address) const int buttonMappings[12] = { - SDLK_x, //A - SDLK_s, //B - SDLK_z, //X - SDLK_a, //Y + SDLK_x, //A + SDLK_s, //B + SDLK_z, //X + SDLK_a, //Y SDLK_w, //LBUMPER SDLK_q, //RBUMPER SDLK_1, //START SDLK_2, //BACK - SDLK_UP, //UP + SDLK_UP, //UP SDLK_DOWN, //DOWN - SDLK_LEFT, //LEFT - SDLK_RIGHT, //RIGHT + SDLK_LEFT, //LEFT + SDLK_RIGHT, //RIGHT }; void SimulateGamepad(const uint8 *keys, InputState *input) { - input->pad_buttons = 0; - input->pad_lstick_x = 0; - input->pad_lstick_y = 0; - input->pad_rstick_x = 0; - input->pad_rstick_y = 0; + input->pad_buttons = 0; + input->pad_lstick_x = 0; + input->pad_lstick_y = 0; + input->pad_rstick_x = 0; + input->pad_rstick_y = 0; for (int b = 0; b < 12; b++) { if (keys[buttonMappings[b]]) input->pad_buttons |= (1<pad_lstick_y=32000; + if (keys['I']) input->pad_lstick_y=32000; else if (keys['K']) input->pad_lstick_y=-32000; - if (keys['J']) input->pad_lstick_x=-32000; + if (keys['J']) input->pad_lstick_x=-32000; else if (keys['L']) input->pad_lstick_x=32000; - if (keys['8']) input->pad_rstick_y=32000; + if (keys['8']) input->pad_rstick_y=32000; else if (keys['2']) input->pad_rstick_y=-32000; - if (keys['4']) input->pad_rstick_x=-32000; + if (keys['4']) input->pad_rstick_x=-32000; else if (keys['6']) input->pad_rstick_x=32000; } extern void mixaudio(void *userdata, Uint8 *stream, int len) { - NativeMix((short *)stream, len / 4); + NativeMix((short *)stream, len / 4); } #ifdef _WIN32 #undef main #endif int main(int argc, char *argv[]) { - /* // Xoom resolution. Other common tablet resolutions: 1024x600 , 1366x768 - g_xres = 1280; - g_yres = 800; - */ + /* // Xoom resolution. Other common tablet resolutions: 1024x600 , 1366x768 + g_xres = 1280; + g_yres = 800; + */ std::string app_name; std::string app_name_nice; bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); + float zoom = 0.7f; + const char *zoomenv = getenv("ZOOM"); + if (zoomenv) { + zoom = atof(zoomenv); + } if (landscape) { - g_xres = 800; - g_yres = 480; + pixel_xres = 800 * zoom; + pixel_yres = 480 * zoom; } else { -#ifdef _WIN32 - g_xres = 1580; - g_yres = 1000; -#endif + pixel_xres = 1580 * zoom; + pixel_yres = 1000 * zoom; } - net::Init(); + float density = 1.0f; + g_xres = (float)pixel_xres * density / zoom; + g_yres = (float)pixel_yres * density / zoom; + + printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); + printf("Virtual pixels: %i x %i\n", g_xres, g_yres); + + net::Init(); if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); @@ -155,7 +165,7 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); - if (SDL_SetVideoMode(g_xres, g_yres, 0, SDL_OPENGL) == NULL) { + if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, SDL_OPENGL) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return(2); @@ -193,32 +203,32 @@ int main(int argc, char *argv[]) { #endif NativeInit(argc, (const char **)argv, path, "BADCOFFEE"); - NativeInitGraphics(); + NativeInitGraphics(); - SDL_AudioSpec fmt; - fmt.freq = 44100; - fmt.format = AUDIO_S16; - fmt.channels = 2; - fmt.samples = 1024; - fmt.callback = &mixaudio; - fmt.userdata = (void *)0; + SDL_AudioSpec fmt; + fmt.freq = 44100; + fmt.format = AUDIO_S16; + fmt.channels = 2; + fmt.samples = 1024; + fmt.callback = &mixaudio; + fmt.userdata = (void *)0; - if (SDL_OpenAudio(&fmt, NULL) < 0) { - ELOG("Failed to open audio: %s", SDL_GetError()); - return 1; - } + if (SDL_OpenAudio(&fmt, NULL) < 0) { + ELOG("Failed to open audio: %s", SDL_GetError()); + return 1; + } - // Audio must be unpaused _after_ NativeInit() - SDL_PauseAudio(0); + // Audio must be unpaused _after_ NativeInit() + SDL_PauseAudio(0); - InputState input_state; - int framecount = 0; + InputState input_state; + int framecount = 0; bool nextFrameMD = 0; while (true) { SDL_Event event; - input_state.accelerometer_valid = false; - input_state.mouse_valid = true; + input_state.accelerometer_valid = false; + input_state.mouse_valid = true; int done = 0; // input_state.mouse_down[1] = nextFrameMD; @@ -230,61 +240,57 @@ int main(int argc, char *argv[]) { done = 1; } } else if (event.type == SDL_MOUSEMOTION) { - input_state.mouse_x[0] = event.motion.x; - input_state.mouse_y[0] = event.motion.y; - input_state.mouse_x[1] = event.motion.x + 150; - input_state.mouse_y[1] = event.motion.y; + input_state.mouse_x[0] = event.motion.x * density / zoom; + input_state.mouse_y[0] = event.motion.y * density / zoom; } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { - ///input_state.mouse_buttons_down = 1; + //input_state.mouse_buttons_down = 1; input_state.mouse_down[0] = true; nextFrameMD = true; } } else if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { input_state.mouse_down[0] = false; - nextFrameMD = false; - //input_state.mouse_buttons_up = 1; - } + nextFrameMD = false; + //input_state.mouse_buttons_up = 1; + } } } + if (done) + break; - - if (done) break; - - input_state.mouse_last[0] = input_state.mouse_down[0]; + input_state.mouse_last[0] = input_state.mouse_down[0]; uint8 *keys = (uint8 *)SDL_GetKeyState(NULL); - if (keys[SDLK_ESCAPE]) { - break; - } + if (keys[SDLK_ESCAPE]) + break; SimulateGamepad(keys, &input_state); - UpdateInputState(&input_state); - NativeUpdate(input_state); - NativeRender(); - if (framecount % 60 == 0) { - // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. - } + UpdateInputState(&input_state); + NativeUpdate(input_state); + NativeRender(); + if (framecount % 60 == 0) { + // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. + } SDL_GL_SwapBuffers(); - // Simple framerate limiting + // Simple framerate limiting static float t=0; while (time_now() < t+1.0f/60.0f) { sleep_ms(0); - time_update(); + time_update(); } - time_update(); + time_update(); t = time_now(); - framecount++; + framecount++; } - // Faster exit, thanks to the OS. Remove this if you want to debug shutdown - exit(0); + // Faster exit, thanks to the OS. Remove this if you want to debug shutdown + exit(0); - NativeShutdownGraphics(); - SDL_PauseAudio(1); - NativeShutdown(); - SDL_CloseAudio(); + NativeShutdownGraphics(); + SDL_PauseAudio(1); + NativeShutdown(); + SDL_CloseAudio(); SDL_Quit(); return 0; } diff --git a/base/display.cpp b/base/display.cpp index b84f2dd604..5896c392f5 100644 --- a/base/display.cpp +++ b/base/display.cpp @@ -2,3 +2,5 @@ int g_xres; int g_yres; +int pixel_xres; +int pixel_yres; diff --git a/base/display.h b/base/display.h index 8dae4a6bb2..18e4920c71 100644 --- a/base/display.h +++ b/base/display.h @@ -5,3 +5,5 @@ extern int g_xres; extern int g_yres; +extern int pixel_xres; +extern int pixel_yres; From 3e05162dc0988b90fcc086bccfec4beb40c2a8a0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 7 Jul 2012 22:58:27 +0200 Subject: [PATCH 0067/1445] Start work on using OpenSL conditionally (to still support Android 2.2) --- android/app-android.cpp | 19 +- android/native-audio-so.cpp | 200 ++++++++++++++++++ android/native-audio-so.h | 8 + android/native_audio.cpp | 34 +++ android/native_audio.h | 12 ++ .../turboviking/libnative/NativeActivity.java | 7 +- .../com/turboviking/libnative/NativeApp.java | 4 +- 7 files changed, 278 insertions(+), 6 deletions(-) create mode 100644 android/native-audio-so.cpp create mode 100644 android/native-audio-so.h create mode 100644 android/native_audio.cpp create mode 100644 android/native_audio.h diff --git a/android/app-android.cpp b/android/app-android.cpp index 97eff63e5c..7968abc568 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -21,6 +21,7 @@ #include "input/input_state.h" #include "audio/mixer.h" #include "math/math_util.h" +#include "android/native_audio.h" #define coord_xres 480 #define coord_yres 800 @@ -81,6 +82,7 @@ InputState input_state; static bool renderer_inited = false; static bool first_lost = true; +static bool use_native_audio = false; extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) { std::string app_name, app_nice_name; @@ -91,13 +93,13 @@ extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv extern "C" void Java_com_turboviking_libnative_NativeApp_init (JNIEnv *env, jclass, jint xxres, jint yyres, jstring apkpath, - jstring dataDir, jstring externalDir, jstring jinstallID) { + jstring dataDir, jstring externalDir, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; pixel_xres = xxres; pixel_yres = yyres; g_xres = xxres; g_yres = yyres; - + use_native_audio = juseNativeAudio; if (g_xres < g_yres) { // Portrait - let's force the imaginary resolution we want @@ -124,7 +126,8 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init str = env->GetStringUTFChars(jinstallID, &isCopy); std::string installID = std::string(str); - std::string app_name, app_nice_name; + std::string app_name; + std::string app_nice_name; bool landscape; NativeGetAppInfo(&app_name, &app_nice_name, &landscape); @@ -275,3 +278,13 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_accelerometer input_state.acc.y = y; input_state.acc.z = z; } + +extern "C" void Java_com_turboviking_libnative_NativeApp_sendMessage + (JNIEnv *env, jclass, jstring message, jstring param) { + jboolean isCopy; + std::string msg(env->GetStringUTFChars(message, &isCopy)); + std::string prm(env->GetStringUTFChars(param, &isCopy)); + ILOG("Message received: %s %s", msg.c_str(), prm.c_str()); +} + + diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp new file mode 100644 index 0000000000..4c4eeed270 --- /dev/null +++ b/android/native-audio-so.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* This is a JNI example where we use native methods to play sounds + * using OpenSL ES. See the corresponding Java source file located at: + * + * src/com/example/nativeaudio/NativeAudio/NativeAudio.java + */ + +#include +#include + +// for __android_log_print(ANDROID_LOG_INFO, "YourApp", "formatted message"); +// #include + +// for native audio +#include +#include + +// engine interfaces +static SLObjectItf engineObject = NULL; +static SLEngineItf engineEngine; + +// output mix interfaces +static SLObjectItf outputMixObject = NULL; +static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL; + +// buffer queue player interfaces +static SLObjectItf bqPlayerObject = NULL; +static SLPlayItf bqPlayerPlay; +static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; +static SLMuteSoloItf bqPlayerMuteSolo; +static SLVolumeItf bqPlayerVolume; + +// synthesized sawtooth clip +#define SAWTOOTH_FRAMES 8000 +static short sawtoothBuffer[SAWTOOTH_FRAMES]; + +// pointer and size of the next player buffer to enqueue, and number of remaining buffers +static short *nextBuffer; +static unsigned nextSize; + +// synthesize a mono sawtooth wave and place it into a buffer (called automatically on load) +__attribute__((constructor)) static void onDlOpen(void) +{ + unsigned int i; + for (i = 0; i < SAWTOOTH_FRAMES; ++i) { + sawtoothBuffer[i] = 32768 - ((i % 100) * 660); + } +} + +// this callback handler is called every time a buffer finishes playing +void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) +{ + assert(bq == bqPlayerBufferQueue); + assert(NULL == context); + + + nextBuffer = sawtoothBuffer; + nextSize = sizeof(sawtoothBuffer); + SLresult result; + // enqueue another buffer + result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); + // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, + // which for this code example would indicate a programming error + assert(SL_RESULT_SUCCESS == result); +} + +// create the engine and output mix objects +extern "C" bool OpenSLWrap_Init() +{ + SLresult result; + + // create engine + result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); + assert(SL_RESULT_SUCCESS == result); + + // realize the engine + result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + + // get the engine interface, which is needed in order to create other objects + result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); + assert(SL_RESULT_SUCCESS == result); + + // create output mix, with environmental reverb specified as a non-required interface + const SLInterfaceID ids1[1] = {SL_IID_ENVIRONMENTALREVERB}; + const SLboolean req1[1] = {SL_BOOLEAN_FALSE}; + result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids1, req1); + assert(SL_RESULT_SUCCESS == result); + + // realize the output mix + result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + + // create buffer queue audio player + // ================================ + + // configure audio source + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; + + // TODO: This is all wrong. + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, + 1, + SL_SAMPLINGRATE_8, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_SPEAKER_FRONT_CENTER, + SL_BYTEORDER_LITTLEENDIAN}; + + SLDataSource audioSrc = {&loc_bufq, &format_pcm}; + + // configure audio sink + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; + SLDataSink audioSnk = {&loc_outmix, NULL}; + + // create audio player + const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; + const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, + 3, ids, req); + assert(SL_RESULT_SUCCESS == result); + + // realize the player + result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + + // get the play interface + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); + assert(SL_RESULT_SUCCESS == result); + + // get the buffer queue interface + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, + &bqPlayerBufferQueue); + assert(SL_RESULT_SUCCESS == result); + + // register callback on the buffer queue + result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); + assert(SL_RESULT_SUCCESS == result); + + // get the volume interface + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); + assert(SL_RESULT_SUCCESS == result); + + // set the player's state to playing + result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); + assert(SL_RESULT_SUCCESS == result); + + if (nextBuffer) { + SLresult result; + result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); + if (SL_RESULT_SUCCESS != result) { + return false; + } + } + return true; +} + +// shut down the native audio system +extern "C" void OpenSLWrap_Shutdown() +{ + // destroy buffer queue audio player object, and invalidate all associated interfaces + if (bqPlayerObject != NULL) { + (*bqPlayerObject)->Destroy(bqPlayerObject); + bqPlayerObject = NULL; + bqPlayerPlay = NULL; + bqPlayerBufferQueue = NULL; + bqPlayerMuteSolo = NULL; + bqPlayerVolume = NULL; + } + + // destroy output mix object, and invalidate all associated interfaces + if (outputMixObject != NULL) { + (*outputMixObject)->Destroy(outputMixObject); + outputMixObject = NULL; + outputMixEnvironmentalReverb = NULL; + } + + // destroy engine object, and invalidate all associated interfaces + if (engineObject != NULL) { + (*engineObject)->Destroy(engineObject); + engineObject = NULL; + engineEngine = NULL; + } +} diff --git a/android/native-audio-so.h b/android/native-audio-so.h new file mode 100644 index 0000000000..bde11af263 --- /dev/null +++ b/android/native-audio-so.h @@ -0,0 +1,8 @@ +#pragma once + +// Header for dynamic loading + +typedef void (*AndroidAudioCallback)(short *buffer, int num_samples); + +typedef bool (*OpenSLWrap_Init_T)(AndroidAudioCallback cb); +typedef void (*OpenSLWrap_Shutdown_T)(); diff --git a/android/native_audio.cpp b/android/native_audio.cpp new file mode 100644 index 0000000000..2b99a9dc25 --- /dev/null +++ b/android/native_audio.cpp @@ -0,0 +1,34 @@ +#include + +#include "base/logging.h" +#include "android/native_audio.h" +#include "android/native-audio-so.h" + +static void *so; +static OpenSLWrap_Init_T init_func; +static OpenSLWrap_Shutdown_T shutdown_func; + +bool AndroidAudio_Init(AndroidAudioCallback cb) { + ILOG("Loading native audio library..."); + so = dlopen("libnative_audio.so", RTLD_NOW); + if (!so) { + ELOG("Failed to find native audio library"); + return false; + } + init_func = (OpenSLWrap_Init_T)dlsym(so, "OpenSLWrap_Init"); + shutdown_func = (OpenSLWrap_Shutdown_T)dlsym(so, "OpenSLWrap_Shutdown"); + + ILOG("Calling OpenSLWrap_Init_T..."); + bool init_retval = init_func(cb); + ILOG("Returned from OpenSLWrap_Init_T"); + return init_retval; +} + + +void AndroidAudio_Shutdown() { + ILOG("Calling OpenSLWrap_Shutdown_T..."); + shutdown_func(); + ILOG("Returned from OpenSLWrap_Shutdown_T"); + dlclose(so); + so = 0; +} diff --git a/android/native_audio.h b/android/native_audio.h new file mode 100644 index 0000000000..af6ec235f7 --- /dev/null +++ b/android/native_audio.h @@ -0,0 +1,12 @@ +#pragma once + +#include "native-audio-so.h" + +// This is the file you should include from your program. It dynamically loads +// the native_audio.so shared object and sets up the function pointers. + +// Do not call this if you have detected that the android version is below +// 2.2, as it will fail miserably. + +bool AndroidAudio_Init(AndroidAudioCallback cb); +void AndroidAudio_Shutdown(); diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 7a2bc9b6f8..ef68757bb0 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -86,6 +86,7 @@ public class NativeActivity extends Activity { private GLSurfaceView mGLSurfaceView; private NativeAudioPlayer audioPlayer; + boolean useOpenSL = false; public static String runCommand; public static String commandParameter; @@ -121,7 +122,8 @@ public class NativeActivity extends Activity { String externalStorageDir = sdcard.getAbsolutePath(); String dataDir = this.getFilesDir().getAbsolutePath(); String apkFilePath = appInfo.sourceDir; - NativeApp.init(scrWidth, scrHeight, apkFilePath, dataDir, externalStorageDir, installID); + NativeApp.sendMessage("Message from Java", "Hot Coffee"); + NativeApp.init(scrWidth, scrHeight, apkFilePath, dataDir, externalStorageDir, installID, useOpenSL); // Keep the screen bright - very annoying if it goes dark when tilting away Window window = this.getWindow(); @@ -143,7 +145,8 @@ public class NativeActivity extends Activity { // Native OpenSL is available. Let's not use the Java player in the future. // TODO: code for that. } - audioPlayer = new NativeAudioPlayer(); + if (!useOpenSL) + audioPlayer = new NativeAudioPlayer(); } private boolean detectOpenGLES20() { diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/turboviking/libnative/NativeApp.java index 8b5e81b097..b1809c76e2 100644 --- a/android/src/com/turboviking/libnative/NativeApp.java +++ b/android/src/com/turboviking/libnative/NativeApp.java @@ -4,7 +4,7 @@ public class NativeApp { public static native boolean isLandscape(); public static native void init( int xxres, int yyres, String apkPath, - String dataDir, String externalDir, String installID); + String dataDir, String externalDir, String installID, boolean useOpenSL); public static native void shutdown(); public static native void keyDown(int key); @@ -16,4 +16,6 @@ public class NativeApp { // Sensor/input data. These are asynchronous, beware! public static native void touch(float x, float y, int data, int pointerId); public static native void accelerometer(float x, float y, float z); + + public static native void sendMessage(String msg, String arg); } \ No newline at end of file From 063e32e1da035aad89769edca2247735ed766296 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 8 Jul 2012 00:17:59 +0200 Subject: [PATCH 0068/1445] The native audio stuff makes noise now (although just the sawtooth). --- android/app-android.cpp | 15 ++++++++++-- android/native-audio-so.cpp | 23 +++++++++---------- android/native_audio.cpp | 10 ++++---- android/native_audio.h | 4 ++-- .../turboviking/libnative/NativeActivity.java | 22 +++++++++++++++++- .../com/turboviking/libnative/NativeApp.java | 2 +- 6 files changed, 54 insertions(+), 22 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 7968abc568..b3b93eb6db 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -93,7 +93,7 @@ extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv extern "C" void Java_com_turboviking_libnative_NativeApp_init (JNIEnv *env, jclass, jint xxres, jint yyres, jstring apkpath, - jstring dataDir, jstring externalDir, jstring jinstallID, jboolean juseNativeAudio) { + jstring dataDir, jstring externalDir, jstring libraryDir, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; pixel_xres = xxres; pixel_yres = yyres; @@ -123,6 +123,9 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init str = env->GetStringUTFChars(dataDir, &isCopy); std::string user_data_path = std::string(str) + "/"; + str = env->GetStringUTFChars(libraryDir, &isCopy); + std::string library_path = std::string(str) + "/"; + str = env->GetStringUTFChars(jinstallID, &isCopy); std::string installID = std::string(str); @@ -133,13 +136,21 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init NativeGetAppInfo(&app_name, &app_nice_name, &landscape); const char *argv[2] = {app_name.c_str(), 0}; NativeInit(1, argv, user_data_path.c_str(), installID.c_str()); + + if (use_native_audio) { + AndroidAudio_Init(&NativeMix, library_path); + } } extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown (JNIEnv *, jclass) { ILOG("NativeShutdown."); - if (renderer_inited) { + if (use_native_audio) { + AndroidAudio_Shutdown(); + } + if (renderer_inited) { NativeShutdownGraphics(); + renderer_inited = false; } NativeShutdown(); ILOG("VFSShutdown."); diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 4c4eeed270..11c0e58613 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -31,6 +31,8 @@ #include #include +#include "../base/logging.h" + // engine interfaces static SLObjectItf engineObject = NULL; static SLEngineItf engineEngine; @@ -57,6 +59,7 @@ static unsigned nextSize; // synthesize a mono sawtooth wave and place it into a buffer (called automatically on load) __attribute__((constructor)) static void onDlOpen(void) { + ILOG("Buffer callback"); unsigned int i; for (i = 0; i < SAWTOOTH_FRAMES; ++i) { sawtoothBuffer[i] = 32768 - ((i % 100) * 660); @@ -98,9 +101,7 @@ extern "C" bool OpenSLWrap_Init() assert(SL_RESULT_SUCCESS == result); // create output mix, with environmental reverb specified as a non-required interface - const SLInterfaceID ids1[1] = {SL_IID_ENVIRONMENTALREVERB}; - const SLboolean req1[1] = {SL_BOOLEAN_FALSE}; - result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids1, req1); + result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0); assert(SL_RESULT_SUCCESS == result); // realize the output mix @@ -130,10 +131,10 @@ extern "C" bool OpenSLWrap_Init() SLDataSink audioSnk = {&loc_outmix, NULL}; // create audio player - const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; - const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; + const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, - 3, ids, req); + 2, ids, req); assert(SL_RESULT_SUCCESS == result); // realize the player @@ -161,12 +162,10 @@ extern "C" bool OpenSLWrap_Init() result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); assert(SL_RESULT_SUCCESS == result); - if (nextBuffer) { - SLresult result; - result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); - if (SL_RESULT_SUCCESS != result) { - return false; - } + // Enqueue a first buffer. + result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, sawtoothBuffer, sizeof(sawtoothBuffer)); + if (SL_RESULT_SUCCESS != result) { + return false; } return true; } diff --git a/android/native_audio.cpp b/android/native_audio.cpp index 2b99a9dc25..7a1a774113 100644 --- a/android/native_audio.cpp +++ b/android/native_audio.cpp @@ -1,18 +1,21 @@ #include +#include #include "base/logging.h" #include "android/native_audio.h" #include "android/native-audio-so.h" static void *so; + static OpenSLWrap_Init_T init_func; static OpenSLWrap_Shutdown_T shutdown_func; -bool AndroidAudio_Init(AndroidAudioCallback cb) { +bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir) { ILOG("Loading native audio library..."); - so = dlopen("libnative_audio.so", RTLD_NOW); + std::string so_filename = libraryDir + "/libnative_audio.so"; + so = dlopen(so_filename.c_str(), RTLD_LAZY); if (!so) { - ELOG("Failed to find native audio library"); + ELOG("Failed to find native audio library: %i: %s ", errno, dlerror()); return false; } init_func = (OpenSLWrap_Init_T)dlsym(so, "OpenSLWrap_Init"); @@ -24,7 +27,6 @@ bool AndroidAudio_Init(AndroidAudioCallback cb) { return init_retval; } - void AndroidAudio_Shutdown() { ILOG("Calling OpenSLWrap_Shutdown_T..."); shutdown_func(); diff --git a/android/native_audio.h b/android/native_audio.h index af6ec235f7..e9a230addf 100644 --- a/android/native_audio.h +++ b/android/native_audio.h @@ -1,12 +1,12 @@ #pragma once #include "native-audio-so.h" - +#include // This is the file you should include from your program. It dynamically loads // the native_audio.so shared object and sets up the function pointers. // Do not call this if you have detected that the android version is below // 2.2, as it will fail miserably. -bool AndroidAudio_Init(AndroidAudioCallback cb); +bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir); void AndroidAudio_Shutdown(); diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index ef68757bb0..2f1b906ec9 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; +import java.lang.reflect.Field; import java.util.UUID; import javax.microedition.khronos.egl.EGLConfig; @@ -93,6 +94,24 @@ public class NativeActivity extends Activity { public static String installID; + String getApplicationLibraryDir(ApplicationInfo application) { + String libdir = null; + try { + // Starting from Android 2.3, nativeLibraryDir is available: + Field field = ApplicationInfo.class.getField("nativeLibraryDir"); + libdir = (String) field.get(application); + } catch (SecurityException e1) { + } catch (NoSuchFieldException e1) { + } catch (IllegalArgumentException e) { + } catch (IllegalAccessException e) { + } + if (libdir == null) { + // Fallback for Android < 2.3: + libdir = application.dataDir + "/lib"; + } + return libdir; + } + @Override public void onCreate(Bundle savedInstanceState) { if (NativeApp.isLandscape()) { @@ -113,6 +132,7 @@ public class NativeActivity extends Activity { e.printStackTrace(); throw new RuntimeException("Unable to locate assets, aborting..."); } + String libraryDir = getApplicationLibraryDir(appInfo); File sdcard = Environment.getExternalStorageDirectory(); Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); int scrPixelFormat = display.getPixelFormat(); @@ -123,7 +143,7 @@ public class NativeActivity extends Activity { String dataDir = this.getFilesDir().getAbsolutePath(); String apkFilePath = appInfo.sourceDir; NativeApp.sendMessage("Message from Java", "Hot Coffee"); - NativeApp.init(scrWidth, scrHeight, apkFilePath, dataDir, externalStorageDir, installID, useOpenSL); + NativeApp.init(scrWidth, scrHeight, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); // Keep the screen bright - very annoying if it goes dark when tilting away Window window = this.getWindow(); diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/turboviking/libnative/NativeApp.java index b1809c76e2..5af6937e6f 100644 --- a/android/src/com/turboviking/libnative/NativeApp.java +++ b/android/src/com/turboviking/libnative/NativeApp.java @@ -4,7 +4,7 @@ public class NativeApp { public static native boolean isLandscape(); public static native void init( int xxres, int yyres, String apkPath, - String dataDir, String externalDir, String installID, boolean useOpenSL); + String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); public static native void shutdown(); public static native void keyDown(int key); From 851df8c51975d271a9e5a0b43b75e6bc34361b27 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 8 Jul 2012 13:23:30 +0200 Subject: [PATCH 0069/1445] Add pause/resume without unloading/reloading the native_audio.so wrapper library --- android/native-audio-so.cpp | 3 +-- android/native_audio.cpp | 34 +++++++++++++++++++++++++++------- android/native_audio.h | 3 +++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 11c0e58613..56c24f536d 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -60,8 +60,7 @@ static unsigned nextSize; __attribute__((constructor)) static void onDlOpen(void) { ILOG("Buffer callback"); - unsigned int i; - for (i = 0; i < SAWTOOTH_FRAMES; ++i) { + for (int i = 0; i < SAWTOOTH_FRAMES; ++i) { sawtoothBuffer[i] = 32768 - ((i % 100) * 660); } } diff --git a/android/native_audio.cpp b/android/native_audio.cpp index 7a1a774113..f6c32fed55 100644 --- a/android/native_audio.cpp +++ b/android/native_audio.cpp @@ -6,11 +6,14 @@ #include "android/native-audio-so.h" static void *so; - +static AndroidAudioCallback s_cb; static OpenSLWrap_Init_T init_func; static OpenSLWrap_Shutdown_T shutdown_func; +static bool playing; bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir) { + s_cb = cb; + playing = false; ILOG("Loading native audio library..."); std::string so_filename = libraryDir + "/libnative_audio.so"; so = dlopen(so_filename.c_str(), RTLD_LAZY); @@ -20,17 +23,34 @@ bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir) { } init_func = (OpenSLWrap_Init_T)dlsym(so, "OpenSLWrap_Init"); shutdown_func = (OpenSLWrap_Shutdown_T)dlsym(so, "OpenSLWrap_Shutdown"); + return AndroidAudio_Resume(); +} - ILOG("Calling OpenSLWrap_Init_T..."); - bool init_retval = init_func(cb); - ILOG("Returned from OpenSLWrap_Init_T"); - return init_retval; +bool AndroidAudio_Resume() { + if (!playing) { + ILOG("Calling OpenSLWrap_Init_T..."); + bool init_retval = init_func(s_cb); + ILOG("Returned from OpenSLWrap_Init_T"); + playing = true; + return init_retval; + } + return false; +} + +bool AndroidAudio_Pause() { + if (playing) { + ILOG("Calling OpenSLWrap_Shutdown_T..."); + shutdown_func(); + playing = false; + return true; + } + return false; } void AndroidAudio_Shutdown() { - ILOG("Calling OpenSLWrap_Shutdown_T..."); - shutdown_func(); + AndroidAudio_Pause(); ILOG("Returned from OpenSLWrap_Shutdown_T"); dlclose(so); so = 0; + ILOG("OpenSLWrap completely unloaded."); } diff --git a/android/native_audio.h b/android/native_audio.h index e9a230addf..8e6679f772 100644 --- a/android/native_audio.h +++ b/android/native_audio.h @@ -2,6 +2,7 @@ #include "native-audio-so.h" #include + // This is the file you should include from your program. It dynamically loads // the native_audio.so shared object and sets up the function pointers. @@ -9,4 +10,6 @@ // 2.2, as it will fail miserably. bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir); +bool AndroidAudio_Pause(); +bool AndroidAudio_Resume(); void AndroidAudio_Shutdown(); From 7d5a9c8566251c83b05b2e0d91b4813d983bc5bb Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 8 Jul 2012 13:37:49 +0200 Subject: [PATCH 0070/1445] Some work on resume/pause --- android/app-android.cpp | 14 ++++++++++++++ android/native_audio.cpp | 6 ++++-- .../com/turboviking/libnative/NativeActivity.java | 2 ++ .../src/com/turboviking/libnative/NativeApp.java | 5 +++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index b3b93eb6db..dfe76f7123 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -142,6 +142,20 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init } } +extern "C" void Java_com_turboviking_libnative_NativeApp_resume(JNIEnv *, jclass) { + ILOG("NativeResume"); + if (use_native_audio) { + AndroidAudio_Resume(); + } +} + +extern "C" void Java_com_turboviking_libnative_NativeApp_pause(JNIEnv *, jclass) { + ILOG("NativePause"); + if (use_native_audio) { + AndroidAudio_Pause(); + } +} + extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown (JNIEnv *, jclass) { ILOG("NativeShutdown."); diff --git a/android/native_audio.cpp b/android/native_audio.cpp index f6c32fed55..871a2ca67a 100644 --- a/android/native_audio.cpp +++ b/android/native_audio.cpp @@ -23,7 +23,7 @@ bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir) { } init_func = (OpenSLWrap_Init_T)dlsym(so, "OpenSLWrap_Init"); shutdown_func = (OpenSLWrap_Shutdown_T)dlsym(so, "OpenSLWrap_Shutdown"); - return AndroidAudio_Resume(); + return true; } bool AndroidAudio_Resume() { @@ -48,7 +48,9 @@ bool AndroidAudio_Pause() { } void AndroidAudio_Shutdown() { - AndroidAudio_Pause(); + if (playing) { + ELOG("Should not shut down when playing! Something is wrong!"); + } ILOG("Returned from OpenSLWrap_Shutdown_T"); dlclose(so); so = 0; diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 2f1b906ec9..7d42fb84be 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -183,6 +183,7 @@ public class NativeActivity extends Activity { if (audioPlayer != null) { audioPlayer.stop(); } + NativeApp.pause(); mGLSurfaceView.onPause(); } @@ -194,6 +195,7 @@ public class NativeActivity extends Activity { if (audioPlayer != null) { audioPlayer.play(); } + NativeApp.resume(); } @Override diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/turboviking/libnative/NativeApp.java index 5af6937e6f..bb75a0603e 100644 --- a/android/src/com/turboviking/libnative/NativeApp.java +++ b/android/src/com/turboviking/libnative/NativeApp.java @@ -5,6 +5,11 @@ public class NativeApp { public static native void init( int xxres, int yyres, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); + + // These have Android semantics: Resume is always called on bootup, after init + public static native void pause(); + public static native void resume(); + public static native void shutdown(); public static native void keyDown(int key); From fad6a869d97f0260adaf03e1d8c1b09e0d9e5c22 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 8 Jul 2012 20:38:52 +0200 Subject: [PATCH 0071/1445] OpenSL audio streaming is now working. --- android/native-audio-so.cpp | 268 +++++++----------- .../turboviking/libnative/NativeActivity.java | 11 +- 2 files changed, 116 insertions(+), 163 deletions(-) diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 56c24f536d..d6bdb0772c 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -1,45 +1,26 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* This is a JNI example where we use native methods to play sounds - * using OpenSL ES. See the corresponding Java source file located at: - * - * src/com/example/nativeaudio/NativeAudio/NativeAudio.java - */ +// Minimal audio streaming using OpenSL. +// +// Loosely based on the Android NDK sample code. +// Hardcoded to 44.1kHz stereo 16-bit audio, because as far as I'm concerned, +// that's the only format that makes any sense. #include #include -// for __android_log_print(ANDROID_LOG_INFO, "YourApp", "formatted message"); -// #include - // for native audio #include #include #include "../base/logging.h" +#include "native-audio-so.h" + +// This is kinda ugly, but for simplicity I've left these as globals just like in the sample, +// as there's not really any use case for this where we have multiple audio devices yet. // engine interfaces -static SLObjectItf engineObject = NULL; +static SLObjectItf engineObject; static SLEngineItf engineEngine; - -// output mix interfaces -static SLObjectItf outputMixObject = NULL; -static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL; +static SLObjectItf outputMixObject; // buffer queue player interfaces static SLObjectItf bqPlayerObject = NULL; @@ -48,151 +29,122 @@ static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; static SLMuteSoloItf bqPlayerMuteSolo; static SLVolumeItf bqPlayerVolume; -// synthesized sawtooth clip -#define SAWTOOTH_FRAMES 8000 -static short sawtoothBuffer[SAWTOOTH_FRAMES]; +#define BUFFER_SIZE 512 +#define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2) -// pointer and size of the next player buffer to enqueue, and number of remaining buffers -static short *nextBuffer; -static unsigned nextSize; +// Double buffering. +static short buffer[2][BUFFER_SIZE]; +static int curBuffer = 0; -// synthesize a mono sawtooth wave and place it into a buffer (called automatically on load) -__attribute__((constructor)) static void onDlOpen(void) -{ - ILOG("Buffer callback"); - for (int i = 0; i < SAWTOOTH_FRAMES; ++i) { - sawtoothBuffer[i] = 32768 - ((i % 100) * 660); - } -} +static AndroidAudioCallback audioCallback; -// this callback handler is called every time a buffer finishes playing -void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) -{ - assert(bq == bqPlayerBufferQueue); - assert(NULL == context); +// This callback handler is called every time a buffer finishes playing. +// The documentation available is very unclear about how to best manage buffers. +// I've chosen to this approach: Instantly enqueue a buffer that was rendered to the last time, +// and then render the next. Hopefully it's okay to spend time in this callback after having enqueued. +static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { + assert(bq == bqPlayerBufferQueue); + assert(NULL == context); + short *nextBuffer = buffer[curBuffer]; + int nextSize = sizeof(buffer[0]); - nextBuffer = sawtoothBuffer; - nextSize = sizeof(sawtoothBuffer); - SLresult result; - // enqueue another buffer - result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); - // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, - // which for this code example would indicate a programming error - assert(SL_RESULT_SUCCESS == result); + SLresult result; + result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); + + // Comment from sample code: + // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, + // which for this code example would indicate a programming error + assert(SL_RESULT_SUCCESS == result); + + curBuffer ^= 1; // Switch buffer + // Render to the fresh buffer + audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); } // create the engine and output mix objects -extern "C" bool OpenSLWrap_Init() -{ - SLresult result; +extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb) { + audioCallback = cb; - // create engine - result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); - assert(SL_RESULT_SUCCESS == result); + SLresult result; + // create engine + result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); + assert(SL_RESULT_SUCCESS == result); + result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); + assert(SL_RESULT_SUCCESS == result); + result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0); + assert(SL_RESULT_SUCCESS == result); + result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); - // realize the engine - result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, + 2, + SL_SAMPLINGRATE_44_1, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, + SL_BYTEORDER_LITTLEENDIAN + }; - // get the engine interface, which is needed in order to create other objects - result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); - assert(SL_RESULT_SUCCESS == result); + SLDataSource audioSrc = {&loc_bufq, &format_pcm}; - // create output mix, with environmental reverb specified as a non-required interface - result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0); - assert(SL_RESULT_SUCCESS == result); + // configure audio sink + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; + SLDataSink audioSnk = {&loc_outmix, NULL}; - // realize the output mix - result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + // create audio player + const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; + const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); + assert(SL_RESULT_SUCCESS == result); - // create buffer queue audio player - // ================================ + result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, + &bqPlayerBufferQueue); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); + assert(SL_RESULT_SUCCESS == result); - // configure audio source - SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; - - // TODO: This is all wrong. - SLDataFormat_PCM format_pcm = { - SL_DATAFORMAT_PCM, - 1, - SL_SAMPLINGRATE_8, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_SPEAKER_FRONT_CENTER, - SL_BYTEORDER_LITTLEENDIAN}; + // Render and enqueue a first buffer. (or should we just play the buffer empty?) + curBuffer = 0; + audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); - SLDataSource audioSrc = {&loc_bufq, &format_pcm}; - - // configure audio sink - SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; - SLDataSink audioSnk = {&loc_outmix, NULL}; - - // create audio player - const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; - const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; - result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, - 2, ids, req); - assert(SL_RESULT_SUCCESS == result); - - // realize the player - result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); - - // get the play interface - result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); - assert(SL_RESULT_SUCCESS == result); - - // get the buffer queue interface - result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, - &bqPlayerBufferQueue); - assert(SL_RESULT_SUCCESS == result); - - // register callback on the buffer queue - result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); - assert(SL_RESULT_SUCCESS == result); - - // get the volume interface - result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); - assert(SL_RESULT_SUCCESS == result); - - // set the player's state to playing - result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); - assert(SL_RESULT_SUCCESS == result); - - // Enqueue a first buffer. - result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, sawtoothBuffer, sizeof(sawtoothBuffer)); - if (SL_RESULT_SUCCESS != result) { - return false; - } - return true; + result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[curBuffer])); + if (SL_RESULT_SUCCESS != result) { + return false; + } + curBuffer ^= 1; + return true; } // shut down the native audio system -extern "C" void OpenSLWrap_Shutdown() -{ - // destroy buffer queue audio player object, and invalidate all associated interfaces - if (bqPlayerObject != NULL) { - (*bqPlayerObject)->Destroy(bqPlayerObject); - bqPlayerObject = NULL; - bqPlayerPlay = NULL; - bqPlayerBufferQueue = NULL; - bqPlayerMuteSolo = NULL; - bqPlayerVolume = NULL; - } - - // destroy output mix object, and invalidate all associated interfaces - if (outputMixObject != NULL) { - (*outputMixObject)->Destroy(outputMixObject); - outputMixObject = NULL; - outputMixEnvironmentalReverb = NULL; - } - - // destroy engine object, and invalidate all associated interfaces - if (engineObject != NULL) { - (*engineObject)->Destroy(engineObject); - engineObject = NULL; - engineEngine = NULL; - } +extern "C" void OpenSLWrap_Shutdown() { + if (bqPlayerObject != NULL) { + (*bqPlayerObject)->Destroy(bqPlayerObject); + bqPlayerObject = NULL; + bqPlayerPlay = NULL; + bqPlayerBufferQueue = NULL; + bqPlayerMuteSolo = NULL; + bqPlayerVolume = NULL; + } + if (outputMixObject != NULL) { + (*outputMixObject)->Destroy(outputMixObject); + outputMixObject = NULL; + } + if (engineObject != NULL) { + (*engineObject)->Destroy(engineObject); + engineObject = NULL; + engineEngine = NULL; + } } diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 7d42fb84be..3e961769c8 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -114,7 +114,12 @@ public class NativeActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { - if (NativeApp.isLandscape()) { + if (Build.VERSION.SDK_INT >= 9) { + // Native OpenSL is available. Let's use it! + useOpenSL = true; + } + + if (NativeApp.isLandscape()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); @@ -161,10 +166,6 @@ public class NativeActivity extends Activity { mGLSurfaceView = new NativeGLView(this); mGLSurfaceView.setRenderer(new NativeRenderer(this)); setContentView(mGLSurfaceView); - if (Build.VERSION.SDK_INT >= 9) { - // Native OpenSL is available. Let's not use the Java player in the future. - // TODO: code for that. - } if (!useOpenSL) audioPlayer = new NativeAudioPlayer(); } From b041bd474b30dfdd3e6aa6bfa960b6f8a3654aff Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 9 Jul 2012 00:43:04 +0200 Subject: [PATCH 0072/1445] Take DPI into account. Fix some memory leaks in JNI code. --- android/app-android.cpp | 67 ++++++++++--------- .../turboviking/libnative/NativeActivity.java | 7 +- .../com/turboviking/libnative/NativeApp.java | 2 +- base/PCMain.cpp | 3 +- base/display.cpp | 2 + base/display.h | 2 + native.vcxproj | 10 +++ native.vcxproj.filters | 21 +++++- 8 files changed, 75 insertions(+), 39 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index dfe76f7123..8d9792dc90 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -52,29 +52,24 @@ void Vibrate(int length_ms) { frameCommandParam = "100"; } -void LaunchBrowser(const char *url) -{ +void LaunchBrowser(const char *url) { frameCommand = "launchBrowser"; frameCommandParam = url; } -void LaunchMarket(const char *url) -{ +void LaunchMarket(const char *url) { frameCommand = "launchMarket"; frameCommandParam = url; } -void LaunchEmail(const char *email_address) -{ +void LaunchEmail(const char *email_address) { frameCommand = "launchEmail"; frameCommandParam = email_address; } - // Remember that all of these need initialization on init! The process // may be reused when restarting the game. Globals are DANGEROUS. -// Used for touch. (TODO) float xscale = 1; float yscale = 1; @@ -84,6 +79,14 @@ static bool renderer_inited = false; static bool first_lost = true; static bool use_native_audio = false; +std::string GetJavaString(JNIEnv *env, jstring jstr) +{ + const char *str = env->GetStringUTFChars(jstr, 0); + std::string cpp_string = std::string(str); + env->ReleaseStringUTFChars(jstr, str); + return cpp_string; +} + extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) { std::string app_name, app_nice_name; bool landscape; @@ -92,13 +95,19 @@ extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv } extern "C" void Java_com_turboviking_libnative_NativeApp_init - (JNIEnv *env, jclass, jint xxres, jint yyres, jstring apkpath, - jstring dataDir, jstring externalDir, jstring libraryDir, jstring jinstallID, jboolean juseNativeAudio) { + (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring japkpath, + jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; + pixel_xres = xxres; pixel_yres = yyres; - g_xres = xxres; - g_yres = yyres; + + g_dpi = dpi; + + // We default to 160 dpi and all our UI code is written to assume it. (DENSITY_MEDIUM). + g_xres = xxres * 160 / dpi; + g_yres = yyres * 160 / dpi; + use_native_audio = juseNativeAudio; if (g_xres < g_yres) { @@ -112,22 +121,16 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init renderer_inited = false; first_lost = true; - jboolean isCopy; - const char *str = env->GetStringUTFChars(apkpath, &isCopy); - ILOG("APK path: %s", str); - VFSRegister("", new ZipAssetReader(str, "assets/")); + std::string apkPath = GetJavaString(env, japkpath); + ILOG("APK path: %s", apkPath.c_str()); + VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); - str = env->GetStringUTFChars(externalDir, &isCopy); - ILOG("External storage path: %s", str); + std::string externalDir = GetJavaString(env, jexternalDir); + std::string user_data_path = GetJavaString(env, jdataDir); + "/"; + std::string library_path = GetJavaString(env, jlibraryDir) + "/"; + std::string installID = GetJavaString(env, jinstallID); - str = env->GetStringUTFChars(dataDir, &isCopy); - std::string user_data_path = std::string(str) + "/"; - - str = env->GetStringUTFChars(libraryDir, &isCopy); - std::string library_path = std::string(str) + "/"; - - str = env->GetStringUTFChars(jinstallID, &isCopy); - std::string installID = std::string(str); + ILOG("External storage path: %s", externalDir.c_str()); std::string app_name; std::string app_nice_name; @@ -213,9 +216,9 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender if (!frameCommand.empty()) { ILOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str()); + jstring cmd = env->NewStringUTF(frameCommand.c_str()); jstring param = env->NewStringUTF(frameCommandParam.c_str()); - env->CallVoidMethod(obj, postCommand, cmd, param); frameCommand = ""; @@ -239,8 +242,8 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* en extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch (JNIEnv *, jclass, float x, float y, int code, int pointerId) { lock_guard guard(input_state.lock); - if (pointerId >= MAX_POINTERS) - { + + if (pointerId >= MAX_POINTERS) { ELOG("Too many pointers: %i", pointerId); return; // We ignore 8+ pointers entirely. } @@ -248,11 +251,9 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch input_state.mouse_x[pointerId] = (int)(x * xscale); input_state.mouse_y[pointerId] = (int)(y * yscale); if (code == 1) { - //ILOG("Down: %i %f %f", pointerId, x, y); input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; input_state.mouse_down[pointerId] = true; } else if (code == 2) { - //ILOG("Up: %i %f %f", pointerId, x, y); input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; input_state.mouse_down[pointerId] = false; } @@ -307,8 +308,8 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_accelerometer extern "C" void Java_com_turboviking_libnative_NativeApp_sendMessage (JNIEnv *env, jclass, jstring message, jstring param) { jboolean isCopy; - std::string msg(env->GetStringUTFChars(message, &isCopy)); - std::string prm(env->GetStringUTFChars(param, &isCopy)); + std::string msg = GetJavaString(env, message); + std::string prm = GetJavaString(env, param); ILOG("Message received: %s %s", msg.c_str(), prm.c_str()); } diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 3e961769c8..065ed5544c 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -31,6 +31,7 @@ import android.opengl.GLSurfaceView; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.KeyEvent; @@ -148,7 +149,11 @@ public class NativeActivity extends Activity { String dataDir = this.getFilesDir().getAbsolutePath(); String apkFilePath = appInfo.sourceDir; NativeApp.sendMessage("Message from Java", "Hot Coffee"); - NativeApp.init(scrWidth, scrHeight, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); + DisplayMetrics metrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metrics); + int dpi = metrics.densityDpi; + // INIT! + NativeApp.init(scrWidth, scrHeight, dpi, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); // Keep the screen bright - very annoying if it goes dark when tilting away Window window = this.getWindow(); diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/turboviking/libnative/NativeApp.java index bb75a0603e..e7e0c32444 100644 --- a/android/src/com/turboviking/libnative/NativeApp.java +++ b/android/src/com/turboviking/libnative/NativeApp.java @@ -3,7 +3,7 @@ package com.turboviking.libnative; public class NativeApp { public static native boolean isLandscape(); public static native void init( - int xxres, int yyres, String apkPath, + int xxres, int yyres, int dpi, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); // These have Android semantics: Resume is always called on bootup, after init diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 84240f8f11..72d126fabc 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -128,7 +128,7 @@ int main(int argc, char *argv[]) { bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); - float zoom = 0.7f; + float zoom = 1.0f; const char *zoomenv = getenv("ZOOM"); if (zoomenv) { zoom = atof(zoomenv); @@ -137,6 +137,7 @@ int main(int argc, char *argv[]) { pixel_xres = 800 * zoom; pixel_yres = 480 * zoom; } else { + // PC development hack pixel_xres = 1580 * zoom; pixel_yres = 1000 * zoom; } diff --git a/base/display.cpp b/base/display.cpp index 5896c392f5..1ba39cb992 100644 --- a/base/display.cpp +++ b/base/display.cpp @@ -4,3 +4,5 @@ int g_xres; int g_yres; int pixel_xres; int pixel_yres; + +int g_dpi; \ No newline at end of file diff --git a/base/display.h b/base/display.h index 18e4920c71..ca561e7c63 100644 --- a/base/display.h +++ b/base/display.h @@ -7,3 +7,5 @@ extern int g_xres; extern int g_yres; extern int pixel_xres; extern int pixel_yres; + +extern int g_dpi; \ No newline at end of file diff --git a/native.vcxproj b/native.vcxproj index fbf66942d2..0402ee4795 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -92,6 +92,8 @@ + + @@ -154,6 +156,14 @@ true true + + true + true + + + true + true + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index a27c2d5378..61af2a0391 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -175,6 +175,12 @@ net + + android + + + android + @@ -294,9 +300,6 @@ file - - base - util @@ -318,6 +321,15 @@ net + + android + + + android + + + android + @@ -371,5 +383,8 @@ {6a548b3d-3a4c-4114-aa2f-0b42bf7bf2ce} + + {b7bc9a09-29c1-447b-9255-fe0709d10689} + \ No newline at end of file From 4a6bc60ea8f79b9ead85bd7631ee2ef02676f90f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 9 Jul 2012 01:11:18 +0200 Subject: [PATCH 0073/1445] warnin fixin --- android/app-android.cpp | 2 +- base/stringutil.cpp | 4 ++-- gfx_es2/glsl_program.cpp | 2 +- midi/midi_input.cpp | 1 + net/http_client.cpp | 5 +++-- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 8d9792dc90..58a7468311 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -126,7 +126,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); std::string externalDir = GetJavaString(env, jexternalDir); - std::string user_data_path = GetJavaString(env, jdataDir); + "/"; + std::string user_data_path = GetJavaString(env, jdataDir) + "/"; std::string library_path = GetJavaString(env, jlibraryDir) + "/"; std::string installID = GetJavaString(env, jinstallID); diff --git a/base/stringutil.cpp b/base/stringutil.cpp index 229a8a7e89..657f3000a5 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -5,11 +5,11 @@ unsigned int parseHex(const char *_szValue) { - int Count, Value = 0; + int Value = 0; size_t Finish = strlen(_szValue); if (Finish > 8 ) { Finish = 8; } - for (Count = 0; Count < Finish; Count++) { + for (size_t Count = 0; Count < Finish; Count++) { Value = (Value << 4); switch( _szValue[Count] ) { case '0': break; diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 74b6f108d1..ea94ca8acc 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -65,7 +65,7 @@ bool glsl_up_to_date(GLSLProgram *program) { stat(program->vshader_filename, &vs); stat(program->fshader_filename, &fs); if (vs.st_mtime != program->vshader_mtime || - fs.st_mtime != program->fshader_mtime) { + fs.st_mtime != program->fshader_mtime) { return false; } else { return true; diff --git a/midi/midi_input.cpp b/midi/midi_input.cpp index 143ac12013..d42ccff13d 100644 --- a/midi/midi_input.cpp +++ b/midi/midi_input.cpp @@ -78,6 +78,7 @@ std::vector MidiInGetDevices() { MidiDevice MidiInStart(int deviceID, MidiListener *listener) { FLOG("Invalid MIDI device"); + return 0; } void MidiInStop(MidiDevice device) { diff --git a/net/http_client.cpp b/net/http_client.cpp index 8e982d5824..90217e7be7 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -1,6 +1,7 @@ #include "net/http_client.h" // for inet_pton +#undef _WIN32_WINNT #define _WIN32_WINNT 0x600 #ifndef _WIN32 @@ -34,7 +35,7 @@ Connection::~Connection() { } bool Connection::Resolve(const char *host, int port) { - CHECK_EQ(-1, sock_); + CHECK_EQ(-1, (intptr_t)sock_); host_ = host; port_ = port; @@ -68,7 +69,7 @@ void Connection::Connect() { } void Connection::Disconnect() { - if (sock_ != -1) { + if ((intptr_t)sock_ != -1) { closesocket(sock_); sock_ = -1; } else { From 1254fe414c49a3d5ddd67c715d12e22b491a7593 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 13 Jul 2012 00:13:02 +0200 Subject: [PATCH 0074/1445] Change target to 4.0 (but support 2.2, of course). Fix resulting lint issues. --- android/AndroidManifest.xml | 2 +- android/app-android.cpp | 5 ++ android/project.properties | 2 +- .../turboviking/libnative/NativeActivity.java | 47 +++++++++++-------- .../com/turboviking/libnative/NativeApp.java | 1 + .../libnative/NativeAudioPlayer.java | 4 +- base/NativeApp.h | 4 ++ 7 files changed, 41 insertions(+), 24 deletions(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index cd288649c3..b28f3165ea 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="1" android:versionName="1.0" > - + diff --git a/android/app-android.cpp b/android/app-android.cpp index 58a7468311..b986cc4e53 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -94,6 +94,11 @@ extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv return landscape; } +// For the Back button to work right. +extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isAtTopLevel(JNIEnv *env, jclass) { + return NativeIsAtTopLevel(); +} + extern "C" void Java_com_turboviking_libnative_NativeApp_init (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { diff --git a/android/project.properties b/android/project.properties index 8061f9c3fe..fec2d6168d 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt # Project target. -target=android-8 +target=android-15 android.library=true diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 065ed5544c..6b88954992 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -6,9 +6,7 @@ import java.io.RandomAccessFile; import java.lang.reflect.Field; import java.util.UUID; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - +import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; @@ -19,13 +17,7 @@ import android.content.pm.ConfigurationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; -import android.media.AudioFormat; import android.media.AudioManager; -import android.media.AudioTrack; import android.net.Uri; import android.opengl.GLSurfaceView; import android.os.Build; @@ -35,14 +27,11 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.KeyEvent; -import android.view.MotionEvent; +import android.view.View; import android.view.Window; import android.view.WindowManager; -import android.view.inputmethod.InputMethodManager; import android.widget.Toast; - - class Installation { private static String sID = null; private static final String INSTALLATION = "INSTALLATION"; @@ -113,6 +102,7 @@ public class NativeActivity extends Activity { return libdir; } + @Override public void onCreate(Bundle savedInstanceState) { if (Build.VERSION.SDK_INT >= 9) { @@ -142,8 +132,10 @@ public class NativeActivity extends Activity { File sdcard = Environment.getExternalStorageDirectory(); Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); int scrPixelFormat = display.getPixelFormat(); + @SuppressWarnings("deprecation") int scrWidth = display.getWidth(); - int scrHeight = display.getHeight(); + @SuppressWarnings("deprecation") + int scrHeight = display.getHeight(); float scrRefreshRate = (float)display.getRefreshRate(); String externalStorageDir = sdcard.getAbsolutePath(); String dataDir = this.getFilesDir().getAbsolutePath(); @@ -152,6 +144,7 @@ public class NativeActivity extends Activity { DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); int dpi = metrics.densityDpi; + // INIT! NativeApp.init(scrWidth, scrHeight, dpi, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); @@ -162,8 +155,9 @@ public class NativeActivity extends Activity { Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat); // Initialize Graphics + if (!detectOpenGLES20()) { - throw new RuntimeException("Application requires OpenGL ES 2.0."); + Log.i(TAG, "OpenGL ES 2.0 NOT detected."); } else { Log.i(TAG, "OpenGL ES 2.0 detected."); } @@ -173,7 +167,15 @@ public class NativeActivity extends Activity { setContentView(mGLSurfaceView); if (!useOpenSL) audioPlayer = new NativeAudioPlayer(); + lightsOut(); } + + @SuppressLint("NewApi") + public void lightsOut() { + if (Build.VERSION.SDK_INT >= 11) { + mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); + } + } private boolean detectOpenGLES20() { ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); @@ -250,19 +252,24 @@ public class NativeActivity extends Activity { // Eat these keys, to avoid accidental exits / other screwups. // Maybe there's even more we need to eat on tablets? if (keyCode == KeyEvent.KEYCODE_BACK) { - NativeApp.keyUp(1); - return true; + if (NativeApp.isAtTopLevel()) { + return false; + } else { + NativeApp.keyUp(1); + return true; + } } else if (keyCode == KeyEvent.KEYCODE_MENU) { - // Menu should be ignored from android 3 forwards + // Menu should be ignored from SDK 11 forwards. We send it to the app. NativeApp.keyUp(2); return true; } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { - // Search probably should also be ignored. + // Search probably should also be ignored. We send it to the app. NativeApp.keyUp(3); return true; } + // All other keys retain their default behaviour. return false; } @@ -292,7 +299,7 @@ public class NativeActivity extends Activity { // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app // http://developer.android.com/guide/publishing/publishing.html#marketintent } else if (command.equals("toast")) { - Toast toast = Toast.makeText(this, params, 2000); + Toast toast = Toast.makeText(this, params, Toast.LENGTH_SHORT); toast.show(); } else if (command.equals("showkeyboard")) { //InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/turboviking/libnative/NativeApp.java index e7e0c32444..420739f406 100644 --- a/android/src/com/turboviking/libnative/NativeApp.java +++ b/android/src/com/turboviking/libnative/NativeApp.java @@ -2,6 +2,7 @@ package com.turboviking.libnative; public class NativeApp { public static native boolean isLandscape(); + public static native boolean isAtTopLevel(); public static native void init( int xxres, int yyres, int dpi, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); diff --git a/android/src/com/turboviking/libnative/NativeAudioPlayer.java b/android/src/com/turboviking/libnative/NativeAudioPlayer.java index ede5ebc375..c15ef0a91b 100644 --- a/android/src/com/turboviking/libnative/NativeAudioPlayer.java +++ b/android/src/com/turboviking/libnative/NativeAudioPlayer.java @@ -63,7 +63,7 @@ public class NativeAudioPlayer { // Get the smallest possible buffer size (which is annoyingly huge). int buffer_size_bytes = AudioTrack.getMinBufferSize( 44100, - AudioFormat.CHANNEL_CONFIGURATION_STEREO, + AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT); // Round buffer_size_bytes up to an even multiple of 128 for convenience. @@ -71,7 +71,7 @@ public class NativeAudioPlayer { AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, - AudioFormat.CHANNEL_CONFIGURATION_STEREO, + AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, buffer_size_bytes, AudioTrack.MODE_STREAM); diff --git a/base/NativeApp.h b/base/NativeApp.h index b66667302e..efb24a460b 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -15,6 +15,10 @@ struct InputState; // This might get called multiple times in some implementations, you must be able to handle that. void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape); +// For the back button to work right, this should return true on your main or title screen. +// Otherwise, just return false. +bool NativeIsAtTopLevel(); + // The very first function to be called after NativeGetAppInfo. Even NativeMix is not called // before this, although it may be called at any point in time afterwards (on any thread!) // This functions must NOT call OpenGL. Main thread. From 5a6622eb370bf3d07d6f210ac422b94086685231 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 15 Jul 2012 17:04:27 +0200 Subject: [PATCH 0075/1445] Redo the DPI/Density code. It now makes sense. --- android/app-android.cpp | 67 ++++++++++++++++++++------------------ base/NativeApp.h | 16 ++++++++- base/PCMain.cpp | 72 ++++++++++++++++++++++++----------------- base/display.cpp | 4 +-- base/display.h | 4 +-- gfx_es2/draw_buffer.cpp | 2 +- net/http_client.cpp | 2 +- net/resolve.cpp | 8 ++++- net/resolve.h | 3 +- 9 files changed, 108 insertions(+), 70 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index b986cc4e53..987f7c4b85 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -21,6 +21,7 @@ #include "input/input_state.h" #include "audio/mixer.h" #include "math/math_util.h" +#include "net/resolve.h" #include "android/native_audio.h" #define coord_xres 480 @@ -70,8 +71,8 @@ void LaunchEmail(const char *email_address) { // Remember that all of these need initialization on init! The process // may be reused when restarting the game. Globals are DANGEROUS. -float xscale = 1; -float yscale = 1; +float dp_xscale = 1; +float dp_yscale = 1; InputState input_state; @@ -104,24 +105,6 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; - pixel_xres = xxres; - pixel_yres = yyres; - - g_dpi = dpi; - - // We default to 160 dpi and all our UI code is written to assume it. (DENSITY_MEDIUM). - g_xres = xxres * 160 / dpi; - g_yres = yyres * 160 / dpi; - - use_native_audio = juseNativeAudio; - if (g_xres < g_yres) - { - // Portrait - let's force the imaginary resolution we want - g_xres = pixel_xres; - g_yres = pixel_yres; - } - xscale = (float)g_xres / pixel_xres; - yscale = (float)g_yres / pixel_yres; memset(&input_state, 0, sizeof(input_state)); renderer_inited = false; first_lost = true; @@ -141,10 +124,18 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init std::string app_nice_name; bool landscape; + net::Init(); + + g_dpi = dpi; + pixel_xres = xxres; + pixel_yres = yyres; + NativeGetAppInfo(&app_name, &app_nice_name, &landscape); + const char *argv[2] = {app_name.c_str(), 0}; NativeInit(1, argv, user_data_path.c_str(), installID.c_str()); + use_native_audio = juseNativeAudio; if (use_native_audio) { AndroidAudio_Init(&NativeMix, library_path); } @@ -164,8 +155,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_pause(JNIEnv *, jclass) } } -extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown - (JNIEnv *, jclass) { +extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown(JNIEnv *, jclass) { ILOG("NativeShutdown."); if (use_native_audio) { AndroidAudio_Shutdown(); @@ -177,26 +167,35 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown NativeShutdown(); ILOG("VFSShutdown."); VFSShutdown(); + net::Shutdown(); } static jmethodID postCommand; extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { if (!renderer_inited) { - ILOG("Calling NativeInitGraphics();"); + ILOG("Calling NativeInitGraphics(); dpi = %i", g_dpi); + + // We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S). + // Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo + // can change the dp resolution if it feels like it. + dp_xres = pixel_xres * 240 / g_dpi; + dp_yres = pixel_yres * 240 / g_dpi; + NativeInitGraphics(); + + dp_xscale = (float)dp_xres / pixel_xres; + dp_yscale = (float)dp_yres / pixel_yres; } else { ILOG("Calling NativeDeviceLost();"); } renderer_inited = true; jclass cls = env->GetObjectClass(obj); - postCommand = env->GetMethodID( - cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); + postCommand = env->GetMethodID(cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); ILOG("MethodID: %i", (int)postCommand); } -extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize - (JNIEnv *, jobject clazz, jint w, jint h) { +extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { ILOG("nativeResize (%i, %i), device lost!", w, h); if (first_lost) { first_lost = false; @@ -205,8 +204,7 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize } } -extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender - (JNIEnv *env, jobject obj) { +extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { if (renderer_inited) { UpdateInputState(&input_state); NativeUpdate(input_state); @@ -252,15 +250,20 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch ELOG("Too many pointers: %i", pointerId); return; // We ignore 8+ pointers entirely. } - - input_state.mouse_x[pointerId] = (int)(x * xscale); - input_state.mouse_y[pointerId] = (int)(y * yscale); + float scaledX = (int)(x * dp_xscale); // why the (int) cast? + float scaledY = (int)(y * dp_yscale); + input_state.mouse_x[pointerId] = scaledX; + input_state.mouse_y[pointerId] = scaledY; if (code == 1) { input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; input_state.mouse_down[pointerId] = true; + NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_DOWN); } else if (code == 2) { input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; input_state.mouse_down[pointerId] = false; + NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_UP); + } else { + NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_MOVE); } input_state.mouse_valid = true; } diff --git a/base/NativeApp.h b/base/NativeApp.h index efb24a460b..e6c2dee743 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -13,6 +13,8 @@ struct InputState; // You must implement this. The first function to get called, just write strings to the two pointers. // This might get called multiple times in some implementations, you must be able to handle that. +// The detected DP dimensions of the screen are set as dp_xres and dp_yres and you're free to change +// them if you have a fixed-size app that needs to stretch a little to fit. void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape); // For the back button to work right, this should return true on your main or title screen. @@ -28,13 +30,25 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co void NativeInitGraphics(); // Signals that you need to recreate all buffered OpenGL resources, -// like textures, vbo etc. Main thread. +// like textures, vbo etc. Also, if you have modified dp_xres and dp_yres, you have to +// do it again here. Main thread. void NativeDeviceLost(); // Called ~sixty times a second, delivers the current input state. // Main thread. void NativeUpdate(const InputState &input); +// Delivers touch events "instantly", without waiting for the next frame so that NativeUpdate can deliver. +// Useful for triggering audio events, saving a few ms. +// If you don't care about touch latency, just do a no-op implementation of this. +// time is not yet implemented. finger can be from 0 to 7, inclusive. +enum TouchEvent { + TOUCH_DOWN, + TOUCH_MOVE, + TOUCH_UP, +}; +void NativeTouch(int finger, float x, float y, double time, TouchEvent event); + // Called when it's time to render. If the device can keep up, this // will also be called sixty times per second. Main thread. void NativeRender(); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 72d126fabc..4510d008e2 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -119,35 +119,34 @@ extern void mixaudio(void *userdata, Uint8 *stream, int len) { #undef main #endif int main(int argc, char *argv[]) { - /* // Xoom resolution. Other common tablet resolutions: 1024x600 , 1366x768 - g_xres = 1280; - g_yres = 800; + /* // Xoom/Nexus 7 resolution. Other common tablet resolutions: 1024x600 , 1366x768 + dp_xres = 1280; + dp_yres = 800; + */ std::string app_name; std::string app_name_nice; - bool landscape; - NativeGetAppInfo(&app_name, &app_name_nice, &landscape); float zoom = 1.0f; const char *zoomenv = getenv("ZOOM"); if (zoomenv) { zoom = atof(zoomenv); } - if (landscape) { + + bool landscape; + NativeGetAppInfo(&app_name, &app_name_nice, &landscape); + + if (landscape) { pixel_xres = 800 * zoom; pixel_yres = 480 * zoom; } else { - // PC development hack - pixel_xres = 1580 * zoom; - pixel_yres = 1000 * zoom; + // PC development hack for more space + //pixel_xres = 1580 * zoom; + //pixel_yres = 1000 * zoom; + pixel_xres = 480 * zoom; + pixel_yres = 800 * zoom; } - float density = 1.0f; - g_xres = (float)pixel_xres * density / zoom; - g_yres = (float)pixel_yres * density / zoom; - - printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); - printf("Virtual pixels: %i x %i\n", g_xres, g_yres); net::Init(); @@ -185,27 +184,35 @@ int main(int argc, char *argv[]) { return 1; } - - #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); TCHAR path[MAX_PATH]; SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path); PathAppend(path, (app_name + "\\").c_str()); #else - // Mac - what about linux? Also, ugly hardcoding. + // Mac / Linux const char *path = getenv("HOME"); if (!path) { struct passwd* pwd = getpwuid(getuid()); if (pwd) path = pwd->pw_dir; } - #endif NativeInit(argc, (const char **)argv, path, "BADCOFFEE"); + + float density = 1.0f; + dp_xres = (float)pixel_xres * density / zoom; + dp_yres = (float)pixel_yres * density / zoom; + NativeInitGraphics(); + float dp_xscale = (float)dp_xres / pixel_xres; + float dp_yscale = (float)dp_yres / pixel_yres; + + printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); + printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); + SDL_AudioSpec fmt; fmt.freq = 44100; fmt.format = AUDIO_S16; @@ -225,44 +232,51 @@ int main(int argc, char *argv[]) { InputState input_state; int framecount = 0; bool nextFrameMD = 0; + float t = 0; while (true) { SDL_Event event; input_state.accelerometer_valid = false; input_state.mouse_valid = true; - int done = 0; + int quitRequested = 0; // input_state.mouse_down[1] = nextFrameMD; while (SDL_PollEvent(&event)) { + float mx = event.motion.x * dp_xscale; + float my = event.motion.y * dp_yscale; + if (event.type == SDL_QUIT) { - done = 1; + quitRequested = 1; } else if (event.type == SDL_KEYDOWN) { if (event.key.keysym.sym == SDLK_ESCAPE) { - done = 1; + quitRequested = 1; } } else if (event.type == SDL_MOUSEMOTION) { - input_state.mouse_x[0] = event.motion.x * density / zoom; - input_state.mouse_y[0] = event.motion.y * density / zoom; + input_state.mouse_x[0] = mx; + input_state.mouse_y[0] = my; + NativeTouch(0, mx, my, 0, TOUCH_MOVE); } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { //input_state.mouse_buttons_down = 1; input_state.mouse_down[0] = true; nextFrameMD = true; + NativeTouch(0, mx, my, 0, TOUCH_DOWN); } } else if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { input_state.mouse_down[0] = false; nextFrameMD = false; //input_state.mouse_buttons_up = 1; + NativeTouch(0, mx, my, 0, TOUCH_UP); } } } - if (done) + if (quitRequested) break; input_state.mouse_last[0] = input_state.mouse_down[0]; - uint8 *keys = (uint8 *)SDL_GetKeyState(NULL); + const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); if (keys[SDLK_ESCAPE]) break; SimulateGamepad(keys, &input_state); @@ -270,14 +284,13 @@ int main(int argc, char *argv[]) { NativeUpdate(input_state); NativeRender(); if (framecount % 60 == 0) { - // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. + // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } SDL_GL_SwapBuffers(); // Simple framerate limiting - static float t=0; - while (time_now() < t+1.0f/60.0f) { + while (time_now() < t + 1.0f/60.0f) { sleep_ms(0); time_update(); } @@ -293,5 +306,6 @@ int main(int argc, char *argv[]) { NativeShutdown(); SDL_CloseAudio(); SDL_Quit(); + net::Shutdown(); return 0; } diff --git a/base/display.cpp b/base/display.cpp index 1ba39cb992..0955677943 100644 --- a/base/display.cpp +++ b/base/display.cpp @@ -1,7 +1,7 @@ #include "base/display.h" -int g_xres; -int g_yres; +int dp_xres; +int dp_yres; int pixel_xres; int pixel_yres; diff --git a/base/display.h b/base/display.h index ca561e7c63..dc6344cbab 100644 --- a/base/display.h +++ b/base/display.h @@ -3,8 +3,8 @@ // This is meant to be a framework for handling DPI scaling etc. // For now, it just consists of these two ugly globals. -extern int g_xres; -extern int g_yres; +extern int dp_xres; +extern int dp_yres; extern int pixel_xres; extern int pixel_yres; diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index b4b3694c6f..38ac6f958e 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -359,7 +359,7 @@ void DrawBuffer::EnableBlend(bool enable) { void DrawBuffer::SetClipRect(float x, float y, float w, float h) { // Sigh, OpenGL is upside down. - glScissor(x, g_yres - y, w, h); + glScissor(x, dp_yres - y, w, h); glEnable(GL_SCISSOR_TEST); } diff --git a/net/http_client.cpp b/net/http_client.cpp index 90217e7be7..ba0b1f9c19 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -46,6 +46,7 @@ bool Connection::Resolve(const char *host, int port) { CHECK_GE(tmpres, 0); // << "inet_pton failed"; CHECK_NE(0, tmpres); // << ip << " not a valid IP address"; remote_.sin_port = htons(port); + free((void *)ip); return true; } @@ -53,7 +54,6 @@ void Connection::Connect() { CHECK_GE(port_, 0); sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); CHECK_GE(sock_, 0); - //VLOG(1) << "Connecting to " << host_ << ":" << port_; // poll once per second.. should find a way to do this blocking. int retval = -1; diff --git a/net/resolve.cpp b/net/resolve.cpp index 0dcd6870c8..9d56f38e54 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -16,7 +16,6 @@ namespace net { - void Init() { #ifdef _WIN32 @@ -25,6 +24,13 @@ void Init() #endif } +void Shutdown() +{ +#ifdef _WIN32 + WSACleanup(); +#endif +} + char *DNSResolve(const char *host) { struct hostent *hent; diff --git a/net/resolve.h b/net/resolve.h index 70e8b3e6cc..3f6d3d2f87 100644 --- a/net/resolve.h +++ b/net/resolve.h @@ -3,8 +3,9 @@ namespace net { -// Required on Win32 +// Strictly only required on Win32, but all platforms should call it. void Init(); +void Shutdown(); // use free() to free the returned string. char *DNSResolve(const char *host); From 5819c79463d0e94c6d9e96ff1dd5d6a56cb173af Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 15 Jul 2012 17:38:03 +0200 Subject: [PATCH 0076/1445] Add writeWString for std::string --- base/LAMEString.cpp | 1 + file/chunk_file.cpp | 25 +++++++++++++++++++++++-- file/chunk_file.h | 3 ++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/base/LAMEString.cpp b/base/LAMEString.cpp index 8383b0e141..624ec054ad 100644 --- a/base/LAMEString.cpp +++ b/base/LAMEString.cpp @@ -380,6 +380,7 @@ void String::toUnicode(wchar_t *dest) { for (int i=0; i @@ -36,6 +36,7 @@ public: void writeInt(int i); void writeWString(String str); + void writeWString(const std::string &str); void writeData(const void *data, int count); int getCurrentChunkSize(); From c762d1c0a50a45e6689697c830c584f7e8e69860 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 16 Jul 2012 01:10:03 +0200 Subject: [PATCH 0077/1445] Add a simple screen manager (kind of like activity stack) --- base/PCMain.cpp | 10 +++--- native.vcxproj | 2 ++ native.vcxproj.filters | 6 ++++ ui/CMakeLists.txt | 1 + ui/screen.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++ ui/screen.h | 62 ++++++++++++++++++++++++++++++++ 6 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 ui/screen.cpp create mode 100644 ui/screen.h diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 4510d008e2..7540cf1d22 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -234,13 +234,11 @@ int main(int argc, char *argv[]) { bool nextFrameMD = 0; float t = 0; while (true) { - SDL_Event event; - input_state.accelerometer_valid = false; input_state.mouse_valid = true; int quitRequested = 0; - // input_state.mouse_down[1] = nextFrameMD; + SDL_Event event; while (SDL_PollEvent(&event)) { float mx = event.motion.x * dp_xscale; float my = event.motion.y * dp_yscale; @@ -289,7 +287,7 @@ int main(int argc, char *argv[]) { SDL_GL_SwapBuffers(); - // Simple framerate limiting + // Simple frame rate limiting while (time_now() < t + 1.0f/60.0f) { sleep_ms(0); time_update(); @@ -299,7 +297,8 @@ int main(int argc, char *argv[]) { framecount++; } // Faster exit, thanks to the OS. Remove this if you want to debug shutdown - exit(0); + // The speed difference is only really noticable on Linux. On Windows you do notice it though + // exit(0); NativeShutdownGraphics(); SDL_PauseAudio(1); @@ -307,5 +306,6 @@ int main(int argc, char *argv[]) { SDL_CloseAudio(); SDL_Quit(); net::Shutdown(); + exit(0); return 0; } diff --git a/native.vcxproj b/native.vcxproj index 0402ee4795..7c1069b6fd 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -148,6 +148,7 @@ + @@ -211,6 +212,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 61af2a0391..8bda8682a6 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -181,6 +181,9 @@ android + + ui + @@ -330,6 +333,9 @@ android + + ui + diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 9a98c118d9..4b6f2c5758 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -1,5 +1,6 @@ set(SRCS ui.cpp + screen.cpp ) set(SRCS ${SRCS}) diff --git a/ui/screen.cpp b/ui/screen.cpp new file mode 100644 index 0000000000..581c3eabd9 --- /dev/null +++ b/ui/screen.cpp @@ -0,0 +1,81 @@ +#include "base/logging.h" +#include "input/input_state.h" +#include "ui/screen.h" + +ScreenManager screenManager; + +Screen::Screen() { } +Screen::~Screen() { } + +ScreenManager::ScreenManager() { + currentScreen_=0; + nextScreen_=0; +} + +ScreenManager::~ScreenManager() { + delete currentScreen_; +} + +void ScreenManager::switchScreen(Screen *screen) { + // Note that if a dialog is found, this will be a silent background switch that + // will only become apparent if the dialog is closed. The previous screen will stick around + // until that switch. + if (nextScreen_ != 0) { + FLOG("WTF? Already had nextScreen_"); + } + nextScreen_ = screen; +} + +void ScreenManager::update(const InputState &input) { + if (dialog_.size()) { + dialog_.back()->update(input); + return; + } + + if (nextScreen_) { + Screen *temp = currentScreen_; + currentScreen_ = nextScreen_; + delete temp; + temp = 0; + nextScreen_ = 0; + } + if (currentScreen_) { + currentScreen_->update(input); + } +} + +void ScreenManager::render() { + if (dialog_.size()) { + dialog_.back()->render(); + } + if (currentScreen_) { + currentScreen_->render(); + } + else { + ELOG("No current screen!"); + } +} + +void ScreenManager::shutdown() { + if (nextScreen_) { + delete nextScreen_; + nextScreen_ = 0; + } + if (currentScreen_) { + delete currentScreen_; + currentScreen_ = 0; + } +} + +void ScreenManager::push(Screen *screen) { + dialog_.push_back(screen); +} + +void ScreenManager::pop() { + if (dialog_.size()) { + delete dialog_.back(); + dialog_.pop_back(); + } else { + ELOG("Can't push when no dialog is shown"); + } +} \ No newline at end of file diff --git a/ui/screen.h b/ui/screen.h new file mode 100644 index 0000000000..5dcd8a841b --- /dev/null +++ b/ui/screen.h @@ -0,0 +1,62 @@ +// Super basic screen manager. Let's you, well, switch between screens. Can also be used +// to pop one screen in front for a bit while keeping another one running, it's basically +// a native "activity stack". Well actually that part is still a TODO. +// +// Semantics +// +// switchScreen: When you call this, on a newed screen, the ScreenManager takes ownership. +// On the next update, it switches to the new screen and deletes the previous screen. +// +// TODO: A way to do smooth transitions between screens. Will probably involve screenshotting +// the previous screen and then animating it on top of the current screen with transparency +// and/or other similar effects. + +#pragma once + +#include +#include "base/display.h" + +struct InputState; + +class Screen { +public: + Screen(); + virtual ~Screen(); + virtual void update(const InputState &input) = 0; + virtual void render() {} + virtual void dialogFinished(const Screen &dialog) {} +}; + +class Transition { +public: + Transition() {} +}; + +class ScreenManager { +public: + ScreenManager(); + virtual ~ScreenManager(); + + void switchScreen(Screen *screen); + void update(const InputState &input); + void render(); + void shutdown(); + + // Push a dialog box in front. Currently 1-level only. + void push(Screen *screen); + + // Pops the dialog away. + void pop(); + +private: + // Base screen. These don't "stack" and you can move in any order between them. + Screen *currentScreen_; + Screen *nextScreen_; + + // Dialog stack. These are shown "on top" of base screens and back works as expected. + // Used for options, in-game menus and other things you expect to be able to back out from onto something. + std::list dialog_; +}; + +// Yeah, an old school non enforced singleton. Good enough. +extern ScreenManager screenManager; From 9d531d717af377fb304527723be52f7562cc16c3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 16 Jul 2012 15:00:52 +0200 Subject: [PATCH 0078/1445] Add some code to pop up an inputbox on android. --- .../turboviking/libnative/NativeActivity.java | 57 +++++++++++++++++++ base/PCMain.cpp | 3 +- ui/screen.cpp | 7 ++- ui/screen.h | 3 + 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 6b88954992..be456068c0 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -9,7 +9,9 @@ import java.util.UUID; import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityManager; +import android.app.AlertDialog; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -26,10 +28,14 @@ import android.os.Environment; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; +import android.view.Gravity; import android.view.KeyEvent; import android.view.View; +import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; +import android.widget.EditText; +import android.widget.FrameLayout; import android.widget.Toast; class Installation { @@ -84,6 +90,8 @@ public class NativeActivity extends Activity { public static String installID; + private EditText editText; + String getApplicationLibraryDir(ApplicationInfo application) { String libdir = null; try { @@ -168,6 +176,14 @@ public class NativeActivity extends Activity { if (!useOpenSL) audioPlayer = new NativeAudioPlayer(); lightsOut(); + + /* + editText = new EditText(this); + editText.setText("Hello world"); + + addContentView(editText, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + */ + inputBox("Please ener a s", "", "Save"); } @SuppressLint("NewApi") @@ -281,6 +297,45 @@ public class NativeActivity extends Activity { super.onConfigurationChanged(newConfig); } + public static boolean inputBoxCancelled; + @SuppressWarnings("deprecation") + public String inputBox(String title, String defaultText, String defaultAction) { + final FrameLayout fl = new FrameLayout(this); + final EditText input = new EditText(this); + input.setGravity(Gravity.CENTER); + + inputBoxCancelled = false; + FrameLayout.LayoutParams editBoxLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); + editBoxLayout.setMargins(2, 20, 2, 20); + fl.addView(input, editBoxLayout); + + input.setText(defaultText); + input.selectAll(); + + AlertDialog dlg = new AlertDialog.Builder(this) + .setView(fl) + .setTitle(title) + .setPositiveButton(defaultAction, new DialogInterface.OnClickListener(){ + @Override + public void onClick(DialogInterface d, int which) { + d.dismiss(); + } + }) + .setNegativeButton("Cancel", new DialogInterface.OnClickListener(){ + @Override + public void onClick(DialogInterface d, int which) { + d.cancel(); + NativeActivity.inputBoxCancelled = false; + } + }).create(); + dlg.setCancelable(false); + dlg.show(); + if (inputBoxCancelled) + return null; + // Toast.makeText(this, "Value: " + input.getText().toString(), Toast.LENGTH_LONG).show(); + return input.getText().toString(); + } + public void processCommand(String command, String params) { if (command.equals("launchBrowser")) { Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); @@ -304,6 +359,8 @@ public class NativeActivity extends Activity { } else if (command.equals("showkeyboard")) { //InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); //inputMethodManager.toggleSoftInputFromWindow(this, InputMethodManager.SHOW_FORCED, 0); + } else if (command.equals("gettext")) { + inputBox("Enter text", params, "OK"); } else { Log.e(TAG, "Unsupported command " + command + " , param: " + params); } diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 7540cf1d22..8739633a48 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -25,9 +25,10 @@ #include "base/NativeApp.h" #include "net/resolve.h" - // Simple implementations of System functions + + void SystemToast(const char *text) { #ifdef _WIN32 MessageBox(0, text, "Toast!", MB_ICONINFORMATION); diff --git a/ui/screen.cpp b/ui/screen.cpp index 581c3eabd9..548ae4fb58 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -21,9 +21,11 @@ void ScreenManager::switchScreen(Screen *screen) { // will only become apparent if the dialog is closed. The previous screen will stick around // until that switch. if (nextScreen_ != 0) { - FLOG("WTF? Already had nextScreen_"); + FLOG("WTF? Already had a nextScreen_"); + } + if (screen != currentScreen_) { + nextScreen_ = screen; } - nextScreen_ = screen; } void ScreenManager::update(const InputState &input) { @@ -47,6 +49,7 @@ void ScreenManager::update(const InputState &input) { void ScreenManager::render() { if (dialog_.size()) { dialog_.back()->render(); + return; } if (currentScreen_) { currentScreen_->render(); diff --git a/ui/screen.h b/ui/screen.h index 5dcd8a841b..cb168ec1d2 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -14,6 +14,7 @@ #pragma once #include +#include "base/basictypes.h" #include "base/display.h" struct InputState; @@ -25,6 +26,8 @@ public: virtual void update(const InputState &input) = 0; virtual void render() {} virtual void dialogFinished(const Screen &dialog) {} +private: + DISALLOW_COPY_AND_ASSIGN(Screen); }; class Transition { From 9d04a56836f1d1166562e663619aed5b1d76fadf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 17 Jul 2012 00:00:48 +0200 Subject: [PATCH 0079/1445] UITheme --- file/file_util.cpp | 16 ++++++++-------- ui/ui.cpp | 34 ++++++++++++++-------------------- ui/ui.h | 15 ++++++++++++++- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index 3741bdbdf3..eeacc9ae55 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -82,16 +82,16 @@ size_t getFilesInDir(const char *directory, std::vector *files) { const std::string virtualName(ffd.cFileName); #else - struct dirent dirent, *result = NULL; + struct dirent dirent, *result = NULL; - DIR *dirp = opendir(directory); - if (!dirp) - return 0; + DIR *dirp = opendir(directory); + if (!dirp) + return 0; - // non windows loop - while (!readdir_r(dirp, &dirent, &result) && result) - { - const std::string virtualName(result->d_name); + // non windows loop + while (!readdir_r(dirp, &dirent, &result) && result) + { + const std::string virtualName(result->d_name); #endif // check for "." and ".." if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || diff --git a/ui/ui.cpp b/ui/ui.cpp index 14a134bacd..b4bda255a5 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -14,19 +14,13 @@ UIState uistate; // Theme. static const Atlas *themeAtlas; -static int themeUIFont; -static int themeButtonImage; -static int themeCheckOnImage; -static int themeCheckOffImage; +static UITheme theme; -void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int checkOff) { +void UIInit(const Atlas *atlas, const UITheme &ui_theme) { ui_draw2d.SetAtlas(atlas); ui_draw2d_front.SetAtlas(atlas); themeAtlas = atlas; - themeUIFont = uiFont; - themeButtonImage = buttonImage; - themeCheckOnImage = checkOn; - themeCheckOffImage = checkOff; + theme = ui_theme; memset(&uistate, 0, sizeof(uistate)); } @@ -85,7 +79,7 @@ void UIEnd() { } void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) { - UIText(themeUIFont, x, y, text, color, scale, align); + UIText(theme.uiFont, x, y, text, color, scale, align); } void UIText(int font, int x, int y, const char *text, uint32_t color, float scale, int align) { @@ -95,7 +89,7 @@ void UIText(int font, int x, int y, const char *text, uint32_t color, float scal } int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align) { - float h = themeAtlas->images[themeButtonImage].h; + float h = themeAtlas->images[theme.buttonImage].h; float x, y; layout.GetPos(&w, &h, &x, &y); @@ -138,8 +132,8 @@ int UIButton(int id, const LayoutManager &layout, float w, const char *text, int // Render button - ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); - ui_draw2d.DrawTextShadow(themeUIFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); + ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); + ui_draw2d.DrawTextShadow(theme.uiFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); uistate.lastwidget = id; return clicked; @@ -187,7 +181,7 @@ int UIImageButton(int id, const LayoutManager &layout, float w, int image, int b // Render button - ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); + ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); uistate.lastwidget = id; @@ -198,8 +192,8 @@ int UIImageButton(int id, const LayoutManager &layout, float w, int image, int b int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { const int h = 64; float tw, th; - ui_draw2d.MeasureText(themeUIFont, text, &tw, &th); - int w = themeAtlas->images[themeCheckOnImage].w + UI_SPACE + tw; + ui_draw2d.MeasureText(theme.uiFont, text, &tw, &th); + int w = themeAtlas->images[theme.checkOn].w + UI_SPACE + tw; if (align & ALIGN_HCENTER) x -= w / 2; if (align & ALIGN_VCENTER) y -= h / 2; if (align & ALIGN_RIGHT) x -= w; @@ -238,8 +232,8 @@ int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { } } - ui_draw2d.DrawImage((*value) ? themeCheckOnImage : themeCheckOffImage, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); - ui_draw2d.DrawTextShadow(themeUIFont, text, x + themeAtlas->images[themeCheckOnImage].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + ui_draw2d.DrawImage((*value) ? theme.checkOn : theme.checkOff, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + ui_draw2d.DrawTextShadow(theme.uiFont, text, x + themeAtlas->images[theme.checkOn].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); uistate.lastwidget = id; @@ -248,8 +242,8 @@ int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, bool selected) const { - ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); - ui_draw2d.DrawTextShadow(themeUIFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); + ui_draw2d.DrawTextShadow(theme.uiFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); } int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListState *state) { diff --git a/ui/ui.h b/ui/ui.h index 4ff3f4776a..2849ff5690 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -116,7 +116,20 @@ struct Atlas; extern DrawBuffer ui_draw2d; extern DrawBuffer ui_draw2d_front; // for things that need to be on top of the rest -void UIInit(const Atlas *atlas, int uiFont, int buttonImage, int checkOn, int checkOff); +struct UITheme { + int uiFont; + int uiFontSmall; + int uiFontSmaller; + int buttonImage; + int checkOn; + int checkOff; +}; + +// The atlas needs to stick around, the theme is copied. +void UIInit(const Atlas *atlas, const UITheme &theme); + +// Just lets you retrieve the theme that was passed into UIInit, for your own controls for example. +UITheme &UIGetTheme(); // TODO: These don't really belong here. const int UI_SPACE = 32; From 4fb4124e0aaf954ad1a68d7db40992ac634001a0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 18 Jul 2012 12:03:51 +0200 Subject: [PATCH 0080/1445] Fixes from fixing the mac port --- base/CMakeLists.txt | 3 +++ ext/etcpack/etctool.cpp | 5 ++--- ext/etcpack/image.cpp | 2 +- gfx/texture_gen.cpp | 1 - math/lin/vec3.h | 9 --------- math/math_util.h | 3 +++ 6 files changed, 9 insertions(+), 14 deletions(-) diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index cb067cad0a..131c7d3834 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -1,8 +1,11 @@ set(SRCS LAMEString.cpp colorutil.cpp + timeutil.cpp + threadutil.cpp error_context.cpp display.cpp + PCMain.cpp buffer.cpp) set(SRCS ${SRCS}) diff --git a/ext/etcpack/etctool.cpp b/ext/etcpack/etctool.cpp index 6e7692826c..3e1fff9832 100644 --- a/ext/etcpack/etctool.cpp +++ b/ext/etcpack/etctool.cpp @@ -958,9 +958,8 @@ void uncompressFile(char *srcfile,char *dstfile) int active_height; int format; - - - if(f=fopen(srcfile,"rb")) + f=fopen(srcfile,"rb"); + if (f) { if(ktx_mode) { diff --git a/ext/etcpack/image.cpp b/ext/etcpack/image.cpp index 61688632b5..f067877467 100644 --- a/ext/etcpack/image.cpp +++ b/ext/etcpack/image.cpp @@ -99,7 +99,7 @@ bool fReadPPM(const char *filename, int &width, int &height, unsigned char *&pix if(strcmp(line, "P6")!=0) { - printf("Error: %s is not binary\n"); + printf("Error: %s is not binary\n", filename); printf("(Binary .ppm files start with P6).\n"); fclose(f1); return false; diff --git a/gfx/texture_gen.cpp b/gfx/texture_gen.cpp index 78545030b0..8dac34c10e 100644 --- a/gfx/texture_gen.cpp +++ b/gfx/texture_gen.cpp @@ -18,7 +18,6 @@ uint8_t *generateTexture(const char *filename, int &bpp, int &w, int &h, bool &c return 0; sscanf(filename, "gen:%i:%i:%s", &w, &h, name_and_params); - bool mip = false; uint8_t *data; if (!strcmp(name_and_params, "vignette")) { bpp = 1; diff --git a/math/lin/vec3.h b/math/lin/vec3.h index ac346a7f76..5355f20977 100644 --- a/math/lin/vec3.h +++ b/math/lin/vec3.h @@ -4,16 +4,7 @@ #include #include // memset -inline float sqr(float f) {return f*f;} -inline float sqr_signed(float f) {return f<0 ? -f*f : f*f;} - -#ifndef PI -#define PI (3.141592654f) -#endif -#define PI_INV (0.318309886f) - class Matrix4x4; -// class Quaternion; // Hm, doesn't belong in this file. class Vec4 { diff --git a/math/math_util.h b/math/math_util.h index 9ee89d6e99..b6196f8240 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -4,6 +4,9 @@ #include #include +inline float sqr(float f) {return f*f;} +inline float sqr_signed(float f) {return f<0 ? -f*f : f*f;} + typedef unsigned short float16; // This ain't a 1.5.10 float16, it's a stupid hack format where we chop 16 bits off a float. From 0f8d52fecb1c204b5283c8a4a0201370afc4a551 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 23 Jul 2012 16:49:08 +0200 Subject: [PATCH 0081/1445] Warning fixes --- input/gesture_detector.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 01b2098bb7..6494553a76 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -47,6 +47,7 @@ bool down(int i, float *xdelta, float *ydelta) { } *xdelta = fingers[i].downX; *ydelta = fingers[i].downY; + return true; } bool dragDistance(int i, float *xdelta, float *ydelta) { @@ -55,6 +56,7 @@ bool dragDistance(int i, float *xdelta, float *ydelta) { *xdelta = fingers[i].X - fingers[i].downX; *ydelta = fingers[i].Y - fingers[i].downY; + return true; } bool dragDelta(int i, float *xdelta, float *ydelta) { @@ -63,6 +65,7 @@ bool dragDelta(int i, float *xdelta, float *ydelta) { *xdelta = fingers[i].X - fingers[i].lastX; *ydelta = fingers[i].Y - fingers[i].lastY; + return true; } } From 7e2e7856d895f8b9293e3bf48b7d504fb4246211 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 23 Jul 2012 20:45:04 +0200 Subject: [PATCH 0082/1445] Remove LAMEString.cpp/h --- base/CMakeLists.txt | 3 +- base/LAMEString.cpp | 415 ----------------------------------------- base/LAMEString.h | 104 ----------- file/chunk_file.cpp | 45 ++--- file/chunk_file.h | 13 +- file/easy_file.cpp | 1 - native.vcxproj | 3 +- native.vcxproj.filters | 9 +- 8 files changed, 27 insertions(+), 566 deletions(-) delete mode 100644 base/LAMEString.cpp delete mode 100644 base/LAMEString.h diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 131c7d3834..184894126a 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -1,11 +1,10 @@ set(SRCS - LAMEString.cpp colorutil.cpp timeutil.cpp threadutil.cpp error_context.cpp display.cpp - PCMain.cpp + PCMain.cpp buffer.cpp) set(SRCS ${SRCS}) diff --git a/base/LAMEString.cpp b/base/LAMEString.cpp deleted file mode 100644 index 624ec054ad..0000000000 --- a/base/LAMEString.cpp +++ /dev/null @@ -1,415 +0,0 @@ -// NOTE: See warning in header. - - -#include -#include -#include -#include "LAMEString.h" - -#define assert(a) - -const int MAX_LENGTH = 1024; // largest size string for input - -#define _tcslen strlen -#define _tcscpy strcpy -#define _tcscmp strcmp -#define _tcsncmp strncmp - - -String::String() -{ - Capacity = 1; - CString = new TCHAR[Capacity]; - CString[0] = '\0'; // make c-style string zero length -} - -String::String(const TCHAR * s) -{ - Capacity = (int)_tcslen(s) + 1; - CString = new TCHAR[Capacity]; - _tcscpy(CString,s); -} - -String::String(const String & str) -{ - Capacity = str.length() + 1; - CString = new TCHAR[Capacity]; - _tcscpy(CString,str.CString); -} - -String::~String() -{ - delete [] CString; // free memory -} - -const String & String::operator = (const String & rhs) -{ - if (this != &rhs) { // check aliasing - if (Capacity < rhs.length() + 1) { // more memory needed? - delete[] CString; // delete old string - Capacity = rhs.length() + 1; // add 1 for '\0' - CString = new TCHAR[Capacity]; - } - _tcscpy(CString,rhs.CString); - } - return *this; -} - - -const String & String::operator = (const TCHAR * s) -{ - int len = 0; // length of newly constructed string - assert(s != 0); // make sure s non-NULL - len = (int)_tcslen(s); // # of characters in string - - // free old string if necessary - - if (Capacity < len + 1) - { - delete[] CString; // delete old string - Capacity = len + 1; // add 1 for '\0' - CString = new TCHAR[Capacity]; - } - _tcscpy(CString,s); - return *this; -} - -const String & String::operator = (TCHAR ch) -{ - if (Capacity < 2) - { - delete [] CString; - Capacity = 2; - CString = new TCHAR[Capacity]; - } - CString[0] = ch; // make string one character long - CString[1] = '\0'; - return *this; -} - -int String::length() const { - int myLength = 0; - while (CString[myLength] != '\0') - myLength++; - return myLength; -} - -TCHAR * String::getPointer() const -{ - return CString; -} - -TCHAR & String::operator [] (int k) -{ - if (k < 0 || (int)_tcslen(CString) <= k) - { - //cerr << "index out of range: " << k << " string: " << CString << endl; - assert(0 <= k && k < _tcslen(CString)); - } - return CString[k]; -} - - -const String & String::operator += (const String & str) -{ - String copystring(str); // copy to avoid aliasing problems - - int newLength = length() + str.length(); // self + added string - int lastLocation = length(); // index of '\0' - - // check to see if local buffer not big enough - if (newLength >= Capacity) - { - Capacity = newLength + 1; - TCHAR * newBuffer = new TCHAR[Capacity]; - _tcscpy(newBuffer,CString); // copy into new buffer - delete [] CString; // delete old string - CString = newBuffer; - } - - // now catenate str (copystring) to end of CString - _tcscpy(CString+lastLocation,copystring.getPointer() ); - - return *this; -} - -const String & String::operator += (const TCHAR * s) -{ - int newLength = length() + (int)_tcslen(s); // self + added string - int lastLocation = length(); // index of '\0' - - // check to see if local buffer not big enough - if (newLength >= Capacity) - { - Capacity = newLength + 1; - TCHAR * newBuffer = new TCHAR[Capacity]; - _tcscpy(newBuffer,CString); // copy into new buffer - delete [] CString; // delete old string - CString = newBuffer; - } - - // now catenate s to end of CString - _tcscpy(CString+lastLocation,s); - - return *this; -} - -const String & String::operator += ( TCHAR ch ) -{ - String temp; // make string equivalent of ch - temp = ch; - *this += temp; - return *this; -} - -String operator + (const String & lhs, const String & rhs) -{ - String result(lhs); // copies lhs to result - result += rhs; // catenate rhs - return result; // returns a copy of result -} - -String operator + ( TCHAR ch, const String & str ) -{ - String result; // make string equivalent of ch - result = ch; - result += str; - return result; -} - -String operator + ( const String & str, TCHAR ch ) -{ - String result(str); - result += ch; - return result; -} - - -String String::subString(int pos, int len) const -{ - String result(*this); // make sure enough space allocated - - if(pos < 0) // start at front when pos < 0 - { - pos = 0; - } - - if(pos >= (int)_tcslen(CString)) - { - result = ""; // empty string - return result; - } - - int lastIndex = pos + len - 1; // last char's index (to copy) - if(lastIndex >= (int)_tcslen(CString)) { // off end of string? - lastIndex = (int)_tcslen(CString)-1; - } - - int j,k; - for(j=0,k=pos; k <= lastIndex; j++,k++) { - result.CString[j] = CString[k]; - } - result.CString[j] = '\0'; // properly terminate C-string - return result; -} - -int String::find(const String & str, int startpos) const -{ - int len = str.length(); - int lastIndex = length() - len; - int k; - for (k=startpos; k <= lastIndex; k++) { - if (_tcsncmp(CString + k,str.getPointer(),len) == 0) return k; - } - return -1; -} - - -int String::find(TCHAR ch, int startpos) const -{ - int k; - for(k=startpos; k < (int)_tcslen(CString); k++) { - if (CString[k] == ch) { - return k; - } - } - return -1; -} - -int String::findLast(TCHAR ch, int count) -{ - for (int k=length()-1; k; k--) - { - if (CString[k] == ch) - { - if (count==0) - return k; - count--; - } - } - return -1; -} - -int String::parseIntoWords(String *words, int maxWords) -{ - int numWords=0; - String currentWord; - for (int i=0; i0) - { - words[numWords] = currentWord; - currentWord=""; - numWords++; - if (numWords == maxWords) - return numWords; - } - } - else - { - currentWord += c; - } - } - return numWords; -} - -void String::toLower() -{ - for (int i=0; i ( const String & lhs, const String & rhs ) -{ - return rhs < lhs; -} - -bool operator >= ( const String & lhs, const String & rhs ) -{ - return rhs <= lhs; -} -/* -int String::convertToInt() const -{ - return(_ttoi(CString)); -}*/ - - -void String::reverseString() -{ - int n = 0, i = 0; - TCHAR *ny = new TCHAR[length()+1]; - - for (i=length()-1; i >= 0; i--, n++) { - ny[i] = CString[n]; - } - - ny[length()]='\0'; - - _tcscpy(CString, ny); - - delete [] ny; -} - - - - -String String::getPath() -{ - int p=find(String("\\"),0); - int lastp=-1; - while (p!=-1) { - lastp=p; - p=find(String("\\"),p+1); - } - if (lastp!=-1) { - return subString(0,lastp); - } else { - return String(""); - } -} - -String String::getFName() -{ - int p=find(String("\\"),0); - int lastp=-1; - while (p!=-1) - { - lastp=p; - p=find(String("\\"),p+1); - } - if (lastp!=-1) - { - return subString(lastp+1,100); - } - else - { - return String(""); - } -} - - -void String::toUnicode(wchar_t *dest) -{ - for (int i=0; i255?' ':i; - } - }; - - int newLength = wideLength(src); - delete [] CString; - Capacity = newLength + 1; - CString = new TCHAR[Capacity]; - - int i; - for (i=0; i -#include - -#include "base/basictypes.h" - -#ifdef UNICODE -typedef wchar_t TCHAR; -#else -typedef char TCHAR; -#endif - -class String -{ -public: - // constructors/destructor - String(); // construct empty string "" - explicit String(const char * s); // construct from string literal - String(const String & str); // copy constructor - ~String(); // destructor - - - // accessors - - int find(const String & str, int startpos=0) const; // index of first occurrence of str - int find(TCHAR ch, int startpos=0) const; // index of first occurrence of ch - int findLast(TCHAR ch,int count=0); - String subString(int pos, int len) const; // substring of len chars - - - int length() const; // number of chars - - // starting at pos - TCHAR * getPointer( ) const; // explicit conversion to char * - const TCHAR *c_str() const { - return getPointer(); - } - - // assignment - const String & operator = ( const String & str ); // assign str - const String & operator = ( const TCHAR * s ); // assign s - const String & operator = ( TCHAR ch ); // assign ch - - //int operator == (String &other); - //int operator != (String &other) {return !(*this == other);} - // indexing - TCHAR & operator [] ( int k ); // range-checked indexing - - // modifiers - const String & operator += ( const String & str ); // append str - const String & operator += ( const TCHAR * s); // append s - const String & operator += ( TCHAR ch ); // append char - - int parseIntoWords(String *words, int maxWords); - int convertToInt() const; - /* - static String fromInt(int i) { - TCHAR temp[15]; - _itot_s(i,temp,15,10); - return String(temp); - }*/ - void reverseString(); - void toUnicode(wchar_t *dest); - void fromUnicode(wchar_t *src); - String getPath(); - String getFName(); - - void toUpper(); - void toLower(); - -private: - int Capacity; // capacity of string - TCHAR * CString; // storage for characters -}; - -// The following free (non-member) functions operate on strings -// -// I/O functions -/* -ostream & operator << ( ostream & os, const String & str ); -istream & operator >> ( istream & is, String & str ); -istream & getline( istream & is, String & str ); -*/ -// comparison operators: - -bool operator == ( const String & lhs, const String & rhs ); -bool operator != ( const String & lhs, const String & rhs ); -bool operator < ( const String & lhs, const String & rhs ); -bool operator <= ( const String & lhs, const String & rhs ); -bool operator > ( const String & lhs, const String & rhs ); -bool operator >= ( const String & lhs, const String & rhs ); - -// concatenation operator + - -String operator + ( const String & lhs, const String & rhs ); -String operator + ( TCHAR ch, const String & str ); -String operator + ( const String & str, TCHAR ch ); - diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index 64f103b312..f8b991bfe7 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -17,8 +17,8 @@ ChunkFile::ChunkFile(const char *filename, bool _read) { if (fastMode) { size_t size; - data = (uint8 *)VFSReadFile(filename, &size); - if (!data) { + data = (uint8_t *)VFSReadFile(filename, &size); + if (!data) { ELOG("Chunkfile fail: %s", filename); didFail = true; return; @@ -190,6 +190,7 @@ void ChunkFile::writeData(const void *what, int count) { } } +/* void ChunkFile::writeWString(String str) { wchar_t *text; int len=str.length(); @@ -206,6 +207,7 @@ void ChunkFile::writeWString(String str) { delete [] text; #endif } +*/ void ChunkFile::writeWString(const std::string &str) { unsigned short *text; @@ -226,24 +228,6 @@ void ChunkFile::writeWString(const std::string &str) { #endif } - -String ChunkFile::readWString() { - int len=readInt(); - wchar_t *text = new wchar_t[len+1]; - readData((char *)text,len*sizeof(wchar_t)); - text[len]=0; -#ifdef UNICODE - String s(text); - delete [] text; - return s; -#else - String temp; - temp.fromUnicode(text); - delete [] text; - return temp; -#endif -} - static void toUnicode(const std::string &str, uint16 *t) { for (int i=0; i<(int)str.size(); i++) { *t++ = str[i]; @@ -251,22 +235,25 @@ static void toUnicode(const std::string &str, uint16 *t) { *t++ = '\0'; } -static std::string fromUnicode(const uint16 *src, int len) { - struct Local { - static int clamp(int i) { - return i>255?' ':i; - } - }; - +static std::string fromUnicode(const uint16_t *src, int len) { std::string str; str.resize(len); - for (int i=0; i 255 ? ' ' : i; } return str; } +std::string ChunkFile::readWString() { + int len=readInt(); + uint16_t *text = new uint16_t[len+1]; + readData((char *)text, len*sizeof(uint16_t)); + text[len] = 0; + std::string temp = fromUnicode(text, len); + delete [] text; + return temp; +} + void ChunkFile::writeString(const std::string &str) { uint16_t *text; int len = str.size(); diff --git a/file/chunk_file.h b/file/chunk_file.h index 4fbfded350..5da5ec747d 100644 --- a/file/chunk_file.h +++ b/file/chunk_file.h @@ -11,7 +11,6 @@ #include #include "base/basictypes.h" -#include "base/LAMEString.h" #include "file/easy_file.h" inline uint32 flipID(uint32 id) { @@ -29,18 +28,19 @@ public: int readInt(); void readInt(int &i) {i = readInt();} void readData(void *data, int count); - String readWString(); + // String readWString(); + std::string readWString(); void writeString(const std::string &str); std::string readString(); void writeInt(int i); - void writeWString(String str); + //void writeWString(String str); void writeWString(const std::string &str); void writeData(const void *data, int count); int getCurrentChunkSize(); - bool failed() const {return didFail;} + bool failed() const { return didFail; } std::string filename() const { return fn; } private: @@ -56,8 +56,8 @@ private: ChunkInfo stack[8]; int numLevels; - uint8 *data; - int pos,eof; + uint8_t *data; + int pos, eof; bool fastMode; bool read; bool didFail; @@ -65,4 +65,3 @@ private: void seekTo(int _pos); int getPos() const {return pos;} }; - diff --git a/file/easy_file.cpp b/file/easy_file.cpp index 21d8935b98..c3259ca3f3 100644 --- a/file/easy_file.cpp +++ b/file/easy_file.cpp @@ -1,7 +1,6 @@ #include #include "base/basictypes.h" -#include "base/LAMEString.h" #include "file/easy_file.h" LAMEFile::LAMEFile() : file_(NULL) { diff --git a/native.vcxproj b/native.vcxproj index 7c1069b6fd..909604b212 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -88,6 +88,7 @@ + @@ -102,7 +103,6 @@ - @@ -171,7 +171,6 @@ - diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 8bda8682a6..e23e6418a1 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -5,6 +5,9 @@ file + + base + @@ -70,9 +73,6 @@ base - - base - base @@ -237,9 +237,6 @@ file - - base - gfx From a67237fba79e69677a846bb4d119f1c5168076f7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 26 Jul 2012 13:47:15 +0200 Subject: [PATCH 0083/1445] Add some old code, do some buildfixing --- base/backtrace.cpp | 17 +++++++ base/backtrace.h | 3 ++ base/fastlist.h | 37 ++++++++++++++ base/fastlist_test.cpp | 19 +++++++ base/linked_ptr.h | 113 +++++++++++++++++++++++++++++++++++++++++ math/lin/aabb.cpp | 4 -- math/lin/aabb.h | 11 +--- math/lin/plane.cpp | 5 +- math/lin/plane.h | 8 +-- math/lin/ray.h | 8 +-- math/lin/vec3.h | 3 ++ math/math_util.h | 7 ++- native.vcxproj | 13 +++++ native.vcxproj.filters | 39 ++++++++++++++ ui/list_screen.cpp | 6 +++ ui/list_screen.h | 10 ++++ ui/screen.h | 2 +- ui/ui.cpp | 2 + ui/ui.h | 4 ++ util/random/perlin.cpp | 10 ++-- util/random/perlin.h | 6 +-- util/random/rng.h | 5 +- 22 files changed, 286 insertions(+), 46 deletions(-) create mode 100644 base/backtrace.cpp create mode 100644 base/backtrace.h create mode 100644 base/fastlist.h create mode 100644 base/fastlist_test.cpp create mode 100644 base/linked_ptr.h create mode 100644 ui/list_screen.cpp create mode 100644 ui/list_screen.h diff --git a/base/backtrace.cpp b/base/backtrace.cpp new file mode 100644 index 0000000000..422b1e17b8 --- /dev/null +++ b/base/backtrace.cpp @@ -0,0 +1,17 @@ +#include "base/backtrace.h" + +#ifndef _MSC_VER + +// LINUX ONLY + +#include +#include + +static void *backtrace_buffer[128]; + +void PrintBacktraceToStderr() { + int num_addrs = backtrace(backtrace_buffer, 128); + backtrace_symbols_fd(backtrace_buffer, num_addrs, STDERR_FILENO); +} + +#endif \ No newline at end of file diff --git a/base/backtrace.h b/base/backtrace.h new file mode 100644 index 0000000000..4ff0917f30 --- /dev/null +++ b/base/backtrace.h @@ -0,0 +1,3 @@ +#pragma once + +void PrintBacktraceToStderr(); diff --git a/base/fastlist.h b/base/fastlist.h new file mode 100644 index 0000000000..78ba4e5512 --- /dev/null +++ b/base/fastlist.h @@ -0,0 +1,37 @@ +#pragma once + +// An inline fastlist is a fixed size array with a position counter. +// Objects stored in a fastlist must be copyable. +// [] returns the objects in consecutive order, up to and not including +// the value of .size(). +// Order is not preserved when removing objects. +template +class InlineFastList { + public: + InlineFastList() : count_(0) {} + ~InlineFastList() {} + + T& operator [](int index) { return data_[index]; } + const T& operator [](int index) const { return data_[index]; } + int size() const { return count_; } + + void Add(T t) { + data_[count_++] = t; + } + void RemoveAt(int index) { + data_[index] = data_[count_ - 1]; + count_--; + } + void Remove(T t) { // Requires operator== + for (int i = 0; i < count_; i++) { + if (data_[i] == t) { + RemoveAt(i); + return; + } + } + } + + private: + T data_[max_size]; + int count_; +}; diff --git a/base/fastlist_test.cpp b/base/fastlist_test.cpp new file mode 100644 index 0000000000..57064adcc4 --- /dev/null +++ b/base/fastlist_test.cpp @@ -0,0 +1,19 @@ +#include "base/fastlist.h" +#include "base/logging.h" + +/* +#include + +TEST(fastlist, AddRemove) { + InlineFastList list; + list.Add(8); + list.Remove(7); + EXPECT_EQ(1, list.size()); + list.Remove(8); + EXPECT_EQ(0, list.size()); + list.Add(1); + list.Add(2); + list.Add(3); + EXPECT_EQ(3, list.size()); +} +*/ \ No newline at end of file diff --git a/base/linked_ptr.h b/base/linked_ptr.h new file mode 100644 index 0000000000..4be7c3ddab --- /dev/null +++ b/base/linked_ptr.h @@ -0,0 +1,113 @@ +// From http://ootips.org/yonat/4dev/linked_ptr.h + +/* + * linked_ptr - simple reference linked pointer + * (like reference counting, just using a linked list of the references + * instead of their count.) + * + * The implementation stores three pointers for every linked_ptr, but + * does not allocate anything on the free store. + */ + +#pragma once + +/* For ANSI-challenged compilers, you may want to #define + * NO_MEMBER_TEMPLATES, explicit or mutable */ + +#ifdef _MSC_VER +#define NO_MEMBER_TEMPLATES +#endif + +template class linked_ptr +{ +public: + +#ifndef NO_MEMBER_TEMPLATES +# define TEMPLATE_FUNCTION template + TEMPLATE_FUNCTION friend class linked_ptr; +#else +# define TEMPLATE_FUNCTION + typedef X Y; +#endif + + typedef X element_type; + + explicit linked_ptr(X* p = 0) throw() + : itsPtr(p) {itsPrev = itsNext = this;} + ~linked_ptr() + {release();} + linked_ptr(const linked_ptr& r) throw() + {acquire(r);} + linked_ptr& operator=(const linked_ptr& r) + { + if (this != &r) { + release(); + acquire(r); + } + return *this; + } + +#ifndef NO_MEMBER_TEMPLATES + template friend class linked_ptr; + template linked_ptr(const linked_ptr& r) throw() + {acquire(r);} + template linked_ptr& operator=(const linked_ptr& r) + { + if (this != &r) { + release(); + acquire(r); + } + return *this; + } +#endif // NO_MEMBER_TEMPLATES + + X& operator*() const throw() {return *itsPtr;} + X* operator->() const throw() {return itsPtr;} + X* get() const throw() {return itsPtr;} + bool unique() const throw() {return itsPrev ? itsPrev==this : true;} + +private: + X* itsPtr; + mutable const linked_ptr* itsPrev; + mutable const linked_ptr* itsNext; + + void acquire(const linked_ptr& r) throw() + { // insert this to the list + itsPtr = r.itsPtr; + itsNext = r.itsNext; + itsNext->itsPrev = this; + itsPrev = &r; +#ifndef mutable + r.itsNext = this; +#else // for ANSI-challenged compilers + (const_cast*>(&r))->itsNext = this; +#endif + } + +#ifndef NO_MEMBER_TEMPLATES + template void acquire(const linked_ptr& r) throw() + { // insert this to the list + itsPtr = r.itsPtr; + itsNext = r.itsNext; + itsNext->itsPrev = this; + itsPrev = &r; +#ifndef mutable + r.itsNext = this; +#else // for ANSI-challenged compilers + (const_cast*>(&r))->itsNext = this; +#endif + } +#endif // NO_MEMBER_TEMPLATES + + void release() + { // erase this from the list, delete if unique + if (unique()) delete itsPtr; + else { + itsPrev->itsNext = itsNext; + itsNext->itsPrev = itsPrev; + itsPrev = itsNext = 0; + } + itsPtr = 0; + } +}; + diff --git a/math/lin/aabb.cpp b/math/lin/aabb.cpp index 4e73b512a0..6a04ddab14 100644 --- a/math/lin/aabb.cpp +++ b/math/lin/aabb.cpp @@ -7,8 +7,6 @@ #define LEFT 1 #define MIDDLE 2 -namespace lin { - static const float flt_plus_inf = -logf(0); // let's keep C and C++ compilers happy. AABB::AABB() : minB(0,0,0),maxB(0,0,0) { @@ -268,5 +266,3 @@ bool AABB::BehindPlane(const Plane &plane) const { return true; } - -} // namespace lin diff --git a/math/lin/aabb.h b/math/lin/aabb.h index 22f2a7b80d..6f887f876e 100644 --- a/math/lin/aabb.h +++ b/math/lin/aabb.h @@ -1,11 +1,8 @@ -#ifndef _MATH_LIN_AABB -#define _MATH_LIN_AABB +#pragma once #include "math/lin/vec3.h" -namespace lin { - -class Ray; +struct Ray; class Plane; struct AABB { @@ -41,7 +38,3 @@ struct AABB { bool BehindPlane(const Plane &plane) const; }; - -} // namespace lin - -#endif // _MATH_LIN_AABB diff --git a/math/lin/plane.cpp b/math/lin/plane.cpp index 31b52fa00d..67e8ef631a 100644 --- a/math/lin/plane.cpp +++ b/math/lin/plane.cpp @@ -1,13 +1,10 @@ #include "math/lin/matrix4x4.h" #include "math/lin/plane.h" -namespace lin { -Plane Plane::TransformByIT(const Matrix4x4 &m, Plane *out) { +void Plane::TransformByIT(const Matrix4x4 &m, Plane *out) { out->x = x * m.xx + y * m.yx + z * m.zx + d * m.wx; out->y = x * m.xy + y * m.yy + z * m.zy + d * m.wy; out->z = x * m.xz + y * m.yz + z * m.zz + d * m.wz; out->d = x * m.xw + y * m.yw + z * m.zw + d * m.ww; } - -} diff --git a/math/lin/plane.h b/math/lin/plane.h index 02c7ad22da..6466617c1b 100644 --- a/math/lin/plane.h +++ b/math/lin/plane.h @@ -3,8 +3,6 @@ #include "math/lin/vec3.h" -namespace lin { - class Matrix4x4; class Plane { @@ -24,7 +22,7 @@ class Plane { } void Normalize() { - float inv_length = 1.0 * sqrtf(x * x + y * y + z * z); + float inv_length = sqrtf(x * x + y * y + z * z); x *= inv_length; y *= inv_length; z *= inv_length; @@ -33,9 +31,7 @@ class Plane { // Matrix is the inverse transpose of the wanted transform. // out cannot be equal to this. - Plane TransformByIT(const Matrix4x4 &matrix, Plane *out); + void TransformByIT(const Matrix4x4 &matrix, Plane *out); }; -} - #endif diff --git a/math/lin/ray.h b/math/lin/ray.h index 5c9a5e91e0..2287460fbb 100644 --- a/math/lin/ray.h +++ b/math/lin/ray.h @@ -1,10 +1,7 @@ -#ifndef _MATH_LIN_RAY_H -#define _MATH_LIN_RAY_H +#pragma once #include "vec3.h" -namespace lin { - /* __declspec(align(16)) */ struct Ray { Vec3 origin; @@ -15,6 +12,3 @@ namespace lin { int pad3; }; -} // namespace lin - -#endif // _MATH_LIN_RAY_H diff --git a/math/lin/vec3.h b/math/lin/vec3.h index 5355f20977..e10fc0d3a9 100644 --- a/math/lin/vec3.h +++ b/math/lin/vec3.h @@ -22,6 +22,9 @@ public: Vec3() { } explicit Vec3(float f) {x=y=z=f;} + float operator [] (int i) const { return (&x)[i]; } + float &operator [] (int i) { return (&x)[i]; } + Vec3(const float _x, const float _y, const float _z) { x=_x; y=_y; z=_z; } diff --git a/math/math_util.h b/math/math_util.h index b6196f8240..71edd44a0b 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -1,8 +1,8 @@ #ifndef _MATHUTILS_H #define _MATHUTILS_H -#include -#include +#include +#include inline float sqr(float f) {return f*f;} inline float sqr_signed(float f) {return f<0 ? -f*f : f*f;} @@ -26,6 +26,9 @@ inline float Float16ToFloat(float16 ix) { #define PI 3.141592653589793f +#ifndef M_PI +#define M_PI 3.141592653589793f +#endif // The stuff in this file is from all over the web, esp. dspmusic.org. I think it's all public domain. // In any case, very little of it is used anywhere at the moment. diff --git a/native.vcxproj b/native.vcxproj index 909604b212..470181302e 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -97,12 +97,15 @@ + + + @@ -140,7 +143,9 @@ + + @@ -148,9 +153,12 @@ + + + @@ -167,6 +175,7 @@ + @@ -203,7 +212,9 @@ + + @@ -211,9 +222,11 @@ + + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index e23e6418a1..a9609633e4 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -184,6 +184,30 @@ ui + + base + + + ui + + + base + + + base + + + math + + + math + + + util + + + util + @@ -333,6 +357,21 @@ ui + + ui + + + base + + + math + + + math + + + util + diff --git a/ui/list_screen.cpp b/ui/list_screen.cpp new file mode 100644 index 0000000000..c3cedcd59b --- /dev/null +++ b/ui/list_screen.cpp @@ -0,0 +1,6 @@ +#include "ui/list_screen.h" + +ListScreen::ListScreen() { + +} + diff --git a/ui/list_screen.h b/ui/list_screen.h new file mode 100644 index 0000000000..9dc08f17e2 --- /dev/null +++ b/ui/list_screen.h @@ -0,0 +1,10 @@ +#include "ui/screen.h" + + +class ListScreen { +public: + ListScreen(); + +private: + +}; \ No newline at end of file diff --git a/ui/screen.h b/ui/screen.h index cb168ec1d2..e2637599ff 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -56,7 +56,7 @@ private: Screen *currentScreen_; Screen *nextScreen_; - // Dialog stack. These are shown "on top" of base screens and back works as expected. + // Dialog stack. These are shown "on top" of base screens and the Android back button works as expected. // Used for options, in-game menus and other things you expect to be able to back out from onto something. std::list dialog_; }; diff --git a/ui/ui.cpp b/ui/ui.cpp index b4bda255a5..d6a0df757d 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -10,6 +10,8 @@ // TODO: UI should probably not own these. DrawBuffer ui_draw2d; DrawBuffer ui_draw2d_front; + +// This one, though, is OK. UIState uistate; // Theme. diff --git a/ui/ui.h b/ui/ui.h index 2849ff5690..78c16da1b5 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -5,6 +5,10 @@ // A common pattern is Adapter classes for changing how things are drawn // in lists, for example. // +// Immediate UI works great for overlay UI for games, for example, but is actually +// not really a good idea for full app UIs. Also, animations are difficult because +// there's not really any good place to store state. +// // hrydgard@gmail.com #pragma once diff --git a/util/random/perlin.cpp b/util/random/perlin.cpp index d0ee8a9fa4..e8a8a578df 100644 --- a/util/random/perlin.cpp +++ b/util/random/perlin.cpp @@ -47,14 +47,14 @@ inline float grad(int hash, float x, float y, float z) { return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); } -float Noise(double z, double y, double x) { - double fx = floor(x), fy = floor(y), fz = floor(z); +float Noise(double iz, double iy, double ix) { + double fx = floor(ix), fy = floor(iy), fz = floor(iz); int X = (int)fx & 255, // FIND UNIT CUBE THAT Y = (int)fy & 255, // CONTAINS POINT. Z = (int)fz & 255; - x -= fx; // FIND RELATIVE X,Y,Z - y -= fy; // OF POINT IN CUBE. - z -= fz; + float x = (float)(ix - fx); // FIND RELATIVE X,Y,Z + float y = (float)(iy - fy); // OF POINT IN CUBE. + float z = (float)(iz - fz); float u = fade(x); // COMPUTE FADE CURVES float v = fade(y); // FOR EACH OF X,Y,Z. float w = fade(z); diff --git a/util/random/perlin.h b/util/random/perlin.h index ace8c521d3..ecda001c23 100644 --- a/util/random/perlin.h +++ b/util/random/perlin.h @@ -1,8 +1,6 @@ -#ifndef _PERLIN_H -#define _PERLIN_H +#pragma once // Implementation of "Improved Noise" // http://mrl.nyu.edu/~perlin/noise/ +// doubles are only used at the very start, not a big performance worry float Noise(double x, double y, double z); - -#endif // _PERLIN_H diff --git a/util/random/rng.h b/util/random/rng.h index 28369196a6..68e66d79b9 100644 --- a/util/random/rng.h +++ b/util/random/rng.h @@ -1,5 +1,4 @@ -#ifndef _RNG_H -#define _RNG_H +#pragma once #include "base/basictypes.h" @@ -22,5 +21,3 @@ class GMRng { uint32 m_w; uint32 m_z; }; - -#endif From 55aea944a4f38e40cb8d095b839122d123496532 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 26 Jul 2012 15:37:18 +0200 Subject: [PATCH 0084/1445] indentation / porta --- base/linked_ptr.h | 138 +++++++++++++++++++++++----------------------- gfx/texture.cpp | 18 +++--- 2 files changed, 77 insertions(+), 79 deletions(-) diff --git a/base/linked_ptr.h b/base/linked_ptr.h index 4be7c3ddab..df5ab97443 100644 --- a/base/linked_ptr.h +++ b/base/linked_ptr.h @@ -1,22 +1,20 @@ // From http://ootips.org/yonat/4dev/linked_ptr.h /* - * linked_ptr - simple reference linked pointer - * (like reference counting, just using a linked list of the references - * instead of their count.) - * - * The implementation stores three pointers for every linked_ptr, but - * does not allocate anything on the free store. - */ +* linked_ptr - simple reference linked pointer +* (like reference counting, just using a linked list of the references +* instead of their count.) +* +* The implementation stores three pointers for every linked_ptr, but +* does not allocate anything on the free store. +*/ #pragma once /* For ANSI-challenged compilers, you may want to #define - * NO_MEMBER_TEMPLATES, explicit or mutable */ +* NO_MEMBER_TEMPLATES, explicit or mutable */ -#ifdef _MSC_VER #define NO_MEMBER_TEMPLATES -#endif template class linked_ptr { @@ -24,90 +22,90 @@ public: #ifndef NO_MEMBER_TEMPLATES # define TEMPLATE_FUNCTION template - TEMPLATE_FUNCTION friend class linked_ptr; + TEMPLATE_FUNCTION friend class linked_ptr; #else # define TEMPLATE_FUNCTION - typedef X Y; + typedef X Y; #endif - typedef X element_type; + typedef X element_type; - explicit linked_ptr(X* p = 0) throw() - : itsPtr(p) {itsPrev = itsNext = this;} - ~linked_ptr() - {release();} - linked_ptr(const linked_ptr& r) throw() - {acquire(r);} - linked_ptr& operator=(const linked_ptr& r) - { - if (this != &r) { - release(); - acquire(r); - } - return *this; + explicit linked_ptr(X* p = 0) throw() + : itsPtr(p) {itsPrev = itsNext = this;} + ~linked_ptr() + {release();} + linked_ptr(const linked_ptr& r) throw() + {acquire(r);} + linked_ptr& operator=(const linked_ptr& r) + { + if (this != &r) { + release(); + acquire(r); } + return *this; + } #ifndef NO_MEMBER_TEMPLATES - template friend class linked_ptr; - template linked_ptr(const linked_ptr& r) throw() - {acquire(r);} - template linked_ptr& operator=(const linked_ptr& r) - { - if (this != &r) { - release(); - acquire(r); - } - return *this; + template friend class linked_ptr; + template linked_ptr(const linked_ptr& r) throw() + {acquire(r);} + template linked_ptr& operator=(const linked_ptr& r) + { + if (this != &r) { + release(); + acquire(r); } + return *this; + } #endif // NO_MEMBER_TEMPLATES - X& operator*() const throw() {return *itsPtr;} - X* operator->() const throw() {return itsPtr;} - X* get() const throw() {return itsPtr;} - bool unique() const throw() {return itsPrev ? itsPrev==this : true;} + X& operator*() const throw() {return *itsPtr;} + X* operator->() const throw() {return itsPtr;} + X* get() const throw() {return itsPtr;} + bool unique() const throw() {return itsPrev ? itsPrev==this : true;} private: - X* itsPtr; - mutable const linked_ptr* itsPrev; - mutable const linked_ptr* itsNext; + X* itsPtr; + mutable const linked_ptr* itsPrev; + mutable const linked_ptr* itsNext; - void acquire(const linked_ptr& r) throw() - { // insert this to the list - itsPtr = r.itsPtr; - itsNext = r.itsNext; - itsNext->itsPrev = this; - itsPrev = &r; + void acquire(const linked_ptr& r) throw() + { // insert this to the list + itsPtr = r.itsPtr; + itsNext = r.itsNext; + itsNext->itsPrev = this; + itsPrev = &r; #ifndef mutable - r.itsNext = this; + r.itsNext = this; #else // for ANSI-challenged compilers - (const_cast*>(&r))->itsNext = this; + (const_cast*>(&r))->itsNext = this; #endif - } + } #ifndef NO_MEMBER_TEMPLATES - template void acquire(const linked_ptr& r) throw() - { // insert this to the list - itsPtr = r.itsPtr; - itsNext = r.itsNext; - itsNext->itsPrev = this; - itsPrev = &r; + template void acquire(const linked_ptr& r) throw() + { // insert this to the list + itsPtr = r.itsPtr; + itsNext = r.itsNext; + itsNext->itsPrev = this; + itsPrev = &r; #ifndef mutable - r.itsNext = this; + r.itsNext = this; #else // for ANSI-challenged compilers - (const_cast*>(&r))->itsNext = this; + (const_cast*>(&r))->itsNext = this; #endif - } + } #endif // NO_MEMBER_TEMPLATES - void release() - { // erase this from the list, delete if unique - if (unique()) delete itsPtr; - else { - itsPrev->itsNext = itsNext; - itsNext->itsPrev = itsPrev; - itsPrev = itsNext = 0; - } - itsPtr = 0; + void release() + { // erase this from the list, delete if unique + if (unique()) delete itsPtr; + else { + itsPrev->itsNext = itsNext; + itsNext->itsPrev = itsPrev; + itsPrev = itsNext = 0; } + itsPtr = 0; + } }; diff --git a/gfx/texture.cpp b/gfx/texture.cpp index af668de98c..62ebc8a681 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -134,16 +134,16 @@ bool Texture::Load(const char *filename) { } } else #endif - if (!strcmp("zim", &name[len-3])) { - if (!LoadZIM(name)) { - LoadXOR(); - return false; - } else { - return true; - } + if (!strcmp("zim", &name[len-3])) { + if (!LoadZIM(name)) { + LoadXOR(); + return false; + } else { + return true; } - LoadXOR(); - return false; + } + LoadXOR(); + return false; } #ifndef ANDROID From f794440d79d919e91ed56c0a9efe5a5e154d3711 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 26 Jul 2012 16:31:16 +0200 Subject: [PATCH 0085/1445] Remove debug code --- .../src/com/turboviking/libnative/NativeActivity.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index be456068c0..d0d920c369 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -183,7 +183,8 @@ public class NativeActivity extends Activity { addContentView(editText, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); */ - inputBox("Please ener a s", "", "Save"); + // inputBox("Please ener a s", "", "Save"); + // Toast.makeText(this, "Value: " + input.getText().toString(), Toast.LENGTH_LONG).show(); } @SuppressLint("NewApi") @@ -285,7 +286,7 @@ public class NativeActivity extends Activity { NativeApp.keyUp(3); return true; } - // All other keys retain their default behaviour. + // All other keys retain their default behavior. return false; } @@ -332,7 +333,6 @@ public class NativeActivity extends Activity { dlg.show(); if (inputBoxCancelled) return null; - // Toast.makeText(this, "Value: " + input.getText().toString(), Toast.LENGTH_LONG).show(); return input.getText().toString(); } @@ -344,12 +344,12 @@ public class NativeActivity extends Activity { Intent send = new Intent(Intent.ACTION_SENDTO); String uriText; uriText = "mailto:email@gmail.com" + - "?subject=Rollfish is..." + + "?subject=Your app is..." + "&body=great! Or?"; uriText = uriText.replace(" ", "%20"); Uri uri = Uri.parse(uriText); send.setData(uri); - startActivity(Intent.createChooser(send, "E-mail Henrik!")); + startActivity(Intent.createChooser(send, "E-mail the app author!")); } else if (command.equals("launchMarket")) { // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app // http://developer.android.com/guide/publishing/publishing.html#marketintent From 3b3f8242b02e63b1506f7a09a62ca821d6670718 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 26 Jul 2012 17:24:47 +0200 Subject: [PATCH 0086/1445] mouse->pointer --- android/app-android.cpp | 10 +++--- .../turboviking/libnative/NativeActivity.java | 2 +- base/NativeApp.h | 2 +- base/PCMain.cpp | 33 +++++++++++-------- base/mutex.h | 3 ++ input/gesture_detector.cpp | 6 ++-- input/input_state.h | 13 ++++---- native.vcxproj | 6 +++- 8 files changed, 44 insertions(+), 31 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 987f7c4b85..a8066b7d2c 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -252,15 +252,13 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch } float scaledX = (int)(x * dp_xscale); // why the (int) cast? float scaledY = (int)(y * dp_yscale); - input_state.mouse_x[pointerId] = scaledX; - input_state.mouse_y[pointerId] = scaledY; + input_state.pointer_x[pointerId] = scaledX; + input_state.pointer_y[pointerId] = scaledY; if (code == 1) { - input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; - input_state.mouse_down[pointerId] = true; + input_state.pointer_down[pointerId] = true; NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_DOWN); } else if (code == 2) { - input_state.mouse_last[pointerId] = input_state.mouse_down[pointerId]; - input_state.mouse_down[pointerId] = false; + input_state.pointer_down[pointerId] = false; NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_UP); } else { NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_MOVE); diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index d0d920c369..29bd884d06 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -335,7 +335,7 @@ public class NativeActivity extends Activity { return null; return input.getText().toString(); } - + public void processCommand(String command, String params) { if (command.equals("launchBrowser")) { Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); diff --git a/base/NativeApp.h b/base/NativeApp.h index e6c2dee743..6468f9541d 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -36,7 +36,7 @@ void NativeDeviceLost(); // Called ~sixty times a second, delivers the current input state. // Main thread. -void NativeUpdate(const InputState &input); +void NativeUpdate(InputState &input); // Delivers touch events "instantly", without waiting for the next frame so that NativeUpdate can deliver. // Useful for triggering audio events, saving a few ms. diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 8739633a48..d3d1c74e19 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -102,14 +102,22 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_buttons |= (1<pad_lstick_y=32000; - else if (keys['K']) input->pad_lstick_y=-32000; - if (keys['J']) input->pad_lstick_x=-32000; - else if (keys['L']) input->pad_lstick_x=32000; - if (keys['8']) input->pad_rstick_y=32000; - else if (keys['2']) input->pad_rstick_y=-32000; - if (keys['4']) input->pad_rstick_x=-32000; - else if (keys['6']) input->pad_rstick_x=32000; + if (keys[SDLK_i]) + input->pad_lstick_y=1; + else if (keys[SDLK_k]) + input->pad_lstick_y=-1; + if (keys[SDLK_j]) + input->pad_lstick_x=-1; + else if (keys[SDLK_l]) + input->pad_lstick_x=1; + if (keys[SDLK_KP8]) + input->pad_rstick_y=1; + else if (keys[SDLK_KP2]) + input->pad_rstick_y=-1; + if (keys[SDLK_KP4]) + input->pad_rstick_x=-1; + else if (keys[SDLK_KP6]) + input->pad_rstick_x=1; } extern void mixaudio(void *userdata, Uint8 *stream, int len) { @@ -251,19 +259,19 @@ int main(int argc, char *argv[]) { quitRequested = 1; } } else if (event.type == SDL_MOUSEMOTION) { - input_state.mouse_x[0] = mx; - input_state.mouse_y[0] = my; + input_state.pointer_x[0] = mx; + input_state.pointer_y[0] = my; NativeTouch(0, mx, my, 0, TOUCH_MOVE); } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { //input_state.mouse_buttons_down = 1; - input_state.mouse_down[0] = true; + input_state.pointer_down[0] = true; nextFrameMD = true; NativeTouch(0, mx, my, 0, TOUCH_DOWN); } } else if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { - input_state.mouse_down[0] = false; + input_state.pointer_down[0] = false; nextFrameMD = false; //input_state.mouse_buttons_up = 1; NativeTouch(0, mx, my, 0, TOUCH_UP); @@ -274,7 +282,6 @@ int main(int argc, char *argv[]) { if (quitRequested) break; - input_state.mouse_last[0] = input_state.mouse_down[0]; const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); if (keys[SDLK_ESCAPE]) break; diff --git a/base/mutex.h b/base/mutex.h index 6700cc7f1f..ebceda318b 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -11,6 +11,7 @@ #include #endif +#include "base/basictypes.h" class recursive_mutex { #ifdef _WIN32 @@ -33,6 +34,7 @@ public: pthread_mutex_destroy(&mut_); #endif } + bool trylock() { #ifdef _WIN32 return TryEnterCriticalSection(&mut_) == TRUE; @@ -57,6 +59,7 @@ public: private: mutexType mut_; + DISALLOW_COPY_AND_ASSIGN(recursive_mutex); }; class lock_guard { diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 6494553a76..f2ec3a81d4 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -27,10 +27,10 @@ static Finger fingers[MAX_FINGERS]; void update(const InputState &state) { // Mouse / 1-finger-touch control. - if (state.mouse_down[0]) { + if (state.pointer_down[0]) { fingers[0].down = true; - fingers[0].downX = state.mouse_x[0]; - fingers[0].downY = state.mouse_y[0]; + fingers[0].downX = state.pointer_x[0]; + fingers[0].downY = state.pointer_y[0]; } else { fingers[0].down = false; } diff --git a/input/input_state.h b/input/input_state.h index 8cce30920e..46d8244bd2 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -34,8 +34,7 @@ struct InputState { pad_buttons_up(0), mouse_valid(false), accelerometer_valid(false) { - memset(mouse_down, 0, sizeof(mouse_down)); - memset(mouse_last, 0, sizeof(mouse_last)); + memset(pointer_down, 0, sizeof(pointer_down)); } // Gamepad style input @@ -54,14 +53,16 @@ struct InputState { // There are up to 8 mice / fingers. volatile bool mouse_valid; - int mouse_x[MAX_POINTERS]; - int mouse_y[MAX_POINTERS]; - bool mouse_down[MAX_POINTERS]; - bool mouse_last[MAX_POINTERS]; + int pointer_x[MAX_POINTERS]; + int pointer_y[MAX_POINTERS]; + bool pointer_down[MAX_POINTERS]; // Accelerometer bool accelerometer_valid; Vec3 acc; + +private: + DISALLOW_COPY_AND_ASSIGN(InputState); }; inline void UpdateInputState(InputState *input) { diff --git a/native.vcxproj b/native.vcxproj index 470181302e..d63c9800c5 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -76,6 +76,8 @@ true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) ..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + StreamingSIMDExtensions2 + Fast Windows @@ -226,7 +228,9 @@ - + + AssemblyAndSourceCode + From 04cdca530b48a70db4c18eafad001824ea2ab1d2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 26 Jul 2012 17:42:19 +0200 Subject: [PATCH 0087/1445] Add Android.mk that generates a static library, for convenience. --- Android.mk | 60 +++++++++++++++++++++++++++++++++++++++++++ ext/libzip/Android.mk | 1 + gfx/texture.cpp | 5 ---- 3 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 Android.mk diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000000..e602aa0971 --- /dev/null +++ b/Android.mk @@ -0,0 +1,60 @@ +# Basic Android.mk for libnative + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libnative +LOCAL_SRC_FILES :=\ + android/app-android.cpp \ + android/native_audio.cpp \ + audio/wav_read.cpp \ + audio/mixer.cpp.arm \ + base/buffer.cpp \ + base/display.cpp \ + base/timeutil.cpp \ + base/colorutil.cpp \ + base/error_context.cpp \ + base/stringutil.cpp \ + ext/sha1/sha1.cpp \ + ext/stb_vorbis/stb_vorbis.c.arm \ + ext/vjson/json.cpp \ + ext/vjson/block_allocator.cpp \ + file/dialog.cpp \ + file/fd_util.cpp \ + file/easy_file.cpp \ + file/chunk_file.cpp \ + file/file_util.cpp \ + file/zip_read.cpp \ + json/json_writer.cpp \ + math/math_util.cpp.arm \ + math/lin/aabb.cpp.arm \ + math/lin/plane.cpp.arm \ + math/lin/quat.cpp.arm \ + math/lin/vec3.cpp.arm \ + math/lin/matrix4x4.cpp.arm \ + midi/midi_input.cpp \ + net/http_client.cpp \ + net/resolve.cpp \ + profiler/profiler.cpp \ + gfx_es2/glsl_program.cpp \ + gfx_es2/draw_buffer.cpp.arm \ + gfx_es2/vertex_format.cpp \ + gfx/gl_debug_log.cpp \ + gfx/gl_lost_manager.cpp \ + gfx/texture.cpp \ + gfx/texture_atlas.cpp \ + gfx/texture_gen.cpp \ + image/zim_load.cpp \ + ui/ui.cpp \ + ui/screen.cpp \ + util/random/perlin.cpp + + +LOCAL_CFLAGS := -O2 -DANDROID_NDK -DUSE_GLES2 +LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x +LOCAL_LDLIBS := -lz +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip + + +include $(BUILD_STATIC_LIBRARY) diff --git a/ext/libzip/Android.mk b/ext/libzip/Android.mk index 34d8074f77..8973e1aaef 100644 --- a/ext/libzip/Android.mk +++ b/ext/libzip/Android.mk @@ -72,6 +72,7 @@ LOCAL_SRC_FILES :=\ zip_unchange_archive.c \ zip_unchange_data.c +LOCAL_CFLAGS := -O2 LOCAL_LDLIBS := -lz include $(BUILD_STATIC_LIBRARY) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 62ebc8a681..d0724e4f60 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -1,12 +1,7 @@ #ifdef ANDROID -#ifdef USE_GLES2 #include #include #else -#include -#include -#endif -#else #include #if defined(__APPLE__) #include From b8cafe15610fdd7e6180e0d9d56a489679f9f2ad Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 6 Aug 2012 22:05:24 +0200 Subject: [PATCH 0088/1445] cleanup --- Android.mk | 3 +- .../turboviking/libnative/NativeActivity.java | 2 - base/linked_ptr.h | 65 ++----------------- native.vcxproj | 1 + native.vcxproj.filters | 1 + 5 files changed, 10 insertions(+), 62 deletions(-) diff --git a/Android.mk b/Android.mk index e602aa0971..a3ace6630b 100644 --- a/Android.mk +++ b/Android.mk @@ -6,7 +6,6 @@ include $(CLEAR_VARS) LOCAL_MODULE := libnative LOCAL_SRC_FILES :=\ - android/app-android.cpp \ android/native_audio.cpp \ audio/wav_read.cpp \ audio/mixer.cpp.arm \ @@ -51,7 +50,7 @@ LOCAL_SRC_FILES :=\ util/random/perlin.cpp -LOCAL_CFLAGS := -O2 -DANDROID_NDK -DUSE_GLES2 +LOCAL_CFLAGS := -O2 LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 29bd884d06..cc671d15c5 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -90,8 +90,6 @@ public class NativeActivity extends Activity { public static String installID; - private EditText editText; - String getApplicationLibraryDir(ApplicationInfo application) { String libdir = null; try { diff --git a/base/linked_ptr.h b/base/linked_ptr.h index df5ab97443..df359d837c 100644 --- a/base/linked_ptr.h +++ b/base/linked_ptr.h @@ -11,31 +11,13 @@ #pragma once -/* For ANSI-challenged compilers, you may want to #define -* NO_MEMBER_TEMPLATES, explicit or mutable */ - -#define NO_MEMBER_TEMPLATES - template class linked_ptr { public: + explicit linked_ptr(X* p = 0) throw() : itsPtr(p) {itsPrev = itsNext = this;} + ~linked_ptr() {release();} + linked_ptr(const linked_ptr& r) throw() {acquire(r);} -#ifndef NO_MEMBER_TEMPLATES -# define TEMPLATE_FUNCTION template - TEMPLATE_FUNCTION friend class linked_ptr; -#else -# define TEMPLATE_FUNCTION - typedef X Y; -#endif - - typedef X element_type; - - explicit linked_ptr(X* p = 0) throw() - : itsPtr(p) {itsPrev = itsNext = this;} - ~linked_ptr() - {release();} - linked_ptr(const linked_ptr& r) throw() - {acquire(r);} linked_ptr& operator=(const linked_ptr& r) { if (this != &r) { @@ -45,24 +27,10 @@ public: return *this; } -#ifndef NO_MEMBER_TEMPLATES - template friend class linked_ptr; - template linked_ptr(const linked_ptr& r) throw() - {acquire(r);} - template linked_ptr& operator=(const linked_ptr& r) - { - if (this != &r) { - release(); - acquire(r); - } - return *this; - } -#endif // NO_MEMBER_TEMPLATES - - X& operator*() const throw() {return *itsPtr;} - X* operator->() const throw() {return itsPtr;} - X* get() const throw() {return itsPtr;} - bool unique() const throw() {return itsPrev ? itsPrev==this : true;} + X& operator*() const throw() {return *itsPtr;} + X* operator->() const throw() {return itsPtr;} + X* get() const throw() {return itsPtr;} + bool unique() const throw() {return itsPrev ? itsPrev==this : true;} private: X* itsPtr; @@ -75,28 +43,9 @@ private: itsNext = r.itsNext; itsNext->itsPrev = this; itsPrev = &r; -#ifndef mutable r.itsNext = this; -#else // for ANSI-challenged compilers - (const_cast*>(&r))->itsNext = this; -#endif } -#ifndef NO_MEMBER_TEMPLATES - template void acquire(const linked_ptr& r) throw() - { // insert this to the list - itsPtr = r.itsPtr; - itsNext = r.itsNext; - itsNext->itsPrev = this; - itsPrev = &r; -#ifndef mutable - r.itsNext = this; -#else // for ANSI-challenged compilers - (const_cast*>(&r))->itsNext = this; -#endif - } -#endif // NO_MEMBER_TEMPLATES - void release() { // erase this from the list, delete if unique if (unique()) delete itsPtr; diff --git a/native.vcxproj b/native.vcxproj index d63c9800c5..9c4ef3e443 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -90,6 +90,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index a9609633e4..6760be9210 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -8,6 +8,7 @@ base + From e64a1594077786688e957f141304e1709ef1b031 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 8 Aug 2012 00:10:34 +0200 Subject: [PATCH 0089/1445] basic events --- base/basictypes.h | 3 ++ base/display.cpp | 1 + base/mutex.h | 74 ++++++++++++++++++++++++++++++++++++++++++----- base/threadutil.h | 37 +++++++++++++++++++++++- net/resolve.cpp | 5 +++- 5 files changed, 111 insertions(+), 9 deletions(-) diff --git a/base/basictypes.h b/base/basictypes.h index 421d69aa88..e0bb39e3a7 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -87,4 +87,7 @@ inline uint64 swap64(const uint8* _pData) {return swap64(*(const uint64*)_pData) #define __THREAD __thread #endif +// For really basic windows code compat +typedef char TCHAR; + #endif // _BASE_BASICTYPES diff --git a/base/display.cpp b/base/display.cpp index 0955677943..bc0b73ef56 100644 --- a/base/display.cpp +++ b/base/display.cpp @@ -2,6 +2,7 @@ int dp_xres; int dp_yres; + int pixel_xres; int pixel_yres; diff --git a/base/mutex.h b/base/mutex.h index ebceda318b..d4f7d9b9da 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -6,6 +6,17 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include + +// Zap stupid windows defines +// Should move these somewhere clever. +#undef p +#undef MIN +#undef MAX +#undef min +#undef max +#undef DrawText +#undef itoa + #else #include #include @@ -57,6 +68,10 @@ public: #endif } + mutexType &native_handle() { + return mut_; + } + private: mutexType mut_; DISALLOW_COPY_AND_ASSIGN(recursive_mutex); @@ -71,10 +86,55 @@ private: recursive_mutex &mtx_; }; -#undef p -#undef MIN -#undef MAX -#undef min -#undef max -#undef DrawText -#undef itoa \ No newline at end of file + +// Like a Windows event, or a modern condition variable. + +class event { +public: +#ifdef _WIN32 +#else +#endif + event() { +#ifdef _WIN32 + event_ = CreateEvent(0, FALSE, FALSE, 0); +#else + pthread_cond_init(&event_, NULL); +#endif + } + ~event() { +#ifdef _WIN32 + CloseHandle(event_); +#else + pthread_cond_destroy(&event_); +#endif + } + + void notify_one() { +#ifdef _WIN32 + SetEvent(event_); +#else + pthread_cond_signal(&event_); +#endif + } + + // notify_all is not really possible to implement with win32 events? + + void wait(recursive_mutex &mtx) { + // broken +#ifdef _WIN32 + //mtx.unlock(); + WaitForSingleObject(event_, INFINITE); + ResetEvent(event_); // necessary? + // mtx.lock(); +#else + pthread_cond_wait(&event_, &mtx.native_handle()); +#endif + } + +private: +#ifdef _WIN32 + HANDLE event_; +#else + pthread_cond_t event_; +#endif +}; \ No newline at end of file diff --git a/base/threadutil.h b/base/threadutil.h index 15e6a477d1..fe8d9bac00 100644 --- a/base/threadutil.h +++ b/base/threadutil.h @@ -1,3 +1,38 @@ #pragma once -void setCurrentThreadName(const char *name); \ No newline at end of file +#include + +#ifdef _WIN32 +#include +#else + +#include + +#ifndef _POSIX_THREADS +#error unsupported platform (no pthreads?) +#endif + +#include + +#endif + +void setCurrentThreadName(const char *name); + +/* +class thread { +private: +#ifdef _WIN32 + typedef HANDLE thread_; +#else + typedef pthread_t thread_; +#endif + +public: + //void run(std::function threadFunc) { + // func_ = + //} + + void wait() { + + } +};*/ \ No newline at end of file diff --git a/net/resolve.cpp b/net/resolve.cpp index 9d56f38e54..725173dc4e 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -1,4 +1,4 @@ -#include "net/resolve.h" + #include "net/resolve.h" #include #include @@ -8,9 +8,12 @@ #ifndef _WIN32 #include #include // gethostbyname +#include #else #include #include +#undef min +#undef max #endif From a757fa2c99568c0a2dd9d30ffbdaba78e61ae4da Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 12 Aug 2012 15:12:23 +0200 Subject: [PATCH 0090/1445] Add x64 crash --- base/logging.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/base/logging.h b/base/logging.h index 435e72a8a5..915a52163b 100644 --- a/base/logging.h +++ b/base/logging.h @@ -12,11 +12,18 @@ // Logging #ifdef _WIN32 +#undef Crash + +#ifdef _M_X64 +inline void Crash() { DebugBreak(); } +#else inline void Crash() { __asm { int 3 }; } +#endif #else #ifdef ANDROID +#undef Crash inline void Crash() { char *p = (char *)1337; From 49a79dc568eba8567d60cc29f148266f7b19f6c6 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 12 Aug 2012 20:50:12 +0200 Subject: [PATCH 0091/1445] porta fixes --- base/basictypes.h | 2 ++ base/mutex.h | 4 +--- input/input_state.h | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/base/basictypes.h b/base/basictypes.h index e0bb39e3a7..083100b89f 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -88,6 +88,8 @@ inline uint64 swap64(const uint8* _pData) {return swap64(*(const uint64*)_pData) #endif // For really basic windows code compat +#ifndef TCHAR typedef char TCHAR; +#endif #endif // _BASE_BASICTYPES diff --git a/base/mutex.h b/base/mutex.h index d4f7d9b9da..5679eecf1f 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -22,8 +22,6 @@ #include #endif -#include "base/basictypes.h" - class recursive_mutex { #ifdef _WIN32 typedef CRITICAL_SECTION mutexType; @@ -74,7 +72,7 @@ public: private: mutexType mut_; - DISALLOW_COPY_AND_ASSIGN(recursive_mutex); + recursive_mutex(const recursive_mutex &other); }; class lock_guard { diff --git a/input/input_state.h b/input/input_state.h index 46d8244bd2..0e609e89d5 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -2,6 +2,7 @@ #include "math/lin/vec3.h" #include "base/mutex.h" +#include "base/basictypes.h" enum { PAD_BUTTON_A = 1, From 9303c13cbe34e090c48e45e4be60d83befa12951 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 13 Aug 2012 00:41:24 +0200 Subject: [PATCH 0092/1445] Pass external dir to native apps --- android/app-android.cpp | 2 +- base/NativeApp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index a8066b7d2c..83d7461399 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -133,7 +133,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init NativeGetAppInfo(&app_name, &app_nice_name, &landscape); const char *argv[2] = {app_name.c_str(), 0}; - NativeInit(1, argv, user_data_path.c_str(), installID.c_str()); + NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); use_native_audio = juseNativeAudio; if (use_native_audio) { diff --git a/base/NativeApp.h b/base/NativeApp.h index 6468f9541d..c567b1d9a1 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -24,7 +24,7 @@ bool NativeIsAtTopLevel(); // The very first function to be called after NativeGetAppInfo. Even NativeMix is not called // before this, although it may be called at any point in time afterwards (on any thread!) // This functions must NOT call OpenGL. Main thread. -void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *installID); +void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *external_directory, const char *installID); // Runs after NativeInit() at some point. May (and probably should) call OpenGL. void NativeInitGraphics(); From 45949ac0087c5a8614492bc2b54ba9d588f2f6f2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 13 Aug 2012 20:11:24 +0200 Subject: [PATCH 0093/1445] ConstString --- base/stringutil.h | 19 +++++++++++++++++++ gfx_es2/glsl_program.h | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/base/stringutil.h b/base/stringutil.h index 59b1d0d03d..7cc61b3086 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -34,3 +34,22 @@ inline void StringToHexString(const std::string &data, std::string *output) { // highly unsafe and not recommended. unsigned int parseHex(const char* _szValue); + + +// Suitable for inserting into maps, unlike char*, and cheaper than std::string. +// Strings must be constant and preferably be stored in the read-only part +// of the binary. +class ConstString { +public: + ConstString(const char *ptr) { + ptr_ = ptr; + } + bool operator <(const ConstString &other) const { + return strcmp(ptr_, other.ptr_) < 0; + } + bool operator ==(const ConstString &other) const { + return ptr_ == other.ptr_ || !strcmp(ptr_, other.ptr_); + } +private: + const char *ptr_; +}; diff --git a/gfx_es2/glsl_program.h b/gfx_es2/glsl_program.h index 58392f64d2..2d5f0adc0a 100644 --- a/gfx_es2/glsl_program.h +++ b/gfx_es2/glsl_program.h @@ -16,6 +16,7 @@ #endif #endif +#include #include #include "gfx/gl_lost_manager.h" @@ -54,6 +55,9 @@ struct GLSLProgram : public GfxResourceHolder { void GLLost(); }; + +// C API, old skool + GLSLProgram *glsl_create(const char *vshader_file, const char *fshader_file); void glsl_destroy(GLSLProgram *program); From f79111b217a9e6e47e2425db409124f6d8027379 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 27 Aug 2012 23:28:52 +0200 Subject: [PATCH 0094/1445] Allow creating shaders from source strings directly --- base/basictypes.h | 3 ++- gfx_es2/glsl_program.cpp | 58 +++++++++++++++++++++++++++++++--------- gfx_es2/glsl_program.h | 5 ++++ ui/screen.h | 2 ++ 4 files changed, 55 insertions(+), 13 deletions(-) diff --git a/base/basictypes.h b/base/basictypes.h index 083100b89f..4f73add10f 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -52,8 +52,9 @@ typedef intptr_t ssize_t; #endif // _WIN32 // Byteswapping - +#ifndef ARRAY_SIZE #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) +#endif inline uint8 swap8(uint8 _data) {return _data;} diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index ea94ca8acc..82c1320da5 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -50,12 +50,35 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader) { program->program_ = 0; program->vsh_ = 0; program->fsh_ = 0; + program->vshader_source = 0; + program->fshader_source = 0; strcpy(program->name, vshader + strlen(vshader) - 15); strcpy(program->vshader_filename, vshader); strcpy(program->fshader_filename, fshader); if (glsl_recompile(program)) { active_programs.insert(program); } + else + { + FLOG("Failed building GLSL program: %s %s", vshader, fshader); + } + register_gl_resource_holder(program); + return program; +} + +GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src) { + GLSLProgram *program = new GLSLProgram(); + program->program_ = 0; + program->vsh_ = 0; + program->fsh_ = 0; + program->vshader_source = vshader_src; + program->fshader_source = fshader_src; + strcpy(program->name, "[srcshader]"); + strcpy(program->vshader_filename, ""); + strcpy(program->fshader_filename, ""); + if (glsl_recompile(program)) { + active_programs.insert(program); + } register_gl_resource_holder(program); return program; } @@ -93,28 +116,37 @@ bool glsl_recompile(GLSLProgram *program) { program->fshader_mtime = fs.st_mtime; else program->fshader_mtime = 0; + + char *vsh_src = 0, *fsh_src = 0; - size_t sz; - char *vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz); - if (!vsh_src) { - ELOG("File missing: %s", vsh_src); - return false; + if (!program->vshader_source) + { + size_t sz; + vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz); + if (!vsh_src) { + ELOG("File missing: %s", program->vshader_filename); + return false; + } } - char *fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz); - if (!fsh_src) { - ELOG("File missing: %s", fsh_src); - delete [] vsh_src; - return false; + if (!program->fshader_source) + { + size_t sz; + fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz); + if (!fsh_src) { + ELOG("File missing: %s", program->fshader_filename); + delete [] vsh_src; + return false; + } } GLuint vsh = glCreateShader(GL_VERTEX_SHADER); - const GLchar *vsh_str = (const GLchar *)(vsh_src); + const GLchar *vsh_str = program->vshader_source ? program->vshader_source : (const GLchar *)(vsh_src); if (!CompileShader(vsh_str, vsh, program->vshader_filename)) { return false; } delete [] vsh_src; - const GLchar *fsh_str = (const GLchar *)(fsh_src); + const GLchar *fsh_str = program->fshader_source ? program->fshader_source : (const GLchar *)(fsh_src); GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); if (!CompileShader(fsh_str, fsh, program->fshader_filename)) { glDeleteShader(vsh); @@ -138,6 +170,8 @@ bool glsl_recompile(GLSLProgram *program) { glGetProgramInfoLog(prog, bufLength, NULL, buf); FLOG("Could not link program:\n %s", buf); delete [] buf; // we're dead! + } else { + FLOG("Could not link program."); } glDeleteShader(vsh); glDeleteShader(fsh); diff --git a/gfx_es2/glsl_program.h b/gfx_es2/glsl_program.h index 2d5f0adc0a..5ebbd03dac 100644 --- a/gfx_es2/glsl_program.h +++ b/gfx_es2/glsl_program.h @@ -28,6 +28,8 @@ struct GLSLProgram : public GfxResourceHolder { char name[16]; char vshader_filename[256]; char fshader_filename[256]; + const char *vshader_source; + const char *fshader_source; time_t vshader_mtime; time_t fshader_mtime; @@ -58,7 +60,10 @@ struct GLSLProgram : public GfxResourceHolder { // C API, old skool +// From files (VFS) GLSLProgram *glsl_create(const char *vshader_file, const char *fshader_file); +// Directly from source code +GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src); void glsl_destroy(GLSLProgram *program); // If recompilation of the program fails, the program is untouched and error messages diff --git a/ui/screen.h b/ui/screen.h index e2637599ff..57a92ca443 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -14,6 +14,7 @@ #pragma once #include + #include "base/basictypes.h" #include "base/display.h" @@ -25,6 +26,7 @@ public: virtual ~Screen(); virtual void update(const InputState &input) = 0; virtual void render() {} + virtual void dialogFinished(const Screen &dialog) {} private: DISALLOW_COPY_AND_ASSIGN(Screen); From 32031a255e59df978bffc938c1cd1fc13a6d57b2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 28 Aug 2012 13:18:21 +0200 Subject: [PATCH 0095/1445] warn fix --- gfx_es2/draw_buffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 38ac6f958e..d51b53fbec 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -265,7 +265,7 @@ void DrawBuffer::DrawImage2GridH(int atlas_image, float x1, float y1, float x2, void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { const AtlasFont &atlasfont = *atlas->fonts[font]; unsigned char cval; - float wacc = 0, maxh = 0; + float wacc = 0; int lines = 1; while ((cval = *text++) != '\0') { if (cval < 32) continue; From 3a533ad74ca90020c0d76cb1468921f729ec14b3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 29 Aug 2012 13:46:28 +0200 Subject: [PATCH 0096/1445] Misc --- audio/mixer.cpp | 3 +- base/logging.h | 2 +- ext/stb_vorbis/stb_vorbis.c | 1 + image/png_load.cpp | 3 ++ native.vcxproj | 88 +++++++++++++++++++++++++++++++++++++ native.vcxproj.filters | 6 +++ 6 files changed, 101 insertions(+), 2 deletions(-) diff --git a/audio/mixer.cpp b/audio/mixer.cpp index 2b3ed7490d..cd6ba8270e 100644 --- a/audio/mixer.cpp +++ b/audio/mixer.cpp @@ -90,7 +90,8 @@ static int get_free_channel(Mixer *mixer) { Clip *clip_load(const char *filename) { short *data; - int num_samples, sample_rate, num_channels; + int num_samples; + int sample_rate, num_channels; if (!strcmp(filename + strlen(filename) - 4, ".ogg")) { // Ogg file. For now, directly decompress, no streaming support. diff --git a/base/logging.h b/base/logging.h index 915a52163b..5d716a1448 100644 --- a/base/logging.h +++ b/base/logging.h @@ -15,7 +15,7 @@ #undef Crash #ifdef _M_X64 -inline void Crash() { DebugBreak(); } +inline void Crash() { /*DebugBreak();*/ } #else inline void Crash() { __asm { int 3 }; } #endif diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index a51aecc5b7..f3457bc20e 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -13,6 +13,7 @@ #pragma warning (disable:4996) +#pragma warning (disable:4244) // Todo: // diff --git a/image/png_load.cpp b/image/png_load.cpp index 8be085d624..6959ef03ff 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -1,3 +1,4 @@ +#ifdef PNG_AVAILABLE #include #include #include @@ -89,3 +90,5 @@ int pngLoad(const char *file, int *pwidth, *image_data_ptr = image_data; return 1; } + +#endif \ No newline at end of file diff --git a/native.vcxproj b/native.vcxproj index 9c4ef3e443..9dcf9b895f 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + {E8B58922-9827-493D-81E0-4B6E6BD77171} @@ -21,34 +29,63 @@ true MultiByte + + StaticLibrary + true + MultiByte + StaticLibrary false false MultiByte + + StaticLibrary + false + false + MultiByte + + + + + + + D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + + D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib + + D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib + D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + + D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib + + D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib + @@ -66,6 +103,23 @@ Ws2_32.lib + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + + + Windows + true + + + Ws2_32.lib + + Level3 @@ -89,6 +143,29 @@ Ws2_32.lib + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + StreamingSIMDExtensions2 + Fast + + + Windows + true + true + true + + + Ws2_32.lib + + @@ -115,6 +192,7 @@ + @@ -166,15 +244,21 @@ true + true true + true true + true true + true true + true true + true @@ -184,6 +268,7 @@ + @@ -193,7 +278,9 @@ true + true true + true @@ -231,6 +318,7 @@ AssemblyAndSourceCode + AssemblyAndSourceCode diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 6760be9210..e888ac3e0a 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -209,6 +209,9 @@ util + + base + @@ -373,6 +376,9 @@ util + + base + From c1d198914cef9fa61999c99d3913165e16eb8379 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 31 Aug 2012 12:11:11 +0200 Subject: [PATCH 0097/1445] Minor fixes --- base/PCMain.cpp | 2 +- ext/stb_vorbis/stb_vorbis.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index d3d1c74e19..c6788ad484 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -208,7 +208,7 @@ int main(int argc, char *argv[]) { } #endif - NativeInit(argc, (const char **)argv, path, "BADCOFFEE"); + NativeInit(argc, (const char **)argv, path, "", "BADCOFFEE"); float density = 1.0f; dp_xres = (float)pixel_xres * density / zoom; diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index a51aecc5b7..bc4469ddb2 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -11,8 +11,9 @@ // Get the latest version and other information at: // http://nothings.org/stb_vorbis/ - +#ifdef _MSC_VER #pragma warning (disable:4996) +#endif // Todo: // @@ -487,7 +488,7 @@ extern int my_prof(int slot); //#define stb_prof my_prof #ifndef stb_prof -#define stb_prof(x) 0 +#define stb_prof(x) {} #endif #if defined(STB_VORBIS_NO_PUSHDATA_API) @@ -1146,9 +1147,10 @@ static int next_segment(vorb *f) static int get8_packet_raw(vorb *f) { - if (!f->bytes_in_seg) + if (!f->bytes_in_seg){ if (f->last_seg) return EOP; else if (!next_segment(f)) return EOP; + } assert(f->bytes_in_seg > 0); --f->bytes_in_seg; ++f->packet_bytes; From 743631c217fe2419a478d19fe8740d2968616c30 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 1 Sep 2012 15:16:23 +0200 Subject: [PATCH 0098/1445] Warning fixes. add comments about OpenGL 3 context in SDL. --- base/PCMain.cpp | 9 +++++++++ ext/stb_vorbis/stb_vorbis.c | 31 +++---------------------------- 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 24f7bd60b8..6c0610c4b8 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -15,6 +15,7 @@ #include "SDL/SDL.h" #include "SDL/SDL_timer.h" #include "SDL/SDL_audio.h" +#include "SDL/SDL_video.h" #include "base/display.h" #include "base/logging.h" @@ -158,6 +159,13 @@ int main(int argc, char *argv[]) { net::Init(); +#ifdef __APPLE__ + // Make sure to request a somewhat modern GL context at least - the + // latest supported by MacOSX (really, really sad...) + // Requires SDL 2.0 (which is even more sad, as that hasn't been released yet) + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); +#endif if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); @@ -174,6 +182,7 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); + if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, SDL_OPENGL) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index 9beb5b1cc8..7b3c69ca6f 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -1202,14 +1202,6 @@ static uint32 get_bits(vorb *f, int n) return z; } -static int32 get_bits_signed(vorb *f, int n) -{ - uint32 z = get_bits(f, n); - if (z & (1 << (n-1))) - z += ~((1 << n) - 1); - return (int32) z; -} - // @OPTIMIZE: primary accumulator for huffman // expand the buffer to as many bits as possible without reading off end of packet // it might be nice to allow f->valid_bits and f->acc to be stored in registers, @@ -1293,23 +1285,6 @@ static int codebook_decode_scalar_raw(vorb *f, Codebook *c) return -1; } -static int codebook_decode_scalar(vorb *f, Codebook *c) -{ - int i; - if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH) - prep_huffman(f); - // fast huffman table lookup - i = f->acc & FAST_HUFFMAN_TABLE_MASK; - i = c->fast_huffman[i]; - if (i >= 0) { - f->acc >>= c->codeword_lengths[i]; - f->valid_bits -= c->codeword_lengths[i]; - if (f->valid_bits < 0) { f->valid_bits = 0; return -1; } - return i; - } - return codebook_decode_scalar_raw(f,c); -} - #ifndef STB_VORBIS_NO_INLINE_DECODE #define DECODE_RAW(var, f,c) \ @@ -2030,7 +2005,7 @@ void dct_iv_slow(float *buffer, int n) float mcos[16384]; float x[2048]; int i,j; - int n2 = n >> 1, nmask = (n << 3) - 1; + int nmask = (n << 3) - 1; memcpy(x, buffer, sizeof(*x) * n); for (i=0; i < 8*n; ++i) mcos[i] = (float) cos(M_PI / 4 * i / n); @@ -2282,7 +2257,6 @@ static __forceinline void iter_54(float *z) static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n) { - int k_off = -8; int a_off = base_n >> 3; float A2 = A[0+a_off]; float *z = e + i_off; @@ -4156,10 +4130,12 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) if (end) *end = stb_vorbis_get_file_offset(f); if (last) + { if (header[5] & 0x04) *last = 1; else *last = 0; + } set_file_offset(f, retry_loc-1); return 1; } @@ -4775,7 +4751,6 @@ static void compute_samples(int mask, short *output, int num_c, float **data, in } } -static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} }; static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len) { #define BUFFER_SIZE 32 From c5370b497b039a9b170f8bf8bfa6ad2734ce2656 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 17 Sep 2012 19:26:28 +0200 Subject: [PATCH 0099/1445] Fix bug in readWString --- base/PCMain.cpp | 10 +++++++--- base/fastlist.h | 2 ++ file/chunk_file.cpp | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 6c0610c4b8..c277bc1af9 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -209,12 +209,16 @@ int main(int argc, char *argv[]) { PathAppend(path, (app_name + "\\").c_str()); #else // Mac / Linux - const char *path = getenv("HOME"); - if (!path) { + char path[512]; + const char *the_path = getenv("HOME"); + if (!the_path) { struct passwd* pwd = getpwuid(getuid()); if (pwd) - path = pwd->pw_dir; + the_path = pwd->pw_dir; } + strcpy(path, the_path); + if (path[strlen(path)-1] != '/') + strcat(path, "/"); #endif NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); diff --git a/base/fastlist.h b/base/fastlist.h index 78ba4e5512..343f8c4afa 100644 --- a/base/fastlist.h +++ b/base/fastlist.h @@ -18,10 +18,12 @@ class InlineFastList { void Add(T t) { data_[count_++] = t; } + void RemoveAt(int index) { data_[index] = data_[count_ - 1]; count_--; } + void Remove(T t) { // Requires operator== for (int i = 0; i < count_; i++) { if (data_[i] == t) { diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index f8b991bfe7..09329d3a0d 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -239,7 +239,7 @@ static std::string fromUnicode(const uint16_t *src, int len) { std::string str; str.resize(len); for (int i=0; i 255 ? ' ' : i; + str[i] = src[i] > 255 ? ' ' : src[i]; } return str; } From 5b7c95d474bd1a56985a7e23bb552efff915c0fa Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 17 Sep 2012 20:45:15 +0200 Subject: [PATCH 0100/1445] Minor error message change --- gfx/gl_lost_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/gl_lost_manager.cpp b/gfx/gl_lost_manager.cpp index 3d87a204e9..e366d4c8b2 100644 --- a/gfx/gl_lost_manager.cpp +++ b/gfx/gl_lost_manager.cpp @@ -18,7 +18,7 @@ void unregister_gl_resource_holder(GfxResourceHolder *holder) { if (holders) { holders->remove(holder); } else { - WLOG("GL resource holder not initialized, cannot unregister resource"); + WLOG("GL resource holder not initialized or already shutdown, cannot unregister resource"); } } From 113f10abfe8e8a5b97af6999bf8209ba84df6d53 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 17 Sep 2012 21:21:34 +0200 Subject: [PATCH 0101/1445] FileInfo struct, not properly used yet. ui code cleaning --- file/file_util.cpp | 16 ++++++++-------- file/file_util.h | 9 ++++++++- ui/screen.h | 2 +- ui/ui.cpp | 26 ++++++++++++++------------ ui/ui.h | 27 ++++++++++++++++----------- 5 files changed, 47 insertions(+), 33 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index eeacc9ae55..90b3728b60 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -61,8 +61,7 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str) #ifndef METRO -size_t getFilesInDir(const char *directory, std::vector *files) -{ +size_t getFilesInDir(const char *directory, std::vector *files) { size_t foundEntries = 0; #ifdef _WIN32 // Find the first file in the directory. @@ -72,10 +71,9 @@ size_t getFilesInDir(const char *directory, std::vector *files) #else HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd); #endif - if (hFind == INVALID_HANDLE_VALUE) - { + if (hFind == INVALID_HANDLE_VALUE) { FindClose(hFind); - return foundEntries; + return 0; } // windows loop do @@ -98,8 +96,10 @@ size_t getFilesInDir(const char *directory, std::vector *files) ((virtualName[0] == '.') && (virtualName[1] == '.') && (virtualName[2] == '\0'))) continue; - - files->push_back(std::string(directory) + virtualName); + FileInfo info; + info.name = std::string(directory) + virtualName; + info.isDirectory = false; // TODO + files->push_back(info); #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); @@ -136,4 +136,4 @@ std::string getDir(const std::string &path) if (cutpath[i] == '\\') cutpath[i] = '/'; } return cutpath; -} \ No newline at end of file +} diff --git a/file/file_util.h b/file/file_util.h index d5d3e4450d..62202155a9 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -8,7 +8,14 @@ bool writeStringToFile(bool text_file, const std::string &str, const char *filen bool readFileToString(bool text_file, const char *filename, std::string &str); // Beginnings of a directory utility system. TODO: Improve. -size_t getFilesInDir(const char *directory, std::vector *files); + +struct FileInfo +{ + std::string name; + bool isDirectory; +}; + +size_t getFilesInDir(const char *directory, std::vector *files); void deleteFile(const char *file); std::string getDir(const std::string &path); diff --git a/ui/screen.h b/ui/screen.h index 57a92ca443..87d2b00b75 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -63,5 +63,5 @@ private: std::list dialog_; }; -// Yeah, an old school non enforced singleton. Good enough. +// Yeah, an old school non enforced singleton. Good enough (not?) extern ScreenManager screenManager; diff --git a/ui/ui.cpp b/ui/ui.cpp index d6a0df757d..1d7c8dec65 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -248,7 +248,7 @@ void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, boo ui_draw2d.DrawTextShadow(theme.uiFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); } -int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListState *state) { +int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { const int item_h = 64; int clicked = 0; @@ -262,12 +262,12 @@ int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListSta } // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. + // down, the user must have clicked a list item (unless after the last item). if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && - uistate.activeitem[i] == id && - state->selected != -1) { - clicked = 1; + uistate.hotitem[i] == id && + uistate.activeitem[i] == id && + selected != -1) { + clicked = 1; } } @@ -275,13 +275,15 @@ int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListSta int itemHeight = adapter->itemHeight(0); int numItems = adapter->getCount(); for (int i = 0; i < numItems; i++) { - int item_y = y + i * itemHeight - state->scrollY; - if (uistate.mousedown && adapter->itemEnabled(i) && item_y >= y - itemHeight && item_y <= y + h && - UIRegionHit(i, x, item_y, w, h, 0)) { - // ultra fast touch response - state->selected = i; + int item_y = y + i * itemHeight - scrollY; + if (uistate.mousedown && + adapter->itemEnabled(i) && + item_y >= y - itemHeight && + item_y <= y + h && + UIRegionHit(i, x, item_y, w, h, 0)) { + selected = i; } - adapter->drawItem(i, x, item_y, w, itemHeight, i == state->selected); + adapter->drawItem(i, x, item_y, w, itemHeight, i == selected); } uistate.lastwidget = id; diff --git a/ui/ui.h b/ui/ui.h index 78c16da1b5..2e4faed7e3 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -162,18 +162,12 @@ public: class StringVectorListAdapter : public UIListAdapter { public: - StringVectorListAdapter(std::vector *items) : items_(items) {} + StringVectorListAdapter(const std::vector *items) : items_(items) {} virtual size_t getCount() const { return items_->size(); } virtual void drawItem(int item, int x, int y, int w, int h, bool active) const; private: - std::vector *items_; -}; - -struct UIListState { - UIListState() : scrollY(0.0f), selected(-1) {} - float scrollY; - int selected; + const std::vector *items_; }; @@ -205,9 +199,20 @@ void UIText(int x, int y, const char *text, uint32_t color, float scale = 1.0f, // Slide choice, like the Angry Birds level selector. Not yet working. void UISlideChoice(int id, int y, const SlideItem *items, int numItems, UISlideState *state); -// List view. -// return -1 = no selection -int UIList(int id, int x, int y, int w, int h, UIListAdapter *adapter, UIListState *state); + +class UIList { + public: + UIList() : scrollY(0.0f), startDragY(0.0f), dragFinger(-1), selected(-1) {} + float scrollY; + float startDragY; + int dragFinger; + int selected; + // List view. + // return -1 = no selection + int Do(int id, int x, int y, int w, int h, UIListAdapter *adapter); + private: + DISALLOW_COPY_AND_ASSIGN(UIList); +}; // Call at end of frame. // Do this afterwards (or similar): From 01f2b5ada046719189fbc4ec2e3a20f17eee585f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 18 Sep 2012 09:46:58 +0200 Subject: [PATCH 0102/1445] Remove the screenManager global, other assorted cleanup --- base/NativeApp.h | 11 +++++++++++ math/CMakeLists.txt | 1 + ui/screen.cpp | 4 +--- ui/screen.h | 3 --- util/CMakeLists.txt | 15 +++++++++++++++ util/bits/varint.cpp | 6 +++--- util/bits/varint.h | 6 +++--- util/hash/hash.cpp | 2 +- 8 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 util/CMakeLists.txt diff --git a/base/NativeApp.h b/base/NativeApp.h index c567b1d9a1..c2e187b549 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -69,6 +69,17 @@ void NativeMix(short *audio, int num_samples); void NativeShutdownGraphics(); void NativeShutdown(); +// Called on app.onCreate and app.onDestroy (?). Tells the app to save/restore +// light state. If app was fully rebooted between these calls, it's okay if some minor +// state is lost (position in level) but the level currently playihg, or the song +// currently being edited, or whatever, should be restored properly. In this case, +// firstTime will be set so that appropriate action can be taken (or not taken when +// it's not set). +// +// Note that NativeRestore is always called on bootup. +void NativeRestoreState(bool firstTime); // onCreate +void NativeSaveState(); // onDestroy + // Calls back into Java / SDL // These APIs must be implemented by every port (for example app-android.cpp, PCMain.cpp). // You are free to call these. diff --git a/math/CMakeLists.txt b/math/CMakeLists.txt index b05acac409..6bd2d91ab2 100644 --- a/math/CMakeLists.txt +++ b/math/CMakeLists.txt @@ -2,6 +2,7 @@ set(SRCS lin/matrix4x4.cpp lin/vec3.cpp lin/quat.cpp + lin/aabb.cpp ) set(SRCS ${SRCS}) diff --git a/ui/screen.cpp b/ui/screen.cpp index 548ae4fb58..4d9ebb9637 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -2,8 +2,6 @@ #include "input/input_state.h" #include "ui/screen.h" -ScreenManager screenManager; - Screen::Screen() { } Screen::~Screen() { } @@ -81,4 +79,4 @@ void ScreenManager::pop() { } else { ELOG("Can't push when no dialog is shown"); } -} \ No newline at end of file +} diff --git a/ui/screen.h b/ui/screen.h index 87d2b00b75..23472328fc 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -62,6 +62,3 @@ private: // Used for options, in-game menus and other things you expect to be able to back out from onto something. std::list dialog_; }; - -// Yeah, an old school non enforced singleton. Good enough (not?) -extern ScreenManager screenManager; diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt new file mode 100644 index 0000000000..3a05cb15bb --- /dev/null +++ b/util/CMakeLists.txt @@ -0,0 +1,15 @@ +set(SRCS + bits/bits.cpp + bits/varint.cpp + random/perlin.cpp + hash/hash.cpp +) + +set(SRCS ${SRCS}) + +add_library(util STATIC ${SRCS}) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) + diff --git a/util/bits/varint.cpp b/util/bits/varint.cpp index 8cd94d052c..fc29c069d1 100644 --- a/util/bits/varint.cpp +++ b/util/bits/varint.cpp @@ -2,7 +2,7 @@ namespace varint { -void Encode32(uint32 value, char **dest) { +void Encode32(uint32_t value, char **dest) { // Simple varint char *p = *dest; while (value > 127) { @@ -13,8 +13,8 @@ void Encode32(uint32 value, char **dest) { *dest = p; } -uint32 Decode32(const char **ptr) { - uint32 value = 0; +uint32_t Decode32(const char **ptr) { + uint32_t value = 0; const char *p = *ptr; while (true) { uint8 b = *p++; diff --git a/util/bits/varint.h b/util/bits/varint.h index aa7d3e8788..e2fdd20583 100644 --- a/util/bits/varint.h +++ b/util/bits/varint.h @@ -1,12 +1,12 @@ #ifndef _UTIL_BITS_VARINT #define _UTIL_BITS_VARINT -#include "base/base.h" +#include "base/basictypes.h" namespace varint { -void Encode32(uint32 value, char **dest); -uint32 Decode32(const char **ptr); +void Encode32(uint32_t value, char **dest); +uint32_t Decode32(const char **ptr); } // namespace varint diff --git a/util/hash/hash.cpp b/util/hash/hash.cpp index 264450dabe..277509ac89 100644 --- a/util/hash/hash.cpp +++ b/util/hash/hash.cpp @@ -1,4 +1,4 @@ -#include "base/base.h" +#include "base/basictypes.h" #include "util/hash/hash.h" namespace hash { From 1c1889c726a93542e840c61dd4ac8da11bbcfbec Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 28 Sep 2012 10:01:01 +0200 Subject: [PATCH 0103/1445] WIP --- android/app-android.cpp | 3 +- android/native-audio-so.cpp | 3 +- .../com/turboviking/libnative/NativeApp.java | 7 ++-- base/PCMain.cpp | 4 ++ ext/stb_vorbis/stb_vorbis.c | 1 - image/png_load.cpp | 1 + ui/screen.cpp | 42 +++++++++++++++++-- ui/screen.h | 15 +++++-- 8 files changed, 63 insertions(+), 13 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 83d7461399..3e3482843e 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -88,7 +88,8 @@ std::string GetJavaString(JNIEnv *env, jstring jstr) return cpp_string; } -extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) { +extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) +{ std::string app_name, app_nice_name; bool landscape; NativeGetAppInfo(&app_name, &app_nice_name, &landscape); diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index d6bdb0772c..93748e3695 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -49,8 +49,7 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { short *nextBuffer = buffer[curBuffer]; int nextSize = sizeof(buffer[0]); - SLresult result; - result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); + SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); // Comment from sample code: // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/turboviking/libnative/NativeApp.java index 420739f406..ee403238b2 100644 --- a/android/src/com/turboviking/libnative/NativeApp.java +++ b/android/src/com/turboviking/libnative/NativeApp.java @@ -1,11 +1,12 @@ package com.turboviking.libnative; public class NativeApp { - public static native boolean isLandscape(); - public static native boolean isAtTopLevel(); public static native void init( int xxres, int yyres, int dpi, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); + + public static native boolean isLandscape(); + public static native boolean isAtTopLevel(); // These have Android semantics: Resume is always called on bootup, after init public static native void pause(); @@ -24,4 +25,4 @@ public class NativeApp { public static native void accelerometer(float x, float y, float z); public static native void sendMessage(String msg, String arg); -} \ No newline at end of file +} \ No newline at end of file diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 6c0610c4b8..99add6aecd 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -217,7 +217,11 @@ int main(int argc, char *argv[]) { } #endif +#ifdef _WIN32 + NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE"); +#else NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); +#endif float density = 1.0f; dp_xres = (float)pixel_xres * density / zoom; diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index 7b3c69ca6f..019438ccbd 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -2016,7 +2016,6 @@ void dct_iv_slow(float *buffer, int n) //acc += x[j] * cos(M_PI / n * (i + 0.5) * (j + 0.5)); buffer[i] = acc; } - free(x); } void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) diff --git a/image/png_load.cpp b/image/png_load.cpp index 6959ef03ff..7c14dd489e 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -1,3 +1,4 @@ +#define PNG_AVAILABLE #ifdef PNG_AVAILABLE #include #include diff --git a/ui/screen.cpp b/ui/screen.cpp index 548ae4fb58..dbfd63a4e9 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -8,8 +8,8 @@ Screen::Screen() { } Screen::~Screen() { } ScreenManager::ScreenManager() { - currentScreen_=0; - nextScreen_=0; + currentScreen_ = 0; + nextScreen_ = 0; } ScreenManager::~ScreenManager() { @@ -17,6 +17,13 @@ ScreenManager::~ScreenManager() { } void ScreenManager::switchScreen(Screen *screen) { + if (dialog_.size()) + { + WLOG("Switching screens - dropping the whole dialog stack"); + while (dialog_.size()) + pop(); + } + // TODO: is this still true? // Note that if a dialog is found, this will be a silent background switch that // will only become apparent if the dialog is closed. The previous screen will stick around // until that switch. @@ -35,12 +42,14 @@ void ScreenManager::update(const InputState &input) { } if (nextScreen_) { + ILOG("Screen switch!"); Screen *temp = currentScreen_; currentScreen_ = nextScreen_; delete temp; temp = 0; nextScreen_ = 0; } + if (currentScreen_) { currentScreen_->update(input); } @@ -59,6 +68,13 @@ void ScreenManager::render() { } } +Screen *ScreenManager::topScreen() { + if (dialog_.size()) + return dialog_.back(); + else + return currentScreen_; +} + void ScreenManager::shutdown() { if (nextScreen_) { delete nextScreen_; @@ -81,4 +97,24 @@ void ScreenManager::pop() { } else { ELOG("Can't push when no dialog is shown"); } -} \ No newline at end of file +} + +void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) +{ + if (!dialog_.size()) { + ELOG("Must be in a dialog to finishDialog"); + return; + } + Screen *dlg = dialog_.back(); + if (dialog != dialog_.back()) + { + ELOG("Wrong dialog being finished!"); + return; + } + if (dialog_.size()) { + dialog_.pop_back(); + } + Screen *caller = topScreen(); + caller->dialogFinished(dialog, result); + delete dialog; +} diff --git a/ui/screen.h b/ui/screen.h index 57a92ca443..46189d9069 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -20,6 +20,13 @@ struct InputState; +enum DialogResult { + DR_OK, + DR_CANCEL, + DR_YES, + DR_NO, +}; + class Screen { public: Screen(); @@ -27,7 +34,7 @@ public: virtual void update(const InputState &input) = 0; virtual void render() {} - virtual void dialogFinished(const Screen &dialog) {} + virtual void dialogFinished(const Screen *dialog, DialogResult result) {} private: DISALLOW_COPY_AND_ASSIGN(Screen); }; @@ -51,9 +58,11 @@ public: void push(Screen *screen); // Pops the dialog away. - void pop(); - + void finishDialog(const Screen *dialog, DialogResult result = DR_OK); + private: + void pop(); + Screen *topScreen(); // Base screen. These don't "stack" and you can move in any order between them. Screen *currentScreen_; Screen *nextScreen_; From 46f7f29cec9027ab01a6558cd676cc2092c29fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 6 Oct 2012 12:28:20 +0200 Subject: [PATCH 0104/1445] Avoid LLVM warning --- base/color.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/color.h b/base/color.h index 3206c7f75a..5a382bc15a 100644 --- a/base/color.h +++ b/base/color.h @@ -3,7 +3,7 @@ typedef unsigned int Color; //have to use a define to ensure constant folding.. with an inline I don't get that, sucks -#define COLOR(i) (((i << 16) & 0xFF0000) | (i & 0xFF00) | ((i >> 16) & 0xFF) | 0xFF000000) +#define COLOR(i) (((i&0xFF) << 16) | (i & 0xFF00) | ((i & 0xFF0000) >> 16) | 0xFF000000) inline Color darkenColor(Color color) { return (color & 0xFF000000) | ((color >> 1)&0x7F7F7F); } @@ -13,4 +13,4 @@ inline Color whitenColor(Color color) { inline Color colorInterpol(Color x, Color y, int n) { // TODO return x; -} \ No newline at end of file +} From ad543fbf4e0a4c6a55377e9b777c0ba32c23e891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 6 Oct 2012 12:38:39 +0200 Subject: [PATCH 0105/1445] Add missing virtual destructor --- file/zip_read.h | 1 + 1 file changed, 1 insertion(+) diff --git a/file/zip_read.h b/file/zip_read.h index d42d1fec77..e0309d8a3a 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -15,6 +15,7 @@ uint8_t *ReadLocalFile(const char *filename, size_t *size); class AssetReader { public: + virtual ~AssetReader() {} // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; virtual std::string toString() const = 0; From c8814b0898332784c20acd95543fbea0a7ffb5ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Oct 2012 12:09:36 +0200 Subject: [PATCH 0106/1445] Update android target version --- android/project.properties | 2 +- android/src/com/turboviking/libnative/NativeActivity.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/android/project.properties b/android/project.properties index fec2d6168d..8996991a47 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt # Project target. -target=android-15 +target=android-16 android.library=true diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index cc671d15c5..2f37883e73 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -31,7 +31,6 @@ import android.view.Display; import android.view.Gravity; import android.view.KeyEvent; import android.view.View; -import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.EditText; From 652646119ebb1030590779bd21345129abbb3a39 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 26 Oct 2012 10:45:51 +0200 Subject: [PATCH 0107/1445] Add atlas and 'zim' texture tools. --- tools/.gitignore | 3 + tools/.project | 11 + tools/CMakeLists.txt | 47 ++ tools/README.txt | 3 + tools/atlastool.cpp | 643 ++++++++++++++++++++++++++ tools/atlastool/atlastool.vcxproj | 104 +++++ tools/audiotool.cpp | 17 + tools/b.sh | 3 + tools/zimtool.cpp | 98 ++++ tools/zimtool/zimtool.vcxproj | 102 ++++ tools/zimtool/zimtool.vcxproj.filters | 6 + 11 files changed, 1037 insertions(+) create mode 100644 tools/.gitignore create mode 100644 tools/.project create mode 100644 tools/CMakeLists.txt create mode 100644 tools/README.txt create mode 100644 tools/atlastool.cpp create mode 100644 tools/atlastool/atlastool.vcxproj create mode 100644 tools/audiotool.cpp create mode 100644 tools/b.sh create mode 100644 tools/zimtool.cpp create mode 100644 tools/zimtool/zimtool.vcxproj create mode 100644 tools/zimtool/zimtool.vcxproj.filters diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 0000000000..bed56d701d --- /dev/null +++ b/tools/.gitignore @@ -0,0 +1,3 @@ +Release +Debug +build diff --git a/tools/.project b/tools/.project new file mode 100644 index 0000000000..d48fc19492 --- /dev/null +++ b/tools/.project @@ -0,0 +1,11 @@ + + + tools + + + + + + + + diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000000..23e09fb98c --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 2.6) + +project (Tools) +find_package(PNG REQUIRED) + + + +add_definitions(-g) +add_definitions(-O2) +add_definitions(-Wall) +add_definitions(-DSDL) +add_definitions(-Wno-multichar) +add_definitions(-fno-strict-aliasing) +add_definitions(-fopenmp) +# add_definitions(-fstrict-aliasing) + +include_directories(../native) +include_directories(../native/base) +include_directories(../native/math/lin) +include_directories(../native/image) +include_directories(../native/ext/libzip) +include_directories(../native/ext/etcpack) +include_directories(/usr/local/include) +include_directories(${PNG_INCLUDE_DIR}) + +link_directories(/usr/X11R6/lib) +link_directories(/opt/local/lib) + +# Horrible horrible hack +include_directories(/usr/include/freetype2) +include_directories(/usr/local/include/freetype2) +include_directories(/opt/local/include/freetype2) + +add_subdirectory(../native/base base) +add_subdirectory(../native/gfx gfx) +add_subdirectory(../native/file file) +add_subdirectory(../native/image image) +add_subdirectory(../native/math math) +add_subdirectory(../native/ext/libzip libzip) +add_subdirectory(../native/ext/etcpack etcpack) + + +add_executable(atlastool atlastool.cpp) +target_link_libraries(atlastool ${PNG_LIBRARY} freetype z image etcpack etcdec file zip gomp) + +add_executable(zimtool zimtool.cpp) +target_link_libraries(zimtool ${PNG_LIBRARY} freetype z image etcpack etcdec file zip gomp) diff --git a/tools/README.txt b/tools/README.txt new file mode 100644 index 0000000000..f22674b841 --- /dev/null +++ b/tools/README.txt @@ -0,0 +1,3 @@ +These are simple tools to create the ZIM texture format and texture atlases based on it. + +Documentation is TODO but they are easy to use. \ No newline at end of file diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp new file mode 100644 index 0000000000..12a7f580e1 --- /dev/null +++ b/tools/atlastool.cpp @@ -0,0 +1,643 @@ +// Sprite packing method borrowed from glorp engine and heavily modified. +// For license safety, just run this as a build tool, don't build it into your game/program. +// https://github.com/zorbathut/glorp + +// data we need to provide: +// sx, sy +// dx, dy +// ox, oy +// wx + +// line height +// dist-per-pixel + +#include +#include +#include FT_FREETYPE_H +#include +#include +#include +#include +#include + +#include "image/png_load.h" +#include "image/zim_save.h" + +#define CHECK(x) if (!(x)) { printf("%i: CHECK failed on this line\n", __LINE__); exit(1); } + +using namespace std; +static int global_id; +static bool highcolor = false; + +enum Effect { + FX_COPY = 0, + FX_RED_TO_ALPHA_SOLID_WHITE = 1, // for alpha fonts + FX_RED_TO_INTENSITY_ALPHA_255 = 2, + FX_PREMULTIPLY_ALPHA = 3, + FX_PINK_TO_ALPHA = 4, // for alpha fonts + FX_INVALID = 5, +}; + +const char *effect_str[5] = { + "copy", "r2a", "r2i", "pre", "p2a", +}; + +Effect GetEffect(const char *text) { + for (int i = 0; i < 5; i++) { + if (!strcmp(text, effect_str[i])) { + return (Effect)i; + } + } + return FX_INVALID; +} + +template +struct Image { + vector > dat; + void resize(int x, int y) { + dat.resize(y); + for(int i = 0; i < y; i++) + dat[i].resize(x); + } + int width() const { + return (int)dat[0].size(); + } + int height() const { + return (int)dat.size(); + } + void copyfrom(const Image &img, int ox, int oy, int effect) { + CHECK(img.dat[0].size() + ox <= dat[0].size()); + CHECK(img.dat.size() + oy <= dat.size()); + for (int y = 0; y < (int)img.dat.size(); y++) { + for (int x = 0; x < (int)img.dat[y].size(); x++) { + switch (effect) { + case FX_COPY: + dat[y + oy][ox + x] = img.dat[y][x]; + break; + case FX_RED_TO_ALPHA_SOLID_WHITE: + dat[y + oy][ox + x] = 0x00FFFFFF | (img.dat[y][x] << 24); + break; + case FX_RED_TO_INTENSITY_ALPHA_255: + dat[y + oy][ox + x] = 0xFF000000 | img.dat[y][x] | (img.dat[y][x] << 8) | (img.dat[y][x] << 16); + break; + case FX_PREMULTIPLY_ALPHA: + { + unsigned int color = img.dat[y][x]; + unsigned int a = color >> 24; + unsigned int r = (color & 0xFF) * a >> 8, g = (color & 0xFF00) * a>> 8, b = (color & 0xFF0000) * a >> 8; + color = (color & 0xFF000000) | (r & 0xFF) | (g & 0xFF00) | (b & 0xFF0000); + // Simulate 4444 + color = color & 0xF0F0F0F0; + color |= color >> 4; + dat[y + oy][ox + x] = color; + break; + } + case FX_PINK_TO_ALPHA: + dat[y + oy][ox + x] = ((img.dat[y][x]&0xFFFFFF) == 0xFF00FF) ? 0x00FFFFFF : (img.dat[y][x] | 0xFF000000); + break; + default: + dat[y + oy][ox + x] = 0xFFFF00FF; + break; + } + } + } + } + void set(int sx, int sy, int ex, int ey, unsigned char fil) { + for(int y = sy; y < ey; y++) + fill(dat[y].begin() + sx, dat[y].begin() + ex, fil); + } + bool LoadPNG(const char *png_name) { + unsigned char *img_data; + int w, h; + if (1 != pngLoad(png_name, &w, &h, &img_data, false)) { + printf("Failed to load %s\n", png_name); + exit(1); + return false; + } + dat.resize(h); + for (int y = 0; y < h; y++) { + dat[y].resize(w); + memcpy(&dat[y][0], img_data + 4 * y * w, 4 * w); + } + free(img_data); + return true; + } + void SavePNG(const char *png_name) { + // Save PNG + FILE *fil = fopen(png_name, "wb"); + png_structp png_ptr; + png_infop info_ptr; + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + CHECK(png_ptr); + info_ptr = png_create_info_struct(png_ptr); + CHECK(info_ptr); + png_init_io(png_ptr, fil); + //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); + png_set_IHDR(png_ptr, info_ptr, dat[0].size(), dat.size(), 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_write_info(png_ptr, info_ptr); + for(int y = 0; y < (int)dat.size(); y++) { + png_write_row(png_ptr, (png_byte*)&dat[y][0]); + } + png_write_end(png_ptr, NULL); + png_destroy_write_struct(&png_ptr, &info_ptr); + } + void SaveZIM(const char *zim_name, int zim_format) { + uint8 *image_data = new uint8[width() * height() * 4]; + for (int y = 0; y < height(); y++) { + memcpy(image_data + y * width() * 4, &dat[y][0], width() * 4); + } + ::SaveZIM(zim_name, width(), height(), width() * 4, zim_format | ZIM_DITHER, image_data); + } +}; + +template +bool operator<(const Image &lhs, const Image &rhs) { + return lhs.dat.size() * lhs.dat[0].size() > rhs.dat.size() * rhs.dat[0].size(); +} + +struct Data { + // item ID + int id; + // dimensions of its spot in the world + int sx, sy, ex, ey; + // offset from the origin + float ox, oy; + // distance to move the origin forward + float wx; + + int effect; +}; + +bool operator<(const Data &lhs, const Data &rhs) { + return lhs.id < rhs.id; // should be unique +} + +string out_prefix; + +int NextPowerOf2(int x) { + int powof2 = 1; + // Double powof2 until >= val + while (powof2 < x) powof2 <<= 1; + return powof2; +} + +struct Bucket { + vector, Data> > items; + void AddItem(const Image &img, const Data &dat) { + items.push_back(make_pair(img, dat)); + } + vector Resolve(int image_width, Image &dest) { + // Place all the little images - whatever they are. + // Uses greedy fill algorithm. Slow but works surprisingly well, CPUs are fast. + Image masq; + masq.resize(image_width, 1); + dest.resize(image_width, 1); + sort(items.begin(), items.end()); + for(int i = 0; i < (int)items.size(); i++) { + int idx = items[i].first.dat[0].size(); + int idy = items[i].first.dat.size(); + CHECK(idx <= image_width); + bool found = false; + for(int ty = 0; ty < 2047 && !found; ty++) { + if(ty + idy + 1 > (int)dest.dat.size()) { + masq.resize(image_width, ty + idy + 1); + dest.resize(image_width, ty + idy + 1); + } + // Brute force packing. + for(int tx = 0; tx < image_width - (int)items[i].first.dat[0].size() && !found; tx++) { + bool valid = !(masq.dat[ty][tx] || masq.dat[ty + idy - 1][tx] || masq.dat[ty][tx + idx - 1] || masq.dat[ty + idy - 1][tx + idx - 1]); + if (valid) { + for(int ity = 0; ity < idy && valid; ity++) + for(int itx = 0; itx < idx && valid; itx++) + if(masq.dat[ty + ity][tx + itx]) { + valid = false; + } + } + if (valid) { + dest.copyfrom(items[i].first, tx, ty, items[i].second.effect); + masq.set(tx, ty, tx + idx + 1, ty + idy + 1, 255); + + items[i].second.sx = tx; + items[i].second.sy = ty; + + items[i].second.ex = tx + idx; + items[i].second.ey = ty + idy; + + found = true; + + // printf("Placed %d at %dx%d-%dx%d\n", items[i].second.id, tx, ty, tx + idx, ty + idy); + } + } + } + } + + if ((int)dest.dat.size() > image_width) { + printf("PACKING FAIL : height=%i", (int)dest.dat.size()); + exit(1); + } + dest.resize(image_width, NextPowerOf2(dest.dat.size())); + + // Output the glyph data. + vector dats; + for(int i = 0; i < (int)items.size(); i++) + dats.push_back(items[i].second); + return dats; + } +}; + +const int supersample = 16; +const int distmult = 64 * 3; // this is "one pixel in the final version equals 64 difference". reduce this number to increase the "blur" radius, increase it to make things "sharper" +const int maxsearch = (128 * supersample + distmult - 1) / distmult; + +struct Closest { + FT_Bitmap bmp; + Closest(FT_Bitmap bmp) : bmp(bmp) { } + float find_closest(int x, int y, char search) { + int best = 1 << 30; + for(int i = 1; i <= maxsearch; i++) { + if(i * i >= best) + break; + for(int f = -i; f < i; f++) { + int dist = i * i + f * f; + if(dist >= best) continue; + if(safe_access(x + i, y + f) == search || safe_access(x - f, y + i) == search || safe_access(x - i, y - f) == search || safe_access(x + f, y - i) == search) + best = dist; + } + } + return sqrt((float)best); + } + char safe_access(int x, int y) { + if(x < 0 || y < 0 || x >= bmp.width || y >= bmp.rows) + return 0; + return bmp.buffer[x + y * bmp.width]; + } +}; + +void RasterizeFont(const char *fontfile, int fontsize, float *metrics_height, Bucket *bucket) { + FT_Library freetype; + CHECK(FT_Init_FreeType(&freetype) == 0); + + FT_Face font; + CHECK(FT_New_Face(freetype, fontfile, 0, &font) == 0); + + printf("%d glyphs, %08x flags, %d units, %d strikes\n", (int)font->num_glyphs, (int)font->face_flags, (int)font->units_per_EM, (int)font->num_fixed_sizes); + + CHECK(FT_Set_Pixel_Sizes(font, 0, fontsize * supersample) == 0); + + // Character range. TODO: Make definable. We might want unicode + // Convert all characters to bitmaps. + for(int kar = 32; kar < 128; kar++) { + Image img; + if (0 != FT_Load_Char(font, kar, FT_LOAD_RENDER|FT_LOAD_MONOCHROME)) { + img.resize(1,1); + Data dat; + + dat.id = global_id++; + + dat.sx = 0; + dat.sy = 0; + dat.ex = 0; + dat.ey = 0; + dat.ox = 0; + dat.oy = 0; + dat.wx = 0; + dat.effect = FX_RED_TO_ALPHA_SOLID_WHITE; + bucket->AddItem(img, dat); + continue; + } + + // printf("%dx%d %p\n", font->glyph->bitmap.width, font->glyph->bitmap.rows, font->glyph->bitmap.buffer); + const int bord = (128 + distmult - 1) / distmult + 1; + if(font->glyph->bitmap.buffer) { + FT_Bitmap tempbitmap; + FT_Bitmap_New(&tempbitmap); + FT_Bitmap_Convert(freetype, &font->glyph->bitmap, &tempbitmap, 1); + Closest closest(tempbitmap); + + // No resampling, just sets the size of the image. + img.resize((tempbitmap.width + supersample - 1) / supersample + bord * 2, (tempbitmap.rows + supersample - 1) / supersample + bord * 2); + int lmx = img.dat[0].size(); + int lmy = img.dat.size(); + + // AA by finding distance to character. Probably a fairly decent approximation but why not do it right? + for(int y = 0; y < lmy; y++) { + int cty = (y - bord) * supersample + supersample / 2; + for(int x = 0; x < lmx; x++) { + int ctx = (x - bord) * supersample + supersample / 2; + float dist; + if(closest.safe_access(ctx, cty)) { + dist = closest.find_closest(ctx, cty, 0); + } else { + dist = -closest.find_closest(ctx, cty, 1); + } + dist = dist / supersample * distmult + 127.5; + dist = floor(dist + 0.5); + if(dist < 0) dist = 0; + if(dist > 255) dist = 255; + + // Only set the red channel. We process when adding the image. + img.dat[y][x] = (unsigned char)dist; + } + } + FT_Bitmap_Done(freetype, &tempbitmap); + } else { + img.resize(1, 1); + } + + Data dat; + + dat.id = global_id++; + + dat.sx = 0; + dat.sy = 0; + dat.ex = img.dat[0].size(); + dat.ey = img.dat.size(); + dat.ox = (float)font->glyph->metrics.horiBearingX / 64 / supersample - bord; + dat.oy = -(float)font->glyph->metrics.horiBearingY / 64 / supersample - bord; + dat.wx = (float)font->glyph->metrics.horiAdvance / 64 / supersample; + + dat.effect = FX_RED_TO_ALPHA_SOLID_WHITE; + bucket->AddItem(img, dat); + } + + *metrics_height = font->size->metrics.height; + FT_Done_FreeType(freetype); +} + + +bool LoadImage(const char *imagefile, Effect effect, Bucket *bucket) { + Image img; + + bool success = false; + if (!strcmp(imagefile, "white.png")) { + img.dat.resize(16); + for (int i = 0; i < 16; i++) { + img.dat[i].resize(16); + for (int j = 0; j < 16; j++) { + img.dat[i][j] = 0xFFFFFFFF; + } + } + success = true; + } else { + success = img.LoadPNG(imagefile); + printf("loaded image: %ix%i\n", (int)img.dat[0].size(), (int)img.dat.size()); + } + if (!success) { + return false; + } + + Data dat; + memset(&dat, 0, sizeof(dat)); + dat.id = global_id++; + dat.sx = 0; + dat.sy = 0; + dat.ex = img.dat[0].size(); + dat.ey = img.dat.size(); + dat.effect = effect; + bucket->AddItem(img, dat); + return true; +} + +// Use the result array, and recorded data, to generate C++ tables for everything. +struct FontDesc { + string name; + + int first_char_id; + int last_char_id; + + float ascend; + float descend; + float height; + + float metrics_height; + + void ComputeHeight(const vector &results, float distmult) { + ascend = 0; + descend = 0; + for(int i = first_char_id; i < last_char_id; i++) { + ascend = max(ascend, -results[i].oy); + descend = max(descend, results[i].ey - results[i].sy + results[i].oy); + } + + height = metrics_height / 64.0 / supersample; + } + + void OutputSelf(FILE *fil, float tw, float th, const vector &results) { + fprintf(fil, "const AtlasFont font_%s = {\n", name.c_str()); + fprintf(fil, " %ff, // padding\n", height - ascend - descend); + fprintf(fil, " %ff, // height\n", ascend + descend); + fprintf(fil, " %ff, // ascend\n", ascend); + fprintf(fil, " %ff, // distslope\n", distmult / 256.0); + fprintf(fil, " {\n"); + CHECK(last_char_id - first_char_id == 96); + for(int i = first_char_id; i < last_char_id; i++) { + fprintf(fil, " {%ff, %ff, %ff, %ff, %1.4ff, %1.4ff, %1.4ff, %i, %i}, // %i\n", + /*results[i].id, */ + results[i].sx / tw, + results[i].sy / th, + results[i].ex / tw, + results[i].ey / th, + results[i].ox, + results[i].oy, + results[i].wx, + results[i].ex - results[i].sx, results[i].ey - results[i].sy, (i - first_char_id + 32)); + } + fprintf(fil, " },\n"); + fprintf(fil, "};\n"); + } + + void OutputIndex(FILE *fil) { + fprintf(fil, " &font_%s,\n", name.c_str()); + } + + void OutputHeader(FILE *fil, int index) { + fprintf(fil, "#define %s %i\n", name.c_str(), index); + } +}; + +struct ImageDesc { + string name; + Effect effect; + int result_index; + + void OutputSelf(FILE *fil, float tw, float th, const vector &results) { + int i = result_index; + float toffx = 0.5f / tw; + float toffy = 0.5f / th; + fprintf(fil, " {%ff, %ff, %ff, %ff, %d, %d},\n", + results[i].sx / tw + toffx, + results[i].sy / th + toffy, + results[i].ex / tw - toffx, + results[i].ey / th - toffy, + results[i].ex - results[i].sx, + results[i].ey - results[i].sy); + } + + void OutputHeader(FILE *fil, int index) { + fprintf(fil, "#define %s %i\n", name.c_str(), index); + } +}; + +int main(int argc, char **argv) { + // initProgram(&argc, const_cast(&argv)); + // /usr/share/fonts/truetype/msttcorefonts/Arial_Black.ttf + // /usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-R.ttf + + CHECK(argc >= 3); + if (argc > 3) + { + highcolor = true; + printf("RGBA8888 enabled!\n"); + } + printf("Reading script %s\n", argv[1]); + const char *atlas_name = argv[2]; + string image_name = string(atlas_name) + "_atlas.zim"; + out_prefix = argv[2]; + + vector fonts; + vector images; + + Bucket bucket; + + char line[512]; + FILE *script = fopen(argv[1], "r"); + if (!fgets(line, 512, script)) { + printf("Error fgets-ing\n"); + } + int image_width; + sscanf(line, "%i", &image_width); + printf("Texture width: %i\n", image_width); + while (!feof(script)) { + if (!fgets(line, 511, script)) break; + if (!strlen(line)) break; + char *rest = strchr(line, ' '); + if (rest) + { + *rest = 0; + rest++; + } + char *word = line; + if (!strcmp(word, "font")) { + // Font! + char fontname[256]; + char fontfile[256]; + int pixheight; + sscanf(rest, "%s %s %i", fontname, fontfile, &pixheight); + printf("Font: %s (%s) in size %i\n", fontname, fontfile, pixheight); + + FontDesc fnt; + fnt.first_char_id = (int)bucket.items.size(); + float metrics_height; + RasterizeFont(fontfile, pixheight, &metrics_height, &bucket); + fnt.name = fontname; + fnt.last_char_id = (int)bucket.items.size(); + CHECK(fnt.last_char_id - fnt.first_char_id == 96); + + fnt.metrics_height = metrics_height; + fonts.push_back(fnt); + } else if (!strcmp(word, "image")) { + char imagename[256]; + char imagefile[256]; + char effectname[256]; + sscanf(rest, "%s %s %s", imagename, imagefile, effectname); + Effect effect = GetEffect(effectname); + printf("Image %s with effect %s (%i)\n", imagefile, effectname, (int)effect); + ImageDesc desc; + desc.name = imagename; + desc.effect = effect; + desc.result_index = (int)bucket.items.size(); + images.push_back(desc); + if (!LoadImage(imagefile, effect, &bucket)) { + fprintf(stderr, "Failed to load image %s\n", imagefile); + } + } else { + fprintf(stderr, "Warning: Failed to parse line starting with %s\n", line); + } + } + fclose(script); + // Script read, all subimages have been generated. + + // Place the subimages onto the main texture. Also writes to png. + Image dest; + // Place things on the bitmap. + printf("Resolving...\n"); + + vector results = bucket.Resolve(image_width, dest); + if (highcolor) { + printf("Writing .ZIM %ix%i RGBA8888...\n", dest.width(), dest.height()); + dest.SaveZIM(image_name.c_str(), ZIM_RGBA8888); + } else { + printf("Writing .ZIM %ix%i RGBA4444...\n", dest.width(), dest.height()); + dest.SaveZIM(image_name.c_str(), ZIM_RGBA4444); + } + // Also save PNG for debugging. + printf("Writing .PNG %s\n", (image_name + ".png").c_str()); + dest.SavePNG((image_name + ".png").c_str()); + + printf("Done. Outputting source files %s_atlas.cpp/h.\n", out_prefix.c_str()); + // Sort items by ID. + sort(results.begin(), results.end()); + + FILE *cpp_fil = fopen((out_prefix + "_atlas.cpp").c_str(), "wb"); + fprintf(cpp_fil, "// C++ generated by atlastool from %s (hrydgard@gmail.com)\n\n", argv[1]); + fprintf(cpp_fil, "#include \"%s\"\n\n", (out_prefix + "_atlas.h").c_str()); + for (int i = 0; i < (int)fonts.size(); i++) { + FontDesc &xfont = fonts[i]; + xfont.ComputeHeight(results, distmult); + xfont.OutputSelf(cpp_fil, dest.width(), dest.height(), results); + } + + if (fonts.size()) { + fprintf(cpp_fil, "const AtlasFont *%s_fonts[%i] = {\n", atlas_name, (int)fonts.size()); + for (int i = 0; i < (int)fonts.size(); i++) { + fonts[i].OutputIndex(cpp_fil); + } + fprintf(cpp_fil, "};\n"); + } + + if (images.size()) { + fprintf(cpp_fil, "const AtlasImage %s_images[%i] = {\n", atlas_name, (int)images.size()); + for (int i = 0; i < (int)images.size(); i++) { + images[i].OutputSelf(cpp_fil, dest.width(), dest.height(), results); + } + fprintf(cpp_fil, "};\n"); + } + + fprintf(cpp_fil, "const Atlas %s_atlas = {\n", atlas_name); + fprintf(cpp_fil, " \"%s\",\n", image_name.c_str()); + if (fonts.size()) { + fprintf(cpp_fil, " %s_fonts, %i,\n", atlas_name, (int)fonts.size()); + } else { + fprintf(cpp_fil, " 0, 0,\n"); + } + if (images.size()) { + fprintf(cpp_fil, " %s_images, %i,\n", atlas_name, (int)images.size()); + } else { + fprintf(cpp_fil, " 0, 0,\n"); + } + fprintf(cpp_fil, "};\n"); + // Should output a list pointing to all the fonts as well. + fclose(cpp_fil); + FILE *h_fil = fopen((out_prefix + "_atlas.h").c_str(), "wb"); + fprintf(h_fil, "// Header generated by atlastool from %s (hrydgard@gmail.com)\n\n", argv[1]); + fprintf(h_fil, "#pragma once\n"); + fprintf(h_fil, "#include \"gfx/texture_atlas.h\"\n\n"); + if (fonts.size()) { + fprintf(h_fil, "// FONTS_%s\n", atlas_name); + for (int i = 0; i < (int)fonts.size(); i++) { + fonts[i].OutputHeader(h_fil, i); + } + fprintf(h_fil, "\n\n"); + } + if (images.size()) { + fprintf(h_fil, "// IMAGES_%s\n", atlas_name); + for (int i = 0; i < (int)images.size(); i++) { + images[i].OutputHeader(h_fil, i); + } + fprintf(h_fil, "\n\n"); + } + fprintf(h_fil, "extern const Atlas %s_atlas;\n", atlas_name); + fprintf(h_fil, "extern const AtlasImage %s_images[%i];\n", atlas_name, (int)images.size()); + fclose(h_fil); + // TODO: Turn into C++ arrays. +} diff --git a/tools/atlastool/atlastool.vcxproj b/tools/atlastool/atlastool.vcxproj new file mode 100644 index 0000000000..ed62624e85 --- /dev/null +++ b/tools/atlastool/atlastool.vcxproj @@ -0,0 +1,104 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0FDAD650-7436-4803-A36B-10CF9F6F9C2B} + Win32Proj + atlastool + + + + Application + true + MultiByte + + + Application + false + false + MultiByte + + + + + + + + + + + + + true + D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib + + + false + D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib + $(SolutionDir)..\..\tools\build\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..;..\..\SDL\include;..\..\..\libpng;%(AdditionalIncludeDirectories); + + + Console + true + freetype.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..;..\..\SDL\include;..\..\..\libpng;%(AdditionalIncludeDirectories); + + + Console + true + true + true + freetype.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;%(AdditionalDependencies) + + + + + + + + {2dbe9ec0-0b03-4b8f-8b8a-75aca6253807} + + + {f761046e-6c38-4428-a5f1-38391a37bb34} + + + {e8b58922-9827-493d-81e0-4b6e6bd77171} + + + + + + \ No newline at end of file diff --git a/tools/audiotool.cpp b/tools/audiotool.cpp new file mode 100644 index 0000000000..68cfee7ae3 --- /dev/null +++ b/tools/audiotool.cpp @@ -0,0 +1,17 @@ +// TODO + +#include + +#include "audio/wav_load.h" +#include "base/logging.h" + + +struct AudioClip { + int length; + +}; + + +int main(int argc, char **argv) { + CHECK(argc == 3); +} diff --git a/tools/b.sh b/tools/b.sh new file mode 100644 index 0000000000..015dc7e52e --- /dev/null +++ b/tools/b.sh @@ -0,0 +1,3 @@ +mkdir -p build +(cd build; cmake .. && make -j5; cd ..) +#cp build/atlastool /home/henrik/bin diff --git a/tools/zimtool.cpp b/tools/zimtool.cpp new file mode 100644 index 0000000000..851f8a7933 --- /dev/null +++ b/tools/zimtool.cpp @@ -0,0 +1,98 @@ +#include +#include +#include + +#include "base/logging.h" +#include "image/png_load.h" +#include "image/zim_save.h" + +char magic[5] = "ZIMG"; + +bool FLAGS_flip = false; + +const char *format_strings[4] = {"8888", "4444", "565", "ETC1"}; +int formats[4] = {ZIM_RGBA8888, ZIM_RGBA4444, ZIM_RGB565, ZIM_ETC1}; + +void printusage() { + fprintf(stderr, "Usage: zimtool infile.png outfile.zim [-f=FORMAT] [-m] [-g]\n"); + fprintf(stderr, "Formats: 8888 4444 565 ETC1\n"); +} + +int filesize(const char *filename) { + FILE *f = fopen(filename, "rb"); + fseek(f, 0, SEEK_END); + int sz = ftell(f); + fclose(f); + return sz; +} + +int main(int argc, char **argv) { + // Parse command line arguments. + const char *FLAGS_infile; + const char *FLAGS_outfile; + if (argc >= 3) { + FLAGS_infile = argv[1]; + FLAGS_outfile = argv[2]; + } else { + fprintf(stderr, "ERROR: Not enough parameters.\n"); + printusage(); + return 1; + } + + int flags = 0; + bool format_set = false; + for (int i = 3; i < argc; i++) { + if (argv[i][0] != '-') { + fprintf(stderr, "Additional arguments must start with '-'\n"); + return 1; + } + switch (argv[i][1]) { + case 'm': + flags |= ZIM_HAS_MIPS; + // Generates mips directly here. We can generate gamma + // corrected mips, and mips for ETC1. + break; + case 'g': + flags |= ZIM_GEN_MIPS; + break; + case 'c': + flags |= ZIM_CLAMP; + break; + case 'f': + { + for (int j = 0; j < 4; j++) { + if (!strcmp(format_strings[j], argv[i] + 3)) { + flags |= j; + format_set = true; + } + } + } + break; + } + } + if ((flags & ZIM_FORMAT_MASK) == ZIM_ETC1) { + if (flags & ZIM_GEN_MIPS) { + fprintf(stderr, "WARNING: Cannot generate ETC1 mips at runtime\n"); + flags &= ~ZIM_GEN_MIPS; + } + } + if (!format_set) { + fprintf(stderr, "Must set format\n"); + printusage(); + return 1; + } + + uint8_t *image_data; + int width, height; + if (1 != pngLoad(FLAGS_infile, &width, &height, &image_data, FLAGS_flip)) { + fprintf(stderr, "Input not a PNG file\n"); + printusage(); + return 1; + } + + SaveZIM(FLAGS_outfile, width, height, width * 4, flags, image_data); + int in_file_size = filesize(FLAGS_infile); + int out_file_size = filesize(FLAGS_outfile); + fprintf(stdout, "Converted %s to %s. %i b to %i b. %ix%i, %s.\n", FLAGS_infile, FLAGS_outfile, in_file_size, out_file_size, width, height, format_strings[flags & ZIM_FORMAT_MASK]); + return 0; +} diff --git a/tools/zimtool/zimtool.vcxproj b/tools/zimtool/zimtool.vcxproj new file mode 100644 index 0000000000..e82758ea99 --- /dev/null +++ b/tools/zimtool/zimtool.vcxproj @@ -0,0 +1,102 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {7055E1C3-0B42-40E4-80B0-8146A647FC5B} + Win32Proj + zimtool + + + + Application + true + MultiByte + + + Application + false + false + MultiByte + + + + + + + + + + + + + true + D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib + + + false + D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib + $(SolutionDir)..\..\tools\build\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..;..\..\..\glew;..\..\SDL\include;%(AdditionalIncludeDirectories); + + + Console + true + kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..;..\..\..\glew;..\..\SDL\include;%(AdditionalIncludeDirectories); + + + Console + true + true + true + kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies) + + + + + + + + {2dbe9ec0-0b03-4b8f-8b8a-75aca6253807} + + + {f761046e-6c38-4428-a5f1-38391a37bb34} + + + {e8b58922-9827-493d-81e0-4b6e6bd77171} + + + + + + \ No newline at end of file diff --git a/tools/zimtool/zimtool.vcxproj.filters b/tools/zimtool/zimtool.vcxproj.filters new file mode 100644 index 0000000000..1b836b2f43 --- /dev/null +++ b/tools/zimtool/zimtool.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From ce2be356b2b34fe1cc9905f4eea8a68ffbc0f9e0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 26 Oct 2012 11:18:19 +0200 Subject: [PATCH 0108/1445] Add stb_image as an alternative to libpng. --- ext/stb_image/CMakeLists.txt | 10 + ext/stb_image/stb_image.c | 4405 +++++++++++++++++++++++++++++ ext/stb_image/stb_image.h | 262 ++ image/png_load.cpp | 46 +- native.vcxproj | 4 + native.vcxproj.filters | 15 + tools/CMakeLists.txt | 2 +- tools/atlastool.cpp | 2 +- tools/atlastool/atlastool.vcxproj | 2 +- tools/zimtool/zimtool.vcxproj | 2 +- 10 files changed, 4744 insertions(+), 6 deletions(-) create mode 100644 ext/stb_image/CMakeLists.txt create mode 100644 ext/stb_image/stb_image.c create mode 100644 ext/stb_image/stb_image.h diff --git a/ext/stb_image/CMakeLists.txt b/ext/stb_image/CMakeLists.txt new file mode 100644 index 0000000000..9c61b3ef99 --- /dev/null +++ b/ext/stb_image/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.6) + +#if(UNIX) +add_definitions(-PIC) +add_definitions(-g) +add_definitions(-O2) +add_definitions(-Wall) +#endif(UNIX) + +add_library(stb_image stb_image.c) diff --git a/ext/stb_image/stb_image.c b/ext/stb_image/stb_image.c new file mode 100644 index 0000000000..70a28c8d6d --- /dev/null +++ b/ext/stb_image/stb_image.c @@ -0,0 +1,4405 @@ +/* stbi-1.33 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c + when you control the images you're loading + no warranty implied; use at your own risk + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline (no JPEG progressive) + PNG 8-bit-per-channel only + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD) + + Latest revisions: + 1.33 (2011-07-14) minor fixes suggested by Dave Moore + 1.32 (2011-07-13) info support for all filetypes (SpartanJ) + 1.31 (2011-06-19) a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) added ability to load files via io callbacks (Ben Wenger) + 1.29 (2010-08-16) various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) cast-to-uint8 to fix warnings (Laurent Gomila) + allow trailing 0s at end of image data (Laurent Gomila) + 1.26 (2010-07-24) fix bug in file buffering for PNG reported by SpartanJ + + See end of file for full revision history. + + TODO: + stbi_info support for BMP,PSD,HDR,PIC + + + ============================ Contributors ========================= + + Image formats Optimizations & bugfixes + Sean Barrett (jpeg, png, bmp) Fabian "ryg" Giesen + Nicolas Schulz (hdr, psd) + Jonathan Dummer (tga) Bug fixes & warning fixes + Jean-Marc Lienher (gif) Marc LeBlanc + Tom Seddon (pic) Christpher Lloyd + Thatcher Ulrich (psd) Dave Moore + Won Chun + the Horde3D community + Extensions, features Janez Zemva + Jetro Lauha (stbi_info) Jonathan Blow + James "moose2000" Brown (iPhone PNG) Laurent Gomila + Ben "Disch" Wenger (io callbacks) Aruelien Pocheville + Martin "SpartanJ" Golini Ryamond Barbiero + David Woo + + + If your name should be here but isn't, let Sean know. + +*/ + +#include "stb_image.h" + +#ifndef STBI_HEADER_FILE_ONLY + +#ifndef STBI_NO_HDR +#include // ldexp +#include // strcmp, strtok +#endif + +#ifndef STBI_NO_STDIO +#include +#endif +#include +#include +#include +#include + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +// implementation: +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned int uint32; +typedef signed int int32; +typedef unsigned int uint; + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(uint32)==4 ? 1 : -1]; + +#if defined(STBI_NO_STDIO) && !defined(STBI_NO_WRITE) +#define STBI_NO_WRITE +#endif + +#define STBI_NOTUSED(v) (void)sizeof(v) + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +/////////////////////////////////////////////// +// +// stbi struct and start_xxx functions + +// stbi structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + uint8 buffer_start[128]; + + uint8 *img_buffer, *img_buffer_end; + uint8 *img_buffer_original; +} stbi; + + +static void refill_buffer(stbi *s); + +// initialize a memory-decode context +static void start_mem(stbi *s, uint8 const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (uint8 *) buffer; + s->img_buffer_end = (uint8 *) buffer+len; +} + +// initialize a callback-based context +static void start_callbacks(stbi *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + refill_buffer(s); +} + +#ifndef STBI_NO_STDIO + +static int stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stdio_skip(void *user, unsigned n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi_stdio_callbacks = +{ + stdio_read, + stdio_skip, + stdio_eof, +}; + +static void start_file(stbi *s, FILE *f) +{ + start_callbacks(s, &stbi_stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi_rewind(stbi *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; +} + +static int stbi_jpeg_test(stbi *s); +static stbi_uc *stbi_jpeg_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_jpeg_info(stbi *s, int *x, int *y, int *comp); +static int stbi_png_test(stbi *s); +static stbi_uc *stbi_png_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_png_info(stbi *s, int *x, int *y, int *comp); +static int stbi_bmp_test(stbi *s); +static stbi_uc *stbi_bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_tga_test(stbi *s); +static stbi_uc *stbi_tga_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_tga_info(stbi *s, int *x, int *y, int *comp); +static int stbi_psd_test(stbi *s); +static stbi_uc *stbi_psd_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_hdr_test(stbi *s); +static float *stbi_hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_pic_test(stbi *s); +static stbi_uc *stbi_pic_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_gif_test(stbi *s); +static stbi_uc *stbi_gif_load(stbi *s, int *x, int *y, int *comp, int req_comp); +static int stbi_gif_info(stbi *s, int *x, int *y, int *comp); + + +// this is not threadsafe +static const char *failure_reason; + +const char *stbi_failure_reason(void) +{ + return failure_reason; +} + +static int e(const char *str) +{ + failure_reason = str; + return 0; +} + +// e - error +// epf - error returning pointer to float +// epuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define e(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define e(x,y) e(y) +#else + #define e(x,y) e(x) +#endif + +#define epf(x,y) ((float *) (e(x,y)?NULL:NULL)) +#define epuc(x,y) ((unsigned char *) (e(x,y)?NULL:NULL)) + +void stbi_image_free(void *retval_from_stbi_load) +{ + free(retval_from_stbi_load); +} + +#ifndef STBI_NO_HDR +static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static unsigned char *stbi_load_main(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + if (stbi_jpeg_test(s)) return stbi_jpeg_load(s,x,y,comp,req_comp); + if (stbi_png_test(s)) return stbi_png_load(s,x,y,comp,req_comp); + if (stbi_bmp_test(s)) return stbi_bmp_load(s,x,y,comp,req_comp); + if (stbi_gif_test(s)) return stbi_gif_load(s,x,y,comp,req_comp); + if (stbi_psd_test(s)) return stbi_psd_load(s,x,y,comp,req_comp); + if (stbi_pic_test(s)) return stbi_pic_load(s,x,y,comp,req_comp); + + #ifndef STBI_NO_HDR + if (stbi_hdr_test(s)) { + float *hdr = stbi_hdr_load(s, x,y,comp,req_comp); + return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + // test tga last because it's a crappy test! + if (stbi_tga_test(s)) + return stbi_tga_load(s,x,y,comp,req_comp); + return epuc("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_STDIO +unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = fopen(filename, "rb"); + unsigned char *result; + if (!f) return epuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +unsigned char *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s,f); + return stbi_load_main(&s,x,y,comp,req_comp); +} +#endif //!STBI_NO_STDIO + +unsigned char *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s,buffer,len); + return stbi_load_main(&s,x,y,comp,req_comp); +} + +unsigned char *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_load_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_HDR + +float *stbi_loadf_main(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi_hdr_test(s)) + return stbi_hdr_load(s,x,y,comp,req_comp); + #endif + data = stbi_load_main(s, x, y, comp, req_comp); + if (data) + return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return epf("unknown image type", "Image not of any known type, or corrupt"); +} + +float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_mem(&s,buffer,len); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} + +float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = fopen(filename, "rb"); + float *result; + if (!f) return epf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi s; + start_file(&s,f); + return stbi_loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_HDR + +// these is-hdr-or-not is defined independent of whether STBI_NO_HDR is +// defined, for API simplicity; if STBI_NO_HDR is defined, it always +// reports false! + +int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi s; + start_mem(&s,buffer,len); + return stbi_hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +extern int stbi_is_hdr (char const *filename) +{ + FILE *f = fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +extern int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + stbi s; + start_file(&s,f); + return stbi_hdr_test(&s); + #else + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +extern int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi_hdr_test(&s); + #else + return 0; + #endif +} + +#ifndef STBI_NO_HDR +static float h2l_gamma_i=1.0f/2.2f, h2l_scale_i=1.0f; +static float l2h_gamma=2.2f, l2h_scale=1.0f; + +void stbi_hdr_to_ldr_gamma(float gamma) { h2l_gamma_i = 1/gamma; } +void stbi_hdr_to_ldr_scale(float scale) { h2l_scale_i = 1/scale; } + +void stbi_ldr_to_hdr_gamma(float gamma) { l2h_gamma = gamma; } +void stbi_ldr_to_hdr_scale(float scale) { l2h_scale = scale; } +#endif + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + SCAN_load=0, + SCAN_type, + SCAN_header +}; + +static void refill_buffer(stbi *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_end-1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static int get8(stbi *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int at_eof(stbi *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +stbi_inline static uint8 get8u(stbi *s) +{ + return (uint8) get8(s); +} + +static void skip(stbi *s, int n) +{ + if (s->io.read) { + int blen = s->img_buffer_end - s->img_buffer; + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int getn(stbi *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = s->img_buffer_end - s->img_buffer; + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int get16(stbi *s) +{ + int z = get8(s); + return (z << 8) + get8(s); +} + +static uint32 get32(stbi *s) +{ + uint32 z = get16(s); + return (z << 16) + get16(s); +} + +static int get16le(stbi *s) +{ + int z = get8(s); + return z + (get8(s) << 8); +} + +static uint32 get32le(stbi *s) +{ + uint32 z = get16le(s); + return z + (get16le(s) << 16); +} + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static uint8 compute_y(int r, int g, int b) +{ + return (uint8) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *convert_format(unsigned char *data, int img_n, int req_comp, uint x, uint y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + assert(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) malloc(req_comp * x * y); + if (good == NULL) { + free(data); + return epuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define COMBO(a,b) ((a)*8+(b)) + #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (COMBO(img_n, req_comp)) { + CASE(1,2) dest[0]=src[0], dest[1]=255; break; + CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; + CASE(2,1) dest[0]=src[0]; break; + CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; + CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; + CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; + CASE(3,1) dest[0]=compute_y(src[0],src[1],src[2]); break; + CASE(3,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = 255; break; + CASE(4,1) dest[0]=compute_y(src[0],src[1],src[2]); break; + CASE(4,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; + CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; + default: assert(0); + } + #undef CASE + } + + free(data); + return good; +} + +#ifndef STBI_NO_HDR +static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output = (float *) malloc(x * y * comp * sizeof(float)); + if (output == NULL) { free(data); return epf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) pow(data[i*comp+k]/255.0f, l2h_gamma) * l2h_scale; + } + if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; + } + free(data); + return output; +} + +#define float2int(x) ((int) (x)) +static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output = (stbi_uc *) malloc(x * y * comp); + if (output == NULL) { free(data); return epuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*h2l_scale_i, h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (uint8) float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (uint8) float2int(z); + } + } + free(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder (not actually fully baseline implementation) +// +// simple implementation +// - channel subsampling of at most 2 in each dimension +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - uses a lot of intermediate memory, could cache poorly +// - load http://nothings.org/remote/anemones.jpg 3 times on 2.8Ghz P4 +// stb_jpeg: 1.34 seconds (MSVC6, default release build) +// stb_jpeg: 1.06 seconds (MSVC6, processor = Pentium Pro) +// IJL11.dll: 1.08 seconds (compiled by intel) +// IJG 1998: 0.98 seconds (MSVC6, makefile provided by IJG) +// IJG 1998: 0.95 seconds (MSVC6, makefile + proc=PPro) + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + uint8 fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + uint16 code[256]; + uint8 values[256]; + uint8 size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} huffman; + +typedef struct +{ + #ifdef STBI_SIMD + unsigned short dequant2[4][64]; + #endif + stbi *s; + huffman huff_dc[4]; + huffman huff_ac[4]; + uint8 dequant[4][64]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + uint8 *data; + void *raw_data; + uint8 *linebuf; + } img_comp[4]; + + uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int scan_n, order[4]; + int restart_interval, todo; +} jpeg; + +static int build_huffman(huffman *h, int *count) +{ + int i,j,k=0,code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (uint8) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (uint16) (code++); + if (code-1 >= (1 << j)) return e("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (uint8) i; + } + } + } + return 1; +} + +static void grow_buffer_unsafe(jpeg *j) +{ + do { + int b = j->nomore ? 0 : get8(j->s); + if (b == 0xff) { + int c = get8(j->s); + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static uint32 bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int decode(jpeg *j, huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & bmask[k]) + h->delta[k]; + assert((((j->code_buffer) >> (32 - h->size[c])) & bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// combined JPEG 'receive' and JPEG 'extend', since baseline +// always extends everything it receives. +stbi_inline static int extend_receive(jpeg *j, int n) +{ + unsigned int m = 1 << (n-1); + unsigned int k; + if (j->code_bits < n) grow_buffer_unsafe(j); + + #if 1 + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~bmask[n]; + k &= bmask[n]; + j->code_bits -= n; + #else + k = (j->code_buffer >> (32 - n)) & bmask[n]; + j->code_bits -= n; + j->code_buffer <<= n; + #endif + // the following test is probably a random branch that won't + // predict well. I tried to table accelerate it but failed. + // maybe it's compiling as a conditional move? + if (k < m) + return (-1 << n) + k + 1; + else + return k; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static uint8 dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int decode_block(jpeg *j, short data[64], huffman *hdc, huffman *hac, int b) +{ + int diff,dc,k; + int t = decode(j, hdc); + if (t < 0) return e("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) dc; + + // decode AC components, see JPEG spec + k = 1; + do { + int r,s; + int rs = decode(j, hac); + if (rs < 0) return e("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + data[dezigzag[k++]] = (short) extend_receive(j,s); + } + } while (k < 64); + return 1; +} + +// take a -128..127 value and clamp it and convert to 0..255 +stbi_inline static uint8 clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (uint8) x; +} + +#define f2f(x) (int) (((x) * 4096 + 0.5)) +#define fsh(x) ((x) << 12) + +// derived from jidctint -- DCT_ISLOW +#define IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * f2f(0.5411961f); \ + t2 = p1 + p3*f2f(-1.847759065f); \ + t3 = p1 + p2*f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = fsh(p2+p3); \ + t1 = fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*f2f( 1.175875602f); \ + t0 = t0*f2f( 0.298631336f); \ + t1 = t1*f2f( 2.053119869f); \ + t2 = t2*f2f( 3.072711026f); \ + t3 = t3*f2f( 1.501321110f); \ + p1 = p5 + p1*f2f(-0.899976223f); \ + p2 = p5 + p2*f2f(-2.562915447f); \ + p3 = p3*f2f(-1.961570560f); \ + p4 = p4*f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +#ifdef STBI_SIMD +typedef unsigned short stbi_dequantize_t; +#else +typedef uint8 stbi_dequantize_t; +#endif + +// .344 seconds on 3*anemones.jpg +static void idct_block(uint8 *out, int out_stride, short data[64], stbi_dequantize_t *dequantize) +{ + int i,val[64],*v=val; + stbi_dequantize_t *dq = dequantize; + uint8 *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d,++dq, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0] * dq[0] << 2; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24], + d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = clamp((x0+t3) >> 17); + o[7] = clamp((x0-t3) >> 17); + o[1] = clamp((x1+t2) >> 17); + o[6] = clamp((x1-t2) >> 17); + o[2] = clamp((x2+t1) >> 17); + o[5] = clamp((x2-t1) >> 17); + o[3] = clamp((x3+t0) >> 17); + o[4] = clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SIMD +static stbi_idct_8x8 stbi_idct_installed = idct_block; + +void stbi_install_idct(stbi_idct_8x8 func) +{ + stbi_idct_installed = func; +} +#endif + +#define MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static uint8 get_marker(jpeg *j) +{ + uint8 x; + if (j->marker != MARKER_none) { x = j->marker; j->marker = MARKER_none; return x; } + x = get8u(j->s); + if (x != 0xff) return MARKER_none; + while (x == 0xff) + x = get8u(j->s); + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, reset the entropy decoder and +// the dc prediction +static void reset(jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->marker = MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int parse_entropy_coded_data(jpeg *z) +{ + reset(z); + if (z->scan_n == 1) { + int i,j; + #ifdef STBI_SIMD + __declspec(align(16)) + #endif + short data[64]; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; + #ifdef STBI_SIMD + stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); + #else + idct_block(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); + #endif + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!RESTART(z->marker)) return 1; + reset(z); + } + } + } + } else { // interleaved! + int i,j,k,x,y; + short data[64]; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0; + #ifdef STBI_SIMD + stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]); + #else + idct_block(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]); + #endif + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!RESTART(z->marker)) return 1; + reset(z); + } + } + } + } + return 1; +} + +static int process_marker(jpeg *z, int m) +{ + int L; + switch (m) { + case MARKER_none: // no marker found + return e("expected marker","Corrupt JPEG"); + + case 0xC2: // SOF - progressive + return e("progressive jpeg","JPEG format not supported (progressive)"); + + case 0xDD: // DRI - specify restart interval + if (get16(z->s) != 4) return e("bad DRI len","Corrupt JPEG"); + z->restart_interval = get16(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = get16(z->s)-2; + while (L > 0) { + int q = get8(z->s); + int p = q >> 4; + int t = q & 15,i; + if (p != 0) return e("bad DQT type","Corrupt JPEG"); + if (t > 3) return e("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) + z->dequant[t][dezigzag[i]] = get8u(z->s); + #ifdef STBI_SIMD + for (i=0; i < 64; ++i) + z->dequant2[t][i] = z->dequant[t][i]; + #endif + L -= 65; + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = get16(z->s)-2; + while (L > 0) { + uint8 *v; + int sizes[16],i,m=0; + int q = get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return e("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = get8(z->s); + m += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < m; ++i) + v[i] = get8u(z->s); + L -= m; + } + return L==0; + } + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + skip(z->s, get16(z->s)-2); + return 1; + } + return 0; +} + +// after we see SOS +static int process_scan_header(jpeg *z) +{ + int i; + int Ls = get16(z->s); + z->scan_n = get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return e("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return e("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = get8(z->s), which; + int q = get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return e("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return e("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + if (get8(z->s) != 0) return e("bad SOS","Corrupt JPEG"); + get8(z->s); // should be 63, but might be 0 + if (get8(z->s) != 0) return e("bad SOS","Corrupt JPEG"); + + return 1; +} + +static int process_frame_header(jpeg *z, int scan) +{ + stbi *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = get16(s); if (Lf < 11) return e("bad SOF len","Corrupt JPEG"); // JPEG + p = get8(s); if (p != 8) return e("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = get16(s); if (s->img_y == 0) return e("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = get16(s); if (s->img_x == 0) return e("0 width","Corrupt JPEG"); // JPEG requires + c = get8(s); + if (c != 3 && c != 1) return e("bad component count","Corrupt JPEG"); // JFIF requires + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return e("bad SOF len","Corrupt JPEG"); + + for (i=0; i < s->img_n; ++i) { + z->img_comp[i].id = get8(s); + if (z->img_comp[i].id != i+1) // JFIF requires + if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! + return e("bad component ID","Corrupt JPEG"); + q = get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return e("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return e("bad V","Corrupt JPEG"); + z->img_comp[i].tq = get8(s); if (z->img_comp[i].tq > 3) return e("bad TQ","Corrupt JPEG"); + } + + if (scan != SCAN_load) return 1; + + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].raw_data = malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); + if (z->img_comp[i].raw_data == NULL) { + for(--i; i >= 0; --i) { + free(z->img_comp[i].raw_data); + z->img_comp[i].data = NULL; + } + return e("outofmem", "Out of memory"); + } + // align blocks for installable-idct using mmx/sse + z->img_comp[i].data = (uint8*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + z->img_comp[i].linebuf = NULL; + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define DNL(x) ((x) == 0xdc) +#define SOI(x) ((x) == 0xd8) +#define EOI(x) ((x) == 0xd9) +#define SOF(x) ((x) == 0xc0 || (x) == 0xc1) +#define SOS(x) ((x) == 0xda) + +static int decode_jpeg_header(jpeg *z, int scan) +{ + int m; + z->marker = MARKER_none; // initialize cached marker to empty + m = get_marker(z); + if (!SOI(m)) return e("no SOI","Corrupt JPEG"); + if (scan == SCAN_type) return 1; + m = get_marker(z); + while (!SOF(m)) { + if (!process_marker(z,m)) return 0; + m = get_marker(z); + while (m == MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (at_eof(z->s)) return e("no SOF", "Corrupt JPEG"); + m = get_marker(z); + } + } + if (!process_frame_header(z, scan)) return 0; + return 1; +} + +static int decode_jpeg_image(jpeg *j) +{ + int m; + j->restart_interval = 0; + if (!decode_jpeg_header(j, SCAN_load)) return 0; + m = get_marker(j); + while (!EOI(m)) { + if (SOS(m)) { + if (!process_scan_header(j)) return 0; + if (!parse_entropy_coded_data(j)) return 0; + if (j->marker == MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!at_eof(j->s)) { + int x = get8(j->s); + if (x == 255) { + j->marker = get8u(j->s); + break; + } else if (x != 0) { + return 0; + } + } + // if we reach eof without hitting a marker, get_marker() below will fail and we'll eventually return 0 + } + } else { + if (!process_marker(j, m)) return 0; + } + m = get_marker(j); + } + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef uint8 *(*resample_row_func)(uint8 *out, uint8 *in0, uint8 *in1, + int w, int hs); + +#define div4(x) ((uint8) ((x) >> 2)) + +static uint8 *resample_row_1(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static uint8* resample_row_v_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static uint8* resample_row_h_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + uint8 *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = div4(n+input[i-1]); + out[i*2+1] = div4(n+input[i+1]); + } + out[i*2+0] = div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define div16(x) ((uint8) ((x) >> 4)) + +static uint8 *resample_row_hv_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = div16(3*t0 + t1 + 8); + out[i*2 ] = div16(3*t1 + t0 + 8); + } + out[w*2-1] = div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +static uint8 *resample_row_generic(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + in_far = in_far; + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) + +// 0.38 seconds on 3*anemones.jpg (0.25 with processor = Pro) +// VC6 without processor=Pro is generating multiple LEAs per multiply! +static void YCbCr_to_RGB_row(uint8 *out, const uint8 *y, const uint8 *pcb, const uint8 *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 16) + 32768; // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr*float2fixed(1.40200f); + g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); + b = y_fixed + cb*float2fixed(1.77200f); + r >>= 16; + g >>= 16; + b >>= 16; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (uint8)r; + out[1] = (uint8)g; + out[2] = (uint8)b; + out[3] = 255; + out += step; + } +} + +#ifdef STBI_SIMD +static stbi_YCbCr_to_RGB_run stbi_YCbCr_installed = YCbCr_to_RGB_row; + +void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func) +{ + stbi_YCbCr_installed = func; +} +#endif + + +// clean up the temporary component buffers +static void cleanup_jpeg(jpeg *j) +{ + int i; + for (i=0; i < j->s->img_n; ++i) { + if (j->img_comp[i].data) { + free(j->img_comp[i].raw_data); + j->img_comp[i].data = NULL; + } + if (j->img_comp[i].linebuf) { + free(j->img_comp[i].linebuf); + j->img_comp[i].linebuf = NULL; + } + } +} + +typedef struct +{ + resample_row_func resample; + uint8 *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi_resample; + +static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n; + // validate req_comp + if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); + z->s->img_n = 0; + + // load a jpeg image from whichever source + if (!decode_jpeg_image(z)) { cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n; + + if (z->s->img_n == 3 && n < 3) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + uint i,j; + uint8 *output; + uint8 *coutput[4]; + + stbi_resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi_resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (uint8 *) malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = resample_row_hv_2; + else r->resample = resample_row_generic; + } + + // can't error after this so, this is safe + output = (uint8 *) malloc(n * z->s->img_x * z->s->img_y + 1); + if (!output) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + uint8 *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi_resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + uint8 *y = coutput[0]; + if (z->s->img_n == 3) { + #ifdef STBI_SIMD + stbi_YCbCr_installed(out, y, coutput[1], coutput[2], z->s.img_x, n); + #else + YCbCr_to_RGB_row(out, y, coutput[1], coutput[2], z->s->img_x, n); + #endif + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + uint8 *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } + } + cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n; // report original components, not output + return output; + } +} + +static unsigned char *stbi_jpeg_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + jpeg j; + j.s = s; + return load_jpeg_image(&j, x,y,comp,req_comp); +} + +static int stbi_jpeg_test(stbi *s) +{ + int r; + jpeg j; + j.s = s; + r = decode_jpeg_header(&j, SCAN_type); + stbi_rewind(s); + return r; +} + +static int stbi_jpeg_info_raw(jpeg *j, int *x, int *y, int *comp) +{ + if (!decode_jpeg_header(j, SCAN_header)) { + stbi_rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n; + return 1; +} + +static int stbi_jpeg_info(stbi *s, int *x, int *y, int *comp) +{ + jpeg j; + j.s = s; + return stbi_jpeg_info_raw(&j, x, y, comp); +} + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define ZFAST_BITS 9 // accelerate all cases in default tables +#define ZFAST_MASK ((1 << ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + uint16 fast[1 << ZFAST_BITS]; + uint16 firstcode[16]; + int maxcode[17]; + uint16 firstsymbol[16]; + uint8 size[288]; + uint16 value[288]; +} zhuffman; + +stbi_inline static int bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int bit_reverse(int v, int bits) +{ + assert(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return bitreverse16(v) >> (16-bits); +} + +static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 255, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + assert(sizes[i] <= (1 << i)); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (uint16) code; + z->firstsymbol[i] = (uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return e("bad codelengths","Corrupt JPEG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + z->size[c] = (uint8)s; + z->value[c] = (uint16)i; + if (s <= ZFAST_BITS) { + int k = bit_reverse(next_code[s],s); + while (k < (1 << ZFAST_BITS)) { + z->fast[k] = (uint16) c; + k += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + uint8 *zbuffer, *zbuffer_end; + int num_bits; + uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + zhuffman z_length, z_distance; +} zbuf; + +stbi_inline static int zget8(zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void fill_bits(zbuf *z) +{ + do { + assert(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int zreceive(zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +stbi_inline static int zhuffman_decode(zbuf *a, zhuffman *z) +{ + int b,s,k; + if (a->num_bits < 16) fill_bits(a); + b = z->fast[a->code_buffer & ZFAST_MASK]; + if (b < 0xffff) { + s = z->size[b]; + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; + } + + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = bit_reverse(a->code_buffer, 16); + for (s=ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + assert(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +static int expand(zbuf *z, int n) // need to make room for n bytes +{ + char *q; + int cur, limit; + if (!z->z_expandable) return e("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) realloc(z->zout_start, limit); + if (q == NULL) return e("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static int length_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static int length_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static int dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static int dist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int parse_huffman_block(zbuf *a) +{ + for(;;) { + int z = zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return e("bad huffman code","Corrupt PNG"); // error in huffman codes + if (a->zout >= a->zout_end) if (!expand(a, 1)) return 0; + *a->zout++ = (char) z; + } else { + uint8 *p; + int len,dist; + if (z == 256) return 1; + z -= 257; + len = length_base[z]; + if (length_extra[z]) len += zreceive(a, length_extra[z]); + z = zhuffman_decode(a, &a->z_distance); + if (z < 0) return e("bad huffman code","Corrupt PNG"); + dist = dist_base[z]; + if (dist_extra[z]) dist += zreceive(a, dist_extra[z]); + if (a->zout - a->zout_start < dist) return e("bad dist","Corrupt PNG"); + if (a->zout + len > a->zout_end) if (!expand(a, len)) return 0; + p = (uint8 *) (a->zout - dist); + while (len--) + *a->zout++ = *p++; + } + } +} + +static int compute_huffman_codes(zbuf *a) +{ + static uint8 length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + zhuffman z_codelength; + uint8 lencodes[286+32+137];//padding for maximum single op + uint8 codelength_sizes[19]; + int i,n; + + int hlit = zreceive(a,5) + 257; + int hdist = zreceive(a,5) + 1; + int hclen = zreceive(a,4) + 4; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (uint8) s; + } + if (!zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < hlit + hdist) { + int c = zhuffman_decode(a, &z_codelength); + assert(c >= 0 && c < 19); + if (c < 16) + lencodes[n++] = (uint8) c; + else if (c == 16) { + c = zreceive(a,2)+3; + memset(lencodes+n, lencodes[n-1], c); + n += c; + } else if (c == 17) { + c = zreceive(a,3)+3; + memset(lencodes+n, 0, c); + n += c; + } else { + assert(c == 18); + c = zreceive(a,7)+11; + memset(lencodes+n, 0, c); + n += c; + } + } + if (n != hlit+hdist) return e("bad codelengths","Corrupt PNG"); + if (!zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int parse_uncompressed_block(zbuf *a) +{ + uint8 header[4]; + int len,nlen,k; + if (a->num_bits & 7) + zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (uint8) (a->code_buffer & 255); // wtf this warns? + a->code_buffer >>= 8; + a->num_bits -= 8; + } + assert(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = (uint8) zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return e("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return e("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!expand(a, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int parse_zlib_header(zbuf *a) +{ + int cmf = zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = zget8(a); + if ((cmf*256+flg) % 31 != 0) return e("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return e("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return e("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +// @TODO: should statically initialize these for optimal thread safety +static uint8 default_length[288], default_distance[32]; +static void init_defaults(void) +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) default_length[i] = 8; + for ( ; i <= 255; ++i) default_length[i] = 9; + for ( ; i <= 279; ++i) default_length[i] = 7; + for ( ; i <= 287; ++i) default_length[i] = 8; + + for (i=0; i <= 31; ++i) default_distance[i] = 5; +} + +int stbi_png_partial; // a quick hack to only allow decoding some of a PNG... I should implement real streaming support instead +static int parse_zlib(zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = zreceive(a,1); + type = zreceive(a,2); + if (type == 0) { + if (!parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!default_distance[31]) init_defaults(); + if (!zbuild_huffman(&a->z_length , default_length , 288)) return 0; + if (!zbuild_huffman(&a->z_distance, default_distance, 32)) return 0; + } else { + if (!compute_huffman_codes(a)) return 0; + } + if (!parse_huffman_block(a)) return 0; + } + if (stbi_png_partial && a->zout - a->zout_start > 65536) + break; + } while (!final); + return 1; +} + +static int do_zlib(zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return parse_zlib(a, parse_header); +} + +char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + zbuf a; + char *p = (char *) malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (uint8 *) buffer; + a.zbuffer_end = (uint8 *) buffer + len; + if (do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + zbuf a; + char *p = (char *) malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (uint8 *) buffer; + a.zbuffer_end = (uint8 *) buffer + len; + if (do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + zbuf a; + a.zbuffer = (uint8 *) ibuffer; + a.zbuffer_end = (uint8 *) ibuffer + ilen; + if (do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + zbuf a; + char *p = (char *) malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (uint8 *) buffer; + a.zbuffer_end = (uint8 *) buffer+len; + if (do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + free(a.zout_start); + return NULL; + } +} + +int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + zbuf a; + a.zbuffer = (uint8 *) ibuffer; + a.zbuffer_end = (uint8 *) ibuffer + ilen; + if (do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + + +typedef struct +{ + uint32 length; + uint32 type; +} chunk; + +#define PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +static chunk get_chunk_header(stbi *s) +{ + chunk c; + c.length = get32(s); + c.type = get32(s); + return c; +} + +static int check_png_header(stbi *s) +{ + static uint8 png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (get8u(s) != png_sig[i]) return e("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi *s; + uint8 *idata, *expanded, *out; +} png; + + +enum { + F_none=0, F_sub=1, F_up=2, F_avg=3, F_paeth=4, + F_avg_first, F_paeth_first +}; + +static uint8 first_row_filter[5] = +{ + F_none, F_sub, F_none, F_avg_first, F_paeth_first +}; + +static int paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +// create the png data from post-deflated data +static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, uint32 x, uint32 y) +{ + stbi *s = a->s; + uint32 i,j,stride = x*out_n; + int k; + int img_n = s->img_n; // copy it into a local for later + assert(out_n == s->img_n || out_n == s->img_n+1); + if (stbi_png_partial) y = 1; + a->out = (uint8 *) malloc(x * y * out_n); + if (!a->out) return e("outofmem", "Out of memory"); + if (!stbi_png_partial) { + if (s->img_x == x && s->img_y == y) { + if (raw_len != (img_n * x + 1) * y) return e("not enough pixels","Corrupt PNG"); + } else { // interlaced: + if (raw_len < (img_n * x + 1) * y) return e("not enough pixels","Corrupt PNG"); + } + } + for (j=0; j < y; ++j) { + uint8 *cur = a->out + stride*j; + uint8 *prior = cur - stride; + int filter = *raw++; + if (filter > 4) return e("invalid filter","Corrupt PNG"); + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + // handle first pixel explicitly + for (k=0; k < img_n; ++k) { + switch (filter) { + case F_none : cur[k] = raw[k]; break; + case F_sub : cur[k] = raw[k]; break; + case F_up : cur[k] = raw[k] + prior[k]; break; + case F_avg : cur[k] = raw[k] + (prior[k]>>1); break; + case F_paeth : cur[k] = (uint8) (raw[k] + paeth(0,prior[k],0)); break; + case F_avg_first : cur[k] = raw[k]; break; + case F_paeth_first: cur[k] = raw[k]; break; + } + } + if (img_n != out_n) cur[img_n] = 255; + raw += img_n; + cur += out_n; + prior += out_n; + // this is a little gross, so that we don't switch per-pixel or per-component + if (img_n == out_n) { + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, raw+=img_n,cur+=img_n,prior+=img_n) \ + for (k=0; k < img_n; ++k) + switch (filter) { + CASE(F_none) cur[k] = raw[k]; break; + CASE(F_sub) cur[k] = raw[k] + cur[k-img_n]; break; + CASE(F_up) cur[k] = raw[k] + prior[k]; break; + CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-img_n])>>1); break; + CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],prior[k],prior[k-img_n])); break; + CASE(F_avg_first) cur[k] = raw[k] + (cur[k-img_n] >> 1); break; + CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],0,0)); break; + } + #undef CASE + } else { + assert(img_n+1 == out_n); + #define CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ + for (k=0; k < img_n; ++k) + switch (filter) { + CASE(F_none) cur[k] = raw[k]; break; + CASE(F_sub) cur[k] = raw[k] + cur[k-out_n]; break; + CASE(F_up) cur[k] = raw[k] + prior[k]; break; + CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-out_n])>>1); break; + CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; + CASE(F_avg_first) cur[k] = raw[k] + (cur[k-out_n] >> 1); break; + CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],0,0)); break; + } + #undef CASE + } + } + return 1; +} + +static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int interlaced) +{ + uint8 *final; + int p; + int save; + if (!interlaced) + return create_png_image_raw(a, raw, raw_len, out_n, a->s->img_x, a->s->img_y); + save = stbi_png_partial; + stbi_png_partial = 0; + + // de-interlacing + final = (uint8 *) malloc(a->s->img_x * a->s->img_y * out_n); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + if (!create_png_image_raw(a, raw, raw_len, out_n, x, y)) { + free(final); + return 0; + } + for (j=0; j < y; ++j) + for (i=0; i < x; ++i) + memcpy(final + (j*yspc[p]+yorig[p])*a->s->img_x*out_n + (i*xspc[p]+xorig[p])*out_n, + a->out + (j*x+i)*out_n, out_n); + free(a->out); + raw += (x*out_n+1)*y; + raw_len -= (x*out_n+1)*y; + } + } + a->out = final; + + stbi_png_partial = save; + return 1; +} + +static int compute_transparency(png *z, uint8 tc[3], int out_n) +{ + stbi *s = z->s; + uint32 i, pixel_count = s->img_x * s->img_y; + uint8 *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + assert(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int expand_palette(png *a, uint8 *palette, int len, int pal_img_n) +{ + uint32 i, pixel_count = a->s->img_x * a->s->img_y; + uint8 *p, *temp_out, *orig = a->out; + + p = (uint8 *) malloc(pixel_count * pal_img_n); + if (p == NULL) return e("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + free(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi_unpremultiply_on_load = 0; +static int stbi_de_iphone_flag = 0; + +void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi_unpremultiply_on_load = flag_true_if_should_unpremultiply; +} +void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi_de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi_de_iphone(png *z) +{ + stbi *s = z->s; + uint32 i, pixel_count = s->img_x * s->img_y; + uint8 *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + uint8 t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + assert(s->img_out_n == 4); + if (stbi_unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + uint8 a = p[3]; + uint8 t = p[0]; + if (a) { + p[0] = p[2] * 255 / a; + p[1] = p[1] * 255 / a; + p[2] = t * 255 / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + uint8 t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +static int parse_png_file(png *z, int scan, int req_comp) +{ + uint8 palette[1024], pal_img_n=0; + uint8 has_trans=0, tc[3]; + uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, iphone=0; + stbi *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!check_png_header(s)) return 0; + + if (scan == SCAN_type) return 1; + + for (;;) { + chunk c = get_chunk_header(s); + switch (c.type) { + case PNG_TYPE('C','g','B','I'): + iphone = stbi_de_iphone_flag; + skip(s, c.length); + break; + case PNG_TYPE('I','H','D','R'): { + int depth,color,comp,filter; + if (!first) return e("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return e("bad IHDR len","Corrupt PNG"); + s->img_x = get32(s); if (s->img_x > (1 << 24)) return e("too large","Very large image (corrupt?)"); + s->img_y = get32(s); if (s->img_y > (1 << 24)) return e("too large","Very large image (corrupt?)"); + depth = get8(s); if (depth != 8) return e("8bit only","PNG not supported: 8-bit only"); + color = get8(s); if (color > 6) return e("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return e("bad ctype","Corrupt PNG"); + comp = get8(s); if (comp) return e("bad comp method","Corrupt PNG"); + filter= get8(s); if (filter) return e("bad filter method","Corrupt PNG"); + interlace = get8(s); if (interlace>1) return e("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return e("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode"); + if (scan == SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return e("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case PNG_TYPE('P','L','T','E'): { + if (first) return e("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return e("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return e("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = get8u(s); + palette[i*4+1] = get8u(s); + palette[i*4+2] = get8u(s); + palette[i*4+3] = 255; + } + break; + } + + case PNG_TYPE('t','R','N','S'): { + if (first) return e("first not IHDR", "Corrupt PNG"); + if (z->idata) return e("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return e("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return e("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = get8u(s); + } else { + if (!(s->img_n & 1)) return e("tRNS with alpha","Corrupt PNG"); + if (c.length != (uint32) s->img_n*2) return e("bad tRNS len","Corrupt PNG"); + has_trans = 1; + for (k=0; k < s->img_n; ++k) + tc[k] = (uint8) get16(s); // non 8-bit images will be larger + } + break; + } + + case PNG_TYPE('I','D','A','T'): { + if (first) return e("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return e("no PLTE","Corrupt PNG"); + if (scan == SCAN_header) { s->img_n = pal_img_n; return 1; } + if (ioff + c.length > idata_limit) { + uint8 *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + p = (uint8 *) realloc(z->idata, idata_limit); if (p == NULL) return e("outofmem", "Out of memory"); + z->idata = p; + } + if (!getn(s, z->idata+ioff,c.length)) return e("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case PNG_TYPE('I','E','N','D'): { + uint32 raw_len; + if (first) return e("first not IHDR", "Corrupt PNG"); + if (scan != SCAN_load) return 1; + if (z->idata == NULL) return e("no IDAT","Corrupt PNG"); + z->expanded = (uint8 *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, 16384, (int *) &raw_len, !iphone); + if (z->expanded == NULL) return 0; // zlib should set error + free(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!create_png_image(z, z->expanded, raw_len, s->img_out_n, interlace)) return 0; + if (has_trans) + if (!compute_transparency(z, tc, s->img_out_n)) return 0; + if (iphone && s->img_out_n > 2) + stbi_de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!expand_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } + free(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return e("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX chunk not known"; + invalid_chunk[0] = (uint8) (c.type >> 24); + invalid_chunk[1] = (uint8) (c.type >> 16); + invalid_chunk[2] = (uint8) (c.type >> 8); + invalid_chunk[3] = (uint8) (c.type >> 0); + #endif + return e(invalid_chunk, "PNG not supported: unknown chunk type"); + } + skip(s, c.length); + break; + } + // end of chunk, read and skip CRC + get32(s); + } +} + +static unsigned char *do_png(png *p, int *x, int *y, int *n, int req_comp) +{ + unsigned char *result=NULL; + if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error"); + if (parse_png_file(p, SCAN_load, req_comp)) { + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + result = convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + free(p->out); p->out = NULL; + free(p->expanded); p->expanded = NULL; + free(p->idata); p->idata = NULL; + + return result; +} + +static unsigned char *stbi_png_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + png p; + p.s = s; + return do_png(&p, x,y,comp,req_comp); +} + +static int stbi_png_test(stbi *s) +{ + int r; + r = check_png_header(s); + stbi_rewind(s); + return r; +} + +static int stbi_png_info_raw(png *p, int *x, int *y, int *comp) +{ + if (!parse_png_file(p, SCAN_header, 0)) { + stbi_rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi_png_info(stbi *s, int *x, int *y, int *comp) +{ + png p; + p.s = s; + return stbi_png_info_raw(&p, x, y, comp); +} + +// Microsoft/Windows BMP image + +static int bmp_test(stbi *s) +{ + int sz; + if (get8(s) != 'B') return 0; + if (get8(s) != 'M') return 0; + get32le(s); // discard filesize + get16le(s); // discard reserved + get16le(s); // discard reserved + get32le(s); // discard data offset + sz = get32le(s); + if (sz == 12 || sz == 40 || sz == 56 || sz == 108) return 1; + return 0; +} + +static int stbi_bmp_test(stbi *s) +{ + int r = bmp_test(s); + stbi_rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +static int shiftsigned(int v, int shift, int bits) +{ + int result; + int z=0; + + if (shift < 0) v <<= -shift; + else v >>= shift; + result = v; + + z = bits; + while (z < 8) { + result += v >> z; + z += bits; + } + return result; +} + +static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + uint8 *out; + unsigned int mr=0,mg=0,mb=0,ma=0, fake_a=0; + stbi_uc pal[256][4]; + int psize=0,i,j,compress=0,width; + int bpp, flip_vertically, pad, target, offset, hsz; + if (get8(s) != 'B' || get8(s) != 'M') return epuc("not BMP", "Corrupt BMP"); + get32le(s); // discard filesize + get16le(s); // discard reserved + get16le(s); // discard reserved + offset = get32le(s); + hsz = get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108) return epuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = get16le(s); + s->img_y = get16le(s); + } else { + s->img_x = get32le(s); + s->img_y = get32le(s); + } + if (get16le(s) != 1) return epuc("bad BMP", "bad BMP"); + bpp = get16le(s); + if (bpp == 1) return epuc("monochrome", "BMP type not supported: 1-bit"); + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + if (hsz == 12) { + if (bpp < 24) + psize = (offset - 14 - 24) / 3; + } else { + compress = get32le(s); + if (compress == 1 || compress == 2) return epuc("BMP RLE", "BMP type not supported: RLE"); + get32le(s); // discard sizeof + get32le(s); // discard hres + get32le(s); // discard vres + get32le(s); // discard colorsused + get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + get32le(s); + get32le(s); + get32le(s); + get32le(s); + } + if (bpp == 16 || bpp == 32) { + mr = mg = mb = 0; + if (compress == 0) { + if (bpp == 32) { + mr = 0xffu << 16; + mg = 0xffu << 8; + mb = 0xffu << 0; + ma = 0xffu << 24; + fake_a = 1; // @TODO: check for cases like alpha value is all 0 and switch it to 255 + } else { + mr = 31u << 10; + mg = 31u << 5; + mb = 31u << 0; + } + } else if (compress == 3) { + mr = get32le(s); + mg = get32le(s); + mb = get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (mr == mg && mg == mb) { + // ?!?!? + return epuc("bad BMP", "bad BMP"); + } + } else + return epuc("bad BMP", "bad BMP"); + } + } else { + assert(hsz == 108); + mr = get32le(s); + mg = get32le(s); + mb = get32le(s); + ma = get32le(s); + get32le(s); // discard color space + for (i=0; i < 12; ++i) + get32le(s); // discard color space parameters + } + if (bpp < 16) + psize = (offset - 14 - hsz) >> 2; + } + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + out = (stbi_uc *) malloc(target * s->img_x * s->img_y); + if (!out) return epuc("outofmem", "Out of memory"); + if (bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { free(out); return epuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = get8u(s); + pal[i][1] = get8u(s); + pal[i][0] = get8u(s); + if (hsz != 12) get8(s); + pal[i][3] = 255; + } + skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4)); + if (bpp == 4) width = (s->img_x + 1) >> 1; + else if (bpp == 8) width = s->img_x; + else { free(out); return epuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=get8(s),v2=0; + if (bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (bpp == 8) ? get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + skip(s, pad); + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + skip(s, offset - 14 - hsz); + if (bpp == 24) width = 3 * s->img_x; + else if (bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (bpp == 24) { + easy = 1; + } else if (bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { free(out); return epuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = high_bit(mr)-7; rcount = bitcount(mr); + gshift = high_bit(mg)-7; gcount = bitcount(mr); + bshift = high_bit(mb)-7; bcount = bitcount(mr); + ashift = high_bit(ma)-7; acount = bitcount(mr); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + int a; + out[z+2] = get8u(s); + out[z+1] = get8u(s); + out[z+0] = get8u(s); + z += 3; + a = (easy == 2 ? get8(s) : 255); + if (target == 4) out[z++] = (uint8) a; + } + } else { + for (i=0; i < (int) s->img_x; ++i) { + uint32 v = (bpp == 16 ? get16le(s) : get32le(s)); + int a; + out[z++] = (uint8) shiftsigned(v & mr, rshift, rcount); + out[z++] = (uint8) shiftsigned(v & mg, gshift, gcount); + out[z++] = (uint8) shiftsigned(v & mb, bshift, bcount); + a = (ma ? shiftsigned(v & ma, ashift, acount) : 255); + if (target == 4) out[z++] = (uint8) a; + } + } + skip(s, pad); + } + } + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} + +static stbi_uc *stbi_bmp_load(stbi *s,int *x, int *y, int *comp, int req_comp) +{ + return bmp_load(s, x,y,comp,req_comp); +} + + +// Targa Truevision - TGA +// by Jonathan Dummer + +static int tga_info(stbi *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp; + int sz; + get8u(s); // discard Offset + sz = get8u(s); // color type + if( sz > 1 ) { + stbi_rewind(s); + return 0; // only RGB or indexed allowed + } + sz = get8u(s); // image type + // only RGB or grey allowed, +/- RLE + if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0; + skip(s,9); + tga_w = get16le(s); + if( tga_w < 1 ) { + stbi_rewind(s); + return 0; // test width + } + tga_h = get16le(s); + if( tga_h < 1 ) { + stbi_rewind(s); + return 0; // test height + } + sz = get8(s); // bits per pixel + // only RGB or RGBA or grey allowed + if ((sz != 8) && (sz != 16) && (sz != 24) && (sz != 32)) { + stbi_rewind(s); + return 0; + } + tga_comp = sz; + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp / 8; + return 1; // seems to have passed everything +} + +int stbi_tga_info(stbi *s, int *x, int *y, int *comp) +{ + return tga_info(s, x, y, comp); +} + +static int tga_test(stbi *s) +{ + int sz; + get8u(s); // discard Offset + sz = get8u(s); // color type + if ( sz > 1 ) return 0; // only RGB or indexed allowed + sz = get8u(s); // image type + if ( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE + get16(s); // discard palette start + get16(s); // discard palette length + get8(s); // discard bits per palette color entry + get16(s); // discard x origin + get16(s); // discard y origin + if ( get16(s) < 1 ) return 0; // test width + if ( get16(s) < 1 ) return 0; // test height + sz = get8(s); // bits per pixel + if ( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) ) return 0; // only RGB or RGBA or grey allowed + return 1; // seems to have passed everything +} + +static int stbi_tga_test(stbi *s) +{ + int res = tga_test(s); + stbi_rewind(s); + return res; +} + +static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + // read in the TGA header stuff + int tga_offset = get8u(s); + int tga_indexed = get8u(s); + int tga_image_type = get8u(s); + int tga_is_RLE = 0; + int tga_palette_start = get16le(s); + int tga_palette_len = get16le(s); + int tga_palette_bits = get8u(s); + int tga_x_origin = get16le(s); + int tga_y_origin = get16le(s); + int tga_width = get16le(s); + int tga_height = get16le(s); + int tga_bits_per_pixel = get8u(s); + int tga_inverted = get8u(s); + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4]; + unsigned char trans_data[4]; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + /* int tga_alpha_bits = tga_inverted & 15; */ + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // error check + if ( //(tga_indexed) || + (tga_width < 1) || (tga_height < 1) || + (tga_image_type < 1) || (tga_image_type > 3) || + ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) && + (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) + ) + { + return NULL; // we don't report this as a bad TGA because we don't even know if it's TGA + } + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) + { + tga_bits_per_pixel = tga_palette_bits; + } + + // tga info + *x = tga_width; + *y = tga_height; + if ( (req_comp < 1) || (req_comp > 4) ) + { + // just use whatever the file was + req_comp = tga_bits_per_pixel / 8; + *comp = req_comp; + } else + { + // force a new number of components + *comp = tga_bits_per_pixel/8; + } + tga_data = (unsigned char*)malloc( tga_width * tga_height * req_comp ); + if (!tga_data) return epuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + skip(s, tga_offset ); + // do I need to load a palette? + if ( tga_indexed ) + { + // any data to skip? (offset usually = 0) + skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); + if (!tga_palette) return epuc("outofmem", "Out of memory"); + if (!getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) { + free(tga_data); + free(tga_palette); + return epuc("bad palette", "Corrupt TGA"); + } + } + // load the data + trans_data[0] = trans_data[1] = trans_data[2] = trans_data[3] = 0; + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE chunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = get8u(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in 1 byte, then perform the lookup + int pal_idx = get8u(s); + if ( pal_idx >= tga_palette_len ) + { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_bits_per_pixel / 8; + for (j = 0; j*8 < tga_bits_per_pixel; ++j) + { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else + { + // read in the data raw + for (j = 0; j*8 < tga_bits_per_pixel; ++j) + { + raw_data[j] = get8u(s); + } + } + // convert raw to the intermediate format + switch (tga_bits_per_pixel) + { + case 8: + // Luminous => RGBA + trans_data[0] = raw_data[0]; + trans_data[1] = raw_data[0]; + trans_data[2] = raw_data[0]; + trans_data[3] = 255; + break; + case 16: + // Luminous,Alpha => RGBA + trans_data[0] = raw_data[0]; + trans_data[1] = raw_data[0]; + trans_data[2] = raw_data[0]; + trans_data[3] = raw_data[1]; + break; + case 24: + // BGR => RGBA + trans_data[0] = raw_data[2]; + trans_data[1] = raw_data[1]; + trans_data[2] = raw_data[0]; + trans_data[3] = 255; + break; + case 32: + // BGRA => RGBA + trans_data[0] = raw_data[2]; + trans_data[1] = raw_data[1]; + trans_data[2] = raw_data[0]; + trans_data[3] = raw_data[3]; + break; + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + // convert to final format + switch (req_comp) + { + case 1: + // RGBA => Luminance + tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); + break; + case 2: + // RGBA => Luminance,Alpha + tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]); + tga_data[i*req_comp+1] = trans_data[3]; + break; + case 3: + // RGBA => RGB + tga_data[i*req_comp+0] = trans_data[0]; + tga_data[i*req_comp+1] = trans_data[1]; + tga_data[i*req_comp+2] = trans_data[2]; + break; + case 4: + // RGBA => RGBA + tga_data[i*req_comp+0] = trans_data[0]; + tga_data[i*req_comp+1] = trans_data[1]; + tga_data[i*req_comp+2] = trans_data[2]; + tga_data[i*req_comp+3] = trans_data[3]; + break; + } + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * req_comp; + int index2 = (tga_height - 1 - j) * tga_width * req_comp; + for (i = tga_width * req_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + free( tga_palette ); + } + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} + +static stbi_uc *stbi_tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + return tga_load(s,x,y,comp,req_comp); +} + + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +static int psd_test(stbi *s) +{ + if (get32(s) != 0x38425053) return 0; // "8BPS" + else return 1; +} + +static int stbi_psd_test(stbi *s) +{ + int r = psd_test(s); + stbi_rewind(s); + return r; +} + +static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + int pixelCount; + int channelCount, compression; + int channel, i, count, len; + int w,h; + uint8 *out; + + // Check identifier + if (get32(s) != 0x38425053) // "8BPS" + return epuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (get16(s) != 1) + return epuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = get16(s); + if (channelCount < 0 || channelCount > 16) + return epuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = get32(s); + w = get32(s); + + // Make sure the depth is 8 bits. + if (get16(s) != 8) + return epuc("unsupported bit depth", "PSD bit depth is not 8 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (get16(s) != 3) + return epuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + skip(s,get32(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + skip(s, get32(s) ); + + // Skip the reserved data. + skip(s, get32(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = get16(s); + if (compression > 1) + return epuc("bad compression", "PSD has an unknown compression format"); + + // Create the destination image. + out = (stbi_uc *) malloc(4 * w*h); + if (!out) return epuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, + // which we're going to just skip. + skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + uint8 *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++) *p = (channel == 3 ? 255 : 0), p += 4; + } else { + // Read the RLE data. + count = 0; + while (count < pixelCount) { + len = get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + count += len; + while (len) { + *p = get8u(s); + p += 4; + len--; + } + } else if (len > 128) { + uint8 val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len ^= 0x0FF; + len += 2; + val = get8u(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + uint8 *p; + + p = out + channel; + if (channel > channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++) *p = channel == 3 ? 255 : 0, p += 4; + } else { + // Read the data. + for (i = 0; i < pixelCount; i++) + *p = get8u(s), p += 4; + } + } + } + + if (req_comp && req_comp != 4) { + out = convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // convert_format frees input on failure + } + + if (comp) *comp = channelCount; + *y = h; + *x = w; + + return out; +} + +static stbi_uc *stbi_psd_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + return psd_load(s,x,y,comp,req_comp); +} + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +static int pic_is4(stbi *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int pic_test(stbi *s) +{ + int i; + + if (!pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + get8(s); + + if (!pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} pic_packet_t; + +static stbi_uc *pic_readval(stbi *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (at_eof(s)) return epuc("bad file","PIC file too short"); + dest[i]=get8u(s); + } + } + + return dest; +} + +static void pic_copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *pic_load2(stbi *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + pic_packet_t packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + pic_packet_t *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return epuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = get8(s); + packet->size = get8u(s); + packet->type = get8u(s); + packet->channel = get8u(s); + + act_comp |= packet->channel; + + if (at_eof(s)) return epuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return epuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return epuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=get8u(s); + if (at_eof(s)) return epuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (uint8) left; + + if (!pic_readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = get8(s), i; + if (at_eof(s)) return epuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + int i; + + if (count==128) + count = get16(s); + else + count -= 127; + if (count > left) + return epuc("bad file","scanline overrun"); + + if (!pic_readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return epuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static stbi_uc *pic_load(stbi *s,int *px,int *py,int *comp,int req_comp) +{ + stbi_uc *result; + int i, x,y; + + for (i=0; i<92; ++i) + get8(s); + + x = get16(s); + y = get16(s); + if (at_eof(s)) return epuc("bad file","file too short (pic header)"); + if ((1 << 28) / x < y) return epuc("too large", "Image too large to decode"); + + get32(s); //skip `ratio' + get16(s); //skip `fields' + get16(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) malloc(x*y*4); + memset(result, 0xff, x*y*4); + + if (!pic_load2(s,x,y,comp, result)) { + free(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi_pic_test(stbi *s) +{ + int r = pic_test(s); + stbi_rewind(s); + return r; +} + +static stbi_uc *stbi_pic_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + return pic_load(s,x,y,comp,req_comp); +} + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb +typedef struct stbi_gif_lzw_struct { + int16 prefix; + uint8 first; + uint8 suffix; +} stbi_gif_lzw; + +typedef struct stbi_gif_struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + int flags, bgindex, ratio, transparent, eflags; + uint8 pal[256][4]; + uint8 lpal[256][4]; + stbi_gif_lzw codes[4096]; + uint8 *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; +} stbi_gif; + +static int gif_test(stbi *s) +{ + int sz; + if (get8(s) != 'G' || get8(s) != 'I' || get8(s) != 'F' || get8(s) != '8') return 0; + sz = get8(s); + if (sz != '9' && sz != '7') return 0; + if (get8(s) != 'a') return 0; + return 1; +} + +static int stbi_gif_test(stbi *s) +{ + int r = gif_test(s); + stbi_rewind(s); + return r; +} + +static void stbi_gif_parse_colortable(stbi *s, uint8 pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = get8u(s); + pal[i][1] = get8u(s); + pal[i][0] = get8u(s); + pal[i][3] = transp ? 0 : 255; + } +} + +static int stbi_gif_header(stbi *s, stbi_gif *g, int *comp, int is_info) +{ + uint8 version; + if (get8(s) != 'G' || get8(s) != 'I' || get8(s) != 'F' || get8(s) != '8') + return e("not GIF", "Corrupt GIF"); + + version = get8u(s); + if (version != '7' && version != '9') return e("not GIF", "Corrupt GIF"); + if (get8(s) != 'a') return e("not GIF", "Corrupt GIF"); + + failure_reason = ""; + g->w = get16le(s); + g->h = get16le(s); + g->flags = get8(s); + g->bgindex = get8(s); + g->ratio = get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi_gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi_gif_info_raw(stbi *s, int *x, int *y, int *comp) +{ + stbi_gif g; + if (!stbi_gif_header(s, &g, comp, 1)) { + stbi_rewind( s ); + return 0; + } + if (x) *x = g.w; + if (y) *y = g.h; + return 1; +} + +static void stbi_out_gif_code(stbi_gif *g, uint16 code) +{ + uint8 *p, *c; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi_out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + p = &g->out[g->cur_x + g->cur_y]; + c = &g->color_table[g->codes[code].suffix * 4]; + + if (c[3] >= 128) { + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static uint8 *stbi_process_gif_raster(stbi *s, stbi_gif *g) +{ + uint8 lzw_cs; + int32 len, code; + uint32 first; + int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi_gif_lzw *p; + + lzw_cs = get8u(s); + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (code = 0; code < clear; code++) { + g->codes[code].prefix = -1; + g->codes[code].first = (uint8) code; + g->codes[code].suffix = (uint8) code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (int32) get8(s) << valid_bits; + valid_bits += 8; + } else { + int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + skip(s, len); + while ((len = get8(s)) > 0) + skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) return epuc("no clear code", "Corrupt GIF"); + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 4096) return epuc("too many codes", "Corrupt GIF"); + p->prefix = (int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return epuc("illegal code in raster", "Corrupt GIF"); + + stbi_out_gif_code(g, (uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return epuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +static void stbi_fill_gif_background(stbi_gif *g) +{ + int i; + uint8 *c = g->pal[g->bgindex]; + // @OPTIMIZE: write a dword at a time + for (i = 0; i < g->w * g->h * 4; i += 4) { + uint8 *p = &g->out[i]; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +static uint8 *stbi_gif_load_next(stbi *s, stbi_gif *g, int *comp, int req_comp) +{ + int i; + uint8 *old_out = 0; + + if (g->out == 0) { + if (!stbi_gif_header(s, g, comp,0)) return 0; // failure_reason set by stbi_gif_header + g->out = (uint8 *) malloc(4 * g->w * g->h); + if (g->out == 0) return epuc("outofmem", "Out of memory"); + stbi_fill_gif_background(g); + } else { + // animated-gif-only path + if (((g->eflags & 0x1C) >> 2) == 3) { + old_out = g->out; + g->out = (uint8 *) malloc(4 * g->w * g->h); + if (g->out == 0) return epuc("outofmem", "Out of memory"); + memcpy(g->out, old_out, g->w*g->h*4); + } + } + + for (;;) { + switch (get8(s)) { + case 0x2C: /* Image Descriptor */ + { + int32 x, y, w, h; + uint8 *o; + + x = get16le(s); + y = get16le(s); + w = get16le(s); + h = get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return epuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + g->lflags = get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi_gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (uint8 *) g->lpal; + } else if (g->flags & 0x80) { + for (i=0; i < 256; ++i) // @OPTIMIZE: reset only the previous transparent + g->pal[i][3] = 255; + if (g->transparent >= 0 && (g->eflags & 0x01)) + g->pal[g->transparent][3] = 0; + g->color_table = (uint8 *) g->pal; + } else + return epuc("missing color table", "Corrupt GIF"); + + o = stbi_process_gif_raster(s, g); + if (o == NULL) return NULL; + + if (req_comp && req_comp != 4) + o = convert_format(o, 4, req_comp, g->w, g->h); + return o; + } + + case 0x21: // Comment Extension. + { + int len; + if (get8(s) == 0xF9) { // Graphic Control Extension. + len = get8(s); + if (len == 4) { + g->eflags = get8(s); + get16le(s); // delay + g->transparent = get8(s); + } else { + skip(s, len); + break; + } + } + while ((len = get8(s)) != 0) + skip(s, len); + break; + } + + case 0x3B: // gif stream termination code + return (uint8 *) 1; + + default: + return epuc("unknown code", "Corrupt GIF"); + } + } +} + +static stbi_uc *stbi_gif_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + uint8 *u = 0; + stbi_gif g={0}; + + u = stbi_gif_load_next(s, &g, comp, req_comp); + if (u == (void *) 1) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + } + + return u; +} + +static int stbi_gif_info(stbi *s, int *x, int *y, int *comp) +{ + return stbi_gif_info_raw(s,x,y,comp); +} + + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int hdr_test(stbi *s) +{ + const char *signature = "#?RADIANCE\n"; + int i; + for (i=0; signature[i]; ++i) + if (get8(s) != signature[i]) + return 0; + return 1; +} + +static int stbi_hdr_test(stbi* s) +{ + int r = hdr_test(s); + stbi_rewind(s); + return r; +} + +#define HDR_BUFLEN 1024 +static char *hdr_gettoken(stbi *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) get8(z); + + while (!at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == HDR_BUFLEN-1) { + // flush to end of line + while (!at_eof(z) && get8(z) != '\n') + ; + break; + } + c = (char) get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + char buffer[HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + + + // Check identifier + if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) + return epf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return epf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return epf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = strtol(token, NULL, 10); + + *x = width; + *y = height; + + *comp = 3; + if (req_comp == 0) req_comp = 3; + + // Read data + hdr_data = (float *) malloc(height * width * req_comp * sizeof(float)); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + getn(s, rgbe, 4); + hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = get8(s); + c2 = get8(s); + len = get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + uint8 rgbe[4]; + rgbe[0] = (uint8) c1; + rgbe[1] = (uint8) c2; + rgbe[2] = (uint8) len; + rgbe[3] = (uint8) get8u(s); + hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + free(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= get8(s); + if (len != width) { free(hdr_data); free(scanline); return epf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) scanline = (stbi_uc *) malloc(width * 4); + + for (k = 0; k < 4; ++k) { + i = 0; + while (i < width) { + count = get8u(s); + if (count > 128) { + // Run + value = get8u(s); + count -= 128; + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = get8u(s); + } + } + } + for (i=0; i < width; ++i) + hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + free(scanline); + } + + return hdr_data; +} + +static float *stbi_hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp) +{ + return hdr_load(s,x,y,comp,req_comp); +} + +static int stbi_hdr_info(stbi *s, int *x, int *y, int *comp) +{ + char buffer[HDR_BUFLEN]; + char *token; + int valid = 0; + + if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0) { + stbi_rewind( s ); + return 0; + } + + for(;;) { + token = hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi_rewind( s ); + return 0; + } + token = hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi_rewind( s ); + return 0; + } + token += 3; + *y = strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi_rewind( s ); + return 0; + } + token += 3; + *x = strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +static int stbi_bmp_info(stbi *s, int *x, int *y, int *comp) +{ + int hsz; + if (get8(s) != 'B' || get8(s) != 'M') { + stbi_rewind( s ); + return 0; + } + skip(s,12); + hsz = get32le(s); + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108) { + stbi_rewind( s ); + return 0; + } + if (hsz == 12) { + *x = get16le(s); + *y = get16le(s); + } else { + *x = get32le(s); + *y = get32le(s); + } + if (get16le(s) != 1) { + stbi_rewind( s ); + return 0; + } + *comp = get16le(s) / 8; + return 1; +} + +static int stbi_psd_info(stbi *s, int *x, int *y, int *comp) +{ + int channelCount; + if (get32(s) != 0x38425053) { + stbi_rewind( s ); + return 0; + } + if (get16(s) != 1) { + stbi_rewind( s ); + return 0; + } + skip(s, 6); + channelCount = get16(s); + if (channelCount < 0 || channelCount > 16) { + stbi_rewind( s ); + return 0; + } + *y = get32(s); + *x = get32(s); + if (get16(s) != 8) { + stbi_rewind( s ); + return 0; + } + if (get16(s) != 3) { + stbi_rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi_pic_info(stbi *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained; + pic_packet_t packets[10]; + + skip(s, 92); + + *x = get16(s); + *y = get16(s); + if (at_eof(s)) return 0; + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi_rewind( s ); + return 0; + } + + skip(s, 8); + + do { + pic_packet_t *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = get8(s); + packet->size = get8u(s); + packet->type = get8u(s); + packet->channel = get8u(s); + act_comp |= packet->channel; + + if (at_eof(s)) { + stbi_rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi_rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} + +static int stbi_info_main(stbi *s, int *x, int *y, int *comp) +{ + if (stbi_jpeg_info(s, x, y, comp)) + return 1; + if (stbi_png_info(s, x, y, comp)) + return 1; + if (stbi_gif_info(s, x, y, comp)) + return 1; + if (stbi_bmp_info(s, x, y, comp)) + return 1; + if (stbi_psd_info(s, x, y, comp)) + return 1; + if (stbi_pic_info(s, x, y, comp)) + return 1; + #ifndef STBI_NO_HDR + if (stbi_hdr_info(s, x, y, comp)) + return 1; + #endif + // test tga last because it's a crappy test! + if (stbi_tga_info(s, x, y, comp)) + return 1; + return e("unknown image type", "Image not of any known type, or corrupt"); +} + +#ifndef STBI_NO_STDIO +int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = fopen(filename, "rb"); + int result; + if (!f) return e("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi s; + long pos = ftell(f); + start_file(&s, f); + r = stbi_info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi s; + start_mem(&s,buffer,len); + return stbi_info_main(&s,x,y,comp); +} + +int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi s; + start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi_info_main(&s,x,y,comp); +} + +#endif // STBI_HEADER_FILE_ONLY + +/* + revision history: + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-uint8 to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.e. Janez (U+017D)emva) + 1.21 fix use of 'uint8' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 2008-08-02 + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi_bmp_load() and stbi_tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 first released version +*/ diff --git a/ext/stb_image/stb_image.h b/ext/stb_image/stb_image.h new file mode 100644 index 0000000000..675bb96285 --- /dev/null +++ b/ext/stb_image/stb_image.h @@ -0,0 +1,262 @@ +#pragma once +//// begin header file //////////////////////////////////////////////////// +// +// Limitations: +// - no jpeg progressive support +// - non-HDR formats support 8-bit samples only (jpeg, png) +// - no delayed line count (jpeg) -- IJG doesn't support either +// - no 1-bit BMP +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *comp -- outputs # of image components in image file +// int req_comp -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. +// If req_comp is non-zero, *comp has the number of components that _would_ +// have been output otherwise. E.g. if you set req_comp to 4, you will always +// get RGBA output, but you can check *comp to easily see if it's opaque. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *comp will be unchanged. The function stbi_failure_reason() +// can be queried for an extremely brief, end-user unfriendly explanation +// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid +// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB; nominally they +// would silently load as BGR, except the existing code should have just +// failed on such iPhone PNGs. But you can disable this conversion by +// by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through. +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image now supports loading HDR images in general, and currently +// the Radiance .HDR file format, although the support is provided +// generically. You can still load any file through the existing interface; +// if you attempt to load an HDR file, it will be automatically remapped to +// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). + + +#ifndef STBI_NO_STDIO + +#if defined(_MSC_VER) && _MSC_VER >= 0x1400 +#define _CRT_SECURE_NO_WARNINGS // suppress bogus warnings about fopen() +#endif + +#include +#endif + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for req_comp + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +typedef unsigned char stbi_uc; + +#ifdef __cplusplus +extern "C" { +#endif + + ////////////////////////////////////////////////////////////////////////////// + // + // PRIMARY API - works on images of any type + // + + // + // load image by filename, open file, or memory buffer + // + + extern stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + +#ifndef STBI_NO_STDIO + extern stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); + extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); + // for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + + typedef struct + { + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,unsigned n); // skip the next 'n' bytes + int (*eof) (void *user); // returns nonzero if we are at end of file/data + } stbi_io_callbacks; + + extern stbi_uc *stbi_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + +#ifndef STBI_NO_HDR + extern float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); + +#ifndef STBI_NO_STDIO + extern float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); + extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); +#endif + + extern float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); + + extern void stbi_hdr_to_ldr_gamma(float gamma); + extern void stbi_hdr_to_ldr_scale(float scale); + + extern void stbi_ldr_to_hdr_gamma(float gamma); + extern void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_HDR + + // stbi_is_hdr is always defined + extern int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); + extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO + extern int stbi_is_hdr (char const *filename); + extern int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + + // get a VERY brief reason for failure + // NOT THREADSAFE + extern const char *stbi_failure_reason (void); + + // free the loaded image -- this is just free() + extern void stbi_image_free (void *retval_from_stbi_load); + + // get image dimensions & components without fully decoding + extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); + extern int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); + +#ifndef STBI_NO_STDIO + extern int stbi_info (char const *filename, int *x, int *y, int *comp); + extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); + +#endif + + + + // for image formats that explicitly notate that they have premultiplied alpha, + // we just return the colors as stored in the file. set this flag to force + // unpremultiplication. results are undefined if the unpremultiply overflow. + extern void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + + // indicate whether we should process iphone images back to canonical format, + // or just pass them through "as-is" + extern void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + + + // ZLIB client - used by PNG, available for other purposes + + extern char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); + extern char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); + extern int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + extern char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); + extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + + // define faster low-level operations (typically SIMD support) +#ifdef STBI_SIMD + typedef void (*stbi_idct_8x8)(stbi_uc *out, int out_stride, short data[64], unsigned short *dequantize); + // compute an integer IDCT on "input" + // input[x] = data[x] * dequantize[x] + // write results to 'out': 64 samples, each run of 8 spaced by 'out_stride' + // CLAMP results to 0..255 + typedef void (*stbi_YCbCr_to_RGB_run)(stbi_uc *output, stbi_uc const *y, stbi_uc const *cb, stbi_uc const *cr, int count, int step); + // compute a conversion from YCbCr to RGB + // 'count' pixels + // write pixels to 'output'; each pixel is 'step' bytes (either 3 or 4; if 4, write '255' as 4th), order R,G,B + // y: Y input channel + // cb: Cb input channel; scale/biased to be 0..255 + // cr: Cr input channel; scale/biased to be 0..255 + + extern void stbi_install_idct(stbi_idct_8x8 func); + extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func); +#endif // STBI_SIMD + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// diff --git a/image/png_load.cpp b/image/png_load.cpp index 7c14dd489e..67d6964c63 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -1,9 +1,51 @@ -#define PNG_AVAILABLE -#ifdef PNG_AVAILABLE +#include +#include +#include "png_load.h" +#include "base/logging.h" +#include "ext/stb_image/stb_image.h" + + +// #define PNG_AVAILABLE +#ifndef PNG_AVAILABLE + +// *image_data_ptr should be deleted with free() +// return value of 1 == success. +int pngLoad(const char *file, int *pwidth, + int *pheight, unsigned char **image_data_ptr, + bool flip) { + if (flip) + { + ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); + } + + int x,y,n; + unsigned char *data = stbi_load(file, &x, &y, &n, 4); // 4 = force RGBA + if (!data) + return 0; + + *pwidth = x; + *pheight = y; + // ... process data if not NULL ... + // ... x = width, y = height, n = # 8-bit components per pixel ... + // ... replace '0' with '1'..'4' to force that many components per pixel + // ... but 'n' will always be the number that it would have been if you said 0 + + // TODO: Get rid of this silly copy which is only to make the buffer free-able with free() + *image_data_ptr = (unsigned char *)malloc(x * y * n); + memcpy(*image_data_ptr, data, x * y * n); + stbi_image_free(data); + return 1; +} + + +#else + #include #include #include +// *image_data_ptr should be deleted with free() +// return value of 1 == success. int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip) { diff --git a/native.vcxproj b/native.vcxproj index 9dcf9b895f..309ba82411 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -169,8 +169,10 @@ + + @@ -198,6 +200,7 @@ + @@ -273,6 +276,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index e888ac3e0a..02ddb8b885 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -9,6 +9,12 @@ base + + ext + + + tools + @@ -212,6 +218,9 @@ base + + ext + @@ -379,6 +388,9 @@ base + + ext + @@ -435,5 +447,8 @@ {b7bc9a09-29c1-447b-9255-fe0709d10689} + + {4515306f-4664-46bf-a89b-abfec5520a15} + \ No newline at end of file diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 23e09fb98c..4eb2cedcca 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -41,7 +41,7 @@ add_subdirectory(../native/ext/etcpack etcpack) add_executable(atlastool atlastool.cpp) -target_link_libraries(atlastool ${PNG_LIBRARY} freetype z image etcpack etcdec file zip gomp) +target_link_libraries(atlastool ${PNG_LIBRARY} freetype z image etcpack etcdec file zip gomp) add_executable(zimtool zimtool.cpp) target_link_libraries(zimtool ${PNG_LIBRARY} freetype z image etcpack etcdec file zip gomp) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 12a7f580e1..6a2cfda2b0 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -380,7 +380,7 @@ bool LoadImage(const char *imagefile, Effect effect, Bucket *bucket) { success = true; } else { success = img.LoadPNG(imagefile); - printf("loaded image: %ix%i\n", (int)img.dat[0].size(), (int)img.dat.size()); + // printf("loaded image: %ix%i\n", (int)img.dat[0].size(), (int)img.dat.size()); } if (!success) { return false; diff --git a/tools/atlastool/atlastool.vcxproj b/tools/atlastool/atlastool.vcxproj index ed62624e85..aa20c790b4 100644 --- a/tools/atlastool/atlastool.vcxproj +++ b/tools/atlastool/atlastool.vcxproj @@ -46,7 +46,7 @@ false D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib - $(SolutionDir)..\..\tools\build\ + $(ProjectDir)\..\build diff --git a/tools/zimtool/zimtool.vcxproj b/tools/zimtool/zimtool.vcxproj index e82758ea99..f3d5c9b8a7 100644 --- a/tools/zimtool/zimtool.vcxproj +++ b/tools/zimtool/zimtool.vcxproj @@ -46,7 +46,7 @@ false D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib - $(SolutionDir)..\..\tools\build\ + $(ProjectDir)\..\build From 70e6752884149b50126d82f1b41e296b28ecee11 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 26 Oct 2012 15:58:09 +0200 Subject: [PATCH 0109/1445] Simple framework for virtual touchscreen buttons --- Android.mk | 1 + android/app-android.cpp | 5 ++- base/display.cpp | 3 +- base/display.h | 3 +- gfx/texture_atlas.cpp | 16 ++++++++ gfx/texture_atlas.h | 6 +++ gfx_es2/glsl_program.cpp | 4 +- native.vcxproj | 2 + native.vcxproj.filters | 6 +++ ui/CMakeLists.txt | 1 + ui/virtual_input.cpp | 80 ++++++++++++++++++++++++++++++++++++++++ ui/virtual_input.h | 69 ++++++++++++++++++++++++++++++++++ 12 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 ui/virtual_input.cpp create mode 100644 ui/virtual_input.h diff --git a/Android.mk b/Android.mk index a3ace6630b..f59e4f9cc5 100644 --- a/Android.mk +++ b/Android.mk @@ -47,6 +47,7 @@ LOCAL_SRC_FILES :=\ image/zim_load.cpp \ ui/ui.cpp \ ui/screen.cpp \ + ui/virtual_input.cpp \ util/random/perlin.cpp diff --git a/android/app-android.cpp b/android/app-android.cpp index 3e3482843e..98a460c263 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -128,6 +128,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init net::Init(); g_dpi = dpi; + g_dpi_scale = 240.0f / (float)g_dpi; pixel_xres = xxres; pixel_yres = yyres; @@ -180,8 +181,8 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayInit(JNIEnv // We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S). // Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo // can change the dp resolution if it feels like it. - dp_xres = pixel_xres * 240 / g_dpi; - dp_yres = pixel_yres * 240 / g_dpi; + dp_xres = pixel_xres * g_dpi_scale; + dp_yres = pixel_yres * g_dpi_scale; NativeInitGraphics(); diff --git a/base/display.cpp b/base/display.cpp index bc0b73ef56..a18a30be77 100644 --- a/base/display.cpp +++ b/base/display.cpp @@ -6,4 +6,5 @@ int dp_yres; int pixel_xres; int pixel_yres; -int g_dpi; \ No newline at end of file +int g_dpi; +float g_dpi_scale; \ No newline at end of file diff --git a/base/display.h b/base/display.h index dc6344cbab..43199561f0 100644 --- a/base/display.h +++ b/base/display.h @@ -8,4 +8,5 @@ extern int dp_yres; extern int pixel_xres; extern int pixel_yres; -extern int g_dpi; \ No newline at end of file +extern int g_dpi; +extern float g_dpi_scale; \ No newline at end of file diff --git a/gfx/texture_atlas.cpp b/gfx/texture_atlas.cpp index 146aa615b4..461bdbe650 100644 --- a/gfx/texture_atlas.cpp +++ b/gfx/texture_atlas.cpp @@ -1,2 +1,18 @@ +#include #include "gfx/texture_atlas.h" +const AtlasFont *Atlas::getFontByName(const char *name) const +{ + for (int i = 0; i < num_fonts; i++) { + if (!strcmp(name, fonts[i]->name)) + return fonts[i]; + } +} + +const AtlasImage *Atlas::getImageByName(const char *name) const +{ + for (int i = 0; i < num_images; i++) { + if (!strcmp(name, images[i].name)) + return &images[i]; + } +} diff --git a/gfx/texture_atlas.h b/gfx/texture_atlas.h index a75dc4de8a..d75c54e271 100644 --- a/gfx/texture_atlas.h +++ b/gfx/texture_atlas.h @@ -17,11 +17,13 @@ struct AtlasFont { float ascend; float distslope; AtlasChar chars[96]; + const char *name; }; struct AtlasImage { float u1, v1, u2, v2; int w, h; + const char *name; }; struct Atlas { @@ -30,4 +32,8 @@ struct Atlas { int num_fonts; const AtlasImage *images; int num_images; + + // These are inefficient linear searches, try not to call every frame. + const AtlasFont *getFontByName(const char *name) const; + const AtlasImage *getImageByName(const char *name) const; }; diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 82c1320da5..248b4f7db7 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -210,7 +210,9 @@ bool glsl_recompile(GLSLProgram *program) { } void GLSLProgram::GLLost() { - ILOG("Restoring GLSL program %s/%s", this->vshader_filename, this->fshader_filename); + ILOG("Restoring GLSL program %s/%s", + this->vshader_filename ? this->vshader_filename : "(mem)", + this->fshader_filename ? this->fshader_filename : "(mem)"); this->program_ = 0; this->vsh_ = 0; this->fsh_ = 0; diff --git a/native.vcxproj b/native.vcxproj index 309ba82411..0ec36aea90 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -240,6 +240,7 @@ + @@ -319,6 +320,7 @@ + AssemblyAndSourceCode diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 02ddb8b885..e9e8ef028d 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -221,6 +221,9 @@ ext + + ui + @@ -391,6 +394,9 @@ ext + + ui + diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 4b6f2c5758..066b1a9bda 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -1,6 +1,7 @@ set(SRCS ui.cpp screen.cpp + virtual_input.cpp ) set(SRCS ${SRCS}) diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp new file mode 100644 index 0000000000..07f640f75e --- /dev/null +++ b/ui/virtual_input.cpp @@ -0,0 +1,80 @@ +#include "gfx_es2/draw_buffer.h" +#include "gfx/texture_atlas.h" +#include "input/input_state.h" +#include "virtual_input.h" + +TouchButton::TouchButton(const Atlas *atlas, int imageIndex, int overlayImageIndex, int button, int rotationAngle) + : atlas_(atlas), imageIndex_(imageIndex), overlayImageIndex_(overlayImageIndex), button_(button), rotationAngle_(rotationAngle) +{ + memset(pointerDown, 0, sizeof(pointerDown)); + w_ = atlas->images[imageIndex].w; + h_ = atlas->images[imageIndex].h; +} + +void TouchButton::update(InputState &input_state) +{ + bool isDown = false; + for (int i = 0; i < MAX_POINTERS; i++) { + if (input_state.pointer_down[i] && isInside(input_state.pointer_x[i], input_state.pointer_y[i])) + isDown = true; + } + + if (isDown) { + int prev_buttons = input_state.pad_buttons; + input_state.pad_buttons |= button_; + input_state.pad_buttons_down |= button_ & (~prev_buttons); + } else { + input_state.pad_buttons_up &= ~(button_ & input_state.pad_buttons); + input_state.pad_buttons &= ~button_; + } +} + +void TouchButton::draw(DrawBuffer &db) +{ + db.DrawImageRotated(imageIndex_, x_ + w_/2, y_ + h_/2, 1.0f, rotationAngle_, 0xFFFFFFFF); + if (overlayImageIndex_ != -1) + db.DrawImageRotated(overlayImageIndex_, x_ + w_/2, y_ + h_/2, 1.0f, rotationAngle_, 0xFFFFFFFF); +} + + +TouchStick::TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick) + : atlas_(atlas), bgImageIndex_(bgImageIndex), stickImageIndex_(stickImageIndex), stick_(stick) +{ + +} + +void TouchStick::update(InputState &input_state) +{ + float inv_stick_size = 1.0f / stick_size_; + for (int i = 0; i < MAX_POINTERS; i++) { + if (input_state.pointer_down[i]) { + float dx = (input_state.pointer_x[i] - stick_x_) * inv_stick_size; + float dy = (input_state.pointer_y[i] - stick_y_) * inv_stick_size; + // Ignore outside box + if (fabsf(dx) > 1.4f || fabsf(dy) > 1.4f) + continue; + // Clamp to a circle + float len = sqrtf(dx * dx + dy * dy); + if (len > 1.0f) { + dx /= len; + dy /= len; + } + stick_delta_x_ = dx; + stick_delta_y_ = dy; + if (stick_ == 0) { + input_state.pad_lstick_x = dx; + input_state.pad_lstick_y = -dy; + } else if (stick_ == 1) { + input_state.pad_rstick_x = dx; + input_state.pad_rstick_y = -dy; + } + } + } +} + +void TouchStick::draw(DrawBuffer &db) +{ + if (bgImageIndex_ != -1) + db.DrawImage(bgImageIndex_, stick_x_, stick_y_, 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + db.DrawImage(stickImageIndex_, stick_x_ + stick_delta_x_, stick_y_ + stick_delta_y_, 1.0f, 0xFFFFFFFF, ALIGN_CENTER); +} \ No newline at end of file diff --git a/ui/virtual_input.h b/ui/virtual_input.h new file mode 100644 index 0000000000..921e83c45e --- /dev/null +++ b/ui/virtual_input.h @@ -0,0 +1,69 @@ +#pragma once + +// Multitouch-enabled emulation of a hardware button. +// (any finger will work, simultaneously with other virtual button/stick actions). +class TouchButton +{ +public: + TouchButton(const Atlas *atlas, int imageIndex, int overlayImageIndex, int button, int rotationAngle = 0); + + void update(InputState &input_state); + void draw(DrawBuffer &db); + + void setPos(float x, float y) { + x_ = x - w_ / 2; + y_ = y - h_ / 2; + } + +private: + virtual bool isInside(float px, float py) const + { + float margin = 5.0f; + return px >= x_ - margin && py >= y_ - margin && px <= x_ + w_ + margin && py <= y_ + h_ + margin; + } + + const Atlas *atlas_; + + int imageIndex_; + int overlayImageIndex_; + int button_; + int rotationAngle_; + + float x_, y_; + float w_; + float h_; + + // TODO: simplify into flags. + bool pointerDown[MAX_POINTERS]; +}; + + +// Multi-touch enabled virtual joystick +// (any finger will work, simultaneously with other virtual button/stick actions). +class TouchStick +{ +public: + TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick); + + void update(InputState &input_state); + void draw(DrawBuffer &db); + + void setPos(float x, float y) { + stick_x_ = x; + stick_y_ = y; + } + +private: + const Atlas *atlas_; + int bgImageIndex_; + int stickImageIndex_; + int stick_; + int stick_size_; + float stick_x_; + float stick_y_; + + // maintained for drawing only + float stick_delta_x_; + float stick_delta_y_; +}; + From ebf1be596a933853865571cb9a872d3576d11a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 26 Oct 2012 16:16:08 +0200 Subject: [PATCH 0110/1445] Return 0 if resource missing --- gfx/texture_atlas.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gfx/texture_atlas.cpp b/gfx/texture_atlas.cpp index 461bdbe650..1a43f3bcc1 100644 --- a/gfx/texture_atlas.cpp +++ b/gfx/texture_atlas.cpp @@ -7,6 +7,7 @@ const AtlasFont *Atlas::getFontByName(const char *name) const if (!strcmp(name, fonts[i]->name)) return fonts[i]; } + return 0; } const AtlasImage *Atlas::getImageByName(const char *name) const @@ -15,4 +16,5 @@ const AtlasImage *Atlas::getImageByName(const char *name) const if (!strcmp(name, images[i].name)) return &images[i]; } + return 0; } From 748bdb310187f87e2f2f3fd68db10920b0272857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 26 Oct 2012 18:42:17 +0200 Subject: [PATCH 0111/1445] Virtual input code now working --- android/app-android.cpp | 1 + base/PCMain.cpp | 3 +++ gfx_es2/draw_buffer.cpp | 2 +- input/input_state.h | 3 +++ ui/virtual_input.cpp | 32 +++++++++++++++++++------------- ui/virtual_input.h | 4 +++- 6 files changed, 30 insertions(+), 15 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 98a460c263..df7c17d36f 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -211,6 +211,7 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender(JNIE UpdateInputState(&input_state); NativeUpdate(input_state); NativeRender(); + EndInputState(&input_state); time_update(); } else { ELOG("Ended up in nativeRender even though app has quit.%s", ""); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index ce6e13e29e..8bb6299b25 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -306,6 +306,9 @@ int main(int argc, char *argv[]) { UpdateInputState(&input_state); NativeUpdate(input_state); NativeRender(); + + EndInputState(&input_state); + if (framecount % 60 == 0) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index d51b53fbec..d433917c55 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -26,7 +26,7 @@ enum { MAX_VERTS = 15000, }; -DrawBuffer::DrawBuffer() : count_(0) { +DrawBuffer::DrawBuffer() : count_(0), atlas(0) { verts_ = new Vertex[MAX_VERTS]; fontscalex = 1.0f; fontscaley = 1.0f; diff --git a/input/input_state.h b/input/input_state.h index 0e609e89d5..d2114ea184 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -69,5 +69,8 @@ private: inline void UpdateInputState(InputState *input) { input->pad_buttons_down = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_buttons; input->pad_buttons_up = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_last_buttons; +} + +inline void EndInputState(InputState *input) { input->pad_last_buttons = input->pad_buttons; } diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index 07f640f75e..bb4b443507 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -1,46 +1,52 @@ +#include #include "gfx_es2/draw_buffer.h" #include "gfx/texture_atlas.h" #include "input/input_state.h" #include "virtual_input.h" TouchButton::TouchButton(const Atlas *atlas, int imageIndex, int overlayImageIndex, int button, int rotationAngle) - : atlas_(atlas), imageIndex_(imageIndex), overlayImageIndex_(overlayImageIndex), button_(button), rotationAngle_(rotationAngle) + : atlas_(atlas), imageIndex_(imageIndex), overlayImageIndex_(overlayImageIndex), button_(button) { memset(pointerDown, 0, sizeof(pointerDown)); - w_ = atlas->images[imageIndex].w; - h_ = atlas->images[imageIndex].h; + w_ = atlas_->images[imageIndex_].w; + h_ = atlas_->images[imageIndex_].h; + rotationAngle_ = (float)rotationAngle * 3.1415927 / 180.0f; + isDown_ = false; } void TouchButton::update(InputState &input_state) { - bool isDown = false; + isDown_ = false; for (int i = 0; i < MAX_POINTERS; i++) { if (input_state.pointer_down[i] && isInside(input_state.pointer_x[i], input_state.pointer_y[i])) - isDown = true; + isDown_ = true; } - if (isDown) { - int prev_buttons = input_state.pad_buttons; + if (isDown_) { input_state.pad_buttons |= button_; - input_state.pad_buttons_down |= button_ & (~prev_buttons); } else { - input_state.pad_buttons_up &= ~(button_ & input_state.pad_buttons); input_state.pad_buttons &= ~button_; } } void TouchButton::draw(DrawBuffer &db) { - db.DrawImageRotated(imageIndex_, x_ + w_/2, y_ + h_/2, 1.0f, rotationAngle_, 0xFFFFFFFF); + uint32_t color = 0xAAFFFFFF; + float scale = 1.0f; + if (isDown_) { + color = 0xFFFFFFFF; + scale = 2.0f; + } + db.DrawImageRotated(imageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color); if (overlayImageIndex_ != -1) - db.DrawImageRotated(overlayImageIndex_, x_ + w_/2, y_ + h_/2, 1.0f, rotationAngle_, 0xFFFFFFFF); + db.DrawImageRotated(overlayImageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color); } TouchStick::TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick) : atlas_(atlas), bgImageIndex_(bgImageIndex), stickImageIndex_(stickImageIndex), stick_(stick) { - + stick_size_ = atlas_->images[bgImageIndex].w; } void TouchStick::update(InputState &input_state) @@ -77,4 +83,4 @@ void TouchStick::draw(DrawBuffer &db) if (bgImageIndex_ != -1) db.DrawImage(bgImageIndex_, stick_x_, stick_y_, 1.0f, 0xFFFFFFFF, ALIGN_CENTER); db.DrawImage(stickImageIndex_, stick_x_ + stick_delta_x_, stick_y_ + stick_delta_y_, 1.0f, 0xFFFFFFFF, ALIGN_CENTER); -} \ No newline at end of file +} diff --git a/ui/virtual_input.h b/ui/virtual_input.h index 921e83c45e..567c5f9580 100644 --- a/ui/virtual_input.h +++ b/ui/virtual_input.h @@ -27,12 +27,14 @@ private: int imageIndex_; int overlayImageIndex_; int button_; - int rotationAngle_; + float rotationAngle_; float x_, y_; float w_; float h_; + bool isDown_; + // TODO: simplify into flags. bool pointerDown[MAX_POINTERS]; }; From da61ce39503b3a26af1b5812b004bd9dfba5f885 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 27 Oct 2012 12:36:25 +0200 Subject: [PATCH 0112/1445] Various work on surviving the Android activity life cycle --- android/app-android.cpp | 16 +++++----------- gfx_es2/glsl_program.cpp | 12 ++++++++++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index df7c17d36f..95e621ed61 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -24,9 +24,6 @@ #include "net/resolve.h" #include "android/native_audio.h" -#define coord_xres 480 -#define coord_yres 800 - static JNIEnv *jniEnvUI; std::string frameCommand; @@ -175,8 +172,8 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown(JNIEnv *, jcla static jmethodID postCommand; extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { + ILOG("displayInit()"); if (!renderer_inited) { - ILOG("Calling NativeInitGraphics(); dpi = %i", g_dpi); // We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S). // Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo @@ -184,26 +181,23 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayInit(JNIEnv dp_xres = pixel_xres * g_dpi_scale; dp_yres = pixel_yres * g_dpi_scale; + ILOG("Calling NativeInitGraphics(); dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); NativeInitGraphics(); dp_xscale = (float)dp_xres / pixel_xres; dp_yscale = (float)dp_yres / pixel_yres; + renderer_inited = true; } else { ILOG("Calling NativeDeviceLost();"); + NativeDeviceLost(); } - renderer_inited = true; jclass cls = env->GetObjectClass(obj); postCommand = env->GetMethodID(cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); ILOG("MethodID: %i", (int)postCommand); } extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { - ILOG("nativeResize (%i, %i), device lost!", w, h); - if (first_lost) { - first_lost = false; - } else { - NativeDeviceLost(); - } + ILOG("displayResize (%i, %i)!", w, h); } extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 248b4f7db7..a830ecf624 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -210,13 +210,21 @@ bool glsl_recompile(GLSLProgram *program) { } void GLSLProgram::GLLost() { - ILOG("Restoring GLSL program %s/%s", + // Quoth http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html; + // "Note that when the EGL context is lost, all OpenGL resources associated with that context will be automatically deleted. + // You do not need to call the corresponding "glDelete" methods such as glDeleteTextures to manually delete these lost resources." + // Hence, we comment out: + // glDeleteShader(this->vsh_); + // glDeleteShader(this->fsh_); + // glDeleteProgram(this->program_); + ILOG("Restoring GLSL program %s/%s", this->vshader_filename ? this->vshader_filename : "(mem)", this->fshader_filename ? this->fshader_filename : "(mem)"); this->program_ = 0; this->vsh_ = 0; this->fsh_ = 0; - glsl_recompile(this); + glsl_recompile(this); + // Note that uniforms are still lost, hopefully the client sets them every frame at a minimum... } From 4c623111321408d3023f455151b5f76cc445a86e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 27 Oct 2012 16:40:42 +0200 Subject: [PATCH 0113/1445] Screens need to know when the device is lost. Cleanup. --- Android.mk | 2 +- native.vcxproj | 2 -- native.vcxproj.filters | 6 ------ ui/list_screen.cpp | 6 ------ ui/list_screen.h | 10 ---------- ui/screen.cpp | 10 +++++++++- ui/screen.h | 8 +++++--- ui/virtual_input.h | 4 ++++ 8 files changed, 19 insertions(+), 29 deletions(-) delete mode 100644 ui/list_screen.cpp delete mode 100644 ui/list_screen.h diff --git a/Android.mk b/Android.mk index f59e4f9cc5..c1debdd761 100644 --- a/Android.mk +++ b/Android.mk @@ -51,7 +51,7 @@ LOCAL_SRC_FILES :=\ util/random/perlin.cpp -LOCAL_CFLAGS := -O2 +LOCAL_CFLAGS := -O2 -DGL_GLEXT_PROTOTYPES -fsigned-char LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip diff --git a/native.vcxproj b/native.vcxproj index 0ec36aea90..f83b166621 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -237,7 +237,6 @@ - @@ -317,7 +316,6 @@ - diff --git a/native.vcxproj.filters b/native.vcxproj.filters index e9e8ef028d..fff6d79d76 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -194,9 +194,6 @@ base - - ui - base @@ -373,9 +370,6 @@ ui - - ui - base diff --git a/ui/list_screen.cpp b/ui/list_screen.cpp deleted file mode 100644 index c3cedcd59b..0000000000 --- a/ui/list_screen.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "ui/list_screen.h" - -ListScreen::ListScreen() { - -} - diff --git a/ui/list_screen.h b/ui/list_screen.h deleted file mode 100644 index 9dc08f17e2..0000000000 --- a/ui/list_screen.h +++ /dev/null @@ -1,10 +0,0 @@ -#include "ui/screen.h" - - -class ListScreen { -public: - ListScreen(); - -private: - -}; \ No newline at end of file diff --git a/ui/screen.cpp b/ui/screen.cpp index b050e02b9c..47034700ef 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -33,7 +33,7 @@ void ScreenManager::switchScreen(Screen *screen) { } } -void ScreenManager::update(const InputState &input) { +void ScreenManager::update(InputState &input) { if (dialog_.size()) { dialog_.back()->update(input); return; @@ -66,6 +66,14 @@ void ScreenManager::render() { } } +void ScreenManager::deviceLost() +{ + if (currentScreen_) + currentScreen_->deviceLost(); + // Dialogs too? Nah, they should only use the standard UI texture anyway. + // TODO: Change this when it becomes necessary. +} + Screen *ScreenManager::topScreen() { if (dialog_.size()) return dialog_.back(); diff --git a/ui/screen.h b/ui/screen.h index 10404626cb..8fdcae7581 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -31,10 +31,11 @@ class Screen { public: Screen(); virtual ~Screen(); - virtual void update(const InputState &input) = 0; + virtual void update(InputState &input) = 0; virtual void render() {} - + virtual void deviceLost() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} + private: DISALLOW_COPY_AND_ASSIGN(Screen); }; @@ -50,8 +51,9 @@ public: virtual ~ScreenManager(); void switchScreen(Screen *screen); - void update(const InputState &input); + void update(InputState &input); void render(); + void deviceLost(); void shutdown(); // Push a dialog box in front. Currently 1-level only. diff --git a/ui/virtual_input.h b/ui/virtual_input.h index 567c5f9580..765bdccb55 100644 --- a/ui/virtual_input.h +++ b/ui/virtual_input.h @@ -1,5 +1,9 @@ #pragma once +#include "gfx/texture_atlas.h" + +class DrawBuffer; + // Multitouch-enabled emulation of a hardware button. // (any finger will work, simultaneously with other virtual button/stick actions). class TouchButton From 60d3b5f6019af61e64656f0f043f3e5975d75a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 28 Oct 2012 11:37:10 +0100 Subject: [PATCH 0114/1445] UI work --- android/app-android.cpp | 4 +-- base/PCMain.cpp | 14 ++++++++--- file/file_util.cpp | 56 +++++++++++++++++++++++++++++++++++++++-- file/file_util.h | 2 ++ input/input_state.h | 6 ++++- ui/screen.cpp | 4 ++- ui/screen.h | 6 +++++ ui/ui.cpp | 39 ++++++++++++++++++---------- ui/ui.h | 6 ++++- 9 files changed, 114 insertions(+), 23 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 95e621ed61..78addc789c 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -272,7 +272,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_keyDown input_state.pad_buttons |= PAD_BUTTON_BACK; break; case 2: // Menu - input_state.pad_buttons |= PAD_BUTTON_START; + input_state.pad_buttons |= PAD_BUTTON_MENU; break; case 3: // Search input_state.pad_buttons |= PAD_BUTTON_A; @@ -289,7 +289,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_keyUp input_state.pad_buttons &= ~PAD_BUTTON_BACK; break; case 2: // Menu - input_state.pad_buttons &= ~PAD_BUTTON_START; + input_state.pad_buttons &= ~PAD_BUTTON_MENU; break; case 3: // Search input_state.pad_buttons &= ~PAD_BUTTON_A; diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 8bb6299b25..d330d783de 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -56,6 +56,8 @@ void LaunchBrowser(const char *url) #ifdef _WIN32 ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); #else + ILOG("Would have gone to %s but LaunchBrowser is not implemented on this platform", + url); #endif } @@ -64,6 +66,8 @@ void LaunchMarket(const char *url) #ifdef _WIN32 ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); #else + ILOG("Would have gone to %s but LaunchMarket is not implemented on this platform", + url); #endif } @@ -72,12 +76,14 @@ void LaunchEmail(const char *email_address) #ifdef _WIN32 ShellExecute(NULL, "open", (std::string("mailto:") + email_address).c_str(), NULL, NULL, SW_SHOWNORMAL); #else + ILOG("Would have opened your email client for %s but LaunchEmail is not implemented on this platform", + email_address); #endif } -const int buttonMappings[12] = { +const int buttonMappings[14] = { SDLK_x, //A SDLK_s, //B SDLK_z, //X @@ -85,11 +91,13 @@ const int buttonMappings[12] = { SDLK_w, //LBUMPER SDLK_q, //RBUMPER SDLK_1, //START - SDLK_2, //BACK + SDLK_2, //SELECT SDLK_UP, //UP SDLK_DOWN, //DOWN SDLK_LEFT, //LEFT SDLK_RIGHT, //RIGHT + SDLK_m, //MENU + SDLK_BACKSPACE, //BACK }; void SimulateGamepad(const uint8 *keys, InputState *input) { @@ -98,7 +106,7 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_lstick_y = 0; input->pad_rstick_x = 0; input->pad_rstick_y = 0; - for (int b = 0; b < 12; b++) { + for (int b = 0; b < 14; b++) { if (keys[buttonMappings[b]]) input->pad_buttons |= (1< 1) + { + size_t i = fname.length() - 1; + while (fname[i] == DIR_SEP_CHR) + fname[i--] = '\0'; + } + return; +} + +// Returns true if file filename exists +bool exists(const std::string &filename) +{ + struct stat64 file_info; + + std::string copy(filename); + stripTailDirSlashes(copy); + + int result = stat64(copy.c_str(), &file_info); + + return (result == 0); +} + +// Returns true if filename is a directory +bool isDirectory(const std::string &filename) +{ + struct stat64 file_info; + + std::string copy(filename); + stripTailDirSlashes(copy); + + int result = stat64(copy.c_str(), &file_info); + + if (result < 0) { + WLOG("IsDirectory: stat failed on %s", filename.c_str()); + return false; + } + + return S_ISDIR(file_info.st_mode); +} + size_t getFilesInDir(const char *directory, std::vector *files) { size_t foundEntries = 0; #ifdef _WIN32 @@ -96,9 +141,14 @@ size_t getFilesInDir(const char *directory, std::vector *files) { ((virtualName[0] == '.') && (virtualName[1] == '.') && (virtualName[2] == '\0'))) continue; + + // Remove dotfiles (should be made optional?) + if (virtualName[0] == '.') + continue; FileInfo info; - info.name = std::string(directory) + virtualName; - info.isDirectory = false; // TODO + info.name = virtualName; + info.fullName = std::string(directory) + "/" + virtualName; + info.isDirectory = isDirectory(info.fullName); files->push_back(info); #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); @@ -127,6 +177,8 @@ void deleteFile(const char *file) std::string getDir(const std::string &path) { + if (path == "/") + return path; int n = path.size() - 1; while (n >= 0 && path[n] != '\\' && path[n] != '/') n--; diff --git a/file/file_util.h b/file/file_util.h index 62202155a9..e269b08151 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -12,10 +12,12 @@ bool readFileToString(bool text_file, const char *filename, std::string &str); struct FileInfo { std::string name; + std::string fullName; bool isDirectory; }; size_t getFilesInDir(const char *directory, std::vector *files); void deleteFile(const char *file); +bool exists(const std::string &filename); std::string getDir(const std::string &path); diff --git a/input/input_state.h b/input/input_state.h index d2114ea184..b73c65fe40 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -12,11 +12,15 @@ enum { PAD_BUTTON_LBUMPER = 16, PAD_BUTTON_RBUMPER = 32, PAD_BUTTON_START = 64, - PAD_BUTTON_BACK = 128, + PAD_BUTTON_SELECT = 128, PAD_BUTTON_UP = 256, PAD_BUTTON_DOWN = 512, PAD_BUTTON_LEFT = 1024, PAD_BUTTON_RIGHT = 2048, + + // Android only + PAD_BUTTON_MENU = 4096, + PAD_BUTTON_BACK = 8192, }; #ifndef MAX_POINTERS diff --git a/ui/screen.cpp b/ui/screen.cpp index 47034700ef..5ce710abaa 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -2,7 +2,7 @@ #include "input/input_state.h" #include "ui/screen.h" -Screen::Screen() { } +Screen::Screen() : screenManager_(0) { } Screen::~Screen() { } ScreenManager::ScreenManager() { @@ -30,6 +30,7 @@ void ScreenManager::switchScreen(Screen *screen) { } if (screen != currentScreen_) { nextScreen_ = screen; + nextScreen_->setScreenManager(this); } } @@ -93,6 +94,7 @@ void ScreenManager::shutdown() { } void ScreenManager::push(Screen *screen) { + screen->setScreenManager(this); dialog_.push_back(screen); } diff --git a/ui/screen.h b/ui/screen.h index 8fdcae7581..36d4993f9f 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -27,6 +27,8 @@ enum DialogResult { DR_NO, }; +class ScreenManager; + class Screen { public: Screen(); @@ -36,7 +38,11 @@ public: virtual void deviceLost() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} + ScreenManager *screenManager() { return screenManager_; } + void setScreenManager(ScreenManager *sm) { screenManager_ = sm; } + private: + ScreenManager *screenManager_; DISALLOW_COPY_AND_ASSIGN(Screen); }; diff --git a/ui/ui.cpp b/ui/ui.cpp index 1d7c8dec65..99fbedc10a 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -44,6 +44,10 @@ void UIUpdateMouse(int i, float x, float y, bool down) { uistate.mousedown[i] = down; } +void UIReset() { + memset(&uistate, 0, sizeof(uistate)); +} + bool UIRegionHit(int i, int x, int y, int w, int h, int margin) { // Input handling if (uistate.mousex[i] < x - margin || @@ -108,8 +112,9 @@ int UIButton(int id, const LayoutManager &layout, float w, const char *text, int // Check whether the button should be hot, use a generous margin for touch ease if (UIRegionHit(i, x, y, w, h, 8)) { uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) { uistate.activeitem[i] = id; + } } if (uistate.hotitem[i] == id) { @@ -126,9 +131,9 @@ int UIButton(int id, const LayoutManager &layout, float w, const char *text, int // If button is hot and active, but mouse button is not // down, the user must have clicked the button. if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && - uistate.activeitem[i] == id) { - clicked = 1; + uistate.hotitem[i] == id && + uistate.activeitem[i] == id) { + clicked = 1; } } @@ -248,9 +253,12 @@ void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, boo ui_draw2d.DrawTextShadow(theme.uiFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); } -int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { - const int item_h = 64; +UIList::UIList() + : scrollY(0.0f), startDragY(0.0f), dragFinger(-1), selected(-1) { +} + +int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { int clicked = 0; for (int i = 0; i < MAX_POINTERS; i++) { @@ -276,13 +284,18 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { int numItems = adapter->getCount(); for (int i = 0; i < numItems; i++) { int item_y = y + i * itemHeight - scrollY; - if (uistate.mousedown && - adapter->itemEnabled(i) && - item_y >= y - itemHeight && - item_y <= y + h && - UIRegionHit(i, x, item_y, w, h, 0)) { - selected = i; - } + + for (int k = 0; k < MAX_POINTERS; k++) { + if (uistate.mousedown[k] && + uistate.mouseframesdown[k] > 10 && + adapter->itemEnabled(i) && + item_y >= y - itemHeight && + item_y <= y + h && + UIRegionHit(k, x, item_y, w, itemHeight, 0)) { + printf("%i", item_y); + selected = i; + } + } adapter->drawItem(i, x, item_y, w, itemHeight, i == selected); } uistate.lastwidget = id; diff --git a/ui/ui.h b/ui/ui.h index 2e4faed7e3..8e8bb52eaf 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -86,6 +86,7 @@ private: // Mouse out of habit, applies just as well to touch events. // UI does not yet support multitouch. // This struct is zeroed on init, so should be valid at that state. +// Never inherit from this. struct UIState { int mousex[MAX_POINTERS]; int mousey[MAX_POINTERS]; @@ -179,6 +180,9 @@ void UIBegin(); void UIUpdateMouse(int i, float x, float y, bool down); +// Call when you switch screens +void UIReset(); + // Returns 1 if clicked int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align); int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images. @@ -202,7 +206,7 @@ void UISlideChoice(int id, int y, const SlideItem *items, int numItems, UISlideS class UIList { public: - UIList() : scrollY(0.0f), startDragY(0.0f), dragFinger(-1), selected(-1) {} + UIList(); float scrollY; float startDragY; int dragFinger; From ef01fc2121764216ee63da5fb73c22105cc5232a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 28 Oct 2012 11:47:26 +0100 Subject: [PATCH 0115/1445] Buildfix, bugfix --- file/file_util.cpp | 5 +++++ tools/CMakeLists.txt | 33 +++++++++++++++------------------ tools/b.sh | 0 3 files changed, 20 insertions(+), 18 deletions(-) mode change 100644 => 100755 tools/b.sh diff --git a/file/file_util.cpp b/file/file_util.cpp index bfaf401775..3331b55e28 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -187,5 +187,10 @@ std::string getDir(const std::string &path) { if (cutpath[i] == '\\') cutpath[i] = '/'; } +#ifndef _WIN32 + if (!cutpath.size()) { + return "/"; + } +#endif return cutpath; } diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 4eb2cedcca..4d7d8b2b1a 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -3,9 +3,6 @@ cmake_minimum_required(VERSION 2.6) project (Tools) find_package(PNG REQUIRED) - - -add_definitions(-g) add_definitions(-O2) add_definitions(-Wall) add_definitions(-DSDL) @@ -14,12 +11,11 @@ add_definitions(-fno-strict-aliasing) add_definitions(-fopenmp) # add_definitions(-fstrict-aliasing) -include_directories(../native) -include_directories(../native/base) -include_directories(../native/math/lin) -include_directories(../native/image) -include_directories(../native/ext/libzip) -include_directories(../native/ext/etcpack) +include_directories(..) +include_directories(../math/lin) +include_directories(../image) +include_directories(../ext/libzip) +include_directories(../ext/etcpack) include_directories(/usr/local/include) include_directories(${PNG_INCLUDE_DIR}) @@ -31,17 +27,18 @@ include_directories(/usr/include/freetype2) include_directories(/usr/local/include/freetype2) include_directories(/opt/local/include/freetype2) -add_subdirectory(../native/base base) -add_subdirectory(../native/gfx gfx) -add_subdirectory(../native/file file) -add_subdirectory(../native/image image) -add_subdirectory(../native/math math) -add_subdirectory(../native/ext/libzip libzip) -add_subdirectory(../native/ext/etcpack etcpack) +add_subdirectory(../base base) +add_subdirectory(../gfx gfx) +add_subdirectory(../file file) +add_subdirectory(../image image) +add_subdirectory(../math math) +add_subdirectory(../ext/libzip libzip) +add_subdirectory(../ext/etcpack etcpack) +add_subdirectory(../ext/stb_image stb_image) add_executable(atlastool atlastool.cpp) -target_link_libraries(atlastool ${PNG_LIBRARY} freetype z image etcpack etcdec file zip gomp) +target_link_libraries(atlastool ${PNG_LIBRARY} freetype z image stb_image etcpack etcdec file zip gomp) add_executable(zimtool zimtool.cpp) -target_link_libraries(zimtool ${PNG_LIBRARY} freetype z image etcpack etcdec file zip gomp) +target_link_libraries(zimtool ${PNG_LIBRARY} freetype z image stb_image etcpack etcdec file zip gomp) diff --git a/tools/b.sh b/tools/b.sh old mode 100644 new mode 100755 From 4b123b25cc450e4bd5d07c3ad592d78be560011d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 29 Oct 2012 14:49:09 +0100 Subject: [PATCH 0116/1445] Reindent UI --- ui/screen.cpp | 128 ++++++------ ui/screen.h | 34 +-- ui/ui.cpp | 484 ++++++++++++++++++++++--------------------- ui/ui.h | 162 ++++++++------- ui/virtual_input.cpp | 18 +- ui/virtual_input.h | 6 +- 6 files changed, 422 insertions(+), 410 deletions(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index 5ce710abaa..5b2357cc65 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -15,50 +15,50 @@ ScreenManager::~ScreenManager() { } void ScreenManager::switchScreen(Screen *screen) { - if (dialog_.size()) - { - WLOG("Switching screens - dropping the whole dialog stack"); - while (dialog_.size()) - pop(); - } - // TODO: is this still true? - // Note that if a dialog is found, this will be a silent background switch that - // will only become apparent if the dialog is closed. The previous screen will stick around - // until that switch. - if (nextScreen_ != 0) { - FLOG("WTF? Already had a nextScreen_"); - } - if (screen != currentScreen_) { - nextScreen_ = screen; + if (dialog_.size()) + { + WLOG("Switching screens - dropping the whole dialog stack"); + while (dialog_.size()) + pop(); + } + // TODO: is this still true? + // Note that if a dialog is found, this will be a silent background switch that + // will only become apparent if the dialog is closed. The previous screen will stick around + // until that switch. + if (nextScreen_ != 0) { + FLOG("WTF? Already had a nextScreen_"); + } + if (screen != currentScreen_) { + nextScreen_ = screen; nextScreen_->setScreenManager(this); - } + } } void ScreenManager::update(InputState &input) { - if (dialog_.size()) { - dialog_.back()->update(input); - return; - } + if (dialog_.size()) { + dialog_.back()->update(input); + return; + } if (nextScreen_) { - ILOG("Screen switch!"); - Screen *temp = currentScreen_; + ILOG("Screen switch!"); + Screen *temp = currentScreen_; currentScreen_ = nextScreen_; - delete temp; - temp = 0; + delete temp; + temp = 0; nextScreen_ = 0; } if (currentScreen_) { currentScreen_->update(input); - } + } } void ScreenManager::render() { - if (dialog_.size()) { - dialog_.back()->render(); - return; - } + if (dialog_.size()) { + dialog_.back()->render(); + return; + } if (currentScreen_) { currentScreen_->render(); } @@ -76,53 +76,53 @@ void ScreenManager::deviceLost() } Screen *ScreenManager::topScreen() { - if (dialog_.size()) - return dialog_.back(); - else - return currentScreen_; + if (dialog_.size()) + return dialog_.back(); + else + return currentScreen_; } void ScreenManager::shutdown() { - if (nextScreen_) { - delete nextScreen_; - nextScreen_ = 0; - } - if (currentScreen_) { - delete currentScreen_; - currentScreen_ = 0; - } + if (nextScreen_) { + delete nextScreen_; + nextScreen_ = 0; + } + if (currentScreen_) { + delete currentScreen_; + currentScreen_ = 0; + } } void ScreenManager::push(Screen *screen) { screen->setScreenManager(this); - dialog_.push_back(screen); + dialog_.push_back(screen); } void ScreenManager::pop() { - if (dialog_.size()) { - delete dialog_.back(); - dialog_.pop_back(); - } else { - ELOG("Can't push when no dialog is shown"); - } + if (dialog_.size()) { + delete dialog_.back(); + dialog_.pop_back(); + } else { + ELOG("Can't push when no dialog is shown"); + } } void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) { - if (!dialog_.size()) { - ELOG("Must be in a dialog to finishDialog"); - return; - } - Screen *dlg = dialog_.back(); - if (dialog != dialog_.back()) - { - ELOG("Wrong dialog being finished!"); - return; - } - if (dialog_.size()) { - dialog_.pop_back(); - } - Screen *caller = topScreen(); - caller->dialogFinished(dialog, result); - delete dialog; + if (!dialog_.size()) { + ELOG("Must be in a dialog to finishDialog"); + return; + } + Screen *dlg = dialog_.back(); + if (dialog != dialog_.back()) + { + ELOG("Wrong dialog being finished!"); + return; + } + if (dialog_.size()) { + dialog_.pop_back(); + } + Screen *caller = topScreen(); + caller->dialogFinished(dialog, result); + delete dialog; } diff --git a/ui/screen.h b/ui/screen.h index 36d4993f9f..4c6af7bccb 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -21,10 +21,10 @@ struct InputState; enum DialogResult { - DR_OK, - DR_CANCEL, - DR_YES, - DR_NO, + DR_OK, + DR_CANCEL, + DR_YES, + DR_NO, }; class ScreenManager; @@ -36,14 +36,14 @@ public: virtual void update(InputState &input) = 0; virtual void render() {} virtual void deviceLost() {} - virtual void dialogFinished(const Screen *dialog, DialogResult result) {} + virtual void dialogFinished(const Screen *dialog, DialogResult result) {} ScreenManager *screenManager() { return screenManager_; } void setScreenManager(ScreenManager *sm) { screenManager_ = sm; } private: ScreenManager *screenManager_; - DISALLOW_COPY_AND_ASSIGN(Screen); + DISALLOW_COPY_AND_ASSIGN(Screen); }; class Transition { @@ -60,22 +60,22 @@ public: void update(InputState &input); void render(); void deviceLost(); - void shutdown(); + void shutdown(); - // Push a dialog box in front. Currently 1-level only. - void push(Screen *screen); + // Push a dialog box in front. Currently 1-level only. + void push(Screen *screen); - // Pops the dialog away. - void finishDialog(const Screen *dialog, DialogResult result = DR_OK); + // Pops the dialog away. + void finishDialog(const Screen *dialog, DialogResult result = DR_OK); private: - void pop(); - Screen *topScreen(); - // Base screen. These don't "stack" and you can move in any order between them. + void pop(); + Screen *topScreen(); + // Base screen. These don't "stack" and you can move in any order between them. Screen *currentScreen_; Screen *nextScreen_; - // Dialog stack. These are shown "on top" of base screens and the Android back button works as expected. - // Used for options, in-game menus and other things you expect to be able to back out from onto something. - std::list dialog_; + // Dialog stack. These are shown "on top" of base screens and the Android back button works as expected. + // Used for options, in-game menus and other things you expect to be able to back out from onto something. + std::list dialog_; }; diff --git a/ui/ui.cpp b/ui/ui.cpp index 99fbedc10a..aabebbab0a 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -19,29 +19,29 @@ static const Atlas *themeAtlas; static UITheme theme; void UIInit(const Atlas *atlas, const UITheme &ui_theme) { - ui_draw2d.SetAtlas(atlas); - ui_draw2d_front.SetAtlas(atlas); - themeAtlas = atlas; - theme = ui_theme; - memset(&uistate, 0, sizeof(uistate)); + ui_draw2d.SetAtlas(atlas); + ui_draw2d_front.SetAtlas(atlas); + themeAtlas = atlas; + theme = ui_theme; + memset(&uistate, 0, sizeof(uistate)); } void UIUpdateMouse(int i, float x, float y, bool down) { - if (down && !uistate.mousedown[i]) { - uistate.mousepressed[i] = 1; - uistate.mouseStartX[i] = x; - uistate.mouseStartY[i] = y; - } else { - uistate.mousepressed[i] = 0; - } - if (uistate.mousedown[i]) - uistate.mouseframesdown[i]++; - else - uistate.mouseframesdown[i] = 0; + if (down && !uistate.mousedown[i]) { + uistate.mousepressed[i] = 1; + uistate.mouseStartX[i] = x; + uistate.mouseStartY[i] = y; + } else { + uistate.mousepressed[i] = 0; + } + if (uistate.mousedown[i]) + uistate.mouseframesdown[i]++; + else + uistate.mouseframesdown[i] = 0; - uistate.mousex[i] = x; - uistate.mousey[i] = y; - uistate.mousedown[i] = down; + uistate.mousex[i] = x; + uistate.mousey[i] = y; + uistate.mousedown[i] = down; } void UIReset() { @@ -49,259 +49,265 @@ void UIReset() { } bool UIRegionHit(int i, int x, int y, int w, int h, int margin) { - // Input handling - if (uistate.mousex[i] < x - margin || - uistate.mousey[i] < y - margin || - uistate.mousex[i] >= x + w + margin || - uistate.mousey[i] >= y + h + margin) { - return false; - } else { - return true; - } + // Input handling + if (uistate.mousex[i] < x - margin || + uistate.mousey[i] < y - margin || + uistate.mousex[i] >= x + w + margin || + uistate.mousey[i] >= y + h + margin) { + return false; + } else { + return true; + } } void UIBegin() { - for (int i = 0; i < MAX_POINTERS; i++) - uistate.hotitem[i] = 0; - ui_draw2d.Begin(); - ui_draw2d_front.Begin(); + for (int i = 0; i < MAX_POINTERS; i++) + uistate.hotitem[i] = 0; + ui_draw2d.Begin(); + ui_draw2d_front.Begin(); } void UIEnd() { - for (int i = 0; i < MAX_POINTERS; i++) { - if (uistate.mousedown[i] == 0) { - uistate.activeitem[i] = 0; - } else { - if (uistate.activeitem[i] == 0) { - uistate.activeitem[i] = -1; - } - } - } - ui_draw2d.End(); - ui_draw2d_front.End(); + for (int i = 0; i < MAX_POINTERS; i++) { + if (uistate.mousedown[i] == 0) { + uistate.activeitem[i] = 0; + } else { + if (uistate.activeitem[i] == 0) { + uistate.activeitem[i] = -1; + } + } + } + ui_draw2d.End(); + ui_draw2d_front.End(); - if (uistate.ui_tick > 0) - uistate.ui_tick--; + if (uistate.ui_tick > 0) + uistate.ui_tick--; } void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) { - UIText(theme.uiFont, x, y, text, color, scale, align); + UIText(theme.uiFont, x, y, text, color, scale, align); } void UIText(int font, int x, int y, const char *text, uint32_t color, float scale, int align) { - ui_draw2d.SetFontScale(scale, scale); - ui_draw2d.DrawTextShadow(font, text, x, y, color, align); - ui_draw2d.SetFontScale(1.0f, 1.0f); + ui_draw2d.SetFontScale(scale, scale); + ui_draw2d.DrawTextShadow(font, text, x, y, color, align); + ui_draw2d.SetFontScale(1.0f, 1.0f); } int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align) { - float h = themeAtlas->images[theme.buttonImage].h; + float h = themeAtlas->images[theme.buttonImage].h; - float x, y; - layout.GetPos(&w, &h, &x, &y); + float x, y; + layout.GetPos(&w, &h, &x, &y); - if (button_align & ALIGN_HCENTER) x -= w / 2; - if (button_align & ALIGN_VCENTER) y -= h / 2; - if (button_align & ALIGN_RIGHT) x -= w; - if (button_align & ALIGN_BOTTOMRIGHT) y -= h; + if (button_align & ALIGN_HCENTER) x -= w / 2; + if (button_align & ALIGN_VCENTER) y -= h / 2; + if (button_align & ALIGN_RIGHT) x -= w; + if (button_align & ALIGN_BOTTOMRIGHT) y -= h; - int txOffset = 0; + int txOffset = 0; - int clicked = 0; - for (int i = 0; i < MAX_POINTERS; i++) { - // Check whether the button should be hot, use a generous margin for touch ease - if (UIRegionHit(i, x, y, w, h, 8)) { - uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) { - uistate.activeitem[i] = id; + int clicked = 0; + for (int i = 0; i < MAX_POINTERS; i++) { + // Check whether the button should be hot, use a generous margin for touch ease + if (UIRegionHit(i, x, y, w, h, 8)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) { + uistate.activeitem[i] = id; } - } + } - if (uistate.hotitem[i] == id) { - if (uistate.activeitem[i] == id) { - // Button is both 'hot' and 'active' - txOffset = 2; - } else { - // Button is merely 'hot' - } - } else { - // button is not hot, but it may be active - } + if (uistate.hotitem[i] == id) { + if (uistate.activeitem[i] == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && uistate.activeitem[i] == id) { - clicked = 1; - } - } + clicked = 1; + } + } - // Render button + // Render button - ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); - ui_draw2d.DrawTextShadow(theme.uiFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); + ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); + ui_draw2d.DrawTextShadow(theme.uiFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); - uistate.lastwidget = id; - return clicked; + uistate.lastwidget = id; + return clicked; } int UIImageButton(int id, const LayoutManager &layout, float w, int image, int button_align) { - float h = 64; - float x, y; - layout.GetPos(&w, &h, &x, &y); + float h = 64; + float x, y; + layout.GetPos(&w, &h, &x, &y); - if (button_align & ALIGN_HCENTER) x -= w / 2; - if (button_align & ALIGN_VCENTER) y -= h / 2; - if (button_align & ALIGN_RIGHT) x -= w; - if (button_align & ALIGN_BOTTOMRIGHT) y -= h; + if (button_align & ALIGN_HCENTER) x -= w / 2; + if (button_align & ALIGN_VCENTER) y -= h / 2; + if (button_align & ALIGN_RIGHT) x -= w; + if (button_align & ALIGN_BOTTOMRIGHT) y -= h; - int txOffset = 0; - int clicked = 0; - for (int i = 0; i < MAX_POINTERS; i++) { - // Check whether the button should be hot, use a generous margin for touch ease - if (UIRegionHit(i, x, y, w, h, 8)) { - uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) - uistate.activeitem[i] = id; - } + int txOffset = 0; + int clicked = 0; + for (int i = 0; i < MAX_POINTERS; i++) { + // Check whether the button should be hot, use a generous margin for touch ease + if (UIRegionHit(i, x, y, w, h, 8)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } - if (uistate.hotitem[i] == id) { - if (uistate.activeitem[i] == id) { - // Button is both 'hot' and 'active' - txOffset = 2; - } else { - // Button is merely 'hot' - } - } else { - // button is not hot, but it may be active - } + if (uistate.hotitem[i] == id) { + if (uistate.activeitem[i] == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active§ + } - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && - uistate.activeitem[i] == id) { - clicked = 1; - } - } + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id) { + clicked = 1; + } + } - // Render button + // Render button - ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); - ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); + ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); + ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); - uistate.lastwidget = id; - return clicked; + uistate.lastwidget = id; + return clicked; } int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { - const int h = 64; - float tw, th; - ui_draw2d.MeasureText(theme.uiFont, text, &tw, &th); - int w = themeAtlas->images[theme.checkOn].w + UI_SPACE + tw; - if (align & ALIGN_HCENTER) x -= w / 2; - if (align & ALIGN_VCENTER) y -= h / 2; - if (align & ALIGN_RIGHT) x -= w; - if (align & ALIGN_BOTTOMRIGHT) y -= h; + const int h = 64; + float tw, th; + ui_draw2d.MeasureText(theme.uiFont, text, &tw, &th); + int w = themeAtlas->images[theme.checkOn].w + UI_SPACE + tw; + if (align & ALIGN_HCENTER) x -= w / 2; + if (align & ALIGN_VCENTER) y -= h / 2; + if (align & ALIGN_RIGHT) x -= w; + if (align & ALIGN_BOTTOMRIGHT) y -= h; - int txOffset = 0; - int clicked = 0; - for (int i = 0; i < MAX_POINTERS; i++) { + int txOffset = 0; + int clicked = 0; + for (int i = 0; i < MAX_POINTERS; i++) { - // Check whether the button should be hot - if (UIRegionHit(i, x, y, w, h, 8)) { - uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) - uistate.activeitem[i] = id; - } + // Check whether the button should be hot + if (UIRegionHit(i, x, y, w, h, 8)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } - // Render button + // Render button - if (uistate.hotitem[i] == id) { - if (uistate.activeitem[i] == id) { - // Button is both 'hot' and 'active' - txOffset = 2; - } else { - // Button is merely 'hot' - } - } else { - // button is not hot, but it may be active - } - // If button is hot and active, but mouse button is not - // down, the user must have clicked the button. - if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && - uistate.activeitem[i] == id) { - *value = !(*value); - clicked = 1; - } - } + if (uistate.hotitem[i] == id) { + if (uistate.activeitem[i] == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id) { + *value = !(*value); + clicked = 1; + } + } - ui_draw2d.DrawImage((*value) ? theme.checkOn : theme.checkOff, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); - ui_draw2d.DrawTextShadow(theme.uiFont, text, x + themeAtlas->images[theme.checkOn].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + ui_draw2d.DrawImage((*value) ? theme.checkOn : theme.checkOff, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + ui_draw2d.DrawTextShadow(theme.uiFont, text, x + themeAtlas->images[theme.checkOn].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); - uistate.lastwidget = id; - return clicked; + uistate.lastwidget = id; + return clicked; } void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, bool selected) const { - ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); - ui_draw2d.DrawTextShadow(theme.uiFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); + ui_draw2d.DrawTextShadow(theme.uiFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); } -UIList::UIList() +UIList::UIList() : scrollY(0.0f), startDragY(0.0f), dragFinger(-1), selected(-1) { + movedDistanceY = 0.0f; } int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { - int clicked = 0; + bool pointerDown = false; - for (int i = 0; i < MAX_POINTERS; i++) { - // Check whether the button should be hot - if (UIRegionHit(i, x, y, w, h, 0)) { - uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) - uistate.activeitem[i] = id; - } + // UIList only cares about the first pointer for simplicity. + // Probably not much need to scroll one of these while dragging something + // else. + for (int i = 0; i < 1; i++) { + // Check for hover + if (UIRegionHit(i, x, y, w, h, 0)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) { + // Mousedown + uistate.activeitem[i] = id; + } + } - // If button is hot and active, but mouse button is not - // down, the user must have clicked a list item (unless after the last item). - if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && - uistate.activeitem[i] == id && - selected != -1) { - clicked = 1; - } - } + // If button is hot and active, but mouse button is not + // down, the user must have clicked a list item (unless after the last item). + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id && + selected != -1) { + clicked = 1; + } + } - // render items - int itemHeight = adapter->itemHeight(0); - int numItems = adapter->getCount(); - for (int i = 0; i < numItems; i++) { - int item_y = y + i * itemHeight - scrollY; + // render items + int itemHeight = adapter->itemHeight(0); + int numItems = adapter->getCount(); + for (int i = 0; i < numItems; i++) { + int item_y = y + i * itemHeight - scrollY; for (int k = 0; k < MAX_POINTERS; k++) { if (uistate.mousedown[k] && uistate.mouseframesdown[k] > 10 && - adapter->itemEnabled(i) && - item_y >= y - itemHeight && + adapter->itemEnabled(i) && + item_y >= y - itemHeight && item_y <= y + h && UIRegionHit(k, x, item_y, w, itemHeight, 0)) { printf("%i", item_y); selected = i; } } - adapter->drawItem(i, x, item_y, w, itemHeight, i == selected); - } - uistate.lastwidget = id; + adapter->drawItem(i, x, item_y, w, itemHeight, i == selected); + } + uistate.lastwidget = id; - // Otherwise, no clicky. - return clicked; + // Otherwise, no clicky. + return clicked; } /* @@ -311,7 +317,7 @@ int image; uint32_t bgColor; }; -struct SlideState +struct SlideState { float scroll; @@ -323,49 +329,49 @@ void UISlideChoice(int id, int y, const SlideItem *items, int numItems, SlideSta // TODO int UIHSlider(int id, int x, int y, int w, int max, int *value) { - // Calculate mouse cursor's relative y offset - int xpos = ((256 - 16) * *value) / max; + // Calculate mouse cursor's relative y offset + int xpos = ((256 - 16) * *value) / max; - for (int i = 0; i < MAX_POINTERS; i++) { - // Check for hotness - if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) { - uistate.hotitem[i] = id; - if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) - uistate.activeitem[i] = id; - } + for (int i = 0; i < MAX_POINTERS; i++) { + // Check for hotness + if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } - // Update widget value - if (uistate.activeitem[i] == id) { - int mousepos = uistate.mousey[i] - (y + 8); - if (mousepos < 0) mousepos = 0; - if (mousepos > 255) mousepos = 255; - int v = (mousepos * max) / 255; - if (v != *value) { - *value = v; - return 1; - } - } - } - // Render the scrollbar - ui_draw2d.Rect(x, y, 32, 256+16, 0x777777); + // Update widget value + if (uistate.activeitem[i] == id) { + int mousepos = uistate.mousey[i] - (y + 8); + if (mousepos < 0) mousepos = 0; + if (mousepos > 255) mousepos = 255; + int v = (mousepos * max) / 255; + if (v != *value) { + *value = v; + return 1; + } + } + } + // Render the scrollbar + ui_draw2d.Rect(x, y, 32, 256+16, 0x777777); - ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xffffff); + ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xffffff); - return 0; + return 0; } /* // TODO int UIVSlider(int id, int x, int y, int h, int max, int *value) { - // Calculate mouse cursor's relative y offset - int ypos = ((256 - 16) * *value) / max; + // Calculate mouse cursor's relative y offset + int ypos = ((256 - 16) * *value) / max; - // Check for hotness - if (UIRegionHit(x+8, y+8, 16, 255, 0)) { - uistate.hotitem = id; - if (uistate.activeitem == 0 && uistate.mousedown) - uistate.activeitem = id; - } + // Check for hotness + if (UIRegionHit(x+8, y+8, 16, 255, 0)) { + uistate.hotitem = id; + if (uistate.activeitem == 0 && uistate.mousedown) + uistate.activeitem = id; + } // Update widget value if (uistate.activeitem == id) { int mousepos = uistate.mousey - (y + 8); @@ -377,12 +383,12 @@ int UIVSlider(int id, int x, int y, int h, int max, int *value) { return 1; } } - // Render the scrollbar - ui_draw2d.Rect(x, y, 32, 256+16, 0x777777); - - ui_draw2d.Rect(x+8, y+8 + ypos, 16, 16, 0xffffff); + // Render the scrollbar + ui_draw2d.Rect(x, y, 32, 256+16, 0x777777); - - return 0; + ui_draw2d.Rect(x+8, y+8 + ypos, 16, 16, 0xffffff); + + + return 0; } */ diff --git a/ui/ui.h b/ui/ui.h index 8e8bb52eaf..35089b0ff4 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -31,84 +31,84 @@ class LayoutManager { public: - virtual void GetPos(float *w, float *h, float *x, float *y) const = 0; + virtual void GetPos(float *w, float *h, float *x, float *y) const = 0; }; class Pos : public LayoutManager { public: - Pos(float x, float y) : x_(x), y_(y) {} - virtual void GetPos(float *w, float *h, float *x, float *y) const { - *x = x_; - *y = y_; - } + Pos(float x, float y) : x_(x), y_(y) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + } private: - float x_; - float y_; + float x_; + float y_; }; class HLinear : public LayoutManager { public: - HLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {} - virtual void GetPos(float *w, float *h, float *x, float *y) const { - *x = x_; - *y = y_; - x_ += *w + spacing_; - } - void Space(float x) { - x_ += x; - } + HLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + x_ += *w + spacing_; + } + void Space(float x) { + x_ += x; + } private: - mutable float x_; - float y_; - float spacing_; + mutable float x_; + float y_; + float spacing_; }; class VLinear : public LayoutManager { public: - VLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {} - virtual void GetPos(float *w, float *h, float *x, float *y) const { - *x = x_; - *y = y_; - y_ += *h + spacing_; - } + VLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + y_ += *h + spacing_; + } private: - float x_; - mutable float y_; - float spacing_; + float x_; + mutable float y_; + float spacing_; }; #ifndef MAX_POINTERS #define MAX_POINTERS 8 #endif -// Mouse out of habit, applies just as well to touch events. -// UI does not yet support multitouch. +// "Mouse" out of habit, applies just as well to touch events. +// TODO: Change to "pointer" // This struct is zeroed on init, so should be valid at that state. // Never inherit from this. struct UIState { - int mousex[MAX_POINTERS]; - int mousey[MAX_POINTERS]; - bool mousedown[MAX_POINTERS]; - bool mousepressed[MAX_POINTERS]; - short mouseframesdown[MAX_POINTERS]; + int mousex[MAX_POINTERS]; + int mousey[MAX_POINTERS]; + bool mousedown[MAX_POINTERS]; + bool mousepressed[MAX_POINTERS]; + short mouseframesdown[MAX_POINTERS]; - int mouseStartX[MAX_POINTERS]; - int mouseStartY[MAX_POINTERS]; + int mouseStartX[MAX_POINTERS]; + int mouseStartY[MAX_POINTERS]; - int hotitem[MAX_POINTERS]; - int activeitem[MAX_POINTERS]; + int hotitem[MAX_POINTERS]; + int activeitem[MAX_POINTERS]; - // keyboard focus, not currently used - int kbdwidget; - int lastwidget; + // keyboard focus, not currently used + int kbdwidget; + int lastwidget; - // Used by controls that need to keep track of the initial value for drags, for example. - // Should probably be indexed by finger - would be neat to be able to move two knobs at the same time. - float tempfloat; + // Used by controls that need to keep track of the initial value for drags, for example. + // Should probably be indexed by finger - would be neat to be able to move two knobs at the same time. + float tempfloat; - int ui_tick; + int ui_tick; }; // This needs to be extern so that additional UI controls can be developed outside this file. @@ -119,15 +119,15 @@ struct Atlas; // This is the drawbuffer used for UI. Remember to flush it at the end of the frame. // TODO: One should probably pass it in through UIInit. extern DrawBuffer ui_draw2d; -extern DrawBuffer ui_draw2d_front; // for things that need to be on top of the rest +extern DrawBuffer ui_draw2d_front; // for things that need to be on top of the rest struct UITheme { - int uiFont; - int uiFontSmall; - int uiFontSmaller; - int buttonImage; - int checkOn; - int checkOff; + int uiFont; + int uiFontSmall; + int uiFontSmaller; + int buttonImage; + int checkOn; + int checkOff; }; // The atlas needs to stick around, the theme is copied. @@ -143,32 +143,32 @@ const int LARGE_BUTTON_WIDTH = 192; const int BUTTON_HEIGHT = 72; struct SlideItem { - const char *text; - int image; - uint32_t bgColor; + const char *text; + int image; + uint32_t bgColor; }; struct UISlideState { - float scroll; + float scroll; }; // Implement this interface to style your lists class UIListAdapter { public: - virtual size_t getCount() const = 0; - virtual void drawItem(int item, int x, int y, int w, int h, bool active) const = 0; - virtual float itemHeight(int itemIndex) const { return 64; } - virtual bool itemEnabled(int itemIndex) const { return true; } + virtual size_t getCount() const = 0; + virtual void drawItem(int item, int x, int y, int w, int h, bool active) const = 0; + virtual float itemHeight(int itemIndex) const { return 64; } + virtual bool itemEnabled(int itemIndex) const { return true; } }; class StringVectorListAdapter : public UIListAdapter { public: - StringVectorListAdapter(const std::vector *items) : items_(items) {} - virtual size_t getCount() const { return items_->size(); } - virtual void drawItem(int item, int x, int y, int w, int h, bool active) const; + StringVectorListAdapter(const std::vector *items) : items_(items) {} + virtual size_t getCount() const { return items_->size(); } + virtual void drawItem(int item, int x, int y, int w, int h, bool active) const; private: - const std::vector *items_; + const std::vector *items_; }; @@ -185,7 +185,7 @@ void UIReset(); // Returns 1 if clicked int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align); -int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images. +int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images. // Returns 1 if clicked, puts the value in *value (where it also gets the current state). int UICheckBox(int id, int x, int y, const char *text, int align, bool *value); @@ -205,17 +205,23 @@ void UISlideChoice(int id, int y, const SlideItem *items, int numItems, UISlideS class UIList { - public: - UIList(); - float scrollY; - float startDragY; - int dragFinger; - int selected; - // List view. - // return -1 = no selection - int Do(int id, int x, int y, int w, int h, UIListAdapter *adapter); - private: - DISALLOW_COPY_AND_ASSIGN(UIList); +public: + UIList(); + + bool scrolling; + int activePointer; + float scrollY; + float startDragY; + float movedDistanceY; + + int dragFinger; + int selected; + // List view. + // return -1 = no selection + int Do(int id, int x, int y, int w, int h, UIListAdapter *adapter); + +private: + DISALLOW_COPY_AND_ASSIGN(UIList); }; // Call at end of frame. diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index bb4b443507..953073f83e 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -10,13 +10,13 @@ TouchButton::TouchButton(const Atlas *atlas, int imageIndex, int overlayImageInd memset(pointerDown, 0, sizeof(pointerDown)); w_ = atlas_->images[imageIndex_].w; h_ = atlas_->images[imageIndex_].h; - rotationAngle_ = (float)rotationAngle * 3.1415927 / 180.0f; - isDown_ = false; + rotationAngle_ = (float)rotationAngle * 3.1415927 / 180.0f; + isDown_ = false; } void TouchButton::update(InputState &input_state) { - isDown_ = false; + isDown_ = false; for (int i = 0; i < MAX_POINTERS; i++) { if (input_state.pointer_down[i] && isInside(input_state.pointer_x[i], input_state.pointer_y[i])) isDown_ = true; @@ -31,12 +31,12 @@ void TouchButton::update(InputState &input_state) void TouchButton::draw(DrawBuffer &db) { - uint32_t color = 0xAAFFFFFF; - float scale = 1.0f; - if (isDown_) { - color = 0xFFFFFFFF; - scale = 2.0f; - } + uint32_t color = 0xAAFFFFFF; + float scale = 1.0f; + if (isDown_) { + color = 0xFFFFFFFF; + scale = 2.0f; + } db.DrawImageRotated(imageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color); if (overlayImageIndex_ != -1) db.DrawImageRotated(overlayImageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color); diff --git a/ui/virtual_input.h b/ui/virtual_input.h index 765bdccb55..ee336ab6b5 100644 --- a/ui/virtual_input.h +++ b/ui/virtual_input.h @@ -37,16 +37,16 @@ private: float w_; float h_; - bool isDown_; + bool isDown_; // TODO: simplify into flags. bool pointerDown[MAX_POINTERS]; }; -// Multi-touch enabled virtual joystick +// Multi-touch enabled virtual joystick // (any finger will work, simultaneously with other virtual button/stick actions). -class TouchStick +class TouchStick { public: TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick); From ae8688f2459ffbcfb6b018ac904024474e25d69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 29 Oct 2012 23:31:28 +0100 Subject: [PATCH 0117/1445] Bugfix in png_load.cpp --- image/png_load.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/image/png_load.cpp b/image/png_load.cpp index 67d6964c63..814db20dba 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -31,8 +31,8 @@ int pngLoad(const char *file, int *pwidth, // ... but 'n' will always be the number that it would have been if you said 0 // TODO: Get rid of this silly copy which is only to make the buffer free-able with free() - *image_data_ptr = (unsigned char *)malloc(x * y * n); - memcpy(*image_data_ptr, data, x * y * n); + *image_data_ptr = (unsigned char *)malloc(x * y * 4); + memcpy(*image_data_ptr, data, x * y * 4); stbi_image_free(data); return 1; } @@ -134,4 +134,4 @@ int pngLoad(const char *file, int *pwidth, return 1; } -#endif \ No newline at end of file +#endif From ea11d9d492f6c00890054ca7cf6272f9a86076ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 30 Oct 2012 00:03:07 +0100 Subject: [PATCH 0118/1445] curves --- math/CMakeLists.txt | 1 + math/curves.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++ math/curves.h | 22 +++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 math/curves.cpp create mode 100644 math/curves.h diff --git a/math/CMakeLists.txt b/math/CMakeLists.txt index 6bd2d91ab2..a204c3e6c2 100644 --- a/math/CMakeLists.txt +++ b/math/CMakeLists.txt @@ -3,6 +3,7 @@ set(SRCS lin/vec3.cpp lin/quat.cpp lin/aabb.cpp + curves.cpp ) set(SRCS ${SRCS}) diff --git a/math/curves.cpp b/math/curves.cpp new file mode 100644 index 0000000000..c86f87ae5d --- /dev/null +++ b/math/curves.cpp @@ -0,0 +1,57 @@ + +#include + +#include "math/math_util.h" +#include "curves.h" + +float linearInOut(int t, int fadeInLength, int solidLength, int fadeOutLength) { + if (t < 0) return 0; + if (t < fadeInLength) { + return (float)t / fadeInLength; + } + t -= fadeInLength; + if (t < solidLength) { + return 1.0f; + } + t -= solidLength; + if (t < fadeOutLength) { + return 1.0f - (float)t / fadeOutLength; + } + return 0.0f; +} + +float linearIn(int t, int fadeInLength) { + if (t < 0) return 0; + if (t < fadeInLength) { + return (float)t / fadeInLength; + } + return 1.0f; +} + +float linearOut(int t, int fadeOutLength) { + return 1.0f - linearIn(t, fadeOutLength); +} + +float ease(float val) { + return ((-cosf(val * PI)) + 1.0f) * 0.5; +} + +float sawtooth(int t, int period) { + return (t % period) * (1.0f / (period - 1)); +} + +float passWithPause(int t, int fadeInLength, int pauseLength, int fadeOutLength) +{ + if (t < fadeInLength) { + return -1.0f + (float)t / fadeInLength; + } + t -= fadeInLength; + if (t < pauseLength) { + return 0.0f; + } + t -= pauseLength; + if (t < fadeOutLength) { + return (float)t / fadeOutLength; + } + return 1.0f; +} diff --git a/math/curves.h b/math/curves.h new file mode 100644 index 0000000000..fb21d91fb5 --- /dev/null +++ b/math/curves.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +// Easy curve computation for fades etc. + + +// output range: [0.0, 1.0] +float linearInOut(int t, int fadeInLength, int solidLength, int fadeOutLength); +float linearIn(int t, int fadeInLength); +float linearOut(int t, int fadeInLength); + +// smooth operator [0, 1] -> [0, 1] +float ease(float val); + +// need a bouncy ease + +// waveforms [0, 1] +float sawtooth(int t, int period); + +// output range: -1.0 to 1.0 +float passWithPause(int t, int fadeInLength, int pauseLength, int fadeOutLength); From 8b5356b66c92782f2182baae1bcedfa88c8dc21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 30 Oct 2012 00:11:30 +0100 Subject: [PATCH 0119/1445] Alignment bugfix --- ui/ui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index aabebbab0a..73dac4eed1 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -103,7 +103,7 @@ int UIButton(int id, const LayoutManager &layout, float w, const char *text, int if (button_align & ALIGN_HCENTER) x -= w / 2; if (button_align & ALIGN_VCENTER) y -= h / 2; if (button_align & ALIGN_RIGHT) x -= w; - if (button_align & ALIGN_BOTTOMRIGHT) y -= h; + if (button_align & ALIGN_BOTTOM) y -= h; int txOffset = 0; From edb0e8e8b24f1f3ffa6a10848dc80619d3215135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 30 Oct 2012 13:07:55 +0100 Subject: [PATCH 0120/1445] Add basic inertial scrolling to list. Overscroll is a bit buggy. --- ui/ui.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++++++------- ui/ui.h | 15 +++++-- 2 files changed, 114 insertions(+), 19 deletions(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index 73dac4eed1..9ef9b74970 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "ui/ui.h" #include "gfx/texture_atlas.h" @@ -256,15 +257,62 @@ void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, boo UIList::UIList() : scrollY(0.0f), startDragY(0.0f), dragFinger(-1), selected(-1) { movedDistanceY = 0.0f; + scrolling = false; + inertiaY = 0.0f; +} +void UIList::pointerDown(int pointer, float x, float y) { + // printf("PointerDown %f %f\n", x, y); + + // Instantly halt if intertia-scrolling + scrolling = false; + inertiaY = 0.0f; + + startScrollY = scrollY; + startDragY = y; + movedDistanceY = 0.0f; +} + +const int holdFrames = 6; + +void UIList::pointerMove(int pointer, float x, float y) { + // printf("PointerMove %f %f\n", x, y); + + float deltaY = y - lastY; + movedDistanceY += fabsf(deltaY); + + if (inertiaY <= 0.0f && deltaY > 0.0f) { + inertiaY = -deltaY; + } else if (inertiaY >= 0.0f && deltaY < 0.0f) { + inertiaY = -deltaY; + } else { + inertiaY = 0.8 * inertiaY + 0.2 * -deltaY; + } + + if (movedDistanceY > 10 && !scrolling && uistate.mouseframesdown[0] > holdFrames) { + scrolling = true; + } + + if (scrolling) { + // Pointer is down so stick to it + scrollY = startScrollY - (y - startDragY); + } +} + +void UIList::pointerUp(int pointer, float x, float y, bool inside) { + // printf("PointerUp %f %f\n", x, y); } int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { - bool pointerDown = false; + int clicked = 0; + + // Pointer and focus handling // UIList only cares about the first pointer for simplicity. // Probably not much need to scroll one of these while dragging something // else. + + // TODO: Abstract this stuff out into EmulatePointerEvents for (int i = 0; i < 1; i++) { // Check for hover if (UIRegionHit(i, x, y, w, h, 0)) { @@ -272,40 +320,80 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) { // Mousedown uistate.activeitem[i] = id; + pointerDown(i, uistate.mousex[i], uistate.mousey[i]); + } + } + + if (uistate.activeitem[i] == id) { + // NOTE: won't work with multiple pointers + if (uistate.mousex[i] != lastX || uistate.mousey[i] != lastY) { + pointerMove(i, uistate.mousex[i], uistate.mousey[i]); } } // If button is hot and active, but mouse button is not // down, the user must have clicked a list item (unless after the last item). if (uistate.mousedown[i] == 0 && - uistate.hotitem[i] == id && uistate.activeitem[i] == id && selected != -1) { - clicked = 1; + if (uistate.hotitem[i] == id) { + clicked = 1; + } + pointerUp(i, uistate.mousex[i], uistate.mousey[i], uistate.hotitem[i] == id); } } - // render items int itemHeight = adapter->itemHeight(0); int numItems = adapter->getCount(); + + // Process inertia scrolling + bool canScroll = itemHeight * numItems > h; + if (canScroll) { + if (inertiaY > 20) inertiaY = 20; + if (inertiaY < -20) inertiaY = -20; + if (!uistate.mousedown[0]) { + scrollY += inertiaY; + } + inertiaY *= 0.9f; + float maxScrollY = numItems * itemHeight - h; + if (scrollY > maxScrollY) { + scrollY -= 0.3 * (scrollY - maxScrollY); + } else if (scrollY < 0.0f) { + scrollY += 0.3f * -scrollY; + } + lastX = uistate.mousex[0]; + lastY = uistate.mousey[0]; + uistate.lastwidget = id; + } else { + scrollY = 0.0f; + scrolling = false; + } + + // Drawing and item hittesting + + // render items for (int i = 0; i < numItems; i++) { int item_y = y + i * itemHeight - scrollY; - for (int k = 0; k < MAX_POINTERS; k++) { - if (uistate.mousedown[k] && - uistate.mouseframesdown[k] > 10 && - adapter->itemEnabled(i) && - item_y >= y - itemHeight && - item_y <= y + h && - UIRegionHit(k, x, item_y, w, itemHeight, 0)) { - printf("%i", item_y); - selected = i; + if (item_y >= y - itemHeight && item_y <= y + h) { + for (int k = 0; k < 1; k++) { // MAX_POINTERS if we add back multitouch + if (uistate.mousedown[k] && + uistate.mouseframesdown[k] >= holdFrames && + adapter->itemEnabled(i) && + !scrolling && + selected == -1 && + UIRegionHit(k, x, item_y, w, itemHeight, 0)) { + selected = i; + } else if (scrolling) { + selected = -1; + } } + adapter->drawItem(i, x, item_y, w, itemHeight, i == selected); } - adapter->drawItem(i, x, item_y, w, itemHeight, i == selected); } - uistate.lastwidget = id; + // Prevent scroll-clicks from registering + if (selected == -1) clicked = 0; // Otherwise, no clicky. return clicked; } diff --git a/ui/ui.h b/ui/ui.h index 35089b0ff4..362a5b5910 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -104,10 +104,6 @@ struct UIState { int kbdwidget; int lastwidget; - // Used by controls that need to keep track of the initial value for drags, for example. - // Should probably be indexed by finger - would be neat to be able to move two knobs at the same time. - float tempfloat; - int ui_tick; }; @@ -210,9 +206,14 @@ public: bool scrolling; int activePointer; + float startScrollY; float scrollY; + float lastX; + float lastY; float startDragY; float movedDistanceY; + float inertiaY; + float dY; int dragFinger; int selected; @@ -221,11 +222,17 @@ public: int Do(int id, int x, int y, int w, int h, UIListAdapter *adapter); private: + // TODO: Migrate to using these directly. + void pointerDown(int pointer, float x, float y); + void pointerUp(int pointer, float x, float y, bool inside); + void pointerMove(int pointer, float x, float y); + DISALLOW_COPY_AND_ASSIGN(UIList); }; // Call at end of frame. // Do this afterwards (or similar): + // ShaderManager::SetUIProgram(); // ui_draw2d.Flush(ShaderManager::Program()); // ui_draw2d_front.Flush(ShaderManager::Program()); From 5a5f599e1b08772968f66a7bca3df0703beffc40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 30 Oct 2012 13:20:55 +0100 Subject: [PATCH 0121/1445] Reindent (->tabs) --- audio/mixer.cpp | 270 ++++++++++++------------- audio/mixer.h | 6 +- audio/wav_read.cpp | 118 +++++------ audio/wav_read.h | 4 +- base/backtrace.cpp | 6 +- base/basictypes.h | 2 +- base/colorutil.cpp | 118 +++++------ base/colorutil.h | 4 +- base/error_context.cpp | 36 ++-- base/error_context.h | 10 +- base/fastlist.h | 50 ++--- base/linked_ptr.h | 72 +++---- base/scoped_ptr.h | 38 ++-- base/stringutil.cpp | 18 +- base/threadutil.h | 16 +- base/timeutil.cpp | 60 +++--- gfx/gl_debug_log.cpp | 70 +++---- gfx/gl_lost_manager.cpp | 53 +++-- gfx/texture.cpp | 394 ++++++++++++++++++------------------- gfx/texture.h | 40 ++-- gfx/texture_atlas.cpp | 4 +- gfx/texture_dx11.cpp | 302 ++++++++++++++-------------- gfx/texture_gen.cpp | 70 +++---- gfx_es2/fbo.cpp | 102 +++++----- gfx_es2/glsl_program.cpp | 332 +++++++++++++++---------------- gfx_es2/glsl_program.h | 50 ++--- gfx_es2/vertex_format.cpp | 104 +++++----- gfx_es2/vertex_format.h | 60 +++--- image/png_load.cpp | 181 +++++++++-------- image/zim_load.cpp | 216 ++++++++++---------- image/zim_load.h | 32 +-- image/zim_save.cpp | 388 ++++++++++++++++++------------------ input/gesture_detector.cpp | 76 +++---- input/gesture_detector.h | 18 +- input/input_state.h | 96 ++++----- json/json_writer.cpp | 108 +++++----- json/json_writer.h | 70 +++---- math/compression.h | 18 +- math/lin/aabb.h | 4 +- math/lin/matrix4x4.cpp | 370 +++++++++++++++++----------------- math/lin/matrix4x4.h | 238 +++++++++++----------- math/lin/plane.cpp | 8 +- math/lin/plane.h | 44 ++--- math/lin/quat.cpp | 176 ++++++++--------- math/lin/quat.h | 156 +++++++-------- math/lin/vec3.cpp | 28 +-- math/lin/vec3.h | 216 ++++++++++---------- math/math_util.cpp | 28 +-- math/math_util.h | 40 ++-- net/http_client.cpp | 150 +++++++------- net/http_client.h | 60 +++--- net/resolve.cpp | 40 ++-- 52 files changed, 2584 insertions(+), 2586 deletions(-) diff --git a/audio/mixer.cpp b/audio/mixer.cpp index cd6ba8270e..c918fcd30a 100644 --- a/audio/mixer.cpp +++ b/audio/mixer.cpp @@ -10,192 +10,192 @@ // * Vorbis streaming playback struct ChannelEffectState { - // Filter state + // Filter state }; enum CLIP_TYPE { - CT_PCM16, - CT_SYNTHFX, - CT_VORBIS, - // CT_PHOENIX? + CT_PCM16, + CT_SYNTHFX, + CT_VORBIS, + // CT_PHOENIX? }; struct Clip { - int type; + int type; - short *data; - int length; - int num_channels; // this is NOT stereo vs mono - int sample_rate; - int loop_start; - int loop_end; + short *data; + int length; + int num_channels; // this is NOT stereo vs mono + int sample_rate; + int loop_start; + int loop_end; }; // If current_clip == 0, the channel is free. enum ClipPlaybackState { - PB_STOPPED = 0, - PB_PLAYING = 1, + PB_STOPPED = 0, + PB_PLAYING = 1, }; struct Channel { - const Clip *current_clip; - // Playback state - ClipPlaybackState state; - int pos; - PlayParams params; - // Effect state - ChannelEffectState effect_state; + const Clip *current_clip; + // Playback state + ClipPlaybackState state; + int pos; + PlayParams params; + // Effect state + ChannelEffectState effect_state; }; struct Mixer { - Channel *channels; - int sample_rate; - int num_channels; - int num_fixed_channels; + Channel *channels; + int sample_rate; + int num_channels; + int num_fixed_channels; }; Mixer *mixer_create(int sample_rate, int channels, int fixed_channels) { - Mixer *mixer = new Mixer(); - memset(mixer, 0, sizeof(Mixer)); - mixer->channels = new Channel[channels]; - memset(mixer->channels, 0, sizeof(Channel) * channels); - mixer->sample_rate = sample_rate; - mixer->num_channels = channels; - mixer->num_fixed_channels = fixed_channels; - return mixer; + Mixer *mixer = new Mixer(); + memset(mixer, 0, sizeof(Mixer)); + mixer->channels = new Channel[channels]; + memset(mixer->channels, 0, sizeof(Channel) * channels); + mixer->sample_rate = sample_rate; + mixer->num_channels = channels; + mixer->num_fixed_channels = fixed_channels; + return mixer; } void mixer_destroy(Mixer *mixer) { - delete [] mixer->channels; - delete mixer; + delete [] mixer->channels; + delete mixer; } static int get_free_channel(Mixer *mixer) { - int chan_with_biggest_pos = -1; - int biggest_pos = -1; - for (int i = mixer->num_fixed_channels; i < mixer->num_channels; i++) { - Channel *chan = &mixer->channels[i]; - if (!chan->current_clip) { - return i; - } - if (chan->pos > biggest_pos) { - biggest_pos = chan->pos; - chan_with_biggest_pos = i; - } - } - return chan_with_biggest_pos; + int chan_with_biggest_pos = -1; + int biggest_pos = -1; + for (int i = mixer->num_fixed_channels; i < mixer->num_channels; i++) { + Channel *chan = &mixer->channels[i]; + if (!chan->current_clip) { + return i; + } + if (chan->pos > biggest_pos) { + biggest_pos = chan->pos; + chan_with_biggest_pos = i; + } + } + return chan_with_biggest_pos; } Clip *clip_load(const char *filename) { - short *data; - int num_samples; - int sample_rate, num_channels; + short *data; + int num_samples; + int sample_rate, num_channels; - if (!strcmp(filename + strlen(filename) - 4, ".ogg")) { - // Ogg file. For now, directly decompress, no streaming support. - uint8_t *filedata; - size_t size; - filedata = VFSReadFile(filename, &size); - num_samples = stb_vorbis_decode_memory(filedata, size, &num_channels, &data); - if (num_samples <= 0) - return NULL; - sample_rate = 44100; - ILOG("read ogg %s, length %i, rate %i", filename, num_samples, sample_rate); - } else { - // Wav file. Easy peasy. - data = wav_read(filename, &num_samples, &sample_rate, &num_channels); - if (!data) { - return NULL; - } - } + if (!strcmp(filename + strlen(filename) - 4, ".ogg")) { + // Ogg file. For now, directly decompress, no streaming support. + uint8_t *filedata; + size_t size; + filedata = VFSReadFile(filename, &size); + num_samples = stb_vorbis_decode_memory(filedata, size, &num_channels, &data); + if (num_samples <= 0) + return NULL; + sample_rate = 44100; + ILOG("read ogg %s, length %i, rate %i", filename, num_samples, sample_rate); + } else { + // Wav file. Easy peasy. + data = wav_read(filename, &num_samples, &sample_rate, &num_channels); + if (!data) { + return NULL; + } + } - Clip *clip = new Clip(); - clip->type = CT_PCM16; - clip->data = data; - clip->length = num_samples; - clip->num_channels = num_channels; - clip->sample_rate = sample_rate; - clip->loop_start = 0; - clip->loop_end = 0; - return clip; + Clip *clip = new Clip(); + clip->type = CT_PCM16; + clip->data = data; + clip->length = num_samples; + clip->num_channels = num_channels; + clip->sample_rate = sample_rate; + clip->loop_start = 0; + clip->loop_end = 0; + return clip; } void clip_destroy(Clip *clip) { - if (clip) { - free(clip->data); - delete clip; - } else { - ELOG("Can't destroy zero clip"); - } + if (clip) { + free(clip->data); + delete clip; + } else { + ELOG("Can't destroy zero clip"); + } } const short *clip_data(const Clip *clip) { - return clip->data; + return clip->data; } size_t clip_length(const Clip *clip) { - return clip->length; + return clip->length; } void clip_set_loop(Clip *clip, int start, int end) { - clip->loop_start = start; - clip->loop_end = end; + clip->loop_start = start; + clip->loop_end = end; } PlayParams *mixer_play_clip(Mixer *mixer, const Clip *clip, int channel) { - if (channel == -1) { - channel = get_free_channel(mixer); - } + if (channel == -1) { + channel = get_free_channel(mixer); + } - Channel *chan = &mixer->channels[channel]; - // Think about this order and make sure it's thread"safe" (not perfect but should not cause crashes). - chan->pos = 0; - chan->current_clip = clip; - chan->state = PB_PLAYING; - PlayParams *params = &chan->params; - params->volume = 128; - params->pan = 128; - return params; + Channel *chan = &mixer->channels[channel]; + // Think about this order and make sure it's thread"safe" (not perfect but should not cause crashes). + chan->pos = 0; + chan->current_clip = clip; + chan->state = PB_PLAYING; + PlayParams *params = &chan->params; + params->volume = 128; + params->pan = 128; + return params; } void mixer_mix(Mixer *mixer, short *buffer, int num_samples) { - // Clear the buffer. - memset(buffer, 0, num_samples * sizeof(short) * 2); - for (int i = 0; i < mixer->num_channels; i++) { - Channel *chan = &mixer->channels[i]; - if (chan->state == PB_PLAYING) { - const Clip *clip = chan->current_clip; - if (clip->type == CT_PCM16) { - // For now, only allow mono PCM - CHECK(clip->num_channels == 1); - if (true || chan->params.delta == 0) { - // Fast playback of non pitched clips - int cnt = num_samples; - if (clip->length - chan->pos < cnt) { - cnt = clip->length - chan->pos; - } - // TODO: Take pan into account. - int left_volume = chan->params.volume; - int right_volume = chan->params.volume; - // TODO: NEONize. Can also make special loops for left_volume == right_volume etc. - for (int s = 0; s < cnt; s++) { - int cdata = clip->data[chan->pos]; - buffer[s * 2 ] += cdata * left_volume >> 8; - buffer[s * 2 + 1] += cdata * right_volume >> 8; - chan->pos++; - } - if (chan->pos >= clip->length) { - chan->state = PB_STOPPED; - chan->current_clip = 0; - break; - } - } - } else if (clip->type == CT_VORBIS) { - // For music - } - } - } + // Clear the buffer. + memset(buffer, 0, num_samples * sizeof(short) * 2); + for (int i = 0; i < mixer->num_channels; i++) { + Channel *chan = &mixer->channels[i]; + if (chan->state == PB_PLAYING) { + const Clip *clip = chan->current_clip; + if (clip->type == CT_PCM16) { + // For now, only allow mono PCM + CHECK(clip->num_channels == 1); + if (true || chan->params.delta == 0) { + // Fast playback of non pitched clips + int cnt = num_samples; + if (clip->length - chan->pos < cnt) { + cnt = clip->length - chan->pos; + } + // TODO: Take pan into account. + int left_volume = chan->params.volume; + int right_volume = chan->params.volume; + // TODO: NEONize. Can also make special loops for left_volume == right_volume etc. + for (int s = 0; s < cnt; s++) { + int cdata = clip->data[chan->pos]; + buffer[s * 2 ] += cdata * left_volume >> 8; + buffer[s * 2 + 1] += cdata * right_volume >> 8; + chan->pos++; + } + if (chan->pos >= clip->length) { + chan->state = PB_STOPPED; + chan->current_clip = 0; + break; + } + } + } else if (clip->type == CT_VORBIS) { + // For music + } + } + } } diff --git a/audio/mixer.h b/audio/mixer.h index 99948f18af..69127df8a5 100644 --- a/audio/mixer.h +++ b/audio/mixer.h @@ -11,9 +11,9 @@ struct Channel; // This struct is public for easy manipulation of running channels. struct PlayParams { - uint8_t volume; // 0-255 - uint8_t pan; // 0-255, 127 is dead center. - int32_t delta; + uint8_t volume; // 0-255 + uint8_t pan; // 0-255, 127 is dead center. + int32_t delta; }; // Mixer diff --git a/audio/wav_read.cpp b/audio/wav_read.cpp index 437ced9208..8b2dbeb76c 100644 --- a/audio/wav_read.cpp +++ b/audio/wav_read.cpp @@ -4,67 +4,67 @@ #include "file/chunk_file.h" short *wav_read(const char *filename, - int *num_samples, int *sample_rate, - int *num_channels) + int *num_samples, int *sample_rate, + int *num_channels) { - ChunkFile cf(filename, true); - if (cf.failed()) { - WLOG("ERROR: Wave file %s could not be opened", filename); - return 0; - } + ChunkFile cf(filename, true); + if (cf.failed()) { + WLOG("ERROR: Wave file %s could not be opened", filename); + return 0; + } - short *data = 0; - int samplesPerSec, avgBytesPerSec,wBlockAlign,wBytesPerSample; - if (cf.descend('RIFF')) { - cf.readInt(); //get past 'WAVE' - if (cf.descend('fmt ')) { //enter the format chunk - int temp = cf.readInt(); - int format = temp & 0xFFFF; - if (format != 1) { - cf.ascend(); - cf.ascend(); - ELOG("Error - bad format"); - return NULL; - } - *num_channels = temp >> 16; - samplesPerSec = cf.readInt(); - avgBytesPerSec = cf.readInt(); + short *data = 0; + int samplesPerSec, avgBytesPerSec,wBlockAlign,wBytesPerSample; + if (cf.descend('RIFF')) { + cf.readInt(); //get past 'WAVE' + if (cf.descend('fmt ')) { //enter the format chunk + int temp = cf.readInt(); + int format = temp & 0xFFFF; + if (format != 1) { + cf.ascend(); + cf.ascend(); + ELOG("Error - bad format"); + return NULL; + } + *num_channels = temp >> 16; + samplesPerSec = cf.readInt(); + avgBytesPerSec = cf.readInt(); - temp = cf.readInt(); - wBlockAlign = temp & 0xFFFF; - wBytesPerSample = temp >> 16; - cf.ascend(); - // ILOG("got fmt data: %i", samplesPerSec); - } else { - ELOG("Error - no format chunk in wav"); - cf.ascend(); - return NULL; - } + temp = cf.readInt(); + wBlockAlign = temp & 0xFFFF; + wBytesPerSample = temp >> 16; + cf.ascend(); + // ILOG("got fmt data: %i", samplesPerSec); + } else { + ELOG("Error - no format chunk in wav"); + cf.ascend(); + return NULL; + } - if (cf.descend('data')) { //enter the data chunk - int numBytes = cf.getCurrentChunkSize(); - int numSamples = numBytes / wBlockAlign; - data = (short *)malloc(sizeof(short) * numSamples * *num_channels); - *num_samples = numSamples; - if (wBlockAlign == 2 && *num_channels == 1) { - cf.readData((uint8*)data,numBytes); - } else { - ELOG("Error - bad blockalign or channels"); - free(data); - return NULL; - } - cf.ascend(); - } else { - ELOG("Error - no data chunk in wav"); - cf.ascend(); - return NULL; - } - cf.ascend(); - } else { - ELOG("Could not descend into RIFF file"); - return NULL; - } - *sample_rate = samplesPerSec; - ILOG("read wav %s, length %i, rate %i", filename, *num_samples, *sample_rate); - return data; + if (cf.descend('data')) { //enter the data chunk + int numBytes = cf.getCurrentChunkSize(); + int numSamples = numBytes / wBlockAlign; + data = (short *)malloc(sizeof(short) * numSamples * *num_channels); + *num_samples = numSamples; + if (wBlockAlign == 2 && *num_channels == 1) { + cf.readData((uint8*)data,numBytes); + } else { + ELOG("Error - bad blockalign or channels"); + free(data); + return NULL; + } + cf.ascend(); + } else { + ELOG("Error - no data chunk in wav"); + cf.ascend(); + return NULL; + } + cf.ascend(); + } else { + ELOG("Could not descend into RIFF file"); + return NULL; + } + *sample_rate = samplesPerSec; + ILOG("read wav %s, length %i, rate %i", filename, *num_samples, *sample_rate); + return data; } diff --git a/audio/wav_read.h b/audio/wav_read.h index a3df5f616d..1929688cbd 100644 --- a/audio/wav_read.h +++ b/audio/wav_read.h @@ -2,6 +2,6 @@ // Allocates a buffer that should be freed using free(). short *wav_read(const char *filename, - int *num_samples, int *sample_rate, - int *num_channels); + int *num_samples, int *sample_rate, + int *num_channels); // TODO: Non-allocating version. diff --git a/base/backtrace.cpp b/base/backtrace.cpp index 422b1e17b8..1af17b4307 100644 --- a/base/backtrace.cpp +++ b/base/backtrace.cpp @@ -10,8 +10,8 @@ static void *backtrace_buffer[128]; void PrintBacktraceToStderr() { - int num_addrs = backtrace(backtrace_buffer, 128); - backtrace_symbols_fd(backtrace_buffer, num_addrs, STDERR_FILENO); + int num_addrs = backtrace(backtrace_buffer, 128); + backtrace_symbols_fd(backtrace_buffer, num_addrs, STDERR_FILENO); } -#endif \ No newline at end of file +#endif diff --git a/base/basictypes.h b/base/basictypes.h index 4f73add10f..fea1874486 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -11,7 +11,7 @@ #endif #define DISALLOW_COPY_AND_ASSIGN(t) \ - private: \ +private: \ t(const t &other); \ void operator =(const t &other); diff --git a/base/colorutil.cpp b/base/colorutil.cpp index a41f50c388..ff5bac7ece 100644 --- a/base/colorutil.cpp +++ b/base/colorutil.cpp @@ -1,45 +1,45 @@ #include "base/colorutil.h" uint32_t whiteAlpha(float alpha) { - if (alpha < 0.0f) alpha = 0.0f; - if (alpha > 1.0f) alpha = 1.0f; - uint32_t color = (int)(alpha*255) << 24; - color |= 0xFFFFFF; - return color; + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + uint32_t color = (int)(alpha*255) << 24; + color |= 0xFFFFFF; + return color; } uint32_t blackAlpha(float alpha) { - if (alpha < 0.0f) alpha = 0.0f; - if (alpha > 1.0f) alpha = 1.0f; - return (int)(alpha*255)<<24; + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + return (int)(alpha*255)<<24; } uint32_t colorAlpha(uint32_t color, float alpha) { - if (alpha < 0.0f) alpha = 0.0f; - if (alpha > 1.0f) alpha = 1.0f; - return ((int)(alpha*255)<<24) | (color & 0xFFFFFF); + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + return ((int)(alpha*255)<<24) | (color & 0xFFFFFF); } uint32_t rgba(float r, float g, float b, float alpha) { - uint32_t color = (int)(alpha*255)<<24; - color |= (int)(b*255)<<16; - color |= (int)(g*255)<<8; - color |= (int)(r*255); - return color; + uint32_t color = (int)(alpha*255)<<24; + color |= (int)(b*255)<<16; + color |= (int)(g*255)<<8; + color |= (int)(r*255); + return color; } uint32_t rgba_clamp(float r, float g, float b, float a) { - if (r > 1.0f) r = 1.0f; - if (g > 1.0f) g = 1.0f; - if (b > 1.0f) b = 1.0f; - if (a > 1.0f) a = 1.0f; + if (r > 1.0f) r = 1.0f; + if (g > 1.0f) g = 1.0f; + if (b > 1.0f) b = 1.0f; + if (a > 1.0f) a = 1.0f; - if (r < 0.0f) r = 0.0f; - if (g < 0.0f) g = 0.0f; - if (b < 0.0f) b = 0.0f; - if (a < 0.0f) a = 0.0f; + if (r < 0.0f) r = 0.0f; + if (g < 0.0f) g = 0.0f; + if (b < 0.0f) b = 0.0f; + if (a < 0.0f) a = 0.0f; - return rgba(r,g,b,a); + return rgba(r,g,b,a); } /* hsv2rgb.c @@ -53,40 +53,40 @@ uint32_t rgba_clamp(float r, float g, float b, float a) { * McGraw Hill 1985 */ uint32_t hsva(float H, float S, float V, float alpha) { - /* - * Purpose: - * Convert HSV values to RGB values - * All values are in the range [0.0 .. 1.0] - */ - float F, M, N, K; - int I; - if ( S == 0.0 ) { - // Achromatic case, set level of grey - return rgba(V, V, V, alpha); - } else { - /* - * Determine levels of primary colours. - */ - if (H >= 1.0) { - H = 0.0; - } else { - H = H * 6; - } - I = (int) H; /* should be in the range 0..5 */ - F = H - I; /* fractional part */ + /* + * Purpose: + * Convert HSV values to RGB values + * All values are in the range [0.0 .. 1.0] + */ + float F, M, N, K; + int I; + if ( S == 0.0 ) { + // Achromatic case, set level of grey + return rgba(V, V, V, alpha); + } else { + /* + * Determine levels of primary colours. + */ + if (H >= 1.0) { + H = 0.0; + } else { + H = H * 6; + } + I = (int) H; /* should be in the range 0..5 */ + F = H - I; /* fractional part */ - M = V * (1 - S); - N = V * (1 - S * F); - K = V * (1 - S * (1 - F)); + M = V * (1 - S); + N = V * (1 - S * F); + K = V * (1 - S * (1 - F)); - float r, g, b; - if (I == 0) { r = V; g = K; b = M; } - else if (I == 1) { r = N; g = V; b = M; } - else if (I == 2) { r = M; g = V; b = K; } - else if (I == 3) { r = M; g = N; b = V; } - else if (I == 4) { r = K; g = M; b = V; } - else if (I == 5) { r = V; g = M; b = N; } - else return 0; - return rgba(r, g, b, alpha); - } + float r, g, b; + if (I == 0) { r = V; g = K; b = M; } + else if (I == 1) { r = N; g = V; b = M; } + else if (I == 2) { r = M; g = V; b = K; } + else if (I == 3) { r = M; g = N; b = V; } + else if (I == 4) { r = K; g = M; b = V; } + else if (I == 5) { r = V; g = M; b = N; } + else return 0; + return rgba(r, g, b, alpha); + } } diff --git a/base/colorutil.h b/base/colorutil.h index 41f5a94ba7..0dad43baf4 100644 --- a/base/colorutil.h +++ b/base/colorutil.h @@ -1,10 +1,10 @@ #pragma once #include "base/basictypes.h" - + uint32_t whiteAlpha(float alpha); uint32_t blackAlpha(float alpha); uint32_t colorAlpha(uint32_t color, float alpha); uint32_t rgba(float r, float g, float b, float alpha); uint32_t rgba_clamp(float r, float g, float b, float alpha); -uint32_t hsva(float h, float s, float v, float alpha); \ No newline at end of file +uint32_t hsva(float h, float s, float v, float alpha); diff --git a/base/error_context.cpp b/base/error_context.cpp index 61afa713dd..b9337ee396 100644 --- a/base/error_context.cpp +++ b/base/error_context.cpp @@ -13,28 +13,28 @@ __THREAD std::vector *_error_context_name; __THREAD std::vector *_error_context_data; _ErrorContext::_ErrorContext(const char *name, const char *data) { - if (!_error_context_name) { - _error_context_name = new std::vector(); - _error_context_data = new std::vector(); - _error_context_name->reserve(16); - _error_context_data->reserve(16); - } - _error_context_name->push_back(name); - _error_context_data->push_back(data); + if (!_error_context_name) { + _error_context_name = new std::vector(); + _error_context_data = new std::vector(); + _error_context_name->reserve(16); + _error_context_data->reserve(16); + } + _error_context_name->push_back(name); + _error_context_data->push_back(data); } _ErrorContext::~_ErrorContext() { - _error_context_name->pop_back(); - _error_context_data->pop_back(); + _error_context_name->pop_back(); + _error_context_data->pop_back(); } void _ErrorContext::Log(const char *message) { - ILOG("EC: %s", message); - for (size_t i = 0; i < _error_context_name->size(); i++) { - if ((*_error_context_data)[i] != 0) { - ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]); - } else { - ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]); - } - } + ILOG("EC: %s", message); + for (size_t i = 0; i < _error_context_name->size(); i++) { + if ((*_error_context_data)[i] != 0) { + ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]); + } else { + ILOG("EC: %s: %s", (*_error_context_name)[i], (*_error_context_data)[i]); + } + } } diff --git a/base/error_context.h b/base/error_context.h index ef53e9b52d..d5cabffbe2 100644 --- a/base/error_context.h +++ b/base/error_context.h @@ -7,12 +7,12 @@ class _ErrorContext { public: - _ErrorContext(const char *name, const char *data = 0); - ~_ErrorContext(); + _ErrorContext(const char *name, const char *data = 0); + ~_ErrorContext(); - // Logs the current context stack. - static void Log(const char *message); + // Logs the current context stack. + static void Log(const char *message); }; #define ErrorContext(...) _ErrorContext __ec(__VA_ARGS__) -#define LogErrorContext(msg) _ErrorContext::Log(msg) \ No newline at end of file +#define LogErrorContext(msg) _ErrorContext::Log(msg) diff --git a/base/fastlist.h b/base/fastlist.h index 343f8c4afa..9a260b173a 100644 --- a/base/fastlist.h +++ b/base/fastlist.h @@ -7,33 +7,33 @@ // Order is not preserved when removing objects. template class InlineFastList { - public: - InlineFastList() : count_(0) {} - ~InlineFastList() {} +public: + InlineFastList() : count_(0) {} + ~InlineFastList() {} - T& operator [](int index) { return data_[index]; } - const T& operator [](int index) const { return data_[index]; } - int size() const { return count_; } - - void Add(T t) { - data_[count_++] = t; - } + T& operator [](int index) { return data_[index]; } + const T& operator [](int index) const { return data_[index]; } + int size() const { return count_; } - void RemoveAt(int index) { - data_[index] = data_[count_ - 1]; - count_--; - } + void Add(T t) { + data_[count_++] = t; + } - void Remove(T t) { // Requires operator== - for (int i = 0; i < count_; i++) { - if (data_[i] == t) { - RemoveAt(i); - return; - } - } - } + void RemoveAt(int index) { + data_[index] = data_[count_ - 1]; + count_--; + } - private: - T data_[max_size]; - int count_; + void Remove(T t) { // Requires operator== + for (int i = 0; i < count_; i++) { + if (data_[i] == t) { + RemoveAt(i); + return; + } + } + } + +private: + T data_[max_size]; + int count_; }; diff --git a/base/linked_ptr.h b/base/linked_ptr.h index df359d837c..7eec84eed6 100644 --- a/base/linked_ptr.h +++ b/base/linked_ptr.h @@ -14,47 +14,47 @@ template class linked_ptr { public: - explicit linked_ptr(X* p = 0) throw() : itsPtr(p) {itsPrev = itsNext = this;} - ~linked_ptr() {release();} - linked_ptr(const linked_ptr& r) throw() {acquire(r);} + explicit linked_ptr(X* p = 0) throw() : itsPtr(p) {itsPrev = itsNext = this;} + ~linked_ptr() {release();} + linked_ptr(const linked_ptr& r) throw() {acquire(r);} - linked_ptr& operator=(const linked_ptr& r) - { - if (this != &r) { - release(); - acquire(r); - } - return *this; - } + linked_ptr& operator=(const linked_ptr& r) + { + if (this != &r) { + release(); + acquire(r); + } + return *this; + } - X& operator*() const throw() {return *itsPtr;} - X* operator->() const throw() {return itsPtr;} - X* get() const throw() {return itsPtr;} - bool unique() const throw() {return itsPrev ? itsPrev==this : true;} + X& operator*() const throw() {return *itsPtr;} + X* operator->() const throw() {return itsPtr;} + X* get() const throw() {return itsPtr;} + bool unique() const throw() {return itsPrev ? itsPrev==this : true;} private: - X* itsPtr; - mutable const linked_ptr* itsPrev; - mutable const linked_ptr* itsNext; + X* itsPtr; + mutable const linked_ptr* itsPrev; + mutable const linked_ptr* itsNext; - void acquire(const linked_ptr& r) throw() - { // insert this to the list - itsPtr = r.itsPtr; - itsNext = r.itsNext; - itsNext->itsPrev = this; - itsPrev = &r; - r.itsNext = this; - } + void acquire(const linked_ptr& r) throw() + { // insert this to the list + itsPtr = r.itsPtr; + itsNext = r.itsNext; + itsNext->itsPrev = this; + itsPrev = &r; + r.itsNext = this; + } - void release() - { // erase this from the list, delete if unique - if (unique()) delete itsPtr; - else { - itsPrev->itsNext = itsNext; - itsNext->itsPrev = itsPrev; - itsPrev = itsNext = 0; - } - itsPtr = 0; - } + void release() + { // erase this from the list, delete if unique + if (unique()) delete itsPtr; + else { + itsPrev->itsNext = itsNext; + itsNext->itsPrev = itsPrev; + itsPrev = itsNext = 0; + } + itsPtr = 0; + } }; diff --git a/base/scoped_ptr.h b/base/scoped_ptr.h index 0dff0fd038..1a31890164 100644 --- a/base/scoped_ptr.h +++ b/base/scoped_ptr.h @@ -5,25 +5,25 @@ template class scoped_ptr { public: - scoped_ptr() : ptr_(0) {} - scoped_ptr(T *p) : ptr_(p) {} - ~scoped_ptr() { - delete ptr_; - } - void reset(T *p) { - delete ptr_; - ptr_ = p; - } - T *release() { - T *p = ptr_; - ptr_ = 0; - return p; - } - T *operator->() { return ptr_; } - const T *operator->() const { return ptr_; } + scoped_ptr() : ptr_(0) {} + scoped_ptr(T *p) : ptr_(p) {} + ~scoped_ptr() { + delete ptr_; + } + void reset(T *p) { + delete ptr_; + ptr_ = p; + } + T *release() { + T *p = ptr_; + ptr_ = 0; + return p; + } + T *operator->() { return ptr_; } + const T *operator->() const { return ptr_; } private: - scoped_ptr(const scoped_ptr &other); - void operator=(const scoped_ptr &other); - T *ptr_; + scoped_ptr(const scoped_ptr &other); + void operator=(const scoped_ptr &other); + T *ptr_; }; diff --git a/base/stringutil.cpp b/base/stringutil.cpp index 657f3000a5..b54b56e627 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -34,7 +34,7 @@ unsigned int parseHex(const char *_szValue) case 'e': Value += 14; break; case 'F': Value += 15; break; case 'f': Value += 15; break; - default: + default: Value = (Value >> 4); Count = Finish; } @@ -43,11 +43,11 @@ unsigned int parseHex(const char *_szValue) } void DataToHexString(const uint8 *data, size_t size, std::string *output) { - Buffer buffer; - for (size_t i = 0; i < size; i++) { - buffer.Printf("%02x ", data[i]); - if (i && !(i & 15)) - buffer.Printf("\n"); - } - buffer.TakeAll(output); -} \ No newline at end of file + Buffer buffer; + for (size_t i = 0; i < size; i++) { + buffer.Printf("%02x ", data[i]); + if (i && !(i & 15)) + buffer.Printf("\n"); + } + buffer.TakeAll(output); +} diff --git a/base/threadutil.h b/base/threadutil.h index fe8d9bac00..6b5d31990c 100644 --- a/base/threadutil.h +++ b/base/threadutil.h @@ -22,17 +22,17 @@ void setCurrentThreadName(const char *name); class thread { private: #ifdef _WIN32 - typedef HANDLE thread_; + typedef HANDLE thread_; #else - typedef pthread_t thread_; + typedef pthread_t thread_; #endif public: - //void run(std::function threadFunc) { - // func_ = - //} + //void run(std::function threadFunc) { + // func_ = + //} - void wait() { + void wait() { - } -};*/ \ No newline at end of file + } +};*/ diff --git a/base/timeutil.cpp b/base/timeutil.cpp index 36a29bea4d..3aa6670872 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -18,63 +18,63 @@ __int64 _frequency = 0; __int64 _starttime = 0; double real_time_now(){ - if (_frequency == 0) { - QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); - QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); - curtime=0; - } - __int64 time; - QueryPerformanceCounter((LARGE_INTEGER*)&time); - return ((double) (time - _starttime) / (double) _frequency); + if (_frequency == 0) { + QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); + QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); + curtime=0; + } + __int64 time; + QueryPerformanceCounter((LARGE_INTEGER*)&time); + return ((double) (time - _starttime) / (double) _frequency); } #else double real_time_now() { - static time_t start; - struct timeval tv; - gettimeofday(&tv, NULL); - if (start == 0) { - start = tv.tv_sec; - } - tv.tv_sec -= start; - return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; + static time_t start; + struct timeval tv; + gettimeofday(&tv, NULL); + if (start == 0) { + start = tv.tv_sec; + } + tv.tv_sec -= start; + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; } #endif void time_update() { - curtime = real_time_now(); - curtime_f = (float)curtime; + curtime = real_time_now(); + curtime_f = (float)curtime; - //printf("curtime: %f %f\n", curtime, curtime_f); - // also smooth time. - //curtime+=float((double) (time-_starttime) / (double) _frequency); - //curtime*=0.5f; - //curtime+=1.0f/60.0f; - //lastTime=curtime; - //curtime_f = (float)curtime; + //printf("curtime: %f %f\n", curtime, curtime_f); + // also smooth time. + //curtime+=float((double) (time-_starttime) / (double) _frequency); + //curtime*=0.5f; + //curtime+=1.0f/60.0f; + //lastTime=curtime; + //curtime_f = (float)curtime; } float time_now() { - return curtime_f; + return curtime_f; } double time_now_d() { - return curtime; + return curtime; } int time_now_ms() { - return int(curtime*1000.0); + return int(curtime*1000.0); } void sleep_ms(int ms) { #ifdef _WIN32 #ifndef METRO - Sleep(ms); + Sleep(ms); #endif #else - usleep(ms * 1000); + usleep(ms * 1000); #endif } diff --git a/gfx/gl_debug_log.cpp b/gfx/gl_debug_log.cpp index 39f2cacb58..9d5249ab74 100644 --- a/gfx/gl_debug_log.cpp +++ b/gfx/gl_debug_log.cpp @@ -14,43 +14,43 @@ typedef char GLchar; #include "base/logging.h" void glCheckzor(const char *file, int line) { - GLenum err = glGetError(); - if (err != GL_NO_ERROR) { - ELOG("GL error on line %i in %s: %i (%04x)", line, file, (int)err, (int)err); - } + GLenum err = glGetError(); + if (err != GL_NO_ERROR) { + ELOG("GL error on line %i in %s: %i (%04x)", line, file, (int)err, (int)err); + } } #ifndef ANDROID #if 0 void log_callback(GLenum source, GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - GLvoid* userParam) { - const char *src = "unknown"; - switch (source) { - case GL_DEBUG_SOURCE_API_GL_ARB: - src = "GL"; - break; - case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: - src = "GLSL"; - break; - case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: - src = "X"; - break; - default: - break; - } - switch (type) { - case GL_DEBUG_TYPE_ERROR_ARB: - case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: - ELOG("%s: %s", src, message); - break; - default: - ILOG("%s: %s", src, message); - break; - } + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + GLvoid* userParam) { + const char *src = "unknown"; + switch (source) { + case GL_DEBUG_SOURCE_API_GL_ARB: + src = "GL"; + break; + case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: + src = "GLSL"; + break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: + src = "X"; + break; + default: + break; + } + switch (type) { + case GL_DEBUG_TYPE_ERROR_ARB: + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: + ELOG("%s: %s", src, message); + break; + default: + ILOG("%s: %s", src, message); + break; + } } #endif #endif @@ -58,9 +58,9 @@ void log_callback(GLenum source, GLenum type, void gl_log_enable() { #ifndef ANDROID #if 0 - glEnable(DEBUG_OUTPUT_SYNCHRONOUS_ARB); // TODO: Look into disabling, for more perf - glDebugMessageCallback(&log_callback, 0); - glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); + glEnable(DEBUG_OUTPUT_SYNCHRONOUS_ARB); // TODO: Look into disabling, for more perf + glDebugMessageCallback(&log_callback, 0); + glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE); #endif #endif } diff --git a/gfx/gl_lost_manager.cpp b/gfx/gl_lost_manager.cpp index e366d4c8b2..99a9776db9 100644 --- a/gfx/gl_lost_manager.cpp +++ b/gfx/gl_lost_manager.cpp @@ -8,42 +8,41 @@ std::list *holders; GfxResourceHolder::~GfxResourceHolder() {} void register_gl_resource_holder(GfxResourceHolder *holder) { - if (holders) { - holders->push_back(holder); - } else { - WLOG("GL resource holder not initialized, cannot register resource"); - } + if (holders) { + holders->push_back(holder); + } else { + WLOG("GL resource holder not initialized, cannot register resource"); + } } void unregister_gl_resource_holder(GfxResourceHolder *holder) { - if (holders) { - holders->remove(holder); - } else { - WLOG("GL resource holder not initialized or already shutdown, cannot unregister resource"); - } + if (holders) { + holders->remove(holder); + } else { + WLOG("GL resource holder not initialized or already shutdown, cannot unregister resource"); + } } void gl_lost() { - if (!holders) { - WLOG("GL resource holder not initialized, cannot process lost request"); - return; - } - for (std::list::iterator iter = holders->begin(); - iter != holders->end(); ++iter) { - (*iter)->GLLost(); - } + if (!holders) { + WLOG("GL resource holder not initialized, cannot process lost request"); + return; + } + for (std::list::iterator iter = holders->begin(); iter != holders->end(); ++iter) { + (*iter)->GLLost(); + } } void gl_lost_manager_init() { - if (holders) { - FLOG("Double GL lost manager init"); - } - holders = new std::list(); + if (holders) { + FLOG("Double GL lost manager init"); + } + holders = new std::list(); } void gl_lost_manager_shutdown() { - if (!holders) { - FLOG("Lost manager already shutdown"); - } - delete holders; - holders = 0; + if (!holders) { + FLOG("Lost manager already shutdown"); + } + delete holders; + holders = 0; } diff --git a/gfx/texture.cpp b/gfx/texture.cpp index d0724e4f60..38f7016127 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -27,160 +27,160 @@ #include "gfx/gl_lost_manager.h" Texture::Texture() : id_(0) { - register_gl_resource_holder(this); + register_gl_resource_holder(this); } void Texture::Destroy() { - if (id_) { - glDeleteTextures(1, &id_); - id_ = 0; - } + if (id_) { + glDeleteTextures(1, &id_); + id_ = 0; + } } void Texture::GLLost() { - ILOG("Reloading lost texture %s", filename_.c_str()); - Load(filename_.c_str()); + ILOG("Reloading lost texture %s", filename_.c_str()); + Load(filename_.c_str()); } Texture::~Texture() { - unregister_gl_resource_holder(this); - Destroy(); + unregister_gl_resource_holder(this); + Destroy(); } static void SetTextureParameters(int zim_flags) { - GLenum wrap = GL_REPEAT; - if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); - GL_CHECK(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - GL_CHECK(); + GLenum wrap = GL_REPEAT; + if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); + GL_CHECK(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + GL_CHECK(); } bool Texture::Load(const char *filename) { - // hook for generated textures - if (!memcmp(filename, "gen:", 4)) { - // TODO - // return false; - int bpp, w, h; - bool clamp; - uint8_t *data = generateTexture(filename, bpp, w, h, clamp); - if (!data) - return false; - glGenTextures(1, &id_); - glBindTexture(GL_TEXTURE_2D, id_); - if (bpp == 1) { + // hook for generated textures + if (!memcmp(filename, "gen:", 4)) { + // TODO + // return false; + int bpp, w, h; + bool clamp; + uint8_t *data = generateTexture(filename, bpp, w, h, clamp); + if (!data) + return false; + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + if (bpp == 1) { #ifdef ANDROID - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); #else - glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); #endif - } else { - FLOG("unsupported"); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - delete [] data; - return true; - } + } else { + FLOG("unsupported"); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + delete [] data; + return true; + } - filename_ = filename; + filename_ = filename; - // Currently here are a bunch of project-specific workarounds. - // They shouldn't really hurt anything else very much though. + // Currently here are a bunch of project-specific workarounds. + // They shouldn't really hurt anything else very much though. - int len = strlen(filename); - char fn[256]; - strcpy(fn, filename); - bool zim = false; - if (!strcmp("dds", &filename[len-3])) { - strcpy(&fn[len-3], "zim"); - zim = true; - } - if (!strcmp("6TX", &filename[len-3]) || !strcmp("6tx", &filename[len-3])) { - ILOG("Detected 6TX %s", filename); - strcpy(&fn[len-3], "zim"); - zim = true; - } - for (int i = 0; i < (int)strlen(fn); i++) { - if (fn[i] == '\\') fn[i] = '/'; - } + int len = strlen(filename); + char fn[256]; + strcpy(fn, filename); + bool zim = false; + if (!strcmp("dds", &filename[len-3])) { + strcpy(&fn[len-3], "zim"); + zim = true; + } + if (!strcmp("6TX", &filename[len-3]) || !strcmp("6tx", &filename[len-3])) { + ILOG("Detected 6TX %s", filename); + strcpy(&fn[len-3], "zim"); + zim = true; + } + for (int i = 0; i < (int)strlen(fn); i++) { + if (fn[i] == '\\') fn[i] = '/'; + } - if (fn[0] == 'm') fn[0] = 'M'; - const char *name = fn; - if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); - len = strlen(name); + if (fn[0] == 'm') fn[0] = 'M'; + const char *name = fn; + if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); + len = strlen(name); #ifndef ANDROID - if (!strcmp("png", &name[len-3]) || - !strcmp("PNG", &name[len-3])) { - if (!LoadPNG(fn)) { - LoadXOR(); - return false; - } else { - return true; - } - } else + if (!strcmp("png", &name[len-3]) || + !strcmp("PNG", &name[len-3])) { + if (!LoadPNG(fn)) { + LoadXOR(); + return false; + } else { + return true; + } + } else #endif - if (!strcmp("zim", &name[len-3])) { - if (!LoadZIM(name)) { - LoadXOR(); - return false; - } else { - return true; - } - } - LoadXOR(); - return false; + if (!strcmp("zim", &name[len-3])) { + if (!LoadZIM(name)) { + LoadXOR(); + return false; + } else { + return true; + } + } + LoadXOR(); + return false; } #ifndef ANDROID bool Texture::LoadPNG(const char *filename) { - unsigned char *image_data; - if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { - return false; - } - GL_CHECK(); - glGenTextures(1, &id_); - glBindTexture(GL_TEXTURE_2D, id_); - SetTextureParameters(ZIM_GEN_MIPS); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image_data); - glGenerateMipmap(GL_TEXTURE_2D); - GL_CHECK(); - free(image_data); - return true; + unsigned char *image_data; + if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { + return false; + } + GL_CHECK(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(ZIM_GEN_MIPS); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image_data); + glGenerateMipmap(GL_TEXTURE_2D); + GL_CHECK(); + free(image_data); + return true; } #endif bool Texture::LoadXOR() { - width_ = height_ = 256; - unsigned char *buf = new unsigned char[width_*height_*4]; - for (int y = 0; y < 256; y++) { - for (int x = 0; x < 256; x++) { - buf[(y*width_ + x)*4 + 0] = x^y; - buf[(y*width_ + x)*4 + 1] = x^y; - buf[(y*width_ + x)*4 + 2] = x^y; - buf[(y*width_ + x)*4 + 3] = 0xFF; - } - } - GL_CHECK(); - glGenTextures(1, &id_); - glBindTexture(GL_TEXTURE_2D, id_); - SetTextureParameters(ZIM_GEN_MIPS); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, - GL_RGBA, GL_UNSIGNED_BYTE, buf); - glGenerateMipmap(GL_TEXTURE_2D); - GL_CHECK(); - delete [] buf; - return true; + width_ = height_ = 256; + unsigned char *buf = new unsigned char[width_*height_*4]; + for (int y = 0; y < 256; y++) { + for (int x = 0; x < 256; x++) { + buf[(y*width_ + x)*4 + 0] = x^y; + buf[(y*width_ + x)*4 + 1] = x^y; + buf[(y*width_ + x)*4 + 2] = x^y; + buf[(y*width_ + x)*4 + 3] = 0xFF; + } + } + GL_CHECK(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(ZIM_GEN_MIPS); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, + GL_RGBA, GL_UNSIGNED_BYTE, buf); + glGenerateMipmap(GL_TEXTURE_2D); + GL_CHECK(); + delete [] buf; + return true; } @@ -188,97 +188,97 @@ bool Texture::LoadXOR() { // Allocates using new[], doesn't free. uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { - uint8_t *rgba = new uint8_t[width * height * 4]; - memset(rgba, 0xFF, width * height * 4); - for (int y = 0; y < height; y += 4) { - for (int x = 0; x < width; x += 4) { - DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8, - rgba + (y * width + x) * 4, width, 255); - } - } - return rgba; + uint8_t *rgba = new uint8_t[width * height * 4]; + memset(rgba, 0xFF, width * height * 4); + for (int y = 0; y < height; y += 4) { + for (int x = 0; x < width; x += 4) { + DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8, + rgba + (y * width + x) * 4, width, 255); + } + } + return rgba; } #endif bool Texture::LoadZIM(const char *filename) { - uint8_t *image_data[ZIM_MAX_MIP_LEVELS]; - int width[ZIM_MAX_MIP_LEVELS]; - int height[ZIM_MAX_MIP_LEVELS]; + uint8_t *image_data[ZIM_MAX_MIP_LEVELS]; + int width[ZIM_MAX_MIP_LEVELS]; + int height[ZIM_MAX_MIP_LEVELS]; - int flags; - int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]); - if (!num_levels) - return false; - width_ = width[0]; - height_ = height[0]; - int data_type = GL_UNSIGNED_BYTE; - int colors = GL_RGBA; - int storage = GL_RGBA; - bool compressed = false; - switch (flags & ZIM_FORMAT_MASK) { - case ZIM_RGBA8888: - data_type = GL_UNSIGNED_BYTE; - break; - case ZIM_RGBA4444: - data_type = GL_UNSIGNED_SHORT_4_4_4_4; - break; - case ZIM_RGB565: - data_type = GL_UNSIGNED_SHORT_5_6_5; - colors = GL_RGB; - storage = GL_RGB; - break; - case ZIM_ETC1: - compressed = true; - break; - } + int flags; + int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]); + if (!num_levels) + return false; + width_ = width[0]; + height_ = height[0]; + int data_type = GL_UNSIGNED_BYTE; + int colors = GL_RGBA; + int storage = GL_RGBA; + bool compressed = false; + switch (flags & ZIM_FORMAT_MASK) { + case ZIM_RGBA8888: + data_type = GL_UNSIGNED_BYTE; + break; + case ZIM_RGBA4444: + data_type = GL_UNSIGNED_SHORT_4_4_4_4; + break; + case ZIM_RGB565: + data_type = GL_UNSIGNED_SHORT_5_6_5; + colors = GL_RGB; + storage = GL_RGB; + break; + case ZIM_ETC1: + compressed = true; + break; + } - GL_CHECK(); - glGenTextures(1, &id_); - glBindTexture(GL_TEXTURE_2D, id_); - SetTextureParameters(flags); + GL_CHECK(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(flags); - if (compressed) { - for (int l = 0; l < num_levels; l++) { - int data_w = width[l]; - int data_h = height[l]; - if (data_w < 4) data_w = 4; - if (data_h < 4) data_h = 4; + if (compressed) { + for (int l = 0; l < num_levels; l++) { + int data_w = width[l]; + int data_h = height[l]; + if (data_w < 4) data_w = 4; + if (data_h < 4) data_h = 4; #if defined(ANDROID) - int compressed_image_bytes = data_w * data_h / 2; - glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); - GL_CHECK(); + int compressed_image_bytes = data_w * data_h / 2; + glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); + GL_CHECK(); #else - image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h); - glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0, - GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]); + image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h); + glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0, + GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]); #endif - } - GL_CHECK(); + } + GL_CHECK(); #if !defined(ANDROID) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); #endif - } else { - for (int l = 0; l < num_levels; l++) { - glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0, - colors, data_type, image_data[l]); - } - if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) { - glGenerateMipmap(GL_TEXTURE_2D); - } - } - SetTextureParameters(flags); + } else { + for (int l = 0; l < num_levels; l++) { + glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0, + colors, data_type, image_data[l]); + } + if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) { + glGenerateMipmap(GL_TEXTURE_2D); + } + } + SetTextureParameters(flags); - GL_CHECK(); - // Only free the top level, since the allocation is used for all of them. - delete [] image_data[0]; - return true; + GL_CHECK(); + // Only free the top level, since the allocation is used for all of them. + delete [] image_data[0]; + return true; } void Texture::Bind(int stage) { - GL_CHECK(); - if (stage != -1) - glActiveTexture(GL_TEXTURE0 + stage); - glBindTexture(GL_TEXTURE_2D, id_); - GL_CHECK(); + GL_CHECK(); + if (stage != -1) + glActiveTexture(GL_TEXTURE0 + stage); + glBindTexture(GL_TEXTURE_2D, id_); + GL_CHECK(); } diff --git a/gfx/texture.h b/gfx/texture.h index dbb1e3d30e..3c3f953e21 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -10,38 +10,38 @@ class Texture : public GfxResourceHolder { public: - Texture(); - ~Texture(); + Texture(); + ~Texture(); - bool LoadZIM(const char *filename); + bool LoadZIM(const char *filename); #ifndef ANDROID - bool LoadPNG(const char *filename); + bool LoadPNG(const char *filename); #endif - bool LoadXOR(); // Loads a placeholder texture. + bool LoadXOR(); // Loads a placeholder texture. - // Deduces format from the filename. - // If loading fails, will load a 256x256 XOR texture. - // If filename begins with "gen:", will defer to texture_gen.cpp/h. - bool Load(const char *filename); + // Deduces format from the filename. + // If loading fails, will load a 256x256 XOR texture. + // If filename begins with "gen:", will defer to texture_gen.cpp/h. + bool Load(const char *filename); - void Bind(int stage = -1); + void Bind(int stage = -1); - void Destroy(); + void Destroy(); - unsigned int Handle() const { - return id_; - } + unsigned int Handle() const { + return id_; + } - virtual void GLLost(); - std::string filename() const { return filename_; } + virtual void GLLost(); + std::string filename() const { return filename_; } private: - std::string filename_; + std::string filename_; #ifdef METRO - ID3D11Texture2D *tex_; + ID3D11Texture2D *tex_; #endif - unsigned int id_; - int width_, height_; + unsigned int id_; + int width_, height_; }; #endif diff --git a/gfx/texture_atlas.cpp b/gfx/texture_atlas.cpp index 1a43f3bcc1..6a706600ae 100644 --- a/gfx/texture_atlas.cpp +++ b/gfx/texture_atlas.cpp @@ -7,7 +7,7 @@ const AtlasFont *Atlas::getFontByName(const char *name) const if (!strcmp(name, fonts[i]->name)) return fonts[i]; } - return 0; + return 0; } const AtlasImage *Atlas::getImageByName(const char *name) const @@ -16,5 +16,5 @@ const AtlasImage *Atlas::getImageByName(const char *name) const if (!strcmp(name, images[i].name)) return &images[i]; } - return 0; + return 0; } diff --git a/gfx/texture_dx11.cpp b/gfx/texture_dx11.cpp index 8dd0f6a9ce..7d72849ca6 100644 --- a/gfx/texture_dx11.cpp +++ b/gfx/texture_dx11.cpp @@ -23,7 +23,7 @@ #include "gfx/gl_lost_manager.h" Texture::Texture() : tex_(0) { - register_gl_resource_holder(this); + register_gl_resource_holder(this); @@ -37,29 +37,29 @@ void Texture::Destroy() { } void Texture::GLLost() { - ILOG("Reloading lost texture %s", filename_.c_str()); - Load(filename_.c_str()); + ILOG("Reloading lost texture %s", filename_.c_str()); + Load(filename_.c_str()); } Texture::~Texture() { - unregister_gl_resource_holder(this); - Destroy(); + unregister_gl_resource_holder(this); + Destroy(); } static void SetTextureParameters(int zim_flags) { /* - GLenum wrap = GL_REPEAT; - if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); - GL_CHECK(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - GL_CHECK();*/ + GLenum wrap = GL_REPEAT; + if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); + GL_CHECK(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + GL_CHECK();*/ } bool Texture::Load(const char *filename) { @@ -74,70 +74,70 @@ bool Texture::Load(const char *filename) { return true; } - filename_ = filename; - // Currently contains many Rollerball-specific workarounds. - // They shouldn't really hurt anything else very much though. - int len = strlen(filename); - char fn[256]; - strcpy(fn, filename); - bool zim = false; - if (!strcmp("dds", &filename[len-3])) { - strcpy(&fn[len-3], "zim"); - zim = true; - } - if (!strcmp("6TX", &filename[len-3]) || !strcmp("6tx", &filename[len-3])) { - ILOG("Detected 6TX %s", filename); - strcpy(&fn[len-3], "zim"); - zim = true; - } - for (int i = 0; i < (int)strlen(fn); i++) { - if (fn[i] == '\\') fn[i] = '/'; - } + filename_ = filename; + // Currently contains many Rollerball-specific workarounds. + // They shouldn't really hurt anything else very much though. + int len = strlen(filename); + char fn[256]; + strcpy(fn, filename); + bool zim = false; + if (!strcmp("dds", &filename[len-3])) { + strcpy(&fn[len-3], "zim"); + zim = true; + } + if (!strcmp("6TX", &filename[len-3]) || !strcmp("6tx", &filename[len-3])) { + ILOG("Detected 6TX %s", filename); + strcpy(&fn[len-3], "zim"); + zim = true; + } + for (int i = 0; i < (int)strlen(fn); i++) { + if (fn[i] == '\\') fn[i] = '/'; + } - if (fn[0] == 'm') fn[0] = 'M'; - const char *name = fn; - if (zim && 0 == memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); - len = strlen(name); - #ifndef ANDROID - if (!strcmp("png", &name[len-3]) || - !strcmp("PNG", &name[len-3])) { - if (!LoadPNG(fn)) { - LoadXOR(); - return false; - } else { - return true; - } - } else - #endif - if (!strcmp("zim", &name[len-3])) { - if (!LoadZIM(name)) { - LoadXOR(); - return false; - } else { - return true; - } - } - LoadXOR(); - return false; + if (fn[0] == 'm') fn[0] = 'M'; + const char *name = fn; + if (zim && 0 == memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); + len = strlen(name); + #ifndef ANDROID + if (!strcmp("png", &name[len-3]) || + !strcmp("PNG", &name[len-3])) { + if (!LoadPNG(fn)) { + LoadXOR(); + return false; + } else { + return true; + } + } else + #endif + if (!strcmp("zim", &name[len-3])) { + if (!LoadZIM(name)) { + LoadXOR(); + return false; + } else { + return true; + } + } + LoadXOR(); + return false; } #ifndef METRO #ifndef ANDROID bool Texture::LoadPNG(const char *filename) { - unsigned char *image_data; - if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { - return false; - } - GL_CHECK(); - glGenTextures(1, &id_); - glBindTexture(GL_TEXTURE_2D, id_); - SetTextureParameters(ZIM_GEN_MIPS); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image_data); - glGenerateMipmap(GL_TEXTURE_2D); - GL_CHECK(); - free(image_data); - return true; + unsigned char *image_data; + if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { + return false; + } + GL_CHECK(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(ZIM_GEN_MIPS); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image_data); + glGenerateMipmap(GL_TEXTURE_2D); + GL_CHECK(); + free(image_data); + return true; } #endif #endif @@ -153,7 +153,7 @@ bool Texture::LoadXOR() { buf[(y*width_ + x)*4 + 3] = 0xFF; } } - GL_CHECK(); + GL_CHECK(); ID3D11Device *ctx; D3D11_TEXTURE2D_DESC desc; desc.Width = width_; @@ -169,10 +169,10 @@ bool Texture::LoadXOR() { if (FAILED(ctx->CreateTexture2D(&desc, 0, &tex_))) { FLOG("Failed creating XOR texture"); } - SetTextureParameters(ZIM_GEN_MIPS); - GL_CHECK(); - delete [] buf; - return true; + SetTextureParameters(ZIM_GEN_MIPS); + GL_CHECK(); + delete [] buf; + return true; } @@ -180,97 +180,97 @@ bool Texture::LoadXOR() { // Allocates using new[], doesn't free. uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { - uint8_t *rgba = new uint8_t[width * height * 4]; - memset(rgba, 0xFF, width * height * 4); - for (int y = 0; y < height; y += 4) { - for (int x = 0; x < width; x += 4) { - DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8, - rgba + (y * width + x) * 4, width, 255); - } - } - return rgba; + uint8_t *rgba = new uint8_t[width * height * 4]; + memset(rgba, 0xFF, width * height * 4); + for (int y = 0; y < height; y += 4) { + for (int x = 0; x < width; x += 4) { + DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8, + rgba + (y * width + x) * 4, width, 255); + } + } + return rgba; } #endif bool Texture::LoadZIM(const char *filename) { - uint8_t *image_data[ZIM_MAX_MIP_LEVELS]; - int width[ZIM_MAX_MIP_LEVELS]; - int height[ZIM_MAX_MIP_LEVELS]; + uint8_t *image_data[ZIM_MAX_MIP_LEVELS]; + int width[ZIM_MAX_MIP_LEVELS]; + int height[ZIM_MAX_MIP_LEVELS]; - int flags; - int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]); - if (!num_levels) - return false; - width_ = width[0]; - height_ = height[0]; - int data_type = GL_UNSIGNED_BYTE; - int colors = GL_RGBA; - int storage = GL_RGBA; - bool compressed = false; - switch (flags & ZIM_FORMAT_MASK) { - case ZIM_RGBA8888: - data_type = GL_UNSIGNED_BYTE; - break; - case ZIM_RGBA4444: + int flags; + int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]); + if (!num_levels) + return false; + width_ = width[0]; + height_ = height[0]; + int data_type = GL_UNSIGNED_BYTE; + int colors = GL_RGBA; + int storage = GL_RGBA; + bool compressed = false; + switch (flags & ZIM_FORMAT_MASK) { + case ZIM_RGBA8888: + data_type = GL_UNSIGNED_BYTE; + break; + case ZIM_RGBA4444: data_type = DXGI_FORMAT_B4G4R4A4_UNORM; - break; - case ZIM_RGB565: + break; + case ZIM_RGB565: data_type = DXGI_FORMAT_B5G6R5_UNORM; - colors = GL_RGB; - storage = GL_RGB; - break; - case ZIM_ETC1: - compressed = true; - break; - } + colors = GL_RGB; + storage = GL_RGB; + break; + case ZIM_ETC1: + compressed = true; + break; + } - GL_CHECK(); - //glGenTextures(1, &id_); - //glBindTexture(GL_TEXTURE_2D, id_); - SetTextureParameters(flags); + GL_CHECK(); + //glGenTextures(1, &id_); + //glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(flags); - if (compressed) { - for (int l = 0; l < num_levels; l++) { - int data_w = width[l]; - int data_h = height[l]; - if (data_w < 4) data_w = 4; - if (data_h < 4) data_h = 4; + if (compressed) { + for (int l = 0; l < num_levels; l++) { + int data_w = width[l]; + int data_h = height[l]; + if (data_w < 4) data_w = 4; + if (data_h < 4) data_h = 4; #if defined(ANDROID) - int compressed_image_bytes = data_w * data_h / 2; - glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); - GL_CHECK(); + int compressed_image_bytes = data_w * data_h / 2; + glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); + GL_CHECK(); #else - //image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h); - //glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0, - // GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]); + //image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h); + //glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0, + // GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]); #endif - } - GL_CHECK(); + } + GL_CHECK(); #if !defined(ANDROID) - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); #endif - } else { - for (int l = 0; l < num_levels; l++) { - //glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0, - // colors, data_type, image_data[l]); - } - if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) { - //glGenerateMipmap(GL_TEXTURE_2D); - } - } - SetTextureParameters(flags); + } else { + for (int l = 0; l < num_levels; l++) { + //glTexImage2D(GL_TEXTURE_2D, l, storage, width[l], height[l], 0, + // colors, data_type, image_data[l]); + } + if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) { + //glGenerateMipmap(GL_TEXTURE_2D); + } + } + SetTextureParameters(flags); - GL_CHECK(); - // Only free the top level, since the allocation is used for all of them. - delete [] image_data[0]; - return true; + GL_CHECK(); + // Only free the top level, since the allocation is used for all of them. + delete [] image_data[0]; + return true; } void Texture::Bind(int stage) { - GL_CHECK(); + GL_CHECK(); //if (stage != -1) // glActiveTexture(GL_TEXTURE0 + stage); // glBindTexture(GL_TEXTURE_2D, id_); - GL_CHECK(); + GL_CHECK(); } diff --git a/gfx/texture_gen.cpp b/gfx/texture_gen.cpp index 8dac34c10e..6b6e76f6ed 100644 --- a/gfx/texture_gen.cpp +++ b/gfx/texture_gen.cpp @@ -12,41 +12,41 @@ uint8_t *generateTexture(const char *filename, int &bpp, int &w, int &h, bool &clamp) { - char name_and_params[256]; - // security check :) - if (strlen(filename) > 200) - return 0; - sscanf(filename, "gen:%i:%i:%s", &w, &h, name_and_params); + char name_and_params[256]; + // security check :) + if (strlen(filename) > 200) + return 0; + sscanf(filename, "gen:%i:%i:%s", &w, &h, name_and_params); - uint8_t *data; - if (!strcmp(name_and_params, "vignette")) { - bpp = 1; - data = new uint8_t[w*h]; - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; x++) { - float dx = (float)(x - w/2) / (w/2); - float dy = (float)(y - h/2) / (h/2); - float dist = sqrtf(dx * dx + dy * dy); - dist /= 1.414f; - float val = 1.0 - powf(dist, 1.4f); - data[y*w + x] = val * 255; - } - } - } else if (!strcmp(name_and_params, "circle")) { - bpp = 1; - // TODO - data = new uint8_t[w*h]; - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; x++) { - float dx = (float)(x - w/2) / (w/2); - float dy = (float)(y - h/2) / (h/2); - float dist = sqrtf(dx * dx + dy * dy); - dist /= 1.414f; - float val = 1.0 - powf(dist, 1.4f); - data[y*w + x] = val * 255; - } - } - } + uint8_t *data; + if (!strcmp(name_and_params, "vignette")) { + bpp = 1; + data = new uint8_t[w*h]; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; x++) { + float dx = (float)(x - w/2) / (w/2); + float dy = (float)(y - h/2) / (h/2); + float dist = sqrtf(dx * dx + dy * dy); + dist /= 1.414f; + float val = 1.0 - powf(dist, 1.4f); + data[y*w + x] = val * 255; + } + } + } else if (!strcmp(name_and_params, "circle")) { + bpp = 1; + // TODO + data = new uint8_t[w*h]; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; x++) { + float dx = (float)(x - w/2) / (w/2); + float dy = (float)(y - h/2) / (h/2); + float dist = sqrtf(dx * dx + dy * dy); + dist /= 1.414f; + float val = 1.0 - powf(dist, 1.4f); + data[y*w + x] = val * 255; + } + } + } - return data; + return data; } diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 6b1759e945..a64f56bb99 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -14,77 +14,77 @@ #include "gfx_es2/fbo.h" struct FBO { - GLuint handle; - GLuint color_texture; - GLuint z_stencil_buffer; + GLuint handle; + GLuint color_texture; + GLuint z_stencil_buffer; - int width; - int height; + int width; + int height; }; FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { - FBO *fbo = new FBO(); - fbo->width = width; - fbo->height = height; - glGenFramebuffers(1, &fbo->handle); - glGenTextures(1, &fbo->color_texture); - glGenRenderbuffers(1, &fbo->z_stencil_buffer); + FBO *fbo = new FBO(); + fbo->width = width; + fbo->height = height; + glGenFramebuffers(1, &fbo->handle); + glGenTextures(1, &fbo->color_texture); + glGenRenderbuffers(1, &fbo->z_stencil_buffer); - // Create the surfaces. - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + // Create the surfaces. + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); - // Bind it all together - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - switch(status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: - ILOG("Framebuffer verified complete."); - break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - ELOG("Framebuffer format not supported"); - break; - default: - FLOG("Other framebuffer error: %i", status); - break; - } - // Unbind state we don't need - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - return fbo; + // Bind it all together + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + switch(status) { + case GL_FRAMEBUFFER_COMPLETE_EXT: + ILOG("Framebuffer verified complete."); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + ELOG("Framebuffer format not supported"); + break; + default: + FLOG("Other framebuffer error: %i", status); + break; + } + // Unbind state we don't need + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + return fbo; } void fbo_unbind() { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } void fbo_bind_as_render_target(FBO *fbo) { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); } void fbo_bind_for_read(FBO *fbo) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); } void fbo_bind_color_as_texture(FBO *fbo, int color) { - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); } void fbo_destroy(FBO *fbo) { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &fbo->handle); - glDeleteTextures(1, &fbo->color_texture); - glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &fbo->handle); + glDeleteTextures(1, &fbo->color_texture); + glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); } diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index a830ecf624..f11f264171 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -24,189 +24,189 @@ typedef char GLchar; static std::set active_programs; bool CompileShader(const char *source, GLuint shader, const char *filename) { - glShaderSource(shader, 1, &source, NULL); - glCompileShader(shader); - GLint success; - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (!success) { + glShaderSource(shader, 1, &source, NULL); + glCompileShader(shader); + GLint success; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) { #define MAX_INFO_LOG_SIZE 2048 - GLchar infoLog[MAX_INFO_LOG_SIZE]; - GLsizei len; - glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog); - infoLog[len] = '\0'; - ELOG("Error in shader compilation of %s!\n", filename); - ELOG("Info log: %s\n", infoLog); - ELOG("Shader source:\n%s\n", (const char *)source); + GLchar infoLog[MAX_INFO_LOG_SIZE]; + GLsizei len; + glGetShaderInfoLog(shader, MAX_INFO_LOG_SIZE, &len, infoLog); + infoLog[len] = '\0'; + ELOG("Error in shader compilation of %s!\n", filename); + ELOG("Info log: %s\n", infoLog); + ELOG("Shader source:\n%s\n", (const char *)source); #ifdef ANDROID - exit(1); + exit(1); #endif - return false; - } - return true; + return false; + } + return true; } GLSLProgram *glsl_create(const char *vshader, const char *fshader) { - GLSLProgram *program = new GLSLProgram(); - program->program_ = 0; - program->vsh_ = 0; - program->fsh_ = 0; - program->vshader_source = 0; - program->fshader_source = 0; - strcpy(program->name, vshader + strlen(vshader) - 15); - strcpy(program->vshader_filename, vshader); - strcpy(program->fshader_filename, fshader); - if (glsl_recompile(program)) { - active_programs.insert(program); - } - else - { - FLOG("Failed building GLSL program: %s %s", vshader, fshader); - } - register_gl_resource_holder(program); - return program; + GLSLProgram *program = new GLSLProgram(); + program->program_ = 0; + program->vsh_ = 0; + program->fsh_ = 0; + program->vshader_source = 0; + program->fshader_source = 0; + strcpy(program->name, vshader + strlen(vshader) - 15); + strcpy(program->vshader_filename, vshader); + strcpy(program->fshader_filename, fshader); + if (glsl_recompile(program)) { + active_programs.insert(program); + } + else + { + FLOG("Failed building GLSL program: %s %s", vshader, fshader); + } + register_gl_resource_holder(program); + return program; } GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src) { - GLSLProgram *program = new GLSLProgram(); - program->program_ = 0; - program->vsh_ = 0; - program->fsh_ = 0; - program->vshader_source = vshader_src; - program->fshader_source = fshader_src; - strcpy(program->name, "[srcshader]"); - strcpy(program->vshader_filename, ""); - strcpy(program->fshader_filename, ""); - if (glsl_recompile(program)) { - active_programs.insert(program); - } - register_gl_resource_holder(program); - return program; + GLSLProgram *program = new GLSLProgram(); + program->program_ = 0; + program->vsh_ = 0; + program->fsh_ = 0; + program->vshader_source = vshader_src; + program->fshader_source = fshader_src; + strcpy(program->name, "[srcshader]"); + strcpy(program->vshader_filename, ""); + strcpy(program->fshader_filename, ""); + if (glsl_recompile(program)) { + active_programs.insert(program); + } + register_gl_resource_holder(program); + return program; } bool glsl_up_to_date(GLSLProgram *program) { - struct stat vs, fs; - stat(program->vshader_filename, &vs); - stat(program->fshader_filename, &fs); - if (vs.st_mtime != program->vshader_mtime || - fs.st_mtime != program->fshader_mtime) { - return false; - } else { - return true; - } + struct stat vs, fs; + stat(program->vshader_filename, &vs); + stat(program->fshader_filename, &fs); + if (vs.st_mtime != program->vshader_mtime || + fs.st_mtime != program->fshader_mtime) { + return false; + } else { + return true; + } } void glsl_refresh() { - ILOG("glsl_refresh()"); - for (std::set::const_iterator iter = active_programs.begin(); - iter != active_programs.end(); ++iter) { - if (!glsl_up_to_date(*iter)) { - glsl_recompile(*iter); - } - } + ILOG("glsl_refresh()"); + for (std::set::const_iterator iter = active_programs.begin(); + iter != active_programs.end(); ++iter) { + if (!glsl_up_to_date(*iter)) { + glsl_recompile(*iter); + } + } } bool glsl_recompile(GLSLProgram *program) { - struct stat vs, fs; - if (0 == stat(program->vshader_filename, &vs)) - program->vshader_mtime = vs.st_mtime; - else - program->vshader_mtime = 0; + struct stat vs, fs; + if (0 == stat(program->vshader_filename, &vs)) + program->vshader_mtime = vs.st_mtime; + else + program->vshader_mtime = 0; - if (0 == stat(program->fshader_filename, &fs)) - program->fshader_mtime = fs.st_mtime; - else - program->fshader_mtime = 0; - - char *vsh_src = 0, *fsh_src = 0; + if (0 == stat(program->fshader_filename, &fs)) + program->fshader_mtime = fs.st_mtime; + else + program->fshader_mtime = 0; + + char *vsh_src = 0, *fsh_src = 0; - if (!program->vshader_source) - { - size_t sz; - vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz); - if (!vsh_src) { - ELOG("File missing: %s", program->vshader_filename); - return false; - } - } - if (!program->fshader_source) - { - size_t sz; - fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz); - if (!fsh_src) { - ELOG("File missing: %s", program->fshader_filename); - delete [] vsh_src; - return false; - } - } + if (!program->vshader_source) + { + size_t sz; + vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz); + if (!vsh_src) { + ELOG("File missing: %s", program->vshader_filename); + return false; + } + } + if (!program->fshader_source) + { + size_t sz; + fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz); + if (!fsh_src) { + ELOG("File missing: %s", program->fshader_filename); + delete [] vsh_src; + return false; + } + } - GLuint vsh = glCreateShader(GL_VERTEX_SHADER); - const GLchar *vsh_str = program->vshader_source ? program->vshader_source : (const GLchar *)(vsh_src); - if (!CompileShader(vsh_str, vsh, program->vshader_filename)) { - return false; - } - delete [] vsh_src; + GLuint vsh = glCreateShader(GL_VERTEX_SHADER); + const GLchar *vsh_str = program->vshader_source ? program->vshader_source : (const GLchar *)(vsh_src); + if (!CompileShader(vsh_str, vsh, program->vshader_filename)) { + return false; + } + delete [] vsh_src; - const GLchar *fsh_str = program->fshader_source ? program->fshader_source : (const GLchar *)(fsh_src); - GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); - if (!CompileShader(fsh_str, fsh, program->fshader_filename)) { - glDeleteShader(vsh); - return false; - } - delete [] fsh_src; + const GLchar *fsh_str = program->fshader_source ? program->fshader_source : (const GLchar *)(fsh_src); + GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); + if (!CompileShader(fsh_str, fsh, program->fshader_filename)) { + glDeleteShader(vsh); + return false; + } + delete [] fsh_src; - GLuint prog = glCreateProgram(); - glAttachShader(prog, vsh); - glAttachShader(prog, fsh); + GLuint prog = glCreateProgram(); + glAttachShader(prog, vsh); + glAttachShader(prog, fsh); - glLinkProgram(prog); + glLinkProgram(prog); - GLint linkStatus; - glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint bufLength = 0; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength); - if (bufLength) { - char* buf = new char[bufLength]; - glGetProgramInfoLog(prog, bufLength, NULL, buf); - FLOG("Could not link program:\n %s", buf); - delete [] buf; // we're dead! - } else { - FLOG("Could not link program."); - } - glDeleteShader(vsh); - glDeleteShader(fsh); - return false; - } + GLint linkStatus; + glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) { + GLint bufLength = 0; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength); + if (bufLength) { + char* buf = new char[bufLength]; + glGetProgramInfoLog(prog, bufLength, NULL, buf); + FLOG("Could not link program:\n %s", buf); + delete [] buf; // we're dead! + } else { + FLOG("Could not link program."); + } + glDeleteShader(vsh); + glDeleteShader(fsh); + return false; + } - // Destroy the old program, if any. - if (program->program_) { - glDeleteProgram(program->program_); - } + // Destroy the old program, if any. + if (program->program_) { + glDeleteProgram(program->program_); + } - program->program_ = prog; - program->vsh_ = vsh; - program->fsh_ = vsh; + program->program_ = prog; + program->vsh_ = vsh; + program->fsh_ = vsh; - program->sampler0 = glGetUniformLocation(program->program_, "sampler0"); - program->sampler1 = glGetUniformLocation(program->program_, "sampler1"); + program->sampler0 = glGetUniformLocation(program->program_, "sampler0"); + program->sampler1 = glGetUniformLocation(program->program_, "sampler1"); - program->a_position = glGetAttribLocation(program->program_, "a_position"); - program->a_color = glGetAttribLocation(program->program_, "a_color"); - program->a_normal = glGetAttribLocation(program->program_, "a_normal"); - program->a_texcoord0 = glGetAttribLocation(program->program_, "a_texcoord0"); - program->a_texcoord1 = glGetAttribLocation(program->program_, "a_texcoord1"); + program->a_position = glGetAttribLocation(program->program_, "a_position"); + program->a_color = glGetAttribLocation(program->program_, "a_color"); + program->a_normal = glGetAttribLocation(program->program_, "a_normal"); + program->a_texcoord0 = glGetAttribLocation(program->program_, "a_texcoord0"); + program->a_texcoord1 = glGetAttribLocation(program->program_, "a_texcoord1"); - program->u_worldviewproj = glGetUniformLocation(program->program_, "u_worldviewproj"); - program->u_world = glGetUniformLocation(program->program_, "u_world"); - program->u_viewproj = glGetUniformLocation(program->program_, "u_viewproj"); - program->u_fog = glGetUniformLocation(program->program_, "u_fog"); - program->u_sundir = glGetUniformLocation(program->program_, "u_sundir"); - program->u_camerapos = glGetUniformLocation(program->program_, "u_camerapos"); + program->u_worldviewproj = glGetUniformLocation(program->program_, "u_worldviewproj"); + program->u_world = glGetUniformLocation(program->program_, "u_world"); + program->u_viewproj = glGetUniformLocation(program->program_, "u_viewproj"); + program->u_fog = glGetUniformLocation(program->program_, "u_fog"); + program->u_sundir = glGetUniformLocation(program->program_, "u_sundir"); + program->u_camerapos = glGetUniformLocation(program->program_, "u_camerapos"); - //ILOG("Shader compilation success: %s %s", - // program->vshader_filename, - // program->fshader_filename); - return true; + //ILOG("Shader compilation success: %s %s", + // program->vshader_filename, + // program->fshader_filename); + return true; } void GLSLProgram::GLLost() { @@ -220,35 +220,35 @@ void GLSLProgram::GLLost() { ILOG("Restoring GLSL program %s/%s", this->vshader_filename ? this->vshader_filename : "(mem)", this->fshader_filename ? this->fshader_filename : "(mem)"); - this->program_ = 0; - this->vsh_ = 0; - this->fsh_ = 0; - glsl_recompile(this); + this->program_ = 0; + this->vsh_ = 0; + this->fsh_ = 0; + glsl_recompile(this); // Note that uniforms are still lost, hopefully the client sets them every frame at a minimum... } int glsl_attrib_loc(const GLSLProgram *program, const char *name) { - return glGetAttribLocation(program->program_, name); + return glGetAttribLocation(program->program_, name); } int glsl_uniform_loc(const GLSLProgram *program, const char *name) { - return glGetUniformLocation(program->program_, name); + return glGetUniformLocation(program->program_, name); } void glsl_destroy(GLSLProgram *program) { - unregister_gl_resource_holder(program); - glDeleteShader(program->vsh_); - glDeleteShader(program->fsh_); - glDeleteProgram(program->program_); - active_programs.erase(program); - delete program; + unregister_gl_resource_holder(program); + glDeleteShader(program->vsh_); + glDeleteShader(program->fsh_); + glDeleteProgram(program->program_); + active_programs.erase(program); + delete program; } void glsl_bind(const GLSLProgram *program) { - glUseProgram(program->program_); + glUseProgram(program->program_); } void glsl_unbind() { - glUseProgram(0); + glUseProgram(0); } diff --git a/gfx_es2/glsl_program.h b/gfx_es2/glsl_program.h index 5ebbd03dac..c5acbfff7f 100644 --- a/gfx_es2/glsl_program.h +++ b/gfx_es2/glsl_program.h @@ -25,36 +25,36 @@ // A just-constructed object is valid but cannot be used as a shader program, meaning that // yes, you can declare these as globals if you like. struct GLSLProgram : public GfxResourceHolder { - char name[16]; - char vshader_filename[256]; - char fshader_filename[256]; - const char *vshader_source; - const char *fshader_source; - time_t vshader_mtime; - time_t fshader_mtime; + char name[16]; + char vshader_filename[256]; + char fshader_filename[256]; + const char *vshader_source; + const char *fshader_source; + time_t vshader_mtime; + time_t fshader_mtime; - // Locations to some common uniforms. Hardcoded for speed. - GLint sampler0; - GLint sampler1; - GLint u_worldviewproj; - GLint u_world; - GLint u_viewproj; - GLint u_fog; // rgb = color, a = density + // Locations to some common uniforms. Hardcoded for speed. + GLint sampler0; + GLint sampler1; + GLint u_worldviewproj; + GLint u_world; + GLint u_viewproj; + GLint u_fog; // rgb = color, a = density GLint u_sundir; GLint u_camerapos; - GLint a_position; - GLint a_color; - GLint a_normal; - GLint a_texcoord0; - GLint a_texcoord1; + GLint a_position; + GLint a_color; + GLint a_normal; + GLint a_texcoord0; + GLint a_texcoord1; - // Private to the implementation, do not touch - GLuint vsh_; - GLuint fsh_; - GLuint program_; + // Private to the implementation, do not touch + GLuint vsh_; + GLuint fsh_; + GLuint program_; - void GLLost(); + void GLLost(); }; @@ -81,4 +81,4 @@ void glsl_refresh(); // Use glUseProgramObjectARB(NULL); to unset. -#endif // _RENDER_UTIL +#endif // _RENDER_UTIL diff --git a/gfx_es2/vertex_format.cpp b/gfx_es2/vertex_format.cpp index 2823901c12..c713ae2006 100644 --- a/gfx_es2/vertex_format.cpp +++ b/gfx_es2/vertex_format.cpp @@ -3,69 +3,69 @@ #include "gfx_es2/vertex_format.h" static const GLuint formatLookup[16] = { - GL_FLOAT, - 0, //GL_HALF_FLOAT_EXT, - GL_UNSIGNED_SHORT, - GL_UNSIGNED_BYTE, - 0, //GL_UNSIGNED_INT_10_10_10_2, - 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + GL_FLOAT, + 0, //GL_HALF_FLOAT_EXT, + GL_UNSIGNED_SHORT, + GL_UNSIGNED_BYTE, + 0, //GL_UNSIGNED_INT_10_10_10_2, + 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; void SetVertexFormat(const GLSLProgram *program, uint32_t vertexFormat) { - // First special case our favorites - if (vertexFormat == (POS_FLOAT | NRM_FLOAT | UV0_FLOAT)) { - const int vertexSize = 3*4 + 3*4 + 2*4; - glUniform1i(program->sampler0, 0); - glEnableVertexAttribArray(program->a_position); - glEnableVertexAttribArray(program->a_normal); - glEnableVertexAttribArray(program->a_texcoord0); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0); - glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12); - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); - return; - } + // First special case our favorites + if (vertexFormat == (POS_FLOAT | NRM_FLOAT | UV0_FLOAT)) { + const int vertexSize = 3*4 + 3*4 + 2*4; + glUniform1i(program->sampler0, 0); + glEnableVertexAttribArray(program->a_position); + glEnableVertexAttribArray(program->a_normal); + glEnableVertexAttribArray(program->a_texcoord0); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0); + glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12); + glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); + return; + } - // Then have generic code here. + // Then have generic code here. - int vertexSize = 0; + int vertexSize = 0; - FLOG("TODO: Write generic code."); + FLOG("TODO: Write generic code."); - if (vertexFormat & UV0_MASK) { - glUniform1i(program->sampler0, 0); - } + if (vertexFormat & UV0_MASK) { + glUniform1i(program->sampler0, 0); + } - glEnableVertexAttribArray(program->a_position); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0); - if (vertexFormat & NRM_MASK) { - glEnableVertexAttribArray(program->a_normal); - glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12); - } - if (vertexFormat & UV0_MASK) { - glEnableVertexAttribArray(program->a_texcoord0); - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); - } - if (vertexFormat & UV1_MASK) { - glEnableVertexAttribArray(program->a_texcoord1); - glVertexAttribPointer(program->a_texcoord1, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); - } - if (vertexFormat & RGBA_MASK) { - glEnableVertexAttribArray(program->a_color); - glVertexAttribPointer(program->a_color, 4, GL_FLOAT, GL_FALSE, vertexSize, (void *)28); - } + glEnableVertexAttribArray(program->a_position); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)0); + if (vertexFormat & NRM_MASK) { + glEnableVertexAttribArray(program->a_normal); + glVertexAttribPointer(program->a_normal, 3, GL_FLOAT, GL_FALSE, vertexSize, (void *)12); + } + if (vertexFormat & UV0_MASK) { + glEnableVertexAttribArray(program->a_texcoord0); + glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); + } + if (vertexFormat & UV1_MASK) { + glEnableVertexAttribArray(program->a_texcoord1); + glVertexAttribPointer(program->a_texcoord1, 2, GL_FLOAT, GL_FALSE, vertexSize, (void *)24); + } + if (vertexFormat & RGBA_MASK) { + glEnableVertexAttribArray(program->a_color); + glVertexAttribPointer(program->a_color, 4, GL_FLOAT, GL_FALSE, vertexSize, (void *)28); + } } // TODO: Save state so that we can get rid of this. void UnsetVertexFormat(const GLSLProgram *program, uint32 vertexFormat) { - glDisableVertexAttribArray(program->a_position); - if (vertexFormat & NRM_MASK) - glDisableVertexAttribArray(program->a_normal); - if (vertexFormat & UV0_MASK) - glDisableVertexAttribArray(program->a_texcoord0); - if (vertexFormat & UV1_MASK) - glDisableVertexAttribArray(program->a_texcoord1); - if (vertexFormat & RGBA_MASK) - glDisableVertexAttribArray(program->a_color); + glDisableVertexAttribArray(program->a_position); + if (vertexFormat & NRM_MASK) + glDisableVertexAttribArray(program->a_normal); + if (vertexFormat & UV0_MASK) + glDisableVertexAttribArray(program->a_texcoord0); + if (vertexFormat & UV1_MASK) + glDisableVertexAttribArray(program->a_texcoord1); + if (vertexFormat & RGBA_MASK) + glDisableVertexAttribArray(program->a_color); } diff --git a/gfx_es2/vertex_format.h b/gfx_es2/vertex_format.h index 8a0b0aed11..edaac48145 100644 --- a/gfx_es2/vertex_format.h +++ b/gfx_es2/vertex_format.h @@ -6,42 +6,42 @@ // Vertex format flags enum VtxFmt { - POS_FLOAT = 1, - POS_FLOAT16 = 2, - POS_UINT16 = 3, - POS_UINT8 = 4, - POS_101010 = 5, + POS_FLOAT = 1, + POS_FLOAT16 = 2, + POS_UINT16 = 3, + POS_UINT8 = 4, + POS_101010 = 5, - NRM_FLOAT = 1 << 4, - NRM_FLOAT16 = 2 << 4, - NRM_SINT16 = 3 << 4, - NRM_UINT8 = 4 << 4, - NRM_101010 = 5 << 4, + NRM_FLOAT = 1 << 4, + NRM_FLOAT16 = 2 << 4, + NRM_SINT16 = 3 << 4, + NRM_UINT8 = 4 << 4, + NRM_101010 = 5 << 4, - TANGENT_FLOAT = 1 << 8, - //.... + TANGENT_FLOAT = 1 << 8, + //.... - UV0_NONE = 1 << 12, - UV0_FLOAT = 1 << 12, - // .... - UV1_NONE = 1 << 16, - UV1_FLOAT = 1 << 16, + UV0_NONE = 1 << 12, + UV0_FLOAT = 1 << 12, + // .... + UV1_NONE = 1 << 16, + UV1_FLOAT = 1 << 16, - RGBA_NONE = 0 << 20, - RGBA_FLOAT = 1 << 20, - RGBA_FLOAT16 = 2 << 20, - RGBA_UINT16 = 3 << 20, - RGBA_UINT8 = 4 << 20, - RGBA_101010 = 5 << 20, + RGBA_NONE = 0 << 20, + RGBA_FLOAT = 1 << 20, + RGBA_FLOAT16 = 2 << 20, + RGBA_UINT16 = 3 << 20, + RGBA_UINT8 = 4 << 20, + RGBA_101010 = 5 << 20, - POS_MASK = 0x0000000F, - NRM_MASK = 0x000000F0, - TANGENT_MASK = 0x00000F00, - UV0_MASK = 0x0000F000, - UV1_MASK = 0x000F0000, - RGBA_MASK = 0x00F00000, + POS_MASK = 0x0000000F, + NRM_MASK = 0x000000F0, + TANGENT_MASK = 0x00000F00, + UV0_MASK = 0x0000F000, + UV1_MASK = 0x000F0000, + RGBA_MASK = 0x00F00000, - // Can add more here, such as a generic AUX or something. Don't know what to use it for though. Hardness for cloth sim? + // Can add more here, such as a generic AUX or something. Don't know what to use it for though. Hardness for cloth sim? }; struct GLSLProgram; diff --git a/image/png_load.cpp b/image/png_load.cpp index 814db20dba..803b2e9a0c 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -10,22 +10,21 @@ // *image_data_ptr should be deleted with free() // return value of 1 == success. -int pngLoad(const char *file, int *pwidth, - int *pheight, unsigned char **image_data_ptr, - bool flip) { - if (flip) +int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, + bool flip) { + if (flip) { ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); } - + int x,y,n; - unsigned char *data = stbi_load(file, &x, &y, &n, 4); // 4 = force RGBA + unsigned char *data = stbi_load(file, &x, &y, &n, 4); // 4 = force RGBA if (!data) return 0; - + *pwidth = x; *pheight = y; - // ... process data if not NULL ... + // ... process data if not NULL ... // ... x = width, y = height, n = # 8-bit components per pixel ... // ... replace '0' with '1'..'4' to force that many components per pixel // ... but 'n' will always be the number that it would have been if you said 0 @@ -47,91 +46,91 @@ int pngLoad(const char *file, int *pwidth, // *image_data_ptr should be deleted with free() // return value of 1 == success. int pngLoad(const char *file, int *pwidth, - int *pheight, unsigned char **image_data_ptr, - bool flip) { - FILE *infile = fopen(file, "rb"); - if (!infile) { - printf("No such file: %s\n", file); - return 0; - } - /* Check for the 8-byte signature */ - char sig[8]; /* PNG signature array */ - int len = fread(sig, 1, 8, infile); - if (len != 8 || !png_check_sig((unsigned char *) sig, 8)) { - fclose(infile); - return 0; - } - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) { - fclose(infile); - return 4; /* out of memory */ - } - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); - fclose(infile); - return 4; /* out of memory */ - } - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(infile); - return 0; - } + int *pheight, unsigned char **image_data_ptr, + bool flip) { + FILE *infile = fopen(file, "rb"); + if (!infile) { + printf("No such file: %s\n", file); + return 0; + } + /* Check for the 8-byte signature */ + char sig[8]; /* PNG signature array */ + int len = fread(sig, 1, 8, infile); + if (len != 8 || !png_check_sig((unsigned char *) sig, 8)) { + fclose(infile); + return 0; + } + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fclose(infile); + return 4; /* out of memory */ + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + fclose(infile); + return 4; /* out of memory */ + } + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(infile); + return 0; + } - png_init_io(png_ptr, infile); - png_set_sig_bytes(png_ptr, 8); // we already checked the sig bytes - png_read_info(png_ptr, info_ptr); - int bit_depth=0; - int color_type=0; - png_uint_32 width=0, height=0; - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); - *pwidth = (int)width; - *pheight = (int)height; - // Set up some transforms. Always load RGBA. - if (color_type & PNG_COLOR_MASK_ALPHA) { - // png_set_strip_alpha(png_ptr); - } - if (bit_depth > 8) { - png_set_strip_16(png_ptr); - } - if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - png_set_gray_to_rgb(png_ptr); - } - if (color_type == PNG_COLOR_TYPE_PALETTE) { - png_set_palette_to_rgb(png_ptr); - } - if (color_type == PNG_COLOR_TYPE_RGB) { - png_set_filler(png_ptr, 255, PNG_FILLER_AFTER); - } + png_init_io(png_ptr, infile); + png_set_sig_bytes(png_ptr, 8); // we already checked the sig bytes + png_read_info(png_ptr, info_ptr); + int bit_depth=0; + int color_type=0; + png_uint_32 width=0, height=0; + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + *pwidth = (int)width; + *pheight = (int)height; + // Set up some transforms. Always load RGBA. + if (color_type & PNG_COLOR_MASK_ALPHA) { + // png_set_strip_alpha(png_ptr); + } + if (bit_depth > 8) { + png_set_strip_16(png_ptr); + } + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + } + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + } + if (color_type == PNG_COLOR_TYPE_RGB) { + png_set_filler(png_ptr, 255, PNG_FILLER_AFTER); + } - // Update the png info struct. - png_read_update_info(png_ptr, info_ptr); - unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr); - unsigned char *image_data = NULL; /* raw png image data */ - if ((image_data = (unsigned char *) malloc(rowbytes * height))==NULL) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return 4; - } - png_bytepp row_pointers = NULL; - if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - free(image_data); - image_data = NULL; - return 4; - } - if (flip) { - for (unsigned long i = 0; i < height; ++i) - row_pointers[height - 1 - i] = (png_byte *)(image_data + i*rowbytes); - } else { - for (unsigned long i = 0; i < height; ++i) - row_pointers[i] = (png_byte *)(image_data + i*rowbytes); - } - png_read_image(png_ptr, row_pointers); - free(row_pointers); - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(infile); - *image_data_ptr = image_data; - return 1; + // Update the png info struct. + png_read_update_info(png_ptr, info_ptr); + unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr); + unsigned char *image_data = NULL; /* raw png image data */ + if ((image_data = (unsigned char *) malloc(rowbytes * height))==NULL) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return 4; + } + png_bytepp row_pointers = NULL; + if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + free(image_data); + image_data = NULL; + return 4; + } + if (flip) { + for (unsigned long i = 0; i < height; ++i) + row_pointers[height - 1 - i] = (png_byte *)(image_data + i*rowbytes); + } else { + for (unsigned long i = 0; i < height; ++i) + row_pointers[i] = (png_byte *)(image_data + i*rowbytes); + } + png_read_image(png_ptr, row_pointers); + free(row_pointers); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(infile); + *image_data_ptr = image_data; + return 1; } #endif diff --git a/image/zim_load.cpp b/image/zim_load.cpp index 23b2693cd3..6980e7b8bd 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -8,132 +8,132 @@ #include "file/vfs.h" int ezuncompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) { - z_stream stream; - stream.next_in = (Bytef*)pSrc; - stream.avail_in = (uInt)nSrcLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != (uLong)nSrcLen) return Z_BUF_ERROR; + z_stream stream; + stream.next_in = (Bytef*)pSrc; + stream.avail_in = (uInt)nSrcLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != (uLong)nSrcLen) return Z_BUF_ERROR; - uInt destlen = (uInt)*pnDestLen; - if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; + uInt destlen = (uInt)*pnDestLen; + if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; - int err = inflateInit(&stream); - if (err != Z_OK) return err; + int err = inflateInit(&stream); + if (err != Z_OK) return err; - int nExtraChunks = 0; - do { - stream.next_out = pDest; - stream.avail_out = destlen; - err = inflate(&stream, Z_FINISH); - if (err == Z_STREAM_END ) - break; - if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) - err = Z_DATA_ERROR; - if (err != Z_BUF_ERROR) { - inflateEnd(&stream); - return err; - } - nExtraChunks += 1; - } while (stream.avail_out == 0); + int nExtraChunks = 0; + do { + stream.next_out = pDest; + stream.avail_out = destlen; + err = inflate(&stream, Z_FINISH); + if (err == Z_STREAM_END ) + break; + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + err = Z_DATA_ERROR; + if (err != Z_BUF_ERROR) { + inflateEnd(&stream); + return err; + } + nExtraChunks += 1; + } while (stream.avail_out == 0); - *pnDestLen = stream.total_out; + *pnDestLen = stream.total_out; - err = inflateEnd(&stream); - if (err != Z_OK) return err; + err = inflateEnd(&stream); + if (err != Z_OK) return err; - return nExtraChunks ? Z_BUF_ERROR : Z_OK; + return nExtraChunks ? Z_BUF_ERROR : Z_OK; } static const char magic[5] = "ZIMG"; static unsigned int log2i(unsigned int val) { - unsigned int ret = -1; - while (val != 0) { - val >>= 1; ret++; - } - return ret; + unsigned int ret = -1; + while (val != 0) { + val >>= 1; ret++; + } + return ret; } int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, uint8 **image) { - if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') { - ELOG("Not a ZIM file"); - return 0; - } - memcpy(width, zim + 4, 4); - memcpy(height, zim + 8, 4); - memcpy(flags, zim + 12, 4); + if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') { + ELOG("Not a ZIM file"); + return 0; + } + memcpy(width, zim + 4, 4); + memcpy(height, zim + 8, 4); + memcpy(flags, zim + 12, 4); - int num_levels = 1; - int image_data_size[ZIM_MAX_MIP_LEVELS]; - if (*flags & ZIM_HAS_MIPS) { - num_levels = log2i(*width < *height ? *width : *height) + 1; - } - int total_data_size = 0; - for (int i = 0; i < num_levels; i++) { - if (i > 0) { - width[i] = width[i-1] / 2; - height[i] = height[i-1] / 2; - } - switch (*flags & ZIM_FORMAT_MASK) { - case ZIM_RGBA8888: - image_data_size[i] = width[i] * height[i] * 4; - break; - case ZIM_RGBA4444: - case ZIM_RGB565: - image_data_size[i] = width[i] * height[i] * 2; - break; - case ZIM_ETC1: - { - int data_width = width[i]; - int data_height = height[i]; - if (data_width < 4) data_width = 4; - if (data_height < 4) data_height = 4; - image_data_size[i] = data_width * data_height / 2; - break; - } - default: - ELOG("Invalid ZIM format %i", *flags & ZIM_FORMAT_MASK); - return 0; - } - total_data_size += image_data_size[i]; - } + int num_levels = 1; + int image_data_size[ZIM_MAX_MIP_LEVELS]; + if (*flags & ZIM_HAS_MIPS) { + num_levels = log2i(*width < *height ? *width : *height) + 1; + } + int total_data_size = 0; + for (int i = 0; i < num_levels; i++) { + if (i > 0) { + width[i] = width[i-1] / 2; + height[i] = height[i-1] / 2; + } + switch (*flags & ZIM_FORMAT_MASK) { + case ZIM_RGBA8888: + image_data_size[i] = width[i] * height[i] * 4; + break; + case ZIM_RGBA4444: + case ZIM_RGB565: + image_data_size[i] = width[i] * height[i] * 2; + break; + case ZIM_ETC1: + { + int data_width = width[i]; + int data_height = height[i]; + if (data_width < 4) data_width = 4; + if (data_height < 4) data_height = 4; + image_data_size[i] = data_width * data_height / 2; + break; + } + default: + ELOG("Invalid ZIM format %i", *flags & ZIM_FORMAT_MASK); + return 0; + } + total_data_size += image_data_size[i]; + } - image[0] = (uint8 *)malloc(total_data_size); - for (int i = 1; i < num_levels; i++) { - image[i] = image[i-1] + image_data_size[i-1]; - } + image[0] = (uint8 *)malloc(total_data_size); + for (int i = 1; i < num_levels; i++) { + image[i] = image[i-1] + image_data_size[i-1]; + } - if (*flags & ZIM_ZLIB_COMPRESSED) { - long outlen = total_data_size; - if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), datasize - 16)) { - free(*image); - *image = 0; - return 0; - } - if (outlen != total_data_size) { - ELOG("Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size); - } - } else { - memcpy(*image, zim + 16, datasize - 16); - if (datasize - 16 != total_data_size) { - ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size); - } - } - return num_levels; + if (*flags & ZIM_ZLIB_COMPRESSED) { + long outlen = total_data_size; + if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), datasize - 16)) { + free(*image); + *image = 0; + return 0; + } + if (outlen != total_data_size) { + ELOG("Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size); + } + } else { + memcpy(*image, zim + 16, datasize - 16); + if (datasize - 16 != total_data_size) { + ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size); + } + } + return num_levels; } int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t **image) { - size_t size; - uint8_t *buffer = VFSReadFile(filename, &size); - if (!buffer) { - return 0; - } - int retval = LoadZIMPtr(buffer, size, width, height, format, image); - if (!retval) { - ELOG("Not a valid ZIM file: %s", filename); - } - delete [] buffer; - return retval; + size_t size; + uint8_t *buffer = VFSReadFile(filename, &size); + if (!buffer) { + return 0; + } + int retval = LoadZIMPtr(buffer, size, width, height, format, image); + if (!retval) { + ELOG("Not a valid ZIM file: %s", filename); + } + delete [] buffer; + return retval; } diff --git a/image/zim_load.h b/image/zim_load.h index cc4eb925ed..fc10dd4a5d 100644 --- a/image/zim_load.h +++ b/image/zim_load.h @@ -18,26 +18,26 @@ // Defined flags: enum { - ZIM_RGBA8888 = 0, // Assumed format if no other format is set - ZIM_RGBA4444 = 1, // GL_UNSIGNED_SHORT_4_4_4_4 - ZIM_RGB565 = 2, // GL_UNSIGNED_SHORT_5_6_5 - ZIM_ETC1 = 3, - ZIM_RGB888 = 4, - ZIM_LUMINANCE_ALPHA = 5, - ZIM_LUMINANCE = 6, - ZIM_ALPHA = 7, - // There's space for plenty more formats. - ZIM_FORMAT_MASK = 15, - ZIM_HAS_MIPS = 16, // If set, assumes that a full mip chain is present. Mips are zlib-compressed individually and stored in sequence. Always half sized. - ZIM_GEN_MIPS = 32, // If set, the caller is advised to automatically generate mips. (maybe later, the ZIM lib will generate the mips for you). - ZIM_DITHER = 64, // If set, dithers during save if color reduction is necessary. - ZIM_CLAMP = 128, // Texture should default to clamp instead of wrap. - ZIM_ZLIB_COMPRESSED = 256, + ZIM_RGBA8888 = 0, // Assumed format if no other format is set + ZIM_RGBA4444 = 1, // GL_UNSIGNED_SHORT_4_4_4_4 + ZIM_RGB565 = 2, // GL_UNSIGNED_SHORT_5_6_5 + ZIM_ETC1 = 3, + ZIM_RGB888 = 4, + ZIM_LUMINANCE_ALPHA = 5, + ZIM_LUMINANCE = 6, + ZIM_ALPHA = 7, + // There's space for plenty more formats. + ZIM_FORMAT_MASK = 15, + ZIM_HAS_MIPS = 16, // If set, assumes that a full mip chain is present. Mips are zlib-compressed individually and stored in sequence. Always half sized. + ZIM_GEN_MIPS = 32, // If set, the caller is advised to automatically generate mips. (maybe later, the ZIM lib will generate the mips for you). + ZIM_DITHER = 64, // If set, dithers during save if color reduction is necessary. + ZIM_CLAMP = 128, // Texture should default to clamp instead of wrap. + ZIM_ZLIB_COMPRESSED = 256, }; // ZIM will only ever support up to 12 levels (4096x4096 max). enum { - ZIM_MAX_MIP_LEVELS = 12, + ZIM_MAX_MIP_LEVELS = 12, }; // Delete the returned pointer using free() diff --git a/image/zim_save.cpp b/image/zim_save.cpp index c4a06b2565..9c62ea64e5 100644 --- a/image/zim_save.cpp +++ b/image/zim_save.cpp @@ -12,55 +12,55 @@ if (flags & ZIM_HAS_MIPS) { num_levels = log2i(width > height ? width : height); }*/ static unsigned int log2i(unsigned int val) { - unsigned int ret = -1; - while (val != 0) { - val >>= 1; ret++; - } - return ret; + unsigned int ret = -1; + while (val != 0) { + val >>= 1; ret++; + } + return ret; } int ezcompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) { - z_stream stream; - int err; + z_stream stream; + int err; - int nExtraChunks; - uInt destlen; + int nExtraChunks; + uInt destlen; - stream.next_in = (Bytef*)pSrc; - stream.avail_in = (uInt)nSrcLen; + stream.next_in = (Bytef*)pSrc; + stream.avail_in = (uInt)nSrcLen; #ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != nSrcLen) return Z_BUF_ERROR; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != nSrcLen) return Z_BUF_ERROR; #endif - destlen = (uInt)*pnDestLen; - if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; + destlen = (uInt)*pnDestLen; + if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; - err = deflateInit(&stream, Z_DEFAULT_COMPRESSION); - if (err != Z_OK) return err; - nExtraChunks = 0; - do { - stream.next_out = pDest; - stream.avail_out = destlen; - err = deflate(&stream, Z_FINISH); - if (err == Z_STREAM_END ) - break; - if (err != Z_OK) { - deflateEnd(&stream); - return err; - } - nExtraChunks += 1; - } while (stream.avail_out == 0); + err = deflateInit(&stream, Z_DEFAULT_COMPRESSION); + if (err != Z_OK) return err; + nExtraChunks = 0; + do { + stream.next_out = pDest; + stream.avail_out = destlen; + err = deflate(&stream, Z_FINISH); + if (err == Z_STREAM_END ) + break; + if (err != Z_OK) { + deflateEnd(&stream); + return err; + } + nExtraChunks += 1; + } while (stream.avail_out == 0); - *pnDestLen = stream.total_out; + *pnDestLen = stream.total_out; - err = deflateEnd(&stream); - if (err != Z_OK) return err; + err = deflateEnd(&stream); + if (err != Z_OK) return err; - return nExtraChunks ? Z_BUF_ERROR : Z_OK; + return nExtraChunks ? Z_BUF_ERROR : Z_OK; } inline int clamp16(int x) { if (x < 0) return 0; if (x > 15) return 15; return x; } @@ -69,179 +69,179 @@ inline int clamp64(int x) { if (x < 0) return 0; if (x > 63) return 63; return x bool ispowerof2 (int x) { - if (!x || (x&(x-1))) - return false; - else - return true; + if (!x || (x&(x-1))) + return false; + else + return true; } void Convert(const uint8_t *image_data, int width, int height, int pitch, int flags, - uint8_t **data, int *data_size) { - // For 4444 and 565. Ordered dither matrix. looks really surprisingly good on cell phone screens at 4444. - int dith[16] = { - 1, 9, 3, 11, - 13, 5, 15, 7, - 4, 12, 2, 10, - 16, 8, 14, 6 - }; - if ((flags & ZIM_DITHER) == 0) { - for (int i = 0; i < 16; i++) { dith[i] = 8; } - } - switch (flags & ZIM_FORMAT_MASK) { - case ZIM_RGBA8888: - { - *data_size = width * height * 4; - *data = new uint8_t[width * height * 4]; - for (int y = 0; y < height; y++) { - memcpy((*data) + y * width * 4, image_data + y * pitch, width * 4); - } - break; - } - case ZIM_ETC1: { - // Check for power of 2 - if (!ispowerof2(width) || !ispowerof2(height)) { - FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height); - } - // Convert RGBX to ETC1 before saving. - int blockw = width/4; - int blockh = height/4; - *data_size = blockw * blockh * 8; - *data = new uint8_t[*data_size]; + uint8_t **data, int *data_size) { + // For 4444 and 565. Ordered dither matrix. looks really surprisingly good on cell phone screens at 4444. + int dith[16] = { + 1, 9, 3, 11, + 13, 5, 15, 7, + 4, 12, 2, 10, + 16, 8, 14, 6 + }; + if ((flags & ZIM_DITHER) == 0) { + for (int i = 0; i < 16; i++) { dith[i] = 8; } + } + switch (flags & ZIM_FORMAT_MASK) { + case ZIM_RGBA8888: + { + *data_size = width * height * 4; + *data = new uint8_t[width * height * 4]; + for (int y = 0; y < height; y++) { + memcpy((*data) + y * width * 4, image_data + y * pitch, width * 4); + } + break; + } + case ZIM_ETC1: { + // Check for power of 2 + if (!ispowerof2(width) || !ispowerof2(height)) { + FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height); + } + // Convert RGBX to ETC1 before saving. + int blockw = width/4; + int blockh = height/4; + *data_size = blockw * blockh * 8; + *data = new uint8_t[*data_size]; #pragma omp parallel for - for (int y = 0; y < blockh; y++) { - for (int x = 0; x < blockw; x++) { - CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width, - (*data) + (blockw * y + x) * 8, 1); - } - } - width = blockw * 4; - height = blockh * 4; - break; - } - case ZIM_RGBA4444: - { - *data_size = width * height * 2; - *data = new uint8_t[*data_size]; - uint16_t *dst = (uint16_t *)(*data); - int i = 0; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int dithval = dith[(x&3)+((y&0x3)<<2)] - 8; - int r = clamp16((image_data[i * 4] + dithval) >> 4); - int g = clamp16((image_data[i * 4 + 1] + dithval) >> 4); - int b = clamp16((image_data[i * 4 + 2] + dithval) >> 4); - int a = clamp16((image_data[i * 4 + 3] + dithval) >> 4); // really dither alpha? - // Note: GL_UNSIGNED_SHORT_4_4_4_4, not GL_UNSIGNED_SHORT_4_4_4_4_REV - *dst++ = (r << 12) | (g << 8) | (b << 4) | (a << 0); - i++; - } - } - break; - } - case ZIM_RGB565: - { - *data_size = width * height * 2; - *data = new uint8_t[*data_size]; - uint16_t *dst = (uint16_t *)(*data); - int i = 0; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int dithval = dith[(x&3)+((y&0x3)<<2)] - 8; - dithval = 0; - int r = clamp32((image_data[i * 4] + dithval/2) >> 3); - int g = clamp64((image_data[i * 4 + 1] + dithval/4) >> 2); - int b = clamp32((image_data[i * 4 + 2] + dithval/2) >> 3); - // Note: GL_UNSIGNED_SHORT_5_6_5, not GL_UNSIGNED_SHORT_5_6_5_REV - *dst++ = (r << 11) | (g << 5) | (b); - i++; - } - } - } - break; + for (int y = 0; y < blockh; y++) { + for (int x = 0; x < blockw; x++) { + CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width, + (*data) + (blockw * y + x) * 8, 1); + } + } + width = blockw * 4; + height = blockh * 4; + break; + } + case ZIM_RGBA4444: + { + *data_size = width * height * 2; + *data = new uint8_t[*data_size]; + uint16_t *dst = (uint16_t *)(*data); + int i = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int dithval = dith[(x&3)+((y&0x3)<<2)] - 8; + int r = clamp16((image_data[i * 4] + dithval) >> 4); + int g = clamp16((image_data[i * 4 + 1] + dithval) >> 4); + int b = clamp16((image_data[i * 4 + 2] + dithval) >> 4); + int a = clamp16((image_data[i * 4 + 3] + dithval) >> 4); // really dither alpha? + // Note: GL_UNSIGNED_SHORT_4_4_4_4, not GL_UNSIGNED_SHORT_4_4_4_4_REV + *dst++ = (r << 12) | (g << 8) | (b << 4) | (a << 0); + i++; + } + } + break; + } + case ZIM_RGB565: + { + *data_size = width * height * 2; + *data = new uint8_t[*data_size]; + uint16_t *dst = (uint16_t *)(*data); + int i = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int dithval = dith[(x&3)+((y&0x3)<<2)] - 8; + dithval = 0; + int r = clamp32((image_data[i * 4] + dithval/2) >> 3); + int g = clamp64((image_data[i * 4 + 1] + dithval/4) >> 2); + int b = clamp32((image_data[i * 4 + 2] + dithval/2) >> 3); + // Note: GL_UNSIGNED_SHORT_5_6_5, not GL_UNSIGNED_SHORT_5_6_5_REV + *dst++ = (r << 11) | (g << 5) | (b); + i++; + } + } + } + break; - default: - ELOG("Unhandled ZIM format %i", flags & ZIM_FORMAT_MASK); - *data = 0; - *data_size = 0; - return; - } + default: + ELOG("Unhandled ZIM format %i", flags & ZIM_FORMAT_MASK); + *data = 0; + *data_size = 0; + return; + } } // Deletes the old buffer. uint8_t *DownsampleBy2(const uint8_t *image, int width, int height, int pitch) { - uint8_t *out = new uint8_t[(width/2) * (height/2) * 4]; + uint8_t *out = new uint8_t[(width/2) * (height/2) * 4]; - int degamma[256]; - int gamma[32768]; - for (int i =0; i < 256; i++) { - degamma[i] = powf((float)i / 255.0f, 1.0f/2.2f) * 8191.0f; - } - for (int i = 0; i < 32768; i++) { - gamma[i] = powf((float)i / 32764.0f, 2.2f) * 255.0f; - } + int degamma[256]; + int gamma[32768]; + for (int i =0; i < 256; i++) { + degamma[i] = powf((float)i / 255.0f, 1.0f/2.2f) * 8191.0f; + } + for (int i = 0; i < 32768; i++) { + gamma[i] = powf((float)i / 32764.0f, 2.2f) * 255.0f; + } - // Really stupid mipmap downsampling - at least it does gamma though. - for (int y = 0; y < height; y+=2) { - for (int x = 0; x < width; x+=2) { - const uint8_t *tl = image + pitch * y + x*4; - const uint8_t *tr = tl + 4; - const uint8_t *bl = tl + pitch; - const uint8_t *br = bl + 4; - uint8_t *d = out + ((y/2) * ((width/2)) + x / 2) * 4; - for (int c = 0; c < 4; c++) { - d[c] = gamma[degamma[tl[c]] + degamma[tr[c]] + degamma[bl[c]] + degamma[br[c]]]; - } - } - } - return out; + // Really stupid mipmap downsampling - at least it does gamma though. + for (int y = 0; y < height; y+=2) { + for (int x = 0; x < width; x+=2) { + const uint8_t *tl = image + pitch * y + x*4; + const uint8_t *tr = tl + 4; + const uint8_t *bl = tl + pitch; + const uint8_t *br = bl + 4; + uint8_t *d = out + ((y/2) * ((width/2)) + x / 2) * 4; + for (int c = 0; c < 4; c++) { + d[c] = gamma[degamma[tl[c]] + degamma[tr[c]] + degamma[bl[c]] + degamma[br[c]]]; + } + } + } + return out; } void SaveZIM(const char *filename, int width, int height, int pitch, int flags, const uint8_t *image_data) { - FILE *f = fopen(filename, "wb"); - fwrite(magic, 1, 4, f); - fwrite(&width, 1, 4, f); - fwrite(&height, 1, 4, f); - fwrite(&flags, 1, 4, f); + FILE *f = fopen(filename, "wb"); + fwrite(magic, 1, 4, f); + fwrite(&width, 1, 4, f); + fwrite(&height, 1, 4, f); + fwrite(&flags, 1, 4, f); - int num_levels = 1; - if (flags & ZIM_HAS_MIPS) { - num_levels = log2i(width > height ? height : width) + 1; - } - for (int i = 0; i < num_levels; i++) { - uint8_t *data = 0; - int data_size; - Convert(image_data, width, height, pitch, flags, &data, &data_size); - if (flags & ZIM_ZLIB_COMPRESSED) { - long dest_len = data_size * 2; - uint8_t *dest = new uint8_t[dest_len]; - if (Z_OK == ezcompress(dest, &dest_len, data, data_size)) { - fwrite(dest, 1, dest_len, f); - } else { - ELOG("Zlib compression failed.\n"); - } - delete [] dest; - } else { - fwrite(data, 1, data_size, f); - } - delete [] data; + int num_levels = 1; + if (flags & ZIM_HAS_MIPS) { + num_levels = log2i(width > height ? height : width) + 1; + } + for (int i = 0; i < num_levels; i++) { + uint8_t *data = 0; + int data_size; + Convert(image_data, width, height, pitch, flags, &data, &data_size); + if (flags & ZIM_ZLIB_COMPRESSED) { + long dest_len = data_size * 2; + uint8_t *dest = new uint8_t[dest_len]; + if (Z_OK == ezcompress(dest, &dest_len, data, data_size)) { + fwrite(dest, 1, dest_len, f); + } else { + ELOG("Zlib compression failed.\n"); + } + delete [] dest; + } else { + fwrite(data, 1, data_size, f); + } + delete [] data; - if (i != num_levels - 1) { - uint8_t *smaller = DownsampleBy2(image_data, width, height, pitch); - if (i != 0) { - delete [] image_data; - } - image_data = smaller; - width /= 2; - height /= 2; - if ((flags & ZIM_FORMAT_MASK) == ZIM_ETC1) { - if (width < 4) width = 4; - if (height < 4) height = 4; - } - pitch = width * 4; - } - } - delete [] image_data; - fclose(f); + if (i != num_levels - 1) { + uint8_t *smaller = DownsampleBy2(image_data, width, height, pitch); + if (i != 0) { + delete [] image_data; + } + image_data = smaller; + width /= 2; + height /= 2; + if ((flags & ZIM_FORMAT_MASK) == ZIM_ETC1) { + if (width < 4) width = 4; + if (height < 4) height = 4; + } + pitch = width * 4; + } + } + delete [] image_data; + fclose(f); } diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index f2ec3a81d4..e9264762dc 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -7,17 +7,17 @@ namespace GestureDetector { struct Finger { - bool down; - float X; - float Y; - float lastX; - float lastY; - float downX; - float downY; - float deltaX; - float deltaY; - float smoothDeltaX; - float smoothDeltaY; + bool down; + float X; + float Y; + float lastX; + float lastY; + float downX; + float downY; + float deltaX; + float deltaY; + float smoothDeltaX; + float smoothDeltaY; }; // State @@ -26,46 +26,46 @@ struct Finger { static Finger fingers[MAX_FINGERS]; void update(const InputState &state) { - // Mouse / 1-finger-touch control. - if (state.pointer_down[0]) { - fingers[0].down = true; - fingers[0].downX = state.pointer_x[0]; - fingers[0].downY = state.pointer_y[0]; - } else { - fingers[0].down = false; - } + // Mouse / 1-finger-touch control. + if (state.pointer_down[0]) { + fingers[0].down = true; + fingers[0].downX = state.pointer_x[0]; + fingers[0].downY = state.pointer_y[0]; + } else { + fingers[0].down = false; + } - fingers[0].lastX = fingers[0].X; - fingers[0].lastY = fingers[0].Y; + fingers[0].lastX = fingers[0].X; + fingers[0].lastY = fingers[0].Y; - // TODO: real multitouch + // TODO: real multitouch } bool down(int i, float *xdelta, float *ydelta) { - if (!fingers[i].down) { - return false; - } - *xdelta = fingers[i].downX; - *ydelta = fingers[i].downY; - return true; + if (!fingers[i].down) { + return false; + } + *xdelta = fingers[i].downX; + *ydelta = fingers[i].downY; + return true; } bool dragDistance(int i, float *xdelta, float *ydelta) { - if (!fingers[i].down) - return false; + if (!fingers[i].down) + return false; - *xdelta = fingers[i].X - fingers[i].downX; - *ydelta = fingers[i].Y - fingers[i].downY; - return true; + *xdelta = fingers[i].X - fingers[i].downX; + *ydelta = fingers[i].Y - fingers[i].downY; + return true; } bool dragDelta(int i, float *xdelta, float *ydelta) { - if (!fingers[i].down) - return false; + if (!fingers[i].down) + return false; - *xdelta = fingers[i].X - fingers[i].lastX; - *ydelta = fingers[i].Y - fingers[i].lastY; - return true; + *xdelta = fingers[i].X - fingers[i].lastX; + *ydelta = fingers[i].Y - fingers[i].lastY; + return true; } } diff --git a/input/gesture_detector.h b/input/gesture_detector.h index 9f5ea36658..a52636b9f0 100644 --- a/input/gesture_detector.h +++ b/input/gesture_detector.h @@ -5,17 +5,17 @@ namespace GestureDetector { - void update(const InputState &state); + void update(const InputState &state); - bool down(int finger, float *xdown, float *ydown); + bool down(int finger, float *xdown, float *ydown); - // x/ydelta is difference from current location to the start of the drag. - // Returns true if button/finger is down, for convenience. - bool dragDistance(int finger, float *xdelta, float *ydelta); - - // x/ydelta is (smoothed?) difference from current location to the position from the last frame. - // Returns true if button/finger is down, for convenience. - bool dragDelta(int finger, float *xdelta, float *ydelta); + // x/ydelta is difference from current location to the start of the drag. + // Returns true if button/finger is down, for convenience. + bool dragDistance(int finger, float *xdelta, float *ydelta); + + // x/ydelta is (smoothed?) difference from current location to the position from the last frame. + // Returns true if button/finger is down, for convenience. + bool dragDelta(int finger, float *xdelta, float *ydelta); }; diff --git a/input/input_state.h b/input/input_state.h index b73c65fe40..cebc112863 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -5,18 +5,18 @@ #include "base/basictypes.h" enum { - PAD_BUTTON_A = 1, - PAD_BUTTON_B = 2, - PAD_BUTTON_X = 4, - PAD_BUTTON_Y = 8, - PAD_BUTTON_LBUMPER = 16, - PAD_BUTTON_RBUMPER = 32, - PAD_BUTTON_START = 64, - PAD_BUTTON_SELECT = 128, - PAD_BUTTON_UP = 256, - PAD_BUTTON_DOWN = 512, - PAD_BUTTON_LEFT = 1024, - PAD_BUTTON_RIGHT = 2048, + PAD_BUTTON_A = 1, + PAD_BUTTON_B = 2, + PAD_BUTTON_X = 4, + PAD_BUTTON_Y = 8, + PAD_BUTTON_LBUMPER = 16, + PAD_BUTTON_RBUMPER = 32, + PAD_BUTTON_START = 64, + PAD_BUTTON_SELECT = 128, + PAD_BUTTON_UP = 256, + PAD_BUTTON_DOWN = 512, + PAD_BUTTON_LEFT = 1024, + PAD_BUTTON_RIGHT = 2048, // Android only PAD_BUTTON_MENU = 4096, @@ -26,55 +26,55 @@ enum { #ifndef MAX_POINTERS #define MAX_POINTERS 8 #endif - + // Agglomeration of all possible inputs, and automatically computed // deltas where applicable. struct InputState { - // Lock this whenever you access the data in this struct. - mutable recursive_mutex lock; - InputState() - : pad_buttons(0), - pad_last_buttons(0), - pad_buttons_down(0), - pad_buttons_up(0), - mouse_valid(false), - accelerometer_valid(false) { - memset(pointer_down, 0, sizeof(pointer_down)); - } + // Lock this whenever you access the data in this struct. + mutable recursive_mutex lock; + InputState() + : pad_buttons(0), + pad_last_buttons(0), + pad_buttons_down(0), + pad_buttons_up(0), + mouse_valid(false), + accelerometer_valid(false) { + memset(pointer_down, 0, sizeof(pointer_down)); + } - // Gamepad style input - int pad_buttons; // bitfield - int pad_last_buttons; - int pad_buttons_down; // buttons just pressed this frame - int pad_buttons_up; // buttons just pressed last frame - float pad_lstick_x; - float pad_lstick_y; - float pad_rstick_x; - float pad_rstick_y; - float pad_ltrigger; - float pad_rtrigger; + // Gamepad style input + int pad_buttons; // bitfield + int pad_last_buttons; + int pad_buttons_down; // buttons just pressed this frame + int pad_buttons_up; // buttons just pressed last frame + float pad_lstick_x; + float pad_lstick_y; + float pad_rstick_x; + float pad_rstick_y; + float pad_ltrigger; + float pad_rtrigger; - // Mouse/touch style input - // There are up to 8 mice / fingers. - volatile bool mouse_valid; + // Mouse/touch style input + // There are up to 8 mice / fingers. + volatile bool mouse_valid; - int pointer_x[MAX_POINTERS]; - int pointer_y[MAX_POINTERS]; - bool pointer_down[MAX_POINTERS]; + int pointer_x[MAX_POINTERS]; + int pointer_y[MAX_POINTERS]; + bool pointer_down[MAX_POINTERS]; - // Accelerometer - bool accelerometer_valid; - Vec3 acc; + // Accelerometer + bool accelerometer_valid; + Vec3 acc; private: - DISALLOW_COPY_AND_ASSIGN(InputState); + DISALLOW_COPY_AND_ASSIGN(InputState); }; inline void UpdateInputState(InputState *input) { - input->pad_buttons_down = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_buttons; - input->pad_buttons_up = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_last_buttons; + input->pad_buttons_down = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_buttons; + input->pad_buttons_up = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_last_buttons; } inline void EndInputState(InputState *input) { - input->pad_last_buttons = input->pad_buttons; + input->pad_last_buttons = input->pad_buttons; } diff --git a/json/json_writer.cpp b/json/json_writer.cpp index 3657129cda..ec9019c50d 100644 --- a/json/json_writer.cpp +++ b/json/json_writer.cpp @@ -7,109 +7,109 @@ JsonWriter::~JsonWriter() { } void JsonWriter::begin() { - str_ << "{"; - stack_.push_back(StackEntry(DICT)); + str_ << "{"; + stack_.push_back(StackEntry(DICT)); } void JsonWriter::end() { - pop(); - str_ << "\n"; + pop(); + str_ << "\n"; } const char *JsonWriter::indent(int n) const { - static const char * const whitespace = " "; - return whitespace + (32 - n); + static const char * const whitespace = " "; + return whitespace + (32 - n); } const char *JsonWriter::indent() const { - int amount = (int)stack_.size() + 1; - amount *= 2; // 2-space indent. - return indent(amount); + int amount = (int)stack_.size() + 1; + amount *= 2; // 2-space indent. + return indent(amount); } const char *JsonWriter::arrayIndent() const { - int amount = (int)stack_.size() + 1; - amount *= 2; // 2-space indent. - return stack_.back().first ? indent(amount) : ""; + int amount = (int)stack_.size() + 1; + amount *= 2; // 2-space indent. + return stack_.back().first ? indent(amount) : ""; } const char *JsonWriter::comma() const { - if (stack_.back().first) { - return ""; - } else { - return ","; - } + if (stack_.back().first) { + return ""; + } else { + return ","; + } } const char *JsonWriter::arrayComma() const { - if (stack_.back().first) { - return "\n"; - } else { - return ", "; - } + if (stack_.back().first) { + return "\n"; + } else { + return ", "; + } } void JsonWriter::pushDict(const char *name) { - str_ << comma() << "\n" << indent() << "\"" << name << "\": {"; - stack_.push_back(StackEntry(DICT)); + str_ << comma() << "\n" << indent() << "\"" << name << "\": {"; + stack_.push_back(StackEntry(DICT)); } void JsonWriter::pushArray(const char *name) { - str_ << comma() << "\n" << indent() << "\"" << name << "\": ["; - stack_.push_back(StackEntry(ARRAY)); + str_ << comma() << "\n" << indent() << "\"" << name << "\": ["; + stack_.push_back(StackEntry(ARRAY)); } void JsonWriter::writeBool(bool value) { - str_ << arrayComma() << arrayIndent() << (value ? "true" : "false"); - stack_.back().first = false; + str_ << arrayComma() << arrayIndent() << (value ? "true" : "false"); + stack_.back().first = false; } void JsonWriter::writeBool(const char *name, bool value) { - str_ << comma() << "\n" << indent() << "\"" << name << "\": " << (value ? "true" : "false"); - stack_.back().first = false; + str_ << comma() << "\n" << indent() << "\"" << name << "\": " << (value ? "true" : "false"); + stack_.back().first = false; } void JsonWriter::writeInt(int value) { - str_ << arrayComma() << arrayIndent() << value; - stack_.back().first = false; + str_ << arrayComma() << arrayIndent() << value; + stack_.back().first = false; } void JsonWriter::writeInt(const char *name, int value) { - str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value; - stack_.back().first = false; + str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value; + stack_.back().first = false; } void JsonWriter::writeFloat(double value) { - str_ << arrayComma() << arrayIndent() << value; - stack_.back().first = false; + str_ << arrayComma() << arrayIndent() << value; + stack_.back().first = false; } void JsonWriter::writeFloat(const char *name, double value) { - str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value; - stack_.back().first = false; + str_ << comma() << "\n" << indent() << "\"" << name << "\": " << value; + stack_.back().first = false; } void JsonWriter::writeString(const char *value) { - str_ << arrayComma() << arrayIndent() << "\"" << value << "\""; - stack_.back().first = false; + str_ << arrayComma() << arrayIndent() << "\"" << value << "\""; + stack_.back().first = false; } void JsonWriter::writeString(const char *name, const char *value) { - str_ << comma() << "\n" << indent() << "\"" << name << "\": \"" << value << "\""; - stack_.back().first = false; + str_ << comma() << "\n" << indent() << "\"" << name << "\": \"" << value << "\""; + stack_.back().first = false; } void JsonWriter::pop() { - BlockType type = stack_.back().type; - stack_.pop_back(); - switch (type) { - case ARRAY: - str_ << "\n" << indent() << "]"; - break; - case DICT: - str_ << "\n" << indent() << "}"; - break; - } - if (stack_.size() > 0) - stack_.back().first = false; + BlockType type = stack_.back().type; + stack_.pop_back(); + switch (type) { + case ARRAY: + str_ << "\n" << indent() << "]"; + break; + case DICT: + str_ << "\n" << indent() << "}"; + break; + } + if (stack_.size() > 0) + stack_.back().first = false; } diff --git a/json/json_writer.h b/json/json_writer.h index 55f2608c1c..faf9e4d937 100644 --- a/json/json_writer.h +++ b/json/json_writer.h @@ -18,43 +18,43 @@ class JsonWriter { public: - JsonWriter(); - ~JsonWriter(); - void begin(); - void end(); - void pushDict(const char *name); - void pushArray(const char *name); - void pop(); - void writeBool(bool value); - void writeBool(const char *name, bool value); - void writeInt(int value); - void writeInt(const char *name, int value); - void writeFloat(double value); - void writeFloat(const char *name, double value); - void writeString(const char *value); - void writeString(const char *name, const char *value); + JsonWriter(); + ~JsonWriter(); + void begin(); + void end(); + void pushDict(const char *name); + void pushArray(const char *name); + void pop(); + void writeBool(bool value); + void writeBool(const char *name, bool value); + void writeInt(int value); + void writeInt(const char *name, int value); + void writeFloat(double value); + void writeFloat(const char *name, double value); + void writeString(const char *value); + void writeString(const char *name, const char *value); - std::string str() const { - return str_.str(); - } + std::string str() const { + return str_.str(); + } private: - const char *indent(int n) const; - const char *comma() const; - const char *arrayComma() const; - const char *indent() const; - const char *arrayIndent() const; - enum BlockType { - ARRAY, - DICT, - }; - struct StackEntry { - StackEntry(BlockType t) : type(t), first(true) {} - BlockType type; - bool first; - }; - std::vector stack_; - std::ostringstream str_; + const char *indent(int n) const; + const char *comma() const; + const char *arrayComma() const; + const char *indent() const; + const char *arrayIndent() const; + enum BlockType { + ARRAY, + DICT, + }; + struct StackEntry { + StackEntry(BlockType t) : type(t), first(true) {} + BlockType type; + bool first; + }; + std::vector stack_; + std::ostringstream str_; - DISALLOW_COPY_AND_ASSIGN(JsonWriter); + DISALLOW_COPY_AND_ASSIGN(JsonWriter); }; diff --git a/math/compression.h b/math/compression.h index 3d96cc6eee..f9e457c8d0 100644 --- a/math/compression.h +++ b/math/compression.h @@ -5,18 +5,18 @@ template inline void delta(T *data, int length) { - T prev = data[0]; - for (int i = 1; i < length; i++) { - T temp = data[i] - prev; - prev = data[i]; - data[i] = temp; - } + T prev = data[0]; + for (int i = 1; i < length; i++) { + T temp = data[i] - prev; + prev = data[i]; + data[i] = temp; + } } template inline void dedelta(T *data, int length) { - for (int i = 1; i < length; i++) { - data[i] += data[i - 1]; - } + for (int i = 1; i < length; i++) { + data[i] += data[i - 1]; + } } diff --git a/math/lin/aabb.h b/math/lin/aabb.h index 6f887f876e..cf7cf963be 100644 --- a/math/lin/aabb.h +++ b/math/lin/aabb.h @@ -15,7 +15,7 @@ struct AABB { bool Contains(const Vec3 &pt) const; bool IntersectRay(const Ray &ray, float &tnear, float &tfar) const; - // Doesn't currently work. + // Doesn't currently work. bool IntersectRay2(const Ray &ray, float &tnear, float &tfar) const; bool IntersectsTriangle(const Vec3& a_V0, const Vec3& a_V1, const Vec3& a_V2) const; @@ -36,5 +36,5 @@ struct AABB { return maxB - minB; } - bool BehindPlane(const Plane &plane) const; + bool BehindPlane(const Plane &plane) const; }; diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp index 2d3ce84299..ec0ef64633 100644 --- a/math/lin/matrix4x4.cpp +++ b/math/lin/matrix4x4.cpp @@ -10,271 +10,271 @@ #undef near #endif -// See http://code.google.com/p/oolongengine/source/browse/trunk/Oolong+Engine2/Math/neonmath/neon_matrix_impl.cpp?spec=svn143&r=143 when we need speed +// See http://code.google.com/p/oolongengine/source/browse/trunk/Oolong+Engine2/Math/neonmath/neon_matrix_impl.cpp?spec=svn143&r=143 when we need speed // no wait. http://code.google.com/p/math-neon/ void matrix_mul_4x4(Matrix4x4 &res, const Matrix4x4 &inA, const Matrix4x4 &inB) { - res.xx = inA.xx*inB.xx + inA.xy*inB.yx + inA.xz*inB.zx + inA.xw*inB.wx; - res.xy = inA.xx*inB.xy + inA.xy*inB.yy + inA.xz*inB.zy + inA.xw*inB.wy; - res.xz = inA.xx*inB.xz + inA.xy*inB.yz + inA.xz*inB.zz + inA.xw*inB.wz; - res.xw = inA.xx*inB.xw + inA.xy*inB.yw + inA.xz*inB.zw + inA.xw*inB.ww; + res.xx = inA.xx*inB.xx + inA.xy*inB.yx + inA.xz*inB.zx + inA.xw*inB.wx; + res.xy = inA.xx*inB.xy + inA.xy*inB.yy + inA.xz*inB.zy + inA.xw*inB.wy; + res.xz = inA.xx*inB.xz + inA.xy*inB.yz + inA.xz*inB.zz + inA.xw*inB.wz; + res.xw = inA.xx*inB.xw + inA.xy*inB.yw + inA.xz*inB.zw + inA.xw*inB.ww; - res.yx = inA.yx*inB.xx + inA.yy*inB.yx + inA.yz*inB.zx + inA.yw*inB.wx; - res.yy = inA.yx*inB.xy + inA.yy*inB.yy + inA.yz*inB.zy + inA.yw*inB.wy; - res.yz = inA.yx*inB.xz + inA.yy*inB.yz + inA.yz*inB.zz + inA.yw*inB.wz; - res.yw = inA.yx*inB.xw + inA.yy*inB.yw + inA.yz*inB.zw + inA.yw*inB.ww; + res.yx = inA.yx*inB.xx + inA.yy*inB.yx + inA.yz*inB.zx + inA.yw*inB.wx; + res.yy = inA.yx*inB.xy + inA.yy*inB.yy + inA.yz*inB.zy + inA.yw*inB.wy; + res.yz = inA.yx*inB.xz + inA.yy*inB.yz + inA.yz*inB.zz + inA.yw*inB.wz; + res.yw = inA.yx*inB.xw + inA.yy*inB.yw + inA.yz*inB.zw + inA.yw*inB.ww; - res.zx = inA.zx*inB.xx + inA.zy*inB.yx + inA.zz*inB.zx + inA.zw*inB.wx; - res.zy = inA.zx*inB.xy + inA.zy*inB.yy + inA.zz*inB.zy + inA.zw*inB.wy; - res.zz = inA.zx*inB.xz + inA.zy*inB.yz + inA.zz*inB.zz + inA.zw*inB.wz; - res.zw = inA.zx*inB.xw + inA.zy*inB.yw + inA.zz*inB.zw + inA.zw*inB.ww; + res.zx = inA.zx*inB.xx + inA.zy*inB.yx + inA.zz*inB.zx + inA.zw*inB.wx; + res.zy = inA.zx*inB.xy + inA.zy*inB.yy + inA.zz*inB.zy + inA.zw*inB.wy; + res.zz = inA.zx*inB.xz + inA.zy*inB.yz + inA.zz*inB.zz + inA.zw*inB.wz; + res.zw = inA.zx*inB.xw + inA.zy*inB.yw + inA.zz*inB.zw + inA.zw*inB.ww; - res.wx = inA.wx*inB.xx + inA.wy*inB.yx + inA.wz*inB.zx + inA.ww*inB.wx; - res.wy = inA.wx*inB.xy + inA.wy*inB.yy + inA.wz*inB.zy + inA.ww*inB.wy; - res.wz = inA.wx*inB.xz + inA.wy*inB.yz + inA.wz*inB.zz + inA.ww*inB.wz; - res.ww = inA.wx*inB.xw + inA.wy*inB.yw + inA.wz*inB.zw + inA.ww*inB.ww; + res.wx = inA.wx*inB.xx + inA.wy*inB.yx + inA.wz*inB.zx + inA.ww*inB.wx; + res.wy = inA.wx*inB.xy + inA.wy*inB.yy + inA.wz*inB.zy + inA.ww*inB.wy; + res.wz = inA.wx*inB.xz + inA.wy*inB.yz + inA.wz*inB.zz + inA.ww*inB.wz; + res.ww = inA.wx*inB.xw + inA.wy*inB.yw + inA.wz*inB.zw + inA.ww*inB.ww; } Matrix4x4 Matrix4x4::simpleInverse() const { - Matrix4x4 out; - out.xx = xx; - out.xy = yx; - out.xz = zx; + Matrix4x4 out; + out.xx = xx; + out.xy = yx; + out.xz = zx; - out.yx = xy; - out.yy = yy; - out.yz = zy; + out.yx = xy; + out.yy = yy; + out.yz = zy; - out.zx = xz; - out.zy = yz; - out.zz = zz; + out.zx = xz; + out.zy = yz; + out.zz = zz; - out.wx = -(xx * wx + xy * wy + xz * wz); - out.wy = -(yx * wx + yy * wy + yz * wz); - out.wz = -(zx * wx + zy * wy + zz * wz); + out.wx = -(xx * wx + xy * wy + xz * wz); + out.wy = -(yx * wx + yy * wy + yz * wz); + out.wz = -(zx * wx + zy * wy + zz * wz); - out.xw = 0.0f; - out.yw = 0.0f; - out.zw = 0.0f; - out.ww = 1.0f; + out.xw = 0.0f; + out.yw = 0.0f; + out.zw = 0.0f; + out.ww = 1.0f; - return out; + return out; } Matrix4x4 Matrix4x4::transpose() const { - Matrix4x4 out; - out.xx = xx;out.xy = yx;out.xz = zx;out.xw = wx; - out.yx = xy;out.yy = yy;out.yz = zy;out.yw = wy; - out.zx = xz;out.zy = yz;out.zz = zz;out.zw = wz; - out.wx = xw;out.wy = yw;out.wz = zw;out.ww = ww; - return out; + Matrix4x4 out; + out.xx = xx;out.xy = yx;out.xz = zx;out.xw = wx; + out.yx = xy;out.yy = yy;out.yz = zy;out.yw = wy; + out.zx = xz;out.zy = yz;out.zz = zz;out.zw = wz; + out.wx = xw;out.wy = yw;out.wz = zw;out.ww = ww; + return out; } Matrix4x4 Matrix4x4::operator * (const Matrix4x4 &other) const { - Matrix4x4 temp; - matrix_mul_4x4(temp, *this, other); - return temp; + Matrix4x4 temp; + matrix_mul_4x4(temp, *this, other); + return temp; } Matrix4x4 Matrix4x4::inverse() const { - Matrix4x4 temp; - float dW = 1.0f / (xx*(yy*zz - yz*zy) - xy*(yx*zz - yz*zx) - xz*(yy*zx - yx*zy)); + Matrix4x4 temp; + float dW = 1.0f / (xx*(yy*zz - yz*zy) - xy*(yx*zz - yz*zx) - xz*(yy*zx - yx*zy)); - temp.xx = (yy*zz - yz*zy) * dW; - temp.xy = (xz*zy - xy*zz) * dW; - temp.xz = (xy*yz - xz*yy) * dW; - temp.xw = xw; + temp.xx = (yy*zz - yz*zy) * dW; + temp.xy = (xz*zy - xy*zz) * dW; + temp.xz = (xy*yz - xz*yy) * dW; + temp.xw = xw; - temp.yx = (yz*zx - yx*zz) * dW; - temp.yy = (xx*zz - xz*zx) * dW; - temp.yz = (xz*yx - xx*zx) * dW; - temp.yw = yw; + temp.yx = (yz*zx - yx*zz) * dW; + temp.yy = (xx*zz - xz*zx) * dW; + temp.yz = (xz*yx - xx*zx) * dW; + temp.yw = yw; - temp.zx = (yx*zy - yy*zx) * dW; - temp.zy = (xy*zx - xx*zy) * dW; - temp.zz = (xx*yy - xy*yx) * dW; - temp.zw = zw; + temp.zx = (yx*zy - yy*zx) * dW; + temp.zy = (xy*zx - xx*zy) * dW; + temp.zz = (xx*yy - xy*yx) * dW; + temp.zw = zw; - temp.wx = (yy*(zx*wz - zz*wx) + yz*(zy*wx - zx*wy) - yx*(zy*wz - zz*wy)) * dW; - temp.wy = (xx*(zy*wz - zz*wy) + xy*(zz*wx - zx*wz) + xz*(zx*wy - zy*wx)) * dW; - temp.wz = (xy*(yx*wz - yz*wx) + xz*(yy*wx - yx*wy) - xx*(yy*wz - yz*wy)) * dW; - temp.ww = ww; + temp.wx = (yy*(zx*wz - zz*wx) + yz*(zy*wx - zx*wy) - yx*(zy*wz - zz*wy)) * dW; + temp.wy = (xx*(zy*wz - zz*wy) + xy*(zz*wx - zx*wz) + xz*(zx*wy - zy*wx)) * dW; + temp.wz = (xy*(yx*wz - yz*wx) + xz*(yy*wx - yx*wy) - xx*(yy*wz - yz*wy)) * dW; + temp.ww = ww; - return temp; + return temp; } void Matrix4x4::setViewLookAt(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 &vWorldUp) { - Vec3 vView = vFrom - vAt; // OpenGL, sigh... - vView.normalize(); - float DotProduct = vWorldUp * vView; - Vec3 vUp = vWorldUp - vView * DotProduct; - float Length = vUp.length(); + Vec3 vView = vFrom - vAt; // OpenGL, sigh... + vView.normalize(); + float DotProduct = vWorldUp * vView; + Vec3 vUp = vWorldUp - vView * DotProduct; + float Length = vUp.length(); - if (1e-6f > Length) { - // EMERGENCY - vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; - // If we still have near-zero length, resort to a different axis. - Length = vUp.length(); - if (1e-6f > Length) - { - vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z; - Length = vUp.length(); - if (1e-6f > Length) - return; - } - } - vUp.normalize(); - Vec3 vRight = vUp % vView; - empty(); + if (1e-6f > Length) { + // EMERGENCY + vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; + // If we still have near-zero length, resort to a different axis. + Length = vUp.length(); + if (1e-6f > Length) + { + vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z; + Length = vUp.length(); + if (1e-6f > Length) + return; + } + } + vUp.normalize(); + Vec3 vRight = vUp % vView; + empty(); - xx = vRight.x; xy = vUp.x; xz=vView.x; - yx = vRight.y; yy = vUp.y; yz=vView.y; - zx = vRight.z; zy = vUp.z; zz=vView.z; + xx = vRight.x; xy = vUp.x; xz=vView.x; + yx = vRight.y; yy = vUp.y; yz=vView.y; + zx = vRight.z; zy = vUp.z; zz=vView.z; - wx = -vFrom * vRight; - wy = -vFrom * vUp; - wz = -vFrom * vView; - ww = 1.0f; + wx = -vFrom * vRight; + wy = -vFrom * vUp; + wz = -vFrom * vView; + ww = 1.0f; } void Matrix4x4::setViewLookAtD3D(const Vec3 &vFrom, const Vec3 &vAt, const Vec3 &vWorldUp) { - Vec3 vView = vAt - vFrom; - vView.normalize(); - float DotProduct = vWorldUp * vView; - Vec3 vUp = vWorldUp - vView * DotProduct; - float Length = vUp.length(); + Vec3 vView = vAt - vFrom; + vView.normalize(); + float DotProduct = vWorldUp * vView; + Vec3 vUp = vWorldUp - vView * DotProduct; + float Length = vUp.length(); - if (1e-6f > Length) { - vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; - // If we still have near-zero length, resort to a different axis. - Length = vUp.length(); - if (1e-6f > Length) - { - vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z; - Length = vUp.length(); - if (1e-6f > Length) - return; - } - } - vUp.normalize(); - Vec3 vRight = vUp % vView; - empty(); + if (1e-6f > Length) { + vUp = Vec3(0.0f, 1.0f, 0.0f) - vView * vView.y; + // If we still have near-zero length, resort to a different axis. + Length = vUp.length(); + if (1e-6f > Length) + { + vUp = Vec3(0.0f, 0.0f, 1.0f) - vView * vView.z; + Length = vUp.length(); + if (1e-6f > Length) + return; + } + } + vUp.normalize(); + Vec3 vRight = vUp % vView; + empty(); - xx = vRight.x; xy = vUp.x; xz=vView.x; - yx = vRight.y; yy = vUp.y; yz=vView.y; - zx = vRight.z; zy = vUp.z; zz=vView.z; + xx = vRight.x; xy = vUp.x; xz=vView.x; + yx = vRight.y; yy = vUp.y; yz=vView.y; + zx = vRight.z; zy = vUp.z; zz=vView.z; - wx = -vFrom * vRight; - wy = -vFrom * vUp; - wz = -vFrom * vView; - ww = 1.0f; + wx = -vFrom * vRight; + wy = -vFrom * vUp; + wz = -vFrom * vView; + ww = 1.0f; } void Matrix4x4::setViewFrame(const Vec3 &pos, const Vec3 &vRight, const Vec3 &vView, const Vec3 &vUp) { - xx = vRight.x; xy = vUp.x; xz=vView.x; xw = 0.0f; - yx = vRight.y; yy = vUp.y; yz=vView.y; yw = 0.0f; - zx = vRight.z; zy = vUp.z; zz=vView.z; zw = 0.0f; + xx = vRight.x; xy = vUp.x; xz=vView.x; xw = 0.0f; + yx = vRight.y; yy = vUp.y; yz=vView.y; yw = 0.0f; + zx = vRight.z; zy = vUp.z; zz=vView.z; zw = 0.0f; - wx = -pos * vRight; - wy = -pos * vUp; - wz = -pos * vView; - ww = 1.0f; + wx = -pos * vRight; + wy = -pos * vUp; + wz = -pos * vView; + ww = 1.0f; } //YXZ euler angles void Matrix4x4::setRotation(float x,float y, float z) { - setRotationY(y); - Matrix4x4 temp; - temp.setRotationX(x); - *this *= temp; - temp.setRotationZ(z); - *this *= temp; + setRotationY(y); + Matrix4x4 temp; + temp.setRotationX(x); + *this *= temp; + temp.setRotationZ(z); + *this *= temp; } void Matrix4x4::setProjection(float near, float far, float fov_horiz, float aspect) { - // Now OpenGL style. - empty(); + // Now OpenGL style. + empty(); - float xFac = tanf(fov_horiz * 3.14f/360); - float yFac = xFac * aspect; - xx = 1.0f / xFac; - yy = 1.0f / yFac; - zz = -(far+near)/(far-near); - zw = -1.0f; - wz = -(2*far*near)/(far-near); + float xFac = tanf(fov_horiz * 3.14f/360); + float yFac = xFac * aspect; + xx = 1.0f / xFac; + yy = 1.0f / yFac; + zz = -(far+near)/(far-near); + zw = -1.0f; + wz = -(2*far*near)/(far-near); } void Matrix4x4::setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect) { - empty(); - float Q, f; + empty(); + float Q, f; - f = fov_horiz*0.5f; - Q = far_plane / (far_plane - near_plane); + f = fov_horiz*0.5f; + Q = far_plane / (far_plane - near_plane); - xx = (float)(1.0f / tanf(f));; - yy = (float)(1.0f / tanf(f*aspect)); - zz = Q; - wz = -Q * near_plane; - zw = 1.0f; + xx = (float)(1.0f / tanf(f));; + yy = (float)(1.0f / tanf(f*aspect)); + zz = Q; + wz = -Q * near_plane; + zw = 1.0f; } void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float near, float far) { - setIdentity(); - xx = 2.0f / (right - left); - yy = 2.0f / (top - bottom); - zz = 2.0f / (far - near); - wx = -(right + left) / (right - left); - wy = -(top + bottom) / (top - bottom); - wz = -(far + near) / (far - near); + setIdentity(); + xx = 2.0f / (right - left); + yy = 2.0f / (top - bottom); + zz = 2.0f / (far - near); + wx = -(right + left) / (right - left); + wy = -(top + bottom) / (top - bottom); + wz = -(far + near) / (far - near); } // This is a D3D style matrix. void Matrix4x4::setProjectionInf(const float near_plane, const float fov_horiz, const float aspect) { - empty(); - float f = fov_horiz*0.5f; - xx = 1.0f / tanf(f); - yy = 1.0f / tanf(f*aspect); - zz = 1; - wz = -near_plane; - zw = 1.0f; + empty(); + float f = fov_horiz*0.5f; + xx = 1.0f / tanf(f); + yy = 1.0f / tanf(f*aspect); + zz = 1; + wz = -near_plane; + zw = 1.0f; } void Matrix4x4::setRotationAxisAngle(const Vec3 &axis, float angle) { - Quaternion quat; - quat.setRotation(axis, angle); - quat.toMatrix(this); + Quaternion quat; + quat.setRotation(axis, angle); + quat.toMatrix(this); } // from a (Position, Rotation, Scale) vec3 quat vec3 tuple Matrix4x4 Matrix4x4::fromPRS(const Vec3 &positionv, const Quaternion &rotv, const Vec3 &scalev) { - Matrix4x4 newM; - newM.setIdentity(); - Matrix4x4 rot, scale; - rotv.toMatrix(&rot); - scale.setScaling(scalev); - newM = rot * scale; - newM.wx = positionv.x; - newM.wy = positionv.y; - newM.wz = positionv.z; - return newM; + Matrix4x4 newM; + newM.setIdentity(); + Matrix4x4 rot, scale; + rotv.toMatrix(&rot); + scale.setScaling(scalev); + newM = rot * scale; + newM.wx = positionv.x; + newM.wy = positionv.y; + newM.wz = positionv.z; + return newM; } #if _MSC_VER #define snprintf _snprintf #endif void Matrix4x4::toText(char *buffer, int len) const { - snprintf(buffer, len, "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", - xx,xy,xz,xw, - yx,yy,yz,yw, - zx,zy,zz,zw, - wx,wy,wz,ww); - buffer[len - 1] = '\0'; + snprintf(buffer, len, "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", + xx,xy,xz,xw, + yx,yy,yz,yw, + zx,zy,zz,zw, + wx,wy,wz,ww); + buffer[len - 1] = '\0'; } void Matrix4x4::print() const { - char buffer[256]; - toText(buffer, 256); - puts(buffer); + char buffer[256]; + toText(buffer, 256); + puts(buffer); } diff --git a/math/lin/matrix4x4.h b/math/lin/matrix4x4.h index 8e058ce09f..32c69db1ca 100644 --- a/math/lin/matrix4x4.h +++ b/math/lin/matrix4x4.h @@ -7,135 +7,135 @@ class Quaternion; class Matrix4x4 { public: - float xx, xy, xz, xw; - float yx, yy, yz, yw; - float zx, zy, zz, zw; - float wx, wy, wz, ww; + float xx, xy, xz, xw; + float yx, yy, yz, yw; + float zx, zy, zz, zw; + float wx, wy, wz, ww; - const Vec3 right() const {return Vec3(xx, xy, xz);} - const Vec3 up() const {return Vec3(yx, yy, yz);} - const Vec3 front() const {return Vec3(zx, zy, zz);} - const Vec3 move() const {return Vec3(wx, wy, wz);} + const Vec3 right() const {return Vec3(xx, xy, xz);} + const Vec3 up() const {return Vec3(yx, yy, yz);} + const Vec3 front() const {return Vec3(zx, zy, zz);} + const Vec3 move() const {return Vec3(wx, wy, wz);} - void setRight(const Vec3 &v) { - xx = v.x; xy = v.y; xz = v.z; - } - void setUp(const Vec3 &v) { - yx = v.x; yy = v.y; yz = v.z; - } - void setFront(const Vec3 &v) { - zx = v.x; zy = v.y; zz = v.z; - } - void setMove(const Vec3 &v) { - wx = v.x; wy = v.y; wz = v.z; - } + void setRight(const Vec3 &v) { + xx = v.x; xy = v.y; xz = v.z; + } + void setUp(const Vec3 &v) { + yx = v.x; yy = v.y; yz = v.z; + } + void setFront(const Vec3 &v) { + zx = v.x; zy = v.y; zz = v.z; + } + void setMove(const Vec3 &v) { + wx = v.x; wy = v.y; wz = v.z; + } - const float &operator[](int i) const { - return *(((const float *)this) + i); - } - float &operator[](int i) { - return *(((float *)this) + i); - } - Matrix4x4 operator * (const Matrix4x4 &other) const ; - void operator *= (const Matrix4x4 &other) { - *this = *this * other; - } - const float *getReadPtr() const { - return (const float *)this; - } - void empty() { - memset(this, 0, 16 * sizeof(float)); - } - void setScaling(const float f) { - empty(); - xx=yy=zz=f; ww=1.0f; - } - void setScaling(const Vec3 f) { - empty(); - xx=f.x; - yy=f.y; - zz=f.z; - ww=1.0f; - } + const float &operator[](int i) const { + return *(((const float *)this) + i); + } + float &operator[](int i) { + return *(((float *)this) + i); + } + Matrix4x4 operator * (const Matrix4x4 &other) const ; + void operator *= (const Matrix4x4 &other) { + *this = *this * other; + } + const float *getReadPtr() const { + return (const float *)this; + } + void empty() { + memset(this, 0, 16 * sizeof(float)); + } + void setScaling(const float f) { + empty(); + xx=yy=zz=f; ww=1.0f; + } + void setScaling(const Vec3 f) { + empty(); + xx=f.x; + yy=f.y; + zz=f.z; + ww=1.0f; + } - void setIdentity() { - setScaling(1.0f); - } - void setTranslation(const Vec3 &trans) { - setIdentity(); - wx = trans.x; - wy = trans.y; - wz = trans.z; - } - Matrix4x4 inverse() const; - Matrix4x4 simpleInverse() const; - Matrix4x4 transpose() const; + void setIdentity() { + setScaling(1.0f); + } + void setTranslation(const Vec3 &trans) { + setIdentity(); + wx = trans.x; + wy = trans.y; + wz = trans.z; + } + Matrix4x4 inverse() const; + Matrix4x4 simpleInverse() const; + Matrix4x4 transpose() const; - void setRotationX(const float a) { - empty(); - float c=cosf(a); - float s=sinf(a); - xx = 1.0f; - yy = c; yz = s; - zy = -s; zz = c; - ww = 1.0f; - } - void setRotationY(const float a) { - empty(); - float c=cosf(a); - float s=sinf(a); - xx = c; xz = -s; - yy = 1.0f; - zx = s; zz = c ; - ww = 1.0f; - } - void setRotationZ(const float a) { - empty(); - float c=cosf(a); - float s=sinf(a); - xx = c; xy = s; - yx = -s; yy = c; - zz = 1.0f; - ww = 1.0f; - } - void setRotationAxisAngle(const Vec3 &axis, float angle); + void setRotationX(const float a) { + empty(); + float c=cosf(a); + float s=sinf(a); + xx = 1.0f; + yy = c; yz = s; + zy = -s; zz = c; + ww = 1.0f; + } + void setRotationY(const float a) { + empty(); + float c=cosf(a); + float s=sinf(a); + xx = c; xz = -s; + yy = 1.0f; + zx = s; zz = c ; + ww = 1.0f; + } + void setRotationZ(const float a) { + empty(); + float c=cosf(a); + float s=sinf(a); + xx = c; xy = s; + yx = -s; yy = c; + zz = 1.0f; + ww = 1.0f; + } + void setRotationAxisAngle(const Vec3 &axis, float angle); - void setRotation(float x,float y, float z); - void setProjection(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); - void setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); - void setProjectionInf(float near_plane, float fov_horiz, float aspect = 0.75f); - void setOrtho(float left, float right, float bottom, float top, float near, float far); - void setShadow(float Lx, float Ly, float Lz, float Lw) { - float Pa=0; - float Pb=1; - float Pc=0; - float Pd=0; - //P = normalize(Plane); - float d = (Pa*Lx + Pb*Ly + Pc*Lz + Pd*Lw); + void setRotation(float x,float y, float z); + void setProjection(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); + void setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); + void setProjectionInf(float near_plane, float fov_horiz, float aspect = 0.75f); + void setOrtho(float left, float right, float bottom, float top, float near, float far); + void setShadow(float Lx, float Ly, float Lz, float Lw) { + float Pa=0; + float Pb=1; + float Pc=0; + float Pd=0; + //P = normalize(Plane); + float d = (Pa*Lx + Pb*Ly + Pc*Lz + Pd*Lw); - xx=Pa * Lx + d; xy=Pa * Ly; xz=Pa * Lz; xw=Pa * Lw; - yx=Pb * Lx; yy=Pb * Ly + d; yz=Pb * Lz; yw=Pb * Lw; - zx=Pc * Lx; zy=Pc * Ly; zz=Pc * Lz + d; zw=Pc * Lw; - wx=Pd * Lx; wy=Pd * Ly; wz=Pd * Lz; ww=Pd * Lw + d; - } + xx=Pa * Lx + d; xy=Pa * Ly; xz=Pa * Lz; xw=Pa * Lw; + yx=Pb * Lx; yy=Pb * Ly + d; yz=Pb * Lz; yw=Pb * Lw; + zx=Pc * Lx; zy=Pc * Ly; zz=Pc * Lz + d; zw=Pc * Lw; + wx=Pd * Lx; wy=Pd * Ly; wz=Pd * Lz; ww=Pd * Lw + d; + } - void setViewLookAt(const Vec3 &from, const Vec3 &at, const Vec3 &worldup); - void setViewLookAtD3D(const Vec3 &from, const Vec3 &at, const Vec3 &worldup); - void setViewFrame(const Vec3 &pos, const Vec3 &right, const Vec3 &forward, const Vec3 &up); - void stabilizeOrtho() { - /* - front().normalize(); - right().normalize(); - up() = front() % right(); - right() = up() % front(); - */ - } - void toText(char *buffer, int len) const; - void print() const; - static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale); + void setViewLookAt(const Vec3 &from, const Vec3 &at, const Vec3 &worldup); + void setViewLookAtD3D(const Vec3 &from, const Vec3 &at, const Vec3 &worldup); + void setViewFrame(const Vec3 &pos, const Vec3 &right, const Vec3 &forward, const Vec3 &up); + void stabilizeOrtho() { + /* + front().normalize(); + right().normalize(); + up() = front() % right(); + right() = up() % front(); + */ + } + void toText(char *buffer, int len) const; + void print() const; + static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale); }; -#endif // _MATH_LIN_MATRIX4X4_H +#endif // _MATH_LIN_MATRIX4X4_H diff --git a/math/lin/plane.cpp b/math/lin/plane.cpp index 67e8ef631a..2b14c3420d 100644 --- a/math/lin/plane.cpp +++ b/math/lin/plane.cpp @@ -3,8 +3,8 @@ void Plane::TransformByIT(const Matrix4x4 &m, Plane *out) { - out->x = x * m.xx + y * m.yx + z * m.zx + d * m.wx; - out->y = x * m.xy + y * m.yy + z * m.zy + d * m.wy; - out->z = x * m.xz + y * m.yz + z * m.zz + d * m.wz; - out->d = x * m.xw + y * m.yw + z * m.zw + d * m.ww; + out->x = x * m.xx + y * m.yx + z * m.zx + d * m.wx; + out->y = x * m.xy + y * m.yy + z * m.zy + d * m.wy; + out->z = x * m.xz + y * m.yz + z * m.zz + d * m.wz; + out->d = x * m.xw + y * m.yw + z * m.zw + d * m.ww; } diff --git a/math/lin/plane.h b/math/lin/plane.h index 6466617c1b..f369ef1259 100644 --- a/math/lin/plane.h +++ b/math/lin/plane.h @@ -6,32 +6,32 @@ class Matrix4x4; class Plane { - public: - float x, y, z, d; - Plane() {} - Plane(float x_, float y_, float z_, float d_) - : x(x_), y(y_), z(z_), d(d_) { } - ~Plane() {} +public: + float x, y, z, d; + Plane() {} + Plane(float x_, float y_, float z_, float d_) + : x(x_), y(y_), z(z_), d(d_) { } + ~Plane() {} - float Distance(const Vec3 &v) const { - return x * v.x + y * v.y + z * v.z + d; - } + float Distance(const Vec3 &v) const { + return x * v.x + y * v.y + z * v.z + d; + } - float Distance(float px, float py, float pz) const { - return x * px + y * py + z * pz + d; - } + float Distance(float px, float py, float pz) const { + return x * px + y * py + z * pz + d; + } - void Normalize() { - float inv_length = sqrtf(x * x + y * y + z * z); - x *= inv_length; - y *= inv_length; - z *= inv_length; - d *= inv_length; - } + void Normalize() { + float inv_length = sqrtf(x * x + y * y + z * z); + x *= inv_length; + y *= inv_length; + z *= inv_length; + d *= inv_length; + } - // Matrix is the inverse transpose of the wanted transform. - // out cannot be equal to this. - void TransformByIT(const Matrix4x4 &matrix, Plane *out); + // Matrix is the inverse transpose of the wanted transform. + // out cannot be equal to this. + void TransformByIT(const Matrix4x4 &matrix, Plane *out); }; #endif diff --git a/math/lin/quat.cpp b/math/lin/quat.cpp index 3c1900ebcc..87ce1a94c3 100644 --- a/math/lin/quat.cpp +++ b/math/lin/quat.cpp @@ -2,124 +2,124 @@ #include "math/lin/matrix4x4.h" void Quaternion::toMatrix(Matrix4x4 *out) const { - Matrix4x4 temp; - temp.setIdentity(); - float ww, xx, yy, zz, wx, wy, wz, xy, xz, yz; - ww = w*w; xx = x*x; yy = y*y; zz = z*z; - wx = w*x*2; wy = w*y*2; wz = w*z*2; - xy = x*y*2; xz = x*z*2; yz = y*z*2; + Matrix4x4 temp; + temp.setIdentity(); + float ww, xx, yy, zz, wx, wy, wz, xy, xz, yz; + ww = w*w; xx = x*x; yy = y*y; zz = z*z; + wx = w*x*2; wy = w*y*2; wz = w*z*2; + xy = x*y*2; xz = x*z*2; yz = y*z*2; - temp.xx = ww + xx - yy - zz; - temp.xy = xy + wz; - temp.xz = xz - wy; + temp.xx = ww + xx - yy - zz; + temp.xy = xy + wz; + temp.xz = xz - wy; - temp.yx = xy - wz; - temp.yy = ww - xx + yy - zz; - temp.yz = yz + wx; + temp.yx = xy - wz; + temp.yy = ww - xx + yy - zz; + temp.yz = yz + wx; - temp.zx = xz + wy; - temp.zy = yz - wx; - temp.zz = ww - xx - yy + zz; + temp.zx = xz + wy; + temp.zy = yz - wx; + temp.zz = ww - xx - yy + zz; - *out = temp; + *out = temp; } Quaternion Quaternion::fromMatrix(Matrix4x4 &m) { - // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes - // article "Quaternion Calculus and Fast Animation". - Quaternion q(0,0,0,1); - /* - float fTrace = m[0][0] + m[1][1] + m[2][2]; - float fRoot; + // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes + // article "Quaternion Calculus and Fast Animation". + Quaternion q(0,0,0,1); + /* + float fTrace = m[0][0] + m[1][1] + m[2][2]; + float fRoot; - if( fTrace > 0.0 ) - { - fRoot = sqrtf( fTrace + 1.0f ); + if( fTrace > 0.0 ) + { + fRoot = sqrtf( fTrace + 1.0f ); - q.w = 0.5f * fRoot; + q.w = 0.5f * fRoot; - fRoot = 0.5f / fRoot; + fRoot = 0.5f / fRoot; - q.x = ( m[2][1] - m[1][2] ) * fRoot; - q.y = ( m[0][2] - m[2][0] ) * fRoot; - q.z = ( m[1][0] - m[0][1] ) * fRoot; - } - else - { - int iNext[3] = { 1, 2, 0 }; + q.x = ( m[2][1] - m[1][2] ) * fRoot; + q.y = ( m[0][2] - m[2][0] ) * fRoot; + q.z = ( m[1][0] - m[0][1] ) * fRoot; + } + else + { + int iNext[3] = { 1, 2, 0 }; - int i = 0; - if( m[1][1] > m[0][0] ) - i = 1; + int i = 0; + if( m[1][1] > m[0][0] ) + i = 1; - if( m[2][2] > m[i][i] ) - i = 2; + if( m[2][2] > m[i][i] ) + i = 2; - int j = iNext[i]; - int k = iNext[j]; + int j = iNext[i]; + int k = iNext[j]; - fRoot = sqrtf( m[i][i] - m[j][j] - m[k][k] + 1.0f ); + fRoot = sqrtf( m[i][i] - m[j][j] - m[k][k] + 1.0f ); - float *apfQuat = &q.x; + float *apfQuat = &q.x; - apfQuat[i] = 0.5f * fRoot; + apfQuat[i] = 0.5f * fRoot; - fRoot = 0.5f / fRoot; + fRoot = 0.5f / fRoot; - q.w = ( m[k][j] - m[j][k] ) * fRoot; + q.w = ( m[k][j] - m[j][k] ) * fRoot; - apfQuat[j] = ( m[j][i] + m[i][j] ) * fRoot; - apfQuat[k] = ( m[k][i] + m[i][k] ) * fRoot; - } - q.normalize(); */ - return q; + apfQuat[j] = ( m[j][i] + m[i][j] ) * fRoot; + apfQuat[k] = ( m[k][i] + m[i][k] ) * fRoot; + } + q.normalize(); */ + return q; }; // TODO: Allegedly, lerp + normalize can achieve almost as good results. Quaternion Quaternion::slerp(const Quaternion &to, const float a) const { - Quaternion to2; - float angle, cos_angle, scale_from, scale_to, sin_angle; + Quaternion to2; + float angle, cos_angle, scale_from, scale_to, sin_angle; - cos_angle = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); //4D dot product + cos_angle = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); //4D dot product - if (cos_angle < 0.0f) - { - cos_angle = -cos_angle; - to2.w = -to.w; to2.x = -to.x; to2.y = -to.y; to2.z = -to.z; - } - else - { - to2 = to; - } + if (cos_angle < 0.0f) + { + cos_angle = -cos_angle; + to2.w = -to.w; to2.x = -to.x; to2.y = -to.y; to2.z = -to.z; + } + else + { + to2 = to; + } - if ((1.0f - fabsf(cos_angle)) > 0.00001f) - { - /* spherical linear interpolation (SLERP) */ - angle = acosf(cos_angle); - sin_angle = sinf(angle); - scale_from = sinf((1.0f - a) * angle) / sin_angle; - scale_to = sinf(a * angle) / sin_angle; - } - else - { - /* to prevent divide-by-zero, resort to linear interpolation */ - // This is okay in 99% of cases anyway, maybe should be the default? - scale_from = 1.0f - a; - scale_to = a; - } + if ((1.0f - fabsf(cos_angle)) > 0.00001f) + { + /* spherical linear interpolation (SLERP) */ + angle = acosf(cos_angle); + sin_angle = sinf(angle); + scale_from = sinf((1.0f - a) * angle) / sin_angle; + scale_to = sinf(a * angle) / sin_angle; + } + else + { + /* to prevent divide-by-zero, resort to linear interpolation */ + // This is okay in 99% of cases anyway, maybe should be the default? + scale_from = 1.0f - a; + scale_to = a; + } - return Quaternion( - scale_from*x + scale_to*to2.x, - scale_from*y + scale_to*to2.y, - scale_from*z + scale_to*to2.z, - scale_from*w + scale_to*to2.w - ); + return Quaternion( + scale_from*x + scale_to*to2.x, + scale_from*y + scale_to*to2.y, + scale_from*z + scale_to*to2.z, + scale_from*w + scale_to*to2.w + ); } Quaternion Quaternion::multiply(const Quaternion &q) const { - return Quaternion((w * q.x) + (x * q.w) + (y * q.z) - (z * q.y), - (w * q.y) + (y * q.w) + (z * q.x) - (x * q.z), - (w * q.z) + (z * q.w) + (x * q.y) - (y * q.x), - (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z)); + return Quaternion((w * q.x) + (x * q.w) + (y * q.z) - (z * q.y), + (w * q.y) + (y * q.w) + (z * q.x) - (x * q.z), + (w * q.z) + (z * q.w) + (x * q.y) - (y * q.x), + (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z)); } diff --git a/math/lin/quat.h b/math/lin/quat.h index 4352e95bc8..89746e5aab 100644 --- a/math/lin/quat.h +++ b/math/lin/quat.h @@ -8,85 +8,85 @@ class Matrix4x4; class Quaternion { public: - float x,y,z,w; + float x,y,z,w; - Quaternion() { } - Quaternion(const float _x, const float _y, const float _z, const float _w) { - x=_x; y=_y; z=_z; w=_w; - } - void setIdentity() - { - x=y=z=0; w=1.0f; - } - void setXRotation(const float r) { w = cosf(r / 2); x = sinf(r / 2); y = z = 0; } - void setYRotation(const float r) { w = cosf(r / 2); y = sinf(r / 2); x = z = 0; } - void setZRotation(const float r) { w = cosf(r / 2); z = sinf(r / 2); x = y = 0; } - void toMatrix(Matrix4x4 *out) const; - static Quaternion fromMatrix(Matrix4x4 &m); + Quaternion() { } + Quaternion(const float _x, const float _y, const float _z, const float _w) { + x=_x; y=_y; z=_z; w=_w; + } + void setIdentity() + { + x=y=z=0; w=1.0f; + } + void setXRotation(const float r) { w = cosf(r / 2); x = sinf(r / 2); y = z = 0; } + void setYRotation(const float r) { w = cosf(r / 2); y = sinf(r / 2); x = z = 0; } + void setZRotation(const float r) { w = cosf(r / 2); z = sinf(r / 2); x = y = 0; } + void toMatrix(Matrix4x4 *out) const; + static Quaternion fromMatrix(Matrix4x4 &m); - Quaternion operator *(Quaternion &q) const - { - return Quaternion( - (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z), - (w * q.x) + (x * q.w) + (y * q.z) - (z * q.y), - (w * q.y) + (y * q.w) + (z * q.x) - (x * q.z), - (w * q.z) + (z * q.w) + (x * q.y) - (y * q.x) - ); - } - Quaternion operator -() - { - return Quaternion(-x,-y,-z,-w); - } - void setRotation(Vec3 axis, float angle) - { - axis /= axis.length(); - angle *= .5f; - float sine = sinf(angle); - w = cosf(angle); - x = sine * axis.x; - y = sine * axis.y; - z = sine * axis.z; - } - void toAxisAngle(Vec3 &v, float &angle) - { - normalize(); - if (w==1.0f && x==0.0f && y==0.0f && z==0.0f) - { - v = Vec3(0,1,0); - angle = 0.0f; - return; - } - float cos_a = w; - angle = acosf(cos_a) * 2; - float sin_a = sqrtf( 1.0f - cos_a * cos_a ); - if (fabsf(sin_a) < 0.00005f) sin_a = 1; - float inv_sin_a=1.0f/sin_a; - v.x = x * inv_sin_a; - v.y = y * inv_sin_a; - v.z = z * inv_sin_a; - } - enum { - QUAT_SHORT, - QUAT_LONG, - QUAT_CW, - QUAT_CCW - }; - Quaternion slerp(const Quaternion &to, const float a) const; - Quaternion multiply(const Quaternion &q) const; - float &operator [] (int i) { - return *((&x) + i); - } - const float operator [] (int i) const { - return *((&x) + i); - } - //not sure about this, maybe mag is supposed to sqrt - float magnitude() const { - return x*x + y*y + z*z + w*w; - } - void normalize() { - float f = 1.0f/sqrtf(magnitude()); - x*=f; y*=f; z*=f; w*=f; - } + Quaternion operator *(Quaternion &q) const + { + return Quaternion( + (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z), + (w * q.x) + (x * q.w) + (y * q.z) - (z * q.y), + (w * q.y) + (y * q.w) + (z * q.x) - (x * q.z), + (w * q.z) + (z * q.w) + (x * q.y) - (y * q.x) + ); + } + Quaternion operator -() + { + return Quaternion(-x,-y,-z,-w); + } + void setRotation(Vec3 axis, float angle) + { + axis /= axis.length(); + angle *= .5f; + float sine = sinf(angle); + w = cosf(angle); + x = sine * axis.x; + y = sine * axis.y; + z = sine * axis.z; + } + void toAxisAngle(Vec3 &v, float &angle) + { + normalize(); + if (w==1.0f && x==0.0f && y==0.0f && z==0.0f) + { + v = Vec3(0,1,0); + angle = 0.0f; + return; + } + float cos_a = w; + angle = acosf(cos_a) * 2; + float sin_a = sqrtf( 1.0f - cos_a * cos_a ); + if (fabsf(sin_a) < 0.00005f) sin_a = 1; + float inv_sin_a=1.0f/sin_a; + v.x = x * inv_sin_a; + v.y = y * inv_sin_a; + v.z = z * inv_sin_a; + } + enum { + QUAT_SHORT, + QUAT_LONG, + QUAT_CW, + QUAT_CCW + }; + Quaternion slerp(const Quaternion &to, const float a) const; + Quaternion multiply(const Quaternion &q) const; + float &operator [] (int i) { + return *((&x) + i); + } + const float operator [] (int i) const { + return *((&x) + i); + } + //not sure about this, maybe mag is supposed to sqrt + float magnitude() const { + return x*x + y*y + z*z + w*w; + } + void normalize() { + float f = 1.0f/sqrtf(magnitude()); + x*=f; y*=f; z*=f; w*=f; + } }; -#endif // _MATH_LIN_QUAT_H +#endif // _MATH_LIN_QUAT_H diff --git a/math/lin/vec3.cpp b/math/lin/vec3.cpp index 4b817ad98b..aaebfc7d02 100644 --- a/math/lin/vec3.cpp +++ b/math/lin/vec3.cpp @@ -4,25 +4,25 @@ #include "math/lin/matrix4x4.h" Vec3 Vec3::operator *(const Matrix4x4 &m) const { - return Vec3(x*m.xx + y*m.yx + z*m.zx + m.wx, - x*m.xy + y*m.yy + z*m.zy + m.wy, - x*m.xz + y*m.yz + z*m.zz + m.wz); + return Vec3(x*m.xx + y*m.yx + z*m.zx + m.wx, + x*m.xy + y*m.yy + z*m.zy + m.wy, + x*m.xz + y*m.yz + z*m.zz + m.wz); } Vec4 Vec3::multiply4D(const Matrix4x4 &m) const { - return Vec4(x*m.xx + y*m.yx + z*m.zx + m.wx, - x*m.xy + y*m.yy + z*m.zy + m.wy, - x*m.xz + y*m.yz + z*m.zz + m.wz, - x*m.xw + y*m.yw + z*m.zw + m.ww); + return Vec4(x*m.xx + y*m.yx + z*m.zx + m.wx, + x*m.xy + y*m.yy + z*m.zy + m.wy, + x*m.xz + y*m.yz + z*m.zz + m.wz, + x*m.xw + y*m.yw + z*m.zw + m.ww); } Vec4 Vec4::multiply4D(Matrix4x4 &m) const { - return Vec4(x*m.xx + y*m.yx + z*m.zx + w*m.wx, - x*m.xy + y*m.yy + z*m.zy + w*m.wy, - x*m.xz + y*m.yz + z*m.zz + w*m.wz, - x*m.xw + y*m.yw + z*m.zw + w*m.ww); + return Vec4(x*m.xx + y*m.yx + z*m.zx + w*m.wx, + x*m.xy + y*m.yy + z*m.zy + w*m.wy, + x*m.xz + y*m.yz + z*m.zz + w*m.wz, + x*m.xw + y*m.yw + z*m.zw + w*m.ww); } Vec3 Vec3::rotatedBy(const Matrix4x4 &m) const { - return Vec3(x*m.xx + y*m.yx + z*m.zx, - x*m.xy + y*m.yy + z*m.zy, - x*m.xz + y*m.yz + z*m.zz); + return Vec3(x*m.xx + y*m.yx + z*m.zx, + x*m.xy + y*m.yy + z*m.zy, + x*m.xz + y*m.yz + z*m.zz); } diff --git a/math/lin/vec3.h b/math/lin/vec3.h index e10fc0d3a9..cfc7d2eb89 100644 --- a/math/lin/vec3.h +++ b/math/lin/vec3.h @@ -2,122 +2,122 @@ #define _MATH_LIN_VEC3 #include -#include // memset +#include // memset class Matrix4x4; // Hm, doesn't belong in this file. class Vec4 { public: - float x,y,z,w; - Vec4(){} - Vec4(float a, float b, float c, float d) {x=a;y=b;z=c;w=d;} - Vec4 multiply4D(Matrix4x4 &m) const; + float x,y,z,w; + Vec4(){} + Vec4(float a, float b, float c, float d) {x=a;y=b;z=c;w=d;} + Vec4 multiply4D(Matrix4x4 &m) const; }; class Vec3 { public: - float x,y,z; + float x,y,z; - Vec3() { } - explicit Vec3(float f) {x=y=z=f;} + Vec3() { } + explicit Vec3(float f) {x=y=z=f;} - float operator [] (int i) const { return (&x)[i]; } - float &operator [] (int i) { return (&x)[i]; } + float operator [] (int i) const { return (&x)[i]; } + float &operator [] (int i) { return (&x)[i]; } - Vec3(const float _x, const float _y, const float _z) { - x=_x; y=_y; z=_z; - } - void Set(float _x, float _y, float _z) { - x=_x; y=_y; z=_z; - } - Vec3 operator + (const Vec3 &other) const { - return Vec3(x+other.x, y+other.y, z+other.z); - } - void operator += (const Vec3 &other) { - x+=other.x; y+=other.y; z+=other.z; - } - Vec3 operator -(const Vec3 &v) const { - return Vec3(x-v.x,y-v.y,z-v.z); - } - void operator -= (const Vec3 &other) - { - x-=other.x; y-=other.y; z-=other.z; - } - Vec3 operator -() const { - return Vec3(-x,-y,-z); - } + Vec3(const float _x, const float _y, const float _z) { + x=_x; y=_y; z=_z; + } + void Set(float _x, float _y, float _z) { + x=_x; y=_y; z=_z; + } + Vec3 operator + (const Vec3 &other) const { + return Vec3(x+other.x, y+other.y, z+other.z); + } + void operator += (const Vec3 &other) { + x+=other.x; y+=other.y; z+=other.z; + } + Vec3 operator -(const Vec3 &v) const { + return Vec3(x-v.x,y-v.y,z-v.z); + } + void operator -= (const Vec3 &other) + { + x-=other.x; y-=other.y; z-=other.z; + } + Vec3 operator -() const { + return Vec3(-x,-y,-z); + } - Vec3 operator * (const float f) const { - return Vec3(x*f,y*f,z*f); - } - Vec3 operator / (const float f) const { - float invf = (1.0f/f); - return Vec3(x*invf,y*invf,z*invf); - } - void operator /= (const float f) - { - *this = *this / f; - } - float operator * (const Vec3 &other) const { - return x*other.x + y*other.y + z*other.z; - } - void operator *= (const float f) { - *this = *this * f; - } - void scaleBy(const Vec3 &other) { - x *= other.x; y *= other.y; z *= other.z; - } - Vec3 scaledBy(const Vec3 &other) const { - return Vec3(x*other.x, y*other.y, z*other.z); - } - Vec3 scaledByInv(const Vec3 &other) const { - return Vec3(x/other.x, y/other.y, z/other.z); - } - Vec3 operator *(const Matrix4x4 &m) const; - void operator *=(const Matrix4x4 &m) { - *this = *this * m; - } - Vec4 multiply4D(const Matrix4x4 &m) const; - Vec3 rotatedBy(const Matrix4x4 &m) const; - Vec3 operator %(const Vec3 &v) const { - return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); - } - float length2() const { - return x*x + y*y + z*z; - } - float length() const { - return sqrtf(length2()); - } - void setLength(const float l) { - (*this) *= l/length(); - } - Vec3 withLength(const float l) const { - return (*this) * l / length(); - } - float distance2To(const Vec3 &other) const { - return Vec3(other-(*this)).length2(); - } - Vec3 normalized() const { - return (*this) / length(); - } - float normalize() { //returns the previous length, is often useful - float len = length(); - (*this) = (*this)/len; - return len; - } - bool operator == (const Vec3 &other) const { - if (x==other.x && y==other.y && z==other.z) - return true; - else - return false; - } - Vec3 lerp(const Vec3 &other, const float t) const { - return (*this)*(1-t) + other*t; - } - void setZero() { - memset((void *)this,0,sizeof(float)*3); - } + Vec3 operator * (const float f) const { + return Vec3(x*f,y*f,z*f); + } + Vec3 operator / (const float f) const { + float invf = (1.0f/f); + return Vec3(x*invf,y*invf,z*invf); + } + void operator /= (const float f) + { + *this = *this / f; + } + float operator * (const Vec3 &other) const { + return x*other.x + y*other.y + z*other.z; + } + void operator *= (const float f) { + *this = *this * f; + } + void scaleBy(const Vec3 &other) { + x *= other.x; y *= other.y; z *= other.z; + } + Vec3 scaledBy(const Vec3 &other) const { + return Vec3(x*other.x, y*other.y, z*other.z); + } + Vec3 scaledByInv(const Vec3 &other) const { + return Vec3(x/other.x, y/other.y, z/other.z); + } + Vec3 operator *(const Matrix4x4 &m) const; + void operator *=(const Matrix4x4 &m) { + *this = *this * m; + } + Vec4 multiply4D(const Matrix4x4 &m) const; + Vec3 rotatedBy(const Matrix4x4 &m) const; + Vec3 operator %(const Vec3 &v) const { + return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); + } + float length2() const { + return x*x + y*y + z*z; + } + float length() const { + return sqrtf(length2()); + } + void setLength(const float l) { + (*this) *= l/length(); + } + Vec3 withLength(const float l) const { + return (*this) * l / length(); + } + float distance2To(const Vec3 &other) const { + return Vec3(other-(*this)).length2(); + } + Vec3 normalized() const { + return (*this) / length(); + } + float normalize() { //returns the previous length, is often useful + float len = length(); + (*this) = (*this)/len; + return len; + } + bool operator == (const Vec3 &other) const { + if (x==other.x && y==other.y && z==other.z) + return true; + else + return false; + } + Vec3 lerp(const Vec3 &other, const float t) const { + return (*this)*(1-t) + other*t; + } + void setZero() { + memset((void *)this,0,sizeof(float)*3); + } }; inline Vec3 operator * (const float f, const Vec3 &v) {return v * f;} @@ -125,21 +125,21 @@ inline Vec3 operator * (const float f, const Vec3 &v) {return v * f;} // In new code, prefer these to the operators. inline float dot(const Vec3 &a, const Vec3 &b) { - return a.x * b.x + a.y * b.y + a.z * b.z; + return a.x * b.x + a.y * b.y + a.z * b.z; } inline Vec3 cross(const Vec3 &a, const Vec3 &b) { - return a % b; + return a % b; } inline float sqr(const Vec3 &v) { - return dot(v, v); + return dot(v, v); } class AABBox { public: - Vec3 min; - Vec3 max; + Vec3 min; + Vec3 max; }; -#endif // _MATH_LIN_VEC3 +#endif // _MATH_LIN_VEC3 diff --git a/math/math_util.cpp b/math/math_util.cpp index 29fe6a902e..2eebdf6036 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -3,7 +3,7 @@ #include /* -static unsigned int randSeed = 22222; // Change this for different random sequences. +static unsigned int randSeed = 22222; // Change this for different random sequences. void SetSeed(unsigned int seed) { randSeed = seed * 382792592; @@ -21,22 +21,22 @@ unsigned int GenerateRandomNumber() { void EnableFZ() { - int x; - asm( - "fmrx %[result],FPSCR \r\n" - "orr %[result],%[result],#16777216 \r\n" - "fmxr FPSCR,%[result]" - :[result] "=r" (x) : : - ); - //printf("ARM FPSCR: %08x\n",x); + int x; + asm( + "fmrx %[result],FPSCR \r\n" + "orr %[result],%[result],#16777216 \r\n" + "fmxr FPSCR,%[result]" + :[result] "=r" (x) : : + ); + //printf("ARM FPSCR: %08x\n",x); } void DisableFZ( ) { - __asm__ volatile( - "fmrx r0, fpscr\n" - "bic r0, $(1 << 24)\n" - "fmxr fpscr, r0" : : : "r0"); + __asm__ volatile( + "fmrx r0, fpscr\n" + "bic r0, $(1 << 24)\n" + "fmxr fpscr, r0" : : : "r0"); } #else @@ -50,4 +50,4 @@ void DisableFZ() } -#endif \ No newline at end of file +#endif diff --git a/math/math_util.h b/math/math_util.h index 71edd44a0b..d5c7e0a14c 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -4,7 +4,7 @@ #include #include -inline float sqr(float f) {return f*f;} +inline float sqr(float f) {return f*f;} inline float sqr_signed(float f) {return f<0 ? -f*f : f*f;} typedef unsigned short float16; @@ -13,15 +13,15 @@ typedef unsigned short float16; // This choice is subject to change. Don't think I'm using this for anything at all now anyway. // DEPRECATED inline float16 FloatToFloat16(float x) { - int ix; - memcpy(&ix, &x, sizeof(float)); - return ix >> 16; + int ix; + memcpy(&ix, &x, sizeof(float)); + return ix >> 16; } inline float Float16ToFloat(float16 ix) { - float x; - memcpy(&x, &ix, sizeof(float)); - return x; + float x; + memcpy(&x, &ix, sizeof(float)); + return x; } @@ -37,40 +37,40 @@ inline float Float16ToFloat(float16 ix) { void SetSeed(unsigned int seed); unsigned int GenerateRandomNumber(); inline float GenerateRandomFloat01() { - return (float)((double)GenerateRandomNumber() / 0xFFFFFFFF); + return (float)((double)GenerateRandomNumber() / 0xFFFFFFFF); } inline float GenerateRandomSignedFloat() { - return (float)((double)GenerateRandomNumber() / 0x80000000) - 1.0f; + return (float)((double)GenerateRandomNumber() / 0x80000000) - 1.0f; } inline float GaussRand() { - float R1 = GenerateRandomFloat01(); - float R2 = GenerateRandomFloat01(); + float R1 = GenerateRandomFloat01(); + float R2 = GenerateRandomFloat01(); - float X = sqrtf(-2.0f * logf(R1)) * cosf(2.0f * PI * R2); - if (X > 4.0f) X = 4.0f; - if (X < -4.0f) X = -4.0f; - return X; + float X = sqrtf(-2.0f * logf(R1)) * cosf(2.0f * PI * R2); + if (X > 4.0f) X = 4.0f; + if (X < -4.0f) X = -4.0f; + return X; } // Accuracy unknown inline double atan_fast(double x) { - return (x / (1.0 + 0.28 * (x * x))); + return (x / (1.0 + 0.28 * (x * x))); } // linear -> dB conversion inline float lin2dB(float lin) { - const float LOG_2_DB = 8.6858896380650365530225783783321f; // 20 / ln( 10 ) - return logf(lin) * LOG_2_DB; + const float LOG_2_DB = 8.6858896380650365530225783783321f; // 20 / ln( 10 ) + return logf(lin) * LOG_2_DB; } // dB -> linear conversion inline float dB2lin(float dB) { - const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20 - return expf(dB * DB_2_LOG); + const float DB_2_LOG = 0.11512925464970228420089957273422f; // ln( 10 ) / 20 + return expf(dB * DB_2_LOG); } diff --git a/net/http_client.cpp b/net/http_client.cpp index ba0b1f9c19..b2bef05618 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -27,62 +27,62 @@ namespace net { Connection::Connection() - : port_(-1), sock_(-1) { + : port_(-1), sock_(-1) { } Connection::~Connection() { - Disconnect(); + Disconnect(); } bool Connection::Resolve(const char *host, int port) { - CHECK_EQ(-1, (intptr_t)sock_); - host_ = host; - port_ = port; + CHECK_EQ(-1, (intptr_t)sock_); + host_ = host; + port_ = port; - const char *ip = net::DNSResolve(host); - // VLOG(1) << "Resolved " << host << " to " << ip; - remote_.sin_family = AF_INET; - int tmpres = inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr))); - CHECK_GE(tmpres, 0); // << "inet_pton failed"; - CHECK_NE(0, tmpres); // << ip << " not a valid IP address"; - remote_.sin_port = htons(port); - free((void *)ip); - return true; + const char *ip = net::DNSResolve(host); + // VLOG(1) << "Resolved " << host << " to " << ip; + remote_.sin_family = AF_INET; + int tmpres = inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr))); + CHECK_GE(tmpres, 0); // << "inet_pton failed"; + CHECK_NE(0, tmpres); // << ip << " not a valid IP address"; + remote_.sin_port = htons(port); + free((void *)ip); + return true; } void Connection::Connect() { - CHECK_GE(port_, 0); - sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - CHECK_GE(sock_, 0); + CHECK_GE(port_, 0); + sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + CHECK_GE(sock_, 0); - // poll once per second.. should find a way to do this blocking. - int retval = -1; - while (retval < 0) { - retval = connect(sock_, (sockaddr *)&remote_, sizeof(struct sockaddr)); - if (retval >= 0) break; + // poll once per second.. should find a way to do this blocking. + int retval = -1; + while (retval < 0) { + retval = connect(sock_, (sockaddr *)&remote_, sizeof(struct sockaddr)); + if (retval >= 0) break; #ifdef _WIN32 - Sleep(1); + Sleep(1); #else - sleep(1); + sleep(1); #endif - } + } } void Connection::Disconnect() { - if ((intptr_t)sock_ != -1) { - closesocket(sock_); - sock_ = -1; - } else { - WLOG("Socket was already disconnected."); - } + if ((intptr_t)sock_ != -1) { + closesocket(sock_); + sock_ = -1; + } else { + WLOG("Socket was already disconnected."); + } } void Connection::Reconnect() { - Disconnect(); - Connect(); + Disconnect(); + Connect(); } -} // net +} // net namespace http { @@ -94,55 +94,55 @@ Client::~Client() { #define USERAGENT "METAGET 1.0" void Client::GET(const char *resource, Buffer *output) { - Buffer buffer; - const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n"; - buffer.Printf(tpl, resource, host_.c_str()); - CHECK(buffer.FlushSocket(sock())); + Buffer buffer; + const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n"; + buffer.Printf(tpl, resource, host_.c_str()); + CHECK(buffer.FlushSocket(sock())); - // Snarf all the data we can. - output->ReadAll(sock()); + // Snarf all the data we can. + output->ReadAll(sock()); - // Skip the header. - while (output->SkipLineCRLF() > 0) - ; + // Skip the header. + while (output->SkipLineCRLF() > 0) + ; - // output now contains the rest of the reply. + // output now contains the rest of the reply. } int Client::POST(const char *resource, const std::string &data, Buffer *output) { - Buffer buffer; - const char *tpl = "POST %s HTTP/1.0\r\nContent-Length: %d\r\n\r\n"; - buffer.Printf(tpl, resource, (int)data.size()); - buffer.Append(data); - CHECK(buffer.Flush(sock())); + Buffer buffer; + const char *tpl = "POST %s HTTP/1.0\r\nContent-Length: %d\r\n\r\n"; + buffer.Printf(tpl, resource, (int)data.size()); + buffer.Append(data); + CHECK(buffer.Flush(sock())); - // I guess we could add a deadline here. - output->ReadAll(sock()); + // I guess we could add a deadline here. + output->ReadAll(sock()); - if (output->size() == 0) { - // The connection was closed. - ELOG("POST failed."); - return -1; - } + if (output->size() == 0) { + // The connection was closed. + ELOG("POST failed."); + return -1; + } - std::string debug_data; - output->PeekAll(&debug_data); - - //VLOG(1) << "Reply size (before stripping headers): " << debug_data.size(); - std::string debug_str; - StringToHexString(debug_data, &debug_str); - // Tear off the http headers, leaving the actual response data. - std::string firstline; - CHECK_GT(output->TakeLineCRLF(&firstline), 0); - int code = atoi(&firstline[9]); // ugggly hardcoding - //VLOG(1) << "HTTP result code: " << code; - while (true) { - int skipped = output->SkipLineCRLF(); - if (skipped == 0) - break; - } - output->PeekAll(&debug_data); - return code; + std::string debug_data; + output->PeekAll(&debug_data); + + //VLOG(1) << "Reply size (before stripping headers): " << debug_data.size(); + std::string debug_str; + StringToHexString(debug_data, &debug_str); + // Tear off the http headers, leaving the actual response data. + std::string firstline; + CHECK_GT(output->TakeLineCRLF(&firstline), 0); + int code = atoi(&firstline[9]); // ugggly hardcoding + //VLOG(1) << "HTTP result code: " << code; + while (true) { + int skipped = output->SkipLineCRLF(); + if (skipped == 0) + break; + } + output->PeekAll(&debug_data); + return code; } -} // http +} // http diff --git a/net/http_client.h b/net/http_client.h index 05cd0f2bd0..320b8fba0f 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -14,53 +14,53 @@ namespace net { class Connection { - public: - Connection(); - virtual ~Connection(); +public: + Connection(); + virtual ~Connection(); - // Inits the sockaddr_in. - bool Resolve(const char *host, int port); + // Inits the sockaddr_in. + bool Resolve(const char *host, int port); - void Connect(); - void Disconnect(); + void Connect(); + void Disconnect(); - // Disconnects, and connects. Doesn't re-resolve. - void Reconnect(); + // Disconnects, and connects. Doesn't re-resolve. + void Reconnect(); - // Only to be used for bring-up and debugging. - uintptr_t sock() const { return sock_; } + // Only to be used for bring-up and debugging. + uintptr_t sock() const { return sock_; } - protected: - // Store the remote host here, so we can send it along through HTTP/1.1 requests. - // TODO: Move to http::client? - std::string host_; - int port_; - - sockaddr_in remote_; +protected: + // Store the remote host here, so we can send it along through HTTP/1.1 requests. + // TODO: Move to http::client? + std::string host_; + int port_; - private: - uintptr_t sock_; + sockaddr_in remote_; + +private: + uintptr_t sock_; }; -} // namespace net +} // namespace net namespace http { class Client : public net::Connection { - public: - Client(); - ~Client(); +public: + Client(); + ~Client(); - void GET(const char *resource, Buffer *output); + void GET(const char *resource, Buffer *output); - // Return value is the HTTP return code. - int POST(const char *resource, const std::string &data, Buffer *output); + // Return value is the HTTP return code. + int POST(const char *resource, const std::string &data, Buffer *output); - // HEAD, PUT, DELETE aren't implemented yet. + // HEAD, PUT, DELETE aren't implemented yet. }; -} // http +} // http -#endif // _NET_HTTP_HTTP_CLIENT +#endif // _NET_HTTP_HTTP_CLIENT diff --git a/net/resolve.cpp b/net/resolve.cpp index 725173dc4e..f1432eec88 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -1,4 +1,4 @@ - #include "net/resolve.h" + #include "net/resolve.h" #include #include @@ -7,7 +7,7 @@ #ifndef _WIN32 #include -#include // gethostbyname +#include // gethostbyname #include #else #include @@ -22,35 +22,35 @@ namespace net { void Init() { #ifdef _WIN32 - WSADATA wsaData = {0}; - WSAStartup(MAKEWORD(2, 2), &wsaData); + WSADATA wsaData = {0}; + WSAStartup(MAKEWORD(2, 2), &wsaData); #endif } void Shutdown() { #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif } char *DNSResolve(const char *host) { - struct hostent *hent; - if((hent = gethostbyname(host)) == NULL) - { - perror("Can't get IP"); - exit(1); - } - int iplen = 15; //XXX.XXX.XXX.XXX - char *ip = (char *)malloc(iplen+1); - memset(ip, 0, iplen+1); - if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL) - { - perror("Can't resolve host"); - exit(1); - } - return ip; + struct hostent *hent; + if((hent = gethostbyname(host)) == NULL) + { + perror("Can't get IP"); + exit(1); + } + int iplen = 15; //XXX.XXX.XXX.XXX + char *ip = (char *)malloc(iplen+1); + memset(ip, 0, iplen+1); + if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL) + { + perror("Can't resolve host"); + exit(1); + } + return ip; } } From 1ea568990da53bce7ae7853663ef062b5f6bb97e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 30 Oct 2012 16:23:08 +0100 Subject: [PATCH 0122/1445] Colored touchbuttons, portafixes --- Android.mk | 5 +++-- android/app-android.cpp | 11 ++++++++--- file/file_util.cpp | 8 ++++++++ gfx_es2/draw_buffer.cpp | 21 ++++++++++++++------- gfx_es2/draw_buffer.h | 2 +- ui/virtual_input.cpp | 19 +++++++++---------- ui/virtual_input.h | 9 ++++++--- 7 files changed, 49 insertions(+), 26 deletions(-) diff --git a/Android.mk b/Android.mk index c1debdd761..1db8a9688e 100644 --- a/Android.mk +++ b/Android.mk @@ -26,7 +26,8 @@ LOCAL_SRC_FILES :=\ file/file_util.cpp \ file/zip_read.cpp \ json/json_writer.cpp \ - math/math_util.cpp.arm \ + math/curves.cpp \ + math/math_util.cpp \ math/lin/aabb.cpp.arm \ math/lin/plane.cpp.arm \ math/lin/quat.cpp.arm \ @@ -51,7 +52,7 @@ LOCAL_SRC_FILES :=\ util/random/perlin.cpp -LOCAL_CFLAGS := -O2 -DGL_GLEXT_PROTOTYPES -fsigned-char +LOCAL_CFLAGS := -O2 -DGL_GLEXT_PROTOTYPES -fsigned-char -fno-strict-aliasing LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip diff --git a/android/app-android.cpp b/android/app-android.cpp index 78addc789c..d9c31ffd05 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -203,9 +203,12 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize(JNIE extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { if (renderer_inited) { UpdateInputState(&input_state); - NativeUpdate(input_state); + { + lock_guard guard(input_state.lock); + NativeUpdate(input_state); + EndInputState(&input_state); + } NativeRender(); - EndInputState(&input_state); time_update(); } else { ELOG("Ended up in nativeRender even though app has quit.%s", ""); @@ -266,6 +269,7 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch extern "C" void Java_com_turboviking_libnative_NativeApp_keyDown (JNIEnv *, jclass, jint key) { ILOG("Keydown %i", key); + lock_guard guard(input_state.lock); // Need a mechanism to release these. switch (key) { case 1: // Back @@ -282,7 +286,8 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_keyDown extern "C" void Java_com_turboviking_libnative_NativeApp_keyUp (JNIEnv *, jclass, jint key) { - ILOG("Keyup %i", key); + ILOG("Keyup %i", key); + lock_guard guard(input_state.lock); // Need a mechanism to release these. switch (key) { case 1: // Back diff --git a/file/file_util.cpp b/file/file_util.cpp index 3331b55e28..2cc447f087 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -78,6 +78,9 @@ static void stripTailDirSlashes(std::string &fname) // Returns true if file filename exists bool exists(const std::string &filename) { +#ifdef _WIN32 + return GetFileAttributes(filename.c_str()) != 0xFFFFFFFF; +#else struct stat64 file_info; std::string copy(filename); @@ -86,11 +89,15 @@ bool exists(const std::string &filename) int result = stat64(copy.c_str(), &file_info); return (result == 0); +#endif } // Returns true if filename is a directory bool isDirectory(const std::string &filename) { +#ifdef _WIN32 + return (GetFileAttributes(filename.c_str()) & FILE_ATTRIBUTE_DIRECTORY) != 0; +#else struct stat64 file_info; std::string copy(filename); @@ -104,6 +111,7 @@ bool isDirectory(const std::string &filename) } return S_ISDIR(file_info.st_mode); +#endif } size_t getFilesInDir(const char *directory, std::vector *files) { diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index d433917c55..9c3069bff5 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -158,7 +158,7 @@ inline void rot(float *v, float angle, float xc, float yc) { } -void DrawBuffer::DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color) { +void DrawBuffer::DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color, bool mirror_h) { const AtlasImage &image = atlas->images[atlas_image]; float w = (float)image.w * scale; float h = (float)image.h * scale; @@ -174,13 +174,20 @@ void DrawBuffer::DrawImageRotated(int atlas_image, float x, float y, float scale {x2, y2}, {x1, y2}, }; + float u1 = image.u1; + float u2 = image.u2; + if (mirror_h) { + float temp = u1; + u1 = u2; + u2 = temp; + } const float uv[6][2] = { - {image.u1, image.v1}, - {image.u2, image.v1}, - {image.u2, image.v2}, - {image.u1, image.v1}, - {image.u2, image.v2}, - {image.u1, image.v2}, + {u1, image.v1}, + {u2, image.v1}, + {u2, image.v2}, + {u1, image.v1}, + {u2, image.v2}, + {u1, image.v2}, }; for (int i = 0; i < 6; i++) { rot(v[i], angle, x, y); diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index c62458ade3..66f7b23072 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -94,7 +94,7 @@ public: void MeasureImage(int atlas_image, float *w, float *h); void DrawImage(int atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT); void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); - void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF)); // Always centers + void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF), bool mirror_h = false); // Always centers void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); // Results in 18 triangles. Kind of expensive for a button. void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index 953073f83e..3d789be092 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -4,8 +4,8 @@ #include "input/input_state.h" #include "virtual_input.h" -TouchButton::TouchButton(const Atlas *atlas, int imageIndex, int overlayImageIndex, int button, int rotationAngle) - : atlas_(atlas), imageIndex_(imageIndex), overlayImageIndex_(overlayImageIndex), button_(button) +TouchButton::TouchButton(const Atlas *atlas, int imageIndex, int overlayImageIndex, int button, int rotationAngle, bool mirror_h) + : atlas_(atlas), imageIndex_(imageIndex), overlayImageIndex_(overlayImageIndex), button_(button), mirror_h_(mirror_h) { memset(pointerDown, 0, sizeof(pointerDown)); w_ = atlas_->images[imageIndex_].w; @@ -29,20 +29,19 @@ void TouchButton::update(InputState &input_state) } } -void TouchButton::draw(DrawBuffer &db) +void TouchButton::draw(DrawBuffer &db, uint32_t color) { - uint32_t color = 0xAAFFFFFF; float scale = 1.0f; if (isDown_) { - color = 0xFFFFFFFF; + color |= 0xFF000000; scale = 2.0f; } - db.DrawImageRotated(imageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color); + // We only mirror background + db.DrawImageRotated(imageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color, mirror_h_); if (overlayImageIndex_ != -1) db.DrawImageRotated(overlayImageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color); } - TouchStick::TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick) : atlas_(atlas), bgImageIndex_(bgImageIndex), stickImageIndex_(stickImageIndex), stick_(stick) { @@ -78,9 +77,9 @@ void TouchStick::update(InputState &input_state) } } -void TouchStick::draw(DrawBuffer &db) +void TouchStick::draw(DrawBuffer &db, uint32_t color) { if (bgImageIndex_ != -1) - db.DrawImage(bgImageIndex_, stick_x_, stick_y_, 1.0f, 0xFFFFFFFF, ALIGN_CENTER); - db.DrawImage(stickImageIndex_, stick_x_ + stick_delta_x_, stick_y_ + stick_delta_y_, 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + db.DrawImage(bgImageIndex_, stick_x_, stick_y_, 1.0f, color, ALIGN_CENTER); + db.DrawImage(stickImageIndex_, stick_x_ + stick_delta_x_, stick_y_ + stick_delta_y_, 1.0f, color, ALIGN_CENTER); } diff --git a/ui/virtual_input.h b/ui/virtual_input.h index ee336ab6b5..ec38dded46 100644 --- a/ui/virtual_input.h +++ b/ui/virtual_input.h @@ -5,14 +5,15 @@ class DrawBuffer; // Multitouch-enabled emulation of a hardware button. +// Many of these can be pressed simultaneously with multitouch. // (any finger will work, simultaneously with other virtual button/stick actions). class TouchButton { public: - TouchButton(const Atlas *atlas, int imageIndex, int overlayImageIndex, int button, int rotationAngle = 0); + TouchButton(const Atlas *atlas, int imageIndex, int overlayImageIndex, int button, int rotationAngle = 0, bool mirror_h = false); void update(InputState &input_state); - void draw(DrawBuffer &db); + void draw(DrawBuffer &db, uint32_t color); void setPos(float x, float y) { x_ = x - w_ / 2; @@ -32,6 +33,7 @@ private: int overlayImageIndex_; int button_; float rotationAngle_; + bool mirror_h_; float x_, y_; float w_; @@ -45,6 +47,7 @@ private: // Multi-touch enabled virtual joystick +// Many of these can be used simultaneously with multitouch. // (any finger will work, simultaneously with other virtual button/stick actions). class TouchStick { @@ -52,7 +55,7 @@ public: TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick); void update(InputState &input_state); - void draw(DrawBuffer &db); + void draw(DrawBuffer &db, uint32_t color); void setPos(float x, float y) { stick_x_ = x; From 2c3f569a9f64903b6ede978ccc6f4aedc5d2b289 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 30 Oct 2012 16:30:55 +0100 Subject: [PATCH 0123/1445] Apparently there were still users of tempfloat --- ui/ui.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/ui.h b/ui/ui.h index 362a5b5910..763a57457a 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -105,6 +105,9 @@ struct UIState { int lastwidget; int ui_tick; + + // deprecated: tempfloat + float tempfloat; }; // This needs to be extern so that additional UI controls can be developed outside this file. From 23e6b0e3742ac4b736009e4d9e913408458647a2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 30 Oct 2012 17:36:28 +0100 Subject: [PATCH 0124/1445] UI tweaks, bugfixing --- android/app-android.cpp | 40 +++++++++++++++++++++++----------------- ui/ui.cpp | 13 +++++++------ ui/ui.h | 1 + ui/virtual_input.cpp | 5 +++-- ui/virtual_input.h | 2 +- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index d9c31ffd05..141469df8c 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -29,6 +29,9 @@ static JNIEnv *jniEnvUI; std::string frameCommand; std::string frameCommandParam; +static uint32_t pad_buttons_async_set; +static uint32_t pad_buttons_async_clear; + // Android implementation of callbacks to the Java part of the app void SystemToast(const char *text) { frameCommand = "toast"; @@ -107,6 +110,9 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init renderer_inited = false; first_lost = true; + pad_buttons_async_set = 0; + pad_buttons_async_clear = 0; + std::string apkPath = GetJavaString(env, japkpath); ILOG("APK path: %s", apkPath.c_str()); VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); @@ -202,9 +208,11 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize(JNIE extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { if (renderer_inited) { - UpdateInputState(&input_state); { lock_guard guard(input_state.lock); + input_state.pad_buttons |= pad_buttons_async_set; + input_state.pad_buttons &= ~pad_buttons_async_clear; + UpdateInputState(&input_state); NativeUpdate(input_state); EndInputState(&input_state); } @@ -266,38 +274,36 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch input_state.mouse_valid = true; } -extern "C" void Java_com_turboviking_libnative_NativeApp_keyDown - (JNIEnv *, jclass, jint key) { - ILOG("Keydown %i", key); - lock_guard guard(input_state.lock); - // Need a mechanism to release these. +extern "C" void Java_com_turboviking_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) { switch (key) { case 1: // Back - input_state.pad_buttons |= PAD_BUTTON_BACK; + pad_buttons_async_set |= PAD_BUTTON_BACK; + pad_buttons_async_clear &= ~PAD_BUTTON_BACK; break; case 2: // Menu - input_state.pad_buttons |= PAD_BUTTON_MENU; + pad_buttons_async_set |= PAD_BUTTON_MENU; + pad_buttons_async_clear &= ~PAD_BUTTON_MENU; break; case 3: // Search - input_state.pad_buttons |= PAD_BUTTON_A; + pad_buttons_async_set |= PAD_BUTTON_A; + pad_buttons_async_clear &= ~PAD_BUTTON_A; break; } } -extern "C" void Java_com_turboviking_libnative_NativeApp_keyUp - (JNIEnv *, jclass, jint key) { - ILOG("Keyup %i", key); - lock_guard guard(input_state.lock); - // Need a mechanism to release these. +extern "C" void Java_com_turboviking_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) { switch (key) { case 1: // Back - input_state.pad_buttons &= ~PAD_BUTTON_BACK; + pad_buttons_async_set &= ~PAD_BUTTON_BACK; + pad_buttons_async_clear |= PAD_BUTTON_BACK; break; case 2: // Menu - input_state.pad_buttons &= ~PAD_BUTTON_MENU; + pad_buttons_async_set &= ~PAD_BUTTON_MENU; + pad_buttons_async_clear |= PAD_BUTTON_MENU; break; case 3: // Search - input_state.pad_buttons &= ~PAD_BUTTON_A; + pad_buttons_async_set &= ~PAD_BUTTON_A; + pad_buttons_async_clear |= PAD_BUTTON_A; break; } } diff --git a/ui/ui.cpp b/ui/ui.cpp index 9ef9b74970..4203756b99 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -140,7 +140,7 @@ int UIButton(int id, const LayoutManager &layout, float w, const char *text, int // Render button - ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); + ui_draw2d.DrawImage2GridH((txOffset && theme.buttonSelected) ? theme.buttonSelected : theme.buttonImage, x, y, x + w); ui_draw2d.DrawTextShadow(theme.uiFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); uistate.lastwidget = id; @@ -361,14 +361,15 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { } else if (scrollY < 0.0f) { scrollY += 0.3f * -scrollY; } - lastX = uistate.mousex[0]; - lastY = uistate.mousey[0]; - uistate.lastwidget = id; } else { scrollY = 0.0f; - scrolling = false; + inertiaY = 0.0f; } + lastX = uistate.mousex[0]; + lastY = uistate.mousey[0]; + uistate.lastwidget = id; + // Drawing and item hittesting // render items @@ -384,7 +385,7 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { selected == -1 && UIRegionHit(k, x, item_y, w, itemHeight, 0)) { selected = i; - } else if (scrolling) { + } else if (scrolling && canScroll) { selected = -1; } } diff --git a/ui/ui.h b/ui/ui.h index 362a5b5910..3227b55858 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -122,6 +122,7 @@ struct UITheme { int uiFontSmall; int uiFontSmaller; int buttonImage; + int buttonSelected; int checkOn; int checkOff; }; diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index 3d789be092..727ea4e90f 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -29,17 +29,18 @@ void TouchButton::update(InputState &input_state) } } -void TouchButton::draw(DrawBuffer &db, uint32_t color) +void TouchButton::draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay) { float scale = 1.0f; if (isDown_) { color |= 0xFF000000; + colorOverlay |= 0xFF000000; scale = 2.0f; } // We only mirror background db.DrawImageRotated(imageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color, mirror_h_); if (overlayImageIndex_ != -1) - db.DrawImageRotated(overlayImageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color); + db.DrawImageRotated(overlayImageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, colorOverlay); } TouchStick::TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick) diff --git a/ui/virtual_input.h b/ui/virtual_input.h index ec38dded46..c4dc4b4647 100644 --- a/ui/virtual_input.h +++ b/ui/virtual_input.h @@ -13,7 +13,7 @@ public: TouchButton(const Atlas *atlas, int imageIndex, int overlayImageIndex, int button, int rotationAngle = 0, bool mirror_h = false); void update(InputState &input_state); - void draw(DrawBuffer &db, uint32_t color); + void draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay); void setPos(float x, float y) { x_ = x - w_ / 2; From 95f0f869f74f5fd4e9f0fd43e2d7c4324ee7926e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 31 Oct 2012 10:14:59 +0100 Subject: [PATCH 0125/1445] Make atlastool write names to the table, so that name-based lookup is possible. --- tools/atlastool.cpp | 69 +++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 6a2cfda2b0..39c570442f 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -443,6 +443,7 @@ struct FontDesc { results[i].ex - results[i].sx, results[i].ey - results[i].sy, (i - first_char_id + 32)); } fprintf(fil, " },\n"); + fprintf(fil, " \"%s\", // name\n", name.c_str()); fprintf(fil, "};\n"); } @@ -464,13 +465,14 @@ struct ImageDesc { int i = result_index; float toffx = 0.5f / tw; float toffy = 0.5f / th; - fprintf(fil, " {%ff, %ff, %ff, %ff, %d, %d},\n", + fprintf(fil, " {%ff, %ff, %ff, %ff, %d, %d, \"%s\"},\n", results[i].sx / tw + toffx, results[i].sy / th + toffy, results[i].ex / tw - toffx, results[i].ey / th - toffy, results[i].ex - results[i].sx, - results[i].ey - results[i].sy); + results[i].ey - results[i].sy, + name.c_str()); } void OutputHeader(FILE *fil, int index) { @@ -578,66 +580,67 @@ int main(int argc, char **argv) { // Sort items by ID. sort(results.begin(), results.end()); - FILE *cpp_fil = fopen((out_prefix + "_atlas.cpp").c_str(), "wb"); - fprintf(cpp_fil, "// C++ generated by atlastool from %s (hrydgard@gmail.com)\n\n", argv[1]); - fprintf(cpp_fil, "#include \"%s\"\n\n", (out_prefix + "_atlas.h").c_str()); + FILE *cpp_file = fopen((out_prefix + "_atlas.cpp").c_str(), "wb"); + fprintf(cpp_file, "// C++ generated by atlastool from %s (hrydgard@gmail.com)\n\n", argv[1]); + fprintf(cpp_file, "#include \"%s\"\n\n", (out_prefix + "_atlas.h").c_str()); for (int i = 0; i < (int)fonts.size(); i++) { FontDesc &xfont = fonts[i]; xfont.ComputeHeight(results, distmult); - xfont.OutputSelf(cpp_fil, dest.width(), dest.height(), results); + xfont.OutputSelf(cpp_file, dest.width(), dest.height(), results); } if (fonts.size()) { - fprintf(cpp_fil, "const AtlasFont *%s_fonts[%i] = {\n", atlas_name, (int)fonts.size()); + fprintf(cpp_file, "const AtlasFont *%s_fonts[%i] = {\n", atlas_name, (int)fonts.size()); for (int i = 0; i < (int)fonts.size(); i++) { - fonts[i].OutputIndex(cpp_fil); + fonts[i].OutputIndex(cpp_file); } - fprintf(cpp_fil, "};\n"); + fprintf(cpp_file, "};\n"); } if (images.size()) { - fprintf(cpp_fil, "const AtlasImage %s_images[%i] = {\n", atlas_name, (int)images.size()); + fprintf(cpp_file, "const AtlasImage %s_images[%i] = {\n", atlas_name, (int)images.size()); for (int i = 0; i < (int)images.size(); i++) { - images[i].OutputSelf(cpp_fil, dest.width(), dest.height(), results); + images[i].OutputSelf(cpp_file, dest.width(), dest.height(), results); } - fprintf(cpp_fil, "};\n"); + fprintf(cpp_file, "};\n"); } - fprintf(cpp_fil, "const Atlas %s_atlas = {\n", atlas_name); - fprintf(cpp_fil, " \"%s\",\n", image_name.c_str()); + fprintf(cpp_file, "const Atlas %s_atlas = {\n", atlas_name); + fprintf(cpp_file, " \"%s\",\n", image_name.c_str()); if (fonts.size()) { - fprintf(cpp_fil, " %s_fonts, %i,\n", atlas_name, (int)fonts.size()); + fprintf(cpp_file, " %s_fonts, %i,\n", atlas_name, (int)fonts.size()); } else { - fprintf(cpp_fil, " 0, 0,\n"); + fprintf(cpp_file, " 0, 0,\n"); } if (images.size()) { - fprintf(cpp_fil, " %s_images, %i,\n", atlas_name, (int)images.size()); + fprintf(cpp_file, " %s_images, %i,\n", atlas_name, (int)images.size()); } else { - fprintf(cpp_fil, " 0, 0,\n"); + fprintf(cpp_file, " 0, 0,\n"); } - fprintf(cpp_fil, "};\n"); + fprintf(cpp_file, "};\n"); // Should output a list pointing to all the fonts as well. - fclose(cpp_fil); - FILE *h_fil = fopen((out_prefix + "_atlas.h").c_str(), "wb"); - fprintf(h_fil, "// Header generated by atlastool from %s (hrydgard@gmail.com)\n\n", argv[1]); - fprintf(h_fil, "#pragma once\n"); - fprintf(h_fil, "#include \"gfx/texture_atlas.h\"\n\n"); + fclose(cpp_file); + + FILE *h_file = fopen((out_prefix + "_atlas.h").c_str(), "wb"); + fprintf(h_file, "// Header generated by atlastool from %s (hrydgard@gmail.com)\n\n", argv[1]); + fprintf(h_file, "#pragma once\n"); + fprintf(h_file, "#include \"gfx/texture_atlas.h\"\n\n"); if (fonts.size()) { - fprintf(h_fil, "// FONTS_%s\n", atlas_name); + fprintf(h_file, "// FONTS_%s\n", atlas_name); for (int i = 0; i < (int)fonts.size(); i++) { - fonts[i].OutputHeader(h_fil, i); + fonts[i].OutputHeader(h_file, i); } - fprintf(h_fil, "\n\n"); + fprintf(h_file, "\n\n"); } if (images.size()) { - fprintf(h_fil, "// IMAGES_%s\n", atlas_name); + fprintf(h_file, "// IMAGES_%s\n", atlas_name); for (int i = 0; i < (int)images.size(); i++) { - images[i].OutputHeader(h_fil, i); + images[i].OutputHeader(h_file, i); } - fprintf(h_fil, "\n\n"); + fprintf(h_file, "\n\n"); } - fprintf(h_fil, "extern const Atlas %s_atlas;\n", atlas_name); - fprintf(h_fil, "extern const AtlasImage %s_images[%i];\n", atlas_name, (int)images.size()); - fclose(h_fil); + fprintf(h_file, "extern const Atlas %s_atlas;\n", atlas_name); + fprintf(h_file, "extern const AtlasImage %s_images[%i];\n", atlas_name, (int)images.size()); + fclose(h_file); // TODO: Turn into C++ arrays. } From 3c231e9056219246ad857ffe6f1e664b48e8ca20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Oct 2012 11:41:06 +0100 Subject: [PATCH 0126/1445] Reindent app-android.cpp and native-audio-so.cpp --- android/app-android.cpp | 274 ++++++++++++++++++------------------ android/native-audio-so.cpp | 166 +++++++++++----------- 2 files changed, 220 insertions(+), 220 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 141469df8c..3310cea888 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -34,8 +34,8 @@ static uint32_t pad_buttons_async_clear; // Android implementation of callbacks to the Java part of the app void SystemToast(const char *text) { - frameCommand = "toast"; - frameCommandParam = text; + frameCommand = "toast"; + frameCommandParam = text; } // TODO: need a Hide or bool show; @@ -49,23 +49,23 @@ void ShowKeyboard() { } void Vibrate(int length_ms) { - frameCommand = "vibrate"; - frameCommandParam = "100"; + frameCommand = "vibrate"; + frameCommandParam = "100"; } void LaunchBrowser(const char *url) { - frameCommand = "launchBrowser"; - frameCommandParam = url; + frameCommand = "launchBrowser"; + frameCommandParam = url; } void LaunchMarket(const char *url) { - frameCommand = "launchMarket"; - frameCommandParam = url; + frameCommand = "launchMarket"; + frameCommandParam = url; } void LaunchEmail(const char *email_address) { - frameCommand = "launchEmail"; - frameCommandParam = email_address; + frameCommand = "launchEmail"; + frameCommandParam = email_address; } // Remember that all of these need initialization on init! The process @@ -82,10 +82,10 @@ static bool use_native_audio = false; std::string GetJavaString(JNIEnv *env, jstring jstr) { - const char *str = env->GetStringUTFChars(jstr, 0); - std::string cpp_string = std::string(str); - env->ReleaseStringUTFChars(jstr, str); - return cpp_string; + const char *str = env->GetStringUTFChars(jstr, 0); + std::string cpp_string = std::string(str); + env->ReleaseStringUTFChars(jstr, str); + return cpp_string; } extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) @@ -98,53 +98,53 @@ extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv // For the Back button to work right. extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isAtTopLevel(JNIEnv *env, jclass) { - return NativeIsAtTopLevel(); + return NativeIsAtTopLevel(); } extern "C" void Java_com_turboviking_libnative_NativeApp_init - (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring japkpath, - jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { - jniEnvUI = env; + (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring japkpath, + jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { + jniEnvUI = env; - memset(&input_state, 0, sizeof(input_state)); - renderer_inited = false; - first_lost = true; + memset(&input_state, 0, sizeof(input_state)); + renderer_inited = false; + first_lost = true; pad_buttons_async_set = 0; pad_buttons_async_clear = 0; - std::string apkPath = GetJavaString(env, japkpath); - ILOG("APK path: %s", apkPath.c_str()); - VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); + std::string apkPath = GetJavaString(env, japkpath); + ILOG("APK path: %s", apkPath.c_str()); + VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); - std::string externalDir = GetJavaString(env, jexternalDir); - std::string user_data_path = GetJavaString(env, jdataDir) + "/"; - std::string library_path = GetJavaString(env, jlibraryDir) + "/"; - std::string installID = GetJavaString(env, jinstallID); + std::string externalDir = GetJavaString(env, jexternalDir); + std::string user_data_path = GetJavaString(env, jdataDir) + "/"; + std::string library_path = GetJavaString(env, jlibraryDir) + "/"; + std::string installID = GetJavaString(env, jinstallID); - ILOG("External storage path: %s", externalDir.c_str()); + ILOG("External storage path: %s", externalDir.c_str()); std::string app_name; std::string app_nice_name; bool landscape; - net::Init(); + net::Init(); - g_dpi = dpi; + g_dpi = dpi; g_dpi_scale = 240.0f / (float)g_dpi; - pixel_xres = xxres; - pixel_yres = yyres; + pixel_xres = xxres; + pixel_yres = yyres; NativeGetAppInfo(&app_name, &app_nice_name, &landscape); const char *argv[2] = {app_name.c_str(), 0}; - NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); + NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); - use_native_audio = juseNativeAudio; + use_native_audio = juseNativeAudio; if (use_native_audio) { AndroidAudio_Init(&NativeMix, library_path); } -} +} extern "C" void Java_com_turboviking_libnative_NativeApp_resume(JNIEnv *, jclass) { ILOG("NativeResume"); @@ -161,54 +161,54 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_pause(JNIEnv *, jclass) } extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown(JNIEnv *, jclass) { - ILOG("NativeShutdown."); + ILOG("NativeShutdown."); if (use_native_audio) { AndroidAudio_Shutdown(); } if (renderer_inited) { - NativeShutdownGraphics(); + NativeShutdownGraphics(); renderer_inited = false; - } - NativeShutdown(); - ILOG("VFSShutdown."); - VFSShutdown(); - net::Shutdown(); + } + NativeShutdown(); + ILOG("VFSShutdown."); + VFSShutdown(); + net::Shutdown(); } static jmethodID postCommand; extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { ILOG("displayInit()"); - if (!renderer_inited) { + if (!renderer_inited) { - // We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S). - // Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo - // can change the dp resolution if it feels like it. - dp_xres = pixel_xres * g_dpi_scale; - dp_yres = pixel_yres * g_dpi_scale; + // We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S). + // Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo + // can change the dp resolution if it feels like it. + dp_xres = pixel_xres * g_dpi_scale; + dp_yres = pixel_yres * g_dpi_scale; - ILOG("Calling NativeInitGraphics(); dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); - NativeInitGraphics(); + ILOG("Calling NativeInitGraphics(); dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); + NativeInitGraphics(); - dp_xscale = (float)dp_xres / pixel_xres; - dp_yscale = (float)dp_yres / pixel_yres; + dp_xscale = (float)dp_xres / pixel_xres; + dp_yscale = (float)dp_yres / pixel_yres; renderer_inited = true; - } else { - ILOG("Calling NativeDeviceLost();"); + } else { + ILOG("Calling NativeDeviceLost();"); NativeDeviceLost(); - } - jclass cls = env->GetObjectClass(obj); - postCommand = env->GetMethodID(cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); - ILOG("MethodID: %i", (int)postCommand); + } + jclass cls = env->GetObjectClass(obj); + postCommand = env->GetMethodID(cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); + ILOG("MethodID: %i", (int)postCommand); } extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { - ILOG("displayResize (%i, %i)!", w, h); + ILOG("displayResize (%i, %i)!", w, h); } extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { - if (renderer_inited) { - { + if (renderer_inited) { + { lock_guard guard(input_state.lock); input_state.pad_buttons |= pad_buttons_async_set; input_state.pad_buttons &= ~pad_buttons_async_clear; @@ -216,111 +216,111 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender(JNIE NativeUpdate(input_state); EndInputState(&input_state); } - NativeRender(); - time_update(); - } else { - ELOG("Ended up in nativeRender even though app has quit.%s", ""); - // Shouldn't really get here. - glClearColor(1.0, 0.0, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } - - if (!frameCommand.empty()) { - ILOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str()); + NativeRender(); + time_update(); + } else { + ELOG("Ended up in nativeRender even though app has quit.%s", ""); + // Shouldn't really get here. + glClearColor(1.0, 0.0, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + if (!frameCommand.empty()) { + ILOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str()); - jstring cmd = env->NewStringUTF(frameCommand.c_str()); - jstring param = env->NewStringUTF(frameCommandParam.c_str()); - env->CallVoidMethod(obj, postCommand, cmd, param); - - frameCommand = ""; - frameCommandParam = ""; - } + jstring cmd = env->NewStringUTF(frameCommand.c_str()); + jstring param = env->NewStringUTF(frameCommandParam.c_str()); + env->CallVoidMethod(obj, postCommand, cmd, param); + + frameCommand = ""; + frameCommandParam = ""; + } } -extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { - // The audio thread can pretty safely enable Flush-to-Zero mode on the FPU. - EnableFZ(); +extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { + // The audio thread can pretty safely enable Flush-to-Zero mode on the FPU. + EnableFZ(); - int buf_size = env->GetArrayLength(array); + int buf_size = env->GetArrayLength(array); if (buf_size) { - short *data = env->GetShortArrayElements(array, 0); - int samples = buf_size / 2; - NativeMix(data, samples); - env->ReleaseShortArrayElements(array, data, 0); - } + short *data = env->GetShortArrayElements(array, 0); + int samples = buf_size / 2; + NativeMix(data, samples); + env->ReleaseShortArrayElements(array, data, 0); + } } extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch - (JNIEnv *, jclass, float x, float y, int code, int pointerId) { - lock_guard guard(input_state.lock); + (JNIEnv *, jclass, float x, float y, int code, int pointerId) { + lock_guard guard(input_state.lock); if (pointerId >= MAX_POINTERS) { ELOG("Too many pointers: %i", pointerId); - return; // We ignore 8+ pointers entirely. + return; // We ignore 8+ pointers entirely. } - float scaledX = (int)(x * dp_xscale); // why the (int) cast? - float scaledY = (int)(y * dp_yscale); - input_state.pointer_x[pointerId] = scaledX; - input_state.pointer_y[pointerId] = scaledY; - if (code == 1) { - input_state.pointer_down[pointerId] = true; - NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_DOWN); - } else if (code == 2) { - input_state.pointer_down[pointerId] = false; - NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_UP); - } else { - NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_MOVE); - } - input_state.mouse_valid = true; + float scaledX = (int)(x * dp_xscale); // why the (int) cast? + float scaledY = (int)(y * dp_yscale); + input_state.pointer_x[pointerId] = scaledX; + input_state.pointer_y[pointerId] = scaledY; + if (code == 1) { + input_state.pointer_down[pointerId] = true; + NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_DOWN); + } else if (code == 2) { + input_state.pointer_down[pointerId] = false; + NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_UP); + } else { + NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_MOVE); + } + input_state.mouse_valid = true; } extern "C" void Java_com_turboviking_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) { - switch (key) { - case 1: // Back - pad_buttons_async_set |= PAD_BUTTON_BACK; + switch (key) { + case 1: // Back + pad_buttons_async_set |= PAD_BUTTON_BACK; pad_buttons_async_clear &= ~PAD_BUTTON_BACK; - break; - case 2: // Menu - pad_buttons_async_set |= PAD_BUTTON_MENU; + break; + case 2: // Menu + pad_buttons_async_set |= PAD_BUTTON_MENU; pad_buttons_async_clear &= ~PAD_BUTTON_MENU; - break; - case 3: // Search + break; + case 3: // Search pad_buttons_async_set |= PAD_BUTTON_A; - pad_buttons_async_clear &= ~PAD_BUTTON_A; - break; - } + pad_buttons_async_clear &= ~PAD_BUTTON_A; + break; + } } extern "C" void Java_com_turboviking_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) { - switch (key) { - case 1: // Back + switch (key) { + case 1: // Back pad_buttons_async_set &= ~PAD_BUTTON_BACK; - pad_buttons_async_clear |= PAD_BUTTON_BACK; - break; - case 2: // Menu - pad_buttons_async_set &= ~PAD_BUTTON_MENU; + pad_buttons_async_clear |= PAD_BUTTON_BACK; + break; + case 2: // Menu + pad_buttons_async_set &= ~PAD_BUTTON_MENU; pad_buttons_async_clear |= PAD_BUTTON_MENU; - break; - case 3: // Search - pad_buttons_async_set &= ~PAD_BUTTON_A; + break; + case 3: // Search + pad_buttons_async_set &= ~PAD_BUTTON_A; pad_buttons_async_clear |= PAD_BUTTON_A; - break; - } + break; + } } extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_accelerometer - (JNIEnv *, jclass, float x, float y, float z) { - // Theoretically this needs locking but I doubt it matters. Worst case, the X - // from one "sensor frame" will be used together with Y from the next. - // Should look into quantization though, for compressed movement storage. - input_state.accelerometer_valid = true; - input_state.acc.x = x; - input_state.acc.y = y; - input_state.acc.z = z; + (JNIEnv *, jclass, float x, float y, float z) { + // Theoretically this needs locking but I doubt it matters. Worst case, the X + // from one "sensor frame" will be used together with Y from the next. + // Should look into quantization though, for compressed movement storage. + input_state.accelerometer_valid = true; + input_state.acc.x = x; + input_state.acc.y = y; + input_state.acc.z = z; } extern "C" void Java_com_turboviking_libnative_NativeApp_sendMessage - (JNIEnv *env, jclass, jstring message, jstring param) { + (JNIEnv *env, jclass, jstring message, jstring param) { jboolean isCopy; std::string msg = GetJavaString(env, message); std::string prm = GetJavaString(env, param); diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 93748e3695..64a6b05b97 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -43,107 +43,107 @@ static AndroidAudioCallback audioCallback; // I've chosen to this approach: Instantly enqueue a buffer that was rendered to the last time, // and then render the next. Hopefully it's okay to spend time in this callback after having enqueued. static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { - assert(bq == bqPlayerBufferQueue); - assert(NULL == context); + assert(bq == bqPlayerBufferQueue); + assert(NULL == context); - short *nextBuffer = buffer[curBuffer]; - int nextSize = sizeof(buffer[0]); + short *nextBuffer = buffer[curBuffer]; + int nextSize = sizeof(buffer[0]); - SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); + SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); - // Comment from sample code: - // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, - // which for this code example would indicate a programming error - assert(SL_RESULT_SUCCESS == result); + // Comment from sample code: + // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, + // which for this code example would indicate a programming error + assert(SL_RESULT_SUCCESS == result); - curBuffer ^= 1; // Switch buffer - // Render to the fresh buffer - audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); + curBuffer ^= 1; // Switch buffer + // Render to the fresh buffer + audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); } // create the engine and output mix objects extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb) { - audioCallback = cb; + audioCallback = cb; - SLresult result; - // create engine - result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); - assert(SL_RESULT_SUCCESS == result); - result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); - result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); - assert(SL_RESULT_SUCCESS == result); - result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0); - assert(SL_RESULT_SUCCESS == result); - result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + SLresult result; + // create engine + result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); + assert(SL_RESULT_SUCCESS == result); + result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); + assert(SL_RESULT_SUCCESS == result); + result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0); + assert(SL_RESULT_SUCCESS == result); + result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); - SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; - SLDataFormat_PCM format_pcm = { - SL_DATAFORMAT_PCM, - 2, - SL_SAMPLINGRATE_44_1, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, - SL_BYTEORDER_LITTLEENDIAN - }; + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, + 2, + SL_SAMPLINGRATE_44_1, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_PCMSAMPLEFORMAT_FIXED_16, + SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, + SL_BYTEORDER_LITTLEENDIAN + }; - SLDataSource audioSrc = {&loc_bufq, &format_pcm}; + SLDataSource audioSrc = {&loc_bufq, &format_pcm}; - // configure audio sink - SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; - SLDataSink audioSnk = {&loc_outmix, NULL}; + // configure audio sink + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; + SLDataSink audioSnk = {&loc_outmix, NULL}; - // create audio player - const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; - const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; - result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); - assert(SL_RESULT_SUCCESS == result); + // create audio player + const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME}; + const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); + assert(SL_RESULT_SUCCESS == result); - result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); - result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); - assert(SL_RESULT_SUCCESS == result); - result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, - &bqPlayerBufferQueue); - assert(SL_RESULT_SUCCESS == result); - result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); - assert(SL_RESULT_SUCCESS == result); - result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); - assert(SL_RESULT_SUCCESS == result); - result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); - assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, + &bqPlayerBufferQueue); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); + assert(SL_RESULT_SUCCESS == result); + result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); + assert(SL_RESULT_SUCCESS == result); - // Render and enqueue a first buffer. (or should we just play the buffer empty?) - curBuffer = 0; - audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); + // Render and enqueue a first buffer. (or should we just play the buffer empty?) + curBuffer = 0; + audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); - result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[curBuffer])); - if (SL_RESULT_SUCCESS != result) { - return false; - } - curBuffer ^= 1; - return true; + result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[curBuffer])); + if (SL_RESULT_SUCCESS != result) { + return false; + } + curBuffer ^= 1; + return true; } // shut down the native audio system extern "C" void OpenSLWrap_Shutdown() { - if (bqPlayerObject != NULL) { - (*bqPlayerObject)->Destroy(bqPlayerObject); - bqPlayerObject = NULL; - bqPlayerPlay = NULL; - bqPlayerBufferQueue = NULL; - bqPlayerMuteSolo = NULL; - bqPlayerVolume = NULL; - } - if (outputMixObject != NULL) { - (*outputMixObject)->Destroy(outputMixObject); - outputMixObject = NULL; - } - if (engineObject != NULL) { - (*engineObject)->Destroy(engineObject); - engineObject = NULL; - engineEngine = NULL; - } + if (bqPlayerObject != NULL) { + (*bqPlayerObject)->Destroy(bqPlayerObject); + bqPlayerObject = NULL; + bqPlayerPlay = NULL; + bqPlayerBufferQueue = NULL; + bqPlayerMuteSolo = NULL; + bqPlayerVolume = NULL; + } + if (outputMixObject != NULL) { + (*outputMixObject)->Destroy(outputMixObject); + outputMixObject = NULL; + } + if (engineObject != NULL) { + (*engineObject)->Destroy(engineObject); + engineObject = NULL; + engineEngine = NULL; + } } From ec05ad7487aab22f186f152ba8e8b783e9de09dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Oct 2012 12:04:37 +0100 Subject: [PATCH 0127/1445] Virtual stick fixes --- ui/virtual_input.cpp | 21 +++++++++++++++++---- ui/virtual_input.h | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index 727ea4e90f..090ac38016 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -46,7 +46,9 @@ void TouchButton::draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay) TouchStick::TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick) : atlas_(atlas), bgImageIndex_(bgImageIndex), stickImageIndex_(stickImageIndex), stick_(stick) { - stick_size_ = atlas_->images[bgImageIndex].w; + stick_size_ = atlas_->images[bgImageIndex].w / 3.5f; + memset(dragging_, 0, sizeof(dragging_)); + memset(lastPointerDown_, 0, sizeof(lastPointerDown_)); } void TouchStick::update(InputState &input_state) @@ -57,8 +59,15 @@ void TouchStick::update(InputState &input_state) float dx = (input_state.pointer_x[i] - stick_x_) * inv_stick_size; float dy = (input_state.pointer_y[i] - stick_y_) * inv_stick_size; // Ignore outside box - if (fabsf(dx) > 1.4f || fabsf(dy) > 1.4f) - continue; + if (!dragging_[i] && (fabsf(dx) > 1.4f || fabsf(dy) > 1.4f)) + goto skip; + if (!lastPointerDown_[i] && (fabsf(dx) < 1.4f && fabsf(dy) < 1.4f)) + { + dragging_[i] = true; + } + if (!dragging_[i]) + goto skip; + // Clamp to a circle float len = sqrtf(dx * dx + dy * dy); if (len > 1.0f) { @@ -74,7 +83,11 @@ void TouchStick::update(InputState &input_state) input_state.pad_rstick_x = dx; input_state.pad_rstick_y = -dy; } + } else { + dragging_[i] = false; } +skip: + lastPointerDown_[i] = input_state.pointer_down[i]; } } @@ -82,5 +95,5 @@ void TouchStick::draw(DrawBuffer &db, uint32_t color) { if (bgImageIndex_ != -1) db.DrawImage(bgImageIndex_, stick_x_, stick_y_, 1.0f, color, ALIGN_CENTER); - db.DrawImage(stickImageIndex_, stick_x_ + stick_delta_x_, stick_y_ + stick_delta_y_, 1.0f, color, ALIGN_CENTER); + db.DrawImage(stickImageIndex_, stick_x_ + stick_delta_x_ * stick_size_, stick_y_ + stick_delta_y_ * stick_size_, 1.0f, color, ALIGN_CENTER); } diff --git a/ui/virtual_input.h b/ui/virtual_input.h index c4dc4b4647..bfc7ed5c37 100644 --- a/ui/virtual_input.h +++ b/ui/virtual_input.h @@ -70,6 +70,8 @@ private: int stick_size_; float stick_x_; float stick_y_; + bool dragging_[MAX_POINTERS]; + bool lastPointerDown_[MAX_POINTERS]; // maintained for drawing only float stick_delta_x_; From ad001f7e16950b4a20b1338819560ecb604c382d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Oct 2012 12:12:24 +0100 Subject: [PATCH 0128/1445] PCMain: Simulate tablet resolution with option --- base/PCMain.cpp | 106 +++++++++++++++++++++++++++--------------------- ui/ui.cpp | 8 +--- 2 files changed, 62 insertions(+), 52 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index d330d783de..10ddf0e24f 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -96,8 +96,8 @@ const int buttonMappings[14] = { SDLK_DOWN, //DOWN SDLK_LEFT, //LEFT SDLK_RIGHT, //RIGHT - SDLK_m, //MENU - SDLK_BACKSPACE, //BACK + SDLK_m, //MENU + SDLK_BACKSPACE, //BACK }; void SimulateGamepad(const uint8 *keys, InputState *input) { @@ -112,21 +112,21 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { } if (keys[SDLK_i]) - input->pad_lstick_y=1; + input->pad_lstick_y=1; else if (keys[SDLK_k]) - input->pad_lstick_y=-1; + input->pad_lstick_y=-1; if (keys[SDLK_j]) - input->pad_lstick_x=-1; + input->pad_lstick_x=-1; else if (keys[SDLK_l]) - input->pad_lstick_x=1; + input->pad_lstick_x=1; if (keys[SDLK_KP8]) - input->pad_rstick_y=1; + input->pad_rstick_y=1; else if (keys[SDLK_KP2]) - input->pad_rstick_y=-1; + input->pad_rstick_y=-1; if (keys[SDLK_KP4]) - input->pad_rstick_x=-1; + input->pad_rstick_x=-1; else if (keys[SDLK_KP6]) - input->pad_rstick_x=1; + input->pad_rstick_x=1; } extern void mixaudio(void *userdata, Uint8 *stream, int len) { @@ -141,34 +141,48 @@ int main(int argc, char *argv[]) { dp_xres = 1280; dp_yres = 800; - */ + */ std::string app_name; std::string app_name_nice; float zoom = 1.0f; + bool tablet = false; const char *zoomenv = getenv("ZOOM"); + const char *tabletenv = getenv("TABLET"); if (zoomenv) { zoom = atof(zoomenv); } + if (tabletenv) + tablet = true; - bool landscape; - NativeGetAppInfo(&app_name, &app_name_nice, &landscape); + bool landscape; + NativeGetAppInfo(&app_name, &app_name_nice, &landscape); - if (landscape) { - pixel_xres = 800 * zoom; - pixel_yres = 480 * zoom; + if (landscape) { + if (tablet) { + pixel_xres = 1280 * zoom; + pixel_yres = 800 * zoom; + } else { + pixel_xres = 800 * zoom; + pixel_yres = 480 * zoom; + } } else { - // PC development hack for more space + // PC development hack for more space //pixel_xres = 1580 * zoom; //pixel_yres = 1000 * zoom; - pixel_xres = 480 * zoom; - pixel_yres = 800 * zoom; + if (tablet) { + pixel_xres = 800 * zoom; + pixel_yres = 1280 * zoom; + } else { + pixel_xres = 800 * zoom; + pixel_yres = 1280 * zoom; + } } net::Init(); #ifdef __APPLE__ - // Make sure to request a somewhat modern GL context at least - the + // Make sure to request a somewhat modern GL context at least - the // latest supported by MacOSX (really, really sad...) // Requires SDL 2.0 (which is even more sad, as that hasn't been released yet) //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); @@ -217,35 +231,35 @@ int main(int argc, char *argv[]) { PathAppend(path, (app_name + "\\").c_str()); #else // Mac / Linux - char path[512]; + char path[512]; const char *the_path = getenv("HOME"); if (!the_path) { struct passwd* pwd = getpwuid(getuid()); if (pwd) the_path = pwd->pw_dir; } - strcpy(path, the_path); - if (path[strlen(path)-1] != '/') - strcat(path, "/"); + strcpy(path, the_path); + if (path[strlen(path)-1] != '/') + strcat(path, "/"); #endif #ifdef _WIN32 - NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE"); #else NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); #endif - float density = 1.0f; - dp_xres = (float)pixel_xres * density / zoom; - dp_yres = (float)pixel_yres * density / zoom; + float density = 1.0f; + dp_xres = (float)pixel_xres * density / zoom; + dp_yres = (float)pixel_yres * density / zoom; NativeInitGraphics(); - float dp_xscale = (float)dp_xres / pixel_xres; - float dp_yscale = (float)dp_yres / pixel_yres; + float dp_xscale = (float)dp_xres / pixel_xres; + float dp_yscale = (float)dp_yres / pixel_yres; - printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); - printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); + printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); + printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); SDL_AudioSpec fmt; fmt.freq = 44100; @@ -266,16 +280,16 @@ int main(int argc, char *argv[]) { InputState input_state; int framecount = 0; bool nextFrameMD = 0; - float t = 0; + float t = 0; while (true) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; int quitRequested = 0; - - SDL_Event event; + + SDL_Event event; while (SDL_PollEvent(&event)) { - float mx = event.motion.x * dp_xscale; - float my = event.motion.y * dp_yscale; + float mx = event.motion.x * dp_xscale; + float my = event.motion.y * dp_yscale; if (event.type == SDL_QUIT) { quitRequested = 1; @@ -286,20 +300,20 @@ int main(int argc, char *argv[]) { } else if (event.type == SDL_MOUSEMOTION) { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; - NativeTouch(0, mx, my, 0, TOUCH_MOVE); + NativeTouch(0, mx, my, 0, TOUCH_MOVE); } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { //input_state.mouse_buttons_down = 1; input_state.pointer_down[0] = true; nextFrameMD = true; - NativeTouch(0, mx, my, 0, TOUCH_DOWN); + NativeTouch(0, mx, my, 0, TOUCH_DOWN); } } else if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { input_state.pointer_down[0] = false; nextFrameMD = false; //input_state.mouse_buttons_up = 1; - NativeTouch(0, mx, my, 0, TOUCH_UP); + NativeTouch(0, mx, my, 0, TOUCH_UP); } } } @@ -315,12 +329,12 @@ int main(int argc, char *argv[]) { NativeUpdate(input_state); NativeRender(); - EndInputState(&input_state); + EndInputState(&input_state); if (framecount % 60 == 0) { - // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. + // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } - + SDL_GL_SwapBuffers(); // Simple frame rate limiting @@ -333,7 +347,7 @@ int main(int argc, char *argv[]) { framecount++; } // Faster exit, thanks to the OS. Remove this if you want to debug shutdown - // The speed difference is only really noticable on Linux. On Windows you do notice it though + // The speed difference is only really noticable on Linux. On Windows you do notice it though // exit(0); NativeShutdownGraphics(); @@ -341,7 +355,7 @@ int main(int argc, char *argv[]) { NativeShutdown(); SDL_CloseAudio(); SDL_Quit(); - net::Shutdown(); - exit(0); + net::Shutdown(); + exit(0); return 0; } diff --git a/ui/ui.cpp b/ui/ui.cpp index 4203756b99..315a10781f 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -262,9 +262,7 @@ UIList::UIList() } void UIList::pointerDown(int pointer, float x, float y) { - // printf("PointerDown %f %f\n", x, y); - - // Instantly halt if intertia-scrolling + // Instantly halt on pointerDown if inertia-scrolling scrolling = false; inertiaY = 0.0f; @@ -276,8 +274,6 @@ void UIList::pointerDown(int pointer, float x, float y) { const int holdFrames = 6; void UIList::pointerMove(int pointer, float x, float y) { - // printf("PointerMove %f %f\n", x, y); - float deltaY = y - lastY; movedDistanceY += fabsf(deltaY); @@ -385,7 +381,7 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { selected == -1 && UIRegionHit(k, x, item_y, w, itemHeight, 0)) { selected = i; - } else if (scrolling && canScroll) { + } else if (scrolling) { selected = -1; } } From 58e9b9ffe8d01e5649c193021fd1b4b9ac47d72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Oct 2012 13:23:16 +0100 Subject: [PATCH 0129/1445] Reindent native/file --- file/chunk_file.cpp | 378 ++++++++++++++++++++++---------------------- file/chunk_file.h | 78 ++++----- file/dialog.cpp | 88 +++++------ file/easy_file.cpp | 100 ++++++------ file/easy_file.h | 64 ++++---- file/file_util.cpp | 170 ++++++++++---------- file/file_util.h | 4 +- file/zip_read.cpp | 168 ++++++++++---------- file/zip_read.h | 44 +++--- 9 files changed, 547 insertions(+), 547 deletions(-) diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index 09329d3a0d..c162f2913a 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -5,278 +5,278 @@ //#define CHUNKDEBUG ChunkFile::ChunkFile(const char *filename, bool _read) { - data=0; - fn = filename; - fastMode=false; - numLevels=0; - read=_read; - pos=0; - didFail=false; + data=0; + fn = filename; + fastMode=false; + numLevels=0; + read=_read; + pos=0; + didFail=false; - fastMode = read ? true : false; + fastMode = read ? true : false; - if (fastMode) { - size_t size; - data = (uint8_t *)VFSReadFile(filename, &size); - if (!data) { - ELOG("Chunkfile fail: %s", filename); - didFail = true; - return; - } - eof = size; - return; - } + if (fastMode) { + size_t size; + data = (uint8_t *)VFSReadFile(filename, &size); + if (!data) { + ELOG("Chunkfile fail: %s", filename); + didFail = true; + return; + } + eof = size; + return; + } - if (file.open(filename, FILE_WRITE)) { - didFail=false; - eof=file.fileSize(); - } else { - didFail=true; - return; - } + if (file.open(filename, FILE_WRITE)) { + didFail=false; + eof=file.fileSize(); + } else { + didFail=true; + return; + } } ChunkFile::~ChunkFile() { - if (fastMode && data) - delete [] data; - else - file.close(); + if (fastMode && data) + delete [] data; + else + file.close(); } int ChunkFile::readInt() { - if (pos>8, id>>16, id>>24); + ILOG("Couldn't find %c%c%c%c", id, id>>8, id>>16, id>>24); #endif - stack[numLevels]=temp; - seekTo(stack[numLevels].parentStartLocation); - return false; - } + stack[numLevels]=temp; + seekTo(stack[numLevels].parentStartLocation); + return false; + } - //descend into it - //pos was set inside the loop above - eof = stack[numLevels].startLocation + stack[numLevels].length; - numLevels++; + //descend into it + //pos was set inside the loop above + eof = stack[numLevels].startLocation + stack[numLevels].length; + numLevels++; #ifdef CHUNKDEBUG - ILOG("Descended into %c%c%c%c", id, id>>8, id>>16, id>>24); + ILOG("Descended into %c%c%c%c", id, id>>8, id>>16, id>>24); #endif - return true; - } else { -#ifndef DEMO_VERSION //if this is missing.. heheh - //write a chunk id, and prepare for filling in length later - writeInt(id); - writeInt(0); //will be filled in by Ascend - stack[numLevels].startLocation=pos; - numLevels++; - return true; + return true; + } else { +#ifndef DEMO_VERSION //if this is missing.. heheh + //write a chunk id, and prepare for filling in length later + writeInt(id); + writeInt(0); //will be filled in by Ascend + stack[numLevels].startLocation=pos; + numLevels++; + return true; #else - return true; + return true; #endif - } + } } void ChunkFile::seekTo(int _pos) { - if (!fastMode) - file.seekBeg(_pos); - pos=_pos; + if (!fastMode) + file.seekBeg(_pos); + pos=_pos; } //let's ascend out void ChunkFile::ascend() { - if (read) { - //ascend, and restore information - numLevels--; - seekTo(stack[numLevels].parentStartLocation); - eof = stack[numLevels].parentEOF; + if (read) { + //ascend, and restore information + numLevels--; + seekTo(stack[numLevels].parentStartLocation); + eof = stack[numLevels].parentEOF; #ifdef CHUNKDEBUG - int id = stack[numLevels].ID; - ILOG("Ascended out of %c%c%c%c", id, id>>8, id>>16, id>>24); + int id = stack[numLevels].ID; + ILOG("Ascended out of %c%c%c%c", id, id>>8, id>>16, id>>24); #endif - } else { - numLevels--; - //now fill in the written length automatically - int posNow = pos; - seekTo(stack[numLevels].startLocation - 4); - writeInt(posNow-stack[numLevels].startLocation); - seekTo(posNow); - } + } else { + numLevels--; + //now fill in the written length automatically + int posNow = pos; + seekTo(stack[numLevels].startLocation - 4); + writeInt(posNow-stack[numLevels].startLocation); + seekTo(posNow); + } } //read a block void ChunkFile::readData(void *what, int count) { - if (fastMode) - memcpy(what, data + pos, count); - else - file.read(what,count); + if (fastMode) + memcpy(what, data + pos, count); + else + file.read(what,count); - pos+=count; - char temp[4]; //discarded - count &= 3; - if (count) { - count=4-count; - if (!fastMode) - file.read(temp,count); - pos+=count; - } + pos+=count; + char temp[4]; //discarded + count &= 3; + if (count) { + count=4-count; + if (!fastMode) + file.read(temp,count); + pos+=count; + } } //write a block void ChunkFile::writeData(const void *what, int count) { - file.write(what, count); - pos+=count; - char temp[5]={0,0,0,0,0}; - count &= 3; - if (count) - { - count=4-count; - file.write(temp,count); - pos+=count; - } + file.write(what, count); + pos+=count; + char temp[5]={0,0,0,0,0}; + count &= 3; + if (count) + { + count=4-count; + file.write(temp,count); + pos+=count; + } } /* void ChunkFile::writeWString(String str) { - wchar_t *text; - int len=str.length(); + wchar_t *text; + int len=str.length(); #ifdef UNICODE #error - text = str.getPointer(); + text = str.getPointer(); #else - text = new wchar_t[len+1]; - str.toUnicode(text); + text = new wchar_t[len+1]; + str.toUnicode(text); #endif - writeInt(len); - writeData((char *)text, len * sizeof(wchar_t)); + writeInt(len); + writeData((char *)text, len * sizeof(wchar_t)); #ifndef UNICODE - delete [] text; + delete [] text; #endif } */ void ChunkFile::writeWString(const std::string &str) { - unsigned short *text; - int len=str.length(); + unsigned short *text; + int len=str.length(); #ifdef UNICODE #error - text = str.c_str(); + text = str.c_str(); #else - text = new unsigned short[len+1]; - for (int i=0; i 255 ? ' ' : src[i]; - } - return str; + std::string str; + str.resize(len); + for (int i=0; i 255 ? ' ' : src[i]; + } + return str; } std::string ChunkFile::readWString() { - int len=readInt(); - uint16_t *text = new uint16_t[len+1]; - readData((char *)text, len*sizeof(uint16_t)); - text[len] = 0; - std::string temp = fromUnicode(text, len); - delete [] text; - return temp; + int len=readInt(); + uint16_t *text = new uint16_t[len+1]; + readData((char *)text, len*sizeof(uint16_t)); + text[len] = 0; + std::string temp = fromUnicode(text, len); + delete [] text; + return temp; } void ChunkFile::writeString(const std::string &str) { - uint16_t *text; - int len = str.size(); - text=new uint16_t[len+1]; - toUnicode(str, text); - writeInt(len); - writeData((char *)text,len*sizeof(uint16_t)); - delete [] text; + uint16_t *text; + int len = str.size(); + text=new uint16_t[len+1]; + toUnicode(str, text); + writeInt(len); + writeData((char *)text,len*sizeof(uint16_t)); + delete [] text; } std::string ChunkFile::readString() { - int len=readInt(); - uint16_t *text = new uint16_t[len+1]; - readData((char *)text,len*sizeof(uint16_t)); - text[len]=0; - std::string temp = fromUnicode(text, len); - delete [] text; - return temp; + int len=readInt(); + uint16_t *text = new uint16_t[len+1]; + readData((char *)text,len*sizeof(uint16_t)); + text[len]=0; + std::string temp = fromUnicode(text, len); + delete [] text; + return temp; } int ChunkFile::getCurrentChunkSize() { - if (numLevels) - return stack[numLevels-1].length; - else - return 0; + if (numLevels) + return stack[numLevels-1].length; + else + return 0; } diff --git a/file/chunk_file.h b/file/chunk_file.h index 5da5ec747d..a4065d0676 100644 --- a/file/chunk_file.h +++ b/file/chunk_file.h @@ -14,54 +14,54 @@ #include "file/easy_file.h" inline uint32 flipID(uint32 id) { - return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000); + return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000); } class ChunkFile { public: - ChunkFile(const char *filename, bool _read); - ~ChunkFile(); + ChunkFile(const char *filename, bool _read); + ~ChunkFile(); - bool descend(uint32 id); - void ascend(); + bool descend(uint32 id); + void ascend(); - int readInt(); - void readInt(int &i) {i = readInt();} - void readData(void *data, int count); - // String readWString(); - std::string readWString(); + int readInt(); + void readInt(int &i) {i = readInt();} + void readData(void *data, int count); + // String readWString(); + std::string readWString(); - void writeString(const std::string &str); - std::string readString(); + void writeString(const std::string &str); + std::string readString(); - void writeInt(int i); - //void writeWString(String str); - void writeWString(const std::string &str); - void writeData(const void *data, int count); + void writeInt(int i); + //void writeWString(String str); + void writeWString(const std::string &str); + void writeData(const void *data, int count); - int getCurrentChunkSize(); - bool failed() const { return didFail; } - std::string filename() const { return fn; } + int getCurrentChunkSize(); + bool failed() const { return didFail; } + std::string filename() const { return fn; } private: - std::string fn; - LAMEFile file; - struct ChunkInfo { - int startLocation; - int parentStartLocation; - int parentEOF; - unsigned int ID; - int length; - }; - ChunkInfo stack[8]; - int numLevels; - - uint8_t *data; - int pos, eof; - bool fastMode; - bool read; - bool didFail; - - void seekTo(int _pos); - int getPos() const {return pos;} + std::string fn; + LAMEFile file; + struct ChunkInfo { + int startLocation; + int parentStartLocation; + int parentEOF; + unsigned int ID; + int length; + }; + ChunkInfo stack[8]; + int numLevels; + + uint8_t *data; + int pos, eof; + bool fastMode; + bool read; + bool didFail; + + void seekTo(int _pos); + int getPos() const {return pos;} }; diff --git a/file/dialog.cpp b/file/dialog.cpp index 6a41e81be6..70864cc3e7 100644 --- a/file/dialog.cpp +++ b/file/dialog.cpp @@ -10,55 +10,55 @@ // An false returned means cancel; bool OpenFileDialog(const char *title, const char *extension, std::string *filename) { - OPENFILENAME of; - memset(&of, 0, sizeof(of)); - char buffer[512] = {0}; - of.lStructSize = sizeof(OPENFILENAME); - of.hInstance = 0; - of.hwndOwner = GetActiveWindow(); + OPENFILENAME of; + memset(&of, 0, sizeof(of)); + char buffer[512] = {0}; + of.lStructSize = sizeof(OPENFILENAME); + of.hInstance = 0; + of.hwndOwner = GetActiveWindow(); - // These weird strings with zeroes in them can't be dealt with using normal string - // functions, so here we go - evil hackery. - char filter[256] = "XXX files\0*.XXX\0\0"; - memcpy(filter, extension, 3); - memcpy(filter + 12, extension, 3); - of.lpstrFilter = filter; + // These weird strings with zeroes in them can't be dealt with using normal string + // functions, so here we go - evil hackery. + char filter[256] = "XXX files\0*.XXX\0\0"; + memcpy(filter, extension, 3); + memcpy(filter + 12, extension, 3); + of.lpstrFilter = filter; - of.lpstrDefExt = extension; - of.lpstrFile = buffer; - of.nMaxFile = 511; + of.lpstrDefExt = extension; + of.lpstrFile = buffer; + of.nMaxFile = 511; - of.Flags = OFN_FILEMUSTEXIST; - if (!GetOpenFileName(&of)) return false; - *filename = of.lpstrFile; - return true; + of.Flags = OFN_FILEMUSTEXIST; + if (!GetOpenFileName(&of)) return false; + *filename = of.lpstrFile; + return true; } bool SaveFileDialog(const char *title, const char *extension, std::string *filename) { - OPENFILENAME of; - memset(&of, 0, sizeof(of)); - char buffer[512] = {0}; - of.lStructSize = sizeof(OPENFILENAME); - of.hInstance = 0; - of.hwndOwner = GetActiveWindow(); + OPENFILENAME of; + memset(&of, 0, sizeof(of)); + char buffer[512] = {0}; + of.lStructSize = sizeof(OPENFILENAME); + of.hInstance = 0; + of.hwndOwner = GetActiveWindow(); - // These weird strings with zeroes in them can't be dealt with using normal string - // functions, so here we go - evil hackery. - char filter[256] = "XXX files\0*.XXX\0\0"; - memcpy(filter, extension, 3); - memcpy(filter + 12, extension, 3); - of.lpstrFilter = filter; + // These weird strings with zeroes in them can't be dealt with using normal string + // functions, so here we go - evil hackery. + char filter[256] = "XXX files\0*.XXX\0\0"; + memcpy(filter, extension, 3); + memcpy(filter + 12, extension, 3); + of.lpstrFilter = filter; - of.lpstrDefExt = extension; - of.lpstrFile = buffer; - of.nMaxFile = 511; + of.lpstrDefExt = extension; + of.lpstrFile = buffer; + of.nMaxFile = 511; - of.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; - if (!GetSaveFileName(&of)) - return false; - *filename = of.lpstrFile; - return true; + of.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; + if (!GetSaveFileName(&of)) + return false; + *filename = of.lpstrFile; + return true; } #else @@ -69,14 +69,14 @@ bool SaveFileDialog(const char *title, const char *extension, std::string *filen bool OpenFileDialog(const char *title, const char *extension, std::string *filename) { - ELOG("Asked for OpenFileDialog, not present on this platform."); - return false; + ELOG("Asked for OpenFileDialog, not present on this platform."); + return false; } bool SaveFileDialog(const char *title, const char *extension, std::string *filename) { - ELOG("Asked for SaveFileDialog, not present on this platform."); - return false; + ELOG("Asked for SaveFileDialog, not present on this platform."); + return false; } -#endif \ No newline at end of file +#endif diff --git a/file/easy_file.cpp b/file/easy_file.cpp index c3259ca3f3..30851dff43 100644 --- a/file/easy_file.cpp +++ b/file/easy_file.cpp @@ -4,87 +4,87 @@ #include "file/easy_file.h" LAMEFile::LAMEFile() : file_(NULL) { - isOpen = false; + isOpen = false; } LAMEFile::~LAMEFile() { } bool LAMEFile::open(const char *filename, eFileMode mode) { - file_ = fopen(filename, mode == FILE_READ ? "rb" : "wb"); + file_ = fopen(filename, mode == FILE_READ ? "rb" : "wb"); - if (!file_) { - isOpen = false; - } else { - isOpen = true; - if (mode == FILE_READ) { - fseek(file_, 0, SEEK_END); - size_ = ftell(file_); - fseek(file_, 0, SEEK_SET); - } - } - return isOpen; + if (!file_) { + isOpen = false; + } else { + isOpen = true; + if (mode == FILE_READ) { + fseek(file_, 0, SEEK_END); + size_ = ftell(file_); + fseek(file_, 0, SEEK_SET); + } + } + return isOpen; } void LAMEFile::close() { - if (isOpen) { - //close the file and reset variables - fclose(file_); - file_ = NULL; - isOpen=false; - } + if (isOpen) { + //close the file and reset variables + fclose(file_); + file_ = NULL; + isOpen=false; + } } int LAMEFile::fileSize() { - if (!isOpen) //of course - return 0; - else - return size_; + if (!isOpen) //of course + return 0; + else + return size_; } std::string LAMEFile::readAll() { - std::string s; - size_t size = fileSize(); - s.resize(size); - read(&s[0], size); - return s; + std::string s; + size_t size = fileSize(); + s.resize(size); + read(&s[0], size); + return s; } int LAMEFile::write(const void *data, int size) { - if (isOpen) { - return fwrite(data, 1, size, file_); //we return the number of bytes that actually got written - } else { - return 0; - } + if (isOpen) { + return fwrite(data, 1, size, file_); //we return the number of bytes that actually got written + } else { + return 0; + } } int LAMEFile::read(void *data, int size) { - if (isOpen) { - return fread(data, 1, size, file_); - } else { - return 0; - } + if (isOpen) { + return fread(data, 1, size, file_); + } else { + return 0; + } } int LAMEFile::readInt() { - int temp; - if (read(&temp, sizeof(int))) - return temp; - else - return 0; + int temp; + if (read(&temp, sizeof(int))) + return temp; + else + return 0; } void LAMEFile::writeInt(int i) { - write(&i, sizeof(int)); + write(&i, sizeof(int)); } char LAMEFile::readChar() { - char temp; - if (read(&temp, sizeof(char))) - return temp; - else - return 0; + char temp; + if (read(&temp, sizeof(char))) + return temp; + else + return 0; } void LAMEFile::writeChar(char i) { - write(&i,sizeof(char)); + write(&i,sizeof(char)); } diff --git a/file/easy_file.h b/file/easy_file.h index 9eed47abd7..b7114050bd 100644 --- a/file/easy_file.h +++ b/file/easy_file.h @@ -11,48 +11,48 @@ // Raw file paths, does not go through VFS. enum eFileMode { - FILE_READ=5, - FILE_WRITE=6 + FILE_READ=5, + FILE_WRITE=6 }; // TODO: Rename. class LAMEFile { public: - LAMEFile(); - virtual ~LAMEFile(); + LAMEFile(); + virtual ~LAMEFile(); - bool open(const char *filename, eFileMode mode); - bool open(std::string filename, eFileMode mode) { - return open(filename.c_str(), mode); - } - void close(); + bool open(const char *filename, eFileMode mode); + bool open(std::string filename, eFileMode mode) { + return open(filename.c_str(), mode); + } + void close(); - void writeInt(int i); - void writeChar(char i); - int write(const void *data, int size); - void write(const std::string &str) { - write((void *)str.data(), str.size()); - } + void writeInt(int i); + void writeChar(char i); + int write(const void *data, int size); + void write(const std::string &str) { + write((void *)str.data(), str.size()); + } - int readInt(); - char readChar(); - int read(void *data, int size); + int readInt(); + char readChar(); + int read(void *data, int size); - std::string readAll(); + std::string readAll(); - int fileSize(); + int fileSize(); - void seekBeg(int pos) { - if (isOpen) fseek(file_,pos,SEEK_SET); - } - void seekEnd(int pos) { - if (isOpen) fseek(file_,pos,SEEK_END); - } - void seekCurrent(int pos) { - if (isOpen) fseek(file_,pos,SEEK_CUR); - } + void seekBeg(int pos) { + if (isOpen) fseek(file_,pos,SEEK_SET); + } + void seekEnd(int pos) { + if (isOpen) fseek(file_,pos,SEEK_END); + } + void seekCurrent(int pos) { + if (isOpen) fseek(file_,pos,SEEK_CUR); + } private: - FILE *file_; - bool isOpen; - int size_; + FILE *file_; + bool isOpen; + int size_; }; diff --git a/file/file_util.cpp b/file/file_util.cpp index 2cc447f087..bbb78b1769 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -14,47 +14,47 @@ bool writeStringToFile(bool text_file, const std::string &str, const char *filename) { - FILE *f = fopen(filename, text_file ? "w" : "wb"); - if (!f) - return false; - size_t len = str.size(); - if (len != fwrite(str.data(), 1, str.size(), f)) - { - fclose(f); - return false; - } - fclose(f); - return true; + FILE *f = fopen(filename, text_file ? "w" : "wb"); + if (!f) + return false; + size_t len = str.size(); + if (len != fwrite(str.data(), 1, str.size(), f)) + { + fclose(f); + return false; + } + fclose(f); + return true; } uint64_t GetSize(FILE *f) { - // can't use off_t here because it can be 32-bit - uint64_t pos = ftell(f); - if (fseek(f, 0, SEEK_END) != 0) { - return 0; - } - uint64_t size = ftell(f); - // Reset the seek position to where it was when we started. - if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) { - // Should error here - return 0; - } - return size; + // can't use off_t here because it can be 32-bit + uint64_t pos = ftell(f); + if (fseek(f, 0, SEEK_END) != 0) { + return 0; + } + uint64_t size = ftell(f); + // Reset the seek position to where it was when we started. + if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) { + // Should error here + return 0; + } + return size; } bool ReadFileToString(bool text_file, const char *filename, std::string &str) { - FILE *f = fopen(filename, text_file ? "r" : "rb"); - if (!f) - return false; - size_t len = (size_t)GetSize(f); - char *buf = new char[len + 1]; - buf[fread(buf, 1, len, f)] = 0; - str = std::string(buf, len); - fclose(f); - delete [] buf; - return true; + FILE *f = fopen(filename, text_file ? "r" : "rb"); + if (!f) + return false; + size_t len = (size_t)GetSize(f); + char *buf = new char[len + 1]; + buf[fread(buf, 1, len, f)] = 0; + str = std::string(buf, len); + fclose(f); + delete [] buf; + return true; } #define DIR_SEP "/" @@ -115,70 +115,70 @@ bool isDirectory(const std::string &filename) } size_t getFilesInDir(const char *directory, std::vector *files) { - size_t foundEntries = 0; + size_t foundEntries = 0; #ifdef _WIN32 - // Find the first file in the directory. - WIN32_FIND_DATA ffd; + // Find the first file in the directory. + WIN32_FIND_DATA ffd; #ifdef UNICODE - HANDLE hFind = FindFirstFile((std::wstring(directory) + "\\*").c_str(), &ffd); + HANDLE hFind = FindFirstFile((std::wstring(directory) + "\\*").c_str(), &ffd); #else - HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd); + HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd); #endif - if (hFind == INVALID_HANDLE_VALUE) { - FindClose(hFind); - return 0; - } - // windows loop - do - { - const std::string virtualName(ffd.cFileName); + if (hFind == INVALID_HANDLE_VALUE) { + FindClose(hFind); + return 0; + } + // windows loop + do + { + const std::string virtualName(ffd.cFileName); #else - struct dirent dirent, *result = NULL; + struct dirent dirent, *result = NULL; - DIR *dirp = opendir(directory); - if (!dirp) - return 0; + DIR *dirp = opendir(directory); + if (!dirp) + return 0; - // non windows loop - while (!readdir_r(dirp, &dirent, &result) && result) - { - const std::string virtualName(result->d_name); + // non windows loop + while (!readdir_r(dirp, &dirent, &result) && result) + { + const std::string virtualName(result->d_name); #endif - // check for "." and ".." - if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || - ((virtualName[0] == '.') && (virtualName[1] == '.') && - (virtualName[2] == '\0'))) - continue; + // check for "." and ".." + if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || + ((virtualName[0] == '.') && (virtualName[1] == '.') && + (virtualName[2] == '\0'))) + continue; // Remove dotfiles (should be made optional?) if (virtualName[0] == '.') continue; - FileInfo info; - info.name = virtualName; - info.fullName = std::string(directory) + "/" + virtualName; - info.isDirectory = isDirectory(info.fullName); - files->push_back(info); + FileInfo info; + info.name = virtualName; + info.fullName = std::string(directory) + "/" + virtualName; + info.isDirectory = isDirectory(info.fullName); + files->push_back(info); #ifdef _WIN32 - } while (FindNextFile(hFind, &ffd) != 0); - FindClose(hFind); + } while (FindNextFile(hFind, &ffd) != 0); + FindClose(hFind); #else - } - closedir(dirp); + } + closedir(dirp); #endif - return foundEntries; + return foundEntries; } void deleteFile(const char *file) { #ifdef _WIN32 - if (!DeleteFile(file)) { - ELOG("Error deleting %s: %i", file, GetLastError()); - } + if (!DeleteFile(file)) { + ELOG("Error deleting %s: %i", file, GetLastError()); + } #else - int err = unlink(file); - if (err) { - ELOG("Error unlinking %s: %i", file, err); - } + int err = unlink(file); + if (err) { + ELOG("Error unlinking %s: %i", file, err); + } #endif } #endif @@ -187,18 +187,18 @@ std::string getDir(const std::string &path) { if (path == "/") return path; - int n = path.size() - 1; - while (n >= 0 && path[n] != '\\' && path[n] != '/') - n--; - std::string cutpath = path.substr(0, n); - for (size_t i = 0; i < cutpath.size(); i++) - { - if (cutpath[i] == '\\') cutpath[i] = '/'; - } + int n = path.size() - 1; + while (n >= 0 && path[n] != '\\' && path[n] != '/') + n--; + std::string cutpath = path.substr(0, n); + for (size_t i = 0; i < cutpath.size(); i++) + { + if (cutpath[i] == '\\') cutpath[i] = '/'; + } #ifndef _WIN32 if (!cutpath.size()) { return "/"; } #endif - return cutpath; + return cutpath; } diff --git a/file/file_util.h b/file/file_util.h index e269b08151..4e4f71c926 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -11,9 +11,9 @@ bool readFileToString(bool text_file, const char *filename, std::string &str); struct FileInfo { - std::string name; + std::string name; std::string fullName; - bool isDirectory; + bool isDirectory; }; size_t getFilesInDir(const char *directory, std::vector *files); diff --git a/file/zip_read.cpp b/file/zip_read.cpp index c5f436901a..27d3a300e4 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -10,128 +10,128 @@ #ifndef _WIN32 uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { - // Figure out the file size first. - struct zip_stat zstat; - zip_stat(archive, filename, ZIP_FL_NOCASE, &zstat); + // Figure out the file size first. + struct zip_stat zstat; + zip_stat(archive, filename, ZIP_FL_NOCASE, &zstat); - uint8_t *contents = new uint8_t[zstat.size + 1]; + uint8_t *contents = new uint8_t[zstat.size + 1]; - zip_file *file = zip_fopen(archive, filename, 0); - if (!file) { - ELOG("Error opening %s from ZIP", filename); - delete [] contents; - return 0; - } - zip_fread(file, contents, zstat.size); - zip_fclose(file); - contents[zstat.size] = 0; + zip_file *file = zip_fopen(archive, filename, 0); + if (!file) { + ELOG("Error opening %s from ZIP", filename); + delete [] contents; + return 0; + } + zip_fread(file, contents, zstat.size); + zip_fclose(file); + contents[zstat.size] = 0; - *size = zstat.size; - return contents; + *size = zstat.size; + return contents; } #endif // The return is non-const because - why not? uint8_t *ReadLocalFile(const char *filename, size_t *size) { - FILE *file = fopen(filename, "rb"); - if (!file) { - return 0; - } - fseek(file, 0, SEEK_END); - size_t f_size = ftell(file); - fseek(file, 0, SEEK_SET); - uint8_t *contents = new uint8_t[f_size+1]; - fread(contents, 1, f_size, file); - fclose(file); - contents[f_size] = 0; - *size = f_size; - return contents; + FILE *file = fopen(filename, "rb"); + if (!file) { + return 0; + } + fseek(file, 0, SEEK_END); + size_t f_size = ftell(file); + fseek(file, 0, SEEK_SET); + uint8_t *contents = new uint8_t[f_size+1]; + fread(contents, 1, f_size, file); + fclose(file); + contents[f_size] = 0; + *size = f_size; + return contents; } #ifndef _WIN32 ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { - zip_file_ = zip_open(zip_file, 0, NULL); - strcpy(in_zip_path_, in_zip_path); - if (!zip_file_) { - ELOG("Failed to open %s as a zip file", zip_file); - } - // This is not really necessary. - int numFiles = zip_get_num_files(zip_file_); - for (int i = 0; i < numFiles; i++) { - const char* name = zip_get_name(zip_file_, i, 0); - if (name == NULL) { - ELOG("Error reading zip file name at index %i : %s", i, zip_strerror(zip_file_)); - return; - } - // ILOG("File %i : %s\n", i, name); - } + zip_file_ = zip_open(zip_file, 0, NULL); + strcpy(in_zip_path_, in_zip_path); + if (!zip_file_) { + ELOG("Failed to open %s as a zip file", zip_file); + } + // This is not really necessary. + int numFiles = zip_get_num_files(zip_file_); + for (int i = 0; i < numFiles; i++) { + const char* name = zip_get_name(zip_file_, i, 0); + if (name == NULL) { + ELOG("Error reading zip file name at index %i : %s", i, zip_strerror(zip_file_)); + return; + } + // ILOG("File %i : %s\n", i, name); + } } ZipAssetReader::~ZipAssetReader() { - zip_close(zip_file_); + zip_close(zip_file_); } uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { - char temp_path[256]; - strcpy(temp_path, in_zip_path_); - strcat(temp_path, path); - return ReadFromZip(zip_file_, temp_path, size); + char temp_path[256]; + strcpy(temp_path, in_zip_path_); + strcat(temp_path, path); + return ReadFromZip(zip_file_, temp_path, size); } #endif uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { - char new_path[256] = {0}; - // Check if it already contains the path - if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { - } - else { - strcpy(new_path, path_); - } - strcat(new_path, path); - // ILOG("New path: %s", new_path); - return ReadLocalFile(new_path, size); + char new_path[256] = {0}; + // Check if it already contains the path + if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { + } + else { + strcpy(new_path, path_); + } + strcat(new_path, path); + // ILOG("New path: %s", new_path); + return ReadLocalFile(new_path, size); } struct VFSEntry { - const char *prefix; - AssetReader *reader; + const char *prefix; + AssetReader *reader; }; static VFSEntry entries[16]; static int num_entries = 0; void VFSRegister(const char *prefix, AssetReader *reader) { - entries[num_entries].prefix = prefix; - entries[num_entries].reader = reader; - ILOG("Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); - num_entries++; + entries[num_entries].prefix = prefix; + entries[num_entries].reader = reader; + ILOG("Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); + num_entries++; } void VFSShutdown() { - for (int i = 0; i < num_entries; i++) { - delete entries[i].reader; - } - num_entries = 0; + for (int i = 0; i < num_entries; i++) { + delete entries[i].reader; + } + num_entries = 0; } uint8_t *VFSReadFile(const char *filename, size_t *size) { - int fn_len = strlen(filename); - for (int i = 0; i < num_entries; i++) { - int prefix_len = strlen(entries[i].prefix); - if (prefix_len >= fn_len) continue; - if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { - // ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); - uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); - if (data) - return data; - else - continue; - // Else try the other registered file systems. - } - } - ELOG("Missing filesystem for %s", filename); - return 0; + int fn_len = strlen(filename); + for (int i = 0; i < num_entries; i++) { + int prefix_len = strlen(entries[i].prefix); + if (prefix_len >= fn_len) continue; + if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { + // ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); + uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); + if (data) + return data; + else + continue; + // Else try the other registered file systems. + } + } + ELOG("Missing filesystem for %s", filename); + return 0; } diff --git a/file/zip_read.h b/file/zip_read.h index e0309d8a3a..2c85ec4504 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -15,42 +15,42 @@ uint8_t *ReadLocalFile(const char *filename, size_t *size); class AssetReader { public: - virtual ~AssetReader() {} - // use delete[] - virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; - virtual std::string toString() const = 0; + virtual ~AssetReader() {} + // use delete[] + virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; + virtual std::string toString() const = 0; }; #ifndef _WIN32 uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size); class ZipAssetReader : public AssetReader { public: - ZipAssetReader(const char *zip_file, const char *in_zip_path); - ~ZipAssetReader(); - // use delete[] - virtual uint8_t *ReadAsset(const char *path, size_t *size); - virtual std::string toString() const { - return in_zip_path_; - } + ZipAssetReader(const char *zip_file, const char *in_zip_path); + ~ZipAssetReader(); + // use delete[] + virtual uint8_t *ReadAsset(const char *path, size_t *size); + virtual std::string toString() const { + return in_zip_path_; + } private: - zip *zip_file_; - char in_zip_path_[256]; + zip *zip_file_; + char in_zip_path_[256]; }; #endif class DirectoryAssetReader : public AssetReader { public: - DirectoryAssetReader(const char *path) { - strcpy(path_, path); - } - // use delete[] - virtual uint8_t *ReadAsset(const char *path, size_t *size); - virtual std::string toString() const { - return path_; - } + DirectoryAssetReader(const char *path) { + strcpy(path_, path); + } + // use delete[] + virtual uint8_t *ReadAsset(const char *path, size_t *size); + virtual std::string toString() const { + return path_; + } private: - char path_[512]; + char path_[512]; }; From 25523b82720d963bdb511eaa45dbeca68ec3c29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Oct 2012 13:34:18 +0100 Subject: [PATCH 0130/1445] Fix a stick bug --- ui/virtual_input.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index 090ac38016..f47386400c 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -54,8 +54,10 @@ TouchStick::TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex void TouchStick::update(InputState &input_state) { float inv_stick_size = 1.0f / stick_size_; + bool all_up = true; for (int i = 0; i < MAX_POINTERS; i++) { if (input_state.pointer_down[i]) { + all_up = false; float dx = (input_state.pointer_x[i] - stick_x_) * inv_stick_size; float dy = (input_state.pointer_y[i] - stick_y_) * inv_stick_size; // Ignore outside box @@ -89,6 +91,17 @@ void TouchStick::update(InputState &input_state) skip: lastPointerDown_[i] = input_state.pointer_down[i]; } + if (all_up) { + stick_delta_x_ = 0.0f; + stick_delta_y_ = 0.0f; + if (stick_ == 0) { + input_state.pad_lstick_x = 0.0f; + input_state.pad_lstick_y = 0.0f; + } else if (stick_ == 1) { + input_state.pad_rstick_x = 0.0f; + input_state.pad_rstick_y = 0.0f; + } + } } void TouchStick::draw(DrawBuffer &db, uint32_t color) From 8c63f83d90832a2da682be93fbe9ff98c726951f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Oct 2012 13:34:27 +0100 Subject: [PATCH 0131/1445] Add filter ability to getFilesInDir --- file/file_util.cpp | 41 ++++++++++++++++++++++++++++++++++++++--- file/file_util.h | 3 ++- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index bbb78b1769..344aff99cf 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -6,11 +6,13 @@ #include #endif #include +#include #include +#include + #include "base/logging.h" #include "base/basictypes.h" #include "file/file_util.h" -#include bool writeStringToFile(bool text_file, const std::string &str, const char *filename) { @@ -114,8 +116,31 @@ bool isDirectory(const std::string &filename) #endif } -size_t getFilesInDir(const char *directory, std::vector *files) { +std::string getFileExtension(const std::string &fn) { + int pos = fn.rfind("."); + if (pos < 0) return ""; + std::string ext = fn.substr(pos+1); + for (size_t i = 0; i < ext.size(); i++) { + ext[i] = tolower(ext[i]); + } + return ext; +} + +size_t getFilesInDir(const char *directory, std::vector *files, const char *filter) { size_t foundEntries = 0; + std::set filters; + std::string tmp; + if (filter) { + while (*filter) { + if (*filter == ':') { + filters.insert(tmp); + tmp = ""; + } else { + tmp.push_back(*filter); + } + filter++; + } + } #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; @@ -153,12 +178,22 @@ size_t getFilesInDir(const char *directory, std::vector *files) { // Remove dotfiles (should be made optional?) if (virtualName[0] == '.') continue; + FileInfo info; info.name = virtualName; info.fullName = std::string(directory) + "/" + virtualName; info.isDirectory = isDirectory(info.fullName); + + if (!info.isDirectory) { + std::string ext = getFileExtension(info.fullName); + if (filter) { + if (filters.find(ext) == filters.end()) + continue; + } + } + files->push_back(info); -#ifdef _WIN32 +#ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); #else diff --git a/file/file_util.h b/file/file_util.h index 4e4f71c926..ffa94fc421 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -16,7 +16,8 @@ struct FileInfo bool isDirectory; }; -size_t getFilesInDir(const char *directory, std::vector *files); +std::string getFileExtension(const std::string &fn); +size_t getFilesInDir(const char *directory, std::vector *files, const char *filter = 0); void deleteFile(const char *file); bool exists(const std::string &filename); From e3335b5817761dc3c3fec78396dc1eb3691993db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Oct 2012 13:35:11 +0100 Subject: [PATCH 0132/1445] Inertia scrolling fixes --- ui/ui.cpp | 45 ++++++++++++++++++++++----------------------- ui/ui.h | 6 +++++- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index 315a10781f..11f682c653 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -288,11 +288,6 @@ void UIList::pointerMove(int pointer, float x, float y) { if (movedDistanceY > 10 && !scrolling && uistate.mouseframesdown[0] > holdFrames) { scrolling = true; } - - if (scrolling) { - // Pointer is down so stick to it - scrollY = startScrollY - (y - startDragY); - } } void UIList::pointerUp(int pointer, float x, float y, bool inside) { @@ -342,24 +337,28 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { int itemHeight = adapter->itemHeight(0); int numItems = adapter->getCount(); - // Process inertia scrolling - bool canScroll = itemHeight * numItems > h; - if (canScroll) { - if (inertiaY > 20) inertiaY = 20; - if (inertiaY < -20) inertiaY = -20; - if (!uistate.mousedown[0]) { - scrollY += inertiaY; - } - inertiaY *= 0.9f; - float maxScrollY = numItems * itemHeight - h; - if (scrollY > maxScrollY) { - scrollY -= 0.3 * (scrollY - maxScrollY); - } else if (scrollY < 0.0f) { - scrollY += 0.3f * -scrollY; - } - } else { - scrollY = 0.0f; - inertiaY = 0.0f; + // Cap total inertia + if (inertiaY > 20) inertiaY = 20; + if (inertiaY < -20) inertiaY = -20; + + if (!uistate.mousedown[0]) { + // Let it slide if the pointer is not down + scrollY += inertiaY; + } else if (scrolling) { + // Pointer is down so stick to it + scrollY = startScrollY - (uistate.mousey[0] - startDragY); + } + + // Inertia gradually trails off + inertiaY *= 0.92f; + + // Cap top and bottom softly. + float maxScrollY = numItems * itemHeight - h; + if (maxScrollY < 0.0f) maxScrollY = 0.0f; + if (scrollY > maxScrollY) { + scrollY -= 0.4f * (scrollY - maxScrollY); + } else if (scrollY < 0.0f) { + scrollY += 0.4f * -scrollY; } lastX = uistate.mousex[0]; diff --git a/ui/ui.h b/ui/ui.h index 0d88eda1e7..fbdfba07ac 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -217,7 +217,6 @@ public: float startDragY; float movedDistanceY; float inertiaY; - float dY; int dragFinger; int selected; @@ -225,6 +224,11 @@ public: // return -1 = no selection int Do(int id, int x, int y, int w, int h, UIListAdapter *adapter); + // Call this when the content has changed, to reset scroll position etc. + void contentChanged() { + scrollY = 0.0f; + inertiaY = 0.0f; + } private: // TODO: Migrate to using these directly. void pointerDown(int pointer, float x, float y); From 78239e7796fabc80f9972be9d7eb8cb722cfb598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Oct 2012 13:39:27 +0100 Subject: [PATCH 0133/1445] Could scroll outside the list area --- ui/ui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index 11f682c653..02b6da0adb 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -341,10 +341,11 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { if (inertiaY > 20) inertiaY = 20; if (inertiaY < -20) inertiaY = -20; + float mouseY = uistate.mousey[0]; if (!uistate.mousedown[0]) { // Let it slide if the pointer is not down scrollY += inertiaY; - } else if (scrolling) { + } else if (scrolling && mouseY > y && mouseY < y + h) { // Pointer is down so stick to it scrollY = startScrollY - (uistate.mousey[0] - startDragY); } From a140c7c87465e309a32773dc9d218e3681914bad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Oct 2012 13:55:17 +0100 Subject: [PATCH 0134/1445] GM RNG can now generate FP numbers --- util/random/rng.h | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/util/random/rng.h b/util/random/rng.h index 68e66d79b9..fbc125bc46 100644 --- a/util/random/rng.h +++ b/util/random/rng.h @@ -4,20 +4,27 @@ // George Marsaglia-style random number generator. class GMRng { - public: - void Init(int seed) { - m_w = seed ^ (seed << 16); - if (!m_w) m_w = 1337; - m_z = ~seed; - if (!m_z) m_z = 31337; - } - uint32 R32() { - m_z = 36969 * (m_z & 65535) + (m_z >> 16); - m_w = 18000 * (m_w & 65535) + (m_w >> 16); - return (m_z << 16) + m_w; - } +public: + GMRng() { + m_w = 0x23E866ED; + m_z = 0x80FD5AF2; + } + void Init(int seed) { + m_w = seed ^ (seed << 16); + if (!m_w) m_w = 1337; + m_z = ~seed; + if (!m_z) m_z = 31337; + } + uint32 R32() { + m_z = 36969 * (m_z & 65535) + (m_z >> 16); + m_w = 18000 * (m_w & 65535) + (m_w >> 16); + return (m_z << 16) + m_w; + } + float F() { + return (float)R32() / (float)(0xFFFFFFFF); + } - private: - uint32 m_w; - uint32 m_z; +private: + uint32 m_w; + uint32 m_z; }; From 91d086e359f6c01b7870184c35a88dd8b150b0e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 31 Oct 2012 14:01:32 +0100 Subject: [PATCH 0135/1445] Fix portrait zoom in PCMain --- base/PCMain.cpp | 52 ++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 10ddf0e24f..4fe1c9d37c 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -56,8 +56,7 @@ void LaunchBrowser(const char *url) #ifdef _WIN32 ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); #else - ILOG("Would have gone to %s but LaunchBrowser is not implemented on this platform", - url); + ILOG("Would have gone to %s but LaunchBrowser is not implemented on this platform", url); #endif } @@ -66,8 +65,7 @@ void LaunchMarket(const char *url) #ifdef _WIN32 ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); #else - ILOG("Would have gone to %s but LaunchMarket is not implemented on this platform", - url); + ILOG("Would have gone to %s but LaunchMarket is not implemented on this platform", url); #endif } @@ -76,26 +74,25 @@ void LaunchEmail(const char *email_address) #ifdef _WIN32 ShellExecute(NULL, "open", (std::string("mailto:") + email_address).c_str(), NULL, NULL, SW_SHOWNORMAL); #else - ILOG("Would have opened your email client for %s but LaunchEmail is not implemented on this platform", - email_address); + ILOG("Would have opened your email client for %s but LaunchEmail is not implemented on this platform", email_address); #endif } const int buttonMappings[14] = { - SDLK_x, //A - SDLK_s, //B - SDLK_z, //X - SDLK_a, //Y + SDLK_x, //A + SDLK_s, //B + SDLK_z, //X + SDLK_a, //Y SDLK_w, //LBUMPER SDLK_q, //RBUMPER SDLK_1, //START SDLK_2, //SELECT - SDLK_UP, //UP - SDLK_DOWN, //DOWN - SDLK_LEFT, //LEFT - SDLK_RIGHT, //RIGHT + SDLK_UP, //UP + SDLK_DOWN, //DOWN + SDLK_LEFT, //LEFT + SDLK_RIGHT, //RIGHT SDLK_m, //MENU SDLK_BACKSPACE, //BACK }; @@ -111,26 +108,26 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_buttons |= (1<pad_lstick_y=1; else if (keys[SDLK_k]) - input->pad_lstick_y=-1; - if (keys[SDLK_j]) + input->pad_lstick_y=-1; + if (keys[SDLK_j]) input->pad_lstick_x=-1; else if (keys[SDLK_l]) - input->pad_lstick_x=1; - if (keys[SDLK_KP8]) + input->pad_lstick_x=1; + if (keys[SDLK_KP8]) input->pad_rstick_y=1; else if (keys[SDLK_KP2]) - input->pad_rstick_y=-1; - if (keys[SDLK_KP4]) + input->pad_rstick_y=-1; + if (keys[SDLK_KP4]) input->pad_rstick_x=-1; else if (keys[SDLK_KP6]) - input->pad_rstick_x=1; + input->pad_rstick_x=1; } extern void mixaudio(void *userdata, Uint8 *stream, int len) { - NativeMix((short *)stream, len / 4); + NativeMix((short *)stream, len / 4); } #ifdef _WIN32 @@ -152,8 +149,9 @@ int main(int argc, char *argv[]) { if (zoomenv) { zoom = atof(zoomenv); } - if (tabletenv) - tablet = true; + if (tabletenv) { + tablet = (bool)atoi(tabletenv); + } bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); @@ -171,8 +169,8 @@ int main(int argc, char *argv[]) { //pixel_xres = 1580 * zoom; //pixel_yres = 1000 * zoom; if (tablet) { - pixel_xres = 800 * zoom; - pixel_yres = 1280 * zoom; + pixel_xres = 480 * zoom; + pixel_yres = 800 * zoom; } else { pixel_xres = 800 * zoom; pixel_yres = 1280 * zoom; From 26c8ffae6150b89a08d4a355c34d4be278838298 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 31 Oct 2012 14:15:21 +0100 Subject: [PATCH 0136/1445] Cleanup. Try to preserve the context on newer androids. --- android/AndroidManifest.xml | 2 +- .../turboviking/libnative/NativeActivity.java | 10 +++----- .../turboviking/libnative/NativeGLView.java | 24 +++++++++++++++++++ .../turboviking/libnative/NativeRenderer.java | 19 ++++++++------- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index b28f3165ea..f31e07181c 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="1" android:versionName="1.0" > - + diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/turboviking/libnative/NativeActivity.java index 2f37883e73..33e5affebc 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/turboviking/libnative/NativeActivity.java @@ -71,7 +71,7 @@ class Installation { } } - + public class NativeActivity extends Activity { // Remember to loadLibrary your JNI .so in a static {} block @@ -86,7 +86,6 @@ public class NativeActivity extends Activity { public static String runCommand; public static String commandParameter; - public static String installID; String getApplicationLibraryDir(ApplicationInfo application) { @@ -184,10 +183,9 @@ public class NativeActivity extends Activity { // Toast.makeText(this, "Value: " + input.getText().toString(), Toast.LENGTH_LONG).show(); } - @SuppressLint("NewApi") public void lightsOut() { if (Build.VERSION.SDK_INT >= 11) { - mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); + // mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); } } @@ -223,7 +221,7 @@ public class NativeActivity extends Activity { @Override protected void onStop() { super.onStop(); - Log.i(TAG, "onStop"); + Log.i(TAG, "onStop - do nothing"); } @Override @@ -241,8 +239,6 @@ public class NativeActivity extends Activity { @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - if (!overrideKeys()) - return false; // Eat these keys, to avoid accidental exits / other screwups. // Maybe there's even more we need to eat on tablets? if (keyCode == KeyEvent.KEYCODE_BACK) { diff --git a/android/src/com/turboviking/libnative/NativeGLView.java b/android/src/com/turboviking/libnative/NativeGLView.java index 2709191f9d..2aec39856a 100644 --- a/android/src/com/turboviking/libnative/NativeGLView.java +++ b/android/src/com/turboviking/libnative/NativeGLView.java @@ -3,12 +3,16 @@ package com.turboviking.libnative; // Touch- and sensor-enabled GLSurfaceView. // Supports simple multitouch and pressure. +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.opengl.GLSurfaceView; +import android.os.Build; import android.util.Log; import android.view.MotionEvent; @@ -17,9 +21,29 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener { private SensorManager mSensorManager; private Sensor mAccelerometer; + + public NativeGLView(NativeActivity activity) { super(activity); setEGLContextClientVersion(2); + + if (Build.VERSION.SDK_INT >= 11) { + try { + Method method_setPreserveEGLContextOnPause = GLSurfaceView.class.getMethod( + "setPreserveEGLContextOnPause", new Class[] { Boolean.class }); + Log.i(TAG, "Invoking setPreserveEGLContextOnPause"); + method_setPreserveEGLContextOnPause.invoke(this, true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + // setEGLConfigChooser(5, 5, 5, 0, 16, 0); // setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); mSensorManager = (SensorManager)activity.getSystemService(Activity.SENSOR_SERVICE); diff --git a/android/src/com/turboviking/libnative/NativeRenderer.java b/android/src/com/turboviking/libnative/NativeRenderer.java index e4f741f474..232204c183 100644 --- a/android/src/com/turboviking/libnative/NativeRenderer.java +++ b/android/src/com/turboviking/libnative/NativeRenderer.java @@ -8,24 +8,26 @@ import android.util.Log; public class NativeRenderer implements GLSurfaceView.Renderer { - private static String TAG = "RollerballRenderer"; + private static String TAG = "NativeRenderer"; NativeActivity mActivity; NativeRenderer(NativeActivity act) { mActivity = act; } - @Override - public void onSurfaceCreated(GL10 unused, EGLConfig config) { - Log.i(TAG, "onSurfaceCreated"); - displayInit(); - } @Override public void onDrawFrame(GL10 unused /*use GLES20*/) { displayRender(); } - + + @Override + public void onSurfaceCreated(GL10 unused, EGLConfig config) { + Log.i(TAG, "onSurfaceCreated - EGL context is new or was lost"); + // Actually, it seems that it is here we should recreate lost GL objects. + displayInit(); + } + @Override public void onSurfaceChanged(GL10 unused, int width, int height) { Log.i(TAG, "onSurfaceChanged"); @@ -35,9 +37,10 @@ public class NativeRenderer implements GLSurfaceView.Renderer { // NATIVE METHODS - public native void displayInit(); // Note: This also means "device lost" and you should reload // all buffered objects. + public native void displayInit(); + public native void displayResize(int w, int h); public native void displayRender(); From 33b82fa077950aba8ce7ef067af3c2b7f56916ba Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 31 Oct 2012 20:42:43 +0100 Subject: [PATCH 0137/1445] Various --- ext/vjson/block_allocator.cpp | 3 ++- file/file_util.cpp | 1 + input/gesture_detector.h | 2 -- input/input_state.h | 4 +++- math/lin/matrix4x4.cpp | 1 - native.vcxproj | 2 ++ native.vcxproj.filters | 6 ++++++ ui/screen.cpp | 2 +- 8 files changed, 15 insertions(+), 6 deletions(-) diff --git a/ext/vjson/block_allocator.cpp b/ext/vjson/block_allocator.cpp index 83bd02110c..16f3c4f9ec 100644 --- a/ext/vjson/block_allocator.cpp +++ b/ext/vjson/block_allocator.cpp @@ -2,7 +2,8 @@ #include #include "block_allocator.h" -block_allocator::block_allocator(size_t blocksize): m_head(0), m_blocksize(blocksize) +block_allocator::block_allocator(size_t blocksize) + : m_head(0), m_blocksize(blocksize) { } diff --git a/file/file_util.cpp b/file/file_util.cpp index 344aff99cf..c4ecf16cbc 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "base/logging.h" #include "base/basictypes.h" diff --git a/input/gesture_detector.h b/input/gesture_detector.h index a52636b9f0..dc3911edf3 100644 --- a/input/gesture_detector.h +++ b/input/gesture_detector.h @@ -16,6 +16,4 @@ namespace GestureDetector // x/ydelta is (smoothed?) difference from current location to the position from the last frame. // Returns true if button/finger is down, for convenience. bool dragDelta(int finger, float *xdelta, float *ydelta); - - }; diff --git a/input/input_state.h b/input/input_state.h index cebc112863..9978da0953 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -27,7 +27,7 @@ enum { #define MAX_POINTERS 8 #endif -// Agglomeration of all possible inputs, and automatically computed +// Collection of all possible inputs, and automatically computed // deltas where applicable. struct InputState { // Lock this whenever you access the data in this struct. @@ -66,6 +66,8 @@ struct InputState { bool accelerometer_valid; Vec3 acc; + // TODO: Add key arrays + private: DISALLOW_COPY_AND_ASSIGN(InputState); }; diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp index ec0ef64633..1dcab71f90 100644 --- a/math/lin/matrix4x4.cpp +++ b/math/lin/matrix4x4.cpp @@ -231,7 +231,6 @@ void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float wz = -(far + near) / (far - near); } -// This is a D3D style matrix. void Matrix4x4::setProjectionInf(const float near_plane, const float fov_horiz, const float aspect) { empty(); float f = fov_horiz*0.5f; diff --git a/native.vcxproj b/native.vcxproj index f83b166621..7cbd19bc41 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -227,6 +227,7 @@ + @@ -306,6 +307,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index fff6d79d76..24db528ab2 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -221,6 +221,9 @@ ui + + math + @@ -391,6 +394,9 @@ ui + + math + diff --git a/ui/screen.cpp b/ui/screen.cpp index 5b2357cc65..c4994b85c7 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -21,10 +21,10 @@ void ScreenManager::switchScreen(Screen *screen) { while (dialog_.size()) pop(); } - // TODO: is this still true? // Note that if a dialog is found, this will be a silent background switch that // will only become apparent if the dialog is closed. The previous screen will stick around // until that switch. + // TODO: is this still true? if (nextScreen_ != 0) { FLOG("WTF? Already had a nextScreen_"); } From 0c2b7605866838df8866846ec31d03e54a5acea7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 1 Nov 2012 09:45:27 +0100 Subject: [PATCH 0138/1445] Sort file listing --- file/file_util.cpp | 2 ++ file/file_util.h | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/file/file_util.cpp b/file/file_util.cpp index c4ecf16cbc..cbc07bd94d 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -7,6 +7,7 @@ #endif #include #include +#include #include #include #include @@ -201,6 +202,7 @@ size_t getFilesInDir(const char *directory, std::vector *files, const } closedir(dirp); #endif + std::sort(files->begin(), files->end()); return foundEntries; } diff --git a/file/file_util.h b/file/file_util.h index ffa94fc421..d83172a2ae 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -14,6 +14,17 @@ struct FileInfo std::string name; std::string fullName; bool isDirectory; + + bool operator <(const FileInfo &other) const { + if (isDirectory && !other.isDirectory) + return true; + else if (!isDirectory && other.isDirectory) + return false; + if (name < other.name) + return true; + else + return false; + } }; std::string getFileExtension(const std::string &fn); From d533766061b866d391ef80607a58d1e4b81643bf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 1 Nov 2012 15:34:32 +0100 Subject: [PATCH 0139/1445] Move from turboviking to henrikrydgard as base namespace --- android/app-android.cpp | 30 +++++++++---------- .../libnative/NativeActivity.java | 2 +- .../libnative/NativeApp.java | 2 +- .../libnative/NativeAudioPlayer.java | 2 +- .../libnative/NativeGLView.java | 2 +- .../libnative/NativeRenderer.java | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) rename android/src/com/{turboviking => henrikrydgard}/libnative/NativeActivity.java (99%) rename android/src/com/{turboviking => henrikrydgard}/libnative/NativeApp.java (96%) rename android/src/com/{turboviking => henrikrydgard}/libnative/NativeAudioPlayer.java (98%) rename android/src/com/{turboviking => henrikrydgard}/libnative/NativeGLView.java (98%) rename android/src/com/{turboviking => henrikrydgard}/libnative/NativeRenderer.java (97%) diff --git a/android/app-android.cpp b/android/app-android.cpp index 3310cea888..2751ad69df 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -88,7 +88,7 @@ std::string GetJavaString(JNIEnv *env, jstring jstr) return cpp_string; } -extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) +extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) { std::string app_name, app_nice_name; bool landscape; @@ -97,11 +97,11 @@ extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isLandscape(JNIEnv } // For the Back button to work right. -extern "C" jboolean Java_com_turboviking_libnative_NativeApp_isAtTopLevel(JNIEnv *env, jclass) { +extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isAtTopLevel(JNIEnv *env, jclass) { return NativeIsAtTopLevel(); } -extern "C" void Java_com_turboviking_libnative_NativeApp_init +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; @@ -146,21 +146,21 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_init } } -extern "C" void Java_com_turboviking_libnative_NativeApp_resume(JNIEnv *, jclass) { +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_resume(JNIEnv *, jclass) { ILOG("NativeResume"); if (use_native_audio) { AndroidAudio_Resume(); } } -extern "C" void Java_com_turboviking_libnative_NativeApp_pause(JNIEnv *, jclass) { +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclass) { ILOG("NativePause"); if (use_native_audio) { AndroidAudio_Pause(); } } -extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown(JNIEnv *, jclass) { +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { ILOG("NativeShutdown."); if (use_native_audio) { AndroidAudio_Shutdown(); @@ -177,7 +177,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_shutdown(JNIEnv *, jcla static jmethodID postCommand; -extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { +extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { ILOG("displayInit()"); if (!renderer_inited) { @@ -202,11 +202,11 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayInit(JNIEnv ILOG("MethodID: %i", (int)postCommand); } -extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { +extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { ILOG("displayResize (%i, %i)!", w, h); } -extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { +extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { if (renderer_inited) { { lock_guard guard(input_state.lock); @@ -237,7 +237,7 @@ extern "C" void Java_com_turboviking_libnative_NativeRenderer_displayRender(JNIE } } -extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { // The audio thread can pretty safely enable Flush-to-Zero mode on the FPU. EnableFZ(); @@ -250,7 +250,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_audioRender(JNIEnv* env } } -extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch +extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch (JNIEnv *, jclass, float x, float y, int code, int pointerId) { lock_guard guard(input_state.lock); @@ -274,7 +274,7 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_touch input_state.mouse_valid = true; } -extern "C" void Java_com_turboviking_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) { +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) { switch (key) { case 1: // Back pad_buttons_async_set |= PAD_BUTTON_BACK; @@ -291,7 +291,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_keyDown(JNIEnv *, jclas } } -extern "C" void Java_com_turboviking_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) { +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) { switch (key) { case 1: // Back pad_buttons_async_set &= ~PAD_BUTTON_BACK; @@ -308,7 +308,7 @@ extern "C" void Java_com_turboviking_libnative_NativeApp_keyUp(JNIEnv *, jclass, } } -extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_accelerometer +extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer (JNIEnv *, jclass, float x, float y, float z) { // Theoretically this needs locking but I doubt it matters. Worst case, the X // from one "sensor frame" will be used together with Y from the next. @@ -319,7 +319,7 @@ extern "C" void JNICALL Java_com_turboviking_libnative_NativeApp_accelerometer input_state.acc.z = z; } -extern "C" void Java_com_turboviking_libnative_NativeApp_sendMessage +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage (JNIEnv *env, jclass, jstring message, jstring param) { jboolean isCopy; std::string msg = GetJavaString(env, message); diff --git a/android/src/com/turboviking/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java similarity index 99% rename from android/src/com/turboviking/libnative/NativeActivity.java rename to android/src/com/henrikrydgard/libnative/NativeActivity.java index 33e5affebc..ed9eff8f6e 100644 --- a/android/src/com/turboviking/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -1,4 +1,4 @@ -package com.turboviking.libnative; +package com.henrikrydgard.libnative; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; diff --git a/android/src/com/turboviking/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java similarity index 96% rename from android/src/com/turboviking/libnative/NativeApp.java rename to android/src/com/henrikrydgard/libnative/NativeApp.java index ee403238b2..9c016f0ada 100644 --- a/android/src/com/turboviking/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -1,4 +1,4 @@ -package com.turboviking.libnative; +package com.henrikrydgard.libnative; public class NativeApp { public static native void init( diff --git a/android/src/com/turboviking/libnative/NativeAudioPlayer.java b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java similarity index 98% rename from android/src/com/turboviking/libnative/NativeAudioPlayer.java rename to android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java index c15ef0a91b..d6fd249407 100644 --- a/android/src/com/turboviking/libnative/NativeAudioPlayer.java +++ b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java @@ -1,4 +1,4 @@ -package com.turboviking.libnative; +package com.henrikrydgard.libnative; import android.media.AudioFormat; import android.media.AudioManager; diff --git a/android/src/com/turboviking/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java similarity index 98% rename from android/src/com/turboviking/libnative/NativeGLView.java rename to android/src/com/henrikrydgard/libnative/NativeGLView.java index 2aec39856a..3d2dec1fce 100644 --- a/android/src/com/turboviking/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -1,4 +1,4 @@ -package com.turboviking.libnative; +package com.henrikrydgard.libnative; // Touch- and sensor-enabled GLSurfaceView. // Supports simple multitouch and pressure. diff --git a/android/src/com/turboviking/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java similarity index 97% rename from android/src/com/turboviking/libnative/NativeRenderer.java rename to android/src/com/henrikrydgard/libnative/NativeRenderer.java index 232204c183..ea5573eb9a 100644 --- a/android/src/com/turboviking/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -1,4 +1,4 @@ -package com.turboviking.libnative; +package com.henrikrydgard.libnative; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; From a0943beedff925c8d412eb254ed801a234367cbf Mon Sep 17 00:00:00 2001 From: MrOrdinaire Date: Sat, 3 Nov 2012 01:04:44 +0800 Subject: [PATCH 0140/1445] fix inconsistent file naming --- ext/sha1/{SHA1.cpp => sha1.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ext/sha1/{SHA1.cpp => sha1.cpp} (100%) diff --git a/ext/sha1/SHA1.cpp b/ext/sha1/sha1.cpp similarity index 100% rename from ext/sha1/SHA1.cpp rename to ext/sha1/sha1.cpp From a13616e684403bc178d7444fe8ae9f2c7d56d658 Mon Sep 17 00:00:00 2001 From: MrOrdinaire Date: Sat, 3 Nov 2012 10:34:06 +0800 Subject: [PATCH 0141/1445] fix missing #include's and missing CMake linking directives --- base/PCMain.cpp | 1 + base/stringutil.h | 5 +++-- ext/etcpack/CMakeLists.txt | 2 +- ext/sha1/CMakeLists.txt | 2 +- ext/sha1/sha1.cpp | 2 +- ext/stb_image/CMakeLists.txt | 2 +- ext/stb_vorbis/CMakeLists.txt | 2 +- ext/vjson/CMakeLists.txt | 2 +- file/CMakeLists.txt | 1 + gfx/texture_gen.cpp | 3 ++- gfx_es2/CMakeLists.txt | 2 ++ ui/ui.cpp | 1 + 12 files changed, 16 insertions(+), 9 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 4fe1c9d37c..aea696da83 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -8,6 +8,7 @@ #include #else #include +#include #endif #include diff --git a/base/stringutil.h b/base/stringutil.h index 7cc61b3086..4c5824f9a0 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -1,7 +1,8 @@ #pragma once -#include -#include +#include +#include +#include #include #include "base/basictypes.h" diff --git a/ext/etcpack/CMakeLists.txt b/ext/etcpack/CMakeLists.txt index 806f4157b0..aa8e189074 100644 --- a/ext/etcpack/CMakeLists.txt +++ b/ext/etcpack/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.6) add_library(etcdec etcdec.cpp) #if UNIX -add_definitions(-PIC) +add_definitions(-fPIC) add_library(etcpack etcpack.cpp) diff --git a/ext/sha1/CMakeLists.txt b/ext/sha1/CMakeLists.txt index b1ac75827e..cb83b1eaec 100644 --- a/ext/sha1/CMakeLists.txt +++ b/ext/sha1/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.6) #if(UNIX) -add_definitions(-PIC) +add_definitions(-fPIC) add_definitions(-g) add_definitions(-O2) add_definitions(-Wall) diff --git a/ext/sha1/sha1.cpp b/ext/sha1/sha1.cpp index f9c5cdf84c..263c6b5927 100644 --- a/ext/sha1/sha1.cpp +++ b/ext/sha1/sha1.cpp @@ -9,7 +9,7 @@ // If compiling with MFC, you might want to add #include "StdAfx.h" #define _CRT_SECURE_NO_WARNINGS -#include "SHA1.h" +#include "sha1.h" #ifdef SHA1_UTILITY_FUNCTIONS #define SHA1_MAX_FILE_BUFFER (32 * 20 * 820) diff --git a/ext/stb_image/CMakeLists.txt b/ext/stb_image/CMakeLists.txt index 9c61b3ef99..d69d96b6b9 100644 --- a/ext/stb_image/CMakeLists.txt +++ b/ext/stb_image/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.6) #if(UNIX) -add_definitions(-PIC) +add_definitions(-fPIC) add_definitions(-g) add_definitions(-O2) add_definitions(-Wall) diff --git a/ext/stb_vorbis/CMakeLists.txt b/ext/stb_vorbis/CMakeLists.txt index 128e155afc..27561cc163 100644 --- a/ext/stb_vorbis/CMakeLists.txt +++ b/ext/stb_vorbis/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.6) #if(UNIX) -add_definitions(-PIC) +add_definitions(-fPIC) add_definitions(-g) add_definitions(-O2) add_definitions(-Wall) diff --git a/ext/vjson/CMakeLists.txt b/ext/vjson/CMakeLists.txt index 97ea0d4876..b8d19dc34f 100644 --- a/ext/vjson/CMakeLists.txt +++ b/ext/vjson/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.6) #if(UNIX) -add_definitions(-PIC) +add_definitions(-fPIC) add_definitions(-g) add_definitions(-O2) add_definitions(-Wall) diff --git a/file/CMakeLists.txt b/file/CMakeLists.txt index b1d9b09122..794d6660c4 100644 --- a/file/CMakeLists.txt +++ b/file/CMakeLists.txt @@ -8,6 +8,7 @@ set(SRCS set(SRCS ${SRCS}) add_library(file STATIC ${SRCS}) +target_link_libraries(file general zip) if(UNIX) add_definitions(-fPIC) diff --git a/gfx/texture_gen.cpp b/gfx/texture_gen.cpp index 6b6e76f6ed..3a8209933d 100644 --- a/gfx/texture_gen.cpp +++ b/gfx/texture_gen.cpp @@ -5,7 +5,8 @@ // future. #include -#include +#include +#include #include "base/basictypes.h" #include "gfx/texture.h" diff --git a/gfx_es2/CMakeLists.txt b/gfx_es2/CMakeLists.txt index fdf0dbfb71..43e11ef74d 100644 --- a/gfx_es2/CMakeLists.txt +++ b/gfx_es2/CMakeLists.txt @@ -7,6 +7,8 @@ set(SRCS set(SRCS ${SRCS}) add_library(gfx_es2 STATIC ${SRCS}) +target_link_libraries(gfx_es2 general gfx) +target_link_libraries(gfx_es2 general file) if(UNIX) add_definitions(-fPIC) diff --git a/ui/ui.cpp b/ui/ui.cpp index 02b6da0adb..0fa0554a49 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "ui/ui.h" #include "gfx/texture_atlas.h" From b52bd57aa1a86f4af97a6c4e8f3d31134c33de5d Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 5 Nov 2012 23:22:10 +1000 Subject: [PATCH 0142/1445] PPSSPP ported to Blackberry 10 Now builds for Playbook and Dev Alpha Android's GLES2 backend is used. --- base/PCMain.cpp | 2 ++ base/logging.h | 2 +- gfx/gl_debug_log.cpp | 6 +++--- gfx/gl_debug_log.h | 2 +- gfx/texture.cpp | 16 ++++++++-------- gfx/texture.h | 2 +- gfx/texture_dx11.cpp | 12 ++++++------ gfx_es2/draw_buffer.cpp | 2 +- gfx_es2/fbo.cpp | 18 +++++++++++++++++- gfx_es2/glsl_program.cpp | 4 ++-- gfx_es2/glsl_program.h | 2 +- math/math_util.cpp | 2 +- 12 files changed, 44 insertions(+), 26 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index aea696da83..0f2a3b3ff6 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -209,6 +209,7 @@ int main(int argc, char *argv[]) { SDL_Quit(); return(2); } +#ifndef BLACKBERRY SDL_WM_SetCaption(app_name_nice.c_str(), NULL); if (GLEW_OK != glewInit()) { @@ -222,6 +223,7 @@ int main(int argc, char *argv[]) { printf("Sorry, this program requires OpenGL 2.0.\n"); return 1; } +#endif #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); diff --git a/base/logging.h b/base/logging.h index 5d716a1448..9433babef5 100644 --- a/base/logging.h +++ b/base/logging.h @@ -22,7 +22,7 @@ inline void Crash() { __asm { int 3 }; } #else -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) #undef Crash inline void Crash() { diff --git a/gfx/gl_debug_log.cpp b/gfx/gl_debug_log.cpp index 9d5249ab74..324bf7e497 100644 --- a/gfx/gl_debug_log.cpp +++ b/gfx/gl_debug_log.cpp @@ -1,4 +1,4 @@ -#if defined(ANDROID) +#if defined(ANDROID) || defined(BLACKBERRY) #include #include typedef char GLchar; @@ -20,7 +20,7 @@ void glCheckzor(const char *file, int line) { } } -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) #if 0 void log_callback(GLenum source, GLenum type, GLuint id, @@ -56,7 +56,7 @@ void log_callback(GLenum source, GLenum type, #endif void gl_log_enable() { -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) #if 0 glEnable(DEBUG_OUTPUT_SYNCHRONOUS_ARB); // TODO: Look into disabling, for more perf glDebugMessageCallback(&log_callback, 0); diff --git a/gfx/gl_debug_log.h b/gfx/gl_debug_log.h index f6cc7f2f4e..cb2cd12f7e 100644 --- a/gfx/gl_debug_log.h +++ b/gfx/gl_debug_log.h @@ -6,7 +6,7 @@ void gl_log_enable(); -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) //#define DEBUG_OPENGL #endif diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 38f7016127..36733be002 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -1,4 +1,4 @@ -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) #include #include #else @@ -14,7 +14,7 @@ #include #include -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) #include "image/png_load.h" #include "ext/etcpack/etcdec.h" #endif @@ -76,7 +76,7 @@ bool Texture::Load(const char *filename) { glBindTexture(GL_TEXTURE_2D, id_); if (bpp == 1) { -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); #else glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); @@ -118,7 +118,7 @@ bool Texture::Load(const char *filename) { const char *name = fn; if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); len = strlen(name); -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) if (!strcmp("png", &name[len-3]) || !strcmp("PNG", &name[len-3])) { if (!LoadPNG(fn)) { @@ -141,7 +141,7 @@ bool Texture::Load(const char *filename) { return false; } -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) bool Texture::LoadPNG(const char *filename) { unsigned char *image_data; if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { @@ -184,7 +184,7 @@ bool Texture::LoadXOR() { } -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) // Allocates using new[], doesn't free. uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { @@ -244,7 +244,7 @@ bool Texture::LoadZIM(const char *filename) { int data_h = height[l]; if (data_w < 4) data_w = 4; if (data_h < 4) data_h = 4; -#if defined(ANDROID) +#if defined(ANDROID) || defined(BLACKBERRY) int compressed_image_bytes = data_w * data_h / 2; glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); GL_CHECK(); @@ -255,7 +255,7 @@ bool Texture::LoadZIM(const char *filename) { #endif } GL_CHECK(); -#if !defined(ANDROID) +#if !defined(ANDROID) && !defined(BLACKBERRY) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); #endif } else { diff --git a/gfx/texture.h b/gfx/texture.h index 3c3f953e21..1823c49494 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -14,7 +14,7 @@ public: ~Texture(); bool LoadZIM(const char *filename); -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) bool LoadPNG(const char *filename); #endif bool LoadXOR(); // Loads a placeholder texture. diff --git a/gfx/texture_dx11.cpp b/gfx/texture_dx11.cpp index 7d72849ca6..a6ef42a750 100644 --- a/gfx/texture_dx11.cpp +++ b/gfx/texture_dx11.cpp @@ -10,7 +10,7 @@ #include #include -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) #include "image/png_load.h" #include "ext/etcpack/etcdec.h" #endif @@ -98,7 +98,7 @@ bool Texture::Load(const char *filename) { const char *name = fn; if (zim && 0 == memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); len = strlen(name); - #ifndef ANDROID + #if !defined(ANDROID) && !defined(BLACKBERRY) if (!strcmp("png", &name[len-3]) || !strcmp("PNG", &name[len-3])) { if (!LoadPNG(fn)) { @@ -122,7 +122,7 @@ bool Texture::Load(const char *filename) { } #ifndef METRO -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) bool Texture::LoadPNG(const char *filename) { unsigned char *image_data; if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { @@ -176,7 +176,7 @@ bool Texture::LoadXOR() { } -#ifndef ANDROID +#if !defined(ANDROID) && !defined(BLACKBERRY) // Allocates using new[], doesn't free. uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { @@ -236,7 +236,7 @@ bool Texture::LoadZIM(const char *filename) { int data_h = height[l]; if (data_w < 4) data_w = 4; if (data_h < 4) data_h = 4; -#if defined(ANDROID) +#if defined(ANDROID) || defined(BLACKBERRY) int compressed_image_bytes = data_w * data_h / 2; glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); GL_CHECK(); @@ -247,7 +247,7 @@ bool Texture::LoadZIM(const char *filename) { #endif } GL_CHECK(); -#if !defined(ANDROID) +#if !defined(ANDROID) && !defined(BLACKBERRY) //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); #endif } else { diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 9c3069bff5..c4452d0bfe 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -1,4 +1,4 @@ -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) #include #include #else diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index a64f56bb99..571db9c318 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -1,4 +1,4 @@ -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) #include #include #else @@ -10,6 +10,20 @@ #endif #endif +// Required for Blackberry10 GLES2 implementation +#ifndef GL_RGBA8 +#define GL_RGBA8 GL_RGBA +#endif +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER +#endif +#ifndef GL_DRAW_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER +#endif +#ifndef GL_DEPTH_COMPONENT24 +#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES +#endif + #include "base/logging.h" #include "gfx_es2/fbo.h" @@ -45,6 +59,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); +#ifndef BLACKBERRY GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); switch(status) { case GL_FRAMEBUFFER_COMPLETE_EXT: @@ -57,6 +72,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { FLOG("Other framebuffer error: %i", status); break; } +#endif // Unbind state we don't need glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index f11f264171..2f7ecf8b1f 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -1,4 +1,4 @@ -#if defined(ANDROID) +#if defined(ANDROID) || defined(BLACKBERRY) #include #include typedef char GLchar; @@ -37,7 +37,7 @@ bool CompileShader(const char *source, GLuint shader, const char *filename) { ELOG("Error in shader compilation of %s!\n", filename); ELOG("Info log: %s\n", infoLog); ELOG("Shader source:\n%s\n", (const char *)source); -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) exit(1); #endif return false; diff --git a/gfx_es2/glsl_program.h b/gfx_es2/glsl_program.h index c5acbfff7f..18fa819fc8 100644 --- a/gfx_es2/glsl_program.h +++ b/gfx_es2/glsl_program.h @@ -4,7 +4,7 @@ #ifndef _RENDER_UTIL #define _RENDER_UTIL -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) #include #include #else diff --git a/math/math_util.cpp b/math/math_util.cpp index 2eebdf6036..70ecede4da 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -17,7 +17,7 @@ unsigned int GenerateRandomNumber() { #include -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) void EnableFZ() { From 8288c307cc896b40f9ad000db8f6b00c2b76ad0f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 5 Nov 2012 15:08:28 +0100 Subject: [PATCH 0143/1445] VCXproj fix --- native.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/native.vcxproj b/native.vcxproj index 7cbd19bc41..d985f3aff0 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -93,7 +93,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); Windows @@ -110,7 +110,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); Windows @@ -129,7 +129,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast @@ -152,7 +152,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast From 652045e46252c51f02196dcd6f769969fb8b3659 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 5 Nov 2012 15:53:54 +0100 Subject: [PATCH 0144/1445] delete [] -> free() --- gfx/texture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 36733be002..24e8079dfb 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -271,7 +271,7 @@ bool Texture::LoadZIM(const char *filename) { GL_CHECK(); // Only free the top level, since the allocation is used for all of them. - delete [] image_data[0]; + free(image_data[0]); return true; } From 0c77415df127781e6c0a86b15eef8a3fae248a03 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 8 Nov 2012 03:29:35 +1000 Subject: [PATCH 0145/1445] Blackberry 10 fully supported with working video, input and sound on Playbook, Dev Alpha and beyond. Video: http://www.youtube.com/watch?v=CdUL1DalYrw --- base/BlackberryMain.cpp | 371 ++++++++++++++++++++++++++++++++++++++++ base/CMakeLists.txt | 3 - base/PCMain.cpp | 5 +- file/file_util.cpp | 29 +++- gfx_es2/fbo.cpp | 17 +- 5 files changed, 411 insertions(+), 14 deletions(-) create mode 100644 base/BlackberryMain.cpp diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp new file mode 100644 index 0000000000..376579336d --- /dev/null +++ b/base/BlackberryMain.cpp @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2012 Sacha Refshauge + * + */ +// Blackberry implementation of the framework. + +#include +#include +#include + +#include "SDL/SDL.h" +#include "SDL/SDL_timer.h" +#include "SDL/SDL_audio.h" +// Our SDL does not support GLES2 so we will set this up with EGL +#include +#include +#include +#include + +#include "base/display.h" +#include "base/logging.h" +#include "base/timeutil.h" +#include "gfx_es2/glsl_program.h" +#include "file/zip_read.h" +#include "input/input_state.h" +#include "base/NativeApp.h" +#include "net/resolve.h" +#include "display.h" + +// Blackberry specific +#include // Blackberry Platform Services +#include // Blackberry Window Manager +#include // Invoke Service +#include // Keyboard Service +#ifdef BLACKBERRY10 +#include // Vibrate Service (BB10) +#endif + +EGLDisplay egl_disp; +EGLSurface egl_surf; + +static EGLConfig egl_conf; +static EGLContext egl_ctx; + +static screen_context_t screen_ctx; +static screen_window_t screen_win; +static screen_display_t screen_disp; + +// Simple implementations of System functions + +void SystemToast(const char *text) { + puts(text); + // dialog_show( ... ) +} + +void ShowAd(int x, int y, bool center_x) { + // Ads on Blackberry? +} + +void ShowKeyboard() { + virtualkeyboard_show(); +} + +void Vibrate(int length_ms) { +#ifdef BLACKBERRY10 + vibration_request(VIBRATION_INTENSITY_LOW, 500 /* intensity (1-100), duration (ms) */); +#endif +} + +void LaunchBrowser(const char *url) +{ + char* error; + navigator_invoke(url, &error); +} + +void LaunchMarket(const char *url) +{ + char* error; + navigator_invoke(url, &error); +} + +void LaunchEmail(const char *email_address) +{ + char* error; + navigator_invoke((std::string("mailto:") + email_address).c_str(), &error); +} + +const int buttonMappings[14] = { + SDLK_x, //A + SDLK_s, //B + SDLK_z, //X + SDLK_a, //Y + SDLK_w, //LBUMPER + SDLK_q, //RBUMPER + SDLK_1, //START + SDLK_2, //SELECT + SDLK_UP, //UP + SDLK_DOWN, //DOWN + SDLK_LEFT, //LEFT + SDLK_RIGHT, //RIGHT + SDLK_m, //MENU + SDLK_BACKSPACE, //BACK +}; + +void SimulateGamepad(const uint8 *keys, InputState *input) { + input->pad_buttons = 0; + input->pad_lstick_x = 0; + input->pad_lstick_y = 0; + input->pad_rstick_x = 0; + input->pad_rstick_y = 0; + for (int b = 0; b < 14; b++) { + if (keys[buttonMappings[b]]) + input->pad_buttons |= (1<pad_lstick_y=1; + else if (keys[SDLK_k]) + input->pad_lstick_y=-1; + if (keys[SDLK_j]) + input->pad_lstick_x=-1; + else if (keys[SDLK_l]) + input->pad_lstick_x=1; + if (keys[SDLK_KP8]) + input->pad_rstick_y=1; + else if (keys[SDLK_KP2]) + input->pad_rstick_y=-1; + if (keys[SDLK_KP4]) + input->pad_rstick_x=-1; + else if (keys[SDLK_KP6]) + input->pad_rstick_x=1; +} + +extern void mixaudio(void *userdata, Uint8 *stream, int len) { + NativeMix((short *)stream, len / 4); +} + +int init_GLES2(screen_context_t ctx) { + int usage = SCREEN_USAGE_DISPLAY | SCREEN_USAGE_OPENGL_ES2; + int format = SCREEN_FORMAT_RGBA8888; + int num_configs; + + EGLint attrib_list[]= { EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE}; + + usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION; + const EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + const EGLint egl_surfaceAttr[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE }; + + screen_ctx = ctx; + screen_create_window(&screen_win, screen_ctx); + screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &format); + screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage); + screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp); + + // This must be landscape. + int screen_resolution[2]; + screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution); + int angle = atoi(getenv("ORIENTATION")); + pixel_xres = screen_resolution[0]; pixel_yres = screen_resolution[1]; + + screen_display_mode_t screen_mode; + screen_get_display_property_pv(screen_disp, SCREEN_PROPERTY_MODE, (void**)&screen_mode); + + int size[2]; + screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size); + + int buffer_size[2] = {size[0], size[1]}; + + if ((angle == 0) || (angle == 180)) { + if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) || + ((screen_mode.width < screen_mode.height) && (size[0] > size[1]))) { + buffer_size[1] = size[0]; + buffer_size[0] = size[1]; + pixel_yres = screen_resolution[0]; + pixel_xres = screen_resolution[1]; + } + } else if ((angle == 90) || (angle == 270)){ + if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) || + ((screen_mode.width < screen_mode.height && size[0] < size[1]))) { + buffer_size[1] = size[0]; + buffer_size[0] = size[1]; + pixel_yres = screen_resolution[0]; + pixel_xres = screen_resolution[1]; + } + } + screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size); + screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle); + + screen_create_window_buffers(screen_win, 2); // Double buffered + egl_disp = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglInitialize(egl_disp, NULL, NULL); + + if (eglChooseConfig(egl_disp, attrib_list, &egl_conf, 1, &num_configs) != EGL_TRUE || egl_conf == 0) + { + printf("Configs weren't set!\n"); + } + egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, attributes); + + egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, egl_surfaceAttr); + + eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx); + eglSwapInterval(egl_disp, 1); + + return 0; +} + +void kill_GLES2() { + if (egl_disp != EGL_NO_DISPLAY) { + eglMakeCurrent(egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (egl_surf != EGL_NO_SURFACE) { + eglDestroySurface(egl_disp, egl_surf); + egl_surf = EGL_NO_SURFACE; + } + if (egl_ctx != EGL_NO_CONTEXT) { + eglDestroyContext(egl_disp, egl_ctx); + egl_ctx = EGL_NO_CONTEXT; + } + if (screen_win != NULL) { + screen_destroy_window(screen_win); + screen_win = NULL; + } + eglTerminate(egl_disp); + egl_disp = EGL_NO_DISPLAY; + } + eglReleaseThread(); +} + +int main(int argc, char *argv[]) { + static screen_context_t screen_cxt; + // Receive events from window manager + screen_create_context(&screen_cxt, 0); + //Initialise Blackberry Platform Services + bps_initialize(); + + net::Init(); + if (SDL_Init(SDL_INIT_AUDIO) < 0) { + fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } + init_GLES2(screen_cxt); + // Playbook: 1024x600@7", Dev Alpha: 1280x768@4.2" + dp_xres = pixel_xres; dp_yres = pixel_yres; + + NativeInit(argc, (const char **)argv, "data/", "/accounts/1000/shared", "BADCOFFEE"); + NativeInitGraphics(); + screen_request_events(screen_cxt); + navigator_request_events(0); + // Yes, we only want landscape. + navigator_rotation_lock(false); +#ifdef BLACKBERRY10 + vibration_request_events(0); +#endif + + SDL_AudioSpec fmt; + fmt.freq = 44100; + fmt.format = AUDIO_S16; + fmt.channels = 2; + fmt.samples = 1024; + fmt.callback = &mixaudio; + fmt.userdata = (void *)0; + + if (SDL_OpenAudio(&fmt, NULL) < 0) { + ELOG("Failed to open audio: %s", SDL_GetError()); + return 1; + } + + // Audio must be unpaused _after_ NativeInit() + SDL_PauseAudio(0); + + InputState input_state; + int framecount = 0; + bool nextFrameMD = 0; + float t = 0; + bool running = true; + while (running) { + // Handle Blackberry events + bps_event_t *event = NULL; + bps_get_event(&event, 0); + + if (event) { + int domain = bps_event_get_domain(event); + if (domain == screen_get_domain()) { + int screen_val, buttons, pointerId; + int pair[2]; + + screen_event_t screen_event = screen_event_get_event(event); + + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, + &screen_val); + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, + pair); + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, + &pointerId); + + // Touchscreen + if (screen_val == SCREEN_EVENT_MTOUCH_TOUCH) { + input_state.pointer_x[pointerId] = pair[0]; + input_state.pointer_y[pointerId] = pair[1]; + input_state.pointer_down[pointerId] = true; + } else if (screen_val == SCREEN_EVENT_MTOUCH_RELEASE) { + input_state.pointer_x[pointerId] = pair[0]; + input_state.pointer_y[pointerId] = pair[1]; + input_state.pointer_down[pointerId] = false; + // Mouse, Simulator + } else if (screen_val == SCREEN_EVENT_POINTER) { + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, + &buttons); + if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down + input_state.pointer_x[pointerId] = pair[0]; + input_state.pointer_y[pointerId] = pair[1]; + input_state.pointer_down[pointerId] = true; + } else if (input_state.pointer_down[pointerId]) { // Up + input_state.pointer_x[pointerId] = pair[0]; + input_state.pointer_y[pointerId] = pair[1]; + input_state.pointer_down[pointerId] = false; + } + } + } else if ((domain == navigator_get_domain()) + && (NAVIGATOR_EXIT == bps_event_get_code(event))) { + running = false; + } + } + input_state.accelerometer_valid = false; + input_state.mouse_valid = true; + +// Maybe ask BPS if there's a USB/BT keyboard attached? +// SimulateGamepad(keys, &input_state); + UpdateInputState(&input_state); + NativeUpdate(input_state); + NativeRender(); + + EndInputState(&input_state); + + if (framecount % 60 == 0) { + // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. + } + + eglSwapBuffers(egl_disp, egl_surf); + + // Simple frame rate limiting + while (time_now() < t + 1.0f/60.0f) { + sleep_ms(0); + time_update(); + } + time_update(); + t = time_now(); + framecount++; + } + + screen_stop_events(screen_cxt); + bps_shutdown(); + + NativeShutdownGraphics(); + SDL_PauseAudio(1); + NativeShutdown(); + SDL_CloseAudio(); + SDL_Quit(); + kill_GLES2(); + net::Shutdown(); + screen_destroy_context(screen_cxt); + exit(0); + return 0; +} diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 184894126a..4b2ef2255f 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -4,11 +4,8 @@ set(SRCS threadutil.cpp error_context.cpp display.cpp - PCMain.cpp buffer.cpp) -set(SRCS ${SRCS}) - add_library(base STATIC ${SRCS}) if(UNIX) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 0f2a3b3ff6..6363f1ac2a 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -178,7 +178,6 @@ int main(int argc, char *argv[]) { } } - net::Init(); #ifdef __APPLE__ // Make sure to request a somewhat modern GL context at least - the @@ -203,13 +202,12 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); - if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, SDL_OPENGL) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return(2); } -#ifndef BLACKBERRY + SDL_WM_SetCaption(app_name_nice.c_str(), NULL); if (GLEW_OK != glewInit()) { @@ -223,7 +221,6 @@ int main(int argc, char *argv[]) { printf("Sorry, this program requires OpenGL 2.0.\n"); return 1; } -#endif #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); diff --git a/file/file_util.cpp b/file/file_util.cpp index cbc07bd94d..97734c47d4 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -5,6 +5,7 @@ #include #include #endif +#include #include #include #include @@ -130,6 +131,32 @@ std::string getFileExtension(const std::string &fn) { size_t getFilesInDir(const char *directory, std::vector *files, const char *filter) { size_t foundEntries = 0; +#ifdef BLACKBERRY + // WORKAROUND: Other implementation will crash on Blackberry (all versions). + struct dirent dirent, *result = NULL; + + DIR *dirp = opendir(directory); + if (!dirp) + return 0; + + while (!readdir_r(dirp, &dirent, &result) && result) { + if (result->d_name[0] == '.') + continue; + FileInfo info; + info.name = std::string(result->d_name); + info.fullName = std::string(directory) + "/" + info.name; + info.isDirectory = isDirectory(info.fullName); + + if (!info.isDirectory) { + const char* ext = strrchr(result->d_name, '.'); + if (ext && strstr(filter, ext+1) == NULL) + continue; + } + + files->push_back(info); + } + closedir(dirp); +#else std::set filters; std::string tmp; if (filter) { @@ -165,7 +192,6 @@ size_t getFilesInDir(const char *directory, std::vector *files, const DIR *dirp = opendir(directory); if (!dirp) return 0; - // non windows loop while (!readdir_r(dirp, &dirent, &result) && result) { @@ -202,6 +228,7 @@ size_t getFilesInDir(const char *directory, std::vector *files, const } closedir(dirp); #endif +#endif // Blackberry workaround std::sort(files->begin(), files->end()); return foundEntries; } diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 571db9c318..904be8da02 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -10,15 +10,15 @@ #endif #endif -// Required for Blackberry10 GLES2 implementation +// Required for Blackberry10/iOS GLES2 implementation #ifndef GL_RGBA8 -#define GL_RGBA8 GL_RGBA +#define GL_RGBA8 GL_RGBA8_OES #endif #ifndef GL_READ_FRAMEBUFFER -#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER GL_READ_FRAMEBUFFER_APPLE #endif #ifndef GL_DRAW_FRAMEBUFFER -#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER GL_DRAW_FRAMEBUFFER_APPLE #endif #ifndef GL_DEPTH_COMPONENT24 #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES @@ -59,7 +59,13 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); -#ifndef BLACKBERRY + +#ifdef BLACKBERRY +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define glCheckFramebufferStatusEXT glCheckFramebufferStatus +#endif GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); switch(status) { case GL_FRAMEBUFFER_COMPLETE_EXT: @@ -72,7 +78,6 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { FLOG("Other framebuffer error: %i", status); break; } -#endif // Unbind state we don't need glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); From febf89bbc8c5473f0158d1023704165d3f0bc889 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 8 Nov 2012 00:35:31 +0100 Subject: [PATCH 0146/1445] Fix an include path and release the input lock between stages. --- android/app-android.cpp | 8 ++++++++ android/project.properties | 2 +- native.vcxproj | 8 ++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 2751ad69df..5a6c5b27b3 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -213,7 +213,15 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN input_state.pad_buttons |= pad_buttons_async_set; input_state.pad_buttons &= ~pad_buttons_async_clear; UpdateInputState(&input_state); + } + + { + lock_guard guard(input_state.lock); NativeUpdate(input_state); + } + + { + lock_guard guard(input_state.lock); EndInputState(&input_state); } NativeRender(); diff --git a/android/project.properties b/android/project.properties index 8996991a47..8061f9c3fe 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt # Project target. -target=android-16 +target=android-8 android.library=true diff --git a/native.vcxproj b/native.vcxproj index d985f3aff0..47579227b0 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -93,7 +93,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); Windows @@ -110,7 +110,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); Windows @@ -129,7 +129,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast @@ -152,7 +152,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast From 19e059c3624d0f3c51bed37f52a3be0498439acd Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 8 Nov 2012 15:27:53 +1000 Subject: [PATCH 0147/1445] Add toast dialogs to BB10. Allow use of (hardcoded) keyboard shortcuts for USB/BT keyboards on Blackberry. Fix a file manager glitch. Track mouse movements (note: this is laggy for now) --- base/BlackberryMain.cpp | 77 ++++++++++++++++++++++++++++------------- file/file_util.cpp | 5 +-- 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 376579336d..06fa343b47 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -32,6 +32,8 @@ #include // Blackberry Window Manager #include // Invoke Service #include // Keyboard Service +#include +#include // Dialog Service (Toast=BB10) #ifdef BLACKBERRY10 #include // Vibrate Service (BB10) #endif @@ -49,8 +51,15 @@ static screen_display_t screen_disp; // Simple implementations of System functions void SystemToast(const char *text) { +#ifdef BLACKBERRY10 + dialog_instance_t dialog = 0; + dialog_create_toast(&dialog); + dialog_set_toast_message_text(dialog, text); + dialog_set_toast_position(dialog, DIALOG_POSITION_TOP_CENTER); + dialog_show(dialog); +#else puts(text); - // dialog_show( ... ) +#endif } void ShowAd(int x, int y, bool center_x) { @@ -86,24 +95,24 @@ void LaunchEmail(const char *email_address) } const int buttonMappings[14] = { - SDLK_x, //A - SDLK_s, //B - SDLK_z, //X - SDLK_a, //Y - SDLK_w, //LBUMPER - SDLK_q, //RBUMPER - SDLK_1, //START - SDLK_2, //SELECT - SDLK_UP, //UP - SDLK_DOWN, //DOWN - SDLK_LEFT, //LEFT - SDLK_RIGHT, //RIGHT - SDLK_m, //MENU - SDLK_BACKSPACE, //BACK + KEYCODE_X, //A + KEYCODE_S, //B + KEYCODE_Z, //X + KEYCODE_A, //Y + KEYCODE_W, //LBUMPER + KEYCODE_Q, //RBUMPER + KEYCODE_ONE, //START + KEYCODE_TWO, //SELECT + KEYCODE_UP, //UP + KEYCODE_DOWN, //DOWN + KEYCODE_LEFT, //LEFT + KEYCODE_RIGHT, //RIGHT + KEYCODE_M, //MENU + KEYCODE_BACKSPACE, //BACK }; -void SimulateGamepad(const uint8 *keys, InputState *input) { - input->pad_buttons = 0; +void SimulateGamepad(const bool *keys, InputState *input) { + input->pad_buttons = 0; input->pad_lstick_x = 0; input->pad_lstick_y = 0; input->pad_rstick_x = 0; @@ -113,22 +122,22 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_buttons |= (1<pad_lstick_y=1; - else if (keys[SDLK_k]) + else if (keys[KEYCODE_K]) input->pad_lstick_y=-1; - if (keys[SDLK_j]) + if (keys[KEYCODE_J]) input->pad_lstick_x=-1; - else if (keys[SDLK_l]) + else if (keys[KEYCODE_L]) input->pad_lstick_x=1; - if (keys[SDLK_KP8]) + /*if (keys[SDLK_KP8]) input->pad_rstick_y=1; else if (keys[SDLK_KP2]) input->pad_rstick_y=-1; if (keys[SDLK_KP4]) input->pad_rstick_x=-1; else if (keys[SDLK_KP6]) - input->pad_rstick_x=1; + input->pad_rstick_x=1;*/ } extern void mixaudio(void *userdata, Uint8 *stream, int len) { @@ -255,6 +264,7 @@ int main(int argc, char *argv[]) { navigator_request_events(0); // Yes, we only want landscape. navigator_rotation_lock(false); + dialog_request_events(0); #ifdef BLACKBERRY10 vibration_request_events(0); #endif @@ -280,6 +290,7 @@ int main(int argc, char *argv[]) { bool nextFrameMD = 0; float t = 0; bool running = true; + bool* keys = new bool[1024]; while (running) { // Handle Blackberry events bps_event_t *event = NULL; @@ -305,6 +316,9 @@ int main(int argc, char *argv[]) { input_state.pointer_x[pointerId] = pair[0]; input_state.pointer_y[pointerId] = pair[1]; input_state.pointer_down[pointerId] = true; + } else if (screen_val == SCREEN_EVENT_MTOUCH_MOVE) { + input_state.pointer_x[pointerId] = pair[0]; + input_state.pointer_y[pointerId] = pair[1]; } else if (screen_val == SCREEN_EVENT_MTOUCH_RELEASE) { input_state.pointer_x[pointerId] = pair[0]; input_state.pointer_y[pointerId] = pair[1]; @@ -323,6 +337,18 @@ int main(int argc, char *argv[]) { input_state.pointer_down[pointerId] = false; } } + // Keyboard + else if (screen_val == SCREEN_EVENT_KEYBOARD) { + int flags, value; + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags); + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value); + if (value < 1024 && value > 0 && (flags & KEY_SYM_VALID)) { + if (flags & KEY_DOWN) + keys[value] = true; + else + keys[value] = false; + } + } } else if ((domain == navigator_get_domain()) && (NAVIGATOR_EXIT == bps_event_get_code(event))) { running = false; @@ -331,8 +357,8 @@ int main(int argc, char *argv[]) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; -// Maybe ask BPS if there's a USB/BT keyboard attached? -// SimulateGamepad(keys, &input_state); +// Maybe ask BPS if there's a USB/BT keyboard attached and show settings to configure + SimulateGamepad(keys, &input_state); UpdateInputState(&input_state); NativeUpdate(input_state); NativeRender(); @@ -354,6 +380,7 @@ int main(int argc, char *argv[]) { t = time_now(); framecount++; } + delete[] keys; screen_stop_events(screen_cxt); bps_shutdown(); diff --git a/file/file_util.cpp b/file/file_util.cpp index 97734c47d4..f7fa575c1e 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -140,10 +140,11 @@ size_t getFilesInDir(const char *directory, std::vector *files, const return 0; while (!readdir_r(dirp, &dirent, &result) && result) { - if (result->d_name[0] == '.') + const std::string filename = result->d_name; + if (filename[0] == '.') continue; FileInfo info; - info.name = std::string(result->d_name); + info.name = filename; info.fullName = std::string(directory) + "/" + info.name; info.isDirectory = isDirectory(info.fullName); From 765e5a341b7644038fc9299ce68ffc269414d7db Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 10 Nov 2012 10:11:18 +0100 Subject: [PATCH 0148/1445] Add untested support for Xperia Play --- .gitignore | 1 + android/app-android.cpp | 80 ++++++++++++++----- .../libnative/NativeActivity.java | 35 ++++---- .../henrikrydgard/libnative/NativeGLView.java | 2 - .../libnative/NativeRenderer.java | 4 - 5 files changed, 80 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index 9e9e916ebb..2e5b81f314 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ Release Debug *.vcxproj.user +android/.settings diff --git a/android/app-android.cpp b/android/app-android.cpp index 5a6c5b27b3..27b26d05ff 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -24,6 +24,22 @@ #include "net/resolve.h" #include "android/native_audio.h" +// For Xperia Play support +enum AndroidKeyCodes { + KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed + KEYCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) + KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed + KEYCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed + KEYCODE_DPAD_LEFT = 21, + KEYCODE_DPAD_UP = 19, + KEYCODE_DPAD_RIGHT = 22, + KEYCODE_DPAD_DOWN = 20, + KEYCODE_BUTTON_L1 = 102, + KEYCODE_BUTTON_R1 = 103, + KEYCODE_BUTTON_START = 108, + KEYCODE_BUTTON_SELECT = 109, +}; + static JNIEnv *jniEnvUI; std::string frameCommand; @@ -282,36 +298,56 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch input_state.mouse_valid = true; } +static void AsyncDown(int padbutton) { + pad_buttons_async_set |= padbutton; + pad_buttons_async_clear &= ~padbutton; +} + +static void AsyncUp(int padbutton) { + pad_buttons_async_set &= ~padbutton; + pad_buttons_async_clear |= padbutton; +} + extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) { switch (key) { - case 1: // Back - pad_buttons_async_set |= PAD_BUTTON_BACK; - pad_buttons_async_clear &= ~PAD_BUTTON_BACK; - break; - case 2: // Menu - pad_buttons_async_set |= PAD_BUTTON_MENU; - pad_buttons_async_clear &= ~PAD_BUTTON_MENU; - break; - case 3: // Search - pad_buttons_async_set |= PAD_BUTTON_A; - pad_buttons_async_clear &= ~PAD_BUTTON_A; + case 1: AsyncDown(PAD_BUTTON_BACK); break; // Back + case 2: AsyncDown(PAD_BUTTON_MENU); break; // Menu + case 3: AsyncDown(PAD_BUTTON_A); break; // Search + case KEYCODE_BUTTON_CROSS: AsyncDown(PAD_BUTTON_A); break; + case KEYCODE_BUTTON_CIRCLE: AsyncDown(PAD_BUTTON_B); break; + case KEYCODE_BUTTON_SQUARE: AsyncDown(PAD_BUTTON_X); break; + case KEYCODE_BUTTON_TRIANGLE: AsyncDown(PAD_BUTTON_Y); break; + case KEYCODE_DPAD_LEFT: AsyncDown(PAD_BUTTON_LEFT); break; + case KEYCODE_DPAD_UP: AsyncDown(PAD_BUTTON_UP); break; + case KEYCODE_DPAD_RIGHT: AsyncDown(PAD_BUTTON_RIGHT); break; + case KEYCODE_DPAD_DOWN: AsyncDown(PAD_BUTTON_LEFT); break; + case KEYCODE_BUTTON_L1: AsyncDown(PAD_BUTTON_LBUMPER); break; + case KEYCODE_BUTTON_R1: AsyncDown(PAD_BUTTON_RBUMPER); break; + case KEYCODE_BUTTON_START: AsyncDown(PAD_BUTTON_START); break; + case KEYCODE_BUTTON_SELECT: AsyncDown(PAD_BUTTON_SELECT); break; + default: break; } } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) { switch (key) { - case 1: // Back - pad_buttons_async_set &= ~PAD_BUTTON_BACK; - pad_buttons_async_clear |= PAD_BUTTON_BACK; - break; - case 2: // Menu - pad_buttons_async_set &= ~PAD_BUTTON_MENU; - pad_buttons_async_clear |= PAD_BUTTON_MENU; - break; - case 3: // Search - pad_buttons_async_set &= ~PAD_BUTTON_A; - pad_buttons_async_clear |= PAD_BUTTON_A; + case 1: AsyncUp(PAD_BUTTON_BACK); break; // Back + case 2: AsyncUp(PAD_BUTTON_MENU); break; // Menu + case 3: AsyncUp(PAD_BUTTON_A); break; // Search + case KEYCODE_BUTTON_CROSS: AsyncUp(PAD_BUTTON_A); break; + case KEYCODE_BUTTON_CIRCLE: AsyncUp(PAD_BUTTON_B); break; + case KEYCODE_BUTTON_SQUARE: AsyncUp(PAD_BUTTON_X); break; + case KEYCODE_BUTTON_TRIANGLE: AsyncUp(PAD_BUTTON_Y); break; + case KEYCODE_DPAD_LEFT: AsyncUp(PAD_BUTTON_LEFT); break; + case KEYCODE_DPAD_UP: AsyncUp(PAD_BUTTON_UP); break; + case KEYCODE_DPAD_RIGHT: AsyncUp(PAD_BUTTON_RIGHT); break; + case KEYCODE_DPAD_DOWN: AsyncUp(PAD_BUTTON_LEFT); break; + case KEYCODE_BUTTON_L1: AsyncUp(PAD_BUTTON_LBUMPER); break; + case KEYCODE_BUTTON_R1: AsyncUp(PAD_BUTTON_RBUMPER); break; + case KEYCODE_BUTTON_START: AsyncUp(PAD_BUTTON_START); break; + case KEYCODE_BUTTON_SELECT: AsyncUp(PAD_BUTTON_SELECT); break; + default: break; } } diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index ed9eff8f6e..8e0791dfc8 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -242,19 +242,24 @@ public class NativeActivity extends Activity { // Eat these keys, to avoid accidental exits / other screwups. // Maybe there's even more we need to eat on tablets? if (keyCode == KeyEvent.KEYCODE_BACK) { - NativeApp.keyDown(1); - return true; + if (event.isAltPressed()) { + NativeApp.keyDown(1004); // special custom keycode + } else { + NativeApp.keyDown(1); + } } else if (keyCode == KeyEvent.KEYCODE_MENU) { NativeApp.keyDown(2); - return true; } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { NativeApp.keyDown(3); - return true; } - // Don't process any other keys. - return false; + else { + // send the rest of the keys through. + // TODO: get rid of the three special cases above by adjusting the native side of the code. + NativeApp.keyDown(keyCode); + } + return true; } @Override @@ -262,25 +267,29 @@ public class NativeActivity extends Activity { // Eat these keys, to avoid accidental exits / other screwups. // Maybe there's even more we need to eat on tablets? if (keyCode == KeyEvent.KEYCODE_BACK) { - if (NativeApp.isAtTopLevel()) { + if (event.isAltPressed()) { + NativeApp.keyUp(1004); // special custom keycode + } + else if (NativeApp.isAtTopLevel()) { return false; } else { NativeApp.keyUp(1); - return true; } } else if (keyCode == KeyEvent.KEYCODE_MENU) { // Menu should be ignored from SDK 11 forwards. We send it to the app. NativeApp.keyUp(2); - return true; } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { // Search probably should also be ignored. We send it to the app. NativeApp.keyUp(3); - return true; } - // All other keys retain their default behavior. - return false; + else { + // send the rest of the keys through. + // TODO: get rid of the three special cases above by adjusting the native side of the code. + NativeApp.keyUp(keyCode); + } + return true; } // Prevent destroying and recreating the main activity when the device rotates etc, @@ -310,13 +319,11 @@ public class NativeActivity extends Activity { .setView(fl) .setTitle(title) .setPositiveButton(defaultAction, new DialogInterface.OnClickListener(){ - @Override public void onClick(DialogInterface d, int which) { d.dismiss(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener(){ - @Override public void onClick(DialogInterface d, int which) { d.cancel(); NativeActivity.inputBoxCancelled = false; diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 3d2dec1fce..6dafdc54ae 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -87,12 +87,10 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener { } // Sensor management - @Override public void onAccuracyChanged(Sensor sensor, int arg1) { Log.i(TAG, "onAccuracyChanged"); } - @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) { return; diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index ea5573eb9a..bb63f4b07b 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -16,19 +16,16 @@ public class NativeRenderer implements GLSurfaceView.Renderer { } - @Override public void onDrawFrame(GL10 unused /*use GLES20*/) { displayRender(); } - @Override public void onSurfaceCreated(GL10 unused, EGLConfig config) { Log.i(TAG, "onSurfaceCreated - EGL context is new or was lost"); // Actually, it seems that it is here we should recreate lost GL objects. displayInit(); } - @Override public void onSurfaceChanged(GL10 unused, int width, int height) { Log.i(TAG, "onSurfaceChanged"); displayResize(width, height); @@ -50,7 +47,6 @@ public class NativeRenderer implements GLSurfaceView.Renderer { final String cmd = command; final String param = parameter; mActivity.runOnUiThread(new Runnable() { - @Override public void run() { NativeRenderer.this.mActivity.processCommand(cmd, param); } From 79e5f1b25a87b2ee1d7b70f85fbe4967f8a3c6a5 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 12 Nov 2012 02:00:51 +1000 Subject: [PATCH 0149/1445] Blackberry: Fixes for keyboard, touch lagg and more --- base/BlackberryMain.cpp | 164 +++++++++++++++++++++++----------------- 1 file changed, 95 insertions(+), 69 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 06fa343b47..d77ec5b880 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -8,10 +8,10 @@ #include #include +// TODO: Replace SDL with asound #include "SDL/SDL.h" -#include "SDL/SDL_timer.h" #include "SDL/SDL_audio.h" -// Our SDL does not support GLES2 so we will set this up with EGL + #include #include #include @@ -28,14 +28,15 @@ #include "display.h" // Blackberry specific -#include // Blackberry Platform Services -#include // Blackberry Window Manager -#include // Invoke Service +//#include // Audio framework for Blackberry +#include // Blackberry Platform Services +#include // Blackberry Window Manager +#include // Invoke Service #include // Keyboard Service #include -#include // Dialog Service (Toast=BB10) +#include // Dialog Service (Toast=BB10) #ifdef BLACKBERRY10 -#include // Vibrate Service (BB10) +#include // Vibrate Service (BB10) #endif EGLDisplay egl_disp; @@ -94,41 +95,41 @@ void LaunchEmail(const char *email_address) navigator_invoke((std::string("mailto:") + email_address).c_str(), &error); } -const int buttonMappings[14] = { - KEYCODE_X, //A - KEYCODE_S, //B - KEYCODE_Z, //X - KEYCODE_A, //Y - KEYCODE_W, //LBUMPER - KEYCODE_Q, //RBUMPER +const int buttonMappings[18] = { + KEYCODE_X, //A + KEYCODE_S, //B + KEYCODE_Z, //X + KEYCODE_A, //Y + KEYCODE_W, //LBUMPER + KEYCODE_Q, //RBUMPER KEYCODE_ONE, //START KEYCODE_TWO, //SELECT - KEYCODE_UP, //UP + KEYCODE_UP, //UP KEYCODE_DOWN, //DOWN KEYCODE_LEFT, //LEFT KEYCODE_RIGHT, //RIGHT - KEYCODE_M, //MENU + KEYCODE_M, //MENU KEYCODE_BACKSPACE, //BACK + KEYCODE_I, //JOY UP + KEYCODE_K, //JOY DOWN + KEYCODE_J, //JOY LEFT + KEYCODE_L, //JOY RIGHT }; -void SimulateGamepad(const bool *keys, InputState *input) { +void SimulateGamepad(InputState *input) { input->pad_buttons = 0; input->pad_lstick_x = 0; input->pad_lstick_y = 0; input->pad_rstick_x = 0; input->pad_rstick_y = 0; - for (int b = 0; b < 14; b++) { - if (keys[buttonMappings[b]]) - input->pad_buttons |= (1<pad_buttons | (1<<14)) input->pad_lstick_y=1; - else if (keys[KEYCODE_K]) + else if (input->pad_buttons | (1<<15)) input->pad_lstick_y=-1; - if (keys[KEYCODE_J]) + if (input->pad_buttons | (1<<16)) input->pad_lstick_x=-1; - else if (keys[KEYCODE_L]) + else if (input->pad_buttons | (1<<17)) input->pad_lstick_x=1; /*if (keys[SDLK_KP8]) input->pad_rstick_y=1; @@ -140,14 +141,11 @@ void SimulateGamepad(const bool *keys, InputState *input) { input->pad_rstick_x=1;*/ } -extern void mixaudio(void *userdata, Uint8 *stream, int len) { - NativeMix((short *)stream, len / 4); -} - int init_GLES2(screen_context_t ctx) { int usage = SCREEN_USAGE_DISPLAY | SCREEN_USAGE_OPENGL_ES2; int format = SCREEN_FORMAT_RGBA8888; int num_configs; + const int intInterval = 0; EGLint attrib_list[]= { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, @@ -200,6 +198,7 @@ int init_GLES2(screen_context_t ctx) { pixel_xres = screen_resolution[1]; } } + screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SWAP_INTERVAL, &intInterval); screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size); screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle); @@ -242,6 +241,10 @@ void kill_GLES2() { eglReleaseThread(); } +extern void mixaudio(void *userdata, Uint8 *stream, int len) { + NativeMix((short *)stream, len / 4); +} + int main(int argc, char *argv[]) { static screen_context_t screen_cxt; // Receive events from window manager @@ -256,7 +259,14 @@ int main(int argc, char *argv[]) { } init_GLES2(screen_cxt); // Playbook: 1024x600@7", Dev Alpha: 1280x768@4.2" - dp_xres = pixel_xres; dp_yres = pixel_yres; +#ifdef BLACKBERRY10 + int dpi; + screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_DPI, &dpi); + float dpi_scale = dpi / 160; +#else + float dpi_scale = 1.1; +#endif + dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); NativeInit(argc, (const char **)argv, "data/", "/accounts/1000/shared", "BADCOFFEE"); NativeInitGraphics(); @@ -284,19 +294,33 @@ int main(int argc, char *argv[]) { // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); +/* snd_pcm_format_t fmt; + fmt.rate = 44100; + fmt.format = SND_PCM_SFMT_S16_LE; + fmt.voices = 2; + snd_pcm_channel_params params; + params.format = fmt; + params.start_mode = SND_PCM_START_DATA; + snd_pcm_t* pcm_handle + snd_pcm_open_preferred(&pcm_handle, NULL, NULL, SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK); + snd_pcm_channel_params(pcm_handle, ¶ms); + snd_pcm_playback_prepare(pcm_handle); + // How to do asound callbacks? + snd_pcm_playback_resume(pcm_handle);*/ InputState input_state; int framecount = 0; - bool nextFrameMD = 0; float t = 0; bool running = true; - bool* keys = new bool[1024]; while (running) { - // Handle Blackberry events - bps_event_t *event = NULL; - bps_get_event(&event, 0); - - if (event) { + input_state.mouse_valid = false; + input_state.accelerometer_valid = false; + while (true) { + // Handle Blackberry events + bps_event_t *event = NULL; + bps_get_event(&event, 0); + if (event == NULL) + break; // Ran out of events int domain = bps_event_get_domain(event); if (domain == screen_get_domain()) { int screen_val, buttons, pointerId; @@ -304,65 +328,66 @@ int main(int argc, char *argv[]) { screen_event_t screen_event = screen_event_get_event(event); - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, - &screen_val); - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, - pair); - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, - &pointerId); + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val); + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pair); + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId); + input_state.mouse_valid = true; + switch(screen_val) + { // Touchscreen - if (screen_val == SCREEN_EVENT_MTOUCH_TOUCH) { - input_state.pointer_x[pointerId] = pair[0]; - input_state.pointer_y[pointerId] = pair[1]; + case SCREEN_EVENT_MTOUCH_TOUCH: + input_state.pointer_x[pointerId] = pair[0] * dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = true; - } else if (screen_val == SCREEN_EVENT_MTOUCH_MOVE) { - input_state.pointer_x[pointerId] = pair[0]; - input_state.pointer_y[pointerId] = pair[1]; - } else if (screen_val == SCREEN_EVENT_MTOUCH_RELEASE) { - input_state.pointer_x[pointerId] = pair[0]; - input_state.pointer_y[pointerId] = pair[1]; + break; + case SCREEN_EVENT_MTOUCH_MOVE: + input_state.pointer_x[pointerId] = pair[0] * dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * dpi_scale; + break; + case SCREEN_EVENT_MTOUCH_RELEASE: + input_state.pointer_x[pointerId] = pair[0] * dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = false; + break; // Mouse, Simulator - } else if (screen_val == SCREEN_EVENT_POINTER) { + case SCREEN_EVENT_POINTER: screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down - input_state.pointer_x[pointerId] = pair[0]; - input_state.pointer_y[pointerId] = pair[1]; + input_state.pointer_x[pointerId] = pair[0] * dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = true; } else if (input_state.pointer_down[pointerId]) { // Up - input_state.pointer_x[pointerId] = pair[0]; - input_state.pointer_y[pointerId] = pair[1]; + input_state.pointer_x[pointerId] = pair[0] * dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = false; } - } + break; // Keyboard - else if (screen_val == SCREEN_EVENT_KEYBOARD) { + case SCREEN_EVENT_KEYBOARD: int flags, value; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value); - if (value < 1024 && value > 0 && (flags & KEY_SYM_VALID)) { - if (flags & KEY_DOWN) - keys[value] = true; - else - keys[value] = false; + if (flags & (KEY_DOWN | KEY_SYM_VALID)) { + for (int b = 0; b < 14; b++) { + if (value == buttonMappings[b]) + input_state.pad_buttons |= (1< Date: Thu, 15 Nov 2012 01:43:33 +1000 Subject: [PATCH 0150/1445] Fix for file UI on Blackberry --- base/BlackberryMain.cpp | 20 ++------------------ file/file_util.cpp | 34 ++++------------------------------ ui/ui.cpp | 10 +++++----- 3 files changed, 11 insertions(+), 53 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index d77ec5b880..150d237627 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -28,7 +28,6 @@ #include "display.h" // Blackberry specific -//#include // Audio framework for Blackberry #include // Blackberry Platform Services #include // Blackberry Window Manager #include // Invoke Service @@ -262,9 +261,9 @@ int main(int argc, char *argv[]) { #ifdef BLACKBERRY10 int dpi; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_DPI, &dpi); - float dpi_scale = dpi / 160; + float dpi_scale = 222.5f / dpi; #else - float dpi_scale = 1.1; + float dpi_scale = 1.1f; #endif dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); @@ -294,19 +293,6 @@ int main(int argc, char *argv[]) { // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); -/* snd_pcm_format_t fmt; - fmt.rate = 44100; - fmt.format = SND_PCM_SFMT_S16_LE; - fmt.voices = 2; - snd_pcm_channel_params params; - params.format = fmt; - params.start_mode = SND_PCM_START_DATA; - snd_pcm_t* pcm_handle - snd_pcm_open_preferred(&pcm_handle, NULL, NULL, SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK); - snd_pcm_channel_params(pcm_handle, ¶ms); - snd_pcm_playback_prepare(pcm_handle); - // How to do asound callbacks? - snd_pcm_playback_resume(pcm_handle);*/ InputState input_state; int framecount = 0; @@ -412,8 +398,6 @@ int main(int argc, char *argv[]) { NativeShutdownGraphics(); SDL_PauseAudio(1); NativeShutdown(); - //snd_pcm_playback_pause(pcm_handle); - //snd_pcm_close(); SDL_CloseAudio(); SDL_Quit(); kill_GLES2(); diff --git a/file/file_util.cpp b/file/file_util.cpp index f7fa575c1e..7b856cbc16 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -131,33 +131,6 @@ std::string getFileExtension(const std::string &fn) { size_t getFilesInDir(const char *directory, std::vector *files, const char *filter) { size_t foundEntries = 0; -#ifdef BLACKBERRY - // WORKAROUND: Other implementation will crash on Blackberry (all versions). - struct dirent dirent, *result = NULL; - - DIR *dirp = opendir(directory); - if (!dirp) - return 0; - - while (!readdir_r(dirp, &dirent, &result) && result) { - const std::string filename = result->d_name; - if (filename[0] == '.') - continue; - FileInfo info; - info.name = filename; - info.fullName = std::string(directory) + "/" + info.name; - info.isDirectory = isDirectory(info.fullName); - - if (!info.isDirectory) { - const char* ext = strrchr(result->d_name, '.'); - if (ext && strstr(filter, ext+1) == NULL) - continue; - } - - files->push_back(info); - } - closedir(dirp); -#else std::set filters; std::string tmp; if (filter) { @@ -188,13 +161,15 @@ size_t getFilesInDir(const char *directory, std::vector *files, const { const std::string virtualName(ffd.cFileName); #else - struct dirent dirent, *result = NULL; + struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; }; + struct dirent_large diren; + struct dirent *result = NULL; DIR *dirp = opendir(directory); if (!dirp) return 0; // non windows loop - while (!readdir_r(dirp, &dirent, &result) && result) + while (!readdir_r(dirp, (dirent*) &diren, &result) && result) { const std::string virtualName(result->d_name); #endif @@ -229,7 +204,6 @@ size_t getFilesInDir(const char *directory, std::vector *files, const } closedir(dirp); #endif -#endif // Blackberry workaround std::sort(files->begin(), files->end()); return foundEntries; } diff --git a/ui/ui.cpp b/ui/ui.cpp index 0fa0554a49..c8ede5ddbe 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -36,14 +36,14 @@ void UIUpdateMouse(int i, float x, float y, bool down) { } else { uistate.mousepressed[i] = 0; } + uistate.mousex[i] = x; + uistate.mousey[i] = y; + uistate.mousedown[i] = down; + if (uistate.mousedown[i]) uistate.mouseframesdown[i]++; else uistate.mouseframesdown[i] = 0; - - uistate.mousex[i] = x; - uistate.mousey[i] = y; - uistate.mousedown[i] = down; } void UIReset() { @@ -286,7 +286,7 @@ void UIList::pointerMove(int pointer, float x, float y) { inertiaY = 0.8 * inertiaY + 0.2 * -deltaY; } - if (movedDistanceY > 10 && !scrolling && uistate.mouseframesdown[0] > holdFrames) { + if (movedDistanceY > 15 && !scrolling && uistate.mouseframesdown[0] > holdFrames) { scrolling = true; } } From dd1be683631efb787d20ff6d7cff4fb4f081f038 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Nov 2012 23:58:16 +0100 Subject: [PATCH 0151/1445] Add ant build --- .gitignore | 1 + android/build.xml | 92 ++++++++++++++++++++++++++++++++++++++ android/project.properties | 2 +- 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 android/build.xml diff --git a/.gitignore b/.gitignore index 2e5b81f314..f7708b4298 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ Release Debug *.vcxproj.user android/.settings +local.properties diff --git a/android/build.xml b/android/build.xml new file mode 100644 index 0000000000..65e93a3e9a --- /dev/null +++ b/android/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/project.properties b/android/project.properties index 8061f9c3fe..4cf07c9ec1 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt # Project target. -target=android-8 +target=android-10 android.library=true From b17119f2c6fc83dcec73550da550021957c14649 Mon Sep 17 00:00:00 2001 From: Kovensky Date: Sun, 18 Nov 2012 21:36:07 -0300 Subject: [PATCH 0152/1445] Fixes for compatibility with FreeBSD backtrace.cpp assumes that anything non-windows is linux. stb_vorbis.c includes malloc.h which has been deprecated since the 90s on all implementations other than MSVC. The stat64 hack in file_util.cpp is only needed on linux. http_client.h also assumes non-windows is linux. --- base/backtrace.cpp | 2 +- ext/stb_vorbis/stb_vorbis.c | 2 +- file/file_util.cpp | 4 ++++ net/http_client.h | 12 ++++++++---- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/base/backtrace.cpp b/base/backtrace.cpp index 1af17b4307..92e3e2739f 100644 --- a/base/backtrace.cpp +++ b/base/backtrace.cpp @@ -1,6 +1,6 @@ #include "base/backtrace.h" -#ifndef _MSC_VER +#ifdef __linux__ // LINUX ONLY diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index 019438ccbd..85aac31688 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -205,7 +205,7 @@ #include #include #include -#if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) +#ifdef _MSC_VER #include #endif #else diff --git a/file/file_util.cpp b/file/file_util.cpp index 7b856cbc16..5a8a557357 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -17,6 +17,10 @@ #include "base/basictypes.h" #include "file/file_util.h" +#ifdef __FreeBSD__ +#define stat64 stat +#endif + bool writeStringToFile(bool text_file, const std::string &str, const char *filename) { FILE *f = fopen(filename, text_file ? "w" : "wb"); diff --git a/net/http_client.h b/net/http_client.h index 320b8fba0f..a9592cbde9 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -4,11 +4,15 @@ #include "base/basictypes.h" #include "base/buffer.h" -#ifndef _WIN32 -#include -#include -#else +#ifdef _WIN32 #include +#else +#ifdef __FreeBSD__ +#include +#else +#include +#endif +#include #endif namespace net { From 9e08523cedc5c9c0c00813c82ed3f9330b85065b Mon Sep 17 00:00:00 2001 From: Kovensky Date: Sun, 18 Nov 2012 21:43:03 -0300 Subject: [PATCH 0153/1445] Nothing actually requires malloc.h It's ancient pre-ISO-standard history. Forget about it. --- ext/stb_vorbis/stb_vorbis.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index 85aac31688..30a3fe65c8 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -205,9 +205,6 @@ #include #include #include -#ifdef _MSC_VER -#include -#endif #else #define NULL 0 #endif From 7e36cef3aeac81dd8071422be93b00128a0cb110 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 19 Nov 2012 19:06:21 +0100 Subject: [PATCH 0154/1445] Add these to the VS projects for convenience. --- native.vcxproj | 12 ++++++++++++ native.vcxproj.filters | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/native.vcxproj b/native.vcxproj index 47579227b0..d21ff5b0f2 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -267,10 +267,22 @@ + + true + true + true + true + + + true + true + true + true + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 24db528ab2..887dcc4b8a 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -397,6 +397,12 @@ math + + base + + + base + From 0598fc425c6b898af9fee5b49b2054b2fffa55e6 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 19 Nov 2012 23:28:42 +0100 Subject: [PATCH 0155/1445] Fix fbo.cpp for android, add to build --- Android.mk | 1 + gfx_es2/fbo.cpp | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Android.mk b/Android.mk index 1db8a9688e..cce8078ece 100644 --- a/Android.mk +++ b/Android.mk @@ -40,6 +40,7 @@ LOCAL_SRC_FILES :=\ gfx_es2/glsl_program.cpp \ gfx_es2/draw_buffer.cpp.arm \ gfx_es2/vertex_format.cpp \ + gfx_es2/fbo.cpp \ gfx/gl_debug_log.cpp \ gfx/gl_lost_manager.cpp \ gfx/texture.cpp \ diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 904be8da02..90221d2c0b 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -11,6 +11,18 @@ #endif // Required for Blackberry10/iOS GLES2 implementation + +#ifdef ANDROID + +#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER +#define GL_RGBA8 GL_RGBA +#ifndef GL_DEPTH_COMPONENT24 +#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES +#endif + +#else + #ifndef GL_RGBA8 #define GL_RGBA8 GL_RGBA8_OES #endif @@ -20,10 +32,13 @@ #ifndef GL_DRAW_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_DRAW_FRAMEBUFFER_APPLE #endif + #ifndef GL_DEPTH_COMPONENT24 #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #endif +#endif + #include "base/logging.h" #include "gfx_es2/fbo.h" @@ -60,18 +75,19 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); -#ifdef BLACKBERRY +#if defined(BLACKBERRY) #define GL_FRAMEBUFFER_EXT 0x8D40 #define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 #define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD #define glCheckFramebufferStatusEXT glCheckFramebufferStatus #endif - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: + case GL_FRAMEBUFFER_COMPLETE: ILOG("Framebuffer verified complete."); break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + case GL_FRAMEBUFFER_UNSUPPORTED: ELOG("Framebuffer format not supported"); break; default: From 1136388f2667d14c541147cf7ca3ab0a45e9b7d1 Mon Sep 17 00:00:00 2001 From: "Diogo Franco (Kovensky)" Date: Tue, 20 Nov 2012 18:27:24 +0000 Subject: [PATCH 0156/1445] Add missing include --- image/zim_save.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/image/zim_save.cpp b/image/zim_save.cpp index 9c62ea64e5..288340d5fa 100644 --- a/image/zim_save.cpp +++ b/image/zim_save.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "base/logging.h" From 0bed6a94f0f4be3954845122d46a5a5150d5f41a Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 21 Nov 2012 23:08:14 +1000 Subject: [PATCH 0157/1445] Remove redundant Blackberry code in FBO and Main --- base/BlackberryMain.cpp | 22 +++++----------------- gfx_es2/fbo.cpp | 29 ----------------------------- 2 files changed, 5 insertions(+), 46 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 150d237627..2a89dd10ae 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -323,28 +323,21 @@ int main(int argc, char *argv[]) { { // Touchscreen case SCREEN_EVENT_MTOUCH_TOUCH: - input_state.pointer_x[pointerId] = pair[0] * dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * dpi_scale; - input_state.pointer_down[pointerId] = true; - break; + case SCREEN_EVENT_MTOUCH_RELEASE: // Up, down + input_state.pointer_down[pointerId] = (screen_val == SCREEN_EVENT_MTOUCH_TOUCH); case SCREEN_EVENT_MTOUCH_MOVE: input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; break; - case SCREEN_EVENT_MTOUCH_RELEASE: - input_state.pointer_x[pointerId] = pair[0] * dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * dpi_scale; - input_state.pointer_down[pointerId] = false; - break; // Mouse, Simulator - case SCREEN_EVENT_POINTER: + case SCREEN_EVENT_POINTER: screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); - if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down + if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = true; - } else if (input_state.pointer_down[pointerId]) { // Up + } else if (input_state.pointer_down[pointerId]) { // Up input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = false; @@ -369,17 +362,12 @@ int main(int argc, char *argv[]) { } } -// Maybe ask BPS if there's a USB/BT keyboard attached and show settings to configure SimulateGamepad(&input_state); UpdateInputState(&input_state); NativeUpdate(input_state); NativeRender(); EndInputState(&input_state); - if (framecount % 60 == 0) { - // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. - } - eglSwapBuffers(egl_disp, egl_surf); // Simple frame rate limiting diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 90221d2c0b..503c717055 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -10,10 +10,6 @@ #endif #endif -// Required for Blackberry10/iOS GLES2 implementation - -#ifdef ANDROID - #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER #define GL_RGBA8 GL_RGBA @@ -21,24 +17,6 @@ #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #endif -#else - -#ifndef GL_RGBA8 -#define GL_RGBA8 GL_RGBA8_OES -#endif -#ifndef GL_READ_FRAMEBUFFER -#define GL_READ_FRAMEBUFFER GL_READ_FRAMEBUFFER_APPLE -#endif -#ifndef GL_DRAW_FRAMEBUFFER -#define GL_DRAW_FRAMEBUFFER GL_DRAW_FRAMEBUFFER_APPLE -#endif - -#ifndef GL_DEPTH_COMPONENT24 -#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES -#endif - -#endif - #include "base/logging.h" #include "gfx_es2/fbo.h" @@ -75,13 +53,6 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); -#if defined(BLACKBERRY) -#define GL_FRAMEBUFFER_EXT 0x8D40 -#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 -#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD -#define glCheckFramebufferStatusEXT glCheckFramebufferStatus -#endif - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { case GL_FRAMEBUFFER_COMPLETE: From 9a17f3626c0d5fa2fc9e17e57d7a5a3fc6566029 Mon Sep 17 00:00:00 2001 From: Kovensky Date: Wed, 21 Nov 2012 11:46:26 -0300 Subject: [PATCH 0158/1445] Add missing sys/time.h include to fd_util.cpp --- file/fd_util.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/file/fd_util.cpp b/file/fd_util.cpp index cccb400167..e8aae7f889 100644 --- a/file/fd_util.cpp +++ b/file/fd_util.cpp @@ -5,6 +5,7 @@ #include #ifndef _WIN32 #include +#include #else #include #include From d9686752733d2681e8cee8ac5533ce5fa42bedae Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 22 Nov 2012 01:55:04 +1000 Subject: [PATCH 0159/1445] Defines only set for devices using GLES2. Add a missing include for QNX/BSD. --- file/fd_util.cpp | 1 + gfx_es2/fbo.cpp | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/file/fd_util.cpp b/file/fd_util.cpp index cccb400167..9f608d6bf5 100644 --- a/file/fd_util.cpp +++ b/file/fd_util.cpp @@ -10,6 +10,7 @@ #include #endif #include +#include #include "base/logging.h" diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 503c717055..95a1807716 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -1,6 +1,12 @@ #if defined(ANDROID) || defined(BLACKBERRY) #include #include +#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER +#define GL_RGBA8 GL_RGBA +#ifndef GL_DEPTH_COMPONENT24 +#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES +#endif #else #include #if defined(__APPLE__) @@ -10,13 +16,6 @@ #endif #endif -#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER -#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER -#define GL_RGBA8 GL_RGBA -#ifndef GL_DEPTH_COMPONENT24 -#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES -#endif - #include "base/logging.h" #include "gfx_es2/fbo.h" From 5e3686f92e4dc222c61bfbd13159800cd289e6a6 Mon Sep 17 00:00:00 2001 From: "Diogo Franco (Kovensky)" Date: Wed, 21 Nov 2012 17:05:32 +0000 Subject: [PATCH 0160/1445] sys/time.h is only included on non-windows --- file/fd_util.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/file/fd_util.cpp b/file/fd_util.cpp index e9ac05c45d..e8aae7f889 100644 --- a/file/fd_util.cpp +++ b/file/fd_util.cpp @@ -11,7 +11,6 @@ #include #endif #include -#include #include "base/logging.h" From 1968e8c529593739728ec04fa187aa52abce6c22 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 14 Nov 2012 16:40:00 +0100 Subject: [PATCH 0161/1445] ScreenManager: Add support for direct async touch events --- native.vcxproj | 2 +- ui/screen.cpp | 12 ++++++++++++ ui/screen.h | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/native.vcxproj b/native.vcxproj index d21ff5b0f2..00224bf93c 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -19,7 +19,7 @@ - {E8B58922-9827-493D-81E0-4B6E6BD77171} + {C4DF647E-80EA-4111-A0A8-218B1B711E18} Win32Proj native diff --git a/ui/screen.cpp b/ui/screen.cpp index c4994b85c7..2937a9dbe5 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -54,6 +54,18 @@ void ScreenManager::update(InputState &input) { } } +void ScreenManager::touch(int pointer, float x, float y, double time, TouchEvent event) +{ + if (dialog_.size()) { + dialog_.back()->touch(pointer, x, y, time, event); + return; + } + if (currentScreen_) + { + currentScreen_->touch(pointer, x, y, time, event); + } +} + void ScreenManager::render() { if (dialog_.size()) { dialog_.back()->render(); diff --git a/ui/screen.h b/ui/screen.h index 4c6af7bccb..59f6963404 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -17,6 +17,7 @@ #include "base/basictypes.h" #include "base/display.h" +#include "base/NativeApp.h" struct InputState; @@ -37,6 +38,7 @@ public: virtual void render() {} virtual void deviceLost() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} + virtual void touch(int pointer, float x, float y, double time, TouchEvent event) {} ScreenManager *screenManager() { return screenManager_; } void setScreenManager(ScreenManager *sm) { screenManager_ = sm; } @@ -68,6 +70,9 @@ public: // Pops the dialog away. void finishDialog(const Screen *dialog, DialogResult result = DR_OK); + // Instant touch, separate from the update() mechanism. + void touch(int pointer, float x, float y, double time, TouchEvent event); + private: void pop(); Screen *topScreen(); From 16e3d670631a346a984b2e4c9be0467f3c6ab9f8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Nov 2012 23:35:40 +0100 Subject: [PATCH 0162/1445] Add UIContext, to make it easier to pass around what's needed to draw. Not used in PPSSPP yet, for the curious. --- Android.mk | 1 + base/PCMain.cpp | 6 ++--- native.vcxproj | 4 +++ native.vcxproj.filters | 15 ++++++----- tools/atlastool/atlastool.vcxproj | 1 + tools/zimtool/zimtool.vcxproj | 1 + ui/CMakeLists.txt | 1 + ui/screen.cpp | 3 ++- ui/screen.h | 21 +++++++++++++++- ui/ui.cpp | 12 +++++++++ ui/ui.h | 4 +++ ui/ui_context.cpp | 41 +++++++++++++++++++++++++++++++ ui/ui_context.h | 30 ++++++++++++++++++++++ 13 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 ui/ui_context.cpp create mode 100644 ui/ui_context.h diff --git a/Android.mk b/Android.mk index cce8078ece..5038523435 100644 --- a/Android.mk +++ b/Android.mk @@ -48,6 +48,7 @@ LOCAL_SRC_FILES :=\ gfx/texture_gen.cpp \ image/zim_load.cpp \ ui/ui.cpp \ + ui/ui_context.cpp \ ui/screen.cpp \ ui/virtual_input.cpp \ util/random/perlin.cpp diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 6363f1ac2a..466872ac3f 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -170,11 +170,11 @@ int main(int argc, char *argv[]) { //pixel_xres = 1580 * zoom; //pixel_yres = 1000 * zoom; if (tablet) { - pixel_xres = 480 * zoom; - pixel_yres = 800 * zoom; - } else { pixel_xres = 800 * zoom; pixel_yres = 1280 * zoom; + } else { + pixel_xres = 480 * zoom; + pixel_yres = 800 * zoom; } } diff --git a/native.vcxproj b/native.vcxproj index 00224bf93c..c515e9a7f3 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -39,6 +39,7 @@ false false MultiByte + v100 StaticLibrary @@ -173,6 +174,7 @@ + @@ -240,6 +242,7 @@ + @@ -332,6 +335,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 887dcc4b8a..d225cca801 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -15,6 +15,9 @@ tools + + ui + @@ -224,6 +227,9 @@ math + + ui + @@ -397,11 +403,8 @@ math - - base - - - base + + ui @@ -463,4 +466,4 @@ {4515306f-4664-46bf-a89b-abfec5520a15} - \ No newline at end of file + diff --git a/tools/atlastool/atlastool.vcxproj b/tools/atlastool/atlastool.vcxproj index aa20c790b4..e55f42a1f8 100644 --- a/tools/atlastool/atlastool.vcxproj +++ b/tools/atlastool/atlastool.vcxproj @@ -26,6 +26,7 @@ false false MultiByte + v100 diff --git a/tools/zimtool/zimtool.vcxproj b/tools/zimtool/zimtool.vcxproj index f3d5c9b8a7..da00f755ea 100644 --- a/tools/zimtool/zimtool.vcxproj +++ b/tools/zimtool/zimtool.vcxproj @@ -26,6 +26,7 @@ false false MultiByte + v100 diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 066b1a9bda..ffefa49d6b 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -1,5 +1,6 @@ set(SRCS ui.cpp + ui_context.cpp screen.cpp virtual_input.cpp ) diff --git a/ui/screen.cpp b/ui/screen.cpp index 2937a9dbe5..4ff06e8476 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -2,12 +2,13 @@ #include "input/input_state.h" #include "ui/screen.h" -Screen::Screen() : screenManager_(0) { } +Screen::Screen(bool isUiScreen) : screenManager_(0), isUiScreen_(isUiScreen) { } Screen::~Screen() { } ScreenManager::ScreenManager() { currentScreen_ = 0; nextScreen_ = 0; + uiContext_ = 0; } ScreenManager::~ScreenManager() { diff --git a/ui/screen.h b/ui/screen.h index 59f6963404..0ff3e27015 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -29,10 +29,11 @@ enum DialogResult { }; class ScreenManager; +class UIContext; class Screen { public: - Screen(); + Screen(bool isUiScreen = false); virtual ~Screen(); virtual void update(InputState &input) = 0; virtual void render() {} @@ -45,6 +46,7 @@ public: private: ScreenManager *screenManager_; + bool isUiScreen_; DISALLOW_COPY_AND_ASSIGN(Screen); }; @@ -53,6 +55,11 @@ public: Transition() {} }; +enum { + LAYER_SIDEMENU = 1, + LAYER_TRANSPARENT = 2, +}; + class ScreenManager { public: ScreenManager(); @@ -60,6 +67,10 @@ public: void switchScreen(Screen *screen); void update(InputState &input); + + void setUIContext(UIContext *context) { uiContext_ = context; } + UIContext *getUIContext() { return uiContext_; } + void render(); void deviceLost(); void shutdown(); @@ -76,10 +87,18 @@ public: private: void pop(); Screen *topScreen(); + // Base screen. These don't "stack" and you can move in any order between them. Screen *currentScreen_; Screen *nextScreen_; + UIContext *uiContext_; + + struct Layer { + Screen *screen; + int flags; // From LAYER_ enum above + }; + // Dialog stack. These are shown "on top" of base screens and the Android back button works as expected. // Used for options, in-game menus and other things you expect to be able to back out from onto something. std::list dialog_; diff --git a/ui/ui.cpp b/ui/ui.cpp index c8ede5ddbe..0735a248b9 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -15,6 +15,7 @@ DrawBuffer ui_draw2d_front; // This one, though, is OK. UIState uistate; +UIState savedUistate; // Theme. static const Atlas *themeAtlas; @@ -28,6 +29,17 @@ void UIInit(const Atlas *atlas, const UITheme &ui_theme) { memset(&uistate, 0, sizeof(uistate)); } +void UIDisableBegin() +{ + savedUistate = uistate; + memset(&uistate, 0, sizeof(uistate)); +} + +void UIDisableEnd() +{ + uistate = savedUistate; +} + void UIUpdateMouse(int i, float x, float y, bool down) { if (down && !uistate.mousedown[i]) { uistate.mousepressed[i] = 1; diff --git a/ui/ui.h b/ui/ui.h index fbdfba07ac..1f2015e988 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -133,6 +133,10 @@ struct UITheme { // The atlas needs to stick around, the theme is copied. void UIInit(const Atlas *atlas, const UITheme &theme); +// Between these, UI components won't see pointer events. +void UIDisableBegin(); +void UIDisableEnd(); + // Just lets you retrieve the theme that was passed into UIInit, for your own controls for example. UITheme &UIGetTheme(); diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp new file mode 100644 index 0000000000..800780532c --- /dev/null +++ b/ui/ui_context.cpp @@ -0,0 +1,41 @@ +#include "ui.h" +#include "ui_context.h" +#include "gfx/texture.h" +#include "gfx_es2/draw_buffer.h" +#include "gfx_es2/glsl_program.h" + +void UIContext::Begin() +{ + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (uishader_) + glsl_bind(uishader_); + if (uitexture_) + uitexture_->Bind(0); + + UIBegin(); + /* + if (uidrawbuffer_ && uishader_) + uidrawbuffer_->Begin(); + if (uidrawbufferTop_ && uishader_) + uidrawbufferTop_->Begin();*/ +} + +void UIContext::End() +{ + UIEnd(); + if (uidrawbuffer_) + { + uidrawbuffer_->End(); + if (uishader_) + uidrawbuffer_->Flush(uishader_); + } + if (uidrawbufferTop_) + { + uidrawbuffer_->End(); + if (uishader_) + uidrawbufferTop_->Flush(uishader_); + } +} \ No newline at end of file diff --git a/ui/ui_context.h b/ui/ui_context.h new file mode 100644 index 0000000000..daea6915f5 --- /dev/null +++ b/ui/ui_context.h @@ -0,0 +1,30 @@ +#pragma once + +// Everything you need to draw a UI collected into a single unit that can be passed around. +// Everything forward declared so this header is safe everywhere. + +struct GLSLProgram; +class Texture; +class DrawBuffer; + +class UIContext { +public: + UIContext() : uishader_(0), uitexture_(0), uidrawbuffer_(0), uidrawbufferTop_(0) {} + + void Init(const GLSLProgram *uishader, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) { + uishader_ = uishader; + uitexture_ = uitexture; + uidrawbuffer_ = uidrawbuffer; + uidrawbufferTop_ = uidrawbufferTop; + } + + void Begin(); + void End(); + +private: + // TODO: Collect these into a UIContext + const GLSLProgram *uishader_; + Texture *uitexture_; + DrawBuffer *uidrawbuffer_; + DrawBuffer *uidrawbufferTop_; +}; From 8677fac72cc5feea91d9b9daf8d13b43fa86d3a1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 21 Nov 2012 15:30:43 +0100 Subject: [PATCH 0163/1445] Some UI code cleanup. Another variant of ease curve function. RebindTexture. --- android/app-android.cpp | 1 + base/PCMain.cpp | 12 ++- base/display.cpp | 3 +- base/display.h | 3 +- gfx_es2/draw_buffer.cpp | 11 ++- gfx_es2/draw_buffer.h | 15 ++-- math/curves.cpp | 7 ++ math/curves.h | 1 + ui/screen.cpp | 160 ++++++++++++++++++++++++---------------- ui/screen.h | 14 ++-- ui/ui.cpp | 14 ++-- ui/ui.h | 2 +- ui/ui_context.cpp | 45 +++++++++-- ui/ui_context.h | 7 +- 14 files changed, 193 insertions(+), 102 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 27b26d05ff..5eaaa513ec 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -150,6 +150,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init g_dpi_scale = 240.0f / (float)g_dpi; pixel_xres = xxres; pixel_yres = yyres; + pixel_in_dps = (float)pixel_xres / (float)dp_xres; NativeGetAppInfo(&app_name, &app_nice_name, &landscape); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 466872ac3f..1a729541fd 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -135,11 +135,6 @@ extern void mixaudio(void *userdata, Uint8 *stream, int len) { #undef main #endif int main(int argc, char *argv[]) { - /* // Xoom/Nexus 7 resolution. Other common tablet resolutions: 1024x600 , 1366x768 - dp_xres = 1280; - dp_yres = 800; - - */ std::string app_name; std::string app_name_nice; @@ -156,7 +151,8 @@ int main(int argc, char *argv[]) { bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); - + + tablet = false; if (landscape) { if (tablet) { pixel_xres = 1280 * zoom; @@ -250,12 +246,14 @@ int main(int argc, char *argv[]) { float density = 1.0f; dp_xres = (float)pixel_xres * density / zoom; dp_yres = (float)pixel_yres * density / zoom; + pixel_in_dps = (float)pixel_xres / dp_xres; NativeInitGraphics(); float dp_xscale = (float)dp_xres / pixel_xres; float dp_yscale = (float)dp_yres / pixel_yres; + printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); @@ -350,8 +348,8 @@ int main(int argc, char *argv[]) { NativeShutdownGraphics(); SDL_PauseAudio(1); - NativeShutdown(); SDL_CloseAudio(); + NativeShutdown(); SDL_Quit(); net::Shutdown(); exit(0); diff --git a/base/display.cpp b/base/display.cpp index a18a30be77..3ceebf334c 100644 --- a/base/display.cpp +++ b/base/display.cpp @@ -7,4 +7,5 @@ int pixel_xres; int pixel_yres; int g_dpi; -float g_dpi_scale; \ No newline at end of file +float g_dpi_scale; +float pixel_in_dps; \ No newline at end of file diff --git a/base/display.h b/base/display.h index 43199561f0..d72ba4dafd 100644 --- a/base/display.h +++ b/base/display.h @@ -9,4 +9,5 @@ extern int pixel_xres; extern int pixel_yres; extern int g_dpi; -extern float g_dpi_scale; \ No newline at end of file +extern float g_dpi_scale; +extern float pixel_in_dps; \ No newline at end of file diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index c4452d0bfe..698ab346c5 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -233,15 +233,15 @@ void DrawBuffer::DrawTexRect(float x1, float y1, float x2, float y2, float u1, f void DrawBuffer::DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color, float corner_scale) { const AtlasImage &image = atlas->images[atlas_image]; - float um = (image.u2 - image.u1) * 0.5f; - float vm = (image.v2 - image.v1) * 0.5f; + float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; + float um = (u2 + u1) * 0.5f; + float vm = (v2 + v1) * 0.5f; float iw2 = (image.w * 0.5f) * corner_scale; float ih2 = (image.h * 0.5f) * corner_scale; float xa = x1 + iw2; float xb = x2 - iw2; float ya = y1 + ih2; float yb = y2 - ih2; - float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; // Top row DrawTexRect(x1, y1, xa, ya, u1, v1, um, vm, color); DrawTexRect(xa, y1, xb, ya, um, v1, um, vm, color); @@ -358,8 +358,11 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co void DrawBuffer::EnableBlend(bool enable) { if (enable) + { glEnable(GL_BLEND); - else + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else glDisable(GL_BLEND); } diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 66f7b23072..7f40829ac1 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -4,6 +4,7 @@ #include "base/basictypes.h" #include "base/color.h" +#include "base/display.h" struct Atlas; @@ -54,16 +55,16 @@ public: void Flush(const GLSLProgram *program, bool set_blend_state=true); void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); - void hLine(float x1, float y, float x2, uint32 color) { Rect(x1, y, x2 - x1, 1, color); } - void vLine(float x, float y1, float y2, uint32 color) { Rect(x, y1, 1, y2 - y1, color); } - void vLineAlpha50(float x, float y1, float y2, uint32 color) { Rect(x, y1, 1, y2 - y1, (color | 0xFF000000) & 0x7F000000); } + void hLine(float x1, float y, float x2, uint32 color) { Rect(x1, y, x2 - x1, pixel_in_dps, color); } + void vLine(float x, float y1, float y2, uint32 color) { Rect(x, y1, pixel_in_dps, y2 - y1, color); } + void vLineAlpha50(float x, float y1, float y2, uint32 color) { Rect(x, y1, pixel_in_dps, y2 - y1, (color | 0xFF000000) & 0x7F000000); } void RectOutline(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT) { - hLine(x, y, x + w + 1, color); - hLine(x, y + h, x + w + 1, color); + hLine(x, y, x + w + pixel_in_dps, color); + hLine(x, y + h, x + w + pixel_in_dps, color); - vLine(x, y, y + h + 1, color); - vLine(x + w, y, y + h + 1, color); + vLine(x, y, y + h + pixel_in_dps, color); + vLine(x + w, y, y + h + pixel_in_dps, color); } void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom); diff --git a/math/curves.cpp b/math/curves.cpp index c86f87ae5d..00c6303a50 100644 --- a/math/curves.cpp +++ b/math/curves.cpp @@ -36,6 +36,13 @@ float ease(float val) { return ((-cosf(val * PI)) + 1.0f) * 0.5; } +float ease(int t, int fadeLength) +{ + if (t < 0) return 0.0f; + if (t >= fadeLength) return 1.0f; + return ease((float)t / (float)fadeLength); +} + float sawtooth(int t, int period) { return (t % period) * (1.0f / (period - 1)); } diff --git a/math/curves.h b/math/curves.h index fb21d91fb5..be5133326a 100644 --- a/math/curves.h +++ b/math/curves.h @@ -12,6 +12,7 @@ float linearOut(int t, int fadeInLength); // smooth operator [0, 1] -> [0, 1] float ease(float val); +float ease(int t, int fadeLength); // need a bouncy ease diff --git a/ui/screen.cpp b/ui/screen.cpp index 4ff06e8476..db0cd5fa37 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -1,27 +1,22 @@ #include "base/logging.h" #include "input/input_state.h" #include "ui/screen.h" +#include "ui/ui.h" Screen::Screen(bool isUiScreen) : screenManager_(0), isUiScreen_(isUiScreen) { } Screen::~Screen() { } ScreenManager::ScreenManager() { - currentScreen_ = 0; nextScreen_ = 0; uiContext_ = 0; + dialogFinished_ = 0; } ScreenManager::~ScreenManager() { - delete currentScreen_; + shutdown(); } void ScreenManager::switchScreen(Screen *screen) { - if (dialog_.size()) - { - WLOG("Switching screens - dropping the whole dialog stack"); - while (dialog_.size()) - pop(); - } // Note that if a dialog is found, this will be a silent background switch that // will only become apparent if the dialog is closed. The previous screen will stick around // until that switch. @@ -29,113 +24,148 @@ void ScreenManager::switchScreen(Screen *screen) { if (nextScreen_ != 0) { FLOG("WTF? Already had a nextScreen_"); } - if (screen != currentScreen_) { + if (stack_.empty() || screen != stack_.back().screen) { nextScreen_ = screen; nextScreen_->setScreenManager(this); } } void ScreenManager::update(InputState &input) { - if (dialog_.size()) { - dialog_.back()->update(input); - return; - } - if (nextScreen_) { - ILOG("Screen switch!"); - Screen *temp = currentScreen_; - currentScreen_ = nextScreen_; - delete temp; - temp = 0; - nextScreen_ = 0; + ILOG("Screen switch! Top of the stack switches."); + switchToNext(); } - if (currentScreen_) { - currentScreen_->update(input); + if (stack_.size()) { + stack_.back().screen->update(input); } } +void ScreenManager::switchToNext() +{ + Layer temp = {0, 0}; + if (!stack_.empty()) + { + temp = stack_.back(); + stack_.pop_back(); + } + Layer newLayer = {nextScreen_, 0}; + stack_.push_back(newLayer); + delete temp.screen; + nextScreen_ = 0; +} + void ScreenManager::touch(int pointer, float x, float y, double time, TouchEvent event) { - if (dialog_.size()) { - dialog_.back()->touch(pointer, x, y, time, event); + if (stack_.size()) { + stack_.back().screen->touch(pointer, x, y, time, event); return; } - if (currentScreen_) - { - currentScreen_->touch(pointer, x, y, time, event); - } } void ScreenManager::render() { - if (dialog_.size()) { - dialog_.back()->render(); - return; - } - if (currentScreen_) { - currentScreen_->render(); - } - else { + if (stack_.size()) { + switch (stack_.back().flags) + { + case LAYER_SIDEMENU: + if (stack_.size() == 1) + { + ELOG("Can't have sidemenu over nothing"); + break; + } + else + { + auto iter = stack_.end(); + iter--; + iter--; + Layer backback = *iter; + UIDisableBegin(); + // Also shift to the right somehow... + backback.screen->render(); + UIDisableEnd(); + stack_.back().screen->render(); + break; + } + default: + stack_.back().screen->render(); + break; + } + } else { ELOG("No current screen!"); } + + processFinishDialog(); } void ScreenManager::deviceLost() { - if (currentScreen_) - currentScreen_->deviceLost(); + if (stack_.size()) + stack_.back().screen->deviceLost(); // Dialogs too? Nah, they should only use the standard UI texture anyway. // TODO: Change this when it becomes necessary. } Screen *ScreenManager::topScreen() { - if (dialog_.size()) - return dialog_.back(); + if (stack_.size()) + return stack_.back().screen; else - return currentScreen_; + return 0; } void ScreenManager::shutdown() { - if (nextScreen_) { - delete nextScreen_; - nextScreen_ = 0; - } - if (currentScreen_) { - delete currentScreen_; - currentScreen_ = 0; + for (auto x = stack_.begin(); x != stack_.end(); x++) + { + delete x->screen; } + stack_.clear(); + delete nextScreen_; } -void ScreenManager::push(Screen *screen) { +void ScreenManager::push(Screen *screen, int layerFlags) { + if (nextScreen_ && stack_.empty()) { + // we're during init, this is OK + switchToNext(); + } screen->setScreenManager(this); - dialog_.push_back(screen); + Layer layer = {screen, layerFlags}; + stack_.push_back(layer); } void ScreenManager::pop() { - if (dialog_.size()) { - delete dialog_.back(); - dialog_.pop_back(); + if (stack_.size()) { + delete stack_.back().screen; + stack_.pop_back(); } else { - ELOG("Can't push when no dialog is shown"); + ELOG("Can't pop when stack empty"); } } void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) { - if (!dialog_.size()) { - ELOG("Must be in a dialog to finishDialog"); - return; - } - Screen *dlg = dialog_.back(); - if (dialog != dialog_.back()) + if (dialog != stack_.back().screen) { ELOG("Wrong dialog being finished!"); return; } - if (dialog_.size()) { - dialog_.pop_back(); + if (!stack_.size()) { + ELOG("Must be in a dialog to finishDialog"); + return; } - Screen *caller = topScreen(); - caller->dialogFinished(dialog, result); - delete dialog; + dialogFinished_ = dialog; + dialogResult_ = result; } + +void ScreenManager::processFinishDialog() +{ + if (dialogFinished_) + { + if (stack_.size()) { + stack_.pop_back(); + } + + Screen *caller = topScreen(); + caller->dialogFinished(dialogFinished_, dialogResult_); + delete dialogFinished_; + dialogFinished_ = 0; + } +} \ No newline at end of file diff --git a/ui/screen.h b/ui/screen.h index 0ff3e27015..14f7cd85cb 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -44,6 +44,8 @@ public: ScreenManager *screenManager() { return screenManager_; } void setScreenManager(ScreenManager *sm) { screenManager_ = sm; } + virtual void *dialogData() { return 0; } + private: ScreenManager *screenManager_; bool isUiScreen_; @@ -76,7 +78,7 @@ public: void shutdown(); // Push a dialog box in front. Currently 1-level only. - void push(Screen *screen); + void push(Screen *screen, int layerFlags = 0); // Pops the dialog away. void finishDialog(const Screen *dialog, DialogResult result = DR_OK); @@ -86,14 +88,16 @@ public: private: void pop(); + void switchToNext(); + void processFinishDialog(); Screen *topScreen(); - // Base screen. These don't "stack" and you can move in any order between them. - Screen *currentScreen_; Screen *nextScreen_; - UIContext *uiContext_; + const Screen *dialogFinished_; + DialogResult dialogResult_; + struct Layer { Screen *screen; int flags; // From LAYER_ enum above @@ -101,5 +105,5 @@ private: // Dialog stack. These are shown "on top" of base screens and the Android back button works as expected. // Used for options, in-game menus and other things you expect to be able to back out from onto something. - std::list dialog_; + std::list stack_; }; diff --git a/ui/ui.cpp b/ui/ui.cpp index 0735a248b9..da57aa777b 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -286,7 +286,7 @@ void UIList::pointerDown(int pointer, float x, float y) { const int holdFrames = 6; -void UIList::pointerMove(int pointer, float x, float y) { +void UIList::pointerMove(int pointer, float x, float y, bool inside) { float deltaY = y - lastY; movedDistanceY += fabsf(deltaY); @@ -298,7 +298,7 @@ void UIList::pointerMove(int pointer, float x, float y) { inertiaY = 0.8 * inertiaY + 0.2 * -deltaY; } - if (movedDistanceY > 15 && !scrolling && uistate.mouseframesdown[0] > holdFrames) { + if (inside && movedDistanceY > 10 && !scrolling && uistate.mouseframesdown[0] > holdFrames) { scrolling = true; } } @@ -319,7 +319,9 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { // TODO: Abstract this stuff out into EmulatePointerEvents for (int i = 0; i < 1; i++) { // Check for hover + bool isInside = false; if (UIRegionHit(i, x, y, w, h, 0)) { + isInside = true; uistate.hotitem[i] = id; if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) { // Mousedown @@ -331,7 +333,7 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { if (uistate.activeitem[i] == id) { // NOTE: won't work with multiple pointers if (uistate.mousex[i] != lastX || uistate.mousey[i] != lastY) { - pointerMove(i, uistate.mousex[i], uistate.mousey[i]); + pointerMove(i, uistate.mousex[i], uistate.mousey[i], isInside); } } @@ -343,7 +345,7 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { if (uistate.hotitem[i] == id) { clicked = 1; } - pointerUp(i, uistate.mousex[i], uistate.mousey[i], uistate.hotitem[i] == id); + pointerUp(i, uistate.mousex[i], uistate.mousey[i], isInside); } } @@ -358,13 +360,15 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { if (!uistate.mousedown[0]) { // Let it slide if the pointer is not down scrollY += inertiaY; - } else if (scrolling && mouseY > y && mouseY < y + h) { + } else if (scrolling /* && mouseY > y && mouseY < y + h*/ ) { // Pointer is down so stick to it scrollY = startScrollY - (uistate.mousey[0] - startDragY); } // Inertia gradually trails off inertiaY *= 0.92f; + if (scrolling && fabsf(inertiaY) < 0.001f) + scrolling = false; // Cap top and bottom softly. float maxScrollY = numItems * itemHeight - h; diff --git a/ui/ui.h b/ui/ui.h index 1f2015e988..6fdfdb334b 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -237,7 +237,7 @@ private: // TODO: Migrate to using these directly. void pointerDown(int pointer, float x, float y); void pointerUp(int pointer, float x, float y, bool inside); - void pointerMove(int pointer, float x, float y); + void pointerMove(int pointer, float x, float y, bool inside); DISALLOW_COPY_AND_ASSIGN(UIList); }; diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 800780532c..f5fd58dd0a 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -23,19 +23,54 @@ void UIContext::Begin() uidrawbufferTop_->Begin();*/ } -void UIContext::End() +void UIContext::RebindTexture() +{ + if (uitexture_) + uitexture_->Bind(0); +} + +void UIContext::Flush() { - UIEnd(); if (uidrawbuffer_) { uidrawbuffer_->End(); - if (uishader_) + if (uishader_) { + glsl_bind(uishader_); uidrawbuffer_->Flush(uishader_); + } } if (uidrawbufferTop_) { - uidrawbuffer_->End(); - if (uishader_) + uidrawbufferTop_->End(); + if (uishader_) { + glsl_bind(uishader_); uidrawbufferTop_->Flush(uishader_); + } } +} + +void UIContext::FlushNoTex() +{ + if (uidrawbuffer_) + { + uidrawbuffer_->End(); + if (uishadernotex_) { + glsl_bind(uishadernotex_); + uidrawbuffer_->Flush(uishadernotex_); + } + } + if (uidrawbufferTop_) + { + uidrawbufferTop_->End(); + if (uishadernotex_) { + glsl_bind(uishadernotex_); + uidrawbufferTop_->Flush(uishadernotex_); + } + } +} + +void UIContext::End() +{ + UIEnd(); + Flush(); } \ No newline at end of file diff --git a/ui/ui_context.h b/ui/ui_context.h index daea6915f5..c756a3a175 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -11,19 +11,24 @@ class UIContext { public: UIContext() : uishader_(0), uitexture_(0), uidrawbuffer_(0), uidrawbufferTop_(0) {} - void Init(const GLSLProgram *uishader, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) { + void Init(const GLSLProgram *uishader, const GLSLProgram *uishadernotex, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) { uishader_ = uishader; + uishadernotex_ = uishadernotex; uitexture_ = uitexture; uidrawbuffer_ = uidrawbuffer; uidrawbufferTop_ = uidrawbufferTop; } void Begin(); + void Flush(); + void FlushNoTex(); void End(); + void RebindTexture(); private: // TODO: Collect these into a UIContext const GLSLProgram *uishader_; + const GLSLProgram *uishadernotex_; Texture *uitexture_; DrawBuffer *uidrawbuffer_; DrawBuffer *uidrawbufferTop_; From d5fdf2271e85dbc25768d8486110ece5d9d006a1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 22 Nov 2012 18:55:39 +0100 Subject: [PATCH 0164/1445] Project cleanup --- ext/stb_vorbis/stb_vorbis.c | 1 + native.vcxproj | 6 ------ native.vcxproj.filters | 19 +++++++++---------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index 30a3fe65c8..f7989b0a2a 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -14,6 +14,7 @@ #ifdef _MSC_VER #pragma warning (disable:4996) #pragma warning (disable:4244) +#include #endif // Todo: diff --git a/native.vcxproj b/native.vcxproj index c515e9a7f3..d488538e03 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -296,12 +296,6 @@ - - true - true - true - true - diff --git a/native.vcxproj.filters b/native.vcxproj.filters index d225cca801..ddc4fc3429 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -116,9 +116,6 @@ gfx - - audio - input @@ -230,6 +227,9 @@ ui + + ext + @@ -301,18 +301,12 @@ ext - - ext - ext gfx - - audio - input @@ -406,6 +400,11 @@ ui + + + + ext + @@ -466,4 +465,4 @@ {4515306f-4664-46bf-a89b-abfec5520a15} - + \ No newline at end of file From 84f741b21dbaa5cc5f67a9399549648df86cd886 Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Fri, 23 Nov 2012 16:57:12 +0100 Subject: [PATCH 0165/1445] Zip reading is reserved for Android. Fixes Linux build --- file/zip_read.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 27d3a300e4..71439d49cd 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -8,7 +8,7 @@ #include "base/logging.h" #include "file/zip_read.h" -#ifndef _WIN32 +#ifdef ANDROID uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. struct zip_stat zstat; @@ -49,7 +49,7 @@ uint8_t *ReadLocalFile(const char *filename, size_t *size) { return contents; } -#ifndef _WIN32 +#ifdef ANDROID ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { zip_file_ = zip_open(zip_file, 0, NULL); From 8900d99779d836cf4a016809277003518d0b2a7c Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Sat, 24 Nov 2012 15:19:08 +0100 Subject: [PATCH 0166/1445] Add OpenGL state cache to save some redundant state change. --- Android.mk | 1 + gfx_es2/CMakeLists.txt | 1 + gfx_es2/draw_buffer.cpp | 14 ++--- gfx_es2/gl_state.cpp | 23 +++++++++ gfx_es2/gl_state.h | 112 ++++++++++++++++++++++++++++++++++++++++ native.vcxproj | 2 + native.vcxproj.filters | 8 ++- ui/ui_context.cpp | 9 ++-- 8 files changed, 156 insertions(+), 14 deletions(-) create mode 100644 gfx_es2/gl_state.cpp create mode 100644 gfx_es2/gl_state.h diff --git a/Android.mk b/Android.mk index 5038523435..5600a9952a 100644 --- a/Android.mk +++ b/Android.mk @@ -38,6 +38,7 @@ LOCAL_SRC_FILES :=\ net/resolve.cpp \ profiler/profiler.cpp \ gfx_es2/glsl_program.cpp \ + gfx_es2/gl_state.cpp \ gfx_es2/draw_buffer.cpp.arm \ gfx_es2/vertex_format.cpp \ gfx_es2/fbo.cpp \ diff --git a/gfx_es2/CMakeLists.txt b/gfx_es2/CMakeLists.txt index 43e11ef74d..e3a45b0a7f 100644 --- a/gfx_es2/CMakeLists.txt +++ b/gfx_es2/CMakeLists.txt @@ -2,6 +2,7 @@ set(SRCS draw_buffer.cpp fbo.cpp glsl_program.cpp + gl_state.cpp vertex_format.cpp) set(SRCS ${SRCS}) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 698ab346c5..f733ea13ac 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -18,6 +18,7 @@ #include "math/math_util.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/glsl_program.h" +#include "gfx_es2/gl_state.h" #include "gfx/texture_atlas.h" #include "gfx/gl_debug_log.h" @@ -50,8 +51,8 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); if (set_blend_state) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blend.enable(); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glUniform1i(program->sampler0, 0); glEnableVertexAttribArray(program->a_position); @@ -357,13 +358,8 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co } void DrawBuffer::EnableBlend(bool enable) { - if (enable) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - else - glDisable(GL_BLEND); + glstate.blend.set(enable); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } void DrawBuffer::SetClipRect(float x, float y, float w, float h) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp new file mode 100644 index 0000000000..a95e9988bd --- /dev/null +++ b/gfx_es2/gl_state.cpp @@ -0,0 +1,23 @@ +#include "gl_state.h" + +OpenGLState glstate; + +void OpenGLState::Initialize() { + if(initialized) return; + + Restore(); + + initialized = true; +} + +void OpenGLState::Restore() { + blend.restore(); + blendEquation.restore(); + blendFunc.restore(); + + cullFace.restore(); + cullFaceMode.restore(); + + depthTest.restore(); + depthFunc.restore(); +} \ No newline at end of file diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h new file mode 100644 index 0000000000..a3cadded1c --- /dev/null +++ b/gfx_es2/gl_state.h @@ -0,0 +1,112 @@ +#pragma once + +#if defined(ANDROID) || defined(BLACKBERRY) +#include +#include +#else +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif +#include + +class OpenGLState +{ +private: + template + class BoolState { + bool _value; + public: + BoolState() : _value(init) {} + + inline void set(bool value) { + if(value && value != _value) { + _value = value; + glEnable(cap); + } + if(!value && value != _value) { + _value = value; + glDisable(cap); + } + } + inline void enable() { + set(true); + } + inline void disable() { + set(false); + } + operator bool() const { + return isset(); + } + inline bool isset() { + return _value; + } + void restore() { + if(_value) + glEnable(cap); + else + glDisable(cap); + } + }; + +#define STATE1(func, p1type, p1def) \ + class SavedState1_##func { \ + p1type p1; \ + public: \ + SavedState1_##func() : p1(p1def) {}; \ + void set(p1type newp1) { \ + if(newp1 != p1) { \ + p1 = newp1; \ + ##func(p1); \ + } \ + } \ + void restore() { \ + ##func(p1); \ + } \ + } + +#define STATE2(func, p1type, p2type, p1def, p2def) \ + class SavedState2_##func { \ + p1type p1; \ + p2type p2; \ + public: \ + SavedState2_##func() : p1(p1def), p2(p2def) {}; \ + inline void set(p1type newp1, p2type newp2) { \ + if(newp1 != p1 || newp2 != p2) { \ + p1 = newp1; \ + p2 = newp2; \ + ##func(p1, p2); \ + } \ + } \ + inline void restore() { \ + ##func(p1, p2); \ + } \ + } + + bool initialized; + + + +public: + OpenGLState() : initialized(false) {} + void Initialize(); + void Restore(); + + BoolState blend; + STATE2(glBlendFunc, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFunc; + STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; + + BoolState cullFace; + STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode; + + BoolState depthTest; + STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; +}; + +#undef STATE1 +#undef STATE2 + +extern OpenGLState glstate; \ No newline at end of file diff --git a/native.vcxproj b/native.vcxproj index d488538e03..de6389110c 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -221,6 +221,7 @@ + @@ -310,6 +311,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index ddc4fc3429..6b3a7f67c9 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -229,6 +229,8 @@ ext + + gfx @@ -404,6 +406,10 @@ ext + + base + + gfx @@ -465,4 +471,4 @@ {4515306f-4664-46bf-a89b-abfec5520a15} - \ No newline at end of file + diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index f5fd58dd0a..f961713b5a 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -3,13 +3,14 @@ #include "gfx/texture.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/glsl_program.h" +#include "gfx_es2/gl_state.h" void UIContext::Begin() { - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blend.enable(); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.cullFace.disable(); + glstate.depthTest.disable(); if (uishader_) glsl_bind(uishader_); if (uitexture_) From 2680dfe10c5b891c62b263f0267db8f4d13b914e Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Sat, 24 Nov 2012 17:36:04 +0100 Subject: [PATCH 0167/1445] Linux fixup --- gfx_es2/gl_state.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index a3cadded1c..98237b2fb6 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -60,11 +60,11 @@ private: void set(p1type newp1) { \ if(newp1 != p1) { \ p1 = newp1; \ - ##func(p1); \ + func(p1); \ } \ } \ void restore() { \ - ##func(p1); \ + func(p1); \ } \ } @@ -78,11 +78,11 @@ private: if(newp1 != p1 || newp2 != p2) { \ p1 = newp1; \ p2 = newp2; \ - ##func(p1, p2); \ + func(p1, p2); \ } \ } \ inline void restore() { \ - ##func(p1, p2); \ + func(p1, p2); \ } \ } @@ -109,4 +109,4 @@ public: #undef STATE1 #undef STATE2 -extern OpenGLState glstate; \ No newline at end of file +extern OpenGLState glstate; From 275331061efb16786b8ba792e004275a64ced5ab Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 24 Nov 2012 09:16:46 -0800 Subject: [PATCH 0168/1445] Fix vcxproj files so things build again. --- native.vcxproj.filters | 3 +++ tools/atlastool/atlastool.vcxproj | 2 +- tools/zimtool/zimtool.vcxproj | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 6b3a7f67c9..ad1206c6d1 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -229,6 +229,7 @@ ext + gfx @@ -406,8 +407,10 @@ ext + base + gfx diff --git a/tools/atlastool/atlastool.vcxproj b/tools/atlastool/atlastool.vcxproj index e55f42a1f8..d7c6770cf8 100644 --- a/tools/atlastool/atlastool.vcxproj +++ b/tools/atlastool/atlastool.vcxproj @@ -96,7 +96,7 @@ {f761046e-6c38-4428-a5f1-38391a37bb34} - {e8b58922-9827-493d-81e0-4b6e6bd77171} + {C4DF647E-80EA-4111-A0A8-218B1B711E18} diff --git a/tools/zimtool/zimtool.vcxproj b/tools/zimtool/zimtool.vcxproj index da00f755ea..46dfd90a1a 100644 --- a/tools/zimtool/zimtool.vcxproj +++ b/tools/zimtool/zimtool.vcxproj @@ -94,7 +94,7 @@ {f761046e-6c38-4428-a5f1-38391a37bb34} - {e8b58922-9827-493d-81e0-4b6e6bd77171} + {C4DF647E-80EA-4111-A0A8-218B1B711E18} From 62b5bc46d01fd0f79c7f54273d6a09c7ae17c17f Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Sun, 25 Nov 2012 00:09:21 +0100 Subject: [PATCH 0169/1445] Add glDepthRange caching --- gfx_es2/gl_state.cpp | 1 + gfx_es2/gl_state.h | 1 + 2 files changed, 2 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index a95e9988bd..f46352bcf4 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -19,5 +19,6 @@ void OpenGLState::Restore() { cullFaceMode.restore(); depthTest.restore(); + depthRange.restore(); depthFunc.restore(); } \ No newline at end of file diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 98237b2fb6..86d2e401e1 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -104,6 +104,7 @@ public: BoolState depthTest; STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; + STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; }; #undef STATE1 From fd25214d490c722dd7d879a3fb13d1c1c90efae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 25 Nov 2012 11:31:20 +0100 Subject: [PATCH 0170/1445] Only need to include zip.h on android. --- file/zip_read.cpp | 2 +- file/zip_read.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 71439d49cd..c8f36c5ef5 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -1,6 +1,6 @@ #include -#ifndef _WIN32 +#ifdef ANDROID #include #endif diff --git a/file/zip_read.h b/file/zip_read.h index 2c85ec4504..44afe96bc3 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -1,6 +1,6 @@ // TODO: Move much of this code to vfs.cpp -#ifndef _WIN32 +#ifdef ANDROID #include #endif @@ -21,7 +21,7 @@ public: virtual std::string toString() const = 0; }; -#ifndef _WIN32 +#ifdef ANDROID uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size); class ZipAssetReader : public AssetReader { public: From 86ed7895d4daf60d88491b5798f0f5742f6643cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 25 Nov 2012 12:24:26 +0100 Subject: [PATCH 0171/1445] MacOSX build fix --- file/file_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index 5a8a557357..22494818f4 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -17,7 +17,7 @@ #include "base/basictypes.h" #include "file/file_util.h" -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__APPLE__) #define stat64 stat #endif From 41e5a5f3675765114d25357509ddd564d5691674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 25 Nov 2012 12:38:44 +0100 Subject: [PATCH 0172/1445] proper tabs --- gfx_es2/gl_state.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 86d2e401e1..d2805bdf9c 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -23,7 +23,7 @@ private: BoolState() : _value(init) {} inline void set(bool value) { - if(value && value != _value) { + if(value && value != _value) { _value = value; glEnable(cap); } @@ -51,39 +51,39 @@ private: glDisable(cap); } }; - + #define STATE1(func, p1type, p1def) \ class SavedState1_##func { \ - p1type p1; \ + p1type p1; \ public: \ SavedState1_##func() : p1(p1def) {}; \ void set(p1type newp1) { \ - if(newp1 != p1) { \ - p1 = newp1; \ - func(p1); \ + if(newp1 != p1) { \ + p1 = newp1; \ + func(p1); \ } \ - } \ + } \ void restore() { \ - func(p1); \ - } \ + func(p1); \ + } \ } #define STATE2(func, p1type, p2type, p1def, p2def) \ class SavedState2_##func { \ - p1type p1; \ - p2type p2; \ + p1type p1; \ + p2type p2; \ public: \ SavedState2_##func() : p1(p1def), p2(p2def) {}; \ inline void set(p1type newp1, p2type newp2) { \ - if(newp1 != p1 || newp2 != p2) { \ - p1 = newp1; \ + if(newp1 != p1 || newp2 != p2) { \ + p1 = newp1; \ p2 = newp2; \ - func(p1, p2); \ + func(p1, p2); \ } \ - } \ + } \ inline void restore() { \ - func(p1, p2); \ - } \ + func(p1, p2); \ + } \ } bool initialized; From f4278247ed7f9d8db221bc2c1a062227442e99bc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 25 Nov 2012 15:47:26 +0100 Subject: [PATCH 0173/1445] glstate: Support glBlendColor --- gfx_es2/gl_state.h | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index d2805bdf9c..66925754a3 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -12,7 +12,11 @@ #endif #endif #include +#include + +// OpenGL state cache. Should convert all code to use this instead of directly calling glEnable etc, +// as GL state changes can be expensive on some hardware. class OpenGLState { private: @@ -56,7 +60,7 @@ private: class SavedState1_##func { \ p1type p1; \ public: \ - SavedState1_##func() : p1(p1def) {}; \ + SavedState1_##func() : p1(p1def) {}; \ void set(p1type newp1) { \ if(newp1 != p1) { \ p1 = newp1; \ @@ -73,7 +77,7 @@ private: p1type p1; \ p2type p2; \ public: \ - SavedState2_##func() : p1(p1def), p2(p2def) {}; \ + SavedState2_##func() : p1(p1def), p2(p2def) {}; \ inline void set(p1type newp1, p2type newp2) { \ if(newp1 != p1 || newp2 != p2) { \ p1 = newp1; \ @@ -86,10 +90,26 @@ private: } \ } +#define STATEFLOAT4(func, def) \ + class SavedState4_##func { \ + float p[4]; \ + public: \ + SavedState4_##func() { \ + for (int i = 0; i < 4; i++) {p[i] = def;} \ + }; \ + inline void set(const float v[4]) { \ + if(memcmp(p,v,sizeof(float)*4)) { \ + memcpy(p,v,sizeof(float)*4); \ + func(p[0], p[1], p[2], p[3]); \ + } \ + } \ + inline void restore() { \ + func(p[0], p[1], p[2], p[3]); \ + } \ + } + bool initialized; - - public: OpenGLState() : initialized(false) {} void Initialize(); @@ -98,6 +118,7 @@ public: BoolState blend; STATE2(glBlendFunc, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFunc; STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; + STATEFLOAT4(glBlendColor, 1.0f) blendColor; BoolState cullFace; STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode; @@ -105,6 +126,7 @@ public: BoolState depthTest; STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; + }; #undef STATE1 From 41b4cf836c4fdf1adec0be24e84804793ceb2c92 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 25 Nov 2012 17:19:17 +0100 Subject: [PATCH 0174/1445] Add stencil support to FBO code. Attempt to make it work on Tegra (not tested) --- gfx_es2/draw_buffer.cpp | 4 +- gfx_es2/fbo.cpp | 104 ++++++++++++++++++++++++++++++++++++++-- gfx_es2/fbo.h | 2 + gfx_es2/gl_state.h | 4 +- 4 files changed, 107 insertions(+), 7 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index f733ea13ac..b00d937d77 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -366,10 +366,10 @@ void DrawBuffer::SetClipRect(float x, float y, float w, float h) { // Sigh, OpenGL is upside down. glScissor(x, dp_yres - y, w, h); - glEnable(GL_SCISSOR_TEST); + glstate.scissorTest.enable(); } void DrawBuffer::NoClip() { - glDisable(GL_SCISSOR_TEST); + glstate.scissorTest.disable(); } diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 95a1807716..e28b003f6a 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -16,25 +16,68 @@ #endif #endif +#include + #include "base/logging.h" #include "gfx_es2/fbo.h" +// TODO: Move out +#if defined(ANDROID) || defined(BLACKBERRY) +#define GLES +#endif + +// TODO: Breakout this GL extension checker in its own file. + +struct GLExtensions { + bool OES_depth24; + bool OES_packed_depth_stencil; + bool OES_depth_texture; +}; + +GLExtensions gl_extensions; + +void CheckExtensions() { + static bool done = false; + if (done) + return; + done = true; + + memset(&gl_extensions, 0, sizeof(gl_extensions)); + + const char *extString = (const char *)glGetString(GL_EXTENSIONS); + + gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil"); + gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24"); + gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture"); +} + + + struct FBO { GLuint handle; GLuint color_texture; - GLuint z_stencil_buffer; + GLuint z_stencil_buffer; // Either this is set, or the two below. + GLuint z_buffer; + GLuint stencil_buffer; int width; int height; }; + +// On PC, we always use GL_DEPTH24_STENCIL8. +// On Android, we try to use what's available. + FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { + CheckExtensions(); + FBO *fbo = new FBO(); fbo->width = width; fbo->height = height; + + // Color texture is same everywhere glGenFramebuffers(1, &fbo->handle); glGenTextures(1, &fbo->color_texture); - glGenRenderbuffers(1, &fbo->z_stencil_buffer); // Create the surfaces. glBindTexture(GL_TEXTURE_2D, fbo->color_texture); @@ -42,15 +85,65 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // TODO: We could opt to only create 16-bit render targets on slow devices. For later. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + +#ifdef GLES + if (gl_extensions.OES_packed_depth_stencil) { + ILOG("Creating FBO using DEPTH24_STENCIL8"); + // Standard method + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 24-bit Z, 8-bit stencil combined + glGenRenderbuffers(1, &fbo->z_stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); + + // Bind it all together + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + } else { + ILOG("Creating FBO using separate stencil"); + // TEGRA + fbo->z_stencil_buffer = 0; + // 16-bit Z, separate 8-bit stencil + glGenRenderbuffers(1, &fbo->z_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + + // 8-bit stencil buffer + glGenRenderbuffers(1, &fbo->stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); + + // Bind it all together + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); + } +#else + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 24-bit Z, 8-bit stencil + glGenRenderbuffers(1, &fbo->z_stencil_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); // Bind it all together glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); +#endif GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { @@ -58,7 +151,10 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { ILOG("Framebuffer verified complete."); break; case GL_FRAMEBUFFER_UNSUPPORTED: - ELOG("Framebuffer format not supported"); + ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); break; default: FLOG("Other framebuffer error: %i", status); diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index 648d255366..034a82dc57 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -9,6 +9,8 @@ struct FBO; // No mipmap support. // num_color_textures must be 1 for now. // you lose bound texture state. + +// On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil); // These functions should be self explanatory. diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 66925754a3..618b2ec3ba 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -120,13 +120,15 @@ public: STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; STATEFLOAT4(glBlendColor, 1.0f) blendColor; + BoolState scissorTest; + BoolState cullFace; STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode; + STATE1(glFrontFace, GLenum, GL_CCW) frontFace; BoolState depthTest; STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; - }; #undef STATE1 From 3837eb106573dcd077dcde93284743b6a8a0737d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 25 Nov 2012 20:06:29 +0100 Subject: [PATCH 0175/1445] Fix glDepthRangef crash --- gfx_es2/gl_state.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 618b2ec3ba..7ed4ae3460 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -128,7 +128,11 @@ public: BoolState depthTest; STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; +#if defined(ANDROID) || defined(BLACKBERRY) STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; +#else + STATE2(glDepthRange, double, double, 0.0, 1.0) depthRange; +#endif }; #undef STATE1 From 3d1a14ef78fc48fc96fefdeed02f5b3ced15eab5 Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Sun, 25 Nov 2012 22:25:54 +0100 Subject: [PATCH 0176/1445] Include SDL.h instead of SDL/SDL.h --- base/PCMain.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 1a729541fd..f3f76058e0 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -13,10 +13,10 @@ #include -#include "SDL/SDL.h" -#include "SDL/SDL_timer.h" -#include "SDL/SDL_audio.h" -#include "SDL/SDL_video.h" +#include "SDL.h" +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "SDL_video.h" #include "base/display.h" #include "base/logging.h" From 975986f79b693952d64272a752ffaded21a84afd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 26 Nov 2012 09:05:31 +0100 Subject: [PATCH 0177/1445] Add -DARM and -DUSING_GLES2 to standalone makefiles. --- Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index 5600a9952a..0cbd849ae8 100644 --- a/Android.mk +++ b/Android.mk @@ -55,7 +55,7 @@ LOCAL_SRC_FILES :=\ util/random/perlin.cpp -LOCAL_CFLAGS := -O2 -DGL_GLEXT_PROTOTYPES -fsigned-char -fno-strict-aliasing +LOCAL_CFLAGS := -O2 -DGL_GLEXT_PROTOTYPES -DARM -DUSING_GLES2 -fsigned-char -fno-strict-aliasing LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip From 640cce9b88651eb11df642f7538e2dfaa82b69d3 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 26 Nov 2012 20:27:35 +1000 Subject: [PATCH 0178/1445] Use new defines: USING_GLES2, ARM and add iOS support. --- base/logging.h | 2 +- gfx/gl_common.h | 22 ++++++++++++++++++++++ gfx/gl_debug_log.cpp | 18 +++--------------- gfx/gl_debug_log.h | 2 +- gfx/texture.cpp | 29 +++++++++-------------------- gfx/texture.h | 2 +- gfx/texture_dx11.cpp | 19 +++++++------------ gfx_es2/draw_buffer.cpp | 13 +------------ gfx_es2/fbo.cpp | 29 ++++++++--------------------- gfx_es2/gl_state.h | 14 ++------------ gfx_es2/glsl_program.cpp | 17 ++--------------- gfx_es2/glsl_program.h | 13 +------------ math/math_util.cpp | 2 +- 13 files changed, 59 insertions(+), 123 deletions(-) create mode 100644 gfx/gl_common.h diff --git a/base/logging.h b/base/logging.h index 9433babef5..cd16386e81 100644 --- a/base/logging.h +++ b/base/logging.h @@ -22,7 +22,7 @@ inline void Crash() { __asm { int 3 }; } #else -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(ARM) #undef Crash inline void Crash() { diff --git a/gfx/gl_common.h b/gfx/gl_common.h new file mode 100644 index 0000000000..d96fd0533b --- /dev/null +++ b/gfx/gl_common.h @@ -0,0 +1,22 @@ +#ifndef _GL_COMMON_H +#define _GL_COMMON_H + +#if defined(USING_GLES2) +#if defined(IOS) +#include +#include +typedef char GLchar; +#else +#include +#include +#endif +#else // OpenGL +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif + +#endif //_GL_COMMON_H diff --git a/gfx/gl_debug_log.cpp b/gfx/gl_debug_log.cpp index 324bf7e497..e895fd81e6 100644 --- a/gfx/gl_debug_log.cpp +++ b/gfx/gl_debug_log.cpp @@ -1,16 +1,4 @@ -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -typedef char GLchar; -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - +#include "gfx/gl_common.h" #include "base/logging.h" void glCheckzor(const char *file, int line) { @@ -20,7 +8,7 @@ void glCheckzor(const char *file, int line) { } } -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) #if 0 void log_callback(GLenum source, GLenum type, GLuint id, @@ -56,7 +44,7 @@ void log_callback(GLenum source, GLenum type, #endif void gl_log_enable() { -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) #if 0 glEnable(DEBUG_OUTPUT_SYNCHRONOUS_ARB); // TODO: Look into disabling, for more perf glDebugMessageCallback(&log_callback, 0); diff --git a/gfx/gl_debug_log.h b/gfx/gl_debug_log.h index cb2cd12f7e..411f55668d 100644 --- a/gfx/gl_debug_log.h +++ b/gfx/gl_debug_log.h @@ -6,7 +6,7 @@ void gl_log_enable(); -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) //#define DEBUG_OPENGL #endif diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 24e8079dfb..79b9736926 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -1,30 +1,19 @@ -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - #include #include #include -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) #include "image/png_load.h" #include "ext/etcpack/etcdec.h" #endif #include "image/zim_load.h" #include "base/logging.h" -#include "texture.h" +#include "gfx/texture.h" #include "gfx/texture_gen.h" #include "gfx/gl_debug_log.h" #include "gfx/gl_lost_manager.h" +#include "gfx/gl_common.h" Texture::Texture() : id_(0) { register_gl_resource_holder(this); @@ -76,7 +65,7 @@ bool Texture::Load(const char *filename) { glBindTexture(GL_TEXTURE_2D, id_); if (bpp == 1) { -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(USING_GLES2) glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); #else glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); @@ -118,7 +107,7 @@ bool Texture::Load(const char *filename) { const char *name = fn; if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); len = strlen(name); -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) if (!strcmp("png", &name[len-3]) || !strcmp("PNG", &name[len-3])) { if (!LoadPNG(fn)) { @@ -141,7 +130,7 @@ bool Texture::Load(const char *filename) { return false; } -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) bool Texture::LoadPNG(const char *filename) { unsigned char *image_data; if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { @@ -184,7 +173,7 @@ bool Texture::LoadXOR() { } -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) // Allocates using new[], doesn't free. uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { @@ -244,7 +233,7 @@ bool Texture::LoadZIM(const char *filename) { int data_h = height[l]; if (data_w < 4) data_w = 4; if (data_h < 4) data_h = 4; -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(USING_GLES2) int compressed_image_bytes = data_w * data_h / 2; glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); GL_CHECK(); @@ -255,7 +244,7 @@ bool Texture::LoadZIM(const char *filename) { #endif } GL_CHECK(); -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); #endif } else { diff --git a/gfx/texture.h b/gfx/texture.h index 1823c49494..65479f76a8 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -14,7 +14,7 @@ public: ~Texture(); bool LoadZIM(const char *filename); -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) bool LoadPNG(const char *filename); #endif bool LoadXOR(); // Loads a placeholder texture. diff --git a/gfx/texture_dx11.cpp b/gfx/texture_dx11.cpp index a6ef42a750..5737aba3ca 100644 --- a/gfx/texture_dx11.cpp +++ b/gfx/texture_dx11.cpp @@ -1,23 +1,18 @@ // WIP, please ignore - - - -#include "gfx/texture.h" - #include #include #include #include -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) #include "image/png_load.h" #include "ext/etcpack/etcdec.h" #endif #include "image/zim_load.h" #include "base/logging.h" -#include "texture.h" +#include "gfx/texture.h" #include "gfx/texture_gen.h" #include "gfx/gl_debug_log.h" #include "gfx/gl_lost_manager.h" @@ -98,7 +93,7 @@ bool Texture::Load(const char *filename) { const char *name = fn; if (zim && 0 == memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); len = strlen(name); - #if !defined(ANDROID) && !defined(BLACKBERRY) + #if !defined(USING_GLES2) if (!strcmp("png", &name[len-3]) || !strcmp("PNG", &name[len-3])) { if (!LoadPNG(fn)) { @@ -122,7 +117,7 @@ bool Texture::Load(const char *filename) { } #ifndef METRO -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) bool Texture::LoadPNG(const char *filename) { unsigned char *image_data; if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { @@ -176,7 +171,7 @@ bool Texture::LoadXOR() { } -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) // Allocates using new[], doesn't free. uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { @@ -236,7 +231,7 @@ bool Texture::LoadZIM(const char *filename) { int data_h = height[l]; if (data_w < 4) data_w = 4; if (data_h < 4) data_h = 4; -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(USING_GLES2) int compressed_image_bytes = data_w * data_h / 2; glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); GL_CHECK(); @@ -247,7 +242,7 @@ bool Texture::LoadZIM(const char *filename) { #endif } GL_CHECK(); -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); #endif } else { diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index b00d937d77..59db3ec0f2 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -1,15 +1,3 @@ -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - #include #include @@ -21,6 +9,7 @@ #include "gfx_es2/gl_state.h" #include "gfx/texture_atlas.h" #include "gfx/gl_debug_log.h" +#include "gfx/gl_common.h" enum { // Enough? diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index e28b003f6a..8a0517e0c4 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -1,29 +1,16 @@ -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include +#include + +#include "base/logging.h" +#include "gfx_es2/fbo.h" +#include "gfx/gl_common.h" + +#if defined(USING_GLES2) #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER #define GL_RGBA8 GL_RGBA #ifndef GL_DEPTH_COMPONENT24 #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #endif -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - -#include - -#include "base/logging.h" -#include "gfx_es2/fbo.h" - -// TODO: Move out -#if defined(ANDROID) || defined(BLACKBERRY) -#define GLES #endif // TODO: Breakout this GL extension checker in its own file. @@ -94,7 +81,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -#ifdef GLES +#ifdef USING_GLES2 if (gl_extensions.OES_packed_depth_stencil) { ILOG("Creating FBO using DEPTH24_STENCIL8"); // Standard method diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 7ed4ae3460..f6b36e4b9b 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -1,18 +1,8 @@ #pragma once -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif #include #include +#include "gfx/gl_common.h" // OpenGL state cache. Should convert all code to use this instead of directly calling glEnable etc, @@ -128,7 +118,7 @@ public: BoolState depthTest; STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(USING_GLES2) STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; #else STATE2(glDepthRange, double, double, 0.0, 1.0) depthRange; diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 2f7ecf8b1f..21483470a3 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -1,16 +1,3 @@ -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -typedef char GLchar; -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - #include #include @@ -19,7 +6,7 @@ typedef char GLchar; #include "base/logging.h" #include "file/vfs.h" -#include "gfx_es2/glsl_program.h" +#include "glsl_program.h" static std::set active_programs; @@ -37,7 +24,7 @@ bool CompileShader(const char *source, GLuint shader, const char *filename) { ELOG("Error in shader compilation of %s!\n", filename); ELOG("Info log: %s\n", infoLog); ELOG("Shader source:\n%s\n", (const char *)source); -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(ARM) exit(1); #endif return false; diff --git a/gfx_es2/glsl_program.h b/gfx_es2/glsl_program.h index 18fa819fc8..f2417d40a3 100644 --- a/gfx_es2/glsl_program.h +++ b/gfx_es2/glsl_program.h @@ -4,22 +4,11 @@ #ifndef _RENDER_UTIL #define _RENDER_UTIL -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - #include #include #include "gfx/gl_lost_manager.h" +#include "gfx/gl_common.h" // Represent a compiled and linked vshader/fshader pair. // A just-constructed object is valid but cannot be used as a shader program, meaning that diff --git a/math/math_util.cpp b/math/math_util.cpp index 70ecede4da..bab216b95f 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -17,7 +17,7 @@ unsigned int GenerateRandomNumber() { #include -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(ARM) void EnableFZ() { From 8b6adf4cd698227dfc51cbbed4f26cf2baffe69c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 26 Nov 2012 17:34:13 +0100 Subject: [PATCH 0179/1445] Add glDepthMask caching --- gfx_es2/gl_state.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index f6b36e4b9b..af0626a546 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -118,6 +118,9 @@ public: BoolState depthTest; STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; + + STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite; + #if defined(USING_GLES2) STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; #else From 0853b3ed8e7c4b862c4adb5f308d35bc3a2b1b79 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 27 Nov 2012 16:38:24 +0100 Subject: [PATCH 0180/1445] Add directory listings to VFS --- .../henrikrydgard/libnative/NativeGLView.java | 4 +- base/PCMain.cpp | 23 +++- file/file_util.cpp | 2 +- file/file_util.h | 1 + file/vfs.h | 6 +- file/zip_read.cpp | 103 ++++++++++++++++-- file/zip_read.h | 9 +- 7 files changed, 127 insertions(+), 21 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 6dafdc54ae..8a1f9c45d3 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -26,7 +26,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener { public NativeGLView(NativeActivity activity) { super(activity); setEGLContextClientVersion(2); - + /* if (Build.VERSION.SDK_INT >= 11) { try { Method method_setPreserveEGLContextOnPause = GLSurfaceView.class.getMethod( @@ -42,7 +42,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener { } catch (InvocationTargetException e) { e.printStackTrace(); } - } + }*/ // setEGLConfigChooser(5, 5, 5, 0, 16, 0); // setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 1a729541fd..df4529d253 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -140,23 +140,35 @@ int main(int argc, char *argv[]) { float zoom = 1.0f; bool tablet = false; + bool aspect43 = false; const char *zoomenv = getenv("ZOOM"); const char *tabletenv = getenv("TABLET"); + const char *ipad = getenv("IPAD"); + if (zoomenv) { zoom = atof(zoomenv); } if (tabletenv) { tablet = (bool)atoi(tabletenv); } - + if (ipad) aspect43 = true; + bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); + // Change these to temporarily test other resolutions. + aspect43 = false; tablet = false; + float density = 1.0f; + zoom = 1.5f; + if (landscape) { if (tablet) { pixel_xres = 1280 * zoom; pixel_yres = 800 * zoom; + } else if (aspect43) { + pixel_xres = 1024 * zoom; + pixel_yres = 768 * zoom; } else { pixel_xres = 800 * zoom; pixel_yres = 480 * zoom; @@ -168,6 +180,9 @@ int main(int argc, char *argv[]) { if (tablet) { pixel_xres = 800 * zoom; pixel_yres = 1280 * zoom; + } else if (aspect43) { + pixel_xres = 768 * zoom; + pixel_yres = 1024 * zoom; } else { pixel_xres = 480 * zoom; pixel_yres = 800 * zoom; @@ -243,7 +258,6 @@ int main(int argc, char *argv[]) { NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); #endif - float density = 1.0f; dp_xres = (float)pixel_xres * density / zoom; dp_yres = (float)pixel_yres * density / zoom; pixel_in_dps = (float)pixel_xres / dp_xres; @@ -344,8 +358,9 @@ int main(int argc, char *argv[]) { } // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though - // exit(0); - +#ifdef _WIN32 + exit(0); +#endif NativeShutdownGraphics(); SDL_PauseAudio(1); SDL_CloseAudio(); diff --git a/file/file_util.cpp b/file/file_util.cpp index 5a8a557357..28dec171a0 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -191,7 +191,7 @@ size_t getFilesInDir(const char *directory, std::vector *files, const info.name = virtualName; info.fullName = std::string(directory) + "/" + virtualName; info.isDirectory = isDirectory(info.fullName); - + info.exists = true; if (!info.isDirectory) { std::string ext = getFileExtension(info.fullName); if (filter) { diff --git a/file/file_util.h b/file/file_util.h index d83172a2ae..c361c0da72 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -13,6 +13,7 @@ struct FileInfo { std::string name; std::string fullName; + bool exists; bool isDirectory; bool operator <(const FileInfo &other) const { diff --git a/file/vfs.h b/file/vfs.h index b5a5643c8e..da302a11cd 100644 --- a/file/vfs.h +++ b/file/vfs.h @@ -1,5 +1,7 @@ -#include "base/basictypes.h" +#pragma once +#include "base/basictypes.h" +#include "file/file_util.h" // Basic virtual file system. Used to manage assets on Android, where we have to // read them manually out of the APK zipfile, while being able to run on other // platforms as well with the appropriate directory set-up. @@ -13,3 +15,5 @@ void VFSShutdown(); // Always allocates an extra zero byte at the end, so that it // can be used for text like shader sources. uint8_t *VFSReadFile(const char *filename, size_t *size); +bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter = 0); +//bool VFSGetFileInfo(const char *filename, FileInfo *fileInfo); diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 27d3a300e4..4631e48a65 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -1,6 +1,8 @@ #include +#include +#include -#ifndef _WIN32 +#ifdef ANDROID #include #endif @@ -8,7 +10,7 @@ #include "base/logging.h" #include "file/zip_read.h" -#ifndef _WIN32 +#ifdef ANDROID uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. struct zip_stat zstat; @@ -49,23 +51,24 @@ uint8_t *ReadLocalFile(const char *filename, size_t *size) { return contents; } -#ifndef _WIN32 +#ifdef ANDROID ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { + ELOG("ZIP File %s", zip_file); zip_file_ = zip_open(zip_file, 0, NULL); strcpy(in_zip_path_, in_zip_path); if (!zip_file_) { ELOG("Failed to open %s as a zip file", zip_file); } - // This is not really necessary. - int numFiles = zip_get_num_files(zip_file_); - for (int i = 0; i < numFiles; i++) { - const char* name = zip_get_name(zip_file_, i, 0); - if (name == NULL) { - ELOG("Error reading zip file name at index %i : %s", i, zip_strerror(zip_file_)); - return; + + std::vector info; + GetFileListing("assets", &info, 0); + for (int i = 0; i < info.size(); i++) { + if (info[i].isDirectory) { + ILOG("Directory: %s", info[i].name.c_str()); + } else { + ILOG("File: %s", info[i].name.c_str()); } - // ILOG("File %i : %s\n", i, name); } } @@ -80,6 +83,62 @@ uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { return ReadFromZip(zip_file_, temp_path, size); } +bool ZipAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) +{ + // We just loop through the whole ZIP file and deduce what files are in this directory, and what subdirectories there are. + std::set files; + std::set directories; + int numFiles = zip_get_num_files(zip_file_); + size_t pathlen = strlen(path); + if (path[pathlen-1] == '/') + pathlen--; + for (int i = 0; i < numFiles; i++) { + const char* name = zip_get_name(zip_file_, i, 0); + if (!name) + continue; + // ILOG("Comparing %s %s %i", name, path, pathlen); + if (!memcmp(name, path, pathlen)) { + // The prefix is right. Let's see if this is a file or path. + char *slashPos = strchr(name + pathlen + 1, '/'); + if (slashPos != 0) { + // A directory. + std::string dirName = std::string(name + pathlen + 1, slashPos - (name + pathlen + 1)); + directories.insert(dirName); + } else { + files.insert(std::string(name + pathlen + 1)); + } + } + } + + for (auto diter = directories.begin(); diter != directories.end(); ++diter) { + FileInfo info; + info.name = *diter; + info.fullName = std::string(path); + if (info.fullName[info.fullName.size()-1] == '/') + info.fullName = info.fullName.substr(0, info.fullName.size() - 1); + info.fullName += "/" + *diter; + info.exists = true; + info.isDirectory = true; + listing->push_back(info); + } + + for (auto fiter = files.begin(); fiter != files.end(); ++fiter) { + FileInfo info; + info.name = *fiter; + info.fullName = std::string(path); + if (info.fullName[info.fullName.size()-1] == '/') + info.fullName = info.fullName.substr(0, info.fullName.size() - 1); + info.fullName += "/" + *fiter; + info.exists = true; + info.isDirectory = false; + listing->push_back(info); + } + + std::sort(listing->begin(), listing->end()); + + return true; +} + #endif uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { @@ -95,6 +154,13 @@ uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { return ReadLocalFile(new_path, size); } +bool DirectoryAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) +{ + getFilesInDir(path, listing, filter); + return true; +} + + struct VFSEntry { const char *prefix; AssetReader *reader; @@ -135,3 +201,18 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { ELOG("Missing filesystem for %s", filename); return 0; } + +bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter) +{ + int fn_len = strlen(path); + for (int i = 0; i < num_entries; i++) { + int prefix_len = strlen(entries[i].prefix); + if (prefix_len >= fn_len) continue; + if (0 == memcmp(path, entries[i].prefix, prefix_len)) { + entries[i].reader->GetFileListing(path + prefix_len, listing, filter); + return true; + } + } + ELOG("Missing filesystem for %s", path); + return false; +} diff --git a/file/zip_read.h b/file/zip_read.h index 2c85ec4504..e155386d4c 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -1,6 +1,6 @@ // TODO: Move much of this code to vfs.cpp -#ifndef _WIN32 +#ifdef ANDROID #include #endif @@ -9,6 +9,7 @@ #include "base/basictypes.h" #include "file/vfs.h" +#include "file/file_util.h" // Direct readers. deallocate using delete []. uint8_t *ReadLocalFile(const char *filename, size_t *size); @@ -18,10 +19,12 @@ public: virtual ~AssetReader() {} // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; + // Filter support is optional but nice to have + virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; virtual std::string toString() const = 0; }; -#ifndef _WIN32 +#ifdef ANDROID uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size); class ZipAssetReader : public AssetReader { public: @@ -29,6 +32,7 @@ public: ~ZipAssetReader(); // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size); + virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter); virtual std::string toString() const { return in_zip_path_; } @@ -46,6 +50,7 @@ public: } // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size); + virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter); virtual std::string toString() const { return path_; } From 8c7b70e0d9e24e0569bb4f8a434833d4c707e54c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 27 Nov 2012 16:53:22 +0100 Subject: [PATCH 0181/1445] SDL include workaround --- base/PCMain.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index ea0830e255..ba944da919 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -12,12 +12,17 @@ #endif #include - +#ifdef _WIN32 +#include "SDL/SDL.h" +#include "SDL/SDL_timer.h" +#include "SDL/SDL_audio.h" +#include "SDL/SDL_video.h" +#else #include "SDL.h" #include "SDL_timer.h" #include "SDL_audio.h" #include "SDL_video.h" - +#endif #include "base/display.h" #include "base/logging.h" #include "base/timeutil.h" From c0f531d182cf984ce2a27627a7120ce0342e5a9a Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 28 Nov 2012 23:00:38 +1000 Subject: [PATCH 0182/1445] Use swipe down or back to pause game on Blackberry (sets PAD_BUTTON_MENU). Fix a glitch which prevented keys from being set. --- base/BlackberryMain.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 2a89dd10ae..ebae1546d0 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -107,7 +107,7 @@ const int buttonMappings[18] = { KEYCODE_DOWN, //DOWN KEYCODE_LEFT, //LEFT KEYCODE_RIGHT, //RIGHT - KEYCODE_M, //MENU + NULL, //MENU (SwipeDown) KEYCODE_BACKSPACE, //BACK KEYCODE_I, //JOY UP KEYCODE_K, //JOY DOWN @@ -301,6 +301,7 @@ int main(int argc, char *argv[]) { while (running) { input_state.mouse_valid = false; input_state.accelerometer_valid = false; + SimulateGamepad(&input_state); while (true) { // Handle Blackberry events bps_event_t *event = NULL; @@ -356,17 +357,24 @@ int main(int argc, char *argv[]) { } break; } - } else if ((domain == navigator_get_domain()) - && (NAVIGATOR_EXIT == bps_event_get_code(event))) { - running = false; + } else if (domain == navigator_get_domain()) { + switch(bps_event_get_code(event)) + { + case NAVIGATOR_BACK: + case NAVIGATOR_SWIPE_DOWN: + input_state.pad_buttons |= PAD_BUTTON_MENU; + break; + case NAVIGATOR_EXIT: + running = false; + break; + } } } - SimulateGamepad(&input_state); UpdateInputState(&input_state); NativeUpdate(input_state); - NativeRender(); EndInputState(&input_state); + NativeRender(); eglSwapBuffers(egl_disp, egl_surf); From e6260474093ee05bc0cb0b812526eeca4906faa1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 29 Nov 2012 14:38:50 +0100 Subject: [PATCH 0183/1445] Add glColorMask to glstate --- gfx_es2/gl_state.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index af0626a546..034e334ed2 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -80,6 +80,28 @@ private: } \ } + #define STATE4(func, p1type, p2type, p3type, p4type, p1def, p2def, p3def, p4def) \ + class SavedState4_##func { \ + p1type p1; \ + p2type p2; \ + p3type p3; \ + p4type p4; \ + public: \ + SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) {}; \ + inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \ + if(newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \ + p1 = newp1; \ + p2 = newp2; \ + p3 = newp3; \ + p4 = newp4; \ + func(p1, p2, p3, p4); \ + } \ + } \ + inline void restore() { \ + func(p1, p2, p3, p4); \ + } \ + } + #define STATEFLOAT4(func, def) \ class SavedState4_##func { \ float p[4]; \ @@ -121,6 +143,8 @@ public: STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite; + STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask; + #if defined(USING_GLES2) STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; #else From c952c8d0e714a62ae00012bacb8cb34129ad60b2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 1 Dec 2012 10:35:55 +0100 Subject: [PATCH 0184/1445] Fix volume buttons on android and add some functonality to the VFS. --- android/app-android.cpp | 8 ++- .../libnative/NativeActivity.java | 47 ++++++++++------- base/NativeApp.h | 6 ++- base/PCMain.cpp | 10 ++-- base/mutex.h | 6 ++- file/chunk_file.cpp | 1 + file/file_util.cpp | 35 +++++++++++-- file/file_util.h | 4 +- file/vfs.h | 2 +- file/zip_read.cpp | 50 +++++++++++++++++-- file/zip_read.h | 3 ++ gfx/texture.h | 15 +++--- ui/screen.cpp | 6 +++ ui/screen.h | 4 ++ 14 files changed, 153 insertions(+), 44 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 5eaaa513ec..19a8bf84e6 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -60,7 +60,7 @@ void ShowAd(int x, int y, bool center_x) { } void ShowKeyboard() { - frameCommand = "showkeyboard"; + frameCommand = "showKeyboard"; frameCommandParam = ""; } @@ -84,6 +84,11 @@ void LaunchEmail(const char *email_address) { frameCommandParam = email_address; } +void System_InputBox(const char *title, const char *defaultValue) { + frameCommand = "inputBox"; + frameCommandParam = title; +} + // Remember that all of these need initialization on init! The process // may be reused when restarting the game. Globals are DANGEROUS. @@ -370,6 +375,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage std::string msg = GetJavaString(env, message); std::string prm = GetJavaString(env, param); ILOG("Message received: %s %s", msg.c_str(), prm.c_str()); + NativeMessageReceived(msg.c_str(), prm.c_str()); } diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 8e0791dfc8..bf71b7b221 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -241,32 +241,37 @@ public class NativeActivity extends Activity { public boolean onKeyDown(int keyCode, KeyEvent event) { // Eat these keys, to avoid accidental exits / other screwups. // Maybe there's even more we need to eat on tablets? - if (keyCode == KeyEvent.KEYCODE_BACK) { + switch (keyCode) { + case KeyEvent.KEYCODE_BACK: if (event.isAltPressed()) { NativeApp.keyDown(1004); // special custom keycode } else { NativeApp.keyDown(1); } - } - else if (keyCode == KeyEvent.KEYCODE_MENU) { + return true; + case KeyEvent.KEYCODE_MENU: NativeApp.keyDown(2); - } - else if (keyCode == KeyEvent.KEYCODE_SEARCH) { + return true; + case KeyEvent.KEYCODE_SEARCH: NativeApp.keyDown(3); - } - else { + return true; + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_VOLUME_UP: + return false; + default: // send the rest of the keys through. // TODO: get rid of the three special cases above by adjusting the native side of the code. NativeApp.keyDown(keyCode); + return true; } - return true; } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { // Eat these keys, to avoid accidental exits / other screwups. // Maybe there's even more we need to eat on tablets? - if (keyCode == KeyEvent.KEYCODE_BACK) { + switch (keyCode) { + case KeyEvent.KEYCODE_BACK: if (event.isAltPressed()) { NativeApp.keyUp(1004); // special custom keycode } @@ -275,21 +280,24 @@ public class NativeActivity extends Activity { } else { NativeApp.keyUp(1); } - } - else if (keyCode == KeyEvent.KEYCODE_MENU) { + return true; + case KeyEvent.KEYCODE_MENU: // Menu should be ignored from SDK 11 forwards. We send it to the app. NativeApp.keyUp(2); - } - else if (keyCode == KeyEvent.KEYCODE_SEARCH) { + return true; + case KeyEvent.KEYCODE_SEARCH: // Search probably should also be ignored. We send it to the app. NativeApp.keyUp(3); - } - else { + return true; + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_VOLUME_UP: + return false; + default: // send the rest of the keys through. // TODO: get rid of the three special cases above by adjusting the native side of the code. NativeApp.keyUp(keyCode); + return true; } - return true; } // Prevent destroying and recreating the main activity when the device rotates etc, @@ -333,6 +341,7 @@ public class NativeActivity extends Activity { dlg.show(); if (inputBoxCancelled) return null; + NativeApp.sendMessage("INPUTBOX:" + title, input.getText().toString()); return input.getText().toString(); } @@ -356,11 +365,11 @@ public class NativeActivity extends Activity { } else if (command.equals("toast")) { Toast toast = Toast.makeText(this, params, Toast.LENGTH_SHORT); toast.show(); - } else if (command.equals("showkeyboard")) { + } else if (command.equals("showKeyboard")) { //InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); //inputMethodManager.toggleSoftInputFromWindow(this, InputMethodManager.SHOW_FORCED, 0); - } else if (command.equals("gettext")) { - inputBox("Enter text", params, "OK"); + } else if (command.equals("inputBox")) { + inputBox(params, "", "OK"); } else { Log.e(TAG, "Unsupported command " + command + " , param: " + params); } diff --git a/base/NativeApp.h b/base/NativeApp.h index c2e187b549..677568c075 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -11,12 +11,15 @@ // This is defined in input/input_state.h. struct InputState; -// You must implement this. The first function to get called, just write strings to the two pointers. +// The first function to get called, just write strings to the two pointers. // This might get called multiple times in some implementations, you must be able to handle that. // The detected DP dimensions of the screen are set as dp_xres and dp_yres and you're free to change // them if you have a fixed-size app that needs to stretch a little to fit. void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape); +// Generic host->C++ messaging, used for functionality like system-native popup input boxes. +void NativeMessageReceived(const char *message, const char *value); + // For the back button to work right, this should return true on your main or title screen. // Otherwise, just return false. bool NativeIsAtTopLevel(); @@ -90,3 +93,4 @@ void Vibrate(int length_ms); void LaunchBrowser(const char *url); void LaunchMarket(const char *url); void LaunchEmail(const char *email_address); +void System_InputBox(const char *title, const char *defaultValue); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index ba944da919..97febbc00e 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -44,7 +44,6 @@ void SystemToast(const char *text) { #endif } - void ShowAd(int x, int y, bool center_x) { // Ignore ads on PC } @@ -57,6 +56,11 @@ void Vibrate(int length_ms) { // Ignore on PC } +void System_InputBox(const char *title, const char *defaultValue) { + // Stub + NativeMessageReceived((std::string("INPUTBOX:") + title).c_str(), "TestFile"); +} + void LaunchBrowser(const char *url) { #ifdef _WIN32 @@ -154,7 +158,7 @@ int main(int argc, char *argv[]) { zoom = atof(zoomenv); } if (tabletenv) { - tablet = (bool)atoi(tabletenv); + tablet = atoi(tabletenv) ? true : false; } if (ipad) aspect43 = true; @@ -165,7 +169,7 @@ int main(int argc, char *argv[]) { aspect43 = false; tablet = false; float density = 1.0f; - zoom = 1.5f; + //zoom = 1.5f; if (landscape) { if (tablet) { diff --git a/base/mutex.h b/base/mutex.h index 5679eecf1f..59594ae883 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -33,7 +33,11 @@ public: #ifdef _WIN32 InitializeCriticalSection(&mut_); #else - pthread_mutex_init(&mut_, NULL); + // Critical sections are recursive so let's make these recursive too. + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mut_, &attr); #endif } ~recursive_mutex() { diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index c162f2913a..f3174a4727 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -17,6 +17,7 @@ ChunkFile::ChunkFile(const char *filename, bool _read) { if (fastMode) { size_t size; + ILOG("VFSReadFile %s", filename); data = (uint8_t *)VFSReadFile(filename, &size); if (!data) { ELOG("Chunkfile fail: %s", filename); diff --git a/file/file_util.cpp b/file/file_util.cpp index 29d42d08f4..d03900a4a4 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -1,6 +1,7 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include +#include #else #include #include @@ -104,23 +105,40 @@ bool exists(const std::string &filename) // Returns true if filename is a directory bool isDirectory(const std::string &filename) { + FileInfo info; + getFileInfo(filename.c_str(), &info); + return info.isDirectory; +} + +bool getFileInfo(const char *path, FileInfo *fileInfo) +{ + // TODO: Expand relative paths? + fileInfo->fullName = path; + #ifdef _WIN32 - return (GetFileAttributes(filename.c_str()) & FILE_ATTRIBUTE_DIRECTORY) != 0; + DWORD attributes = GetFileAttributes(path); + fileInfo->isDirectory = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + fileInfo->isWritable = (attributes & FILE_ATTRIBUTE_READONLY) == 0; #else struct stat64 file_info; - std::string copy(filename); + std::string copy(path); stripTailDirSlashes(copy); int result = stat64(copy.c_str(), &file_info); if (result < 0) { - WLOG("IsDirectory: stat failed on %s", filename.c_str()); + WLOG("IsDirectory: stat failed on %s", path); return false; } - return S_ISDIR(file_info.st_mode); + fileInfo->isDirectory = S_ISDIR(file_info.st_mode); + fileInfo->isWritable = false; + // HACK: approximation + if (file_info.st_mode & 0200) + fileInfo->isWritable = true; #endif + return true; } std::string getFileExtension(const std::string &fn) { @@ -246,3 +264,12 @@ std::string getDir(const std::string &path) #endif return cutpath; } + +void mkDir(const std::string &path) +{ +#ifdef _WIN32 + mkdir(path.c_str()); +#else + mkdir(path.c_str(), 0777); +#endif +} diff --git a/file/file_util.h b/file/file_util.h index c361c0da72..2627bd11f3 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -15,6 +15,7 @@ struct FileInfo std::string fullName; bool exists; bool isDirectory; + bool isWritable; bool operator <(const FileInfo &other) const { if (isDirectory && !other.isDirectory) @@ -29,8 +30,9 @@ struct FileInfo }; std::string getFileExtension(const std::string &fn); +bool getFileInfo(const char *path, FileInfo *fileInfo); size_t getFilesInDir(const char *directory, std::vector *files, const char *filter = 0); void deleteFile(const char *file); bool exists(const std::string &filename); - +void mkDir(const std::string &path); std::string getDir(const std::string &path); diff --git a/file/vfs.h b/file/vfs.h index da302a11cd..ce1023b635 100644 --- a/file/vfs.h +++ b/file/vfs.h @@ -16,4 +16,4 @@ void VFSShutdown(); // can be used for text like shader sources. uint8_t *VFSReadFile(const char *filename, size_t *size); bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter = 0); -//bool VFSGetFileInfo(const char *filename, FileInfo *fileInfo); +bool VFSGetFileInfo(const char *filename, FileInfo *fileInfo); diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 4631e48a65..fc2460e8ff 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -118,6 +118,7 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis info.fullName = info.fullName.substr(0, info.fullName.size() - 1); info.fullName += "/" + *diter; info.exists = true; + info.isWritable = false; info.isDirectory = true; listing->push_back(info); } @@ -130,15 +131,23 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis info.fullName = info.fullName.substr(0, info.fullName.size() - 1); info.fullName += "/" + *fiter; info.exists = true; + info.isWritable = false; info.isDirectory = false; listing->push_back(info); } std::sort(listing->begin(), listing->end()); - return true; } +bool ZipAssetReader::GetFileInfo(const char *path, FileInfo *info) +{ + info->fullName = path; + info->exists = true; // TODO + info->isWritable = false; + info->isDirectory = false; // TODO +} + #endif uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { @@ -150,16 +159,35 @@ uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { strcpy(new_path, path_); } strcat(new_path, path); - // ILOG("New path: %s", new_path); return ReadLocalFile(new_path, size); } bool DirectoryAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) { - getFilesInDir(path, listing, filter); + char new_path[256] = {0}; + // Check if it already contains the path + if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { + } + else { + strcpy(new_path, path_); + } + strcat(new_path, path); + getFilesInDir(new_path, listing, filter); return true; } +bool DirectoryAssetReader::GetFileInfo(const char *path, FileInfo *info) +{ + char new_path[256] = {0}; + // Check if it already contains the path + if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { + } + else { + strcpy(new_path, path_); + } + strcat(new_path, path); + return getFileInfo(new_path, info); +} struct VFSEntry { const char *prefix; @@ -189,7 +217,7 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { int prefix_len = strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { - // ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); + ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); if (data) return data; @@ -216,3 +244,17 @@ bool VFSGetFileListing(const char *path, std::vector *listing, const c ELOG("Missing filesystem for %s", path); return false; } + +bool VFSGetFileInfo(const char *path, FileInfo *info) +{ + int fn_len = strlen(path); + for (int i = 0; i < num_entries; i++) { + int prefix_len = strlen(entries[i].prefix); + if (prefix_len >= fn_len) continue; + if (0 == memcmp(path, entries[i].prefix, prefix_len)) { + return entries[i].reader->GetFileInfo(path + prefix_len, info); + } + } + ELOG("Missing filesystem for %s", path); + return false; +} diff --git a/file/zip_read.h b/file/zip_read.h index e155386d4c..0857bfc86c 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -21,6 +21,7 @@ public: virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; // Filter support is optional but nice to have virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; + virtual bool GetFileInfo(const char *path, FileInfo *info) = 0; virtual std::string toString() const = 0; }; @@ -33,6 +34,7 @@ public: // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size); virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter); + virtual bool GetFileInfo(const char *path, FileInfo *info); virtual std::string toString() const { return in_zip_path_; } @@ -51,6 +53,7 @@ public: // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size); virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter); + virtual bool GetFileInfo(const char *path, FileInfo *info); virtual std::string toString() const { return path_; } diff --git a/gfx/texture.h b/gfx/texture.h index 65479f76a8..47f6e6b602 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -3,7 +3,6 @@ // Load and manage OpenGL textures easily. Supports ETC1 compressed texture with mipmaps. - #include #include "gfx/gl_lost_manager.h" @@ -13,19 +12,11 @@ public: Texture(); ~Texture(); - bool LoadZIM(const char *filename); -#if !defined(USING_GLES2) - bool LoadPNG(const char *filename); -#endif - bool LoadXOR(); // Loads a placeholder texture. - // Deduces format from the filename. // If loading fails, will load a 256x256 XOR texture. // If filename begins with "gen:", will defer to texture_gen.cpp/h. bool Load(const char *filename); - void Bind(int stage = -1); - void Destroy(); unsigned int Handle() const { @@ -36,6 +27,12 @@ public: std::string filename() const { return filename_; } private: + bool LoadZIM(const char *filename); +#if !defined(USING_GLES2) + bool LoadPNG(const char *filename); +#endif + bool LoadXOR(); // Loads a placeholder texture. + std::string filename_; #ifdef METRO ID3D11Texture2D *tex_; diff --git a/ui/screen.cpp b/ui/screen.cpp index db0cd5fa37..e4d3e7b57c 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -97,6 +97,12 @@ void ScreenManager::render() { processFinishDialog(); } +void ScreenManager::sendMessage(const char *msg, const char *value) +{ + if (stack_.size()) + stack_.back().screen->sendMessage(msg, value); +} + void ScreenManager::deviceLost() { if (stack_.size()) diff --git a/ui/screen.h b/ui/screen.h index 14f7cd85cb..883b381e5e 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -40,6 +40,7 @@ public: virtual void deviceLost() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} virtual void touch(int pointer, float x, float y, double time, TouchEvent event) {} + virtual void sendMessage(const char *msg, const char *value) {} ScreenManager *screenManager() { return screenManager_; } void setScreenManager(ScreenManager *sm) { screenManager_ = sm; } @@ -86,6 +87,9 @@ public: // Instant touch, separate from the update() mechanism. void touch(int pointer, float x, float y, double time, TouchEvent event); + // Generic facility for gross hacks :P + void sendMessage(const char *msg, const char *value); + private: void pop(); void switchToNext(); From 3785e2994de2b8121c2cef6a4552b4f03bf22a2a Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 2 Dec 2012 15:53:13 +1000 Subject: [PATCH 0185/1445] Blackberry 10 Port * Replace SDL with asound backend (removes the only dependency) * Use BlackberryAudio to expose asound (Known bug: delayed audio) * Proper spacing for keyboard keys * Clean up for BlackberryMain.cpp * Remove some redundancies for Blackberry EGL setup --- base/BlackberryMain.cpp | 247 ++++++++++++++++++++++++++-------------- 1 file changed, 162 insertions(+), 85 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index ebae1546d0..7780129745 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -8,9 +8,8 @@ #include #include -// TODO: Replace SDL with asound -#include "SDL/SDL.h" -#include "SDL/SDL_audio.h" +#include +#include #include #include @@ -94,25 +93,26 @@ void LaunchEmail(const char *email_address) navigator_invoke((std::string("mailto:") + email_address).c_str(), &error); } +// Input const int buttonMappings[18] = { - KEYCODE_X, //A - KEYCODE_S, //B - KEYCODE_Z, //X - KEYCODE_A, //Y - KEYCODE_W, //LBUMPER - KEYCODE_Q, //RBUMPER - KEYCODE_ONE, //START - KEYCODE_TWO, //SELECT - KEYCODE_UP, //UP - KEYCODE_DOWN, //DOWN - KEYCODE_LEFT, //LEFT - KEYCODE_RIGHT, //RIGHT - NULL, //MENU (SwipeDown) - KEYCODE_BACKSPACE, //BACK - KEYCODE_I, //JOY UP - KEYCODE_K, //JOY DOWN - KEYCODE_J, //JOY LEFT - KEYCODE_L, //JOY RIGHT + KEYCODE_X, //A + KEYCODE_S, //B + KEYCODE_Z, //X + KEYCODE_A, //Y + KEYCODE_W, //LBUMPER + KEYCODE_Q, //RBUMPER + KEYCODE_ONE, //START + KEYCODE_TWO, //SELECT + KEYCODE_UP, //UP + KEYCODE_DOWN, //DOWN + KEYCODE_LEFT, //LEFT + KEYCODE_RIGHT, //RIGHT + 0, //MENU (SwipeDown) + KEYCODE_BACKSPACE, //BACK + KEYCODE_I, //JOY UP + KEYCODE_K, //JOY DOWN + KEYCODE_J, //JOY LEFT + KEYCODE_L, //JOY RIGHT }; void SimulateGamepad(InputState *input) { @@ -130,33 +130,24 @@ void SimulateGamepad(InputState *input) { input->pad_lstick_x=-1; else if (input->pad_buttons | (1<<17)) input->pad_lstick_x=1; - /*if (keys[SDLK_KP8]) - input->pad_rstick_y=1; - else if (keys[SDLK_KP2]) - input->pad_rstick_y=-1; - if (keys[SDLK_KP4]) - input->pad_rstick_x=-1; - else if (keys[SDLK_KP6]) - input->pad_rstick_x=1;*/ } +// Video int init_GLES2(screen_context_t ctx) { - int usage = SCREEN_USAGE_DISPLAY | SCREEN_USAGE_OPENGL_ES2; - int format = SCREEN_FORMAT_RGBA8888; + int usage = SCREEN_USAGE_ROTATION | SCREEN_USAGE_OPENGL_ES2; + int format = SCREEN_FORMAT_RGBX8888; int num_configs; - const int intInterval = 0; - EGLint attrib_list[]= { EGL_RED_SIZE, 8, + EGLint attrib_list[]= { + EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_STENCIL_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE}; - usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION; const EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; const EGLint egl_surfaceAttr[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE }; @@ -197,7 +188,6 @@ int init_GLES2(screen_context_t ctx) { pixel_xres = screen_resolution[1]; } } - screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SWAP_INTERVAL, &intInterval); screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size); screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle); @@ -205,10 +195,7 @@ int init_GLES2(screen_context_t ctx) { egl_disp = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(egl_disp, NULL, NULL); - if (eglChooseConfig(egl_disp, attrib_list, &egl_conf, 1, &num_configs) != EGL_TRUE || egl_conf == 0) - { - printf("Configs weren't set!\n"); - } + eglChooseConfig(egl_disp, attrib_list, &egl_conf, 1, &num_configs); egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, attributes); egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, egl_surfaceAttr); @@ -240,10 +227,129 @@ void kill_GLES2() { eglReleaseThread(); } -extern void mixaudio(void *userdata, Uint8 *stream, int len) { - NativeMix((short *)stream, len / 4); -} +// Audio +#define AUDIO_CHANNELS 2 +#define AUDIO_FREQ 44100 +#define AUDIO_SAMPLES 1024 +class BlackberryAudio +{ +public: + BlackberryAudio() + { + paused = false; + OpenAudio(); + } + ~BlackberryAudio() + { + pthread_cancel(thread_handle); + snd_pcm_plugin_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK); + snd_mixer_close(mixer_handle); + snd_pcm_close(pcm_handle); + free(mixer_handle); + free(pcm_handle); + } + void setPaused(bool pause) + { + paused = pause; + } + static void* staticThreadProc(void* arg) + { + return reinterpret_cast(arg)->RunAudio(); + } +private: + void OpenAudio() + { + int card = -1, dev = 0; + snd_pcm_channel_info_t pi; + snd_mixer_group_t group; + snd_pcm_channel_params_t pp; + snd_pcm_channel_setup_t setup; + + mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; + mixbuf = (uint8_t*)malloc(mixlen); + if (mixbuf == NULL) + return; + memset(mixbuf, 0, mixlen); + + if ((snd_pcm_open_preferred(&pcm_handle, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0) + return; + + memset(&pi, 0, sizeof (pi)); + pi.channel = SND_PCM_CHANNEL_PLAYBACK; + if ((snd_pcm_plugin_info (pcm_handle, &pi)) < 0) + return; + + memset(&pp, 0, sizeof (pp)); + pp.mode = SND_PCM_MODE_BLOCK; + pp.channel = SND_PCM_CHANNEL_PLAYBACK; + pp.start_mode = SND_PCM_START_FULL; + pp.stop_mode = SND_PCM_STOP_STOP; + + pp.buf.block.frag_size = pi.max_fragment_size; + pp.buf.block.frags_max = -1; + pp.buf.block.frags_min = 1; + + pp.format.interleave = 1; + pp.format.rate = AUDIO_FREQ; + pp.format.voices = AUDIO_CHANNELS; + pp.format.format = SND_PCM_SFMT_S16_LE; + + if ((snd_pcm_plugin_params (pcm_handle, &pp)) < 0) + return; + + snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK); + + memset (&setup, 0, sizeof(setup)); + memset (&group, 0, sizeof(group)); + setup.channel = SND_PCM_CHANNEL_PLAYBACK; + setup.mixer_gid = &group.gid; + if ((snd_pcm_plugin_setup (pcm_handle, &setup)) < 0) + return; + setup.buf.block.frag_size; + if ((snd_mixer_open(&mixer_handle, card, setup.mixer_device)) < 0) + return; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&thread_handle, &attr, &BlackberryAudio::staticThreadProc, this); + } + void* RunAudio() + { + while(true) + { + if (!paused) + { + memset(mixbuf, 0, mixlen); + NativeMix((short *)mixbuf, mixlen / 4); + + fd_set rfds, wfds; + int nflds; + if (!paused && (FD_ISSET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds))) + { + snd_pcm_plugin_write(pcm_handle, mixbuf, mixlen); + } + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + FD_SET(snd_mixer_file_descriptor(mixer_handle), &rfds); + FD_SET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds); + nflds = std::max(snd_mixer_file_descriptor(mixer_handle), snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK)); + select (nflds+1, &rfds, &wfds, NULL, NULL); + } + else + delay((AUDIO_SAMPLES*1000)/AUDIO_FREQ); + } + } + snd_pcm_t* pcm_handle; + snd_mixer_t* mixer_handle; + int mixlen; + uint8_t* mixbuf; + pthread_t thread_handle; + bool paused; +}; + +// Entry Point int main(int argc, char *argv[]) { static screen_context_t screen_cxt; // Receive events from window manager @@ -252,51 +358,34 @@ int main(int argc, char *argv[]) { bps_initialize(); net::Init(); - if (SDL_Init(SDL_INIT_AUDIO) < 0) { - fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); - return 1; - } init_GLES2(screen_cxt); - // Playbook: 1024x600@7", Dev Alpha: 1280x768@4.2" #ifdef BLACKBERRY10 + // Dev Alpha: 1280x768, 4.2", 356DPI, 0.6f scale int dpi; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_DPI, &dpi); - float dpi_scale = 222.5f / dpi; #else - float dpi_scale = 1.1f; + // Playbook: 1024x600, 7", 170DPI, 1.25f scale + int screen_phys_size[2]; + screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_PHYSICAL_SIZE, screen_phys_size); + int screen_resolution[2]; + screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution); + double diagonal_pixels = sqrt(screen_resolution[0] * screen_resolution[0] + screen_resolution[1] * screen_resolution[1]); + double diagonal_inches = 0.0393700787 * sqrt(screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1]); + int dpi = (int)(diagonal_pixels / diagonal_inches + 0.5); #endif + float dpi_scale = 213.6f / dpi; dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); NativeInit(argc, (const char **)argv, "data/", "/accounts/1000/shared", "BADCOFFEE"); NativeInitGraphics(); screen_request_events(screen_cxt); navigator_request_events(0); - // Yes, we only want landscape. - navigator_rotation_lock(false); dialog_request_events(0); #ifdef BLACKBERRY10 vibration_request_events(0); #endif - - SDL_AudioSpec fmt; - fmt.freq = 44100; - fmt.format = AUDIO_S16; - fmt.channels = 2; - fmt.samples = 1024; - fmt.callback = &mixaudio; - fmt.userdata = (void *)0; - - if (SDL_OpenAudio(&fmt, NULL) < 0) { - ELOG("Failed to open audio: %s", SDL_GetError()); - return 1; - } - - // Audio must be unpaused _after_ NativeInit() - SDL_PauseAudio(0); - + BlackberryAudio* audio = new BlackberryAudio(); InputState input_state; - int framecount = 0; - float t = 0; bool running = true; while (running) { input_state.mouse_valid = false; @@ -370,32 +459,20 @@ int main(int argc, char *argv[]) { } } } - UpdateInputState(&input_state); NativeUpdate(input_state); EndInputState(&input_state); NativeRender(); - + // On Blackberry, this handles VSync for us eglSwapBuffers(egl_disp, egl_surf); - - // Simple frame rate limiting - while (time_now() < t + 1.0f/60.0f) { - sleep_ms(0); - time_update(); - } - time_update(); - t = time_now(); - framecount++; } screen_stop_events(screen_cxt); bps_shutdown(); NativeShutdownGraphics(); - SDL_PauseAudio(1); + delete audio; NativeShutdown(); - SDL_CloseAudio(); - SDL_Quit(); kill_GLES2(); net::Shutdown(); screen_destroy_context(screen_cxt); From 0d441906ccead856a6b635012e2758cdb518d90c Mon Sep 17 00:00:00 2001 From: "U-CARLOS-2P5HQ6IZ\\Carlos" Date: Sun, 2 Dec 2012 20:47:51 +0100 Subject: [PATCH 0186/1445] armv6support --- Android.mk | 10 +++++++-- math/math_utilarmv6.cpp | 47 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100755 math/math_utilarmv6.cpp diff --git a/Android.mk b/Android.mk index 0cbd849ae8..56edd11034 100644 --- a/Android.mk +++ b/Android.mk @@ -5,6 +5,7 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libnative +LOCAL_ARM_MODE := arm LOCAL_SRC_FILES :=\ android/native_audio.cpp \ audio/wav_read.cpp \ @@ -27,7 +28,6 @@ LOCAL_SRC_FILES :=\ file/zip_read.cpp \ json/json_writer.cpp \ math/curves.cpp \ - math/math_util.cpp \ math/lin/aabb.cpp.arm \ math/lin/plane.cpp.arm \ math/lin/quat.cpp.arm \ @@ -54,11 +54,17 @@ LOCAL_SRC_FILES :=\ ui/virtual_input.cpp \ util/random/perlin.cpp - LOCAL_CFLAGS := -O2 -DGL_GLEXT_PROTOTYPES -DARM -DUSING_GLES2 -fsigned-char -fno-strict-aliasing LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip +#Portable native and separate code on android in future is easy you needs add files +#by ($(target_arch_ABI),arquitecture (armeabi-v7a , armeabi , x86 , MIPS) +ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) +LOCAL_SRC_FILES += math/math_util.cpp +else ifeq ($(TARGET_ARCH_ABI),armeabi) +LOCAL_SRC_FILES += math/math_utilarmv6.cpp +endif include $(BUILD_STATIC_LIBRARY) diff --git a/math/math_utilarmv6.cpp b/math/math_utilarmv6.cpp new file mode 100755 index 0000000000..4271fb3460 --- /dev/null +++ b/math/math_utilarmv6.cpp @@ -0,0 +1,47 @@ +#include "math/math_util.h" +#include +#include + +/* +static unsigned int randSeed = 22222; // Change this for different random sequences. + +void SetSeed(unsigned int seed) { + randSeed = seed * 382792592; +} + +unsigned int GenerateRandomNumber() { + randSeed = (randSeed * 196314165) + 907633515; + randSeed ^= _rotl(randSeed, 13); + return randSeed; +}*/ + +#if defined(ARM) + +void EnableFZ() +{ + int x; + asm( + "orr %[result],%[result],#16777216 \r\n" + :[result] "=r" (x) : : + ); + +} + +void DisableFZ( ) +{ + __asm__ volatile( + "bic r0, $(1 << 24)\n"); +} +#else + +void EnableFZ() +{ + + +} +void DisableFZ() +{ + +} + +#endif From 7ed5811db38f3547f8eec3d3b577dae38405b1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 5 Dec 2012 10:41:01 +0700 Subject: [PATCH 0187/1445] Restore a few missing pieces of glstate. Cleanup. --- base/PCMain.cpp | 1 - gfx_es2/gl_state.cpp | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 97febbc00e..808c3fcb2f 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -218,7 +218,6 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index f46352bcf4..e3dfcb5ce4 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -14,11 +14,15 @@ void OpenGLState::Restore() { blend.restore(); blendEquation.restore(); blendFunc.restore(); + blendColor.restore(); + + scissorTest.restore(); cullFace.restore(); cullFaceMode.restore(); + frontFace.restore(); depthTest.restore(); depthRange.restore(); depthFunc.restore(); -} \ No newline at end of file +} From 839b393745121bdd98c8672a02db2216f0529ba1 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Sat, 8 Dec 2012 23:26:14 +0100 Subject: [PATCH 0188/1445] Add Read/Write for binary data in file --- file/file_util.cpp | 33 +++++++++++++++++++++++++++++++++ file/file_util.h | 3 +++ 2 files changed, 36 insertions(+) diff --git a/file/file_util.cpp b/file/file_util.cpp index d03900a4a4..4ac156a346 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -37,6 +37,21 @@ bool writeStringToFile(bool text_file, const std::string &str, const char *filen return true; } +bool writeDataToFile(bool text_file, const void* data, const unsigned int size, const char *filename) +{ + FILE *f = fopen(filename, text_file ? "w" : "wb"); + if (!f) + return false; + size_t len = size; + if (len != fwrite(data, 1, len, f)) + { + fclose(f); + return false; + } + fclose(f); + return true; +} + uint64_t GetSize(FILE *f) { // can't use off_t here because it can be 32-bit @@ -67,6 +82,24 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str) return true; } + +bool readDataFromFile(bool text_file, unsigned char* &data, const unsigned int size, const char *filename) +{ + FILE *f = fopen(filename, text_file ? "r" : "rb"); + if (!f) + return false; + size_t len = (size_t)GetSize(f); + if(len < size) + { + fclose(f); + return false; + } + data[fread(data, 1, size, f)] = 0; + fclose(f); + return true; +} + + #define DIR_SEP "/" #define DIR_SEP_CHR '\\' diff --git a/file/file_util.h b/file/file_util.h index 2627bd11f3..5a118b457c 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -7,6 +7,9 @@ bool writeStringToFile(bool text_file, const std::string &str, const char *filename); bool readFileToString(bool text_file, const char *filename, std::string &str); +bool writeDataToFile(bool text_file, const void* data, const unsigned int size, const char *filename); +bool readDataFromFile(bool text_file, unsigned char* &data, const unsigned int size, const char *filename); + // Beginnings of a directory utility system. TODO: Improve. struct FileInfo From 965c93411f0cb4599fcb83bd746a8edf202fba31 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 13 Dec 2012 14:39:44 +1000 Subject: [PATCH 0189/1445] Symbian support for project. Also, check if 24-bit depth is supported and use it (when packed stencil isn't provided). VideoCore III and VideoCore IV used in Symbian, Android and Raspberry Pi require this as they only support 24-bit depth, 8-bit stencil. --- ext/stb_image/stb_image.c | 6 ++++-- ext/stb_vorbis/stb_vorbis.h | 3 +++ file/chunk_file.cpp | 4 ++++ file/fd_util.cpp | 3 +++ file/file_util.cpp | 19 ++++++++++++++++++- gfx/gl_common.h | 4 ++++ gfx_es2/fbo.cpp | 7 +++++-- net/http_client.h | 2 +- 8 files changed, 42 insertions(+), 6 deletions(-) diff --git a/ext/stb_image/stb_image.c b/ext/stb_image/stb_image.c index 70a28c8d6d..924960fb93 100644 --- a/ext/stb_image/stb_image.c +++ b/ext/stb_image/stb_image.c @@ -92,10 +92,12 @@ // implementation: typedef unsigned char uint8; typedef unsigned short uint16; -typedef signed short int16; +typedef signed short int16; typedef unsigned int uint32; -typedef signed int int32; +typedef signed int int32; +#ifndef __SYMBIAN32__ typedef unsigned int uint; +#endif // should produce compiler error if size is wrong typedef unsigned char validate_uint32[sizeof(uint32)==4 ? 1 : -1]; diff --git a/ext/stb_vorbis/stb_vorbis.h b/ext/stb_vorbis/stb_vorbis.h index 16ccc10036..3c39b06405 100644 --- a/ext/stb_vorbis/stb_vorbis.h +++ b/ext/stb_vorbis/stb_vorbis.h @@ -46,6 +46,9 @@ extern "C" { // If you pass in a non-NULL buffer of the type below, allocation // will occur from it as described above. Otherwise just pass NULL // to use malloc()/alloca() +#ifdef __SYMBIAN32__ +#define alloca(size) __builtin_alloca (size) +#endif typedef struct { diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index f3174a4727..738c32ad27 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -2,6 +2,10 @@ #include "file/chunk_file.h" #include "file/zip_read.h" +#ifdef __SYMBIAN32__ +#undef UNICODE +#endif + //#define CHUNKDEBUG ChunkFile::ChunkFile(const char *filename, bool _read) { diff --git a/file/fd_util.cpp b/file/fd_util.cpp index e8aae7f889..e2cb775c67 100644 --- a/file/fd_util.cpp +++ b/file/fd_util.cpp @@ -6,6 +6,9 @@ #ifndef _WIN32 #include #include +#ifdef __SYMBIAN32__ +#include +#endif #else #include #include diff --git a/file/file_util.cpp b/file/file_util.cpp index 4ac156a346..f47e3b45dc 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -5,6 +5,7 @@ #else #include #include +#include #endif #include #include @@ -18,10 +19,26 @@ #include "base/basictypes.h" #include "file/file_util.h" -#if defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__SYMBIAN32__) #define stat64 stat #endif +#if !defined(readdir_r) +static inline int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) { + struct dirent *readdir_entry; + + readdir_entry = readdir(dirp); + if (readdir_entry == NULL) { + *result = NULL; + return errno; + } + + *entry = *readdir_entry; + *result = entry; + return 0; +} +#endif + bool writeStringToFile(bool text_file, const std::string &str, const char *filename) { FILE *f = fopen(filename, text_file ? "w" : "wb"); diff --git a/gfx/gl_common.h b/gfx/gl_common.h index d96fd0533b..ba8fee8dd5 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -19,4 +19,8 @@ typedef char GLchar; #endif #endif +#ifdef __SYMBIAN32__ +typedef char GLchar; +#endif + #endif //_GL_COMMON_H diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 8a0517e0c4..519d891513 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -11,6 +11,9 @@ #ifndef GL_DEPTH_COMPONENT24 #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #endif +#ifndef GL_DEPTH24_STENCIL8_OES +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif #endif // TODO: Breakout this GL extension checker in its own file. @@ -101,10 +104,10 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { ILOG("Creating FBO using separate stencil"); // TEGRA fbo->z_stencil_buffer = 0; - // 16-bit Z, separate 8-bit stencil + // 16/24-bit Z, separate 8-bit stencil glGenRenderbuffers(1, &fbo->z_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, width, height); // 8-bit stencil buffer glGenRenderbuffers(1, &fbo->stencil_buffer); diff --git a/net/http_client.h b/net/http_client.h index a9592cbde9..ac813f3b99 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -7,7 +7,7 @@ #ifdef _WIN32 #include #else -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__SYMBIAN32__) #include #else #include From aa8a1c7de01b846bc6a273105b357cdcb4f8671f Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 13 Dec 2012 16:38:33 +1000 Subject: [PATCH 0190/1445] Symbian support. Add new Qt frontend. Can be used by any platform. Currently used by Symbian. --- base/QtMain.cpp | 58 +++++++++++++++++++++++++++++++++ base/QtMain.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 base/QtMain.cpp create mode 100644 base/QtMain.h diff --git a/base/QtMain.cpp b/base/QtMain.cpp new file mode 100644 index 0000000000..64acc52bd6 --- /dev/null +++ b/base/QtMain.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012 Sacha Refshauge + * + */ +// Qt implementation of the framework. +// Currently supports: Symbian + +#include +#include +#include +#include + +#ifdef __SYMBIAN32__ +#include +#endif +#include "QtMain.h" + +void LaunchBrowser(const char *url) +{ + QDesktopServices::openUrl(QUrl(url)); +} + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + // Lock orientation to landscape on Symbian +#ifdef __SYMBIAN32__ + QT_TRAP_THROWING(dynamic_cast(CEikonEnv::Static()->AppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); +#endif + net::Init(); + QSize res = QApplication::desktop()->screenGeometry().size(); + if (res.width() < res.height()) + res.transpose(); + pixel_xres = res.width(); + pixel_yres = res.height(); + // Calculate DPI from TWIPS on Symbian +#ifdef __SYMBIAN32__ + TSize sizeTwips = CEikonEnv::Static()->ScreenDevice()->SizeInTwips(); + float dpi = sqrt((float)(pixel_xres*pixel_xres + pixel_yres*pixel_yres)) + / (sqrt((float)(sizeTwips.iHeight*sizeTwips.iHeight + sizeTwips.iWidth*sizeTwips.iWidth)) / KTwipsPerInch); + float dpi_scale = dpi / 170.0f; +#endif + dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); + NativeInit(argc, (const char **)argv, +#ifdef __SYMBIAN32__ + "E:/PPSSPP/", "E:", "BADCOFFEE"); +#else + "./","/tmp","BADCOFFEE"); +#endif + MainUI w; + w.resize(pixel_xres, pixel_yres); + w.showFullScreen(); + int ret = a.exec(); + NativeShutdown(); + net::Shutdown(); + return ret; +} + diff --git a/base/QtMain.h b/base/QtMain.h new file mode 100644 index 0000000000..96365208ff --- /dev/null +++ b/base/QtMain.h @@ -0,0 +1,87 @@ +#ifndef SYMBIANMAIN_H +#define SYMBIANMAIN_H + +#include +#include + +#include +#include + +#include "base/display.h" +#include "base/logging.h" +#include "base/timeutil.h" +#include "gfx_es2/glsl_program.h" +#include "file/zip_read.h" +#include "input/input_state.h" +#include "base/NativeApp.h" +#include "net/resolve.h" +#include "display.h" + +class MainUI : public QGLWidget +{ + Q_OBJECT +public: + explicit MainUI(float scale, QWidget *parent = 0): + QGLWidget(parent), dpi_scale(scale) + { + setAttribute(Qt::WA_AcceptTouchEvents); + } + ~MainUI() { + NativeShutdownGraphics(); + } + +protected: + bool event(QEvent *e) + { + QList touchPoints; + switch(e->type()) + { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + touchPoints = static_cast(e)->touchPoints(); + foreach (const QTouchEvent::TouchPoint &touchPoint, touchPoints) { + switch (touchPoint.state()) { + case Qt::TouchPointStationary: + break; + case Qt::TouchPointPressed: + case Qt::TouchPointReleased: + input_state.pointer_down[touchPoint.id()] = (touchPoint.state() == Qt::TouchPointPressed); + case Qt::TouchPointMoved: + input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * dpi_scale; + input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * dpi_scale; + break; + default: + break; + } + } + break; + default: + return QWidget::event(e); + } + e->accept(); + return true; + } + + void initializeGL() + { + NativeInitGraphics(); + } + + void paintGL() + { + UpdateInputState(&input_state); + NativeUpdate(input_state); + EndInputState(&input_state); + NativeRender(); + + update(); + } + +private: + InputState input_state; + float dpi_scale; +}; + +#endif + From 57d6d42d667b4679ed7e88b830c61eb661a9e337 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 13 Dec 2012 16:43:08 +1000 Subject: [PATCH 0191/1445] Build fix --- file/file_util.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index f47e3b45dc..db169e3245 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -23,7 +23,8 @@ #define stat64 stat #endif -#if !defined(readdir_r) +// Hack +#ifdef __SYMBIAN32__ static inline int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) { struct dirent *readdir_entry; From 5cec70972fcfa1ed3b7358c9e8cbd5a0a33f7f81 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 13 Dec 2012 17:05:12 +1000 Subject: [PATCH 0192/1445] Clean up QtMain --- base/QtMain.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 64acc52bd6..96f47af2d0 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -20,6 +20,17 @@ void LaunchBrowser(const char *url) QDesktopServices::openUrl(QUrl(url)); } +float CalculateDPIScale() +{ + // Calculate DPI from TWIPS on Symbian +#ifdef __SYMBIAN32__ + TSize sizeTwips = CEikonEnv::Static()->ScreenDevice()->SizeInTwips(); + float dpi = sqrt((float)(pixel_xres*pixel_xres + pixel_yres*pixel_yres)) + / (sqrt((float)(sizeTwips.iHeight*sizeTwips.iHeight + sizeTwips.iWidth*sizeTwips.iWidth)) / KTwipsPerInch); + return dpi / 170.0f; +#endif +} + int main(int argc, char *argv[]) { QApplication a(argc, argv); @@ -27,27 +38,21 @@ int main(int argc, char *argv[]) #ifdef __SYMBIAN32__ QT_TRAP_THROWING(dynamic_cast(CEikonEnv::Static()->AppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); #endif - net::Init(); QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); - // Calculate DPI from TWIPS on Symbian -#ifdef __SYMBIAN32__ - TSize sizeTwips = CEikonEnv::Static()->ScreenDevice()->SizeInTwips(); - float dpi = sqrt((float)(pixel_xres*pixel_xres + pixel_yres*pixel_yres)) - / (sqrt((float)(sizeTwips.iHeight*sizeTwips.iHeight + sizeTwips.iWidth*sizeTwips.iWidth)) / KTwipsPerInch); - float dpi_scale = dpi / 170.0f; -#endif + float dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); + net::Init(); NativeInit(argc, (const char **)argv, #ifdef __SYMBIAN32__ "E:/PPSSPP/", "E:", "BADCOFFEE"); #else "./","/tmp","BADCOFFEE"); #endif - MainUI w; + MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); w.showFullScreen(); int ret = a.exec(); From 09ad65d3dd7a3c64523be57582e7c2dfad54511e Mon Sep 17 00:00:00 2001 From: Xele02 Date: Fri, 14 Dec 2012 23:35:09 +0100 Subject: [PATCH 0193/1445] Add decoding png function for Save Dialog --- Android.mk | 2 ++ image/png_load.cpp | 25 +++++++++++++++++++++++++ image/png_load.h | 3 +++ 3 files changed, 30 insertions(+) diff --git a/Android.mk b/Android.mk index 56edd11034..a8588cbc6e 100644 --- a/Android.mk +++ b/Android.mk @@ -17,6 +17,7 @@ LOCAL_SRC_FILES :=\ base/error_context.cpp \ base/stringutil.cpp \ ext/sha1/sha1.cpp \ + ext/stb_image/stb_image.c \ ext/stb_vorbis/stb_vorbis.c.arm \ ext/vjson/json.cpp \ ext/vjson/block_allocator.cpp \ @@ -48,6 +49,7 @@ LOCAL_SRC_FILES :=\ gfx/texture_atlas.cpp \ gfx/texture_gen.cpp \ image/zim_load.cpp \ + image/png_load.cpp \ ui/ui.cpp \ ui/ui_context.cpp \ ui/screen.cpp \ diff --git a/image/png_load.cpp b/image/png_load.cpp index 803b2e9a0c..3d264879bc 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -36,6 +36,31 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d return 1; } +int pngLoadPtr(const unsigned char *input_ptr, const int input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr, + bool flip) { + if (flip) + { + ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); + } + + int x,y,n; + unsigned char *data = stbi_load_from_memory(input_ptr,input_len, &x, &y, &n, 4); // 4 = force RGBA + if (!data) + return 0; + + *pwidth = x; + *pheight = y; + // ... process data if not NULL ... + // ... x = width, y = height, n = # 8-bit components per pixel ... + // ... replace '0' with '1'..'4' to force that many components per pixel + // ... but 'n' will always be the number that it would have been if you said 0 + + // TODO: Get rid of this silly copy which is only to make the buffer free-able with free() + *image_data_ptr = (unsigned char *)malloc(x * y * 4); + memcpy(*image_data_ptr, data, x * y * 4); + stbi_image_free(data); + return 1; +} #else diff --git a/image/png_load.h b/image/png_load.h index 5a4ee08c54..1b1babc1af 100644 --- a/image/png_load.h +++ b/image/png_load.h @@ -6,6 +6,9 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip); +int pngLoadPtr(const unsigned char *input_ptr, const int input_len, int *pwidth, + int *pheight, unsigned char **image_data_ptr, bool flip); + #endif // _PNG_LOAD_H From 885f06eecf4ae6ccddcc9b93fb5df7157d0c21b4 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 16 Dec 2012 19:47:51 +1000 Subject: [PATCH 0194/1445] Add audio to Qt frontend --- base/BlackberryMain.cpp | 2 +- base/QtMain.cpp | 6 +++++ base/QtMain.h | 51 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 7780129745..98026d9b9c 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -325,7 +325,7 @@ private: fd_set rfds, wfds; int nflds; - if (!paused && (FD_ISSET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds))) + if (FD_ISSET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds)) { snd_pcm_plugin_write(pcm_handle, mixbuf, mixlen); } diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 96f47af2d0..d6dc9bd82e 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -28,6 +28,8 @@ float CalculateDPIScale() float dpi = sqrt((float)(pixel_xres*pixel_xres + pixel_yres*pixel_yres)) / (sqrt((float)(sizeTwips.iHeight*sizeTwips.iHeight + sizeTwips.iWidth*sizeTwips.iWidth)) / KTwipsPerInch); return dpi / 170.0f; +#else + return 1.2f; #endif } @@ -55,7 +57,11 @@ int main(int argc, char *argv[]) MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); w.showFullScreen(); + + MainAudio *audio = new MainAudio(); + int ret = a.exec(); + delete audio; NativeShutdown(); net::Shutdown(); return ret; diff --git a/base/QtMain.h b/base/QtMain.h index 96365208ff..a253660de7 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -1,11 +1,11 @@ -#ifndef SYMBIANMAIN_H -#define SYMBIANMAIN_H +#ifndef QTMAIN_H +#define QTMAIN_H #include #include -#include -#include +#include +#include #include "base/display.h" #include "base/logging.h" @@ -83,5 +83,48 @@ private: float dpi_scale; }; +#define AUDIO_FREQ 44100 +#define AUDIO_CHANNELS 2 +#define AUDIO_SAMPLES 1024 +#define AUDIO_SAMPLESIZE 16 +class MainAudio: public QObject +{ + Q_OBJECT +public: + MainAudio() { + QAudioFormat fmt; + fmt.setFrequency(AUDIO_FREQ); + fmt.setCodec("audio/pcm"); + fmt.setChannelCount(AUDIO_CHANNELS); + fmt.setSampleSize(AUDIO_SAMPLESIZE); + fmt.setByteOrder(QAudioFormat::LittleEndian); + fmt.setSampleType(QAudioFormat::SignedInt); + mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; + mixbuf = (char*)malloc(mixlen); + output = new QAudioOutput(fmt); + output->setNotifyInterval(1000*AUDIO_SAMPLES / AUDIO_FREQ); + output->setBufferSize(mixlen); + this->connect(output, SIGNAL(notify()), this, SLOT(writeData())); + feed = output->start(); + } + ~MainAudio() { + delete feed; + delete output; + free(mixbuf); + } + +private slots: + void writeData() { + memset(mixbuf, 0, mixlen); + NativeMix((short *)mixbuf, mixlen / 4); + feed->write(mixbuf, mixlen); + } +private: + QIODevice* feed; + QAudioOutput* output; + int mixlen; + char* mixbuf; +}; + #endif From 1a3fa623619354c30c972f3fe4cb4b52861a9619 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 23 Dec 2012 17:47:52 +1000 Subject: [PATCH 0195/1445] Support for Linux/Windows in Qt frontend --- base/QtMain.cpp | 9 +++++---- base/QtMain.h | 13 ++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index d6dc9bd82e..914e425e2d 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -3,7 +3,7 @@ * */ // Qt implementation of the framework. -// Currently supports: Symbian +// Currently supports: Symbian, Blackberry, Linux #include #include @@ -48,11 +48,12 @@ int main(int argc, char *argv[]) float dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); net::Init(); - NativeInit(argc, (const char **)argv, #ifdef __SYMBIAN32__ - "E:/PPSSPP/", "E:", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, "E:/PPSSPP/", "E:", "BADCOFFEE"); +#elif defined(BLACKBERRY) + NativeInit(argc, (const char **)argv, "data/", "/tmp", "BADCOFFEE"); #else - "./","/tmp","BADCOFFEE"); + NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #endif MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); diff --git a/base/QtMain.h b/base/QtMain.h index a253660de7..325256c127 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -2,6 +2,8 @@ #define QTMAIN_H #include +#include +#include "gfx_es2/glsl_program.h" #include #include @@ -10,7 +12,6 @@ #include "base/display.h" #include "base/logging.h" #include "base/timeutil.h" -#include "gfx_es2/glsl_program.h" #include "file/zip_read.h" #include "input/input_state.h" #include "base/NativeApp.h" @@ -56,6 +57,13 @@ protected: } } break; + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + input_state.pointer_down[0] = (e->type() == QEvent::MouseButtonPress); + case QEvent::MouseMove: + input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * dpi_scale; + input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * dpi_scale; + break; default: return QWidget::event(e); } @@ -65,6 +73,9 @@ protected: void initializeGL() { +#ifndef USING_GLES2 + glewInit(); +#endif NativeInitGraphics(); } From 15563281297adb62c8e690fc063a9bf4442fcfc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 26 Dec 2012 08:25:38 +0100 Subject: [PATCH 0196/1445] Make TouchButton not always override other input. Modify mappings. --- base/PCMain.cpp | 12 ++++++------ ui/virtual_input.cpp | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 808c3fcb2f..35a25d1e0b 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -91,14 +91,14 @@ void LaunchEmail(const char *email_address) const int buttonMappings[14] = { - SDLK_x, //A - SDLK_s, //B - SDLK_z, //X - SDLK_a, //Y + SDLK_z, //A + SDLK_x, //B + SDLK_a, //X + SDLK_s, //Y SDLK_w, //LBUMPER SDLK_q, //RBUMPER - SDLK_1, //START - SDLK_2, //SELECT + SDLK_SPACE, //START + SDLK_v, //SELECT SDLK_UP, //UP SDLK_DOWN, //DOWN SDLK_LEFT, //LEFT diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index f47386400c..7e6d756789 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -16,6 +16,7 @@ TouchButton::TouchButton(const Atlas *atlas, int imageIndex, int overlayImageInd void TouchButton::update(InputState &input_state) { + bool oldIsDown = isDown_; isDown_ = false; for (int i = 0; i < MAX_POINTERS; i++) { if (input_state.pointer_down[i] && isInside(input_state.pointer_x[i], input_state.pointer_y[i])) @@ -24,7 +25,7 @@ void TouchButton::update(InputState &input_state) if (isDown_) { input_state.pad_buttons |= button_; - } else { + } else if (oldIsDown && !isDown_) { input_state.pad_buttons &= ~button_; } } From 74057385bfc3baae81b3e35266596d031a196067 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 2 Jan 2013 20:56:09 +0100 Subject: [PATCH 0197/1445] Initial UTF-8 support --- Android.mk | 3 +- gfx_es2/draw_buffer.cpp | 13 +- native.vcxproj | 2 + native.vcxproj.filters | 8 +- ui/ui.cpp | 11 ++ ui/ui.h | 1 + util/text/utf8.cpp | 405 ++++++++++++++++++++++++++++++++++++++++ util/text/utf8.h | 38 ++++ 8 files changed, 478 insertions(+), 3 deletions(-) create mode 100644 util/text/utf8.cpp create mode 100644 util/text/utf8.h diff --git a/Android.mk b/Android.mk index a8588cbc6e..ca569fa5e7 100644 --- a/Android.mk +++ b/Android.mk @@ -54,7 +54,8 @@ LOCAL_SRC_FILES :=\ ui/ui_context.cpp \ ui/screen.cpp \ ui/virtual_input.cpp \ - util/random/perlin.cpp + util/random/perlin.cpp \ + util/text/utf8.cpp LOCAL_CFLAGS := -O2 -DGL_GLEXT_PROTOTYPES -DARM -DUSING_GLES2 -fsigned-char -fno-strict-aliasing LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 59db3ec0f2..cbe8309ec8 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -10,6 +10,7 @@ #include "gfx/texture_atlas.h" #include "gfx/gl_debug_log.h" #include "gfx/gl_common.h" +#include "util/text/utf8.h" enum { // Enough? @@ -295,6 +296,12 @@ void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) { } } +// TODO: Unicode support. +// U+4E00–U+9FBF Kanji +// U+3040–U+309F Hiragana +// U+30A0–U+30FF Katakana + + // ROTATE_* doesn't yet work right. void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int flags) { const AtlasFont &atlasfont = *atlas->fonts[font]; @@ -312,7 +319,11 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co else y += atlasfont.ascend*fontscaley; float sx = x; - while ((cval = *text++) != '\0') { + UTF8 utf(text); + while (true) { + if (utf.end()) + break; + cval = utf.next(); if (cval == '\n') { y += atlasfont.height * fontscaley; x = sx; diff --git a/native.vcxproj b/native.vcxproj index de6389110c..df06267bb1 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -248,6 +248,7 @@ + @@ -338,6 +339,7 @@ AssemblyAndSourceCode AssemblyAndSourceCode + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index ad1206c6d1..d047cd88a6 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -233,6 +233,9 @@ gfx + + util + @@ -414,6 +417,9 @@ gfx + + util + @@ -474,4 +480,4 @@ {4515306f-4664-46bf-a89b-abfec5520a15} - + \ No newline at end of file diff --git a/ui/ui.cpp b/ui/ui.cpp index da57aa777b..4c209d88be 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -108,6 +108,17 @@ void UIText(int font, int x, int y, const char *text, uint32_t color, float scal ui_draw2d.SetFontScale(1.0f, 1.0f); } +void UIText(int font, const LayoutManager &layout, const char *text, uint32_t color, float scale, int align) +{ + ui_draw2d.SetFontScale(scale, scale); + float w, h; + ui_draw2d.MeasureText(font, text, &w, &h); + float x, y; + layout.GetPos(&w, &h, &x, &y); + UIText(font, x, y, text, color, scale, 0); + ui_draw2d.SetFontScale(1.0f, 1.0f); +} + int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align) { float h = themeAtlas->images[theme.buttonImage].h; diff --git a/ui/ui.h b/ui/ui.h index 6fdfdb334b..aad8fa0675 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -203,6 +203,7 @@ int UIHSlider(int id, int x, int y, int w, int max, int *value); // Draws static text, that does not participate in any focusing scheme etc, it just is. void UIText(int font, int x, int y, const char *text, uint32_t color, float scale = 1.0f, int align = ALIGN_TOPLEFT); void UIText(int x, int y, const char *text, uint32_t color, float scale = 1.0f, int align = ALIGN_TOPLEFT); +void UIText(int font, const LayoutManager &layout, const char *text, uint32_t color, float scale = 1.0f, int align = ALIGN_TOPLEFT); // Slide choice, like the Angry Birds level selector. Not yet working. void UISlideChoice(int id, int y, const SlideItem *items, int numItems, UISlideState *state); diff --git a/util/text/utf8.cpp b/util/text/utf8.cpp new file mode 100644 index 0000000000..10b239ea52 --- /dev/null +++ b/util/text/utf8.cpp @@ -0,0 +1,405 @@ +/* + Basic UTF-8 manipulation routines + by Jeff Bezanson + placed in the public domain Fall 2005 + + This code is designed to provide the utilities you need to manipulate + UTF-8 as an internal string encoding. These functions do not perform the + error checking normally needed when handling UTF-8 data, so if you happen + to be from the Unicode Consortium you will want to flay me alive. + I do this because error checking can be performed at the boundaries (I/O), + with these routines reserved for higher performance on data known to be + valid. +*/ +#include +#include +#include +#include + +#include "base/basictypes.h" +#include "utf8.h" + +// is start of UTF sequence +inline bool isutf(char c) { + return (c & 0xC0) != 0x80; +} + +static const uint32_t offsetsFromUTF8[6] = { + 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL +}; + +static const uint8_t trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5, +}; + +/* returns length of next utf-8 sequence */ +int u8_seqlen(const char *s) +{ + return trailingBytesForUTF8[(unsigned int)(unsigned char)s[0]] + 1; +} + +/* conversions without error checking + only works for valid UTF-8, i.e. no 5- or 6-byte sequences + srcsz = source size in bytes, or -1 if 0-terminated + sz = dest size in # of wide characters + + returns # characters converted + dest will always be L'\0'-terminated, even if there isn't enough room + for all the characters. + if sz = srcsz+1 (i.e. 4*srcsz+4 bytes), there will always be enough space. +*/ +int u8_toucs(uint32_t *dest, int sz, const char *src, int srcsz) +{ + uint32_t ch; + const char *src_end = src + srcsz; + int nb; + int i=0; + + while (i < sz-1) { + nb = trailingBytesForUTF8[(unsigned char)*src]; + if (srcsz == -1) { + if (*src == 0) + goto done_toucs; + } + else { + if (src + nb >= src_end) + goto done_toucs; + } + ch = 0; + switch (nb) { + /* these fall through deliberately */ + case 3: ch += (unsigned char)*src++; ch <<= 6; + case 2: ch += (unsigned char)*src++; ch <<= 6; + case 1: ch += (unsigned char)*src++; ch <<= 6; + case 0: ch += (unsigned char)*src++; + } + ch -= offsetsFromUTF8[nb]; + dest[i++] = ch; + } + done_toucs: + dest[i] = 0; + return i; +} + +/* srcsz = number of source characters, or -1 if 0-terminated + sz = size of dest buffer in bytes + + returns # characters converted + dest will only be '\0'-terminated if there is enough space. this is + for consistency; imagine there are 2 bytes of space left, but the next + character requires 3 bytes. in this case we could NUL-terminate, but in + general we can't when there's insufficient space. therefore this function + only NUL-terminates if all the characters fit, and there's space for + the NUL as well. + the destination string will never be bigger than the source string. +*/ +int u8_toutf8(char *dest, int sz, uint32_t *src, int srcsz) +{ + uint32_t ch; + int i = 0; + char *dest_end = dest + sz; + + while (srcsz<0 ? src[i]!=0 : i < srcsz) { + ch = src[i]; + if (ch < 0x80) { + if (dest >= dest_end) + return i; + *dest++ = (char)ch; + } + else if (ch < 0x800) { + if (dest >= dest_end-1) + return i; + *dest++ = (ch>>6) | 0xC0; + *dest++ = (ch & 0x3F) | 0x80; + } + else if (ch < 0x10000) { + if (dest >= dest_end-2) + return i; + *dest++ = (ch>>12) | 0xE0; + *dest++ = ((ch>>6) & 0x3F) | 0x80; + *dest++ = (ch & 0x3F) | 0x80; + } + else if (ch < 0x110000) { + if (dest >= dest_end-3) + return i; + *dest++ = (ch>>18) | 0xF0; + *dest++ = ((ch>>12) & 0x3F) | 0x80; + *dest++ = ((ch>>6) & 0x3F) | 0x80; + *dest++ = (ch & 0x3F) | 0x80; + } + i++; + } + if (dest < dest_end) + *dest = '\0'; + return i; +} + +int u8_wc_toutf8(char *dest, uint32_t ch) +{ + if (ch < 0x80) { + dest[0] = (char)ch; + return 1; + } + if (ch < 0x800) { + dest[0] = (ch>>6) | 0xC0; + dest[1] = (ch & 0x3F) | 0x80; + return 2; + } + if (ch < 0x10000) { + dest[0] = (ch>>12) | 0xE0; + dest[1] = ((ch>>6) & 0x3F) | 0x80; + dest[2] = (ch & 0x3F) | 0x80; + return 3; + } + if (ch < 0x110000) { + dest[0] = (ch>>18) | 0xF0; + dest[1] = ((ch>>12) & 0x3F) | 0x80; + dest[2] = ((ch>>6) & 0x3F) | 0x80; + dest[3] = (ch & 0x3F) | 0x80; + return 4; + } + return 0; +} + +/* charnum => byte offset */ +int u8_offset(const char *str, int charnum) +{ + int offs=0; + + while (charnum > 0 && str[offs]) { + (void)(isutf(str[++offs]) || isutf(str[++offs]) || + isutf(str[++offs]) || ++offs); + charnum--; + } + return offs; +} + +/* byte offset => charnum */ +int u8_charnum(const char *s, int offset) +{ + int charnum = 0, offs=0; + + while (offs < offset && s[offs]) { + (void)(isutf(s[++offs]) || isutf(s[++offs]) || + isutf(s[++offs]) || ++offs); + charnum++; + } + return charnum; +} + +/* number of characters */ +int u8_strlen(const char *s) +{ + int count = 0; + int i = 0; + + while (u8_nextchar(s, &i) != 0) + count++; + + return count; +} + +/* reads the next utf-8 sequence out of a string, updating an index */ +uint32_t u8_nextchar(const char *s, int *i) +{ + uint32_t ch = 0; + int sz = 0; + + do { + ch <<= 6; + ch += (unsigned char)s[(*i)++]; + sz++; + } while (s[*i] && !isutf(s[*i])); + ch -= offsetsFromUTF8[sz-1]; + + return ch; +} + +void u8_inc(const char *s, int *i) +{ + (void)(isutf(s[++(*i)]) || isutf(s[++(*i)]) || + isutf(s[++(*i)]) || ++(*i)); +} + +void u8_dec(const char *s, int *i) +{ + (void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) || + isutf(s[--(*i)]) || --(*i)); +} + +int octal_digit(char c) +{ + return (c >= '0' && c <= '7'); +} + +int hex_digit(char c) +{ + return ((c >= '0' && c <= '9') || + (c >= 'A' && c <= 'F') || + (c >= 'a' && c <= 'f')); +} + +/* assumes that src points to the character after a backslash + returns number of input characters processed */ +int u8_read_escape_sequence(const char *str, uint32_t *dest) +{ + uint32_t ch; + char digs[9]="\0\0\0\0\0\0\0\0"; + int dno=0, i=1; + + ch = (uint32_t)str[0]; /* take literal character */ + if (str[0] == 'n') + ch = L'\n'; + else if (str[0] == 't') + ch = L'\t'; + else if (str[0] == 'r') + ch = L'\r'; + else if (str[0] == 'b') + ch = L'\b'; + else if (str[0] == 'f') + ch = L'\f'; + else if (str[0] == 'v') + ch = L'\v'; + else if (str[0] == 'a') + ch = L'\a'; + else if (octal_digit(str[0])) { + i = 0; + do { + digs[dno++] = str[i++]; + } while (octal_digit(str[i]) && dno < 3); + ch = strtol(digs, NULL, 8); + } + else if (str[0] == 'x') { + while (hex_digit(str[i]) && dno < 2) { + digs[dno++] = str[i++]; + } + if (dno > 0) + ch = strtol(digs, NULL, 16); + } + else if (str[0] == 'u') { + while (hex_digit(str[i]) && dno < 4) { + digs[dno++] = str[i++]; + } + if (dno > 0) + ch = strtol(digs, NULL, 16); + } + else if (str[0] == 'U') { + while (hex_digit(str[i]) && dno < 8) { + digs[dno++] = str[i++]; + } + if (dno > 0) + ch = strtol(digs, NULL, 16); + } + *dest = ch; + + return i; +} + +/* convert a string with literal \uxxxx or \Uxxxxxxxx characters to UTF-8 + example: u8_unescape(mybuf, 256, "hello\\u220e") + note the double backslash is needed if called on a C string literal */ +int u8_unescape(char *buf, int sz, char *src) +{ + int c=0, amt; + uint32_t ch; + char temp[4]; + + while (*src && c < sz) { + if (*src == '\\') { + src++; + amt = u8_read_escape_sequence(src, &ch); + } + else { + ch = (uint32_t)*src; + amt = 1; + } + src += amt; + amt = u8_wc_toutf8(temp, ch); + if (amt > sz-c) + break; + memcpy(&buf[c], temp, amt); + c += amt; + } + if (c < sz) + buf[c] = '\0'; + return c; +} + +const char *u8_strchr(const char *s, uint32_t ch, int *charn) +{ + int i = 0, lasti=0; + uint32_t c; + + *charn = 0; + while (s[i]) { + c = u8_nextchar(s, &i); + if (c == ch) { + return &s[lasti]; + } + lasti = i; + (*charn)++; + } + return NULL; +} + +const char *u8_memchr(const char *s, uint32_t ch, size_t sz, int *charn) +{ + int i = 0, lasti=0; + uint32_t c; + int csz; + + *charn = 0; + while (i < sz) { + c = csz = 0; + do { + c <<= 6; + c += (unsigned char)s[i++]; + csz++; + } while (i < sz && !isutf(s[i])); + c -= offsetsFromUTF8[csz-1]; + + if (c == ch) { + return &s[lasti]; + } + lasti = i; + (*charn)++; + } + return NULL; +} + +int u8_is_locale_utf8(const char *locale) +{ + /* this code based on libutf8 */ + const char* cp = locale; + + for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++) { + if (*cp == '.') { + const char* encoding = ++cp; + for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++) + ; + if ((cp-encoding == 5 && !strncmp(encoding, "UTF-8", 5)) + || (cp-encoding == 4 && !strncmp(encoding, "utf8", 4))) + return 1; /* it's UTF-8 */ + break; + } + } + return 0; +} + +bool UTF8StringHasNonASCII(const char *utf8string) { + UTF8 utf(utf8string); + while (!utf.end()) { + int c = utf.next(); + if (c > 127) + return true; + } + return false; +} \ No newline at end of file diff --git a/util/text/utf8.h b/util/text/utf8.h new file mode 100644 index 0000000000..84c2ae8c97 --- /dev/null +++ b/util/text/utf8.h @@ -0,0 +1,38 @@ +/* + Basic UTF-8 manipulation routines + by Jeff Bezanson + placed in the public domain Fall 2005 + + This code is designed to provide the utilities you need to manipulate + UTF-8 as an internal string encoding. These functions do not perform the + error checking normally needed when handling UTF-8 data, so if you happen + to be from the Unicode Consortium you will want to flay me alive. + I do this because error checking can be performed at the boundaries (I/O), + with these routines reserved for higher performance on data known to be + valid. +*/ + +// Further modified, and C++ stuff added, by hrydgard@gmail.com. + +#include "base/basictypes.h" + +uint32_t u8_nextchar(const char *s, int *i); +int u8_strlen(const char *s); + +class UTF8 { +public: + UTF8(const char *c) : c_(c), index_(0) {} + bool end() const { return c_[index_] == 0; } + uint32_t next() { + return u8_nextchar(c_, &index_); + } + int length() const { + return u8_strlen(c_); + } + +private: + const char *c_; + int index_; +}; + +bool UTF8StringHasNonASCII(const char *utf8string); \ No newline at end of file From 618680d3792980df42b29ab7bedec4a5f2a802b5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 3 Jan 2013 12:01:51 +0100 Subject: [PATCH 0198/1445] make stbi_png_partial static --- ext/stb_image/stb_image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/stb_image/stb_image.c b/ext/stb_image/stb_image.c index 924960fb93..062e32fa8e 100644 --- a/ext/stb_image/stb_image.c +++ b/ext/stb_image/stb_image.c @@ -1992,7 +1992,7 @@ static void init_defaults(void) for (i=0; i <= 31; ++i) default_distance[i] = 5; } -int stbi_png_partial; // a quick hack to only allow decoding some of a PNG... I should implement real streaming support instead +static int stbi_png_partial; // a quick hack to only allow decoding some of a PNG... I should implement real streaming support instead static int parse_zlib(zbuf *a, int parse_header) { int final, type; From dbda5f8037e3da7fda5e5ec4cb59a8047c319e38 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 4 Jan 2013 00:24:21 +0100 Subject: [PATCH 0199/1445] Fix Down on Xperia Play --- android/app-android.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 19a8bf84e6..627359fce1 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -326,7 +326,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jcl case KEYCODE_DPAD_LEFT: AsyncDown(PAD_BUTTON_LEFT); break; case KEYCODE_DPAD_UP: AsyncDown(PAD_BUTTON_UP); break; case KEYCODE_DPAD_RIGHT: AsyncDown(PAD_BUTTON_RIGHT); break; - case KEYCODE_DPAD_DOWN: AsyncDown(PAD_BUTTON_LEFT); break; + case KEYCODE_DPAD_DOWN: AsyncDown(PAD_BUTTON_DOWN); break; case KEYCODE_BUTTON_L1: AsyncDown(PAD_BUTTON_LBUMPER); break; case KEYCODE_BUTTON_R1: AsyncDown(PAD_BUTTON_RBUMPER); break; case KEYCODE_BUTTON_START: AsyncDown(PAD_BUTTON_START); break; @@ -348,7 +348,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclas case KEYCODE_DPAD_LEFT: AsyncUp(PAD_BUTTON_LEFT); break; case KEYCODE_DPAD_UP: AsyncUp(PAD_BUTTON_UP); break; case KEYCODE_DPAD_RIGHT: AsyncUp(PAD_BUTTON_RIGHT); break; - case KEYCODE_DPAD_DOWN: AsyncUp(PAD_BUTTON_LEFT); break; + case KEYCODE_DPAD_DOWN: AsyncUp(PAD_BUTTON_DOWN); break; case KEYCODE_BUTTON_L1: AsyncUp(PAD_BUTTON_LBUMPER); break; case KEYCODE_BUTTON_R1: AsyncUp(PAD_BUTTON_RBUMPER); break; case KEYCODE_BUTTON_START: AsyncUp(PAD_BUTTON_START); break; From 8f7fa5e4e2738a1da83b2f52540b359c801ea3c0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 Jan 2013 23:22:30 +0100 Subject: [PATCH 0200/1445] Add glViewport to tracked state. --- gfx_es2/gl_state.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 034e334ed2..987ec59384 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -145,6 +145,8 @@ public: STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask; + STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport; + #if defined(USING_GLES2) STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; #else From bbc6f2f8697a3aff9e668483229ef76e883024e7 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 7 Jan 2013 23:20:16 +1000 Subject: [PATCH 0201/1445] Compatibility with harmattan --- gfx/gl_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index ba8fee8dd5..25f93c42d5 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -19,7 +19,7 @@ typedef char GLchar; #endif #endif -#ifdef __SYMBIAN32__ +#if defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) typedef char GLchar; #endif From 472cf6af1ae2467b79d6780bb7cc4305a27ba7d0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 10 Jan 2013 18:06:11 +1000 Subject: [PATCH 0202/1445] Fix keyboard input on Blackberry and enable on Qt frontend. Make Qt open a window instead of fullscreen for non-mobile systems. Make the window resizable (updates pixel_*res and dp_*res). --- base/BlackberryMain.cpp | 9 ++++++-- base/QtMain.cpp | 32 ++++++++++++++++++++++++++-- base/QtMain.h | 46 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 98026d9b9c..86467e498e 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -116,7 +116,6 @@ const int buttonMappings[18] = { }; void SimulateGamepad(InputState *input) { - input->pad_buttons = 0; input->pad_lstick_x = 0; input->pad_lstick_y = 0; input->pad_rstick_x = 0; @@ -370,7 +369,7 @@ int main(int argc, char *argv[]) { int screen_resolution[2]; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution); double diagonal_pixels = sqrt(screen_resolution[0] * screen_resolution[0] + screen_resolution[1] * screen_resolution[1]); - double diagonal_inches = 0.0393700787 * sqrt(screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1]); + double diagonal_inches = 0.0393700787 * sqrt(screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1]); int dpi = (int)(diagonal_pixels / diagonal_inches + 0.5); #endif float dpi_scale = 213.6f / dpi; @@ -444,6 +443,12 @@ int main(int argc, char *argv[]) { input_state.pad_buttons |= (1<pad_lstick_x = 0; + input->pad_lstick_y = 0; + input->pad_rstick_x = 0; + input->pad_rstick_y = 0; + + if (input->pad_buttons | (1<<14)) + input->pad_lstick_y=1; + else if (input->pad_buttons | (1<<15)) + input->pad_lstick_y=-1; + if (input->pad_buttons | (1<<16)) + input->pad_lstick_x=-1; + else if (input->pad_buttons | (1<<17)) + input->pad_lstick_x=1; +} + float CalculateDPIScale() { // Calculate DPI from TWIPS on Symbian #ifdef __SYMBIAN32__ - TSize sizeTwips = CEikonEnv::Static()->ScreenDevice()->SizeInTwips(); + TSize sTwips = CEikonEnv::Static()->ScreenDevice()->SizeInTwips(); float dpi = sqrt((float)(pixel_xres*pixel_xres + pixel_yres*pixel_yres)) - / (sqrt((float)(sizeTwips.iHeight*sizeTwips.iHeight + sizeTwips.iWidth*sizeTwips.iWidth)) / KTwipsPerInch); + / (sqrt((float)(sTwips.iHeight*sTwips.iHeight + sTwips.iWidth*sTwips.iWidth)) / KTwipsPerInch); return dpi / 170.0f; #else + // Sane default for Blackberry and Meego return 1.2f; #endif } @@ -41,10 +58,16 @@ int main(int argc, char *argv[]) QT_TRAP_THROWING(dynamic_cast(CEikonEnv::Static()->AppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); #endif QSize res = QApplication::desktop()->screenGeometry().size(); +#ifdef USING_GLES2 if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); +#else + // Set resolution to half of the monitor on desktop systems + pixel_xres = res.width() / 2; + pixel_yres = res.height() / 2; +#endif float dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); net::Init(); @@ -55,9 +78,14 @@ int main(int argc, char *argv[]) #else NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #endif + MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); +#ifdef USING_GLES2 w.showFullScreen(); +#else + w.show(); +#endif MainAudio *audio = new MainAudio(); diff --git a/base/QtMain.h b/base/QtMain.h index 325256c127..4c47054504 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -18,6 +18,30 @@ #include "net/resolve.h" #include "display.h" +// Input +const int buttonMappings[18] = { + Qt::Key_X, //A + Qt::Key_S, //B + Qt::Key_Z, //X + Qt::Key_A, //Y + Qt::Key_W, //LBUMPER + Qt::Key_Q, //RBUMPER + Qt::Key_1, //START + Qt::Key_2, //SELECT + Qt::Key_Up, //UP + Qt::Key_Down, //DOWN + Qt::Key_Left, //LEFT + Qt::Key_Right, //RIGHT + 0, //MENU (event) + Qt::Key_Backspace, //BACK + Qt::Key_I, //JOY UP + Qt::Key_K, //JOY DOWN + Qt::Key_J, //JOY LEFT + Qt::Key_L, //JOY RIGHT +}; +void SimulateGamepad(InputState *input); + +//GUI class MainUI : public QGLWidget { Q_OBJECT @@ -32,6 +56,14 @@ public: } protected: + void resizeEvent(QResizeEvent * e) + { + pixel_xres = e->size().width(); + pixel_yres = e->size().height(); + dp_xres = pixel_xres * dpi_scale; + dp_yres = pixel_yres * dpi_scale; + } + bool event(QEvent *e) { QList touchPoints; @@ -64,6 +96,18 @@ protected: input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * dpi_scale; input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * dpi_scale; break; + case QEvent::KeyPress: + for (int b = 0; b < 14; b++) { + if (((QKeyEvent*)e)->key() == buttonMappings[b]) + input_state.pad_buttons |= (1<key() == buttonMappings[b]) + input_state.pad_buttons &= ~(1< Date: Thu, 10 Jan 2013 09:42:02 +0100 Subject: [PATCH 0203/1445] Retab drawbuffer before changing it --- gfx_es2/draw_buffer.cpp | 484 ++++++++++++++++++++-------------------- gfx_es2/draw_buffer.h | 184 +++++++-------- 2 files changed, 334 insertions(+), 334 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index cbe8309ec8..bd8f803551 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -13,158 +13,158 @@ #include "util/text/utf8.h" enum { - // Enough? - MAX_VERTS = 15000, + // Enough? + MAX_VERTS = 15000, }; DrawBuffer::DrawBuffer() : count_(0), atlas(0) { - verts_ = new Vertex[MAX_VERTS]; - fontscalex = 1.0f; - fontscaley = 1.0f; + verts_ = new Vertex[MAX_VERTS]; + fontscalex = 1.0f; + fontscaley = 1.0f; } DrawBuffer::~DrawBuffer() { - delete [] verts_; + delete [] verts_; } void DrawBuffer::Begin(DrawBufferMode dbmode) { - count_ = 0; - mode_ = dbmode; + count_ = 0; + mode_ = dbmode; } void DrawBuffer::End() { - // Currently does nothing, but call it! + // Currently does nothing, but call it! } void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { - if (count_ == 0) - return; - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - if (set_blend_state) { + if (count_ == 0) + return; + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + if (set_blend_state) { glstate.blend.enable(); glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - glUniform1i(program->sampler0, 0); - glEnableVertexAttribArray(program->a_position); - glEnableVertexAttribArray(program->a_color); - if (program->a_texcoord0 != -1) - glEnableVertexAttribArray(program->a_texcoord0); - GL_CHECK(); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].x); - glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &verts_[0].rgba); - if (program->a_texcoord0 != -1) - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].u); - glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_); - GL_CHECK(); - glDisableVertexAttribArray(program->a_position); - glDisableVertexAttribArray(program->a_color); - if (program->a_texcoord0 != -1) - glDisableVertexAttribArray(program->a_texcoord0); - GL_CHECK(); + } + glUniform1i(program->sampler0, 0); + glEnableVertexAttribArray(program->a_position); + glEnableVertexAttribArray(program->a_color); + if (program->a_texcoord0 != -1) + glEnableVertexAttribArray(program->a_texcoord0); + GL_CHECK(); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].x); + glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &verts_[0].rgba); + if (program->a_texcoord0 != -1) + glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].u); + glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_); + GL_CHECK(); + glDisableVertexAttribArray(program->a_position); + glDisableVertexAttribArray(program->a_color); + if (program->a_texcoord0 != -1) + glDisableVertexAttribArray(program->a_texcoord0); + GL_CHECK(); - count_ = 0; + count_ = 0; } void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) { - Vertex *vert = &verts_[count_++]; - vert->x = x; - vert->y = y; - vert->z = z; - vert->rgba = color; - vert->u = u; - vert->v = v; + Vertex *vert = &verts_[count_++]; + vert->x = x; + vert->y = y; + vert->z = z; + vert->rgba = color; + vert->u = u; + vert->v = v; } void DrawBuffer::Rect(float x, float y, float w, float h, uint32 color, int align) { - DoAlign(align, &x, &y, &w, &h); - RectVGradient(x, y, w, h, color, color); + DoAlign(align, &x, &y, &w, &h); + RectVGradient(x, y, w, h, color, color); } void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom) { - V(x, y, 0, colorTop, 0, 0); - V(x + w, y, 0, colorTop, 1, 0); - V(x + w, y + h, 0, colorBottom, 1, 1); - V(x, y, 0, colorTop, 0, 0); - V(x + w, y + h, 0, colorBottom, 1, 1); - V(x, y + h, 0, colorBottom, 0, 1); + V(x, y, 0, colorTop, 0, 0); + V(x + w, y, 0, colorTop, 1, 0); + V(x + w, y + h, 0, colorBottom, 1, 1); + V(x, y, 0, colorTop, 0, 0); + V(x + w, y + h, 0, colorBottom, 1, 1); + V(x, y + h, 0, colorBottom, 0, 1); } void DrawBuffer::MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops) { - for (int i = 0; i < numStops - 1; i++) { - float t0 = stops[i].t, t1 = stops[i+1].t; - uint32_t c0 = stops[i].t, c1 = stops[i+1].t; - RectVGradient(x, y + h * t0, w, h * (t1 - t0), c0, c1); - } + for (int i = 0; i < numStops - 1; i++) { + float t0 = stops[i].t, t1 = stops[i+1].t; + uint32_t c0 = stops[i].t, c1 = stops[i+1].t; + RectVGradient(x, y + h * t0, w, h * (t1 - t0), c0, c1); + } } void DrawBuffer::Rect(float x, float y, float w, float h, - float u, float v, float uw, float uh, - uint32 color) { - V(x, y, 0, color, u, v); - V(x + w, y, 0, color, u + uw, v); - V(x + w, y + h, 0, color, u + uw, v + uh); - V(x, y, 0, color, u, v); - V(x + w, y + h, 0, color, u + uw, v + uh); - V(x, y + h, 0, color, u, v + uh); + float u, float v, float uw, float uh, + uint32 color) { + V(x, y, 0, color, u, v); + V(x + w, y, 0, color, u + uw, v); + V(x + w, y + h, 0, color, u + uw, v + uh); + V(x, y, 0, color, u, v); + V(x + w, y + h, 0, color, u + uw, v + uh); + V(x, y + h, 0, color, u, v + uh); } void DrawBuffer::MeasureImage(int atlas_image, float *w, float *h) { - const AtlasImage &image = atlas->images[atlas_image]; - *w = (float)image.w; - *h = (float)image.h; + const AtlasImage &image = atlas->images[atlas_image]; + *w = (float)image.w; + *h = (float)image.h; } void DrawBuffer::DrawImage(int atlas_image, float x, float y, float scale, Color color, int align) { - const AtlasImage &image = atlas->images[atlas_image]; - float w = (float)image.w * scale; - float h = (float)image.h * scale; - if (align & ALIGN_HCENTER) x -= w / 2; - if (align & ALIGN_RIGHT) x -= w; - if (align & ALIGN_VCENTER) y -= h / 2; - if (align & ALIGN_BOTTOM) y -= h; - DrawImageStretch(atlas_image, x, y, x + w, y + h, color); + const AtlasImage &image = atlas->images[atlas_image]; + float w = (float)image.w * scale; + float h = (float)image.h * scale; + if (align & ALIGN_HCENTER) x -= w / 2; + if (align & ALIGN_RIGHT) x -= w; + if (align & ALIGN_VCENTER) y -= h / 2; + if (align & ALIGN_BOTTOM) y -= h; + DrawImageStretch(atlas_image, x, y, x + w, y + h, color); } void DrawBuffer::DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color) { - const AtlasImage &image = atlas->images[atlas_image]; - V(x1, y1, color, image.u1, image.v1); - V(x2, y1, color, image.u2, image.v1); - V(x2, y2, color, image.u2, image.v2); - V(x1, y1, color, image.u1, image.v1); - V(x2, y2, color, image.u2, image.v2); - V(x1, y2, color, image.u1, image.v2); + const AtlasImage &image = atlas->images[atlas_image]; + V(x1, y1, color, image.u1, image.v1); + V(x2, y1, color, image.u2, image.v1); + V(x2, y2, color, image.u2, image.v2); + V(x1, y1, color, image.u1, image.v1); + V(x2, y2, color, image.u2, image.v2); + V(x1, y2, color, image.u1, image.v2); } inline void rot(float *v, float angle, float xc, float yc) { - v[0]-=xc; - v[1]-=yc; + v[0]-=xc; + v[1]-=yc; - float ca=cosf(angle),sa=sinf(angle); + float ca=cosf(angle),sa=sinf(angle); - float t0 = v[0] * ca + v[1] * -sa; - float t1 = v[0] * sa + v[1] * ca; + float t0 = v[0] * ca + v[1] * -sa; + float t1 = v[0] * sa + v[1] * ca; - v[0] = t0 + xc; - v[1] = t1 + yc; + v[0] = t0 + xc; + v[1] = t1 + yc; } void DrawBuffer::DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color, bool mirror_h) { - const AtlasImage &image = atlas->images[atlas_image]; - float w = (float)image.w * scale; - float h = (float)image.h * scale; - float x1 = x - w / 2; - float x2 = x + w / 2; - float y1 = y - h / 2; - float y2 = y + h / 2; - float v[6][2] = { - {x1, y1}, - {x2, y1}, - {x2, y2}, - {x1, y1}, - {x2, y2}, - {x1, y2}, - }; + const AtlasImage &image = atlas->images[atlas_image]; + float w = (float)image.w * scale; + float h = (float)image.h * scale; + float x1 = x - w / 2; + float x2 = x + w / 2; + float y1 = y - h / 2; + float y2 = y + h / 2; + float v[6][2] = { + {x1, y1}, + {x2, y1}, + {x2, y2}, + {x1, y1}, + {x2, y2}, + {x1, y2}, + }; float u1 = image.u1; float u2 = image.u2; if (mirror_h) { @@ -172,128 +172,128 @@ void DrawBuffer::DrawImageRotated(int atlas_image, float x, float y, float scale u1 = u2; u2 = temp; } - const float uv[6][2] = { + const float uv[6][2] = { {u1, image.v1}, {u2, image.v1}, {u2, image.v2}, {u1, image.v1}, {u2, image.v2}, {u1, image.v2}, - }; - for (int i = 0; i < 6; i++) { - rot(v[i], angle, x, y); - V(v[i][0], v[i][1], 0, color, uv[i][0], uv[i][1]); - } + }; + for (int i = 0; i < 6; i++) { + rot(v[i], angle, x, y); + V(v[i][0], v[i][1], 0, color, uv[i][0], uv[i][1]); + } } // TODO: add arc support void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul) { - float angleDelta = PI * 2 / segments; - float uDelta = 1.0f / segments; - float t2 = thickness / 2.0f; - float r1 = radius + t2; - float r2 = radius - t2; - for (int i = 0; i < segments + 1; i++) { - float angle1 = i * angleDelta; - float angle2 = (i + 1) * angleDelta; - float u1 = u_mul * i * uDelta; - float u2 = u_mul * (i + 1) * uDelta; - // TODO: get rid of one pair of cos/sin per loop, can reuse from last iteration - float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2); - const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc}; - const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc}; - V(x[0], y[0], color, u1, 0); - V(x[1], y[1], color, u2, 0); - V(x[2], y[2], color, u1, 1); - V(x[1], y[1], color, u2, 0); - V(x[3], y[3], color, u2, 1); - V(x[2], y[2], color, u1, 1); - } + float angleDelta = PI * 2 / segments; + float uDelta = 1.0f / segments; + float t2 = thickness / 2.0f; + float r1 = radius + t2; + float r2 = radius - t2; + for (int i = 0; i < segments + 1; i++) { + float angle1 = i * angleDelta; + float angle2 = (i + 1) * angleDelta; + float u1 = u_mul * i * uDelta; + float u2 = u_mul * (i + 1) * uDelta; + // TODO: get rid of one pair of cos/sin per loop, can reuse from last iteration + float c1 = cosf(angle1), s1 = sinf(angle1), c2 = cosf(angle2), s2 = sinf(angle2); + const float x[4] = {c1 * r1 + xc, c2 * r1 + xc, c1 * r2 + xc, c2 * r2 + xc}; + const float y[4] = {s1 * r1 + yc, s2 * r1 + yc, s1 * r2 + yc, s2 * r2 + yc}; + V(x[0], y[0], color, u1, 0); + V(x[1], y[1], color, u2, 0); + V(x[2], y[2], color, u1, 1); + V(x[1], y[1], color, u2, 0); + V(x[3], y[3], color, u2, 1); + V(x[2], y[2], color, u1, 1); + } } void DrawBuffer::DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color) { - V(x1, y1, color, u1, v1); - V(x2, y1, color, u2, v1); - V(x2, y2, color, u2, v2); - V(x1, y1, color, u1, v1); - V(x2, y2, color, u2, v2); - V(x1, y2, color, u1, v2); + V(x1, y1, color, u1, v1); + V(x2, y1, color, u2, v1); + V(x2, y2, color, u2, v2); + V(x1, y1, color, u1, v1); + V(x2, y2, color, u2, v2); + V(x1, y2, color, u1, v2); } void DrawBuffer::DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color, float corner_scale) { - const AtlasImage &image = atlas->images[atlas_image]; + const AtlasImage &image = atlas->images[atlas_image]; float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; float um = (u2 + u1) * 0.5f; - float vm = (v2 + v1) * 0.5f; - float iw2 = (image.w * 0.5f) * corner_scale; - float ih2 = (image.h * 0.5f) * corner_scale; - float xa = x1 + iw2; - float xb = x2 - iw2; - float ya = y1 + ih2; - float yb = y2 - ih2; - // Top row - DrawTexRect(x1, y1, xa, ya, u1, v1, um, vm, color); - DrawTexRect(xa, y1, xb, ya, um, v1, um, vm, color); - DrawTexRect(xb, y1, x2, ya, um, v1, u2, vm, color); - // Middle row - DrawTexRect(x1, ya, xa, yb, u1, vm, um, vm, color); - DrawTexRect(xa, ya, xb, yb, um, vm, um, vm, color); - DrawTexRect(xb, ya, x2, yb, um, vm, u2, vm, color); - // Bottom row - DrawTexRect(x1, yb, xa, y2, u1, vm, um, v2, color); - DrawTexRect(xa, yb, xb, y2, um, vm, um, v2, color); - DrawTexRect(xb, yb, x2, y2, um, vm, u2, v2, color); + float vm = (v2 + v1) * 0.5f; + float iw2 = (image.w * 0.5f) * corner_scale; + float ih2 = (image.h * 0.5f) * corner_scale; + float xa = x1 + iw2; + float xb = x2 - iw2; + float ya = y1 + ih2; + float yb = y2 - ih2; + // Top row + DrawTexRect(x1, y1, xa, ya, u1, v1, um, vm, color); + DrawTexRect(xa, y1, xb, ya, um, v1, um, vm, color); + DrawTexRect(xb, y1, x2, ya, um, v1, u2, vm, color); + // Middle row + DrawTexRect(x1, ya, xa, yb, u1, vm, um, vm, color); + DrawTexRect(xa, ya, xb, yb, um, vm, um, vm, color); + DrawTexRect(xb, ya, x2, yb, um, vm, u2, vm, color); + // Bottom row + DrawTexRect(x1, yb, xa, y2, u1, vm, um, v2, color); + DrawTexRect(xa, yb, xb, y2, um, vm, um, v2, color); + DrawTexRect(xb, yb, x2, y2, um, vm, u2, v2, color); } void DrawBuffer::DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color, float corner_scale) { - const AtlasImage &image = atlas->images[atlas_image]; - float um = (image.u1 + image.u2) * 0.5f; - float iw2 = (image.w * 0.5f) * corner_scale; - float xa = x1 + iw2; - float xb = x2 - iw2; - float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; - float y2 = y1 + image.h; - DrawTexRect(x1, y1, xa, y2, u1, v1, um, v2, color); - DrawTexRect(xa, y1, xb, y2, um, v1, um, v2, color); - DrawTexRect(xb, y1, x2, y2, um, v1, u2, v2, color); + const AtlasImage &image = atlas->images[atlas_image]; + float um = (image.u1 + image.u2) * 0.5f; + float iw2 = (image.w * 0.5f) * corner_scale; + float xa = x1 + iw2; + float xb = x2 - iw2; + float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; + float y2 = y1 + image.h; + DrawTexRect(x1, y1, xa, y2, u1, v1, um, v2, color); + DrawTexRect(xa, y1, xb, y2, um, v1, um, v2, color); + DrawTexRect(xb, y1, x2, y2, um, v1, u2, v2, color); } void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { - const AtlasFont &atlasfont = *atlas->fonts[font]; - unsigned char cval; - float wacc = 0; - int lines = 1; - while ((cval = *text++) != '\0') { - if (cval < 32) continue; - if (cval > 127) continue; - if (cval == '\n') { - wacc = 0; - lines++; - } - AtlasChar c = atlasfont.chars[cval - 32]; - wacc += c.wx * fontscalex; - } - if (w) *w = wacc; - if (h) *h = atlasfont.height * fontscaley * lines; + const AtlasFont &atlasfont = *atlas->fonts[font]; + unsigned char cval; + float wacc = 0; + int lines = 1; + while ((cval = *text++) != '\0') { + if (cval < 32) continue; + if (cval > 127) continue; + if (cval == '\n') { + wacc = 0; + lines++; + } + AtlasChar c = atlasfont.chars[cval - 32]; + wacc += c.wx * fontscalex; + } + if (w) *w = wacc; + if (h) *h = atlasfont.height * fontscaley * lines; } void DrawBuffer::DrawTextShadow(int font, const char *text, float x, float y, Color color, int flags) { - uint32_t alpha = (color >> 1) & 0xFF000000; - DrawText(font, text, x + 2, y + 2, alpha, flags); - DrawText(font, text, x, y, color, flags); + uint32_t alpha = (color >> 1) & 0xFF000000; + DrawText(font, text, x + 2, y + 2, alpha, flags); + DrawText(font, text, x, y, color, flags); } void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) { - if (flags & ALIGN_HCENTER) *x -= *w / 2; - if (flags & ALIGN_RIGHT) *x -= *w; - if (flags & ALIGN_VCENTER) *y -= *h / 2; - if (flags & ALIGN_BOTTOM) *y -= *h; - if (flags & (ROTATE_90DEG_LEFT | ROTATE_90DEG_RIGHT)) { - std::swap(*w, *h); - std::swap(*x, *y); - } + if (flags & ALIGN_HCENTER) *x -= *w / 2; + if (flags & ALIGN_RIGHT) *x -= *w; + if (flags & ALIGN_VCENTER) *y -= *h / 2; + if (flags & ALIGN_BOTTOM) *y -= *h; + if (flags & (ROTATE_90DEG_LEFT | ROTATE_90DEG_RIGHT)) { + std::swap(*w, *h); + std::swap(*x, *y); + } } // TODO: Unicode support. @@ -304,69 +304,69 @@ void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) { // ROTATE_* doesn't yet work right. void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int flags) { - const AtlasFont &atlasfont = *atlas->fonts[font]; - unsigned char cval; - float w, h; - MeasureText(font, text, &w, &h); - if (flags) { - DoAlign(flags, &x, &y, &w, &h); - } + const AtlasFont &atlasfont = *atlas->fonts[font]; + unsigned char cval; + float w, h; + MeasureText(font, text, &w, &h); + if (flags) { + DoAlign(flags, &x, &y, &w, &h); + } - if (flags & ROTATE_90DEG_LEFT) { - x -= atlasfont.ascend*fontscaley; - // y += h; - } - else - y += atlasfont.ascend*fontscaley; - float sx = x; + if (flags & ROTATE_90DEG_LEFT) { + x -= atlasfont.ascend*fontscaley; + // y += h; + } + else + y += atlasfont.ascend*fontscaley; + float sx = x; UTF8 utf(text); - while (true) { + while (true) { if (utf.end()) break; cval = utf.next(); - if (cval == '\n') { - y += atlasfont.height * fontscaley; - x = sx; - continue; - } - if (cval < 32) continue; - if (cval > 127) continue; - AtlasChar c = atlasfont.chars[cval - 32]; - float cx1, cy1, cx2, cy2; - if (flags & ROTATE_90DEG_LEFT) { - cy1 = y - c.ox * fontscalex; - cx1 = x + c.oy * fontscaley; - cy2 = y - (c.ox + c.pw) * fontscalex; - cx2 = x + (c.oy + c.ph) * fontscaley; - } else { - cx1 = x + c.ox * fontscalex; - cy1 = y + c.oy * fontscaley; - cx2 = x + (c.ox + c.pw) * fontscalex; - cy2 = y + (c.oy + c.ph) * fontscaley; - } - V(cx1, cy1, color, c.sx, c.sy); - V(cx2, cy1, color, c.ex, c.sy); - V(cx2, cy2, color, c.ex, c.ey); - V(cx1, cy1, color, c.sx, c.sy); - V(cx2, cy2, color, c.ex, c.ey); - V(cx1, cy2, color, c.sx, c.ey); - if (flags & ROTATE_90DEG_LEFT) - y -= c.wx * fontscalex; - else - x += c.wx * fontscalex; - } + if (cval == '\n') { + y += atlasfont.height * fontscaley; + x = sx; + continue; + } + if (cval < 32) continue; + if (cval > 127) continue; + AtlasChar c = atlasfont.chars[cval - 32]; + float cx1, cy1, cx2, cy2; + if (flags & ROTATE_90DEG_LEFT) { + cy1 = y - c.ox * fontscalex; + cx1 = x + c.oy * fontscaley; + cy2 = y - (c.ox + c.pw) * fontscalex; + cx2 = x + (c.oy + c.ph) * fontscaley; + } else { + cx1 = x + c.ox * fontscalex; + cy1 = y + c.oy * fontscaley; + cx2 = x + (c.ox + c.pw) * fontscalex; + cy2 = y + (c.oy + c.ph) * fontscaley; + } + V(cx1, cy1, color, c.sx, c.sy); + V(cx2, cy1, color, c.ex, c.sy); + V(cx2, cy2, color, c.ex, c.ey); + V(cx1, cy1, color, c.sx, c.sy); + V(cx2, cy2, color, c.ex, c.ey); + V(cx1, cy2, color, c.sx, c.ey); + if (flags & ROTATE_90DEG_LEFT) + y -= c.wx * fontscalex; + else + x += c.wx * fontscalex; + } } void DrawBuffer::EnableBlend(bool enable) { - glstate.blend.set(enable); - glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blend.set(enable); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } void DrawBuffer::SetClipRect(float x, float y, float w, float h) { - // Sigh, OpenGL is upside down. - glScissor(x, dp_yres - y, w, h); - glstate.scissorTest.enable(); + // Sigh, OpenGL is upside down. + glScissor(x, dp_yres - y, w, h); + glstate.scissorTest.enable(); } void DrawBuffer::NoClip() diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 7f40829ac1..3e202238cb 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -9,133 +9,133 @@ struct Atlas; enum { - ALIGN_LEFT = 0, - ALIGN_RIGHT = 16, - ALIGN_TOP = 0, - ALIGN_BOTTOM = 1, - ALIGN_HCENTER = 4, - ALIGN_VCENTER = 8, - ALIGN_VBASELINE = 32, // text only, possibly not yet working + ALIGN_LEFT = 0, + ALIGN_RIGHT = 16, + ALIGN_TOP = 0, + ALIGN_BOTTOM = 1, + ALIGN_HCENTER = 4, + ALIGN_VCENTER = 8, + ALIGN_VBASELINE = 32, // text only, possibly not yet working - ALIGN_CENTER = ALIGN_HCENTER | ALIGN_VCENTER, - ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT, - ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT, - ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT, - ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT, + ALIGN_CENTER = ALIGN_HCENTER | ALIGN_VCENTER, + ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT, + ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT, + ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT, + ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT, - // Only for text drawing - ROTATE_90DEG_LEFT = 256, - ROTATE_90DEG_RIGHT = 512, - ROTATE_180DEG = 1024, + // Only for text drawing + ROTATE_90DEG_LEFT = 256, + ROTATE_90DEG_RIGHT = 512, + ROTATE_180DEG = 1024, }; struct GLSLProgram; enum DrawBufferMode { - DBMODE_NORMAL = 0, - DBMODE_LINES = 1 + DBMODE_NORMAL = 0, + DBMODE_LINES = 1 }; struct GradientStop { - float t; - uint32_t color; + float t; + uint32_t color; }; class DrawBuffer { public: - DrawBuffer(); - ~DrawBuffer(); + DrawBuffer(); + ~DrawBuffer(); - void Begin(DrawBufferMode mode = DBMODE_NORMAL); - void End(); + void Begin(DrawBufferMode mode = DBMODE_NORMAL); + void End(); - int Count() const { return count_; } + int Count() const { return count_; } - void Flush(const GLSLProgram *program, bool set_blend_state=true); - - void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); - void hLine(float x1, float y, float x2, uint32 color) { Rect(x1, y, x2 - x1, pixel_in_dps, color); } - void vLine(float x, float y1, float y2, uint32 color) { Rect(x, y1, pixel_in_dps, y2 - y1, color); } - void vLineAlpha50(float x, float y1, float y2, uint32 color) { Rect(x, y1, pixel_in_dps, y2 - y1, (color | 0xFF000000) & 0x7F000000); } + void Flush(const GLSLProgram *program, bool set_blend_state=true); + + void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); + void hLine(float x1, float y, float x2, uint32 color) { Rect(x1, y, x2 - x1, pixel_in_dps, color); } + void vLine(float x, float y1, float y2, uint32 color) { Rect(x, y1, pixel_in_dps, y2 - y1, color); } + void vLineAlpha50(float x, float y1, float y2, uint32 color) { Rect(x, y1, pixel_in_dps, y2 - y1, (color | 0xFF000000) & 0x7F000000); } - void RectOutline(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT) { - hLine(x, y, x + w + pixel_in_dps, color); - hLine(x, y + h, x + w + pixel_in_dps, color); + void RectOutline(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT) { + hLine(x, y, x + w + pixel_in_dps, color); + hLine(x, y + h, x + w + pixel_in_dps, color); - vLine(x, y, y + h + pixel_in_dps, color); - vLine(x + w, y, y + h + pixel_in_dps, color); - } - - void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom); - void RectVDarkFaded(float x, float y, float w, float h, uint32 colorTop) { - RectVGradient(x, y, w, h, colorTop, darkenColor(colorTop)); - } + vLine(x, y, y + h + pixel_in_dps, color); + vLine(x + w, y, y + h + pixel_in_dps, color); + } + + void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom); + void RectVDarkFaded(float x, float y, float w, float h, uint32 colorTop) { + RectVGradient(x, y, w, h, colorTop, darkenColor(colorTop)); + } - void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops); + void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops); - void RectCenter(float x, float y, float w, float h, uint32 color) { - Rect(x - w/2, y - h/2, w, h, color); - } - void Rect(float x, float y, float w, float h, float u, float v, float uw, float uh, uint32 color); + void RectCenter(float x, float y, float w, float h, uint32 color) { + Rect(x - w/2, y - h/2, w, h, color); + } + void Rect(float x, float y, float w, float h, float u, float v, float uw, float uh, uint32 color); - void V(float x, float y, float z, uint32 color, float u, float v); - void V(float x, float y, uint32 color, float u, float v) { - V(x, y, 0.0f, color, u, v); - } + void V(float x, float y, float z, uint32 color, float u, float v); + void V(float x, float y, uint32 color, float u, float v) { + V(x, y, 0.0f, color, u, v); + } - void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul); + void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul); - // New drawing APIs + // New drawing APIs - // Must call this before you use any functions with atlas_image etc. - void SetAtlas(const Atlas *_atlas) { - atlas = _atlas; - } - void MeasureImage(int atlas_image, float *w, float *h); - void DrawImage(int atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT); - void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); - void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF), bool mirror_h = false); // Always centers - void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); - // Results in 18 triangles. Kind of expensive for a button. - void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); - // This is only 6 triangles, much cheaper. - void DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); + // Must call this before you use any functions with atlas_image etc. + void SetAtlas(const Atlas *_atlas) { + atlas = _atlas; + } + void MeasureImage(int atlas_image, float *w, float *h); + void DrawImage(int atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT); + void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); + void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF), bool mirror_h = false); // Always centers + void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); + // Results in 18 triangles. Kind of expensive for a button. + void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); + // This is only 6 triangles, much cheaper. + void DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); - void MeasureText(int font, const char *text, float *w, float *h); - void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); - void DrawTextShadow(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); + void MeasureText(int font, const char *text, float *w, float *h); + void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); + void DrawTextShadow(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); - void RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color); - void SetFontScale(float xs, float ys) { - fontscalex = xs; - fontscaley = ys; - } + void RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color); + void SetFontScale(float xs, float ys) { + fontscalex = xs; + fontscaley = ys; + } - // Utility to avoid having to include gl.h just for this in UI code. - void EnableBlend(bool enable); + // Utility to avoid having to include gl.h just for this in UI code. + void EnableBlend(bool enable); - // Rectangular clipping, implemented using scissoring. - // Must flush before and after. - void SetClipRect(float x1, float y1, float x2, float y2); - void NoClip(); + // Rectangular clipping, implemented using scissoring. + // Must flush before and after. + void SetClipRect(float x1, float y1, float x2, float y2); + void NoClip(); private: - void DoAlign(int flags, float *x, float *y, float *w, float *h); - struct Vertex { - float x, y, z; - uint32_t rgba; - float u, v; - }; + void DoAlign(int flags, float *x, float *y, float *w, float *h); + struct Vertex { + float x, y, z; + uint32_t rgba; + float u, v; + }; - Vertex *verts_; - int count_; - DrawBufferMode mode_; - const Atlas *atlas; + Vertex *verts_; + int count_; + DrawBufferMode mode_; + const Atlas *atlas; - float fontscalex; - float fontscaley; + float fontscalex; + float fontscaley; }; From 20c37d8d0e48b23681d78ebc866f05bc09d4fbc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 10 Jan 2013 10:14:39 +0100 Subject: [PATCH 0204/1445] Use VBO to draw UI, just because that's how it's supposed to be done. --- gfx_es2/draw_buffer.cpp | 36 ++++++++++++++++++++++++++++++------ gfx_es2/draw_buffer.h | 16 +++++++++++----- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index bd8f803551..c7d6b5258b 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -21,12 +21,34 @@ DrawBuffer::DrawBuffer() : count_(0), atlas(0) { verts_ = new Vertex[MAX_VERTS]; fontscalex = 1.0f; fontscaley = 1.0f; + inited_ = false; + register_gl_resource_holder(this); } DrawBuffer::~DrawBuffer() { + unregister_gl_resource_holder(this); delete [] verts_; } +void DrawBuffer::Init() { + if (inited_) + return; + inited_ = true; + glGenBuffers(1, (GLuint *)&vbo_); +} + +void DrawBuffer::Shutdown() { + glDeleteBuffers(1, (GLuint *)&vbo_); + vbo_ = 0; + inited_ = false; +} + +void DrawBuffer::GLLost() { + inited_ = false; + Init(); +} + void DrawBuffer::Begin(DrawBufferMode dbmode) { + Init(); count_ = 0; mode_ = dbmode; } @@ -38,11 +60,12 @@ void DrawBuffer::End() { void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { if (count_ == 0) return; - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, vbo_); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * count_, verts_, GL_STREAM_DRAW); if (set_blend_state) { - glstate.blend.enable(); - glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blend.enable(); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glUniform1i(program->sampler0, 0); glEnableVertexAttribArray(program->a_position); @@ -50,10 +73,10 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { if (program->a_texcoord0 != -1) glEnableVertexAttribArray(program->a_texcoord0); GL_CHECK(); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].x); - glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), &verts_[0].rgba); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, x)); + glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void *)offsetof(Vertex, rgba)); if (program->a_texcoord0 != -1) - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &verts_[0].u); + glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, u)); glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_); GL_CHECK(); glDisableVertexAttribArray(program->a_position); @@ -61,6 +84,7 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { if (program->a_texcoord0 != -1) glDisableVertexAttribArray(program->a_texcoord0); GL_CHECK(); + glBindBuffer(GL_ARRAY_BUFFER, 0); count_ = 0; } diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 3e202238cb..1ec42a847f 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -5,6 +5,7 @@ #include "base/basictypes.h" #include "base/color.h" #include "base/display.h" +#include "gfx/gl_lost_manager.h" struct Atlas; @@ -36,13 +37,12 @@ enum DrawBufferMode { DBMODE_LINES = 1 }; -struct GradientStop -{ +struct GradientStop { float t; uint32_t color; }; -class DrawBuffer { +class DrawBuffer : public GfxResourceHolder { public: DrawBuffer(); ~DrawBuffer(); @@ -50,10 +50,15 @@ public: void Begin(DrawBufferMode mode = DBMODE_NORMAL); void End(); + // TODO: Enforce these. Now Init is autocalled and shutdown not called. + void Init(); + void Shutdown(); + virtual void GLLost(); + int Count() const { return count_; } void Flush(const GLSLProgram *program, bool set_blend_state=true); - + void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); void hLine(float x1, float y, float x2, uint32 color) { Rect(x1, y, x2 - x1, pixel_in_dps, color); } void vLine(float x, float y1, float y2, uint32 color) { Rect(x, y1, pixel_in_dps, y2 - y1, color); } @@ -121,7 +126,6 @@ public: void SetClipRect(float x1, float y1, float x2, float y2); void NoClip(); - private: void DoAlign(int flags, float *x, float *y, float *w, float *h); struct Vertex { @@ -130,11 +134,13 @@ private: float u, v; }; + int vbo_; Vertex *verts_; int count_; DrawBufferMode mode_; const Atlas *atlas; + bool inited_; float fontscalex; float fontscaley; }; From 11a1e3578345468ec041e72892f0a84032e2e361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 10 Jan 2013 11:11:32 +0100 Subject: [PATCH 0205/1445] Disable poor frame limiter in PCMain.cpp (SDL) for now, rely on vsync instead. --- base/PCMain.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 35a25d1e0b..b1c2c055c3 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -356,10 +356,10 @@ int main(int argc, char *argv[]) { SDL_GL_SwapBuffers(); // Simple frame rate limiting - while (time_now() < t + 1.0f/60.0f) { - sleep_ms(0); - time_update(); - } +// while (time_now() < t + 1.0f/60.0f) { +// sleep_ms(0); +// time_update(); +// } time_update(); t = time_now(); framecount++; From 1d82b785df70ef8992d5e14837801e356facb65a Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 10 Jan 2013 20:25:10 +1000 Subject: [PATCH 0206/1445] Fix joystick keys --- base/BlackberryMain.cpp | 8 ++++---- base/QtMain.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 86467e498e..8f82335e81 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -121,13 +121,13 @@ void SimulateGamepad(InputState *input) { input->pad_rstick_x = 0; input->pad_rstick_y = 0; - if (input->pad_buttons | (1<<14)) + if (input->pad_buttons & (1<<14)) input->pad_lstick_y=1; - else if (input->pad_buttons | (1<<15)) + else if (input->pad_buttons & (1<<15)) input->pad_lstick_y=-1; - if (input->pad_buttons | (1<<16)) + if (input->pad_buttons & (1<<16)) input->pad_lstick_x=-1; - else if (input->pad_buttons | (1<<17)) + else if (input->pad_buttons & (1<<17)) input->pad_lstick_x=1; } diff --git a/base/QtMain.cpp b/base/QtMain.cpp index ee74314d0c..469eb4135f 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -26,13 +26,13 @@ void SimulateGamepad(InputState *input) { input->pad_rstick_x = 0; input->pad_rstick_y = 0; - if (input->pad_buttons | (1<<14)) + if (input->pad_buttons & (1<<14)) input->pad_lstick_y=1; - else if (input->pad_buttons | (1<<15)) + else if (input->pad_buttons & (1<<15)) input->pad_lstick_y=-1; - if (input->pad_buttons | (1<<16)) + if (input->pad_buttons & (1<<16)) input->pad_lstick_x=-1; - else if (input->pad_buttons | (1<<17)) + else if (input->pad_buttons & (1<<17)) input->pad_lstick_x=1; } From 135ae4faf52f13d1bb79d9bbaf2eadd7177cc864 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 10 Jan 2013 23:47:50 +0100 Subject: [PATCH 0207/1445] Add LoggingDeadline, sprinkle this to track what takes time --- base/timeutil.cpp | 23 +++++++++++++++++++++++ base/timeutil.h | 16 ++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/base/timeutil.cpp b/base/timeutil.cpp index 3aa6670872..923c1f268a 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -1,4 +1,5 @@ #include "base/basictypes.h" +#include "base/logging.h" #include "base/timeutil.h" #ifdef _WIN32 @@ -78,3 +79,25 @@ void sleep_ms(int ms) { #endif } +LoggingDeadline::LoggingDeadline(const char *name, int ms) : name_(name), endCalled_(false) { + totalTime_ = (double)ms * 0.001; + time_update(); + endTime_ = time_now_d() + totalTime_; +} + +LoggingDeadline::~LoggingDeadline() { + if (!endCalled_) + End(); +} + +bool LoggingDeadline::End() { + time_update(); + if (time_now_d() > endTime_) { + double late = (time_now_d() - endTime_); + double totalTime = late + totalTime_; + ELOG("===== %0.2fms DEADLINE PASSED FOR %s at %0.2fms - %0.2fms late =====", totalTime_ * 1000.0f, name_, 1000.0 * late); + return false; + } + return true; +} + diff --git a/base/timeutil.h b/base/timeutil.h index 14dee0151b..8ba68ca8ad 100644 --- a/base/timeutil.h +++ b/base/timeutil.h @@ -19,3 +19,19 @@ int time_now_ms(); // Sleep. Does not necessarily have millisecond granularity, especially on Windows. void sleep_ms(int ms); + + +// Can be sprinkled around the code to make sure that thing don't take +// unexpectedly long. What that means is up to you. +class LoggingDeadline { +public: + LoggingDeadline(const char *name, int deadline_in_ms); + ~LoggingDeadline(); + bool End(); + +private: + const char *name_; + bool endCalled_; + double totalTime_; + double endTime_; +}; \ No newline at end of file From 7ceecd22b421c697d4d8c8ad6bda7654226be8ca Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 10 Jan 2013 23:48:28 +0100 Subject: [PATCH 0208/1445] Check for EXT_discard_framebuffer --- gfx_es2/fbo.cpp | 30 ++---------------------------- gfx_es2/gl_state.cpp | 18 ++++++++++++++++++ gfx_es2/gl_state.h | 11 +++++++++++ 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 519d891513..3eac4e53bc 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -3,6 +3,7 @@ #include "base/logging.h" #include "gfx_es2/fbo.h" #include "gfx/gl_common.h" +#include "gfx_es2/gl_state.h" #if defined(USING_GLES2) #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER @@ -16,33 +17,6 @@ #endif #endif -// TODO: Breakout this GL extension checker in its own file. - -struct GLExtensions { - bool OES_depth24; - bool OES_packed_depth_stencil; - bool OES_depth_texture; -}; - -GLExtensions gl_extensions; - -void CheckExtensions() { - static bool done = false; - if (done) - return; - done = true; - - memset(&gl_extensions, 0, sizeof(gl_extensions)); - - const char *extString = (const char *)glGetString(GL_EXTENSIONS); - - gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil"); - gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24"); - gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture"); -} - - - struct FBO { GLuint handle; GLuint color_texture; @@ -59,7 +33,7 @@ struct FBO { // On Android, we try to use what's available. FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { - CheckExtensions(); + CheckGLExtensions(); FBO *fbo = new FBO(); fbo->width = width; diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index e3dfcb5ce4..7a9e0087ad 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -1,6 +1,7 @@ #include "gl_state.h" OpenGLState glstate; +GLExtensions gl_extensions; void OpenGLState::Initialize() { if(initialized) return; @@ -26,3 +27,20 @@ void OpenGLState::Restore() { depthRange.restore(); depthFunc.restore(); } + +void CheckGLExtensions() { + static bool done = false; + if (done) + return; + done = true; + + memset(&gl_extensions, 0, sizeof(gl_extensions)); + + const char *extString = (const char *)glGetString(GL_EXTENSIONS); + + gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0; + gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; + gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; + gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; +} + diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 987ec59384..412f92de01 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -158,3 +158,14 @@ public: #undef STATE2 extern OpenGLState glstate; + +struct GLExtensions { + bool OES_depth24; + bool OES_packed_depth_stencil; + bool OES_depth_texture; + bool EXT_discard_framebuffer; +}; + +extern GLExtensions gl_extensions; + +void CheckGLExtensions(); From af5142d32a283ffc0ad1bba5d79a5f30fba717d9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 11 Jan 2013 00:29:26 +0100 Subject: [PATCH 0209/1445] Add missing printf parameter --- base/timeutil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/timeutil.cpp b/base/timeutil.cpp index 923c1f268a..4931b22919 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -95,7 +95,7 @@ bool LoggingDeadline::End() { if (time_now_d() > endTime_) { double late = (time_now_d() - endTime_); double totalTime = late + totalTime_; - ELOG("===== %0.2fms DEADLINE PASSED FOR %s at %0.2fms - %0.2fms late =====", totalTime_ * 1000.0f, name_, 1000.0 * late); + ELOG("===== %0.2fms DEADLINE PASSED FOR %s at %0.2fms - %0.2fms late =====", totalTime_ * 1000.0, name_, 1000.0 * totalTime, 1000.0 * late); return false; } return true; From 7b9daa28c4c21c91864c7ef3d2cf480ae890b2be Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Fri, 11 Jan 2013 19:02:56 +0100 Subject: [PATCH 0210/1445] Properly restore all the OpenGL states properly and added a sanity check. Also set the proper viewport value at startup. --- base/PCMain.cpp | 2 ++ gfx_es2/gl_state.cpp | 32 +++++++++++++++++++++----------- gfx_es2/gl_state.h | 33 +++++++++++++++++++++------------ 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index b1c2c055c3..11619f91a7 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -26,6 +26,7 @@ #include "base/display.h" #include "base/logging.h" #include "base/timeutil.h" +#include "gfx_es2/gl_state.h" #include "gfx_es2/glsl_program.h" #include "file/zip_read.h" #include "input/input_state.h" @@ -271,6 +272,7 @@ int main(int argc, char *argv[]) { pixel_in_dps = (float)pixel_xres / dp_xres; NativeInitGraphics(); + glstate.viewport.set(0, 0, pixel_xres, pixel_yres); float dp_xscale = (float)dp_xres / pixel_xres; float dp_yscale = (float)dp_yres / pixel_yres; diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 7a9e0087ad..19f3b4a9bc 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -1,8 +1,11 @@ +#include #include "gl_state.h" OpenGLState glstate; GLExtensions gl_extensions; +int OpenGLState::state_count = 0; + void OpenGLState::Initialize() { if(initialized) return; @@ -12,20 +15,27 @@ void OpenGLState::Initialize() { } void OpenGLState::Restore() { - blend.restore(); - blendEquation.restore(); - blendFunc.restore(); - blendColor.restore(); + int count = 0; + blend.restore(); count++; + blendEquation.restore(); count++; + blendFunc.restore(); count++; + blendColor.restore(); count++; - scissorTest.restore(); + scissorTest.restore(); count++; - cullFace.restore(); - cullFaceMode.restore(); - frontFace.restore(); + cullFace.restore(); count++; + cullFaceMode.restore(); count++; + frontFace.restore(); count++; - depthTest.restore(); - depthRange.restore(); - depthFunc.restore(); + depthTest.restore(); count++; + depthRange.restore(); count++; + depthFunc.restore(); count++; + depthWrite.restore(); count++; + + colorMask.restore(); count++; + viewport.restore(); count++; + + assert(count == state_count && "OpenGLState::Restore is missing some states"); } void CheckGLExtensions() { diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 412f92de01..eac3b26cd6 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -14,7 +14,9 @@ private: class BoolState { bool _value; public: - BoolState() : _value(init) {} + BoolState() : _value(init) { + OpenGLState::state_count++; + } inline void set(bool value) { if(value && value != _value) { @@ -50,7 +52,9 @@ private: class SavedState1_##func { \ p1type p1; \ public: \ - SavedState1_##func() : p1(p1def) {}; \ + SavedState1_##func() : p1(p1def) { \ + OpenGLState::state_count++; \ + }; \ void set(p1type newp1) { \ if(newp1 != p1) { \ p1 = newp1; \ @@ -67,7 +71,9 @@ private: p1type p1; \ p2type p2; \ public: \ - SavedState2_##func() : p1(p1def), p2(p2def) {}; \ + SavedState2_##func() : p1(p1def), p2(p2def) { \ + OpenGLState::state_count++; \ + }; \ inline void set(p1type newp1, p2type newp2) { \ if(newp1 != p1 || newp2 != p2) { \ p1 = newp1; \ @@ -87,7 +93,9 @@ private: p3type p3; \ p4type p4; \ public: \ - SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) {}; \ + SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) { \ + OpenGLState::state_count++; \ + }; \ inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \ if(newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \ p1 = newp1; \ @@ -108,6 +116,7 @@ private: public: \ SavedState4_##func() { \ for (int i = 0; i < 4; i++) {p[i] = def;} \ + OpenGLState::state_count++; \ }; \ inline void set(const float v[4]) { \ if(memcmp(p,v,sizeof(float)*4)) { \ @@ -123,10 +132,12 @@ private: bool initialized; public: + static int state_count; OpenGLState() : initialized(false) {} void Initialize(); void Restore(); + // When adding a state here, don't forget to add it to OpenGLState::Restore() too BoolState blend; STATE2(glBlendFunc, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFunc; STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; @@ -139,19 +150,17 @@ public: STATE1(glFrontFace, GLenum, GL_CCW) frontFace; BoolState depthTest; - STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; - - STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite; - - STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask; - - STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport; - #if defined(USING_GLES2) STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; #else STATE2(glDepthRange, double, double, 0.0, 1.0) depthRange; #endif + STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; + STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite; + + STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask; + + STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport; }; #undef STATE1 From dcc978535796a7ceb8363cab582305774543dfaa Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 11 Jan 2013 23:45:39 +0100 Subject: [PATCH 0211/1445] Bugfix LoggingDeadline --- base/timeutil.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/base/timeutil.cpp b/base/timeutil.cpp index 4931b22919..0f18c16fbc 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -91,6 +91,7 @@ LoggingDeadline::~LoggingDeadline() { } bool LoggingDeadline::End() { + endCalled_ = true; time_update(); if (time_now_d() > endTime_) { double late = (time_now_d() - endTime_); From c60bda83b6871f151921ca818a4ba292714bd7ec Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 11 Jan 2013 23:46:03 +0100 Subject: [PATCH 0212/1445] Don't try to register/unregister too early. --- gfx_es2/draw_buffer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index c7d6b5258b..87106e5ac4 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -22,10 +22,8 @@ DrawBuffer::DrawBuffer() : count_(0), atlas(0) { fontscalex = 1.0f; fontscaley = 1.0f; inited_ = false; - register_gl_resource_holder(this); } DrawBuffer::~DrawBuffer() { - unregister_gl_resource_holder(this); delete [] verts_; } @@ -34,12 +32,14 @@ void DrawBuffer::Init() { return; inited_ = true; glGenBuffers(1, (GLuint *)&vbo_); + register_gl_resource_holder(this); } void DrawBuffer::Shutdown() { glDeleteBuffers(1, (GLuint *)&vbo_); vbo_ = 0; inited_ = false; + unregister_gl_resource_holder(this); } void DrawBuffer::GLLost() { From 7c0f9617b0085f99559d141bd3015dae9a02a3b0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 13 Jan 2013 01:38:37 +1000 Subject: [PATCH 0213/1445] Port to Pandora. Thanks to ptitSeb. --- base/PCMain.cpp | 185 +++++++++++++++++++++++++++++++++++++++++++----- gfx/gl_common.h | 2 +- 2 files changed, 170 insertions(+), 17 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index b1c2c055c3..84b061bd04 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -32,8 +32,125 @@ #include "base/NativeApp.h" #include "net/resolve.h" -// Simple implementations of System functions +#ifdef PANDORA +// EGL2SDL for Pandora +#include "EGL/egl.h" +#include +#include +#include "SDL_syswm.h" +EGLDisplay g_eglDisplay = NULL; +EGLContext g_eglContext = NULL; +EGLSurface g_eglSurface = NULL; +Display* g_Display = NULL; +NativeWindowType g_Window = NULL; + +int8_t CheckEGLErrors(const string& file, uint16_t line) { + EGLenum error; + string errortext; + + error = eglGetError(); + switch (error) + { + case EGL_SUCCESS: case 0: return 0; + case EGL_NOT_INITIALIZED: errortext = "EGL_NOT_INITIALIZED"; break; + case EGL_BAD_ACCESS: errortext = "EGL_BAD_ACCESS"; break; + case EGL_BAD_ALLOC: errortext = "EGL_BAD_ALLOC"; break; + case EGL_BAD_ATTRIBUTE: errortext = "EGL_BAD_ATTRIBUTE"; break; + case EGL_BAD_CONTEXT: errortext = "EGL_BAD_CONTEXT"; break; + case EGL_BAD_CONFIG: errortext = "EGL_BAD_CONFIG"; break; + case EGL_BAD_CURRENT_SURFACE: errortext = "EGL_BAD_CURRENT_SURFACE"; break; + case EGL_BAD_DISPLAY: errortext = "EGL_BAD_DISPLAY"; break; + case EGL_BAD_SURFACE: errortext = "EGL_BAD_SURFACE"; break; + case EGL_BAD_MATCH: errortext = "EGL_BAD_MATCH"; break; + case EGL_BAD_PARAMETER: errortext = "EGL_BAD_PARAMETER"; break; + case EGL_BAD_NATIVE_PIXMAP: errortext = "EGL_BAD_NATIVE_PIXMAP"; break; + case EGL_BAD_NATIVE_WINDOW: errortext = "EGL_BAD_NATIVE_WINDOW"; break; + default: errortext = "unknown"; break; + } + printf( "ERROR: EGL Error detected in file %s at line %d: %s (0x%X)\n", file.c_str(), line, errortext.c_str(), error ); + return 1; +} +#define EGL_ERROR(str, check) { \ + if (check) CheckEGLErrors( __FILE__, __LINE__ ); \ + printf("EGL ERROR: " str "\n"); \ + return 1; \ + } + +void EGL_Open() { + if ((g_Display = XOpenDisplay(NULL)) == NULL) + EGL_ERROR("Unable to get display!", false); + + if ((g_eglDisplay = eglGetDisplay((NativeDisplayType)g_Display)) == EGL_NO_DISPLAY) + EGL_ERROR("Unable to create EGL display.", true); + + if (eglInitialize(g_eglDisplay, NULL, NULL) != EGL_TRUE) + EGL_ERROR("Unable to initialize EGL display.", true); +} + +int8_t EGL_Init() { + EGLConfig g_eglConfig = NULL; + EGLint g_numConfigs = 0; + EGLint attrib_list[]= { + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_DEPTH_SIZE, 16, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_SAMPLE_BUFFERS, 0, + EGL_SAMPLES, 0, + EGL_NONE}; + + const EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + + EGLBoolean result = eglChooseConfig(g_eglDisplay, attrib_list, g_eglConfig, 1, &g_numConfigs); + if (result != EGL_TRUE || g_numConfigs == 0) EGL_ERROR("Unable to query for available configs."); + + g_eglContext = eglCreateContext(g_eglDisplay, g_eglConfig, NULL, attributes); + if (g_eglContext == EGL_NO_CONTEXT) EGL_ERROR("Unable to create GLES context!", true); + + // Get the SDL window handle + SDL_SysWMinfo sysInfo; //Will hold our Window information + SDL_VERSION(&sysInfo.version); //Set SDL version + if(SDL_GetWMInfo(&sysInfo) <= 0) + { + printf("EGL ERROR: Unable to get SDL window handle: %s\n", SDL_GetError()); + return 1; + } + + g_Window = (NativeWindowType)sysInfo.info.x11.window; + g_eglSurface = eglCreateWindowSurface(g_eglDisplay, g_eglConfig, g_Window, 0); + if (g_eglSurface == EGL_NO_SURFACE) EGL_ERROR("Unable to create EGL surface!", true); + + if (eglMakeCurrent(g_eglDisplay, g_eglSurface, g_eglSurface, g_eglContext) != EGL_TRUE) + EGL_ERROR("Unable to make GLES context current.", true); + return 0; +} + +void EGL_Close() { + if (g_eglDisplay != NULL) + { + eglMakeCurrent(g_eglDisplay, NULL, NULL, EGL_NO_CONTEXT); + if (g_eglContext != NULL) { + eglDestroyContext(g_eglDisplay, g_eglContext); + } + if (g_eglSurface != NULL) { + eglDestroySurface(g_eglDisplay, g_eglSurface); + } + eglTerminate(g_eglDisplay); + g_eglDisplay = NULL; + } + if (g_Display != NULL) { + XCloseDisplay(g_Display); + g_Display = NULL; + } + g_eglSurface = NULL; + g_eglContext = NULL; +} +#endif + +// Simple implementations of System functions void SystemToast(const char *text) { @@ -91,20 +208,31 @@ void LaunchEmail(const char *email_address) const int buttonMappings[14] = { - SDLK_z, //A - SDLK_x, //B - SDLK_a, //X - SDLK_s, //Y - SDLK_w, //LBUMPER - SDLK_q, //RBUMPER - SDLK_SPACE, //START - SDLK_v, //SELECT - SDLK_UP, //UP - SDLK_DOWN, //DOWN - SDLK_LEFT, //LEFT - SDLK_RIGHT, //RIGHT - SDLK_m, //MENU - SDLK_BACKSPACE, //BACK +#ifdef PANDORA + SDLK_PAGEDOWN, //X => cross + SDLK_END, //B => circle + SDLK_HOME, //A => box + SDLK_PAGEUP, //Y => triangle + SDLK_RSHIFT, //LBUMPER + SDLK_RCTRL, //RBUMPER + SDLK_LALT, //START + SDLK_LCTRL, //SELECT +#else + SDLK_z, //A + SDLK_x, //B + SDLK_a, //X + SDLK_s, //Y + SDLK_w, //LBUMPER + SDLK_q, //RBUMPER + SDLK_SPACE, //START + SDLK_v, //SELECT +#endif + SDLK_UP, //UP + SDLK_DOWN, //DOWN + SDLK_LEFT, //LEFT + SDLK_RIGHT, //RIGHT + SDLK_m, //MENU + SDLK_BACKSPACE, //BACK }; void SimulateGamepad(const uint8 *keys, InputState *input) { @@ -118,6 +246,9 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_buttons |= (1<pad_lstick_y=1; else if (keys[SDLK_k]) @@ -134,6 +265,7 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_rstick_x=-1; else if (keys[SDLK_KP6]) input->pad_rstick_x=1; +#endif } extern void mixaudio(void *userdata, Uint8 *stream, int len) { @@ -211,6 +343,9 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } +#ifdef PANDORA + EGL_Open(); +#endif SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); @@ -221,14 +356,24 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); - if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, SDL_OPENGL) == NULL) { + if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, +#ifdef USING_GLES2 + SDL_SWSURFACE | SDL_FULLSCREEN +#else + SDL_OPENGL +#endif + ) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return(2); } +#ifdef PANDORA + EGL_Init(); +#endif SDL_WM_SetCaption(app_name_nice.c_str(), NULL); +#ifndef USING_GLES2 if (GLEW_OK != glewInit()) { printf("Failed to initialize glew!\n"); return 1; @@ -240,6 +385,7 @@ int main(int argc, char *argv[]) { printf("Sorry, this program requires OpenGL 2.0.\n"); return 1; } +#endif #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); @@ -353,7 +499,11 @@ int main(int argc, char *argv[]) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } +#ifdef PANDORA + eglSwapBuffers(g_eglDisplay, g_eglSurface); +#else SDL_GL_SwapBuffers(); +#endif // Simple frame rate limiting // while (time_now() < t + 1.0f/60.0f) { @@ -373,6 +523,9 @@ int main(int argc, char *argv[]) { SDL_PauseAudio(1); SDL_CloseAudio(); NativeShutdown(); +#ifdef PANDORA + EGL_Close(); +#endif SDL_Quit(); net::Shutdown(); exit(0); diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 25f93c42d5..fcbe486c06 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -19,7 +19,7 @@ typedef char GLchar; #endif #endif -#if defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) +#if defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(PANDORA) typedef char GLchar; #endif From de36ea9f34187172b8da2bbb25d5b0e03027eb2c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 12 Jan 2013 16:54:19 +0100 Subject: [PATCH 0214/1445] Add state caching for stencil test. --- gfx_es2/gl_state.cpp | 5 ++++- gfx_es2/gl_state.h | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 19f3b4a9bc..488bdaf950 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -35,6 +35,10 @@ void OpenGLState::Restore() { colorMask.restore(); count++; viewport.restore(); count++; + stencilTest.restore(); count++; + stencilOp.restore(); count++; + stencilFunc.restore(); count++; + assert(count == state_count && "OpenGLState::Restore is missing some states"); } @@ -53,4 +57,3 @@ void CheckGLExtensions() { gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; } - diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index eac3b26cd6..c02d8ef083 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -86,6 +86,28 @@ private: } \ } + #define STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \ + class SavedState3_##func { \ + p1type p1; \ + p2type p2; \ + p3type p3; \ + public: \ + SavedState3_##func() : p1(p1def), p2(p2def), p3(p3def) { \ + OpenGLState::state_count++; \ + }; \ + inline void set(p1type newp1, p2type newp2, p3type newp3) { \ + if(newp1 != p1 || newp2 != p2 || newp3 != p3) { \ + p1 = newp1; \ + p2 = newp2; \ + p3 = newp3; \ + func(p1, p2, p3); \ + } \ + } \ + inline void restore() { \ + func(p1, p2, p3); \ + } \ + } + #define STATE4(func, p1type, p2type, p3type, p4type, p1def, p2def, p3def, p4def) \ class SavedState4_##func { \ p1type p1; \ @@ -161,6 +183,10 @@ public: STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask; STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport; + + BoolState stencilTest; + STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp; + STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; }; #undef STATE1 From 44e9e946a90411dc9ce4663483d4365e2e17bc3b Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 11 Jan 2013 13:41:21 +1000 Subject: [PATCH 0215/1445] Add names to the magic numbers of left joystick input (Qt/Blackberry). --- base/BlackberryMain.cpp | 8 ++++---- base/QtMain.cpp | 8 ++++---- input/input_state.h | 7 ++++++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 8f82335e81..6a90becc7c 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -121,13 +121,13 @@ void SimulateGamepad(InputState *input) { input->pad_rstick_x = 0; input->pad_rstick_y = 0; - if (input->pad_buttons & (1<<14)) + if (input->pad_buttons & PAD_BUTTON_JOY_UP) input->pad_lstick_y=1; - else if (input->pad_buttons & (1<<15)) + else if (input->pad_buttons & PAD_BUTTON_JOY_DOWN) input->pad_lstick_y=-1; - if (input->pad_buttons & (1<<16)) + if (input->pad_buttons & PAD_BUTTON_JOY_LEFT) input->pad_lstick_x=-1; - else if (input->pad_buttons & (1<<17)) + else if (input->pad_buttons & PAD_BUTTON_JOY_RIGHT) input->pad_lstick_x=1; } diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 469eb4135f..69137ead14 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -26,13 +26,13 @@ void SimulateGamepad(InputState *input) { input->pad_rstick_x = 0; input->pad_rstick_y = 0; - if (input->pad_buttons & (1<<14)) + if (input->pad_buttons & PAD_BUTTON_JOY_UP) input->pad_lstick_y=1; - else if (input->pad_buttons & (1<<15)) + else if (input->pad_buttons & PAD_BUTTON_JOY_DOWN) input->pad_lstick_y=-1; - if (input->pad_buttons & (1<<16)) + if (input->pad_buttons & PAD_BUTTON_JOY_LEFT) input->pad_lstick_x=-1; - else if (input->pad_buttons & (1<<17)) + else if (input->pad_buttons & PAD_BUTTON_JOY_RIGHT) input->pad_lstick_x=1; } diff --git a/input/input_state.h b/input/input_state.h index 9978da0953..27480e4a0e 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -18,9 +18,14 @@ enum { PAD_BUTTON_LEFT = 1024, PAD_BUTTON_RIGHT = 2048, - // Android only PAD_BUTTON_MENU = 4096, PAD_BUTTON_BACK = 8192, + + // For Blackberry and Qt + PAD_BUTTON_JOY_UP = 1<<14, + PAD_BUTTON_JOY_DOWN = 1<<15, + PAD_BUTTON_JOY_LEFT = 1<<16, + PAD_BUTTON_JOY_RIGHT = 1<<17, }; #ifndef MAX_POINTERS From 4b8c56330a32e52b4265f715385a71f29990bcd4 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 13 Jan 2013 03:09:22 +1000 Subject: [PATCH 0216/1445] Many platforms don't have GLchar defined, just check if it is instead. --- gfx/gl_common.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index fcbe486c06..7722ed3133 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -5,7 +5,6 @@ #if defined(IOS) #include #include -typedef char GLchar; #else #include #include @@ -19,7 +18,7 @@ typedef char GLchar; #endif #endif -#if defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(PANDORA) +#ifndef GLchar typedef char GLchar; #endif From 657f5d32f4f2f38d711bbc144bf8667cf3141653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 13 Jan 2013 14:55:19 +0100 Subject: [PATCH 0217/1445] Zero nextScreen_ on screenmanager shutdown. --- ui/screen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index e4d3e7b57c..edb31846e7 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -125,6 +125,7 @@ void ScreenManager::shutdown() { } stack_.clear(); delete nextScreen_; + nextScreen_ = 0; } void ScreenManager::push(Screen *screen, int layerFlags) { @@ -174,4 +175,4 @@ void ScreenManager::processFinishDialog() delete dialogFinished_; dialogFinished_ = 0; } -} \ No newline at end of file +} From 597be2bb04e71157de520e432485f297b5b56f75 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Fri, 11 Jan 2013 23:00:33 +0100 Subject: [PATCH 0218/1445] Update native for Qt Window Add mutex lock. Wait cond didn't work without it. --- base/NativeApp.h | 1 + base/QtMain.cpp | 36 +++++++++++++++++++++++++++++++++++- base/QtMain.h | 12 ++++++++++-- base/mutex.h | 8 +++++--- 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/base/NativeApp.h b/base/NativeApp.h index 677568c075..ea46683736 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -61,6 +61,7 @@ void NativeRender(); // of num_samples. // This function may be called from a totally separate thread from // the rest of the game, so be careful with synchronization. +void NativeSetMixer(void* mix); void NativeMix(short *audio, int num_samples); // Called when it's time to shutdown. After this has been called, diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 469eb4135f..a3448ccc0f 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -15,6 +15,16 @@ #endif #include "QtMain.h" +#ifdef LINUX +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "qtapp.h" +#ifdef Q_WS_X11 +#include +#endif +MainWindow* qMW; +#endif + void LaunchBrowser(const char *url) { QDesktopServices::openUrl(QUrl(url)); @@ -52,11 +62,23 @@ float CalculateDPIScale() int main(int argc, char *argv[]) { +#ifdef LINUX +#ifdef Q_WS_X11 + XInitThreads(); +#endif +#endif QApplication a(argc, argv); // Lock orientation to landscape on Symbian #ifdef __SYMBIAN32__ QT_TRAP_THROWING(dynamic_cast(CEikonEnv::Static()->AppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); #endif +#ifdef LINUX + pixel_xres = 480; + pixel_yres = 272; + + float dpi_scale = 1; + dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); +#else QSize res = QApplication::desktop()->screenGeometry().size(); #ifdef USING_GLES2 if (res.width() < res.height()) @@ -70,21 +92,33 @@ int main(int argc, char *argv[]) #endif float dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); +#endif + net::Init(); + #ifdef __SYMBIAN32__ NativeInit(argc, (const char **)argv, "E:/PPSSPP/", "E:", "BADCOFFEE"); #elif defined(BLACKBERRY) NativeInit(argc, (const char **)argv, "data/", "/tmp", "BADCOFFEE"); -#else +#elif !defined(LINUX) NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); +#else + MainWindow mainWindow; + qMW = &mainWindow; + mainWindow.show(); + mainWindow.Create(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #endif +#ifdef LINUX +#else MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); #ifdef USING_GLES2 w.showFullScreen(); #else w.show(); +#endif + #endif MainAudio *audio = new MainAudio(); diff --git a/base/QtMain.h b/base/QtMain.h index 4c47054504..c4365ca484 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -5,6 +5,7 @@ #include #include "gfx_es2/glsl_program.h" #include +#include #include #include @@ -88,7 +89,7 @@ protected: break; } } - break; + break; case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: input_state.pointer_down[0] = (e->type() == QEvent::MouseButtonPress); @@ -161,16 +162,23 @@ public: output = new QAudioOutput(fmt); output->setNotifyInterval(1000*AUDIO_SAMPLES / AUDIO_FREQ); output->setBufferSize(mixlen); - this->connect(output, SIGNAL(notify()), this, SLOT(writeData())); feed = output->start(); + + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(writeData())); + timer->start(1000*AUDIO_SAMPLES / AUDIO_FREQ); + } ~MainAudio() { + feed->close(); delete feed; + output->stop(); delete output; free(mixbuf); } private slots: + void writeData() { memset(mixbuf, 0, mixlen); NativeMix((short *)mixbuf, mixlen / 4); diff --git a/base/mutex.h b/base/mutex.h index 59594ae883..53f8534fe3 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -115,7 +115,7 @@ public: #ifdef _WIN32 SetEvent(event_); #else - pthread_cond_signal(&event_); + pthread_cond_signal(&event_); #endif } @@ -129,7 +129,9 @@ public: ResetEvent(event_); // necessary? // mtx.lock(); #else - pthread_cond_wait(&event_, &mtx.native_handle()); + pthread_mutex_lock( &mtx.native_handle() ); + pthread_cond_wait(&event_, &mtx.native_handle()); + pthread_mutex_unlock( &mtx.native_handle() ); #endif } @@ -139,4 +141,4 @@ private: #else pthread_cond_t event_; #endif -}; \ No newline at end of file +}; From 063087abba1bfffa33f00470971fd3c428ada30d Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 14 Jan 2013 19:10:51 +1000 Subject: [PATCH 0219/1445] Revert "Merge pull request #29 from Xele02/qtwindow" This reverts commit 170a45ef4f2d92f290bdaa1d680c3bbbb6c5edbb, reversing changes made to 657f5d32f4f2f38d711bbc144bf8667cf3141653. --- base/NativeApp.h | 1 - base/QtMain.cpp | 36 +----------------------------------- base/QtMain.h | 12 ++---------- base/mutex.h | 8 +++----- 4 files changed, 6 insertions(+), 51 deletions(-) diff --git a/base/NativeApp.h b/base/NativeApp.h index ea46683736..677568c075 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -61,7 +61,6 @@ void NativeRender(); // of num_samples. // This function may be called from a totally separate thread from // the rest of the game, so be careful with synchronization. -void NativeSetMixer(void* mix); void NativeMix(short *audio, int num_samples); // Called when it's time to shutdown. After this has been called, diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 14dd1284d6..69137ead14 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -15,16 +15,6 @@ #endif #include "QtMain.h" -#ifdef LINUX -#include "mainwindow.h" -#include "ui_mainwindow.h" -#include "qtapp.h" -#ifdef Q_WS_X11 -#include -#endif -MainWindow* qMW; -#endif - void LaunchBrowser(const char *url) { QDesktopServices::openUrl(QUrl(url)); @@ -62,23 +52,11 @@ float CalculateDPIScale() int main(int argc, char *argv[]) { -#ifdef LINUX -#ifdef Q_WS_X11 - XInitThreads(); -#endif -#endif QApplication a(argc, argv); // Lock orientation to landscape on Symbian #ifdef __SYMBIAN32__ QT_TRAP_THROWING(dynamic_cast(CEikonEnv::Static()->AppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); #endif -#ifdef LINUX - pixel_xres = 480; - pixel_yres = 272; - - float dpi_scale = 1; - dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); -#else QSize res = QApplication::desktop()->screenGeometry().size(); #ifdef USING_GLES2 if (res.width() < res.height()) @@ -92,33 +70,21 @@ int main(int argc, char *argv[]) #endif float dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); -#endif - net::Init(); - #ifdef __SYMBIAN32__ NativeInit(argc, (const char **)argv, "E:/PPSSPP/", "E:", "BADCOFFEE"); #elif defined(BLACKBERRY) NativeInit(argc, (const char **)argv, "data/", "/tmp", "BADCOFFEE"); -#elif !defined(LINUX) - NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #else - MainWindow mainWindow; - qMW = &mainWindow; - mainWindow.show(); - mainWindow.Create(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #endif -#ifdef LINUX -#else MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); #ifdef USING_GLES2 w.showFullScreen(); #else w.show(); -#endif - #endif MainAudio *audio = new MainAudio(); diff --git a/base/QtMain.h b/base/QtMain.h index c4365ca484..4c47054504 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -5,7 +5,6 @@ #include #include "gfx_es2/glsl_program.h" #include -#include #include #include @@ -89,7 +88,7 @@ protected: break; } } - break; + break; case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: input_state.pointer_down[0] = (e->type() == QEvent::MouseButtonPress); @@ -162,23 +161,16 @@ public: output = new QAudioOutput(fmt); output->setNotifyInterval(1000*AUDIO_SAMPLES / AUDIO_FREQ); output->setBufferSize(mixlen); + this->connect(output, SIGNAL(notify()), this, SLOT(writeData())); feed = output->start(); - - QTimer *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(writeData())); - timer->start(1000*AUDIO_SAMPLES / AUDIO_FREQ); - } ~MainAudio() { - feed->close(); delete feed; - output->stop(); delete output; free(mixbuf); } private slots: - void writeData() { memset(mixbuf, 0, mixlen); NativeMix((short *)mixbuf, mixlen / 4); diff --git a/base/mutex.h b/base/mutex.h index 53f8534fe3..59594ae883 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -115,7 +115,7 @@ public: #ifdef _WIN32 SetEvent(event_); #else - pthread_cond_signal(&event_); + pthread_cond_signal(&event_); #endif } @@ -129,9 +129,7 @@ public: ResetEvent(event_); // necessary? // mtx.lock(); #else - pthread_mutex_lock( &mtx.native_handle() ); - pthread_cond_wait(&event_, &mtx.native_handle()); - pthread_mutex_unlock( &mtx.native_handle() ); + pthread_cond_wait(&event_, &mtx.native_handle()); #endif } @@ -141,4 +139,4 @@ private: #else pthread_cond_t event_; #endif -}; +}; \ No newline at end of file From 02307d822632f66a7d22352671f3c93afa06f486 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 14 Jan 2013 19:20:28 +1000 Subject: [PATCH 0220/1445] Fix Qt native file and remove redundancies. --- base/QtMain.cpp | 14 ++++++++++++++ base/QtMain.h | 6 ++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 69137ead14..1f79499e48 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -13,6 +13,9 @@ #ifdef __SYMBIAN32__ #include #endif +#ifdef Q_WS_X11 +#include "mainwindow.h" +#endif #include "QtMain.h" void LaunchBrowser(const char *url) @@ -52,6 +55,9 @@ float CalculateDPIScale() int main(int argc, char *argv[]) { +#ifdef Q_WS_X11 + QApplication::setAttribute(Qt::AA_X11InitThreads, true); +#endif QApplication a(argc, argv); // Lock orientation to landscape on Symbian #ifdef __SYMBIAN32__ @@ -75,16 +81,24 @@ int main(int argc, char *argv[]) NativeInit(argc, (const char **)argv, "E:/PPSSPP/", "E:", "BADCOFFEE"); #elif defined(BLACKBERRY) NativeInit(argc, (const char **)argv, "data/", "/tmp", "BADCOFFEE"); +#elif defined(Q_WS_X11) + // Temporary until ppsspp is fixed #else NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #endif +#ifdef Q_WS_X11 + MainWindow mainWindow; + mainWindow.show(); + mainWindow.Create(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); +#else MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); #ifdef USING_GLES2 w.showFullScreen(); #else w.show(); +#endif #endif MainAudio *audio = new MainAudio(); diff --git a/base/QtMain.h b/base/QtMain.h index 4c47054504..0cf76cefa1 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -88,7 +88,7 @@ protected: break; } } - break; + break; case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: input_state.pointer_down[0] = (e->type() == QEvent::MouseButtonPress); @@ -161,11 +161,13 @@ public: output = new QAudioOutput(fmt); output->setNotifyInterval(1000*AUDIO_SAMPLES / AUDIO_FREQ); output->setBufferSize(mixlen); - this->connect(output, SIGNAL(notify()), this, SLOT(writeData())); + connect(output, SIGNAL(notify()), this, SLOT(writeData())); feed = output->start(); } ~MainAudio() { + feed->close(); delete feed; + output->stop(); delete output; free(mixbuf); } From 0578607c84f7893cbee215aa259d444414e8d0b8 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 14 Jan 2013 21:32:39 +1000 Subject: [PATCH 0221/1445] Pandora buildfix and joystick support. --- base/PCMain.cpp | 48 ++++++++++++++++++++++++++++++----------- gfx_es2/draw_buffer.cpp | 3 +++ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index d7afeec551..fdc88e2436 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -39,16 +39,18 @@ #include #include #include "SDL_syswm.h" +SDL_Joystick *ljoy = NULL; +SDL_Joystick *rjoy = NULL; EGLDisplay g_eglDisplay = NULL; EGLContext g_eglContext = NULL; EGLSurface g_eglSurface = NULL; Display* g_Display = NULL; -NativeWindowType g_Window = NULL; +NativeWindowType g_Window = (NativeWindowType)NULL; -int8_t CheckEGLErrors(const string& file, uint16_t line) { +int8_t CheckEGLErrors(const std::string& file, uint16_t line) { EGLenum error; - string errortext; + std::string errortext; error = eglGetError(); switch (error) @@ -78,19 +80,18 @@ int8_t CheckEGLErrors(const string& file, uint16_t line) { return 1; \ } -void EGL_Open() { +int8_t EGL_Open() { if ((g_Display = XOpenDisplay(NULL)) == NULL) EGL_ERROR("Unable to get display!", false); - if ((g_eglDisplay = eglGetDisplay((NativeDisplayType)g_Display)) == EGL_NO_DISPLAY) EGL_ERROR("Unable to create EGL display.", true); - if (eglInitialize(g_eglDisplay, NULL, NULL) != EGL_TRUE) EGL_ERROR("Unable to initialize EGL display.", true); + return 0; } int8_t EGL_Init() { - EGLConfig g_eglConfig = NULL; + EGLConfig g_eglConfig[1] = {NULL}; EGLint g_numConfigs = 0; EGLint attrib_list[]= { EGL_RED_SIZE, 5, @@ -105,10 +106,10 @@ int8_t EGL_Init() { const EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - EGLBoolean result = eglChooseConfig(g_eglDisplay, attrib_list, g_eglConfig, 1, &g_numConfigs); - if (result != EGL_TRUE || g_numConfigs == 0) EGL_ERROR("Unable to query for available configs."); + EGLBoolean result = eglChooseConfig(g_eglDisplay, attrib_list, g_eglConfig[0], 1, &g_numConfigs); + if (result != EGL_TRUE || g_numConfigs == 0) EGL_ERROR("Unable to query for available configs.", true); - g_eglContext = eglCreateContext(g_eglDisplay, g_eglConfig, NULL, attributes); + g_eglContext = eglCreateContext(g_eglDisplay, g_eglConfig[0], NULL, attributes); if (g_eglContext == EGL_NO_CONTEXT) EGL_ERROR("Unable to create GLES context!", true); // Get the SDL window handle @@ -248,7 +249,17 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { } #ifdef PANDORA - // TODO: Use console joystick instead + if ((ljoy)||(rjoy)) { + SDL_JoystickUpdate(); + if (ljoy) { + input->pad_lstick_x = SDL_JoystickGetAxis(ljoy, 0) / 32768.0f; + input->pad_lstick_y = SDL_JoystickGetAxis(ljoy, 1) / 32768.0f; + } + if (rjoy) { + input->pad_rstick_x = SDL_JoystickGetAxis(rjoy, 0) / 32768.0f; + input->pad_rstick_y = SDL_JoystickGetAxis(rjoy, 1) / 32768.0f; + } + } #else if (keys[SDLK_i]) input->pad_lstick_y=1; @@ -345,7 +356,8 @@ int main(int argc, char *argv[]) { return 1; } #ifdef PANDORA - EGL_Open(); + if (EGL_Open()) + return 1; #endif SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); @@ -442,6 +454,18 @@ int main(int argc, char *argv[]) { // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); +#ifdef PANDORA + // Joysticks init, we the nubs if setup as Joystick + int numjoys = SDL_NumJoysticks(); + if (numjoys>0) + for (int i=0; i #include +#ifdef PANDORA +#include +#endif #include "base/display.h" #include "base/logging.h" From f5e775a9a10e38d5ac98261c132875492dfd91c3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 14 Jan 2013 19:25:05 +0100 Subject: [PATCH 0222/1445] Always specify all buffers for clearing. Missing one hurts, one extra doesn't. --- android/app-android.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 627359fce1..d65714d63f 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -252,7 +252,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN ELOG("Ended up in nativeRender even though app has quit.%s", ""); // Shouldn't really get here. glClearColor(1.0, 0.0, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } if (!frameCommand.empty()) { From ef75aee0a24f72f7e8ba5ce1aefb354309c48626 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 15 Jan 2013 20:45:26 +1000 Subject: [PATCH 0223/1445] Fix Qt audio for all platforms. --- base/QtMain.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index 0cf76cefa1..21c8fb45bb 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -159,10 +159,9 @@ public: mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; mixbuf = (char*)malloc(mixlen); output = new QAudioOutput(fmt); - output->setNotifyInterval(1000*AUDIO_SAMPLES / AUDIO_FREQ); output->setBufferSize(mixlen); - connect(output, SIGNAL(notify()), this, SLOT(writeData())); feed = output->start(); + startTimer(1000*AUDIO_SAMPLES / AUDIO_FREQ); } ~MainAudio() { feed->close(); @@ -172,8 +171,8 @@ public: free(mixbuf); } -private slots: - void writeData() { +protected: + void timerEvent(QTimerEvent *) { memset(mixbuf, 0, mixlen); NativeMix((short *)mixbuf, mixlen / 4); feed->write(mixbuf, mixlen); From 00acbd2f748b188a60512b455f6ec0c17ca47a99 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 16 Jan 2013 02:19:22 +1000 Subject: [PATCH 0224/1445] Revert some temporary changes for Stage 1 refactor of Qt. --- base/NativeApp.h | 1 + base/QtMain.cpp | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/base/NativeApp.h b/base/NativeApp.h index 677568c075..7a4195f8dd 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -62,6 +62,7 @@ void NativeRender(); // This function may be called from a totally separate thread from // the rest of the game, so be careful with synchronization. void NativeMix(short *audio, int num_samples); +void NativeSetMixer(void* mixer); // Called when it's time to shutdown. After this has been called, // no more calls to any other function will be made from the framework diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 1f79499e48..6a23895f21 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -81,8 +81,6 @@ int main(int argc, char *argv[]) NativeInit(argc, (const char **)argv, "E:/PPSSPP/", "E:", "BADCOFFEE"); #elif defined(BLACKBERRY) NativeInit(argc, (const char **)argv, "data/", "/tmp", "BADCOFFEE"); -#elif defined(Q_WS_X11) - // Temporary until ppsspp is fixed #else NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #endif @@ -90,7 +88,6 @@ int main(int argc, char *argv[]) #ifdef Q_WS_X11 MainWindow mainWindow; mainWindow.show(); - mainWindow.Create(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #else MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); @@ -109,4 +106,3 @@ int main(int argc, char *argv[]) net::Shutdown(); return ret; } - From b5037341aaca775e806be4b6a7bf109a47e0c655 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 19 Jan 2013 12:01:28 +0100 Subject: [PATCH 0225/1445] Add cityhash, a good and fast hash. --- Android.mk | 9 +- ext/cityhash/COPYING | 19 ++ ext/cityhash/README | 200 +++++++++++++ ext/cityhash/city.cpp | 620 +++++++++++++++++++++++++++++++++++++++++ ext/cityhash/city.h | 108 +++++++ ext/cityhash/citycrc.h | 43 +++ native.vcxproj | 3 + native.vcxproj.filters | 9 + 8 files changed, 1007 insertions(+), 4 deletions(-) create mode 100644 ext/cityhash/COPYING create mode 100644 ext/cityhash/README create mode 100644 ext/cityhash/city.cpp create mode 100644 ext/cityhash/city.h create mode 100644 ext/cityhash/citycrc.h diff --git a/Android.mk b/Android.mk index ca569fa5e7..2d6d695c00 100644 --- a/Android.mk +++ b/Android.mk @@ -16,6 +16,7 @@ LOCAL_SRC_FILES :=\ base/colorutil.cpp \ base/error_context.cpp \ base/stringutil.cpp \ + ext/cityhash/city.cpp \ ext/sha1/sha1.cpp \ ext/stb_image/stb_image.c \ ext/stb_vorbis/stb_vorbis.c.arm \ @@ -50,10 +51,10 @@ LOCAL_SRC_FILES :=\ gfx/texture_gen.cpp \ image/zim_load.cpp \ image/png_load.cpp \ - ui/ui.cpp \ - ui/ui_context.cpp \ - ui/screen.cpp \ - ui/virtual_input.cpp \ + ui/ui.cpp \ + ui/ui_context.cpp \ + ui/screen.cpp \ + ui/virtual_input.cpp \ util/random/perlin.cpp \ util/text/utf8.cpp diff --git a/ext/cityhash/COPYING b/ext/cityhash/COPYING new file mode 100644 index 0000000000..bf15194dd5 --- /dev/null +++ b/ext/cityhash/COPYING @@ -0,0 +1,19 @@ +// Copyright (c) 2011 Google, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. diff --git a/ext/cityhash/README b/ext/cityhash/README new file mode 100644 index 0000000000..9ce14ea3b7 --- /dev/null +++ b/ext/cityhash/README @@ -0,0 +1,200 @@ +NOTE: This is a cut down version of Google CityHash for easy building. + + + +CityHash, a family of hash functions for strings. + + +Introduction +============ + +CityHash provides hash functions for strings. The functions mix the +input bits thoroughly but are not suitable for cryptography. See +"Hash Quality," below, for details on how CityHash was tested and so on. + +We provide reference implementations in C++, with a friendly MIT license. + +CityHash32() returns a 32-bit hash. + +CityHash64() and similar return a 64-bit hash. + +CityHash128() and similar return a 128-bit hash and are tuned for +strings of at least a few hundred bytes. Depending on your compiler +and hardware, it's likely faster than CityHash64() on sufficiently long +strings. It's slower than necessary on shorter strings, but we expect +that case to be relatively unimportant. + +CityHashCrc128() and similar are variants of CityHash128() that depend +on _mm_crc32_u64(), an intrinsic that compiles to a CRC32 instruction +on some CPUs. However, none of the functions we provide are CRCs. + +CityHashCrc256() is a variant of CityHashCrc128() that also depends +on _mm_crc32_u64(). It returns a 256-bit hash. + +All members of the CityHash family were designed with heavy reliance +on previous work by Austin Appleby, Bob Jenkins, and others. +For example, CityHash32 has many similarities with Murmur3a. + +Performance on long strings: 64-bit CPUs +======================================== + +We are most excited by the performance of CityHash64() and its variants on +short strings, but long strings are interesting as well. + +CityHash is intended to be fast, under the constraint that it hash very +well. For CPUs with the CRC32 instruction, CRC is speedy, but CRC wasn't +designed as a hash function and shouldn't be used as one. CityHashCrc128() +is not a CRC, but it uses the CRC32 machinery. + +On a single core of a 2.67GHz Intel Xeon X5550, CityHashCrc256 peaks at about +5 to 5.5 bytes/cycle. The other CityHashCrc functions are wrappers around +CityHashCrc256 and should have similar performance on long strings. +(CityHashCrc256 in v1.0.3 was even faster, but we decided it wasn't as thorough +as it should be.) CityHash128 peaks at about 4.3 bytes/cycle. The fastest +Murmur variant on that hardware, Murmur3F, peaks at about 2.4 bytes/cycle. +We expect the peak speed of CityHash128 to dominate CityHash64, which is +aimed more toward short strings or use in hash tables. + +For long strings, a new function by Bob Jenkins, SpookyHash, is just +slightly slower than CityHash128 on Intel x86-64 CPUs, but noticeably +faster on AMD x86-64 CPUs. For hashing long strings on AMD CPUs +and/or CPUs without the CRC instruction, SpookyHash may be just as +good or better than any of the CityHash variants. + +Performance on short strings: 64-bit CPUs +========================================= + +For short strings, e.g., most hash table keys, CityHash64 is faster than +CityHash128, and probably faster than all the aforementioned functions, +depending on the mix of string lengths. Here are a few results from that +same hardware, where we (unrealistically) tested a single string length over +and over again: + +Hash Results +------------------------------------------------------------------------------ +CityHash64 v1.0.3 7ns for 1 byte, or 6ns for 8 bytes, or 9ns for 64 bytes +Murmur2 (64-bit) 6ns for 1 byte, or 6ns for 8 bytes, or 15ns for 64 bytes +Murmur3F 14ns for 1 byte, or 15ns for 8 bytes, or 23ns for 64 bytes + +We don't have CityHash64 benchmarks results for v1.1, but we expect the +numbers to be similar. + +Performance: 32-bit CPUs +======================== + +CityHash32 is the newest variant of CityHash. It is intended for +32-bit hardware in general but has been mostly tested on x86. Our benchmarks +suggest that Murmur3 is the nearest competitor to CityHash32 on x86. +We don't know of anything faster that has comparable quality. The speed rankings +in our testing: CityHash32 > Murmur3f > Murmur3a (for long strings), and +CityHash32 > Murmur3a > Murmur3f (for short strings). + +Installation +============ + +We provide reference implementations of several CityHash functions, written +in C++. The build system is based on autoconf. It defaults the C++ +compiler flags to "-g -O2", which is probably slower than -O3 if you are +using gcc. YMMV. + +On systems with gcc, we generally recommend: + +./configure +make all check CXXFLAGS="-g -O3" +sudo make install + +Or, if your system has the CRC32 instruction, and you want to build everything: + +./configure --enable-sse4.2 +make all check CXXFLAGS="-g -O3 -msse4.2" +sudo make install + +Note that our build system doesn't try to determine the appropriate compiler +flag for enabling SSE4.2. For gcc it is "-msse4.2". The --enable-sse4.2 +flag to the configure script controls whether citycrc.h is installed when +you "make install." In general, picking the right compiler flags can be +tricky, and may depend on your compiler, your hardware, and even how you +plan to use the library. + +For generic information about how to configure this software, please try: + +./configure --help + +Failing that, please work from city.cc and city*.h, as they contain all the +necessary code. + + +Usage +===== + +The above installation instructions will produce a single library. It will +contain CityHash32(), CityHash64(), and CityHash128(), and their variants, +and possibly CityHashCrc128(), CityHashCrc128WithSeed(), and +CityHashCrc256(). The functions with Crc in the name are declared in +citycrc.h; the rest are declared in city.h. + + +Limitations +=========== + +1) CityHash32 is intended for little-endian 32-bit code, and everything else in +the current version of CityHash is intended for little-endian 64-bit CPUs. + +All functions that don't use the CRC32 instruction should work in +little-endian 32-bit or 64-bit code. CityHash should work on big-endian CPUs +as well, but we haven't tested that very thoroughly yet. + +2) CityHash is fairly complex. As a result of its complexity, it may not +perform as expected on some compilers. For example, preliminary reports +suggest that some Microsoft compilers compile CityHash to assembly that's +10-20% slower than it could be. + + +Hash Quality +============ + +We like to test hash functions with SMHasher, among other things. +SMHasher isn't perfect, but it seems to find almost any significant flaw. +SMHasher is available at http://code.google.com/p/smhasher/ + +SMHasher is designed to pass a 32-bit seed to the hash functions it tests. +No CityHash function is designed to work that way, so we adapt as follows: +For our functions that accept a seed, we use the given seed directly (padded +with zeroes); for our functions that don't accept a seed, we hash the +concatenation of the given seed and the input string. + +The CityHash functions have the following flaws according to SMHasher: + +(1) CityHash64: none + +(2) CityHash64WithSeed: none + +(3) CityHash64WithSeeds: did not test + +(4) CityHash128: none + +(5) CityHash128WithSeed: none + +(6) CityHashCrc128: none + +(7) CityHashCrc128WithSeed: none + +(8) CityHashCrc256: none + +(9) CityHash32: none + +Some minor flaws in 32-bit and 64-bit functions are harmless, as we +expect the primary use of these functions will be in hash tables. We +may have gone slightly overboard in trying to please SMHasher and other +similar tests, but we don't want anyone to choose a different hash function +because of some minor issue reported by a quality test. + + +For more information +==================== + +http://code.google.com/p/cityhash/ + +cityhash-discuss@googlegroups.com + +Please feel free to send us comments, questions, bug reports, or patches. diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp new file mode 100644 index 0000000000..d86d4e6924 --- /dev/null +++ b/ext/cityhash/city.cpp @@ -0,0 +1,620 @@ +// Copyright (c) 2011 Google, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// CityHash, by Geoff Pike and Jyrki Alakuijala +// +// This file provides CityHash64() and related functions. +// +// It's probably possible to create even faster hash functions by +// writing a program that systematically explores some of the space of +// possible hash functions, by using SIMD instructions, or by +// compromising on hash quality. + +#include "city.h" + +#include +#include // for memcpy and memset + +typedef unsigned long long uint64; +typedef unsigned int uint32; + +using namespace std; + +static uint64 UNALIGNED_LOAD64(const char *p) { + uint64 result; + memcpy(&result, p, sizeof(result)); + return result; +} + +static uint32 UNALIGNED_LOAD32(const char *p) { + uint32 result; + memcpy(&result, p, sizeof(result)); + return result; +} + +#ifdef _MSC_VER + +#include +#define bswap_32(x) _byteswap_ulong(x) +#define bswap_64(x) _byteswap_uint64(x) + +#elif defined(__APPLE__) + +// Mac OS X / Darwin features +#include +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) + +#else + +#include + +#endif + +#ifdef WORDS_BIGENDIAN +#define uint32_in_expected_order(x) (bswap_32(x)) +#define uint64_in_expected_order(x) (bswap_64(x)) +#else +#define uint32_in_expected_order(x) (x) +#define uint64_in_expected_order(x) (x) +#endif + +#if !defined(LIKELY) +#if HAVE_BUILTIN_EXPECT +#define LIKELY(x) (__builtin_expect(!!(x), 1)) +#else +#define LIKELY(x) (x) +#endif +#endif + +static uint64 Fetch64(const char *p) { + return uint64_in_expected_order(UNALIGNED_LOAD64(p)); +} + +static uint32 Fetch32(const char *p) { + return uint32_in_expected_order(UNALIGNED_LOAD32(p)); +} + +// Some primes between 2^63 and 2^64 for various uses. +static const uint64 k0 = 0xc3a5c85c97cb3127ULL; +static const uint64 k1 = 0xb492b66fbe98f273ULL; +static const uint64 k2 = 0x9ae16a3b2f90404fULL; + +// Magic numbers for 32-bit hashing. Copied from Murmur3. +static const uint32_t c1 = 0xcc9e2d51; +static const uint32_t c2 = 0x1b873593; + +// A 32-bit to 32-bit integer hash copied from Murmur3. +static uint32 fmix(uint32 h) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + return h; +} + +static uint32 Rotate32(uint32 val, int shift) { + // Avoid shifting by 32: doing so yields an undefined result. + return shift == 0 ? val : ((val >> shift) | (val << (32 - shift))); +} + +#undef PERMUTE3 +#define PERMUTE3(a, b, c) do { std::swap(a, b); std::swap(a, c); } while (0) + +static uint32 Mur(uint32 a, uint32 h) { + // Helper from Murmur3 for combining two 32-bit values. + a *= c1; + a = Rotate32(a, 17); + a *= c2; + h ^= a; + h = Rotate32(h, 19); + return h * 5 + 0xe6546b64; +} + +static uint32 Hash32Len13to24(const char *s, size_t len) { + uint32 a = Fetch32(s - 4 + (len >> 1)); + uint32 b = Fetch32(s + 4); + uint32 c = Fetch32(s + len - 8); + uint32 d = Fetch32(s + (len >> 1)); + uint32 e = Fetch32(s); + uint32 f = Fetch32(s + len - 4); + uint32 h = len; + + return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h))))))); +} + +static uint32 Hash32Len0to4(const char *s, size_t len) { + uint32 b = 0; + uint32 c = 9; + for (size_t i = 0; i < len; i++) { + b = b * c1 + s[i]; + c ^= b; + } + return fmix(Mur(b, Mur(len, c))); +} + +static uint32 Hash32Len5to12(const char *s, size_t len) { + uint32 a = len, b = len * 5, c = 9, d = b; + a += Fetch32(s); + b += Fetch32(s + len - 4); + c += Fetch32(s + ((len >> 1) & 4)); + return fmix(Mur(c, Mur(b, Mur(a, d)))); +} + +uint32 CityHash32(const char *s, size_t len) { + if (len <= 24) { + return len <= 12 ? + (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len)) : + Hash32Len13to24(s, len); + } + + // len > 24 + uint32 h = len, g = c1 * len, f = g; + uint32 a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2; + uint32 a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2; + uint32 a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2; + uint32 a3 = Rotate32(Fetch32(s + len - 12) * c1, 17) * c2; + uint32 a4 = Rotate32(Fetch32(s + len - 20) * c1, 17) * c2; + h ^= a0; + h = Rotate32(h, 19); + h = h * 5 + 0xe6546b64; + h ^= a2; + h = Rotate32(h, 19); + h = h * 5 + 0xe6546b64; + g ^= a1; + g = Rotate32(g, 19); + g = g * 5 + 0xe6546b64; + g ^= a3; + g = Rotate32(g, 19); + g = g * 5 + 0xe6546b64; + f += a4; + f = Rotate32(f, 19); + f = f * 5 + 0xe6546b64; + size_t iters = (len - 1) / 20; + do { + uint32 a0 = Rotate32(Fetch32(s) * c1, 17) * c2; + uint32 a1 = Fetch32(s + 4); + uint32 a2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2; + uint32 a3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2; + uint32 a4 = Fetch32(s + 16); + h ^= a0; + h = Rotate32(h, 18); + h = h * 5 + 0xe6546b64; + f += a1; + f = Rotate32(f, 19); + f = f * c1; + g += a2; + g = Rotate32(g, 18); + g = g * 5 + 0xe6546b64; + h ^= a3 + a1; + h = Rotate32(h, 19); + h = h * 5 + 0xe6546b64; + g ^= a4; + g = bswap_32(g) * 5; + h += a4 * 5; + h = bswap_32(h); + f += a0; + PERMUTE3(f, h, g); + s += 20; + } while (--iters != 0); + g = Rotate32(g, 11) * c1; + g = Rotate32(g, 17) * c1; + f = Rotate32(f, 11) * c1; + f = Rotate32(f, 17) * c1; + h = Rotate32(h + g, 19); + h = h * 5 + 0xe6546b64; + h = Rotate32(h, 17) * c1; + h = Rotate32(h + f, 19); + h = h * 5 + 0xe6546b64; + h = Rotate32(h, 17) * c1; + return h; +} + +// Bitwise right rotate. Normally this will compile to a single +// instruction, especially if the shift is a manifest constant. +static uint64 Rotate(uint64 val, int shift) { + // Avoid shifting by 64: doing so yields an undefined result. + return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); +} + +static uint64 ShiftMix(uint64 val) { + return val ^ (val >> 47); +} + +static uint64 HashLen16(uint64 u, uint64 v) { + return Hash128to64(uint128(u, v)); +} + +static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) { + // Murmur-inspired hashing. + uint64 a = (u ^ v) * mul; + a ^= (a >> 47); + uint64 b = (v ^ a) * mul; + b ^= (b >> 47); + b *= mul; + return b; +} + +static uint64 HashLen0to16(const char *s, size_t len) { + if (len >= 8) { + uint64 mul = k2 + len * 2; + uint64 a = Fetch64(s) + k2; + uint64 b = Fetch64(s + len - 8); + uint64 c = Rotate(b, 37) * mul + a; + uint64 d = (Rotate(a, 25) + b) * mul; + return HashLen16(c, d, mul); + } + if (len >= 4) { + uint64 mul = k2 + len * 2; + uint64 a = Fetch32(s); + return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul); + } + if (len > 0) { + uint8 a = s[0]; + uint8 b = s[len >> 1]; + uint8 c = s[len - 1]; + uint32 y = static_cast(a) + (static_cast(b) << 8); + uint32 z = len + (static_cast(c) << 2); + return ShiftMix(y * k2 ^ z * k0) * k2; + } + return k2; +} + +// This probably works well for 16-byte strings as well, but it may be overkill +// in that case. +static uint64 HashLen17to32(const char *s, size_t len) { + uint64 mul = k2 + len * 2; + uint64 a = Fetch64(s) * k1; + uint64 b = Fetch64(s + 8); + uint64 c = Fetch64(s + len - 8) * mul; + uint64 d = Fetch64(s + len - 16) * k2; + return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, + a + Rotate(b + k2, 18) + c, mul); +} + +// Return a 16-byte hash for 48 bytes. Quick and dirty. +// Callers do best to use "random-looking" values for a and b. +static pair WeakHashLen32WithSeeds( + uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) { + a += w; + b = Rotate(b + a + z, 21); + uint64 c = a; + a += x; + a += y; + b += Rotate(a, 44); + return make_pair(a + z, b + c); +} + +// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. +static pair WeakHashLen32WithSeeds( + const char* s, uint64 a, uint64 b) { + return WeakHashLen32WithSeeds(Fetch64(s), + Fetch64(s + 8), + Fetch64(s + 16), + Fetch64(s + 24), + a, + b); +} + +// Return an 8-byte hash for 33 to 64 bytes. +static uint64 HashLen33to64(const char *s, size_t len) { + uint64 mul = k2 + len * 2; + uint64 a = Fetch64(s) * k2; + uint64 b = Fetch64(s + 8); + uint64 c = Fetch64(s + len - 24); + uint64 d = Fetch64(s + len - 32); + uint64 e = Fetch64(s + 16) * k2; + uint64 f = Fetch64(s + 24) * 9; + uint64 g = Fetch64(s + len - 8); + uint64 h = Fetch64(s + len - 16) * mul; + uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9; + uint64 v = ((a + g) ^ d) + f + 1; + uint64 w = bswap_64((u + v) * mul) + h; + uint64 x = Rotate(e + f, 42) + c; + uint64 y = (bswap_64((v + w) * mul) + g) * mul; + uint64 z = e + f + c; + a = bswap_64((x + z) * mul + y) + b; + b = ShiftMix((z + a) * mul + d + h) * mul; + return b + x; +} + +uint64 CityHash64(const char *s, size_t len) { + if (len <= 32) { + if (len <= 16) { + return HashLen0to16(s, len); + } else { + return HashLen17to32(s, len); + } + } else if (len <= 64) { + return HashLen33to64(s, len); + } + + // For strings over 64 bytes we hash the end first, and then as we + // loop we keep 56 bytes of state: v, w, x, y, and z. + uint64 x = Fetch64(s + len - 40); + uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56); + uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); + pair v = WeakHashLen32WithSeeds(s + len - 64, len, z); + pair w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x); + x = x * k1 + Fetch64(s); + + // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. + len = (len - 1) & ~static_cast(63); + do { + x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; + y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; + x ^= w.second; + y += v.first + Fetch64(s + 40); + z = Rotate(z + w.first, 33) * k1; + v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); + w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); + std::swap(z, x); + s += 64; + len -= 64; + } while (len != 0); + return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, + HashLen16(v.second, w.second) + x); +} + +uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) { + return CityHash64WithSeeds(s, len, k2, seed); +} + +uint64 CityHash64WithSeeds(const char *s, size_t len, + uint64 seed0, uint64 seed1) { + return HashLen16(CityHash64(s, len) - seed0, seed1); +} + +// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings +// of any length representable in signed long. Based on City and Murmur. +static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { + uint64 a = Uint128Low64(seed); + uint64 b = Uint128High64(seed); + uint64 c = 0; + uint64 d = 0; + signed long l = len - 16; + if (l <= 0) { // len <= 16 + a = ShiftMix(a * k1) * k1; + c = b * k1 + HashLen0to16(s, len); + d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c)); + } else { // len > 16 + c = HashLen16(Fetch64(s + len - 8) + k1, a); + d = HashLen16(b + len, c + Fetch64(s + len - 16)); + a += d; + do { + a ^= ShiftMix(Fetch64(s) * k1) * k1; + a *= k1; + b ^= a; + c ^= ShiftMix(Fetch64(s + 8) * k1) * k1; + c *= k1; + d ^= c; + s += 16; + l -= 16; + } while (l > 0); + } + a = HashLen16(a, c); + b = HashLen16(d, b); + return uint128(a ^ b, HashLen16(b, a)); +} + +uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { + if (len < 128) { + return CityMurmur(s, len, seed); + } + + // We expect len >= 128 to be the common case. Keep 56 bytes of state: + // v, w, x, y, and z. + pair v, w; + uint64 x = Uint128Low64(seed); + uint64 y = Uint128High64(seed); + uint64 z = len * k1; + v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s); + v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8); + w.first = Rotate(y + z, 35) * k1 + x; + w.second = Rotate(x + Fetch64(s + 88), 53) * k1; + + // This is the same inner loop as CityHash64(), manually unrolled. + do { + x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; + y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; + x ^= w.second; + y += v.first + Fetch64(s + 40); + z = Rotate(z + w.first, 33) * k1; + v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); + w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); + std::swap(z, x); + s += 64; + x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; + y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; + x ^= w.second; + y += v.first + Fetch64(s + 40); + z = Rotate(z + w.first, 33) * k1; + v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); + w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); + std::swap(z, x); + s += 64; + len -= 128; + } while (LIKELY(len >= 128)); + x += Rotate(v.first + z, 49) * k0; + y = y * k0 + Rotate(w.second, 37); + z = z * k0 + Rotate(w.first, 27); + w.first *= 9; + v.first *= k0; + // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. + for (size_t tail_done = 0; tail_done < len; ) { + tail_done += 32; + y = Rotate(x + y, 42) * k0 + v.second; + w.first += Fetch64(s + len - tail_done + 16); + x = x * k0 + w.first; + z += w.second + Fetch64(s + len - tail_done); + w.second += v.first; + v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second); + v.first *= k0; + } + // At this point our 56 bytes of state should contain more than + // enough information for a strong 128-bit hash. We use two + // different 56-byte-to-8-byte hashes to get a 16-byte final result. + x = HashLen16(x, v.first); + y = HashLen16(y + z, w.first); + return uint128(HashLen16(x + v.second, w.second) + y, + HashLen16(x + w.second, y + v.second)); +} + +uint128 CityHash128(const char *s, size_t len) { + return len >= 16 ? + CityHash128WithSeed(s + 16, len - 16, + uint128(Fetch64(s), Fetch64(s + 8) + k0)) : + CityHash128WithSeed(s, len, uint128(k0, k1)); +} + +#ifdef __SSE4_2__ +#include +#include + +// Requires len >= 240. +static void CityHashCrc256Long(const char *s, size_t len, + uint32 seed, uint64 *result) { + uint64 a = Fetch64(s + 56) + k0; + uint64 b = Fetch64(s + 96) + k0; + uint64 c = result[0] = HashLen16(b, len); + uint64 d = result[1] = Fetch64(s + 120) * k0 + len; + uint64 e = Fetch64(s + 184) + seed; + uint64 f = 0; + uint64 g = 0; + uint64 h = c + d; + uint64 x = seed; + uint64 y = 0; + uint64 z = 0; + + // 240 bytes of input per iter. + size_t iters = len / 240; + len -= iters * 240; + do { +#undef CHUNK +#define CHUNK(r) \ + PERMUTE3(x, z, y); \ + b += Fetch64(s); \ + c += Fetch64(s + 8); \ + d += Fetch64(s + 16); \ + e += Fetch64(s + 24); \ + f += Fetch64(s + 32); \ + a += b; \ + h += f; \ + b += c; \ + f += d; \ + g += e; \ + e += z; \ + g += x; \ + z = _mm_crc32_u64(z, b + g); \ + y = _mm_crc32_u64(y, e + h); \ + x = _mm_crc32_u64(x, f + a); \ + e = Rotate(e, r); \ + c += e; \ + s += 40 + + CHUNK(0); PERMUTE3(a, h, c); + CHUNK(33); PERMUTE3(a, h, f); + CHUNK(0); PERMUTE3(b, h, f); + CHUNK(42); PERMUTE3(b, h, d); + CHUNK(0); PERMUTE3(b, h, e); + CHUNK(33); PERMUTE3(a, h, e); + } while (--iters > 0); + + while (len >= 40) { + CHUNK(29); + e ^= Rotate(a, 20); + h += Rotate(b, 30); + g ^= Rotate(c, 40); + f += Rotate(d, 34); + PERMUTE3(c, h, g); + len -= 40; + } + if (len > 0) { + s = s + len - 40; + CHUNK(33); + e ^= Rotate(a, 43); + h += Rotate(b, 42); + g ^= Rotate(c, 41); + f += Rotate(d, 40); + } + result[0] ^= h; + result[1] ^= g; + g += h; + a = HashLen16(a, g + z); + x += y << 32; + b += x; + c = HashLen16(c, z) + h; + d = HashLen16(d, e + result[0]); + g += e; + h += HashLen16(x, f); + e = HashLen16(a, d) + g; + z = HashLen16(b, c) + a; + y = HashLen16(g, h) + c; + result[0] = e + z + y + x; + a = ShiftMix((a + y) * k0) * k0 + b; + result[1] += a + result[0]; + a = ShiftMix(a * k0) * k0 + c; + result[2] = a + result[1]; + a = ShiftMix((a + e) * k0) * k0; + result[3] = a + result[2]; +} + +// Requires len < 240. +static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) { + char buf[240]; + memcpy(buf, s, len); + memset(buf + len, 0, 240 - len); + CityHashCrc256Long(buf, 240, ~static_cast(len), result); +} + +void CityHashCrc256(const char *s, size_t len, uint64 *result) { + if (LIKELY(len >= 240)) { + CityHashCrc256Long(s, len, 0, result); + } else { + CityHashCrc256Short(s, len, result); + } +} + +uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) { + if (len <= 900) { + return CityHash128WithSeed(s, len, seed); + } else { + uint64 result[4]; + CityHashCrc256(s, len, result); + uint64 u = Uint128High64(seed) + result[0]; + uint64 v = Uint128Low64(seed) + result[1]; + return uint128(HashLen16(u, v + result[2]), + HashLen16(Rotate(v, 32), u * k0 + result[3])); + } +} + +uint128 CityHashCrc128(const char *s, size_t len) { + if (len <= 900) { + return CityHash128(s, len); + } else { + uint64 result[4]; + CityHashCrc256(s, len, result); + return uint128(result[2], result[3]); + } +} + +#endif diff --git a/ext/cityhash/city.h b/ext/cityhash/city.h new file mode 100644 index 0000000000..ec52f2b5b2 --- /dev/null +++ b/ext/cityhash/city.h @@ -0,0 +1,108 @@ +// Copyright (c) 2011 Google, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// CityHash, by Geoff Pike and Jyrki Alakuijala +// +// http://code.google.com/p/cityhash/ +// +// This file provides a few functions for hashing strings. All of them are +// high-quality functions in the sense that they pass standard tests such +// as Austin Appleby's SMHasher. They are also fast. +// +// For 64-bit x86 code, on short strings, we don't know of anything faster than +// CityHash64 that is of comparable quality. We believe our nearest competitor +// is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash +// tables and most other hashing (excluding cryptography). +// +// For 64-bit x86 code, on long strings, the picture is more complicated. +// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc., +// CityHashCrc128 appears to be faster than all competitors of comparable +// quality. CityHash128 is also good but not quite as fast. We believe our +// nearest competitor is Bob Jenkins' Spooky. We don't have great data for +// other 64-bit CPUs, but for long strings we know that Spooky is slightly +// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example. +// +// For 32-bit x86 code, we don't know of anything faster than CityHash32 that +// is of comparable quality. We believe our nearest competitor is Murmur3A. +// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.) +// +// Functions in the CityHash family are not suitable for cryptography. +// +// WARNING: This code has been only lightly tested on big-endian platforms! +// It is known to work well on little-endian platforms that have a small penalty +// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs. +// It should work on all 32-bit and 64-bit platforms that allow unaligned reads; +// bug reports are welcome. +// +// By the way, for some hash functions, given strings a and b, the hash +// of a+b is easily derived from the hashes of a and b. This property +// doesn't hold for any hash functions in this file. + +#ifndef CITY_HASH_H_ +#define CITY_HASH_H_ + +#include // for size_t. +#include +#include + +typedef uint8_t uint8; +typedef uint32_t uint32; +typedef uint64_t uint64; +typedef std::pair uint128; + +inline uint64 Uint128Low64(const uint128& x) { return x.first; } +inline uint64 Uint128High64(const uint128& x) { return x.second; } + +// Hash function for a byte array. +uint64 CityHash64(const char *buf, size_t len); + +// Hash function for a byte array. For convenience, a 64-bit seed is also +// hashed into the result. +uint64 CityHash64WithSeed(const char *buf, size_t len, uint64 seed); + +// Hash function for a byte array. For convenience, two seeds are also +// hashed into the result. +uint64 CityHash64WithSeeds(const char *buf, size_t len, + uint64 seed0, uint64 seed1); + +// Hash function for a byte array. +uint128 CityHash128(const char *s, size_t len); + +// Hash function for a byte array. For convenience, a 128-bit seed is also +// hashed into the result. +uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed); + +// Hash function for a byte array. Most useful in 32-bit binaries. +uint32 CityHash32(const char *buf, size_t len); + +// Hash 128 input bits down to 64 bits of output. +// This is intended to be a reasonably good hash function. +inline uint64 Hash128to64(const uint128& x) { + // Murmur-inspired hashing. + const uint64 kMul = 0x9ddfea08eb382d69ULL; + uint64 a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; + a ^= (a >> 47); + uint64 b = (Uint128High64(x) ^ a) * kMul; + b ^= (b >> 47); + b *= kMul; + return b; +} + +#endif // CITY_HASH_H_ diff --git a/ext/cityhash/citycrc.h b/ext/cityhash/citycrc.h new file mode 100644 index 0000000000..318e3917ca --- /dev/null +++ b/ext/cityhash/citycrc.h @@ -0,0 +1,43 @@ +// Copyright (c) 2011 Google, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// CityHash, by Geoff Pike and Jyrki Alakuijala +// +// This file declares the subset of the CityHash functions that require +// _mm_crc32_u64(). See the CityHash README for details. +// +// Functions in the CityHash family are not suitable for cryptography. + +#ifndef CITY_HASH_CRC_H_ +#define CITY_HASH_CRC_H_ + +#include + +// Hash function for a byte array. +uint128 CityHashCrc128(const char *s, size_t len); + +// Hash function for a byte array. For convenience, a 128-bit seed is also +// hashed into the result. +uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed); + +// Hash function for a byte array. Sets result[0] ... result[3]. +void CityHashCrc256(const char *s, size_t len, uint64 *result); + +#endif // CITY_HASH_CRC_H_ diff --git a/native.vcxproj b/native.vcxproj index df06267bb1..cb234d18e4 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -199,6 +199,8 @@ + + @@ -291,6 +293,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index d047cd88a6..0c27bfa6ad 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -236,6 +236,12 @@ util + + ext + + + ext + @@ -420,6 +426,9 @@ util + + ext + From c02c9e6bdd69ad35d45d1eb36e2f0f31f7d30a29 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Mon, 21 Jan 2013 01:22:00 +0100 Subject: [PATCH 0226/1445] Remove typedef redefined which break linux build --- ext/cityhash/city.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index d86d4e6924..8e2dec0ab3 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -32,9 +32,6 @@ #include #include // for memcpy and memset -typedef unsigned long long uint64; -typedef unsigned int uint32; - using namespace std; static uint64 UNALIGNED_LOAD64(const char *p) { From 0f7f38a5ff23769e4ed0c95d343c002d1b82aa1e Mon Sep 17 00:00:00 2001 From: Summeli Date: Tue, 22 Jan 2013 23:20:17 +0200 Subject: [PATCH 0227/1445] Added byteswap functions for Symbian & BlackBerry --- ext/cityhash/city.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 8e2dec0ab3..34d7edca6d 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -59,6 +59,11 @@ static uint32 UNALIGNED_LOAD32(const char *p) { #define bswap_32(x) OSSwapInt32(x) #define bswap_64(x) OSSwapInt64(x) +#elif defined(__SYMBIAN32__) || defined(BLACKBERRY) +//TODO: I'm not really sure if this is the fasters or the safest way to do this. However both platforms should have qendian which should map swap-functions +#include +#define bswap_32(x) qbswap((qint32)x) +#define bswap_64(x) qbswap((qint64)x) #else #include From d783975258366b57d79f2200c8b44795fce52210 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 23 Jan 2013 11:21:14 +1000 Subject: [PATCH 0228/1445] Fix cityhash for non-glibc systems where byteswap isn't defined. Define it manually instead. Also, fix harmattan building of Qt frontend. --- base/QtMain.cpp | 4 ++-- ext/cityhash/city.cpp | 30 +++++++++++++++++------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 6a23895f21..63b5748a08 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -13,7 +13,7 @@ #ifdef __SYMBIAN32__ #include #endif -#ifdef Q_WS_X11 +#if defined(Q_WS_X11) && !defined(USING_GLES2) #include "mainwindow.h" #endif #include "QtMain.h" @@ -85,7 +85,7 @@ int main(int argc, char *argv[]) NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #endif -#ifdef Q_WS_X11 +#if defined(Q_WS_X11) && !defined(USING_GLES2) MainWindow mainWindow; mainWindow.show(); #else diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 34d7edca6d..64a12a42f9 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -30,6 +30,7 @@ #include "city.h" #include +#include // To check for glibc #include // for memcpy and memset using namespace std; @@ -47,27 +48,30 @@ static uint32 UNALIGNED_LOAD32(const char *p) { } #ifdef _MSC_VER - -#include #define bswap_32(x) _byteswap_ulong(x) #define bswap_64(x) _byteswap_uint64(x) - +#elif defined(__GLIBC__) +#include #elif defined(__APPLE__) - // Mac OS X / Darwin features #include #define bswap_32(x) OSSwapInt32(x) #define bswap_64(x) OSSwapInt64(x) - -#elif defined(__SYMBIAN32__) || defined(BLACKBERRY) -//TODO: I'm not really sure if this is the fasters or the safest way to do this. However both platforms should have qendian which should map swap-functions -#include -#define bswap_32(x) qbswap((qint32)x) -#define bswap_64(x) qbswap((qint64)x) #else - -#include - +// Otherwise it doesn't exist (Symbian, Blackberry10) +#define UINT64_C(c) static_cast(c ## ULL) +#define bswap_32(x) (0 | ((x & 0x000000ff) << 24) \ + | ((x & 0x0000ff00) << 8) \ + | ((x & 0x00ff0000) >> 8) \ + | ((x & 0xff000000) >> 24)) +#define bswap_64(x) (0 | ((x & UINT64_C(0x00000000000000ff)) << 56) \ + | ((x & UINT64_C(0x000000000000ff00)) << 40) \ + | ((x & UINT64_C(0x0000000000ff0000)) << 24) \ + | ((x & UINT64_C(0x00000000ff000000)) << 8) \ + | ((x & UINT64_C(0x000000ff00000000)) >> 8) \ + | ((x & UINT64_C(0x0000ff0000000000)) >> 24) \ + | ((x & UINT64_C(0x00ff000000000000)) >> 40) \ + | ((x & UINT64_C(0xff00000000000000)) >> 56)) #endif #ifdef WORDS_BIGENDIAN From f315424c42b1fa5a8d08a702b435c0c7deb5dd00 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 23 Jan 2013 23:01:45 +0100 Subject: [PATCH 0229/1445] Add dither to state. Allow choosing FBO color depth. Disable VBO for draw_buffer but keep code. --- gfx_es2/draw_buffer.cpp | 28 +++++++++++++++++++++++++++- gfx_es2/fbo.cpp | 19 +++++++++++++++++-- gfx_es2/fbo.h | 11 ++++++++++- gfx_es2/gl_state.cpp | 2 ++ gfx_es2/gl_state.h | 1 + 5 files changed, 57 insertions(+), 4 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index f920578f6c..6cef2e0bcd 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -20,6 +20,8 @@ enum { MAX_VERTS = 15000, }; +// #define USE_VBO + DrawBuffer::DrawBuffer() : count_(0), atlas(0) { verts_ = new Vertex[MAX_VERTS]; fontscalex = 1.0f; @@ -63,6 +65,7 @@ void DrawBuffer::End() { void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { if (count_ == 0) return; +#ifdef USE_VBO glBindBuffer(GL_ARRAY_BUFFER, vbo_); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * count_, verts_, GL_STREAM_DRAW); @@ -88,7 +91,30 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { glDisableVertexAttribArray(program->a_texcoord0); GL_CHECK(); glBindBuffer(GL_ARRAY_BUFFER, 0); - +#else + if (set_blend_state) { + glstate.blend.enable(); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + glBindBuffer(GL_ARRAY_BUFFER, 0); + glUniform1i(program->sampler0, 0); + glEnableVertexAttribArray(program->a_position); + glEnableVertexAttribArray(program->a_color); + if (program->a_texcoord0 != -1) + glEnableVertexAttribArray(program->a_texcoord0); + GL_CHECK(); + glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)&verts_[0].x); + glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void *)&verts_[0].rgba); + if (program->a_texcoord0 != -1) + glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)&verts_[0].u); + glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_); + GL_CHECK(); + glDisableVertexAttribArray(program->a_position); + glDisableVertexAttribArray(program->a_color); + if (program->a_texcoord0 != -1) + glDisableVertexAttribArray(program->a_texcoord0); + GL_CHECK(); +#endif count_ = 0; } diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 3eac4e53bc..d29f516787 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -26,18 +26,20 @@ struct FBO { int width; int height; + FBOColorDepth colorDepth; }; // On PC, we always use GL_DEPTH24_STENCIL8. // On Android, we try to use what's available. -FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { +FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { CheckGLExtensions(); FBO *fbo = new FBO(); fbo->width = width; fbo->height = height; + fbo->colorDepth = colorDepth; // Color texture is same everywhere glGenFramebuffers(1, &fbo->handle); @@ -51,7 +53,20 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // TODO: We could opt to only create 16-bit render targets on slow devices. For later. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + switch (colorDepth) { + case FBO_8888: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + break; + case FBO_4444: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); + break; + case FBO_5551: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); + break; + case FBO_565: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); + break; + } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index 034a82dc57..ecdc669878 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -4,6 +4,15 @@ struct FBO; + +enum FBOColorDepth { + FBO_8888, + FBO_565, + FBO_4444, + FBO_5551, +}; + + // Creates a simple FBO with a RGBA32 color buffer stored in a texture, and // optionally an accompanying Z/stencil buffer. // No mipmap support. @@ -11,7 +20,7 @@ struct FBO; // you lose bound texture state. // On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. -FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil); +FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth = FBO_8888); // These functions should be self explanatory. void fbo_bind_as_render_target(FBO *fbo); diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 488bdaf950..b0e8fa0a17 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -39,6 +39,8 @@ void OpenGLState::Restore() { stencilOp.restore(); count++; stencilFunc.restore(); count++; + dither.restore(); count++; + assert(count == state_count && "OpenGLState::Restore is missing some states"); } diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index c02d8ef083..8ea0d5ee5c 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -168,6 +168,7 @@ public: BoolState scissorTest; BoolState cullFace; + BoolState dither; STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode; STATE1(glFrontFace, GLenum, GL_CCW) frontFace; From 9493e56b2c2c421ff82759c0a4d0aad999ea79c6 Mon Sep 17 00:00:00 2001 From: Summeli Date: Fri, 25 Jan 2013 17:00:07 +0200 Subject: [PATCH 0230/1445] Routing loggings in Symbian though qDebug to the console --- base/logging.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/base/logging.h b/base/logging.h index cd16386e81..ca97110497 100644 --- a/base/logging.h +++ b/base/logging.h @@ -38,7 +38,7 @@ inline void Crash() { #endif -#ifdef ANDROID +#if defined(ANDROID) #include @@ -54,6 +54,13 @@ inline void Crash() { #define MessageBox(a, b, c, d) __android_log_print(ANDROID_LOG_INFO, APP_NAME, "%s %s", (b), (c)); +#elif defined(__SYMBIAN32__) +#include +#define ILOG(...) { qDebug(__VA_ARGS__);} +#define WLOG(...) { qDebug(__VA_ARGS__);} +#define ELOG(...) { qDebug(__VA_ARGS__);} +#define FLOG(...) { qDebug(__VA_ARGS__); Crash();} + #else // TODO: Win32 version using OutputDebugString From 0d8bcfe9ae10ab31b237e8a100d37f066b8f499f Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Fri, 25 Jan 2013 17:24:50 -0800 Subject: [PATCH 0231/1445] tab key for turbo mode --- base/PCMain.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index fdc88e2436..5a2c6c5bac 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -470,7 +470,7 @@ int main(int argc, char *argv[]) { InputState input_state; int framecount = 0; bool nextFrameMD = 0; - float t = 0; + float t = 0, lastT = 0; while (true) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; @@ -528,7 +528,11 @@ int main(int argc, char *argv[]) { #ifdef PANDORA eglSwapBuffers(g_eglDisplay, g_eglSurface); #else - SDL_GL_SwapBuffers(); + if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) + { + SDL_GL_SwapBuffers(); + lastT = t; + } #endif // Simple frame rate limiting From c21e1ee2cced55bb68edefbb58ba4b30bde807ba Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 26 Jan 2013 17:25:00 +0100 Subject: [PATCH 0232/1445] Add scaling of touch buttons --- ui/virtual_input.cpp | 11 ++++++----- ui/virtual_input.h | 14 +++++++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index 7e6d756789..e9d051397c 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -38,10 +38,11 @@ void TouchButton::draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay) colorOverlay |= 0xFF000000; scale = 2.0f; } + scale *= scale_; // We only mirror background - db.DrawImageRotated(imageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color, mirror_h_); + db.DrawImageRotated(imageIndex_, x_ + w_*scale_/2, y_ + h_*scale_/2, scale, rotationAngle_, color, mirror_h_); if (overlayImageIndex_ != -1) - db.DrawImageRotated(overlayImageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, colorOverlay); + db.DrawImageRotated(overlayImageIndex_, x_ + w_*scale_/2, y_ + h_*scale_/2, scale, rotationAngle_, colorOverlay); } TouchStick::TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick) @@ -54,7 +55,7 @@ TouchStick::TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex void TouchStick::update(InputState &input_state) { - float inv_stick_size = 1.0f / stick_size_; + float inv_stick_size = 1.0f / (stick_size_ * scale_); bool all_up = true; for (int i = 0; i < MAX_POINTERS; i++) { if (input_state.pointer_down[i]) { @@ -108,6 +109,6 @@ skip: void TouchStick::draw(DrawBuffer &db, uint32_t color) { if (bgImageIndex_ != -1) - db.DrawImage(bgImageIndex_, stick_x_, stick_y_, 1.0f, color, ALIGN_CENTER); - db.DrawImage(stickImageIndex_, stick_x_ + stick_delta_x_ * stick_size_, stick_y_ + stick_delta_y_ * stick_size_, 1.0f, color, ALIGN_CENTER); + db.DrawImage(bgImageIndex_, stick_x_, stick_y_, 1.0f * scale_, color, ALIGN_CENTER); + db.DrawImage(stickImageIndex_, stick_x_ + stick_delta_x_ * stick_size_ * scale_, stick_y_ + stick_delta_y_ * stick_size_ * scale_, 1.0f * scale_, color, ALIGN_CENTER); } diff --git a/ui/virtual_input.h b/ui/virtual_input.h index bfc7ed5c37..adeb81c5e5 100644 --- a/ui/virtual_input.h +++ b/ui/virtual_input.h @@ -15,16 +15,17 @@ public: void update(InputState &input_state); void draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay); - void setPos(float x, float y) { - x_ = x - w_ / 2; - y_ = y - h_ / 2; + void setPos(float x, float y, float scale) { + scale_ = scale; + x_ = x - w_ * scale / 2; + y_ = y - h_ * scale / 2; } private: virtual bool isInside(float px, float py) const { float margin = 5.0f; - return px >= x_ - margin && py >= y_ - margin && px <= x_ + w_ + margin && py <= y_ + h_ + margin; + return px >= x_ - margin * scale_ && py >= y_ - margin * scale_ && px <= x_ + (w_ + margin) * scale_ && py <= y_ + (h_ + margin) * scale_; } const Atlas *atlas_; @@ -38,6 +39,7 @@ private: float x_, y_; float w_; float h_; + float scale_; bool isDown_; @@ -57,9 +59,10 @@ public: void update(InputState &input_state); void draw(DrawBuffer &db, uint32_t color); - void setPos(float x, float y) { + void setPos(float x, float y, float scale) { stick_x_ = x; stick_y_ = y; + scale_ = scale; } private: @@ -70,6 +73,7 @@ private: int stick_size_; float stick_x_; float stick_y_; + float scale_; bool dragging_[MAX_POINTERS]; bool lastPointerDown_[MAX_POINTERS]; From 4497f1c5ced56bc9d973fa44b873c95e444ee25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 26 Jan 2013 17:47:02 +0100 Subject: [PATCH 0233/1445] Default touch ui scale to 1.0. --- ui/virtual_input.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/virtual_input.h b/ui/virtual_input.h index adeb81c5e5..41796fee89 100644 --- a/ui/virtual_input.h +++ b/ui/virtual_input.h @@ -15,7 +15,7 @@ public: void update(InputState &input_state); void draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay); - void setPos(float x, float y, float scale) { + void setPos(float x, float y, float scale = 1.0f) { scale_ = scale; x_ = x - w_ * scale / 2; y_ = y - h_ * scale / 2; @@ -59,7 +59,7 @@ public: void update(InputState &input_state); void draw(DrawBuffer &db, uint32_t color); - void setPos(float x, float y, float scale) { + void setPos(float x, float y, float scale = 1.0f) { stick_x_ = x; stick_y_ = y; scale_ = scale; From 5e54aea274f8d7725f3b42f168c03f607111d39c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20G?= Date: Sun, 27 Jan 2013 12:00:43 +0100 Subject: [PATCH 0234/1445] fix city.cpp build when SSE_4_2 is defined --- ext/cityhash/city.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 64a12a42f9..6b73ebe944 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -493,7 +493,7 @@ uint128 CityHash128(const char *s, size_t len) { } #ifdef __SSE4_2__ -#include +#include "citycrc.h" #include // Requires len >= 240. From a8e30185f29914c61c779207366364602a8ed975 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 29 Jan 2013 07:35:39 +1000 Subject: [PATCH 0235/1445] Small adjustments for Blackberry/Symbian --- base/BlackberryMain.cpp | 4 ++-- base/QtMain.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 6a90becc7c..1da1661e7f 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -368,8 +368,8 @@ int main(int argc, char *argv[]) { screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_PHYSICAL_SIZE, screen_phys_size); int screen_resolution[2]; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution); - double diagonal_pixels = sqrt(screen_resolution[0] * screen_resolution[0] + screen_resolution[1] * screen_resolution[1]); - double diagonal_inches = 0.0393700787 * sqrt(screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1]); + double diagonal_pixels = sqrt((double)(screen_resolution[0] * screen_resolution[0] + screen_resolution[1] * screen_resolution[1])); + double diagonal_inches = 0.0393700787 * sqrt((double)(screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1])); int dpi = (int)(diagonal_pixels / diagonal_inches + 0.5); #endif float dpi_scale = 213.6f / dpi; diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 63b5748a08..dd9b29832b 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -46,7 +46,7 @@ float CalculateDPIScale() TSize sTwips = CEikonEnv::Static()->ScreenDevice()->SizeInTwips(); float dpi = sqrt((float)(pixel_xres*pixel_xres + pixel_yres*pixel_yres)) / (sqrt((float)(sTwips.iHeight*sTwips.iHeight + sTwips.iWidth*sTwips.iWidth)) / KTwipsPerInch); - return dpi / 170.0f; + return dpi / 160.0f; #else // Sane default for Blackberry and Meego return 1.2f; From de960cb8c9fe3c901dab72eee2099a23023655f0 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Thu, 31 Jan 2013 23:49:37 +0100 Subject: [PATCH 0236/1445] Correct audio crash when close --- base/QtMain.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index 21c8fb45bb..7741f3835f 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -161,11 +161,11 @@ public: output = new QAudioOutput(fmt); output->setBufferSize(mixlen); feed = output->start(); - startTimer(1000*AUDIO_SAMPLES / AUDIO_FREQ); + timer = startTimer(1000*AUDIO_SAMPLES / AUDIO_FREQ); } ~MainAudio() { + killTimer(timer); feed->close(); - delete feed; output->stop(); delete output; free(mixbuf); @@ -182,6 +182,7 @@ private: QAudioOutput* output; int mixlen; char* mixbuf; + int timer; }; #endif From 36c82b5d183f2f3d2eadf29a303bc773a4fec56b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 2 Feb 2013 01:36:53 -0500 Subject: [PATCH 0237/1445] Resource leak fix, also cleanup. --- audio/mixer.cpp | 2 +- ext/etcpack/etctool.cpp | 3 ++- ext/stb_image/stb_image.c | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/audio/mixer.cpp b/audio/mixer.cpp index c918fcd30a..de19807f4b 100644 --- a/audio/mixer.cpp +++ b/audio/mixer.cpp @@ -183,7 +183,7 @@ void mixer_mix(Mixer *mixer, short *buffer, int num_samples) { // TODO: NEONize. Can also make special loops for left_volume == right_volume etc. for (int s = 0; s < cnt; s++) { int cdata = clip->data[chan->pos]; - buffer[s * 2 ] += cdata * left_volume >> 8; + buffer[s * 2 + 0] += cdata * left_volume >> 8; buffer[s * 2 + 1] += cdata * right_volume >> 8; chan->pos++; } diff --git a/ext/etcpack/etctool.cpp b/ext/etcpack/etctool.cpp index 3e1fff9832..dbe7af8e04 100644 --- a/ext/etcpack/etctool.cpp +++ b/ext/etcpack/etctool.cpp @@ -728,7 +728,7 @@ double calculatePSNRfile(char *srcfile, uint8 *origimg) int active_width; int active_height; int format; - f=fopen(srcfile,"rb"); + f=fopen(srcfile,"rb"); if(f) { if(ktx_mode) @@ -847,6 +847,7 @@ double calculatePSNRfile(char *srcfile, uint8 *origimg) wPSNR = (float)(10*log((double)((255*255)/wMSE))/log((double)10)); printf("Perceptually weighted PSNR = (%f)\n",wPSNR); + fclose(f); free(img); return PSNR; } diff --git a/ext/stb_image/stb_image.c b/ext/stb_image/stb_image.c index 062e32fa8e..98aca5d85a 100644 --- a/ext/stb_image/stb_image.c +++ b/ext/stb_image/stb_image.c @@ -3032,7 +3032,10 @@ static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) skip(s, tga_palette_start ); // load the palette tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); - if (!tga_palette) return epuc("outofmem", "Out of memory"); + if (!tga_palette) { + free(tga_data); + return epuc("outofmem", "Out of memory"); + } if (!getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) { free(tga_data); free(tga_palette); From 5b5eec793faa3c988c964b3504b46420e86b07cd Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 2 Feb 2013 01:41:06 -0500 Subject: [PATCH 0238/1445] Damn tabs. --- ext/stb_image/stb_image.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/stb_image/stb_image.c b/ext/stb_image/stb_image.c index 98aca5d85a..1d996da7b3 100644 --- a/ext/stb_image/stb_image.c +++ b/ext/stb_image/stb_image.c @@ -3033,9 +3033,9 @@ static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp) // load the palette tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 ); if (!tga_palette) { - free(tga_data); - return epuc("outofmem", "Out of memory"); - } + free(tga_data); + return epuc("outofmem", "Out of memory"); + } if (!getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) { free(tga_data); free(tga_palette); From 09a37c4e283019cff0cdf4954667065ca97f92f5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 1 Feb 2013 00:10:55 +0100 Subject: [PATCH 0239/1445] Don't log when framebuffer creation succeeds. --- gfx_es2/fbo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index d29f516787..10baf70f9c 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -75,7 +75,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F #ifdef USING_GLES2 if (gl_extensions.OES_packed_depth_stencil) { - ILOG("Creating FBO using DEPTH24_STENCIL8"); + ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", width, height); // Standard method fbo->stencil_buffer = 0; fbo->z_buffer = 0; @@ -90,7 +90,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); } else { - ILOG("Creating FBO using separate stencil"); + ILOG("Creating %i x %i FBO using separate stencil", width, height); // TEGRA fbo->z_stencil_buffer = 0; // 16/24-bit Z, separate 8-bit stencil @@ -127,7 +127,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { case GL_FRAMEBUFFER_COMPLETE: - ILOG("Framebuffer verified complete."); + // ILOG("Framebuffer verified complete."); break; case GL_FRAMEBUFFER_UNSUPPORTED: ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); From f22ad17d40c00d9a60bd21f53820012b302d7559 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 2 Feb 2013 12:36:09 +0100 Subject: [PATCH 0240/1445] Add way to query the size of an FBO --- gfx_es2/fbo.cpp | 5 +++++ gfx_es2/fbo.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 10baf70f9c..bab538f47b 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -170,3 +170,8 @@ void fbo_destroy(FBO *fbo) { glDeleteTextures(1, &fbo->color_texture); glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); } + +void fbo_get_dimensions(FBO *fbo, int *w, int *h) { + *w = fbo->width; + *h = fbo->height; +} \ No newline at end of file diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index ecdc669878..9641dc7225 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -1,6 +1,8 @@ #pragma once // Simple wrapper around FBO functionality. +// Very C-ish API because that's what I felt like, and it's cool to completely +// hide the data from callers... struct FBO; @@ -29,3 +31,4 @@ void fbo_bind_color_as_texture(FBO *fbo, int color); void fbo_bind_for_read(FBO *fbo); void fbo_unbind(); void fbo_destroy(FBO *fbo); +void fbo_get_dimensions(FBO *fbo, int *w, int *h); \ No newline at end of file From 366de9f248ecec1c6c0274be5c9e3c82c95de5a4 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 2 Feb 2013 13:18:23 -0500 Subject: [PATCH 0241/1445] Fix a another memory leak in etctool. imgdec = (unsigned char*) malloc(expandedwidth*expandedheight*3); is called before the if statement "if((f=fopen(dstfile,"wb")))" If the file 'f' failed in the if statement, it would never be freed (since "free(imgdec)" was within that if block. --- ext/etcpack/etctool.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/etcpack/etctool.cpp b/ext/etcpack/etctool.cpp index dbe7af8e04..56f2e07dc5 100644 --- a/ext/etcpack/etctool.cpp +++ b/ext/etcpack/etctool.cpp @@ -612,9 +612,10 @@ void compressImageFile(uint8 *img,int width,int height,char *dstfile, int expand printf("\n"); fclose(f); - free(imgdec); - printf("Saved file <%s>.\n",dstfile); + printf("Saved file <%s>.\n",dstfile); } + + free(imgdec); } double calculatePSNR(uint8 *lossyimg, uint8 *origimg, int width, int height) From e6dce8e1af69d1480121b5d4b26cbd147baf2c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 4 Feb 2013 15:55:17 +0100 Subject: [PATCH 0242/1445] Fix PPSSPP Qt interface compilation on 64bit Linux --- base/logging.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/base/logging.h b/base/logging.h index ca97110497..a7b15889ff 100644 --- a/base/logging.h +++ b/base/logging.h @@ -9,11 +9,11 @@ #pragma warning (disable:4996) //strcpy may be dangerous #endif +#undef Crash + // Logging #ifdef _WIN32 -#undef Crash - #ifdef _M_X64 inline void Crash() { /*DebugBreak();*/ } #else @@ -23,8 +23,6 @@ inline void Crash() { __asm { int 3 }; } #else #if defined(ARM) -#undef Crash - inline void Crash() { char *p = (char *)1337; *p = 1; From 70a56b48871eb4eb27c54804c1fba1fbfcf9763f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Feb 2013 00:33:41 -0800 Subject: [PATCH 0243/1445] Delete FBOs in fbo_destroy(). --- gfx_es2/fbo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index bab538f47b..f0800e1bb9 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -169,6 +169,7 @@ void fbo_destroy(FBO *fbo) { glDeleteFramebuffers(1, &fbo->handle); glDeleteTextures(1, &fbo->color_texture); glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); + delete fbo; } void fbo_get_dimensions(FBO *fbo, int *w, int *h) { From fa10aae32fcbb88236d33ea554c8e99eb3ad98c5 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 11 Feb 2013 00:42:12 +1000 Subject: [PATCH 0244/1445] Use fixed DPI on Symbian. New devices seem to lie about DPI. --- base/QtMain.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index dd9b29832b..c9a74a3e40 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -41,14 +41,10 @@ void SimulateGamepad(InputState *input) { float CalculateDPIScale() { - // Calculate DPI from TWIPS on Symbian + // Sane default for Symbian, Blackberry and Meego #ifdef __SYMBIAN32__ - TSize sTwips = CEikonEnv::Static()->ScreenDevice()->SizeInTwips(); - float dpi = sqrt((float)(pixel_xres*pixel_xres + pixel_yres*pixel_yres)) - / (sqrt((float)(sTwips.iHeight*sTwips.iHeight + sTwips.iWidth*sTwips.iWidth)) / KTwipsPerInch); - return dpi / 160.0f; + return 1.3f; #else - // Sane default for Blackberry and Meego return 1.2f; #endif } From 21e4e12f655a039e66e26cf4349a403ac8de03c9 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 11 Feb 2013 21:35:10 +1000 Subject: [PATCH 0245/1445] Fix spinny buttons animation on Qt and Blackberry front-ends. --- base/BlackberryMain.cpp | 1 + base/QtMain.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 1da1661e7f..62dac3b7dc 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -468,6 +468,7 @@ int main(int argc, char *argv[]) { NativeUpdate(input_state); EndInputState(&input_state); NativeRender(); + time_update(); // On Blackberry, this handles VSync for us eglSwapBuffers(egl_disp, egl_surf); } diff --git a/base/QtMain.h b/base/QtMain.h index 7741f3835f..f54ae7c4b6 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -130,7 +130,7 @@ protected: NativeUpdate(input_state); EndInputState(&input_state); NativeRender(); - + time_update(); update(); } From 14b9794c260de5cf695e34052f9ffb686d6caf27 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 13 Feb 2013 04:54:47 +1000 Subject: [PATCH 0246/1445] Move PPSSPP window init out of here because native is meant to be generic. --- base/QtMain.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index c9a74a3e40..eeb61dd059 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -13,9 +13,6 @@ #ifdef __SYMBIAN32__ #include #endif -#if defined(Q_WS_X11) && !defined(USING_GLES2) -#include "mainwindow.h" -#endif #include "QtMain.h" void LaunchBrowser(const char *url) @@ -81,10 +78,7 @@ int main(int argc, char *argv[]) NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #endif -#if defined(Q_WS_X11) && !defined(USING_GLES2) - MainWindow mainWindow; - mainWindow.show(); -#else +#if !defined(Q_WS_X11) || defined(USING_GLES2) MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); #ifdef USING_GLES2 From 0bb312c92a6561b9d929f09257e27eee1f1e29a0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 13 Feb 2013 05:11:56 +1000 Subject: [PATCH 0247/1445] Now that only mobile platforms use this code path, remove the desktop support --- base/QtMain.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index eeb61dd059..c2aca1cad5 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -57,16 +57,11 @@ int main(int argc, char *argv[]) QT_TRAP_THROWING(dynamic_cast(CEikonEnv::Static()->AppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); #endif QSize res = QApplication::desktop()->screenGeometry().size(); -#ifdef USING_GLES2 if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); -#else - // Set resolution to half of the monitor on desktop systems - pixel_xres = res.width() / 2; - pixel_yres = res.height() / 2; -#endif + float dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); net::Init(); @@ -78,14 +73,10 @@ int main(int argc, char *argv[]) NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #endif -#if !defined(Q_WS_X11) || defined(USING_GLES2) +#if defined(USING_GLES2) MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); -#ifdef USING_GLES2 w.showFullScreen(); -#else - w.show(); -#endif #endif MainAudio *audio = new MainAudio(); From be52e8c6736df713fa462d019633c06e4a53546f Mon Sep 17 00:00:00 2001 From: Xele02 Date: Sun, 17 Feb 2013 01:28:26 +0100 Subject: [PATCH 0248/1445] Add mutex, or wait don't work correctly --- base/mutex.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/mutex.h b/base/mutex.h index 59594ae883..f0c13b8adc 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -129,7 +129,9 @@ public: ResetEvent(event_); // necessary? // mtx.lock(); #else + pthread_mutex_lock(&mtx.native_handle()); pthread_cond_wait(&event_, &mtx.native_handle()); + pthread_mutex_unlock(&mtx.native_handle()); #endif } @@ -139,4 +141,4 @@ private: #else pthread_cond_t event_; #endif -}; \ No newline at end of file +}; From 14386f87b044ff59bf509a35591debf89d917fb2 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 20 Feb 2013 00:04:30 +1000 Subject: [PATCH 0249/1445] Use temp path from Qt. Fixes windows. --- base/QtMain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index c2aca1cad5..db19e45588 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -68,9 +68,9 @@ int main(int argc, char *argv[]) #ifdef __SYMBIAN32__ NativeInit(argc, (const char **)argv, "E:/PPSSPP/", "E:", "BADCOFFEE"); #elif defined(BLACKBERRY) - NativeInit(argc, (const char **)argv, "data/", "/tmp", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, "data/", QDir::tempPath().toStdString().c_str(), "BADCOFFEE"); #else - NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, "./", QDir::tempPath().toStdString().c_str(), "BADCOFFEE"); #endif #if defined(USING_GLES2) From f807e225f75b131e614c92770fb93a5e902be22b Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 20 Feb 2013 00:18:13 +1000 Subject: [PATCH 0250/1445] Quick fix for missing QDir --- base/QtMain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index db19e45588..574395445e 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include From f4cc78cbfdb5c9d9c3d83353e66625db43cf54b5 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 20 Feb 2013 13:07:19 +1000 Subject: [PATCH 0251/1445] Use RunFast VFPv2 mode on Symbian. --- base/QtMain.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 574395445e..05d3f471ac 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -53,9 +53,11 @@ int main(int argc, char *argv[]) QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); - // Lock orientation to landscape on Symbian #ifdef __SYMBIAN32__ + // Lock orientation to landscape on Symbian QT_TRAP_THROWING(dynamic_cast(CEikonEnv::Static()->AppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); + // Set RunFast hardware mode for VFPv2. Denormalised values are treated as 0. NaN used for all NaN situations. + User::SetFloatingPointMode(EFpModeRunFast); #endif QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) @@ -67,12 +69,13 @@ int main(int argc, char *argv[]) dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); net::Init(); #ifdef __SYMBIAN32__ - NativeInit(argc, (const char **)argv, "E:/PPSSPP/", "E:", "BADCOFFEE"); + char* savegame_dir = "E:/PPSSPP/"; #elif defined(BLACKBERRY) - NativeInit(argc, (const char **)argv, "data/", QDir::tempPath().toStdString().c_str(), "BADCOFFEE"); + char* savegame_dir = "data/"; #else - NativeInit(argc, (const char **)argv, "./", QDir::tempPath().toStdString().c_str(), "BADCOFFEE"); + char* savegame_dir = "./"; #endif + NativeInit(argc, (const char **)argv, savegame_dir, QDir::tempPath().toStdString().c_str(), "BADCOFFEE"); #if defined(USING_GLES2) MainUI w(dpi_scale); From a9a067ef8473628f170dfdab1f7692b53a5f130b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 22 Feb 2013 22:11:26 +0100 Subject: [PATCH 0252/1445] Set depth and color mask before clearing. --- android/app-android.cpp | 3 +++ gfx_es2/fbo.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index d65714d63f..6dc9843454 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -23,6 +23,7 @@ #include "math/math_util.h" #include "net/resolve.h" #include "android/native_audio.h" +#include "gfx_es2/gl_state.h" // For Xperia Play support enum AndroidKeyCodes { @@ -251,6 +252,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN } else { ELOG("Ended up in nativeRender even though app has quit.%s", ""); // Shouldn't really get here. + glstate.depthWrite.set(GL_TRUE); + glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearColor(1.0, 0.0, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index f0800e1bb9..81b23244dc 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -1,6 +1,7 @@ #include #include "base/logging.h" +#include "gfx/gl_common.h" #include "gfx_es2/fbo.h" #include "gfx/gl_common.h" #include "gfx_es2/gl_state.h" @@ -35,7 +36,6 @@ struct FBO { FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { CheckGLExtensions(); - FBO *fbo = new FBO(); fbo->width = width; fbo->height = height; @@ -175,4 +175,4 @@ void fbo_destroy(FBO *fbo) { void fbo_get_dimensions(FBO *fbo, int *w, int *h) { *w = fbo->width; *h = fbo->height; -} \ No newline at end of file +} From 9c183fcca8416a34d510880d483ccf5f2ec573f4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 Feb 2013 13:23:20 -0800 Subject: [PATCH 0253/1445] Add a timeout event.wait_for() method. Not exactly like std::condition_variable, but similar. --- base/mutex.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/base/mutex.h b/base/mutex.h index f0c13b8adc..76b78facaa 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -135,6 +135,23 @@ public: #endif } + void wait_for(recursive_mutex &mtx, int milliseconds) { +#ifdef _WIN32 + //mtx.unlock(); + WaitForSingleObject(event_, milliseconds); + ResetEvent(event_); // necessary? + // mtx.lock(); +#else + timespec timeout; + clock_gettime(CLOCK_REALTIME, &timeout); + timeout.tv_sec += milliseconds / 1000; + timeout.tv_nsec += milliseconds * 1000000; + pthread_mutex_lock(&mtx.native_handle()); + pthread_cond_timedwait(&event_, &mtx.native_handle(), &timeout); + pthread_mutex_unlock(&mtx.native_handle()); +#endif + } + private: #ifdef _WIN32 HANDLE event_; From 318e75a66544ef7a1ddbc2423603d3d7a8116d24 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 24 Feb 2013 13:45:48 +1000 Subject: [PATCH 0254/1445] Fix for FBO on iOS devices (from rock88). --- gfx_es2/fbo.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 81b23244dc..b8bb99b9e4 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -18,6 +18,10 @@ #endif #endif +#ifdef IOS +extern void bindDefaultFBO(); +#endif + struct FBO { GLuint handle; GLuint color_texture; @@ -147,6 +151,9 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F void fbo_unbind() { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +#ifdef IOS + bindDefaultFBO(); +#endif } void fbo_bind_as_render_target(FBO *fbo) { From e77cea0211a9cf480a815113f6e598c6666d453f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 Feb 2013 19:48:09 -0800 Subject: [PATCH 0255/1445] Buildfix for Mac. --- base/mutex.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/base/mutex.h b/base/mutex.h index 76b78facaa..d1b7d552ed 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -20,6 +20,7 @@ #else #include #include +#include #endif class recursive_mutex { @@ -143,7 +144,15 @@ public: // mtx.lock(); #else timespec timeout; +#ifdef __APPLE__ + timeval tv; + gettimeofday(&tv, NULL); + timeout.tv_sec = tv.tv_sec; + timeout.tv_nsec = tv.tv_usec * 1000; clock_gettime(CLOCK_REALTIME, &timeout); +#else + clock_gettime(CLOCK_REALTIME, &timeout); +#endif timeout.tv_sec += milliseconds / 1000; timeout.tv_nsec += milliseconds * 1000000; pthread_mutex_lock(&mtx.native_handle()); From 17c8eb1ae7ca285a4228bac56059ca441b53ba6f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 Feb 2013 19:52:15 -0800 Subject: [PATCH 0256/1445] Arg, buildfix for Mac. --- base/mutex.h | 1 - 1 file changed, 1 deletion(-) diff --git a/base/mutex.h b/base/mutex.h index d1b7d552ed..cae54dae77 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -149,7 +149,6 @@ public: gettimeofday(&tv, NULL); timeout.tv_sec = tv.tv_sec; timeout.tv_nsec = tv.tv_usec * 1000; - clock_gettime(CLOCK_REALTIME, &timeout); #else clock_gettime(CLOCK_REALTIME, &timeout); #endif From 3f6353af5afe1542a50c33eb0bb554ea25653258 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 26 Feb 2013 23:07:30 +0100 Subject: [PATCH 0257/1445] Add VFSFileSystem for Android to be able to mount flash0: inside the APK --- file/file_util.cpp | 8 ++++++++ file/file_util.h | 1 + file/zip_read.cpp | 16 +++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index db169e3245..25ad3eb741 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -167,6 +167,13 @@ bool getFileInfo(const char *path, FileInfo *fileInfo) fileInfo->fullName = path; #ifdef _WIN32 + fileInfo->size = 0; + FILE *f = fopen(path, "rb"); + if (f) { + fseek(f, 0, SEEK_END); + fileInfo->size = ftell(f); + fclose(f); + } DWORD attributes = GetFileAttributes(path); fileInfo->isDirectory = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; fileInfo->isWritable = (attributes & FILE_ATTRIBUTE_READONLY) == 0; @@ -185,6 +192,7 @@ bool getFileInfo(const char *path, FileInfo *fileInfo) fileInfo->isDirectory = S_ISDIR(file_info.st_mode); fileInfo->isWritable = false; + fileInfo->size = file_info.st_size; // HACK: approximation if (file_info.st_mode & 0200) fileInfo->isWritable = true; diff --git a/file/file_util.h b/file/file_util.h index 5a118b457c..b17a804d07 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -19,6 +19,7 @@ struct FileInfo bool exists; bool isDirectory; bool isWritable; + size_t size; bool operator <(const FileInfo &other) const { if (isDirectory && !other.isDirectory) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index fc2460e8ff..70880f1032 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -77,7 +77,7 @@ ZipAssetReader::~ZipAssetReader() { } uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { - char temp_path[256]; + char temp_path[1024]; strcpy(temp_path, in_zip_path_); strcat(temp_path, path); return ReadFromZip(zip_file_, temp_path, size); @@ -142,10 +142,24 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis bool ZipAssetReader::GetFileInfo(const char *path, FileInfo *info) { + struct zip_stat zstat; + char temp_path[1024]; + strcpy(temp_path, in_zip_path_); + strcat(temp_path, path); + if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE, &zstat)) + { + ELOG("Failed doing zip_stat on %s, bailing", path); + info->exists = false; + info->size = 0; + return false; + } + info->fullName = path; info->exists = true; // TODO info->isWritable = false; info->isDirectory = false; // TODO + info->size = zstat.size; + return true; } #endif From 3030c2a91423cac5cffb70b6ff3cba4450521be9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 28 Feb 2013 23:38:55 -0800 Subject: [PATCH 0258/1445] Fix http::Client::POST() on Windows. Was using write() not send(), also was missing Host header. --- net/http_client.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index b2bef05618..0c69057a77 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -111,10 +111,10 @@ void Client::GET(const char *resource, Buffer *output) { int Client::POST(const char *resource, const std::string &data, Buffer *output) { Buffer buffer; - const char *tpl = "POST %s HTTP/1.0\r\nContent-Length: %d\r\n\r\n"; - buffer.Printf(tpl, resource, (int)data.size()); + const char *tpl = "POST %s HTTP/1.0\r\nHost: %s\r\nContent-Length: %d\r\n\r\n"; + buffer.Printf(tpl, resource, host_.c_str(), (int)data.size()); buffer.Append(data); - CHECK(buffer.Flush(sock())); + CHECK(buffer.FlushSocket(sock())); // I guess we could add a deadline here. output->ReadAll(sock()); From 6680469821da4d3d74510436c5546763f0887298 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 28 Feb 2013 23:39:35 -0800 Subject: [PATCH 0259/1445] Include the User-Agent header in HTTP requests. --- net/http_client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 0c69057a77..31c0dcf0c2 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -95,7 +95,7 @@ Client::~Client() { void Client::GET(const char *resource, Buffer *output) { Buffer buffer; - const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n"; + const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " USERAGENT "\r\n\r\n"; buffer.Printf(tpl, resource, host_.c_str()); CHECK(buffer.FlushSocket(sock())); @@ -111,7 +111,7 @@ void Client::GET(const char *resource, Buffer *output) { int Client::POST(const char *resource, const std::string &data, Buffer *output) { Buffer buffer; - const char *tpl = "POST %s HTTP/1.0\r\nHost: %s\r\nContent-Length: %d\r\n\r\n"; + const char *tpl = "POST %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " USERAGENT "\r\nContent-Length: %d\r\n\r\n"; buffer.Printf(tpl, resource, host_.c_str(), (int)data.size()); buffer.Append(data); CHECK(buffer.FlushSocket(sock())); From 9817448c59414b65cce7674dc2b2f81f6c53331b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 28 Feb 2013 23:48:19 -0800 Subject: [PATCH 0260/1445] If needed, call send() multiple times in HTTP. --- base/buffer.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index 5b3dabe77b..ee91fd3917 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -109,16 +109,26 @@ bool Buffer::Flush(int fd) { } bool Buffer::FlushSocket(uintptr_t sock) { - // TODO: send may need retries! - size_t sent = send(sock, &data_[0], data_.size(), 0); - // bool success = fd_util::WriteLine(fd, data_.data(), data_.size()); - if (sent == data_.size()) { - data_.resize(0); - return true; - } else { - ELOG("FlushSocket failed"); - return false; + for (size_t pos = 0, end = data_.size(); pos < end; ) { + size_t sent = send(sock, &data_[pos], end - pos, 0); + if (sent < 0) { + ELOG("FlushSocket failed"); + return false; + } + pos += sent; + + // Buffer full, don't spin. + if (sent == 0) { +#ifdef _WIN32 + Sleep(1); +#else + sleep(1); +#endif + } } + + data_.resize(0); + return true; } void Buffer::ReadAll(int fd) { From 19d3ce79ed0688598b4e1386d663443e969b5abe Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 28 Feb 2013 23:59:32 -0800 Subject: [PATCH 0261/1445] Don't exit(1) on DNS resolution failure. --- net/http_client.cpp | 9 ++++++++- net/resolve.cpp | 20 ++++++++++++++++---- net/resolve.h | 1 + 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 31c0dcf0c2..ecbf5f86f2 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -39,7 +39,14 @@ bool Connection::Resolve(const char *host, int port) { host_ = host; port_ = port; - const char *ip = net::DNSResolve(host); + const char *err; + const char *ip = net::DNSResolveTry(host, &err); + if (ip == NULL) { + ELOG("Failed to resolve host %s", host); + // So that future calls fail. + port_ = 0; + return false; + } // VLOG(1) << "Resolved " << host << " to " << ip; remote_.sin_family = AF_INET; int tmpres = inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr))); diff --git a/net/resolve.cpp b/net/resolve.cpp index f1432eec88..f46159422e 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -34,20 +34,32 @@ void Shutdown() #endif } -char *DNSResolve(const char *host) +char *DNSResolveTry(const char *host, const char **err) { struct hostent *hent; if((hent = gethostbyname(host)) == NULL) { - perror("Can't get IP"); - exit(1); + *err = "Can't get IP"; + return NULL; } int iplen = 15; //XXX.XXX.XXX.XXX char *ip = (char *)malloc(iplen+1); memset(ip, 0, iplen+1); if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL) { - perror("Can't resolve host"); + *err = "Can't resolve host"; + return NULL; + } + return ip; +} + +char *DNSResolve(const char *host) +{ + const char *err; + char *ip = DNSResolveTry(host, &err); + if (ip == NULL) + { + perror(err); exit(1); } return ip; diff --git a/net/resolve.h b/net/resolve.h index 3f6d3d2f87..bcefe6ffa5 100644 --- a/net/resolve.h +++ b/net/resolve.h @@ -8,6 +8,7 @@ void Init(); void Shutdown(); // use free() to free the returned string. +char *DNSResolveTry(const char *host, const char **err); char *DNSResolve(const char *host); } // namespace net #endif From 8611631555d37797b886578930809c8dd8fa7aa9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 1 Mar 2013 00:04:42 -0800 Subject: [PATCH 0262/1445] Allow http::Client::POST() to specify the content-type. --- net/http_client.cpp | 12 ++++++++++-- net/http_client.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index ecbf5f86f2..96a730a5a9 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -116,10 +116,14 @@ void Client::GET(const char *resource, Buffer *output) { // output now contains the rest of the reply. } -int Client::POST(const char *resource, const std::string &data, Buffer *output) { +int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output) { Buffer buffer; - const char *tpl = "POST %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " USERAGENT "\r\nContent-Length: %d\r\n\r\n"; + const char *tpl = "POST %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " USERAGENT "\r\nContent-Length: %d\r\n"; buffer.Printf(tpl, resource, host_.c_str(), (int)data.size()); + if (!mime.empty()) { + buffer.Printf("Content-Type: %s\r\n", mime.c_str()); + } + buffer.Append("\r\n"); buffer.Append(data); CHECK(buffer.FlushSocket(sock())); @@ -152,4 +156,8 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) return code; } +int Client::POST(const char *resource, const std::string &data, Buffer *output) { + return POST(resource, data, "", output); +} + } // http diff --git a/net/http_client.h b/net/http_client.h index ac813f3b99..2b36360541 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -59,6 +59,7 @@ public: void GET(const char *resource, Buffer *output); // Return value is the HTTP return code. + int POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output); int POST(const char *resource, const std::string &data, Buffer *output); // HEAD, PUT, DELETE aren't implemented yet. From 3c1566b9a7559708dfd7d1413f723da51299e5c4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 1 Mar 2013 22:50:14 -0800 Subject: [PATCH 0263/1445] Linux buildfix, darn. --- base/buffer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/base/buffer.cpp b/base/buffer.cpp index ee91fd3917..c1e34ea534 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -10,6 +10,7 @@ #undef max #else #include +#include #endif #include "base/logging.h" From f26d95dba1abc7d3936b929ab01aafff40555c93 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 2 Mar 2013 13:40:07 -0800 Subject: [PATCH 0264/1445] Fix FlushSocket() error check. --- base/buffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index c1e34ea534..9abcfe8eab 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -111,7 +111,7 @@ bool Buffer::Flush(int fd) { bool Buffer::FlushSocket(uintptr_t sock) { for (size_t pos = 0, end = data_.size(); pos < end; ) { - size_t sent = send(sock, &data_[pos], end - pos, 0); + int sent = send(sock, &data_[pos], end - pos, 0); if (sent < 0) { ELOG("FlushSocket failed"); return false; From 4ee889c0255f0dbd9066c7a624cc03b625ec48fe Mon Sep 17 00:00:00 2001 From: oioitff Date: Mon, 4 Mar 2013 14:48:18 -0800 Subject: [PATCH 0265/1445] Use a custom inet_pton and avoid inet_ntoa for now. When/if ipv6 is needed we can fix inet_ntop. --- net/http_client.cpp | 6 +--- net/resolve.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++- net/resolve.h | 2 ++ 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 96a730a5a9..882861eb7f 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -1,9 +1,5 @@ #include "net/http_client.h" -// for inet_pton -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x600 - #ifndef _WIN32 #include #include @@ -49,7 +45,7 @@ bool Connection::Resolve(const char *host, int port) { } // VLOG(1) << "Resolved " << host << " to " << ip; remote_.sin_family = AF_INET; - int tmpres = inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr))); + int tmpres = net::inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr))); CHECK_GE(tmpres, 0); // << "inet_pton failed"; CHECK_NE(0, tmpres); // << ip << " not a valid IP address"; remote_.sin_port = htons(port); diff --git a/net/resolve.cpp b/net/resolve.cpp index f46159422e..77e81b586a 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -45,11 +45,13 @@ char *DNSResolveTry(const char *host, const char **err) int iplen = 15; //XXX.XXX.XXX.XXX char *ip = (char *)malloc(iplen+1); memset(ip, 0, iplen+1); - if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL) + char *iptoa = inet_ntoa(*(in_addr *)hent->h_addr_list[0]); + if (iptoa == NULL) { *err = "Can't resolve host"; return NULL; } + strncpy(ip, iptoa, iplen); return ip; } @@ -65,4 +67,76 @@ char *DNSResolve(const char *host) return ip; } +int inet_pton(int af, const char* src, void* dst) +{ + if (af == AF_INET) + { + BYTE *ip = (BYTE *)dst; + int k = 0, x = 0; + char ch; + for (int i = 0; (ch = src[i]) != 0; i++) + { + if (ch == '.') + { + ip[k++] = x; + if (k == 4) + return 0; + x = 0; + } + else if (ch < '0' || ch > '9') + return 0; + else + x = x * 10 + ch - '0'; + if (x > 255) + return 0; + } + ip[k++] = x; + if (k != 4) + return 0; + } + else if (af == AF_INET6) + { + unsigned short* ip = ( unsigned short* )dst; + int i; + for (i = 0; i < 8; i++) ip[i] = 0; + int k = 0; + unsigned int x = 0; + char ch; + int marknum = 0; + for (i = 0; src[i] != 0; i++) + { + if (src[i] == ':') + marknum++; + } + for (i = 0; (ch = src[i]) != 0; i++) + { + if (ch == ':') + { + x = ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8); + ip[k++] = x; + if (k == 8) + return 0; + x = 0; + if (i > 0 && src[i - 1] == ':') + k += 7 - marknum; + } + else if (ch >= '0' && ch <= '9') + x = x * 16 + ch - '0'; + else if (ch >= 'a' && ch <= 'f') + x = x * 16 + ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') + x = x * 16 + ch - 'A' + 10; + else + return 0; + if (x > 0xFFFF) + return 0; + } + x = ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8); + ip[k++] = x; + if (k != 8) + return 0; + } + return 1; +} + } diff --git a/net/resolve.h b/net/resolve.h index bcefe6ffa5..4a82d84971 100644 --- a/net/resolve.h +++ b/net/resolve.h @@ -10,5 +10,7 @@ void Shutdown(); // use free() to free the returned string. char *DNSResolveTry(const char *host, const char **err); char *DNSResolve(const char *host); + +int inet_pton(int af, const char* src, void* dst); } // namespace net #endif From dff0ac566954bfa18f0a972839a03bea737b821b Mon Sep 17 00:00:00 2001 From: Todd Christensen Date: Mon, 4 Mar 2013 16:10:46 -0800 Subject: [PATCH 0266/1445] Buildfix. --- net/resolve.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/resolve.cpp b/net/resolve.cpp index 77e81b586a..6b0af606f0 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -71,7 +71,7 @@ int inet_pton(int af, const char* src, void* dst) { if (af == AF_INET) { - BYTE *ip = (BYTE *)dst; + unsigned char *ip = (unsigned char *)dst; int k = 0, x = 0; char ch; for (int i = 0; (ch = src[i]) != 0; i++) From 21bf00463270e49796e98b26e750e46bb9733cb1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 6 Mar 2013 19:05:59 +0100 Subject: [PATCH 0267/1445] Zip reader: logging fixes --- file/zip_read.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 70880f1032..cb01aa3191 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -54,7 +54,6 @@ uint8_t *ReadLocalFile(const char *filename, size_t *size) { #ifdef ANDROID ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { - ELOG("ZIP File %s", zip_file); zip_file_ = zip_open(zip_file, 0, NULL); strcpy(in_zip_path_, in_zip_path); if (!zip_file_) { @@ -140,15 +139,14 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis return true; } -bool ZipAssetReader::GetFileInfo(const char *path, FileInfo *info) -{ +bool ZipAssetReader::GetFileInfo(const char *path, FileInfo *info) { struct zip_stat zstat; char temp_path[1024]; strcpy(temp_path, in_zip_path_); strcat(temp_path, path); - if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE, &zstat)) - { - ELOG("Failed doing zip_stat on %s, bailing", path); + if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE, &zstat)) { + // ZIP files do not have real directories, so we'll end up here if we + // try to stat one. For now that's fine. info->exists = false; info->size = 0; return false; From 7bc8374c8816efe0fab4a9cd5959ca2d2fcd09d8 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 10 Mar 2013 12:28:34 +1000 Subject: [PATCH 0268/1445] Change Blackbery paths --- base/BlackberryMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 62dac3b7dc..2804f00597 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -375,7 +375,7 @@ int main(int argc, char *argv[]) { float dpi_scale = 213.6f / dpi; dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); - NativeInit(argc, (const char **)argv, "data/", "/accounts/1000/shared", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, "/accounts/1000/shared/documents/PPSSPP/", "data/", "BADCOFFEE"); NativeInitGraphics(); screen_request_events(screen_cxt); navigator_request_events(0); From b8100e023858a9b2a217ac7f38cb78cca983b952 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 10 Mar 2013 13:22:46 +1000 Subject: [PATCH 0269/1445] MIPS support --- base/logging.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/logging.h b/base/logging.h index a7b15889ff..e21ccf7ae2 100644 --- a/base/logging.h +++ b/base/logging.h @@ -22,7 +22,7 @@ inline void Crash() { __asm { int 3 }; } #else -#if defined(ARM) +#if defined(ARM) || defined(MIPS) inline void Crash() { char *p = (char *)1337; *p = 1; From 4fb2e97afaaa2bd0b7d322545c79a65d8927ac8d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 10 Mar 2013 17:49:01 +0100 Subject: [PATCH 0270/1445] Fix bugs causing infinite loop in gllost, add more logging. --- android/app-android.cpp | 40 ++++++++++++++----- .../henrikrydgard/libnative/NativeApp.java | 2 +- gfx/gl_lost_manager.cpp | 33 ++++++++++++--- gfx/texture.cpp | 18 ++++++--- gfx_es2/draw_buffer.cpp | 7 ++-- gfx_es2/draw_buffer.h | 2 +- 6 files changed, 75 insertions(+), 27 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 6dc9843454..6fdc010e8a 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -46,6 +46,8 @@ static JNIEnv *jniEnvUI; std::string frameCommand; std::string frameCommandParam; +const bool extraLog = true; + static uint32_t pad_buttons_async_set; static uint32_t pad_buttons_async_clear; @@ -120,6 +122,9 @@ extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isLandscape(JNIEn // For the Back button to work right. extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isAtTopLevel(JNIEnv *env, jclass) { + if (extraLog) { + ILOG("isAtTopLevel"); + } return NativeIsAtTopLevel(); } @@ -128,6 +133,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; + ILOG("NativeApp.init() -- begin"); + memset(&input_state, 0, sizeof(input_state)); renderer_inited = false; first_lost = true; @@ -136,7 +143,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init pad_buttons_async_clear = 0; std::string apkPath = GetJavaString(env, japkpath); - ILOG("APK path: %s", apkPath.c_str()); + ILOG("NativeApp::Init: APK path: %s", apkPath.c_str()); VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); std::string externalDir = GetJavaString(env, jexternalDir); @@ -144,7 +151,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init std::string library_path = GetJavaString(env, jlibraryDir) + "/"; std::string installID = GetJavaString(env, jinstallID); - ILOG("External storage path: %s", externalDir.c_str()); + ILOG("NativeApp.init(): External storage path: %s", externalDir.c_str()); std::string app_name; std::string app_nice_name; @@ -167,24 +174,25 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init if (use_native_audio) { AndroidAudio_Init(&NativeMix, library_path); } + ILOG("NativeApp.init() -- end"); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_resume(JNIEnv *, jclass) { - ILOG("NativeResume"); + ILOG("NativeApp.resume() - resuming audio"); if (use_native_audio) { AndroidAudio_Resume(); } } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclass) { - ILOG("NativePause"); + ILOG("NativeApp.pause() - pausing audio"); if (use_native_audio) { AndroidAudio_Pause(); } } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { - ILOG("NativeShutdown."); + ILOG("NativeApp.shutdown() -- begin"); if (use_native_audio) { AndroidAudio_Shutdown(); } @@ -196,21 +204,21 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jc ILOG("VFSShutdown."); VFSShutdown(); net::Shutdown(); + ILOG("NativeApp.shutdown() -- end"); } static jmethodID postCommand; extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { - ILOG("displayInit()"); + ILOG("NativeApp.displayInit()"); if (!renderer_inited) { - // We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S). // Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo // can change the dp resolution if it feels like it. dp_xres = pixel_xres * g_dpi_scale; dp_yres = pixel_yres * g_dpi_scale; - ILOG("Calling NativeInitGraphics(); dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); + ILOG("Calling NativeInitGraphics(): dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); NativeInitGraphics(); dp_xscale = (float)dp_xres / pixel_xres; @@ -219,18 +227,24 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIE } else { ILOG("Calling NativeDeviceLost();"); NativeDeviceLost(); + ILOG("NativeDeviceLost completed.;"); } + ILOG("(Re)-fetching method ID to postCommand..."); jclass cls = env->GetObjectClass(obj); postCommand = env->GetMethodID(cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); ILOG("MethodID: %i", (int)postCommand); } extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { - ILOG("displayResize (%i, %i)!", w, h); + ILOG("NativeApp.displayResize(%i, %i)", w, h); + // TODO: Move some of the logic from displayInit here? } extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { + // Too spammy + // ILOG("NativeApp.displayRender()"); if (renderer_inited) { + // TODO: Look into if these locks are a perf loss { lock_guard guard(input_state.lock); input_state.pad_buttons |= pad_buttons_async_set; @@ -247,11 +261,12 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN lock_guard guard(input_state.lock); EndInputState(&input_state); } + NativeRender(); time_update(); } else { - ELOG("Ended up in nativeRender even though app has quit.%s", ""); - // Shouldn't really get here. + ELOG("BAD: Ended up in nativeRender even though app has quit.%s", ""); + // Shouldn't really get here. Let's draw magenta. glstate.depthWrite.set(GL_TRUE); glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearColor(1.0, 0.0, 1.0f, 1.0f); @@ -271,6 +286,9 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { + // Too spammy + // ILOG("NativeApp.audioRender"); + // The audio thread can pretty safely enable Flush-to-Zero mode on the FPU. EnableFZ(); diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 9c016f0ada..7c119ae96a 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -10,7 +10,7 @@ public class NativeApp { // These have Android semantics: Resume is always called on bootup, after init public static native void pause(); - public static native void resume(); + public static native void resume(); public static native void shutdown(); diff --git a/gfx/gl_lost_manager.cpp b/gfx/gl_lost_manager.cpp index 99a9776db9..1c2ed98262 100644 --- a/gfx/gl_lost_manager.cpp +++ b/gfx/gl_lost_manager.cpp @@ -1,13 +1,19 @@ -#include +#include #include "base/logging.h" #include "gfx/gl_lost_manager.h" -std::list *holders; +std::vector *holders; GfxResourceHolder::~GfxResourceHolder() {} +static bool inLost; + void register_gl_resource_holder(GfxResourceHolder *holder) { + if (inLost) { + FLOG("BAD: Should not call register_gl_resource_holder from lost path"); + return; + } if (holders) { holders->push_back(holder); } else { @@ -15,28 +21,43 @@ void register_gl_resource_holder(GfxResourceHolder *holder) { } } void unregister_gl_resource_holder(GfxResourceHolder *holder) { + if (inLost) { + FLOG("BAD: Should not call unregister_gl_resource_holder from lost path"); + return; + } if (holders) { - holders->remove(holder); + for (size_t i = 0; i < holders->size(); i++) { + if ((*holders)[i] == holder) { + holders->erase(holders->begin() + i); + return; + } + } + WLOG("unregister_gl_resource_holder: Resource not registered"); } else { WLOG("GL resource holder not initialized or already shutdown, cannot unregister resource"); } } void gl_lost() { + inLost = true; if (!holders) { WLOG("GL resource holder not initialized, cannot process lost request"); return; } - for (std::list::iterator iter = holders->begin(); iter != holders->end(); ++iter) { - (*iter)->GLLost(); + ILOG("gl_lost() restoring %i items:", (int)holders->size()); + for (size_t i = 0; i < holders->size(); i++) { + ILOG("GLLost(%i, %p)", i, holders->size(), (*holders)[i]); + (*holders)[i]->GLLost(); } + ILOG("gl_lost() completed restoring %i items:", (int)holders->size()); + inLost = false; } void gl_lost_manager_init() { if (holders) { FLOG("Double GL lost manager init"); } - holders = new std::list(); + holders = new std::vector(); } void gl_lost_manager_shutdown() { diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 79b9736926..77e5c353f4 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -29,6 +29,7 @@ void Texture::Destroy() { void Texture::GLLost() { ILOG("Reloading lost texture %s", filename_.c_str()); Load(filename_.c_str()); + ILOG("Reloaded lost texture %s", filename_.c_str()); } Texture::~Texture() { @@ -87,8 +88,9 @@ bool Texture::Load(const char *filename) { // They shouldn't really hurt anything else very much though. int len = strlen(filename); - char fn[256]; - strcpy(fn, filename); + char fn[1024]; + strncpy(fn, filename, sizeof(fn)); + fn[1023] = 0; bool zim = false; if (!strcmp("dds", &filename[len-3])) { strcpy(&fn[len-3], "zim"); @@ -119,11 +121,11 @@ bool Texture::Load(const char *filename) { } else #endif if (!strcmp("zim", &name[len-3])) { - if (!LoadZIM(name)) { + if (LoadZIM(name)) { + return true; + } else { LoadXOR(); return false; - } else { - return true; } } LoadXOR(); @@ -197,8 +199,11 @@ bool Texture::LoadZIM(const char *filename) { int flags; int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]); + ILOG("ZIM loaded: %i levels", num_levels); if (!num_levels) return false; + if (num_levels >= ZIM_MAX_MIP_LEVELS) + return false; width_ = width[0]; height_ = height[0]; int data_type = GL_UNSIGNED_BYTE; @@ -223,6 +228,9 @@ bool Texture::LoadZIM(const char *filename) { } GL_CHECK(); + + + ILOG("Gen-binding texture"); glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); SetTextureParameters(flags); diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 6cef2e0bcd..6e2545e001 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -32,12 +32,13 @@ DrawBuffer::~DrawBuffer() { delete [] verts_; } -void DrawBuffer::Init() { +void DrawBuffer::Init(bool registerAsHolder) { if (inited_) return; inited_ = true; glGenBuffers(1, (GLuint *)&vbo_); - register_gl_resource_holder(this); + if (registerAsHolder) + register_gl_resource_holder(this); } void DrawBuffer::Shutdown() { @@ -49,7 +50,7 @@ void DrawBuffer::Shutdown() { void DrawBuffer::GLLost() { inited_ = false; - Init(); + Init(false); } void DrawBuffer::Begin(DrawBufferMode dbmode) { diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 1ec42a847f..3ba0e7f001 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -51,7 +51,7 @@ public: void End(); // TODO: Enforce these. Now Init is autocalled and shutdown not called. - void Init(); + void Init(bool registerAsHolder = true); void Shutdown(); virtual void GLLost(); From ac86ea83bea7d0fac31b478bb1cda9d68908dffb Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 11 Mar 2013 00:24:40 +0100 Subject: [PATCH 0271/1445] Make it a bit easier to select stuff in lists. --- ui/ui.cpp | 6 +++++- ui/ui.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index 4c209d88be..14cd15e9db 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -280,6 +280,7 @@ void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, boo UIList::UIList() : scrollY(0.0f), startDragY(0.0f), dragFinger(-1), selected(-1) { + movedDistanceX = 0.0f; movedDistanceY = 0.0f; scrolling = false; inertiaY = 0.0f; @@ -292,14 +293,17 @@ void UIList::pointerDown(int pointer, float x, float y) { startScrollY = scrollY; startDragY = y; + movedDistanceX = 0.0f; movedDistanceY = 0.0f; } const int holdFrames = 6; void UIList::pointerMove(int pointer, float x, float y, bool inside) { + float deltaX = x - lastX; float deltaY = y - lastY; movedDistanceY += fabsf(deltaY); + movedDistanceX += fabsf(deltaX); if (inertiaY <= 0.0f && deltaY > 0.0f) { inertiaY = -deltaY; @@ -309,7 +313,7 @@ void UIList::pointerMove(int pointer, float x, float y, bool inside) { inertiaY = 0.8 * inertiaY + 0.2 * -deltaY; } - if (inside && movedDistanceY > 10 && !scrolling && uistate.mouseframesdown[0] > holdFrames) { + if (inside && movedDistanceY > 35 && movedDistanceY > movedDistanceX && !scrolling && uistate.mouseframesdown[0] > holdFrames) { scrolling = true; } } diff --git a/ui/ui.h b/ui/ui.h index aad8fa0675..e5d9dd55a6 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -220,6 +220,7 @@ public: float lastX; float lastY; float startDragY; + float movedDistanceX; float movedDistanceY; float inertiaY; From 99646849208340805dc6e2510ec342b2fcb5a0a7 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 11 Mar 2013 11:51:10 +1000 Subject: [PATCH 0272/1445] Add accelerometer support to Qt (Symbian-only for now) --- base/QtMain.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/base/QtMain.h b/base/QtMain.h index f54ae7c4b6..e44eaba1f4 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -8,6 +8,10 @@ #include #include +#ifdef __SYMBIAN32__ +#include +QTM_USE_NAMESPACE +#endif #include "base/display.h" #include "base/logging.h" @@ -50,8 +54,15 @@ public: QGLWidget(parent), dpi_scale(scale) { setAttribute(Qt::WA_AcceptTouchEvents); +#ifdef __SYMBIAN32__ + acc = new QAccelerometer(this); + acc->start(); +#endif } ~MainUI() { +#ifdef __SYMBIAN32__ + delete acc; +#endif NativeShutdownGraphics(); } @@ -126,6 +137,7 @@ protected: void paintGL() { SimulateGamepad(&input_state); + updateAccelerometer(); UpdateInputState(&input_state); NativeUpdate(input_state); EndInputState(&input_state); @@ -134,8 +146,24 @@ protected: update(); } + void updateAccelerometer() + { +#ifdef __SYMBIAN32__ + // TODO: Toggle it depending on whether it is enabled + QAccelerometerReading *reading = acc->reading(); + if (reading) { + input_state.acc.x = reading->x(); + input_state.acc.y = reading->y(); + input_state.acc.z = reading->z(); + } +#endif + } + private: InputState input_state; +#ifdef __SYMBIAN32__ + QAccelerometer* acc; +#endif float dpi_scale; }; From e0d107ad2063e6ec878e1b24889b9d949ee8d6a6 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 11 Mar 2013 22:04:06 +1000 Subject: [PATCH 0273/1445] Accelerometer support for Blackberry. --- base/BlackberryMain.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 2804f00597..fdb3f1cd36 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -27,14 +27,15 @@ #include "display.h" // Blackberry specific -#include // Blackberry Platform Services -#include // Blackberry Window Manager -#include // Invoke Service +#include // Blackberry Platform Services +#include // Blackberry Window Manager +#include // Invoke Service #include // Keyboard Service +#include // Accelerometer #include -#include // Dialog Service (Toast=BB10) +#include // Dialog Service (Toast=BB10) #ifdef BLACKBERRY10 -#include // Vibrate Service (BB10) +#include // Vibrate Service (BB10) #endif EGLDisplay egl_disp; @@ -355,6 +356,8 @@ int main(int argc, char *argv[]) { screen_create_context(&screen_cxt, 0); //Initialise Blackberry Platform Services bps_initialize(); + // TODO: Enable/disable based on setting + accelerometer_set_update_frequency(FREQ_40_HZ); net::Init(); init_GLES2(screen_cxt); @@ -464,6 +467,10 @@ int main(int argc, char *argv[]) { } } } + // Handle accelerometer + double x, y, z; + accelerometer_read_forces(&x, &y, &z); + input_state.acc.x = x; input_state.acc.y = y; input_state.acc.z = z; UpdateInputState(&input_state); NativeUpdate(input_state); EndInputState(&input_state); From 7f18e1faabd18381cf4a8ab85ff24bb6b9b7f89d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 11 Mar 2013 21:31:44 +0100 Subject: [PATCH 0274/1445] Add UTF8StringNonASCIICount --- util/text/utf8.cpp | 11 ++++++++--- util/text/utf8.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/util/text/utf8.cpp b/util/text/utf8.cpp index 10b239ea52..e77eb076bb 100644 --- a/util/text/utf8.cpp +++ b/util/text/utf8.cpp @@ -394,12 +394,17 @@ int u8_is_locale_utf8(const char *locale) return 0; } -bool UTF8StringHasNonASCII(const char *utf8string) { +int UTF8StringNonASCIICount(const char *utf8string) { UTF8 utf(utf8string); + int count = 0; while (!utf.end()) { int c = utf.next(); if (c > 127) - return true; + ++count; } - return false; + return count; +} + +bool UTF8StringHasNonASCII(const char *utf8string) { + return UTF8StringNonASCIICount(utf8string) > 0; } \ No newline at end of file diff --git a/util/text/utf8.h b/util/text/utf8.h index 84c2ae8c97..bd320979f8 100644 --- a/util/text/utf8.h +++ b/util/text/utf8.h @@ -35,4 +35,6 @@ private: int index_; }; +int UTF8StringNonASCIICount(const char *utf8string); + bool UTF8StringHasNonASCII(const char *utf8string); \ No newline at end of file From 1ec67d5ac2e52d2a1bc02b92645fefa78fca1e8b Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 12 Mar 2013 14:41:26 +1000 Subject: [PATCH 0275/1445] Use lowercase letters for mobile Qt UI --- base/QtMain.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index e44eaba1f4..34881a0876 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -24,12 +24,12 @@ QTM_USE_NAMESPACE // Input const int buttonMappings[18] = { - Qt::Key_X, //A - Qt::Key_S, //B - Qt::Key_Z, //X - Qt::Key_A, //Y - Qt::Key_W, //LBUMPER - Qt::Key_Q, //RBUMPER + Qt::Key_X + 0x20, //A + Qt::Key_S + 0x20, //B + Qt::Key_Z + 0x20, //X + Qt::Key_A + 0x20, //Y + Qt::Key_W + 0x20, //LBUMPER + Qt::Key_Q + 0x20, //RBUMPER Qt::Key_1, //START Qt::Key_2, //SELECT Qt::Key_Up, //UP @@ -38,10 +38,10 @@ const int buttonMappings[18] = { Qt::Key_Right, //RIGHT 0, //MENU (event) Qt::Key_Backspace, //BACK - Qt::Key_I, //JOY UP - Qt::Key_K, //JOY DOWN - Qt::Key_J, //JOY LEFT - Qt::Key_L, //JOY RIGHT + Qt::Key_I + 0x20, //JOY UP + Qt::Key_K + 0x20, //JOY DOWN + Qt::Key_J + 0x20, //JOY LEFT + Qt::Key_L + 0x20, //JOY RIGHT }; void SimulateGamepad(InputState *input); From e572fac401f73657298b16fdc3b68edfbcaabb3a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 15 Mar 2013 08:10:34 -0700 Subject: [PATCH 0276/1445] Minor warning fixes. --- gfx/gl_lost_manager.cpp | 2 +- gfx/texture_gen.cpp | 2 ++ image/zim_load.cpp | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/gfx/gl_lost_manager.cpp b/gfx/gl_lost_manager.cpp index 1c2ed98262..92d273706b 100644 --- a/gfx/gl_lost_manager.cpp +++ b/gfx/gl_lost_manager.cpp @@ -46,7 +46,7 @@ void gl_lost() { } ILOG("gl_lost() restoring %i items:", (int)holders->size()); for (size_t i = 0; i < holders->size(); i++) { - ILOG("GLLost(%i, %p)", i, holders->size(), (*holders)[i]); + ILOG("GLLost(%i / %i, %p)", (int) i, (int) holders->size(), (*holders)[i]); (*holders)[i]->GLLost(); } ILOG("gl_lost() completed restoring %i items:", (int)holders->size()); diff --git a/gfx/texture_gen.cpp b/gfx/texture_gen.cpp index 3a8209933d..673126de72 100644 --- a/gfx/texture_gen.cpp +++ b/gfx/texture_gen.cpp @@ -47,6 +47,8 @@ uint8_t *generateTexture(const char *filename, int &bpp, int &w, int &h, bool &c data[y*w + x] = val * 255; } } + } else { + data = NULL; } return data; diff --git a/image/zim_load.cpp b/image/zim_load.cpp index 6980e7b8bd..16162e4a9f 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -100,6 +100,12 @@ int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, total_data_size += image_data_size[i]; } + if (total_data_size == 0) + { + ELOG("Invalid ZIM data size 0"); + return 0; + } + image[0] = (uint8 *)malloc(total_data_size); for (int i = 1; i < num_levels; i++) { image[i] = image[i-1] + image_data_size[i-1]; From 93ec9dc2ba8bff27b66935e23167ac148d64d6b8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 15 Mar 2013 08:53:02 -0700 Subject: [PATCH 0277/1445] Adjust the deadzone for taps and swipes. Fixes #990, or does for me. --- ui/ui.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index 14cd15e9db..19f3d0ff9a 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -297,7 +297,8 @@ void UIList::pointerDown(int pointer, float x, float y) { movedDistanceY = 0.0f; } -const int holdFrames = 6; +const int holdFramesClick = 3; +const int holdFramesScroll = 10; void UIList::pointerMove(int pointer, float x, float y, bool inside) { float deltaX = x - lastX; @@ -313,7 +314,8 @@ void UIList::pointerMove(int pointer, float x, float y, bool inside) { inertiaY = 0.8 * inertiaY + 0.2 * -deltaY; } - if (inside && movedDistanceY > 35 && movedDistanceY > movedDistanceX && !scrolling && uistate.mouseframesdown[0] > holdFrames) { + const int deadzone = 30 * holdFramesScroll; + if (inside && movedDistanceY * uistate.mouseframesdown[0] > deadzone && !scrolling) { scrolling = true; } } @@ -407,7 +409,7 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { if (item_y >= y - itemHeight && item_y <= y + h) { for (int k = 0; k < 1; k++) { // MAX_POINTERS if we add back multitouch if (uistate.mousedown[k] && - uistate.mouseframesdown[k] >= holdFrames && + uistate.mouseframesdown[k] >= holdFramesClick && adapter->itemEnabled(i) && !scrolling && selected == -1 && From 21a7ee80fb2f31bfff1a739bce80ac8e5047952b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 15 Mar 2013 22:23:41 +0100 Subject: [PATCH 0278/1445] Add scissor rect to gl state --- gfx_es2/gl_state.cpp | 1 + gfx_es2/gl_state.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index b0e8fa0a17..6a50f648a7 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -22,6 +22,7 @@ void OpenGLState::Restore() { blendColor.restore(); count++; scissorTest.restore(); count++; + scissorRect.restore(); count++; cullFace.restore(); count++; cullFaceMode.restore(); count++; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 8ea0d5ee5c..2e325e0fbf 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -185,6 +185,8 @@ public: STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport; + STATE4(glScissor, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) scissorRect; + BoolState stencilTest; STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp; STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; From a0f4674f0bc86199865315d88bfe647a297d1b0e Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 20 Mar 2013 05:26:53 +1000 Subject: [PATCH 0279/1445] Use Qt to lock orientation instead of platform-specific code. --- base/QtMain.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 05d3f471ac..c103f02457 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -12,7 +12,7 @@ #include #ifdef __SYMBIAN32__ -#include +#include #endif #include "QtMain.h" @@ -41,7 +41,7 @@ float CalculateDPIScale() { // Sane default for Symbian, Blackberry and Meego #ifdef __SYMBIAN32__ - return 1.3f; + return 1.4f; #else return 1.2f; #endif @@ -54,8 +54,6 @@ int main(int argc, char *argv[]) #endif QApplication a(argc, argv); #ifdef __SYMBIAN32__ - // Lock orientation to landscape on Symbian - QT_TRAP_THROWING(dynamic_cast(CEikonEnv::Static()->AppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); // Set RunFast hardware mode for VFPv2. Denormalised values are treated as 0. NaN used for all NaN situations. User::SetFloatingPointMode(EFpModeRunFast); #endif @@ -79,6 +77,7 @@ int main(int argc, char *argv[]) #if defined(USING_GLES2) MainUI w(dpi_scale); + w.setAttribute(Qt::WA_LockLandscapeOrientation); w.resize(pixel_xres, pixel_yres); w.showFullScreen(); #endif From 3c160ecb5a848d67e2be5a165ae3a81ff8401fae Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 20 Mar 2013 08:49:50 +1000 Subject: [PATCH 0280/1445] Only run the UI on X11 for now until threads issue is resolved. --- base/QtMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index c103f02457..907aed1309 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -75,7 +75,7 @@ int main(int argc, char *argv[]) #endif NativeInit(argc, (const char **)argv, savegame_dir, QDir::tempPath().toStdString().c_str(), "BADCOFFEE"); -#if defined(USING_GLES2) +#ifndef Q_WS_X11 MainUI w(dpi_scale); w.setAttribute(Qt::WA_LockLandscapeOrientation); w.resize(pixel_xres, pixel_yres); From 9ef592a09faf46e733cc062d154aaf2483f8bcd1 Mon Sep 17 00:00:00 2001 From: Jamie Halpern Date: Thu, 21 Mar 2013 00:40:02 -0400 Subject: [PATCH 0281/1445] Jamie H - Updated the project version to 17 to support new APIs. Added a JNI call to allow for left joystick input from Java. Added in the key codes for the PS3 controller's X and O buttons. Joystick input for buttons is now suppressed in the NativeActivity class. --- android/app-android.cpp | 102 ++++++----- android/project.properties | 2 +- .../libnative/NativeActivity.java | 170 +++++++++++------- .../henrikrydgard/libnative/NativeApp.java | 26 +-- 4 files changed, 179 insertions(+), 121 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 6fdc010e8a..c2e28313b6 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -4,7 +4,6 @@ // It calls a set of methods defined in NativeApp.h. These should be implemented // by your game or app. - #include #include #include @@ -27,9 +26,11 @@ // For Xperia Play support enum AndroidKeyCodes { - KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed + KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed + KEYCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed KEYCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) - KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed + KEYCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed + KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed KEYCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed KEYCODE_DPAD_LEFT = 21, KEYCODE_DPAD_UP = 19, @@ -50,6 +51,8 @@ const bool extraLog = true; static uint32_t pad_buttons_async_set; static uint32_t pad_buttons_async_clear; +static float left_joystick_x_async; +static float left_joystick_y_async; // Android implementation of callbacks to the Java part of the app void SystemToast(const char *text) { @@ -254,6 +257,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN { lock_guard guard(input_state.lock); + input_state.pad_lstick_x = left_joystick_x_async; + input_state.pad_lstick_y = left_joystick_y_async; NativeUpdate(input_state); } @@ -337,50 +342,65 @@ static void AsyncUp(int padbutton) { extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) { switch (key) { - case 1: AsyncDown(PAD_BUTTON_BACK); break; // Back - case 2: AsyncDown(PAD_BUTTON_MENU); break; // Menu - case 3: AsyncDown(PAD_BUTTON_A); break; // Search - case KEYCODE_BUTTON_CROSS: AsyncDown(PAD_BUTTON_A); break; - case KEYCODE_BUTTON_CIRCLE: AsyncDown(PAD_BUTTON_B); break; - case KEYCODE_BUTTON_SQUARE: AsyncDown(PAD_BUTTON_X); break; - case KEYCODE_BUTTON_TRIANGLE: AsyncDown(PAD_BUTTON_Y); break; - case KEYCODE_DPAD_LEFT: AsyncDown(PAD_BUTTON_LEFT); break; - case KEYCODE_DPAD_UP: AsyncDown(PAD_BUTTON_UP); break; - case KEYCODE_DPAD_RIGHT: AsyncDown(PAD_BUTTON_RIGHT); break; - case KEYCODE_DPAD_DOWN: AsyncDown(PAD_BUTTON_DOWN); break; - case KEYCODE_BUTTON_L1: AsyncDown(PAD_BUTTON_LBUMPER); break; - case KEYCODE_BUTTON_R1: AsyncDown(PAD_BUTTON_RBUMPER); break; - case KEYCODE_BUTTON_START: AsyncDown(PAD_BUTTON_START); break; - case KEYCODE_BUTTON_SELECT: AsyncDown(PAD_BUTTON_SELECT); break; - default: - break; + case 1: AsyncDown (PAD_BUTTON_BACK); break; // Back + case 2: AsyncDown (PAD_BUTTON_MENU); break; // Menu + case 3: AsyncDown (PAD_BUTTON_A); break; // Search + case KEYCODE_BUTTON_CROSS: + case KEYCODE_BUTTON_CROSS_PS3: + AsyncDown(PAD_BUTTON_A); + break; + case KEYCODE_BUTTON_CIRCLE: + case KEYCODE_BUTTON_CIRCLE_PS3: + AsyncDown (PAD_BUTTON_B); + break; + case KEYCODE_BUTTON_SQUARE: AsyncDown (PAD_BUTTON_X); break; + case KEYCODE_BUTTON_TRIANGLE: AsyncDown (PAD_BUTTON_Y); break; + case KEYCODE_DPAD_LEFT: AsyncDown (PAD_BUTTON_LEFT); break; + case KEYCODE_DPAD_UP: AsyncDown (PAD_BUTTON_UP); break; + case KEYCODE_DPAD_RIGHT: AsyncDown (PAD_BUTTON_RIGHT); break; + case KEYCODE_DPAD_DOWN: AsyncDown (PAD_BUTTON_DOWN); break; + case KEYCODE_BUTTON_L1: AsyncDown (PAD_BUTTON_LBUMPER); break; + case KEYCODE_BUTTON_R1: AsyncDown (PAD_BUTTON_RBUMPER); break; + case KEYCODE_BUTTON_START: AsyncDown (PAD_BUTTON_START); break; + case KEYCODE_BUTTON_SELECT: AsyncDown (PAD_BUTTON_SELECT); break; + default: break; } } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) { switch (key) { - case 1: AsyncUp(PAD_BUTTON_BACK); break; // Back - case 2: AsyncUp(PAD_BUTTON_MENU); break; // Menu - case 3: AsyncUp(PAD_BUTTON_A); break; // Search - case KEYCODE_BUTTON_CROSS: AsyncUp(PAD_BUTTON_A); break; - case KEYCODE_BUTTON_CIRCLE: AsyncUp(PAD_BUTTON_B); break; - case KEYCODE_BUTTON_SQUARE: AsyncUp(PAD_BUTTON_X); break; - case KEYCODE_BUTTON_TRIANGLE: AsyncUp(PAD_BUTTON_Y); break; - case KEYCODE_DPAD_LEFT: AsyncUp(PAD_BUTTON_LEFT); break; - case KEYCODE_DPAD_UP: AsyncUp(PAD_BUTTON_UP); break; - case KEYCODE_DPAD_RIGHT: AsyncUp(PAD_BUTTON_RIGHT); break; - case KEYCODE_DPAD_DOWN: AsyncUp(PAD_BUTTON_DOWN); break; - case KEYCODE_BUTTON_L1: AsyncUp(PAD_BUTTON_LBUMPER); break; - case KEYCODE_BUTTON_R1: AsyncUp(PAD_BUTTON_RBUMPER); break; - case KEYCODE_BUTTON_START: AsyncUp(PAD_BUTTON_START); break; - case KEYCODE_BUTTON_SELECT: AsyncUp(PAD_BUTTON_SELECT); break; - default: - break; + case 1: AsyncUp (PAD_BUTTON_BACK); break; // Back + case 2: AsyncUp (PAD_BUTTON_MENU); break; // Menu + case 3: AsyncUp (PAD_BUTTON_A); break; // Search + case KEYCODE_BUTTON_CROSS: + case KEYCODE_BUTTON_CROSS_PS3: + AsyncUp(PAD_BUTTON_A); + break; + case KEYCODE_BUTTON_CIRCLE: + case KEYCODE_BUTTON_CIRCLE_PS3: + AsyncUp (PAD_BUTTON_B); + break; + case KEYCODE_BUTTON_SQUARE: AsyncUp (PAD_BUTTON_X); break; + case KEYCODE_BUTTON_TRIANGLE: AsyncUp (PAD_BUTTON_Y); break; + case KEYCODE_DPAD_LEFT: AsyncUp (PAD_BUTTON_LEFT); break; + case KEYCODE_DPAD_UP: AsyncUp (PAD_BUTTON_UP); break; + case KEYCODE_DPAD_RIGHT: AsyncUp (PAD_BUTTON_RIGHT); break; + case KEYCODE_DPAD_DOWN: AsyncUp (PAD_BUTTON_DOWN); break; + case KEYCODE_BUTTON_L1: AsyncUp (PAD_BUTTON_LBUMPER); break; + case KEYCODE_BUTTON_R1: AsyncUp (PAD_BUTTON_RBUMPER); break; + case KEYCODE_BUTTON_START: AsyncUp (PAD_BUTTON_START); break; + case KEYCODE_BUTTON_SELECT: AsyncUp (PAD_BUTTON_SELECT); break; + default: break; } } -extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer - (JNIEnv *, jclass, float x, float y, float z) { +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickEvent( + JNIEnv *env, jclass, jfloat x, jfloat y) { + left_joystick_x_async = x; + left_joystick_y_async = y; +} + +extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) { // Theoretically this needs locking but I doubt it matters. Worst case, the X // from one "sensor frame" will be used together with Y from the next. // Should look into quantization though, for compressed movement storage. @@ -390,8 +410,7 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer input_state.acc.z = z; } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage - (JNIEnv *env, jclass, jstring message, jstring param) { +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) { jboolean isCopy; std::string msg = GetJavaString(env, message); std::string prm = GetJavaString(env, param); @@ -399,4 +418,3 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage NativeMessageReceived(msg.c_str(), prm.c_str()); } - diff --git a/android/project.properties b/android/project.properties index 4cf07c9ec1..137f19ac6a 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt # Project target. -target=android-10 +target=android-17 android.library=true diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index bf71b7b221..37561fbfa9 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -1,4 +1,5 @@ package com.henrikrydgard.libnative; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -7,6 +8,7 @@ import java.lang.reflect.Field; import java.util.UUID; import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; @@ -29,8 +31,9 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.Gravity; +import android.view.InputDevice; import android.view.KeyEvent; -import android.view.View; +import android.view.MotionEvent; import android.view.Window; import android.view.WindowManager; import android.widget.EditText; @@ -135,12 +138,13 @@ public class NativeActivity extends Activity { String libraryDir = getApplicationLibraryDir(appInfo); File sdcard = Environment.getExternalStorageDirectory(); Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); + @SuppressWarnings("deprecation") int scrPixelFormat = display.getPixelFormat(); @SuppressWarnings("deprecation") int scrWidth = display.getWidth(); @SuppressWarnings("deprecation") int scrHeight = display.getHeight(); - float scrRefreshRate = (float)display.getRefreshRate(); + float scrRefreshRate = display.getRefreshRate(); String externalStorageDir = sdcard.getAbsolutePath(); String dataDir = this.getFilesDir().getAbsolutePath(); String apkFilePath = appInfo.sourceDir; @@ -236,69 +240,6 @@ public class NativeActivity extends Activity { public boolean overrideKeys() { return true; } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - // Eat these keys, to avoid accidental exits / other screwups. - // Maybe there's even more we need to eat on tablets? - switch (keyCode) { - case KeyEvent.KEYCODE_BACK: - if (event.isAltPressed()) { - NativeApp.keyDown(1004); // special custom keycode - } else { - NativeApp.keyDown(1); - } - return true; - case KeyEvent.KEYCODE_MENU: - NativeApp.keyDown(2); - return true; - case KeyEvent.KEYCODE_SEARCH: - NativeApp.keyDown(3); - return true; - case KeyEvent.KEYCODE_VOLUME_DOWN: - case KeyEvent.KEYCODE_VOLUME_UP: - return false; - default: - // send the rest of the keys through. - // TODO: get rid of the three special cases above by adjusting the native side of the code. - NativeApp.keyDown(keyCode); - return true; - } - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - // Eat these keys, to avoid accidental exits / other screwups. - // Maybe there's even more we need to eat on tablets? - switch (keyCode) { - case KeyEvent.KEYCODE_BACK: - if (event.isAltPressed()) { - NativeApp.keyUp(1004); // special custom keycode - } - else if (NativeApp.isAtTopLevel()) { - return false; - } else { - NativeApp.keyUp(1); - } - return true; - case KeyEvent.KEYCODE_MENU: - // Menu should be ignored from SDK 11 forwards. We send it to the app. - NativeApp.keyUp(2); - return true; - case KeyEvent.KEYCODE_SEARCH: - // Search probably should also be ignored. We send it to the app. - NativeApp.keyUp(3); - return true; - case KeyEvent.KEYCODE_VOLUME_DOWN: - case KeyEvent.KEYCODE_VOLUME_UP: - return false; - default: - // send the rest of the keys through. - // TODO: get rid of the three special cases above by adjusting the native side of the code. - NativeApp.keyUp(keyCode); - return true; - } - } // Prevent destroying and recreating the main activity when the device rotates etc, // since this would stop the sound. @@ -309,14 +250,107 @@ public class NativeActivity extends Activity { } public static boolean inputBoxCancelled; - @SuppressWarnings("deprecation") + + @SuppressLint("NewApi") + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + // Eat these keys, to avoid accidental exits / other screwups. + // Maybe there's even more we need to eat on tablets? + switch (keyCode) { + case KeyEvent.KEYCODE_BACK: + if (event.isAltPressed()) { + NativeApp.keyDown(1004); // special custom keycode + } else { + NativeApp.keyDown(1); + } + return true; + case KeyEvent.KEYCODE_MENU: + NativeApp.keyDown(2); + return true; + case KeyEvent.KEYCODE_SEARCH: + NativeApp.keyDown(3); + return true; + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_VOLUME_UP: + return false; + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + // Joysticks are supported in Honeycomb MR1 and later via the onGenericMotionEvent method. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && event.getSource() == InputDevice.SOURCE_JOYSTICK) { + return false; + } + default: + // send the rest of the keys through. + // TODO: get rid of the three special cases above by adjusting the native side of the code. + Log.d("JAMIE", "Key code: " + keyCode + ", KeyEvent: " + event); + NativeApp.keyDown(keyCode); + return true; + } + } + + @Override + @TargetApi(12) + public boolean onGenericMotionEvent(MotionEvent event) { + Log.d("JAMIE", "onGenericMotionEvent: " + event); + if (event.getSource() == InputDevice.SOURCE_JOYSTICK) { + float leftJoystickX = event.getAxisValue(MotionEvent.AXIS_X) * 1f; + float leftJoystickY = event.getAxisValue(MotionEvent.AXIS_Y) * -1f; + NativeApp.joystickEvent(leftJoystickX, leftJoystickY); + } + return false; + } + + @SuppressLint("NewApi") + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + // Eat these keys, to avoid accidental exits / other screwups. + // Maybe there's even more we need to eat on tablets? + Log.d("JAMIE", "KeyEvent: " + event); + switch (keyCode) { + case KeyEvent.KEYCODE_BACK: + if (event.isAltPressed()) { + NativeApp.keyUp(1004); // special custom keycode + } else if (NativeApp.isAtTopLevel()) { + return false; + } else { + NativeApp.keyUp(1); + } + return true; + case KeyEvent.KEYCODE_MENU: + // Menu should be ignored from SDK 11 forwards. We send it to the app. + NativeApp.keyUp(2); + return true; + case KeyEvent.KEYCODE_SEARCH: + // Search probably should also be ignored. We send it to the app. + NativeApp.keyUp(3); + return true; + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_VOLUME_UP: + return false; + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + // Joysticks are supported in Honeycomb MR1 and later via the onGenericMotionEvent method. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && event.getSource() == InputDevice.SOURCE_JOYSTICK) { + return false; + } + default: + // send the rest of the keys through. + // TODO: get rid of the three special cases above by adjusting the native side of the code. + NativeApp.keyUp(keyCode); + return true; + } + } public String inputBox(String title, String defaultText, String defaultAction) { final FrameLayout fl = new FrameLayout(this); final EditText input = new EditText(this); input.setGravity(Gravity.CENTER); inputBoxCancelled = false; - FrameLayout.LayoutParams editBoxLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); + FrameLayout.LayoutParams editBoxLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); editBoxLayout.setMargins(2, 20, 2, 20); fl.addView(input, editBoxLayout); @@ -327,11 +361,13 @@ public class NativeActivity extends Activity { .setView(fl) .setTitle(title) .setPositiveButton(defaultAction, new DialogInterface.OnClickListener(){ + @Override public void onClick(DialogInterface d, int which) { d.dismiss(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener(){ + @Override public void onClick(DialogInterface d, int which) { d.cancel(); NativeActivity.inputBoxCancelled = false; diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 7c119ae96a..4e02203621 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -1,28 +1,32 @@ package com.henrikrydgard.libnative; -public class NativeApp { - public static native void init( - int xxres, int yyres, int dpi, String apkPath, - String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); +public class NativeApp { + public static native void init(int xxres, int yyres, int dpi, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); public static native boolean isLandscape(); + public static native boolean isAtTopLevel(); - + // These have Android semantics: Resume is always called on bootup, after init public static native void pause(); + public static native void resume(); - + public static native void shutdown(); - + public static native void keyDown(int key); + public static native void keyUp(int key); + public static native void joystickEvent(float x, float y); + // will only be called between init() and shutdown() - public static native void audioRender(short [] buffer); - + public static native void audioRender(short[] buffer); + // Sensor/input data. These are asynchronous, beware! public static native void touch(float x, float y, int data, int pointerId); + public static native void accelerometer(float x, float y, float z); - + public static native void sendMessage(String msg, String arg); -} \ No newline at end of file +} From 4fef50245deeb14253372704684586aa85e9e21f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 21 Mar 2013 20:51:35 +0100 Subject: [PATCH 0282/1445] Include math_util in build --- Android.mk | 1 + math/math_util.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Android.mk b/Android.mk index 2d6d695c00..dc7b665d1f 100644 --- a/Android.mk +++ b/Android.mk @@ -29,6 +29,7 @@ LOCAL_SRC_FILES :=\ file/file_util.cpp \ file/zip_read.cpp \ json/json_writer.cpp \ + math/math_util.cpp \ math/curves.cpp \ math/lin/aabb.cpp.arm \ math/lin/plane.cpp.arm \ diff --git a/math/math_util.cpp b/math/math_util.cpp index bab216b95f..5284cb893e 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -17,7 +17,7 @@ unsigned int GenerateRandomNumber() { #include -#if defined(ARM) +#if defined(ARMV7) void EnableFZ() { @@ -42,12 +42,12 @@ void DisableFZ( ) void EnableFZ() { - - + // TODO } + void DisableFZ() { - + // TODO } #endif From c4b6067eeb5434bcba7547f2ac53e5499f91dcd5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 21 Mar 2013 22:50:24 +0100 Subject: [PATCH 0283/1445] Attempt at android build fix on the build server (old ndk?) --- Android.mk | 8 +++++++- net/http_client.cpp | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index dc7b665d1f..d7a64e92eb 100644 --- a/Android.mk +++ b/Android.mk @@ -59,17 +59,23 @@ LOCAL_SRC_FILES :=\ util/random/perlin.cpp \ util/text/utf8.cpp -LOCAL_CFLAGS := -O2 -DGL_GLEXT_PROTOTYPES -DARM -DUSING_GLES2 -fsigned-char -fno-strict-aliasing +LOCAL_CFLAGS := -O3 -DGL_GLEXT_PROTOTYPES -DUSING_GLES2 -fsigned-char -fno-strict-aliasing LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip #Portable native and separate code on android in future is easy you needs add files #by ($(target_arch_ABI),arquitecture (armeabi-v7a , armeabi , x86 , MIPS) + ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) LOCAL_SRC_FILES += math/math_util.cpp +LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM else ifeq ($(TARGET_ARCH_ABI),armeabi) LOCAL_SRC_FILES += math/math_utilarmv6.cpp +LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM +else ifeq ($(TARGET_ARCH_ABI),x86) +LOCAL_SRC_FILES += math/math_util.cpp +LOCAL_CFLAGS := $(LOCAL_CFLAGS) -D_M_IX86 endif include $(BUILD_STATIC_LIBRARY) diff --git a/net/http_client.cpp b/net/http_client.cpp index 882861eb7f..8c2964693a 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -3,6 +3,7 @@ #ifndef _WIN32 #include #include +#include #include #define closesocket close #else From 9ffb8ca766ac4550de6f49c4374cc1b9b34d6c20 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 21 Mar 2013 23:19:27 +0100 Subject: [PATCH 0284/1445] htons not available on x86 android on the build server, what? fix. --- net/http_client.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 8c2964693a..5f827fea29 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -31,6 +31,13 @@ Connection::~Connection() { Disconnect(); } +// For whatever crazy reason, htons isn't available on android x86 on the build server. so here we go. + +// TODO: Fix for big-endian +inline unsigned short myhtons(unsigned short x) { + return (x >> 8) | (x << 8); +} + bool Connection::Resolve(const char *host, int port) { CHECK_EQ(-1, (intptr_t)sock_); host_ = host; @@ -49,7 +56,7 @@ bool Connection::Resolve(const char *host, int port) { int tmpres = net::inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr))); CHECK_GE(tmpres, 0); // << "inet_pton failed"; CHECK_NE(0, tmpres); // << ip << " not a valid IP address"; - remote_.sin_port = htons(port); + remote_.sin_port = myhtons(port); free((void *)ip); return true; } From 5f000da0e558a95825c87bd0a84a59858099fe8b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 21 Mar 2013 23:32:13 +0100 Subject: [PATCH 0285/1445] Remove bad include sys/endian.h --- net/http_client.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 5f827fea29..739546af5d 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -3,7 +3,6 @@ #ifndef _WIN32 #include #include -#include #include #define closesocket close #else From 0fbb4c3905f35faa8dbecc72a15e8814c6507c9b Mon Sep 17 00:00:00 2001 From: Aapo Rantalainen Date: Fri, 22 Mar 2013 17:14:18 +0200 Subject: [PATCH 0286/1445] Maemo5 support. Almost same than PANDORA --- base/PCMain.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 5a2c6c5bac..1ac87e593d 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -33,8 +33,16 @@ #include "base/NativeApp.h" #include "net/resolve.h" + +#ifdef MAEMO +#define EGL +#endif + #ifdef PANDORA -// EGL2SDL for Pandora +#define EGL +#endif + +#ifdef EGL #include "EGL/egl.h" #include #include @@ -91,25 +99,30 @@ int8_t EGL_Open() { } int8_t EGL_Init() { - EGLConfig g_eglConfig[1] = {NULL}; + EGLConfig g_eglConfig; //[1] = {NULL}; EGLint g_numConfigs = 0; EGLint attrib_list[]= { +#ifdef PANDORA EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, +#endif EGL_DEPTH_SIZE, 16, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, 0, +#ifdef MAEMO + EGL_BUFFER_SIZE, 16, +#endif EGL_NONE}; const EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - EGLBoolean result = eglChooseConfig(g_eglDisplay, attrib_list, g_eglConfig[0], 1, &g_numConfigs); + EGLBoolean result = eglChooseConfig(g_eglDisplay, attrib_list, &g_eglConfig, 1, &g_numConfigs); if (result != EGL_TRUE || g_numConfigs == 0) EGL_ERROR("Unable to query for available configs.", true); - g_eglContext = eglCreateContext(g_eglDisplay, g_eglConfig[0], NULL, attributes); + g_eglContext = eglCreateContext(g_eglDisplay, g_eglConfig, NULL, attributes ); if (g_eglContext == EGL_NO_CONTEXT) EGL_ERROR("Unable to create GLES context!", true); // Get the SDL window handle @@ -355,7 +368,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } -#ifdef PANDORA +#ifdef EGL if (EGL_Open()) return 1; #endif @@ -380,7 +393,7 @@ int main(int argc, char *argv[]) { SDL_Quit(); return(2); } -#ifdef PANDORA +#ifdef EGL EGL_Init(); #endif @@ -525,7 +538,7 @@ int main(int argc, char *argv[]) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } -#ifdef PANDORA +#ifdef EGL eglSwapBuffers(g_eglDisplay, g_eglSurface); #else if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) @@ -553,7 +566,7 @@ int main(int argc, char *argv[]) { SDL_PauseAudio(1); SDL_CloseAudio(); NativeShutdown(); -#ifdef PANDORA +#ifdef EGL EGL_Close(); #endif SDL_Quit(); From 762d096cc0f9ec24fab4776591f7425ed199cfac Mon Sep 17 00:00:00 2001 From: Aapo Rantalainen Date: Mon, 25 Mar 2013 20:45:39 +0200 Subject: [PATCH 0287/1445] Maemo5: SDL_ShowCursor(SDL_DISABLE); Cursor flickered. And there are no use of cursor with touch screen. --- base/PCMain.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 1ac87e593d..4b1f1a8d73 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -398,6 +398,10 @@ int main(int argc, char *argv[]) { #endif SDL_WM_SetCaption(app_name_nice.c_str(), NULL); +#ifdef MAEMO + SDL_ShowCursor(SDL_DISABLE); +#endif + #ifndef USING_GLES2 if (GLEW_OK != glewInit()) { From b1bf596472cac8e00e2bf72801adb2e1f34b6ac3 Mon Sep 17 00:00:00 2001 From: tpu Date: Fri, 29 Mar 2013 14:12:56 +0800 Subject: [PATCH 0288/1445] define GLEW_STATIC to avoid warning --- ext/glew/GL/glew.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/glew/GL/glew.h b/ext/glew/GL/glew.h index f70103d118..68ffbd8b7d 100644 --- a/ext/glew/GL/glew.h +++ b/ext/glew/GL/glew.h @@ -175,6 +175,7 @@ typedef _W64 int ptrdiff_t; * GLEW_STATIC is defined for static library. * GLEW_BUILD is defined for building the DLL library. */ +#define GLEW_STATIC #ifdef GLEW_STATIC # define GLEWAPI extern From c6e8a64684388a9a322d198b0de32795e8263a6a Mon Sep 17 00:00:00 2001 From: tpu Date: Fri, 29 Mar 2013 14:16:16 +0800 Subject: [PATCH 0289/1445] using GL_EXT_framebuffer_objects instead of GL_ARB_framubuffer_objects. --- gfx_es2/fbo.cpp | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index b8bb99b9e4..c99fc0634c 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -46,7 +46,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F fbo->colorDepth = colorDepth; // Color texture is same everywhere - glGenFramebuffers(1, &fbo->handle); + glGenFramebuffersEXT(1, &fbo->handle); glGenTextures(1, &fbo->color_texture); // Create the surfaces. @@ -117,26 +117,30 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F fbo->stencil_buffer = 0; fbo->z_buffer = 0; // 24-bit Z, 8-bit stencil - glGenRenderbuffers(1, &fbo->z_stencil_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height); + //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height); // Bind it all together - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + //glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + + // When enable STENCIL, glCheckFramebufferStatusEXT will return GL_FRAMEBUFFER_UNSUPPORTED on GMA4500. + #endif - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); switch(status) { - case GL_FRAMEBUFFER_COMPLETE: + case GL_FRAMEBUFFER_COMPLETE_EXT: // ILOG("Framebuffer verified complete."); break; - case GL_FRAMEBUFFER_UNSUPPORTED: + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); break; default: @@ -144,24 +148,24 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F break; } // Unbind state we don't need - glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); glBindTexture(GL_TEXTURE_2D, 0); return fbo; } void fbo_unbind() { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); #ifdef IOS bindDefaultFBO(); #endif } void fbo_bind_as_render_target(FBO *fbo) { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); } void fbo_bind_for_read(FBO *fbo) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); } void fbo_bind_color_as_texture(FBO *fbo, int color) { @@ -169,13 +173,13 @@ void fbo_bind_color_as_texture(FBO *fbo, int color) { } void fbo_destroy(FBO *fbo) { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &fbo->handle); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, &fbo->handle); glDeleteTextures(1, &fbo->color_texture); - glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); + glDeleteRenderbuffersEXT(1, &fbo->z_stencil_buffer); delete fbo; } From 75e9af1379753f8654dbe2b22c70ce7481bfd012 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 29 Mar 2013 13:53:04 +0100 Subject: [PATCH 0290/1445] Switch out etcpack with the ZLIB licensed rg_etc1 library --- Android.mk | 2 + README.md | 4 +- ext/etcpack/README | 7 - ext/etcpack/etcdec.cpp | 418 -- ext/etcpack/etcdec.h | 9 - ext/etcpack/etcpack.cpp | 5730 ----------------------- ext/etcpack/etcpack.h | 26 - ext/etcpack/etctool.cpp | 1613 ------- ext/etcpack/image.cpp | 212 - ext/etcpack/image.h | 33 - ext/etcpack/license.txt | 69 - ext/etcpack/version_1_0_6.txt | 49 - ext/{etcpack => rg_etc1}/CMakeLists.txt | 0 ext/rg_etc1/rg_etc1.cpp | 2442 ++++++++++ ext/rg_etc1/rg_etc1.h | 76 + gfx/texture.cpp | 6 +- image/zim_load.h | 4 + image/zim_save.cpp | 20 +- native.vcxproj | 6 +- native.vcxproj.filters | 18 +- tools/zimtool.cpp | 2 + 21 files changed, 2556 insertions(+), 8190 deletions(-) delete mode 100644 ext/etcpack/README delete mode 100644 ext/etcpack/etcdec.cpp delete mode 100644 ext/etcpack/etcdec.h delete mode 100644 ext/etcpack/etcpack.cpp delete mode 100644 ext/etcpack/etcpack.h delete mode 100644 ext/etcpack/etctool.cpp delete mode 100644 ext/etcpack/image.cpp delete mode 100644 ext/etcpack/image.h delete mode 100644 ext/etcpack/license.txt delete mode 100644 ext/etcpack/version_1_0_6.txt rename ext/{etcpack => rg_etc1}/CMakeLists.txt (100%) create mode 100644 ext/rg_etc1/rg_etc1.cpp create mode 100644 ext/rg_etc1/rg_etc1.h diff --git a/Android.mk b/Android.mk index d7a64e92eb..e20ce9c897 100644 --- a/Android.mk +++ b/Android.mk @@ -16,6 +16,7 @@ LOCAL_SRC_FILES :=\ base/colorutil.cpp \ base/error_context.cpp \ base/stringutil.cpp \ + ext/rg_etc1/rg_etc1.cpp \ ext/cityhash/city.cpp \ ext/sha1/sha1.cpp \ ext/stb_image/stb_image.c \ @@ -51,6 +52,7 @@ LOCAL_SRC_FILES :=\ gfx/texture_atlas.cpp \ gfx/texture_gen.cpp \ image/zim_load.cpp \ + image/zim_save.cpp \ image/png_load.cpp \ ui/ui.cpp \ ui/ui_context.cpp \ diff --git a/README.md b/README.md index 0e2cd18456..fb9f428c97 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Features * JSON read/write (two libraries that should be made more similar) * basic OpenGL utility code, like compressed texture loading * 2D texture atlases and drawing code -* ETC1 texture loading support +* ETC1 texture save/load support * basic logging * Really simple audio mixer with OGG sample support * RIFF file read/write @@ -29,7 +29,7 @@ Licenses This library, for my convenience, incorporates code from a variety of public domain or similarly-licensed code. This is the list: * glew (GL extension wrangler), MIT license. TODO: should just use a submodule. -* etcpack by Ericsson, in a cleaned up form. Has strange license but not very limiting - you can only use the code for making textures for hardware supporting ETC1, or something like that. Don't think it affects the rest of the code in any way. +* rg_etc1. ZLIB license. * sha1, public domain implementation by Dominik Reichl * vjson in a heavily modified form, originally by Ivan Vashchaev (TODO: break out into its own repo?) * libzip with attribution "Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner" diff --git a/ext/etcpack/README b/ext/etcpack/README deleted file mode 100644 index d3fbabb1eb..0000000000 --- a/ext/etcpack/README +++ /dev/null @@ -1,7 +0,0 @@ -This folder contains code adapted from etcpack by ERICSSON ///. - -The license comments have been left at the top of each file, but some code may have moved around. - -See LICENSE.TXT for details. It says that use of the code is limited to applications using the -code to compress textures for use with a Khronos-derived API. This game engine only supports -OpenGL ES 2.0, which certainly qualifies, so there is no issue there. diff --git a/ext/etcpack/etcdec.cpp b/ext/etcpack/etcdec.cpp deleted file mode 100644 index e19e48d54b..0000000000 --- a/ext/etcpack/etcdec.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/** - -@~English -@page licensing Licensing - -@section etcdec etcdec.cxx License - -etcdec.cxx is made available under the terms and conditions of the following -License Agreement. - -SOFTWARE LICENSE AGREEMENT - -PLEASE REVIEW THE FOLLOWING TERMS AND CONDITIONS PRIOR TO USING THE -ERICSSON TEXTURE COMPRESSION CODEC SOFTWARE (THE "SOFTWARE"). THE USE -OF THE SOFTWARE IS SUBJECT TO THE TERMS AND CONDITIONS OF THE -FOLLOWING LICENSE AGREEMENT (THE "LICENSE AGREEMENT"). IF YOU DO NOT -ACCEPT SUCH TERMS AND CONDITIONS YOU MAY NOT USE THE SOFTWARE. - -Under the terms and conditions of the License Agreement, Licensee -hereby, receives a non-exclusive, non transferable, limited, free of -charge, perpetual and worldwide license, to copy, use, distribute and -modify the Software, but only for the purpose of developing, -manufacturing, selling, using and distributing products including the -Software, which products are used for (i) compression and/or -decompression to create content creation tools for usage with a -Khronos API, and/or (ii) compression and/or decompression for the -purpose of usage with a middleware API that is built on top of a -Khronos API, such as JCPs based on a Khronos API (in particular -"Mobile 3D Graphics API for J2ME" and its future versions and "Java -Bindings for OpenGL ES" and its future versions), and/or (iii) -compression and/or decompression to implement a Khronos specification. - -If Licensee institutes patent litigation against Ericsson or any -licensee of the Software for using the Software for making, -developing, manufacturing, selling, using and/or distributing products -within the scope of the Khronos framework, Ericsson shall have the -right to terminate this License Agreement with immediate -effect. However, should Licensee institute patent litigation against -any other licensee of the Software based on such licenseeŽs use of any -other software distributed together with the Software then Ericsson -shall have no right to terminate this License Agreement. - -The License Agreement does not transfer to Licensee any ownership to -any Ericsson or third party intellectual property rights. - -THE SOFTWARE IS PROVIDED "AS IS". ERICSSON MAKES NO REPRESENTATIONS OF -ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND, EITHER EXPRESS OR -IMPLIED; INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK -AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH THE -LICENSEE. SHOULD THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE ASSUMES -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON -MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, DISTRIBUTION, LEASE, USE -OR IMPORTATION UNDER THE LICENSE AGREEMENT WILL BE FREE FROM -INFRINGEMENT OF PATENTS, COPYRIGHTS OR OTHER INTELLECTUAL PROPERTY -RIGHTS OF OTHERS, AND THE VALIDITY OF THE LICENSE AND THE LICENSE -AGREEMENT IS SUBJECT TO LICENSEE'S SOLE RESPONSIBILITY TO MAKE SUCH -DETERMINATION AND ACQUIRE SUCH LICENSES AS MAY BE NECESSARY WITH -RESPECT TO PATENTS AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES. - -IN NO EVENT WILL ERICSSON BE LIABLE TO THE LICENSEE FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT -NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR -LOSSES SUSTAINED BY THE LICENSEE OR THIRD PARTIES OR A FAILURE OF THE -SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR -OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -Licensee acknowledges that "ERICSSON ///" is the corporate trademark -of Telefonaktiebolaget LM Ericsson and that both "Ericsson" and the -figure "///" are important features of the trade names of -Telefonaktiebolaget LM Ericsson. Nothing contained in these terms and -conditions shall be deemed to grant Licensee any right, title or -interest in the word "Ericsson" or the figure "///". - -The parties agree that this License Agreement based on these terms and -conditions is governed by the laws of Sweden, and in the event of any -dispute as a result of this License Agreement, the parties submit -themselves to the exclusive jurisdiction of the Swedish Courts. -*/ - -#include -#include - -#define CLAMP(ll,x,ul) (((x)<(ll)) ? (ll) : (((x)>(ul)) ? (ul) : (x))) -#define GETBITS(source, size, startpos) (( (source) >> ((startpos)-(size)+1) ) & ((1<<(size)) -1)) -#define GETBITSHIGH(source, size, startpos) (( (source) >> (((startpos)-32)-(size)+1) ) & ((1<<(size)) -1)) -#define RED(img,width,x,y) img[3*(y*width+x)+0] -#define GREEN(img,width,x,y) img[3*(y*width+x)+1] -#define BLUE(img,width,x,y) img[3*(y*width+x)+2] - -typedef unsigned char uint8; - -int unscramble[4] = {2, 3, 1, 0}; - -static const int compressParams[16][4] = {{-8, -2, 2, 8}, {-8, -2, 2, 8}, {-17, -5, 5, 17}, {-17, -5, 5, 17}, {-29, -9, 9, 29}, {-29, -9, 9, 29}, {-42, -13, 13, 42}, {-42, -13, 13, 42}, {-60, -18, 18, 60}, {-60, -18, 18, 60}, {-80, -24, 24, 80}, {-80, -24, 24, 80}, {-106, -33, 33, 106}, {-106, -33, 33, 106}, {-183, -47, 47, 183}, {-183, -47, 47, 183}}; - -void decompressBlockDiffFlip(unsigned int block_part1, unsigned int block_part2, uint8 *img,int width,int height,int startx,int starty) -{ - uint8 avg_color[3], enc_color1[3], enc_color2[3]; - char diff[3]; - int table; - int index,shift; - int r,g,b; - int diffbit; - int flipbit; - unsigned int pixel_indices_MSB, pixel_indices_LSB; - int x,y; - - diffbit = (GETBITSHIGH(block_part1, 1, 33)); - flipbit = (GETBITSHIGH(block_part1, 1, 32)); - - if( !diffbit ) - { - - // We have diffbit = 0. - - // First decode left part of block. - avg_color[0]= GETBITSHIGH(block_part1, 4, 63); - avg_color[1]= GETBITSHIGH(block_part1, 4, 55); - avg_color[2]= GETBITSHIGH(block_part1, 4, 47); - - // Here, we should really multiply by 17 instead of 16. This can - // be done by just copying the four lower bits to the upper ones - // while keeping the lower bits. - avg_color[0] |= (avg_color[0] <<4); - avg_color[1] |= (avg_color[1] <<4); - avg_color[2] |= (avg_color[2] <<4); - - table = GETBITSHIGH(block_part1, 3, 39) << 1; - - - - pixel_indices_MSB = GETBITS(block_part2, 16, 31); - pixel_indices_LSB = GETBITS(block_part2, 16, 15); - - if( (flipbit) == 0 ) - { - // We should not flip - shift = 0; - for(x=startx; x> shift) & 1) << 1; - index |= ((pixel_indices_LSB >> shift) & 1); - shift++; - index=unscramble[index]; - - r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); - g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); - b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); - - - } - } - } - else - { - // We should flip - shift = 0; - for(x=startx; x> shift) & 1) << 1; - index |= ((pixel_indices_LSB >> shift) & 1); - shift++; - index=unscramble[index]; - - r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); - g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); - b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); - } - shift+=2; - } - } - - // Now decode other part of block. - avg_color[0]= GETBITSHIGH(block_part1, 4, 59); - avg_color[1]= GETBITSHIGH(block_part1, 4, 51); - avg_color[2]= GETBITSHIGH(block_part1, 4, 43); - - // Here, we should really multiply by 17 instead of 16. This can - // be done by just copying the four lower bits to the upper ones - // while keeping the lower bits. - avg_color[0] |= (avg_color[0] <<4); - avg_color[1] |= (avg_color[1] <<4); - avg_color[2] |= (avg_color[2] <<4); - - table = GETBITSHIGH(block_part1, 3, 36) << 1; - pixel_indices_MSB = GETBITS(block_part2, 16, 31); - pixel_indices_LSB = GETBITS(block_part2, 16, 15); - - if( (flipbit) == 0 ) - { - // We should not flip - shift=8; - for(x=startx+2; x> shift) & 1) << 1; - index |= ((pixel_indices_LSB >> shift) & 1); - shift++; - index=unscramble[index]; - - r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); - g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); - b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); - - } - } - } - else - { - // We should flip - shift=2; - for(x=startx; x> shift) & 1) << 1; - index |= ((pixel_indices_LSB >> shift) & 1); - shift++; - index=unscramble[index]; - - r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); - g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); - b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); - - } - shift += 2; - } - } - - } - else - { - // We have diffbit = 1. - -// 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 -// --------------------------------------------------------------------------------------------------- -// | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| -// | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | -// --------------------------------------------------------------------------------------------------- -// -// -// c) bit layout in bits 31 through 0 (in both cases) -// -// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -// -------------------------------------------------------------------------------------------------- -// | most significant pixel index bits | least significant pixel index bits | -// | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | -// -------------------------------------------------------------------------------------------------- - - - // First decode left part of block. - enc_color1[0]= GETBITSHIGH(block_part1, 5, 63); - enc_color1[1]= GETBITSHIGH(block_part1, 5, 55); - enc_color1[2]= GETBITSHIGH(block_part1, 5, 47); - - - // Expand from 5 to 8 bits - avg_color[0] = (enc_color1[0] <<3) | (enc_color1[0] >> 2); - avg_color[1] = (enc_color1[1] <<3) | (enc_color1[1] >> 2); - avg_color[2] = (enc_color1[2] <<3) | (enc_color1[2] >> 2); - - - table = GETBITSHIGH(block_part1, 3, 39) << 1; - - pixel_indices_MSB = GETBITS(block_part2, 16, 31); - pixel_indices_LSB = GETBITS(block_part2, 16, 15); - - if( (flipbit) == 0 ) - { - // We should not flip - shift = 0; - for(x=startx; x> shift) & 1) << 1; - index |= ((pixel_indices_LSB >> shift) & 1); - shift++; - index=unscramble[index]; - - r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); - g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); - b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); - - - } - } - } - else - { - // We should flip - shift = 0; - for(x=startx; x> shift) & 1) << 1; - index |= ((pixel_indices_LSB >> shift) & 1); - shift++; - index=unscramble[index]; - - r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); - g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); - b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); - } - shift+=2; - } - } - - - // Now decode right part of block. - - - diff[0]= GETBITSHIGH(block_part1, 3, 58); - diff[1]= GETBITSHIGH(block_part1, 3, 50); - diff[2]= GETBITSHIGH(block_part1, 3, 42); - - enc_color2[0]= enc_color1[0] + diff[0]; - enc_color2[1]= enc_color1[1] + diff[1]; - enc_color2[2]= enc_color1[2] + diff[2]; - - // Extend sign bit to entire byte. - diff[0] = (diff[0] << 5); - diff[1] = (diff[1] << 5); - diff[2] = (diff[2] << 5); - diff[0] = diff[0] >> 5; - diff[1] = diff[1] >> 5; - diff[2] = diff[2] >> 5; - - // Calculale second color - enc_color2[0]= enc_color1[0] + diff[0]; - enc_color2[1]= enc_color1[1] + diff[1]; - enc_color2[2]= enc_color1[2] + diff[2]; - - // Expand from 5 to 8 bits - avg_color[0] = (enc_color2[0] <<3) | (enc_color2[0] >> 2); - avg_color[1] = (enc_color2[1] <<3) | (enc_color2[1] >> 2); - avg_color[2] = (enc_color2[2] <<3) | (enc_color2[2] >> 2); - - - table = GETBITSHIGH(block_part1, 3, 36) << 1; - pixel_indices_MSB = GETBITS(block_part2, 16, 31); - pixel_indices_LSB = GETBITS(block_part2, 16, 15); - - if( (flipbit) == 0 ) - { - // We should not flip - shift=8; - for(x=startx+2; x> shift) & 1) << 1; - index |= ((pixel_indices_LSB >> shift) & 1); - shift++; - index=unscramble[index]; - - r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); - g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); - b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); - - } - } - } - else - { - // We should flip - shift=2; - for(x=startx; x> shift) & 1) << 1; - index |= ((pixel_indices_LSB >> shift) & 1); - shift++; - index=unscramble[index]; - - r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255); - g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255); - b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255); - } - shift += 2; - } - } - } -} - -static int bswap(unsigned int x) { - return ((x & 0xFF000000) >> 24) | - ((x & 0x00FF0000) >> 8) | - ((x & 0x0000FF00) << 8) | - ((x & 0x000000FF) << 24); -} - -void DecompressBlock(const uint8 *compressed, uint8 *out, int out_width, int alpha=255) { - uint8 rgb[4*4*3]; - unsigned int block_part1, block_part2; - memcpy(&block_part1, compressed, 4); - memcpy(&block_part2, compressed + 4, 4); - block_part1 = bswap(block_part1); - block_part2 = bswap(block_part2); - decompressBlockDiffFlip(block_part1, block_part2, rgb, 4, 4, 0, 0); - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - out[(y * out_width + x) * 4 + 0] = rgb[(4 * y + x) * 3 + 0]; - out[(y * out_width + x) * 4 + 1] = rgb[(4 * y + x) * 3 + 1]; - out[(y * out_width + x) * 4 + 2] = rgb[(4 * y + x) * 3 + 2]; - out[(y * out_width + x) * 4 + 3] = alpha; - } - } -} diff --git a/ext/etcpack/etcdec.h b/ext/etcpack/etcdec.h deleted file mode 100644 index 5a0ac6e5bb..0000000000 --- a/ext/etcpack/etcdec.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -typedef unsigned char uint8; - -/* In etcdec.cxx */ -void decompressBlockDiffFlip(unsigned int block_part1, unsigned int block_part2, uint8 *img,int width,int height,int startx,int starty); - -// Writes RGBA output instead of RGB. -void DecompressBlock(const uint8 *compressed, uint8 *out, int out_width, int alpha=255); diff --git a/ext/etcpack/etcpack.cpp b/ext/etcpack/etcpack.cpp deleted file mode 100644 index 3cf9feb7e0..0000000000 --- a/ext/etcpack/etcpack.cpp +++ /dev/null @@ -1,5730 +0,0 @@ -// Modified by Henrik RydgÃ¥rd: -// -// * Moved many I/O and similar functions to etctool.cpp, this file -// should only concern itself with compression. -// * got rid of readCompress.. - - - -// etcpack.cxx v1.06 -// -// NO WARRANTY -// -// BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, ERICSSON MAKES NO -// REPRESENTATIONS OF ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND; EITHER -// EXPRESS OR IMPLIED; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -// PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME -// THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON -// MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, LEASE, USE OR -// IMPORTATION WILL BE FREE FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR -// OTHER INTELLECTUAL PROPERTY RIGHTS OF OTHERS, AND IT SHALL BE THE SOLE -// RESPONSIBILITY OF THE LICENSEE TO MAKE SUCH DETERMINATION AS IS -// NECESSARY WITH RESPECT TO THE ACQUISITION OF LICENSES UNDER PATENTS -// AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES; -// -// IN NO EVENT WILL ERICSSON, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -// GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF -// THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO -// LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -// YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY -// OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGES. -// -// (C) Ericsson AB 2005. All Rights Reserved. -// - -#include -#include - -#include "etcpack.h" -#include "etcdec.h" - - - -#define CLAMP(ll,x,ul) (((x)<(ll)) ? (ll) : (((x)>(ul)) ? (ul) : (x))) -#define GETBITS(source, size, startpos) (( (source) >> ((startpos)-(size)+1) ) & ((1<<(size)) -1)) -#define GETBITSHIGH(source, size, startpos) (( (source) >> (((startpos)-32)-(size)+1) ) & ((1<<(size)) -1)) - -#define SQUARE(x) ((x)*(x)) -#define JAS_ROUND(x) (((x) < 0.0 ) ? ((int)((x)-0.5)) : ((int)((x)+0.5))) - -#define RED(img,width,x,y) img[3*(y*width+x)+0] -#define GREEN(img,width,x,y) img[3*(y*width+x)+1] -#define BLUE(img,width,x,y) img[3*(y*width+x)+2] - - -// SLOW SCAN RANGE IS -5 to 5 in all three colors -#define SLOW_SCAN_MIN (-5) -#define SLOW_SCAN_MAX (5) -#define SLOW_SCAN_RANGE ((SLOW_SCAN_MAX-(SLOW_SCAN_MIN)+1)) -#define SLOW_SCAN_OFFSET (-(SLOW_SCAN_MIN)) -// We need this to guarrantee that at least one try is valid -#define SLOW_TRY_MIN (-4 - SLOW_SCAN_MAX) -#define SLOW_TRY_MAX (3 - (SLOW_SCAN_MIN)) - - -// MEDIUM SCAN RANGE IS -3 to 3in all three colors -#define MEDIUM_SCAN_MIN (-3) -#define MEDIUM_SCAN_MAX (3) -#define MEDIUM_SCAN_RANGE ((MEDIUM_SCAN_MAX-(MEDIUM_SCAN_MIN)+1)) -#define MEDIUM_SCAN_OFFSET (-(MEDIUM_SCAN_MIN)) - -// We need this to guarrantee that at least one try is valid -#define MEDIUM_TRY_MIN (-4 - MEDIUM_SCAN_MAX) -#define MEDIUM_TRY_MAX (3 - (MEDIUM_SCAN_MIN)) - - -#define PUTBITS( dest, data, size, startpos) dest |= ( (data) & ((1<<(size))-1) ) << ((startpos)-(size)+1) -#define PUTBITSHIGH( dest, data, size, startpos) dest |= ( (data) & ((1<<(size))-1) ) << (((startpos)-32)-(size)+1) - -int scramble[4] = {3, 2, 0, 1}; - -static const int compressParamsEnc[16][4] = { - { -8, -2, 2, 8 }, - { -8, -2, 2, 8 }, - { -17, -5, 5, 17 }, - { -17, -5, 5, 17 }, - { -29, -9, 9, 29 }, - { -29, -9, 9, 29 }, - { -42, -13, 13, 42 }, - { -42, -13, 13, 42 }, - { -60, -18, 18, 60 }, - { -60, -18, 18, 60 }, - { -80, -24, 24, 80 }, - { -80, -24, 24, 80 }, - {-106, -33, 33,106 }, - {-106, -33, 33,106 }, - {-183, -47, 47,183 }, - {-183, -47, 47,183 }, -}; - -void computeAverageColor2x4noQuantFloat(uint8 *img,int width,int height,int startx,int starty,float *avg_color) { - int r=0,g=0,b=0; - for(int y=starty; y> 1), 1, i); - PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); - - i++; - - // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} - // so that first bit is sign bit and the other bit is size bit (4 or 12). - // This means that we have to scramble the bits before storing them. - - - sum_error+=min_error; - } - - } - - *pixel_indices_MSBp = pixel_indices_MSB; - *pixel_indices_LSBp = pixel_indices_LSB; - - return sum_error; -} - -float compressBlockWithTable2x4percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp) -{ - uint8 orig[3],approx[3]; - unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0; - float sum_error=0; - int q, i; - - double wR2 = PERCEPTUAL_WEIGHT_R_SQUARED; - double wG2 = PERCEPTUAL_WEIGHT_G_SQUARED; - double wB2 = PERCEPTUAL_WEIGHT_B_SQUARED; - - i = 0; - for(int x=startx; x> 1), 1, i); - PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); - - i++; - - // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} - // so that first bit is sign bit and the other bit is size bit (4 or 12). - // This means that we have to scramble the bits before storing them. - - - sum_error+=min_error; - } - - } - - *pixel_indices_MSBp = pixel_indices_MSB; - *pixel_indices_LSBp = pixel_indices_LSB; - - return sum_error; -} -int compressBlockWithTable4x2(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp) -{ - uint8 orig[3],approx[3]; - unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0; - int sum_error=0; - int q; - int i; - - - i = 0; - for(int x=startx; x> 1), 1, i); - PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); - i++; - - // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} - // so that first bit is sign bit and the other bit is size bit (4 or 12). - // This means that we have to scramble the bits before storing them. - - sum_error+=min_error; - } - i+=2; - - } - - *pixel_indices_MSBp = pixel_indices_MSB; - *pixel_indices_LSBp = pixel_indices_LSB; - - - return sum_error; -} - -float compressBlockWithTable4x2percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color,int table,unsigned int *pixel_indices_MSBp, unsigned int *pixel_indices_LSBp) -{ - uint8 orig[3],approx[3]; - unsigned int pixel_indices_MSB=0, pixel_indices_LSB=0, pixel_indices = 0; - float sum_error=0; - int q; - int i; - float wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED; - float wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED; - float wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED; - - - i = 0; - for(int x=startx; x> 1), 1, i); - PUTBITS( pixel_indices_LSB, (pixel_indices & 1) , 1, i); - i++; - - // In order to simplify hardware, the table {-12, -4, 4, 12} is indexed {11, 10, 00, 01} - // so that first bit is sign bit and the other bit is size bit (4 or 12). - // This means that we have to scramble the bits before storing them. - - sum_error+=min_error; - } - i+=2; - - } - - *pixel_indices_MSBp = pixel_indices_MSB; - *pixel_indices_LSBp = pixel_indices_LSB; - - - return sum_error; -} - -int tryalltables_3bittable2x4(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) -{ - int min_error = 3*255*255*16; - int q; - int err; - unsigned int pixel_indices_MSB, pixel_indices_LSB; - - for(q=0;q<16;q+=2) // try all the 8 tables. - { - - err=compressBlockWithTable2x4(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); - - if(err> 1; - - } - } - return min_error; -} - -int tryalltables_3bittable2x4percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) -{ - float min_error = 3*255*255*16; - int q; - float err; - unsigned int pixel_indices_MSB, pixel_indices_LSB; - - for(q=0;q<16;q+=2) // try all the 8 tables. - { - - err=compressBlockWithTable2x4percep(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); - - if(err> 1; - - } - } - return (int) min_error; -} - -int tryalltables_3bittable4x2(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) -{ - int min_error = 3*255*255*16; - int q; - int err; - unsigned int pixel_indices_MSB, pixel_indices_LSB; - - for(q=0;q<16;q+=2) // try all the 8 tables. - { - - err=compressBlockWithTable4x2(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); - - if(err> 1; - } - } - - return min_error; -} -int tryalltables_3bittable4x2percep(uint8 *img,int width,int height,int startx,int starty,uint8 *avg_color, unsigned int &best_table,unsigned int &best_pixel_indices_MSB, unsigned int &best_pixel_indices_LSB) -{ - float min_error = 3*255*255*16; - int q; - float err; - unsigned int pixel_indices_MSB, pixel_indices_LSB; - - for(q=0;q<16;q+=2) // try all the 8 tables. - { - - err=compressBlockWithTable4x2percep(img,width,height,startx,starty,avg_color,q,&pixel_indices_MSB, &pixel_indices_LSB); - - if(err> 1; - } - } - - return (int) min_error; -} - -// The below code quantizes a float RGB value to RGB555. -// - -void quantize444ColorCombined(float *avg_col_in, int *enc_color, uint8 *avg_color) -{ - // Detta ar nummer tva - float dr, dg, db; - float kr, kg, kb; - float wR2, wG2, wB2; - uint8 low_color[3]; - uint8 high_color[3]; - float lowhightable[8]; - int q; - float kval = (float) (255.0/15.0); - - - // These are the values that we want to have: - float red_average, green_average, blue_average; - - int red_4bit_low, green_4bit_low, blue_4bit_low; - int red_4bit_high, green_4bit_high, blue_4bit_high; - - // These are the values that we approximate with: - int red_low, green_low, blue_low; - int red_high, green_high, blue_high; - - red_average = avg_col_in[0]; - green_average = avg_col_in[1]; - blue_average = avg_col_in[2]; - - // Find the 5-bit reconstruction levels red_low, red_high - // so that red_average is in interval [red_low, red_high]. - // (The same with green and blue.) - - red_4bit_low = (int) (red_average/kval); - green_4bit_low = (int) (green_average/kval); - blue_4bit_low = (int) (blue_average/kval); - - red_4bit_high = CLAMP(0, red_4bit_low + 1, 15); - green_4bit_high = CLAMP(0, green_4bit_low + 1, 15); - blue_4bit_high = CLAMP(0, blue_4bit_low + 1, 15); - - red_low = (red_4bit_low << 4) | (red_4bit_low >> 0); - green_low = (green_4bit_low << 4) | (green_4bit_low >> 0); - blue_low = (blue_4bit_low << 4) | (blue_4bit_low >> 0); - - red_high = (red_4bit_high << 4) | (red_4bit_high >> 0); - green_high = (green_4bit_high << 4) | (green_4bit_high >> 0); - blue_high = (blue_4bit_high << 4) | (blue_4bit_high >> 0); - - kr = (float)red_high - (float)red_low; - kg = (float)green_high - (float)green_low; - kb = (float)blue_high - (float)blue_low; - - // Note that dr, dg, and db are all negative. - dr = red_low - red_average; - dg = green_low - green_average; - db = blue_low - blue_average; - - // Use straight (nonperceptive) weights. - wR2 = (float) 1.0; - wG2 = (float) 1.0; - wB2 = (float) 1.0; - - lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); - lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); - lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); - lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); - lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); - lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); - lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); - lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); - - float min_value = lowhightable[0]; - int min_index = 0; - - for(q = 1; q<8; q++) - { - if(lowhightable[q] < min_value) - { - min_value = lowhightable[q]; - min_index = q; - } - } - - low_color[0] = red_4bit_low; - low_color[1] = green_4bit_low; - low_color[2] = blue_4bit_low; - - high_color[0] = red_4bit_high; - high_color[1] = green_4bit_high; - high_color[2] = blue_4bit_high; - - switch(min_index) - { - case 0: - // Since the step size is always 17 in RGB444 format (15*17=255), - // kr = kg = kb = 17, which means that case 0 and case 7 will - // always have equal projected error. Choose the one that is - // closer to the desired color. - if(dr*dr + dg*dg + db*db > 3*8*8) - { - enc_color[0] = high_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = high_color[2]; - } - else - { - enc_color[0] = low_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = low_color[2]; - } - break; - case 1: - enc_color[0] = high_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = low_color[2]; - break; - case 2: - enc_color[0] = low_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = low_color[2]; - break; - case 3: - enc_color[0] = low_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = high_color[2]; - break; - case 4: - enc_color[0] = high_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = low_color[2]; - break; - case 5: - enc_color[0] = high_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = high_color[2]; - break; - case 6: - enc_color[0] = low_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = high_color[2]; - break; - case 7: - if(dr*dr + dg*dg + db*db > 3*8*8) - { - enc_color[0] = high_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = high_color[2]; - } - else - { - enc_color[0] = low_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = low_color[2]; - } - break; - } - - // Expand 5-bit encoded color to 8-bit color - avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2); - avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2); - avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2); -} - - -// The below code quantizes a float RGB value to RGB555. -// -void quantize555ColorCombined(float *avg_col_in, int *enc_color, uint8 *avg_color) -{ - float dr, dg, db; - float kr, kg, kb; - float wR2, wG2, wB2; - uint8 low_color[3]; - uint8 high_color[3]; - float lowhightable[8]; - int q; - float kval = (float) (255.0/31.0); - - - // These are the values that we want to have: - float red_average, green_average, blue_average; - - int red_5bit_low, green_5bit_low, blue_5bit_low; - int red_5bit_high, green_5bit_high, blue_5bit_high; - - // These are the values that we approximate with: - int red_low, green_low, blue_low; - int red_high, green_high, blue_high; - - red_average = avg_col_in[0]; - green_average = avg_col_in[1]; - blue_average = avg_col_in[2]; - - // Find the 5-bit reconstruction levels red_low, red_high - // so that red_average is in interval [red_low, red_high]. - // (The same with green and blue.) - - red_5bit_low = (int) (red_average/kval); - green_5bit_low = (int) (green_average/kval); - blue_5bit_low = (int) (blue_average/kval); - - red_5bit_high = CLAMP(0, red_5bit_low + 1, 31); - green_5bit_high = CLAMP(0, green_5bit_low + 1, 31); - blue_5bit_high = CLAMP(0, blue_5bit_low + 1, 31); - - red_low = (red_5bit_low << 3) | (red_5bit_low >> 2); - green_low = (green_5bit_low << 3) | (green_5bit_low >> 2); - blue_low = (blue_5bit_low << 3) | (blue_5bit_low >> 2); - - red_high = (red_5bit_high << 3) | (red_5bit_high >> 2); - green_high = (green_5bit_high << 3) | (green_5bit_high >> 2); - blue_high = (blue_5bit_high << 3) | (blue_5bit_high >> 2); - - kr = (float)red_high - (float)red_low; - kg = (float)green_high - (float)green_low; - kb = (float)blue_high - (float)blue_low; - - // Note that dr, dg, and db are all negative. - - dr = red_low - red_average; - dg = green_low - green_average; - db = blue_low - blue_average; - - // Use straight (nonperceptive) weights. - wR2 = (float) 1.0; - wG2 = (float) 1.0; - wB2 = (float) 1.0; - - lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); - lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); - lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); - lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); - lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); - lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); - lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); - lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); - - - float min_value = lowhightable[0]; - int min_index = 0; - - for(q = 1; q<8; q++) - { - if(lowhightable[q] < min_value) - { - min_value = lowhightable[q]; - min_index = q; - } - } - - low_color[0] = red_5bit_low; - low_color[1] = green_5bit_low; - low_color[2] = blue_5bit_low; - - high_color[0] = red_5bit_high; - high_color[1] = green_5bit_high; - high_color[2] = blue_5bit_high; - - switch(min_index) - { - case 0: - enc_color[0] = low_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = low_color[2]; - break; - case 1: - enc_color[0] = high_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = low_color[2]; - break; - case 2: - enc_color[0] = low_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = low_color[2]; - break; - case 3: - enc_color[0] = low_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = high_color[2]; - break; - case 4: - enc_color[0] = high_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = low_color[2]; - break; - case 5: - enc_color[0] = high_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = high_color[2]; - break; - case 6: - enc_color[0] = low_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = high_color[2]; - break; - case 7: - enc_color[0] = high_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = high_color[2]; - break; - } - - // Expand 5-bit encoded color to 8-bit color - avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2); - avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2); - avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2); - -} - - -// The below code quantizes a float RGB value to RGB444. -// It is thus the same as the above function quantize444ColorCombined(), but it uses a -// weighted error metric instead. -// -void quantize444ColorCombinedPerceptual(float *avg_col_in, int *enc_color, uint8 *avg_color) -{ - float dr, dg, db; - float kr, kg, kb; - float wR2, wG2, wB2; - uint8 low_color[3]; - uint8 high_color[3]; - float lowhightable[8]; - int q; - float kval = (float) (255.0/15.0); - - - // These are the values that we want to have: - float red_average, green_average, blue_average; - - int red_4bit_low, green_4bit_low, blue_4bit_low; - int red_4bit_high, green_4bit_high, blue_4bit_high; - - // These are the values that we approximate with: - int red_low, green_low, blue_low; - int red_high, green_high, blue_high; - - red_average = avg_col_in[0]; - green_average = avg_col_in[1]; - blue_average = avg_col_in[2]; - - // Find the 5-bit reconstruction levels red_low, red_high - // so that red_average is in interval [red_low, red_high]. - // (The same with green and blue.) - - red_4bit_low = (int) (red_average/kval); - green_4bit_low = (int) (green_average/kval); - blue_4bit_low = (int) (blue_average/kval); - - red_4bit_high = CLAMP(0, red_4bit_low + 1, 15); - green_4bit_high = CLAMP(0, green_4bit_low + 1, 15); - blue_4bit_high = CLAMP(0, blue_4bit_low + 1, 15); - - red_low = (red_4bit_low << 4) | (red_4bit_low >> 0); - green_low = (green_4bit_low << 4) | (green_4bit_low >> 0); - blue_low = (blue_4bit_low << 4) | (blue_4bit_low >> 0); - - red_high = (red_4bit_high << 4) | (red_4bit_high >> 0); - green_high = (green_4bit_high << 4) | (green_4bit_high >> 0); - blue_high = (blue_4bit_high << 4) | (blue_4bit_high >> 0); - - low_color[0] = red_4bit_low; - low_color[1] = green_4bit_low; - low_color[2] = blue_4bit_low; - - high_color[0] = red_4bit_high; - high_color[1] = green_4bit_high; - high_color[2] = blue_4bit_high; - - kr = (float)red_high - (float)red_low; - kg = (float)green_high - (float)green_low; - kb = (float)blue_high- (float)blue_low; - - // Note that dr, dg, and db are all negative. - - dr = red_low - red_average; - dg = green_low - green_average; - db = blue_low - blue_average; - - // Perceptual weights to use - wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED; - wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED; - wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED; - - lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); - lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); - lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); - lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); - lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); - lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); - lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); - lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); - - - float min_value = lowhightable[0]; - int min_index = 0; - - for(q = 1; q<8; q++) - { - if(lowhightable[q] < min_value) - { - min_value = lowhightable[q]; - min_index = q; - } - } - - switch(min_index) - { - case 0: - enc_color[0] = low_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = low_color[2]; - break; - case 1: - enc_color[0] = high_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = low_color[2]; - break; - case 2: - enc_color[0] = low_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = low_color[2]; - break; - case 3: - enc_color[0] = low_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = high_color[2]; - break; - case 4: - enc_color[0] = high_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = low_color[2]; - break; - case 5: - enc_color[0] = high_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = high_color[2]; - break; - case 6: - enc_color[0] = low_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = high_color[2]; - break; - case 7: - enc_color[0] = high_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = high_color[2]; - break; - } - - // Expand encoded color to eight bits - avg_color[0] = (enc_color[0] << 4) | enc_color[0]; - avg_color[1] = (enc_color[1] << 4) | enc_color[1]; - avg_color[2] = (enc_color[2] << 4) | enc_color[2]; -} - - -// The below code quantizes a float RGB value to RGB555. -// It is thus the same as the above function quantize555ColorCombined(), but it uses a -// weighted error metric instead. -// -void quantize555ColorCombinedPerceptual(float *avg_col_in, int *enc_color, uint8 *avg_color) -{ - float dr, dg, db; - float kr, kg, kb; - float wR2, wG2, wB2; - uint8 low_color[3]; - uint8 high_color[3]; - float lowhightable[8]; - int q; - float kval = (float) (255.0/31.0); - - - // These are the values that we want to have: - float red_average, green_average, blue_average; - - int red_5bit_low, green_5bit_low, blue_5bit_low; - int red_5bit_high, green_5bit_high, blue_5bit_high; - - // These are the values that we approximate with: - int red_low, green_low, blue_low; - int red_high, green_high, blue_high; - - red_average = avg_col_in[0]; - green_average = avg_col_in[1]; - blue_average = avg_col_in[2]; - - // Find the 5-bit reconstruction levels red_low, red_high - // so that red_average is in interval [red_low, red_high]. - // (The same with green and blue.) - - red_5bit_low = (int) (red_average/kval); - green_5bit_low = (int) (green_average/kval); - blue_5bit_low = (int) (blue_average/kval); - - red_5bit_high = CLAMP(0, red_5bit_low + 1, 31); - green_5bit_high = CLAMP(0, green_5bit_low + 1, 31); - blue_5bit_high = CLAMP(0, blue_5bit_low + 1, 31); - - red_low = (red_5bit_low << 3) | (red_5bit_low >> 2); - green_low = (green_5bit_low << 3) | (green_5bit_low >> 2); - blue_low = (blue_5bit_low << 3) | (blue_5bit_low >> 2); - - red_high = (red_5bit_high << 3) | (red_5bit_high >> 2); - green_high = (green_5bit_high << 3) | (green_5bit_high >> 2); - blue_high = (blue_5bit_high << 3) | (blue_5bit_high >> 2); - - low_color[0] = red_5bit_low; - low_color[1] = green_5bit_low; - low_color[2] = blue_5bit_low; - - high_color[0] = red_5bit_high; - high_color[1] = green_5bit_high; - high_color[2] = blue_5bit_high; - - kr = (float)red_high - (float)red_low; - kg = (float)green_high - (float)green_low; - kb = (float)blue_high - (float)blue_low; - - // Note that dr, dg, and db are all negative. - - dr = red_low - red_average; - dg = green_low - green_average; - db = blue_low - blue_average; - - // Perceptual weights to use - wR2 = (float) PERCEPTUAL_WEIGHT_R_SQUARED; - wG2 = (float) PERCEPTUAL_WEIGHT_G_SQUARED; - wB2 = (float) PERCEPTUAL_WEIGHT_B_SQUARED; - - lowhightable[0] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); - lowhightable[1] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+ 0) ); - lowhightable[2] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); - lowhightable[3] = wR2*wG2*SQUARE( (dr+ 0) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); - lowhightable[4] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+ 0) ) + wG2*wB2*SQUARE( (dg+kg) - (db+ 0) ); - lowhightable[5] = wR2*wG2*SQUARE( (dr+kr) - (dg+ 0) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+ 0) - (db+kb) ); - lowhightable[6] = wR2*wG2*SQUARE( (dr+ 0) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+ 0) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); - lowhightable[7] = wR2*wG2*SQUARE( (dr+kr) - (dg+kg) ) + wR2*wB2*SQUARE( (dr+kr) - (db+kb) ) + wG2*wB2*SQUARE( (dg+kg) - (db+kb) ); - - - float min_value = lowhightable[0]; - int min_index = 0; - - for(q = 1; q<8; q++) - { - if(lowhightable[q] < min_value) - { - min_value = lowhightable[q]; - min_index = q; - } - } - - switch(min_index) - { - case 0: - enc_color[0] = low_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = low_color[2]; - break; - case 1: - enc_color[0] = high_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = low_color[2]; - break; - case 2: - enc_color[0] = low_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = low_color[2]; - break; - case 3: - enc_color[0] = low_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = high_color[2]; - break; - case 4: - enc_color[0] = high_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = low_color[2]; - break; - case 5: - enc_color[0] = high_color[0]; - enc_color[1] = low_color[1]; - enc_color[2] = high_color[2]; - break; - case 6: - enc_color[0] = low_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = high_color[2]; - break; - case 7: - enc_color[0] = high_color[0]; - enc_color[1] = high_color[1]; - enc_color[2] = high_color[2]; - break; - } - - // Expand 5-bit encoded color to 8-bit color - avg_color[0] = (enc_color[0] << 3) | (enc_color[0] >> 2); - avg_color[1] = (enc_color[1] << 3) | (enc_color[1] >> 2); - avg_color[2] = (enc_color[2] << 3) | (enc_color[2] >> 2); - -} - - -void compressBlockDiffFlipSlow(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) -{ - - - unsigned int compressed1_norm_diff, compressed2_norm_diff; - unsigned int compressed1_norm_444, compressed2_norm_444; - unsigned int compressed1_flip_diff, compressed2_flip_diff; - unsigned int compressed1_flip_444, compressed2_flip_444; - unsigned int best_err_norm_diff = 255*255*8*3; - unsigned int best_err_norm_444 = 255*255*8*3; - unsigned int best_err_flip_diff = 255*255*8*3; - unsigned int best_err_flip_444 = 255*255*8*3; - uint8 avg_color_quant1[3], avg_color_quant2[3]; - - float avg_color_float1[3],avg_color_float2[3]; - int enc_color1[3], enc_color2[3], diff[3]; - int enc_base1[3], enc_base2[3]; - int enc_try1[3], enc_try2[3]; - int err; - unsigned int best_pixel_indices1_MSB=0; - unsigned int best_pixel_indices1_LSB=0; - unsigned int best_pixel_indices2_MSB=0; - unsigned int best_pixel_indices2_LSB=0; - - unsigned int best_table1=0, best_table2=0; - int diffbit; - - int norm_err=0; - int flip_err=0; - int minerr; - int dr1, dg1, db1, dr2, dg2, db2; - - // First try normal blocks 2x4: - - computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); - computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); - - // First test if avg_color1 is similar enough to avg_color2 so that - // we can use differential coding of colors. - - enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); - enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); - enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); - enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); - enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); - enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - if( (diff[0] >= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) - { - diffbit = 1; - - enc_base1[0] = enc_color1[0]; - enc_base1[1] = enc_color1[1]; - enc_base1[2] = enc_color1[2]; - enc_base2[0] = enc_color2[0]; - enc_base2[1] = enc_color2[1]; - enc_base2[2] = enc_color2[2]; - - int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; - int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; - - // left part of block - for(dr1 = SLOW_SCAN_MIN; dr1> 2); - avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); - avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); - - // left part of block - err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - } - } - } - - // right part of block - for(dr2 = SLOW_SCAN_MIN; dr2> 2); - avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); - avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); - - // left part of block - err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - } - } - } - - // Now see what combinations are both low in error and possible to - // encode differentially. - - minerr = 255*255*3*8*2; - - for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - // The diff is OK, calculate total error: - - err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; - - if(err < minerr) - { - minerr = err; - - enc_color1[0] = enc_try1[0]; - enc_color1[1] = enc_try1[1]; - enc_color1[2] = enc_try1[2]; - enc_color2[0] = enc_try2[0]; - enc_color2[1] = enc_try2[1]; - enc_color2[2] = enc_try2[2]; - } - } - } - } - } - } - } - } - - best_err_norm_diff = minerr; - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - - // Pack bits into the first word. - - - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - compressed1_norm_diff = 0; - PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); - PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); - PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); - - - // left part of block - tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); - - compressed2_norm_diff = 0; - PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); - - } - // We should do this in any case... - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - - // Color for left block - - int besterr = 255*255*3*8; - int bestri = 0, bestgi = 0, bestbi = 0; - int ri, gi, bi; - - for(ri = 0; ri<15; ri++) - { - for(gi = 0; gi<15; gi++) - { - for(bi = 0; bi<15; bi++) - { - enc_color1[0] = ri; - enc_color1[1] = gi; - enc_color1[2] = bi; - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - - // left part of block - err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); - - if(err= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) - { - diffbit = 1; - - enc_base1[0] = enc_color1[0]; - enc_base1[1] = enc_color1[1]; - enc_base1[2] = enc_color1[2]; - enc_base2[0] = enc_color2[0]; - enc_base2[1] = enc_color2[1]; - enc_base2[2] = enc_color2[2]; - - int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; - int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; - - // upper part of block - for(dr1 = SLOW_SCAN_MIN; dr1> 2); - avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); - avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); - - // upper part of block - err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - } - } - } - - // lower part of block - for(dr2 = SLOW_SCAN_MIN; dr2> 2); - avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); - avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); - - // lower part of block - err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - } - } - } - - // Now see what combinations are both low in error and possible to - // encode differentially. - - minerr = 255*255*3*8*2; - - for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - // The diff is OK, calculate total error: - - err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; - - if(err < minerr) - { - minerr = err; - - enc_color1[0] = enc_try1[0]; - enc_color1[1] = enc_try1[1]; - enc_color1[2] = enc_try1[2]; - enc_color2[0] = enc_try2[0]; - enc_color2[1] = enc_try2[1]; - enc_color2[2] = enc_try2[2]; - } - } - } - } - } - } - } - } - - - flip_err = minerr; - - best_err_flip_diff = flip_err; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - // Pack bits into the first word. - - compressed1_flip_diff = 0; - PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); - PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); - PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); - - - - - // upper part of block - tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - - PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); - - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - } - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - - // Color for upper block - - int besterr = 255*255*3*8; - int bestri = 0, bestgi = 0, bestbi = 0; - int ri, gi, bi; - - for(ri = 0; ri<15; ri++) - { - for(gi = 0; gi<15; gi++) - { - for(bi = 0; bi<15; bi++) - { - enc_color1[0] = ri; - enc_color1[1] = gi; - enc_color1[2] = bi; - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - - // upper part of block - err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) - { - diffbit = 1; - - enc_base1[0] = enc_color1[0]; - enc_base1[1] = enc_color1[1]; - enc_base1[2] = enc_color1[2]; - enc_base2[0] = enc_color2[0]; - enc_base2[1] = enc_color2[1]; - enc_base2[2] = enc_color2[2]; - - int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; - int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; - - // left part of block - for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); - avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); - avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); - - // left part of block - err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - } - } - } - - // right part of block - for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); - avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); - avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); - - // left part of block - err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - } - } - } - - // Now see what combinations are both low in error and possible to - // encode differentially. - - minerr = 255*255*3*8*2; - - for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - // The diff is OK, calculate total error: - - err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; - - if(err < minerr) - { - minerr = err; - - enc_color1[0] = enc_try1[0]; - enc_color1[1] = enc_try1[1]; - enc_color1[2] = enc_try1[2]; - enc_color2[0] = enc_try2[0]; - enc_color2[1] = enc_try2[1]; - enc_color2[2] = enc_try2[2]; - } - } - } - } - } - } - } - } - - best_err_norm_diff = minerr; - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - - // Pack bits into the first word. - - - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - compressed1_norm_diff = 0; - PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); - PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); - PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); - - - // left part of block - tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); - - compressed2_norm_diff = 0; - PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); - - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - - // Color for left block - - int besterr = 255*255*3*8; - int bestri = 0, bestgi = 0, bestbi = 0; - int ri, gi, bi; - - for(ri = 0; ri<15; ri++) - { - for(gi = 0; gi<15; gi++) - { - for(bi = 0; bi<15; bi++) - { - enc_color1[0] = ri; - enc_color1[1] = gi; - enc_color1[2] = bi; - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - - // left part of block - err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); - - if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) - { - diffbit = 1; - - enc_base1[0] = enc_color1[0]; - enc_base1[1] = enc_color1[1]; - enc_base1[2] = enc_color1[2]; - enc_base2[0] = enc_color2[0]; - enc_base2[1] = enc_color2[1]; - enc_base2[2] = enc_color2[2]; - - int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; - int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; - - // upper part of block - for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); - avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); - avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); - - // upper part of block - err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - } - } - } - - // lower part of block - for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); - avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); - avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); - - // lower part of block - err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - } - } - } - - // Now see what combinations are both low in error and possible to - // encode differentially. - - minerr = 255*255*3*8*2; - - for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - // The diff is OK, calculate total error: - - err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; - - if(err < minerr) - { - minerr = err; - - enc_color1[0] = enc_try1[0]; - enc_color1[1] = enc_try1[1]; - enc_color1[2] = enc_try1[2]; - enc_color2[0] = enc_try2[0]; - enc_color2[1] = enc_try2[1]; - enc_color2[2] = enc_try2[2]; - } - } - } - } - } - } - } - } - - - flip_err = minerr; - - best_err_flip_diff = flip_err; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - // Pack bits into the first word. - - compressed1_flip_diff = 0; - PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); - PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); - PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); - - - - - // upper part of block - tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - - PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); - - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - - // Color for upper block - - int besterr = 255*255*3*8; - int bestri = 0, bestgi = 0, bestbi = 0; - int ri, gi, bi; - - for(ri = 0; ri<15; ri++) - { - for(gi = 0; gi<15; gi++) - { - for(bi = 0; bi<15; bi++) - { - enc_color1[0] = ri; - enc_color1[1] = gi; - enc_color1[2] = bi; - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - - // upper part of block - err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - if(err= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) - { - diffbit = 1; - - enc_base1[0] = enc_color1[0]; - enc_base1[1] = enc_color1[1]; - enc_base1[2] = enc_color1[2]; - enc_base2[0] = enc_color2[0]; - enc_base2[1] = enc_color2[1]; - enc_base2[2] = enc_color2[2]; - - int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; - int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; - - // left part of block - for(dr1 = SLOW_SCAN_MIN; dr1> 2); - avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); - avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); - - // left part of block - err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - } - } - } - - // right part of block - for(dr2 = SLOW_SCAN_MIN; dr2> 2); - avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); - avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); - - // left part of block - err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - } - } - } - - // Now see what combinations are both low in error and possible to - // encode differentially. - - minerr = 255*255*3*8*2; - - for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - // The diff is OK, calculate total error: - - err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; - - if(err < minerr) - { - minerr = err; - - enc_color1[0] = enc_try1[0]; - enc_color1[1] = enc_try1[1]; - enc_color1[2] = enc_try1[2]; - enc_color2[0] = enc_try2[0]; - enc_color2[1] = enc_try2[1]; - enc_color2[2] = enc_try2[2]; - } - } - } - } - } - } - } - } - - best_err_norm_diff = minerr; - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - - // Pack bits into the first word. - - - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - compressed1_norm_diff = 0; - PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); - PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); - PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); - - - // left part of block - tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); - - compressed2_norm_diff = 0; - PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); - - - } - // We should do this in any case... - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - - // Color for left block - - int besterr = 255*255*3*8; - int bestri = 0, bestgi = 0, bestbi = 0; - int ri, gi, bi; - - for(ri = 0; ri<15; ri++) - { - for(gi = 0; gi<15; gi++) - { - for(bi = 0; bi<15; bi++) - { - enc_color1[0] = ri; - enc_color1[1] = gi; - enc_color1[2] = bi; - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - - // left part of block - err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); - - if(err= SLOW_TRY_MIN) && (diff[0] <= SLOW_TRY_MAX) && (diff[1] >= SLOW_TRY_MIN) && (diff[1] <= SLOW_TRY_MAX) && (diff[2] >= SLOW_TRY_MIN) && (diff[2] <= SLOW_TRY_MAX) ) - { - diffbit = 1; - - enc_base1[0] = enc_color1[0]; - enc_base1[1] = enc_color1[1]; - enc_base1[2] = enc_color1[2]; - enc_base2[0] = enc_color2[0]; - enc_base2[1] = enc_color2[1]; - enc_base2[2] = enc_color2[2]; - - int err1[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; - int err2[SLOW_SCAN_RANGE][SLOW_SCAN_RANGE][SLOW_SCAN_RANGE]; - - // upper part of block - for(dr1 = SLOW_SCAN_MIN; dr1> 2); - avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); - avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); - - // upper part of block - err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - } - } - } - - // lower part of block - for(dr2 = SLOW_SCAN_MIN; dr2> 2); - avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); - avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); - - // lower part of block - err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - } - } - } - - // Now see what combinations are both low in error and possible to - // encode differentially. - - minerr = 255*255*3*8*2; - - for(dr1 = SLOW_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - // The diff is OK, calculate total error: - - err = err1[dr1+SLOW_SCAN_OFFSET][dg1+SLOW_SCAN_OFFSET][db1+SLOW_SCAN_OFFSET] + err2[dr2+SLOW_SCAN_OFFSET][dg2+SLOW_SCAN_OFFSET][db2+SLOW_SCAN_OFFSET]; - - if(err < minerr) - { - minerr = err; - - enc_color1[0] = enc_try1[0]; - enc_color1[1] = enc_try1[1]; - enc_color1[2] = enc_try1[2]; - enc_color2[0] = enc_try2[0]; - enc_color2[1] = enc_try2[1]; - enc_color2[2] = enc_try2[2]; - } - } - } - } - } - } - } - } - - - flip_err = minerr; - - best_err_flip_diff = flip_err; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - // Pack bits into the first word. - - compressed1_flip_diff = 0; - PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); - PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); - PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); - - - - - // upper part of block - tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - - PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); - - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - } - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - - // Color for upper block - - int besterr = 255*255*3*8; - int bestri = 0, bestgi = 0, bestbi = 0; - int ri, gi, bi; - - for(ri = 0; ri<15; ri++) - { - for(gi = 0; gi<15; gi++) - { - for(bi = 0; bi<15; bi++) - { - enc_color1[0] = ri; - enc_color1[1] = gi; - enc_color1[2] = bi; - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - - // upper part of block - err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) - { - diffbit = 1; - - enc_base1[0] = enc_color1[0]; - enc_base1[1] = enc_color1[1]; - enc_base1[2] = enc_color1[2]; - enc_base2[0] = enc_color2[0]; - enc_base2[1] = enc_color2[1]; - enc_base2[2] = enc_color2[2]; - - int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; - int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; - - // left part of block - for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); - avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); - avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); - - // left part of block - err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - } - } - } - - // right part of block - for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); - avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); - avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); - - // left part of block - err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - } - } - } - - // Now see what combinations are both low in error and possible to - // encode differentially. - - minerr = 255*255*3*8*2; - - for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - // The diff is OK, calculate total error: - - err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; - - if(err < minerr) - { - minerr = err; - - enc_color1[0] = enc_try1[0]; - enc_color1[1] = enc_try1[1]; - enc_color1[2] = enc_try1[2]; - enc_color2[0] = enc_try2[0]; - enc_color2[1] = enc_try2[1]; - enc_color2[2] = enc_try2[2]; - } - } - } - } - } - } - } - } - - best_err_norm_diff = minerr; - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - - // Pack bits into the first word. - - - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - compressed1_norm_diff = 0; - PUTBITSHIGH( compressed1_norm_diff, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_norm_diff, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_norm_diff, diff[0], 3, 58); - PUTBITSHIGH( compressed1_norm_diff, diff[1], 3, 50); - PUTBITSHIGH( compressed1_norm_diff, diff[2], 3, 42); - - - // left part of block - tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm_diff, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm_diff, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm_diff, 0, 1, 32); - - compressed2_norm_diff = 0; - PUTBITS( compressed2_norm_diff, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm_diff, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm_diff, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm_diff, (best_pixel_indices2_LSB ), 8, 15); - - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - - // Color for left block - - int besterr = 255*255*3*8; - int bestri = 0, bestgi = 0, bestbi = 0; - int ri, gi, bi; - - for(ri = 0; ri<15; ri++) - { - for(gi = 0; gi<15; gi++) - { - for(bi = 0; bi<15; bi++) - { - enc_color1[0] = ri; - enc_color1[1] = gi; - enc_color1[2] = bi; - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - - // left part of block - err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB,best_pixel_indices1_LSB); - - if(err= MEDIUM_TRY_MIN) && (diff[0] <= MEDIUM_TRY_MAX) && (diff[1] >= MEDIUM_TRY_MIN) && (diff[1] <= MEDIUM_TRY_MAX) && (diff[2] >= MEDIUM_TRY_MIN) && (diff[2] <= MEDIUM_TRY_MAX) ) - { - diffbit = 1; - - enc_base1[0] = enc_color1[0]; - enc_base1[1] = enc_color1[1]; - enc_base1[2] = enc_color1[2]; - enc_base2[0] = enc_color2[0]; - enc_base2[1] = enc_color2[1]; - enc_base2[2] = enc_color2[2]; - - int err1[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; - int err2[MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE][MEDIUM_SCAN_RANGE]; - - // upper part of block - for(dr1 = MEDIUM_SCAN_MIN; dr1> 2); - avg_color_quant1[1] = enc_try1[1] << 3 | (enc_try1[1] >> 2); - avg_color_quant1[2] = enc_try1[2] << 3 | (enc_try1[2] >> 2); - - // upper part of block - err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - } - } - } - - // lower part of block - for(dr2 = MEDIUM_SCAN_MIN; dr2> 2); - avg_color_quant2[1] = enc_try2[1] << 3 | (enc_try2[1] >> 2); - avg_color_quant2[2] = enc_try2[2] << 3 | (enc_try2[2] >> 2); - - // lower part of block - err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET] = tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - } - } - } - - // Now see what combinations are both low in error and possible to - // encode differentially. - - minerr = 255*255*3*8*2; - - for(dr1 = MEDIUM_SCAN_MIN; dr1= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - // The diff is OK, calculate total error: - - err = err1[dr1+MEDIUM_SCAN_OFFSET][dg1+MEDIUM_SCAN_OFFSET][db1+MEDIUM_SCAN_OFFSET] + err2[dr2+MEDIUM_SCAN_OFFSET][dg2+MEDIUM_SCAN_OFFSET][db2+MEDIUM_SCAN_OFFSET]; - - if(err < minerr) - { - minerr = err; - - enc_color1[0] = enc_try1[0]; - enc_color1[1] = enc_try1[1]; - enc_color1[2] = enc_try1[2]; - enc_color2[0] = enc_try2[0]; - enc_color2[1] = enc_try2[1]; - enc_color2[2] = enc_try2[2]; - } - } - } - } - } - } - } - } - - - flip_err = minerr; - - best_err_flip_diff = flip_err; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - // Pack bits into the first word. - - compressed1_flip_diff = 0; - PUTBITSHIGH( compressed1_flip_diff, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_flip_diff, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_flip_diff, diff[0], 3, 58); - PUTBITSHIGH( compressed1_flip_diff, diff[1], 3, 50); - PUTBITSHIGH( compressed1_flip_diff, diff[2], 3, 42); - - - - - // upper part of block - tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - - PUTBITSHIGH( compressed1_flip_diff, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip_diff, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip_diff, 1, 1, 32); - - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip_diff = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - - // Color for upper block - - int besterr = 255*255*3*8; - int bestri = 0, bestgi = 0, bestbi = 0; - int ri, gi, bi; - - for(ri = 0; ri<15; ri++) - { - for(gi = 0; gi<15; gi++) - { - for(bi = 0; bi<15; bi++) - { - enc_color1[0] = ri; - enc_color1[1] = gi; - enc_color1[2] = bi; - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - - // upper part of block - err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - if(err= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - diffbit = 1; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - // Pack bits into the first word. - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - compressed1_norm = 0; - PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); - PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); - PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - norm_err = 0; - - // left part of block - norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm, 0, 1, 32); - - compressed2_norm = 0; - PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - eps = (float) 0.0001; - - enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); - enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); - enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); - enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); - enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); - enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; - avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; - avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; - - - // Pack bits into the first word. - - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - - compressed1_norm = 0; - PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); - PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); - PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); - PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); - PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); - PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - - // left part of block - norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm, 0, 1, 32); - - compressed2_norm = 0; - PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); - - - } - - // Now try flipped blocks 4x2: - - computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); - computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); - - // First test if avg_color1 is similar enough to avg_color2 so that - // we can use differential coding of colors. - - enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); - enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); - enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); - enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); - enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); - enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - diffbit = 1; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - // Pack bits into the first word. - - compressed1_flip = 0; - PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); - PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); - PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); - - - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - // upper part of block - flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip, 1, 1, 32); - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - eps = (float) 0.0001; - - enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); - enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); - enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); - enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); - enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); - enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; - avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; - avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; - - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - - - // Pack bits into the first word. - - compressed1_flip = 0; - PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); - PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); - PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); - PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); - PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); - PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - // upper part of block - flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip, 1, 1, 32); - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - - } - - // Now lets see which is the best table to use. Only 8 tables are possible. - - if(norm_err <= flip_err) - { - - compressed1 = compressed1_norm | 0; - compressed2 = compressed2_norm; - - } - else - { - - compressed1 = compressed1_flip | 1; - compressed2 = compressed2_flip; - } -} - -void compressBlockDiffFlipCombined(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) -{ - unsigned int compressed1_norm, compressed2_norm; - unsigned int compressed1_flip, compressed2_flip; - uint8 avg_color_quant1[3], avg_color_quant2[3]; - - float avg_color_float1[3],avg_color_float2[3]; - int enc_color1[3], enc_color2[3], diff[3]; - unsigned int best_table1=0, best_table2=0; - int diffbit; - - int norm_err=0; - int flip_err=0; - - // First try normal blocks 2x4: - - computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); - computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); - - // First test if avg_color1 is similar enough to avg_color2 so that - // we can use differential coding of colors. - - float eps; - - uint8 dummy[3]; - - quantize555ColorCombined(avg_color_float1, enc_color1, dummy); - quantize555ColorCombined(avg_color_float2, enc_color2, dummy); - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - diffbit = 1; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - // Pack bits into the first word. - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - compressed1_norm = 0; - PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); - PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); - PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - norm_err = 0; - - // left part of block - norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm, 0, 1, 32); - - compressed2_norm = 0; - PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - eps = (float) 0.0001; - - uint8 dummy[3]; - quantize444ColorCombined(avg_color_float1, enc_color1, dummy); - quantize444ColorCombined(avg_color_float2, enc_color2, dummy); - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; - avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; - avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; - - - // Pack bits into the first word. - - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - - compressed1_norm = 0; - PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); - PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); - PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); - PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); - PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); - PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - - // left part of block - norm_err = tryalltables_3bittable2x4(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - norm_err += tryalltables_3bittable2x4(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm, 0, 1, 32); - - compressed2_norm = 0; - PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); - - - } - - // Now try flipped blocks 4x2: - - computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); - computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); - - // First test if avg_color1 is similar enough to avg_color2 so that - // we can use differential coding of colors. - - quantize555ColorCombined(avg_color_float1, enc_color1, dummy); - quantize555ColorCombined(avg_color_float2, enc_color2, dummy); - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - diffbit = 1; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - // Pack bits into the first word. - - compressed1_flip = 0; - PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); - PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); - PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); - - - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - // upper part of block - flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip, 1, 1, 32); - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - eps = (float) 0.0001; - - uint8 dummy[3]; - quantize444ColorCombined(avg_color_float1, enc_color1, dummy); - quantize444ColorCombined(avg_color_float2, enc_color2, dummy); - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; - avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; - avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; - - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - - - // Pack bits into the first word. - - compressed1_flip = 0; - PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); - PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); - PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); - PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); - PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); - PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - // upper part of block - flip_err = tryalltables_3bittable4x2(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - flip_err += tryalltables_3bittable4x2(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip, 1, 1, 32); - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - - } - - // Now lets see which is the best table to use. Only 8 tables are possible. - - if(norm_err <= flip_err) - { - - compressed1 = compressed1_norm | 0; - compressed2 = compressed2_norm; - - } - else - { - - compressed1 = compressed1_flip | 1; - compressed2 = compressed2_flip; - } -} - -void compressBlockDiffFlipAveragePerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) -{ - - unsigned int compressed1_norm, compressed2_norm; - unsigned int compressed1_flip, compressed2_flip; - uint8 avg_color_quant1[3], avg_color_quant2[3]; - - float avg_color_float1[3],avg_color_float2[3]; - int enc_color1[3], enc_color2[3], diff[3]; - unsigned int best_table1=0, best_table2=0; - int diffbit; - - int norm_err=0; - int flip_err=0; - - // First try normal blocks 2x4: - - computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); - computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); - - // First test if avg_color1 is similar enough to avg_color2 so that - // we can use differential coding of colors. - - - float eps; - - enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); - enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); - enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); - enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); - enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); - enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - diffbit = 1; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - // Pack bits into the first word. - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - compressed1_norm = 0; - PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); - PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); - PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - norm_err = 0; - - // left part of block - norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm, 0, 1, 32); - - compressed2_norm = 0; - PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - eps = (float) 0.0001; - - enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); - enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); - enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); - enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); - enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); - enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; - avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; - avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; - - - // Pack bits into the first word. - - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - - compressed1_norm = 0; - PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); - PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); - PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); - PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); - PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); - PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - - // left part of block - norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm, 0, 1, 32); - - compressed2_norm = 0; - PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); - - - } - - // Now try flipped blocks 4x2: - - computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); - computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); - - // First test if avg_color1 is similar enough to avg_color2 so that - // we can use differential coding of colors. - - enc_color1[0] = int( JAS_ROUND(31.0*avg_color_float1[0]/255.0) ); - enc_color1[1] = int( JAS_ROUND(31.0*avg_color_float1[1]/255.0) ); - enc_color1[2] = int( JAS_ROUND(31.0*avg_color_float1[2]/255.0) ); - enc_color2[0] = int( JAS_ROUND(31.0*avg_color_float2[0]/255.0) ); - enc_color2[1] = int( JAS_ROUND(31.0*avg_color_float2[1]/255.0) ); - enc_color2[2] = int( JAS_ROUND(31.0*avg_color_float2[2]/255.0) ); - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - diffbit = 1; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - // Pack bits into the first word. - - compressed1_flip = 0; - PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); - PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); - PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); - - - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - // upper part of block - flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip, 1, 1, 32); - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - eps = (float) 0.0001; - - enc_color1[0] = int( ((float) avg_color_float1[0] / (17.0)) +0.5 + eps); - enc_color1[1] = int( ((float) avg_color_float1[1] / (17.0)) +0.5 + eps); - enc_color1[2] = int( ((float) avg_color_float1[2] / (17.0)) +0.5 + eps); - enc_color2[0] = int( ((float) avg_color_float2[0] / (17.0)) +0.5 + eps); - enc_color2[1] = int( ((float) avg_color_float2[1] / (17.0)) +0.5 + eps); - enc_color2[2] = int( ((float) avg_color_float2[2] / (17.0)) +0.5 + eps); - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; - avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; - avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; - - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - - - // Pack bits into the first word. - - compressed1_flip = 0; - PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); - PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); - PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); - PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); - PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); - PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - // upper part of block - flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip, 1, 1, 32); - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - - } - - // Now lets see which is the best table to use. Only 8 tables are possible. - - if(norm_err <= flip_err) - { - - compressed1 = compressed1_norm | 0; - compressed2 = compressed2_norm; - - } - else - { - - compressed1 = compressed1_flip | 1; - compressed2 = compressed2_flip; - } -} - -void compressBlockDiffFlipCombinedPerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2) -{ - - unsigned int compressed1_norm, compressed2_norm; - unsigned int compressed1_flip, compressed2_flip; - uint8 avg_color_quant1[3], avg_color_quant2[3]; - - float avg_color_float1[3],avg_color_float2[3]; - int enc_color1[3], enc_color2[3], diff[3]; - unsigned int best_table1=0, best_table2=0; - int diffbit; - - int norm_err=0; - int flip_err=0; - - // First try normal blocks 2x4: - - computeAverageColor2x4noQuantFloat(img,width,height,startx,starty,avg_color_float1); - computeAverageColor2x4noQuantFloat(img,width,height,startx+2,starty,avg_color_float2); - - // First test if avg_color1 is similar enough to avg_color2 so that - // we can use differential coding of colors. - - - float eps; - - uint8 dummy[3]; - - quantize555ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); - quantize555ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - diffbit = 1; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - // Pack bits into the first word. - - // ETC1_RGB8_OES: - // - // a) bit layout in bits 63 through 32 if diffbit = 0 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // b) bit layout in bits 63 through 32 if diffbit = 1 - // - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip| - // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - // - // c) bit layout in bits 31 through 0 (in both cases) - // - // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------------------------- - // | most significant pixel index bits | least significant pixel index bits | - // | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a | - // -------------------------------------------------------------------------------------------------- - - - compressed1_norm = 0; - PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_norm, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_norm, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_norm, diff[0], 3, 58); - PUTBITSHIGH( compressed1_norm, diff[1], 3, 50); - PUTBITSHIGH( compressed1_norm, diff[2], 3, 42); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - norm_err = 0; - - // left part of block - norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm, 0, 1, 32); - - compressed2_norm = 0; - PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - - eps = (float) 0.0001; - - quantize444ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); - quantize444ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; - avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; - avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; - - - // Pack bits into the first word. - - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - - compressed1_norm = 0; - PUTBITSHIGH( compressed1_norm, diffbit, 1, 33); - PUTBITSHIGH( compressed1_norm, enc_color1[0], 4, 63); - PUTBITSHIGH( compressed1_norm, enc_color1[1], 4, 55); - PUTBITSHIGH( compressed1_norm, enc_color1[2], 4, 47); - PUTBITSHIGH( compressed1_norm, enc_color2[0], 4, 59); - PUTBITSHIGH( compressed1_norm, enc_color2[1], 4, 51); - PUTBITSHIGH( compressed1_norm, enc_color2[2], 4, 43); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - - // left part of block - norm_err = tryalltables_3bittable2x4percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - - // right part of block - norm_err += tryalltables_3bittable2x4percep(img,width,height,startx+2,starty,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_norm, best_table1, 3, 39); - PUTBITSHIGH( compressed1_norm, best_table2, 3, 36); - PUTBITSHIGH( compressed1_norm, 0, 1, 32); - - compressed2_norm = 0; - PUTBITS( compressed2_norm, (best_pixel_indices1_MSB ), 8, 23); - PUTBITS( compressed2_norm, (best_pixel_indices2_MSB ), 8, 31); - PUTBITS( compressed2_norm, (best_pixel_indices1_LSB ), 8, 7); - PUTBITS( compressed2_norm, (best_pixel_indices2_LSB ), 8, 15); - - - } - - // Now try flipped blocks 4x2: - - computeAverageColor4x2noQuantFloat(img,width,height,startx,starty,avg_color_float1); - computeAverageColor4x2noQuantFloat(img,width,height,startx,starty+2,avg_color_float2); - - // First test if avg_color1 is similar enough to avg_color2 so that - // we can use differential coding of colors. - - - quantize555ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); - quantize555ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - if( (diff[0] >= -4) && (diff[0] <= 3) && (diff[1] >= -4) && (diff[1] <= 3) && (diff[2] >= -4) && (diff[2] <= 3) ) - { - diffbit = 1; - - // The difference to be coded: - - diff[0] = enc_color2[0]-enc_color1[0]; - diff[1] = enc_color2[1]-enc_color1[1]; - diff[2] = enc_color2[2]-enc_color1[2]; - - avg_color_quant1[0] = enc_color1[0] << 3 | (enc_color1[0] >> 2); - avg_color_quant1[1] = enc_color1[1] << 3 | (enc_color1[1] >> 2); - avg_color_quant1[2] = enc_color1[2] << 3 | (enc_color1[2] >> 2); - avg_color_quant2[0] = enc_color2[0] << 3 | (enc_color2[0] >> 2); - avg_color_quant2[1] = enc_color2[1] << 3 | (enc_color2[1] >> 2); - avg_color_quant2[2] = enc_color2[2] << 3 | (enc_color2[2] >> 2); - - // Pack bits into the first word. - - compressed1_flip = 0; - PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip, enc_color1[0], 5, 63); - PUTBITSHIGH( compressed1_flip, enc_color1[1], 5, 55); - PUTBITSHIGH( compressed1_flip, enc_color1[2], 5, 47); - PUTBITSHIGH( compressed1_flip, diff[0], 3, 58); - PUTBITSHIGH( compressed1_flip, diff[1], 3, 50); - PUTBITSHIGH( compressed1_flip, diff[2], 3, 42); - - - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - // upper part of block - flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip, 1, 1, 32); - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - - } - else - { - diffbit = 0; - // The difference is bigger than what fits in 555 plus delta-333, so we will have - // to deal with 444 444. - eps = (float) 0.0001; - - quantize444ColorCombinedPerceptual(avg_color_float1, enc_color1, dummy); - quantize444ColorCombinedPerceptual(avg_color_float2, enc_color2, dummy); - - avg_color_quant1[0] = enc_color1[0] << 4 | enc_color1[0]; - avg_color_quant1[1] = enc_color1[1] << 4 | enc_color1[1]; - avg_color_quant1[2] = enc_color1[2] << 4 | enc_color1[2]; - avg_color_quant2[0] = enc_color2[0] << 4 | enc_color2[0]; - avg_color_quant2[1] = enc_color2[1] << 4 | enc_color2[1]; - avg_color_quant2[2] = enc_color2[2] << 4 | enc_color2[2]; - - // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 - // --------------------------------------------------------------------------------------------------- - // | base col1 | base col2 | base col1 | base col2 | base col1 | base col2 | table | table |diff|flip| - // | R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit | - // --------------------------------------------------------------------------------------------------- - - - // Pack bits into the first word. - - compressed1_flip = 0; - PUTBITSHIGH( compressed1_flip, diffbit, 1, 33); - PUTBITSHIGH( compressed1_flip, enc_color1[0], 4, 63); - PUTBITSHIGH( compressed1_flip, enc_color1[1], 4, 55); - PUTBITSHIGH( compressed1_flip, enc_color1[2], 4, 47); - PUTBITSHIGH( compressed1_flip, enc_color2[0], 4, 59); - PUTBITSHIGH( compressed1_flip, enc_color2[1], 4, 51); - PUTBITSHIGH( compressed1_flip, enc_color2[2], 4, 43); - - unsigned int best_pixel_indices1_MSB; - unsigned int best_pixel_indices1_LSB; - unsigned int best_pixel_indices2_MSB; - unsigned int best_pixel_indices2_LSB; - - // upper part of block - flip_err = tryalltables_3bittable4x2percep(img,width,height,startx,starty,avg_color_quant1,best_table1,best_pixel_indices1_MSB, best_pixel_indices1_LSB); - // lower part of block - flip_err += tryalltables_3bittable4x2percep(img,width,height,startx,starty+2,avg_color_quant2,best_table2,best_pixel_indices2_MSB, best_pixel_indices2_LSB); - - PUTBITSHIGH( compressed1_flip, best_table1, 3, 39); - PUTBITSHIGH( compressed1_flip, best_table2, 3, 36); - PUTBITSHIGH( compressed1_flip, 1, 1, 32); - - best_pixel_indices1_MSB |= (best_pixel_indices2_MSB << 2); - best_pixel_indices1_LSB |= (best_pixel_indices2_LSB << 2); - - compressed2_flip = ((best_pixel_indices1_MSB & 0xffff) << 16) | (best_pixel_indices1_LSB & 0xffff); - - - } - - // Now lets see which is the best table to use. Only 8 tables are possible. - - if(norm_err <= flip_err) - { - - compressed1 = compressed1_norm | 0; - compressed2 = compressed2_norm; - - } - else - { - - compressed1 = compressed1_flip | 1; - compressed2 = compressed2_flip; - } -} - -double calcBlockErrorRGB(uint8 *img, uint8 *imgdec, int width, int height, int startx, int starty) -{ - int xx,yy; - double err; - - err = 0; - - for(xx = startx; xx< startx+4; xx++) - { - for(yy = starty; yy> 24) | - ((x & 0x00FF0000) >> 8) | - ((x & 0x0000FF00) << 8) | - ((x & 0x000000FF) << 24); -} - -void CompressBlock(const uint8 *in, int in_width, uint8 *output, int quality) { - uint8 rgb[4 * 4 * 3]; - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - rgb[(y * 4 + x) * 3 + 0] = in[(y * in_width + x) * 4 + 0]; - rgb[(y * 4 + x) * 3 + 1] = in[(y * in_width + x) * 4 + 1]; - rgb[(y * 4 + x) * 3 + 2] = in[(y * in_width + x) * 4 + 2]; - } - } - - uint8 imgdec[4 * 4 * 3]={0}; // temporary storage used by some of the functions. - unsigned int compressed1 = 0, compressed2 = 0; - switch (quality) { - case 0: - compressBlockDiffFlipFast(rgb, imgdec, 4, 4, 0, 0, compressed1, compressed2); - break; - case 1: - compressBlockDiffFlipFastPerceptual(rgb, imgdec, 4, 4, 0, 0, compressed1, compressed2); - break; - case 2: - compressBlockDiffFlipMedium(rgb, 4, 4, 0, 0, compressed1, compressed2); - break; - case 3: - compressBlockDiffFlipMediumPerceptual(rgb, 4, 4, 0, 0, compressed1, compressed2); - break; - case 4: - compressBlockDiffFlipSlow(rgb, 4, 4, 0, 0, compressed1, compressed2); - break; - case 5: - compressBlockDiffFlipSlowPerceptual(rgb, 4, 4, 0, 0, compressed1, compressed2); - break; - default: - fprintf(stderr, "ETC1: Compression level %i not defined", quality); - return; - } - compressed1 = bswap(compressed1); - compressed2 = bswap(compressed2); - memcpy(output, &compressed1, 4); - memcpy(output + 4, &compressed2, 4); - memset(rgb, 0, 4 * 4 * 3); -} diff --git a/ext/etcpack/etcpack.h b/ext/etcpack/etcpack.h deleted file mode 100644 index f8332ad17e..0000000000 --- a/ext/etcpack/etcpack.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#define PERCEPTUAL_WEIGHT_R_SQUARED 0.299 -#define PERCEPTUAL_WEIGHT_G_SQUARED 0.587 -#define PERCEPTUAL_WEIGHT_B_SQUARED 0.114 - -typedef unsigned char uint8; - -// These functions take RGB888. -void compressBlockDiffFlipSlow(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); - -void compressBlockDiffFlipMedium(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); - -void compressBlockDiffFlipFast(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); - -void compressBlockDiffFlipSlowPerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); - -void compressBlockDiffFlipMediumPerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); - -void compressBlockDiffFlipFastPerceptual(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2); - - -// This one takes RGBA8888 and converts to RGB first. -// Writes 64 bits of compressed data to output[0..7]. -// Quality is 0 to 5. The odd numbers use perceptual metrics. -void CompressBlock(const uint8 *in, int in_width, uint8 *output, int quality); diff --git a/ext/etcpack/etctool.cpp b/ext/etcpack/etctool.cpp deleted file mode 100644 index 56f2e07dc5..0000000000 --- a/ext/etcpack/etctool.cpp +++ /dev/null @@ -1,1613 +0,0 @@ -// Contains a lot of code from etcpack.cpp. -// Extracted by Henrik RydgÃ¥rd. - - -#include -#include -#include -#include - -#include "etcpack.h" -#include "etcdec.h" -#include "image.h" - -enum{FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0, FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T1}; - -int orientation; - -int ktx_mode; - -typedef struct KTX_header_t -{ - uint8 identifier[12]; - unsigned int endianness; - unsigned int glType; - unsigned int glTypeSize; - unsigned int glFormat; - unsigned int glInternalFormat; - unsigned int glBaseInternalFormat; - unsigned int pixelWidth; - unsigned int pixelHeight; - unsigned int pixelDepth; - unsigned int numberOfArrayElements; - unsigned int numberOfFaces; - unsigned int numberOfMipmapLevels; - unsigned int bytesOfKeyValueData; -} -KTX_header; -#define KTX_IDENTIFIER_REF { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A } - -#define KTX_ENDIAN_REF (0x04030201) -#define KTX_ENDIAN_REF_REV (0x01020304) - -int ktx_identifier[] = KTX_IDENTIFIER_REF; - - -enum {GL_R=0x1903,GL_RG=0x8227,GL_RGB=0x1907,GL_RGBA=0x1908}; -enum {GL_ETC1_RGB8_OES=0x8d64}; - -#define ETC1_RGB_NO_MIPMAPS 0 -#define ETC1_RGBA_NO_MIPMAPS 1 -#define ETC1_RGB_MIPMAPS 2 -#define ETC1_RGBA_MIPMAPS 3 - -// The error metric Wr Wg Wb should be definied so that Wr^2 + Wg^2 + Wb^2 = 1. -// Hence it is easier to first define the squared values and derive the weights -// as their square-roots. - - -// Alternative weights -//#define PERCEPTUAL_WEIGHT_R_SQUARED 0.3086 -//#define PERCEPTUAL_WEIGHT_G_SQUARED 0.6094 -//#define PERCEPTUAL_WEIGHT_B_SQUARED 0.082 - -#define PERCEPTUAL_WEIGHT_R (sqrt(PERCEPTUAL_WEIGHT_R_SQUARED)) -#define PERCEPTUAL_WEIGHT_G (sqrt(PERCEPTUAL_WEIGHT_G_SQUARED)) -#define PERCEPTUAL_WEIGHT_B (sqrt(PERCEPTUAL_WEIGHT_B_SQUARED)) - - -double wR = PERCEPTUAL_WEIGHT_R; -double wG = PERCEPTUAL_WEIGHT_G; -double wB = PERCEPTUAL_WEIGHT_B; - -double wR2 = PERCEPTUAL_WEIGHT_R_SQUARED; -double wG2 = PERCEPTUAL_WEIGHT_G_SQUARED; -double wB2 = PERCEPTUAL_WEIGHT_B_SQUARED; - -void read_big_endian_2byte_word(unsigned short *blockadr, FILE *f) -{ - uint8 bytes[2]; - unsigned short block; - - fread(&bytes[0], 1, 1, f); - fread(&bytes[1], 1, 1, f); - - block = 0; - - block |= bytes[0]; - block = block << 8; - block |= bytes[1]; - - blockadr[0] = block; -} - -void read_big_endian_4byte_word(unsigned int *blockadr, FILE *f) -{ - uint8 bytes[4]; - unsigned int block; - - fread(&bytes[0], 1, 1, f); - fread(&bytes[1], 1, 1, f); - fread(&bytes[2], 1, 1, f); - fread(&bytes[3], 1, 1, f); - - block = 0; - - block |= bytes[0]; - block = block << 8; - block |= bytes[1]; - block = block << 8; - block |= bytes[2]; - block = block << 8; - block |= bytes[3]; - - blockadr[0] = block; -} - - - -bool fileExist(const char *filename) -{ - FILE *f=NULL; - if((f=fopen(filename,"rb"))!=NULL) - { - fclose(f); - return true; - } - return false; -} - -bool expandToWidthDivByFour(uint8 *&img, int width, int height, int &expandedwidth, int &expandedheight) -{ - int wdiv4; - int xx, yy; - uint8 *newimg; - - wdiv4 = width /4; - if( !(wdiv4 *4 == width) ) - { - expandedwidth = (wdiv4 + 1)*4; - expandedheight = height; - newimg=(uint8*)malloc(3*expandedwidth*expandedheight); - if(!newimg) - { - printf("Could not allocate memory to expand width\n"); - return false; - } - - // First copy image - for(yy = 0; yy> 8) & 0xff; - bytes[1] = (block >> 0) & 0xff; - - fwrite(&bytes[0],1,1,f); - fwrite(&bytes[1],1,1,f); -} - -void write_big_endian_4byte_word(unsigned int *blockadr, FILE *f) -{ - uint8 bytes[4]; - unsigned int block; - - block = blockadr[0]; - - bytes[0] = (block >> 24) & 0xff; - bytes[1] = (block >> 16) & 0xff; - bytes[2] = (block >> 8) & 0xff; - bytes[3] = (block >> 0) & 0xff; - - fwrite(&bytes[0],1,1,f); - fwrite(&bytes[1],1,1,f); - fwrite(&bytes[2],1,1,f); - fwrite(&bytes[3],1,1,f); -} - - -int find_pos_of_extension(const char *src) -{ - int q=strlen(src); - while(q>=0) // find file name extension - { - if(src[q]=='.') break; - q--; - } - if(q<0) - return -1; - else - return q; -} - -bool readSrcFile(const char *filename,uint8 *&img,int &width,int &height, int &expandedwidth, int &expandedheight) -{ - int w1,h1; - int wdiv4, hdiv4; - char str[255]; - - - // Delete temp file if it exists. - if(fileExist("tmp.ppm")) - { - sprintf(str, "del tmp.ppm\n"); - system(str); - } - - - int q = find_pos_of_extension(filename); - if(!strcmp(&filename[q],".ppm")) - { - // Already a .ppm file. Just copy. - sprintf(str,"copy %s tmp.ppm \n", filename); - printf("Copying source file %s to tmp.ppm\n", filename); - } - else - { - // Converting from other format to .ppm - // - // Use your favorite command line image converter program, - // for instance Image Magick. Just make sure the syntax can - // be written as below: - // - // C:\imconv source.jpg dest.ppm - // - sprintf(str,"imconv %s tmp.ppm\n", filename); - printf("Converting source file from %s to .ppm\n", filename); - } - // Execute system call - system(str); - - bool FLIP; - if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0) - FLIP = false; - else if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T1) - FLIP = true; - else - { - printf("orientation error\n"); - exit(1); - } - - if(fReadPPM("tmp.ppm",w1,h1,img,FLIP)) - { - width=w1; - height=h1; - system("del tmp.ppm"); - - // Width must be divisible by 2 and height must be - // divisible by 4. Otherwise, we will not compress - // the image. - - wdiv4 = width / 4; - hdiv4 = height / 4; - - expandedwidth = width; - expandedheight = height; - - if( !(wdiv4 * 4 == width) ) - { - printf(" Width = %d is not divisible by four... ", width); - printf(" expanding image in x-dir... "); - if(expandToWidthDivByFour(img, width, height, expandedwidth, expandedheight)) - { - printf("OK.\n"); - } - else - { - printf("\n Error: could not expand image\n"); - return false; - } - } - if( !(hdiv4 * 4 == height)) - { - printf(" Height = %d is not divisible by four... ", height); - printf(" expanding image in y-dir..."); - if(expandToHeightDivByFour(img, expandedwidth, height, expandedwidth, expandedheight)) - { - printf("OK.\n"); - } - else - { - printf("\n Error: could not expand image\n"); - return false; - } - } - if(!(expandedwidth == width && expandedheight == height)) - printf("Active pixels: %dx%d. Expanded image: %dx%d\n",width,height,expandedwidth,expandedheight); - return true; - } - return false; - -} -bool readSrcFileNoExpand(const char *filename,uint8 *&img,int &width,int &height) -{ - int w1,h1; - char str[255]; - - - // Delete temp file if it exists. - if(fileExist("tmp.ppm")) - { - sprintf(str, "del tmp.ppm\n"); - system(str); - } - - - int q = find_pos_of_extension(filename); - if(!strcmp(&filename[q],".ppm")) - { - // Already a .ppm file. Just copy. - sprintf(str,"copy %s tmp.ppm \n", filename); - printf("Copying source file %s to tmp.ppm\n", filename); - } - else - { - // Converting from other format to .ppm - // - // Use your favorite command line image converter program, - // for instance Image Magick. Just make sure the syntax can - // be written as below: - // - // C:\imconv source.jpg dest.ppm - // - sprintf(str,"imconv %s tmp.ppm\n", filename); - printf("Converting source file from %s to .ppm\n", filename); - } - // Execute system call - system(str); - - // The current function is only used when comparing two ppm files --- we don't need to flip them. Hence reverse_y is false - if(fReadPPM("tmp.ppm",w1,h1,img,false)) - { - width=w1; - height=h1; - system("del tmp.ppm"); - - return true; - } - return false; - -} - - -void compressImageFile(uint8 *img,int width,int height,char *dstfile, int expandedwidth, int expandedheight, int action) -{ - FILE *f; - int x,y,w,h; - unsigned int block1, block2; - unsigned short wi, hi; - unsigned char magic[4]; - unsigned char version[2]; - unsigned short texture_type; - uint8 *imgdec; - - imgdec = (unsigned char*) malloc(expandedwidth*expandedheight*3); - if(!imgdec) - { - printf("Could not allocate decompression buffer --- exiting\n"); - exit(1); - } - - magic[0] = 'P'; magic[1] = 'K'; magic[2] = 'M'; magic[3] = ' '; - version[0] = '1'; version[1] = '0'; - texture_type = ETC1_RGB_NO_MIPMAPS; - - if((f=fopen(dstfile,"wb"))) - { - w=expandedwidth/4; w*=4; - h=expandedheight/4; h*=4; - wi = w; - hi = h; - - if(ktx_mode) - { - printf("Outputting to .kxt file...\n"); - //.ktx file: KTX header followed by compressed binary data. - KTX_header header; - //identifier - for(int i=0; i<12; i++) - { - header.identifier[i]=ktx_identifier[i]; - } - //endianess int.. if this comes out reversed, all of the other ints will too. - header.endianness=KTX_ENDIAN_REF; - - //these values are always 0/1 for compressed textures. - header.glType=0; - header.glTypeSize=1; - header.glFormat=0; - - header.pixelWidth=width; - header.pixelHeight=height; - header.pixelDepth=0; - - //we only support single non-mipmapped non-cubemap textures.. - header.numberOfArrayElements=0; - header.numberOfFaces=1; - header.numberOfMipmapLevels=1; - - //and no metadata.. - header.bytesOfKeyValueData=0; - - int halfbytes=1; - //header.glInternalFormat=? - //header.glBaseInternalFormat=? - if(texture_type==ETC1_RGB_NO_MIPMAPS) - { - header.glBaseInternalFormat=GL_RGB; - header.glInternalFormat=GL_ETC1_RGB8_OES; - } - else - { - printf("internal error: bad format!\n"); - exit(1); - } - //write header - fwrite(&header,sizeof(KTX_header),1,f); - - //write size of compressed data.. which depend on the expanded size.. - unsigned int imagesize=(w*h*halfbytes)/2; - fwrite(&imagesize,sizeof(int),1,f); - } - else - { - printf("outputting to .pkm file...\n"); - // Write magic number - fwrite(&magic[0], sizeof(unsigned char), 1, f); - fwrite(&magic[1], sizeof(unsigned char), 1, f); - fwrite(&magic[2], sizeof(unsigned char), 1, f); - fwrite(&magic[3], sizeof(unsigned char), 1, f); - - // Write version - fwrite(&version[0], sizeof(unsigned char), 1, f); - fwrite(&version[1], sizeof(unsigned char), 1, f); - - // Write texture type - write_big_endian_2byte_word(&texture_type, f); - - // Write binary header: the width and height as unsigned 16-bit words - write_big_endian_2byte_word(&wi, f); - write_big_endian_2byte_word(&hi, f); - - // Also write the active pixels. For instance, if we want to compress - // a 128 x 129 image, we have to extend it to 128 x 132 pixels. - // Then the wi and hi written above will be 128 and 132, but the - // additional information that we write below will be 128 and 129, - // to indicate that it is only the top 129 lines of data in the - // decompressed image that will be valid data, and the rest will - // be just garbage. - - unsigned short activew, activeh; - activew = width; - activeh = height; - - write_big_endian_2byte_word(&activew, f); - write_big_endian_2byte_word(&activeh, f); - } - - int totblocks = expandedheight/4 * expandedwidth/4; - int countblocks = 0; - - /// xxx - for(y=0;y.\n",dstfile); - } - - free(imgdec); -} - -double calculatePSNR(uint8 *lossyimg, uint8 *origimg, int width, int height) -{ - // calculate Mean Square Error (MSE) - - int x,y; - double MSE; - double PSNR; - double err; - MSE = 0; - - // Note: This calculation of PSNR uses the formula - // - // PSNR = 10 * log_10 ( 255^2 / MSE ) - // - // where the MSE is calculated as - // - // 1/(N*M) * sum ( 1/3 * ((R' - R)^2 + (G' - G)^2 + (B' - B)^2) ) - // - // The reason for having the 1/3 factor is the following: - // Presume we have a grayscale image, that is acutally just the red component - // of a color image.. The squared error is then (R' - R)^2. - // Assume that we have a certain signal to noise ratio, say 30 dB. If we add - // another two components (say green and blue) with the same signal to noise - // ratio, we want the total signal to noise ratio be the same. For the - // squared error to remain constant we must divide by three after adding - // together the squared errors of the components. - - for(y=0;y.\n",srcfile); - return -1; - } -} - -void compressFile(char *srcfile,char *dstfile, int action) -{ - uint8 *srcimg; - int width,height; - int extendedwidth, extendedheight; - double PSNR; - - printf("\n"); - switch(action) - { - case 0: - printf("Using FAST compression mode and NONPERCEPTUAL error metric\n"); - break; - case 1: - printf("Using MEDIUM-speed compression mode and NONPERCEPTUAL error metric\n"); - break; - case 2: - printf("Using SLOW compression mode and NONPERCEPTUAL error metric\n"); - break; - case 3: - printf("Using FAST compression mode and PERCEPTUAL error metric\n"); - break; - case 4: - printf("Using MEDIUM-speed compression mode and PERCEPTUAL error metric\n"); - break; - case 5: - printf("Using SLOW compression mode and PERCEPTUAL error metric\n"); - break; - } - printf("Using the orientation that maps the first pixel in .ppm file to "); - if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0) - printf("s=0, t=0.\n"); - else if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T1) - printf("s=0, t=1.\n"); - - if(readSrcFile(srcfile,srcimg,width,height,extendedwidth, extendedheight)) - { - printf("Compressing...\n"); - compressImageFile(srcimg,width,height,dstfile,extendedwidth, extendedheight, action); - PSNR = calculatePSNRfile(dstfile, srcimg); - free(srcimg); - printf("PSNR = %f\n",PSNR); - } -} - -double calculatePSNRTwoFiles(char *srcfile1,char *srcfile2) -{ - uint8 *srcimg1; - uint8 *srcimg2; - int width1, height1; - int width2, height2; - double PSNR = 0.0f; - double perceptually_weighted_PSNR; - - if(readSrcFileNoExpand(srcfile1,srcimg1,width1,height1)) - { - if(readSrcFileNoExpand(srcfile2,srcimg2,width2,height2)) - { - if((width1 == width2) && (height1 == height2)) - { - PSNR = calculatePSNR(srcimg1, srcimg2, width1, height1); - printf("PSNR = %f\n",PSNR); - perceptually_weighted_PSNR = calculatePerceptuallyWeightedPSNR(srcimg1, srcimg2, width1, height1); - printf("perceptually weighted PSNR = (%f)\n",perceptually_weighted_PSNR); - - } - else - { - printf("\n Width and height do no not match for image: width, height = (%d, %d) and (%d, %d)\n",width1,height1, width2, height2); - } - } - else - { - printf("Couldn't open file %s.\n",srcfile2); - } - } - else - { - printf("Couldn't open file %s.\n",srcfile1); - } - - return PSNR; -} - - -void uncompressFile(char *srcfile,char *dstfile) -{ - FILE *f; - int width,height; - unsigned int block_part1, block_part2; - uint8 *img, *newimg; - char str[300]; - unsigned short w, h; - int xx, yy; - unsigned char magic[4]; - unsigned char version[2]; - unsigned short texture_type; - int active_width; - int active_height; - int format; - - f=fopen(srcfile,"rb"); - if (f) - { - if(ktx_mode) - { - //read ktx header.. - KTX_header header; - fread(&header,sizeof(KTX_header),1,f); - //read size parameter, which we don't actually need.. - unsigned int bitsize; - fread(&bitsize,sizeof(unsigned int),1,f); - - active_width = header.pixelWidth; - active_height = header.pixelHeight; - w = ((active_width+3)/4)*4; - h = ((active_height+3)/4)*4; - width=w; - height=h; - - if(header.glInternalFormat==GL_ETC1_RGB8_OES) - { - format=ETC1_RGB_NO_MIPMAPS; - } - else { - printf("ktx file has unknown glInternalFormat (not etc compressed)!\n"); - exit(1); - } - } - else - { - // Read magic nunmber - fread(&magic[0], sizeof(unsigned char), 1, f); - fread(&magic[1], sizeof(unsigned char), 1, f); - fread(&magic[2], sizeof(unsigned char), 1, f); - fread(&magic[3], sizeof(unsigned char), 1, f); - if(!(magic[0] == 'P' && magic[1] == 'K' && magic[2] == 'M' && magic[3] == ' ')) - { - printf("\n\n The file %s is not a .pkm file.\n",srcfile); - exit(1); - } - - // Read version - fread(&version[0], sizeof(unsigned char), 1, f); - fread(&version[1], sizeof(unsigned char), 1, f); - if(!(version[0] == '1' && version[1] == '0')) - { - printf("\n\n The file %s is not of version 1.0 but of version %c.%c.\n",srcfile, version[0], version[1]); - exit(1); - } - - // Read texture type - read_big_endian_2byte_word(&texture_type, f); - if(!(texture_type == ETC1_RGB_NO_MIPMAPS)) - { - printf("\n\n The file %s does not contain a ETC1_RGB_NO_MIPMAPS texture.\n", srcfile); - exit(1); - } - - // Read how many pixels the blocks make up - - read_big_endian_2byte_word(&w, f); - read_big_endian_2byte_word(&h, f); - width = w; - height = h; - - // Read how many pixels contain active data (the rest are just - // for making sure we have a 2*a x 4*b size). - - read_big_endian_2byte_word(&w, f); - read_big_endian_2byte_word(&h, f); - active_width = w; - active_height = h; - } - - printf("Width = %d, Height = %d\n",width, height); - printf("active pixel area: top left %d x %d area.\n",active_width, active_height); - - img=(uint8*)malloc(3*width*height); - if(!img) - { - printf("Error: could not allocate memory\n"); - exit(0); - } - - - for(int y=0;y.\n",srcfile); - } -} - -int determineAction(int argc,char *argv[],char *dst) -{ - char *src; - int q; - - enum {MODE_COMPRESS, MODE_UNCOMPRESS, MODE_PSNR}; - enum {SPEED_SLOW, SPEED_FAST, SPEED_MEDIUM}; - enum {METRIC_PERCEPTUAL, METRIC_NONPERCEPTUAL}; - - int mode = MODE_COMPRESS; - int speed = SPEED_FAST; - int metric = METRIC_PERCEPTUAL; - - // A bit hackish: First check for the orientation flag. When this flag is set, remove it from the string and proceed with the rest of the arguments as before. - - bool orientation_flag_found = false; - orientation = FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0; - - for(q = 1; q < argc && !orientation_flag_found; q++) - { - src = argv[q]; - if(!strcmp(src, "-o")) - { - orientation_flag_found = true; - src = argv[q+1]; - if(!strcmp(src, "topleftmapsto_s0t0")) - { - orientation = FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0; - } - else if(!strcmp(src, "bottomleftmapsto_s0t0")) - { - orientation = FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T1; - } - else - { - return -1; - } - // At this stage in the code we know we have a valid orientation argument. - // Now remove it from the argument list. - for(int xx=q+2; xx does not exist.\n",srcfile); - exit(0); - } - // 0: compress from .any to .pkm with SPEED_FAST, METRIC_NONPERCEPTUAL, - // 1: compress from .any to .pkm with SPEED_MEDIUM, METRIC_NONPERCEPTUAL, - // 2: compress from .any to .pkm with SPEED_SLOW, METRIC_NONPERCEPTUAL, - // 3: compress from .any to .pkm with SPEED_FAST, METRIC_PERCEPTUAL, - // 4: compress from .any to .pkm with SPEED_MEDIUM, METRIC_PERCEPTUAL, - // 5: compress from .any to .pkm with SPEED_SLOW, METRIC_PERCEPTUAL, - // 6: decompress from .pkm to .any - // 7: calculate PSNR between .any and .any - - if(action == 6) - { - printf("Uncompressing from .pkm file ...\n"); - printf("Using the orientation that maps the first pixel in .ppm file to "); - if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T0) - printf("s=0, t=0.\n"); - else if(orientation == FIRST_PIXEL_IN_PPM_FILE_MAPS_TO_S0T1) - printf("s=0, t=1.\n"); - - uncompressFile(srcfile,dstfile); - } - else if(action == 7) - { - printf("Calculating PSNR between files...\n"); - calculatePSNRTwoFiles(srcfile,dstfile); - } - else - { - compressFile(srcfile, dstfile, action); - } - } - } else { - printf("ETCPACK v1.06\n"); - printf("Usage: etcpack srcfile dstfile\n\nCompresses and decompresses images using the Ericsson Texture Compression (ETC) scheme.\n\n"); - printf(" -s {fast|medium|slow} Compression speed. Slow = best quality\n"); - printf(" (default: fast)\n"); - printf(" -e {perceptual|nonperceptual} Error metric: Perceptual (nicest) or \n"); - printf(" nonperceptual (highest PSNR)\n"); - printf(" (default: perceptual)\n"); - printf(" -o {topleftmapsto_s0t0| Orientation: Which pixel (top left or\n"); - printf(" bottomleftmapsto_s0t0} bottom left) that will map to texture\n"); - printf(" coordinates (s=0, t=0). \n"); - printf(" (default: topleftmapsto_s0t0.) For a \n"); - printf(" .ppm file this means that the first \n"); - printf(" pixel in the file will be mapped to \n"); - printf(" s=0, t=0 by default.\n"); - printf(" \n"); - printf("Examples: \n"); - printf(" etcpack img.ppm img.ktx Compresses img.ppm to img.ktx\n"); - printf(" etcpack img.ppm img.pkm Compresses img.ppm to img.pkm\n"); - printf(" etcpack img.ktx img_copy.ppm Decompresses img.ktx to img_copy.ppm\n"); - printf(" etcpack -s slow img.ppm img.ktx Compress using the slow mode.\n"); - printf(" etcpack -p orig.ppm copy.ppm Calculate PSNR between orig and copy\n\n"); - - } - return 0; - -} diff --git a/ext/etcpack/image.cpp b/ext/etcpack/image.cpp deleted file mode 100644 index f067877467..0000000000 --- a/ext/etcpack/image.cpp +++ /dev/null @@ -1,212 +0,0 @@ -// image.cxx -// -// NO WARRANTY -// -// BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, ERICSSON MAKES NO -// REPRESENTATIONS OF ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND; EITHER -// EXPRESS OR IMPLIED; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -// PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME -// THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON -// MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, LEASE, USE OR -// IMPORTATION WILL BE FREE FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR -// OTHER INTELLECTUAL PROPERTY RIGHTS OF OTHERS, AND IT SHALL BE THE SOLE -// RESPONSIBILITY OF THE LICENSEE TO MAKE SUCH DETERMINATION AS IS -// NECESSARY WITH RESPECT TO THE ACQUISITION OF LICENSES UNDER PATENTS -// AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES; -// -// IN NO EVENT WILL ERICSSON, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -// GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF -// THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO -// LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -// YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY -// OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGES. -// -// (C) Ericsson AB 2005. All Rights Reserved. -// -#include -#include -#include -#include "image.h" - -// Removes comments in a .ppm file -// (i.e., lines starting with #) -// -// Written by Jacob Strom -// -void removeComments(FILE *f1) -{ - int c; - - while((c = getc(f1)) == '#') - { - char line[1024]; - fgets(line, 1024, f1); - } - ungetc(c, f1); -} - - -// Removes white spaces in a .ppm file -// -// Written by Jacob Strom -// -void removeSpaces(FILE *f1) -{ - int c; - - c = getc(f1); - while(c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r') - { - c = getc(f1); - } - ungetc(c, f1); -} - -// fReadPPM -// -// Written by Jacob Strom -// -// reads a ppm file with P6 header (meaning binary, as opposed to P5, which is ascII) -// and returns the image in pixels. -// -// The header must look like this: -// -// P6 -// # Comments (not necessary) -// width height -// 255 -// -// after that follows RGBRGBRGB... -// -bool fReadPPM(const char *filename, int &width, int &height, unsigned char *&pixels, bool reverse_y) -{ - FILE *f1; - int mustbe255; - f1 = fopen(filename, "rb"); - - if(f1) - { - char line[255]; - - removeSpaces(f1); - removeComments(f1); - removeSpaces(f1); - - fscanf(f1, "%s", line); - - if(strcmp(line, "P6")!=0) - { - printf("Error: %s is not binary\n", filename); - printf("(Binary .ppm files start with P6).\n"); - fclose(f1); - return false; - } - removeSpaces(f1); - removeComments(f1); - removeSpaces(f1); - - fscanf(f1, "%d %d", &width, &height); - if( width<=0 || height <=0) - { - printf("Error: width or height negative. File: %s\n",filename); - fclose(f1); - return false; - } - - removeSpaces(f1); - removeComments(f1); - removeSpaces(f1); - - fscanf(f1, "%d", &mustbe255); - if( mustbe255!= 255 ) - { - printf("Error: Color resolution must be 255. File: %s\n",filename); - fclose(f1); - return false; - } - - // We need to remove the newline. - char c = 0; - while(c != '\n') - fscanf(f1, "%c", &c); - - - pixels = (unsigned char*) malloc(3*width*height); - - if(!pixels) - { - printf("Error: Could not allocate memory for image. File: %s\n", filename); - fclose(f1); - return false; - } - - if(reverse_y) - { - for(int yy = 0; yy +// Please see ZLIB license at the end of rg_etc1.h. +// +// For more information Ericsson Texture Compression (ETC/ETC1), see: +// http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt +// +// v1.03 - 5/12/13 - Initial public release +#include "rg_etc1.h" + +#include +#include +#include +//#include +#include + +#pragma warning (disable: 4201) // nonstandard extension used : nameless struct/union + +#if defined(_DEBUG) || defined(DEBUG) +#define RG_ETC1_BUILD_DEBUG +#endif + +#define RG_ETC1_ASSERT assert + +namespace rg_etc1 +{ + typedef unsigned char uint8; + typedef unsigned short uint16; + typedef unsigned int uint; + typedef unsigned int uint32; + typedef long long int64; + typedef unsigned long long uint64; + + const uint32 cUINT32_MAX = 0xFFFFFFFFU; + const uint64 cUINT64_MAX = 0xFFFFFFFFFFFFFFFFULL; //0xFFFFFFFFFFFFFFFFui64; + + template inline T minimum(T a, T b) { return (a < b) ? a : b; } + template inline T minimum(T a, T b, T c) { return minimum(minimum(a, b), c); } + template inline T maximum(T a, T b) { return (a > b) ? a : b; } + template inline T maximum(T a, T b, T c) { return maximum(maximum(a, b), c); } + template inline T clamp(T value, T low, T high) { return (value < low) ? low : ((value > high) ? high : value); } + template inline T square(T value) { return value * value; } + template inline void zero_object(T& obj) { memset((void*)&obj, 0, sizeof(obj)); } + template inline void zero_this(T* pObj) { memset((void*)pObj, 0, sizeof(*pObj)); } + + template T decay_array_to_subtype(T (&a)[N]); + +#define RG_ETC1_ARRAY_SIZE(X) (sizeof(X) / sizeof(decay_array_to_subtype(X))) + + enum eNoClamp { cNoClamp }; + + struct color_quad_u8 + { + static inline int clamp(int v) { if (v & 0xFFFFFF00U) v = (~(static_cast(v) >> 31)) & 0xFF; return v; } + + struct component_traits { enum { cSigned = false, cFloat = false, cMin = 0U, cMax = 255U }; }; + + public: + typedef unsigned char component_t; + typedef int parameter_t; + + enum { cNumComps = 4 }; + + union + { + struct + { + component_t r; + component_t g; + component_t b; + component_t a; + }; + + component_t c[cNumComps]; + + uint32 m_u32; + }; + + inline color_quad_u8() + { + } + + inline color_quad_u8(const color_quad_u8& other) : m_u32(other.m_u32) + { + } + + explicit inline color_quad_u8(parameter_t y, parameter_t alpha = component_traits::cMax) + { + set(y, alpha); + } + + inline color_quad_u8(parameter_t red, parameter_t green, parameter_t blue, parameter_t alpha = component_traits::cMax) + { + set(red, green, blue, alpha); + } + + explicit inline color_quad_u8(eNoClamp, parameter_t y, parameter_t alpha = component_traits::cMax) + { + set_noclamp_y_alpha(y, alpha); + } + + inline color_quad_u8(eNoClamp, parameter_t red, parameter_t green, parameter_t blue, parameter_t alpha = component_traits::cMax) + { + set_noclamp_rgba(red, green, blue, alpha); + } + + inline void clear() + { + m_u32 = 0; + } + + inline color_quad_u8& operator= (const color_quad_u8& other) + { + m_u32 = other.m_u32; + return *this; + } + + inline color_quad_u8& set_rgb(const color_quad_u8& other) + { + r = other.r; + g = other.g; + b = other.b; + return *this; + } + + inline color_quad_u8& operator= (parameter_t y) + { + set(y, component_traits::cMax); + return *this; + } + + inline color_quad_u8& set(parameter_t y, parameter_t alpha = component_traits::cMax) + { + y = clamp(y); + alpha = clamp(alpha); + r = static_cast(y); + g = static_cast(y); + b = static_cast(y); + a = static_cast(alpha); + return *this; + } + + inline color_quad_u8& set_noclamp_y_alpha(parameter_t y, parameter_t alpha = component_traits::cMax) + { + RG_ETC1_ASSERT( (y >= component_traits::cMin) && (y <= component_traits::cMax) ); + RG_ETC1_ASSERT( (alpha >= component_traits::cMin) && (alpha <= component_traits::cMax) ); + + r = static_cast(y); + g = static_cast(y); + b = static_cast(y); + a = static_cast(alpha); + return *this; + } + + inline color_quad_u8& set(parameter_t red, parameter_t green, parameter_t blue, parameter_t alpha = component_traits::cMax) + { + r = static_cast(clamp(red)); + g = static_cast(clamp(green)); + b = static_cast(clamp(blue)); + a = static_cast(clamp(alpha)); + return *this; + } + + inline color_quad_u8& set_noclamp_rgba(parameter_t red, parameter_t green, parameter_t blue, parameter_t alpha) + { + RG_ETC1_ASSERT( (red >= component_traits::cMin) && (red <= component_traits::cMax) ); + RG_ETC1_ASSERT( (green >= component_traits::cMin) && (green <= component_traits::cMax) ); + RG_ETC1_ASSERT( (blue >= component_traits::cMin) && (blue <= component_traits::cMax) ); + RG_ETC1_ASSERT( (alpha >= component_traits::cMin) && (alpha <= component_traits::cMax) ); + + r = static_cast(red); + g = static_cast(green); + b = static_cast(blue); + a = static_cast(alpha); + return *this; + } + + inline color_quad_u8& set_noclamp_rgb(parameter_t red, parameter_t green, parameter_t blue) + { + RG_ETC1_ASSERT( (red >= component_traits::cMin) && (red <= component_traits::cMax) ); + RG_ETC1_ASSERT( (green >= component_traits::cMin) && (green <= component_traits::cMax) ); + RG_ETC1_ASSERT( (blue >= component_traits::cMin) && (blue <= component_traits::cMax) ); + + r = static_cast(red); + g = static_cast(green); + b = static_cast(blue); + return *this; + } + + static inline parameter_t get_min_comp() { return component_traits::cMin; } + static inline parameter_t get_max_comp() { return component_traits::cMax; } + static inline bool get_comps_are_signed() { return component_traits::cSigned; } + + inline component_t operator[] (uint i) const { RG_ETC1_ASSERT(i < cNumComps); return c[i]; } + inline component_t& operator[] (uint i) { RG_ETC1_ASSERT(i < cNumComps); return c[i]; } + + inline color_quad_u8& set_component(uint i, parameter_t f) + { + RG_ETC1_ASSERT(i < cNumComps); + + c[i] = static_cast(clamp(f)); + + return *this; + } + + inline color_quad_u8& set_grayscale(parameter_t l) + { + component_t x = static_cast(clamp(l)); + c[0] = x; + c[1] = x; + c[2] = x; + return *this; + } + + inline color_quad_u8& clamp(const color_quad_u8& l, const color_quad_u8& h) + { + for (uint i = 0; i < cNumComps; i++) + c[i] = static_cast(rg_etc1::clamp(c[i], l[i], h[i])); + return *this; + } + + inline color_quad_u8& clamp(parameter_t l, parameter_t h) + { + for (uint i = 0; i < cNumComps; i++) + c[i] = static_cast(rg_etc1::clamp(c[i], l, h)); + return *this; + } + + // Returns CCIR 601 luma (consistent with color_utils::RGB_To_Y). + inline parameter_t get_luma() const + { + return static_cast((19595U * r + 38470U * g + 7471U * b + 32768U) >> 16U); + } + + // Returns REC 709 luma. + inline parameter_t get_luma_rec709() const + { + return static_cast((13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U); + } + + inline uint squared_distance_rgb(const color_quad_u8& c) const + { + return rg_etc1::square(r - c.r) + rg_etc1::square(g - c.g) + rg_etc1::square(b - c.b); + } + + inline uint squared_distance_rgba(const color_quad_u8& c) const + { + return rg_etc1::square(r - c.r) + rg_etc1::square(g - c.g) + rg_etc1::square(b - c.b) + rg_etc1::square(a - c.a); + } + + inline bool rgb_equals(const color_quad_u8& rhs) const + { + return (r == rhs.r) && (g == rhs.g) && (b == rhs.b); + } + + inline bool operator== (const color_quad_u8& rhs) const + { + return m_u32 == rhs.m_u32; + } + + color_quad_u8& operator+= (const color_quad_u8& other) + { + for (uint i = 0; i < 4; i++) + c[i] = static_cast(clamp(c[i] + other.c[i])); + return *this; + } + + color_quad_u8& operator-= (const color_quad_u8& other) + { + for (uint i = 0; i < 4; i++) + c[i] = static_cast(clamp(c[i] - other.c[i])); + return *this; + } + + friend color_quad_u8 operator+ (const color_quad_u8& lhs, const color_quad_u8& rhs) + { + color_quad_u8 result(lhs); + result += rhs; + return result; + } + + friend color_quad_u8 operator- (const color_quad_u8& lhs, const color_quad_u8& rhs) + { + color_quad_u8 result(lhs); + result -= rhs; + return result; + } + }; // class color_quad_u8 + + struct vec3F + { + float m_s[3]; + + inline vec3F() { } + inline vec3F(float s) { m_s[0] = s; m_s[1] = s; m_s[2] = s; } + inline vec3F(float x, float y, float z) { m_s[0] = x; m_s[1] = y; m_s[2] = z; } + + inline float operator[] (uint i) const { RG_ETC1_ASSERT(i < 3); return m_s[i]; } + + inline vec3F& operator += (const vec3F& other) { for (uint i = 0; i < 3; i++) m_s[i] += other.m_s[i]; return *this; } + + inline vec3F& operator *= (float s) { for (uint i = 0; i < 3; i++) m_s[i] *= s; return *this; } + }; + + enum etc_constants + { + cETC1BytesPerBlock = 8U, + + cETC1SelectorBits = 2U, + cETC1SelectorValues = 1U << cETC1SelectorBits, + cETC1SelectorMask = cETC1SelectorValues - 1U, + + cETC1BlockShift = 2U, + cETC1BlockSize = 1U << cETC1BlockShift, + + cETC1LSBSelectorIndicesBitOffset = 0, + cETC1MSBSelectorIndicesBitOffset = 16, + + cETC1FlipBitOffset = 32, + cETC1DiffBitOffset = 33, + + cETC1IntenModifierNumBits = 3, + cETC1IntenModifierValues = 1 << cETC1IntenModifierNumBits, + cETC1RightIntenModifierTableBitOffset = 34, + cETC1LeftIntenModifierTableBitOffset = 37, + + // Base+Delta encoding (5 bit bases, 3 bit delta) + cETC1BaseColorCompNumBits = 5, + cETC1BaseColorCompMax = 1 << cETC1BaseColorCompNumBits, + + cETC1DeltaColorCompNumBits = 3, + cETC1DeltaColorComp = 1 << cETC1DeltaColorCompNumBits, + cETC1DeltaColorCompMax = 1 << cETC1DeltaColorCompNumBits, + + cETC1BaseColor5RBitOffset = 59, + cETC1BaseColor5GBitOffset = 51, + cETC1BaseColor5BBitOffset = 43, + + cETC1DeltaColor3RBitOffset = 56, + cETC1DeltaColor3GBitOffset = 48, + cETC1DeltaColor3BBitOffset = 40, + + // Absolute (non-delta) encoding (two 4-bit per component bases) + cETC1AbsColorCompNumBits = 4, + cETC1AbsColorCompMax = 1 << cETC1AbsColorCompNumBits, + + cETC1AbsColor4R1BitOffset = 60, + cETC1AbsColor4G1BitOffset = 52, + cETC1AbsColor4B1BitOffset = 44, + + cETC1AbsColor4R2BitOffset = 56, + cETC1AbsColor4G2BitOffset = 48, + cETC1AbsColor4B2BitOffset = 40, + + cETC1ColorDeltaMin = -4, + cETC1ColorDeltaMax = 3, + + // Delta3: + // 0 1 2 3 4 5 6 7 + // 000 001 010 011 100 101 110 111 + // 0 1 2 3 -4 -3 -2 -1 + }; + + static uint8 g_quant5_tab[256+16]; + + static const int g_etc1_inten_tables[cETC1IntenModifierValues][cETC1SelectorValues] = + { + { -8, -2, 2, 8 }, { -17, -5, 5, 17 }, { -29, -9, 9, 29 }, { -42, -13, 13, 42 }, + { -60, -18, 18, 60 }, { -80, -24, 24, 80 }, { -106, -33, 33, 106 }, { -183, -47, 47, 183 } + }; + + static const uint8 g_etc1_to_selector_index[cETC1SelectorValues] = { 2, 3, 1, 0 }; + static const uint8 g_selector_index_to_etc1[cETC1SelectorValues] = { 3, 2, 0, 1 }; + + // Given an ETC1 diff/inten_table/selector, and an 8-bit desired color, this table encodes the best packed_color in the low byte, and the abs error in the high byte. + static uint16 g_etc1_inverse_lookup[2*8*4][256]; // [diff/inten_table/selector][desired_color] + + // g_color8_to_etc_block_config[color][table_index] = Supplies for each 8-bit color value a list of packed ETC1 diff/intensity table/selectors/packed_colors that map to that color. + // To pack: diff | (inten << 1) | (selector << 4) | (packed_c << 8) + static const uint16 g_color8_to_etc_block_config_0_255[2][33] = + { + { 0x0000, 0x0010, 0x0002, 0x0012, 0x0004, 0x0014, 0x0006, 0x0016, 0x0008, 0x0018, 0x000A, 0x001A, 0x000C, 0x001C, 0x000E, 0x001E, + 0x0001, 0x0011, 0x0003, 0x0013, 0x0005, 0x0015, 0x0007, 0x0017, 0x0009, 0x0019, 0x000B, 0x001B, 0x000D, 0x001D, 0x000F, 0x001F, 0xFFFF }, + { 0x0F20, 0x0F30, 0x0E32, 0x0F22, 0x0E34, 0x0F24, 0x0D36, 0x0F26, 0x0C38, 0x0E28, 0x0B3A, 0x0E2A, 0x093C, 0x0E2C, 0x053E, 0x0D2E, + 0x1E31, 0x1F21, 0x1D33, 0x1F23, 0x1C35, 0x1E25, 0x1A37, 0x1E27, 0x1839, 0x1D29, 0x163B, 0x1C2B, 0x133D, 0x1B2D, 0x093F, 0x1A2F, 0xFFFF }, + }; + + // Really only [254][11]. + static const uint16 g_color8_to_etc_block_config_1_to_254[254][12] = + { + { 0x021C, 0x0D0D, 0xFFFF }, { 0x0020, 0x0021, 0x0A0B, 0x061F, 0xFFFF }, { 0x0113, 0x0217, 0xFFFF }, { 0x0116, 0x031E, + 0x0B0E, 0x0405, 0xFFFF }, { 0x0022, 0x0204, 0x050A, 0x0023, 0xFFFF }, { 0x0111, 0x0319, 0x0809, 0x170F, 0xFFFF }, { + 0x0303, 0x0215, 0x0607, 0xFFFF }, { 0x0030, 0x0114, 0x0408, 0x0031, 0x0201, 0x051D, 0xFFFF }, { 0x0100, 0x0024, 0x0306, + 0x0025, 0x041B, 0x0E0D, 0xFFFF }, { 0x021A, 0x0121, 0x0B0B, 0x071F, 0xFFFF }, { 0x0213, 0x0317, 0xFFFF }, { 0x0112, + 0x0505, 0xFFFF }, { 0x0026, 0x070C, 0x0123, 0x0027, 0xFFFF }, { 0x0211, 0x0909, 0xFFFF }, { 0x0110, 0x0315, 0x0707, + 0x0419, 0x180F, 0xFFFF }, { 0x0218, 0x0131, 0x0301, 0x0403, 0x061D, 0xFFFF }, { 0x0032, 0x0202, 0x0033, 0x0125, 0x051B, + 0x0F0D, 0xFFFF }, { 0x0028, 0x031C, 0x0221, 0x0029, 0xFFFF }, { 0x0120, 0x0313, 0x0C0B, 0x081F, 0xFFFF }, { 0x0605, + 0x0417, 0xFFFF }, { 0x0216, 0x041E, 0x0C0E, 0x0223, 0x0127, 0xFFFF }, { 0x0122, 0x0304, 0x060A, 0x0311, 0x0A09, 0xFFFF + }, { 0x0519, 0x190F, 0xFFFF }, { 0x002A, 0x0231, 0x0503, 0x0415, 0x0807, 0x002B, 0x071D, 0xFFFF }, { 0x0130, 0x0214, + 0x0508, 0x0401, 0x0133, 0x0225, 0x061B, 0xFFFF }, { 0x0200, 0x0124, 0x0406, 0x0321, 0x0129, 0x100D, 0xFFFF }, { 0x031A, + 0x0D0B, 0x091F, 0xFFFF }, { 0x0413, 0x0705, 0x0517, 0xFFFF }, { 0x0212, 0x0034, 0x0323, 0x0035, 0x0227, 0xFFFF }, { + 0x0126, 0x080C, 0x0B09, 0xFFFF }, { 0x0411, 0x0619, 0x1A0F, 0xFFFF }, { 0x0210, 0x0331, 0x0603, 0x0515, 0x0907, 0x012B, + 0xFFFF }, { 0x0318, 0x002C, 0x0501, 0x0233, 0x0325, 0x071B, 0x002D, 0x081D, 0xFFFF }, { 0x0132, 0x0302, 0x0229, 0x110D, + 0xFFFF }, { 0x0128, 0x041C, 0x0421, 0x0E0B, 0x0A1F, 0xFFFF }, { 0x0220, 0x0513, 0x0617, 0xFFFF }, { 0x0135, 0x0805, + 0x0327, 0xFFFF }, { 0x0316, 0x051E, 0x0D0E, 0x0423, 0xFFFF }, { 0x0222, 0x0404, 0x070A, 0x0511, 0x0719, 0x0C09, 0x1B0F, + 0xFFFF }, { 0x0703, 0x0615, 0x0A07, 0x022B, 0xFFFF }, { 0x012A, 0x0431, 0x0601, 0x0333, 0x012D, 0x091D, 0xFFFF }, { + 0x0230, 0x0314, 0x0036, 0x0608, 0x0425, 0x0037, 0x0329, 0x081B, 0x120D, 0xFFFF }, { 0x0300, 0x0224, 0x0506, 0x0521, + 0x0F0B, 0x0B1F, 0xFFFF }, { 0x041A, 0x0613, 0x0717, 0xFFFF }, { 0x0235, 0x0905, 0xFFFF }, { 0x0312, 0x0134, 0x0523, + 0x0427, 0xFFFF }, { 0x0226, 0x090C, 0x002E, 0x0611, 0x0D09, 0x002F, 0xFFFF }, { 0x0715, 0x0B07, 0x0819, 0x032B, 0x1C0F, + 0xFFFF }, { 0x0310, 0x0531, 0x0701, 0x0803, 0x022D, 0x0A1D, 0xFFFF }, { 0x0418, 0x012C, 0x0433, 0x0525, 0x0137, 0x091B, + 0x130D, 0xFFFF }, { 0x0232, 0x0402, 0x0621, 0x0429, 0xFFFF }, { 0x0228, 0x051C, 0x0713, 0x100B, 0x0C1F, 0xFFFF }, { + 0x0320, 0x0335, 0x0A05, 0x0817, 0xFFFF }, { 0x0623, 0x0527, 0xFFFF }, { 0x0416, 0x061E, 0x0E0E, 0x0711, 0x0E09, 0x012F, + 0xFFFF }, { 0x0322, 0x0504, 0x080A, 0x0919, 0x1D0F, 0xFFFF }, { 0x0631, 0x0903, 0x0815, 0x0C07, 0x042B, 0x032D, 0x0B1D, + 0xFFFF }, { 0x022A, 0x0801, 0x0533, 0x0625, 0x0237, 0x0A1B, 0xFFFF }, { 0x0330, 0x0414, 0x0136, 0x0708, 0x0721, 0x0529, + 0x140D, 0xFFFF }, { 0x0400, 0x0324, 0x0606, 0x0038, 0x0039, 0x110B, 0x0D1F, 0xFFFF }, { 0x051A, 0x0813, 0x0B05, 0x0917, + 0xFFFF }, { 0x0723, 0x0435, 0x0627, 0xFFFF }, { 0x0412, 0x0234, 0x0F09, 0x022F, 0xFFFF }, { 0x0326, 0x0A0C, 0x012E, + 0x0811, 0x0A19, 0x1E0F, 0xFFFF }, { 0x0731, 0x0A03, 0x0915, 0x0D07, 0x052B, 0xFFFF }, { 0x0410, 0x0901, 0x0633, 0x0725, + 0x0337, 0x0B1B, 0x042D, 0x0C1D, 0xFFFF }, { 0x0518, 0x022C, 0x0629, 0x150D, 0xFFFF }, { 0x0332, 0x0502, 0x0821, 0x0139, + 0x120B, 0x0E1F, 0xFFFF }, { 0x0328, 0x061C, 0x0913, 0x0A17, 0xFFFF }, { 0x0420, 0x0535, 0x0C05, 0x0727, 0xFFFF }, { + 0x0823, 0x032F, 0xFFFF }, { 0x0516, 0x071E, 0x0F0E, 0x0911, 0x0B19, 0x1009, 0x1F0F, 0xFFFF }, { 0x0422, 0x0604, 0x090A, + 0x0B03, 0x0A15, 0x0E07, 0x062B, 0xFFFF }, { 0x0831, 0x0A01, 0x0733, 0x052D, 0x0D1D, 0xFFFF }, { 0x032A, 0x0825, 0x0437, + 0x0729, 0x0C1B, 0x160D, 0xFFFF }, { 0x0430, 0x0514, 0x0236, 0x0808, 0x0921, 0x0239, 0x130B, 0x0F1F, 0xFFFF }, { 0x0500, + 0x0424, 0x0706, 0x0138, 0x0A13, 0x0B17, 0xFFFF }, { 0x061A, 0x0635, 0x0D05, 0xFFFF }, { 0x0923, 0x0827, 0xFFFF }, { + 0x0512, 0x0334, 0x003A, 0x0A11, 0x1109, 0x003B, 0x042F, 0xFFFF }, { 0x0426, 0x0B0C, 0x022E, 0x0B15, 0x0F07, 0x0C19, + 0x072B, 0xFFFF }, { 0x0931, 0x0B01, 0x0C03, 0x062D, 0x0E1D, 0xFFFF }, { 0x0510, 0x0833, 0x0925, 0x0537, 0x0D1B, 0x170D, + 0xFFFF }, { 0x0618, 0x032C, 0x0A21, 0x0339, 0x0829, 0xFFFF }, { 0x0432, 0x0602, 0x0B13, 0x140B, 0x101F, 0xFFFF }, { + 0x0428, 0x071C, 0x0735, 0x0E05, 0x0C17, 0xFFFF }, { 0x0520, 0x0A23, 0x0927, 0xFFFF }, { 0x0B11, 0x1209, 0x013B, 0x052F, + 0xFFFF }, { 0x0616, 0x081E, 0x0D19, 0xFFFF }, { 0x0522, 0x0704, 0x0A0A, 0x0A31, 0x0D03, 0x0C15, 0x1007, 0x082B, 0x072D, + 0x0F1D, 0xFFFF }, { 0x0C01, 0x0933, 0x0A25, 0x0637, 0x0E1B, 0xFFFF }, { 0x042A, 0x0B21, 0x0929, 0x180D, 0xFFFF }, { + 0x0530, 0x0614, 0x0336, 0x0908, 0x0439, 0x150B, 0x111F, 0xFFFF }, { 0x0600, 0x0524, 0x0806, 0x0238, 0x0C13, 0x0F05, + 0x0D17, 0xFFFF }, { 0x071A, 0x0B23, 0x0835, 0x0A27, 0xFFFF }, { 0x1309, 0x023B, 0x062F, 0xFFFF }, { 0x0612, 0x0434, + 0x013A, 0x0C11, 0x0E19, 0xFFFF }, { 0x0526, 0x0C0C, 0x032E, 0x0B31, 0x0E03, 0x0D15, 0x1107, 0x092B, 0xFFFF }, { 0x0D01, + 0x0A33, 0x0B25, 0x0737, 0x0F1B, 0x082D, 0x101D, 0xFFFF }, { 0x0610, 0x0A29, 0x190D, 0xFFFF }, { 0x0718, 0x042C, 0x0C21, + 0x0539, 0x160B, 0x121F, 0xFFFF }, { 0x0532, 0x0702, 0x0D13, 0x0E17, 0xFFFF }, { 0x0528, 0x081C, 0x0935, 0x1005, 0x0B27, + 0xFFFF }, { 0x0620, 0x0C23, 0x033B, 0x072F, 0xFFFF }, { 0x0D11, 0x0F19, 0x1409, 0xFFFF }, { 0x0716, 0x003C, 0x091E, + 0x0F03, 0x0E15, 0x1207, 0x0A2B, 0x003D, 0xFFFF }, { 0x0622, 0x0804, 0x0B0A, 0x0C31, 0x0E01, 0x0B33, 0x092D, 0x111D, + 0xFFFF }, { 0x0C25, 0x0837, 0x0B29, 0x101B, 0x1A0D, 0xFFFF }, { 0x052A, 0x0D21, 0x0639, 0x170B, 0x131F, 0xFFFF }, { + 0x0630, 0x0714, 0x0436, 0x0A08, 0x0E13, 0x0F17, 0xFFFF }, { 0x0700, 0x0624, 0x0906, 0x0338, 0x0A35, 0x1105, 0xFFFF }, { + 0x081A, 0x0D23, 0x0C27, 0xFFFF }, { 0x0E11, 0x1509, 0x043B, 0x082F, 0xFFFF }, { 0x0712, 0x0534, 0x023A, 0x0F15, 0x1307, + 0x1019, 0x0B2B, 0x013D, 0xFFFF }, { 0x0626, 0x0D0C, 0x042E, 0x0D31, 0x0F01, 0x1003, 0x0A2D, 0x121D, 0xFFFF }, { 0x0C33, + 0x0D25, 0x0937, 0x111B, 0x1B0D, 0xFFFF }, { 0x0710, 0x0E21, 0x0739, 0x0C29, 0xFFFF }, { 0x0818, 0x052C, 0x0F13, 0x180B, + 0x141F, 0xFFFF }, { 0x0632, 0x0802, 0x0B35, 0x1205, 0x1017, 0xFFFF }, { 0x0628, 0x091C, 0x0E23, 0x0D27, 0xFFFF }, { + 0x0720, 0x0F11, 0x1609, 0x053B, 0x092F, 0xFFFF }, { 0x1119, 0x023D, 0xFFFF }, { 0x0816, 0x013C, 0x0A1E, 0x0E31, 0x1103, + 0x1015, 0x1407, 0x0C2B, 0x0B2D, 0x131D, 0xFFFF }, { 0x0722, 0x0904, 0x0C0A, 0x1001, 0x0D33, 0x0E25, 0x0A37, 0x121B, + 0xFFFF }, { 0x0F21, 0x0D29, 0x1C0D, 0xFFFF }, { 0x062A, 0x0839, 0x190B, 0x151F, 0xFFFF }, { 0x0730, 0x0814, 0x0536, + 0x0B08, 0x1013, 0x1305, 0x1117, 0xFFFF }, { 0x0800, 0x0724, 0x0A06, 0x0438, 0x0F23, 0x0C35, 0x0E27, 0xFFFF }, { 0x091A, + 0x1709, 0x063B, 0x0A2F, 0xFFFF }, { 0x1011, 0x1219, 0x033D, 0xFFFF }, { 0x0812, 0x0634, 0x033A, 0x0F31, 0x1203, 0x1115, + 0x1507, 0x0D2B, 0xFFFF }, { 0x0726, 0x0E0C, 0x052E, 0x1101, 0x0E33, 0x0F25, 0x0B37, 0x131B, 0x0C2D, 0x141D, 0xFFFF }, { + 0x0E29, 0x1D0D, 0xFFFF }, { 0x0810, 0x1021, 0x0939, 0x1A0B, 0x161F, 0xFFFF }, { 0x0918, 0x062C, 0x1113, 0x1217, 0xFFFF + }, { 0x0732, 0x0902, 0x0D35, 0x1405, 0x0F27, 0xFFFF }, { 0x0728, 0x0A1C, 0x1023, 0x073B, 0x0B2F, 0xFFFF }, { 0x0820, + 0x1111, 0x1319, 0x1809, 0xFFFF }, { 0x1303, 0x1215, 0x1607, 0x0E2B, 0x043D, 0xFFFF }, { 0x0916, 0x023C, 0x0B1E, 0x1031, + 0x1201, 0x0F33, 0x0D2D, 0x151D, 0xFFFF }, { 0x0822, 0x0A04, 0x0D0A, 0x1025, 0x0C37, 0x0F29, 0x141B, 0x1E0D, 0xFFFF }, { + 0x1121, 0x0A39, 0x1B0B, 0x171F, 0xFFFF }, { 0x072A, 0x1213, 0x1317, 0xFFFF }, { 0x0830, 0x0914, 0x0636, 0x0C08, 0x0E35, + 0x1505, 0xFFFF }, { 0x0900, 0x0824, 0x0B06, 0x0538, 0x1123, 0x1027, 0xFFFF }, { 0x0A1A, 0x1211, 0x1909, 0x083B, 0x0C2F, + 0xFFFF }, { 0x1315, 0x1707, 0x1419, 0x0F2B, 0x053D, 0xFFFF }, { 0x0912, 0x0734, 0x043A, 0x1131, 0x1301, 0x1403, 0x0E2D, + 0x161D, 0xFFFF }, { 0x0826, 0x0F0C, 0x062E, 0x1033, 0x1125, 0x0D37, 0x151B, 0x1F0D, 0xFFFF }, { 0x1221, 0x0B39, 0x1029, + 0xFFFF }, { 0x0910, 0x1313, 0x1C0B, 0x181F, 0xFFFF }, { 0x0A18, 0x072C, 0x0F35, 0x1605, 0x1417, 0xFFFF }, { 0x0832, + 0x0A02, 0x1223, 0x1127, 0xFFFF }, { 0x0828, 0x0B1C, 0x1311, 0x1A09, 0x093B, 0x0D2F, 0xFFFF }, { 0x0920, 0x1519, 0x063D, + 0xFFFF }, { 0x1231, 0x1503, 0x1415, 0x1807, 0x102B, 0x0F2D, 0x171D, 0xFFFF }, { 0x0A16, 0x033C, 0x0C1E, 0x1401, 0x1133, + 0x1225, 0x0E37, 0x161B, 0xFFFF }, { 0x0922, 0x0B04, 0x0E0A, 0x1321, 0x1129, 0xFFFF }, { 0x0C39, 0x1D0B, 0x191F, 0xFFFF + }, { 0x082A, 0x1413, 0x1705, 0x1517, 0xFFFF }, { 0x0930, 0x0A14, 0x0736, 0x0D08, 0x1323, 0x1035, 0x1227, 0xFFFF }, { + 0x0A00, 0x0924, 0x0C06, 0x0638, 0x1B09, 0x0A3B, 0x0E2F, 0xFFFF }, { 0x0B1A, 0x1411, 0x1619, 0x073D, 0xFFFF }, { 0x1331, + 0x1603, 0x1515, 0x1907, 0x112B, 0xFFFF }, { 0x0A12, 0x0834, 0x053A, 0x1501, 0x1233, 0x1325, 0x0F37, 0x171B, 0x102D, + 0x181D, 0xFFFF }, { 0x0926, 0x072E, 0x1229, 0xFFFF }, { 0x1421, 0x0D39, 0x1E0B, 0x1A1F, 0xFFFF }, { 0x0A10, 0x1513, + 0x1617, 0xFFFF }, { 0x0B18, 0x082C, 0x1135, 0x1805, 0x1327, 0xFFFF }, { 0x0932, 0x0B02, 0x1423, 0x0B3B, 0x0F2F, 0xFFFF + }, { 0x0928, 0x0C1C, 0x1511, 0x1719, 0x1C09, 0xFFFF }, { 0x0A20, 0x1703, 0x1615, 0x1A07, 0x122B, 0x083D, 0xFFFF }, { + 0x1431, 0x1601, 0x1333, 0x112D, 0x191D, 0xFFFF }, { 0x0B16, 0x043C, 0x0D1E, 0x1425, 0x1037, 0x1329, 0x181B, 0xFFFF }, { + 0x0A22, 0x0C04, 0x0F0A, 0x1521, 0x0E39, 0x1F0B, 0x1B1F, 0xFFFF }, { 0x1613, 0x1717, 0xFFFF }, { 0x092A, 0x1235, 0x1905, + 0xFFFF }, { 0x0A30, 0x0B14, 0x0836, 0x0E08, 0x1523, 0x1427, 0xFFFF }, { 0x0B00, 0x0A24, 0x0D06, 0x0738, 0x1611, 0x1D09, + 0x0C3B, 0x102F, 0xFFFF }, { 0x0C1A, 0x1715, 0x1B07, 0x1819, 0x132B, 0x093D, 0xFFFF }, { 0x1531, 0x1701, 0x1803, 0x122D, + 0x1A1D, 0xFFFF }, { 0x0B12, 0x0934, 0x063A, 0x1433, 0x1525, 0x1137, 0x191B, 0xFFFF }, { 0x0A26, 0x003E, 0x082E, 0x1621, + 0x0F39, 0x1429, 0x003F, 0xFFFF }, { 0x1713, 0x1C1F, 0xFFFF }, { 0x0B10, 0x1335, 0x1A05, 0x1817, 0xFFFF }, { 0x0C18, + 0x092C, 0x1623, 0x1527, 0xFFFF }, { 0x0A32, 0x0C02, 0x1711, 0x1E09, 0x0D3B, 0x112F, 0xFFFF }, { 0x0A28, 0x0D1C, 0x1919, + 0x0A3D, 0xFFFF }, { 0x0B20, 0x1631, 0x1903, 0x1815, 0x1C07, 0x142B, 0x132D, 0x1B1D, 0xFFFF }, { 0x1801, 0x1533, 0x1625, + 0x1237, 0x1A1B, 0xFFFF }, { 0x0C16, 0x053C, 0x0E1E, 0x1721, 0x1529, 0x013F, 0xFFFF }, { 0x0B22, 0x0D04, 0x1039, 0x1D1F, + 0xFFFF }, { 0x1813, 0x1B05, 0x1917, 0xFFFF }, { 0x0A2A, 0x1723, 0x1435, 0x1627, 0xFFFF }, { 0x0B30, 0x0C14, 0x0936, + 0x0F08, 0x1F09, 0x0E3B, 0x122F, 0xFFFF }, { 0x0C00, 0x0B24, 0x0E06, 0x0838, 0x1811, 0x1A19, 0x0B3D, 0xFFFF }, { 0x0D1A, + 0x1731, 0x1A03, 0x1915, 0x1D07, 0x152B, 0xFFFF }, { 0x1901, 0x1633, 0x1725, 0x1337, 0x1B1B, 0x142D, 0x1C1D, 0xFFFF }, { + 0x0C12, 0x0A34, 0x073A, 0x1629, 0x023F, 0xFFFF }, { 0x0B26, 0x013E, 0x092E, 0x1821, 0x1139, 0x1E1F, 0xFFFF }, { 0x1913, + 0x1A17, 0xFFFF }, { 0x0C10, 0x1535, 0x1C05, 0x1727, 0xFFFF }, { 0x0D18, 0x0A2C, 0x1823, 0x0F3B, 0x132F, 0xFFFF }, { + 0x0B32, 0x0D02, 0x1911, 0x1B19, 0xFFFF }, { 0x0B28, 0x0E1C, 0x1B03, 0x1A15, 0x1E07, 0x162B, 0x0C3D, 0xFFFF }, { 0x0C20, + 0x1831, 0x1A01, 0x1733, 0x152D, 0x1D1D, 0xFFFF }, { 0x1825, 0x1437, 0x1729, 0x1C1B, 0x033F, 0xFFFF }, { 0x0D16, 0x063C, + 0x0F1E, 0x1921, 0x1239, 0x1F1F, 0xFFFF }, { 0x0C22, 0x0E04, 0x1A13, 0x1B17, 0xFFFF }, { 0x1635, 0x1D05, 0xFFFF }, { + 0x0B2A, 0x1923, 0x1827, 0xFFFF }, { 0x0C30, 0x0D14, 0x0A36, 0x1A11, 0x103B, 0x142F, 0xFFFF }, { 0x0D00, 0x0C24, 0x0F06, + 0x0938, 0x1B15, 0x1F07, 0x1C19, 0x172B, 0x0D3D, 0xFFFF }, { 0x0E1A, 0x1931, 0x1B01, 0x1C03, 0x162D, 0x1E1D, 0xFFFF }, { + 0x1833, 0x1925, 0x1537, 0x1D1B, 0xFFFF }, { 0x0D12, 0x0B34, 0x083A, 0x1A21, 0x1339, 0x1829, 0x043F, 0xFFFF }, { 0x0C26, + 0x023E, 0x0A2E, 0x1B13, 0xFFFF }, { 0x1735, 0x1E05, 0x1C17, 0xFFFF }, { 0x0D10, 0x1A23, 0x1927, 0xFFFF }, { 0x0E18, + 0x0B2C, 0x1B11, 0x113B, 0x152F, 0xFFFF }, { 0x0C32, 0x0E02, 0x1D19, 0x0E3D, 0xFFFF }, { 0x0C28, 0x0F1C, 0x1A31, 0x1D03, + 0x1C15, 0x182B, 0x172D, 0x1F1D, 0xFFFF }, { 0x0D20, 0x1C01, 0x1933, 0x1A25, 0x1637, 0x1E1B, 0xFFFF }, { 0x1B21, 0x1929, + 0x053F, 0xFFFF }, { 0x0E16, 0x073C, 0x1439, 0xFFFF }, { 0x0D22, 0x0F04, 0x1C13, 0x1F05, 0x1D17, 0xFFFF }, { 0x1B23, + 0x1835, 0x1A27, 0xFFFF }, { 0x0C2A, 0x123B, 0x162F, 0xFFFF }, { 0x0D30, 0x0E14, 0x0B36, 0x1C11, 0x1E19, 0x0F3D, 0xFFFF + }, { 0x0E00, 0x0D24, 0x0A38, 0x1B31, 0x1E03, 0x1D15, 0x192B, 0xFFFF }, { 0x0F1A, 0x1D01, 0x1A33, 0x1B25, 0x1737, 0x1F1B, + 0x182D, 0xFFFF }, { 0x1A29, 0x063F, 0xFFFF }, { 0x0E12, 0x0C34, 0x093A, 0x1C21, 0x1539, 0xFFFF }, { 0x0D26, 0x033E, + 0x0B2E, 0x1D13, 0x1E17, 0xFFFF }, { 0x1935, 0x1B27, 0xFFFF }, { 0x0E10, 0x1C23, 0x133B, 0x172F, 0xFFFF }, { 0x0F18, + 0x0C2C, 0x1D11, 0x1F19, 0xFFFF }, { 0x0D32, 0x0F02, 0x1F03, 0x1E15, 0x1A2B, 0x103D, 0xFFFF }, { 0x0D28, 0x1C31, 0x1E01, + 0x1B33, 0x192D, 0xFFFF }, { 0x0E20, 0x1C25, 0x1837, 0x1B29, 0x073F, 0xFFFF }, { 0x1D21, 0x1639, 0xFFFF }, { 0x0F16, + 0x083C, 0x1E13, 0x1F17, 0xFFFF }, { 0x0E22, 0x1A35, 0xFFFF }, { 0x1D23, 0x1C27, 0xFFFF }, { 0x0D2A, 0x1E11, 0x143B, + 0x182F, 0xFFFF }, { 0x0E30, 0x0F14, 0x0C36, 0x1F15, 0x1B2B, 0x113D, 0xFFFF }, { 0x0F00, 0x0E24, 0x0B38, 0x1D31, 0x1F01, + 0x1A2D, 0xFFFF }, { 0x1C33, 0x1D25, 0x1937, 0xFFFF }, { 0x1E21, 0x1739, 0x1C29, 0x083F, 0xFFFF }, { 0x0F12, 0x0D34, + 0x0A3A, 0x1F13, 0xFFFF }, { 0x0E26, 0x043E, 0x0C2E, 0x1B35, 0xFFFF }, { 0x1E23, 0x1D27, 0xFFFF }, { 0x0F10, 0x1F11, + 0x153B, 0x192F, 0xFFFF }, { 0x0D2C, 0x123D, 0xFFFF }, + }; + + struct etc1_block + { + // big endian uint64: + // bit ofs: 56 48 40 32 24 16 8 0 + // byte ofs: b0, b1, b2, b3, b4, b5, b6, b7 + union + { + uint64 m_uint64; + uint8 m_bytes[8]; + }; + + uint8 m_low_color[2]; + uint8 m_high_color[2]; + + enum { cNumSelectorBytes = 4 }; + uint8 m_selectors[cNumSelectorBytes]; + + inline void clear() + { + zero_this(this); + } + + inline uint get_byte_bits(uint ofs, uint num) const + { + RG_ETC1_ASSERT((ofs + num) <= 64U); + RG_ETC1_ASSERT(num && (num <= 8U)); + RG_ETC1_ASSERT((ofs >> 3) == ((ofs + num - 1) >> 3)); + const uint byte_ofs = 7 - (ofs >> 3); + const uint byte_bit_ofs = ofs & 7; + return (m_bytes[byte_ofs] >> byte_bit_ofs) & ((1 << num) - 1); + } + + inline void set_byte_bits(uint ofs, uint num, uint bits) + { + RG_ETC1_ASSERT((ofs + num) <= 64U); + RG_ETC1_ASSERT(num && (num < 32U)); + RG_ETC1_ASSERT((ofs >> 3) == ((ofs + num - 1) >> 3)); + RG_ETC1_ASSERT(bits < (1U << num)); + const uint byte_ofs = 7 - (ofs >> 3); + const uint byte_bit_ofs = ofs & 7; + const uint mask = (1 << num) - 1; + m_bytes[byte_ofs] &= ~(mask << byte_bit_ofs); + m_bytes[byte_ofs] |= (bits << byte_bit_ofs); + } + + // false = left/right subblocks + // true = upper/lower subblocks + inline bool get_flip_bit() const + { + return (m_bytes[3] & 1) != 0; + } + + inline void set_flip_bit(bool flip) + { + m_bytes[3] &= ~1; + m_bytes[3] |= static_cast(flip); + } + + inline bool get_diff_bit() const + { + return (m_bytes[3] & 2) != 0; + } + + inline void set_diff_bit(bool diff) + { + m_bytes[3] &= ~2; + m_bytes[3] |= (static_cast(diff) << 1); + } + + // Returns intensity modifier table (0-7) used by subblock subblock_id. + // subblock_id=0 left/top (CW 1), 1=right/bottom (CW 2) + inline uint get_inten_table(uint subblock_id) const + { + RG_ETC1_ASSERT(subblock_id < 2); + const uint ofs = subblock_id ? 2 : 5; + return (m_bytes[3] >> ofs) & 7; + } + + // Sets intensity modifier table (0-7) used by subblock subblock_id (0 or 1) + inline void set_inten_table(uint subblock_id, uint t) + { + RG_ETC1_ASSERT(subblock_id < 2); + RG_ETC1_ASSERT(t < 8); + const uint ofs = subblock_id ? 2 : 5; + m_bytes[3] &= ~(7 << ofs); + m_bytes[3] |= (t << ofs); + } + + // Returned selector value ranges from 0-3 and is a direct index into g_etc1_inten_tables. + inline uint get_selector(uint x, uint y) const + { + RG_ETC1_ASSERT((x | y) < 4); + + const uint bit_index = x * 4 + y; + const uint byte_bit_ofs = bit_index & 7; + const uint8 *p = &m_bytes[7 - (bit_index >> 3)]; + const uint lsb = (p[0] >> byte_bit_ofs) & 1; + const uint msb = (p[-2] >> byte_bit_ofs) & 1; + const uint val = lsb | (msb << 1); + + return g_etc1_to_selector_index[val]; + } + + // Selector "val" ranges from 0-3 and is a direct index into g_etc1_inten_tables. + inline void set_selector(uint x, uint y, uint val) + { + RG_ETC1_ASSERT((x | y | val) < 4); + const uint bit_index = x * 4 + y; + + uint8 *p = &m_bytes[7 - (bit_index >> 3)]; + + const uint byte_bit_ofs = bit_index & 7; + const uint mask = 1 << byte_bit_ofs; + + const uint etc1_val = g_selector_index_to_etc1[val]; + + const uint lsb = etc1_val & 1; + const uint msb = etc1_val >> 1; + + p[0] &= ~mask; + p[0] |= (lsb << byte_bit_ofs); + + p[-2] &= ~mask; + p[-2] |= (msb << byte_bit_ofs); + } + + inline void set_base4_color(uint idx, uint16 c) + { + if (idx) + { + set_byte_bits(cETC1AbsColor4R2BitOffset, 4, (c >> 8) & 15); + set_byte_bits(cETC1AbsColor4G2BitOffset, 4, (c >> 4) & 15); + set_byte_bits(cETC1AbsColor4B2BitOffset, 4, c & 15); + } + else + { + set_byte_bits(cETC1AbsColor4R1BitOffset, 4, (c >> 8) & 15); + set_byte_bits(cETC1AbsColor4G1BitOffset, 4, (c >> 4) & 15); + set_byte_bits(cETC1AbsColor4B1BitOffset, 4, c & 15); + } + } + + inline uint16 get_base4_color(uint idx) const + { + uint r, g, b; + if (idx) + { + r = get_byte_bits(cETC1AbsColor4R2BitOffset, 4); + g = get_byte_bits(cETC1AbsColor4G2BitOffset, 4); + b = get_byte_bits(cETC1AbsColor4B2BitOffset, 4); + } + else + { + r = get_byte_bits(cETC1AbsColor4R1BitOffset, 4); + g = get_byte_bits(cETC1AbsColor4G1BitOffset, 4); + b = get_byte_bits(cETC1AbsColor4B1BitOffset, 4); + } + return static_cast(b | (g << 4U) | (r << 8U)); + } + + inline void set_base5_color(uint16 c) + { + set_byte_bits(cETC1BaseColor5RBitOffset, 5, (c >> 10) & 31); + set_byte_bits(cETC1BaseColor5GBitOffset, 5, (c >> 5) & 31); + set_byte_bits(cETC1BaseColor5BBitOffset, 5, c & 31); + } + + inline uint16 get_base5_color() const + { + const uint r = get_byte_bits(cETC1BaseColor5RBitOffset, 5); + const uint g = get_byte_bits(cETC1BaseColor5GBitOffset, 5); + const uint b = get_byte_bits(cETC1BaseColor5BBitOffset, 5); + return static_cast(b | (g << 5U) | (r << 10U)); + } + + void set_delta3_color(uint16 c) + { + set_byte_bits(cETC1DeltaColor3RBitOffset, 3, (c >> 6) & 7); + set_byte_bits(cETC1DeltaColor3GBitOffset, 3, (c >> 3) & 7); + set_byte_bits(cETC1DeltaColor3BBitOffset, 3, c & 7); + } + + inline uint16 get_delta3_color() const + { + const uint r = get_byte_bits(cETC1DeltaColor3RBitOffset, 3); + const uint g = get_byte_bits(cETC1DeltaColor3GBitOffset, 3); + const uint b = get_byte_bits(cETC1DeltaColor3BBitOffset, 3); + return static_cast(b | (g << 3U) | (r << 6U)); + } + + // Base color 5 + static uint16 pack_color5(const color_quad_u8& color, bool scaled, uint bias = 127U); + static uint16 pack_color5(uint r, uint g, uint b, bool scaled, uint bias = 127U); + + static color_quad_u8 unpack_color5(uint16 packed_color5, bool scaled, uint alpha = 255U); + static void unpack_color5(uint& r, uint& g, uint& b, uint16 packed_color, bool scaled); + + static bool unpack_color5(color_quad_u8& result, uint16 packed_color5, uint16 packed_delta3, bool scaled, uint alpha = 255U); + static bool unpack_color5(uint& r, uint& g, uint& b, uint16 packed_color5, uint16 packed_delta3, bool scaled, uint alpha = 255U); + + // Delta color 3 + // Inputs range from -4 to 3 (cETC1ColorDeltaMin to cETC1ColorDeltaMax) + static uint16 pack_delta3(int r, int g, int b); + + // Results range from -4 to 3 (cETC1ColorDeltaMin to cETC1ColorDeltaMax) + static void unpack_delta3(int& r, int& g, int& b, uint16 packed_delta3); + + // Abs color 4 + static uint16 pack_color4(const color_quad_u8& color, bool scaled, uint bias = 127U); + static uint16 pack_color4(uint r, uint g, uint b, bool scaled, uint bias = 127U); + + static color_quad_u8 unpack_color4(uint16 packed_color4, bool scaled, uint alpha = 255U); + static void unpack_color4(uint& r, uint& g, uint& b, uint16 packed_color4, bool scaled); + + // subblock colors + static void get_diff_subblock_colors(color_quad_u8* pDst, uint16 packed_color5, uint table_idx); + static bool get_diff_subblock_colors(color_quad_u8* pDst, uint16 packed_color5, uint16 packed_delta3, uint table_idx); + static void get_abs_subblock_colors(color_quad_u8* pDst, uint16 packed_color4, uint table_idx); + + static inline void unscaled_to_scaled_color(color_quad_u8& dst, const color_quad_u8& src, bool color4) + { + if (color4) + { + dst.r = src.r | (src.r << 4); + dst.g = src.g | (src.g << 4); + dst.b = src.b | (src.b << 4); + } + else + { + dst.r = (src.r >> 2) | (src.r << 3); + dst.g = (src.g >> 2) | (src.g << 3); + dst.b = (src.b >> 2) | (src.b << 3); + } + dst.a = src.a; + } + }; + + // Returns pointer to sorted array. + template + T* indirect_radix_sort(uint num_indices, T* pIndices0, T* pIndices1, const Q* pKeys, uint key_ofs, uint key_size, bool init_indices) + { + RG_ETC1_ASSERT((key_ofs >= 0) && (key_ofs < sizeof(T))); + RG_ETC1_ASSERT((key_size >= 1) && (key_size <= 4)); + + if (init_indices) + { + T* p = pIndices0; + T* q = pIndices0 + (num_indices >> 1) * 2; + uint i; + for (i = 0; p != q; p += 2, i += 2) + { + p[0] = static_cast(i); + p[1] = static_cast(i + 1); + } + + if (num_indices & 1) + *p = static_cast(i); + } + + uint hist[256 * 4]; + + memset(hist, 0, sizeof(hist[0]) * 256 * key_size); + +#define RG_ETC1_GET_KEY(p) (*(const uint*)((const uint8*)(pKeys + *(p)) + key_ofs)) +#define RG_ETC1_GET_KEY_FROM_INDEX(i) (*(const uint*)((const uint8*)(pKeys + (i)) + key_ofs)) + + if (key_size == 4) + { + T* p = pIndices0; + T* q = pIndices0 + num_indices; + for ( ; p != q; p++) + { + const uint key = RG_ETC1_GET_KEY(p); + + hist[ key & 0xFF]++; + hist[256 + ((key >> 8) & 0xFF)]++; + hist[512 + ((key >> 16) & 0xFF)]++; + hist[768 + ((key >> 24) & 0xFF)]++; + } + } + else if (key_size == 3) + { + T* p = pIndices0; + T* q = pIndices0 + num_indices; + for ( ; p != q; p++) + { + const uint key = RG_ETC1_GET_KEY(p); + + hist[ key & 0xFF]++; + hist[256 + ((key >> 8) & 0xFF)]++; + hist[512 + ((key >> 16) & 0xFF)]++; + } + } + else if (key_size == 2) + { + T* p = pIndices0; + T* q = pIndices0 + (num_indices >> 1) * 2; + + for ( ; p != q; p += 2) + { + const uint key0 = RG_ETC1_GET_KEY(p); + const uint key1 = RG_ETC1_GET_KEY(p+1); + + hist[ key0 & 0xFF]++; + hist[256 + ((key0 >> 8) & 0xFF)]++; + + hist[ key1 & 0xFF]++; + hist[256 + ((key1 >> 8) & 0xFF)]++; + } + + if (num_indices & 1) + { + const uint key = RG_ETC1_GET_KEY(p); + + hist[ key & 0xFF]++; + hist[256 + ((key >> 8) & 0xFF)]++; + } + } + else + { + RG_ETC1_ASSERT(key_size == 1); + if (key_size != 1) + return NULL; + + T* p = pIndices0; + T* q = pIndices0 + (num_indices >> 1) * 2; + + for ( ; p != q; p += 2) + { + const uint key0 = RG_ETC1_GET_KEY(p); + const uint key1 = RG_ETC1_GET_KEY(p+1); + + hist[key0 & 0xFF]++; + hist[key1 & 0xFF]++; + } + + if (num_indices & 1) + { + const uint key = RG_ETC1_GET_KEY(p); + + hist[key & 0xFF]++; + } + } + + T* pCur = pIndices0; + T* pNew = pIndices1; + + for (uint pass = 0; pass < key_size; pass++) + { + const uint* pHist = &hist[pass << 8]; + + uint offsets[256]; + + uint cur_ofs = 0; + for (uint i = 0; i < 256; i += 2) + { + offsets[i] = cur_ofs; + cur_ofs += pHist[i]; + + offsets[i+1] = cur_ofs; + cur_ofs += pHist[i+1]; + } + + const uint pass_shift = pass << 3; + + T* p = pCur; + T* q = pCur + (num_indices >> 1) * 2; + + for ( ; p != q; p += 2) + { + uint index0 = p[0]; + uint index1 = p[1]; + + uint c0 = (RG_ETC1_GET_KEY_FROM_INDEX(index0) >> pass_shift) & 0xFF; + uint c1 = (RG_ETC1_GET_KEY_FROM_INDEX(index1) >> pass_shift) & 0xFF; + + if (c0 == c1) + { + uint dst_offset0 = offsets[c0]; + + offsets[c0] = dst_offset0 + 2; + + pNew[dst_offset0] = static_cast(index0); + pNew[dst_offset0 + 1] = static_cast(index1); + } + else + { + uint dst_offset0 = offsets[c0]++; + uint dst_offset1 = offsets[c1]++; + + pNew[dst_offset0] = static_cast(index0); + pNew[dst_offset1] = static_cast(index1); + } + } + + if (num_indices & 1) + { + uint index = *p; + uint c = (RG_ETC1_GET_KEY_FROM_INDEX(index) >> pass_shift) & 0xFF; + + uint dst_offset = offsets[c]; + offsets[c] = dst_offset + 1; + + pNew[dst_offset] = static_cast(index); + } + + T* t = pCur; + pCur = pNew; + pNew = t; + } + + return pCur; + } + +#undef RG_ETC1_GET_KEY +#undef RG_ETC1_GET_KEY_FROM_INDEX + + uint16 etc1_block::pack_color5(const color_quad_u8& color, bool scaled, uint bias) + { + return pack_color5(color.r, color.g, color.b, scaled, bias); + } + + uint16 etc1_block::pack_color5(uint r, uint g, uint b, bool scaled, uint bias) + { + if (scaled) + { + r = (r * 31U + bias) / 255U; + g = (g * 31U + bias) / 255U; + b = (b * 31U + bias) / 255U; + } + + r = rg_etc1::minimum(r, 31U); + g = rg_etc1::minimum(g, 31U); + b = rg_etc1::minimum(b, 31U); + + return static_cast(b | (g << 5U) | (r << 10U)); + } + + color_quad_u8 etc1_block::unpack_color5(uint16 packed_color5, bool scaled, uint alpha) + { + uint b = packed_color5 & 31U; + uint g = (packed_color5 >> 5U) & 31U; + uint r = (packed_color5 >> 10U) & 31U; + + if (scaled) + { + b = (b << 3U) | (b >> 2U); + g = (g << 3U) | (g >> 2U); + r = (r << 3U) | (r >> 2U); + } + + return color_quad_u8(cNoClamp, r, g, b, rg_etc1::minimum(alpha, 255U)); + } + + void etc1_block::unpack_color5(uint& r, uint& g, uint& b, uint16 packed_color5, bool scaled) + { + color_quad_u8 c(unpack_color5(packed_color5, scaled, 0)); + r = c.r; + g = c.g; + b = c.b; + } + + bool etc1_block::unpack_color5(color_quad_u8& result, uint16 packed_color5, uint16 packed_delta3, bool scaled, uint alpha) + { + int dc_r, dc_g, dc_b; + unpack_delta3(dc_r, dc_g, dc_b, packed_delta3); + + int b = (packed_color5 & 31U) + dc_b; + int g = ((packed_color5 >> 5U) & 31U) + dc_g; + int r = ((packed_color5 >> 10U) & 31U) + dc_r; + + bool success = true; + if (static_cast(r | g | b) > 31U) + { + success = false; + r = rg_etc1::clamp(r, 0, 31); + g = rg_etc1::clamp(g, 0, 31); + b = rg_etc1::clamp(b, 0, 31); + } + + if (scaled) + { + b = (b << 3U) | (b >> 2U); + g = (g << 3U) | (g >> 2U); + r = (r << 3U) | (r >> 2U); + } + + result.set_noclamp_rgba(r, g, b, rg_etc1::minimum(alpha, 255U)); + return success; + } + + bool etc1_block::unpack_color5(uint& r, uint& g, uint& b, uint16 packed_color5, uint16 packed_delta3, bool scaled, uint alpha) + { + color_quad_u8 result; + const bool success = unpack_color5(result, packed_color5, packed_delta3, scaled, alpha); + r = result.r; + g = result.g; + b = result.b; + return success; + } + + uint16 etc1_block::pack_delta3(int r, int g, int b) + { + RG_ETC1_ASSERT((r >= cETC1ColorDeltaMin) && (r <= cETC1ColorDeltaMax)); + RG_ETC1_ASSERT((g >= cETC1ColorDeltaMin) && (g <= cETC1ColorDeltaMax)); + RG_ETC1_ASSERT((b >= cETC1ColorDeltaMin) && (b <= cETC1ColorDeltaMax)); + if (r < 0) r += 8; + if (g < 0) g += 8; + if (b < 0) b += 8; + return static_cast(b | (g << 3) | (r << 6)); + } + + void etc1_block::unpack_delta3(int& r, int& g, int& b, uint16 packed_delta3) + { + r = (packed_delta3 >> 6) & 7; + g = (packed_delta3 >> 3) & 7; + b = packed_delta3 & 7; + if (r >= 4) r -= 8; + if (g >= 4) g -= 8; + if (b >= 4) b -= 8; + } + + uint16 etc1_block::pack_color4(const color_quad_u8& color, bool scaled, uint bias) + { + return pack_color4(color.r, color.g, color.b, scaled, bias); + } + + uint16 etc1_block::pack_color4(uint r, uint g, uint b, bool scaled, uint bias) + { + if (scaled) + { + r = (r * 15U + bias) / 255U; + g = (g * 15U + bias) / 255U; + b = (b * 15U + bias) / 255U; + } + + r = rg_etc1::minimum(r, 15U); + g = rg_etc1::minimum(g, 15U); + b = rg_etc1::minimum(b, 15U); + + return static_cast(b | (g << 4U) | (r << 8U)); + } + + color_quad_u8 etc1_block::unpack_color4(uint16 packed_color4, bool scaled, uint alpha) + { + uint b = packed_color4 & 15U; + uint g = (packed_color4 >> 4U) & 15U; + uint r = (packed_color4 >> 8U) & 15U; + + if (scaled) + { + b = (b << 4U) | b; + g = (g << 4U) | g; + r = (r << 4U) | r; + } + + return color_quad_u8(cNoClamp, r, g, b, rg_etc1::minimum(alpha, 255U)); + } + + void etc1_block::unpack_color4(uint& r, uint& g, uint& b, uint16 packed_color4, bool scaled) + { + color_quad_u8 c(unpack_color4(packed_color4, scaled, 0)); + r = c.r; + g = c.g; + b = c.b; + } + + void etc1_block::get_diff_subblock_colors(color_quad_u8* pDst, uint16 packed_color5, uint table_idx) + { + RG_ETC1_ASSERT(table_idx < cETC1IntenModifierValues); + const int *pInten_modifer_table = &g_etc1_inten_tables[table_idx][0]; + + uint r, g, b; + unpack_color5(r, g, b, packed_color5, true); + + const int ir = static_cast(r), ig = static_cast(g), ib = static_cast(b); + + const int y0 = pInten_modifer_table[0]; + pDst[0].set(ir + y0, ig + y0, ib + y0); + + const int y1 = pInten_modifer_table[1]; + pDst[1].set(ir + y1, ig + y1, ib + y1); + + const int y2 = pInten_modifer_table[2]; + pDst[2].set(ir + y2, ig + y2, ib + y2); + + const int y3 = pInten_modifer_table[3]; + pDst[3].set(ir + y3, ig + y3, ib + y3); + } + + bool etc1_block::get_diff_subblock_colors(color_quad_u8* pDst, uint16 packed_color5, uint16 packed_delta3, uint table_idx) + { + RG_ETC1_ASSERT(table_idx < cETC1IntenModifierValues); + const int *pInten_modifer_table = &g_etc1_inten_tables[table_idx][0]; + + uint r, g, b; + bool success = unpack_color5(r, g, b, packed_color5, packed_delta3, true); + + const int ir = static_cast(r), ig = static_cast(g), ib = static_cast(b); + + const int y0 = pInten_modifer_table[0]; + pDst[0].set(ir + y0, ig + y0, ib + y0); + + const int y1 = pInten_modifer_table[1]; + pDst[1].set(ir + y1, ig + y1, ib + y1); + + const int y2 = pInten_modifer_table[2]; + pDst[2].set(ir + y2, ig + y2, ib + y2); + + const int y3 = pInten_modifer_table[3]; + pDst[3].set(ir + y3, ig + y3, ib + y3); + + return success; + } + + void etc1_block::get_abs_subblock_colors(color_quad_u8* pDst, uint16 packed_color4, uint table_idx) + { + RG_ETC1_ASSERT(table_idx < cETC1IntenModifierValues); + const int *pInten_modifer_table = &g_etc1_inten_tables[table_idx][0]; + + uint r, g, b; + unpack_color4(r, g, b, packed_color4, true); + + const int ir = static_cast(r), ig = static_cast(g), ib = static_cast(b); + + const int y0 = pInten_modifer_table[0]; + pDst[0].set(ir + y0, ig + y0, ib + y0); + + const int y1 = pInten_modifer_table[1]; + pDst[1].set(ir + y1, ig + y1, ib + y1); + + const int y2 = pInten_modifer_table[2]; + pDst[2].set(ir + y2, ig + y2, ib + y2); + + const int y3 = pInten_modifer_table[3]; + pDst[3].set(ir + y3, ig + y3, ib + y3); + } + + bool unpack_etc1_block(const void* pETC1_block, unsigned int* pDst_pixels_rgba, int stride, bool preserve_alpha) + { + color_quad_u8* pDst = reinterpret_cast(pDst_pixels_rgba); + const etc1_block& block = *static_cast(pETC1_block); + + const bool diff_flag = block.get_diff_bit(); + const bool flip_flag = block.get_flip_bit(); + const uint table_index0 = block.get_inten_table(0); + const uint table_index1 = block.get_inten_table(1); + + color_quad_u8 subblock_colors0[4]; + color_quad_u8 subblock_colors1[4]; + bool success = true; + + if (diff_flag) + { + const uint16 base_color5 = block.get_base5_color(); + const uint16 delta_color3 = block.get_delta3_color(); + etc1_block::get_diff_subblock_colors(subblock_colors0, base_color5, table_index0); + + if (!etc1_block::get_diff_subblock_colors(subblock_colors1, base_color5, delta_color3, table_index1)) + success = false; + } + else + { + const uint16 base_color4_0 = block.get_base4_color(0); + etc1_block::get_abs_subblock_colors(subblock_colors0, base_color4_0, table_index0); + + const uint16 base_color4_1 = block.get_base4_color(1); + etc1_block::get_abs_subblock_colors(subblock_colors1, base_color4_1, table_index1); + } + + if (preserve_alpha) + { + if (flip_flag) + { + for (uint y = 0; y < 2; y++) + { + pDst[0].set_rgb(subblock_colors0[block.get_selector(0, y)]); + pDst[1].set_rgb(subblock_colors0[block.get_selector(1, y)]); + pDst[2].set_rgb(subblock_colors0[block.get_selector(2, y)]); + pDst[3].set_rgb(subblock_colors0[block.get_selector(3, y)]); + pDst += stride; + } + + for (uint y = 2; y < 4; y++) + { + pDst[0].set_rgb(subblock_colors1[block.get_selector(0, y)]); + pDst[1].set_rgb(subblock_colors1[block.get_selector(1, y)]); + pDst[2].set_rgb(subblock_colors1[block.get_selector(2, y)]); + pDst[3].set_rgb(subblock_colors1[block.get_selector(3, y)]); + pDst += stride; + } + } + else + { + for (uint y = 0; y < 4; y++) + { + pDst[0].set_rgb(subblock_colors0[block.get_selector(0, y)]); + pDst[1].set_rgb(subblock_colors0[block.get_selector(1, y)]); + pDst[2].set_rgb(subblock_colors1[block.get_selector(2, y)]); + pDst[3].set_rgb(subblock_colors1[block.get_selector(3, y)]); + pDst += stride; + } + } + } + else + { + if (flip_flag) + { + // 0000 + // 0000 + // 1111 + // 1111 + for (uint y = 0; y < 2; y++) + { + pDst[0] = subblock_colors0[block.get_selector(0, y)]; + pDst[1] = subblock_colors0[block.get_selector(1, y)]; + pDst[2] = subblock_colors0[block.get_selector(2, y)]; + pDst[3] = subblock_colors0[block.get_selector(3, y)]; + pDst += stride; + } + + for (uint y = 2; y < 4; y++) + { + pDst[0] = subblock_colors1[block.get_selector(0, y)]; + pDst[1] = subblock_colors1[block.get_selector(1, y)]; + pDst[2] = subblock_colors1[block.get_selector(2, y)]; + pDst[3] = subblock_colors1[block.get_selector(3, y)]; + pDst += stride; + } + } + else + { + // 0011 + // 0011 + // 0011 + // 0011 + for (uint y = 0; y < 4; y++) + { + pDst[0] = subblock_colors0[block.get_selector(0, y)]; + pDst[1] = subblock_colors0[block.get_selector(1, y)]; + pDst[2] = subblock_colors1[block.get_selector(2, y)]; + pDst[3] = subblock_colors1[block.get_selector(3, y)]; + pDst += stride; + } + } + } + + return success; + } + + struct etc1_solution_coordinates + { + inline etc1_solution_coordinates() : + m_unscaled_color(0, 0, 0, 0), + m_inten_table(0), + m_color4(false) + { + } + + inline etc1_solution_coordinates(uint r, uint g, uint b, uint inten_table, bool color4) : + m_unscaled_color(r, g, b, 255), + m_inten_table(inten_table), + m_color4(color4) + { + } + + inline etc1_solution_coordinates(const color_quad_u8& c, uint inten_table, bool color4) : + m_unscaled_color(c), + m_inten_table(inten_table), + m_color4(color4) + { + } + + inline etc1_solution_coordinates(const etc1_solution_coordinates& other) + { + *this = other; + } + + inline etc1_solution_coordinates& operator= (const etc1_solution_coordinates& rhs) + { + m_unscaled_color = rhs.m_unscaled_color; + m_inten_table = rhs.m_inten_table; + m_color4 = rhs.m_color4; + return *this; + } + + inline void clear() + { + m_unscaled_color.clear(); + m_inten_table = 0; + m_color4 = false; + } + + inline color_quad_u8 get_scaled_color() const + { + int br, bg, bb; + if (m_color4) + { + br = m_unscaled_color.r | (m_unscaled_color.r << 4); + bg = m_unscaled_color.g | (m_unscaled_color.g << 4); + bb = m_unscaled_color.b | (m_unscaled_color.b << 4); + } + else + { + br = (m_unscaled_color.r >> 2) | (m_unscaled_color.r << 3); + bg = (m_unscaled_color.g >> 2) | (m_unscaled_color.g << 3); + bb = (m_unscaled_color.b >> 2) | (m_unscaled_color.b << 3); + } + return color_quad_u8(br, bg, bb); + } + + inline void get_block_colors(color_quad_u8* pBlock_colors) + { + int br, bg, bb; + if (m_color4) + { + br = m_unscaled_color.r | (m_unscaled_color.r << 4); + bg = m_unscaled_color.g | (m_unscaled_color.g << 4); + bb = m_unscaled_color.b | (m_unscaled_color.b << 4); + } + else + { + br = (m_unscaled_color.r >> 2) | (m_unscaled_color.r << 3); + bg = (m_unscaled_color.g >> 2) | (m_unscaled_color.g << 3); + bb = (m_unscaled_color.b >> 2) | (m_unscaled_color.b << 3); + } + const int* pInten_table = g_etc1_inten_tables[m_inten_table]; + pBlock_colors[0].set(br + pInten_table[0], bg + pInten_table[0], bb + pInten_table[0]); + pBlock_colors[1].set(br + pInten_table[1], bg + pInten_table[1], bb + pInten_table[1]); + pBlock_colors[2].set(br + pInten_table[2], bg + pInten_table[2], bb + pInten_table[2]); + pBlock_colors[3].set(br + pInten_table[3], bg + pInten_table[3], bb + pInten_table[3]); + } + + color_quad_u8 m_unscaled_color; + uint m_inten_table; + bool m_color4; + }; + + class etc1_optimizer + { + etc1_optimizer(const etc1_optimizer&); + etc1_optimizer& operator= (const etc1_optimizer&); + + public: + etc1_optimizer() + { + clear(); + } + + void clear() + { + m_pParams = NULL; + m_pResult = NULL; + m_pSorted_luma = NULL; + m_pSorted_luma_indices = NULL; + } + + struct params : etc1_pack_params + { + params() + { + clear(); + } + + params(const etc1_pack_params& base_params) : + etc1_pack_params(base_params) + { + clear_optimizer_params(); + } + + void clear() + { + etc1_pack_params::clear(); + clear_optimizer_params(); + } + + void clear_optimizer_params() + { + m_num_src_pixels = 0; + m_pSrc_pixels = 0; + + m_use_color4 = false; + static const int s_default_scan_delta[] = { 0 }; + m_pScan_deltas = s_default_scan_delta; + m_scan_delta_size = 1; + + m_base_color5.clear(); + m_constrain_against_base_color5 = false; + } + + uint m_num_src_pixels; + const color_quad_u8* m_pSrc_pixels; + + bool m_use_color4; + const int* m_pScan_deltas; + uint m_scan_delta_size; + + color_quad_u8 m_base_color5; + bool m_constrain_against_base_color5; + }; + + struct results + { + uint64 m_error; + color_quad_u8 m_block_color_unscaled; + uint m_block_inten_table; + uint m_n; + uint8* m_pSelectors; + bool m_block_color4; + + inline results& operator= (const results& rhs) + { + m_block_color_unscaled = rhs.m_block_color_unscaled; + m_block_color4 = rhs.m_block_color4; + m_block_inten_table = rhs.m_block_inten_table; + m_error = rhs.m_error; + RG_ETC1_ASSERT(m_n == rhs.m_n); + memcpy(m_pSelectors, rhs.m_pSelectors, rhs.m_n); + return *this; + } + }; + + void init(const params& params, results& result); + bool compute(); + + private: + struct potential_solution + { + potential_solution() : m_coords(), m_error(cUINT64_MAX), m_valid(false) + { + } + + etc1_solution_coordinates m_coords; + uint8 m_selectors[8]; + uint64 m_error; + bool m_valid; + + void clear() + { + m_coords.clear(); + m_error = cUINT64_MAX; + m_valid = false; + } + }; + + const params* m_pParams; + results* m_pResult; + + int m_limit; + + vec3F m_avg_color; + int m_br, m_bg, m_bb; + uint16 m_luma[8]; + uint32 m_sorted_luma[2][8]; + const uint32* m_pSorted_luma_indices; + uint32* m_pSorted_luma; + + uint8 m_selectors[8]; + uint8 m_best_selectors[8]; + + potential_solution m_best_solution; + potential_solution m_trial_solution; + uint8 m_temp_selectors[8]; + + bool evaluate_solution(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution); + bool evaluate_solution_fast(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution); + }; + + bool etc1_optimizer::compute() + { + const uint n = m_pParams->m_num_src_pixels; + const int scan_delta_size = m_pParams->m_scan_delta_size; + + // Scan through a subset of the 3D lattice centered around the avg block color trying each 3D (555 or 444) lattice point as a potential block color. + // Each time a better solution is found try to refine the current solution's block color based of the current selectors and intensity table index. + for (int zdi = 0; zdi < scan_delta_size; zdi++) + { + const int zd = m_pParams->m_pScan_deltas[zdi]; + const int mbb = m_bb + zd; + if (mbb < 0) continue; else if (mbb > m_limit) break; + + for (int ydi = 0; ydi < scan_delta_size; ydi++) + { + const int yd = m_pParams->m_pScan_deltas[ydi]; + const int mbg = m_bg + yd; + if (mbg < 0) continue; else if (mbg > m_limit) break; + + for (int xdi = 0; xdi < scan_delta_size; xdi++) + { + const int xd = m_pParams->m_pScan_deltas[xdi]; + const int mbr = m_br + xd; + if (mbr < 0) continue; else if (mbr > m_limit) break; + + etc1_solution_coordinates coords(mbr, mbg, mbb, 0, m_pParams->m_use_color4); + if (m_pParams->m_quality == cHighQuality) + { + if (!evaluate_solution(coords, m_trial_solution, &m_best_solution)) + continue; + } + else + { + if (!evaluate_solution_fast(coords, m_trial_solution, &m_best_solution)) + continue; + } + + // Now we have the input block, the avg. color of the input pixels, a set of trial selector indices, and the block color+intensity index. + // Now, for each component, attempt to refine the current solution by solving a simple linear equation. For example, for 4 colors: + // The goal is: + // pixel0 - (block_color+inten_table[selector0]) + pixel1 - (block_color+inten_table[selector1]) + pixel2 - (block_color+inten_table[selector2]) + pixel3 - (block_color+inten_table[selector3]) = 0 + // Rearranging this: + // (pixel0 + pixel1 + pixel2 + pixel3) - (block_color+inten_table[selector0]) - (block_color+inten_table[selector1]) - (block_color+inten_table[selector2]) - (block_color+inten_table[selector3]) = 0 + // (pixel0 + pixel1 + pixel2 + pixel3) - block_color - inten_table[selector0] - block_color-inten_table[selector1] - block_color-inten_table[selector2] - block_color-inten_table[selector3] = 0 + // (pixel0 + pixel1 + pixel2 + pixel3) - 4*block_color - inten_table[selector0] - inten_table[selector1] - inten_table[selector2] - inten_table[selector3] = 0 + // (pixel0 + pixel1 + pixel2 + pixel3) - 4*block_color - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3]) = 0 + // (pixel0 + pixel1 + pixel2 + pixel3)/4 - block_color - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3])/4 = 0 + // block_color = (pixel0 + pixel1 + pixel2 + pixel3)/4 - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3])/4 + // So what this means: + // optimal_block_color = avg_input - avg_inten_delta + // So the optimal block color can be computed by taking the average block color and subtracting the current average of the intensity delta. + // Unfortunately, optimal_block_color must then be quantized to 555 or 444 so it's not always possible to improve matters using this formula. + // Also, the above formula is for unclamped intensity deltas. The actual implementation takes into account clamping. + + const uint max_refinement_trials = (m_pParams->m_quality == cLowQuality) ? 2 : (((xd | yd | zd) == 0) ? 4 : 2); + for (uint refinement_trial = 0; refinement_trial < max_refinement_trials; refinement_trial++) + { + const uint8* pSelectors = m_best_solution.m_selectors; + const int* pInten_table = g_etc1_inten_tables[m_best_solution.m_coords.m_inten_table]; + + int delta_sum_r = 0, delta_sum_g = 0, delta_sum_b = 0; + const color_quad_u8 base_color(m_best_solution.m_coords.get_scaled_color()); + for (uint r = 0; r < n; r++) + { + const uint s = *pSelectors++; + const int yd = pInten_table[s]; + // Compute actual delta being applied to each pixel, taking into account clamping. + delta_sum_r += rg_etc1::clamp(base_color.r + yd, 0, 255) - base_color.r; + delta_sum_g += rg_etc1::clamp(base_color.g + yd, 0, 255) - base_color.g; + delta_sum_b += rg_etc1::clamp(base_color.b + yd, 0, 255) - base_color.b; + } + if ((!delta_sum_r) && (!delta_sum_g) && (!delta_sum_b)) + break; + const float avg_delta_r_f = static_cast(delta_sum_r) / n; + const float avg_delta_g_f = static_cast(delta_sum_g) / n; + const float avg_delta_b_f = static_cast(delta_sum_b) / n; + const int br1 = rg_etc1::clamp(static_cast((m_avg_color[0] - avg_delta_r_f) * m_limit / 255.0f + .5f), 0, m_limit); + const int bg1 = rg_etc1::clamp(static_cast((m_avg_color[1] - avg_delta_g_f) * m_limit / 255.0f + .5f), 0, m_limit); + const int bb1 = rg_etc1::clamp(static_cast((m_avg_color[2] - avg_delta_b_f) * m_limit / 255.0f + .5f), 0, m_limit); + + bool skip = false; + + if ((mbr == br1) && (mbg == bg1) && (mbb == bb1)) + skip = true; + else if ((br1 == m_best_solution.m_coords.m_unscaled_color.r) && (bg1 == m_best_solution.m_coords.m_unscaled_color.g) && (bb1 == m_best_solution.m_coords.m_unscaled_color.b)) + skip = true; + else if ((m_br == br1) && (m_bg == bg1) && (m_bb == bb1)) + skip = true; + + if (skip) + break; + + etc1_solution_coordinates coords1(br1, bg1, bb1, 0, m_pParams->m_use_color4); + if (m_pParams->m_quality == cHighQuality) + { + if (!evaluate_solution(coords1, m_trial_solution, &m_best_solution)) + break; + } + else + { + if (!evaluate_solution_fast(coords1, m_trial_solution, &m_best_solution)) + break; + } + + } // refinement_trial + + } // xdi + } // ydi + } // zdi + + if (!m_best_solution.m_valid) + { + m_pResult->m_error = cUINT32_MAX; + return false; + } + + const uint8* pSelectors = m_best_solution.m_selectors; + +#ifdef RG_ETC1_BUILD_DEBUG + { + color_quad_u8 block_colors[4]; + m_best_solution.m_coords.get_block_colors(block_colors); + + const color_quad_u8* pSrc_pixels = m_pParams->m_pSrc_pixels; + uint64 actual_error = 0; + for (uint i = 0; i < n; i++) + actual_error += pSrc_pixels[i].squared_distance_rgb(block_colors[pSelectors[i]]); + + RG_ETC1_ASSERT(actual_error == m_best_solution.m_error); + } +#endif + + m_pResult->m_error = m_best_solution.m_error; + + m_pResult->m_block_color_unscaled = m_best_solution.m_coords.m_unscaled_color; + m_pResult->m_block_color4 = m_best_solution.m_coords.m_color4; + + m_pResult->m_block_inten_table = m_best_solution.m_coords.m_inten_table; + memcpy(m_pResult->m_pSelectors, pSelectors, n); + m_pResult->m_n = n; + + return true; + } + + void etc1_optimizer::init(const params& p, results& r) + { + // This version is hardcoded for 8 pixel subblocks. + RG_ETC1_ASSERT(p.m_num_src_pixels == 8); + + m_pParams = &p; + m_pResult = &r; + + const uint n = 8; + + m_limit = m_pParams->m_use_color4 ? 15 : 31; + + vec3F avg_color(0.0f); + + for (uint i = 0; i < n; i++) + { + const color_quad_u8& c = m_pParams->m_pSrc_pixels[i]; + const vec3F fc(c.r, c.g, c.b); + + avg_color += fc; + + m_luma[i] = static_cast(c.r + c.g + c.b); + m_sorted_luma[0][i] = i; + } + avg_color *= (1.0f / static_cast(n)); + m_avg_color = avg_color; + + m_br = rg_etc1::clamp(static_cast(m_avg_color[0] * m_limit / 255.0f + .5f), 0, m_limit); + m_bg = rg_etc1::clamp(static_cast(m_avg_color[1] * m_limit / 255.0f + .5f), 0, m_limit); + m_bb = rg_etc1::clamp(static_cast(m_avg_color[2] * m_limit / 255.0f + .5f), 0, m_limit); + + if (m_pParams->m_quality <= cMediumQuality) + { + m_pSorted_luma_indices = indirect_radix_sort(n, m_sorted_luma[0], m_sorted_luma[1], m_luma, 0, sizeof(m_luma[0]), false); + m_pSorted_luma = m_sorted_luma[0]; + if (m_pSorted_luma_indices == m_sorted_luma[0]) + m_pSorted_luma = m_sorted_luma[1]; + + for (uint i = 0; i < n; i++) + m_pSorted_luma[i] = m_luma[m_pSorted_luma_indices[i]]; + } + + m_best_solution.m_coords.clear(); + m_best_solution.m_valid = false; + m_best_solution.m_error = cUINT64_MAX; + } + + bool etc1_optimizer::evaluate_solution(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution) + { + trial_solution.m_valid = false; + + if (m_pParams->m_constrain_against_base_color5) + { + const int dr = coords.m_unscaled_color.r - m_pParams->m_base_color5.r; + const int dg = coords.m_unscaled_color.g - m_pParams->m_base_color5.g; + const int db = coords.m_unscaled_color.b - m_pParams->m_base_color5.b; + + if ((rg_etc1::minimum(dr, dg, db) < cETC1ColorDeltaMin) || (rg_etc1::maximum(dr, dg, db) > cETC1ColorDeltaMax)) + return false; + } + + const color_quad_u8 base_color(coords.get_scaled_color()); + + const uint n = 8; + + trial_solution.m_error = cUINT64_MAX; + + for (uint inten_table = 0; inten_table < cETC1IntenModifierValues; inten_table++) + { + const int* pInten_table = g_etc1_inten_tables[inten_table]; + + color_quad_u8 block_colors[4]; + for (uint s = 0; s < 4; s++) + { + const int yd = pInten_table[s]; + block_colors[s].set(base_color.r + yd, base_color.g + yd, base_color.b + yd, 0); + } + + uint64 total_error = 0; + + const color_quad_u8* pSrc_pixels = m_pParams->m_pSrc_pixels; + for (uint c = 0; c < n; c++) + { + const color_quad_u8& src_pixel = *pSrc_pixels++; + + uint best_selector_index = 0; + uint best_error = rg_etc1::square(src_pixel.r - block_colors[0].r) + rg_etc1::square(src_pixel.g - block_colors[0].g) + rg_etc1::square(src_pixel.b - block_colors[0].b); + + uint trial_error = rg_etc1::square(src_pixel.r - block_colors[1].r) + rg_etc1::square(src_pixel.g - block_colors[1].g) + rg_etc1::square(src_pixel.b - block_colors[1].b); + if (trial_error < best_error) + { + best_error = trial_error; + best_selector_index = 1; + } + + trial_error = rg_etc1::square(src_pixel.r - block_colors[2].r) + rg_etc1::square(src_pixel.g - block_colors[2].g) + rg_etc1::square(src_pixel.b - block_colors[2].b); + if (trial_error < best_error) + { + best_error = trial_error; + best_selector_index = 2; + } + + trial_error = rg_etc1::square(src_pixel.r - block_colors[3].r) + rg_etc1::square(src_pixel.g - block_colors[3].g) + rg_etc1::square(src_pixel.b - block_colors[3].b); + if (trial_error < best_error) + { + best_error = trial_error; + best_selector_index = 3; + } + + m_temp_selectors[c] = static_cast(best_selector_index); + + total_error += best_error; + if (total_error >= trial_solution.m_error) + break; + } + + if (total_error < trial_solution.m_error) + { + trial_solution.m_error = total_error; + trial_solution.m_coords.m_inten_table = inten_table; + memcpy(trial_solution.m_selectors, m_temp_selectors, 8); + trial_solution.m_valid = true; + } + } + trial_solution.m_coords.m_unscaled_color = coords.m_unscaled_color; + trial_solution.m_coords.m_color4 = m_pParams->m_use_color4; + + bool success = false; + if (pBest_solution) + { + if (trial_solution.m_error < pBest_solution->m_error) + { + *pBest_solution = trial_solution; + success = true; + } + } + + return success; + } + + bool etc1_optimizer::evaluate_solution_fast(const etc1_solution_coordinates& coords, potential_solution& trial_solution, potential_solution* pBest_solution) + { + if (m_pParams->m_constrain_against_base_color5) + { + const int dr = coords.m_unscaled_color.r - m_pParams->m_base_color5.r; + const int dg = coords.m_unscaled_color.g - m_pParams->m_base_color5.g; + const int db = coords.m_unscaled_color.b - m_pParams->m_base_color5.b; + + if ((rg_etc1::minimum(dr, dg, db) < cETC1ColorDeltaMin) || (rg_etc1::maximum(dr, dg, db) > cETC1ColorDeltaMax)) + { + trial_solution.m_valid = false; + return false; + } + } + + const color_quad_u8 base_color(coords.get_scaled_color()); + + const uint n = 8; + + trial_solution.m_error = cUINT64_MAX; + + for (int inten_table = cETC1IntenModifierValues - 1; inten_table >= 0; --inten_table) + { + const int* pInten_table = g_etc1_inten_tables[inten_table]; + + uint block_inten[4]; + color_quad_u8 block_colors[4]; + for (uint s = 0; s < 4; s++) + { + const int yd = pInten_table[s]; + color_quad_u8 block_color(base_color.r + yd, base_color.g + yd, base_color.b + yd, 0); + block_colors[s] = block_color; + block_inten[s] = block_color.r + block_color.g + block_color.b; + } + + // evaluate_solution_fast() enforces/assumesd a total ordering of the input colors along the intensity (1,1,1) axis to more quickly classify the inputs to selectors. + // The inputs colors have been presorted along the projection onto this axis, and ETC1 block colors are always ordered along the intensity axis, so this classification is fast. + // 0 1 2 3 + // 01 12 23 + const uint block_inten_midpoints[3] = { block_inten[0] + block_inten[1], block_inten[1] + block_inten[2], block_inten[2] + block_inten[3] }; + + uint64 total_error = 0; + const color_quad_u8* pSrc_pixels = m_pParams->m_pSrc_pixels; + if ((m_pSorted_luma[n - 1] * 2) < block_inten_midpoints[0]) + { + if (block_inten[0] > m_pSorted_luma[n - 1]) + { + const uint min_error = labs(block_inten[0] - m_pSorted_luma[n - 1]); + if (min_error >= trial_solution.m_error) + continue; + } + + memset(&m_temp_selectors[0], 0, n); + + for (uint c = 0; c < n; c++) + total_error += block_colors[0].squared_distance_rgb(pSrc_pixels[c]); + } + else if ((m_pSorted_luma[0] * 2) >= block_inten_midpoints[2]) + { + if (m_pSorted_luma[0] > block_inten[3]) + { + const uint min_error = labs(m_pSorted_luma[0] - block_inten[3]); + if (min_error >= trial_solution.m_error) + continue; + } + + memset(&m_temp_selectors[0], 3, n); + + for (uint c = 0; c < n; c++) + total_error += block_colors[3].squared_distance_rgb(pSrc_pixels[c]); + } + else + { + uint cur_selector = 0, c; + for (c = 0; c < n; c++) + { + const uint y = m_pSorted_luma[c]; + while ((y * 2) >= block_inten_midpoints[cur_selector]) + if (++cur_selector > 2) + goto done; + const uint sorted_pixel_index = m_pSorted_luma_indices[c]; + m_temp_selectors[sorted_pixel_index] = static_cast(cur_selector); + total_error += block_colors[cur_selector].squared_distance_rgb(pSrc_pixels[sorted_pixel_index]); + } +done: + while (c < n) + { + const uint sorted_pixel_index = m_pSorted_luma_indices[c]; + m_temp_selectors[sorted_pixel_index] = 3; + total_error += block_colors[3].squared_distance_rgb(pSrc_pixels[sorted_pixel_index]); + ++c; + } + } + + if (total_error < trial_solution.m_error) + { + trial_solution.m_error = total_error; + trial_solution.m_coords.m_inten_table = inten_table; + memcpy(trial_solution.m_selectors, m_temp_selectors, n); + trial_solution.m_valid = true; + if (!total_error) + break; + } + } + trial_solution.m_coords.m_unscaled_color = coords.m_unscaled_color; + trial_solution.m_coords.m_color4 = m_pParams->m_use_color4; + + bool success = false; + if (pBest_solution) + { + if (trial_solution.m_error < pBest_solution->m_error) + { + *pBest_solution = trial_solution; + success = true; + } + } + + return success; + } + + static uint etc1_decode_value(uint diff, uint inten, uint selector, uint packed_c) + { + const uint limit = diff ? 32 : 16; limit; + RG_ETC1_ASSERT((diff < 2) && (inten < 8) && (selector < 4) && (packed_c < limit)); + int c; + if (diff) + c = (packed_c >> 2) | (packed_c << 3); + else + c = packed_c | (packed_c << 4); + c += g_etc1_inten_tables[inten][selector]; + c = rg_etc1::clamp(c, 0, 255); + return c; + } + + static inline int mul_8bit(int a, int b) { int t = a*b + 128; return (t + (t >> 8)) >> 8; } + + void pack_etc1_block_init() + { + for (uint diff = 0; diff < 2; diff++) + { + const uint limit = diff ? 32 : 16; + + for (uint inten = 0; inten < 8; inten++) + { + for (uint selector = 0; selector < 4; selector++) + { + const uint inverse_table_index = diff + (inten << 1) + (selector << 4); + for (uint color = 0; color < 256; color++) + { + uint best_error = cUINT32_MAX, best_packed_c = 0; + for (uint packed_c = 0; packed_c < limit; packed_c++) + { + int v = etc1_decode_value(diff, inten, selector, packed_c); + uint err = labs(v - color); + if (err < best_error) + { + best_error = err; + best_packed_c = packed_c; + if (!best_error) + break; + } + } + RG_ETC1_ASSERT(best_error <= 255); + g_etc1_inverse_lookup[inverse_table_index][color] = static_cast(best_packed_c | (best_error << 8)); + } + } + } + } + + uint expand5[32]; + for(int i = 0; i < 32; i++) + expand5[i] = (i << 3) | (i >> 2); + + for(int i = 0; i < 256 + 16; i++) + { + int v = clamp(i - 8, 0, 255); + g_quant5_tab[i] = static_cast(expand5[mul_8bit(v,31)]); + } + } + + // Packs solid color blocks efficiently using a set of small precomputed tables. + // For random 888 inputs, MSE results are better than Erricson's ETC1 packer in "slow" mode ~9.5% of the time, is slightly worse only ~.01% of the time, and is equal the rest of the time. + static uint64 pack_etc1_block_solid_color(etc1_block& block, const uint8* pColor, etc1_pack_params& pack_params) + { + pack_params; + RG_ETC1_ASSERT(g_etc1_inverse_lookup[0][255]); + + static uint s_next_comp[4] = { 1, 2, 0, 1 }; + + uint best_error = cUINT32_MAX, best_i = 0; + int best_x = 0, best_packed_c1 = 0, best_packed_c2 = 0; + + // For each possible 8-bit value, there is a precomputed list of diff/inten/selector configurations that allow that 8-bit value to be encoded with no error. + for (uint i = 0; i < 3; i++) + { + const uint c1 = pColor[s_next_comp[i]], c2 = pColor[s_next_comp[i + 1]]; + + const int delta_range = 1; + for (int delta = -delta_range; delta <= delta_range; delta++) + { + const int c_plus_delta = rg_etc1::clamp(pColor[i] + delta, 0, 255); + + const uint16* pTable; + if (!c_plus_delta) + pTable = g_color8_to_etc_block_config_0_255[0]; + else if (c_plus_delta == 255) + pTable = g_color8_to_etc_block_config_0_255[1]; + else + pTable = g_color8_to_etc_block_config_1_to_254[c_plus_delta - 1]; + + do + { + const uint x = *pTable++; + +#ifdef RG_ETC1_BUILD_DEBUG + const uint diff = x & 1; + const uint inten = (x >> 1) & 7; + const uint selector = (x >> 4) & 3; + const uint p0 = (x >> 8) & 255; + RG_ETC1_ASSERT(etc1_decode_value(diff, inten, selector, p0) == (uint)c_plus_delta); +#endif + + const uint16* pInverse_table = g_etc1_inverse_lookup[x & 0xFF]; + uint16 p1 = pInverse_table[c1]; + uint16 p2 = pInverse_table[c2]; + const uint trial_error = rg_etc1::square(c_plus_delta - pColor[i]) + rg_etc1::square(p1 >> 8) + rg_etc1::square(p2 >> 8); + if (trial_error < best_error) + { + best_error = trial_error; + best_x = x; + best_packed_c1 = p1 & 0xFF; + best_packed_c2 = p2 & 0xFF; + best_i = i; + if (!best_error) + goto found_perfect_match; + } + } while (*pTable != 0xFFFF); + } + } +found_perfect_match: + + const uint diff = best_x & 1; + const uint inten = (best_x >> 1) & 7; + + block.m_bytes[3] = static_cast(((inten | (inten << 3)) << 2) | (diff << 1)); + + const uint etc1_selector = g_selector_index_to_etc1[(best_x >> 4) & 3]; + *reinterpret_cast(&block.m_bytes[4]) = (etc1_selector & 2) ? 0xFFFF : 0; + *reinterpret_cast(&block.m_bytes[6]) = (etc1_selector & 1) ? 0xFFFF : 0; + + const uint best_packed_c0 = (best_x >> 8) & 255; + if (diff) + { + block.m_bytes[best_i] = static_cast(best_packed_c0 << 3); + block.m_bytes[s_next_comp[best_i]] = static_cast(best_packed_c1 << 3); + block.m_bytes[s_next_comp[best_i+1]] = static_cast(best_packed_c2 << 3); + } + else + { + block.m_bytes[best_i] = static_cast(best_packed_c0 | (best_packed_c0 << 4)); + block.m_bytes[s_next_comp[best_i]] = static_cast(best_packed_c1 | (best_packed_c1 << 4)); + block.m_bytes[s_next_comp[best_i+1]] = static_cast(best_packed_c2 | (best_packed_c2 << 4)); + } + + return best_error; + } + + static uint pack_etc1_block_solid_color_constrained( + etc1_optimizer::results& results, + uint num_colors, const uint8* pColor, + etc1_pack_params& pack_params, + bool use_diff, + const color_quad_u8* pBase_color5_unscaled) + { + RG_ETC1_ASSERT(g_etc1_inverse_lookup[0][255]); + + pack_params; + static uint s_next_comp[4] = { 1, 2, 0, 1 }; + + uint best_error = cUINT32_MAX, best_i = 0; + int best_x = 0, best_packed_c1 = 0, best_packed_c2 = 0; + + // For each possible 8-bit value, there is a precomputed list of diff/inten/selector configurations that allow that 8-bit value to be encoded with no error. + for (uint i = 0; i < 3; i++) + { + const uint c1 = pColor[s_next_comp[i]], c2 = pColor[s_next_comp[i + 1]]; + + const int delta_range = 1; + for (int delta = -delta_range; delta <= delta_range; delta++) + { + const int c_plus_delta = rg_etc1::clamp(pColor[i] + delta, 0, 255); + + const uint16* pTable; + if (!c_plus_delta) + pTable = g_color8_to_etc_block_config_0_255[0]; + else if (c_plus_delta == 255) + pTable = g_color8_to_etc_block_config_0_255[1]; + else + pTable = g_color8_to_etc_block_config_1_to_254[c_plus_delta - 1]; + + do + { + const uint x = *pTable++; + const uint diff = x & 1; + if (static_cast(use_diff) != diff) + { + if (*pTable == 0xFFFF) + break; + continue; + } + + if ((diff) && (pBase_color5_unscaled)) + { + const int p0 = (x >> 8) & 255; + int delta = p0 - static_cast(pBase_color5_unscaled->c[i]); + if ((delta < cETC1ColorDeltaMin) || (delta > cETC1ColorDeltaMax)) + { + if (*pTable == 0xFFFF) + break; + continue; + } + } + +#ifdef RG_ETC1_BUILD_DEBUG + { + const uint inten = (x >> 1) & 7; + const uint selector = (x >> 4) & 3; + const uint p0 = (x >> 8) & 255; + RG_ETC1_ASSERT(etc1_decode_value(diff, inten, selector, p0) == (uint)c_plus_delta); + } +#endif + + const uint16* pInverse_table = g_etc1_inverse_lookup[x & 0xFF]; + uint16 p1 = pInverse_table[c1]; + uint16 p2 = pInverse_table[c2]; + + if ((diff) && (pBase_color5_unscaled)) + { + int delta1 = (p1 & 0xFF) - static_cast(pBase_color5_unscaled->c[s_next_comp[i]]); + int delta2 = (p2 & 0xFF) - static_cast(pBase_color5_unscaled->c[s_next_comp[i + 1]]); + if ((delta1 < cETC1ColorDeltaMin) || (delta1 > cETC1ColorDeltaMax) || (delta2 < cETC1ColorDeltaMin) || (delta2 > cETC1ColorDeltaMax)) + { + if (*pTable == 0xFFFF) + break; + continue; + } + } + + const uint trial_error = rg_etc1::square(c_plus_delta - pColor[i]) + rg_etc1::square(p1 >> 8) + rg_etc1::square(p2 >> 8); + if (trial_error < best_error) + { + best_error = trial_error; + best_x = x; + best_packed_c1 = p1 & 0xFF; + best_packed_c2 = p2 & 0xFF; + best_i = i; + if (!best_error) + goto found_perfect_match; + } + } while (*pTable != 0xFFFF); + } + } +found_perfect_match: + + if (best_error == cUINT32_MAX) + return best_error; + + best_error *= num_colors; + + results.m_n = num_colors; + results.m_block_color4 = !(best_x & 1); + results.m_block_inten_table = (best_x >> 1) & 7; + memset(results.m_pSelectors, (best_x >> 4) & 3, num_colors); + + const uint best_packed_c0 = (best_x >> 8) & 255; + results.m_block_color_unscaled[best_i] = static_cast(best_packed_c0); + results.m_block_color_unscaled[s_next_comp[best_i]] = static_cast(best_packed_c1); + results.m_block_color_unscaled[s_next_comp[best_i + 1]] = static_cast(best_packed_c2); + results.m_error = best_error; + + return best_error; + } + + // Function originally from RYG's public domain real-time DXT1 compressor, modified for 555. + static void dither_block_555(color_quad_u8* dest, const color_quad_u8* block) + { + int err[8],*ep1 = err,*ep2 = err+4; + uint8 *quant = g_quant5_tab+8; + + memset(dest, 0xFF, sizeof(color_quad_u8)*16); + + // process channels seperately + for(int ch=0;ch<3;ch++) + { + uint8* bp = (uint8*)block; + uint8* dp = (uint8*)dest; + + bp += ch; dp += ch; + + memset(err,0, sizeof(err)); + for(int y = 0; y < 4; y++) + { + // pixel 0 + dp[ 0] = quant[bp[ 0] + ((3*ep2[1] + 5*ep2[0]) >> 4)]; + ep1[0] = bp[ 0] - dp[ 0]; + + // pixel 1 + dp[ 4] = quant[bp[ 4] + ((7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]) >> 4)]; + ep1[1] = bp[ 4] - dp[ 4]; + + // pixel 2 + dp[ 8] = quant[bp[ 8] + ((7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]) >> 4)]; + ep1[2] = bp[ 8] - dp[ 8]; + + // pixel 3 + dp[12] = quant[bp[12] + ((7*ep1[2] + 5*ep2[3] + ep2[2]) >> 4)]; + ep1[3] = bp[12] - dp[12]; + + // advance to next line + int* tmp = ep1; ep1 = ep2; ep2 = tmp; + bp += 16; + dp += 16; + } + } + } + + unsigned int pack_etc1_block(void* pETC1_block, const unsigned int* pSrc_pixels_rgba, etc1_pack_params& pack_params) + { + const color_quad_u8* pSrc_pixels = reinterpret_cast(pSrc_pixels_rgba); + etc1_block& dst_block = *static_cast(pETC1_block); + +#ifdef RG_ETC1_BUILD_DEBUG + // Ensure all alpha values are 0xFF. + for (uint i = 0; i < 16; i++) + { + RG_ETC1_ASSERT(pSrc_pixels[i].a == 255); + } +#endif + + color_quad_u8 src_pixel0(pSrc_pixels[0]); + + // Check for solid block. + const uint32 first_pixel_u32 = pSrc_pixels->m_u32; + int r; + for (r = 15; r >= 1; --r) + if (pSrc_pixels[r].m_u32 != first_pixel_u32) + break; + if (!r) + return static_cast(16 * pack_etc1_block_solid_color(dst_block, &pSrc_pixels[0].r, pack_params)); + + color_quad_u8 dithered_pixels[16]; + if (pack_params.m_dithering) + { + dither_block_555(dithered_pixels, pSrc_pixels); + pSrc_pixels = dithered_pixels; + } + + etc1_optimizer optimizer; + + uint64 best_error = cUINT64_MAX; + uint best_flip = false, best_use_color4 = false; + + uint8 best_selectors[2][8]; + etc1_optimizer::results best_results[2]; + for (uint i = 0; i < 2; i++) + { + best_results[i].m_n = 8; + best_results[i].m_pSelectors = best_selectors[i]; + } + + uint8 selectors[3][8]; + etc1_optimizer::results results[3]; + + for (uint i = 0; i < 3; i++) + { + results[i].m_n = 8; + results[i].m_pSelectors = selectors[i]; + } + + color_quad_u8 subblock_pixels[8]; + + etc1_optimizer::params params(pack_params); + params.m_num_src_pixels = 8; + params.m_pSrc_pixels = subblock_pixels; + + for (uint flip = 0; flip < 2; flip++) + { + for (uint use_color4 = 0; use_color4 < 2; use_color4++) + { + uint64 trial_error = 0; + + uint subblock; + for (subblock = 0; subblock < 2; subblock++) + { + if (flip) + memcpy(subblock_pixels, pSrc_pixels + subblock * 8, sizeof(color_quad_u8) * 8); + else + { + const color_quad_u8* pSrc_col = pSrc_pixels + subblock * 2; + subblock_pixels[0] = pSrc_col[0]; subblock_pixels[1] = pSrc_col[4]; subblock_pixels[2] = pSrc_col[8]; subblock_pixels[3] = pSrc_col[12]; + subblock_pixels[4] = pSrc_col[1]; subblock_pixels[5] = pSrc_col[5]; subblock_pixels[6] = pSrc_col[9]; subblock_pixels[7] = pSrc_col[13]; + } + + results[2].m_error = cUINT64_MAX; + if ((params.m_quality >= cMediumQuality) && ((subblock) || (use_color4))) + { + const uint32 subblock_pixel0_u32 = subblock_pixels[0].m_u32; + for (r = 7; r >= 1; --r) + if (subblock_pixels[r].m_u32 != subblock_pixel0_u32) + break; + if (!r) + { + pack_etc1_block_solid_color_constrained(results[2], 8, &subblock_pixels[0].r, pack_params, !use_color4, (subblock && !use_color4) ? &results[0].m_block_color_unscaled : NULL); + } + } + + params.m_use_color4 = (use_color4 != 0); + params.m_constrain_against_base_color5 = false; + + if ((!use_color4) && (subblock)) + { + params.m_constrain_against_base_color5 = true; + params.m_base_color5 = results[0].m_block_color_unscaled; + } + + if (params.m_quality == cHighQuality) + { + static const int s_scan_delta_0_to_4[] = { -4, -3, -2, -1, 0, 1, 2, 3, 4 }; + params.m_scan_delta_size = RG_ETC1_ARRAY_SIZE(s_scan_delta_0_to_4); + params.m_pScan_deltas = s_scan_delta_0_to_4; + } + else if (params.m_quality == cMediumQuality) + { + static const int s_scan_delta_0_to_1[] = { -1, 0, 1 }; + params.m_scan_delta_size = RG_ETC1_ARRAY_SIZE(s_scan_delta_0_to_1); + params.m_pScan_deltas = s_scan_delta_0_to_1; + } + else + { + static const int s_scan_delta_0[] = { 0 }; + params.m_scan_delta_size = RG_ETC1_ARRAY_SIZE(s_scan_delta_0); + params.m_pScan_deltas = s_scan_delta_0; + } + + optimizer.init(params, results[subblock]); + if (!optimizer.compute()) + break; + + if (params.m_quality >= cMediumQuality) + { + // TODO: Fix fairly arbitrary/unrefined thresholds that control how far away to scan for potentially better solutions. + const uint refinement_error_thresh0 = 3000; + const uint refinement_error_thresh1 = 6000; + if (results[subblock].m_error > refinement_error_thresh0) + { + if (params.m_quality == cMediumQuality) + { + static const int s_scan_delta_2_to_3[] = { -3, -2, 2, 3 }; + params.m_scan_delta_size = RG_ETC1_ARRAY_SIZE(s_scan_delta_2_to_3); + params.m_pScan_deltas = s_scan_delta_2_to_3; + } + else + { + static const int s_scan_delta_5_to_5[] = { -5, 5 }; + static const int s_scan_delta_5_to_8[] = { -8, -7, -6, -5, 5, 6, 7, 8 }; + if (results[subblock].m_error > refinement_error_thresh1) + { + params.m_scan_delta_size = RG_ETC1_ARRAY_SIZE(s_scan_delta_5_to_8); + params.m_pScan_deltas = s_scan_delta_5_to_8; + } + else + { + params.m_scan_delta_size = RG_ETC1_ARRAY_SIZE(s_scan_delta_5_to_5); + params.m_pScan_deltas = s_scan_delta_5_to_5; + } + } + + if (!optimizer.compute()) + break; + } + + if (results[2].m_error < results[subblock].m_error) + results[subblock] = results[2]; + } + + trial_error += results[subblock].m_error; + if (trial_error >= best_error) + break; + } + + if (subblock < 2) + continue; + + best_error = trial_error; + best_results[0] = results[0]; + best_results[1] = results[1]; + best_flip = flip; + best_use_color4 = use_color4; + + } // use_color4 + + } // flip + + int dr = best_results[1].m_block_color_unscaled.r - best_results[0].m_block_color_unscaled.r; + int dg = best_results[1].m_block_color_unscaled.g - best_results[0].m_block_color_unscaled.g; + int db = best_results[1].m_block_color_unscaled.b - best_results[0].m_block_color_unscaled.b; + RG_ETC1_ASSERT(best_use_color4 || (rg_etc1::minimum(dr, dg, db) >= cETC1ColorDeltaMin) && (rg_etc1::maximum(dr, dg, db) <= cETC1ColorDeltaMax)); + + if (best_use_color4) + { + dst_block.m_bytes[0] = static_cast(best_results[1].m_block_color_unscaled.r | (best_results[0].m_block_color_unscaled.r << 4)); + dst_block.m_bytes[1] = static_cast(best_results[1].m_block_color_unscaled.g | (best_results[0].m_block_color_unscaled.g << 4)); + dst_block.m_bytes[2] = static_cast(best_results[1].m_block_color_unscaled.b | (best_results[0].m_block_color_unscaled.b << 4)); + } + else + { + if (dr < 0) dr += 8; dst_block.m_bytes[0] = static_cast((best_results[0].m_block_color_unscaled.r << 3) | dr); + if (dg < 0) dg += 8; dst_block.m_bytes[1] = static_cast((best_results[0].m_block_color_unscaled.g << 3) | dg); + if (db < 0) db += 8; dst_block.m_bytes[2] = static_cast((best_results[0].m_block_color_unscaled.b << 3) | db); + } + + dst_block.m_bytes[3] = static_cast( (best_results[1].m_block_inten_table << 2) | (best_results[0].m_block_inten_table << 5) | ((~best_use_color4 & 1) << 1) | best_flip ); + + uint selector0 = 0, selector1 = 0; + if (best_flip) + { + // flipped: + // { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, + // { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 } + // + // { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 }, + // { 0, 3 }, { 1, 3 }, { 2, 3 }, { 3, 3 } + const uint8* pSelectors0 = best_results[0].m_pSelectors; + const uint8* pSelectors1 = best_results[1].m_pSelectors; + for (int x = 3; x >= 0; --x) + { + uint b; + b = g_selector_index_to_etc1[pSelectors1[4 + x]]; + selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1); + + b = g_selector_index_to_etc1[pSelectors1[x]]; + selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1); + + b = g_selector_index_to_etc1[pSelectors0[4 + x]]; + selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1); + + b = g_selector_index_to_etc1[pSelectors0[x]]; + selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1); + } + } + else + { + // non-flipped: + // { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, + // { 1, 0 }, { 1, 1 }, { 1, 2 }, { 1, 3 } + // + // { 2, 0 }, { 2, 1 }, { 2, 2 }, { 2, 3 }, + // { 3, 0 }, { 3, 1 }, { 3, 2 }, { 3, 3 } + for (int subblock = 1; subblock >= 0; --subblock) + { + const uint8* pSelectors = best_results[subblock].m_pSelectors + 4; + for (uint i = 0; i < 2; i++) + { + uint b; + b = g_selector_index_to_etc1[pSelectors[3]]; + selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1); + + b = g_selector_index_to_etc1[pSelectors[2]]; + selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1); + + b = g_selector_index_to_etc1[pSelectors[1]]; + selector0 = (selector0 << 1) | (b & 1); selector1 = (selector1 << 1) | (b >> 1); + + b = g_selector_index_to_etc1[pSelectors[0]]; + selector0 = (selector0 << 1) | (b & 1);selector1 = (selector1 << 1) | (b >> 1); + + pSelectors -= 4; + } + } + } + + dst_block.m_bytes[4] = static_cast(selector1 >> 8); dst_block.m_bytes[5] = static_cast(selector1 & 0xFF); + dst_block.m_bytes[6] = static_cast(selector0 >> 8); dst_block.m_bytes[7] = static_cast(selector0 & 0xFF); + + return static_cast(best_error); + } + +} // namespace rg_etc1 diff --git a/ext/rg_etc1/rg_etc1.h b/ext/rg_etc1/rg_etc1.h new file mode 100644 index 0000000000..bb2961c361 --- /dev/null +++ b/ext/rg_etc1/rg_etc1.h @@ -0,0 +1,76 @@ +// File: rg_etc1.h - Fast, high quality ETC1 block packer/unpacker - Rich Geldreich +// Please see ZLIB license at the end of this file. +#pragma once + +namespace rg_etc1 +{ + // Unpacks an 8-byte ETC1 compressed block to a block of 4x4 32bpp RGBA pixels. + // Returns false if the block is invalid. Invalid blocks will still be unpacked with clamping. + // This function is thread safe, and does not dynamically allocate any memory. + // If preserve_alpha is true, the alpha channel of the destination pixels will not be overwritten. Otherwise, alpha will be set to 255. + bool unpack_etc1_block(const void *pETC1_block, unsigned int* pDst_pixels_rgba, int stride, bool preserve_alpha = false); + + // Quality setting = the higher the quality, the slower. + // To pack large textures, it is highly recommended to call pack_etc1_block() in parallel, on different blocks, from multiple threads (particularly when using cHighQuality). + enum etc1_quality + { + cLowQuality, + cMediumQuality, + cHighQuality, + }; + + struct etc1_pack_params + { + etc1_quality m_quality; + bool m_dithering; + + inline etc1_pack_params() + { + clear(); + } + + void clear() + { + m_quality = cHighQuality; + m_dithering = false; + } + }; + + // Important: pack_etc1_block_init() must be called before calling pack_etc1_block(). + void pack_etc1_block_init(); + + // Packs a 4x4 block of 32bpp RGBA pixels to an 8-byte ETC1 block. + // 32-bit RGBA pixels must always be arranged as (R,G,B,A) (R first, A last) in memory, independent of platform endianness. A should always be 255. + // Returns squared error of result. + // This function is thread safe, and does not dynamically allocate any memory. + // pack_etc1_block() does not currently support "perceptual" colorspace metrics - it primarily optimizes for RGB RMSE. + unsigned int pack_etc1_block(void* pETC1_block, const unsigned int* pSrc_pixels_rgba, etc1_pack_params& pack_params); + +} // namespace rg_etc1 + +//------------------------------------------------------------------------------ +// +// rg_etc1 uses the ZLIB license: +// http://opensource.org/licenses/Zlib +// +// Copyright (c) 2012 Rich Geldreich +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//------------------------------------------------------------------------------ diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 77e5c353f4..54c7dd61db 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -4,7 +4,7 @@ #if !defined(USING_GLES2) #include "image/png_load.h" -#include "ext/etcpack/etcdec.h" +#include "ext/rg_etc1/rg_etc1.h" #endif #include "image/zim_load.h" @@ -183,8 +183,8 @@ uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { memset(rgba, 0xFF, width * height * 4); for (int y = 0; y < height; y += 4) { for (int x = 0; x < width; x += 4) { - DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8, - rgba + (y * width + x) * 4, width, 255); + rg_etc1::unpack_etc1_block(etc1 + ((y / 4) * width/4 + (x / 4)) * 8, + (uint32_t *)rgba + (y * width + x), width, false); } } return rgba; diff --git a/image/zim_load.h b/image/zim_load.h index fc10dd4a5d..4e90c717c9 100644 --- a/image/zim_load.h +++ b/image/zim_load.h @@ -33,6 +33,10 @@ enum { ZIM_DITHER = 64, // If set, dithers during save if color reduction is necessary. ZIM_CLAMP = 128, // Texture should default to clamp instead of wrap. ZIM_ZLIB_COMPRESSED = 256, + ZIM_ETC1_LOW = 512, + ZIM_ETC1_MEDIUM = 1024, + ZIM_ETC1_HIGH = 0, // default + ZIM_ETC1_DITHER = 2048, }; // ZIM will only ever support up to 12 levels (4096x4096 max). diff --git a/image/zim_save.cpp b/image/zim_save.cpp index 288340d5fa..be9bb5485d 100644 --- a/image/zim_save.cpp +++ b/image/zim_save.cpp @@ -2,7 +2,7 @@ #include #include #include "base/logging.h" -#include "ext/etcpack/etcpack.h" +#include "ext/rg_etc1/rg_etc1.h" #include "image/zim_save.h" #include "zlib.h" @@ -101,6 +101,17 @@ void Convert(const uint8_t *image_data, int width, int height, int pitch, int fl break; } case ZIM_ETC1: { + rg_etc1::pack_etc1_block_init(); + rg_etc1::etc1_pack_params params; + params.m_dithering = false; //(flags & ZIM_ETC1_DITHER) != 0; + if (flags & ZIM_ETC1_LOW) { + params.m_quality = rg_etc1::cLowQuality; + } else if (flags & ZIM_ETC1_MEDIUM) { + params.m_quality = rg_etc1::cMediumQuality; + } else { + params.m_quality = rg_etc1::cHighQuality; + } + // Check for power of 2 if (!ispowerof2(width) || !ispowerof2(height)) { FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height); @@ -113,8 +124,11 @@ void Convert(const uint8_t *image_data, int width, int height, int pitch, int fl #pragma omp parallel for for (int y = 0; y < blockh; y++) { for (int x = 0; x < blockw; x++) { - CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width, - (*data) + (blockw * y + x) * 8, 1); + uint32_t block[16]; + for (int iy = 0; iy < 4; iy++) { + memcpy(block + 4 * iy, image_data + ((y * 4 + iy) * (pitch/4) + x * 4) * 4, 16); + } + rg_etc1::pack_etc1_block((*data) + (blockw * y + x) * 8, block, params); } } width = blockw * 4; diff --git a/native.vcxproj b/native.vcxproj index cb234d18e4..c54dbfeabf 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -201,8 +201,7 @@ - - + @@ -294,8 +293,7 @@ - - + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 0c27bfa6ad..9baa377be3 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -53,9 +53,6 @@ gfx - - ext - audio @@ -98,9 +95,6 @@ math - - ext - base @@ -242,6 +236,9 @@ ext + + ext + @@ -274,9 +271,6 @@ gfx - - ext - audio @@ -301,9 +295,6 @@ gfx - - ext - base @@ -429,6 +420,9 @@ ext + + ext + diff --git a/tools/zimtool.cpp b/tools/zimtool.cpp index 851f8a7933..69f84221b3 100644 --- a/tools/zimtool.cpp +++ b/tools/zimtool.cpp @@ -70,6 +70,8 @@ int main(int argc, char **argv) { break; } } + // TODO: make setting? + flags |= ZIM_ETC1_MEDIUM; if ((flags & ZIM_FORMAT_MASK) == ZIM_ETC1) { if (flags & ZIM_GEN_MIPS) { fprintf(stderr, "WARNING: Cannot generate ETC1 mips at runtime\n"); From ede99eecb4bc81d89fc4f3f60bacdfba868ba9e1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 29 Mar 2013 16:55:45 +0100 Subject: [PATCH 0291/1445] Add warn log when falling back to xor texture --- gfx/texture.cpp | 2 ++ gfx_es2/draw_buffer.cpp | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 54c7dd61db..1d89dd2229 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -113,6 +113,7 @@ bool Texture::Load(const char *filename) { if (!strcmp("png", &name[len-3]) || !strcmp("PNG", &name[len-3])) { if (!LoadPNG(fn)) { + WLOG("WARNING: Failed to load .png %s, falling back to ugly gray XOR pattern!", fn); LoadXOR(); return false; } else { @@ -124,6 +125,7 @@ bool Texture::Load(const char *filename) { if (LoadZIM(name)) { return true; } else { + WLOG("WARNING: Failed to load .zim texture %s, falling back to ugly gray XOR pattern!", fn); LoadXOR(); return false; } diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 6e2545e001..87273b87d0 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -120,6 +120,13 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { } void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) { +#ifdef _DEBUG + if (count_ >= MAX_VERTS) { + FLOG("Overflowed the DrawBuffer"); + return; + } +#endif + Vertex *vert = &verts_[count_++]; vert->x = x; vert->y = y; From 9c23f850589963c3377134261c368baf46563e27 Mon Sep 17 00:00:00 2001 From: tpu Date: Sat, 30 Mar 2013 01:03:25 +0800 Subject: [PATCH 0292/1445] mix FBO_ARB and FBO_EXT code. --- gfx_es2/fbo.cpp | 150 +++++++++++++++++++++++++++++++++++-------- gfx_es2/gl_state.cpp | 2 + gfx_es2/gl_state.h | 2 + 3 files changed, 127 insertions(+), 27 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index c99fc0634c..a4f1624625 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -38,8 +38,7 @@ struct FBO { // On PC, we always use GL_DEPTH24_STENCIL8. // On Android, we try to use what's available. -FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { - CheckGLExtensions(); +FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { FBO *fbo = new FBO(); fbo->width = width; fbo->height = height; @@ -77,6 +76,83 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 24-bit Z, 8-bit stencil + glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, width, height); + //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height); + + // Bind it all together + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + switch(status) { + case GL_FRAMEBUFFER_COMPLETE_EXT: + // ILOG("Framebuffer verified complete."); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); + break; + default: + FLOG("Other framebuffer error: %i", status); + break; + } + // Unbind state we don't need + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + glBindTexture(GL_TEXTURE_2D, 0); + return fbo; +} + +FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { + CheckGLExtensions(); + if(gl_extensions.FBO_ARB==false) + return fbo_ext_create(width, height, num_color_textures, z_stencil, colorDepth); + + FBO *fbo = new FBO(); + fbo->width = width; + fbo->height = height; + fbo->colorDepth = colorDepth; + + // Color texture is same everywhere + glGenFramebuffers(1, &fbo->handle); + glGenTextures(1, &fbo->color_texture); + + // Create the surfaces. + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // TODO: We could opt to only create 16-bit render targets on slow devices. For later. + switch (colorDepth) { + case FBO_8888: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + break; + case FBO_4444: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); + break; + case FBO_5551: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); + break; + case FBO_565: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); + break; + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + #ifdef USING_GLES2 if (gl_extensions.OES_packed_depth_stencil) { ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", width, height); @@ -117,30 +193,26 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F fbo->stencil_buffer = 0; fbo->z_buffer = 0; // 24-bit Z, 8-bit stencil - glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height); - //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height); + glGenRenderbuffers(1, &fbo->z_stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); // Bind it all together - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); - //glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); - - // When enable STENCIL, glCheckFramebufferStatusEXT will return GL_FRAMEBUFFER_UNSUPPORTED on GMA4500. - + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); #endif - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: + case GL_FRAMEBUFFER_COMPLETE: // ILOG("Framebuffer verified complete."); break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + case GL_FRAMEBUFFER_UNSUPPORTED: ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); break; default: @@ -148,24 +220,38 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F break; } // Unbind state we don't need - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); return fbo; } void fbo_unbind() { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + CheckGLExtensions(); + + if(gl_extensions.FBO_ARB){ + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + }else{ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } #ifdef IOS bindDefaultFBO(); #endif } void fbo_bind_as_render_target(FBO *fbo) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + if(gl_extensions.FBO_ARB){ + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + }else{ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + } } void fbo_bind_for_read(FBO *fbo) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + if(gl_extensions.FBO_ARB){ + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); + }else{ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + } } void fbo_bind_color_as_texture(FBO *fbo, int color) { @@ -173,13 +259,23 @@ void fbo_bind_color_as_texture(FBO *fbo, int color) { } void fbo_destroy(FBO *fbo) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glDeleteFramebuffersEXT(1, &fbo->handle); + if(gl_extensions.FBO_ARB){ + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &fbo->handle); + glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); + }else{ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, &fbo->handle); + glDeleteRenderbuffersEXT(1, &fbo->z_stencil_buffer); + } + glDeleteTextures(1, &fbo->color_texture); - glDeleteRenderbuffersEXT(1, &fbo->z_stencil_buffer); delete fbo; } diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 6a50f648a7..77f33319c7 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -59,4 +59,6 @@ void CheckGLExtensions() { gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; + gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; + gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; } diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 2e325e0fbf..14dbd48e23 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -202,6 +202,8 @@ struct GLExtensions { bool OES_packed_depth_stencil; bool OES_depth_texture; bool EXT_discard_framebuffer; + bool FBO_ARB; + bool FBO_EXT; }; extern GLExtensions gl_extensions; From a47c3b465eb2a37f817dd0950cec8cd81375a2db Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 29 Mar 2013 18:09:59 +0100 Subject: [PATCH 0293/1445] NativeMix now returns int --- base/NativeApp.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/NativeApp.h b/base/NativeApp.h index 7a4195f8dd..04630fbb9c 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -61,7 +61,9 @@ void NativeRender(); // of num_samples. // This function may be called from a totally separate thread from // the rest of the game, so be careful with synchronization. -void NativeMix(short *audio, int num_samples); +// Returns the number of samples actually output. The app should do everything it can +// to fill the buffer completely. +int NativeMix(short *audio, int num_samples); void NativeSetMixer(void* mixer); // Called when it's time to shutdown. After this has been called, From 4f5a60d82b38dbb609084782211a272b9e4e53fb Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 29 Mar 2013 20:04:36 +0100 Subject: [PATCH 0294/1445] Buildfix --- android/native-audio-so.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/native-audio-so.h b/android/native-audio-so.h index bde11af263..c44e7a50a3 100644 --- a/android/native-audio-so.h +++ b/android/native-audio-so.h @@ -2,7 +2,7 @@ // Header for dynamic loading -typedef void (*AndroidAudioCallback)(short *buffer, int num_samples); +typedef int (*AndroidAudioCallback)(short *buffer, int num_samples); typedef bool (*OpenSLWrap_Init_T)(AndroidAudioCallback cb); typedef void (*OpenSLWrap_Shutdown_T)(); From 4ffc4f0415c2b2efa79c900fa61da78d61411797 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Mar 2013 00:09:58 +0100 Subject: [PATCH 0295/1445] Cmakelist update --- ext/rg_etc1/CMakeLists.txt | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/ext/rg_etc1/CMakeLists.txt b/ext/rg_etc1/CMakeLists.txt index aa8e189074..70f73115f4 100644 --- a/ext/rg_etc1/CMakeLists.txt +++ b/ext/rg_etc1/CMakeLists.txt @@ -1,36 +1,3 @@ cmake_minimum_required(VERSION 2.6) -add_library(etcdec etcdec.cpp) -#if UNIX -add_definitions(-fPIC) - -add_library(etcpack etcpack.cpp) - -add_definitions(-g) -add_definitions(-O2) -add_definitions(-Wall) -add_definitions(-DSDL) -add_definitions(-Wno-multichar) -# add_definitions(-fno-strict-aliasing) -add_definitions(-fstrict-aliasing) - -set(LIBS ${LIBS}) - -add_executable(etctool etctool.cpp image.cpp) -target_link_libraries(etctool etcdec etcpack) - -#add_executable(zimtool zimtool.cpp) -#target_link_libraries(zimtool png freetype z image file zip) - -#set(SRCS -# draw2d.cpp -# fbo.cpp -# glsl_program.cpp) -# -#set(SRCS ${SRCS}) - -#add_library(gfx_es2 STATIC ${SRCS}) - -#if(UNIX) -# add_definitions(-fPIC) -#endif(UNIX) +add_library(rg_etc1 rg_etc1.cpp) From abc38a90f6ec067090dbbc68ecd7f489732d54c0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 29 Mar 2013 22:20:21 -0700 Subject: [PATCH 0296/1445] Buildfix for Mac/Linux/etc. Although, Qt seems more involved... --- base/BlackberryMain.cpp | 3 ++- base/PCMain.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index fdb3f1cd36..850ddab926 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -94,6 +94,8 @@ void LaunchEmail(const char *email_address) navigator_invoke((std::string("mailto:") + email_address).c_str(), &error); } +InputState input_state; + // Input const int buttonMappings[18] = { KEYCODE_X, //A @@ -387,7 +389,6 @@ int main(int argc, char *argv[]) { vibration_request_events(0); #endif BlackberryAudio* audio = new BlackberryAudio(); - InputState input_state; bool running = true; while (running) { input_state.mouse_valid = false; diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 4b1f1a8d73..76afe561a8 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -222,6 +222,8 @@ void LaunchEmail(const char *email_address) +InputState input_state; + const int buttonMappings[14] = { #ifdef PANDORA SDLK_PAGEDOWN, //X => cross @@ -484,7 +486,6 @@ int main(int argc, char *argv[]) { } #endif - InputState input_state; int framecount = 0; bool nextFrameMD = 0; float t = 0, lastT = 0; From 6a014ab92d970b337351c42d70e4dfd433e94e54 Mon Sep 17 00:00:00 2001 From: tpu Date: Sat, 30 Mar 2013 15:34:13 +0800 Subject: [PATCH 0297/1445] add condition define for USING_GLES2 --- gfx_es2/fbo.cpp | 15 ++++++++++++++- gfx_es2/gl_state.cpp | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index a4f1624625..27ecaa92b1 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -38,6 +38,7 @@ struct FBO { // On PC, we always use GL_DEPTH24_STENCIL8. // On Android, we try to use what's available. +#ifndef USING_GLES2 FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { FBO *fbo = new FBO(); fbo->width = width; @@ -110,11 +111,15 @@ FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stenci glBindTexture(GL_TEXTURE_2D, 0); return fbo; } +#endif FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { CheckGLExtensions(); - if(gl_extensions.FBO_ARB==false) + +#ifndef USING_GLES2 + if(!gl_extensions.FBO_ARB) return fbo_ext_create(width, height, num_color_textures, z_stencil, colorDepth); +#endif FBO *fbo = new FBO(); fbo->width = width; @@ -231,7 +236,9 @@ void fbo_unbind() { if(gl_extensions.FBO_ARB){ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); }else{ +#ifndef USING_GLES2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +#endif } #ifdef IOS bindDefaultFBO(); @@ -242,7 +249,9 @@ void fbo_bind_as_render_target(FBO *fbo) { if(gl_extensions.FBO_ARB){ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); }else{ +#ifndef USING_GLES2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); +#endif } } @@ -250,7 +259,9 @@ void fbo_bind_for_read(FBO *fbo) { if(gl_extensions.FBO_ARB){ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); }else{ +#ifndef USING_GLES2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); +#endif } } @@ -267,12 +278,14 @@ void fbo_destroy(FBO *fbo) { glDeleteFramebuffers(1, &fbo->handle); glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); }else{ +#ifndef USING_GLES2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &fbo->handle); glDeleteRenderbuffersEXT(1, &fbo->z_stencil_buffer); +#endif } glDeleteTextures(1, &fbo->color_texture); diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 77f33319c7..ee84087ed0 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -59,6 +59,11 @@ void CheckGLExtensions() { gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; +#ifdef USING_GLES2 + gl_extensions.FBO_ARB = true; + gl_extensions.FBO_EXT = false; +#else gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; +#endif } From 1f34f8ff60e32396d39f3c5add58841dff772e34 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Mar 2013 12:56:39 +0100 Subject: [PATCH 0298/1445] Allow loading textures from a PNG in RAM. Add startsWith string function. --- base/stringutil.h | 4 ++++ gfx/texture.cpp | 31 ++++++++++++++++++++----------- gfx/texture.h | 22 ++++++++++++---------- image/png_load.h | 2 -- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/base/stringutil.h b/base/stringutil.h index 4c5824f9a0..d34ce12de0 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -23,6 +23,10 @@ public: // Other simple string utilities. +inline bool startsWith(const std::string &str, const std::string &what) { + return str.substr(0, what.size()) == what; +} + inline bool endsWith(const std::string &str, const std::string &what) { return str.substr(str.size() - what.size()) == what; } diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 1d89dd2229..a5cc819cab 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -2,11 +2,8 @@ #include #include -#if !defined(USING_GLES2) -#include "image/png_load.h" #include "ext/rg_etc1/rg_etc1.h" -#endif - +#include "image/png_load.h" #include "image/zim_load.h" #include "base/logging.h" #include "gfx/texture.h" @@ -65,7 +62,6 @@ bool Texture::Load(const char *filename) { glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); if (bpp == 1) { - #if defined(USING_GLES2) glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); #else @@ -109,7 +105,6 @@ bool Texture::Load(const char *filename) { const char *name = fn; if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); len = strlen(name); -#if !defined(USING_GLES2) if (!strcmp("png", &name[len-3]) || !strcmp("PNG", &name[len-3])) { if (!LoadPNG(fn)) { @@ -119,9 +114,7 @@ bool Texture::Load(const char *filename) { } else { return true; } - } else -#endif - if (!strcmp("zim", &name[len-3])) { + } else if (!strcmp("zim", &name[len-3])) { if (LoadZIM(name)) { return true; } else { @@ -134,7 +127,6 @@ bool Texture::Load(const char *filename) { return false; } -#if !defined(USING_GLES2) bool Texture::LoadPNG(const char *filename) { unsigned char *image_data; if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { @@ -151,7 +143,23 @@ bool Texture::LoadPNG(const char *filename) { free(image_data); return true; } -#endif + +bool Texture::LoadPNG(const uint8_t *data, size_t size) { + unsigned char *image_data; + if (1 != pngLoadPtr(data, size, &width_, &height_, &image_data, false)) { + return false; + } + GL_CHECK(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(ZIM_GEN_MIPS); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image_data); + glGenerateMipmap(GL_TEXTURE_2D); + GL_CHECK(); + free(image_data); + return true; +} bool Texture::LoadXOR() { width_ = height_ = 256; @@ -248,6 +256,7 @@ bool Texture::LoadZIM(const char *filename) { glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); GL_CHECK(); #else + // TODO: OpenGL 4.3+ accepts ETC1 so we should not have to do this anymore on those cards. image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h); glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]); diff --git a/gfx/texture.h b/gfx/texture.h index 47f6e6b602..9e0f1b27b9 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -1,10 +1,11 @@ -#ifndef _TEXTURE_H -#define _TEXTURE_H +#pragma once -// Load and manage OpenGL textures easily. Supports ETC1 compressed texture with mipmaps. +// Load and manage OpenGL textures easily. Supports ETC1 compressed texture with mipmaps +// in the custom ZIM format. #include +#include "base/basictypes.h" #include "gfx/gl_lost_manager.h" class Texture : public GfxResourceHolder { @@ -15,10 +16,17 @@ public: // Deduces format from the filename. // If loading fails, will load a 256x256 XOR texture. // If filename begins with "gen:", will defer to texture_gen.cpp/h. + // When format is known, it's fine to use LoadZIM etc directly. + // Those will NOT auto-fall back to xor texture however! bool Load(const char *filename); void Bind(int stage = -1); void Destroy(); + // PNG from memory buffer + bool LoadPNG(const uint8_t *data, size_t size); + bool LoadZIM(const char *filename); + bool LoadPNG(const char *filename); + unsigned int Handle() const { return id_; } @@ -27,10 +35,6 @@ public: std::string filename() const { return filename_; } private: - bool LoadZIM(const char *filename); -#if !defined(USING_GLES2) - bool LoadPNG(const char *filename); -#endif bool LoadXOR(); // Loads a placeholder texture. std::string filename_; @@ -39,6 +43,4 @@ private: #endif unsigned int id_; int width_, height_; -}; - -#endif +}; \ No newline at end of file diff --git a/image/png_load.h b/image/png_load.h index 1b1babc1af..0cc7ab42ea 100644 --- a/image/png_load.h +++ b/image/png_load.h @@ -9,6 +9,4 @@ int pngLoad(const char *file, int *pwidth, int pngLoadPtr(const unsigned char *input_ptr, const int input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip); - - #endif // _PNG_LOAD_H From faf8b260ed7617aaa08e6d420db95e03eef659d3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Mar 2013 16:48:02 +0100 Subject: [PATCH 0299/1445] Add TouchCrossPad widget which actually can do diagonals reasonably. --- ui/virtual_input.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++ ui/virtual_input.h | 30 +++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index e9d051397c..e6735773ff 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -1,4 +1,5 @@ #include +#include "base/logging.h" #include "gfx_es2/draw_buffer.h" #include "gfx/texture_atlas.h" #include "input/input_state.h" @@ -45,6 +46,67 @@ void TouchButton::draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay) db.DrawImageRotated(overlayImageIndex_, x_ + w_*scale_/2, y_ + h_*scale_/2, scale, rotationAngle_, colorOverlay); } +TouchCrossPad::TouchCrossPad(const Atlas *atlas, int arrowIndex, int overlayIndex) + : atlas_(atlas), arrowIndex_(arrowIndex), overlayIndex_(overlayIndex) +{ + +} + +void TouchCrossPad::update(InputState &input_state) +{ + float stick_size_ = radius_ * 2; + float inv_stick_size = 1.0f / (stick_size_ * scale_); + const float deadzone = 0.17f; + bool all_up = true; + + input_state.pad_buttons &= ~(PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN); + + for (int i = 0; i < MAX_POINTERS; i++) { + if (input_state.pointer_down[i]) { + float dx = (input_state.pointer_x[i] - x_) * inv_stick_size; + float dy = (input_state.pointer_y[i] - y_) * inv_stick_size; + float rad = sqrtf(dx*dx+dy*dy); + if (rad < deadzone || rad > 1.0f) + continue; + + all_up = false; + + if (dx == 0 && dy == 0) + continue; + + int direction = (int)(floorf((atan2f(dy, dx) / (2 * M_PI) * 8) + 0.5f)) & 7; + + switch (direction) { + case 0: input_state.pad_buttons |= PAD_BUTTON_RIGHT; break; + case 1: input_state.pad_buttons |= PAD_BUTTON_RIGHT | PAD_BUTTON_DOWN; break; + case 2: input_state.pad_buttons |= PAD_BUTTON_DOWN; break; + case 3: input_state.pad_buttons |= PAD_BUTTON_DOWN | PAD_BUTTON_LEFT; break; + case 4: input_state.pad_buttons |= PAD_BUTTON_LEFT; break; + case 5: input_state.pad_buttons |= PAD_BUTTON_UP | PAD_BUTTON_LEFT; break; + case 6: input_state.pad_buttons |= PAD_BUTTON_UP; break; + case 7: input_state.pad_buttons |= PAD_BUTTON_UP | PAD_BUTTON_RIGHT; break; + } + } + } + down_ = input_state.pad_buttons & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN); +} + +void TouchCrossPad::draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay) +{ + static const float xoff[4] = {1, 0, -1, 0}; + static const float yoff[4] = {0, 1, 0, -1}; + static const int dir[4] = {PAD_BUTTON_RIGHT, PAD_BUTTON_DOWN, PAD_BUTTON_LEFT, PAD_BUTTON_UP}; + for (int i = 0; i < 4; i++) { + float x = x_ + xoff[i] * scale_ * radius_; + float y = y_ + yoff[i] * scale_ * radius_; + float angle = i * M_PI / 2; + float imgScale = (down_ & dir[i]) ? scale_ * 2 : scale_; + db.DrawImageRotated(arrowIndex_, x, y, imgScale, angle + PI, color, false); + if (overlayIndex_ != -1) + db.DrawImageRotated(overlayIndex_, x, y, imgScale, angle + PI, colorOverlay); + } +} + TouchStick::TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick) : atlas_(atlas), bgImageIndex_(bgImageIndex), stickImageIndex_(stickImageIndex), stick_(stick) { diff --git a/ui/virtual_input.h b/ui/virtual_input.h index 41796fee89..a383cd467b 100644 --- a/ui/virtual_input.h +++ b/ui/virtual_input.h @@ -1,5 +1,6 @@ #pragma once +#include "math/math_util.h" #include "gfx/texture_atlas.h" class DrawBuffer; @@ -47,6 +48,35 @@ private: bool pointerDown[MAX_POINTERS]; }; +// 4-in-one directional pad, with support for single touch diagonals. +class TouchCrossPad +{ +public: + TouchCrossPad(const Atlas *atlas, int arrowIndex, int overlayIndex); + + void update(InputState &input_state); + void draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay); + + void setPos(float x, float y, float radius, float scale = 1.0f) { + x_ = x; + y_ = y; + radius_ = radius; + scale_ = scale; + } + +private: + const Atlas *atlas_; + + float x_; + float y_; + float radius_; + float scale_; + + int arrowIndex_; + int overlayIndex_; + int down_; +}; + // Multi-touch enabled virtual joystick // Many of these can be used simultaneously with multitouch. From 36a6c179a0f1c8978628babf71a10878b14bc3c0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Mar 2013 19:23:02 +0100 Subject: [PATCH 0300/1445] Some drawing refactoring --- gfx_es2/draw_buffer.cpp | 60 +++++++++++++++++---------------- gfx_es2/draw_buffer.h | 6 ++-- ui/ui.cpp | 75 ++++++++++++++++++++++++++++++++++++++--- ui/ui.h | 23 +++++++------ ui/ui_context.cpp | 52 +++++++++++++--------------- ui/ui_context.h | 4 ++- 6 files changed, 143 insertions(+), 77 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 87273b87d0..1e5a847e65 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -53,8 +53,9 @@ void DrawBuffer::GLLost() { Init(false); } -void DrawBuffer::Begin(DrawBufferMode dbmode) { +void DrawBuffer::Begin(const GLSLProgram *program, DrawBufferMode dbmode) { Init(); + program_ = program; count_ = 0; mode_ = dbmode; } @@ -63,7 +64,8 @@ void DrawBuffer::End() { // Currently does nothing, but call it! } -void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { +void DrawBuffer::Flush(bool set_blend_state) { + glsl_bind(program_); if (count_ == 0) return; #ifdef USE_VBO @@ -74,22 +76,22 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { glstate.blend.enable(); glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - glUniform1i(program->sampler0, 0); - glEnableVertexAttribArray(program->a_position); - glEnableVertexAttribArray(program->a_color); - if (program->a_texcoord0 != -1) - glEnableVertexAttribArray(program->a_texcoord0); + glUniform1i(program_->sampler0, 0); + glEnableVertexAttribArray(program_->a_position); + glEnableVertexAttribArray(program_->a_color); + if (program_->a_texcoord0 != -1) + glEnableVertexAttribArray(program_->a_texcoord0); GL_CHECK(); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, x)); - glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void *)offsetof(Vertex, rgba)); - if (program->a_texcoord0 != -1) - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, u)); + glVertexAttribPointer(program_->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, x)); + glVertexAttribPointer(program_->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void *)offsetof(Vertex, rgba)); + if (program_->a_texcoord0 != -1) + glVertexAttribPointer(program_->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, u)); glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_); GL_CHECK(); - glDisableVertexAttribArray(program->a_position); - glDisableVertexAttribArray(program->a_color); - if (program->a_texcoord0 != -1) - glDisableVertexAttribArray(program->a_texcoord0); + glDisableVertexAttribArray(program_->a_position); + glDisableVertexAttribArray(program_->a_color); + if (program_->a_texcoord0 != -1) + glDisableVertexAttribArray(program_->a_texcoord0); GL_CHECK(); glBindBuffer(GL_ARRAY_BUFFER, 0); #else @@ -98,22 +100,22 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glBindBuffer(GL_ARRAY_BUFFER, 0); - glUniform1i(program->sampler0, 0); - glEnableVertexAttribArray(program->a_position); - glEnableVertexAttribArray(program->a_color); - if (program->a_texcoord0 != -1) - glEnableVertexAttribArray(program->a_texcoord0); + glUniform1i(program_->sampler0, 0); + glEnableVertexAttribArray(program_->a_position); + glEnableVertexAttribArray(program_->a_color); + if (program_->a_texcoord0 != -1) + glEnableVertexAttribArray(program_->a_texcoord0); GL_CHECK(); - glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)&verts_[0].x); - glVertexAttribPointer(program->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void *)&verts_[0].rgba); - if (program->a_texcoord0 != -1) - glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)&verts_[0].u); + glVertexAttribPointer(program_->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)&verts_[0].x); + glVertexAttribPointer(program_->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void *)&verts_[0].rgba); + if (program_->a_texcoord0 != -1) + glVertexAttribPointer(program_->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)&verts_[0].u); glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_); GL_CHECK(); - glDisableVertexAttribArray(program->a_position); - glDisableVertexAttribArray(program->a_color); - if (program->a_texcoord0 != -1) - glDisableVertexAttribArray(program->a_texcoord0); + glDisableVertexAttribArray(program_->a_position); + glDisableVertexAttribArray(program_->a_color); + if (program_->a_texcoord0 != -1) + glDisableVertexAttribArray(program_->a_texcoord0); GL_CHECK(); #endif count_ = 0; @@ -426,7 +428,7 @@ void DrawBuffer::EnableBlend(bool enable) { void DrawBuffer::SetClipRect(float x, float y, float w, float h) { // Sigh, OpenGL is upside down. - glScissor(x, dp_yres - y, w, h); + glstate.scissorRect.set(x, dp_yres - y, w, h); glstate.scissorTest.enable(); } diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 3ba0e7f001..74355542d5 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -47,7 +47,7 @@ public: DrawBuffer(); ~DrawBuffer(); - void Begin(DrawBufferMode mode = DBMODE_NORMAL); + void Begin(const GLSLProgram *program, DrawBufferMode mode = DBMODE_NORMAL); void End(); // TODO: Enforce these. Now Init is autocalled and shutdown not called. @@ -57,7 +57,7 @@ public: int Count() const { return count_; } - void Flush(const GLSLProgram *program, bool set_blend_state=true); + void Flush(bool set_blend_state=true); void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); void hLine(float x1, float y, float x2, uint32 color) { Rect(x1, y, x2 - x1, pixel_in_dps, color); } @@ -134,6 +134,8 @@ private: float u, v; }; + const GLSLProgram *program_; + int vbo_; Vertex *verts_; int count_; diff --git a/ui/ui.cpp b/ui/ui.cpp index 19f3d0ff9a..e8068af967 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -6,6 +6,8 @@ #include #include "ui/ui.h" +#include "ui/ui_context.h" +#include "gfx/texture.h" #include "gfx/texture_atlas.h" #include "gfx_es2/draw_buffer.h" @@ -74,13 +76,19 @@ bool UIRegionHit(int i, int x, int y, int w, int h, int margin) { } } -void UIBegin() { +void UIBegin(const GLSLProgram *shader) { for (int i = 0; i < MAX_POINTERS; i++) uistate.hotitem[i] = 0; - ui_draw2d.Begin(); - ui_draw2d_front.Begin(); + ui_draw2d.Begin(shader); + ui_draw2d_front.Begin(shader); } +void UIFlush() { + ui_draw2d.Flush(); + ui_draw2d_front.Flush(); +} + + void UIEnd() { for (int i = 0; i < MAX_POINTERS; i++) { if (uistate.mousedown[i] == 0) { @@ -96,6 +104,8 @@ void UIEnd() { if (uistate.ui_tick > 0) uistate.ui_tick--; + ui_draw2d.Flush(); + ui_draw2d_front.Flush(); } void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) { @@ -199,7 +209,7 @@ int UIImageButton(int id, const LayoutManager &layout, float w, int image, int b // Button is merely 'hot' } } else { - // button is not hot, but it may be active§ + // button is not hot, but it may be active } // If button is hot and active, but mouse button is not @@ -220,6 +230,61 @@ int UIImageButton(int id, const LayoutManager &layout, float w, int image, int b return clicked; } +int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align) // uses current UI atlas for fetching images. +{ + float x, y; + layout.GetPos(&w, &h, &x, &y); + + if (button_align & ALIGN_HCENTER) x -= w / 2; + if (button_align & ALIGN_VCENTER) y -= h / 2; + if (button_align & ALIGN_RIGHT) x -= w; + if (button_align & ALIGN_BOTTOMRIGHT) y -= h; + + int txOffset = 0; + int clicked = 0; + for (int i = 0; i < MAX_POINTERS; i++) { + // Check whether the button should be hot, use a generous margin for touch ease + if (UIRegionHit(i, x, y, w, h, 8)) { + uistate.hotitem[i] = id; + if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) + uistate.activeitem[i] = id; + } + + if (uistate.hotitem[i] == id) { + if (uistate.activeitem[i] == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown[i] == 0 && + uistate.hotitem[i] == id && + uistate.activeitem[i] == id) { + clicked = 1; + } + } + + // Render button + + ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); + ui_draw2d.Flush(); + + texture->Bind(0); + + ui_draw2d.DrawTexRect(x, y, x+w, y+h, 0, 0, 1, 1, 0xFFFFFFFF); + ui_draw2d.Flush(); + ctx->RebindTexture(); + + uistate.lastwidget = id; + return clicked; +} + int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { const int h = 64; @@ -367,7 +432,7 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { } int itemHeight = adapter->itemHeight(0); - int numItems = adapter->getCount(); + int numItems = (int)adapter->getCount(); // Cap total inertia if (inertiaY > 20) inertiaY = 20; diff --git a/ui/ui.h b/ui/ui.h index e5d9dd55a6..3ffd7cff31 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -16,8 +16,8 @@ // Simple ID generators. Absolutely no guarantee of collision avoidance if you implement // multiple parts of a single screen of UI over multiple files unless you use IMGUI_SRC_ID. #ifdef IMGUI_SRC_ID -#define GEN_ID ((IMGUI_SRC_ID) + (__LINE__)) -#define GEN_ID_LOOP(i) ((IMGUI_SRC_ID) + (__LINE__) + (i) * 13612) +#define GEN_ID (int)((IMGUI_SRC_ID) + (__LINE__)) +#define GEN_ID_LOOP(i) (int)((IMGUI_SRC_ID) + (__LINE__) + (i) * 13612) #else #define GEN_ID (__LINE__) #define GEN_ID_LOOP(i) ((__LINE__) + (i) * 13612) @@ -28,6 +28,8 @@ #include #include +class Texture; +class UIContext; class LayoutManager { public: @@ -79,6 +81,7 @@ private: float spacing_; }; + #ifndef MAX_POINTERS #define MAX_POINTERS 8 #endif @@ -180,7 +183,12 @@ private: bool UIRegionHit(int pointerId, int x, int y, int w, int h, int margin); // Call at start of frame -void UIBegin(); +void UIBegin(const GLSLProgram *shader); + +// Call at end of frame. + +void UIEnd(); +void UIFlush(); void UIUpdateMouse(int i, float x, float y, bool down); @@ -190,6 +198,7 @@ void UIReset(); // Returns 1 if clicked int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align); int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images. +int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align); // uses current UI atlas for fetching images. // Returns 1 if clicked, puts the value in *value (where it also gets the current state). int UICheckBox(int id, int x, int y, const char *text, int align, bool *value); @@ -244,11 +253,3 @@ private: DISALLOW_COPY_AND_ASSIGN(UIList); }; -// Call at end of frame. -// Do this afterwards (or similar): - -// ShaderManager::SetUIProgram(); -// ui_draw2d.Flush(ShaderManager::Program()); -// ui_draw2d_front.Flush(ShaderManager::Program()); - -void UIEnd(); diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index f961713b5a..4296d31c81 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -16,7 +16,7 @@ void UIContext::Begin() if (uitexture_) uitexture_->Bind(0); - UIBegin(); + UIBegin(uishader_); /* if (uidrawbuffer_ && uishader_) uidrawbuffer_->Begin(); @@ -24,6 +24,26 @@ void UIContext::Begin() uidrawbufferTop_->Begin();*/ } +void UIContext::BeginNoTex() +{ + glstate.blend.enable(); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.cullFace.disable(); + glstate.depthTest.disable(); + if (uishader_) + glsl_bind(uishader_); + if (uitexture_) + uitexture_->Bind(0); + + UIBegin(uishadernotex_); + /* + if (uidrawbuffer_ && uishader_) + uidrawbuffer_->Begin(); + if (uidrawbufferTop_ && uishader_) + uidrawbufferTop_->Begin();*/ +} + + void UIContext::RebindTexture() { if (uitexture_) @@ -35,38 +55,12 @@ void UIContext::Flush() if (uidrawbuffer_) { uidrawbuffer_->End(); - if (uishader_) { - glsl_bind(uishader_); - uidrawbuffer_->Flush(uishader_); - } + uidrawbuffer_->Flush(); } if (uidrawbufferTop_) { uidrawbufferTop_->End(); - if (uishader_) { - glsl_bind(uishader_); - uidrawbufferTop_->Flush(uishader_); - } - } -} - -void UIContext::FlushNoTex() -{ - if (uidrawbuffer_) - { - uidrawbuffer_->End(); - if (uishadernotex_) { - glsl_bind(uishadernotex_); - uidrawbuffer_->Flush(uishadernotex_); - } - } - if (uidrawbufferTop_) - { - uidrawbufferTop_->End(); - if (uishadernotex_) { - glsl_bind(uishadernotex_); - uidrawbufferTop_->Flush(uishadernotex_); - } + uidrawbufferTop_->Flush(); } } diff --git a/ui/ui_context.h b/ui/ui_context.h index c756a3a175..e86f9b8814 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -7,6 +7,7 @@ struct GLSLProgram; class Texture; class DrawBuffer; +// Who should own this? Really not sure. class UIContext { public: UIContext() : uishader_(0), uitexture_(0), uidrawbuffer_(0), uidrawbufferTop_(0) {} @@ -20,9 +21,10 @@ public: } void Begin(); + void BeginNoTex(); void Flush(); - void FlushNoTex(); void End(); + void RebindTexture(); private: From 7ec766a980dd9f77c407f482d8b570c43f35461c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Mar 2013 19:23:02 +0100 Subject: [PATCH 0301/1445] Some drawing refactoring --- gfx/texture.cpp | 10 +++++++++- gfx/texture.h | 2 ++ image/png_load.cpp | 4 ++-- image/png_load.h | 2 +- ui/ui.cpp | 6 +++++- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index a5cc819cab..db3af115cb 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -83,7 +83,7 @@ bool Texture::Load(const char *filename) { // Currently here are a bunch of project-specific workarounds. // They shouldn't really hurt anything else very much though. - int len = strlen(filename); + size_t len = strlen(filename); char fn[1024]; strncpy(fn, filename, sizeof(fn)); fn[1023] = 0; @@ -290,3 +290,11 @@ void Texture::Bind(int stage) { glBindTexture(GL_TEXTURE_2D, id_); GL_CHECK(); } + +void Texture::Unbind(int stage) { + GL_CHECK(); + if (stage != -1) + glActiveTexture(GL_TEXTURE0 + stage); + glBindTexture(GL_TEXTURE_2D, 0); + GL_CHECK(); +} diff --git a/gfx/texture.h b/gfx/texture.h index 9e0f1b27b9..a01dec2635 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -34,6 +34,8 @@ public: virtual void GLLost(); std::string filename() const { return filename_; } + static void Unbind(int stage = -1); + private: bool LoadXOR(); // Loads a placeholder texture. diff --git a/image/png_load.cpp b/image/png_load.cpp index 3d264879bc..1b23fd99de 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -36,7 +36,7 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d return 1; } -int pngLoadPtr(const unsigned char *input_ptr, const int input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr, +int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip) { if (flip) { @@ -44,7 +44,7 @@ int pngLoadPtr(const unsigned char *input_ptr, const int input_len, int *pwidth, } int x,y,n; - unsigned char *data = stbi_load_from_memory(input_ptr,input_len, &x, &y, &n, 4); // 4 = force RGBA + unsigned char *data = stbi_load_from_memory(input_ptr,(int)input_len, &x, &y, &n, 4); // 4 = force RGBA if (!data) return 0; diff --git a/image/png_load.h b/image/png_load.h index 0cc7ab42ea..bae14c210e 100644 --- a/image/png_load.h +++ b/image/png_load.h @@ -6,7 +6,7 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip); -int pngLoadPtr(const unsigned char *input_ptr, const int input_len, int *pwidth, +int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip); #endif // _PNG_LOAD_H diff --git a/ui/ui.cpp b/ui/ui.cpp index e8068af967..dbfcdba79d 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -275,7 +275,11 @@ int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); ui_draw2d.Flush(); - texture->Bind(0); + if (texture) { + texture->Bind(0); + } else { + Texture::Unbind(); + } ui_draw2d.DrawTexRect(x, y, x+w, y+h, 0, 0, 1, 1, 0xFFFFFFFF); ui_draw2d.Flush(); From 5bdd4bd6631290d86b82fb99b26aefda6b73c64d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Mar 2013 20:10:01 +0100 Subject: [PATCH 0302/1445] Make generating mips optional for loaded-from-memory PNGs. --- gfx/texture.cpp | 4 ++-- gfx/texture.h | 2 +- ui/ui_context.cpp | 2 +- ui/ui_context.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index db3af115cb..ac60e55a66 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -144,7 +144,7 @@ bool Texture::LoadPNG(const char *filename) { return true; } -bool Texture::LoadPNG(const uint8_t *data, size_t size) { +bool Texture::LoadPNG(const uint8_t *data, size_t size, bool genMips) { unsigned char *image_data; if (1 != pngLoadPtr(data, size, &width_, &height_, &image_data, false)) { return false; @@ -152,7 +152,7 @@ bool Texture::LoadPNG(const uint8_t *data, size_t size) { GL_CHECK(); glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); - SetTextureParameters(ZIM_GEN_MIPS); + SetTextureParameters(genMips ? ZIM_GEN_MIPS : 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); glGenerateMipmap(GL_TEXTURE_2D); diff --git a/gfx/texture.h b/gfx/texture.h index a01dec2635..c48807b3c2 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -23,7 +23,7 @@ public: void Destroy(); // PNG from memory buffer - bool LoadPNG(const uint8_t *data, size_t size); + bool LoadPNG(const uint8_t *data, size_t size, bool genMips = true); bool LoadZIM(const char *filename); bool LoadPNG(const char *filename); diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 4296d31c81..731b105982 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -44,7 +44,7 @@ void UIContext::BeginNoTex() } -void UIContext::RebindTexture() +void UIContext::RebindTexture() const { if (uitexture_) uitexture_->Bind(0); diff --git a/ui/ui_context.h b/ui/ui_context.h index e86f9b8814..ba87378d87 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -25,7 +25,7 @@ public: void Flush(); void End(); - void RebindTexture(); + void RebindTexture() const; private: // TODO: Collect these into a UIContext From 34c4700adb67b405fe7b1f6804cca41d49eb165e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Mar 2013 22:32:56 +0100 Subject: [PATCH 0303/1445] TouchCrossPad - don't break other input --- ui/virtual_input.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index e6735773ff..45faa0ddb2 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -59,8 +59,6 @@ void TouchCrossPad::update(InputState &input_state) const float deadzone = 0.17f; bool all_up = true; - input_state.pad_buttons &= ~(PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN); - for (int i = 0; i < MAX_POINTERS; i++) { if (input_state.pointer_down[i]) { float dx = (input_state.pointer_x[i] - x_) * inv_stick_size; @@ -76,6 +74,7 @@ void TouchCrossPad::update(InputState &input_state) int direction = (int)(floorf((atan2f(dy, dx) / (2 * M_PI) * 8) + 0.5f)) & 7; + input_state.pad_buttons &= ~(PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN); switch (direction) { case 0: input_state.pad_buttons |= PAD_BUTTON_RIGHT; break; case 1: input_state.pad_buttons |= PAD_BUTTON_RIGHT | PAD_BUTTON_DOWN; break; From 7efbd96754d7a1467487993a29f3fd1473edae13 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Mar 2013 23:54:23 +0100 Subject: [PATCH 0304/1445] Android: Don't preserve state of buttons not set through jni between frames. --- android/app-android.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index c2e28313b6..d893aeb6b9 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -54,6 +54,8 @@ static uint32_t pad_buttons_async_clear; static float left_joystick_x_async; static float left_joystick_y_async; +static uint32_t pad_buttons_down; + // Android implementation of callbacks to the Java part of the app void SystemToast(const char *text) { frameCommand = "toast"; @@ -142,6 +144,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init renderer_inited = false; first_lost = true; + pad_buttons_down = 0; pad_buttons_async_set = 0; pad_buttons_async_clear = 0; @@ -250,8 +253,9 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN // TODO: Look into if these locks are a perf loss { lock_guard guard(input_state.lock); - input_state.pad_buttons |= pad_buttons_async_set; - input_state.pad_buttons &= ~pad_buttons_async_clear; + pad_buttons_down |= pad_buttons_async_set; + pad_buttons_down &= ~pad_buttons_async_clear; + input_state.pad_buttons = pad_buttons_down; UpdateInputState(&input_state); } From d7a58a31543230acc2c3850cf2523f1e40bf85ec Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 31 Mar 2013 00:21:19 +0100 Subject: [PATCH 0305/1445] Buttons don't have to clear state when not pressed after sticky fix. --- ui/virtual_input.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index 45faa0ddb2..27b0205fe5 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -24,11 +24,8 @@ void TouchButton::update(InputState &input_state) isDown_ = true; } - if (isDown_) { + if (isDown_) input_state.pad_buttons |= button_; - } else if (oldIsDown && !isDown_) { - input_state.pad_buttons &= ~button_; - } } void TouchButton::draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay) From 73177ff463480f959d55bb228a9a9b967252cb9b Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 31 Mar 2013 15:28:18 +1000 Subject: [PATCH 0306/1445] Allow loading VFS resources from QRC (Qt assets inbuilt in to binary) if they exist --- file/zip_read.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index cb01aa3191..53531521fb 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -5,6 +5,9 @@ #ifdef ANDROID #include #endif +#ifdef USING_QT_UI +#include +#endif #include "base/basictypes.h" #include "base/logging.h" @@ -224,13 +227,25 @@ void VFSShutdown() { } uint8_t *VFSReadFile(const char *filename, size_t *size) { + uint8_t *data; +#ifdef USING_QT_UI + // File should be in the binary + QFile asset(QString(":/assets/") + filename); + if (asset.exists()) + { + *size = asset.size(); + data = (uint8_t*)asset.readAll().data(); + return data; + } + // Otherwise, fallback +#endif int fn_len = strlen(filename); for (int i = 0; i < num_entries; i++) { int prefix_len = strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); - uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); + data = entries[i].reader->ReadAsset(filename + prefix_len, size); if (data) return data; else From 22e648bb1a5e8fe6e427efc906194edbb9ce6ed8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 31 Mar 2013 10:03:05 +0200 Subject: [PATCH 0307/1445] png texture: set clamp mode if no mipmaps requested, and don't actually generate mips... --- gfx/texture.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index ac60e55a66..c214dbaef5 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -150,12 +150,14 @@ bool Texture::LoadPNG(const uint8_t *data, size_t size, bool genMips) { return false; } GL_CHECK(); + // TODO: should check for power of 2 tex size and disallow genMips when not. glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); - SetTextureParameters(genMips ? ZIM_GEN_MIPS : 0); + SetTextureParameters(genMips ? ZIM_GEN_MIPS : ZIM_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); - glGenerateMipmap(GL_TEXTURE_2D); + if (genMips) + glGenerateMipmap(GL_TEXTURE_2D); GL_CHECK(); free(image_data); return true; From 79e14282ecf006caef6fe12d19358952741ad7fc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 31 Mar 2013 11:22:49 +0200 Subject: [PATCH 0308/1445] Allow mapping thumb stick clicks. Make touch controls show the state of real controls. --- input/input_state.h | 3 +++ ui/virtual_input.cpp | 28 +++++++++------------------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/input/input_state.h b/input/input_state.h index 27480e4a0e..6c7191269f 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -26,6 +26,9 @@ enum { PAD_BUTTON_JOY_DOWN = 1<<15, PAD_BUTTON_JOY_LEFT = 1<<16, PAD_BUTTON_JOY_RIGHT = 1<<17, + + PAD_BUTTON_LEFT_THUMB = 1 << 18, // Click left thumb stick on X360 + PAD_BUTTON_RIGHT_THUMB = 1 << 19, // Click right thumb stick on X360 }; #ifndef MAX_POINTERS diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index 27b0205fe5..dbc3924574 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -17,15 +17,16 @@ TouchButton::TouchButton(const Atlas *atlas, int imageIndex, int overlayImageInd void TouchButton::update(InputState &input_state) { - bool oldIsDown = isDown_; - isDown_ = false; + bool down = false; for (int i = 0; i < MAX_POINTERS; i++) { if (input_state.pointer_down[i] && isInside(input_state.pointer_x[i], input_state.pointer_y[i])) - isDown_ = true; + down = true; } - if (isDown_) + if (down) input_state.pad_buttons |= button_; + + isDown_ = (input_state.pad_buttons & button_) != 0; } void TouchButton::draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay) @@ -123,8 +124,7 @@ void TouchStick::update(InputState &input_state) // Ignore outside box if (!dragging_[i] && (fabsf(dx) > 1.4f || fabsf(dy) > 1.4f)) goto skip; - if (!lastPointerDown_[i] && (fabsf(dx) < 1.4f && fabsf(dy) < 1.4f)) - { + if (!lastPointerDown_[i] && (fabsf(dx) < 1.4f && fabsf(dy) < 1.4f)) { dragging_[i] = true; } if (!dragging_[i]) @@ -136,8 +136,6 @@ void TouchStick::update(InputState &input_state) dx /= len; dy /= len; } - stick_delta_x_ = dx; - stick_delta_y_ = dy; if (stick_ == 0) { input_state.pad_lstick_x = dx; input_state.pad_lstick_y = -dy; @@ -151,17 +149,9 @@ void TouchStick::update(InputState &input_state) skip: lastPointerDown_[i] = input_state.pointer_down[i]; } - if (all_up) { - stick_delta_x_ = 0.0f; - stick_delta_y_ = 0.0f; - if (stick_ == 0) { - input_state.pad_lstick_x = 0.0f; - input_state.pad_lstick_y = 0.0f; - } else if (stick_ == 1) { - input_state.pad_rstick_x = 0.0f; - input_state.pad_rstick_y = 0.0f; - } - } + + stick_delta_x_ = input_state.pad_lstick_x; + stick_delta_y_ = -input_state.pad_lstick_y; } void TouchStick::draw(DrawBuffer &db, uint32_t color) From 4b0631ccc5210f95d3c70a4d9f130750cf868049 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 1 Apr 2013 12:32:19 +0200 Subject: [PATCH 0309/1445] Add accessors for texture width/height --- gfx/texture.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx/texture.h b/gfx/texture.h index c48807b3c2..7861c52c30 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -36,6 +36,9 @@ public: static void Unbind(int stage = -1); + int Width() const { return width_; } + int Height() const { return height_; } + private: bool LoadXOR(); // Loads a placeholder texture. From 00307429ebc954cf248cc940ed87d04b4eab5ea0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 1 Apr 2013 22:42:40 +1000 Subject: [PATCH 0310/1445] Add input state to Qt, as required --- base/QtMain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 907aed1309..153236dea0 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -16,6 +16,8 @@ #endif #include "QtMain.h" +InputState* input_state; + void LaunchBrowser(const char *url) { QDesktopServices::openUrl(QUrl(url)); From 2b32a7115eb09b90593943481130d5d748e51040 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 4 Apr 2013 11:36:10 +1000 Subject: [PATCH 0311/1445] Fix resource loading for Qt --- file/zip_read.cpp | 17 +---------------- image/zim_load.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 53531521fb..cb01aa3191 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -5,9 +5,6 @@ #ifdef ANDROID #include #endif -#ifdef USING_QT_UI -#include -#endif #include "base/basictypes.h" #include "base/logging.h" @@ -227,25 +224,13 @@ void VFSShutdown() { } uint8_t *VFSReadFile(const char *filename, size_t *size) { - uint8_t *data; -#ifdef USING_QT_UI - // File should be in the binary - QFile asset(QString(":/assets/") + filename); - if (asset.exists()) - { - *size = asset.size(); - data = (uint8_t*)asset.readAll().data(); - return data; - } - // Otherwise, fallback -#endif int fn_len = strlen(filename); for (int i = 0; i < num_entries; i++) { int prefix_len = strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); - data = entries[i].reader->ReadAsset(filename + prefix_len, size); + uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); if (data) return data; else diff --git a/image/zim_load.cpp b/image/zim_load.cpp index 16162e4a9f..6e80bc72de 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -2,6 +2,10 @@ #include #include +#ifdef USING_QT_UI +#include +#endif + #include "base/logging.h" #include "zlib.h" #include "image/zim_load.h" @@ -131,6 +135,14 @@ int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, } int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t **image) { +#ifdef USING_QT_UI + QFile asset(QString(":/assets/") + filename); + if (!asset.open(QIODevice::ReadOnly)) + return 0; + int retval = LoadZIMPtr((uint8_t*)asset.readAll().data(), asset.size(), width, height, format, image); + size = asset.size(); + asset.close(); +#else size_t size; uint8_t *buffer = VFSReadFile(filename, &size); if (!buffer) { @@ -141,5 +153,6 @@ int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t ELOG("Not a valid ZIM file: %s", filename); } delete [] buffer; +#endif return retval; } From 8e06b06d7efb3299d8c6139651d99616273d6aa7 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 4 Apr 2013 17:29:09 +1000 Subject: [PATCH 0312/1445] Build fix for Qt --- image/zim_load.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/image/zim_load.cpp b/image/zim_load.cpp index 6e80bc72de..7b5bf3e859 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -140,7 +140,6 @@ int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t if (!asset.open(QIODevice::ReadOnly)) return 0; int retval = LoadZIMPtr((uint8_t*)asset.readAll().data(), asset.size(), width, height, format, image); - size = asset.size(); asset.close(); #else size_t size; From 110e88e2579c3431d0c9e3df6459ab05f057148d Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 7 Apr 2013 00:34:46 +1000 Subject: [PATCH 0313/1445] Fix stuck keys on Qt and Blackberry --- base/BlackberryMain.cpp | 10 +++++++--- base/PCMain.cpp | 4 +++- base/QtMain.cpp | 7 +++---- base/QtMain.h | 12 ++++++++---- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 850ddab926..ceac9524f1 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -388,6 +388,7 @@ int main(int argc, char *argv[]) { #ifdef BLACKBERRY10 vibration_request_events(0); #endif + static int pad_buttons = 0; BlackberryAudio* audio = new BlackberryAudio(); bool running = true; while (running) { @@ -444,13 +445,13 @@ int main(int argc, char *argv[]) { if (flags & (KEY_DOWN | KEY_SYM_VALID)) { for (int b = 0; b < 14; b++) { if (value == buttonMappings[b]) - input_state.pad_buttons |= (1< #include @@ -41,7 +41,7 @@ void SimulateGamepad(InputState *input) { float CalculateDPIScale() { - // Sane default for Symbian, Blackberry and Meego + // Sane default rather than check DPI #ifdef __SYMBIAN32__ return 1.4f; #else @@ -79,7 +79,6 @@ int main(int argc, char *argv[]) #ifndef Q_WS_X11 MainUI w(dpi_scale); - w.setAttribute(Qt::WA_LockLandscapeOrientation); w.resize(pixel_xres, pixel_yres); w.showFullScreen(); #endif diff --git a/base/QtMain.h b/base/QtMain.h index 34881a0876..fc298504c4 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -54,6 +54,8 @@ public: QGLWidget(parent), dpi_scale(scale) { setAttribute(Qt::WA_AcceptTouchEvents); + setAttribute(Qt::WA_LockLandscapeOrientation); + pad_buttons = 0; #ifdef __SYMBIAN32__ acc = new QAccelerometer(this); acc->start(); @@ -108,15 +110,15 @@ protected: input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * dpi_scale; break; case QEvent::KeyPress: - for (int b = 0; b < 14; b++) { + for (int b = 0; b < 18; b++) { if (((QKeyEvent*)e)->key() == buttonMappings[b]) - input_state.pad_buttons |= (1<key() == buttonMappings[b]) - input_state.pad_buttons &= ~(1< Date: Sun, 7 Apr 2013 00:52:09 +1000 Subject: [PATCH 0314/1445] Support accelerometer in Qt for all mobile platforms. --- base/QtMain.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index fc298504c4..9c4d27c545 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -8,7 +8,7 @@ #include #include -#ifdef __SYMBIAN32__ +#ifdef USING_GLES2 #include QTM_USE_NAMESPACE #endif @@ -56,13 +56,13 @@ public: setAttribute(Qt::WA_AcceptTouchEvents); setAttribute(Qt::WA_LockLandscapeOrientation); pad_buttons = 0; -#ifdef __SYMBIAN32__ +#ifdef USING_GLES2 acc = new QAccelerometer(this); acc->start(); #endif } ~MainUI() { -#ifdef __SYMBIAN32__ +#ifdef USING_GLES2 delete acc; #endif NativeShutdownGraphics(); @@ -151,7 +151,7 @@ protected: void updateAccelerometer() { -#ifdef __SYMBIAN32__ +#ifdef USING_GLES2 // TODO: Toggle it depending on whether it is enabled QAccelerometerReading *reading = acc->reading(); if (reading) { @@ -165,7 +165,7 @@ protected: private: int pad_buttons; InputState input_state; -#ifdef __SYMBIAN32__ +#ifdef USING_GLES2 QAccelerometer* acc; #endif float dpi_scale; From f45b5d6094d38f8ae21935c2ebff3cf269950be8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Apr 2013 17:46:59 -0700 Subject: [PATCH 0315/1445] Add a simple grid-based layout manager. --- ui/ui.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/ui/ui.h b/ui/ui.h index 3ffd7cff31..be67e693fc 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -81,6 +81,52 @@ private: float spacing_; }; +class HGrid : public LayoutManager { +public: + HGrid(float x, float y, float xMax, float xSpacing = 2.0f, float ySpacing = 2.0f) + : x_(x), y_(y), xInit_(x), xMax_(xMax), xSpacing_(xSpacing), ySpacing_(ySpacing) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + x_ += *w + xSpacing_; + if (x_ >= xMax_) { + x_ = xInit_; + y_ += *h + ySpacing_; + } + } + +private: + mutable float x_; + mutable float y_; + float xInit_; + float xMax_; + float xSpacing_; + float ySpacing_; +}; + +class VGrid : public LayoutManager { +public: + VGrid(float x, float y, float yMax, float xSpacing = 2.0f, float ySpacing = 2.0f) + : x_(x), y_(y), yInit_(y), yMax_(yMax), xSpacing_(xSpacing), ySpacing_(ySpacing) {} + virtual void GetPos(float *w, float *h, float *x, float *y) const { + *x = x_; + *y = y_; + y_ += *h + ySpacing_; + if (y_ >= yMax_) { + x_ += *w + xSpacing_; + y_ = yInit_; + } + } + +private: + mutable float x_; + mutable float y_; + float yInit_; + float yMax_; + float xSpacing_; + float ySpacing_; +}; + #ifndef MAX_POINTERS #define MAX_POINTERS 8 From 75dfa1206ed5c84c04af758e8465be2574e72b2c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Apr 2013 18:05:09 -0700 Subject: [PATCH 0316/1445] Don't stretch the image in UITextureButton(). --- ui/ui.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index dbfcdba79d..04b32fff83 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -272,12 +272,21 @@ int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w // Render button - ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); - ui_draw2d.Flush(); - if (texture) { texture->Bind(0); + + float tw = texture->Width(); + float th = texture->Height(); + + // Adjust position so we don't stretch the image vertically or horizontally. + // TODO: Add a param to specify fit? The below assumes it's never too wide. + float nw = h * tw / th; + x += (w - nw) / 2.0f; + w = nw; } else { + ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); + ui_draw2d.Flush(); + Texture::Unbind(); } From 8e0e4bf1d12b1aecc6f6462984d5874efc5eded9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Apr 2013 20:22:29 -0700 Subject: [PATCH 0317/1445] Uninvert bumpers, fixes hrydgard/ppsspp#1096. --- base/BlackberryMain.cpp | 4 ++-- base/PCMain.cpp | 4 ++-- base/QtMain.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index ceac9524f1..e984996f2a 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -102,8 +102,8 @@ const int buttonMappings[18] = { KEYCODE_S, //B KEYCODE_Z, //X KEYCODE_A, //Y - KEYCODE_W, //LBUMPER - KEYCODE_Q, //RBUMPER + KEYCODE_Q, //LBUMPER + KEYCODE_W, //RBUMPER KEYCODE_ONE, //START KEYCODE_TWO, //SELECT KEYCODE_UP, //UP diff --git a/base/PCMain.cpp b/base/PCMain.cpp index ae3162cc4b..803b24f242 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -241,8 +241,8 @@ const int buttonMappings[14] = { SDLK_x, //B SDLK_a, //X SDLK_s, //Y - SDLK_w, //LBUMPER - SDLK_q, //RBUMPER + SDLK_q, //LBUMPER + SDLK_w, //RBUMPER SDLK_SPACE, //START SDLK_v, //SELECT #endif diff --git a/base/QtMain.h b/base/QtMain.h index 9c4d27c545..73eda8676b 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -28,8 +28,8 @@ const int buttonMappings[18] = { Qt::Key_S + 0x20, //B Qt::Key_Z + 0x20, //X Qt::Key_A + 0x20, //Y - Qt::Key_W + 0x20, //LBUMPER - Qt::Key_Q + 0x20, //RBUMPER + Qt::Key_Q + 0x20, //LBUMPER + Qt::Key_W + 0x20, //RBUMPER Qt::Key_1, //START Qt::Key_2, //SELECT Qt::Key_Up, //UP From f71f3183b2149a59660a05b2aed8e25d2d278ceb Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 7 Apr 2013 22:56:09 +0200 Subject: [PATCH 0318/1445] Enforce the drawbuffer overflow check in release too. --- gfx_es2/draw_buffer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 1e5a847e65..117a0c762c 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -122,12 +122,10 @@ void DrawBuffer::Flush(bool set_blend_state) { } void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) { -#ifdef _DEBUG if (count_ >= MAX_VERTS) { FLOG("Overflowed the DrawBuffer"); return; } -#endif Vertex *vert = &verts_[count_++]; vert->x = x; From c0963ec11fd57f2bd3d389464b3e1455bbc5a6a4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 7 Apr 2013 23:30:25 +0200 Subject: [PATCH 0319/1445] Increase drawbuffer size, fix potential utf8 issue --- gfx_es2/draw_buffer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 117a0c762c..28c3b56d83 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -17,7 +17,7 @@ enum { // Enough? - MAX_VERTS = 15000, + MAX_VERTS = 65536, }; // #define USE_VBO @@ -366,7 +366,7 @@ void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) { // ROTATE_* doesn't yet work right. void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int flags) { const AtlasFont &atlasfont = *atlas->fonts[font]; - unsigned char cval; + unsigned int cval; float w, h; MeasureText(font, text, &w, &h); if (flags) { From 9c96dcea91f6d4237e878c9d1b004e3e1e9678d7 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 11 Apr 2013 15:12:48 +1000 Subject: [PATCH 0320/1445] Blackberry: If PPSSPP dir doesn't exist yet, a lot of things break. Let's just use documents dir. --- base/BlackberryMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index e984996f2a..af99394468 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -380,7 +380,7 @@ int main(int argc, char *argv[]) { float dpi_scale = 213.6f / dpi; dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); - NativeInit(argc, (const char **)argv, "/accounts/1000/shared/documents/PPSSPP/", "data/", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, "/accounts/1000/shared/documents/", "data/", "BADCOFFEE"); NativeInitGraphics(); screen_request_events(screen_cxt); navigator_request_events(0); From bd7bee5a11cd01ebf9f2e8445db7fedab7e3b295 Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 12 Apr 2013 00:21:35 +1000 Subject: [PATCH 0321/1445] Blackberry tablets have reversed accelerometer values (y = x) due to their landscape affinity. The only Blackberry tablet is also the only device with 1024 pixel width, so check for this as it is easier than looking up machine ID. --- base/BlackberryMain.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index af99394468..ee15770c9e 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -473,7 +473,15 @@ int main(int argc, char *argv[]) { // Handle accelerometer double x, y, z; accelerometer_read_forces(&x, &y, &z); - input_state.acc.x = x; input_state.acc.y = y; input_state.acc.z = z; + if (pixel_xres == 1024) // Playbook has this reversed + { + input_state.acc.x = y; + input_state.acc.y = x; + } else { + input_state.acc.x = x; + input_state.acc.y = y; + } + input_state.acc.z = z; UpdateInputState(&input_state); NativeUpdate(input_state); EndInputState(&input_state); From 5626d01e14eecd1fbd837cd8e1c6a5b9a2efc650 Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 12 Apr 2013 02:50:14 +1000 Subject: [PATCH 0322/1445] More Harmattan/N9 support. --- base/QtMain.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 6ac7bccc8e..ad63d10843 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -72,12 +72,14 @@ int main(int argc, char *argv[]) char* savegame_dir = "E:/PPSSPP/"; #elif defined(BLACKBERRY) char* savegame_dir = "data/"; +#elif defined(MEEGO_EDITION_HARMATTAN) + char* savegame_dir = "/home/user/MyDocs/PPSSPP/"; #else char* savegame_dir = "./"; #endif NativeInit(argc, (const char **)argv, savegame_dir, QDir::tempPath().toStdString().c_str(), "BADCOFFEE"); -#ifndef Q_WS_X11 +#if !defined(Q_WS_X11) || defined(ARM) MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); w.showFullScreen(); From 8f8f65c45dc42ac2cd2fc7580082e5ffbfa2ae4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 13 Apr 2013 15:01:09 +0200 Subject: [PATCH 0323/1445] Add height parameter to UIButton --- ui/ui.cpp | 10 +++++++--- ui/ui.h | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index 04b32fff83..f894eb97e1 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -129,8 +129,9 @@ void UIText(int font, const LayoutManager &layout, const char *text, uint32_t co ui_draw2d.SetFontScale(1.0f, 1.0f); } -int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align) { - float h = themeAtlas->images[theme.buttonImage].h; +int UIButton(int id, const LayoutManager &layout, float w, float h, const char *text, int button_align) { + if (h == 0.0f) + h = themeAtlas->images[theme.buttonImage].h; float x, y; layout.GetPos(&w, &h, &x, &y); @@ -174,7 +175,10 @@ int UIButton(int id, const LayoutManager &layout, float w, const char *text, int // Render button - ui_draw2d.DrawImage2GridH((txOffset && theme.buttonSelected) ? theme.buttonSelected : theme.buttonImage, x, y, x + w); + if (h == themeAtlas->images[theme.buttonImage].h) + ui_draw2d.DrawImage2GridH((txOffset && theme.buttonSelected) ? theme.buttonSelected : theme.buttonImage, x, y, x + w); + else + ui_draw2d.DrawImage4Grid((txOffset && theme.buttonSelected) ? theme.buttonSelected : theme.buttonImage, x, y, x + w, y + h); ui_draw2d.DrawTextShadow(theme.uiFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); uistate.lastwidget = id; diff --git a/ui/ui.h b/ui/ui.h index be67e693fc..237d57fed3 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -242,7 +242,7 @@ void UIUpdateMouse(int i, float x, float y, bool down); void UIReset(); // Returns 1 if clicked -int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align); +int UIButton(int id, const LayoutManager &layout, float w, float h, const char *text, int button_align); int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images. int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align); // uses current UI atlas for fetching images. From bff1115f0ccd861ee016e5d4027c25af8bffb5c2 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 14 Apr 2013 03:00:43 +1000 Subject: [PATCH 0324/1445] Support Qt 'app boosters'. A technique where Qt apps are treated as shared objects and loaded in to an existing Qt app shell. This is used on Harmattan and Blackberry10. --- base/QtMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index ad63d10843..48ebffb525 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -49,7 +49,7 @@ float CalculateDPIScale() #endif } -int main(int argc, char *argv[]) +Q_DECL_EXPORT int main(int argc, char *argv[]) { #ifdef Q_WS_X11 QApplication::setAttribute(Qt::AA_X11InitThreads, true); From 25711066df80e789515c65ef05b05d1290e2191a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 13 Apr 2013 21:22:03 +0200 Subject: [PATCH 0325/1445] Add prioritizedworkqueue, thread stuff, ui tweaks, small optimizations in file util --- Android.mk | 4 +- base/basictypes.h | 5 +- base/mutex.h | 88 ++++++++- file/file_util.cpp | 13 +- gfx/gl_lost_manager.cpp | 3 +- gfx/gl_lost_manager.h | 2 +- math/curves.cpp | 2 + native.vcxproj | 7 +- native.vcxproj.filters | 24 ++- thread/prioritizedworkqueue.cpp | 82 +++++++++ thread/prioritizedworkqueue.h | 51 ++++++ thread/thread.h | 310 ++++++++++++++++++++++++++++++++ {base => thread}/threadutil.cpp | 2 +- {base => thread}/threadutil.h | 18 ++ ui/screen.cpp | 3 - ui/screen.h | 5 +- ui/ui.cpp | 4 +- ui/ui.h | 4 +- 18 files changed, 587 insertions(+), 40 deletions(-) create mode 100644 thread/prioritizedworkqueue.cpp create mode 100644 thread/prioritizedworkqueue.h create mode 100644 thread/thread.h rename {base => thread}/threadutil.cpp (95%) rename {base => thread}/threadutil.h (64%) diff --git a/Android.mk b/Android.mk index e20ce9c897..29a7993e5c 100644 --- a/Android.mk +++ b/Android.mk @@ -41,6 +41,8 @@ LOCAL_SRC_FILES :=\ net/http_client.cpp \ net/resolve.cpp \ profiler/profiler.cpp \ + thread/threadutil.cpp \ + thread/prioritizedworkqueue.cpp \ gfx_es2/glsl_program.cpp \ gfx_es2/gl_state.cpp \ gfx_es2/draw_buffer.cpp.arm \ @@ -62,7 +64,7 @@ LOCAL_SRC_FILES :=\ util/text/utf8.cpp LOCAL_CFLAGS := -O3 -DGL_GLEXT_PROTOTYPES -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x +LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip diff --git a/base/basictypes.h b/base/basictypes.h index fea1874486..32efa91cdd 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -1,5 +1,4 @@ -#ifndef _BASE_BASICTYPES -#define _BASE_BASICTYPES +#pragma once #include #include // for byte swapping @@ -92,5 +91,3 @@ inline uint64 swap64(const uint8* _pData) {return swap64(*(const uint64*)_pData) #ifndef TCHAR typedef char TCHAR; #endif - -#endif // _BASE_BASICTYPES diff --git a/base/mutex.h b/base/mutex.h index cae54dae77..ebd73df85b 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -1,19 +1,20 @@ #pragma once + // Simple cross platform mutex implementation. // Similar to the new C++11 api. + // Windows and pthreads implementations in one. +// TODO: Need to clean up these primitives and put them in a reasonable namespace. + #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN +#define NOMINMAX #include // Zap stupid windows defines // Should move these somewhere clever. #undef p -#undef MIN -#undef MAX -#undef min -#undef max #undef DrawText #undef itoa @@ -125,10 +126,11 @@ public: void wait(recursive_mutex &mtx) { // broken #ifdef _WIN32 - //mtx.unlock(); + // This has to be horribly racy. + mtx.unlock(); WaitForSingleObject(event_, INFINITE); ResetEvent(event_); // necessary? - // mtx.lock(); + mtx.lock(); #else pthread_mutex_lock(&mtx.native_handle()); pthread_cond_wait(&event_, &mtx.native_handle()); @@ -167,3 +169,77 @@ private: pthread_cond_t event_; #endif }; + + +class condition_variable { +public: +#ifdef _WIN32 +#else +#endif + condition_variable() { +#ifdef _WIN32 + event_ = CreateEvent(0, FALSE, FALSE, 0); +#else + pthread_cond_init(&event_, NULL); +#endif + } + ~condition_variable() { +#ifdef _WIN32 + CloseHandle(event_); +#else + pthread_cond_destroy(&event_); +#endif + } + + void notify_one() { +#ifdef _WIN32 + SetEvent(event_); +#else + pthread_cond_signal(&event_); +#endif + } + + // notify_all is not really possible to implement with win32 events? + + void wait(recursive_mutex &mtx) { + // broken +#ifdef _WIN32 + // This has to be horribly racy. + mtx.unlock(); + WaitForSingleObject(event_, INFINITE); + ResetEvent(event_); // necessary? + mtx.lock(); +#else + pthread_cond_wait(&event_, &mtx.native_handle()); +#endif + } + + void wait_for(recursive_mutex &mtx, int milliseconds) { +#ifdef _WIN32 + //mtx.unlock(); + WaitForSingleObject(event_, milliseconds); + ResetEvent(event_); // necessary? + // mtx.lock(); +#else + timespec timeout; +#ifdef __APPLE__ + timeval tv; + gettimeofday(&tv, NULL); + timeout.tv_sec = tv.tv_sec; + timeout.tv_nsec = tv.tv_usec * 1000; +#else + clock_gettime(CLOCK_REALTIME, &timeout); +#endif + timeout.tv_sec += milliseconds / 1000; + timeout.tv_nsec += milliseconds * 1000000; + pthread_cond_timedwait(&event_, &mtx.native_handle(), &timeout); +#endif + } + +private: +#ifdef _WIN32 + HANDLE event_; +#else + pthread_cond_t event_; +#endif +}; diff --git a/file/file_util.cpp b/file/file_util.cpp index 25ad3eb741..fbaf027260 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -168,15 +168,12 @@ bool getFileInfo(const char *path, FileInfo *fileInfo) #ifdef _WIN32 fileInfo->size = 0; - FILE *f = fopen(path, "rb"); - if (f) { - fseek(f, 0, SEEK_END); - fileInfo->size = ftell(f); - fclose(f); + WIN32_FILE_ATTRIBUTE_DATA attrs; + if (GetFileAttributesExA(path, GetFileExInfoStandard, &attrs)) { + fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32); } - DWORD attributes = GetFileAttributes(path); - fileInfo->isDirectory = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - fileInfo->isWritable = (attributes & FILE_ATTRIBUTE_READONLY) == 0; + fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0; #else struct stat64 file_info; diff --git a/gfx/gl_lost_manager.cpp b/gfx/gl_lost_manager.cpp index 92d273706b..50a87449c2 100644 --- a/gfx/gl_lost_manager.cpp +++ b/gfx/gl_lost_manager.cpp @@ -1,12 +1,11 @@ #include +#include "base/basictypes.h" #include "base/logging.h" #include "gfx/gl_lost_manager.h" std::vector *holders; -GfxResourceHolder::~GfxResourceHolder() {} - static bool inLost; void register_gl_resource_holder(GfxResourceHolder *holder) { diff --git a/gfx/gl_lost_manager.h b/gfx/gl_lost_manager.h index 699d17075f..a8fb0249b3 100644 --- a/gfx/gl_lost_manager.h +++ b/gfx/gl_lost_manager.h @@ -5,7 +5,7 @@ class GfxResourceHolder { public: - virtual ~GfxResourceHolder(); + virtual ~GfxResourceHolder() {} virtual void GLLost() = 0; }; diff --git a/math/curves.cpp b/math/curves.cpp index 00c6303a50..be737cab29 100644 --- a/math/curves.cpp +++ b/math/curves.cpp @@ -33,6 +33,8 @@ float linearOut(int t, int fadeOutLength) { } float ease(float val) { + if (val > 1.0f) return 1.0f; + if (val < 0.0f) return 0.0f; return ((-cosf(val * PI)) + 1.0f) * 0.5; } diff --git a/native.vcxproj b/native.vcxproj index c54dbfeabf..b9aa090825 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -196,7 +196,6 @@ - @@ -242,6 +241,9 @@ + + + @@ -290,7 +292,6 @@ true - @@ -331,6 +332,8 @@ + + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 9baa377be3..3b902f1bd9 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -206,9 +206,6 @@ util - - base - ext @@ -239,6 +236,15 @@ ext + + thread + + + thread + + + thread + @@ -388,9 +394,6 @@ util - - base - ext @@ -423,6 +426,12 @@ ext + + thread + + + thread + @@ -482,5 +491,8 @@ {4515306f-4664-46bf-a89b-abfec5520a15} + + {caa41117-1d90-47cc-9fba-f7e670e315a3} + \ No newline at end of file diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp new file mode 100644 index 0000000000..2866d3d8c8 --- /dev/null +++ b/thread/prioritizedworkqueue.cpp @@ -0,0 +1,82 @@ +#include + +#include "base/logging.h" +#include "thread/thread.h" +#include "thread/prioritizedworkqueue.h" + +#if defined(IOS) || (defined(__APPLE__) && !defined(__MAC_10_7)) +namespace std { + using tr1::bind; +} +#endif + +PrioritizedWorkQueue::~PrioritizedWorkQueue() { + if (!done_) { + ELOG("PrioritizedWorkQueue destroyed but not done!"); + } +} + +void PrioritizedWorkQueue::Add(PrioritizedWorkQueueItem *item) { + mutex_.lock(); + queue_.push_back(item); + mutex_.unlock(); + notEmpty_.notify_one(); +} + +void PrioritizedWorkQueue::Stop() { + mutex_.lock(); + done_ = true; + notEmpty_.notify_one(); + mutex_.unlock(); +} + +// The worker should simply call this in a loop. Will block when appropriate. +PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { + mutex_.lock(); + while (queue_.empty()) { + notEmpty_.wait(mutex_); + if (done_) + return 0; + } + + // Find the top priority item (lowest value). + float best_prio = std::numeric_limits::infinity(); + std::vector::iterator best = queue_.end(); + for (auto iter = queue_.begin(); iter != queue_.end(); ++iter) { + if ((*iter)->priority() < best_prio) { + best = iter; + best_prio = (*iter)->priority(); + } + } + PrioritizedWorkQueueItem *poppedItem = *best; + queue_.erase(best); + mutex_.unlock(); + return poppedItem; +} + +// TODO: This feels ugly. Revisit later. + +static std::thread *workThread; + +static void threadfunc(PrioritizedWorkQueue *wq) { + while (true) { + PrioritizedWorkQueueItem *item = wq->Pop(); + if (!item) { + if (wq->Done()) + break; + } else { + item->run(); + } + } +} + +void ProcessWorkQueueOnThreadWhile(PrioritizedWorkQueue *wq) { + workThread = new std::thread(std::bind(&threadfunc, wq)); +} + +void StopProcessingWorkQueue(PrioritizedWorkQueue *wq) { + wq->Stop(); + workThread->join(); + delete workThread; + workThread = 0; +} \ No newline at end of file diff --git a/thread/prioritizedworkqueue.h b/thread/prioritizedworkqueue.h new file mode 100644 index 0000000000..e3e815d7a3 --- /dev/null +++ b/thread/prioritizedworkqueue.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +#include "base/basictypes.h" +#include "base/mutex.h" +#include "thread/threadutil.h" + +// Priorities can change dynamically. +// Try to make priority() fast, it will be called a lot. + +class PrioritizedWorkQueueItem { +public: + PrioritizedWorkQueueItem() {} + virtual ~PrioritizedWorkQueueItem() {} + virtual void run() = 0; + virtual float priority() = 0; // Low priority value = high priority! + +private: + DISALLOW_COPY_AND_ASSIGN(PrioritizedWorkQueueItem); +}; + +class PrioritizedWorkQueue { +public: + PrioritizedWorkQueue() : done_(false) {} + ~PrioritizedWorkQueue(); + // Takes ownership. + void Add(PrioritizedWorkQueueItem *item); + + // The worker should simply call this in a loop. Will block when appropriate. + PrioritizedWorkQueueItem *Pop(); + + bool Done() { return done_; } + void Stop(); + +private: + bool done_; + recursive_mutex mutex_; + condition_variable notEmpty_; + + std::vector queue_; + + DISALLOW_COPY_AND_ASSIGN(PrioritizedWorkQueue); +}; + + +// Starts up a thread that keeps trying to run this workqueue. +// TODO: This feels ugly. Revisit later. +void ProcessWorkQueueOnThreadWhile(PrioritizedWorkQueue *wq); +void StopProcessingWorkQueue(PrioritizedWorkQueue *wq); \ No newline at end of file diff --git a/thread/thread.h b/thread/thread.h new file mode 100644 index 0000000000..f32a96be92 --- /dev/null +++ b/thread/thread.h @@ -0,0 +1,310 @@ + +#ifndef STD_THREAD_H_ +#define STD_THREAD_H_ + +#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) +#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) + +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !defined(ANDROID) && !defined(__SYMBIAN32__) +// GCC 4.4 provides +#ifndef _GLIBCXX_USE_SCHED_YIELD +#define _GLIBCXX_USE_SCHED_YIELD +#endif +#include +#else + +// partial std::thread implementation for win32/pthread + +#include + +#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__) +#define USE_RVALUE_REFERENCES +#endif + +//#ifdef __APPLE__ +//#import +//#endif + +#if defined(_WIN32) +// WIN32 + +#define WIN32_LEAN_AND_MEAN +#include + +#if defined(_MSC_VER) && defined(_MT) +// When linking with LIBCMT (the multithreaded C library), Microsoft recommends +// using _beginthreadex instead of CreateThread. +#define USE_BEGINTHREADEX +#include +#endif + +#ifdef USE_BEGINTHREADEX +#define THREAD_ID unsigned +#define THREAD_RETURN unsigned __stdcall +#else +#define THREAD_ID DWORD +#define THREAD_RETURN DWORD WINAPI +#endif +#define THREAD_HANDLE HANDLE + +#else +// PTHREAD + +#include + +#ifndef _POSIX_THREADS +#error unsupported platform (no pthreads?) +#endif + +#include + +#define THREAD_ID pthread_t +#define THREAD_HANDLE pthread_t +#define THREAD_RETURN void* + +#endif + +namespace std +{ + +class thread +{ +public: + typedef THREAD_HANDLE native_handle_type; + + class id + { + friend class thread; + public: + id() : m_thread(0) {} + id(THREAD_ID _id) : m_thread(_id) {} + + bool operator==(const id& rhs) const + { + return m_thread == rhs.m_thread; + } + + bool operator!=(const id& rhs) const + { + return !(*this == rhs); + } + + bool operator<(const id& rhs) const + { + return m_thread < rhs.m_thread; + } + + private: + THREAD_ID m_thread; + }; + + // no variadic template support in msvc + //template + //thread(C&& func, A&&... args); + + template + thread(C func) + { + StartThread(new Func(func)); + } + + template + thread(C func, A arg) + { + StartThread(new FuncArg(func, arg)); + } + + thread() /*= default;*/ {} + +#ifdef USE_RVALUE_REFERENCES + thread(const thread&) /*= delete*/; + + thread(thread&& other) + { +#else + thread(const thread& t) + { + // ugly const_cast to get around lack of rvalue references + thread& other = const_cast(t); +#endif + swap(other); + } + +#ifdef USE_RVALUE_REFERENCES + thread& operator=(const thread&) /*= delete*/; + + thread& operator=(thread&& other) + { +#else + thread& operator=(const thread& t) + { + // ugly const_cast to get around lack of rvalue references + thread& other = const_cast(t); +#endif + if (joinable()) + detach(); + swap(other); + return *this; + } + + ~thread() + { + if (joinable()) + detach(); + } + + bool joinable() const + { + return m_id != id(); + } + + id get_id() const + { + return m_id; + } + + native_handle_type native_handle() + { +#ifdef _WIN32 + return m_handle; +#else + return m_id.m_thread; +#endif + } + + void join() + { +#ifdef _WIN32 + WaitForSingleObject(m_handle, INFINITE); + detach(); +#else + pthread_join(m_id.m_thread, NULL); + m_id = id(); +#endif + } + + void detach() + { +#ifdef _WIN32 + CloseHandle(m_handle); +#else + pthread_detach(m_id.m_thread); +#endif + m_id = id(); + } + + void swap(thread& other) + { + std::swap(m_id, other.m_id); +#ifdef _WIN32 + std::swap(m_handle, other.m_handle); +#endif + } + + static unsigned hardware_concurrency() + { +#ifdef _WIN32 + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + return static_cast(sysinfo.dwNumberOfProcessors); +#else + return 0; +#endif + } + +private: + id m_id; + +#ifdef _WIN32 + native_handle_type m_handle; +#endif + + template + void StartThread(F* param) + { +#ifdef USE_BEGINTHREADEX + m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete, param, 0, &m_id.m_thread); +#elif defined(_WIN32) + m_handle = CreateThread(NULL, 0, &RunAndDelete, param, 0, &m_id.m_thread); +#else + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 1024 * 1024); + if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete, param)) + m_id = id(); +#endif + } + + template + class Func + { + public: + Func(C _func) : func(_func) {} + + void Run() { func(); } + + private: + C const func; + }; + + template + class FuncArg + { + public: + FuncArg(C _func, A _arg) : func(_func), arg(_arg) {} + + void Run() { func(arg); } + + private: + C const func; + A arg; + }; + + template + static THREAD_RETURN RunAndDelete(void* param) + { +#ifdef __APPLE__ + // NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +#endif + static_cast(param)->Run(); + delete static_cast(param); +#ifdef __APPLE__ + // [pool release]; +#endif + return 0; + } +}; + +namespace this_thread +{ + +inline void yield() +{ +#ifdef _WIN32 + SwitchToThread(); +#else + sleep(0); +#endif +} + +inline thread::id get_id() +{ +#ifdef _WIN32 + return GetCurrentThreadId(); +#else + return pthread_self(); +#endif +} + +} // namespace this_thread + +} // namespace std + +#undef USE_RVALUE_REFERENCES +#undef USE_BEGINTHREADEX +#undef THREAD_ID +#undef THREAD_RETURN +#undef THREAD_HANDLE + +#endif +#endif diff --git a/base/threadutil.cpp b/thread/threadutil.cpp similarity index 95% rename from base/threadutil.cpp rename to thread/threadutil.cpp index d8447e039e..24ff853c1b 100644 --- a/base/threadutil.cpp +++ b/thread/threadutil.cpp @@ -1,7 +1,7 @@ #ifdef _WIN32 #include #endif -#include "base/threadutil.h" +#include "thread/threadutil.h" void setCurrentThreadName(const char* szThreadName) { diff --git a/base/threadutil.h b/thread/threadutil.h similarity index 64% rename from base/threadutil.h rename to thread/threadutil.h index 6b5d31990c..347562a26c 100644 --- a/base/threadutil.h +++ b/thread/threadutil.h @@ -3,7 +3,10 @@ #include #ifdef _WIN32 +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN #include +#include #else #include @@ -36,3 +39,18 @@ public: } };*/ + + +#ifdef _WIN32 +#define THREAD_HANDLE HANDLE +#else +#define THREAD_HANDLE pthread_t +#endif + + +// TODO: replace this abomination with std::thread + +class thread { +public: + virtual void Run(); +}; \ No newline at end of file diff --git a/ui/screen.cpp b/ui/screen.cpp index edb31846e7..fd7661fab6 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -3,9 +3,6 @@ #include "ui/screen.h" #include "ui/ui.h" -Screen::Screen(bool isUiScreen) : screenManager_(0), isUiScreen_(isUiScreen) { } -Screen::~Screen() { } - ScreenManager::ScreenManager() { nextScreen_ = 0; uiContext_ = 0; diff --git a/ui/screen.h b/ui/screen.h index 883b381e5e..f77becca33 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -33,8 +33,9 @@ class UIContext; class Screen { public: - Screen(bool isUiScreen = false); - virtual ~Screen(); + Screen(bool isUiScreen = false) : screenManager_(0), isUiScreen_(isUiScreen) { } + virtual ~Screen() {} + virtual void update(InputState &input) = 0; virtual void render() {} virtual void deviceLost() {} diff --git a/ui/ui.cpp b/ui/ui.cpp index f894eb97e1..71e53c071e 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -234,7 +234,7 @@ int UIImageButton(int id, const LayoutManager &layout, float w, int image, int b return clicked; } -int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align) // uses current UI atlas for fetching images. +int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align, uint32_t color) // uses current UI atlas for fetching images. { float x, y; layout.GetPos(&w, &h, &x, &y); @@ -294,7 +294,7 @@ int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w Texture::Unbind(); } - ui_draw2d.DrawTexRect(x, y, x+w, y+h, 0, 0, 1, 1, 0xFFFFFFFF); + ui_draw2d.DrawTexRect(x, y, x+w, y+h, 0, 0, 1, 1, color); ui_draw2d.Flush(); ctx->RebindTexture(); diff --git a/ui/ui.h b/ui/ui.h index 237d57fed3..3bd7444661 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -20,7 +20,7 @@ #define GEN_ID_LOOP(i) (int)((IMGUI_SRC_ID) + (__LINE__) + (i) * 13612) #else #define GEN_ID (__LINE__) -#define GEN_ID_LOOP(i) ((__LINE__) + (i) * 13612) +#define GEN_ID_LOOP(i) ((__LINE__) + ((int)i) * 13612) #endif #include "gfx_es2/draw_buffer.h" @@ -244,7 +244,7 @@ void UIReset(); // Returns 1 if clicked int UIButton(int id, const LayoutManager &layout, float w, float h, const char *text, int button_align); int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images. -int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align); // uses current UI atlas for fetching images. +int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align, uint32_t color = 0xFFFFFFFF); // uses current UI atlas for fetching images. // Returns 1 if clicked, puts the value in *value (where it also gets the current state). int UICheckBox(int id, int x, int y, const char *text, int align, bool *value); From 1ef32d13abd2c0b080b230b81007d560fbe50b55 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 13 Apr 2013 21:49:03 +0200 Subject: [PATCH 0326/1445] Custom implementations of isnan/isinf as it's just a mess portability-wise.. --- math/math_util.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/math/math_util.h b/math/math_util.h index d5c7e0a14c..bea22b291a 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -4,6 +4,8 @@ #include #include +#include "base/basictypes.h" + inline float sqr(float f) {return f*f;} inline float sqr_signed(float f) {return f<0 ? -f*f : f*f;} @@ -73,6 +75,24 @@ inline float dB2lin(float dB) { return expf(dB * DB_2_LOG); } +inline bool my_isinf(float f) { + union { + float f; + uint32_t u; + } f2u; + f2u.f = f; + return f2u.u == 0x7f800000 || + f2u.u == 0xff800000; +} + +inline bool my_isnan(float f) { + union { + float f; + uint32_t u; + } f2u; + f2u.f = f; + return (f2u.u & 0x7F800000) == 0x7F800000; +} // FPU control. void EnableFZ(); From 6e24983f8a3f75362972fa910f653af1f17fc513 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 13 Apr 2013 12:49:41 -0700 Subject: [PATCH 0327/1445] iOS: Buildfix. --- thread/prioritizedworkqueue.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index 2866d3d8c8..b51ab45a6f 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -5,6 +5,7 @@ #include "thread/prioritizedworkqueue.h" #if defined(IOS) || (defined(__APPLE__) && !defined(__MAC_10_7)) +#include namespace std { using tr1::bind; } From 4cc3c5079af162f224418889f53a8721361a4ede Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 13 Apr 2013 21:58:55 +0200 Subject: [PATCH 0328/1445] Apply color to fallback graphics for texturebuttons too --- ui/ui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index 71e53c071e..9f7698eebe 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -288,7 +288,7 @@ int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w x += (w - nw) / 2.0f; w = nw; } else { - ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w); + ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w, color); ui_draw2d.Flush(); Texture::Unbind(); From 1b471762427f8699fe08eaa267537c49a43c2faf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 13 Apr 2013 23:04:53 +0200 Subject: [PATCH 0329/1445] Fix for my_isnan --- math/math_util.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/math/math_util.h b/math/math_util.h index bea22b291a..6a7ff6b3b4 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -91,7 +91,8 @@ inline bool my_isnan(float f) { uint32_t u; } f2u; f2u.f = f; - return (f2u.u & 0x7F800000) == 0x7F800000; + // NaNs have non-zero mantissa + return ((f2u.u & 0x7F800000) == 0x7F800000) && (f2u.u & 0x7FFFFF); } // FPU control. From 9b709c21704c433ea809a9e3ed710fc8714e6034 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 14 Apr 2013 17:01:39 +1000 Subject: [PATCH 0330/1445] Harmattan: create PPSSPP dir if it doesn't exist. --- base/QtMain.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 48ebffb525..2769deb582 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -74,6 +74,9 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) char* savegame_dir = "data/"; #elif defined(MEEGO_EDITION_HARMATTAN) char* savegame_dir = "/home/user/MyDocs/PPSSPP/"; + QDir myDocs("/home/user/MyDocs/"); + if (!myDocs.exists("PPSSPP")) + myDocs.mkdir("PPSSPP"); #else char* savegame_dir = "./"; #endif From 961e400e1f07ae313cc8ef13e1669b2a549c8899 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 14 Apr 2013 09:58:01 +0200 Subject: [PATCH 0331/1445] Fix bug in getDir --- file/file_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index fbaf027260..f062d82d42 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -308,7 +308,7 @@ std::string getDir(const std::string &path) int n = path.size() - 1; while (n >= 0 && path[n] != '\\' && path[n] != '/') n--; - std::string cutpath = path.substr(0, n); + std::string cutpath = n > 0 ? path.substr(0, n) : ""; for (size_t i = 0; i < cutpath.size(); i++) { if (cutpath[i] == '\\') cutpath[i] = '/'; From 345180dcef8b47a3c21b6eb7a18942e54eb93c6c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 14 Apr 2013 11:57:38 +0200 Subject: [PATCH 0332/1445] Add queue flush ability. Fix VGrid wrapping in UI. Fix some strange java error. --- .../com/henrikrydgard/libnative/NativeActivity.java | 2 -- thread/prioritizedworkqueue.cpp | 13 +++++++++++++ thread/prioritizedworkqueue.h | 1 + ui/ui.h | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 37561fbfa9..2f2edb526d 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -361,13 +361,11 @@ public class NativeActivity extends Activity { .setView(fl) .setTitle(title) .setPositiveButton(defaultAction, new DialogInterface.OnClickListener(){ - @Override public void onClick(DialogInterface d, int which) { d.dismiss(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener(){ - @Override public void onClick(DialogInterface d, int which) { d.cancel(); NativeActivity.inputBoxCancelled = false; diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index b51ab45a6f..a8ec8cc05c 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -31,6 +31,18 @@ void PrioritizedWorkQueue::Stop() { mutex_.unlock(); } +void PrioritizedWorkQueue::Flush() { + if (queue_.empty()) + return; + mutex_.lock(); + for (auto iter = queue_.begin(); iter != queue_.end(); ++iter) { + delete *iter; + } + queue_.clear(); + mutex_.unlock(); +} + + // The worker should simply call this in a loop. Will block when appropriate. PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { mutex_.lock(); @@ -67,6 +79,7 @@ static void threadfunc(PrioritizedWorkQueue *wq) { break; } else { item->run(); + delete item; } } } diff --git a/thread/prioritizedworkqueue.h b/thread/prioritizedworkqueue.h index e3e815d7a3..c2198a3d5b 100644 --- a/thread/prioritizedworkqueue.h +++ b/thread/prioritizedworkqueue.h @@ -31,6 +31,7 @@ public: // The worker should simply call this in a loop. Will block when appropriate. PrioritizedWorkQueueItem *Pop(); + void Flush(); bool Done() { return done_; } void Stop(); diff --git a/ui/ui.h b/ui/ui.h index 3bd7444661..22a566a6e9 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -112,7 +112,7 @@ public: *x = x_; *y = y_; y_ += *h + ySpacing_; - if (y_ >= yMax_) { + if (y_ + *h >= yMax_) { x_ += *w + xSpacing_; y_ = yInit_; } From 0d0ed1256b5c7fafa86de4ea75d29bbc5b16d12e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 14 Apr 2013 12:24:28 +0200 Subject: [PATCH 0333/1445] Add safety check in prio work queue --- thread/prioritizedworkqueue.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index a8ec8cc05c..82742e058d 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -48,8 +48,10 @@ PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { mutex_.lock(); while (queue_.empty()) { notEmpty_.wait(mutex_); - if (done_) + if (done_) { + mutex_.unlock(); return 0; + } } // Find the top priority item (lowest value). @@ -61,10 +63,17 @@ PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { best_prio = (*iter)->priority(); } } - PrioritizedWorkQueueItem *poppedItem = *best; - queue_.erase(best); - mutex_.unlock(); - return poppedItem; + + if (best != queue_.end()) { + PrioritizedWorkQueueItem *poppedItem = *best; + queue_.erase(best); + mutex_.unlock(); + return poppedItem; + } else { + // Not really sure how this can happen, but let's be safe. + mutex_.unlock(); + return 0; + } } // TODO: This feels ugly. Revisit later. From 3199137b46089aa103dd642fa1c3236338118f13 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 14 Apr 2013 23:08:51 +1000 Subject: [PATCH 0334/1445] Use lambdas instead if we don't have C++11 support. --- thread/prioritizedworkqueue.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index 82742e058d..75026f4f56 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -94,7 +94,12 @@ static void threadfunc(PrioritizedWorkQueue *wq) { } void ProcessWorkQueueOnThreadWhile(PrioritizedWorkQueue *wq) { - workThread = new std::thread(std::bind(&threadfunc, wq)); + workThread = new std::thread( +#if defined(__SYMBIAN32__) || defined(MAEMO) || defined(MEEGO_EDITION_HARMATTAN) || defined(BLACKBERRY) + [wq](){threadfunc(wq);} +#else + std::bind(&threadfunc, wq) + ); } void StopProcessingWorkQueue(PrioritizedWorkQueue *wq) { @@ -102,4 +107,4 @@ void StopProcessingWorkQueue(PrioritizedWorkQueue *wq) { workThread->join(); delete workThread; workThread = 0; -} \ No newline at end of file +} From 4d6df78162a7928fbc2d246a6ac813e1efa04aeb Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 15 Apr 2013 00:49:04 +1000 Subject: [PATCH 0335/1445] Buildfix --- thread/prioritizedworkqueue.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index 75026f4f56..2cb79c4d40 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -99,6 +99,7 @@ void ProcessWorkQueueOnThreadWhile(PrioritizedWorkQueue *wq) { [wq](){threadfunc(wq);} #else std::bind(&threadfunc, wq) +#endif ); } From d032f659aaa3177e38e7417838a4f0fe67dbf464 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 17 Apr 2013 12:18:32 +0200 Subject: [PATCH 0336/1445] Change AtlasFont format to support disjoint char ranges --- gfx/texture_atlas.cpp | 9 ++++++ gfx/texture_atlas.h | 15 +++++++-- gfx_es2/draw_buffer.cpp | 59 ++++++++++++++++++---------------- tools/atlastool.cpp | 71 ++++++++++++++++++++++++++++++----------- 4 files changed, 107 insertions(+), 47 deletions(-) diff --git a/gfx/texture_atlas.cpp b/gfx/texture_atlas.cpp index 6a706600ae..628dd7b9c4 100644 --- a/gfx/texture_atlas.cpp +++ b/gfx/texture_atlas.cpp @@ -18,3 +18,12 @@ const AtlasImage *Atlas::getImageByName(const char *name) const } return 0; } + +const AtlasChar *AtlasFont::getChar(int utf32) const { + for (int i = 0; i < numRanges; i++) { + if (utf32 >= ranges[i].start && utf32 < ranges[i].end) { + return &charData[ranges[i].start_index + utf32 - ranges[i].start]; + } + } + return 0; +} diff --git a/gfx/texture_atlas.h b/gfx/texture_atlas.h index d75c54e271..7aeda2bd6f 100644 --- a/gfx/texture_atlas.h +++ b/gfx/texture_atlas.h @@ -11,13 +11,24 @@ struct AtlasChar { unsigned short pw, ph; }; +struct AtlasCharRange { + int start; + int end; + int start_index; +}; + struct AtlasFont { float padding; float height; float ascend; float distslope; - AtlasChar chars[96]; + const AtlasChar *charData; + const AtlasCharRange *ranges; + int numRanges; const char *name; + + // Returns 0 on no match. + const AtlasChar *getChar(int utf32) const ; }; struct AtlasImage { @@ -36,4 +47,4 @@ struct Atlas { // These are inefficient linear searches, try not to call every frame. const AtlasFont *getFontByName(const char *name) const; const AtlasImage *getImageByName(const char *name) const; -}; +}; \ No newline at end of file diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 28c3b56d83..461bce6e30 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -323,18 +323,20 @@ void DrawBuffer::DrawImage2GridH(int atlas_image, float x1, float y1, float x2, void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { const AtlasFont &atlasfont = *atlas->fonts[font]; - unsigned char cval; + + unsigned int cval; float wacc = 0; int lines = 1; while ((cval = *text++) != '\0') { - if (cval < 32) continue; - if (cval > 127) continue; if (cval == '\n') { wacc = 0; lines++; + continue; + } + const AtlasChar *c = atlasfont.getChar(cval); + if (c) { + wacc += c->wx * fontscalex; } - AtlasChar c = atlasfont.chars[cval - 32]; - wacc += c.wx * fontscalex; } if (w) *w = wacc; if (h) *h = atlasfont.height * fontscaley * lines; @@ -392,29 +394,32 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co } if (cval < 32) continue; if (cval > 127) continue; - AtlasChar c = atlasfont.chars[cval - 32]; - float cx1, cy1, cx2, cy2; - if (flags & ROTATE_90DEG_LEFT) { - cy1 = y - c.ox * fontscalex; - cx1 = x + c.oy * fontscaley; - cy2 = y - (c.ox + c.pw) * fontscalex; - cx2 = x + (c.oy + c.ph) * fontscaley; - } else { - cx1 = x + c.ox * fontscalex; - cy1 = y + c.oy * fontscaley; - cx2 = x + (c.ox + c.pw) * fontscalex; - cy2 = y + (c.oy + c.ph) * fontscaley; + const AtlasChar *ch = atlasfont.getChar(cval); + if (ch) { + const AtlasChar &c = *ch; + float cx1, cy1, cx2, cy2; + if (flags & ROTATE_90DEG_LEFT) { + cy1 = y - c.ox * fontscalex; + cx1 = x + c.oy * fontscaley; + cy2 = y - (c.ox + c.pw) * fontscalex; + cx2 = x + (c.oy + c.ph) * fontscaley; + } else { + cx1 = x + c.ox * fontscalex; + cy1 = y + c.oy * fontscaley; + cx2 = x + (c.ox + c.pw) * fontscalex; + cy2 = y + (c.oy + c.ph) * fontscaley; + } + V(cx1, cy1, color, c.sx, c.sy); + V(cx2, cy1, color, c.ex, c.sy); + V(cx2, cy2, color, c.ex, c.ey); + V(cx1, cy1, color, c.sx, c.sy); + V(cx2, cy2, color, c.ex, c.ey); + V(cx1, cy2, color, c.sx, c.ey); + if (flags & ROTATE_90DEG_LEFT) + y -= c.wx * fontscalex; + else + x += c.wx * fontscalex; } - V(cx1, cy1, color, c.sx, c.sy); - V(cx2, cy1, color, c.ex, c.sy); - V(cx2, cy2, color, c.ex, c.ey); - V(cx1, cy1, color, c.sx, c.sy); - V(cx2, cy2, color, c.ex, c.ey); - V(cx1, cy2, color, c.sx, c.ey); - if (flags & ROTATE_90DEG_LEFT) - y -= c.wx * fontscalex; - else - x += c.wx * fontscalex; } } diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 39c570442f..b380bafd22 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -20,6 +20,8 @@ #include #include +#include "gfx/texture_atlas.h" + #include "image/png_load.h" #include "image/zim_save.h" @@ -166,6 +168,7 @@ struct Data { float wx; int effect; + int charNum; }; bool operator<(const Data &lhs, const Data &rhs) { @@ -273,7 +276,7 @@ struct Closest { } }; -void RasterizeFont(const char *fontfile, int fontsize, float *metrics_height, Bucket *bucket) { +void RasterizeFont(const char *fontfile, const std::vector &ranges, int fontsize, float *metrics_height, Bucket *bucket) { FT_Library freetype; CHECK(FT_Init_FreeType(&freetype) == 0); @@ -284,9 +287,11 @@ void RasterizeFont(const char *fontfile, int fontsize, float *metrics_height, Bu CHECK(FT_Set_Pixel_Sizes(font, 0, fontsize * supersample) == 0); + + // Character range. TODO: Make definable. We might want unicode // Convert all characters to bitmaps. - for(int kar = 32; kar < 128; kar++) { + for(int kar = ranges[0].start; kar < ranges[0].end; kar++) { Image img; if (0 != FT_Load_Char(font, kar, FT_LOAD_RENDER|FT_LOAD_MONOCHROME)) { img.resize(1,1); @@ -301,6 +306,7 @@ void RasterizeFont(const char *fontfile, int fontsize, float *metrics_height, Bu dat.ox = 0; dat.oy = 0; dat.wx = 0; + dat.charNum = kar; dat.effect = FX_RED_TO_ALPHA_SOLID_WHITE; bucket->AddItem(img, dat); continue; @@ -355,6 +361,7 @@ void RasterizeFont(const char *fontfile, int fontsize, float *metrics_height, Bu dat.ox = (float)font->glyph->metrics.horiBearingX / 64 / supersample - bord; dat.oy = -(float)font->glyph->metrics.horiBearingY / 64 / supersample - bord; dat.wx = (float)font->glyph->metrics.horiAdvance / 64 / supersample; + dat.charNum = kar; dat.effect = FX_RED_TO_ALPHA_SOLID_WHITE; bucket->AddItem(img, dat); @@ -411,6 +418,13 @@ struct FontDesc { float metrics_height; + std::vector ranges; + + FontDesc() { + AtlasCharRange range = {32, 128, 0}; + ranges.push_back(range); + } + void ComputeHeight(const vector &results, float distmult) { ascend = 0; descend = 0; @@ -423,26 +437,42 @@ struct FontDesc { } void OutputSelf(FILE *fil, float tw, float th, const vector &results) { + // Dump results as chardata. + fprintf(fil, "const AtlasChar font_%s_chardata[] = {\n", name.c_str()); + for (size_t i = 0; i < results.size(); i++) { + fprintf(fil, " {%ff, %ff, %ff, %ff, %1.4ff, %1.4ff, %1.4ff, %i, %i}, // %i\n", + /*results[i].id, */ + results[i].sx / tw, + results[i].sy / th, + results[i].ex / tw, + results[i].ey / th, + results[i].ox, + results[i].oy, + results[i].wx, + results[i].ex - results[i].sx, results[i].ey - results[i].sy, + results[i].charNum); + } + fprintf(fil, "};\n"); + + fprintf(fil, "const AtlasCharRange font_%s_ranges[] = {\n", name.c_str()); + // Write range information. + int start_index = 0; + for (int r = 0; r < 1; r++) { + int first_char_id = ranges[r].start; + int last_char_id = ranges[r].end; + fprintf(fil, " { %i, %i, %i },", first_char_id, last_char_id, start_index); + start_index += last_char_id - first_char_id; + } + fprintf(fil, "};\n"); + fprintf(fil, "const AtlasFont font_%s = {\n", name.c_str()); fprintf(fil, " %ff, // padding\n", height - ascend - descend); fprintf(fil, " %ff, // height\n", ascend + descend); fprintf(fil, " %ff, // ascend\n", ascend); fprintf(fil, " %ff, // distslope\n", distmult / 256.0); - fprintf(fil, " {\n"); - CHECK(last_char_id - first_char_id == 96); - for(int i = first_char_id; i < last_char_id; i++) { - fprintf(fil, " {%ff, %ff, %ff, %ff, %1.4ff, %1.4ff, %1.4ff, %i, %i}, // %i\n", - /*results[i].id, */ - results[i].sx / tw, - results[i].sy / th, - results[i].ex / tw, - results[i].ey / th, - results[i].ox, - results[i].oy, - results[i].wx, - results[i].ex - results[i].sx, results[i].ey - results[i].sy, (i - first_char_id + 32)); - } - fprintf(fil, " },\n"); + fprintf(fil, " font_%s_chardata,\n", name.c_str()); + fprintf(fil, " font_%s_ranges,\n", name.c_str()); + fprintf(fil, " %i,\n", (int)ranges.size()); fprintf(fil, " \"%s\", // name\n", name.c_str()); fprintf(fil, "};\n"); } @@ -527,10 +557,15 @@ int main(int argc, char **argv) { sscanf(rest, "%s %s %i", fontname, fontfile, &pixheight); printf("Font: %s (%s) in size %i\n", fontname, fontfile, pixheight); + std::vector ranges; + AtlasCharRange def = {32, 128, 0}; + ranges.push_back(def); + FontDesc fnt; + fnt.ranges = ranges; fnt.first_char_id = (int)bucket.items.size(); float metrics_height; - RasterizeFont(fontfile, pixheight, &metrics_height, &bucket); + RasterizeFont(fontfile, ranges, pixheight, &metrics_height, &bucket); fnt.name = fontname; fnt.last_char_id = (int)bucket.items.size(); CHECK(fnt.last_char_id - fnt.first_char_id == 96); From 7d7bd3a9988dc4f801f71fc5734f83ad83e5958d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 17 Apr 2013 13:14:38 +0200 Subject: [PATCH 0337/1445] Basic UTF-8 support in atlastool / draw_buffer. --- gfx_es2/draw_buffer.cpp | 2 - tools/atlastool.cpp | 272 ++++++++++++++++++++++------------------ 2 files changed, 152 insertions(+), 122 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 461bce6e30..4f6b7346f5 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -392,8 +392,6 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co x = sx; continue; } - if (cval < 32) continue; - if (cval > 127) continue; const AtlasChar *ch = atlasfont.getChar(cval); if (ch) { const AtlasChar &c = *ch; diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index b380bafd22..ce29f0d58b 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -196,41 +196,45 @@ struct Bucket { masq.resize(image_width, 1); dest.resize(image_width, 1); sort(items.begin(), items.end()); - for(int i = 0; i < (int)items.size(); i++) { + for (int i = 0; i < (int)items.size(); i++) { int idx = items[i].first.dat[0].size(); int idy = items[i].first.dat.size(); - CHECK(idx <= image_width); - bool found = false; - for(int ty = 0; ty < 2047 && !found; ty++) { - if(ty + idy + 1 > (int)dest.dat.size()) { - masq.resize(image_width, ty + idy + 1); - dest.resize(image_width, ty + idy + 1); - } - // Brute force packing. - for(int tx = 0; tx < image_width - (int)items[i].first.dat[0].size() && !found; tx++) { - bool valid = !(masq.dat[ty][tx] || masq.dat[ty + idy - 1][tx] || masq.dat[ty][tx + idx - 1] || masq.dat[ty + idy - 1][tx + idx - 1]); - if (valid) { - for(int ity = 0; ity < idy && valid; ity++) - for(int itx = 0; itx < idx && valid; itx++) - if(masq.dat[ty + ity][tx + itx]) { - valid = false; - } - } - if (valid) { - dest.copyfrom(items[i].first, tx, ty, items[i].second.effect); - masq.set(tx, ty, tx + idx + 1, ty + idy + 1, 255); + if (idx > 0 && idy > 0) { + CHECK(idx <= image_width); + bool found = false; + for (int ty = 0; ty < 2047 && !found; ty++) { + if(ty + idy + 1 > (int)dest.dat.size()) { + masq.resize(image_width, ty + idy + 1); + dest.resize(image_width, ty + idy + 1); + } + // Brute force packing. + for (int tx = 0; tx < image_width - (int)items[i].first.dat[0].size() && !found; tx++) { + bool valid = !(masq.dat[ty][tx] || masq.dat[ty + idy - 1][tx] || masq.dat[ty][tx + idx - 1] || masq.dat[ty + idy - 1][tx + idx - 1]); + if (valid) { + for(int ity = 0; ity < idy && valid; ity++) { + for(int itx = 0; itx < idx && valid; itx++) { + if(masq.dat[ty + ity][tx + itx]) { + valid = false; + } + } + } + } + if (valid) { + dest.copyfrom(items[i].first, tx, ty, items[i].second.effect); + masq.set(tx, ty, tx + idx + 1, ty + idy + 1, 255); - items[i].second.sx = tx; - items[i].second.sy = ty; + items[i].second.sx = tx; + items[i].second.sy = ty; - items[i].second.ex = tx + idx; - items[i].second.ey = ty + idy; + items[i].second.ex = tx + idx; + items[i].second.ey = ty + idy; - found = true; + found = true; - // printf("Placed %d at %dx%d-%dx%d\n", items[i].second.id, tx, ty, tx + idx, ty + idy); - } - } + // printf("Placed %d at %dx%d-%dx%d\n", items[i].second.id, tx, ty, tx + idx, ty + idy); + } + } + } } } @@ -276,14 +280,14 @@ struct Closest { } }; -void RasterizeFont(const char *fontfile, const std::vector &ranges, int fontsize, float *metrics_height, Bucket *bucket) { +void RasterizeFont(const char *fontfile, std::vector &ranges, int fontsize, float *metrics_height, Bucket *bucket) { FT_Library freetype; CHECK(FT_Init_FreeType(&freetype) == 0); FT_Face font; CHECK(FT_New_Face(freetype, fontfile, 0, &font) == 0); - printf("%d glyphs, %08x flags, %d units, %d strikes\n", (int)font->num_glyphs, (int)font->face_flags, (int)font->units_per_EM, (int)font->num_fixed_sizes); + printf("TTF info: %d glyphs, %08x flags, %d units, %d strikes\n", (int)font->num_glyphs, (int)font->face_flags, (int)font->units_per_EM, (int)font->num_fixed_sizes); CHECK(FT_Set_Pixel_Sizes(font, 0, fontsize * supersample) == 0); @@ -291,80 +295,83 @@ void RasterizeFont(const char *fontfile, const std::vector &rang // Character range. TODO: Make definable. We might want unicode // Convert all characters to bitmaps. - for(int kar = ranges[0].start; kar < ranges[0].end; kar++) { - Image img; - if (0 != FT_Load_Char(font, kar, FT_LOAD_RENDER|FT_LOAD_MONOCHROME)) { - img.resize(1,1); + for (size_t r = 0; r < ranges.size(); r++) { + ranges[r].start_index = global_id; + for(int kar = ranges[r].start; kar < ranges[r].end; kar++) { + Image img; + if (0 != FT_Load_Char(font, kar, FT_LOAD_RENDER|FT_LOAD_MONOCHROME)) { + img.resize(0, 0); + Data dat; + + dat.id = global_id++; + + dat.sx = 0; + dat.sy = 0; + dat.ex = 0; + dat.ey = 0; + dat.ox = 0; + dat.oy = 0; + dat.wx = 0; + dat.charNum = kar; + dat.effect = FX_RED_TO_ALPHA_SOLID_WHITE; + bucket->AddItem(img, dat); + continue; + } + + // printf("%dx%d %p\n", font->glyph->bitmap.width, font->glyph->bitmap.rows, font->glyph->bitmap.buffer); + const int bord = (128 + distmult - 1) / distmult + 1; + if(font->glyph->bitmap.buffer) { + FT_Bitmap tempbitmap; + FT_Bitmap_New(&tempbitmap); + FT_Bitmap_Convert(freetype, &font->glyph->bitmap, &tempbitmap, 1); + Closest closest(tempbitmap); + + // No resampling, just sets the size of the image. + img.resize((tempbitmap.width + supersample - 1) / supersample + bord * 2, (tempbitmap.rows + supersample - 1) / supersample + bord * 2); + int lmx = img.dat[0].size(); + int lmy = img.dat.size(); + + // AA by finding distance to character. Probably a fairly decent approximation but why not do it right? + for(int y = 0; y < lmy; y++) { + int cty = (y - bord) * supersample + supersample / 2; + for(int x = 0; x < lmx; x++) { + int ctx = (x - bord) * supersample + supersample / 2; + float dist; + if(closest.safe_access(ctx, cty)) { + dist = closest.find_closest(ctx, cty, 0); + } else { + dist = -closest.find_closest(ctx, cty, 1); + } + dist = dist / supersample * distmult + 127.5; + dist = floor(dist + 0.5); + if(dist < 0) dist = 0; + if(dist > 255) dist = 255; + + // Only set the red channel. We process when adding the image. + img.dat[y][x] = (unsigned char)dist; + } + } + FT_Bitmap_Done(freetype, &tempbitmap); + } else { + img.resize(1, 1); + } + Data dat; dat.id = global_id++; dat.sx = 0; dat.sy = 0; - dat.ex = 0; - dat.ey = 0; - dat.ox = 0; - dat.oy = 0; - dat.wx = 0; + dat.ex = img.dat[0].size(); + dat.ey = img.dat.size(); + dat.ox = (float)font->glyph->metrics.horiBearingX / 64 / supersample - bord; + dat.oy = -(float)font->glyph->metrics.horiBearingY / 64 / supersample - bord; + dat.wx = (float)font->glyph->metrics.horiAdvance / 64 / supersample; dat.charNum = kar; + dat.effect = FX_RED_TO_ALPHA_SOLID_WHITE; bucket->AddItem(img, dat); - continue; } - - // printf("%dx%d %p\n", font->glyph->bitmap.width, font->glyph->bitmap.rows, font->glyph->bitmap.buffer); - const int bord = (128 + distmult - 1) / distmult + 1; - if(font->glyph->bitmap.buffer) { - FT_Bitmap tempbitmap; - FT_Bitmap_New(&tempbitmap); - FT_Bitmap_Convert(freetype, &font->glyph->bitmap, &tempbitmap, 1); - Closest closest(tempbitmap); - - // No resampling, just sets the size of the image. - img.resize((tempbitmap.width + supersample - 1) / supersample + bord * 2, (tempbitmap.rows + supersample - 1) / supersample + bord * 2); - int lmx = img.dat[0].size(); - int lmy = img.dat.size(); - - // AA by finding distance to character. Probably a fairly decent approximation but why not do it right? - for(int y = 0; y < lmy; y++) { - int cty = (y - bord) * supersample + supersample / 2; - for(int x = 0; x < lmx; x++) { - int ctx = (x - bord) * supersample + supersample / 2; - float dist; - if(closest.safe_access(ctx, cty)) { - dist = closest.find_closest(ctx, cty, 0); - } else { - dist = -closest.find_closest(ctx, cty, 1); - } - dist = dist / supersample * distmult + 127.5; - dist = floor(dist + 0.5); - if(dist < 0) dist = 0; - if(dist > 255) dist = 255; - - // Only set the red channel. We process when adding the image. - img.dat[y][x] = (unsigned char)dist; - } - } - FT_Bitmap_Done(freetype, &tempbitmap); - } else { - img.resize(1, 1); - } - - Data dat; - - dat.id = global_id++; - - dat.sx = 0; - dat.sy = 0; - dat.ex = img.dat[0].size(); - dat.ey = img.dat.size(); - dat.ox = (float)font->glyph->metrics.horiBearingX / 64 / supersample - bord; - dat.oy = -(float)font->glyph->metrics.horiBearingY / 64 / supersample - bord; - dat.wx = (float)font->glyph->metrics.horiAdvance / 64 / supersample; - dat.charNum = kar; - - dat.effect = FX_RED_TO_ALPHA_SOLID_WHITE; - bucket->AddItem(img, dat); } *metrics_height = font->size->metrics.height; @@ -420,9 +427,8 @@ struct FontDesc { std::vector ranges; - FontDesc() { - AtlasCharRange range = {32, 128, 0}; - ranges.push_back(range); + FontDesc() + { } void ComputeHeight(const vector &results, float distmult) { @@ -439,25 +445,29 @@ struct FontDesc { void OutputSelf(FILE *fil, float tw, float th, const vector &results) { // Dump results as chardata. fprintf(fil, "const AtlasChar font_%s_chardata[] = {\n", name.c_str()); - for (size_t i = 0; i < results.size(); i++) { - fprintf(fil, " {%ff, %ff, %ff, %ff, %1.4ff, %1.4ff, %1.4ff, %i, %i}, // %i\n", - /*results[i].id, */ - results[i].sx / tw, - results[i].sy / th, - results[i].ex / tw, - results[i].ey / th, - results[i].ox, - results[i].oy, - results[i].wx, - results[i].ex - results[i].sx, results[i].ey - results[i].sy, - results[i].charNum); + for (size_t r = 0; r < ranges.size(); r++) { + fprintf(fil, "// RANGE: 0x%x - 0x%x, start 0x%x\n", ranges[r].start, ranges[r].end, ranges[r].start_index); + for (int i = ranges[r].start; i < ranges[r].end; i++) { + int idx = i - ranges[r].start + ranges[r].start_index; + fprintf(fil, " {%ff, %ff, %ff, %ff, %1.4ff, %1.4ff, %1.4ff, %i, %i}, // %i\n", + /*results[i].id, */ + results[idx].sx / tw, + results[idx].sy / th, + results[idx].ex / tw, + results[idx].ey / th, + results[idx].ox, + results[idx].oy, + results[idx].wx, + results[idx].ex - results[idx].sx, results[idx].ey - results[idx].sy, + results[idx].charNum); + } } fprintf(fil, "};\n"); fprintf(fil, "const AtlasCharRange font_%s_ranges[] = {\n", name.c_str()); // Write range information. int start_index = 0; - for (int r = 0; r < 1; r++) { + for (size_t r = 0; r < ranges.size(); r++) { int first_char_id = ranges[r].start; int last_char_id = ranges[r].end; fprintf(fil, " { %i, %i, %i },", first_char_id, last_char_id, start_index); @@ -510,6 +520,27 @@ struct ImageDesc { } }; +AtlasCharRange range(int start, int end) { + AtlasCharRange r = {start, end, 0}; + return r; +} + +void GetLocales(const char *locales, std::vector &ranges) +{ + for (size_t i = 0; i < strlen(locales); i++) { + switch (locales[i]) { + case 'U': // US ASCII + ranges.push_back(range(32, 128)); + break; + case 'W': // Latin-1 extras 1 + ranges.push_back(range(0x80, 0x81)); // euro sign + ranges.push_back(range(0xA2, 0xFF)); // 80 - A0 appears to contain nothing interesting + ranges.push_back(range(0x2122, 0x2123)); // trademark symbol + break; + } + } +} + int main(int argc, char **argv) { // initProgram(&argc, const_cast(&argv)); // /usr/share/fonts/truetype/msttcorefonts/Arial_Black.ttf @@ -553,24 +584,25 @@ int main(int argc, char **argv) { // Font! char fontname[256]; char fontfile[256]; + char locales[256]; int pixheight; - sscanf(rest, "%s %s %i", fontname, fontfile, &pixheight); - printf("Font: %s (%s) in size %i\n", fontname, fontfile, pixheight); + sscanf(rest, "%s %s %s %i", fontname, fontfile, locales, &pixheight); + printf("Font: %s (%s) in size %i. Locales: %s\n", fontname, fontfile, pixheight, locales); std::vector ranges; - AtlasCharRange def = {32, 128, 0}; - ranges.push_back(def); - + GetLocales(locales, ranges); + printf("locales fetched.\n"); FontDesc fnt; - fnt.ranges = ranges; fnt.first_char_id = (int)bucket.items.size(); + float metrics_height; RasterizeFont(fontfile, ranges, pixheight, &metrics_height, &bucket); - fnt.name = fontname; - fnt.last_char_id = (int)bucket.items.size(); - CHECK(fnt.last_char_id - fnt.first_char_id == 96); + printf("font rasterized.\n"); + fnt.ranges = ranges; + fnt.name = fontname; fnt.metrics_height = metrics_height; + fonts.push_back(fnt); } else if (!strcmp(word, "image")) { char imagename[256]; From 2bfeb0b59b69b18e7f03a586fe766ced5dcdb6ea Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 17 Apr 2013 15:04:40 +0200 Subject: [PATCH 0338/1445] Add some more unicode ranges --- tools/atlastool.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index ce29f0d58b..069e522b73 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -537,6 +537,21 @@ void GetLocales(const char *locales, std::vector &ranges) ranges.push_back(range(0xA2, 0xFF)); // 80 - A0 appears to contain nothing interesting ranges.push_back(range(0x2122, 0x2123)); // trademark symbol break; + case 'k': // Katakana + ranges.push_back(range(0x30A0, 0x30FF)); + break; + case 'h': // Hiragana + ranges.push_back(range(0x3041, 0x3097)); + ranges.push_back(range(0x3099, 0x309F)); + break; + case 'H': // Hebrew + ranges.push_back(range(0x0590, 0x05FF)); + break; + case 'G': // Greek + ranges.push_back(range(0x0370, 0x03FF)); + break; + case 'c': // Kanji + break; } } } From 7d25fe3736a376f782b0e26f3ce00e13272d3773 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 18 Apr 2013 00:22:38 +1000 Subject: [PATCH 0339/1445] Disable screensaver for Symbian. --- base/QtMain.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 2769deb582..f8ef3b9557 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -13,6 +13,7 @@ #ifdef __SYMBIAN32__ #include +#include #endif #include "QtMain.h" @@ -58,6 +59,9 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) #ifdef __SYMBIAN32__ // Set RunFast hardware mode for VFPv2. Denormalised values are treated as 0. NaN used for all NaN situations. User::SetFloatingPointMode(EFpModeRunFast); + // Disable screensaver + QSystemScreenSaver *ssObject = new QSystemScreenSaver(this); + ssObject->setScreenSaverInhibit(); #endif QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) From e41c7ebbf4a5868c3e9f4c0c2833a991edfde8a9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 17 Apr 2013 16:31:41 +0200 Subject: [PATCH 0340/1445] Atlastool bugfix --- tools/atlastool.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 069e522b73..79c3d266db 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -208,18 +208,17 @@ struct Bucket { dest.resize(image_width, ty + idy + 1); } // Brute force packing. - for (int tx = 0; tx < image_width - (int)items[i].first.dat[0].size() && !found; tx++) { + int sz = (int)items[i].first.dat[0].size(); + for (int tx = 0; tx < image_width - sz && !found; tx++) { bool valid = !(masq.dat[ty][tx] || masq.dat[ty + idy - 1][tx] || masq.dat[ty][tx + idx - 1] || masq.dat[ty + idy - 1][tx + idx - 1]); if (valid) { for(int ity = 0; ity < idy && valid; ity++) { for(int itx = 0; itx < idx && valid; itx++) { if(masq.dat[ty + ity][tx + itx]) { - valid = false; + goto skip; } } } - } - if (valid) { dest.copyfrom(items[i].first, tx, ty, items[i].second.effect); masq.set(tx, ty, tx + idx + 1, ty + idy + 1, 255); @@ -233,6 +232,8 @@ struct Bucket { // printf("Placed %d at %dx%d-%dx%d\n", items[i].second.id, tx, ty, tx + idx, ty + idy); } +skip: + ; } } } @@ -300,7 +301,7 @@ void RasterizeFont(const char *fontfile, std::vector &ranges, in for(int kar = ranges[r].start; kar < ranges[r].end; kar++) { Image img; if (0 != FT_Load_Char(font, kar, FT_LOAD_RENDER|FT_LOAD_MONOCHROME)) { - img.resize(0, 0); + img.resize(1, 1); Data dat; dat.id = global_id++; @@ -434,10 +435,13 @@ struct FontDesc { void ComputeHeight(const vector &results, float distmult) { ascend = 0; descend = 0; - for(int i = first_char_id; i < last_char_id; i++) { - ascend = max(ascend, -results[i].oy); - descend = max(descend, results[i].ey - results[i].sy + results[i].oy); - } + for (size_t r = 0; r < ranges.size(); r++) { + for(int i = ranges[r].start; i < ranges[r].end; i++) { + int idx = i - ranges[r].start + ranges[r].start_index; + ascend = max(ascend, -results[idx].oy); + descend = max(descend, results[idx].ey - results[idx].sy + results[idx].oy); + } + } height = metrics_height / 64.0 / supersample; } From 97abf0d2efd57ae1954bc82688bfa0c65770a223 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 17 Apr 2013 16:32:48 +0200 Subject: [PATCH 0341/1445] drawbuffer: Parse utf-8 when measuring text --- gfx_es2/draw_buffer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 4f6b7346f5..aa5017aa0d 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -327,7 +327,11 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { unsigned int cval; float wacc = 0; int lines = 1; - while ((cval = *text++) != '\0') { + UTF8 utf(text); + while (true) { + if (utf.end()) + break; + cval = utf.next(); if (cval == '\n') { wacc = 0; lines++; From 82b266e358e9268aedd2b87e64d76a748a500f1d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 17 Apr 2013 21:45:31 +0200 Subject: [PATCH 0342/1445] Add missing linebreak to atlastool output --- tools/atlastool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 79c3d266db..9b20c174fa 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -474,7 +474,7 @@ struct FontDesc { for (size_t r = 0; r < ranges.size(); r++) { int first_char_id = ranges[r].start; int last_char_id = ranges[r].end; - fprintf(fil, " { %i, %i, %i },", first_char_id, last_char_id, start_index); + fprintf(fil, " { %i, %i, %i },\n", first_char_id, last_char_id, start_index); start_index += last_char_id - first_char_id; } fprintf(fil, "};\n"); From 909b67743e221d8f838ffca384bbe6c9199cface Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 17 Apr 2013 17:08:31 +0200 Subject: [PATCH 0343/1445] Drop shadow support for TextureButton --- base/colorutil.cpp | 13 +++++++++++-- base/colorutil.h | 1 + ui/ui.cpp | 23 ++++++++++++++++------- ui/ui.h | 2 +- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/base/colorutil.cpp b/base/colorutil.cpp index ff5bac7ece..ec9766296e 100644 --- a/base/colorutil.cpp +++ b/base/colorutil.cpp @@ -14,10 +14,19 @@ uint32_t blackAlpha(float alpha) { return (int)(alpha*255)<<24; } -uint32_t colorAlpha(uint32_t color, float alpha) { +uint32_t colorAlpha(uint32_t rgb, float alpha) { if (alpha < 0.0f) alpha = 0.0f; if (alpha > 1.0f) alpha = 1.0f; - return ((int)(alpha*255)<<24) | (color & 0xFFFFFF); + return ((int)(alpha*255)<<24) | (rgb & 0xFFFFFF); +} + +uint32_t alphaMul(uint32_t color, float alphaMul) { + uint32_t rgb = color & 0xFFFFFF; + uint32_t alpha = color >> 24; + alpha *= alphaMul; + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 255.0f) alpha = 255.0f; + return ((int)(alpha)<<24) | (rgb & 0xFFFFFF); } uint32_t rgba(float r, float g, float b, float alpha) { diff --git a/base/colorutil.h b/base/colorutil.h index 0dad43baf4..61d6f8b127 100644 --- a/base/colorutil.h +++ b/base/colorutil.h @@ -5,6 +5,7 @@ uint32_t whiteAlpha(float alpha); uint32_t blackAlpha(float alpha); uint32_t colorAlpha(uint32_t color, float alpha); +uint32_t alphaMul(uint32_t color, float alphaMul); uint32_t rgba(float r, float g, float b, float alpha); uint32_t rgba_clamp(float r, float g, float b, float alpha); uint32_t hsva(float h, float s, float v, float alpha); diff --git a/ui/ui.cpp b/ui/ui.cpp index 9f7698eebe..eb2c69c903 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -5,6 +5,7 @@ #include #include +#include "base/colorutil.h" #include "ui/ui.h" #include "ui/ui_context.h" #include "gfx/texture.h" @@ -234,7 +235,7 @@ int UIImageButton(int id, const LayoutManager &layout, float w, int image, int b return clicked; } -int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align, uint32_t color) // uses current UI atlas for fetching images. +int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align, uint32_t color, int drop_shadow) // uses current UI atlas for fetching images. { float x, y; layout.GetPos(&w, &h, &x, &y); @@ -273,12 +274,7 @@ int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w clicked = 1; } } - - // Render button - if (texture) { - texture->Bind(0); - float tw = texture->Width(); float th = texture->Height(); @@ -287,14 +283,27 @@ int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w float nw = h * tw / th; x += (w - nw) / 2.0f; w = nw; + } + + // Render button + const int dropsize = 10; + if (drop_shadow && texture) + { + ui_draw2d.DrawImage4Grid(drop_shadow, x - dropsize, y, x+w + dropsize, y+h+dropsize*1.5, + alphaMul(color,0.5f), 1.0f); + ui_draw2d.Flush(true); + } + + if (texture) { + texture->Bind(0); } else { ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w, color); ui_draw2d.Flush(); Texture::Unbind(); } - ui_draw2d.DrawTexRect(x, y, x+w, y+h, 0, 0, 1, 1, color); + ui_draw2d.Flush(); ctx->RebindTexture(); diff --git a/ui/ui.h b/ui/ui.h index 22a566a6e9..13150f38ff 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -244,7 +244,7 @@ void UIReset(); // Returns 1 if clicked int UIButton(int id, const LayoutManager &layout, float w, float h, const char *text, int button_align); int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images. -int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align, uint32_t color = 0xFFFFFFFF); // uses current UI atlas for fetching images. +int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align, uint32_t color, int drop_shadow=0); // uses current UI atlas for fetching images. // Returns 1 if clicked, puts the value in *value (where it also gets the current state). int UICheckBox(int id, int x, int y, const char *text, int align, bool *value); From b25cfe209b574e5d2e9ef7c9f49350a6d39500ab Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Apr 2013 11:52:18 +0200 Subject: [PATCH 0344/1445] Basic internationalization (i18n) framework. --- base/stringutil.cpp | 152 +++++++++++ base/stringutil.h | 41 +++ file/ini_file.cpp | 580 ++++++++++++++++++++++++++++++++++++++++ file/ini_file.h | 179 +++++++++++++ gfx_es2/draw_buffer.cpp | 2 + i18n/i18n.cpp | 105 ++++++++ i18n/i18n.h | 95 +++++++ native.vcxproj | 4 + native.vcxproj.filters | 15 ++ ui/ui.cpp | 6 +- 10 files changed, 1178 insertions(+), 1 deletion(-) create mode 100644 file/ini_file.cpp create mode 100644 file/ini_file.h create mode 100644 i18n/i18n.cpp create mode 100644 i18n/i18n.h diff --git a/base/stringutil.cpp b/base/stringutil.cpp index b54b56e627..fb4acebc33 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -1,8 +1,19 @@ #include +#include +#include +#include +#include + +#include #include "base/buffer.h" #include "base/stringutil.h" +#ifdef _WIN32 +// Function Cross-Compatibility +#define strcasecmp _stricmp +#endif + unsigned int parseHex(const char *_szValue) { int Value = 0; @@ -51,3 +62,144 @@ void DataToHexString(const uint8 *data, size_t size, std::string *output) { } buffer.TakeAll(output); } + +std::string StringFromFormat(const char* format, ...) +{ + va_list args; + char *buf = NULL; + std::string temp = ""; +#ifdef _WIN32 + int required = 0; + + va_start(args, format); + required = _vscprintf(format, args); + buf = new char[required + 1]; + if(vsnprintf(buf, required, format, args) < 0) + buf[0] = '\0'; + va_end(args); + + buf[required] = '\0'; + temp = buf; + delete[] buf; +#else + va_start(args, format); + if(vasprintf(&buf, format, args) < 0) + buf = NULL; + va_end(args); + + if(buf != NULL) { + temp = buf; + free(buf); + } +#endif + return temp; +} + +std::string StringFromInt(int value) +{ + char temp[16]; + sprintf(temp, "%i", value); + return temp; +} + +std::string StringFromBool(bool value) +{ + return value ? "True" : "False"; +} + +// Turns " hej " into "hej". Also handles tabs. +std::string StripSpaces(const std::string &str) +{ + const size_t s = str.find_first_not_of(" \t\r\n"); + + if (str.npos != s) + return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1); + else + return ""; +} + +// "\"hello\"" is turned to "hello" +// This one assumes that the string has already been space stripped in both +// ends, as done by StripSpaces above, for example. +std::string StripQuotes(const std::string& s) +{ + if (s.size() && '\"' == s[0] && '\"' == *s.rbegin()) + return s.substr(1, s.size() - 2); + else + return s; +} + +// For Debugging. Read out an u8 array. +std::string ArrayToString(const uint8_t *data, uint32_t size, int line_len, bool spaces) +{ + std::ostringstream oss; + oss << std::setfill('0') << std::hex; + + for (int line = 0; size; ++data, --size) + { + oss << std::setw(2) << (int)*data; + if (line_len == ++line) + { + oss << '\n'; + line = 0; + } + else if (spaces) + oss << ' '; + } + + return oss.str(); +} + +bool TryParse(const std::string &str, uint32_t *const output) +{ + char *endptr = NULL; + + // Holy crap this is ugly. + + // Reset errno to a value other than ERANGE + errno = 0; + + unsigned long value = strtoul(str.c_str(), &endptr, 0); + + if (!endptr || *endptr) + return false; + + if (errno == ERANGE) + return false; + + if (ULONG_MAX > UINT_MAX) { +#ifdef _MSC_VER +#pragma warning (disable:4309) +#endif + // Note: The typecasts avoid GCC warnings when long is 32 bits wide. + if (value >= static_cast(0x100000000ull) + && value <= static_cast(0xFFFFFFFF00000000ull)) + return false; + } + + *output = static_cast(value); + return true; +} + +bool TryParse(const std::string &str, bool *const output) +{ + if ("1" == str || !strcasecmp("true", str.c_str())) + *output = true; + else if ("0" == str || !strcasecmp("false", str.c_str())) + *output = false; + else + return false; + + return true; +} + +void SplitString(const std::string& str, const char delim, std::vector& output) +{ + std::istringstream iss(str); + output.resize(1); + + while (std::getline(iss, *output.rbegin(), delim)) + output.push_back(""); + + output.pop_back(); +} diff --git a/base/stringutil.h b/base/stringutil.h index d34ce12de0..026c2d0ff3 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "base/basictypes.h" @@ -55,6 +57,45 @@ public: bool operator ==(const ConstString &other) const { return ptr_ == other.ptr_ || !strcmp(ptr_, other.ptr_); } + const char *get() const { return ptr_; } private: const char *ptr_; }; + +std::string StringFromFormat(const char* format, ...); +std::string StringFromInt(int value); +std::string StringFromBool(bool value); + +std::string ArrayToString(const uint8_t *data, uint32_t size, int line_len = 20, bool spaces = true); + +std::string StripSpaces(const std::string &s); +std::string StripQuotes(const std::string &s); + +bool TryParse(const std::string &str, bool *const output); +bool TryParse(const std::string &str, uint32_t *const output); + +template +static bool TryParse(const std::string &str, N *const output) +{ + std::istringstream iss(str); + + N tmp = 0; + if (iss >> tmp) + { + *output = tmp; + return true; + } + else + return false; +} +void SplitString(const std::string& str, const char delim, std::vector& output); + + +template +static std::string ValueToString(const N value) +{ + std::stringstream string; + string << value; + return string.str(); +} + diff --git a/file/ini_file.cpp b/file/ini_file.cpp new file mode 100644 index 0000000000..e576289138 --- /dev/null +++ b/file/ini_file.cpp @@ -0,0 +1,580 @@ +// IniFile +// Taken from Dolphin but relicensed by me, Henrik Rydgard, under the MIT +// license as I wrote the whole thing originally and it has barely changed. + +#include +#include + +#ifndef _MSC_VER +#include +#endif + +#include +#include +#include +#include +#include + +#include "base/stringutil.h" +#include "file/ini_file.h" + +namespace { + +#ifdef _WIN32 + // Function Cross-Compatibility +#define strcasecmp _stricmp +#endif + +// Ugh, this is ugly. +static bool ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) +{ + int FirstEquals = (int)line.find("=", 0); + int FirstCommentChar = -1; + + // Comments + if (FirstCommentChar < 0) + FirstCommentChar = + (int)line.find("#", FirstEquals > 0 ? FirstEquals : 0); + if (FirstCommentChar < 0 && line[0] == ';') + FirstCommentChar = 0; + + // Allow preservation of spacing before comment + if (FirstCommentChar > 0) + { + while (line[FirstCommentChar - 1] == ' ' || line[FirstCommentChar - 1] == 9) // 9 == tab + { + FirstCommentChar--; + } + } + + if ((FirstEquals >= 0) && ((FirstCommentChar < 0) || (FirstEquals < FirstCommentChar))) + { + // Yes, a valid key/value line! + *keyOut = StripSpaces(line.substr(0, FirstEquals)); + if (commentOut) *commentOut = FirstCommentChar > 0 ? line.substr(FirstCommentChar) : std::string(""); + if (valueOut) *valueOut = StripQuotes(StripSpaces(line.substr(FirstEquals + 1, FirstCommentChar - FirstEquals - 1))); + return true; + } + return false; +} + +} + +std::string* IniFile::Section::GetLine(const char* key, std::string* valueOut, std::string* commentOut) +{ + for (std::vector::iterator iter = lines.begin(); iter != lines.end(); ++iter) + { + std::string& line = *iter; + std::string lineKey; + ParseLine(line, &lineKey, valueOut, commentOut); + if (!strcasecmp(lineKey.c_str(), key)) + return &line; + } + return 0; +} + +void IniFile::Section::Set(const char* key, const char* newValue) +{ + std::string value, commented; + std::string* line = GetLine(key, &value, &commented); + if (line) + { + // Change the value - keep the key and comment + *line = StripSpaces(key) + " = " + newValue + commented; + } + else + { + // The key did not already exist in this section - let's add it. + lines.push_back(std::string(key) + " = " + newValue); + } +} + +void IniFile::Section::Set(const char* key, const std::string& newValue, const std::string& defaultValue) +{ + if (newValue != defaultValue) + Set(key, newValue); + else + Delete(key); +} + +bool IniFile::Section::Get(const char* key, std::string* value, const char* defaultValue) +{ + std::string* line = GetLine(key, value, 0); + if (!line) + { + if (defaultValue) + { + *value = defaultValue; + } + return false; + } + return true; +} + +void IniFile::Section::Set(const char* key, const float newValue, const float defaultValue) +{ + if (newValue != defaultValue) + Set(key, newValue); + else + Delete(key); +} + +void IniFile::Section::Set(const char* key, int newValue, int defaultValue) +{ + if (newValue != defaultValue) + Set(key, newValue); + else + Delete(key); +} + +void IniFile::Section::Set(const char* key, bool newValue, bool defaultValue) +{ + if (newValue != defaultValue) + Set(key, newValue); + else + Delete(key); +} + +void IniFile::Section::Set(const char* key, const std::vector& newValues) +{ + std::string temp; + // Join the strings with , + std::vector::const_iterator it; + for (it = newValues.begin(); it != newValues.end(); ++it) + { + temp += (*it) + ","; + } + // remove last , + if (temp.length()) + temp.resize(temp.length() - 1); + Set(key, temp.c_str()); +} + +bool IniFile::Section::Get(const char* key, std::vector& values) +{ + std::string temp; + bool retval = Get(key, &temp, 0); + if (!retval || temp.empty()) + { + return false; + } + // ignore starting , if any + size_t subStart = temp.find_first_not_of(","); + size_t subEnd; + + // split by , + while (subStart != std::string::npos) { + + // Find next , + subEnd = temp.find_first_of(",", subStart); + if (subStart != subEnd) + // take from first char until next , + values.push_back(StripSpaces(temp.substr(subStart, subEnd - subStart))); + + // Find the next non , char + subStart = temp.find_first_not_of(",", subEnd); + } + + return true; +} + +bool IniFile::Section::Get(const char* key, int* value, int defaultValue) +{ + std::string temp; + bool retval = Get(key, &temp, 0); + if (retval && TryParse(temp.c_str(), value)) + return true; + *value = defaultValue; + return false; +} + +bool IniFile::Section::Get(const char* key, uint32_t* value, uint32_t defaultValue) +{ + std::string temp; + bool retval = Get(key, &temp, 0); + if (retval && TryParse(temp, value)) + return true; + *value = defaultValue; + return false; +} + +bool IniFile::Section::Get(const char* key, bool* value, bool defaultValue) +{ + std::string temp; + bool retval = Get(key, &temp, 0); + if (retval && TryParse(temp.c_str(), value)) + return true; + *value = defaultValue; + return false; +} + +bool IniFile::Section::Get(const char* key, float* value, float defaultValue) +{ + std::string temp; + bool retval = Get(key, &temp, 0); + if (retval && TryParse(temp.c_str(), value)) + return true; + *value = defaultValue; + return false; +} + +bool IniFile::Section::Get(const char* key, double* value, double defaultValue) +{ + std::string temp; + bool retval = Get(key, &temp, 0); + if (retval && TryParse(temp.c_str(), value)) + return true; + *value = defaultValue; + return false; +} + +bool IniFile::Section::Exists(const char *key) const +{ + for (std::vector::const_iterator iter = lines.begin(); iter != lines.end(); ++iter) + { + std::string lineKey; + ParseLine(*iter, &lineKey, NULL, NULL); + if (!strcasecmp(lineKey.c_str(), key)) + return true; + } + return false; +} + +std::map IniFile::Section::ToMap() const +{ + std::map outMap; + for (std::vector::const_iterator iter = lines.begin(); iter != lines.end(); ++iter) + { + std::string lineKey, lineValue; + if (ParseLine(*iter, &lineKey, &lineValue, NULL)) { + outMap[lineKey] = lineValue; + } + } + return outMap; +} + + +bool IniFile::Section::Delete(const char *key) +{ + std::string* line = GetLine(key, 0, 0); + for (std::vector::iterator liter = lines.begin(); liter != lines.end(); ++liter) + { + if (line == &*liter) + { + lines.erase(liter); + return true; + } + } + return false; +} + +// IniFile + +const IniFile::Section* IniFile::GetSection(const char* sectionName) const +{ + for (std::vector
::const_iterator iter = sections.begin(); iter != sections.end(); ++iter) + if (!strcasecmp(iter->name().c_str(), sectionName)) + return (&(*iter)); + return 0; +} + +IniFile::Section* IniFile::GetSection(const char* sectionName) +{ + for (std::vector
::iterator iter = sections.begin(); iter != sections.end(); ++iter) + if (!strcasecmp(iter->name().c_str(), sectionName)) + return (&(*iter)); + return 0; +} + +IniFile::Section* IniFile::GetOrCreateSection(const char* sectionName) +{ + Section* section = GetSection(sectionName); + if (!section) + { + sections.push_back(Section(sectionName)); + section = §ions[sections.size() - 1]; + } + return section; +} + +bool IniFile::DeleteSection(const char* sectionName) +{ + Section* s = GetSection(sectionName); + if (!s) + return false; + for (std::vector
::iterator iter = sections.begin(); iter != sections.end(); ++iter) + { + if (&(*iter) == s) + { + sections.erase(iter); + return true; + } + } + return false; +} + +bool IniFile::Exists(const char* sectionName, const char* key) const +{ + const Section* section = GetSection(sectionName); + if (!section) + return false; + return section->Exists(key); +} + +void IniFile::SetLines(const char* sectionName, const std::vector &lines) +{ + Section* section = GetOrCreateSection(sectionName); + section->lines.clear(); + for (std::vector::const_iterator iter = lines.begin(); iter != lines.end(); ++iter) + { + section->lines.push_back(*iter); + } +} + +bool IniFile::DeleteKey(const char* sectionName, const char* key) +{ + Section* section = GetSection(sectionName); + if (!section) + return false; + std::string* line = section->GetLine(key, 0, 0); + for (std::vector::iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter) + { + if (line == &(*liter)) + { + section->lines.erase(liter); + return true; + } + } + return false; //shouldn't happen +} + +// Return a list of all keys in a section +bool IniFile::GetKeys(const char* sectionName, std::vector& keys) const +{ + const Section* section = GetSection(sectionName); + if (!section) + return false; + keys.clear(); + for (std::vector::const_iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter) + { + std::string key; + ParseLine(*liter, &key, 0, 0); + keys.push_back(key); + } + return true; +} + +// Return a list of all lines in a section +bool IniFile::GetLines(const char* sectionName, std::vector& lines, const bool remove_comments) const +{ + const Section* section = GetSection(sectionName); + if (!section) + return false; + + lines.clear(); + for (std::vector::const_iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter) + { + std::string line = StripSpaces(*iter); + + if (remove_comments) + { + int commentPos = (int)line.find('#'); + if (commentPos == 0) + { + continue; + } + + if (commentPos != (int)std::string::npos) + { + line = StripSpaces(line.substr(0, commentPos)); + } + } + + lines.push_back(line); + } + + return true; +} + + +void IniFile::SortSections() +{ + std::sort(sections.begin(), sections.end()); +} + +bool IniFile::Load(const char* filename) +{ + // Maximum number of letters in a line + static const int MAX_BYTES = 1024*32; + + sections.clear(); + sections.push_back(Section("")); + // first section consists of the comments before the first real section + + // Open file + std::ifstream in; + in.open(filename, std::ios::in); + + if (in.fail()) return false; + + while (!in.eof()) + { + char templine[MAX_BYTES]; + in.getline(templine, MAX_BYTES); + std::string line = templine; + + // Remove UTF-8 byte order marks. + if (line.substr(0, 3) == "\xEF\xBB\xBF") + line = line.substr(3); + +#ifndef _WIN32 + // Check for CRLF eol and convert it to LF + if (!line.empty() && line.at(line.size()-1) == '\r') + { + line.erase(line.size()-1); + } +#endif + + if (in.eof()) break; + + if (line.size() > 0) + { + if (line[0] == '[') + { + size_t endpos = line.find("]"); + + if (endpos != std::string::npos) + { + // New section! + std::string sub = line.substr(1, endpos - 1); + sections.push_back(Section(sub)); + + if (endpos + 1 < line.size()) + { + sections[sections.size() - 1].comment = line.substr(endpos + 1); + } + } + } + else + { + sections[sections.size() - 1].lines.push_back(line); + } + } + } + + in.close(); + return true; +} + +bool IniFile::Save(const char* filename) +{ + std::ofstream out; + out.open(filename, std::ios::out); + + if (out.fail()) + { + return false; + } + + // UTF-8 byte order mark. To make sure notepad doesn't go nuts. + out << "\xEF\xBB\xBF"; + + // Currently testing if dolphin community can handle the requirements of C++11 compilation + // If you get a compiler error on this line, your compiler is probably old. + // Update to g++ 4.4 or a recent version of clang (XCode 4.2 on OS X). + // If you don't want to update, complain in a google code issue, the dolphin forums or #dolphin-emu. + for (std::vector
::iterator iter = sections.begin(); iter != sections.end(); ++iter) + { + const Section& section = *iter; + + if (section.name() != "") + { + out << "[" << section.name() << "]" << section.comment << std::endl; + } + + for (std::vector::const_iterator liter = section.lines.begin(); liter != section.lines.end(); ++liter) + { + std::string s = *liter; + out << s << std::endl; + } + } + + out.close(); + return true; +} + + +bool IniFile::Get(const char* sectionName, const char* key, std::string* value, const char* defaultValue) +{ + Section* section = GetSection(sectionName); + if (!section) { + if (defaultValue) { + *value = defaultValue; + } + return false; + } + return section->Get(key, value, defaultValue); +} + +bool IniFile::Get(const char *sectionName, const char* key, std::vector& values) +{ + Section *section = GetSection(sectionName); + if (!section) + return false; + return section->Get(key, values); +} + +bool IniFile::Get(const char* sectionName, const char* key, int* value, int defaultValue) +{ + Section *section = GetSection(sectionName); + if (!section) { + *value = defaultValue; + return false; + } else { + return section->Get(key, value, defaultValue); + } +} + +bool IniFile::Get(const char* sectionName, const char* key, uint32_t* value, uint32_t defaultValue) +{ + Section *section = GetSection(sectionName); + if (!section) { + *value = defaultValue; + return false; + } else { + return section->Get(key, value, defaultValue); + } +} + +bool IniFile::Get(const char* sectionName, const char* key, bool* value, bool defaultValue) +{ + Section *section = GetSection(sectionName); + if (!section) { + *value = defaultValue; + return false; + } else { + return section->Get(key, value, defaultValue); + } +} + + +// Unit test. TODO: Move to the real unit test framework. +/* + int main() + { + IniFile ini; + ini.Load("my.ini"); + ini.Set("Hej", "A", "amaskdfl"); + ini.Set("Mossa", "A", "amaskdfl"); + ini.Set("Aissa", "A", "amaskdfl"); + //ini.Read("my.ini"); + std::string x; + ini.Get("Hej", "B", &x, "boo"); + ini.DeleteKey("Mossa", "A"); + ini.DeleteSection("Mossa"); + ini.SortSections(); + ini.Save("my.ini"); + //UpdateVars(ini); + return 0; + } + */ diff --git a/file/ini_file.h b/file/ini_file.h new file mode 100644 index 0000000000..fbf63e0328 --- /dev/null +++ b/file/ini_file.h @@ -0,0 +1,179 @@ +// IniFile +// Taken from Dolphin but relicensed by me, Henrik Rydgard, under the MIT +// license as I wrote the whole thing originally and it has barely changed. + +#pragma once + +#include +#include +#include + +#include "base/stringutil.h" + +class IniFile +{ +public: + class Section + { + friend class IniFile; + + public: + Section() {} + Section(const std::string& name) : name_(name) {} + + bool Exists(const char *key) const; + bool Delete(const char *key); + + std::map ToMap() const; + + std::string* GetLine(const char* key, std::string* valueOut, std::string* commentOut); + void Set(const char* key, const char* newValue); + void Set(const char* key, const std::string& newValue, const std::string& defaultValue); + + void Set(const std::string &key, const std::string &value) { + Set(key.c_str(), value.c_str()); + } + bool Get(const char* key, std::string* value, const char* defaultValue); + + void Set(const char* key, uint32_t newValue) { + Set(key, StringFromFormat("0x%08x", newValue).c_str()); + } + void Set(const char* key, float newValue) { + Set(key, StringFromFormat("%f", newValue).c_str()); + } + void Set(const char* key, const float newValue, const float defaultValue); + void Set(const char* key, double newValue) { + Set(key, StringFromFormat("%f", newValue).c_str()); + } + + void Set(const char* key, int newValue, int defaultValue); + void Set(const char* key, int newValue) { + Set(key, StringFromInt(newValue).c_str()); + } + + void Set(const char* key, bool newValue, bool defaultValue); + void Set(const char* key, bool newValue) { + Set(key, StringFromBool(newValue).c_str()); + } + void Set(const char* key, const std::vector& newValues); + + template + void Set(const char* key, const std::map& newValues) + { + std::vector temp; + for(typename std::map::const_iterator it = newValues.begin(); it != newValues.end(); it++) + { + temp.push_back(ValueToString(it->first)+"_"+ValueToString(it->second)); + } + Set(key,temp); + } + + bool Get(const char* key, int* value, int defaultValue = 0); + bool Get(const char* key, uint32_t* value, uint32_t defaultValue = 0); + bool Get(const char* key, bool* value, bool defaultValue = false); + bool Get(const char* key, float* value, float defaultValue = false); + bool Get(const char* key, double* value, double defaultValue = false); + bool Get(const char* key, std::vector& values); + template + bool Get(const char* key, std::map& values) + { + std::vector temp; + if(!Get(key,temp)) + { + return false; + } + values.clear(); + for(size_t i = 0; i < temp.size(); i++) + { + std::vector key_val; + SplitString(temp[i],'_',key_val); + if(key_val.size() < 2) + continue; + U mapKey; + V mapValue; + if(!TryParse(key_val[0],&mapKey)) + continue; + if(!TryParse(key_val[1],&mapValue)) + continue; + values[mapKey] = mapValue; + } + return true; + } + + bool operator < (const Section& other) const { + return name_ < other.name_; + } + + const std::string &name() const { + return name_; + } + + protected: + std::vector lines; + std::string name_; + std::string comment; + }; + + bool Load(const char* filename); + bool Load(const std::string &filename) { return Load(filename.c_str()); } + bool Save(const char* filename); + bool Save(const std::string &filename) { return Save(filename.c_str()); } + + // Returns true if key exists in section + bool Exists(const char* sectionName, const char* key) const; + + // TODO: Get rid of these, in favor of the Section ones. + void Set(const char* sectionName, const char* key, const char* newValue) { + GetOrCreateSection(sectionName)->Set(key, newValue); + } + void Set(const char* sectionName, const char* key, const std::string& newValue) { + GetOrCreateSection(sectionName)->Set(key, newValue.c_str()); + } + void Set(const char* sectionName, const char* key, int newValue) { + GetOrCreateSection(sectionName)->Set(key, newValue); + } + void Set(const char* sectionName, const char* key, uint32_t newValue) { + GetOrCreateSection(sectionName)->Set(key, newValue); + } + void Set(const char* sectionName, const char* key, bool newValue) { + GetOrCreateSection(sectionName)->Set(key, newValue); + } + void Set(const char* sectionName, const char* key, const std::vector& newValues) { + GetOrCreateSection(sectionName)->Set(key, newValues); + } + + // TODO: Get rid of these, in favor of the Section ones. + bool Get(const char* sectionName, const char* key, std::string* value, const char* defaultValue = ""); + bool Get(const char* sectionName, const char* key, int* value, int defaultValue = 0); + bool Get(const char* sectionName, const char* key, uint32_t* value, uint32_t defaultValue = 0); + bool Get(const char* sectionName, const char* key, bool* value, bool defaultValue = false); + bool Get(const char* sectionName, const char* key, std::vector& values); + + template bool GetIfExists(const char* sectionName, const char* key, T value) + { + if (Exists(sectionName, key)) + return Get(sectionName, key, value); + return false; + } + + bool GetKeys(const char* sectionName, std::vector& keys) const; + + void SetLines(const char* sectionName, const std::vector &lines); + bool GetLines(const char* sectionName, std::vector& lines, const bool remove_comments = true) const; + + bool DeleteKey(const char* sectionName, const char* key); + bool DeleteSection(const char* sectionName); + + void SortSections(); + const std::vector
&Sections() { return sections; } + + Section* GetOrCreateSection(const char* section); + +private: + std::vector
sections; + + const Section* GetSection(const char* section) const; + Section* GetSection(const char* section); + std::string* GetLine(const char* section, const char* key); + void CreateSection(const char* section); +}; diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index aa5017aa0d..51bc62bad7 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -397,6 +397,8 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co continue; } const AtlasChar *ch = atlasfont.getChar(cval); + if (!ch) + ch = atlasfont.getChar('?'); if (ch) { const AtlasChar &c = *ch; float cx1, cy1, cx2, cy2; diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp new file mode 100644 index 0000000000..8dfb50faf8 --- /dev/null +++ b/i18n/i18n.cpp @@ -0,0 +1,105 @@ +#include "i18n/i18n.h" +#include "file/ini_file.h" + +I18NRepo i18nrepo; + +I18NRepo::~I18NRepo() { + Clear(); +} + +void I18NRepo::Clear() { + for (auto iter = cats_.begin(); iter != cats_.end(); ++iter) { + delete iter->second; + } + cats_.clear(); +} + +const char *I18NCategory::T(const char *key, const char *def) { + auto iter = map_.find(key); + if (iter != map_.end()) { + return iter->second.text.c_str(); + } else { + if (def) + missedKeyLog_[key] = def; + else + missedKeyLog_[key] = key; + return def ? def : key; + } +} + +void I18NCategory::SetMap(const std::map &m) { + for (auto iter = m.begin(); iter != m.end(); ++iter) { + if (map_.find(iter->first) == map_.end()) { + map_[iter->first] = I18NEntry(iter->second); + } + } +} + +I18NCategory *I18NRepo::GetCategory(const char *category) { + auto iter = cats_.find(category); + if (iter != cats_.end()) { + return iter->second; + } else { + I18NCategory *c = new I18NCategory(this); + cats_[category] = c; + return c; + } +} + +std::string I18NRepo::GetIniPath(const std::string &languageID) const { + return "lang/" + languageID + ".ini"; +} + +void I18NRepo::LoadIni(const std::string &languageID) { + IniFile ini; + if (!ini.Load(GetIniPath(languageID))) { + return; + } + + Clear(); + + const std::vector §ions = ini.Sections(); + + for (auto iter = sections.begin(); iter != sections.end(); ++iter) { + if (iter->name() != "") { + cats_[iter->name()] = LoadSection(&(*iter)); + } + } +} + +I18NCategory *I18NRepo::LoadSection(const IniFile::Section *section) { + I18NCategory *cat = new I18NCategory(this); + std::map sectionMap = section->ToMap(); + cat->SetMap(sectionMap); + return cat; +} + +// This is a very light touched save variant - it won't overwrite +// anything, only create new entries. +void I18NRepo::SaveIni(const std::string &languageID) { + IniFile ini; + ini.Load(GetIniPath(languageID)); + for (auto iter = cats_.begin(); iter != cats_.end(); ++iter) { + std::string categoryName = iter->first; + IniFile::Section *section = ini.GetOrCreateSection(categoryName.c_str()); + SaveSection(ini, section, iter->second); + } + ini.Save(GetIniPath(languageID)); +} + +void I18NRepo::SaveSection(IniFile &ini, IniFile::Section *section, I18NCategory *cat) { + const std::map &missed = cat->Missed(); + + for (auto iter = missed.begin(); iter != missed.end(); ++iter) { + if (!section->Exists(iter->first.c_str())) { + section->Set(iter->first, iter->second); + } + } + + const std::map &entries = cat->GetMap(); + for (auto iter = entries.begin(); iter != entries.end(); ++iter) { + section->Set(iter->first, iter->second.text); + } + + cat->ClearMissed(); +} diff --git a/i18n/i18n.h b/i18n/i18n.h new file mode 100644 index 0000000000..41fb833c2c --- /dev/null +++ b/i18n/i18n.h @@ -0,0 +1,95 @@ +#pragma once + +// I18N = I....18..dots.....N = INTERNATIONALIZATION + +// Super simple I18N library. +// Just enough to be useful and usable. +// Spits out easy-to-edit utf-8 .INI files. + +// As usual, everything is UTF-8. Nothing else allowed. + +#include +#include +#include + +#include "base/stringutil.h" +#include "file/ini_file.h" + +// Reasonably thread safe. + +class I18NRepo; + +struct I18NEntry { + I18NEntry(const std::string &t) : text(t), readFlag(false) {} + I18NEntry() : readFlag(false) {} + std::string text; + bool readFlag; +}; + +struct I18NCandidate { + I18NCandidate() : key(0), defVal(0) {} + I18NCandidate(const char *k, const char *d) : key(k), defVal(d) {} + const char *key; + const char *defVal; +}; + +class I18NCategory { +public: + const char *T(const char *key, const char *def = 0); + + const std::map &Missed() const { + return missedKeyLog_; + } + + void SetMap(const std::map &m); + const std::map &GetMap() { return map_; } + void ClearMissed() { missedKeyLog_.clear(); } + +private: + I18NCategory(I18NRepo *repo) {} + + std::map map_; + std::map missedKeyLog_; + + // Noone else can create these. + friend class I18NRepo; + + DISALLOW_COPY_AND_ASSIGN(I18NCategory); +}; + +class I18NRepo { +public: + I18NRepo() {} + ~I18NRepo(); + + void LoadIni(const std::string &languageID); // NOT the filename! + void SaveIni(const std::string &languageID); + + I18NCategory *GetCategory(const char *categoryName); + const char *T(const char *category, const char *key, const char *def = 0); + +private: + std::string GetIniPath(const std::string &languageID) const; + void Clear(); + I18NCategory *LoadSection(const IniFile::Section *section); + void SaveSection(IniFile &ini, IniFile::Section *section, I18NCategory *cat); + + std::map cats_; + + DISALLOW_COPY_AND_ASSIGN(I18NRepo); +}; + +extern I18NRepo i18nrepo; + +// These are simply talking to the one global instance of I18NRepo. + +inline I18NCategory *GetI18NCategory(const char *categoryName) { + return i18nrepo.GetCategory(categoryName); +} + +inline const char *T(const char *category, const char *key, const char *def = 0) { + return i18nrepo.T(category, key, def); +} + + + diff --git a/native.vcxproj b/native.vcxproj index b9aa090825..2366edce00 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -211,6 +211,7 @@ + @@ -223,6 +224,7 @@ + @@ -305,6 +307,7 @@ + @@ -316,6 +319,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 3b902f1bd9..af6190b45d 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -245,6 +245,12 @@ thread + + i18n + + + file + @@ -432,6 +438,12 @@ thread + + i18n + + + file + @@ -494,5 +506,8 @@ {caa41117-1d90-47cc-9fba-f7e670e315a3} + + {02e8ef95-82c7-4420-b029-a189a5e0fcbd} + \ No newline at end of file diff --git a/ui/ui.cpp b/ui/ui.cpp index eb2c69c903..301fc9cda8 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -286,9 +286,13 @@ int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w } // Render button - const int dropsize = 10; + int dropsize = 10; if (drop_shadow && texture) { + if (txOffset) { + dropsize = 3; + y += txOffset * 2; + } ui_draw2d.DrawImage4Grid(drop_shadow, x - dropsize, y, x+w + dropsize, y+h+dropsize*1.5, alphaMul(color,0.5f), 1.0f); ui_draw2d.Flush(true); From 43b78be9dd5d343a2133e42501ba9b56552c9d4e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Apr 2013 11:57:22 +0200 Subject: [PATCH 0345/1445] Update android.mk --- Android.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Android.mk b/Android.mk index 29a7993e5c..2241f43cb8 100644 --- a/Android.mk +++ b/Android.mk @@ -28,8 +28,10 @@ LOCAL_SRC_FILES :=\ file/easy_file.cpp \ file/chunk_file.cpp \ file/file_util.cpp \ + file/ini_file.cpp \ file/zip_read.cpp \ json/json_writer.cpp \ + i18n/i18n.cpp \ math/math_util.cpp \ math/curves.cpp \ math/lin/aabb.cpp.arm \ From 3494d9282d1319c7ea982f7d6e4fb7687a151046 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Apr 2013 14:40:14 +0200 Subject: [PATCH 0346/1445] Kanji stuff --- gfx/texture_atlas.cpp | 6 +- tools/atlastool.cpp | 97 +- tools/atlastool/atlastool.vcxproj | 3 + tools/kanjifilter.h | 1952 +++++++++++++++++++++++++++++ ui/ui.h | 1 - 5 files changed, 2037 insertions(+), 22 deletions(-) create mode 100644 tools/kanjifilter.h diff --git a/gfx/texture_atlas.cpp b/gfx/texture_atlas.cpp index 628dd7b9c4..275d17f0cb 100644 --- a/gfx/texture_atlas.cpp +++ b/gfx/texture_atlas.cpp @@ -22,7 +22,11 @@ const AtlasImage *Atlas::getImageByName(const char *name) const const AtlasChar *AtlasFont::getChar(int utf32) const { for (int i = 0; i < numRanges; i++) { if (utf32 >= ranges[i].start && utf32 < ranges[i].end) { - return &charData[ranges[i].start_index + utf32 - ranges[i].start]; + const AtlasChar *c = &charData[ranges[i].start_index + utf32 - ranges[i].start]; + if (c->ex == 0 && c->ey == 0) + return 0; + else + return c; } } return 0; diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 9b20c174fa..68f1920fa0 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -11,6 +11,8 @@ // line height // dist-per-pixel +#include + #include #include #include FT_FREETYPE_H @@ -25,12 +27,23 @@ #include "image/png_load.h" #include "image/zim_save.h" +#include "kanjifilter.h" + #define CHECK(x) if (!(x)) { printf("%i: CHECK failed on this line\n", __LINE__); exit(1); } using namespace std; static int global_id; static bool highcolor = false; + + + +typedef unsigned short u16; + +struct CharRange : public AtlasCharRange { + std::set filter; +}; + enum Effect { FX_COPY = 0, FX_RED_TO_ALPHA_SOLID_WHITE = 1, // for alpha fonts @@ -197,15 +210,18 @@ struct Bucket { dest.resize(image_width, 1); sort(items.begin(), items.end()); for (int i = 0; i < (int)items.size(); i++) { + if ((i + 1) % 200 == 0) { + printf("Resolving (%i / %i)\n", i, (int)items.size()); + } int idx = items[i].first.dat[0].size(); int idy = items[i].first.dat.size(); - if (idx > 0 && idy > 0) { + if (idx > 1 && idy > 1) { CHECK(idx <= image_width); bool found = false; for (int ty = 0; ty < 2047 && !found; ty++) { if(ty + idy + 1 > (int)dest.dat.size()) { - masq.resize(image_width, ty + idy + 1); - dest.resize(image_width, ty + idy + 1); + masq.resize(image_width, ty + idy + 16); + dest.resize(image_width, ty + idy + 16); } // Brute force packing. int sz = (int)items[i].first.dat[0].size(); @@ -239,7 +255,7 @@ skip: } } - if ((int)dest.dat.size() > image_width) { + if ((int)dest.dat.size() > image_width * 2) { printf("PACKING FAIL : height=%i", (int)dest.dat.size()); exit(1); } @@ -281,7 +297,7 @@ struct Closest { } }; -void RasterizeFont(const char *fontfile, std::vector &ranges, int fontsize, float *metrics_height, Bucket *bucket) { +void RasterizeFont(const char *fontfile, std::vector &ranges, int fontsize, float *metrics_height, Bucket *bucket) { FT_Library freetype; CHECK(FT_Init_FreeType(&freetype) == 0); @@ -299,8 +315,13 @@ void RasterizeFont(const char *fontfile, std::vector &ranges, in for (size_t r = 0; r < ranges.size(); r++) { ranges[r].start_index = global_id; for(int kar = ranges[r].start; kar < ranges[r].end; kar++) { + bool filtered = false; + if (ranges[r].filter.size()) { + if (ranges[r].filter.find((u16)kar) == ranges[r].filter.end()) + filtered = true; + } Image img; - if (0 != FT_Load_Char(font, kar, FT_LOAD_RENDER|FT_LOAD_MONOCHROME)) { + if (filtered || 0 != FT_Load_Char(font, kar, FT_LOAD_RENDER|FT_LOAD_MONOCHROME)) { img.resize(1, 1); Data dat; @@ -426,7 +447,7 @@ struct FontDesc { float metrics_height; - std::vector ranges; + std::vector ranges; FontDesc() { @@ -453,7 +474,7 @@ struct FontDesc { fprintf(fil, "// RANGE: 0x%x - 0x%x, start 0x%x\n", ranges[r].start, ranges[r].end, ranges[r].start_index); for (int i = ranges[r].start; i < ranges[r].end; i++) { int idx = i - ranges[r].start + ranges[r].start_index; - fprintf(fil, " {%ff, %ff, %ff, %ff, %1.4ff, %1.4ff, %1.4ff, %i, %i}, // %i\n", + fprintf(fil, " {%ff, %ff, %ff, %ff, %1.4ff, %1.4ff, %1.4ff, %i, %i}, // %04x\n", /*results[i].id, */ results[idx].sx / tw, results[idx].sy / th, @@ -524,25 +545,55 @@ struct ImageDesc { } }; -AtlasCharRange range(int start, int end) { - AtlasCharRange r = {start, end, 0}; + +CharRange range(int start, int end, const std::set &filter) { + CharRange r; + r.start = start; + r.end = end + 1; + r.start_index = 0; + r.filter = filter; return r; } -void GetLocales(const char *locales, std::vector &ranges) +CharRange range(int start, int end) { + CharRange r; + r.start = start; + r.end = end + 1; + r.start_index = 0; + return r; +} + +inline bool operator <(const CharRange &a, const CharRange &b) { + // These ranges should never overlap so this should be enough. + return a.start < b.start; +} + +void GetLocales(const char *locales, std::vector &ranges) { + std::set kanji; + for (int i = 0; i < sizeof(kanjiFilter)/sizeof(kanjiFilter[0]); i+=2) + { + // TODO: learning level check? + if (kanjiFilter[i+1] > 0) { + kanji.insert(kanjiFilter[i]); + } + } + // The end point of a range is now inclusive! + for (size_t i = 0; i < strlen(locales); i++) { switch (locales[i]) { case 'U': // US ASCII - ranges.push_back(range(32, 128)); + ranges.push_back(range(32, 127)); break; case 'W': // Latin-1 extras 1 - ranges.push_back(range(0x80, 0x81)); // euro sign + ranges.push_back(range(0x80, 0x80)); // euro sign ranges.push_back(range(0xA2, 0xFF)); // 80 - A0 appears to contain nothing interesting - ranges.push_back(range(0x2122, 0x2123)); // trademark symbol + ranges.push_back(range(0x2122, 0x2122)); // trademark symbol break; case 'k': // Katakana ranges.push_back(range(0x30A0, 0x30FF)); + ranges.push_back(range(0x31F0, 0x31FF)); + // ranges.push_back(range(0xFF00, 0xFFEF)); // half-width ascii break; case 'h': // Hiragana ranges.push_back(range(0x3041, 0x3097)); @@ -554,10 +605,17 @@ void GetLocales(const char *locales, std::vector &ranges) case 'G': // Greek ranges.push_back(range(0x0370, 0x03FF)); break; - case 'c': // Kanji + case 'R': // Russian + ranges.push_back(range(0x0400, 0x04FF)); + break; + case 'c': // Japanese Kanji + ranges.push_back(range(0x4E00, 0x9F92, kanji)); break; } } + + ranges.push_back(range(0xFFFD, 0xFFFD)); + std::sort(ranges.begin(), ranges.end()); } int main(int argc, char **argv) { @@ -593,8 +651,7 @@ int main(int argc, char **argv) { if (!fgets(line, 511, script)) break; if (!strlen(line)) break; char *rest = strchr(line, ' '); - if (rest) - { + if (rest) { *rest = 0; rest++; } @@ -608,7 +665,7 @@ int main(int argc, char **argv) { sscanf(rest, "%s %s %s %i", fontname, fontfile, locales, &pixheight); printf("Font: %s (%s) in size %i. Locales: %s\n", fontname, fontfile, pixheight, locales); - std::vector ranges; + std::vector ranges; GetLocales(locales, ranges); printf("locales fetched.\n"); FontDesc fnt; @@ -653,10 +710,10 @@ int main(int argc, char **argv) { vector results = bucket.Resolve(image_width, dest); if (highcolor) { printf("Writing .ZIM %ix%i RGBA8888...\n", dest.width(), dest.height()); - dest.SaveZIM(image_name.c_str(), ZIM_RGBA8888); + dest.SaveZIM(image_name.c_str(), ZIM_RGBA8888 | ZIM_ZLIB_COMPRESSED); } else { printf("Writing .ZIM %ix%i RGBA4444...\n", dest.width(), dest.height()); - dest.SaveZIM(image_name.c_str(), ZIM_RGBA4444); + dest.SaveZIM(image_name.c_str(), ZIM_RGBA4444 | ZIM_ZLIB_COMPRESSED); } // Also save PNG for debugging. printf("Writing .PNG %s\n", (image_name + ".png").c_str()); diff --git a/tools/atlastool/atlastool.vcxproj b/tools/atlastool/atlastool.vcxproj index d7c6770cf8..2cee3d51d5 100644 --- a/tools/atlastool/atlastool.vcxproj +++ b/tools/atlastool/atlastool.vcxproj @@ -99,6 +99,9 @@ {C4DF647E-80EA-4111-A0A8-218B1B711E18} + + + diff --git a/tools/kanjifilter.h b/tools/kanjifilter.h new file mode 100644 index 0000000000..03039b05b0 --- /dev/null +++ b/tools/kanjifilter.h @@ -0,0 +1,1952 @@ +// http://www.tonypottier.info/Unicode_And_Japanese_Kanji/Appendix1.html +// http://www.tonypottier.info/Unicode_And_Japanese_Kanji/Appendix1.html + +// The parameter is the learning order. +const unsigned short kanjiFilter[] = { + 0x4E00, 1, // 侀 + 0x4E01, 3, // 䞁 + 0x4E03, 1, // 䞃 + 0x4E07, 2, // 侇 + 0x4E08, 7, // 䞈 + 0x4E09, 1, // 侉 + 0x4E0A, 1, // 侊 + 0x4E0B, 1, // 例 + 0x4E0D, 4, // 䞍 + 0x4E0E, 7, // 侎 + 0x4E14, 7, // 侔 + 0x4E16, 3, // 侖 + 0x4E18, 7, // 䞘 + 0x4E19, 7, // 侙 + 0x4E21, 3, // äž¡ + 0x4E26, 6, // 䞊 + 0x4E2D, 1, // äž­ + 0x4E38, 2, // äžž + 0x4E39, 7, // äž¹ + 0x4E3B, 3, // äž» + 0x4E45, 5, // 久 + 0x4E4F, 7, // 乏 + 0x4E57, 3, // 乗 + 0x4E59, 7, // 乙 + 0x4E5D, 1, // 九 + 0x4E71, 6, // ä¹± + 0x4E73, 6, // ä¹³ + 0x4E7E, 7, // 也 + 0x4E86, 7, // 了 + 0x4E88, 3, // 予 + 0x4E89, 4, // 争 + 0x4E8B, 3, // 事 + 0x4E8C, 1, // 二 + 0x4E92, 7, // 互 + 0x4E94, 1, // 五 + 0x4E95, 7, // 井 + 0x4E9C, 7, // 亜 + 0x4EA1, 6, // 亡 + 0x4EA4, 2, // 亀 + 0x4EAB, 7, // 享 + 0x4EAC, 2, // 京 + 0x4EAD, 7, // 亭 + 0x4EBA, 1, // 人 + 0x4EC1, 6, // 仁 + 0x4ECA, 2, // 今 + 0x4ECB, 7, // 介 + 0x4ECF, 5, // 仏 + 0x4ED5, 3, // 仕 + 0x4ED6, 3, // 他 + 0x4ED8, 4, // 付 + 0x4ED9, 7, // 仙 + 0x4EE3, 3, // 代 + 0x4EE4, 4, // 什 + 0x4EE5, 4, // 以 + 0x4EEE, 5, // ä»® + 0x4EF0, 7, // ä»° + 0x4EF2, 4, // 仲 + 0x4EF6, 5, // ä»¶ + 0x4EFB, 5, // ä»» + 0x4F01, 7, // 䌁 + 0x4F0F, 7, // 䌏 + 0x4F10, 7, // 䌐 + 0x4F11, 1, // 䌑 + 0x4F1A, 2, // 䌚 + 0x4F1D, 4, // 䌝 + 0x4F2F, 7, // 䌯 + 0x4F34, 7, // 䌎 + 0x4F38, 7, // 䌞 + 0x4F3A, 7, // 䌺 + 0x4F3C, 5, // 䌌 + 0x4F46, 7, // 䜆 + 0x4F4D, 4, // 䜍 + 0x4F4E, 4, // 䜎 + 0x4F4F, 3, // 䜏 + 0x4F50, 7, // 䜐 + 0x4F53, 2, // 䜓 + 0x4F55, 2, // 䜕 + 0x4F59, 5, // 䜙 + 0x4F5C, 2, // 䜜 + 0x4F73, 7, // 䜳 + 0x4F75, 7, // 䜵 + 0x4F7F, 3, // 䜿 + 0x4F8B, 4, // 䟋 + 0x4F8D, 7, // 䟍 + 0x4F9B, 6, // 䟛 + 0x4F9D, 7, // 䟝 + 0x4FA1, 5, // 䟡 + 0x4FAE, 7, // 䟮 + 0x4FAF, 7, // 䟯 + 0x4FB5, 7, // 䟵 + 0x4FBF, 4, // 䟿 + 0x4FC2, 3, // 係 + 0x4FC3, 7, // 促 + 0x4FCA, 7, // 俊 + 0x4FD7, 7, // 俗 + 0x4FDD, 5, // 保 + 0x4FE1, 4, // ä¿¡ + 0x4FEE, 5, // ä¿® + 0x4FF3, 6, // 俳 + 0x4FF5, 5, // 俵 + 0x4FF8, 7, // 俞 + 0x5009, 4, // 倉 + 0x500B, 5, // 個 + 0x500D, 3, // 倍 + 0x5012, 7, // 倒 + 0x5019, 4, // 候 + 0x501F, 4, // 借 + 0x5023, 7, // 倣 + 0x5024, 6, // 倀 + 0x502B, 7, // 倫 + 0x5039, 7, // 倹 + 0x5049, 7, // 偉 + 0x504F, 7, // 偏 + 0x505C, 4, // 停 + 0x5065, 4, // 健 + 0x5074, 4, // 偎 + 0x5075, 7, // 偵 + 0x5076, 7, // 偶 + 0x507D, 7, // 停 + 0x508D, 7, // 傍 + 0x5091, 7, // 傑 + 0x5098, 7, // 傘 + 0x5099, 5, // 備 + 0x50AC, 7, // 催 + 0x50B5, 7, // 債 + 0x50B7, 6, // 傷 + 0x50BE, 7, // 傟 + 0x50CD, 4, // 働 + 0x50CF, 5, // 像 + 0x50D5, 7, // 僕 + 0x50DA, 7, // 僚 + 0x50E7, 7, // 僧 + 0x5100, 7, // 儀 + 0x5104, 4, // 億 + 0x5112, 7, // 儒 + 0x511F, 7, // 償 + 0x512A, 6, // 優 + 0x5143, 2, // 元 + 0x5144, 2, // 兄 + 0x5145, 7, // 充 + 0x5146, 4, // 兆 + 0x5148, 1, // 先 + 0x5149, 2, // 光 + 0x514B, 7, // 克 + 0x514D, 7, // 免 + 0x5150, 4, // 児 + 0x515A, 6, // 党 + 0x5165, 1, // 入 + 0x5168, 3, // å…š + 0x516B, 1, // 八 + 0x516C, 2, // 公 + 0x516D, 1, // 六 + 0x5171, 4, // 共 + 0x5175, 4, // 兵 + 0x5177, 3, // 具 + 0x5178, 4, // å…ž + 0x517C, 7, // å…Œ + 0x5185, 2, // 内 + 0x5186, 1, // 円 + 0x518A, 6, // 冊 + 0x518D, 5, // 再 + 0x5192, 7, // 冒 + 0x5197, 7, // 冗 + 0x5199, 3, // 写 + 0x51A0, 7, // 冠 + 0x51AC, 2, // 冬 + 0x51B7, 4, // 冷 + 0x51C6, 7, // 准 + 0x51CD, 7, // 凍 + 0x51DD, 7, // 凝 + 0x51E1, 7, // 凡 + 0x51E6, 6, // 凊 + 0x51F6, 7, // 凶 + 0x51F8, 7, // 凞 + 0x51F9, 7, // 凹 + 0x51FA, 1, // 出 + 0x5200, 2, // 刀 + 0x5203, 7, // 刃 + 0x5206, 2, // 分 + 0x5207, 2, // 切 + 0x5208, 7, // 刈 + 0x520A, 5, // 刊 + 0x5211, 7, // 刑 + 0x5217, 3, // 列 + 0x521D, 4, // 初 + 0x5224, 5, // 刀 + 0x5225, 4, // 別 + 0x5229, 4, // 利 + 0x5230, 7, // 到 + 0x5236, 5, // 制 + 0x5237, 4, // 刷 + 0x5238, 5, // 刞 + 0x523A, 7, // 刺 + 0x523B, 6, // 刻 + 0x5247, 5, // 則 + 0x524A, 7, // 削 + 0x524D, 2, // 前 + 0x5256, 7, // 剖 + 0x525B, 7, // 剛 + 0x5263, 7, // 剣 + 0x5264, 7, // 剀 + 0x526F, 4, // 副 + 0x5270, 7, // 剰 + 0x5272, 6, // 割 + 0x5275, 6, // 創 + 0x5287, 6, // 劇 + 0x529B, 1, // 力 + 0x529F, 4, // 功 + 0x52A0, 4, // 加 + 0x52A3, 7, // 劣 + 0x52A9, 3, // 助 + 0x52AA, 4, // 努 + 0x52B1, 7, // 励 + 0x52B4, 4, // 劎 + 0x52B9, 5, // 効 + 0x52BE, 7, // 功 + 0x52C5, 7, // 勅 + 0x52C7, 4, // 勇 + 0x52C9, 3, // 勉 + 0x52D5, 3, // 動 + 0x52D8, 7, // 勘 + 0x52D9, 5, // 務 + 0x52DD, 3, // 勝 + 0x52DF, 7, // 募 + 0x52E2, 5, // 勢 + 0x52E4, 6, // å‹€ + 0x52E7, 7, // 勧 + 0x52F2, 7, // 勲 + 0x52FA, 7, // 勺 + 0x5301, 7, // 匁 + 0x5305, 4, // 包 + 0x5316, 3, // 化 + 0x5317, 2, // 北 + 0x5320, 7, // 匠 + 0x5339, 7, // 匹 + 0x533A, 3, // 区 + 0x533B, 3, // 医 + 0x533F, 7, // 匿 + 0x5341, 1, // 十 + 0x5343, 1, // 千 + 0x5347, 7, // 升 + 0x5348, 2, // 午 + 0x534A, 2, // 半 + 0x5351, 7, // 卑 + 0x5352, 4, // 卒 + 0x5353, 7, // 卓 + 0x5354, 4, // 協 + 0x5357, 2, // 南 + 0x5358, 4, // 単 + 0x535A, 4, // 博 + 0x5360, 7, // 占 + 0x5370, 4, // 印 + 0x5371, 6, // 危 + 0x5373, 7, // 即 + 0x5374, 7, // 华 + 0x5375, 6, // 卵 + 0x5378, 7, // 卞 + 0x5384, 7, // 厄 + 0x5398, 7, // 厘 + 0x539A, 5, // 厚 + 0x539F, 2, // 原 + 0x53B3, 6, // 厳 + 0x53BB, 3, // 去 + 0x53C2, 4, // 参 + 0x53C8, 7, // 又 + 0x53CA, 7, // 及 + 0x53CB, 2, // 友 + 0x53CC, 7, // 双 + 0x53CD, 3, // 反 + 0x53CE, 6, // 収 + 0x53D4, 7, // 叔 + 0x53D6, 3, // 取 + 0x53D7, 3, // 受 + 0x53D9, 7, // 叙 + 0x53E3, 1, // 口 + 0x53E4, 2, // 叀 + 0x53E5, 5, // 句 + 0x53EB, 7, // 叫 + 0x53EC, 7, // 召 + 0x53EF, 5, // 可 + 0x53F0, 2, // 台 + 0x53F2, 4, // 史 + 0x53F3, 1, // 右 + 0x53F7, 3, // 号 + 0x53F8, 4, // 叞 + 0x5404, 4, // 各 + 0x5408, 2, // 合 + 0x5409, 7, // 吉 + 0x540C, 2, // 同 + 0x540D, 1, // 名 + 0x540E, 6, // 后 + 0x540F, 7, // 吏 + 0x5410, 7, // 吐 + 0x5411, 3, // 向 + 0x541B, 3, // 君 + 0x541F, 7, // 吟 + 0x5426, 6, // 吊 + 0x542B, 7, // 含 + 0x5438, 6, // 吞 + 0x5439, 7, // 吹 + 0x5448, 7, // 呈 + 0x5449, 7, // 呉 + 0x544A, 4, // 告 + 0x5468, 4, // 呚 + 0x5473, 3, // 味 + 0x547C, 6, // 呌 + 0x547D, 3, // 呜 + 0x548C, 3, // 和 + 0x54B2, 7, // 咲 + 0x54C0, 7, // 哀 + 0x54C1, 3, // 品 + 0x54E1, 3, // 員 + 0x54F2, 7, // 哲 + 0x5506, 7, // 唆 + 0x5507, 7, // 唇 + 0x5510, 7, // 唐 + 0x552F, 7, // 唯 + 0x5531, 4, // 唱 + 0x5546, 3, // 商 + 0x554F, 3, // 問 + 0x5553, 7, // 啓 + 0x5584, 6, // 善 + 0x559A, 7, // 喚 + 0x559C, 4, // 喜 + 0x559D, 7, // 喝 + 0x55AA, 7, // 喪 + 0x55AB, 7, // 喫 + 0x55B6, 5, // 営 + 0x55E3, 7, // 嗣 + 0x5606, 7, // 嘆 + 0x5631, 7, // 嘱 + 0x5668, 4, // 噚 + 0x5674, 7, // 噎 + 0x5687, 7, // 嚇 + 0x56DA, 7, // 囚 + 0x56DB, 1, // 四 + 0x56DE, 2, // 回 + 0x56E0, 5, // 因 + 0x56E3, 5, // 団 + 0x56F0, 6, // 困 + 0x56F2, 4, // 囲 + 0x56F3, 2, // 図 + 0x56FA, 4, // 固 + 0x56FD, 2, // 囜 + 0x570F, 7, // 圏 + 0x5712, 2, // 園 + 0x571F, 1, // 土 + 0x5727, 5, // 圧 + 0x5728, 5, // 圚 + 0x5730, 2, // 地 + 0x5742, 3, // 坂 + 0x5747, 5, // 均 + 0x574A, 7, // 坊 + 0x5751, 7, // 坑 + 0x576A, 7, // 坪 + 0x5782, 6, // 垂 + 0x578B, 4, // 型 + 0x57A3, 7, // 垣 + 0x57CB, 7, // 埋 + 0x57CE, 6, // 城 + 0x57DF, 6, // 域 + 0x57F7, 7, // 執 + 0x57F9, 7, // 培 + 0x57FA, 5, // 基 + 0x5800, 7, // 堀 + 0x5802, 4, // 堂 + 0x5805, 7, // 堅 + 0x5815, 7, // 堕 + 0x5824, 7, // å € + 0x582A, 7, // å ª + 0x5831, 5, // å ± + 0x5834, 2, // å Ž + 0x5840, 7, // 塀 + 0x5841, 7, // 塁 + 0x584A, 7, // 塊 + 0x5851, 7, // 塑 + 0x5854, 7, // 塔 + 0x5857, 7, // 塗 + 0x585A, 7, // 塚 + 0x5869, 4, // å¡© + 0x587E, 7, // 塟 + 0x5883, 5, // 境 + 0x5893, 5, // 墓 + 0x5897, 5, // 増 + 0x589C, 7, // 墜 + 0x58A8, 7, // 墚 + 0x58B3, 7, // 墳 + 0x58BE, 7, // 墟 + 0x58C1, 7, // 壁 + 0x58C7, 7, // 壇 + 0x58CA, 7, // 壊 + 0x58CC, 7, // 壌 + 0x58EB, 4, // 士 + 0x58EE, 7, // 壮 + 0x58F0, 2, // 声 + 0x58F1, 7, // 壱 + 0x58F2, 2, // 売 + 0x5909, 4, // 倉 + 0x590F, 2, // 倏 + 0x5915, 1, // 倕 + 0x5916, 2, // 倖 + 0x591A, 2, // 倚 + 0x591C, 2, // 倜 + 0x5922, 5, // 倢 + 0x5927, 1, // 倧 + 0x5929, 1, // 倩 + 0x592A, 2, // 倪 + 0x592B, 4, // 倫 + 0x592E, 3, // 倮 + 0x5931, 4, // 倱 + 0x5947, 7, // 奇 + 0x5949, 7, // 奉 + 0x594F, 6, // 奏 + 0x5951, 7, // 契 + 0x5954, 7, // 奔 + 0x5965, 7, // 奥 + 0x5968, 7, // 奚 + 0x596A, 7, // 奪 + 0x596E, 6, // 奮 + 0x5973, 1, // 女 + 0x5974, 7, // 奎 + 0x597D, 4, // 奜 + 0x5982, 7, // 劂 + 0x5983, 7, // 劃 + 0x5984, 7, // 劄 + 0x598A, 7, // 劊 + 0x5999, 7, // 劙 + 0x59A5, 7, // 劥 + 0x59A8, 7, // 劚 + 0x59B9, 2, // 効 + 0x59BB, 5, // 劻 + 0x59C9, 2, // 姉 + 0x59CB, 3, // 始 + 0x59D3, 7, // 姓 + 0x59D4, 3, // 委 + 0x59EB, 7, // å§« + 0x59FB, 7, // å§» + 0x59FF, 6, // å§¿ + 0x5A01, 7, // 嚁 + 0x5A18, 7, // 嚘 + 0x5A20, 7, // åš  + 0x5A2F, 7, // 嚯 + 0x5A46, 7, // 婆 + 0x5A5A, 7, // 婚 + 0x5A66, 5, // 婊 + 0x5A7F, 7, // å©¿ + 0x5A92, 7, // 媒 + 0x5AC1, 7, // 嫁 + 0x5ACC, 7, // 嫌 + 0x5AE1, 7, // å«¡ + 0x5B22, 7, // 嬢 + 0x5B50, 1, // 子 + 0x5B54, 7, // 孔 + 0x5B57, 1, // 字 + 0x5B58, 6, // 存 + 0x5B5D, 6, // 孝 + 0x5B63, 4, // å­£ + 0x5B64, 7, // å­€ + 0x5B66, 1, // å­Š + 0x5B6B, 4, // å­« + 0x5B85, 6, // 宅 + 0x5B87, 6, // 宇 + 0x5B88, 3, // 守 + 0x5B89, 3, // 安 + 0x5B8C, 4, // 完 + 0x5B97, 6, // 宗 + 0x5B98, 4, // 官 + 0x5B99, 6, // 宙 + 0x5B9A, 3, // 定 + 0x5B9C, 7, // 宜 + 0x5B9D, 6, // 宝 + 0x5B9F, 3, // 実 + 0x5BA2, 3, // 客 + 0x5BA3, 6, // 宣 + 0x5BA4, 2, // 宀 + 0x5BAE, 3, // å®® + 0x5BB0, 7, // å®° + 0x5BB3, 4, // 害 + 0x5BB4, 7, // 宎 + 0x5BB5, 7, // 宵 + 0x5BB6, 2, // å®¶ + 0x5BB9, 5, // 容 + 0x5BBF, 3, // 宿 + 0x5BC2, 7, // 寂 + 0x5BC4, 5, // 寄 + 0x5BC6, 6, // 密 + 0x5BCC, 5, // 富 + 0x5BD2, 3, // 寒 + 0x5BDB, 7, // 寛 + 0x5BDD, 7, // 寝 + 0x5BDF, 4, // 察 + 0x5BE1, 7, // 寡 + 0x5BE7, 7, // 寧 + 0x5BE9, 7, // 審 + 0x5BEE, 7, // 寮 + 0x5BF8, 6, // 寞 + 0x5BFA, 2, // 寺 + 0x5BFE, 3, // 察 + 0x5BFF, 7, // 寿 + 0x5C01, 7, // 封 + 0x5C02, 6, // 専 + 0x5C04, 6, // 射 + 0x5C06, 6, // 将 + 0x5C09, 7, // 尉 + 0x5C0A, 6, // 尊 + 0x5C0B, 7, // 尋 + 0x5C0E, 5, // 導 + 0x5C0F, 1, // 小 + 0x5C11, 2, // 少 + 0x5C1A, 7, // 尚 + 0x5C31, 6, // å°± + 0x5C3A, 6, // å°º + 0x5C3C, 7, // å°Œ + 0x5C3D, 7, // å°œ + 0x5C3E, 7, // å°Ÿ + 0x5C3F, 7, // å°¿ + 0x5C40, 3, // 局 + 0x5C45, 5, // 居 + 0x5C48, 7, // 屈 + 0x5C4A, 6, // 届 + 0x5C4B, 3, // 屋 + 0x5C55, 6, // 展 + 0x5C5E, 5, // 属 + 0x5C64, 6, // å±€ + 0x5C65, 7, // å±¥ + 0x5C6F, 7, // 屯 + 0x5C71, 1, // å±± + 0x5C90, 7, // 岐 + 0x5CA9, 2, // 岩 + 0x5CAC, 7, // 岬 + 0x5CB3, 7, // å²³ + 0x5CB8, 3, // 岞 + 0x5CE0, 7, // å³  + 0x5CE1, 7, // 峡 + 0x5CF0, 7, // å³° + 0x5CF6, 3, // å³¶ + 0x5D07, 7, // 厇 + 0x5D0E, 7, // 厎 + 0x5D29, 7, // 厩 + 0x5DDD, 1, // 川 + 0x5DDE, 3, // 州 + 0x5DE1, 7, // å·¡ + 0x5DE3, 4, // å·£ + 0x5DE5, 2, // å·¥ + 0x5DE6, 1, // å·Š + 0x5DE7, 7, // å·§ + 0x5DE8, 7, // å·š + 0x5DEE, 4, // å·® + 0x5DF1, 6, // å·± + 0x5DFB, 6, // å·» + 0x5E02, 2, // åž‚ + 0x5E03, 5, // 垃 + 0x5E06, 7, // 垆 + 0x5E0C, 4, // 垌 + 0x5E1D, 7, // 垝 + 0x5E25, 7, // 垥 + 0x5E2B, 5, // åž« + 0x5E2D, 4, // åž­ + 0x5E2F, 4, // 垯 + 0x5E30, 2, // åž° + 0x5E33, 3, // åž³ + 0x5E38, 5, // åžž + 0x5E3D, 7, // åžœ + 0x5E45, 7, // 幅 + 0x5E55, 6, // 幕 + 0x5E63, 7, // å¹£ + 0x5E72, 6, // å¹² + 0x5E73, 3, // å¹³ + 0x5E74, 1, // 幎 + 0x5E78, 3, // 幞 + 0x5E79, 5, // å¹¹ + 0x5E7B, 7, // å¹» + 0x5E7C, 6, // 幌 + 0x5E7D, 7, // 幜 + 0x5E7E, 7, // 幟 + 0x5E81, 6, // 庁 + 0x5E83, 2, // 広 + 0x5E8A, 7, // 床 + 0x5E8F, 5, // 序 + 0x5E95, 4, // 底 + 0x5E97, 2, // 店 + 0x5E9C, 4, // 府 + 0x5EA6, 3, // 床 + 0x5EA7, 6, // 座 + 0x5EAB, 3, // 庫 + 0x5EAD, 3, // 庭 + 0x5EB6, 7, // 庶 + 0x5EB7, 4, // 康 + 0x5EB8, 7, // 庞 + 0x5EC3, 7, // 廃 + 0x5EC9, 7, // 廉 + 0x5ECA, 7, // 廊 + 0x5EF6, 6, // å»¶ + 0x5EF7, 7, // å»· + 0x5EFA, 4, // 建 + 0x5F01, 5, // 匁 + 0x5F0A, 7, // 匊 + 0x5F0F, 3, // 匏 + 0x5F10, 7, // 匐 + 0x5F13, 2, // 匓 + 0x5F14, 7, // 匔 + 0x5F15, 2, // 匕 + 0x5F1F, 2, // 匟 + 0x5F26, 7, // 匊 + 0x5F27, 7, // 匧 + 0x5F31, 2, // 匱 + 0x5F35, 5, // 匵 + 0x5F37, 2, // 匷 + 0x5F3E, 7, // 匟 + 0x5F53, 2, // 圓 + 0x5F62, 2, // 圢 + 0x5F69, 7, // 圩 + 0x5F6B, 7, // 圫 + 0x5F70, 7, // 地 + 0x5F71, 7, // 圱 + 0x5F79, 3, // 圹 + 0x5F7C, 7, // 圌 + 0x5F80, 5, // 埀 + 0x5F81, 7, // 埁 + 0x5F84, 4, // 埄 + 0x5F85, 3, // 埅 + 0x5F8B, 6, // 埋 + 0x5F8C, 2, // 埌 + 0x5F90, 7, // 埐 + 0x5F92, 4, // 埒 + 0x5F93, 6, // 埓 + 0x5F97, 4, // 埗 + 0x5FA1, 7, // 埡 + 0x5FA9, 5, // 埩 + 0x5FAA, 7, // 埪 + 0x5FAE, 7, // 埮 + 0x5FB3, 5, // 埳 + 0x5FB4, 7, // 城 + 0x5FB9, 7, // 培 + 0x5FC3, 2, // 心 + 0x5FC5, 4, // 必 + 0x5FCC, 7, // 忌 + 0x5FCD, 7, // 忍 + 0x5FD7, 5, // 志 + 0x5FD8, 6, // 忘 + 0x5FD9, 7, // 忙 + 0x5FDC, 5, // 応 + 0x5FE0, 6, // å¿  + 0x5FEB, 5, // å¿« + 0x5FF5, 4, // 念 + 0x6012, 7, // 怒 + 0x6016, 7, // 怖 + 0x601D, 2, // 思 + 0x6020, 7, // 怠 + 0x6025, 3, // 急 + 0x6027, 5, // 性 + 0x602A, 7, // 怪 + 0x604B, 7, // 恋 + 0x6050, 7, // 恐 + 0x6052, 7, // 恒 + 0x6065, 7, // 恥 + 0x6068, 7, // 恚 + 0x6069, 5, // 恩 + 0x606D, 7, // 恭 + 0x606F, 3, // 息 + 0x6075, 7, // 恵 + 0x6094, 7, // 悔 + 0x609F, 7, // 悟 + 0x60A0, 7, // 悠 + 0x60A3, 7, // 患 + 0x60A6, 7, // 悊 + 0x60A9, 7, // 悩 + 0x60AA, 3, // 悪 + 0x60B2, 3, // 悲 + 0x60BC, 7, // 悌 + 0x60C5, 5, // 情 + 0x60D1, 7, // 惑 + 0x60DC, 7, // 惜 + 0x60E8, 7, // 惚 + 0x60F0, 7, // 惰 + 0x60F3, 3, // 想 + 0x6101, 7, // 愁 + 0x6109, 7, // 愉 + 0x610F, 3, // 意 + 0x611A, 7, // 愚 + 0x611B, 4, // 愛 + 0x611F, 3, // 感 + 0x6148, 7, // 慈 + 0x614B, 5, // 態 + 0x614C, 7, // 慌 + 0x614E, 7, // 慎 + 0x6155, 7, // 慕 + 0x6162, 7, // 慢 + 0x6163, 5, // 慣 + 0x6168, 7, // æ…š + 0x616E, 7, // 慮 + 0x6170, 7, // 慰 + 0x6176, 7, // 慶 + 0x6182, 7, // 憂 + 0x618E, 7, // 憎 + 0x61A4, 7, // 憀 + 0x61A9, 7, // 憩 + 0x61B2, 6, // 憲 + 0x61B6, 7, // 憶 + 0x61BE, 7, // 憟 + 0x61C7, 7, // 懇 + 0x61D0, 7, // 懐 + 0x61F2, 7, // 懲 + 0x61F8, 7, // 懞 + 0x6210, 4, // 成 + 0x6211, 6, // 我 + 0x6212, 7, // 戒 + 0x6226, 4, // 戊 + 0x622F, 7, // 戯 + 0x6238, 2, // 戞 + 0x623B, 7, // 戻 + 0x623F, 7, // 房 + 0x6240, 3, // 所 + 0x6247, 7, // 扇 + 0x6249, 7, // 扉 + 0x624B, 1, // 手 + 0x624D, 2, // 才 + 0x6253, 3, // 打 + 0x6255, 7, // 払 + 0x6271, 7, // 扱 + 0x6276, 7, // 扶 + 0x6279, 6, // 批 + 0x627F, 5, // 承 + 0x6280, 5, // 技 + 0x6284, 7, // 抄 + 0x628A, 7, // 把 + 0x6291, 7, // 抑 + 0x6295, 3, // 投 + 0x6297, 7, // 抗 + 0x6298, 4, // 折 + 0x629C, 7, // 抜 + 0x629E, 7, // 択 + 0x62AB, 7, // 披 + 0x62B1, 7, // 抱 + 0x62B5, 7, // 抵 + 0x62B9, 7, // 抹 + 0x62BC, 7, // 抌 + 0x62BD, 7, // 抜 + 0x62C5, 6, // 担 + 0x62CD, 7, // 拍 + 0x62D0, 7, // 拐 + 0x62D2, 7, // 拒 + 0x62D3, 7, // 拓 + 0x62D8, 7, // 拘 + 0x62D9, 7, // 拙 + 0x62DB, 5, // 招 + 0x62DD, 6, // 拝 + 0x62E0, 7, // 拠 + 0x62E1, 6, // 拡 + 0x62EC, 7, // 括 + 0x62F7, 7, // 拷 + 0x62FE, 3, // 拟 + 0x6301, 3, // 持 + 0x6307, 3, // 指 + 0x6311, 7, // 挑 + 0x6319, 4, // 挙 + 0x631F, 7, // 挟 + 0x632F, 7, // 振 + 0x633F, 7, // 挿 + 0x6355, 7, // 捕 + 0x635C, 7, // 捜 + 0x6368, 6, // 捚 + 0x636E, 7, // 据 + 0x6383, 7, // 掃 + 0x6388, 5, // 授 + 0x638C, 7, // 掌 + 0x6392, 7, // 排 + 0x6398, 7, // 掘 + 0x639B, 7, // 掛 + 0x63A1, 5, // 採 + 0x63A2, 6, // 探 + 0x63A5, 5, // 接 + 0x63A7, 7, // 控 + 0x63A8, 6, // 掚 + 0x63AA, 7, // 措 + 0x63B2, 7, // 掲 + 0x63CF, 7, // 描 + 0x63D0, 5, // 提 + 0x63DA, 7, // 揚 + 0x63DB, 7, // 換 + 0x63E1, 7, // 握 + 0x63EE, 6, // 揮 + 0x63F4, 7, // 揎 + 0x63FA, 7, // 揺 + 0x640D, 5, // 損 + 0x642C, 7, // 搬 + 0x642D, 7, // 搭 + 0x643A, 7, // 携 + 0x643E, 7, // 搟 + 0x6442, 7, // 摂 + 0x6458, 7, // 摘 + 0x6469, 7, // 摩 + 0x6483, 7, // 撃 + 0x64A4, 7, // æ’€ + 0x64AE, 7, // 撮 + 0x64B2, 7, // 撲 + 0x64C1, 7, // 擁 + 0x64CD, 6, // 操 + 0x64E6, 7, // 擊 + 0x64EC, 7, // 擬 + 0x652F, 5, // 支 + 0x6539, 4, // 改 + 0x653B, 7, // 攻 + 0x653E, 3, // 攟 + 0x653F, 5, // 政 + 0x6545, 5, // 故 + 0x654F, 7, // 敏 + 0x6551, 4, // 救 + 0x6557, 4, // 敗 + 0x6559, 2, // 教 + 0x6562, 7, // 敢 + 0x6563, 4, // 散 + 0x656C, 6, // 敬 + 0x6570, 2, // 数 + 0x6574, 3, // 敎 + 0x6575, 5, // 敵 + 0x6577, 7, // 敷 + 0x6587, 1, // 文 + 0x6589, 7, // 斉 + 0x658E, 7, // 斎 + 0x6597, 7, // 斗 + 0x6599, 4, // 料 + 0x659C, 7, // 斜 + 0x65A4, 7, // æ–€ + 0x65A5, 7, // 斥 + 0x65AD, 5, // 断 + 0x65B0, 2, // 新 + 0x65B9, 2, // 方 + 0x65BD, 7, // æ–œ + 0x65C5, 3, // 旅 + 0x65CB, 7, // 旋 + 0x65CF, 3, // 族 + 0x65D7, 4, // 旗 + 0x65E2, 7, // 既 + 0x65E5, 1, // 日 + 0x65E7, 5, // 旧 + 0x65E8, 7, // æ—š + 0x65E9, 1, // 早 + 0x65EC, 7, // 旬 + 0x6606, 7, // 昆 + 0x6607, 7, // 昇 + 0x660E, 2, // 明 + 0x6613, 5, // 易 + 0x6614, 3, // 昔 + 0x661F, 2, // 星 + 0x6620, 6, // 映 + 0x6625, 2, // 春 + 0x6628, 4, // 昚 + 0x662D, 3, // 昭 + 0x662F, 7, // 是 + 0x663C, 2, // 昌 + 0x6642, 2, // 時 + 0x6669, 6, // 晩 + 0x666E, 7, // 普 + 0x666F, 4, // 景 + 0x6674, 2, // 晎 + 0x6676, 7, // 晶 + 0x6681, 7, // 暁 + 0x6687, 7, // 暇 + 0x6691, 3, // 暑 + 0x6696, 6, // 暖 + 0x6697, 3, // 暗 + 0x66A6, 7, // 暊 + 0x66AB, 7, // 暫 + 0x66AE, 6, // 暮 + 0x66B4, 5, // 暎 + 0x66C7, 7, // 曇 + 0x66DC, 2, // 曜 + 0x66F2, 3, // 曲 + 0x66F4, 7, // 曎 + 0x66F8, 2, // 曞 + 0x66F9, 7, // 曹 + 0x66FF, 7, // 替 + 0x6700, 4, // 最 + 0x6708, 1, // 月 + 0x6709, 3, // 有 + 0x670D, 3, // 服 + 0x6715, 7, // 朕 + 0x6717, 6, // 朗 + 0x671B, 4, // 望 + 0x671D, 2, // 朝 + 0x671F, 3, // 期 + 0x6728, 1, // 朚 + 0x672A, 4, // 未 + 0x672B, 4, // 末 + 0x672C, 1, // 本 + 0x672D, 4, // 札 + 0x6731, 7, // 朱 + 0x6734, 7, // 朎 + 0x673A, 6, // 机 + 0x673D, 7, // 朜 + 0x6749, 7, // 杉 + 0x6750, 4, // 材 + 0x6751, 1, // 村 + 0x675F, 4, // 束 + 0x6761, 5, // 条 + 0x6765, 2, // 来 + 0x676F, 7, // 杯 + 0x6771, 2, // 東 + 0x677E, 4, // 束 + 0x677F, 3, // 板 + 0x6790, 7, // 析 + 0x6797, 1, // 林 + 0x679A, 6, // 枚 + 0x679C, 4, // 果 + 0x679D, 5, // 枝 + 0x67A0, 7, // 枠 + 0x67A2, 7, // 枢 + 0x67AF, 7, // 枯 + 0x67B6, 7, // 架 + 0x67C4, 7, // 柄 + 0x67D0, 7, // 某 + 0x67D3, 6, // 染 + 0x67D4, 7, // 柔 + 0x67F1, 3, // 柱 + 0x67F3, 7, // 柳 + 0x67FB, 5, // 査 + 0x6804, 4, // 栄 + 0x6813, 7, // 栓 + 0x6821, 1, // æ ¡ + 0x682A, 6, // æ ª + 0x6838, 7, // æ ž + 0x6839, 3, // æ ¹ + 0x683C, 5, // æ Œ + 0x683D, 7, // æ œ + 0x6843, 7, // 桃 + 0x6848, 4, // 案 + 0x6851, 7, // 桑 + 0x685C, 5, // 桜 + 0x685F, 7, // 桟 + 0x6885, 4, // 梅 + 0x68B0, 4, // 械 + 0x68C4, 7, // 棄 + 0x68CB, 7, // 棋 + 0x68D2, 6, // 棒 + 0x68DA, 7, // 棚 + 0x68DF, 7, // 棟 + 0x68EE, 1, // 森 + 0x68FA, 7, // 棺 + 0x690D, 3, // 怍 + 0x691C, 5, // 怜 + 0x696D, 3, // 業 + 0x6975, 4, // 極 + 0x697C, 7, // 楌 + 0x697D, 2, // 楜 + 0x6982, 7, // 抂 + 0x69CB, 5, // 構 + 0x69D8, 3, // 様 + 0x69FD, 7, // æ§œ + 0x6A19, 4, // æš™ + 0x6A21, 6, // æš¡ + 0x6A29, 6, // æš© + 0x6A2A, 3, // 暪 + 0x6A39, 6, // æš¹ + 0x6A4B, 3, // 橋 + 0x6A5F, 4, // 機 + 0x6B04, 7, // 欄 + 0x6B20, 4, // 欠 + 0x6B21, 3, // 次 + 0x6B27, 7, // 欧 + 0x6B32, 6, // 欲 + 0x6B3A, 7, // 欺 + 0x6B3E, 7, // 欟 + 0x6B4C, 2, // 歌 + 0x6B53, 7, // 歓 + 0x6B62, 2, // æ­¢ + 0x6B63, 1, // æ­£ + 0x6B66, 5, // æ­Š + 0x6B69, 2, // æ­© + 0x6B6F, 3, // æ­¯ + 0x6B73, 7, // æ­³ + 0x6B74, 4, // æ­Ž + 0x6B7B, 3, // æ­» + 0x6B89, 7, // 殉 + 0x6B8A, 7, // 殊 + 0x6B8B, 4, // 残 + 0x6B96, 7, // 殖 + 0x6BB4, 7, // 殎 + 0x6BB5, 6, // 段 + 0x6BBA, 4, // 殺 + 0x6BBB, 7, // æ®» + 0x6BBF, 7, // 殿 + 0x6BCD, 2, // 母 + 0x6BCE, 2, // 毎 + 0x6BD2, 4, // 毒 + 0x6BD4, 5, // 比 + 0x6BDB, 2, // 毛 + 0x6C0F, 4, // 氏 + 0x6C11, 4, // 民 + 0x6C17, 1, // 気 + 0x6C34, 1, // æ°Ž + 0x6C37, 3, // æ°· + 0x6C38, 5, // æ°ž + 0x6C41, 7, // 汁 + 0x6C42, 4, // 求 + 0x6C57, 7, // 汗 + 0x6C5A, 7, // 汚 + 0x6C5F, 7, // 江 + 0x6C60, 2, // æ±  + 0x6C7A, 3, // 決 + 0x6C7D, 2, // 汜 + 0x6C88, 7, // 沈 + 0x6C96, 7, // 沖 + 0x6CA1, 7, // 没 + 0x6CA2, 7, // æ²¢ + 0x6CB3, 5, // æ²³ + 0x6CB8, 7, // 沞 + 0x6CB9, 3, // æ²¹ + 0x6CBB, 4, // æ²» + 0x6CBC, 7, // 沌 + 0x6CBF, 6, // 沿 + 0x6CC1, 7, // 況 + 0x6CC9, 6, // 泉 + 0x6CCA, 7, // 泊 + 0x6CCC, 7, // 泌 + 0x6CD5, 4, // 法 + 0x6CE1, 7, // 泡 + 0x6CE2, 3, // æ³¢ + 0x6CE3, 4, // æ³£ + 0x6CE5, 7, // æ³¥ + 0x6CE8, 3, // 泚 + 0x6CF0, 7, // æ³° + 0x6CF3, 3, // æ³³ + 0x6D0B, 3, // 掋 + 0x6D17, 6, // 掗 + 0x6D1E, 7, // 掞 + 0x6D25, 7, // 接 + 0x6D2A, 7, // 措 + 0x6D3B, 2, // 掻 + 0x6D3E, 6, // 掟 + 0x6D41, 3, // 流 + 0x6D44, 7, // 浄 + 0x6D45, 4, // 浅 + 0x6D5C, 7, // 浜 + 0x6D66, 7, // 浊 + 0x6D6A, 7, // 浪 + 0x6D6E, 7, // æµ® + 0x6D74, 4, // 济 + 0x6D77, 2, // æµ· + 0x6D78, 7, // 浞 + 0x6D88, 3, // 消 + 0x6D99, 7, // 涙 + 0x6DAF, 7, // 涯 + 0x6DB2, 5, // æ¶² + 0x6DBC, 7, // æ¶Œ + 0x6DD1, 7, // 淑 + 0x6DE1, 7, // æ·¡ + 0x6DF1, 3, // æ·± + 0x6DF7, 5, // æ·· + 0x6DFB, 7, // æ·» + 0x6E05, 4, // æž… + 0x6E07, 7, // 枇 + 0x6E08, 6, // 枈 + 0x6E09, 7, // 枉 + 0x6E0B, 7, // æž‹ + 0x6E13, 7, // æž“ + 0x6E1B, 5, // æž› + 0x6E21, 7, // æž¡ + 0x6E26, 7, // 枊 + 0x6E29, 3, // æž© + 0x6E2C, 5, // 枬 + 0x6E2F, 3, // 枯 + 0x6E56, 3, // 湖 + 0x6E6F, 3, // 湯 + 0x6E7E, 7, // 湟 + 0x6E7F, 7, // 湿 + 0x6E80, 4, // 満 + 0x6E90, 6, // 源 + 0x6E96, 5, // 準 + 0x6E9D, 7, // 溝 + 0x6EB6, 7, // 溶 + 0x6EC5, 7, // 滅 + 0x6ECB, 7, // 滋 + 0x6ED1, 7, // 滑 + 0x6EDD, 7, // 滝 + 0x6EDE, 7, // 滞 + 0x6EF4, 7, // 滎 + 0x6F01, 4, // 持 + 0x6F02, 7, // 挂 + 0x6F06, 7, // 挆 + 0x6F0F, 7, // 挏 + 0x6F14, 5, // 挔 + 0x6F20, 7, // 挠 + 0x6F22, 3, // 挢 + 0x6F2B, 7, // 挫 + 0x6F2C, 7, // 挬 + 0x6F38, 7, // 挞 + 0x6F54, 5, // 朔 + 0x6F5C, 7, // 朜 + 0x6F5F, 7, // 期 + 0x6F64, 7, // 最 + 0x6F6E, 6, // 朮 + 0x6F84, 7, // 柄 + 0x6FC0, 6, // 激 + 0x6FC1, 7, // 濁 + 0x6FC3, 7, // 濃 + 0x6FEB, 7, // æ¿« + 0x6FEF, 7, // 濯 + 0x702C, 7, // 瀬 + 0x706B, 1, // 火 + 0x706F, 4, // 灯 + 0x7070, 6, // 灰 + 0x707D, 5, // 灜 + 0x7089, 7, // 炉 + 0x708A, 7, // 炊 + 0x708E, 7, // 炎 + 0x70AD, 3, // 炭 + 0x70B9, 2, // 点 + 0x70BA, 7, // 為 + 0x70C8, 7, // 烈 + 0x7121, 4, // 無 + 0x7126, 7, // 焩 + 0x7136, 4, // 然 + 0x713C, 4, // 焌 + 0x7159, 7, // 煙 + 0x7167, 4, // 照 + 0x7169, 7, // 煩 + 0x716E, 7, // 煮 + 0x719F, 6, // 熟 + 0x71B1, 4, // 熱 + 0x71C3, 5, // 燃 + 0x71C8, 7, // 燈 + 0x71E5, 7, // 燥 + 0x7206, 7, // 爆 + 0x7235, 7, // 爵 + 0x7236, 2, // 父 + 0x7247, 6, // 片 + 0x7248, 5, // 版 + 0x725B, 2, // 牛 + 0x7267, 4, // 牧 + 0x7269, 3, // 物 + 0x7272, 7, // 牲 + 0x7279, 4, // 特 + 0x72A0, 7, // 犠 + 0x72AC, 1, // 犬 + 0x72AF, 5, // 犯 + 0x72B6, 5, // 状 + 0x72C2, 7, // 狂 + 0x72E9, 7, // 狩 + 0x72EC, 5, // 独 + 0x72ED, 7, // 狭 + 0x731B, 7, // 猛 + 0x731F, 7, // 猟 + 0x732B, 7, // 猫 + 0x732E, 7, // 献 + 0x7336, 7, // 猶 + 0x733F, 7, // 猿 + 0x7344, 7, // 獄 + 0x7363, 7, // 獣 + 0x7372, 7, // 獲 + 0x7384, 7, // 玄 + 0x7387, 5, // 率 + 0x7389, 1, // 玉 + 0x738B, 1, // 王 + 0x73CD, 7, // 珍 + 0x73E0, 7, // 珠 + 0x73ED, 6, // 班 + 0x73FE, 5, // 珟 + 0x7403, 3, // 球 + 0x7406, 2, // 理 + 0x7434, 7, // 琎 + 0x74B0, 7, // 環 + 0x74BD, 7, // ç’œ + 0x74F6, 7, // 瓶 + 0x7518, 7, // 甘 + 0x751A, 7, // 甚 + 0x751F, 1, // 生 + 0x7523, 4, // 産 + 0x7528, 2, // 甹 + 0x7530, 1, // 田 + 0x7531, 3, // 由 + 0x7532, 7, // 甲 + 0x7533, 3, // 申 + 0x7537, 1, // 男 + 0x753A, 1, // 町 + 0x753B, 2, // 画 + 0x754C, 3, // 界 + 0x7551, 3, // 畑 + 0x7554, 7, // 畔 + 0x7559, 5, // 留 + 0x755C, 7, // 畜 + 0x755D, 7, // 畝 + 0x7565, 5, // 略 + 0x756A, 2, // 番 + 0x7570, 6, // 異 + 0x7573, 7, // 畳 + 0x758E, 7, // 疎 + 0x7591, 6, // 疑 + 0x75AB, 7, // 疫 + 0x75B2, 7, // 疲 + 0x75BE, 7, // ç–Ÿ + 0x75C5, 3, // 病 + 0x75C7, 7, // 症 + 0x75D8, 7, // 痘 + 0x75DB, 6, // 痛 + 0x75E2, 7, // 痢 + 0x75F4, 7, // 痮 + 0x7642, 7, // 療 + 0x7652, 7, // 癒 + 0x7656, 7, // 癖 + 0x767A, 3, // 発 + 0x767B, 3, // 登 + 0x767D, 1, // 癜 + 0x767E, 1, // 癟 + 0x7684, 4, // 的 + 0x7686, 7, // 皆 + 0x7687, 6, // 皇 + 0x76AE, 3, // 皮 + 0x76BF, 3, // 皿 + 0x76C6, 7, // 盆 + 0x76CA, 5, // 益 + 0x76D7, 7, // 盗 + 0x76DB, 6, // 盛 + 0x76DF, 6, // 盟 + 0x76E3, 7, // 監 + 0x76E4, 7, // 盀 + 0x76EE, 1, // 目 + 0x76F2, 7, // 盲 + 0x76F4, 2, // 目 + 0x76F8, 3, // 盾 + 0x76FE, 7, // 盟 + 0x7701, 4, // 省 + 0x770B, 6, // 看 + 0x770C, 3, // 県 + 0x771F, 3, // 真 + 0x7720, 7, // 眠 + 0x773A, 7, // 眺 + 0x773C, 5, // 県 + 0x7740, 3, // 着 + 0x7761, 7, // 睡 + 0x7763, 7, // 督 + 0x77AC, 7, // 瞬 + 0x77DB, 7, // 矛 + 0x77E2, 2, // 矢 + 0x77E5, 2, // 知 + 0x77ED, 3, // 短 + 0x77EF, 7, // 矯 + 0x77F3, 1, // 石 + 0x7802, 6, // 砂 + 0x7814, 3, // 研 + 0x7815, 7, // 砕 + 0x7832, 7, // ç ² + 0x7834, 5, // ç Ž + 0x785D, 7, // 硝 + 0x786B, 7, // ç¡« + 0x786C, 7, // 硬 + 0x7881, 7, // 碁 + 0x7891, 7, // 碑 + 0x78BA, 5, // 確 + 0x78C1, 6, // 磁 + 0x78E8, 7, // 磚 + 0x7901, 7, // 瀁 + 0x790E, 7, // 瀎 + 0x793A, 5, // 瀺 + 0x793C, 3, // 瀌 + 0x793E, 2, // 瀟 + 0x7948, 7, // 祈 + 0x7949, 7, // 祉 + 0x7956, 5, // 祖 + 0x795D, 4, // 祝 + 0x795E, 3, // 神 + 0x7965, 7, // 祥 + 0x7968, 4, // 祚 + 0x796D, 3, // 祭 + 0x7981, 5, // 犁 + 0x7985, 7, // 穅 + 0x798D, 7, // 犍 + 0x798F, 3, // 犏 + 0x79C0, 7, // 秀 + 0x79C1, 6, // 私 + 0x79CB, 2, // 秋 + 0x79D1, 2, // 科 + 0x79D2, 3, // 秒 + 0x79D8, 6, // 秘 + 0x79DF, 7, // 租 + 0x79E9, 7, // ç§© + 0x79F0, 7, // ç§° + 0x79FB, 5, // ç§» + 0x7A0B, 5, // 繋 + 0x7A0E, 5, // 皎 + 0x7A1A, 7, // 繚 + 0x7A2E, 4, // çš® + 0x7A32, 7, // çš² + 0x7A3C, 7, // 皌 + 0x7A3F, 7, // çš¿ + 0x7A40, 6, // 穀 + 0x7A42, 7, // 穂 + 0x7A4D, 4, // 積 + 0x7A4F, 7, // 穏 + 0x7A6B, 7, // ç©« + 0x7A74, 6, // 穎 + 0x7A76, 3, // ç©¶ + 0x7A7A, 1, // 空 + 0x7A81, 7, // 突 + 0x7A83, 7, // 窃 + 0x7A92, 7, // 窒 + 0x7A93, 6, // 窓 + 0x7AAE, 7, // 窮 + 0x7AAF, 7, // 窯 + 0x7ACB, 1, // 立 + 0x7ADC, 7, // 竜 + 0x7AE0, 3, // ç«  + 0x7AE5, 3, // ç«¥ + 0x7AEF, 7, // 端 + 0x7AF6, 4, // ç«¶ + 0x7AF9, 1, // 竹 + 0x7B11, 4, // 笑 + 0x7B1B, 3, // 笛 + 0x7B26, 7, // 笊 + 0x7B2C, 3, // 第 + 0x7B46, 3, // 筆 + 0x7B49, 3, // 等 + 0x7B4B, 6, // 筋 + 0x7B52, 7, // 筒 + 0x7B54, 2, // 答 + 0x7B56, 6, // 策 + 0x7B87, 7, // 箇 + 0x7B97, 2, // 算 + 0x7BA1, 4, // 管 + 0x7BB1, 3, // ç®± + 0x7BC0, 4, // 節 + 0x7BC4, 7, // 範 + 0x7BC9, 5, // 築 + 0x7BE4, 7, // 節 + 0x7C21, 6, // ç°¡ + 0x7C3F, 7, // ç°¿ + 0x7C4D, 7, // 籍 + 0x7C73, 2, // ç±³ + 0x7C89, 4, // 粉 + 0x7C8B, 7, // 粋 + 0x7C92, 7, // 粒 + 0x7C97, 7, // 粗 + 0x7C98, 7, // 粘 + 0x7C9B, 7, // 粛 + 0x7CA7, 7, // ç²§ + 0x7CBE, 5, // 粟 + 0x7CD6, 6, // 糖 + 0x7CE7, 7, // ç³§ + 0x7CF8, 1, // 糞 + 0x7CFB, 6, // ç³» + 0x7CFE, 7, // 糟 + 0x7D00, 4, // 简 + 0x7D04, 4, // 箄 + 0x7D05, 6, // 箅 + 0x7D0B, 7, // 箋 + 0x7D0D, 6, // 玍 + 0x7D14, 6, // 箔 + 0x7D19, 2, // 箙 + 0x7D1A, 3, // 箚 + 0x7D1B, 7, // 箛 + 0x7D20, 5, // 玠 + 0x7D21, 7, // 玡 + 0x7D22, 7, // 玢 + 0x7D2B, 7, // 玫 + 0x7D2F, 7, // 环 + 0x7D30, 2, // 现 + 0x7D33, 7, // 玳 + 0x7D39, 7, // 玹 + 0x7D3A, 7, // 玺 + 0x7D42, 3, // 終 + 0x7D44, 2, // 組 + 0x7D4C, 5, // 経 + 0x7D50, 4, // 結 + 0x7D5E, 7, // 絞 + 0x7D61, 7, // 絡 + 0x7D66, 4, // 絊 + 0x7D71, 5, // çµ± + 0x7D75, 2, // çµµ + 0x7D76, 5, // çµ¶ + 0x7D79, 6, // çµ¹ + 0x7D99, 7, // 継 + 0x7D9A, 4, // 続 + 0x7DAD, 7, // ç¶­ + 0x7DB1, 7, // ç¶± + 0x7DB2, 7, // ç¶² + 0x7DBF, 5, // ç¶¿ + 0x7DCA, 7, // 緊 + 0x7DCF, 5, // 総 + 0x7DD1, 3, // 緑 + 0x7DD2, 7, // 緒 + 0x7DDA, 2, // 線 + 0x7DE0, 7, // ç·  + 0x7DE8, 5, // ç·š + 0x7DE9, 7, // ç·© + 0x7DEF, 7, // ç·¯ + 0x7DF4, 3, // ç·Ž + 0x7E01, 7, // 瞁 + 0x7E04, 7, // 羄 + 0x7E1B, 7, // 羛 + 0x7E26, 6, // 瞊 + 0x7E2B, 7, // çž« + 0x7E2E, 6, // çž® + 0x7E3E, 5, // 瞟 + 0x7E41, 7, // 繁 + 0x7E4A, 7, // 繊 + 0x7E54, 5, // 織 + 0x7E55, 7, // 繕 + 0x7E6D, 7, // ç¹­ + 0x7E70, 7, // ç¹° + 0x7F36, 7, // 猶 + 0x7F6A, 5, // 眪 + 0x7F6E, 4, // 眮 + 0x7F70, 7, // 眰 + 0x7F72, 6, // 眲 + 0x7F77, 7, // 眷 + 0x7F85, 7, // 矅 + 0x7F8A, 3, // 矊 + 0x7F8E, 3, // 矎 + 0x7FA4, 5, // 矀 + 0x7FA9, 5, // 矩 + 0x7FBD, 2, // 矜 + 0x7FC1, 7, // 翁 + 0x7FCC, 6, // 翌 + 0x7FD2, 3, // 習 + 0x7FFB, 7, // ç¿» + 0x7FFC, 7, // 翌 + 0x8001, 4, // 老 + 0x8003, 2, // 考 + 0x8005, 3, // 者 + 0x8010, 7, // 耐 + 0x8015, 5, // 耕 + 0x8017, 7, // 耗 + 0x8033, 1, // 耳 + 0x8056, 6, // 聖 + 0x805E, 2, // 聞 + 0x8074, 7, // 聎 + 0x8077, 5, // 職 + 0x8089, 2, // 肉 + 0x808C, 7, // 肌 + 0x8096, 7, // 肖 + 0x809D, 7, // 肝 + 0x80A2, 7, // 肢 + 0x80A5, 5, // 肥 + 0x80A9, 7, // 肩 + 0x80AA, 7, // 肪 + 0x80AF, 7, // 肯 + 0x80B2, 3, // 育 + 0x80BA, 6, // 肺 + 0x80C3, 4, // 胃 + 0x80C6, 7, // 胆 + 0x80CC, 6, // 背 + 0x80CE, 7, // 胎 + 0x80DE, 7, // 胞 + 0x80F4, 7, // 胎 + 0x80F8, 6, // 胞 + 0x80FD, 5, // 胜 + 0x8102, 7, // 脂 + 0x8105, 7, // 脅 + 0x8108, 4, // 脈 + 0x811A, 7, // 脚 + 0x8131, 7, // 脱 + 0x8133, 6, // 脳 + 0x8139, 7, // 脹 + 0x8150, 7, // 腐 + 0x8155, 7, // 腕 + 0x8170, 7, // 腰 + 0x8178, 4, // è…ž + 0x8179, 6, // 腹 + 0x819A, 7, // 膚 + 0x819C, 7, // 膜 + 0x81A8, 7, // 膚 + 0x81D3, 6, // 臓 + 0x81E3, 4, // 臣 + 0x81E8, 6, // 臚 + 0x81EA, 2, // 自 + 0x81ED, 7, // 臭 + 0x81F3, 6, // 至 + 0x81F4, 7, // 臎 + 0x8208, 5, // 興 + 0x820C, 5, // 舌 + 0x820E, 5, // 舎 + 0x8217, 7, // 舗 + 0x821E, 7, // 舞 + 0x821F, 7, // 舟 + 0x822A, 4, // 航 + 0x822C, 7, // 般 + 0x8236, 7, // 舶 + 0x8239, 2, // 船 + 0x8247, 7, // 艇 + 0x8266, 7, // 艊 + 0x826F, 4, // 良 + 0x8272, 2, // 色 + 0x828B, 7, // 芋 + 0x829D, 7, // 芝 + 0x82B1, 1, // 花 + 0x82B3, 7, // 芳 + 0x82B8, 4, // 芞 + 0x82BD, 4, // 芜 + 0x82D7, 7, // 苗 + 0x82E5, 6, // 若 + 0x82E6, 3, // 苊 + 0x82F1, 4, // 英 + 0x8302, 7, // 茂 + 0x830E, 7, // 茎 + 0x8336, 2, // 茶 + 0x8349, 1, // 草 + 0x8352, 7, // 荒 + 0x8358, 7, // 荘 + 0x8377, 3, // 荷 + 0x83CA, 7, // 菊 + 0x83CC, 7, // 菌 + 0x83D3, 7, // 菓 + 0x83DC, 4, // 菜 + 0x83EF, 7, // 華 + 0x843D, 3, // 萜 + 0x8449, 3, // 葉 + 0x8457, 6, // 著 + 0x846C, 7, // 葬 + 0x84B8, 6, // è’ž + 0x84C4, 7, // 蓄 + 0x8535, 6, // 蔵 + 0x8584, 7, // 薄 + 0x85A6, 7, // è–Š + 0x85AA, 7, // 薪 + 0x85AB, 7, // 薫 + 0x85AC, 3, // 薬 + 0x85E9, 7, // 藩 + 0x85FB, 7, // 藻 + 0x8650, 7, // 虐 + 0x865A, 7, // 虚 + 0x865C, 7, // 虜 + 0x865E, 7, // 虞 + 0x866B, 1, // 虫 + 0x868A, 7, // 蚊 + 0x8695, 6, // 蚕 + 0x86C7, 7, // 蛇 + 0x86CD, 7, // 蛍 + 0x86EE, 7, // 蛮 + 0x878D, 7, // 融 + 0x8840, 3, // 血 + 0x8846, 6, // 衆 + 0x884C, 2, // 行 + 0x8853, 5, // 術 + 0x8857, 4, // 街 + 0x885B, 5, // 衛 + 0x885D, 7, // 衝 + 0x8861, 7, // è¡¡ + 0x8863, 4, // è¡£ + 0x8868, 3, // 衚 + 0x8870, 7, // è¡° + 0x8877, 7, // è¡· + 0x888B, 7, // 袋 + 0x88AB, 7, // 被 + 0x88C1, 6, // 裁 + 0x88C2, 7, // 裂 + 0x88C5, 6, // 装 + 0x88CF, 6, // 裏 + 0x88D5, 7, // 裕 + 0x88DC, 6, // 補 + 0x88F8, 7, // 裞 + 0x88FD, 5, // 補 + 0x8907, 5, // 耇 + 0x8910, 7, // 耐 + 0x8912, 7, // 耒 + 0x895F, 7, // 襟 + 0x8972, 7, // 襲 + 0x897F, 2, // 西 + 0x8981, 4, // 芁 + 0x8986, 7, // 芆 + 0x8987, 7, // 芇 + 0x898B, 1, // 芋 + 0x898F, 5, // 芏 + 0x8996, 6, // 芖 + 0x899A, 4, // 芚 + 0x89A7, 6, // 芧 + 0x89AA, 2, // 芪 + 0x89B3, 4, // 芳 + 0x89D2, 2, // 角 + 0x89E3, 5, // è§£ + 0x89E6, 7, // è§Š + 0x8A00, 2, // 蚀 + 0x8A02, 7, // èš‚ + 0x8A08, 2, // 蚈 + 0x8A0E, 6, // 蚎 + 0x8A13, 4, // èš“ + 0x8A17, 7, // èš— + 0x8A18, 2, // 蚘 + 0x8A1F, 7, // 蚟 + 0x8A2A, 6, // 蚪 + 0x8A2D, 5, // èš­ + 0x8A31, 5, // èš± + 0x8A33, 6, // èš³ + 0x8A34, 7, // 蚎 + 0x8A3A, 7, // 蚺 + 0x8A3C, 5, // 蚌 + 0x8A50, 7, // 詐 + 0x8A54, 7, // 詔 + 0x8A55, 5, // 評 + 0x8A5E, 6, // 詞 + 0x8A60, 7, // è©  + 0x8A66, 4, // 詊 + 0x8A69, 3, // è©© + 0x8A70, 7, // è©° + 0x8A71, 2, // 話 + 0x8A72, 7, // 該 + 0x8A73, 7, // 詳 + 0x8A87, 7, // 誇 + 0x8A89, 7, // 誉 + 0x8A8C, 6, // 誌 + 0x8A8D, 6, // 認 + 0x8A93, 7, // 誓 + 0x8A95, 6, // 誕 + 0x8A98, 7, // 誘 + 0x8A9E, 2, // 語 + 0x8AA0, 6, // 誠 + 0x8AA4, 6, // 誀 + 0x8AAC, 4, // 説 + 0x8AAD, 2, // 読 + 0x8AB2, 4, // 課 + 0x8ABF, 3, // 調 + 0x8AC7, 3, // 談 + 0x8ACB, 7, // 請 + 0x8AD6, 6, // 論 + 0x8AED, 7, // è«­ + 0x8AEE, 7, // è«® + 0x8AF8, 6, // 諞 + 0x8AFE, 7, // 諟 + 0x8B00, 7, // 謀 + 0x8B01, 7, // 謁 + 0x8B04, 7, // 謄 + 0x8B19, 7, // 謙 + 0x8B1B, 5, // 講 + 0x8B1D, 5, // 謝 + 0x8B21, 7, // 謡 + 0x8B39, 7, // 謹 + 0x8B58, 5, // 識 + 0x8B5C, 7, // 譜 + 0x8B66, 6, // è­Š + 0x8B70, 4, // è­° + 0x8B72, 7, // è­² + 0x8B77, 5, // è­· + 0x8C37, 2, // è°· + 0x8C46, 3, // 豆 + 0x8C4A, 5, // 豊 + 0x8C5A, 7, // 豚 + 0x8C61, 4, // 象 + 0x8C6A, 7, // 豪 + 0x8C9D, 1, // 貝 + 0x8C9E, 7, // 貞 + 0x8CA0, 3, // è²  + 0x8CA1, 5, // 財 + 0x8CA2, 7, // è²¢ + 0x8CA7, 5, // è²§ + 0x8CA8, 4, // 貚 + 0x8CA9, 7, // 販 + 0x8CAB, 7, // 貫 + 0x8CAC, 5, // 責 + 0x8CAF, 4, // 貯 + 0x8CB4, 6, // 貎 + 0x8CB7, 2, // è²· + 0x8CB8, 5, // 貞 + 0x8CBB, 4, // è²» + 0x8CBF, 5, // 貿 + 0x8CC0, 5, // 賀 + 0x8CC3, 6, // 賃 + 0x8CC4, 7, // 賄 + 0x8CC7, 5, // 資 + 0x8CCA, 7, // 賊 + 0x8CD3, 7, // 賓 + 0x8CDB, 5, // 賛 + 0x8CDC, 7, // 賜 + 0x8CDE, 4, // 賞 + 0x8CE0, 7, // è³  + 0x8CE2, 7, // è³¢ + 0x8CE6, 7, // 賊 + 0x8CEA, 5, // 質 + 0x8CFC, 7, // 賌 + 0x8D08, 7, // 莈 + 0x8D64, 1, // èµ€ + 0x8D66, 7, // 赊 + 0x8D70, 2, // èµ° + 0x8D74, 7, // 赎 + 0x8D77, 3, // èµ· + 0x8D85, 7, // 超 + 0x8D8A, 7, // 越 + 0x8DA3, 7, // è¶£ + 0x8DB3, 1, // è¶³ + 0x8DDD, 7, // 距 + 0x8DE1, 7, // è·¡ + 0x8DEF, 3, // è·¯ + 0x8DF3, 7, // è·³ + 0x8DF5, 7, // è·µ + 0x8E0A, 7, // 螊 + 0x8E0F, 7, // 螏 + 0x8E8D, 7, // 躍 + 0x8EAB, 3, // 身 + 0x8ECA, 1, // 車 + 0x8ECC, 7, // 軌 + 0x8ECD, 4, // 軍 + 0x8ED2, 7, // 軒 + 0x8EDF, 7, // 軟 + 0x8EE2, 3, // 転 + 0x8EF8, 7, // 軞 + 0x8EFD, 3, // 軜 + 0x8F03, 7, // 范 + 0x8F09, 7, // 茉 + 0x8F1D, 7, // 茝 + 0x8F29, 7, // 茩 + 0x8F2A, 4, // 茪 + 0x8F38, 5, // 茞 + 0x8F44, 7, // 蜄 + 0x8F9B, 7, // 蟛 + 0x8F9E, 4, // 蟞 + 0x8FB1, 7, // 蟱 + 0x8FB2, 3, // 蟲 + 0x8FBA, 4, // 蟺 + 0x8FBC, 7, // 蟌 + 0x8FC5, 7, // 迅 + 0x8FCE, 7, // 迎 + 0x8FD1, 2, // 近 + 0x8FD4, 3, // 返 + 0x8FEB, 7, // è¿« + 0x8FED, 7, // è¿­ + 0x8FF0, 5, // è¿° + 0x8FF7, 5, // è¿· + 0x8FFD, 3, // 远 + 0x9000, 5, // 退 + 0x9001, 3, // 送 + 0x9003, 7, // 逃 + 0x9006, 5, // 逆 + 0x900F, 7, // 透 + 0x9010, 7, // 逐 + 0x9013, 7, // 逓 + 0x9014, 7, // 途 + 0x901A, 2, // 通 + 0x901D, 7, // 逝 + 0x901F, 3, // 速 + 0x9020, 5, // 造 + 0x9023, 4, // 連 + 0x902E, 7, // 逮 + 0x9031, 2, // 週 + 0x9032, 3, // 進 + 0x9038, 7, // 逾 + 0x9042, 7, // 遂 + 0x9045, 7, // 遅 + 0x9047, 7, // 遇 + 0x904A, 3, // 遊 + 0x904B, 3, // 運 + 0x904D, 7, // 遍 + 0x904E, 5, // 過 + 0x9053, 2, // 道 + 0x9054, 4, // 達 + 0x9055, 7, // 違 + 0x9060, 2, // 遠 + 0x9063, 7, // 遣 + 0x9069, 5, // 適 + 0x906D, 7, // 遭 + 0x906E, 7, // 遮 + 0x9075, 7, // 遵 + 0x9077, 7, // 遷 + 0x9078, 4, // 遞 + 0x907A, 6, // 遺 + 0x907F, 7, // 避 + 0x9084, 7, // 還 + 0x90A6, 7, // 邩 + 0x90AA, 7, // 邪 + 0x90B8, 7, // 邾 + 0x90CA, 7, // 郊 + 0x90CE, 7, // 郎 + 0x90E1, 4, // 郡 + 0x90E8, 3, // 郚 + 0x90ED, 7, // 郭 + 0x90F5, 6, // 郵 + 0x90F7, 6, // 郷 + 0x90FD, 3, // 郜 + 0x914C, 7, // 酌 + 0x914D, 3, // 配 + 0x9152, 3, // 酒 + 0x9154, 7, // 酔 + 0x9162, 7, // 酢 + 0x916A, 7, // 酪 + 0x916C, 7, // 酬 + 0x9175, 7, // 酵 + 0x9177, 7, // 酷 + 0x9178, 5, // 酾 + 0x919C, 7, // 醜 + 0x91B8, 7, // 醾 + 0x91C8, 7, // 釈 + 0x91CC, 2, // 里 + 0x91CD, 3, // 重 + 0x91CE, 2, // 野 + 0x91CF, 4, // 量 + 0x91D1, 1, // 金 + 0x91DD, 6, // 針 + 0x91E3, 7, // 釣 + 0x920D, 7, // 鈍 + 0x9234, 7, // 鈎 + 0x9244, 3, // 鉄 + 0x925B, 7, // 鉛 + 0x9262, 7, // 鉢 + 0x9271, 5, // 鉱 + 0x9280, 3, // 銀 + 0x9283, 7, // 銃 + 0x9285, 5, // 銅 + 0x9291, 7, // 銑 + 0x9298, 7, // 銘 + 0x92AD, 5, // 銭 + 0x92ED, 7, // 鋭 + 0x92F3, 7, // 鋳 + 0x92FC, 6, // 鋌 + 0x9318, 7, // 錘 + 0x9320, 7, // 錠 + 0x932C, 7, // 錬 + 0x932F, 7, // 錯 + 0x9332, 4, // 録 + 0x935B, 7, // 鍛 + 0x9396, 7, // 鎖 + 0x93AE, 7, // 鎮 + 0x93E1, 4, // 鏡 + 0x9418, 7, // 鐘 + 0x9451, 7, // 鑑 + 0x9577, 2, // 長 + 0x9580, 2, // 門 + 0x9589, 6, // 閉 + 0x958B, 3, // 開 + 0x9591, 7, // 閑 + 0x9593, 2, // 間 + 0x95A2, 4, // 関 + 0x95A3, 6, // 閣 + 0x95A5, 7, // 閥 + 0x95B2, 7, // 閲 + 0x95D8, 7, // 闘 + 0x9632, 5, // 防 + 0x963B, 7, // 阻 + 0x9644, 7, // 附 + 0x964D, 6, // 降 + 0x9650, 5, // 限 + 0x965B, 6, // 陛 + 0x9662, 3, // 院 + 0x9663, 7, // 陣 + 0x9664, 6, // 陀 + 0x9665, 7, // 陥 + 0x966A, 7, // 陪 + 0x9670, 7, // 陰 + 0x9673, 7, // 陳 + 0x9675, 7, // 陵 + 0x9676, 7, // 陶 + 0x9678, 4, // 陾 + 0x967A, 5, // 険 + 0x967D, 3, // 陜 + 0x9685, 7, // 隅 + 0x9686, 7, // 隆 + 0x968A, 4, // 隊 + 0x968E, 3, // 階 + 0x968F, 7, // 随 + 0x9694, 7, // 隔 + 0x969B, 5, // 際 + 0x969C, 6, // 障 + 0x96A0, 7, // 隠 + 0x96A3, 7, // 隣 + 0x96B7, 7, // 隷 + 0x96BB, 7, // 隻 + 0x96C4, 7, // 雄 + 0x96C5, 7, // 雅 + 0x96C6, 3, // 集 + 0x96C7, 7, // 雇 + 0x96CC, 7, // 雌 + 0x96D1, 5, // 雑 + 0x96E2, 7, // 離 + 0x96E3, 6, // 難 + 0x96E8, 1, // 雹 + 0x96EA, 2, // 雪 + 0x96F0, 7, // 雰 + 0x96F2, 2, // 雲 + 0x96F6, 7, // 零 + 0x96F7, 7, // 雷 + 0x96FB, 2, // 電 + 0x9700, 7, // 需 + 0x9707, 7, // 震 + 0x970A, 7, // 霊 + 0x971C, 7, // 霜 + 0x9727, 7, // 霧 + 0x9732, 7, // 露 + 0x9752, 1, // 青 + 0x9759, 4, // 静 + 0x975E, 5, // 非 + 0x9762, 3, // 面 + 0x9769, 6, // 革 + 0x9774, 7, // 靎 + 0x97F3, 1, // 音 + 0x97FB, 7, // 韻 + 0x97FF, 7, // 響 + 0x9802, 6, // 頂 + 0x9805, 7, // 項 + 0x9806, 4, // 順 + 0x9810, 5, // 預 + 0x9811, 7, // 頑 + 0x9812, 7, // 頒 + 0x9818, 5, // 領 + 0x982D, 2, // é ­ + 0x983B, 7, // é » + 0x983C, 7, // é Œ + 0x984C, 3, // 題 + 0x984D, 5, // 額 + 0x9854, 2, // 顔 + 0x9855, 7, // 顕 + 0x9858, 4, // 願 + 0x985E, 4, // 類 + 0x9867, 7, // é¡§ + 0x98A8, 2, // 颚 + 0x98DB, 4, // 飛 + 0x98DF, 2, // 食 + 0x98E2, 7, // 飢 + 0x98EF, 4, // 飯 + 0x98F2, 3, // 飲 + 0x98FC, 5, // 飌 + 0x98FD, 7, // 飜 + 0x98FE, 7, // 食 + 0x990A, 4, // 逊 + 0x9913, 7, // 逓 + 0x9928, 3, // 通 + 0x9996, 2, // 驖 + 0x9999, 7, // 驙 + 0x99AC, 2, // 銬 + 0x99C4, 7, // 駄 + 0x99C5, 3, // 駅 + 0x99C6, 7, // 駆 + 0x99D0, 7, // 駐 + 0x9A0E, 7, // 階 + 0x9A12, 7, // 鹒 + 0x9A13, 4, // 鹓 + 0x9A30, 7, // éš° + 0x9A5A, 7, // 驚 + 0x9AA8, 6, // 骚 + 0x9AC4, 7, // 髄 + 0x9AD8, 2, // 高 + 0x9AEA, 7, // 髪 + 0x9B3C, 7, // 鬌 + 0x9B42, 7, // 魂 + 0x9B45, 7, // 魅 + 0x9B54, 7, // 魔 + 0x9B5A, 2, // 魚 + 0x9BAE, 7, // é®® + 0x9BE8, 7, // 鯚 + 0x9CE5, 2, // é³¥ + 0x9CF4, 2, // 鳎 + 0x9D8F, 7, // 鶏 + 0x9E97, 7, // 麗 + 0x9EA6, 2, // 麊 + 0x9EBB, 7, // 麻 + 0x9EC4, 2, // 黄 + 0x9ED2, 2, // 黒 + 0x9ED9, 7, // 黙 + 0x9F13, 7, // 錓 + 0x9F3B, 3, // 錻 + 0x9F62, 7, // 霢 +}; diff --git a/ui/ui.h b/ui/ui.h index 13150f38ff..0d39fc4c5f 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -245,7 +245,6 @@ void UIReset(); int UIButton(int id, const LayoutManager &layout, float w, float h, const char *text, int button_align); int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images. int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align, uint32_t color, int drop_shadow=0); // uses current UI atlas for fetching images. - // Returns 1 if clicked, puts the value in *value (where it also gets the current state). int UICheckBox(int id, int x, int y, const char *text, int align, bool *value); From b98957bf8dccec39f149bcf4c90d092acb98b070 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Apr 2013 20:55:46 +0200 Subject: [PATCH 0347/1445] Buildfix for linux --- base/stringutil.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/base/stringutil.cpp b/base/stringutil.cpp index fb4acebc33..69a4844f29 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include From 0023ec5f50f13b82f42a83a4487079f99e3169db Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Apr 2013 22:09:26 +0200 Subject: [PATCH 0348/1445] Add some more character ranges to atlastool, uncomment halfwidth ascii --- tools/atlastool.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 68f1920fa0..46932e9eaa 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -590,10 +590,13 @@ void GetLocales(const char *locales, std::vector &ranges) ranges.push_back(range(0xA2, 0xFF)); // 80 - A0 appears to contain nothing interesting ranges.push_back(range(0x2122, 0x2122)); // trademark symbol break; + case 'E': // Latin-1 Extended A (needed for Hungarian etc) + ranges.push_back(range(0x100, 0x17F)); + break; case 'k': // Katakana ranges.push_back(range(0x30A0, 0x30FF)); ranges.push_back(range(0x31F0, 0x31FF)); - // ranges.push_back(range(0xFF00, 0xFFEF)); // half-width ascii + ranges.push_back(range(0xFF00, 0xFFEF)); // half-width ascii break; case 'h': // Hiragana ranges.push_back(range(0x3041, 0x3097)); @@ -611,6 +614,9 @@ void GetLocales(const char *locales, std::vector &ranges) case 'c': // Japanese Kanji ranges.push_back(range(0x4E00, 0x9F92, kanji)); break; + case 'T': // Thai + ranges.push_back(range(0x0E00, 0x0E5B)); + break; } } From c5acf22754854c0e332fde35ab660594419abe56 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Apr 2013 22:36:43 +0200 Subject: [PATCH 0349/1445] IniFile: Add support for loading from VFS --- file/ini_file.cpp | 30 ++++++++++++++++++++++-------- file/ini_file.h | 3 +++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index e576289138..6aafa64b10 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -17,8 +17,7 @@ #include "base/stringutil.h" #include "file/ini_file.h" - -namespace { +#include "file/vfs.h" #ifdef _WIN32 // Function Cross-Compatibility @@ -58,8 +57,6 @@ static bool ParseLine(const std::string& line, std::string* keyOut, std::string* return false; } -} - std::string* IniFile::Section::GetLine(const char* key, std::string* valueOut, std::string* commentOut) { for (std::vector::iterator iter = lines.begin(); iter != lines.end(); ++iter) @@ -404,9 +401,6 @@ void IniFile::SortSections() bool IniFile::Load(const char* filename) { - // Maximum number of letters in a line - static const int MAX_BYTES = 1024*32; - sections.clear(); sections.push_back(Section("")); // first section consists of the comments before the first real section @@ -417,6 +411,27 @@ bool IniFile::Load(const char* filename) if (in.fail()) return false; + bool success = Load(in); + in.close(); + return success; +} + +bool IniFile::LoadFromVFS(const char *filename) { + size_t size; + uint8_t *data = VFSReadFile(filename, &size); + if (!data) + return false; + std::string str((const char*)data, size); + delete [] data; + + std::stringstream sstream(str); + return Load(sstream); +} + +bool IniFile::Load(std::istream &in) { + // Maximum number of letters in a line + static const int MAX_BYTES = 1024*32; + while (!in.eof()) { char templine[MAX_BYTES]; @@ -462,7 +477,6 @@ bool IniFile::Load(const char* filename) } } - in.close(); return true; } diff --git a/file/ini_file.h b/file/ini_file.h index fbf63e0328..e742f6c85b 100644 --- a/file/ini_file.h +++ b/file/ini_file.h @@ -116,6 +116,9 @@ public: bool Load(const char* filename); bool Load(const std::string &filename) { return Load(filename.c_str()); } + bool Load(std::istream &istream); + bool LoadFromVFS(const char *filename); + bool Save(const char* filename); bool Save(const std::string &filename) { return Save(filename.c_str()); } From 56f5fcf9755072f5a16ad6e9fcc39b0bde3e82ba Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Apr 2013 23:39:22 +0200 Subject: [PATCH 0350/1445] Fix language ini reading on android --- file/file_util.cpp | 2 ++ file/ini_file.cpp | 7 ++++--- file/ini_file.h | 2 +- file/zip_read.cpp | 24 +++++++++++++++++++----- i18n/i18n.cpp | 8 +++++--- i18n/i18n.h | 2 +- 6 files changed, 32 insertions(+), 13 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index f062d82d42..b4be4e3f00 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -222,6 +222,8 @@ size_t getFilesInDir(const char *directory, std::vector *files, const filter++; } } + if (tmp.size()) + filters.insert(tmp); #ifdef _WIN32 // Find the first file in the directory. WIN32_FIND_DATA ffd; diff --git a/file/ini_file.cpp b/file/ini_file.cpp index 6aafa64b10..045edc9d5f 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -416,9 +416,9 @@ bool IniFile::Load(const char* filename) return success; } -bool IniFile::LoadFromVFS(const char *filename) { +bool IniFile::LoadFromVFS(const std::string &filename) { size_t size; - uint8_t *data = VFSReadFile(filename, &size); + uint8_t *data = VFSReadFile(filename.c_str(), &size); if (!data) return false; std::string str((const char*)data, size); @@ -472,7 +472,8 @@ bool IniFile::Load(std::istream &in) { } else { - sections[sections.size() - 1].lines.push_back(line); + if (sections.size() > 0) + sections[sections.size() - 1].lines.push_back(line); } } } diff --git a/file/ini_file.h b/file/ini_file.h index e742f6c85b..aa5146e34e 100644 --- a/file/ini_file.h +++ b/file/ini_file.h @@ -117,7 +117,7 @@ public: bool Load(const char* filename); bool Load(const std::string &filename) { return Load(filename.c_str()); } bool Load(std::istream &istream); - bool LoadFromVFS(const char *filename); + bool LoadFromVFS(const std::string &filename); bool Save(const char* filename); bool Save(const std::string &filename) { return Save(filename.c_str()); } diff --git a/file/zip_read.cpp b/file/zip_read.cpp index cb01aa3191..de669a1f52 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -84,6 +84,7 @@ uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { bool ZipAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) { + ILOG("Zip path: %s", path); // We just loop through the whole ZIP file and deduce what files are in this directory, and what subdirectories there are. std::set files; std::set directories; @@ -95,7 +96,7 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis const char* name = zip_get_name(zip_file_, i, 0); if (!name) continue; - // ILOG("Comparing %s %s %i", name, path, pathlen); + ILOG("Comparing %s %s %i", name, path, pathlen); if (!memcmp(name, path, pathlen)) { // The prefix is right. Let's see if this is a file or path. char *slashPos = strchr(name + pathlen + 1, '/'); @@ -184,8 +185,19 @@ bool DirectoryAssetReader::GetFileListing(const char *path, std::vector *listing, const c int prefix_len = strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(path, entries[i].prefix, prefix_len)) { - entries[i].reader->GetFileListing(path + prefix_len, listing, filter); - return true; + if (entries[i].reader->GetFileListing(path + prefix_len, listing, filter)) + { + return true; + } } } ELOG("Missing filesystem for %s", path); diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp index 8dfb50faf8..883fd58688 100644 --- a/i18n/i18n.cpp +++ b/i18n/i18n.cpp @@ -1,3 +1,4 @@ +#include "base/logging.h" #include "i18n/i18n.h" #include "file/ini_file.h" @@ -50,10 +51,10 @@ std::string I18NRepo::GetIniPath(const std::string &languageID) const { return "lang/" + languageID + ".ini"; } -void I18NRepo::LoadIni(const std::string &languageID) { +bool I18NRepo::LoadIni(const std::string &languageID) { IniFile ini; - if (!ini.Load(GetIniPath(languageID))) { - return; + if (!ini.LoadFromVFS(GetIniPath(languageID))) { + return false; } Clear(); @@ -65,6 +66,7 @@ void I18NRepo::LoadIni(const std::string &languageID) { cats_[iter->name()] = LoadSection(&(*iter)); } } + return true; } I18NCategory *I18NRepo::LoadSection(const IniFile::Section *section) { diff --git a/i18n/i18n.h b/i18n/i18n.h index 41fb833c2c..b91d6840da 100644 --- a/i18n/i18n.h +++ b/i18n/i18n.h @@ -62,7 +62,7 @@ public: I18NRepo() {} ~I18NRepo(); - void LoadIni(const std::string &languageID); // NOT the filename! + bool LoadIni(const std::string &languageID); // NOT the filename! void SaveIni(const std::string &languageID); I18NCategory *GetCategory(const char *categoryName); From 2e9ff37dd76ab52735b6c8d6b2061bc18f3bdf58 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 19 Apr 2013 23:54:38 +0200 Subject: [PATCH 0351/1445] Support a 'training file' for chinese characters. --- tools/atlastool.cpp | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 46932e9eaa..97d4cd7548 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -28,6 +28,7 @@ #include "image/zim_save.h" #include "kanjifilter.h" +#include "util/text/utf8.h" #define CHECK(x) if (!(x)) { printf("%i: CHECK failed on this line\n", __LINE__); exit(1); } @@ -578,6 +579,33 @@ void GetLocales(const char *locales, std::vector &ranges) kanji.insert(kanjiFilter[i]); } } + + // Also, load chinese.txt if available. + FILE *f = fopen("chinese.txt", "rb"); + if (f) { + fseek(f, 0, SEEK_END); + size_t sz = ftell(f); + fseek(f, 0, SEEK_SET); + char *data = new char[sz+1]; + fread(data, 1, sz, f); + fclose(f); + data[sz]=0; + + UTF8 utf(data); + int learnCount = 0; + while (!utf.end()) { + uint32_t c = utf.next(); + if (c >= 0x3400) { + if (kanji.find(c) == kanji.end()) { + learnCount++; + kanji.insert(c); + } + } + } + delete [] data; + printf("%i Chinese charactes learned.\n", learnCount); + } + // The end point of a range is now inclusive! for (size_t i = 0; i < strlen(locales); i++) { @@ -593,6 +621,9 @@ void GetLocales(const char *locales, std::vector &ranges) case 'E': // Latin-1 Extended A (needed for Hungarian etc) ranges.push_back(range(0x100, 0x17F)); break; + case 'e': // Latin-1 Extended B (for some African and latinized asian languages?) + ranges.push_back(range(0x180, 0x250)); + break; case 'k': // Katakana ranges.push_back(range(0x30A0, 0x30FF)); ranges.push_back(range(0x31F0, 0x31FF)); @@ -611,8 +642,9 @@ void GetLocales(const char *locales, std::vector &ranges) case 'R': // Russian ranges.push_back(range(0x0400, 0x04FF)); break; - case 'c': // Japanese Kanji - ranges.push_back(range(0x4E00, 0x9F92, kanji)); + case 'c': // All Kanji, filtered though! + ranges.push_back(range(0x3400, 0x9FFF, kanji)); + ranges.push_back(range(0xF900, 0xFAFF, kanji)); break; case 'T': // Thai ranges.push_back(range(0x0E00, 0x0E5B)); From 4469c65cff172824ace13495acabc06969303f12 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 20 Apr 2013 00:00:51 +0200 Subject: [PATCH 0352/1445] Add ideographics symbols --- tools/atlastool.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 97d4cd7548..0ebc6865c1 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -643,6 +643,7 @@ void GetLocales(const char *locales, std::vector &ranges) ranges.push_back(range(0x0400, 0x04FF)); break; case 'c': // All Kanji, filtered though! + ranges.push_back(range(0x3000, 0x303f)); // Ideographic symbols ranges.push_back(range(0x3400, 0x9FFF, kanji)); ranges.push_back(range(0xF900, 0xFAFF, kanji)); break; From fd895a4b0e43d99b662e5b83887e86b4b647ae1e Mon Sep 17 00:00:00 2001 From: tpu Date: Sat, 20 Apr 2013 14:48:13 +0800 Subject: [PATCH 0353/1445] another FBO_ARB/FBO_EXT issue --- gfx/texture.cpp | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index c214dbaef5..7009d85d9d 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -11,8 +11,10 @@ #include "gfx/gl_debug_log.h" #include "gfx/gl_lost_manager.h" #include "gfx/gl_common.h" +#include "gfx_es2/gl_state.h" Texture::Texture() : id_(0) { + CheckGLExtensions(); register_gl_resource_holder(this); } @@ -138,7 +140,13 @@ bool Texture::LoadPNG(const char *filename) { SetTextureParameters(ZIM_GEN_MIPS); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); - glGenerateMipmap(GL_TEXTURE_2D); + if(gl_extensions.FBO_ARB){ + glGenerateMipmap(GL_TEXTURE_2D); + }else{ +#ifndef USING_GLES2 + glGenerateMipmapEXT(GL_TEXTURE_2D); +#endif + } GL_CHECK(); free(image_data); return true; @@ -156,8 +164,15 @@ bool Texture::LoadPNG(const uint8_t *data, size_t size, bool genMips) { SetTextureParameters(genMips ? ZIM_GEN_MIPS : ZIM_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); - if (genMips) - glGenerateMipmap(GL_TEXTURE_2D); + if (genMips) { + if(gl_extensions.FBO_ARB) { + glGenerateMipmap(GL_TEXTURE_2D); + }else{ +#ifndef USING_GLES2 + glGenerateMipmapEXT(GL_TEXTURE_2D); +#endif + } + } GL_CHECK(); free(image_data); return true; @@ -180,7 +195,13 @@ bool Texture::LoadXOR() { SetTextureParameters(ZIM_GEN_MIPS); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); - glGenerateMipmap(GL_TEXTURE_2D); + if(gl_extensions.FBO_ARB){ + glGenerateMipmap(GL_TEXTURE_2D); + }else{ +#ifndef USING_GLES2 + glGenerateMipmapEXT(GL_TEXTURE_2D); +#endif + } GL_CHECK(); delete [] buf; return true; @@ -274,7 +295,13 @@ bool Texture::LoadZIM(const char *filename) { colors, data_type, image_data[l]); } if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) { - glGenerateMipmap(GL_TEXTURE_2D); + if(gl_extensions.FBO_ARB) { + glGenerateMipmap(GL_TEXTURE_2D); + }else{ +#ifndef USING_GLES2 + glGenerateMipmapEXT(GL_TEXTURE_2D); +#endif + } } } SetTextureParameters(flags); From 491c32179e852d359f9fd73d5e20acca2ade6a70 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 20 Apr 2013 17:41:17 +0200 Subject: [PATCH 0354/1445] Korean support --- tools/atlastool.cpp | 49 ++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 0ebc6865c1..c6ecea034b 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -569,19 +569,9 @@ inline bool operator <(const CharRange &a, const CharRange &b) { return a.start < b.start; } -void GetLocales(const char *locales, std::vector &ranges) -{ - std::set kanji; - for (int i = 0; i < sizeof(kanjiFilter)/sizeof(kanjiFilter[0]); i+=2) - { - // TODO: learning level check? - if (kanjiFilter[i+1] > 0) { - kanji.insert(kanjiFilter[i]); - } - } - // Also, load chinese.txt if available. - FILE *f = fopen("chinese.txt", "rb"); +void LearnFile(const char *filename, const char *desc, std::set &chars, int lowerLimit, int upperLimit) { + FILE *f = fopen(filename, "rb"); if (f) { fseek(f, 0, SEEK_END); size_t sz = ftell(f); @@ -595,17 +585,37 @@ void GetLocales(const char *locales, std::vector &ranges) int learnCount = 0; while (!utf.end()) { uint32_t c = utf.next(); - if (c >= 0x3400) { - if (kanji.find(c) == kanji.end()) { + if (c >= lowerLimit && c <= upperLimit) { + if (chars.find(c) == chars.end()) { learnCount++; - kanji.insert(c); + chars.insert(c); } } } delete [] data; - printf("%i Chinese charactes learned.\n", learnCount); + printf("%i %s characters learned.\n", learnCount, desc); } +} + +void GetLocales(const char *locales, std::vector &ranges) +{ + std::set kanji; + std::set hangul1, hangul2, hangul3; + for (int i = 0; i < sizeof(kanjiFilter)/sizeof(kanjiFilter[0]); i+=2) + { + // TODO: learning level check? + if (kanjiFilter[i+1] > 0) { + kanji.insert(kanjiFilter[i]); + } + } + + // Also, load chinese.txt if available. + LearnFile("chinese.txt", "Chinese", kanji, 0x3400, 0xFFFF); + LearnFile("korean.txt", "Korean", hangul1, 0x1100, 0x11FF); + LearnFile("korean.txt", "Korean", hangul2, 0x3130, 0x318F); + LearnFile("korean.txt", "Korean", hangul3, 0xAC00, 0xD7A3); + // The end point of a range is now inclusive! for (size_t i = 0; i < strlen(locales); i++) { @@ -644,12 +654,15 @@ void GetLocales(const char *locales, std::vector &ranges) break; case 'c': // All Kanji, filtered though! ranges.push_back(range(0x3000, 0x303f)); // Ideographic symbols - ranges.push_back(range(0x3400, 0x9FFF, kanji)); - ranges.push_back(range(0xF900, 0xFAFF, kanji)); + ranges.push_back(range(0x4E00, 0x9FFF, kanji)); + // ranges.push_back(range(0xFB00, 0xFAFF, kanji)); break; case 'T': // Thai ranges.push_back(range(0x0E00, 0x0E5B)); break; + case 'K': // Korean (hangul) + ranges.push_back(range(0xAC00, 0xD7A3, hangul3)); + break; } } From d923a8f1e6806860f1cadd58582c2ad82d137ab6 Mon Sep 17 00:00:00 2001 From: JimLee168 Date: Sun, 21 Apr 2013 00:29:45 +0800 Subject: [PATCH 0355/1445] The event modify mutex use and increase the reset --- base/mutex.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index ebd73df85b..ead43f36a2 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -127,10 +127,10 @@ public: // broken #ifdef _WIN32 // This has to be horribly racy. - mtx.unlock(); + mtx.lock(); WaitForSingleObject(event_, INFINITE); ResetEvent(event_); // necessary? - mtx.lock(); + mtx.unlock(); #else pthread_mutex_lock(&mtx.native_handle()); pthread_cond_wait(&event_, &mtx.native_handle()); @@ -162,6 +162,11 @@ public: #endif } + void reset() { +#ifdef _WIN32 + ResetEvent(event_); +#endif + } private: #ifdef _WIN32 HANDLE event_; From 6868cb5d325b9e129dc74dd56b8461b98ee8b960 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 21 Apr 2013 16:36:05 +1000 Subject: [PATCH 0356/1445] Buildfix for Symbian. --- base/QtMain.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index f8ef3b9557..bd12b67818 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -56,13 +56,6 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); -#ifdef __SYMBIAN32__ - // Set RunFast hardware mode for VFPv2. Denormalised values are treated as 0. NaN used for all NaN situations. - User::SetFloatingPointMode(EFpModeRunFast); - // Disable screensaver - QSystemScreenSaver *ssObject = new QSystemScreenSaver(this); - ssObject->setScreenSaverInhibit(); -#endif QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) res.transpose(); @@ -91,6 +84,13 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) w.resize(pixel_xres, pixel_yres); w.showFullScreen(); #endif +#ifdef __SYMBIAN32__ + // Set RunFast hardware mode for VFPv2. + User::SetFloatingPointMode(EFpModeRunFast); + // Disable screensaver + QSystemScreenSaver *ssObject = new QSystemScreenSaver(&w); + ssObject->setScreenSaverInhibit(); +#endif MainAudio *audio = new MainAudio(); From ead5f5ade552776521ecf44242367825129025bb Mon Sep 17 00:00:00 2001 From: aquanull Date: Sun, 21 Apr 2013 23:13:07 +0800 Subject: [PATCH 0357/1445] Win32: Make getFileInfo() fail and label the path non-directory when GetFileAttributesExA fails This fixes the problem on Windows that the Language selection list might sometimes be blank. (The cause was that attrs would only contain random garbage data when GetFileAttributesExA failed with a non-existing path.) --- file/file_util.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index b4be4e3f00..681a6464b8 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -167,11 +167,13 @@ bool getFileInfo(const char *path, FileInfo *fileInfo) fileInfo->fullName = path; #ifdef _WIN32 - fileInfo->size = 0; WIN32_FILE_ATTRIBUTE_DATA attrs; - if (GetFileAttributesExA(path, GetFileExInfoStandard, &attrs)) { - fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32); + if (!GetFileAttributesExA(path, GetFileExInfoStandard, &attrs)) { + fileInfo->size = 0; + fileInfo->isDirectory = false; + return false; } + fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32); fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0; #else From 6126faef84b9fa79c6f401199facc68768894e7a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Apr 2013 10:39:32 -0700 Subject: [PATCH 0358/1445] Output a warning for missing glyphs in a font. --- tools/atlastool.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index c6ecea034b..2bc89b6566 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -341,6 +341,9 @@ void RasterizeFont(const char *fontfile, std::vector &ranges, int fon continue; } + if (FT_Get_Char_Index(font, kar) == 0) + fprintf(stderr, "WARNING: Font does not contain character %x.\n", kar); + // printf("%dx%d %p\n", font->glyph->bitmap.width, font->glyph->bitmap.rows, font->glyph->bitmap.buffer); const int bord = (128 + distmult - 1) / distmult + 1; if(font->glyph->bitmap.buffer) { From f6469b31dea43414959dadbc6d39e2cb84f5a50e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Apr 2013 11:51:58 -0700 Subject: [PATCH 0359/1445] Allow multiple ttfs per font, use first with char. --- tools/atlastool.cpp | 165 ++++++++++++++++++++++++++++++++------------ 1 file changed, 119 insertions(+), 46 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 2bc89b6566..45e0095afa 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -11,12 +11,12 @@ // line height // dist-per-pixel -#include - #include #include #include FT_FREETYPE_H #include +#include +#include #include #include #include @@ -67,6 +67,19 @@ Effect GetEffect(const char *text) { return FX_INVALID; } +struct FontReference { + FontReference(string name, string file, vector ranges, int pixheight) + : name_(name), file_(file), ranges_(ranges), size_(pixheight) { + } + + string name_; + string file_; + vector ranges_; + int size_; +}; + +typedef vector FontReferenceList; + template struct Image { vector > dat; @@ -296,24 +309,62 @@ struct Closest { return 0; return bmp.buffer[x + y * bmp.width]; } -}; +}; -void RasterizeFont(const char *fontfile, std::vector &ranges, int fontsize, float *metrics_height, Bucket *bucket) { - FT_Library freetype; - CHECK(FT_Init_FreeType(&freetype) == 0); +typedef vector FT_Face_List; - FT_Face font; - CHECK(FT_New_Face(freetype, fontfile, 0, &font) == 0); +inline vector merge(const vector &a, const vector &b) { + vector result = a; + for (size_t i = 0, in = b.size(); i < in; ++i) { + bool insert = true; + for (size_t j = 0, jn = a.size(); j < jn; ++j) { + // Should never overlap, so same start is always a duplicate. + if (b[i].start == a[j].start) { + insert = false; + break; + } + } - printf("TTF info: %d glyphs, %08x flags, %d units, %d strikes\n", (int)font->num_glyphs, (int)font->face_flags, (int)font->units_per_EM, (int)font->num_fixed_sizes); + if (insert) { + result.push_back(b[i]); + } + } - CHECK(FT_Set_Pixel_Sizes(font, 0, fontsize * supersample) == 0); + return result; +} +void RasterizeFonts(const FontReferenceList fontRefs, vector &ranges, float *metrics_height, Bucket *bucket) { + FT_Library freetype; + CHECK(FT_Init_FreeType(&freetype) == 0); + vector fonts; + fonts.resize(fontRefs.size()); - // Character range. TODO: Make definable. We might want unicode - // Convert all characters to bitmaps. - for (size_t r = 0; r < ranges.size(); r++) { + // The ranges may overlap, so build a list of fonts per range. + map fontsByRange; + // TODO: Better way than average? + float totalHeight = 0.0f; + + for (size_t i = 0, n = fontRefs.size(); i < n; ++i) { + FT_Face &font = fonts[i]; + CHECK(FT_New_Face(freetype, fontRefs[i].file_.c_str(), 0, &font) == 0); + printf("TTF info: %d glyphs, %08x flags, %d units, %d strikes\n", (int)font->num_glyphs, (int)font->face_flags, (int)font->units_per_EM, (int)font->num_fixed_sizes); + + CHECK(FT_Set_Pixel_Sizes(font, 0, fontRefs[i].size_ * supersample) == 0); + + ranges = merge(ranges, fontRefs[i].ranges_); + for (size_t r = 0, rn = fontRefs[i].ranges_.size(); r < rn; ++r) { + const CharRange &range = fontRefs[i].ranges_[r]; + fontsByRange[range.start].push_back(fonts[i]); + } + + totalHeight += font->size->metrics.height; + } + *metrics_height = totalHeight / (float) fontRefs.size(); + + // Convert all characters to bitmaps. + for (size_t r = 0, rn = ranges.size(); r < rn; r++) { + FT_Face_List &tryFonts = fontsByRange[ranges[r].start]; ranges[r].start_index = global_id; for(int kar = ranges[r].start; kar < ranges[r].end; kar++) { bool filtered = false; @@ -321,6 +372,19 @@ void RasterizeFont(const char *fontfile, std::vector &ranges, int fon if (ranges[r].filter.find((u16)kar) == ranges[r].filter.end()) filtered = true; } + + FT_Face font; + bool foundMatch = false; + for (size_t i = 0, n = tryFonts.size(); i < n; ++i) { + font = tryFonts[i]; + if (FT_Get_Char_Index(font, kar) != 0) { + foundMatch = true; + break; + } + } + if (!foundMatch) + fprintf(stderr, "WARNING: No font contains character %x.\n", kar); + Image img; if (filtered || 0 != FT_Load_Char(font, kar, FT_LOAD_RENDER|FT_LOAD_MONOCHROME)) { img.resize(1, 1); @@ -341,9 +405,6 @@ void RasterizeFont(const char *fontfile, std::vector &ranges, int fon continue; } - if (FT_Get_Char_Index(font, kar) == 0) - fprintf(stderr, "WARNING: Font does not contain character %x.\n", kar); - // printf("%dx%d %p\n", font->glyph->bitmap.width, font->glyph->bitmap.rows, font->glyph->bitmap.buffer); const int bord = (128 + distmult - 1) / distmult + 1; if(font->glyph->bitmap.buffer) { @@ -398,10 +459,12 @@ void RasterizeFont(const char *fontfile, std::vector &ranges, int fon dat.effect = FX_RED_TO_ALPHA_SOLID_WHITE; bucket->AddItem(img, dat); } - } + } - *metrics_height = font->size->metrics.height; - FT_Done_FreeType(freetype); + for (size_t i = 0, n = fonts.size(); i < n; ++i) { + FT_Done_Face(fonts[i]); + } + FT_Done_FreeType(freetype); } @@ -573,7 +636,7 @@ inline bool operator <(const CharRange &a, const CharRange &b) { } -void LearnFile(const char *filename, const char *desc, std::set &chars, int lowerLimit, int upperLimit) { +void LearnFile(const char *filename, const char *desc, std::set &chars, uint32_t lowerLimit, uint32_t upperLimit) { FILE *f = fopen(filename, "rb"); if (f) { fseek(f, 0, SEEK_END); @@ -689,6 +752,7 @@ int main(int argc, char **argv) { string image_name = string(atlas_name) + "_atlas.zim"; out_prefix = argv[2]; + map fontRefs; vector fonts; vector images; @@ -702,39 +766,30 @@ int main(int argc, char **argv) { int image_width; sscanf(line, "%i", &image_width); printf("Texture width: %i\n", image_width); - while (!feof(script)) { - if (!fgets(line, 511, script)) break; - if (!strlen(line)) break; - char *rest = strchr(line, ' '); - if (rest) { + while (!feof(script)) { + if (!fgets(line, 511, script)) break; + if (!strlen(line)) break; + char *rest = strchr(line, ' '); + if (rest) { *rest = 0; rest++; } - char *word = line; - if (!strcmp(word, "font")) { - // Font! - char fontname[256]; - char fontfile[256]; + char *word = line; + if (!strcmp(word, "font")) { + // Font! + char fontname[256]; + char fontfile[256]; char locales[256]; - int pixheight; - sscanf(rest, "%s %s %s %i", fontname, fontfile, locales, &pixheight); - printf("Font: %s (%s) in size %i. Locales: %s\n", fontname, fontfile, pixheight, locales); + int pixheight; + sscanf(rest, "%s %s %s %i", fontname, fontfile, locales, &pixheight); + printf("Font: %s (%s) in size %i. Locales: %s\n", fontname, fontfile, pixheight, locales); std::vector ranges; GetLocales(locales, ranges); printf("locales fetched.\n"); - FontDesc fnt; - fnt.first_char_id = (int)bucket.items.size(); - float metrics_height; - RasterizeFont(fontfile, ranges, pixheight, &metrics_height, &bucket); - printf("font rasterized.\n"); - - fnt.ranges = ranges; - fnt.name = fontname; - fnt.metrics_height = metrics_height; - - fonts.push_back(fnt); + FontReference fnt(fontname, fontfile, ranges, pixheight); + fontRefs[fontname].push_back(fnt); } else if (!strcmp(word, "image")) { char imagename[256]; char imagefile[256]; @@ -753,8 +808,26 @@ int main(int argc, char **argv) { } else { fprintf(stderr, "Warning: Failed to parse line starting with %s\n", line); } - } - fclose(script); + } + fclose(script); + + // Script fully read, now rasterize the fonts. + for (auto it = fontRefs.begin(), end = fontRefs.end(); it != end; ++it) { + FontDesc fnt; + fnt.first_char_id = (int)bucket.items.size(); + + vector finalRanges; + float metrics_height; + RasterizeFonts(it->second, finalRanges, &metrics_height, &bucket); + printf("font rasterized.\n"); + + fnt.ranges = finalRanges; + fnt.name = it->first; + fnt.metrics_height = metrics_height; + + fonts.push_back(fnt); + } + // Script read, all subimages have been generated. // Place the subimages onto the main texture. Also writes to png. From 8cd3304c29b699a6da82d4ae54c33f7c8d373dbf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Apr 2013 12:02:13 -0700 Subject: [PATCH 0360/1445] Shave 23% of time off of atlastool. No need to check a bool, let's just use goto. It's worth being faster. --- tools/atlastool.cpp | 46 +++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 45e0095afa..484b458248 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -212,35 +212,36 @@ int NextPowerOf2(int x) { } struct Bucket { - vector, Data> > items; - void AddItem(const Image &img, const Data &dat) { - items.push_back(make_pair(img, dat)); - } - vector Resolve(int image_width, Image &dest) { - // Place all the little images - whatever they are. - // Uses greedy fill algorithm. Slow but works surprisingly well, CPUs are fast. - Image masq; - masq.resize(image_width, 1); - dest.resize(image_width, 1); - sort(items.begin(), items.end()); - for (int i = 0; i < (int)items.size(); i++) { + vector, Data> > items; + void AddItem(const Image &img, const Data &dat) { + items.push_back(make_pair(img, dat)); + } + vector Resolve(int image_width, Image &dest) { + // Place all the little images - whatever they are. + // Uses greedy fill algorithm. Slow but works surprisingly well, CPUs are fast. + Image masq; + masq.resize(image_width, 1); + dest.resize(image_width, 1); + sort(items.begin(), items.end()); + for (int i = 0; i < (int)items.size(); i++) { if ((i + 1) % 200 == 0) { printf("Resolving (%i / %i)\n", i, (int)items.size()); } - int idx = items[i].first.dat[0].size(); - int idy = items[i].first.dat.size(); + int idx = items[i].first.dat[0].size(); + int idy = items[i].first.dat.size(); if (idx > 1 && idy > 1) { CHECK(idx <= image_width); - bool found = false; - for (int ty = 0; ty < 2047 && !found; ty++) { + for (int ty = 0; ty < 2047; ty++) { if(ty + idy + 1 > (int)dest.dat.size()) { masq.resize(image_width, ty + idy + 16); dest.resize(image_width, ty + idy + 16); } // Brute force packing. int sz = (int)items[i].first.dat[0].size(); - for (int tx = 0; tx < image_width - sz && !found; tx++) { - bool valid = !(masq.dat[ty][tx] || masq.dat[ty + idy - 1][tx] || masq.dat[ty][tx + idx - 1] || masq.dat[ty + idy - 1][tx + idx - 1]); + auto &masq_ty = masq.dat[ty]; + auto &masq_idy = masq.dat[ty + idy - 1]; + for (int tx = 0; tx < image_width - sz; tx++) { + bool valid = !(masq_ty[tx] || masq_idy[tx] || masq_ty[tx + idx - 1] || masq_idy[tx + idx - 1]); if (valid) { for(int ity = 0; ity < idy && valid; ity++) { for(int itx = 0; itx < idx && valid; itx++) { @@ -258,16 +259,17 @@ struct Bucket { items[i].second.ex = tx + idx; items[i].second.ey = ty + idy; - found = true; - // printf("Placed %d at %dx%d-%dx%d\n", items[i].second.id, tx, ty, tx + idx, ty + idy); + goto found; } skip: ; } } - } - } +found: + ; + } + } if ((int)dest.dat.size() > image_width * 2) { printf("PACKING FAIL : height=%i", (int)dest.dat.size()); From 25e03c243c271b921d3e65de47504efc22387ce3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 21 Apr 2013 21:53:46 +0200 Subject: [PATCH 0361/1445] Add vertical offset to fonts --- tools/atlastool.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 484b458248..ddae3b6014 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -68,14 +68,15 @@ Effect GetEffect(const char *text) { } struct FontReference { - FontReference(string name, string file, vector ranges, int pixheight) - : name_(name), file_(file), ranges_(ranges), size_(pixheight) { + FontReference(string name, string file, vector ranges, int pixheight, float vertOffset) + : name_(name), file_(file), ranges_(ranges), size_(pixheight), vertOffset_(vertOffset) { } string name_; string file_; vector ranges_; int size_; + float vertOffset_; }; typedef vector FontReferenceList; @@ -191,6 +192,7 @@ struct Data { int sx, sy, ex, ey; // offset from the origin float ox, oy; + float voffset; // to apply at the end // distance to move the origin forward float wx; @@ -377,8 +379,10 @@ void RasterizeFonts(const FontReferenceList fontRefs, vector &ranges, FT_Face font; bool foundMatch = false; + float vertOffset = 0; for (size_t i = 0, n = tryFonts.size(); i < n; ++i) { font = tryFonts[i]; + vertOffset = fontRefs[i].vertOffset_; if (FT_Get_Char_Index(font, kar) != 0) { foundMatch = true; break; @@ -455,6 +459,7 @@ void RasterizeFonts(const FontReferenceList fontRefs, vector &ranges, dat.ey = img.dat.size(); dat.ox = (float)font->glyph->metrics.horiBearingX / 64 / supersample - bord; dat.oy = -(float)font->glyph->metrics.horiBearingY / 64 / supersample - bord; + dat.voffset = vertOffset; dat.wx = (float)font->glyph->metrics.horiAdvance / 64 / supersample; dat.charNum = kar; @@ -550,7 +555,7 @@ struct FontDesc { results[idx].ex / tw, results[idx].ey / th, results[idx].ox, - results[idx].oy, + results[idx].oy + results[idx].voffset, results[idx].wx, results[idx].ex - results[idx].sx, results[idx].ey - results[idx].sy, results[idx].charNum); @@ -783,14 +788,15 @@ int main(int argc, char **argv) { char fontfile[256]; char locales[256]; int pixheight; - sscanf(rest, "%s %s %s %i", fontname, fontfile, locales, &pixheight); + float vertOffset; + sscanf(rest, "%s %s %s %i %f", fontname, fontfile, locales, &pixheight, &vertOffset); printf("Font: %s (%s) in size %i. Locales: %s\n", fontname, fontfile, pixheight, locales); std::vector ranges; GetLocales(locales, ranges); printf("locales fetched.\n"); - FontReference fnt(fontname, fontfile, ranges, pixheight); + FontReference fnt(fontname, fontfile, ranges, pixheight, vertOffset); fontRefs[fontname].push_back(fnt); } else if (!strcmp(word, "image")) { char imagename[256]; From e584a005ac06fb3af48cff9f4d9ed352de60fea3 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 22 Apr 2013 14:22:18 +1000 Subject: [PATCH 0362/1445] Define vasprintf is native, for Blackberry --- base/stringutil.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/base/stringutil.h b/base/stringutil.h index 026c2d0ff3..fe607fa9aa 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "base/basictypes.h" @@ -13,6 +14,42 @@ #pragma warning (disable:4996) #endif +#ifdef BLACKBERRY +// QNX Does not have an implementation of vasprintf +static inline int vasprintf(char **rResult, const char *aFormat, va_list aAp) +{ + int rVal; + char *result; + va_list ap; + + result = (char *) malloc(16); + if (result == NULL) return -1; + + va_copy(ap, aAp); + rVal = vsnprintf(result, 16, aFormat, ap); + va_end(ap); + + if (rVal == -1) + { + free(result); + return rVal; + } + else if (rVal >= 16) + { + free(result); + result = (char *) malloc(rVal + 1); + if (result == NULL) return -1; + + va_copy(ap, aAp); + rVal = vsnprintf(result, rVal + 1, aFormat, aAp); + va_end(ap); + } + + *rResult = result; + return rVal; +} +#endif + // Dumb wrapper around itoa, providing a buffer. Declare this on the stack. class ITOA { public: From c59ee2bccca9eeeb168f0bfb82f1459230981e28 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 22 Apr 2013 23:18:51 +1000 Subject: [PATCH 0363/1445] Update for Blackberry10. Update deprecated functions. Add support for Portrait QWERTY devices like Q10. --- base/BlackberryMain.cpp | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index ee15770c9e..e586618318 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -31,7 +31,11 @@ #include // Blackberry Window Manager #include // Invoke Service #include // Keyboard Service +#ifdef BLACKBERRY10 +#include // Accelerometer +#else #include // Accelerometer +#endif #include #include // Dialog Service (Toast=BB10) #ifdef BLACKBERRY10 @@ -359,7 +363,12 @@ int main(int argc, char *argv[]) { //Initialise Blackberry Platform Services bps_initialize(); // TODO: Enable/disable based on setting +#ifdef BLACKBERRY10 + sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, 25000); + sensor_request_events(SENSOR_TYPE_ACCELEROMETER); +#else accelerometer_set_update_frequency(FREQ_40_HZ); +#endif net::Init(); init_GLES2(screen_cxt); @@ -378,6 +387,7 @@ int main(int argc, char *argv[]) { int dpi = (int)(diagonal_pixels / diagonal_inches + 0.5); #endif float dpi_scale = 213.6f / dpi; + if (pixel_xres == 720) dpi_scale *= 1.4; dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); NativeInit(argc, (const char **)argv, "/accounts/1000/shared/documents/", "data/", "BADCOFFEE"); @@ -467,13 +477,31 @@ int main(int argc, char *argv[]) { running = false; break; } +#ifdef BLACKBERRY10 + } else if (domain == sensor_get_domain()) { + if (SENSOR_ACCELEROMETER_READING == bps_event_get_code(event)) { + float x, y, z; + sensor_event_get_xyz(event, &x, &y, &z); + if (pixel_xres == 1024 || pixel_xres == 720) // Q10 has this negative and reversed + { + input_state.acc.x = -y; + input_state.acc.y = -x; + } else { + input_state.acc.x = x; + input_state.acc.y = y; + } + input_state.acc.z = z; + } +#endif } } input_state.pad_buttons = pad_buttons; + pad_buttons = 0; +#ifndef BLACKBERRY10 // Handle accelerometer double x, y, z; accelerometer_read_forces(&x, &y, &z); - if (pixel_xres == 1024) // Playbook has this reversed + if (pixel_xres == 1024 || pixel_xres == 720) // Playbook has this reversed { input_state.acc.x = y; input_state.acc.y = x; @@ -482,13 +510,12 @@ int main(int argc, char *argv[]) { input_state.acc.y = y; } input_state.acc.z = z; +#endif UpdateInputState(&input_state); NativeUpdate(input_state); EndInputState(&input_state); NativeRender(); time_update(); - // TODO: For gestures, clear this where it is handled - pad_buttons &= ~PAD_BUTTON_MENU; // On Blackberry, this handles VSync for us eglSwapBuffers(egl_disp, egl_surf); } From 0a8acae315d87d25ead2e335f4933126965402ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Wed, 24 Apr 2013 17:07:13 +0200 Subject: [PATCH 0364/1445] First attempt at fixing native/tools build --- base/CMakeLists.txt | 2 +- tools/CMakeLists.txt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 4b2ef2255f..62bf4979b2 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -1,7 +1,7 @@ set(SRCS colorutil.cpp timeutil.cpp - threadutil.cpp + ../thread/threadutil.cpp error_context.cpp display.cpp buffer.cpp) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 4d7d8b2b1a..03523a7cb3 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -15,7 +15,7 @@ include_directories(..) include_directories(../math/lin) include_directories(../image) include_directories(../ext/libzip) -include_directories(../ext/etcpack) +include_directories(../ext/rg_etc1) include_directories(/usr/local/include) include_directories(${PNG_INCLUDE_DIR}) @@ -33,12 +33,12 @@ add_subdirectory(../file file) add_subdirectory(../image image) add_subdirectory(../math math) add_subdirectory(../ext/libzip libzip) -add_subdirectory(../ext/etcpack etcpack) +add_subdirectory(../ext/rg_etc1 rg_etc1) add_subdirectory(../ext/stb_image stb_image) add_executable(atlastool atlastool.cpp) -target_link_libraries(atlastool ${PNG_LIBRARY} freetype z image stb_image etcpack etcdec file zip gomp) +target_link_libraries(atlastool ${PNG_LIBRARY} freetype z image stb_image rg_etc1 etcdec file zip gomp) add_executable(zimtool zimtool.cpp) -target_link_libraries(zimtool ${PNG_LIBRARY} freetype z image stb_image etcpack etcdec file zip gomp) +target_link_libraries(zimtool ${PNG_LIBRARY} freetype z image stb_image rg_etc1 etcdec file zip gomp) From b7ab5e9905f43e6dcfd45a2871d9672baddb699a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20G?= Date: Wed, 24 Apr 2013 22:37:34 +0200 Subject: [PATCH 0365/1445] Fix build again when __SSE_4_2__ is enabled --- ext/cityhash/citycrc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/cityhash/citycrc.h b/ext/cityhash/citycrc.h index 318e3917ca..054d188a95 100644 --- a/ext/cityhash/citycrc.h +++ b/ext/cityhash/citycrc.h @@ -28,7 +28,7 @@ #ifndef CITY_HASH_CRC_H_ #define CITY_HASH_CRC_H_ -#include +#include "city.h" // Hash function for a byte array. uint128 CityHashCrc128(const char *s, size_t len); From 79bee5ac451014c1303196cc2045ee638114abb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Thu, 25 Apr 2013 12:47:21 +0200 Subject: [PATCH 0366/1445] Force std=c++11 --- tools/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 03523a7cb3..4545a64e46 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -9,6 +9,7 @@ add_definitions(-DSDL) add_definitions(-Wno-multichar) add_definitions(-fno-strict-aliasing) add_definitions(-fopenmp) +add_definitions(-std=c++11) # add_definitions(-fstrict-aliasing) include_directories(..) From 09495fb2a5a570209fba09b061d89fca1919cbd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Thu, 25 Apr 2013 12:58:55 +0200 Subject: [PATCH 0367/1445] Remove non-existent etcdec --- tools/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 4545a64e46..7298259c2b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -39,7 +39,7 @@ add_subdirectory(../ext/stb_image stb_image) add_executable(atlastool atlastool.cpp) -target_link_libraries(atlastool ${PNG_LIBRARY} freetype z image stb_image rg_etc1 etcdec file zip gomp) +target_link_libraries(atlastool ${PNG_LIBRARY} freetype z image stb_image rg_etc1 file zip gomp) add_executable(zimtool zimtool.cpp) -target_link_libraries(zimtool ${PNG_LIBRARY} freetype z image stb_image rg_etc1 etcdec file zip gomp) +target_link_libraries(zimtool ${PNG_LIBRARY} freetype z image stb_image rg_etc1 file zip gomp) From 479350271432d97d2ab04e5864fb330a92349b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 25 Apr 2013 14:19:53 +0200 Subject: [PATCH 0368/1445] atlastool CMake buildfix --- tools/CMakeLists.txt | 17 +++++++++++++++-- util/CMakeLists.txt | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 7298259c2b..48b888df4f 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -9,7 +9,19 @@ add_definitions(-DSDL) add_definitions(-Wno-multichar) add_definitions(-fno-strict-aliasing) add_definitions(-fopenmp) -add_definitions(-std=c++11) + +if(IOS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") +elseif(APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -mmacosx-version-min=10.7") +endif() + +if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7.0) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +endif() + # add_definitions(-fstrict-aliasing) include_directories(..) @@ -33,13 +45,14 @@ add_subdirectory(../gfx gfx) add_subdirectory(../file file) add_subdirectory(../image image) add_subdirectory(../math math) +add_subdirectory(../util util) add_subdirectory(../ext/libzip libzip) add_subdirectory(../ext/rg_etc1 rg_etc1) add_subdirectory(../ext/stb_image stb_image) add_executable(atlastool atlastool.cpp) -target_link_libraries(atlastool ${PNG_LIBRARY} freetype z image stb_image rg_etc1 file zip gomp) +target_link_libraries(atlastool ${PNG_LIBRARY} freetype util z image stb_image rg_etc1 file zip gomp) add_executable(zimtool zimtool.cpp) target_link_libraries(zimtool ${PNG_LIBRARY} freetype z image stb_image rg_etc1 file zip gomp) diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt index 3a05cb15bb..34e4dd907e 100644 --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -3,6 +3,7 @@ set(SRCS bits/varint.cpp random/perlin.cpp hash/hash.cpp + text/utf8.cpp ) set(SRCS ${SRCS}) From 56a1fb627839124a21260c40a5517b27de289b6a Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 28 Apr 2013 16:19:59 +1000 Subject: [PATCH 0369/1445] Maemo/Harmattan actually support std::bind and not lambdas --- thread/prioritizedworkqueue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index 2cb79c4d40..997f835cfb 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -95,7 +95,7 @@ static void threadfunc(PrioritizedWorkQueue *wq) { void ProcessWorkQueueOnThreadWhile(PrioritizedWorkQueue *wq) { workThread = new std::thread( -#if defined(__SYMBIAN32__) || defined(MAEMO) || defined(MEEGO_EDITION_HARMATTAN) || defined(BLACKBERRY) +#if defined(__SYMBIAN32__) || defined(BLACKBERRY) [wq](){threadfunc(wq);} #else std::bind(&threadfunc, wq) From 3fdbc2ea2193d6f29a45251039cddfc26bd18f7b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 28 Apr 2013 21:55:42 -0700 Subject: [PATCH 0370/1445] Mark cityhash to always be optimized, even in debug. This takes it from 10% to 0.34% in a debug build. We don't need to debug its internals, so there's no reason for debug to be slower. --- native.vcxproj | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/native.vcxproj b/native.vcxproj index 2366edce00..dee6f91a1a 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -295,7 +295,28 @@ - + + AnySuitable + true + Speed + AnySuitable + Speed + AnySuitable + true + Speed + false + AnySuitable + Speed + false + StreamingSIMDExtensions2 + Fast + StreamingSIMDExtensions2 + Fast + MaxSpeed + MaxSpeed + Default + Default + From dbff26fce55731d1d06709f328112a15f24ae03a Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Wed, 1 May 2013 13:15:52 +0200 Subject: [PATCH 0371/1445] Added NOMINMAX before including Windows.h in thread.h -- finally found where this came from --- thread/thread.h | 1 + 1 file changed, 1 insertion(+) diff --git a/thread/thread.h b/thread/thread.h index f32a96be92..21ea1f0c41 100644 --- a/thread/thread.h +++ b/thread/thread.h @@ -29,6 +29,7 @@ // WIN32 #define WIN32_LEAN_AND_MEAN +#define NOMINMAX #include #if defined(_MSC_VER) && defined(_MT) From 0fcf809d375597a003839bc16e0fb58a1e8583b7 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Wed, 1 May 2013 13:18:25 +0200 Subject: [PATCH 0372/1445] Added ThreadPool with parallel loop functionality --- native.vcxproj | 25 ++------------ native.vcxproj.filters | 6 ++++ thread/threadpool.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++ thread/threadpool.h | 57 ++++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 22 deletions(-) create mode 100644 thread/threadpool.cpp create mode 100644 thread/threadpool.h diff --git a/native.vcxproj b/native.vcxproj index dee6f91a1a..11b90a4b8f 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -245,6 +245,7 @@ + @@ -295,28 +296,7 @@ - - AnySuitable - true - Speed - AnySuitable - Speed - AnySuitable - true - Speed - false - AnySuitable - Speed - false - StreamingSIMDExtensions2 - Fast - StreamingSIMDExtensions2 - Fast - MaxSpeed - MaxSpeed - Default - Default - + @@ -358,6 +338,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index af6190b45d..da9f3d708f 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -251,6 +251,9 @@ file + + thread + @@ -444,6 +447,9 @@ file + + thread + diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp new file mode 100644 index 0000000000..86794c6faa --- /dev/null +++ b/thread/threadpool.cpp @@ -0,0 +1,74 @@ +#include "threadpool.h" + +///////////////////////////// WorkerThread + +WorkerThread::WorkerThread() : active(true), started(false) { + thread = new std::thread([&]() { WorkFunc(); }); + doneMutex.lock(); + while(!started) { }; +} + +WorkerThread::~WorkerThread() { + mutex.lock(); + active = false; + signal.notify_one(); + mutex.unlock(); + thread->join(); + delete thread; +} + +void WorkerThread::Process(const std::function& work) { + mutex.lock(); + work_ = work; + signal.notify_one(); + mutex.unlock(); +} + +void WorkerThread::WaitForCompletion() { + done.wait(doneMutex); +} + +void WorkerThread::WorkFunc() { + mutex.lock(); + started = true; + while(active) { + signal.wait(mutex); + if(active) work_(); + doneMutex.lock(); + done.notify_one(); + doneMutex.unlock(); + } +} + +///////////////////////////// ThreadPool + +ThreadPool::ThreadPool(int numThreads) : numThreads(numThreads), workersStarted(false) { +} + +void ThreadPool::StartWorkers() { + if(!workersStarted) { + for(int i=0; i()); + } + workersStarted = true; + } +} + +void ThreadPool::ParallelLoop(std::function loop, int lower, int upper) { + StartWorkers(); + int range = upper-lower; + if(range >= numThreads*2) { // don't parallelize tiny loops + // could do slightly better load balancing for the generic case, + // but doesn't matter since all our loops are power of 2 + int chunk = range/numThreads; + for(int s=lower, i=0; iProcess(std::bind(loop, s, std::min(s+chunk,upper))); + } + for(int i=0; iWaitForCompletion(); + } + } else { + loop(lower, upper); + } +} + diff --git a/thread/threadpool.h b/thread/threadpool.h new file mode 100644 index 0000000000..19b563c9d7 --- /dev/null +++ b/thread/threadpool.h @@ -0,0 +1,57 @@ +#pragma once + +#include "thread.h" +#include "base/mutex.h" + +#include +#include + +// This is the simplest possible worker implementation I can think of +// but entirely sufficient for the given purpose. +// Only handles a single item of work at a time. +class WorkerThread { +public: + WorkerThread(); + ~WorkerThread(); + + // submit a new work item + void Process(const std::function& work); + // wait for a submitted work item to be completed + void WaitForCompletion(); + +private: + std::thread *thread; // the worker thread + condition_variable signal; // used to signal new work + condition_variable done; // used to signal work completion + recursive_mutex mutex, doneMutex; // associated with each respective condition variable + volatile bool active, started; + std::function work_; // the work to be done by this thread + + void WorkFunc(); + + WorkerThread(const WorkerThread& other); // prevent copies + void operator =(const WorkerThread &other); +}; + +// A thread pool manages a set of worker threads, and allows the execution of parallel loops on them +// individual parallel loops are sequentialized, which should not be a problem as they should each +// use the entire system +class ThreadPool { +public: + ThreadPool(int numThreads); + // don't need a destructor, "workers" is cleared on delete, + // leading to the stopping and joining of all worker threads (RAII and all that) + + void ParallelLoop(std::function loop, int lower, int upper); + +private: + const int numThreads; + std::vector> workers; + recursive_mutex mutex; // used to sequentialize loop execution + + bool workersStarted; + void StartWorkers(); + + ThreadPool(const ThreadPool& other); // prevent copies + void operator =(const WorkerThread &other); +}; From f0f0fd2b75436b3e76d237b3eb26c684bc79c5c8 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Wed, 1 May 2013 13:20:25 +0200 Subject: [PATCH 0373/1445] Forgot loop sequentialization --- thread/threadpool.cpp | 2 ++ thread/threadpool.h | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp index 86794c6faa..cc596a6ab5 100644 --- a/thread/threadpool.cpp +++ b/thread/threadpool.cpp @@ -55,6 +55,7 @@ void ThreadPool::StartWorkers() { } void ThreadPool::ParallelLoop(std::function loop, int lower, int upper) { + mutex.lock(); StartWorkers(); int range = upper-lower; if(range >= numThreads*2) { // don't parallelize tiny loops @@ -70,5 +71,6 @@ void ThreadPool::ParallelLoop(std::function loop, int lower, int } else { loop(lower, upper); } + mutex.unlock(); } diff --git a/thread/threadpool.h b/thread/threadpool.h index 19b563c9d7..6f90073d8c 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -34,8 +34,8 @@ private: }; // A thread pool manages a set of worker threads, and allows the execution of parallel loops on them -// individual parallel loops are sequentialized, which should not be a problem as they should each -// use the entire system +// individual parallel loops are fully sequentialized to simplify synchronization, which should not +// be a problem as they should each use the entire system class ThreadPool { public: ThreadPool(int numThreads); From 7a22148583b541a22fe98a18ee0041af01e212e1 Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Wed, 1 May 2013 13:23:51 +0200 Subject: [PATCH 0374/1445] Added ThreadPool to Android Makefile, hope this works --- Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/Android.mk b/Android.mk index 2241f43cb8..2311998a62 100644 --- a/Android.mk +++ b/Android.mk @@ -45,6 +45,7 @@ LOCAL_SRC_FILES :=\ profiler/profiler.cpp \ thread/threadutil.cpp \ thread/prioritizedworkqueue.cpp \ + thread/threadpool.cpp \ gfx_es2/glsl_program.cpp \ gfx_es2/gl_state.cpp \ gfx_es2/draw_buffer.cpp.arm \ From c7399857e31690b7d92a20925ce43b0cdb628c3a Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Wed, 1 May 2013 14:06:29 +0200 Subject: [PATCH 0375/1445] Fixed potential shutdown deadlock issue --- thread/threadpool.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp index cc596a6ab5..dfbe73b14e 100644 --- a/thread/threadpool.cpp +++ b/thread/threadpool.cpp @@ -33,10 +33,12 @@ void WorkerThread::WorkFunc() { started = true; while(active) { signal.wait(mutex); - if(active) work_(); - doneMutex.lock(); - done.notify_one(); - doneMutex.unlock(); + if(active) { + work_(); + doneMutex.lock(); + done.notify_one(); + doneMutex.unlock(); + } } } @@ -58,7 +60,7 @@ void ThreadPool::ParallelLoop(std::function loop, int lower, int mutex.lock(); StartWorkers(); int range = upper-lower; - if(range >= numThreads*2) { // don't parallelize tiny loops + if(range >= numThreads*2) { // don't parallelize tiny loops (this could be better, maybe add optional parameter that estimates work per iteration) // could do slightly better load balancing for the generic case, // but doesn't matter since all our loops are power of 2 int chunk = range/numThreads; From c75510b304c2514447b151cc6b9bd04d688bd12c Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Wed, 1 May 2013 16:06:54 +0200 Subject: [PATCH 0376/1445] Eliminated lambda, undo debug compialtion changes --- native.vcxproj | 23 ++++++++++++++++++++++- thread/threadpool.cpp | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/native.vcxproj b/native.vcxproj index 11b90a4b8f..e9a230f557 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -296,7 +296,28 @@ - + + AnySuitable + true + Speed + AnySuitable + Speed + AnySuitable + true + Speed + false + AnySuitable + Speed + false + StreamingSIMDExtensions2 + Fast + StreamingSIMDExtensions2 + Fast + MaxSpeed + MaxSpeed + Default + Default + diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp index dfbe73b14e..8da01601a9 100644 --- a/thread/threadpool.cpp +++ b/thread/threadpool.cpp @@ -3,7 +3,7 @@ ///////////////////////////// WorkerThread WorkerThread::WorkerThread() : active(true), started(false) { - thread = new std::thread([&]() { WorkFunc(); }); + thread = new std::thread(std::bind(&WorkerThread::WorkFunc, this)); doneMutex.lock(); while(!started) { }; } From eb0f7f9b3a0554f0475f429d875df71df64f8998 Mon Sep 17 00:00:00 2001 From: nachume Date: Thu, 2 May 2013 00:22:59 +0900 Subject: [PATCH 0377/1445] submodule update. add define switch for the kanjifilter changing add utf-8 code table for the perfect convert to UTF-8 from ShiftJIS --- tools/atlastool.cpp | 10 +- tools/kanjifilter.h | 26427 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 24487 insertions(+), 1950 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index ddae3b6014..5ce4155919 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -28,6 +28,9 @@ #include "image/zim_save.h" #include "kanjifilter.h" +// #define USE_KANJI KANJI_STANDARD | KANJI_RARELY_USED | KANJI_LEVEL4 +// #define USE_KANJI KANJI_STANDARD +#define USE_KANJI KANJI_LEARNING_ORDER_ALL #include "util/text/utf8.h" #define CHECK(x) if (!(x)) { printf("%i: CHECK failed on this line\n", __LINE__); exit(1); } @@ -678,7 +681,7 @@ void GetLocales(const char *locales, std::vector &ranges) for (int i = 0; i < sizeof(kanjiFilter)/sizeof(kanjiFilter[0]); i+=2) { // TODO: learning level check? - if (kanjiFilter[i+1] > 0) { + if ((kanjiFilter[i+1] & USE_KANJI) > 0) { kanji.insert(kanjiFilter[i]); } } @@ -716,6 +719,11 @@ void GetLocales(const char *locales, std::vector &ranges) ranges.push_back(range(0x3041, 0x3097)); ranges.push_back(range(0x3099, 0x309F)); break; + case 's': // ShiftJIS symbols + ranges.push_back(range(0x2010, 0x2312)); // General Punctuation, Letterlike Symbols, Arrows, + // Mathematical Operators, Miscellaneous Technical + ranges.push_back(range(0x2500, 0x254B)); // Box drawing + ranges.push_back(range(0x25A0, 0x266F)); // Geometric Shapes, Miscellaneous Symbols case 'H': // Hebrew ranges.push_back(range(0x0590, 0x05FF)); break; diff --git a/tools/kanjifilter.h b/tools/kanjifilter.h index 03039b05b0..7ab817124e 100644 --- a/tools/kanjifilter.h +++ b/tools/kanjifilter.h @@ -1,1952 +1,24481 @@ -// http://www.tonypottier.info/Unicode_And_Japanese_Kanji/Appendix1.html -// http://www.tonypottier.info/Unicode_And_Japanese_Kanji/Appendix1.html +// http://www.asahi-net.or.jp/~ax2s-kmtn/character/japan.html +enum KANJI_LEVEL +{ + KANJI_LEARNING_ORDER_1 = 0x0001, + KANJI_LEARNING_ORDER_2 = 0x0002, + KANJI_LEARNING_ORDER_3 = 0x0004, + KANJI_LEARNING_ORDER_4 = 0x0008, + KANJI_LEARNING_ORDER_5 = 0x0010, + KANJI_LEARNING_ORDER_6 = 0x0020, + KANJI_LEARNING_ORDER_7 = 0x0040, + KANJI_LEARNING_ORDER_ADDTIONAL = 0x1000, // if you find garbled character when playing. + + KANJI_LEARNING_ORDER_ALL = 0x1FFF, + + // warning Cannot used. BlockAllocator size over. 2048x4096 size = 0x00400000 + KANJI_STANDARD = 0x2000, // daily use (JIS X 2008 = The level 1 JIS and The leve 2 JIS) + KANJI_RARELY_USED = 0x4000, // not daily use. but, The Chinese characters that may be used in a visual novel game maybe. (JIS X 2012 = The level 3 JIS) + KANJI_LEVEL4 = 0x8000, // JIS X 2008 extend. (JIS X 2008 + 1259 characters of JIS X 2012 + The level 4 JIS) + +}; // The parameter is the learning order. const unsigned short kanjiFilter[] = { - 0x4E00, 1, // 侀 - 0x4E01, 3, // 䞁 - 0x4E03, 1, // 䞃 - 0x4E07, 2, // 侇 - 0x4E08, 7, // 䞈 - 0x4E09, 1, // 侉 - 0x4E0A, 1, // 侊 - 0x4E0B, 1, // 例 - 0x4E0D, 4, // 䞍 - 0x4E0E, 7, // 侎 - 0x4E14, 7, // 侔 - 0x4E16, 3, // 侖 - 0x4E18, 7, // 䞘 - 0x4E19, 7, // 侙 - 0x4E21, 3, // äž¡ - 0x4E26, 6, // 䞊 - 0x4E2D, 1, // äž­ - 0x4E38, 2, // äžž - 0x4E39, 7, // äž¹ - 0x4E3B, 3, // äž» - 0x4E45, 5, // 久 - 0x4E4F, 7, // 乏 - 0x4E57, 3, // 乗 - 0x4E59, 7, // 乙 - 0x4E5D, 1, // 九 - 0x4E71, 6, // ä¹± - 0x4E73, 6, // ä¹³ - 0x4E7E, 7, // 也 - 0x4E86, 7, // 了 - 0x4E88, 3, // 予 - 0x4E89, 4, // 争 - 0x4E8B, 3, // 事 - 0x4E8C, 1, // 二 - 0x4E92, 7, // 互 - 0x4E94, 1, // 五 - 0x4E95, 7, // 井 - 0x4E9C, 7, // 亜 - 0x4EA1, 6, // 亡 - 0x4EA4, 2, // 亀 - 0x4EAB, 7, // 享 - 0x4EAC, 2, // 京 - 0x4EAD, 7, // 亭 - 0x4EBA, 1, // 人 - 0x4EC1, 6, // 仁 - 0x4ECA, 2, // 今 - 0x4ECB, 7, // 介 - 0x4ECF, 5, // 仏 - 0x4ED5, 3, // 仕 - 0x4ED6, 3, // 他 - 0x4ED8, 4, // 付 - 0x4ED9, 7, // 仙 - 0x4EE3, 3, // 代 - 0x4EE4, 4, // 什 - 0x4EE5, 4, // 以 - 0x4EEE, 5, // ä»® - 0x4EF0, 7, // ä»° - 0x4EF2, 4, // 仲 - 0x4EF6, 5, // ä»¶ - 0x4EFB, 5, // ä»» - 0x4F01, 7, // 䌁 - 0x4F0F, 7, // 䌏 - 0x4F10, 7, // 䌐 - 0x4F11, 1, // 䌑 - 0x4F1A, 2, // 䌚 - 0x4F1D, 4, // 䌝 - 0x4F2F, 7, // 䌯 - 0x4F34, 7, // 䌎 - 0x4F38, 7, // 䌞 - 0x4F3A, 7, // 䌺 - 0x4F3C, 5, // 䌌 - 0x4F46, 7, // 䜆 - 0x4F4D, 4, // 䜍 - 0x4F4E, 4, // 䜎 - 0x4F4F, 3, // 䜏 - 0x4F50, 7, // 䜐 - 0x4F53, 2, // 䜓 - 0x4F55, 2, // 䜕 - 0x4F59, 5, // 䜙 - 0x4F5C, 2, // 䜜 - 0x4F73, 7, // 䜳 - 0x4F75, 7, // 䜵 - 0x4F7F, 3, // 䜿 - 0x4F8B, 4, // 䟋 - 0x4F8D, 7, // 䟍 - 0x4F9B, 6, // 䟛 - 0x4F9D, 7, // 䟝 - 0x4FA1, 5, // 䟡 - 0x4FAE, 7, // 䟮 - 0x4FAF, 7, // 䟯 - 0x4FB5, 7, // 䟵 - 0x4FBF, 4, // 䟿 - 0x4FC2, 3, // 係 - 0x4FC3, 7, // 促 - 0x4FCA, 7, // 俊 - 0x4FD7, 7, // 俗 - 0x4FDD, 5, // 保 - 0x4FE1, 4, // ä¿¡ - 0x4FEE, 5, // ä¿® - 0x4FF3, 6, // 俳 - 0x4FF5, 5, // 俵 - 0x4FF8, 7, // 俞 - 0x5009, 4, // 倉 - 0x500B, 5, // 個 - 0x500D, 3, // 倍 - 0x5012, 7, // 倒 - 0x5019, 4, // 候 - 0x501F, 4, // 借 - 0x5023, 7, // 倣 - 0x5024, 6, // 倀 - 0x502B, 7, // 倫 - 0x5039, 7, // 倹 - 0x5049, 7, // 偉 - 0x504F, 7, // 偏 - 0x505C, 4, // 停 - 0x5065, 4, // 健 - 0x5074, 4, // 偎 - 0x5075, 7, // 偵 - 0x5076, 7, // 偶 - 0x507D, 7, // 停 - 0x508D, 7, // 傍 - 0x5091, 7, // 傑 - 0x5098, 7, // 傘 - 0x5099, 5, // 備 - 0x50AC, 7, // 催 - 0x50B5, 7, // 債 - 0x50B7, 6, // 傷 - 0x50BE, 7, // 傟 - 0x50CD, 4, // 働 - 0x50CF, 5, // 像 - 0x50D5, 7, // 僕 - 0x50DA, 7, // 僚 - 0x50E7, 7, // 僧 - 0x5100, 7, // 儀 - 0x5104, 4, // 億 - 0x5112, 7, // 儒 - 0x511F, 7, // 償 - 0x512A, 6, // 優 - 0x5143, 2, // 元 - 0x5144, 2, // 兄 - 0x5145, 7, // 充 - 0x5146, 4, // 兆 - 0x5148, 1, // 先 - 0x5149, 2, // 光 - 0x514B, 7, // 克 - 0x514D, 7, // 免 - 0x5150, 4, // 児 - 0x515A, 6, // 党 - 0x5165, 1, // 入 - 0x5168, 3, // å…š - 0x516B, 1, // 八 - 0x516C, 2, // 公 - 0x516D, 1, // 六 - 0x5171, 4, // 共 - 0x5175, 4, // 兵 - 0x5177, 3, // 具 - 0x5178, 4, // å…ž - 0x517C, 7, // å…Œ - 0x5185, 2, // 内 - 0x5186, 1, // 円 - 0x518A, 6, // 冊 - 0x518D, 5, // 再 - 0x5192, 7, // 冒 - 0x5197, 7, // 冗 - 0x5199, 3, // 写 - 0x51A0, 7, // 冠 - 0x51AC, 2, // 冬 - 0x51B7, 4, // 冷 - 0x51C6, 7, // 准 - 0x51CD, 7, // 凍 - 0x51DD, 7, // 凝 - 0x51E1, 7, // 凡 - 0x51E6, 6, // 凊 - 0x51F6, 7, // 凶 - 0x51F8, 7, // 凞 - 0x51F9, 7, // 凹 - 0x51FA, 1, // 出 - 0x5200, 2, // 刀 - 0x5203, 7, // 刃 - 0x5206, 2, // 分 - 0x5207, 2, // 切 - 0x5208, 7, // 刈 - 0x520A, 5, // 刊 - 0x5211, 7, // 刑 - 0x5217, 3, // 列 - 0x521D, 4, // 初 - 0x5224, 5, // 刀 - 0x5225, 4, // 別 - 0x5229, 4, // 利 - 0x5230, 7, // 到 - 0x5236, 5, // 制 - 0x5237, 4, // 刷 - 0x5238, 5, // 刞 - 0x523A, 7, // 刺 - 0x523B, 6, // 刻 - 0x5247, 5, // 則 - 0x524A, 7, // 削 - 0x524D, 2, // 前 - 0x5256, 7, // 剖 - 0x525B, 7, // 剛 - 0x5263, 7, // 剣 - 0x5264, 7, // 剀 - 0x526F, 4, // 副 - 0x5270, 7, // 剰 - 0x5272, 6, // 割 - 0x5275, 6, // 創 - 0x5287, 6, // 劇 - 0x529B, 1, // 力 - 0x529F, 4, // 功 - 0x52A0, 4, // 加 - 0x52A3, 7, // 劣 - 0x52A9, 3, // 助 - 0x52AA, 4, // 努 - 0x52B1, 7, // 励 - 0x52B4, 4, // 劎 - 0x52B9, 5, // 効 - 0x52BE, 7, // 功 - 0x52C5, 7, // 勅 - 0x52C7, 4, // 勇 - 0x52C9, 3, // 勉 - 0x52D5, 3, // 動 - 0x52D8, 7, // 勘 - 0x52D9, 5, // 務 - 0x52DD, 3, // 勝 - 0x52DF, 7, // 募 - 0x52E2, 5, // 勢 - 0x52E4, 6, // å‹€ - 0x52E7, 7, // 勧 - 0x52F2, 7, // 勲 - 0x52FA, 7, // 勺 - 0x5301, 7, // 匁 - 0x5305, 4, // 包 - 0x5316, 3, // 化 - 0x5317, 2, // 北 - 0x5320, 7, // 匠 - 0x5339, 7, // 匹 - 0x533A, 3, // 区 - 0x533B, 3, // 医 - 0x533F, 7, // 匿 - 0x5341, 1, // 十 - 0x5343, 1, // 千 - 0x5347, 7, // 升 - 0x5348, 2, // 午 - 0x534A, 2, // 半 - 0x5351, 7, // 卑 - 0x5352, 4, // 卒 - 0x5353, 7, // 卓 - 0x5354, 4, // 協 - 0x5357, 2, // 南 - 0x5358, 4, // 単 - 0x535A, 4, // 博 - 0x5360, 7, // 占 - 0x5370, 4, // 印 - 0x5371, 6, // 危 - 0x5373, 7, // 即 - 0x5374, 7, // 华 - 0x5375, 6, // 卵 - 0x5378, 7, // 卞 - 0x5384, 7, // 厄 - 0x5398, 7, // 厘 - 0x539A, 5, // 厚 - 0x539F, 2, // 原 - 0x53B3, 6, // 厳 - 0x53BB, 3, // 去 - 0x53C2, 4, // 参 - 0x53C8, 7, // 又 - 0x53CA, 7, // 及 - 0x53CB, 2, // 友 - 0x53CC, 7, // 双 - 0x53CD, 3, // 反 - 0x53CE, 6, // 収 - 0x53D4, 7, // 叔 - 0x53D6, 3, // 取 - 0x53D7, 3, // 受 - 0x53D9, 7, // 叙 - 0x53E3, 1, // 口 - 0x53E4, 2, // 叀 - 0x53E5, 5, // 句 - 0x53EB, 7, // 叫 - 0x53EC, 7, // 召 - 0x53EF, 5, // 可 - 0x53F0, 2, // 台 - 0x53F2, 4, // 史 - 0x53F3, 1, // 右 - 0x53F7, 3, // 号 - 0x53F8, 4, // 叞 - 0x5404, 4, // 各 - 0x5408, 2, // 合 - 0x5409, 7, // 吉 - 0x540C, 2, // 同 - 0x540D, 1, // 名 - 0x540E, 6, // 后 - 0x540F, 7, // 吏 - 0x5410, 7, // 吐 - 0x5411, 3, // 向 - 0x541B, 3, // 君 - 0x541F, 7, // 吟 - 0x5426, 6, // 吊 - 0x542B, 7, // 含 - 0x5438, 6, // 吞 - 0x5439, 7, // 吹 - 0x5448, 7, // 呈 - 0x5449, 7, // 呉 - 0x544A, 4, // 告 - 0x5468, 4, // 呚 - 0x5473, 3, // 味 - 0x547C, 6, // 呌 - 0x547D, 3, // 呜 - 0x548C, 3, // 和 - 0x54B2, 7, // 咲 - 0x54C0, 7, // 哀 - 0x54C1, 3, // 品 - 0x54E1, 3, // 員 - 0x54F2, 7, // 哲 - 0x5506, 7, // 唆 - 0x5507, 7, // 唇 - 0x5510, 7, // 唐 - 0x552F, 7, // 唯 - 0x5531, 4, // 唱 - 0x5546, 3, // 商 - 0x554F, 3, // 問 - 0x5553, 7, // 啓 - 0x5584, 6, // 善 - 0x559A, 7, // 喚 - 0x559C, 4, // 喜 - 0x559D, 7, // 喝 - 0x55AA, 7, // 喪 - 0x55AB, 7, // 喫 - 0x55B6, 5, // 営 - 0x55E3, 7, // 嗣 - 0x5606, 7, // 嘆 - 0x5631, 7, // 嘱 - 0x5668, 4, // 噚 - 0x5674, 7, // 噎 - 0x5687, 7, // 嚇 - 0x56DA, 7, // 囚 - 0x56DB, 1, // 四 - 0x56DE, 2, // 回 - 0x56E0, 5, // 因 - 0x56E3, 5, // 団 - 0x56F0, 6, // 困 - 0x56F2, 4, // 囲 - 0x56F3, 2, // 図 - 0x56FA, 4, // 固 - 0x56FD, 2, // 囜 - 0x570F, 7, // 圏 - 0x5712, 2, // 園 - 0x571F, 1, // 土 - 0x5727, 5, // 圧 - 0x5728, 5, // 圚 - 0x5730, 2, // 地 - 0x5742, 3, // 坂 - 0x5747, 5, // 均 - 0x574A, 7, // 坊 - 0x5751, 7, // 坑 - 0x576A, 7, // 坪 - 0x5782, 6, // 垂 - 0x578B, 4, // 型 - 0x57A3, 7, // 垣 - 0x57CB, 7, // 埋 - 0x57CE, 6, // 城 - 0x57DF, 6, // 域 - 0x57F7, 7, // 執 - 0x57F9, 7, // 培 - 0x57FA, 5, // 基 - 0x5800, 7, // 堀 - 0x5802, 4, // 堂 - 0x5805, 7, // 堅 - 0x5815, 7, // 堕 - 0x5824, 7, // å € - 0x582A, 7, // å ª - 0x5831, 5, // å ± - 0x5834, 2, // å Ž - 0x5840, 7, // 塀 - 0x5841, 7, // 塁 - 0x584A, 7, // 塊 - 0x5851, 7, // 塑 - 0x5854, 7, // 塔 - 0x5857, 7, // 塗 - 0x585A, 7, // 塚 - 0x5869, 4, // å¡© - 0x587E, 7, // 塟 - 0x5883, 5, // 境 - 0x5893, 5, // 墓 - 0x5897, 5, // 増 - 0x589C, 7, // 墜 - 0x58A8, 7, // 墚 - 0x58B3, 7, // 墳 - 0x58BE, 7, // 墟 - 0x58C1, 7, // 壁 - 0x58C7, 7, // 壇 - 0x58CA, 7, // 壊 - 0x58CC, 7, // 壌 - 0x58EB, 4, // 士 - 0x58EE, 7, // 壮 - 0x58F0, 2, // 声 - 0x58F1, 7, // 壱 - 0x58F2, 2, // 売 - 0x5909, 4, // 倉 - 0x590F, 2, // 倏 - 0x5915, 1, // 倕 - 0x5916, 2, // 倖 - 0x591A, 2, // 倚 - 0x591C, 2, // 倜 - 0x5922, 5, // 倢 - 0x5927, 1, // 倧 - 0x5929, 1, // 倩 - 0x592A, 2, // 倪 - 0x592B, 4, // 倫 - 0x592E, 3, // 倮 - 0x5931, 4, // 倱 - 0x5947, 7, // 奇 - 0x5949, 7, // 奉 - 0x594F, 6, // 奏 - 0x5951, 7, // 契 - 0x5954, 7, // 奔 - 0x5965, 7, // 奥 - 0x5968, 7, // 奚 - 0x596A, 7, // 奪 - 0x596E, 6, // 奮 - 0x5973, 1, // 女 - 0x5974, 7, // 奎 - 0x597D, 4, // 奜 - 0x5982, 7, // 劂 - 0x5983, 7, // 劃 - 0x5984, 7, // 劄 - 0x598A, 7, // 劊 - 0x5999, 7, // 劙 - 0x59A5, 7, // 劥 - 0x59A8, 7, // 劚 - 0x59B9, 2, // 効 - 0x59BB, 5, // 劻 - 0x59C9, 2, // 姉 - 0x59CB, 3, // 始 - 0x59D3, 7, // 姓 - 0x59D4, 3, // 委 - 0x59EB, 7, // å§« - 0x59FB, 7, // å§» - 0x59FF, 6, // å§¿ - 0x5A01, 7, // 嚁 - 0x5A18, 7, // 嚘 - 0x5A20, 7, // åš  - 0x5A2F, 7, // 嚯 - 0x5A46, 7, // 婆 - 0x5A5A, 7, // 婚 - 0x5A66, 5, // 婊 - 0x5A7F, 7, // å©¿ - 0x5A92, 7, // 媒 - 0x5AC1, 7, // 嫁 - 0x5ACC, 7, // 嫌 - 0x5AE1, 7, // å«¡ - 0x5B22, 7, // 嬢 - 0x5B50, 1, // 子 - 0x5B54, 7, // 孔 - 0x5B57, 1, // 字 - 0x5B58, 6, // 存 - 0x5B5D, 6, // 孝 - 0x5B63, 4, // å­£ - 0x5B64, 7, // å­€ - 0x5B66, 1, // å­Š - 0x5B6B, 4, // å­« - 0x5B85, 6, // 宅 - 0x5B87, 6, // 宇 - 0x5B88, 3, // 守 - 0x5B89, 3, // 安 - 0x5B8C, 4, // 完 - 0x5B97, 6, // 宗 - 0x5B98, 4, // 官 - 0x5B99, 6, // 宙 - 0x5B9A, 3, // 定 - 0x5B9C, 7, // 宜 - 0x5B9D, 6, // 宝 - 0x5B9F, 3, // 実 - 0x5BA2, 3, // 客 - 0x5BA3, 6, // 宣 - 0x5BA4, 2, // 宀 - 0x5BAE, 3, // å®® - 0x5BB0, 7, // å®° - 0x5BB3, 4, // 害 - 0x5BB4, 7, // 宎 - 0x5BB5, 7, // 宵 - 0x5BB6, 2, // å®¶ - 0x5BB9, 5, // 容 - 0x5BBF, 3, // 宿 - 0x5BC2, 7, // 寂 - 0x5BC4, 5, // 寄 - 0x5BC6, 6, // 密 - 0x5BCC, 5, // 富 - 0x5BD2, 3, // 寒 - 0x5BDB, 7, // 寛 - 0x5BDD, 7, // 寝 - 0x5BDF, 4, // 察 - 0x5BE1, 7, // 寡 - 0x5BE7, 7, // 寧 - 0x5BE9, 7, // 審 - 0x5BEE, 7, // 寮 - 0x5BF8, 6, // 寞 - 0x5BFA, 2, // 寺 - 0x5BFE, 3, // 察 - 0x5BFF, 7, // 寿 - 0x5C01, 7, // 封 - 0x5C02, 6, // 専 - 0x5C04, 6, // 射 - 0x5C06, 6, // 将 - 0x5C09, 7, // 尉 - 0x5C0A, 6, // 尊 - 0x5C0B, 7, // 尋 - 0x5C0E, 5, // 導 - 0x5C0F, 1, // 小 - 0x5C11, 2, // 少 - 0x5C1A, 7, // 尚 - 0x5C31, 6, // å°± - 0x5C3A, 6, // å°º - 0x5C3C, 7, // å°Œ - 0x5C3D, 7, // å°œ - 0x5C3E, 7, // å°Ÿ - 0x5C3F, 7, // å°¿ - 0x5C40, 3, // 局 - 0x5C45, 5, // 居 - 0x5C48, 7, // 屈 - 0x5C4A, 6, // 届 - 0x5C4B, 3, // 屋 - 0x5C55, 6, // 展 - 0x5C5E, 5, // 属 - 0x5C64, 6, // å±€ - 0x5C65, 7, // å±¥ - 0x5C6F, 7, // 屯 - 0x5C71, 1, // å±± - 0x5C90, 7, // 岐 - 0x5CA9, 2, // 岩 - 0x5CAC, 7, // 岬 - 0x5CB3, 7, // å²³ - 0x5CB8, 3, // 岞 - 0x5CE0, 7, // å³  - 0x5CE1, 7, // 峡 - 0x5CF0, 7, // å³° - 0x5CF6, 3, // å³¶ - 0x5D07, 7, // 厇 - 0x5D0E, 7, // 厎 - 0x5D29, 7, // 厩 - 0x5DDD, 1, // 川 - 0x5DDE, 3, // 州 - 0x5DE1, 7, // å·¡ - 0x5DE3, 4, // å·£ - 0x5DE5, 2, // å·¥ - 0x5DE6, 1, // å·Š - 0x5DE7, 7, // å·§ - 0x5DE8, 7, // å·š - 0x5DEE, 4, // å·® - 0x5DF1, 6, // å·± - 0x5DFB, 6, // å·» - 0x5E02, 2, // åž‚ - 0x5E03, 5, // 垃 - 0x5E06, 7, // 垆 - 0x5E0C, 4, // 垌 - 0x5E1D, 7, // 垝 - 0x5E25, 7, // 垥 - 0x5E2B, 5, // åž« - 0x5E2D, 4, // åž­ - 0x5E2F, 4, // 垯 - 0x5E30, 2, // åž° - 0x5E33, 3, // åž³ - 0x5E38, 5, // åžž - 0x5E3D, 7, // åžœ - 0x5E45, 7, // 幅 - 0x5E55, 6, // 幕 - 0x5E63, 7, // å¹£ - 0x5E72, 6, // å¹² - 0x5E73, 3, // å¹³ - 0x5E74, 1, // 幎 - 0x5E78, 3, // 幞 - 0x5E79, 5, // å¹¹ - 0x5E7B, 7, // å¹» - 0x5E7C, 6, // 幌 - 0x5E7D, 7, // 幜 - 0x5E7E, 7, // 幟 - 0x5E81, 6, // 庁 - 0x5E83, 2, // 広 - 0x5E8A, 7, // 床 - 0x5E8F, 5, // 序 - 0x5E95, 4, // 底 - 0x5E97, 2, // 店 - 0x5E9C, 4, // 府 - 0x5EA6, 3, // 床 - 0x5EA7, 6, // 座 - 0x5EAB, 3, // 庫 - 0x5EAD, 3, // 庭 - 0x5EB6, 7, // 庶 - 0x5EB7, 4, // 康 - 0x5EB8, 7, // 庞 - 0x5EC3, 7, // 廃 - 0x5EC9, 7, // 廉 - 0x5ECA, 7, // 廊 - 0x5EF6, 6, // å»¶ - 0x5EF7, 7, // å»· - 0x5EFA, 4, // 建 - 0x5F01, 5, // 匁 - 0x5F0A, 7, // 匊 - 0x5F0F, 3, // 匏 - 0x5F10, 7, // 匐 - 0x5F13, 2, // 匓 - 0x5F14, 7, // 匔 - 0x5F15, 2, // 匕 - 0x5F1F, 2, // 匟 - 0x5F26, 7, // 匊 - 0x5F27, 7, // 匧 - 0x5F31, 2, // 匱 - 0x5F35, 5, // 匵 - 0x5F37, 2, // 匷 - 0x5F3E, 7, // 匟 - 0x5F53, 2, // 圓 - 0x5F62, 2, // 圢 - 0x5F69, 7, // 圩 - 0x5F6B, 7, // 圫 - 0x5F70, 7, // 地 - 0x5F71, 7, // 圱 - 0x5F79, 3, // 圹 - 0x5F7C, 7, // 圌 - 0x5F80, 5, // 埀 - 0x5F81, 7, // 埁 - 0x5F84, 4, // 埄 - 0x5F85, 3, // 埅 - 0x5F8B, 6, // 埋 - 0x5F8C, 2, // 埌 - 0x5F90, 7, // 埐 - 0x5F92, 4, // 埒 - 0x5F93, 6, // 埓 - 0x5F97, 4, // 埗 - 0x5FA1, 7, // 埡 - 0x5FA9, 5, // 埩 - 0x5FAA, 7, // 埪 - 0x5FAE, 7, // 埮 - 0x5FB3, 5, // 埳 - 0x5FB4, 7, // 城 - 0x5FB9, 7, // 培 - 0x5FC3, 2, // 心 - 0x5FC5, 4, // 必 - 0x5FCC, 7, // 忌 - 0x5FCD, 7, // 忍 - 0x5FD7, 5, // 志 - 0x5FD8, 6, // 忘 - 0x5FD9, 7, // 忙 - 0x5FDC, 5, // 応 - 0x5FE0, 6, // å¿  - 0x5FEB, 5, // å¿« - 0x5FF5, 4, // 念 - 0x6012, 7, // 怒 - 0x6016, 7, // 怖 - 0x601D, 2, // 思 - 0x6020, 7, // 怠 - 0x6025, 3, // 急 - 0x6027, 5, // 性 - 0x602A, 7, // 怪 - 0x604B, 7, // 恋 - 0x6050, 7, // 恐 - 0x6052, 7, // 恒 - 0x6065, 7, // 恥 - 0x6068, 7, // 恚 - 0x6069, 5, // 恩 - 0x606D, 7, // 恭 - 0x606F, 3, // 息 - 0x6075, 7, // 恵 - 0x6094, 7, // 悔 - 0x609F, 7, // 悟 - 0x60A0, 7, // 悠 - 0x60A3, 7, // 患 - 0x60A6, 7, // 悊 - 0x60A9, 7, // 悩 - 0x60AA, 3, // 悪 - 0x60B2, 3, // 悲 - 0x60BC, 7, // 悌 - 0x60C5, 5, // 情 - 0x60D1, 7, // 惑 - 0x60DC, 7, // 惜 - 0x60E8, 7, // 惚 - 0x60F0, 7, // 惰 - 0x60F3, 3, // 想 - 0x6101, 7, // 愁 - 0x6109, 7, // 愉 - 0x610F, 3, // 意 - 0x611A, 7, // 愚 - 0x611B, 4, // 愛 - 0x611F, 3, // 感 - 0x6148, 7, // 慈 - 0x614B, 5, // 態 - 0x614C, 7, // 慌 - 0x614E, 7, // 慎 - 0x6155, 7, // 慕 - 0x6162, 7, // 慢 - 0x6163, 5, // 慣 - 0x6168, 7, // æ…š - 0x616E, 7, // 慮 - 0x6170, 7, // 慰 - 0x6176, 7, // 慶 - 0x6182, 7, // 憂 - 0x618E, 7, // 憎 - 0x61A4, 7, // 憀 - 0x61A9, 7, // 憩 - 0x61B2, 6, // 憲 - 0x61B6, 7, // 憶 - 0x61BE, 7, // 憟 - 0x61C7, 7, // 懇 - 0x61D0, 7, // 懐 - 0x61F2, 7, // 懲 - 0x61F8, 7, // 懞 - 0x6210, 4, // 成 - 0x6211, 6, // 我 - 0x6212, 7, // 戒 - 0x6226, 4, // 戊 - 0x622F, 7, // 戯 - 0x6238, 2, // 戞 - 0x623B, 7, // 戻 - 0x623F, 7, // 房 - 0x6240, 3, // 所 - 0x6247, 7, // 扇 - 0x6249, 7, // 扉 - 0x624B, 1, // 手 - 0x624D, 2, // 才 - 0x6253, 3, // 打 - 0x6255, 7, // 払 - 0x6271, 7, // 扱 - 0x6276, 7, // 扶 - 0x6279, 6, // 批 - 0x627F, 5, // 承 - 0x6280, 5, // 技 - 0x6284, 7, // 抄 - 0x628A, 7, // 把 - 0x6291, 7, // 抑 - 0x6295, 3, // 投 - 0x6297, 7, // 抗 - 0x6298, 4, // 折 - 0x629C, 7, // 抜 - 0x629E, 7, // 択 - 0x62AB, 7, // 披 - 0x62B1, 7, // 抱 - 0x62B5, 7, // 抵 - 0x62B9, 7, // 抹 - 0x62BC, 7, // 抌 - 0x62BD, 7, // 抜 - 0x62C5, 6, // 担 - 0x62CD, 7, // 拍 - 0x62D0, 7, // 拐 - 0x62D2, 7, // 拒 - 0x62D3, 7, // 拓 - 0x62D8, 7, // 拘 - 0x62D9, 7, // 拙 - 0x62DB, 5, // 招 - 0x62DD, 6, // 拝 - 0x62E0, 7, // 拠 - 0x62E1, 6, // 拡 - 0x62EC, 7, // 括 - 0x62F7, 7, // 拷 - 0x62FE, 3, // 拟 - 0x6301, 3, // 持 - 0x6307, 3, // 指 - 0x6311, 7, // 挑 - 0x6319, 4, // 挙 - 0x631F, 7, // 挟 - 0x632F, 7, // 振 - 0x633F, 7, // 挿 - 0x6355, 7, // 捕 - 0x635C, 7, // 捜 - 0x6368, 6, // 捚 - 0x636E, 7, // 据 - 0x6383, 7, // 掃 - 0x6388, 5, // 授 - 0x638C, 7, // 掌 - 0x6392, 7, // 排 - 0x6398, 7, // 掘 - 0x639B, 7, // 掛 - 0x63A1, 5, // 採 - 0x63A2, 6, // 探 - 0x63A5, 5, // 接 - 0x63A7, 7, // 控 - 0x63A8, 6, // 掚 - 0x63AA, 7, // 措 - 0x63B2, 7, // 掲 - 0x63CF, 7, // 描 - 0x63D0, 5, // 提 - 0x63DA, 7, // 揚 - 0x63DB, 7, // 換 - 0x63E1, 7, // 握 - 0x63EE, 6, // 揮 - 0x63F4, 7, // 揎 - 0x63FA, 7, // 揺 - 0x640D, 5, // 損 - 0x642C, 7, // 搬 - 0x642D, 7, // 搭 - 0x643A, 7, // 携 - 0x643E, 7, // 搟 - 0x6442, 7, // 摂 - 0x6458, 7, // 摘 - 0x6469, 7, // 摩 - 0x6483, 7, // 撃 - 0x64A4, 7, // æ’€ - 0x64AE, 7, // 撮 - 0x64B2, 7, // 撲 - 0x64C1, 7, // 擁 - 0x64CD, 6, // 操 - 0x64E6, 7, // 擊 - 0x64EC, 7, // 擬 - 0x652F, 5, // 支 - 0x6539, 4, // 改 - 0x653B, 7, // 攻 - 0x653E, 3, // 攟 - 0x653F, 5, // 政 - 0x6545, 5, // 故 - 0x654F, 7, // 敏 - 0x6551, 4, // 救 - 0x6557, 4, // 敗 - 0x6559, 2, // 教 - 0x6562, 7, // 敢 - 0x6563, 4, // 散 - 0x656C, 6, // 敬 - 0x6570, 2, // 数 - 0x6574, 3, // 敎 - 0x6575, 5, // 敵 - 0x6577, 7, // 敷 - 0x6587, 1, // 文 - 0x6589, 7, // 斉 - 0x658E, 7, // 斎 - 0x6597, 7, // 斗 - 0x6599, 4, // 料 - 0x659C, 7, // 斜 - 0x65A4, 7, // æ–€ - 0x65A5, 7, // 斥 - 0x65AD, 5, // 断 - 0x65B0, 2, // 新 - 0x65B9, 2, // 方 - 0x65BD, 7, // æ–œ - 0x65C5, 3, // 旅 - 0x65CB, 7, // 旋 - 0x65CF, 3, // 族 - 0x65D7, 4, // 旗 - 0x65E2, 7, // 既 - 0x65E5, 1, // 日 - 0x65E7, 5, // 旧 - 0x65E8, 7, // æ—š - 0x65E9, 1, // 早 - 0x65EC, 7, // 旬 - 0x6606, 7, // 昆 - 0x6607, 7, // 昇 - 0x660E, 2, // 明 - 0x6613, 5, // 易 - 0x6614, 3, // 昔 - 0x661F, 2, // 星 - 0x6620, 6, // 映 - 0x6625, 2, // 春 - 0x6628, 4, // 昚 - 0x662D, 3, // 昭 - 0x662F, 7, // 是 - 0x663C, 2, // 昌 - 0x6642, 2, // 時 - 0x6669, 6, // 晩 - 0x666E, 7, // 普 - 0x666F, 4, // 景 - 0x6674, 2, // 晎 - 0x6676, 7, // 晶 - 0x6681, 7, // 暁 - 0x6687, 7, // 暇 - 0x6691, 3, // 暑 - 0x6696, 6, // 暖 - 0x6697, 3, // 暗 - 0x66A6, 7, // 暊 - 0x66AB, 7, // 暫 - 0x66AE, 6, // 暮 - 0x66B4, 5, // 暎 - 0x66C7, 7, // 曇 - 0x66DC, 2, // 曜 - 0x66F2, 3, // 曲 - 0x66F4, 7, // 曎 - 0x66F8, 2, // 曞 - 0x66F9, 7, // 曹 - 0x66FF, 7, // 替 - 0x6700, 4, // 最 - 0x6708, 1, // 月 - 0x6709, 3, // 有 - 0x670D, 3, // 服 - 0x6715, 7, // 朕 - 0x6717, 6, // 朗 - 0x671B, 4, // 望 - 0x671D, 2, // 朝 - 0x671F, 3, // 期 - 0x6728, 1, // 朚 - 0x672A, 4, // 未 - 0x672B, 4, // 末 - 0x672C, 1, // 本 - 0x672D, 4, // 札 - 0x6731, 7, // 朱 - 0x6734, 7, // 朎 - 0x673A, 6, // 机 - 0x673D, 7, // 朜 - 0x6749, 7, // 杉 - 0x6750, 4, // 材 - 0x6751, 1, // 村 - 0x675F, 4, // 束 - 0x6761, 5, // 条 - 0x6765, 2, // 来 - 0x676F, 7, // 杯 - 0x6771, 2, // 東 - 0x677E, 4, // 束 - 0x677F, 3, // 板 - 0x6790, 7, // 析 - 0x6797, 1, // 林 - 0x679A, 6, // 枚 - 0x679C, 4, // 果 - 0x679D, 5, // 枝 - 0x67A0, 7, // 枠 - 0x67A2, 7, // 枢 - 0x67AF, 7, // 枯 - 0x67B6, 7, // 架 - 0x67C4, 7, // 柄 - 0x67D0, 7, // 某 - 0x67D3, 6, // 染 - 0x67D4, 7, // 柔 - 0x67F1, 3, // 柱 - 0x67F3, 7, // 柳 - 0x67FB, 5, // 査 - 0x6804, 4, // 栄 - 0x6813, 7, // 栓 - 0x6821, 1, // æ ¡ - 0x682A, 6, // æ ª - 0x6838, 7, // æ ž - 0x6839, 3, // æ ¹ - 0x683C, 5, // æ Œ - 0x683D, 7, // æ œ - 0x6843, 7, // 桃 - 0x6848, 4, // 案 - 0x6851, 7, // 桑 - 0x685C, 5, // 桜 - 0x685F, 7, // 桟 - 0x6885, 4, // 梅 - 0x68B0, 4, // 械 - 0x68C4, 7, // 棄 - 0x68CB, 7, // 棋 - 0x68D2, 6, // 棒 - 0x68DA, 7, // 棚 - 0x68DF, 7, // 棟 - 0x68EE, 1, // 森 - 0x68FA, 7, // 棺 - 0x690D, 3, // 怍 - 0x691C, 5, // 怜 - 0x696D, 3, // 業 - 0x6975, 4, // 極 - 0x697C, 7, // 楌 - 0x697D, 2, // 楜 - 0x6982, 7, // 抂 - 0x69CB, 5, // 構 - 0x69D8, 3, // 様 - 0x69FD, 7, // æ§œ - 0x6A19, 4, // æš™ - 0x6A21, 6, // æš¡ - 0x6A29, 6, // æš© - 0x6A2A, 3, // 暪 - 0x6A39, 6, // æš¹ - 0x6A4B, 3, // 橋 - 0x6A5F, 4, // 機 - 0x6B04, 7, // 欄 - 0x6B20, 4, // 欠 - 0x6B21, 3, // 次 - 0x6B27, 7, // 欧 - 0x6B32, 6, // 欲 - 0x6B3A, 7, // 欺 - 0x6B3E, 7, // 欟 - 0x6B4C, 2, // 歌 - 0x6B53, 7, // 歓 - 0x6B62, 2, // æ­¢ - 0x6B63, 1, // æ­£ - 0x6B66, 5, // æ­Š - 0x6B69, 2, // æ­© - 0x6B6F, 3, // æ­¯ - 0x6B73, 7, // æ­³ - 0x6B74, 4, // æ­Ž - 0x6B7B, 3, // æ­» - 0x6B89, 7, // 殉 - 0x6B8A, 7, // 殊 - 0x6B8B, 4, // 残 - 0x6B96, 7, // 殖 - 0x6BB4, 7, // 殎 - 0x6BB5, 6, // 段 - 0x6BBA, 4, // 殺 - 0x6BBB, 7, // æ®» - 0x6BBF, 7, // 殿 - 0x6BCD, 2, // 母 - 0x6BCE, 2, // 毎 - 0x6BD2, 4, // 毒 - 0x6BD4, 5, // 比 - 0x6BDB, 2, // 毛 - 0x6C0F, 4, // 氏 - 0x6C11, 4, // 民 - 0x6C17, 1, // 気 - 0x6C34, 1, // æ°Ž - 0x6C37, 3, // æ°· - 0x6C38, 5, // æ°ž - 0x6C41, 7, // 汁 - 0x6C42, 4, // 求 - 0x6C57, 7, // 汗 - 0x6C5A, 7, // 汚 - 0x6C5F, 7, // 江 - 0x6C60, 2, // æ±  - 0x6C7A, 3, // 決 - 0x6C7D, 2, // 汜 - 0x6C88, 7, // 沈 - 0x6C96, 7, // 沖 - 0x6CA1, 7, // 没 - 0x6CA2, 7, // æ²¢ - 0x6CB3, 5, // æ²³ - 0x6CB8, 7, // 沞 - 0x6CB9, 3, // æ²¹ - 0x6CBB, 4, // æ²» - 0x6CBC, 7, // 沌 - 0x6CBF, 6, // 沿 - 0x6CC1, 7, // 況 - 0x6CC9, 6, // 泉 - 0x6CCA, 7, // 泊 - 0x6CCC, 7, // 泌 - 0x6CD5, 4, // 法 - 0x6CE1, 7, // 泡 - 0x6CE2, 3, // æ³¢ - 0x6CE3, 4, // æ³£ - 0x6CE5, 7, // æ³¥ - 0x6CE8, 3, // 泚 - 0x6CF0, 7, // æ³° - 0x6CF3, 3, // æ³³ - 0x6D0B, 3, // 掋 - 0x6D17, 6, // 掗 - 0x6D1E, 7, // 掞 - 0x6D25, 7, // 接 - 0x6D2A, 7, // 措 - 0x6D3B, 2, // 掻 - 0x6D3E, 6, // 掟 - 0x6D41, 3, // 流 - 0x6D44, 7, // 浄 - 0x6D45, 4, // 浅 - 0x6D5C, 7, // 浜 - 0x6D66, 7, // 浊 - 0x6D6A, 7, // 浪 - 0x6D6E, 7, // æµ® - 0x6D74, 4, // 济 - 0x6D77, 2, // æµ· - 0x6D78, 7, // 浞 - 0x6D88, 3, // 消 - 0x6D99, 7, // 涙 - 0x6DAF, 7, // 涯 - 0x6DB2, 5, // æ¶² - 0x6DBC, 7, // æ¶Œ - 0x6DD1, 7, // 淑 - 0x6DE1, 7, // æ·¡ - 0x6DF1, 3, // æ·± - 0x6DF7, 5, // æ·· - 0x6DFB, 7, // æ·» - 0x6E05, 4, // æž… - 0x6E07, 7, // 枇 - 0x6E08, 6, // 枈 - 0x6E09, 7, // 枉 - 0x6E0B, 7, // æž‹ - 0x6E13, 7, // æž“ - 0x6E1B, 5, // æž› - 0x6E21, 7, // æž¡ - 0x6E26, 7, // 枊 - 0x6E29, 3, // æž© - 0x6E2C, 5, // 枬 - 0x6E2F, 3, // 枯 - 0x6E56, 3, // 湖 - 0x6E6F, 3, // 湯 - 0x6E7E, 7, // 湟 - 0x6E7F, 7, // 湿 - 0x6E80, 4, // 満 - 0x6E90, 6, // 源 - 0x6E96, 5, // 準 - 0x6E9D, 7, // 溝 - 0x6EB6, 7, // 溶 - 0x6EC5, 7, // 滅 - 0x6ECB, 7, // 滋 - 0x6ED1, 7, // 滑 - 0x6EDD, 7, // 滝 - 0x6EDE, 7, // 滞 - 0x6EF4, 7, // 滎 - 0x6F01, 4, // 持 - 0x6F02, 7, // 挂 - 0x6F06, 7, // 挆 - 0x6F0F, 7, // 挏 - 0x6F14, 5, // 挔 - 0x6F20, 7, // 挠 - 0x6F22, 3, // 挢 - 0x6F2B, 7, // 挫 - 0x6F2C, 7, // 挬 - 0x6F38, 7, // 挞 - 0x6F54, 5, // 朔 - 0x6F5C, 7, // 朜 - 0x6F5F, 7, // 期 - 0x6F64, 7, // 最 - 0x6F6E, 6, // 朮 - 0x6F84, 7, // 柄 - 0x6FC0, 6, // 激 - 0x6FC1, 7, // 濁 - 0x6FC3, 7, // 濃 - 0x6FEB, 7, // æ¿« - 0x6FEF, 7, // 濯 - 0x702C, 7, // 瀬 - 0x706B, 1, // 火 - 0x706F, 4, // 灯 - 0x7070, 6, // 灰 - 0x707D, 5, // 灜 - 0x7089, 7, // 炉 - 0x708A, 7, // 炊 - 0x708E, 7, // 炎 - 0x70AD, 3, // 炭 - 0x70B9, 2, // 点 - 0x70BA, 7, // 為 - 0x70C8, 7, // 烈 - 0x7121, 4, // 無 - 0x7126, 7, // 焩 - 0x7136, 4, // 然 - 0x713C, 4, // 焌 - 0x7159, 7, // 煙 - 0x7167, 4, // 照 - 0x7169, 7, // 煩 - 0x716E, 7, // 煮 - 0x719F, 6, // 熟 - 0x71B1, 4, // 熱 - 0x71C3, 5, // 燃 - 0x71C8, 7, // 燈 - 0x71E5, 7, // 燥 - 0x7206, 7, // 爆 - 0x7235, 7, // 爵 - 0x7236, 2, // 父 - 0x7247, 6, // 片 - 0x7248, 5, // 版 - 0x725B, 2, // 牛 - 0x7267, 4, // 牧 - 0x7269, 3, // 物 - 0x7272, 7, // 牲 - 0x7279, 4, // 特 - 0x72A0, 7, // 犠 - 0x72AC, 1, // 犬 - 0x72AF, 5, // 犯 - 0x72B6, 5, // 状 - 0x72C2, 7, // 狂 - 0x72E9, 7, // 狩 - 0x72EC, 5, // 独 - 0x72ED, 7, // 狭 - 0x731B, 7, // 猛 - 0x731F, 7, // 猟 - 0x732B, 7, // 猫 - 0x732E, 7, // 献 - 0x7336, 7, // 猶 - 0x733F, 7, // 猿 - 0x7344, 7, // 獄 - 0x7363, 7, // 獣 - 0x7372, 7, // 獲 - 0x7384, 7, // 玄 - 0x7387, 5, // 率 - 0x7389, 1, // 玉 - 0x738B, 1, // 王 - 0x73CD, 7, // 珍 - 0x73E0, 7, // 珠 - 0x73ED, 6, // 班 - 0x73FE, 5, // 珟 - 0x7403, 3, // 球 - 0x7406, 2, // 理 - 0x7434, 7, // 琎 - 0x74B0, 7, // 環 - 0x74BD, 7, // ç’œ - 0x74F6, 7, // 瓶 - 0x7518, 7, // 甘 - 0x751A, 7, // 甚 - 0x751F, 1, // 生 - 0x7523, 4, // 産 - 0x7528, 2, // 甹 - 0x7530, 1, // 田 - 0x7531, 3, // 由 - 0x7532, 7, // 甲 - 0x7533, 3, // 申 - 0x7537, 1, // 男 - 0x753A, 1, // 町 - 0x753B, 2, // 画 - 0x754C, 3, // 界 - 0x7551, 3, // 畑 - 0x7554, 7, // 畔 - 0x7559, 5, // 留 - 0x755C, 7, // 畜 - 0x755D, 7, // 畝 - 0x7565, 5, // 略 - 0x756A, 2, // 番 - 0x7570, 6, // 異 - 0x7573, 7, // 畳 - 0x758E, 7, // 疎 - 0x7591, 6, // 疑 - 0x75AB, 7, // 疫 - 0x75B2, 7, // 疲 - 0x75BE, 7, // ç–Ÿ - 0x75C5, 3, // 病 - 0x75C7, 7, // 症 - 0x75D8, 7, // 痘 - 0x75DB, 6, // 痛 - 0x75E2, 7, // 痢 - 0x75F4, 7, // 痮 - 0x7642, 7, // 療 - 0x7652, 7, // 癒 - 0x7656, 7, // 癖 - 0x767A, 3, // 発 - 0x767B, 3, // 登 - 0x767D, 1, // 癜 - 0x767E, 1, // 癟 - 0x7684, 4, // 的 - 0x7686, 7, // 皆 - 0x7687, 6, // 皇 - 0x76AE, 3, // 皮 - 0x76BF, 3, // 皿 - 0x76C6, 7, // 盆 - 0x76CA, 5, // 益 - 0x76D7, 7, // 盗 - 0x76DB, 6, // 盛 - 0x76DF, 6, // 盟 - 0x76E3, 7, // 監 - 0x76E4, 7, // 盀 - 0x76EE, 1, // 目 - 0x76F2, 7, // 盲 - 0x76F4, 2, // 目 - 0x76F8, 3, // 盾 - 0x76FE, 7, // 盟 - 0x7701, 4, // 省 - 0x770B, 6, // 看 - 0x770C, 3, // 県 - 0x771F, 3, // 真 - 0x7720, 7, // 眠 - 0x773A, 7, // 眺 - 0x773C, 5, // 県 - 0x7740, 3, // 着 - 0x7761, 7, // 睡 - 0x7763, 7, // 督 - 0x77AC, 7, // 瞬 - 0x77DB, 7, // 矛 - 0x77E2, 2, // 矢 - 0x77E5, 2, // 知 - 0x77ED, 3, // 短 - 0x77EF, 7, // 矯 - 0x77F3, 1, // 石 - 0x7802, 6, // 砂 - 0x7814, 3, // 研 - 0x7815, 7, // 砕 - 0x7832, 7, // ç ² - 0x7834, 5, // ç Ž - 0x785D, 7, // 硝 - 0x786B, 7, // ç¡« - 0x786C, 7, // 硬 - 0x7881, 7, // 碁 - 0x7891, 7, // 碑 - 0x78BA, 5, // 確 - 0x78C1, 6, // 磁 - 0x78E8, 7, // 磚 - 0x7901, 7, // 瀁 - 0x790E, 7, // 瀎 - 0x793A, 5, // 瀺 - 0x793C, 3, // 瀌 - 0x793E, 2, // 瀟 - 0x7948, 7, // 祈 - 0x7949, 7, // 祉 - 0x7956, 5, // 祖 - 0x795D, 4, // 祝 - 0x795E, 3, // 神 - 0x7965, 7, // 祥 - 0x7968, 4, // 祚 - 0x796D, 3, // 祭 - 0x7981, 5, // 犁 - 0x7985, 7, // 穅 - 0x798D, 7, // 犍 - 0x798F, 3, // 犏 - 0x79C0, 7, // 秀 - 0x79C1, 6, // 私 - 0x79CB, 2, // 秋 - 0x79D1, 2, // 科 - 0x79D2, 3, // 秒 - 0x79D8, 6, // 秘 - 0x79DF, 7, // 租 - 0x79E9, 7, // ç§© - 0x79F0, 7, // ç§° - 0x79FB, 5, // ç§» - 0x7A0B, 5, // 繋 - 0x7A0E, 5, // 皎 - 0x7A1A, 7, // 繚 - 0x7A2E, 4, // çš® - 0x7A32, 7, // çš² - 0x7A3C, 7, // 皌 - 0x7A3F, 7, // çš¿ - 0x7A40, 6, // 穀 - 0x7A42, 7, // 穂 - 0x7A4D, 4, // 積 - 0x7A4F, 7, // 穏 - 0x7A6B, 7, // ç©« - 0x7A74, 6, // 穎 - 0x7A76, 3, // ç©¶ - 0x7A7A, 1, // 空 - 0x7A81, 7, // 突 - 0x7A83, 7, // 窃 - 0x7A92, 7, // 窒 - 0x7A93, 6, // 窓 - 0x7AAE, 7, // 窮 - 0x7AAF, 7, // 窯 - 0x7ACB, 1, // 立 - 0x7ADC, 7, // 竜 - 0x7AE0, 3, // ç«  - 0x7AE5, 3, // ç«¥ - 0x7AEF, 7, // 端 - 0x7AF6, 4, // ç«¶ - 0x7AF9, 1, // 竹 - 0x7B11, 4, // 笑 - 0x7B1B, 3, // 笛 - 0x7B26, 7, // 笊 - 0x7B2C, 3, // 第 - 0x7B46, 3, // 筆 - 0x7B49, 3, // 等 - 0x7B4B, 6, // 筋 - 0x7B52, 7, // 筒 - 0x7B54, 2, // 答 - 0x7B56, 6, // 策 - 0x7B87, 7, // 箇 - 0x7B97, 2, // 算 - 0x7BA1, 4, // 管 - 0x7BB1, 3, // ç®± - 0x7BC0, 4, // 節 - 0x7BC4, 7, // 範 - 0x7BC9, 5, // 築 - 0x7BE4, 7, // 節 - 0x7C21, 6, // ç°¡ - 0x7C3F, 7, // ç°¿ - 0x7C4D, 7, // 籍 - 0x7C73, 2, // ç±³ - 0x7C89, 4, // 粉 - 0x7C8B, 7, // 粋 - 0x7C92, 7, // 粒 - 0x7C97, 7, // 粗 - 0x7C98, 7, // 粘 - 0x7C9B, 7, // 粛 - 0x7CA7, 7, // ç²§ - 0x7CBE, 5, // 粟 - 0x7CD6, 6, // 糖 - 0x7CE7, 7, // ç³§ - 0x7CF8, 1, // 糞 - 0x7CFB, 6, // ç³» - 0x7CFE, 7, // 糟 - 0x7D00, 4, // 简 - 0x7D04, 4, // 箄 - 0x7D05, 6, // 箅 - 0x7D0B, 7, // 箋 - 0x7D0D, 6, // 玍 - 0x7D14, 6, // 箔 - 0x7D19, 2, // 箙 - 0x7D1A, 3, // 箚 - 0x7D1B, 7, // 箛 - 0x7D20, 5, // 玠 - 0x7D21, 7, // 玡 - 0x7D22, 7, // 玢 - 0x7D2B, 7, // 玫 - 0x7D2F, 7, // 环 - 0x7D30, 2, // 现 - 0x7D33, 7, // 玳 - 0x7D39, 7, // 玹 - 0x7D3A, 7, // 玺 - 0x7D42, 3, // 終 - 0x7D44, 2, // 組 - 0x7D4C, 5, // 経 - 0x7D50, 4, // 結 - 0x7D5E, 7, // 絞 - 0x7D61, 7, // 絡 - 0x7D66, 4, // 絊 - 0x7D71, 5, // çµ± - 0x7D75, 2, // çµµ - 0x7D76, 5, // çµ¶ - 0x7D79, 6, // çµ¹ - 0x7D99, 7, // 継 - 0x7D9A, 4, // 続 - 0x7DAD, 7, // ç¶­ - 0x7DB1, 7, // ç¶± - 0x7DB2, 7, // ç¶² - 0x7DBF, 5, // ç¶¿ - 0x7DCA, 7, // 緊 - 0x7DCF, 5, // 総 - 0x7DD1, 3, // 緑 - 0x7DD2, 7, // 緒 - 0x7DDA, 2, // 線 - 0x7DE0, 7, // ç·  - 0x7DE8, 5, // ç·š - 0x7DE9, 7, // ç·© - 0x7DEF, 7, // ç·¯ - 0x7DF4, 3, // ç·Ž - 0x7E01, 7, // 瞁 - 0x7E04, 7, // 羄 - 0x7E1B, 7, // 羛 - 0x7E26, 6, // 瞊 - 0x7E2B, 7, // çž« - 0x7E2E, 6, // çž® - 0x7E3E, 5, // 瞟 - 0x7E41, 7, // 繁 - 0x7E4A, 7, // 繊 - 0x7E54, 5, // 織 - 0x7E55, 7, // 繕 - 0x7E6D, 7, // ç¹­ - 0x7E70, 7, // ç¹° - 0x7F36, 7, // 猶 - 0x7F6A, 5, // 眪 - 0x7F6E, 4, // 眮 - 0x7F70, 7, // 眰 - 0x7F72, 6, // 眲 - 0x7F77, 7, // 眷 - 0x7F85, 7, // 矅 - 0x7F8A, 3, // 矊 - 0x7F8E, 3, // 矎 - 0x7FA4, 5, // 矀 - 0x7FA9, 5, // 矩 - 0x7FBD, 2, // 矜 - 0x7FC1, 7, // 翁 - 0x7FCC, 6, // 翌 - 0x7FD2, 3, // 習 - 0x7FFB, 7, // ç¿» - 0x7FFC, 7, // 翌 - 0x8001, 4, // 老 - 0x8003, 2, // 考 - 0x8005, 3, // 者 - 0x8010, 7, // 耐 - 0x8015, 5, // 耕 - 0x8017, 7, // 耗 - 0x8033, 1, // 耳 - 0x8056, 6, // 聖 - 0x805E, 2, // 聞 - 0x8074, 7, // 聎 - 0x8077, 5, // 職 - 0x8089, 2, // 肉 - 0x808C, 7, // 肌 - 0x8096, 7, // 肖 - 0x809D, 7, // 肝 - 0x80A2, 7, // 肢 - 0x80A5, 5, // 肥 - 0x80A9, 7, // 肩 - 0x80AA, 7, // 肪 - 0x80AF, 7, // 肯 - 0x80B2, 3, // 育 - 0x80BA, 6, // 肺 - 0x80C3, 4, // 胃 - 0x80C6, 7, // 胆 - 0x80CC, 6, // 背 - 0x80CE, 7, // 胎 - 0x80DE, 7, // 胞 - 0x80F4, 7, // 胎 - 0x80F8, 6, // 胞 - 0x80FD, 5, // 胜 - 0x8102, 7, // 脂 - 0x8105, 7, // 脅 - 0x8108, 4, // 脈 - 0x811A, 7, // 脚 - 0x8131, 7, // 脱 - 0x8133, 6, // 脳 - 0x8139, 7, // 脹 - 0x8150, 7, // 腐 - 0x8155, 7, // 腕 - 0x8170, 7, // 腰 - 0x8178, 4, // è…ž - 0x8179, 6, // 腹 - 0x819A, 7, // 膚 - 0x819C, 7, // 膜 - 0x81A8, 7, // 膚 - 0x81D3, 6, // 臓 - 0x81E3, 4, // 臣 - 0x81E8, 6, // 臚 - 0x81EA, 2, // 自 - 0x81ED, 7, // 臭 - 0x81F3, 6, // 至 - 0x81F4, 7, // 臎 - 0x8208, 5, // 興 - 0x820C, 5, // 舌 - 0x820E, 5, // 舎 - 0x8217, 7, // 舗 - 0x821E, 7, // 舞 - 0x821F, 7, // 舟 - 0x822A, 4, // 航 - 0x822C, 7, // 般 - 0x8236, 7, // 舶 - 0x8239, 2, // 船 - 0x8247, 7, // 艇 - 0x8266, 7, // 艊 - 0x826F, 4, // 良 - 0x8272, 2, // 色 - 0x828B, 7, // 芋 - 0x829D, 7, // 芝 - 0x82B1, 1, // 花 - 0x82B3, 7, // 芳 - 0x82B8, 4, // 芞 - 0x82BD, 4, // 芜 - 0x82D7, 7, // 苗 - 0x82E5, 6, // 若 - 0x82E6, 3, // 苊 - 0x82F1, 4, // 英 - 0x8302, 7, // 茂 - 0x830E, 7, // 茎 - 0x8336, 2, // 茶 - 0x8349, 1, // 草 - 0x8352, 7, // 荒 - 0x8358, 7, // 荘 - 0x8377, 3, // 荷 - 0x83CA, 7, // 菊 - 0x83CC, 7, // 菌 - 0x83D3, 7, // 菓 - 0x83DC, 4, // 菜 - 0x83EF, 7, // 華 - 0x843D, 3, // 萜 - 0x8449, 3, // 葉 - 0x8457, 6, // 著 - 0x846C, 7, // 葬 - 0x84B8, 6, // è’ž - 0x84C4, 7, // 蓄 - 0x8535, 6, // 蔵 - 0x8584, 7, // 薄 - 0x85A6, 7, // è–Š - 0x85AA, 7, // 薪 - 0x85AB, 7, // 薫 - 0x85AC, 3, // 薬 - 0x85E9, 7, // 藩 - 0x85FB, 7, // 藻 - 0x8650, 7, // 虐 - 0x865A, 7, // 虚 - 0x865C, 7, // 虜 - 0x865E, 7, // 虞 - 0x866B, 1, // 虫 - 0x868A, 7, // 蚊 - 0x8695, 6, // 蚕 - 0x86C7, 7, // 蛇 - 0x86CD, 7, // 蛍 - 0x86EE, 7, // 蛮 - 0x878D, 7, // 融 - 0x8840, 3, // 血 - 0x8846, 6, // 衆 - 0x884C, 2, // 行 - 0x8853, 5, // 術 - 0x8857, 4, // 街 - 0x885B, 5, // 衛 - 0x885D, 7, // 衝 - 0x8861, 7, // è¡¡ - 0x8863, 4, // è¡£ - 0x8868, 3, // 衚 - 0x8870, 7, // è¡° - 0x8877, 7, // è¡· - 0x888B, 7, // 袋 - 0x88AB, 7, // 被 - 0x88C1, 6, // 裁 - 0x88C2, 7, // 裂 - 0x88C5, 6, // 装 - 0x88CF, 6, // 裏 - 0x88D5, 7, // 裕 - 0x88DC, 6, // 補 - 0x88F8, 7, // 裞 - 0x88FD, 5, // 補 - 0x8907, 5, // 耇 - 0x8910, 7, // 耐 - 0x8912, 7, // 耒 - 0x895F, 7, // 襟 - 0x8972, 7, // 襲 - 0x897F, 2, // 西 - 0x8981, 4, // 芁 - 0x8986, 7, // 芆 - 0x8987, 7, // 芇 - 0x898B, 1, // 芋 - 0x898F, 5, // 芏 - 0x8996, 6, // 芖 - 0x899A, 4, // 芚 - 0x89A7, 6, // 芧 - 0x89AA, 2, // 芪 - 0x89B3, 4, // 芳 - 0x89D2, 2, // 角 - 0x89E3, 5, // è§£ - 0x89E6, 7, // è§Š - 0x8A00, 2, // 蚀 - 0x8A02, 7, // èš‚ - 0x8A08, 2, // 蚈 - 0x8A0E, 6, // 蚎 - 0x8A13, 4, // èš“ - 0x8A17, 7, // èš— - 0x8A18, 2, // 蚘 - 0x8A1F, 7, // 蚟 - 0x8A2A, 6, // 蚪 - 0x8A2D, 5, // èš­ - 0x8A31, 5, // èš± - 0x8A33, 6, // èš³ - 0x8A34, 7, // 蚎 - 0x8A3A, 7, // 蚺 - 0x8A3C, 5, // 蚌 - 0x8A50, 7, // 詐 - 0x8A54, 7, // 詔 - 0x8A55, 5, // 評 - 0x8A5E, 6, // 詞 - 0x8A60, 7, // è©  - 0x8A66, 4, // 詊 - 0x8A69, 3, // è©© - 0x8A70, 7, // è©° - 0x8A71, 2, // 話 - 0x8A72, 7, // 該 - 0x8A73, 7, // 詳 - 0x8A87, 7, // 誇 - 0x8A89, 7, // 誉 - 0x8A8C, 6, // 誌 - 0x8A8D, 6, // 認 - 0x8A93, 7, // 誓 - 0x8A95, 6, // 誕 - 0x8A98, 7, // 誘 - 0x8A9E, 2, // 語 - 0x8AA0, 6, // 誠 - 0x8AA4, 6, // 誀 - 0x8AAC, 4, // 説 - 0x8AAD, 2, // 読 - 0x8AB2, 4, // 課 - 0x8ABF, 3, // 調 - 0x8AC7, 3, // 談 - 0x8ACB, 7, // 請 - 0x8AD6, 6, // 論 - 0x8AED, 7, // è«­ - 0x8AEE, 7, // è«® - 0x8AF8, 6, // 諞 - 0x8AFE, 7, // 諟 - 0x8B00, 7, // 謀 - 0x8B01, 7, // 謁 - 0x8B04, 7, // 謄 - 0x8B19, 7, // 謙 - 0x8B1B, 5, // 講 - 0x8B1D, 5, // 謝 - 0x8B21, 7, // 謡 - 0x8B39, 7, // 謹 - 0x8B58, 5, // 識 - 0x8B5C, 7, // 譜 - 0x8B66, 6, // è­Š - 0x8B70, 4, // è­° - 0x8B72, 7, // è­² - 0x8B77, 5, // è­· - 0x8C37, 2, // è°· - 0x8C46, 3, // 豆 - 0x8C4A, 5, // 豊 - 0x8C5A, 7, // 豚 - 0x8C61, 4, // 象 - 0x8C6A, 7, // 豪 - 0x8C9D, 1, // 貝 - 0x8C9E, 7, // 貞 - 0x8CA0, 3, // è²  - 0x8CA1, 5, // 財 - 0x8CA2, 7, // è²¢ - 0x8CA7, 5, // è²§ - 0x8CA8, 4, // 貚 - 0x8CA9, 7, // 販 - 0x8CAB, 7, // 貫 - 0x8CAC, 5, // 責 - 0x8CAF, 4, // 貯 - 0x8CB4, 6, // 貎 - 0x8CB7, 2, // è²· - 0x8CB8, 5, // 貞 - 0x8CBB, 4, // è²» - 0x8CBF, 5, // 貿 - 0x8CC0, 5, // 賀 - 0x8CC3, 6, // 賃 - 0x8CC4, 7, // 賄 - 0x8CC7, 5, // 資 - 0x8CCA, 7, // 賊 - 0x8CD3, 7, // 賓 - 0x8CDB, 5, // 賛 - 0x8CDC, 7, // 賜 - 0x8CDE, 4, // 賞 - 0x8CE0, 7, // è³  - 0x8CE2, 7, // è³¢ - 0x8CE6, 7, // 賊 - 0x8CEA, 5, // 質 - 0x8CFC, 7, // 賌 - 0x8D08, 7, // 莈 - 0x8D64, 1, // èµ€ - 0x8D66, 7, // 赊 - 0x8D70, 2, // èµ° - 0x8D74, 7, // 赎 - 0x8D77, 3, // èµ· - 0x8D85, 7, // 超 - 0x8D8A, 7, // 越 - 0x8DA3, 7, // è¶£ - 0x8DB3, 1, // è¶³ - 0x8DDD, 7, // 距 - 0x8DE1, 7, // è·¡ - 0x8DEF, 3, // è·¯ - 0x8DF3, 7, // è·³ - 0x8DF5, 7, // è·µ - 0x8E0A, 7, // 螊 - 0x8E0F, 7, // 螏 - 0x8E8D, 7, // 躍 - 0x8EAB, 3, // 身 - 0x8ECA, 1, // 車 - 0x8ECC, 7, // 軌 - 0x8ECD, 4, // 軍 - 0x8ED2, 7, // 軒 - 0x8EDF, 7, // 軟 - 0x8EE2, 3, // 転 - 0x8EF8, 7, // 軞 - 0x8EFD, 3, // 軜 - 0x8F03, 7, // 范 - 0x8F09, 7, // 茉 - 0x8F1D, 7, // 茝 - 0x8F29, 7, // 茩 - 0x8F2A, 4, // 茪 - 0x8F38, 5, // 茞 - 0x8F44, 7, // 蜄 - 0x8F9B, 7, // 蟛 - 0x8F9E, 4, // 蟞 - 0x8FB1, 7, // 蟱 - 0x8FB2, 3, // 蟲 - 0x8FBA, 4, // 蟺 - 0x8FBC, 7, // 蟌 - 0x8FC5, 7, // 迅 - 0x8FCE, 7, // 迎 - 0x8FD1, 2, // 近 - 0x8FD4, 3, // 返 - 0x8FEB, 7, // è¿« - 0x8FED, 7, // è¿­ - 0x8FF0, 5, // è¿° - 0x8FF7, 5, // è¿· - 0x8FFD, 3, // 远 - 0x9000, 5, // 退 - 0x9001, 3, // 送 - 0x9003, 7, // 逃 - 0x9006, 5, // 逆 - 0x900F, 7, // 透 - 0x9010, 7, // 逐 - 0x9013, 7, // 逓 - 0x9014, 7, // 途 - 0x901A, 2, // 通 - 0x901D, 7, // 逝 - 0x901F, 3, // 速 - 0x9020, 5, // 造 - 0x9023, 4, // 連 - 0x902E, 7, // 逮 - 0x9031, 2, // 週 - 0x9032, 3, // 進 - 0x9038, 7, // 逾 - 0x9042, 7, // 遂 - 0x9045, 7, // 遅 - 0x9047, 7, // 遇 - 0x904A, 3, // 遊 - 0x904B, 3, // 運 - 0x904D, 7, // 遍 - 0x904E, 5, // 過 - 0x9053, 2, // 道 - 0x9054, 4, // 達 - 0x9055, 7, // 違 - 0x9060, 2, // 遠 - 0x9063, 7, // 遣 - 0x9069, 5, // 適 - 0x906D, 7, // 遭 - 0x906E, 7, // 遮 - 0x9075, 7, // 遵 - 0x9077, 7, // 遷 - 0x9078, 4, // 遞 - 0x907A, 6, // 遺 - 0x907F, 7, // 避 - 0x9084, 7, // 還 - 0x90A6, 7, // 邩 - 0x90AA, 7, // 邪 - 0x90B8, 7, // 邾 - 0x90CA, 7, // 郊 - 0x90CE, 7, // 郎 - 0x90E1, 4, // 郡 - 0x90E8, 3, // 郚 - 0x90ED, 7, // 郭 - 0x90F5, 6, // 郵 - 0x90F7, 6, // 郷 - 0x90FD, 3, // 郜 - 0x914C, 7, // 酌 - 0x914D, 3, // 配 - 0x9152, 3, // 酒 - 0x9154, 7, // 酔 - 0x9162, 7, // 酢 - 0x916A, 7, // 酪 - 0x916C, 7, // 酬 - 0x9175, 7, // 酵 - 0x9177, 7, // 酷 - 0x9178, 5, // 酾 - 0x919C, 7, // 醜 - 0x91B8, 7, // 醾 - 0x91C8, 7, // 釈 - 0x91CC, 2, // 里 - 0x91CD, 3, // 重 - 0x91CE, 2, // 野 - 0x91CF, 4, // 量 - 0x91D1, 1, // 金 - 0x91DD, 6, // 針 - 0x91E3, 7, // 釣 - 0x920D, 7, // 鈍 - 0x9234, 7, // 鈎 - 0x9244, 3, // 鉄 - 0x925B, 7, // 鉛 - 0x9262, 7, // 鉢 - 0x9271, 5, // 鉱 - 0x9280, 3, // 銀 - 0x9283, 7, // 銃 - 0x9285, 5, // 銅 - 0x9291, 7, // 銑 - 0x9298, 7, // 銘 - 0x92AD, 5, // 銭 - 0x92ED, 7, // 鋭 - 0x92F3, 7, // 鋳 - 0x92FC, 6, // 鋌 - 0x9318, 7, // 錘 - 0x9320, 7, // 錠 - 0x932C, 7, // 錬 - 0x932F, 7, // 錯 - 0x9332, 4, // 録 - 0x935B, 7, // 鍛 - 0x9396, 7, // 鎖 - 0x93AE, 7, // 鎮 - 0x93E1, 4, // 鏡 - 0x9418, 7, // 鐘 - 0x9451, 7, // 鑑 - 0x9577, 2, // 長 - 0x9580, 2, // 門 - 0x9589, 6, // 閉 - 0x958B, 3, // 開 - 0x9591, 7, // 閑 - 0x9593, 2, // 間 - 0x95A2, 4, // 関 - 0x95A3, 6, // 閣 - 0x95A5, 7, // 閥 - 0x95B2, 7, // 閲 - 0x95D8, 7, // 闘 - 0x9632, 5, // 防 - 0x963B, 7, // 阻 - 0x9644, 7, // 附 - 0x964D, 6, // 降 - 0x9650, 5, // 限 - 0x965B, 6, // 陛 - 0x9662, 3, // 院 - 0x9663, 7, // 陣 - 0x9664, 6, // 陀 - 0x9665, 7, // 陥 - 0x966A, 7, // 陪 - 0x9670, 7, // 陰 - 0x9673, 7, // 陳 - 0x9675, 7, // 陵 - 0x9676, 7, // 陶 - 0x9678, 4, // 陾 - 0x967A, 5, // 険 - 0x967D, 3, // 陜 - 0x9685, 7, // 隅 - 0x9686, 7, // 隆 - 0x968A, 4, // 隊 - 0x968E, 3, // 階 - 0x968F, 7, // 随 - 0x9694, 7, // 隔 - 0x969B, 5, // 際 - 0x969C, 6, // 障 - 0x96A0, 7, // 隠 - 0x96A3, 7, // 隣 - 0x96B7, 7, // 隷 - 0x96BB, 7, // 隻 - 0x96C4, 7, // 雄 - 0x96C5, 7, // 雅 - 0x96C6, 3, // 集 - 0x96C7, 7, // 雇 - 0x96CC, 7, // 雌 - 0x96D1, 5, // 雑 - 0x96E2, 7, // 離 - 0x96E3, 6, // 難 - 0x96E8, 1, // 雹 - 0x96EA, 2, // 雪 - 0x96F0, 7, // 雰 - 0x96F2, 2, // 雲 - 0x96F6, 7, // 零 - 0x96F7, 7, // 雷 - 0x96FB, 2, // 電 - 0x9700, 7, // 需 - 0x9707, 7, // 震 - 0x970A, 7, // 霊 - 0x971C, 7, // 霜 - 0x9727, 7, // 霧 - 0x9732, 7, // 露 - 0x9752, 1, // 青 - 0x9759, 4, // 静 - 0x975E, 5, // 非 - 0x9762, 3, // 面 - 0x9769, 6, // 革 - 0x9774, 7, // 靎 - 0x97F3, 1, // 音 - 0x97FB, 7, // 韻 - 0x97FF, 7, // 響 - 0x9802, 6, // 頂 - 0x9805, 7, // 項 - 0x9806, 4, // 順 - 0x9810, 5, // 預 - 0x9811, 7, // 頑 - 0x9812, 7, // 頒 - 0x9818, 5, // 領 - 0x982D, 2, // é ­ - 0x983B, 7, // é » - 0x983C, 7, // é Œ - 0x984C, 3, // 題 - 0x984D, 5, // 額 - 0x9854, 2, // 顔 - 0x9855, 7, // 顕 - 0x9858, 4, // 願 - 0x985E, 4, // 類 - 0x9867, 7, // é¡§ - 0x98A8, 2, // 颚 - 0x98DB, 4, // 飛 - 0x98DF, 2, // 食 - 0x98E2, 7, // 飢 - 0x98EF, 4, // 飯 - 0x98F2, 3, // 飲 - 0x98FC, 5, // 飌 - 0x98FD, 7, // 飜 - 0x98FE, 7, // 食 - 0x990A, 4, // 逊 - 0x9913, 7, // 逓 - 0x9928, 3, // 通 - 0x9996, 2, // 驖 - 0x9999, 7, // 驙 - 0x99AC, 2, // 銬 - 0x99C4, 7, // 駄 - 0x99C5, 3, // 駅 - 0x99C6, 7, // 駆 - 0x99D0, 7, // 駐 - 0x9A0E, 7, // 階 - 0x9A12, 7, // 鹒 - 0x9A13, 4, // 鹓 - 0x9A30, 7, // éš° - 0x9A5A, 7, // 驚 - 0x9AA8, 6, // 骚 - 0x9AC4, 7, // 髄 - 0x9AD8, 2, // 高 - 0x9AEA, 7, // 髪 - 0x9B3C, 7, // 鬌 - 0x9B42, 7, // 魂 - 0x9B45, 7, // 魅 - 0x9B54, 7, // 魔 - 0x9B5A, 2, // 魚 - 0x9BAE, 7, // é®® - 0x9BE8, 7, // 鯚 - 0x9CE5, 2, // é³¥ - 0x9CF4, 2, // 鳎 - 0x9D8F, 7, // 鶏 - 0x9E97, 7, // 麗 - 0x9EA6, 2, // 麊 - 0x9EBB, 7, // 麻 - 0x9EC4, 2, // 黄 - 0x9ED2, 2, // 黒 - 0x9ED9, 7, // 黙 - 0x9F13, 7, // 錓 - 0x9F3B, 3, // 錻 - 0x9F62, 7, // 霢 -}; + 0x7A9F, KANJI_LEARNING_ORDER_ADDTIONAL, // 窟 + 0x4E00, KANJI_LEARNING_ORDER_1, // 侀 + 0x4E01, KANJI_LEARNING_ORDER_3, // 䞁 + 0x4E03, KANJI_LEARNING_ORDER_1, // 䞃 + 0x4E07, KANJI_LEARNING_ORDER_2, // 侇 + 0x4E08, KANJI_LEARNING_ORDER_7, // 䞈 + 0x4E09, KANJI_LEARNING_ORDER_1, // 侉 + 0x4E0A, KANJI_LEARNING_ORDER_1, // 侊 + 0x4E0B, KANJI_LEARNING_ORDER_1, // 例 + 0x4E0D, KANJI_LEARNING_ORDER_4, // 䞍 + 0x4E0E, KANJI_LEARNING_ORDER_7, // 侎 + 0x4E14, KANJI_LEARNING_ORDER_7, // 侔 + 0x4E16, KANJI_LEARNING_ORDER_3, // 侖 + 0x4E18, KANJI_LEARNING_ORDER_7, // 䞘 + 0x4E19, KANJI_LEARNING_ORDER_7, // 侙 + 0x4E21, KANJI_LEARNING_ORDER_3, // äž¡ + 0x4E26, KANJI_LEARNING_ORDER_6, // 䞊 + 0x4E2D, KANJI_LEARNING_ORDER_1, // äž­ + 0x4E38, KANJI_LEARNING_ORDER_2, // äžž + 0x4E39, KANJI_LEARNING_ORDER_7, // äž¹ + 0x4E3B, KANJI_LEARNING_ORDER_3, // äž» + 0x4E45, KANJI_LEARNING_ORDER_5, // 久 + 0x4E4F, KANJI_LEARNING_ORDER_7, // 乏 + 0x4E57, KANJI_LEARNING_ORDER_3, // 乗 + 0x4E59, KANJI_LEARNING_ORDER_7, // 乙 + 0x4E5D, KANJI_LEARNING_ORDER_1, // 九 + 0x4E71, KANJI_LEARNING_ORDER_6, // ä¹± + 0x4E73, KANJI_LEARNING_ORDER_6, // ä¹³ + 0x4E7E, KANJI_LEARNING_ORDER_7, // 也 + 0x4E86, KANJI_LEARNING_ORDER_7, // 了 + 0x4E88, KANJI_LEARNING_ORDER_3, // 予 + 0x4E89, KANJI_LEARNING_ORDER_4, // 争 + 0x4E8B, KANJI_LEARNING_ORDER_3, // 事 + 0x4E8C, KANJI_LEARNING_ORDER_1, // 二 + 0x4E92, KANJI_LEARNING_ORDER_7, // 互 + 0x4E94, KANJI_LEARNING_ORDER_1, // 五 + 0x4E95, KANJI_LEARNING_ORDER_7, // 井 + 0x4E9C, KANJI_LEARNING_ORDER_7, // 亜 + 0x4EA1, KANJI_LEARNING_ORDER_6, // 亡 + 0x4EA4, KANJI_LEARNING_ORDER_2, // 亀 + 0x4EAB, KANJI_LEARNING_ORDER_7, // 享 + 0x4EAC, KANJI_LEARNING_ORDER_2, // 京 + 0x4EAD, KANJI_LEARNING_ORDER_7, // 亭 + 0x4EBA, KANJI_LEARNING_ORDER_1, // 人 + 0x4EC1, KANJI_LEARNING_ORDER_6, // 仁 + 0x4ECA, KANJI_LEARNING_ORDER_2, // 今 + 0x4ECB, KANJI_LEARNING_ORDER_7, // 介 + 0x4ECF, KANJI_LEARNING_ORDER_5, // 仏 + 0x4ED5, KANJI_LEARNING_ORDER_3, // 仕 + 0x4ED6, KANJI_LEARNING_ORDER_3, // 他 + 0x4ED8, KANJI_LEARNING_ORDER_4, // 付 + 0x4ED9, KANJI_LEARNING_ORDER_7, // 仙 + 0x4EE3, KANJI_LEARNING_ORDER_3, // 代 + 0x4EE4, KANJI_LEARNING_ORDER_4, // 什 + 0x4EE5, KANJI_LEARNING_ORDER_4, // 以 + 0x4EEE, KANJI_LEARNING_ORDER_5, // ä»® + 0x4EF0, KANJI_LEARNING_ORDER_7, // ä»° + 0x4EF2, KANJI_LEARNING_ORDER_4, // 仲 + 0x4EF6, KANJI_LEARNING_ORDER_5, // ä»¶ + 0x4EFB, KANJI_LEARNING_ORDER_5, // ä»» + 0x4F01, KANJI_LEARNING_ORDER_7, // 䌁 + 0x4F0F, KANJI_LEARNING_ORDER_7, // 䌏 + 0x4F10, KANJI_LEARNING_ORDER_7, // 䌐 + 0x4F11, KANJI_LEARNING_ORDER_1, // 䌑 + 0x4F1A, KANJI_LEARNING_ORDER_2, // 䌚 + 0x4F1D, KANJI_LEARNING_ORDER_4, // 䌝 + 0x4F2F, KANJI_LEARNING_ORDER_7, // 䌯 + 0x4F34, KANJI_LEARNING_ORDER_7, // 䌎 + 0x4F38, KANJI_LEARNING_ORDER_7, // 䌞 + 0x4F3A, KANJI_LEARNING_ORDER_7, // 䌺 + 0x4F3C, KANJI_LEARNING_ORDER_5, // 䌌 + 0x4F46, KANJI_LEARNING_ORDER_7, // 䜆 + 0x4F4D, KANJI_LEARNING_ORDER_4, // 䜍 + 0x4F4E, KANJI_LEARNING_ORDER_4, // 䜎 + 0x4F4F, KANJI_LEARNING_ORDER_3, // 䜏 + 0x4F50, KANJI_LEARNING_ORDER_7, // 䜐 + 0x4F53, KANJI_LEARNING_ORDER_2, // 䜓 + 0x4F55, KANJI_LEARNING_ORDER_2, // 䜕 + 0x4F59, KANJI_LEARNING_ORDER_5, // 䜙 + 0x4F5C, KANJI_LEARNING_ORDER_2, // 䜜 + 0x4F73, KANJI_LEARNING_ORDER_7, // 䜳 + 0x4F75, KANJI_LEARNING_ORDER_7, // 䜵 + 0x4F7F, KANJI_LEARNING_ORDER_3, // 䜿 + 0x4F8B, KANJI_LEARNING_ORDER_4, // 䟋 + 0x4F8D, KANJI_LEARNING_ORDER_7, // 䟍 + 0x4F9B, KANJI_LEARNING_ORDER_6, // 䟛 + 0x4F9D, KANJI_LEARNING_ORDER_7, // 䟝 + 0x4FA1, KANJI_LEARNING_ORDER_5, // 䟡 + 0x4FAE, KANJI_LEARNING_ORDER_7, // 䟮 + 0x4FAF, KANJI_LEARNING_ORDER_7, // 䟯 + 0x4FB5, KANJI_LEARNING_ORDER_7, // 䟵 + 0x4FBF, KANJI_LEARNING_ORDER_4, // 䟿 + 0x4FC2, KANJI_LEARNING_ORDER_3, // 係 + 0x4FC3, KANJI_LEARNING_ORDER_7, // 促 + 0x4FCA, KANJI_LEARNING_ORDER_7, // 俊 + 0x4FD7, KANJI_LEARNING_ORDER_7, // 俗 + 0x4FDD, KANJI_LEARNING_ORDER_5, // 保 + 0x4FE1, KANJI_LEARNING_ORDER_4, // ä¿¡ + 0x4FEE, KANJI_LEARNING_ORDER_5, // ä¿® + 0x4FF3, KANJI_LEARNING_ORDER_6, // 俳 + 0x4FF5, KANJI_LEARNING_ORDER_5, // 俵 + 0x4FF8, KANJI_LEARNING_ORDER_7, // 俞 + 0x5009, KANJI_LEARNING_ORDER_4, // 倉 + 0x500B, KANJI_LEARNING_ORDER_5, // 個 + 0x500D, KANJI_LEARNING_ORDER_3, // 倍 + 0x5012, KANJI_LEARNING_ORDER_7, // 倒 + 0x5019, KANJI_LEARNING_ORDER_4, // 候 + 0x501F, KANJI_LEARNING_ORDER_4, // 借 + 0x5023, KANJI_LEARNING_ORDER_7, // 倣 + 0x5024, KANJI_LEARNING_ORDER_6, // 倀 + 0x502B, KANJI_LEARNING_ORDER_7, // 倫 + 0x5039, KANJI_LEARNING_ORDER_7, // 倹 + 0x5049, KANJI_LEARNING_ORDER_7, // 偉 + 0x504F, KANJI_LEARNING_ORDER_7, // 偏 + 0x505C, KANJI_LEARNING_ORDER_4, // 停 + 0x5065, KANJI_LEARNING_ORDER_4, // 健 + 0x5074, KANJI_LEARNING_ORDER_4, // 偎 + 0x5075, KANJI_LEARNING_ORDER_7, // 偵 + 0x5076, KANJI_LEARNING_ORDER_7, // 偶 + 0x507D, KANJI_LEARNING_ORDER_7, // 停 + 0x508D, KANJI_LEARNING_ORDER_7, // 傍 + 0x5091, KANJI_LEARNING_ORDER_7, // 傑 + 0x5098, KANJI_LEARNING_ORDER_7, // 傘 + 0x5099, KANJI_LEARNING_ORDER_5, // 備 + 0x50AC, KANJI_LEARNING_ORDER_7, // 催 + 0x50B5, KANJI_LEARNING_ORDER_7, // 債 + 0x50B7, KANJI_LEARNING_ORDER_6, // 傷 + 0x50BE, KANJI_LEARNING_ORDER_7, // 傟 + 0x50CD, KANJI_LEARNING_ORDER_4, // 働 + 0x50CF, KANJI_LEARNING_ORDER_5, // 像 + 0x50D5, KANJI_LEARNING_ORDER_7, // 僕 + 0x50DA, KANJI_LEARNING_ORDER_7, // 僚 + 0x50E7, KANJI_LEARNING_ORDER_7, // 僧 + 0x5100, KANJI_LEARNING_ORDER_7, // 儀 + 0x5104, KANJI_LEARNING_ORDER_4, // 億 + 0x5112, KANJI_LEARNING_ORDER_7, // 儒 + 0x511F, KANJI_LEARNING_ORDER_7, // 償 + 0x512A, KANJI_LEARNING_ORDER_6, // 優 + 0x5143, KANJI_LEARNING_ORDER_2, // 元 + 0x5144, KANJI_LEARNING_ORDER_2, // 兄 + 0x5145, KANJI_LEARNING_ORDER_7, // 充 + 0x5146, KANJI_LEARNING_ORDER_4, // 兆 + 0x5148, KANJI_LEARNING_ORDER_1, // 先 + 0x5149, KANJI_LEARNING_ORDER_2, // 光 + 0x514B, KANJI_LEARNING_ORDER_7, // 克 + 0x514D, KANJI_LEARNING_ORDER_7, // 免 + 0x5150, KANJI_LEARNING_ORDER_4, // 児 + 0x515A, KANJI_LEARNING_ORDER_6, // 党 + 0x5165, KANJI_LEARNING_ORDER_1, // 入 + 0x5168, KANJI_LEARNING_ORDER_3, // å…š + 0x516B, KANJI_LEARNING_ORDER_1, // 八 + 0x516C, KANJI_LEARNING_ORDER_2, // 公 + 0x516D, KANJI_LEARNING_ORDER_1, // 六 + 0x5171, KANJI_LEARNING_ORDER_4, // 共 + 0x5175, KANJI_LEARNING_ORDER_4, // 兵 + 0x5177, KANJI_LEARNING_ORDER_3, // 具 + 0x5178, KANJI_LEARNING_ORDER_4, // å…ž + 0x517C, KANJI_LEARNING_ORDER_7, // å…Œ + 0x5185, KANJI_LEARNING_ORDER_2, // 内 + 0x5186, KANJI_LEARNING_ORDER_1, // 円 + 0x518A, KANJI_LEARNING_ORDER_6, // 冊 + 0x518D, KANJI_LEARNING_ORDER_5, // 再 + 0x5192, KANJI_LEARNING_ORDER_7, // 冒 + 0x5197, KANJI_LEARNING_ORDER_7, // 冗 + 0x5199, KANJI_LEARNING_ORDER_3, // 写 + 0x51A0, KANJI_LEARNING_ORDER_7, // 冠 + 0x51AC, KANJI_LEARNING_ORDER_2, // 冬 + 0x51B7, KANJI_LEARNING_ORDER_4, // 冷 + 0x51C6, KANJI_LEARNING_ORDER_7, // 准 + 0x51CD, KANJI_LEARNING_ORDER_7, // 凍 + 0x51DD, KANJI_LEARNING_ORDER_7, // 凝 + 0x51E1, KANJI_LEARNING_ORDER_7, // 凡 + 0x51E6, KANJI_LEARNING_ORDER_6, // 凊 + 0x51F6, KANJI_LEARNING_ORDER_7, // 凶 + 0x51F8, KANJI_LEARNING_ORDER_7, // 凞 + 0x51F9, KANJI_LEARNING_ORDER_7, // 凹 + 0x51FA, KANJI_LEARNING_ORDER_1, // 出 + 0x5200, KANJI_LEARNING_ORDER_2, // 刀 + 0x5203, KANJI_LEARNING_ORDER_7, // 刃 + 0x5206, KANJI_LEARNING_ORDER_2, // 分 + 0x5207, KANJI_LEARNING_ORDER_2, // 切 + 0x5208, KANJI_LEARNING_ORDER_7, // 刈 + 0x520A, KANJI_LEARNING_ORDER_5, // 刊 + 0x5211, KANJI_LEARNING_ORDER_7, // 刑 + 0x5217, KANJI_LEARNING_ORDER_3, // 列 + 0x521D, KANJI_LEARNING_ORDER_4, // 初 + 0x5224, KANJI_LEARNING_ORDER_5, // 刀 + 0x5225, KANJI_LEARNING_ORDER_4, // 別 + 0x5229, KANJI_LEARNING_ORDER_4, // 利 + 0x5230, KANJI_LEARNING_ORDER_7, // 到 + 0x5236, KANJI_LEARNING_ORDER_5, // 制 + 0x5237, KANJI_LEARNING_ORDER_4, // 刷 + 0x5238, KANJI_LEARNING_ORDER_5, // 刞 + 0x523A, KANJI_LEARNING_ORDER_7, // 刺 + 0x523B, KANJI_LEARNING_ORDER_6, // 刻 + 0x5247, KANJI_LEARNING_ORDER_5, // 則 + 0x524A, KANJI_LEARNING_ORDER_7, // 削 + 0x524D, KANJI_LEARNING_ORDER_2, // 前 + 0x5256, KANJI_LEARNING_ORDER_7, // 剖 + 0x525B, KANJI_LEARNING_ORDER_7, // 剛 + 0x5263, KANJI_LEARNING_ORDER_7, // 剣 + 0x5264, KANJI_LEARNING_ORDER_7, // 剀 + 0x526F, KANJI_LEARNING_ORDER_4, // 副 + 0x5270, KANJI_LEARNING_ORDER_7, // 剰 + 0x5272, KANJI_LEARNING_ORDER_6, // 割 + 0x5275, KANJI_LEARNING_ORDER_6, // 創 + 0x5287, KANJI_LEARNING_ORDER_6, // 劇 + 0x529B, KANJI_LEARNING_ORDER_1, // 力 + 0x529F, KANJI_LEARNING_ORDER_4, // 功 + 0x52A0, KANJI_LEARNING_ORDER_4, // 加 + 0x52A3, KANJI_LEARNING_ORDER_7, // 劣 + 0x52A9, KANJI_LEARNING_ORDER_3, // 助 + 0x52AA, KANJI_LEARNING_ORDER_4, // 努 + 0x52B1, KANJI_LEARNING_ORDER_7, // 励 + 0x52B4, KANJI_LEARNING_ORDER_4, // 劎 + 0x52B9, KANJI_LEARNING_ORDER_5, // 効 + 0x52BE, KANJI_LEARNING_ORDER_7, // 功 + 0x52C5, KANJI_LEARNING_ORDER_7, // 勅 + 0x52C7, KANJI_LEARNING_ORDER_4, // 勇 + 0x52C9, KANJI_LEARNING_ORDER_3, // 勉 + 0x52D5, KANJI_LEARNING_ORDER_3, // 動 + 0x52D8, KANJI_LEARNING_ORDER_7, // 勘 + 0x52D9, KANJI_LEARNING_ORDER_5, // 務 + 0x52DD, KANJI_LEARNING_ORDER_3, // 勝 + 0x52DF, KANJI_LEARNING_ORDER_7, // 募 + 0x52E2, KANJI_LEARNING_ORDER_5, // 勢 + 0x52E4, KANJI_LEARNING_ORDER_6, // å‹€ + 0x52E7, KANJI_LEARNING_ORDER_7, // 勧 + 0x52F2, KANJI_LEARNING_ORDER_7, // 勲 + 0x52FA, KANJI_LEARNING_ORDER_7, // 勺 + 0x5301, KANJI_LEARNING_ORDER_7, // 匁 + 0x5305, KANJI_LEARNING_ORDER_4, // 包 + 0x5316, KANJI_LEARNING_ORDER_3, // 化 + 0x5317, KANJI_LEARNING_ORDER_2, // 北 + 0x5320, KANJI_LEARNING_ORDER_7, // 匠 + 0x5339, KANJI_LEARNING_ORDER_7, // 匹 + 0x533A, KANJI_LEARNING_ORDER_3, // 区 + 0x533B, KANJI_LEARNING_ORDER_3, // 医 + 0x533F, KANJI_LEARNING_ORDER_7, // 匿 + 0x5341, KANJI_LEARNING_ORDER_1, // 十 + 0x5343, KANJI_LEARNING_ORDER_1, // 千 + 0x5347, KANJI_LEARNING_ORDER_7, // 升 + 0x5348, KANJI_LEARNING_ORDER_2, // 午 + 0x534A, KANJI_LEARNING_ORDER_2, // 半 + 0x5351, KANJI_LEARNING_ORDER_7, // 卑 + 0x5352, KANJI_LEARNING_ORDER_4, // 卒 + 0x5353, KANJI_LEARNING_ORDER_7, // 卓 + 0x5354, KANJI_LEARNING_ORDER_4, // 協 + 0x5357, KANJI_LEARNING_ORDER_2, // 南 + 0x5358, KANJI_LEARNING_ORDER_4, // 単 + 0x535A, KANJI_LEARNING_ORDER_4, // 博 + 0x5360, KANJI_LEARNING_ORDER_7, // 占 + 0x5370, KANJI_LEARNING_ORDER_4, // 印 + 0x5371, KANJI_LEARNING_ORDER_6, // 危 + 0x5373, KANJI_LEARNING_ORDER_7, // 即 + 0x5374, KANJI_LEARNING_ORDER_7, // 华 + 0x5375, KANJI_LEARNING_ORDER_6, // 卵 + 0x5378, KANJI_LEARNING_ORDER_7, // 卞 + 0x5384, KANJI_LEARNING_ORDER_7, // 厄 + 0x5398, KANJI_LEARNING_ORDER_7, // 厘 + 0x539A, KANJI_LEARNING_ORDER_5, // 厚 + 0x539F, KANJI_LEARNING_ORDER_2, // 原 + 0x53B3, KANJI_LEARNING_ORDER_6, // 厳 + 0x53BB, KANJI_LEARNING_ORDER_3, // 去 + 0x53C2, KANJI_LEARNING_ORDER_4, // 参 + 0x53C8, KANJI_LEARNING_ORDER_7, // 又 + 0x53CA, KANJI_LEARNING_ORDER_7, // 及 + 0x53CB, KANJI_LEARNING_ORDER_2, // 友 + 0x53CC, KANJI_LEARNING_ORDER_7, // 双 + 0x53CD, KANJI_LEARNING_ORDER_3, // 反 + 0x53CE, KANJI_LEARNING_ORDER_6, // 収 + 0x53D4, KANJI_LEARNING_ORDER_7, // 叔 + 0x53D6, KANJI_LEARNING_ORDER_3, // 取 + 0x53D7, KANJI_LEARNING_ORDER_3, // 受 + 0x53D9, KANJI_LEARNING_ORDER_7, // 叙 + 0x53E3, KANJI_LEARNING_ORDER_1, // 口 + 0x53E4, KANJI_LEARNING_ORDER_2, // 叀 + 0x53E5, KANJI_LEARNING_ORDER_5, // 句 + 0x53EB, KANJI_LEARNING_ORDER_7, // 叫 + 0x53EC, KANJI_LEARNING_ORDER_7, // 召 + 0x53EF, KANJI_LEARNING_ORDER_5, // 可 + 0x53F0, KANJI_LEARNING_ORDER_2, // 台 + 0x53F2, KANJI_LEARNING_ORDER_4, // 史 + 0x53F3, KANJI_LEARNING_ORDER_1, // 右 + 0x53F7, KANJI_LEARNING_ORDER_3, // 号 + 0x53F8, KANJI_LEARNING_ORDER_4, // 叞 + 0x5404, KANJI_LEARNING_ORDER_4, // 各 + 0x5408, KANJI_LEARNING_ORDER_2, // 合 + 0x5409, KANJI_LEARNING_ORDER_7, // 吉 + 0x540C, KANJI_LEARNING_ORDER_2, // 同 + 0x540D, KANJI_LEARNING_ORDER_1, // 名 + 0x540E, KANJI_LEARNING_ORDER_6, // 后 + 0x540F, KANJI_LEARNING_ORDER_7, // 吏 + 0x5410, KANJI_LEARNING_ORDER_7, // 吐 + 0x5411, KANJI_LEARNING_ORDER_3, // 向 + 0x541B, KANJI_LEARNING_ORDER_3, // 君 + 0x541F, KANJI_LEARNING_ORDER_7, // 吟 + 0x5426, KANJI_LEARNING_ORDER_6, // 吊 + 0x542B, KANJI_LEARNING_ORDER_7, // 含 + 0x5438, KANJI_LEARNING_ORDER_6, // 吞 + 0x5439, KANJI_LEARNING_ORDER_7, // 吹 + 0x5448, KANJI_LEARNING_ORDER_7, // 呈 + 0x5449, KANJI_LEARNING_ORDER_7, // 呉 + 0x544A, KANJI_LEARNING_ORDER_4, // 告 + 0x5468, KANJI_LEARNING_ORDER_4, // 呚 + 0x5473, KANJI_LEARNING_ORDER_3, // 味 + 0x547C, KANJI_LEARNING_ORDER_6, // 呌 + 0x547D, KANJI_LEARNING_ORDER_3, // 呜 + 0x548C, KANJI_LEARNING_ORDER_3, // 和 + 0x54B2, KANJI_LEARNING_ORDER_7, // 咲 + 0x54C0, KANJI_LEARNING_ORDER_7, // 哀 + 0x54C1, KANJI_LEARNING_ORDER_3, // 品 + 0x54E1, KANJI_LEARNING_ORDER_3, // 員 + 0x54F2, KANJI_LEARNING_ORDER_7, // 哲 + 0x5506, KANJI_LEARNING_ORDER_7, // 唆 + 0x5507, KANJI_LEARNING_ORDER_7, // 唇 + 0x5510, KANJI_LEARNING_ORDER_7, // 唐 + 0x552F, KANJI_LEARNING_ORDER_7, // 唯 + 0x5531, KANJI_LEARNING_ORDER_4, // 唱 + 0x5546, KANJI_LEARNING_ORDER_3, // 商 + 0x554F, KANJI_LEARNING_ORDER_3, // 問 + 0x5553, KANJI_LEARNING_ORDER_7, // 啓 + 0x5584, KANJI_LEARNING_ORDER_6, // 善 + 0x559A, KANJI_LEARNING_ORDER_7, // 喚 + 0x559C, KANJI_LEARNING_ORDER_4, // 喜 + 0x559D, KANJI_LEARNING_ORDER_7, // 喝 + 0x55AA, KANJI_LEARNING_ORDER_7, // 喪 + 0x55AB, KANJI_LEARNING_ORDER_7, // 喫 + 0x55B6, KANJI_LEARNING_ORDER_5, // 営 + 0x55E3, KANJI_LEARNING_ORDER_7, // 嗣 + 0x5606, KANJI_LEARNING_ORDER_7, // 嘆 + 0x5631, KANJI_LEARNING_ORDER_7, // 嘱 + 0x5668, KANJI_LEARNING_ORDER_4, // 噚 + 0x5674, KANJI_LEARNING_ORDER_7, // 噎 + 0x5687, KANJI_LEARNING_ORDER_7, // 嚇 + 0x56DA, KANJI_LEARNING_ORDER_7, // 囚 + 0x56DB, KANJI_LEARNING_ORDER_1, // 四 + 0x56DE, KANJI_LEARNING_ORDER_2, // 回 + 0x56E0, KANJI_LEARNING_ORDER_5, // 因 + 0x56E3, KANJI_LEARNING_ORDER_5, // 団 + 0x56F0, KANJI_LEARNING_ORDER_6, // 困 + 0x56F2, KANJI_LEARNING_ORDER_4, // 囲 + 0x56F3, KANJI_LEARNING_ORDER_2, // 図 + 0x56FA, KANJI_LEARNING_ORDER_4, // 固 + 0x56FD, KANJI_LEARNING_ORDER_2, // 囜 + 0x570F, KANJI_LEARNING_ORDER_7, // 圏 + 0x5712, KANJI_LEARNING_ORDER_2, // 園 + 0x571F, KANJI_LEARNING_ORDER_1, // 土 + 0x5727, KANJI_LEARNING_ORDER_5, // 圧 + 0x5728, KANJI_LEARNING_ORDER_5, // 圚 + 0x5730, KANJI_LEARNING_ORDER_2, // 地 + 0x5742, KANJI_LEARNING_ORDER_3, // 坂 + 0x5747, KANJI_LEARNING_ORDER_5, // 均 + 0x574A, KANJI_LEARNING_ORDER_7, // 坊 + 0x5751, KANJI_LEARNING_ORDER_7, // 坑 + 0x576A, KANJI_LEARNING_ORDER_7, // 坪 + 0x5782, KANJI_LEARNING_ORDER_6, // 垂 + 0x578B, KANJI_LEARNING_ORDER_4, // 型 + 0x57A3, KANJI_LEARNING_ORDER_7, // 垣 + 0x57CB, KANJI_LEARNING_ORDER_7, // 埋 + 0x57CE, KANJI_LEARNING_ORDER_6, // 城 + 0x57DF, KANJI_LEARNING_ORDER_6, // 域 + 0x57F7, KANJI_LEARNING_ORDER_7, // 執 + 0x57F9, KANJI_LEARNING_ORDER_7, // 培 + 0x57FA, KANJI_LEARNING_ORDER_5, // 基 + 0x5800, KANJI_LEARNING_ORDER_7, // 堀 + 0x5802, KANJI_LEARNING_ORDER_4, // 堂 + 0x5805, KANJI_LEARNING_ORDER_7, // 堅 + 0x5815, KANJI_LEARNING_ORDER_7, // 堕 + 0x5824, KANJI_LEARNING_ORDER_7, // å € + 0x582A, KANJI_LEARNING_ORDER_7, // å ª + 0x5831, KANJI_LEARNING_ORDER_5, // å ± + 0x5834, KANJI_LEARNING_ORDER_2, // å Ž + 0x5840, KANJI_LEARNING_ORDER_7, // 塀 + 0x5841, KANJI_LEARNING_ORDER_7, // 塁 + 0x584A, KANJI_LEARNING_ORDER_7, // 塊 + 0x5851, KANJI_LEARNING_ORDER_7, // 塑 + 0x5854, KANJI_LEARNING_ORDER_7, // 塔 + 0x5857, KANJI_LEARNING_ORDER_7, // 塗 + 0x585A, KANJI_LEARNING_ORDER_7, // 塚 + 0x5869, KANJI_LEARNING_ORDER_4, // å¡© + 0x587E, KANJI_LEARNING_ORDER_7, // 塟 + 0x5883, KANJI_LEARNING_ORDER_5, // 境 + 0x5893, KANJI_LEARNING_ORDER_5, // 墓 + 0x5897, KANJI_LEARNING_ORDER_5, // 増 + 0x589C, KANJI_LEARNING_ORDER_7, // 墜 + 0x58A8, KANJI_LEARNING_ORDER_7, // 墚 + 0x58B3, KANJI_LEARNING_ORDER_7, // 墳 + 0x58BE, KANJI_LEARNING_ORDER_7, // 墟 + 0x58C1, KANJI_LEARNING_ORDER_7, // 壁 + 0x58C7, KANJI_LEARNING_ORDER_7, // 壇 + 0x58CA, KANJI_LEARNING_ORDER_7, // 壊 + 0x58CC, KANJI_LEARNING_ORDER_7, // 壌 + 0x58EB, KANJI_LEARNING_ORDER_4, // 士 + 0x58EE, KANJI_LEARNING_ORDER_7, // 壮 + 0x58F0, KANJI_LEARNING_ORDER_2, // 声 + 0x58F1, KANJI_LEARNING_ORDER_7, // 壱 + 0x58F2, KANJI_LEARNING_ORDER_2, // 売 + 0x5909, KANJI_LEARNING_ORDER_4, // 倉 + 0x590F, KANJI_LEARNING_ORDER_2, // 倏 + 0x5915, KANJI_LEARNING_ORDER_1, // 倕 + 0x5916, KANJI_LEARNING_ORDER_2, // 倖 + 0x591A, KANJI_LEARNING_ORDER_2, // 倚 + 0x591C, KANJI_LEARNING_ORDER_2, // 倜 + 0x5922, KANJI_LEARNING_ORDER_5, // 倢 + 0x5927, KANJI_LEARNING_ORDER_1, // 倧 + 0x5929, KANJI_LEARNING_ORDER_1, // 倩 + 0x592A, KANJI_LEARNING_ORDER_2, // 倪 + 0x592B, KANJI_LEARNING_ORDER_4, // 倫 + 0x592E, KANJI_LEARNING_ORDER_3, // 倮 + 0x5931, KANJI_LEARNING_ORDER_4, // 倱 + 0x5947, KANJI_LEARNING_ORDER_7, // 奇 + 0x5949, KANJI_LEARNING_ORDER_7, // 奉 + 0x594F, KANJI_LEARNING_ORDER_6, // 奏 + 0x5951, KANJI_LEARNING_ORDER_7, // 契 + 0x5954, KANJI_LEARNING_ORDER_7, // 奔 + 0x5965, KANJI_LEARNING_ORDER_7, // 奥 + 0x5968, KANJI_LEARNING_ORDER_7, // 奚 + 0x596A, KANJI_LEARNING_ORDER_7, // 奪 + 0x596E, KANJI_LEARNING_ORDER_6, // 奮 + 0x5973, KANJI_LEARNING_ORDER_1, // 女 + 0x5974, KANJI_LEARNING_ORDER_7, // 奎 + 0x597D, KANJI_LEARNING_ORDER_4, // 奜 + 0x5982, KANJI_LEARNING_ORDER_7, // 劂 + 0x5983, KANJI_LEARNING_ORDER_7, // 劃 + 0x5984, KANJI_LEARNING_ORDER_7, // 劄 + 0x598A, KANJI_LEARNING_ORDER_7, // 劊 + 0x5999, KANJI_LEARNING_ORDER_7, // 劙 + 0x59A5, KANJI_LEARNING_ORDER_7, // 劥 + 0x59A8, KANJI_LEARNING_ORDER_7, // 劚 + 0x59B9, KANJI_LEARNING_ORDER_2, // 効 + 0x59BB, KANJI_LEARNING_ORDER_5, // 劻 + 0x59C9, KANJI_LEARNING_ORDER_2, // 姉 + 0x59CB, KANJI_LEARNING_ORDER_3, // 始 + 0x59D3, KANJI_LEARNING_ORDER_7, // 姓 + 0x59D4, KANJI_LEARNING_ORDER_3, // 委 + 0x59EB, KANJI_LEARNING_ORDER_7, // å§« + 0x59FB, KANJI_LEARNING_ORDER_7, // å§» + 0x59FF, KANJI_LEARNING_ORDER_6, // å§¿ + 0x5A01, KANJI_LEARNING_ORDER_7, // 嚁 + 0x5A18, KANJI_LEARNING_ORDER_7, // 嚘 + 0x5A20, KANJI_LEARNING_ORDER_7, // åš  + 0x5A2F, KANJI_LEARNING_ORDER_7, // 嚯 + 0x5A46, KANJI_LEARNING_ORDER_7, // 婆 + 0x5A5A, KANJI_LEARNING_ORDER_7, // 婚 + 0x5A66, KANJI_LEARNING_ORDER_5, // 婊 + 0x5A7F, KANJI_LEARNING_ORDER_7, // å©¿ + 0x5A92, KANJI_LEARNING_ORDER_7, // 媒 + 0x5AC1, KANJI_LEARNING_ORDER_7, // 嫁 + 0x5ACC, KANJI_LEARNING_ORDER_7, // 嫌 + 0x5AE1, KANJI_LEARNING_ORDER_7, // å«¡ + 0x5B22, KANJI_LEARNING_ORDER_7, // 嬢 + 0x5B50, KANJI_LEARNING_ORDER_1, // 子 + 0x5B54, KANJI_LEARNING_ORDER_7, // 孔 + 0x5B57, KANJI_LEARNING_ORDER_1, // 字 + 0x5B58, KANJI_LEARNING_ORDER_6, // 存 + 0x5B5D, KANJI_LEARNING_ORDER_6, // 孝 + 0x5B63, KANJI_LEARNING_ORDER_4, // å­£ + 0x5B64, KANJI_LEARNING_ORDER_7, // å­€ + 0x5B66, KANJI_LEARNING_ORDER_1, // å­Š + 0x5B6B, KANJI_LEARNING_ORDER_4, // å­« + 0x5B85, KANJI_LEARNING_ORDER_6, // 宅 + 0x5B87, KANJI_LEARNING_ORDER_6, // 宇 + 0x5B88, KANJI_LEARNING_ORDER_3, // 守 + 0x5B89, KANJI_LEARNING_ORDER_3, // 安 + 0x5B8C, KANJI_LEARNING_ORDER_4, // 完 + 0x5B97, KANJI_LEARNING_ORDER_6, // 宗 + 0x5B98, KANJI_LEARNING_ORDER_4, // 官 + 0x5B99, KANJI_LEARNING_ORDER_6, // 宙 + 0x5B9A, KANJI_LEARNING_ORDER_3, // 定 + 0x5B9C, KANJI_LEARNING_ORDER_7, // 宜 + 0x5B9D, KANJI_LEARNING_ORDER_6, // 宝 + 0x5B9F, KANJI_LEARNING_ORDER_3, // 実 + 0x5BA2, KANJI_LEARNING_ORDER_3, // 客 + 0x5BA3, KANJI_LEARNING_ORDER_6, // 宣 + 0x5BA4, KANJI_LEARNING_ORDER_2, // 宀 + 0x5BAE, KANJI_LEARNING_ORDER_3, // å®® + 0x5BB0, KANJI_LEARNING_ORDER_7, // å®° + 0x5BB3, KANJI_LEARNING_ORDER_4, // 害 + 0x5BB4, KANJI_LEARNING_ORDER_7, // 宎 + 0x5BB5, KANJI_LEARNING_ORDER_7, // 宵 + 0x5BB6, KANJI_LEARNING_ORDER_2, // å®¶ + 0x5BB9, KANJI_LEARNING_ORDER_5, // 容 + 0x5BBF, KANJI_LEARNING_ORDER_3, // 宿 + 0x5BC2, KANJI_LEARNING_ORDER_7, // 寂 + 0x5BC4, KANJI_LEARNING_ORDER_5, // 寄 + 0x5BC6, KANJI_LEARNING_ORDER_6, // 密 + 0x5BCC, KANJI_LEARNING_ORDER_5, // 富 + 0x5BD2, KANJI_LEARNING_ORDER_3, // 寒 + 0x5BDB, KANJI_LEARNING_ORDER_7, // 寛 + 0x5BDD, KANJI_LEARNING_ORDER_7, // 寝 + 0x5BDF, KANJI_LEARNING_ORDER_4, // 察 + 0x5BE1, KANJI_LEARNING_ORDER_7, // 寡 + 0x5BE7, KANJI_LEARNING_ORDER_7, // 寧 + 0x5BE9, KANJI_LEARNING_ORDER_7, // 審 + 0x5BEE, KANJI_LEARNING_ORDER_7, // 寮 + 0x5BF8, KANJI_LEARNING_ORDER_6, // 寞 + 0x5BFA, KANJI_LEARNING_ORDER_2, // 寺 + 0x5BFE, KANJI_LEARNING_ORDER_3, // 察 + 0x5BFF, KANJI_LEARNING_ORDER_7, // 寿 + 0x5C01, KANJI_LEARNING_ORDER_7, // 封 + 0x5C02, KANJI_LEARNING_ORDER_6, // 専 + 0x5C04, KANJI_LEARNING_ORDER_6, // 射 + 0x5C06, KANJI_LEARNING_ORDER_6, // 将 + 0x5C09, KANJI_LEARNING_ORDER_7, // 尉 + 0x5C0A, KANJI_LEARNING_ORDER_6, // 尊 + 0x5C0B, KANJI_LEARNING_ORDER_7, // 尋 + 0x5C0E, KANJI_LEARNING_ORDER_5, // 導 + 0x5C0F, KANJI_LEARNING_ORDER_1, // 小 + 0x5C11, KANJI_LEARNING_ORDER_2, // 少 + 0x5C1A, KANJI_LEARNING_ORDER_7, // 尚 + 0x5C31, KANJI_LEARNING_ORDER_6, // å°± + 0x5C3A, KANJI_LEARNING_ORDER_6, // å°º + 0x5C3C, KANJI_LEARNING_ORDER_7, // å°Œ + 0x5C3D, KANJI_LEARNING_ORDER_7, // å°œ + 0x5C3E, KANJI_LEARNING_ORDER_7, // å°Ÿ + 0x5C3F, KANJI_LEARNING_ORDER_7, // å°¿ + 0x5C40, KANJI_LEARNING_ORDER_3, // 局 + 0x5C45, KANJI_LEARNING_ORDER_5, // 居 + 0x5C48, KANJI_LEARNING_ORDER_7, // 屈 + 0x5C4A, KANJI_LEARNING_ORDER_6, // 届 + 0x5C4B, KANJI_LEARNING_ORDER_3, // 屋 + 0x5C55, KANJI_LEARNING_ORDER_6, // 展 + 0x5C5E, KANJI_LEARNING_ORDER_5, // 属 + 0x5C64, KANJI_LEARNING_ORDER_6, // å±€ + 0x5C65, KANJI_LEARNING_ORDER_7, // å±¥ + 0x5C6F, KANJI_LEARNING_ORDER_7, // 屯 + 0x5C71, KANJI_LEARNING_ORDER_1, // å±± + 0x5C90, KANJI_LEARNING_ORDER_7, // 岐 + 0x5CA9, KANJI_LEARNING_ORDER_2, // 岩 + 0x5CAC, KANJI_LEARNING_ORDER_7, // 岬 + 0x5CB3, KANJI_LEARNING_ORDER_7, // å²³ + 0x5CB8, KANJI_LEARNING_ORDER_3, // 岞 + 0x5CE0, KANJI_LEARNING_ORDER_7, // å³  + 0x5CE1, KANJI_LEARNING_ORDER_7, // 峡 + 0x5CF0, KANJI_LEARNING_ORDER_7, // å³° + 0x5CF6, KANJI_LEARNING_ORDER_3, // å³¶ + 0x5D07, KANJI_LEARNING_ORDER_7, // 厇 + 0x5D0E, KANJI_LEARNING_ORDER_7, // 厎 + 0x5D29, KANJI_LEARNING_ORDER_7, // 厩 + 0x5DDD, KANJI_LEARNING_ORDER_1, // 川 + 0x5DDE, KANJI_LEARNING_ORDER_3, // 州 + 0x5DE1, KANJI_LEARNING_ORDER_7, // å·¡ + 0x5DE3, KANJI_LEARNING_ORDER_4, // å·£ + 0x5DE5, KANJI_LEARNING_ORDER_2, // å·¥ + 0x5DE6, KANJI_LEARNING_ORDER_1, // å·Š + 0x5DE7, KANJI_LEARNING_ORDER_7, // å·§ + 0x5DE8, KANJI_LEARNING_ORDER_7, // å·š + 0x5DEE, KANJI_LEARNING_ORDER_4, // å·® + 0x5DF1, KANJI_LEARNING_ORDER_6, // å·± + 0x5DFB, KANJI_LEARNING_ORDER_6, // å·» + 0x5E02, KANJI_LEARNING_ORDER_2, // åž‚ + 0x5E03, KANJI_LEARNING_ORDER_5, // 垃 + 0x5E06, KANJI_LEARNING_ORDER_7, // 垆 + 0x5E0C, KANJI_LEARNING_ORDER_4, // 垌 + 0x5E1D, KANJI_LEARNING_ORDER_7, // 垝 + 0x5E25, KANJI_LEARNING_ORDER_7, // 垥 + 0x5E2B, KANJI_LEARNING_ORDER_5, // åž« + 0x5E2D, KANJI_LEARNING_ORDER_4, // åž­ + 0x5E2F, KANJI_LEARNING_ORDER_4, // 垯 + 0x5E30, KANJI_LEARNING_ORDER_2, // åž° + 0x5E33, KANJI_LEARNING_ORDER_3, // åž³ + 0x5E38, KANJI_LEARNING_ORDER_5, // åžž + 0x5E3D, KANJI_LEARNING_ORDER_7, // åžœ + 0x5E45, KANJI_LEARNING_ORDER_7, // 幅 + 0x5E55, KANJI_LEARNING_ORDER_6, // 幕 + 0x5E63, KANJI_LEARNING_ORDER_7, // å¹£ + 0x5E72, KANJI_LEARNING_ORDER_6, // å¹² + 0x5E73, KANJI_LEARNING_ORDER_3, // å¹³ + 0x5E74, KANJI_LEARNING_ORDER_1, // 幎 + 0x5E78, KANJI_LEARNING_ORDER_3, // 幞 + 0x5E79, KANJI_LEARNING_ORDER_5, // å¹¹ + 0x5E7B, KANJI_LEARNING_ORDER_7, // å¹» + 0x5E7C, KANJI_LEARNING_ORDER_6, // 幌 + 0x5E7D, KANJI_LEARNING_ORDER_7, // 幜 + 0x5E7E, KANJI_LEARNING_ORDER_7, // 幟 + 0x5E81, KANJI_LEARNING_ORDER_6, // 庁 + 0x5E83, KANJI_LEARNING_ORDER_2, // 広 + 0x5E8A, KANJI_LEARNING_ORDER_7, // 床 + 0x5E8F, KANJI_LEARNING_ORDER_5, // 序 + 0x5E95, KANJI_LEARNING_ORDER_4, // 底 + 0x5E97, KANJI_LEARNING_ORDER_2, // 店 + 0x5E9C, KANJI_LEARNING_ORDER_4, // 府 + 0x5EA6, KANJI_LEARNING_ORDER_3, // 床 + 0x5EA7, KANJI_LEARNING_ORDER_6, // 座 + 0x5EAB, KANJI_LEARNING_ORDER_3, // 庫 + 0x5EAD, KANJI_LEARNING_ORDER_3, // 庭 + 0x5EB6, KANJI_LEARNING_ORDER_7, // 庶 + 0x5EB7, KANJI_LEARNING_ORDER_4, // 康 + 0x5EB8, KANJI_LEARNING_ORDER_7, // 庞 + 0x5EC3, KANJI_LEARNING_ORDER_7, // 廃 + 0x5EC9, KANJI_LEARNING_ORDER_7, // 廉 + 0x5ECA, KANJI_LEARNING_ORDER_7, // 廊 + 0x5EF6, KANJI_LEARNING_ORDER_6, // å»¶ + 0x5EF7, KANJI_LEARNING_ORDER_7, // å»· + 0x5EFA, KANJI_LEARNING_ORDER_4, // 建 + 0x5F01, KANJI_LEARNING_ORDER_5, // 匁 + 0x5F0A, KANJI_LEARNING_ORDER_7, // 匊 + 0x5F0F, KANJI_LEARNING_ORDER_3, // 匏 + 0x5F10, KANJI_LEARNING_ORDER_7, // 匐 + 0x5F13, KANJI_LEARNING_ORDER_2, // 匓 + 0x5F14, KANJI_LEARNING_ORDER_7, // 匔 + 0x5F15, KANJI_LEARNING_ORDER_2, // 匕 + 0x5F1F, KANJI_LEARNING_ORDER_2, // 匟 + 0x5F26, KANJI_LEARNING_ORDER_7, // 匊 + 0x5F27, KANJI_LEARNING_ORDER_7, // 匧 + 0x5F31, KANJI_LEARNING_ORDER_2, // 匱 + 0x5F35, KANJI_LEARNING_ORDER_5, // 匵 + 0x5F37, KANJI_LEARNING_ORDER_2, // 匷 + 0x5F3E, KANJI_LEARNING_ORDER_7, // 匟 + 0x5F53, KANJI_LEARNING_ORDER_2, // 圓 + 0x5F62, KANJI_LEARNING_ORDER_2, // 圢 + 0x5F69, KANJI_LEARNING_ORDER_7, // 圩 + 0x5F6B, KANJI_LEARNING_ORDER_7, // 圫 + 0x5F70, KANJI_LEARNING_ORDER_7, // 地 + 0x5F71, KANJI_LEARNING_ORDER_7, // 圱 + 0x5F79, KANJI_LEARNING_ORDER_3, // 圹 + 0x5F7C, KANJI_LEARNING_ORDER_7, // 圌 + 0x5F80, KANJI_LEARNING_ORDER_5, // 埀 + 0x5F81, KANJI_LEARNING_ORDER_7, // 埁 + 0x5F84, KANJI_LEARNING_ORDER_4, // 埄 + 0x5F85, KANJI_LEARNING_ORDER_3, // 埅 + 0x5F8B, KANJI_LEARNING_ORDER_6, // 埋 + 0x5F8C, KANJI_LEARNING_ORDER_2, // 埌 + 0x5F90, KANJI_LEARNING_ORDER_7, // 埐 + 0x5F92, KANJI_LEARNING_ORDER_4, // 埒 + 0x5F93, KANJI_LEARNING_ORDER_6, // 埓 + 0x5F97, KANJI_LEARNING_ORDER_4, // 埗 + 0x5FA1, KANJI_LEARNING_ORDER_7, // 埡 + 0x5FA9, KANJI_LEARNING_ORDER_5, // 埩 + 0x5FAA, KANJI_LEARNING_ORDER_7, // 埪 + 0x5FAE, KANJI_LEARNING_ORDER_7, // 埮 + 0x5FB3, KANJI_LEARNING_ORDER_5, // 埳 + 0x5FB4, KANJI_LEARNING_ORDER_7, // 城 + 0x5FB9, KANJI_LEARNING_ORDER_7, // 培 + 0x5FC3, KANJI_LEARNING_ORDER_2, // 心 + 0x5FC5, KANJI_LEARNING_ORDER_4, // 必 + 0x5FCC, KANJI_LEARNING_ORDER_7, // 忌 + 0x5FCD, KANJI_LEARNING_ORDER_7, // 忍 + 0x5FD7, KANJI_LEARNING_ORDER_5, // 志 + 0x5FD8, KANJI_LEARNING_ORDER_6, // 忘 + 0x5FD9, KANJI_LEARNING_ORDER_7, // 忙 + 0x5FDC, KANJI_LEARNING_ORDER_5, // 応 + 0x5FE0, KANJI_LEARNING_ORDER_6, // å¿  + 0x5FEB, KANJI_LEARNING_ORDER_5, // å¿« + 0x5FF5, KANJI_LEARNING_ORDER_4, // 念 + 0x6012, KANJI_LEARNING_ORDER_7, // 怒 + 0x6016, KANJI_LEARNING_ORDER_7, // 怖 + 0x601D, KANJI_LEARNING_ORDER_2, // 思 + 0x6020, KANJI_LEARNING_ORDER_7, // 怠 + 0x6025, KANJI_LEARNING_ORDER_3, // 急 + 0x6027, KANJI_LEARNING_ORDER_5, // 性 + 0x602A, KANJI_LEARNING_ORDER_7, // 怪 + 0x604B, KANJI_LEARNING_ORDER_7, // 恋 + 0x6050, KANJI_LEARNING_ORDER_7, // 恐 + 0x6052, KANJI_LEARNING_ORDER_7, // 恒 + 0x6065, KANJI_LEARNING_ORDER_7, // 恥 + 0x6068, KANJI_LEARNING_ORDER_7, // 恚 + 0x6069, KANJI_LEARNING_ORDER_5, // 恩 + 0x606D, KANJI_LEARNING_ORDER_7, // 恭 + 0x606F, KANJI_LEARNING_ORDER_3, // 息 + 0x6075, KANJI_LEARNING_ORDER_7, // 恵 + 0x6094, KANJI_LEARNING_ORDER_7, // 悔 + 0x609F, KANJI_LEARNING_ORDER_7, // 悟 + 0x60A0, KANJI_LEARNING_ORDER_7, // 悠 + 0x60A3, KANJI_LEARNING_ORDER_7, // 患 + 0x60A6, KANJI_LEARNING_ORDER_7, // 悊 + 0x60A9, KANJI_LEARNING_ORDER_7, // 悩 + 0x60AA, KANJI_LEARNING_ORDER_3, // 悪 + 0x60B2, KANJI_LEARNING_ORDER_3, // 悲 + 0x60BC, KANJI_LEARNING_ORDER_7, // 悌 + 0x60C5, KANJI_LEARNING_ORDER_5, // 情 + 0x60D1, KANJI_LEARNING_ORDER_7, // 惑 + 0x60DC, KANJI_LEARNING_ORDER_7, // 惜 + 0x60E8, KANJI_LEARNING_ORDER_7, // 惚 + 0x60F0, KANJI_LEARNING_ORDER_7, // 惰 + 0x60F3, KANJI_LEARNING_ORDER_3, // 想 + 0x6101, KANJI_LEARNING_ORDER_7, // 愁 + 0x6109, KANJI_LEARNING_ORDER_7, // 愉 + 0x610F, KANJI_LEARNING_ORDER_3, // 意 + 0x611A, KANJI_LEARNING_ORDER_7, // 愚 + 0x611B, KANJI_LEARNING_ORDER_4, // 愛 + 0x611F, KANJI_LEARNING_ORDER_3, // 感 + 0x6148, KANJI_LEARNING_ORDER_7, // 慈 + 0x614B, KANJI_LEARNING_ORDER_5, // 態 + 0x614C, KANJI_LEARNING_ORDER_7, // 慌 + 0x614E, KANJI_LEARNING_ORDER_7, // 慎 + 0x6155, KANJI_LEARNING_ORDER_7, // 慕 + 0x6162, KANJI_LEARNING_ORDER_7, // 慢 + 0x6163, KANJI_LEARNING_ORDER_5, // 慣 + 0x6168, KANJI_LEARNING_ORDER_7, // æ…š + 0x616E, KANJI_LEARNING_ORDER_7, // 慮 + 0x6170, KANJI_LEARNING_ORDER_7, // 慰 + 0x6176, KANJI_LEARNING_ORDER_7, // 慶 + 0x6182, KANJI_LEARNING_ORDER_7, // 憂 + 0x618E, KANJI_LEARNING_ORDER_7, // 憎 + 0x61A4, KANJI_LEARNING_ORDER_7, // 憀 + 0x61A9, KANJI_LEARNING_ORDER_7, // 憩 + 0x61B2, KANJI_LEARNING_ORDER_6, // 憲 + 0x61B6, KANJI_LEARNING_ORDER_7, // 憶 + 0x61BE, KANJI_LEARNING_ORDER_7, // 憟 + 0x61C7, KANJI_LEARNING_ORDER_7, // 懇 + 0x61D0, KANJI_LEARNING_ORDER_7, // 懐 + 0x61F2, KANJI_LEARNING_ORDER_7, // 懲 + 0x61F8, KANJI_LEARNING_ORDER_7, // 懞 + 0x6210, KANJI_LEARNING_ORDER_4, // 成 + 0x6211, KANJI_LEARNING_ORDER_6, // 我 + 0x6212, KANJI_LEARNING_ORDER_7, // 戒 + 0x6226, KANJI_LEARNING_ORDER_4, // 戊 + 0x622F, KANJI_LEARNING_ORDER_7, // 戯 + 0x6238, KANJI_LEARNING_ORDER_2, // 戞 + 0x623B, KANJI_LEARNING_ORDER_7, // 戻 + 0x623F, KANJI_LEARNING_ORDER_7, // 房 + 0x6240, KANJI_LEARNING_ORDER_3, // 所 + 0x6247, KANJI_LEARNING_ORDER_7, // 扇 + 0x6249, KANJI_LEARNING_ORDER_7, // 扉 + 0x624B, KANJI_LEARNING_ORDER_1, // 手 + 0x624D, KANJI_LEARNING_ORDER_2, // 才 + 0x6253, KANJI_LEARNING_ORDER_3, // 打 + 0x6255, KANJI_LEARNING_ORDER_7, // 払 + 0x6271, KANJI_LEARNING_ORDER_7, // 扱 + 0x6276, KANJI_LEARNING_ORDER_7, // 扶 + 0x6279, KANJI_LEARNING_ORDER_6, // 批 + 0x627F, KANJI_LEARNING_ORDER_5, // 承 + 0x6280, KANJI_LEARNING_ORDER_5, // 技 + 0x6284, KANJI_LEARNING_ORDER_7, // 抄 + 0x628A, KANJI_LEARNING_ORDER_7, // 把 + 0x6291, KANJI_LEARNING_ORDER_7, // 抑 + 0x6295, KANJI_LEARNING_ORDER_3, // 投 + 0x6297, KANJI_LEARNING_ORDER_7, // 抗 + 0x6298, KANJI_LEARNING_ORDER_4, // 折 + 0x629C, KANJI_LEARNING_ORDER_7, // 抜 + 0x629E, KANJI_LEARNING_ORDER_7, // 択 + 0x62AB, KANJI_LEARNING_ORDER_7, // 披 + 0x62B1, KANJI_LEARNING_ORDER_7, // 抱 + 0x62B5, KANJI_LEARNING_ORDER_7, // 抵 + 0x62B9, KANJI_LEARNING_ORDER_7, // 抹 + 0x62BC, KANJI_LEARNING_ORDER_7, // 抌 + 0x62BD, KANJI_LEARNING_ORDER_7, // 抜 + 0x62C5, KANJI_LEARNING_ORDER_6, // 担 + 0x62CD, KANJI_LEARNING_ORDER_7, // 拍 + 0x62D0, KANJI_LEARNING_ORDER_7, // 拐 + 0x62D2, KANJI_LEARNING_ORDER_7, // 拒 + 0x62D3, KANJI_LEARNING_ORDER_7, // 拓 + 0x62D8, KANJI_LEARNING_ORDER_7, // 拘 + 0x62D9, KANJI_LEARNING_ORDER_7, // 拙 + 0x62DB, KANJI_LEARNING_ORDER_5, // 招 + 0x62DD, KANJI_LEARNING_ORDER_6, // 拝 + 0x62E0, KANJI_LEARNING_ORDER_7, // 拠 + 0x62E1, KANJI_LEARNING_ORDER_6, // 拡 + 0x62EC, KANJI_LEARNING_ORDER_7, // 括 + 0x62F7, KANJI_LEARNING_ORDER_7, // 拷 + 0x62FE, KANJI_LEARNING_ORDER_3, // 拟 + 0x6301, KANJI_LEARNING_ORDER_3, // 持 + 0x6307, KANJI_LEARNING_ORDER_3, // 指 + 0x6311, KANJI_LEARNING_ORDER_7, // 挑 + 0x6319, KANJI_LEARNING_ORDER_4, // 挙 + 0x631F, KANJI_LEARNING_ORDER_7, // 挟 + 0x632F, KANJI_LEARNING_ORDER_7, // 振 + 0x633F, KANJI_LEARNING_ORDER_7, // 挿 + 0x6355, KANJI_LEARNING_ORDER_7, // 捕 + 0x635C, KANJI_LEARNING_ORDER_7, // 捜 + 0x6368, KANJI_LEARNING_ORDER_6, // 捚 + 0x636E, KANJI_LEARNING_ORDER_7, // 据 + 0x6383, KANJI_LEARNING_ORDER_7, // 掃 + 0x6388, KANJI_LEARNING_ORDER_5, // 授 + 0x638C, KANJI_LEARNING_ORDER_7, // 掌 + 0x6392, KANJI_LEARNING_ORDER_7, // 排 + 0x6398, KANJI_LEARNING_ORDER_7, // 掘 + 0x639B, KANJI_LEARNING_ORDER_7, // 掛 + 0x63A1, KANJI_LEARNING_ORDER_5, // 採 + 0x63A2, KANJI_LEARNING_ORDER_6, // 探 + 0x63A5, KANJI_LEARNING_ORDER_5, // 接 + 0x63A7, KANJI_LEARNING_ORDER_7, // 控 + 0x63A8, KANJI_LEARNING_ORDER_6, // 掚 + 0x63AA, KANJI_LEARNING_ORDER_7, // 措 + 0x63B2, KANJI_LEARNING_ORDER_7, // 掲 + 0x63CF, KANJI_LEARNING_ORDER_7, // 描 + 0x63D0, KANJI_LEARNING_ORDER_5, // 提 + 0x63DA, KANJI_LEARNING_ORDER_7, // 揚 + 0x63DB, KANJI_LEARNING_ORDER_7, // 換 + 0x63E1, KANJI_LEARNING_ORDER_7, // 握 + 0x63EE, KANJI_LEARNING_ORDER_6, // 揮 + 0x63F4, KANJI_LEARNING_ORDER_7, // 揎 + 0x63FA, KANJI_LEARNING_ORDER_7, // 揺 + 0x640D, KANJI_LEARNING_ORDER_5, // 損 + 0x642C, KANJI_LEARNING_ORDER_7, // 搬 + 0x642D, KANJI_LEARNING_ORDER_7, // 搭 + 0x643A, KANJI_LEARNING_ORDER_7, // 携 + 0x643E, KANJI_LEARNING_ORDER_7, // 搟 + 0x6442, KANJI_LEARNING_ORDER_7, // 摂 + 0x6458, KANJI_LEARNING_ORDER_7, // 摘 + 0x6469, KANJI_LEARNING_ORDER_7, // 摩 + 0x6483, KANJI_LEARNING_ORDER_7, // 撃 + 0x64A4, KANJI_LEARNING_ORDER_7, // æ’€ + 0x64AE, KANJI_LEARNING_ORDER_7, // 撮 + 0x64B2, KANJI_LEARNING_ORDER_7, // 撲 + 0x64C1, KANJI_LEARNING_ORDER_7, // 擁 + 0x64CD, KANJI_LEARNING_ORDER_6, // 操 + 0x64E6, KANJI_LEARNING_ORDER_7, // 擊 + 0x64EC, KANJI_LEARNING_ORDER_7, // 擬 + 0x652F, KANJI_LEARNING_ORDER_5, // 支 + 0x6539, KANJI_LEARNING_ORDER_4, // 改 + 0x653B, KANJI_LEARNING_ORDER_7, // 攻 + 0x653E, KANJI_LEARNING_ORDER_3, // 攟 + 0x653F, KANJI_LEARNING_ORDER_5, // 政 + 0x6545, KANJI_LEARNING_ORDER_5, // 故 + 0x654F, KANJI_LEARNING_ORDER_7, // 敏 + 0x6551, KANJI_LEARNING_ORDER_4, // 救 + 0x6557, KANJI_LEARNING_ORDER_4, // 敗 + 0x6559, KANJI_LEARNING_ORDER_2, // 教 + 0x6562, KANJI_LEARNING_ORDER_7, // 敢 + 0x6563, KANJI_LEARNING_ORDER_4, // 散 + 0x656C, KANJI_LEARNING_ORDER_6, // 敬 + 0x6570, KANJI_LEARNING_ORDER_2, // 数 + 0x6574, KANJI_LEARNING_ORDER_3, // 敎 + 0x6575, KANJI_LEARNING_ORDER_5, // 敵 + 0x6577, KANJI_LEARNING_ORDER_7, // 敷 + 0x6587, KANJI_LEARNING_ORDER_1, // 文 + 0x6589, KANJI_LEARNING_ORDER_7, // 斉 + 0x658E, KANJI_LEARNING_ORDER_7, // 斎 + 0x6597, KANJI_LEARNING_ORDER_7, // 斗 + 0x6599, KANJI_LEARNING_ORDER_4, // 料 + 0x659C, KANJI_LEARNING_ORDER_7, // 斜 + 0x65A4, KANJI_LEARNING_ORDER_7, // æ–€ + 0x65A5, KANJI_LEARNING_ORDER_7, // 斥 + 0x65AD, KANJI_LEARNING_ORDER_5, // 断 + 0x65B0, KANJI_LEARNING_ORDER_2, // 新 + 0x65B9, KANJI_LEARNING_ORDER_2, // 方 + 0x65BD, KANJI_LEARNING_ORDER_7, // æ–œ + 0x65C5, KANJI_LEARNING_ORDER_3, // 旅 + 0x65CB, KANJI_LEARNING_ORDER_7, // 旋 + 0x65CF, KANJI_LEARNING_ORDER_3, // 族 + 0x65D7, KANJI_LEARNING_ORDER_4, // 旗 + 0x65E2, KANJI_LEARNING_ORDER_7, // 既 + 0x65E5, KANJI_LEARNING_ORDER_1, // 日 + 0x65E7, KANJI_LEARNING_ORDER_5, // 旧 + 0x65E8, KANJI_LEARNING_ORDER_7, // æ—š + 0x65E9, KANJI_LEARNING_ORDER_1, // 早 + 0x65EC, KANJI_LEARNING_ORDER_7, // 旬 + 0x6606, KANJI_LEARNING_ORDER_7, // 昆 + 0x6607, KANJI_LEARNING_ORDER_7, // 昇 + 0x660E, KANJI_LEARNING_ORDER_2, // 明 + 0x6613, KANJI_LEARNING_ORDER_5, // 易 + 0x6614, KANJI_LEARNING_ORDER_3, // 昔 + 0x661F, KANJI_LEARNING_ORDER_2, // 星 + 0x6620, KANJI_LEARNING_ORDER_6, // 映 + 0x6625, KANJI_LEARNING_ORDER_2, // 春 + 0x6628, KANJI_LEARNING_ORDER_4, // 昚 + 0x662D, KANJI_LEARNING_ORDER_3, // 昭 + 0x662F, KANJI_LEARNING_ORDER_7, // 是 + 0x663C, KANJI_LEARNING_ORDER_2, // 昌 + 0x6642, KANJI_LEARNING_ORDER_2, // 時 + 0x6669, KANJI_LEARNING_ORDER_6, // 晩 + 0x666E, KANJI_LEARNING_ORDER_7, // 普 + 0x666F, KANJI_LEARNING_ORDER_4, // 景 + 0x6674, KANJI_LEARNING_ORDER_2, // 晎 + 0x6676, KANJI_LEARNING_ORDER_7, // 晶 + 0x6681, KANJI_LEARNING_ORDER_7, // 暁 + 0x6687, KANJI_LEARNING_ORDER_7, // 暇 + 0x6691, KANJI_LEARNING_ORDER_3, // 暑 + 0x6696, KANJI_LEARNING_ORDER_6, // 暖 + 0x6697, KANJI_LEARNING_ORDER_3, // 暗 + 0x66A6, KANJI_LEARNING_ORDER_7, // 暊 + 0x66AB, KANJI_LEARNING_ORDER_7, // 暫 + 0x66AE, KANJI_LEARNING_ORDER_6, // 暮 + 0x66B4, KANJI_LEARNING_ORDER_5, // 暎 + 0x66C7, KANJI_LEARNING_ORDER_7, // 曇 + 0x66DC, KANJI_LEARNING_ORDER_2, // 曜 + 0x66F2, KANJI_LEARNING_ORDER_3, // 曲 + 0x66F4, KANJI_LEARNING_ORDER_7, // 曎 + 0x66F8, KANJI_LEARNING_ORDER_2, // 曞 + 0x66F9, KANJI_LEARNING_ORDER_7, // 曹 + 0x66FF, KANJI_LEARNING_ORDER_7, // 替 + 0x6700, KANJI_LEARNING_ORDER_4, // 最 + 0x6708, KANJI_LEARNING_ORDER_1, // 月 + 0x6709, KANJI_LEARNING_ORDER_3, // 有 + 0x670D, KANJI_LEARNING_ORDER_3, // 服 + 0x6715, KANJI_LEARNING_ORDER_7, // 朕 + 0x6717, KANJI_LEARNING_ORDER_6, // 朗 + 0x671B, KANJI_LEARNING_ORDER_4, // 望 + 0x671D, KANJI_LEARNING_ORDER_2, // 朝 + 0x671F, KANJI_LEARNING_ORDER_3, // 期 + 0x6728, KANJI_LEARNING_ORDER_1, // 朚 + 0x672A, KANJI_LEARNING_ORDER_4, // 未 + 0x672B, KANJI_LEARNING_ORDER_4, // 末 + 0x672C, KANJI_LEARNING_ORDER_1, // 本 + 0x672D, KANJI_LEARNING_ORDER_4, // 札 + 0x6731, KANJI_LEARNING_ORDER_7, // 朱 + 0x6734, KANJI_LEARNING_ORDER_7, // 朎 + 0x673A, KANJI_LEARNING_ORDER_6, // 机 + 0x673D, KANJI_LEARNING_ORDER_7, // 朜 + 0x6749, KANJI_LEARNING_ORDER_7, // 杉 + 0x6750, KANJI_LEARNING_ORDER_4, // 材 + 0x6751, KANJI_LEARNING_ORDER_1, // 村 + 0x675F, KANJI_LEARNING_ORDER_4, // 束 + 0x6761, KANJI_LEARNING_ORDER_5, // 条 + 0x6765, KANJI_LEARNING_ORDER_2, // 来 + 0x676F, KANJI_LEARNING_ORDER_7, // 杯 + 0x6771, KANJI_LEARNING_ORDER_2, // 東 + 0x677E, KANJI_LEARNING_ORDER_4, // 束 + 0x677F, KANJI_LEARNING_ORDER_3, // 板 + 0x6790, KANJI_LEARNING_ORDER_7, // 析 + 0x6797, KANJI_LEARNING_ORDER_1, // 林 + 0x679A, KANJI_LEARNING_ORDER_6, // 枚 + 0x679C, KANJI_LEARNING_ORDER_4, // 果 + 0x679D, KANJI_LEARNING_ORDER_5, // 枝 + 0x67A0, KANJI_LEARNING_ORDER_7, // 枠 + 0x67A2, KANJI_LEARNING_ORDER_7, // 枢 + 0x67AF, KANJI_LEARNING_ORDER_7, // 枯 + 0x67B6, KANJI_LEARNING_ORDER_7, // 架 + 0x67C4, KANJI_LEARNING_ORDER_7, // 柄 + 0x67D0, KANJI_LEARNING_ORDER_7, // 某 + 0x67D3, KANJI_LEARNING_ORDER_6, // 染 + 0x67D4, KANJI_LEARNING_ORDER_7, // 柔 + 0x67F1, KANJI_LEARNING_ORDER_3, // 柱 + 0x67F3, KANJI_LEARNING_ORDER_7, // 柳 + 0x67FB, KANJI_LEARNING_ORDER_5, // 査 + 0x6804, KANJI_LEARNING_ORDER_4, // 栄 + 0x6813, KANJI_LEARNING_ORDER_7, // 栓 + 0x6821, KANJI_LEARNING_ORDER_1, // æ ¡ + 0x682A, KANJI_LEARNING_ORDER_6, // æ ª + 0x6838, KANJI_LEARNING_ORDER_7, // æ ž + 0x6839, KANJI_LEARNING_ORDER_3, // æ ¹ + 0x683C, KANJI_LEARNING_ORDER_5, // æ Œ + 0x683D, KANJI_LEARNING_ORDER_7, // æ œ + 0x6843, KANJI_LEARNING_ORDER_7, // 桃 + 0x6848, KANJI_LEARNING_ORDER_4, // 案 + 0x6851, KANJI_LEARNING_ORDER_7, // 桑 + 0x685C, KANJI_LEARNING_ORDER_5, // 桜 + 0x685F, KANJI_LEARNING_ORDER_7, // 桟 + 0x6885, KANJI_LEARNING_ORDER_4, // 梅 + 0x68B0, KANJI_LEARNING_ORDER_4, // 械 + 0x68C4, KANJI_LEARNING_ORDER_7, // 棄 + 0x68CB, KANJI_LEARNING_ORDER_7, // 棋 + 0x68D2, KANJI_LEARNING_ORDER_6, // 棒 + 0x68DA, KANJI_LEARNING_ORDER_7, // 棚 + 0x68DF, KANJI_LEARNING_ORDER_7, // 棟 + 0x68EE, KANJI_LEARNING_ORDER_1, // 森 + 0x68FA, KANJI_LEARNING_ORDER_7, // 棺 + 0x690D, KANJI_LEARNING_ORDER_3, // 怍 + 0x691C, KANJI_LEARNING_ORDER_5, // 怜 + 0x696D, KANJI_LEARNING_ORDER_3, // 業 + 0x6975, KANJI_LEARNING_ORDER_4, // 極 + 0x697C, KANJI_LEARNING_ORDER_7, // 楌 + 0x697D, KANJI_LEARNING_ORDER_2, // 楜 + 0x6982, KANJI_LEARNING_ORDER_7, // 抂 + 0x69CB, KANJI_LEARNING_ORDER_5, // 構 + 0x69D8, KANJI_LEARNING_ORDER_3, // 様 + 0x69FD, KANJI_LEARNING_ORDER_7, // æ§œ + 0x6A19, KANJI_LEARNING_ORDER_4, // æš™ + 0x6A21, KANJI_LEARNING_ORDER_6, // æš¡ + 0x6A29, KANJI_LEARNING_ORDER_6, // æš© + 0x6A2A, KANJI_LEARNING_ORDER_3, // 暪 + 0x6A39, KANJI_LEARNING_ORDER_6, // æš¹ + 0x6A4B, KANJI_LEARNING_ORDER_3, // 橋 + 0x6A5F, KANJI_LEARNING_ORDER_4, // 機 + 0x6B04, KANJI_LEARNING_ORDER_7, // 欄 + 0x6B20, KANJI_LEARNING_ORDER_4, // 欠 + 0x6B21, KANJI_LEARNING_ORDER_3, // 次 + 0x6B27, KANJI_LEARNING_ORDER_7, // 欧 + 0x6B32, KANJI_LEARNING_ORDER_6, // 欲 + 0x6B3A, KANJI_LEARNING_ORDER_7, // 欺 + 0x6B3E, KANJI_LEARNING_ORDER_7, // 欟 + 0x6B4C, KANJI_LEARNING_ORDER_2, // 歌 + 0x6B53, KANJI_LEARNING_ORDER_7, // 歓 + 0x6B62, KANJI_LEARNING_ORDER_2, // æ­¢ + 0x6B63, KANJI_LEARNING_ORDER_1, // æ­£ + 0x6B66, KANJI_LEARNING_ORDER_5, // æ­Š + 0x6B69, KANJI_LEARNING_ORDER_2, // æ­© + 0x6B6F, KANJI_LEARNING_ORDER_3, // æ­¯ + 0x6B73, KANJI_LEARNING_ORDER_7, // æ­³ + 0x6B74, KANJI_LEARNING_ORDER_4, // æ­Ž + 0x6B7B, KANJI_LEARNING_ORDER_3, // æ­» + 0x6B89, KANJI_LEARNING_ORDER_7, // 殉 + 0x6B8A, KANJI_LEARNING_ORDER_7, // 殊 + 0x6B8B, KANJI_LEARNING_ORDER_4, // 残 + 0x6B96, KANJI_LEARNING_ORDER_7, // 殖 + 0x6BB4, KANJI_LEARNING_ORDER_7, // 殎 + 0x6BB5, KANJI_LEARNING_ORDER_6, // 段 + 0x6BBA, KANJI_LEARNING_ORDER_4, // 殺 + 0x6BBB, KANJI_LEARNING_ORDER_7, // æ®» + 0x6BBF, KANJI_LEARNING_ORDER_7, // 殿 + 0x6BCD, KANJI_LEARNING_ORDER_2, // 母 + 0x6BCE, KANJI_LEARNING_ORDER_2, // 毎 + 0x6BD2, KANJI_LEARNING_ORDER_4, // 毒 + 0x6BD4, KANJI_LEARNING_ORDER_5, // 比 + 0x6BDB, KANJI_LEARNING_ORDER_2, // 毛 + 0x6C0F, KANJI_LEARNING_ORDER_4, // 氏 + 0x6C11, KANJI_LEARNING_ORDER_4, // 民 + 0x6C17, KANJI_LEARNING_ORDER_1, // 気 + 0x6C34, KANJI_LEARNING_ORDER_1, // æ°Ž + 0x6C37, KANJI_LEARNING_ORDER_3, // æ°· + 0x6C38, KANJI_LEARNING_ORDER_5, // æ°ž + 0x6C41, KANJI_LEARNING_ORDER_7, // 汁 + 0x6C42, KANJI_LEARNING_ORDER_4, // 求 + 0x6C57, KANJI_LEARNING_ORDER_7, // 汗 + 0x6C5A, KANJI_LEARNING_ORDER_7, // 汚 + 0x6C5F, KANJI_LEARNING_ORDER_7, // 江 + 0x6C60, KANJI_LEARNING_ORDER_2, // æ±  + 0x6C7A, KANJI_LEARNING_ORDER_3, // 決 + 0x6C7D, KANJI_LEARNING_ORDER_2, // 汜 + 0x6C88, KANJI_LEARNING_ORDER_7, // 沈 + 0x6C96, KANJI_LEARNING_ORDER_7, // 沖 + 0x6CA1, KANJI_LEARNING_ORDER_7, // 没 + 0x6CA2, KANJI_LEARNING_ORDER_7, // æ²¢ + 0x6CB3, KANJI_LEARNING_ORDER_5, // æ²³ + 0x6CB8, KANJI_LEARNING_ORDER_7, // 沞 + 0x6CB9, KANJI_LEARNING_ORDER_3, // æ²¹ + 0x6CBB, KANJI_LEARNING_ORDER_4, // æ²» + 0x6CBC, KANJI_LEARNING_ORDER_7, // 沌 + 0x6CBF, KANJI_LEARNING_ORDER_6, // 沿 + 0x6CC1, KANJI_LEARNING_ORDER_7, // 況 + 0x6CC9, KANJI_LEARNING_ORDER_6, // 泉 + 0x6CCA, KANJI_LEARNING_ORDER_7, // 泊 + 0x6CCC, KANJI_LEARNING_ORDER_7, // 泌 + 0x6CD5, KANJI_LEARNING_ORDER_4, // 法 + 0x6CE1, KANJI_LEARNING_ORDER_7, // 泡 + 0x6CE2, KANJI_LEARNING_ORDER_3, // æ³¢ + 0x6CE3, KANJI_LEARNING_ORDER_4, // æ³£ + 0x6CE5, KANJI_LEARNING_ORDER_7, // æ³¥ + 0x6CE8, KANJI_LEARNING_ORDER_3, // 泚 + 0x6CF0, KANJI_LEARNING_ORDER_7, // æ³° + 0x6CF3, KANJI_LEARNING_ORDER_3, // æ³³ + 0x6D0B, KANJI_LEARNING_ORDER_3, // 掋 + 0x6D17, KANJI_LEARNING_ORDER_6, // 掗 + 0x6D1E, KANJI_LEARNING_ORDER_7, // 掞 + 0x6D25, KANJI_LEARNING_ORDER_7, // 接 + 0x6D2A, KANJI_LEARNING_ORDER_7, // 措 + 0x6D3B, KANJI_LEARNING_ORDER_2, // 掻 + 0x6D3E, KANJI_LEARNING_ORDER_6, // 掟 + 0x6D41, KANJI_LEARNING_ORDER_3, // 流 + 0x6D44, KANJI_LEARNING_ORDER_7, // 浄 + 0x6D45, KANJI_LEARNING_ORDER_4, // 浅 + 0x6D5C, KANJI_LEARNING_ORDER_7, // 浜 + 0x6D66, KANJI_LEARNING_ORDER_7, // 浊 + 0x6D6A, KANJI_LEARNING_ORDER_7, // 浪 + 0x6D6E, KANJI_LEARNING_ORDER_7, // æµ® + 0x6D74, KANJI_LEARNING_ORDER_4, // 济 + 0x6D77, KANJI_LEARNING_ORDER_2, // æµ· + 0x6D78, KANJI_LEARNING_ORDER_7, // 浞 + 0x6D88, KANJI_LEARNING_ORDER_3, // 消 + 0x6D99, KANJI_LEARNING_ORDER_7, // 涙 + 0x6DAF, KANJI_LEARNING_ORDER_7, // 涯 + 0x6DB2, KANJI_LEARNING_ORDER_5, // æ¶² + 0x6DBC, KANJI_LEARNING_ORDER_7, // æ¶Œ + 0x6DD1, KANJI_LEARNING_ORDER_7, // 淑 + 0x6DE1, KANJI_LEARNING_ORDER_7, // æ·¡ + 0x6DF1, KANJI_LEARNING_ORDER_3, // æ·± + 0x6DF7, KANJI_LEARNING_ORDER_5, // æ·· + 0x6DFB, KANJI_LEARNING_ORDER_7, // æ·» + 0x6E05, KANJI_LEARNING_ORDER_4, // æž… + 0x6E07, KANJI_LEARNING_ORDER_7, // 枇 + 0x6E08, KANJI_LEARNING_ORDER_6, // 枈 + 0x6E09, KANJI_LEARNING_ORDER_7, // 枉 + 0x6E0B, KANJI_LEARNING_ORDER_7, // æž‹ + 0x6E13, KANJI_LEARNING_ORDER_7, // æž“ + 0x6E1B, KANJI_LEARNING_ORDER_5, // æž› + 0x6E21, KANJI_LEARNING_ORDER_7, // æž¡ + 0x6E26, KANJI_LEARNING_ORDER_7, // 枊 + 0x6E29, KANJI_LEARNING_ORDER_3, // æž© + 0x6E2C, KANJI_LEARNING_ORDER_5, // 枬 + 0x6E2F, KANJI_LEARNING_ORDER_3, // 枯 + 0x6E56, KANJI_LEARNING_ORDER_3, // 湖 + 0x6E6F, KANJI_LEARNING_ORDER_3, // 湯 + 0x6E7E, KANJI_LEARNING_ORDER_7, // 湟 + 0x6E7F, KANJI_LEARNING_ORDER_7, // 湿 + 0x6E80, KANJI_LEARNING_ORDER_4, // 満 + 0x6E90, KANJI_LEARNING_ORDER_6, // 源 + 0x6E96, KANJI_LEARNING_ORDER_5, // 準 + 0x6E9D, KANJI_LEARNING_ORDER_7, // 溝 + 0x6EB6, KANJI_LEARNING_ORDER_7, // 溶 + 0x6EC5, KANJI_LEARNING_ORDER_7, // 滅 + 0x6ECB, KANJI_LEARNING_ORDER_7, // 滋 + 0x6ED1, KANJI_LEARNING_ORDER_7, // 滑 + 0x6EDD, KANJI_LEARNING_ORDER_7, // 滝 + 0x6EDE, KANJI_LEARNING_ORDER_7, // 滞 + 0x6EF4, KANJI_LEARNING_ORDER_7, // 滎 + 0x6F01, KANJI_LEARNING_ORDER_4, // 持 + 0x6F02, KANJI_LEARNING_ORDER_7, // 挂 + 0x6F06, KANJI_LEARNING_ORDER_7, // 挆 + 0x6F0F, KANJI_LEARNING_ORDER_7, // 挏 + 0x6F14, KANJI_LEARNING_ORDER_5, // 挔 + 0x6F20, KANJI_LEARNING_ORDER_7, // 挠 + 0x6F22, KANJI_LEARNING_ORDER_3, // 挢 + 0x6F2B, KANJI_LEARNING_ORDER_7, // 挫 + 0x6F2C, KANJI_LEARNING_ORDER_7, // 挬 + 0x6F38, KANJI_LEARNING_ORDER_7, // 挞 + 0x6F54, KANJI_LEARNING_ORDER_5, // 朔 + 0x6F5C, KANJI_LEARNING_ORDER_7, // 朜 + 0x6F5F, KANJI_LEARNING_ORDER_7, // 期 + 0x6F64, KANJI_LEARNING_ORDER_7, // 最 + 0x6F6E, KANJI_LEARNING_ORDER_6, // 朮 + 0x6F84, KANJI_LEARNING_ORDER_7, // 柄 + 0x6FC0, KANJI_LEARNING_ORDER_6, // 激 + 0x6FC1, KANJI_LEARNING_ORDER_7, // 濁 + 0x6FC3, KANJI_LEARNING_ORDER_7, // 濃 + 0x6FEB, KANJI_LEARNING_ORDER_7, // æ¿« + 0x6FEF, KANJI_LEARNING_ORDER_7, // 濯 + 0x702C, KANJI_LEARNING_ORDER_7, // 瀬 + 0x706B, KANJI_LEARNING_ORDER_1, // 火 + 0x706F, KANJI_LEARNING_ORDER_4, // 灯 + 0x7070, KANJI_LEARNING_ORDER_6, // 灰 + 0x707D, KANJI_LEARNING_ORDER_5, // 灜 + 0x7089, KANJI_LEARNING_ORDER_7, // 炉 + 0x708A, KANJI_LEARNING_ORDER_7, // 炊 + 0x708E, KANJI_LEARNING_ORDER_7, // 炎 + 0x70AD, KANJI_LEARNING_ORDER_3, // 炭 + 0x70B9, KANJI_LEARNING_ORDER_2, // 点 + 0x70BA, KANJI_LEARNING_ORDER_7, // 為 + 0x70C8, KANJI_LEARNING_ORDER_7, // 烈 + 0x7121, KANJI_LEARNING_ORDER_4, // 無 + 0x7126, KANJI_LEARNING_ORDER_7, // 焩 + 0x7136, KANJI_LEARNING_ORDER_4, // 然 + 0x713C, KANJI_LEARNING_ORDER_4, // 焌 + 0x7159, KANJI_LEARNING_ORDER_7, // 煙 + 0x7167, KANJI_LEARNING_ORDER_4, // 照 + 0x7169, KANJI_LEARNING_ORDER_7, // 煩 + 0x716E, KANJI_LEARNING_ORDER_7, // 煮 + 0x719F, KANJI_LEARNING_ORDER_6, // 熟 + 0x71B1, KANJI_LEARNING_ORDER_4, // 熱 + 0x71C3, KANJI_LEARNING_ORDER_5, // 燃 + 0x71C8, KANJI_LEARNING_ORDER_7, // 燈 + 0x71E5, KANJI_LEARNING_ORDER_7, // 燥 + 0x7206, KANJI_LEARNING_ORDER_7, // 爆 + 0x7235, KANJI_LEARNING_ORDER_7, // 爵 + 0x7236, KANJI_LEARNING_ORDER_2, // 父 + 0x7247, KANJI_LEARNING_ORDER_6, // 片 + 0x7248, KANJI_LEARNING_ORDER_5, // 版 + 0x725B, KANJI_LEARNING_ORDER_2, // 牛 + 0x7267, KANJI_LEARNING_ORDER_4, // 牧 + 0x7269, KANJI_LEARNING_ORDER_3, // 物 + 0x7272, KANJI_LEARNING_ORDER_7, // 牲 + 0x7279, KANJI_LEARNING_ORDER_4, // 特 + 0x72A0, KANJI_LEARNING_ORDER_7, // 犠 + 0x72AC, KANJI_LEARNING_ORDER_1, // 犬 + 0x72AF, KANJI_LEARNING_ORDER_5, // 犯 + 0x72B6, KANJI_LEARNING_ORDER_5, // 状 + 0x72C2, KANJI_LEARNING_ORDER_7, // 狂 + 0x72E9, KANJI_LEARNING_ORDER_7, // 狩 + 0x72EC, KANJI_LEARNING_ORDER_5, // 独 + 0x72ED, KANJI_LEARNING_ORDER_7, // 狭 + 0x731B, KANJI_LEARNING_ORDER_7, // 猛 + 0x731F, KANJI_LEARNING_ORDER_7, // 猟 + 0x732B, KANJI_LEARNING_ORDER_7, // 猫 + 0x732E, KANJI_LEARNING_ORDER_7, // 献 + 0x7336, KANJI_LEARNING_ORDER_7, // 猶 + 0x733F, KANJI_LEARNING_ORDER_7, // 猿 + 0x7344, KANJI_LEARNING_ORDER_7, // 獄 + 0x7363, KANJI_LEARNING_ORDER_7, // 獣 + 0x7372, KANJI_LEARNING_ORDER_7, // 獲 + 0x7384, KANJI_LEARNING_ORDER_7, // 玄 + 0x7387, KANJI_LEARNING_ORDER_5, // 率 + 0x7389, KANJI_LEARNING_ORDER_1, // 玉 + 0x738B, KANJI_LEARNING_ORDER_1, // 王 + 0x73CD, KANJI_LEARNING_ORDER_7, // 珍 + 0x73E0, KANJI_LEARNING_ORDER_7, // 珠 + 0x73ED, KANJI_LEARNING_ORDER_6, // 班 + 0x73FE, KANJI_LEARNING_ORDER_5, // 珟 + 0x7403, KANJI_LEARNING_ORDER_3, // 球 + 0x7406, KANJI_LEARNING_ORDER_2, // 理 + 0x7434, KANJI_LEARNING_ORDER_7, // 琎 + 0x74B0, KANJI_LEARNING_ORDER_7, // 環 + 0x74BD, KANJI_LEARNING_ORDER_7, // ç’œ + 0x74F6, KANJI_LEARNING_ORDER_7, // 瓶 + 0x7518, KANJI_LEARNING_ORDER_7, // 甘 + 0x751A, KANJI_LEARNING_ORDER_7, // 甚 + 0x751F, KANJI_LEARNING_ORDER_1, // 生 + 0x7523, KANJI_LEARNING_ORDER_4, // 産 + 0x7528, KANJI_LEARNING_ORDER_2, // 甹 + 0x7530, KANJI_LEARNING_ORDER_1, // 田 + 0x7531, KANJI_LEARNING_ORDER_3, // 由 + 0x7532, KANJI_LEARNING_ORDER_7, // 甲 + 0x7533, KANJI_LEARNING_ORDER_3, // 申 + 0x7537, KANJI_LEARNING_ORDER_1, // 男 + 0x753A, KANJI_LEARNING_ORDER_1, // 町 + 0x753B, KANJI_LEARNING_ORDER_2, // 画 + 0x754C, KANJI_LEARNING_ORDER_3, // 界 + 0x7551, KANJI_LEARNING_ORDER_3, // 畑 + 0x7554, KANJI_LEARNING_ORDER_7, // 畔 + 0x7559, KANJI_LEARNING_ORDER_5, // 留 + 0x755C, KANJI_LEARNING_ORDER_7, // 畜 + 0x755D, KANJI_LEARNING_ORDER_7, // 畝 + 0x7565, KANJI_LEARNING_ORDER_5, // 略 + 0x756A, KANJI_LEARNING_ORDER_2, // 番 + 0x7570, KANJI_LEARNING_ORDER_6, // 異 + 0x7573, KANJI_LEARNING_ORDER_7, // 畳 + 0x758E, KANJI_LEARNING_ORDER_7, // 疎 + 0x7591, KANJI_LEARNING_ORDER_6, // 疑 + 0x75AB, KANJI_LEARNING_ORDER_7, // 疫 + 0x75B2, KANJI_LEARNING_ORDER_7, // 疲 + 0x75BE, KANJI_LEARNING_ORDER_7, // ç–Ÿ + 0x75C5, KANJI_LEARNING_ORDER_3, // 病 + 0x75C7, KANJI_LEARNING_ORDER_7, // 症 + 0x75D8, KANJI_LEARNING_ORDER_7, // 痘 + 0x75DB, KANJI_LEARNING_ORDER_6, // 痛 + 0x75E2, KANJI_LEARNING_ORDER_7, // 痢 + 0x75F4, KANJI_LEARNING_ORDER_7, // 痮 + 0x7642, KANJI_LEARNING_ORDER_7, // 療 + 0x7652, KANJI_LEARNING_ORDER_7, // 癒 + 0x7656, KANJI_LEARNING_ORDER_7, // 癖 + 0x767A, KANJI_LEARNING_ORDER_3, // 発 + 0x767B, KANJI_LEARNING_ORDER_3, // 登 + 0x767D, KANJI_LEARNING_ORDER_1, // 癜 + 0x767E, KANJI_LEARNING_ORDER_1, // 癟 + 0x7684, KANJI_LEARNING_ORDER_4, // 的 + 0x7686, KANJI_LEARNING_ORDER_7, // 皆 + 0x7687, KANJI_LEARNING_ORDER_6, // 皇 + 0x76AE, KANJI_LEARNING_ORDER_3, // 皮 + 0x76BF, KANJI_LEARNING_ORDER_3, // 皿 + 0x76C6, KANJI_LEARNING_ORDER_7, // 盆 + 0x76CA, KANJI_LEARNING_ORDER_5, // 益 + 0x76D7, KANJI_LEARNING_ORDER_7, // 盗 + 0x76DB, KANJI_LEARNING_ORDER_6, // 盛 + 0x76DF, KANJI_LEARNING_ORDER_6, // 盟 + 0x76E3, KANJI_LEARNING_ORDER_7, // 監 + 0x76E4, KANJI_LEARNING_ORDER_7, // 盀 + 0x76EE, KANJI_LEARNING_ORDER_1, // 目 + 0x76F2, KANJI_LEARNING_ORDER_7, // 盲 + 0x76F4, KANJI_LEARNING_ORDER_2, // 目 + 0x76F8, KANJI_LEARNING_ORDER_3, // 盾 + 0x76FE, KANJI_LEARNING_ORDER_7, // 盟 + 0x7701, KANJI_LEARNING_ORDER_4, // 省 + 0x770B, KANJI_LEARNING_ORDER_6, // 看 + 0x770C, KANJI_LEARNING_ORDER_3, // 県 + 0x771F, KANJI_LEARNING_ORDER_3, // 真 + 0x7720, KANJI_LEARNING_ORDER_7, // 眠 + 0x773A, KANJI_LEARNING_ORDER_7, // 眺 + 0x773C, KANJI_LEARNING_ORDER_5, // 県 + 0x7740, KANJI_LEARNING_ORDER_3, // 着 + 0x7761, KANJI_LEARNING_ORDER_7, // 睡 + 0x7763, KANJI_LEARNING_ORDER_7, // 督 + 0x77AC, KANJI_LEARNING_ORDER_7, // 瞬 + 0x77DB, KANJI_LEARNING_ORDER_7, // 矛 + 0x77E2, KANJI_LEARNING_ORDER_2, // 矢 + 0x77E5, KANJI_LEARNING_ORDER_2, // 知 + 0x77ED, KANJI_LEARNING_ORDER_3, // 短 + 0x77EF, KANJI_LEARNING_ORDER_7, // 矯 + 0x77F3, KANJI_LEARNING_ORDER_1, // 石 + 0x7802, KANJI_LEARNING_ORDER_6, // 砂 + 0x7814, KANJI_LEARNING_ORDER_3, // 研 + 0x7815, KANJI_LEARNING_ORDER_7, // 砕 + 0x7832, KANJI_LEARNING_ORDER_7, // ç ² + 0x7834, KANJI_LEARNING_ORDER_5, // ç Ž + 0x785D, KANJI_LEARNING_ORDER_7, // 硝 + 0x786B, KANJI_LEARNING_ORDER_7, // ç¡« + 0x786C, KANJI_LEARNING_ORDER_7, // 硬 + 0x7881, KANJI_LEARNING_ORDER_7, // 碁 + 0x7891, KANJI_LEARNING_ORDER_7, // 碑 + 0x78BA, KANJI_LEARNING_ORDER_5, // 確 + 0x78C1, KANJI_LEARNING_ORDER_6, // 磁 + 0x78E8, KANJI_LEARNING_ORDER_7, // 磚 + 0x7901, KANJI_LEARNING_ORDER_7, // 瀁 + 0x790E, KANJI_LEARNING_ORDER_7, // 瀎 + 0x793A, KANJI_LEARNING_ORDER_5, // 瀺 + 0x793C, KANJI_LEARNING_ORDER_3, // 瀌 + 0x793E, KANJI_LEARNING_ORDER_2, // 瀟 + 0x7948, KANJI_LEARNING_ORDER_7, // 祈 + 0x7949, KANJI_LEARNING_ORDER_7, // 祉 + 0x7956, KANJI_LEARNING_ORDER_5, // 祖 + 0x795D, KANJI_LEARNING_ORDER_4, // 祝 + 0x795E, KANJI_LEARNING_ORDER_3, // 神 + 0x7965, KANJI_LEARNING_ORDER_7, // 祥 + 0x7968, KANJI_LEARNING_ORDER_4, // 祚 + 0x796D, KANJI_LEARNING_ORDER_3, // 祭 + 0x7981, KANJI_LEARNING_ORDER_5, // 犁 + 0x7985, KANJI_LEARNING_ORDER_7, // 穅 + 0x798D, KANJI_LEARNING_ORDER_7, // 犍 + 0x798F, KANJI_LEARNING_ORDER_3, // 犏 + 0x79C0, KANJI_LEARNING_ORDER_7, // 秀 + 0x79C1, KANJI_LEARNING_ORDER_6, // 私 + 0x79CB, KANJI_LEARNING_ORDER_2, // 秋 + 0x79D1, KANJI_LEARNING_ORDER_2, // 科 + 0x79D2, KANJI_LEARNING_ORDER_3, // 秒 + 0x79D8, KANJI_LEARNING_ORDER_6, // 秘 + 0x79DF, KANJI_LEARNING_ORDER_7, // 租 + 0x79E9, KANJI_LEARNING_ORDER_7, // ç§© + 0x79F0, KANJI_LEARNING_ORDER_7, // ç§° + 0x79FB, KANJI_LEARNING_ORDER_5, // ç§» + 0x7A0B, KANJI_LEARNING_ORDER_5, // 繋 + 0x7A0E, KANJI_LEARNING_ORDER_5, // 皎 + 0x7A1A, KANJI_LEARNING_ORDER_7, // 繚 + 0x7A2E, KANJI_LEARNING_ORDER_4, // çš® + 0x7A32, KANJI_LEARNING_ORDER_7, // çš² + 0x7A3C, KANJI_LEARNING_ORDER_7, // 皌 + 0x7A3F, KANJI_LEARNING_ORDER_7, // çš¿ + 0x7A40, KANJI_LEARNING_ORDER_6, // 穀 + 0x7A42, KANJI_LEARNING_ORDER_7, // 穂 + 0x7A4D, KANJI_LEARNING_ORDER_4, // 積 + 0x7A4F, KANJI_LEARNING_ORDER_7, // 穏 + 0x7A6B, KANJI_LEARNING_ORDER_7, // ç©« + 0x7A74, KANJI_LEARNING_ORDER_6, // 穎 + 0x7A76, KANJI_LEARNING_ORDER_3, // ç©¶ + 0x7A7A, KANJI_LEARNING_ORDER_1, // 空 + 0x7A81, KANJI_LEARNING_ORDER_7, // 突 + 0x7A83, KANJI_LEARNING_ORDER_7, // 窃 + 0x7A92, KANJI_LEARNING_ORDER_7, // 窒 + 0x7A93, KANJI_LEARNING_ORDER_6, // 窓 + 0x7AAE, KANJI_LEARNING_ORDER_7, // 窮 + 0x7AAF, KANJI_LEARNING_ORDER_7, // 窯 + 0x7ACB, KANJI_LEARNING_ORDER_1, // 立 + 0x7ADC, KANJI_LEARNING_ORDER_7, // 竜 + 0x7AE0, KANJI_LEARNING_ORDER_3, // ç«  + 0x7AE5, KANJI_LEARNING_ORDER_3, // ç«¥ + 0x7AEF, KANJI_LEARNING_ORDER_7, // 端 + 0x7AF6, KANJI_LEARNING_ORDER_4, // ç«¶ + 0x7AF9, KANJI_LEARNING_ORDER_1, // 竹 + 0x7B11, KANJI_LEARNING_ORDER_4, // 笑 + 0x7B1B, KANJI_LEARNING_ORDER_3, // 笛 + 0x7B26, KANJI_LEARNING_ORDER_7, // 笊 + 0x7B2C, KANJI_LEARNING_ORDER_3, // 第 + 0x7B46, KANJI_LEARNING_ORDER_3, // 筆 + 0x7B49, KANJI_LEARNING_ORDER_3, // 等 + 0x7B4B, KANJI_LEARNING_ORDER_6, // 筋 + 0x7B52, KANJI_LEARNING_ORDER_7, // 筒 + 0x7B54, KANJI_LEARNING_ORDER_2, // 答 + 0x7B56, KANJI_LEARNING_ORDER_6, // 策 + 0x7B87, KANJI_LEARNING_ORDER_7, // 箇 + 0x7B97, KANJI_LEARNING_ORDER_2, // 算 + 0x7BA1, KANJI_LEARNING_ORDER_4, // 管 + 0x7BB1, KANJI_LEARNING_ORDER_3, // ç®± + 0x7BC0, KANJI_LEARNING_ORDER_4, // 節 + 0x7BC4, KANJI_LEARNING_ORDER_7, // 範 + 0x7BC9, KANJI_LEARNING_ORDER_5, // 築 + 0x7BE4, KANJI_LEARNING_ORDER_7, // 節 + 0x7C21, KANJI_LEARNING_ORDER_6, // ç°¡ + 0x7C3F, KANJI_LEARNING_ORDER_7, // ç°¿ + 0x7C4D, KANJI_LEARNING_ORDER_7, // 籍 + 0x7C73, KANJI_LEARNING_ORDER_2, // ç±³ + 0x7C89, KANJI_LEARNING_ORDER_4, // 粉 + 0x7C8B, KANJI_LEARNING_ORDER_7, // 粋 + 0x7C92, KANJI_LEARNING_ORDER_7, // 粒 + 0x7C97, KANJI_LEARNING_ORDER_7, // 粗 + 0x7C98, KANJI_LEARNING_ORDER_7, // 粘 + 0x7C9B, KANJI_LEARNING_ORDER_7, // 粛 + 0x7CA7, KANJI_LEARNING_ORDER_7, // ç²§ + 0x7CBE, KANJI_LEARNING_ORDER_5, // 粟 + 0x7CD6, KANJI_LEARNING_ORDER_6, // 糖 + 0x7CE7, KANJI_LEARNING_ORDER_7, // ç³§ + 0x7CF8, KANJI_LEARNING_ORDER_1, // 糞 + 0x7CFB, KANJI_LEARNING_ORDER_6, // ç³» + 0x7CFE, KANJI_LEARNING_ORDER_7, // 糟 + 0x7D00, KANJI_LEARNING_ORDER_4, // 简 + 0x7D04, KANJI_LEARNING_ORDER_4, // 箄 + 0x7D05, KANJI_LEARNING_ORDER_6, // 箅 + 0x7D0B, KANJI_LEARNING_ORDER_7, // 箋 + 0x7D0D, KANJI_LEARNING_ORDER_6, // 玍 + 0x7D14, KANJI_LEARNING_ORDER_6, // 箔 + 0x7D19, KANJI_LEARNING_ORDER_2, // 箙 + 0x7D1A, KANJI_LEARNING_ORDER_3, // 箚 + 0x7D1B, KANJI_LEARNING_ORDER_7, // 箛 + 0x7D20, KANJI_LEARNING_ORDER_5, // 玠 + 0x7D21, KANJI_LEARNING_ORDER_7, // 玡 + 0x7D22, KANJI_LEARNING_ORDER_7, // 玢 + 0x7D2B, KANJI_LEARNING_ORDER_7, // 玫 + 0x7D2F, KANJI_LEARNING_ORDER_7, // 环 + 0x7D30, KANJI_LEARNING_ORDER_2, // 现 + 0x7D33, KANJI_LEARNING_ORDER_7, // 玳 + 0x7D39, KANJI_LEARNING_ORDER_7, // 玹 + 0x7D3A, KANJI_LEARNING_ORDER_7, // 玺 + 0x7D42, KANJI_LEARNING_ORDER_3, // 終 + 0x7D44, KANJI_LEARNING_ORDER_2, // 組 + 0x7D4C, KANJI_LEARNING_ORDER_5, // 経 + 0x7D50, KANJI_LEARNING_ORDER_4, // 結 + 0x7D5E, KANJI_LEARNING_ORDER_7, // 絞 + 0x7D61, KANJI_LEARNING_ORDER_7, // 絡 + 0x7D66, KANJI_LEARNING_ORDER_4, // 絊 + 0x7D71, KANJI_LEARNING_ORDER_5, // çµ± + 0x7D75, KANJI_LEARNING_ORDER_2, // çµµ + 0x7D76, KANJI_LEARNING_ORDER_5, // çµ¶ + 0x7D79, KANJI_LEARNING_ORDER_6, // çµ¹ + 0x7D99, KANJI_LEARNING_ORDER_7, // 継 + 0x7D9A, KANJI_LEARNING_ORDER_4, // 続 + 0x7DAD, KANJI_LEARNING_ORDER_7, // ç¶­ + 0x7DB1, KANJI_LEARNING_ORDER_7, // ç¶± + 0x7DB2, KANJI_LEARNING_ORDER_7, // ç¶² + 0x7DBF, KANJI_LEARNING_ORDER_5, // ç¶¿ + 0x7DCA, KANJI_LEARNING_ORDER_7, // 緊 + 0x7DCF, KANJI_LEARNING_ORDER_5, // 総 + 0x7DD1, KANJI_LEARNING_ORDER_3, // 緑 + 0x7DD2, KANJI_LEARNING_ORDER_7, // 緒 + 0x7DDA, KANJI_LEARNING_ORDER_2, // 線 + 0x7DE0, KANJI_LEARNING_ORDER_7, // ç·  + 0x7DE8, KANJI_LEARNING_ORDER_5, // ç·š + 0x7DE9, KANJI_LEARNING_ORDER_7, // ç·© + 0x7DEF, KANJI_LEARNING_ORDER_7, // ç·¯ + 0x7DF4, KANJI_LEARNING_ORDER_3, // ç·Ž + 0x7E01, KANJI_LEARNING_ORDER_7, // 瞁 + 0x7E04, KANJI_LEARNING_ORDER_7, // 羄 + 0x7E1B, KANJI_LEARNING_ORDER_7, // 羛 + 0x7E26, KANJI_LEARNING_ORDER_6, // 瞊 + 0x7E2B, KANJI_LEARNING_ORDER_7, // çž« + 0x7E2E, KANJI_LEARNING_ORDER_6, // çž® + 0x7E3E, KANJI_LEARNING_ORDER_5, // 瞟 + 0x7E41, KANJI_LEARNING_ORDER_7, // 繁 + 0x7E4A, KANJI_LEARNING_ORDER_7, // 繊 + 0x7E54, KANJI_LEARNING_ORDER_5, // 織 + 0x7E55, KANJI_LEARNING_ORDER_7, // 繕 + 0x7E6D, KANJI_LEARNING_ORDER_7, // ç¹­ + 0x7E70, KANJI_LEARNING_ORDER_7, // ç¹° + 0x7F36, KANJI_LEARNING_ORDER_7, // 猶 + 0x7F6A, KANJI_LEARNING_ORDER_5, // 眪 + 0x7F6E, KANJI_LEARNING_ORDER_4, // 眮 + 0x7F70, KANJI_LEARNING_ORDER_7, // 眰 + 0x7F72, KANJI_LEARNING_ORDER_6, // 眲 + 0x7F77, KANJI_LEARNING_ORDER_7, // 眷 + 0x7F85, KANJI_LEARNING_ORDER_7, // 矅 + 0x7F8A, KANJI_LEARNING_ORDER_3, // 矊 + 0x7F8E, KANJI_LEARNING_ORDER_3, // 矎 + 0x7FA4, KANJI_LEARNING_ORDER_5, // 矀 + 0x7FA9, KANJI_LEARNING_ORDER_5, // 矩 + 0x7FBD, KANJI_LEARNING_ORDER_2, // 矜 + 0x7FC1, KANJI_LEARNING_ORDER_7, // 翁 + 0x7FCC, KANJI_LEARNING_ORDER_6, // 翌 + 0x7FD2, KANJI_LEARNING_ORDER_3, // 習 + 0x7FFB, KANJI_LEARNING_ORDER_7, // ç¿» + 0x7FFC, KANJI_LEARNING_ORDER_7, // 翌 + 0x8001, KANJI_LEARNING_ORDER_4, // 老 + 0x8003, KANJI_LEARNING_ORDER_2, // 考 + 0x8005, KANJI_LEARNING_ORDER_3, // 者 + 0x8010, KANJI_LEARNING_ORDER_7, // 耐 + 0x8015, KANJI_LEARNING_ORDER_5, // 耕 + 0x8017, KANJI_LEARNING_ORDER_7, // 耗 + 0x8033, KANJI_LEARNING_ORDER_1, // 耳 + 0x8056, KANJI_LEARNING_ORDER_6, // 聖 + 0x805E, KANJI_LEARNING_ORDER_2, // 聞 + 0x8074, KANJI_LEARNING_ORDER_7, // 聎 + 0x8077, KANJI_LEARNING_ORDER_5, // 職 + 0x8089, KANJI_LEARNING_ORDER_2, // 肉 + 0x808C, KANJI_LEARNING_ORDER_7, // 肌 + 0x8096, KANJI_LEARNING_ORDER_7, // 肖 + 0x809D, KANJI_LEARNING_ORDER_7, // 肝 + 0x80A2, KANJI_LEARNING_ORDER_7, // 肢 + 0x80A5, KANJI_LEARNING_ORDER_5, // 肥 + 0x80A9, KANJI_LEARNING_ORDER_7, // 肩 + 0x80AA, KANJI_LEARNING_ORDER_7, // 肪 + 0x80AF, KANJI_LEARNING_ORDER_7, // 肯 + 0x80B2, KANJI_LEARNING_ORDER_3, // 育 + 0x80BA, KANJI_LEARNING_ORDER_6, // 肺 + 0x80C3, KANJI_LEARNING_ORDER_4, // 胃 + 0x80C6, KANJI_LEARNING_ORDER_7, // 胆 + 0x80CC, KANJI_LEARNING_ORDER_6, // 背 + 0x80CE, KANJI_LEARNING_ORDER_7, // 胎 + 0x80DE, KANJI_LEARNING_ORDER_7, // 胞 + 0x80F4, KANJI_LEARNING_ORDER_7, // 胎 + 0x80F8, KANJI_LEARNING_ORDER_6, // 胞 + 0x80FD, KANJI_LEARNING_ORDER_5, // 胜 + 0x8102, KANJI_LEARNING_ORDER_7, // 脂 + 0x8105, KANJI_LEARNING_ORDER_7, // 脅 + 0x8108, KANJI_LEARNING_ORDER_4, // 脈 + 0x811A, KANJI_LEARNING_ORDER_7, // 脚 + 0x8131, KANJI_LEARNING_ORDER_7, // 脱 + 0x8133, KANJI_LEARNING_ORDER_6, // 脳 + 0x8139, KANJI_LEARNING_ORDER_7, // 脹 + 0x8150, KANJI_LEARNING_ORDER_7, // 腐 + 0x8155, KANJI_LEARNING_ORDER_7, // 腕 + 0x8170, KANJI_LEARNING_ORDER_7, // 腰 + 0x8178, KANJI_LEARNING_ORDER_4, // è…ž + 0x8179, KANJI_LEARNING_ORDER_6, // 腹 + 0x819A, KANJI_LEARNING_ORDER_7, // 膚 + 0x819C, KANJI_LEARNING_ORDER_7, // 膜 + 0x81A8, KANJI_LEARNING_ORDER_7, // 膚 + 0x81D3, KANJI_LEARNING_ORDER_6, // 臓 + 0x81E3, KANJI_LEARNING_ORDER_4, // 臣 + 0x81E8, KANJI_LEARNING_ORDER_6, // 臚 + 0x81EA, KANJI_LEARNING_ORDER_2, // 自 + 0x81ED, KANJI_LEARNING_ORDER_7, // 臭 + 0x81F3, KANJI_LEARNING_ORDER_6, // 至 + 0x81F4, KANJI_LEARNING_ORDER_7, // 臎 + 0x8208, KANJI_LEARNING_ORDER_5, // 興 + 0x820C, KANJI_LEARNING_ORDER_5, // 舌 + 0x820E, KANJI_LEARNING_ORDER_5, // 舎 + 0x8217, KANJI_LEARNING_ORDER_7, // 舗 + 0x821E, KANJI_LEARNING_ORDER_7, // 舞 + 0x821F, KANJI_LEARNING_ORDER_7, // 舟 + 0x822A, KANJI_LEARNING_ORDER_4, // 航 + 0x822C, KANJI_LEARNING_ORDER_7, // 般 + 0x8236, KANJI_LEARNING_ORDER_7, // 舶 + 0x8239, KANJI_LEARNING_ORDER_2, // 船 + 0x8247, KANJI_LEARNING_ORDER_7, // 艇 + 0x8266, KANJI_LEARNING_ORDER_7, // 艊 + 0x826F, KANJI_LEARNING_ORDER_4, // 良 + 0x8272, KANJI_LEARNING_ORDER_2, // 色 + 0x828B, KANJI_LEARNING_ORDER_7, // 芋 + 0x829D, KANJI_LEARNING_ORDER_7, // 芝 + 0x82B1, KANJI_LEARNING_ORDER_1, // 花 + 0x82B3, KANJI_LEARNING_ORDER_7, // 芳 + 0x82B8, KANJI_LEARNING_ORDER_4, // 芞 + 0x82BD, KANJI_LEARNING_ORDER_4, // 芜 + 0x82D7, KANJI_LEARNING_ORDER_7, // 苗 + 0x82E5, KANJI_LEARNING_ORDER_6, // 若 + 0x82E6, KANJI_LEARNING_ORDER_3, // 苊 + 0x82F1, KANJI_LEARNING_ORDER_4, // 英 + 0x8302, KANJI_LEARNING_ORDER_7, // 茂 + 0x830E, KANJI_LEARNING_ORDER_7, // 茎 + 0x8336, KANJI_LEARNING_ORDER_2, // 茶 + 0x8349, KANJI_LEARNING_ORDER_1, // 草 + 0x8352, KANJI_LEARNING_ORDER_7, // 荒 + 0x8358, KANJI_LEARNING_ORDER_7, // 荘 + 0x8377, KANJI_LEARNING_ORDER_3, // 荷 + 0x83CA, KANJI_LEARNING_ORDER_7, // 菊 + 0x83CC, KANJI_LEARNING_ORDER_7, // 菌 + 0x83D3, KANJI_LEARNING_ORDER_7, // 菓 + 0x83DC, KANJI_LEARNING_ORDER_4, // 菜 + 0x83EF, KANJI_LEARNING_ORDER_7, // 華 + 0x843D, KANJI_LEARNING_ORDER_3, // 萜 + 0x8449, KANJI_LEARNING_ORDER_3, // 葉 + 0x8457, KANJI_LEARNING_ORDER_6, // 著 + 0x846C, KANJI_LEARNING_ORDER_7, // 葬 + 0x84B8, KANJI_LEARNING_ORDER_6, // è’ž + 0x84C4, KANJI_LEARNING_ORDER_7, // 蓄 + 0x8535, KANJI_LEARNING_ORDER_6, // 蔵 + 0x8584, KANJI_LEARNING_ORDER_7, // 薄 + 0x85A6, KANJI_LEARNING_ORDER_7, // è–Š + 0x85AA, KANJI_LEARNING_ORDER_7, // 薪 + 0x85AB, KANJI_LEARNING_ORDER_7, // 薫 + 0x85AC, KANJI_LEARNING_ORDER_3, // 薬 + 0x85E9, KANJI_LEARNING_ORDER_7, // 藩 + 0x85FB, KANJI_LEARNING_ORDER_7, // 藻 + 0x8650, KANJI_LEARNING_ORDER_7, // 虐 + 0x865A, KANJI_LEARNING_ORDER_7, // 虚 + 0x865C, KANJI_LEARNING_ORDER_7, // 虜 + 0x865E, KANJI_LEARNING_ORDER_7, // 虞 + 0x866B, KANJI_LEARNING_ORDER_1, // 虫 + 0x868A, KANJI_LEARNING_ORDER_7, // 蚊 + 0x8695, KANJI_LEARNING_ORDER_6, // 蚕 + 0x86C7, KANJI_LEARNING_ORDER_7, // 蛇 + 0x86CD, KANJI_LEARNING_ORDER_7, // 蛍 + 0x86EE, KANJI_LEARNING_ORDER_7, // 蛮 + 0x878D, KANJI_LEARNING_ORDER_7, // 融 + 0x8840, KANJI_LEARNING_ORDER_3, // 血 + 0x8846, KANJI_LEARNING_ORDER_6, // 衆 + 0x884C, KANJI_LEARNING_ORDER_2, // 行 + 0x8853, KANJI_LEARNING_ORDER_5, // 術 + 0x8857, KANJI_LEARNING_ORDER_4, // 街 + 0x885B, KANJI_LEARNING_ORDER_5, // 衛 + 0x885D, KANJI_LEARNING_ORDER_7, // 衝 + 0x8861, KANJI_LEARNING_ORDER_7, // è¡¡ + 0x8863, KANJI_LEARNING_ORDER_4, // è¡£ + 0x8868, KANJI_LEARNING_ORDER_3, // 衚 + 0x8870, KANJI_LEARNING_ORDER_7, // è¡° + 0x8877, KANJI_LEARNING_ORDER_7, // è¡· + 0x888B, KANJI_LEARNING_ORDER_7, // 袋 + 0x88AB, KANJI_LEARNING_ORDER_7, // 被 + 0x88C1, KANJI_LEARNING_ORDER_6, // 裁 + 0x88C2, KANJI_LEARNING_ORDER_7, // 裂 + 0x88C5, KANJI_LEARNING_ORDER_6, // 装 + 0x88CF, KANJI_LEARNING_ORDER_6, // 裏 + 0x88D5, KANJI_LEARNING_ORDER_7, // 裕 + 0x88DC, KANJI_LEARNING_ORDER_6, // 補 + 0x88F8, KANJI_LEARNING_ORDER_7, // 裞 + 0x88FD, KANJI_LEARNING_ORDER_5, // 補 + 0x8907, KANJI_LEARNING_ORDER_5, // 耇 + 0x8910, KANJI_LEARNING_ORDER_7, // 耐 + 0x8912, KANJI_LEARNING_ORDER_7, // 耒 + 0x895F, KANJI_LEARNING_ORDER_7, // 襟 + 0x8972, KANJI_LEARNING_ORDER_7, // 襲 + 0x897F, KANJI_LEARNING_ORDER_2, // 西 + 0x8981, KANJI_LEARNING_ORDER_4, // 芁 + 0x8986, KANJI_LEARNING_ORDER_7, // 芆 + 0x8987, KANJI_LEARNING_ORDER_7, // 芇 + 0x898B, KANJI_LEARNING_ORDER_1, // 芋 + 0x898F, KANJI_LEARNING_ORDER_5, // 芏 + 0x8996, KANJI_LEARNING_ORDER_6, // 芖 + 0x899A, KANJI_LEARNING_ORDER_4, // 芚 + 0x89A7, KANJI_LEARNING_ORDER_6, // 芧 + 0x89AA, KANJI_LEARNING_ORDER_2, // 芪 + 0x89B3, KANJI_LEARNING_ORDER_4, // 芳 + 0x89D2, KANJI_LEARNING_ORDER_2, // 角 + 0x89E3, KANJI_LEARNING_ORDER_5, // è§£ + 0x89E6, KANJI_LEARNING_ORDER_7, // è§Š + 0x8A00, KANJI_LEARNING_ORDER_2, // 蚀 + 0x8A02, KANJI_LEARNING_ORDER_7, // èš‚ + 0x8A08, KANJI_LEARNING_ORDER_2, // 蚈 + 0x8A0E, KANJI_LEARNING_ORDER_6, // 蚎 + 0x8A13, KANJI_LEARNING_ORDER_4, // èš“ + 0x8A17, KANJI_LEARNING_ORDER_7, // èš— + 0x8A18, KANJI_LEARNING_ORDER_2, // 蚘 + 0x8A1F, KANJI_LEARNING_ORDER_7, // 蚟 + 0x8A2A, KANJI_LEARNING_ORDER_6, // 蚪 + 0x8A2D, KANJI_LEARNING_ORDER_5, // èš­ + 0x8A31, KANJI_LEARNING_ORDER_5, // èš± + 0x8A33, KANJI_LEARNING_ORDER_6, // èš³ + 0x8A34, KANJI_LEARNING_ORDER_7, // 蚎 + 0x8A3A, KANJI_LEARNING_ORDER_7, // 蚺 + 0x8A3C, KANJI_LEARNING_ORDER_5, // 蚌 + 0x8A50, KANJI_LEARNING_ORDER_7, // 詐 + 0x8A54, KANJI_LEARNING_ORDER_7, // 詔 + 0x8A55, KANJI_LEARNING_ORDER_5, // 評 + 0x8A5E, KANJI_LEARNING_ORDER_6, // 詞 + 0x8A60, KANJI_LEARNING_ORDER_7, // è©  + 0x8A66, KANJI_LEARNING_ORDER_4, // 詊 + 0x8A69, KANJI_LEARNING_ORDER_3, // è©© + 0x8A70, KANJI_LEARNING_ORDER_7, // è©° + 0x8A71, KANJI_LEARNING_ORDER_2, // 話 + 0x8A72, KANJI_LEARNING_ORDER_7, // 該 + 0x8A73, KANJI_LEARNING_ORDER_7, // 詳 + 0x8A87, KANJI_LEARNING_ORDER_7, // 誇 + 0x8A89, KANJI_LEARNING_ORDER_7, // 誉 + 0x8A8C, KANJI_LEARNING_ORDER_6, // 誌 + 0x8A8D, KANJI_LEARNING_ORDER_6, // 認 + 0x8A93, KANJI_LEARNING_ORDER_7, // 誓 + 0x8A95, KANJI_LEARNING_ORDER_6, // 誕 + 0x8A98, KANJI_LEARNING_ORDER_7, // 誘 + 0x8A9E, KANJI_LEARNING_ORDER_2, // 語 + 0x8AA0, KANJI_LEARNING_ORDER_6, // 誠 + 0x8AA4, KANJI_LEARNING_ORDER_6, // 誀 + 0x8AAC, KANJI_LEARNING_ORDER_4, // 説 + 0x8AAD, KANJI_LEARNING_ORDER_2, // 読 + 0x8AB2, KANJI_LEARNING_ORDER_4, // 課 + 0x8ABF, KANJI_LEARNING_ORDER_3, // 調 + 0x8AC7, KANJI_LEARNING_ORDER_3, // 談 + 0x8ACB, KANJI_LEARNING_ORDER_7, // 請 + 0x8AD6, KANJI_LEARNING_ORDER_6, // 論 + 0x8AED, KANJI_LEARNING_ORDER_7, // è«­ + 0x8AEE, KANJI_LEARNING_ORDER_7, // è«® + 0x8AF8, KANJI_LEARNING_ORDER_6, // 諞 + 0x8AFE, KANJI_LEARNING_ORDER_7, // 諟 + 0x8B00, KANJI_LEARNING_ORDER_7, // 謀 + 0x8B01, KANJI_LEARNING_ORDER_7, // 謁 + 0x8B04, KANJI_LEARNING_ORDER_7, // 謄 + 0x8B19, KANJI_LEARNING_ORDER_7, // 謙 + 0x8B1B, KANJI_LEARNING_ORDER_5, // 講 + 0x8B1D, KANJI_LEARNING_ORDER_5, // 謝 + 0x8B21, KANJI_LEARNING_ORDER_7, // 謡 + 0x8B39, KANJI_LEARNING_ORDER_7, // 謹 + 0x8B58, KANJI_LEARNING_ORDER_5, // 識 + 0x8B5C, KANJI_LEARNING_ORDER_7, // 譜 + 0x8B66, KANJI_LEARNING_ORDER_6, // è­Š + 0x8B70, KANJI_LEARNING_ORDER_4, // è­° + 0x8B72, KANJI_LEARNING_ORDER_7, // è­² + 0x8B77, KANJI_LEARNING_ORDER_5, // è­· + 0x8C37, KANJI_LEARNING_ORDER_2, // è°· + 0x8C46, KANJI_LEARNING_ORDER_3, // 豆 + 0x8C4A, KANJI_LEARNING_ORDER_5, // 豊 + 0x8C5A, KANJI_LEARNING_ORDER_7, // 豚 + 0x8C61, KANJI_LEARNING_ORDER_4, // 象 + 0x8C6A, KANJI_LEARNING_ORDER_7, // 豪 + 0x8C9D, KANJI_LEARNING_ORDER_1, // 貝 + 0x8C9E, KANJI_LEARNING_ORDER_7, // 貞 + 0x8CA0, KANJI_LEARNING_ORDER_3, // è²  + 0x8CA1, KANJI_LEARNING_ORDER_5, // 財 + 0x8CA2, KANJI_LEARNING_ORDER_7, // è²¢ + 0x8CA7, KANJI_LEARNING_ORDER_5, // è²§ + 0x8CA8, KANJI_LEARNING_ORDER_4, // 貚 + 0x8CA9, KANJI_LEARNING_ORDER_7, // 販 + 0x8CAB, KANJI_LEARNING_ORDER_7, // 貫 + 0x8CAC, KANJI_LEARNING_ORDER_5, // 責 + 0x8CAF, KANJI_LEARNING_ORDER_4, // 貯 + 0x8CB4, KANJI_LEARNING_ORDER_6, // 貎 + 0x8CB7, KANJI_LEARNING_ORDER_2, // è²· + 0x8CB8, KANJI_LEARNING_ORDER_5, // 貞 + 0x8CBB, KANJI_LEARNING_ORDER_4, // è²» + 0x8CBF, KANJI_LEARNING_ORDER_5, // 貿 + 0x8CC0, KANJI_LEARNING_ORDER_5, // 賀 + 0x8CC3, KANJI_LEARNING_ORDER_6, // 賃 + 0x8CC4, KANJI_LEARNING_ORDER_7, // 賄 + 0x8CC7, KANJI_LEARNING_ORDER_5, // 資 + 0x8CCA, KANJI_LEARNING_ORDER_7, // 賊 + 0x8CD3, KANJI_LEARNING_ORDER_7, // 賓 + 0x8CDB, KANJI_LEARNING_ORDER_5, // 賛 + 0x8CDC, KANJI_LEARNING_ORDER_7, // 賜 + 0x8CDE, KANJI_LEARNING_ORDER_4, // 賞 + 0x8CE0, KANJI_LEARNING_ORDER_7, // è³  + 0x8CE2, KANJI_LEARNING_ORDER_7, // è³¢ + 0x8CE6, KANJI_LEARNING_ORDER_7, // 賊 + 0x8CEA, KANJI_LEARNING_ORDER_5, // 質 + 0x8CFC, KANJI_LEARNING_ORDER_7, // 賌 + 0x8D08, KANJI_LEARNING_ORDER_7, // 莈 + 0x8D64, KANJI_LEARNING_ORDER_1, // èµ€ + 0x8D66, KANJI_LEARNING_ORDER_7, // 赊 + 0x8D70, KANJI_LEARNING_ORDER_2, // èµ° + 0x8D74, KANJI_LEARNING_ORDER_7, // 赎 + 0x8D77, KANJI_LEARNING_ORDER_3, // èµ· + 0x8D85, KANJI_LEARNING_ORDER_7, // 超 + 0x8D8A, KANJI_LEARNING_ORDER_7, // 越 + 0x8DA3, KANJI_LEARNING_ORDER_7, // è¶£ + 0x8DB3, KANJI_LEARNING_ORDER_1, // è¶³ + 0x8DDD, KANJI_LEARNING_ORDER_7, // 距 + 0x8DE1, KANJI_LEARNING_ORDER_7, // è·¡ + 0x8DEF, KANJI_LEARNING_ORDER_3, // è·¯ + 0x8DF3, KANJI_LEARNING_ORDER_7, // è·³ + 0x8DF5, KANJI_LEARNING_ORDER_7, // è·µ + 0x8E0A, KANJI_LEARNING_ORDER_7, // 螊 + 0x8E0F, KANJI_LEARNING_ORDER_7, // 螏 + 0x8E8D, KANJI_LEARNING_ORDER_7, // 躍 + 0x8EAB, KANJI_LEARNING_ORDER_3, // 身 + 0x8ECA, KANJI_LEARNING_ORDER_1, // 車 + 0x8ECC, KANJI_LEARNING_ORDER_7, // 軌 + 0x8ECD, KANJI_LEARNING_ORDER_4, // 軍 + 0x8ED2, KANJI_LEARNING_ORDER_7, // 軒 + 0x8EDF, KANJI_LEARNING_ORDER_7, // 軟 + 0x8EE2, KANJI_LEARNING_ORDER_3, // 転 + 0x8EF8, KANJI_LEARNING_ORDER_7, // 軞 + 0x8EFD, KANJI_LEARNING_ORDER_3, // 軜 + 0x8F03, KANJI_LEARNING_ORDER_7, // 范 + 0x8F09, KANJI_LEARNING_ORDER_7, // 茉 + 0x8F1D, KANJI_LEARNING_ORDER_7, // 茝 + 0x8F29, KANJI_LEARNING_ORDER_7, // 茩 + 0x8F2A, KANJI_LEARNING_ORDER_4, // 茪 + 0x8F38, KANJI_LEARNING_ORDER_5, // 茞 + 0x8F44, KANJI_LEARNING_ORDER_7, // 蜄 + 0x8F9B, KANJI_LEARNING_ORDER_7, // 蟛 + 0x8F9E, KANJI_LEARNING_ORDER_4, // 蟞 + 0x8FB1, KANJI_LEARNING_ORDER_7, // 蟱 + 0x8FB2, KANJI_LEARNING_ORDER_3, // 蟲 + 0x8FBA, KANJI_LEARNING_ORDER_4, // 蟺 + 0x8FBC, KANJI_LEARNING_ORDER_7, // 蟌 + 0x8FC5, KANJI_LEARNING_ORDER_7, // 迅 + 0x8FCE, KANJI_LEARNING_ORDER_7, // 迎 + 0x8FD1, KANJI_LEARNING_ORDER_2, // 近 + 0x8FD4, KANJI_LEARNING_ORDER_3, // 返 + 0x8FEB, KANJI_LEARNING_ORDER_7, // è¿« + 0x8FED, KANJI_LEARNING_ORDER_7, // è¿­ + 0x8FF0, KANJI_LEARNING_ORDER_5, // è¿° + 0x8FF7, KANJI_LEARNING_ORDER_5, // è¿· + 0x8FFD, KANJI_LEARNING_ORDER_3, // 远 + 0x9000, KANJI_LEARNING_ORDER_5, // 退 + 0x9001, KANJI_LEARNING_ORDER_3, // 送 + 0x9003, KANJI_LEARNING_ORDER_7, // 逃 + 0x9006, KANJI_LEARNING_ORDER_5, // 逆 + 0x900F, KANJI_LEARNING_ORDER_7, // 透 + 0x9010, KANJI_LEARNING_ORDER_7, // 逐 + 0x9013, KANJI_LEARNING_ORDER_7, // 逓 + 0x9014, KANJI_LEARNING_ORDER_7, // 途 + 0x901A, KANJI_LEARNING_ORDER_2, // 通 + 0x901D, KANJI_LEARNING_ORDER_7, // 逝 + 0x901F, KANJI_LEARNING_ORDER_3, // 速 + 0x9020, KANJI_LEARNING_ORDER_5, // 造 + 0x9023, KANJI_LEARNING_ORDER_4, // 連 + 0x902E, KANJI_LEARNING_ORDER_7, // 逮 + 0x9031, KANJI_LEARNING_ORDER_2, // 週 + 0x9032, KANJI_LEARNING_ORDER_3, // 進 + 0x9038, KANJI_LEARNING_ORDER_7, // 逾 + 0x9042, KANJI_LEARNING_ORDER_7, // 遂 + 0x9045, KANJI_LEARNING_ORDER_7, // 遅 + 0x9047, KANJI_LEARNING_ORDER_7, // 遇 + 0x904A, KANJI_LEARNING_ORDER_3, // 遊 + 0x904B, KANJI_LEARNING_ORDER_3, // 運 + 0x904D, KANJI_LEARNING_ORDER_7, // 遍 + 0x904E, KANJI_LEARNING_ORDER_5, // 過 + 0x9053, KANJI_LEARNING_ORDER_2, // 道 + 0x9054, KANJI_LEARNING_ORDER_4, // 達 + 0x9055, KANJI_LEARNING_ORDER_7, // 違 + 0x9060, KANJI_LEARNING_ORDER_2, // 遠 + 0x9063, KANJI_LEARNING_ORDER_7, // 遣 + 0x9069, KANJI_LEARNING_ORDER_5, // 適 + 0x906D, KANJI_LEARNING_ORDER_7, // 遭 + 0x906E, KANJI_LEARNING_ORDER_7, // 遮 + 0x9075, KANJI_LEARNING_ORDER_7, // 遵 + 0x9077, KANJI_LEARNING_ORDER_7, // 遷 + 0x9078, KANJI_LEARNING_ORDER_4, // 遞 + 0x907A, KANJI_LEARNING_ORDER_6, // 遺 + 0x907F, KANJI_LEARNING_ORDER_7, // 避 + 0x9084, KANJI_LEARNING_ORDER_7, // 還 + 0x90A6, KANJI_LEARNING_ORDER_7, // 邩 + 0x90AA, KANJI_LEARNING_ORDER_7, // 邪 + 0x90B8, KANJI_LEARNING_ORDER_7, // 邾 + 0x90CA, KANJI_LEARNING_ORDER_7, // 郊 + 0x90CE, KANJI_LEARNING_ORDER_7, // 郎 + 0x90E1, KANJI_LEARNING_ORDER_4, // 郡 + 0x90E8, KANJI_LEARNING_ORDER_3, // 郚 + 0x90ED, KANJI_LEARNING_ORDER_7, // 郭 + 0x90F5, KANJI_LEARNING_ORDER_6, // 郵 + 0x90F7, KANJI_LEARNING_ORDER_6, // 郷 + 0x90FD, KANJI_LEARNING_ORDER_3, // 郜 + 0x914C, KANJI_LEARNING_ORDER_7, // 酌 + 0x914D, KANJI_LEARNING_ORDER_3, // 配 + 0x9152, KANJI_LEARNING_ORDER_3, // 酒 + 0x9154, KANJI_LEARNING_ORDER_7, // 酔 + 0x9162, KANJI_LEARNING_ORDER_7, // 酢 + 0x916A, KANJI_LEARNING_ORDER_7, // 酪 + 0x916C, KANJI_LEARNING_ORDER_7, // 酬 + 0x9175, KANJI_LEARNING_ORDER_7, // 酵 + 0x9177, KANJI_LEARNING_ORDER_7, // 酷 + 0x9178, KANJI_LEARNING_ORDER_5, // 酾 + 0x919C, KANJI_LEARNING_ORDER_7, // 醜 + 0x91B8, KANJI_LEARNING_ORDER_7, // 醾 + 0x91C8, KANJI_LEARNING_ORDER_7, // 釈 + 0x91CC, KANJI_LEARNING_ORDER_2, // 里 + 0x91CD, KANJI_LEARNING_ORDER_3, // 重 + 0x91CE, KANJI_LEARNING_ORDER_2, // 野 + 0x91CF, KANJI_LEARNING_ORDER_4, // 量 + 0x91D1, KANJI_LEARNING_ORDER_1, // 金 + 0x91DD, KANJI_LEARNING_ORDER_6, // 針 + 0x91E3, KANJI_LEARNING_ORDER_7, // 釣 + 0x920D, KANJI_LEARNING_ORDER_7, // 鈍 + 0x9234, KANJI_LEARNING_ORDER_7, // 鈎 + 0x9244, KANJI_LEARNING_ORDER_3, // 鉄 + 0x925B, KANJI_LEARNING_ORDER_7, // 鉛 + 0x9262, KANJI_LEARNING_ORDER_7, // 鉢 + 0x9271, KANJI_LEARNING_ORDER_5, // 鉱 + 0x9280, KANJI_LEARNING_ORDER_3, // 銀 + 0x9283, KANJI_LEARNING_ORDER_7, // 銃 + 0x9285, KANJI_LEARNING_ORDER_5, // 銅 + 0x9291, KANJI_LEARNING_ORDER_7, // 銑 + 0x9298, KANJI_LEARNING_ORDER_7, // 銘 + 0x92AD, KANJI_LEARNING_ORDER_5, // 銭 + 0x92ED, KANJI_LEARNING_ORDER_7, // 鋭 + 0x92F3, KANJI_LEARNING_ORDER_7, // 鋳 + 0x92FC, KANJI_LEARNING_ORDER_6, // 鋌 + 0x9318, KANJI_LEARNING_ORDER_7, // 錘 + 0x9320, KANJI_LEARNING_ORDER_7, // 錠 + 0x932C, KANJI_LEARNING_ORDER_7, // 錬 + 0x932F, KANJI_LEARNING_ORDER_7, // 錯 + 0x9332, KANJI_LEARNING_ORDER_4, // 録 + 0x935B, KANJI_LEARNING_ORDER_7, // 鍛 + 0x9396, KANJI_LEARNING_ORDER_7, // 鎖 + 0x93AE, KANJI_LEARNING_ORDER_7, // 鎮 + 0x93E1, KANJI_LEARNING_ORDER_4, // 鏡 + 0x9418, KANJI_LEARNING_ORDER_7, // 鐘 + 0x9451, KANJI_LEARNING_ORDER_7, // 鑑 + 0x9577, KANJI_LEARNING_ORDER_2, // 長 + 0x9580, KANJI_LEARNING_ORDER_2, // 門 + 0x9589, KANJI_LEARNING_ORDER_6, // 閉 + 0x958B, KANJI_LEARNING_ORDER_3, // 開 + 0x9591, KANJI_LEARNING_ORDER_7, // 閑 + 0x9593, KANJI_LEARNING_ORDER_2, // 間 + 0x95A2, KANJI_LEARNING_ORDER_4, // 関 + 0x95A3, KANJI_LEARNING_ORDER_6, // 閣 + 0x95A5, KANJI_LEARNING_ORDER_7, // 閥 + 0x95B2, KANJI_LEARNING_ORDER_7, // 閲 + 0x95D8, KANJI_LEARNING_ORDER_7, // 闘 + 0x9632, KANJI_LEARNING_ORDER_5, // 防 + 0x963B, KANJI_LEARNING_ORDER_7, // 阻 + 0x9644, KANJI_LEARNING_ORDER_7, // 附 + 0x964D, KANJI_LEARNING_ORDER_6, // 降 + 0x9650, KANJI_LEARNING_ORDER_5, // 限 + 0x965B, KANJI_LEARNING_ORDER_6, // 陛 + 0x9662, KANJI_LEARNING_ORDER_3, // 院 + 0x9663, KANJI_LEARNING_ORDER_7, // 陣 + 0x9664, KANJI_LEARNING_ORDER_6, // 陀 + 0x9665, KANJI_LEARNING_ORDER_7, // 陥 + 0x966A, KANJI_LEARNING_ORDER_7, // 陪 + 0x9670, KANJI_LEARNING_ORDER_7, // 陰 + 0x9673, KANJI_LEARNING_ORDER_7, // 陳 + 0x9675, KANJI_LEARNING_ORDER_7, // 陵 + 0x9676, KANJI_LEARNING_ORDER_7, // 陶 + 0x9678, KANJI_LEARNING_ORDER_4, // 陾 + 0x967A, KANJI_LEARNING_ORDER_5, // 険 + 0x967D, KANJI_LEARNING_ORDER_3, // 陜 + 0x9685, KANJI_LEARNING_ORDER_7, // 隅 + 0x9686, KANJI_LEARNING_ORDER_7, // 隆 + 0x968A, KANJI_LEARNING_ORDER_4, // 隊 + 0x968E, KANJI_LEARNING_ORDER_3, // 階 + 0x968F, KANJI_LEARNING_ORDER_7, // 随 + 0x9694, KANJI_LEARNING_ORDER_7, // 隔 + 0x969B, KANJI_LEARNING_ORDER_5, // 際 + 0x969C, KANJI_LEARNING_ORDER_6, // 障 + 0x96A0, KANJI_LEARNING_ORDER_7, // 隠 + 0x96A3, KANJI_LEARNING_ORDER_7, // 隣 + 0x96B7, KANJI_LEARNING_ORDER_7, // 隷 + 0x96BB, KANJI_LEARNING_ORDER_7, // 隻 + 0x96C4, KANJI_LEARNING_ORDER_7, // 雄 + 0x96C5, KANJI_LEARNING_ORDER_7, // 雅 + 0x96C6, KANJI_LEARNING_ORDER_3, // 集 + 0x96C7, KANJI_LEARNING_ORDER_7, // 雇 + 0x96CC, KANJI_LEARNING_ORDER_7, // 雌 + 0x96D1, KANJI_LEARNING_ORDER_5, // 雑 + 0x96E2, KANJI_LEARNING_ORDER_7, // 離 + 0x96E3, KANJI_LEARNING_ORDER_6, // 難 + 0x96E8, KANJI_LEARNING_ORDER_1, // 雹 + 0x96EA, KANJI_LEARNING_ORDER_2, // 雪 + 0x96F0, KANJI_LEARNING_ORDER_7, // 雰 + 0x96F2, KANJI_LEARNING_ORDER_2, // 雲 + 0x96F6, KANJI_LEARNING_ORDER_7, // 零 + 0x96F7, KANJI_LEARNING_ORDER_7, // 雷 + 0x96FB, KANJI_LEARNING_ORDER_2, // 電 + 0x9700, KANJI_LEARNING_ORDER_7, // 需 + 0x9707, KANJI_LEARNING_ORDER_7, // 震 + 0x970A, KANJI_LEARNING_ORDER_7, // 霊 + 0x971C, KANJI_LEARNING_ORDER_7, // 霜 + 0x9727, KANJI_LEARNING_ORDER_7, // 霧 + 0x9732, KANJI_LEARNING_ORDER_7, // 露 + 0x9752, KANJI_LEARNING_ORDER_1, // 青 + 0x9759, KANJI_LEARNING_ORDER_4, // 静 + 0x975E, KANJI_LEARNING_ORDER_5, // 非 + 0x9762, KANJI_LEARNING_ORDER_3, // 面 + 0x9769, KANJI_LEARNING_ORDER_6, // 革 + 0x9774, KANJI_LEARNING_ORDER_7, // 靎 + 0x97F3, KANJI_LEARNING_ORDER_1, // 音 + 0x97FB, KANJI_LEARNING_ORDER_7, // 韻 + 0x97FF, KANJI_LEARNING_ORDER_7, // 響 + 0x9802, KANJI_LEARNING_ORDER_6, // 頂 + 0x9805, KANJI_LEARNING_ORDER_7, // 項 + 0x9806, KANJI_LEARNING_ORDER_4, // 順 + 0x9810, KANJI_LEARNING_ORDER_5, // 預 + 0x9811, KANJI_LEARNING_ORDER_7, // 頑 + 0x9812, KANJI_LEARNING_ORDER_7, // 頒 + 0x9818, KANJI_LEARNING_ORDER_5, // 領 + 0x982D, KANJI_LEARNING_ORDER_2, // é ­ + 0x983B, KANJI_LEARNING_ORDER_7, // é » + 0x983C, KANJI_LEARNING_ORDER_7, // é Œ + 0x984C, KANJI_LEARNING_ORDER_3, // 題 + 0x984D, KANJI_LEARNING_ORDER_5, // 額 + 0x9854, KANJI_LEARNING_ORDER_2, // 顔 + 0x9855, KANJI_LEARNING_ORDER_7, // 顕 + 0x9858, KANJI_LEARNING_ORDER_4, // 願 + 0x985E, KANJI_LEARNING_ORDER_4, // 類 + 0x9867, KANJI_LEARNING_ORDER_7, // é¡§ + 0x98A8, KANJI_LEARNING_ORDER_2, // 颚 + 0x98DB, KANJI_LEARNING_ORDER_4, // 飛 + 0x98DF, KANJI_LEARNING_ORDER_2, // 食 + 0x98E2, KANJI_LEARNING_ORDER_7, // 飢 + 0x98EF, KANJI_LEARNING_ORDER_4, // 飯 + 0x98F2, KANJI_LEARNING_ORDER_3, // 飲 + 0x98FC, KANJI_LEARNING_ORDER_5, // 飌 + 0x98FD, KANJI_LEARNING_ORDER_7, // 飜 + 0x98FE, KANJI_LEARNING_ORDER_7, // 食 + 0x990A, KANJI_LEARNING_ORDER_4, // 逊 + 0x9913, KANJI_LEARNING_ORDER_7, // 逓 + 0x9928, KANJI_LEARNING_ORDER_3, // 通 + 0x9996, KANJI_LEARNING_ORDER_2, // 驖 + 0x9999, KANJI_LEARNING_ORDER_7, // 驙 + 0x99AC, KANJI_LEARNING_ORDER_2, // 銬 + 0x99C4, KANJI_LEARNING_ORDER_7, // 駄 + 0x99C5, KANJI_LEARNING_ORDER_3, // 駅 + 0x99C6, KANJI_LEARNING_ORDER_7, // 駆 + 0x99D0, KANJI_LEARNING_ORDER_7, // 駐 + 0x9A0E, KANJI_LEARNING_ORDER_7, // 階 + 0x9A12, KANJI_LEARNING_ORDER_7, // 鹒 + 0x9A13, KANJI_LEARNING_ORDER_4, // 鹓 + 0x9A30, KANJI_LEARNING_ORDER_7, // éš° + 0x9A5A, KANJI_LEARNING_ORDER_7, // 驚 + 0x9AA8, KANJI_LEARNING_ORDER_6, // 骚 + 0x9AC4, KANJI_LEARNING_ORDER_7, // 髄 + 0x9AD8, KANJI_LEARNING_ORDER_2, // 高 + 0x9AEA, KANJI_LEARNING_ORDER_7, // 髪 + 0x9B3C, KANJI_LEARNING_ORDER_7, // 鬌 + 0x9B42, KANJI_LEARNING_ORDER_7, // 魂 + 0x9B45, KANJI_LEARNING_ORDER_7, // 魅 + 0x9B54, KANJI_LEARNING_ORDER_7, // 魔 + 0x9B5A, KANJI_LEARNING_ORDER_2, // 魚 + 0x9BAE, KANJI_LEARNING_ORDER_7, // é®® + 0x9BE8, KANJI_LEARNING_ORDER_7, // 鯚 + 0x9CE5, KANJI_LEARNING_ORDER_2, // é³¥ + 0x9CF4, KANJI_LEARNING_ORDER_2, // 鳎 + 0x9D8F, KANJI_LEARNING_ORDER_7, // 鶏 + 0x9E97, KANJI_LEARNING_ORDER_7, // 麗 + 0x9EA6, KANJI_LEARNING_ORDER_2, // 麊 + 0x9EBB, KANJI_LEARNING_ORDER_7, // 麻 + 0x9EC4, KANJI_LEARNING_ORDER_2, // 黄 + 0x9ED2, KANJI_LEARNING_ORDER_2, // 黒 + 0x9ED9, KANJI_LEARNING_ORDER_7, // 黙 + 0x9F13, KANJI_LEARNING_ORDER_7, // 錓 + 0x9F3B, KANJI_LEARNING_ORDER_3, // 錻 + 0x9F62, KANJI_LEARNING_ORDER_7, // 霢 + + 0x4E9C, KANJI_STANDARD, // 亜 + 0x5516, KANJI_STANDARD, // 唖 + 0x5A03, KANJI_STANDARD, // 嚃 + 0x963F, KANJI_STANDARD, // 阿 + 0x54C0, KANJI_STANDARD, // 哀 + 0x611B, KANJI_STANDARD, // 愛 + 0x6328, KANJI_STANDARD, // 挚 + 0x59F6, KANJI_STANDARD, // å§¶ + 0x9022, KANJI_STANDARD, // 逢 + 0x8475, KANJI_STANDARD, // 葵 + 0x831C, KANJI_STANDARD, // 茜 + 0x7A50, KANJI_STANDARD, // 穐 + 0x60AA, KANJI_STANDARD, // 悪 + 0x63E1, KANJI_STANDARD, // 握 + 0x6E25, KANJI_STANDARD, // 枥 + 0x65ED, KANJI_STANDARD, // 旭 + 0x8466, KANJI_STANDARD, // 葊 + 0x82A6, KANJI_STANDARD, // 芊 + 0x9BF5, KANJI_STANDARD, // 鯵 + 0x6893, KANJI_STANDARD, // 梓 + 0x5727, KANJI_STANDARD, // 圧 + 0x65A1, KANJI_STANDARD, // 斡 + 0x6271, KANJI_STANDARD, // 扱 + 0x5B9B, KANJI_STANDARD, // 宛 + 0x59D0, KANJI_STANDARD, // 姐 + 0x867B, KANJI_STANDARD, // 虻 + 0x98F4, KANJI_STANDARD, // 风 + 0x7D62, KANJI_STANDARD, // çµ¢ + 0x7DBE, KANJI_STANDARD, // ç¶Ÿ + 0x9B8E, KANJI_STANDARD, // 鮎 + 0x6216, KANJI_STANDARD, // 或 + 0x7C9F, KANJI_STANDARD, // 粟 + 0x88B7, KANJI_STANDARD, // 袷 + 0x5B89, KANJI_STANDARD, // 安 + 0x5EB5, KANJI_STANDARD, // 庵 + 0x6309, KANJI_STANDARD, // 按 + 0x6697, KANJI_STANDARD, // 暗 + 0x6848, KANJI_STANDARD, // 案 + 0x95C7, KANJI_STANDARD, // 闇 + 0x978D, KANJI_STANDARD, // 鞍 + 0x674F, KANJI_STANDARD, // 杏 + 0x4EE5, KANJI_STANDARD, // 以 + 0x4F0A, KANJI_STANDARD, // 䌊 + 0x4F4D, KANJI_STANDARD, // 䜍 + 0x4F9D, KANJI_STANDARD, // 䟝 + 0x5049, KANJI_STANDARD, // 偉 + 0x56F2, KANJI_STANDARD, // 囲 + 0x5937, KANJI_STANDARD, // 倷 + 0x59D4, KANJI_STANDARD, // 委 + 0x5A01, KANJI_STANDARD, // 嚁 + 0x5C09, KANJI_STANDARD, // 尉 + 0x60DF, KANJI_STANDARD, // 惟 + 0x610F, KANJI_STANDARD, // 意 + 0x6170, KANJI_STANDARD, // 慰 + 0x6613, KANJI_STANDARD, // 易 + 0x6905, KANJI_STANDARD, // 怅 + 0x70BA, KANJI_STANDARD, // 為 + 0x754F, KANJI_STANDARD, // 畏 + 0x7570, KANJI_STANDARD, // 異 + 0x79FB, KANJI_STANDARD, // ç§» + 0x7DAD, KANJI_STANDARD, // ç¶­ + 0x7DEF, KANJI_STANDARD, // ç·¯ + 0x80C3, KANJI_STANDARD, // 胃 + 0x840E, KANJI_STANDARD, // 萎 + 0x8863, KANJI_STANDARD, // è¡£ + 0x8B02, KANJI_STANDARD, // 謂 + 0x9055, KANJI_STANDARD, // 違 + 0x907A, KANJI_STANDARD, // 遺 + 0x533B, KANJI_STANDARD, // 医 + 0x4E95, KANJI_STANDARD, // 井 + 0x4EA5, KANJI_STANDARD, // 亥 + 0x57DF, KANJI_STANDARD, // 域 + 0x80B2, KANJI_STANDARD, // 育 + 0x90C1, KANJI_STANDARD, // 郁 + 0x78EF, KANJI_STANDARD, // 磯 + 0x4E00, KANJI_STANDARD, // 侀 + 0x58F1, KANJI_STANDARD, // 壱 + 0x6EA2, KANJI_STANDARD, // 溢 + 0x9038, KANJI_STANDARD, // 逾 + 0x7A32, KANJI_STANDARD, // çš² + 0x8328, KANJI_STANDARD, // 茚 + 0x828B, KANJI_STANDARD, // 芋 + 0x9C2F, KANJI_STANDARD, // é°¯ + 0x5141, KANJI_STANDARD, // 允 + 0x5370, KANJI_STANDARD, // 印 + 0x54BD, KANJI_STANDARD, // å’œ + 0x54E1, KANJI_STANDARD, // 員 + 0x56E0, KANJI_STANDARD, // 因 + 0x59FB, KANJI_STANDARD, // å§» + 0x5F15, KANJI_STANDARD, // 匕 + 0x98F2, KANJI_STANDARD, // 飲 + 0x6DEB, KANJI_STANDARD, // æ·« + 0x80E4, KANJI_STANDARD, // 胀 + 0x852D, KANJI_STANDARD, // 蔭 + 0x9662, KANJI_STANDARD, // 院 + 0x9670, KANJI_STANDARD, // 陰 + 0x96A0, KANJI_STANDARD, // 隠 + 0x97FB, KANJI_STANDARD, // 韻 + 0x540B, KANJI_STANDARD, // 吋 + 0x53F3, KANJI_STANDARD, // 右 + 0x5B87, KANJI_STANDARD, // 宇 + 0x70CF, KANJI_STANDARD, // 烏 + 0x7FBD, KANJI_STANDARD, // 矜 + 0x8FC2, KANJI_STANDARD, // 迂 + 0x96E8, KANJI_STANDARD, // 雹 + 0x536F, KANJI_STANDARD, // 卯 + 0x9D5C, KANJI_STANDARD, // 鵜 + 0x7ABA, KANJI_STANDARD, // 窺 + 0x4E11, KANJI_STANDARD, // 侑 + 0x7893, KANJI_STANDARD, // 碓 + 0x81FC, KANJI_STANDARD, // 臌 + 0x6E26, KANJI_STANDARD, // 枊 + 0x5618, KANJI_STANDARD, // 嘘 + 0x5504, KANJI_STANDARD, // 唄 + 0x6B1D, KANJI_STANDARD, // 欝 + 0x851A, KANJI_STANDARD, // 蔚 + 0x9C3B, KANJI_STANDARD, // é°» + 0x59E5, KANJI_STANDARD, // å§¥ + 0x53A9, KANJI_STANDARD, // 厩 + 0x6D66, KANJI_STANDARD, // 浊 + 0x74DC, KANJI_STANDARD, // 瓜 + 0x958F, KANJI_STANDARD, // 閏 + 0x5642, KANJI_STANDARD, // 噂 + 0x4E91, KANJI_STANDARD, // 云 + 0x904B, KANJI_STANDARD, // 運 + 0x96F2, KANJI_STANDARD, // 雲 + 0x834F, KANJI_STANDARD, // 荏 + 0x990C, KANJI_STANDARD, // 逌 + 0x53E1, KANJI_STANDARD, // 叡 + 0x55B6, KANJI_STANDARD, // 営 + 0x5B30, KANJI_STANDARD, // 嬰 + 0x5F71, KANJI_STANDARD, // 圱 + 0x6620, KANJI_STANDARD, // 映 + 0x66F3, KANJI_STANDARD, // 曳 + 0x6804, KANJI_STANDARD, // 栄 + 0x6C38, KANJI_STANDARD, // æ°ž + 0x6CF3, KANJI_STANDARD, // æ³³ + 0x6D29, KANJI_STANDARD, // 掩 + 0x745B, KANJI_STANDARD, // 瑛 + 0x76C8, KANJI_STANDARD, // 盈 + 0x7A4E, KANJI_STANDARD, // 穎 + 0x9834, KANJI_STANDARD, // é Ž + 0x82F1, KANJI_STANDARD, // 英 + 0x885B, KANJI_STANDARD, // 衛 + 0x8A60, KANJI_STANDARD, // è©  + 0x92ED, KANJI_STANDARD, // 鋭 + 0x6DB2, KANJI_STANDARD, // æ¶² + 0x75AB, KANJI_STANDARD, // 疫 + 0x76CA, KANJI_STANDARD, // 益 + 0x99C5, KANJI_STANDARD, // 駅 + 0x60A6, KANJI_STANDARD, // 悊 + 0x8B01, KANJI_STANDARD, // 謁 + 0x8D8A, KANJI_STANDARD, // 越 + 0x95B2, KANJI_STANDARD, // 閲 + 0x698E, KANJI_STANDARD, // 抎 + 0x53AD, KANJI_STANDARD, // 厭 + 0x5186, KANJI_STANDARD, // 円 + 0x5712, KANJI_STANDARD, // 園 + 0x5830, KANJI_STANDARD, // å ° + 0x5944, KANJI_STANDARD, // 奄 + 0x5BB4, KANJI_STANDARD, // 宎 + 0x5EF6, KANJI_STANDARD, // å»¶ + 0x6028, KANJI_STANDARD, // 怚 + 0x63A9, KANJI_STANDARD, // 掩 + 0x63F4, KANJI_STANDARD, // 揎 + 0x6CBF, KANJI_STANDARD, // 沿 + 0x6F14, KANJI_STANDARD, // 挔 + 0x708E, KANJI_STANDARD, // 炎 + 0x7114, KANJI_STANDARD, // 焔 + 0x7159, KANJI_STANDARD, // 煙 + 0x71D5, KANJI_STANDARD, // 燕 + 0x733F, KANJI_STANDARD, // 猿 + 0x7E01, KANJI_STANDARD, // 瞁 + 0x8276, KANJI_STANDARD, // 艶 + 0x82D1, KANJI_STANDARD, // 苑 + 0x8597, KANJI_STANDARD, // 薗 + 0x9060, KANJI_STANDARD, // 遠 + 0x925B, KANJI_STANDARD, // 鉛 + 0x9D1B, KANJI_STANDARD, // 鮛 + 0x5869, KANJI_STANDARD, // å¡© + 0x65BC, KANJI_STANDARD, // æ–Œ + 0x6C5A, KANJI_STANDARD, // 汚 + 0x7525, KANJI_STANDARD, // 甥 + 0x51F9, KANJI_STANDARD, // 凹 + 0x592E, KANJI_STANDARD, // 倮 + 0x5965, KANJI_STANDARD, // 奥 + 0x5F80, KANJI_STANDARD, // 埀 + 0x5FDC, KANJI_STANDARD, // 応 + 0x62BC, KANJI_STANDARD, // 抌 + 0x65FA, KANJI_STANDARD, // 旺 + 0x6A2A, KANJI_STANDARD, // 暪 + 0x6B27, KANJI_STANDARD, // 欧 + 0x6BB4, KANJI_STANDARD, // 殎 + 0x738B, KANJI_STANDARD, // 王 + 0x7FC1, KANJI_STANDARD, // 翁 + 0x8956, KANJI_STANDARD, // 襖 + 0x9D2C, KANJI_STANDARD, // 鎬 + 0x9D0E, KANJI_STANDARD, // 鮎 + 0x9EC4, KANJI_STANDARD, // 黄 + 0x5CA1, KANJI_STANDARD, // 岡 + 0x6C96, KANJI_STANDARD, // 沖 + 0x837B, KANJI_STANDARD, // 荻 + 0x5104, KANJI_STANDARD, // 億 + 0x5C4B, KANJI_STANDARD, // 屋 + 0x61B6, KANJI_STANDARD, // 憶 + 0x81C6, KANJI_STANDARD, // 臆 + 0x6876, KANJI_STANDARD, // æ¡¶ + 0x7261, KANJI_STANDARD, // 牡 + 0x4E59, KANJI_STANDARD, // 乙 + 0x4FFA, KANJI_STANDARD, // 俺 + 0x5378, KANJI_STANDARD, // 卞 + 0x6069, KANJI_STANDARD, // 恩 + 0x6E29, KANJI_STANDARD, // æž© + 0x7A4F, KANJI_STANDARD, // 穏 + 0x97F3, KANJI_STANDARD, // 音 + 0x4E0B, KANJI_STANDARD, // 例 + 0x5316, KANJI_STANDARD, // 化 + 0x4EEE, KANJI_STANDARD, // ä»® + 0x4F55, KANJI_STANDARD, // 䜕 + 0x4F3D, KANJI_STANDARD, // 䌜 + 0x4FA1, KANJI_STANDARD, // 䟡 + 0x4F73, KANJI_STANDARD, // 䜳 + 0x52A0, KANJI_STANDARD, // 加 + 0x53EF, KANJI_STANDARD, // 可 + 0x5609, KANJI_STANDARD, // 嘉 + 0x590F, KANJI_STANDARD, // 倏 + 0x5AC1, KANJI_STANDARD, // 嫁 + 0x5BB6, KANJI_STANDARD, // å®¶ + 0x5BE1, KANJI_STANDARD, // 寡 + 0x79D1, KANJI_STANDARD, // 科 + 0x6687, KANJI_STANDARD, // 暇 + 0x679C, KANJI_STANDARD, // 果 + 0x67B6, KANJI_STANDARD, // 架 + 0x6B4C, KANJI_STANDARD, // 歌 + 0x6CB3, KANJI_STANDARD, // æ²³ + 0x706B, KANJI_STANDARD, // 火 + 0x73C2, KANJI_STANDARD, // 珂 + 0x798D, KANJI_STANDARD, // 犍 + 0x79BE, KANJI_STANDARD, // 犟 + 0x7A3C, KANJI_STANDARD, // 皌 + 0x7B87, KANJI_STANDARD, // 箇 + 0x82B1, KANJI_STANDARD, // 花 + 0x82DB, KANJI_STANDARD, // 苛 + 0x8304, KANJI_STANDARD, // 茄 + 0x8377, KANJI_STANDARD, // 荷 + 0x83EF, KANJI_STANDARD, // 華 + 0x83D3, KANJI_STANDARD, // 菓 + 0x8766, KANJI_STANDARD, // 蝊 + 0x8AB2, KANJI_STANDARD, // 課 + 0x5629, KANJI_STANDARD, // 嘩 + 0x8CA8, KANJI_STANDARD, // 貚 + 0x8FE6, KANJI_STANDARD, // 迊 + 0x904E, KANJI_STANDARD, // 過 + 0x971E, KANJI_STANDARD, // 霞 + 0x868A, KANJI_STANDARD, // 蚊 + 0x4FC4, KANJI_STANDARD, // 俄 + 0x5CE8, KANJI_STANDARD, // 峚 + 0x6211, KANJI_STANDARD, // 我 + 0x7259, KANJI_STANDARD, // 牙 + 0x753B, KANJI_STANDARD, // 画 + 0x81E5, KANJI_STANDARD, // 臥 + 0x82BD, KANJI_STANDARD, // 芜 + 0x86FE, KANJI_STANDARD, // 蛟 + 0x8CC0, KANJI_STANDARD, // 賀 + 0x96C5, KANJI_STANDARD, // 雅 + 0x9913, KANJI_STANDARD, // 逓 + 0x99D5, KANJI_STANDARD, // 駕 + 0x4ECB, KANJI_STANDARD, // 介 + 0x4F1A, KANJI_STANDARD, // 䌚 + 0x89E3, KANJI_STANDARD, // è§£ + 0x56DE, KANJI_STANDARD, // 回 + 0x584A, KANJI_STANDARD, // 塊 + 0x58CA, KANJI_STANDARD, // 壊 + 0x5EFB, KANJI_STANDARD, // å»» + 0x5FEB, KANJI_STANDARD, // å¿« + 0x602A, KANJI_STANDARD, // 怪 + 0x6094, KANJI_STANDARD, // 悔 + 0x6062, KANJI_STANDARD, // 恢 + 0x61D0, KANJI_STANDARD, // 懐 + 0x6212, KANJI_STANDARD, // 戒 + 0x62D0, KANJI_STANDARD, // 拐 + 0x6539, KANJI_STANDARD, // 改 + 0x9B41, KANJI_STANDARD, // 魁 + 0x6666, KANJI_STANDARD, // 晊 + 0x68B0, KANJI_STANDARD, // 械 + 0x6D77, KANJI_STANDARD, // æµ· + 0x7070, KANJI_STANDARD, // 灰 + 0x754C, KANJI_STANDARD, // 界 + 0x7686, KANJI_STANDARD, // 皆 + 0x7D75, KANJI_STANDARD, // çµµ + 0x82A5, KANJI_STANDARD, // 芥 + 0x87F9, KANJI_STANDARD, // 蟹 + 0x958B, KANJI_STANDARD, // 開 + 0x968E, KANJI_STANDARD, // 階 + 0x8C9D, KANJI_STANDARD, // 貝 + 0x51F1, KANJI_STANDARD, // 凱 + 0x52BE, KANJI_STANDARD, // 功 + 0x5916, KANJI_STANDARD, // 倖 + 0x54B3, KANJI_STANDARD, // 咳 + 0x5BB3, KANJI_STANDARD, // 害 + 0x5D16, KANJI_STANDARD, // 厖 + 0x6168, KANJI_STANDARD, // æ…š + 0x6982, KANJI_STANDARD, // 抂 + 0x6DAF, KANJI_STANDARD, // 涯 + 0x788D, KANJI_STANDARD, // 碍 + 0x84CB, KANJI_STANDARD, // 蓋 + 0x8857, KANJI_STANDARD, // 街 + 0x8A72, KANJI_STANDARD, // 該 + 0x93A7, KANJI_STANDARD, // 鎧 + 0x9AB8, KANJI_STANDARD, // 骞 + 0x6D6C, KANJI_STANDARD, // 浬 + 0x99A8, KANJI_STANDARD, // 銚 + 0x86D9, KANJI_STANDARD, // 蛙 + 0x57A3, KANJI_STANDARD, // 垣 + 0x67FF, KANJI_STANDARD, // 柿 + 0x86CE, KANJI_STANDARD, // 蛎 + 0x920E, KANJI_STANDARD, // 鈎 + 0x5283, KANJI_STANDARD, // 劃 + 0x5687, KANJI_STANDARD, // 嚇 + 0x5404, KANJI_STANDARD, // 各 + 0x5ED3, KANJI_STANDARD, // 廓 + 0x62E1, KANJI_STANDARD, // 拡 + 0x64B9, KANJI_STANDARD, // 撹 + 0x683C, KANJI_STANDARD, // æ Œ + 0x6838, KANJI_STANDARD, // æ ž + 0x6BBB, KANJI_STANDARD, // æ®» + 0x7372, KANJI_STANDARD, // 獲 + 0x78BA, KANJI_STANDARD, // 確 + 0x7A6B, KANJI_STANDARD, // ç©« + 0x899A, KANJI_STANDARD, // 芚 + 0x89D2, KANJI_STANDARD, // 角 + 0x8D6B, KANJI_STANDARD, // 赫 + 0x8F03, KANJI_STANDARD, // 范 + 0x90ED, KANJI_STANDARD, // 郭 + 0x95A3, KANJI_STANDARD, // 閣 + 0x9694, KANJI_STANDARD, // 隔 + 0x9769, KANJI_STANDARD, // 革 + 0x5B66, KANJI_STANDARD, // å­Š + 0x5CB3, KANJI_STANDARD, // å²³ + 0x697D, KANJI_STANDARD, // 楜 + 0x984D, KANJI_STANDARD, // 額 + 0x984E, KANJI_STANDARD, // 顎 + 0x639B, KANJI_STANDARD, // 掛 + 0x7B20, KANJI_STANDARD, // 笠 + 0x6A2B, KANJI_STANDARD, // æš« + 0x6A7F, KANJI_STANDARD, // æ©¿ + 0x68B6, KANJI_STANDARD, // 梶 + 0x9C0D, KANJI_STANDARD, // 鰍 + 0x6F5F, KANJI_STANDARD, // 期 + 0x5272, KANJI_STANDARD, // 割 + 0x559D, KANJI_STANDARD, // 喝 + 0x6070, KANJI_STANDARD, // 恰 + 0x62EC, KANJI_STANDARD, // 括 + 0x6D3B, KANJI_STANDARD, // 掻 + 0x6E07, KANJI_STANDARD, // 枇 + 0x6ED1, KANJI_STANDARD, // 滑 + 0x845B, KANJI_STANDARD, // 葛 + 0x8910, KANJI_STANDARD, // 耐 + 0x8F44, KANJI_STANDARD, // 蜄 + 0x4E14, KANJI_STANDARD, // 侔 + 0x9C39, KANJI_STANDARD, // é°¹ + 0x53F6, KANJI_STANDARD, // 叶 + 0x691B, KANJI_STANDARD, // 怛 + 0x6A3A, KANJI_STANDARD, // 暺 + 0x9784, KANJI_STANDARD, // 鞄 + 0x682A, KANJI_STANDARD, // æ ª + 0x515C, KANJI_STANDARD, // 兜 + 0x7AC3, KANJI_STANDARD, // 竃 + 0x84B2, KANJI_STANDARD, // 蒲 + 0x91DC, KANJI_STANDARD, // 釜 + 0x938C, KANJI_STANDARD, // 鎌 + 0x565B, KANJI_STANDARD, // 噛 + 0x9D28, KANJI_STANDARD, // 鎚 + 0x6822, KANJI_STANDARD, // æ ¢ + 0x8305, KANJI_STANDARD, // 茅 + 0x8431, KANJI_STANDARD, // 萱 + 0x7CA5, KANJI_STANDARD, // ç²¥ + 0x5208, KANJI_STANDARD, // 刈 + 0x82C5, KANJI_STANDARD, // 苅 + 0x74E6, KANJI_STANDARD, // 瓩 + 0x4E7E, KANJI_STANDARD, // 也 + 0x4F83, KANJI_STANDARD, // 䟃 + 0x51A0, KANJI_STANDARD, // 冠 + 0x5BD2, KANJI_STANDARD, // 寒 + 0x520A, KANJI_STANDARD, // 刊 + 0x52D8, KANJI_STANDARD, // 勘 + 0x52E7, KANJI_STANDARD, // 勧 + 0x5DFB, KANJI_STANDARD, // å·» + 0x559A, KANJI_STANDARD, // 喚 + 0x582A, KANJI_STANDARD, // å ª + 0x59E6, KANJI_STANDARD, // å§Š + 0x5B8C, KANJI_STANDARD, // 完 + 0x5B98, KANJI_STANDARD, // 官 + 0x5BDB, KANJI_STANDARD, // 寛 + 0x5E72, KANJI_STANDARD, // å¹² + 0x5E79, KANJI_STANDARD, // å¹¹ + 0x60A3, KANJI_STANDARD, // 患 + 0x611F, KANJI_STANDARD, // 感 + 0x6163, KANJI_STANDARD, // 慣 + 0x61BE, KANJI_STANDARD, // 憟 + 0x63DB, KANJI_STANDARD, // 換 + 0x6562, KANJI_STANDARD, // 敢 + 0x67D1, KANJI_STANDARD, // 柑 + 0x6853, KANJI_STANDARD, // 桓 + 0x68FA, KANJI_STANDARD, // 棺 + 0x6B3E, KANJI_STANDARD, // 欟 + 0x6B53, KANJI_STANDARD, // 歓 + 0x6C57, KANJI_STANDARD, // 汗 + 0x6F22, KANJI_STANDARD, // 挢 + 0x6F97, KANJI_STANDARD, // 柗 + 0x6F45, KANJI_STANDARD, // 朅 + 0x74B0, KANJI_STANDARD, // 環 + 0x7518, KANJI_STANDARD, // 甘 + 0x76E3, KANJI_STANDARD, // 監 + 0x770B, KANJI_STANDARD, // 看 + 0x7AFF, KANJI_STANDARD, // ç«¿ + 0x7BA1, KANJI_STANDARD, // 管 + 0x7C21, KANJI_STANDARD, // ç°¡ + 0x7DE9, KANJI_STANDARD, // ç·© + 0x7F36, KANJI_STANDARD, // 猶 + 0x7FF0, KANJI_STANDARD, // ç¿° + 0x809D, KANJI_STANDARD, // 肝 + 0x8266, KANJI_STANDARD, // 艊 + 0x839E, KANJI_STANDARD, // 莞 + 0x89B3, KANJI_STANDARD, // 芳 + 0x8ACC, KANJI_STANDARD, // 諌 + 0x8CAB, KANJI_STANDARD, // 貫 + 0x9084, KANJI_STANDARD, // 還 + 0x9451, KANJI_STANDARD, // 鑑 + 0x9593, KANJI_STANDARD, // 間 + 0x9591, KANJI_STANDARD, // 閑 + 0x95A2, KANJI_STANDARD, // 関 + 0x9665, KANJI_STANDARD, // 陥 + 0x97D3, KANJI_STANDARD, // 韓 + 0x9928, KANJI_STANDARD, // 通 + 0x8218, KANJI_STANDARD, // 舘 + 0x4E38, KANJI_STANDARD, // äžž + 0x542B, KANJI_STANDARD, // 含 + 0x5CB8, KANJI_STANDARD, // 岞 + 0x5DCC, KANJI_STANDARD, // 巌 + 0x73A9, KANJI_STANDARD, // 玩 + 0x764C, KANJI_STANDARD, // 癌 + 0x773C, KANJI_STANDARD, // 県 + 0x5CA9, KANJI_STANDARD, // 岩 + 0x7FEB, KANJI_STANDARD, // ç¿« + 0x8D0B, KANJI_STANDARD, // 莋 + 0x96C1, KANJI_STANDARD, // 雁 + 0x9811, KANJI_STANDARD, // 頑 + 0x9854, KANJI_STANDARD, // 顔 + 0x9858, KANJI_STANDARD, // 願 + 0x4F01, KANJI_STANDARD, // 䌁 + 0x4F0E, KANJI_STANDARD, // 䌎 + 0x5371, KANJI_STANDARD, // 危 + 0x559C, KANJI_STANDARD, // 喜 + 0x5668, KANJI_STANDARD, // 噚 + 0x57FA, KANJI_STANDARD, // 基 + 0x5947, KANJI_STANDARD, // 奇 + 0x5B09, KANJI_STANDARD, // 嬉 + 0x5BC4, KANJI_STANDARD, // 寄 + 0x5C90, KANJI_STANDARD, // 岐 + 0x5E0C, KANJI_STANDARD, // 垌 + 0x5E7E, KANJI_STANDARD, // 幟 + 0x5FCC, KANJI_STANDARD, // 忌 + 0x63EE, KANJI_STANDARD, // 揮 + 0x673A, KANJI_STANDARD, // 机 + 0x65D7, KANJI_STANDARD, // 旗 + 0x65E2, KANJI_STANDARD, // 既 + 0x671F, KANJI_STANDARD, // 期 + 0x68CB, KANJI_STANDARD, // 棋 + 0x68C4, KANJI_STANDARD, // 棄 + 0x6A5F, KANJI_STANDARD, // 機 + 0x5E30, KANJI_STANDARD, // åž° + 0x6BC5, KANJI_STANDARD, // 毅 + 0x6C17, KANJI_STANDARD, // 気 + 0x6C7D, KANJI_STANDARD, // 汜 + 0x757F, KANJI_STANDARD, // 畿 + 0x7948, KANJI_STANDARD, // 祈 + 0x5B63, KANJI_STANDARD, // å­£ + 0x7A00, KANJI_STANDARD, // 繀 + 0x7D00, KANJI_STANDARD, // 简 + 0x5FBD, KANJI_STANDARD, // 埜 + 0x898F, KANJI_STANDARD, // 芏 + 0x8A18, KANJI_STANDARD, // 蚘 + 0x8CB4, KANJI_STANDARD, // 貎 + 0x8D77, KANJI_STANDARD, // èµ· + 0x8ECC, KANJI_STANDARD, // 軌 + 0x8F1D, KANJI_STANDARD, // 茝 + 0x98E2, KANJI_STANDARD, // 飢 + 0x9A0E, KANJI_STANDARD, // 階 + 0x9B3C, KANJI_STANDARD, // 鬌 + 0x4E80, KANJI_STANDARD, // 亀 + 0x507D, KANJI_STANDARD, // 停 + 0x5100, KANJI_STANDARD, // 儀 + 0x5993, KANJI_STANDARD, // 劓 + 0x5B9C, KANJI_STANDARD, // 宜 + 0x622F, KANJI_STANDARD, // 戯 + 0x6280, KANJI_STANDARD, // 技 + 0x64EC, KANJI_STANDARD, // 擬 + 0x6B3A, KANJI_STANDARD, // 欺 + 0x72A0, KANJI_STANDARD, // 犠 + 0x7591, KANJI_STANDARD, // 疑 + 0x7947, KANJI_STANDARD, // 祇 + 0x7FA9, KANJI_STANDARD, // 矩 + 0x87FB, KANJI_STANDARD, // 蟻 + 0x8ABC, KANJI_STANDARD, // 誌 + 0x8B70, KANJI_STANDARD, // è­° + 0x63AC, KANJI_STANDARD, // 掬 + 0x83CA, KANJI_STANDARD, // 菊 + 0x97A0, KANJI_STANDARD, // 鞠 + 0x5409, KANJI_STANDARD, // 吉 + 0x5403, KANJI_STANDARD, // 吃 + 0x55AB, KANJI_STANDARD, // 喫 + 0x6854, KANJI_STANDARD, // 桔 + 0x6A58, KANJI_STANDARD, // 橘 + 0x8A70, KANJI_STANDARD, // è©° + 0x7827, KANJI_STANDARD, // ç § + 0x6775, KANJI_STANDARD, // 杵 + 0x9ECD, KANJI_STANDARD, // 黍 + 0x5374, KANJI_STANDARD, // 华 + 0x5BA2, KANJI_STANDARD, // 客 + 0x811A, KANJI_STANDARD, // 脚 + 0x8650, KANJI_STANDARD, // 虐 + 0x9006, KANJI_STANDARD, // 逆 + 0x4E18, KANJI_STANDARD, // 䞘 + 0x4E45, KANJI_STANDARD, // 久 + 0x4EC7, KANJI_STANDARD, // 仇 + 0x4F11, KANJI_STANDARD, // 䌑 + 0x53CA, KANJI_STANDARD, // 及 + 0x5438, KANJI_STANDARD, // 吞 + 0x5BAE, KANJI_STANDARD, // å®® + 0x5F13, KANJI_STANDARD, // 匓 + 0x6025, KANJI_STANDARD, // 急 + 0x6551, KANJI_STANDARD, // 救 + 0x673D, KANJI_STANDARD, // 朜 + 0x6C42, KANJI_STANDARD, // 求 + 0x6C72, KANJI_STANDARD, // æ±² + 0x6CE3, KANJI_STANDARD, // æ³£ + 0x7078, KANJI_STANDARD, // 灞 + 0x7403, KANJI_STANDARD, // 球 + 0x7A76, KANJI_STANDARD, // ç©¶ + 0x7AAE, KANJI_STANDARD, // 窮 + 0x7B08, KANJI_STANDARD, // 笈 + 0x7D1A, KANJI_STANDARD, // 箚 + 0x7CFE, KANJI_STANDARD, // 糟 + 0x7D66, KANJI_STANDARD, // 絊 + 0x65E7, KANJI_STANDARD, // 旧 + 0x725B, KANJI_STANDARD, // 牛 + 0x53BB, KANJI_STANDARD, // 去 + 0x5C45, KANJI_STANDARD, // 居 + 0x5DE8, KANJI_STANDARD, // å·š + 0x62D2, KANJI_STANDARD, // 拒 + 0x62E0, KANJI_STANDARD, // 拠 + 0x6319, KANJI_STANDARD, // 挙 + 0x6E20, KANJI_STANDARD, // æž  + 0x865A, KANJI_STANDARD, // 虚 + 0x8A31, KANJI_STANDARD, // èš± + 0x8DDD, KANJI_STANDARD, // 距 + 0x92F8, KANJI_STANDARD, // 鋾 + 0x6F01, KANJI_STANDARD, // 持 + 0x79A6, KANJI_STANDARD, // 犊 + 0x9B5A, KANJI_STANDARD, // 魚 + 0x4EA8, KANJI_STANDARD, // 亚 + 0x4EAB, KANJI_STANDARD, // 享 + 0x4EAC, KANJI_STANDARD, // 京 + 0x4F9B, KANJI_STANDARD, // 䟛 + 0x4FA0, KANJI_STANDARD, // 䟠 + 0x50D1, KANJI_STANDARD, // 僑 + 0x5147, KANJI_STANDARD, // 兇 + 0x7AF6, KANJI_STANDARD, // ç«¶ + 0x5171, KANJI_STANDARD, // 共 + 0x51F6, KANJI_STANDARD, // 凶 + 0x5354, KANJI_STANDARD, // 協 + 0x5321, KANJI_STANDARD, // 匡 + 0x537F, KANJI_STANDARD, // 卿 + 0x53EB, KANJI_STANDARD, // 叫 + 0x55AC, KANJI_STANDARD, // 喬 + 0x5883, KANJI_STANDARD, // 境 + 0x5CE1, KANJI_STANDARD, // 峡 + 0x5F37, KANJI_STANDARD, // 匷 + 0x5F4A, KANJI_STANDARD, // 圊 + 0x602F, KANJI_STANDARD, // 怯 + 0x6050, KANJI_STANDARD, // 恐 + 0x606D, KANJI_STANDARD, // 恭 + 0x631F, KANJI_STANDARD, // 挟 + 0x6559, KANJI_STANDARD, // 教 + 0x6A4B, KANJI_STANDARD, // 橋 + 0x6CC1, KANJI_STANDARD, // 況 + 0x72C2, KANJI_STANDARD, // 狂 + 0x72ED, KANJI_STANDARD, // 狭 + 0x77EF, KANJI_STANDARD, // 矯 + 0x80F8, KANJI_STANDARD, // 胞 + 0x8105, KANJI_STANDARD, // 脅 + 0x8208, KANJI_STANDARD, // 興 + 0x854E, KANJI_STANDARD, // 蕎 + 0x90F7, KANJI_STANDARD, // 郷 + 0x93E1, KANJI_STANDARD, // 鏡 + 0x97FF, KANJI_STANDARD, // 響 + 0x9957, KANJI_STANDARD, // 饗 + 0x9A5A, KANJI_STANDARD, // 驚 + 0x4EF0, KANJI_STANDARD, // ä»° + 0x51DD, KANJI_STANDARD, // 凝 + 0x5C2D, KANJI_STANDARD, // å°­ + 0x6681, KANJI_STANDARD, // 暁 + 0x696D, KANJI_STANDARD, // 業 + 0x5C40, KANJI_STANDARD, // 局 + 0x66F2, KANJI_STANDARD, // 曲 + 0x6975, KANJI_STANDARD, // 極 + 0x7389, KANJI_STANDARD, // 玉 + 0x6850, KANJI_STANDARD, // 桐 + 0x7C81, KANJI_STANDARD, // 粁 + 0x50C5, KANJI_STANDARD, // 僅 + 0x52E4, KANJI_STANDARD, // å‹€ + 0x5747, KANJI_STANDARD, // 均 + 0x5DFE, KANJI_STANDARD, // å·Ÿ + 0x9326, KANJI_STANDARD, // 錩 + 0x65A4, KANJI_STANDARD, // æ–€ + 0x6B23, KANJI_STANDARD, // 欣 + 0x6B3D, KANJI_STANDARD, // 欜 + 0x7434, KANJI_STANDARD, // 琎 + 0x7981, KANJI_STANDARD, // 犁 + 0x79BD, KANJI_STANDARD, // 犜 + 0x7B4B, KANJI_STANDARD, // 筋 + 0x7DCA, KANJI_STANDARD, // 緊 + 0x82B9, KANJI_STANDARD, // 芹 + 0x83CC, KANJI_STANDARD, // 菌 + 0x887F, KANJI_STANDARD, // è¡¿ + 0x895F, KANJI_STANDARD, // 襟 + 0x8B39, KANJI_STANDARD, // 謹 + 0x8FD1, KANJI_STANDARD, // 近 + 0x91D1, KANJI_STANDARD, // 金 + 0x541F, KANJI_STANDARD, // 吟 + 0x9280, KANJI_STANDARD, // 銀 + 0x4E5D, KANJI_STANDARD, // 九 + 0x5036, KANJI_STANDARD, // 倶 + 0x53E5, KANJI_STANDARD, // 句 + 0x533A, KANJI_STANDARD, // 区 + 0x72D7, KANJI_STANDARD, // 狗 + 0x7396, KANJI_STANDARD, // 玖 + 0x77E9, KANJI_STANDARD, // 矩 + 0x82E6, KANJI_STANDARD, // 苊 + 0x8EAF, KANJI_STANDARD, // 躯 + 0x99C6, KANJI_STANDARD, // 駆 + 0x99C8, KANJI_STANDARD, // 駈 + 0x99D2, KANJI_STANDARD, // 駒 + 0x5177, KANJI_STANDARD, // 具 + 0x611A, KANJI_STANDARD, // 愚 + 0x865E, KANJI_STANDARD, // 虞 + 0x55B0, KANJI_STANDARD, // 喰 + 0x7A7A, KANJI_STANDARD, // 空 + 0x5076, KANJI_STANDARD, // 偶 + 0x5BD3, KANJI_STANDARD, // 寓 + 0x9047, KANJI_STANDARD, // 遇 + 0x9685, KANJI_STANDARD, // 隅 + 0x4E32, KANJI_STANDARD, // äž² + 0x6ADB, KANJI_STANDARD, // 櫛 + 0x91E7, KANJI_STANDARD, // 釧 + 0x5C51, KANJI_STANDARD, // 屑 + 0x5C48, KANJI_STANDARD, // 屈 + 0x6398, KANJI_STANDARD, // 掘 + 0x7A9F, KANJI_STANDARD, // 窟 + 0x6C93, KANJI_STANDARD, // 沓 + 0x9774, KANJI_STANDARD, // 靎 + 0x8F61, KANJI_STANDARD, // 蜡 + 0x7AAA, KANJI_STANDARD, // 窪 + 0x718A, KANJI_STANDARD, // 熊 + 0x9688, KANJI_STANDARD, // 隈 + 0x7C82, KANJI_STANDARD, // 粂 + 0x6817, KANJI_STANDARD, // 栗 + 0x7E70, KANJI_STANDARD, // ç¹° + 0x6851, KANJI_STANDARD, // 桑 + 0x936C, KANJI_STANDARD, // 鍬 + 0x52F2, KANJI_STANDARD, // 勲 + 0x541B, KANJI_STANDARD, // 君 + 0x85AB, KANJI_STANDARD, // 薫 + 0x8A13, KANJI_STANDARD, // èš“ + 0x7FA4, KANJI_STANDARD, // 矀 + 0x8ECD, KANJI_STANDARD, // 軍 + 0x90E1, KANJI_STANDARD, // 郡 + 0x5366, KANJI_STANDARD, // 半 + 0x8888, KANJI_STANDARD, // 袈 + 0x7941, KANJI_STANDARD, // 祁 + 0x4FC2, KANJI_STANDARD, // 係 + 0x50BE, KANJI_STANDARD, // 傟 + 0x5211, KANJI_STANDARD, // 刑 + 0x5144, KANJI_STANDARD, // 兄 + 0x5553, KANJI_STANDARD, // 啓 + 0x572D, KANJI_STANDARD, // 圭 + 0x73EA, KANJI_STANDARD, // 珪 + 0x578B, KANJI_STANDARD, // 型 + 0x5951, KANJI_STANDARD, // 契 + 0x5F62, KANJI_STANDARD, // 圢 + 0x5F84, KANJI_STANDARD, // 埄 + 0x6075, KANJI_STANDARD, // 恵 + 0x6176, KANJI_STANDARD, // 慶 + 0x6167, KANJI_STANDARD, // 慧 + 0x61A9, KANJI_STANDARD, // 憩 + 0x63B2, KANJI_STANDARD, // 掲 + 0x643A, KANJI_STANDARD, // 携 + 0x656C, KANJI_STANDARD, // 敬 + 0x666F, KANJI_STANDARD, // 景 + 0x6842, KANJI_STANDARD, // 桂 + 0x6E13, KANJI_STANDARD, // æž“ + 0x7566, KANJI_STANDARD, // 畩 + 0x7A3D, KANJI_STANDARD, // çšœ + 0x7CFB, KANJI_STANDARD, // ç³» + 0x7D4C, KANJI_STANDARD, // 経 + 0x7D99, KANJI_STANDARD, // 継 + 0x7E4B, KANJI_STANDARD, // 繋 + 0x7F6B, KANJI_STANDARD, // 眫 + 0x830E, KANJI_STANDARD, // 茎 + 0x834A, KANJI_STANDARD, // 荊 + 0x86CD, KANJI_STANDARD, // 蛍 + 0x8A08, KANJI_STANDARD, // 蚈 + 0x8A63, KANJI_STANDARD, // è©£ + 0x8B66, KANJI_STANDARD, // è­Š + 0x8EFD, KANJI_STANDARD, // 軜 + 0x981A, KANJI_STANDARD, // 頚 + 0x9D8F, KANJI_STANDARD, // 鶏 + 0x82B8, KANJI_STANDARD, // 芞 + 0x8FCE, KANJI_STANDARD, // 迎 + 0x9BE8, KANJI_STANDARD, // 鯚 + 0x5287, KANJI_STANDARD, // 劇 + 0x621F, KANJI_STANDARD, // 戟 + 0x6483, KANJI_STANDARD, // 撃 + 0x6FC0, KANJI_STANDARD, // 激 + 0x9699, KANJI_STANDARD, // 隙 + 0x6841, KANJI_STANDARD, // 桁 + 0x5091, KANJI_STANDARD, // 傑 + 0x6B20, KANJI_STANDARD, // 欠 + 0x6C7A, KANJI_STANDARD, // 決 + 0x6F54, KANJI_STANDARD, // 朔 + 0x7A74, KANJI_STANDARD, // 穎 + 0x7D50, KANJI_STANDARD, // 結 + 0x8840, KANJI_STANDARD, // 血 + 0x8A23, KANJI_STANDARD, // 蚣 + 0x6708, KANJI_STANDARD, // 月 + 0x4EF6, KANJI_STANDARD, // ä»¶ + 0x5039, KANJI_STANDARD, // 倹 + 0x5026, KANJI_STANDARD, // 倊 + 0x5065, KANJI_STANDARD, // 健 + 0x517C, KANJI_STANDARD, // å…Œ + 0x5238, KANJI_STANDARD, // 刞 + 0x5263, KANJI_STANDARD, // 剣 + 0x55A7, KANJI_STANDARD, // 喧 + 0x570F, KANJI_STANDARD, // 圏 + 0x5805, KANJI_STANDARD, // 堅 + 0x5ACC, KANJI_STANDARD, // 嫌 + 0x5EFA, KANJI_STANDARD, // 建 + 0x61B2, KANJI_STANDARD, // 憲 + 0x61F8, KANJI_STANDARD, // 懞 + 0x62F3, KANJI_STANDARD, // 拳 + 0x6372, KANJI_STANDARD, // 捲 + 0x691C, KANJI_STANDARD, // 怜 + 0x6A29, KANJI_STANDARD, // æš© + 0x727D, KANJI_STANDARD, // 牜 + 0x72AC, KANJI_STANDARD, // 犬 + 0x732E, KANJI_STANDARD, // 献 + 0x7814, KANJI_STANDARD, // 研 + 0x786F, KANJI_STANDARD, // 硯 + 0x7D79, KANJI_STANDARD, // çµ¹ + 0x770C, KANJI_STANDARD, // 県 + 0x80A9, KANJI_STANDARD, // 肩 + 0x898B, KANJI_STANDARD, // 芋 + 0x8B19, KANJI_STANDARD, // 謙 + 0x8CE2, KANJI_STANDARD, // è³¢ + 0x8ED2, KANJI_STANDARD, // 軒 + 0x9063, KANJI_STANDARD, // 遣 + 0x9375, KANJI_STANDARD, // 鍵 + 0x967A, KANJI_STANDARD, // 険 + 0x9855, KANJI_STANDARD, // 顕 + 0x9A13, KANJI_STANDARD, // 鹓 + 0x9E78, KANJI_STANDARD, // 鹞 + 0x5143, KANJI_STANDARD, // 元 + 0x539F, KANJI_STANDARD, // 原 + 0x53B3, KANJI_STANDARD, // 厳 + 0x5E7B, KANJI_STANDARD, // å¹» + 0x5F26, KANJI_STANDARD, // 匊 + 0x6E1B, KANJI_STANDARD, // æž› + 0x6E90, KANJI_STANDARD, // 源 + 0x7384, KANJI_STANDARD, // 玄 + 0x73FE, KANJI_STANDARD, // 珟 + 0x7D43, KANJI_STANDARD, // 絃 + 0x8237, KANJI_STANDARD, // 舷 + 0x8A00, KANJI_STANDARD, // 蚀 + 0x8AFA, KANJI_STANDARD, // 諺 + 0x9650, KANJI_STANDARD, // 限 + 0x4E4E, KANJI_STANDARD, // 乎 + 0x500B, KANJI_STANDARD, // 個 + 0x53E4, KANJI_STANDARD, // 叀 + 0x547C, KANJI_STANDARD, // 呌 + 0x56FA, KANJI_STANDARD, // 固 + 0x59D1, KANJI_STANDARD, // 姑 + 0x5B64, KANJI_STANDARD, // å­€ + 0x5DF1, KANJI_STANDARD, // å·± + 0x5EAB, KANJI_STANDARD, // 庫 + 0x5F27, KANJI_STANDARD, // 匧 + 0x6238, KANJI_STANDARD, // 戞 + 0x6545, KANJI_STANDARD, // 故 + 0x67AF, KANJI_STANDARD, // 枯 + 0x6E56, KANJI_STANDARD, // 湖 + 0x72D0, KANJI_STANDARD, // 狐 + 0x7CCA, KANJI_STANDARD, // 糊 + 0x88B4, KANJI_STANDARD, // 袎 + 0x80A1, KANJI_STANDARD, // 股 + 0x80E1, KANJI_STANDARD, // 胡 + 0x83F0, KANJI_STANDARD, // 菰 + 0x864E, KANJI_STANDARD, // 虎 + 0x8A87, KANJI_STANDARD, // 誇 + 0x8DE8, KANJI_STANDARD, // è·š + 0x9237, KANJI_STANDARD, // 鈷 + 0x96C7, KANJI_STANDARD, // 雇 + 0x9867, KANJI_STANDARD, // é¡§ + 0x9F13, KANJI_STANDARD, // 錓 + 0x4E94, KANJI_STANDARD, // 五 + 0x4E92, KANJI_STANDARD, // 互 + 0x4F0D, KANJI_STANDARD, // 䌍 + 0x5348, KANJI_STANDARD, // 午 + 0x5449, KANJI_STANDARD, // 呉 + 0x543E, KANJI_STANDARD, // 吟 + 0x5A2F, KANJI_STANDARD, // 嚯 + 0x5F8C, KANJI_STANDARD, // 埌 + 0x5FA1, KANJI_STANDARD, // 埡 + 0x609F, KANJI_STANDARD, // 悟 + 0x68A7, KANJI_STANDARD, // 梧 + 0x6A8E, KANJI_STANDARD, // 檎 + 0x745A, KANJI_STANDARD, // 瑚 + 0x7881, KANJI_STANDARD, // 碁 + 0x8A9E, KANJI_STANDARD, // 語 + 0x8AA4, KANJI_STANDARD, // 誀 + 0x8B77, KANJI_STANDARD, // è­· + 0x9190, KANJI_STANDARD, // 醐 + 0x4E5E, KANJI_STANDARD, // 乞 + 0x9BC9, KANJI_STANDARD, // 鯉 + 0x4EA4, KANJI_STANDARD, // 亀 + 0x4F7C, KANJI_STANDARD, // 䜌 + 0x4FAF, KANJI_STANDARD, // 䟯 + 0x5019, KANJI_STANDARD, // 候 + 0x5016, KANJI_STANDARD, // 倖 + 0x5149, KANJI_STANDARD, // 光 + 0x516C, KANJI_STANDARD, // 公 + 0x529F, KANJI_STANDARD, // 功 + 0x52B9, KANJI_STANDARD, // 効 + 0x52FE, KANJI_STANDARD, // 募 + 0x539A, KANJI_STANDARD, // 厚 + 0x53E3, KANJI_STANDARD, // 口 + 0x5411, KANJI_STANDARD, // 向 + 0x540E, KANJI_STANDARD, // 后 + 0x5589, KANJI_STANDARD, // 喉 + 0x5751, KANJI_STANDARD, // 坑 + 0x57A2, KANJI_STANDARD, // 垢 + 0x597D, KANJI_STANDARD, // 奜 + 0x5B54, KANJI_STANDARD, // 孔 + 0x5B5D, KANJI_STANDARD, // 孝 + 0x5B8F, KANJI_STANDARD, // 宏 + 0x5DE5, KANJI_STANDARD, // å·¥ + 0x5DE7, KANJI_STANDARD, // å·§ + 0x5DF7, KANJI_STANDARD, // å·· + 0x5E78, KANJI_STANDARD, // 幞 + 0x5E83, KANJI_STANDARD, // 広 + 0x5E9A, KANJI_STANDARD, // 庚 + 0x5EB7, KANJI_STANDARD, // 康 + 0x5F18, KANJI_STANDARD, // 匘 + 0x6052, KANJI_STANDARD, // 恒 + 0x614C, KANJI_STANDARD, // 慌 + 0x6297, KANJI_STANDARD, // 抗 + 0x62D8, KANJI_STANDARD, // 拘 + 0x63A7, KANJI_STANDARD, // 控 + 0x653B, KANJI_STANDARD, // 攻 + 0x6602, KANJI_STANDARD, // 昂 + 0x6643, KANJI_STANDARD, // 晃 + 0x66F4, KANJI_STANDARD, // 曎 + 0x676D, KANJI_STANDARD, // 杭 + 0x6821, KANJI_STANDARD, // æ ¡ + 0x6897, KANJI_STANDARD, // 梗 + 0x69CB, KANJI_STANDARD, // 構 + 0x6C5F, KANJI_STANDARD, // 江 + 0x6D2A, KANJI_STANDARD, // 措 + 0x6D69, KANJI_STANDARD, // 浩 + 0x6E2F, KANJI_STANDARD, // 枯 + 0x6E9D, KANJI_STANDARD, // 溝 + 0x7532, KANJI_STANDARD, // 甲 + 0x7687, KANJI_STANDARD, // 皇 + 0x786C, KANJI_STANDARD, // 硬 + 0x7A3F, KANJI_STANDARD, // çš¿ + 0x7CE0, KANJI_STANDARD, // ç³  + 0x7D05, KANJI_STANDARD, // 箅 + 0x7D18, KANJI_STANDARD, // 玘 + 0x7D5E, KANJI_STANDARD, // 絞 + 0x7DB1, KANJI_STANDARD, // ç¶± + 0x8015, KANJI_STANDARD, // 耕 + 0x8003, KANJI_STANDARD, // 考 + 0x80AF, KANJI_STANDARD, // 肯 + 0x80B1, KANJI_STANDARD, // 肱 + 0x8154, KANJI_STANDARD, // 腔 + 0x818F, KANJI_STANDARD, // 膏 + 0x822A, KANJI_STANDARD, // 航 + 0x8352, KANJI_STANDARD, // 荒 + 0x884C, KANJI_STANDARD, // 行 + 0x8861, KANJI_STANDARD, // è¡¡ + 0x8B1B, KANJI_STANDARD, // 講 + 0x8CA2, KANJI_STANDARD, // è²¢ + 0x8CFC, KANJI_STANDARD, // 賌 + 0x90CA, KANJI_STANDARD, // 郊 + 0x9175, KANJI_STANDARD, // 酵 + 0x9271, KANJI_STANDARD, // 鉱 + 0x783F, KANJI_STANDARD, // ç ¿ + 0x92FC, KANJI_STANDARD, // 鋌 + 0x95A4, KANJI_STANDARD, // é–€ + 0x964D, KANJI_STANDARD, // 降 + 0x9805, KANJI_STANDARD, // 項 + 0x9999, KANJI_STANDARD, // 驙 + 0x9AD8, KANJI_STANDARD, // 高 + 0x9D3B, KANJI_STANDARD, // 鎻 + 0x525B, KANJI_STANDARD, // 剛 + 0x52AB, KANJI_STANDARD, // 劫 + 0x53F7, KANJI_STANDARD, // 号 + 0x5408, KANJI_STANDARD, // 合 + 0x58D5, KANJI_STANDARD, // 壕 + 0x62F7, KANJI_STANDARD, // 拷 + 0x6FE0, KANJI_STANDARD, // æ¿  + 0x8C6A, KANJI_STANDARD, // 豪 + 0x8F5F, KANJI_STANDARD, // 蜟 + 0x9EB9, KANJI_STANDARD, // 麹 + 0x514B, KANJI_STANDARD, // 克 + 0x523B, KANJI_STANDARD, // 刻 + 0x544A, KANJI_STANDARD, // 告 + 0x56FD, KANJI_STANDARD, // 囜 + 0x7A40, KANJI_STANDARD, // 穀 + 0x9177, KANJI_STANDARD, // 酷 + 0x9D60, KANJI_STANDARD, // éµ  + 0x9ED2, KANJI_STANDARD, // 黒 + 0x7344, KANJI_STANDARD, // 獄 + 0x6F09, KANJI_STANDARD, // 按 + 0x8170, KANJI_STANDARD, // 腰 + 0x7511, KANJI_STANDARD, // 甑 + 0x5FFD, KANJI_STANDARD, // 応 + 0x60DA, KANJI_STANDARD, // 惚 + 0x9AA8, KANJI_STANDARD, // 骚 + 0x72DB, KANJI_STANDARD, // 狛 + 0x8FBC, KANJI_STANDARD, // 蟌 + 0x6B64, KANJI_STANDARD, // æ­€ + 0x9803, KANJI_STANDARD, // 頃 + 0x4ECA, KANJI_STANDARD, // 今 + 0x56F0, KANJI_STANDARD, // 困 + 0x5764, KANJI_STANDARD, // 址 + 0x58BE, KANJI_STANDARD, // 墟 + 0x5A5A, KANJI_STANDARD, // 婚 + 0x6068, KANJI_STANDARD, // 恚 + 0x61C7, KANJI_STANDARD, // 懇 + 0x660F, KANJI_STANDARD, // 昏 + 0x6606, KANJI_STANDARD, // 昆 + 0x6839, KANJI_STANDARD, // æ ¹ + 0x68B1, KANJI_STANDARD, // 梱 + 0x6DF7, KANJI_STANDARD, // æ·· + 0x75D5, KANJI_STANDARD, // 痕 + 0x7D3A, KANJI_STANDARD, // 玺 + 0x826E, KANJI_STANDARD, // 艮 + 0x9B42, KANJI_STANDARD, // 魂 + 0x4E9B, KANJI_STANDARD, // 些 + 0x4F50, KANJI_STANDARD, // 䜐 + 0x53C9, KANJI_STANDARD, // 叉 + 0x5506, KANJI_STANDARD, // 唆 + 0x5D6F, KANJI_STANDARD, // 嵯 + 0x5DE6, KANJI_STANDARD, // å·Š + 0x5DEE, KANJI_STANDARD, // å·® + 0x67FB, KANJI_STANDARD, // 査 + 0x6C99, KANJI_STANDARD, // 沙 + 0x7473, KANJI_STANDARD, // 瑳 + 0x7802, KANJI_STANDARD, // 砂 + 0x8A50, KANJI_STANDARD, // 詐 + 0x9396, KANJI_STANDARD, // 鎖 + 0x88DF, KANJI_STANDARD, // 裟 + 0x5750, KANJI_STANDARD, // 坐 + 0x5EA7, KANJI_STANDARD, // 座 + 0x632B, KANJI_STANDARD, // 挫 + 0x50B5, KANJI_STANDARD, // 債 + 0x50AC, KANJI_STANDARD, // 催 + 0x518D, KANJI_STANDARD, // 再 + 0x6700, KANJI_STANDARD, // 最 + 0x54C9, KANJI_STANDARD, // 哉 + 0x585E, KANJI_STANDARD, // 塞 + 0x59BB, KANJI_STANDARD, // 劻 + 0x5BB0, KANJI_STANDARD, // å®° + 0x5F69, KANJI_STANDARD, // 圩 + 0x624D, KANJI_STANDARD, // 才 + 0x63A1, KANJI_STANDARD, // 採 + 0x683D, KANJI_STANDARD, // æ œ + 0x6B73, KANJI_STANDARD, // æ­³ + 0x6E08, KANJI_STANDARD, // 枈 + 0x707D, KANJI_STANDARD, // 灜 + 0x91C7, KANJI_STANDARD, // 采 + 0x7280, KANJI_STANDARD, // 犀 + 0x7815, KANJI_STANDARD, // 砕 + 0x7826, KANJI_STANDARD, // ç Š + 0x796D, KANJI_STANDARD, // 祭 + 0x658E, KANJI_STANDARD, // 斎 + 0x7D30, KANJI_STANDARD, // 现 + 0x83DC, KANJI_STANDARD, // 菜 + 0x88C1, KANJI_STANDARD, // 裁 + 0x8F09, KANJI_STANDARD, // 茉 + 0x969B, KANJI_STANDARD, // 際 + 0x5264, KANJI_STANDARD, // 剀 + 0x5728, KANJI_STANDARD, // 圚 + 0x6750, KANJI_STANDARD, // 材 + 0x7F6A, KANJI_STANDARD, // 眪 + 0x8CA1, KANJI_STANDARD, // 財 + 0x51B4, KANJI_STANDARD, // 冎 + 0x5742, KANJI_STANDARD, // 坂 + 0x962A, KANJI_STANDARD, // 阪 + 0x583A, KANJI_STANDARD, // å º + 0x698A, KANJI_STANDARD, // 把 + 0x80B4, KANJI_STANDARD, // 肎 + 0x54B2, KANJI_STANDARD, // 咲 + 0x5D0E, KANJI_STANDARD, // 厎 + 0x57FC, KANJI_STANDARD, // 埌 + 0x7895, KANJI_STANDARD, // 碕 + 0x9DFA, KANJI_STANDARD, // é·º + 0x4F5C, KANJI_STANDARD, // 䜜 + 0x524A, KANJI_STANDARD, // 削 + 0x548B, KANJI_STANDARD, // 咋 + 0x643E, KANJI_STANDARD, // 搟 + 0x6628, KANJI_STANDARD, // 昚 + 0x6714, KANJI_STANDARD, // 朔 + 0x67F5, KANJI_STANDARD, // 柵 + 0x7A84, KANJI_STANDARD, // 窄 + 0x7B56, KANJI_STANDARD, // 策 + 0x7D22, KANJI_STANDARD, // 玢 + 0x932F, KANJI_STANDARD, // 錯 + 0x685C, KANJI_STANDARD, // 桜 + 0x9BAD, KANJI_STANDARD, // é®­ + 0x7B39, KANJI_STANDARD, // 笹 + 0x5319, KANJI_STANDARD, // 匙 + 0x518A, KANJI_STANDARD, // 冊 + 0x5237, KANJI_STANDARD, // 刷 + 0x5BDF, KANJI_STANDARD, // 察 + 0x62F6, KANJI_STANDARD, // 拶 + 0x64AE, KANJI_STANDARD, // 撮 + 0x64E6, KANJI_STANDARD, // 擊 + 0x672D, KANJI_STANDARD, // 札 + 0x6BBA, KANJI_STANDARD, // 殺 + 0x85A9, KANJI_STANDARD, // 薩 + 0x96D1, KANJI_STANDARD, // 雑 + 0x7690, KANJI_STANDARD, // 皐 + 0x9BD6, KANJI_STANDARD, // 鯖 + 0x634C, KANJI_STANDARD, // 捌 + 0x9306, KANJI_STANDARD, // 錆 + 0x9BAB, KANJI_STANDARD, // 鮫 + 0x76BF, KANJI_STANDARD, // 皿 + 0x6652, KANJI_STANDARD, // 晒 + 0x4E09, KANJI_STANDARD, // 侉 + 0x5098, KANJI_STANDARD, // 傘 + 0x53C2, KANJI_STANDARD, // 参 + 0x5C71, KANJI_STANDARD, // å±± + 0x60E8, KANJI_STANDARD, // 惚 + 0x6492, KANJI_STANDARD, // 撒 + 0x6563, KANJI_STANDARD, // 散 + 0x685F, KANJI_STANDARD, // 桟 + 0x71E6, KANJI_STANDARD, // 燩 + 0x73CA, KANJI_STANDARD, // 珊 + 0x7523, KANJI_STANDARD, // 産 + 0x7B97, KANJI_STANDARD, // 算 + 0x7E82, KANJI_STANDARD, // 纂 + 0x8695, KANJI_STANDARD, // 蚕 + 0x8B83, KANJI_STANDARD, // 讃 + 0x8CDB, KANJI_STANDARD, // 賛 + 0x9178, KANJI_STANDARD, // 酾 + 0x9910, KANJI_STANDARD, // 逐 + 0x65AC, KANJI_STANDARD, // 斬 + 0x66AB, KANJI_STANDARD, // 暫 + 0x6B8B, KANJI_STANDARD, // 残 + 0x4ED5, KANJI_STANDARD, // 仕 + 0x4ED4, KANJI_STANDARD, // 仔 + 0x4F3A, KANJI_STANDARD, // 䌺 + 0x4F7F, KANJI_STANDARD, // 䜿 + 0x523A, KANJI_STANDARD, // 刺 + 0x53F8, KANJI_STANDARD, // 叞 + 0x53F2, KANJI_STANDARD, // 史 + 0x55E3, KANJI_STANDARD, // 嗣 + 0x56DB, KANJI_STANDARD, // 四 + 0x58EB, KANJI_STANDARD, // 士 + 0x59CB, KANJI_STANDARD, // 始 + 0x59C9, KANJI_STANDARD, // 姉 + 0x59FF, KANJI_STANDARD, // å§¿ + 0x5B50, KANJI_STANDARD, // 子 + 0x5C4D, KANJI_STANDARD, // 屍 + 0x5E02, KANJI_STANDARD, // åž‚ + 0x5E2B, KANJI_STANDARD, // åž« + 0x5FD7, KANJI_STANDARD, // 志 + 0x601D, KANJI_STANDARD, // 思 + 0x6307, KANJI_STANDARD, // 指 + 0x652F, KANJI_STANDARD, // 支 + 0x5B5C, KANJI_STANDARD, // 孜 + 0x65AF, KANJI_STANDARD, // 斯 + 0x65BD, KANJI_STANDARD, // æ–œ + 0x65E8, KANJI_STANDARD, // æ—š + 0x679D, KANJI_STANDARD, // 枝 + 0x6B62, KANJI_STANDARD, // æ­¢ + 0x6B7B, KANJI_STANDARD, // æ­» + 0x6C0F, KANJI_STANDARD, // 氏 + 0x7345, KANJI_STANDARD, // 獅 + 0x7949, KANJI_STANDARD, // 祉 + 0x79C1, KANJI_STANDARD, // 私 + 0x7CF8, KANJI_STANDARD, // 糞 + 0x7D19, KANJI_STANDARD, // 箙 + 0x7D2B, KANJI_STANDARD, // 玫 + 0x80A2, KANJI_STANDARD, // 肢 + 0x8102, KANJI_STANDARD, // 脂 + 0x81F3, KANJI_STANDARD, // 至 + 0x8996, KANJI_STANDARD, // 芖 + 0x8A5E, KANJI_STANDARD, // 詞 + 0x8A69, KANJI_STANDARD, // è©© + 0x8A66, KANJI_STANDARD, // 詊 + 0x8A8C, KANJI_STANDARD, // 誌 + 0x8AEE, KANJI_STANDARD, // è«® + 0x8CC7, KANJI_STANDARD, // 資 + 0x8CDC, KANJI_STANDARD, // 賜 + 0x96CC, KANJI_STANDARD, // 雌 + 0x98FC, KANJI_STANDARD, // 飌 + 0x6B6F, KANJI_STANDARD, // æ­¯ + 0x4E8B, KANJI_STANDARD, // 事 + 0x4F3C, KANJI_STANDARD, // 䌌 + 0x4F8D, KANJI_STANDARD, // 䟍 + 0x5150, KANJI_STANDARD, // 児 + 0x5B57, KANJI_STANDARD, // 字 + 0x5BFA, KANJI_STANDARD, // 寺 + 0x6148, KANJI_STANDARD, // 慈 + 0x6301, KANJI_STANDARD, // 持 + 0x6642, KANJI_STANDARD, // 時 + 0x6B21, KANJI_STANDARD, // 次 + 0x6ECB, KANJI_STANDARD, // 滋 + 0x6CBB, KANJI_STANDARD, // æ²» + 0x723E, KANJI_STANDARD, // 爟 + 0x74BD, KANJI_STANDARD, // ç’œ + 0x75D4, KANJI_STANDARD, // 痔 + 0x78C1, KANJI_STANDARD, // 磁 + 0x793A, KANJI_STANDARD, // 瀺 + 0x800C, KANJI_STANDARD, // 而 + 0x8033, KANJI_STANDARD, // 耳 + 0x81EA, KANJI_STANDARD, // 自 + 0x8494, KANJI_STANDARD, // 蒔 + 0x8F9E, KANJI_STANDARD, // 蟞 + 0x6C50, KANJI_STANDARD, // 汐 + 0x9E7F, KANJI_STANDARD, // 鹿 + 0x5F0F, KANJI_STANDARD, // 匏 + 0x8B58, KANJI_STANDARD, // 識 + 0x9D2B, KANJI_STANDARD, // 鎫 + 0x7AFA, KANJI_STANDARD, // 竺 + 0x8EF8, KANJI_STANDARD, // 軞 + 0x5B8D, KANJI_STANDARD, // 宍 + 0x96EB, KANJI_STANDARD, // 雫 + 0x4E03, KANJI_STANDARD, // 䞃 + 0x53F1, KANJI_STANDARD, // 叱 + 0x57F7, KANJI_STANDARD, // 執 + 0x5931, KANJI_STANDARD, // 倱 + 0x5AC9, KANJI_STANDARD, // 嫉 + 0x5BA4, KANJI_STANDARD, // 宀 + 0x6089, KANJI_STANDARD, // 悉 + 0x6E7F, KANJI_STANDARD, // 湿 + 0x6F06, KANJI_STANDARD, // 挆 + 0x75BE, KANJI_STANDARD, // ç–Ÿ + 0x8CEA, KANJI_STANDARD, // 質 + 0x5B9F, KANJI_STANDARD, // 実 + 0x8500, KANJI_STANDARD, // 蔀 + 0x7BE0, KANJI_STANDARD, // 篠 + 0x5072, KANJI_STANDARD, // 偲 + 0x67F4, KANJI_STANDARD, // 柎 + 0x829D, KANJI_STANDARD, // 芝 + 0x5C61, KANJI_STANDARD, // 屡 + 0x854A, KANJI_STANDARD, // 蕊 + 0x7E1E, KANJI_STANDARD, // 羞 + 0x820E, KANJI_STANDARD, // 舎 + 0x5199, KANJI_STANDARD, // 写 + 0x5C04, KANJI_STANDARD, // 射 + 0x6368, KANJI_STANDARD, // 捚 + 0x8D66, KANJI_STANDARD, // 赊 + 0x659C, KANJI_STANDARD, // 斜 + 0x716E, KANJI_STANDARD, // 煮 + 0x793E, KANJI_STANDARD, // 瀟 + 0x7D17, KANJI_STANDARD, // 算 + 0x8005, KANJI_STANDARD, // 者 + 0x8B1D, KANJI_STANDARD, // 謝 + 0x8ECA, KANJI_STANDARD, // 車 + 0x906E, KANJI_STANDARD, // 遮 + 0x86C7, KANJI_STANDARD, // 蛇 + 0x90AA, KANJI_STANDARD, // 邪 + 0x501F, KANJI_STANDARD, // 借 + 0x52FA, KANJI_STANDARD, // 勺 + 0x5C3A, KANJI_STANDARD, // å°º + 0x6753, KANJI_STANDARD, // 杓 + 0x707C, KANJI_STANDARD, // 灌 + 0x7235, KANJI_STANDARD, // 爵 + 0x914C, KANJI_STANDARD, // 酌 + 0x91C8, KANJI_STANDARD, // 釈 + 0x932B, KANJI_STANDARD, // 錫 + 0x82E5, KANJI_STANDARD, // 若 + 0x5BC2, KANJI_STANDARD, // 寂 + 0x5F31, KANJI_STANDARD, // 匱 + 0x60F9, KANJI_STANDARD, // 惹 + 0x4E3B, KANJI_STANDARD, // äž» + 0x53D6, KANJI_STANDARD, // 取 + 0x5B88, KANJI_STANDARD, // 守 + 0x624B, KANJI_STANDARD, // 手 + 0x6731, KANJI_STANDARD, // 朱 + 0x6B8A, KANJI_STANDARD, // 殊 + 0x72E9, KANJI_STANDARD, // 狩 + 0x73E0, KANJI_STANDARD, // 珠 + 0x7A2E, KANJI_STANDARD, // çš® + 0x816B, KANJI_STANDARD, // 腫 + 0x8DA3, KANJI_STANDARD, // è¶£ + 0x9152, KANJI_STANDARD, // 酒 + 0x9996, KANJI_STANDARD, // 驖 + 0x5112, KANJI_STANDARD, // 儒 + 0x53D7, KANJI_STANDARD, // 受 + 0x546A, KANJI_STANDARD, // 呪 + 0x5BFF, KANJI_STANDARD, // 寿 + 0x6388, KANJI_STANDARD, // 授 + 0x6A39, KANJI_STANDARD, // æš¹ + 0x7DAC, KANJI_STANDARD, // 綬 + 0x9700, KANJI_STANDARD, // 需 + 0x56DA, KANJI_STANDARD, // 囚 + 0x53CE, KANJI_STANDARD, // 収 + 0x5468, KANJI_STANDARD, // 呚 + 0x5B97, KANJI_STANDARD, // 宗 + 0x5C31, KANJI_STANDARD, // å°± + 0x5DDE, KANJI_STANDARD, // 州 + 0x4FEE, KANJI_STANDARD, // ä¿® + 0x6101, KANJI_STANDARD, // 愁 + 0x62FE, KANJI_STANDARD, // 拟 + 0x6D32, KANJI_STANDARD, // 掲 + 0x79C0, KANJI_STANDARD, // 秀 + 0x79CB, KANJI_STANDARD, // 秋 + 0x7D42, KANJI_STANDARD, // 終 + 0x7E4D, KANJI_STANDARD, // 繍 + 0x7FD2, KANJI_STANDARD, // 習 + 0x81ED, KANJI_STANDARD, // 臭 + 0x821F, KANJI_STANDARD, // 舟 + 0x8490, KANJI_STANDARD, // 蒐 + 0x8846, KANJI_STANDARD, // 衆 + 0x8972, KANJI_STANDARD, // 襲 + 0x8B90, KANJI_STANDARD, // 讐 + 0x8E74, KANJI_STANDARD, // 蹎 + 0x8F2F, KANJI_STANDARD, // 茯 + 0x9031, KANJI_STANDARD, // 週 + 0x914B, KANJI_STANDARD, // 酋 + 0x916C, KANJI_STANDARD, // 酬 + 0x96C6, KANJI_STANDARD, // 集 + 0x919C, KANJI_STANDARD, // 醜 + 0x4EC0, KANJI_STANDARD, // 什 + 0x4F4F, KANJI_STANDARD, // 䜏 + 0x5145, KANJI_STANDARD, // 充 + 0x5341, KANJI_STANDARD, // 十 + 0x5F93, KANJI_STANDARD, // 埓 + 0x620E, KANJI_STANDARD, // 戎 + 0x67D4, KANJI_STANDARD, // 柔 + 0x6C41, KANJI_STANDARD, // 汁 + 0x6E0B, KANJI_STANDARD, // æž‹ + 0x7363, KANJI_STANDARD, // 獣 + 0x7E26, KANJI_STANDARD, // 瞊 + 0x91CD, KANJI_STANDARD, // 重 + 0x9283, KANJI_STANDARD, // 銃 + 0x53D4, KANJI_STANDARD, // 叔 + 0x5919, KANJI_STANDARD, // 候 + 0x5BBF, KANJI_STANDARD, // 宿 + 0x6DD1, KANJI_STANDARD, // 淑 + 0x795D, KANJI_STANDARD, // 祝 + 0x7E2E, KANJI_STANDARD, // çž® + 0x7C9B, KANJI_STANDARD, // 粛 + 0x587E, KANJI_STANDARD, // 塟 + 0x719F, KANJI_STANDARD, // 熟 + 0x51FA, KANJI_STANDARD, // 出 + 0x8853, KANJI_STANDARD, // 術 + 0x8FF0, KANJI_STANDARD, // è¿° + 0x4FCA, KANJI_STANDARD, // 俊 + 0x5CFB, KANJI_STANDARD, // å³» + 0x6625, KANJI_STANDARD, // 春 + 0x77AC, KANJI_STANDARD, // 瞬 + 0x7AE3, KANJI_STANDARD, // ç«£ + 0x821C, KANJI_STANDARD, // 舜 + 0x99FF, KANJI_STANDARD, // é§¿ + 0x51C6, KANJI_STANDARD, // 准 + 0x5FAA, KANJI_STANDARD, // 埪 + 0x65EC, KANJI_STANDARD, // 旬 + 0x696F, KANJI_STANDARD, // 楯 + 0x6B89, KANJI_STANDARD, // 殉 + 0x6DF3, KANJI_STANDARD, // æ·³ + 0x6E96, KANJI_STANDARD, // 準 + 0x6F64, KANJI_STANDARD, // 最 + 0x76FE, KANJI_STANDARD, // 盟 + 0x7D14, KANJI_STANDARD, // 箔 + 0x5DE1, KANJI_STANDARD, // å·¡ + 0x9075, KANJI_STANDARD, // 遵 + 0x9187, KANJI_STANDARD, // 醇 + 0x9806, KANJI_STANDARD, // 順 + 0x51E6, KANJI_STANDARD, // 凊 + 0x521D, KANJI_STANDARD, // 初 + 0x6240, KANJI_STANDARD, // 所 + 0x6691, KANJI_STANDARD, // 暑 + 0x66D9, KANJI_STANDARD, // 曙 + 0x6E1A, KANJI_STANDARD, // æžš + 0x5EB6, KANJI_STANDARD, // 庶 + 0x7DD2, KANJI_STANDARD, // 緒 + 0x7F72, KANJI_STANDARD, // 眲 + 0x66F8, KANJI_STANDARD, // 曞 + 0x85AF, KANJI_STANDARD, // 薯 + 0x85F7, KANJI_STANDARD, // 藷 + 0x8AF8, KANJI_STANDARD, // 諞 + 0x52A9, KANJI_STANDARD, // 助 + 0x53D9, KANJI_STANDARD, // 叙 + 0x5973, KANJI_STANDARD, // 女 + 0x5E8F, KANJI_STANDARD, // 序 + 0x5F90, KANJI_STANDARD, // 埐 + 0x6055, KANJI_STANDARD, // 恕 + 0x92E4, KANJI_STANDARD, // é‹€ + 0x9664, KANJI_STANDARD, // 陀 + 0x50B7, KANJI_STANDARD, // 傷 + 0x511F, KANJI_STANDARD, // 償 + 0x52DD, KANJI_STANDARD, // 勝 + 0x5320, KANJI_STANDARD, // 匠 + 0x5347, KANJI_STANDARD, // 升 + 0x53EC, KANJI_STANDARD, // 召 + 0x54E8, KANJI_STANDARD, // 哚 + 0x5546, KANJI_STANDARD, // 商 + 0x5531, KANJI_STANDARD, // 唱 + 0x5617, KANJI_STANDARD, // 嘗 + 0x5968, KANJI_STANDARD, // 奚 + 0x59BE, KANJI_STANDARD, // 功 + 0x5A3C, KANJI_STANDARD, // 嚌 + 0x5BB5, KANJI_STANDARD, // 宵 + 0x5C06, KANJI_STANDARD, // 将 + 0x5C0F, KANJI_STANDARD, // 小 + 0x5C11, KANJI_STANDARD, // 少 + 0x5C1A, KANJI_STANDARD, // 尚 + 0x5E84, KANJI_STANDARD, // 庄 + 0x5E8A, KANJI_STANDARD, // 床 + 0x5EE0, KANJI_STANDARD, // å»  + 0x5F70, KANJI_STANDARD, // 地 + 0x627F, KANJI_STANDARD, // 承 + 0x6284, KANJI_STANDARD, // 抄 + 0x62DB, KANJI_STANDARD, // 招 + 0x638C, KANJI_STANDARD, // 掌 + 0x6377, KANJI_STANDARD, // 捷 + 0x6607, KANJI_STANDARD, // 昇 + 0x660C, KANJI_STANDARD, // 昌 + 0x662D, KANJI_STANDARD, // 昭 + 0x6676, KANJI_STANDARD, // 晶 + 0x677E, KANJI_STANDARD, // 束 + 0x68A2, KANJI_STANDARD, // 梢 + 0x6A1F, KANJI_STANDARD, // 暟 + 0x6A35, KANJI_STANDARD, // æšµ + 0x6CBC, KANJI_STANDARD, // 沌 + 0x6D88, KANJI_STANDARD, // 消 + 0x6E09, KANJI_STANDARD, // 枉 + 0x6E58, KANJI_STANDARD, // 湘 + 0x713C, KANJI_STANDARD, // 焌 + 0x7126, KANJI_STANDARD, // 焩 + 0x7167, KANJI_STANDARD, // 照 + 0x75C7, KANJI_STANDARD, // 症 + 0x7701, KANJI_STANDARD, // 省 + 0x785D, KANJI_STANDARD, // 硝 + 0x7901, KANJI_STANDARD, // 瀁 + 0x7965, KANJI_STANDARD, // 祥 + 0x79F0, KANJI_STANDARD, // ç§° + 0x7AE0, KANJI_STANDARD, // ç«  + 0x7B11, KANJI_STANDARD, // 笑 + 0x7CA7, KANJI_STANDARD, // ç²§ + 0x7D39, KANJI_STANDARD, // 玹 + 0x8096, KANJI_STANDARD, // 肖 + 0x83D6, KANJI_STANDARD, // 菖 + 0x848B, KANJI_STANDARD, // 蒋 + 0x8549, KANJI_STANDARD, // 蕉 + 0x885D, KANJI_STANDARD, // 衝 + 0x88F3, KANJI_STANDARD, // 裳 + 0x8A1F, KANJI_STANDARD, // 蚟 + 0x8A3C, KANJI_STANDARD, // 蚌 + 0x8A54, KANJI_STANDARD, // 詔 + 0x8A73, KANJI_STANDARD, // 詳 + 0x8C61, KANJI_STANDARD, // 象 + 0x8CDE, KANJI_STANDARD, // 賞 + 0x91A4, KANJI_STANDARD, // 醀 + 0x9266, KANJI_STANDARD, // 鉩 + 0x937E, KANJI_STANDARD, // 鍟 + 0x9418, KANJI_STANDARD, // 鐘 + 0x969C, KANJI_STANDARD, // 障 + 0x9798, KANJI_STANDARD, // 鞘 + 0x4E0A, KANJI_STANDARD, // 侊 + 0x4E08, KANJI_STANDARD, // 䞈 + 0x4E1E, KANJI_STANDARD, // 侞 + 0x4E57, KANJI_STANDARD, // 乗 + 0x5197, KANJI_STANDARD, // 冗 + 0x5270, KANJI_STANDARD, // 剰 + 0x57CE, KANJI_STANDARD, // 城 + 0x5834, KANJI_STANDARD, // å Ž + 0x58CC, KANJI_STANDARD, // 壌 + 0x5B22, KANJI_STANDARD, // 嬢 + 0x5E38, KANJI_STANDARD, // åžž + 0x60C5, KANJI_STANDARD, // 情 + 0x64FE, KANJI_STANDARD, // 擟 + 0x6761, KANJI_STANDARD, // 条 + 0x6756, KANJI_STANDARD, // 杖 + 0x6D44, KANJI_STANDARD, // 浄 + 0x72B6, KANJI_STANDARD, // 状 + 0x7573, KANJI_STANDARD, // 畳 + 0x7A63, KANJI_STANDARD, // ç©£ + 0x84B8, KANJI_STANDARD, // è’ž + 0x8B72, KANJI_STANDARD, // è­² + 0x91B8, KANJI_STANDARD, // 醾 + 0x9320, KANJI_STANDARD, // 錠 + 0x5631, KANJI_STANDARD, // 嘱 + 0x57F4, KANJI_STANDARD, // 城 + 0x98FE, KANJI_STANDARD, // 食 + 0x62ED, KANJI_STANDARD, // 拭 + 0x690D, KANJI_STANDARD, // 怍 + 0x6B96, KANJI_STANDARD, // 殖 + 0x71ED, KANJI_STANDARD, // 燭 + 0x7E54, KANJI_STANDARD, // 織 + 0x8077, KANJI_STANDARD, // 職 + 0x8272, KANJI_STANDARD, // 色 + 0x89E6, KANJI_STANDARD, // è§Š + 0x98DF, KANJI_STANDARD, // 食 + 0x8755, KANJI_STANDARD, // 蝕 + 0x8FB1, KANJI_STANDARD, // 蟱 + 0x5C3B, KANJI_STANDARD, // å°» + 0x4F38, KANJI_STANDARD, // 䌞 + 0x4FE1, KANJI_STANDARD, // ä¿¡ + 0x4FB5, KANJI_STANDARD, // 䟵 + 0x5507, KANJI_STANDARD, // 唇 + 0x5A20, KANJI_STANDARD, // åš  + 0x5BDD, KANJI_STANDARD, // 寝 + 0x5BE9, KANJI_STANDARD, // 審 + 0x5FC3, KANJI_STANDARD, // 心 + 0x614E, KANJI_STANDARD, // 慎 + 0x632F, KANJI_STANDARD, // 振 + 0x65B0, KANJI_STANDARD, // 新 + 0x664B, KANJI_STANDARD, // 晋 + 0x68EE, KANJI_STANDARD, // 森 + 0x699B, KANJI_STANDARD, // 抛 + 0x6D78, KANJI_STANDARD, // 浞 + 0x6DF1, KANJI_STANDARD, // æ·± + 0x7533, KANJI_STANDARD, // 申 + 0x75B9, KANJI_STANDARD, // 疹 + 0x771F, KANJI_STANDARD, // 真 + 0x795E, KANJI_STANDARD, // 神 + 0x79E6, KANJI_STANDARD, // ç§Š + 0x7D33, KANJI_STANDARD, // 玳 + 0x81E3, KANJI_STANDARD, // 臣 + 0x82AF, KANJI_STANDARD, // 芯 + 0x85AA, KANJI_STANDARD, // 薪 + 0x89AA, KANJI_STANDARD, // 芪 + 0x8A3A, KANJI_STANDARD, // 蚺 + 0x8EAB, KANJI_STANDARD, // 身 + 0x8F9B, KANJI_STANDARD, // 蟛 + 0x9032, KANJI_STANDARD, // 進 + 0x91DD, KANJI_STANDARD, // 針 + 0x9707, KANJI_STANDARD, // 震 + 0x4EBA, KANJI_STANDARD, // 人 + 0x4EC1, KANJI_STANDARD, // 仁 + 0x5203, KANJI_STANDARD, // 刃 + 0x5875, KANJI_STANDARD, // 塵 + 0x58EC, KANJI_STANDARD, // 壬 + 0x5C0B, KANJI_STANDARD, // 尋 + 0x751A, KANJI_STANDARD, // 甚 + 0x5C3D, KANJI_STANDARD, // å°œ + 0x814E, KANJI_STANDARD, // 腎 + 0x8A0A, KANJI_STANDARD, // 蚊 + 0x8FC5, KANJI_STANDARD, // 迅 + 0x9663, KANJI_STANDARD, // 陣 + 0x976D, KANJI_STANDARD, // 靭 + 0x7B25, KANJI_STANDARD, // 笥 + 0x8ACF, KANJI_STANDARD, // 諏 + 0x9808, KANJI_STANDARD, // 須 + 0x9162, KANJI_STANDARD, // 酢 + 0x56F3, KANJI_STANDARD, // 図 + 0x53A8, KANJI_STANDARD, // 厚 + 0x9017, KANJI_STANDARD, // 逗 + 0x5439, KANJI_STANDARD, // 吹 + 0x5782, KANJI_STANDARD, // 垂 + 0x5E25, KANJI_STANDARD, // 垥 + 0x63A8, KANJI_STANDARD, // 掚 + 0x6C34, KANJI_STANDARD, // æ°Ž + 0x708A, KANJI_STANDARD, // 炊 + 0x7761, KANJI_STANDARD, // 睡 + 0x7C8B, KANJI_STANDARD, // 粋 + 0x7FE0, KANJI_STANDARD, // ç¿  + 0x8870, KANJI_STANDARD, // è¡° + 0x9042, KANJI_STANDARD, // 遂 + 0x9154, KANJI_STANDARD, // 酔 + 0x9310, KANJI_STANDARD, // 錐 + 0x9318, KANJI_STANDARD, // 錘 + 0x968F, KANJI_STANDARD, // 随 + 0x745E, KANJI_STANDARD, // 瑞 + 0x9AC4, KANJI_STANDARD, // 髄 + 0x5D07, KANJI_STANDARD, // 厇 + 0x5D69, KANJI_STANDARD, // 嵩 + 0x6570, KANJI_STANDARD, // 数 + 0x67A2, KANJI_STANDARD, // 枢 + 0x8DA8, KANJI_STANDARD, // è¶š + 0x96DB, KANJI_STANDARD, // 雛 + 0x636E, KANJI_STANDARD, // 据 + 0x6749, KANJI_STANDARD, // 杉 + 0x6919, KANJI_STANDARD, // 怙 + 0x83C5, KANJI_STANDARD, // 菅 + 0x9817, KANJI_STANDARD, // 頗 + 0x96C0, KANJI_STANDARD, // 雀 + 0x88FE, KANJI_STANDARD, // 裟 + 0x6F84, KANJI_STANDARD, // 柄 + 0x647A, KANJI_STANDARD, // 摺 + 0x5BF8, KANJI_STANDARD, // 寞 + 0x4E16, KANJI_STANDARD, // 侖 + 0x702C, KANJI_STANDARD, // 瀬 + 0x755D, KANJI_STANDARD, // 畝 + 0x662F, KANJI_STANDARD, // 是 + 0x51C4, KANJI_STANDARD, // 凄 + 0x5236, KANJI_STANDARD, // 制 + 0x52E2, KANJI_STANDARD, // 勢 + 0x59D3, KANJI_STANDARD, // 姓 + 0x5F81, KANJI_STANDARD, // 埁 + 0x6027, KANJI_STANDARD, // 性 + 0x6210, KANJI_STANDARD, // 成 + 0x653F, KANJI_STANDARD, // 政 + 0x6574, KANJI_STANDARD, // 敎 + 0x661F, KANJI_STANDARD, // 星 + 0x6674, KANJI_STANDARD, // 晎 + 0x68F2, KANJI_STANDARD, // 棲 + 0x6816, KANJI_STANDARD, // 栖 + 0x6B63, KANJI_STANDARD, // æ­£ + 0x6E05, KANJI_STANDARD, // æž… + 0x7272, KANJI_STANDARD, // 牲 + 0x751F, KANJI_STANDARD, // 生 + 0x76DB, KANJI_STANDARD, // 盛 + 0x7CBE, KANJI_STANDARD, // 粟 + 0x8056, KANJI_STANDARD, // 聖 + 0x58F0, KANJI_STANDARD, // 声 + 0x88FD, KANJI_STANDARD, // 補 + 0x897F, KANJI_STANDARD, // 西 + 0x8AA0, KANJI_STANDARD, // 誠 + 0x8A93, KANJI_STANDARD, // 誓 + 0x8ACB, KANJI_STANDARD, // 請 + 0x901D, KANJI_STANDARD, // 逝 + 0x9192, KANJI_STANDARD, // 醒 + 0x9752, KANJI_STANDARD, // 青 + 0x9759, KANJI_STANDARD, // 静 + 0x6589, KANJI_STANDARD, // 斉 + 0x7A0E, KANJI_STANDARD, // 皎 + 0x8106, KANJI_STANDARD, // 脆 + 0x96BB, KANJI_STANDARD, // 隻 + 0x5E2D, KANJI_STANDARD, // åž­ + 0x60DC, KANJI_STANDARD, // 惜 + 0x621A, KANJI_STANDARD, // 戚 + 0x65A5, KANJI_STANDARD, // 斥 + 0x6614, KANJI_STANDARD, // 昔 + 0x6790, KANJI_STANDARD, // 析 + 0x77F3, KANJI_STANDARD, // 石 + 0x7A4D, KANJI_STANDARD, // 積 + 0x7C4D, KANJI_STANDARD, // 籍 + 0x7E3E, KANJI_STANDARD, // 瞟 + 0x810A, KANJI_STANDARD, // 脊 + 0x8CAC, KANJI_STANDARD, // 責 + 0x8D64, KANJI_STANDARD, // èµ€ + 0x8DE1, KANJI_STANDARD, // è·¡ + 0x8E5F, KANJI_STANDARD, // 蹟 + 0x78A9, KANJI_STANDARD, // 碩 + 0x5207, KANJI_STANDARD, // 切 + 0x62D9, KANJI_STANDARD, // 拙 + 0x63A5, KANJI_STANDARD, // 接 + 0x6442, KANJI_STANDARD, // 摂 + 0x6298, KANJI_STANDARD, // 折 + 0x8A2D, KANJI_STANDARD, // èš­ + 0x7A83, KANJI_STANDARD, // 窃 + 0x7BC0, KANJI_STANDARD, // 節 + 0x8AAC, KANJI_STANDARD, // 説 + 0x96EA, KANJI_STANDARD, // 雪 + 0x7D76, KANJI_STANDARD, // çµ¶ + 0x820C, KANJI_STANDARD, // 舌 + 0x8749, KANJI_STANDARD, // 蝉 + 0x4ED9, KANJI_STANDARD, // 仙 + 0x5148, KANJI_STANDARD, // 先 + 0x5343, KANJI_STANDARD, // 千 + 0x5360, KANJI_STANDARD, // 占 + 0x5BA3, KANJI_STANDARD, // 宣 + 0x5C02, KANJI_STANDARD, // 専 + 0x5C16, KANJI_STANDARD, // 尖 + 0x5DDD, KANJI_STANDARD, // 川 + 0x6226, KANJI_STANDARD, // 戊 + 0x6247, KANJI_STANDARD, // 扇 + 0x64B0, KANJI_STANDARD, // 撰 + 0x6813, KANJI_STANDARD, // 栓 + 0x6834, KANJI_STANDARD, // æ Ž + 0x6CC9, KANJI_STANDARD, // 泉 + 0x6D45, KANJI_STANDARD, // 浅 + 0x6D17, KANJI_STANDARD, // 掗 + 0x67D3, KANJI_STANDARD, // 染 + 0x6F5C, KANJI_STANDARD, // 朜 + 0x714E, KANJI_STANDARD, // 煎 + 0x717D, KANJI_STANDARD, // ç…œ + 0x65CB, KANJI_STANDARD, // 旋 + 0x7A7F, KANJI_STANDARD, // ç©¿ + 0x7BAD, KANJI_STANDARD, // ç®­ + 0x7DDA, KANJI_STANDARD, // 線 + 0x7E4A, KANJI_STANDARD, // 繊 + 0x7FA8, KANJI_STANDARD, // 矚 + 0x817A, KANJI_STANDARD, // 腺 + 0x821B, KANJI_STANDARD, // 舛 + 0x8239, KANJI_STANDARD, // 船 + 0x85A6, KANJI_STANDARD, // è–Š + 0x8A6E, KANJI_STANDARD, // è©® + 0x8CCE, KANJI_STANDARD, // 賎 + 0x8DF5, KANJI_STANDARD, // è·µ + 0x9078, KANJI_STANDARD, // 遞 + 0x9077, KANJI_STANDARD, // 遷 + 0x92AD, KANJI_STANDARD, // 銭 + 0x9291, KANJI_STANDARD, // 銑 + 0x9583, KANJI_STANDARD, // 閃 + 0x9BAE, KANJI_STANDARD, // é®® + 0x524D, KANJI_STANDARD, // 前 + 0x5584, KANJI_STANDARD, // 善 + 0x6F38, KANJI_STANDARD, // 挞 + 0x7136, KANJI_STANDARD, // 然 + 0x5168, KANJI_STANDARD, // å…š + 0x7985, KANJI_STANDARD, // 穅 + 0x7E55, KANJI_STANDARD, // 繕 + 0x81B3, KANJI_STANDARD, // 膳 + 0x7CCE, KANJI_STANDARD, // 糎 + 0x564C, KANJI_STANDARD, // 噌 + 0x5851, KANJI_STANDARD, // 塑 + 0x5CA8, KANJI_STANDARD, // 岚 + 0x63AA, KANJI_STANDARD, // 措 + 0x66FE, KANJI_STANDARD, // 曟 + 0x66FD, KANJI_STANDARD, // 曜 + 0x695A, KANJI_STANDARD, // 楚 + 0x72D9, KANJI_STANDARD, // 狙 + 0x758F, KANJI_STANDARD, // 疏 + 0x758E, KANJI_STANDARD, // 疎 + 0x790E, KANJI_STANDARD, // 瀎 + 0x7956, KANJI_STANDARD, // 祖 + 0x79DF, KANJI_STANDARD, // 租 + 0x7C97, KANJI_STANDARD, // 粗 + 0x7D20, KANJI_STANDARD, // 玠 + 0x7D44, KANJI_STANDARD, // 組 + 0x8607, KANJI_STANDARD, // 蘇 + 0x8A34, KANJI_STANDARD, // 蚎 + 0x963B, KANJI_STANDARD, // 阻 + 0x9061, KANJI_STANDARD, // 遡 + 0x9F20, KANJI_STANDARD, // 錠 + 0x50E7, KANJI_STANDARD, // 僧 + 0x5275, KANJI_STANDARD, // 創 + 0x53CC, KANJI_STANDARD, // 双 + 0x53E2, KANJI_STANDARD, // 叢 + 0x5009, KANJI_STANDARD, // 倉 + 0x55AA, KANJI_STANDARD, // 喪 + 0x58EE, KANJI_STANDARD, // 壮 + 0x594F, KANJI_STANDARD, // 奏 + 0x723D, KANJI_STANDARD, // 爜 + 0x5B8B, KANJI_STANDARD, // 宋 + 0x5C64, KANJI_STANDARD, // å±€ + 0x531D, KANJI_STANDARD, // 匝 + 0x60E3, KANJI_STANDARD, // 惣 + 0x60F3, KANJI_STANDARD, // 想 + 0x635C, KANJI_STANDARD, // 捜 + 0x6383, KANJI_STANDARD, // 掃 + 0x633F, KANJI_STANDARD, // 挿 + 0x63BB, KANJI_STANDARD, // 掻 + 0x64CD, KANJI_STANDARD, // 操 + 0x65E9, KANJI_STANDARD, // 早 + 0x66F9, KANJI_STANDARD, // 曹 + 0x5DE3, KANJI_STANDARD, // å·£ + 0x69CD, KANJI_STANDARD, // 槍 + 0x69FD, KANJI_STANDARD, // æ§œ + 0x6F15, KANJI_STANDARD, // 挕 + 0x71E5, KANJI_STANDARD, // 燥 + 0x4E89, KANJI_STANDARD, // 争 + 0x75E9, KANJI_STANDARD, // 痩 + 0x76F8, KANJI_STANDARD, // 盾 + 0x7A93, KANJI_STANDARD, // 窓 + 0x7CDF, KANJI_STANDARD, // 糟 + 0x7DCF, KANJI_STANDARD, // 総 + 0x7D9C, KANJI_STANDARD, // 綜 + 0x8061, KANJI_STANDARD, // 聡 + 0x8349, KANJI_STANDARD, // 草 + 0x8358, KANJI_STANDARD, // 荘 + 0x846C, KANJI_STANDARD, // 葬 + 0x84BC, KANJI_STANDARD, // è’Œ + 0x85FB, KANJI_STANDARD, // 藻 + 0x88C5, KANJI_STANDARD, // 装 + 0x8D70, KANJI_STANDARD, // èµ° + 0x9001, KANJI_STANDARD, // 送 + 0x906D, KANJI_STANDARD, // 遭 + 0x9397, KANJI_STANDARD, // 鎗 + 0x971C, KANJI_STANDARD, // 霜 + 0x9A12, KANJI_STANDARD, // 鹒 + 0x50CF, KANJI_STANDARD, // 像 + 0x5897, KANJI_STANDARD, // 増 + 0x618E, KANJI_STANDARD, // 憎 + 0x81D3, KANJI_STANDARD, // 臓 + 0x8535, KANJI_STANDARD, // 蔵 + 0x8D08, KANJI_STANDARD, // 莈 + 0x9020, KANJI_STANDARD, // 造 + 0x4FC3, KANJI_STANDARD, // 促 + 0x5074, KANJI_STANDARD, // 偎 + 0x5247, KANJI_STANDARD, // 則 + 0x5373, KANJI_STANDARD, // 即 + 0x606F, KANJI_STANDARD, // 息 + 0x6349, KANJI_STANDARD, // 捉 + 0x675F, KANJI_STANDARD, // 束 + 0x6E2C, KANJI_STANDARD, // 枬 + 0x8DB3, KANJI_STANDARD, // è¶³ + 0x901F, KANJI_STANDARD, // 速 + 0x4FD7, KANJI_STANDARD, // 俗 + 0x5C5E, KANJI_STANDARD, // 属 + 0x8CCA, KANJI_STANDARD, // 賊 + 0x65CF, KANJI_STANDARD, // 族 + 0x7D9A, KANJI_STANDARD, // 続 + 0x5352, KANJI_STANDARD, // 卒 + 0x8896, KANJI_STANDARD, // 袖 + 0x5176, KANJI_STANDARD, // 其 + 0x63C3, KANJI_STANDARD, // 揃 + 0x5B58, KANJI_STANDARD, // 存 + 0x5B6B, KANJI_STANDARD, // å­« + 0x5C0A, KANJI_STANDARD, // 尊 + 0x640D, KANJI_STANDARD, // 損 + 0x6751, KANJI_STANDARD, // 村 + 0x905C, KANJI_STANDARD, // 遜 + 0x4ED6, KANJI_STANDARD, // 他 + 0x591A, KANJI_STANDARD, // 倚 + 0x592A, KANJI_STANDARD, // 倪 + 0x6C70, KANJI_STANDARD, // æ±° + 0x8A51, KANJI_STANDARD, // 詑 + 0x553E, KANJI_STANDARD, // 唟 + 0x5815, KANJI_STANDARD, // 堕 + 0x59A5, KANJI_STANDARD, // 劥 + 0x60F0, KANJI_STANDARD, // 惰 + 0x6253, KANJI_STANDARD, // 打 + 0x67C1, KANJI_STANDARD, // 柁 + 0x8235, KANJI_STANDARD, // 舵 + 0x6955, KANJI_STANDARD, // 楕 + 0x9640, KANJI_STANDARD, // 陀 + 0x99C4, KANJI_STANDARD, // 駄 + 0x9A28, KANJI_STANDARD, // éšš + 0x4F53, KANJI_STANDARD, // 䜓 + 0x5806, KANJI_STANDARD, // 堆 + 0x5BFE, KANJI_STANDARD, // 察 + 0x8010, KANJI_STANDARD, // 耐 + 0x5CB1, KANJI_STANDARD, // å²± + 0x5E2F, KANJI_STANDARD, // 垯 + 0x5F85, KANJI_STANDARD, // 埅 + 0x6020, KANJI_STANDARD, // 怠 + 0x614B, KANJI_STANDARD, // 態 + 0x6234, KANJI_STANDARD, // 戎 + 0x66FF, KANJI_STANDARD, // 替 + 0x6CF0, KANJI_STANDARD, // æ³° + 0x6EDE, KANJI_STANDARD, // 滞 + 0x80CE, KANJI_STANDARD, // 胎 + 0x817F, KANJI_STANDARD, // 腿 + 0x82D4, KANJI_STANDARD, // 苔 + 0x888B, KANJI_STANDARD, // 袋 + 0x8CB8, KANJI_STANDARD, // 貞 + 0x9000, KANJI_STANDARD, // 退 + 0x902E, KANJI_STANDARD, // 逮 + 0x968A, KANJI_STANDARD, // 隊 + 0x9EDB, KANJI_STANDARD, // 黛 + 0x9BDB, KANJI_STANDARD, // 鯛 + 0x4EE3, KANJI_STANDARD, // 代 + 0x53F0, KANJI_STANDARD, // 台 + 0x5927, KANJI_STANDARD, // 倧 + 0x7B2C, KANJI_STANDARD, // 第 + 0x918D, KANJI_STANDARD, // 醍 + 0x984C, KANJI_STANDARD, // 題 + 0x9DF9, KANJI_STANDARD, // é·¹ + 0x6EDD, KANJI_STANDARD, // 滝 + 0x7027, KANJI_STANDARD, // 瀧 + 0x5353, KANJI_STANDARD, // 卓 + 0x5544, KANJI_STANDARD, // 啄 + 0x5B85, KANJI_STANDARD, // 宅 + 0x6258, KANJI_STANDARD, // 托 + 0x629E, KANJI_STANDARD, // 択 + 0x62D3, KANJI_STANDARD, // 拓 + 0x6CA2, KANJI_STANDARD, // æ²¢ + 0x6FEF, KANJI_STANDARD, // 濯 + 0x7422, KANJI_STANDARD, // 琢 + 0x8A17, KANJI_STANDARD, // èš— + 0x9438, KANJI_STANDARD, // 鐞 + 0x6FC1, KANJI_STANDARD, // 濁 + 0x8AFE, KANJI_STANDARD, // 諟 + 0x8338, KANJI_STANDARD, // 茞 + 0x51E7, KANJI_STANDARD, // 凧 + 0x86F8, KANJI_STANDARD, // 蛞 + 0x53EA, KANJI_STANDARD, // 只 + 0x53E9, KANJI_STANDARD, // 叩 + 0x4F46, KANJI_STANDARD, // 䜆 + 0x9054, KANJI_STANDARD, // 達 + 0x8FB0, KANJI_STANDARD, // 蟰 + 0x596A, KANJI_STANDARD, // 奪 + 0x8131, KANJI_STANDARD, // 脱 + 0x5DFD, KANJI_STANDARD, // å·œ + 0x7AEA, KANJI_STANDARD, // 竪 + 0x8FBF, KANJI_STANDARD, // 蟿 + 0x68DA, KANJI_STANDARD, // 棚 + 0x8C37, KANJI_STANDARD, // è°· + 0x72F8, KANJI_STANDARD, // 狾 + 0x9C48, KANJI_STANDARD, // 鱈 + 0x6A3D, KANJI_STANDARD, // æšœ + 0x8AB0, KANJI_STANDARD, // 誰 + 0x4E39, KANJI_STANDARD, // äž¹ + 0x5358, KANJI_STANDARD, // 単 + 0x5606, KANJI_STANDARD, // 嘆 + 0x5766, KANJI_STANDARD, // 坊 + 0x62C5, KANJI_STANDARD, // 担 + 0x63A2, KANJI_STANDARD, // 探 + 0x65E6, KANJI_STANDARD, // æ—Š + 0x6B4E, KANJI_STANDARD, // 歎 + 0x6DE1, KANJI_STANDARD, // æ·¡ + 0x6E5B, KANJI_STANDARD, // 湛 + 0x70AD, KANJI_STANDARD, // 炭 + 0x77ED, KANJI_STANDARD, // 短 + 0x7AEF, KANJI_STANDARD, // 端 + 0x7BAA, KANJI_STANDARD, // 箪 + 0x7DBB, KANJI_STANDARD, // ç¶» + 0x803D, KANJI_STANDARD, // 耜 + 0x80C6, KANJI_STANDARD, // 胆 + 0x86CB, KANJI_STANDARD, // 蛋 + 0x8A95, KANJI_STANDARD, // 誕 + 0x935B, KANJI_STANDARD, // 鍛 + 0x56E3, KANJI_STANDARD, // 団 + 0x58C7, KANJI_STANDARD, // 壇 + 0x5F3E, KANJI_STANDARD, // 匟 + 0x65AD, KANJI_STANDARD, // 断 + 0x6696, KANJI_STANDARD, // 暖 + 0x6A80, KANJI_STANDARD, // 檀 + 0x6BB5, KANJI_STANDARD, // 段 + 0x7537, KANJI_STANDARD, // 男 + 0x8AC7, KANJI_STANDARD, // 談 + 0x5024, KANJI_STANDARD, // 倀 + 0x77E5, KANJI_STANDARD, // 知 + 0x5730, KANJI_STANDARD, // 地 + 0x5F1B, KANJI_STANDARD, // 匛 + 0x6065, KANJI_STANDARD, // 恥 + 0x667A, KANJI_STANDARD, // 智 + 0x6C60, KANJI_STANDARD, // æ±  + 0x75F4, KANJI_STANDARD, // 痮 + 0x7A1A, KANJI_STANDARD, // 繚 + 0x7F6E, KANJI_STANDARD, // 眮 + 0x81F4, KANJI_STANDARD, // 臎 + 0x8718, KANJI_STANDARD, // 蜘 + 0x9045, KANJI_STANDARD, // 遅 + 0x99B3, KANJI_STANDARD, // 銳 + 0x7BC9, KANJI_STANDARD, // 築 + 0x755C, KANJI_STANDARD, // 畜 + 0x7AF9, KANJI_STANDARD, // 竹 + 0x7B51, KANJI_STANDARD, // 筑 + 0x84C4, KANJI_STANDARD, // 蓄 + 0x9010, KANJI_STANDARD, // 逐 + 0x79E9, KANJI_STANDARD, // ç§© + 0x7A92, KANJI_STANDARD, // 窒 + 0x8336, KANJI_STANDARD, // 茶 + 0x5AE1, KANJI_STANDARD, // å«¡ + 0x7740, KANJI_STANDARD, // 着 + 0x4E2D, KANJI_STANDARD, // äž­ + 0x4EF2, KANJI_STANDARD, // 仲 + 0x5B99, KANJI_STANDARD, // 宙 + 0x5FE0, KANJI_STANDARD, // å¿  + 0x62BD, KANJI_STANDARD, // 抜 + 0x663C, KANJI_STANDARD, // 昌 + 0x67F1, KANJI_STANDARD, // 柱 + 0x6CE8, KANJI_STANDARD, // 泚 + 0x866B, KANJI_STANDARD, // 虫 + 0x8877, KANJI_STANDARD, // è¡· + 0x8A3B, KANJI_STANDARD, // èš» + 0x914E, KANJI_STANDARD, // 酎 + 0x92F3, KANJI_STANDARD, // 鋳 + 0x99D0, KANJI_STANDARD, // 駐 + 0x6A17, KANJI_STANDARD, // æš— + 0x7026, KANJI_STANDARD, // 瀩 + 0x732A, KANJI_STANDARD, // 猪 + 0x82E7, KANJI_STANDARD, // 苧 + 0x8457, KANJI_STANDARD, // 著 + 0x8CAF, KANJI_STANDARD, // 貯 + 0x4E01, KANJI_STANDARD, // 䞁 + 0x5146, KANJI_STANDARD, // 兆 + 0x51CB, KANJI_STANDARD, // 凋 + 0x558B, KANJI_STANDARD, // 喋 + 0x5BF5, KANJI_STANDARD, // 寵 + 0x5E16, KANJI_STANDARD, // åž– + 0x5E33, KANJI_STANDARD, // åž³ + 0x5E81, KANJI_STANDARD, // 庁 + 0x5F14, KANJI_STANDARD, // 匔 + 0x5F35, KANJI_STANDARD, // 匵 + 0x5F6B, KANJI_STANDARD, // 圫 + 0x5FB4, KANJI_STANDARD, // 城 + 0x61F2, KANJI_STANDARD, // 懲 + 0x6311, KANJI_STANDARD, // 挑 + 0x66A2, KANJI_STANDARD, // 暢 + 0x671D, KANJI_STANDARD, // 朝 + 0x6F6E, KANJI_STANDARD, // 朮 + 0x7252, KANJI_STANDARD, // 牒 + 0x753A, KANJI_STANDARD, // 町 + 0x773A, KANJI_STANDARD, // 眺 + 0x8074, KANJI_STANDARD, // 聎 + 0x8139, KANJI_STANDARD, // 脹 + 0x8178, KANJI_STANDARD, // è…ž + 0x8776, KANJI_STANDARD, // 蝶 + 0x8ABF, KANJI_STANDARD, // 調 + 0x8ADC, KANJI_STANDARD, // 諜 + 0x8D85, KANJI_STANDARD, // 超 + 0x8DF3, KANJI_STANDARD, // è·³ + 0x929A, KANJI_STANDARD, // 銚 + 0x9577, KANJI_STANDARD, // 長 + 0x9802, KANJI_STANDARD, // 頂 + 0x9CE5, KANJI_STANDARD, // é³¥ + 0x52C5, KANJI_STANDARD, // 勅 + 0x6357, KANJI_STANDARD, // 捗 + 0x76F4, KANJI_STANDARD, // 目 + 0x6715, KANJI_STANDARD, // 朕 + 0x6C88, KANJI_STANDARD, // 沈 + 0x73CD, KANJI_STANDARD, // 珍 + 0x8CC3, KANJI_STANDARD, // 賃 + 0x93AE, KANJI_STANDARD, // 鎮 + 0x9673, KANJI_STANDARD, // 陳 + 0x6D25, KANJI_STANDARD, // 接 + 0x589C, KANJI_STANDARD, // 墜 + 0x690E, KANJI_STANDARD, // 怎 + 0x69CC, KANJI_STANDARD, // 槌 + 0x8FFD, KANJI_STANDARD, // 远 + 0x939A, KANJI_STANDARD, // 鎚 + 0x75DB, KANJI_STANDARD, // 痛 + 0x901A, KANJI_STANDARD, // 通 + 0x585A, KANJI_STANDARD, // 塚 + 0x6802, KANJI_STANDARD, // 栂 + 0x63B4, KANJI_STANDARD, // 掎 + 0x69FB, KANJI_STANDARD, // æ§» + 0x4F43, KANJI_STANDARD, // 䜃 + 0x6F2C, KANJI_STANDARD, // 挬 + 0x67D8, KANJI_STANDARD, // 柘 + 0x8FBB, KANJI_STANDARD, // 蟻 + 0x8526, KANJI_STANDARD, // 蔊 + 0x7DB4, KANJI_STANDARD, // ç¶Ž + 0x9354, KANJI_STANDARD, // 鍔 + 0x693F, KANJI_STANDARD, // 怿 + 0x6F70, KANJI_STANDARD, // 朰 + 0x576A, KANJI_STANDARD, // 坪 + 0x58F7, KANJI_STANDARD, // 壷 + 0x5B2C, KANJI_STANDARD, // 嬬 + 0x7D2C, KANJI_STANDARD, // 玬 + 0x722A, KANJI_STANDARD, // 爪 + 0x540A, KANJI_STANDARD, // 吊 + 0x91E3, KANJI_STANDARD, // 釣 + 0x9DB4, KANJI_STANDARD, // é¶Ž + 0x4EAD, KANJI_STANDARD, // 亭 + 0x4F4E, KANJI_STANDARD, // 䜎 + 0x505C, KANJI_STANDARD, // 停 + 0x5075, KANJI_STANDARD, // 偵 + 0x5243, KANJI_STANDARD, // 剃 + 0x8C9E, KANJI_STANDARD, // 貞 + 0x5448, KANJI_STANDARD, // 呈 + 0x5824, KANJI_STANDARD, // å € + 0x5B9A, KANJI_STANDARD, // 定 + 0x5E1D, KANJI_STANDARD, // 垝 + 0x5E95, KANJI_STANDARD, // 底 + 0x5EAD, KANJI_STANDARD, // 庭 + 0x5EF7, KANJI_STANDARD, // å»· + 0x5F1F, KANJI_STANDARD, // 匟 + 0x608C, KANJI_STANDARD, // 悌 + 0x62B5, KANJI_STANDARD, // 抵 + 0x633A, KANJI_STANDARD, // 挺 + 0x63D0, KANJI_STANDARD, // 提 + 0x68AF, KANJI_STANDARD, // 梯 + 0x6C40, KANJI_STANDARD, // 汀 + 0x7887, KANJI_STANDARD, // 碇 + 0x798E, KANJI_STANDARD, // 犎 + 0x7A0B, KANJI_STANDARD, // 繋 + 0x7DE0, KANJI_STANDARD, // ç·  + 0x8247, KANJI_STANDARD, // 艇 + 0x8A02, KANJI_STANDARD, // èš‚ + 0x8AE6, KANJI_STANDARD, // 諊 + 0x8E44, KANJI_STANDARD, // 蹄 + 0x9013, KANJI_STANDARD, // 逓 + 0x90B8, KANJI_STANDARD, // 邾 + 0x912D, KANJI_STANDARD, // 鄭 + 0x91D8, KANJI_STANDARD, // 釘 + 0x9F0E, KANJI_STANDARD, // 錎 + 0x6CE5, KANJI_STANDARD, // æ³¥ + 0x6458, KANJI_STANDARD, // 摘 + 0x64E2, KANJI_STANDARD, // 擢 + 0x6575, KANJI_STANDARD, // 敵 + 0x6EF4, KANJI_STANDARD, // 滎 + 0x7684, KANJI_STANDARD, // 的 + 0x7B1B, KANJI_STANDARD, // 笛 + 0x9069, KANJI_STANDARD, // 適 + 0x93D1, KANJI_STANDARD, // 鏑 + 0x6EBA, KANJI_STANDARD, // 溺 + 0x54F2, KANJI_STANDARD, // 哲 + 0x5FB9, KANJI_STANDARD, // 培 + 0x64A4, KANJI_STANDARD, // æ’€ + 0x8F4D, KANJI_STANDARD, // 蜍 + 0x8FED, KANJI_STANDARD, // è¿­ + 0x9244, KANJI_STANDARD, // 鉄 + 0x5178, KANJI_STANDARD, // å…ž + 0x586B, KANJI_STANDARD, // å¡« + 0x5929, KANJI_STANDARD, // 倩 + 0x5C55, KANJI_STANDARD, // 展 + 0x5E97, KANJI_STANDARD, // 店 + 0x6DFB, KANJI_STANDARD, // æ·» + 0x7E8F, KANJI_STANDARD, // 纏 + 0x751C, KANJI_STANDARD, // 甜 + 0x8CBC, KANJI_STANDARD, // 貌 + 0x8EE2, KANJI_STANDARD, // 転 + 0x985B, KANJI_STANDARD, // 顛 + 0x70B9, KANJI_STANDARD, // 点 + 0x4F1D, KANJI_STANDARD, // 䌝 + 0x6BBF, KANJI_STANDARD, // 殿 + 0x6FB1, KANJI_STANDARD, // 柱 + 0x7530, KANJI_STANDARD, // 田 + 0x96FB, KANJI_STANDARD, // 電 + 0x514E, KANJI_STANDARD, // 兎 + 0x5410, KANJI_STANDARD, // 吐 + 0x5835, KANJI_STANDARD, // å µ + 0x5857, KANJI_STANDARD, // 塗 + 0x59AC, KANJI_STANDARD, // 劬 + 0x5C60, KANJI_STANDARD, // å±  + 0x5F92, KANJI_STANDARD, // 埒 + 0x6597, KANJI_STANDARD, // 斗 + 0x675C, KANJI_STANDARD, // 杜 + 0x6E21, KANJI_STANDARD, // æž¡ + 0x767B, KANJI_STANDARD, // 登 + 0x83DF, KANJI_STANDARD, // 菟 + 0x8CED, KANJI_STANDARD, // è³­ + 0x9014, KANJI_STANDARD, // 途 + 0x90FD, KANJI_STANDARD, // 郜 + 0x934D, KANJI_STANDARD, // 鍍 + 0x7825, KANJI_STANDARD, // ç ¥ + 0x783A, KANJI_STANDARD, // ç º + 0x52AA, KANJI_STANDARD, // 努 + 0x5EA6, KANJI_STANDARD, // 床 + 0x571F, KANJI_STANDARD, // 土 + 0x5974, KANJI_STANDARD, // 奎 + 0x6012, KANJI_STANDARD, // 怒 + 0x5012, KANJI_STANDARD, // 倒 + 0x515A, KANJI_STANDARD, // 党 + 0x51AC, KANJI_STANDARD, // 冬 + 0x51CD, KANJI_STANDARD, // 凍 + 0x5200, KANJI_STANDARD, // 刀 + 0x5510, KANJI_STANDARD, // 唐 + 0x5854, KANJI_STANDARD, // 塔 + 0x5858, KANJI_STANDARD, // 塘 + 0x5957, KANJI_STANDARD, // 套 + 0x5B95, KANJI_STANDARD, // 宕 + 0x5CF6, KANJI_STANDARD, // å³¶ + 0x5D8B, KANJI_STANDARD, // 嶋 + 0x60BC, KANJI_STANDARD, // 悌 + 0x6295, KANJI_STANDARD, // 投 + 0x642D, KANJI_STANDARD, // 搭 + 0x6771, KANJI_STANDARD, // 東 + 0x6843, KANJI_STANDARD, // 桃 + 0x68BC, KANJI_STANDARD, // 梌 + 0x68DF, KANJI_STANDARD, // 棟 + 0x76D7, KANJI_STANDARD, // 盗 + 0x6DD8, KANJI_STANDARD, // 淘 + 0x6E6F, KANJI_STANDARD, // 湯 + 0x6D9B, KANJI_STANDARD, // 涛 + 0x706F, KANJI_STANDARD, // 灯 + 0x71C8, KANJI_STANDARD, // 燈 + 0x5F53, KANJI_STANDARD, // 圓 + 0x75D8, KANJI_STANDARD, // 痘 + 0x7977, KANJI_STANDARD, // 祷 + 0x7B49, KANJI_STANDARD, // 等 + 0x7B54, KANJI_STANDARD, // 答 + 0x7B52, KANJI_STANDARD, // 筒 + 0x7CD6, KANJI_STANDARD, // 糖 + 0x7D71, KANJI_STANDARD, // çµ± + 0x5230, KANJI_STANDARD, // 到 + 0x8463, KANJI_STANDARD, // 董 + 0x8569, KANJI_STANDARD, // 蕩 + 0x85E4, KANJI_STANDARD, // è—€ + 0x8A0E, KANJI_STANDARD, // 蚎 + 0x8B04, KANJI_STANDARD, // 謄 + 0x8C46, KANJI_STANDARD, // 豆 + 0x8E0F, KANJI_STANDARD, // 螏 + 0x9003, KANJI_STANDARD, // 逃 + 0x900F, KANJI_STANDARD, // 透 + 0x9419, KANJI_STANDARD, // 鐙 + 0x9676, KANJI_STANDARD, // 陶 + 0x982D, KANJI_STANDARD, // é ­ + 0x9A30, KANJI_STANDARD, // éš° + 0x95D8, KANJI_STANDARD, // 闘 + 0x50CD, KANJI_STANDARD, // 働 + 0x52D5, KANJI_STANDARD, // 動 + 0x540C, KANJI_STANDARD, // 同 + 0x5802, KANJI_STANDARD, // 堂 + 0x5C0E, KANJI_STANDARD, // 導 + 0x61A7, KANJI_STANDARD, // 憧 + 0x649E, KANJI_STANDARD, // 撞 + 0x6D1E, KANJI_STANDARD, // 掞 + 0x77B3, KANJI_STANDARD, // 瞳 + 0x7AE5, KANJI_STANDARD, // ç«¥ + 0x80F4, KANJI_STANDARD, // 胎 + 0x8404, KANJI_STANDARD, // 萄 + 0x9053, KANJI_STANDARD, // 道 + 0x9285, KANJI_STANDARD, // 銅 + 0x5CE0, KANJI_STANDARD, // å³  + 0x9D07, KANJI_STANDARD, // 鮇 + 0x533F, KANJI_STANDARD, // 匿 + 0x5F97, KANJI_STANDARD, // 埗 + 0x5FB3, KANJI_STANDARD, // 埳 + 0x6D9C, KANJI_STANDARD, // 涜 + 0x7279, KANJI_STANDARD, // 特 + 0x7763, KANJI_STANDARD, // 督 + 0x79BF, KANJI_STANDARD, // 犿 + 0x7BE4, KANJI_STANDARD, // 節 + 0x6BD2, KANJI_STANDARD, // 毒 + 0x72EC, KANJI_STANDARD, // 独 + 0x8AAD, KANJI_STANDARD, // 読 + 0x6803, KANJI_STANDARD, // 栃 + 0x6A61, KANJI_STANDARD, // æ©¡ + 0x51F8, KANJI_STANDARD, // 凞 + 0x7A81, KANJI_STANDARD, // 突 + 0x6934, KANJI_STANDARD, // 怎 + 0x5C4A, KANJI_STANDARD, // 届 + 0x9CF6, KANJI_STANDARD, // é³¶ + 0x82EB, KANJI_STANDARD, // 苫 + 0x5BC5, KANJI_STANDARD, // 寅 + 0x9149, KANJI_STANDARD, // 酉 + 0x701E, KANJI_STANDARD, // 瀞 + 0x5678, KANJI_STANDARD, // 噞 + 0x5C6F, KANJI_STANDARD, // 屯 + 0x60C7, KANJI_STANDARD, // 惇 + 0x6566, KANJI_STANDARD, // 敊 + 0x6C8C, KANJI_STANDARD, // 沌 + 0x8C5A, KANJI_STANDARD, // 豚 + 0x9041, KANJI_STANDARD, // 遁 + 0x9813, KANJI_STANDARD, // 頓 + 0x5451, KANJI_STANDARD, // 呑 + 0x66C7, KANJI_STANDARD, // 曇 + 0x920D, KANJI_STANDARD, // 鈍 + 0x5948, KANJI_STANDARD, // 奈 + 0x90A3, KANJI_STANDARD, // 那 + 0x5185, KANJI_STANDARD, // 内 + 0x4E4D, KANJI_STANDARD, // 乍 + 0x51EA, KANJI_STANDARD, // 凪 + 0x8599, KANJI_STANDARD, // 薙 + 0x8B0E, KANJI_STANDARD, // 謎 + 0x7058, KANJI_STANDARD, // 灘 + 0x637A, KANJI_STANDARD, // 捺 + 0x934B, KANJI_STANDARD, // 鍋 + 0x6962, KANJI_STANDARD, // 楢 + 0x99B4, KANJI_STANDARD, // 銎 + 0x7E04, KANJI_STANDARD, // 羄 + 0x7577, KANJI_STANDARD, // 畷 + 0x5357, KANJI_STANDARD, // 南 + 0x6960, KANJI_STANDARD, // 楠 + 0x8EDF, KANJI_STANDARD, // 軟 + 0x96E3, KANJI_STANDARD, // 難 + 0x6C5D, KANJI_STANDARD, // 汝 + 0x4E8C, KANJI_STANDARD, // 二 + 0x5C3C, KANJI_STANDARD, // å°Œ + 0x5F10, KANJI_STANDARD, // 匐 + 0x8FE9, KANJI_STANDARD, // è¿© + 0x5302, KANJI_STANDARD, // 匂 + 0x8CD1, KANJI_STANDARD, // 賑 + 0x8089, KANJI_STANDARD, // 肉 + 0x8679, KANJI_STANDARD, // 虹 + 0x5EFF, KANJI_STANDARD, // 廿 + 0x65E5, KANJI_STANDARD, // 日 + 0x4E73, KANJI_STANDARD, // ä¹³ + 0x5165, KANJI_STANDARD, // 入 + 0x5982, KANJI_STANDARD, // 劂 + 0x5C3F, KANJI_STANDARD, // å°¿ + 0x97EE, KANJI_STANDARD, // 韮 + 0x4EFB, KANJI_STANDARD, // ä»» + 0x598A, KANJI_STANDARD, // 劊 + 0x5FCD, KANJI_STANDARD, // 忍 + 0x8A8D, KANJI_STANDARD, // 認 + 0x6FE1, KANJI_STANDARD, // æ¿¡ + 0x79B0, KANJI_STANDARD, // 犰 + 0x7962, KANJI_STANDARD, // 祢 + 0x5BE7, KANJI_STANDARD, // 寧 + 0x8471, KANJI_STANDARD, // 葱 + 0x732B, KANJI_STANDARD, // 猫 + 0x71B1, KANJI_STANDARD, // 熱 + 0x5E74, KANJI_STANDARD, // 幎 + 0x5FF5, KANJI_STANDARD, // 念 + 0x637B, KANJI_STANDARD, // 捻 + 0x649A, KANJI_STANDARD, // 撚 + 0x71C3, KANJI_STANDARD, // 燃 + 0x7C98, KANJI_STANDARD, // 粘 + 0x4E43, KANJI_STANDARD, // 乃 + 0x5EFC, KANJI_STANDARD, // 廌 + 0x4E4B, KANJI_STANDARD, // 之 + 0x57DC, KANJI_STANDARD, // 埜 + 0x56A2, KANJI_STANDARD, // 嚢 + 0x60A9, KANJI_STANDARD, // 悩 + 0x6FC3, KANJI_STANDARD, // 濃 + 0x7D0D, KANJI_STANDARD, // 玍 + 0x80FD, KANJI_STANDARD, // 胜 + 0x8133, KANJI_STANDARD, // 脳 + 0x81BF, KANJI_STANDARD, // 膿 + 0x8FB2, KANJI_STANDARD, // 蟲 + 0x8997, KANJI_STANDARD, // 芗 + 0x86A4, KANJI_STANDARD, // 蚀 + 0x5DF4, KANJI_STANDARD, // å·Ž + 0x628A, KANJI_STANDARD, // 把 + 0x64AD, KANJI_STANDARD, // 播 + 0x8987, KANJI_STANDARD, // 芇 + 0x6777, KANJI_STANDARD, // 杷 + 0x6CE2, KANJI_STANDARD, // æ³¢ + 0x6D3E, KANJI_STANDARD, // 掟 + 0x7436, KANJI_STANDARD, // 琶 + 0x7834, KANJI_STANDARD, // ç Ž + 0x5A46, KANJI_STANDARD, // 婆 + 0x7F75, KANJI_STANDARD, // 眵 + 0x82AD, KANJI_STANDARD, // 芭 + 0x99AC, KANJI_STANDARD, // 銬 + 0x4FF3, KANJI_STANDARD, // 俳 + 0x5EC3, KANJI_STANDARD, // 廃 + 0x62DD, KANJI_STANDARD, // 拝 + 0x6392, KANJI_STANDARD, // 排 + 0x6557, KANJI_STANDARD, // 敗 + 0x676F, KANJI_STANDARD, // 杯 + 0x76C3, KANJI_STANDARD, // 盃 + 0x724C, KANJI_STANDARD, // 牌 + 0x80CC, KANJI_STANDARD, // 背 + 0x80BA, KANJI_STANDARD, // 肺 + 0x8F29, KANJI_STANDARD, // 茩 + 0x914D, KANJI_STANDARD, // 配 + 0x500D, KANJI_STANDARD, // 倍 + 0x57F9, KANJI_STANDARD, // 培 + 0x5A92, KANJI_STANDARD, // 媒 + 0x6885, KANJI_STANDARD, // 梅 + 0x6973, KANJI_STANDARD, // 楳 + 0x7164, KANJI_STANDARD, // ç…€ + 0x72FD, KANJI_STANDARD, // 狜 + 0x8CB7, KANJI_STANDARD, // è²· + 0x58F2, KANJI_STANDARD, // 売 + 0x8CE0, KANJI_STANDARD, // è³  + 0x966A, KANJI_STANDARD, // 陪 + 0x9019, KANJI_STANDARD, // 這 + 0x877F, KANJI_STANDARD, // 蝿 + 0x79E4, KANJI_STANDARD, // ç§€ + 0x77E7, KANJI_STANDARD, // 矧 + 0x8429, KANJI_STANDARD, // 萩 + 0x4F2F, KANJI_STANDARD, // 䌯 + 0x5265, KANJI_STANDARD, // 剥 + 0x535A, KANJI_STANDARD, // 博 + 0x62CD, KANJI_STANDARD, // 拍 + 0x67CF, KANJI_STANDARD, // 柏 + 0x6CCA, KANJI_STANDARD, // 泊 + 0x767D, KANJI_STANDARD, // 癜 + 0x7B94, KANJI_STANDARD, // 箔 + 0x7C95, KANJI_STANDARD, // 粕 + 0x8236, KANJI_STANDARD, // 舶 + 0x8584, KANJI_STANDARD, // 薄 + 0x8FEB, KANJI_STANDARD, // è¿« + 0x66DD, KANJI_STANDARD, // 曝 + 0x6F20, KANJI_STANDARD, // 挠 + 0x7206, KANJI_STANDARD, // 爆 + 0x7E1B, KANJI_STANDARD, // 羛 + 0x83AB, KANJI_STANDARD, // 莫 + 0x99C1, KANJI_STANDARD, // 駁 + 0x9EA6, KANJI_STANDARD, // 麊 + 0x51FD, KANJI_STANDARD, // 凜 + 0x7BB1, KANJI_STANDARD, // ç®± + 0x7872, KANJI_STANDARD, // 硲 + 0x7BB8, KANJI_STANDARD, // 箞 + 0x8087, KANJI_STANDARD, // 肇 + 0x7B48, KANJI_STANDARD, // 筈 + 0x6AE8, KANJI_STANDARD, // 櫚 + 0x5E61, KANJI_STANDARD, // 幡 + 0x808C, KANJI_STANDARD, // 肌 + 0x7551, KANJI_STANDARD, // 畑 + 0x7560, KANJI_STANDARD, // 畠 + 0x516B, KANJI_STANDARD, // 八 + 0x9262, KANJI_STANDARD, // 鉢 + 0x6E8C, KANJI_STANDARD, // 溌 + 0x767A, KANJI_STANDARD, // 発 + 0x9197, KANJI_STANDARD, // 醗 + 0x9AEA, KANJI_STANDARD, // 髪 + 0x4F10, KANJI_STANDARD, // 䌐 + 0x7F70, KANJI_STANDARD, // 眰 + 0x629C, KANJI_STANDARD, // 抜 + 0x7B4F, KANJI_STANDARD, // 筏 + 0x95A5, KANJI_STANDARD, // 閥 + 0x9CE9, KANJI_STANDARD, // 鳩 + 0x567A, KANJI_STANDARD, // 噺 + 0x5859, KANJI_STANDARD, // 塙 + 0x86E4, KANJI_STANDARD, // 蛀 + 0x96BC, KANJI_STANDARD, // 隌 + 0x4F34, KANJI_STANDARD, // 䌎 + 0x5224, KANJI_STANDARD, // 刀 + 0x534A, KANJI_STANDARD, // 半 + 0x53CD, KANJI_STANDARD, // 反 + 0x53DB, KANJI_STANDARD, // 叛 + 0x5E06, KANJI_STANDARD, // 垆 + 0x642C, KANJI_STANDARD, // 搬 + 0x6591, KANJI_STANDARD, // 斑 + 0x677F, KANJI_STANDARD, // 板 + 0x6C3E, KANJI_STANDARD, // æ°Ÿ + 0x6C4E, KANJI_STANDARD, // 汎 + 0x7248, KANJI_STANDARD, // 版 + 0x72AF, KANJI_STANDARD, // 犯 + 0x73ED, KANJI_STANDARD, // 班 + 0x7554, KANJI_STANDARD, // 畔 + 0x7E41, KANJI_STANDARD, // 繁 + 0x822C, KANJI_STANDARD, // 般 + 0x85E9, KANJI_STANDARD, // 藩 + 0x8CA9, KANJI_STANDARD, // 販 + 0x7BC4, KANJI_STANDARD, // 範 + 0x91C6, KANJI_STANDARD, // 釆 + 0x7169, KANJI_STANDARD, // 煩 + 0x9812, KANJI_STANDARD, // 頒 + 0x98EF, KANJI_STANDARD, // 飯 + 0x633D, KANJI_STANDARD, // 挜 + 0x6669, KANJI_STANDARD, // 晩 + 0x756A, KANJI_STANDARD, // 番 + 0x76E4, KANJI_STANDARD, // 盀 + 0x78D0, KANJI_STANDARD, // 磐 + 0x8543, KANJI_STANDARD, // 蕃 + 0x86EE, KANJI_STANDARD, // 蛮 + 0x532A, KANJI_STANDARD, // 匪 + 0x5351, KANJI_STANDARD, // 卑 + 0x5426, KANJI_STANDARD, // 吊 + 0x5983, KANJI_STANDARD, // 劃 + 0x5E87, KANJI_STANDARD, // 庇 + 0x5F7C, KANJI_STANDARD, // 圌 + 0x60B2, KANJI_STANDARD, // 悲 + 0x6249, KANJI_STANDARD, // 扉 + 0x6279, KANJI_STANDARD, // 批 + 0x62AB, KANJI_STANDARD, // 披 + 0x6590, KANJI_STANDARD, // 斐 + 0x6BD4, KANJI_STANDARD, // 比 + 0x6CCC, KANJI_STANDARD, // 泌 + 0x75B2, KANJI_STANDARD, // 疲 + 0x76AE, KANJI_STANDARD, // 皮 + 0x7891, KANJI_STANDARD, // 碑 + 0x79D8, KANJI_STANDARD, // 秘 + 0x7DCB, KANJI_STANDARD, // 緋 + 0x7F77, KANJI_STANDARD, // 眷 + 0x80A5, KANJI_STANDARD, // 肥 + 0x88AB, KANJI_STANDARD, // 被 + 0x8AB9, KANJI_STANDARD, // 誹 + 0x8CBB, KANJI_STANDARD, // è²» + 0x907F, KANJI_STANDARD, // 避 + 0x975E, KANJI_STANDARD, // 非 + 0x98DB, KANJI_STANDARD, // 飛 + 0x6A0B, KANJI_STANDARD, // æš‹ + 0x7C38, KANJI_STANDARD, // ç°ž + 0x5099, KANJI_STANDARD, // 備 + 0x5C3E, KANJI_STANDARD, // å°Ÿ + 0x5FAE, KANJI_STANDARD, // 埮 + 0x6787, KANJI_STANDARD, // 枇 + 0x6BD8, KANJI_STANDARD, // 毘 + 0x7435, KANJI_STANDARD, // 琵 + 0x7709, KANJI_STANDARD, // 眉 + 0x7F8E, KANJI_STANDARD, // 矎 + 0x9F3B, KANJI_STANDARD, // 錻 + 0x67CA, KANJI_STANDARD, // 柊 + 0x7A17, KANJI_STANDARD, // 繗 + 0x5339, KANJI_STANDARD, // 匹 + 0x758B, KANJI_STANDARD, // 疋 + 0x9AED, KANJI_STANDARD, // é«­ + 0x5F66, KANJI_STANDARD, // 圊 + 0x819D, KANJI_STANDARD, // 膝 + 0x83F1, KANJI_STANDARD, // 菱 + 0x8098, KANJI_STANDARD, // 肘 + 0x5F3C, KANJI_STANDARD, // 匌 + 0x5FC5, KANJI_STANDARD, // 必 + 0x7562, KANJI_STANDARD, // 畢 + 0x7B46, KANJI_STANDARD, // 筆 + 0x903C, KANJI_STANDARD, // 逌 + 0x6867, KANJI_STANDARD, // æ¡§ + 0x59EB, KANJI_STANDARD, // å§« + 0x5A9B, KANJI_STANDARD, // 媛 + 0x7D10, KANJI_STANDARD, // 玐 + 0x767E, KANJI_STANDARD, // 癟 + 0x8B2C, KANJI_STANDARD, // 謬 + 0x4FF5, KANJI_STANDARD, // 俵 + 0x5F6A, KANJI_STANDARD, // 圪 + 0x6A19, KANJI_STANDARD, // æš™ + 0x6C37, KANJI_STANDARD, // æ°· + 0x6F02, KANJI_STANDARD, // 挂 + 0x74E2, KANJI_STANDARD, // 瓢 + 0x7968, KANJI_STANDARD, // 祚 + 0x8868, KANJI_STANDARD, // 衚 + 0x8A55, KANJI_STANDARD, // 評 + 0x8C79, KANJI_STANDARD, // è±¹ + 0x5EDF, KANJI_STANDARD, // 廟 + 0x63CF, KANJI_STANDARD, // 描 + 0x75C5, KANJI_STANDARD, // 病 + 0x79D2, KANJI_STANDARD, // 秒 + 0x82D7, KANJI_STANDARD, // 苗 + 0x9328, KANJI_STANDARD, // 錹 + 0x92F2, KANJI_STANDARD, // 鋲 + 0x849C, KANJI_STANDARD, // 蒜 + 0x86ED, KANJI_STANDARD, // 蛭 + 0x9C2D, KANJI_STANDARD, // é°­ + 0x54C1, KANJI_STANDARD, // 品 + 0x5F6C, KANJI_STANDARD, // 圬 + 0x658C, KANJI_STANDARD, // 斌 + 0x6D5C, KANJI_STANDARD, // 浜 + 0x7015, KANJI_STANDARD, // 瀕 + 0x8CA7, KANJI_STANDARD, // è²§ + 0x8CD3, KANJI_STANDARD, // 賓 + 0x983B, KANJI_STANDARD, // é » + 0x654F, KANJI_STANDARD, // 敏 + 0x74F6, KANJI_STANDARD, // 瓶 + 0x4E0D, KANJI_STANDARD, // 䞍 + 0x4ED8, KANJI_STANDARD, // 付 + 0x57E0, KANJI_STANDARD, // 埠 + 0x592B, KANJI_STANDARD, // 倫 + 0x5A66, KANJI_STANDARD, // 婊 + 0x5BCC, KANJI_STANDARD, // 富 + 0x51A8, KANJI_STANDARD, // 冚 + 0x5E03, KANJI_STANDARD, // 垃 + 0x5E9C, KANJI_STANDARD, // 府 + 0x6016, KANJI_STANDARD, // 怖 + 0x6276, KANJI_STANDARD, // 扶 + 0x6577, KANJI_STANDARD, // 敷 + 0x65A7, KANJI_STANDARD, // 斧 + 0x666E, KANJI_STANDARD, // 普 + 0x6D6E, KANJI_STANDARD, // æµ® + 0x7236, KANJI_STANDARD, // 父 + 0x7B26, KANJI_STANDARD, // 笊 + 0x8150, KANJI_STANDARD, // 腐 + 0x819A, KANJI_STANDARD, // 膚 + 0x8299, KANJI_STANDARD, // 芙 + 0x8B5C, KANJI_STANDARD, // 譜 + 0x8CA0, KANJI_STANDARD, // è²  + 0x8CE6, KANJI_STANDARD, // 賊 + 0x8D74, KANJI_STANDARD, // 赎 + 0x961C, KANJI_STANDARD, // 阜 + 0x9644, KANJI_STANDARD, // 附 + 0x4FAE, KANJI_STANDARD, // 䟮 + 0x64AB, KANJI_STANDARD, // 撫 + 0x6B66, KANJI_STANDARD, // æ­Š + 0x821E, KANJI_STANDARD, // 舞 + 0x8461, KANJI_STANDARD, // 葡 + 0x856A, KANJI_STANDARD, // 蕪 + 0x90E8, KANJI_STANDARD, // 郚 + 0x5C01, KANJI_STANDARD, // 封 + 0x6953, KANJI_STANDARD, // 楓 + 0x98A8, KANJI_STANDARD, // 颚 + 0x847A, KANJI_STANDARD, // 葺 + 0x8557, KANJI_STANDARD, // 蕗 + 0x4F0F, KANJI_STANDARD, // 䌏 + 0x526F, KANJI_STANDARD, // 副 + 0x5FA9, KANJI_STANDARD, // 埩 + 0x5E45, KANJI_STANDARD, // 幅 + 0x670D, KANJI_STANDARD, // 服 + 0x798F, KANJI_STANDARD, // 犏 + 0x8179, KANJI_STANDARD, // 腹 + 0x8907, KANJI_STANDARD, // 耇 + 0x8986, KANJI_STANDARD, // 芆 + 0x6DF5, KANJI_STANDARD, // æ·µ + 0x5F17, KANJI_STANDARD, // 北 + 0x6255, KANJI_STANDARD, // 払 + 0x6CB8, KANJI_STANDARD, // 沞 + 0x4ECF, KANJI_STANDARD, // 仏 + 0x7269, KANJI_STANDARD, // 物 + 0x9B92, KANJI_STANDARD, // 鮒 + 0x5206, KANJI_STANDARD, // 分 + 0x543B, KANJI_STANDARD, // 吻 + 0x5674, KANJI_STANDARD, // 噎 + 0x58B3, KANJI_STANDARD, // 墳 + 0x61A4, KANJI_STANDARD, // 憀 + 0x626E, KANJI_STANDARD, // 扮 + 0x711A, KANJI_STANDARD, // 焚 + 0x596E, KANJI_STANDARD, // 奮 + 0x7C89, KANJI_STANDARD, // 粉 + 0x7CDE, KANJI_STANDARD, // 糞 + 0x7D1B, KANJI_STANDARD, // 箛 + 0x96F0, KANJI_STANDARD, // 雰 + 0x6587, KANJI_STANDARD, // 文 + 0x805E, KANJI_STANDARD, // 聞 + 0x4E19, KANJI_STANDARD, // 侙 + 0x4F75, KANJI_STANDARD, // 䜵 + 0x5175, KANJI_STANDARD, // 兵 + 0x5840, KANJI_STANDARD, // 塀 + 0x5E63, KANJI_STANDARD, // å¹£ + 0x5E73, KANJI_STANDARD, // å¹³ + 0x5F0A, KANJI_STANDARD, // 匊 + 0x67C4, KANJI_STANDARD, // 柄 + 0x4E26, KANJI_STANDARD, // 䞊 + 0x853D, KANJI_STANDARD, // 蔜 + 0x9589, KANJI_STANDARD, // 閉 + 0x965B, KANJI_STANDARD, // 陛 + 0x7C73, KANJI_STANDARD, // ç±³ + 0x9801, KANJI_STANDARD, // 頁 + 0x50FB, KANJI_STANDARD, // 僻 + 0x58C1, KANJI_STANDARD, // 壁 + 0x7656, KANJI_STANDARD, // 癖 + 0x78A7, KANJI_STANDARD, // 碧 + 0x5225, KANJI_STANDARD, // 別 + 0x77A5, KANJI_STANDARD, // 瞥 + 0x8511, KANJI_STANDARD, // 蔑 + 0x7B86, KANJI_STANDARD, // 箆 + 0x504F, KANJI_STANDARD, // 偏 + 0x5909, KANJI_STANDARD, // 倉 + 0x7247, KANJI_STANDARD, // 片 + 0x7BC7, KANJI_STANDARD, // 篇 + 0x7DE8, KANJI_STANDARD, // ç·š + 0x8FBA, KANJI_STANDARD, // 蟺 + 0x8FD4, KANJI_STANDARD, // 返 + 0x904D, KANJI_STANDARD, // 遍 + 0x4FBF, KANJI_STANDARD, // 䟿 + 0x52C9, KANJI_STANDARD, // 勉 + 0x5A29, KANJI_STANDARD, // åš© + 0x5F01, KANJI_STANDARD, // 匁 + 0x97AD, KANJI_STANDARD, // 鞭 + 0x4FDD, KANJI_STANDARD, // 保 + 0x8217, KANJI_STANDARD, // 舗 + 0x92EA, KANJI_STANDARD, // 鋪 + 0x5703, KANJI_STANDARD, // 圃 + 0x6355, KANJI_STANDARD, // 捕 + 0x6B69, KANJI_STANDARD, // æ­© + 0x752B, KANJI_STANDARD, // 甫 + 0x88DC, KANJI_STANDARD, // 補 + 0x8F14, KANJI_STANDARD, // 茔 + 0x7A42, KANJI_STANDARD, // 穂 + 0x52DF, KANJI_STANDARD, // 募 + 0x5893, KANJI_STANDARD, // 墓 + 0x6155, KANJI_STANDARD, // 慕 + 0x620A, KANJI_STANDARD, // 戊 + 0x66AE, KANJI_STANDARD, // 暮 + 0x6BCD, KANJI_STANDARD, // 母 + 0x7C3F, KANJI_STANDARD, // ç°¿ + 0x83E9, KANJI_STANDARD, // 菩 + 0x5023, KANJI_STANDARD, // 倣 + 0x4FF8, KANJI_STANDARD, // 俞 + 0x5305, KANJI_STANDARD, // 包 + 0x5446, KANJI_STANDARD, // 呆 + 0x5831, KANJI_STANDARD, // å ± + 0x5949, KANJI_STANDARD, // 奉 + 0x5B9D, KANJI_STANDARD, // 宝 + 0x5CF0, KANJI_STANDARD, // å³° + 0x5CEF, KANJI_STANDARD, // 峯 + 0x5D29, KANJI_STANDARD, // 厩 + 0x5E96, KANJI_STANDARD, // 庖 + 0x62B1, KANJI_STANDARD, // 抱 + 0x6367, KANJI_STANDARD, // 捧 + 0x653E, KANJI_STANDARD, // 攟 + 0x65B9, KANJI_STANDARD, // 方 + 0x670B, KANJI_STANDARD, // 朋 + 0x6CD5, KANJI_STANDARD, // 法 + 0x6CE1, KANJI_STANDARD, // 泡 + 0x70F9, KANJI_STANDARD, // 烹 + 0x7832, KANJI_STANDARD, // ç ² + 0x7E2B, KANJI_STANDARD, // çž« + 0x80DE, KANJI_STANDARD, // 胞 + 0x82B3, KANJI_STANDARD, // 芳 + 0x840C, KANJI_STANDARD, // 萌 + 0x84EC, KANJI_STANDARD, // 蓬 + 0x8702, KANJI_STANDARD, // 蜂 + 0x8912, KANJI_STANDARD, // 耒 + 0x8A2A, KANJI_STANDARD, // 蚪 + 0x8C4A, KANJI_STANDARD, // 豊 + 0x90A6, KANJI_STANDARD, // 邩 + 0x92D2, KANJI_STANDARD, // 鋒 + 0x98FD, KANJI_STANDARD, // 飜 + 0x9CF3, KANJI_STANDARD, // é³³ + 0x9D6C, KANJI_STANDARD, // 鵬 + 0x4E4F, KANJI_STANDARD, // 乏 + 0x4EA1, KANJI_STANDARD, // 亡 + 0x508D, KANJI_STANDARD, // 傍 + 0x5256, KANJI_STANDARD, // 剖 + 0x574A, KANJI_STANDARD, // 坊 + 0x59A8, KANJI_STANDARD, // 劚 + 0x5E3D, KANJI_STANDARD, // åžœ + 0x5FD8, KANJI_STANDARD, // 忘 + 0x5FD9, KANJI_STANDARD, // 忙 + 0x623F, KANJI_STANDARD, // 房 + 0x66B4, KANJI_STANDARD, // 暎 + 0x671B, KANJI_STANDARD, // 望 + 0x67D0, KANJI_STANDARD, // 某 + 0x68D2, KANJI_STANDARD, // 棒 + 0x5192, KANJI_STANDARD, // 冒 + 0x7D21, KANJI_STANDARD, // 玡 + 0x80AA, KANJI_STANDARD, // 肪 + 0x81A8, KANJI_STANDARD, // 膚 + 0x8B00, KANJI_STANDARD, // 謀 + 0x8C8C, KANJI_STANDARD, // 貌 + 0x8CBF, KANJI_STANDARD, // 貿 + 0x927E, KANJI_STANDARD, // 鉟 + 0x9632, KANJI_STANDARD, // 防 + 0x5420, KANJI_STANDARD, // 吠 + 0x982C, KANJI_STANDARD, // é ¬ + 0x5317, KANJI_STANDARD, // 北 + 0x50D5, KANJI_STANDARD, // 僕 + 0x535C, KANJI_STANDARD, // 卜 + 0x58A8, KANJI_STANDARD, // 墚 + 0x64B2, KANJI_STANDARD, // 撲 + 0x6734, KANJI_STANDARD, // 朎 + 0x7267, KANJI_STANDARD, // 牧 + 0x7766, KANJI_STANDARD, // 睊 + 0x7A46, KANJI_STANDARD, // 穆 + 0x91E6, KANJI_STANDARD, // 釩 + 0x52C3, KANJI_STANDARD, // 勃 + 0x6CA1, KANJI_STANDARD, // 没 + 0x6B86, KANJI_STANDARD, // 殆 + 0x5800, KANJI_STANDARD, // 堀 + 0x5E4C, KANJI_STANDARD, // 幌 + 0x5954, KANJI_STANDARD, // 奔 + 0x672C, KANJI_STANDARD, // 本 + 0x7FFB, KANJI_STANDARD, // ç¿» + 0x51E1, KANJI_STANDARD, // 凡 + 0x76C6, KANJI_STANDARD, // 盆 + 0x6469, KANJI_STANDARD, // 摩 + 0x78E8, KANJI_STANDARD, // 磚 + 0x9B54, KANJI_STANDARD, // 魔 + 0x9EBB, KANJI_STANDARD, // 麻 + 0x57CB, KANJI_STANDARD, // 埋 + 0x59B9, KANJI_STANDARD, // 効 + 0x6627, KANJI_STANDARD, // 昧 + 0x679A, KANJI_STANDARD, // 枚 + 0x6BCE, KANJI_STANDARD, // 毎 + 0x54E9, KANJI_STANDARD, // 哩 + 0x69D9, KANJI_STANDARD, // 槙 + 0x5E55, KANJI_STANDARD, // 幕 + 0x819C, KANJI_STANDARD, // 膜 + 0x6795, KANJI_STANDARD, // 枕 + 0x9BAA, KANJI_STANDARD, // 鮪 + 0x67FE, KANJI_STANDARD, // 柟 + 0x9C52, KANJI_STANDARD, // 鱒 + 0x685D, KANJI_STANDARD, // 桝 + 0x4EA6, KANJI_STANDARD, // 亊 + 0x4FE3, KANJI_STANDARD, // ä¿£ + 0x53C8, KANJI_STANDARD, // 又 + 0x62B9, KANJI_STANDARD, // 抹 + 0x672B, KANJI_STANDARD, // 末 + 0x6CAB, KANJI_STANDARD, // 沫 + 0x8FC4, KANJI_STANDARD, // 迄 + 0x4FAD, KANJI_STANDARD, // 䟭 + 0x7E6D, KANJI_STANDARD, // ç¹­ + 0x9EBF, KANJI_STANDARD, // 麿 + 0x4E07, KANJI_STANDARD, // 侇 + 0x6162, KANJI_STANDARD, // 慢 + 0x6E80, KANJI_STANDARD, // 満 + 0x6F2B, KANJI_STANDARD, // 挫 + 0x8513, KANJI_STANDARD, // 蔓 + 0x5473, KANJI_STANDARD, // 味 + 0x672A, KANJI_STANDARD, // 未 + 0x9B45, KANJI_STANDARD, // 魅 + 0x5DF3, KANJI_STANDARD, // å·³ + 0x7B95, KANJI_STANDARD, // 箕 + 0x5CAC, KANJI_STANDARD, // 岬 + 0x5BC6, KANJI_STANDARD, // 密 + 0x871C, KANJI_STANDARD, // 蜜 + 0x6E4A, KANJI_STANDARD, // 湊 + 0x84D1, KANJI_STANDARD, // 蓑 + 0x7A14, KANJI_STANDARD, // 織 + 0x8108, KANJI_STANDARD, // 脈 + 0x5999, KANJI_STANDARD, // 劙 + 0x7C8D, KANJI_STANDARD, // 粍 + 0x6C11, KANJI_STANDARD, // 民 + 0x7720, KANJI_STANDARD, // 眠 + 0x52D9, KANJI_STANDARD, // 務 + 0x5922, KANJI_STANDARD, // 倢 + 0x7121, KANJI_STANDARD, // 無 + 0x725F, KANJI_STANDARD, // 牟 + 0x77DB, KANJI_STANDARD, // 矛 + 0x9727, KANJI_STANDARD, // 霧 + 0x9D61, KANJI_STANDARD, // 鵡 + 0x690B, KANJI_STANDARD, // 怋 + 0x5A7F, KANJI_STANDARD, // å©¿ + 0x5A18, KANJI_STANDARD, // 嚘 + 0x51A5, KANJI_STANDARD, // 冥 + 0x540D, KANJI_STANDARD, // 名 + 0x547D, KANJI_STANDARD, // 呜 + 0x660E, KANJI_STANDARD, // 明 + 0x76DF, KANJI_STANDARD, // 盟 + 0x8FF7, KANJI_STANDARD, // è¿· + 0x9298, KANJI_STANDARD, // 銘 + 0x9CF4, KANJI_STANDARD, // 鳎 + 0x59EA, KANJI_STANDARD, // 姪 + 0x725D, KANJI_STANDARD, // 牝 + 0x6EC5, KANJI_STANDARD, // 滅 + 0x514D, KANJI_STANDARD, // 免 + 0x68C9, KANJI_STANDARD, // 棉 + 0x7DBF, KANJI_STANDARD, // ç¶¿ + 0x7DEC, KANJI_STANDARD, // ç·¬ + 0x9762, KANJI_STANDARD, // 面 + 0x9EBA, KANJI_STANDARD, // 麺 + 0x6478, KANJI_STANDARD, // 摞 + 0x6A21, KANJI_STANDARD, // æš¡ + 0x8302, KANJI_STANDARD, // 茂 + 0x5984, KANJI_STANDARD, // 劄 + 0x5B5F, KANJI_STANDARD, // 孟 + 0x6BDB, KANJI_STANDARD, // 毛 + 0x731B, KANJI_STANDARD, // 猛 + 0x76F2, KANJI_STANDARD, // 盲 + 0x7DB2, KANJI_STANDARD, // ç¶² + 0x8017, KANJI_STANDARD, // 耗 + 0x8499, KANJI_STANDARD, // 蒙 + 0x5132, KANJI_STANDARD, // 儲 + 0x6728, KANJI_STANDARD, // 朚 + 0x9ED9, KANJI_STANDARD, // 黙 + 0x76EE, KANJI_STANDARD, // 目 + 0x6762, KANJI_STANDARD, // 杢 + 0x52FF, KANJI_STANDARD, // 勿 + 0x9905, KANJI_STANDARD, // 逅 + 0x5C24, KANJI_STANDARD, // å°€ + 0x623B, KANJI_STANDARD, // 戻 + 0x7C7E, KANJI_STANDARD, // 籟 + 0x8CB0, KANJI_STANDARD, // è²° + 0x554F, KANJI_STANDARD, // 問 + 0x60B6, KANJI_STANDARD, // 悶 + 0x7D0B, KANJI_STANDARD, // 箋 + 0x9580, KANJI_STANDARD, // 門 + 0x5301, KANJI_STANDARD, // 匁 + 0x4E5F, KANJI_STANDARD, // 也 + 0x51B6, KANJI_STANDARD, // 冶 + 0x591C, KANJI_STANDARD, // 倜 + 0x723A, KANJI_STANDARD, // 爺 + 0x8036, KANJI_STANDARD, // 耶 + 0x91CE, KANJI_STANDARD, // 野 + 0x5F25, KANJI_STANDARD, // 匥 + 0x77E2, KANJI_STANDARD, // 矢 + 0x5384, KANJI_STANDARD, // 厄 + 0x5F79, KANJI_STANDARD, // 圹 + 0x7D04, KANJI_STANDARD, // 箄 + 0x85AC, KANJI_STANDARD, // 薬 + 0x8A33, KANJI_STANDARD, // èš³ + 0x8E8D, KANJI_STANDARD, // 躍 + 0x9756, KANJI_STANDARD, // 靖 + 0x67F3, KANJI_STANDARD, // 柳 + 0x85AE, KANJI_STANDARD, // 薮 + 0x9453, KANJI_STANDARD, // 鑓 + 0x6109, KANJI_STANDARD, // 愉 + 0x6108, KANJI_STANDARD, // 愈 + 0x6CB9, KANJI_STANDARD, // æ²¹ + 0x7652, KANJI_STANDARD, // 癒 + 0x8AED, KANJI_STANDARD, // è«­ + 0x8F38, KANJI_STANDARD, // 茞 + 0x552F, KANJI_STANDARD, // 唯 + 0x4F51, KANJI_STANDARD, // 䜑 + 0x512A, KANJI_STANDARD, // 優 + 0x52C7, KANJI_STANDARD, // 勇 + 0x53CB, KANJI_STANDARD, // 友 + 0x5BA5, KANJI_STANDARD, // 宥 + 0x5E7D, KANJI_STANDARD, // 幜 + 0x60A0, KANJI_STANDARD, // 悠 + 0x6182, KANJI_STANDARD, // 憂 + 0x63D6, KANJI_STANDARD, // 揖 + 0x6709, KANJI_STANDARD, // 有 + 0x67DA, KANJI_STANDARD, // 柚 + 0x6E67, KANJI_STANDARD, // æ¹§ + 0x6D8C, KANJI_STANDARD, // 涌 + 0x7336, KANJI_STANDARD, // 猶 + 0x7337, KANJI_STANDARD, // 猷 + 0x7531, KANJI_STANDARD, // 由 + 0x7950, KANJI_STANDARD, // 祐 + 0x88D5, KANJI_STANDARD, // 裕 + 0x8A98, KANJI_STANDARD, // 誘 + 0x904A, KANJI_STANDARD, // 遊 + 0x9091, KANJI_STANDARD, // 邑 + 0x90F5, KANJI_STANDARD, // 郵 + 0x96C4, KANJI_STANDARD, // 雄 + 0x878D, KANJI_STANDARD, // 融 + 0x5915, KANJI_STANDARD, // 倕 + 0x4E88, KANJI_STANDARD, // 予 + 0x4F59, KANJI_STANDARD, // 䜙 + 0x4E0E, KANJI_STANDARD, // 侎 + 0x8A89, KANJI_STANDARD, // 誉 + 0x8F3F, KANJI_STANDARD, // 茿 + 0x9810, KANJI_STANDARD, // 預 + 0x50AD, KANJI_STANDARD, // 傭 + 0x5E7C, KANJI_STANDARD, // 幌 + 0x5996, KANJI_STANDARD, // 劖 + 0x5BB9, KANJI_STANDARD, // 容 + 0x5EB8, KANJI_STANDARD, // 庞 + 0x63DA, KANJI_STANDARD, // 揚 + 0x63FA, KANJI_STANDARD, // 揺 + 0x64C1, KANJI_STANDARD, // 擁 + 0x66DC, KANJI_STANDARD, // 曜 + 0x694A, KANJI_STANDARD, // 楊 + 0x69D8, KANJI_STANDARD, // 様 + 0x6D0B, KANJI_STANDARD, // 掋 + 0x6EB6, KANJI_STANDARD, // 溶 + 0x7194, KANJI_STANDARD, // 熔 + 0x7528, KANJI_STANDARD, // 甹 + 0x7AAF, KANJI_STANDARD, // 窯 + 0x7F8A, KANJI_STANDARD, // 矊 + 0x8000, KANJI_STANDARD, // 耀 + 0x8449, KANJI_STANDARD, // 葉 + 0x84C9, KANJI_STANDARD, // 蓉 + 0x8981, KANJI_STANDARD, // 芁 + 0x8B21, KANJI_STANDARD, // 謡 + 0x8E0A, KANJI_STANDARD, // 螊 + 0x9065, KANJI_STANDARD, // 遥 + 0x967D, KANJI_STANDARD, // 陜 + 0x990A, KANJI_STANDARD, // 逊 + 0x617E, KANJI_STANDARD, // æ…Ÿ + 0x6291, KANJI_STANDARD, // 抑 + 0x6B32, KANJI_STANDARD, // 欲 + 0x6C83, KANJI_STANDARD, // 沃 + 0x6D74, KANJI_STANDARD, // 济 + 0x7FCC, KANJI_STANDARD, // 翌 + 0x7FFC, KANJI_STANDARD, // 翌 + 0x6DC0, KANJI_STANDARD, // 淀 + 0x7F85, KANJI_STANDARD, // 矅 + 0x87BA, KANJI_STANDARD, // 螺 + 0x88F8, KANJI_STANDARD, // 裞 + 0x6765, KANJI_STANDARD, // 来 + 0x83B1, KANJI_STANDARD, // 莱 + 0x983C, KANJI_STANDARD, // é Œ + 0x96F7, KANJI_STANDARD, // 雷 + 0x6D1B, KANJI_STANDARD, // 掛 + 0x7D61, KANJI_STANDARD, // 絡 + 0x843D, KANJI_STANDARD, // 萜 + 0x916A, KANJI_STANDARD, // 酪 + 0x4E71, KANJI_STANDARD, // ä¹± + 0x5375, KANJI_STANDARD, // 卵 + 0x5D50, KANJI_STANDARD, // 嵐 + 0x6B04, KANJI_STANDARD, // 欄 + 0x6FEB, KANJI_STANDARD, // æ¿« + 0x85CD, KANJI_STANDARD, // 藍 + 0x862D, KANJI_STANDARD, // 蘭 + 0x89A7, KANJI_STANDARD, // 芧 + 0x5229, KANJI_STANDARD, // 利 + 0x540F, KANJI_STANDARD, // 吏 + 0x5C65, KANJI_STANDARD, // å±¥ + 0x674E, KANJI_STANDARD, // 李 + 0x68A8, KANJI_STANDARD, // 梚 + 0x7406, KANJI_STANDARD, // 理 + 0x7483, KANJI_STANDARD, // 璃 + 0x75E2, KANJI_STANDARD, // 痢 + 0x88CF, KANJI_STANDARD, // 裏 + 0x88E1, KANJI_STANDARD, // 裡 + 0x91CC, KANJI_STANDARD, // 里 + 0x96E2, KANJI_STANDARD, // 離 + 0x9678, KANJI_STANDARD, // 陾 + 0x5F8B, KANJI_STANDARD, // 埋 + 0x7387, KANJI_STANDARD, // 率 + 0x7ACB, KANJI_STANDARD, // 立 + 0x844E, KANJI_STANDARD, // 葎 + 0x63A0, KANJI_STANDARD, // 掠 + 0x7565, KANJI_STANDARD, // 略 + 0x5289, KANJI_STANDARD, // 劉 + 0x6D41, KANJI_STANDARD, // 流 + 0x6E9C, KANJI_STANDARD, // 溜 + 0x7409, KANJI_STANDARD, // 琉 + 0x7559, KANJI_STANDARD, // 留 + 0x786B, KANJI_STANDARD, // ç¡« + 0x7C92, KANJI_STANDARD, // 粒 + 0x9686, KANJI_STANDARD, // 隆 + 0x7ADC, KANJI_STANDARD, // 竜 + 0x9F8D, KANJI_STANDARD, // 韍 + 0x4FB6, KANJI_STANDARD, // 䟶 + 0x616E, KANJI_STANDARD, // 慮 + 0x65C5, KANJI_STANDARD, // 旅 + 0x865C, KANJI_STANDARD, // 虜 + 0x4E86, KANJI_STANDARD, // 了 + 0x4EAE, KANJI_STANDARD, // 亮 + 0x50DA, KANJI_STANDARD, // 僚 + 0x4E21, KANJI_STANDARD, // äž¡ + 0x51CC, KANJI_STANDARD, // 凌 + 0x5BEE, KANJI_STANDARD, // 寮 + 0x6599, KANJI_STANDARD, // 料 + 0x6881, KANJI_STANDARD, // 梁 + 0x6DBC, KANJI_STANDARD, // æ¶Œ + 0x731F, KANJI_STANDARD, // 猟 + 0x7642, KANJI_STANDARD, // 療 + 0x77AD, KANJI_STANDARD, // 瞭 + 0x7A1C, KANJI_STANDARD, // 繜 + 0x7CE7, KANJI_STANDARD, // ç³§ + 0x826F, KANJI_STANDARD, // 良 + 0x8AD2, KANJI_STANDARD, // 諒 + 0x907C, KANJI_STANDARD, // 遌 + 0x91CF, KANJI_STANDARD, // 量 + 0x9675, KANJI_STANDARD, // 陵 + 0x9818, KANJI_STANDARD, // 領 + 0x529B, KANJI_STANDARD, // 力 + 0x7DD1, KANJI_STANDARD, // 緑 + 0x502B, KANJI_STANDARD, // 倫 + 0x5398, KANJI_STANDARD, // 厘 + 0x6797, KANJI_STANDARD, // 林 + 0x6DCB, KANJI_STANDARD, // 淋 + 0x71D0, KANJI_STANDARD, // 燐 + 0x7433, KANJI_STANDARD, // 琳 + 0x81E8, KANJI_STANDARD, // 臚 + 0x8F2A, KANJI_STANDARD, // 茪 + 0x96A3, KANJI_STANDARD, // 隣 + 0x9C57, KANJI_STANDARD, // 鱗 + 0x9E9F, KANJI_STANDARD, // 麟 + 0x7460, KANJI_STANDARD, // 瑠 + 0x5841, KANJI_STANDARD, // 塁 + 0x6D99, KANJI_STANDARD, // 涙 + 0x7D2F, KANJI_STANDARD, // 环 + 0x985E, KANJI_STANDARD, // 類 + 0x4EE4, KANJI_STANDARD, // 什 + 0x4F36, KANJI_STANDARD, // 䌶 + 0x4F8B, KANJI_STANDARD, // 䟋 + 0x51B7, KANJI_STANDARD, // 冷 + 0x52B1, KANJI_STANDARD, // 励 + 0x5DBA, KANJI_STANDARD, // 嶺 + 0x601C, KANJI_STANDARD, // 怜 + 0x73B2, KANJI_STANDARD, // 玲 + 0x793C, KANJI_STANDARD, // 瀌 + 0x82D3, KANJI_STANDARD, // 苓 + 0x9234, KANJI_STANDARD, // 鈎 + 0x96B7, KANJI_STANDARD, // 隷 + 0x96F6, KANJI_STANDARD, // 零 + 0x970A, KANJI_STANDARD, // 霊 + 0x9E97, KANJI_STANDARD, // 麗 + 0x9F62, KANJI_STANDARD, // 霢 + 0x66A6, KANJI_STANDARD, // 暊 + 0x6B74, KANJI_STANDARD, // æ­Ž + 0x5217, KANJI_STANDARD, // 列 + 0x52A3, KANJI_STANDARD, // 劣 + 0x70C8, KANJI_STANDARD, // 烈 + 0x88C2, KANJI_STANDARD, // 裂 + 0x5EC9, KANJI_STANDARD, // 廉 + 0x604B, KANJI_STANDARD, // 恋 + 0x6190, KANJI_STANDARD, // 憐 + 0x6F23, KANJI_STANDARD, // 挣 + 0x7149, KANJI_STANDARD, // 煉 + 0x7C3E, KANJI_STANDARD, // ç°Ÿ + 0x7DF4, KANJI_STANDARD, // ç·Ž + 0x806F, KANJI_STANDARD, // 聯 + 0x84EE, KANJI_STANDARD, // 蓮 + 0x9023, KANJI_STANDARD, // 連 + 0x932C, KANJI_STANDARD, // 錬 + 0x5442, KANJI_STANDARD, // 呂 + 0x9B6F, KANJI_STANDARD, // é­¯ + 0x6AD3, KANJI_STANDARD, // 櫓 + 0x7089, KANJI_STANDARD, // 炉 + 0x8CC2, KANJI_STANDARD, // 賂 + 0x8DEF, KANJI_STANDARD, // è·¯ + 0x9732, KANJI_STANDARD, // 露 + 0x52B4, KANJI_STANDARD, // 劎 + 0x5A41, KANJI_STANDARD, // 婁 + 0x5ECA, KANJI_STANDARD, // 廊 + 0x5F04, KANJI_STANDARD, // 匄 + 0x6717, KANJI_STANDARD, // 朗 + 0x697C, KANJI_STANDARD, // 楌 + 0x6994, KANJI_STANDARD, // 抔 + 0x6D6A, KANJI_STANDARD, // 浪 + 0x6F0F, KANJI_STANDARD, // 挏 + 0x7262, KANJI_STANDARD, // 牢 + 0x72FC, KANJI_STANDARD, // 狌 + 0x7BED, KANJI_STANDARD, // 篭 + 0x8001, KANJI_STANDARD, // 老 + 0x807E, KANJI_STANDARD, // 聟 + 0x874B, KANJI_STANDARD, // 蝋 + 0x90CE, KANJI_STANDARD, // 郎 + 0x516D, KANJI_STANDARD, // 六 + 0x9E93, KANJI_STANDARD, // 麓 + 0x7984, KANJI_STANDARD, // 穄 + 0x808B, KANJI_STANDARD, // 肋 + 0x9332, KANJI_STANDARD, // 録 + 0x8AD6, KANJI_STANDARD, // 論 + 0x502D, KANJI_STANDARD, // 倭 + 0x548C, KANJI_STANDARD, // 和 + 0x8A71, KANJI_STANDARD, // 話 + 0x6B6A, KANJI_STANDARD, // æ­ª + 0x8CC4, KANJI_STANDARD, // 賄 + 0x8107, KANJI_STANDARD, // 脇 + 0x60D1, KANJI_STANDARD, // 惑 + 0x67A0, KANJI_STANDARD, // 枠 + 0x9DF2, KANJI_STANDARD, // é·² + 0x4E99, KANJI_STANDARD, // 亙 + 0x4E98, KANJI_STANDARD, // 亘 + 0x9C10, KANJI_STANDARD, // 鰐 + 0x8A6B, KANJI_STANDARD, // è©« + 0x85C1, KANJI_STANDARD, // 藁 + 0x8568, KANJI_STANDARD, // 蕚 + 0x6900, KANJI_STANDARD, // 怀 + 0x6E7E, KANJI_STANDARD, // 湟 + 0x7897, KANJI_STANDARD, // 碗 + 0x8155, KANJI_STANDARD, // 腕 + 0x5F0C, KANJI_STANDARD, // 匌 + 0x4E10, KANJI_STANDARD, // 䞐 + 0x4E15, KANJI_STANDARD, // 侕 + 0x4E2A, KANJI_STANDARD, // 䞪 + 0x4E31, KANJI_STANDARD, // äž± + 0x4E36, KANJI_STANDARD, // äž¶ + 0x4E3C, KANJI_STANDARD, // 䞌 + 0x4E3F, KANJI_STANDARD, // äž¿ + 0x4E42, KANJI_STANDARD, // 乂 + 0x4E56, KANJI_STANDARD, // 乖 + 0x4E58, KANJI_STANDARD, // 乘 + 0x4E82, KANJI_STANDARD, // 亂 + 0x4E85, KANJI_STANDARD, // 亅 + 0x8C6B, KANJI_STANDARD, // 豫 + 0x4E8A, KANJI_STANDARD, // 亊 + 0x8212, KANJI_STANDARD, // 舒 + 0x5F0D, KANJI_STANDARD, // 匍 + 0x4E8E, KANJI_STANDARD, // 于 + 0x4E9E, KANJI_STANDARD, // 亞 + 0x4E9F, KANJI_STANDARD, // 亟 + 0x4EA0, KANJI_STANDARD, // 亠 + 0x4EA2, KANJI_STANDARD, // 亢 + 0x4EB0, KANJI_STANDARD, // 亰 + 0x4EB3, KANJI_STANDARD, // 亳 + 0x4EB6, KANJI_STANDARD, // 亶 + 0x4ECE, KANJI_STANDARD, // 从 + 0x4ECD, KANJI_STANDARD, // 仍 + 0x4EC4, KANJI_STANDARD, // 仄 + 0x4EC6, KANJI_STANDARD, // 仆 + 0x4EC2, KANJI_STANDARD, // 仂 + 0x4ED7, KANJI_STANDARD, // 仗 + 0x4EDE, KANJI_STANDARD, // 仞 + 0x4EED, KANJI_STANDARD, // ä»­ + 0x4EDF, KANJI_STANDARD, // 仟 + 0x4EF7, KANJI_STANDARD, // ä»· + 0x4F09, KANJI_STANDARD, // 䌉 + 0x4F5A, KANJI_STANDARD, // 䜚 + 0x4F30, KANJI_STANDARD, // 䌰 + 0x4F5B, KANJI_STANDARD, // 䜛 + 0x4F5D, KANJI_STANDARD, // 䜝 + 0x4F57, KANJI_STANDARD, // 䜗 + 0x4F47, KANJI_STANDARD, // 䜇 + 0x4F76, KANJI_STANDARD, // 䜶 + 0x4F88, KANJI_STANDARD, // 䟈 + 0x4F8F, KANJI_STANDARD, // 䟏 + 0x4F98, KANJI_STANDARD, // 䟘 + 0x4F7B, KANJI_STANDARD, // 䜻 + 0x4F69, KANJI_STANDARD, // 䜩 + 0x4F70, KANJI_STANDARD, // 䜰 + 0x4F91, KANJI_STANDARD, // 䟑 + 0x4F6F, KANJI_STANDARD, // 䜯 + 0x4F86, KANJI_STANDARD, // 䟆 + 0x4F96, KANJI_STANDARD, // 䟖 + 0x5118, KANJI_STANDARD, // 儘 + 0x4FD4, KANJI_STANDARD, // 俔 + 0x4FDF, KANJI_STANDARD, // 俟 + 0x4FCE, KANJI_STANDARD, // 俎 + 0x4FD8, KANJI_STANDARD, // 俘 + 0x4FDB, KANJI_STANDARD, // 俛 + 0x4FD1, KANJI_STANDARD, // 俑 + 0x4FDA, KANJI_STANDARD, // 俚 + 0x4FD0, KANJI_STANDARD, // 俐 + 0x4FE4, KANJI_STANDARD, // ä¿€ + 0x4FE5, KANJI_STANDARD, // ä¿¥ + 0x501A, KANJI_STANDARD, // 倚 + 0x5028, KANJI_STANDARD, // 倚 + 0x5014, KANJI_STANDARD, // 倔 + 0x502A, KANJI_STANDARD, // 倪 + 0x5025, KANJI_STANDARD, // 倥 + 0x5005, KANJI_STANDARD, // 倅 + 0x4F1C, KANJI_STANDARD, // 䌜 + 0x4FF6, KANJI_STANDARD, // ä¿¶ + 0x5021, KANJI_STANDARD, // 倡 + 0x5029, KANJI_STANDARD, // 倩 + 0x502C, KANJI_STANDARD, // 倬 + 0x4FFE, KANJI_STANDARD, // 俟 + 0x4FEF, KANJI_STANDARD, // 俯 + 0x5011, KANJI_STANDARD, // 們 + 0x5006, KANJI_STANDARD, // 倆 + 0x5043, KANJI_STANDARD, // 偃 + 0x5047, KANJI_STANDARD, // 假 + 0x6703, KANJI_STANDARD, // 會 + 0x5055, KANJI_STANDARD, // 偕 + 0x5050, KANJI_STANDARD, // 偐 + 0x5048, KANJI_STANDARD, // 偈 + 0x505A, KANJI_STANDARD, // 做 + 0x5056, KANJI_STANDARD, // 偖 + 0x506C, KANJI_STANDARD, // 偬 + 0x5078, KANJI_STANDARD, // 偞 + 0x5080, KANJI_STANDARD, // 傀 + 0x509A, KANJI_STANDARD, // 傚 + 0x5085, KANJI_STANDARD, // 傅 + 0x50B4, KANJI_STANDARD, // 傎 + 0x50B2, KANJI_STANDARD, // 傲 + 0x50C9, KANJI_STANDARD, // 僉 + 0x50CA, KANJI_STANDARD, // 僊 + 0x50B3, KANJI_STANDARD, // 傳 + 0x50C2, KANJI_STANDARD, // 僂 + 0x50D6, KANJI_STANDARD, // 僖 + 0x50DE, KANJI_STANDARD, // 僞 + 0x50E5, KANJI_STANDARD, // 僥 + 0x50ED, KANJI_STANDARD, // 僭 + 0x50E3, KANJI_STANDARD, // 僣 + 0x50EE, KANJI_STANDARD, // 僮 + 0x50F9, KANJI_STANDARD, // 價 + 0x50F5, KANJI_STANDARD, // 僵 + 0x5109, KANJI_STANDARD, // 儉 + 0x5101, KANJI_STANDARD, // 儁 + 0x5102, KANJI_STANDARD, // 儂 + 0x5116, KANJI_STANDARD, // 儖 + 0x5115, KANJI_STANDARD, // 儕 + 0x5114, KANJI_STANDARD, // 儔 + 0x511A, KANJI_STANDARD, // 儚 + 0x5121, KANJI_STANDARD, // 儡 + 0x513A, KANJI_STANDARD, // 儺 + 0x5137, KANJI_STANDARD, // 儷 + 0x513C, KANJI_STANDARD, // 儌 + 0x513B, KANJI_STANDARD, // 儻 + 0x513F, KANJI_STANDARD, // 儿 + 0x5140, KANJI_STANDARD, // 兀 + 0x5152, KANJI_STANDARD, // 兒 + 0x514C, KANJI_STANDARD, // 兌 + 0x5154, KANJI_STANDARD, // 兔 + 0x5162, KANJI_STANDARD, // 兢 + 0x7AF8, KANJI_STANDARD, // 竞 + 0x5169, KANJI_STANDARD, // 兩 + 0x516A, KANJI_STANDARD, // 兪 + 0x516E, KANJI_STANDARD, // 兮 + 0x5180, KANJI_STANDARD, // 冀 + 0x5182, KANJI_STANDARD, // 冂 + 0x56D8, KANJI_STANDARD, // 囘 + 0x518C, KANJI_STANDARD, // 册 + 0x5189, KANJI_STANDARD, // 冉 + 0x518F, KANJI_STANDARD, // 冏 + 0x5191, KANJI_STANDARD, // 冑 + 0x5193, KANJI_STANDARD, // 冓 + 0x5195, KANJI_STANDARD, // 冕 + 0x5196, KANJI_STANDARD, // 冖 + 0x51A4, KANJI_STANDARD, // 冀 + 0x51A6, KANJI_STANDARD, // 冊 + 0x51A2, KANJI_STANDARD, // 冢 + 0x51A9, KANJI_STANDARD, // 冩 + 0x51AA, KANJI_STANDARD, // 冪 + 0x51AB, KANJI_STANDARD, // 冫 + 0x51B3, KANJI_STANDARD, // 决 + 0x51B1, KANJI_STANDARD, // 冱 + 0x51B2, KANJI_STANDARD, // 冲 + 0x51B0, KANJI_STANDARD, // 冰 + 0x51B5, KANJI_STANDARD, // 况 + 0x51BD, KANJI_STANDARD, // 农 + 0x51C5, KANJI_STANDARD, // 凅 + 0x51C9, KANJI_STANDARD, // 凉 + 0x51DB, KANJI_STANDARD, // 凛 + 0x51E0, KANJI_STANDARD, // 几 + 0x8655, KANJI_STANDARD, // 處 + 0x51E9, KANJI_STANDARD, // 凩 + 0x51ED, KANJI_STANDARD, // 凭 + 0x51F0, KANJI_STANDARD, // 凰 + 0x51F5, KANJI_STANDARD, // 凵 + 0x51FE, KANJI_STANDARD, // 凟 + 0x5204, KANJI_STANDARD, // 刄 + 0x520B, KANJI_STANDARD, // 刋 + 0x5214, KANJI_STANDARD, // 刔 + 0x520E, KANJI_STANDARD, // 刎 + 0x5227, KANJI_STANDARD, // 刧 + 0x522A, KANJI_STANDARD, // 刪 + 0x522E, KANJI_STANDARD, // 刮 + 0x5233, KANJI_STANDARD, // 刳 + 0x5239, KANJI_STANDARD, // 刹 + 0x524F, KANJI_STANDARD, // 剏 + 0x5244, KANJI_STANDARD, // 剄 + 0x524B, KANJI_STANDARD, // 剋 + 0x524C, KANJI_STANDARD, // 剌 + 0x525E, KANJI_STANDARD, // 剞 + 0x5254, KANJI_STANDARD, // 剔 + 0x526A, KANJI_STANDARD, // 剪 + 0x5274, KANJI_STANDARD, // 剎 + 0x5269, KANJI_STANDARD, // 剩 + 0x5273, KANJI_STANDARD, // 剳 + 0x527F, KANJI_STANDARD, // 剿 + 0x527D, KANJI_STANDARD, // 剜 + 0x528D, KANJI_STANDARD, // 劍 + 0x5294, KANJI_STANDARD, // 劔 + 0x5292, KANJI_STANDARD, // 劒 + 0x5271, KANJI_STANDARD, // 剱 + 0x5288, KANJI_STANDARD, // 劈 + 0x5291, KANJI_STANDARD, // 劑 + 0x8FA8, KANJI_STANDARD, // 蟚 + 0x8FA7, KANJI_STANDARD, // 蟧 + 0x52AC, KANJI_STANDARD, // 劬 + 0x52AD, KANJI_STANDARD, // 劭 + 0x52BC, KANJI_STANDARD, // 劌 + 0x52B5, KANJI_STANDARD, // 劵 + 0x52C1, KANJI_STANDARD, // 勁 + 0x52CD, KANJI_STANDARD, // 勍 + 0x52D7, KANJI_STANDARD, // 勗 + 0x52DE, KANJI_STANDARD, // 勞 + 0x52E3, KANJI_STANDARD, // 勣 + 0x52E6, KANJI_STANDARD, // 勊 + 0x98ED, KANJI_STANDARD, // 飭 + 0x52E0, KANJI_STANDARD, // 勠 + 0x52F3, KANJI_STANDARD, // 勳 + 0x52F5, KANJI_STANDARD, // 勵 + 0x52F8, KANJI_STANDARD, // 勞 + 0x52F9, KANJI_STANDARD, // 勹 + 0x5306, KANJI_STANDARD, // 匆 + 0x5308, KANJI_STANDARD, // 匈 + 0x7538, KANJI_STANDARD, // 甾 + 0x530D, KANJI_STANDARD, // 匍 + 0x5310, KANJI_STANDARD, // 匐 + 0x530F, KANJI_STANDARD, // 匏 + 0x5315, KANJI_STANDARD, // 匕 + 0x531A, KANJI_STANDARD, // 匚 + 0x5323, KANJI_STANDARD, // 匣 + 0x532F, KANJI_STANDARD, // 匯 + 0x5331, KANJI_STANDARD, // 匱 + 0x5333, KANJI_STANDARD, // 匳 + 0x5338, KANJI_STANDARD, // 匞 + 0x5340, KANJI_STANDARD, // 區 + 0x5346, KANJI_STANDARD, // 卆 + 0x5345, KANJI_STANDARD, // 卅 + 0x4E17, KANJI_STANDARD, // 侗 + 0x5349, KANJI_STANDARD, // 卉 + 0x534D, KANJI_STANDARD, // 卍 + 0x51D6, KANJI_STANDARD, // 凖 + 0x535E, KANJI_STANDARD, // 卞 + 0x5369, KANJI_STANDARD, // 卩 + 0x536E, KANJI_STANDARD, // 卮 + 0x5918, KANJI_STANDARD, // 倘 + 0x537B, KANJI_STANDARD, // 卻 + 0x5377, KANJI_STANDARD, // 卷 + 0x5382, KANJI_STANDARD, // 厂 + 0x5396, KANJI_STANDARD, // 厖 + 0x53A0, KANJI_STANDARD, // 厠 + 0x53A6, KANJI_STANDARD, // 厊 + 0x53A5, KANJI_STANDARD, // 厥 + 0x53AE, KANJI_STANDARD, // 厮 + 0x53B0, KANJI_STANDARD, // 厰 + 0x53B6, KANJI_STANDARD, // 厶 + 0x53C3, KANJI_STANDARD, // 參 + 0x7C12, KANJI_STANDARD, // 簒 + 0x96D9, KANJI_STANDARD, // 雙 + 0x53DF, KANJI_STANDARD, // 叟 + 0x66FC, KANJI_STANDARD, // 曌 + 0x71EE, KANJI_STANDARD, // 燮 + 0x53EE, KANJI_STANDARD, // 叮 + 0x53E8, KANJI_STANDARD, // 叚 + 0x53ED, KANJI_STANDARD, // 叭 + 0x53FA, KANJI_STANDARD, // 叺 + 0x5401, KANJI_STANDARD, // 吁 + 0x543D, KANJI_STANDARD, // 吜 + 0x5440, KANJI_STANDARD, // 呀 + 0x542C, KANJI_STANDARD, // 听 + 0x542D, KANJI_STANDARD, // 吭 + 0x543C, KANJI_STANDARD, // 同 + 0x542E, KANJI_STANDARD, // 吮 + 0x5436, KANJI_STANDARD, // 吶 + 0x5429, KANJI_STANDARD, // 吩 + 0x541D, KANJI_STANDARD, // 吝 + 0x544E, KANJI_STANDARD, // 呎 + 0x548F, KANJI_STANDARD, // 咏 + 0x5475, KANJI_STANDARD, // 呵 + 0x548E, KANJI_STANDARD, // 咎 + 0x545F, KANJI_STANDARD, // 呟 + 0x5471, KANJI_STANDARD, // 呱 + 0x5477, KANJI_STANDARD, // 呷 + 0x5470, KANJI_STANDARD, // 呰 + 0x5492, KANJI_STANDARD, // 咒 + 0x547B, KANJI_STANDARD, // 呻 + 0x5480, KANJI_STANDARD, // 咀 + 0x5476, KANJI_STANDARD, // 呶 + 0x5484, KANJI_STANDARD, // 咄 + 0x5490, KANJI_STANDARD, // 咐 + 0x5486, KANJI_STANDARD, // 咆 + 0x54C7, KANJI_STANDARD, // 哇 + 0x54A2, KANJI_STANDARD, // 咢 + 0x54B8, KANJI_STANDARD, // å’ž + 0x54A5, KANJI_STANDARD, // 咥 + 0x54AC, KANJI_STANDARD, // 咬 + 0x54C4, KANJI_STANDARD, // 哄 + 0x54C8, KANJI_STANDARD, // 哈 + 0x54A8, KANJI_STANDARD, // å’š + 0x54AB, KANJI_STANDARD, // 咫 + 0x54C2, KANJI_STANDARD, // 哂 + 0x54A4, KANJI_STANDARD, // å’€ + 0x54BE, KANJI_STANDARD, // å’Ÿ + 0x54BC, KANJI_STANDARD, // å’Œ + 0x54D8, KANJI_STANDARD, // 哘 + 0x54E5, KANJI_STANDARD, // 哥 + 0x54E6, KANJI_STANDARD, // 哊 + 0x550F, KANJI_STANDARD, // 唏 + 0x5514, KANJI_STANDARD, // 唔 + 0x54FD, KANJI_STANDARD, // 哜 + 0x54EE, KANJI_STANDARD, // 哮 + 0x54ED, KANJI_STANDARD, // 哭 + 0x54FA, KANJI_STANDARD, // 哺 + 0x54E2, KANJI_STANDARD, // 哢 + 0x5539, KANJI_STANDARD, // 唹 + 0x5540, KANJI_STANDARD, // 啀 + 0x5563, KANJI_STANDARD, // 啣 + 0x554C, KANJI_STANDARD, // 啌 + 0x552E, KANJI_STANDARD, // 售 + 0x555C, KANJI_STANDARD, // 啜 + 0x5545, KANJI_STANDARD, // 啅 + 0x5556, KANJI_STANDARD, // 啖 + 0x5557, KANJI_STANDARD, // 啗 + 0x5538, KANJI_STANDARD, // 唞 + 0x5533, KANJI_STANDARD, // 唳 + 0x555D, KANJI_STANDARD, // 啝 + 0x5599, KANJI_STANDARD, // 喙 + 0x5580, KANJI_STANDARD, // 喀 + 0x54AF, KANJI_STANDARD, // 咯 + 0x558A, KANJI_STANDARD, // 喊 + 0x559F, KANJI_STANDARD, // 喟 + 0x557B, KANJI_STANDARD, // 啻 + 0x557E, KANJI_STANDARD, // 啟 + 0x5598, KANJI_STANDARD, // 喘 + 0x559E, KANJI_STANDARD, // 喞 + 0x55AE, KANJI_STANDARD, // 單 + 0x557C, KANJI_STANDARD, // 啌 + 0x5583, KANJI_STANDARD, // 喃 + 0x55A9, KANJI_STANDARD, // 喩 + 0x5587, KANJI_STANDARD, // 喇 + 0x55A8, KANJI_STANDARD, // å–š + 0x55DA, KANJI_STANDARD, // 嗚 + 0x55C5, KANJI_STANDARD, // 嗅 + 0x55DF, KANJI_STANDARD, // 嗟 + 0x55C4, KANJI_STANDARD, // 嗄 + 0x55DC, KANJI_STANDARD, // 嗜 + 0x55E4, KANJI_STANDARD, // å—€ + 0x55D4, KANJI_STANDARD, // 嗔 + 0x5614, KANJI_STANDARD, // 嘔 + 0x55F7, KANJI_STANDARD, // 嗷 + 0x5616, KANJI_STANDARD, // 嘖 + 0x55FE, KANJI_STANDARD, // å—Ÿ + 0x55FD, KANJI_STANDARD, // å—œ + 0x561B, KANJI_STANDARD, // 嘛 + 0x55F9, KANJI_STANDARD, // 嗹 + 0x564E, KANJI_STANDARD, // 噎 + 0x5650, KANJI_STANDARD, // 噐 + 0x71DF, KANJI_STANDARD, // 營 + 0x5634, KANJI_STANDARD, // 嘎 + 0x5636, KANJI_STANDARD, // 嘶 + 0x5632, KANJI_STANDARD, // 嘲 + 0x5638, KANJI_STANDARD, // 嘞 + 0x566B, KANJI_STANDARD, // 噫 + 0x5664, KANJI_STANDARD, // 噀 + 0x562F, KANJI_STANDARD, // 嘯 + 0x566C, KANJI_STANDARD, // 噬 + 0x566A, KANJI_STANDARD, // 噪 + 0x5686, KANJI_STANDARD, // 嚆 + 0x5680, KANJI_STANDARD, // 嚀 + 0x568A, KANJI_STANDARD, // 嚊 + 0x56A0, KANJI_STANDARD, // 嚠 + 0x5694, KANJI_STANDARD, // 嚔 + 0x568F, KANJI_STANDARD, // 嚏 + 0x56A5, KANJI_STANDARD, // 嚥 + 0x56AE, KANJI_STANDARD, // 嚮 + 0x56B6, KANJI_STANDARD, // 嚶 + 0x56B4, KANJI_STANDARD, // 嚎 + 0x56C2, KANJI_STANDARD, // 囂 + 0x56BC, KANJI_STANDARD, // 嚌 + 0x56C1, KANJI_STANDARD, // 囁 + 0x56C3, KANJI_STANDARD, // 囃 + 0x56C0, KANJI_STANDARD, // 囀 + 0x56C8, KANJI_STANDARD, // 囈 + 0x56CE, KANJI_STANDARD, // 囎 + 0x56D1, KANJI_STANDARD, // 囑 + 0x56D3, KANJI_STANDARD, // 囓 + 0x56D7, KANJI_STANDARD, // 囗 + 0x56EE, KANJI_STANDARD, // 囮 + 0x56F9, KANJI_STANDARD, // 囹 + 0x5700, KANJI_STANDARD, // 圀 + 0x56FF, KANJI_STANDARD, // 囿 + 0x5704, KANJI_STANDARD, // 圄 + 0x5709, KANJI_STANDARD, // 圉 + 0x5708, KANJI_STANDARD, // 圈 + 0x570B, KANJI_STANDARD, // 國 + 0x570D, KANJI_STANDARD, // 圍 + 0x5713, KANJI_STANDARD, // 圓 + 0x5718, KANJI_STANDARD, // 團 + 0x5716, KANJI_STANDARD, // 圖 + 0x55C7, KANJI_STANDARD, // 嗇 + 0x571C, KANJI_STANDARD, // 圜 + 0x5726, KANJI_STANDARD, // 圊 + 0x5737, KANJI_STANDARD, // 圷 + 0x5738, KANJI_STANDARD, // 圞 + 0x574E, KANJI_STANDARD, // 坎 + 0x573B, KANJI_STANDARD, // 圻 + 0x5740, KANJI_STANDARD, // 址 + 0x574F, KANJI_STANDARD, // 坏 + 0x5769, KANJI_STANDARD, // 坩 + 0x57C0, KANJI_STANDARD, // 埀 + 0x5788, KANJI_STANDARD, // 垈 + 0x5761, KANJI_STANDARD, // 坡 + 0x577F, KANJI_STANDARD, // 坿 + 0x5789, KANJI_STANDARD, // 垉 + 0x5793, KANJI_STANDARD, // 垓 + 0x57A0, KANJI_STANDARD, // 垠 + 0x57B3, KANJI_STANDARD, // 垳 + 0x57A4, KANJI_STANDARD, // 垀 + 0x57AA, KANJI_STANDARD, // 垪 + 0x57B0, KANJI_STANDARD, // 垰 + 0x57C3, KANJI_STANDARD, // 埃 + 0x57C6, KANJI_STANDARD, // 埆 + 0x57D4, KANJI_STANDARD, // 埔 + 0x57D2, KANJI_STANDARD, // 埒 + 0x57D3, KANJI_STANDARD, // 埓 + 0x580A, KANJI_STANDARD, // 堊 + 0x57D6, KANJI_STANDARD, // 埖 + 0x57E3, KANJI_STANDARD, // 埣 + 0x580B, KANJI_STANDARD, // 堋 + 0x5819, KANJI_STANDARD, // 堙 + 0x581D, KANJI_STANDARD, // 堝 + 0x5872, KANJI_STANDARD, // 塲 + 0x5821, KANJI_STANDARD, // å ¡ + 0x5862, KANJI_STANDARD, // å¡¢ + 0x584B, KANJI_STANDARD, // 塋 + 0x5870, KANJI_STANDARD, // å¡° + 0x6BC0, KANJI_STANDARD, // 毀 + 0x5852, KANJI_STANDARD, // 塒 + 0x583D, KANJI_STANDARD, // å œ + 0x5879, KANJI_STANDARD, // 塹 + 0x5885, KANJI_STANDARD, // 墅 + 0x58B9, KANJI_STANDARD, // 墹 + 0x589F, KANJI_STANDARD, // 墟 + 0x58AB, KANJI_STANDARD, // 墫 + 0x58BA, KANJI_STANDARD, // 墺 + 0x58DE, KANJI_STANDARD, // 壞 + 0x58BB, KANJI_STANDARD, // 墻 + 0x58B8, KANJI_STANDARD, // 增 + 0x58AE, KANJI_STANDARD, // 墮 + 0x58C5, KANJI_STANDARD, // 壅 + 0x58D3, KANJI_STANDARD, // 壓 + 0x58D1, KANJI_STANDARD, // 壑 + 0x58D7, KANJI_STANDARD, // 壗 + 0x58D9, KANJI_STANDARD, // 壙 + 0x58D8, KANJI_STANDARD, // 壘 + 0x58E5, KANJI_STANDARD, // 壥 + 0x58DC, KANJI_STANDARD, // 壜 + 0x58E4, KANJI_STANDARD, // 壀 + 0x58DF, KANJI_STANDARD, // 壟 + 0x58EF, KANJI_STANDARD, // 壯 + 0x58FA, KANJI_STANDARD, // 壺 + 0x58F9, KANJI_STANDARD, // 壹 + 0x58FB, KANJI_STANDARD, // 壻 + 0x58FC, KANJI_STANDARD, // 壌 + 0x58FD, KANJI_STANDARD, // 壜 + 0x5902, KANJI_STANDARD, // 倂 + 0x590A, KANJI_STANDARD, // 倊 + 0x5910, KANJI_STANDARD, // 倐 + 0x591B, KANJI_STANDARD, // 倛 + 0x68A6, KANJI_STANDARD, // 梊 + 0x5925, KANJI_STANDARD, // 倥 + 0x592C, KANJI_STANDARD, // 倬 + 0x592D, KANJI_STANDARD, // 倭 + 0x5932, KANJI_STANDARD, // 倲 + 0x5938, KANJI_STANDARD, // 倞 + 0x593E, KANJI_STANDARD, // 借 + 0x7AD2, KANJI_STANDARD, // 竒 + 0x5955, KANJI_STANDARD, // 奕 + 0x5950, KANJI_STANDARD, // 奐 + 0x594E, KANJI_STANDARD, // 奎 + 0x595A, KANJI_STANDARD, // 奚 + 0x5958, KANJI_STANDARD, // 奘 + 0x5962, KANJI_STANDARD, // 奢 + 0x5960, KANJI_STANDARD, // 奠 + 0x5967, KANJI_STANDARD, // 奧 + 0x596C, KANJI_STANDARD, // 奬 + 0x5969, KANJI_STANDARD, // 奩 + 0x5978, KANJI_STANDARD, // 奞 + 0x5981, KANJI_STANDARD, // 劁 + 0x599D, KANJI_STANDARD, // 劝 + 0x4F5E, KANJI_STANDARD, // 䜞 + 0x4FAB, KANJI_STANDARD, // 䟫 + 0x59A3, KANJI_STANDARD, // 劣 + 0x59B2, KANJI_STANDARD, // 劲 + 0x59C6, KANJI_STANDARD, // 姆 + 0x59E8, KANJI_STANDARD, // å§š + 0x59DC, KANJI_STANDARD, // 姜 + 0x598D, KANJI_STANDARD, // 劍 + 0x59D9, KANJI_STANDARD, // 姙 + 0x59DA, KANJI_STANDARD, // 姚 + 0x5A25, KANJI_STANDARD, // 嚥 + 0x5A1F, KANJI_STANDARD, // 嚟 + 0x5A11, KANJI_STANDARD, // åš‘ + 0x5A1C, KANJI_STANDARD, // åšœ + 0x5A09, KANJI_STANDARD, // 嚉 + 0x5A1A, KANJI_STANDARD, // åšš + 0x5A40, KANJI_STANDARD, // 婀 + 0x5A6C, KANJI_STANDARD, // 婬 + 0x5A49, KANJI_STANDARD, // 婉 + 0x5A35, KANJI_STANDARD, // åšµ + 0x5A36, KANJI_STANDARD, // åš¶ + 0x5A62, KANJI_STANDARD, // å©¢ + 0x5A6A, KANJI_STANDARD, // 婪 + 0x5A9A, KANJI_STANDARD, // 媚 + 0x5ABC, KANJI_STANDARD, // 媌 + 0x5ABE, KANJI_STANDARD, // 媟 + 0x5ACB, KANJI_STANDARD, // 嫋 + 0x5AC2, KANJI_STANDARD, // 嫂 + 0x5ABD, KANJI_STANDARD, // 媜 + 0x5AE3, KANJI_STANDARD, // å«£ + 0x5AD7, KANJI_STANDARD, // 嫗 + 0x5AE6, KANJI_STANDARD, // 嫊 + 0x5AE9, KANJI_STANDARD, // å«© + 0x5AD6, KANJI_STANDARD, // 嫖 + 0x5AFA, KANJI_STANDARD, // 嫺 + 0x5AFB, KANJI_STANDARD, // å«» + 0x5B0C, KANJI_STANDARD, // 嬌 + 0x5B0B, KANJI_STANDARD, // 嬋 + 0x5B16, KANJI_STANDARD, // 嬖 + 0x5B32, KANJI_STANDARD, // 嬲 + 0x5AD0, KANJI_STANDARD, // 嫐 + 0x5B2A, KANJI_STANDARD, // 嬪 + 0x5B36, KANJI_STANDARD, // 嬶 + 0x5B3E, KANJI_STANDARD, // 嬟 + 0x5B43, KANJI_STANDARD, // 孃 + 0x5B45, KANJI_STANDARD, // 孅 + 0x5B40, KANJI_STANDARD, // 孀 + 0x5B51, KANJI_STANDARD, // 孑 + 0x5B55, KANJI_STANDARD, // 孕 + 0x5B5A, KANJI_STANDARD, // 孚 + 0x5B5B, KANJI_STANDARD, // 孛 + 0x5B65, KANJI_STANDARD, // å­¥ + 0x5B69, KANJI_STANDARD, // å­© + 0x5B70, KANJI_STANDARD, // å­° + 0x5B73, KANJI_STANDARD, // å­³ + 0x5B75, KANJI_STANDARD, // å­µ + 0x5B78, KANJI_STANDARD, // å­ž + 0x6588, KANJI_STANDARD, // 斈 + 0x5B7A, KANJI_STANDARD, // å­º + 0x5B80, KANJI_STANDARD, // 宀 + 0x5B83, KANJI_STANDARD, // 它 + 0x5BA6, KANJI_STANDARD, // 宊 + 0x5BB8, KANJI_STANDARD, // 实 + 0x5BC3, KANJI_STANDARD, // 寃 + 0x5BC7, KANJI_STANDARD, // 寇 + 0x5BC9, KANJI_STANDARD, // 寉 + 0x5BD4, KANJI_STANDARD, // 寔 + 0x5BD0, KANJI_STANDARD, // 寐 + 0x5BE4, KANJI_STANDARD, // 寀 + 0x5BE6, KANJI_STANDARD, // 寊 + 0x5BE2, KANJI_STANDARD, // 寢 + 0x5BDE, KANJI_STANDARD, // 寞 + 0x5BE5, KANJI_STANDARD, // 寥 + 0x5BEB, KANJI_STANDARD, // 寫 + 0x5BF0, KANJI_STANDARD, // 寰 + 0x5BF6, KANJI_STANDARD, // 寶 + 0x5BF3, KANJI_STANDARD, // 寳 + 0x5C05, KANJI_STANDARD, // 尅 + 0x5C07, KANJI_STANDARD, // 將 + 0x5C08, KANJI_STANDARD, // 專 + 0x5C0D, KANJI_STANDARD, // 對 + 0x5C13, KANJI_STANDARD, // 尓 + 0x5C20, KANJI_STANDARD, // å°  + 0x5C22, KANJI_STANDARD, // å°¢ + 0x5C28, KANJI_STANDARD, // å°š + 0x5C38, KANJI_STANDARD, // å°ž + 0x5C39, KANJI_STANDARD, // å°¹ + 0x5C41, KANJI_STANDARD, // 屁 + 0x5C46, KANJI_STANDARD, // 屆 + 0x5C4E, KANJI_STANDARD, // 屎 + 0x5C53, KANJI_STANDARD, // 屓 + 0x5C50, KANJI_STANDARD, // 屐 + 0x5C4F, KANJI_STANDARD, // 屏 + 0x5B71, KANJI_STANDARD, // å­± + 0x5C6C, KANJI_STANDARD, // 屬 + 0x5C6E, KANJI_STANDARD, // å±® + 0x4E62, KANJI_STANDARD, // ä¹¢ + 0x5C76, KANJI_STANDARD, // å±¶ + 0x5C79, KANJI_STANDARD, // å±¹ + 0x5C8C, KANJI_STANDARD, // 岌 + 0x5C91, KANJI_STANDARD, // 岑 + 0x5C94, KANJI_STANDARD, // 岔 + 0x599B, KANJI_STANDARD, // 力 + 0x5CAB, KANJI_STANDARD, // 岫 + 0x5CBB, KANJI_STANDARD, // å²» + 0x5CB6, KANJI_STANDARD, // å²¶ + 0x5CBC, KANJI_STANDARD, // 岌 + 0x5CB7, KANJI_STANDARD, // å²· + 0x5CC5, KANJI_STANDARD, // 峅 + 0x5CBE, KANJI_STANDARD, // 岟 + 0x5CC7, KANJI_STANDARD, // 峇 + 0x5CD9, KANJI_STANDARD, // 峙 + 0x5CE9, KANJI_STANDARD, // 峩 + 0x5CFD, KANJI_STANDARD, // 峜 + 0x5CFA, KANJI_STANDARD, // 峺 + 0x5CED, KANJI_STANDARD, // å³­ + 0x5D8C, KANJI_STANDARD, // 嶌 + 0x5CEA, KANJI_STANDARD, // 峪 + 0x5D0B, KANJI_STANDARD, // 压 + 0x5D15, KANJI_STANDARD, // 厕 + 0x5D17, KANJI_STANDARD, // 厗 + 0x5D5C, KANJI_STANDARD, // 嵜 + 0x5D1F, KANJI_STANDARD, // 原 + 0x5D1B, KANJI_STANDARD, // 厛 + 0x5D11, KANJI_STANDARD, // 厑 + 0x5D14, KANJI_STANDARD, // 厔 + 0x5D22, KANJI_STANDARD, // 厢 + 0x5D1A, KANJI_STANDARD, // 厚 + 0x5D19, KANJI_STANDARD, // 厙 + 0x5D18, KANJI_STANDARD, // 厘 + 0x5D4C, KANJI_STANDARD, // 嵌 + 0x5D52, KANJI_STANDARD, // 嵒 + 0x5D4E, KANJI_STANDARD, // 嵎 + 0x5D4B, KANJI_STANDARD, // 嵋 + 0x5D6C, KANJI_STANDARD, // 嵬 + 0x5D73, KANJI_STANDARD, // åµ³ + 0x5D76, KANJI_STANDARD, // åµ¶ + 0x5D87, KANJI_STANDARD, // 嶇 + 0x5D84, KANJI_STANDARD, // 嶄 + 0x5D82, KANJI_STANDARD, // 嶂 + 0x5DA2, KANJI_STANDARD, // å¶¢ + 0x5D9D, KANJI_STANDARD, // 嶝 + 0x5DAC, KANJI_STANDARD, // 嶬 + 0x5DAE, KANJI_STANDARD, // å¶® + 0x5DBD, KANJI_STANDARD, // å¶œ + 0x5D90, KANJI_STANDARD, // 嶐 + 0x5DB7, KANJI_STANDARD, // å¶· + 0x5DBC, KANJI_STANDARD, // å¶Œ + 0x5DC9, KANJI_STANDARD, // 巉 + 0x5DCD, KANJI_STANDARD, // 巍 + 0x5DD3, KANJI_STANDARD, // 巓 + 0x5DD2, KANJI_STANDARD, // 巒 + 0x5DD6, KANJI_STANDARD, // 巖 + 0x5DDB, KANJI_STANDARD, // 巛 + 0x5DEB, KANJI_STANDARD, // å·« + 0x5DF2, KANJI_STANDARD, // å·² + 0x5DF5, KANJI_STANDARD, // å·µ + 0x5E0B, KANJI_STANDARD, // åž‹ + 0x5E1A, KANJI_STANDARD, // åžš + 0x5E19, KANJI_STANDARD, // åž™ + 0x5E11, KANJI_STANDARD, // åž‘ + 0x5E1B, KANJI_STANDARD, // åž› + 0x5E36, KANJI_STANDARD, // åž¶ + 0x5E37, KANJI_STANDARD, // åž· + 0x5E44, KANJI_STANDARD, // 幄 + 0x5E43, KANJI_STANDARD, // 幃 + 0x5E40, KANJI_STANDARD, // 幀 + 0x5E4E, KANJI_STANDARD, // 幎 + 0x5E57, KANJI_STANDARD, // 幗 + 0x5E54, KANJI_STANDARD, // 幔 + 0x5E5F, KANJI_STANDARD, // 幟 + 0x5E62, KANJI_STANDARD, // å¹¢ + 0x5E64, KANJI_STANDARD, // å¹€ + 0x5E47, KANJI_STANDARD, // 幇 + 0x5E75, KANJI_STANDARD, // å¹µ + 0x5E76, KANJI_STANDARD, // å¹¶ + 0x5E7A, KANJI_STANDARD, // 幺 + 0x9EBC, KANJI_STANDARD, // 麌 + 0x5E7F, KANJI_STANDARD, // 广 + 0x5EA0, KANJI_STANDARD, // 庠 + 0x5EC1, KANJI_STANDARD, // 廁 + 0x5EC2, KANJI_STANDARD, // 廂 + 0x5EC8, KANJI_STANDARD, // 廈 + 0x5ED0, KANJI_STANDARD, // 廐 + 0x5ECF, KANJI_STANDARD, // 廏 + 0x5ED6, KANJI_STANDARD, // 廖 + 0x5EE3, KANJI_STANDARD, // 廣 + 0x5EDD, KANJI_STANDARD, // 廝 + 0x5EDA, KANJI_STANDARD, // 廚 + 0x5EDB, KANJI_STANDARD, // 廛 + 0x5EE2, KANJI_STANDARD, // 廢 + 0x5EE1, KANJI_STANDARD, // 廡 + 0x5EE8, KANJI_STANDARD, // 廚 + 0x5EE9, KANJI_STANDARD, // 廩 + 0x5EEC, KANJI_STANDARD, // 廬 + 0x5EF1, KANJI_STANDARD, // å»± + 0x5EF3, KANJI_STANDARD, // 廳 + 0x5EF0, KANJI_STANDARD, // å»° + 0x5EF4, KANJI_STANDARD, // 廎 + 0x5EF8, KANJI_STANDARD, // 廞 + 0x5EFE, KANJI_STANDARD, // 廟 + 0x5F03, KANJI_STANDARD, // 匃 + 0x5F09, KANJI_STANDARD, // 匉 + 0x5F5D, KANJI_STANDARD, // 圝 + 0x5F5C, KANJI_STANDARD, // 圜 + 0x5F0B, KANJI_STANDARD, // 匋 + 0x5F11, KANJI_STANDARD, // 匑 + 0x5F16, KANJI_STANDARD, // 化 + 0x5F29, KANJI_STANDARD, // 匩 + 0x5F2D, KANJI_STANDARD, // 匭 + 0x5F38, KANJI_STANDARD, // 匞 + 0x5F41, KANJI_STANDARD, // 圁 + 0x5F48, KANJI_STANDARD, // 圈 + 0x5F4C, KANJI_STANDARD, // 圌 + 0x5F4E, KANJI_STANDARD, // 圎 + 0x5F2F, KANJI_STANDARD, // 匯 + 0x5F51, KANJI_STANDARD, // 圑 + 0x5F56, KANJI_STANDARD, // 圖 + 0x5F57, KANJI_STANDARD, // 圗 + 0x5F59, KANJI_STANDARD, // 圙 + 0x5F61, KANJI_STANDARD, // 圡 + 0x5F6D, KANJI_STANDARD, // 圭 + 0x5F73, KANJI_STANDARD, // 圳 + 0x5F77, KANJI_STANDARD, // 圷 + 0x5F83, KANJI_STANDARD, // 埃 + 0x5F82, KANJI_STANDARD, // 埂 + 0x5F7F, KANJI_STANDARD, // 圿 + 0x5F8A, KANJI_STANDARD, // 埊 + 0x5F88, KANJI_STANDARD, // 埈 + 0x5F91, KANJI_STANDARD, // 埑 + 0x5F87, KANJI_STANDARD, // 埇 + 0x5F9E, KANJI_STANDARD, // 埞 + 0x5F99, KANJI_STANDARD, // 埙 + 0x5F98, KANJI_STANDARD, // 埘 + 0x5FA0, KANJI_STANDARD, // 埠 + 0x5FA8, KANJI_STANDARD, // 埚 + 0x5FAD, KANJI_STANDARD, // 埭 + 0x5FBC, KANJI_STANDARD, // 埌 + 0x5FD6, KANJI_STANDARD, // 忖 + 0x5FFB, KANJI_STANDARD, // å¿» + 0x5FE4, KANJI_STANDARD, // å¿€ + 0x5FF8, KANJI_STANDARD, // 忞 + 0x5FF1, KANJI_STANDARD, // 忱 + 0x5FDD, KANJI_STANDARD, // 忝 + 0x60B3, KANJI_STANDARD, // 悳 + 0x5FFF, KANJI_STANDARD, // å¿¿ + 0x6021, KANJI_STANDARD, // 怡 + 0x6060, KANJI_STANDARD, // 恠 + 0x6019, KANJI_STANDARD, // 怙 + 0x6010, KANJI_STANDARD, // 怐 + 0x6029, KANJI_STANDARD, // 怩 + 0x600E, KANJI_STANDARD, // 怎 + 0x6031, KANJI_STANDARD, // 怱 + 0x601B, KANJI_STANDARD, // 怛 + 0x6015, KANJI_STANDARD, // 怕 + 0x602B, KANJI_STANDARD, // 怫 + 0x6026, KANJI_STANDARD, // 怊 + 0x600F, KANJI_STANDARD, // 怏 + 0x603A, KANJI_STANDARD, // 怺 + 0x605A, KANJI_STANDARD, // 恚 + 0x6041, KANJI_STANDARD, // 恁 + 0x606A, KANJI_STANDARD, // 恪 + 0x6077, KANJI_STANDARD, // 恷 + 0x605F, KANJI_STANDARD, // 恟 + 0x604A, KANJI_STANDARD, // 恊 + 0x6046, KANJI_STANDARD, // 恆 + 0x604D, KANJI_STANDARD, // 恍 + 0x6063, KANJI_STANDARD, // 恣 + 0x6043, KANJI_STANDARD, // 恃 + 0x6064, KANJI_STANDARD, // 恀 + 0x6042, KANJI_STANDARD, // 恂 + 0x606C, KANJI_STANDARD, // 恬 + 0x606B, KANJI_STANDARD, // 恫 + 0x6059, KANJI_STANDARD, // 恙 + 0x6081, KANJI_STANDARD, // 悁 + 0x608D, KANJI_STANDARD, // 悍 + 0x60E7, KANJI_STANDARD, // 惧 + 0x6083, KANJI_STANDARD, // 悃 + 0x609A, KANJI_STANDARD, // 悚 + 0x6084, KANJI_STANDARD, // 悄 + 0x609B, KANJI_STANDARD, // 悛 + 0x6096, KANJI_STANDARD, // 悖 + 0x6097, KANJI_STANDARD, // 悗 + 0x6092, KANJI_STANDARD, // 悒 + 0x60A7, KANJI_STANDARD, // 悧 + 0x608B, KANJI_STANDARD, // 悋 + 0x60E1, KANJI_STANDARD, // 惡 + 0x60B8, KANJI_STANDARD, // 悞 + 0x60E0, KANJI_STANDARD, // 惠 + 0x60D3, KANJI_STANDARD, // 惓 + 0x60B4, KANJI_STANDARD, // 悎 + 0x5FF0, KANJI_STANDARD, // å¿° + 0x60BD, KANJI_STANDARD, // 悜 + 0x60C6, KANJI_STANDARD, // 惆 + 0x60B5, KANJI_STANDARD, // 悵 + 0x60D8, KANJI_STANDARD, // 惘 + 0x614D, KANJI_STANDARD, // 慍 + 0x6115, KANJI_STANDARD, // 愕 + 0x6106, KANJI_STANDARD, // 愆 + 0x60F6, KANJI_STANDARD, // 惶 + 0x60F7, KANJI_STANDARD, // 惷 + 0x6100, KANJI_STANDARD, // 愀 + 0x60F4, KANJI_STANDARD, // 惎 + 0x60FA, KANJI_STANDARD, // 惺 + 0x6103, KANJI_STANDARD, // 愃 + 0x6121, KANJI_STANDARD, // 愡 + 0x60FB, KANJI_STANDARD, // 惻 + 0x60F1, KANJI_STANDARD, // 惱 + 0x610D, KANJI_STANDARD, // 愍 + 0x610E, KANJI_STANDARD, // 愎 + 0x6147, KANJI_STANDARD, // 慇 + 0x613E, KANJI_STANDARD, // 感 + 0x6128, KANJI_STANDARD, // 愚 + 0x6127, KANJI_STANDARD, // 愧 + 0x614A, KANJI_STANDARD, // 慊 + 0x613F, KANJI_STANDARD, // 愿 + 0x613C, KANJI_STANDARD, // 愌 + 0x612C, KANJI_STANDARD, // 愬 + 0x6134, KANJI_STANDARD, // 愎 + 0x613D, KANJI_STANDARD, // 愜 + 0x6142, KANJI_STANDARD, // 慂 + 0x6144, KANJI_STANDARD, // 慄 + 0x6173, KANJI_STANDARD, // 慳 + 0x6177, KANJI_STANDARD, // 慷 + 0x6158, KANJI_STANDARD, // 慘 + 0x6159, KANJI_STANDARD, // 慙 + 0x615A, KANJI_STANDARD, // 慚 + 0x616B, KANJI_STANDARD, // 慫 + 0x6174, KANJI_STANDARD, // æ…Ž + 0x616F, KANJI_STANDARD, // 慯 + 0x6165, KANJI_STANDARD, // 慥 + 0x6171, KANJI_STANDARD, // 慱 + 0x615F, KANJI_STANDARD, // 慟 + 0x615D, KANJI_STANDARD, // 慝 + 0x6153, KANJI_STANDARD, // 慓 + 0x6175, KANJI_STANDARD, // 慵 + 0x6199, KANJI_STANDARD, // 憙 + 0x6196, KANJI_STANDARD, // 憖 + 0x6187, KANJI_STANDARD, // 憇 + 0x61AC, KANJI_STANDARD, // 憬 + 0x6194, KANJI_STANDARD, // 憔 + 0x619A, KANJI_STANDARD, // 憚 + 0x618A, KANJI_STANDARD, // 憊 + 0x6191, KANJI_STANDARD, // 憑 + 0x61AB, KANJI_STANDARD, // 憫 + 0x61AE, KANJI_STANDARD, // 憮 + 0x61CC, KANJI_STANDARD, // 懌 + 0x61CA, KANJI_STANDARD, // 懊 + 0x61C9, KANJI_STANDARD, // 應 + 0x61F7, KANJI_STANDARD, // 懷 + 0x61C8, KANJI_STANDARD, // 懈 + 0x61C3, KANJI_STANDARD, // 懃 + 0x61C6, KANJI_STANDARD, // 懆 + 0x61BA, KANJI_STANDARD, // 憺 + 0x61CB, KANJI_STANDARD, // 懋 + 0x7F79, KANJI_STANDARD, // 眹 + 0x61CD, KANJI_STANDARD, // 懍 + 0x61E6, KANJI_STANDARD, // 懊 + 0x61E3, KANJI_STANDARD, // 懣 + 0x61F6, KANJI_STANDARD, // 懶 + 0x61FA, KANJI_STANDARD, // 懺 + 0x61F4, KANJI_STANDARD, // 懎 + 0x61FF, KANJI_STANDARD, // 懿 + 0x61FD, KANJI_STANDARD, // 懜 + 0x61FC, KANJI_STANDARD, // 懌 + 0x61FE, KANJI_STANDARD, // 懟 + 0x6200, KANJI_STANDARD, // 戀 + 0x6208, KANJI_STANDARD, // 戈 + 0x6209, KANJI_STANDARD, // 戉 + 0x620D, KANJI_STANDARD, // 戍 + 0x620C, KANJI_STANDARD, // 戌 + 0x6214, KANJI_STANDARD, // 戔 + 0x621B, KANJI_STANDARD, // 戛 + 0x621E, KANJI_STANDARD, // 戞 + 0x6221, KANJI_STANDARD, // 戡 + 0x622A, KANJI_STANDARD, // 截 + 0x622E, KANJI_STANDARD, // 戮 + 0x6230, KANJI_STANDARD, // 戰 + 0x6232, KANJI_STANDARD, // 戲 + 0x6233, KANJI_STANDARD, // 戳 + 0x6241, KANJI_STANDARD, // 扁 + 0x624E, KANJI_STANDARD, // 扎 + 0x625E, KANJI_STANDARD, // 扞 + 0x6263, KANJI_STANDARD, // 扣 + 0x625B, KANJI_STANDARD, // 扛 + 0x6260, KANJI_STANDARD, // 扠 + 0x6268, KANJI_STANDARD, // 扚 + 0x627C, KANJI_STANDARD, // 扌 + 0x6282, KANJI_STANDARD, // 抂 + 0x6289, KANJI_STANDARD, // 抉 + 0x627E, KANJI_STANDARD, // 扟 + 0x6292, KANJI_STANDARD, // 抒 + 0x6293, KANJI_STANDARD, // 抓 + 0x6296, KANJI_STANDARD, // 抖 + 0x62D4, KANJI_STANDARD, // 拔 + 0x6283, KANJI_STANDARD, // 抃 + 0x6294, KANJI_STANDARD, // 抔 + 0x62D7, KANJI_STANDARD, // 拗 + 0x62D1, KANJI_STANDARD, // 拑 + 0x62BB, KANJI_STANDARD, // 抻 + 0x62CF, KANJI_STANDARD, // 拏 + 0x62FF, KANJI_STANDARD, // 拿 + 0x62C6, KANJI_STANDARD, // 拆 + 0x64D4, KANJI_STANDARD, // 擔 + 0x62C8, KANJI_STANDARD, // 拈 + 0x62DC, KANJI_STANDARD, // 拜 + 0x62CC, KANJI_STANDARD, // 拌 + 0x62CA, KANJI_STANDARD, // 拊 + 0x62C2, KANJI_STANDARD, // 拂 + 0x62C7, KANJI_STANDARD, // 拇 + 0x629B, KANJI_STANDARD, // 抛 + 0x62C9, KANJI_STANDARD, // 拉 + 0x630C, KANJI_STANDARD, // 挌 + 0x62EE, KANJI_STANDARD, // 拮 + 0x62F1, KANJI_STANDARD, // 拱 + 0x6327, KANJI_STANDARD, // 挧 + 0x6302, KANJI_STANDARD, // 挂 + 0x6308, KANJI_STANDARD, // 挈 + 0x62EF, KANJI_STANDARD, // 拯 + 0x62F5, KANJI_STANDARD, // 拵 + 0x6350, KANJI_STANDARD, // 捐 + 0x633E, KANJI_STANDARD, // 挟 + 0x634D, KANJI_STANDARD, // 捍 + 0x641C, KANJI_STANDARD, // 搜 + 0x634F, KANJI_STANDARD, // 捏 + 0x6396, KANJI_STANDARD, // 掖 + 0x638E, KANJI_STANDARD, // 掎 + 0x6380, KANJI_STANDARD, // 掀 + 0x63AB, KANJI_STANDARD, // 掫 + 0x6376, KANJI_STANDARD, // 捶 + 0x63A3, KANJI_STANDARD, // 掣 + 0x638F, KANJI_STANDARD, // 掏 + 0x6389, KANJI_STANDARD, // 掉 + 0x639F, KANJI_STANDARD, // 掟 + 0x63B5, KANJI_STANDARD, // 掵 + 0x636B, KANJI_STANDARD, // 捫 + 0x6369, KANJI_STANDARD, // 捩 + 0x63BE, KANJI_STANDARD, // 掟 + 0x63E9, KANJI_STANDARD, // 揩 + 0x63C0, KANJI_STANDARD, // 揀 + 0x63C6, KANJI_STANDARD, // 揆 + 0x63E3, KANJI_STANDARD, // 揣 + 0x63C9, KANJI_STANDARD, // 揉 + 0x63D2, KANJI_STANDARD, // 插 + 0x63F6, KANJI_STANDARD, // 揶 + 0x63C4, KANJI_STANDARD, // 揄 + 0x6416, KANJI_STANDARD, // 搖 + 0x6434, KANJI_STANDARD, // 搎 + 0x6406, KANJI_STANDARD, // 搆 + 0x6413, KANJI_STANDARD, // 搓 + 0x6426, KANJI_STANDARD, // 搊 + 0x6436, KANJI_STANDARD, // 搶 + 0x651D, KANJI_STANDARD, // 攝 + 0x6417, KANJI_STANDARD, // 搗 + 0x6428, KANJI_STANDARD, // 搚 + 0x640F, KANJI_STANDARD, // 搏 + 0x6467, KANJI_STANDARD, // 摧 + 0x646F, KANJI_STANDARD, // 摯 + 0x6476, KANJI_STANDARD, // 摶 + 0x644E, KANJI_STANDARD, // 摎 + 0x652A, KANJI_STANDARD, // 攪 + 0x6495, KANJI_STANDARD, // 撕 + 0x6493, KANJI_STANDARD, // 撓 + 0x64A5, KANJI_STANDARD, // 撥 + 0x64A9, KANJI_STANDARD, // 撩 + 0x6488, KANJI_STANDARD, // 撈 + 0x64BC, KANJI_STANDARD, // æ’Œ + 0x64DA, KANJI_STANDARD, // 據 + 0x64D2, KANJI_STANDARD, // 擒 + 0x64C5, KANJI_STANDARD, // 擅 + 0x64C7, KANJI_STANDARD, // 擇 + 0x64BB, KANJI_STANDARD, // 撻 + 0x64D8, KANJI_STANDARD, // 擘 + 0x64C2, KANJI_STANDARD, // 擂 + 0x64F1, KANJI_STANDARD, // 擱 + 0x64E7, KANJI_STANDARD, // 擧 + 0x8209, KANJI_STANDARD, // 舉 + 0x64E0, KANJI_STANDARD, // 擠 + 0x64E1, KANJI_STANDARD, // 擡 + 0x62AC, KANJI_STANDARD, // 抬 + 0x64E3, KANJI_STANDARD, // 擣 + 0x64EF, KANJI_STANDARD, // 擯 + 0x652C, KANJI_STANDARD, // 攬 + 0x64F6, KANJI_STANDARD, // 擶 + 0x64F4, KANJI_STANDARD, // 擎 + 0x64F2, KANJI_STANDARD, // 擲 + 0x64FA, KANJI_STANDARD, // 擺 + 0x6500, KANJI_STANDARD, // 攀 + 0x64FD, KANJI_STANDARD, // 擜 + 0x6518, KANJI_STANDARD, // 攘 + 0x651C, KANJI_STANDARD, // 攜 + 0x6505, KANJI_STANDARD, // 攅 + 0x6524, KANJI_STANDARD, // 攀 + 0x6523, KANJI_STANDARD, // 攣 + 0x652B, KANJI_STANDARD, // 攫 + 0x6534, KANJI_STANDARD, // 攎 + 0x6535, KANJI_STANDARD, // 攵 + 0x6537, KANJI_STANDARD, // 攷 + 0x6536, KANJI_STANDARD, // 收 + 0x6538, KANJI_STANDARD, // 攞 + 0x754B, KANJI_STANDARD, // 畋 + 0x6548, KANJI_STANDARD, // 效 + 0x6556, KANJI_STANDARD, // 敖 + 0x6555, KANJI_STANDARD, // 敕 + 0x654D, KANJI_STANDARD, // 敍 + 0x6558, KANJI_STANDARD, // 敘 + 0x655E, KANJI_STANDARD, // 敞 + 0x655D, KANJI_STANDARD, // 敝 + 0x6572, KANJI_STANDARD, // 敲 + 0x6578, KANJI_STANDARD, // 敞 + 0x6582, KANJI_STANDARD, // 斂 + 0x6583, KANJI_STANDARD, // 斃 + 0x8B8A, KANJI_STANDARD, // 變 + 0x659B, KANJI_STANDARD, // 斛 + 0x659F, KANJI_STANDARD, // 斟 + 0x65AB, KANJI_STANDARD, // 斫 + 0x65B7, KANJI_STANDARD, // 斷 + 0x65C3, KANJI_STANDARD, // 旃 + 0x65C6, KANJI_STANDARD, // 旆 + 0x65C1, KANJI_STANDARD, // 旁 + 0x65C4, KANJI_STANDARD, // 旄 + 0x65CC, KANJI_STANDARD, // 旌 + 0x65D2, KANJI_STANDARD, // 旒 + 0x65DB, KANJI_STANDARD, // 旛 + 0x65D9, KANJI_STANDARD, // 旙 + 0x65E0, KANJI_STANDARD, // 无 + 0x65E1, KANJI_STANDARD, // 旡 + 0x65F1, KANJI_STANDARD, // 旱 + 0x6772, KANJI_STANDARD, // 杲 + 0x660A, KANJI_STANDARD, // 昊 + 0x6603, KANJI_STANDARD, // 昃 + 0x65FB, KANJI_STANDARD, // 旻 + 0x6773, KANJI_STANDARD, // 杳 + 0x6635, KANJI_STANDARD, // 昵 + 0x6636, KANJI_STANDARD, // 昶 + 0x6634, KANJI_STANDARD, // 明 + 0x661C, KANJI_STANDARD, // 昜 + 0x664F, KANJI_STANDARD, // 晏 + 0x6644, KANJI_STANDARD, // 晄 + 0x6649, KANJI_STANDARD, // 晉 + 0x6641, KANJI_STANDARD, // 晁 + 0x665E, KANJI_STANDARD, // 晞 + 0x665D, KANJI_STANDARD, // 晝 + 0x6664, KANJI_STANDARD, // 晀 + 0x6667, KANJI_STANDARD, // 晧 + 0x6668, KANJI_STANDARD, // 晚 + 0x665F, KANJI_STANDARD, // 晟 + 0x6662, KANJI_STANDARD, // 晢 + 0x6670, KANJI_STANDARD, // 晰 + 0x6683, KANJI_STANDARD, // 暃 + 0x6688, KANJI_STANDARD, // 暈 + 0x668E, KANJI_STANDARD, // 暎 + 0x6689, KANJI_STANDARD, // 暉 + 0x6684, KANJI_STANDARD, // 暄 + 0x6698, KANJI_STANDARD, // 暘 + 0x669D, KANJI_STANDARD, // 暝 + 0x66C1, KANJI_STANDARD, // 曁 + 0x66B9, KANJI_STANDARD, // 暹 + 0x66C9, KANJI_STANDARD, // 曉 + 0x66BE, KANJI_STANDARD, // 暟 + 0x66BC, KANJI_STANDARD, // 暌 + 0x66C4, KANJI_STANDARD, // 曄 + 0x66B8, KANJI_STANDARD, // æšž + 0x66D6, KANJI_STANDARD, // 曖 + 0x66DA, KANJI_STANDARD, // 曚 + 0x66E0, KANJI_STANDARD, // 曠 + 0x663F, KANJI_STANDARD, // 昿 + 0x66E6, KANJI_STANDARD, // 曊 + 0x66E9, KANJI_STANDARD, // 曩 + 0x66F0, KANJI_STANDARD, // 曰 + 0x66F5, KANJI_STANDARD, // 曵 + 0x66F7, KANJI_STANDARD, // 曷 + 0x670F, KANJI_STANDARD, // 朏 + 0x6716, KANJI_STANDARD, // 朖 + 0x671E, KANJI_STANDARD, // 朞 + 0x6726, KANJI_STANDARD, // 朊 + 0x6727, KANJI_STANDARD, // 朧 + 0x9738, KANJI_STANDARD, // 霾 + 0x672E, KANJI_STANDARD, // 朮 + 0x673F, KANJI_STANDARD, // 朿 + 0x6736, KANJI_STANDARD, // 朶 + 0x6741, KANJI_STANDARD, // 杁 + 0x6738, KANJI_STANDARD, // 朞 + 0x6737, KANJI_STANDARD, // 朷 + 0x6746, KANJI_STANDARD, // 杆 + 0x675E, KANJI_STANDARD, // 杞 + 0x6760, KANJI_STANDARD, // 杠 + 0x6759, KANJI_STANDARD, // 杙 + 0x6763, KANJI_STANDARD, // 杣 + 0x6764, KANJI_STANDARD, // 杀 + 0x6789, KANJI_STANDARD, // 枉 + 0x6770, KANJI_STANDARD, // 杰 + 0x67A9, KANJI_STANDARD, // 枩 + 0x677C, KANJI_STANDARD, // 杌 + 0x676A, KANJI_STANDARD, // 杪 + 0x678C, KANJI_STANDARD, // 枌 + 0x678B, KANJI_STANDARD, // 枋 + 0x67A6, KANJI_STANDARD, // 枊 + 0x67A1, KANJI_STANDARD, // 枡 + 0x6785, KANJI_STANDARD, // 枅 + 0x67B7, KANJI_STANDARD, // 枷 + 0x67EF, KANJI_STANDARD, // 柯 + 0x67B4, KANJI_STANDARD, // 枎 + 0x67EC, KANJI_STANDARD, // 柬 + 0x67B3, KANJI_STANDARD, // 枳 + 0x67E9, KANJI_STANDARD, // 柩 + 0x67B8, KANJI_STANDARD, // æžž + 0x67E4, KANJI_STANDARD, // 柀 + 0x67DE, KANJI_STANDARD, // 柞 + 0x67DD, KANJI_STANDARD, // 柝 + 0x67E2, KANJI_STANDARD, // 柢 + 0x67EE, KANJI_STANDARD, // 柮 + 0x67B9, KANJI_STANDARD, // 枹 + 0x67CE, KANJI_STANDARD, // 柎 + 0x67C6, KANJI_STANDARD, // 柆 + 0x67E7, KANJI_STANDARD, // 柧 + 0x6A9C, KANJI_STANDARD, // 檜 + 0x681E, KANJI_STANDARD, // 栞 + 0x6846, KANJI_STANDARD, // 框 + 0x6829, KANJI_STANDARD, // æ © + 0x6840, KANJI_STANDARD, // 桀 + 0x684D, KANJI_STANDARD, // 桍 + 0x6832, KANJI_STANDARD, // æ ² + 0x684E, KANJI_STANDARD, // 桎 + 0x68B3, KANJI_STANDARD, // 梳 + 0x682B, KANJI_STANDARD, // æ « + 0x6859, KANJI_STANDARD, // 桙 + 0x6863, KANJI_STANDARD, // æ¡£ + 0x6877, KANJI_STANDARD, // æ¡· + 0x687F, KANJI_STANDARD, // æ¡¿ + 0x689F, KANJI_STANDARD, // 梟 + 0x688F, KANJI_STANDARD, // 梏 + 0x68AD, KANJI_STANDARD, // 梭 + 0x6894, KANJI_STANDARD, // 梔 + 0x689D, KANJI_STANDARD, // 條 + 0x689B, KANJI_STANDARD, // 梛 + 0x6883, KANJI_STANDARD, // 梃 + 0x6AAE, KANJI_STANDARD, // 檮 + 0x68B9, KANJI_STANDARD, // 梹 + 0x6874, KANJI_STANDARD, // 桎 + 0x68B5, KANJI_STANDARD, // 梵 + 0x68A0, KANJI_STANDARD, // 梠 + 0x68BA, KANJI_STANDARD, // 梺 + 0x690F, KANJI_STANDARD, // 怏 + 0x688D, KANJI_STANDARD, // 梍 + 0x687E, KANJI_STANDARD, // 桟 + 0x6901, KANJI_STANDARD, // 态 + 0x68CA, KANJI_STANDARD, // 棊 + 0x6908, KANJI_STANDARD, // 怈 + 0x68D8, KANJI_STANDARD, // 棘 + 0x6922, KANJI_STANDARD, // 怢 + 0x6926, KANJI_STANDARD, // 怊 + 0x68E1, KANJI_STANDARD, // 棡 + 0x690C, KANJI_STANDARD, // 怌 + 0x68CD, KANJI_STANDARD, // 棍 + 0x68D4, KANJI_STANDARD, // 棔 + 0x68E7, KANJI_STANDARD, // 棧 + 0x68D5, KANJI_STANDARD, // 棕 + 0x6936, KANJI_STANDARD, // 怶 + 0x6912, KANJI_STANDARD, // 怒 + 0x6904, KANJI_STANDARD, // 怄 + 0x68D7, KANJI_STANDARD, // 棗 + 0x68E3, KANJI_STANDARD, // 棣 + 0x6925, KANJI_STANDARD, // 急 + 0x68F9, KANJI_STANDARD, // 棹 + 0x68E0, KANJI_STANDARD, // 棠 + 0x68EF, KANJI_STANDARD, // 棯 + 0x6928, KANJI_STANDARD, // 怚 + 0x692A, KANJI_STANDARD, // 怪 + 0x691A, KANJI_STANDARD, // 怚 + 0x6923, KANJI_STANDARD, // 怣 + 0x6921, KANJI_STANDARD, // 怡 + 0x68C6, KANJI_STANDARD, // 棆 + 0x6979, KANJI_STANDARD, // 楹 + 0x6977, KANJI_STANDARD, // 楷 + 0x695C, KANJI_STANDARD, // 楜 + 0x6978, KANJI_STANDARD, // 楞 + 0x696B, KANJI_STANDARD, // 楫 + 0x6954, KANJI_STANDARD, // 楔 + 0x697E, KANJI_STANDARD, // 楟 + 0x696E, KANJI_STANDARD, // 楮 + 0x6939, KANJI_STANDARD, // 怹 + 0x6974, KANJI_STANDARD, // 楎 + 0x693D, KANJI_STANDARD, // 怜 + 0x6959, KANJI_STANDARD, // 楙 + 0x6930, KANJI_STANDARD, // 怰 + 0x6961, KANJI_STANDARD, // 楡 + 0x695E, KANJI_STANDARD, // 楞 + 0x695D, KANJI_STANDARD, // 楝 + 0x6981, KANJI_STANDARD, // 抁 + 0x696A, KANJI_STANDARD, // 楪 + 0x69B2, KANJI_STANDARD, // 抲 + 0x69AE, KANJI_STANDARD, // 抮 + 0x69D0, KANJI_STANDARD, // 槐 + 0x69BF, KANJI_STANDARD, // 抿 + 0x69C1, KANJI_STANDARD, // 槁 + 0x69D3, KANJI_STANDARD, // 槓 + 0x69BE, KANJI_STANDARD, // 抟 + 0x69CE, KANJI_STANDARD, // 槎 + 0x5BE8, KANJI_STANDARD, // 寚 + 0x69CA, KANJI_STANDARD, // 槊 + 0x69DD, KANJI_STANDARD, // 槝 + 0x69BB, KANJI_STANDARD, // 抻 + 0x69C3, KANJI_STANDARD, // 槃 + 0x69A7, KANJI_STANDARD, // 抧 + 0x6A2E, KANJI_STANDARD, // æš® + 0x6991, KANJI_STANDARD, // 抑 + 0x69A0, KANJI_STANDARD, // 抠 + 0x699C, KANJI_STANDARD, // 抜 + 0x6995, KANJI_STANDARD, // 投 + 0x69B4, KANJI_STANDARD, // 抎 + 0x69DE, KANJI_STANDARD, // 槞 + 0x69E8, KANJI_STANDARD, // æ§š + 0x6A02, KANJI_STANDARD, // æš‚ + 0x6A1B, KANJI_STANDARD, // æš› + 0x69FF, KANJI_STANDARD, // æ§¿ + 0x6B0A, KANJI_STANDARD, // 權 + 0x69F9, KANJI_STANDARD, // æ§¹ + 0x69F2, KANJI_STANDARD, // æ§² + 0x69E7, KANJI_STANDARD, // æ§§ + 0x6A05, KANJI_STANDARD, // æš… + 0x69B1, KANJI_STANDARD, // 抱 + 0x6A1E, KANJI_STANDARD, // 暞 + 0x69ED, KANJI_STANDARD, // æ§­ + 0x6A14, KANJI_STANDARD, // æš” + 0x69EB, KANJI_STANDARD, // æ§« + 0x6A0A, KANJI_STANDARD, // 暊 + 0x6A12, KANJI_STANDARD, // æš’ + 0x6AC1, KANJI_STANDARD, // 櫁 + 0x6A23, KANJI_STANDARD, // 暣 + 0x6A13, KANJI_STANDARD, // æš“ + 0x6A44, KANJI_STANDARD, // 橄 + 0x6A0C, KANJI_STANDARD, // 暌 + 0x6A72, KANJI_STANDARD, // 橲 + 0x6A36, KANJI_STANDARD, // æš¶ + 0x6A78, KANJI_STANDARD, // 橞 + 0x6A47, KANJI_STANDARD, // 橇 + 0x6A62, KANJI_STANDARD, // æ©¢ + 0x6A59, KANJI_STANDARD, // 橙 + 0x6A66, KANJI_STANDARD, // 橊 + 0x6A48, KANJI_STANDARD, // 橈 + 0x6A38, KANJI_STANDARD, // æšž + 0x6A22, KANJI_STANDARD, // 暢 + 0x6A90, KANJI_STANDARD, // 檐 + 0x6A8D, KANJI_STANDARD, // 檍 + 0x6AA0, KANJI_STANDARD, // 檠 + 0x6A84, KANJI_STANDARD, // 檄 + 0x6AA2, KANJI_STANDARD, // 檢 + 0x6AA3, KANJI_STANDARD, // 檣 + 0x6A97, KANJI_STANDARD, // 檗 + 0x8617, KANJI_STANDARD, // 蘗 + 0x6ABB, KANJI_STANDARD, // 檻 + 0x6AC3, KANJI_STANDARD, // 櫃 + 0x6AC2, KANJI_STANDARD, // 櫂 + 0x6AB8, KANJI_STANDARD, // 檞 + 0x6AB3, KANJI_STANDARD, // 檳 + 0x6AAC, KANJI_STANDARD, // 檬 + 0x6ADE, KANJI_STANDARD, // 櫞 + 0x6AD1, KANJI_STANDARD, // 櫑 + 0x6ADF, KANJI_STANDARD, // 櫟 + 0x6AAA, KANJI_STANDARD, // 檪 + 0x6ADA, KANJI_STANDARD, // 櫚 + 0x6AEA, KANJI_STANDARD, // 櫪 + 0x6AFB, KANJI_STANDARD, // æ«» + 0x6B05, KANJI_STANDARD, // 欅 + 0x8616, KANJI_STANDARD, // 蘖 + 0x6AFA, KANJI_STANDARD, // 櫺 + 0x6B12, KANJI_STANDARD, // 欒 + 0x6B16, KANJI_STANDARD, // 欖 + 0x9B31, KANJI_STANDARD, // 鬱 + 0x6B1F, KANJI_STANDARD, // 欟 + 0x6B38, KANJI_STANDARD, // 欞 + 0x6B37, KANJI_STANDARD, // 欷 + 0x76DC, KANJI_STANDARD, // 盜 + 0x6B39, KANJI_STANDARD, // 欹 + 0x98EE, KANJI_STANDARD, // 飮 + 0x6B47, KANJI_STANDARD, // 歇 + 0x6B43, KANJI_STANDARD, // 歃 + 0x6B49, KANJI_STANDARD, // 歉 + 0x6B50, KANJI_STANDARD, // 歐 + 0x6B59, KANJI_STANDARD, // 歙 + 0x6B54, KANJI_STANDARD, // 歔 + 0x6B5B, KANJI_STANDARD, // 歛 + 0x6B5F, KANJI_STANDARD, // 歟 + 0x6B61, KANJI_STANDARD, // æ­¡ + 0x6B78, KANJI_STANDARD, // æ­ž + 0x6B79, KANJI_STANDARD, // æ­¹ + 0x6B7F, KANJI_STANDARD, // æ­¿ + 0x6B80, KANJI_STANDARD, // 殀 + 0x6B84, KANJI_STANDARD, // 殄 + 0x6B83, KANJI_STANDARD, // 殃 + 0x6B8D, KANJI_STANDARD, // 殍 + 0x6B98, KANJI_STANDARD, // 殘 + 0x6B95, KANJI_STANDARD, // 殕 + 0x6B9E, KANJI_STANDARD, // 殞 + 0x6BA4, KANJI_STANDARD, // 殀 + 0x6BAA, KANJI_STANDARD, // 殪 + 0x6BAB, KANJI_STANDARD, // 殫 + 0x6BAF, KANJI_STANDARD, // 殯 + 0x6BB2, KANJI_STANDARD, // 殲 + 0x6BB1, KANJI_STANDARD, // æ®± + 0x6BB3, KANJI_STANDARD, // 殳 + 0x6BB7, KANJI_STANDARD, // æ®· + 0x6BBC, KANJI_STANDARD, // 殌 + 0x6BC6, KANJI_STANDARD, // 毆 + 0x6BCB, KANJI_STANDARD, // 毋 + 0x6BD3, KANJI_STANDARD, // 毓 + 0x6BDF, KANJI_STANDARD, // 毟 + 0x6BEC, KANJI_STANDARD, // 毬 + 0x6BEB, KANJI_STANDARD, // 毫 + 0x6BF3, KANJI_STANDARD, // 毳 + 0x6BEF, KANJI_STANDARD, // 毯 + 0x9EBE, KANJI_STANDARD, // 麟 + 0x6C08, KANJI_STANDARD, // 氈 + 0x6C13, KANJI_STANDARD, // 氓 + 0x6C14, KANJI_STANDARD, // 气 + 0x6C1B, KANJI_STANDARD, // 氛 + 0x6C24, KANJI_STANDARD, // æ°€ + 0x6C23, KANJI_STANDARD, // æ°£ + 0x6C5E, KANJI_STANDARD, // 汞 + 0x6C55, KANJI_STANDARD, // 汕 + 0x6C62, KANJI_STANDARD, // æ±¢ + 0x6C6A, KANJI_STANDARD, // 汪 + 0x6C82, KANJI_STANDARD, // 沂 + 0x6C8D, KANJI_STANDARD, // 沍 + 0x6C9A, KANJI_STANDARD, // 沚 + 0x6C81, KANJI_STANDARD, // 沁 + 0x6C9B, KANJI_STANDARD, // 沛 + 0x6C7E, KANJI_STANDARD, // 江 + 0x6C68, KANJI_STANDARD, // 汚 + 0x6C73, KANJI_STANDARD, // æ±³ + 0x6C92, KANJI_STANDARD, // 沒 + 0x6C90, KANJI_STANDARD, // 沐 + 0x6CC4, KANJI_STANDARD, // 泄 + 0x6CF1, KANJI_STANDARD, // æ³± + 0x6CD3, KANJI_STANDARD, // 泓 + 0x6CBD, KANJI_STANDARD, // 沜 + 0x6CD7, KANJI_STANDARD, // 泗 + 0x6CC5, KANJI_STANDARD, // 泅 + 0x6CDD, KANJI_STANDARD, // 泝 + 0x6CAE, KANJI_STANDARD, // æ²® + 0x6CB1, KANJI_STANDARD, // æ²± + 0x6CBE, KANJI_STANDARD, // 沟 + 0x6CBA, KANJI_STANDARD, // 沺 + 0x6CDB, KANJI_STANDARD, // 泛 + 0x6CEF, KANJI_STANDARD, // 泯 + 0x6CD9, KANJI_STANDARD, // 泙 + 0x6CEA, KANJI_STANDARD, // 泪 + 0x6D1F, KANJI_STANDARD, // 掟 + 0x884D, KANJI_STANDARD, // 衍 + 0x6D36, KANJI_STANDARD, // 掶 + 0x6D2B, KANJI_STANDARD, // 掫 + 0x6D3D, KANJI_STANDARD, // 掜 + 0x6D38, KANJI_STANDARD, // 掞 + 0x6D19, KANJI_STANDARD, // 掙 + 0x6D35, KANJI_STANDARD, // 掵 + 0x6D33, KANJI_STANDARD, // 掳 + 0x6D12, KANJI_STANDARD, // 排 + 0x6D0C, KANJI_STANDARD, // 掌 + 0x6D63, KANJI_STANDARD, // æµ£ + 0x6D93, KANJI_STANDARD, // 涓 + 0x6D64, KANJI_STANDARD, // æµ€ + 0x6D5A, KANJI_STANDARD, // 浚 + 0x6D79, KANJI_STANDARD, // æµ¹ + 0x6D59, KANJI_STANDARD, // 浙 + 0x6D8E, KANJI_STANDARD, // 涎 + 0x6D95, KANJI_STANDARD, // 涕 + 0x6FE4, KANJI_STANDARD, // æ¿€ + 0x6D85, KANJI_STANDARD, // 涅 + 0x6DF9, KANJI_STANDARD, // æ·¹ + 0x6E15, KANJI_STANDARD, // æž• + 0x6E0A, KANJI_STANDARD, // 枊 + 0x6DB5, KANJI_STANDARD, // æ¶µ + 0x6DC7, KANJI_STANDARD, // 淇 + 0x6DE6, KANJI_STANDARD, // æ·Š + 0x6DB8, KANJI_STANDARD, // æ¶ž + 0x6DC6, KANJI_STANDARD, // 淆 + 0x6DEC, KANJI_STANDARD, // æ·¬ + 0x6DDE, KANJI_STANDARD, // 淞 + 0x6DCC, KANJI_STANDARD, // 淌 + 0x6DE8, KANJI_STANDARD, // æ·š + 0x6DD2, KANJI_STANDARD, // 淒 + 0x6DC5, KANJI_STANDARD, // 淅 + 0x6DFA, KANJI_STANDARD, // æ·º + 0x6DD9, KANJI_STANDARD, // 淙 + 0x6DE4, KANJI_STANDARD, // æ·€ + 0x6DD5, KANJI_STANDARD, // 淕 + 0x6DEA, KANJI_STANDARD, // æ·ª + 0x6DEE, KANJI_STANDARD, // æ·® + 0x6E2D, KANJI_STANDARD, // æž­ + 0x6E6E, KANJI_STANDARD, // æ¹® + 0x6E2E, KANJI_STANDARD, // æž® + 0x6E19, KANJI_STANDARD, // æž™ + 0x6E72, KANJI_STANDARD, // æ¹² + 0x6E5F, KANJI_STANDARD, // 湟 + 0x6E3E, KANJI_STANDARD, // 枟 + 0x6E23, KANJI_STANDARD, // 枣 + 0x6E6B, KANJI_STANDARD, // 湫 + 0x6E2B, KANJI_STANDARD, // æž« + 0x6E76, KANJI_STANDARD, // æ¹¶ + 0x6E4D, KANJI_STANDARD, // 湍 + 0x6E1F, KANJI_STANDARD, // 枟 + 0x6E43, KANJI_STANDARD, // 湃 + 0x6E3A, KANJI_STANDARD, // 枺 + 0x6E4E, KANJI_STANDARD, // 湎 + 0x6E24, KANJI_STANDARD, // 枀 + 0x6EFF, KANJI_STANDARD, // 滿 + 0x6E1D, KANJI_STANDARD, // 枝 + 0x6E38, KANJI_STANDARD, // æžž + 0x6E82, KANJI_STANDARD, // 溂 + 0x6EAA, KANJI_STANDARD, // 溪 + 0x6E98, KANJI_STANDARD, // 溘 + 0x6EC9, KANJI_STANDARD, // 滉 + 0x6EB7, KANJI_STANDARD, // 溷 + 0x6ED3, KANJI_STANDARD, // 滓 + 0x6EBD, KANJI_STANDARD, // 溜 + 0x6EAF, KANJI_STANDARD, // 溯 + 0x6EC4, KANJI_STANDARD, // 滄 + 0x6EB2, KANJI_STANDARD, // 溲 + 0x6ED4, KANJI_STANDARD, // 滔 + 0x6ED5, KANJI_STANDARD, // 滕 + 0x6E8F, KANJI_STANDARD, // 溏 + 0x6EA5, KANJI_STANDARD, // 溥 + 0x6EC2, KANJI_STANDARD, // 滂 + 0x6E9F, KANJI_STANDARD, // 溟 + 0x6F41, KANJI_STANDARD, // 朁 + 0x6F11, KANJI_STANDARD, // 挑 + 0x704C, KANJI_STANDARD, // 灌 + 0x6EEC, KANJI_STANDARD, // 滬 + 0x6EF8, KANJI_STANDARD, // 滞 + 0x6EFE, KANJI_STANDARD, // 滟 + 0x6F3F, KANJI_STANDARD, // 挿 + 0x6EF2, KANJI_STANDARD, // 滲 + 0x6F31, KANJI_STANDARD, // 挱 + 0x6EEF, KANJI_STANDARD, // 滯 + 0x6F32, KANJI_STANDARD, // 挲 + 0x6ECC, KANJI_STANDARD, // 滌 + 0x6F3E, KANJI_STANDARD, // 挟 + 0x6F13, KANJI_STANDARD, // 挓 + 0x6EF7, KANJI_STANDARD, // æ»· + 0x6F86, KANJI_STANDARD, // 柆 + 0x6F7A, KANJI_STANDARD, // 机 + 0x6F78, KANJI_STANDARD, // 朞 + 0x6F81, KANJI_STANDARD, // 柁 + 0x6F80, KANJI_STANDARD, // 柀 + 0x6F6F, KANJI_STANDARD, // 术 + 0x6F5B, KANJI_STANDARD, // 望 + 0x6FF3, KANJI_STANDARD, // 濳 + 0x6F6D, KANJI_STANDARD, // 札 + 0x6F82, KANJI_STANDARD, // 柂 + 0x6F7C, KANJI_STANDARD, // 朌 + 0x6F58, KANJI_STANDARD, // 朘 + 0x6F8E, KANJI_STANDARD, // 柎 + 0x6F91, KANJI_STANDARD, // 柑 + 0x6FC2, KANJI_STANDARD, // 濂 + 0x6F66, KANJI_STANDARD, // 朊 + 0x6FB3, KANJI_STANDARD, // 柳 + 0x6FA3, KANJI_STANDARD, // 柣 + 0x6FA1, KANJI_STANDARD, // 柡 + 0x6FA4, KANJI_STANDARD, // 柀 + 0x6FB9, KANJI_STANDARD, // 柹 + 0x6FC6, KANJI_STANDARD, // 濆 + 0x6FAA, KANJI_STANDARD, // 柪 + 0x6FDF, KANJI_STANDARD, // 濟 + 0x6FD5, KANJI_STANDARD, // 濕 + 0x6FEC, KANJI_STANDARD, // 濬 + 0x6FD4, KANJI_STANDARD, // 濔 + 0x6FD8, KANJI_STANDARD, // 濘 + 0x6FF1, KANJI_STANDARD, // 濱 + 0x6FEE, KANJI_STANDARD, // æ¿® + 0x6FDB, KANJI_STANDARD, // 濛 + 0x7009, KANJI_STANDARD, // 瀉 + 0x700B, KANJI_STANDARD, // 瀋 + 0x6FFA, KANJI_STANDARD, // 濺 + 0x7011, KANJI_STANDARD, // 瀑 + 0x7001, KANJI_STANDARD, // 瀁 + 0x700F, KANJI_STANDARD, // 瀏 + 0x6FFE, KANJI_STANDARD, // 濟 + 0x701B, KANJI_STANDARD, // 瀛 + 0x701A, KANJI_STANDARD, // 瀚 + 0x6F74, KANJI_STANDARD, // 朎 + 0x701D, KANJI_STANDARD, // 瀝 + 0x7018, KANJI_STANDARD, // 瀘 + 0x701F, KANJI_STANDARD, // 瀟 + 0x7030, KANJI_STANDARD, // 瀰 + 0x703E, KANJI_STANDARD, // 瀟 + 0x7032, KANJI_STANDARD, // 瀲 + 0x7051, KANJI_STANDARD, // 灑 + 0x7063, KANJI_STANDARD, // 灣 + 0x7099, KANJI_STANDARD, // 炙 + 0x7092, KANJI_STANDARD, // 炒 + 0x70AF, KANJI_STANDARD, // 炯 + 0x70F1, KANJI_STANDARD, // 烱 + 0x70AC, KANJI_STANDARD, // 炬 + 0x70B8, KANJI_STANDARD, // 炾 + 0x70B3, KANJI_STANDARD, // 炳 + 0x70AE, KANJI_STANDARD, // 炮 + 0x70DF, KANJI_STANDARD, // 烟 + 0x70CB, KANJI_STANDARD, // 烋 + 0x70DD, KANJI_STANDARD, // 烝 + 0x70D9, KANJI_STANDARD, // 烙 + 0x7109, KANJI_STANDARD, // 焉 + 0x70FD, KANJI_STANDARD, // 烜 + 0x711C, KANJI_STANDARD, // 焜 + 0x7119, KANJI_STANDARD, // 焙 + 0x7165, KANJI_STANDARD, // 煥 + 0x7155, KANJI_STANDARD, // 煕 + 0x7188, KANJI_STANDARD, // 熈 + 0x7166, KANJI_STANDARD, // 煩 + 0x7162, KANJI_STANDARD, // 煢 + 0x714C, KANJI_STANDARD, // 煌 + 0x7156, KANJI_STANDARD, // 煖 + 0x716C, KANJI_STANDARD, // 煬 + 0x718F, KANJI_STANDARD, // 熏 + 0x71FB, KANJI_STANDARD, // 燻 + 0x7184, KANJI_STANDARD, // 熄 + 0x7195, KANJI_STANDARD, // 熕 + 0x71A8, KANJI_STANDARD, // 熹 + 0x71AC, KANJI_STANDARD, // 熬 + 0x71D7, KANJI_STANDARD, // 燗 + 0x71B9, KANJI_STANDARD, // 熹 + 0x71BE, KANJI_STANDARD, // 熟 + 0x71D2, KANJI_STANDARD, // 燒 + 0x71C9, KANJI_STANDARD, // 燉 + 0x71D4, KANJI_STANDARD, // 燔 + 0x71CE, KANJI_STANDARD, // 燎 + 0x71E0, KANJI_STANDARD, // 燠 + 0x71EC, KANJI_STANDARD, // 燬 + 0x71E7, KANJI_STANDARD, // 燧 + 0x71F5, KANJI_STANDARD, // 燵 + 0x71FC, KANJI_STANDARD, // 燌 + 0x71F9, KANJI_STANDARD, // 燹 + 0x71FF, KANJI_STANDARD, // 燿 + 0x720D, KANJI_STANDARD, // 爍 + 0x7210, KANJI_STANDARD, // 爐 + 0x721B, KANJI_STANDARD, // 爛 + 0x7228, KANJI_STANDARD, // 爚 + 0x722D, KANJI_STANDARD, // 爭 + 0x722C, KANJI_STANDARD, // 爬 + 0x7230, KANJI_STANDARD, // 爰 + 0x7232, KANJI_STANDARD, // 爲 + 0x723B, KANJI_STANDARD, // 爻 + 0x723C, KANJI_STANDARD, // 爌 + 0x723F, KANJI_STANDARD, // 爿 + 0x7240, KANJI_STANDARD, // 牀 + 0x7246, KANJI_STANDARD, // 牆 + 0x724B, KANJI_STANDARD, // 牋 + 0x7258, KANJI_STANDARD, // 牘 + 0x7274, KANJI_STANDARD, // 牮 + 0x727E, KANJI_STANDARD, // 牟 + 0x7282, KANJI_STANDARD, // 犂 + 0x7281, KANJI_STANDARD, // 犁 + 0x7287, KANJI_STANDARD, // 犇 + 0x7292, KANJI_STANDARD, // 犒 + 0x7296, KANJI_STANDARD, // 犖 + 0x72A2, KANJI_STANDARD, // 犢 + 0x72A7, KANJI_STANDARD, // 犧 + 0x72B9, KANJI_STANDARD, // 犹 + 0x72B2, KANJI_STANDARD, // 犲 + 0x72C3, KANJI_STANDARD, // 狃 + 0x72C6, KANJI_STANDARD, // 狆 + 0x72C4, KANJI_STANDARD, // 狄 + 0x72CE, KANJI_STANDARD, // 狎 + 0x72D2, KANJI_STANDARD, // 狒 + 0x72E2, KANJI_STANDARD, // 狢 + 0x72E0, KANJI_STANDARD, // 狠 + 0x72E1, KANJI_STANDARD, // 狡 + 0x72F9, KANJI_STANDARD, // 狹 + 0x72F7, KANJI_STANDARD, // 狷 + 0x500F, KANJI_STANDARD, // 倏 + 0x7317, KANJI_STANDARD, // 猗 + 0x730A, KANJI_STANDARD, // 猊 + 0x731C, KANJI_STANDARD, // 猜 + 0x7316, KANJI_STANDARD, // 猖 + 0x731D, KANJI_STANDARD, // 猝 + 0x7334, KANJI_STANDARD, // 献 + 0x732F, KANJI_STANDARD, // 猯 + 0x7329, KANJI_STANDARD, // 猩 + 0x7325, KANJI_STANDARD, // 猥 + 0x733E, KANJI_STANDARD, // 猟 + 0x734E, KANJI_STANDARD, // 獎 + 0x734F, KANJI_STANDARD, // 獏 + 0x9ED8, KANJI_STANDARD, // 默 + 0x7357, KANJI_STANDARD, // 獗 + 0x736A, KANJI_STANDARD, // 獪 + 0x7368, KANJI_STANDARD, // 獚 + 0x7370, KANJI_STANDARD, // 獰 + 0x7378, KANJI_STANDARD, // 獞 + 0x7375, KANJI_STANDARD, // 獵 + 0x737B, KANJI_STANDARD, // 獻 + 0x737A, KANJI_STANDARD, // 獺 + 0x73C8, KANJI_STANDARD, // 珈 + 0x73B3, KANJI_STANDARD, // 玳 + 0x73CE, KANJI_STANDARD, // 珎 + 0x73BB, KANJI_STANDARD, // 玻 + 0x73C0, KANJI_STANDARD, // 珀 + 0x73E5, KANJI_STANDARD, // 珥 + 0x73EE, KANJI_STANDARD, // 珮 + 0x73DE, KANJI_STANDARD, // 珞 + 0x74A2, KANJI_STANDARD, // 璢 + 0x7405, KANJI_STANDARD, // 琅 + 0x746F, KANJI_STANDARD, // 瑯 + 0x7425, KANJI_STANDARD, // 琥 + 0x73F8, KANJI_STANDARD, // 珞 + 0x7432, KANJI_STANDARD, // 琲 + 0x743A, KANJI_STANDARD, // 琺 + 0x7455, KANJI_STANDARD, // 瑕 + 0x743F, KANJI_STANDARD, // 琿 + 0x745F, KANJI_STANDARD, // 瑟 + 0x7459, KANJI_STANDARD, // 瑙 + 0x7441, KANJI_STANDARD, // 瑁 + 0x745C, KANJI_STANDARD, // 瑜 + 0x7469, KANJI_STANDARD, // 瑩 + 0x7470, KANJI_STANDARD, // 瑰 + 0x7463, KANJI_STANDARD, // 瑣 + 0x746A, KANJI_STANDARD, // 瑪 + 0x7476, KANJI_STANDARD, // 瑶 + 0x747E, KANJI_STANDARD, // 瑟 + 0x748B, KANJI_STANDARD, // 璋 + 0x749E, KANJI_STANDARD, // 璞 + 0x74A7, KANJI_STANDARD, // 璧 + 0x74CA, KANJI_STANDARD, // 瓊 + 0x74CF, KANJI_STANDARD, // 瓏 + 0x74D4, KANJI_STANDARD, // 瓔 + 0x73F1, KANJI_STANDARD, // 珱 + 0x74E0, KANJI_STANDARD, // 瓠 + 0x74E3, KANJI_STANDARD, // 瓣 + 0x74E7, KANJI_STANDARD, // 瓧 + 0x74E9, KANJI_STANDARD, // 瓩 + 0x74EE, KANJI_STANDARD, // 瓮 + 0x74F2, KANJI_STANDARD, // 瓲 + 0x74F0, KANJI_STANDARD, // 瓰 + 0x74F1, KANJI_STANDARD, // 瓱 + 0x74F8, KANJI_STANDARD, // 瓾 + 0x74F7, KANJI_STANDARD, // 瓷 + 0x7504, KANJI_STANDARD, // 甄 + 0x7503, KANJI_STANDARD, // 甃 + 0x7505, KANJI_STANDARD, // 甅 + 0x750C, KANJI_STANDARD, // 甌 + 0x750E, KANJI_STANDARD, // 甎 + 0x750D, KANJI_STANDARD, // 甍 + 0x7515, KANJI_STANDARD, // 甕 + 0x7513, KANJI_STANDARD, // 甓 + 0x751E, KANJI_STANDARD, // 甞 + 0x7526, KANJI_STANDARD, // 甩 + 0x752C, KANJI_STANDARD, // 甬 + 0x753C, KANJI_STANDARD, // 甌 + 0x7544, KANJI_STANDARD, // 畄 + 0x754D, KANJI_STANDARD, // 畍 + 0x754A, KANJI_STANDARD, // 畊 + 0x7549, KANJI_STANDARD, // 畉 + 0x755B, KANJI_STANDARD, // 畛 + 0x7546, KANJI_STANDARD, // 畆 + 0x755A, KANJI_STANDARD, // 畚 + 0x7569, KANJI_STANDARD, // 畩 + 0x7564, KANJI_STANDARD, // ç•€ + 0x7567, KANJI_STANDARD, // 畧 + 0x756B, KANJI_STANDARD, // 畫 + 0x756D, KANJI_STANDARD, // 畭 + 0x7578, KANJI_STANDARD, // 畾 + 0x7576, KANJI_STANDARD, // 當 + 0x7586, KANJI_STANDARD, // 疆 + 0x7587, KANJI_STANDARD, // 疇 + 0x7574, KANJI_STANDARD, // 畮 + 0x758A, KANJI_STANDARD, // 疊 + 0x7589, KANJI_STANDARD, // 疉 + 0x7582, KANJI_STANDARD, // 疂 + 0x7594, KANJI_STANDARD, // 疔 + 0x759A, KANJI_STANDARD, // 疚 + 0x759D, KANJI_STANDARD, // 疝 + 0x75A5, KANJI_STANDARD, // 疥 + 0x75A3, KANJI_STANDARD, // 疣 + 0x75C2, KANJI_STANDARD, // 痂 + 0x75B3, KANJI_STANDARD, // 疳 + 0x75C3, KANJI_STANDARD, // 痃 + 0x75B5, KANJI_STANDARD, // 疵 + 0x75BD, KANJI_STANDARD, // ç–œ + 0x75B8, KANJI_STANDARD, // 疾 + 0x75BC, KANJI_STANDARD, // ç–Œ + 0x75B1, KANJI_STANDARD, // 疱 + 0x75CD, KANJI_STANDARD, // 痍 + 0x75CA, KANJI_STANDARD, // 痊 + 0x75D2, KANJI_STANDARD, // 痒 + 0x75D9, KANJI_STANDARD, // 痙 + 0x75E3, KANJI_STANDARD, // 痣 + 0x75DE, KANJI_STANDARD, // 痞 + 0x75FE, KANJI_STANDARD, // ç—Ÿ + 0x75FF, KANJI_STANDARD, // 痿 + 0x75FC, KANJI_STANDARD, // ç—Œ + 0x7601, KANJI_STANDARD, // 瘁 + 0x75F0, KANJI_STANDARD, // 痰 + 0x75FA, KANJI_STANDARD, // 痺 + 0x75F2, KANJI_STANDARD, // 痲 + 0x75F3, KANJI_STANDARD, // 痳 + 0x760B, KANJI_STANDARD, // 瘋 + 0x760D, KANJI_STANDARD, // 瘍 + 0x7609, KANJI_STANDARD, // 瘉 + 0x761F, KANJI_STANDARD, // 瘟 + 0x7627, KANJI_STANDARD, // 瘧 + 0x7620, KANJI_STANDARD, // 瘠 + 0x7621, KANJI_STANDARD, // 瘡 + 0x7622, KANJI_STANDARD, // 瘢 + 0x7624, KANJI_STANDARD, // 瘀 + 0x7634, KANJI_STANDARD, // 瘎 + 0x7630, KANJI_STANDARD, // 瘰 + 0x763B, KANJI_STANDARD, // 瘻 + 0x7647, KANJI_STANDARD, // 癇 + 0x7648, KANJI_STANDARD, // 癈 + 0x7646, KANJI_STANDARD, // 癆 + 0x765C, KANJI_STANDARD, // 癜 + 0x7658, KANJI_STANDARD, // 癘 + 0x7661, KANJI_STANDARD, // 癡 + 0x7662, KANJI_STANDARD, // 癢 + 0x7668, KANJI_STANDARD, // 癹 + 0x7669, KANJI_STANDARD, // 癩 + 0x766A, KANJI_STANDARD, // 癪 + 0x7667, KANJI_STANDARD, // 癧 + 0x766C, KANJI_STANDARD, // 癬 + 0x7670, KANJI_STANDARD, // 癰 + 0x7672, KANJI_STANDARD, // 癲 + 0x7676, KANJI_STANDARD, // 癶 + 0x7678, KANJI_STANDARD, // 百 + 0x767C, KANJI_STANDARD, // 癌 + 0x7680, KANJI_STANDARD, // 皀 + 0x7683, KANJI_STANDARD, // 皃 + 0x7688, KANJI_STANDARD, // 皈 + 0x768B, KANJI_STANDARD, // 皋 + 0x768E, KANJI_STANDARD, // 皎 + 0x7696, KANJI_STANDARD, // 皖 + 0x7693, KANJI_STANDARD, // 皓 + 0x7699, KANJI_STANDARD, // 皙 + 0x769A, KANJI_STANDARD, // 皚 + 0x76B0, KANJI_STANDARD, // 皰 + 0x76B4, KANJI_STANDARD, // 皮 + 0x76B8, KANJI_STANDARD, // 皾 + 0x76B9, KANJI_STANDARD, // 皹 + 0x76BA, KANJI_STANDARD, // 皺 + 0x76C2, KANJI_STANDARD, // 盂 + 0x76CD, KANJI_STANDARD, // 盍 + 0x76D6, KANJI_STANDARD, // 盖 + 0x76D2, KANJI_STANDARD, // 盒 + 0x76DE, KANJI_STANDARD, // 盞 + 0x76E1, KANJI_STANDARD, // 盡 + 0x76E5, KANJI_STANDARD, // 盥 + 0x76E7, KANJI_STANDARD, // 盧 + 0x76EA, KANJI_STANDARD, // 盪 + 0x862F, KANJI_STANDARD, // 蘯 + 0x76FB, KANJI_STANDARD, // 盻 + 0x7708, KANJI_STANDARD, // 眈 + 0x7707, KANJI_STANDARD, // 眇 + 0x7704, KANJI_STANDARD, // 眄 + 0x7729, KANJI_STANDARD, // 眩 + 0x7724, KANJI_STANDARD, // 眀 + 0x771E, KANJI_STANDARD, // 眞 + 0x7725, KANJI_STANDARD, // 眥 + 0x7726, KANJI_STANDARD, // 眩 + 0x771B, KANJI_STANDARD, // 眛 + 0x7737, KANJI_STANDARD, // 眷 + 0x7738, KANJI_STANDARD, // 眾 + 0x7747, KANJI_STANDARD, // 睇 + 0x775A, KANJI_STANDARD, // 睚 + 0x7768, KANJI_STANDARD, // 睚 + 0x776B, KANJI_STANDARD, // 睫 + 0x775B, KANJI_STANDARD, // 睛 + 0x7765, KANJI_STANDARD, // 睥 + 0x777F, KANJI_STANDARD, // 睿 + 0x777E, KANJI_STANDARD, // 睟 + 0x7779, KANJI_STANDARD, // 睹 + 0x778E, KANJI_STANDARD, // 瞎 + 0x778B, KANJI_STANDARD, // 瞋 + 0x7791, KANJI_STANDARD, // 瞑 + 0x77A0, KANJI_STANDARD, // 瞠 + 0x779E, KANJI_STANDARD, // 瞞 + 0x77B0, KANJI_STANDARD, // 瞰 + 0x77B6, KANJI_STANDARD, // 瞶 + 0x77B9, KANJI_STANDARD, // 瞹 + 0x77BF, KANJI_STANDARD, // 瞿 + 0x77BC, KANJI_STANDARD, // 瞌 + 0x77BD, KANJI_STANDARD, // 瞜 + 0x77BB, KANJI_STANDARD, // 瞻 + 0x77C7, KANJI_STANDARD, // 矇 + 0x77CD, KANJI_STANDARD, // 矍 + 0x77D7, KANJI_STANDARD, // 矗 + 0x77DA, KANJI_STANDARD, // 矚 + 0x77DC, KANJI_STANDARD, // 矜 + 0x77E3, KANJI_STANDARD, // 矣 + 0x77EE, KANJI_STANDARD, // 矮 + 0x77FC, KANJI_STANDARD, // 矌 + 0x780C, KANJI_STANDARD, // 砌 + 0x7812, KANJI_STANDARD, // 砒 + 0x7926, KANJI_STANDARD, // 瀊 + 0x7820, KANJI_STANDARD, // ç   + 0x792A, KANJI_STANDARD, // 瀪 + 0x7845, KANJI_STANDARD, // 硅 + 0x788E, KANJI_STANDARD, // 碎 + 0x7874, KANJI_STANDARD, // 硎 + 0x7886, KANJI_STANDARD, // 碆 + 0x787C, KANJI_STANDARD, // 硌 + 0x789A, KANJI_STANDARD, // 碚 + 0x788C, KANJI_STANDARD, // 碌 + 0x78A3, KANJI_STANDARD, // 碣 + 0x78B5, KANJI_STANDARD, // 碵 + 0x78AA, KANJI_STANDARD, // 碪 + 0x78AF, KANJI_STANDARD, // 碯 + 0x78D1, KANJI_STANDARD, // 磑 + 0x78C6, KANJI_STANDARD, // 磆 + 0x78CB, KANJI_STANDARD, // 磋 + 0x78D4, KANJI_STANDARD, // 磔 + 0x78BE, KANJI_STANDARD, // 碟 + 0x78BC, KANJI_STANDARD, // 碌 + 0x78C5, KANJI_STANDARD, // 磅 + 0x78CA, KANJI_STANDARD, // 磊 + 0x78EC, KANJI_STANDARD, // 磬 + 0x78E7, KANJI_STANDARD, // 磧 + 0x78DA, KANJI_STANDARD, // 磚 + 0x78FD, KANJI_STANDARD, // 磜 + 0x78F4, KANJI_STANDARD, // 磎 + 0x7907, KANJI_STANDARD, // 瀇 + 0x7912, KANJI_STANDARD, // 瀒 + 0x7911, KANJI_STANDARD, // 瀑 + 0x7919, KANJI_STANDARD, // 瀙 + 0x792C, KANJI_STANDARD, // 瀬 + 0x792B, KANJI_STANDARD, // 瀫 + 0x7940, KANJI_STANDARD, // 祀 + 0x7960, KANJI_STANDARD, // 祠 + 0x7957, KANJI_STANDARD, // 祗 + 0x795F, KANJI_STANDARD, // 祟 + 0x795A, KANJI_STANDARD, // 祚 + 0x7955, KANJI_STANDARD, // 祕 + 0x7953, KANJI_STANDARD, // 祓 + 0x797A, KANJI_STANDARD, // 祺 + 0x797F, KANJI_STANDARD, // 祿 + 0x798A, KANJI_STANDARD, // 穊 + 0x799D, KANJI_STANDARD, // 犝 + 0x79A7, KANJI_STANDARD, // 犧 + 0x9F4B, KANJI_STANDARD, // 霋 + 0x79AA, KANJI_STANDARD, // 犪 + 0x79AE, KANJI_STANDARD, // 犮 + 0x79B3, KANJI_STANDARD, // 犳 + 0x79B9, KANJI_STANDARD, // 犹 + 0x79BA, KANJI_STANDARD, // 犺 + 0x79C9, KANJI_STANDARD, // 秉 + 0x79D5, KANJI_STANDARD, // 秕 + 0x79E7, KANJI_STANDARD, // ç§§ + 0x79EC, KANJI_STANDARD, // 秬 + 0x79E1, KANJI_STANDARD, // ç§¡ + 0x79E3, KANJI_STANDARD, // ç§£ + 0x7A08, KANJI_STANDARD, // 皈 + 0x7A0D, KANJI_STANDARD, // 皍 + 0x7A18, KANJI_STANDARD, // 皘 + 0x7A19, KANJI_STANDARD, // 繙 + 0x7A20, KANJI_STANDARD, // çš  + 0x7A1F, KANJI_STANDARD, // 繟 + 0x7980, KANJI_STANDARD, // 穀 + 0x7A31, KANJI_STANDARD, // çš± + 0x7A3B, KANJI_STANDARD, // çš» + 0x7A3E, KANJI_STANDARD, // 皟 + 0x7A37, KANJI_STANDARD, // çš· + 0x7A43, KANJI_STANDARD, // 穃 + 0x7A57, KANJI_STANDARD, // 穗 + 0x7A49, KANJI_STANDARD, // 穉 + 0x7A61, KANJI_STANDARD, // ç©¡ + 0x7A62, KANJI_STANDARD, // ç©¢ + 0x7A69, KANJI_STANDARD, // ç©© + 0x9F9D, KANJI_STANDARD, // 韝 + 0x7A70, KANJI_STANDARD, // ç©° + 0x7A79, KANJI_STANDARD, // 穹 + 0x7A7D, KANJI_STANDARD, // 穜 + 0x7A88, KANJI_STANDARD, // 窈 + 0x7A97, KANJI_STANDARD, // 窗 + 0x7A95, KANJI_STANDARD, // 窕 + 0x7A98, KANJI_STANDARD, // 窘 + 0x7A96, KANJI_STANDARD, // 窖 + 0x7AA9, KANJI_STANDARD, // 窩 + 0x7AC8, KANJI_STANDARD, // 竈 + 0x7AB0, KANJI_STANDARD, // 窰 + 0x7AB6, KANJI_STANDARD, // 窶 + 0x7AC5, KANJI_STANDARD, // 竅 + 0x7AC4, KANJI_STANDARD, // 竄 + 0x7ABF, KANJI_STANDARD, // 窿 + 0x9083, KANJI_STANDARD, // 邃 + 0x7AC7, KANJI_STANDARD, // 竇 + 0x7ACA, KANJI_STANDARD, // 竊 + 0x7ACD, KANJI_STANDARD, // 竍 + 0x7ACF, KANJI_STANDARD, // 竏 + 0x7AD5, KANJI_STANDARD, // 竕 + 0x7AD3, KANJI_STANDARD, // 竓 + 0x7AD9, KANJI_STANDARD, // 站 + 0x7ADA, KANJI_STANDARD, // 竚 + 0x7ADD, KANJI_STANDARD, // 竝 + 0x7AE1, KANJI_STANDARD, // ç«¡ + 0x7AE2, KANJI_STANDARD, // ç«¢ + 0x7AE6, KANJI_STANDARD, // 竊 + 0x7AED, KANJI_STANDARD, // ç«­ + 0x7AF0, KANJI_STANDARD, // ç«° + 0x7B02, KANJI_STANDARD, // 笂 + 0x7B0F, KANJI_STANDARD, // 笏 + 0x7B0A, KANJI_STANDARD, // 笊 + 0x7B06, KANJI_STANDARD, // 笆 + 0x7B33, KANJI_STANDARD, // 笳 + 0x7B18, KANJI_STANDARD, // 笘 + 0x7B19, KANJI_STANDARD, // 笙 + 0x7B1E, KANJI_STANDARD, // 笞 + 0x7B35, KANJI_STANDARD, // 笵 + 0x7B28, KANJI_STANDARD, // 笚 + 0x7B36, KANJI_STANDARD, // 笶 + 0x7B50, KANJI_STANDARD, // 筐 + 0x7B7A, KANJI_STANDARD, // ç­º + 0x7B04, KANJI_STANDARD, // 笄 + 0x7B4D, KANJI_STANDARD, // 筍 + 0x7B0B, KANJI_STANDARD, // 笋 + 0x7B4C, KANJI_STANDARD, // 筌 + 0x7B45, KANJI_STANDARD, // 筅 + 0x7B75, KANJI_STANDARD, // ç­µ + 0x7B65, KANJI_STANDARD, // ç­¥ + 0x7B74, KANJI_STANDARD, // ç­Ž + 0x7B67, KANJI_STANDARD, // ç­§ + 0x7B70, KANJI_STANDARD, // ç­° + 0x7B71, KANJI_STANDARD, // ç­± + 0x7B6C, KANJI_STANDARD, // ç­¬ + 0x7B6E, KANJI_STANDARD, // ç­® + 0x7B9D, KANJI_STANDARD, // 箝 + 0x7B98, KANJI_STANDARD, // 箘 + 0x7B9F, KANJI_STANDARD, // 箟 + 0x7B8D, KANJI_STANDARD, // 箍 + 0x7B9C, KANJI_STANDARD, // 箜 + 0x7B9A, KANJI_STANDARD, // 箚 + 0x7B8B, KANJI_STANDARD, // 箋 + 0x7B92, KANJI_STANDARD, // 箒 + 0x7B8F, KANJI_STANDARD, // 箏 + 0x7B5D, KANJI_STANDARD, // 筝 + 0x7B99, KANJI_STANDARD, // 箙 + 0x7BCB, KANJI_STANDARD, // 篋 + 0x7BC1, KANJI_STANDARD, // 篁 + 0x7BCC, KANJI_STANDARD, // 篌 + 0x7BCF, KANJI_STANDARD, // 篏 + 0x7BB4, KANJI_STANDARD, // 箎 + 0x7BC6, KANJI_STANDARD, // 篆 + 0x7BDD, KANJI_STANDARD, // 篝 + 0x7BE9, KANJI_STANDARD, // 篩 + 0x7C11, KANJI_STANDARD, // 簑 + 0x7C14, KANJI_STANDARD, // 簔 + 0x7BE6, KANJI_STANDARD, // 篊 + 0x7BE5, KANJI_STANDARD, // 篥 + 0x7C60, KANJI_STANDARD, // ç±  + 0x7C00, KANJI_STANDARD, // 簀 + 0x7C07, KANJI_STANDARD, // 簇 + 0x7C13, KANJI_STANDARD, // 簓 + 0x7BF3, KANJI_STANDARD, // 篳 + 0x7BF7, KANJI_STANDARD, // 篷 + 0x7C17, KANJI_STANDARD, // 簗 + 0x7C0D, KANJI_STANDARD, // 簍 + 0x7BF6, KANJI_STANDARD, // 篶 + 0x7C23, KANJI_STANDARD, // ç°£ + 0x7C27, KANJI_STANDARD, // ç°§ + 0x7C2A, KANJI_STANDARD, // ç°ª + 0x7C1F, KANJI_STANDARD, // 簟 + 0x7C37, KANJI_STANDARD, // ç°· + 0x7C2B, KANJI_STANDARD, // ç°« + 0x7C3D, KANJI_STANDARD, // ç°œ + 0x7C4C, KANJI_STANDARD, // 籌 + 0x7C43, KANJI_STANDARD, // 籃 + 0x7C54, KANJI_STANDARD, // 籔 + 0x7C4F, KANJI_STANDARD, // 籏 + 0x7C40, KANJI_STANDARD, // 籀 + 0x7C50, KANJI_STANDARD, // 籐 + 0x7C58, KANJI_STANDARD, // 籘 + 0x7C5F, KANJI_STANDARD, // 籟 + 0x7C64, KANJI_STANDARD, // ç±€ + 0x7C56, KANJI_STANDARD, // 籖 + 0x7C65, KANJI_STANDARD, // ç±¥ + 0x7C6C, KANJI_STANDARD, // 籬 + 0x7C75, KANJI_STANDARD, // ç±µ + 0x7C83, KANJI_STANDARD, // 粃 + 0x7C90, KANJI_STANDARD, // 粐 + 0x7CA4, KANJI_STANDARD, // ç²€ + 0x7CAD, KANJI_STANDARD, // ç²­ + 0x7CA2, KANJI_STANDARD, // ç²¢ + 0x7CAB, KANJI_STANDARD, // 粫 + 0x7CA1, KANJI_STANDARD, // 粡 + 0x7CA8, KANJI_STANDARD, // 粚 + 0x7CB3, KANJI_STANDARD, // ç²³ + 0x7CB2, KANJI_STANDARD, // ç²² + 0x7CB1, KANJI_STANDARD, // ç²± + 0x7CAE, KANJI_STANDARD, // ç²® + 0x7CB9, KANJI_STANDARD, // ç²¹ + 0x7CBD, KANJI_STANDARD, // 粜 + 0x7CC0, KANJI_STANDARD, // 糀 + 0x7CC5, KANJI_STANDARD, // 糅 + 0x7CC2, KANJI_STANDARD, // 糂 + 0x7CD8, KANJI_STANDARD, // 糘 + 0x7CD2, KANJI_STANDARD, // 糒 + 0x7CDC, KANJI_STANDARD, // 糜 + 0x7CE2, KANJI_STANDARD, // ç³¢ + 0x9B3B, KANJI_STANDARD, // 鬻 + 0x7CEF, KANJI_STANDARD, // 糯 + 0x7CF2, KANJI_STANDARD, // ç³² + 0x7CF4, KANJI_STANDARD, // 糎 + 0x7CF6, KANJI_STANDARD, // ç³¶ + 0x7CFA, KANJI_STANDARD, // 糺 + 0x7D06, KANJI_STANDARD, // 箆 + 0x7D02, KANJI_STANDARD, // 箂 + 0x7D1C, KANJI_STANDARD, // 箜 + 0x7D15, KANJI_STANDARD, // 箕 + 0x7D0A, KANJI_STANDARD, // 箊 + 0x7D45, KANJI_STANDARD, // 絅 + 0x7D4B, KANJI_STANDARD, // 絋 + 0x7D2E, KANJI_STANDARD, // 玮 + 0x7D32, KANJI_STANDARD, // 玲 + 0x7D3F, KANJI_STANDARD, // 玿 + 0x7D35, KANJI_STANDARD, // 玵 + 0x7D46, KANJI_STANDARD, // 絆 + 0x7D73, KANJI_STANDARD, // çµ³ + 0x7D56, KANJI_STANDARD, // 絖 + 0x7D4E, KANJI_STANDARD, // 絎 + 0x7D72, KANJI_STANDARD, // çµ² + 0x7D68, KANJI_STANDARD, // 絚 + 0x7D6E, KANJI_STANDARD, // çµ® + 0x7D4F, KANJI_STANDARD, // 絏 + 0x7D63, KANJI_STANDARD, // çµ£ + 0x7D93, KANJI_STANDARD, // 經 + 0x7D89, KANJI_STANDARD, // 綉 + 0x7D5B, KANJI_STANDARD, // 絛 + 0x7D8F, KANJI_STANDARD, // 綏 + 0x7D7D, KANJI_STANDARD, // 絜 + 0x7D9B, KANJI_STANDARD, // 綛 + 0x7DBA, KANJI_STANDARD, // 綺 + 0x7DAE, KANJI_STANDARD, // ç¶® + 0x7DA3, KANJI_STANDARD, // ç¶£ + 0x7DB5, KANJI_STANDARD, // ç¶µ + 0x7DC7, KANJI_STANDARD, // 緇 + 0x7DBD, KANJI_STANDARD, // ç¶œ + 0x7DAB, KANJI_STANDARD, // ç¶« + 0x7E3D, KANJI_STANDARD, // çžœ + 0x7DA2, KANJI_STANDARD, // ç¶¢ + 0x7DAF, KANJI_STANDARD, // 綯 + 0x7DDC, KANJI_STANDARD, // 緜 + 0x7DB8, KANJI_STANDARD, // ç¶ž + 0x7D9F, KANJI_STANDARD, // 綟 + 0x7DB0, KANJI_STANDARD, // ç¶° + 0x7DD8, KANJI_STANDARD, // 緘 + 0x7DDD, KANJI_STANDARD, // 緝 + 0x7DE4, KANJI_STANDARD, // ç·€ + 0x7DDE, KANJI_STANDARD, // 緞 + 0x7DFB, KANJI_STANDARD, // ç·» + 0x7DF2, KANJI_STANDARD, // ç·² + 0x7DE1, KANJI_STANDARD, // ç·¡ + 0x7E05, KANJI_STANDARD, // 羅 + 0x7E0A, KANJI_STANDARD, // 羊 + 0x7E23, KANJI_STANDARD, // 瞣 + 0x7E21, KANJI_STANDARD, // çž¡ + 0x7E12, KANJI_STANDARD, // 羒 + 0x7E31, KANJI_STANDARD, // çž± + 0x7E1F, KANJI_STANDARD, // 羟 + 0x7E09, KANJI_STANDARD, // 羉 + 0x7E0B, KANJI_STANDARD, // 羋 + 0x7E22, KANJI_STANDARD, // 瞢 + 0x7E46, KANJI_STANDARD, // 繆 + 0x7E66, KANJI_STANDARD, // 繊 + 0x7E3B, KANJI_STANDARD, // çž» + 0x7E35, KANJI_STANDARD, // çžµ + 0x7E39, KANJI_STANDARD, // çž¹ + 0x7E43, KANJI_STANDARD, // 繃 + 0x7E37, KANJI_STANDARD, // çž· + 0x7E32, KANJI_STANDARD, // çž² + 0x7E3A, KANJI_STANDARD, // 瞺 + 0x7E67, KANJI_STANDARD, // ç¹§ + 0x7E5D, KANJI_STANDARD, // 繝 + 0x7E56, KANJI_STANDARD, // 繖 + 0x7E5E, KANJI_STANDARD, // 繞 + 0x7E59, KANJI_STANDARD, // 繙 + 0x7E5A, KANJI_STANDARD, // 繚 + 0x7E79, KANJI_STANDARD, // ç¹¹ + 0x7E6A, KANJI_STANDARD, // 繪 + 0x7E69, KANJI_STANDARD, // 繩 + 0x7E7C, KANJI_STANDARD, // 繌 + 0x7E7B, KANJI_STANDARD, // ç¹» + 0x7E83, KANJI_STANDARD, // 纃 + 0x7DD5, KANJI_STANDARD, // 緕 + 0x7E7D, KANJI_STANDARD, // 繜 + 0x8FAE, KANJI_STANDARD, // 蟮 + 0x7E7F, KANJI_STANDARD, // 繿 + 0x7E88, KANJI_STANDARD, // 纈 + 0x7E89, KANJI_STANDARD, // 纉 + 0x7E8C, KANJI_STANDARD, // 續 + 0x7E92, KANJI_STANDARD, // 纒 + 0x7E90, KANJI_STANDARD, // 纐 + 0x7E93, KANJI_STANDARD, // 纓 + 0x7E94, KANJI_STANDARD, // 纔 + 0x7E96, KANJI_STANDARD, // 纖 + 0x7E8E, KANJI_STANDARD, // 纎 + 0x7E9B, KANJI_STANDARD, // 纛 + 0x7E9C, KANJI_STANDARD, // 纜 + 0x7F38, KANJI_STANDARD, // 猞 + 0x7F3A, KANJI_STANDARD, // 猺 + 0x7F45, KANJI_STANDARD, // 眅 + 0x7F4C, KANJI_STANDARD, // 県 + 0x7F4D, KANJI_STANDARD, // 眍 + 0x7F4E, KANJI_STANDARD, // 眎 + 0x7F50, KANJI_STANDARD, // 眐 + 0x7F51, KANJI_STANDARD, // 眑 + 0x7F55, KANJI_STANDARD, // 眕 + 0x7F54, KANJI_STANDARD, // 眔 + 0x7F58, KANJI_STANDARD, // 眘 + 0x7F5F, KANJI_STANDARD, // 真 + 0x7F60, KANJI_STANDARD, // 眠 + 0x7F68, KANJI_STANDARD, // 眚 + 0x7F69, KANJI_STANDARD, // 眩 + 0x7F67, KANJI_STANDARD, // 眧 + 0x7F78, KANJI_STANDARD, // 眞 + 0x7F82, KANJI_STANDARD, // 矂 + 0x7F86, KANJI_STANDARD, // 矆 + 0x7F83, KANJI_STANDARD, // 矃 + 0x7F88, KANJI_STANDARD, // 矈 + 0x7F87, KANJI_STANDARD, // 矇 + 0x7F8C, KANJI_STANDARD, // 矌 + 0x7F94, KANJI_STANDARD, // 矔 + 0x7F9E, KANJI_STANDARD, // 矞 + 0x7F9D, KANJI_STANDARD, // 矝 + 0x7F9A, KANJI_STANDARD, // 矚 + 0x7FA3, KANJI_STANDARD, // 矣 + 0x7FAF, KANJI_STANDARD, // 矯 + 0x7FB2, KANJI_STANDARD, // 矲 + 0x7FB9, KANJI_STANDARD, // 矹 + 0x7FAE, KANJI_STANDARD, // 矮 + 0x7FB6, KANJI_STANDARD, // 矶 + 0x7FB8, KANJI_STANDARD, // 矞 + 0x8B71, KANJI_STANDARD, // è­± + 0x7FC5, KANJI_STANDARD, // 翅 + 0x7FC6, KANJI_STANDARD, // 翆 + 0x7FCA, KANJI_STANDARD, // 翊 + 0x7FD5, KANJI_STANDARD, // 翕 + 0x7FD4, KANJI_STANDARD, // 翔 + 0x7FE1, KANJI_STANDARD, // ç¿¡ + 0x7FE6, KANJI_STANDARD, // 翊 + 0x7FE9, KANJI_STANDARD, // ç¿© + 0x7FF3, KANJI_STANDARD, // 翳 + 0x7FF9, KANJI_STANDARD, // 翹 + 0x98DC, KANJI_STANDARD, // 飜 + 0x8006, KANJI_STANDARD, // 耆 + 0x8004, KANJI_STANDARD, // 耄 + 0x800B, KANJI_STANDARD, // 耋 + 0x8012, KANJI_STANDARD, // 耒 + 0x8018, KANJI_STANDARD, // 耘 + 0x8019, KANJI_STANDARD, // 耙 + 0x801C, KANJI_STANDARD, // 耜 + 0x8021, KANJI_STANDARD, // 耡 + 0x8028, KANJI_STANDARD, // 耚 + 0x803F, KANJI_STANDARD, // 耿 + 0x803B, KANJI_STANDARD, // 耻 + 0x804A, KANJI_STANDARD, // 聊 + 0x8046, KANJI_STANDARD, // 聆 + 0x8052, KANJI_STANDARD, // 聒 + 0x8058, KANJI_STANDARD, // 聘 + 0x805A, KANJI_STANDARD, // 聚 + 0x805F, KANJI_STANDARD, // 聟 + 0x8062, KANJI_STANDARD, // 聢 + 0x8068, KANJI_STANDARD, // 聚 + 0x8073, KANJI_STANDARD, // 聳 + 0x8072, KANJI_STANDARD, // 聲 + 0x8070, KANJI_STANDARD, // 聰 + 0x8076, KANJI_STANDARD, // 聶 + 0x8079, KANJI_STANDARD, // 聹 + 0x807D, KANJI_STANDARD, // 聜 + 0x807F, KANJI_STANDARD, // 聿 + 0x8084, KANJI_STANDARD, // 肄 + 0x8086, KANJI_STANDARD, // 肆 + 0x8085, KANJI_STANDARD, // 肅 + 0x809B, KANJI_STANDARD, // 肛 + 0x8093, KANJI_STANDARD, // 肓 + 0x809A, KANJI_STANDARD, // 肚 + 0x80AD, KANJI_STANDARD, // 肭 + 0x5190, KANJI_STANDARD, // 冐 + 0x80AC, KANJI_STANDARD, // 肬 + 0x80DB, KANJI_STANDARD, // 胛 + 0x80E5, KANJI_STANDARD, // 胥 + 0x80D9, KANJI_STANDARD, // 胙 + 0x80DD, KANJI_STANDARD, // 胝 + 0x80C4, KANJI_STANDARD, // 胄 + 0x80DA, KANJI_STANDARD, // 胚 + 0x80D6, KANJI_STANDARD, // 胖 + 0x8109, KANJI_STANDARD, // 脉 + 0x80EF, KANJI_STANDARD, // 胯 + 0x80F1, KANJI_STANDARD, // 胱 + 0x811B, KANJI_STANDARD, // 脛 + 0x8129, KANJI_STANDARD, // 脩 + 0x8123, KANJI_STANDARD, // 脣 + 0x812F, KANJI_STANDARD, // 脯 + 0x814B, KANJI_STANDARD, // 腋 + 0x968B, KANJI_STANDARD, // 隋 + 0x8146, KANJI_STANDARD, // 腆 + 0x813E, KANJI_STANDARD, // 脟 + 0x8153, KANJI_STANDARD, // 腓 + 0x8151, KANJI_STANDARD, // 腑 + 0x80FC, KANJI_STANDARD, // 背 + 0x8171, KANJI_STANDARD, // 腱 + 0x816E, KANJI_STANDARD, // 腮 + 0x8165, KANJI_STANDARD, // 腥 + 0x8166, KANJI_STANDARD, // è…Š + 0x8174, KANJI_STANDARD, // è…Ž + 0x8183, KANJI_STANDARD, // 膃 + 0x8188, KANJI_STANDARD, // 膈 + 0x818A, KANJI_STANDARD, // 膊 + 0x8180, KANJI_STANDARD, // 膀 + 0x8182, KANJI_STANDARD, // 膂 + 0x81A0, KANJI_STANDARD, // 膠 + 0x8195, KANJI_STANDARD, // 膕 + 0x81A4, KANJI_STANDARD, // 膀 + 0x81A3, KANJI_STANDARD, // 膣 + 0x815F, KANJI_STANDARD, // 腟 + 0x8193, KANJI_STANDARD, // 膓 + 0x81A9, KANJI_STANDARD, // 膩 + 0x81B0, KANJI_STANDARD, // 膰 + 0x81B5, KANJI_STANDARD, // 膵 + 0x81BE, KANJI_STANDARD, // 膟 + 0x81B8, KANJI_STANDARD, // 膞 + 0x81BD, KANJI_STANDARD, // 膜 + 0x81C0, KANJI_STANDARD, // 臀 + 0x81C2, KANJI_STANDARD, // 臂 + 0x81BA, KANJI_STANDARD, // 膺 + 0x81C9, KANJI_STANDARD, // 臉 + 0x81CD, KANJI_STANDARD, // 臍 + 0x81D1, KANJI_STANDARD, // 臑 + 0x81D9, KANJI_STANDARD, // 臙 + 0x81D8, KANJI_STANDARD, // 臘 + 0x81C8, KANJI_STANDARD, // 臈 + 0x81DA, KANJI_STANDARD, // 臚 + 0x81DF, KANJI_STANDARD, // 臟 + 0x81E0, KANJI_STANDARD, // 臠 + 0x81E7, KANJI_STANDARD, // 臧 + 0x81FA, KANJI_STANDARD, // 臺 + 0x81FB, KANJI_STANDARD, // 臻 + 0x81FE, KANJI_STANDARD, // 臟 + 0x8201, KANJI_STANDARD, // 舁 + 0x8202, KANJI_STANDARD, // 舂 + 0x8205, KANJI_STANDARD, // 舅 + 0x8207, KANJI_STANDARD, // 與 + 0x820A, KANJI_STANDARD, // 舊 + 0x820D, KANJI_STANDARD, // 舍 + 0x8210, KANJI_STANDARD, // 舐 + 0x8216, KANJI_STANDARD, // 舖 + 0x8229, KANJI_STANDARD, // 舩 + 0x822B, KANJI_STANDARD, // 舫 + 0x8238, KANJI_STANDARD, // 舞 + 0x8233, KANJI_STANDARD, // 舳 + 0x8240, KANJI_STANDARD, // 艀 + 0x8259, KANJI_STANDARD, // 艙 + 0x8258, KANJI_STANDARD, // 艘 + 0x825D, KANJI_STANDARD, // 艝 + 0x825A, KANJI_STANDARD, // 艚 + 0x825F, KANJI_STANDARD, // 艟 + 0x8264, KANJI_STANDARD, // 艀 + 0x8262, KANJI_STANDARD, // 艢 + 0x8268, KANJI_STANDARD, // 艚 + 0x826A, KANJI_STANDARD, // 艪 + 0x826B, KANJI_STANDARD, // 艫 + 0x822E, KANJI_STANDARD, // 舮 + 0x8271, KANJI_STANDARD, // 艱 + 0x8277, KANJI_STANDARD, // 艷 + 0x8278, KANJI_STANDARD, // 艞 + 0x827E, KANJI_STANDARD, // 艟 + 0x828D, KANJI_STANDARD, // 芍 + 0x8292, KANJI_STANDARD, // 芒 + 0x82AB, KANJI_STANDARD, // 芫 + 0x829F, KANJI_STANDARD, // 芟 + 0x82BB, KANJI_STANDARD, // 芻 + 0x82AC, KANJI_STANDARD, // 芬 + 0x82E1, KANJI_STANDARD, // 苡 + 0x82E3, KANJI_STANDARD, // 苣 + 0x82DF, KANJI_STANDARD, // 苟 + 0x82D2, KANJI_STANDARD, // 苒 + 0x82F4, KANJI_STANDARD, // 苎 + 0x82F3, KANJI_STANDARD, // 苳 + 0x82FA, KANJI_STANDARD, // 苺 + 0x8393, KANJI_STANDARD, // 莓 + 0x8303, KANJI_STANDARD, // 范 + 0x82FB, KANJI_STANDARD, // 苻 + 0x82F9, KANJI_STANDARD, // 苹 + 0x82DE, KANJI_STANDARD, // 苞 + 0x8306, KANJI_STANDARD, // 茆 + 0x82DC, KANJI_STANDARD, // 苜 + 0x8309, KANJI_STANDARD, // 茉 + 0x82D9, KANJI_STANDARD, // 苙 + 0x8335, KANJI_STANDARD, // 茵 + 0x8334, KANJI_STANDARD, // 茎 + 0x8316, KANJI_STANDARD, // 茖 + 0x8332, KANJI_STANDARD, // 茲 + 0x8331, KANJI_STANDARD, // 茱 + 0x8340, KANJI_STANDARD, // 荀 + 0x8339, KANJI_STANDARD, // 茹 + 0x8350, KANJI_STANDARD, // 荐 + 0x8345, KANJI_STANDARD, // 荅 + 0x832F, KANJI_STANDARD, // 茯 + 0x832B, KANJI_STANDARD, // 茫 + 0x8317, KANJI_STANDARD, // 茗 + 0x8318, KANJI_STANDARD, // 茘 + 0x8385, KANJI_STANDARD, // 莅 + 0x839A, KANJI_STANDARD, // 莚 + 0x83AA, KANJI_STANDARD, // 莪 + 0x839F, KANJI_STANDARD, // 莟 + 0x83A2, KANJI_STANDARD, // 莢 + 0x8396, KANJI_STANDARD, // 莖 + 0x8323, KANJI_STANDARD, // 茣 + 0x838E, KANJI_STANDARD, // 莎 + 0x8387, KANJI_STANDARD, // 莇 + 0x838A, KANJI_STANDARD, // 莊 + 0x837C, KANJI_STANDARD, // 荌 + 0x83B5, KANJI_STANDARD, // 莵 + 0x8373, KANJI_STANDARD, // 荳 + 0x8375, KANJI_STANDARD, // 荵 + 0x83A0, KANJI_STANDARD, // 莠 + 0x8389, KANJI_STANDARD, // 莉 + 0x83A8, KANJI_STANDARD, // 莚 + 0x83F4, KANJI_STANDARD, // 菎 + 0x8413, KANJI_STANDARD, // 萓 + 0x83EB, KANJI_STANDARD, // 菫 + 0x83CE, KANJI_STANDARD, // 菎 + 0x83FD, KANJI_STANDARD, // 菜 + 0x8403, KANJI_STANDARD, // 萃 + 0x83D8, KANJI_STANDARD, // 菘 + 0x840B, KANJI_STANDARD, // 萋 + 0x83C1, KANJI_STANDARD, // 菁 + 0x83F7, KANJI_STANDARD, // 菷 + 0x8407, KANJI_STANDARD, // 萇 + 0x83E0, KANJI_STANDARD, // 菠 + 0x83F2, KANJI_STANDARD, // 菲 + 0x840D, KANJI_STANDARD, // 萍 + 0x8422, KANJI_STANDARD, // 萢 + 0x8420, KANJI_STANDARD, // 萠 + 0x83BD, KANJI_STANDARD, // 莜 + 0x8438, KANJI_STANDARD, // 萞 + 0x8506, KANJI_STANDARD, // 蔆 + 0x83FB, KANJI_STANDARD, // 菻 + 0x846D, KANJI_STANDARD, // 葭 + 0x842A, KANJI_STANDARD, // 萪 + 0x843C, KANJI_STANDARD, // 萌 + 0x855A, KANJI_STANDARD, // 蕚 + 0x8484, KANJI_STANDARD, // 蒄 + 0x8477, KANJI_STANDARD, // 葷 + 0x846B, KANJI_STANDARD, // 葫 + 0x84AD, KANJI_STANDARD, // 蒭 + 0x846E, KANJI_STANDARD, // 葮 + 0x8482, KANJI_STANDARD, // 蒂 + 0x8469, KANJI_STANDARD, // 葩 + 0x8446, KANJI_STANDARD, // 葆 + 0x842C, KANJI_STANDARD, // 萬 + 0x846F, KANJI_STANDARD, // 葯 + 0x8479, KANJI_STANDARD, // 葹 + 0x8435, KANJI_STANDARD, // 萵 + 0x84CA, KANJI_STANDARD, // 蓊 + 0x8462, KANJI_STANDARD, // 葢 + 0x84B9, KANJI_STANDARD, // 蒹 + 0x84BF, KANJI_STANDARD, // 蒿 + 0x849F, KANJI_STANDARD, // 蒟 + 0x84D9, KANJI_STANDARD, // 蓙 + 0x84CD, KANJI_STANDARD, // 蓍 + 0x84BB, KANJI_STANDARD, // 蒻 + 0x84DA, KANJI_STANDARD, // 蓚 + 0x84D0, KANJI_STANDARD, // 蓐 + 0x84C1, KANJI_STANDARD, // 蓁 + 0x84C6, KANJI_STANDARD, // 蓆 + 0x84D6, KANJI_STANDARD, // 蓖 + 0x84A1, KANJI_STANDARD, // 蒡 + 0x8521, KANJI_STANDARD, // 蔡 + 0x84FF, KANJI_STANDARD, // 蓿 + 0x84F4, KANJI_STANDARD, // 蓎 + 0x8517, KANJI_STANDARD, // 蔗 + 0x8518, KANJI_STANDARD, // 蔘 + 0x852C, KANJI_STANDARD, // 蔬 + 0x851F, KANJI_STANDARD, // 蔟 + 0x8515, KANJI_STANDARD, // 蔕 + 0x8514, KANJI_STANDARD, // 蔔 + 0x84FC, KANJI_STANDARD, // 蓌 + 0x8540, KANJI_STANDARD, // 蕀 + 0x8563, KANJI_STANDARD, // 蕣 + 0x8558, KANJI_STANDARD, // 蕘 + 0x8548, KANJI_STANDARD, // 蕈 + 0x8541, KANJI_STANDARD, // 蕁 + 0x8602, KANJI_STANDARD, // 蘂 + 0x854B, KANJI_STANDARD, // 蕋 + 0x8555, KANJI_STANDARD, // 蕕 + 0x8580, KANJI_STANDARD, // 薀 + 0x85A4, KANJI_STANDARD, // è–€ + 0x8588, KANJI_STANDARD, // 薈 + 0x8591, KANJI_STANDARD, // 薑 + 0x858A, KANJI_STANDARD, // 薊 + 0x85A8, KANJI_STANDARD, // è–š + 0x856D, KANJI_STANDARD, // 蕭 + 0x8594, KANJI_STANDARD, // 薔 + 0x859B, KANJI_STANDARD, // 薛 + 0x85EA, KANJI_STANDARD, // 藪 + 0x8587, KANJI_STANDARD, // 薇 + 0x859C, KANJI_STANDARD, // 薜 + 0x8577, KANJI_STANDARD, // 蕷 + 0x857E, KANJI_STANDARD, // 蕟 + 0x8590, KANJI_STANDARD, // 薐 + 0x85C9, KANJI_STANDARD, // 藉 + 0x85BA, KANJI_STANDARD, // 薺 + 0x85CF, KANJI_STANDARD, // 藏 + 0x85B9, KANJI_STANDARD, // 薹 + 0x85D0, KANJI_STANDARD, // 藐 + 0x85D5, KANJI_STANDARD, // 藕 + 0x85DD, KANJI_STANDARD, // 藝 + 0x85E5, KANJI_STANDARD, // 藥 + 0x85DC, KANJI_STANDARD, // 藜 + 0x85F9, KANJI_STANDARD, // 藹 + 0x860A, KANJI_STANDARD, // 蘊 + 0x8613, KANJI_STANDARD, // 蘓 + 0x860B, KANJI_STANDARD, // 蘋 + 0x85FE, KANJI_STANDARD, // è—Ÿ + 0x85FA, KANJI_STANDARD, // 藺 + 0x8606, KANJI_STANDARD, // 蘆 + 0x8622, KANJI_STANDARD, // 蘢 + 0x861A, KANJI_STANDARD, // 蘚 + 0x8630, KANJI_STANDARD, // 蘰 + 0x863F, KANJI_STANDARD, // 蘿 + 0x864D, KANJI_STANDARD, // 虍 + 0x4E55, KANJI_STANDARD, // 乕 + 0x8654, KANJI_STANDARD, // 虔 + 0x865F, KANJI_STANDARD, // 號 + 0x8667, KANJI_STANDARD, // 虧 + 0x8671, KANJI_STANDARD, // 虱 + 0x8693, KANJI_STANDARD, // 蚓 + 0x86A3, KANJI_STANDARD, // 蚣 + 0x86A9, KANJI_STANDARD, // 蚩 + 0x86AA, KANJI_STANDARD, // 蚪 + 0x868B, KANJI_STANDARD, // 蚋 + 0x868C, KANJI_STANDARD, // 蚌 + 0x86B6, KANJI_STANDARD, // 蚶 + 0x86AF, KANJI_STANDARD, // 蚯 + 0x86C4, KANJI_STANDARD, // 蛄 + 0x86C6, KANJI_STANDARD, // 蛆 + 0x86B0, KANJI_STANDARD, // 蚰 + 0x86C9, KANJI_STANDARD, // 蛉 + 0x8823, KANJI_STANDARD, // è £ + 0x86AB, KANJI_STANDARD, // 蚫 + 0x86D4, KANJI_STANDARD, // 蛔 + 0x86DE, KANJI_STANDARD, // 蛞 + 0x86E9, KANJI_STANDARD, // 蛩 + 0x86EC, KANJI_STANDARD, // 蛬 + 0x86DF, KANJI_STANDARD, // 蛟 + 0x86DB, KANJI_STANDARD, // 蛛 + 0x86EF, KANJI_STANDARD, // 蛯 + 0x8712, KANJI_STANDARD, // 蜒 + 0x8706, KANJI_STANDARD, // 蜆 + 0x8708, KANJI_STANDARD, // 蜈 + 0x8700, KANJI_STANDARD, // 蜀 + 0x8703, KANJI_STANDARD, // 蜃 + 0x86FB, KANJI_STANDARD, // 蛻 + 0x8711, KANJI_STANDARD, // 蜑 + 0x8709, KANJI_STANDARD, // 蜉 + 0x870D, KANJI_STANDARD, // 蜍 + 0x86F9, KANJI_STANDARD, // 蛹 + 0x870A, KANJI_STANDARD, // 蜊 + 0x8734, KANJI_STANDARD, // 蜎 + 0x873F, KANJI_STANDARD, // 蜿 + 0x8737, KANJI_STANDARD, // 蜷 + 0x873B, KANJI_STANDARD, // 蜻 + 0x8725, KANJI_STANDARD, // 蜥 + 0x8729, KANJI_STANDARD, // 蜩 + 0x871A, KANJI_STANDARD, // 蜚 + 0x8760, KANJI_STANDARD, // 蝠 + 0x875F, KANJI_STANDARD, // 蝟 + 0x8778, KANJI_STANDARD, // 蝞 + 0x874C, KANJI_STANDARD, // 蝌 + 0x874E, KANJI_STANDARD, // 蝎 + 0x8774, KANJI_STANDARD, // 蝎 + 0x8757, KANJI_STANDARD, // 蝗 + 0x8768, KANJI_STANDARD, // 蝚 + 0x876E, KANJI_STANDARD, // 蝮 + 0x8759, KANJI_STANDARD, // 蝙 + 0x8753, KANJI_STANDARD, // 蝓 + 0x8763, KANJI_STANDARD, // 蝣 + 0x876A, KANJI_STANDARD, // 蝪 + 0x8805, KANJI_STANDARD, // 蠅 + 0x87A2, KANJI_STANDARD, // 螢 + 0x879F, KANJI_STANDARD, // 螟 + 0x8782, KANJI_STANDARD, // 螂 + 0x87AF, KANJI_STANDARD, // 螯 + 0x87CB, KANJI_STANDARD, // 蟋 + 0x87BD, KANJI_STANDARD, // 螜 + 0x87C0, KANJI_STANDARD, // 蟀 + 0x87D0, KANJI_STANDARD, // 蟐 + 0x96D6, KANJI_STANDARD, // 雖 + 0x87AB, KANJI_STANDARD, // 螫 + 0x87C4, KANJI_STANDARD, // 蟄 + 0x87B3, KANJI_STANDARD, // 螳 + 0x87C7, KANJI_STANDARD, // 蟇 + 0x87C6, KANJI_STANDARD, // 蟆 + 0x87BB, KANJI_STANDARD, // 螻 + 0x87EF, KANJI_STANDARD, // 蟯 + 0x87F2, KANJI_STANDARD, // 蟲 + 0x87E0, KANJI_STANDARD, // 蟠 + 0x880F, KANJI_STANDARD, // 蠏 + 0x880D, KANJI_STANDARD, // 蠍 + 0x87FE, KANJI_STANDARD, // 蟟 + 0x87F6, KANJI_STANDARD, // 蟶 + 0x87F7, KANJI_STANDARD, // 蟷 + 0x880E, KANJI_STANDARD, // 蠎 + 0x87D2, KANJI_STANDARD, // 蟒 + 0x8811, KANJI_STANDARD, // 蠑 + 0x8816, KANJI_STANDARD, // 蠖 + 0x8815, KANJI_STANDARD, // 蠕 + 0x8822, KANJI_STANDARD, // è ¢ + 0x8821, KANJI_STANDARD, // è ¡ + 0x8831, KANJI_STANDARD, // è ± + 0x8836, KANJI_STANDARD, // è ¶ + 0x8839, KANJI_STANDARD, // è ¹ + 0x8827, KANJI_STANDARD, // è § + 0x883B, KANJI_STANDARD, // è » + 0x8844, KANJI_STANDARD, // 衄 + 0x8842, KANJI_STANDARD, // 衂 + 0x8852, KANJI_STANDARD, // 衒 + 0x8859, KANJI_STANDARD, // 衙 + 0x885E, KANJI_STANDARD, // 衞 + 0x8862, KANJI_STANDARD, // è¡¢ + 0x886B, KANJI_STANDARD, // è¡« + 0x8881, KANJI_STANDARD, // 袁 + 0x887E, KANJI_STANDARD, // 衟 + 0x889E, KANJI_STANDARD, // 袞 + 0x8875, KANJI_STANDARD, // 衵 + 0x887D, KANJI_STANDARD, // 衜 + 0x88B5, KANJI_STANDARD, // 袵 + 0x8872, KANJI_STANDARD, // 衲 + 0x8882, KANJI_STANDARD, // 袂 + 0x8897, KANJI_STANDARD, // 袗 + 0x8892, KANJI_STANDARD, // 袒 + 0x88AE, KANJI_STANDARD, // 袮 + 0x8899, KANJI_STANDARD, // 袙 + 0x88A2, KANJI_STANDARD, // 袢 + 0x888D, KANJI_STANDARD, // 袍 + 0x88A4, KANJI_STANDARD, // 袀 + 0x88B0, KANJI_STANDARD, // 袰 + 0x88BF, KANJI_STANDARD, // 袿 + 0x88B1, KANJI_STANDARD, // 袱 + 0x88C3, KANJI_STANDARD, // 裃 + 0x88C4, KANJI_STANDARD, // 裄 + 0x88D4, KANJI_STANDARD, // 裔 + 0x88D8, KANJI_STANDARD, // 裘 + 0x88D9, KANJI_STANDARD, // 裙 + 0x88DD, KANJI_STANDARD, // 裝 + 0x88F9, KANJI_STANDARD, // 裹 + 0x8902, KANJI_STANDARD, // 耂 + 0x88FC, KANJI_STANDARD, // 裌 + 0x88F4, KANJI_STANDARD, // 裎 + 0x88E8, KANJI_STANDARD, // 裚 + 0x88F2, KANJI_STANDARD, // 裲 + 0x8904, KANJI_STANDARD, // 耄 + 0x890C, KANJI_STANDARD, // 而 + 0x890A, KANJI_STANDARD, // 耊 + 0x8913, KANJI_STANDARD, // 耓 + 0x8943, KANJI_STANDARD, // 襃 + 0x891E, KANJI_STANDARD, // 耞 + 0x8925, KANJI_STANDARD, // 耥 + 0x892A, KANJI_STANDARD, // 耪 + 0x892B, KANJI_STANDARD, // 耫 + 0x8941, KANJI_STANDARD, // 襁 + 0x8944, KANJI_STANDARD, // 襄 + 0x893B, KANJI_STANDARD, // 耻 + 0x8936, KANJI_STANDARD, // 耶 + 0x8938, KANJI_STANDARD, // 耞 + 0x894C, KANJI_STANDARD, // 襌 + 0x891D, KANJI_STANDARD, // 耝 + 0x8960, KANJI_STANDARD, // 襠 + 0x895E, KANJI_STANDARD, // 襞 + 0x8966, KANJI_STANDARD, // 襊 + 0x8964, KANJI_STANDARD, // 襀 + 0x896D, KANJI_STANDARD, // 襭 + 0x896A, KANJI_STANDARD, // 襪 + 0x896F, KANJI_STANDARD, // 襯 + 0x8974, KANJI_STANDARD, // 襎 + 0x8977, KANJI_STANDARD, // 襷 + 0x897E, KANJI_STANDARD, // 襟 + 0x8983, KANJI_STANDARD, // 芃 + 0x8988, KANJI_STANDARD, // 芈 + 0x898A, KANJI_STANDARD, // 芊 + 0x8993, KANJI_STANDARD, // 芓 + 0x8998, KANJI_STANDARD, // 芘 + 0x89A1, KANJI_STANDARD, // 芡 + 0x89A9, KANJI_STANDARD, // 芩 + 0x89A6, KANJI_STANDARD, // 芊 + 0x89AC, KANJI_STANDARD, // 芬 + 0x89AF, KANJI_STANDARD, // 芯 + 0x89B2, KANJI_STANDARD, // 芲 + 0x89BA, KANJI_STANDARD, // 芺 + 0x89BD, KANJI_STANDARD, // 芜 + 0x89BF, KANJI_STANDARD, // 芿 + 0x89C0, KANJI_STANDARD, // 觀 + 0x89DA, KANJI_STANDARD, // 觚 + 0x89DC, KANJI_STANDARD, // 觜 + 0x89DD, KANJI_STANDARD, // 觝 + 0x89E7, KANJI_STANDARD, // è§§ + 0x89F4, KANJI_STANDARD, // è§Ž + 0x89F8, KANJI_STANDARD, // è§ž + 0x8A03, KANJI_STANDARD, // 蚃 + 0x8A16, KANJI_STANDARD, // èš– + 0x8A10, KANJI_STANDARD, // 蚐 + 0x8A0C, KANJI_STANDARD, // 蚌 + 0x8A1B, KANJI_STANDARD, // èš› + 0x8A1D, KANJI_STANDARD, // 蚝 + 0x8A25, KANJI_STANDARD, // 蚥 + 0x8A36, KANJI_STANDARD, // èš¶ + 0x8A41, KANJI_STANDARD, // 詁 + 0x8A5B, KANJI_STANDARD, // 詛 + 0x8A52, KANJI_STANDARD, // 詒 + 0x8A46, KANJI_STANDARD, // 詆 + 0x8A48, KANJI_STANDARD, // 詈 + 0x8A7C, KANJI_STANDARD, // 詌 + 0x8A6D, KANJI_STANDARD, // è©­ + 0x8A6C, KANJI_STANDARD, // 詬 + 0x8A62, KANJI_STANDARD, // è©¢ + 0x8A85, KANJI_STANDARD, // 誅 + 0x8A82, KANJI_STANDARD, // 誂 + 0x8A84, KANJI_STANDARD, // 誄 + 0x8AA8, KANJI_STANDARD, // 誚 + 0x8AA1, KANJI_STANDARD, // 誡 + 0x8A91, KANJI_STANDARD, // 誑 + 0x8AA5, KANJI_STANDARD, // 誥 + 0x8AA6, KANJI_STANDARD, // 誊 + 0x8A9A, KANJI_STANDARD, // 誚 + 0x8AA3, KANJI_STANDARD, // 誣 + 0x8AC4, KANJI_STANDARD, // 諄 + 0x8ACD, KANJI_STANDARD, // 諍 + 0x8AC2, KANJI_STANDARD, // 諂 + 0x8ADA, KANJI_STANDARD, // 諚 + 0x8AEB, KANJI_STANDARD, // è«« + 0x8AF3, KANJI_STANDARD, // 諳 + 0x8AE7, KANJI_STANDARD, // è«§ + 0x8AE4, KANJI_STANDARD, // è«€ + 0x8AF1, KANJI_STANDARD, // 諱 + 0x8B14, KANJI_STANDARD, // 謔 + 0x8AE0, KANJI_STANDARD, // è«  + 0x8AE2, KANJI_STANDARD, // è«¢ + 0x8AF7, KANJI_STANDARD, // è«· + 0x8ADE, KANJI_STANDARD, // 諞 + 0x8ADB, KANJI_STANDARD, // 諛 + 0x8B0C, KANJI_STANDARD, // 謌 + 0x8B07, KANJI_STANDARD, // 謇 + 0x8B1A, KANJI_STANDARD, // 謚 + 0x8AE1, KANJI_STANDARD, // è«¡ + 0x8B16, KANJI_STANDARD, // 謖 + 0x8B10, KANJI_STANDARD, // 謐 + 0x8B17, KANJI_STANDARD, // 謗 + 0x8B20, KANJI_STANDARD, // 謠 + 0x8B33, KANJI_STANDARD, // 謳 + 0x97AB, KANJI_STANDARD, // 鞫 + 0x8B26, KANJI_STANDARD, // 謊 + 0x8B2B, KANJI_STANDARD, // 謫 + 0x8B3E, KANJI_STANDARD, // 謟 + 0x8B28, KANJI_STANDARD, // 謚 + 0x8B41, KANJI_STANDARD, // 譁 + 0x8B4C, KANJI_STANDARD, // 譌 + 0x8B4F, KANJI_STANDARD, // 譏 + 0x8B4E, KANJI_STANDARD, // 譎 + 0x8B49, KANJI_STANDARD, // 證 + 0x8B56, KANJI_STANDARD, // 譖 + 0x8B5B, KANJI_STANDARD, // 譛 + 0x8B5A, KANJI_STANDARD, // 譚 + 0x8B6B, KANJI_STANDARD, // è­« + 0x8B5F, KANJI_STANDARD, // 譟 + 0x8B6C, KANJI_STANDARD, // è­¬ + 0x8B6F, KANJI_STANDARD, // è­¯ + 0x8B74, KANJI_STANDARD, // è­Ž + 0x8B7D, KANJI_STANDARD, // è­œ + 0x8B80, KANJI_STANDARD, // 讀 + 0x8B8C, KANJI_STANDARD, // 讌 + 0x8B8E, KANJI_STANDARD, // 讎 + 0x8B92, KANJI_STANDARD, // 讒 + 0x8B93, KANJI_STANDARD, // 讓 + 0x8B96, KANJI_STANDARD, // 讖 + 0x8B99, KANJI_STANDARD, // 讙 + 0x8B9A, KANJI_STANDARD, // 讚 + 0x8C3A, KANJI_STANDARD, // è°º + 0x8C41, KANJI_STANDARD, // 豁 + 0x8C3F, KANJI_STANDARD, // è°¿ + 0x8C48, KANJI_STANDARD, // 豈 + 0x8C4C, KANJI_STANDARD, // 豌 + 0x8C4E, KANJI_STANDARD, // 豎 + 0x8C50, KANJI_STANDARD, // 豐 + 0x8C55, KANJI_STANDARD, // 豕 + 0x8C62, KANJI_STANDARD, // è±¢ + 0x8C6C, KANJI_STANDARD, // 豬 + 0x8C78, KANJI_STANDARD, // 豞 + 0x8C7A, KANJI_STANDARD, // 豺 + 0x8C82, KANJI_STANDARD, // 貂 + 0x8C89, KANJI_STANDARD, // 貉 + 0x8C85, KANJI_STANDARD, // 貅 + 0x8C8A, KANJI_STANDARD, // 貊 + 0x8C8D, KANJI_STANDARD, // 貍 + 0x8C8E, KANJI_STANDARD, // 貎 + 0x8C94, KANJI_STANDARD, // 貔 + 0x8C7C, KANJI_STANDARD, // 豌 + 0x8C98, KANJI_STANDARD, // 貘 + 0x621D, KANJI_STANDARD, // 戝 + 0x8CAD, KANJI_STANDARD, // è²­ + 0x8CAA, KANJI_STANDARD, // 貪 + 0x8CBD, KANJI_STANDARD, // 貜 + 0x8CB2, KANJI_STANDARD, // è²² + 0x8CB3, KANJI_STANDARD, // è²³ + 0x8CAE, KANJI_STANDARD, // è²® + 0x8CB6, KANJI_STANDARD, // è²¶ + 0x8CC8, KANJI_STANDARD, // 賈 + 0x8CC1, KANJI_STANDARD, // 賁 + 0x8CE4, KANJI_STANDARD, // è³€ + 0x8CE3, KANJI_STANDARD, // è³£ + 0x8CDA, KANJI_STANDARD, // 賚 + 0x8CFD, KANJI_STANDARD, // 賜 + 0x8CFA, KANJI_STANDARD, // 賺 + 0x8CFB, KANJI_STANDARD, // è³» + 0x8D04, KANJI_STANDARD, // 莄 + 0x8D05, KANJI_STANDARD, // 莅 + 0x8D0A, KANJI_STANDARD, // 莊 + 0x8D07, KANJI_STANDARD, // 莇 + 0x8D0F, KANJI_STANDARD, // 莏 + 0x8D0D, KANJI_STANDARD, // 莍 + 0x8D10, KANJI_STANDARD, // 莐 + 0x9F4E, KANJI_STANDARD, // 霎 + 0x8D13, KANJI_STANDARD, // 莓 + 0x8CCD, KANJI_STANDARD, // 賍 + 0x8D14, KANJI_STANDARD, // 莔 + 0x8D16, KANJI_STANDARD, // 莖 + 0x8D67, KANJI_STANDARD, // èµ§ + 0x8D6D, KANJI_STANDARD, // èµ­ + 0x8D71, KANJI_STANDARD, // èµ± + 0x8D73, KANJI_STANDARD, // èµ³ + 0x8D81, KANJI_STANDARD, // 趁 + 0x8D99, KANJI_STANDARD, // 趙 + 0x8DC2, KANJI_STANDARD, // 跂 + 0x8DBE, KANJI_STANDARD, // è¶Ÿ + 0x8DBA, KANJI_STANDARD, // 趺 + 0x8DCF, KANJI_STANDARD, // 跏 + 0x8DDA, KANJI_STANDARD, // 跚 + 0x8DD6, KANJI_STANDARD, // 跖 + 0x8DCC, KANJI_STANDARD, // 跌 + 0x8DDB, KANJI_STANDARD, // 跛 + 0x8DCB, KANJI_STANDARD, // 跋 + 0x8DEA, KANJI_STANDARD, // è·ª + 0x8DEB, KANJI_STANDARD, // è·« + 0x8DDF, KANJI_STANDARD, // 跟 + 0x8DE3, KANJI_STANDARD, // è·£ + 0x8DFC, KANJI_STANDARD, // è·Œ + 0x8E08, KANJI_STANDARD, // 螈 + 0x8E09, KANJI_STANDARD, // 螉 + 0x8DFF, KANJI_STANDARD, // è·¿ + 0x8E1D, KANJI_STANDARD, // 螝 + 0x8E1E, KANJI_STANDARD, // èžž + 0x8E10, KANJI_STANDARD, // 螐 + 0x8E1F, KANJI_STANDARD, // 螟 + 0x8E42, KANJI_STANDARD, // 蹂 + 0x8E35, KANJI_STANDARD, // èžµ + 0x8E30, KANJI_STANDARD, // èž° + 0x8E34, KANJI_STANDARD, // 螎 + 0x8E4A, KANJI_STANDARD, // 蹊 + 0x8E47, KANJI_STANDARD, // 蹇 + 0x8E49, KANJI_STANDARD, // 蹉 + 0x8E4C, KANJI_STANDARD, // 蹌 + 0x8E50, KANJI_STANDARD, // 蹐 + 0x8E48, KANJI_STANDARD, // 蹈 + 0x8E59, KANJI_STANDARD, // 蹙 + 0x8E64, KANJI_STANDARD, // è¹€ + 0x8E60, KANJI_STANDARD, // è¹  + 0x8E2A, KANJI_STANDARD, // 螪 + 0x8E63, KANJI_STANDARD, // è¹£ + 0x8E55, KANJI_STANDARD, // 蹕 + 0x8E76, KANJI_STANDARD, // è¹¶ + 0x8E72, KANJI_STANDARD, // è¹² + 0x8E7C, KANJI_STANDARD, // 蹌 + 0x8E81, KANJI_STANDARD, // 躁 + 0x8E87, KANJI_STANDARD, // 躇 + 0x8E85, KANJI_STANDARD, // 躅 + 0x8E84, KANJI_STANDARD, // 躄 + 0x8E8B, KANJI_STANDARD, // 躋 + 0x8E8A, KANJI_STANDARD, // 躊 + 0x8E93, KANJI_STANDARD, // 躓 + 0x8E91, KANJI_STANDARD, // 躑 + 0x8E94, KANJI_STANDARD, // 躔 + 0x8E99, KANJI_STANDARD, // 躙 + 0x8EAA, KANJI_STANDARD, // 躪 + 0x8EA1, KANJI_STANDARD, // 躡 + 0x8EAC, KANJI_STANDARD, // 躬 + 0x8EB0, KANJI_STANDARD, // 躰 + 0x8EC6, KANJI_STANDARD, // 軆 + 0x8EB1, KANJI_STANDARD, // 躱 + 0x8EBE, KANJI_STANDARD, // 躟 + 0x8EC5, KANJI_STANDARD, // 軅 + 0x8EC8, KANJI_STANDARD, // 軈 + 0x8ECB, KANJI_STANDARD, // 軋 + 0x8EDB, KANJI_STANDARD, // 軛 + 0x8EE3, KANJI_STANDARD, // 軣 + 0x8EFC, KANJI_STANDARD, // 軌 + 0x8EFB, KANJI_STANDARD, // è»» + 0x8EEB, KANJI_STANDARD, // 軫 + 0x8EFE, KANJI_STANDARD, // 軟 + 0x8F0A, KANJI_STANDARD, // 茊 + 0x8F05, KANJI_STANDARD, // 茅 + 0x8F15, KANJI_STANDARD, // 茕 + 0x8F12, KANJI_STANDARD, // 茒 + 0x8F19, KANJI_STANDARD, // 茙 + 0x8F13, KANJI_STANDARD, // 茓 + 0x8F1C, KANJI_STANDARD, // 茜 + 0x8F1F, KANJI_STANDARD, // 茟 + 0x8F1B, KANJI_STANDARD, // 茛 + 0x8F0C, KANJI_STANDARD, // 茌 + 0x8F26, KANJI_STANDARD, // 茊 + 0x8F33, KANJI_STANDARD, // 茳 + 0x8F3B, KANJI_STANDARD, // 茻 + 0x8F39, KANJI_STANDARD, // 茹 + 0x8F45, KANJI_STANDARD, // 蜅 + 0x8F42, KANJI_STANDARD, // 蜂 + 0x8F3E, KANJI_STANDARD, // 茟 + 0x8F4C, KANJI_STANDARD, // 蜌 + 0x8F49, KANJI_STANDARD, // 蜉 + 0x8F46, KANJI_STANDARD, // 蜆 + 0x8F4E, KANJI_STANDARD, // 蜎 + 0x8F57, KANJI_STANDARD, // 蜗 + 0x8F5C, KANJI_STANDARD, // 蜜 + 0x8F62, KANJI_STANDARD, // 蜢 + 0x8F63, KANJI_STANDARD, // 蜣 + 0x8F64, KANJI_STANDARD, // 蜀 + 0x8F9C, KANJI_STANDARD, // 蟜 + 0x8F9F, KANJI_STANDARD, // 蟟 + 0x8FA3, KANJI_STANDARD, // 蟣 + 0x8FAD, KANJI_STANDARD, // 蟭 + 0x8FAF, KANJI_STANDARD, // 蟯 + 0x8FB7, KANJI_STANDARD, // 蟷 + 0x8FDA, KANJI_STANDARD, // 迚 + 0x8FE5, KANJI_STANDARD, // è¿¥ + 0x8FE2, KANJI_STANDARD, // è¿¢ + 0x8FEA, KANJI_STANDARD, // 迪 + 0x8FEF, KANJI_STANDARD, // 迯 + 0x9087, KANJI_STANDARD, // 邇 + 0x8FF4, KANJI_STANDARD, // 迎 + 0x9005, KANJI_STANDARD, // 逅 + 0x8FF9, KANJI_STANDARD, // 迹 + 0x8FFA, KANJI_STANDARD, // 迺 + 0x9011, KANJI_STANDARD, // 逑 + 0x9015, KANJI_STANDARD, // 逕 + 0x9021, KANJI_STANDARD, // 逡 + 0x900D, KANJI_STANDARD, // 逍 + 0x901E, KANJI_STANDARD, // 逞 + 0x9016, KANJI_STANDARD, // 逖 + 0x900B, KANJI_STANDARD, // 逋 + 0x9027, KANJI_STANDARD, // 逧 + 0x9036, KANJI_STANDARD, // 逶 + 0x9035, KANJI_STANDARD, // 逵 + 0x9039, KANJI_STANDARD, // 逹 + 0x8FF8, KANJI_STANDARD, // 连 + 0x904F, KANJI_STANDARD, // 遏 + 0x9050, KANJI_STANDARD, // 遐 + 0x9051, KANJI_STANDARD, // 遑 + 0x9052, KANJI_STANDARD, // 遒 + 0x900E, KANJI_STANDARD, // 逎 + 0x9049, KANJI_STANDARD, // 遉 + 0x903E, KANJI_STANDARD, // 速 + 0x9056, KANJI_STANDARD, // 遖 + 0x9058, KANJI_STANDARD, // 遘 + 0x905E, KANJI_STANDARD, // 遞 + 0x9068, KANJI_STANDARD, // 遚 + 0x906F, KANJI_STANDARD, // 遯 + 0x9076, KANJI_STANDARD, // 遶 + 0x96A8, KANJI_STANDARD, // 隹 + 0x9072, KANJI_STANDARD, // 遲 + 0x9082, KANJI_STANDARD, // 邂 + 0x907D, KANJI_STANDARD, // 遜 + 0x9081, KANJI_STANDARD, // 邁 + 0x9080, KANJI_STANDARD, // 邀 + 0x908A, KANJI_STANDARD, // 邊 + 0x9089, KANJI_STANDARD, // 邉 + 0x908F, KANJI_STANDARD, // 邏 + 0x90A8, KANJI_STANDARD, // 邹 + 0x90AF, KANJI_STANDARD, // 邯 + 0x90B1, KANJI_STANDARD, // 邱 + 0x90B5, KANJI_STANDARD, // 邵 + 0x90E2, KANJI_STANDARD, // 郢 + 0x90E4, KANJI_STANDARD, // 郀 + 0x6248, KANJI_STANDARD, // 扈 + 0x90DB, KANJI_STANDARD, // 郛 + 0x9102, KANJI_STANDARD, // 鄂 + 0x9112, KANJI_STANDARD, // 鄒 + 0x9119, KANJI_STANDARD, // 鄙 + 0x9132, KANJI_STANDARD, // 鄲 + 0x9130, KANJI_STANDARD, // 鄰 + 0x914A, KANJI_STANDARD, // 酊 + 0x9156, KANJI_STANDARD, // 酖 + 0x9158, KANJI_STANDARD, // 酘 + 0x9163, KANJI_STANDARD, // 酣 + 0x9165, KANJI_STANDARD, // 酥 + 0x9169, KANJI_STANDARD, // 酩 + 0x9173, KANJI_STANDARD, // 酳 + 0x9172, KANJI_STANDARD, // 酲 + 0x918B, KANJI_STANDARD, // 醋 + 0x9189, KANJI_STANDARD, // 醉 + 0x9182, KANJI_STANDARD, // 醂 + 0x91A2, KANJI_STANDARD, // 醢 + 0x91AB, KANJI_STANDARD, // 醫 + 0x91AF, KANJI_STANDARD, // 醯 + 0x91AA, KANJI_STANDARD, // 醪 + 0x91B5, KANJI_STANDARD, // 醵 + 0x91B4, KANJI_STANDARD, // 醮 + 0x91BA, KANJI_STANDARD, // 醺 + 0x91C0, KANJI_STANDARD, // 釀 + 0x91C1, KANJI_STANDARD, // 釁 + 0x91C9, KANJI_STANDARD, // 釉 + 0x91CB, KANJI_STANDARD, // 釋 + 0x91D0, KANJI_STANDARD, // 釐 + 0x91D6, KANJI_STANDARD, // 釖 + 0x91DF, KANJI_STANDARD, // 釟 + 0x91E1, KANJI_STANDARD, // 釡 + 0x91DB, KANJI_STANDARD, // 釛 + 0x91FC, KANJI_STANDARD, // 里 + 0x91F5, KANJI_STANDARD, // 釵 + 0x91F6, KANJI_STANDARD, // 釶 + 0x921E, KANJI_STANDARD, // 鈞 + 0x91FF, KANJI_STANDARD, // 釿 + 0x9214, KANJI_STANDARD, // 鈔 + 0x922C, KANJI_STANDARD, // 鈬 + 0x9215, KANJI_STANDARD, // 鈕 + 0x9211, KANJI_STANDARD, // 鈑 + 0x925E, KANJI_STANDARD, // 鉞 + 0x9257, KANJI_STANDARD, // 鉗 + 0x9245, KANJI_STANDARD, // 鉅 + 0x9249, KANJI_STANDARD, // 鉉 + 0x9264, KANJI_STANDARD, // 鉀 + 0x9248, KANJI_STANDARD, // 鉈 + 0x9295, KANJI_STANDARD, // 銕 + 0x923F, KANJI_STANDARD, // 鈿 + 0x924B, KANJI_STANDARD, // 鉋 + 0x9250, KANJI_STANDARD, // 鉐 + 0x929C, KANJI_STANDARD, // 銜 + 0x9296, KANJI_STANDARD, // 銖 + 0x9293, KANJI_STANDARD, // 銓 + 0x929B, KANJI_STANDARD, // 銛 + 0x925A, KANJI_STANDARD, // 鉚 + 0x92CF, KANJI_STANDARD, // 鋏 + 0x92B9, KANJI_STANDARD, // 銹 + 0x92B7, KANJI_STANDARD, // 銷 + 0x92E9, KANJI_STANDARD, // 鋩 + 0x930F, KANJI_STANDARD, // 錏 + 0x92FA, KANJI_STANDARD, // 鋺 + 0x9344, KANJI_STANDARD, // 鍄 + 0x932E, KANJI_STANDARD, // 錮 + 0x9319, KANJI_STANDARD, // 錙 + 0x9322, KANJI_STANDARD, // 錢 + 0x931A, KANJI_STANDARD, // 錚 + 0x9323, KANJI_STANDARD, // 錣 + 0x933A, KANJI_STANDARD, // 錺 + 0x9335, KANJI_STANDARD, // 錵 + 0x933B, KANJI_STANDARD, // 錻 + 0x935C, KANJI_STANDARD, // 鍜 + 0x9360, KANJI_STANDARD, // 鍠 + 0x937C, KANJI_STANDARD, // 鍌 + 0x936E, KANJI_STANDARD, // 鍮 + 0x9356, KANJI_STANDARD, // 鍖 + 0x93B0, KANJI_STANDARD, // 鎰 + 0x93AC, KANJI_STANDARD, // 鎬 + 0x93AD, KANJI_STANDARD, // 鎭 + 0x9394, KANJI_STANDARD, // 鎔 + 0x93B9, KANJI_STANDARD, // 鎹 + 0x93D6, KANJI_STANDARD, // 鏖 + 0x93D7, KANJI_STANDARD, // 鏗 + 0x93E8, KANJI_STANDARD, // 鏚 + 0x93E5, KANJI_STANDARD, // 鏥 + 0x93D8, KANJI_STANDARD, // 鏘 + 0x93C3, KANJI_STANDARD, // 鏃 + 0x93DD, KANJI_STANDARD, // 鏝 + 0x93D0, KANJI_STANDARD, // 鏐 + 0x93C8, KANJI_STANDARD, // 鏈 + 0x93E4, KANJI_STANDARD, // 鏀 + 0x941A, KANJI_STANDARD, // 鐚 + 0x9414, KANJI_STANDARD, // 鐔 + 0x9413, KANJI_STANDARD, // 鐓 + 0x9403, KANJI_STANDARD, // 鐃 + 0x9407, KANJI_STANDARD, // 鐇 + 0x9410, KANJI_STANDARD, // 鐐 + 0x9436, KANJI_STANDARD, // 鐶 + 0x942B, KANJI_STANDARD, // 鐫 + 0x9435, KANJI_STANDARD, // 鐵 + 0x9421, KANJI_STANDARD, // 鐡 + 0x943A, KANJI_STANDARD, // 鐺 + 0x9441, KANJI_STANDARD, // 鑁 + 0x9452, KANJI_STANDARD, // 鑒 + 0x9444, KANJI_STANDARD, // 鑄 + 0x945B, KANJI_STANDARD, // 鑛 + 0x9460, KANJI_STANDARD, // 鑠 + 0x9462, KANJI_STANDARD, // 鑢 + 0x945E, KANJI_STANDARD, // 鑞 + 0x946A, KANJI_STANDARD, // 鑪 + 0x9229, KANJI_STANDARD, // 鈩 + 0x9470, KANJI_STANDARD, // 鑰 + 0x9475, KANJI_STANDARD, // 鑵 + 0x9477, KANJI_STANDARD, // 鑷 + 0x947D, KANJI_STANDARD, // 鑜 + 0x945A, KANJI_STANDARD, // 鑚 + 0x947C, KANJI_STANDARD, // 鑌 + 0x947E, KANJI_STANDARD, // 鑟 + 0x9481, KANJI_STANDARD, // 钁 + 0x947F, KANJI_STANDARD, // 鑿 + 0x9582, KANJI_STANDARD, // 閂 + 0x9587, KANJI_STANDARD, // 閇 + 0x958A, KANJI_STANDARD, // 閊 + 0x9594, KANJI_STANDARD, // 閔 + 0x9596, KANJI_STANDARD, // 閖 + 0x9598, KANJI_STANDARD, // 閘 + 0x9599, KANJI_STANDARD, // 閙 + 0x95A0, KANJI_STANDARD, // 閠 + 0x95A8, KANJI_STANDARD, // 閹 + 0x95A7, KANJI_STANDARD, // 閧 + 0x95AD, KANJI_STANDARD, // 閭 + 0x95BC, KANJI_STANDARD, // é–Œ + 0x95BB, KANJI_STANDARD, // 閻 + 0x95B9, KANJI_STANDARD, // 閹 + 0x95BE, KANJI_STANDARD, // é–Ÿ + 0x95CA, KANJI_STANDARD, // 闊 + 0x6FF6, KANJI_STANDARD, // æ¿¶ + 0x95C3, KANJI_STANDARD, // 闃 + 0x95CD, KANJI_STANDARD, // 闍 + 0x95CC, KANJI_STANDARD, // 闌 + 0x95D5, KANJI_STANDARD, // 闕 + 0x95D4, KANJI_STANDARD, // 闔 + 0x95D6, KANJI_STANDARD, // 闖 + 0x95DC, KANJI_STANDARD, // 關 + 0x95E1, KANJI_STANDARD, // 闡 + 0x95E5, KANJI_STANDARD, // 闥 + 0x95E2, KANJI_STANDARD, // 闢 + 0x9621, KANJI_STANDARD, // 阡 + 0x9628, KANJI_STANDARD, // 阚 + 0x962E, KANJI_STANDARD, // 阮 + 0x962F, KANJI_STANDARD, // 阯 + 0x9642, KANJI_STANDARD, // 陂 + 0x964C, KANJI_STANDARD, // 陌 + 0x964F, KANJI_STANDARD, // 陏 + 0x964B, KANJI_STANDARD, // 陋 + 0x9677, KANJI_STANDARD, // 陷 + 0x965C, KANJI_STANDARD, // 陜 + 0x965E, KANJI_STANDARD, // 陞 + 0x965D, KANJI_STANDARD, // 陝 + 0x965F, KANJI_STANDARD, // 陟 + 0x9666, KANJI_STANDARD, // 险 + 0x9672, KANJI_STANDARD, // 陲 + 0x966C, KANJI_STANDARD, // 陬 + 0x968D, KANJI_STANDARD, // 隍 + 0x9698, KANJI_STANDARD, // 隘 + 0x9695, KANJI_STANDARD, // 隕 + 0x9697, KANJI_STANDARD, // 隗 + 0x96AA, KANJI_STANDARD, // 險 + 0x96A7, KANJI_STANDARD, // 隧 + 0x96B1, KANJI_STANDARD, // 隱 + 0x96B2, KANJI_STANDARD, // 隲 + 0x96B0, KANJI_STANDARD, // 隰 + 0x96B4, KANJI_STANDARD, // 隮 + 0x96B6, KANJI_STANDARD, // 隶 + 0x96B8, KANJI_STANDARD, // 难 + 0x96B9, KANJI_STANDARD, // 隹 + 0x96CE, KANJI_STANDARD, // 雎 + 0x96CB, KANJI_STANDARD, // 雋 + 0x96C9, KANJI_STANDARD, // 雉 + 0x96CD, KANJI_STANDARD, // 雍 + 0x894D, KANJI_STANDARD, // 襍 + 0x96DC, KANJI_STANDARD, // 雜 + 0x970D, KANJI_STANDARD, // 霍 + 0x96D5, KANJI_STANDARD, // 雕 + 0x96F9, KANJI_STANDARD, // 雹 + 0x9704, KANJI_STANDARD, // 霄 + 0x9706, KANJI_STANDARD, // 霆 + 0x9708, KANJI_STANDARD, // 霈 + 0x9713, KANJI_STANDARD, // 霓 + 0x970E, KANJI_STANDARD, // 霎 + 0x9711, KANJI_STANDARD, // 霑 + 0x970F, KANJI_STANDARD, // 霏 + 0x9716, KANJI_STANDARD, // 霖 + 0x9719, KANJI_STANDARD, // 霙 + 0x9724, KANJI_STANDARD, // 需 + 0x972A, KANJI_STANDARD, // 霪 + 0x9730, KANJI_STANDARD, // 霰 + 0x9739, KANJI_STANDARD, // 霹 + 0x973D, KANJI_STANDARD, // 霜 + 0x973E, KANJI_STANDARD, // 霟 + 0x9744, KANJI_STANDARD, // 靄 + 0x9746, KANJI_STANDARD, // 靆 + 0x9748, KANJI_STANDARD, // 靈 + 0x9742, KANJI_STANDARD, // 靂 + 0x9749, KANJI_STANDARD, // 靉 + 0x975C, KANJI_STANDARD, // 靜 + 0x9760, KANJI_STANDARD, // 靠 + 0x9764, KANJI_STANDARD, // 靀 + 0x9766, KANJI_STANDARD, // 靊 + 0x9768, KANJI_STANDARD, // 靚 + 0x52D2, KANJI_STANDARD, // 勒 + 0x976B, KANJI_STANDARD, // 靫 + 0x9771, KANJI_STANDARD, // 靱 + 0x9779, KANJI_STANDARD, // 靹 + 0x9785, KANJI_STANDARD, // 鞅 + 0x977C, KANJI_STANDARD, // 靌 + 0x9781, KANJI_STANDARD, // 鞁 + 0x977A, KANJI_STANDARD, // 靺 + 0x9786, KANJI_STANDARD, // 鞆 + 0x978B, KANJI_STANDARD, // 鞋 + 0x978F, KANJI_STANDARD, // 鞏 + 0x9790, KANJI_STANDARD, // 鞐 + 0x979C, KANJI_STANDARD, // 鞜 + 0x97A8, KANJI_STANDARD, // 鞚 + 0x97A6, KANJI_STANDARD, // 鞊 + 0x97A3, KANJI_STANDARD, // 鞣 + 0x97B3, KANJI_STANDARD, // 鞳 + 0x97B4, KANJI_STANDARD, // 鞮 + 0x97C3, KANJI_STANDARD, // 韃 + 0x97C6, KANJI_STANDARD, // 韆 + 0x97C8, KANJI_STANDARD, // 韈 + 0x97CB, KANJI_STANDARD, // 韋 + 0x97DC, KANJI_STANDARD, // 韜 + 0x97ED, KANJI_STANDARD, // 韭 + 0x9F4F, KANJI_STANDARD, // 霏 + 0x97F2, KANJI_STANDARD, // 韲 + 0x7ADF, KANJI_STANDARD, // 竟 + 0x97F6, KANJI_STANDARD, // 韶 + 0x97F5, KANJI_STANDARD, // 韵 + 0x980F, KANJI_STANDARD, // 頏 + 0x980C, KANJI_STANDARD, // 頌 + 0x9838, KANJI_STANDARD, // é ž + 0x9824, KANJI_STANDARD, // é € + 0x9821, KANJI_STANDARD, // é ¡ + 0x9837, KANJI_STANDARD, // é · + 0x983D, KANJI_STANDARD, // é œ + 0x9846, KANJI_STANDARD, // 顆 + 0x984F, KANJI_STANDARD, // 顏 + 0x984B, KANJI_STANDARD, // 顋 + 0x986B, KANJI_STANDARD, // é¡« + 0x986F, KANJI_STANDARD, // 顯 + 0x9870, KANJI_STANDARD, // é¡° + 0x9871, KANJI_STANDARD, // 顱 + 0x9874, KANJI_STANDARD, // 顎 + 0x9873, KANJI_STANDARD, // 顳 + 0x98AA, KANJI_STANDARD, // 颪 + 0x98AF, KANJI_STANDARD, // 颯 + 0x98B1, KANJI_STANDARD, // 颱 + 0x98B6, KANJI_STANDARD, // 颶 + 0x98C4, KANJI_STANDARD, // 飄 + 0x98C3, KANJI_STANDARD, // 飃 + 0x98C6, KANJI_STANDARD, // 飆 + 0x98E9, KANJI_STANDARD, // 飩 + 0x98EB, KANJI_STANDARD, // 飫 + 0x9903, KANJI_STANDARD, // 逃 + 0x9909, KANJI_STANDARD, // 选 + 0x9912, KANJI_STANDARD, // 递 + 0x9914, KANJI_STANDARD, // 途 + 0x9918, KANJI_STANDARD, // 逘 + 0x9921, KANJI_STANDARD, // 逡 + 0x991D, KANJI_STANDARD, // 逝 + 0x991E, KANJI_STANDARD, // 逞 + 0x9924, KANJI_STANDARD, // 退 + 0x9920, KANJI_STANDARD, // 造 + 0x992C, KANJI_STANDARD, // 逬 + 0x992E, KANJI_STANDARD, // 逮 + 0x993D, KANJI_STANDARD, // 逜 + 0x993E, KANJI_STANDARD, // 速 + 0x9942, KANJI_STANDARD, // 饂 + 0x9949, KANJI_STANDARD, // 饉 + 0x9945, KANJI_STANDARD, // 饅 + 0x9950, KANJI_STANDARD, // 饐 + 0x994B, KANJI_STANDARD, // 饋 + 0x9951, KANJI_STANDARD, // 饑 + 0x9952, KANJI_STANDARD, // 饒 + 0x994C, KANJI_STANDARD, // 饌 + 0x9955, KANJI_STANDARD, // 饕 + 0x9997, KANJI_STANDARD, // 驗 + 0x9998, KANJI_STANDARD, // 銘 + 0x99A5, KANJI_STANDARD, // 銥 + 0x99AD, KANJI_STANDARD, // 銭 + 0x99AE, KANJI_STANDARD, // 銮 + 0x99BC, KANJI_STANDARD, // 銌 + 0x99DF, KANJI_STANDARD, // 駟 + 0x99DB, KANJI_STANDARD, // 駛 + 0x99DD, KANJI_STANDARD, // 駝 + 0x99D8, KANJI_STANDARD, // 駘 + 0x99D1, KANJI_STANDARD, // 駑 + 0x99ED, KANJI_STANDARD, // é§­ + 0x99EE, KANJI_STANDARD, // é§® + 0x99F1, KANJI_STANDARD, // é§± + 0x99F2, KANJI_STANDARD, // é§² + 0x99FB, KANJI_STANDARD, // é§» + 0x99F8, KANJI_STANDARD, // é§ž + 0x9A01, KANJI_STANDARD, // 隁 + 0x9A0F, KANJI_STANDARD, // 随 + 0x9A05, KANJI_STANDARD, // 鹅 + 0x99E2, KANJI_STANDARD, // é§¢ + 0x9A19, KANJI_STANDARD, // 鹙 + 0x9A2B, KANJI_STANDARD, // éš« + 0x9A37, KANJI_STANDARD, // éš· + 0x9A45, KANJI_STANDARD, // 驅 + 0x9A42, KANJI_STANDARD, // 驂 + 0x9A40, KANJI_STANDARD, // 驀 + 0x9A43, KANJI_STANDARD, // 驃 + 0x9A3E, KANJI_STANDARD, // 隟 + 0x9A55, KANJI_STANDARD, // 驕 + 0x9A4D, KANJI_STANDARD, // 驍 + 0x9A5B, KANJI_STANDARD, // 驛 + 0x9A57, KANJI_STANDARD, // 驗 + 0x9A5F, KANJI_STANDARD, // 驟 + 0x9A62, KANJI_STANDARD, // é©¢ + 0x9A65, KANJI_STANDARD, // é©¥ + 0x9A64, KANJI_STANDARD, // é©€ + 0x9A69, KANJI_STANDARD, // é©© + 0x9A6B, KANJI_STANDARD, // é©« + 0x9A6A, KANJI_STANDARD, // 驪 + 0x9AAD, KANJI_STANDARD, // 骭 + 0x9AB0, KANJI_STANDARD, // 骰 + 0x9ABC, KANJI_STANDARD, // 验 + 0x9AC0, KANJI_STANDARD, // 髀 + 0x9ACF, KANJI_STANDARD, // 髏 + 0x9AD1, KANJI_STANDARD, // 髑 + 0x9AD3, KANJI_STANDARD, // 髓 + 0x9AD4, KANJI_STANDARD, // 體 + 0x9ADE, KANJI_STANDARD, // 髞 + 0x9ADF, KANJI_STANDARD, // 髟 + 0x9AE2, KANJI_STANDARD, // é«¢ + 0x9AE3, KANJI_STANDARD, // é«£ + 0x9AE6, KANJI_STANDARD, // 髊 + 0x9AEF, KANJI_STANDARD, // 髯 + 0x9AEB, KANJI_STANDARD, // é«« + 0x9AEE, KANJI_STANDARD, // é«® + 0x9AF4, KANJI_STANDARD, // 髎 + 0x9AF1, KANJI_STANDARD, // 髱 + 0x9AF7, KANJI_STANDARD, // é«· + 0x9AFB, KANJI_STANDARD, // é«» + 0x9B06, KANJI_STANDARD, // 鬆 + 0x9B18, KANJI_STANDARD, // 鬘 + 0x9B1A, KANJI_STANDARD, // 鬚 + 0x9B1F, KANJI_STANDARD, // 鬟 + 0x9B22, KANJI_STANDARD, // 鬢 + 0x9B23, KANJI_STANDARD, // 鬣 + 0x9B25, KANJI_STANDARD, // 鬥 + 0x9B27, KANJI_STANDARD, // 鬧 + 0x9B28, KANJI_STANDARD, // 鬚 + 0x9B29, KANJI_STANDARD, // 鬩 + 0x9B2A, KANJI_STANDARD, // 鬪 + 0x9B2E, KANJI_STANDARD, // 鬮 + 0x9B2F, KANJI_STANDARD, // 鬯 + 0x9B32, KANJI_STANDARD, // 鬲 + 0x9B44, KANJI_STANDARD, // 魄 + 0x9B43, KANJI_STANDARD, // 魃 + 0x9B4F, KANJI_STANDARD, // 魏 + 0x9B4D, KANJI_STANDARD, // 魍 + 0x9B4E, KANJI_STANDARD, // 魎 + 0x9B51, KANJI_STANDARD, // 魑 + 0x9B58, KANJI_STANDARD, // 魘 + 0x9B74, KANJI_STANDARD, // é­Ž + 0x9B93, KANJI_STANDARD, // 鮓 + 0x9B83, KANJI_STANDARD, // 鮃 + 0x9B91, KANJI_STANDARD, // 鮑 + 0x9B96, KANJI_STANDARD, // 鮖 + 0x9B97, KANJI_STANDARD, // 鮗 + 0x9B9F, KANJI_STANDARD, // 鮟 + 0x9BA0, KANJI_STANDARD, // é®  + 0x9BA8, KANJI_STANDARD, // 鮚 + 0x9BB4, KANJI_STANDARD, // 鮎 + 0x9BC0, KANJI_STANDARD, // 鯀 + 0x9BCA, KANJI_STANDARD, // 鯊 + 0x9BB9, KANJI_STANDARD, // 鮹 + 0x9BC6, KANJI_STANDARD, // 鯆 + 0x9BCF, KANJI_STANDARD, // 鯏 + 0x9BD1, KANJI_STANDARD, // 鯑 + 0x9BD2, KANJI_STANDARD, // 鯒 + 0x9BE3, KANJI_STANDARD, // 鯣 + 0x9BE2, KANJI_STANDARD, // 鯢 + 0x9BE4, KANJI_STANDARD, // 鯀 + 0x9BD4, KANJI_STANDARD, // 鯔 + 0x9BE1, KANJI_STANDARD, // 鯡 + 0x9C3A, KANJI_STANDARD, // é°º + 0x9BF2, KANJI_STANDARD, // 鯲 + 0x9BF1, KANJI_STANDARD, // 鯱 + 0x9BF0, KANJI_STANDARD, // 鯰 + 0x9C15, KANJI_STANDARD, // 鰕 + 0x9C14, KANJI_STANDARD, // 鰔 + 0x9C09, KANJI_STANDARD, // 鰉 + 0x9C13, KANJI_STANDARD, // 鰓 + 0x9C0C, KANJI_STANDARD, // 鰌 + 0x9C06, KANJI_STANDARD, // 鰆 + 0x9C08, KANJI_STANDARD, // 鰈 + 0x9C12, KANJI_STANDARD, // 鰒 + 0x9C0A, KANJI_STANDARD, // 鰊 + 0x9C04, KANJI_STANDARD, // 鰄 + 0x9C2E, KANJI_STANDARD, // é°® + 0x9C1B, KANJI_STANDARD, // 鰛 + 0x9C25, KANJI_STANDARD, // é°¥ + 0x9C24, KANJI_STANDARD, // é°€ + 0x9C21, KANJI_STANDARD, // é°¡ + 0x9C30, KANJI_STANDARD, // é°° + 0x9C47, KANJI_STANDARD, // 鱇 + 0x9C32, KANJI_STANDARD, // é°² + 0x9C46, KANJI_STANDARD, // 鱆 + 0x9C3E, KANJI_STANDARD, // é°Ÿ + 0x9C5A, KANJI_STANDARD, // 鱚 + 0x9C60, KANJI_STANDARD, // é±  + 0x9C67, KANJI_STANDARD, // é±§ + 0x9C76, KANJI_STANDARD, // é±¶ + 0x9C78, KANJI_STANDARD, // 鱞 + 0x9CE7, KANJI_STANDARD, // é³§ + 0x9CEC, KANJI_STANDARD, // 鳬 + 0x9CF0, KANJI_STANDARD, // é³° + 0x9D09, KANJI_STANDARD, // 鮉 + 0x9D08, KANJI_STANDARD, // 鎈 + 0x9CEB, KANJI_STANDARD, // 鳫 + 0x9D03, KANJI_STANDARD, // 鎃 + 0x9D06, KANJI_STANDARD, // 鮆 + 0x9D2A, KANJI_STANDARD, // 鎪 + 0x9D26, KANJI_STANDARD, // 鎊 + 0x9DAF, KANJI_STANDARD, // 鶯 + 0x9D23, KANJI_STANDARD, // 鎣 + 0x9D1F, KANJI_STANDARD, // 鮟 + 0x9D44, KANJI_STANDARD, // 鵄 + 0x9D15, KANJI_STANDARD, // 鮕 + 0x9D12, KANJI_STANDARD, // 鮒 + 0x9D41, KANJI_STANDARD, // 鵁 + 0x9D3F, KANJI_STANDARD, // 鎿 + 0x9D3E, KANJI_STANDARD, // 鎟 + 0x9D46, KANJI_STANDARD, // 鵆 + 0x9D48, KANJI_STANDARD, // 鵈 + 0x9D5D, KANJI_STANDARD, // 鵝 + 0x9D5E, KANJI_STANDARD, // 鵞 + 0x9D64, KANJI_STANDARD, // éµ€ + 0x9D51, KANJI_STANDARD, // 鵑 + 0x9D50, KANJI_STANDARD, // 鵐 + 0x9D59, KANJI_STANDARD, // 鵙 + 0x9D72, KANJI_STANDARD, // éµ² + 0x9D89, KANJI_STANDARD, // 鶉 + 0x9D87, KANJI_STANDARD, // 鶇 + 0x9DAB, KANJI_STANDARD, // é¶« + 0x9D6F, KANJI_STANDARD, // 鵯 + 0x9D7A, KANJI_STANDARD, // 鵺 + 0x9D9A, KANJI_STANDARD, // 鶚 + 0x9DA4, KANJI_STANDARD, // é¶€ + 0x9DA9, KANJI_STANDARD, // é¶© + 0x9DB2, KANJI_STANDARD, // é¶² + 0x9DC4, KANJI_STANDARD, // 鷄 + 0x9DC1, KANJI_STANDARD, // 鷁 + 0x9DBB, KANJI_STANDARD, // é¶» + 0x9DB8, KANJI_STANDARD, // é¶ž + 0x9DBA, KANJI_STANDARD, // 鶺 + 0x9DC6, KANJI_STANDARD, // 鷆 + 0x9DCF, KANJI_STANDARD, // 鷏 + 0x9DC2, KANJI_STANDARD, // 鷂 + 0x9DD9, KANJI_STANDARD, // 鷙 + 0x9DD3, KANJI_STANDARD, // 鷓 + 0x9DF8, KANJI_STANDARD, // é·ž + 0x9DE6, KANJI_STANDARD, // é·Š + 0x9DED, KANJI_STANDARD, // é·­ + 0x9DEF, KANJI_STANDARD, // é·¯ + 0x9DFD, KANJI_STANDARD, // é·œ + 0x9E1A, KANJI_STANDARD, // 龚 + 0x9E1B, KANJI_STANDARD, // 龛 + 0x9E1E, KANJI_STANDARD, // 龞 + 0x9E75, KANJI_STANDARD, // é¹µ + 0x9E79, KANJI_STANDARD, // é¹¹ + 0x9E7D, KANJI_STANDARD, // 鹜 + 0x9E81, KANJI_STANDARD, // 麁 + 0x9E88, KANJI_STANDARD, // 麈 + 0x9E8B, KANJI_STANDARD, // 麋 + 0x9E8C, KANJI_STANDARD, // 麌 + 0x9E92, KANJI_STANDARD, // 麒 + 0x9E95, KANJI_STANDARD, // 麕 + 0x9E91, KANJI_STANDARD, // 麑 + 0x9E9D, KANJI_STANDARD, // 麝 + 0x9EA5, KANJI_STANDARD, // 麥 + 0x9EA9, KANJI_STANDARD, // 麩 + 0x9EB8, KANJI_STANDARD, // 麞 + 0x9EAA, KANJI_STANDARD, // 麪 + 0x9EAD, KANJI_STANDARD, // 麭 + 0x9761, KANJI_STANDARD, // 靡 + 0x9ECC, KANJI_STANDARD, // 黌 + 0x9ECE, KANJI_STANDARD, // 黎 + 0x9ECF, KANJI_STANDARD, // 黏 + 0x9ED0, KANJI_STANDARD, // 黐 + 0x9ED4, KANJI_STANDARD, // 黔 + 0x9EDC, KANJI_STANDARD, // 黜 + 0x9EDE, KANJI_STANDARD, // 點 + 0x9EDD, KANJI_STANDARD, // 黝 + 0x9EE0, KANJI_STANDARD, // é»  + 0x9EE5, KANJI_STANDARD, // 黥 + 0x9EE8, KANJI_STANDARD, // 黚 + 0x9EEF, KANJI_STANDARD, // 黯 + 0x9EF4, KANJI_STANDARD, // 黎 + 0x9EF6, KANJI_STANDARD, // é»¶ + 0x9EF7, KANJI_STANDARD, // é»· + 0x9EF9, KANJI_STANDARD, // 黹 + 0x9EFB, KANJI_STANDARD, // é»» + 0x9EFC, KANJI_STANDARD, // 黌 + 0x9EFD, KANJI_STANDARD, // 黜 + 0x9F07, KANJI_STANDARD, // 錇 + 0x9F08, KANJI_STANDARD, // 錈 + 0x76B7, KANJI_STANDARD, // 皷 + 0x9F15, KANJI_STANDARD, // 錕 + 0x9F21, KANJI_STANDARD, // 錡 + 0x9F2C, KANJI_STANDARD, // 錬 + 0x9F3E, KANJI_STANDARD, // 錟 + 0x9F4A, KANJI_STANDARD, // 霊 + 0x9F52, KANJI_STANDARD, // 霒 + 0x9F54, KANJI_STANDARD, // 霔 + 0x9F63, KANJI_STANDARD, // 霣 + 0x9F5F, KANJI_STANDARD, // 霟 + 0x9F60, KANJI_STANDARD, // 霠 + 0x9F61, KANJI_STANDARD, // 霡 + 0x9F66, KANJI_STANDARD, // 霊 + 0x9F67, KANJI_STANDARD, // 霧 + 0x9F6C, KANJI_STANDARD, // 霬 + 0x9F6A, KANJI_STANDARD, // 霪 + 0x9F77, KANJI_STANDARD, // 霷 + 0x9F72, KANJI_STANDARD, // 露 + 0x9F76, KANJI_STANDARD, // 霶 + 0x9F95, KANJI_STANDARD, // 韕 + 0x9F9C, KANJI_STANDARD, // 韜 + 0x9FA0, KANJI_STANDARD, // 韠 + 0x582F, KANJI_STANDARD, // å ¯ + 0x69C7, KANJI_STANDARD, // 槇 + 0x9059, KANJI_STANDARD, // 遙 + 0x7464, KANJI_STANDARD, // ç‘€ + 0x51DC, KANJI_STANDARD, // 凜 + 0x7199, KANJI_STANDARD, // 熙 + 0x4E02, KANJI_RARELY_USED, // 侂 + 0x4E04, KANJI_RARELY_USED, // 侄 + 0x4E05, KANJI_RARELY_USED, // 侅 + 0x4E0C, KANJI_RARELY_USED, // 侌 + 0x4E12, KANJI_RARELY_USED, // 侒 + 0x4E1F, KANJI_RARELY_USED, // 侟 + 0x4E23, KANJI_RARELY_USED, // 䞣 + 0x4E24, KANJI_RARELY_USED, // 䞀 + 0x4E28, KANJI_RARELY_USED, // äžš + 0x4E2B, KANJI_RARELY_USED, // äž« + 0x4E2E, KANJI_RARELY_USED, // äž® + 0x4E2F, KANJI_RARELY_USED, // 䞯 + 0x4E30, KANJI_RARELY_USED, // äž° + 0x4E35, KANJI_RARELY_USED, // äžµ + 0x4E40, KANJI_RARELY_USED, // 乀 + 0x4E41, KANJI_RARELY_USED, // 乁 + 0x4E44, KANJI_RARELY_USED, // 乄 + 0x4E47, KANJI_RARELY_USED, // 乇 + 0x4E51, KANJI_RARELY_USED, // 乑 + 0x4E5A, KANJI_RARELY_USED, // 乚 + 0x4E5C, KANJI_RARELY_USED, // 乜 + 0x4E63, KANJI_RARELY_USED, // ä¹£ + 0x4E68, KANJI_RARELY_USED, // 乚 + 0x4E69, KANJI_RARELY_USED, // 乩 + 0x4E74, KANJI_RARELY_USED, // 乎 + 0x4E75, KANJI_RARELY_USED, // ä¹µ + 0x4E79, KANJI_RARELY_USED, // ä¹¹ + 0x4E7F, KANJI_RARELY_USED, // 乿 + 0x4E8D, KANJI_RARELY_USED, // 亍 + 0x4E96, KANJI_RARELY_USED, // 亖 + 0x4E97, KANJI_RARELY_USED, // 亗 + 0x4E9D, KANJI_RARELY_USED, // 亝 + 0x4EAF, KANJI_RARELY_USED, // 亯 + 0x4EB9, KANJI_RARELY_USED, // 亹 + 0x4EC3, KANJI_RARELY_USED, // 仃 + 0x4ED0, KANJI_RARELY_USED, // 仐 + 0x4EDA, KANJI_RARELY_USED, // 仚 + 0x4EDB, KANJI_RARELY_USED, // 仛 + 0x4EE0, KANJI_RARELY_USED, // ä»  + 0x4EE1, KANJI_RARELY_USED, // 仡 + 0x4EE2, KANJI_RARELY_USED, // 仢 + 0x4EE8, KANJI_RARELY_USED, // 仚 + 0x4EEF, KANJI_RARELY_USED, // 仯 + 0x4EF1, KANJI_RARELY_USED, // ä»± + 0x4EF3, KANJI_RARELY_USED, // 仳 + 0x4EF5, KANJI_RARELY_USED, // 仵 + 0x4EFD, KANJI_RARELY_USED, // 仜 + 0x4EFE, KANJI_RARELY_USED, // 仟 + 0x4EFF, KANJI_RARELY_USED, // 仿 + 0x4F00, KANJI_RARELY_USED, // 䌀 + 0x4F02, KANJI_RARELY_USED, // 䌂 + 0x4F03, KANJI_RARELY_USED, // 䌃 + 0x4F08, KANJI_RARELY_USED, // 䌈 + 0x4F0B, KANJI_RARELY_USED, // 䌋 + 0x4F0C, KANJI_RARELY_USED, // 䌌 + 0x4F12, KANJI_RARELY_USED, // 䌒 + 0x4F15, KANJI_RARELY_USED, // 䌕 + 0x4F16, KANJI_RARELY_USED, // 䌖 + 0x4F17, KANJI_RARELY_USED, // 䌗 + 0x4F19, KANJI_RARELY_USED, // 䌙 + 0x4F2E, KANJI_RARELY_USED, // 䌮 + 0x4F31, KANJI_RARELY_USED, // 䌱 + 0x4F60, KANJI_RARELY_USED, // 䜠 + 0x4F33, KANJI_RARELY_USED, // 䌳 + 0x4F35, KANJI_RARELY_USED, // 䌵 + 0x4F37, KANJI_RARELY_USED, // 䌷 + 0x4F39, KANJI_RARELY_USED, // 䌹 + 0x4F3B, KANJI_RARELY_USED, // 䌻 + 0x4F3E, KANJI_RARELY_USED, // 䌟 + 0x4F40, KANJI_RARELY_USED, // 䜀 + 0x4F42, KANJI_RARELY_USED, // 䜂 + 0x4F48, KANJI_RARELY_USED, // 䜈 + 0x4F49, KANJI_RARELY_USED, // 䜉 + 0x4F4B, KANJI_RARELY_USED, // 䜋 + 0x4F4C, KANJI_RARELY_USED, // 䜌 + 0x4F52, KANJI_RARELY_USED, // 䜒 + 0x4F54, KANJI_RARELY_USED, // 䜔 + 0x4F56, KANJI_RARELY_USED, // 䜖 + 0x4F58, KANJI_RARELY_USED, // 䜘 + 0x4F5F, KANJI_RARELY_USED, // 䜟 + 0x4F63, KANJI_RARELY_USED, // 䜣 + 0x4F6A, KANJI_RARELY_USED, // 䜪 + 0x4F6C, KANJI_RARELY_USED, // 䜬 + 0x4F6E, KANJI_RARELY_USED, // 䜮 + 0x4F71, KANJI_RARELY_USED, // 䜱 + 0x4F77, KANJI_RARELY_USED, // 䜷 + 0x4F78, KANJI_RARELY_USED, // 䜞 + 0x4F79, KANJI_RARELY_USED, // 䜹 + 0x4F7A, KANJI_RARELY_USED, // 䜺 + 0x4F7D, KANJI_RARELY_USED, // 䜜 + 0x4F7E, KANJI_RARELY_USED, // 䜟 + 0x4F81, KANJI_RARELY_USED, // 䟁 + 0x4F82, KANJI_RARELY_USED, // 䟂 + 0x4F84, KANJI_RARELY_USED, // 䟄 + 0x4F85, KANJI_RARELY_USED, // 䟅 + 0x4F89, KANJI_RARELY_USED, // 䟉 + 0x4F8A, KANJI_RARELY_USED, // 䟊 + 0x4F8C, KANJI_RARELY_USED, // 䟌 + 0x4F8E, KANJI_RARELY_USED, // 䟎 + 0x4F90, KANJI_RARELY_USED, // 䟐 + 0x4F92, KANJI_RARELY_USED, // 䟒 + 0x4F93, KANJI_RARELY_USED, // 䟓 + 0x4F94, KANJI_RARELY_USED, // 䟔 + 0x4F97, KANJI_RARELY_USED, // 䟗 + 0x4F99, KANJI_RARELY_USED, // 䟙 + 0x4F9A, KANJI_RARELY_USED, // 䟚 + 0x4F9E, KANJI_RARELY_USED, // 䟞 + 0x4F9F, KANJI_RARELY_USED, // 䟟 + 0x4FB2, KANJI_RARELY_USED, // 䟲 + 0x4FB7, KANJI_RARELY_USED, // 䟷 + 0x4FB9, KANJI_RARELY_USED, // 䟹 + 0x4FBB, KANJI_RARELY_USED, // 䟻 + 0x4FBC, KANJI_RARELY_USED, // 䟌 + 0x4FBD, KANJI_RARELY_USED, // 䟜 + 0x4FBE, KANJI_RARELY_USED, // 䟟 + 0x4FC0, KANJI_RARELY_USED, // 俀 + 0x4FC1, KANJI_RARELY_USED, // 俁 + 0x4FC5, KANJI_RARELY_USED, // 俅 + 0x4FC6, KANJI_RARELY_USED, // 俆 + 0x4FC8, KANJI_RARELY_USED, // 俈 + 0x4FC9, KANJI_RARELY_USED, // 俉 + 0x4FCB, KANJI_RARELY_USED, // 俋 + 0x4FCC, KANJI_RARELY_USED, // 俌 + 0x4FCD, KANJI_RARELY_USED, // 俍 + 0x4FCF, KANJI_RARELY_USED, // 俏 + 0x4FD2, KANJI_RARELY_USED, // 俒 + 0x4FDC, KANJI_RARELY_USED, // 俜 + 0x4FE0, KANJI_RARELY_USED, // ä¿  + 0x4FE2, KANJI_RARELY_USED, // ä¿¢ + 0x4FF0, KANJI_RARELY_USED, // ä¿° + 0x4FF2, KANJI_RARELY_USED, // 俲 + 0x4FFC, KANJI_RARELY_USED, // 俌 + 0x4FFD, KANJI_RARELY_USED, // 俜 + 0x4FFF, KANJI_RARELY_USED, // ä¿¿ + 0x5000, KANJI_RARELY_USED, // 倀 + 0x5001, KANJI_RARELY_USED, // 倁 + 0x5004, KANJI_RARELY_USED, // 倄 + 0x5007, KANJI_RARELY_USED, // 倇 + 0x500A, KANJI_RARELY_USED, // 倊 + 0x500C, KANJI_RARELY_USED, // 倌 + 0x500E, KANJI_RARELY_USED, // 倎 + 0x5010, KANJI_RARELY_USED, // 倐 + 0x5013, KANJI_RARELY_USED, // 倓 + 0x5017, KANJI_RARELY_USED, // 倗 + 0x5018, KANJI_RARELY_USED, // 倘 + 0x501B, KANJI_RARELY_USED, // 倛 + 0x501C, KANJI_RARELY_USED, // 倜 + 0x501D, KANJI_RARELY_USED, // 倝 + 0x501E, KANJI_RARELY_USED, // 倞 + 0x5022, KANJI_RARELY_USED, // 倢 + 0x5027, KANJI_RARELY_USED, // 倧 + 0x502E, KANJI_RARELY_USED, // 倮 + 0x5030, KANJI_RARELY_USED, // 倰 + 0x5032, KANJI_RARELY_USED, // 倲 + 0x5033, KANJI_RARELY_USED, // 倳 + 0x5035, KANJI_RARELY_USED, // 倵 + 0x5040, KANJI_RARELY_USED, // 偀 + 0x5041, KANJI_RARELY_USED, // 偁 + 0x5042, KANJI_RARELY_USED, // 偂 + 0x5045, KANJI_RARELY_USED, // 偅 + 0x5046, KANJI_RARELY_USED, // 偆 + 0x504A, KANJI_RARELY_USED, // 偊 + 0x504C, KANJI_RARELY_USED, // 偌 + 0x504E, KANJI_RARELY_USED, // 偎 + 0x5051, KANJI_RARELY_USED, // 偑 + 0x5052, KANJI_RARELY_USED, // 偒 + 0x5053, KANJI_RARELY_USED, // 偓 + 0x5057, KANJI_RARELY_USED, // 偗 + 0x5059, KANJI_RARELY_USED, // 偙 + 0x505F, KANJI_RARELY_USED, // 偟 + 0x5060, KANJI_RARELY_USED, // 偠 + 0x5062, KANJI_RARELY_USED, // 偢 + 0x5063, KANJI_RARELY_USED, // 偣 + 0x5066, KANJI_RARELY_USED, // 偊 + 0x5067, KANJI_RARELY_USED, // 偧 + 0x506A, KANJI_RARELY_USED, // 偪 + 0x506D, KANJI_RARELY_USED, // 偭 + 0x5070, KANJI_RARELY_USED, // 偰 + 0x5071, KANJI_RARELY_USED, // 偱 + 0x503B, KANJI_RARELY_USED, // 倻 + 0x5081, KANJI_RARELY_USED, // 傁 + 0x5083, KANJI_RARELY_USED, // 傃 + 0x5084, KANJI_RARELY_USED, // 傄 + 0x5086, KANJI_RARELY_USED, // 傆 + 0x508A, KANJI_RARELY_USED, // 傊 + 0x508E, KANJI_RARELY_USED, // 傎 + 0x508F, KANJI_RARELY_USED, // 傏 + 0x5090, KANJI_RARELY_USED, // 傐 + 0x5092, KANJI_RARELY_USED, // 傒 + 0x5093, KANJI_RARELY_USED, // 傓 + 0x5094, KANJI_RARELY_USED, // 傔 + 0x5096, KANJI_RARELY_USED, // 傖 + 0x509B, KANJI_RARELY_USED, // 傛 + 0x509C, KANJI_RARELY_USED, // 傜 + 0x509E, KANJI_RARELY_USED, // 傞 + 0x509F, KANJI_RARELY_USED, // 傟 + 0x50A0, KANJI_RARELY_USED, // 傠 + 0x50A1, KANJI_RARELY_USED, // 傡 + 0x50A2, KANJI_RARELY_USED, // 傢 + 0x50AA, KANJI_RARELY_USED, // 傪 + 0x50AF, KANJI_RARELY_USED, // 傯 + 0x50B0, KANJI_RARELY_USED, // 傰 + 0x50B9, KANJI_RARELY_USED, // 傹 + 0x50BA, KANJI_RARELY_USED, // 傺 + 0x50BD, KANJI_RARELY_USED, // 傜 + 0x50C0, KANJI_RARELY_USED, // 僀 + 0x50C3, KANJI_RARELY_USED, // 僃 + 0x50C4, KANJI_RARELY_USED, // 僄 + 0x50C7, KANJI_RARELY_USED, // 僇 + 0x50CC, KANJI_RARELY_USED, // 僌 + 0x50CE, KANJI_RARELY_USED, // 僎 + 0x50D0, KANJI_RARELY_USED, // 僐 + 0x50D3, KANJI_RARELY_USED, // 僓 + 0x50D4, KANJI_RARELY_USED, // 僔 + 0x50D8, KANJI_RARELY_USED, // 僘 + 0x50DC, KANJI_RARELY_USED, // 僜 + 0x50DD, KANJI_RARELY_USED, // 僝 + 0x50DF, KANJI_RARELY_USED, // 僟 + 0x50E2, KANJI_RARELY_USED, // 僢 + 0x50E4, KANJI_RARELY_USED, // 僀 + 0x50E6, KANJI_RARELY_USED, // 僊 + 0x50E8, KANJI_RARELY_USED, // 僚 + 0x50E9, KANJI_RARELY_USED, // 僩 + 0x50EF, KANJI_RARELY_USED, // 僯 + 0x50F1, KANJI_RARELY_USED, // 僱 + 0x50F6, KANJI_RARELY_USED, // 僶 + 0x50FA, KANJI_RARELY_USED, // 僺 + 0x50FE, KANJI_RARELY_USED, // 僟 + 0x5103, KANJI_RARELY_USED, // 儃 + 0x5106, KANJI_RARELY_USED, // 儆 + 0x5107, KANJI_RARELY_USED, // 儇 + 0x5108, KANJI_RARELY_USED, // 儈 + 0x510B, KANJI_RARELY_USED, // 儋 + 0x510C, KANJI_RARELY_USED, // 儌 + 0x510D, KANJI_RARELY_USED, // 儍 + 0x510E, KANJI_RARELY_USED, // 儎 + 0x50F2, KANJI_RARELY_USED, // 僲 + 0x5110, KANJI_RARELY_USED, // 儐 + 0x5117, KANJI_RARELY_USED, // 儗 + 0x5119, KANJI_RARELY_USED, // 儙 + 0x511B, KANJI_RARELY_USED, // 儛 + 0x511C, KANJI_RARELY_USED, // 儜 + 0x511D, KANJI_RARELY_USED, // 儝 + 0x511E, KANJI_RARELY_USED, // 儞 + 0x5123, KANJI_RARELY_USED, // 儣 + 0x5127, KANJI_RARELY_USED, // 儧 + 0x5128, KANJI_RARELY_USED, // 儚 + 0x512C, KANJI_RARELY_USED, // 儬 + 0x512D, KANJI_RARELY_USED, // 儭 + 0x512F, KANJI_RARELY_USED, // 儯 + 0x5131, KANJI_RARELY_USED, // 儱 + 0x5133, KANJI_RARELY_USED, // 儳 + 0x5134, KANJI_RARELY_USED, // 儎 + 0x5135, KANJI_RARELY_USED, // 儵 + 0x5138, KANJI_RARELY_USED, // 儞 + 0x5139, KANJI_RARELY_USED, // 儹 + 0x5142, KANJI_RARELY_USED, // 兂 + 0x514A, KANJI_RARELY_USED, // 兊 + 0x514F, KANJI_RARELY_USED, // 兏 + 0x5153, KANJI_RARELY_USED, // 兓 + 0x5155, KANJI_RARELY_USED, // 兕 + 0x5157, KANJI_RARELY_USED, // 兗 + 0x5158, KANJI_RARELY_USED, // 兘 + 0x515F, KANJI_RARELY_USED, // 兟 + 0x5164, KANJI_RARELY_USED, // å…€ + 0x5166, KANJI_RARELY_USED, // å…Š + 0x517E, KANJI_RARELY_USED, // å…Ÿ + 0x5183, KANJI_RARELY_USED, // 冃 + 0x5184, KANJI_RARELY_USED, // 冄 + 0x518B, KANJI_RARELY_USED, // 冋 + 0x518E, KANJI_RARELY_USED, // 冎 + 0x5198, KANJI_RARELY_USED, // 冘 + 0x519D, KANJI_RARELY_USED, // 冝 + 0x51A1, KANJI_RARELY_USED, // 冡 + 0x51A3, KANJI_RARELY_USED, // 冣 + 0x51AD, KANJI_RARELY_USED, // 冭 + 0x51B8, KANJI_RARELY_USED, // 冞 + 0x51BA, KANJI_RARELY_USED, // 冺 + 0x51BC, KANJI_RARELY_USED, // 册 + 0x51BE, KANJI_RARELY_USED, // 冟 + 0x51BF, KANJI_RARELY_USED, // 冿 + 0x51C2, KANJI_RARELY_USED, // 凂 + 0x51C8, KANJI_RARELY_USED, // 凈 + 0x51CF, KANJI_RARELY_USED, // 减 + 0x51D1, KANJI_RARELY_USED, // 凑 + 0x51D2, KANJI_RARELY_USED, // 凒 + 0x51D3, KANJI_RARELY_USED, // 凓 + 0x51D5, KANJI_RARELY_USED, // 凕 + 0x51D8, KANJI_RARELY_USED, // 凘 + 0x51DE, KANJI_RARELY_USED, // 凞 + 0x51E2, KANJI_RARELY_USED, // 凢 + 0x51E5, KANJI_RARELY_USED, // 凥 + 0x51EE, KANJI_RARELY_USED, // 凮 + 0x51F2, KANJI_RARELY_USED, // 凲 + 0x51F3, KANJI_RARELY_USED, // 凳 + 0x51F4, KANJI_RARELY_USED, // 凎 + 0x51F7, KANJI_RARELY_USED, // 凷 + 0x5201, KANJI_RARELY_USED, // 刁 + 0x5202, KANJI_RARELY_USED, // 刂 + 0x5205, KANJI_RARELY_USED, // 刅 + 0x5212, KANJI_RARELY_USED, // 划 + 0x5213, KANJI_RARELY_USED, // 刓 + 0x5215, KANJI_RARELY_USED, // 刕 + 0x5216, KANJI_RARELY_USED, // 刖 + 0x5218, KANJI_RARELY_USED, // 刘 + 0x5222, KANJI_RARELY_USED, // 刢 + 0x5228, KANJI_RARELY_USED, // 刚 + 0x5231, KANJI_RARELY_USED, // 刱 + 0x5232, KANJI_RARELY_USED, // 刲 + 0x5235, KANJI_RARELY_USED, // 刵 + 0x523C, KANJI_RARELY_USED, // 刌 + 0x5245, KANJI_RARELY_USED, // 剅 + 0x5249, KANJI_RARELY_USED, // 剉 + 0x5255, KANJI_RARELY_USED, // 剕 + 0x5257, KANJI_RARELY_USED, // 剗 + 0x5258, KANJI_RARELY_USED, // 剘 + 0x525A, KANJI_RARELY_USED, // 剚 + 0x525C, KANJI_RARELY_USED, // 剜 + 0x525F, KANJI_RARELY_USED, // 剟 + 0x5260, KANJI_RARELY_USED, // 剠 + 0x5261, KANJI_RARELY_USED, // 剡 + 0x5266, KANJI_RARELY_USED, // 削 + 0x526E, KANJI_RARELY_USED, // 剮 + 0x5277, KANJI_RARELY_USED, // 剷 + 0x5278, KANJI_RARELY_USED, // 剞 + 0x5279, KANJI_RARELY_USED, // 剹 + 0x5280, KANJI_RARELY_USED, // 劀 + 0x5282, KANJI_RARELY_USED, // 劂 + 0x5285, KANJI_RARELY_USED, // 劅 + 0x528A, KANJI_RARELY_USED, // 劊 + 0x528C, KANJI_RARELY_USED, // 劌 + 0x5293, KANJI_RARELY_USED, // 劓 + 0x5295, KANJI_RARELY_USED, // 劕 + 0x5296, KANJI_RARELY_USED, // 劖 + 0x5297, KANJI_RARELY_USED, // 劗 + 0x5298, KANJI_RARELY_USED, // 劘 + 0x529A, KANJI_RARELY_USED, // 劚 + 0x529C, KANJI_RARELY_USED, // 劜 + 0x52A4, KANJI_RARELY_USED, // 劀 + 0x52A5, KANJI_RARELY_USED, // 劥 + 0x52A6, KANJI_RARELY_USED, // 劊 + 0x52A7, KANJI_RARELY_USED, // 劧 + 0x52AF, KANJI_RARELY_USED, // 劯 + 0x52B0, KANJI_RARELY_USED, // 劰 + 0x52B6, KANJI_RARELY_USED, // 劶 + 0x52B7, KANJI_RARELY_USED, // 劷 + 0x52B8, KANJI_RARELY_USED, // 办 + 0x52BA, KANJI_RARELY_USED, // 劺 + 0x52BB, KANJI_RARELY_USED, // 劻 + 0x52BD, KANJI_RARELY_USED, // 劜 + 0x52C0, KANJI_RARELY_USED, // 勀 + 0x52C4, KANJI_RARELY_USED, // 勄 + 0x52C6, KANJI_RARELY_USED, // 勆 + 0x52C8, KANJI_RARELY_USED, // 勈 + 0x52CC, KANJI_RARELY_USED, // 勌 + 0x52CF, KANJI_RARELY_USED, // 勏 + 0x52D1, KANJI_RARELY_USED, // 勑 + 0x52D4, KANJI_RARELY_USED, // 勔 + 0x52D6, KANJI_RARELY_USED, // 勖 + 0x52DB, KANJI_RARELY_USED, // 勛 + 0x52DC, KANJI_RARELY_USED, // 勜 + 0x52E1, KANJI_RARELY_USED, // 勡 + 0x52E5, KANJI_RARELY_USED, // 勥 + 0x52E8, KANJI_RARELY_USED, // 勚 + 0x52E9, KANJI_RARELY_USED, // 勩 + 0x52EA, KANJI_RARELY_USED, // 勪 + 0x52EC, KANJI_RARELY_USED, // 勬 + 0x52F0, KANJI_RARELY_USED, // 勰 + 0x52F1, KANJI_RARELY_USED, // 勱 + 0x52F4, KANJI_RARELY_USED, // 勎 + 0x52F6, KANJI_RARELY_USED, // 勶 + 0x52F7, KANJI_RARELY_USED, // 勷 + 0x5300, KANJI_RARELY_USED, // 匀 + 0x5303, KANJI_RARELY_USED, // 匃 + 0x530A, KANJI_RARELY_USED, // 匊 + 0x530B, KANJI_RARELY_USED, // 匋 + 0x530C, KANJI_RARELY_USED, // 匌 + 0x5311, KANJI_RARELY_USED, // 匑 + 0x5313, KANJI_RARELY_USED, // 匓 + 0x5318, KANJI_RARELY_USED, // 匘 + 0x531B, KANJI_RARELY_USED, // 匛 + 0x531C, KANJI_RARELY_USED, // 匜 + 0x531E, KANJI_RARELY_USED, // 匞 + 0x531F, KANJI_RARELY_USED, // 匟 + 0x5325, KANJI_RARELY_USED, // 匥 + 0x5327, KANJI_RARELY_USED, // 匧 + 0x5328, KANJI_RARELY_USED, // 匚 + 0x5329, KANJI_RARELY_USED, // 匩 + 0x532B, KANJI_RARELY_USED, // 匫 + 0x532C, KANJI_RARELY_USED, // 匬 + 0x532D, KANJI_RARELY_USED, // 匭 + 0x5330, KANJI_RARELY_USED, // 匰 + 0x5332, KANJI_RARELY_USED, // 匲 + 0x5335, KANJI_RARELY_USED, // 匵 + 0x533C, KANJI_RARELY_USED, // 匌 + 0x533D, KANJI_RARELY_USED, // 匜 + 0x533E, KANJI_RARELY_USED, // 匟 + 0x5342, KANJI_RARELY_USED, // 卂 + 0x534C, KANJI_RARELY_USED, // 卌 + 0x534B, KANJI_RARELY_USED, // 卋 + 0x5359, KANJI_RARELY_USED, // 卙 + 0x535B, KANJI_RARELY_USED, // 卛 + 0x5361, KANJI_RARELY_USED, // 卡 + 0x5363, KANJI_RARELY_USED, // 卣 + 0x5365, KANJI_RARELY_USED, // 卥 + 0x536C, KANJI_RARELY_USED, // 卬 + 0x536D, KANJI_RARELY_USED, // 卭 + 0x5372, KANJI_RARELY_USED, // 卲 + 0x5379, KANJI_RARELY_USED, // 卹 + 0x537E, KANJI_RARELY_USED, // 卟 + 0x5383, KANJI_RARELY_USED, // 厃 + 0x5387, KANJI_RARELY_USED, // 厇 + 0x5388, KANJI_RARELY_USED, // 厈 + 0x538E, KANJI_RARELY_USED, // 厎 + 0x5393, KANJI_RARELY_USED, // 厓 + 0x5394, KANJI_RARELY_USED, // 厔 + 0x5399, KANJI_RARELY_USED, // 厙 + 0x539D, KANJI_RARELY_USED, // 厝 + 0x53A1, KANJI_RARELY_USED, // 厡 + 0x53A4, KANJI_RARELY_USED, // 厀 + 0x53AA, KANJI_RARELY_USED, // 厪 + 0x53AB, KANJI_RARELY_USED, // 厫 + 0x53AF, KANJI_RARELY_USED, // 厯 + 0x53B2, KANJI_RARELY_USED, // 厲 + 0x53B4, KANJI_RARELY_USED, // 厎 + 0x53B5, KANJI_RARELY_USED, // 厵 + 0x53B7, KANJI_RARELY_USED, // 厷 + 0x53B8, KANJI_RARELY_USED, // 厞 + 0x53BA, KANJI_RARELY_USED, // 厺 + 0x53BD, KANJI_RARELY_USED, // 厜 + 0x53C0, KANJI_RARELY_USED, // 叀 + 0x53C5, KANJI_RARELY_USED, // 叅 + 0x53CF, KANJI_RARELY_USED, // 叏 + 0x53D2, KANJI_RARELY_USED, // 叒 + 0x53D3, KANJI_RARELY_USED, // 叓 + 0x53D5, KANJI_RARELY_USED, // 叕 + 0x53DA, KANJI_RARELY_USED, // 叚 + 0x53DD, KANJI_RARELY_USED, // 叝 + 0x53DE, KANJI_RARELY_USED, // 叞 + 0x53E0, KANJI_RARELY_USED, // 叠 + 0x53E6, KANJI_RARELY_USED, // 及 + 0x53E7, KANJI_RARELY_USED, // 叧 + 0x53F5, KANJI_RARELY_USED, // 叵 + 0x5402, KANJI_RARELY_USED, // 吂 + 0x5413, KANJI_RARELY_USED, // 吓 + 0x541A, KANJI_RARELY_USED, // 吚 + 0x5421, KANJI_RARELY_USED, // 吡 + 0x5427, KANJI_RARELY_USED, // 吧 + 0x5428, KANJI_RARELY_USED, // 吚 + 0x542A, KANJI_RARELY_USED, // 吪 + 0x542F, KANJI_RARELY_USED, // 启 + 0x5431, KANJI_RARELY_USED, // 吱 + 0x5434, KANJI_RARELY_USED, // 后 + 0x5435, KANJI_RARELY_USED, // 吵 + 0x5443, KANJI_RARELY_USED, // 呃 + 0x5444, KANJI_RARELY_USED, // 呄 + 0x5447, KANJI_RARELY_USED, // 呇 + 0x544D, KANJI_RARELY_USED, // 呍 + 0x544F, KANJI_RARELY_USED, // 呏 + 0x545E, KANJI_RARELY_USED, // 呞 + 0x5462, KANJI_RARELY_USED, // 呢 + 0x5464, KANJI_RARELY_USED, // å‘€ + 0x5466, KANJI_RARELY_USED, // 告 + 0x5467, KANJI_RARELY_USED, // 呧 + 0x5469, KANJI_RARELY_USED, // 呩 + 0x546B, KANJI_RARELY_USED, // 呫 + 0x546D, KANJI_RARELY_USED, // 呭 + 0x546E, KANJI_RARELY_USED, // 呮 + 0x5474, KANJI_RARELY_USED, // 呎 + 0x547F, KANJI_RARELY_USED, // 呿 + 0x5481, KANJI_RARELY_USED, // 咁 + 0x5483, KANJI_RARELY_USED, // 咃 + 0x5485, KANJI_RARELY_USED, // 咅 + 0x5488, KANJI_RARELY_USED, // 咈 + 0x5489, KANJI_RARELY_USED, // 咉 + 0x548D, KANJI_RARELY_USED, // 咍 + 0x5491, KANJI_RARELY_USED, // 咑 + 0x5495, KANJI_RARELY_USED, // 咕 + 0x5496, KANJI_RARELY_USED, // 咖 + 0x549C, KANJI_RARELY_USED, // 咜 + 0x549F, KANJI_RARELY_USED, // 咟 + 0x54A1, KANJI_RARELY_USED, // 咡 + 0x54A6, KANJI_RARELY_USED, // å’Š + 0x54A7, KANJI_RARELY_USED, // 咧 + 0x54A9, KANJI_RARELY_USED, // 咩 + 0x54AA, KANJI_RARELY_USED, // 咪 + 0x54AD, KANJI_RARELY_USED, // 咭 + 0x54AE, KANJI_RARELY_USED, // 咮 + 0x54B1, KANJI_RARELY_USED, // 咱 + 0x54B7, KANJI_RARELY_USED, // 咷 + 0x54B9, KANJI_RARELY_USED, // 咹 + 0x54BA, KANJI_RARELY_USED, // 咺 + 0x54BB, KANJI_RARELY_USED, // 咻 + 0x54BF, KANJI_RARELY_USED, // 咿 + 0x54C6, KANJI_RARELY_USED, // 哆 + 0x54CA, KANJI_RARELY_USED, // 哊 + 0x54CD, KANJI_RARELY_USED, // 响 + 0x54CE, KANJI_RARELY_USED, // 哎 + 0x54E0, KANJI_RARELY_USED, // 哠 + 0x54EA, KANJI_RARELY_USED, // 哪 + 0x54EC, KANJI_RARELY_USED, // 哬 + 0x54EF, KANJI_RARELY_USED, // 哯 + 0x54F6, KANJI_RARELY_USED, // 哶 + 0x54FC, KANJI_RARELY_USED, // 哌 + 0x54FE, KANJI_RARELY_USED, // 哟 + 0x54FF, KANJI_RARELY_USED, // 哿 + 0x5500, KANJI_RARELY_USED, // 唀 + 0x5501, KANJI_RARELY_USED, // 唁 + 0x5505, KANJI_RARELY_USED, // 唅 + 0x5508, KANJI_RARELY_USED, // 唈 + 0x5509, KANJI_RARELY_USED, // 唉 + 0x550C, KANJI_RARELY_USED, // 唌 + 0x550D, KANJI_RARELY_USED, // 唍 + 0x550E, KANJI_RARELY_USED, // 唎 + 0x5515, KANJI_RARELY_USED, // 唕 + 0x552A, KANJI_RARELY_USED, // 唪 + 0x552B, KANJI_RARELY_USED, // 唫 + 0x5532, KANJI_RARELY_USED, // 唲 + 0x5535, KANJI_RARELY_USED, // 唵 + 0x5536, KANJI_RARELY_USED, // 唶 + 0x553B, KANJI_RARELY_USED, // 唻 + 0x553C, KANJI_RARELY_USED, // 唌 + 0x553D, KANJI_RARELY_USED, // 唜 + 0x5541, KANJI_RARELY_USED, // 啁 + 0x5547, KANJI_RARELY_USED, // 啇 + 0x5549, KANJI_RARELY_USED, // 啉 + 0x554A, KANJI_RARELY_USED, // 啊 + 0x554D, KANJI_RARELY_USED, // 啍 + 0x5550, KANJI_RARELY_USED, // 啐 + 0x5551, KANJI_RARELY_USED, // 啑 + 0x5558, KANJI_RARELY_USED, // 啘 + 0x555A, KANJI_RARELY_USED, // 啚 + 0x555B, KANJI_RARELY_USED, // 啛 + 0x555E, KANJI_RARELY_USED, // 啞 + 0x5560, KANJI_RARELY_USED, // 啠 + 0x5561, KANJI_RARELY_USED, // 啡 + 0x5564, KANJI_RARELY_USED, // å•€ + 0x5566, KANJI_RARELY_USED, // 啊 + 0x557F, KANJI_RARELY_USED, // 啿 + 0x5581, KANJI_RARELY_USED, // 喁 + 0x5582, KANJI_RARELY_USED, // 喂 + 0x5586, KANJI_RARELY_USED, // 喆 + 0x5588, KANJI_RARELY_USED, // 喈 + 0x558E, KANJI_RARELY_USED, // 喎 + 0x558F, KANJI_RARELY_USED, // 喏 + 0x5591, KANJI_RARELY_USED, // 喑 + 0x5592, KANJI_RARELY_USED, // 喒 + 0x5593, KANJI_RARELY_USED, // 喓 + 0x5594, KANJI_RARELY_USED, // 喔 + 0x5597, KANJI_RARELY_USED, // 喗 + 0x55A3, KANJI_RARELY_USED, // 喣 + 0x55A4, KANJI_RARELY_USED, // å–€ + 0x55AD, KANJI_RARELY_USED, // 喭 + 0x55B2, KANJI_RARELY_USED, // 喲 + 0x55BF, KANJI_RARELY_USED, // 喿 + 0x55C1, KANJI_RARELY_USED, // 嗁 + 0x55C3, KANJI_RARELY_USED, // 嗃 + 0x55C6, KANJI_RARELY_USED, // 嗆 + 0x55C9, KANJI_RARELY_USED, // 嗉 + 0x55CB, KANJI_RARELY_USED, // 嗋 + 0x55CC, KANJI_RARELY_USED, // 嗌 + 0x55CE, KANJI_RARELY_USED, // 嗎 + 0x55D1, KANJI_RARELY_USED, // 嗑 + 0x55D2, KANJI_RARELY_USED, // 嗒 + 0x55D3, KANJI_RARELY_USED, // 嗓 + 0x55D7, KANJI_RARELY_USED, // 嗗 + 0x55D8, KANJI_RARELY_USED, // 嗘 + 0x55DB, KANJI_RARELY_USED, // 嗛 + 0x55DE, KANJI_RARELY_USED, // 嗞 + 0x55E2, KANJI_RARELY_USED, // 嗢 + 0x55E9, KANJI_RARELY_USED, // 嗩 + 0x55F6, KANJI_RARELY_USED, // 嗶 + 0x55FF, KANJI_RARELY_USED, // 嗿 + 0x5605, KANJI_RARELY_USED, // 嘅 + 0x5608, KANJI_RARELY_USED, // 嘈 + 0x560A, KANJI_RARELY_USED, // 嘊 + 0x560D, KANJI_RARELY_USED, // 嘍 + 0x560E, KANJI_RARELY_USED, // 嘎 + 0x560F, KANJI_RARELY_USED, // 嘏 + 0x5610, KANJI_RARELY_USED, // 嘐 + 0x5611, KANJI_RARELY_USED, // 嘑 + 0x5612, KANJI_RARELY_USED, // 嘒 + 0x5619, KANJI_RARELY_USED, // 嘙 + 0x562C, KANJI_RARELY_USED, // 嘬 + 0x5630, KANJI_RARELY_USED, // 嘰 + 0x5633, KANJI_RARELY_USED, // 嘳 + 0x5635, KANJI_RARELY_USED, // 嘵 + 0x5637, KANJI_RARELY_USED, // 嘷 + 0x5639, KANJI_RARELY_USED, // 嘹 + 0x563B, KANJI_RARELY_USED, // 嘻 + 0x563C, KANJI_RARELY_USED, // 嘌 + 0x563D, KANJI_RARELY_USED, // 嘜 + 0x563F, KANJI_RARELY_USED, // 嘿 + 0x5640, KANJI_RARELY_USED, // 噀 + 0x5641, KANJI_RARELY_USED, // 噁 + 0x5643, KANJI_RARELY_USED, // 噃 + 0x5644, KANJI_RARELY_USED, // 噄 + 0x5646, KANJI_RARELY_USED, // 噆 + 0x5649, KANJI_RARELY_USED, // 噉 + 0x564B, KANJI_RARELY_USED, // 噋 + 0x564D, KANJI_RARELY_USED, // 噍 + 0x564F, KANJI_RARELY_USED, // 噏 + 0x5654, KANJI_RARELY_USED, // 噔 + 0x565E, KANJI_RARELY_USED, // 噞 + 0x5660, KANJI_RARELY_USED, // 噠 + 0x5661, KANJI_RARELY_USED, // 噡 + 0x5662, KANJI_RARELY_USED, // 噢 + 0x5663, KANJI_RARELY_USED, // 噣 + 0x5666, KANJI_RARELY_USED, // 噊 + 0x5669, KANJI_RARELY_USED, // 噩 + 0x566D, KANJI_RARELY_USED, // 噭 + 0x566F, KANJI_RARELY_USED, // 噯 + 0x5671, KANJI_RARELY_USED, // 噱 + 0x5672, KANJI_RARELY_USED, // 噲 + 0x5675, KANJI_RARELY_USED, // 噵 + 0x5684, KANJI_RARELY_USED, // 嚄 + 0x5685, KANJI_RARELY_USED, // 嚅 + 0x5688, KANJI_RARELY_USED, // 嚈 + 0x568B, KANJI_RARELY_USED, // 嚋 + 0x568C, KANJI_RARELY_USED, // 嚌 + 0x5695, KANJI_RARELY_USED, // 嚕 + 0x5699, KANJI_RARELY_USED, // 嚙 + 0x569A, KANJI_RARELY_USED, // 嚚 + 0x569D, KANJI_RARELY_USED, // 嚝 + 0x569E, KANJI_RARELY_USED, // 嚞 + 0x569F, KANJI_RARELY_USED, // 嚟 + 0x56A6, KANJI_RARELY_USED, // 嚊 + 0x56A7, KANJI_RARELY_USED, // 嚧 + 0x56A8, KANJI_RARELY_USED, // åšš + 0x56A9, KANJI_RARELY_USED, // 嚩 + 0x56AB, KANJI_RARELY_USED, // 嚫 + 0x56AC, KANJI_RARELY_USED, // 嚬 + 0x56AD, KANJI_RARELY_USED, // 嚭 + 0x56B1, KANJI_RARELY_USED, // 嚱 + 0x56B3, KANJI_RARELY_USED, // 嚳 + 0x56B7, KANJI_RARELY_USED, // 嚷 + 0x56BE, KANJI_RARELY_USED, // 嚟 + 0x56C5, KANJI_RARELY_USED, // 囅 + 0x56C9, KANJI_RARELY_USED, // 囉 + 0x56CA, KANJI_RARELY_USED, // 囊 + 0x56CB, KANJI_RARELY_USED, // 囋 + 0x56CF, KANJI_RARELY_USED, // 囏 + 0x56D0, KANJI_RARELY_USED, // 囐 + 0x56CC, KANJI_RARELY_USED, // 囌 + 0x56CD, KANJI_RARELY_USED, // 囍 + 0x56D9, KANJI_RARELY_USED, // 囙 + 0x56DC, KANJI_RARELY_USED, // 囜 + 0x56DD, KANJI_RARELY_USED, // 囝 + 0x56DF, KANJI_RARELY_USED, // 囟 + 0x56E1, KANJI_RARELY_USED, // 囡 + 0x56E4, KANJI_RARELY_USED, // 囀 + 0x56E5, KANJI_RARELY_USED, // 囥 + 0x56E6, KANJI_RARELY_USED, // 囊 + 0x56E7, KANJI_RARELY_USED, // 囧 + 0x56E8, KANJI_RARELY_USED, // 囚 + 0x56F1, KANJI_RARELY_USED, // 囱 + 0x56EB, KANJI_RARELY_USED, // 囫 + 0x56ED, KANJI_RARELY_USED, // 园 + 0x56F6, KANJI_RARELY_USED, // 囶 + 0x56F7, KANJI_RARELY_USED, // 囷 + 0x5701, KANJI_RARELY_USED, // 圁 + 0x5702, KANJI_RARELY_USED, // 圂 + 0x5707, KANJI_RARELY_USED, // 圇 + 0x570A, KANJI_RARELY_USED, // 圊 + 0x570C, KANJI_RARELY_USED, // 圌 + 0x5711, KANJI_RARELY_USED, // 圑 + 0x5715, KANJI_RARELY_USED, // 圕 + 0x571A, KANJI_RARELY_USED, // 圚 + 0x571B, KANJI_RARELY_USED, // 圛 + 0x571D, KANJI_RARELY_USED, // 圝 + 0x5720, KANJI_RARELY_USED, // 圠 + 0x5722, KANJI_RARELY_USED, // 圢 + 0x5723, KANJI_RARELY_USED, // 圣 + 0x5724, KANJI_RARELY_USED, // 圀 + 0x5725, KANJI_RARELY_USED, // 圥 + 0x5729, KANJI_RARELY_USED, // 圩 + 0x572A, KANJI_RARELY_USED, // 圪 + 0x572C, KANJI_RARELY_USED, // 圬 + 0x572E, KANJI_RARELY_USED, // 圮 + 0x572F, KANJI_RARELY_USED, // 圯 + 0x5733, KANJI_RARELY_USED, // 圳 + 0x5734, KANJI_RARELY_USED, // 圎 + 0x573D, KANJI_RARELY_USED, // 圜 + 0x573E, KANJI_RARELY_USED, // 土 + 0x573F, KANJI_RARELY_USED, // 圿 + 0x5745, KANJI_RARELY_USED, // 坅 + 0x5746, KANJI_RARELY_USED, // 坆 + 0x574C, KANJI_RARELY_USED, // 坌 + 0x574D, KANJI_RARELY_USED, // 坍 + 0x5752, KANJI_RARELY_USED, // 坒 + 0x5762, KANJI_RARELY_USED, // 坢 + 0x5765, KANJI_RARELY_USED, // 坥 + 0x5767, KANJI_RARELY_USED, // 坧 + 0x5768, KANJI_RARELY_USED, // 坚 + 0x576B, KANJI_RARELY_USED, // 坫 + 0x576D, KANJI_RARELY_USED, // 坭 + 0x576E, KANJI_RARELY_USED, // 坮 + 0x576F, KANJI_RARELY_USED, // 坯 + 0x5770, KANJI_RARELY_USED, // 坰 + 0x5771, KANJI_RARELY_USED, // 坱 + 0x5773, KANJI_RARELY_USED, // 坳 + 0x5774, KANJI_RARELY_USED, // 坎 + 0x5775, KANJI_RARELY_USED, // 坵 + 0x5777, KANJI_RARELY_USED, // 坷 + 0x5779, KANJI_RARELY_USED, // 坹 + 0x577A, KANJI_RARELY_USED, // 坺 + 0x577B, KANJI_RARELY_USED, // 坻 + 0x577C, KANJI_RARELY_USED, // 坌 + 0x577E, KANJI_RARELY_USED, // 坟 + 0x5781, KANJI_RARELY_USED, // 垁 + 0x5783, KANJI_RARELY_USED, // 垃 + 0x578C, KANJI_RARELY_USED, // 垌 + 0x5794, KANJI_RARELY_USED, // 垔 + 0x5797, KANJI_RARELY_USED, // 垗 + 0x5799, KANJI_RARELY_USED, // 垙 + 0x579A, KANJI_RARELY_USED, // 垚 + 0x579C, KANJI_RARELY_USED, // 垜 + 0x579D, KANJI_RARELY_USED, // 垝 + 0x579E, KANJI_RARELY_USED, // 垞 + 0x579F, KANJI_RARELY_USED, // 垟 + 0x57A1, KANJI_RARELY_USED, // 垡 + 0x5795, KANJI_RARELY_USED, // 垕 + 0x57A7, KANJI_RARELY_USED, // 垧 + 0x57A8, KANJI_RARELY_USED, // 垚 + 0x57A9, KANJI_RARELY_USED, // 垩 + 0x57AC, KANJI_RARELY_USED, // 垬 + 0x57B8, KANJI_RARELY_USED, // åžž + 0x57BD, KANJI_RARELY_USED, // 垜 + 0x57C7, KANJI_RARELY_USED, // 埇 + 0x57C8, KANJI_RARELY_USED, // 埈 + 0x57CC, KANJI_RARELY_USED, // 埌 + 0x57CF, KANJI_RARELY_USED, // 埏 + 0x57D5, KANJI_RARELY_USED, // 埕 + 0x57DD, KANJI_RARELY_USED, // 埝 + 0x57DE, KANJI_RARELY_USED, // 埞 + 0x57E4, KANJI_RARELY_USED, // 埀 + 0x57E6, KANJI_RARELY_USED, // 埊 + 0x57E7, KANJI_RARELY_USED, // 埧 + 0x57E9, KANJI_RARELY_USED, // 埩 + 0x57ED, KANJI_RARELY_USED, // 埭 + 0x57F0, KANJI_RARELY_USED, // 埰 + 0x57F5, KANJI_RARELY_USED, // 埵 + 0x57F6, KANJI_RARELY_USED, // 埶 + 0x57F8, KANJI_RARELY_USED, // 埞 + 0x57FD, KANJI_RARELY_USED, // 埜 + 0x57FE, KANJI_RARELY_USED, // 域 + 0x57FF, KANJI_RARELY_USED, // 埿 + 0x5803, KANJI_RARELY_USED, // 堃 + 0x5804, KANJI_RARELY_USED, // 堄 + 0x5808, KANJI_RARELY_USED, // 堈 + 0x5809, KANJI_RARELY_USED, // 堉 + 0x57E1, KANJI_RARELY_USED, // 埡 + 0x580C, KANJI_RARELY_USED, // 堌 + 0x580D, KANJI_RARELY_USED, // 堍 + 0x581B, KANJI_RARELY_USED, // 堛 + 0x581E, KANJI_RARELY_USED, // 堞 + 0x581F, KANJI_RARELY_USED, // 堟 + 0x5820, KANJI_RARELY_USED, // å   + 0x5826, KANJI_RARELY_USED, // å Š + 0x5827, KANJI_RARELY_USED, // å § + 0x582D, KANJI_RARELY_USED, // å ­ + 0x5832, KANJI_RARELY_USED, // å ² + 0x5839, KANJI_RARELY_USED, // å ¹ + 0x583F, KANJI_RARELY_USED, // å ¿ + 0x5849, KANJI_RARELY_USED, // 塉 + 0x584C, KANJI_RARELY_USED, // 塌 + 0x584D, KANJI_RARELY_USED, // 塍 + 0x584F, KANJI_RARELY_USED, // 塏 + 0x5850, KANJI_RARELY_USED, // 塐 + 0x5855, KANJI_RARELY_USED, // 塕 + 0x585F, KANJI_RARELY_USED, // 塟 + 0x5861, KANJI_RARELY_USED, // å¡¡ + 0x5864, KANJI_RARELY_USED, // å¡€ + 0x5867, KANJI_RARELY_USED, // å¡§ + 0x5868, KANJI_RARELY_USED, // 塚 + 0x5878, KANJI_RARELY_USED, // 塞 + 0x587C, KANJI_RARELY_USED, // 塌 + 0x587F, KANJI_RARELY_USED, // å¡¿ + 0x5880, KANJI_RARELY_USED, // 墀 + 0x5881, KANJI_RARELY_USED, // 墁 + 0x5887, KANJI_RARELY_USED, // 墇 + 0x5888, KANJI_RARELY_USED, // 墈 + 0x5889, KANJI_RARELY_USED, // 墉 + 0x588A, KANJI_RARELY_USED, // 墊 + 0x588C, KANJI_RARELY_USED, // 墌 + 0x588D, KANJI_RARELY_USED, // 墍 + 0x588F, KANJI_RARELY_USED, // 墏 + 0x5890, KANJI_RARELY_USED, // 墐 + 0x5894, KANJI_RARELY_USED, // 墔 + 0x5896, KANJI_RARELY_USED, // 墖 + 0x589D, KANJI_RARELY_USED, // 墝 + 0x58A0, KANJI_RARELY_USED, // 墠 + 0x58A1, KANJI_RARELY_USED, // 墡 + 0x58A2, KANJI_RARELY_USED, // 墢 + 0x58A6, KANJI_RARELY_USED, // 墊 + 0x58A9, KANJI_RARELY_USED, // 墩 + 0x58B1, KANJI_RARELY_USED, // 墱 + 0x58B2, KANJI_RARELY_USED, // 墲 + 0x58C4, KANJI_RARELY_USED, // 壄 + 0x58BC, KANJI_RARELY_USED, // 墌 + 0x58C2, KANJI_RARELY_USED, // 壂 + 0x58C8, KANJI_RARELY_USED, // 壈 + 0x58CD, KANJI_RARELY_USED, // 壍 + 0x58CE, KANJI_RARELY_USED, // 壎 + 0x58D0, KANJI_RARELY_USED, // 壐 + 0x58D2, KANJI_RARELY_USED, // 壒 + 0x58D4, KANJI_RARELY_USED, // 壔 + 0x58D6, KANJI_RARELY_USED, // 壖 + 0x58DA, KANJI_RARELY_USED, // 壚 + 0x58DD, KANJI_RARELY_USED, // 壝 + 0x58E1, KANJI_RARELY_USED, // 壡 + 0x58E2, KANJI_RARELY_USED, // 壢 + 0x58E9, KANJI_RARELY_USED, // 壩 + 0x58F3, KANJI_RARELY_USED, // 壳 + 0x5905, KANJI_RARELY_USED, // 倅 + 0x5906, KANJI_RARELY_USED, // 倆 + 0x590B, KANJI_RARELY_USED, // 個 + 0x590C, KANJI_RARELY_USED, // 倌 + 0x5912, KANJI_RARELY_USED, // 倒 + 0x5913, KANJI_RARELY_USED, // 倓 + 0x5914, KANJI_RARELY_USED, // 倔 + 0x8641, KANJI_RARELY_USED, // 虁 + 0x591D, KANJI_RARELY_USED, // 倝 + 0x5921, KANJI_RARELY_USED, // 倡 + 0x5923, KANJI_RARELY_USED, // 倣 + 0x5924, KANJI_RARELY_USED, // 倀 + 0x5928, KANJI_RARELY_USED, // 倚 + 0x592F, KANJI_RARELY_USED, // 倯 + 0x5930, KANJI_RARELY_USED, // 倰 + 0x5933, KANJI_RARELY_USED, // 倳 + 0x5935, KANJI_RARELY_USED, // 倵 + 0x5936, KANJI_RARELY_USED, // 倶 + 0x593F, KANJI_RARELY_USED, // 倿 + 0x5943, KANJI_RARELY_USED, // 奃 + 0x5946, KANJI_RARELY_USED, // 奆 + 0x5952, KANJI_RARELY_USED, // 奒 + 0x5953, KANJI_RARELY_USED, // 奓 + 0x5959, KANJI_RARELY_USED, // 奙 + 0x595B, KANJI_RARELY_USED, // 奛 + 0x595D, KANJI_RARELY_USED, // 奝 + 0x595E, KANJI_RARELY_USED, // 奞 + 0x595F, KANJI_RARELY_USED, // 奟 + 0x5961, KANJI_RARELY_USED, // 奡 + 0x5963, KANJI_RARELY_USED, // 奣 + 0x596B, KANJI_RARELY_USED, // 奫 + 0x596D, KANJI_RARELY_USED, // 奭 + 0x596F, KANJI_RARELY_USED, // 奯 + 0x5972, KANJI_RARELY_USED, // 奲 + 0x5975, KANJI_RARELY_USED, // 奵 + 0x5976, KANJI_RARELY_USED, // 奶 + 0x5979, KANJI_RARELY_USED, // 她 + 0x597B, KANJI_RARELY_USED, // 奻 + 0x597C, KANJI_RARELY_USED, // 奌 + 0x598B, KANJI_RARELY_USED, // 劋 + 0x598C, KANJI_RARELY_USED, // 劌 + 0x598E, KANJI_RARELY_USED, // 劎 + 0x5992, KANJI_RARELY_USED, // 劒 + 0x5995, KANJI_RARELY_USED, // 劕 + 0x5997, KANJI_RARELY_USED, // 劗 + 0x599F, KANJI_RARELY_USED, // 功 + 0x59A4, KANJI_RARELY_USED, // 劀 + 0x59A7, KANJI_RARELY_USED, // 劧 + 0x59AD, KANJI_RARELY_USED, // 劭 + 0x59AE, KANJI_RARELY_USED, // 劮 + 0x59AF, KANJI_RARELY_USED, // 劯 + 0x59B0, KANJI_RARELY_USED, // 劰 + 0x59B3, KANJI_RARELY_USED, // 劳 + 0x59B7, KANJI_RARELY_USED, // 劷 + 0x59BA, KANJI_RARELY_USED, // 劺 + 0x59BC, KANJI_RARELY_USED, // 劌 + 0x59C1, KANJI_RARELY_USED, // 姁 + 0x59C3, KANJI_RARELY_USED, // 姃 + 0x59C4, KANJI_RARELY_USED, // 姄 + 0x59C8, KANJI_RARELY_USED, // 姈 + 0x59CA, KANJI_RARELY_USED, // 姊 + 0x59CD, KANJI_RARELY_USED, // 姍 + 0x59D2, KANJI_RARELY_USED, // 姒 + 0x59DD, KANJI_RARELY_USED, // 姝 + 0x59DE, KANJI_RARELY_USED, // 姞 + 0x59DF, KANJI_RARELY_USED, // 姟 + 0x59E3, KANJI_RARELY_USED, // å§£ + 0x59E4, KANJI_RARELY_USED, // å§€ + 0x59E7, KANJI_RARELY_USED, // å§§ + 0x59EE, KANJI_RARELY_USED, // å§® + 0x59EF, KANJI_RARELY_USED, // 姯 + 0x59F1, KANJI_RARELY_USED, // å§± + 0x59F2, KANJI_RARELY_USED, // å§² + 0x59F4, KANJI_RARELY_USED, // å§Ž + 0x59F7, KANJI_RARELY_USED, // å§· + 0x5A00, KANJI_RARELY_USED, // 嚀 + 0x5A04, KANJI_RARELY_USED, // åš„ + 0x5A0C, KANJI_RARELY_USED, // 嚌 + 0x5A0D, KANJI_RARELY_USED, // 嚍 + 0x5A0E, KANJI_RARELY_USED, // 嚎 + 0x5A12, KANJI_RARELY_USED, // åš’ + 0x5A13, KANJI_RARELY_USED, // åš“ + 0x5A1E, KANJI_RARELY_USED, // 嚞 + 0x5A23, KANJI_RARELY_USED, // 嚣 + 0x5A24, KANJI_RARELY_USED, // 嚀 + 0x5A27, KANJI_RARELY_USED, // åš§ + 0x5A28, KANJI_RARELY_USED, // åšš + 0x5A2A, KANJI_RARELY_USED, // 嚪 + 0x5A2D, KANJI_RARELY_USED, // åš­ + 0x5A30, KANJI_RARELY_USED, // åš° + 0x5A44, KANJI_RARELY_USED, // 婄 + 0x5A45, KANJI_RARELY_USED, // 婅 + 0x5A47, KANJI_RARELY_USED, // 婇 + 0x5A48, KANJI_RARELY_USED, // 婈 + 0x5A4C, KANJI_RARELY_USED, // 婌 + 0x5A50, KANJI_RARELY_USED, // 婐 + 0x5A55, KANJI_RARELY_USED, // 婕 + 0x5A5E, KANJI_RARELY_USED, // 婞 + 0x5A63, KANJI_RARELY_USED, // å©£ + 0x5A65, KANJI_RARELY_USED, // å©¥ + 0x5A67, KANJI_RARELY_USED, // å©§ + 0x5A6D, KANJI_RARELY_USED, // å©­ + 0x5A77, KANJI_RARELY_USED, // å©· + 0x5A7A, KANJI_RARELY_USED, // 婺 + 0x5A7B, KANJI_RARELY_USED, // å©» + 0x5A7E, KANJI_RARELY_USED, // 婟 + 0x5A8B, KANJI_RARELY_USED, // 媋 + 0x5A90, KANJI_RARELY_USED, // 媐 + 0x5A93, KANJI_RARELY_USED, // 媓 + 0x5A96, KANJI_RARELY_USED, // 媖 + 0x5A99, KANJI_RARELY_USED, // 媙 + 0x5A9C, KANJI_RARELY_USED, // 媜 + 0x5A9E, KANJI_RARELY_USED, // 媞 + 0x5A9F, KANJI_RARELY_USED, // 媟 + 0x5AA0, KANJI_RARELY_USED, // 媠 + 0x5AA2, KANJI_RARELY_USED, // 媢 + 0x5AA7, KANJI_RARELY_USED, // 媧 + 0x5AAC, KANJI_RARELY_USED, // 媬 + 0x5AB1, KANJI_RARELY_USED, // 媱 + 0x5AB2, KANJI_RARELY_USED, // 媲 + 0x5AB3, KANJI_RARELY_USED, // 媳 + 0x5AB5, KANJI_RARELY_USED, // 媵 + 0x5AB8, KANJI_RARELY_USED, // 媞 + 0x5ABA, KANJI_RARELY_USED, // 媺 + 0x5ABB, KANJI_RARELY_USED, // 媻 + 0x5ABF, KANJI_RARELY_USED, // 媿 + 0x5AC4, KANJI_RARELY_USED, // 嫄 + 0x5AC6, KANJI_RARELY_USED, // 嫆 + 0x5AC8, KANJI_RARELY_USED, // 嫈 + 0x5ACF, KANJI_RARELY_USED, // 嫏 + 0x5ADA, KANJI_RARELY_USED, // 嫚 + 0x5ADC, KANJI_RARELY_USED, // 嫜 + 0x5AE0, KANJI_RARELY_USED, // å«  + 0x5AE5, KANJI_RARELY_USED, // å«¥ + 0x5AEA, KANJI_RARELY_USED, // 嫪 + 0x5AEE, KANJI_RARELY_USED, // å«® + 0x5AF5, KANJI_RARELY_USED, // 嫵 + 0x5AF6, KANJI_RARELY_USED, // å«¶ + 0x5AFD, KANJI_RARELY_USED, // 嫜 + 0x5B00, KANJI_RARELY_USED, // 嬀 + 0x5B01, KANJI_RARELY_USED, // 嬁 + 0x5B08, KANJI_RARELY_USED, // 嬈 + 0x5B17, KANJI_RARELY_USED, // 嬗 + 0x5B34, KANJI_RARELY_USED, // 嬎 + 0x5B19, KANJI_RARELY_USED, // 嬙 + 0x5B1B, KANJI_RARELY_USED, // 嬛 + 0x5B1D, KANJI_RARELY_USED, // 嬝 + 0x5B21, KANJI_RARELY_USED, // 嬡 + 0x5B25, KANJI_RARELY_USED, // 嬥 + 0x5B2D, KANJI_RARELY_USED, // 嬭 + 0x5B38, KANJI_RARELY_USED, // 嬞 + 0x5B41, KANJI_RARELY_USED, // 孁 + 0x5B4B, KANJI_RARELY_USED, // 孋 + 0x5B4C, KANJI_RARELY_USED, // 孌 + 0x5B52, KANJI_RARELY_USED, // 孒 + 0x5B56, KANJI_RARELY_USED, // 孖 + 0x5B5E, KANJI_RARELY_USED, // 孞 + 0x5B68, KANJI_RARELY_USED, // å­š + 0x5B6E, KANJI_RARELY_USED, // å­® + 0x5B6F, KANJI_RARELY_USED, // å­¯ + 0x5B7C, KANJI_RARELY_USED, // å­Œ + 0x5B7D, KANJI_RARELY_USED, // å­œ + 0x5B7E, KANJI_RARELY_USED, // å­Ÿ + 0x5B7F, KANJI_RARELY_USED, // å­¿ + 0x5B81, KANJI_RARELY_USED, // 宁 + 0x5B84, KANJI_RARELY_USED, // 宄 + 0x5B86, KANJI_RARELY_USED, // 宆 + 0x5B8A, KANJI_RARELY_USED, // 宊 + 0x5B8E, KANJI_RARELY_USED, // 宎 + 0x5B90, KANJI_RARELY_USED, // 宐 + 0x5B91, KANJI_RARELY_USED, // 宑 + 0x5B93, KANJI_RARELY_USED, // 宓 + 0x5B94, KANJI_RARELY_USED, // 宔 + 0x5B96, KANJI_RARELY_USED, // 宖 + 0x5BA8, KANJI_RARELY_USED, // 定 + 0x5BA9, KANJI_RARELY_USED, // 宩 + 0x5BAC, KANJI_RARELY_USED, // 宬 + 0x5BAD, KANJI_RARELY_USED, // å®­ + 0x5BAF, KANJI_RARELY_USED, // 宯 + 0x5BB1, KANJI_RARELY_USED, // å®± + 0x5BB2, KANJI_RARELY_USED, // 宲 + 0x5BB7, KANJI_RARELY_USED, // å®· + 0x5BBA, KANJI_RARELY_USED, // 宺 + 0x5BBC, KANJI_RARELY_USED, // 完 + 0x5BC0, KANJI_RARELY_USED, // 寀 + 0x5BC1, KANJI_RARELY_USED, // 寁 + 0x5BCD, KANJI_RARELY_USED, // 寍 + 0x5BCF, KANJI_RARELY_USED, // 寏 + 0x5BD6, KANJI_RARELY_USED, // 寖 + 0x5BD7, KANJI_RARELY_USED, // 寗 + 0x5BD8, KANJI_RARELY_USED, // 寘 + 0x5BD9, KANJI_RARELY_USED, // 寙 + 0x5BDA, KANJI_RARELY_USED, // 寚 + 0x5BE0, KANJI_RARELY_USED, // 寠 + 0x5BEF, KANJI_RARELY_USED, // 寯 + 0x5BF1, KANJI_RARELY_USED, // 寱 + 0x5BF4, KANJI_RARELY_USED, // 寎 + 0x5BFD, KANJI_RARELY_USED, // 寜 + 0x5C0C, KANJI_RARELY_USED, // 尌 + 0x5C17, KANJI_RARELY_USED, // 尗 + 0x5C1E, KANJI_RARELY_USED, // 尞 + 0x5C1F, KANJI_RARELY_USED, // 尟 + 0x5C23, KANJI_RARELY_USED, // å°£ + 0x5C26, KANJI_RARELY_USED, // å°Š + 0x5C29, KANJI_RARELY_USED, // å°© + 0x5C2B, KANJI_RARELY_USED, // å°« + 0x5C2C, KANJI_RARELY_USED, // å°¬ + 0x5C2E, KANJI_RARELY_USED, // å°® + 0x5C30, KANJI_RARELY_USED, // å°° + 0x5C32, KANJI_RARELY_USED, // å°² + 0x5C35, KANJI_RARELY_USED, // å°µ + 0x5C36, KANJI_RARELY_USED, // å°¶ + 0x5C59, KANJI_RARELY_USED, // 屙 + 0x5C5A, KANJI_RARELY_USED, // 屚 + 0x5C5C, KANJI_RARELY_USED, // 屜 + 0x5C62, KANJI_RARELY_USED, // å±¢ + 0x5C63, KANJI_RARELY_USED, // å±£ + 0x5C67, KANJI_RARELY_USED, // å±§ + 0x5C68, KANJI_RARELY_USED, // 屚 + 0x5C69, KANJI_RARELY_USED, // 屩 + 0x5C6D, KANJI_RARELY_USED, // å±­ + 0x5C70, KANJI_RARELY_USED, // å±° + 0x5C74, KANJI_RARELY_USED, // 屎 + 0x5C75, KANJI_RARELY_USED, // å±µ + 0x5C7A, KANJI_RARELY_USED, // 屺 + 0x5C7B, KANJI_RARELY_USED, // å±» + 0x5C7C, KANJI_RARELY_USED, // 屌 + 0x5C7D, KANJI_RARELY_USED, // 屜 + 0x5C87, KANJI_RARELY_USED, // 岇 + 0x5C88, KANJI_RARELY_USED, // 岈 + 0x5C8A, KANJI_RARELY_USED, // 岊 + 0x5C8F, KANJI_RARELY_USED, // 岏 + 0x5C92, KANJI_RARELY_USED, // 岒 + 0x5C9D, KANJI_RARELY_USED, // 岝 + 0x5C9F, KANJI_RARELY_USED, // 岟 + 0x5CA0, KANJI_RARELY_USED, // å²  + 0x5CA2, KANJI_RARELY_USED, // å²¢ + 0x5CA3, KANJI_RARELY_USED, // å²£ + 0x5CA6, KANJI_RARELY_USED, // 岊 + 0x5CAA, KANJI_RARELY_USED, // 岪 + 0x5CB2, KANJI_RARELY_USED, // å²² + 0x5CB4, KANJI_RARELY_USED, // 岎 + 0x5CB5, KANJI_RARELY_USED, // å²µ + 0x5CBA, KANJI_RARELY_USED, // 岺 + 0x5CC9, KANJI_RARELY_USED, // 峉 + 0x5CCB, KANJI_RARELY_USED, // 峋 + 0x5CD2, KANJI_RARELY_USED, // 峒 + 0x5CDD, KANJI_RARELY_USED, // 峝 + 0x5CD7, KANJI_RARELY_USED, // 峗 + 0x5CEE, KANJI_RARELY_USED, // å³® + 0x5CF1, KANJI_RARELY_USED, // å³± + 0x5CF2, KANJI_RARELY_USED, // å³² + 0x5CF4, KANJI_RARELY_USED, // 峎 + 0x5D01, KANJI_RARELY_USED, // 厁 + 0x5D06, KANJI_RARELY_USED, // 历 + 0x5D0D, KANJI_RARELY_USED, // 厍 + 0x5D12, KANJI_RARELY_USED, // 厒 + 0x5D2B, KANJI_RARELY_USED, // 厫 + 0x5D23, KANJI_RARELY_USED, // 厣 + 0x5D24, KANJI_RARELY_USED, // 厀 + 0x5D26, KANJI_RARELY_USED, // 厊 + 0x5D27, KANJI_RARELY_USED, // 厧 + 0x5D31, KANJI_RARELY_USED, // 厱 + 0x5D34, KANJI_RARELY_USED, // 厎 + 0x5D39, KANJI_RARELY_USED, // 厹 + 0x5D3D, KANJI_RARELY_USED, // 厜 + 0x5D3F, KANJI_RARELY_USED, // 县 + 0x5D42, KANJI_RARELY_USED, // 嵂 + 0x5D43, KANJI_RARELY_USED, // 嵃 + 0x5D46, KANJI_RARELY_USED, // 嵆 + 0x5D48, KANJI_RARELY_USED, // 嵈 + 0x5D55, KANJI_RARELY_USED, // 嵕 + 0x5D51, KANJI_RARELY_USED, // 嵑 + 0x5D59, KANJI_RARELY_USED, // 嵙 + 0x5D4A, KANJI_RARELY_USED, // 嵊 + 0x5D5F, KANJI_RARELY_USED, // 嵟 + 0x5D60, KANJI_RARELY_USED, // åµ  + 0x5D61, KANJI_RARELY_USED, // 嵡 + 0x5D62, KANJI_RARELY_USED, // åµ¢ + 0x5D64, KANJI_RARELY_USED, // åµ€ + 0x5D6A, KANJI_RARELY_USED, // 嵪 + 0x5D6D, KANJI_RARELY_USED, // åµ­ + 0x5D70, KANJI_RARELY_USED, // åµ° + 0x5D79, KANJI_RARELY_USED, // åµ¹ + 0x5D7A, KANJI_RARELY_USED, // 嵺 + 0x5D7E, KANJI_RARELY_USED, // 嵟 + 0x5D7F, KANJI_RARELY_USED, // 嵿 + 0x5D81, KANJI_RARELY_USED, // 嶁 + 0x5D83, KANJI_RARELY_USED, // 嶃 + 0x5D88, KANJI_RARELY_USED, // 嶈 + 0x5D8A, KANJI_RARELY_USED, // 嶊 + 0x5D92, KANJI_RARELY_USED, // 嶒 + 0x5D93, KANJI_RARELY_USED, // 嶓 + 0x5D94, KANJI_RARELY_USED, // 嶔 + 0x5D95, KANJI_RARELY_USED, // 嶕 + 0x5D99, KANJI_RARELY_USED, // 嶙 + 0x5D9B, KANJI_RARELY_USED, // 嶛 + 0x5D9F, KANJI_RARELY_USED, // 嶟 + 0x5DA0, KANJI_RARELY_USED, // å¶  + 0x5DA7, KANJI_RARELY_USED, // å¶§ + 0x5DAB, KANJI_RARELY_USED, // å¶« + 0x5DB0, KANJI_RARELY_USED, // å¶° + 0x5DB4, KANJI_RARELY_USED, // å¶Ž + 0x5DB8, KANJI_RARELY_USED, // å¶ž + 0x5DB9, KANJI_RARELY_USED, // å¶¹ + 0x5DC3, KANJI_RARELY_USED, // 巃 + 0x5DC7, KANJI_RARELY_USED, // 巇 + 0x5DCB, KANJI_RARELY_USED, // 巋 + 0x5DD0, KANJI_RARELY_USED, // 巐 + 0x5DCE, KANJI_RARELY_USED, // 巎 + 0x5DD8, KANJI_RARELY_USED, // 巘 + 0x5DD9, KANJI_RARELY_USED, // 巙 + 0x5DE0, KANJI_RARELY_USED, // å·  + 0x5DE4, KANJI_RARELY_USED, // å·€ + 0x5DE9, KANJI_RARELY_USED, // å·© + 0x5DF8, KANJI_RARELY_USED, // å·ž + 0x5DF9, KANJI_RARELY_USED, // å·¹ + 0x5E00, KANJI_RARELY_USED, // 垀 + 0x5E07, KANJI_RARELY_USED, // 垇 + 0x5E0D, KANJI_RARELY_USED, // 垍 + 0x5E12, KANJI_RARELY_USED, // åž’ + 0x5E14, KANJI_RARELY_USED, // åž” + 0x5E15, KANJI_RARELY_USED, // åž• + 0x5E18, KANJI_RARELY_USED, // 垘 + 0x5E1F, KANJI_RARELY_USED, // 垟 + 0x5E20, KANJI_RARELY_USED, // åž  + 0x5E2E, KANJI_RARELY_USED, // åž® + 0x5E28, KANJI_RARELY_USED, // åžš + 0x5E32, KANJI_RARELY_USED, // åž² + 0x5E35, KANJI_RARELY_USED, // åžµ + 0x5E3E, KANJI_RARELY_USED, // 垟 + 0x5E4B, KANJI_RARELY_USED, // 幋 + 0x5E50, KANJI_RARELY_USED, // 幐 + 0x5E49, KANJI_RARELY_USED, // 幉 + 0x5E51, KANJI_RARELY_USED, // 幑 + 0x5E56, KANJI_RARELY_USED, // 幖 + 0x5E58, KANJI_RARELY_USED, // 幘 + 0x5E5B, KANJI_RARELY_USED, // 幛 + 0x5E5C, KANJI_RARELY_USED, // 幜 + 0x5E5E, KANJI_RARELY_USED, // 幞 + 0x5E68, KANJI_RARELY_USED, // 幚 + 0x5E6A, KANJI_RARELY_USED, // 幪 + 0x5E6B, KANJI_RARELY_USED, // 幫 + 0x5E6C, KANJI_RARELY_USED, // 幬 + 0x5E6D, KANJI_RARELY_USED, // å¹­ + 0x5E6E, KANJI_RARELY_USED, // å¹® + 0x5E70, KANJI_RARELY_USED, // å¹° + 0x5E80, KANJI_RARELY_USED, // 庀 + 0x5E8B, KANJI_RARELY_USED, // 庋 + 0x5E8E, KANJI_RARELY_USED, // 庎 + 0x5EA2, KANJI_RARELY_USED, // 庢 + 0x5EA4, KANJI_RARELY_USED, // 庀 + 0x5EA5, KANJI_RARELY_USED, // 庥 + 0x5EA8, KANJI_RARELY_USED, // 庚 + 0x5EAA, KANJI_RARELY_USED, // 庪 + 0x5EAC, KANJI_RARELY_USED, // 庬 + 0x5EB1, KANJI_RARELY_USED, // 庱 + 0x5EB3, KANJI_RARELY_USED, // 庳 + 0x5EBD, KANJI_RARELY_USED, // 府 + 0x5EBE, KANJI_RARELY_USED, // 废 + 0x5EBF, KANJI_RARELY_USED, // 庿 + 0x5EC6, KANJI_RARELY_USED, // 廆 + 0x5ECC, KANJI_RARELY_USED, // 廌 + 0x5ECB, KANJI_RARELY_USED, // 廋 + 0x5ECE, KANJI_RARELY_USED, // 廎 + 0x5ED1, KANJI_RARELY_USED, // 廑 + 0x5ED2, KANJI_RARELY_USED, // 廒 + 0x5ED4, KANJI_RARELY_USED, // 廔 + 0x5ED5, KANJI_RARELY_USED, // 廕 + 0x5EDC, KANJI_RARELY_USED, // 廜 + 0x5EDE, KANJI_RARELY_USED, // 廞 + 0x5EE5, KANJI_RARELY_USED, // 廥 + 0x5EEB, KANJI_RARELY_USED, // 廫 + 0x5F02, KANJI_RARELY_USED, // 匂 + 0x5F06, KANJI_RARELY_USED, // 匆 + 0x5F07, KANJI_RARELY_USED, // 匇 + 0x5F08, KANJI_RARELY_USED, // 匈 + 0x5F0E, KANJI_RARELY_USED, // 匎 + 0x5F19, KANJI_RARELY_USED, // 匙 + 0x5F1C, KANJI_RARELY_USED, // 匜 + 0x5F1D, KANJI_RARELY_USED, // 匝 + 0x5F21, KANJI_RARELY_USED, // 匡 + 0x5F22, KANJI_RARELY_USED, // 匢 + 0x5F23, KANJI_RARELY_USED, // 匣 + 0x5F24, KANJI_RARELY_USED, // 匀 + 0x5F28, KANJI_RARELY_USED, // 匚 + 0x5F2B, KANJI_RARELY_USED, // 匫 + 0x5F2C, KANJI_RARELY_USED, // 匬 + 0x5F2E, KANJI_RARELY_USED, // 匮 + 0x5F30, KANJI_RARELY_USED, // 匰 + 0x5F34, KANJI_RARELY_USED, // 匎 + 0x5F36, KANJI_RARELY_USED, // 匶 + 0x5F3B, KANJI_RARELY_USED, // 医 + 0x5F3D, KANJI_RARELY_USED, // 匜 + 0x5F3F, KANJI_RARELY_USED, // 匿 + 0x5F40, KANJI_RARELY_USED, // 圀 + 0x5F44, KANJI_RARELY_USED, // 圄 + 0x5F45, KANJI_RARELY_USED, // 圅 + 0x5F47, KANJI_RARELY_USED, // 圇 + 0x5F4D, KANJI_RARELY_USED, // 圍 + 0x5F50, KANJI_RARELY_USED, // 圐 + 0x5F54, KANJI_RARELY_USED, // 圔 + 0x5F58, KANJI_RARELY_USED, // 團 + 0x5F5B, KANJI_RARELY_USED, // 圛 + 0x5F60, KANJI_RARELY_USED, // 圠 + 0x5F63, KANJI_RARELY_USED, // 圣 + 0x5F64, KANJI_RARELY_USED, // 圀 + 0x5F67, KANJI_RARELY_USED, // 圧 + 0x5F6F, KANJI_RARELY_USED, // 圯 + 0x5F72, KANJI_RARELY_USED, // 圲 + 0x5F74, KANJI_RARELY_USED, // 圎 + 0x5F75, KANJI_RARELY_USED, // 圵 + 0x5F78, KANJI_RARELY_USED, // 圞 + 0x5F7A, KANJI_RARELY_USED, // 场 + 0x5F7D, KANJI_RARELY_USED, // 圜 + 0x5F7E, KANJI_RARELY_USED, // 土 + 0x5F89, KANJI_RARELY_USED, // 埉 + 0x5F8D, KANJI_RARELY_USED, // 埍 + 0x5F8F, KANJI_RARELY_USED, // 埏 + 0x5F96, KANJI_RARELY_USED, // 埖 + 0x5F9C, KANJI_RARELY_USED, // 埜 + 0x5F9D, KANJI_RARELY_USED, // 埝 + 0x5FA2, KANJI_RARELY_USED, // 埢 + 0x5FA7, KANJI_RARELY_USED, // 埧 + 0x5FAB, KANJI_RARELY_USED, // 埫 + 0x5FA4, KANJI_RARELY_USED, // 埀 + 0x5FAC, KANJI_RARELY_USED, // 埬 + 0x5FAF, KANJI_RARELY_USED, // 埯 + 0x5FB0, KANJI_RARELY_USED, // 埰 + 0x5FB1, KANJI_RARELY_USED, // 埱 + 0x5FB8, KANJI_RARELY_USED, // 埞 + 0x5FC4, KANJI_RARELY_USED, // 忄 + 0x5FC7, KANJI_RARELY_USED, // 忇 + 0x5FC8, KANJI_RARELY_USED, // 忈 + 0x5FC9, KANJI_RARELY_USED, // 忉 + 0x5FCB, KANJI_RARELY_USED, // 忋 + 0x5FD0, KANJI_RARELY_USED, // 忐 + 0x5FD1, KANJI_RARELY_USED, // 忑 + 0x5FD2, KANJI_RARELY_USED, // 忒 + 0x5FD3, KANJI_RARELY_USED, // 忓 + 0x5FD4, KANJI_RARELY_USED, // 忔 + 0x5FDE, KANJI_RARELY_USED, // 忞 + 0x5FE1, KANJI_RARELY_USED, // å¿¡ + 0x5FE2, KANJI_RARELY_USED, // å¿¢ + 0x5FE8, KANJI_RARELY_USED, // 忚 + 0x5FE9, KANJI_RARELY_USED, // å¿© + 0x5FEA, KANJI_RARELY_USED, // 忪 + 0x5FEC, KANJI_RARELY_USED, // 忬 + 0x5FED, KANJI_RARELY_USED, // å¿­ + 0x5FEE, KANJI_RARELY_USED, // å¿® + 0x5FEF, KANJI_RARELY_USED, // 忯 + 0x5FF2, KANJI_RARELY_USED, // 忲 + 0x5FF3, KANJI_RARELY_USED, // 忳 + 0x5FF6, KANJI_RARELY_USED, // å¿¶ + 0x5FFA, KANJI_RARELY_USED, // 忺 + 0x5FFC, KANJI_RARELY_USED, // 忌 + 0x6007, KANJI_RARELY_USED, // 怇 + 0x600A, KANJI_RARELY_USED, // 怊 + 0x600D, KANJI_RARELY_USED, // 怍 + 0x6013, KANJI_RARELY_USED, // 怓 + 0x6014, KANJI_RARELY_USED, // 怔 + 0x6017, KANJI_RARELY_USED, // 怗 + 0x6018, KANJI_RARELY_USED, // 怘 + 0x601A, KANJI_RARELY_USED, // 怚 + 0x601F, KANJI_RARELY_USED, // 怟 + 0x6024, KANJI_RARELY_USED, // 怀 + 0x602D, KANJI_RARELY_USED, // 怭 + 0x6033, KANJI_RARELY_USED, // 怳 + 0x6035, KANJI_RARELY_USED, // 怵 + 0x6040, KANJI_RARELY_USED, // 恀 + 0x6047, KANJI_RARELY_USED, // 恇 + 0x6048, KANJI_RARELY_USED, // 恈 + 0x6049, KANJI_RARELY_USED, // 恉 + 0x604C, KANJI_RARELY_USED, // 恌 + 0x6051, KANJI_RARELY_USED, // 恑 + 0x6054, KANJI_RARELY_USED, // 恔 + 0x6056, KANJI_RARELY_USED, // 恖 + 0x6057, KANJI_RARELY_USED, // 恗 + 0x605D, KANJI_RARELY_USED, // 恝 + 0x6061, KANJI_RARELY_USED, // 恡 + 0x6067, KANJI_RARELY_USED, // 恧 + 0x6071, KANJI_RARELY_USED, // 恱 + 0x607E, KANJI_RARELY_USED, // 恟 + 0x607F, KANJI_RARELY_USED, // 恿 + 0x6082, KANJI_RARELY_USED, // 悂 + 0x6086, KANJI_RARELY_USED, // 悆 + 0x6088, KANJI_RARELY_USED, // 悈 + 0x608A, KANJI_RARELY_USED, // 悊 + 0x608E, KANJI_RARELY_USED, // 悎 + 0x6091, KANJI_RARELY_USED, // 悑 + 0x6093, KANJI_RARELY_USED, // 悓 + 0x6095, KANJI_RARELY_USED, // 悕 + 0x6098, KANJI_RARELY_USED, // 悘 + 0x609D, KANJI_RARELY_USED, // 悝 + 0x609E, KANJI_RARELY_USED, // 悞 + 0x60A2, KANJI_RARELY_USED, // 悢 + 0x60A4, KANJI_RARELY_USED, // æ‚€ + 0x60A5, KANJI_RARELY_USED, // 悥 + 0x60A8, KANJI_RARELY_USED, // 悚 + 0x60B0, KANJI_RARELY_USED, // 悰 + 0x60B1, KANJI_RARELY_USED, // 悱 + 0x60B7, KANJI_RARELY_USED, // 悷 + 0x60BB, KANJI_RARELY_USED, // 悻 + 0x60BE, KANJI_RARELY_USED, // 悟 + 0x60C2, KANJI_RARELY_USED, // 惂 + 0x60C4, KANJI_RARELY_USED, // 惄 + 0x60C8, KANJI_RARELY_USED, // 惈 + 0x60C9, KANJI_RARELY_USED, // 惉 + 0x60CA, KANJI_RARELY_USED, // 惊 + 0x60CB, KANJI_RARELY_USED, // 惋 + 0x60CE, KANJI_RARELY_USED, // 惎 + 0x60CF, KANJI_RARELY_USED, // 惏 + 0x60D4, KANJI_RARELY_USED, // 惔 + 0x60D5, KANJI_RARELY_USED, // 惕 + 0x60D9, KANJI_RARELY_USED, // 惙 + 0x60DB, KANJI_RARELY_USED, // 惛 + 0x60DD, KANJI_RARELY_USED, // 惝 + 0x60DE, KANJI_RARELY_USED, // 惞 + 0x60E2, KANJI_RARELY_USED, // 惢 + 0x60E5, KANJI_RARELY_USED, // 惥 + 0x60F2, KANJI_RARELY_USED, // 惲 + 0x60F5, KANJI_RARELY_USED, // 惵 + 0x60F8, KANJI_RARELY_USED, // 惞 + 0x60FC, KANJI_RARELY_USED, // 惌 + 0x60FD, KANJI_RARELY_USED, // 惜 + 0x6102, KANJI_RARELY_USED, // 愂 + 0x6107, KANJI_RARELY_USED, // 愇 + 0x610A, KANJI_RARELY_USED, // 愊 + 0x610C, KANJI_RARELY_USED, // 愌 + 0x6110, KANJI_RARELY_USED, // 愐 + 0x6111, KANJI_RARELY_USED, // 愑 + 0x6112, KANJI_RARELY_USED, // 愒 + 0x6113, KANJI_RARELY_USED, // 愓 + 0x6114, KANJI_RARELY_USED, // 愔 + 0x6116, KANJI_RARELY_USED, // 愖 + 0x6117, KANJI_RARELY_USED, // 愗 + 0x6119, KANJI_RARELY_USED, // 愙 + 0x611C, KANJI_RARELY_USED, // 愜 + 0x611E, KANJI_RARELY_USED, // 愞 + 0x6122, KANJI_RARELY_USED, // 愢 + 0x612A, KANJI_RARELY_USED, // 愪 + 0x612B, KANJI_RARELY_USED, // 愫 + 0x6130, KANJI_RARELY_USED, // 愰 + 0x6131, KANJI_RARELY_USED, // 愱 + 0x6135, KANJI_RARELY_USED, // 愵 + 0x6136, KANJI_RARELY_USED, // 愶 + 0x6137, KANJI_RARELY_USED, // 愷 + 0x6139, KANJI_RARELY_USED, // 愹 + 0x6141, KANJI_RARELY_USED, // 慁 + 0x6145, KANJI_RARELY_USED, // 慅 + 0x6146, KANJI_RARELY_USED, // 慆 + 0x6149, KANJI_RARELY_USED, // 慉 + 0x615E, KANJI_RARELY_USED, // 慞 + 0x6160, KANJI_RARELY_USED, // 慠 + 0x616C, KANJI_RARELY_USED, // 慬 + 0x6172, KANJI_RARELY_USED, // 慲 + 0x6178, KANJI_RARELY_USED, // æ…ž + 0x617B, KANJI_RARELY_USED, // 慻 + 0x617C, KANJI_RARELY_USED, // æ…Œ + 0x617F, KANJI_RARELY_USED, // 慿 + 0x6180, KANJI_RARELY_USED, // 憀 + 0x6181, KANJI_RARELY_USED, // 憁 + 0x6183, KANJI_RARELY_USED, // 憃 + 0x6184, KANJI_RARELY_USED, // 憄 + 0x618B, KANJI_RARELY_USED, // 憋 + 0x618D, KANJI_RARELY_USED, // 憍 + 0x6192, KANJI_RARELY_USED, // 憒 + 0x6193, KANJI_RARELY_USED, // 憓 + 0x6197, KANJI_RARELY_USED, // 憗 + 0x6198, KANJI_RARELY_USED, // 憘 + 0x619C, KANJI_RARELY_USED, // 憜 + 0x619D, KANJI_RARELY_USED, // 憝 + 0x619F, KANJI_RARELY_USED, // 憟 + 0x61A0, KANJI_RARELY_USED, // 憠 + 0x61A5, KANJI_RARELY_USED, // 憥 + 0x61A8, KANJI_RARELY_USED, // 憚 + 0x61AA, KANJI_RARELY_USED, // 憪 + 0x61AD, KANJI_RARELY_USED, // 憭 + 0x61B8, KANJI_RARELY_USED, // 憞 + 0x61B9, KANJI_RARELY_USED, // 憹 + 0x61BC, KANJI_RARELY_USED, // 憌 + 0x61C0, KANJI_RARELY_USED, // 懀 + 0x61C1, KANJI_RARELY_USED, // 懁 + 0x61C2, KANJI_RARELY_USED, // 懂 + 0x61CE, KANJI_RARELY_USED, // 懎 + 0x61CF, KANJI_RARELY_USED, // 懏 + 0x61D5, KANJI_RARELY_USED, // 懕 + 0x61DC, KANJI_RARELY_USED, // 懜 + 0x61DD, KANJI_RARELY_USED, // 懝 + 0x61DE, KANJI_RARELY_USED, // 懞 + 0x61DF, KANJI_RARELY_USED, // 懟 + 0x61E1, KANJI_RARELY_USED, // 懡 + 0x61E2, KANJI_RARELY_USED, // 懢 + 0x61E7, KANJI_RARELY_USED, // 懧 + 0x61E9, KANJI_RARELY_USED, // 懩 + 0x61E5, KANJI_RARELY_USED, // 懥 + 0x61EC, KANJI_RARELY_USED, // 懬 + 0x61ED, KANJI_RARELY_USED, // 懭 + 0x61EF, KANJI_RARELY_USED, // 懯 + 0x6201, KANJI_RARELY_USED, // 戁 + 0x6203, KANJI_RARELY_USED, // 戃 + 0x6204, KANJI_RARELY_USED, // 戄 + 0x6207, KANJI_RARELY_USED, // 戇 + 0x6213, KANJI_RARELY_USED, // 戓 + 0x6215, KANJI_RARELY_USED, // 戕 + 0x621C, KANJI_RARELY_USED, // 戜 + 0x6220, KANJI_RARELY_USED, // 戠 + 0x6222, KANJI_RARELY_USED, // 戢 + 0x6223, KANJI_RARELY_USED, // 戣 + 0x6227, KANJI_RARELY_USED, // 戧 + 0x6229, KANJI_RARELY_USED, // 戩 + 0x622B, KANJI_RARELY_USED, // 戫 + 0x6239, KANJI_RARELY_USED, // 戹 + 0x623D, KANJI_RARELY_USED, // 戜 + 0x6242, KANJI_RARELY_USED, // 扂 + 0x6243, KANJI_RARELY_USED, // 扃 + 0x6244, KANJI_RARELY_USED, // 扄 + 0x6246, KANJI_RARELY_USED, // 扆 + 0x624C, KANJI_RARELY_USED, // 扌 + 0x6250, KANJI_RARELY_USED, // 扐 + 0x6251, KANJI_RARELY_USED, // 扑 + 0x6252, KANJI_RARELY_USED, // 扒 + 0x6254, KANJI_RARELY_USED, // 扔 + 0x6256, KANJI_RARELY_USED, // 扖 + 0x625A, KANJI_RARELY_USED, // 扚 + 0x625C, KANJI_RARELY_USED, // 扜 + 0x6264, KANJI_RARELY_USED, // 所 + 0x626D, KANJI_RARELY_USED, // 扭 + 0x626F, KANJI_RARELY_USED, // 扯 + 0x6273, KANJI_RARELY_USED, // 扳 + 0x627A, KANJI_RARELY_USED, // 扺 + 0x627D, KANJI_RARELY_USED, // 扜 + 0x628D, KANJI_RARELY_USED, // 抍 + 0x628E, KANJI_RARELY_USED, // 抎 + 0x628F, KANJI_RARELY_USED, // 抏 + 0x6290, KANJI_RARELY_USED, // 抐 + 0x62A6, KANJI_RARELY_USED, // 把 + 0x62A8, KANJI_RARELY_USED, // 抚 + 0x62B3, KANJI_RARELY_USED, // 抳 + 0x62B6, KANJI_RARELY_USED, // 抶 + 0x62B7, KANJI_RARELY_USED, // 抷 + 0x62BA, KANJI_RARELY_USED, // 抺 + 0x62BE, KANJI_RARELY_USED, // 抟 + 0x62BF, KANJI_RARELY_USED, // 抿 + 0x62C4, KANJI_RARELY_USED, // 拄 + 0x62CE, KANJI_RARELY_USED, // 拎 + 0x62D5, KANJI_RARELY_USED, // 拕 + 0x62D6, KANJI_RARELY_USED, // 拖 + 0x62DA, KANJI_RARELY_USED, // 拚 + 0x62EA, KANJI_RARELY_USED, // 拪 + 0x62F2, KANJI_RARELY_USED, // 拲 + 0x62F4, KANJI_RARELY_USED, // 拎 + 0x62FC, KANJI_RARELY_USED, // 拌 + 0x62FD, KANJI_RARELY_USED, // 拜 + 0x6303, KANJI_RARELY_USED, // 挃 + 0x6304, KANJI_RARELY_USED, // 挄 + 0x630A, KANJI_RARELY_USED, // 挊 + 0x630B, KANJI_RARELY_USED, // 挋 + 0x630D, KANJI_RARELY_USED, // 挍 + 0x6310, KANJI_RARELY_USED, // 挐 + 0x6313, KANJI_RARELY_USED, // 挓 + 0x6316, KANJI_RARELY_USED, // 挖 + 0x6318, KANJI_RARELY_USED, // 挘 + 0x6329, KANJI_RARELY_USED, // 挩 + 0x632A, KANJI_RARELY_USED, // 挪 + 0x632D, KANJI_RARELY_USED, // 挭 + 0x6335, KANJI_RARELY_USED, // 挵 + 0x6336, KANJI_RARELY_USED, // 挶 + 0x6339, KANJI_RARELY_USED, // 挹 + 0x633C, KANJI_RARELY_USED, // 挌 + 0x6341, KANJI_RARELY_USED, // 捁 + 0x6342, KANJI_RARELY_USED, // 捂 + 0x6343, KANJI_RARELY_USED, // 捃 + 0x6344, KANJI_RARELY_USED, // 捄 + 0x6346, KANJI_RARELY_USED, // 捆 + 0x634A, KANJI_RARELY_USED, // 捊 + 0x634B, KANJI_RARELY_USED, // 捋 + 0x634E, KANJI_RARELY_USED, // 捎 + 0x6352, KANJI_RARELY_USED, // 捒 + 0x6353, KANJI_RARELY_USED, // 捓 + 0x6354, KANJI_RARELY_USED, // 捔 + 0x6358, KANJI_RARELY_USED, // 捘 + 0x635B, KANJI_RARELY_USED, // 捛 + 0x6365, KANJI_RARELY_USED, // 捥 + 0x6366, KANJI_RARELY_USED, // 捊 + 0x636C, KANJI_RARELY_USED, // 捬 + 0x636D, KANJI_RARELY_USED, // 捭 + 0x6371, KANJI_RARELY_USED, // 捱 + 0x6374, KANJI_RARELY_USED, // 捎 + 0x6375, KANJI_RARELY_USED, // 捵 + 0x6378, KANJI_RARELY_USED, // 捞 + 0x637C, KANJI_RARELY_USED, // 捌 + 0x637D, KANJI_RARELY_USED, // 捜 + 0x637F, KANJI_RARELY_USED, // 捿 + 0x6382, KANJI_RARELY_USED, // 掂 + 0x6384, KANJI_RARELY_USED, // 掄 + 0x6387, KANJI_RARELY_USED, // 掇 + 0x638A, KANJI_RARELY_USED, // 掊 + 0x6390, KANJI_RARELY_USED, // 掐 + 0x6394, KANJI_RARELY_USED, // 掔 + 0x6395, KANJI_RARELY_USED, // 掕 + 0x6399, KANJI_RARELY_USED, // 掙 + 0x639A, KANJI_RARELY_USED, // 掚 + 0x639E, KANJI_RARELY_USED, // 掞 + 0x63A4, KANJI_RARELY_USED, // 掀 + 0x63A6, KANJI_RARELY_USED, // 掊 + 0x63AD, KANJI_RARELY_USED, // 掭 + 0x63AE, KANJI_RARELY_USED, // 掮 + 0x63AF, KANJI_RARELY_USED, // 掯 + 0x63BD, KANJI_RARELY_USED, // 掜 + 0x63C1, KANJI_RARELY_USED, // 揁 + 0x63C5, KANJI_RARELY_USED, // 揅 + 0x63C8, KANJI_RARELY_USED, // 揈 + 0x63CE, KANJI_RARELY_USED, // 揎 + 0x63D1, KANJI_RARELY_USED, // 揑 + 0x63D3, KANJI_RARELY_USED, // 揓 + 0x63D4, KANJI_RARELY_USED, // 揔 + 0x63D5, KANJI_RARELY_USED, // 揕 + 0x63DC, KANJI_RARELY_USED, // 揜 + 0x63E0, KANJI_RARELY_USED, // 揠 + 0x63E5, KANJI_RARELY_USED, // 揥 + 0x63EA, KANJI_RARELY_USED, // 揪 + 0x63EC, KANJI_RARELY_USED, // 揬 + 0x63F2, KANJI_RARELY_USED, // 揲 + 0x63F3, KANJI_RARELY_USED, // 揳 + 0x63F5, KANJI_RARELY_USED, // 揵 + 0x63F8, KANJI_RARELY_USED, // 揞 + 0x63F9, KANJI_RARELY_USED, // 揹 + 0x6409, KANJI_RARELY_USED, // 搉 + 0x640A, KANJI_RARELY_USED, // 搊 + 0x6410, KANJI_RARELY_USED, // 搐 + 0x6412, KANJI_RARELY_USED, // 搒 + 0x6414, KANJI_RARELY_USED, // 搔 + 0x6418, KANJI_RARELY_USED, // 搘 + 0x641E, KANJI_RARELY_USED, // 搞 + 0x6420, KANJI_RARELY_USED, // 搠 + 0x6422, KANJI_RARELY_USED, // 搢 + 0x6424, KANJI_RARELY_USED, // 搀 + 0x6425, KANJI_RARELY_USED, // 搥 + 0x6429, KANJI_RARELY_USED, // 搩 + 0x642A, KANJI_RARELY_USED, // 搪 + 0x642F, KANJI_RARELY_USED, // 搯 + 0x6430, KANJI_RARELY_USED, // 搰 + 0x6435, KANJI_RARELY_USED, // 搵 + 0x643D, KANJI_RARELY_USED, // 搜 + 0x643F, KANJI_RARELY_USED, // 搿 + 0x644B, KANJI_RARELY_USED, // 摋 + 0x644F, KANJI_RARELY_USED, // 摏 + 0x6451, KANJI_RARELY_USED, // 摑 + 0x6452, KANJI_RARELY_USED, // 摒 + 0x6453, KANJI_RARELY_USED, // 摓 + 0x6454, KANJI_RARELY_USED, // 摔 + 0x645A, KANJI_RARELY_USED, // 摚 + 0x645B, KANJI_RARELY_USED, // 摛 + 0x645C, KANJI_RARELY_USED, // 摜 + 0x645D, KANJI_RARELY_USED, // 摝 + 0x645F, KANJI_RARELY_USED, // 摟 + 0x6460, KANJI_RARELY_USED, // 摠 + 0x6461, KANJI_RARELY_USED, // 摡 + 0x6463, KANJI_RARELY_USED, // 摣 + 0x646D, KANJI_RARELY_USED, // 摭 + 0x6473, KANJI_RARELY_USED, // 摳 + 0x6474, KANJI_RARELY_USED, // 摎 + 0x647B, KANJI_RARELY_USED, // 摻 + 0x647D, KANJI_RARELY_USED, // 摜 + 0x6485, KANJI_RARELY_USED, // 撅 + 0x6487, KANJI_RARELY_USED, // 撇 + 0x648F, KANJI_RARELY_USED, // 撏 + 0x6490, KANJI_RARELY_USED, // 撐 + 0x6491, KANJI_RARELY_USED, // 撑 + 0x6498, KANJI_RARELY_USED, // 撘 + 0x6499, KANJI_RARELY_USED, // 撙 + 0x649B, KANJI_RARELY_USED, // 撛 + 0x649D, KANJI_RARELY_USED, // 撝 + 0x649F, KANJI_RARELY_USED, // 撟 + 0x64A1, KANJI_RARELY_USED, // 撡 + 0x64A3, KANJI_RARELY_USED, // 撣 + 0x64A6, KANJI_RARELY_USED, // æ’Š + 0x64A8, KANJI_RARELY_USED, // æ’š + 0x64AC, KANJI_RARELY_USED, // 撬 + 0x64B3, KANJI_RARELY_USED, // 撳 + 0x64BD, KANJI_RARELY_USED, // æ’œ + 0x64BE, KANJI_RARELY_USED, // æ’Ÿ + 0x64BF, KANJI_RARELY_USED, // 撿 + 0x64C4, KANJI_RARELY_USED, // 擄 + 0x64C9, KANJI_RARELY_USED, // 擉 + 0x64CA, KANJI_RARELY_USED, // 擊 + 0x64CB, KANJI_RARELY_USED, // 擋 + 0x64CC, KANJI_RARELY_USED, // 擌 + 0x64CE, KANJI_RARELY_USED, // 擎 + 0x64D0, KANJI_RARELY_USED, // 擐 + 0x64D1, KANJI_RARELY_USED, // 擑 + 0x64D5, KANJI_RARELY_USED, // 擕 + 0x64D7, KANJI_RARELY_USED, // 擗 + 0x64E4, KANJI_RARELY_USED, // æ“€ + 0x64E5, KANJI_RARELY_USED, // 擥 + 0x64E9, KANJI_RARELY_USED, // 擩 + 0x64EA, KANJI_RARELY_USED, // 擪 + 0x64ED, KANJI_RARELY_USED, // 擭 + 0x64F0, KANJI_RARELY_USED, // 擰 + 0x64F5, KANJI_RARELY_USED, // 擵 + 0x64F7, KANJI_RARELY_USED, // 擷 + 0x64FB, KANJI_RARELY_USED, // 擻 + 0x64FF, KANJI_RARELY_USED, // 擿 + 0x6501, KANJI_RARELY_USED, // 攁 + 0x6504, KANJI_RARELY_USED, // 攄 + 0x6508, KANJI_RARELY_USED, // 攈 + 0x6509, KANJI_RARELY_USED, // 攉 + 0x650A, KANJI_RARELY_USED, // 攊 + 0x650F, KANJI_RARELY_USED, // 攏 + 0x6513, KANJI_RARELY_USED, // 攓 + 0x6514, KANJI_RARELY_USED, // 攔 + 0x6516, KANJI_RARELY_USED, // 攖 + 0x6519, KANJI_RARELY_USED, // 攙 + 0x651B, KANJI_RARELY_USED, // 攛 + 0x651E, KANJI_RARELY_USED, // 攞 + 0x651F, KANJI_RARELY_USED, // 攟 + 0x6522, KANJI_RARELY_USED, // 攢 + 0x6526, KANJI_RARELY_USED, // 攊 + 0x6529, KANJI_RARELY_USED, // 攩 + 0x652E, KANJI_RARELY_USED, // 攮 + 0x6531, KANJI_RARELY_USED, // 攱 + 0x653A, KANJI_RARELY_USED, // 攺 + 0x653C, KANJI_RARELY_USED, // 攌 + 0x653D, KANJI_RARELY_USED, // 攜 + 0x6543, KANJI_RARELY_USED, // 敃 + 0x6547, KANJI_RARELY_USED, // 敇 + 0x6549, KANJI_RARELY_USED, // 敉 + 0x6550, KANJI_RARELY_USED, // 敐 + 0x6552, KANJI_RARELY_USED, // 敒 + 0x6554, KANJI_RARELY_USED, // 敔 + 0x655F, KANJI_RARELY_USED, // 敟 + 0x6560, KANJI_RARELY_USED, // 敠 + 0x6567, KANJI_RARELY_USED, // 敧 + 0x656B, KANJI_RARELY_USED, // 敫 + 0x657A, KANJI_RARELY_USED, // 敺 + 0x657D, KANJI_RARELY_USED, // 敜 + 0x6581, KANJI_RARELY_USED, // 斁 + 0x6585, KANJI_RARELY_USED, // 斅 + 0x658A, KANJI_RARELY_USED, // 斊 + 0x6592, KANJI_RARELY_USED, // 斒 + 0x6595, KANJI_RARELY_USED, // 斕 + 0x6598, KANJI_RARELY_USED, // 斘 + 0x659D, KANJI_RARELY_USED, // 斝 + 0x65A0, KANJI_RARELY_USED, // 斠 + 0x65A3, KANJI_RARELY_USED, // 斣 + 0x65A6, KANJI_RARELY_USED, // æ–Š + 0x65AE, KANJI_RARELY_USED, // 斮 + 0x65B2, KANJI_RARELY_USED, // 斲 + 0x65B3, KANJI_RARELY_USED, // 斳 + 0x65B4, KANJI_RARELY_USED, // æ–Ž + 0x65BF, KANJI_RARELY_USED, // 斿 + 0x65C2, KANJI_RARELY_USED, // 旂 + 0x65C8, KANJI_RARELY_USED, // 旈 + 0x65C9, KANJI_RARELY_USED, // 旉 + 0x65CE, KANJI_RARELY_USED, // 旎 + 0x65D0, KANJI_RARELY_USED, // 旐 + 0x65D4, KANJI_RARELY_USED, // 旔 + 0x65D6, KANJI_RARELY_USED, // 旖 + 0x65D8, KANJI_RARELY_USED, // 旘 + 0x65DF, KANJI_RARELY_USED, // 旟 + 0x65F0, KANJI_RARELY_USED, // 旰 + 0x65F2, KANJI_RARELY_USED, // 旲 + 0x65F4, KANJI_RARELY_USED, // æ—Ž + 0x65F5, KANJI_RARELY_USED, // 旵 + 0x65F9, KANJI_RARELY_USED, // 旹 + 0x65FE, KANJI_RARELY_USED, // æ—Ÿ + 0x65FF, KANJI_RARELY_USED, // 旿 + 0x6600, KANJI_RARELY_USED, // 昀 + 0x6604, KANJI_RARELY_USED, // 昄 + 0x6608, KANJI_RARELY_USED, // 昈 + 0x6609, KANJI_RARELY_USED, // 昉 + 0x660D, KANJI_RARELY_USED, // 昍 + 0x6611, KANJI_RARELY_USED, // 昑 + 0x6612, KANJI_RARELY_USED, // 昒 + 0x6615, KANJI_RARELY_USED, // 昕 + 0x6616, KANJI_RARELY_USED, // 昖 + 0x661D, KANJI_RARELY_USED, // 昝 + 0x661E, KANJI_RARELY_USED, // 昞 + 0x6621, KANJI_RARELY_USED, // 昡 + 0x6622, KANJI_RARELY_USED, // 昢 + 0x6623, KANJI_RARELY_USED, // 昣 + 0x6624, KANJI_RARELY_USED, // 昀 + 0x6626, KANJI_RARELY_USED, // 昊 + 0x6629, KANJI_RARELY_USED, // 昩 + 0x662A, KANJI_RARELY_USED, // 昪 + 0x662B, KANJI_RARELY_USED, // 昫 + 0x662C, KANJI_RARELY_USED, // 昬 + 0x662E, KANJI_RARELY_USED, // 昮 + 0x6630, KANJI_RARELY_USED, // 昰 + 0x6631, KANJI_RARELY_USED, // 昱 + 0x6633, KANJI_RARELY_USED, // 昳 + 0x6639, KANJI_RARELY_USED, // 昹 + 0x6637, KANJI_RARELY_USED, // 昷 + 0x6640, KANJI_RARELY_USED, // 晀 + 0x6645, KANJI_RARELY_USED, // 晅 + 0x6646, KANJI_RARELY_USED, // 晆 + 0x664A, KANJI_RARELY_USED, // 晊 + 0x664C, KANJI_RARELY_USED, // 晌 + 0x6651, KANJI_RARELY_USED, // 晑 + 0x664E, KANJI_RARELY_USED, // 晎 + 0x6657, KANJI_RARELY_USED, // 晗 + 0x6658, KANJI_RARELY_USED, // 晘 + 0x6659, KANJI_RARELY_USED, // 晙 + 0x665B, KANJI_RARELY_USED, // 晛 + 0x665C, KANJI_RARELY_USED, // 晜 + 0x6660, KANJI_RARELY_USED, // 晠 + 0x6661, KANJI_RARELY_USED, // 晡 + 0x66FB, KANJI_RARELY_USED, // 曻 + 0x666A, KANJI_RARELY_USED, // 晪 + 0x666B, KANJI_RARELY_USED, // 晫 + 0x666C, KANJI_RARELY_USED, // 晬 + 0x667E, KANJI_RARELY_USED, // 晟 + 0x6673, KANJI_RARELY_USED, // 晳 + 0x6675, KANJI_RARELY_USED, // 晵 + 0x667F, KANJI_RARELY_USED, // 晿 + 0x6677, KANJI_RARELY_USED, // 晷 + 0x6678, KANJI_RARELY_USED, // 晞 + 0x6679, KANJI_RARELY_USED, // 晹 + 0x667B, KANJI_RARELY_USED, // 晻 + 0x6680, KANJI_RARELY_USED, // 暀 + 0x667C, KANJI_RARELY_USED, // 晌 + 0x668B, KANJI_RARELY_USED, // 暋 + 0x668C, KANJI_RARELY_USED, // 暌 + 0x668D, KANJI_RARELY_USED, // 暍 + 0x6690, KANJI_RARELY_USED, // 暐 + 0x6692, KANJI_RARELY_USED, // 暒 + 0x6699, KANJI_RARELY_USED, // 暙 + 0x669A, KANJI_RARELY_USED, // 暚 + 0x669B, KANJI_RARELY_USED, // 暛 + 0x669C, KANJI_RARELY_USED, // 暜 + 0x669F, KANJI_RARELY_USED, // 暟 + 0x66A0, KANJI_RARELY_USED, // 暠 + 0x66A4, KANJI_RARELY_USED, // 暀 + 0x66AD, KANJI_RARELY_USED, // 暭 + 0x66B1, KANJI_RARELY_USED, // 暱 + 0x66B2, KANJI_RARELY_USED, // 暲 + 0x66B5, KANJI_RARELY_USED, // 暵 + 0x66BB, KANJI_RARELY_USED, // 暻 + 0x66BF, KANJI_RARELY_USED, // 暿 + 0x66C0, KANJI_RARELY_USED, // 曀 + 0x66C2, KANJI_RARELY_USED, // 曂 + 0x66C3, KANJI_RARELY_USED, // 曃 + 0x66C8, KANJI_RARELY_USED, // 曈 + 0x66CC, KANJI_RARELY_USED, // 曌 + 0x66CE, KANJI_RARELY_USED, // 曎 + 0x66CF, KANJI_RARELY_USED, // 曏 + 0x66D4, KANJI_RARELY_USED, // 曔 + 0x66DB, KANJI_RARELY_USED, // 曛 + 0x66DF, KANJI_RARELY_USED, // 曟 + 0x66E8, KANJI_RARELY_USED, // 曚 + 0x66EB, KANJI_RARELY_USED, // 曫 + 0x66EC, KANJI_RARELY_USED, // 曬 + 0x66EE, KANJI_RARELY_USED, // 曮 + 0x66FA, KANJI_RARELY_USED, // 曺 + 0x6705, KANJI_RARELY_USED, // 朅 + 0x6707, KANJI_RARELY_USED, // 朇 + 0x670E, KANJI_RARELY_USED, // 朎 + 0x6713, KANJI_RARELY_USED, // 朓 + 0x6719, KANJI_RARELY_USED, // 朙 + 0x671C, KANJI_RARELY_USED, // 朜 + 0x6720, KANJI_RARELY_USED, // 朠 + 0x6722, KANJI_RARELY_USED, // 朢 + 0x6733, KANJI_RARELY_USED, // 朳 + 0x673E, KANJI_RARELY_USED, // 期 + 0x6745, KANJI_RARELY_USED, // 杅 + 0x6747, KANJI_RARELY_USED, // 杇 + 0x6748, KANJI_RARELY_USED, // 杈 + 0x674C, KANJI_RARELY_USED, // 杌 + 0x6754, KANJI_RARELY_USED, // 杔 + 0x6755, KANJI_RARELY_USED, // 杕 + 0x675D, KANJI_RARELY_USED, // 杝 + 0x6766, KANJI_RARELY_USED, // 杊 + 0x676C, KANJI_RARELY_USED, // 杬 + 0x676E, KANJI_RARELY_USED, // 杮 + 0x6774, KANJI_RARELY_USED, // 李 + 0x6776, KANJI_RARELY_USED, // 杶 + 0x677B, KANJI_RARELY_USED, // 杻 + 0x6781, KANJI_RARELY_USED, // 极 + 0x6784, KANJI_RARELY_USED, // 构 + 0x678E, KANJI_RARELY_USED, // 枎 + 0x678F, KANJI_RARELY_USED, // 枏 + 0x6791, KANJI_RARELY_USED, // 枑 + 0x6793, KANJI_RARELY_USED, // 枓 + 0x6796, KANJI_RARELY_USED, // 枖 + 0x6798, KANJI_RARELY_USED, // 枘 + 0x6799, KANJI_RARELY_USED, // 枙 + 0x679B, KANJI_RARELY_USED, // 枛 + 0x67B0, KANJI_RARELY_USED, // 枰 + 0x67B1, KANJI_RARELY_USED, // 枱 + 0x67B2, KANJI_RARELY_USED, // 枲 + 0x67B5, KANJI_RARELY_USED, // 枵 + 0x67BB, KANJI_RARELY_USED, // 枻 + 0x67BC, KANJI_RARELY_USED, // 枌 + 0x67BD, KANJI_RARELY_USED, // 果 + 0x67F9, KANJI_RARELY_USED, // 柹 + 0x67C0, KANJI_RARELY_USED, // 柀 + 0x67C2, KANJI_RARELY_USED, // 柂 + 0x67C3, KANJI_RARELY_USED, // 柃 + 0x67C5, KANJI_RARELY_USED, // 柅 + 0x67C8, KANJI_RARELY_USED, // 柈 + 0x67C9, KANJI_RARELY_USED, // 柉 + 0x67D2, KANJI_RARELY_USED, // 柒 + 0x67D7, KANJI_RARELY_USED, // 柗 + 0x67D9, KANJI_RARELY_USED, // 柙 + 0x67DC, KANJI_RARELY_USED, // 柜 + 0x67E1, KANJI_RARELY_USED, // 柡 + 0x67E6, KANJI_RARELY_USED, // 柊 + 0x67F0, KANJI_RARELY_USED, // 柰 + 0x67F2, KANJI_RARELY_USED, // 柲 + 0x67F6, KANJI_RARELY_USED, // 柶 + 0x67F7, KANJI_RARELY_USED, // 柷 + 0x6852, KANJI_RARELY_USED, // 桒 + 0x6814, KANJI_RARELY_USED, // 栔 + 0x6819, KANJI_RARELY_USED, // 栙 + 0x681D, KANJI_RARELY_USED, // 栝 + 0x681F, KANJI_RARELY_USED, // 栟 + 0x6828, KANJI_RARELY_USED, // æ š + 0x6827, KANJI_RARELY_USED, // æ § + 0x682C, KANJI_RARELY_USED, // æ ¬ + 0x682D, KANJI_RARELY_USED, // æ ­ + 0x682F, KANJI_RARELY_USED, // æ ¯ + 0x6830, KANJI_RARELY_USED, // æ ° + 0x6831, KANJI_RARELY_USED, // æ ± + 0x6833, KANJI_RARELY_USED, // æ ³ + 0x683B, KANJI_RARELY_USED, // æ » + 0x683F, KANJI_RARELY_USED, // æ ¿ + 0x6844, KANJI_RARELY_USED, // 桄 + 0x6845, KANJI_RARELY_USED, // 桅 + 0x684A, KANJI_RARELY_USED, // 桊 + 0x684C, KANJI_RARELY_USED, // 桌 + 0x6855, KANJI_RARELY_USED, // 桕 + 0x6857, KANJI_RARELY_USED, // 桗 + 0x6858, KANJI_RARELY_USED, // 桘 + 0x685B, KANJI_RARELY_USED, // 桛 + 0x686B, KANJI_RARELY_USED, // æ¡« + 0x686E, KANJI_RARELY_USED, // æ¡® + 0x686F, KANJI_RARELY_USED, // 桯 + 0x6870, KANJI_RARELY_USED, // æ¡° + 0x6871, KANJI_RARELY_USED, // 桱 + 0x6872, KANJI_RARELY_USED, // 桲 + 0x6875, KANJI_RARELY_USED, // 桵 + 0x6879, KANJI_RARELY_USED, // 桹 + 0x687A, KANJI_RARELY_USED, // 桺 + 0x687B, KANJI_RARELY_USED, // æ¡» + 0x687C, KANJI_RARELY_USED, // 桌 + 0x6882, KANJI_RARELY_USED, // 梂 + 0x6884, KANJI_RARELY_USED, // 梄 + 0x6886, KANJI_RARELY_USED, // 梆 + 0x6888, KANJI_RARELY_USED, // 梈 + 0x6896, KANJI_RARELY_USED, // 梖 + 0x6898, KANJI_RARELY_USED, // 梘 + 0x689A, KANJI_RARELY_USED, // 梚 + 0x689C, KANJI_RARELY_USED, // 梜 + 0x68A1, KANJI_RARELY_USED, // 梡 + 0x68A3, KANJI_RARELY_USED, // 梣 + 0x68A5, KANJI_RARELY_USED, // 梥 + 0x68A9, KANJI_RARELY_USED, // 梩 + 0x68AA, KANJI_RARELY_USED, // 梪 + 0x68AE, KANJI_RARELY_USED, // 梮 + 0x68B2, KANJI_RARELY_USED, // 梲 + 0x68BB, KANJI_RARELY_USED, // 梻 + 0x68C5, KANJI_RARELY_USED, // 棅 + 0x68C8, KANJI_RARELY_USED, // 棈 + 0x68CC, KANJI_RARELY_USED, // 棌 + 0x68CF, KANJI_RARELY_USED, // 棏 + 0x68D0, KANJI_RARELY_USED, // 棐 + 0x68D1, KANJI_RARELY_USED, // 棑 + 0x68D3, KANJI_RARELY_USED, // 棓 + 0x68D6, KANJI_RARELY_USED, // 棖 + 0x68D9, KANJI_RARELY_USED, // 棙 + 0x68DC, KANJI_RARELY_USED, // 棜 + 0x68DD, KANJI_RARELY_USED, // 棝 + 0x68E5, KANJI_RARELY_USED, // 棥 + 0x68E8, KANJI_RARELY_USED, // 棚 + 0x68EA, KANJI_RARELY_USED, // 棪 + 0x68EB, KANJI_RARELY_USED, // 棫 + 0x68EC, KANJI_RARELY_USED, // 棬 + 0x68ED, KANJI_RARELY_USED, // 棭 + 0x68F0, KANJI_RARELY_USED, // 棰 + 0x68F1, KANJI_RARELY_USED, // 棱 + 0x68F5, KANJI_RARELY_USED, // 棵 + 0x68F6, KANJI_RARELY_USED, // 棶 + 0x68FB, KANJI_RARELY_USED, // 棻 + 0x68FC, KANJI_RARELY_USED, // 棌 + 0x68FD, KANJI_RARELY_USED, // 棜 + 0x6906, KANJI_RARELY_USED, // 怆 + 0x6909, KANJI_RARELY_USED, // 怉 + 0x690A, KANJI_RARELY_USED, // 怊 + 0x6910, KANJI_RARELY_USED, // 怐 + 0x6911, KANJI_RARELY_USED, // 怑 + 0x6913, KANJI_RARELY_USED, // 怓 + 0x6916, KANJI_RARELY_USED, // 怖 + 0x6917, KANJI_RARELY_USED, // 怗 + 0x6931, KANJI_RARELY_USED, // 怱 + 0x6933, KANJI_RARELY_USED, // 怳 + 0x6935, KANJI_RARELY_USED, // 怵 + 0x6938, KANJI_RARELY_USED, // 怞 + 0x693B, KANJI_RARELY_USED, // 总 + 0x6942, KANJI_RARELY_USED, // 楂 + 0x6945, KANJI_RARELY_USED, // 楅 + 0x6949, KANJI_RARELY_USED, // 楉 + 0x694E, KANJI_RARELY_USED, // 楎 + 0x6957, KANJI_RARELY_USED, // 楗 + 0x695B, KANJI_RARELY_USED, // 楛 + 0x6963, KANJI_RARELY_USED, // 楣 + 0x6964, KANJI_RARELY_USED, // 楀 + 0x6965, KANJI_RARELY_USED, // 楥 + 0x6966, KANJI_RARELY_USED, // 楊 + 0x6968, KANJI_RARELY_USED, // 楚 + 0x6969, KANJI_RARELY_USED, // 楩 + 0x696C, KANJI_RARELY_USED, // 楬 + 0x6970, KANJI_RARELY_USED, // 楰 + 0x6971, KANJI_RARELY_USED, // 楱 + 0x6972, KANJI_RARELY_USED, // 楲 + 0x697A, KANJI_RARELY_USED, // 楺 + 0x697B, KANJI_RARELY_USED, // 楻 + 0x697F, KANJI_RARELY_USED, // 楿 + 0x6980, KANJI_RARELY_USED, // 技 + 0x698D, KANJI_RARELY_USED, // 抍 + 0x6992, KANJI_RARELY_USED, // 抒 + 0x6996, KANJI_RARELY_USED, // 抖 + 0x6998, KANJI_RARELY_USED, // 折 + 0x69A1, KANJI_RARELY_USED, // 抡 + 0x69A5, KANJI_RARELY_USED, // 报 + 0x69A6, KANJI_RARELY_USED, // 把 + 0x69A8, KANJI_RARELY_USED, // 抚 + 0x69AB, KANJI_RARELY_USED, // 披 + 0x69AD, KANJI_RARELY_USED, // 抭 + 0x69AF, KANJI_RARELY_USED, // 抯 + 0x69B7, KANJI_RARELY_USED, // 抷 + 0x69B8, KANJI_RARELY_USED, // 択 + 0x69BA, KANJI_RARELY_USED, // 抺 + 0x69BC, KANJI_RARELY_USED, // 抌 + 0x69C5, KANJI_RARELY_USED, // 槅 + 0x69C8, KANJI_RARELY_USED, // 槈 + 0x69D1, KANJI_RARELY_USED, // 槑 + 0x69D6, KANJI_RARELY_USED, // 槖 + 0x69D7, KANJI_RARELY_USED, // 槗 + 0x69E2, KANJI_RARELY_USED, // æ§¢ + 0x69E5, KANJI_RARELY_USED, // æ§¥ + 0x69EE, KANJI_RARELY_USED, // æ§® + 0x69EF, KANJI_RARELY_USED, // 槯 + 0x69F1, KANJI_RARELY_USED, // æ§± + 0x69F3, KANJI_RARELY_USED, // æ§³ + 0x69F5, KANJI_RARELY_USED, // æ§µ + 0x69FE, KANJI_RARELY_USED, // æ§Ÿ + 0x6A00, KANJI_RARELY_USED, // 暀 + 0x6A01, KANJI_RARELY_USED, // 暁 + 0x6A03, KANJI_RARELY_USED, // 暃 + 0x6A0F, KANJI_RARELY_USED, // 暏 + 0x6A11, KANJI_RARELY_USED, // æš‘ + 0x6A15, KANJI_RARELY_USED, // æš• + 0x6A1A, KANJI_RARELY_USED, // æšš + 0x6A1D, KANJI_RARELY_USED, // 暝 + 0x6A20, KANJI_RARELY_USED, // æš  + 0x6A24, KANJI_RARELY_USED, // 暀 + 0x6A28, KANJI_RARELY_USED, // æšš + 0x6A30, KANJI_RARELY_USED, // æš° + 0x6A32, KANJI_RARELY_USED, // æš² + 0x6A34, KANJI_RARELY_USED, // 暎 + 0x6A37, KANJI_RARELY_USED, // æš· + 0x6A3B, KANJI_RARELY_USED, // æš» + 0x6A3E, KANJI_RARELY_USED, // 暟 + 0x6A3F, KANJI_RARELY_USED, // æš¿ + 0x6A45, KANJI_RARELY_USED, // 橅 + 0x6A46, KANJI_RARELY_USED, // 橆 + 0x6A49, KANJI_RARELY_USED, // 橉 + 0x6A4A, KANJI_RARELY_USED, // 橊 + 0x6A4E, KANJI_RARELY_USED, // 橎 + 0x6A50, KANJI_RARELY_USED, // 橐 + 0x6A51, KANJI_RARELY_USED, // 橑 + 0x6A52, KANJI_RARELY_USED, // 橒 + 0x6A55, KANJI_RARELY_USED, // 橕 + 0x6A56, KANJI_RARELY_USED, // 橖 + 0x6A5B, KANJI_RARELY_USED, // 橛 + 0x6A64, KANJI_RARELY_USED, // æ©€ + 0x6A67, KANJI_RARELY_USED, // æ©§ + 0x6A6A, KANJI_RARELY_USED, // 橪 + 0x6A71, KANJI_RARELY_USED, // 橱 + 0x6A73, KANJI_RARELY_USED, // 橳 + 0x6A7E, KANJI_RARELY_USED, // 機 + 0x6A81, KANJI_RARELY_USED, // 檁 + 0x6A83, KANJI_RARELY_USED, // 檃 + 0x6A86, KANJI_RARELY_USED, // 檆 + 0x6A87, KANJI_RARELY_USED, // 檇 + 0x6A89, KANJI_RARELY_USED, // 檉 + 0x6A8B, KANJI_RARELY_USED, // 檋 + 0x6A91, KANJI_RARELY_USED, // 檑 + 0x6A9B, KANJI_RARELY_USED, // 檛 + 0x6A9D, KANJI_RARELY_USED, // 檝 + 0x6A9E, KANJI_RARELY_USED, // 檞 + 0x6A9F, KANJI_RARELY_USED, // 檟 + 0x6AA5, KANJI_RARELY_USED, // 檥 + 0x6AAB, KANJI_RARELY_USED, // 檫 + 0x6AAF, KANJI_RARELY_USED, // 檯 + 0x6AB0, KANJI_RARELY_USED, // 檰 + 0x6AB1, KANJI_RARELY_USED, // 檱 + 0x6AB4, KANJI_RARELY_USED, // 檎 + 0x6ABD, KANJI_RARELY_USED, // 檜 + 0x6ABE, KANJI_RARELY_USED, // 檟 + 0x6ABF, KANJI_RARELY_USED, // 檿 + 0x6AC6, KANJI_RARELY_USED, // 櫆 + 0x6AC9, KANJI_RARELY_USED, // 櫉 + 0x6AC8, KANJI_RARELY_USED, // 櫈 + 0x6ACC, KANJI_RARELY_USED, // 櫌 + 0x6AD0, KANJI_RARELY_USED, // 櫐 + 0x6AD4, KANJI_RARELY_USED, // 櫔 + 0x6AD5, KANJI_RARELY_USED, // 櫕 + 0x6AD6, KANJI_RARELY_USED, // 櫖 + 0x6ADC, KANJI_RARELY_USED, // 櫜 + 0x6ADD, KANJI_RARELY_USED, // 櫝 + 0x6AE4, KANJI_RARELY_USED, // æ«€ + 0x6AE7, KANJI_RARELY_USED, // æ«§ + 0x6AEC, KANJI_RARELY_USED, // 櫬 + 0x6AF0, KANJI_RARELY_USED, // æ«° + 0x6AF1, KANJI_RARELY_USED, // 櫱 + 0x6AF2, KANJI_RARELY_USED, // 櫲 + 0x6AFC, KANJI_RARELY_USED, // 櫌 + 0x6AFD, KANJI_RARELY_USED, // 櫜 + 0x6B02, KANJI_RARELY_USED, // 欂 + 0x6B03, KANJI_RARELY_USED, // 欃 + 0x6B06, KANJI_RARELY_USED, // 欆 + 0x6B07, KANJI_RARELY_USED, // 欇 + 0x6B09, KANJI_RARELY_USED, // 欉 + 0x6B0F, KANJI_RARELY_USED, // 欏 + 0x6B10, KANJI_RARELY_USED, // 欐 + 0x6B11, KANJI_RARELY_USED, // 欑 + 0x6B17, KANJI_RARELY_USED, // 欗 + 0x6B1B, KANJI_RARELY_USED, // 欛 + 0x6B1E, KANJI_RARELY_USED, // 欞 + 0x6B24, KANJI_RARELY_USED, // 欀 + 0x6B28, KANJI_RARELY_USED, // 欚 + 0x6B2B, KANJI_RARELY_USED, // 欫 + 0x6B2C, KANJI_RARELY_USED, // 欬 + 0x6B2F, KANJI_RARELY_USED, // 欯 + 0x6B35, KANJI_RARELY_USED, // 欵 + 0x6B36, KANJI_RARELY_USED, // 欶 + 0x6B3B, KANJI_RARELY_USED, // 欻 + 0x6B3F, KANJI_RARELY_USED, // 欿 + 0x6B46, KANJI_RARELY_USED, // 歆 + 0x6B4A, KANJI_RARELY_USED, // 歊 + 0x6B4D, KANJI_RARELY_USED, // 歍 + 0x6B52, KANJI_RARELY_USED, // 歒 + 0x6B56, KANJI_RARELY_USED, // 歖 + 0x6B58, KANJI_RARELY_USED, // 歘 + 0x6B5D, KANJI_RARELY_USED, // 歝 + 0x6B60, KANJI_RARELY_USED, // æ­  + 0x6B67, KANJI_RARELY_USED, // æ­§ + 0x6B6B, KANJI_RARELY_USED, // æ­« + 0x6B6E, KANJI_RARELY_USED, // æ­® + 0x6B70, KANJI_RARELY_USED, // æ­° + 0x6B75, KANJI_RARELY_USED, // æ­µ + 0x6B7D, KANJI_RARELY_USED, // æ­œ + 0x6B7E, KANJI_RARELY_USED, // æ­Ÿ + 0x6B82, KANJI_RARELY_USED, // 殂 + 0x6B85, KANJI_RARELY_USED, // 殅 + 0x6B97, KANJI_RARELY_USED, // 殗 + 0x6B9B, KANJI_RARELY_USED, // 殛 + 0x6B9F, KANJI_RARELY_USED, // 殟 + 0x6BA0, KANJI_RARELY_USED, // æ®  + 0x6BA2, KANJI_RARELY_USED, // 殢 + 0x6BA3, KANJI_RARELY_USED, // 殣 + 0x6BA8, KANJI_RARELY_USED, // 殚 + 0x6BA9, KANJI_RARELY_USED, // 殩 + 0x6BAC, KANJI_RARELY_USED, // 殬 + 0x6BAD, KANJI_RARELY_USED, // æ®­ + 0x6BAE, KANJI_RARELY_USED, // æ®® + 0x6BB0, KANJI_RARELY_USED, // æ®° + 0x6BB8, KANJI_RARELY_USED, // 殞 + 0x6BB9, KANJI_RARELY_USED, // 殹 + 0x6BBD, KANJI_RARELY_USED, // 殜 + 0x6BBE, KANJI_RARELY_USED, // 殟 + 0x6BC3, KANJI_RARELY_USED, // 毃 + 0x6BC4, KANJI_RARELY_USED, // 毄 + 0x6BC9, KANJI_RARELY_USED, // 毉 + 0x6BCC, KANJI_RARELY_USED, // 毌 + 0x6BD6, KANJI_RARELY_USED, // 毖 + 0x6BDA, KANJI_RARELY_USED, // 毚 + 0x6BE1, KANJI_RARELY_USED, // 毡 + 0x6BE3, KANJI_RARELY_USED, // 毣 + 0x6BE6, KANJI_RARELY_USED, // 毊 + 0x6BE7, KANJI_RARELY_USED, // 毧 + 0x6BEE, KANJI_RARELY_USED, // 毮 + 0x6BF1, KANJI_RARELY_USED, // 毱 + 0x6BF7, KANJI_RARELY_USED, // 毷 + 0x6BF9, KANJI_RARELY_USED, // 毹 + 0x6BFF, KANJI_RARELY_USED, // 毿 + 0x6C02, KANJI_RARELY_USED, // 氂 + 0x6C04, KANJI_RARELY_USED, // 氄 + 0x6C05, KANJI_RARELY_USED, // 氅 + 0x6C09, KANJI_RARELY_USED, // 氉 + 0x6C0D, KANJI_RARELY_USED, // 氍 + 0x6C0E, KANJI_RARELY_USED, // 氎 + 0x6C10, KANJI_RARELY_USED, // 氐 + 0x6C12, KANJI_RARELY_USED, // 氒 + 0x6C19, KANJI_RARELY_USED, // 氙 + 0x6C1F, KANJI_RARELY_USED, // 氟 + 0x6C26, KANJI_RARELY_USED, // æ°Š + 0x6C27, KANJI_RARELY_USED, // æ°§ + 0x6C28, KANJI_RARELY_USED, // æ°š + 0x6C2C, KANJI_RARELY_USED, // æ°¬ + 0x6C2E, KANJI_RARELY_USED, // æ°® + 0x6C33, KANJI_RARELY_USED, // æ°³ + 0x6C35, KANJI_RARELY_USED, // æ°µ + 0x6C36, KANJI_RARELY_USED, // æ°¶ + 0x6C3A, KANJI_RARELY_USED, // æ°º + 0x6C3B, KANJI_RARELY_USED, // æ°» + 0x6C3F, KANJI_RARELY_USED, // æ°¿ + 0x6C4A, KANJI_RARELY_USED, // 汊 + 0x6C4B, KANJI_RARELY_USED, // 汋 + 0x6C4D, KANJI_RARELY_USED, // 汍 + 0x6C4F, KANJI_RARELY_USED, // 汏 + 0x6C52, KANJI_RARELY_USED, // 汒 + 0x6C54, KANJI_RARELY_USED, // 汔 + 0x6C59, KANJI_RARELY_USED, // 汙 + 0x6C5B, KANJI_RARELY_USED, // 汛 + 0x6C5C, KANJI_RARELY_USED, // 汜 + 0x6C6B, KANJI_RARELY_USED, // 汫 + 0x6C6D, KANJI_RARELY_USED, // æ±­ + 0x6C6F, KANJI_RARELY_USED, // 汯 + 0x6C74, KANJI_RARELY_USED, // 汎 + 0x6C76, KANJI_RARELY_USED, // æ±¶ + 0x6C78, KANJI_RARELY_USED, // 汞 + 0x6C79, KANJI_RARELY_USED, // æ±¹ + 0x6C7B, KANJI_RARELY_USED, // æ±» + 0x6C85, KANJI_RARELY_USED, // 沅 + 0x6C86, KANJI_RARELY_USED, // 沆 + 0x6C87, KANJI_RARELY_USED, // 沇 + 0x6C89, KANJI_RARELY_USED, // 沉 + 0x6C94, KANJI_RARELY_USED, // 沔 + 0x6C95, KANJI_RARELY_USED, // 沕 + 0x6C97, KANJI_RARELY_USED, // 沗 + 0x6C98, KANJI_RARELY_USED, // 沘 + 0x6C9C, KANJI_RARELY_USED, // 沜 + 0x6C9F, KANJI_RARELY_USED, // 沟 + 0x6CB0, KANJI_RARELY_USED, // æ²° + 0x6CB2, KANJI_RARELY_USED, // æ²² + 0x6CB4, KANJI_RARELY_USED, // 沎 + 0x6CC2, KANJI_RARELY_USED, // 泂 + 0x6CC6, KANJI_RARELY_USED, // 泆 + 0x6CCD, KANJI_RARELY_USED, // 泍 + 0x6CCF, KANJI_RARELY_USED, // 泏 + 0x6CD0, KANJI_RARELY_USED, // 泐 + 0x6CD1, KANJI_RARELY_USED, // 泑 + 0x6CD2, KANJI_RARELY_USED, // 泒 + 0x6CD4, KANJI_RARELY_USED, // 泔 + 0x6CD6, KANJI_RARELY_USED, // 泖 + 0x6CDA, KANJI_RARELY_USED, // 泚 + 0x6CDC, KANJI_RARELY_USED, // 泜 + 0x6CE0, KANJI_RARELY_USED, // æ³  + 0x6CE7, KANJI_RARELY_USED, // æ³§ + 0x6CE9, KANJI_RARELY_USED, // 泩 + 0x6CEB, KANJI_RARELY_USED, // 泫 + 0x6CEC, KANJI_RARELY_USED, // 泬 + 0x6CEE, KANJI_RARELY_USED, // æ³® + 0x6CF2, KANJI_RARELY_USED, // æ³² + 0x6CF4, KANJI_RARELY_USED, // 泎 + 0x6D04, KANJI_RARELY_USED, // 掄 + 0x6D07, KANJI_RARELY_USED, // 掇 + 0x6D0A, KANJI_RARELY_USED, // 掊 + 0x6D0E, KANJI_RARELY_USED, // 掎 + 0x6D0F, KANJI_RARELY_USED, // 掏 + 0x6D11, KANJI_RARELY_USED, // 掑 + 0x6D13, KANJI_RARELY_USED, // 掓 + 0x6D1A, KANJI_RARELY_USED, // 掚 + 0x6D26, KANJI_RARELY_USED, // 掊 + 0x6D27, KANJI_RARELY_USED, // 控 + 0x6D28, KANJI_RARELY_USED, // 掚 + 0x6C67, KANJI_RARELY_USED, // æ±§ + 0x6D2E, KANJI_RARELY_USED, // 掮 + 0x6D2F, KANJI_RARELY_USED, // 掯 + 0x6D31, KANJI_RARELY_USED, // 掱 + 0x6D39, KANJI_RARELY_USED, // 掹 + 0x6D3C, KANJI_RARELY_USED, // 掌 + 0x6D3F, KANJI_RARELY_USED, // 掿 + 0x6D57, KANJI_RARELY_USED, // 浗 + 0x6D5E, KANJI_RARELY_USED, // 浞 + 0x6D5F, KANJI_RARELY_USED, // 浟 + 0x6D61, KANJI_RARELY_USED, // 浡 + 0x6D65, KANJI_RARELY_USED, // æµ¥ + 0x6D67, KANJI_RARELY_USED, // æµ§ + 0x6D6F, KANJI_RARELY_USED, // 浯 + 0x6D70, KANJI_RARELY_USED, // æµ° + 0x6D7C, KANJI_RARELY_USED, // 浌 + 0x6D82, KANJI_RARELY_USED, // 涂 + 0x6D87, KANJI_RARELY_USED, // 涇 + 0x6D91, KANJI_RARELY_USED, // 涑 + 0x6D92, KANJI_RARELY_USED, // 涒 + 0x6D94, KANJI_RARELY_USED, // 涔 + 0x6D96, KANJI_RARELY_USED, // 涖 + 0x6D97, KANJI_RARELY_USED, // 涗 + 0x6D98, KANJI_RARELY_USED, // 涘 + 0x6DAA, KANJI_RARELY_USED, // 涪 + 0x6DAC, KANJI_RARELY_USED, // 涬 + 0x6DB4, KANJI_RARELY_USED, // æ¶Ž + 0x6DB7, KANJI_RARELY_USED, // æ¶· + 0x6DB9, KANJI_RARELY_USED, // æ¶¹ + 0x6DBD, KANJI_RARELY_USED, // æ¶œ + 0x6DBF, KANJI_RARELY_USED, // æ¶¿ + 0x6DC4, KANJI_RARELY_USED, // 淄 + 0x6DC8, KANJI_RARELY_USED, // 淈 + 0x6DCA, KANJI_RARELY_USED, // 淊 + 0x6DCE, KANJI_RARELY_USED, // 淎 + 0x6DCF, KANJI_RARELY_USED, // 淏 + 0x6DD6, KANJI_RARELY_USED, // 淖 + 0x6DDB, KANJI_RARELY_USED, // 淛 + 0x6DDD, KANJI_RARELY_USED, // 淝 + 0x6DDF, KANJI_RARELY_USED, // 淟 + 0x6DE0, KANJI_RARELY_USED, // æ·  + 0x6DE2, KANJI_RARELY_USED, // æ·¢ + 0x6DE5, KANJI_RARELY_USED, // æ·¥ + 0x6DE9, KANJI_RARELY_USED, // æ·© + 0x6DEF, KANJI_RARELY_USED, // æ·¯ + 0x6DF0, KANJI_RARELY_USED, // æ·° + 0x6DF4, KANJI_RARELY_USED, // æ·Ž + 0x6DF6, KANJI_RARELY_USED, // æ·¶ + 0x6DFC, KANJI_RARELY_USED, // æ·Œ + 0x6E00, KANJI_RARELY_USED, // 枀 + 0x6E04, KANJI_RARELY_USED, // æž„ + 0x6E1E, KANJI_RARELY_USED, // æžž + 0x6E22, KANJI_RARELY_USED, // 枢 + 0x6E27, KANJI_RARELY_USED, // æž§ + 0x6E32, KANJI_RARELY_USED, // æž² + 0x6E36, KANJI_RARELY_USED, // æž¶ + 0x6E39, KANJI_RARELY_USED, // æž¹ + 0x6E3B, KANJI_RARELY_USED, // æž» + 0x6E3C, KANJI_RARELY_USED, // 枌 + 0x6E44, KANJI_RARELY_USED, // 湄 + 0x6E45, KANJI_RARELY_USED, // 湅 + 0x6E48, KANJI_RARELY_USED, // 湈 + 0x6E49, KANJI_RARELY_USED, // 湉 + 0x6E4B, KANJI_RARELY_USED, // 湋 + 0x6E4F, KANJI_RARELY_USED, // 湏 + 0x6E51, KANJI_RARELY_USED, // 湑 + 0x6E52, KANJI_RARELY_USED, // 湒 + 0x6E53, KANJI_RARELY_USED, // 湓 + 0x6E54, KANJI_RARELY_USED, // 湔 + 0x6E57, KANJI_RARELY_USED, // 湗 + 0x6E5C, KANJI_RARELY_USED, // 湜 + 0x6E5D, KANJI_RARELY_USED, // 湝 + 0x6E5E, KANJI_RARELY_USED, // 湞 + 0x6E62, KANJI_RARELY_USED, // æ¹¢ + 0x6E63, KANJI_RARELY_USED, // æ¹£ + 0x6E68, KANJI_RARELY_USED, // 湚 + 0x6E73, KANJI_RARELY_USED, // æ¹³ + 0x6E7B, KANJI_RARELY_USED, // æ¹» + 0x6E7D, KANJI_RARELY_USED, // 湜 + 0x6E8D, KANJI_RARELY_USED, // 溍 + 0x6E93, KANJI_RARELY_USED, // 溓 + 0x6E99, KANJI_RARELY_USED, // 溙 + 0x6EA0, KANJI_RARELY_USED, // 溠 + 0x6EA7, KANJI_RARELY_USED, // 溧 + 0x6EAD, KANJI_RARELY_USED, // 溭 + 0x6EAE, KANJI_RARELY_USED, // 溮 + 0x6EB1, KANJI_RARELY_USED, // 溱 + 0x6EB3, KANJI_RARELY_USED, // 溳 + 0x6EBB, KANJI_RARELY_USED, // 溻 + 0x6EBF, KANJI_RARELY_USED, // 溿 + 0x6EC0, KANJI_RARELY_USED, // 滀 + 0x6EC1, KANJI_RARELY_USED, // 滁 + 0x6EC3, KANJI_RARELY_USED, // 滃 + 0x6EC7, KANJI_RARELY_USED, // 滇 + 0x6EC8, KANJI_RARELY_USED, // 滈 + 0x6ECA, KANJI_RARELY_USED, // 滊 + 0x6ECD, KANJI_RARELY_USED, // 滍 + 0x6ECE, KANJI_RARELY_USED, // 滎 + 0x6ECF, KANJI_RARELY_USED, // 滏 + 0x6EEB, KANJI_RARELY_USED, // 滫 + 0x6EED, KANJI_RARELY_USED, // æ»­ + 0x6EEE, KANJI_RARELY_USED, // æ»® + 0x6EF9, KANJI_RARELY_USED, // 滹 + 0x6EFB, KANJI_RARELY_USED, // æ»» + 0x6EFD, KANJI_RARELY_USED, // 滜 + 0x6F04, KANJI_RARELY_USED, // 挄 + 0x6F08, KANJI_RARELY_USED, // 挈 + 0x6F0A, KANJI_RARELY_USED, // 挊 + 0x6F0C, KANJI_RARELY_USED, // 挌 + 0x6F0D, KANJI_RARELY_USED, // 挍 + 0x6F16, KANJI_RARELY_USED, // 挖 + 0x6F18, KANJI_RARELY_USED, // 挘 + 0x6F1A, KANJI_RARELY_USED, // 挚 + 0x6F1B, KANJI_RARELY_USED, // 挛 + 0x6F26, KANJI_RARELY_USED, // 挊 + 0x6F29, KANJI_RARELY_USED, // 挩 + 0x6F2A, KANJI_RARELY_USED, // 挪 + 0x6F2F, KANJI_RARELY_USED, // 振 + 0x6F30, KANJI_RARELY_USED, // 挰 + 0x6F33, KANJI_RARELY_USED, // 挳 + 0x6F36, KANJI_RARELY_USED, // 挶 + 0x6F3B, KANJI_RARELY_USED, // 挻 + 0x6F3C, KANJI_RARELY_USED, // 挌 + 0x6F2D, KANJI_RARELY_USED, // 挭 + 0x6F4F, KANJI_RARELY_USED, // 朏 + 0x6F51, KANJI_RARELY_USED, // 朑 + 0x6F52, KANJI_RARELY_USED, // 朒 + 0x6F53, KANJI_RARELY_USED, // 朓 + 0x6F57, KANJI_RARELY_USED, // 朗 + 0x6F59, KANJI_RARELY_USED, // 朙 + 0x6F5A, KANJI_RARELY_USED, // 朚 + 0x6F5D, KANJI_RARELY_USED, // 朝 + 0x6F5E, KANJI_RARELY_USED, // 朞 + 0x6F61, KANJI_RARELY_USED, // 朡 + 0x6F62, KANJI_RARELY_USED, // 朢 + 0x6F68, KANJI_RARELY_USED, // 朚 + 0x6F6C, KANJI_RARELY_USED, // 本 + 0x6F7D, KANJI_RARELY_USED, // 朜 + 0x6F7E, KANJI_RARELY_USED, // 期 + 0x6F83, KANJI_RARELY_USED, // 柃 + 0x6F87, KANJI_RARELY_USED, // 柇 + 0x6F88, KANJI_RARELY_USED, // 柈 + 0x6F8B, KANJI_RARELY_USED, // 柋 + 0x6F8C, KANJI_RARELY_USED, // 柌 + 0x6F8D, KANJI_RARELY_USED, // 柍 + 0x6F90, KANJI_RARELY_USED, // 某 + 0x6F92, KANJI_RARELY_USED, // 柒 + 0x6F93, KANJI_RARELY_USED, // 染 + 0x6F94, KANJI_RARELY_USED, // 柔 + 0x6F96, KANJI_RARELY_USED, // 柖 + 0x6F9A, KANJI_RARELY_USED, // 柚 + 0x6F9F, KANJI_RARELY_USED, // 柟 + 0x6FA0, KANJI_RARELY_USED, // 柠 + 0x6FA5, KANJI_RARELY_USED, // 查 + 0x6FA6, KANJI_RARELY_USED, // 柊 + 0x6FA7, KANJI_RARELY_USED, // 柧 + 0x6FA8, KANJI_RARELY_USED, // 柚 + 0x6FAE, KANJI_RARELY_USED, // 柮 + 0x6FAF, KANJI_RARELY_USED, // 柯 + 0x6FB0, KANJI_RARELY_USED, // 柰 + 0x6FB5, KANJI_RARELY_USED, // 柵 + 0x6FB6, KANJI_RARELY_USED, // 柶 + 0x6FBC, KANJI_RARELY_USED, // 柌 + 0x6FC5, KANJI_RARELY_USED, // 濅 + 0x6FC7, KANJI_RARELY_USED, // 濇 + 0x6FC8, KANJI_RARELY_USED, // 濈 + 0x6FCA, KANJI_RARELY_USED, // 濊 + 0x6FDA, KANJI_RARELY_USED, // 濚 + 0x6FDE, KANJI_RARELY_USED, // 濞 + 0x6FE8, KANJI_RARELY_USED, // 濚 + 0x6FE9, KANJI_RARELY_USED, // æ¿© + 0x6FF0, KANJI_RARELY_USED, // æ¿° + 0x6FF5, KANJI_RARELY_USED, // 濵 + 0x6FF9, KANJI_RARELY_USED, // 濹 + 0x6FFC, KANJI_RARELY_USED, // 濌 + 0x6FFD, KANJI_RARELY_USED, // 濜 + 0x7000, KANJI_RARELY_USED, // 瀀 + 0x7005, KANJI_RARELY_USED, // 瀅 + 0x7006, KANJI_RARELY_USED, // 瀆 + 0x7007, KANJI_RARELY_USED, // 瀇 + 0x700D, KANJI_RARELY_USED, // 瀍 + 0x7017, KANJI_RARELY_USED, // 瀗 + 0x7020, KANJI_RARELY_USED, // 瀠 + 0x7023, KANJI_RARELY_USED, // 瀣 + 0x702F, KANJI_RARELY_USED, // 瀯 + 0x7034, KANJI_RARELY_USED, // 瀮 + 0x7037, KANJI_RARELY_USED, // 瀷 + 0x7039, KANJI_RARELY_USED, // 瀹 + 0x703C, KANJI_RARELY_USED, // 瀌 + 0x7043, KANJI_RARELY_USED, // 灃 + 0x7044, KANJI_RARELY_USED, // 灄 + 0x7048, KANJI_RARELY_USED, // 灈 + 0x7049, KANJI_RARELY_USED, // 灉 + 0x704A, KANJI_RARELY_USED, // 灊 + 0x704B, KANJI_RARELY_USED, // 灋 + 0x7054, KANJI_RARELY_USED, // 灔 + 0x7055, KANJI_RARELY_USED, // 灕 + 0x705D, KANJI_RARELY_USED, // 灝 + 0x705E, KANJI_RARELY_USED, // 灞 + 0x704E, KANJI_RARELY_USED, // 灎 + 0x7064, KANJI_RARELY_USED, // 灀 + 0x7065, KANJI_RARELY_USED, // 灥 + 0x706C, KANJI_RARELY_USED, // 灬 + 0x706E, KANJI_RARELY_USED, // 灮 + 0x7075, KANJI_RARELY_USED, // 灵 + 0x7076, KANJI_RARELY_USED, // 灶 + 0x707E, KANJI_RARELY_USED, // 灟 + 0x7081, KANJI_RARELY_USED, // 炁 + 0x7085, KANJI_RARELY_USED, // 炅 + 0x7086, KANJI_RARELY_USED, // 炆 + 0x7094, KANJI_RARELY_USED, // 炔 + 0x7095, KANJI_RARELY_USED, // 炕 + 0x7096, KANJI_RARELY_USED, // 炖 + 0x7097, KANJI_RARELY_USED, // 炗 + 0x7098, KANJI_RARELY_USED, // 炘 + 0x709B, KANJI_RARELY_USED, // 炛 + 0x70A4, KANJI_RARELY_USED, // ç‚€ + 0x70AB, KANJI_RARELY_USED, // 炫 + 0x70B0, KANJI_RARELY_USED, // 炰 + 0x70B1, KANJI_RARELY_USED, // 炱 + 0x70B4, KANJI_RARELY_USED, // 炮 + 0x70B7, KANJI_RARELY_USED, // 炷 + 0x70CA, KANJI_RARELY_USED, // 烊 + 0x70D1, KANJI_RARELY_USED, // 烑 + 0x70D3, KANJI_RARELY_USED, // 烓 + 0x70D4, KANJI_RARELY_USED, // 烔 + 0x70D5, KANJI_RARELY_USED, // 烕 + 0x70D6, KANJI_RARELY_USED, // 烖 + 0x70D8, KANJI_RARELY_USED, // 烘 + 0x70DC, KANJI_RARELY_USED, // 烜 + 0x70E4, KANJI_RARELY_USED, // 烀 + 0x70FA, KANJI_RARELY_USED, // 烺 + 0x7103, KANJI_RARELY_USED, // 焃 + 0x7104, KANJI_RARELY_USED, // 焄 + 0x7105, KANJI_RARELY_USED, // 焅 + 0x7106, KANJI_RARELY_USED, // 焆 + 0x7107, KANJI_RARELY_USED, // 焇 + 0x710B, KANJI_RARELY_USED, // 焋 + 0x710C, KANJI_RARELY_USED, // 焌 + 0x710F, KANJI_RARELY_USED, // 焏 + 0x711E, KANJI_RARELY_USED, // 焞 + 0x7120, KANJI_RARELY_USED, // 焠 + 0x712B, KANJI_RARELY_USED, // 焫 + 0x712D, KANJI_RARELY_USED, // 焭 + 0x712F, KANJI_RARELY_USED, // 焯 + 0x7130, KANJI_RARELY_USED, // 焰 + 0x7131, KANJI_RARELY_USED, // 焱 + 0x7138, KANJI_RARELY_USED, // 焾 + 0x7141, KANJI_RARELY_USED, // 煁 + 0x7145, KANJI_RARELY_USED, // 煅 + 0x7146, KANJI_RARELY_USED, // 煆 + 0x7147, KANJI_RARELY_USED, // 煇 + 0x714A, KANJI_RARELY_USED, // 煊 + 0x714B, KANJI_RARELY_USED, // 煋 + 0x7150, KANJI_RARELY_USED, // 煐 + 0x7152, KANJI_RARELY_USED, // 煒 + 0x7157, KANJI_RARELY_USED, // 煗 + 0x715A, KANJI_RARELY_USED, // 煚 + 0x715C, KANJI_RARELY_USED, // 煜 + 0x715E, KANJI_RARELY_USED, // 煞 + 0x7160, KANJI_RARELY_USED, // 煠 + 0x7168, KANJI_RARELY_USED, // 煹 + 0x7179, KANJI_RARELY_USED, // 煹 + 0x7180, KANJI_RARELY_USED, // 熀 + 0x7185, KANJI_RARELY_USED, // 熅 + 0x7187, KANJI_RARELY_USED, // 熇 + 0x718C, KANJI_RARELY_USED, // 熌 + 0x7192, KANJI_RARELY_USED, // 熒 + 0x719A, KANJI_RARELY_USED, // 熚 + 0x719B, KANJI_RARELY_USED, // 熛 + 0x71A0, KANJI_RARELY_USED, // 熠 + 0x71A2, KANJI_RARELY_USED, // 熢 + 0x71AF, KANJI_RARELY_USED, // 熯 + 0x71B0, KANJI_RARELY_USED, // 熰 + 0x71B2, KANJI_RARELY_USED, // 熲 + 0x71B3, KANJI_RARELY_USED, // 熳 + 0x71BA, KANJI_RARELY_USED, // 熺 + 0x71BF, KANJI_RARELY_USED, // 熿 + 0x71C0, KANJI_RARELY_USED, // 燀 + 0x71C1, KANJI_RARELY_USED, // 燁 + 0x71C4, KANJI_RARELY_USED, // 燄 + 0x71CB, KANJI_RARELY_USED, // 燋 + 0x71CC, KANJI_RARELY_USED, // 燌 + 0x71D3, KANJI_RARELY_USED, // 燓 + 0x71D6, KANJI_RARELY_USED, // 燖 + 0x71D9, KANJI_RARELY_USED, // 燙 + 0x71DA, KANJI_RARELY_USED, // 燚 + 0x71DC, KANJI_RARELY_USED, // 燜 + 0x71F8, KANJI_RARELY_USED, // 燾 + 0x71FE, KANJI_RARELY_USED, // 營 + 0x7200, KANJI_RARELY_USED, // 爀 + 0x7207, KANJI_RARELY_USED, // 爇 + 0x7208, KANJI_RARELY_USED, // 爈 + 0x7209, KANJI_RARELY_USED, // 爉 + 0x7213, KANJI_RARELY_USED, // 爓 + 0x7217, KANJI_RARELY_USED, // 爗 + 0x721A, KANJI_RARELY_USED, // 爚 + 0x721D, KANJI_RARELY_USED, // 爝 + 0x721F, KANJI_RARELY_USED, // 爟 + 0x7224, KANJI_RARELY_USED, // 爀 + 0x722B, KANJI_RARELY_USED, // 爫 + 0x722F, KANJI_RARELY_USED, // 爯 + 0x7234, KANJI_RARELY_USED, // 爎 + 0x7238, KANJI_RARELY_USED, // 爞 + 0x7239, KANJI_RARELY_USED, // 爹 + 0x7241, KANJI_RARELY_USED, // 牁 + 0x7242, KANJI_RARELY_USED, // 牂 + 0x7243, KANJI_RARELY_USED, // 牃 + 0x7245, KANJI_RARELY_USED, // 牅 + 0x724E, KANJI_RARELY_USED, // 牎 + 0x724F, KANJI_RARELY_USED, // 牏 + 0x7250, KANJI_RARELY_USED, // 牐 + 0x7253, KANJI_RARELY_USED, // 牓 + 0x7255, KANJI_RARELY_USED, // 牕 + 0x7256, KANJI_RARELY_USED, // 牖 + 0x725A, KANJI_RARELY_USED, // 牚 + 0x725C, KANJI_RARELY_USED, // 牜 + 0x725E, KANJI_RARELY_USED, // 牞 + 0x7260, KANJI_RARELY_USED, // 牠 + 0x7263, KANJI_RARELY_USED, // 牣 + 0x7268, KANJI_RARELY_USED, // 特 + 0x726B, KANJI_RARELY_USED, // 牫 + 0x726E, KANJI_RARELY_USED, // 牮 + 0x726F, KANJI_RARELY_USED, // 牯 + 0x7271, KANJI_RARELY_USED, // 牱 + 0x7277, KANJI_RARELY_USED, // 牷 + 0x7278, KANJI_RARELY_USED, // 牾 + 0x727B, KANJI_RARELY_USED, // 牻 + 0x727C, KANJI_RARELY_USED, // 牌 + 0x727F, KANJI_RARELY_USED, // 牿 + 0x7284, KANJI_RARELY_USED, // 犄 + 0x7289, KANJI_RARELY_USED, // 犉 + 0x728D, KANJI_RARELY_USED, // 犍 + 0x728E, KANJI_RARELY_USED, // 犎 + 0x7293, KANJI_RARELY_USED, // 犓 + 0x729B, KANJI_RARELY_USED, // 犛 + 0x72A8, KANJI_RARELY_USED, // 犹 + 0x72AD, KANJI_RARELY_USED, // 犭 + 0x72AE, KANJI_RARELY_USED, // 犮 + 0x72B1, KANJI_RARELY_USED, // 犱 + 0x72B4, KANJI_RARELY_USED, // 犮 + 0x72BE, KANJI_RARELY_USED, // 犟 + 0x72C1, KANJI_RARELY_USED, // 狁 + 0x72C7, KANJI_RARELY_USED, // 狇 + 0x72C9, KANJI_RARELY_USED, // 狉 + 0x72CC, KANJI_RARELY_USED, // 狌 + 0x72D5, KANJI_RARELY_USED, // 狕 + 0x72D6, KANJI_RARELY_USED, // 狖 + 0x72D8, KANJI_RARELY_USED, // 狘 + 0x72DF, KANJI_RARELY_USED, // 狟 + 0x72E5, KANJI_RARELY_USED, // 狥 + 0x72F3, KANJI_RARELY_USED, // 狳 + 0x72F4, KANJI_RARELY_USED, // 狮 + 0x72FA, KANJI_RARELY_USED, // 狺 + 0x72FB, KANJI_RARELY_USED, // 狻 + 0x72FE, KANJI_RARELY_USED, // 狟 + 0x7302, KANJI_RARELY_USED, // 猂 + 0x7304, KANJI_RARELY_USED, // 猄 + 0x7305, KANJI_RARELY_USED, // 猅 + 0x7307, KANJI_RARELY_USED, // 猇 + 0x730B, KANJI_RARELY_USED, // 猋 + 0x730D, KANJI_RARELY_USED, // 猍 + 0x7312, KANJI_RARELY_USED, // 猒 + 0x7313, KANJI_RARELY_USED, // 猓 + 0x7318, KANJI_RARELY_USED, // 猘 + 0x7319, KANJI_RARELY_USED, // 猙 + 0x731E, KANJI_RARELY_USED, // 猞 + 0x7322, KANJI_RARELY_USED, // 猢 + 0x7324, KANJI_RARELY_USED, // 猀 + 0x7327, KANJI_RARELY_USED, // 猧 + 0x7328, KANJI_RARELY_USED, // 猹 + 0x732C, KANJI_RARELY_USED, // 猬 + 0x7331, KANJI_RARELY_USED, // 猱 + 0x7332, KANJI_RARELY_USED, // 猲 + 0x7335, KANJI_RARELY_USED, // 猵 + 0x733A, KANJI_RARELY_USED, // 猺 + 0x733B, KANJI_RARELY_USED, // 猻 + 0x733D, KANJI_RARELY_USED, // 猜 + 0x7343, KANJI_RARELY_USED, // 獃 + 0x734D, KANJI_RARELY_USED, // 獍 + 0x7350, KANJI_RARELY_USED, // 獐 + 0x7352, KANJI_RARELY_USED, // 獒 + 0x7356, KANJI_RARELY_USED, // 獖 + 0x7358, KANJI_RARELY_USED, // 獘 + 0x735D, KANJI_RARELY_USED, // 獝 + 0x735E, KANJI_RARELY_USED, // 獞 + 0x735F, KANJI_RARELY_USED, // 獟 + 0x7360, KANJI_RARELY_USED, // 獠 + 0x7366, KANJI_RARELY_USED, // 獊 + 0x7367, KANJI_RARELY_USED, // 獧 + 0x7369, KANJI_RARELY_USED, // 獩 + 0x736B, KANJI_RARELY_USED, // 獫 + 0x736C, KANJI_RARELY_USED, // 獬 + 0x736E, KANJI_RARELY_USED, // 獮 + 0x736F, KANJI_RARELY_USED, // 獯 + 0x7371, KANJI_RARELY_USED, // 獱 + 0x7377, KANJI_RARELY_USED, // 獷 + 0x7379, KANJI_RARELY_USED, // 獹 + 0x737C, KANJI_RARELY_USED, // 獌 + 0x7380, KANJI_RARELY_USED, // 玀 + 0x7381, KANJI_RARELY_USED, // 玁 + 0x7383, KANJI_RARELY_USED, // 玃 + 0x7385, KANJI_RARELY_USED, // 玅 + 0x7386, KANJI_RARELY_USED, // 玆 + 0x738E, KANJI_RARELY_USED, // 玎 + 0x7390, KANJI_RARELY_USED, // 玐 + 0x7393, KANJI_RARELY_USED, // 玓 + 0x7395, KANJI_RARELY_USED, // 玕 + 0x7397, KANJI_RARELY_USED, // 玗 + 0x7398, KANJI_RARELY_USED, // 玘 + 0x739C, KANJI_RARELY_USED, // 玜 + 0x739E, KANJI_RARELY_USED, // 玞 + 0x739F, KANJI_RARELY_USED, // 玟 + 0x73A0, KANJI_RARELY_USED, // 玠 + 0x73A2, KANJI_RARELY_USED, // 玢 + 0x73A5, KANJI_RARELY_USED, // 玥 + 0x73A6, KANJI_RARELY_USED, // 玊 + 0x73AA, KANJI_RARELY_USED, // 玪 + 0x73AB, KANJI_RARELY_USED, // 玫 + 0x73AD, KANJI_RARELY_USED, // 玭 + 0x73B5, KANJI_RARELY_USED, // 玵 + 0x73B7, KANJI_RARELY_USED, // 玷 + 0x73B9, KANJI_RARELY_USED, // 玹 + 0x73BC, KANJI_RARELY_USED, // 玌 + 0x73BD, KANJI_RARELY_USED, // 玜 + 0x73BF, KANJI_RARELY_USED, // 玿 + 0x73C5, KANJI_RARELY_USED, // 珅 + 0x73C6, KANJI_RARELY_USED, // 珆 + 0x73C9, KANJI_RARELY_USED, // 珉 + 0x73CB, KANJI_RARELY_USED, // 珋 + 0x73CC, KANJI_RARELY_USED, // 珌 + 0x73CF, KANJI_RARELY_USED, // 珏 + 0x73D2, KANJI_RARELY_USED, // 珒 + 0x73D3, KANJI_RARELY_USED, // 珓 + 0x73D6, KANJI_RARELY_USED, // 珖 + 0x73D9, KANJI_RARELY_USED, // 珙 + 0x73DD, KANJI_RARELY_USED, // 珝 + 0x73E1, KANJI_RARELY_USED, // 珡 + 0x73E3, KANJI_RARELY_USED, // 珣 + 0x73E6, KANJI_RARELY_USED, // 珊 + 0x73E7, KANJI_RARELY_USED, // 珧 + 0x73E9, KANJI_RARELY_USED, // 珩 + 0x73F4, KANJI_RARELY_USED, // 珎 + 0x73F5, KANJI_RARELY_USED, // 珵 + 0x73F7, KANJI_RARELY_USED, // 珷 + 0x73F9, KANJI_RARELY_USED, // 珹 + 0x73FA, KANJI_RARELY_USED, // 珺 + 0x73FB, KANJI_RARELY_USED, // 珻 + 0x73FD, KANJI_RARELY_USED, // 珜 + 0x73FF, KANJI_RARELY_USED, // 珿 + 0x7400, KANJI_RARELY_USED, // 琀 + 0x7401, KANJI_RARELY_USED, // 琁 + 0x7404, KANJI_RARELY_USED, // 琄 + 0x7407, KANJI_RARELY_USED, // 琇 + 0x740A, KANJI_RARELY_USED, // 琊 + 0x7411, KANJI_RARELY_USED, // 琑 + 0x741A, KANJI_RARELY_USED, // 琚 + 0x741B, KANJI_RARELY_USED, // 琛 + 0x7424, KANJI_RARELY_USED, // 琀 + 0x7426, KANJI_RARELY_USED, // 琊 + 0x7428, KANJI_RARELY_USED, // 琚 + 0x7429, KANJI_RARELY_USED, // 琩 + 0x742A, KANJI_RARELY_USED, // 琪 + 0x742B, KANJI_RARELY_USED, // 琫 + 0x742C, KANJI_RARELY_USED, // 琬 + 0x742D, KANJI_RARELY_USED, // 琭 + 0x742E, KANJI_RARELY_USED, // 琮 + 0x742F, KANJI_RARELY_USED, // 琯 + 0x7430, KANJI_RARELY_USED, // 琰 + 0x7431, KANJI_RARELY_USED, // 琱 + 0x7439, KANJI_RARELY_USED, // 琹 + 0x7440, KANJI_RARELY_USED, // 瑀 + 0x7443, KANJI_RARELY_USED, // 瑃 + 0x7444, KANJI_RARELY_USED, // 瑄 + 0x7446, KANJI_RARELY_USED, // 瑆 + 0x7447, KANJI_RARELY_USED, // 瑇 + 0x744B, KANJI_RARELY_USED, // 瑋 + 0x744D, KANJI_RARELY_USED, // 瑍 + 0x7451, KANJI_RARELY_USED, // 瑑 + 0x7452, KANJI_RARELY_USED, // 瑒 + 0x7457, KANJI_RARELY_USED, // 瑗 + 0x745D, KANJI_RARELY_USED, // 瑝 + 0x7462, KANJI_RARELY_USED, // 瑢 + 0x7466, KANJI_RARELY_USED, // 瑩 + 0x7467, KANJI_RARELY_USED, // 瑧 + 0x7468, KANJI_RARELY_USED, // 瑹 + 0x746B, KANJI_RARELY_USED, // 瑫 + 0x746D, KANJI_RARELY_USED, // 瑭 + 0x746E, KANJI_RARELY_USED, // 瑮 + 0x7471, KANJI_RARELY_USED, // 瑱 + 0x7472, KANJI_RARELY_USED, // 瑲 + 0x7480, KANJI_RARELY_USED, // 璀 + 0x7481, KANJI_RARELY_USED, // 璁 + 0x7485, KANJI_RARELY_USED, // 璅 + 0x7486, KANJI_RARELY_USED, // 璆 + 0x7487, KANJI_RARELY_USED, // 璇 + 0x7489, KANJI_RARELY_USED, // 璉 + 0x748F, KANJI_RARELY_USED, // 璏 + 0x7490, KANJI_RARELY_USED, // 璐 + 0x7491, KANJI_RARELY_USED, // 璑 + 0x7492, KANJI_RARELY_USED, // 璒 + 0x7498, KANJI_RARELY_USED, // 璘 + 0x7499, KANJI_RARELY_USED, // 璙 + 0x749A, KANJI_RARELY_USED, // 璚 + 0x749C, KANJI_RARELY_USED, // 璜 + 0x749F, KANJI_RARELY_USED, // 璟 + 0x74A0, KANJI_RARELY_USED, // 璠 + 0x74A1, KANJI_RARELY_USED, // 璡 + 0x74A3, KANJI_RARELY_USED, // 璣 + 0x74A6, KANJI_RARELY_USED, // 璩 + 0x74A8, KANJI_RARELY_USED, // 璹 + 0x74A9, KANJI_RARELY_USED, // 璩 + 0x74AA, KANJI_RARELY_USED, // 璪 + 0x74AB, KANJI_RARELY_USED, // 璫 + 0x74AE, KANJI_RARELY_USED, // 璮 + 0x74AF, KANJI_RARELY_USED, // 璯 + 0x74B1, KANJI_RARELY_USED, // 璱 + 0x74B2, KANJI_RARELY_USED, // 璲 + 0x74B5, KANJI_RARELY_USED, // 璵 + 0x74B9, KANJI_RARELY_USED, // 璹 + 0x74BB, KANJI_RARELY_USED, // 璻 + 0x74BF, KANJI_RARELY_USED, // 璿 + 0x74C8, KANJI_RARELY_USED, // 瓈 + 0x74C9, KANJI_RARELY_USED, // 瓉 + 0x74CC, KANJI_RARELY_USED, // 瓌 + 0x74D0, KANJI_RARELY_USED, // 瓐 + 0x74D3, KANJI_RARELY_USED, // 瓓 + 0x74D8, KANJI_RARELY_USED, // 瓘 + 0x74DA, KANJI_RARELY_USED, // 瓚 + 0x74DB, KANJI_RARELY_USED, // 瓛 + 0x74DE, KANJI_RARELY_USED, // 瓞 + 0x74DF, KANJI_RARELY_USED, // 瓟 + 0x74E4, KANJI_RARELY_USED, // ç“€ + 0x74E8, KANJI_RARELY_USED, // 瓹 + 0x74EA, KANJI_RARELY_USED, // 瓪 + 0x74EB, KANJI_RARELY_USED, // 瓫 + 0x74EF, KANJI_RARELY_USED, // 瓯 + 0x74F4, KANJI_RARELY_USED, // 瓮 + 0x74FA, KANJI_RARELY_USED, // 瓺 + 0x74FB, KANJI_RARELY_USED, // 瓻 + 0x74FC, KANJI_RARELY_USED, // 瓌 + 0x74FF, KANJI_RARELY_USED, // 瓿 + 0x7506, KANJI_RARELY_USED, // 甆 + 0x7512, KANJI_RARELY_USED, // 甒 + 0x7516, KANJI_RARELY_USED, // 甖 + 0x7517, KANJI_RARELY_USED, // 甗 + 0x7520, KANJI_RARELY_USED, // 甠 + 0x7521, KANJI_RARELY_USED, // 甡 + 0x7524, KANJI_RARELY_USED, // 甀 + 0x7527, KANJI_RARELY_USED, // 甧 + 0x7529, KANJI_RARELY_USED, // 甩 + 0x752A, KANJI_RARELY_USED, // 甪 + 0x752F, KANJI_RARELY_USED, // 甯 + 0x7536, KANJI_RARELY_USED, // 甶 + 0x7539, KANJI_RARELY_USED, // 甹 + 0x753D, KANJI_RARELY_USED, // 甜 + 0x753E, KANJI_RARELY_USED, // 生 + 0x753F, KANJI_RARELY_USED, // 甿 + 0x7540, KANJI_RARELY_USED, // 畀 + 0x7543, KANJI_RARELY_USED, // 畃 + 0x7547, KANJI_RARELY_USED, // 畇 + 0x7548, KANJI_RARELY_USED, // 畈 + 0x754E, KANJI_RARELY_USED, // 畎 + 0x7550, KANJI_RARELY_USED, // 畐 + 0x7552, KANJI_RARELY_USED, // 畒 + 0x7557, KANJI_RARELY_USED, // 畗 + 0x755E, KANJI_RARELY_USED, // 畞 + 0x755F, KANJI_RARELY_USED, // 畟 + 0x7561, KANJI_RARELY_USED, // 畡 + 0x756F, KANJI_RARELY_USED, // 畯 + 0x7571, KANJI_RARELY_USED, // 畱 + 0x7579, KANJI_RARELY_USED, // 畹 + 0x757A, KANJI_RARELY_USED, // 畺 + 0x757B, KANJI_RARELY_USED, // 畻 + 0x757C, KANJI_RARELY_USED, // 界 + 0x757D, KANJI_RARELY_USED, // 畜 + 0x757E, KANJI_RARELY_USED, // 畟 + 0x7581, KANJI_RARELY_USED, // 疁 + 0x7585, KANJI_RARELY_USED, // 疅 + 0x7590, KANJI_RARELY_USED, // 疐 + 0x7592, KANJI_RARELY_USED, // 疒 + 0x7593, KANJI_RARELY_USED, // 疓 + 0x7595, KANJI_RARELY_USED, // 疕 + 0x7599, KANJI_RARELY_USED, // 疙 + 0x759C, KANJI_RARELY_USED, // 疜 + 0x75A2, KANJI_RARELY_USED, // 疢 + 0x75A4, KANJI_RARELY_USED, // ç–€ + 0x75B4, KANJI_RARELY_USED, // 疮 + 0x75BA, KANJI_RARELY_USED, // 疺 + 0x75BF, KANJI_RARELY_USED, // 疿 + 0x75C0, KANJI_RARELY_USED, // 痀 + 0x75C1, KANJI_RARELY_USED, // 痁 + 0x75C4, KANJI_RARELY_USED, // 痄 + 0x75C6, KANJI_RARELY_USED, // 痆 + 0x75CC, KANJI_RARELY_USED, // 痌 + 0x75CE, KANJI_RARELY_USED, // 痎 + 0x75CF, KANJI_RARELY_USED, // 痏 + 0x75D7, KANJI_RARELY_USED, // 痗 + 0x75DC, KANJI_RARELY_USED, // 痜 + 0x75DF, KANJI_RARELY_USED, // 痟 + 0x75E0, KANJI_RARELY_USED, // 痠 + 0x75E1, KANJI_RARELY_USED, // 痡 + 0x75E4, KANJI_RARELY_USED, // ç—€ + 0x75E7, KANJI_RARELY_USED, // 痧 + 0x75EC, KANJI_RARELY_USED, // 痬 + 0x75EE, KANJI_RARELY_USED, // 痮 + 0x75EF, KANJI_RARELY_USED, // 痯 + 0x75F1, KANJI_RARELY_USED, // 痱 + 0x75F9, KANJI_RARELY_USED, // 痹 + 0x7600, KANJI_RARELY_USED, // 瘀 + 0x7602, KANJI_RARELY_USED, // 瘂 + 0x7603, KANJI_RARELY_USED, // 瘃 + 0x7604, KANJI_RARELY_USED, // 瘄 + 0x7607, KANJI_RARELY_USED, // 瘇 + 0x7608, KANJI_RARELY_USED, // 瘈 + 0x760A, KANJI_RARELY_USED, // 瘊 + 0x760C, KANJI_RARELY_USED, // 瘌 + 0x760F, KANJI_RARELY_USED, // 瘏 + 0x7612, KANJI_RARELY_USED, // 瘒 + 0x7613, KANJI_RARELY_USED, // 瘓 + 0x7615, KANJI_RARELY_USED, // 瘕 + 0x7616, KANJI_RARELY_USED, // 瘖 + 0x7619, KANJI_RARELY_USED, // 瘙 + 0x761B, KANJI_RARELY_USED, // 瘛 + 0x761C, KANJI_RARELY_USED, // 瘜 + 0x761D, KANJI_RARELY_USED, // 瘝 + 0x761E, KANJI_RARELY_USED, // 瘞 + 0x7623, KANJI_RARELY_USED, // 瘣 + 0x7625, KANJI_RARELY_USED, // 瘥 + 0x7626, KANJI_RARELY_USED, // 瘊 + 0x7629, KANJI_RARELY_USED, // 瘩 + 0x762D, KANJI_RARELY_USED, // 瘭 + 0x7632, KANJI_RARELY_USED, // 瘲 + 0x7633, KANJI_RARELY_USED, // 瘳 + 0x7635, KANJI_RARELY_USED, // 瘵 + 0x7638, KANJI_RARELY_USED, // 瘞 + 0x7639, KANJI_RARELY_USED, // 瘹 + 0x763A, KANJI_RARELY_USED, // 瘺 + 0x763C, KANJI_RARELY_USED, // 瘌 + 0x764A, KANJI_RARELY_USED, // 癊 + 0x7640, KANJI_RARELY_USED, // 癀 + 0x7641, KANJI_RARELY_USED, // 癁 + 0x7643, KANJI_RARELY_USED, // 癃 + 0x7644, KANJI_RARELY_USED, // 癄 + 0x7645, KANJI_RARELY_USED, // 癅 + 0x7649, KANJI_RARELY_USED, // 癉 + 0x764B, KANJI_RARELY_USED, // 癋 + 0x7655, KANJI_RARELY_USED, // 癕 + 0x7659, KANJI_RARELY_USED, // 癙 + 0x765F, KANJI_RARELY_USED, // 癟 + 0x7664, KANJI_RARELY_USED, // 癀 + 0x7665, KANJI_RARELY_USED, // 癥 + 0x766D, KANJI_RARELY_USED, // 癭 + 0x766E, KANJI_RARELY_USED, // 癮 + 0x766F, KANJI_RARELY_USED, // 癯 + 0x7671, KANJI_RARELY_USED, // 癱 + 0x7674, KANJI_RARELY_USED, // 癮 + 0x7681, KANJI_RARELY_USED, // 皁 + 0x7685, KANJI_RARELY_USED, // 皅 + 0x768C, KANJI_RARELY_USED, // 皌 + 0x768D, KANJI_RARELY_USED, // 皍 + 0x7695, KANJI_RARELY_USED, // 皕 + 0x769B, KANJI_RARELY_USED, // 皛 + 0x769C, KANJI_RARELY_USED, // 皜 + 0x769D, KANJI_RARELY_USED, // 皝 + 0x769F, KANJI_RARELY_USED, // 皟 + 0x76A0, KANJI_RARELY_USED, // 皠 + 0x76A2, KANJI_RARELY_USED, // 皢 + 0x76A3, KANJI_RARELY_USED, // 皣 + 0x76A4, KANJI_RARELY_USED, // 皀 + 0x76A5, KANJI_RARELY_USED, // 皥 + 0x76A6, KANJI_RARELY_USED, // 皩 + 0x76A7, KANJI_RARELY_USED, // 皧 + 0x76A8, KANJI_RARELY_USED, // 皹 + 0x76AA, KANJI_RARELY_USED, // 皪 + 0x76AD, KANJI_RARELY_USED, // 皭 + 0x76BD, KANJI_RARELY_USED, // çšœ + 0x76C1, KANJI_RARELY_USED, // 盁 + 0x76C5, KANJI_RARELY_USED, // 盅 + 0x76C9, KANJI_RARELY_USED, // 盉 + 0x76CB, KANJI_RARELY_USED, // 盋 + 0x76CC, KANJI_RARELY_USED, // 盌 + 0x76CE, KANJI_RARELY_USED, // 盎 + 0x76D4, KANJI_RARELY_USED, // 盔 + 0x76D9, KANJI_RARELY_USED, // 盙 + 0x76E0, KANJI_RARELY_USED, // 盠 + 0x76E6, KANJI_RARELY_USED, // 盩 + 0x76E8, KANJI_RARELY_USED, // 盹 + 0x76EC, KANJI_RARELY_USED, // 盬 + 0x76F0, KANJI_RARELY_USED, // 盰 + 0x76F1, KANJI_RARELY_USED, // 盱 + 0x76F6, KANJI_RARELY_USED, // 盶 + 0x76F9, KANJI_RARELY_USED, // 盹 + 0x76FC, KANJI_RARELY_USED, // 盌 + 0x7700, KANJI_RARELY_USED, // 眀 + 0x7706, KANJI_RARELY_USED, // 眆 + 0x770A, KANJI_RARELY_USED, // 眊 + 0x770E, KANJI_RARELY_USED, // 眎 + 0x7712, KANJI_RARELY_USED, // 眒 + 0x7714, KANJI_RARELY_USED, // 眔 + 0x7715, KANJI_RARELY_USED, // 眕 + 0x7717, KANJI_RARELY_USED, // 眗 + 0x7719, KANJI_RARELY_USED, // 眙 + 0x771A, KANJI_RARELY_USED, // 眚 + 0x771C, KANJI_RARELY_USED, // 眜 + 0x7722, KANJI_RARELY_USED, // 眢 + 0x7728, KANJI_RARELY_USED, // 眹 + 0x772D, KANJI_RARELY_USED, // 眭 + 0x772E, KANJI_RARELY_USED, // 眮 + 0x772F, KANJI_RARELY_USED, // 眯 + 0x7734, KANJI_RARELY_USED, // 眮 + 0x7735, KANJI_RARELY_USED, // 眵 + 0x7736, KANJI_RARELY_USED, // 眶 + 0x7739, KANJI_RARELY_USED, // 眹 + 0x773D, KANJI_RARELY_USED, // 眜 + 0x773E, KANJI_RARELY_USED, // 真 + 0x7742, KANJI_RARELY_USED, // 睂 + 0x7745, KANJI_RARELY_USED, // 睅 + 0x7746, KANJI_RARELY_USED, // 睆 + 0x774A, KANJI_RARELY_USED, // 睊 + 0x774D, KANJI_RARELY_USED, // 睍 + 0x774E, KANJI_RARELY_USED, // 睎 + 0x774F, KANJI_RARELY_USED, // 睏 + 0x7752, KANJI_RARELY_USED, // 睒 + 0x7756, KANJI_RARELY_USED, // 睖 + 0x7757, KANJI_RARELY_USED, // 睗 + 0x775C, KANJI_RARELY_USED, // 睜 + 0x775E, KANJI_RARELY_USED, // 睞 + 0x775F, KANJI_RARELY_USED, // 睟 + 0x7760, KANJI_RARELY_USED, // 睠 + 0x7762, KANJI_RARELY_USED, // 睢 + 0x7764, KANJI_RARELY_USED, // 着 + 0x7767, KANJI_RARELY_USED, // 睧 + 0x776A, KANJI_RARELY_USED, // 睪 + 0x776C, KANJI_RARELY_USED, // 睬 + 0x7770, KANJI_RARELY_USED, // 睰 + 0x7772, KANJI_RARELY_USED, // 睲 + 0x7773, KANJI_RARELY_USED, // 睳 + 0x7774, KANJI_RARELY_USED, // 睎 + 0x777A, KANJI_RARELY_USED, // 睺 + 0x777D, KANJI_RARELY_USED, // 睜 + 0x7780, KANJI_RARELY_USED, // 瞀 + 0x7784, KANJI_RARELY_USED, // 瞄 + 0x778C, KANJI_RARELY_USED, // 瞌 + 0x778D, KANJI_RARELY_USED, // 瞍 + 0x7794, KANJI_RARELY_USED, // 瞔 + 0x7795, KANJI_RARELY_USED, // 瞕 + 0x7796, KANJI_RARELY_USED, // 瞖 + 0x779A, KANJI_RARELY_USED, // 瞚 + 0x779F, KANJI_RARELY_USED, // 瞟 + 0x77A2, KANJI_RARELY_USED, // 瞢 + 0x77A7, KANJI_RARELY_USED, // 瞧 + 0x77AA, KANJI_RARELY_USED, // 瞪 + 0x77AE, KANJI_RARELY_USED, // 瞮 + 0x77AF, KANJI_RARELY_USED, // 瞯 + 0x77B1, KANJI_RARELY_USED, // 瞱 + 0x77B5, KANJI_RARELY_USED, // 瞵 + 0x77BE, KANJI_RARELY_USED, // 瞟 + 0x77C3, KANJI_RARELY_USED, // 矃 + 0x77C9, KANJI_RARELY_USED, // 矉 + 0x77D1, KANJI_RARELY_USED, // 矑 + 0x77D2, KANJI_RARELY_USED, // 矒 + 0x77D5, KANJI_RARELY_USED, // 矕 + 0x77D9, KANJI_RARELY_USED, // 矙 + 0x77DE, KANJI_RARELY_USED, // 矞 + 0x77DF, KANJI_RARELY_USED, // 矟 + 0x77E0, KANJI_RARELY_USED, // 矠 + 0x77E4, KANJI_RARELY_USED, // 矀 + 0x77E6, KANJI_RARELY_USED, // 矩 + 0x77EA, KANJI_RARELY_USED, // 矪 + 0x77EC, KANJI_RARELY_USED, // 矬 + 0x77F0, KANJI_RARELY_USED, // 矰 + 0x77F1, KANJI_RARELY_USED, // 矱 + 0x77F4, KANJI_RARELY_USED, // 矮 + 0x77F8, KANJI_RARELY_USED, // 矾 + 0x77FB, KANJI_RARELY_USED, // 矻 + 0x7805, KANJI_RARELY_USED, // 砅 + 0x7806, KANJI_RARELY_USED, // 砆 + 0x7809, KANJI_RARELY_USED, // 砉 + 0x780D, KANJI_RARELY_USED, // 砍 + 0x780E, KANJI_RARELY_USED, // 砎 + 0x7811, KANJI_RARELY_USED, // 砑 + 0x781D, KANJI_RARELY_USED, // 砝 + 0x7821, KANJI_RARELY_USED, // ç ¡ + 0x7822, KANJI_RARELY_USED, // ç ¢ + 0x7823, KANJI_RARELY_USED, // ç £ + 0x782D, KANJI_RARELY_USED, // ç ­ + 0x782E, KANJI_RARELY_USED, // ç ® + 0x7830, KANJI_RARELY_USED, // ç ° + 0x7835, KANJI_RARELY_USED, // ç µ + 0x7837, KANJI_RARELY_USED, // ç · + 0x7843, KANJI_RARELY_USED, // 硃 + 0x7844, KANJI_RARELY_USED, // 硄 + 0x7847, KANJI_RARELY_USED, // 硇 + 0x7848, KANJI_RARELY_USED, // 硈 + 0x784C, KANJI_RARELY_USED, // 硌 + 0x784E, KANJI_RARELY_USED, // 硎 + 0x7852, KANJI_RARELY_USED, // 硒 + 0x785C, KANJI_RARELY_USED, // 硜 + 0x785E, KANJI_RARELY_USED, // 硞 + 0x7860, KANJI_RARELY_USED, // ç¡  + 0x7861, KANJI_RARELY_USED, // ç¡¡ + 0x7863, KANJI_RARELY_USED, // ç¡£ + 0x7864, KANJI_RARELY_USED, // ç¡€ + 0x7868, KANJI_RARELY_USED, // 硚 + 0x786A, KANJI_RARELY_USED, // 硪 + 0x786E, KANJI_RARELY_USED, // ç¡® + 0x787A, KANJI_RARELY_USED, // 硺 + 0x787E, KANJI_RARELY_USED, // 硟 + 0x788A, KANJI_RARELY_USED, // 碊 + 0x788F, KANJI_RARELY_USED, // 碏 + 0x7894, KANJI_RARELY_USED, // 碔 + 0x7898, KANJI_RARELY_USED, // 碘 + 0x78A1, KANJI_RARELY_USED, // 碡 + 0x789D, KANJI_RARELY_USED, // 碝 + 0x789E, KANJI_RARELY_USED, // 碞 + 0x789F, KANJI_RARELY_USED, // 碟 + 0x78A4, KANJI_RARELY_USED, // 碀 + 0x78A8, KANJI_RARELY_USED, // 碚 + 0x78AC, KANJI_RARELY_USED, // 碬 + 0x78AD, KANJI_RARELY_USED, // 碭 + 0x78B0, KANJI_RARELY_USED, // 碰 + 0x78B1, KANJI_RARELY_USED, // 碱 + 0x78B2, KANJI_RARELY_USED, // 碲 + 0x78B3, KANJI_RARELY_USED, // 碳 + 0x78BB, KANJI_RARELY_USED, // 碻 + 0x78BD, KANJI_RARELY_USED, // 碜 + 0x78BF, KANJI_RARELY_USED, // 碿 + 0x78C7, KANJI_RARELY_USED, // 磇 + 0x78C8, KANJI_RARELY_USED, // 磈 + 0x78C9, KANJI_RARELY_USED, // 磉 + 0x78CC, KANJI_RARELY_USED, // 磌 + 0x78CE, KANJI_RARELY_USED, // 磎 + 0x78D2, KANJI_RARELY_USED, // 磒 + 0x78D3, KANJI_RARELY_USED, // 磓 + 0x78D5, KANJI_RARELY_USED, // 磕 + 0x78D6, KANJI_RARELY_USED, // 磖 + 0x78E4, KANJI_RARELY_USED, // 磀 + 0x78DB, KANJI_RARELY_USED, // 磛 + 0x78DF, KANJI_RARELY_USED, // 磟 + 0x78E0, KANJI_RARELY_USED, // 磠 + 0x78E1, KANJI_RARELY_USED, // 磡 + 0x78E6, KANJI_RARELY_USED, // 磊 + 0x78EA, KANJI_RARELY_USED, // 磪 + 0x78F2, KANJI_RARELY_USED, // 磲 + 0x78F3, KANJI_RARELY_USED, // 磳 + 0x7900, KANJI_RARELY_USED, // 瀀 + 0x78F6, KANJI_RARELY_USED, // 磶 + 0x78F7, KANJI_RARELY_USED, // 磷 + 0x78FA, KANJI_RARELY_USED, // 磺 + 0x78FB, KANJI_RARELY_USED, // 磻 + 0x78FF, KANJI_RARELY_USED, // 磿 + 0x7906, KANJI_RARELY_USED, // 瀆 + 0x790C, KANJI_RARELY_USED, // 瀌 + 0x7910, KANJI_RARELY_USED, // 瀐 + 0x791A, KANJI_RARELY_USED, // 瀚 + 0x791C, KANJI_RARELY_USED, // 瀜 + 0x791E, KANJI_RARELY_USED, // 瀞 + 0x791F, KANJI_RARELY_USED, // 瀟 + 0x7920, KANJI_RARELY_USED, // 瀠 + 0x7925, KANJI_RARELY_USED, // 瀥 + 0x7927, KANJI_RARELY_USED, // 瀧 + 0x7929, KANJI_RARELY_USED, // 瀩 + 0x792D, KANJI_RARELY_USED, // 瀭 + 0x7931, KANJI_RARELY_USED, // 瀱 + 0x7934, KANJI_RARELY_USED, // 瀎 + 0x7935, KANJI_RARELY_USED, // 瀵 + 0x793B, KANJI_RARELY_USED, // 瀻 + 0x793D, KANJI_RARELY_USED, // 瀜 + 0x793F, KANJI_RARELY_USED, // 瀿 + 0x7944, KANJI_RARELY_USED, // 祄 + 0x7945, KANJI_RARELY_USED, // 祅 + 0x7946, KANJI_RARELY_USED, // 祆 + 0x794A, KANJI_RARELY_USED, // 祊 + 0x794B, KANJI_RARELY_USED, // 祋 + 0x794F, KANJI_RARELY_USED, // 祏 + 0x7951, KANJI_RARELY_USED, // 祑 + 0x7954, KANJI_RARELY_USED, // 祔 + 0x7958, KANJI_RARELY_USED, // 祘 + 0x795B, KANJI_RARELY_USED, // 祛 + 0x795C, KANJI_RARELY_USED, // 祜 + 0x7967, KANJI_RARELY_USED, // 祧 + 0x7969, KANJI_RARELY_USED, // 祩 + 0x796B, KANJI_RARELY_USED, // 祫 + 0x7972, KANJI_RARELY_USED, // 祲 + 0x7979, KANJI_RARELY_USED, // 祹 + 0x797B, KANJI_RARELY_USED, // 祻 + 0x797C, KANJI_RARELY_USED, // 祌 + 0x797E, KANJI_RARELY_USED, // 祟 + 0x798B, KANJI_RARELY_USED, // 穋 + 0x798C, KANJI_RARELY_USED, // 穌 + 0x7991, KANJI_RARELY_USED, // 穑 + 0x7993, KANJI_RARELY_USED, // 穓 + 0x7994, KANJI_RARELY_USED, // 穔 + 0x7995, KANJI_RARELY_USED, // 穕 + 0x7996, KANJI_RARELY_USED, // 穖 + 0x7998, KANJI_RARELY_USED, // 犘 + 0x799B, KANJI_RARELY_USED, // 穛 + 0x799C, KANJI_RARELY_USED, // 穜 + 0x79A1, KANJI_RARELY_USED, // 犡 + 0x79A8, KANJI_RARELY_USED, // 犚 + 0x79A9, KANJI_RARELY_USED, // 犩 + 0x79AB, KANJI_RARELY_USED, // 犫 + 0x79AF, KANJI_RARELY_USED, // 犯 + 0x79B1, KANJI_RARELY_USED, // 犱 + 0x79B4, KANJI_RARELY_USED, // 犎 + 0x79B8, KANJI_RARELY_USED, // 犞 + 0x79BB, KANJI_RARELY_USED, // 犻 + 0x79C2, KANJI_RARELY_USED, // 秂 + 0x79C4, KANJI_RARELY_USED, // 秄 + 0x79C7, KANJI_RARELY_USED, // 秇 + 0x79C8, KANJI_RARELY_USED, // 秈 + 0x79CA, KANJI_RARELY_USED, // 秊 + 0x79CF, KANJI_RARELY_USED, // 秏 + 0x79D4, KANJI_RARELY_USED, // 秔 + 0x79D6, KANJI_RARELY_USED, // 秖 + 0x79DA, KANJI_RARELY_USED, // 秚 + 0x79DD, KANJI_RARELY_USED, // 秝 + 0x79DE, KANJI_RARELY_USED, // 秞 + 0x79E0, KANJI_RARELY_USED, // ç§  + 0x79E2, KANJI_RARELY_USED, // ç§¢ + 0x79E5, KANJI_RARELY_USED, // ç§¥ + 0x79EA, KANJI_RARELY_USED, // 秪 + 0x79EB, KANJI_RARELY_USED, // ç§« + 0x79ED, KANJI_RARELY_USED, // ç§­ + 0x79F1, KANJI_RARELY_USED, // ç§± + 0x79F8, KANJI_RARELY_USED, // ç§ž + 0x79FC, KANJI_RARELY_USED, // ç§Œ + 0x7A02, KANJI_RARELY_USED, // 繂 + 0x7A03, KANJI_RARELY_USED, // 皃 + 0x7A07, KANJI_RARELY_USED, // 繇 + 0x7A09, KANJI_RARELY_USED, // 繉 + 0x7A0A, KANJI_RARELY_USED, // 繊 + 0x7A0C, KANJI_RARELY_USED, // 繌 + 0x7A11, KANJI_RARELY_USED, // 繑 + 0x7A15, KANJI_RARELY_USED, // 繕 + 0x7A1B, KANJI_RARELY_USED, // 繛 + 0x7A1E, KANJI_RARELY_USED, // 皞 + 0x7A21, KANJI_RARELY_USED, // çš¡ + 0x7A27, KANJI_RARELY_USED, // çš§ + 0x7A2B, KANJI_RARELY_USED, // çš« + 0x7A2D, KANJI_RARELY_USED, // çš­ + 0x7A2F, KANJI_RARELY_USED, // 皯 + 0x7A30, KANJI_RARELY_USED, // çš° + 0x7A34, KANJI_RARELY_USED, // 皎 + 0x7A35, KANJI_RARELY_USED, // çšµ + 0x7A38, KANJI_RARELY_USED, // çšž + 0x7A39, KANJI_RARELY_USED, // çš¹ + 0x7A3A, KANJI_RARELY_USED, // 皺 + 0x7A44, KANJI_RARELY_USED, // 穄 + 0x7A45, KANJI_RARELY_USED, // 穅 + 0x7A47, KANJI_RARELY_USED, // 穇 + 0x7A48, KANJI_RARELY_USED, // 穈 + 0x7A4C, KANJI_RARELY_USED, // 穌 + 0x7A55, KANJI_RARELY_USED, // 穕 + 0x7A56, KANJI_RARELY_USED, // 穖 + 0x7A59, KANJI_RARELY_USED, // 穙 + 0x7A5C, KANJI_RARELY_USED, // 穜 + 0x7A5D, KANJI_RARELY_USED, // 穝 + 0x7A5F, KANJI_RARELY_USED, // 穟 + 0x7A60, KANJI_RARELY_USED, // ç©  + 0x7A65, KANJI_RARELY_USED, // ç©¥ + 0x7A67, KANJI_RARELY_USED, // ç©§ + 0x7A6A, KANJI_RARELY_USED, // 穪 + 0x7A6D, KANJI_RARELY_USED, // ç©­ + 0x7A75, KANJI_RARELY_USED, // 穵 + 0x7A78, KANJI_RARELY_USED, // 穞 + 0x7A7E, KANJI_RARELY_USED, // 穟 + 0x7A80, KANJI_RARELY_USED, // 窀 + 0x7A82, KANJI_RARELY_USED, // 窂 + 0x7A85, KANJI_RARELY_USED, // 窅 + 0x7A86, KANJI_RARELY_USED, // 窆 + 0x7A8A, KANJI_RARELY_USED, // 窊 + 0x7A8B, KANJI_RARELY_USED, // 窋 + 0x7A90, KANJI_RARELY_USED, // 窐 + 0x7A91, KANJI_RARELY_USED, // 窑 + 0x7A94, KANJI_RARELY_USED, // 窔 + 0x7A9E, KANJI_RARELY_USED, // 窞 + 0x7AA0, KANJI_RARELY_USED, // 窠 + 0x7AA3, KANJI_RARELY_USED, // 窣 + 0x7AAC, KANJI_RARELY_USED, // 窬 + 0x7AB3, KANJI_RARELY_USED, // 窳 + 0x7AB5, KANJI_RARELY_USED, // 窵 + 0x7AB9, KANJI_RARELY_USED, // 窹 + 0x7ABB, KANJI_RARELY_USED, // 窻 + 0x7ABC, KANJI_RARELY_USED, // 窌 + 0x7AC6, KANJI_RARELY_USED, // 竆 + 0x7AC9, KANJI_RARELY_USED, // 竉 + 0x7ACC, KANJI_RARELY_USED, // 竌 + 0x7ACE, KANJI_RARELY_USED, // 竎 + 0x7AD1, KANJI_RARELY_USED, // 竑 + 0x7ADB, KANJI_RARELY_USED, // 竛 + 0x7AE8, KANJI_RARELY_USED, // 竚 + 0x7AE9, KANJI_RARELY_USED, // ç«© + 0x7AEB, KANJI_RARELY_USED, // ç«« + 0x7AEC, KANJI_RARELY_USED, // 竬 + 0x7AF1, KANJI_RARELY_USED, // 竱 + 0x7AF4, KANJI_RARELY_USED, // 竎 + 0x7AFB, KANJI_RARELY_USED, // ç«» + 0x7AFD, KANJI_RARELY_USED, // 竜 + 0x7AFE, KANJI_RARELY_USED, // 竟 + 0x7B07, KANJI_RARELY_USED, // 笇 + 0x7B14, KANJI_RARELY_USED, // 笔 + 0x7B1F, KANJI_RARELY_USED, // 笟 + 0x7B23, KANJI_RARELY_USED, // 笣 + 0x7B27, KANJI_RARELY_USED, // 笧 + 0x7B29, KANJI_RARELY_USED, // 笩 + 0x7B2A, KANJI_RARELY_USED, // 笪 + 0x7B2B, KANJI_RARELY_USED, // 笫 + 0x7B2D, KANJI_RARELY_USED, // 笭 + 0x7B2E, KANJI_RARELY_USED, // 笮 + 0x7B2F, KANJI_RARELY_USED, // 笯 + 0x7B30, KANJI_RARELY_USED, // 笰 + 0x7B31, KANJI_RARELY_USED, // 笱 + 0x7B34, KANJI_RARELY_USED, // 笎 + 0x7B3D, KANJI_RARELY_USED, // 笜 + 0x7B3F, KANJI_RARELY_USED, // 笿 + 0x7B40, KANJI_RARELY_USED, // 筀 + 0x7B41, KANJI_RARELY_USED, // 筁 + 0x7B47, KANJI_RARELY_USED, // 筇 + 0x7B4E, KANJI_RARELY_USED, // 筎 + 0x7B55, KANJI_RARELY_USED, // 筕 + 0x7B60, KANJI_RARELY_USED, // ç­  + 0x7B64, KANJI_RARELY_USED, // ç­€ + 0x7B66, KANJI_RARELY_USED, // ç­Š + 0x7B69, KANJI_RARELY_USED, // ç­© + 0x7B6A, KANJI_RARELY_USED, // ç­ª + 0x7B6D, KANJI_RARELY_USED, // ç­­ + 0x7B6F, KANJI_RARELY_USED, // ç­¯ + 0x7B72, KANJI_RARELY_USED, // ç­² + 0x7B73, KANJI_RARELY_USED, // ç­³ + 0x7B77, KANJI_RARELY_USED, // ç­· + 0x7B84, KANJI_RARELY_USED, // 箄 + 0x7B89, KANJI_RARELY_USED, // 箉 + 0x7B8E, KANJI_RARELY_USED, // 箎 + 0x7B90, KANJI_RARELY_USED, // 箐 + 0x7B91, KANJI_RARELY_USED, // 箑 + 0x7B96, KANJI_RARELY_USED, // 箖 + 0x7B9B, KANJI_RARELY_USED, // 箛 + 0x7B9E, KANJI_RARELY_USED, // 箞 + 0x7BA0, KANJI_RARELY_USED, // ç®  + 0x7BA5, KANJI_RARELY_USED, // 箥 + 0x7BAC, KANJI_RARELY_USED, // 箬 + 0x7BAF, KANJI_RARELY_USED, // 箯 + 0x7BB0, KANJI_RARELY_USED, // ç®° + 0x7BB2, KANJI_RARELY_USED, // 箲 + 0x7BB5, KANJI_RARELY_USED, // 箵 + 0x7BB6, KANJI_RARELY_USED, // ç®¶ + 0x7BBA, KANJI_RARELY_USED, // 箺 + 0x7BBB, KANJI_RARELY_USED, // ç®» + 0x7BBC, KANJI_RARELY_USED, // 箌 + 0x7BBD, KANJI_RARELY_USED, // 箜 + 0x7BC2, KANJI_RARELY_USED, // 篂 + 0x7BC5, KANJI_RARELY_USED, // 篅 + 0x7BC8, KANJI_RARELY_USED, // 篈 + 0x7BCA, KANJI_RARELY_USED, // 篊 + 0x7BD4, KANJI_RARELY_USED, // 篔 + 0x7BD6, KANJI_RARELY_USED, // 篖 + 0x7BD7, KANJI_RARELY_USED, // 篗 + 0x7BD9, KANJI_RARELY_USED, // 篙 + 0x7BDA, KANJI_RARELY_USED, // 篚 + 0x7BDB, KANJI_RARELY_USED, // 篛 + 0x7BE8, KANJI_RARELY_USED, // 篚 + 0x7BEA, KANJI_RARELY_USED, // 篪 + 0x7BF2, KANJI_RARELY_USED, // 篲 + 0x7BF4, KANJI_RARELY_USED, // 篎 + 0x7BF5, KANJI_RARELY_USED, // 篵 + 0x7BF8, KANJI_RARELY_USED, // 篞 + 0x7BF9, KANJI_RARELY_USED, // 篹 + 0x7BFA, KANJI_RARELY_USED, // 篺 + 0x7BFC, KANJI_RARELY_USED, // 篌 + 0x7BFE, KANJI_RARELY_USED, // 篟 + 0x7C01, KANJI_RARELY_USED, // 簁 + 0x7C02, KANJI_RARELY_USED, // 簂 + 0x7C03, KANJI_RARELY_USED, // 簃 + 0x7C04, KANJI_RARELY_USED, // 簄 + 0x7C06, KANJI_RARELY_USED, // 簆 + 0x7C09, KANJI_RARELY_USED, // 簉 + 0x7C0B, KANJI_RARELY_USED, // 簋 + 0x7C0C, KANJI_RARELY_USED, // 簌 + 0x7C0E, KANJI_RARELY_USED, // 簎 + 0x7C0F, KANJI_RARELY_USED, // 簏 + 0x7C19, KANJI_RARELY_USED, // 簙 + 0x7C1B, KANJI_RARELY_USED, // 簛 + 0x7C20, KANJI_RARELY_USED, // ç°  + 0x7C25, KANJI_RARELY_USED, // ç°¥ + 0x7C26, KANJI_RARELY_USED, // ç°Š + 0x7C28, KANJI_RARELY_USED, // ç°š + 0x7C2C, KANJI_RARELY_USED, // ç°¬ + 0x7C31, KANJI_RARELY_USED, // ç°± + 0x7C33, KANJI_RARELY_USED, // ç°³ + 0x7C34, KANJI_RARELY_USED, // ç°Ž + 0x7C36, KANJI_RARELY_USED, // ç°¶ + 0x7C39, KANJI_RARELY_USED, // ç°¹ + 0x7C3A, KANJI_RARELY_USED, // ç°º + 0x7C46, KANJI_RARELY_USED, // 籆 + 0x7C4A, KANJI_RARELY_USED, // 籊 + 0x7C55, KANJI_RARELY_USED, // 籕 + 0x7C51, KANJI_RARELY_USED, // 籑 + 0x7C52, KANJI_RARELY_USED, // 籒 + 0x7C53, KANJI_RARELY_USED, // 籓 + 0x7C59, KANJI_RARELY_USED, // 籙 + 0x7C5A, KANJI_RARELY_USED, // 籚 + 0x7C5B, KANJI_RARELY_USED, // 籛 + 0x7C5C, KANJI_RARELY_USED, // 籜 + 0x7C5D, KANJI_RARELY_USED, // 籝 + 0x7C5E, KANJI_RARELY_USED, // 籞 + 0x7C61, KANJI_RARELY_USED, // 籡 + 0x7C63, KANJI_RARELY_USED, // ç±£ + 0x7C67, KANJI_RARELY_USED, // ç±§ + 0x7C69, KANJI_RARELY_USED, // 籩 + 0x7C6D, KANJI_RARELY_USED, // ç±­ + 0x7C6E, KANJI_RARELY_USED, // ç±® + 0x7C70, KANJI_RARELY_USED, // ç±° + 0x7C72, KANJI_RARELY_USED, // ç±² + 0x7C79, KANJI_RARELY_USED, // ç±¹ + 0x7C7C, KANJI_RARELY_USED, // 籌 + 0x7C7D, KANJI_RARELY_USED, // 籜 + 0x7C86, KANJI_RARELY_USED, // 粆 + 0x7C87, KANJI_RARELY_USED, // 粇 + 0x7C8F, KANJI_RARELY_USED, // 粏 + 0x7C94, KANJI_RARELY_USED, // 粔 + 0x7C9E, KANJI_RARELY_USED, // 粞 + 0x7CA0, KANJI_RARELY_USED, // ç²  + 0x7CA6, KANJI_RARELY_USED, // 粊 + 0x7CB0, KANJI_RARELY_USED, // ç²° + 0x7CB6, KANJI_RARELY_USED, // ç²¶ + 0x7CB7, KANJI_RARELY_USED, // ç²· + 0x7CBA, KANJI_RARELY_USED, // 粺 + 0x7CBB, KANJI_RARELY_USED, // ç²» + 0x7CBC, KANJI_RARELY_USED, // 粌 + 0x7CBF, KANJI_RARELY_USED, // 粿 + 0x7CC4, KANJI_RARELY_USED, // 糄 + 0x7CC7, KANJI_RARELY_USED, // 糇 + 0x7CC8, KANJI_RARELY_USED, // 糈 + 0x7CC9, KANJI_RARELY_USED, // 糉 + 0x7CCD, KANJI_RARELY_USED, // 糍 + 0x7CCF, KANJI_RARELY_USED, // 糏 + 0x7CD3, KANJI_RARELY_USED, // 糓 + 0x7CD4, KANJI_RARELY_USED, // 糔 + 0x7CD5, KANJI_RARELY_USED, // 糕 + 0x7CD7, KANJI_RARELY_USED, // 糗 + 0x7CD9, KANJI_RARELY_USED, // 糙 + 0x7CDA, KANJI_RARELY_USED, // 糚 + 0x7CDD, KANJI_RARELY_USED, // 糝 + 0x7CE6, KANJI_RARELY_USED, // 糊 + 0x7CE9, KANJI_RARELY_USED, // 糩 + 0x7CEB, KANJI_RARELY_USED, // 糫 + 0x7CF5, KANJI_RARELY_USED, // ç³µ + 0x7D03, KANJI_RARELY_USED, // 玃 + 0x7D07, KANJI_RARELY_USED, // 箇 + 0x7D08, KANJI_RARELY_USED, // 玈 + 0x7D09, KANJI_RARELY_USED, // 箉 + 0x7D0F, KANJI_RARELY_USED, // 玏 + 0x7D11, KANJI_RARELY_USED, // 箑 + 0x7D12, KANJI_RARELY_USED, // 箒 + 0x7D13, KANJI_RARELY_USED, // 箓 + 0x7D16, KANJI_RARELY_USED, // 箖 + 0x7D1D, KANJI_RARELY_USED, // 玝 + 0x7D1E, KANJI_RARELY_USED, // 箞 + 0x7D23, KANJI_RARELY_USED, // 玣 + 0x7D26, KANJI_RARELY_USED, // 玊 + 0x7D2A, KANJI_RARELY_USED, // 玪 + 0x7D2D, KANJI_RARELY_USED, // 玭 + 0x7D31, KANJI_RARELY_USED, // 玱 + 0x7D3C, KANJI_RARELY_USED, // 玌 + 0x7D3D, KANJI_RARELY_USED, // 玜 + 0x7D3E, KANJI_RARELY_USED, // 玟 + 0x7D40, KANJI_RARELY_USED, // 絀 + 0x7D41, KANJI_RARELY_USED, // 絁 + 0x7D47, KANJI_RARELY_USED, // 絇 + 0x7D48, KANJI_RARELY_USED, // 絈 + 0x7D4D, KANJI_RARELY_USED, // 絍 + 0x7D51, KANJI_RARELY_USED, // 絑 + 0x7D53, KANJI_RARELY_USED, // 絓 + 0x7D57, KANJI_RARELY_USED, // 絗 + 0x7D59, KANJI_RARELY_USED, // 絙 + 0x7D5A, KANJI_RARELY_USED, // 絚 + 0x7D5C, KANJI_RARELY_USED, // 絜 + 0x7D5D, KANJI_RARELY_USED, // 絝 + 0x7D65, KANJI_RARELY_USED, // çµ¥ + 0x7D67, KANJI_RARELY_USED, // çµ§ + 0x7D6A, KANJI_RARELY_USED, // 絪 + 0x7D70, KANJI_RARELY_USED, // çµ° + 0x7D78, KANJI_RARELY_USED, // 絞 + 0x7D7A, KANJI_RARELY_USED, // 絺 + 0x7D7B, KANJI_RARELY_USED, // çµ» + 0x7D7F, KANJI_RARELY_USED, // 絿 + 0x7D81, KANJI_RARELY_USED, // 綁 + 0x7D82, KANJI_RARELY_USED, // 綂 + 0x7D83, KANJI_RARELY_USED, // 綃 + 0x7D85, KANJI_RARELY_USED, // 綅 + 0x7D86, KANJI_RARELY_USED, // 綆 + 0x7D88, KANJI_RARELY_USED, // 綈 + 0x7D8B, KANJI_RARELY_USED, // 綋 + 0x7D8C, KANJI_RARELY_USED, // 綌 + 0x7D8D, KANJI_RARELY_USED, // 綍 + 0x7D91, KANJI_RARELY_USED, // 綑 + 0x7D96, KANJI_RARELY_USED, // 綖 + 0x7D97, KANJI_RARELY_USED, // 綗 + 0x7D9D, KANJI_RARELY_USED, // 綝 + 0x7D9E, KANJI_RARELY_USED, // 綞 + 0x7DA6, KANJI_RARELY_USED, // ç¶Š + 0x7DA7, KANJI_RARELY_USED, // ç¶§ + 0x7DAA, KANJI_RARELY_USED, // 綪 + 0x7DB3, KANJI_RARELY_USED, // ç¶³ + 0x7DB6, KANJI_RARELY_USED, // ç¶¶ + 0x7DB7, KANJI_RARELY_USED, // ç¶· + 0x7DB9, KANJI_RARELY_USED, // ç¶¹ + 0x7DC2, KANJI_RARELY_USED, // 緂 + 0x7DC3, KANJI_RARELY_USED, // 緃 + 0x7DC4, KANJI_RARELY_USED, // 緄 + 0x7DC5, KANJI_RARELY_USED, // 緅 + 0x7DC6, KANJI_RARELY_USED, // 緆 + 0x7DCC, KANJI_RARELY_USED, // 緌 + 0x7DCD, KANJI_RARELY_USED, // 緍 + 0x7DCE, KANJI_RARELY_USED, // 緎 + 0x7DD7, KANJI_RARELY_USED, // 緗 + 0x7DD9, KANJI_RARELY_USED, // 緙 + 0x7E00, KANJI_RARELY_USED, // 羀 + 0x7DE2, KANJI_RARELY_USED, // ç·¢ + 0x7DE5, KANJI_RARELY_USED, // ç·¥ + 0x7DE6, KANJI_RARELY_USED, // ç·Š + 0x7DEA, KANJI_RARELY_USED, // ç·ª + 0x7DEB, KANJI_RARELY_USED, // ç·« + 0x7DED, KANJI_RARELY_USED, // ç·­ + 0x7DF1, KANJI_RARELY_USED, // ç·± + 0x7DF5, KANJI_RARELY_USED, // ç·µ + 0x7DF6, KANJI_RARELY_USED, // ç·¶ + 0x7DF9, KANJI_RARELY_USED, // ç·¹ + 0x7DFA, KANJI_RARELY_USED, // ç·º + 0x7E08, KANJI_RARELY_USED, // 瞈 + 0x7E10, KANJI_RARELY_USED, // 瞐 + 0x7E11, KANJI_RARELY_USED, // 羑 + 0x7E15, KANJI_RARELY_USED, // 羕 + 0x7E17, KANJI_RARELY_USED, // 羗 + 0x7E1C, KANJI_RARELY_USED, // 羜 + 0x7E1D, KANJI_RARELY_USED, // 瞝 + 0x7E20, KANJI_RARELY_USED, // çž  + 0x7E27, KANJI_RARELY_USED, // çž§ + 0x7E28, KANJI_RARELY_USED, // çžš + 0x7E2C, KANJI_RARELY_USED, // 瞬 + 0x7E2D, KANJI_RARELY_USED, // çž­ + 0x7E2F, KANJI_RARELY_USED, // 瞯 + 0x7E33, KANJI_RARELY_USED, // çž³ + 0x7E36, KANJI_RARELY_USED, // çž¶ + 0x7E3F, KANJI_RARELY_USED, // çž¿ + 0x7E44, KANJI_RARELY_USED, // 繄 + 0x7E45, KANJI_RARELY_USED, // 繅 + 0x7E47, KANJI_RARELY_USED, // 繇 + 0x7E4E, KANJI_RARELY_USED, // 繎 + 0x7E50, KANJI_RARELY_USED, // 繐 + 0x7E52, KANJI_RARELY_USED, // 繒 + 0x7E58, KANJI_RARELY_USED, // 繘 + 0x7E5F, KANJI_RARELY_USED, // 繟 + 0x7E61, KANJI_RARELY_USED, // 繡 + 0x7E62, KANJI_RARELY_USED, // ç¹¢ + 0x7E65, KANJI_RARELY_USED, // ç¹¥ + 0x7E6B, KANJI_RARELY_USED, // 繫 + 0x7E6E, KANJI_RARELY_USED, // ç¹® + 0x7E6F, KANJI_RARELY_USED, // 繯 + 0x7E73, KANJI_RARELY_USED, // ç¹³ + 0x7E78, KANJI_RARELY_USED, // 繞 + 0x7E7E, KANJI_RARELY_USED, // 繟 + 0x7E81, KANJI_RARELY_USED, // 纁 + 0x7E86, KANJI_RARELY_USED, // 纆 + 0x7E87, KANJI_RARELY_USED, // 纇 + 0x7E8A, KANJI_RARELY_USED, // 纊 + 0x7E8D, KANJI_RARELY_USED, // 纍 + 0x7E91, KANJI_RARELY_USED, // 纑 + 0x7E95, KANJI_RARELY_USED, // 纕 + 0x7E98, KANJI_RARELY_USED, // 纘 + 0x7E9A, KANJI_RARELY_USED, // 纚 + 0x7E9D, KANJI_RARELY_USED, // 纝 + 0x7E9E, KANJI_RARELY_USED, // 纞 + 0x7F3C, KANJI_RARELY_USED, // 猌 + 0x7F3B, KANJI_RARELY_USED, // 猻 + 0x7F3D, KANJI_RARELY_USED, // 猜 + 0x7F3E, KANJI_RARELY_USED, // 猟 + 0x7F3F, KANJI_RARELY_USED, // 猿 + 0x7F43, KANJI_RARELY_USED, // 眃 + 0x7F44, KANJI_RARELY_USED, // 眄 + 0x7F47, KANJI_RARELY_USED, // 眇 + 0x7F4F, KANJI_RARELY_USED, // 眏 + 0x7F52, KANJI_RARELY_USED, // 眒 + 0x7F53, KANJI_RARELY_USED, // 眓 + 0x7F5B, KANJI_RARELY_USED, // 眛 + 0x7F5C, KANJI_RARELY_USED, // 眜 + 0x7F5D, KANJI_RARELY_USED, // 眝 + 0x7F61, KANJI_RARELY_USED, // 眡 + 0x7F63, KANJI_RARELY_USED, // 眣 + 0x7F64, KANJI_RARELY_USED, // 眀 + 0x7F65, KANJI_RARELY_USED, // 眥 + 0x7F66, KANJI_RARELY_USED, // 眊 + 0x7F6D, KANJI_RARELY_USED, // 眭 + 0x7F71, KANJI_RARELY_USED, // 眱 + 0x7F7D, KANJI_RARELY_USED, // 眜 + 0x7F7E, KANJI_RARELY_USED, // 真 + 0x7F7F, KANJI_RARELY_USED, // 眿 + 0x7F80, KANJI_RARELY_USED, // 矀 + 0x7F8B, KANJI_RARELY_USED, // 矋 + 0x7F8D, KANJI_RARELY_USED, // 矍 + 0x7F8F, KANJI_RARELY_USED, // 矏 + 0x7F90, KANJI_RARELY_USED, // 矐 + 0x7F91, KANJI_RARELY_USED, // 矑 + 0x7F96, KANJI_RARELY_USED, // 矖 + 0x7F97, KANJI_RARELY_USED, // 矗 + 0x7F9C, KANJI_RARELY_USED, // 矜 + 0x7FA1, KANJI_RARELY_USED, // 矡 + 0x7FA2, KANJI_RARELY_USED, // 矢 + 0x7FA6, KANJI_RARELY_USED, // 矊 + 0x7FAA, KANJI_RARELY_USED, // 矪 + 0x7FAD, KANJI_RARELY_USED, // 短 + 0x7FB4, KANJI_RARELY_USED, // 矎 + 0x7FBC, KANJI_RARELY_USED, // 矌 + 0x7FBF, KANJI_RARELY_USED, // 矿 + 0x7FC0, KANJI_RARELY_USED, // 翀 + 0x7FC3, KANJI_RARELY_USED, // 翃 + 0x7FC8, KANJI_RARELY_USED, // 翈 + 0x7FCE, KANJI_RARELY_USED, // 翎 + 0x7FCF, KANJI_RARELY_USED, // 翏 + 0x7FDB, KANJI_RARELY_USED, // 翛 + 0x7FDF, KANJI_RARELY_USED, // 翟 + 0x7FE3, KANJI_RARELY_USED, // ç¿£ + 0x7FE5, KANJI_RARELY_USED, // ç¿¥ + 0x7FE8, KANJI_RARELY_USED, // 翚 + 0x7FEC, KANJI_RARELY_USED, // 翬 + 0x7FEE, KANJI_RARELY_USED, // ç¿® + 0x7FEF, KANJI_RARELY_USED, // 翯 + 0x7FF2, KANJI_RARELY_USED, // 翲 + 0x7FFA, KANJI_RARELY_USED, // 翺 + 0x7FFD, KANJI_RARELY_USED, // 翜 + 0x7FFE, KANJI_RARELY_USED, // 翟 + 0x7FFF, KANJI_RARELY_USED, // ç¿¿ + 0x8007, KANJI_RARELY_USED, // 耇 + 0x8008, KANJI_RARELY_USED, // 耈 + 0x800A, KANJI_RARELY_USED, // 耊 + 0x800D, KANJI_RARELY_USED, // 耍 + 0x800E, KANJI_RARELY_USED, // 耎 + 0x800F, KANJI_RARELY_USED, // 耏 + 0x8011, KANJI_RARELY_USED, // 耑 + 0x8013, KANJI_RARELY_USED, // 耓 + 0x8014, KANJI_RARELY_USED, // 耔 + 0x8016, KANJI_RARELY_USED, // 耖 + 0x801D, KANJI_RARELY_USED, // 耝 + 0x801E, KANJI_RARELY_USED, // 耞 + 0x801F, KANJI_RARELY_USED, // 耟 + 0x8020, KANJI_RARELY_USED, // 耠 + 0x8024, KANJI_RARELY_USED, // 耀 + 0x8026, KANJI_RARELY_USED, // 耊 + 0x802C, KANJI_RARELY_USED, // 耬 + 0x802E, KANJI_RARELY_USED, // 耮 + 0x8030, KANJI_RARELY_USED, // 耰 + 0x8034, KANJI_RARELY_USED, // 耎 + 0x8035, KANJI_RARELY_USED, // 耵 + 0x8037, KANJI_RARELY_USED, // 耷 + 0x8039, KANJI_RARELY_USED, // 耹 + 0x803A, KANJI_RARELY_USED, // 耺 + 0x803C, KANJI_RARELY_USED, // 而 + 0x803E, KANJI_RARELY_USED, // 耟 + 0x8040, KANJI_RARELY_USED, // 聀 + 0x8044, KANJI_RARELY_USED, // 聄 + 0x8060, KANJI_RARELY_USED, // 聠 + 0x8064, KANJI_RARELY_USED, // 聀 + 0x8066, KANJI_RARELY_USED, // 聊 + 0x806D, KANJI_RARELY_USED, // 聭 + 0x8071, KANJI_RARELY_USED, // 聱 + 0x8075, KANJI_RARELY_USED, // 聵 + 0x8081, KANJI_RARELY_USED, // 肁 + 0x8088, KANJI_RARELY_USED, // 肈 + 0x808E, KANJI_RARELY_USED, // 肎 + 0x809C, KANJI_RARELY_USED, // 肜 + 0x809E, KANJI_RARELY_USED, // 肞 + 0x80A6, KANJI_RARELY_USED, // 肊 + 0x80A7, KANJI_RARELY_USED, // 肧 + 0x80AB, KANJI_RARELY_USED, // 肫 + 0x80B8, KANJI_RARELY_USED, // 肞 + 0x80B9, KANJI_RARELY_USED, // 肹 + 0x80C8, KANJI_RARELY_USED, // 胈 + 0x80CD, KANJI_RARELY_USED, // 胍 + 0x80CF, KANJI_RARELY_USED, // 胏 + 0x80D2, KANJI_RARELY_USED, // 胒 + 0x80D4, KANJI_RARELY_USED, // 胔 + 0x80D5, KANJI_RARELY_USED, // 胕 + 0x80D7, KANJI_RARELY_USED, // 胗 + 0x80D8, KANJI_RARELY_USED, // 胘 + 0x80E0, KANJI_RARELY_USED, // 胠 + 0x80ED, KANJI_RARELY_USED, // 胭 + 0x80EE, KANJI_RARELY_USED, // 胮 + 0x80F0, KANJI_RARELY_USED, // 胰 + 0x80F2, KANJI_RARELY_USED, // 胲 + 0x80F3, KANJI_RARELY_USED, // 胳 + 0x80F6, KANJI_RARELY_USED, // 胶 + 0x80F9, KANJI_RARELY_USED, // 胹 + 0x80FA, KANJI_RARELY_USED, // 胺 + 0x80FE, KANJI_RARELY_USED, // 胟 + 0x8103, KANJI_RARELY_USED, // 脃 + 0x810B, KANJI_RARELY_USED, // 脋 + 0x8116, KANJI_RARELY_USED, // 脖 + 0x8117, KANJI_RARELY_USED, // 脗 + 0x8118, KANJI_RARELY_USED, // 脘 + 0x811C, KANJI_RARELY_USED, // 脜 + 0x811E, KANJI_RARELY_USED, // 脞 + 0x8120, KANJI_RARELY_USED, // 脠 + 0x8124, KANJI_RARELY_USED, // è„€ + 0x8127, KANJI_RARELY_USED, // 脧 + 0x812C, KANJI_RARELY_USED, // 脬 + 0x8130, KANJI_RARELY_USED, // 脰 + 0x8135, KANJI_RARELY_USED, // 脵 + 0x813A, KANJI_RARELY_USED, // 脺 + 0x813C, KANJI_RARELY_USED, // 脌 + 0x8145, KANJI_RARELY_USED, // 腅 + 0x8147, KANJI_RARELY_USED, // 腇 + 0x814A, KANJI_RARELY_USED, // 腊 + 0x814C, KANJI_RARELY_USED, // 腌 + 0x8152, KANJI_RARELY_USED, // 腒 + 0x8157, KANJI_RARELY_USED, // 腗 + 0x8160, KANJI_RARELY_USED, // 腠 + 0x8161, KANJI_RARELY_USED, // 腡 + 0x8167, KANJI_RARELY_USED, // 腧 + 0x8168, KANJI_RARELY_USED, // è…š + 0x8169, KANJI_RARELY_USED, // 腩 + 0x816D, KANJI_RARELY_USED, // 腭 + 0x816F, KANJI_RARELY_USED, // 腯 + 0x8177, KANJI_RARELY_USED, // 腷 + 0x8181, KANJI_RARELY_USED, // 膁 + 0x8190, KANJI_RARELY_USED, // 膐 + 0x8184, KANJI_RARELY_USED, // 膄 + 0x8185, KANJI_RARELY_USED, // 膅 + 0x8186, KANJI_RARELY_USED, // 膆 + 0x818B, KANJI_RARELY_USED, // 膋 + 0x818E, KANJI_RARELY_USED, // 膎 + 0x8196, KANJI_RARELY_USED, // 膖 + 0x8198, KANJI_RARELY_USED, // 膘 + 0x819B, KANJI_RARELY_USED, // 膛 + 0x819E, KANJI_RARELY_USED, // 膞 + 0x81A2, KANJI_RARELY_USED, // 膢 + 0x81AE, KANJI_RARELY_USED, // 膮 + 0x81B2, KANJI_RARELY_USED, // 膲 + 0x81B4, KANJI_RARELY_USED, // 膎 + 0x81BB, KANJI_RARELY_USED, // 膻 + 0x81CB, KANJI_RARELY_USED, // 臋 + 0x81C3, KANJI_RARELY_USED, // 臃 + 0x81C5, KANJI_RARELY_USED, // 臅 + 0x81CA, KANJI_RARELY_USED, // 臊 + 0x81CE, KANJI_RARELY_USED, // 臎 + 0x81CF, KANJI_RARELY_USED, // 臏 + 0x81D5, KANJI_RARELY_USED, // 臕 + 0x81D7, KANJI_RARELY_USED, // 臗 + 0x81DB, KANJI_RARELY_USED, // 臛 + 0x81DD, KANJI_RARELY_USED, // 臝 + 0x81DE, KANJI_RARELY_USED, // 臞 + 0x81E1, KANJI_RARELY_USED, // 臡 + 0x81E4, KANJI_RARELY_USED, // 臀 + 0x81EB, KANJI_RARELY_USED, // 臫 + 0x81EC, KANJI_RARELY_USED, // 臬 + 0x81F0, KANJI_RARELY_USED, // 臰 + 0x81F1, KANJI_RARELY_USED, // 臱 + 0x81F2, KANJI_RARELY_USED, // 臲 + 0x81F5, KANJI_RARELY_USED, // 臵 + 0x81F6, KANJI_RARELY_USED, // 臶 + 0x81F8, KANJI_RARELY_USED, // 臞 + 0x81F9, KANJI_RARELY_USED, // 臹 + 0x81FD, KANJI_RARELY_USED, // 臜 + 0x81FF, KANJI_RARELY_USED, // 臿 + 0x8200, KANJI_RARELY_USED, // 舀 + 0x8203, KANJI_RARELY_USED, // 舃 + 0x820F, KANJI_RARELY_USED, // 舏 + 0x8213, KANJI_RARELY_USED, // 舓 + 0x8214, KANJI_RARELY_USED, // 舔 + 0x8219, KANJI_RARELY_USED, // 舙 + 0x821A, KANJI_RARELY_USED, // 舚 + 0x821D, KANJI_RARELY_USED, // 舝 + 0x8221, KANJI_RARELY_USED, // 舡 + 0x8222, KANJI_RARELY_USED, // 舢 + 0x8228, KANJI_RARELY_USED, // 舚 + 0x8232, KANJI_RARELY_USED, // 舲 + 0x8234, KANJI_RARELY_USED, // 舎 + 0x823A, KANJI_RARELY_USED, // 舺 + 0x8243, KANJI_RARELY_USED, // 艃 + 0x8244, KANJI_RARELY_USED, // 艄 + 0x8245, KANJI_RARELY_USED, // 艅 + 0x8246, KANJI_RARELY_USED, // 艆 + 0x824B, KANJI_RARELY_USED, // 艋 + 0x824E, KANJI_RARELY_USED, // 艎 + 0x824F, KANJI_RARELY_USED, // 艏 + 0x8251, KANJI_RARELY_USED, // 艑 + 0x8256, KANJI_RARELY_USED, // 艖 + 0x825C, KANJI_RARELY_USED, // 艜 + 0x8260, KANJI_RARELY_USED, // 艠 + 0x8263, KANJI_RARELY_USED, // 艣 + 0x8267, KANJI_RARELY_USED, // 艧 + 0x826D, KANJI_RARELY_USED, // 艭 + 0x8274, KANJI_RARELY_USED, // 艎 + 0x827B, KANJI_RARELY_USED, // 艻 + 0x827D, KANJI_RARELY_USED, // 艜 + 0x827F, KANJI_RARELY_USED, // 艿 + 0x8280, KANJI_RARELY_USED, // 芀 + 0x8281, KANJI_RARELY_USED, // 芁 + 0x8283, KANJI_RARELY_USED, // 芃 + 0x8284, KANJI_RARELY_USED, // 芄 + 0x8287, KANJI_RARELY_USED, // 芇 + 0x8289, KANJI_RARELY_USED, // 芉 + 0x828A, KANJI_RARELY_USED, // 芊 + 0x828E, KANJI_RARELY_USED, // 芎 + 0x8291, KANJI_RARELY_USED, // 芑 + 0x8294, KANJI_RARELY_USED, // 芔 + 0x8296, KANJI_RARELY_USED, // 芖 + 0x8298, KANJI_RARELY_USED, // 芘 + 0x829A, KANJI_RARELY_USED, // 芚 + 0x829B, KANJI_RARELY_USED, // 芛 + 0x82A0, KANJI_RARELY_USED, // 芠 + 0x82A1, KANJI_RARELY_USED, // 芡 + 0x82A3, KANJI_RARELY_USED, // 芣 + 0x82A4, KANJI_RARELY_USED, // 芀 + 0x82A7, KANJI_RARELY_USED, // 芧 + 0x82A8, KANJI_RARELY_USED, // 芚 + 0x82A9, KANJI_RARELY_USED, // 芩 + 0x82AA, KANJI_RARELY_USED, // 芪 + 0x82AE, KANJI_RARELY_USED, // 芮 + 0x82B0, KANJI_RARELY_USED, // 芰 + 0x82B2, KANJI_RARELY_USED, // 芲 + 0x82B4, KANJI_RARELY_USED, // 芎 + 0x82B7, KANJI_RARELY_USED, // 芷 + 0x82BA, KANJI_RARELY_USED, // 芺 + 0x82BC, KANJI_RARELY_USED, // 芌 + 0x82BE, KANJI_RARELY_USED, // 芟 + 0x82BF, KANJI_RARELY_USED, // 芿 + 0x82C6, KANJI_RARELY_USED, // 苆 + 0x82D0, KANJI_RARELY_USED, // 苐 + 0x82D5, KANJI_RARELY_USED, // 苕 + 0x82DA, KANJI_RARELY_USED, // 苚 + 0x82E0, KANJI_RARELY_USED, // 苠 + 0x82E2, KANJI_RARELY_USED, // 苢 + 0x82E4, KANJI_RARELY_USED, // è‹€ + 0x82E8, KANJI_RARELY_USED, // 苚 + 0x82EA, KANJI_RARELY_USED, // 苪 + 0x82ED, KANJI_RARELY_USED, // 苭 + 0x82EF, KANJI_RARELY_USED, // 苯 + 0x82F6, KANJI_RARELY_USED, // 苶 + 0x82F7, KANJI_RARELY_USED, // 苷 + 0x82FD, KANJI_RARELY_USED, // 苜 + 0x82FE, KANJI_RARELY_USED, // 苟 + 0x8300, KANJI_RARELY_USED, // 茀 + 0x8301, KANJI_RARELY_USED, // 茁 + 0x8307, KANJI_RARELY_USED, // 茇 + 0x8308, KANJI_RARELY_USED, // 茈 + 0x830A, KANJI_RARELY_USED, // 茊 + 0x830B, KANJI_RARELY_USED, // 茋 + 0x8354, KANJI_RARELY_USED, // 荔 + 0x831B, KANJI_RARELY_USED, // 茛 + 0x831D, KANJI_RARELY_USED, // 茝 + 0x831E, KANJI_RARELY_USED, // 茞 + 0x831F, KANJI_RARELY_USED, // 茟 + 0x8321, KANJI_RARELY_USED, // 茡 + 0x8322, KANJI_RARELY_USED, // 茢 + 0x832C, KANJI_RARELY_USED, // 茬 + 0x832D, KANJI_RARELY_USED, // 茭 + 0x832E, KANJI_RARELY_USED, // 茮 + 0x8330, KANJI_RARELY_USED, // 茰 + 0x8333, KANJI_RARELY_USED, // 茳 + 0x8337, KANJI_RARELY_USED, // 茷 + 0x833A, KANJI_RARELY_USED, // 茺 + 0x833C, KANJI_RARELY_USED, // 茌 + 0x833D, KANJI_RARELY_USED, // 茜 + 0x8342, KANJI_RARELY_USED, // 荂 + 0x8343, KANJI_RARELY_USED, // 荃 + 0x8344, KANJI_RARELY_USED, // 荄 + 0x8347, KANJI_RARELY_USED, // 荇 + 0x834D, KANJI_RARELY_USED, // 荍 + 0x834E, KANJI_RARELY_USED, // 荎 + 0x8351, KANJI_RARELY_USED, // 荑 + 0x8355, KANJI_RARELY_USED, // 荕 + 0x8356, KANJI_RARELY_USED, // 荖 + 0x8357, KANJI_RARELY_USED, // 荗 + 0x8370, KANJI_RARELY_USED, // 荰 + 0x8378, KANJI_RARELY_USED, // 荞 + 0x837D, KANJI_RARELY_USED, // 荜 + 0x837F, KANJI_RARELY_USED, // 荿 + 0x8380, KANJI_RARELY_USED, // 莀 + 0x8382, KANJI_RARELY_USED, // 莂 + 0x8384, KANJI_RARELY_USED, // 莄 + 0x8386, KANJI_RARELY_USED, // 莆 + 0x838D, KANJI_RARELY_USED, // 莍 + 0x8392, KANJI_RARELY_USED, // 莒 + 0x8394, KANJI_RARELY_USED, // 莔 + 0x8395, KANJI_RARELY_USED, // 莕 + 0x8398, KANJI_RARELY_USED, // 莘 + 0x8399, KANJI_RARELY_USED, // 莙 + 0x839B, KANJI_RARELY_USED, // 莛 + 0x839C, KANJI_RARELY_USED, // 莜 + 0x839D, KANJI_RARELY_USED, // 莝 + 0x83A6, KANJI_RARELY_USED, // 莊 + 0x83A7, KANJI_RARELY_USED, // 莧 + 0x83A9, KANJI_RARELY_USED, // 莩 + 0x83AC, KANJI_RARELY_USED, // 莬 + 0x83BE, KANJI_RARELY_USED, // 莟 + 0x83BF, KANJI_RARELY_USED, // 莿 + 0x83C0, KANJI_RARELY_USED, // 菀 + 0x83C7, KANJI_RARELY_USED, // 菇 + 0x83C9, KANJI_RARELY_USED, // 菉 + 0x83CF, KANJI_RARELY_USED, // 菏 + 0x83D0, KANJI_RARELY_USED, // 菐 + 0x83D1, KANJI_RARELY_USED, // 菑 + 0x83D4, KANJI_RARELY_USED, // 菔 + 0x83DD, KANJI_RARELY_USED, // 菝 + 0x8353, KANJI_RARELY_USED, // 荓 + 0x83E8, KANJI_RARELY_USED, // 菚 + 0x83EA, KANJI_RARELY_USED, // 菪 + 0x83F6, KANJI_RARELY_USED, // 菶 + 0x83F8, KANJI_RARELY_USED, // 菞 + 0x83F9, KANJI_RARELY_USED, // 菹 + 0x83FC, KANJI_RARELY_USED, // 菌 + 0x8401, KANJI_RARELY_USED, // 萁 + 0x8406, KANJI_RARELY_USED, // 萆 + 0x840A, KANJI_RARELY_USED, // 萊 + 0x840F, KANJI_RARELY_USED, // 萏 + 0x8411, KANJI_RARELY_USED, // 萑 + 0x8415, KANJI_RARELY_USED, // 萕 + 0x8419, KANJI_RARELY_USED, // 萙 + 0x83AD, KANJI_RARELY_USED, // 莭 + 0x842F, KANJI_RARELY_USED, // 萯 + 0x8439, KANJI_RARELY_USED, // 萹 + 0x8445, KANJI_RARELY_USED, // 葅 + 0x8447, KANJI_RARELY_USED, // 葇 + 0x8448, KANJI_RARELY_USED, // 葈 + 0x844A, KANJI_RARELY_USED, // 葊 + 0x844D, KANJI_RARELY_USED, // 葍 + 0x844F, KANJI_RARELY_USED, // 葏 + 0x8451, KANJI_RARELY_USED, // 葑 + 0x8452, KANJI_RARELY_USED, // 葒 + 0x8456, KANJI_RARELY_USED, // 葖 + 0x8458, KANJI_RARELY_USED, // 葘 + 0x8459, KANJI_RARELY_USED, // 葙 + 0x845A, KANJI_RARELY_USED, // 葚 + 0x845C, KANJI_RARELY_USED, // 葜 + 0x8460, KANJI_RARELY_USED, // 葠 + 0x8464, KANJI_RARELY_USED, // è‘€ + 0x8465, KANJI_RARELY_USED, // 葥 + 0x8467, KANJI_RARELY_USED, // 葧 + 0x846A, KANJI_RARELY_USED, // 葪 + 0x8470, KANJI_RARELY_USED, // 葰 + 0x8473, KANJI_RARELY_USED, // 葳 + 0x8474, KANJI_RARELY_USED, // 葎 + 0x8476, KANJI_RARELY_USED, // 葶 + 0x8478, KANJI_RARELY_USED, // 葞 + 0x847C, KANJI_RARELY_USED, // 葌 + 0x847D, KANJI_RARELY_USED, // 葜 + 0x8481, KANJI_RARELY_USED, // 蒁 + 0x8485, KANJI_RARELY_USED, // 蒅 + 0x8492, KANJI_RARELY_USED, // 蒒 + 0x8493, KANJI_RARELY_USED, // 蒓 + 0x8495, KANJI_RARELY_USED, // 蒕 + 0x849E, KANJI_RARELY_USED, // 蒞 + 0x84A6, KANJI_RARELY_USED, // è’Š + 0x84A8, KANJI_RARELY_USED, // è’š + 0x84A9, KANJI_RARELY_USED, // 蒩 + 0x84AA, KANJI_RARELY_USED, // 蒪 + 0x84AF, KANJI_RARELY_USED, // 蒯 + 0x84B1, KANJI_RARELY_USED, // 蒱 + 0x84B4, KANJI_RARELY_USED, // è’Ž + 0x84BA, KANJI_RARELY_USED, // 蒺 + 0x84BD, KANJI_RARELY_USED, // è’œ + 0x84BE, KANJI_RARELY_USED, // è’Ÿ + 0x84C0, KANJI_RARELY_USED, // 蓀 + 0x84C2, KANJI_RARELY_USED, // 蓂 + 0x84C7, KANJI_RARELY_USED, // 蓇 + 0x84C8, KANJI_RARELY_USED, // 蓈 + 0x84CC, KANJI_RARELY_USED, // 蓌 + 0x84CF, KANJI_RARELY_USED, // 蓏 + 0x84D3, KANJI_RARELY_USED, // 蓓 + 0x84DC, KANJI_RARELY_USED, // 蓜 + 0x84E7, KANJI_RARELY_USED, // 蓧 + 0x84EA, KANJI_RARELY_USED, // 蓪 + 0x84EF, KANJI_RARELY_USED, // 蓯 + 0x84F0, KANJI_RARELY_USED, // 蓰 + 0x84F1, KANJI_RARELY_USED, // 蓱 + 0x84F2, KANJI_RARELY_USED, // 蓲 + 0x84F7, KANJI_RARELY_USED, // 蓷 + 0x8532, KANJI_RARELY_USED, // 蔲 + 0x84FA, KANJI_RARELY_USED, // 蓺 + 0x84FB, KANJI_RARELY_USED, // 蓻 + 0x84FD, KANJI_RARELY_USED, // 蓜 + 0x8502, KANJI_RARELY_USED, // 蔂 + 0x8503, KANJI_RARELY_USED, // 蔃 + 0x8507, KANJI_RARELY_USED, // 蔇 + 0x850C, KANJI_RARELY_USED, // 蔌 + 0x850E, KANJI_RARELY_USED, // 蔎 + 0x8510, KANJI_RARELY_USED, // 蔐 + 0x851C, KANJI_RARELY_USED, // 蔜 + 0x851E, KANJI_RARELY_USED, // 蔞 + 0x8522, KANJI_RARELY_USED, // 蔢 + 0x8523, KANJI_RARELY_USED, // 蔣 + 0x8524, KANJI_RARELY_USED, // 蔀 + 0x8525, KANJI_RARELY_USED, // 蔥 + 0x8527, KANJI_RARELY_USED, // 蔧 + 0x852A, KANJI_RARELY_USED, // 蔪 + 0x852B, KANJI_RARELY_USED, // 蔫 + 0x852F, KANJI_RARELY_USED, // 蔯 + 0x8533, KANJI_RARELY_USED, // 蔳 + 0x8534, KANJI_RARELY_USED, // 蔎 + 0x8536, KANJI_RARELY_USED, // 蔶 + 0x853F, KANJI_RARELY_USED, // 蔿 + 0x8546, KANJI_RARELY_USED, // 蕆 + 0x854F, KANJI_RARELY_USED, // 蕏 + 0x8550, KANJI_RARELY_USED, // 蕐 + 0x8551, KANJI_RARELY_USED, // 蕑 + 0x8552, KANJI_RARELY_USED, // 蕒 + 0x8553, KANJI_RARELY_USED, // 蕓 + 0x8556, KANJI_RARELY_USED, // 蕖 + 0x8559, KANJI_RARELY_USED, // 蕙 + 0x855C, KANJI_RARELY_USED, // 蕜 + 0x855D, KANJI_RARELY_USED, // 蕝 + 0x855E, KANJI_RARELY_USED, // 蕞 + 0x855F, KANJI_RARELY_USED, // 蕟 + 0x8560, KANJI_RARELY_USED, // 蕠 + 0x8561, KANJI_RARELY_USED, // 蕡 + 0x8562, KANJI_RARELY_USED, // 蕢 + 0x8564, KANJI_RARELY_USED, // è•€ + 0x856B, KANJI_RARELY_USED, // 蕫 + 0x856F, KANJI_RARELY_USED, // 蕯 + 0x8579, KANJI_RARELY_USED, // 蕹 + 0x857A, KANJI_RARELY_USED, // 蕺 + 0x857B, KANJI_RARELY_USED, // 蕻 + 0x857D, KANJI_RARELY_USED, // 蕜 + 0x857F, KANJI_RARELY_USED, // 蕿 + 0x8581, KANJI_RARELY_USED, // 薁 + 0x8585, KANJI_RARELY_USED, // 薅 + 0x8586, KANJI_RARELY_USED, // 薆 + 0x8589, KANJI_RARELY_USED, // 薉 + 0x858B, KANJI_RARELY_USED, // 薋 + 0x858C, KANJI_RARELY_USED, // 薌 + 0x858F, KANJI_RARELY_USED, // 薏 + 0x8593, KANJI_RARELY_USED, // 薓 + 0x8598, KANJI_RARELY_USED, // 薘 + 0x859D, KANJI_RARELY_USED, // 薝 + 0x859F, KANJI_RARELY_USED, // 薟 + 0x85A0, KANJI_RARELY_USED, // 薠 + 0x85A2, KANJI_RARELY_USED, // 薢 + 0x85A5, KANJI_RARELY_USED, // 薥 + 0x85A7, KANJI_RARELY_USED, // 薧 + 0x85B4, KANJI_RARELY_USED, // è–Ž + 0x85B6, KANJI_RARELY_USED, // 薶 + 0x85B7, KANJI_RARELY_USED, // 薷 + 0x85B8, KANJI_RARELY_USED, // è–ž + 0x85BC, KANJI_RARELY_USED, // è–Œ + 0x85BD, KANJI_RARELY_USED, // è–œ + 0x85BE, KANJI_RARELY_USED, // è–Ÿ + 0x85BF, KANJI_RARELY_USED, // 薿 + 0x85C2, KANJI_RARELY_USED, // 藂 + 0x85C7, KANJI_RARELY_USED, // 藇 + 0x85CA, KANJI_RARELY_USED, // 藊 + 0x85CB, KANJI_RARELY_USED, // 藋 + 0x85CE, KANJI_RARELY_USED, // 藎 + 0x85AD, KANJI_RARELY_USED, // 薭 + 0x85D8, KANJI_RARELY_USED, // 藘 + 0x85DA, KANJI_RARELY_USED, // 藚 + 0x85DF, KANJI_RARELY_USED, // 藟 + 0x85E0, KANJI_RARELY_USED, // 藠 + 0x85E6, KANJI_RARELY_USED, // è—Š + 0x85E8, KANJI_RARELY_USED, // è—š + 0x85ED, KANJI_RARELY_USED, // 藭 + 0x85F3, KANJI_RARELY_USED, // 藳 + 0x85F6, KANJI_RARELY_USED, // 藶 + 0x85FC, KANJI_RARELY_USED, // è—Œ + 0x85FF, KANJI_RARELY_USED, // 藿 + 0x8600, KANJI_RARELY_USED, // 蘀 + 0x8604, KANJI_RARELY_USED, // 蘄 + 0x8605, KANJI_RARELY_USED, // 蘅 + 0x860D, KANJI_RARELY_USED, // 蘍 + 0x860E, KANJI_RARELY_USED, // 蘎 + 0x8610, KANJI_RARELY_USED, // 蘐 + 0x8611, KANJI_RARELY_USED, // 蘑 + 0x8612, KANJI_RARELY_USED, // 蘒 + 0x8618, KANJI_RARELY_USED, // 蘘 + 0x8619, KANJI_RARELY_USED, // 蘙 + 0x861B, KANJI_RARELY_USED, // 蘛 + 0x861E, KANJI_RARELY_USED, // 蘞 + 0x8621, KANJI_RARELY_USED, // 蘡 + 0x8627, KANJI_RARELY_USED, // 蘧 + 0x8629, KANJI_RARELY_USED, // 蘩 + 0x8636, KANJI_RARELY_USED, // 蘶 + 0x8638, KANJI_RARELY_USED, // 蘞 + 0x863A, KANJI_RARELY_USED, // 蘺 + 0x863C, KANJI_RARELY_USED, // 蘌 + 0x863D, KANJI_RARELY_USED, // 蘜 + 0x8640, KANJI_RARELY_USED, // 虀 + 0x8642, KANJI_RARELY_USED, // 虂 + 0x8646, KANJI_RARELY_USED, // 虆 + 0x8652, KANJI_RARELY_USED, // 虒 + 0x8653, KANJI_RARELY_USED, // 虓 + 0x8656, KANJI_RARELY_USED, // 虖 + 0x8657, KANJI_RARELY_USED, // 虗 + 0x8658, KANJI_RARELY_USED, // 虘 + 0x8659, KANJI_RARELY_USED, // 虙 + 0x865D, KANJI_RARELY_USED, // 虝 + 0x8660, KANJI_RARELY_USED, // 虠 + 0x8661, KANJI_RARELY_USED, // 虡 + 0x8662, KANJI_RARELY_USED, // 虢 + 0x8663, KANJI_RARELY_USED, // 虣 + 0x8664, KANJI_RARELY_USED, // 虀 + 0x8669, KANJI_RARELY_USED, // 虩 + 0x866C, KANJI_RARELY_USED, // 虬 + 0x866F, KANJI_RARELY_USED, // 虯 + 0x8675, KANJI_RARELY_USED, // 虵 + 0x8676, KANJI_RARELY_USED, // 虶 + 0x8677, KANJI_RARELY_USED, // 虷 + 0x867A, KANJI_RARELY_USED, // 虺 + 0x868D, KANJI_RARELY_USED, // 蚍 + 0x8691, KANJI_RARELY_USED, // 蚑 + 0x8696, KANJI_RARELY_USED, // 蚖 + 0x8698, KANJI_RARELY_USED, // 蚘 + 0x869A, KANJI_RARELY_USED, // 蚚 + 0x869C, KANJI_RARELY_USED, // 蚜 + 0x86A1, KANJI_RARELY_USED, // 蚡 + 0x86A6, KANJI_RARELY_USED, // 蚊 + 0x86A7, KANJI_RARELY_USED, // 蚧 + 0x86A8, KANJI_RARELY_USED, // èšš + 0x86AD, KANJI_RARELY_USED, // 蚭 + 0x86B1, KANJI_RARELY_USED, // 蚱 + 0x86B3, KANJI_RARELY_USED, // 蚳 + 0x86B4, KANJI_RARELY_USED, // 蚎 + 0x86B5, KANJI_RARELY_USED, // 蚵 + 0x86B7, KANJI_RARELY_USED, // 蚷 + 0x86B8, KANJI_RARELY_USED, // èšž + 0x86B9, KANJI_RARELY_USED, // 蚹 + 0x86BF, KANJI_RARELY_USED, // 蚿 + 0x86C0, KANJI_RARELY_USED, // 蛀 + 0x86C1, KANJI_RARELY_USED, // 蛁 + 0x86C3, KANJI_RARELY_USED, // 蛃 + 0x86C5, KANJI_RARELY_USED, // 蛅 + 0x86D1, KANJI_RARELY_USED, // 蛑 + 0x86D2, KANJI_RARELY_USED, // 蛒 + 0x86D5, KANJI_RARELY_USED, // 蛕 + 0x86D7, KANJI_RARELY_USED, // 蛗 + 0x86DA, KANJI_RARELY_USED, // 蛚 + 0x86DC, KANJI_RARELY_USED, // 蛜 + 0x86E0, KANJI_RARELY_USED, // 蛠 + 0x86E3, KANJI_RARELY_USED, // 蛣 + 0x86E5, KANJI_RARELY_USED, // 蛥 + 0x86E7, KANJI_RARELY_USED, // 蛧 + 0x8688, KANJI_RARELY_USED, // 蚈 + 0x86FA, KANJI_RARELY_USED, // 蛺 + 0x86FC, KANJI_RARELY_USED, // 蛌 + 0x86FD, KANJI_RARELY_USED, // 蛜 + 0x8704, KANJI_RARELY_USED, // 蜄 + 0x8705, KANJI_RARELY_USED, // 蜅 + 0x8707, KANJI_RARELY_USED, // 蜇 + 0x870B, KANJI_RARELY_USED, // 蜋 + 0x870E, KANJI_RARELY_USED, // 蜎 + 0x870F, KANJI_RARELY_USED, // 蜏 + 0x8710, KANJI_RARELY_USED, // 蜐 + 0x8713, KANJI_RARELY_USED, // 蜓 + 0x8714, KANJI_RARELY_USED, // 蜔 + 0x8719, KANJI_RARELY_USED, // 蜙 + 0x871E, KANJI_RARELY_USED, // 蜞 + 0x871F, KANJI_RARELY_USED, // 蜟 + 0x8721, KANJI_RARELY_USED, // 蜡 + 0x8723, KANJI_RARELY_USED, // 蜣 + 0x8728, KANJI_RARELY_USED, // 蜚 + 0x872E, KANJI_RARELY_USED, // 蜮 + 0x872F, KANJI_RARELY_USED, // 蜯 + 0x8731, KANJI_RARELY_USED, // 蜱 + 0x8732, KANJI_RARELY_USED, // 蜲 + 0x8739, KANJI_RARELY_USED, // 蜹 + 0x873A, KANJI_RARELY_USED, // 蜺 + 0x873C, KANJI_RARELY_USED, // 蜌 + 0x873D, KANJI_RARELY_USED, // 蜜 + 0x873E, KANJI_RARELY_USED, // 蜟 + 0x8740, KANJI_RARELY_USED, // 蝀 + 0x8743, KANJI_RARELY_USED, // 蝃 + 0x8745, KANJI_RARELY_USED, // 蝅 + 0x874D, KANJI_RARELY_USED, // 蝍 + 0x8758, KANJI_RARELY_USED, // 蝘 + 0x875D, KANJI_RARELY_USED, // 蝝 + 0x8761, KANJI_RARELY_USED, // 蝡 + 0x8764, KANJI_RARELY_USED, // 蝀 + 0x8765, KANJI_RARELY_USED, // 蝥 + 0x876F, KANJI_RARELY_USED, // 蝯 + 0x8771, KANJI_RARELY_USED, // 蝱 + 0x8772, KANJI_RARELY_USED, // 蝲 + 0x877B, KANJI_RARELY_USED, // 蝻 + 0x8783, KANJI_RARELY_USED, // 螃 + 0x8784, KANJI_RARELY_USED, // 螄 + 0x8785, KANJI_RARELY_USED, // 螅 + 0x8786, KANJI_RARELY_USED, // 螆 + 0x8787, KANJI_RARELY_USED, // 螇 + 0x8788, KANJI_RARELY_USED, // 螈 + 0x8789, KANJI_RARELY_USED, // 螉 + 0x878B, KANJI_RARELY_USED, // 螋 + 0x878C, KANJI_RARELY_USED, // 螌 + 0x8790, KANJI_RARELY_USED, // 螐 + 0x8793, KANJI_RARELY_USED, // 螓 + 0x8795, KANJI_RARELY_USED, // 螕 + 0x8797, KANJI_RARELY_USED, // 螗 + 0x8798, KANJI_RARELY_USED, // 螘 + 0x8799, KANJI_RARELY_USED, // 螙 + 0x879E, KANJI_RARELY_USED, // 螞 + 0x87A0, KANJI_RARELY_USED, // 螠 + 0x87A3, KANJI_RARELY_USED, // 螣 + 0x87A7, KANJI_RARELY_USED, // 螧 + 0x87AC, KANJI_RARELY_USED, // 螬 + 0x87AD, KANJI_RARELY_USED, // 螭 + 0x87AE, KANJI_RARELY_USED, // 螮 + 0x87B1, KANJI_RARELY_USED, // 螱 + 0x87B5, KANJI_RARELY_USED, // 螵 + 0x87BE, KANJI_RARELY_USED, // 螟 + 0x87BF, KANJI_RARELY_USED, // 螿 + 0x87C1, KANJI_RARELY_USED, // 蟁 + 0x87C8, KANJI_RARELY_USED, // 蟈 + 0x87C9, KANJI_RARELY_USED, // 蟉 + 0x87CA, KANJI_RARELY_USED, // 蟊 + 0x87CE, KANJI_RARELY_USED, // 蟎 + 0x87D5, KANJI_RARELY_USED, // 蟕 + 0x87D6, KANJI_RARELY_USED, // 蟖 + 0x87D9, KANJI_RARELY_USED, // 蟙 + 0x87DA, KANJI_RARELY_USED, // 蟚 + 0x87DC, KANJI_RARELY_USED, // 蟜 + 0x87DF, KANJI_RARELY_USED, // 蟟 + 0x87E2, KANJI_RARELY_USED, // 蟢 + 0x87E3, KANJI_RARELY_USED, // 蟣 + 0x87E4, KANJI_RARELY_USED, // 蟀 + 0x87EA, KANJI_RARELY_USED, // 蟪 + 0x87EB, KANJI_RARELY_USED, // 蟫 + 0x87ED, KANJI_RARELY_USED, // 蟭 + 0x87F1, KANJI_RARELY_USED, // 蟱 + 0x87F3, KANJI_RARELY_USED, // 蟳 + 0x87F8, KANJI_RARELY_USED, // 蟞 + 0x87FA, KANJI_RARELY_USED, // 蟺 + 0x87FF, KANJI_RARELY_USED, // 蟿 + 0x8801, KANJI_RARELY_USED, // 蠁 + 0x8803, KANJI_RARELY_USED, // 蠃 + 0x8806, KANJI_RARELY_USED, // 蠆 + 0x8809, KANJI_RARELY_USED, // 蠉 + 0x880A, KANJI_RARELY_USED, // 蠊 + 0x880B, KANJI_RARELY_USED, // 蠋 + 0x8810, KANJI_RARELY_USED, // 蠐 + 0x8819, KANJI_RARELY_USED, // 蠙 + 0x8812, KANJI_RARELY_USED, // 蠒 + 0x8813, KANJI_RARELY_USED, // 蠓 + 0x8814, KANJI_RARELY_USED, // 蠔 + 0x8818, KANJI_RARELY_USED, // 蠘 + 0x881A, KANJI_RARELY_USED, // 蠚 + 0x881B, KANJI_RARELY_USED, // 蠛 + 0x881C, KANJI_RARELY_USED, // 蠜 + 0x881E, KANJI_RARELY_USED, // 蠞 + 0x881F, KANJI_RARELY_USED, // 蠟 + 0x8828, KANJI_RARELY_USED, // è š + 0x882D, KANJI_RARELY_USED, // è ­ + 0x882E, KANJI_RARELY_USED, // è ® + 0x8830, KANJI_RARELY_USED, // è ° + 0x8832, KANJI_RARELY_USED, // è ² + 0x8835, KANJI_RARELY_USED, // è µ + 0x883A, KANJI_RARELY_USED, // è º + 0x883C, KANJI_RARELY_USED, // è Œ + 0x8841, KANJI_RARELY_USED, // 衁 + 0x8843, KANJI_RARELY_USED, // 衃 + 0x8845, KANJI_RARELY_USED, // 衅 + 0x8848, KANJI_RARELY_USED, // 衈 + 0x8849, KANJI_RARELY_USED, // 衉 + 0x884A, KANJI_RARELY_USED, // 衊 + 0x884B, KANJI_RARELY_USED, // 衋 + 0x884E, KANJI_RARELY_USED, // 衎 + 0x8851, KANJI_RARELY_USED, // 衑 + 0x8855, KANJI_RARELY_USED, // 衕 + 0x8856, KANJI_RARELY_USED, // 衖 + 0x8858, KANJI_RARELY_USED, // 衘 + 0x885A, KANJI_RARELY_USED, // 衚 + 0x885C, KANJI_RARELY_USED, // 衜 + 0x885F, KANJI_RARELY_USED, // 衟 + 0x8860, KANJI_RARELY_USED, // è¡  + 0x8864, KANJI_RARELY_USED, // è¡€ + 0x8869, KANJI_RARELY_USED, // è¡© + 0x8871, KANJI_RARELY_USED, // 衱 + 0x8879, KANJI_RARELY_USED, // 衹 + 0x887B, KANJI_RARELY_USED, // è¡» + 0x8880, KANJI_RARELY_USED, // 袀 + 0x8898, KANJI_RARELY_USED, // 袘 + 0x889A, KANJI_RARELY_USED, // 袚 + 0x889B, KANJI_RARELY_USED, // 袛 + 0x889C, KANJI_RARELY_USED, // 袜 + 0x889F, KANJI_RARELY_USED, // 袟 + 0x88A0, KANJI_RARELY_USED, // 袠 + 0x88A8, KANJI_RARELY_USED, // 袚 + 0x88AA, KANJI_RARELY_USED, // 袪 + 0x88BA, KANJI_RARELY_USED, // 袺 + 0x88BD, KANJI_RARELY_USED, // 袜 + 0x88BE, KANJI_RARELY_USED, // 袟 + 0x88C0, KANJI_RARELY_USED, // 裀 + 0x88CA, KANJI_RARELY_USED, // 裊 + 0x88CB, KANJI_RARELY_USED, // 裋 + 0x88CC, KANJI_RARELY_USED, // 裌 + 0x88CD, KANJI_RARELY_USED, // 裍 + 0x88CE, KANJI_RARELY_USED, // 裎 + 0x88D1, KANJI_RARELY_USED, // 裑 + 0x88D2, KANJI_RARELY_USED, // 裒 + 0x88D3, KANJI_RARELY_USED, // 裓 + 0x88DB, KANJI_RARELY_USED, // 裛 + 0x88DE, KANJI_RARELY_USED, // 裞 + 0x88E7, KANJI_RARELY_USED, // 裧 + 0x88EF, KANJI_RARELY_USED, // 裯 + 0x88F0, KANJI_RARELY_USED, // 裰 + 0x88F1, KANJI_RARELY_USED, // 裱 + 0x88F5, KANJI_RARELY_USED, // 裵 + 0x88F7, KANJI_RARELY_USED, // 裷 + 0x8901, KANJI_RARELY_USED, // 老 + 0x8906, KANJI_RARELY_USED, // 耆 + 0x890D, KANJI_RARELY_USED, // 耍 + 0x890E, KANJI_RARELY_USED, // 耎 + 0x890F, KANJI_RARELY_USED, // 耏 + 0x8915, KANJI_RARELY_USED, // 耕 + 0x8916, KANJI_RARELY_USED, // 耖 + 0x8918, KANJI_RARELY_USED, // 耘 + 0x8919, KANJI_RARELY_USED, // 耙 + 0x891A, KANJI_RARELY_USED, // 耚 + 0x891C, KANJI_RARELY_USED, // 耜 + 0x8920, KANJI_RARELY_USED, // 耠 + 0x8926, KANJI_RARELY_USED, // 耊 + 0x8927, KANJI_RARELY_USED, // 耧 + 0x8928, KANJI_RARELY_USED, // 耚 + 0x8930, KANJI_RARELY_USED, // 耰 + 0x8931, KANJI_RARELY_USED, // 耱 + 0x8932, KANJI_RARELY_USED, // 耲 + 0x8935, KANJI_RARELY_USED, // 耵 + 0x8939, KANJI_RARELY_USED, // 耹 + 0x893A, KANJI_RARELY_USED, // 耺 + 0x893E, KANJI_RARELY_USED, // 耟 + 0x8940, KANJI_RARELY_USED, // 襀 + 0x8942, KANJI_RARELY_USED, // 襂 + 0x8945, KANJI_RARELY_USED, // 襅 + 0x8946, KANJI_RARELY_USED, // 襆 + 0x8949, KANJI_RARELY_USED, // 襉 + 0x894F, KANJI_RARELY_USED, // 襏 + 0x8952, KANJI_RARELY_USED, // 襒 + 0x8957, KANJI_RARELY_USED, // 襗 + 0x895A, KANJI_RARELY_USED, // 襚 + 0x895B, KANJI_RARELY_USED, // 襛 + 0x895C, KANJI_RARELY_USED, // 襜 + 0x8961, KANJI_RARELY_USED, // 襡 + 0x8962, KANJI_RARELY_USED, // 襢 + 0x8963, KANJI_RARELY_USED, // 襣 + 0x896B, KANJI_RARELY_USED, // 襫 + 0x896E, KANJI_RARELY_USED, // 襮 + 0x8970, KANJI_RARELY_USED, // 襰 + 0x8973, KANJI_RARELY_USED, // 襳 + 0x8975, KANJI_RARELY_USED, // 襵 + 0x897A, KANJI_RARELY_USED, // 襺 + 0x897B, KANJI_RARELY_USED, // 襻 + 0x897C, KANJI_RARELY_USED, // 襌 + 0x897D, KANJI_RARELY_USED, // 襜 + 0x8989, KANJI_RARELY_USED, // 芉 + 0x898D, KANJI_RARELY_USED, // 芍 + 0x8990, KANJI_RARELY_USED, // 芐 + 0x8994, KANJI_RARELY_USED, // 芔 + 0x8995, KANJI_RARELY_USED, // 芕 + 0x899B, KANJI_RARELY_USED, // 芛 + 0x899C, KANJI_RARELY_USED, // 芜 + 0x899F, KANJI_RARELY_USED, // 芟 + 0x89A0, KANJI_RARELY_USED, // 芠 + 0x89A5, KANJI_RARELY_USED, // 芥 + 0x89B0, KANJI_RARELY_USED, // 芰 + 0x89B4, KANJI_RARELY_USED, // 芎 + 0x89B5, KANJI_RARELY_USED, // 芵 + 0x89B6, KANJI_RARELY_USED, // 芶 + 0x89B7, KANJI_RARELY_USED, // 芷 + 0x89BC, KANJI_RARELY_USED, // 芌 + 0x89D4, KANJI_RARELY_USED, // 觔 + 0x89D5, KANJI_RARELY_USED, // 觕 + 0x89D6, KANJI_RARELY_USED, // 觖 + 0x89D7, KANJI_RARELY_USED, // 觗 + 0x89D8, KANJI_RARELY_USED, // 觘 + 0x89E5, KANJI_RARELY_USED, // è§¥ + 0x89E9, KANJI_RARELY_USED, // è§© + 0x89EB, KANJI_RARELY_USED, // è§« + 0x89ED, KANJI_RARELY_USED, // è§­ + 0x89F1, KANJI_RARELY_USED, // è§± + 0x89F3, KANJI_RARELY_USED, // è§³ + 0x89F6, KANJI_RARELY_USED, // è§¶ + 0x89F9, KANJI_RARELY_USED, // è§¹ + 0x89FD, KANJI_RARELY_USED, // è§œ + 0x89FF, KANJI_RARELY_USED, // è§¿ + 0x8A04, KANJI_RARELY_USED, // èš„ + 0x8A05, KANJI_RARELY_USED, // èš… + 0x8A07, KANJI_RARELY_USED, // 蚇 + 0x8A0F, KANJI_RARELY_USED, // 蚏 + 0x8A11, KANJI_RARELY_USED, // èš‘ + 0x8A12, KANJI_RARELY_USED, // èš’ + 0x8A14, KANJI_RARELY_USED, // èš” + 0x8A15, KANJI_RARELY_USED, // èš• + 0x8A1E, KANJI_RARELY_USED, // 蚞 + 0x8A20, KANJI_RARELY_USED, // èš  + 0x8A22, KANJI_RARELY_USED, // 蚢 + 0x8A24, KANJI_RARELY_USED, // 蚀 + 0x8A26, KANJI_RARELY_USED, // 蚊 + 0x8A2B, KANJI_RARELY_USED, // èš« + 0x8A2C, KANJI_RARELY_USED, // 蚬 + 0x8A2F, KANJI_RARELY_USED, // 蚯 + 0x8A35, KANJI_RARELY_USED, // èšµ + 0x8A37, KANJI_RARELY_USED, // èš· + 0x8A3D, KANJI_RARELY_USED, // èšœ + 0x8A3E, KANJI_RARELY_USED, // 蚟 + 0x8A40, KANJI_RARELY_USED, // 詀 + 0x8A43, KANJI_RARELY_USED, // 詃 + 0x8A45, KANJI_RARELY_USED, // 詅 + 0x8A47, KANJI_RARELY_USED, // 詇 + 0x8A49, KANJI_RARELY_USED, // 詉 + 0x8A4D, KANJI_RARELY_USED, // 詍 + 0x8A4E, KANJI_RARELY_USED, // 詎 + 0x8A53, KANJI_RARELY_USED, // 詓 + 0x8A56, KANJI_RARELY_USED, // 詖 + 0x8A57, KANJI_RARELY_USED, // 詗 + 0x8A58, KANJI_RARELY_USED, // 詘 + 0x8A5C, KANJI_RARELY_USED, // 詜 + 0x8A5D, KANJI_RARELY_USED, // 詝 + 0x8A61, KANJI_RARELY_USED, // è©¡ + 0x8A65, KANJI_RARELY_USED, // è©¥ + 0x8A67, KANJI_RARELY_USED, // è©§ + 0x8A75, KANJI_RARELY_USED, // 詵 + 0x8A76, KANJI_RARELY_USED, // è©¶ + 0x8A77, KANJI_RARELY_USED, // è©· + 0x8A79, KANJI_RARELY_USED, // 詹 + 0x8A7A, KANJI_RARELY_USED, // 詺 + 0x8A7B, KANJI_RARELY_USED, // è©» + 0x8A7E, KANJI_RARELY_USED, // 詟 + 0x8A7F, KANJI_RARELY_USED, // è©¿ + 0x8A80, KANJI_RARELY_USED, // 誀 + 0x8A83, KANJI_RARELY_USED, // 誃 + 0x8A86, KANJI_RARELY_USED, // 誆 + 0x8A8B, KANJI_RARELY_USED, // 誋 + 0x8A8F, KANJI_RARELY_USED, // 誏 + 0x8A90, KANJI_RARELY_USED, // 誐 + 0x8A92, KANJI_RARELY_USED, // 誒 + 0x8A96, KANJI_RARELY_USED, // 誖 + 0x8A97, KANJI_RARELY_USED, // 誗 + 0x8A99, KANJI_RARELY_USED, // 誙 + 0x8A9F, KANJI_RARELY_USED, // 誟 + 0x8AA7, KANJI_RARELY_USED, // 誧 + 0x8AA9, KANJI_RARELY_USED, // 誩 + 0x8AAE, KANJI_RARELY_USED, // 誮 + 0x8AAF, KANJI_RARELY_USED, // 誯 + 0x8AB3, KANJI_RARELY_USED, // 誳 + 0x8AB6, KANJI_RARELY_USED, // 誶 + 0x8AB7, KANJI_RARELY_USED, // 誷 + 0x8ABB, KANJI_RARELY_USED, // 誻 + 0x8ABE, KANJI_RARELY_USED, // 誟 + 0x8AC3, KANJI_RARELY_USED, // 諃 + 0x8AC6, KANJI_RARELY_USED, // 諆 + 0x8AC8, KANJI_RARELY_USED, // 諈 + 0x8AC9, KANJI_RARELY_USED, // 諉 + 0x8ACA, KANJI_RARELY_USED, // 諊 + 0x8AD1, KANJI_RARELY_USED, // 諑 + 0x8AD3, KANJI_RARELY_USED, // 諓 + 0x8AD4, KANJI_RARELY_USED, // 諔 + 0x8AD5, KANJI_RARELY_USED, // 諕 + 0x8AD7, KANJI_RARELY_USED, // 諗 + 0x8ADD, KANJI_RARELY_USED, // 諝 + 0x8ADF, KANJI_RARELY_USED, // 諟 + 0x8AEC, KANJI_RARELY_USED, // 諬 + 0x8AF0, KANJI_RARELY_USED, // è«° + 0x8AF4, KANJI_RARELY_USED, // 諎 + 0x8AF5, KANJI_RARELY_USED, // 諵 + 0x8AF6, KANJI_RARELY_USED, // è«¶ + 0x8AFC, KANJI_RARELY_USED, // 諌 + 0x8AFF, KANJI_RARELY_USED, // è«¿ + 0x8B05, KANJI_RARELY_USED, // 謅 + 0x8B06, KANJI_RARELY_USED, // 謆 + 0x8B0B, KANJI_RARELY_USED, // 謋 + 0x8B11, KANJI_RARELY_USED, // 謑 + 0x8B1C, KANJI_RARELY_USED, // 謜 + 0x8B1E, KANJI_RARELY_USED, // 謞 + 0x8B1F, KANJI_RARELY_USED, // 謟 + 0x8B0A, KANJI_RARELY_USED, // 謊 + 0x8B2D, KANJI_RARELY_USED, // 謭 + 0x8B30, KANJI_RARELY_USED, // 謰 + 0x8B37, KANJI_RARELY_USED, // 謷 + 0x8B3C, KANJI_RARELY_USED, // 謌 + 0x8B42, KANJI_RARELY_USED, // 譂 + 0x8B43, KANJI_RARELY_USED, // 譃 + 0x8B44, KANJI_RARELY_USED, // 譄 + 0x8B45, KANJI_RARELY_USED, // 譅 + 0x8B46, KANJI_RARELY_USED, // 譆 + 0x8B48, KANJI_RARELY_USED, // 譈 + 0x8B52, KANJI_RARELY_USED, // 譒 + 0x8B53, KANJI_RARELY_USED, // 譓 + 0x8B54, KANJI_RARELY_USED, // 譔 + 0x8B59, KANJI_RARELY_USED, // 譙 + 0x8B4D, KANJI_RARELY_USED, // 譍 + 0x8B5E, KANJI_RARELY_USED, // 譞 + 0x8B63, KANJI_RARELY_USED, // è­£ + 0x8B6D, KANJI_RARELY_USED, // è­­ + 0x8B76, KANJI_RARELY_USED, // è­¶ + 0x8B78, KANJI_RARELY_USED, // è­ž + 0x8B79, KANJI_RARELY_USED, // è­¹ + 0x8B7C, KANJI_RARELY_USED, // è­Œ + 0x8B7E, KANJI_RARELY_USED, // è­Ÿ + 0x8B81, KANJI_RARELY_USED, // 讁 + 0x8B84, KANJI_RARELY_USED, // 讄 + 0x8B85, KANJI_RARELY_USED, // 讅 + 0x8B8B, KANJI_RARELY_USED, // 讋 + 0x8B8D, KANJI_RARELY_USED, // 讍 + 0x8B8F, KANJI_RARELY_USED, // 讏 + 0x8B94, KANJI_RARELY_USED, // 讔 + 0x8B95, KANJI_RARELY_USED, // 讕 + 0x8B9C, KANJI_RARELY_USED, // 讜 + 0x8B9E, KANJI_RARELY_USED, // 讞 + 0x8B9F, KANJI_RARELY_USED, // 讟 + 0x8C38, KANJI_RARELY_USED, // è°ž + 0x8C39, KANJI_RARELY_USED, // è°¹ + 0x8C3D, KANJI_RARELY_USED, // è°œ + 0x8C3E, KANJI_RARELY_USED, // è°Ÿ + 0x8C45, KANJI_RARELY_USED, // 豅 + 0x8C47, KANJI_RARELY_USED, // 豇 + 0x8C49, KANJI_RARELY_USED, // 豉 + 0x8C4B, KANJI_RARELY_USED, // 豋 + 0x8C4F, KANJI_RARELY_USED, // 豏 + 0x8C51, KANJI_RARELY_USED, // 豑 + 0x8C53, KANJI_RARELY_USED, // 豓 + 0x8C54, KANJI_RARELY_USED, // 豔 + 0x8C57, KANJI_RARELY_USED, // 豗 + 0x8C58, KANJI_RARELY_USED, // 豘 + 0x8C5B, KANJI_RARELY_USED, // 豛 + 0x8C5D, KANJI_RARELY_USED, // 豝 + 0x8C59, KANJI_RARELY_USED, // 豙 + 0x8C63, KANJI_RARELY_USED, // è±£ + 0x8C64, KANJI_RARELY_USED, // è±€ + 0x8C66, KANJI_RARELY_USED, // 豊 + 0x8C68, KANJI_RARELY_USED, // 豚 + 0x8C69, KANJI_RARELY_USED, // 豩 + 0x8C6D, KANJI_RARELY_USED, // è±­ + 0x8C73, KANJI_RARELY_USED, // è±³ + 0x8C75, KANJI_RARELY_USED, // è±µ + 0x8C76, KANJI_RARELY_USED, // è±¶ + 0x8C7B, KANJI_RARELY_USED, // è±» + 0x8C7E, KANJI_RARELY_USED, // 豟 + 0x8C86, KANJI_RARELY_USED, // 貆 + 0x8C87, KANJI_RARELY_USED, // 貇 + 0x8C8B, KANJI_RARELY_USED, // 貋 + 0x8C90, KANJI_RARELY_USED, // 貐 + 0x8C92, KANJI_RARELY_USED, // 貒 + 0x8C93, KANJI_RARELY_USED, // 貓 + 0x8C99, KANJI_RARELY_USED, // 貙 + 0x8C9B, KANJI_RARELY_USED, // 貛 + 0x8C9C, KANJI_RARELY_USED, // 貜 + 0x8CA4, KANJI_RARELY_USED, // è²€ + 0x8CB9, KANJI_RARELY_USED, // è²¹ + 0x8CBA, KANJI_RARELY_USED, // 貺 + 0x8CC5, KANJI_RARELY_USED, // 賅 + 0x8CC6, KANJI_RARELY_USED, // 賆 + 0x8CC9, KANJI_RARELY_USED, // 賉 + 0x8CCB, KANJI_RARELY_USED, // 賋 + 0x8CCF, KANJI_RARELY_USED, // 賏 + 0x8CD6, KANJI_RARELY_USED, // 賖 + 0x8CD5, KANJI_RARELY_USED, // 賕 + 0x8CD9, KANJI_RARELY_USED, // 賙 + 0x8CDD, KANJI_RARELY_USED, // 賝 + 0x8CE1, KANJI_RARELY_USED, // 賡 + 0x8CE8, KANJI_RARELY_USED, // 賚 + 0x8CEC, KANJI_RARELY_USED, // 賬 + 0x8CEF, KANJI_RARELY_USED, // 賯 + 0x8CF0, KANJI_RARELY_USED, // è³° + 0x8CF2, KANJI_RARELY_USED, // è³² + 0x8CF5, KANJI_RARELY_USED, // è³µ + 0x8CF7, KANJI_RARELY_USED, // è³· + 0x8CF8, KANJI_RARELY_USED, // 賞 + 0x8CFE, KANJI_RARELY_USED, // 賟 + 0x8CFF, KANJI_RARELY_USED, // 賿 + 0x8D01, KANJI_RARELY_USED, // 莁 + 0x8D03, KANJI_RARELY_USED, // 莃 + 0x8D09, KANJI_RARELY_USED, // 莉 + 0x8D12, KANJI_RARELY_USED, // 莒 + 0x8D17, KANJI_RARELY_USED, // 莗 + 0x8D1B, KANJI_RARELY_USED, // 莛 + 0x8D65, KANJI_RARELY_USED, // èµ¥ + 0x8D69, KANJI_RARELY_USED, // 赩 + 0x8D6C, KANJI_RARELY_USED, // 赬 + 0x8D6E, KANJI_RARELY_USED, // èµ® + 0x8D7F, KANJI_RARELY_USED, // 赿 + 0x8D82, KANJI_RARELY_USED, // 趂 + 0x8D84, KANJI_RARELY_USED, // 趄 + 0x8D88, KANJI_RARELY_USED, // 趈 + 0x8D8D, KANJI_RARELY_USED, // 趍 + 0x8D90, KANJI_RARELY_USED, // 趐 + 0x8D91, KANJI_RARELY_USED, // 趑 + 0x8D95, KANJI_RARELY_USED, // 趕 + 0x8D9E, KANJI_RARELY_USED, // 趞 + 0x8D9F, KANJI_RARELY_USED, // 趟 + 0x8DA0, KANJI_RARELY_USED, // è¶  + 0x8DA6, KANJI_RARELY_USED, // è¶Š + 0x8DAB, KANJI_RARELY_USED, // è¶« + 0x8DAC, KANJI_RARELY_USED, // 趬 + 0x8DAF, KANJI_RARELY_USED, // 趯 + 0x8DB2, KANJI_RARELY_USED, // è¶² + 0x8DB5, KANJI_RARELY_USED, // è¶µ + 0x8DB7, KANJI_RARELY_USED, // è¶· + 0x8DB9, KANJI_RARELY_USED, // è¶¹ + 0x8DBB, KANJI_RARELY_USED, // è¶» + 0x8DC0, KANJI_RARELY_USED, // 跀 + 0x8DC5, KANJI_RARELY_USED, // 跅 + 0x8DC6, KANJI_RARELY_USED, // 跆 + 0x8DC7, KANJI_RARELY_USED, // 跇 + 0x8DC8, KANJI_RARELY_USED, // 跈 + 0x8DCA, KANJI_RARELY_USED, // 跊 + 0x8DCE, KANJI_RARELY_USED, // 跎 + 0x8DD1, KANJI_RARELY_USED, // 跑 + 0x8DD4, KANJI_RARELY_USED, // 跔 + 0x8DD5, KANJI_RARELY_USED, // 跕 + 0x8DD7, KANJI_RARELY_USED, // 跗 + 0x8DD9, KANJI_RARELY_USED, // 跙 + 0x8DE4, KANJI_RARELY_USED, // è·€ + 0x8DE5, KANJI_RARELY_USED, // è·¥ + 0x8DE7, KANJI_RARELY_USED, // è·§ + 0x8DEC, KANJI_RARELY_USED, // è·¬ + 0x8DF0, KANJI_RARELY_USED, // è·° + 0x8DBC, KANJI_RARELY_USED, // è¶Œ + 0x8DF1, KANJI_RARELY_USED, // è·± + 0x8DF2, KANJI_RARELY_USED, // è·² + 0x8DF4, KANJI_RARELY_USED, // è·Ž + 0x8DFD, KANJI_RARELY_USED, // è·œ + 0x8E01, KANJI_RARELY_USED, // 螁 + 0x8E04, KANJI_RARELY_USED, // èž„ + 0x8E05, KANJI_RARELY_USED, // èž… + 0x8E06, KANJI_RARELY_USED, // 螆 + 0x8E0B, KANJI_RARELY_USED, // èž‹ + 0x8E11, KANJI_RARELY_USED, // èž‘ + 0x8E14, KANJI_RARELY_USED, // èž” + 0x8E16, KANJI_RARELY_USED, // èž– + 0x8E20, KANJI_RARELY_USED, // èž  + 0x8E21, KANJI_RARELY_USED, // èž¡ + 0x8E22, KANJI_RARELY_USED, // 螢 + 0x8E23, KANJI_RARELY_USED, // 螣 + 0x8E26, KANJI_RARELY_USED, // 螊 + 0x8E27, KANJI_RARELY_USED, // èž§ + 0x8E31, KANJI_RARELY_USED, // èž± + 0x8E33, KANJI_RARELY_USED, // èž³ + 0x8E36, KANJI_RARELY_USED, // èž¶ + 0x8E37, KANJI_RARELY_USED, // èž· + 0x8E38, KANJI_RARELY_USED, // èžž + 0x8E39, KANJI_RARELY_USED, // èž¹ + 0x8E3D, KANJI_RARELY_USED, // èžœ + 0x8E40, KANJI_RARELY_USED, // 蹀 + 0x8E41, KANJI_RARELY_USED, // 蹁 + 0x8E4B, KANJI_RARELY_USED, // 蹋 + 0x8E4D, KANJI_RARELY_USED, // 蹍 + 0x8E4E, KANJI_RARELY_USED, // 蹎 + 0x8E4F, KANJI_RARELY_USED, // 蹏 + 0x8E54, KANJI_RARELY_USED, // 蹔 + 0x8E5B, KANJI_RARELY_USED, // 蹛 + 0x8E5C, KANJI_RARELY_USED, // 蹜 + 0x8E5D, KANJI_RARELY_USED, // 蹝 + 0x8E5E, KANJI_RARELY_USED, // 蹞 + 0x8E61, KANJI_RARELY_USED, // 蹡 + 0x8E62, KANJI_RARELY_USED, // è¹¢ + 0x8E69, KANJI_RARELY_USED, // 蹩 + 0x8E6C, KANJI_RARELY_USED, // 蹬 + 0x8E6D, KANJI_RARELY_USED, // è¹­ + 0x8E6F, KANJI_RARELY_USED, // 蹯 + 0x8E70, KANJI_RARELY_USED, // è¹° + 0x8E71, KANJI_RARELY_USED, // è¹± + 0x8E79, KANJI_RARELY_USED, // è¹¹ + 0x8E7A, KANJI_RARELY_USED, // 蹺 + 0x8E7B, KANJI_RARELY_USED, // è¹» + 0x8E82, KANJI_RARELY_USED, // 躂 + 0x8E83, KANJI_RARELY_USED, // 躃 + 0x8E89, KANJI_RARELY_USED, // 躉 + 0x8E90, KANJI_RARELY_USED, // 躐 + 0x8E92, KANJI_RARELY_USED, // 躒 + 0x8E95, KANJI_RARELY_USED, // 躕 + 0x8E9A, KANJI_RARELY_USED, // 躚 + 0x8E9B, KANJI_RARELY_USED, // 躛 + 0x8E9D, KANJI_RARELY_USED, // 躝 + 0x8E9E, KANJI_RARELY_USED, // 躞 + 0x8EA2, KANJI_RARELY_USED, // 躢 + 0x8EA7, KANJI_RARELY_USED, // 躧 + 0x8EA9, KANJI_RARELY_USED, // 躩 + 0x8EAD, KANJI_RARELY_USED, // 躭 + 0x8EAE, KANJI_RARELY_USED, // 躮 + 0x8EB3, KANJI_RARELY_USED, // 躳 + 0x8EB5, KANJI_RARELY_USED, // 躵 + 0x8EBA, KANJI_RARELY_USED, // 躺 + 0x8EBB, KANJI_RARELY_USED, // 躻 + 0x8EC0, KANJI_RARELY_USED, // 軀 + 0x8EC1, KANJI_RARELY_USED, // 軁 + 0x8EC3, KANJI_RARELY_USED, // 軃 + 0x8EC4, KANJI_RARELY_USED, // 軄 + 0x8EC7, KANJI_RARELY_USED, // 軇 + 0x8ECF, KANJI_RARELY_USED, // 軏 + 0x8ED1, KANJI_RARELY_USED, // 軑 + 0x8ED4, KANJI_RARELY_USED, // 軔 + 0x8EDC, KANJI_RARELY_USED, // 軜 + 0x8EE8, KANJI_RARELY_USED, // 軚 + 0x8EEE, KANJI_RARELY_USED, // è»® + 0x8EF0, KANJI_RARELY_USED, // è»° + 0x8EF1, KANJI_RARELY_USED, // è»± + 0x8EF7, KANJI_RARELY_USED, // è»· + 0x8EF9, KANJI_RARELY_USED, // 軹 + 0x8EFA, KANJI_RARELY_USED, // 軺 + 0x8EED, KANJI_RARELY_USED, // è»­ + 0x8F00, KANJI_RARELY_USED, // 茀 + 0x8F02, KANJI_RARELY_USED, // 茂 + 0x8F07, KANJI_RARELY_USED, // 茇 + 0x8F08, KANJI_RARELY_USED, // 茈 + 0x8F0F, KANJI_RARELY_USED, // 茏 + 0x8F10, KANJI_RARELY_USED, // 茐 + 0x8F16, KANJI_RARELY_USED, // 茖 + 0x8F17, KANJI_RARELY_USED, // 茗 + 0x8F18, KANJI_RARELY_USED, // 茘 + 0x8F1E, KANJI_RARELY_USED, // 茞 + 0x8F20, KANJI_RARELY_USED, // 茠 + 0x8F21, KANJI_RARELY_USED, // 茡 + 0x8F23, KANJI_RARELY_USED, // 茣 + 0x8F25, KANJI_RARELY_USED, // 茥 + 0x8F27, KANJI_RARELY_USED, // 茧 + 0x8F28, KANJI_RARELY_USED, // 茚 + 0x8F2C, KANJI_RARELY_USED, // 茬 + 0x8F2D, KANJI_RARELY_USED, // 茭 + 0x8F2E, KANJI_RARELY_USED, // 茮 + 0x8F34, KANJI_RARELY_USED, // 茎 + 0x8F35, KANJI_RARELY_USED, // 茵 + 0x8F36, KANJI_RARELY_USED, // 茶 + 0x8F37, KANJI_RARELY_USED, // 茷 + 0x8F3A, KANJI_RARELY_USED, // 茺 + 0x8F40, KANJI_RARELY_USED, // 蜀 + 0x8F41, KANJI_RARELY_USED, // 蜁 + 0x8F43, KANJI_RARELY_USED, // 蜃 + 0x8F47, KANJI_RARELY_USED, // 蜇 + 0x8F4F, KANJI_RARELY_USED, // 蜏 + 0x8F51, KANJI_RARELY_USED, // 蜑 + 0x8F52, KANJI_RARELY_USED, // 蜒 + 0x8F53, KANJI_RARELY_USED, // 蜓 + 0x8F54, KANJI_RARELY_USED, // 蜔 + 0x8F55, KANJI_RARELY_USED, // 蜕 + 0x8F58, KANJI_RARELY_USED, // 蜘 + 0x8F5D, KANJI_RARELY_USED, // 蜝 + 0x8F5E, KANJI_RARELY_USED, // 蜞 + 0x8F65, KANJI_RARELY_USED, // 蜥 + 0x8F9D, KANJI_RARELY_USED, // 蟝 + 0x8FA0, KANJI_RARELY_USED, // 蟠 + 0x8FA1, KANJI_RARELY_USED, // 蟡 + 0x8FA4, KANJI_RARELY_USED, // 蟀 + 0x8FA5, KANJI_RARELY_USED, // 蟥 + 0x8FA6, KANJI_RARELY_USED, // 蟊 + 0x8FB5, KANJI_RARELY_USED, // 蟵 + 0x8FB6, KANJI_RARELY_USED, // 蟶 + 0x8FB8, KANJI_RARELY_USED, // 蟞 + 0x8FBE, KANJI_RARELY_USED, // 蟟 + 0x8FC0, KANJI_RARELY_USED, // 迀 + 0x8FC1, KANJI_RARELY_USED, // 迁 + 0x8FC6, KANJI_RARELY_USED, // 迆 + 0x8FCA, KANJI_RARELY_USED, // 迊 + 0x8FCB, KANJI_RARELY_USED, // 迋 + 0x8FCD, KANJI_RARELY_USED, // 迍 + 0x8FD0, KANJI_RARELY_USED, // 运 + 0x8FD2, KANJI_RARELY_USED, // 迒 + 0x8FD3, KANJI_RARELY_USED, // 迓 + 0x8FD5, KANJI_RARELY_USED, // 迕 + 0x8FE0, KANJI_RARELY_USED, // è¿  + 0x8FE3, KANJI_RARELY_USED, // è¿£ + 0x8FE4, KANJI_RARELY_USED, // è¿€ + 0x8FE8, KANJI_RARELY_USED, // 迚 + 0x8FEE, KANJI_RARELY_USED, // è¿® + 0x8FF1, KANJI_RARELY_USED, // 迱 + 0x8FF5, KANJI_RARELY_USED, // 迵 + 0x8FF6, KANJI_RARELY_USED, // è¿¶ + 0x8FFB, KANJI_RARELY_USED, // è¿» + 0x8FFE, KANJI_RARELY_USED, // 迟 + 0x9002, KANJI_RARELY_USED, // 适 + 0x9004, KANJI_RARELY_USED, // 逄 + 0x9008, KANJI_RARELY_USED, // 逈 + 0x900C, KANJI_RARELY_USED, // 逌 + 0x9018, KANJI_RARELY_USED, // 逘 + 0x901B, KANJI_RARELY_USED, // 逛 + 0x9028, KANJI_RARELY_USED, // 逹 + 0x9029, KANJI_RARELY_USED, // 逩 + 0x902F, KANJI_RARELY_USED, // 逯 + 0x902A, KANJI_RARELY_USED, // 逪 + 0x902C, KANJI_RARELY_USED, // 逬 + 0x902D, KANJI_RARELY_USED, // 逭 + 0x9033, KANJI_RARELY_USED, // 逳 + 0x9034, KANJI_RARELY_USED, // 逮 + 0x9037, KANJI_RARELY_USED, // 逷 + 0x903F, KANJI_RARELY_USED, // 逿 + 0x9043, KANJI_RARELY_USED, // 遃 + 0x9044, KANJI_RARELY_USED, // 遄 + 0x904C, KANJI_RARELY_USED, // 遌 + 0x905B, KANJI_RARELY_USED, // 遛 + 0x905D, KANJI_RARELY_USED, // 遝 + 0x9062, KANJI_RARELY_USED, // 遢 + 0x9066, KANJI_RARELY_USED, // 遊 + 0x9067, KANJI_RARELY_USED, // 遧 + 0x906C, KANJI_RARELY_USED, // 遬 + 0x9070, KANJI_RARELY_USED, // 遰 + 0x9074, KANJI_RARELY_USED, // 過 + 0x9079, KANJI_RARELY_USED, // 遹 + 0x9085, KANJI_RARELY_USED, // 邅 + 0x9088, KANJI_RARELY_USED, // 邈 + 0x908B, KANJI_RARELY_USED, // 邋 + 0x908C, KANJI_RARELY_USED, // 邌 + 0x908E, KANJI_RARELY_USED, // 邎 + 0x9090, KANJI_RARELY_USED, // 邐 + 0x9095, KANJI_RARELY_USED, // 邕 + 0x9097, KANJI_RARELY_USED, // 邗 + 0x9098, KANJI_RARELY_USED, // 邘 + 0x9099, KANJI_RARELY_USED, // 邙 + 0x909B, KANJI_RARELY_USED, // 邛 + 0x90A0, KANJI_RARELY_USED, // 邠 + 0x90A1, KANJI_RARELY_USED, // 邡 + 0x90A2, KANJI_RARELY_USED, // 邢 + 0x90A5, KANJI_RARELY_USED, // 邥 + 0x90B0, KANJI_RARELY_USED, // 邰 + 0x90B2, KANJI_RARELY_USED, // 邲 + 0x90B3, KANJI_RARELY_USED, // 邳 + 0x90B4, KANJI_RARELY_USED, // 邮 + 0x90B6, KANJI_RARELY_USED, // 邶 + 0x90BD, KANJI_RARELY_USED, // 邜 + 0x90CC, KANJI_RARELY_USED, // 郌 + 0x90BE, KANJI_RARELY_USED, // 邟 + 0x90C3, KANJI_RARELY_USED, // 郃 + 0x90C4, KANJI_RARELY_USED, // 郄 + 0x90C5, KANJI_RARELY_USED, // 郅 + 0x90C7, KANJI_RARELY_USED, // 郇 + 0x90C8, KANJI_RARELY_USED, // 郈 + 0x90D5, KANJI_RARELY_USED, // 郕 + 0x90D7, KANJI_RARELY_USED, // 郗 + 0x90D8, KANJI_RARELY_USED, // 郘 + 0x90D9, KANJI_RARELY_USED, // 郙 + 0x90DC, KANJI_RARELY_USED, // 郜 + 0x90DD, KANJI_RARELY_USED, // 郝 + 0x90DF, KANJI_RARELY_USED, // 郟 + 0x90E5, KANJI_RARELY_USED, // 郥 + 0x90D2, KANJI_RARELY_USED, // 郒 + 0x90F6, KANJI_RARELY_USED, // 郶 + 0x90EB, KANJI_RARELY_USED, // 郫 + 0x90EF, KANJI_RARELY_USED, // 郯 + 0x90F0, KANJI_RARELY_USED, // 郰 + 0x90F4, KANJI_RARELY_USED, // 郎 + 0x90FE, KANJI_RARELY_USED, // 郟 + 0x90FF, KANJI_RARELY_USED, // 郿 + 0x9100, KANJI_RARELY_USED, // 鄀 + 0x9104, KANJI_RARELY_USED, // 鄄 + 0x9105, KANJI_RARELY_USED, // 鄅 + 0x9106, KANJI_RARELY_USED, // 鄆 + 0x9108, KANJI_RARELY_USED, // 鄈 + 0x910D, KANJI_RARELY_USED, // 鄍 + 0x9110, KANJI_RARELY_USED, // 鄐 + 0x9114, KANJI_RARELY_USED, // 鄔 + 0x9116, KANJI_RARELY_USED, // 鄖 + 0x9117, KANJI_RARELY_USED, // 鄗 + 0x9118, KANJI_RARELY_USED, // 鄘 + 0x911A, KANJI_RARELY_USED, // 鄚 + 0x911C, KANJI_RARELY_USED, // 鄜 + 0x911E, KANJI_RARELY_USED, // 鄞 + 0x9120, KANJI_RARELY_USED, // 鄠 + 0x9125, KANJI_RARELY_USED, // 鄥 + 0x9122, KANJI_RARELY_USED, // 鄢 + 0x9123, KANJI_RARELY_USED, // 鄣 + 0x9127, KANJI_RARELY_USED, // 鄧 + 0x9129, KANJI_RARELY_USED, // 鄩 + 0x912E, KANJI_RARELY_USED, // 鄮 + 0x912F, KANJI_RARELY_USED, // 鄯 + 0x9131, KANJI_RARELY_USED, // 鄱 + 0x9134, KANJI_RARELY_USED, // 鄮 + 0x9136, KANJI_RARELY_USED, // 鄶 + 0x9137, KANJI_RARELY_USED, // 鄷 + 0x9139, KANJI_RARELY_USED, // 鄹 + 0x913A, KANJI_RARELY_USED, // 鄺 + 0x913C, KANJI_RARELY_USED, // 鄌 + 0x913D, KANJI_RARELY_USED, // 鄜 + 0x9143, KANJI_RARELY_USED, // 酃 + 0x9147, KANJI_RARELY_USED, // 酇 + 0x9148, KANJI_RARELY_USED, // 酈 + 0x914F, KANJI_RARELY_USED, // 酏 + 0x9153, KANJI_RARELY_USED, // 酓 + 0x9157, KANJI_RARELY_USED, // 酗 + 0x9159, KANJI_RARELY_USED, // 酙 + 0x915A, KANJI_RARELY_USED, // 酚 + 0x915B, KANJI_RARELY_USED, // 酛 + 0x9161, KANJI_RARELY_USED, // 酡 + 0x9164, KANJI_RARELY_USED, // é…€ + 0x9167, KANJI_RARELY_USED, // 酧 + 0x916D, KANJI_RARELY_USED, // 酭 + 0x9174, KANJI_RARELY_USED, // 酮 + 0x9179, KANJI_RARELY_USED, // 酹 + 0x917A, KANJI_RARELY_USED, // 酺 + 0x917B, KANJI_RARELY_USED, // 酻 + 0x9181, KANJI_RARELY_USED, // 醁 + 0x9183, KANJI_RARELY_USED, // 醃 + 0x9185, KANJI_RARELY_USED, // 醅 + 0x9186, KANJI_RARELY_USED, // 醆 + 0x918A, KANJI_RARELY_USED, // 醊 + 0x918E, KANJI_RARELY_USED, // 醎 + 0x9191, KANJI_RARELY_USED, // 醑 + 0x9193, KANJI_RARELY_USED, // 醓 + 0x9194, KANJI_RARELY_USED, // 醔 + 0x9195, KANJI_RARELY_USED, // 醕 + 0x9198, KANJI_RARELY_USED, // 醘 + 0x919E, KANJI_RARELY_USED, // 醞 + 0x91A1, KANJI_RARELY_USED, // 醡 + 0x91A6, KANJI_RARELY_USED, // 醩 + 0x91A8, KANJI_RARELY_USED, // 醹 + 0x91AC, KANJI_RARELY_USED, // 醬 + 0x91AD, KANJI_RARELY_USED, // 醭 + 0x91AE, KANJI_RARELY_USED, // 醮 + 0x91B0, KANJI_RARELY_USED, // 醰 + 0x91B1, KANJI_RARELY_USED, // 醱 + 0x91B2, KANJI_RARELY_USED, // 醲 + 0x91B3, KANJI_RARELY_USED, // 醳 + 0x91B6, KANJI_RARELY_USED, // 醶 + 0x91BB, KANJI_RARELY_USED, // 醻 + 0x91BC, KANJI_RARELY_USED, // 醌 + 0x91BD, KANJI_RARELY_USED, // 醜 + 0x91BF, KANJI_RARELY_USED, // 醿 + 0x91C2, KANJI_RARELY_USED, // 釂 + 0x91C3, KANJI_RARELY_USED, // 釃 + 0x91C5, KANJI_RARELY_USED, // 釅 + 0x91D3, KANJI_RARELY_USED, // 釓 + 0x91D4, KANJI_RARELY_USED, // 釔 + 0x91D7, KANJI_RARELY_USED, // 釗 + 0x91D9, KANJI_RARELY_USED, // 釙 + 0x91DA, KANJI_RARELY_USED, // 釚 + 0x91DE, KANJI_RARELY_USED, // 釞 + 0x91E4, KANJI_RARELY_USED, // 釀 + 0x91E5, KANJI_RARELY_USED, // 釥 + 0x91E9, KANJI_RARELY_USED, // 釩 + 0x91EA, KANJI_RARELY_USED, // 釪 + 0x91EC, KANJI_RARELY_USED, // 釬 + 0x91ED, KANJI_RARELY_USED, // 釭 + 0x91EE, KANJI_RARELY_USED, // 釮 + 0x91EF, KANJI_RARELY_USED, // 釯 + 0x91F0, KANJI_RARELY_USED, // 釰 + 0x91F1, KANJI_RARELY_USED, // 釱 + 0x91F7, KANJI_RARELY_USED, // 釷 + 0x91F9, KANJI_RARELY_USED, // 釹 + 0x91FB, KANJI_RARELY_USED, // 釻 + 0x91FD, KANJI_RARELY_USED, // 釜 + 0x9200, KANJI_RARELY_USED, // 鈀 + 0x9201, KANJI_RARELY_USED, // 鈁 + 0x9204, KANJI_RARELY_USED, // 鈄 + 0x9205, KANJI_RARELY_USED, // 鈅 + 0x9206, KANJI_RARELY_USED, // 鈆 + 0x9207, KANJI_RARELY_USED, // 鈇 + 0x9209, KANJI_RARELY_USED, // 鈉 + 0x920A, KANJI_RARELY_USED, // 鈊 + 0x920C, KANJI_RARELY_USED, // 鈌 + 0x9210, KANJI_RARELY_USED, // 鈐 + 0x9212, KANJI_RARELY_USED, // 鈒 + 0x9213, KANJI_RARELY_USED, // 鈓 + 0x9216, KANJI_RARELY_USED, // 鈖 + 0x9218, KANJI_RARELY_USED, // 鈘 + 0x921C, KANJI_RARELY_USED, // 鈜 + 0x921D, KANJI_RARELY_USED, // 鈝 + 0x9223, KANJI_RARELY_USED, // 鈣 + 0x9224, KANJI_RARELY_USED, // 鈀 + 0x9225, KANJI_RARELY_USED, // 鈥 + 0x9226, KANJI_RARELY_USED, // 鈊 + 0x9228, KANJI_RARELY_USED, // 鈚 + 0x922E, KANJI_RARELY_USED, // 鈮 + 0x922F, KANJI_RARELY_USED, // 鈯 + 0x9230, KANJI_RARELY_USED, // 鈰 + 0x9233, KANJI_RARELY_USED, // 鈳 + 0x9235, KANJI_RARELY_USED, // 鈵 + 0x9236, KANJI_RARELY_USED, // 鈶 + 0x9238, KANJI_RARELY_USED, // 鈞 + 0x9239, KANJI_RARELY_USED, // 鈹 + 0x923A, KANJI_RARELY_USED, // 鈺 + 0x923C, KANJI_RARELY_USED, // 鈌 + 0x923E, KANJI_RARELY_USED, // 鈟 + 0x9240, KANJI_RARELY_USED, // 鉀 + 0x9242, KANJI_RARELY_USED, // 鉂 + 0x9243, KANJI_RARELY_USED, // 鉃 + 0x9246, KANJI_RARELY_USED, // 鉆 + 0x9247, KANJI_RARELY_USED, // 鉇 + 0x924A, KANJI_RARELY_USED, // 鉊 + 0x924D, KANJI_RARELY_USED, // 鉍 + 0x924E, KANJI_RARELY_USED, // 鉎 + 0x924F, KANJI_RARELY_USED, // 鉏 + 0x9251, KANJI_RARELY_USED, // 鉑 + 0x9258, KANJI_RARELY_USED, // 鉘 + 0x9259, KANJI_RARELY_USED, // 鉙 + 0x925C, KANJI_RARELY_USED, // 鉜 + 0x925D, KANJI_RARELY_USED, // 鉝 + 0x9260, KANJI_RARELY_USED, // 鉠 + 0x9261, KANJI_RARELY_USED, // 鉡 + 0x9265, KANJI_RARELY_USED, // 鉥 + 0x9267, KANJI_RARELY_USED, // 鉧 + 0x9268, KANJI_RARELY_USED, // 鉹 + 0x9269, KANJI_RARELY_USED, // 鉩 + 0x926E, KANJI_RARELY_USED, // 鉮 + 0x926F, KANJI_RARELY_USED, // 鉯 + 0x9270, KANJI_RARELY_USED, // 鉰 + 0x9275, KANJI_RARELY_USED, // 鉵 + 0x9276, KANJI_RARELY_USED, // 鉶 + 0x9277, KANJI_RARELY_USED, // 鉷 + 0x9278, KANJI_RARELY_USED, // 鉾 + 0x9279, KANJI_RARELY_USED, // 鉹 + 0x927B, KANJI_RARELY_USED, // 鉻 + 0x927C, KANJI_RARELY_USED, // 鉌 + 0x927D, KANJI_RARELY_USED, // 鉜 + 0x927F, KANJI_RARELY_USED, // 鉿 + 0x9288, KANJI_RARELY_USED, // 銈 + 0x9289, KANJI_RARELY_USED, // 銉 + 0x928A, KANJI_RARELY_USED, // 銊 + 0x928D, KANJI_RARELY_USED, // 銍 + 0x928E, KANJI_RARELY_USED, // 銎 + 0x9292, KANJI_RARELY_USED, // 銒 + 0x9297, KANJI_RARELY_USED, // 銗 + 0x9299, KANJI_RARELY_USED, // 銙 + 0x929F, KANJI_RARELY_USED, // 銟 + 0x92A0, KANJI_RARELY_USED, // 銠 + 0x92A4, KANJI_RARELY_USED, // 銀 + 0x92A5, KANJI_RARELY_USED, // 銥 + 0x92A7, KANJI_RARELY_USED, // 銧 + 0x92A8, KANJI_RARELY_USED, // 銹 + 0x92AB, KANJI_RARELY_USED, // 銫 + 0x92AF, KANJI_RARELY_USED, // 銯 + 0x92B2, KANJI_RARELY_USED, // 銲 + 0x92B6, KANJI_RARELY_USED, // 銶 + 0x92B8, KANJI_RARELY_USED, // 銾 + 0x92BA, KANJI_RARELY_USED, // 銺 + 0x92BB, KANJI_RARELY_USED, // 銻 + 0x92BC, KANJI_RARELY_USED, // 銌 + 0x92BD, KANJI_RARELY_USED, // 銜 + 0x92BF, KANJI_RARELY_USED, // 銿 + 0x92C0, KANJI_RARELY_USED, // 鋀 + 0x92C1, KANJI_RARELY_USED, // 鋁 + 0x92C2, KANJI_RARELY_USED, // 鋂 + 0x92C3, KANJI_RARELY_USED, // 鋃 + 0x92C5, KANJI_RARELY_USED, // 鋅 + 0x92C6, KANJI_RARELY_USED, // 鋆 + 0x92C7, KANJI_RARELY_USED, // 鋇 + 0x92C8, KANJI_RARELY_USED, // 鋈 + 0x92CB, KANJI_RARELY_USED, // 鋋 + 0x92CC, KANJI_RARELY_USED, // 鋌 + 0x92CD, KANJI_RARELY_USED, // 鋍 + 0x92CE, KANJI_RARELY_USED, // 鋎 + 0x92D0, KANJI_RARELY_USED, // 鋐 + 0x92D3, KANJI_RARELY_USED, // 鋓 + 0x92D5, KANJI_RARELY_USED, // 鋕 + 0x92D7, KANJI_RARELY_USED, // 鋗 + 0x92D8, KANJI_RARELY_USED, // 鋘 + 0x92D9, KANJI_RARELY_USED, // 鋙 + 0x92DC, KANJI_RARELY_USED, // 鋜 + 0x92DD, KANJI_RARELY_USED, // 鋝 + 0x92DF, KANJI_RARELY_USED, // 鋟 + 0x92E0, KANJI_RARELY_USED, // 鋠 + 0x92E1, KANJI_RARELY_USED, // 鋡 + 0x92E3, KANJI_RARELY_USED, // 鋣 + 0x92E5, KANJI_RARELY_USED, // 鋥 + 0x92E7, KANJI_RARELY_USED, // 鋧 + 0x92E8, KANJI_RARELY_USED, // 鋹 + 0x92EC, KANJI_RARELY_USED, // 鋬 + 0x92EE, KANJI_RARELY_USED, // 鋮 + 0x92F0, KANJI_RARELY_USED, // 鋰 + 0x92F9, KANJI_RARELY_USED, // 鋹 + 0x92FB, KANJI_RARELY_USED, // 鋻 + 0x92FF, KANJI_RARELY_USED, // 鋿 + 0x9300, KANJI_RARELY_USED, // 錀 + 0x9302, KANJI_RARELY_USED, // 錂 + 0x9308, KANJI_RARELY_USED, // 錈 + 0x930D, KANJI_RARELY_USED, // 錍 + 0x9311, KANJI_RARELY_USED, // 錑 + 0x9314, KANJI_RARELY_USED, // 錔 + 0x9315, KANJI_RARELY_USED, // 錕 + 0x931C, KANJI_RARELY_USED, // 錜 + 0x931D, KANJI_RARELY_USED, // 錝 + 0x931E, KANJI_RARELY_USED, // 錞 + 0x931F, KANJI_RARELY_USED, // 錟 + 0x9321, KANJI_RARELY_USED, // 錡 + 0x9324, KANJI_RARELY_USED, // 錀 + 0x9325, KANJI_RARELY_USED, // 錥 + 0x9327, KANJI_RARELY_USED, // 錧 + 0x9329, KANJI_RARELY_USED, // 錩 + 0x932A, KANJI_RARELY_USED, // 錪 + 0x9333, KANJI_RARELY_USED, // 錳 + 0x9334, KANJI_RARELY_USED, // 錮 + 0x9336, KANJI_RARELY_USED, // 錶 + 0x9337, KANJI_RARELY_USED, // 錷 + 0x9347, KANJI_RARELY_USED, // 鍇 + 0x9348, KANJI_RARELY_USED, // 鍈 + 0x9349, KANJI_RARELY_USED, // 鍉 + 0x9350, KANJI_RARELY_USED, // 鍐 + 0x9351, KANJI_RARELY_USED, // 鍑 + 0x9352, KANJI_RARELY_USED, // 鍒 + 0x9355, KANJI_RARELY_USED, // 鍕 + 0x9357, KANJI_RARELY_USED, // 鍗 + 0x9358, KANJI_RARELY_USED, // 鍘 + 0x935A, KANJI_RARELY_USED, // 鍚 + 0x935E, KANJI_RARELY_USED, // 鍞 + 0x9364, KANJI_RARELY_USED, // 鍀 + 0x9365, KANJI_RARELY_USED, // 鍥 + 0x9367, KANJI_RARELY_USED, // 鍧 + 0x9369, KANJI_RARELY_USED, // 鍩 + 0x936A, KANJI_RARELY_USED, // 鍪 + 0x936D, KANJI_RARELY_USED, // 鍭 + 0x936F, KANJI_RARELY_USED, // 鍯 + 0x9370, KANJI_RARELY_USED, // 鍰 + 0x9371, KANJI_RARELY_USED, // 鍱 + 0x9373, KANJI_RARELY_USED, // 鍳 + 0x9374, KANJI_RARELY_USED, // 鍎 + 0x9376, KANJI_RARELY_USED, // 鍶 + 0x937A, KANJI_RARELY_USED, // 鍺 + 0x937D, KANJI_RARELY_USED, // 鍜 + 0x937F, KANJI_RARELY_USED, // 鍿 + 0x9380, KANJI_RARELY_USED, // 鎀 + 0x9381, KANJI_RARELY_USED, // 鎁 + 0x9382, KANJI_RARELY_USED, // 鎂 + 0x9388, KANJI_RARELY_USED, // 鎈 + 0x938A, KANJI_RARELY_USED, // 鎊 + 0x938B, KANJI_RARELY_USED, // 鎋 + 0x938D, KANJI_RARELY_USED, // 鎍 + 0x938F, KANJI_RARELY_USED, // 鎏 + 0x9392, KANJI_RARELY_USED, // 鎒 + 0x9395, KANJI_RARELY_USED, // 鎕 + 0x9398, KANJI_RARELY_USED, // 鎘 + 0x939B, KANJI_RARELY_USED, // 鎛 + 0x939E, KANJI_RARELY_USED, // 鎞 + 0x93A1, KANJI_RARELY_USED, // 鎡 + 0x93A3, KANJI_RARELY_USED, // 鎣 + 0x93A4, KANJI_RARELY_USED, // 鎀 + 0x93A6, KANJI_RARELY_USED, // 鎊 + 0x93A8, KANJI_RARELY_USED, // 鎚 + 0x93AB, KANJI_RARELY_USED, // 鎫 + 0x93B4, KANJI_RARELY_USED, // 鎮 + 0x93B5, KANJI_RARELY_USED, // 鎵 + 0x93B6, KANJI_RARELY_USED, // 鎶 + 0x93BA, KANJI_RARELY_USED, // 鎺 + 0x93A9, KANJI_RARELY_USED, // 鎩 + 0x93C1, KANJI_RARELY_USED, // 鏁 + 0x93C4, KANJI_RARELY_USED, // 鏄 + 0x93C5, KANJI_RARELY_USED, // 鏅 + 0x93C6, KANJI_RARELY_USED, // 鏆 + 0x93C7, KANJI_RARELY_USED, // 鏇 + 0x93C9, KANJI_RARELY_USED, // 鏉 + 0x93CA, KANJI_RARELY_USED, // 鏊 + 0x93CB, KANJI_RARELY_USED, // 鏋 + 0x93CC, KANJI_RARELY_USED, // 鏌 + 0x93CD, KANJI_RARELY_USED, // 鏍 + 0x93D3, KANJI_RARELY_USED, // 鏓 + 0x93D9, KANJI_RARELY_USED, // 鏙 + 0x93DC, KANJI_RARELY_USED, // 鏜 + 0x93DE, KANJI_RARELY_USED, // 鏞 + 0x93DF, KANJI_RARELY_USED, // 鏟 + 0x93E2, KANJI_RARELY_USED, // 鏢 + 0x93E6, KANJI_RARELY_USED, // 鏊 + 0x93E7, KANJI_RARELY_USED, // 鏧 + 0x93F9, KANJI_RARELY_USED, // 鏹 + 0x93F7, KANJI_RARELY_USED, // 鏷 + 0x93F8, KANJI_RARELY_USED, // 鏞 + 0x93FA, KANJI_RARELY_USED, // 鏺 + 0x93FB, KANJI_RARELY_USED, // 鏻 + 0x93FD, KANJI_RARELY_USED, // 鏜 + 0x9401, KANJI_RARELY_USED, // 鐁 + 0x9402, KANJI_RARELY_USED, // 鐂 + 0x9404, KANJI_RARELY_USED, // 鐄 + 0x9408, KANJI_RARELY_USED, // 鐈 + 0x9409, KANJI_RARELY_USED, // 鐉 + 0x940D, KANJI_RARELY_USED, // 鐍 + 0x940E, KANJI_RARELY_USED, // 鐎 + 0x940F, KANJI_RARELY_USED, // 鐏 + 0x9415, KANJI_RARELY_USED, // 鐕 + 0x9416, KANJI_RARELY_USED, // 鐖 + 0x9417, KANJI_RARELY_USED, // 鐗 + 0x941F, KANJI_RARELY_USED, // 鐟 + 0x942E, KANJI_RARELY_USED, // 鐮 + 0x942F, KANJI_RARELY_USED, // 鐯 + 0x9431, KANJI_RARELY_USED, // 鐱 + 0x9432, KANJI_RARELY_USED, // 鐲 + 0x9433, KANJI_RARELY_USED, // 鐳 + 0x9434, KANJI_RARELY_USED, // 鐎 + 0x943B, KANJI_RARELY_USED, // 鐻 + 0x943F, KANJI_RARELY_USED, // 鐿 + 0x943D, KANJI_RARELY_USED, // 鐜 + 0x9443, KANJI_RARELY_USED, // 鑃 + 0x9445, KANJI_RARELY_USED, // 鑅 + 0x9448, KANJI_RARELY_USED, // 鑈 + 0x944A, KANJI_RARELY_USED, // 鑊 + 0x944C, KANJI_RARELY_USED, // 鑌 + 0x9455, KANJI_RARELY_USED, // 鑕 + 0x9459, KANJI_RARELY_USED, // 鑙 + 0x945C, KANJI_RARELY_USED, // 鑜 + 0x945F, KANJI_RARELY_USED, // 鑟 + 0x9461, KANJI_RARELY_USED, // 鑡 + 0x9463, KANJI_RARELY_USED, // 鑣 + 0x9468, KANJI_RARELY_USED, // 鑹 + 0x946B, KANJI_RARELY_USED, // 鑫 + 0x946D, KANJI_RARELY_USED, // 鑭 + 0x946E, KANJI_RARELY_USED, // 鑮 + 0x946F, KANJI_RARELY_USED, // 鑯 + 0x9471, KANJI_RARELY_USED, // 鑱 + 0x9472, KANJI_RARELY_USED, // 鑲 + 0x9484, KANJI_RARELY_USED, // 钄 + 0x9483, KANJI_RARELY_USED, // 钃 + 0x9578, KANJI_RARELY_USED, // 镾 + 0x9579, KANJI_RARELY_USED, // 镹 + 0x957E, KANJI_RARELY_USED, // 镟 + 0x9584, KANJI_RARELY_USED, // 閄 + 0x9588, KANJI_RARELY_USED, // 閈 + 0x958C, KANJI_RARELY_USED, // 閌 + 0x958D, KANJI_RARELY_USED, // 閍 + 0x958E, KANJI_RARELY_USED, // 閎 + 0x959D, KANJI_RARELY_USED, // 閝 + 0x959E, KANJI_RARELY_USED, // 閞 + 0x959F, KANJI_RARELY_USED, // 閟 + 0x95A1, KANJI_RARELY_USED, // 閡 + 0x95A6, KANJI_RARELY_USED, // 閩 + 0x95A9, KANJI_RARELY_USED, // 閩 + 0x95AB, KANJI_RARELY_USED, // 閫 + 0x95AC, KANJI_RARELY_USED, // 閬 + 0x95B4, KANJI_RARELY_USED, // 閮 + 0x95B6, KANJI_RARELY_USED, // 閶 + 0x95BA, KANJI_RARELY_USED, // 閺 + 0x95BD, KANJI_RARELY_USED, // é–œ + 0x95BF, KANJI_RARELY_USED, // 閿 + 0x95C6, KANJI_RARELY_USED, // 闆 + 0x95C8, KANJI_RARELY_USED, // 闈 + 0x95C9, KANJI_RARELY_USED, // 闉 + 0x95CB, KANJI_RARELY_USED, // 闋 + 0x95D0, KANJI_RARELY_USED, // 闐 + 0x95D1, KANJI_RARELY_USED, // 闑 + 0x95D2, KANJI_RARELY_USED, // 闒 + 0x95D3, KANJI_RARELY_USED, // 闓 + 0x95D9, KANJI_RARELY_USED, // 闙 + 0x95DA, KANJI_RARELY_USED, // 闚 + 0x95DD, KANJI_RARELY_USED, // 闝 + 0x95DE, KANJI_RARELY_USED, // 闞 + 0x95DF, KANJI_RARELY_USED, // 闟 + 0x95E0, KANJI_RARELY_USED, // 闠 + 0x95E4, KANJI_RARELY_USED, // é—€ + 0x95E6, KANJI_RARELY_USED, // 闩 + 0x961D, KANJI_RARELY_USED, // 阝 + 0x961E, KANJI_RARELY_USED, // 阞 + 0x9622, KANJI_RARELY_USED, // 阢 + 0x9624, KANJI_RARELY_USED, // 阀 + 0x9625, KANJI_RARELY_USED, // 阥 + 0x9626, KANJI_RARELY_USED, // 阊 + 0x962C, KANJI_RARELY_USED, // 阬 + 0x9631, KANJI_RARELY_USED, // 阱 + 0x9633, KANJI_RARELY_USED, // 阳 + 0x9637, KANJI_RARELY_USED, // 阷 + 0x9638, KANJI_RARELY_USED, // 阞 + 0x9639, KANJI_RARELY_USED, // 阹 + 0x963A, KANJI_RARELY_USED, // 阺 + 0x963C, KANJI_RARELY_USED, // 阌 + 0x963D, KANJI_RARELY_USED, // 阜 + 0x9641, KANJI_RARELY_USED, // 陁 + 0x9652, KANJI_RARELY_USED, // 陒 + 0x9654, KANJI_RARELY_USED, // 陔 + 0x9656, KANJI_RARELY_USED, // 陖 + 0x9657, KANJI_RARELY_USED, // 陗 + 0x9658, KANJI_RARELY_USED, // 陘 + 0x9661, KANJI_RARELY_USED, // 陡 + 0x966E, KANJI_RARELY_USED, // 陮 + 0x9674, KANJI_RARELY_USED, // 陮 + 0x967B, KANJI_RARELY_USED, // 陻 + 0x967C, KANJI_RARELY_USED, // 陌 + 0x967E, KANJI_RARELY_USED, // 陟 + 0x967F, KANJI_RARELY_USED, // 陿 + 0x9681, KANJI_RARELY_USED, // 隁 + 0x9682, KANJI_RARELY_USED, // 隂 + 0x9683, KANJI_RARELY_USED, // 隃 + 0x9684, KANJI_RARELY_USED, // 隄 + 0x9689, KANJI_RARELY_USED, // 隉 + 0x9691, KANJI_RARELY_USED, // 隑 + 0x9696, KANJI_RARELY_USED, // 隖 + 0x969A, KANJI_RARELY_USED, // 隚 + 0x969D, KANJI_RARELY_USED, // 隝 + 0x969F, KANJI_RARELY_USED, // 隟 + 0x96A4, KANJI_RARELY_USED, // 隀 + 0x96A5, KANJI_RARELY_USED, // 隥 + 0x96A6, KANJI_RARELY_USED, // 隩 + 0x96A9, KANJI_RARELY_USED, // 隩 + 0x96AE, KANJI_RARELY_USED, // 隮 + 0x96AF, KANJI_RARELY_USED, // 隯 + 0x96B3, KANJI_RARELY_USED, // 隳 + 0x96BA, KANJI_RARELY_USED, // 隺 + 0x96CA, KANJI_RARELY_USED, // 雊 + 0x96D2, KANJI_RARELY_USED, // 雒 + 0x5DB2, KANJI_RARELY_USED, // å¶² + 0x96D8, KANJI_RARELY_USED, // 雘 + 0x96DA, KANJI_RARELY_USED, // 雚 + 0x96DD, KANJI_RARELY_USED, // 雝 + 0x96DE, KANJI_RARELY_USED, // 雞 + 0x96DF, KANJI_RARELY_USED, // 雟 + 0x96E9, KANJI_RARELY_USED, // 雩 + 0x96EF, KANJI_RARELY_USED, // 雯 + 0x96F1, KANJI_RARELY_USED, // 雱 + 0x96FA, KANJI_RARELY_USED, // 雺 + 0x9702, KANJI_RARELY_USED, // 霂 + 0x9703, KANJI_RARELY_USED, // 霃 + 0x9705, KANJI_RARELY_USED, // 霅 + 0x9709, KANJI_RARELY_USED, // 霉 + 0x971A, KANJI_RARELY_USED, // 霚 + 0x971B, KANJI_RARELY_USED, // 霛 + 0x971D, KANJI_RARELY_USED, // 霝 + 0x9721, KANJI_RARELY_USED, // 霡 + 0x9722, KANJI_RARELY_USED, // 霢 + 0x9723, KANJI_RARELY_USED, // 霣 + 0x9728, KANJI_RARELY_USED, // 霹 + 0x9731, KANJI_RARELY_USED, // 霱 + 0x9733, KANJI_RARELY_USED, // 霳 + 0x9741, KANJI_RARELY_USED, // 靁 + 0x9743, KANJI_RARELY_USED, // 靃 + 0x974A, KANJI_RARELY_USED, // 靊 + 0x974E, KANJI_RARELY_USED, // 靎 + 0x974F, KANJI_RARELY_USED, // 靏 + 0x9755, KANJI_RARELY_USED, // 靕 + 0x9757, KANJI_RARELY_USED, // 靗 + 0x9758, KANJI_RARELY_USED, // 靘 + 0x975A, KANJI_RARELY_USED, // 靚 + 0x975B, KANJI_RARELY_USED, // 靛 + 0x9763, KANJI_RARELY_USED, // 靣 + 0x9767, KANJI_RARELY_USED, // 靧 + 0x976A, KANJI_RARELY_USED, // 靪 + 0x976E, KANJI_RARELY_USED, // 靮 + 0x9773, KANJI_RARELY_USED, // 靳 + 0x9776, KANJI_RARELY_USED, // 靶 + 0x9777, KANJI_RARELY_USED, // 靷 + 0x9778, KANJI_RARELY_USED, // 非 + 0x977B, KANJI_RARELY_USED, // 靻 + 0x977D, KANJI_RARELY_USED, // 靜 + 0x977F, KANJI_RARELY_USED, // 靿 + 0x9780, KANJI_RARELY_USED, // 鞀 + 0x9789, KANJI_RARELY_USED, // 鞉 + 0x9795, KANJI_RARELY_USED, // 鞕 + 0x9796, KANJI_RARELY_USED, // 鞖 + 0x9797, KANJI_RARELY_USED, // 鞗 + 0x9799, KANJI_RARELY_USED, // 鞙 + 0x979A, KANJI_RARELY_USED, // 鞚 + 0x979E, KANJI_RARELY_USED, // 鞞 + 0x979F, KANJI_RARELY_USED, // 鞟 + 0x97A2, KANJI_RARELY_USED, // 鞢 + 0x97AC, KANJI_RARELY_USED, // 鞬 + 0x97AE, KANJI_RARELY_USED, // 鞮 + 0x97B1, KANJI_RARELY_USED, // 鞱 + 0x97B2, KANJI_RARELY_USED, // 鞲 + 0x97B5, KANJI_RARELY_USED, // 鞵 + 0x97B6, KANJI_RARELY_USED, // 鞶 + 0x97B8, KANJI_RARELY_USED, // 鞾 + 0x97B9, KANJI_RARELY_USED, // 鞹 + 0x97BA, KANJI_RARELY_USED, // 鞺 + 0x97BC, KANJI_RARELY_USED, // 鞌 + 0x97BE, KANJI_RARELY_USED, // 鞟 + 0x97BF, KANJI_RARELY_USED, // 鞿 + 0x97C1, KANJI_RARELY_USED, // 韁 + 0x97C4, KANJI_RARELY_USED, // 韄 + 0x97C5, KANJI_RARELY_USED, // 韅 + 0x97C7, KANJI_RARELY_USED, // 韇 + 0x97C9, KANJI_RARELY_USED, // 韉 + 0x97CA, KANJI_RARELY_USED, // 韊 + 0x97CC, KANJI_RARELY_USED, // 韌 + 0x97CD, KANJI_RARELY_USED, // 韍 + 0x97CE, KANJI_RARELY_USED, // 韎 + 0x97D0, KANJI_RARELY_USED, // 韐 + 0x97D1, KANJI_RARELY_USED, // 韑 + 0x97D4, KANJI_RARELY_USED, // 韔 + 0x97D7, KANJI_RARELY_USED, // 韗 + 0x97D8, KANJI_RARELY_USED, // 韘 + 0x97D9, KANJI_RARELY_USED, // 韙 + 0x97DD, KANJI_RARELY_USED, // 韝 + 0x97DE, KANJI_RARELY_USED, // 韞 + 0x97E0, KANJI_RARELY_USED, // 韠 + 0x97DB, KANJI_RARELY_USED, // 韛 + 0x97E1, KANJI_RARELY_USED, // 韡 + 0x97E4, KANJI_RARELY_USED, // 韀 + 0x97EF, KANJI_RARELY_USED, // 韯 + 0x97F1, KANJI_RARELY_USED, // 韱 + 0x97F4, KANJI_RARELY_USED, // 韮 + 0x97F7, KANJI_RARELY_USED, // 韷 + 0x97F8, KANJI_RARELY_USED, // 韾 + 0x97FA, KANJI_RARELY_USED, // 韺 + 0x9807, KANJI_RARELY_USED, // 頇 + 0x980A, KANJI_RARELY_USED, // 頊 + 0x9819, KANJI_RARELY_USED, // 頙 + 0x980D, KANJI_RARELY_USED, // 頍 + 0x980E, KANJI_RARELY_USED, // 頎 + 0x9814, KANJI_RARELY_USED, // 頔 + 0x9816, KANJI_RARELY_USED, // 頖 + 0x981C, KANJI_RARELY_USED, // 頜 + 0x981E, KANJI_RARELY_USED, // 頞 + 0x9820, KANJI_RARELY_USED, // é   + 0x9823, KANJI_RARELY_USED, // é £ + 0x9826, KANJI_RARELY_USED, // é Š + 0x982B, KANJI_RARELY_USED, // é « + 0x982E, KANJI_RARELY_USED, // é ® + 0x982F, KANJI_RARELY_USED, // é ¯ + 0x9830, KANJI_RARELY_USED, // é ° + 0x9832, KANJI_RARELY_USED, // é ² + 0x9833, KANJI_RARELY_USED, // é ³ + 0x9835, KANJI_RARELY_USED, // é µ + 0x9825, KANJI_RARELY_USED, // é ¥ + 0x983E, KANJI_RARELY_USED, // é Ÿ + 0x9844, KANJI_RARELY_USED, // 顄 + 0x9847, KANJI_RARELY_USED, // 顇 + 0x984A, KANJI_RARELY_USED, // 顊 + 0x9851, KANJI_RARELY_USED, // 顑 + 0x9852, KANJI_RARELY_USED, // 顒 + 0x9853, KANJI_RARELY_USED, // 顓 + 0x9856, KANJI_RARELY_USED, // 顖 + 0x9857, KANJI_RARELY_USED, // 顗 + 0x9859, KANJI_RARELY_USED, // 顙 + 0x985A, KANJI_RARELY_USED, // 顚 + 0x9862, KANJI_RARELY_USED, // é¡¢ + 0x9863, KANJI_RARELY_USED, // é¡£ + 0x9865, KANJI_RARELY_USED, // é¡¥ + 0x9866, KANJI_RARELY_USED, // 顊 + 0x986A, KANJI_RARELY_USED, // 顪 + 0x986C, KANJI_RARELY_USED, // 顬 + 0x98AB, KANJI_RARELY_USED, // 颫 + 0x98AD, KANJI_RARELY_USED, // 颭 + 0x98AE, KANJI_RARELY_USED, // 颮 + 0x98B0, KANJI_RARELY_USED, // 颰 + 0x98B4, KANJI_RARELY_USED, // 颎 + 0x98B7, KANJI_RARELY_USED, // 颷 + 0x98B8, KANJI_RARELY_USED, // 颞 + 0x98BA, KANJI_RARELY_USED, // 颺 + 0x98BB, KANJI_RARELY_USED, // 颻 + 0x98BF, KANJI_RARELY_USED, // 颿 + 0x98C2, KANJI_RARELY_USED, // 飂 + 0x98C5, KANJI_RARELY_USED, // 飅 + 0x98C8, KANJI_RARELY_USED, // 飈 + 0x98CC, KANJI_RARELY_USED, // 飌 + 0x98E1, KANJI_RARELY_USED, // 飡 + 0x98E3, KANJI_RARELY_USED, // 飣 + 0x98E5, KANJI_RARELY_USED, // 飥 + 0x98E6, KANJI_RARELY_USED, // 飊 + 0x98E7, KANJI_RARELY_USED, // 飧 + 0x98EA, KANJI_RARELY_USED, // 飪 + 0x98F3, KANJI_RARELY_USED, // 飳 + 0x98F6, KANJI_RARELY_USED, // 飶 + 0x9902, KANJI_RARELY_USED, // 适 + 0x9907, KANJI_RARELY_USED, // 逇 + 0x9908, KANJI_RARELY_USED, // 逈 + 0x9911, KANJI_RARELY_USED, // 逑 + 0x9915, KANJI_RARELY_USED, // 逕 + 0x9916, KANJI_RARELY_USED, // 逖 + 0x9917, KANJI_RARELY_USED, // 逗 + 0x991A, KANJI_RARELY_USED, // 通 + 0x991B, KANJI_RARELY_USED, // 逛 + 0x991C, KANJI_RARELY_USED, // 逜 + 0x991F, KANJI_RARELY_USED, // 速 + 0x9922, KANJI_RARELY_USED, // 逢 + 0x9926, KANJI_RARELY_USED, // 逊 + 0x9927, KANJI_RARELY_USED, // 逧 + 0x992B, KANJI_RARELY_USED, // 逫 + 0x9931, KANJI_RARELY_USED, // 週 + 0x9932, KANJI_RARELY_USED, // 進 + 0x9933, KANJI_RARELY_USED, // 逳 + 0x9934, KANJI_RARELY_USED, // 逎 + 0x9935, KANJI_RARELY_USED, // 逵 + 0x9939, KANJI_RARELY_USED, // 逹 + 0x993A, KANJI_RARELY_USED, // 逺 + 0x993B, KANJI_RARELY_USED, // 逻 + 0x993C, KANJI_RARELY_USED, // 逌 + 0x9940, KANJI_RARELY_USED, // 饀 + 0x9941, KANJI_RARELY_USED, // 饁 + 0x9946, KANJI_RARELY_USED, // 饆 + 0x9947, KANJI_RARELY_USED, // 饇 + 0x9948, KANJI_RARELY_USED, // 饈 + 0x994D, KANJI_RARELY_USED, // 饍 + 0x994E, KANJI_RARELY_USED, // 饎 + 0x9954, KANJI_RARELY_USED, // 饔 + 0x9958, KANJI_RARELY_USED, // 饘 + 0x9959, KANJI_RARELY_USED, // 饙 + 0x995B, KANJI_RARELY_USED, // 饛 + 0x995C, KANJI_RARELY_USED, // 饜 + 0x995E, KANJI_RARELY_USED, // 饞 + 0x995F, KANJI_RARELY_USED, // 饟 + 0x9960, KANJI_RARELY_USED, // 饠 + 0x999B, KANJI_RARELY_USED, // 驛 + 0x999D, KANJI_RARELY_USED, // 銝 + 0x999F, KANJI_RARELY_USED, // 驟 + 0x99A6, KANJI_RARELY_USED, // 銊 + 0x99B0, KANJI_RARELY_USED, // 銰 + 0x99B1, KANJI_RARELY_USED, // 銱 + 0x99B2, KANJI_RARELY_USED, // 銲 + 0x99B5, KANJI_RARELY_USED, // 銵 + 0x99B9, KANJI_RARELY_USED, // 銹 + 0x99BA, KANJI_RARELY_USED, // 銺 + 0x99BD, KANJI_RARELY_USED, // 銜 + 0x99BF, KANJI_RARELY_USED, // 銿 + 0x99C3, KANJI_RARELY_USED, // 駃 + 0x99C9, KANJI_RARELY_USED, // 駉 + 0x99D3, KANJI_RARELY_USED, // 駓 + 0x99D4, KANJI_RARELY_USED, // 駔 + 0x99D9, KANJI_RARELY_USED, // 駙 + 0x99DA, KANJI_RARELY_USED, // 駚 + 0x99DC, KANJI_RARELY_USED, // 駜 + 0x99DE, KANJI_RARELY_USED, // 駞 + 0x99E7, KANJI_RARELY_USED, // é§§ + 0x99EA, KANJI_RARELY_USED, // 駪 + 0x99EB, KANJI_RARELY_USED, // é§« + 0x99EC, KANJI_RARELY_USED, // 駬 + 0x99F0, KANJI_RARELY_USED, // é§° + 0x99F4, KANJI_RARELY_USED, // é§Ž + 0x99F5, KANJI_RARELY_USED, // é§µ + 0x99F9, KANJI_RARELY_USED, // é§¹ + 0x99FD, KANJI_RARELY_USED, // é§œ + 0x99FE, KANJI_RARELY_USED, // é§Ÿ + 0x9A02, KANJI_RARELY_USED, // 鹂 + 0x9A03, KANJI_RARELY_USED, // 隃 + 0x9A04, KANJI_RARELY_USED, // 鹄 + 0x9A0B, KANJI_RARELY_USED, // 鹋 + 0x9A0C, KANJI_RARELY_USED, // 鹌 + 0x9A10, KANJI_RARELY_USED, // 隐 + 0x9A11, KANJI_RARELY_USED, // 鹑 + 0x9A16, KANJI_RARELY_USED, // 鹖 + 0x9A1E, KANJI_RARELY_USED, // 隞 + 0x9A20, KANJI_RARELY_USED, // éš  + 0x9A22, KANJI_RARELY_USED, // 隢 + 0x9A23, KANJI_RARELY_USED, // 隣 + 0x9A24, KANJI_RARELY_USED, // 隀 + 0x9A27, KANJI_RARELY_USED, // éš§ + 0x9A2D, KANJI_RARELY_USED, // éš­ + 0x9A2E, KANJI_RARELY_USED, // éš® + 0x9A33, KANJI_RARELY_USED, // éš³ + 0x9A35, KANJI_RARELY_USED, // éšµ + 0x9A36, KANJI_RARELY_USED, // éš¶ + 0x9A38, KANJI_RARELY_USED, // éšž + 0x9A47, KANJI_RARELY_USED, // 驇 + 0x9A41, KANJI_RARELY_USED, // 驁 + 0x9A44, KANJI_RARELY_USED, // 驄 + 0x9A4A, KANJI_RARELY_USED, // 驊 + 0x9A4B, KANJI_RARELY_USED, // 驋 + 0x9A4C, KANJI_RARELY_USED, // 驌 + 0x9A4E, KANJI_RARELY_USED, // 驎 + 0x9A51, KANJI_RARELY_USED, // 驑 + 0x9A54, KANJI_RARELY_USED, // 驔 + 0x9A56, KANJI_RARELY_USED, // 驖 + 0x9A5D, KANJI_RARELY_USED, // 驝 + 0x9AAA, KANJI_RARELY_USED, // 骪 + 0x9AAC, KANJI_RARELY_USED, // 骬 + 0x9AAE, KANJI_RARELY_USED, // 骮 + 0x9AAF, KANJI_RARELY_USED, // 骯 + 0x9AB2, KANJI_RARELY_USED, // 骲 + 0x9AB4, KANJI_RARELY_USED, // 骎 + 0x9AB5, KANJI_RARELY_USED, // 骵 + 0x9AB6, KANJI_RARELY_USED, // 骶 + 0x9AB9, KANJI_RARELY_USED, // 骹 + 0x9ABB, KANJI_RARELY_USED, // 骻 + 0x9ABE, KANJI_RARELY_USED, // 骟 + 0x9ABF, KANJI_RARELY_USED, // 骿 + 0x9AC1, KANJI_RARELY_USED, // 髁 + 0x9AC3, KANJI_RARELY_USED, // 髃 + 0x9AC6, KANJI_RARELY_USED, // 髆 + 0x9AC8, KANJI_RARELY_USED, // 髈 + 0x9ACE, KANJI_RARELY_USED, // 髎 + 0x9AD0, KANJI_RARELY_USED, // 髐 + 0x9AD2, KANJI_RARELY_USED, // 髒 + 0x9AD5, KANJI_RARELY_USED, // 髕 + 0x9AD6, KANJI_RARELY_USED, // 髖 + 0x9AD7, KANJI_RARELY_USED, // 髗 + 0x9ADB, KANJI_RARELY_USED, // 髛 + 0x9ADC, KANJI_RARELY_USED, // 髜 + 0x9AE0, KANJI_RARELY_USED, // é«  + 0x9AE4, KANJI_RARELY_USED, // é«€ + 0x9AE5, KANJI_RARELY_USED, // é«¥ + 0x9AE7, KANJI_RARELY_USED, // é«§ + 0x9AE9, KANJI_RARELY_USED, // é«© + 0x9AEC, KANJI_RARELY_USED, // 髬 + 0x9AF2, KANJI_RARELY_USED, // 髲 + 0x9AF3, KANJI_RARELY_USED, // 髳 + 0x9AF5, KANJI_RARELY_USED, // 髵 + 0x9AF9, KANJI_RARELY_USED, // 髹 + 0x9AFA, KANJI_RARELY_USED, // 髺 + 0x9AFD, KANJI_RARELY_USED, // 髜 + 0x9AFF, KANJI_RARELY_USED, // é«¿ + 0x9B00, KANJI_RARELY_USED, // 鬀 + 0x9B01, KANJI_RARELY_USED, // 鬁 + 0x9B02, KANJI_RARELY_USED, // 鬂 + 0x9B03, KANJI_RARELY_USED, // 鬃 + 0x9B04, KANJI_RARELY_USED, // 鬄 + 0x9B05, KANJI_RARELY_USED, // 鬅 + 0x9B08, KANJI_RARELY_USED, // 鬈 + 0x9B09, KANJI_RARELY_USED, // 鬉 + 0x9B0B, KANJI_RARELY_USED, // 鬋 + 0x9B0C, KANJI_RARELY_USED, // 鬌 + 0x9B0D, KANJI_RARELY_USED, // 鬍 + 0x9B0E, KANJI_RARELY_USED, // 鬎 + 0x9B10, KANJI_RARELY_USED, // 鬐 + 0x9B12, KANJI_RARELY_USED, // 鬒 + 0x9B16, KANJI_RARELY_USED, // 鬖 + 0x9B19, KANJI_RARELY_USED, // 鬙 + 0x9B1B, KANJI_RARELY_USED, // 鬛 + 0x9B1C, KANJI_RARELY_USED, // 鬜 + 0x9B20, KANJI_RARELY_USED, // 鬠 + 0x9B26, KANJI_RARELY_USED, // 鬊 + 0x9B2B, KANJI_RARELY_USED, // 鬫 + 0x9B2D, KANJI_RARELY_USED, // 鬭 + 0x9B33, KANJI_RARELY_USED, // 鬳 + 0x9B34, KANJI_RARELY_USED, // 鬎 + 0x9B35, KANJI_RARELY_USED, // 鬵 + 0x9B37, KANJI_RARELY_USED, // 鬷 + 0x9B39, KANJI_RARELY_USED, // 鬹 + 0x9B3A, KANJI_RARELY_USED, // 鬺 + 0x9B3D, KANJI_RARELY_USED, // 鬜 + 0x9B48, KANJI_RARELY_USED, // 魈 + 0x9B4B, KANJI_RARELY_USED, // 魋 + 0x9B4C, KANJI_RARELY_USED, // 魌 + 0x9B55, KANJI_RARELY_USED, // 魕 + 0x9B56, KANJI_RARELY_USED, // 魖 + 0x9B57, KANJI_RARELY_USED, // 魗 + 0x9B5B, KANJI_RARELY_USED, // 魛 + 0x9B5E, KANJI_RARELY_USED, // 魞 + 0x9B61, KANJI_RARELY_USED, // é­¡ + 0x9B63, KANJI_RARELY_USED, // é­£ + 0x9B65, KANJI_RARELY_USED, // é­¥ + 0x9B66, KANJI_RARELY_USED, // é­Š + 0x9B68, KANJI_RARELY_USED, // é­š + 0x9B6A, KANJI_RARELY_USED, // é­ª + 0x9B6B, KANJI_RARELY_USED, // é­« + 0x9B6C, KANJI_RARELY_USED, // é­¬ + 0x9B6D, KANJI_RARELY_USED, // é­­ + 0x9B6E, KANJI_RARELY_USED, // é­® + 0x9B73, KANJI_RARELY_USED, // é­³ + 0x9B75, KANJI_RARELY_USED, // é­µ + 0x9B77, KANJI_RARELY_USED, // é­· + 0x9B78, KANJI_RARELY_USED, // é­ž + 0x9B79, KANJI_RARELY_USED, // é­¹ + 0x9B7F, KANJI_RARELY_USED, // é­¿ + 0x9B80, KANJI_RARELY_USED, // 鮀 + 0x9B84, KANJI_RARELY_USED, // 鮄 + 0x9B85, KANJI_RARELY_USED, // 鮅 + 0x9B86, KANJI_RARELY_USED, // 鮆 + 0x9B87, KANJI_RARELY_USED, // 鮇 + 0x9B89, KANJI_RARELY_USED, // 鮉 + 0x9B8A, KANJI_RARELY_USED, // 鮊 + 0x9B8B, KANJI_RARELY_USED, // 鮋 + 0x9B8D, KANJI_RARELY_USED, // 鮍 + 0x9B8F, KANJI_RARELY_USED, // 鮏 + 0x9B90, KANJI_RARELY_USED, // 鮐 + 0x9B94, KANJI_RARELY_USED, // 鮔 + 0x9B9A, KANJI_RARELY_USED, // 鮚 + 0x9B9D, KANJI_RARELY_USED, // 鮝 + 0x9B9E, KANJI_RARELY_USED, // 鮞 + 0x9BA6, KANJI_RARELY_USED, // 鮊 + 0x9BA7, KANJI_RARELY_USED, // é®§ + 0x9BA9, KANJI_RARELY_USED, // 鮩 + 0x9BAC, KANJI_RARELY_USED, // 鮬 + 0x9BB0, KANJI_RARELY_USED, // é®° + 0x9BB1, KANJI_RARELY_USED, // é®± + 0x9BB2, KANJI_RARELY_USED, // 鮲 + 0x9BB7, KANJI_RARELY_USED, // é®· + 0x9BB8, KANJI_RARELY_USED, // 鮞 + 0x9BBB, KANJI_RARELY_USED, // é®» + 0x9BBC, KANJI_RARELY_USED, // 鮌 + 0x9BBE, KANJI_RARELY_USED, // 鮟 + 0x9BBF, KANJI_RARELY_USED, // 鮿 + 0x9BC1, KANJI_RARELY_USED, // 鯁 + 0x9BC7, KANJI_RARELY_USED, // 鯇 + 0x9BC8, KANJI_RARELY_USED, // 鯈 + 0x9BCE, KANJI_RARELY_USED, // 鯎 + 0x9BD0, KANJI_RARELY_USED, // 鯐 + 0x9BD7, KANJI_RARELY_USED, // 鯗 + 0x9BD8, KANJI_RARELY_USED, // 鯘 + 0x9BDD, KANJI_RARELY_USED, // 鯝 + 0x9BDF, KANJI_RARELY_USED, // 鯟 + 0x9BE5, KANJI_RARELY_USED, // 鯥 + 0x9BE7, KANJI_RARELY_USED, // 鯧 + 0x9BEA, KANJI_RARELY_USED, // 鯪 + 0x9BEB, KANJI_RARELY_USED, // 鯫 + 0x9BEF, KANJI_RARELY_USED, // 鯯 + 0x9BF3, KANJI_RARELY_USED, // 鯳 + 0x9BF7, KANJI_RARELY_USED, // 鯷 + 0x9BF8, KANJI_RARELY_USED, // 鯞 + 0x9BF9, KANJI_RARELY_USED, // 鯹 + 0x9BFA, KANJI_RARELY_USED, // 鯺 + 0x9BFD, KANJI_RARELY_USED, // 鯜 + 0x9BFF, KANJI_RARELY_USED, // 鯿 + 0x9C00, KANJI_RARELY_USED, // 鰀 + 0x9C02, KANJI_RARELY_USED, // 鰂 + 0x9C0B, KANJI_RARELY_USED, // 鰋 + 0x9C0F, KANJI_RARELY_USED, // 鰏 + 0x9C11, KANJI_RARELY_USED, // 鰑 + 0x9C16, KANJI_RARELY_USED, // 鰖 + 0x9C18, KANJI_RARELY_USED, // 鰘 + 0x9C19, KANJI_RARELY_USED, // 鰙 + 0x9C1A, KANJI_RARELY_USED, // 鰚 + 0x9C1C, KANJI_RARELY_USED, // 鰜 + 0x9C1E, KANJI_RARELY_USED, // 鰞 + 0x9C22, KANJI_RARELY_USED, // é°¢ + 0x9C23, KANJI_RARELY_USED, // é°£ + 0x9C26, KANJI_RARELY_USED, // é°Š + 0x9C27, KANJI_RARELY_USED, // é°§ + 0x9C28, KANJI_RARELY_USED, // é°š + 0x9C29, KANJI_RARELY_USED, // é°© + 0x9C2A, KANJI_RARELY_USED, // é°ª + 0x9C31, KANJI_RARELY_USED, // é°± + 0x9C35, KANJI_RARELY_USED, // é°µ + 0x9C36, KANJI_RARELY_USED, // é°¶ + 0x9C37, KANJI_RARELY_USED, // é°· + 0x9C3D, KANJI_RARELY_USED, // é°œ + 0x9C41, KANJI_RARELY_USED, // 鱁 + 0x9C43, KANJI_RARELY_USED, // 鱃 + 0x9C44, KANJI_RARELY_USED, // 鱄 + 0x9C45, KANJI_RARELY_USED, // 鱅 + 0x9C49, KANJI_RARELY_USED, // 鱉 + 0x9C4A, KANJI_RARELY_USED, // 鱊 + 0x9C4E, KANJI_RARELY_USED, // 鱎 + 0x9C4F, KANJI_RARELY_USED, // 鱏 + 0x9C50, KANJI_RARELY_USED, // 鱐 + 0x9C53, KANJI_RARELY_USED, // 鱓 + 0x9C54, KANJI_RARELY_USED, // 鱔 + 0x9C56, KANJI_RARELY_USED, // 鱖 + 0x9C58, KANJI_RARELY_USED, // 鱘 + 0x9C5B, KANJI_RARELY_USED, // 鱛 + 0x9C5D, KANJI_RARELY_USED, // 鱝 + 0x9C5E, KANJI_RARELY_USED, // 鱞 + 0x9C5F, KANJI_RARELY_USED, // 鱟 + 0x9C63, KANJI_RARELY_USED, // é±£ + 0x9C69, KANJI_RARELY_USED, // 鱩 + 0x9C6A, KANJI_RARELY_USED, // 鱪 + 0x9C5C, KANJI_RARELY_USED, // 鱜 + 0x9C6B, KANJI_RARELY_USED, // 鱫 + 0x9C68, KANJI_RARELY_USED, // 鱚 + 0x9C6E, KANJI_RARELY_USED, // é±® + 0x9C70, KANJI_RARELY_USED, // é±° + 0x9C72, KANJI_RARELY_USED, // é±² + 0x9C75, KANJI_RARELY_USED, // é±µ + 0x9C77, KANJI_RARELY_USED, // é±· + 0x9C7B, KANJI_RARELY_USED, // é±» + 0x9CE6, KANJI_RARELY_USED, // 鳊 + 0x9CF2, KANJI_RARELY_USED, // é³² + 0x9CF7, KANJI_RARELY_USED, // é³· + 0x9CF9, KANJI_RARELY_USED, // é³¹ + 0x9D0B, KANJI_RARELY_USED, // 鮋 + 0x9D02, KANJI_RARELY_USED, // 鮂 + 0x9D11, KANJI_RARELY_USED, // 鮑 + 0x9D17, KANJI_RARELY_USED, // 鮗 + 0x9D18, KANJI_RARELY_USED, // 鎘 + 0x9D1C, KANJI_RARELY_USED, // 鮜 + 0x9D1D, KANJI_RARELY_USED, // 鎝 + 0x9D1E, KANJI_RARELY_USED, // 鮞 + 0x9D2F, KANJI_RARELY_USED, // 鎯 + 0x9D30, KANJI_RARELY_USED, // 鎰 + 0x9D32, KANJI_RARELY_USED, // 鎲 + 0x9D33, KANJI_RARELY_USED, // 鎳 + 0x9D34, KANJI_RARELY_USED, // 鎎 + 0x9D3A, KANJI_RARELY_USED, // 鎺 + 0x9D3C, KANJI_RARELY_USED, // 鎌 + 0x9D45, KANJI_RARELY_USED, // 鵅 + 0x9D3D, KANJI_RARELY_USED, // 鎜 + 0x9D42, KANJI_RARELY_USED, // 鵂 + 0x9D43, KANJI_RARELY_USED, // 鵃 + 0x9D47, KANJI_RARELY_USED, // 鵇 + 0x9D4A, KANJI_RARELY_USED, // 鵊 + 0x9D53, KANJI_RARELY_USED, // 鵓 + 0x9D54, KANJI_RARELY_USED, // 鵔 + 0x9D5F, KANJI_RARELY_USED, // 鵟 + 0x9D63, KANJI_RARELY_USED, // éµ£ + 0x9D62, KANJI_RARELY_USED, // éµ¢ + 0x9D65, KANJI_RARELY_USED, // éµ¥ + 0x9D69, KANJI_RARELY_USED, // 鵩 + 0x9D6A, KANJI_RARELY_USED, // 鵪 + 0x9D6B, KANJI_RARELY_USED, // 鵫 + 0x9D70, KANJI_RARELY_USED, // éµ° + 0x9D76, KANJI_RARELY_USED, // éµ¶ + 0x9D77, KANJI_RARELY_USED, // éµ· + 0x9D7B, KANJI_RARELY_USED, // éµ» + 0x9D7C, KANJI_RARELY_USED, // 鵌 + 0x9D7E, KANJI_RARELY_USED, // 鵟 + 0x9D83, KANJI_RARELY_USED, // 鶃 + 0x9D84, KANJI_RARELY_USED, // 鶄 + 0x9D86, KANJI_RARELY_USED, // 鶆 + 0x9D8A, KANJI_RARELY_USED, // 鶊 + 0x9D8D, KANJI_RARELY_USED, // 鶍 + 0x9D8E, KANJI_RARELY_USED, // 鶎 + 0x9D92, KANJI_RARELY_USED, // 鶒 + 0x9D93, KANJI_RARELY_USED, // 鶓 + 0x9D95, KANJI_RARELY_USED, // 鶕 + 0x9D96, KANJI_RARELY_USED, // 鶖 + 0x9D97, KANJI_RARELY_USED, // 鶗 + 0x9D98, KANJI_RARELY_USED, // 鶘 + 0x9DA1, KANJI_RARELY_USED, // é¶¡ + 0x9DAA, KANJI_RARELY_USED, // 鶪 + 0x9DAC, KANJI_RARELY_USED, // 鶬 + 0x9DAE, KANJI_RARELY_USED, // é¶® + 0x9DB1, KANJI_RARELY_USED, // é¶± + 0x9DB5, KANJI_RARELY_USED, // é¶µ + 0x9DB9, KANJI_RARELY_USED, // é¶¹ + 0x9DBC, KANJI_RARELY_USED, // é¶Œ + 0x9DBF, KANJI_RARELY_USED, // é¶¿ + 0x9DC3, KANJI_RARELY_USED, // 鷃 + 0x9DC7, KANJI_RARELY_USED, // 鷇 + 0x9DC9, KANJI_RARELY_USED, // 鷉 + 0x9DCA, KANJI_RARELY_USED, // 鷊 + 0x9DD4, KANJI_RARELY_USED, // 鷔 + 0x9DD5, KANJI_RARELY_USED, // 鷕 + 0x9DD6, KANJI_RARELY_USED, // 鷖 + 0x9DD7, KANJI_RARELY_USED, // 鷗 + 0x9DDA, KANJI_RARELY_USED, // 鷚 + 0x9DDE, KANJI_RARELY_USED, // 鷞 + 0x9DDF, KANJI_RARELY_USED, // 鷟 + 0x9DE0, KANJI_RARELY_USED, // é·  + 0x9DE5, KANJI_RARELY_USED, // é·¥ + 0x9DE7, KANJI_RARELY_USED, // é·§ + 0x9DE9, KANJI_RARELY_USED, // é·© + 0x9DEB, KANJI_RARELY_USED, // é·« + 0x9DEE, KANJI_RARELY_USED, // é·® + 0x9DF0, KANJI_RARELY_USED, // é·° + 0x9DF3, KANJI_RARELY_USED, // é·³ + 0x9DF4, KANJI_RARELY_USED, // é·Ž + 0x9DFE, KANJI_RARELY_USED, // é·Ÿ + 0x9E0A, KANJI_RARELY_USED, // 龊 + 0x9E02, KANJI_RARELY_USED, // 龂 + 0x9E07, KANJI_RARELY_USED, // 龇 + 0x9E0E, KANJI_RARELY_USED, // 龎 + 0x9E10, KANJI_RARELY_USED, // 鞐 + 0x9E11, KANJI_RARELY_USED, // 龑 + 0x9E12, KANJI_RARELY_USED, // 龒 + 0x9E15, KANJI_RARELY_USED, // 龕 + 0x9E16, KANJI_RARELY_USED, // 龖 + 0x9E19, KANJI_RARELY_USED, // 龙 + 0x9E1C, KANJI_RARELY_USED, // 龜 + 0x9E1D, KANJI_RARELY_USED, // 鞝 + 0x9E7A, KANJI_RARELY_USED, // 鹺 + 0x9E7B, KANJI_RARELY_USED, // é¹» + 0x9E7C, KANJI_RARELY_USED, // 鹌 + 0x9E80, KANJI_RARELY_USED, // 麀 + 0x9E82, KANJI_RARELY_USED, // 麂 + 0x9E83, KANJI_RARELY_USED, // 麃 + 0x9E84, KANJI_RARELY_USED, // 麄 + 0x9E85, KANJI_RARELY_USED, // 麅 + 0x9E87, KANJI_RARELY_USED, // 麇 + 0x9E8E, KANJI_RARELY_USED, // 麎 + 0x9E8F, KANJI_RARELY_USED, // 麏 + 0x9E96, KANJI_RARELY_USED, // 麖 + 0x9E98, KANJI_RARELY_USED, // 麘 + 0x9E9B, KANJI_RARELY_USED, // 麛 + 0x9E9E, KANJI_RARELY_USED, // 麞 + 0x9EA4, KANJI_RARELY_USED, // 麀 + 0x9EA8, KANJI_RARELY_USED, // 麚 + 0x9EAC, KANJI_RARELY_USED, // 麬 + 0x9EAE, KANJI_RARELY_USED, // 麮 + 0x9EAF, KANJI_RARELY_USED, // 麯 + 0x9EB0, KANJI_RARELY_USED, // 麰 + 0x9EB3, KANJI_RARELY_USED, // 麳 + 0x9EB4, KANJI_RARELY_USED, // 麎 + 0x9EB5, KANJI_RARELY_USED, // 麵 + 0x9EC6, KANJI_RARELY_USED, // 黆 + 0x9EC8, KANJI_RARELY_USED, // 黈 + 0x9ECB, KANJI_RARELY_USED, // 黋 + 0x9ED5, KANJI_RARELY_USED, // 黕 + 0x9EDF, KANJI_RARELY_USED, // 黟 + 0x9EE4, KANJI_RARELY_USED, // 黀 + 0x9EE7, KANJI_RARELY_USED, // é»§ + 0x9EEC, KANJI_RARELY_USED, // 黬 + 0x9EED, KANJI_RARELY_USED, // é»­ + 0x9EEE, KANJI_RARELY_USED, // é»® + 0x9EF0, KANJI_RARELY_USED, // é»° + 0x9EF1, KANJI_RARELY_USED, // é»± + 0x9EF2, KANJI_RARELY_USED, // 黲 + 0x9EF5, KANJI_RARELY_USED, // 黵 + 0x9EF8, KANJI_RARELY_USED, // 點 + 0x9EFF, KANJI_RARELY_USED, // 黿 + 0x9F02, KANJI_RARELY_USED, // 錂 + 0x9F03, KANJI_RARELY_USED, // 錃 + 0x9F09, KANJI_RARELY_USED, // 錉 + 0x9F0F, KANJI_RARELY_USED, // 錏 + 0x9F10, KANJI_RARELY_USED, // 錐 + 0x9F11, KANJI_RARELY_USED, // 錑 + 0x9F12, KANJI_RARELY_USED, // 錒 + 0x9F14, KANJI_RARELY_USED, // 錔 + 0x9F16, KANJI_RARELY_USED, // 錖 + 0x9F17, KANJI_RARELY_USED, // 錗 + 0x9F19, KANJI_RARELY_USED, // 錙 + 0x9F1A, KANJI_RARELY_USED, // 錚 + 0x9F1B, KANJI_RARELY_USED, // 錛 + 0x9F1F, KANJI_RARELY_USED, // 錟 + 0x9F22, KANJI_RARELY_USED, // 錢 + 0x9F26, KANJI_RARELY_USED, // 錊 + 0x9F2A, KANJI_RARELY_USED, // 錪 + 0x9F2B, KANJI_RARELY_USED, // 錫 + 0x9F2F, KANJI_RARELY_USED, // 錯 + 0x9F31, KANJI_RARELY_USED, // 錱 + 0x9F32, KANJI_RARELY_USED, // 録 + 0x9F34, KANJI_RARELY_USED, // 錎 + 0x9F37, KANJI_RARELY_USED, // 錷 + 0x9F39, KANJI_RARELY_USED, // 錹 + 0x9F3A, KANJI_RARELY_USED, // 錺 + 0x9F3C, KANJI_RARELY_USED, // 錌 + 0x9F3D, KANJI_RARELY_USED, // 錜 + 0x9F3F, KANJI_RARELY_USED, // 錿 + 0x9F41, KANJI_RARELY_USED, // 霁 + 0x9F43, KANJI_RARELY_USED, // 霃 + 0x9F44, KANJI_RARELY_USED, // 霄 + 0x9F45, KANJI_RARELY_USED, // 霅 + 0x9F46, KANJI_RARELY_USED, // 霆 + 0x9F47, KANJI_RARELY_USED, // 震 + 0x9F53, KANJI_RARELY_USED, // 霓 + 0x9F55, KANJI_RARELY_USED, // 霕 + 0x9F56, KANJI_RARELY_USED, // 霖 + 0x9F57, KANJI_RARELY_USED, // 霗 + 0x9F58, KANJI_RARELY_USED, // 霘 + 0x9F5A, KANJI_RARELY_USED, // 霚 + 0x9F5D, KANJI_RARELY_USED, // 霝 + 0x9F5E, KANJI_RARELY_USED, // 霞 + 0x9F68, KANJI_RARELY_USED, // 霚 + 0x9F69, KANJI_RARELY_USED, // 霩 + 0x9F6D, KANJI_RARELY_USED, // 霭 + 0x9F6E, KANJI_RARELY_USED, // 霮 + 0x9F6F, KANJI_RARELY_USED, // 霯 + 0x9F70, KANJI_RARELY_USED, // 霰 + 0x9F71, KANJI_RARELY_USED, // 霱 + 0x9F73, KANJI_RARELY_USED, // 霳 + 0x9F75, KANJI_RARELY_USED, // 霵 + 0x9F7A, KANJI_RARELY_USED, // 霺 + 0x9F7D, KANJI_RARELY_USED, // 霜 + 0x9F8F, KANJI_RARELY_USED, // 韏 + 0x9F90, KANJI_RARELY_USED, // 韐 + 0x9F91, KANJI_RARELY_USED, // 韑 + 0x9F92, KANJI_RARELY_USED, // 韒 + 0x9F94, KANJI_RARELY_USED, // 韔 + 0x9F96, KANJI_RARELY_USED, // 韖 + 0x9F97, KANJI_RARELY_USED, // 韗 + 0x9F9E, KANJI_RARELY_USED, // 韞 + 0x9FA1, KANJI_RARELY_USED, // 韡 + 0x9FA2, KANJI_RARELY_USED, // 韢 + 0x9FA3, KANJI_RARELY_USED, // 韣 + 0x9FA5, KANJI_RARELY_USED, // 韥 + 0x4FF1, KANJI_LEVEL4, // 俱 + 0xD840, KANJI_LEVEL4, // ᅵ + 0xDC0B, KANJI_LEVEL4, // ᅵ + 0x3402, KANJI_LEVEL4, // 㐂 + 0x4E28, KANJI_LEVEL4, // äžš + 0x4E2F, KANJI_LEVEL4, // 䞯 + 0x4E30, KANJI_LEVEL4, // äž° + 0x4E8D, KANJI_LEVEL4, // 亍 + 0x4EE1, KANJI_LEVEL4, // 仡 + 0x4EFD, KANJI_LEVEL4, // 仜 + 0x4EFF, KANJI_LEVEL4, // 仿 + 0x4F03, KANJI_LEVEL4, // 䌃 + 0x4F0B, KANJI_LEVEL4, // 䌋 + 0x4F60, KANJI_LEVEL4, // 䜠 + 0x4F48, KANJI_LEVEL4, // 䜈 + 0x4F49, KANJI_LEVEL4, // 䜉 + 0x4F56, KANJI_LEVEL4, // 䜖 + 0x4F5F, KANJI_LEVEL4, // 䜟 + 0x4F6A, KANJI_LEVEL4, // 䜪 + 0x4F6C, KANJI_LEVEL4, // 䜬 + 0x4F7E, KANJI_LEVEL4, // 䜟 + 0x4F8A, KANJI_LEVEL4, // 䟊 + 0x4F94, KANJI_LEVEL4, // 䟔 + 0x4F97, KANJI_LEVEL4, // 䟗 + 0xFA30, KANJI_LEVEL4, // ïš° + 0x4FC9, KANJI_LEVEL4, // 俉 + 0x4FE0, KANJI_LEVEL4, // ä¿  + 0x5001, KANJI_LEVEL4, // 倁 + 0x5002, KANJI_LEVEL4, // 倂 + 0x500E, KANJI_LEVEL4, // 倎 + 0x5018, KANJI_LEVEL4, // 倘 + 0x5027, KANJI_LEVEL4, // 倧 + 0x502E, KANJI_LEVEL4, // 倮 + 0x5040, KANJI_LEVEL4, // 偀 + 0x503B, KANJI_LEVEL4, // 倻 + 0x5041, KANJI_LEVEL4, // 偁 + 0x5094, KANJI_LEVEL4, // 傔 + 0x50CC, KANJI_LEVEL4, // 僌 + 0x50F2, KANJI_LEVEL4, // 僲 + 0x50D0, KANJI_LEVEL4, // 僐 + 0x50E6, KANJI_LEVEL4, // 僊 + 0xFA31, KANJI_LEVEL4, // ïš± + 0x5106, KANJI_LEVEL4, // 儆 + 0x5103, KANJI_LEVEL4, // 儃 + 0x510B, KANJI_LEVEL4, // 儋 + 0x511E, KANJI_LEVEL4, // 儞 + 0x5135, KANJI_LEVEL4, // 儵 + 0x514A, KANJI_LEVEL4, // 兊 + 0xFA32, KANJI_LEVEL4, // ïš² + 0x5155, KANJI_LEVEL4, // 兕 + 0x5157, KANJI_LEVEL4, // 兗 + 0x34B5, KANJI_LEVEL4, // 㒵 + 0x519D, KANJI_LEVEL4, // 冝 + 0x51C3, KANJI_LEVEL4, // 凃 + 0x51CA, KANJI_LEVEL4, // 凊 + 0x51DE, KANJI_LEVEL4, // 凞 + 0x51E2, KANJI_LEVEL4, // 凢 + 0x51EE, KANJI_LEVEL4, // 凮 + 0x5201, KANJI_LEVEL4, // 刁 + 0x34DB, KANJI_LEVEL4, // 㓛 + 0x5213, KANJI_LEVEL4, // 刓 + 0x5215, KANJI_LEVEL4, // 刕 + 0x5249, KANJI_LEVEL4, // 剉 + 0x5257, KANJI_LEVEL4, // 剗 + 0x5261, KANJI_LEVEL4, // 剡 + 0x5293, KANJI_LEVEL4, // 劓 + 0x52C8, KANJI_LEVEL4, // 勈 + 0xFA33, KANJI_LEVEL4, // ïš³ + 0x52CC, KANJI_LEVEL4, // 勌 + 0x52D0, KANJI_LEVEL4, // 勐 + 0x52D6, KANJI_LEVEL4, // 勖 + 0x52DB, KANJI_LEVEL4, // 勛 + 0xFA34, KANJI_LEVEL4, //  + 0x52F0, KANJI_LEVEL4, // 勰 + 0x52FB, KANJI_LEVEL4, // 勻 + 0x5300, KANJI_LEVEL4, // 匀 + 0x5307, KANJI_LEVEL4, // 匇 + 0x531C, KANJI_LEVEL4, // 匜 + 0xFA35, KANJI_LEVEL4, // ïšµ + 0x5361, KANJI_LEVEL4, // 卡 + 0x5363, KANJI_LEVEL4, // 卣 + 0x537D, KANJI_LEVEL4, // 卜 + 0x5393, KANJI_LEVEL4, // 厓 + 0x539D, KANJI_LEVEL4, // 厝 + 0x53B2, KANJI_LEVEL4, // 厲 + 0x5412, KANJI_LEVEL4, // 吒 + 0x5427, KANJI_LEVEL4, // 吧 + 0x544D, KANJI_LEVEL4, // 呍 + 0x549C, KANJI_LEVEL4, // 咜 + 0x546B, KANJI_LEVEL4, // 呫 + 0x5474, KANJI_LEVEL4, // 呎 + 0x547F, KANJI_LEVEL4, // 呿 + 0x5488, KANJI_LEVEL4, // 咈 + 0x5496, KANJI_LEVEL4, // 咖 + 0x54A1, KANJI_LEVEL4, // 咡 + 0x54A9, KANJI_LEVEL4, // 咩 + 0x54C6, KANJI_LEVEL4, // 哆 + 0x54FF, KANJI_LEVEL4, // 哿 + 0x550E, KANJI_LEVEL4, // 唎 + 0x552B, KANJI_LEVEL4, // 唫 + 0x5535, KANJI_LEVEL4, // 唵 + 0x5550, KANJI_LEVEL4, // 啐 + 0x555E, KANJI_LEVEL4, // 啞 + 0x5581, KANJI_LEVEL4, // 喁 + 0x5586, KANJI_LEVEL4, // 喆 + 0x558E, KANJI_LEVEL4, // 喎 + 0xFA36, KANJI_LEVEL4, // ïš¶ + 0x55AD, KANJI_LEVEL4, // 喭 + 0x55CE, KANJI_LEVEL4, // 嗎 + 0xFA37, KANJI_LEVEL4, // ïš· + 0x5608, KANJI_LEVEL4, // 嘈 + 0x560E, KANJI_LEVEL4, // 嘎 + 0x563B, KANJI_LEVEL4, // 嘻 + 0x5649, KANJI_LEVEL4, // 噉 + 0x5676, KANJI_LEVEL4, // 噶 + 0x5666, KANJI_LEVEL4, // 噊 + 0xFA38, KANJI_LEVEL4, // ïšž + 0x566F, KANJI_LEVEL4, // 噯 + 0x5671, KANJI_LEVEL4, // 噱 + 0x5672, KANJI_LEVEL4, // 噲 + 0x5699, KANJI_LEVEL4, // 嚙 + 0x569E, KANJI_LEVEL4, // 嚞 + 0x56A9, KANJI_LEVEL4, // 嚩 + 0x56AC, KANJI_LEVEL4, // 嚬 + 0x56B3, KANJI_LEVEL4, // 嚳 + 0x56C9, KANJI_LEVEL4, // 囉 + 0x56CA, KANJI_LEVEL4, // 囊 + 0x570A, KANJI_LEVEL4, // 圊 + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDE3D, KANJI_LEVEL4, // ᅵ + 0x5721, KANJI_LEVEL4, // 圡 + 0x572F, KANJI_LEVEL4, // 圯 + 0x5733, KANJI_LEVEL4, // 圳 + 0x5734, KANJI_LEVEL4, // 圎 + 0x5770, KANJI_LEVEL4, // 坰 + 0x5777, KANJI_LEVEL4, // 坷 + 0x577C, KANJI_LEVEL4, // 坌 + 0x579C, KANJI_LEVEL4, // 垜 + 0xFA0F, KANJI_LEVEL4, //  + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDF1B, KANJI_LEVEL4, // ᅵ + 0x57B8, KANJI_LEVEL4, // åžž + 0x57C7, KANJI_LEVEL4, // 埇 + 0x57C8, KANJI_LEVEL4, // 埈 + 0x57CF, KANJI_LEVEL4, // 埏 + 0x57E4, KANJI_LEVEL4, // 埀 + 0x57ED, KANJI_LEVEL4, // 埭 + 0x57F5, KANJI_LEVEL4, // 埵 + 0x57F6, KANJI_LEVEL4, // 埶 + 0x57FF, KANJI_LEVEL4, // 埿 + 0x5809, KANJI_LEVEL4, // 堉 + 0xFA10, KANJI_LEVEL4, //  + 0x5861, KANJI_LEVEL4, // å¡¡ + 0x5864, KANJI_LEVEL4, // å¡€ + 0xFA39, KANJI_LEVEL4, // ïš¹ + 0x587C, KANJI_LEVEL4, // 塌 + 0x5889, KANJI_LEVEL4, // 墉 + 0x589E, KANJI_LEVEL4, // 增 + 0xFA3A, KANJI_LEVEL4, //  + 0x58A9, KANJI_LEVEL4, // 墩 + 0xD845, KANJI_LEVEL4, // ᅵ + 0xDC6E, KANJI_LEVEL4, // ᅵ + 0x58D2, KANJI_LEVEL4, // 壒 + 0x58CE, KANJI_LEVEL4, // 壎 + 0x58D4, KANJI_LEVEL4, // 壔 + 0x58DA, KANJI_LEVEL4, // 壚 + 0x58E0, KANJI_LEVEL4, // 壠 + 0x58E9, KANJI_LEVEL4, // 壩 + 0x590C, KANJI_LEVEL4, // 倌 + 0x8641, KANJI_LEVEL4, // 虁 + 0x595D, KANJI_LEVEL4, // 奝 + 0x596D, KANJI_LEVEL4, // 奭 + 0x598B, KANJI_LEVEL4, // 劋 + 0x5992, KANJI_LEVEL4, // 劒 + 0x59A4, KANJI_LEVEL4, // 劀 + 0x59C3, KANJI_LEVEL4, // 姃 + 0x59D2, KANJI_LEVEL4, // 姒 + 0x59DD, KANJI_LEVEL4, // 姝 + 0x5A13, KANJI_LEVEL4, // åš“ + 0x5A23, KANJI_LEVEL4, // 嚣 + 0x5A67, KANJI_LEVEL4, // å©§ + 0x5A6D, KANJI_LEVEL4, // å©­ + 0x5A77, KANJI_LEVEL4, // å©· + 0x5A7E, KANJI_LEVEL4, // 婟 + 0x5A84, KANJI_LEVEL4, // 媄 + 0x5A9E, KANJI_LEVEL4, // 媞 + 0x5AA7, KANJI_LEVEL4, // 媧 + 0x5AC4, KANJI_LEVEL4, // 嫄 + 0xD846, KANJI_LEVEL4, // ᅵ + 0xDCBD, KANJI_LEVEL4, // ᅵ + 0x5B19, KANJI_LEVEL4, // 嬙 + 0x5B25, KANJI_LEVEL4, // 嬥 + 0x525D, KANJI_LEVEL4, // 剝 + 0x4E9C, KANJI_LEVEL4, // 亜 + 0x5516, KANJI_LEVEL4, // 唖 + 0x5A03, KANJI_LEVEL4, // 嚃 + 0x963F, KANJI_LEVEL4, // 阿 + 0x54C0, KANJI_LEVEL4, // 哀 + 0x611B, KANJI_LEVEL4, // 愛 + 0x6328, KANJI_LEVEL4, // 挚 + 0x59F6, KANJI_LEVEL4, // å§¶ + 0x9022, KANJI_LEVEL4, // 逢 + 0x8475, KANJI_LEVEL4, // 葵 + 0x831C, KANJI_LEVEL4, // 茜 + 0x7A50, KANJI_LEVEL4, // 穐 + 0x60AA, KANJI_LEVEL4, // 悪 + 0x63E1, KANJI_LEVEL4, // 握 + 0x6E25, KANJI_LEVEL4, // 枥 + 0x65ED, KANJI_LEVEL4, // 旭 + 0x8466, KANJI_LEVEL4, // 葊 + 0x82A6, KANJI_LEVEL4, // 芊 + 0x9BF5, KANJI_LEVEL4, // 鯵 + 0x6893, KANJI_LEVEL4, // 梓 + 0x5727, KANJI_LEVEL4, // 圧 + 0x65A1, KANJI_LEVEL4, // 斡 + 0x6271, KANJI_LEVEL4, // 扱 + 0x5B9B, KANJI_LEVEL4, // 宛 + 0x59D0, KANJI_LEVEL4, // 姐 + 0x867B, KANJI_LEVEL4, // 虻 + 0x98F4, KANJI_LEVEL4, // 风 + 0x7D62, KANJI_LEVEL4, // çµ¢ + 0x7DBE, KANJI_LEVEL4, // ç¶Ÿ + 0x9B8E, KANJI_LEVEL4, // 鮎 + 0x6216, KANJI_LEVEL4, // 或 + 0x7C9F, KANJI_LEVEL4, // 粟 + 0x88B7, KANJI_LEVEL4, // 袷 + 0x5B89, KANJI_LEVEL4, // 安 + 0x5EB5, KANJI_LEVEL4, // 庵 + 0x6309, KANJI_LEVEL4, // 按 + 0x6697, KANJI_LEVEL4, // 暗 + 0x6848, KANJI_LEVEL4, // 案 + 0x95C7, KANJI_LEVEL4, // 闇 + 0x978D, KANJI_LEVEL4, // 鞍 + 0x674F, KANJI_LEVEL4, // 杏 + 0x4EE5, KANJI_LEVEL4, // 以 + 0x4F0A, KANJI_LEVEL4, // 䌊 + 0x4F4D, KANJI_LEVEL4, // 䜍 + 0x4F9D, KANJI_LEVEL4, // 䟝 + 0x5049, KANJI_LEVEL4, // 偉 + 0x56F2, KANJI_LEVEL4, // 囲 + 0x5937, KANJI_LEVEL4, // 倷 + 0x59D4, KANJI_LEVEL4, // 委 + 0x5A01, KANJI_LEVEL4, // 嚁 + 0x5C09, KANJI_LEVEL4, // 尉 + 0x60DF, KANJI_LEVEL4, // 惟 + 0x610F, KANJI_LEVEL4, // 意 + 0x6170, KANJI_LEVEL4, // 慰 + 0x6613, KANJI_LEVEL4, // 易 + 0x6905, KANJI_LEVEL4, // 怅 + 0x70BA, KANJI_LEVEL4, // 為 + 0x754F, KANJI_LEVEL4, // 畏 + 0x7570, KANJI_LEVEL4, // 異 + 0x79FB, KANJI_LEVEL4, // ç§» + 0x7DAD, KANJI_LEVEL4, // ç¶­ + 0x7DEF, KANJI_LEVEL4, // ç·¯ + 0x80C3, KANJI_LEVEL4, // 胃 + 0x840E, KANJI_LEVEL4, // 萎 + 0x8863, KANJI_LEVEL4, // è¡£ + 0x8B02, KANJI_LEVEL4, // 謂 + 0x9055, KANJI_LEVEL4, // 違 + 0x907A, KANJI_LEVEL4, // 遺 + 0x533B, KANJI_LEVEL4, // 医 + 0x4E95, KANJI_LEVEL4, // 井 + 0x4EA5, KANJI_LEVEL4, // 亥 + 0x57DF, KANJI_LEVEL4, // 域 + 0x80B2, KANJI_LEVEL4, // 育 + 0x90C1, KANJI_LEVEL4, // 郁 + 0x78EF, KANJI_LEVEL4, // 磯 + 0x4E00, KANJI_LEVEL4, // 侀 + 0x58F1, KANJI_LEVEL4, // 壱 + 0x6EA2, KANJI_LEVEL4, // 溢 + 0x9038, KANJI_LEVEL4, // 逾 + 0x7A32, KANJI_LEVEL4, // çš² + 0x8328, KANJI_LEVEL4, // 茚 + 0x828B, KANJI_LEVEL4, // 芋 + 0x9C2F, KANJI_LEVEL4, // é°¯ + 0x5141, KANJI_LEVEL4, // 允 + 0x5370, KANJI_LEVEL4, // 印 + 0x54BD, KANJI_LEVEL4, // å’œ + 0x54E1, KANJI_LEVEL4, // 員 + 0x56E0, KANJI_LEVEL4, // 因 + 0x59FB, KANJI_LEVEL4, // å§» + 0x5F15, KANJI_LEVEL4, // 匕 + 0x98F2, KANJI_LEVEL4, // 飲 + 0x6DEB, KANJI_LEVEL4, // æ·« + 0x80E4, KANJI_LEVEL4, // 胀 + 0x852D, KANJI_LEVEL4, // 蔭 + 0x9662, KANJI_LEVEL4, // 院 + 0x9670, KANJI_LEVEL4, // 陰 + 0x96A0, KANJI_LEVEL4, // 隠 + 0x97FB, KANJI_LEVEL4, // 韻 + 0x540B, KANJI_LEVEL4, // 吋 + 0x53F3, KANJI_LEVEL4, // 右 + 0x5B87, KANJI_LEVEL4, // 宇 + 0x70CF, KANJI_LEVEL4, // 烏 + 0x7FBD, KANJI_LEVEL4, // 矜 + 0x8FC2, KANJI_LEVEL4, // 迂 + 0x96E8, KANJI_LEVEL4, // 雹 + 0x536F, KANJI_LEVEL4, // 卯 + 0x9D5C, KANJI_LEVEL4, // 鵜 + 0x7ABA, KANJI_LEVEL4, // 窺 + 0x4E11, KANJI_LEVEL4, // 侑 + 0x7893, KANJI_LEVEL4, // 碓 + 0x81FC, KANJI_LEVEL4, // 臌 + 0x6E26, KANJI_LEVEL4, // 枊 + 0x5618, KANJI_LEVEL4, // 嘘 + 0x5504, KANJI_LEVEL4, // 唄 + 0x6B1D, KANJI_LEVEL4, // 欝 + 0x851A, KANJI_LEVEL4, // 蔚 + 0x9C3B, KANJI_LEVEL4, // é°» + 0x59E5, KANJI_LEVEL4, // å§¥ + 0x53A9, KANJI_LEVEL4, // 厩 + 0x6D66, KANJI_LEVEL4, // 浊 + 0x74DC, KANJI_LEVEL4, // 瓜 + 0x958F, KANJI_LEVEL4, // 閏 + 0x5642, KANJI_LEVEL4, // 噂 + 0x4E91, KANJI_LEVEL4, // 云 + 0x904B, KANJI_LEVEL4, // 運 + 0x96F2, KANJI_LEVEL4, // 雲 + 0x834F, KANJI_LEVEL4, // 荏 + 0x990C, KANJI_LEVEL4, // 逌 + 0x53E1, KANJI_LEVEL4, // 叡 + 0x55B6, KANJI_LEVEL4, // 営 + 0x5B30, KANJI_LEVEL4, // 嬰 + 0x5F71, KANJI_LEVEL4, // 圱 + 0x6620, KANJI_LEVEL4, // 映 + 0x66F3, KANJI_LEVEL4, // 曳 + 0x6804, KANJI_LEVEL4, // 栄 + 0x6C38, KANJI_LEVEL4, // æ°ž + 0x6CF3, KANJI_LEVEL4, // æ³³ + 0x6D29, KANJI_LEVEL4, // 掩 + 0x745B, KANJI_LEVEL4, // 瑛 + 0x76C8, KANJI_LEVEL4, // 盈 + 0x7A4E, KANJI_LEVEL4, // 穎 + 0x9834, KANJI_LEVEL4, // é Ž + 0x82F1, KANJI_LEVEL4, // 英 + 0x885B, KANJI_LEVEL4, // 衛 + 0x8A60, KANJI_LEVEL4, // è©  + 0x92ED, KANJI_LEVEL4, // 鋭 + 0x6DB2, KANJI_LEVEL4, // æ¶² + 0x75AB, KANJI_LEVEL4, // 疫 + 0x76CA, KANJI_LEVEL4, // 益 + 0x99C5, KANJI_LEVEL4, // 駅 + 0x60A6, KANJI_LEVEL4, // 悊 + 0x8B01, KANJI_LEVEL4, // 謁 + 0x8D8A, KANJI_LEVEL4, // 越 + 0x95B2, KANJI_LEVEL4, // 閲 + 0x698E, KANJI_LEVEL4, // 抎 + 0x53AD, KANJI_LEVEL4, // 厭 + 0x5186, KANJI_LEVEL4, // 円 + 0x5712, KANJI_LEVEL4, // 園 + 0x5830, KANJI_LEVEL4, // å ° + 0x5944, KANJI_LEVEL4, // 奄 + 0x5BB4, KANJI_LEVEL4, // 宎 + 0x5EF6, KANJI_LEVEL4, // å»¶ + 0x6028, KANJI_LEVEL4, // 怚 + 0x63A9, KANJI_LEVEL4, // 掩 + 0x63F4, KANJI_LEVEL4, // 揎 + 0x6CBF, KANJI_LEVEL4, // 沿 + 0x6F14, KANJI_LEVEL4, // 挔 + 0x708E, KANJI_LEVEL4, // 炎 + 0x7114, KANJI_LEVEL4, // 焔 + 0x7159, KANJI_LEVEL4, // 煙 + 0x71D5, KANJI_LEVEL4, // 燕 + 0x733F, KANJI_LEVEL4, // 猿 + 0x7E01, KANJI_LEVEL4, // 瞁 + 0x8276, KANJI_LEVEL4, // 艶 + 0x82D1, KANJI_LEVEL4, // 苑 + 0x8597, KANJI_LEVEL4, // 薗 + 0x9060, KANJI_LEVEL4, // 遠 + 0x925B, KANJI_LEVEL4, // 鉛 + 0x9D1B, KANJI_LEVEL4, // 鮛 + 0x5869, KANJI_LEVEL4, // å¡© + 0x65BC, KANJI_LEVEL4, // æ–Œ + 0x6C5A, KANJI_LEVEL4, // 汚 + 0x7525, KANJI_LEVEL4, // 甥 + 0x51F9, KANJI_LEVEL4, // 凹 + 0x592E, KANJI_LEVEL4, // 倮 + 0x5965, KANJI_LEVEL4, // 奥 + 0x5F80, KANJI_LEVEL4, // 埀 + 0x5FDC, KANJI_LEVEL4, // 応 + 0x62BC, KANJI_LEVEL4, // 抌 + 0x65FA, KANJI_LEVEL4, // 旺 + 0x6A2A, KANJI_LEVEL4, // 暪 + 0x6B27, KANJI_LEVEL4, // 欧 + 0x6BB4, KANJI_LEVEL4, // 殎 + 0x738B, KANJI_LEVEL4, // 王 + 0x7FC1, KANJI_LEVEL4, // 翁 + 0x8956, KANJI_LEVEL4, // 襖 + 0x9D2C, KANJI_LEVEL4, // 鎬 + 0x9D0E, KANJI_LEVEL4, // 鮎 + 0x9EC4, KANJI_LEVEL4, // 黄 + 0x5CA1, KANJI_LEVEL4, // 岡 + 0x6C96, KANJI_LEVEL4, // 沖 + 0x837B, KANJI_LEVEL4, // 荻 + 0x5104, KANJI_LEVEL4, // 億 + 0x5C4B, KANJI_LEVEL4, // 屋 + 0x61B6, KANJI_LEVEL4, // 憶 + 0x81C6, KANJI_LEVEL4, // 臆 + 0x6876, KANJI_LEVEL4, // æ¡¶ + 0x7261, KANJI_LEVEL4, // 牡 + 0x4E59, KANJI_LEVEL4, // 乙 + 0x4FFA, KANJI_LEVEL4, // 俺 + 0x5378, KANJI_LEVEL4, // 卞 + 0x6069, KANJI_LEVEL4, // 恩 + 0x6E29, KANJI_LEVEL4, // æž© + 0x7A4F, KANJI_LEVEL4, // 穏 + 0x97F3, KANJI_LEVEL4, // 音 + 0x4E0B, KANJI_LEVEL4, // 例 + 0x5316, KANJI_LEVEL4, // 化 + 0x4EEE, KANJI_LEVEL4, // ä»® + 0x4F55, KANJI_LEVEL4, // 䜕 + 0x4F3D, KANJI_LEVEL4, // 䌜 + 0x4FA1, KANJI_LEVEL4, // 䟡 + 0x4F73, KANJI_LEVEL4, // 䜳 + 0x52A0, KANJI_LEVEL4, // 加 + 0x53EF, KANJI_LEVEL4, // 可 + 0x5609, KANJI_LEVEL4, // 嘉 + 0x590F, KANJI_LEVEL4, // 倏 + 0x5AC1, KANJI_LEVEL4, // 嫁 + 0x5BB6, KANJI_LEVEL4, // å®¶ + 0x5BE1, KANJI_LEVEL4, // 寡 + 0x79D1, KANJI_LEVEL4, // 科 + 0x6687, KANJI_LEVEL4, // 暇 + 0x679C, KANJI_LEVEL4, // 果 + 0x67B6, KANJI_LEVEL4, // 架 + 0x6B4C, KANJI_LEVEL4, // 歌 + 0x6CB3, KANJI_LEVEL4, // æ²³ + 0x706B, KANJI_LEVEL4, // 火 + 0x73C2, KANJI_LEVEL4, // 珂 + 0x798D, KANJI_LEVEL4, // 犍 + 0x79BE, KANJI_LEVEL4, // 犟 + 0x7A3C, KANJI_LEVEL4, // 皌 + 0x7B87, KANJI_LEVEL4, // 箇 + 0x82B1, KANJI_LEVEL4, // 花 + 0x82DB, KANJI_LEVEL4, // 苛 + 0x8304, KANJI_LEVEL4, // 茄 + 0x8377, KANJI_LEVEL4, // 荷 + 0x83EF, KANJI_LEVEL4, // 華 + 0x83D3, KANJI_LEVEL4, // 菓 + 0x8766, KANJI_LEVEL4, // 蝊 + 0x8AB2, KANJI_LEVEL4, // 課 + 0x5629, KANJI_LEVEL4, // 嘩 + 0x8CA8, KANJI_LEVEL4, // 貚 + 0x8FE6, KANJI_LEVEL4, // 迊 + 0x904E, KANJI_LEVEL4, // 過 + 0x971E, KANJI_LEVEL4, // 霞 + 0x868A, KANJI_LEVEL4, // 蚊 + 0x4FC4, KANJI_LEVEL4, // 俄 + 0x5CE8, KANJI_LEVEL4, // 峚 + 0x6211, KANJI_LEVEL4, // 我 + 0x7259, KANJI_LEVEL4, // 牙 + 0x753B, KANJI_LEVEL4, // 画 + 0x81E5, KANJI_LEVEL4, // 臥 + 0x82BD, KANJI_LEVEL4, // 芜 + 0x86FE, KANJI_LEVEL4, // 蛟 + 0x8CC0, KANJI_LEVEL4, // 賀 + 0x96C5, KANJI_LEVEL4, // 雅 + 0x9913, KANJI_LEVEL4, // 逓 + 0x99D5, KANJI_LEVEL4, // 駕 + 0x4ECB, KANJI_LEVEL4, // 介 + 0x4F1A, KANJI_LEVEL4, // 䌚 + 0x89E3, KANJI_LEVEL4, // è§£ + 0x56DE, KANJI_LEVEL4, // 回 + 0x584A, KANJI_LEVEL4, // 塊 + 0x58CA, KANJI_LEVEL4, // 壊 + 0x5EFB, KANJI_LEVEL4, // å»» + 0x5FEB, KANJI_LEVEL4, // å¿« + 0x602A, KANJI_LEVEL4, // 怪 + 0x6094, KANJI_LEVEL4, // 悔 + 0x6062, KANJI_LEVEL4, // 恢 + 0x61D0, KANJI_LEVEL4, // 懐 + 0x6212, KANJI_LEVEL4, // 戒 + 0x62D0, KANJI_LEVEL4, // 拐 + 0x6539, KANJI_LEVEL4, // 改 + 0x9B41, KANJI_LEVEL4, // 魁 + 0x6666, KANJI_LEVEL4, // 晊 + 0x68B0, KANJI_LEVEL4, // 械 + 0x6D77, KANJI_LEVEL4, // æµ· + 0x7070, KANJI_LEVEL4, // 灰 + 0x754C, KANJI_LEVEL4, // 界 + 0x7686, KANJI_LEVEL4, // 皆 + 0x7D75, KANJI_LEVEL4, // çµµ + 0x82A5, KANJI_LEVEL4, // 芥 + 0x87F9, KANJI_LEVEL4, // 蟹 + 0x958B, KANJI_LEVEL4, // 開 + 0x968E, KANJI_LEVEL4, // 階 + 0x8C9D, KANJI_LEVEL4, // 貝 + 0x51F1, KANJI_LEVEL4, // 凱 + 0x52BE, KANJI_LEVEL4, // 功 + 0x5916, KANJI_LEVEL4, // 倖 + 0x54B3, KANJI_LEVEL4, // 咳 + 0x5BB3, KANJI_LEVEL4, // 害 + 0x5D16, KANJI_LEVEL4, // 厖 + 0x6168, KANJI_LEVEL4, // æ…š + 0x6982, KANJI_LEVEL4, // 抂 + 0x6DAF, KANJI_LEVEL4, // 涯 + 0x788D, KANJI_LEVEL4, // 碍 + 0x84CB, KANJI_LEVEL4, // 蓋 + 0x8857, KANJI_LEVEL4, // 街 + 0x8A72, KANJI_LEVEL4, // 該 + 0x93A7, KANJI_LEVEL4, // 鎧 + 0x9AB8, KANJI_LEVEL4, // 骞 + 0x6D6C, KANJI_LEVEL4, // 浬 + 0x99A8, KANJI_LEVEL4, // 銚 + 0x86D9, KANJI_LEVEL4, // 蛙 + 0x57A3, KANJI_LEVEL4, // 垣 + 0x67FF, KANJI_LEVEL4, // 柿 + 0x86CE, KANJI_LEVEL4, // 蛎 + 0x920E, KANJI_LEVEL4, // 鈎 + 0x5283, KANJI_LEVEL4, // 劃 + 0x5687, KANJI_LEVEL4, // 嚇 + 0x5404, KANJI_LEVEL4, // 各 + 0x5ED3, KANJI_LEVEL4, // 廓 + 0x62E1, KANJI_LEVEL4, // 拡 + 0x64B9, KANJI_LEVEL4, // 撹 + 0x683C, KANJI_LEVEL4, // æ Œ + 0x6838, KANJI_LEVEL4, // æ ž + 0x6BBB, KANJI_LEVEL4, // æ®» + 0x7372, KANJI_LEVEL4, // 獲 + 0x78BA, KANJI_LEVEL4, // 確 + 0x7A6B, KANJI_LEVEL4, // ç©« + 0x899A, KANJI_LEVEL4, // 芚 + 0x89D2, KANJI_LEVEL4, // 角 + 0x8D6B, KANJI_LEVEL4, // 赫 + 0x8F03, KANJI_LEVEL4, // 范 + 0x90ED, KANJI_LEVEL4, // 郭 + 0x95A3, KANJI_LEVEL4, // 閣 + 0x9694, KANJI_LEVEL4, // 隔 + 0x9769, KANJI_LEVEL4, // 革 + 0x5B66, KANJI_LEVEL4, // å­Š + 0x5CB3, KANJI_LEVEL4, // å²³ + 0x697D, KANJI_LEVEL4, // 楜 + 0x984D, KANJI_LEVEL4, // 額 + 0x984E, KANJI_LEVEL4, // 顎 + 0x639B, KANJI_LEVEL4, // 掛 + 0x7B20, KANJI_LEVEL4, // 笠 + 0x6A2B, KANJI_LEVEL4, // æš« + 0x6A7F, KANJI_LEVEL4, // æ©¿ + 0x68B6, KANJI_LEVEL4, // 梶 + 0x9C0D, KANJI_LEVEL4, // 鰍 + 0x6F5F, KANJI_LEVEL4, // 期 + 0x5272, KANJI_LEVEL4, // 割 + 0x559D, KANJI_LEVEL4, // 喝 + 0x6070, KANJI_LEVEL4, // 恰 + 0x62EC, KANJI_LEVEL4, // 括 + 0x6D3B, KANJI_LEVEL4, // 掻 + 0x6E07, KANJI_LEVEL4, // 枇 + 0x6ED1, KANJI_LEVEL4, // 滑 + 0x845B, KANJI_LEVEL4, // 葛 + 0x8910, KANJI_LEVEL4, // 耐 + 0x8F44, KANJI_LEVEL4, // 蜄 + 0x4E14, KANJI_LEVEL4, // 侔 + 0x9C39, KANJI_LEVEL4, // é°¹ + 0x53F6, KANJI_LEVEL4, // 叶 + 0x691B, KANJI_LEVEL4, // 怛 + 0x6A3A, KANJI_LEVEL4, // 暺 + 0x9784, KANJI_LEVEL4, // 鞄 + 0x682A, KANJI_LEVEL4, // æ ª + 0x515C, KANJI_LEVEL4, // 兜 + 0x7AC3, KANJI_LEVEL4, // 竃 + 0x84B2, KANJI_LEVEL4, // 蒲 + 0x91DC, KANJI_LEVEL4, // 釜 + 0x938C, KANJI_LEVEL4, // 鎌 + 0x565B, KANJI_LEVEL4, // 噛 + 0x9D28, KANJI_LEVEL4, // 鎚 + 0x6822, KANJI_LEVEL4, // æ ¢ + 0x8305, KANJI_LEVEL4, // 茅 + 0x8431, KANJI_LEVEL4, // 萱 + 0x7CA5, KANJI_LEVEL4, // ç²¥ + 0x5208, KANJI_LEVEL4, // 刈 + 0x82C5, KANJI_LEVEL4, // 苅 + 0x74E6, KANJI_LEVEL4, // 瓩 + 0x4E7E, KANJI_LEVEL4, // 也 + 0x4F83, KANJI_LEVEL4, // 䟃 + 0x51A0, KANJI_LEVEL4, // 冠 + 0x5BD2, KANJI_LEVEL4, // 寒 + 0x520A, KANJI_LEVEL4, // 刊 + 0x52D8, KANJI_LEVEL4, // 勘 + 0x52E7, KANJI_LEVEL4, // 勧 + 0x5DFB, KANJI_LEVEL4, // å·» + 0x559A, KANJI_LEVEL4, // 喚 + 0x582A, KANJI_LEVEL4, // å ª + 0x59E6, KANJI_LEVEL4, // å§Š + 0x5B8C, KANJI_LEVEL4, // 完 + 0x5B98, KANJI_LEVEL4, // 官 + 0x5BDB, KANJI_LEVEL4, // 寛 + 0x5E72, KANJI_LEVEL4, // å¹² + 0x5E79, KANJI_LEVEL4, // å¹¹ + 0x60A3, KANJI_LEVEL4, // 患 + 0x611F, KANJI_LEVEL4, // 感 + 0x6163, KANJI_LEVEL4, // 慣 + 0x61BE, KANJI_LEVEL4, // 憟 + 0x63DB, KANJI_LEVEL4, // 換 + 0x6562, KANJI_LEVEL4, // 敢 + 0x67D1, KANJI_LEVEL4, // 柑 + 0x6853, KANJI_LEVEL4, // 桓 + 0x68FA, KANJI_LEVEL4, // 棺 + 0x6B3E, KANJI_LEVEL4, // 欟 + 0x6B53, KANJI_LEVEL4, // 歓 + 0x6C57, KANJI_LEVEL4, // 汗 + 0x6F22, KANJI_LEVEL4, // 挢 + 0x6F97, KANJI_LEVEL4, // 柗 + 0x6F45, KANJI_LEVEL4, // 朅 + 0x74B0, KANJI_LEVEL4, // 環 + 0x7518, KANJI_LEVEL4, // 甘 + 0x76E3, KANJI_LEVEL4, // 監 + 0x770B, KANJI_LEVEL4, // 看 + 0x7AFF, KANJI_LEVEL4, // ç«¿ + 0x7BA1, KANJI_LEVEL4, // 管 + 0x7C21, KANJI_LEVEL4, // ç°¡ + 0x7DE9, KANJI_LEVEL4, // ç·© + 0x7F36, KANJI_LEVEL4, // 猶 + 0x7FF0, KANJI_LEVEL4, // ç¿° + 0x809D, KANJI_LEVEL4, // 肝 + 0x8266, KANJI_LEVEL4, // 艊 + 0x839E, KANJI_LEVEL4, // 莞 + 0x89B3, KANJI_LEVEL4, // 芳 + 0x8ACC, KANJI_LEVEL4, // 諌 + 0x8CAB, KANJI_LEVEL4, // 貫 + 0x9084, KANJI_LEVEL4, // 還 + 0x9451, KANJI_LEVEL4, // 鑑 + 0x9593, KANJI_LEVEL4, // 間 + 0x9591, KANJI_LEVEL4, // 閑 + 0x95A2, KANJI_LEVEL4, // 関 + 0x9665, KANJI_LEVEL4, // 陥 + 0x97D3, KANJI_LEVEL4, // 韓 + 0x9928, KANJI_LEVEL4, // 通 + 0x8218, KANJI_LEVEL4, // 舘 + 0x4E38, KANJI_LEVEL4, // äžž + 0x542B, KANJI_LEVEL4, // 含 + 0x5CB8, KANJI_LEVEL4, // 岞 + 0x5DCC, KANJI_LEVEL4, // 巌 + 0x73A9, KANJI_LEVEL4, // 玩 + 0x764C, KANJI_LEVEL4, // 癌 + 0x773C, KANJI_LEVEL4, // 県 + 0x5CA9, KANJI_LEVEL4, // 岩 + 0x7FEB, KANJI_LEVEL4, // ç¿« + 0x8D0B, KANJI_LEVEL4, // 莋 + 0x96C1, KANJI_LEVEL4, // 雁 + 0x9811, KANJI_LEVEL4, // 頑 + 0x9854, KANJI_LEVEL4, // 顔 + 0x9858, KANJI_LEVEL4, // 願 + 0x4F01, KANJI_LEVEL4, // 䌁 + 0x4F0E, KANJI_LEVEL4, // 䌎 + 0x5371, KANJI_LEVEL4, // 危 + 0x559C, KANJI_LEVEL4, // 喜 + 0x5668, KANJI_LEVEL4, // 噚 + 0x57FA, KANJI_LEVEL4, // 基 + 0x5947, KANJI_LEVEL4, // 奇 + 0x5B09, KANJI_LEVEL4, // 嬉 + 0x5BC4, KANJI_LEVEL4, // 寄 + 0x5C90, KANJI_LEVEL4, // 岐 + 0x5E0C, KANJI_LEVEL4, // 垌 + 0x5E7E, KANJI_LEVEL4, // 幟 + 0x5FCC, KANJI_LEVEL4, // 忌 + 0x63EE, KANJI_LEVEL4, // 揮 + 0x673A, KANJI_LEVEL4, // 机 + 0x65D7, KANJI_LEVEL4, // 旗 + 0x65E2, KANJI_LEVEL4, // 既 + 0x671F, KANJI_LEVEL4, // 期 + 0x68CB, KANJI_LEVEL4, // 棋 + 0x68C4, KANJI_LEVEL4, // 棄 + 0x6A5F, KANJI_LEVEL4, // 機 + 0x5E30, KANJI_LEVEL4, // åž° + 0x6BC5, KANJI_LEVEL4, // 毅 + 0x6C17, KANJI_LEVEL4, // 気 + 0x6C7D, KANJI_LEVEL4, // 汜 + 0x757F, KANJI_LEVEL4, // 畿 + 0x7948, KANJI_LEVEL4, // 祈 + 0x5B63, KANJI_LEVEL4, // å­£ + 0x7A00, KANJI_LEVEL4, // 繀 + 0x7D00, KANJI_LEVEL4, // 简 + 0x5FBD, KANJI_LEVEL4, // 埜 + 0x898F, KANJI_LEVEL4, // 芏 + 0x8A18, KANJI_LEVEL4, // 蚘 + 0x8CB4, KANJI_LEVEL4, // 貎 + 0x8D77, KANJI_LEVEL4, // èµ· + 0x8ECC, KANJI_LEVEL4, // 軌 + 0x8F1D, KANJI_LEVEL4, // 茝 + 0x98E2, KANJI_LEVEL4, // 飢 + 0x9A0E, KANJI_LEVEL4, // 階 + 0x9B3C, KANJI_LEVEL4, // 鬌 + 0x4E80, KANJI_LEVEL4, // 亀 + 0x507D, KANJI_LEVEL4, // 停 + 0x5100, KANJI_LEVEL4, // 儀 + 0x5993, KANJI_LEVEL4, // 劓 + 0x5B9C, KANJI_LEVEL4, // 宜 + 0x622F, KANJI_LEVEL4, // 戯 + 0x6280, KANJI_LEVEL4, // 技 + 0x64EC, KANJI_LEVEL4, // 擬 + 0x6B3A, KANJI_LEVEL4, // 欺 + 0x72A0, KANJI_LEVEL4, // 犠 + 0x7591, KANJI_LEVEL4, // 疑 + 0x7947, KANJI_LEVEL4, // 祇 + 0x7FA9, KANJI_LEVEL4, // 矩 + 0x87FB, KANJI_LEVEL4, // 蟻 + 0x8ABC, KANJI_LEVEL4, // 誌 + 0x8B70, KANJI_LEVEL4, // è­° + 0x63AC, KANJI_LEVEL4, // 掬 + 0x83CA, KANJI_LEVEL4, // 菊 + 0x97A0, KANJI_LEVEL4, // 鞠 + 0x5409, KANJI_LEVEL4, // 吉 + 0x5403, KANJI_LEVEL4, // 吃 + 0x55AB, KANJI_LEVEL4, // 喫 + 0x6854, KANJI_LEVEL4, // 桔 + 0x6A58, KANJI_LEVEL4, // 橘 + 0x8A70, KANJI_LEVEL4, // è©° + 0x7827, KANJI_LEVEL4, // ç § + 0x6775, KANJI_LEVEL4, // 杵 + 0x9ECD, KANJI_LEVEL4, // 黍 + 0x5374, KANJI_LEVEL4, // 华 + 0x5BA2, KANJI_LEVEL4, // 客 + 0x811A, KANJI_LEVEL4, // 脚 + 0x8650, KANJI_LEVEL4, // 虐 + 0x9006, KANJI_LEVEL4, // 逆 + 0x4E18, KANJI_LEVEL4, // 䞘 + 0x4E45, KANJI_LEVEL4, // 久 + 0x4EC7, KANJI_LEVEL4, // 仇 + 0x4F11, KANJI_LEVEL4, // 䌑 + 0x53CA, KANJI_LEVEL4, // 及 + 0x5438, KANJI_LEVEL4, // 吞 + 0x5BAE, KANJI_LEVEL4, // å®® + 0x5F13, KANJI_LEVEL4, // 匓 + 0x6025, KANJI_LEVEL4, // 急 + 0x6551, KANJI_LEVEL4, // 救 + 0x673D, KANJI_LEVEL4, // 朜 + 0x6C42, KANJI_LEVEL4, // 求 + 0x6C72, KANJI_LEVEL4, // æ±² + 0x6CE3, KANJI_LEVEL4, // æ³£ + 0x7078, KANJI_LEVEL4, // 灞 + 0x7403, KANJI_LEVEL4, // 球 + 0x7A76, KANJI_LEVEL4, // ç©¶ + 0x7AAE, KANJI_LEVEL4, // 窮 + 0x7B08, KANJI_LEVEL4, // 笈 + 0x7D1A, KANJI_LEVEL4, // 箚 + 0x7CFE, KANJI_LEVEL4, // 糟 + 0x7D66, KANJI_LEVEL4, // 絊 + 0x65E7, KANJI_LEVEL4, // 旧 + 0x725B, KANJI_LEVEL4, // 牛 + 0x53BB, KANJI_LEVEL4, // 去 + 0x5C45, KANJI_LEVEL4, // 居 + 0x5DE8, KANJI_LEVEL4, // å·š + 0x62D2, KANJI_LEVEL4, // 拒 + 0x62E0, KANJI_LEVEL4, // 拠 + 0x6319, KANJI_LEVEL4, // 挙 + 0x6E20, KANJI_LEVEL4, // æž  + 0x865A, KANJI_LEVEL4, // 虚 + 0x8A31, KANJI_LEVEL4, // èš± + 0x8DDD, KANJI_LEVEL4, // 距 + 0x92F8, KANJI_LEVEL4, // 鋾 + 0x6F01, KANJI_LEVEL4, // 持 + 0x79A6, KANJI_LEVEL4, // 犊 + 0x9B5A, KANJI_LEVEL4, // 魚 + 0x4EA8, KANJI_LEVEL4, // 亚 + 0x4EAB, KANJI_LEVEL4, // 享 + 0x4EAC, KANJI_LEVEL4, // 京 + 0x4F9B, KANJI_LEVEL4, // 䟛 + 0x4FA0, KANJI_LEVEL4, // 䟠 + 0x50D1, KANJI_LEVEL4, // 僑 + 0x5147, KANJI_LEVEL4, // 兇 + 0x7AF6, KANJI_LEVEL4, // ç«¶ + 0x5171, KANJI_LEVEL4, // 共 + 0x51F6, KANJI_LEVEL4, // 凶 + 0x5354, KANJI_LEVEL4, // 協 + 0x5321, KANJI_LEVEL4, // 匡 + 0x537F, KANJI_LEVEL4, // 卿 + 0x53EB, KANJI_LEVEL4, // 叫 + 0x55AC, KANJI_LEVEL4, // 喬 + 0x5883, KANJI_LEVEL4, // 境 + 0x5CE1, KANJI_LEVEL4, // 峡 + 0x5F37, KANJI_LEVEL4, // 匷 + 0x5F4A, KANJI_LEVEL4, // 圊 + 0x602F, KANJI_LEVEL4, // 怯 + 0x6050, KANJI_LEVEL4, // 恐 + 0x606D, KANJI_LEVEL4, // 恭 + 0x631F, KANJI_LEVEL4, // 挟 + 0x6559, KANJI_LEVEL4, // 教 + 0x6A4B, KANJI_LEVEL4, // 橋 + 0x6CC1, KANJI_LEVEL4, // 況 + 0x72C2, KANJI_LEVEL4, // 狂 + 0x72ED, KANJI_LEVEL4, // 狭 + 0x77EF, KANJI_LEVEL4, // 矯 + 0x80F8, KANJI_LEVEL4, // 胞 + 0x8105, KANJI_LEVEL4, // 脅 + 0x8208, KANJI_LEVEL4, // 興 + 0x854E, KANJI_LEVEL4, // 蕎 + 0x90F7, KANJI_LEVEL4, // 郷 + 0x93E1, KANJI_LEVEL4, // 鏡 + 0x97FF, KANJI_LEVEL4, // 響 + 0x9957, KANJI_LEVEL4, // 饗 + 0x9A5A, KANJI_LEVEL4, // 驚 + 0x4EF0, KANJI_LEVEL4, // ä»° + 0x51DD, KANJI_LEVEL4, // 凝 + 0x5C2D, KANJI_LEVEL4, // å°­ + 0x6681, KANJI_LEVEL4, // 暁 + 0x696D, KANJI_LEVEL4, // 業 + 0x5C40, KANJI_LEVEL4, // 局 + 0x66F2, KANJI_LEVEL4, // 曲 + 0x6975, KANJI_LEVEL4, // 極 + 0x7389, KANJI_LEVEL4, // 玉 + 0x6850, KANJI_LEVEL4, // 桐 + 0x7C81, KANJI_LEVEL4, // 粁 + 0x50C5, KANJI_LEVEL4, // 僅 + 0x52E4, KANJI_LEVEL4, // å‹€ + 0x5747, KANJI_LEVEL4, // 均 + 0x5DFE, KANJI_LEVEL4, // å·Ÿ + 0x9326, KANJI_LEVEL4, // 錩 + 0x65A4, KANJI_LEVEL4, // æ–€ + 0x6B23, KANJI_LEVEL4, // 欣 + 0x6B3D, KANJI_LEVEL4, // 欜 + 0x7434, KANJI_LEVEL4, // 琎 + 0x7981, KANJI_LEVEL4, // 犁 + 0x79BD, KANJI_LEVEL4, // 犜 + 0x7B4B, KANJI_LEVEL4, // 筋 + 0x7DCA, KANJI_LEVEL4, // 緊 + 0x82B9, KANJI_LEVEL4, // 芹 + 0x83CC, KANJI_LEVEL4, // 菌 + 0x887F, KANJI_LEVEL4, // è¡¿ + 0x895F, KANJI_LEVEL4, // 襟 + 0x8B39, KANJI_LEVEL4, // 謹 + 0x8FD1, KANJI_LEVEL4, // 近 + 0x91D1, KANJI_LEVEL4, // 金 + 0x541F, KANJI_LEVEL4, // 吟 + 0x9280, KANJI_LEVEL4, // 銀 + 0x4E5D, KANJI_LEVEL4, // 九 + 0x5036, KANJI_LEVEL4, // 倶 + 0x53E5, KANJI_LEVEL4, // 句 + 0x533A, KANJI_LEVEL4, // 区 + 0x72D7, KANJI_LEVEL4, // 狗 + 0x7396, KANJI_LEVEL4, // 玖 + 0x77E9, KANJI_LEVEL4, // 矩 + 0x82E6, KANJI_LEVEL4, // 苊 + 0x8EAF, KANJI_LEVEL4, // 躯 + 0x99C6, KANJI_LEVEL4, // 駆 + 0x99C8, KANJI_LEVEL4, // 駈 + 0x99D2, KANJI_LEVEL4, // 駒 + 0x5177, KANJI_LEVEL4, // 具 + 0x611A, KANJI_LEVEL4, // 愚 + 0x865E, KANJI_LEVEL4, // 虞 + 0x55B0, KANJI_LEVEL4, // 喰 + 0x7A7A, KANJI_LEVEL4, // 空 + 0x5076, KANJI_LEVEL4, // 偶 + 0x5BD3, KANJI_LEVEL4, // 寓 + 0x9047, KANJI_LEVEL4, // 遇 + 0x9685, KANJI_LEVEL4, // 隅 + 0x4E32, KANJI_LEVEL4, // äž² + 0x6ADB, KANJI_LEVEL4, // 櫛 + 0x91E7, KANJI_LEVEL4, // 釧 + 0x5C51, KANJI_LEVEL4, // 屑 + 0x5C48, KANJI_LEVEL4, // 屈 + 0x6398, KANJI_LEVEL4, // 掘 + 0x7A9F, KANJI_LEVEL4, // 窟 + 0x6C93, KANJI_LEVEL4, // 沓 + 0x9774, KANJI_LEVEL4, // 靎 + 0x8F61, KANJI_LEVEL4, // 蜡 + 0x7AAA, KANJI_LEVEL4, // 窪 + 0x718A, KANJI_LEVEL4, // 熊 + 0x9688, KANJI_LEVEL4, // 隈 + 0x7C82, KANJI_LEVEL4, // 粂 + 0x6817, KANJI_LEVEL4, // 栗 + 0x7E70, KANJI_LEVEL4, // ç¹° + 0x6851, KANJI_LEVEL4, // 桑 + 0x936C, KANJI_LEVEL4, // 鍬 + 0x52F2, KANJI_LEVEL4, // 勲 + 0x541B, KANJI_LEVEL4, // 君 + 0x85AB, KANJI_LEVEL4, // 薫 + 0x8A13, KANJI_LEVEL4, // èš“ + 0x7FA4, KANJI_LEVEL4, // 矀 + 0x8ECD, KANJI_LEVEL4, // 軍 + 0x90E1, KANJI_LEVEL4, // 郡 + 0x5366, KANJI_LEVEL4, // 半 + 0x8888, KANJI_LEVEL4, // 袈 + 0x7941, KANJI_LEVEL4, // 祁 + 0x4FC2, KANJI_LEVEL4, // 係 + 0x50BE, KANJI_LEVEL4, // 傟 + 0x5211, KANJI_LEVEL4, // 刑 + 0x5144, KANJI_LEVEL4, // 兄 + 0x5553, KANJI_LEVEL4, // 啓 + 0x572D, KANJI_LEVEL4, // 圭 + 0x73EA, KANJI_LEVEL4, // 珪 + 0x578B, KANJI_LEVEL4, // 型 + 0x5951, KANJI_LEVEL4, // 契 + 0x5F62, KANJI_LEVEL4, // 圢 + 0x5F84, KANJI_LEVEL4, // 埄 + 0x6075, KANJI_LEVEL4, // 恵 + 0x6176, KANJI_LEVEL4, // 慶 + 0x6167, KANJI_LEVEL4, // 慧 + 0x61A9, KANJI_LEVEL4, // 憩 + 0x63B2, KANJI_LEVEL4, // 掲 + 0x643A, KANJI_LEVEL4, // 携 + 0x656C, KANJI_LEVEL4, // 敬 + 0x666F, KANJI_LEVEL4, // 景 + 0x6842, KANJI_LEVEL4, // 桂 + 0x6E13, KANJI_LEVEL4, // æž“ + 0x7566, KANJI_LEVEL4, // 畩 + 0x7A3D, KANJI_LEVEL4, // çšœ + 0x7CFB, KANJI_LEVEL4, // ç³» + 0x7D4C, KANJI_LEVEL4, // 経 + 0x7D99, KANJI_LEVEL4, // 継 + 0x7E4B, KANJI_LEVEL4, // 繋 + 0x7F6B, KANJI_LEVEL4, // 眫 + 0x830E, KANJI_LEVEL4, // 茎 + 0x834A, KANJI_LEVEL4, // 荊 + 0x86CD, KANJI_LEVEL4, // 蛍 + 0x8A08, KANJI_LEVEL4, // 蚈 + 0x8A63, KANJI_LEVEL4, // è©£ + 0x8B66, KANJI_LEVEL4, // è­Š + 0x8EFD, KANJI_LEVEL4, // 軜 + 0x981A, KANJI_LEVEL4, // 頚 + 0x9D8F, KANJI_LEVEL4, // 鶏 + 0x82B8, KANJI_LEVEL4, // 芞 + 0x8FCE, KANJI_LEVEL4, // 迎 + 0x9BE8, KANJI_LEVEL4, // 鯚 + 0x5287, KANJI_LEVEL4, // 劇 + 0x621F, KANJI_LEVEL4, // 戟 + 0x6483, KANJI_LEVEL4, // 撃 + 0x6FC0, KANJI_LEVEL4, // 激 + 0x9699, KANJI_LEVEL4, // 隙 + 0x6841, KANJI_LEVEL4, // 桁 + 0x5091, KANJI_LEVEL4, // 傑 + 0x6B20, KANJI_LEVEL4, // 欠 + 0x6C7A, KANJI_LEVEL4, // 決 + 0x6F54, KANJI_LEVEL4, // 朔 + 0x7A74, KANJI_LEVEL4, // 穎 + 0x7D50, KANJI_LEVEL4, // 結 + 0x8840, KANJI_LEVEL4, // 血 + 0x8A23, KANJI_LEVEL4, // 蚣 + 0x6708, KANJI_LEVEL4, // 月 + 0x4EF6, KANJI_LEVEL4, // ä»¶ + 0x5039, KANJI_LEVEL4, // 倹 + 0x5026, KANJI_LEVEL4, // 倊 + 0x5065, KANJI_LEVEL4, // 健 + 0x517C, KANJI_LEVEL4, // å…Œ + 0x5238, KANJI_LEVEL4, // 刞 + 0x5263, KANJI_LEVEL4, // 剣 + 0x55A7, KANJI_LEVEL4, // 喧 + 0x570F, KANJI_LEVEL4, // 圏 + 0x5805, KANJI_LEVEL4, // 堅 + 0x5ACC, KANJI_LEVEL4, // 嫌 + 0x5EFA, KANJI_LEVEL4, // 建 + 0x61B2, KANJI_LEVEL4, // 憲 + 0x61F8, KANJI_LEVEL4, // 懞 + 0x62F3, KANJI_LEVEL4, // 拳 + 0x6372, KANJI_LEVEL4, // 捲 + 0x691C, KANJI_LEVEL4, // 怜 + 0x6A29, KANJI_LEVEL4, // æš© + 0x727D, KANJI_LEVEL4, // 牜 + 0x72AC, KANJI_LEVEL4, // 犬 + 0x732E, KANJI_LEVEL4, // 献 + 0x7814, KANJI_LEVEL4, // 研 + 0x786F, KANJI_LEVEL4, // 硯 + 0x7D79, KANJI_LEVEL4, // çµ¹ + 0x770C, KANJI_LEVEL4, // 県 + 0x80A9, KANJI_LEVEL4, // 肩 + 0x898B, KANJI_LEVEL4, // 芋 + 0x8B19, KANJI_LEVEL4, // 謙 + 0x8CE2, KANJI_LEVEL4, // è³¢ + 0x8ED2, KANJI_LEVEL4, // 軒 + 0x9063, KANJI_LEVEL4, // 遣 + 0x9375, KANJI_LEVEL4, // 鍵 + 0x967A, KANJI_LEVEL4, // 険 + 0x9855, KANJI_LEVEL4, // 顕 + 0x9A13, KANJI_LEVEL4, // 鹓 + 0x9E78, KANJI_LEVEL4, // 鹞 + 0x5143, KANJI_LEVEL4, // 元 + 0x539F, KANJI_LEVEL4, // 原 + 0x53B3, KANJI_LEVEL4, // 厳 + 0x5E7B, KANJI_LEVEL4, // å¹» + 0x5F26, KANJI_LEVEL4, // 匊 + 0x6E1B, KANJI_LEVEL4, // æž› + 0x6E90, KANJI_LEVEL4, // 源 + 0x7384, KANJI_LEVEL4, // 玄 + 0x73FE, KANJI_LEVEL4, // 珟 + 0x7D43, KANJI_LEVEL4, // 絃 + 0x8237, KANJI_LEVEL4, // 舷 + 0x8A00, KANJI_LEVEL4, // 蚀 + 0x8AFA, KANJI_LEVEL4, // 諺 + 0x9650, KANJI_LEVEL4, // 限 + 0x4E4E, KANJI_LEVEL4, // 乎 + 0x500B, KANJI_LEVEL4, // 個 + 0x53E4, KANJI_LEVEL4, // 叀 + 0x547C, KANJI_LEVEL4, // 呌 + 0x56FA, KANJI_LEVEL4, // 固 + 0x59D1, KANJI_LEVEL4, // 姑 + 0x5B64, KANJI_LEVEL4, // å­€ + 0x5DF1, KANJI_LEVEL4, // å·± + 0x5EAB, KANJI_LEVEL4, // 庫 + 0x5F27, KANJI_LEVEL4, // 匧 + 0x6238, KANJI_LEVEL4, // 戞 + 0x6545, KANJI_LEVEL4, // 故 + 0x67AF, KANJI_LEVEL4, // 枯 + 0x6E56, KANJI_LEVEL4, // 湖 + 0x72D0, KANJI_LEVEL4, // 狐 + 0x7CCA, KANJI_LEVEL4, // 糊 + 0x88B4, KANJI_LEVEL4, // 袎 + 0x80A1, KANJI_LEVEL4, // 股 + 0x80E1, KANJI_LEVEL4, // 胡 + 0x83F0, KANJI_LEVEL4, // 菰 + 0x864E, KANJI_LEVEL4, // 虎 + 0x8A87, KANJI_LEVEL4, // 誇 + 0x8DE8, KANJI_LEVEL4, // è·š + 0x9237, KANJI_LEVEL4, // 鈷 + 0x96C7, KANJI_LEVEL4, // 雇 + 0x9867, KANJI_LEVEL4, // é¡§ + 0x9F13, KANJI_LEVEL4, // 錓 + 0x4E94, KANJI_LEVEL4, // 五 + 0x4E92, KANJI_LEVEL4, // 互 + 0x4F0D, KANJI_LEVEL4, // 䌍 + 0x5348, KANJI_LEVEL4, // 午 + 0x5449, KANJI_LEVEL4, // 呉 + 0x543E, KANJI_LEVEL4, // 吟 + 0x5A2F, KANJI_LEVEL4, // 嚯 + 0x5F8C, KANJI_LEVEL4, // 埌 + 0x5FA1, KANJI_LEVEL4, // 埡 + 0x609F, KANJI_LEVEL4, // 悟 + 0x68A7, KANJI_LEVEL4, // 梧 + 0x6A8E, KANJI_LEVEL4, // 檎 + 0x745A, KANJI_LEVEL4, // 瑚 + 0x7881, KANJI_LEVEL4, // 碁 + 0x8A9E, KANJI_LEVEL4, // 語 + 0x8AA4, KANJI_LEVEL4, // 誀 + 0x8B77, KANJI_LEVEL4, // è­· + 0x9190, KANJI_LEVEL4, // 醐 + 0x4E5E, KANJI_LEVEL4, // 乞 + 0x9BC9, KANJI_LEVEL4, // 鯉 + 0x4EA4, KANJI_LEVEL4, // 亀 + 0x4F7C, KANJI_LEVEL4, // 䜌 + 0x4FAF, KANJI_LEVEL4, // 䟯 + 0x5019, KANJI_LEVEL4, // 候 + 0x5016, KANJI_LEVEL4, // 倖 + 0x5149, KANJI_LEVEL4, // 光 + 0x516C, KANJI_LEVEL4, // 公 + 0x529F, KANJI_LEVEL4, // 功 + 0x52B9, KANJI_LEVEL4, // 効 + 0x52FE, KANJI_LEVEL4, // 募 + 0x539A, KANJI_LEVEL4, // 厚 + 0x53E3, KANJI_LEVEL4, // 口 + 0x5411, KANJI_LEVEL4, // 向 + 0x540E, KANJI_LEVEL4, // 后 + 0x5589, KANJI_LEVEL4, // 喉 + 0x5751, KANJI_LEVEL4, // 坑 + 0x57A2, KANJI_LEVEL4, // 垢 + 0x597D, KANJI_LEVEL4, // 奜 + 0x5B54, KANJI_LEVEL4, // 孔 + 0x5B5D, KANJI_LEVEL4, // 孝 + 0x5B8F, KANJI_LEVEL4, // 宏 + 0x5DE5, KANJI_LEVEL4, // å·¥ + 0x5DE7, KANJI_LEVEL4, // å·§ + 0x5DF7, KANJI_LEVEL4, // å·· + 0x5E78, KANJI_LEVEL4, // 幞 + 0x5E83, KANJI_LEVEL4, // 広 + 0x5E9A, KANJI_LEVEL4, // 庚 + 0x5EB7, KANJI_LEVEL4, // 康 + 0x5F18, KANJI_LEVEL4, // 匘 + 0x6052, KANJI_LEVEL4, // 恒 + 0x614C, KANJI_LEVEL4, // 慌 + 0x6297, KANJI_LEVEL4, // 抗 + 0x62D8, KANJI_LEVEL4, // 拘 + 0x63A7, KANJI_LEVEL4, // 控 + 0x653B, KANJI_LEVEL4, // 攻 + 0x6602, KANJI_LEVEL4, // 昂 + 0x6643, KANJI_LEVEL4, // 晃 + 0x66F4, KANJI_LEVEL4, // 曎 + 0x676D, KANJI_LEVEL4, // 杭 + 0x6821, KANJI_LEVEL4, // æ ¡ + 0x6897, KANJI_LEVEL4, // 梗 + 0x69CB, KANJI_LEVEL4, // 構 + 0x6C5F, KANJI_LEVEL4, // 江 + 0x6D2A, KANJI_LEVEL4, // 措 + 0x6D69, KANJI_LEVEL4, // 浩 + 0x6E2F, KANJI_LEVEL4, // 枯 + 0x6E9D, KANJI_LEVEL4, // 溝 + 0x7532, KANJI_LEVEL4, // 甲 + 0x7687, KANJI_LEVEL4, // 皇 + 0x786C, KANJI_LEVEL4, // 硬 + 0x7A3F, KANJI_LEVEL4, // çš¿ + 0x7CE0, KANJI_LEVEL4, // ç³  + 0x7D05, KANJI_LEVEL4, // 箅 + 0x7D18, KANJI_LEVEL4, // 玘 + 0x7D5E, KANJI_LEVEL4, // 絞 + 0x7DB1, KANJI_LEVEL4, // ç¶± + 0x8015, KANJI_LEVEL4, // 耕 + 0x8003, KANJI_LEVEL4, // 考 + 0x80AF, KANJI_LEVEL4, // 肯 + 0x80B1, KANJI_LEVEL4, // 肱 + 0x8154, KANJI_LEVEL4, // 腔 + 0x818F, KANJI_LEVEL4, // 膏 + 0x822A, KANJI_LEVEL4, // 航 + 0x8352, KANJI_LEVEL4, // 荒 + 0x884C, KANJI_LEVEL4, // 行 + 0x8861, KANJI_LEVEL4, // è¡¡ + 0x8B1B, KANJI_LEVEL4, // 講 + 0x8CA2, KANJI_LEVEL4, // è²¢ + 0x8CFC, KANJI_LEVEL4, // 賌 + 0x90CA, KANJI_LEVEL4, // 郊 + 0x9175, KANJI_LEVEL4, // 酵 + 0x9271, KANJI_LEVEL4, // 鉱 + 0x783F, KANJI_LEVEL4, // ç ¿ + 0x92FC, KANJI_LEVEL4, // 鋌 + 0x95A4, KANJI_LEVEL4, // é–€ + 0x964D, KANJI_LEVEL4, // 降 + 0x9805, KANJI_LEVEL4, // 項 + 0x9999, KANJI_LEVEL4, // 驙 + 0x9AD8, KANJI_LEVEL4, // 高 + 0x9D3B, KANJI_LEVEL4, // 鎻 + 0x525B, KANJI_LEVEL4, // 剛 + 0x52AB, KANJI_LEVEL4, // 劫 + 0x53F7, KANJI_LEVEL4, // 号 + 0x5408, KANJI_LEVEL4, // 合 + 0x58D5, KANJI_LEVEL4, // 壕 + 0x62F7, KANJI_LEVEL4, // 拷 + 0x6FE0, KANJI_LEVEL4, // æ¿  + 0x8C6A, KANJI_LEVEL4, // 豪 + 0x8F5F, KANJI_LEVEL4, // 蜟 + 0x9EB9, KANJI_LEVEL4, // 麹 + 0x514B, KANJI_LEVEL4, // 克 + 0x523B, KANJI_LEVEL4, // 刻 + 0x544A, KANJI_LEVEL4, // 告 + 0x56FD, KANJI_LEVEL4, // 囜 + 0x7A40, KANJI_LEVEL4, // 穀 + 0x9177, KANJI_LEVEL4, // 酷 + 0x9D60, KANJI_LEVEL4, // éµ  + 0x9ED2, KANJI_LEVEL4, // 黒 + 0x7344, KANJI_LEVEL4, // 獄 + 0x6F09, KANJI_LEVEL4, // 按 + 0x8170, KANJI_LEVEL4, // 腰 + 0x7511, KANJI_LEVEL4, // 甑 + 0x5FFD, KANJI_LEVEL4, // 応 + 0x60DA, KANJI_LEVEL4, // 惚 + 0x9AA8, KANJI_LEVEL4, // 骚 + 0x72DB, KANJI_LEVEL4, // 狛 + 0x8FBC, KANJI_LEVEL4, // 蟌 + 0x6B64, KANJI_LEVEL4, // æ­€ + 0x9803, KANJI_LEVEL4, // 頃 + 0x4ECA, KANJI_LEVEL4, // 今 + 0x56F0, KANJI_LEVEL4, // 困 + 0x5764, KANJI_LEVEL4, // 址 + 0x58BE, KANJI_LEVEL4, // 墟 + 0x5A5A, KANJI_LEVEL4, // 婚 + 0x6068, KANJI_LEVEL4, // 恚 + 0x61C7, KANJI_LEVEL4, // 懇 + 0x660F, KANJI_LEVEL4, // 昏 + 0x6606, KANJI_LEVEL4, // 昆 + 0x6839, KANJI_LEVEL4, // æ ¹ + 0x68B1, KANJI_LEVEL4, // 梱 + 0x6DF7, KANJI_LEVEL4, // æ·· + 0x75D5, KANJI_LEVEL4, // 痕 + 0x7D3A, KANJI_LEVEL4, // 玺 + 0x826E, KANJI_LEVEL4, // 艮 + 0x9B42, KANJI_LEVEL4, // 魂 + 0x4E9B, KANJI_LEVEL4, // 些 + 0x4F50, KANJI_LEVEL4, // 䜐 + 0x53C9, KANJI_LEVEL4, // 叉 + 0x5506, KANJI_LEVEL4, // 唆 + 0x5D6F, KANJI_LEVEL4, // 嵯 + 0x5DE6, KANJI_LEVEL4, // å·Š + 0x5DEE, KANJI_LEVEL4, // å·® + 0x67FB, KANJI_LEVEL4, // 査 + 0x6C99, KANJI_LEVEL4, // 沙 + 0x7473, KANJI_LEVEL4, // 瑳 + 0x7802, KANJI_LEVEL4, // 砂 + 0x8A50, KANJI_LEVEL4, // 詐 + 0x9396, KANJI_LEVEL4, // 鎖 + 0x88DF, KANJI_LEVEL4, // 裟 + 0x5750, KANJI_LEVEL4, // 坐 + 0x5EA7, KANJI_LEVEL4, // 座 + 0x632B, KANJI_LEVEL4, // 挫 + 0x50B5, KANJI_LEVEL4, // 債 + 0x50AC, KANJI_LEVEL4, // 催 + 0x518D, KANJI_LEVEL4, // 再 + 0x6700, KANJI_LEVEL4, // 最 + 0x54C9, KANJI_LEVEL4, // 哉 + 0x585E, KANJI_LEVEL4, // 塞 + 0x59BB, KANJI_LEVEL4, // 劻 + 0x5BB0, KANJI_LEVEL4, // å®° + 0x5F69, KANJI_LEVEL4, // 圩 + 0x624D, KANJI_LEVEL4, // 才 + 0x63A1, KANJI_LEVEL4, // 採 + 0x683D, KANJI_LEVEL4, // æ œ + 0x6B73, KANJI_LEVEL4, // æ­³ + 0x6E08, KANJI_LEVEL4, // 枈 + 0x707D, KANJI_LEVEL4, // 灜 + 0x91C7, KANJI_LEVEL4, // 采 + 0x7280, KANJI_LEVEL4, // 犀 + 0x7815, KANJI_LEVEL4, // 砕 + 0x7826, KANJI_LEVEL4, // ç Š + 0x796D, KANJI_LEVEL4, // 祭 + 0x658E, KANJI_LEVEL4, // 斎 + 0x7D30, KANJI_LEVEL4, // 现 + 0x83DC, KANJI_LEVEL4, // 菜 + 0x88C1, KANJI_LEVEL4, // 裁 + 0x8F09, KANJI_LEVEL4, // 茉 + 0x969B, KANJI_LEVEL4, // 際 + 0x5264, KANJI_LEVEL4, // 剀 + 0x5728, KANJI_LEVEL4, // 圚 + 0x6750, KANJI_LEVEL4, // 材 + 0x7F6A, KANJI_LEVEL4, // 眪 + 0x8CA1, KANJI_LEVEL4, // 財 + 0x51B4, KANJI_LEVEL4, // 冎 + 0x5742, KANJI_LEVEL4, // 坂 + 0x962A, KANJI_LEVEL4, // 阪 + 0x583A, KANJI_LEVEL4, // å º + 0x698A, KANJI_LEVEL4, // 把 + 0x80B4, KANJI_LEVEL4, // 肎 + 0x54B2, KANJI_LEVEL4, // 咲 + 0x5D0E, KANJI_LEVEL4, // 厎 + 0x57FC, KANJI_LEVEL4, // 埌 + 0x7895, KANJI_LEVEL4, // 碕 + 0x9DFA, KANJI_LEVEL4, // é·º + 0x4F5C, KANJI_LEVEL4, // 䜜 + 0x524A, KANJI_LEVEL4, // 削 + 0x548B, KANJI_LEVEL4, // 咋 + 0x643E, KANJI_LEVEL4, // 搟 + 0x6628, KANJI_LEVEL4, // 昚 + 0x6714, KANJI_LEVEL4, // 朔 + 0x67F5, KANJI_LEVEL4, // 柵 + 0x7A84, KANJI_LEVEL4, // 窄 + 0x7B56, KANJI_LEVEL4, // 策 + 0x7D22, KANJI_LEVEL4, // 玢 + 0x932F, KANJI_LEVEL4, // 錯 + 0x685C, KANJI_LEVEL4, // 桜 + 0x9BAD, KANJI_LEVEL4, // é®­ + 0x7B39, KANJI_LEVEL4, // 笹 + 0x5319, KANJI_LEVEL4, // 匙 + 0x518A, KANJI_LEVEL4, // 冊 + 0x5237, KANJI_LEVEL4, // 刷 + 0x5BDF, KANJI_LEVEL4, // 察 + 0x62F6, KANJI_LEVEL4, // 拶 + 0x64AE, KANJI_LEVEL4, // 撮 + 0x64E6, KANJI_LEVEL4, // 擊 + 0x672D, KANJI_LEVEL4, // 札 + 0x6BBA, KANJI_LEVEL4, // 殺 + 0x85A9, KANJI_LEVEL4, // 薩 + 0x96D1, KANJI_LEVEL4, // 雑 + 0x7690, KANJI_LEVEL4, // 皐 + 0x9BD6, KANJI_LEVEL4, // 鯖 + 0x634C, KANJI_LEVEL4, // 捌 + 0x9306, KANJI_LEVEL4, // 錆 + 0x9BAB, KANJI_LEVEL4, // 鮫 + 0x76BF, KANJI_LEVEL4, // 皿 + 0x6652, KANJI_LEVEL4, // 晒 + 0x4E09, KANJI_LEVEL4, // 侉 + 0x5098, KANJI_LEVEL4, // 傘 + 0x53C2, KANJI_LEVEL4, // 参 + 0x5C71, KANJI_LEVEL4, // å±± + 0x60E8, KANJI_LEVEL4, // 惚 + 0x6492, KANJI_LEVEL4, // 撒 + 0x6563, KANJI_LEVEL4, // 散 + 0x685F, KANJI_LEVEL4, // 桟 + 0x71E6, KANJI_LEVEL4, // 燩 + 0x73CA, KANJI_LEVEL4, // 珊 + 0x7523, KANJI_LEVEL4, // 産 + 0x7B97, KANJI_LEVEL4, // 算 + 0x7E82, KANJI_LEVEL4, // 纂 + 0x8695, KANJI_LEVEL4, // 蚕 + 0x8B83, KANJI_LEVEL4, // 讃 + 0x8CDB, KANJI_LEVEL4, // 賛 + 0x9178, KANJI_LEVEL4, // 酾 + 0x9910, KANJI_LEVEL4, // 逐 + 0x65AC, KANJI_LEVEL4, // 斬 + 0x66AB, KANJI_LEVEL4, // 暫 + 0x6B8B, KANJI_LEVEL4, // 残 + 0x4ED5, KANJI_LEVEL4, // 仕 + 0x4ED4, KANJI_LEVEL4, // 仔 + 0x4F3A, KANJI_LEVEL4, // 䌺 + 0x4F7F, KANJI_LEVEL4, // 䜿 + 0x523A, KANJI_LEVEL4, // 刺 + 0x53F8, KANJI_LEVEL4, // 叞 + 0x53F2, KANJI_LEVEL4, // 史 + 0x55E3, KANJI_LEVEL4, // 嗣 + 0x56DB, KANJI_LEVEL4, // 四 + 0x58EB, KANJI_LEVEL4, // 士 + 0x59CB, KANJI_LEVEL4, // 始 + 0x59C9, KANJI_LEVEL4, // 姉 + 0x59FF, KANJI_LEVEL4, // å§¿ + 0x5B50, KANJI_LEVEL4, // 子 + 0x5C4D, KANJI_LEVEL4, // 屍 + 0x5E02, KANJI_LEVEL4, // åž‚ + 0x5E2B, KANJI_LEVEL4, // åž« + 0x5FD7, KANJI_LEVEL4, // 志 + 0x601D, KANJI_LEVEL4, // 思 + 0x6307, KANJI_LEVEL4, // 指 + 0x652F, KANJI_LEVEL4, // 支 + 0x5B5C, KANJI_LEVEL4, // 孜 + 0x65AF, KANJI_LEVEL4, // 斯 + 0x65BD, KANJI_LEVEL4, // æ–œ + 0x65E8, KANJI_LEVEL4, // æ—š + 0x679D, KANJI_LEVEL4, // 枝 + 0x6B62, KANJI_LEVEL4, // æ­¢ + 0x6B7B, KANJI_LEVEL4, // æ­» + 0x6C0F, KANJI_LEVEL4, // 氏 + 0x7345, KANJI_LEVEL4, // 獅 + 0x7949, KANJI_LEVEL4, // 祉 + 0x79C1, KANJI_LEVEL4, // 私 + 0x7CF8, KANJI_LEVEL4, // 糞 + 0x7D19, KANJI_LEVEL4, // 箙 + 0x7D2B, KANJI_LEVEL4, // 玫 + 0x80A2, KANJI_LEVEL4, // 肢 + 0x8102, KANJI_LEVEL4, // 脂 + 0x81F3, KANJI_LEVEL4, // 至 + 0x8996, KANJI_LEVEL4, // 芖 + 0x8A5E, KANJI_LEVEL4, // 詞 + 0x8A69, KANJI_LEVEL4, // è©© + 0x8A66, KANJI_LEVEL4, // 詊 + 0x8A8C, KANJI_LEVEL4, // 誌 + 0x8AEE, KANJI_LEVEL4, // è«® + 0x8CC7, KANJI_LEVEL4, // 資 + 0x8CDC, KANJI_LEVEL4, // 賜 + 0x96CC, KANJI_LEVEL4, // 雌 + 0x98FC, KANJI_LEVEL4, // 飌 + 0x6B6F, KANJI_LEVEL4, // æ­¯ + 0x4E8B, KANJI_LEVEL4, // 事 + 0x4F3C, KANJI_LEVEL4, // 䌌 + 0x4F8D, KANJI_LEVEL4, // 䟍 + 0x5150, KANJI_LEVEL4, // 児 + 0x5B57, KANJI_LEVEL4, // 字 + 0x5BFA, KANJI_LEVEL4, // 寺 + 0x6148, KANJI_LEVEL4, // 慈 + 0x6301, KANJI_LEVEL4, // 持 + 0x6642, KANJI_LEVEL4, // 時 + 0x6B21, KANJI_LEVEL4, // 次 + 0x6ECB, KANJI_LEVEL4, // 滋 + 0x6CBB, KANJI_LEVEL4, // æ²» + 0x723E, KANJI_LEVEL4, // 爟 + 0x74BD, KANJI_LEVEL4, // ç’œ + 0x75D4, KANJI_LEVEL4, // 痔 + 0x78C1, KANJI_LEVEL4, // 磁 + 0x793A, KANJI_LEVEL4, // 瀺 + 0x800C, KANJI_LEVEL4, // 而 + 0x8033, KANJI_LEVEL4, // 耳 + 0x81EA, KANJI_LEVEL4, // 自 + 0x8494, KANJI_LEVEL4, // 蒔 + 0x8F9E, KANJI_LEVEL4, // 蟞 + 0x6C50, KANJI_LEVEL4, // 汐 + 0x9E7F, KANJI_LEVEL4, // 鹿 + 0x5F0F, KANJI_LEVEL4, // 匏 + 0x8B58, KANJI_LEVEL4, // 識 + 0x9D2B, KANJI_LEVEL4, // 鎫 + 0x7AFA, KANJI_LEVEL4, // 竺 + 0x8EF8, KANJI_LEVEL4, // 軞 + 0x5B8D, KANJI_LEVEL4, // 宍 + 0x96EB, KANJI_LEVEL4, // 雫 + 0x4E03, KANJI_LEVEL4, // 䞃 + 0x53F1, KANJI_LEVEL4, // 叱 + 0x57F7, KANJI_LEVEL4, // 執 + 0x5931, KANJI_LEVEL4, // 倱 + 0x5AC9, KANJI_LEVEL4, // 嫉 + 0x5BA4, KANJI_LEVEL4, // 宀 + 0x6089, KANJI_LEVEL4, // 悉 + 0x6E7F, KANJI_LEVEL4, // 湿 + 0x6F06, KANJI_LEVEL4, // 挆 + 0x75BE, KANJI_LEVEL4, // ç–Ÿ + 0x8CEA, KANJI_LEVEL4, // 質 + 0x5B9F, KANJI_LEVEL4, // 実 + 0x8500, KANJI_LEVEL4, // 蔀 + 0x7BE0, KANJI_LEVEL4, // 篠 + 0x5072, KANJI_LEVEL4, // 偲 + 0x67F4, KANJI_LEVEL4, // 柎 + 0x829D, KANJI_LEVEL4, // 芝 + 0x5C61, KANJI_LEVEL4, // 屡 + 0x854A, KANJI_LEVEL4, // 蕊 + 0x7E1E, KANJI_LEVEL4, // 羞 + 0x820E, KANJI_LEVEL4, // 舎 + 0x5199, KANJI_LEVEL4, // 写 + 0x5C04, KANJI_LEVEL4, // 射 + 0x6368, KANJI_LEVEL4, // 捚 + 0x8D66, KANJI_LEVEL4, // 赊 + 0x659C, KANJI_LEVEL4, // 斜 + 0x716E, KANJI_LEVEL4, // 煮 + 0x793E, KANJI_LEVEL4, // 瀟 + 0x7D17, KANJI_LEVEL4, // 算 + 0x8005, KANJI_LEVEL4, // 者 + 0x8B1D, KANJI_LEVEL4, // 謝 + 0x8ECA, KANJI_LEVEL4, // 車 + 0x906E, KANJI_LEVEL4, // 遮 + 0x86C7, KANJI_LEVEL4, // 蛇 + 0x90AA, KANJI_LEVEL4, // 邪 + 0x501F, KANJI_LEVEL4, // 借 + 0x52FA, KANJI_LEVEL4, // 勺 + 0x5C3A, KANJI_LEVEL4, // å°º + 0x6753, KANJI_LEVEL4, // 杓 + 0x707C, KANJI_LEVEL4, // 灌 + 0x7235, KANJI_LEVEL4, // 爵 + 0x914C, KANJI_LEVEL4, // 酌 + 0x91C8, KANJI_LEVEL4, // 釈 + 0x932B, KANJI_LEVEL4, // 錫 + 0x82E5, KANJI_LEVEL4, // 若 + 0x5BC2, KANJI_LEVEL4, // 寂 + 0x5F31, KANJI_LEVEL4, // 匱 + 0x60F9, KANJI_LEVEL4, // 惹 + 0x4E3B, KANJI_LEVEL4, // äž» + 0x53D6, KANJI_LEVEL4, // 取 + 0x5B88, KANJI_LEVEL4, // 守 + 0x624B, KANJI_LEVEL4, // 手 + 0x6731, KANJI_LEVEL4, // 朱 + 0x6B8A, KANJI_LEVEL4, // 殊 + 0x72E9, KANJI_LEVEL4, // 狩 + 0x73E0, KANJI_LEVEL4, // 珠 + 0x7A2E, KANJI_LEVEL4, // çš® + 0x816B, KANJI_LEVEL4, // 腫 + 0x8DA3, KANJI_LEVEL4, // è¶£ + 0x9152, KANJI_LEVEL4, // 酒 + 0x9996, KANJI_LEVEL4, // 驖 + 0x5112, KANJI_LEVEL4, // 儒 + 0x53D7, KANJI_LEVEL4, // 受 + 0x546A, KANJI_LEVEL4, // 呪 + 0x5BFF, KANJI_LEVEL4, // 寿 + 0x6388, KANJI_LEVEL4, // 授 + 0x6A39, KANJI_LEVEL4, // æš¹ + 0x7DAC, KANJI_LEVEL4, // 綬 + 0x9700, KANJI_LEVEL4, // 需 + 0x56DA, KANJI_LEVEL4, // 囚 + 0x53CE, KANJI_LEVEL4, // 収 + 0x5468, KANJI_LEVEL4, // 呚 + 0x5B97, KANJI_LEVEL4, // 宗 + 0x5C31, KANJI_LEVEL4, // å°± + 0x5DDE, KANJI_LEVEL4, // 州 + 0x4FEE, KANJI_LEVEL4, // ä¿® + 0x6101, KANJI_LEVEL4, // 愁 + 0x62FE, KANJI_LEVEL4, // 拟 + 0x6D32, KANJI_LEVEL4, // 掲 + 0x79C0, KANJI_LEVEL4, // 秀 + 0x79CB, KANJI_LEVEL4, // 秋 + 0x7D42, KANJI_LEVEL4, // 終 + 0x7E4D, KANJI_LEVEL4, // 繍 + 0x7FD2, KANJI_LEVEL4, // 習 + 0x81ED, KANJI_LEVEL4, // 臭 + 0x821F, KANJI_LEVEL4, // 舟 + 0x8490, KANJI_LEVEL4, // 蒐 + 0x8846, KANJI_LEVEL4, // 衆 + 0x8972, KANJI_LEVEL4, // 襲 + 0x8B90, KANJI_LEVEL4, // 讐 + 0x8E74, KANJI_LEVEL4, // 蹎 + 0x8F2F, KANJI_LEVEL4, // 茯 + 0x9031, KANJI_LEVEL4, // 週 + 0x914B, KANJI_LEVEL4, // 酋 + 0x916C, KANJI_LEVEL4, // 酬 + 0x96C6, KANJI_LEVEL4, // 集 + 0x919C, KANJI_LEVEL4, // 醜 + 0x4EC0, KANJI_LEVEL4, // 什 + 0x4F4F, KANJI_LEVEL4, // 䜏 + 0x5145, KANJI_LEVEL4, // 充 + 0x5341, KANJI_LEVEL4, // 十 + 0x5F93, KANJI_LEVEL4, // 埓 + 0x620E, KANJI_LEVEL4, // 戎 + 0x67D4, KANJI_LEVEL4, // 柔 + 0x6C41, KANJI_LEVEL4, // 汁 + 0x6E0B, KANJI_LEVEL4, // æž‹ + 0x7363, KANJI_LEVEL4, // 獣 + 0x7E26, KANJI_LEVEL4, // 瞊 + 0x91CD, KANJI_LEVEL4, // 重 + 0x9283, KANJI_LEVEL4, // 銃 + 0x53D4, KANJI_LEVEL4, // 叔 + 0x5919, KANJI_LEVEL4, // 候 + 0x5BBF, KANJI_LEVEL4, // 宿 + 0x6DD1, KANJI_LEVEL4, // 淑 + 0x795D, KANJI_LEVEL4, // 祝 + 0x7E2E, KANJI_LEVEL4, // çž® + 0x7C9B, KANJI_LEVEL4, // 粛 + 0x587E, KANJI_LEVEL4, // 塟 + 0x719F, KANJI_LEVEL4, // 熟 + 0x51FA, KANJI_LEVEL4, // 出 + 0x8853, KANJI_LEVEL4, // 術 + 0x8FF0, KANJI_LEVEL4, // è¿° + 0x4FCA, KANJI_LEVEL4, // 俊 + 0x5CFB, KANJI_LEVEL4, // å³» + 0x6625, KANJI_LEVEL4, // 春 + 0x77AC, KANJI_LEVEL4, // 瞬 + 0x7AE3, KANJI_LEVEL4, // ç«£ + 0x821C, KANJI_LEVEL4, // 舜 + 0x99FF, KANJI_LEVEL4, // é§¿ + 0x51C6, KANJI_LEVEL4, // 准 + 0x5FAA, KANJI_LEVEL4, // 埪 + 0x65EC, KANJI_LEVEL4, // 旬 + 0x696F, KANJI_LEVEL4, // 楯 + 0x6B89, KANJI_LEVEL4, // 殉 + 0x6DF3, KANJI_LEVEL4, // æ·³ + 0x6E96, KANJI_LEVEL4, // 準 + 0x6F64, KANJI_LEVEL4, // 最 + 0x76FE, KANJI_LEVEL4, // 盟 + 0x7D14, KANJI_LEVEL4, // 箔 + 0x5DE1, KANJI_LEVEL4, // å·¡ + 0x9075, KANJI_LEVEL4, // 遵 + 0x9187, KANJI_LEVEL4, // 醇 + 0x9806, KANJI_LEVEL4, // 順 + 0x51E6, KANJI_LEVEL4, // 凊 + 0x521D, KANJI_LEVEL4, // 初 + 0x6240, KANJI_LEVEL4, // 所 + 0x6691, KANJI_LEVEL4, // 暑 + 0x66D9, KANJI_LEVEL4, // 曙 + 0x6E1A, KANJI_LEVEL4, // æžš + 0x5EB6, KANJI_LEVEL4, // 庶 + 0x7DD2, KANJI_LEVEL4, // 緒 + 0x7F72, KANJI_LEVEL4, // 眲 + 0x66F8, KANJI_LEVEL4, // 曞 + 0x85AF, KANJI_LEVEL4, // 薯 + 0x85F7, KANJI_LEVEL4, // 藷 + 0x8AF8, KANJI_LEVEL4, // 諞 + 0x52A9, KANJI_LEVEL4, // 助 + 0x53D9, KANJI_LEVEL4, // 叙 + 0x5973, KANJI_LEVEL4, // 女 + 0x5E8F, KANJI_LEVEL4, // 序 + 0x5F90, KANJI_LEVEL4, // 埐 + 0x6055, KANJI_LEVEL4, // 恕 + 0x92E4, KANJI_LEVEL4, // é‹€ + 0x9664, KANJI_LEVEL4, // 陀 + 0x50B7, KANJI_LEVEL4, // 傷 + 0x511F, KANJI_LEVEL4, // 償 + 0x52DD, KANJI_LEVEL4, // 勝 + 0x5320, KANJI_LEVEL4, // 匠 + 0x5347, KANJI_LEVEL4, // 升 + 0x53EC, KANJI_LEVEL4, // 召 + 0x54E8, KANJI_LEVEL4, // 哚 + 0x5546, KANJI_LEVEL4, // 商 + 0x5531, KANJI_LEVEL4, // 唱 + 0x5617, KANJI_LEVEL4, // 嘗 + 0x5968, KANJI_LEVEL4, // 奚 + 0x59BE, KANJI_LEVEL4, // 功 + 0x5A3C, KANJI_LEVEL4, // 嚌 + 0x5BB5, KANJI_LEVEL4, // 宵 + 0x5C06, KANJI_LEVEL4, // 将 + 0x5C0F, KANJI_LEVEL4, // 小 + 0x5C11, KANJI_LEVEL4, // 少 + 0x5C1A, KANJI_LEVEL4, // 尚 + 0x5E84, KANJI_LEVEL4, // 庄 + 0x5E8A, KANJI_LEVEL4, // 床 + 0x5EE0, KANJI_LEVEL4, // å»  + 0x5F70, KANJI_LEVEL4, // 地 + 0x627F, KANJI_LEVEL4, // 承 + 0x6284, KANJI_LEVEL4, // 抄 + 0x62DB, KANJI_LEVEL4, // 招 + 0x638C, KANJI_LEVEL4, // 掌 + 0x6377, KANJI_LEVEL4, // 捷 + 0x6607, KANJI_LEVEL4, // 昇 + 0x660C, KANJI_LEVEL4, // 昌 + 0x662D, KANJI_LEVEL4, // 昭 + 0x6676, KANJI_LEVEL4, // 晶 + 0x677E, KANJI_LEVEL4, // 束 + 0x68A2, KANJI_LEVEL4, // 梢 + 0x6A1F, KANJI_LEVEL4, // 暟 + 0x6A35, KANJI_LEVEL4, // æšµ + 0x6CBC, KANJI_LEVEL4, // 沌 + 0x6D88, KANJI_LEVEL4, // 消 + 0x6E09, KANJI_LEVEL4, // 枉 + 0x6E58, KANJI_LEVEL4, // 湘 + 0x713C, KANJI_LEVEL4, // 焌 + 0x7126, KANJI_LEVEL4, // 焩 + 0x7167, KANJI_LEVEL4, // 照 + 0x75C7, KANJI_LEVEL4, // 症 + 0x7701, KANJI_LEVEL4, // 省 + 0x785D, KANJI_LEVEL4, // 硝 + 0x7901, KANJI_LEVEL4, // 瀁 + 0x7965, KANJI_LEVEL4, // 祥 + 0x79F0, KANJI_LEVEL4, // ç§° + 0x7AE0, KANJI_LEVEL4, // ç«  + 0x7B11, KANJI_LEVEL4, // 笑 + 0x7CA7, KANJI_LEVEL4, // ç²§ + 0x7D39, KANJI_LEVEL4, // 玹 + 0x8096, KANJI_LEVEL4, // 肖 + 0x83D6, KANJI_LEVEL4, // 菖 + 0x848B, KANJI_LEVEL4, // 蒋 + 0x8549, KANJI_LEVEL4, // 蕉 + 0x885D, KANJI_LEVEL4, // 衝 + 0x88F3, KANJI_LEVEL4, // 裳 + 0x8A1F, KANJI_LEVEL4, // 蚟 + 0x8A3C, KANJI_LEVEL4, // 蚌 + 0x8A54, KANJI_LEVEL4, // 詔 + 0x8A73, KANJI_LEVEL4, // 詳 + 0x8C61, KANJI_LEVEL4, // 象 + 0x8CDE, KANJI_LEVEL4, // 賞 + 0x91A4, KANJI_LEVEL4, // 醀 + 0x9266, KANJI_LEVEL4, // 鉩 + 0x937E, KANJI_LEVEL4, // 鍟 + 0x9418, KANJI_LEVEL4, // 鐘 + 0x969C, KANJI_LEVEL4, // 障 + 0x9798, KANJI_LEVEL4, // 鞘 + 0x4E0A, KANJI_LEVEL4, // 侊 + 0x4E08, KANJI_LEVEL4, // 䞈 + 0x4E1E, KANJI_LEVEL4, // 侞 + 0x4E57, KANJI_LEVEL4, // 乗 + 0x5197, KANJI_LEVEL4, // 冗 + 0x5270, KANJI_LEVEL4, // 剰 + 0x57CE, KANJI_LEVEL4, // 城 + 0x5834, KANJI_LEVEL4, // å Ž + 0x58CC, KANJI_LEVEL4, // 壌 + 0x5B22, KANJI_LEVEL4, // 嬢 + 0x5E38, KANJI_LEVEL4, // åžž + 0x60C5, KANJI_LEVEL4, // 情 + 0x64FE, KANJI_LEVEL4, // 擟 + 0x6761, KANJI_LEVEL4, // 条 + 0x6756, KANJI_LEVEL4, // 杖 + 0x6D44, KANJI_LEVEL4, // 浄 + 0x72B6, KANJI_LEVEL4, // 状 + 0x7573, KANJI_LEVEL4, // 畳 + 0x7A63, KANJI_LEVEL4, // ç©£ + 0x84B8, KANJI_LEVEL4, // è’ž + 0x8B72, KANJI_LEVEL4, // è­² + 0x91B8, KANJI_LEVEL4, // 醾 + 0x9320, KANJI_LEVEL4, // 錠 + 0x5631, KANJI_LEVEL4, // 嘱 + 0x57F4, KANJI_LEVEL4, // 城 + 0x98FE, KANJI_LEVEL4, // 食 + 0x62ED, KANJI_LEVEL4, // 拭 + 0x690D, KANJI_LEVEL4, // 怍 + 0x6B96, KANJI_LEVEL4, // 殖 + 0x71ED, KANJI_LEVEL4, // 燭 + 0x7E54, KANJI_LEVEL4, // 織 + 0x8077, KANJI_LEVEL4, // 職 + 0x8272, KANJI_LEVEL4, // 色 + 0x89E6, KANJI_LEVEL4, // è§Š + 0x98DF, KANJI_LEVEL4, // 食 + 0x8755, KANJI_LEVEL4, // 蝕 + 0x8FB1, KANJI_LEVEL4, // 蟱 + 0x5C3B, KANJI_LEVEL4, // å°» + 0x4F38, KANJI_LEVEL4, // 䌞 + 0x4FE1, KANJI_LEVEL4, // ä¿¡ + 0x4FB5, KANJI_LEVEL4, // 䟵 + 0x5507, KANJI_LEVEL4, // 唇 + 0x5A20, KANJI_LEVEL4, // åš  + 0x5BDD, KANJI_LEVEL4, // 寝 + 0x5BE9, KANJI_LEVEL4, // 審 + 0x5FC3, KANJI_LEVEL4, // 心 + 0x614E, KANJI_LEVEL4, // 慎 + 0x632F, KANJI_LEVEL4, // 振 + 0x65B0, KANJI_LEVEL4, // 新 + 0x664B, KANJI_LEVEL4, // 晋 + 0x68EE, KANJI_LEVEL4, // 森 + 0x699B, KANJI_LEVEL4, // 抛 + 0x6D78, KANJI_LEVEL4, // 浞 + 0x6DF1, KANJI_LEVEL4, // æ·± + 0x7533, KANJI_LEVEL4, // 申 + 0x75B9, KANJI_LEVEL4, // 疹 + 0x771F, KANJI_LEVEL4, // 真 + 0x795E, KANJI_LEVEL4, // 神 + 0x79E6, KANJI_LEVEL4, // ç§Š + 0x7D33, KANJI_LEVEL4, // 玳 + 0x81E3, KANJI_LEVEL4, // 臣 + 0x82AF, KANJI_LEVEL4, // 芯 + 0x85AA, KANJI_LEVEL4, // 薪 + 0x89AA, KANJI_LEVEL4, // 芪 + 0x8A3A, KANJI_LEVEL4, // 蚺 + 0x8EAB, KANJI_LEVEL4, // 身 + 0x8F9B, KANJI_LEVEL4, // 蟛 + 0x9032, KANJI_LEVEL4, // 進 + 0x91DD, KANJI_LEVEL4, // 針 + 0x9707, KANJI_LEVEL4, // 震 + 0x4EBA, KANJI_LEVEL4, // 人 + 0x4EC1, KANJI_LEVEL4, // 仁 + 0x5203, KANJI_LEVEL4, // 刃 + 0x5875, KANJI_LEVEL4, // 塵 + 0x58EC, KANJI_LEVEL4, // 壬 + 0x5C0B, KANJI_LEVEL4, // 尋 + 0x751A, KANJI_LEVEL4, // 甚 + 0x5C3D, KANJI_LEVEL4, // å°œ + 0x814E, KANJI_LEVEL4, // 腎 + 0x8A0A, KANJI_LEVEL4, // 蚊 + 0x8FC5, KANJI_LEVEL4, // 迅 + 0x9663, KANJI_LEVEL4, // 陣 + 0x976D, KANJI_LEVEL4, // 靭 + 0x7B25, KANJI_LEVEL4, // 笥 + 0x8ACF, KANJI_LEVEL4, // 諏 + 0x9808, KANJI_LEVEL4, // 須 + 0x9162, KANJI_LEVEL4, // 酢 + 0x56F3, KANJI_LEVEL4, // 図 + 0x53A8, KANJI_LEVEL4, // 厚 + 0x9017, KANJI_LEVEL4, // 逗 + 0x5439, KANJI_LEVEL4, // 吹 + 0x5782, KANJI_LEVEL4, // 垂 + 0x5E25, KANJI_LEVEL4, // 垥 + 0x63A8, KANJI_LEVEL4, // 掚 + 0x6C34, KANJI_LEVEL4, // æ°Ž + 0x708A, KANJI_LEVEL4, // 炊 + 0x7761, KANJI_LEVEL4, // 睡 + 0x7C8B, KANJI_LEVEL4, // 粋 + 0x7FE0, KANJI_LEVEL4, // ç¿  + 0x8870, KANJI_LEVEL4, // è¡° + 0x9042, KANJI_LEVEL4, // 遂 + 0x9154, KANJI_LEVEL4, // 酔 + 0x9310, KANJI_LEVEL4, // 錐 + 0x9318, KANJI_LEVEL4, // 錘 + 0x968F, KANJI_LEVEL4, // 随 + 0x745E, KANJI_LEVEL4, // 瑞 + 0x9AC4, KANJI_LEVEL4, // 髄 + 0x5D07, KANJI_LEVEL4, // 厇 + 0x5D69, KANJI_LEVEL4, // 嵩 + 0x6570, KANJI_LEVEL4, // 数 + 0x67A2, KANJI_LEVEL4, // 枢 + 0x8DA8, KANJI_LEVEL4, // è¶š + 0x96DB, KANJI_LEVEL4, // 雛 + 0x636E, KANJI_LEVEL4, // 据 + 0x6749, KANJI_LEVEL4, // 杉 + 0x6919, KANJI_LEVEL4, // 怙 + 0x83C5, KANJI_LEVEL4, // 菅 + 0x9817, KANJI_LEVEL4, // 頗 + 0x96C0, KANJI_LEVEL4, // 雀 + 0x88FE, KANJI_LEVEL4, // 裟 + 0x6F84, KANJI_LEVEL4, // 柄 + 0x647A, KANJI_LEVEL4, // 摺 + 0x5BF8, KANJI_LEVEL4, // 寞 + 0x4E16, KANJI_LEVEL4, // 侖 + 0x702C, KANJI_LEVEL4, // 瀬 + 0x755D, KANJI_LEVEL4, // 畝 + 0x662F, KANJI_LEVEL4, // 是 + 0x51C4, KANJI_LEVEL4, // 凄 + 0x5236, KANJI_LEVEL4, // 制 + 0x52E2, KANJI_LEVEL4, // 勢 + 0x59D3, KANJI_LEVEL4, // 姓 + 0x5F81, KANJI_LEVEL4, // 埁 + 0x6027, KANJI_LEVEL4, // 性 + 0x6210, KANJI_LEVEL4, // 成 + 0x653F, KANJI_LEVEL4, // 政 + 0x6574, KANJI_LEVEL4, // 敎 + 0x661F, KANJI_LEVEL4, // 星 + 0x6674, KANJI_LEVEL4, // 晎 + 0x68F2, KANJI_LEVEL4, // 棲 + 0x6816, KANJI_LEVEL4, // 栖 + 0x6B63, KANJI_LEVEL4, // æ­£ + 0x6E05, KANJI_LEVEL4, // æž… + 0x7272, KANJI_LEVEL4, // 牲 + 0x751F, KANJI_LEVEL4, // 生 + 0x76DB, KANJI_LEVEL4, // 盛 + 0x7CBE, KANJI_LEVEL4, // 粟 + 0x8056, KANJI_LEVEL4, // 聖 + 0x58F0, KANJI_LEVEL4, // 声 + 0x88FD, KANJI_LEVEL4, // 補 + 0x897F, KANJI_LEVEL4, // 西 + 0x8AA0, KANJI_LEVEL4, // 誠 + 0x8A93, KANJI_LEVEL4, // 誓 + 0x8ACB, KANJI_LEVEL4, // 請 + 0x901D, KANJI_LEVEL4, // 逝 + 0x9192, KANJI_LEVEL4, // 醒 + 0x9752, KANJI_LEVEL4, // 青 + 0x9759, KANJI_LEVEL4, // 静 + 0x6589, KANJI_LEVEL4, // 斉 + 0x7A0E, KANJI_LEVEL4, // 皎 + 0x8106, KANJI_LEVEL4, // 脆 + 0x96BB, KANJI_LEVEL4, // 隻 + 0x5E2D, KANJI_LEVEL4, // åž­ + 0x60DC, KANJI_LEVEL4, // 惜 + 0x621A, KANJI_LEVEL4, // 戚 + 0x65A5, KANJI_LEVEL4, // 斥 + 0x6614, KANJI_LEVEL4, // 昔 + 0x6790, KANJI_LEVEL4, // 析 + 0x77F3, KANJI_LEVEL4, // 石 + 0x7A4D, KANJI_LEVEL4, // 積 + 0x7C4D, KANJI_LEVEL4, // 籍 + 0x7E3E, KANJI_LEVEL4, // 瞟 + 0x810A, KANJI_LEVEL4, // 脊 + 0x8CAC, KANJI_LEVEL4, // 責 + 0x8D64, KANJI_LEVEL4, // èµ€ + 0x8DE1, KANJI_LEVEL4, // è·¡ + 0x8E5F, KANJI_LEVEL4, // 蹟 + 0x78A9, KANJI_LEVEL4, // 碩 + 0x5207, KANJI_LEVEL4, // 切 + 0x62D9, KANJI_LEVEL4, // 拙 + 0x63A5, KANJI_LEVEL4, // 接 + 0x6442, KANJI_LEVEL4, // 摂 + 0x6298, KANJI_LEVEL4, // 折 + 0x8A2D, KANJI_LEVEL4, // èš­ + 0x7A83, KANJI_LEVEL4, // 窃 + 0x7BC0, KANJI_LEVEL4, // 節 + 0x8AAC, KANJI_LEVEL4, // 説 + 0x96EA, KANJI_LEVEL4, // 雪 + 0x7D76, KANJI_LEVEL4, // çµ¶ + 0x820C, KANJI_LEVEL4, // 舌 + 0x8749, KANJI_LEVEL4, // 蝉 + 0x4ED9, KANJI_LEVEL4, // 仙 + 0x5148, KANJI_LEVEL4, // 先 + 0x5343, KANJI_LEVEL4, // 千 + 0x5360, KANJI_LEVEL4, // 占 + 0x5BA3, KANJI_LEVEL4, // 宣 + 0x5C02, KANJI_LEVEL4, // 専 + 0x5C16, KANJI_LEVEL4, // 尖 + 0x5DDD, KANJI_LEVEL4, // 川 + 0x6226, KANJI_LEVEL4, // 戊 + 0x6247, KANJI_LEVEL4, // 扇 + 0x64B0, KANJI_LEVEL4, // 撰 + 0x6813, KANJI_LEVEL4, // 栓 + 0x6834, KANJI_LEVEL4, // æ Ž + 0x6CC9, KANJI_LEVEL4, // 泉 + 0x6D45, KANJI_LEVEL4, // 浅 + 0x6D17, KANJI_LEVEL4, // 掗 + 0x67D3, KANJI_LEVEL4, // 染 + 0x6F5C, KANJI_LEVEL4, // 朜 + 0x714E, KANJI_LEVEL4, // 煎 + 0x717D, KANJI_LEVEL4, // ç…œ + 0x65CB, KANJI_LEVEL4, // 旋 + 0x7A7F, KANJI_LEVEL4, // ç©¿ + 0x7BAD, KANJI_LEVEL4, // ç®­ + 0x7DDA, KANJI_LEVEL4, // 線 + 0x7E4A, KANJI_LEVEL4, // 繊 + 0x7FA8, KANJI_LEVEL4, // 矚 + 0x817A, KANJI_LEVEL4, // 腺 + 0x821B, KANJI_LEVEL4, // 舛 + 0x8239, KANJI_LEVEL4, // 船 + 0x85A6, KANJI_LEVEL4, // è–Š + 0x8A6E, KANJI_LEVEL4, // è©® + 0x8CCE, KANJI_LEVEL4, // 賎 + 0x8DF5, KANJI_LEVEL4, // è·µ + 0x9078, KANJI_LEVEL4, // 遞 + 0x9077, KANJI_LEVEL4, // 遷 + 0x92AD, KANJI_LEVEL4, // 銭 + 0x9291, KANJI_LEVEL4, // 銑 + 0x9583, KANJI_LEVEL4, // 閃 + 0x9BAE, KANJI_LEVEL4, // é®® + 0x524D, KANJI_LEVEL4, // 前 + 0x5584, KANJI_LEVEL4, // 善 + 0x6F38, KANJI_LEVEL4, // 挞 + 0x7136, KANJI_LEVEL4, // 然 + 0x5168, KANJI_LEVEL4, // å…š + 0x7985, KANJI_LEVEL4, // 穅 + 0x7E55, KANJI_LEVEL4, // 繕 + 0x81B3, KANJI_LEVEL4, // 膳 + 0x7CCE, KANJI_LEVEL4, // 糎 + 0x564C, KANJI_LEVEL4, // 噌 + 0x5851, KANJI_LEVEL4, // 塑 + 0x5CA8, KANJI_LEVEL4, // 岚 + 0x63AA, KANJI_LEVEL4, // 措 + 0x66FE, KANJI_LEVEL4, // 曟 + 0x66FD, KANJI_LEVEL4, // 曜 + 0x695A, KANJI_LEVEL4, // 楚 + 0x72D9, KANJI_LEVEL4, // 狙 + 0x758F, KANJI_LEVEL4, // 疏 + 0x758E, KANJI_LEVEL4, // 疎 + 0x790E, KANJI_LEVEL4, // 瀎 + 0x7956, KANJI_LEVEL4, // 祖 + 0x79DF, KANJI_LEVEL4, // 租 + 0x7C97, KANJI_LEVEL4, // 粗 + 0x7D20, KANJI_LEVEL4, // 玠 + 0x7D44, KANJI_LEVEL4, // 組 + 0x8607, KANJI_LEVEL4, // 蘇 + 0x8A34, KANJI_LEVEL4, // 蚎 + 0x963B, KANJI_LEVEL4, // 阻 + 0x9061, KANJI_LEVEL4, // 遡 + 0x9F20, KANJI_LEVEL4, // 錠 + 0x50E7, KANJI_LEVEL4, // 僧 + 0x5275, KANJI_LEVEL4, // 創 + 0x53CC, KANJI_LEVEL4, // 双 + 0x53E2, KANJI_LEVEL4, // 叢 + 0x5009, KANJI_LEVEL4, // 倉 + 0x55AA, KANJI_LEVEL4, // 喪 + 0x58EE, KANJI_LEVEL4, // 壮 + 0x594F, KANJI_LEVEL4, // 奏 + 0x723D, KANJI_LEVEL4, // 爜 + 0x5B8B, KANJI_LEVEL4, // 宋 + 0x5C64, KANJI_LEVEL4, // å±€ + 0x531D, KANJI_LEVEL4, // 匝 + 0x60E3, KANJI_LEVEL4, // 惣 + 0x60F3, KANJI_LEVEL4, // 想 + 0x635C, KANJI_LEVEL4, // 捜 + 0x6383, KANJI_LEVEL4, // 掃 + 0x633F, KANJI_LEVEL4, // 挿 + 0x63BB, KANJI_LEVEL4, // 掻 + 0x64CD, KANJI_LEVEL4, // 操 + 0x65E9, KANJI_LEVEL4, // 早 + 0x66F9, KANJI_LEVEL4, // 曹 + 0x5DE3, KANJI_LEVEL4, // å·£ + 0x69CD, KANJI_LEVEL4, // 槍 + 0x69FD, KANJI_LEVEL4, // æ§œ + 0x6F15, KANJI_LEVEL4, // 挕 + 0x71E5, KANJI_LEVEL4, // 燥 + 0x4E89, KANJI_LEVEL4, // 争 + 0x75E9, KANJI_LEVEL4, // 痩 + 0x76F8, KANJI_LEVEL4, // 盾 + 0x7A93, KANJI_LEVEL4, // 窓 + 0x7CDF, KANJI_LEVEL4, // 糟 + 0x7DCF, KANJI_LEVEL4, // 総 + 0x7D9C, KANJI_LEVEL4, // 綜 + 0x8061, KANJI_LEVEL4, // 聡 + 0x8349, KANJI_LEVEL4, // 草 + 0x8358, KANJI_LEVEL4, // 荘 + 0x846C, KANJI_LEVEL4, // 葬 + 0x84BC, KANJI_LEVEL4, // è’Œ + 0x85FB, KANJI_LEVEL4, // 藻 + 0x88C5, KANJI_LEVEL4, // 装 + 0x8D70, KANJI_LEVEL4, // èµ° + 0x9001, KANJI_LEVEL4, // 送 + 0x906D, KANJI_LEVEL4, // 遭 + 0x9397, KANJI_LEVEL4, // 鎗 + 0x971C, KANJI_LEVEL4, // 霜 + 0x9A12, KANJI_LEVEL4, // 鹒 + 0x50CF, KANJI_LEVEL4, // 像 + 0x5897, KANJI_LEVEL4, // 増 + 0x618E, KANJI_LEVEL4, // 憎 + 0x81D3, KANJI_LEVEL4, // 臓 + 0x8535, KANJI_LEVEL4, // 蔵 + 0x8D08, KANJI_LEVEL4, // 莈 + 0x9020, KANJI_LEVEL4, // 造 + 0x4FC3, KANJI_LEVEL4, // 促 + 0x5074, KANJI_LEVEL4, // 偎 + 0x5247, KANJI_LEVEL4, // 則 + 0x5373, KANJI_LEVEL4, // 即 + 0x606F, KANJI_LEVEL4, // 息 + 0x6349, KANJI_LEVEL4, // 捉 + 0x675F, KANJI_LEVEL4, // 束 + 0x6E2C, KANJI_LEVEL4, // 枬 + 0x8DB3, KANJI_LEVEL4, // è¶³ + 0x901F, KANJI_LEVEL4, // 速 + 0x4FD7, KANJI_LEVEL4, // 俗 + 0x5C5E, KANJI_LEVEL4, // 属 + 0x8CCA, KANJI_LEVEL4, // 賊 + 0x65CF, KANJI_LEVEL4, // 族 + 0x7D9A, KANJI_LEVEL4, // 続 + 0x5352, KANJI_LEVEL4, // 卒 + 0x8896, KANJI_LEVEL4, // 袖 + 0x5176, KANJI_LEVEL4, // 其 + 0x63C3, KANJI_LEVEL4, // 揃 + 0x5B58, KANJI_LEVEL4, // 存 + 0x5B6B, KANJI_LEVEL4, // å­« + 0x5C0A, KANJI_LEVEL4, // 尊 + 0x640D, KANJI_LEVEL4, // 損 + 0x6751, KANJI_LEVEL4, // 村 + 0x905C, KANJI_LEVEL4, // 遜 + 0x4ED6, KANJI_LEVEL4, // 他 + 0x591A, KANJI_LEVEL4, // 倚 + 0x592A, KANJI_LEVEL4, // 倪 + 0x6C70, KANJI_LEVEL4, // æ±° + 0x8A51, KANJI_LEVEL4, // 詑 + 0x553E, KANJI_LEVEL4, // 唟 + 0x5815, KANJI_LEVEL4, // 堕 + 0x59A5, KANJI_LEVEL4, // 劥 + 0x60F0, KANJI_LEVEL4, // 惰 + 0x6253, KANJI_LEVEL4, // 打 + 0x67C1, KANJI_LEVEL4, // 柁 + 0x8235, KANJI_LEVEL4, // 舵 + 0x6955, KANJI_LEVEL4, // 楕 + 0x9640, KANJI_LEVEL4, // 陀 + 0x99C4, KANJI_LEVEL4, // 駄 + 0x9A28, KANJI_LEVEL4, // éšš + 0x4F53, KANJI_LEVEL4, // 䜓 + 0x5806, KANJI_LEVEL4, // 堆 + 0x5BFE, KANJI_LEVEL4, // 察 + 0x8010, KANJI_LEVEL4, // 耐 + 0x5CB1, KANJI_LEVEL4, // å²± + 0x5E2F, KANJI_LEVEL4, // 垯 + 0x5F85, KANJI_LEVEL4, // 埅 + 0x6020, KANJI_LEVEL4, // 怠 + 0x614B, KANJI_LEVEL4, // 態 + 0x6234, KANJI_LEVEL4, // 戎 + 0x66FF, KANJI_LEVEL4, // 替 + 0x6CF0, KANJI_LEVEL4, // æ³° + 0x6EDE, KANJI_LEVEL4, // 滞 + 0x80CE, KANJI_LEVEL4, // 胎 + 0x817F, KANJI_LEVEL4, // 腿 + 0x82D4, KANJI_LEVEL4, // 苔 + 0x888B, KANJI_LEVEL4, // 袋 + 0x8CB8, KANJI_LEVEL4, // 貞 + 0x9000, KANJI_LEVEL4, // 退 + 0x902E, KANJI_LEVEL4, // 逮 + 0x968A, KANJI_LEVEL4, // 隊 + 0x9EDB, KANJI_LEVEL4, // 黛 + 0x9BDB, KANJI_LEVEL4, // 鯛 + 0x4EE3, KANJI_LEVEL4, // 代 + 0x53F0, KANJI_LEVEL4, // 台 + 0x5927, KANJI_LEVEL4, // 倧 + 0x7B2C, KANJI_LEVEL4, // 第 + 0x918D, KANJI_LEVEL4, // 醍 + 0x984C, KANJI_LEVEL4, // 題 + 0x9DF9, KANJI_LEVEL4, // é·¹ + 0x6EDD, KANJI_LEVEL4, // 滝 + 0x7027, KANJI_LEVEL4, // 瀧 + 0x5353, KANJI_LEVEL4, // 卓 + 0x5544, KANJI_LEVEL4, // 啄 + 0x5B85, KANJI_LEVEL4, // 宅 + 0x6258, KANJI_LEVEL4, // 托 + 0x629E, KANJI_LEVEL4, // 択 + 0x62D3, KANJI_LEVEL4, // 拓 + 0x6CA2, KANJI_LEVEL4, // æ²¢ + 0x6FEF, KANJI_LEVEL4, // 濯 + 0x7422, KANJI_LEVEL4, // 琢 + 0x8A17, KANJI_LEVEL4, // èš— + 0x9438, KANJI_LEVEL4, // 鐞 + 0x6FC1, KANJI_LEVEL4, // 濁 + 0x8AFE, KANJI_LEVEL4, // 諟 + 0x8338, KANJI_LEVEL4, // 茞 + 0x51E7, KANJI_LEVEL4, // 凧 + 0x86F8, KANJI_LEVEL4, // 蛞 + 0x53EA, KANJI_LEVEL4, // 只 + 0x53E9, KANJI_LEVEL4, // 叩 + 0x4F46, KANJI_LEVEL4, // 䜆 + 0x9054, KANJI_LEVEL4, // 達 + 0x8FB0, KANJI_LEVEL4, // 蟰 + 0x596A, KANJI_LEVEL4, // 奪 + 0x8131, KANJI_LEVEL4, // 脱 + 0x5DFD, KANJI_LEVEL4, // å·œ + 0x7AEA, KANJI_LEVEL4, // 竪 + 0x8FBF, KANJI_LEVEL4, // 蟿 + 0x68DA, KANJI_LEVEL4, // 棚 + 0x8C37, KANJI_LEVEL4, // è°· + 0x72F8, KANJI_LEVEL4, // 狾 + 0x9C48, KANJI_LEVEL4, // 鱈 + 0x6A3D, KANJI_LEVEL4, // æšœ + 0x8AB0, KANJI_LEVEL4, // 誰 + 0x4E39, KANJI_LEVEL4, // äž¹ + 0x5358, KANJI_LEVEL4, // 単 + 0x5606, KANJI_LEVEL4, // 嘆 + 0x5766, KANJI_LEVEL4, // 坊 + 0x62C5, KANJI_LEVEL4, // 担 + 0x63A2, KANJI_LEVEL4, // 探 + 0x65E6, KANJI_LEVEL4, // æ—Š + 0x6B4E, KANJI_LEVEL4, // 歎 + 0x6DE1, KANJI_LEVEL4, // æ·¡ + 0x6E5B, KANJI_LEVEL4, // 湛 + 0x70AD, KANJI_LEVEL4, // 炭 + 0x77ED, KANJI_LEVEL4, // 短 + 0x7AEF, KANJI_LEVEL4, // 端 + 0x7BAA, KANJI_LEVEL4, // 箪 + 0x7DBB, KANJI_LEVEL4, // ç¶» + 0x803D, KANJI_LEVEL4, // 耜 + 0x80C6, KANJI_LEVEL4, // 胆 + 0x86CB, KANJI_LEVEL4, // 蛋 + 0x8A95, KANJI_LEVEL4, // 誕 + 0x935B, KANJI_LEVEL4, // 鍛 + 0x56E3, KANJI_LEVEL4, // 団 + 0x58C7, KANJI_LEVEL4, // 壇 + 0x5F3E, KANJI_LEVEL4, // 匟 + 0x65AD, KANJI_LEVEL4, // 断 + 0x6696, KANJI_LEVEL4, // 暖 + 0x6A80, KANJI_LEVEL4, // 檀 + 0x6BB5, KANJI_LEVEL4, // 段 + 0x7537, KANJI_LEVEL4, // 男 + 0x8AC7, KANJI_LEVEL4, // 談 + 0x5024, KANJI_LEVEL4, // 倀 + 0x77E5, KANJI_LEVEL4, // 知 + 0x5730, KANJI_LEVEL4, // 地 + 0x5F1B, KANJI_LEVEL4, // 匛 + 0x6065, KANJI_LEVEL4, // 恥 + 0x667A, KANJI_LEVEL4, // 智 + 0x6C60, KANJI_LEVEL4, // æ±  + 0x75F4, KANJI_LEVEL4, // 痮 + 0x7A1A, KANJI_LEVEL4, // 繚 + 0x7F6E, KANJI_LEVEL4, // 眮 + 0x81F4, KANJI_LEVEL4, // 臎 + 0x8718, KANJI_LEVEL4, // 蜘 + 0x9045, KANJI_LEVEL4, // 遅 + 0x99B3, KANJI_LEVEL4, // 銳 + 0x7BC9, KANJI_LEVEL4, // 築 + 0x755C, KANJI_LEVEL4, // 畜 + 0x7AF9, KANJI_LEVEL4, // 竹 + 0x7B51, KANJI_LEVEL4, // 筑 + 0x84C4, KANJI_LEVEL4, // 蓄 + 0x9010, KANJI_LEVEL4, // 逐 + 0x79E9, KANJI_LEVEL4, // ç§© + 0x7A92, KANJI_LEVEL4, // 窒 + 0x8336, KANJI_LEVEL4, // 茶 + 0x5AE1, KANJI_LEVEL4, // å«¡ + 0x7740, KANJI_LEVEL4, // 着 + 0x4E2D, KANJI_LEVEL4, // äž­ + 0x4EF2, KANJI_LEVEL4, // 仲 + 0x5B99, KANJI_LEVEL4, // 宙 + 0x5FE0, KANJI_LEVEL4, // å¿  + 0x62BD, KANJI_LEVEL4, // 抜 + 0x663C, KANJI_LEVEL4, // 昌 + 0x67F1, KANJI_LEVEL4, // 柱 + 0x6CE8, KANJI_LEVEL4, // 泚 + 0x866B, KANJI_LEVEL4, // 虫 + 0x8877, KANJI_LEVEL4, // è¡· + 0x8A3B, KANJI_LEVEL4, // èš» + 0x914E, KANJI_LEVEL4, // 酎 + 0x92F3, KANJI_LEVEL4, // 鋳 + 0x99D0, KANJI_LEVEL4, // 駐 + 0x6A17, KANJI_LEVEL4, // æš— + 0x7026, KANJI_LEVEL4, // 瀩 + 0x732A, KANJI_LEVEL4, // 猪 + 0x82E7, KANJI_LEVEL4, // 苧 + 0x8457, KANJI_LEVEL4, // 著 + 0x8CAF, KANJI_LEVEL4, // 貯 + 0x4E01, KANJI_LEVEL4, // 䞁 + 0x5146, KANJI_LEVEL4, // 兆 + 0x51CB, KANJI_LEVEL4, // 凋 + 0x558B, KANJI_LEVEL4, // 喋 + 0x5BF5, KANJI_LEVEL4, // 寵 + 0x5E16, KANJI_LEVEL4, // åž– + 0x5E33, KANJI_LEVEL4, // åž³ + 0x5E81, KANJI_LEVEL4, // 庁 + 0x5F14, KANJI_LEVEL4, // 匔 + 0x5F35, KANJI_LEVEL4, // 匵 + 0x5F6B, KANJI_LEVEL4, // 圫 + 0x5FB4, KANJI_LEVEL4, // 城 + 0x61F2, KANJI_LEVEL4, // 懲 + 0x6311, KANJI_LEVEL4, // 挑 + 0x66A2, KANJI_LEVEL4, // 暢 + 0x671D, KANJI_LEVEL4, // 朝 + 0x6F6E, KANJI_LEVEL4, // 朮 + 0x7252, KANJI_LEVEL4, // 牒 + 0x753A, KANJI_LEVEL4, // 町 + 0x773A, KANJI_LEVEL4, // 眺 + 0x8074, KANJI_LEVEL4, // 聎 + 0x8139, KANJI_LEVEL4, // 脹 + 0x8178, KANJI_LEVEL4, // è…ž + 0x8776, KANJI_LEVEL4, // 蝶 + 0x8ABF, KANJI_LEVEL4, // 調 + 0x8ADC, KANJI_LEVEL4, // 諜 + 0x8D85, KANJI_LEVEL4, // 超 + 0x8DF3, KANJI_LEVEL4, // è·³ + 0x929A, KANJI_LEVEL4, // 銚 + 0x9577, KANJI_LEVEL4, // 長 + 0x9802, KANJI_LEVEL4, // 頂 + 0x9CE5, KANJI_LEVEL4, // é³¥ + 0x52C5, KANJI_LEVEL4, // 勅 + 0x6357, KANJI_LEVEL4, // 捗 + 0x76F4, KANJI_LEVEL4, // 目 + 0x6715, KANJI_LEVEL4, // 朕 + 0x6C88, KANJI_LEVEL4, // 沈 + 0x73CD, KANJI_LEVEL4, // 珍 + 0x8CC3, KANJI_LEVEL4, // 賃 + 0x93AE, KANJI_LEVEL4, // 鎮 + 0x9673, KANJI_LEVEL4, // 陳 + 0x6D25, KANJI_LEVEL4, // 接 + 0x589C, KANJI_LEVEL4, // 墜 + 0x690E, KANJI_LEVEL4, // 怎 + 0x69CC, KANJI_LEVEL4, // 槌 + 0x8FFD, KANJI_LEVEL4, // 远 + 0x939A, KANJI_LEVEL4, // 鎚 + 0x75DB, KANJI_LEVEL4, // 痛 + 0x901A, KANJI_LEVEL4, // 通 + 0x585A, KANJI_LEVEL4, // 塚 + 0x6802, KANJI_LEVEL4, // 栂 + 0x63B4, KANJI_LEVEL4, // 掎 + 0x69FB, KANJI_LEVEL4, // æ§» + 0x4F43, KANJI_LEVEL4, // 䜃 + 0x6F2C, KANJI_LEVEL4, // 挬 + 0x67D8, KANJI_LEVEL4, // 柘 + 0x8FBB, KANJI_LEVEL4, // 蟻 + 0x8526, KANJI_LEVEL4, // 蔊 + 0x7DB4, KANJI_LEVEL4, // ç¶Ž + 0x9354, KANJI_LEVEL4, // 鍔 + 0x693F, KANJI_LEVEL4, // 怿 + 0x6F70, KANJI_LEVEL4, // 朰 + 0x576A, KANJI_LEVEL4, // 坪 + 0x58F7, KANJI_LEVEL4, // 壷 + 0x5B2C, KANJI_LEVEL4, // 嬬 + 0x7D2C, KANJI_LEVEL4, // 玬 + 0x722A, KANJI_LEVEL4, // 爪 + 0x540A, KANJI_LEVEL4, // 吊 + 0x91E3, KANJI_LEVEL4, // 釣 + 0x9DB4, KANJI_LEVEL4, // é¶Ž + 0x4EAD, KANJI_LEVEL4, // 亭 + 0x4F4E, KANJI_LEVEL4, // 䜎 + 0x505C, KANJI_LEVEL4, // 停 + 0x5075, KANJI_LEVEL4, // 偵 + 0x5243, KANJI_LEVEL4, // 剃 + 0x8C9E, KANJI_LEVEL4, // 貞 + 0x5448, KANJI_LEVEL4, // 呈 + 0x5824, KANJI_LEVEL4, // å € + 0x5B9A, KANJI_LEVEL4, // 定 + 0x5E1D, KANJI_LEVEL4, // 垝 + 0x5E95, KANJI_LEVEL4, // 底 + 0x5EAD, KANJI_LEVEL4, // 庭 + 0x5EF7, KANJI_LEVEL4, // å»· + 0x5F1F, KANJI_LEVEL4, // 匟 + 0x608C, KANJI_LEVEL4, // 悌 + 0x62B5, KANJI_LEVEL4, // 抵 + 0x633A, KANJI_LEVEL4, // 挺 + 0x63D0, KANJI_LEVEL4, // 提 + 0x68AF, KANJI_LEVEL4, // 梯 + 0x6C40, KANJI_LEVEL4, // 汀 + 0x7887, KANJI_LEVEL4, // 碇 + 0x798E, KANJI_LEVEL4, // 犎 + 0x7A0B, KANJI_LEVEL4, // 繋 + 0x7DE0, KANJI_LEVEL4, // ç·  + 0x8247, KANJI_LEVEL4, // 艇 + 0x8A02, KANJI_LEVEL4, // èš‚ + 0x8AE6, KANJI_LEVEL4, // 諊 + 0x8E44, KANJI_LEVEL4, // 蹄 + 0x9013, KANJI_LEVEL4, // 逓 + 0x90B8, KANJI_LEVEL4, // 邾 + 0x912D, KANJI_LEVEL4, // 鄭 + 0x91D8, KANJI_LEVEL4, // 釘 + 0x9F0E, KANJI_LEVEL4, // 錎 + 0x6CE5, KANJI_LEVEL4, // æ³¥ + 0x6458, KANJI_LEVEL4, // 摘 + 0x64E2, KANJI_LEVEL4, // 擢 + 0x6575, KANJI_LEVEL4, // 敵 + 0x6EF4, KANJI_LEVEL4, // 滎 + 0x7684, KANJI_LEVEL4, // 的 + 0x7B1B, KANJI_LEVEL4, // 笛 + 0x9069, KANJI_LEVEL4, // 適 + 0x93D1, KANJI_LEVEL4, // 鏑 + 0x6EBA, KANJI_LEVEL4, // 溺 + 0x54F2, KANJI_LEVEL4, // 哲 + 0x5FB9, KANJI_LEVEL4, // 培 + 0x64A4, KANJI_LEVEL4, // æ’€ + 0x8F4D, KANJI_LEVEL4, // 蜍 + 0x8FED, KANJI_LEVEL4, // è¿­ + 0x9244, KANJI_LEVEL4, // 鉄 + 0x5178, KANJI_LEVEL4, // å…ž + 0x586B, KANJI_LEVEL4, // å¡« + 0x5929, KANJI_LEVEL4, // 倩 + 0x5C55, KANJI_LEVEL4, // 展 + 0x5E97, KANJI_LEVEL4, // 店 + 0x6DFB, KANJI_LEVEL4, // æ·» + 0x7E8F, KANJI_LEVEL4, // 纏 + 0x751C, KANJI_LEVEL4, // 甜 + 0x8CBC, KANJI_LEVEL4, // 貌 + 0x8EE2, KANJI_LEVEL4, // 転 + 0x985B, KANJI_LEVEL4, // 顛 + 0x70B9, KANJI_LEVEL4, // 点 + 0x4F1D, KANJI_LEVEL4, // 䌝 + 0x6BBF, KANJI_LEVEL4, // 殿 + 0x6FB1, KANJI_LEVEL4, // 柱 + 0x7530, KANJI_LEVEL4, // 田 + 0x96FB, KANJI_LEVEL4, // 電 + 0x514E, KANJI_LEVEL4, // 兎 + 0x5410, KANJI_LEVEL4, // 吐 + 0x5835, KANJI_LEVEL4, // å µ + 0x5857, KANJI_LEVEL4, // 塗 + 0x59AC, KANJI_LEVEL4, // 劬 + 0x5C60, KANJI_LEVEL4, // å±  + 0x5F92, KANJI_LEVEL4, // 埒 + 0x6597, KANJI_LEVEL4, // 斗 + 0x675C, KANJI_LEVEL4, // 杜 + 0x6E21, KANJI_LEVEL4, // æž¡ + 0x767B, KANJI_LEVEL4, // 登 + 0x83DF, KANJI_LEVEL4, // 菟 + 0x8CED, KANJI_LEVEL4, // è³­ + 0x9014, KANJI_LEVEL4, // 途 + 0x90FD, KANJI_LEVEL4, // 郜 + 0x934D, KANJI_LEVEL4, // 鍍 + 0x7825, KANJI_LEVEL4, // ç ¥ + 0x783A, KANJI_LEVEL4, // ç º + 0x52AA, KANJI_LEVEL4, // 努 + 0x5EA6, KANJI_LEVEL4, // 床 + 0x571F, KANJI_LEVEL4, // 土 + 0x5974, KANJI_LEVEL4, // 奎 + 0x6012, KANJI_LEVEL4, // 怒 + 0x5012, KANJI_LEVEL4, // 倒 + 0x515A, KANJI_LEVEL4, // 党 + 0x51AC, KANJI_LEVEL4, // 冬 + 0x51CD, KANJI_LEVEL4, // 凍 + 0x5200, KANJI_LEVEL4, // 刀 + 0x5510, KANJI_LEVEL4, // 唐 + 0x5854, KANJI_LEVEL4, // 塔 + 0x5858, KANJI_LEVEL4, // 塘 + 0x5957, KANJI_LEVEL4, // 套 + 0x5B95, KANJI_LEVEL4, // 宕 + 0x5CF6, KANJI_LEVEL4, // å³¶ + 0x5D8B, KANJI_LEVEL4, // 嶋 + 0x60BC, KANJI_LEVEL4, // 悌 + 0x6295, KANJI_LEVEL4, // 投 + 0x642D, KANJI_LEVEL4, // 搭 + 0x6771, KANJI_LEVEL4, // 東 + 0x6843, KANJI_LEVEL4, // 桃 + 0x68BC, KANJI_LEVEL4, // 梌 + 0x68DF, KANJI_LEVEL4, // 棟 + 0x76D7, KANJI_LEVEL4, // 盗 + 0x6DD8, KANJI_LEVEL4, // 淘 + 0x6E6F, KANJI_LEVEL4, // 湯 + 0x6D9B, KANJI_LEVEL4, // 涛 + 0x706F, KANJI_LEVEL4, // 灯 + 0x71C8, KANJI_LEVEL4, // 燈 + 0x5F53, KANJI_LEVEL4, // 圓 + 0x75D8, KANJI_LEVEL4, // 痘 + 0x7977, KANJI_LEVEL4, // 祷 + 0x7B49, KANJI_LEVEL4, // 等 + 0x7B54, KANJI_LEVEL4, // 答 + 0x7B52, KANJI_LEVEL4, // 筒 + 0x7CD6, KANJI_LEVEL4, // 糖 + 0x7D71, KANJI_LEVEL4, // çµ± + 0x5230, KANJI_LEVEL4, // 到 + 0x8463, KANJI_LEVEL4, // 董 + 0x8569, KANJI_LEVEL4, // 蕩 + 0x85E4, KANJI_LEVEL4, // è—€ + 0x8A0E, KANJI_LEVEL4, // 蚎 + 0x8B04, KANJI_LEVEL4, // 謄 + 0x8C46, KANJI_LEVEL4, // 豆 + 0x8E0F, KANJI_LEVEL4, // 螏 + 0x9003, KANJI_LEVEL4, // 逃 + 0x900F, KANJI_LEVEL4, // 透 + 0x9419, KANJI_LEVEL4, // 鐙 + 0x9676, KANJI_LEVEL4, // 陶 + 0x982D, KANJI_LEVEL4, // é ­ + 0x9A30, KANJI_LEVEL4, // éš° + 0x95D8, KANJI_LEVEL4, // 闘 + 0x50CD, KANJI_LEVEL4, // 働 + 0x52D5, KANJI_LEVEL4, // 動 + 0x540C, KANJI_LEVEL4, // 同 + 0x5802, KANJI_LEVEL4, // 堂 + 0x5C0E, KANJI_LEVEL4, // 導 + 0x61A7, KANJI_LEVEL4, // 憧 + 0x649E, KANJI_LEVEL4, // 撞 + 0x6D1E, KANJI_LEVEL4, // 掞 + 0x77B3, KANJI_LEVEL4, // 瞳 + 0x7AE5, KANJI_LEVEL4, // ç«¥ + 0x80F4, KANJI_LEVEL4, // 胎 + 0x8404, KANJI_LEVEL4, // 萄 + 0x9053, KANJI_LEVEL4, // 道 + 0x9285, KANJI_LEVEL4, // 銅 + 0x5CE0, KANJI_LEVEL4, // å³  + 0x9D07, KANJI_LEVEL4, // 鮇 + 0x533F, KANJI_LEVEL4, // 匿 + 0x5F97, KANJI_LEVEL4, // 埗 + 0x5FB3, KANJI_LEVEL4, // 埳 + 0x6D9C, KANJI_LEVEL4, // 涜 + 0x7279, KANJI_LEVEL4, // 特 + 0x7763, KANJI_LEVEL4, // 督 + 0x79BF, KANJI_LEVEL4, // 犿 + 0x7BE4, KANJI_LEVEL4, // 節 + 0x6BD2, KANJI_LEVEL4, // 毒 + 0x72EC, KANJI_LEVEL4, // 独 + 0x8AAD, KANJI_LEVEL4, // 読 + 0x6803, KANJI_LEVEL4, // 栃 + 0x6A61, KANJI_LEVEL4, // æ©¡ + 0x51F8, KANJI_LEVEL4, // 凞 + 0x7A81, KANJI_LEVEL4, // 突 + 0x6934, KANJI_LEVEL4, // 怎 + 0x5C4A, KANJI_LEVEL4, // 届 + 0x9CF6, KANJI_LEVEL4, // é³¶ + 0x82EB, KANJI_LEVEL4, // 苫 + 0x5BC5, KANJI_LEVEL4, // 寅 + 0x9149, KANJI_LEVEL4, // 酉 + 0x701E, KANJI_LEVEL4, // 瀞 + 0x5678, KANJI_LEVEL4, // 噞 + 0x5C6F, KANJI_LEVEL4, // 屯 + 0x60C7, KANJI_LEVEL4, // 惇 + 0x6566, KANJI_LEVEL4, // 敊 + 0x6C8C, KANJI_LEVEL4, // 沌 + 0x8C5A, KANJI_LEVEL4, // 豚 + 0x9041, KANJI_LEVEL4, // 遁 + 0x9813, KANJI_LEVEL4, // 頓 + 0x5451, KANJI_LEVEL4, // 呑 + 0x66C7, KANJI_LEVEL4, // 曇 + 0x920D, KANJI_LEVEL4, // 鈍 + 0x5948, KANJI_LEVEL4, // 奈 + 0x90A3, KANJI_LEVEL4, // 那 + 0x5185, KANJI_LEVEL4, // 内 + 0x4E4D, KANJI_LEVEL4, // 乍 + 0x51EA, KANJI_LEVEL4, // 凪 + 0x8599, KANJI_LEVEL4, // 薙 + 0x8B0E, KANJI_LEVEL4, // 謎 + 0x7058, KANJI_LEVEL4, // 灘 + 0x637A, KANJI_LEVEL4, // 捺 + 0x934B, KANJI_LEVEL4, // 鍋 + 0x6962, KANJI_LEVEL4, // 楢 + 0x99B4, KANJI_LEVEL4, // 銎 + 0x7E04, KANJI_LEVEL4, // 羄 + 0x7577, KANJI_LEVEL4, // 畷 + 0x5357, KANJI_LEVEL4, // 南 + 0x6960, KANJI_LEVEL4, // 楠 + 0x8EDF, KANJI_LEVEL4, // 軟 + 0x96E3, KANJI_LEVEL4, // 難 + 0x6C5D, KANJI_LEVEL4, // 汝 + 0x4E8C, KANJI_LEVEL4, // 二 + 0x5C3C, KANJI_LEVEL4, // å°Œ + 0x5F10, KANJI_LEVEL4, // 匐 + 0x8FE9, KANJI_LEVEL4, // è¿© + 0x5302, KANJI_LEVEL4, // 匂 + 0x8CD1, KANJI_LEVEL4, // 賑 + 0x8089, KANJI_LEVEL4, // 肉 + 0x8679, KANJI_LEVEL4, // 虹 + 0x5EFF, KANJI_LEVEL4, // 廿 + 0x65E5, KANJI_LEVEL4, // 日 + 0x4E73, KANJI_LEVEL4, // ä¹³ + 0x5165, KANJI_LEVEL4, // 入 + 0x5982, KANJI_LEVEL4, // 劂 + 0x5C3F, KANJI_LEVEL4, // å°¿ + 0x97EE, KANJI_LEVEL4, // 韮 + 0x4EFB, KANJI_LEVEL4, // ä»» + 0x598A, KANJI_LEVEL4, // 劊 + 0x5FCD, KANJI_LEVEL4, // 忍 + 0x8A8D, KANJI_LEVEL4, // 認 + 0x6FE1, KANJI_LEVEL4, // æ¿¡ + 0x79B0, KANJI_LEVEL4, // 犰 + 0x7962, KANJI_LEVEL4, // 祢 + 0x5BE7, KANJI_LEVEL4, // 寧 + 0x8471, KANJI_LEVEL4, // 葱 + 0x732B, KANJI_LEVEL4, // 猫 + 0x71B1, KANJI_LEVEL4, // 熱 + 0x5E74, KANJI_LEVEL4, // 幎 + 0x5FF5, KANJI_LEVEL4, // 念 + 0x637B, KANJI_LEVEL4, // 捻 + 0x649A, KANJI_LEVEL4, // 撚 + 0x71C3, KANJI_LEVEL4, // 燃 + 0x7C98, KANJI_LEVEL4, // 粘 + 0x4E43, KANJI_LEVEL4, // 乃 + 0x5EFC, KANJI_LEVEL4, // 廌 + 0x4E4B, KANJI_LEVEL4, // 之 + 0x57DC, KANJI_LEVEL4, // 埜 + 0x56A2, KANJI_LEVEL4, // 嚢 + 0x60A9, KANJI_LEVEL4, // 悩 + 0x6FC3, KANJI_LEVEL4, // 濃 + 0x7D0D, KANJI_LEVEL4, // 玍 + 0x80FD, KANJI_LEVEL4, // 胜 + 0x8133, KANJI_LEVEL4, // 脳 + 0x81BF, KANJI_LEVEL4, // 膿 + 0x8FB2, KANJI_LEVEL4, // 蟲 + 0x8997, KANJI_LEVEL4, // 芗 + 0x86A4, KANJI_LEVEL4, // 蚀 + 0x5DF4, KANJI_LEVEL4, // å·Ž + 0x628A, KANJI_LEVEL4, // 把 + 0x64AD, KANJI_LEVEL4, // 播 + 0x8987, KANJI_LEVEL4, // 芇 + 0x6777, KANJI_LEVEL4, // 杷 + 0x6CE2, KANJI_LEVEL4, // æ³¢ + 0x6D3E, KANJI_LEVEL4, // 掟 + 0x7436, KANJI_LEVEL4, // 琶 + 0x7834, KANJI_LEVEL4, // ç Ž + 0x5A46, KANJI_LEVEL4, // 婆 + 0x7F75, KANJI_LEVEL4, // 眵 + 0x82AD, KANJI_LEVEL4, // 芭 + 0x99AC, KANJI_LEVEL4, // 銬 + 0x4FF3, KANJI_LEVEL4, // 俳 + 0x5EC3, KANJI_LEVEL4, // 廃 + 0x62DD, KANJI_LEVEL4, // 拝 + 0x6392, KANJI_LEVEL4, // 排 + 0x6557, KANJI_LEVEL4, // 敗 + 0x676F, KANJI_LEVEL4, // 杯 + 0x76C3, KANJI_LEVEL4, // 盃 + 0x724C, KANJI_LEVEL4, // 牌 + 0x80CC, KANJI_LEVEL4, // 背 + 0x80BA, KANJI_LEVEL4, // 肺 + 0x8F29, KANJI_LEVEL4, // 茩 + 0x914D, KANJI_LEVEL4, // 配 + 0x500D, KANJI_LEVEL4, // 倍 + 0x57F9, KANJI_LEVEL4, // 培 + 0x5A92, KANJI_LEVEL4, // 媒 + 0x6885, KANJI_LEVEL4, // 梅 + 0x6973, KANJI_LEVEL4, // 楳 + 0x7164, KANJI_LEVEL4, // ç…€ + 0x72FD, KANJI_LEVEL4, // 狜 + 0x8CB7, KANJI_LEVEL4, // è²· + 0x58F2, KANJI_LEVEL4, // 売 + 0x8CE0, KANJI_LEVEL4, // è³  + 0x966A, KANJI_LEVEL4, // 陪 + 0x9019, KANJI_LEVEL4, // 這 + 0x877F, KANJI_LEVEL4, // 蝿 + 0x79E4, KANJI_LEVEL4, // ç§€ + 0x77E7, KANJI_LEVEL4, // 矧 + 0x8429, KANJI_LEVEL4, // 萩 + 0x4F2F, KANJI_LEVEL4, // 䌯 + 0x5265, KANJI_LEVEL4, // 剥 + 0x535A, KANJI_LEVEL4, // 博 + 0x62CD, KANJI_LEVEL4, // 拍 + 0x67CF, KANJI_LEVEL4, // 柏 + 0x6CCA, KANJI_LEVEL4, // 泊 + 0x767D, KANJI_LEVEL4, // 癜 + 0x7B94, KANJI_LEVEL4, // 箔 + 0x7C95, KANJI_LEVEL4, // 粕 + 0x8236, KANJI_LEVEL4, // 舶 + 0x8584, KANJI_LEVEL4, // 薄 + 0x8FEB, KANJI_LEVEL4, // è¿« + 0x66DD, KANJI_LEVEL4, // 曝 + 0x6F20, KANJI_LEVEL4, // 挠 + 0x7206, KANJI_LEVEL4, // 爆 + 0x7E1B, KANJI_LEVEL4, // 羛 + 0x83AB, KANJI_LEVEL4, // 莫 + 0x99C1, KANJI_LEVEL4, // 駁 + 0x9EA6, KANJI_LEVEL4, // 麊 + 0x51FD, KANJI_LEVEL4, // 凜 + 0x7BB1, KANJI_LEVEL4, // ç®± + 0x7872, KANJI_LEVEL4, // 硲 + 0x7BB8, KANJI_LEVEL4, // 箞 + 0x8087, KANJI_LEVEL4, // 肇 + 0x7B48, KANJI_LEVEL4, // 筈 + 0x6AE8, KANJI_LEVEL4, // 櫚 + 0x5E61, KANJI_LEVEL4, // 幡 + 0x808C, KANJI_LEVEL4, // 肌 + 0x7551, KANJI_LEVEL4, // 畑 + 0x7560, KANJI_LEVEL4, // 畠 + 0x516B, KANJI_LEVEL4, // 八 + 0x9262, KANJI_LEVEL4, // 鉢 + 0x6E8C, KANJI_LEVEL4, // 溌 + 0x767A, KANJI_LEVEL4, // 発 + 0x9197, KANJI_LEVEL4, // 醗 + 0x9AEA, KANJI_LEVEL4, // 髪 + 0x4F10, KANJI_LEVEL4, // 䌐 + 0x7F70, KANJI_LEVEL4, // 眰 + 0x629C, KANJI_LEVEL4, // 抜 + 0x7B4F, KANJI_LEVEL4, // 筏 + 0x95A5, KANJI_LEVEL4, // 閥 + 0x9CE9, KANJI_LEVEL4, // 鳩 + 0x567A, KANJI_LEVEL4, // 噺 + 0x5859, KANJI_LEVEL4, // 塙 + 0x86E4, KANJI_LEVEL4, // 蛀 + 0x96BC, KANJI_LEVEL4, // 隌 + 0x4F34, KANJI_LEVEL4, // 䌎 + 0x5224, KANJI_LEVEL4, // 刀 + 0x534A, KANJI_LEVEL4, // 半 + 0x53CD, KANJI_LEVEL4, // 反 + 0x53DB, KANJI_LEVEL4, // 叛 + 0x5E06, KANJI_LEVEL4, // 垆 + 0x642C, KANJI_LEVEL4, // 搬 + 0x6591, KANJI_LEVEL4, // 斑 + 0x677F, KANJI_LEVEL4, // 板 + 0x6C3E, KANJI_LEVEL4, // æ°Ÿ + 0x6C4E, KANJI_LEVEL4, // 汎 + 0x7248, KANJI_LEVEL4, // 版 + 0x72AF, KANJI_LEVEL4, // 犯 + 0x73ED, KANJI_LEVEL4, // 班 + 0x7554, KANJI_LEVEL4, // 畔 + 0x7E41, KANJI_LEVEL4, // 繁 + 0x822C, KANJI_LEVEL4, // 般 + 0x85E9, KANJI_LEVEL4, // 藩 + 0x8CA9, KANJI_LEVEL4, // 販 + 0x7BC4, KANJI_LEVEL4, // 範 + 0x91C6, KANJI_LEVEL4, // 釆 + 0x7169, KANJI_LEVEL4, // 煩 + 0x9812, KANJI_LEVEL4, // 頒 + 0x98EF, KANJI_LEVEL4, // 飯 + 0x633D, KANJI_LEVEL4, // 挜 + 0x6669, KANJI_LEVEL4, // 晩 + 0x756A, KANJI_LEVEL4, // 番 + 0x76E4, KANJI_LEVEL4, // 盀 + 0x78D0, KANJI_LEVEL4, // 磐 + 0x8543, KANJI_LEVEL4, // 蕃 + 0x86EE, KANJI_LEVEL4, // 蛮 + 0x532A, KANJI_LEVEL4, // 匪 + 0x5351, KANJI_LEVEL4, // 卑 + 0x5426, KANJI_LEVEL4, // 吊 + 0x5983, KANJI_LEVEL4, // 劃 + 0x5E87, KANJI_LEVEL4, // 庇 + 0x5F7C, KANJI_LEVEL4, // 圌 + 0x60B2, KANJI_LEVEL4, // 悲 + 0x6249, KANJI_LEVEL4, // 扉 + 0x6279, KANJI_LEVEL4, // 批 + 0x62AB, KANJI_LEVEL4, // 披 + 0x6590, KANJI_LEVEL4, // 斐 + 0x6BD4, KANJI_LEVEL4, // 比 + 0x6CCC, KANJI_LEVEL4, // 泌 + 0x75B2, KANJI_LEVEL4, // 疲 + 0x76AE, KANJI_LEVEL4, // 皮 + 0x7891, KANJI_LEVEL4, // 碑 + 0x79D8, KANJI_LEVEL4, // 秘 + 0x7DCB, KANJI_LEVEL4, // 緋 + 0x7F77, KANJI_LEVEL4, // 眷 + 0x80A5, KANJI_LEVEL4, // 肥 + 0x88AB, KANJI_LEVEL4, // 被 + 0x8AB9, KANJI_LEVEL4, // 誹 + 0x8CBB, KANJI_LEVEL4, // è²» + 0x907F, KANJI_LEVEL4, // 避 + 0x975E, KANJI_LEVEL4, // 非 + 0x98DB, KANJI_LEVEL4, // 飛 + 0x6A0B, KANJI_LEVEL4, // æš‹ + 0x7C38, KANJI_LEVEL4, // ç°ž + 0x5099, KANJI_LEVEL4, // 備 + 0x5C3E, KANJI_LEVEL4, // å°Ÿ + 0x5FAE, KANJI_LEVEL4, // 埮 + 0x6787, KANJI_LEVEL4, // 枇 + 0x6BD8, KANJI_LEVEL4, // 毘 + 0x7435, KANJI_LEVEL4, // 琵 + 0x7709, KANJI_LEVEL4, // 眉 + 0x7F8E, KANJI_LEVEL4, // 矎 + 0x9F3B, KANJI_LEVEL4, // 錻 + 0x67CA, KANJI_LEVEL4, // 柊 + 0x7A17, KANJI_LEVEL4, // 繗 + 0x5339, KANJI_LEVEL4, // 匹 + 0x758B, KANJI_LEVEL4, // 疋 + 0x9AED, KANJI_LEVEL4, // é«­ + 0x5F66, KANJI_LEVEL4, // 圊 + 0x819D, KANJI_LEVEL4, // 膝 + 0x83F1, KANJI_LEVEL4, // 菱 + 0x8098, KANJI_LEVEL4, // 肘 + 0x5F3C, KANJI_LEVEL4, // 匌 + 0x5FC5, KANJI_LEVEL4, // 必 + 0x7562, KANJI_LEVEL4, // 畢 + 0x7B46, KANJI_LEVEL4, // 筆 + 0x903C, KANJI_LEVEL4, // 逌 + 0x6867, KANJI_LEVEL4, // æ¡§ + 0x59EB, KANJI_LEVEL4, // å§« + 0x5A9B, KANJI_LEVEL4, // 媛 + 0x7D10, KANJI_LEVEL4, // 玐 + 0x767E, KANJI_LEVEL4, // 癟 + 0x8B2C, KANJI_LEVEL4, // 謬 + 0x4FF5, KANJI_LEVEL4, // 俵 + 0x5F6A, KANJI_LEVEL4, // 圪 + 0x6A19, KANJI_LEVEL4, // æš™ + 0x6C37, KANJI_LEVEL4, // æ°· + 0x6F02, KANJI_LEVEL4, // 挂 + 0x74E2, KANJI_LEVEL4, // 瓢 + 0x7968, KANJI_LEVEL4, // 祚 + 0x8868, KANJI_LEVEL4, // 衚 + 0x8A55, KANJI_LEVEL4, // 評 + 0x8C79, KANJI_LEVEL4, // è±¹ + 0x5EDF, KANJI_LEVEL4, // 廟 + 0x63CF, KANJI_LEVEL4, // 描 + 0x75C5, KANJI_LEVEL4, // 病 + 0x79D2, KANJI_LEVEL4, // 秒 + 0x82D7, KANJI_LEVEL4, // 苗 + 0x9328, KANJI_LEVEL4, // 錹 + 0x92F2, KANJI_LEVEL4, // 鋲 + 0x849C, KANJI_LEVEL4, // 蒜 + 0x86ED, KANJI_LEVEL4, // 蛭 + 0x9C2D, KANJI_LEVEL4, // é°­ + 0x54C1, KANJI_LEVEL4, // 品 + 0x5F6C, KANJI_LEVEL4, // 圬 + 0x658C, KANJI_LEVEL4, // 斌 + 0x6D5C, KANJI_LEVEL4, // 浜 + 0x7015, KANJI_LEVEL4, // 瀕 + 0x8CA7, KANJI_LEVEL4, // è²§ + 0x8CD3, KANJI_LEVEL4, // 賓 + 0x983B, KANJI_LEVEL4, // é » + 0x654F, KANJI_LEVEL4, // 敏 + 0x74F6, KANJI_LEVEL4, // 瓶 + 0x4E0D, KANJI_LEVEL4, // 䞍 + 0x4ED8, KANJI_LEVEL4, // 付 + 0x57E0, KANJI_LEVEL4, // 埠 + 0x592B, KANJI_LEVEL4, // 倫 + 0x5A66, KANJI_LEVEL4, // 婊 + 0x5BCC, KANJI_LEVEL4, // 富 + 0x51A8, KANJI_LEVEL4, // 冚 + 0x5E03, KANJI_LEVEL4, // 垃 + 0x5E9C, KANJI_LEVEL4, // 府 + 0x6016, KANJI_LEVEL4, // 怖 + 0x6276, KANJI_LEVEL4, // 扶 + 0x6577, KANJI_LEVEL4, // 敷 + 0x65A7, KANJI_LEVEL4, // 斧 + 0x666E, KANJI_LEVEL4, // 普 + 0x6D6E, KANJI_LEVEL4, // æµ® + 0x7236, KANJI_LEVEL4, // 父 + 0x7B26, KANJI_LEVEL4, // 笊 + 0x8150, KANJI_LEVEL4, // 腐 + 0x819A, KANJI_LEVEL4, // 膚 + 0x8299, KANJI_LEVEL4, // 芙 + 0x8B5C, KANJI_LEVEL4, // 譜 + 0x8CA0, KANJI_LEVEL4, // è²  + 0x8CE6, KANJI_LEVEL4, // 賊 + 0x8D74, KANJI_LEVEL4, // 赎 + 0x961C, KANJI_LEVEL4, // 阜 + 0x9644, KANJI_LEVEL4, // 附 + 0x4FAE, KANJI_LEVEL4, // 䟮 + 0x64AB, KANJI_LEVEL4, // 撫 + 0x6B66, KANJI_LEVEL4, // æ­Š + 0x821E, KANJI_LEVEL4, // 舞 + 0x8461, KANJI_LEVEL4, // 葡 + 0x856A, KANJI_LEVEL4, // 蕪 + 0x90E8, KANJI_LEVEL4, // 郚 + 0x5C01, KANJI_LEVEL4, // 封 + 0x6953, KANJI_LEVEL4, // 楓 + 0x98A8, KANJI_LEVEL4, // 颚 + 0x847A, KANJI_LEVEL4, // 葺 + 0x8557, KANJI_LEVEL4, // 蕗 + 0x4F0F, KANJI_LEVEL4, // 䌏 + 0x526F, KANJI_LEVEL4, // 副 + 0x5FA9, KANJI_LEVEL4, // 埩 + 0x5E45, KANJI_LEVEL4, // 幅 + 0x670D, KANJI_LEVEL4, // 服 + 0x798F, KANJI_LEVEL4, // 犏 + 0x8179, KANJI_LEVEL4, // 腹 + 0x8907, KANJI_LEVEL4, // 耇 + 0x8986, KANJI_LEVEL4, // 芆 + 0x6DF5, KANJI_LEVEL4, // æ·µ + 0x5F17, KANJI_LEVEL4, // 北 + 0x6255, KANJI_LEVEL4, // 払 + 0x6CB8, KANJI_LEVEL4, // 沞 + 0x4ECF, KANJI_LEVEL4, // 仏 + 0x7269, KANJI_LEVEL4, // 物 + 0x9B92, KANJI_LEVEL4, // 鮒 + 0x5206, KANJI_LEVEL4, // 分 + 0x543B, KANJI_LEVEL4, // 吻 + 0x5674, KANJI_LEVEL4, // 噎 + 0x58B3, KANJI_LEVEL4, // 墳 + 0x61A4, KANJI_LEVEL4, // 憀 + 0x626E, KANJI_LEVEL4, // 扮 + 0x711A, KANJI_LEVEL4, // 焚 + 0x596E, KANJI_LEVEL4, // 奮 + 0x7C89, KANJI_LEVEL4, // 粉 + 0x7CDE, KANJI_LEVEL4, // 糞 + 0x7D1B, KANJI_LEVEL4, // 箛 + 0x96F0, KANJI_LEVEL4, // 雰 + 0x6587, KANJI_LEVEL4, // 文 + 0x805E, KANJI_LEVEL4, // 聞 + 0x4E19, KANJI_LEVEL4, // 侙 + 0x4F75, KANJI_LEVEL4, // 䜵 + 0x5175, KANJI_LEVEL4, // 兵 + 0x5840, KANJI_LEVEL4, // 塀 + 0x5E63, KANJI_LEVEL4, // å¹£ + 0x5E73, KANJI_LEVEL4, // å¹³ + 0x5F0A, KANJI_LEVEL4, // 匊 + 0x67C4, KANJI_LEVEL4, // 柄 + 0x4E26, KANJI_LEVEL4, // 䞊 + 0x853D, KANJI_LEVEL4, // 蔜 + 0x9589, KANJI_LEVEL4, // 閉 + 0x965B, KANJI_LEVEL4, // 陛 + 0x7C73, KANJI_LEVEL4, // ç±³ + 0x9801, KANJI_LEVEL4, // 頁 + 0x50FB, KANJI_LEVEL4, // 僻 + 0x58C1, KANJI_LEVEL4, // 壁 + 0x7656, KANJI_LEVEL4, // 癖 + 0x78A7, KANJI_LEVEL4, // 碧 + 0x5225, KANJI_LEVEL4, // 別 + 0x77A5, KANJI_LEVEL4, // 瞥 + 0x8511, KANJI_LEVEL4, // 蔑 + 0x7B86, KANJI_LEVEL4, // 箆 + 0x504F, KANJI_LEVEL4, // 偏 + 0x5909, KANJI_LEVEL4, // 倉 + 0x7247, KANJI_LEVEL4, // 片 + 0x7BC7, KANJI_LEVEL4, // 篇 + 0x7DE8, KANJI_LEVEL4, // ç·š + 0x8FBA, KANJI_LEVEL4, // 蟺 + 0x8FD4, KANJI_LEVEL4, // 返 + 0x904D, KANJI_LEVEL4, // 遍 + 0x4FBF, KANJI_LEVEL4, // 䟿 + 0x52C9, KANJI_LEVEL4, // 勉 + 0x5A29, KANJI_LEVEL4, // åš© + 0x5F01, KANJI_LEVEL4, // 匁 + 0x97AD, KANJI_LEVEL4, // 鞭 + 0x4FDD, KANJI_LEVEL4, // 保 + 0x8217, KANJI_LEVEL4, // 舗 + 0x92EA, KANJI_LEVEL4, // 鋪 + 0x5703, KANJI_LEVEL4, // 圃 + 0x6355, KANJI_LEVEL4, // 捕 + 0x6B69, KANJI_LEVEL4, // æ­© + 0x752B, KANJI_LEVEL4, // 甫 + 0x88DC, KANJI_LEVEL4, // 補 + 0x8F14, KANJI_LEVEL4, // 茔 + 0x7A42, KANJI_LEVEL4, // 穂 + 0x52DF, KANJI_LEVEL4, // 募 + 0x5893, KANJI_LEVEL4, // 墓 + 0x6155, KANJI_LEVEL4, // 慕 + 0x620A, KANJI_LEVEL4, // 戊 + 0x66AE, KANJI_LEVEL4, // 暮 + 0x6BCD, KANJI_LEVEL4, // 母 + 0x7C3F, KANJI_LEVEL4, // ç°¿ + 0x83E9, KANJI_LEVEL4, // 菩 + 0x5023, KANJI_LEVEL4, // 倣 + 0x4FF8, KANJI_LEVEL4, // 俞 + 0x5305, KANJI_LEVEL4, // 包 + 0x5446, KANJI_LEVEL4, // 呆 + 0x5831, KANJI_LEVEL4, // å ± + 0x5949, KANJI_LEVEL4, // 奉 + 0x5B9D, KANJI_LEVEL4, // 宝 + 0x5CF0, KANJI_LEVEL4, // å³° + 0x5CEF, KANJI_LEVEL4, // 峯 + 0x5D29, KANJI_LEVEL4, // 厩 + 0x5E96, KANJI_LEVEL4, // 庖 + 0x62B1, KANJI_LEVEL4, // 抱 + 0x6367, KANJI_LEVEL4, // 捧 + 0x653E, KANJI_LEVEL4, // 攟 + 0x65B9, KANJI_LEVEL4, // 方 + 0x670B, KANJI_LEVEL4, // 朋 + 0x6CD5, KANJI_LEVEL4, // 法 + 0x6CE1, KANJI_LEVEL4, // 泡 + 0x70F9, KANJI_LEVEL4, // 烹 + 0x7832, KANJI_LEVEL4, // ç ² + 0x7E2B, KANJI_LEVEL4, // çž« + 0x80DE, KANJI_LEVEL4, // 胞 + 0x82B3, KANJI_LEVEL4, // 芳 + 0x840C, KANJI_LEVEL4, // 萌 + 0x84EC, KANJI_LEVEL4, // 蓬 + 0x8702, KANJI_LEVEL4, // 蜂 + 0x8912, KANJI_LEVEL4, // 耒 + 0x8A2A, KANJI_LEVEL4, // 蚪 + 0x8C4A, KANJI_LEVEL4, // 豊 + 0x90A6, KANJI_LEVEL4, // 邩 + 0x92D2, KANJI_LEVEL4, // 鋒 + 0x98FD, KANJI_LEVEL4, // 飜 + 0x9CF3, KANJI_LEVEL4, // é³³ + 0x9D6C, KANJI_LEVEL4, // 鵬 + 0x4E4F, KANJI_LEVEL4, // 乏 + 0x4EA1, KANJI_LEVEL4, // 亡 + 0x508D, KANJI_LEVEL4, // 傍 + 0x5256, KANJI_LEVEL4, // 剖 + 0x574A, KANJI_LEVEL4, // 坊 + 0x59A8, KANJI_LEVEL4, // 劚 + 0x5E3D, KANJI_LEVEL4, // åžœ + 0x5FD8, KANJI_LEVEL4, // 忘 + 0x5FD9, KANJI_LEVEL4, // 忙 + 0x623F, KANJI_LEVEL4, // 房 + 0x66B4, KANJI_LEVEL4, // 暎 + 0x671B, KANJI_LEVEL4, // 望 + 0x67D0, KANJI_LEVEL4, // 某 + 0x68D2, KANJI_LEVEL4, // 棒 + 0x5192, KANJI_LEVEL4, // 冒 + 0x7D21, KANJI_LEVEL4, // 玡 + 0x80AA, KANJI_LEVEL4, // 肪 + 0x81A8, KANJI_LEVEL4, // 膚 + 0x8B00, KANJI_LEVEL4, // 謀 + 0x8C8C, KANJI_LEVEL4, // 貌 + 0x8CBF, KANJI_LEVEL4, // 貿 + 0x927E, KANJI_LEVEL4, // 鉟 + 0x9632, KANJI_LEVEL4, // 防 + 0x5420, KANJI_LEVEL4, // 吠 + 0x982C, KANJI_LEVEL4, // é ¬ + 0x5317, KANJI_LEVEL4, // 北 + 0x50D5, KANJI_LEVEL4, // 僕 + 0x535C, KANJI_LEVEL4, // 卜 + 0x58A8, KANJI_LEVEL4, // 墚 + 0x64B2, KANJI_LEVEL4, // 撲 + 0x6734, KANJI_LEVEL4, // 朎 + 0x7267, KANJI_LEVEL4, // 牧 + 0x7766, KANJI_LEVEL4, // 睊 + 0x7A46, KANJI_LEVEL4, // 穆 + 0x91E6, KANJI_LEVEL4, // 釩 + 0x52C3, KANJI_LEVEL4, // 勃 + 0x6CA1, KANJI_LEVEL4, // 没 + 0x6B86, KANJI_LEVEL4, // 殆 + 0x5800, KANJI_LEVEL4, // 堀 + 0x5E4C, KANJI_LEVEL4, // 幌 + 0x5954, KANJI_LEVEL4, // 奔 + 0x672C, KANJI_LEVEL4, // 本 + 0x7FFB, KANJI_LEVEL4, // ç¿» + 0x51E1, KANJI_LEVEL4, // 凡 + 0x76C6, KANJI_LEVEL4, // 盆 + 0x6469, KANJI_LEVEL4, // 摩 + 0x78E8, KANJI_LEVEL4, // 磚 + 0x9B54, KANJI_LEVEL4, // 魔 + 0x9EBB, KANJI_LEVEL4, // 麻 + 0x57CB, KANJI_LEVEL4, // 埋 + 0x59B9, KANJI_LEVEL4, // 効 + 0x6627, KANJI_LEVEL4, // 昧 + 0x679A, KANJI_LEVEL4, // 枚 + 0x6BCE, KANJI_LEVEL4, // 毎 + 0x54E9, KANJI_LEVEL4, // 哩 + 0x69D9, KANJI_LEVEL4, // 槙 + 0x5E55, KANJI_LEVEL4, // 幕 + 0x819C, KANJI_LEVEL4, // 膜 + 0x6795, KANJI_LEVEL4, // 枕 + 0x9BAA, KANJI_LEVEL4, // 鮪 + 0x67FE, KANJI_LEVEL4, // 柟 + 0x9C52, KANJI_LEVEL4, // 鱒 + 0x685D, KANJI_LEVEL4, // 桝 + 0x4EA6, KANJI_LEVEL4, // 亊 + 0x4FE3, KANJI_LEVEL4, // ä¿£ + 0x53C8, KANJI_LEVEL4, // 又 + 0x62B9, KANJI_LEVEL4, // 抹 + 0x672B, KANJI_LEVEL4, // 末 + 0x6CAB, KANJI_LEVEL4, // 沫 + 0x8FC4, KANJI_LEVEL4, // 迄 + 0x4FAD, KANJI_LEVEL4, // 䟭 + 0x7E6D, KANJI_LEVEL4, // ç¹­ + 0x9EBF, KANJI_LEVEL4, // 麿 + 0x4E07, KANJI_LEVEL4, // 侇 + 0x6162, KANJI_LEVEL4, // 慢 + 0x6E80, KANJI_LEVEL4, // 満 + 0x6F2B, KANJI_LEVEL4, // 挫 + 0x8513, KANJI_LEVEL4, // 蔓 + 0x5473, KANJI_LEVEL4, // 味 + 0x672A, KANJI_LEVEL4, // 未 + 0x9B45, KANJI_LEVEL4, // 魅 + 0x5DF3, KANJI_LEVEL4, // å·³ + 0x7B95, KANJI_LEVEL4, // 箕 + 0x5CAC, KANJI_LEVEL4, // 岬 + 0x5BC6, KANJI_LEVEL4, // 密 + 0x871C, KANJI_LEVEL4, // 蜜 + 0x6E4A, KANJI_LEVEL4, // 湊 + 0x84D1, KANJI_LEVEL4, // 蓑 + 0x7A14, KANJI_LEVEL4, // 織 + 0x8108, KANJI_LEVEL4, // 脈 + 0x5999, KANJI_LEVEL4, // 劙 + 0x7C8D, KANJI_LEVEL4, // 粍 + 0x6C11, KANJI_LEVEL4, // 民 + 0x7720, KANJI_LEVEL4, // 眠 + 0x52D9, KANJI_LEVEL4, // 務 + 0x5922, KANJI_LEVEL4, // 倢 + 0x7121, KANJI_LEVEL4, // 無 + 0x725F, KANJI_LEVEL4, // 牟 + 0x77DB, KANJI_LEVEL4, // 矛 + 0x9727, KANJI_LEVEL4, // 霧 + 0x9D61, KANJI_LEVEL4, // 鵡 + 0x690B, KANJI_LEVEL4, // 怋 + 0x5A7F, KANJI_LEVEL4, // å©¿ + 0x5A18, KANJI_LEVEL4, // 嚘 + 0x51A5, KANJI_LEVEL4, // 冥 + 0x540D, KANJI_LEVEL4, // 名 + 0x547D, KANJI_LEVEL4, // 呜 + 0x660E, KANJI_LEVEL4, // 明 + 0x76DF, KANJI_LEVEL4, // 盟 + 0x8FF7, KANJI_LEVEL4, // è¿· + 0x9298, KANJI_LEVEL4, // 銘 + 0x9CF4, KANJI_LEVEL4, // 鳎 + 0x59EA, KANJI_LEVEL4, // 姪 + 0x725D, KANJI_LEVEL4, // 牝 + 0x6EC5, KANJI_LEVEL4, // 滅 + 0x514D, KANJI_LEVEL4, // 免 + 0x68C9, KANJI_LEVEL4, // 棉 + 0x7DBF, KANJI_LEVEL4, // ç¶¿ + 0x7DEC, KANJI_LEVEL4, // ç·¬ + 0x9762, KANJI_LEVEL4, // 面 + 0x9EBA, KANJI_LEVEL4, // 麺 + 0x6478, KANJI_LEVEL4, // 摞 + 0x6A21, KANJI_LEVEL4, // æš¡ + 0x8302, KANJI_LEVEL4, // 茂 + 0x5984, KANJI_LEVEL4, // 劄 + 0x5B5F, KANJI_LEVEL4, // 孟 + 0x6BDB, KANJI_LEVEL4, // 毛 + 0x731B, KANJI_LEVEL4, // 猛 + 0x76F2, KANJI_LEVEL4, // 盲 + 0x7DB2, KANJI_LEVEL4, // ç¶² + 0x8017, KANJI_LEVEL4, // 耗 + 0x8499, KANJI_LEVEL4, // 蒙 + 0x5132, KANJI_LEVEL4, // 儲 + 0x6728, KANJI_LEVEL4, // 朚 + 0x9ED9, KANJI_LEVEL4, // 黙 + 0x76EE, KANJI_LEVEL4, // 目 + 0x6762, KANJI_LEVEL4, // 杢 + 0x52FF, KANJI_LEVEL4, // 勿 + 0x9905, KANJI_LEVEL4, // 逅 + 0x5C24, KANJI_LEVEL4, // å°€ + 0x623B, KANJI_LEVEL4, // 戻 + 0x7C7E, KANJI_LEVEL4, // 籟 + 0x8CB0, KANJI_LEVEL4, // è²° + 0x554F, KANJI_LEVEL4, // 問 + 0x60B6, KANJI_LEVEL4, // 悶 + 0x7D0B, KANJI_LEVEL4, // 箋 + 0x9580, KANJI_LEVEL4, // 門 + 0x5301, KANJI_LEVEL4, // 匁 + 0x4E5F, KANJI_LEVEL4, // 也 + 0x51B6, KANJI_LEVEL4, // 冶 + 0x591C, KANJI_LEVEL4, // 倜 + 0x723A, KANJI_LEVEL4, // 爺 + 0x8036, KANJI_LEVEL4, // 耶 + 0x91CE, KANJI_LEVEL4, // 野 + 0x5F25, KANJI_LEVEL4, // 匥 + 0x77E2, KANJI_LEVEL4, // 矢 + 0x5384, KANJI_LEVEL4, // 厄 + 0x5F79, KANJI_LEVEL4, // 圹 + 0x7D04, KANJI_LEVEL4, // 箄 + 0x85AC, KANJI_LEVEL4, // 薬 + 0x8A33, KANJI_LEVEL4, // èš³ + 0x8E8D, KANJI_LEVEL4, // 躍 + 0x9756, KANJI_LEVEL4, // 靖 + 0x67F3, KANJI_LEVEL4, // 柳 + 0x85AE, KANJI_LEVEL4, // 薮 + 0x9453, KANJI_LEVEL4, // 鑓 + 0x6109, KANJI_LEVEL4, // 愉 + 0x6108, KANJI_LEVEL4, // 愈 + 0x6CB9, KANJI_LEVEL4, // æ²¹ + 0x7652, KANJI_LEVEL4, // 癒 + 0x8AED, KANJI_LEVEL4, // è«­ + 0x8F38, KANJI_LEVEL4, // 茞 + 0x552F, KANJI_LEVEL4, // 唯 + 0x4F51, KANJI_LEVEL4, // 䜑 + 0x512A, KANJI_LEVEL4, // 優 + 0x52C7, KANJI_LEVEL4, // 勇 + 0x53CB, KANJI_LEVEL4, // 友 + 0x5BA5, KANJI_LEVEL4, // 宥 + 0x5E7D, KANJI_LEVEL4, // 幜 + 0x60A0, KANJI_LEVEL4, // 悠 + 0x6182, KANJI_LEVEL4, // 憂 + 0x63D6, KANJI_LEVEL4, // 揖 + 0x6709, KANJI_LEVEL4, // 有 + 0x67DA, KANJI_LEVEL4, // 柚 + 0x6E67, KANJI_LEVEL4, // æ¹§ + 0x6D8C, KANJI_LEVEL4, // 涌 + 0x7336, KANJI_LEVEL4, // 猶 + 0x7337, KANJI_LEVEL4, // 猷 + 0x7531, KANJI_LEVEL4, // 由 + 0x7950, KANJI_LEVEL4, // 祐 + 0x88D5, KANJI_LEVEL4, // 裕 + 0x8A98, KANJI_LEVEL4, // 誘 + 0x904A, KANJI_LEVEL4, // 遊 + 0x9091, KANJI_LEVEL4, // 邑 + 0x90F5, KANJI_LEVEL4, // 郵 + 0x96C4, KANJI_LEVEL4, // 雄 + 0x878D, KANJI_LEVEL4, // 融 + 0x5915, KANJI_LEVEL4, // 倕 + 0x4E88, KANJI_LEVEL4, // 予 + 0x4F59, KANJI_LEVEL4, // 䜙 + 0x4E0E, KANJI_LEVEL4, // 侎 + 0x8A89, KANJI_LEVEL4, // 誉 + 0x8F3F, KANJI_LEVEL4, // 茿 + 0x9810, KANJI_LEVEL4, // 預 + 0x50AD, KANJI_LEVEL4, // 傭 + 0x5E7C, KANJI_LEVEL4, // 幌 + 0x5996, KANJI_LEVEL4, // 劖 + 0x5BB9, KANJI_LEVEL4, // 容 + 0x5EB8, KANJI_LEVEL4, // 庞 + 0x63DA, KANJI_LEVEL4, // 揚 + 0x63FA, KANJI_LEVEL4, // 揺 + 0x64C1, KANJI_LEVEL4, // 擁 + 0x66DC, KANJI_LEVEL4, // 曜 + 0x694A, KANJI_LEVEL4, // 楊 + 0x69D8, KANJI_LEVEL4, // 様 + 0x6D0B, KANJI_LEVEL4, // 掋 + 0x6EB6, KANJI_LEVEL4, // 溶 + 0x7194, KANJI_LEVEL4, // 熔 + 0x7528, KANJI_LEVEL4, // 甹 + 0x7AAF, KANJI_LEVEL4, // 窯 + 0x7F8A, KANJI_LEVEL4, // 矊 + 0x8000, KANJI_LEVEL4, // 耀 + 0x8449, KANJI_LEVEL4, // 葉 + 0x84C9, KANJI_LEVEL4, // 蓉 + 0x8981, KANJI_LEVEL4, // 芁 + 0x8B21, KANJI_LEVEL4, // 謡 + 0x8E0A, KANJI_LEVEL4, // 螊 + 0x9065, KANJI_LEVEL4, // 遥 + 0x967D, KANJI_LEVEL4, // 陜 + 0x990A, KANJI_LEVEL4, // 逊 + 0x617E, KANJI_LEVEL4, // æ…Ÿ + 0x6291, KANJI_LEVEL4, // 抑 + 0x6B32, KANJI_LEVEL4, // 欲 + 0x6C83, KANJI_LEVEL4, // 沃 + 0x6D74, KANJI_LEVEL4, // 济 + 0x7FCC, KANJI_LEVEL4, // 翌 + 0x7FFC, KANJI_LEVEL4, // 翌 + 0x6DC0, KANJI_LEVEL4, // 淀 + 0x7F85, KANJI_LEVEL4, // 矅 + 0x87BA, KANJI_LEVEL4, // 螺 + 0x88F8, KANJI_LEVEL4, // 裞 + 0x6765, KANJI_LEVEL4, // 来 + 0x83B1, KANJI_LEVEL4, // 莱 + 0x983C, KANJI_LEVEL4, // é Œ + 0x96F7, KANJI_LEVEL4, // 雷 + 0x6D1B, KANJI_LEVEL4, // 掛 + 0x7D61, KANJI_LEVEL4, // 絡 + 0x843D, KANJI_LEVEL4, // 萜 + 0x916A, KANJI_LEVEL4, // 酪 + 0x4E71, KANJI_LEVEL4, // ä¹± + 0x5375, KANJI_LEVEL4, // 卵 + 0x5D50, KANJI_LEVEL4, // 嵐 + 0x6B04, KANJI_LEVEL4, // 欄 + 0x6FEB, KANJI_LEVEL4, // æ¿« + 0x85CD, KANJI_LEVEL4, // 藍 + 0x862D, KANJI_LEVEL4, // 蘭 + 0x89A7, KANJI_LEVEL4, // 芧 + 0x5229, KANJI_LEVEL4, // 利 + 0x540F, KANJI_LEVEL4, // 吏 + 0x5C65, KANJI_LEVEL4, // å±¥ + 0x674E, KANJI_LEVEL4, // 李 + 0x68A8, KANJI_LEVEL4, // 梚 + 0x7406, KANJI_LEVEL4, // 理 + 0x7483, KANJI_LEVEL4, // 璃 + 0x75E2, KANJI_LEVEL4, // 痢 + 0x88CF, KANJI_LEVEL4, // 裏 + 0x88E1, KANJI_LEVEL4, // 裡 + 0x91CC, KANJI_LEVEL4, // 里 + 0x96E2, KANJI_LEVEL4, // 離 + 0x9678, KANJI_LEVEL4, // 陾 + 0x5F8B, KANJI_LEVEL4, // 埋 + 0x7387, KANJI_LEVEL4, // 率 + 0x7ACB, KANJI_LEVEL4, // 立 + 0x844E, KANJI_LEVEL4, // 葎 + 0x63A0, KANJI_LEVEL4, // 掠 + 0x7565, KANJI_LEVEL4, // 略 + 0x5289, KANJI_LEVEL4, // 劉 + 0x6D41, KANJI_LEVEL4, // 流 + 0x6E9C, KANJI_LEVEL4, // 溜 + 0x7409, KANJI_LEVEL4, // 琉 + 0x7559, KANJI_LEVEL4, // 留 + 0x786B, KANJI_LEVEL4, // ç¡« + 0x7C92, KANJI_LEVEL4, // 粒 + 0x9686, KANJI_LEVEL4, // 隆 + 0x7ADC, KANJI_LEVEL4, // 竜 + 0x9F8D, KANJI_LEVEL4, // 韍 + 0x4FB6, KANJI_LEVEL4, // 䟶 + 0x616E, KANJI_LEVEL4, // 慮 + 0x65C5, KANJI_LEVEL4, // 旅 + 0x865C, KANJI_LEVEL4, // 虜 + 0x4E86, KANJI_LEVEL4, // 了 + 0x4EAE, KANJI_LEVEL4, // 亮 + 0x50DA, KANJI_LEVEL4, // 僚 + 0x4E21, KANJI_LEVEL4, // äž¡ + 0x51CC, KANJI_LEVEL4, // 凌 + 0x5BEE, KANJI_LEVEL4, // 寮 + 0x6599, KANJI_LEVEL4, // 料 + 0x6881, KANJI_LEVEL4, // 梁 + 0x6DBC, KANJI_LEVEL4, // æ¶Œ + 0x731F, KANJI_LEVEL4, // 猟 + 0x7642, KANJI_LEVEL4, // 療 + 0x77AD, KANJI_LEVEL4, // 瞭 + 0x7A1C, KANJI_LEVEL4, // 繜 + 0x7CE7, KANJI_LEVEL4, // ç³§ + 0x826F, KANJI_LEVEL4, // 良 + 0x8AD2, KANJI_LEVEL4, // 諒 + 0x907C, KANJI_LEVEL4, // 遌 + 0x91CF, KANJI_LEVEL4, // 量 + 0x9675, KANJI_LEVEL4, // 陵 + 0x9818, KANJI_LEVEL4, // 領 + 0x529B, KANJI_LEVEL4, // 力 + 0x7DD1, KANJI_LEVEL4, // 緑 + 0x502B, KANJI_LEVEL4, // 倫 + 0x5398, KANJI_LEVEL4, // 厘 + 0x6797, KANJI_LEVEL4, // 林 + 0x6DCB, KANJI_LEVEL4, // 淋 + 0x71D0, KANJI_LEVEL4, // 燐 + 0x7433, KANJI_LEVEL4, // 琳 + 0x81E8, KANJI_LEVEL4, // 臚 + 0x8F2A, KANJI_LEVEL4, // 茪 + 0x96A3, KANJI_LEVEL4, // 隣 + 0x9C57, KANJI_LEVEL4, // 鱗 + 0x9E9F, KANJI_LEVEL4, // 麟 + 0x7460, KANJI_LEVEL4, // 瑠 + 0x5841, KANJI_LEVEL4, // 塁 + 0x6D99, KANJI_LEVEL4, // 涙 + 0x7D2F, KANJI_LEVEL4, // 环 + 0x985E, KANJI_LEVEL4, // 類 + 0x4EE4, KANJI_LEVEL4, // 什 + 0x4F36, KANJI_LEVEL4, // 䌶 + 0x4F8B, KANJI_LEVEL4, // 䟋 + 0x51B7, KANJI_LEVEL4, // 冷 + 0x52B1, KANJI_LEVEL4, // 励 + 0x5DBA, KANJI_LEVEL4, // 嶺 + 0x601C, KANJI_LEVEL4, // 怜 + 0x73B2, KANJI_LEVEL4, // 玲 + 0x793C, KANJI_LEVEL4, // 瀌 + 0x82D3, KANJI_LEVEL4, // 苓 + 0x9234, KANJI_LEVEL4, // 鈎 + 0x96B7, KANJI_LEVEL4, // 隷 + 0x96F6, KANJI_LEVEL4, // 零 + 0x970A, KANJI_LEVEL4, // 霊 + 0x9E97, KANJI_LEVEL4, // 麗 + 0x9F62, KANJI_LEVEL4, // 霢 + 0x66A6, KANJI_LEVEL4, // 暊 + 0x6B74, KANJI_LEVEL4, // æ­Ž + 0x5217, KANJI_LEVEL4, // 列 + 0x52A3, KANJI_LEVEL4, // 劣 + 0x70C8, KANJI_LEVEL4, // 烈 + 0x88C2, KANJI_LEVEL4, // 裂 + 0x5EC9, KANJI_LEVEL4, // 廉 + 0x604B, KANJI_LEVEL4, // 恋 + 0x6190, KANJI_LEVEL4, // 憐 + 0x6F23, KANJI_LEVEL4, // 挣 + 0x7149, KANJI_LEVEL4, // 煉 + 0x7C3E, KANJI_LEVEL4, // ç°Ÿ + 0x7DF4, KANJI_LEVEL4, // ç·Ž + 0x806F, KANJI_LEVEL4, // 聯 + 0x84EE, KANJI_LEVEL4, // 蓮 + 0x9023, KANJI_LEVEL4, // 連 + 0x932C, KANJI_LEVEL4, // 錬 + 0x5442, KANJI_LEVEL4, // 呂 + 0x9B6F, KANJI_LEVEL4, // é­¯ + 0x6AD3, KANJI_LEVEL4, // 櫓 + 0x7089, KANJI_LEVEL4, // 炉 + 0x8CC2, KANJI_LEVEL4, // 賂 + 0x8DEF, KANJI_LEVEL4, // è·¯ + 0x9732, KANJI_LEVEL4, // 露 + 0x52B4, KANJI_LEVEL4, // 劎 + 0x5A41, KANJI_LEVEL4, // 婁 + 0x5ECA, KANJI_LEVEL4, // 廊 + 0x5F04, KANJI_LEVEL4, // 匄 + 0x6717, KANJI_LEVEL4, // 朗 + 0x697C, KANJI_LEVEL4, // 楌 + 0x6994, KANJI_LEVEL4, // 抔 + 0x6D6A, KANJI_LEVEL4, // 浪 + 0x6F0F, KANJI_LEVEL4, // 挏 + 0x7262, KANJI_LEVEL4, // 牢 + 0x72FC, KANJI_LEVEL4, // 狌 + 0x7BED, KANJI_LEVEL4, // 篭 + 0x8001, KANJI_LEVEL4, // 老 + 0x807E, KANJI_LEVEL4, // 聟 + 0x874B, KANJI_LEVEL4, // 蝋 + 0x90CE, KANJI_LEVEL4, // 郎 + 0x516D, KANJI_LEVEL4, // 六 + 0x9E93, KANJI_LEVEL4, // 麓 + 0x7984, KANJI_LEVEL4, // 穄 + 0x808B, KANJI_LEVEL4, // 肋 + 0x9332, KANJI_LEVEL4, // 録 + 0x8AD6, KANJI_LEVEL4, // 論 + 0x502D, KANJI_LEVEL4, // 倭 + 0x548C, KANJI_LEVEL4, // 和 + 0x8A71, KANJI_LEVEL4, // 話 + 0x6B6A, KANJI_LEVEL4, // æ­ª + 0x8CC4, KANJI_LEVEL4, // 賄 + 0x8107, KANJI_LEVEL4, // 脇 + 0x60D1, KANJI_LEVEL4, // 惑 + 0x67A0, KANJI_LEVEL4, // 枠 + 0x9DF2, KANJI_LEVEL4, // é·² + 0x4E99, KANJI_LEVEL4, // 亙 + 0x4E98, KANJI_LEVEL4, // 亘 + 0x9C10, KANJI_LEVEL4, // 鰐 + 0x8A6B, KANJI_LEVEL4, // è©« + 0x85C1, KANJI_LEVEL4, // 藁 + 0x8568, KANJI_LEVEL4, // 蕚 + 0x6900, KANJI_LEVEL4, // 怀 + 0x6E7E, KANJI_LEVEL4, // 湟 + 0x7897, KANJI_LEVEL4, // 碗 + 0x8155, KANJI_LEVEL4, // 腕 + 0xD842, KANJI_LEVEL4, // ᅵ + 0xDF9F, KANJI_LEVEL4, // ᅵ + 0x5B41, KANJI_LEVEL4, // 孁 + 0x5B56, KANJI_LEVEL4, // 孖 + 0x5B7D, KANJI_LEVEL4, // å­œ + 0x5B93, KANJI_LEVEL4, // 宓 + 0x5BD8, KANJI_LEVEL4, // 寘 + 0x5BEC, KANJI_LEVEL4, // 寬 + 0x5C12, KANJI_LEVEL4, // 尒 + 0x5C1E, KANJI_LEVEL4, // 尞 + 0x5C23, KANJI_LEVEL4, // å°£ + 0x5C2B, KANJI_LEVEL4, // å°« + 0x378D, KANJI_LEVEL4, // 㞍 + 0x5C62, KANJI_LEVEL4, // å±¢ + 0xFA3B, KANJI_LEVEL4, // ïš» + 0xFA3C, KANJI_LEVEL4, //  + 0xD845, KANJI_LEVEL4, // ᅵ + 0xDEB4, KANJI_LEVEL4, // ᅵ + 0x5C7A, KANJI_LEVEL4, // 屺 + 0x5C8F, KANJI_LEVEL4, // 岏 + 0x5C9F, KANJI_LEVEL4, // 岟 + 0x5CA3, KANJI_LEVEL4, // å²£ + 0x5CAA, KANJI_LEVEL4, // 岪 + 0x5CBA, KANJI_LEVEL4, // 岺 + 0x5CCB, KANJI_LEVEL4, // 峋 + 0x5CD0, KANJI_LEVEL4, // 峐 + 0x5CD2, KANJI_LEVEL4, // 峒 + 0x5CF4, KANJI_LEVEL4, // 峎 + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDE34, KANJI_LEVEL4, // ᅵ + 0x37E2, KANJI_LEVEL4, // 㟢 + 0x5D0D, KANJI_LEVEL4, // 厍 + 0x5D27, KANJI_LEVEL4, // 厧 + 0xFA11, KANJI_LEVEL4, // ïš‘ + 0x5D46, KANJI_LEVEL4, // 嵆 + 0x5D47, KANJI_LEVEL4, // 嵇 + 0x5D53, KANJI_LEVEL4, // 嵓 + 0x5D4A, KANJI_LEVEL4, // 嵊 + 0x5D6D, KANJI_LEVEL4, // åµ­ + 0x5D81, KANJI_LEVEL4, // 嶁 + 0x5DA0, KANJI_LEVEL4, // å¶  + 0x5DA4, KANJI_LEVEL4, // å¶€ + 0x5DA7, KANJI_LEVEL4, // å¶§ + 0x5DB8, KANJI_LEVEL4, // å¶ž + 0x5DCB, KANJI_LEVEL4, // 巋 + 0x541E, KANJI_LEVEL4, // 吞 + 0x5F0C, KANJI_LEVEL4, // 匌 + 0x4E10, KANJI_LEVEL4, // 䞐 + 0x4E15, KANJI_LEVEL4, // 侕 + 0x4E2A, KANJI_LEVEL4, // 䞪 + 0x4E31, KANJI_LEVEL4, // äž± + 0x4E36, KANJI_LEVEL4, // äž¶ + 0x4E3C, KANJI_LEVEL4, // 䞌 + 0x4E3F, KANJI_LEVEL4, // äž¿ + 0x4E42, KANJI_LEVEL4, // 乂 + 0x4E56, KANJI_LEVEL4, // 乖 + 0x4E58, KANJI_LEVEL4, // 乘 + 0x4E82, KANJI_LEVEL4, // 亂 + 0x4E85, KANJI_LEVEL4, // 亅 + 0x8C6B, KANJI_LEVEL4, // 豫 + 0x4E8A, KANJI_LEVEL4, // 亊 + 0x8212, KANJI_LEVEL4, // 舒 + 0x5F0D, KANJI_LEVEL4, // 匍 + 0x4E8E, KANJI_LEVEL4, // 于 + 0x4E9E, KANJI_LEVEL4, // 亞 + 0x4E9F, KANJI_LEVEL4, // 亟 + 0x4EA0, KANJI_LEVEL4, // 亠 + 0x4EA2, KANJI_LEVEL4, // 亢 + 0x4EB0, KANJI_LEVEL4, // 亰 + 0x4EB3, KANJI_LEVEL4, // 亳 + 0x4EB6, KANJI_LEVEL4, // 亶 + 0x4ECE, KANJI_LEVEL4, // 从 + 0x4ECD, KANJI_LEVEL4, // 仍 + 0x4EC4, KANJI_LEVEL4, // 仄 + 0x4EC6, KANJI_LEVEL4, // 仆 + 0x4EC2, KANJI_LEVEL4, // 仂 + 0x4ED7, KANJI_LEVEL4, // 仗 + 0x4EDE, KANJI_LEVEL4, // 仞 + 0x4EED, KANJI_LEVEL4, // ä»­ + 0x4EDF, KANJI_LEVEL4, // 仟 + 0x4EF7, KANJI_LEVEL4, // ä»· + 0x4F09, KANJI_LEVEL4, // 䌉 + 0x4F5A, KANJI_LEVEL4, // 䜚 + 0x4F30, KANJI_LEVEL4, // 䌰 + 0x4F5B, KANJI_LEVEL4, // 䜛 + 0x4F5D, KANJI_LEVEL4, // 䜝 + 0x4F57, KANJI_LEVEL4, // 䜗 + 0x4F47, KANJI_LEVEL4, // 䜇 + 0x4F76, KANJI_LEVEL4, // 䜶 + 0x4F88, KANJI_LEVEL4, // 䟈 + 0x4F8F, KANJI_LEVEL4, // 䟏 + 0x4F98, KANJI_LEVEL4, // 䟘 + 0x4F7B, KANJI_LEVEL4, // 䜻 + 0x4F69, KANJI_LEVEL4, // 䜩 + 0x4F70, KANJI_LEVEL4, // 䜰 + 0x4F91, KANJI_LEVEL4, // 䟑 + 0x4F6F, KANJI_LEVEL4, // 䜯 + 0x4F86, KANJI_LEVEL4, // 䟆 + 0x4F96, KANJI_LEVEL4, // 䟖 + 0x5118, KANJI_LEVEL4, // 儘 + 0x4FD4, KANJI_LEVEL4, // 俔 + 0x4FDF, KANJI_LEVEL4, // 俟 + 0x4FCE, KANJI_LEVEL4, // 俎 + 0x4FD8, KANJI_LEVEL4, // 俘 + 0x4FDB, KANJI_LEVEL4, // 俛 + 0x4FD1, KANJI_LEVEL4, // 俑 + 0x4FDA, KANJI_LEVEL4, // 俚 + 0x4FD0, KANJI_LEVEL4, // 俐 + 0x4FE4, KANJI_LEVEL4, // ä¿€ + 0x4FE5, KANJI_LEVEL4, // ä¿¥ + 0x501A, KANJI_LEVEL4, // 倚 + 0x5028, KANJI_LEVEL4, // 倚 + 0x5014, KANJI_LEVEL4, // 倔 + 0x502A, KANJI_LEVEL4, // 倪 + 0x5025, KANJI_LEVEL4, // 倥 + 0x5005, KANJI_LEVEL4, // 倅 + 0x4F1C, KANJI_LEVEL4, // 䌜 + 0x4FF6, KANJI_LEVEL4, // ä¿¶ + 0x5021, KANJI_LEVEL4, // 倡 + 0x5029, KANJI_LEVEL4, // 倩 + 0x502C, KANJI_LEVEL4, // 倬 + 0x4FFE, KANJI_LEVEL4, // 俟 + 0x4FEF, KANJI_LEVEL4, // 俯 + 0x5011, KANJI_LEVEL4, // 們 + 0x5006, KANJI_LEVEL4, // 倆 + 0x5043, KANJI_LEVEL4, // 偃 + 0x5047, KANJI_LEVEL4, // 假 + 0x6703, KANJI_LEVEL4, // 會 + 0x5055, KANJI_LEVEL4, // 偕 + 0x5050, KANJI_LEVEL4, // 偐 + 0x5048, KANJI_LEVEL4, // 偈 + 0x505A, KANJI_LEVEL4, // 做 + 0x5056, KANJI_LEVEL4, // 偖 + 0x506C, KANJI_LEVEL4, // 偬 + 0x5078, KANJI_LEVEL4, // 偞 + 0x5080, KANJI_LEVEL4, // 傀 + 0x509A, KANJI_LEVEL4, // 傚 + 0x5085, KANJI_LEVEL4, // 傅 + 0x50B4, KANJI_LEVEL4, // 傎 + 0x50B2, KANJI_LEVEL4, // 傲 + 0x50C9, KANJI_LEVEL4, // 僉 + 0x50CA, KANJI_LEVEL4, // 僊 + 0x50B3, KANJI_LEVEL4, // 傳 + 0x50C2, KANJI_LEVEL4, // 僂 + 0x50D6, KANJI_LEVEL4, // 僖 + 0x50DE, KANJI_LEVEL4, // 僞 + 0x50E5, KANJI_LEVEL4, // 僥 + 0x50ED, KANJI_LEVEL4, // 僭 + 0x50E3, KANJI_LEVEL4, // 僣 + 0x50EE, KANJI_LEVEL4, // 僮 + 0x50F9, KANJI_LEVEL4, // 價 + 0x50F5, KANJI_LEVEL4, // 僵 + 0x5109, KANJI_LEVEL4, // 儉 + 0x5101, KANJI_LEVEL4, // 儁 + 0x5102, KANJI_LEVEL4, // 儂 + 0x5116, KANJI_LEVEL4, // 儖 + 0x5115, KANJI_LEVEL4, // 儕 + 0x5114, KANJI_LEVEL4, // 儔 + 0x511A, KANJI_LEVEL4, // 儚 + 0x5121, KANJI_LEVEL4, // 儡 + 0x513A, KANJI_LEVEL4, // 儺 + 0x5137, KANJI_LEVEL4, // 儷 + 0x513C, KANJI_LEVEL4, // 儌 + 0x513B, KANJI_LEVEL4, // 儻 + 0x513F, KANJI_LEVEL4, // 儿 + 0x5140, KANJI_LEVEL4, // 兀 + 0x5152, KANJI_LEVEL4, // 兒 + 0x514C, KANJI_LEVEL4, // 兌 + 0x5154, KANJI_LEVEL4, // 兔 + 0x5162, KANJI_LEVEL4, // 兢 + 0x7AF8, KANJI_LEVEL4, // 竞 + 0x5169, KANJI_LEVEL4, // 兩 + 0x516A, KANJI_LEVEL4, // 兪 + 0x516E, KANJI_LEVEL4, // 兮 + 0x5180, KANJI_LEVEL4, // 冀 + 0x5182, KANJI_LEVEL4, // 冂 + 0x56D8, KANJI_LEVEL4, // 囘 + 0x518C, KANJI_LEVEL4, // 册 + 0x5189, KANJI_LEVEL4, // 冉 + 0x518F, KANJI_LEVEL4, // 冏 + 0x5191, KANJI_LEVEL4, // 冑 + 0x5193, KANJI_LEVEL4, // 冓 + 0x5195, KANJI_LEVEL4, // 冕 + 0x5196, KANJI_LEVEL4, // 冖 + 0x51A4, KANJI_LEVEL4, // 冀 + 0x51A6, KANJI_LEVEL4, // 冊 + 0x51A2, KANJI_LEVEL4, // 冢 + 0x51A9, KANJI_LEVEL4, // 冩 + 0x51AA, KANJI_LEVEL4, // 冪 + 0x51AB, KANJI_LEVEL4, // 冫 + 0x51B3, KANJI_LEVEL4, // 决 + 0x51B1, KANJI_LEVEL4, // 冱 + 0x51B2, KANJI_LEVEL4, // 冲 + 0x51B0, KANJI_LEVEL4, // 冰 + 0x51B5, KANJI_LEVEL4, // 况 + 0x51BD, KANJI_LEVEL4, // 农 + 0x51C5, KANJI_LEVEL4, // 凅 + 0x51C9, KANJI_LEVEL4, // 凉 + 0x51DB, KANJI_LEVEL4, // 凛 + 0x51E0, KANJI_LEVEL4, // 几 + 0x8655, KANJI_LEVEL4, // 處 + 0x51E9, KANJI_LEVEL4, // 凩 + 0x51ED, KANJI_LEVEL4, // 凭 + 0x51F0, KANJI_LEVEL4, // 凰 + 0x51F5, KANJI_LEVEL4, // 凵 + 0x51FE, KANJI_LEVEL4, // 凟 + 0x5204, KANJI_LEVEL4, // 刄 + 0x520B, KANJI_LEVEL4, // 刋 + 0x5214, KANJI_LEVEL4, // 刔 + 0x520E, KANJI_LEVEL4, // 刎 + 0x5227, KANJI_LEVEL4, // 刧 + 0x522A, KANJI_LEVEL4, // 刪 + 0x522E, KANJI_LEVEL4, // 刮 + 0x5233, KANJI_LEVEL4, // 刳 + 0x5239, KANJI_LEVEL4, // 刹 + 0x524F, KANJI_LEVEL4, // 剏 + 0x5244, KANJI_LEVEL4, // 剄 + 0x524B, KANJI_LEVEL4, // 剋 + 0x524C, KANJI_LEVEL4, // 剌 + 0x525E, KANJI_LEVEL4, // 剞 + 0x5254, KANJI_LEVEL4, // 剔 + 0x526A, KANJI_LEVEL4, // 剪 + 0x5274, KANJI_LEVEL4, // 剎 + 0x5269, KANJI_LEVEL4, // 剩 + 0x5273, KANJI_LEVEL4, // 剳 + 0x527F, KANJI_LEVEL4, // 剿 + 0x527D, KANJI_LEVEL4, // 剜 + 0x528D, KANJI_LEVEL4, // 劍 + 0x5294, KANJI_LEVEL4, // 劔 + 0x5292, KANJI_LEVEL4, // 劒 + 0x5271, KANJI_LEVEL4, // 剱 + 0x5288, KANJI_LEVEL4, // 劈 + 0x5291, KANJI_LEVEL4, // 劑 + 0x8FA8, KANJI_LEVEL4, // 蟚 + 0x8FA7, KANJI_LEVEL4, // 蟧 + 0x52AC, KANJI_LEVEL4, // 劬 + 0x52AD, KANJI_LEVEL4, // 劭 + 0x52BC, KANJI_LEVEL4, // 劌 + 0x52B5, KANJI_LEVEL4, // 劵 + 0x52C1, KANJI_LEVEL4, // 勁 + 0x52CD, KANJI_LEVEL4, // 勍 + 0x52D7, KANJI_LEVEL4, // 勗 + 0x52DE, KANJI_LEVEL4, // 勞 + 0x52E3, KANJI_LEVEL4, // 勣 + 0x52E6, KANJI_LEVEL4, // 勊 + 0x98ED, KANJI_LEVEL4, // 飭 + 0x52E0, KANJI_LEVEL4, // 勠 + 0x52F3, KANJI_LEVEL4, // 勳 + 0x52F5, KANJI_LEVEL4, // 勵 + 0x52F8, KANJI_LEVEL4, // 勞 + 0x52F9, KANJI_LEVEL4, // 勹 + 0x5306, KANJI_LEVEL4, // 匆 + 0x5308, KANJI_LEVEL4, // 匈 + 0x7538, KANJI_LEVEL4, // 甾 + 0x530D, KANJI_LEVEL4, // 匍 + 0x5310, KANJI_LEVEL4, // 匐 + 0x530F, KANJI_LEVEL4, // 匏 + 0x5315, KANJI_LEVEL4, // 匕 + 0x531A, KANJI_LEVEL4, // 匚 + 0x5323, KANJI_LEVEL4, // 匣 + 0x532F, KANJI_LEVEL4, // 匯 + 0x5331, KANJI_LEVEL4, // 匱 + 0x5333, KANJI_LEVEL4, // 匳 + 0x5338, KANJI_LEVEL4, // 匞 + 0x5340, KANJI_LEVEL4, // 區 + 0x5346, KANJI_LEVEL4, // 卆 + 0x5345, KANJI_LEVEL4, // 卅 + 0x4E17, KANJI_LEVEL4, // 侗 + 0x5349, KANJI_LEVEL4, // 卉 + 0x534D, KANJI_LEVEL4, // 卍 + 0x51D6, KANJI_LEVEL4, // 凖 + 0x535E, KANJI_LEVEL4, // 卞 + 0x5369, KANJI_LEVEL4, // 卩 + 0x536E, KANJI_LEVEL4, // 卮 + 0x5918, KANJI_LEVEL4, // 倘 + 0x537B, KANJI_LEVEL4, // 卻 + 0x5377, KANJI_LEVEL4, // 卷 + 0x5382, KANJI_LEVEL4, // 厂 + 0x5396, KANJI_LEVEL4, // 厖 + 0x53A0, KANJI_LEVEL4, // 厠 + 0x53A6, KANJI_LEVEL4, // 厊 + 0x53A5, KANJI_LEVEL4, // 厥 + 0x53AE, KANJI_LEVEL4, // 厮 + 0x53B0, KANJI_LEVEL4, // 厰 + 0x53B6, KANJI_LEVEL4, // 厶 + 0x53C3, KANJI_LEVEL4, // 參 + 0x7C12, KANJI_LEVEL4, // 簒 + 0x96D9, KANJI_LEVEL4, // 雙 + 0x53DF, KANJI_LEVEL4, // 叟 + 0x66FC, KANJI_LEVEL4, // 曌 + 0x71EE, KANJI_LEVEL4, // 燮 + 0x53EE, KANJI_LEVEL4, // 叮 + 0x53E8, KANJI_LEVEL4, // 叚 + 0x53ED, KANJI_LEVEL4, // 叭 + 0x53FA, KANJI_LEVEL4, // 叺 + 0x5401, KANJI_LEVEL4, // 吁 + 0x543D, KANJI_LEVEL4, // 吜 + 0x5440, KANJI_LEVEL4, // 呀 + 0x542C, KANJI_LEVEL4, // 听 + 0x542D, KANJI_LEVEL4, // 吭 + 0x543C, KANJI_LEVEL4, // 同 + 0x542E, KANJI_LEVEL4, // 吮 + 0x5436, KANJI_LEVEL4, // 吶 + 0x5429, KANJI_LEVEL4, // 吩 + 0x541D, KANJI_LEVEL4, // 吝 + 0x544E, KANJI_LEVEL4, // 呎 + 0x548F, KANJI_LEVEL4, // 咏 + 0x5475, KANJI_LEVEL4, // 呵 + 0x548E, KANJI_LEVEL4, // 咎 + 0x545F, KANJI_LEVEL4, // 呟 + 0x5471, KANJI_LEVEL4, // 呱 + 0x5477, KANJI_LEVEL4, // 呷 + 0x5470, KANJI_LEVEL4, // 呰 + 0x5492, KANJI_LEVEL4, // 咒 + 0x547B, KANJI_LEVEL4, // 呻 + 0x5480, KANJI_LEVEL4, // 咀 + 0x5476, KANJI_LEVEL4, // 呶 + 0x5484, KANJI_LEVEL4, // 咄 + 0x5490, KANJI_LEVEL4, // 咐 + 0x5486, KANJI_LEVEL4, // 咆 + 0x54C7, KANJI_LEVEL4, // 哇 + 0x54A2, KANJI_LEVEL4, // 咢 + 0x54B8, KANJI_LEVEL4, // å’ž + 0x54A5, KANJI_LEVEL4, // 咥 + 0x54AC, KANJI_LEVEL4, // 咬 + 0x54C4, KANJI_LEVEL4, // 哄 + 0x54C8, KANJI_LEVEL4, // 哈 + 0x54A8, KANJI_LEVEL4, // å’š + 0x54AB, KANJI_LEVEL4, // 咫 + 0x54C2, KANJI_LEVEL4, // 哂 + 0x54A4, KANJI_LEVEL4, // å’€ + 0x54BE, KANJI_LEVEL4, // å’Ÿ + 0x54BC, KANJI_LEVEL4, // å’Œ + 0x54D8, KANJI_LEVEL4, // 哘 + 0x54E5, KANJI_LEVEL4, // 哥 + 0x54E6, KANJI_LEVEL4, // 哊 + 0x550F, KANJI_LEVEL4, // 唏 + 0x5514, KANJI_LEVEL4, // 唔 + 0x54FD, KANJI_LEVEL4, // 哜 + 0x54EE, KANJI_LEVEL4, // 哮 + 0x54ED, KANJI_LEVEL4, // 哭 + 0x54FA, KANJI_LEVEL4, // 哺 + 0x54E2, KANJI_LEVEL4, // 哢 + 0x5539, KANJI_LEVEL4, // 唹 + 0x5540, KANJI_LEVEL4, // 啀 + 0x5563, KANJI_LEVEL4, // 啣 + 0x554C, KANJI_LEVEL4, // 啌 + 0x552E, KANJI_LEVEL4, // 售 + 0x555C, KANJI_LEVEL4, // 啜 + 0x5545, KANJI_LEVEL4, // 啅 + 0x5556, KANJI_LEVEL4, // 啖 + 0x5557, KANJI_LEVEL4, // 啗 + 0x5538, KANJI_LEVEL4, // 唞 + 0x5533, KANJI_LEVEL4, // 唳 + 0x555D, KANJI_LEVEL4, // 啝 + 0x5599, KANJI_LEVEL4, // 喙 + 0x5580, KANJI_LEVEL4, // 喀 + 0x54AF, KANJI_LEVEL4, // 咯 + 0x558A, KANJI_LEVEL4, // 喊 + 0x559F, KANJI_LEVEL4, // 喟 + 0x557B, KANJI_LEVEL4, // 啻 + 0x557E, KANJI_LEVEL4, // 啟 + 0x5598, KANJI_LEVEL4, // 喘 + 0x559E, KANJI_LEVEL4, // 喞 + 0x55AE, KANJI_LEVEL4, // 單 + 0x557C, KANJI_LEVEL4, // 啌 + 0x5583, KANJI_LEVEL4, // 喃 + 0x55A9, KANJI_LEVEL4, // 喩 + 0x5587, KANJI_LEVEL4, // 喇 + 0x55A8, KANJI_LEVEL4, // å–š + 0x55DA, KANJI_LEVEL4, // 嗚 + 0x55C5, KANJI_LEVEL4, // 嗅 + 0x55DF, KANJI_LEVEL4, // 嗟 + 0x55C4, KANJI_LEVEL4, // 嗄 + 0x55DC, KANJI_LEVEL4, // 嗜 + 0x55E4, KANJI_LEVEL4, // å—€ + 0x55D4, KANJI_LEVEL4, // 嗔 + 0x5614, KANJI_LEVEL4, // 嘔 + 0x55F7, KANJI_LEVEL4, // 嗷 + 0x5616, KANJI_LEVEL4, // 嘖 + 0x55FE, KANJI_LEVEL4, // å—Ÿ + 0x55FD, KANJI_LEVEL4, // å—œ + 0x561B, KANJI_LEVEL4, // 嘛 + 0x55F9, KANJI_LEVEL4, // 嗹 + 0x564E, KANJI_LEVEL4, // 噎 + 0x5650, KANJI_LEVEL4, // 噐 + 0x71DF, KANJI_LEVEL4, // 營 + 0x5634, KANJI_LEVEL4, // 嘎 + 0x5636, KANJI_LEVEL4, // 嘶 + 0x5632, KANJI_LEVEL4, // 嘲 + 0x5638, KANJI_LEVEL4, // 嘞 + 0x566B, KANJI_LEVEL4, // 噫 + 0x5664, KANJI_LEVEL4, // 噀 + 0x562F, KANJI_LEVEL4, // 嘯 + 0x566C, KANJI_LEVEL4, // 噬 + 0x566A, KANJI_LEVEL4, // 噪 + 0x5686, KANJI_LEVEL4, // 嚆 + 0x5680, KANJI_LEVEL4, // 嚀 + 0x568A, KANJI_LEVEL4, // 嚊 + 0x56A0, KANJI_LEVEL4, // 嚠 + 0x5694, KANJI_LEVEL4, // 嚔 + 0x568F, KANJI_LEVEL4, // 嚏 + 0x56A5, KANJI_LEVEL4, // 嚥 + 0x56AE, KANJI_LEVEL4, // 嚮 + 0x56B6, KANJI_LEVEL4, // 嚶 + 0x56B4, KANJI_LEVEL4, // 嚎 + 0x56C2, KANJI_LEVEL4, // 囂 + 0x56BC, KANJI_LEVEL4, // 嚌 + 0x56C1, KANJI_LEVEL4, // 囁 + 0x56C3, KANJI_LEVEL4, // 囃 + 0x56C0, KANJI_LEVEL4, // 囀 + 0x56C8, KANJI_LEVEL4, // 囈 + 0x56CE, KANJI_LEVEL4, // 囎 + 0x56D1, KANJI_LEVEL4, // 囑 + 0x56D3, KANJI_LEVEL4, // 囓 + 0x56D7, KANJI_LEVEL4, // 囗 + 0x56EE, KANJI_LEVEL4, // 囮 + 0x56F9, KANJI_LEVEL4, // 囹 + 0x5700, KANJI_LEVEL4, // 圀 + 0x56FF, KANJI_LEVEL4, // 囿 + 0x5704, KANJI_LEVEL4, // 圄 + 0x5709, KANJI_LEVEL4, // 圉 + 0x5708, KANJI_LEVEL4, // 圈 + 0x570B, KANJI_LEVEL4, // 國 + 0x570D, KANJI_LEVEL4, // 圍 + 0x5713, KANJI_LEVEL4, // 圓 + 0x5718, KANJI_LEVEL4, // 團 + 0x5716, KANJI_LEVEL4, // 圖 + 0x55C7, KANJI_LEVEL4, // 嗇 + 0x571C, KANJI_LEVEL4, // 圜 + 0x5726, KANJI_LEVEL4, // 圊 + 0x5737, KANJI_LEVEL4, // 圷 + 0x5738, KANJI_LEVEL4, // 圞 + 0x574E, KANJI_LEVEL4, // 坎 + 0x573B, KANJI_LEVEL4, // 圻 + 0x5740, KANJI_LEVEL4, // 址 + 0x574F, KANJI_LEVEL4, // 坏 + 0x5769, KANJI_LEVEL4, // 坩 + 0x57C0, KANJI_LEVEL4, // 埀 + 0x5788, KANJI_LEVEL4, // 垈 + 0x5761, KANJI_LEVEL4, // 坡 + 0x577F, KANJI_LEVEL4, // 坿 + 0x5789, KANJI_LEVEL4, // 垉 + 0x5793, KANJI_LEVEL4, // 垓 + 0x57A0, KANJI_LEVEL4, // 垠 + 0x57B3, KANJI_LEVEL4, // 垳 + 0x57A4, KANJI_LEVEL4, // 垀 + 0x57AA, KANJI_LEVEL4, // 垪 + 0x57B0, KANJI_LEVEL4, // 垰 + 0x57C3, KANJI_LEVEL4, // 埃 + 0x57C6, KANJI_LEVEL4, // 埆 + 0x57D4, KANJI_LEVEL4, // 埔 + 0x57D2, KANJI_LEVEL4, // 埒 + 0x57D3, KANJI_LEVEL4, // 埓 + 0x580A, KANJI_LEVEL4, // 堊 + 0x57D6, KANJI_LEVEL4, // 埖 + 0x57E3, KANJI_LEVEL4, // 埣 + 0x580B, KANJI_LEVEL4, // 堋 + 0x5819, KANJI_LEVEL4, // 堙 + 0x581D, KANJI_LEVEL4, // 堝 + 0x5872, KANJI_LEVEL4, // 塲 + 0x5821, KANJI_LEVEL4, // å ¡ + 0x5862, KANJI_LEVEL4, // å¡¢ + 0x584B, KANJI_LEVEL4, // 塋 + 0x5870, KANJI_LEVEL4, // å¡° + 0x6BC0, KANJI_LEVEL4, // 毀 + 0x5852, KANJI_LEVEL4, // 塒 + 0x583D, KANJI_LEVEL4, // å œ + 0x5879, KANJI_LEVEL4, // 塹 + 0x5885, KANJI_LEVEL4, // 墅 + 0x58B9, KANJI_LEVEL4, // 墹 + 0x589F, KANJI_LEVEL4, // 墟 + 0x58AB, KANJI_LEVEL4, // 墫 + 0x58BA, KANJI_LEVEL4, // 墺 + 0x58DE, KANJI_LEVEL4, // 壞 + 0x58BB, KANJI_LEVEL4, // 墻 + 0x58B8, KANJI_LEVEL4, // 增 + 0x58AE, KANJI_LEVEL4, // 墮 + 0x58C5, KANJI_LEVEL4, // 壅 + 0x58D3, KANJI_LEVEL4, // 壓 + 0x58D1, KANJI_LEVEL4, // 壑 + 0x58D7, KANJI_LEVEL4, // 壗 + 0x58D9, KANJI_LEVEL4, // 壙 + 0x58D8, KANJI_LEVEL4, // 壘 + 0x58E5, KANJI_LEVEL4, // 壥 + 0x58DC, KANJI_LEVEL4, // 壜 + 0x58E4, KANJI_LEVEL4, // 壀 + 0x58DF, KANJI_LEVEL4, // 壟 + 0x58EF, KANJI_LEVEL4, // 壯 + 0x58FA, KANJI_LEVEL4, // 壺 + 0x58F9, KANJI_LEVEL4, // 壹 + 0x58FB, KANJI_LEVEL4, // 壻 + 0x58FC, KANJI_LEVEL4, // 壌 + 0x58FD, KANJI_LEVEL4, // 壜 + 0x5902, KANJI_LEVEL4, // 倂 + 0x590A, KANJI_LEVEL4, // 倊 + 0x5910, KANJI_LEVEL4, // 倐 + 0x591B, KANJI_LEVEL4, // 倛 + 0x68A6, KANJI_LEVEL4, // 梊 + 0x5925, KANJI_LEVEL4, // 倥 + 0x592C, KANJI_LEVEL4, // 倬 + 0x592D, KANJI_LEVEL4, // 倭 + 0x5932, KANJI_LEVEL4, // 倲 + 0x5938, KANJI_LEVEL4, // 倞 + 0x593E, KANJI_LEVEL4, // 借 + 0x7AD2, KANJI_LEVEL4, // 竒 + 0x5955, KANJI_LEVEL4, // 奕 + 0x5950, KANJI_LEVEL4, // 奐 + 0x594E, KANJI_LEVEL4, // 奎 + 0x595A, KANJI_LEVEL4, // 奚 + 0x5958, KANJI_LEVEL4, // 奘 + 0x5962, KANJI_LEVEL4, // 奢 + 0x5960, KANJI_LEVEL4, // 奠 + 0x5967, KANJI_LEVEL4, // 奧 + 0x596C, KANJI_LEVEL4, // 奬 + 0x5969, KANJI_LEVEL4, // 奩 + 0x5978, KANJI_LEVEL4, // 奞 + 0x5981, KANJI_LEVEL4, // 劁 + 0x599D, KANJI_LEVEL4, // 劝 + 0x4F5E, KANJI_LEVEL4, // 䜞 + 0x4FAB, KANJI_LEVEL4, // 䟫 + 0x59A3, KANJI_LEVEL4, // 劣 + 0x59B2, KANJI_LEVEL4, // 劲 + 0x59C6, KANJI_LEVEL4, // 姆 + 0x59E8, KANJI_LEVEL4, // å§š + 0x59DC, KANJI_LEVEL4, // 姜 + 0x598D, KANJI_LEVEL4, // 劍 + 0x59D9, KANJI_LEVEL4, // 姙 + 0x59DA, KANJI_LEVEL4, // 姚 + 0x5A25, KANJI_LEVEL4, // 嚥 + 0x5A1F, KANJI_LEVEL4, // 嚟 + 0x5A11, KANJI_LEVEL4, // åš‘ + 0x5A1C, KANJI_LEVEL4, // åšœ + 0x5A09, KANJI_LEVEL4, // 嚉 + 0x5A1A, KANJI_LEVEL4, // åšš + 0x5A40, KANJI_LEVEL4, // 婀 + 0x5A6C, KANJI_LEVEL4, // 婬 + 0x5A49, KANJI_LEVEL4, // 婉 + 0x5A35, KANJI_LEVEL4, // åšµ + 0x5A36, KANJI_LEVEL4, // åš¶ + 0x5A62, KANJI_LEVEL4, // å©¢ + 0x5A6A, KANJI_LEVEL4, // 婪 + 0x5A9A, KANJI_LEVEL4, // 媚 + 0x5ABC, KANJI_LEVEL4, // 媌 + 0x5ABE, KANJI_LEVEL4, // 媟 + 0x5ACB, KANJI_LEVEL4, // 嫋 + 0x5AC2, KANJI_LEVEL4, // 嫂 + 0x5ABD, KANJI_LEVEL4, // 媜 + 0x5AE3, KANJI_LEVEL4, // å«£ + 0x5AD7, KANJI_LEVEL4, // 嫗 + 0x5AE6, KANJI_LEVEL4, // 嫊 + 0x5AE9, KANJI_LEVEL4, // å«© + 0x5AD6, KANJI_LEVEL4, // 嫖 + 0x5AFA, KANJI_LEVEL4, // 嫺 + 0x5AFB, KANJI_LEVEL4, // å«» + 0x5B0C, KANJI_LEVEL4, // 嬌 + 0x5B0B, KANJI_LEVEL4, // 嬋 + 0x5B16, KANJI_LEVEL4, // 嬖 + 0x5B32, KANJI_LEVEL4, // 嬲 + 0x5AD0, KANJI_LEVEL4, // 嫐 + 0x5B2A, KANJI_LEVEL4, // 嬪 + 0x5B36, KANJI_LEVEL4, // 嬶 + 0x5B3E, KANJI_LEVEL4, // 嬟 + 0x5B43, KANJI_LEVEL4, // 孃 + 0x5B45, KANJI_LEVEL4, // 孅 + 0x5B40, KANJI_LEVEL4, // 孀 + 0x5B51, KANJI_LEVEL4, // 孑 + 0x5B55, KANJI_LEVEL4, // 孕 + 0x5B5A, KANJI_LEVEL4, // 孚 + 0x5B5B, KANJI_LEVEL4, // 孛 + 0x5B65, KANJI_LEVEL4, // å­¥ + 0x5B69, KANJI_LEVEL4, // å­© + 0x5B70, KANJI_LEVEL4, // å­° + 0x5B73, KANJI_LEVEL4, // å­³ + 0x5B75, KANJI_LEVEL4, // å­µ + 0x5B78, KANJI_LEVEL4, // å­ž + 0x6588, KANJI_LEVEL4, // 斈 + 0x5B7A, KANJI_LEVEL4, // å­º + 0x5B80, KANJI_LEVEL4, // 宀 + 0x5B83, KANJI_LEVEL4, // 它 + 0x5BA6, KANJI_LEVEL4, // 宊 + 0x5BB8, KANJI_LEVEL4, // 实 + 0x5BC3, KANJI_LEVEL4, // 寃 + 0x5BC7, KANJI_LEVEL4, // 寇 + 0x5BC9, KANJI_LEVEL4, // 寉 + 0x5BD4, KANJI_LEVEL4, // 寔 + 0x5BD0, KANJI_LEVEL4, // 寐 + 0x5BE4, KANJI_LEVEL4, // 寀 + 0x5BE6, KANJI_LEVEL4, // 寊 + 0x5BE2, KANJI_LEVEL4, // 寢 + 0x5BDE, KANJI_LEVEL4, // 寞 + 0x5BE5, KANJI_LEVEL4, // 寥 + 0x5BEB, KANJI_LEVEL4, // 寫 + 0x5BF0, KANJI_LEVEL4, // 寰 + 0x5BF6, KANJI_LEVEL4, // 寶 + 0x5BF3, KANJI_LEVEL4, // 寳 + 0x5C05, KANJI_LEVEL4, // 尅 + 0x5C07, KANJI_LEVEL4, // 將 + 0x5C08, KANJI_LEVEL4, // 專 + 0x5C0D, KANJI_LEVEL4, // 對 + 0x5C13, KANJI_LEVEL4, // 尓 + 0x5C20, KANJI_LEVEL4, // å°  + 0x5C22, KANJI_LEVEL4, // å°¢ + 0x5C28, KANJI_LEVEL4, // å°š + 0x5C38, KANJI_LEVEL4, // å°ž + 0x5C39, KANJI_LEVEL4, // å°¹ + 0x5C41, KANJI_LEVEL4, // 屁 + 0x5C46, KANJI_LEVEL4, // 屆 + 0x5C4E, KANJI_LEVEL4, // 屎 + 0x5C53, KANJI_LEVEL4, // 屓 + 0x5C50, KANJI_LEVEL4, // 屐 + 0x5C4F, KANJI_LEVEL4, // 屏 + 0x5B71, KANJI_LEVEL4, // å­± + 0x5C6C, KANJI_LEVEL4, // 屬 + 0x5C6E, KANJI_LEVEL4, // å±® + 0x4E62, KANJI_LEVEL4, // ä¹¢ + 0x5C76, KANJI_LEVEL4, // å±¶ + 0x5C79, KANJI_LEVEL4, // å±¹ + 0x5C8C, KANJI_LEVEL4, // 岌 + 0x5C91, KANJI_LEVEL4, // 岑 + 0x5C94, KANJI_LEVEL4, // 岔 + 0x599B, KANJI_LEVEL4, // 力 + 0x5CAB, KANJI_LEVEL4, // 岫 + 0x5CBB, KANJI_LEVEL4, // å²» + 0x5CB6, KANJI_LEVEL4, // å²¶ + 0x5CBC, KANJI_LEVEL4, // 岌 + 0x5CB7, KANJI_LEVEL4, // å²· + 0x5CC5, KANJI_LEVEL4, // 峅 + 0x5CBE, KANJI_LEVEL4, // 岟 + 0x5CC7, KANJI_LEVEL4, // 峇 + 0x5CD9, KANJI_LEVEL4, // 峙 + 0x5CE9, KANJI_LEVEL4, // 峩 + 0x5CFD, KANJI_LEVEL4, // 峜 + 0x5CFA, KANJI_LEVEL4, // 峺 + 0x5CED, KANJI_LEVEL4, // å³­ + 0x5D8C, KANJI_LEVEL4, // 嶌 + 0x5CEA, KANJI_LEVEL4, // 峪 + 0x5D0B, KANJI_LEVEL4, // 压 + 0x5D15, KANJI_LEVEL4, // 厕 + 0x5D17, KANJI_LEVEL4, // 厗 + 0x5D5C, KANJI_LEVEL4, // 嵜 + 0x5D1F, KANJI_LEVEL4, // 原 + 0x5D1B, KANJI_LEVEL4, // 厛 + 0x5D11, KANJI_LEVEL4, // 厑 + 0x5D14, KANJI_LEVEL4, // 厔 + 0x5D22, KANJI_LEVEL4, // 厢 + 0x5D1A, KANJI_LEVEL4, // 厚 + 0x5D19, KANJI_LEVEL4, // 厙 + 0x5D18, KANJI_LEVEL4, // 厘 + 0x5D4C, KANJI_LEVEL4, // 嵌 + 0x5D52, KANJI_LEVEL4, // 嵒 + 0x5D4E, KANJI_LEVEL4, // 嵎 + 0x5D4B, KANJI_LEVEL4, // 嵋 + 0x5D6C, KANJI_LEVEL4, // 嵬 + 0x5D73, KANJI_LEVEL4, // åµ³ + 0x5D76, KANJI_LEVEL4, // åµ¶ + 0x5D87, KANJI_LEVEL4, // 嶇 + 0x5D84, KANJI_LEVEL4, // 嶄 + 0x5D82, KANJI_LEVEL4, // 嶂 + 0x5DA2, KANJI_LEVEL4, // å¶¢ + 0x5D9D, KANJI_LEVEL4, // 嶝 + 0x5DAC, KANJI_LEVEL4, // 嶬 + 0x5DAE, KANJI_LEVEL4, // å¶® + 0x5DBD, KANJI_LEVEL4, // å¶œ + 0x5D90, KANJI_LEVEL4, // 嶐 + 0x5DB7, KANJI_LEVEL4, // å¶· + 0x5DBC, KANJI_LEVEL4, // å¶Œ + 0x5DC9, KANJI_LEVEL4, // 巉 + 0x5DCD, KANJI_LEVEL4, // 巍 + 0x5DD3, KANJI_LEVEL4, // 巓 + 0x5DD2, KANJI_LEVEL4, // 巒 + 0x5DD6, KANJI_LEVEL4, // 巖 + 0x5DDB, KANJI_LEVEL4, // 巛 + 0x5DEB, KANJI_LEVEL4, // å·« + 0x5DF2, KANJI_LEVEL4, // å·² + 0x5DF5, KANJI_LEVEL4, // å·µ + 0x5E0B, KANJI_LEVEL4, // åž‹ + 0x5E1A, KANJI_LEVEL4, // åžš + 0x5E19, KANJI_LEVEL4, // åž™ + 0x5E11, KANJI_LEVEL4, // åž‘ + 0x5E1B, KANJI_LEVEL4, // åž› + 0x5E36, KANJI_LEVEL4, // åž¶ + 0x5E37, KANJI_LEVEL4, // åž· + 0x5E44, KANJI_LEVEL4, // 幄 + 0x5E43, KANJI_LEVEL4, // 幃 + 0x5E40, KANJI_LEVEL4, // 幀 + 0x5E4E, KANJI_LEVEL4, // 幎 + 0x5E57, KANJI_LEVEL4, // 幗 + 0x5E54, KANJI_LEVEL4, // 幔 + 0x5E5F, KANJI_LEVEL4, // 幟 + 0x5E62, KANJI_LEVEL4, // å¹¢ + 0x5E64, KANJI_LEVEL4, // å¹€ + 0x5E47, KANJI_LEVEL4, // 幇 + 0x5E75, KANJI_LEVEL4, // å¹µ + 0x5E76, KANJI_LEVEL4, // å¹¶ + 0x5E7A, KANJI_LEVEL4, // 幺 + 0x9EBC, KANJI_LEVEL4, // 麌 + 0x5E7F, KANJI_LEVEL4, // 广 + 0x5EA0, KANJI_LEVEL4, // 庠 + 0x5EC1, KANJI_LEVEL4, // 廁 + 0x5EC2, KANJI_LEVEL4, // 廂 + 0x5EC8, KANJI_LEVEL4, // 廈 + 0x5ED0, KANJI_LEVEL4, // 廐 + 0x5ECF, KANJI_LEVEL4, // 廏 + 0x5ED6, KANJI_LEVEL4, // 廖 + 0x5EE3, KANJI_LEVEL4, // 廣 + 0x5EDD, KANJI_LEVEL4, // 廝 + 0x5EDA, KANJI_LEVEL4, // 廚 + 0x5EDB, KANJI_LEVEL4, // 廛 + 0x5EE2, KANJI_LEVEL4, // 廢 + 0x5EE1, KANJI_LEVEL4, // 廡 + 0x5EE8, KANJI_LEVEL4, // 廚 + 0x5EE9, KANJI_LEVEL4, // 廩 + 0x5EEC, KANJI_LEVEL4, // 廬 + 0x5EF1, KANJI_LEVEL4, // å»± + 0x5EF3, KANJI_LEVEL4, // 廳 + 0x5EF0, KANJI_LEVEL4, // å»° + 0x5EF4, KANJI_LEVEL4, // 廎 + 0x5EF8, KANJI_LEVEL4, // 廞 + 0x5EFE, KANJI_LEVEL4, // 廟 + 0x5F03, KANJI_LEVEL4, // 匃 + 0x5F09, KANJI_LEVEL4, // 匉 + 0x5F5D, KANJI_LEVEL4, // 圝 + 0x5F5C, KANJI_LEVEL4, // 圜 + 0x5F0B, KANJI_LEVEL4, // 匋 + 0x5F11, KANJI_LEVEL4, // 匑 + 0x5F16, KANJI_LEVEL4, // 化 + 0x5F29, KANJI_LEVEL4, // 匩 + 0x5F2D, KANJI_LEVEL4, // 匭 + 0x5F38, KANJI_LEVEL4, // 匞 + 0x5F41, KANJI_LEVEL4, // 圁 + 0x5F48, KANJI_LEVEL4, // 圈 + 0x5F4C, KANJI_LEVEL4, // 圌 + 0x5F4E, KANJI_LEVEL4, // 圎 + 0x5F2F, KANJI_LEVEL4, // 匯 + 0x5F51, KANJI_LEVEL4, // 圑 + 0x5F56, KANJI_LEVEL4, // 圖 + 0x5F57, KANJI_LEVEL4, // 圗 + 0x5F59, KANJI_LEVEL4, // 圙 + 0x5F61, KANJI_LEVEL4, // 圡 + 0x5F6D, KANJI_LEVEL4, // 圭 + 0x5F73, KANJI_LEVEL4, // 圳 + 0x5F77, KANJI_LEVEL4, // 圷 + 0x5F83, KANJI_LEVEL4, // 埃 + 0x5F82, KANJI_LEVEL4, // 埂 + 0x5F7F, KANJI_LEVEL4, // 圿 + 0x5F8A, KANJI_LEVEL4, // 埊 + 0x5F88, KANJI_LEVEL4, // 埈 + 0x5F91, KANJI_LEVEL4, // 埑 + 0x5F87, KANJI_LEVEL4, // 埇 + 0x5F9E, KANJI_LEVEL4, // 埞 + 0x5F99, KANJI_LEVEL4, // 埙 + 0x5F98, KANJI_LEVEL4, // 埘 + 0x5FA0, KANJI_LEVEL4, // 埠 + 0x5FA8, KANJI_LEVEL4, // 埚 + 0x5FAD, KANJI_LEVEL4, // 埭 + 0x5FBC, KANJI_LEVEL4, // 埌 + 0x5FD6, KANJI_LEVEL4, // 忖 + 0x5FFB, KANJI_LEVEL4, // å¿» + 0x5FE4, KANJI_LEVEL4, // å¿€ + 0x5FF8, KANJI_LEVEL4, // 忞 + 0x5FF1, KANJI_LEVEL4, // 忱 + 0x5FDD, KANJI_LEVEL4, // 忝 + 0x60B3, KANJI_LEVEL4, // 悳 + 0x5FFF, KANJI_LEVEL4, // å¿¿ + 0x6021, KANJI_LEVEL4, // 怡 + 0x6060, KANJI_LEVEL4, // 恠 + 0x6019, KANJI_LEVEL4, // 怙 + 0x6010, KANJI_LEVEL4, // 怐 + 0x6029, KANJI_LEVEL4, // 怩 + 0x600E, KANJI_LEVEL4, // 怎 + 0x6031, KANJI_LEVEL4, // 怱 + 0x601B, KANJI_LEVEL4, // 怛 + 0x6015, KANJI_LEVEL4, // 怕 + 0x602B, KANJI_LEVEL4, // 怫 + 0x6026, KANJI_LEVEL4, // 怊 + 0x600F, KANJI_LEVEL4, // 怏 + 0x603A, KANJI_LEVEL4, // 怺 + 0x605A, KANJI_LEVEL4, // 恚 + 0x6041, KANJI_LEVEL4, // 恁 + 0x606A, KANJI_LEVEL4, // 恪 + 0x6077, KANJI_LEVEL4, // 恷 + 0x605F, KANJI_LEVEL4, // 恟 + 0x604A, KANJI_LEVEL4, // 恊 + 0x6046, KANJI_LEVEL4, // 恆 + 0x604D, KANJI_LEVEL4, // 恍 + 0x6063, KANJI_LEVEL4, // 恣 + 0x6043, KANJI_LEVEL4, // 恃 + 0x6064, KANJI_LEVEL4, // 恀 + 0x6042, KANJI_LEVEL4, // 恂 + 0x606C, KANJI_LEVEL4, // 恬 + 0x606B, KANJI_LEVEL4, // 恫 + 0x6059, KANJI_LEVEL4, // 恙 + 0x6081, KANJI_LEVEL4, // 悁 + 0x608D, KANJI_LEVEL4, // 悍 + 0x60E7, KANJI_LEVEL4, // 惧 + 0x6083, KANJI_LEVEL4, // 悃 + 0x609A, KANJI_LEVEL4, // 悚 + 0x6084, KANJI_LEVEL4, // 悄 + 0x609B, KANJI_LEVEL4, // 悛 + 0x6096, KANJI_LEVEL4, // 悖 + 0x6097, KANJI_LEVEL4, // 悗 + 0x6092, KANJI_LEVEL4, // 悒 + 0x60A7, KANJI_LEVEL4, // 悧 + 0x608B, KANJI_LEVEL4, // 悋 + 0x60E1, KANJI_LEVEL4, // 惡 + 0x60B8, KANJI_LEVEL4, // 悞 + 0x60E0, KANJI_LEVEL4, // 惠 + 0x60D3, KANJI_LEVEL4, // 惓 + 0x60B4, KANJI_LEVEL4, // 悎 + 0x5FF0, KANJI_LEVEL4, // å¿° + 0x60BD, KANJI_LEVEL4, // 悜 + 0x60C6, KANJI_LEVEL4, // 惆 + 0x60B5, KANJI_LEVEL4, // 悵 + 0x60D8, KANJI_LEVEL4, // 惘 + 0x614D, KANJI_LEVEL4, // 慍 + 0x6115, KANJI_LEVEL4, // 愕 + 0x6106, KANJI_LEVEL4, // 愆 + 0x60F6, KANJI_LEVEL4, // 惶 + 0x60F7, KANJI_LEVEL4, // 惷 + 0x6100, KANJI_LEVEL4, // 愀 + 0x60F4, KANJI_LEVEL4, // 惎 + 0x60FA, KANJI_LEVEL4, // 惺 + 0x6103, KANJI_LEVEL4, // 愃 + 0x6121, KANJI_LEVEL4, // 愡 + 0x60FB, KANJI_LEVEL4, // 惻 + 0x60F1, KANJI_LEVEL4, // 惱 + 0x610D, KANJI_LEVEL4, // 愍 + 0x610E, KANJI_LEVEL4, // 愎 + 0x6147, KANJI_LEVEL4, // 慇 + 0x613E, KANJI_LEVEL4, // 感 + 0x6128, KANJI_LEVEL4, // 愚 + 0x6127, KANJI_LEVEL4, // 愧 + 0x614A, KANJI_LEVEL4, // 慊 + 0x613F, KANJI_LEVEL4, // 愿 + 0x613C, KANJI_LEVEL4, // 愌 + 0x612C, KANJI_LEVEL4, // 愬 + 0x6134, KANJI_LEVEL4, // 愎 + 0x613D, KANJI_LEVEL4, // 愜 + 0x6142, KANJI_LEVEL4, // 慂 + 0x6144, KANJI_LEVEL4, // 慄 + 0x6173, KANJI_LEVEL4, // 慳 + 0x6177, KANJI_LEVEL4, // 慷 + 0x6158, KANJI_LEVEL4, // 慘 + 0x6159, KANJI_LEVEL4, // 慙 + 0x615A, KANJI_LEVEL4, // 慚 + 0x616B, KANJI_LEVEL4, // 慫 + 0x6174, KANJI_LEVEL4, // æ…Ž + 0x616F, KANJI_LEVEL4, // 慯 + 0x6165, KANJI_LEVEL4, // 慥 + 0x6171, KANJI_LEVEL4, // 慱 + 0x615F, KANJI_LEVEL4, // 慟 + 0x615D, KANJI_LEVEL4, // 慝 + 0x6153, KANJI_LEVEL4, // 慓 + 0x6175, KANJI_LEVEL4, // 慵 + 0x6199, KANJI_LEVEL4, // 憙 + 0x6196, KANJI_LEVEL4, // 憖 + 0x6187, KANJI_LEVEL4, // 憇 + 0x61AC, KANJI_LEVEL4, // 憬 + 0x6194, KANJI_LEVEL4, // 憔 + 0x619A, KANJI_LEVEL4, // 憚 + 0x618A, KANJI_LEVEL4, // 憊 + 0x6191, KANJI_LEVEL4, // 憑 + 0x61AB, KANJI_LEVEL4, // 憫 + 0x61AE, KANJI_LEVEL4, // 憮 + 0x61CC, KANJI_LEVEL4, // 懌 + 0x61CA, KANJI_LEVEL4, // 懊 + 0x61C9, KANJI_LEVEL4, // 應 + 0x61F7, KANJI_LEVEL4, // 懷 + 0x61C8, KANJI_LEVEL4, // 懈 + 0x61C3, KANJI_LEVEL4, // 懃 + 0x61C6, KANJI_LEVEL4, // 懆 + 0x61BA, KANJI_LEVEL4, // 憺 + 0x61CB, KANJI_LEVEL4, // 懋 + 0x7F79, KANJI_LEVEL4, // 眹 + 0x61CD, KANJI_LEVEL4, // 懍 + 0x61E6, KANJI_LEVEL4, // 懊 + 0x61E3, KANJI_LEVEL4, // 懣 + 0x61F6, KANJI_LEVEL4, // 懶 + 0x61FA, KANJI_LEVEL4, // 懺 + 0x61F4, KANJI_LEVEL4, // 懎 + 0x61FF, KANJI_LEVEL4, // 懿 + 0x61FD, KANJI_LEVEL4, // 懜 + 0x61FC, KANJI_LEVEL4, // 懌 + 0x61FE, KANJI_LEVEL4, // 懟 + 0x6200, KANJI_LEVEL4, // 戀 + 0x6208, KANJI_LEVEL4, // 戈 + 0x6209, KANJI_LEVEL4, // 戉 + 0x620D, KANJI_LEVEL4, // 戍 + 0x620C, KANJI_LEVEL4, // 戌 + 0x6214, KANJI_LEVEL4, // 戔 + 0x621B, KANJI_LEVEL4, // 戛 + 0x621E, KANJI_LEVEL4, // 戞 + 0x6221, KANJI_LEVEL4, // 戡 + 0x622A, KANJI_LEVEL4, // 截 + 0x622E, KANJI_LEVEL4, // 戮 + 0x6230, KANJI_LEVEL4, // 戰 + 0x6232, KANJI_LEVEL4, // 戲 + 0x6233, KANJI_LEVEL4, // 戳 + 0x6241, KANJI_LEVEL4, // 扁 + 0x624E, KANJI_LEVEL4, // 扎 + 0x625E, KANJI_LEVEL4, // 扞 + 0x6263, KANJI_LEVEL4, // 扣 + 0x625B, KANJI_LEVEL4, // 扛 + 0x6260, KANJI_LEVEL4, // 扠 + 0x6268, KANJI_LEVEL4, // 扚 + 0x627C, KANJI_LEVEL4, // 扌 + 0x6282, KANJI_LEVEL4, // 抂 + 0x6289, KANJI_LEVEL4, // 抉 + 0x627E, KANJI_LEVEL4, // 扟 + 0x6292, KANJI_LEVEL4, // 抒 + 0x6293, KANJI_LEVEL4, // 抓 + 0x6296, KANJI_LEVEL4, // 抖 + 0x62D4, KANJI_LEVEL4, // 拔 + 0x6283, KANJI_LEVEL4, // 抃 + 0x6294, KANJI_LEVEL4, // 抔 + 0x62D7, KANJI_LEVEL4, // 拗 + 0x62D1, KANJI_LEVEL4, // 拑 + 0x62BB, KANJI_LEVEL4, // 抻 + 0x62CF, KANJI_LEVEL4, // 拏 + 0x62FF, KANJI_LEVEL4, // 拿 + 0x62C6, KANJI_LEVEL4, // 拆 + 0x64D4, KANJI_LEVEL4, // 擔 + 0x62C8, KANJI_LEVEL4, // 拈 + 0x62DC, KANJI_LEVEL4, // 拜 + 0x62CC, KANJI_LEVEL4, // 拌 + 0x62CA, KANJI_LEVEL4, // 拊 + 0x62C2, KANJI_LEVEL4, // 拂 + 0x62C7, KANJI_LEVEL4, // 拇 + 0x629B, KANJI_LEVEL4, // 抛 + 0x62C9, KANJI_LEVEL4, // 拉 + 0x630C, KANJI_LEVEL4, // 挌 + 0x62EE, KANJI_LEVEL4, // 拮 + 0x62F1, KANJI_LEVEL4, // 拱 + 0x6327, KANJI_LEVEL4, // 挧 + 0x6302, KANJI_LEVEL4, // 挂 + 0x6308, KANJI_LEVEL4, // 挈 + 0x62EF, KANJI_LEVEL4, // 拯 + 0x62F5, KANJI_LEVEL4, // 拵 + 0x6350, KANJI_LEVEL4, // 捐 + 0x633E, KANJI_LEVEL4, // 挟 + 0x634D, KANJI_LEVEL4, // 捍 + 0x641C, KANJI_LEVEL4, // 搜 + 0x634F, KANJI_LEVEL4, // 捏 + 0x6396, KANJI_LEVEL4, // 掖 + 0x638E, KANJI_LEVEL4, // 掎 + 0x6380, KANJI_LEVEL4, // 掀 + 0x63AB, KANJI_LEVEL4, // 掫 + 0x6376, KANJI_LEVEL4, // 捶 + 0x63A3, KANJI_LEVEL4, // 掣 + 0x638F, KANJI_LEVEL4, // 掏 + 0x6389, KANJI_LEVEL4, // 掉 + 0x639F, KANJI_LEVEL4, // 掟 + 0x63B5, KANJI_LEVEL4, // 掵 + 0x636B, KANJI_LEVEL4, // 捫 + 0x6369, KANJI_LEVEL4, // 捩 + 0x63BE, KANJI_LEVEL4, // 掟 + 0x63E9, KANJI_LEVEL4, // 揩 + 0x63C0, KANJI_LEVEL4, // 揀 + 0x63C6, KANJI_LEVEL4, // 揆 + 0x63E3, KANJI_LEVEL4, // 揣 + 0x63C9, KANJI_LEVEL4, // 揉 + 0x63D2, KANJI_LEVEL4, // 插 + 0x63F6, KANJI_LEVEL4, // 揶 + 0x63C4, KANJI_LEVEL4, // 揄 + 0x6416, KANJI_LEVEL4, // 搖 + 0x6434, KANJI_LEVEL4, // 搎 + 0x6406, KANJI_LEVEL4, // 搆 + 0x6413, KANJI_LEVEL4, // 搓 + 0x6426, KANJI_LEVEL4, // 搊 + 0x6436, KANJI_LEVEL4, // 搶 + 0x651D, KANJI_LEVEL4, // 攝 + 0x6417, KANJI_LEVEL4, // 搗 + 0x6428, KANJI_LEVEL4, // 搚 + 0x640F, KANJI_LEVEL4, // 搏 + 0x6467, KANJI_LEVEL4, // 摧 + 0x646F, KANJI_LEVEL4, // 摯 + 0x6476, KANJI_LEVEL4, // 摶 + 0x644E, KANJI_LEVEL4, // 摎 + 0x652A, KANJI_LEVEL4, // 攪 + 0x6495, KANJI_LEVEL4, // 撕 + 0x6493, KANJI_LEVEL4, // 撓 + 0x64A5, KANJI_LEVEL4, // 撥 + 0x64A9, KANJI_LEVEL4, // 撩 + 0x6488, KANJI_LEVEL4, // 撈 + 0x64BC, KANJI_LEVEL4, // æ’Œ + 0x64DA, KANJI_LEVEL4, // 據 + 0x64D2, KANJI_LEVEL4, // 擒 + 0x64C5, KANJI_LEVEL4, // 擅 + 0x64C7, KANJI_LEVEL4, // 擇 + 0x64BB, KANJI_LEVEL4, // 撻 + 0x64D8, KANJI_LEVEL4, // 擘 + 0x64C2, KANJI_LEVEL4, // 擂 + 0x64F1, KANJI_LEVEL4, // 擱 + 0x64E7, KANJI_LEVEL4, // 擧 + 0x8209, KANJI_LEVEL4, // 舉 + 0x64E0, KANJI_LEVEL4, // 擠 + 0x64E1, KANJI_LEVEL4, // 擡 + 0x62AC, KANJI_LEVEL4, // 抬 + 0x64E3, KANJI_LEVEL4, // 擣 + 0x64EF, KANJI_LEVEL4, // 擯 + 0x652C, KANJI_LEVEL4, // 攬 + 0x64F6, KANJI_LEVEL4, // 擶 + 0x64F4, KANJI_LEVEL4, // 擎 + 0x64F2, KANJI_LEVEL4, // 擲 + 0x64FA, KANJI_LEVEL4, // 擺 + 0x6500, KANJI_LEVEL4, // 攀 + 0x64FD, KANJI_LEVEL4, // 擜 + 0x6518, KANJI_LEVEL4, // 攘 + 0x651C, KANJI_LEVEL4, // 攜 + 0x6505, KANJI_LEVEL4, // 攅 + 0x6524, KANJI_LEVEL4, // 攀 + 0x6523, KANJI_LEVEL4, // 攣 + 0x652B, KANJI_LEVEL4, // 攫 + 0x6534, KANJI_LEVEL4, // 攎 + 0x6535, KANJI_LEVEL4, // 攵 + 0x6537, KANJI_LEVEL4, // 攷 + 0x6536, KANJI_LEVEL4, // 收 + 0x6538, KANJI_LEVEL4, // 攞 + 0x754B, KANJI_LEVEL4, // 畋 + 0x6548, KANJI_LEVEL4, // 效 + 0x6556, KANJI_LEVEL4, // 敖 + 0x6555, KANJI_LEVEL4, // 敕 + 0x654D, KANJI_LEVEL4, // 敍 + 0x6558, KANJI_LEVEL4, // 敘 + 0x655E, KANJI_LEVEL4, // 敞 + 0x655D, KANJI_LEVEL4, // 敝 + 0x6572, KANJI_LEVEL4, // 敲 + 0x6578, KANJI_LEVEL4, // 敞 + 0x6582, KANJI_LEVEL4, // 斂 + 0x6583, KANJI_LEVEL4, // 斃 + 0x8B8A, KANJI_LEVEL4, // 變 + 0x659B, KANJI_LEVEL4, // 斛 + 0x659F, KANJI_LEVEL4, // 斟 + 0x65AB, KANJI_LEVEL4, // 斫 + 0x65B7, KANJI_LEVEL4, // 斷 + 0x65C3, KANJI_LEVEL4, // 旃 + 0x65C6, KANJI_LEVEL4, // 旆 + 0x65C1, KANJI_LEVEL4, // 旁 + 0x65C4, KANJI_LEVEL4, // 旄 + 0x65CC, KANJI_LEVEL4, // 旌 + 0x65D2, KANJI_LEVEL4, // 旒 + 0x65DB, KANJI_LEVEL4, // 旛 + 0x65D9, KANJI_LEVEL4, // 旙 + 0x65E0, KANJI_LEVEL4, // 无 + 0x65E1, KANJI_LEVEL4, // 旡 + 0x65F1, KANJI_LEVEL4, // 旱 + 0x6772, KANJI_LEVEL4, // 杲 + 0x660A, KANJI_LEVEL4, // 昊 + 0x6603, KANJI_LEVEL4, // 昃 + 0x65FB, KANJI_LEVEL4, // 旻 + 0x6773, KANJI_LEVEL4, // 杳 + 0x6635, KANJI_LEVEL4, // 昵 + 0x6636, KANJI_LEVEL4, // 昶 + 0x6634, KANJI_LEVEL4, // 明 + 0x661C, KANJI_LEVEL4, // 昜 + 0x664F, KANJI_LEVEL4, // 晏 + 0x6644, KANJI_LEVEL4, // 晄 + 0x6649, KANJI_LEVEL4, // 晉 + 0x6641, KANJI_LEVEL4, // 晁 + 0x665E, KANJI_LEVEL4, // 晞 + 0x665D, KANJI_LEVEL4, // 晝 + 0x6664, KANJI_LEVEL4, // 晀 + 0x6667, KANJI_LEVEL4, // 晧 + 0x6668, KANJI_LEVEL4, // 晚 + 0x665F, KANJI_LEVEL4, // 晟 + 0x6662, KANJI_LEVEL4, // 晢 + 0x6670, KANJI_LEVEL4, // 晰 + 0x6683, KANJI_LEVEL4, // 暃 + 0x6688, KANJI_LEVEL4, // 暈 + 0x668E, KANJI_LEVEL4, // 暎 + 0x6689, KANJI_LEVEL4, // 暉 + 0x6684, KANJI_LEVEL4, // 暄 + 0x6698, KANJI_LEVEL4, // 暘 + 0x669D, KANJI_LEVEL4, // 暝 + 0x66C1, KANJI_LEVEL4, // 曁 + 0x66B9, KANJI_LEVEL4, // 暹 + 0x66C9, KANJI_LEVEL4, // 曉 + 0x66BE, KANJI_LEVEL4, // 暟 + 0x66BC, KANJI_LEVEL4, // 暌 + 0x66C4, KANJI_LEVEL4, // 曄 + 0x66B8, KANJI_LEVEL4, // æšž + 0x66D6, KANJI_LEVEL4, // 曖 + 0x66DA, KANJI_LEVEL4, // 曚 + 0x66E0, KANJI_LEVEL4, // 曠 + 0x663F, KANJI_LEVEL4, // 昿 + 0x66E6, KANJI_LEVEL4, // 曊 + 0x66E9, KANJI_LEVEL4, // 曩 + 0x66F0, KANJI_LEVEL4, // 曰 + 0x66F5, KANJI_LEVEL4, // 曵 + 0x66F7, KANJI_LEVEL4, // 曷 + 0x670F, KANJI_LEVEL4, // 朏 + 0x6716, KANJI_LEVEL4, // 朖 + 0x671E, KANJI_LEVEL4, // 朞 + 0x6726, KANJI_LEVEL4, // 朊 + 0x6727, KANJI_LEVEL4, // 朧 + 0x9738, KANJI_LEVEL4, // 霾 + 0x672E, KANJI_LEVEL4, // 朮 + 0x673F, KANJI_LEVEL4, // 朿 + 0x6736, KANJI_LEVEL4, // 朶 + 0x6741, KANJI_LEVEL4, // 杁 + 0x6738, KANJI_LEVEL4, // 朞 + 0x6737, KANJI_LEVEL4, // 朷 + 0x6746, KANJI_LEVEL4, // 杆 + 0x675E, KANJI_LEVEL4, // 杞 + 0x6760, KANJI_LEVEL4, // 杠 + 0x6759, KANJI_LEVEL4, // 杙 + 0x6763, KANJI_LEVEL4, // 杣 + 0x6764, KANJI_LEVEL4, // 杀 + 0x6789, KANJI_LEVEL4, // 枉 + 0x6770, KANJI_LEVEL4, // 杰 + 0x67A9, KANJI_LEVEL4, // 枩 + 0x677C, KANJI_LEVEL4, // 杌 + 0x676A, KANJI_LEVEL4, // 杪 + 0x678C, KANJI_LEVEL4, // 枌 + 0x678B, KANJI_LEVEL4, // 枋 + 0x67A6, KANJI_LEVEL4, // 枊 + 0x67A1, KANJI_LEVEL4, // 枡 + 0x6785, KANJI_LEVEL4, // 枅 + 0x67B7, KANJI_LEVEL4, // 枷 + 0x67EF, KANJI_LEVEL4, // 柯 + 0x67B4, KANJI_LEVEL4, // 枎 + 0x67EC, KANJI_LEVEL4, // 柬 + 0x67B3, KANJI_LEVEL4, // 枳 + 0x67E9, KANJI_LEVEL4, // 柩 + 0x67B8, KANJI_LEVEL4, // æžž + 0x67E4, KANJI_LEVEL4, // 柀 + 0x67DE, KANJI_LEVEL4, // 柞 + 0x67DD, KANJI_LEVEL4, // 柝 + 0x67E2, KANJI_LEVEL4, // 柢 + 0x67EE, KANJI_LEVEL4, // 柮 + 0x67B9, KANJI_LEVEL4, // 枹 + 0x67CE, KANJI_LEVEL4, // 柎 + 0x67C6, KANJI_LEVEL4, // 柆 + 0x67E7, KANJI_LEVEL4, // 柧 + 0x6A9C, KANJI_LEVEL4, // 檜 + 0x681E, KANJI_LEVEL4, // 栞 + 0x6846, KANJI_LEVEL4, // 框 + 0x6829, KANJI_LEVEL4, // æ © + 0x6840, KANJI_LEVEL4, // 桀 + 0x684D, KANJI_LEVEL4, // 桍 + 0x6832, KANJI_LEVEL4, // æ ² + 0x684E, KANJI_LEVEL4, // 桎 + 0x68B3, KANJI_LEVEL4, // 梳 + 0x682B, KANJI_LEVEL4, // æ « + 0x6859, KANJI_LEVEL4, // 桙 + 0x6863, KANJI_LEVEL4, // æ¡£ + 0x6877, KANJI_LEVEL4, // æ¡· + 0x687F, KANJI_LEVEL4, // æ¡¿ + 0x689F, KANJI_LEVEL4, // 梟 + 0x688F, KANJI_LEVEL4, // 梏 + 0x68AD, KANJI_LEVEL4, // 梭 + 0x6894, KANJI_LEVEL4, // 梔 + 0x689D, KANJI_LEVEL4, // 條 + 0x689B, KANJI_LEVEL4, // 梛 + 0x6883, KANJI_LEVEL4, // 梃 + 0x6AAE, KANJI_LEVEL4, // 檮 + 0x68B9, KANJI_LEVEL4, // 梹 + 0x6874, KANJI_LEVEL4, // 桎 + 0x68B5, KANJI_LEVEL4, // 梵 + 0x68A0, KANJI_LEVEL4, // 梠 + 0x68BA, KANJI_LEVEL4, // 梺 + 0x690F, KANJI_LEVEL4, // 怏 + 0x688D, KANJI_LEVEL4, // 梍 + 0x687E, KANJI_LEVEL4, // 桟 + 0x6901, KANJI_LEVEL4, // 态 + 0x68CA, KANJI_LEVEL4, // 棊 + 0x6908, KANJI_LEVEL4, // 怈 + 0x68D8, KANJI_LEVEL4, // 棘 + 0x6922, KANJI_LEVEL4, // 怢 + 0x6926, KANJI_LEVEL4, // 怊 + 0x68E1, KANJI_LEVEL4, // 棡 + 0x690C, KANJI_LEVEL4, // 怌 + 0x68CD, KANJI_LEVEL4, // 棍 + 0x68D4, KANJI_LEVEL4, // 棔 + 0x68E7, KANJI_LEVEL4, // 棧 + 0x68D5, KANJI_LEVEL4, // 棕 + 0x6936, KANJI_LEVEL4, // 怶 + 0x6912, KANJI_LEVEL4, // 怒 + 0x6904, KANJI_LEVEL4, // 怄 + 0x68D7, KANJI_LEVEL4, // 棗 + 0x68E3, KANJI_LEVEL4, // 棣 + 0x6925, KANJI_LEVEL4, // 急 + 0x68F9, KANJI_LEVEL4, // 棹 + 0x68E0, KANJI_LEVEL4, // 棠 + 0x68EF, KANJI_LEVEL4, // 棯 + 0x6928, KANJI_LEVEL4, // 怚 + 0x692A, KANJI_LEVEL4, // 怪 + 0x691A, KANJI_LEVEL4, // 怚 + 0x6923, KANJI_LEVEL4, // 怣 + 0x6921, KANJI_LEVEL4, // 怡 + 0x68C6, KANJI_LEVEL4, // 棆 + 0x6979, KANJI_LEVEL4, // 楹 + 0x6977, KANJI_LEVEL4, // 楷 + 0x695C, KANJI_LEVEL4, // 楜 + 0x6978, KANJI_LEVEL4, // 楞 + 0x696B, KANJI_LEVEL4, // 楫 + 0x6954, KANJI_LEVEL4, // 楔 + 0x697E, KANJI_LEVEL4, // 楟 + 0x696E, KANJI_LEVEL4, // 楮 + 0x6939, KANJI_LEVEL4, // 怹 + 0x6974, KANJI_LEVEL4, // 楎 + 0x693D, KANJI_LEVEL4, // 怜 + 0x6959, KANJI_LEVEL4, // 楙 + 0x6930, KANJI_LEVEL4, // 怰 + 0x6961, KANJI_LEVEL4, // 楡 + 0x695E, KANJI_LEVEL4, // 楞 + 0x695D, KANJI_LEVEL4, // 楝 + 0x6981, KANJI_LEVEL4, // 抁 + 0x696A, KANJI_LEVEL4, // 楪 + 0x69B2, KANJI_LEVEL4, // 抲 + 0x69AE, KANJI_LEVEL4, // 抮 + 0x69D0, KANJI_LEVEL4, // 槐 + 0x69BF, KANJI_LEVEL4, // 抿 + 0x69C1, KANJI_LEVEL4, // 槁 + 0x69D3, KANJI_LEVEL4, // 槓 + 0x69BE, KANJI_LEVEL4, // 抟 + 0x69CE, KANJI_LEVEL4, // 槎 + 0x5BE8, KANJI_LEVEL4, // 寚 + 0x69CA, KANJI_LEVEL4, // 槊 + 0x69DD, KANJI_LEVEL4, // 槝 + 0x69BB, KANJI_LEVEL4, // 抻 + 0x69C3, KANJI_LEVEL4, // 槃 + 0x69A7, KANJI_LEVEL4, // 抧 + 0x6A2E, KANJI_LEVEL4, // æš® + 0x6991, KANJI_LEVEL4, // 抑 + 0x69A0, KANJI_LEVEL4, // 抠 + 0x699C, KANJI_LEVEL4, // 抜 + 0x6995, KANJI_LEVEL4, // 投 + 0x69B4, KANJI_LEVEL4, // 抎 + 0x69DE, KANJI_LEVEL4, // 槞 + 0x69E8, KANJI_LEVEL4, // æ§š + 0x6A02, KANJI_LEVEL4, // æš‚ + 0x6A1B, KANJI_LEVEL4, // æš› + 0x69FF, KANJI_LEVEL4, // æ§¿ + 0x6B0A, KANJI_LEVEL4, // 權 + 0x69F9, KANJI_LEVEL4, // æ§¹ + 0x69F2, KANJI_LEVEL4, // æ§² + 0x69E7, KANJI_LEVEL4, // æ§§ + 0x6A05, KANJI_LEVEL4, // æš… + 0x69B1, KANJI_LEVEL4, // 抱 + 0x6A1E, KANJI_LEVEL4, // 暞 + 0x69ED, KANJI_LEVEL4, // æ§­ + 0x6A14, KANJI_LEVEL4, // æš” + 0x69EB, KANJI_LEVEL4, // æ§« + 0x6A0A, KANJI_LEVEL4, // 暊 + 0x6A12, KANJI_LEVEL4, // æš’ + 0x6AC1, KANJI_LEVEL4, // 櫁 + 0x6A23, KANJI_LEVEL4, // 暣 + 0x6A13, KANJI_LEVEL4, // æš“ + 0x6A44, KANJI_LEVEL4, // 橄 + 0x6A0C, KANJI_LEVEL4, // 暌 + 0x6A72, KANJI_LEVEL4, // 橲 + 0x6A36, KANJI_LEVEL4, // æš¶ + 0x6A78, KANJI_LEVEL4, // 橞 + 0x6A47, KANJI_LEVEL4, // 橇 + 0x6A62, KANJI_LEVEL4, // æ©¢ + 0x6A59, KANJI_LEVEL4, // 橙 + 0x6A66, KANJI_LEVEL4, // 橊 + 0x6A48, KANJI_LEVEL4, // 橈 + 0x6A38, KANJI_LEVEL4, // æšž + 0x6A22, KANJI_LEVEL4, // 暢 + 0x6A90, KANJI_LEVEL4, // 檐 + 0x6A8D, KANJI_LEVEL4, // 檍 + 0x6AA0, KANJI_LEVEL4, // 檠 + 0x6A84, KANJI_LEVEL4, // 檄 + 0x6AA2, KANJI_LEVEL4, // 檢 + 0x6AA3, KANJI_LEVEL4, // 檣 + 0x6A97, KANJI_LEVEL4, // 檗 + 0x8617, KANJI_LEVEL4, // 蘗 + 0x6ABB, KANJI_LEVEL4, // 檻 + 0x6AC3, KANJI_LEVEL4, // 櫃 + 0x6AC2, KANJI_LEVEL4, // 櫂 + 0x6AB8, KANJI_LEVEL4, // 檞 + 0x6AB3, KANJI_LEVEL4, // 檳 + 0x6AAC, KANJI_LEVEL4, // 檬 + 0x6ADE, KANJI_LEVEL4, // 櫞 + 0x6AD1, KANJI_LEVEL4, // 櫑 + 0x6ADF, KANJI_LEVEL4, // 櫟 + 0x6AAA, KANJI_LEVEL4, // 檪 + 0x6ADA, KANJI_LEVEL4, // 櫚 + 0x6AEA, KANJI_LEVEL4, // 櫪 + 0x6AFB, KANJI_LEVEL4, // æ«» + 0x6B05, KANJI_LEVEL4, // 欅 + 0x8616, KANJI_LEVEL4, // 蘖 + 0x6AFA, KANJI_LEVEL4, // 櫺 + 0x6B12, KANJI_LEVEL4, // 欒 + 0x6B16, KANJI_LEVEL4, // 欖 + 0x9B31, KANJI_LEVEL4, // 鬱 + 0x6B1F, KANJI_LEVEL4, // 欟 + 0x6B38, KANJI_LEVEL4, // 欞 + 0x6B37, KANJI_LEVEL4, // 欷 + 0x76DC, KANJI_LEVEL4, // 盜 + 0x6B39, KANJI_LEVEL4, // 欹 + 0x98EE, KANJI_LEVEL4, // 飮 + 0x6B47, KANJI_LEVEL4, // 歇 + 0x6B43, KANJI_LEVEL4, // 歃 + 0x6B49, KANJI_LEVEL4, // 歉 + 0x6B50, KANJI_LEVEL4, // 歐 + 0x6B59, KANJI_LEVEL4, // 歙 + 0x6B54, KANJI_LEVEL4, // 歔 + 0x6B5B, KANJI_LEVEL4, // 歛 + 0x6B5F, KANJI_LEVEL4, // 歟 + 0x6B61, KANJI_LEVEL4, // æ­¡ + 0x6B78, KANJI_LEVEL4, // æ­ž + 0x6B79, KANJI_LEVEL4, // æ­¹ + 0x6B7F, KANJI_LEVEL4, // æ­¿ + 0x6B80, KANJI_LEVEL4, // 殀 + 0x6B84, KANJI_LEVEL4, // 殄 + 0x6B83, KANJI_LEVEL4, // 殃 + 0x6B8D, KANJI_LEVEL4, // 殍 + 0x6B98, KANJI_LEVEL4, // 殘 + 0x6B95, KANJI_LEVEL4, // 殕 + 0x6B9E, KANJI_LEVEL4, // 殞 + 0x6BA4, KANJI_LEVEL4, // 殀 + 0x6BAA, KANJI_LEVEL4, // 殪 + 0x6BAB, KANJI_LEVEL4, // 殫 + 0x6BAF, KANJI_LEVEL4, // 殯 + 0x6BB2, KANJI_LEVEL4, // 殲 + 0x6BB1, KANJI_LEVEL4, // æ®± + 0x6BB3, KANJI_LEVEL4, // 殳 + 0x6BB7, KANJI_LEVEL4, // æ®· + 0x6BBC, KANJI_LEVEL4, // 殌 + 0x6BC6, KANJI_LEVEL4, // 毆 + 0x6BCB, KANJI_LEVEL4, // 毋 + 0x6BD3, KANJI_LEVEL4, // 毓 + 0x6BDF, KANJI_LEVEL4, // 毟 + 0x6BEC, KANJI_LEVEL4, // 毬 + 0x6BEB, KANJI_LEVEL4, // 毫 + 0x6BF3, KANJI_LEVEL4, // 毳 + 0x6BEF, KANJI_LEVEL4, // 毯 + 0x9EBE, KANJI_LEVEL4, // 麟 + 0x6C08, KANJI_LEVEL4, // 氈 + 0x6C13, KANJI_LEVEL4, // 氓 + 0x6C14, KANJI_LEVEL4, // 气 + 0x6C1B, KANJI_LEVEL4, // 氛 + 0x6C24, KANJI_LEVEL4, // æ°€ + 0x6C23, KANJI_LEVEL4, // æ°£ + 0x6C5E, KANJI_LEVEL4, // 汞 + 0x6C55, KANJI_LEVEL4, // 汕 + 0x6C62, KANJI_LEVEL4, // æ±¢ + 0x6C6A, KANJI_LEVEL4, // 汪 + 0x6C82, KANJI_LEVEL4, // 沂 + 0x6C8D, KANJI_LEVEL4, // 沍 + 0x6C9A, KANJI_LEVEL4, // 沚 + 0x6C81, KANJI_LEVEL4, // 沁 + 0x6C9B, KANJI_LEVEL4, // 沛 + 0x6C7E, KANJI_LEVEL4, // 江 + 0x6C68, KANJI_LEVEL4, // 汚 + 0x6C73, KANJI_LEVEL4, // æ±³ + 0x6C92, KANJI_LEVEL4, // 沒 + 0x6C90, KANJI_LEVEL4, // 沐 + 0x6CC4, KANJI_LEVEL4, // 泄 + 0x6CF1, KANJI_LEVEL4, // æ³± + 0x6CD3, KANJI_LEVEL4, // 泓 + 0x6CBD, KANJI_LEVEL4, // 沜 + 0x6CD7, KANJI_LEVEL4, // 泗 + 0x6CC5, KANJI_LEVEL4, // 泅 + 0x6CDD, KANJI_LEVEL4, // 泝 + 0x6CAE, KANJI_LEVEL4, // æ²® + 0x6CB1, KANJI_LEVEL4, // æ²± + 0x6CBE, KANJI_LEVEL4, // 沟 + 0x6CBA, KANJI_LEVEL4, // 沺 + 0x6CDB, KANJI_LEVEL4, // 泛 + 0x6CEF, KANJI_LEVEL4, // 泯 + 0x6CD9, KANJI_LEVEL4, // 泙 + 0x6CEA, KANJI_LEVEL4, // 泪 + 0x6D1F, KANJI_LEVEL4, // 掟 + 0x884D, KANJI_LEVEL4, // 衍 + 0x6D36, KANJI_LEVEL4, // 掶 + 0x6D2B, KANJI_LEVEL4, // 掫 + 0x6D3D, KANJI_LEVEL4, // 掜 + 0x6D38, KANJI_LEVEL4, // 掞 + 0x6D19, KANJI_LEVEL4, // 掙 + 0x6D35, KANJI_LEVEL4, // 掵 + 0x6D33, KANJI_LEVEL4, // 掳 + 0x6D12, KANJI_LEVEL4, // 排 + 0x6D0C, KANJI_LEVEL4, // 掌 + 0x6D63, KANJI_LEVEL4, // æµ£ + 0x6D93, KANJI_LEVEL4, // 涓 + 0x6D64, KANJI_LEVEL4, // æµ€ + 0x6D5A, KANJI_LEVEL4, // 浚 + 0x6D79, KANJI_LEVEL4, // æµ¹ + 0x6D59, KANJI_LEVEL4, // 浙 + 0x6D8E, KANJI_LEVEL4, // 涎 + 0x6D95, KANJI_LEVEL4, // 涕 + 0x6FE4, KANJI_LEVEL4, // æ¿€ + 0x6D85, KANJI_LEVEL4, // 涅 + 0x6DF9, KANJI_LEVEL4, // æ·¹ + 0x6E15, KANJI_LEVEL4, // æž• + 0x6E0A, KANJI_LEVEL4, // 枊 + 0x6DB5, KANJI_LEVEL4, // æ¶µ + 0x6DC7, KANJI_LEVEL4, // 淇 + 0x6DE6, KANJI_LEVEL4, // æ·Š + 0x6DB8, KANJI_LEVEL4, // æ¶ž + 0x6DC6, KANJI_LEVEL4, // 淆 + 0x6DEC, KANJI_LEVEL4, // æ·¬ + 0x6DDE, KANJI_LEVEL4, // 淞 + 0x6DCC, KANJI_LEVEL4, // 淌 + 0x6DE8, KANJI_LEVEL4, // æ·š + 0x6DD2, KANJI_LEVEL4, // 淒 + 0x6DC5, KANJI_LEVEL4, // 淅 + 0x6DFA, KANJI_LEVEL4, // æ·º + 0x6DD9, KANJI_LEVEL4, // 淙 + 0x6DE4, KANJI_LEVEL4, // æ·€ + 0x6DD5, KANJI_LEVEL4, // 淕 + 0x6DEA, KANJI_LEVEL4, // æ·ª + 0x6DEE, KANJI_LEVEL4, // æ·® + 0x6E2D, KANJI_LEVEL4, // æž­ + 0x6E6E, KANJI_LEVEL4, // æ¹® + 0x6E2E, KANJI_LEVEL4, // æž® + 0x6E19, KANJI_LEVEL4, // æž™ + 0x6E72, KANJI_LEVEL4, // æ¹² + 0x6E5F, KANJI_LEVEL4, // 湟 + 0x6E3E, KANJI_LEVEL4, // 枟 + 0x6E23, KANJI_LEVEL4, // 枣 + 0x6E6B, KANJI_LEVEL4, // 湫 + 0x6E2B, KANJI_LEVEL4, // æž« + 0x6E76, KANJI_LEVEL4, // æ¹¶ + 0x6E4D, KANJI_LEVEL4, // 湍 + 0x6E1F, KANJI_LEVEL4, // 枟 + 0x6E43, KANJI_LEVEL4, // 湃 + 0x6E3A, KANJI_LEVEL4, // 枺 + 0x6E4E, KANJI_LEVEL4, // 湎 + 0x6E24, KANJI_LEVEL4, // 枀 + 0x6EFF, KANJI_LEVEL4, // 滿 + 0x6E1D, KANJI_LEVEL4, // 枝 + 0x6E38, KANJI_LEVEL4, // æžž + 0x6E82, KANJI_LEVEL4, // 溂 + 0x6EAA, KANJI_LEVEL4, // 溪 + 0x6E98, KANJI_LEVEL4, // 溘 + 0x6EC9, KANJI_LEVEL4, // 滉 + 0x6EB7, KANJI_LEVEL4, // 溷 + 0x6ED3, KANJI_LEVEL4, // 滓 + 0x6EBD, KANJI_LEVEL4, // 溜 + 0x6EAF, KANJI_LEVEL4, // 溯 + 0x6EC4, KANJI_LEVEL4, // 滄 + 0x6EB2, KANJI_LEVEL4, // 溲 + 0x6ED4, KANJI_LEVEL4, // 滔 + 0x6ED5, KANJI_LEVEL4, // 滕 + 0x6E8F, KANJI_LEVEL4, // 溏 + 0x6EA5, KANJI_LEVEL4, // 溥 + 0x6EC2, KANJI_LEVEL4, // 滂 + 0x6E9F, KANJI_LEVEL4, // 溟 + 0x6F41, KANJI_LEVEL4, // 朁 + 0x6F11, KANJI_LEVEL4, // 挑 + 0x704C, KANJI_LEVEL4, // 灌 + 0x6EEC, KANJI_LEVEL4, // 滬 + 0x6EF8, KANJI_LEVEL4, // 滞 + 0x6EFE, KANJI_LEVEL4, // 滟 + 0x6F3F, KANJI_LEVEL4, // 挿 + 0x6EF2, KANJI_LEVEL4, // 滲 + 0x6F31, KANJI_LEVEL4, // 挱 + 0x6EEF, KANJI_LEVEL4, // 滯 + 0x6F32, KANJI_LEVEL4, // 挲 + 0x6ECC, KANJI_LEVEL4, // 滌 + 0x6F3E, KANJI_LEVEL4, // 挟 + 0x6F13, KANJI_LEVEL4, // 挓 + 0x6EF7, KANJI_LEVEL4, // æ»· + 0x6F86, KANJI_LEVEL4, // 柆 + 0x6F7A, KANJI_LEVEL4, // 机 + 0x6F78, KANJI_LEVEL4, // 朞 + 0x6F81, KANJI_LEVEL4, // 柁 + 0x6F80, KANJI_LEVEL4, // 柀 + 0x6F6F, KANJI_LEVEL4, // 术 + 0x6F5B, KANJI_LEVEL4, // 望 + 0x6FF3, KANJI_LEVEL4, // 濳 + 0x6F6D, KANJI_LEVEL4, // 札 + 0x6F82, KANJI_LEVEL4, // 柂 + 0x6F7C, KANJI_LEVEL4, // 朌 + 0x6F58, KANJI_LEVEL4, // 朘 + 0x6F8E, KANJI_LEVEL4, // 柎 + 0x6F91, KANJI_LEVEL4, // 柑 + 0x6FC2, KANJI_LEVEL4, // 濂 + 0x6F66, KANJI_LEVEL4, // 朊 + 0x6FB3, KANJI_LEVEL4, // 柳 + 0x6FA3, KANJI_LEVEL4, // 柣 + 0x6FA1, KANJI_LEVEL4, // 柡 + 0x6FA4, KANJI_LEVEL4, // 柀 + 0x6FB9, KANJI_LEVEL4, // 柹 + 0x6FC6, KANJI_LEVEL4, // 濆 + 0x6FAA, KANJI_LEVEL4, // 柪 + 0x6FDF, KANJI_LEVEL4, // 濟 + 0x6FD5, KANJI_LEVEL4, // 濕 + 0x6FEC, KANJI_LEVEL4, // 濬 + 0x6FD4, KANJI_LEVEL4, // 濔 + 0x6FD8, KANJI_LEVEL4, // 濘 + 0x6FF1, KANJI_LEVEL4, // 濱 + 0x6FEE, KANJI_LEVEL4, // æ¿® + 0x6FDB, KANJI_LEVEL4, // 濛 + 0x7009, KANJI_LEVEL4, // 瀉 + 0x700B, KANJI_LEVEL4, // 瀋 + 0x6FFA, KANJI_LEVEL4, // 濺 + 0x7011, KANJI_LEVEL4, // 瀑 + 0x7001, KANJI_LEVEL4, // 瀁 + 0x700F, KANJI_LEVEL4, // 瀏 + 0x6FFE, KANJI_LEVEL4, // 濟 + 0x701B, KANJI_LEVEL4, // 瀛 + 0x701A, KANJI_LEVEL4, // 瀚 + 0x6F74, KANJI_LEVEL4, // 朎 + 0x701D, KANJI_LEVEL4, // 瀝 + 0x7018, KANJI_LEVEL4, // 瀘 + 0x701F, KANJI_LEVEL4, // 瀟 + 0x7030, KANJI_LEVEL4, // 瀰 + 0x703E, KANJI_LEVEL4, // 瀟 + 0x7032, KANJI_LEVEL4, // 瀲 + 0x7051, KANJI_LEVEL4, // 灑 + 0x7063, KANJI_LEVEL4, // 灣 + 0x7099, KANJI_LEVEL4, // 炙 + 0x7092, KANJI_LEVEL4, // 炒 + 0x70AF, KANJI_LEVEL4, // 炯 + 0x70F1, KANJI_LEVEL4, // 烱 + 0x70AC, KANJI_LEVEL4, // 炬 + 0x70B8, KANJI_LEVEL4, // 炾 + 0x70B3, KANJI_LEVEL4, // 炳 + 0x70AE, KANJI_LEVEL4, // 炮 + 0x70DF, KANJI_LEVEL4, // 烟 + 0x70CB, KANJI_LEVEL4, // 烋 + 0x70DD, KANJI_LEVEL4, // 烝 + 0x70D9, KANJI_LEVEL4, // 烙 + 0x7109, KANJI_LEVEL4, // 焉 + 0x70FD, KANJI_LEVEL4, // 烜 + 0x711C, KANJI_LEVEL4, // 焜 + 0x7119, KANJI_LEVEL4, // 焙 + 0x7165, KANJI_LEVEL4, // 煥 + 0x7155, KANJI_LEVEL4, // 煕 + 0x7188, KANJI_LEVEL4, // 熈 + 0x7166, KANJI_LEVEL4, // 煩 + 0x7162, KANJI_LEVEL4, // 煢 + 0x714C, KANJI_LEVEL4, // 煌 + 0x7156, KANJI_LEVEL4, // 煖 + 0x716C, KANJI_LEVEL4, // 煬 + 0x718F, KANJI_LEVEL4, // 熏 + 0x71FB, KANJI_LEVEL4, // 燻 + 0x7184, KANJI_LEVEL4, // 熄 + 0x7195, KANJI_LEVEL4, // 熕 + 0x71A8, KANJI_LEVEL4, // 熹 + 0x71AC, KANJI_LEVEL4, // 熬 + 0x71D7, KANJI_LEVEL4, // 燗 + 0x71B9, KANJI_LEVEL4, // 熹 + 0x71BE, KANJI_LEVEL4, // 熟 + 0x71D2, KANJI_LEVEL4, // 燒 + 0x71C9, KANJI_LEVEL4, // 燉 + 0x71D4, KANJI_LEVEL4, // 燔 + 0x71CE, KANJI_LEVEL4, // 燎 + 0x71E0, KANJI_LEVEL4, // 燠 + 0x71EC, KANJI_LEVEL4, // 燬 + 0x71E7, KANJI_LEVEL4, // 燧 + 0x71F5, KANJI_LEVEL4, // 燵 + 0x71FC, KANJI_LEVEL4, // 燌 + 0x71F9, KANJI_LEVEL4, // 燹 + 0x71FF, KANJI_LEVEL4, // 燿 + 0x720D, KANJI_LEVEL4, // 爍 + 0x7210, KANJI_LEVEL4, // 爐 + 0x721B, KANJI_LEVEL4, // 爛 + 0x7228, KANJI_LEVEL4, // 爚 + 0x722D, KANJI_LEVEL4, // 爭 + 0x722C, KANJI_LEVEL4, // 爬 + 0x7230, KANJI_LEVEL4, // 爰 + 0x7232, KANJI_LEVEL4, // 爲 + 0x723B, KANJI_LEVEL4, // 爻 + 0x723C, KANJI_LEVEL4, // 爌 + 0x723F, KANJI_LEVEL4, // 爿 + 0x7240, KANJI_LEVEL4, // 牀 + 0x7246, KANJI_LEVEL4, // 牆 + 0x724B, KANJI_LEVEL4, // 牋 + 0x7258, KANJI_LEVEL4, // 牘 + 0x7274, KANJI_LEVEL4, // 牮 + 0x727E, KANJI_LEVEL4, // 牟 + 0x7282, KANJI_LEVEL4, // 犂 + 0x7281, KANJI_LEVEL4, // 犁 + 0x7287, KANJI_LEVEL4, // 犇 + 0x7292, KANJI_LEVEL4, // 犒 + 0x7296, KANJI_LEVEL4, // 犖 + 0x72A2, KANJI_LEVEL4, // 犢 + 0x72A7, KANJI_LEVEL4, // 犧 + 0x72B9, KANJI_LEVEL4, // 犹 + 0x72B2, KANJI_LEVEL4, // 犲 + 0x72C3, KANJI_LEVEL4, // 狃 + 0x72C6, KANJI_LEVEL4, // 狆 + 0x72C4, KANJI_LEVEL4, // 狄 + 0x72CE, KANJI_LEVEL4, // 狎 + 0x72D2, KANJI_LEVEL4, // 狒 + 0x72E2, KANJI_LEVEL4, // 狢 + 0x72E0, KANJI_LEVEL4, // 狠 + 0x72E1, KANJI_LEVEL4, // 狡 + 0x72F9, KANJI_LEVEL4, // 狹 + 0x72F7, KANJI_LEVEL4, // 狷 + 0x500F, KANJI_LEVEL4, // 倏 + 0x7317, KANJI_LEVEL4, // 猗 + 0x730A, KANJI_LEVEL4, // 猊 + 0x731C, KANJI_LEVEL4, // 猜 + 0x7316, KANJI_LEVEL4, // 猖 + 0x731D, KANJI_LEVEL4, // 猝 + 0x7334, KANJI_LEVEL4, // 献 + 0x732F, KANJI_LEVEL4, // 猯 + 0x7329, KANJI_LEVEL4, // 猩 + 0x7325, KANJI_LEVEL4, // 猥 + 0x733E, KANJI_LEVEL4, // 猟 + 0x734E, KANJI_LEVEL4, // 獎 + 0x734F, KANJI_LEVEL4, // 獏 + 0x9ED8, KANJI_LEVEL4, // 默 + 0x7357, KANJI_LEVEL4, // 獗 + 0x736A, KANJI_LEVEL4, // 獪 + 0x7368, KANJI_LEVEL4, // 獚 + 0x7370, KANJI_LEVEL4, // 獰 + 0x7378, KANJI_LEVEL4, // 獞 + 0x7375, KANJI_LEVEL4, // 獵 + 0x737B, KANJI_LEVEL4, // 獻 + 0x737A, KANJI_LEVEL4, // 獺 + 0x73C8, KANJI_LEVEL4, // 珈 + 0x73B3, KANJI_LEVEL4, // 玳 + 0x73CE, KANJI_LEVEL4, // 珎 + 0x73BB, KANJI_LEVEL4, // 玻 + 0x73C0, KANJI_LEVEL4, // 珀 + 0x73E5, KANJI_LEVEL4, // 珥 + 0x73EE, KANJI_LEVEL4, // 珮 + 0x73DE, KANJI_LEVEL4, // 珞 + 0x74A2, KANJI_LEVEL4, // 璢 + 0x7405, KANJI_LEVEL4, // 琅 + 0x746F, KANJI_LEVEL4, // 瑯 + 0x7425, KANJI_LEVEL4, // 琥 + 0x73F8, KANJI_LEVEL4, // 珞 + 0x7432, KANJI_LEVEL4, // 琲 + 0x743A, KANJI_LEVEL4, // 琺 + 0x7455, KANJI_LEVEL4, // 瑕 + 0x743F, KANJI_LEVEL4, // 琿 + 0x745F, KANJI_LEVEL4, // 瑟 + 0x7459, KANJI_LEVEL4, // 瑙 + 0x7441, KANJI_LEVEL4, // 瑁 + 0x745C, KANJI_LEVEL4, // 瑜 + 0x7469, KANJI_LEVEL4, // 瑩 + 0x7470, KANJI_LEVEL4, // 瑰 + 0x7463, KANJI_LEVEL4, // 瑣 + 0x746A, KANJI_LEVEL4, // 瑪 + 0x7476, KANJI_LEVEL4, // 瑶 + 0x747E, KANJI_LEVEL4, // 瑟 + 0x748B, KANJI_LEVEL4, // 璋 + 0x749E, KANJI_LEVEL4, // 璞 + 0x74A7, KANJI_LEVEL4, // 璧 + 0x74CA, KANJI_LEVEL4, // 瓊 + 0x74CF, KANJI_LEVEL4, // 瓏 + 0x74D4, KANJI_LEVEL4, // 瓔 + 0x73F1, KANJI_LEVEL4, // 珱 + 0x74E0, KANJI_LEVEL4, // 瓠 + 0x74E3, KANJI_LEVEL4, // 瓣 + 0x74E7, KANJI_LEVEL4, // 瓧 + 0x74E9, KANJI_LEVEL4, // 瓩 + 0x74EE, KANJI_LEVEL4, // 瓮 + 0x74F2, KANJI_LEVEL4, // 瓲 + 0x74F0, KANJI_LEVEL4, // 瓰 + 0x74F1, KANJI_LEVEL4, // 瓱 + 0x74F8, KANJI_LEVEL4, // 瓾 + 0x74F7, KANJI_LEVEL4, // 瓷 + 0x7504, KANJI_LEVEL4, // 甄 + 0x7503, KANJI_LEVEL4, // 甃 + 0x7505, KANJI_LEVEL4, // 甅 + 0x750C, KANJI_LEVEL4, // 甌 + 0x750E, KANJI_LEVEL4, // 甎 + 0x750D, KANJI_LEVEL4, // 甍 + 0x7515, KANJI_LEVEL4, // 甕 + 0x7513, KANJI_LEVEL4, // 甓 + 0x751E, KANJI_LEVEL4, // 甞 + 0x7526, KANJI_LEVEL4, // 甩 + 0x752C, KANJI_LEVEL4, // 甬 + 0x753C, KANJI_LEVEL4, // 甌 + 0x7544, KANJI_LEVEL4, // 畄 + 0x754D, KANJI_LEVEL4, // 畍 + 0x754A, KANJI_LEVEL4, // 畊 + 0x7549, KANJI_LEVEL4, // 畉 + 0x755B, KANJI_LEVEL4, // 畛 + 0x7546, KANJI_LEVEL4, // 畆 + 0x755A, KANJI_LEVEL4, // 畚 + 0x7569, KANJI_LEVEL4, // 畩 + 0x7564, KANJI_LEVEL4, // ç•€ + 0x7567, KANJI_LEVEL4, // 畧 + 0x756B, KANJI_LEVEL4, // 畫 + 0x756D, KANJI_LEVEL4, // 畭 + 0x7578, KANJI_LEVEL4, // 畾 + 0x7576, KANJI_LEVEL4, // 當 + 0x7586, KANJI_LEVEL4, // 疆 + 0x7587, KANJI_LEVEL4, // 疇 + 0x7574, KANJI_LEVEL4, // 畮 + 0x758A, KANJI_LEVEL4, // 疊 + 0x7589, KANJI_LEVEL4, // 疉 + 0x7582, KANJI_LEVEL4, // 疂 + 0x7594, KANJI_LEVEL4, // 疔 + 0x759A, KANJI_LEVEL4, // 疚 + 0x759D, KANJI_LEVEL4, // 疝 + 0x75A5, KANJI_LEVEL4, // 疥 + 0x75A3, KANJI_LEVEL4, // 疣 + 0x75C2, KANJI_LEVEL4, // 痂 + 0x75B3, KANJI_LEVEL4, // 疳 + 0x75C3, KANJI_LEVEL4, // 痃 + 0x75B5, KANJI_LEVEL4, // 疵 + 0x75BD, KANJI_LEVEL4, // ç–œ + 0x75B8, KANJI_LEVEL4, // 疾 + 0x75BC, KANJI_LEVEL4, // ç–Œ + 0x75B1, KANJI_LEVEL4, // 疱 + 0x75CD, KANJI_LEVEL4, // 痍 + 0x75CA, KANJI_LEVEL4, // 痊 + 0x75D2, KANJI_LEVEL4, // 痒 + 0x75D9, KANJI_LEVEL4, // 痙 + 0x75E3, KANJI_LEVEL4, // 痣 + 0x75DE, KANJI_LEVEL4, // 痞 + 0x75FE, KANJI_LEVEL4, // ç—Ÿ + 0x75FF, KANJI_LEVEL4, // 痿 + 0x75FC, KANJI_LEVEL4, // ç—Œ + 0x7601, KANJI_LEVEL4, // 瘁 + 0x75F0, KANJI_LEVEL4, // 痰 + 0x75FA, KANJI_LEVEL4, // 痺 + 0x75F2, KANJI_LEVEL4, // 痲 + 0x75F3, KANJI_LEVEL4, // 痳 + 0x760B, KANJI_LEVEL4, // 瘋 + 0x760D, KANJI_LEVEL4, // 瘍 + 0x7609, KANJI_LEVEL4, // 瘉 + 0x761F, KANJI_LEVEL4, // 瘟 + 0x7627, KANJI_LEVEL4, // 瘧 + 0x7620, KANJI_LEVEL4, // 瘠 + 0x7621, KANJI_LEVEL4, // 瘡 + 0x7622, KANJI_LEVEL4, // 瘢 + 0x7624, KANJI_LEVEL4, // 瘀 + 0x7634, KANJI_LEVEL4, // 瘎 + 0x7630, KANJI_LEVEL4, // 瘰 + 0x763B, KANJI_LEVEL4, // 瘻 + 0x7647, KANJI_LEVEL4, // 癇 + 0x7648, KANJI_LEVEL4, // 癈 + 0x7646, KANJI_LEVEL4, // 癆 + 0x765C, KANJI_LEVEL4, // 癜 + 0x7658, KANJI_LEVEL4, // 癘 + 0x7661, KANJI_LEVEL4, // 癡 + 0x7662, KANJI_LEVEL4, // 癢 + 0x7668, KANJI_LEVEL4, // 癹 + 0x7669, KANJI_LEVEL4, // 癩 + 0x766A, KANJI_LEVEL4, // 癪 + 0x7667, KANJI_LEVEL4, // 癧 + 0x766C, KANJI_LEVEL4, // 癬 + 0x7670, KANJI_LEVEL4, // 癰 + 0x7672, KANJI_LEVEL4, // 癲 + 0x7676, KANJI_LEVEL4, // 癶 + 0x7678, KANJI_LEVEL4, // 百 + 0x767C, KANJI_LEVEL4, // 癌 + 0x7680, KANJI_LEVEL4, // 皀 + 0x7683, KANJI_LEVEL4, // 皃 + 0x7688, KANJI_LEVEL4, // 皈 + 0x768B, KANJI_LEVEL4, // 皋 + 0x768E, KANJI_LEVEL4, // 皎 + 0x7696, KANJI_LEVEL4, // 皖 + 0x7693, KANJI_LEVEL4, // 皓 + 0x7699, KANJI_LEVEL4, // 皙 + 0x769A, KANJI_LEVEL4, // 皚 + 0x76B0, KANJI_LEVEL4, // 皰 + 0x76B4, KANJI_LEVEL4, // 皮 + 0x76B8, KANJI_LEVEL4, // 皾 + 0x76B9, KANJI_LEVEL4, // 皹 + 0x76BA, KANJI_LEVEL4, // 皺 + 0x76C2, KANJI_LEVEL4, // 盂 + 0x76CD, KANJI_LEVEL4, // 盍 + 0x76D6, KANJI_LEVEL4, // 盖 + 0x76D2, KANJI_LEVEL4, // 盒 + 0x76DE, KANJI_LEVEL4, // 盞 + 0x76E1, KANJI_LEVEL4, // 盡 + 0x76E5, KANJI_LEVEL4, // 盥 + 0x76E7, KANJI_LEVEL4, // 盧 + 0x76EA, KANJI_LEVEL4, // 盪 + 0x862F, KANJI_LEVEL4, // 蘯 + 0x76FB, KANJI_LEVEL4, // 盻 + 0x7708, KANJI_LEVEL4, // 眈 + 0x7707, KANJI_LEVEL4, // 眇 + 0x7704, KANJI_LEVEL4, // 眄 + 0x7729, KANJI_LEVEL4, // 眩 + 0x7724, KANJI_LEVEL4, // 眀 + 0x771E, KANJI_LEVEL4, // 眞 + 0x7725, KANJI_LEVEL4, // 眥 + 0x7726, KANJI_LEVEL4, // 眩 + 0x771B, KANJI_LEVEL4, // 眛 + 0x7737, KANJI_LEVEL4, // 眷 + 0x7738, KANJI_LEVEL4, // 眾 + 0x7747, KANJI_LEVEL4, // 睇 + 0x775A, KANJI_LEVEL4, // 睚 + 0x7768, KANJI_LEVEL4, // 睚 + 0x776B, KANJI_LEVEL4, // 睫 + 0x775B, KANJI_LEVEL4, // 睛 + 0x7765, KANJI_LEVEL4, // 睥 + 0x777F, KANJI_LEVEL4, // 睿 + 0x777E, KANJI_LEVEL4, // 睟 + 0x7779, KANJI_LEVEL4, // 睹 + 0x778E, KANJI_LEVEL4, // 瞎 + 0x778B, KANJI_LEVEL4, // 瞋 + 0x7791, KANJI_LEVEL4, // 瞑 + 0x77A0, KANJI_LEVEL4, // 瞠 + 0x779E, KANJI_LEVEL4, // 瞞 + 0x77B0, KANJI_LEVEL4, // 瞰 + 0x77B6, KANJI_LEVEL4, // 瞶 + 0x77B9, KANJI_LEVEL4, // 瞹 + 0x77BF, KANJI_LEVEL4, // 瞿 + 0x77BC, KANJI_LEVEL4, // 瞌 + 0x77BD, KANJI_LEVEL4, // 瞜 + 0x77BB, KANJI_LEVEL4, // 瞻 + 0x77C7, KANJI_LEVEL4, // 矇 + 0x77CD, KANJI_LEVEL4, // 矍 + 0x77D7, KANJI_LEVEL4, // 矗 + 0x77DA, KANJI_LEVEL4, // 矚 + 0x77DC, KANJI_LEVEL4, // 矜 + 0x77E3, KANJI_LEVEL4, // 矣 + 0x77EE, KANJI_LEVEL4, // 矮 + 0x77FC, KANJI_LEVEL4, // 矌 + 0x780C, KANJI_LEVEL4, // 砌 + 0x7812, KANJI_LEVEL4, // 砒 + 0x7926, KANJI_LEVEL4, // 瀊 + 0x7820, KANJI_LEVEL4, // ç   + 0x792A, KANJI_LEVEL4, // 瀪 + 0x7845, KANJI_LEVEL4, // 硅 + 0x788E, KANJI_LEVEL4, // 碎 + 0x7874, KANJI_LEVEL4, // 硎 + 0x7886, KANJI_LEVEL4, // 碆 + 0x787C, KANJI_LEVEL4, // 硌 + 0x789A, KANJI_LEVEL4, // 碚 + 0x788C, KANJI_LEVEL4, // 碌 + 0x78A3, KANJI_LEVEL4, // 碣 + 0x78B5, KANJI_LEVEL4, // 碵 + 0x78AA, KANJI_LEVEL4, // 碪 + 0x78AF, KANJI_LEVEL4, // 碯 + 0x78D1, KANJI_LEVEL4, // 磑 + 0x78C6, KANJI_LEVEL4, // 磆 + 0x78CB, KANJI_LEVEL4, // 磋 + 0x78D4, KANJI_LEVEL4, // 磔 + 0x78BE, KANJI_LEVEL4, // 碟 + 0x78BC, KANJI_LEVEL4, // 碌 + 0x78C5, KANJI_LEVEL4, // 磅 + 0x78CA, KANJI_LEVEL4, // 磊 + 0x78EC, KANJI_LEVEL4, // 磬 + 0x78E7, KANJI_LEVEL4, // 磧 + 0x78DA, KANJI_LEVEL4, // 磚 + 0x78FD, KANJI_LEVEL4, // 磜 + 0x78F4, KANJI_LEVEL4, // 磎 + 0x7907, KANJI_LEVEL4, // 瀇 + 0x7912, KANJI_LEVEL4, // 瀒 + 0x7911, KANJI_LEVEL4, // 瀑 + 0x7919, KANJI_LEVEL4, // 瀙 + 0x792C, KANJI_LEVEL4, // 瀬 + 0x792B, KANJI_LEVEL4, // 瀫 + 0x7940, KANJI_LEVEL4, // 祀 + 0x7960, KANJI_LEVEL4, // 祠 + 0x7957, KANJI_LEVEL4, // 祗 + 0x795F, KANJI_LEVEL4, // 祟 + 0x795A, KANJI_LEVEL4, // 祚 + 0x7955, KANJI_LEVEL4, // 祕 + 0x7953, KANJI_LEVEL4, // 祓 + 0x797A, KANJI_LEVEL4, // 祺 + 0x797F, KANJI_LEVEL4, // 祿 + 0x798A, KANJI_LEVEL4, // 穊 + 0x799D, KANJI_LEVEL4, // 犝 + 0x79A7, KANJI_LEVEL4, // 犧 + 0x9F4B, KANJI_LEVEL4, // 霋 + 0x79AA, KANJI_LEVEL4, // 犪 + 0x79AE, KANJI_LEVEL4, // 犮 + 0x79B3, KANJI_LEVEL4, // 犳 + 0x79B9, KANJI_LEVEL4, // 犹 + 0x79BA, KANJI_LEVEL4, // 犺 + 0x79C9, KANJI_LEVEL4, // 秉 + 0x79D5, KANJI_LEVEL4, // 秕 + 0x79E7, KANJI_LEVEL4, // ç§§ + 0x79EC, KANJI_LEVEL4, // 秬 + 0x79E1, KANJI_LEVEL4, // ç§¡ + 0x79E3, KANJI_LEVEL4, // ç§£ + 0x7A08, KANJI_LEVEL4, // 皈 + 0x7A0D, KANJI_LEVEL4, // 皍 + 0x7A18, KANJI_LEVEL4, // 皘 + 0x7A19, KANJI_LEVEL4, // 繙 + 0x7A20, KANJI_LEVEL4, // çš  + 0x7A1F, KANJI_LEVEL4, // 繟 + 0x7980, KANJI_LEVEL4, // 穀 + 0x7A31, KANJI_LEVEL4, // çš± + 0x7A3B, KANJI_LEVEL4, // çš» + 0x7A3E, KANJI_LEVEL4, // 皟 + 0x7A37, KANJI_LEVEL4, // çš· + 0x7A43, KANJI_LEVEL4, // 穃 + 0x7A57, KANJI_LEVEL4, // 穗 + 0x7A49, KANJI_LEVEL4, // 穉 + 0x7A61, KANJI_LEVEL4, // ç©¡ + 0x7A62, KANJI_LEVEL4, // ç©¢ + 0x7A69, KANJI_LEVEL4, // ç©© + 0x9F9D, KANJI_LEVEL4, // 韝 + 0x7A70, KANJI_LEVEL4, // ç©° + 0x7A79, KANJI_LEVEL4, // 穹 + 0x7A7D, KANJI_LEVEL4, // 穜 + 0x7A88, KANJI_LEVEL4, // 窈 + 0x7A97, KANJI_LEVEL4, // 窗 + 0x7A95, KANJI_LEVEL4, // 窕 + 0x7A98, KANJI_LEVEL4, // 窘 + 0x7A96, KANJI_LEVEL4, // 窖 + 0x7AA9, KANJI_LEVEL4, // 窩 + 0x7AC8, KANJI_LEVEL4, // 竈 + 0x7AB0, KANJI_LEVEL4, // 窰 + 0x7AB6, KANJI_LEVEL4, // 窶 + 0x7AC5, KANJI_LEVEL4, // 竅 + 0x7AC4, KANJI_LEVEL4, // 竄 + 0x7ABF, KANJI_LEVEL4, // 窿 + 0x9083, KANJI_LEVEL4, // 邃 + 0x7AC7, KANJI_LEVEL4, // 竇 + 0x7ACA, KANJI_LEVEL4, // 竊 + 0x7ACD, KANJI_LEVEL4, // 竍 + 0x7ACF, KANJI_LEVEL4, // 竏 + 0x7AD5, KANJI_LEVEL4, // 竕 + 0x7AD3, KANJI_LEVEL4, // 竓 + 0x7AD9, KANJI_LEVEL4, // 站 + 0x7ADA, KANJI_LEVEL4, // 竚 + 0x7ADD, KANJI_LEVEL4, // 竝 + 0x7AE1, KANJI_LEVEL4, // ç«¡ + 0x7AE2, KANJI_LEVEL4, // ç«¢ + 0x7AE6, KANJI_LEVEL4, // 竊 + 0x7AED, KANJI_LEVEL4, // ç«­ + 0x7AF0, KANJI_LEVEL4, // ç«° + 0x7B02, KANJI_LEVEL4, // 笂 + 0x7B0F, KANJI_LEVEL4, // 笏 + 0x7B0A, KANJI_LEVEL4, // 笊 + 0x7B06, KANJI_LEVEL4, // 笆 + 0x7B33, KANJI_LEVEL4, // 笳 + 0x7B18, KANJI_LEVEL4, // 笘 + 0x7B19, KANJI_LEVEL4, // 笙 + 0x7B1E, KANJI_LEVEL4, // 笞 + 0x7B35, KANJI_LEVEL4, // 笵 + 0x7B28, KANJI_LEVEL4, // 笚 + 0x7B36, KANJI_LEVEL4, // 笶 + 0x7B50, KANJI_LEVEL4, // 筐 + 0x7B7A, KANJI_LEVEL4, // ç­º + 0x7B04, KANJI_LEVEL4, // 笄 + 0x7B4D, KANJI_LEVEL4, // 筍 + 0x7B0B, KANJI_LEVEL4, // 笋 + 0x7B4C, KANJI_LEVEL4, // 筌 + 0x7B45, KANJI_LEVEL4, // 筅 + 0x7B75, KANJI_LEVEL4, // ç­µ + 0x7B65, KANJI_LEVEL4, // ç­¥ + 0x7B74, KANJI_LEVEL4, // ç­Ž + 0x7B67, KANJI_LEVEL4, // ç­§ + 0x7B70, KANJI_LEVEL4, // ç­° + 0x7B71, KANJI_LEVEL4, // ç­± + 0x7B6C, KANJI_LEVEL4, // ç­¬ + 0x7B6E, KANJI_LEVEL4, // ç­® + 0x7B9D, KANJI_LEVEL4, // 箝 + 0x7B98, KANJI_LEVEL4, // 箘 + 0x7B9F, KANJI_LEVEL4, // 箟 + 0x7B8D, KANJI_LEVEL4, // 箍 + 0x7B9C, KANJI_LEVEL4, // 箜 + 0x7B9A, KANJI_LEVEL4, // 箚 + 0x7B8B, KANJI_LEVEL4, // 箋 + 0x7B92, KANJI_LEVEL4, // 箒 + 0x7B8F, KANJI_LEVEL4, // 箏 + 0x7B5D, KANJI_LEVEL4, // 筝 + 0x7B99, KANJI_LEVEL4, // 箙 + 0x7BCB, KANJI_LEVEL4, // 篋 + 0x7BC1, KANJI_LEVEL4, // 篁 + 0x7BCC, KANJI_LEVEL4, // 篌 + 0x7BCF, KANJI_LEVEL4, // 篏 + 0x7BB4, KANJI_LEVEL4, // 箎 + 0x7BC6, KANJI_LEVEL4, // 篆 + 0x7BDD, KANJI_LEVEL4, // 篝 + 0x7BE9, KANJI_LEVEL4, // 篩 + 0x7C11, KANJI_LEVEL4, // 簑 + 0x7C14, KANJI_LEVEL4, // 簔 + 0x7BE6, KANJI_LEVEL4, // 篊 + 0x7BE5, KANJI_LEVEL4, // 篥 + 0x7C60, KANJI_LEVEL4, // ç±  + 0x7C00, KANJI_LEVEL4, // 簀 + 0x7C07, KANJI_LEVEL4, // 簇 + 0x7C13, KANJI_LEVEL4, // 簓 + 0x7BF3, KANJI_LEVEL4, // 篳 + 0x7BF7, KANJI_LEVEL4, // 篷 + 0x7C17, KANJI_LEVEL4, // 簗 + 0x7C0D, KANJI_LEVEL4, // 簍 + 0x7BF6, KANJI_LEVEL4, // 篶 + 0x7C23, KANJI_LEVEL4, // ç°£ + 0x7C27, KANJI_LEVEL4, // ç°§ + 0x7C2A, KANJI_LEVEL4, // ç°ª + 0x7C1F, KANJI_LEVEL4, // 簟 + 0x7C37, KANJI_LEVEL4, // ç°· + 0x7C2B, KANJI_LEVEL4, // ç°« + 0x7C3D, KANJI_LEVEL4, // ç°œ + 0x7C4C, KANJI_LEVEL4, // 籌 + 0x7C43, KANJI_LEVEL4, // 籃 + 0x7C54, KANJI_LEVEL4, // 籔 + 0x7C4F, KANJI_LEVEL4, // 籏 + 0x7C40, KANJI_LEVEL4, // 籀 + 0x7C50, KANJI_LEVEL4, // 籐 + 0x7C58, KANJI_LEVEL4, // 籘 + 0x7C5F, KANJI_LEVEL4, // 籟 + 0x7C64, KANJI_LEVEL4, // ç±€ + 0x7C56, KANJI_LEVEL4, // 籖 + 0x7C65, KANJI_LEVEL4, // ç±¥ + 0x7C6C, KANJI_LEVEL4, // 籬 + 0x7C75, KANJI_LEVEL4, // ç±µ + 0x7C83, KANJI_LEVEL4, // 粃 + 0x7C90, KANJI_LEVEL4, // 粐 + 0x7CA4, KANJI_LEVEL4, // ç²€ + 0x7CAD, KANJI_LEVEL4, // ç²­ + 0x7CA2, KANJI_LEVEL4, // ç²¢ + 0x7CAB, KANJI_LEVEL4, // 粫 + 0x7CA1, KANJI_LEVEL4, // 粡 + 0x7CA8, KANJI_LEVEL4, // 粚 + 0x7CB3, KANJI_LEVEL4, // ç²³ + 0x7CB2, KANJI_LEVEL4, // ç²² + 0x7CB1, KANJI_LEVEL4, // ç²± + 0x7CAE, KANJI_LEVEL4, // ç²® + 0x7CB9, KANJI_LEVEL4, // ç²¹ + 0x7CBD, KANJI_LEVEL4, // 粜 + 0x7CC0, KANJI_LEVEL4, // 糀 + 0x7CC5, KANJI_LEVEL4, // 糅 + 0x7CC2, KANJI_LEVEL4, // 糂 + 0x7CD8, KANJI_LEVEL4, // 糘 + 0x7CD2, KANJI_LEVEL4, // 糒 + 0x7CDC, KANJI_LEVEL4, // 糜 + 0x7CE2, KANJI_LEVEL4, // ç³¢ + 0x9B3B, KANJI_LEVEL4, // 鬻 + 0x7CEF, KANJI_LEVEL4, // 糯 + 0x7CF2, KANJI_LEVEL4, // ç³² + 0x7CF4, KANJI_LEVEL4, // 糎 + 0x7CF6, KANJI_LEVEL4, // ç³¶ + 0x7CFA, KANJI_LEVEL4, // 糺 + 0x7D06, KANJI_LEVEL4, // 箆 + 0x7D02, KANJI_LEVEL4, // 箂 + 0x7D1C, KANJI_LEVEL4, // 箜 + 0x7D15, KANJI_LEVEL4, // 箕 + 0x7D0A, KANJI_LEVEL4, // 箊 + 0x7D45, KANJI_LEVEL4, // 絅 + 0x7D4B, KANJI_LEVEL4, // 絋 + 0x7D2E, KANJI_LEVEL4, // 玮 + 0x7D32, KANJI_LEVEL4, // 玲 + 0x7D3F, KANJI_LEVEL4, // 玿 + 0x7D35, KANJI_LEVEL4, // 玵 + 0x7D46, KANJI_LEVEL4, // 絆 + 0x7D73, KANJI_LEVEL4, // çµ³ + 0x7D56, KANJI_LEVEL4, // 絖 + 0x7D4E, KANJI_LEVEL4, // 絎 + 0x7D72, KANJI_LEVEL4, // çµ² + 0x7D68, KANJI_LEVEL4, // 絚 + 0x7D6E, KANJI_LEVEL4, // çµ® + 0x7D4F, KANJI_LEVEL4, // 絏 + 0x7D63, KANJI_LEVEL4, // çµ£ + 0x7D93, KANJI_LEVEL4, // 經 + 0x7D89, KANJI_LEVEL4, // 綉 + 0x7D5B, KANJI_LEVEL4, // 絛 + 0x7D8F, KANJI_LEVEL4, // 綏 + 0x7D7D, KANJI_LEVEL4, // 絜 + 0x7D9B, KANJI_LEVEL4, // 綛 + 0x7DBA, KANJI_LEVEL4, // 綺 + 0x7DAE, KANJI_LEVEL4, // ç¶® + 0x7DA3, KANJI_LEVEL4, // ç¶£ + 0x7DB5, KANJI_LEVEL4, // ç¶µ + 0x7DC7, KANJI_LEVEL4, // 緇 + 0x7DBD, KANJI_LEVEL4, // ç¶œ + 0x7DAB, KANJI_LEVEL4, // ç¶« + 0x7E3D, KANJI_LEVEL4, // çžœ + 0x7DA2, KANJI_LEVEL4, // ç¶¢ + 0x7DAF, KANJI_LEVEL4, // 綯 + 0x7DDC, KANJI_LEVEL4, // 緜 + 0x7DB8, KANJI_LEVEL4, // ç¶ž + 0x7D9F, KANJI_LEVEL4, // 綟 + 0x7DB0, KANJI_LEVEL4, // ç¶° + 0x7DD8, KANJI_LEVEL4, // 緘 + 0x7DDD, KANJI_LEVEL4, // 緝 + 0x7DE4, KANJI_LEVEL4, // ç·€ + 0x7DDE, KANJI_LEVEL4, // 緞 + 0x7DFB, KANJI_LEVEL4, // ç·» + 0x7DF2, KANJI_LEVEL4, // ç·² + 0x7DE1, KANJI_LEVEL4, // ç·¡ + 0x7E05, KANJI_LEVEL4, // 羅 + 0x7E0A, KANJI_LEVEL4, // 羊 + 0x7E23, KANJI_LEVEL4, // 瞣 + 0x7E21, KANJI_LEVEL4, // çž¡ + 0x7E12, KANJI_LEVEL4, // 羒 + 0x7E31, KANJI_LEVEL4, // çž± + 0x7E1F, KANJI_LEVEL4, // 羟 + 0x7E09, KANJI_LEVEL4, // 羉 + 0x7E0B, KANJI_LEVEL4, // 羋 + 0x7E22, KANJI_LEVEL4, // 瞢 + 0x7E46, KANJI_LEVEL4, // 繆 + 0x7E66, KANJI_LEVEL4, // 繊 + 0x7E3B, KANJI_LEVEL4, // çž» + 0x7E35, KANJI_LEVEL4, // çžµ + 0x7E39, KANJI_LEVEL4, // çž¹ + 0x7E43, KANJI_LEVEL4, // 繃 + 0x7E37, KANJI_LEVEL4, // çž· + 0x7E32, KANJI_LEVEL4, // çž² + 0x7E3A, KANJI_LEVEL4, // 瞺 + 0x7E67, KANJI_LEVEL4, // ç¹§ + 0x7E5D, KANJI_LEVEL4, // 繝 + 0x7E56, KANJI_LEVEL4, // 繖 + 0x7E5E, KANJI_LEVEL4, // 繞 + 0x7E59, KANJI_LEVEL4, // 繙 + 0x7E5A, KANJI_LEVEL4, // 繚 + 0x7E79, KANJI_LEVEL4, // ç¹¹ + 0x7E6A, KANJI_LEVEL4, // 繪 + 0x7E69, KANJI_LEVEL4, // 繩 + 0x7E7C, KANJI_LEVEL4, // 繌 + 0x7E7B, KANJI_LEVEL4, // ç¹» + 0x7E83, KANJI_LEVEL4, // 纃 + 0x7DD5, KANJI_LEVEL4, // 緕 + 0x7E7D, KANJI_LEVEL4, // 繜 + 0x8FAE, KANJI_LEVEL4, // 蟮 + 0x7E7F, KANJI_LEVEL4, // 繿 + 0x7E88, KANJI_LEVEL4, // 纈 + 0x7E89, KANJI_LEVEL4, // 纉 + 0x7E8C, KANJI_LEVEL4, // 續 + 0x7E92, KANJI_LEVEL4, // 纒 + 0x7E90, KANJI_LEVEL4, // 纐 + 0x7E93, KANJI_LEVEL4, // 纓 + 0x7E94, KANJI_LEVEL4, // 纔 + 0x7E96, KANJI_LEVEL4, // 纖 + 0x7E8E, KANJI_LEVEL4, // 纎 + 0x7E9B, KANJI_LEVEL4, // 纛 + 0x7E9C, KANJI_LEVEL4, // 纜 + 0x7F38, KANJI_LEVEL4, // 猞 + 0x7F3A, KANJI_LEVEL4, // 猺 + 0x7F45, KANJI_LEVEL4, // 眅 + 0x7F4C, KANJI_LEVEL4, // 県 + 0x7F4D, KANJI_LEVEL4, // 眍 + 0x7F4E, KANJI_LEVEL4, // 眎 + 0x7F50, KANJI_LEVEL4, // 眐 + 0x7F51, KANJI_LEVEL4, // 眑 + 0x7F55, KANJI_LEVEL4, // 眕 + 0x7F54, KANJI_LEVEL4, // 眔 + 0x7F58, KANJI_LEVEL4, // 眘 + 0x7F5F, KANJI_LEVEL4, // 真 + 0x7F60, KANJI_LEVEL4, // 眠 + 0x7F68, KANJI_LEVEL4, // 眚 + 0x7F69, KANJI_LEVEL4, // 眩 + 0x7F67, KANJI_LEVEL4, // 眧 + 0x7F78, KANJI_LEVEL4, // 眞 + 0x7F82, KANJI_LEVEL4, // 矂 + 0x7F86, KANJI_LEVEL4, // 矆 + 0x7F83, KANJI_LEVEL4, // 矃 + 0x7F88, KANJI_LEVEL4, // 矈 + 0x7F87, KANJI_LEVEL4, // 矇 + 0x7F8C, KANJI_LEVEL4, // 矌 + 0x7F94, KANJI_LEVEL4, // 矔 + 0x7F9E, KANJI_LEVEL4, // 矞 + 0x7F9D, KANJI_LEVEL4, // 矝 + 0x7F9A, KANJI_LEVEL4, // 矚 + 0x7FA3, KANJI_LEVEL4, // 矣 + 0x7FAF, KANJI_LEVEL4, // 矯 + 0x7FB2, KANJI_LEVEL4, // 矲 + 0x7FB9, KANJI_LEVEL4, // 矹 + 0x7FAE, KANJI_LEVEL4, // 矮 + 0x7FB6, KANJI_LEVEL4, // 矶 + 0x7FB8, KANJI_LEVEL4, // 矞 + 0x8B71, KANJI_LEVEL4, // è­± + 0x7FC5, KANJI_LEVEL4, // 翅 + 0x7FC6, KANJI_LEVEL4, // 翆 + 0x7FCA, KANJI_LEVEL4, // 翊 + 0x7FD5, KANJI_LEVEL4, // 翕 + 0x7FD4, KANJI_LEVEL4, // 翔 + 0x7FE1, KANJI_LEVEL4, // ç¿¡ + 0x7FE6, KANJI_LEVEL4, // 翊 + 0x7FE9, KANJI_LEVEL4, // ç¿© + 0x7FF3, KANJI_LEVEL4, // 翳 + 0x7FF9, KANJI_LEVEL4, // 翹 + 0x98DC, KANJI_LEVEL4, // 飜 + 0x8006, KANJI_LEVEL4, // 耆 + 0x8004, KANJI_LEVEL4, // 耄 + 0x800B, KANJI_LEVEL4, // 耋 + 0x8012, KANJI_LEVEL4, // 耒 + 0x8018, KANJI_LEVEL4, // 耘 + 0x8019, KANJI_LEVEL4, // 耙 + 0x801C, KANJI_LEVEL4, // 耜 + 0x8021, KANJI_LEVEL4, // 耡 + 0x8028, KANJI_LEVEL4, // 耚 + 0x803F, KANJI_LEVEL4, // 耿 + 0x803B, KANJI_LEVEL4, // 耻 + 0x804A, KANJI_LEVEL4, // 聊 + 0x8046, KANJI_LEVEL4, // 聆 + 0x8052, KANJI_LEVEL4, // 聒 + 0x8058, KANJI_LEVEL4, // 聘 + 0x805A, KANJI_LEVEL4, // 聚 + 0x805F, KANJI_LEVEL4, // 聟 + 0x8062, KANJI_LEVEL4, // 聢 + 0x8068, KANJI_LEVEL4, // 聚 + 0x8073, KANJI_LEVEL4, // 聳 + 0x8072, KANJI_LEVEL4, // 聲 + 0x8070, KANJI_LEVEL4, // 聰 + 0x8076, KANJI_LEVEL4, // 聶 + 0x8079, KANJI_LEVEL4, // 聹 + 0x807D, KANJI_LEVEL4, // 聜 + 0x807F, KANJI_LEVEL4, // 聿 + 0x8084, KANJI_LEVEL4, // 肄 + 0x8086, KANJI_LEVEL4, // 肆 + 0x8085, KANJI_LEVEL4, // 肅 + 0x809B, KANJI_LEVEL4, // 肛 + 0x8093, KANJI_LEVEL4, // 肓 + 0x809A, KANJI_LEVEL4, // 肚 + 0x80AD, KANJI_LEVEL4, // 肭 + 0x5190, KANJI_LEVEL4, // 冐 + 0x80AC, KANJI_LEVEL4, // 肬 + 0x80DB, KANJI_LEVEL4, // 胛 + 0x80E5, KANJI_LEVEL4, // 胥 + 0x80D9, KANJI_LEVEL4, // 胙 + 0x80DD, KANJI_LEVEL4, // 胝 + 0x80C4, KANJI_LEVEL4, // 胄 + 0x80DA, KANJI_LEVEL4, // 胚 + 0x80D6, KANJI_LEVEL4, // 胖 + 0x8109, KANJI_LEVEL4, // 脉 + 0x80EF, KANJI_LEVEL4, // 胯 + 0x80F1, KANJI_LEVEL4, // 胱 + 0x811B, KANJI_LEVEL4, // 脛 + 0x8129, KANJI_LEVEL4, // 脩 + 0x8123, KANJI_LEVEL4, // 脣 + 0x812F, KANJI_LEVEL4, // 脯 + 0x814B, KANJI_LEVEL4, // 腋 + 0x968B, KANJI_LEVEL4, // 隋 + 0x8146, KANJI_LEVEL4, // 腆 + 0x813E, KANJI_LEVEL4, // 脟 + 0x8153, KANJI_LEVEL4, // 腓 + 0x8151, KANJI_LEVEL4, // 腑 + 0x80FC, KANJI_LEVEL4, // 背 + 0x8171, KANJI_LEVEL4, // 腱 + 0x816E, KANJI_LEVEL4, // 腮 + 0x8165, KANJI_LEVEL4, // 腥 + 0x8166, KANJI_LEVEL4, // è…Š + 0x8174, KANJI_LEVEL4, // è…Ž + 0x8183, KANJI_LEVEL4, // 膃 + 0x8188, KANJI_LEVEL4, // 膈 + 0x818A, KANJI_LEVEL4, // 膊 + 0x8180, KANJI_LEVEL4, // 膀 + 0x8182, KANJI_LEVEL4, // 膂 + 0x81A0, KANJI_LEVEL4, // 膠 + 0x8195, KANJI_LEVEL4, // 膕 + 0x81A4, KANJI_LEVEL4, // 膀 + 0x81A3, KANJI_LEVEL4, // 膣 + 0x815F, KANJI_LEVEL4, // 腟 + 0x8193, KANJI_LEVEL4, // 膓 + 0x81A9, KANJI_LEVEL4, // 膩 + 0x81B0, KANJI_LEVEL4, // 膰 + 0x81B5, KANJI_LEVEL4, // 膵 + 0x81BE, KANJI_LEVEL4, // 膟 + 0x81B8, KANJI_LEVEL4, // 膞 + 0x81BD, KANJI_LEVEL4, // 膜 + 0x81C0, KANJI_LEVEL4, // 臀 + 0x81C2, KANJI_LEVEL4, // 臂 + 0x81BA, KANJI_LEVEL4, // 膺 + 0x81C9, KANJI_LEVEL4, // 臉 + 0x81CD, KANJI_LEVEL4, // 臍 + 0x81D1, KANJI_LEVEL4, // 臑 + 0x81D9, KANJI_LEVEL4, // 臙 + 0x81D8, KANJI_LEVEL4, // 臘 + 0x81C8, KANJI_LEVEL4, // 臈 + 0x81DA, KANJI_LEVEL4, // 臚 + 0x81DF, KANJI_LEVEL4, // 臟 + 0x81E0, KANJI_LEVEL4, // 臠 + 0x81E7, KANJI_LEVEL4, // 臧 + 0x81FA, KANJI_LEVEL4, // 臺 + 0x81FB, KANJI_LEVEL4, // 臻 + 0x81FE, KANJI_LEVEL4, // 臟 + 0x8201, KANJI_LEVEL4, // 舁 + 0x8202, KANJI_LEVEL4, // 舂 + 0x8205, KANJI_LEVEL4, // 舅 + 0x8207, KANJI_LEVEL4, // 與 + 0x820A, KANJI_LEVEL4, // 舊 + 0x820D, KANJI_LEVEL4, // 舍 + 0x8210, KANJI_LEVEL4, // 舐 + 0x8216, KANJI_LEVEL4, // 舖 + 0x8229, KANJI_LEVEL4, // 舩 + 0x822B, KANJI_LEVEL4, // 舫 + 0x8238, KANJI_LEVEL4, // 舞 + 0x8233, KANJI_LEVEL4, // 舳 + 0x8240, KANJI_LEVEL4, // 艀 + 0x8259, KANJI_LEVEL4, // 艙 + 0x8258, KANJI_LEVEL4, // 艘 + 0x825D, KANJI_LEVEL4, // 艝 + 0x825A, KANJI_LEVEL4, // 艚 + 0x825F, KANJI_LEVEL4, // 艟 + 0x8264, KANJI_LEVEL4, // 艀 + 0x8262, KANJI_LEVEL4, // 艢 + 0x8268, KANJI_LEVEL4, // 艚 + 0x826A, KANJI_LEVEL4, // 艪 + 0x826B, KANJI_LEVEL4, // 艫 + 0x822E, KANJI_LEVEL4, // 舮 + 0x8271, KANJI_LEVEL4, // 艱 + 0x8277, KANJI_LEVEL4, // 艷 + 0x8278, KANJI_LEVEL4, // 艞 + 0x827E, KANJI_LEVEL4, // 艟 + 0x828D, KANJI_LEVEL4, // 芍 + 0x8292, KANJI_LEVEL4, // 芒 + 0x82AB, KANJI_LEVEL4, // 芫 + 0x829F, KANJI_LEVEL4, // 芟 + 0x82BB, KANJI_LEVEL4, // 芻 + 0x82AC, KANJI_LEVEL4, // 芬 + 0x82E1, KANJI_LEVEL4, // 苡 + 0x82E3, KANJI_LEVEL4, // 苣 + 0x82DF, KANJI_LEVEL4, // 苟 + 0x82D2, KANJI_LEVEL4, // 苒 + 0x82F4, KANJI_LEVEL4, // 苎 + 0x82F3, KANJI_LEVEL4, // 苳 + 0x82FA, KANJI_LEVEL4, // 苺 + 0x8393, KANJI_LEVEL4, // 莓 + 0x8303, KANJI_LEVEL4, // 范 + 0x82FB, KANJI_LEVEL4, // 苻 + 0x82F9, KANJI_LEVEL4, // 苹 + 0x82DE, KANJI_LEVEL4, // 苞 + 0x8306, KANJI_LEVEL4, // 茆 + 0x82DC, KANJI_LEVEL4, // 苜 + 0x8309, KANJI_LEVEL4, // 茉 + 0x82D9, KANJI_LEVEL4, // 苙 + 0x8335, KANJI_LEVEL4, // 茵 + 0x8334, KANJI_LEVEL4, // 茎 + 0x8316, KANJI_LEVEL4, // 茖 + 0x8332, KANJI_LEVEL4, // 茲 + 0x8331, KANJI_LEVEL4, // 茱 + 0x8340, KANJI_LEVEL4, // 荀 + 0x8339, KANJI_LEVEL4, // 茹 + 0x8350, KANJI_LEVEL4, // 荐 + 0x8345, KANJI_LEVEL4, // 荅 + 0x832F, KANJI_LEVEL4, // 茯 + 0x832B, KANJI_LEVEL4, // 茫 + 0x8317, KANJI_LEVEL4, // 茗 + 0x8318, KANJI_LEVEL4, // 茘 + 0x8385, KANJI_LEVEL4, // 莅 + 0x839A, KANJI_LEVEL4, // 莚 + 0x83AA, KANJI_LEVEL4, // 莪 + 0x839F, KANJI_LEVEL4, // 莟 + 0x83A2, KANJI_LEVEL4, // 莢 + 0x8396, KANJI_LEVEL4, // 莖 + 0x8323, KANJI_LEVEL4, // 茣 + 0x838E, KANJI_LEVEL4, // 莎 + 0x8387, KANJI_LEVEL4, // 莇 + 0x838A, KANJI_LEVEL4, // 莊 + 0x837C, KANJI_LEVEL4, // 荌 + 0x83B5, KANJI_LEVEL4, // 莵 + 0x8373, KANJI_LEVEL4, // 荳 + 0x8375, KANJI_LEVEL4, // 荵 + 0x83A0, KANJI_LEVEL4, // 莠 + 0x8389, KANJI_LEVEL4, // 莉 + 0x83A8, KANJI_LEVEL4, // 莚 + 0x83F4, KANJI_LEVEL4, // 菎 + 0x8413, KANJI_LEVEL4, // 萓 + 0x83EB, KANJI_LEVEL4, // 菫 + 0x83CE, KANJI_LEVEL4, // 菎 + 0x83FD, KANJI_LEVEL4, // 菜 + 0x8403, KANJI_LEVEL4, // 萃 + 0x83D8, KANJI_LEVEL4, // 菘 + 0x840B, KANJI_LEVEL4, // 萋 + 0x83C1, KANJI_LEVEL4, // 菁 + 0x83F7, KANJI_LEVEL4, // 菷 + 0x8407, KANJI_LEVEL4, // 萇 + 0x83E0, KANJI_LEVEL4, // 菠 + 0x83F2, KANJI_LEVEL4, // 菲 + 0x840D, KANJI_LEVEL4, // 萍 + 0x8422, KANJI_LEVEL4, // 萢 + 0x8420, KANJI_LEVEL4, // 萠 + 0x83BD, KANJI_LEVEL4, // 莜 + 0x8438, KANJI_LEVEL4, // 萞 + 0x8506, KANJI_LEVEL4, // 蔆 + 0x83FB, KANJI_LEVEL4, // 菻 + 0x846D, KANJI_LEVEL4, // 葭 + 0x842A, KANJI_LEVEL4, // 萪 + 0x843C, KANJI_LEVEL4, // 萌 + 0x855A, KANJI_LEVEL4, // 蕚 + 0x8484, KANJI_LEVEL4, // 蒄 + 0x8477, KANJI_LEVEL4, // 葷 + 0x846B, KANJI_LEVEL4, // 葫 + 0x84AD, KANJI_LEVEL4, // 蒭 + 0x846E, KANJI_LEVEL4, // 葮 + 0x8482, KANJI_LEVEL4, // 蒂 + 0x8469, KANJI_LEVEL4, // 葩 + 0x8446, KANJI_LEVEL4, // 葆 + 0x842C, KANJI_LEVEL4, // 萬 + 0x846F, KANJI_LEVEL4, // 葯 + 0x8479, KANJI_LEVEL4, // 葹 + 0x8435, KANJI_LEVEL4, // 萵 + 0x84CA, KANJI_LEVEL4, // 蓊 + 0x8462, KANJI_LEVEL4, // 葢 + 0x84B9, KANJI_LEVEL4, // 蒹 + 0x84BF, KANJI_LEVEL4, // 蒿 + 0x849F, KANJI_LEVEL4, // 蒟 + 0x84D9, KANJI_LEVEL4, // 蓙 + 0x84CD, KANJI_LEVEL4, // 蓍 + 0x84BB, KANJI_LEVEL4, // 蒻 + 0x84DA, KANJI_LEVEL4, // 蓚 + 0x84D0, KANJI_LEVEL4, // 蓐 + 0x84C1, KANJI_LEVEL4, // 蓁 + 0x84C6, KANJI_LEVEL4, // 蓆 + 0x84D6, KANJI_LEVEL4, // 蓖 + 0x84A1, KANJI_LEVEL4, // 蒡 + 0x8521, KANJI_LEVEL4, // 蔡 + 0x84FF, KANJI_LEVEL4, // 蓿 + 0x84F4, KANJI_LEVEL4, // 蓎 + 0x8517, KANJI_LEVEL4, // 蔗 + 0x8518, KANJI_LEVEL4, // 蔘 + 0x852C, KANJI_LEVEL4, // 蔬 + 0x851F, KANJI_LEVEL4, // 蔟 + 0x8515, KANJI_LEVEL4, // 蔕 + 0x8514, KANJI_LEVEL4, // 蔔 + 0x84FC, KANJI_LEVEL4, // 蓌 + 0x8540, KANJI_LEVEL4, // 蕀 + 0x8563, KANJI_LEVEL4, // 蕣 + 0x8558, KANJI_LEVEL4, // 蕘 + 0x8548, KANJI_LEVEL4, // 蕈 + 0x8541, KANJI_LEVEL4, // 蕁 + 0x8602, KANJI_LEVEL4, // 蘂 + 0x854B, KANJI_LEVEL4, // 蕋 + 0x8555, KANJI_LEVEL4, // 蕕 + 0x8580, KANJI_LEVEL4, // 薀 + 0x85A4, KANJI_LEVEL4, // è–€ + 0x8588, KANJI_LEVEL4, // 薈 + 0x8591, KANJI_LEVEL4, // 薑 + 0x858A, KANJI_LEVEL4, // 薊 + 0x85A8, KANJI_LEVEL4, // è–š + 0x856D, KANJI_LEVEL4, // 蕭 + 0x8594, KANJI_LEVEL4, // 薔 + 0x859B, KANJI_LEVEL4, // 薛 + 0x85EA, KANJI_LEVEL4, // 藪 + 0x8587, KANJI_LEVEL4, // 薇 + 0x859C, KANJI_LEVEL4, // 薜 + 0x8577, KANJI_LEVEL4, // 蕷 + 0x857E, KANJI_LEVEL4, // 蕟 + 0x8590, KANJI_LEVEL4, // 薐 + 0x85C9, KANJI_LEVEL4, // 藉 + 0x85BA, KANJI_LEVEL4, // 薺 + 0x85CF, KANJI_LEVEL4, // 藏 + 0x85B9, KANJI_LEVEL4, // 薹 + 0x85D0, KANJI_LEVEL4, // 藐 + 0x85D5, KANJI_LEVEL4, // 藕 + 0x85DD, KANJI_LEVEL4, // 藝 + 0x85E5, KANJI_LEVEL4, // 藥 + 0x85DC, KANJI_LEVEL4, // 藜 + 0x85F9, KANJI_LEVEL4, // 藹 + 0x860A, KANJI_LEVEL4, // 蘊 + 0x8613, KANJI_LEVEL4, // 蘓 + 0x860B, KANJI_LEVEL4, // 蘋 + 0x85FE, KANJI_LEVEL4, // è—Ÿ + 0x85FA, KANJI_LEVEL4, // 藺 + 0x8606, KANJI_LEVEL4, // 蘆 + 0x8622, KANJI_LEVEL4, // 蘢 + 0x861A, KANJI_LEVEL4, // 蘚 + 0x8630, KANJI_LEVEL4, // 蘰 + 0x863F, KANJI_LEVEL4, // 蘿 + 0x864D, KANJI_LEVEL4, // 虍 + 0x4E55, KANJI_LEVEL4, // 乕 + 0x8654, KANJI_LEVEL4, // 虔 + 0x865F, KANJI_LEVEL4, // 號 + 0x8667, KANJI_LEVEL4, // 虧 + 0x8671, KANJI_LEVEL4, // 虱 + 0x8693, KANJI_LEVEL4, // 蚓 + 0x86A3, KANJI_LEVEL4, // 蚣 + 0x86A9, KANJI_LEVEL4, // 蚩 + 0x86AA, KANJI_LEVEL4, // 蚪 + 0x868B, KANJI_LEVEL4, // 蚋 + 0x868C, KANJI_LEVEL4, // 蚌 + 0x86B6, KANJI_LEVEL4, // 蚶 + 0x86AF, KANJI_LEVEL4, // 蚯 + 0x86C4, KANJI_LEVEL4, // 蛄 + 0x86C6, KANJI_LEVEL4, // 蛆 + 0x86B0, KANJI_LEVEL4, // 蚰 + 0x86C9, KANJI_LEVEL4, // 蛉 + 0x8823, KANJI_LEVEL4, // è £ + 0x86AB, KANJI_LEVEL4, // 蚫 + 0x86D4, KANJI_LEVEL4, // 蛔 + 0x86DE, KANJI_LEVEL4, // 蛞 + 0x86E9, KANJI_LEVEL4, // 蛩 + 0x86EC, KANJI_LEVEL4, // 蛬 + 0x86DF, KANJI_LEVEL4, // 蛟 + 0x86DB, KANJI_LEVEL4, // 蛛 + 0x86EF, KANJI_LEVEL4, // 蛯 + 0x8712, KANJI_LEVEL4, // 蜒 + 0x8706, KANJI_LEVEL4, // 蜆 + 0x8708, KANJI_LEVEL4, // 蜈 + 0x8700, KANJI_LEVEL4, // 蜀 + 0x8703, KANJI_LEVEL4, // 蜃 + 0x86FB, KANJI_LEVEL4, // 蛻 + 0x8711, KANJI_LEVEL4, // 蜑 + 0x8709, KANJI_LEVEL4, // 蜉 + 0x870D, KANJI_LEVEL4, // 蜍 + 0x86F9, KANJI_LEVEL4, // 蛹 + 0x870A, KANJI_LEVEL4, // 蜊 + 0x8734, KANJI_LEVEL4, // 蜎 + 0x873F, KANJI_LEVEL4, // 蜿 + 0x8737, KANJI_LEVEL4, // 蜷 + 0x873B, KANJI_LEVEL4, // 蜻 + 0x8725, KANJI_LEVEL4, // 蜥 + 0x8729, KANJI_LEVEL4, // 蜩 + 0x871A, KANJI_LEVEL4, // 蜚 + 0x8760, KANJI_LEVEL4, // 蝠 + 0x875F, KANJI_LEVEL4, // 蝟 + 0x8778, KANJI_LEVEL4, // 蝞 + 0x874C, KANJI_LEVEL4, // 蝌 + 0x874E, KANJI_LEVEL4, // 蝎 + 0x8774, KANJI_LEVEL4, // 蝎 + 0x8757, KANJI_LEVEL4, // 蝗 + 0x8768, KANJI_LEVEL4, // 蝚 + 0x876E, KANJI_LEVEL4, // 蝮 + 0x8759, KANJI_LEVEL4, // 蝙 + 0x8753, KANJI_LEVEL4, // 蝓 + 0x8763, KANJI_LEVEL4, // 蝣 + 0x876A, KANJI_LEVEL4, // 蝪 + 0x8805, KANJI_LEVEL4, // 蠅 + 0x87A2, KANJI_LEVEL4, // 螢 + 0x879F, KANJI_LEVEL4, // 螟 + 0x8782, KANJI_LEVEL4, // 螂 + 0x87AF, KANJI_LEVEL4, // 螯 + 0x87CB, KANJI_LEVEL4, // 蟋 + 0x87BD, KANJI_LEVEL4, // 螜 + 0x87C0, KANJI_LEVEL4, // 蟀 + 0x87D0, KANJI_LEVEL4, // 蟐 + 0x96D6, KANJI_LEVEL4, // 雖 + 0x87AB, KANJI_LEVEL4, // 螫 + 0x87C4, KANJI_LEVEL4, // 蟄 + 0x87B3, KANJI_LEVEL4, // 螳 + 0x87C7, KANJI_LEVEL4, // 蟇 + 0x87C6, KANJI_LEVEL4, // 蟆 + 0x87BB, KANJI_LEVEL4, // 螻 + 0x87EF, KANJI_LEVEL4, // 蟯 + 0x87F2, KANJI_LEVEL4, // 蟲 + 0x87E0, KANJI_LEVEL4, // 蟠 + 0x880F, KANJI_LEVEL4, // 蠏 + 0x880D, KANJI_LEVEL4, // 蠍 + 0x87FE, KANJI_LEVEL4, // 蟟 + 0x87F6, KANJI_LEVEL4, // 蟶 + 0x87F7, KANJI_LEVEL4, // 蟷 + 0x880E, KANJI_LEVEL4, // 蠎 + 0x87D2, KANJI_LEVEL4, // 蟒 + 0x8811, KANJI_LEVEL4, // 蠑 + 0x8816, KANJI_LEVEL4, // 蠖 + 0x8815, KANJI_LEVEL4, // 蠕 + 0x8822, KANJI_LEVEL4, // è ¢ + 0x8821, KANJI_LEVEL4, // è ¡ + 0x8831, KANJI_LEVEL4, // è ± + 0x8836, KANJI_LEVEL4, // è ¶ + 0x8839, KANJI_LEVEL4, // è ¹ + 0x8827, KANJI_LEVEL4, // è § + 0x883B, KANJI_LEVEL4, // è » + 0x8844, KANJI_LEVEL4, // 衄 + 0x8842, KANJI_LEVEL4, // 衂 + 0x8852, KANJI_LEVEL4, // 衒 + 0x8859, KANJI_LEVEL4, // 衙 + 0x885E, KANJI_LEVEL4, // 衞 + 0x8862, KANJI_LEVEL4, // è¡¢ + 0x886B, KANJI_LEVEL4, // è¡« + 0x8881, KANJI_LEVEL4, // 袁 + 0x887E, KANJI_LEVEL4, // 衟 + 0x889E, KANJI_LEVEL4, // 袞 + 0x8875, KANJI_LEVEL4, // 衵 + 0x887D, KANJI_LEVEL4, // 衜 + 0x88B5, KANJI_LEVEL4, // 袵 + 0x8872, KANJI_LEVEL4, // 衲 + 0x8882, KANJI_LEVEL4, // 袂 + 0x8897, KANJI_LEVEL4, // 袗 + 0x8892, KANJI_LEVEL4, // 袒 + 0x88AE, KANJI_LEVEL4, // 袮 + 0x8899, KANJI_LEVEL4, // 袙 + 0x88A2, KANJI_LEVEL4, // 袢 + 0x888D, KANJI_LEVEL4, // 袍 + 0x88A4, KANJI_LEVEL4, // 袀 + 0x88B0, KANJI_LEVEL4, // 袰 + 0x88BF, KANJI_LEVEL4, // 袿 + 0x88B1, KANJI_LEVEL4, // 袱 + 0x88C3, KANJI_LEVEL4, // 裃 + 0x88C4, KANJI_LEVEL4, // 裄 + 0x88D4, KANJI_LEVEL4, // 裔 + 0x88D8, KANJI_LEVEL4, // 裘 + 0x88D9, KANJI_LEVEL4, // 裙 + 0x88DD, KANJI_LEVEL4, // 裝 + 0x88F9, KANJI_LEVEL4, // 裹 + 0x8902, KANJI_LEVEL4, // 耂 + 0x88FC, KANJI_LEVEL4, // 裌 + 0x88F4, KANJI_LEVEL4, // 裎 + 0x88E8, KANJI_LEVEL4, // 裚 + 0x88F2, KANJI_LEVEL4, // 裲 + 0x8904, KANJI_LEVEL4, // 耄 + 0x890C, KANJI_LEVEL4, // 而 + 0x890A, KANJI_LEVEL4, // 耊 + 0x8913, KANJI_LEVEL4, // 耓 + 0x8943, KANJI_LEVEL4, // 襃 + 0x891E, KANJI_LEVEL4, // 耞 + 0x8925, KANJI_LEVEL4, // 耥 + 0x892A, KANJI_LEVEL4, // 耪 + 0x892B, KANJI_LEVEL4, // 耫 + 0x8941, KANJI_LEVEL4, // 襁 + 0x8944, KANJI_LEVEL4, // 襄 + 0x893B, KANJI_LEVEL4, // 耻 + 0x8936, KANJI_LEVEL4, // 耶 + 0x8938, KANJI_LEVEL4, // 耞 + 0x894C, KANJI_LEVEL4, // 襌 + 0x891D, KANJI_LEVEL4, // 耝 + 0x8960, KANJI_LEVEL4, // 襠 + 0x895E, KANJI_LEVEL4, // 襞 + 0x8966, KANJI_LEVEL4, // 襊 + 0x8964, KANJI_LEVEL4, // 襀 + 0x896D, KANJI_LEVEL4, // 襭 + 0x896A, KANJI_LEVEL4, // 襪 + 0x896F, KANJI_LEVEL4, // 襯 + 0x8974, KANJI_LEVEL4, // 襎 + 0x8977, KANJI_LEVEL4, // 襷 + 0x897E, KANJI_LEVEL4, // 襟 + 0x8983, KANJI_LEVEL4, // 芃 + 0x8988, KANJI_LEVEL4, // 芈 + 0x898A, KANJI_LEVEL4, // 芊 + 0x8993, KANJI_LEVEL4, // 芓 + 0x8998, KANJI_LEVEL4, // 芘 + 0x89A1, KANJI_LEVEL4, // 芡 + 0x89A9, KANJI_LEVEL4, // 芩 + 0x89A6, KANJI_LEVEL4, // 芊 + 0x89AC, KANJI_LEVEL4, // 芬 + 0x89AF, KANJI_LEVEL4, // 芯 + 0x89B2, KANJI_LEVEL4, // 芲 + 0x89BA, KANJI_LEVEL4, // 芺 + 0x89BD, KANJI_LEVEL4, // 芜 + 0x89BF, KANJI_LEVEL4, // 芿 + 0x89C0, KANJI_LEVEL4, // 觀 + 0x89DA, KANJI_LEVEL4, // 觚 + 0x89DC, KANJI_LEVEL4, // 觜 + 0x89DD, KANJI_LEVEL4, // 觝 + 0x89E7, KANJI_LEVEL4, // è§§ + 0x89F4, KANJI_LEVEL4, // è§Ž + 0x89F8, KANJI_LEVEL4, // è§ž + 0x8A03, KANJI_LEVEL4, // 蚃 + 0x8A16, KANJI_LEVEL4, // èš– + 0x8A10, KANJI_LEVEL4, // 蚐 + 0x8A0C, KANJI_LEVEL4, // 蚌 + 0x8A1B, KANJI_LEVEL4, // èš› + 0x8A1D, KANJI_LEVEL4, // 蚝 + 0x8A25, KANJI_LEVEL4, // 蚥 + 0x8A36, KANJI_LEVEL4, // èš¶ + 0x8A41, KANJI_LEVEL4, // 詁 + 0x8A5B, KANJI_LEVEL4, // 詛 + 0x8A52, KANJI_LEVEL4, // 詒 + 0x8A46, KANJI_LEVEL4, // 詆 + 0x8A48, KANJI_LEVEL4, // 詈 + 0x8A7C, KANJI_LEVEL4, // 詌 + 0x8A6D, KANJI_LEVEL4, // è©­ + 0x8A6C, KANJI_LEVEL4, // 詬 + 0x8A62, KANJI_LEVEL4, // è©¢ + 0x8A85, KANJI_LEVEL4, // 誅 + 0x8A82, KANJI_LEVEL4, // 誂 + 0x8A84, KANJI_LEVEL4, // 誄 + 0x8AA8, KANJI_LEVEL4, // 誚 + 0x8AA1, KANJI_LEVEL4, // 誡 + 0x8A91, KANJI_LEVEL4, // 誑 + 0x8AA5, KANJI_LEVEL4, // 誥 + 0x8AA6, KANJI_LEVEL4, // 誊 + 0x8A9A, KANJI_LEVEL4, // 誚 + 0x8AA3, KANJI_LEVEL4, // 誣 + 0x8AC4, KANJI_LEVEL4, // 諄 + 0x8ACD, KANJI_LEVEL4, // 諍 + 0x8AC2, KANJI_LEVEL4, // 諂 + 0x8ADA, KANJI_LEVEL4, // 諚 + 0x8AEB, KANJI_LEVEL4, // è«« + 0x8AF3, KANJI_LEVEL4, // 諳 + 0x8AE7, KANJI_LEVEL4, // è«§ + 0x8AE4, KANJI_LEVEL4, // è«€ + 0x8AF1, KANJI_LEVEL4, // 諱 + 0x8B14, KANJI_LEVEL4, // 謔 + 0x8AE0, KANJI_LEVEL4, // è«  + 0x8AE2, KANJI_LEVEL4, // è«¢ + 0x8AF7, KANJI_LEVEL4, // è«· + 0x8ADE, KANJI_LEVEL4, // 諞 + 0x8ADB, KANJI_LEVEL4, // 諛 + 0x8B0C, KANJI_LEVEL4, // 謌 + 0x8B07, KANJI_LEVEL4, // 謇 + 0x8B1A, KANJI_LEVEL4, // 謚 + 0x8AE1, KANJI_LEVEL4, // è«¡ + 0x8B16, KANJI_LEVEL4, // 謖 + 0x8B10, KANJI_LEVEL4, // 謐 + 0x8B17, KANJI_LEVEL4, // 謗 + 0x8B20, KANJI_LEVEL4, // 謠 + 0x8B33, KANJI_LEVEL4, // 謳 + 0x97AB, KANJI_LEVEL4, // 鞫 + 0x8B26, KANJI_LEVEL4, // 謊 + 0x8B2B, KANJI_LEVEL4, // 謫 + 0x8B3E, KANJI_LEVEL4, // 謟 + 0x8B28, KANJI_LEVEL4, // 謚 + 0x8B41, KANJI_LEVEL4, // 譁 + 0x8B4C, KANJI_LEVEL4, // 譌 + 0x8B4F, KANJI_LEVEL4, // 譏 + 0x8B4E, KANJI_LEVEL4, // 譎 + 0x8B49, KANJI_LEVEL4, // 證 + 0x8B56, KANJI_LEVEL4, // 譖 + 0x8B5B, KANJI_LEVEL4, // 譛 + 0x8B5A, KANJI_LEVEL4, // 譚 + 0x8B6B, KANJI_LEVEL4, // è­« + 0x8B5F, KANJI_LEVEL4, // 譟 + 0x8B6C, KANJI_LEVEL4, // è­¬ + 0x8B6F, KANJI_LEVEL4, // è­¯ + 0x8B74, KANJI_LEVEL4, // è­Ž + 0x8B7D, KANJI_LEVEL4, // è­œ + 0x8B80, KANJI_LEVEL4, // 讀 + 0x8B8C, KANJI_LEVEL4, // 讌 + 0x8B8E, KANJI_LEVEL4, // 讎 + 0x8B92, KANJI_LEVEL4, // 讒 + 0x8B93, KANJI_LEVEL4, // 讓 + 0x8B96, KANJI_LEVEL4, // 讖 + 0x8B99, KANJI_LEVEL4, // 讙 + 0x8B9A, KANJI_LEVEL4, // 讚 + 0x8C3A, KANJI_LEVEL4, // è°º + 0x8C41, KANJI_LEVEL4, // 豁 + 0x8C3F, KANJI_LEVEL4, // è°¿ + 0x8C48, KANJI_LEVEL4, // 豈 + 0x8C4C, KANJI_LEVEL4, // 豌 + 0x8C4E, KANJI_LEVEL4, // 豎 + 0x8C50, KANJI_LEVEL4, // 豐 + 0x8C55, KANJI_LEVEL4, // 豕 + 0x8C62, KANJI_LEVEL4, // è±¢ + 0x8C6C, KANJI_LEVEL4, // 豬 + 0x8C78, KANJI_LEVEL4, // 豞 + 0x8C7A, KANJI_LEVEL4, // 豺 + 0x8C82, KANJI_LEVEL4, // 貂 + 0x8C89, KANJI_LEVEL4, // 貉 + 0x8C85, KANJI_LEVEL4, // 貅 + 0x8C8A, KANJI_LEVEL4, // 貊 + 0x8C8D, KANJI_LEVEL4, // 貍 + 0x8C8E, KANJI_LEVEL4, // 貎 + 0x8C94, KANJI_LEVEL4, // 貔 + 0x8C7C, KANJI_LEVEL4, // 豌 + 0x8C98, KANJI_LEVEL4, // 貘 + 0x621D, KANJI_LEVEL4, // 戝 + 0x8CAD, KANJI_LEVEL4, // è²­ + 0x8CAA, KANJI_LEVEL4, // 貪 + 0x8CBD, KANJI_LEVEL4, // 貜 + 0x8CB2, KANJI_LEVEL4, // è²² + 0x8CB3, KANJI_LEVEL4, // è²³ + 0x8CAE, KANJI_LEVEL4, // è²® + 0x8CB6, KANJI_LEVEL4, // è²¶ + 0x8CC8, KANJI_LEVEL4, // 賈 + 0x8CC1, KANJI_LEVEL4, // 賁 + 0x8CE4, KANJI_LEVEL4, // è³€ + 0x8CE3, KANJI_LEVEL4, // è³£ + 0x8CDA, KANJI_LEVEL4, // 賚 + 0x8CFD, KANJI_LEVEL4, // 賜 + 0x8CFA, KANJI_LEVEL4, // 賺 + 0x8CFB, KANJI_LEVEL4, // è³» + 0x8D04, KANJI_LEVEL4, // 莄 + 0x8D05, KANJI_LEVEL4, // 莅 + 0x8D0A, KANJI_LEVEL4, // 莊 + 0x8D07, KANJI_LEVEL4, // 莇 + 0x8D0F, KANJI_LEVEL4, // 莏 + 0x8D0D, KANJI_LEVEL4, // 莍 + 0x8D10, KANJI_LEVEL4, // 莐 + 0x9F4E, KANJI_LEVEL4, // 霎 + 0x8D13, KANJI_LEVEL4, // 莓 + 0x8CCD, KANJI_LEVEL4, // 賍 + 0x8D14, KANJI_LEVEL4, // 莔 + 0x8D16, KANJI_LEVEL4, // 莖 + 0x8D67, KANJI_LEVEL4, // èµ§ + 0x8D6D, KANJI_LEVEL4, // èµ­ + 0x8D71, KANJI_LEVEL4, // èµ± + 0x8D73, KANJI_LEVEL4, // èµ³ + 0x8D81, KANJI_LEVEL4, // 趁 + 0x8D99, KANJI_LEVEL4, // 趙 + 0x8DC2, KANJI_LEVEL4, // 跂 + 0x8DBE, KANJI_LEVEL4, // è¶Ÿ + 0x8DBA, KANJI_LEVEL4, // 趺 + 0x8DCF, KANJI_LEVEL4, // 跏 + 0x8DDA, KANJI_LEVEL4, // 跚 + 0x8DD6, KANJI_LEVEL4, // 跖 + 0x8DCC, KANJI_LEVEL4, // 跌 + 0x8DDB, KANJI_LEVEL4, // 跛 + 0x8DCB, KANJI_LEVEL4, // 跋 + 0x8DEA, KANJI_LEVEL4, // è·ª + 0x8DEB, KANJI_LEVEL4, // è·« + 0x8DDF, KANJI_LEVEL4, // 跟 + 0x8DE3, KANJI_LEVEL4, // è·£ + 0x8DFC, KANJI_LEVEL4, // è·Œ + 0x8E08, KANJI_LEVEL4, // 螈 + 0x8E09, KANJI_LEVEL4, // 螉 + 0x8DFF, KANJI_LEVEL4, // è·¿ + 0x8E1D, KANJI_LEVEL4, // 螝 + 0x8E1E, KANJI_LEVEL4, // èžž + 0x8E10, KANJI_LEVEL4, // 螐 + 0x8E1F, KANJI_LEVEL4, // 螟 + 0x8E42, KANJI_LEVEL4, // 蹂 + 0x8E35, KANJI_LEVEL4, // èžµ + 0x8E30, KANJI_LEVEL4, // èž° + 0x8E34, KANJI_LEVEL4, // 螎 + 0x8E4A, KANJI_LEVEL4, // 蹊 + 0x8E47, KANJI_LEVEL4, // 蹇 + 0x8E49, KANJI_LEVEL4, // 蹉 + 0x8E4C, KANJI_LEVEL4, // 蹌 + 0x8E50, KANJI_LEVEL4, // 蹐 + 0x8E48, KANJI_LEVEL4, // 蹈 + 0x8E59, KANJI_LEVEL4, // 蹙 + 0x8E64, KANJI_LEVEL4, // è¹€ + 0x8E60, KANJI_LEVEL4, // è¹  + 0x8E2A, KANJI_LEVEL4, // 螪 + 0x8E63, KANJI_LEVEL4, // è¹£ + 0x8E55, KANJI_LEVEL4, // 蹕 + 0x8E76, KANJI_LEVEL4, // è¹¶ + 0x8E72, KANJI_LEVEL4, // è¹² + 0x8E7C, KANJI_LEVEL4, // 蹌 + 0x8E81, KANJI_LEVEL4, // 躁 + 0x8E87, KANJI_LEVEL4, // 躇 + 0x8E85, KANJI_LEVEL4, // 躅 + 0x8E84, KANJI_LEVEL4, // 躄 + 0x8E8B, KANJI_LEVEL4, // 躋 + 0x8E8A, KANJI_LEVEL4, // 躊 + 0x8E93, KANJI_LEVEL4, // 躓 + 0x8E91, KANJI_LEVEL4, // 躑 + 0x8E94, KANJI_LEVEL4, // 躔 + 0x8E99, KANJI_LEVEL4, // 躙 + 0x8EAA, KANJI_LEVEL4, // 躪 + 0x8EA1, KANJI_LEVEL4, // 躡 + 0x8EAC, KANJI_LEVEL4, // 躬 + 0x8EB0, KANJI_LEVEL4, // 躰 + 0x8EC6, KANJI_LEVEL4, // 軆 + 0x8EB1, KANJI_LEVEL4, // 躱 + 0x8EBE, KANJI_LEVEL4, // 躟 + 0x8EC5, KANJI_LEVEL4, // 軅 + 0x8EC8, KANJI_LEVEL4, // 軈 + 0x8ECB, KANJI_LEVEL4, // 軋 + 0x8EDB, KANJI_LEVEL4, // 軛 + 0x8EE3, KANJI_LEVEL4, // 軣 + 0x8EFC, KANJI_LEVEL4, // 軌 + 0x8EFB, KANJI_LEVEL4, // è»» + 0x8EEB, KANJI_LEVEL4, // 軫 + 0x8EFE, KANJI_LEVEL4, // 軟 + 0x8F0A, KANJI_LEVEL4, // 茊 + 0x8F05, KANJI_LEVEL4, // 茅 + 0x8F15, KANJI_LEVEL4, // 茕 + 0x8F12, KANJI_LEVEL4, // 茒 + 0x8F19, KANJI_LEVEL4, // 茙 + 0x8F13, KANJI_LEVEL4, // 茓 + 0x8F1C, KANJI_LEVEL4, // 茜 + 0x8F1F, KANJI_LEVEL4, // 茟 + 0x8F1B, KANJI_LEVEL4, // 茛 + 0x8F0C, KANJI_LEVEL4, // 茌 + 0x8F26, KANJI_LEVEL4, // 茊 + 0x8F33, KANJI_LEVEL4, // 茳 + 0x8F3B, KANJI_LEVEL4, // 茻 + 0x8F39, KANJI_LEVEL4, // 茹 + 0x8F45, KANJI_LEVEL4, // 蜅 + 0x8F42, KANJI_LEVEL4, // 蜂 + 0x8F3E, KANJI_LEVEL4, // 茟 + 0x8F4C, KANJI_LEVEL4, // 蜌 + 0x8F49, KANJI_LEVEL4, // 蜉 + 0x8F46, KANJI_LEVEL4, // 蜆 + 0x8F4E, KANJI_LEVEL4, // 蜎 + 0x8F57, KANJI_LEVEL4, // 蜗 + 0x8F5C, KANJI_LEVEL4, // 蜜 + 0x8F62, KANJI_LEVEL4, // 蜢 + 0x8F63, KANJI_LEVEL4, // 蜣 + 0x8F64, KANJI_LEVEL4, // 蜀 + 0x8F9C, KANJI_LEVEL4, // 蟜 + 0x8F9F, KANJI_LEVEL4, // 蟟 + 0x8FA3, KANJI_LEVEL4, // 蟣 + 0x8FAD, KANJI_LEVEL4, // 蟭 + 0x8FAF, KANJI_LEVEL4, // 蟯 + 0x8FB7, KANJI_LEVEL4, // 蟷 + 0x8FDA, KANJI_LEVEL4, // 迚 + 0x8FE5, KANJI_LEVEL4, // è¿¥ + 0x8FE2, KANJI_LEVEL4, // è¿¢ + 0x8FEA, KANJI_LEVEL4, // 迪 + 0x8FEF, KANJI_LEVEL4, // 迯 + 0x9087, KANJI_LEVEL4, // 邇 + 0x8FF4, KANJI_LEVEL4, // 迎 + 0x9005, KANJI_LEVEL4, // 逅 + 0x8FF9, KANJI_LEVEL4, // 迹 + 0x8FFA, KANJI_LEVEL4, // 迺 + 0x9011, KANJI_LEVEL4, // 逑 + 0x9015, KANJI_LEVEL4, // 逕 + 0x9021, KANJI_LEVEL4, // 逡 + 0x900D, KANJI_LEVEL4, // 逍 + 0x901E, KANJI_LEVEL4, // 逞 + 0x9016, KANJI_LEVEL4, // 逖 + 0x900B, KANJI_LEVEL4, // 逋 + 0x9027, KANJI_LEVEL4, // 逧 + 0x9036, KANJI_LEVEL4, // 逶 + 0x9035, KANJI_LEVEL4, // 逵 + 0x9039, KANJI_LEVEL4, // 逹 + 0x8FF8, KANJI_LEVEL4, // 连 + 0x904F, KANJI_LEVEL4, // 遏 + 0x9050, KANJI_LEVEL4, // 遐 + 0x9051, KANJI_LEVEL4, // 遑 + 0x9052, KANJI_LEVEL4, // 遒 + 0x900E, KANJI_LEVEL4, // 逎 + 0x9049, KANJI_LEVEL4, // 遉 + 0x903E, KANJI_LEVEL4, // 速 + 0x9056, KANJI_LEVEL4, // 遖 + 0x9058, KANJI_LEVEL4, // 遘 + 0x905E, KANJI_LEVEL4, // 遞 + 0x9068, KANJI_LEVEL4, // 遚 + 0x906F, KANJI_LEVEL4, // 遯 + 0x9076, KANJI_LEVEL4, // 遶 + 0x96A8, KANJI_LEVEL4, // 隹 + 0x9072, KANJI_LEVEL4, // 遲 + 0x9082, KANJI_LEVEL4, // 邂 + 0x907D, KANJI_LEVEL4, // 遜 + 0x9081, KANJI_LEVEL4, // 邁 + 0x9080, KANJI_LEVEL4, // 邀 + 0x908A, KANJI_LEVEL4, // 邊 + 0x9089, KANJI_LEVEL4, // 邉 + 0x908F, KANJI_LEVEL4, // 邏 + 0x90A8, KANJI_LEVEL4, // 邹 + 0x90AF, KANJI_LEVEL4, // 邯 + 0x90B1, KANJI_LEVEL4, // 邱 + 0x90B5, KANJI_LEVEL4, // 邵 + 0x90E2, KANJI_LEVEL4, // 郢 + 0x90E4, KANJI_LEVEL4, // 郀 + 0x6248, KANJI_LEVEL4, // 扈 + 0x90DB, KANJI_LEVEL4, // 郛 + 0x9102, KANJI_LEVEL4, // 鄂 + 0x9112, KANJI_LEVEL4, // 鄒 + 0x9119, KANJI_LEVEL4, // 鄙 + 0x9132, KANJI_LEVEL4, // 鄲 + 0x9130, KANJI_LEVEL4, // 鄰 + 0x914A, KANJI_LEVEL4, // 酊 + 0x9156, KANJI_LEVEL4, // 酖 + 0x9158, KANJI_LEVEL4, // 酘 + 0x9163, KANJI_LEVEL4, // 酣 + 0x9165, KANJI_LEVEL4, // 酥 + 0x9169, KANJI_LEVEL4, // 酩 + 0x9173, KANJI_LEVEL4, // 酳 + 0x9172, KANJI_LEVEL4, // 酲 + 0x918B, KANJI_LEVEL4, // 醋 + 0x9189, KANJI_LEVEL4, // 醉 + 0x9182, KANJI_LEVEL4, // 醂 + 0x91A2, KANJI_LEVEL4, // 醢 + 0x91AB, KANJI_LEVEL4, // 醫 + 0x91AF, KANJI_LEVEL4, // 醯 + 0x91AA, KANJI_LEVEL4, // 醪 + 0x91B5, KANJI_LEVEL4, // 醵 + 0x91B4, KANJI_LEVEL4, // 醮 + 0x91BA, KANJI_LEVEL4, // 醺 + 0x91C0, KANJI_LEVEL4, // 釀 + 0x91C1, KANJI_LEVEL4, // 釁 + 0x91C9, KANJI_LEVEL4, // 釉 + 0x91CB, KANJI_LEVEL4, // 釋 + 0x91D0, KANJI_LEVEL4, // 釐 + 0x91D6, KANJI_LEVEL4, // 釖 + 0x91DF, KANJI_LEVEL4, // 釟 + 0x91E1, KANJI_LEVEL4, // 釡 + 0x91DB, KANJI_LEVEL4, // 釛 + 0x91FC, KANJI_LEVEL4, // 里 + 0x91F5, KANJI_LEVEL4, // 釵 + 0x91F6, KANJI_LEVEL4, // 釶 + 0x921E, KANJI_LEVEL4, // 鈞 + 0x91FF, KANJI_LEVEL4, // 釿 + 0x9214, KANJI_LEVEL4, // 鈔 + 0x922C, KANJI_LEVEL4, // 鈬 + 0x9215, KANJI_LEVEL4, // 鈕 + 0x9211, KANJI_LEVEL4, // 鈑 + 0x925E, KANJI_LEVEL4, // 鉞 + 0x9257, KANJI_LEVEL4, // 鉗 + 0x9245, KANJI_LEVEL4, // 鉅 + 0x9249, KANJI_LEVEL4, // 鉉 + 0x9264, KANJI_LEVEL4, // 鉀 + 0x9248, KANJI_LEVEL4, // 鉈 + 0x9295, KANJI_LEVEL4, // 銕 + 0x923F, KANJI_LEVEL4, // 鈿 + 0x924B, KANJI_LEVEL4, // 鉋 + 0x9250, KANJI_LEVEL4, // 鉐 + 0x929C, KANJI_LEVEL4, // 銜 + 0x9296, KANJI_LEVEL4, // 銖 + 0x9293, KANJI_LEVEL4, // 銓 + 0x929B, KANJI_LEVEL4, // 銛 + 0x925A, KANJI_LEVEL4, // 鉚 + 0x92CF, KANJI_LEVEL4, // 鋏 + 0x92B9, KANJI_LEVEL4, // 銹 + 0x92B7, KANJI_LEVEL4, // 銷 + 0x92E9, KANJI_LEVEL4, // 鋩 + 0x930F, KANJI_LEVEL4, // 錏 + 0x92FA, KANJI_LEVEL4, // 鋺 + 0x9344, KANJI_LEVEL4, // 鍄 + 0x932E, KANJI_LEVEL4, // 錮 + 0x9319, KANJI_LEVEL4, // 錙 + 0x9322, KANJI_LEVEL4, // 錢 + 0x931A, KANJI_LEVEL4, // 錚 + 0x9323, KANJI_LEVEL4, // 錣 + 0x933A, KANJI_LEVEL4, // 錺 + 0x9335, KANJI_LEVEL4, // 錵 + 0x933B, KANJI_LEVEL4, // 錻 + 0x935C, KANJI_LEVEL4, // 鍜 + 0x9360, KANJI_LEVEL4, // 鍠 + 0x937C, KANJI_LEVEL4, // 鍌 + 0x936E, KANJI_LEVEL4, // 鍮 + 0x9356, KANJI_LEVEL4, // 鍖 + 0x93B0, KANJI_LEVEL4, // 鎰 + 0x93AC, KANJI_LEVEL4, // 鎬 + 0x93AD, KANJI_LEVEL4, // 鎭 + 0x9394, KANJI_LEVEL4, // 鎔 + 0x93B9, KANJI_LEVEL4, // 鎹 + 0x93D6, KANJI_LEVEL4, // 鏖 + 0x93D7, KANJI_LEVEL4, // 鏗 + 0x93E8, KANJI_LEVEL4, // 鏚 + 0x93E5, KANJI_LEVEL4, // 鏥 + 0x93D8, KANJI_LEVEL4, // 鏘 + 0x93C3, KANJI_LEVEL4, // 鏃 + 0x93DD, KANJI_LEVEL4, // 鏝 + 0x93D0, KANJI_LEVEL4, // 鏐 + 0x93C8, KANJI_LEVEL4, // 鏈 + 0x93E4, KANJI_LEVEL4, // 鏀 + 0x941A, KANJI_LEVEL4, // 鐚 + 0x9414, KANJI_LEVEL4, // 鐔 + 0x9413, KANJI_LEVEL4, // 鐓 + 0x9403, KANJI_LEVEL4, // 鐃 + 0x9407, KANJI_LEVEL4, // 鐇 + 0x9410, KANJI_LEVEL4, // 鐐 + 0x9436, KANJI_LEVEL4, // 鐶 + 0x942B, KANJI_LEVEL4, // 鐫 + 0x9435, KANJI_LEVEL4, // 鐵 + 0x9421, KANJI_LEVEL4, // 鐡 + 0x943A, KANJI_LEVEL4, // 鐺 + 0x9441, KANJI_LEVEL4, // 鑁 + 0x9452, KANJI_LEVEL4, // 鑒 + 0x9444, KANJI_LEVEL4, // 鑄 + 0x945B, KANJI_LEVEL4, // 鑛 + 0x9460, KANJI_LEVEL4, // 鑠 + 0x9462, KANJI_LEVEL4, // 鑢 + 0x945E, KANJI_LEVEL4, // 鑞 + 0x946A, KANJI_LEVEL4, // 鑪 + 0x9229, KANJI_LEVEL4, // 鈩 + 0x9470, KANJI_LEVEL4, // 鑰 + 0x9475, KANJI_LEVEL4, // 鑵 + 0x9477, KANJI_LEVEL4, // 鑷 + 0x947D, KANJI_LEVEL4, // 鑜 + 0x945A, KANJI_LEVEL4, // 鑚 + 0x947C, KANJI_LEVEL4, // 鑌 + 0x947E, KANJI_LEVEL4, // 鑟 + 0x9481, KANJI_LEVEL4, // 钁 + 0x947F, KANJI_LEVEL4, // 鑿 + 0x9582, KANJI_LEVEL4, // 閂 + 0x9587, KANJI_LEVEL4, // 閇 + 0x958A, KANJI_LEVEL4, // 閊 + 0x9594, KANJI_LEVEL4, // 閔 + 0x9596, KANJI_LEVEL4, // 閖 + 0x9598, KANJI_LEVEL4, // 閘 + 0x9599, KANJI_LEVEL4, // 閙 + 0x95A0, KANJI_LEVEL4, // 閠 + 0x95A8, KANJI_LEVEL4, // 閹 + 0x95A7, KANJI_LEVEL4, // 閧 + 0x95AD, KANJI_LEVEL4, // 閭 + 0x95BC, KANJI_LEVEL4, // é–Œ + 0x95BB, KANJI_LEVEL4, // 閻 + 0x95B9, KANJI_LEVEL4, // 閹 + 0x95BE, KANJI_LEVEL4, // é–Ÿ + 0x95CA, KANJI_LEVEL4, // 闊 + 0x6FF6, KANJI_LEVEL4, // æ¿¶ + 0x95C3, KANJI_LEVEL4, // 闃 + 0x95CD, KANJI_LEVEL4, // 闍 + 0x95CC, KANJI_LEVEL4, // 闌 + 0x95D5, KANJI_LEVEL4, // 闕 + 0x95D4, KANJI_LEVEL4, // 闔 + 0x95D6, KANJI_LEVEL4, // 闖 + 0x95DC, KANJI_LEVEL4, // 關 + 0x95E1, KANJI_LEVEL4, // 闡 + 0x95E5, KANJI_LEVEL4, // 闥 + 0x95E2, KANJI_LEVEL4, // 闢 + 0x9621, KANJI_LEVEL4, // 阡 + 0x9628, KANJI_LEVEL4, // 阚 + 0x962E, KANJI_LEVEL4, // 阮 + 0x962F, KANJI_LEVEL4, // 阯 + 0x9642, KANJI_LEVEL4, // 陂 + 0x964C, KANJI_LEVEL4, // 陌 + 0x964F, KANJI_LEVEL4, // 陏 + 0x964B, KANJI_LEVEL4, // 陋 + 0x9677, KANJI_LEVEL4, // 陷 + 0x965C, KANJI_LEVEL4, // 陜 + 0x965E, KANJI_LEVEL4, // 陞 + 0x965D, KANJI_LEVEL4, // 陝 + 0x965F, KANJI_LEVEL4, // 陟 + 0x9666, KANJI_LEVEL4, // 险 + 0x9672, KANJI_LEVEL4, // 陲 + 0x966C, KANJI_LEVEL4, // 陬 + 0x968D, KANJI_LEVEL4, // 隍 + 0x9698, KANJI_LEVEL4, // 隘 + 0x9695, KANJI_LEVEL4, // 隕 + 0x9697, KANJI_LEVEL4, // 隗 + 0x96AA, KANJI_LEVEL4, // 險 + 0x96A7, KANJI_LEVEL4, // 隧 + 0x96B1, KANJI_LEVEL4, // 隱 + 0x96B2, KANJI_LEVEL4, // 隲 + 0x96B0, KANJI_LEVEL4, // 隰 + 0x96B4, KANJI_LEVEL4, // 隮 + 0x96B6, KANJI_LEVEL4, // 隶 + 0x96B8, KANJI_LEVEL4, // 难 + 0x96B9, KANJI_LEVEL4, // 隹 + 0x96CE, KANJI_LEVEL4, // 雎 + 0x96CB, KANJI_LEVEL4, // 雋 + 0x96C9, KANJI_LEVEL4, // 雉 + 0x96CD, KANJI_LEVEL4, // 雍 + 0x894D, KANJI_LEVEL4, // 襍 + 0x96DC, KANJI_LEVEL4, // 雜 + 0x970D, KANJI_LEVEL4, // 霍 + 0x96D5, KANJI_LEVEL4, // 雕 + 0x96F9, KANJI_LEVEL4, // 雹 + 0x9704, KANJI_LEVEL4, // 霄 + 0x9706, KANJI_LEVEL4, // 霆 + 0x9708, KANJI_LEVEL4, // 霈 + 0x9713, KANJI_LEVEL4, // 霓 + 0x970E, KANJI_LEVEL4, // 霎 + 0x9711, KANJI_LEVEL4, // 霑 + 0x970F, KANJI_LEVEL4, // 霏 + 0x9716, KANJI_LEVEL4, // 霖 + 0x9719, KANJI_LEVEL4, // 霙 + 0x9724, KANJI_LEVEL4, // 需 + 0x972A, KANJI_LEVEL4, // 霪 + 0x9730, KANJI_LEVEL4, // 霰 + 0x9739, KANJI_LEVEL4, // 霹 + 0x973D, KANJI_LEVEL4, // 霜 + 0x973E, KANJI_LEVEL4, // 霟 + 0x9744, KANJI_LEVEL4, // 靄 + 0x9746, KANJI_LEVEL4, // 靆 + 0x9748, KANJI_LEVEL4, // 靈 + 0x9742, KANJI_LEVEL4, // 靂 + 0x9749, KANJI_LEVEL4, // 靉 + 0x975C, KANJI_LEVEL4, // 靜 + 0x9760, KANJI_LEVEL4, // 靠 + 0x9764, KANJI_LEVEL4, // 靀 + 0x9766, KANJI_LEVEL4, // 靊 + 0x9768, KANJI_LEVEL4, // 靚 + 0x52D2, KANJI_LEVEL4, // 勒 + 0x976B, KANJI_LEVEL4, // 靫 + 0x9771, KANJI_LEVEL4, // 靱 + 0x9779, KANJI_LEVEL4, // 靹 + 0x9785, KANJI_LEVEL4, // 鞅 + 0x977C, KANJI_LEVEL4, // 靌 + 0x9781, KANJI_LEVEL4, // 鞁 + 0x977A, KANJI_LEVEL4, // 靺 + 0x9786, KANJI_LEVEL4, // 鞆 + 0x978B, KANJI_LEVEL4, // 鞋 + 0x978F, KANJI_LEVEL4, // 鞏 + 0x9790, KANJI_LEVEL4, // 鞐 + 0x979C, KANJI_LEVEL4, // 鞜 + 0x97A8, KANJI_LEVEL4, // 鞚 + 0x97A6, KANJI_LEVEL4, // 鞊 + 0x97A3, KANJI_LEVEL4, // 鞣 + 0x97B3, KANJI_LEVEL4, // 鞳 + 0x97B4, KANJI_LEVEL4, // 鞮 + 0x97C3, KANJI_LEVEL4, // 韃 + 0x97C6, KANJI_LEVEL4, // 韆 + 0x97C8, KANJI_LEVEL4, // 韈 + 0x97CB, KANJI_LEVEL4, // 韋 + 0x97DC, KANJI_LEVEL4, // 韜 + 0x97ED, KANJI_LEVEL4, // 韭 + 0x9F4F, KANJI_LEVEL4, // 霏 + 0x97F2, KANJI_LEVEL4, // 韲 + 0x7ADF, KANJI_LEVEL4, // 竟 + 0x97F6, KANJI_LEVEL4, // 韶 + 0x97F5, KANJI_LEVEL4, // 韵 + 0x980F, KANJI_LEVEL4, // 頏 + 0x980C, KANJI_LEVEL4, // 頌 + 0x9838, KANJI_LEVEL4, // é ž + 0x9824, KANJI_LEVEL4, // é € + 0x9821, KANJI_LEVEL4, // é ¡ + 0x9837, KANJI_LEVEL4, // é · + 0x983D, KANJI_LEVEL4, // é œ + 0x9846, KANJI_LEVEL4, // 顆 + 0x984F, KANJI_LEVEL4, // 顏 + 0x984B, KANJI_LEVEL4, // 顋 + 0x986B, KANJI_LEVEL4, // é¡« + 0x986F, KANJI_LEVEL4, // 顯 + 0x9870, KANJI_LEVEL4, // é¡° + 0x9871, KANJI_LEVEL4, // 顱 + 0x9874, KANJI_LEVEL4, // 顎 + 0x9873, KANJI_LEVEL4, // 顳 + 0x98AA, KANJI_LEVEL4, // 颪 + 0x98AF, KANJI_LEVEL4, // 颯 + 0x98B1, KANJI_LEVEL4, // 颱 + 0x98B6, KANJI_LEVEL4, // 颶 + 0x98C4, KANJI_LEVEL4, // 飄 + 0x98C3, KANJI_LEVEL4, // 飃 + 0x98C6, KANJI_LEVEL4, // 飆 + 0x98E9, KANJI_LEVEL4, // 飩 + 0x98EB, KANJI_LEVEL4, // 飫 + 0x9903, KANJI_LEVEL4, // 逃 + 0x9909, KANJI_LEVEL4, // 选 + 0x9912, KANJI_LEVEL4, // 递 + 0x9914, KANJI_LEVEL4, // 途 + 0x9918, KANJI_LEVEL4, // 逘 + 0x9921, KANJI_LEVEL4, // 逡 + 0x991D, KANJI_LEVEL4, // 逝 + 0x991E, KANJI_LEVEL4, // 逞 + 0x9924, KANJI_LEVEL4, // 退 + 0x9920, KANJI_LEVEL4, // 造 + 0x992C, KANJI_LEVEL4, // 逬 + 0x992E, KANJI_LEVEL4, // 逮 + 0x993D, KANJI_LEVEL4, // 逜 + 0x993E, KANJI_LEVEL4, // 速 + 0x9942, KANJI_LEVEL4, // 饂 + 0x9949, KANJI_LEVEL4, // 饉 + 0x9945, KANJI_LEVEL4, // 饅 + 0x9950, KANJI_LEVEL4, // 饐 + 0x994B, KANJI_LEVEL4, // 饋 + 0x9951, KANJI_LEVEL4, // 饑 + 0x9952, KANJI_LEVEL4, // 饒 + 0x994C, KANJI_LEVEL4, // 饌 + 0x9955, KANJI_LEVEL4, // 饕 + 0x9997, KANJI_LEVEL4, // 驗 + 0x9998, KANJI_LEVEL4, // 銘 + 0x99A5, KANJI_LEVEL4, // 銥 + 0x99AD, KANJI_LEVEL4, // 銭 + 0x99AE, KANJI_LEVEL4, // 銮 + 0x99BC, KANJI_LEVEL4, // 銌 + 0x99DF, KANJI_LEVEL4, // 駟 + 0x99DB, KANJI_LEVEL4, // 駛 + 0x99DD, KANJI_LEVEL4, // 駝 + 0x99D8, KANJI_LEVEL4, // 駘 + 0x99D1, KANJI_LEVEL4, // 駑 + 0x99ED, KANJI_LEVEL4, // é§­ + 0x99EE, KANJI_LEVEL4, // é§® + 0x99F1, KANJI_LEVEL4, // é§± + 0x99F2, KANJI_LEVEL4, // é§² + 0x99FB, KANJI_LEVEL4, // é§» + 0x99F8, KANJI_LEVEL4, // é§ž + 0x9A01, KANJI_LEVEL4, // 隁 + 0x9A0F, KANJI_LEVEL4, // 随 + 0x9A05, KANJI_LEVEL4, // 鹅 + 0x99E2, KANJI_LEVEL4, // é§¢ + 0x9A19, KANJI_LEVEL4, // 鹙 + 0x9A2B, KANJI_LEVEL4, // éš« + 0x9A37, KANJI_LEVEL4, // éš· + 0x9A45, KANJI_LEVEL4, // 驅 + 0x9A42, KANJI_LEVEL4, // 驂 + 0x9A40, KANJI_LEVEL4, // 驀 + 0x9A43, KANJI_LEVEL4, // 驃 + 0x9A3E, KANJI_LEVEL4, // 隟 + 0x9A55, KANJI_LEVEL4, // 驕 + 0x9A4D, KANJI_LEVEL4, // 驍 + 0x9A5B, KANJI_LEVEL4, // 驛 + 0x9A57, KANJI_LEVEL4, // 驗 + 0x9A5F, KANJI_LEVEL4, // 驟 + 0x9A62, KANJI_LEVEL4, // é©¢ + 0x9A65, KANJI_LEVEL4, // é©¥ + 0x9A64, KANJI_LEVEL4, // é©€ + 0x9A69, KANJI_LEVEL4, // é©© + 0x9A6B, KANJI_LEVEL4, // é©« + 0x9A6A, KANJI_LEVEL4, // 驪 + 0x9AAD, KANJI_LEVEL4, // 骭 + 0x9AB0, KANJI_LEVEL4, // 骰 + 0x9ABC, KANJI_LEVEL4, // 验 + 0x9AC0, KANJI_LEVEL4, // 髀 + 0x9ACF, KANJI_LEVEL4, // 髏 + 0x9AD1, KANJI_LEVEL4, // 髑 + 0x9AD3, KANJI_LEVEL4, // 髓 + 0x9AD4, KANJI_LEVEL4, // 體 + 0x9ADE, KANJI_LEVEL4, // 髞 + 0x9ADF, KANJI_LEVEL4, // 髟 + 0x9AE2, KANJI_LEVEL4, // é«¢ + 0x9AE3, KANJI_LEVEL4, // é«£ + 0x9AE6, KANJI_LEVEL4, // 髊 + 0x9AEF, KANJI_LEVEL4, // 髯 + 0x9AEB, KANJI_LEVEL4, // é«« + 0x9AEE, KANJI_LEVEL4, // é«® + 0x9AF4, KANJI_LEVEL4, // 髎 + 0x9AF1, KANJI_LEVEL4, // 髱 + 0x9AF7, KANJI_LEVEL4, // é«· + 0x9AFB, KANJI_LEVEL4, // é«» + 0x9B06, KANJI_LEVEL4, // 鬆 + 0x9B18, KANJI_LEVEL4, // 鬘 + 0x9B1A, KANJI_LEVEL4, // 鬚 + 0x9B1F, KANJI_LEVEL4, // 鬟 + 0x9B22, KANJI_LEVEL4, // 鬢 + 0x9B23, KANJI_LEVEL4, // 鬣 + 0x9B25, KANJI_LEVEL4, // 鬥 + 0x9B27, KANJI_LEVEL4, // 鬧 + 0x9B28, KANJI_LEVEL4, // 鬚 + 0x9B29, KANJI_LEVEL4, // 鬩 + 0x9B2A, KANJI_LEVEL4, // 鬪 + 0x9B2E, KANJI_LEVEL4, // 鬮 + 0x9B2F, KANJI_LEVEL4, // 鬯 + 0x9B32, KANJI_LEVEL4, // 鬲 + 0x9B44, KANJI_LEVEL4, // 魄 + 0x9B43, KANJI_LEVEL4, // 魃 + 0x9B4F, KANJI_LEVEL4, // 魏 + 0x9B4D, KANJI_LEVEL4, // 魍 + 0x9B4E, KANJI_LEVEL4, // 魎 + 0x9B51, KANJI_LEVEL4, // 魑 + 0x9B58, KANJI_LEVEL4, // 魘 + 0x9B74, KANJI_LEVEL4, // é­Ž + 0x9B93, KANJI_LEVEL4, // 鮓 + 0x9B83, KANJI_LEVEL4, // 鮃 + 0x9B91, KANJI_LEVEL4, // 鮑 + 0x9B96, KANJI_LEVEL4, // 鮖 + 0x9B97, KANJI_LEVEL4, // 鮗 + 0x9B9F, KANJI_LEVEL4, // 鮟 + 0x9BA0, KANJI_LEVEL4, // é®  + 0x9BA8, KANJI_LEVEL4, // 鮚 + 0x9BB4, KANJI_LEVEL4, // 鮎 + 0x9BC0, KANJI_LEVEL4, // 鯀 + 0x9BCA, KANJI_LEVEL4, // 鯊 + 0x9BB9, KANJI_LEVEL4, // 鮹 + 0x9BC6, KANJI_LEVEL4, // 鯆 + 0x9BCF, KANJI_LEVEL4, // 鯏 + 0x9BD1, KANJI_LEVEL4, // 鯑 + 0x9BD2, KANJI_LEVEL4, // 鯒 + 0x9BE3, KANJI_LEVEL4, // 鯣 + 0x9BE2, KANJI_LEVEL4, // 鯢 + 0x9BE4, KANJI_LEVEL4, // 鯀 + 0x9BD4, KANJI_LEVEL4, // 鯔 + 0x9BE1, KANJI_LEVEL4, // 鯡 + 0x9C3A, KANJI_LEVEL4, // é°º + 0x9BF2, KANJI_LEVEL4, // 鯲 + 0x9BF1, KANJI_LEVEL4, // 鯱 + 0x9BF0, KANJI_LEVEL4, // 鯰 + 0x9C15, KANJI_LEVEL4, // 鰕 + 0x9C14, KANJI_LEVEL4, // 鰔 + 0x9C09, KANJI_LEVEL4, // 鰉 + 0x9C13, KANJI_LEVEL4, // 鰓 + 0x9C0C, KANJI_LEVEL4, // 鰌 + 0x9C06, KANJI_LEVEL4, // 鰆 + 0x9C08, KANJI_LEVEL4, // 鰈 + 0x9C12, KANJI_LEVEL4, // 鰒 + 0x9C0A, KANJI_LEVEL4, // 鰊 + 0x9C04, KANJI_LEVEL4, // 鰄 + 0x9C2E, KANJI_LEVEL4, // é°® + 0x9C1B, KANJI_LEVEL4, // 鰛 + 0x9C25, KANJI_LEVEL4, // é°¥ + 0x9C24, KANJI_LEVEL4, // é°€ + 0x9C21, KANJI_LEVEL4, // é°¡ + 0x9C30, KANJI_LEVEL4, // é°° + 0x9C47, KANJI_LEVEL4, // 鱇 + 0x9C32, KANJI_LEVEL4, // é°² + 0x9C46, KANJI_LEVEL4, // 鱆 + 0x9C3E, KANJI_LEVEL4, // é°Ÿ + 0x9C5A, KANJI_LEVEL4, // 鱚 + 0x9C60, KANJI_LEVEL4, // é±  + 0x9C67, KANJI_LEVEL4, // é±§ + 0x9C76, KANJI_LEVEL4, // é±¶ + 0x9C78, KANJI_LEVEL4, // 鱞 + 0x9CE7, KANJI_LEVEL4, // é³§ + 0x9CEC, KANJI_LEVEL4, // 鳬 + 0x9CF0, KANJI_LEVEL4, // é³° + 0x9D09, KANJI_LEVEL4, // 鮉 + 0x9D08, KANJI_LEVEL4, // 鎈 + 0x9CEB, KANJI_LEVEL4, // 鳫 + 0x9D03, KANJI_LEVEL4, // 鎃 + 0x9D06, KANJI_LEVEL4, // 鮆 + 0x9D2A, KANJI_LEVEL4, // 鎪 + 0x9D26, KANJI_LEVEL4, // 鎊 + 0x9DAF, KANJI_LEVEL4, // 鶯 + 0x9D23, KANJI_LEVEL4, // 鎣 + 0x9D1F, KANJI_LEVEL4, // 鮟 + 0x9D44, KANJI_LEVEL4, // 鵄 + 0x9D15, KANJI_LEVEL4, // 鮕 + 0x9D12, KANJI_LEVEL4, // 鮒 + 0x9D41, KANJI_LEVEL4, // 鵁 + 0x9D3F, KANJI_LEVEL4, // 鎿 + 0x9D3E, KANJI_LEVEL4, // 鎟 + 0x9D46, KANJI_LEVEL4, // 鵆 + 0x9D48, KANJI_LEVEL4, // 鵈 + 0x9D5D, KANJI_LEVEL4, // 鵝 + 0x9D5E, KANJI_LEVEL4, // 鵞 + 0x9D64, KANJI_LEVEL4, // éµ€ + 0x9D51, KANJI_LEVEL4, // 鵑 + 0x9D50, KANJI_LEVEL4, // 鵐 + 0x9D59, KANJI_LEVEL4, // 鵙 + 0x9D72, KANJI_LEVEL4, // éµ² + 0x9D89, KANJI_LEVEL4, // 鶉 + 0x9D87, KANJI_LEVEL4, // 鶇 + 0x9DAB, KANJI_LEVEL4, // é¶« + 0x9D6F, KANJI_LEVEL4, // 鵯 + 0x9D7A, KANJI_LEVEL4, // 鵺 + 0x9D9A, KANJI_LEVEL4, // 鶚 + 0x9DA4, KANJI_LEVEL4, // é¶€ + 0x9DA9, KANJI_LEVEL4, // é¶© + 0x9DB2, KANJI_LEVEL4, // é¶² + 0x9DC4, KANJI_LEVEL4, // 鷄 + 0x9DC1, KANJI_LEVEL4, // 鷁 + 0x9DBB, KANJI_LEVEL4, // é¶» + 0x9DB8, KANJI_LEVEL4, // é¶ž + 0x9DBA, KANJI_LEVEL4, // 鶺 + 0x9DC6, KANJI_LEVEL4, // 鷆 + 0x9DCF, KANJI_LEVEL4, // 鷏 + 0x9DC2, KANJI_LEVEL4, // 鷂 + 0x9DD9, KANJI_LEVEL4, // 鷙 + 0x9DD3, KANJI_LEVEL4, // 鷓 + 0x9DF8, KANJI_LEVEL4, // é·ž + 0x9DE6, KANJI_LEVEL4, // é·Š + 0x9DED, KANJI_LEVEL4, // é·­ + 0x9DEF, KANJI_LEVEL4, // é·¯ + 0x9DFD, KANJI_LEVEL4, // é·œ + 0x9E1A, KANJI_LEVEL4, // 龚 + 0x9E1B, KANJI_LEVEL4, // 龛 + 0x9E1E, KANJI_LEVEL4, // 龞 + 0x9E75, KANJI_LEVEL4, // é¹µ + 0x9E79, KANJI_LEVEL4, // é¹¹ + 0x9E7D, KANJI_LEVEL4, // 鹜 + 0x9E81, KANJI_LEVEL4, // 麁 + 0x9E88, KANJI_LEVEL4, // 麈 + 0x9E8B, KANJI_LEVEL4, // 麋 + 0x9E8C, KANJI_LEVEL4, // 麌 + 0x9E92, KANJI_LEVEL4, // 麒 + 0x9E95, KANJI_LEVEL4, // 麕 + 0x9E91, KANJI_LEVEL4, // 麑 + 0x9E9D, KANJI_LEVEL4, // 麝 + 0x9EA5, KANJI_LEVEL4, // 麥 + 0x9EA9, KANJI_LEVEL4, // 麩 + 0x9EB8, KANJI_LEVEL4, // 麞 + 0x9EAA, KANJI_LEVEL4, // 麪 + 0x9EAD, KANJI_LEVEL4, // 麭 + 0x9761, KANJI_LEVEL4, // 靡 + 0x9ECC, KANJI_LEVEL4, // 黌 + 0x9ECE, KANJI_LEVEL4, // 黎 + 0x9ECF, KANJI_LEVEL4, // 黏 + 0x9ED0, KANJI_LEVEL4, // 黐 + 0x9ED4, KANJI_LEVEL4, // 黔 + 0x9EDC, KANJI_LEVEL4, // 黜 + 0x9EDE, KANJI_LEVEL4, // 點 + 0x9EDD, KANJI_LEVEL4, // 黝 + 0x9EE0, KANJI_LEVEL4, // é»  + 0x9EE5, KANJI_LEVEL4, // 黥 + 0x9EE8, KANJI_LEVEL4, // 黚 + 0x9EEF, KANJI_LEVEL4, // 黯 + 0x9EF4, KANJI_LEVEL4, // 黎 + 0x9EF6, KANJI_LEVEL4, // é»¶ + 0x9EF7, KANJI_LEVEL4, // é»· + 0x9EF9, KANJI_LEVEL4, // 黹 + 0x9EFB, KANJI_LEVEL4, // é»» + 0x9EFC, KANJI_LEVEL4, // 黌 + 0x9EFD, KANJI_LEVEL4, // 黜 + 0x9F07, KANJI_LEVEL4, // 錇 + 0x9F08, KANJI_LEVEL4, // 錈 + 0x76B7, KANJI_LEVEL4, // 皷 + 0x9F15, KANJI_LEVEL4, // 錕 + 0x9F21, KANJI_LEVEL4, // 錡 + 0x9F2C, KANJI_LEVEL4, // 錬 + 0x9F3E, KANJI_LEVEL4, // 錟 + 0x9F4A, KANJI_LEVEL4, // 霊 + 0x9F52, KANJI_LEVEL4, // 霒 + 0x9F54, KANJI_LEVEL4, // 霔 + 0x9F63, KANJI_LEVEL4, // 霣 + 0x9F5F, KANJI_LEVEL4, // 霟 + 0x9F60, KANJI_LEVEL4, // 霠 + 0x9F61, KANJI_LEVEL4, // 霡 + 0x9F66, KANJI_LEVEL4, // 霊 + 0x9F67, KANJI_LEVEL4, // 霧 + 0x9F6C, KANJI_LEVEL4, // 霬 + 0x9F6A, KANJI_LEVEL4, // 霪 + 0x9F77, KANJI_LEVEL4, // 霷 + 0x9F72, KANJI_LEVEL4, // 露 + 0x9F76, KANJI_LEVEL4, // 霶 + 0x9F95, KANJI_LEVEL4, // 韕 + 0x9F9C, KANJI_LEVEL4, // 韜 + 0x9FA0, KANJI_LEVEL4, // 韠 + 0x582F, KANJI_LEVEL4, // å ¯ + 0x69C7, KANJI_LEVEL4, // 槇 + 0x9059, KANJI_LEVEL4, // 遙 + 0x7464, KANJI_LEVEL4, // ç‘€ + 0x51DC, KANJI_LEVEL4, // 凜 + 0x7199, KANJI_LEVEL4, // 熙 + 0x5653, KANJI_LEVEL4, // 噓 + 0x5DE2, KANJI_LEVEL4, // å·¢ + 0x5E14, KANJI_LEVEL4, // åž” + 0x5E18, KANJI_LEVEL4, // 垘 + 0x5E58, KANJI_LEVEL4, // 幘 + 0x5E5E, KANJI_LEVEL4, // 幞 + 0x5EBE, KANJI_LEVEL4, // 废 + 0xF928, KANJI_LEVEL4, //  + 0x5ECB, KANJI_LEVEL4, // 廋 + 0x5EF9, KANJI_LEVEL4, // 廹 + 0x5F00, KANJI_LEVEL4, // 匀 + 0x5F02, KANJI_LEVEL4, // 匂 + 0x5F07, KANJI_LEVEL4, // 匇 + 0x5F1D, KANJI_LEVEL4, // 匝 + 0x5F23, KANJI_LEVEL4, // 匣 + 0x5F34, KANJI_LEVEL4, // 匎 + 0x5F36, KANJI_LEVEL4, // 匶 + 0x5F3D, KANJI_LEVEL4, // 匜 + 0x5F40, KANJI_LEVEL4, // 圀 + 0x5F45, KANJI_LEVEL4, // 圅 + 0x5F54, KANJI_LEVEL4, // 圔 + 0x5F58, KANJI_LEVEL4, // 團 + 0x5F64, KANJI_LEVEL4, // 圀 + 0x5F67, KANJI_LEVEL4, // 圧 + 0x5F7D, KANJI_LEVEL4, // 圜 + 0x5F89, KANJI_LEVEL4, // 埉 + 0x5F9C, KANJI_LEVEL4, // 埜 + 0x5FA7, KANJI_LEVEL4, // 埧 + 0x5FAF, KANJI_LEVEL4, // 埯 + 0x5FB5, KANJI_LEVEL4, // 埵 + 0x5FB7, KANJI_LEVEL4, // 執 + 0x5FC9, KANJI_LEVEL4, // 忉 + 0x5FDE, KANJI_LEVEL4, // 忞 + 0x5FE1, KANJI_LEVEL4, // å¿¡ + 0x5FE9, KANJI_LEVEL4, // å¿© + 0x600D, KANJI_LEVEL4, // 怍 + 0x6014, KANJI_LEVEL4, // 怔 + 0x6018, KANJI_LEVEL4, // 怘 + 0x6033, KANJI_LEVEL4, // 怳 + 0x6035, KANJI_LEVEL4, // 怵 + 0x6047, KANJI_LEVEL4, // 恇 + 0xFA3D, KANJI_LEVEL4, // ïšœ + 0x609D, KANJI_LEVEL4, // 悝 + 0x609E, KANJI_LEVEL4, // 悞 + 0x60CB, KANJI_LEVEL4, // 惋 + 0x60D4, KANJI_LEVEL4, // 惔 + 0x60D5, KANJI_LEVEL4, // 惕 + 0x60DD, KANJI_LEVEL4, // 惝 + 0x60F8, KANJI_LEVEL4, // 惞 + 0x611C, KANJI_LEVEL4, // 愜 + 0x612B, KANJI_LEVEL4, // 愫 + 0x6130, KANJI_LEVEL4, // 愰 + 0x6137, KANJI_LEVEL4, // 愷 + 0xFA3E, KANJI_LEVEL4, //  + 0x618D, KANJI_LEVEL4, // 憍 + 0xFA3F, KANJI_LEVEL4, // ïš¿ + 0x61BC, KANJI_LEVEL4, // 憌 + 0x61B9, KANJI_LEVEL4, // 憹 + 0xFA40, KANJI_LEVEL4, // 懲 + 0x6222, KANJI_LEVEL4, // 戢 + 0x623E, KANJI_LEVEL4, // 戟 + 0x6243, KANJI_LEVEL4, // 扃 + 0x6256, KANJI_LEVEL4, // 扖 + 0x625A, KANJI_LEVEL4, // 扚 + 0x626F, KANJI_LEVEL4, // 扯 + 0x6285, KANJI_LEVEL4, // 抅 + 0x62C4, KANJI_LEVEL4, // 拄 + 0x62D6, KANJI_LEVEL4, // 拖 + 0x62FC, KANJI_LEVEL4, // 拌 + 0x630A, KANJI_LEVEL4, // 挊 + 0x6318, KANJI_LEVEL4, // 挘 + 0x6339, KANJI_LEVEL4, // 挹 + 0x6343, KANJI_LEVEL4, // 捃 + 0x6365, KANJI_LEVEL4, // 捥 + 0x637C, KANJI_LEVEL4, // 捌 + 0x63E5, KANJI_LEVEL4, // 揥 + 0x63ED, KANJI_LEVEL4, // 揭 + 0x63F5, KANJI_LEVEL4, // 揵 + 0x6410, KANJI_LEVEL4, // 搐 + 0x6414, KANJI_LEVEL4, // 搔 + 0x6422, KANJI_LEVEL4, // 搢 + 0x6479, KANJI_LEVEL4, // 摹 + 0x6451, KANJI_LEVEL4, // 摑 + 0x6460, KANJI_LEVEL4, // 摠 + 0x646D, KANJI_LEVEL4, // 摭 + 0x64CE, KANJI_LEVEL4, // 擎 + 0x64BE, KANJI_LEVEL4, // æ’Ÿ + 0x64BF, KANJI_LEVEL4, // 撿 + 0x64C4, KANJI_LEVEL4, // 擄 + 0x64CA, KANJI_LEVEL4, // 擊 + 0x64D0, KANJI_LEVEL4, // 擐 + 0x64F7, KANJI_LEVEL4, // 擷 + 0x64FB, KANJI_LEVEL4, // 擻 + 0x6522, KANJI_LEVEL4, // 攢 + 0x6529, KANJI_LEVEL4, // 攩 + 0xFA41, KANJI_LEVEL4, // 敏 + 0x6567, KANJI_LEVEL4, // 敧 + 0x659D, KANJI_LEVEL4, // 斝 + 0xFA42, KANJI_LEVEL4, // 既 + 0x6600, KANJI_LEVEL4, // 昀 + 0x6609, KANJI_LEVEL4, // 昉 + 0x6615, KANJI_LEVEL4, // 昕 + 0x661E, KANJI_LEVEL4, // 昞 + 0x663A, KANJI_LEVEL4, // 昺 + 0x6622, KANJI_LEVEL4, // 昢 + 0x6624, KANJI_LEVEL4, // 昀 + 0x662B, KANJI_LEVEL4, // 昫 + 0x6630, KANJI_LEVEL4, // 昰 + 0x6631, KANJI_LEVEL4, // 昱 + 0x6633, KANJI_LEVEL4, // 昳 + 0x66FB, KANJI_LEVEL4, // 曻 + 0x6648, KANJI_LEVEL4, // 晈 + 0x664C, KANJI_LEVEL4, // 晌 + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDDC4, KANJI_LEVEL4, // ᅵ + 0x6659, KANJI_LEVEL4, // 晙 + 0x665A, KANJI_LEVEL4, // 晚 + 0x6661, KANJI_LEVEL4, // 晡 + 0x6665, KANJI_LEVEL4, // 晥 + 0x6673, KANJI_LEVEL4, // 晳 + 0x6677, KANJI_LEVEL4, // 晷 + 0x6678, KANJI_LEVEL4, // 晞 + 0x668D, KANJI_LEVEL4, // 暍 + 0xFA43, KANJI_LEVEL4, // 暑 + 0x66A0, KANJI_LEVEL4, // 暠 + 0x66B2, KANJI_LEVEL4, // 暲 + 0x66BB, KANJI_LEVEL4, // 暻 + 0x66C6, KANJI_LEVEL4, // 曆 + 0x66C8, KANJI_LEVEL4, // 曈 + 0x3B22, KANJI_LEVEL4, // 㬢 + 0x66DB, KANJI_LEVEL4, // 曛 + 0x66E8, KANJI_LEVEL4, // 曚 + 0x66FA, KANJI_LEVEL4, // 曺 + 0x6713, KANJI_LEVEL4, // 朓 + 0xF929, KANJI_LEVEL4, //  + 0x6733, KANJI_LEVEL4, // 朳 + 0x6766, KANJI_LEVEL4, // 杊 + 0x6747, KANJI_LEVEL4, // 杇 + 0x6748, KANJI_LEVEL4, // 杈 + 0x677B, KANJI_LEVEL4, // 杻 + 0x6781, KANJI_LEVEL4, // 极 + 0x6793, KANJI_LEVEL4, // 枓 + 0x6798, KANJI_LEVEL4, // 枘 + 0x679B, KANJI_LEVEL4, // 枛 + 0x67BB, KANJI_LEVEL4, // 枻 + 0x67F9, KANJI_LEVEL4, // 柹 + 0x67C0, KANJI_LEVEL4, // 柀 + 0x67D7, KANJI_LEVEL4, // 柗 + 0x67FC, KANJI_LEVEL4, // 柌 + 0x6801, KANJI_LEVEL4, // 栁 + 0x6852, KANJI_LEVEL4, // 桒 + 0x681D, KANJI_LEVEL4, // 栝 + 0x682C, KANJI_LEVEL4, // æ ¬ + 0x6831, KANJI_LEVEL4, // æ ± + 0x685B, KANJI_LEVEL4, // 桛 + 0x6872, KANJI_LEVEL4, // 桲 + 0x6875, KANJI_LEVEL4, // 桵 + 0xFA44, KANJI_LEVEL4, // 梅 + 0x68A3, KANJI_LEVEL4, // 梣 + 0x68A5, KANJI_LEVEL4, // 梥 + 0x68B2, KANJI_LEVEL4, // 梲 + 0x68C8, KANJI_LEVEL4, // 棈 + 0x68D0, KANJI_LEVEL4, // 棐 + 0x68E8, KANJI_LEVEL4, // 棚 + 0x68ED, KANJI_LEVEL4, // 棭 + 0x68F0, KANJI_LEVEL4, // 棰 + 0x68F1, KANJI_LEVEL4, // 棱 + 0x68FC, KANJI_LEVEL4, // 棌 + 0x690A, KANJI_LEVEL4, // 怊 + 0x6949, KANJI_LEVEL4, // 楉 + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDDC4, KANJI_LEVEL4, // ᅵ + 0x6935, KANJI_LEVEL4, // 怵 + 0x6942, KANJI_LEVEL4, // 楂 + 0x6957, KANJI_LEVEL4, // 楗 + 0x6963, KANJI_LEVEL4, // 楣 + 0x6964, KANJI_LEVEL4, // 楀 + 0x6968, KANJI_LEVEL4, // 楚 + 0x6980, KANJI_LEVEL4, // 技 + 0xFA14, KANJI_LEVEL4, // ïš” + 0x69A5, KANJI_LEVEL4, // 报 + 0x69AD, KANJI_LEVEL4, // 抭 + 0x69CF, KANJI_LEVEL4, // 槏 + 0x3BB6, KANJI_LEVEL4, // ã®¶ + 0x3BC3, KANJI_LEVEL4, // 㯃 + 0x69E2, KANJI_LEVEL4, // æ§¢ + 0x69E9, KANJI_LEVEL4, // æ§© + 0x69EA, KANJI_LEVEL4, // 槪 + 0x69F5, KANJI_LEVEL4, // æ§µ + 0x69F6, KANJI_LEVEL4, // æ§¶ + 0x6A0F, KANJI_LEVEL4, // 暏 + 0x6A15, KANJI_LEVEL4, // æš• + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDF3F, KANJI_LEVEL4, // ᅵ + 0x6A3B, KANJI_LEVEL4, // æš» + 0x6A3E, KANJI_LEVEL4, // 暟 + 0x6A45, KANJI_LEVEL4, // 橅 + 0x6A50, KANJI_LEVEL4, // 橐 + 0x6A56, KANJI_LEVEL4, // 橖 + 0x6A5B, KANJI_LEVEL4, // 橛 + 0x6A6B, KANJI_LEVEL4, // æ©« + 0x6A73, KANJI_LEVEL4, // 橳 + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDF63, KANJI_LEVEL4, // ᅵ + 0x6A89, KANJI_LEVEL4, // 檉 + 0x6A94, KANJI_LEVEL4, // 檔 + 0x6A9D, KANJI_LEVEL4, // 檝 + 0x6A9E, KANJI_LEVEL4, // 檞 + 0x6AA5, KANJI_LEVEL4, // 檥 + 0x6AE4, KANJI_LEVEL4, // æ«€ + 0x6AE7, KANJI_LEVEL4, // æ«§ + 0x3C0F, KANJI_LEVEL4, // 㰏 + 0xF91D, KANJI_LEVEL4, //  + 0x6B1B, KANJI_LEVEL4, // 欛 + 0x6B1E, KANJI_LEVEL4, // 欞 + 0x6B2C, KANJI_LEVEL4, // 欬 + 0x6B35, KANJI_LEVEL4, // 欵 + 0x6B46, KANJI_LEVEL4, // 歆 + 0x6B56, KANJI_LEVEL4, // 歖 + 0x6B60, KANJI_LEVEL4, // æ­  + 0x6B65, KANJI_LEVEL4, // æ­¥ + 0x6B67, KANJI_LEVEL4, // æ­§ + 0x6B77, KANJI_LEVEL4, // æ­· + 0x6B82, KANJI_LEVEL4, // 殂 + 0x6BA9, KANJI_LEVEL4, // 殩 + 0x6BAD, KANJI_LEVEL4, // æ®­ + 0xF970, KANJI_LEVEL4, // 殺 + 0x6BCF, KANJI_LEVEL4, // 每 + 0x6BD6, KANJI_LEVEL4, // 毖 + 0x6BD7, KANJI_LEVEL4, // 毗 + 0x6BFF, KANJI_LEVEL4, // 毿 + 0x6C05, KANJI_LEVEL4, // 氅 + 0x6C10, KANJI_LEVEL4, // 氐 + 0x6C33, KANJI_LEVEL4, // æ°³ + 0x6C59, KANJI_LEVEL4, // 汙 + 0x6C5C, KANJI_LEVEL4, // 汜 + 0x6CAA, KANJI_LEVEL4, // 沪 + 0x6C74, KANJI_LEVEL4, // 汎 + 0x6C76, KANJI_LEVEL4, // æ±¶ + 0x6C85, KANJI_LEVEL4, // 沅 + 0x6C86, KANJI_LEVEL4, // 沆 + 0x6C98, KANJI_LEVEL4, // 沘 + 0x6C9C, KANJI_LEVEL4, // 沜 + 0x6CFB, KANJI_LEVEL4, // æ³» + 0x6CC6, KANJI_LEVEL4, // 泆 + 0x6CD4, KANJI_LEVEL4, // 泔 + 0x6CE0, KANJI_LEVEL4, // æ³  + 0x6CEB, KANJI_LEVEL4, // 泫 + 0x6CEE, KANJI_LEVEL4, // æ³® + 0xD84F, KANJI_LEVEL4, // ᅵ + 0xDCFE, KANJI_LEVEL4, // ᅵ + 0x6D04, KANJI_LEVEL4, // 掄 + 0x6D0E, KANJI_LEVEL4, // 掎 + 0x6D2E, KANJI_LEVEL4, // 掮 + 0x6D31, KANJI_LEVEL4, // 掱 + 0x6D39, KANJI_LEVEL4, // 掹 + 0x6D3F, KANJI_LEVEL4, // 掿 + 0x6D58, KANJI_LEVEL4, // 浘 + 0x6D65, KANJI_LEVEL4, // æµ¥ + 0xFA45, KANJI_LEVEL4, // 海 + 0x6D82, KANJI_LEVEL4, // 涂 + 0x6D87, KANJI_LEVEL4, // 涇 + 0x6D89, KANJI_LEVEL4, // 涉 + 0x6D94, KANJI_LEVEL4, // 涔 + 0x6DAA, KANJI_LEVEL4, // 涪 + 0x6DAC, KANJI_LEVEL4, // 涬 + 0x6DBF, KANJI_LEVEL4, // æ¶¿ + 0x6DC4, KANJI_LEVEL4, // 淄 + 0x6DD6, KANJI_LEVEL4, // 淖 + 0x6DDA, KANJI_LEVEL4, // 淚 + 0x6DDB, KANJI_LEVEL4, // 淛 + 0x6DDD, KANJI_LEVEL4, // 淝 + 0x6DFC, KANJI_LEVEL4, // æ·Œ + 0xFA46, KANJI_LEVEL4, // 渚 + 0x6E34, KANJI_LEVEL4, // 枎 + 0x6E44, KANJI_LEVEL4, // 湄 + 0x6E5C, KANJI_LEVEL4, // 湜 + 0x6E5E, KANJI_LEVEL4, // 湞 + 0x6EAB, KANJI_LEVEL4, // 溫 + 0x6EB1, KANJI_LEVEL4, // 溱 + 0x6EC1, KANJI_LEVEL4, // 滁 + 0x6EC7, KANJI_LEVEL4, // 滇 + 0x6ECE, KANJI_LEVEL4, // 滎 + 0x6F10, KANJI_LEVEL4, // 挐 + 0x6F1A, KANJI_LEVEL4, // 挚 + 0xFA47, KANJI_LEVEL4, // 漢 + 0x6F2A, KANJI_LEVEL4, // 挪 + 0x6F2F, KANJI_LEVEL4, // 振 + 0x6F33, KANJI_LEVEL4, // 挳 + 0x6F51, KANJI_LEVEL4, // 朑 + 0x6F59, KANJI_LEVEL4, // 朙 + 0x6F5E, KANJI_LEVEL4, // 朞 + 0x6F61, KANJI_LEVEL4, // 朡 + 0x6F62, KANJI_LEVEL4, // 朢 + 0x6F7E, KANJI_LEVEL4, // 期 + 0x6F88, KANJI_LEVEL4, // 柈 + 0x6F8C, KANJI_LEVEL4, // 柌 + 0x6F8D, KANJI_LEVEL4, // 柍 + 0x6F94, KANJI_LEVEL4, // 柔 + 0x6FA0, KANJI_LEVEL4, // 柠 + 0x6FA7, KANJI_LEVEL4, // 柧 + 0x6FB6, KANJI_LEVEL4, // 柶 + 0x6FBC, KANJI_LEVEL4, // 柌 + 0x6FC7, KANJI_LEVEL4, // 濇 + 0x6FCA, KANJI_LEVEL4, // 濊 + 0x6FF9, KANJI_LEVEL4, // 濹 + 0x6FF0, KANJI_LEVEL4, // æ¿° + 0x6FF5, KANJI_LEVEL4, // 濵 + 0x7005, KANJI_LEVEL4, // 瀅 + 0x7006, KANJI_LEVEL4, // 瀆 + 0x7028, KANJI_LEVEL4, // 瀹 + 0x704A, KANJI_LEVEL4, // 灊 + 0x705D, KANJI_LEVEL4, // 灝 + 0x705E, KANJI_LEVEL4, // 灞 + 0x704E, KANJI_LEVEL4, // 灎 + 0x7064, KANJI_LEVEL4, // 灀 + 0x7075, KANJI_LEVEL4, // 灵 + 0x7085, KANJI_LEVEL4, // 炅 + 0x70A4, KANJI_LEVEL4, // ç‚€ + 0x70AB, KANJI_LEVEL4, // 炫 + 0x70B7, KANJI_LEVEL4, // 炷 + 0x70D4, KANJI_LEVEL4, // 烔 + 0x70D8, KANJI_LEVEL4, // 烘 + 0x70E4, KANJI_LEVEL4, // 烀 + 0x710F, KANJI_LEVEL4, // 焏 + 0x712B, KANJI_LEVEL4, // 焫 + 0x711E, KANJI_LEVEL4, // 焞 + 0x7120, KANJI_LEVEL4, // 焠 + 0x712E, KANJI_LEVEL4, // 焮 + 0x7130, KANJI_LEVEL4, // 焰 + 0x7146, KANJI_LEVEL4, // 煆 + 0x7147, KANJI_LEVEL4, // 煇 + 0x7151, KANJI_LEVEL4, // 煑 + 0xFA48, KANJI_LEVEL4, // 煮 + 0x7152, KANJI_LEVEL4, // 煒 + 0x715C, KANJI_LEVEL4, // 煜 + 0x7160, KANJI_LEVEL4, // 煠 + 0x7168, KANJI_LEVEL4, // 煹 + 0xFA15, KANJI_LEVEL4, // ïš• + 0x7185, KANJI_LEVEL4, // 熅 + 0x7187, KANJI_LEVEL4, // 熇 + 0x7192, KANJI_LEVEL4, // 熒 + 0x71C1, KANJI_LEVEL4, // 燁 + 0x71BA, KANJI_LEVEL4, // 熺 + 0x71C4, KANJI_LEVEL4, // 燄 + 0x71FE, KANJI_LEVEL4, // 營 + 0x7200, KANJI_LEVEL4, // 爀 + 0x7215, KANJI_LEVEL4, // 爕 + 0x7255, KANJI_LEVEL4, // 牕 + 0x7256, KANJI_LEVEL4, // 牖 + 0x3E3F, KANJI_LEVEL4, // ãž¿ + 0x728D, KANJI_LEVEL4, // 犍 + 0x729B, KANJI_LEVEL4, // 犛 + 0x72BE, KANJI_LEVEL4, // 犟 + 0x72C0, KANJI_LEVEL4, // 狀 + 0x72FB, KANJI_LEVEL4, // 狻 + 0xD851, KANJI_LEVEL4, // ᅵ + 0xDFF1, KANJI_LEVEL4, // ᅵ + 0x7327, KANJI_LEVEL4, // 猧 + 0x7328, KANJI_LEVEL4, // 猹 + 0xFA16, KANJI_LEVEL4, // ïš– + 0x7350, KANJI_LEVEL4, // 獐 + 0x7366, KANJI_LEVEL4, // 獊 + 0x737C, KANJI_LEVEL4, // 獌 + 0x7395, KANJI_LEVEL4, // 玕 + 0x739F, KANJI_LEVEL4, // 玟 + 0x73A0, KANJI_LEVEL4, // 玠 + 0x73A2, KANJI_LEVEL4, // 玢 + 0x73A6, KANJI_LEVEL4, // 玊 + 0x73AB, KANJI_LEVEL4, // 玫 + 0x73C9, KANJI_LEVEL4, // 珉 + 0x73CF, KANJI_LEVEL4, // 珏 + 0x73D6, KANJI_LEVEL4, // 珖 + 0x73D9, KANJI_LEVEL4, // 珙 + 0x73E3, KANJI_LEVEL4, // 珣 + 0x73E9, KANJI_LEVEL4, // 珩 + 0x7407, KANJI_LEVEL4, // 琇 + 0x740A, KANJI_LEVEL4, // 琊 + 0x741A, KANJI_LEVEL4, // 琚 + 0x741B, KANJI_LEVEL4, // 琛 + 0xFA4A, KANJI_LEVEL4, // 琢 + 0x7426, KANJI_LEVEL4, // 琊 + 0x7428, KANJI_LEVEL4, // 琚 + 0x742A, KANJI_LEVEL4, // 琪 + 0x742B, KANJI_LEVEL4, // 琫 + 0x742C, KANJI_LEVEL4, // 琬 + 0x742E, KANJI_LEVEL4, // 琮 + 0x742F, KANJI_LEVEL4, // 琯 + 0x7430, KANJI_LEVEL4, // 琰 + 0x7444, KANJI_LEVEL4, // 瑄 + 0x7446, KANJI_LEVEL4, // 瑆 + 0x7447, KANJI_LEVEL4, // 瑇 + 0x744B, KANJI_LEVEL4, // 瑋 + 0x7457, KANJI_LEVEL4, // 瑗 + 0x7462, KANJI_LEVEL4, // 瑢 + 0x746B, KANJI_LEVEL4, // 瑫 + 0x746D, KANJI_LEVEL4, // 瑭 + 0x7486, KANJI_LEVEL4, // 璆 + 0x7487, KANJI_LEVEL4, // 璇 + 0x7489, KANJI_LEVEL4, // 璉 + 0x7498, KANJI_LEVEL4, // 璘 + 0x749C, KANJI_LEVEL4, // 璜 + 0x749F, KANJI_LEVEL4, // 璟 + 0x74A3, KANJI_LEVEL4, // 璣 + 0x7490, KANJI_LEVEL4, // 璐 + 0x74A6, KANJI_LEVEL4, // 璩 + 0x74A8, KANJI_LEVEL4, // 璹 + 0x74A9, KANJI_LEVEL4, // 璩 + 0x74B5, KANJI_LEVEL4, // 璵 + 0x74BF, KANJI_LEVEL4, // 璿 + 0x74C8, KANJI_LEVEL4, // 瓈 + 0x74C9, KANJI_LEVEL4, // 瓉 + 0x74DA, KANJI_LEVEL4, // 瓚 + 0x74FF, KANJI_LEVEL4, // 瓿 + 0x7501, KANJI_LEVEL4, // 甁 + 0x7517, KANJI_LEVEL4, // 甗 + 0x752F, KANJI_LEVEL4, // 甯 + 0x756F, KANJI_LEVEL4, // 畯 + 0x7579, KANJI_LEVEL4, // 畹 + 0x7592, KANJI_LEVEL4, // 疒 + 0x3F72, KANJI_LEVEL4, // 㜲 + 0x75CE, KANJI_LEVEL4, // 痎 + 0x75E4, KANJI_LEVEL4, // ç—€ + 0x7600, KANJI_LEVEL4, // 瘀 + 0x7602, KANJI_LEVEL4, // 瘂 + 0x7608, KANJI_LEVEL4, // 瘈 + 0x7615, KANJI_LEVEL4, // 瘕 + 0x7616, KANJI_LEVEL4, // 瘖 + 0x7619, KANJI_LEVEL4, // 瘙 + 0x761E, KANJI_LEVEL4, // 瘞 + 0x762D, KANJI_LEVEL4, // 瘭 + 0x7635, KANJI_LEVEL4, // 瘵 + 0x7643, KANJI_LEVEL4, // 癃 + 0x764B, KANJI_LEVEL4, // 癋 + 0x7664, KANJI_LEVEL4, // 癀 + 0x7665, KANJI_LEVEL4, // 癥 + 0x766D, KANJI_LEVEL4, // 癭 + 0x766F, KANJI_LEVEL4, // 癯 + 0x7671, KANJI_LEVEL4, // 癱 + 0x7681, KANJI_LEVEL4, // 皁 + 0x769B, KANJI_LEVEL4, // 皛 + 0x769D, KANJI_LEVEL4, // 皝 + 0x769E, KANJI_LEVEL4, // 皞 + 0x76A6, KANJI_LEVEL4, // 皩 + 0x76AA, KANJI_LEVEL4, // 皪 + 0x76B6, KANJI_LEVEL4, // 皶 + 0x76C5, KANJI_LEVEL4, // 盅 + 0x76CC, KANJI_LEVEL4, // 盌 + 0x76CE, KANJI_LEVEL4, // 盎 + 0x76D4, KANJI_LEVEL4, // 盔 + 0x76E6, KANJI_LEVEL4, // 盩 + 0x76F1, KANJI_LEVEL4, // 盱 + 0x76FC, KANJI_LEVEL4, // 盌 + 0x770A, KANJI_LEVEL4, // 眊 + 0x7719, KANJI_LEVEL4, // 眙 + 0x7734, KANJI_LEVEL4, // 眮 + 0x7736, KANJI_LEVEL4, // 眶 + 0x7746, KANJI_LEVEL4, // 睆 + 0x774D, KANJI_LEVEL4, // 睍 + 0x774E, KANJI_LEVEL4, // 睎 + 0x775C, KANJI_LEVEL4, // 睜 + 0x775F, KANJI_LEVEL4, // 睟 + 0x7762, KANJI_LEVEL4, // 睢 + 0x777A, KANJI_LEVEL4, // 睺 + 0x7780, KANJI_LEVEL4, // 瞀 + 0x7794, KANJI_LEVEL4, // 瞔 + 0x77AA, KANJI_LEVEL4, // 瞪 + 0x77E0, KANJI_LEVEL4, // 矠 + 0x782D, KANJI_LEVEL4, // ç ­ + 0xD855, KANJI_LEVEL4, // ᅵ + 0xDC8E, KANJI_LEVEL4, // ᅵ + 0x7843, KANJI_LEVEL4, // 硃 + 0x784E, KANJI_LEVEL4, // 硎 + 0x784F, KANJI_LEVEL4, // 硏 + 0x7851, KANJI_LEVEL4, // 硑 + 0x7868, KANJI_LEVEL4, // 硚 + 0x786E, KANJI_LEVEL4, // ç¡® + 0xFA4B, KANJI_LEVEL4, // 碑 + 0x78B0, KANJI_LEVEL4, // 碰 + 0xD855, KANJI_LEVEL4, // ᅵ + 0xDD0E, KANJI_LEVEL4, // ᅵ + 0x78AD, KANJI_LEVEL4, // 碭 + 0x78E4, KANJI_LEVEL4, // 磀 + 0x78F2, KANJI_LEVEL4, // 磲 + 0x7900, KANJI_LEVEL4, // 瀀 + 0x78F7, KANJI_LEVEL4, // 磷 + 0x791C, KANJI_LEVEL4, // 瀜 + 0x792E, KANJI_LEVEL4, // 瀮 + 0x7931, KANJI_LEVEL4, // 瀱 + 0x7934, KANJI_LEVEL4, // 瀎 + 0xFA4C, KANJI_LEVEL4, // 社 + 0xFA4D, KANJI_LEVEL4, // 祉 + 0x7945, KANJI_LEVEL4, // 祅 + 0x7946, KANJI_LEVEL4, // 祆 + 0xFA4E, KANJI_LEVEL4, // 祈 + 0xFA4F, KANJI_LEVEL4, // 祐 + 0xFA50, KANJI_LEVEL4, // 祖 + 0x795C, KANJI_LEVEL4, // 祜 + 0xFA51, KANJI_LEVEL4, // 祝 + 0xFA19, KANJI_LEVEL4, // ïš™ + 0xFA1A, KANJI_LEVEL4, // ïšš + 0x7979, KANJI_LEVEL4, // 祹 + 0xFA52, KANJI_LEVEL4, // 禍 + 0xFA53, KANJI_LEVEL4, // 禎 + 0xFA1B, KANJI_LEVEL4, // ïš› + 0x7998, KANJI_LEVEL4, // 犘 + 0x79B1, KANJI_LEVEL4, // 犱 + 0x79B8, KANJI_LEVEL4, // 犞 + 0x79C8, KANJI_LEVEL4, // 秈 + 0x79CA, KANJI_LEVEL4, // 秊 + 0xD855, KANJI_LEVEL4, // ᅵ + 0xDF71, KANJI_LEVEL4, // ᅵ + 0x79D4, KANJI_LEVEL4, // 秔 + 0x79DE, KANJI_LEVEL4, // 秞 + 0x79EB, KANJI_LEVEL4, // ç§« + 0x79ED, KANJI_LEVEL4, // ç§­ + 0x7A03, KANJI_LEVEL4, // 皃 + 0xFA54, KANJI_LEVEL4, // 穀 + 0x7A39, KANJI_LEVEL4, // çš¹ + 0x7A5D, KANJI_LEVEL4, // 穝 + 0x7A6D, KANJI_LEVEL4, // ç©­ + 0xFA55, KANJI_LEVEL4, // 突 + 0x7A85, KANJI_LEVEL4, // 窅 + 0x7AA0, KANJI_LEVEL4, // 窠 + 0xD856, KANJI_LEVEL4, // ᅵ + 0xDDC4, KANJI_LEVEL4, // ᅵ + 0x7AB3, KANJI_LEVEL4, // 窳 + 0x7ABB, KANJI_LEVEL4, // 窻 + 0x7ACE, KANJI_LEVEL4, // 竎 + 0x7AEB, KANJI_LEVEL4, // ç«« + 0x7AFD, KANJI_LEVEL4, // 竜 + 0x7B12, KANJI_LEVEL4, // 笒 + 0x7B2D, KANJI_LEVEL4, // 笭 + 0x7B3B, KANJI_LEVEL4, // 笻 + 0x7B47, KANJI_LEVEL4, // 筇 + 0x7B4E, KANJI_LEVEL4, // 筎 + 0x7B60, KANJI_LEVEL4, // ç­  + 0x7B6D, KANJI_LEVEL4, // ç­­ + 0x7B6F, KANJI_LEVEL4, // ç­¯ + 0x7B72, KANJI_LEVEL4, // ç­² + 0x7B9E, KANJI_LEVEL4, // 箞 + 0xFA56, KANJI_LEVEL4, // 節 + 0x7BD7, KANJI_LEVEL4, // 篗 + 0x7BD9, KANJI_LEVEL4, // 篙 + 0x7C01, KANJI_LEVEL4, // 簁 + 0x7C31, KANJI_LEVEL4, // ç°± + 0x7C1E, KANJI_LEVEL4, // 簞 + 0x7C20, KANJI_LEVEL4, // ç°  + 0x7C33, KANJI_LEVEL4, // ç°³ + 0x7C36, KANJI_LEVEL4, // ç°¶ + 0x4264, KANJI_LEVEL4, // 䉀 + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDDA1, KANJI_LEVEL4, // ᅵ + 0x7C59, KANJI_LEVEL4, // 籙 + 0x7C6D, KANJI_LEVEL4, // ç±­ + 0x7C79, KANJI_LEVEL4, // ç±¹ + 0x7C8F, KANJI_LEVEL4, // 粏 + 0x7C94, KANJI_LEVEL4, // 粔 + 0x7CA0, KANJI_LEVEL4, // ç²  + 0x7CBC, KANJI_LEVEL4, // 粌 + 0x7CD5, KANJI_LEVEL4, // 糕 + 0x7CD9, KANJI_LEVEL4, // 糙 + 0x7CDD, KANJI_LEVEL4, // 糝 + 0x7D07, KANJI_LEVEL4, // 箇 + 0x7D08, KANJI_LEVEL4, // 玈 + 0x7D13, KANJI_LEVEL4, // 箓 + 0x7D1D, KANJI_LEVEL4, // 玝 + 0x7D23, KANJI_LEVEL4, // 玣 + 0x7D31, KANJI_LEVEL4, // 玱 + 0x7D41, KANJI_LEVEL4, // 絁 + 0x7D48, KANJI_LEVEL4, // 絈 + 0x7D53, KANJI_LEVEL4, // 絓 + 0x7D5C, KANJI_LEVEL4, // 絜 + 0x7D7A, KANJI_LEVEL4, // 絺 + 0x7D83, KANJI_LEVEL4, // 綃 + 0x7D8B, KANJI_LEVEL4, // 綋 + 0x7DA0, KANJI_LEVEL4, // ç¶  + 0x7DA6, KANJI_LEVEL4, // ç¶Š + 0x7DC2, KANJI_LEVEL4, // 緂 + 0x7DCC, KANJI_LEVEL4, // 緌 + 0x7DD6, KANJI_LEVEL4, // 緖 + 0x7DE3, KANJI_LEVEL4, // ç·£ + 0xFA57, KANJI_LEVEL4, // 練 + 0x7E28, KANJI_LEVEL4, // çžš + 0x7E08, KANJI_LEVEL4, // 瞈 + 0x7E11, KANJI_LEVEL4, // 羑 + 0x7E15, KANJI_LEVEL4, // 羕 + 0xFA59, KANJI_LEVEL4, // 繁 + 0x7E47, KANJI_LEVEL4, // 繇 + 0x7E52, KANJI_LEVEL4, // 繒 + 0x7E61, KANJI_LEVEL4, // 繡 + 0x7E8A, KANJI_LEVEL4, // 纊 + 0x7E8D, KANJI_LEVEL4, // 纍 + 0x7F47, KANJI_LEVEL4, // 眇 + 0xFA5A, KANJI_LEVEL4, // 署 + 0x7F91, KANJI_LEVEL4, // 矑 + 0x7F97, KANJI_LEVEL4, // 矗 + 0x7FBF, KANJI_LEVEL4, // 矿 + 0x7FCE, KANJI_LEVEL4, // 翎 + 0x7FDB, KANJI_LEVEL4, // 翛 + 0x7FDF, KANJI_LEVEL4, // 翟 + 0x7FEC, KANJI_LEVEL4, // 翬 + 0x7FEE, KANJI_LEVEL4, // ç¿® + 0x7FFA, KANJI_LEVEL4, // 翺 + 0xFA5B, KANJI_LEVEL4, // 者 + 0x8014, KANJI_LEVEL4, // 耔 + 0x8026, KANJI_LEVEL4, // 耊 + 0x8035, KANJI_LEVEL4, // 耵 + 0x8037, KANJI_LEVEL4, // 耷 + 0x803C, KANJI_LEVEL4, // 而 + 0x80CA, KANJI_LEVEL4, // 胊 + 0x80D7, KANJI_LEVEL4, // 胗 + 0x80E0, KANJI_LEVEL4, // 胠 + 0x80F3, KANJI_LEVEL4, // 胳 + 0x8118, KANJI_LEVEL4, // 脘 + 0x814A, KANJI_LEVEL4, // 腊 + 0x8160, KANJI_LEVEL4, // 腠 + 0x8167, KANJI_LEVEL4, // 腧 + 0x8168, KANJI_LEVEL4, // è…š + 0x816D, KANJI_LEVEL4, // 腭 + 0x81BB, KANJI_LEVEL4, // 膻 + 0x81CA, KANJI_LEVEL4, // 臊 + 0x81CF, KANJI_LEVEL4, // 臏 + 0x81D7, KANJI_LEVEL4, // 臗 + 0xFA5C, KANJI_LEVEL4, // 臭 + 0x4453, KANJI_LEVEL4, // 䑓 + 0x445B, KANJI_LEVEL4, // 䑛 + 0x8260, KANJI_LEVEL4, // 艠 + 0x8274, KANJI_LEVEL4, // 艎 + 0xD85A, KANJI_LEVEL4, // ᅵ + 0xDEFF, KANJI_LEVEL4, // ᅵ + 0x828E, KANJI_LEVEL4, // 芎 + 0x82A1, KANJI_LEVEL4, // 芡 + 0x82A3, KANJI_LEVEL4, // 芣 + 0x82A4, KANJI_LEVEL4, // 芀 + 0x82A9, KANJI_LEVEL4, // 芩 + 0x82AE, KANJI_LEVEL4, // 芮 + 0x82B7, KANJI_LEVEL4, // 芷 + 0x82BE, KANJI_LEVEL4, // 芟 + 0x82BF, KANJI_LEVEL4, // 芿 + 0x82C6, KANJI_LEVEL4, // 苆 + 0x82D5, KANJI_LEVEL4, // 苕 + 0x82FD, KANJI_LEVEL4, // 苜 + 0x82FE, KANJI_LEVEL4, // 苟 + 0x8300, KANJI_LEVEL4, // 茀 + 0x8301, KANJI_LEVEL4, // 茁 + 0x8362, KANJI_LEVEL4, // 荢 + 0x8322, KANJI_LEVEL4, // 茢 + 0x832D, KANJI_LEVEL4, // 茭 + 0x833A, KANJI_LEVEL4, // 茺 + 0x8343, KANJI_LEVEL4, // 荃 + 0x8347, KANJI_LEVEL4, // 荇 + 0x8351, KANJI_LEVEL4, // 荑 + 0x8355, KANJI_LEVEL4, // 荕 + 0x837D, KANJI_LEVEL4, // 荜 + 0x8386, KANJI_LEVEL4, // 莆 + 0x8392, KANJI_LEVEL4, // 莒 + 0x8398, KANJI_LEVEL4, // 莘 + 0x83A7, KANJI_LEVEL4, // 莧 + 0x83A9, KANJI_LEVEL4, // 莩 + 0x83BF, KANJI_LEVEL4, // 莿 + 0x83C0, KANJI_LEVEL4, // 菀 + 0x83C7, KANJI_LEVEL4, // 菇 + 0x83CF, KANJI_LEVEL4, // 菏 + 0x83D1, KANJI_LEVEL4, // 菑 + 0x83E1, KANJI_LEVEL4, // 菡 + 0x83EA, KANJI_LEVEL4, // 菪 + 0x8401, KANJI_LEVEL4, // 萁 + 0x8406, KANJI_LEVEL4, // 萆 + 0x840A, KANJI_LEVEL4, // 萊 + 0xFA5F, KANJI_LEVEL4, // 著 + 0x8448, KANJI_LEVEL4, // 葈 + 0x845F, KANJI_LEVEL4, // 葟 + 0x8470, KANJI_LEVEL4, // 葰 + 0x8473, KANJI_LEVEL4, // 葳 + 0x8485, KANJI_LEVEL4, // 蒅 + 0x849E, KANJI_LEVEL4, // 蒞 + 0x84AF, KANJI_LEVEL4, // 蒯 + 0x84B4, KANJI_LEVEL4, // è’Ž + 0x84BA, KANJI_LEVEL4, // 蒺 + 0x84C0, KANJI_LEVEL4, // 蓀 + 0x84C2, KANJI_LEVEL4, // 蓂 + 0xD85B, KANJI_LEVEL4, // ᅵ + 0xDE40, KANJI_LEVEL4, // ᅵ + 0x8532, KANJI_LEVEL4, // 蔲 + 0x851E, KANJI_LEVEL4, // 蔞 + 0x8523, KANJI_LEVEL4, // 蔣 + 0x852F, KANJI_LEVEL4, // 蔯 + 0x8559, KANJI_LEVEL4, // 蕙 + 0x8564, KANJI_LEVEL4, // è•€ + 0xFA1F, KANJI_LEVEL4, //  + 0x85AD, KANJI_LEVEL4, // 薭 + 0x857A, KANJI_LEVEL4, // 蕺 + 0x858C, KANJI_LEVEL4, // 薌 + 0x858F, KANJI_LEVEL4, // 薏 + 0x85A2, KANJI_LEVEL4, // 薢 + 0x85B0, KANJI_LEVEL4, // 薰 + 0x85CB, KANJI_LEVEL4, // 藋 + 0x85CE, KANJI_LEVEL4, // 藎 + 0x85ED, KANJI_LEVEL4, // 藭 + 0x8612, KANJI_LEVEL4, // 蘒 + 0x85FF, KANJI_LEVEL4, // 藿 + 0x8604, KANJI_LEVEL4, // 蘄 + 0x8605, KANJI_LEVEL4, // 蘅 + 0x8610, KANJI_LEVEL4, // 蘐 + 0xD85C, KANJI_LEVEL4, // ᅵ + 0xDCF4, KANJI_LEVEL4, // ᅵ + 0x8618, KANJI_LEVEL4, // 蘘 + 0x8629, KANJI_LEVEL4, // 蘩 + 0x8638, KANJI_LEVEL4, // 蘞 + 0x8657, KANJI_LEVEL4, // 虗 + 0x865B, KANJI_LEVEL4, // 虛 + 0xF936, KANJI_LEVEL4, //  + 0x8662, KANJI_LEVEL4, // 虢 + 0x459D, KANJI_LEVEL4, // 䖝 + 0x866C, KANJI_LEVEL4, // 虬 + 0x8675, KANJI_LEVEL4, // 虵 + 0x8698, KANJI_LEVEL4, // 蚘 + 0x86B8, KANJI_LEVEL4, // èšž + 0x86FA, KANJI_LEVEL4, // 蛺 + 0x86FC, KANJI_LEVEL4, // 蛌 + 0x86FD, KANJI_LEVEL4, // 蛜 + 0x870B, KANJI_LEVEL4, // 蜋 + 0x8771, KANJI_LEVEL4, // 蝱 + 0x8787, KANJI_LEVEL4, // 螇 + 0x8788, KANJI_LEVEL4, // 螈 + 0x87AC, KANJI_LEVEL4, // 螬 + 0x87AD, KANJI_LEVEL4, // 螭 + 0x87B5, KANJI_LEVEL4, // 螵 + 0x45EA, KANJI_LEVEL4, // 䗪 + 0x87D6, KANJI_LEVEL4, // 蟖 + 0x87EC, KANJI_LEVEL4, // 蟬 + 0x8806, KANJI_LEVEL4, // 蠆 + 0x880A, KANJI_LEVEL4, // 蠊 + 0x8810, KANJI_LEVEL4, // 蠐 + 0x8814, KANJI_LEVEL4, // 蠔 + 0x881F, KANJI_LEVEL4, // 蠟 + 0x8898, KANJI_LEVEL4, // 袘 + 0x88AA, KANJI_LEVEL4, // 袪 + 0x88CA, KANJI_LEVEL4, // 裊 + 0x88CE, KANJI_LEVEL4, // 裎 + 0xD85D, KANJI_LEVEL4, // ᅵ + 0xDE84, KANJI_LEVEL4, // ᅵ + 0x88F5, KANJI_LEVEL4, // 裵 + 0x891C, KANJI_LEVEL4, // 耜 + 0xFA60, KANJI_LEVEL4, // ï©  + 0x8918, KANJI_LEVEL4, // 耘 + 0x8919, KANJI_LEVEL4, // 耙 + 0x891A, KANJI_LEVEL4, // 耚 + 0x8927, KANJI_LEVEL4, // 耧 + 0x8930, KANJI_LEVEL4, // 耰 + 0x8932, KANJI_LEVEL4, // 耲 + 0x8939, KANJI_LEVEL4, // 耹 + 0x8940, KANJI_LEVEL4, // 襀 + 0x8994, KANJI_LEVEL4, // 芔 + 0xFA61, KANJI_LEVEL4, // ï©¡ + 0x89D4, KANJI_LEVEL4, // 觔 + 0x89E5, KANJI_LEVEL4, // è§¥ + 0x89F6, KANJI_LEVEL4, // è§¶ + 0x8A12, KANJI_LEVEL4, // èš’ + 0x8A15, KANJI_LEVEL4, // èš• + 0x8A22, KANJI_LEVEL4, // 蚢 + 0x8A37, KANJI_LEVEL4, // èš· + 0x8A47, KANJI_LEVEL4, // 詇 + 0x8A4E, KANJI_LEVEL4, // 詎 + 0x8A5D, KANJI_LEVEL4, // 詝 + 0x8A61, KANJI_LEVEL4, // è©¡ + 0x8A75, KANJI_LEVEL4, // 詵 + 0x8A79, KANJI_LEVEL4, // 詹 + 0x8AA7, KANJI_LEVEL4, // 誧 + 0x8AD0, KANJI_LEVEL4, // 諐 + 0x8ADF, KANJI_LEVEL4, // 諟 + 0x8AF4, KANJI_LEVEL4, // 諎 + 0x8AF6, KANJI_LEVEL4, // è«¶ + 0xFA22, KANJI_LEVEL4, //  + 0xFA62, KANJI_LEVEL4, // ï©¢ + 0xFA63, KANJI_LEVEL4, // ï©£ + 0x8B46, KANJI_LEVEL4, // 譆 + 0x8B54, KANJI_LEVEL4, // 譔 + 0x8B59, KANJI_LEVEL4, // 譙 + 0x8B69, KANJI_LEVEL4, // è­© + 0x8B9D, KANJI_LEVEL4, // 讝 + 0x8C49, KANJI_LEVEL4, // 豉 + 0x8C68, KANJI_LEVEL4, // 豚 + 0xFA64, KANJI_LEVEL4, // ï©€ + 0x8CE1, KANJI_LEVEL4, // 賡 + 0x8CF4, KANJI_LEVEL4, // 賎 + 0x8CF8, KANJI_LEVEL4, // 賞 + 0x8CFE, KANJI_LEVEL4, // 賟 + 0xFA65, KANJI_LEVEL4, // ï©¥ + 0x8D12, KANJI_LEVEL4, // 莒 + 0x8D1B, KANJI_LEVEL4, // 莛 + 0x8DAF, KANJI_LEVEL4, // 趯 + 0x8DCE, KANJI_LEVEL4, // 跎 + 0x8DD1, KANJI_LEVEL4, // 跑 + 0x8DD7, KANJI_LEVEL4, // 跗 + 0x8E20, KANJI_LEVEL4, // èž  + 0x8E23, KANJI_LEVEL4, // 螣 + 0x8E3D, KANJI_LEVEL4, // èžœ + 0x8E70, KANJI_LEVEL4, // è¹° + 0x8E7B, KANJI_LEVEL4, // è¹» + 0xD860, KANJI_LEVEL4, // ᅵ + 0xDE77, KANJI_LEVEL4, // ᅵ + 0x8EC0, KANJI_LEVEL4, // 軀 + 0x4844, KANJI_LEVEL4, // 䡄 + 0x8EFA, KANJI_LEVEL4, // 軺 + 0x8F1E, KANJI_LEVEL4, // 茞 + 0x8F2D, KANJI_LEVEL4, // 茭 + 0x8F36, KANJI_LEVEL4, // 茶 + 0x8F54, KANJI_LEVEL4, // 蜔 + 0xD860, KANJI_LEVEL4, // ᅵ + 0xDFCD, KANJI_LEVEL4, // ᅵ + 0x8FA6, KANJI_LEVEL4, // 蟊 + 0x8FB5, KANJI_LEVEL4, // 蟵 + 0x8FE4, KANJI_LEVEL4, // è¿€ + 0x8FE8, KANJI_LEVEL4, // 迚 + 0x8FEE, KANJI_LEVEL4, // è¿® + 0x9008, KANJI_LEVEL4, // 逈 + 0x902D, KANJI_LEVEL4, // 逭 + 0xFA67, KANJI_LEVEL4, // ï©§ + 0x9088, KANJI_LEVEL4, // 邈 + 0x9095, KANJI_LEVEL4, // 邕 + 0x9097, KANJI_LEVEL4, // 邗 + 0x9099, KANJI_LEVEL4, // 邙 + 0x909B, KANJI_LEVEL4, // 邛 + 0x90A2, KANJI_LEVEL4, // 邢 + 0x90B3, KANJI_LEVEL4, // 邳 + 0x90BE, KANJI_LEVEL4, // 邟 + 0x90C4, KANJI_LEVEL4, // 郄 + 0x90C5, KANJI_LEVEL4, // 郅 + 0x90C7, KANJI_LEVEL4, // 郇 + 0x90D7, KANJI_LEVEL4, // 郗 + 0x90DD, KANJI_LEVEL4, // 郝 + 0x90DE, KANJI_LEVEL4, // 郞 + 0x90EF, KANJI_LEVEL4, // 郯 + 0x90F4, KANJI_LEVEL4, // 郎 + 0xFA26, KANJI_LEVEL4, //  + 0x9114, KANJI_LEVEL4, // 鄔 + 0x9115, KANJI_LEVEL4, // 鄕 + 0x9116, KANJI_LEVEL4, // 鄖 + 0x9122, KANJI_LEVEL4, // 鄢 + 0x9123, KANJI_LEVEL4, // 鄣 + 0x9127, KANJI_LEVEL4, // 鄧 + 0x912F, KANJI_LEVEL4, // 鄯 + 0x9131, KANJI_LEVEL4, // 鄱 + 0x9134, KANJI_LEVEL4, // 鄮 + 0x913D, KANJI_LEVEL4, // 鄜 + 0x9148, KANJI_LEVEL4, // 酈 + 0x915B, KANJI_LEVEL4, // 酛 + 0x9183, KANJI_LEVEL4, // 醃 + 0x919E, KANJI_LEVEL4, // 醞 + 0x91AC, KANJI_LEVEL4, // 醬 + 0x91B1, KANJI_LEVEL4, // 醱 + 0x91BC, KANJI_LEVEL4, // 醌 + 0x91D7, KANJI_LEVEL4, // 釗 + 0x91FB, KANJI_LEVEL4, // 釻 + 0x91E4, KANJI_LEVEL4, // 釀 + 0x91E5, KANJI_LEVEL4, // 釥 + 0x91ED, KANJI_LEVEL4, // 釭 + 0x91F1, KANJI_LEVEL4, // 釱 + 0x9207, KANJI_LEVEL4, // 鈇 + 0x9210, KANJI_LEVEL4, // 鈐 + 0x9238, KANJI_LEVEL4, // 鈞 + 0x9239, KANJI_LEVEL4, // 鈹 + 0x923A, KANJI_LEVEL4, // 鈺 + 0x923C, KANJI_LEVEL4, // 鈌 + 0x9240, KANJI_LEVEL4, // 鉀 + 0x9243, KANJI_LEVEL4, // 鉃 + 0x924F, KANJI_LEVEL4, // 鉏 + 0x9278, KANJI_LEVEL4, // 鉾 + 0x9288, KANJI_LEVEL4, // 銈 + 0x92C2, KANJI_LEVEL4, // 鋂 + 0x92CB, KANJI_LEVEL4, // 鋋 + 0x92CC, KANJI_LEVEL4, // 鋌 + 0x92D3, KANJI_LEVEL4, // 鋓 + 0x92E0, KANJI_LEVEL4, // 鋠 + 0x92FF, KANJI_LEVEL4, // 鋿 + 0x9304, KANJI_LEVEL4, // 錄 + 0x931F, KANJI_LEVEL4, // 錟 + 0x9321, KANJI_LEVEL4, // 錡 + 0x9325, KANJI_LEVEL4, // 錥 + 0x9348, KANJI_LEVEL4, // 鍈 + 0x9349, KANJI_LEVEL4, // 鍉 + 0x934A, KANJI_LEVEL4, // 鍊 + 0x9364, KANJI_LEVEL4, // 鍀 + 0x9365, KANJI_LEVEL4, // 鍥 + 0x936A, KANJI_LEVEL4, // 鍪 + 0x9370, KANJI_LEVEL4, // 鍰 + 0x939B, KANJI_LEVEL4, // 鎛 + 0x93A3, KANJI_LEVEL4, // 鎣 + 0x93BA, KANJI_LEVEL4, // 鎺 + 0x93C6, KANJI_LEVEL4, // 鏆 + 0x93DE, KANJI_LEVEL4, // 鏞 + 0x93DF, KANJI_LEVEL4, // 鏟 + 0x9404, KANJI_LEVEL4, // 鐄 + 0x93FD, KANJI_LEVEL4, // 鏜 + 0x9433, KANJI_LEVEL4, // 鐳 + 0x944A, KANJI_LEVEL4, // 鑊 + 0x9463, KANJI_LEVEL4, // 鑣 + 0x946B, KANJI_LEVEL4, // 鑫 + 0x9471, KANJI_LEVEL4, // 鑱 + 0x9472, KANJI_LEVEL4, // 鑲 + 0x958E, KANJI_LEVEL4, // 閎 + 0x959F, KANJI_LEVEL4, // 閟 + 0x95A6, KANJI_LEVEL4, // 閩 + 0x95A9, KANJI_LEVEL4, // 閩 + 0x95AC, KANJI_LEVEL4, // 閬 + 0x95B6, KANJI_LEVEL4, // 閶 + 0x95BD, KANJI_LEVEL4, // é–œ + 0x95CB, KANJI_LEVEL4, // 闋 + 0x95D0, KANJI_LEVEL4, // 闐 + 0x95D3, KANJI_LEVEL4, // 闓 + 0x49B0, KANJI_LEVEL4, // 䊰 + 0x95DA, KANJI_LEVEL4, // 闚 + 0x95DE, KANJI_LEVEL4, // 闞 + 0x9658, KANJI_LEVEL4, // 陘 + 0x9684, KANJI_LEVEL4, // 隄 + 0xF9DC, KANJI_LEVEL4, // 隆 + 0x969D, KANJI_LEVEL4, // 隝 + 0x96A4, KANJI_LEVEL4, // 隀 + 0x96A5, KANJI_LEVEL4, // 隥 + 0x96D2, KANJI_LEVEL4, // 雒 + 0x96DE, KANJI_LEVEL4, // 雞 + 0xFA68, KANJI_LEVEL4, // 署 + 0x96E9, KANJI_LEVEL4, // 雩 + 0x96EF, KANJI_LEVEL4, // 雯 + 0x9733, KANJI_LEVEL4, // 霳 + 0x973B, KANJI_LEVEL4, // 霻 + 0x974D, KANJI_LEVEL4, // 靍 + 0x974E, KANJI_LEVEL4, // 靎 + 0x974F, KANJI_LEVEL4, // 靏 + 0x975A, KANJI_LEVEL4, // 靚 + 0x976E, KANJI_LEVEL4, // 靮 + 0x9773, KANJI_LEVEL4, // 靳 + 0x9795, KANJI_LEVEL4, // 鞕 + 0x97AE, KANJI_LEVEL4, // 鞮 + 0x97BA, KANJI_LEVEL4, // 鞺 + 0x97C1, KANJI_LEVEL4, // 韁 + 0x97C9, KANJI_LEVEL4, // 韉 + 0x97DE, KANJI_LEVEL4, // 韞 + 0x97DB, KANJI_LEVEL4, // 韛 + 0x97F4, KANJI_LEVEL4, // 韮 + 0xFA69, KANJI_LEVEL4, // ï©© + 0x980A, KANJI_LEVEL4, // 頊 + 0x981E, KANJI_LEVEL4, // 頞 + 0x982B, KANJI_LEVEL4, // é « + 0x9830, KANJI_LEVEL4, // é ° + 0xFA6A, KANJI_LEVEL4, // 頻 + 0x9852, KANJI_LEVEL4, // 顒 + 0x9853, KANJI_LEVEL4, // 顓 + 0x9856, KANJI_LEVEL4, // 顖 + 0x9857, KANJI_LEVEL4, // 顗 + 0x9859, KANJI_LEVEL4, // 顙 + 0x985A, KANJI_LEVEL4, // 顚 + 0xF9D0, KANJI_LEVEL4, // 類 + 0x9865, KANJI_LEVEL4, // é¡¥ + 0x986C, KANJI_LEVEL4, // 顬 + 0x98BA, KANJI_LEVEL4, // 颺 + 0x98C8, KANJI_LEVEL4, // 飈 + 0x98E7, KANJI_LEVEL4, // 飧 + 0x9958, KANJI_LEVEL4, // 饘 + 0x999E, KANJI_LEVEL4, // 銞 + 0x9A02, KANJI_LEVEL4, // 鹂 + 0x9A03, KANJI_LEVEL4, // 隃 + 0x9A24, KANJI_LEVEL4, // 隀 + 0x9A2D, KANJI_LEVEL4, // éš­ + 0x9A2E, KANJI_LEVEL4, // éš® + 0x9A38, KANJI_LEVEL4, // éšž + 0x9A4A, KANJI_LEVEL4, // 驊 + 0x9A4E, KANJI_LEVEL4, // 驎 + 0x9A52, KANJI_LEVEL4, // 驒 + 0x9AB6, KANJI_LEVEL4, // 骶 + 0x9AC1, KANJI_LEVEL4, // 髁 + 0x9AC3, KANJI_LEVEL4, // 髃 + 0x9ACE, KANJI_LEVEL4, // 髎 + 0x9AD6, KANJI_LEVEL4, // 髖 + 0x9AF9, KANJI_LEVEL4, // 髹 + 0x9B02, KANJI_LEVEL4, // 鬂 + 0x9B08, KANJI_LEVEL4, // 鬈 + 0x9B20, KANJI_LEVEL4, // 鬠 + 0x4C17, KANJI_LEVEL4, // 䰗 + 0x9B2D, KANJI_LEVEL4, // 鬭 + 0x9B5E, KANJI_LEVEL4, // 魞 + 0x9B79, KANJI_LEVEL4, // é­¹ + 0x9B66, KANJI_LEVEL4, // é­Š + 0x9B72, KANJI_LEVEL4, // é­² + 0x9B75, KANJI_LEVEL4, // é­µ + 0x9B84, KANJI_LEVEL4, // 鮄 + 0x9B8A, KANJI_LEVEL4, // 鮊 + 0x9B8F, KANJI_LEVEL4, // 鮏 + 0x9B9E, KANJI_LEVEL4, // 鮞 + 0x9BA7, KANJI_LEVEL4, // é®§ + 0x9BC1, KANJI_LEVEL4, // 鯁 + 0x9BCE, KANJI_LEVEL4, // 鯎 + 0x9BE5, KANJI_LEVEL4, // 鯥 + 0x9BF8, KANJI_LEVEL4, // 鯞 + 0x9BFD, KANJI_LEVEL4, // 鯜 + 0x9C00, KANJI_LEVEL4, // 鰀 + 0x9C23, KANJI_LEVEL4, // é°£ + 0x9C41, KANJI_LEVEL4, // 鱁 + 0x9C4F, KANJI_LEVEL4, // 鱏 + 0x9C50, KANJI_LEVEL4, // 鱐 + 0x9C53, KANJI_LEVEL4, // 鱓 + 0x9C63, KANJI_LEVEL4, // é±£ + 0x9C65, KANJI_LEVEL4, // é±¥ + 0x9C77, KANJI_LEVEL4, // é±· + 0x9D1D, KANJI_LEVEL4, // 鎝 + 0x9D1E, KANJI_LEVEL4, // 鮞 + 0x9D43, KANJI_LEVEL4, // 鵃 + 0x9D47, KANJI_LEVEL4, // 鵇 + 0x9D52, KANJI_LEVEL4, // 鵒 + 0x9D63, KANJI_LEVEL4, // éµ£ + 0x9D70, KANJI_LEVEL4, // éµ° + 0x9D7C, KANJI_LEVEL4, // 鵌 + 0x9D8A, KANJI_LEVEL4, // 鶊 + 0x9D96, KANJI_LEVEL4, // 鶖 + 0x9DC0, KANJI_LEVEL4, // 鷀 + 0x9DAC, KANJI_LEVEL4, // 鶬 + 0x9DBC, KANJI_LEVEL4, // é¶Œ + 0x9DD7, KANJI_LEVEL4, // 鷗 + 0xD868, KANJI_LEVEL4, // ᅵ + 0xDD90, KANJI_LEVEL4, // ᅵ + 0x9DE7, KANJI_LEVEL4, // é·§ + 0x9E07, KANJI_LEVEL4, // 龇 + 0x9E15, KANJI_LEVEL4, // 龕 + 0x9E7C, KANJI_LEVEL4, // 鹌 + 0x9E9E, KANJI_LEVEL4, // 麞 + 0x9EA4, KANJI_LEVEL4, // 麀 + 0x9EAC, KANJI_LEVEL4, // 麬 + 0x9EAF, KANJI_LEVEL4, // 麯 + 0x9EB4, KANJI_LEVEL4, // 麎 + 0x9EB5, KANJI_LEVEL4, // 麵 + 0x9EC3, KANJI_LEVEL4, // 黃 + 0x9ED1, KANJI_LEVEL4, // 黑 + 0x9F10, KANJI_LEVEL4, // 錐 + 0x9F39, KANJI_LEVEL4, // 錹 + 0x9F57, KANJI_LEVEL4, // 霗 + 0x9F90, KANJI_LEVEL4, // 韐 + 0x9F94, KANJI_LEVEL4, // 韔 + 0x9F97, KANJI_LEVEL4, // 韗 + 0x9FA2, KANJI_LEVEL4, // 韢 + 0x59F8, KANJI_LEVEL4, // å§ž + 0x5C5B, KANJI_LEVEL4, // 屛 + 0x5E77, KANJI_LEVEL4, // å¹· + 0x7626, KANJI_LEVEL4, // 瘊 + 0x7E6B, KANJI_LEVEL4, // 繫 + 0xD840, KANJI_LEVEL4, // ᅵ + 0xDC89, KANJI_LEVEL4, // ᅵ + 0x4E02, KANJI_LEVEL4, // 侂 + 0x4E0F, KANJI_LEVEL4, // 䞏 + 0x4E12, KANJI_LEVEL4, // 侒 + 0x4E29, KANJI_LEVEL4, // äž© + 0x4E2B, KANJI_LEVEL4, // äž« + 0x4E2E, KANJI_LEVEL4, // äž® + 0x4E40, KANJI_LEVEL4, // 乀 + 0x4E47, KANJI_LEVEL4, // 乇 + 0x4E48, KANJI_LEVEL4, // 么 + 0xD840, KANJI_LEVEL4, // ᅵ + 0xDCA2, KANJI_LEVEL4, // ᅵ + 0x4E51, KANJI_LEVEL4, // 乑 + 0x3406, KANJI_LEVEL4, // 㐆 + 0xD840, KANJI_LEVEL4, // ᅵ + 0xDCA4, KANJI_LEVEL4, // ᅵ + 0x4E5A, KANJI_LEVEL4, // 乚 + 0x4E69, KANJI_LEVEL4, // 乩 + 0x4E9D, KANJI_LEVEL4, // 亝 + 0x342C, KANJI_LEVEL4, // 㐬 + 0x342E, KANJI_LEVEL4, // 㐮 + 0x4EB9, KANJI_LEVEL4, // 亹 + 0x4EBB, KANJI_LEVEL4, // 亻 + 0xD840, KANJI_LEVEL4, // ᅵ + 0xDDA2, KANJI_LEVEL4, // ᅵ + 0x4EBC, KANJI_LEVEL4, // 二 + 0x4EC3, KANJI_LEVEL4, // 仃 + 0x4EC8, KANJI_LEVEL4, // 仈 + 0x4ED0, KANJI_LEVEL4, // 仐 + 0x4EEB, KANJI_LEVEL4, // 仫 + 0x4EDA, KANJI_LEVEL4, // 仚 + 0x4EF1, KANJI_LEVEL4, // ä»± + 0x4EF5, KANJI_LEVEL4, // 仵 + 0x4F00, KANJI_LEVEL4, // 䌀 + 0x4F16, KANJI_LEVEL4, // 䌖 + 0x4F64, KANJI_LEVEL4, // 䜀 + 0x4F37, KANJI_LEVEL4, // 䌷 + 0x4F3E, KANJI_LEVEL4, // 䌟 + 0x4F54, KANJI_LEVEL4, // 䜔 + 0x4F58, KANJI_LEVEL4, // 䜘 + 0xD840, KANJI_LEVEL4, // ᅵ + 0xDE13, KANJI_LEVEL4, // ᅵ + 0x4F77, KANJI_LEVEL4, // 䜷 + 0x4F78, KANJI_LEVEL4, // 䜞 + 0x4F7A, KANJI_LEVEL4, // 䜺 + 0x4F7D, KANJI_LEVEL4, // 䜜 + 0x4F82, KANJI_LEVEL4, // 䟂 + 0x4F85, KANJI_LEVEL4, // 䟅 + 0x4F92, KANJI_LEVEL4, // 䟒 + 0x4F9A, KANJI_LEVEL4, // 䟚 + 0x4FE6, KANJI_LEVEL4, // 俊 + 0x4FB2, KANJI_LEVEL4, // 䟲 + 0x4FBE, KANJI_LEVEL4, // 䟟 + 0x4FC5, KANJI_LEVEL4, // 俅 + 0x4FCB, KANJI_LEVEL4, // 俋 + 0x4FCF, KANJI_LEVEL4, // 俏 + 0x4FD2, KANJI_LEVEL4, // 俒 + 0x346A, KANJI_LEVEL4, // 㑪 + 0x4FF2, KANJI_LEVEL4, // 俲 + 0x5000, KANJI_LEVEL4, // 倀 + 0x5010, KANJI_LEVEL4, // 倐 + 0x5013, KANJI_LEVEL4, // 倓 + 0x501C, KANJI_LEVEL4, // 倜 + 0x501E, KANJI_LEVEL4, // 倞 + 0x5022, KANJI_LEVEL4, // 倢 + 0x3468, KANJI_LEVEL4, // 㑚 + 0x5042, KANJI_LEVEL4, // 偂 + 0x5046, KANJI_LEVEL4, // 偆 + 0x504E, KANJI_LEVEL4, // 偎 + 0x5053, KANJI_LEVEL4, // 偓 + 0x5057, KANJI_LEVEL4, // 偗 + 0x5063, KANJI_LEVEL4, // 偣 + 0x5066, KANJI_LEVEL4, // 偊 + 0x506A, KANJI_LEVEL4, // 偪 + 0x5070, KANJI_LEVEL4, // 偰 + 0x50A3, KANJI_LEVEL4, // 傣 + 0x5088, KANJI_LEVEL4, // 傈 + 0x5092, KANJI_LEVEL4, // 傒 + 0x5093, KANJI_LEVEL4, // 傓 + 0x5095, KANJI_LEVEL4, // 傕 + 0x5096, KANJI_LEVEL4, // 傖 + 0x509C, KANJI_LEVEL4, // 傜 + 0x50AA, KANJI_LEVEL4, // 傪 + 0xD840, KANJI_LEVEL4, // ᅵ + 0xDF2B, KANJI_LEVEL4, // ᅵ + 0x50B1, KANJI_LEVEL4, // 傱 + 0x50BA, KANJI_LEVEL4, // 傺 + 0x50BB, KANJI_LEVEL4, // 傻 + 0x50C4, KANJI_LEVEL4, // 僄 + 0x50C7, KANJI_LEVEL4, // 僇 + 0x50F3, KANJI_LEVEL4, // 僳 + 0xD840, KANJI_LEVEL4, // ᅵ + 0xDF81, KANJI_LEVEL4, // ᅵ + 0x50CE, KANJI_LEVEL4, // 僎 + 0xD840, KANJI_LEVEL4, // ᅵ + 0xDF71, KANJI_LEVEL4, // ᅵ + 0x50D4, KANJI_LEVEL4, // 僔 + 0x50D9, KANJI_LEVEL4, // 僙 + 0x50E1, KANJI_LEVEL4, // 僡 + 0x50E9, KANJI_LEVEL4, // 僩 + 0x3492, KANJI_LEVEL4, // 㒒 + 0x5108, KANJI_LEVEL4, // 儈 + 0xD840, KANJI_LEVEL4, // ᅵ + 0xDFF9, KANJI_LEVEL4, // ᅵ + 0x5117, KANJI_LEVEL4, // 儗 + 0x511B, KANJI_LEVEL4, // 儛 + 0xD841, KANJI_LEVEL4, // ᅵ + 0xDC4A, KANJI_LEVEL4, // ᅵ + 0x5160, KANJI_LEVEL4, // 兠 + 0xD841, KANJI_LEVEL4, // ᅵ + 0xDD09, KANJI_LEVEL4, // ᅵ + 0x5173, KANJI_LEVEL4, // 关 + 0x5183, KANJI_LEVEL4, // 冃 + 0x518B, KANJI_LEVEL4, // 冋 + 0x34BC, KANJI_LEVEL4, // ã’Œ + 0x5198, KANJI_LEVEL4, // 冘 + 0x51A3, KANJI_LEVEL4, // 冣 + 0x51AD, KANJI_LEVEL4, // 冭 + 0x34C7, KANJI_LEVEL4, // 㓇 + 0x51BC, KANJI_LEVEL4, // 册 + 0xD841, KANJI_LEVEL4, // ᅵ + 0xDDD6, KANJI_LEVEL4, // ᅵ + 0xD841, KANJI_LEVEL4, // ᅵ + 0xDE28, KANJI_LEVEL4, // ᅵ + 0x51F3, KANJI_LEVEL4, // 凳 + 0x51F4, KANJI_LEVEL4, // 凎 + 0x5202, KANJI_LEVEL4, // 刂 + 0x5212, KANJI_LEVEL4, // 划 + 0x5216, KANJI_LEVEL4, // 刖 + 0xD841, KANJI_LEVEL4, // ᅵ + 0xDF4F, KANJI_LEVEL4, // ᅵ + 0x5255, KANJI_LEVEL4, // 剕 + 0x525C, KANJI_LEVEL4, // 剜 + 0x526C, KANJI_LEVEL4, // 剬 + 0x5277, KANJI_LEVEL4, // 剷 + 0x5284, KANJI_LEVEL4, // 劄 + 0x5282, KANJI_LEVEL4, // 劂 + 0xD842, KANJI_LEVEL4, // ᅵ + 0xDC07, KANJI_LEVEL4, // ᅵ + 0x5298, KANJI_LEVEL4, // 劘 + 0xD842, KANJI_LEVEL4, // ᅵ + 0xDC3A, KANJI_LEVEL4, // ᅵ + 0x52A4, KANJI_LEVEL4, // 劀 + 0x52A6, KANJI_LEVEL4, // 劊 + 0x52AF, KANJI_LEVEL4, // 劯 + 0x52BA, KANJI_LEVEL4, // 劺 + 0x52BB, KANJI_LEVEL4, // 劻 + 0x52CA, KANJI_LEVEL4, // 勊 + 0x351F, KANJI_LEVEL4, // 㔟 + 0x52D1, KANJI_LEVEL4, // 勑 + 0xD842, KANJI_LEVEL4, // ᅵ + 0xDCB9, KANJI_LEVEL4, // ᅵ + 0x52F7, KANJI_LEVEL4, // 勷 + 0x530A, KANJI_LEVEL4, // 匊 + 0x530B, KANJI_LEVEL4, // 匋 + 0x5324, KANJI_LEVEL4, // 匀 + 0x5335, KANJI_LEVEL4, // 匵 + 0x533E, KANJI_LEVEL4, // 匟 + 0x5342, KANJI_LEVEL4, // 卂 + 0xD842, KANJI_LEVEL4, // ᅵ + 0xDD7C, KANJI_LEVEL4, // ᅵ + 0xD842, KANJI_LEVEL4, // ᅵ + 0xDD9D, KANJI_LEVEL4, // ᅵ + 0x5367, KANJI_LEVEL4, // 卧 + 0x536C, KANJI_LEVEL4, // 卬 + 0x537A, KANJI_LEVEL4, // 卺 + 0x53A4, KANJI_LEVEL4, // 厀 + 0x53B4, KANJI_LEVEL4, // 厎 + 0xD842, KANJI_LEVEL4, // ᅵ + 0xDED3, KANJI_LEVEL4, // ᅵ + 0x53B7, KANJI_LEVEL4, // 厷 + 0x53C0, KANJI_LEVEL4, // 叀 + 0xD842, KANJI_LEVEL4, // ᅵ + 0xDF1D, KANJI_LEVEL4, // ᅵ + 0x355D, KANJI_LEVEL4, // 㕝 + 0x355E, KANJI_LEVEL4, // 㕞 + 0x53D5, KANJI_LEVEL4, // 叕 + 0x53DA, KANJI_LEVEL4, // 叚 + 0x3563, KANJI_LEVEL4, // 㕣 + 0x53F4, KANJI_LEVEL4, // 収 + 0x53F5, KANJI_LEVEL4, // 叵 + 0x5455, KANJI_LEVEL4, // 呕 + 0x5424, KANJI_LEVEL4, // 吀 + 0x5428, KANJI_LEVEL4, // 吚 + 0x356E, KANJI_LEVEL4, // 㕮 + 0x5443, KANJI_LEVEL4, // 呃 + 0x5462, KANJI_LEVEL4, // 呢 + 0x5466, KANJI_LEVEL4, // 告 + 0x546C, KANJI_LEVEL4, // 呬 + 0x548A, KANJI_LEVEL4, // 咊 + 0x548D, KANJI_LEVEL4, // 咍 + 0x5495, KANJI_LEVEL4, // 咕 + 0x54A0, KANJI_LEVEL4, // 咠 + 0x54A6, KANJI_LEVEL4, // å’Š + 0x54AD, KANJI_LEVEL4, // 咭 + 0x54AE, KANJI_LEVEL4, // 咮 + 0x54B7, KANJI_LEVEL4, // 咷 + 0x54BA, KANJI_LEVEL4, // 咺 + 0x54BF, KANJI_LEVEL4, // 咿 + 0x54C3, KANJI_LEVEL4, // 哃 + 0xD843, KANJI_LEVEL4, // ᅵ + 0xDD45, KANJI_LEVEL4, // ᅵ + 0x54EC, KANJI_LEVEL4, // 哬 + 0x54EF, KANJI_LEVEL4, // 哯 + 0x54F1, KANJI_LEVEL4, // 哱 + 0x54F3, KANJI_LEVEL4, // 哳 + 0x5500, KANJI_LEVEL4, // 唀 + 0x5501, KANJI_LEVEL4, // 唁 + 0x5509, KANJI_LEVEL4, // 唉 + 0x553C, KANJI_LEVEL4, // 唌 + 0x5541, KANJI_LEVEL4, // 啁 + 0x35A6, KANJI_LEVEL4, // ã–Š + 0x5547, KANJI_LEVEL4, // 啇 + 0x554A, KANJI_LEVEL4, // 啊 + 0x35A8, KANJI_LEVEL4, // ã–š + 0x5560, KANJI_LEVEL4, // 啠 + 0x5561, KANJI_LEVEL4, // 啡 + 0x5564, KANJI_LEVEL4, // å•€ + 0xD843, KANJI_LEVEL4, // ᅵ + 0xDDE1, KANJI_LEVEL4, // ᅵ + 0x557D, KANJI_LEVEL4, // 啜 + 0x5582, KANJI_LEVEL4, // 喂 + 0x5588, KANJI_LEVEL4, // 喈 + 0x5591, KANJI_LEVEL4, // 喑 + 0x35C5, KANJI_LEVEL4, // 㗅 + 0x55D2, KANJI_LEVEL4, // 嗒 + 0xD843, KANJI_LEVEL4, // ᅵ + 0xDE95, KANJI_LEVEL4, // ᅵ + 0xD843, KANJI_LEVEL4, // ᅵ + 0xDE6D, KANJI_LEVEL4, // ᅵ + 0x55BF, KANJI_LEVEL4, // 喿 + 0x55C9, KANJI_LEVEL4, // 嗉 + 0x55CC, KANJI_LEVEL4, // 嗌 + 0x55D1, KANJI_LEVEL4, // 嗑 + 0x55DD, KANJI_LEVEL4, // 嗝 + 0x35DA, KANJI_LEVEL4, // 㗚 + 0x55E2, KANJI_LEVEL4, // 嗢 + 0xD843, KANJI_LEVEL4, // ᅵ + 0xDE64, KANJI_LEVEL4, // ᅵ + 0x55E9, KANJI_LEVEL4, // 嗩 + 0x5628, KANJI_LEVEL4, // 嘚 + 0xD843, KANJI_LEVEL4, // ᅵ + 0xDF5F, KANJI_LEVEL4, // ᅵ + 0x5607, KANJI_LEVEL4, // 嘇 + 0x5610, KANJI_LEVEL4, // 嘐 + 0x5630, KANJI_LEVEL4, // 嘰 + 0x5637, KANJI_LEVEL4, // 嘷 + 0x35F4, KANJI_LEVEL4, // ã—Ž + 0x563D, KANJI_LEVEL4, // 嘜 + 0x563F, KANJI_LEVEL4, // 嘿 + 0x5640, KANJI_LEVEL4, // 噀 + 0x5647, KANJI_LEVEL4, // 噇 + 0x565E, KANJI_LEVEL4, // 噞 + 0x5660, KANJI_LEVEL4, // 噠 + 0x566D, KANJI_LEVEL4, // 噭 + 0x3605, KANJI_LEVEL4, // 㘅 + 0x5688, KANJI_LEVEL4, // 嚈 + 0x568C, KANJI_LEVEL4, // 嚌 + 0x5695, KANJI_LEVEL4, // 嚕 + 0x569A, KANJI_LEVEL4, // 嚚 + 0x569D, KANJI_LEVEL4, // 嚝 + 0x56A8, KANJI_LEVEL4, // åšš + 0x56AD, KANJI_LEVEL4, // 嚭 + 0x56B2, KANJI_LEVEL4, // 嚲 + 0x56C5, KANJI_LEVEL4, // 囅 + 0x56CD, KANJI_LEVEL4, // 囍 + 0x56DF, KANJI_LEVEL4, // 囟 + 0x56E8, KANJI_LEVEL4, // 囚 + 0x56F6, KANJI_LEVEL4, // 囶 + 0x56F7, KANJI_LEVEL4, // 囷 + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDE01, KANJI_LEVEL4, // ᅵ + 0x5715, KANJI_LEVEL4, // 圕 + 0x5723, KANJI_LEVEL4, // 圣 + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDE55, KANJI_LEVEL4, // ᅵ + 0x5729, KANJI_LEVEL4, // 圩 + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDE7B, KANJI_LEVEL4, // ᅵ + 0x5745, KANJI_LEVEL4, // 坅 + 0x5746, KANJI_LEVEL4, // 坆 + 0x574C, KANJI_LEVEL4, // 坌 + 0x574D, KANJI_LEVEL4, // 坍 + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDE74, KANJI_LEVEL4, // ᅵ + 0x5768, KANJI_LEVEL4, // 坚 + 0x576F, KANJI_LEVEL4, // 坯 + 0x5773, KANJI_LEVEL4, // 坳 + 0x5774, KANJI_LEVEL4, // 坎 + 0x5775, KANJI_LEVEL4, // 坵 + 0x577B, KANJI_LEVEL4, // 坻 + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDEE4, KANJI_LEVEL4, // ᅵ + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDED7, KANJI_LEVEL4, // ᅵ + 0x57AC, KANJI_LEVEL4, // 垬 + 0x579A, KANJI_LEVEL4, // 垚 + 0x579D, KANJI_LEVEL4, // 垝 + 0x579E, KANJI_LEVEL4, // 垞 + 0x57A8, KANJI_LEVEL4, // 垚 + 0x57D7, KANJI_LEVEL4, // 埗 + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDEFD, KANJI_LEVEL4, // ᅵ + 0x57CC, KANJI_LEVEL4, // 埌 + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDF36, KANJI_LEVEL4, // ᅵ + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDF44, KANJI_LEVEL4, // ᅵ + 0x57DE, KANJI_LEVEL4, // 埞 + 0x57E6, KANJI_LEVEL4, // 埊 + 0x57F0, KANJI_LEVEL4, // 埰 + 0x364A, KANJI_LEVEL4, // 㙊 + 0x57F8, KANJI_LEVEL4, // 埞 + 0x57FB, KANJI_LEVEL4, // 埻 + 0x57FD, KANJI_LEVEL4, // 埜 + 0x5804, KANJI_LEVEL4, // 堄 + 0x581E, KANJI_LEVEL4, // 堞 + 0x5820, KANJI_LEVEL4, // å   + 0x5827, KANJI_LEVEL4, // å § + 0x5832, KANJI_LEVEL4, // å ² + 0x5839, KANJI_LEVEL4, // å ¹ + 0xD844, KANJI_LEVEL4, // ᅵ + 0xDFC4, KANJI_LEVEL4, // ᅵ + 0x5849, KANJI_LEVEL4, // 塉 + 0x584C, KANJI_LEVEL4, // 塌 + 0x5867, KANJI_LEVEL4, // å¡§ + 0x588A, KANJI_LEVEL4, // 墊 + 0x588B, KANJI_LEVEL4, // 墋 + 0x588D, KANJI_LEVEL4, // 墍 + 0x588F, KANJI_LEVEL4, // 墏 + 0x5890, KANJI_LEVEL4, // 墐 + 0x5894, KANJI_LEVEL4, // 墔 + 0x589D, KANJI_LEVEL4, // 墝 + 0x58AA, KANJI_LEVEL4, // 墪 + 0x58B1, KANJI_LEVEL4, // 墱 + 0xD845, KANJI_LEVEL4, // ᅵ + 0xDC6D, KANJI_LEVEL4, // ᅵ + 0x58C3, KANJI_LEVEL4, // 壃 + 0x58CD, KANJI_LEVEL4, // 壍 + 0x58E2, KANJI_LEVEL4, // 壢 + 0x58F3, KANJI_LEVEL4, // 壳 + 0x58F4, KANJI_LEVEL4, // 壎 + 0x5905, KANJI_LEVEL4, // 倅 + 0x5906, KANJI_LEVEL4, // 倆 + 0x590B, KANJI_LEVEL4, // 個 + 0x590D, KANJI_LEVEL4, // 倍 + 0x5914, KANJI_LEVEL4, // 倔 + 0x5924, KANJI_LEVEL4, // 倀 + 0xD845, KANJI_LEVEL4, // ᅵ + 0xDDD7, KANJI_LEVEL4, // ᅵ + 0x3691, KANJI_LEVEL4, // 㚑 + 0x593D, KANJI_LEVEL4, // 倜 + 0x3699, KANJI_LEVEL4, // 㚙 + 0x5946, KANJI_LEVEL4, // 奆 + 0x3696, KANJI_LEVEL4, // 㚖 + 0xD85B, KANJI_LEVEL4, // ᅵ + 0xDC29, KANJI_LEVEL4, // ᅵ + 0x595B, KANJI_LEVEL4, // 奛 + 0x595F, KANJI_LEVEL4, // 奟 + 0xD845, KANJI_LEVEL4, // ᅵ + 0xDE47, KANJI_LEVEL4, // ᅵ + 0x5975, KANJI_LEVEL4, // 奵 + 0x5976, KANJI_LEVEL4, // 奶 + 0x597C, KANJI_LEVEL4, // 奌 + 0x599F, KANJI_LEVEL4, // 功 + 0x59AE, KANJI_LEVEL4, // 劮 + 0x59BC, KANJI_LEVEL4, // 劌 + 0x59C8, KANJI_LEVEL4, // 姈 + 0x59CD, KANJI_LEVEL4, // 姍 + 0x59DE, KANJI_LEVEL4, // 姞 + 0x59E3, KANJI_LEVEL4, // å§£ + 0x59E4, KANJI_LEVEL4, // å§€ + 0x59E7, KANJI_LEVEL4, // å§§ + 0x59EE, KANJI_LEVEL4, // å§® + 0xD845, KANJI_LEVEL4, // ᅵ + 0xDF06, KANJI_LEVEL4, // ᅵ + 0xD845, KANJI_LEVEL4, // ᅵ + 0xDF42, KANJI_LEVEL4, // ᅵ + 0x36CF, KANJI_LEVEL4, // 㛏 + 0x5A0C, KANJI_LEVEL4, // 嚌 + 0x5A0D, KANJI_LEVEL4, // 嚍 + 0x5A17, KANJI_LEVEL4, // åš— + 0x5A27, KANJI_LEVEL4, // åš§ + 0x5A2D, KANJI_LEVEL4, // åš­ + 0x5A55, KANJI_LEVEL4, // 婕 + 0x5A65, KANJI_LEVEL4, // å©¥ + 0x5A7A, KANJI_LEVEL4, // 婺 + 0x5A8B, KANJI_LEVEL4, // 媋 + 0x5A9C, KANJI_LEVEL4, // 媜 + 0x5A9F, KANJI_LEVEL4, // 媟 + 0x5AA0, KANJI_LEVEL4, // 媠 + 0x5AA2, KANJI_LEVEL4, // 媢 + 0x5AB1, KANJI_LEVEL4, // 媱 + 0x5AB3, KANJI_LEVEL4, // 媳 + 0x5AB5, KANJI_LEVEL4, // 媵 + 0x5ABA, KANJI_LEVEL4, // 媺 + 0x5ABF, KANJI_LEVEL4, // 媿 + 0x5ADA, KANJI_LEVEL4, // 嫚 + 0x5ADC, KANJI_LEVEL4, // 嫜 + 0x5AE0, KANJI_LEVEL4, // å«  + 0x5AE5, KANJI_LEVEL4, // å«¥ + 0x5AF0, KANJI_LEVEL4, // å«° + 0x5AEE, KANJI_LEVEL4, // å«® + 0x5AF5, KANJI_LEVEL4, // 嫵 + 0x5B00, KANJI_LEVEL4, // 嬀 + 0x5B08, KANJI_LEVEL4, // 嬈 + 0x5B17, KANJI_LEVEL4, // 嬗 + 0x5B34, KANJI_LEVEL4, // 嬎 + 0x5B2D, KANJI_LEVEL4, // 嬭 + 0x5B4C, KANJI_LEVEL4, // 孌 + 0x5B52, KANJI_LEVEL4, // 孒 + 0x5B68, KANJI_LEVEL4, // å­š + 0x5B6F, KANJI_LEVEL4, // å­¯ + 0x5B7C, KANJI_LEVEL4, // å­Œ + 0x5B7F, KANJI_LEVEL4, // å­¿ + 0x5B81, KANJI_LEVEL4, // 宁 + 0x5B84, KANJI_LEVEL4, // 宄 + 0xD846, KANJI_LEVEL4, // ᅵ + 0xDDC3, KANJI_LEVEL4, // ᅵ + 0x5B96, KANJI_LEVEL4, // 宖 + 0x5BAC, KANJI_LEVEL4, // 宬 + 0x3761, KANJI_LEVEL4, // 㝡 + 0x5BC0, KANJI_LEVEL4, // 寀 + 0x3762, KANJI_LEVEL4, // 㝢 + 0x5BCE, KANJI_LEVEL4, // 寎 + 0x5BD6, KANJI_LEVEL4, // 寖 + 0x376C, KANJI_LEVEL4, // 㝬 + 0x376B, KANJI_LEVEL4, // 㝫 + 0x5BF1, KANJI_LEVEL4, // 寱 + 0x5BFD, KANJI_LEVEL4, // 寜 + 0x3775, KANJI_LEVEL4, // 㝵 + 0x5C03, KANJI_LEVEL4, // 尃 + 0x5C29, KANJI_LEVEL4, // å°© + 0x5C30, KANJI_LEVEL4, // å°° + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDC56, KANJI_LEVEL4, // ᅵ + 0x5C5F, KANJI_LEVEL4, // 屟 + 0x5C63, KANJI_LEVEL4, // å±£ + 0x5C67, KANJI_LEVEL4, // å±§ + 0x5C68, KANJI_LEVEL4, // 屚 + 0x5C69, KANJI_LEVEL4, // 屩 + 0x5C70, KANJI_LEVEL4, // å±° + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDD2D, KANJI_LEVEL4, // ᅵ + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDD45, KANJI_LEVEL4, // ᅵ + 0x5C7C, KANJI_LEVEL4, // 屌 + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDD78, KANJI_LEVEL4, // ᅵ + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDD62, KANJI_LEVEL4, // ᅵ + 0x5C88, KANJI_LEVEL4, // 岈 + 0x5C8A, KANJI_LEVEL4, // 岊 + 0x37C1, KANJI_LEVEL4, // 㟁 + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDDA1, KANJI_LEVEL4, // ᅵ + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDD9C, KANJI_LEVEL4, // ᅵ + 0x5CA0, KANJI_LEVEL4, // å²  + 0x5CA2, KANJI_LEVEL4, // å²¢ + 0x5CA6, KANJI_LEVEL4, // 岊 + 0x5CA7, KANJI_LEVEL4, // å²§ + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDD92, KANJI_LEVEL4, // ᅵ + 0x5CAD, KANJI_LEVEL4, // å²­ + 0x5CB5, KANJI_LEVEL4, // å²µ + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDDB7, KANJI_LEVEL4, // ᅵ + 0x5CC9, KANJI_LEVEL4, // 峉 + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDDE0, KANJI_LEVEL4, // ᅵ + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDE33, KANJI_LEVEL4, // ᅵ + 0x5D06, KANJI_LEVEL4, // 历 + 0x5D10, KANJI_LEVEL4, // 厐 + 0x5D2B, KANJI_LEVEL4, // 厫 + 0x5D1D, KANJI_LEVEL4, // 厝 + 0x5D20, KANJI_LEVEL4, // 厠 + 0x5D24, KANJI_LEVEL4, // 厀 + 0x5D26, KANJI_LEVEL4, // 厊 + 0x5D31, KANJI_LEVEL4, // 厱 + 0x5D39, KANJI_LEVEL4, // 厹 + 0x5D42, KANJI_LEVEL4, // 嵂 + 0x37E8, KANJI_LEVEL4, // 㟚 + 0x5D61, KANJI_LEVEL4, // 嵡 + 0x5D6A, KANJI_LEVEL4, // 嵪 + 0x37F4, KANJI_LEVEL4, // 㟎 + 0x5D70, KANJI_LEVEL4, // åµ° + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDF1E, KANJI_LEVEL4, // ᅵ + 0x37FD, KANJI_LEVEL4, // 㟜 + 0x5D88, KANJI_LEVEL4, // 嶈 + 0x3800, KANJI_LEVEL4, // 㠀 + 0x5D92, KANJI_LEVEL4, // 嶒 + 0x5D94, KANJI_LEVEL4, // 嶔 + 0x5D97, KANJI_LEVEL4, // 嶗 + 0x5D99, KANJI_LEVEL4, // 嶙 + 0x5DB0, KANJI_LEVEL4, // å¶° + 0x5DB2, KANJI_LEVEL4, // å¶² + 0x5DB4, KANJI_LEVEL4, // å¶Ž + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDF76, KANJI_LEVEL4, // ᅵ + 0x5DB9, KANJI_LEVEL4, // å¶¹ + 0x5DD1, KANJI_LEVEL4, // 巑 + 0x5DD7, KANJI_LEVEL4, // 巗 + 0x5DD8, KANJI_LEVEL4, // 巘 + 0x5DE0, KANJI_LEVEL4, // å·  + 0xD847, KANJI_LEVEL4, // ᅵ + 0xDFFA, KANJI_LEVEL4, // ᅵ + 0x5DE4, KANJI_LEVEL4, // å·€ + 0x5DE9, KANJI_LEVEL4, // å·© + 0x382F, KANJI_LEVEL4, // ã ¯ + 0x5E00, KANJI_LEVEL4, // 垀 + 0x3836, KANJI_LEVEL4, // ã ¶ + 0x5E12, KANJI_LEVEL4, // åž’ + 0x5E15, KANJI_LEVEL4, // åž• + 0x3840, KANJI_LEVEL4, // 㡀 + 0x5E1F, KANJI_LEVEL4, // 垟 + 0x5E2E, KANJI_LEVEL4, // åž® + 0x5E3E, KANJI_LEVEL4, // 垟 + 0x5E49, KANJI_LEVEL4, // 幉 + 0x385C, KANJI_LEVEL4, // 㡜 + 0x5E56, KANJI_LEVEL4, // 幖 + 0x3861, KANJI_LEVEL4, // ã¡¡ + 0x5E6B, KANJI_LEVEL4, // 幫 + 0x5E6C, KANJI_LEVEL4, // 幬 + 0x5E6D, KANJI_LEVEL4, // å¹­ + 0x5E6E, KANJI_LEVEL4, // å¹® + 0xD848, KANJI_LEVEL4, // ᅵ + 0xDD7B, KANJI_LEVEL4, // ᅵ + 0x5EA5, KANJI_LEVEL4, // 庥 + 0x5EAA, KANJI_LEVEL4, // 庪 + 0x5EAC, KANJI_LEVEL4, // 庬 + 0x5EB9, KANJI_LEVEL4, // 庹 + 0x5EBF, KANJI_LEVEL4, // 庿 + 0x5EC6, KANJI_LEVEL4, // 廆 + 0x5ED2, KANJI_LEVEL4, // 廒 + 0x5ED9, KANJI_LEVEL4, // 廙 + 0xD848, KANJI_LEVEL4, // ᅵ + 0xDF1E, KANJI_LEVEL4, // ᅵ + 0x5EFD, KANJI_LEVEL4, // 廜 + 0x5F08, KANJI_LEVEL4, // 匈 + 0x5F0E, KANJI_LEVEL4, // 匎 + 0x5F1C, KANJI_LEVEL4, // 匜 + 0xD848, KANJI_LEVEL4, // ᅵ + 0xDFAD, KANJI_LEVEL4, // ᅵ + 0x5F1E, KANJI_LEVEL4, // 匞 + 0x5F47, KANJI_LEVEL4, // 圇 + 0x5F63, KANJI_LEVEL4, // 圣 + 0x5F72, KANJI_LEVEL4, // 圲 + 0x5F7E, KANJI_LEVEL4, // 土 + 0x5F8F, KANJI_LEVEL4, // 埏 + 0x5FA2, KANJI_LEVEL4, // 埢 + 0x5FA4, KANJI_LEVEL4, // 埀 + 0x5FB8, KANJI_LEVEL4, // 埞 + 0x5FC4, KANJI_LEVEL4, // 忄 + 0x38FA, KANJI_LEVEL4, // 㣺 + 0x5FC7, KANJI_LEVEL4, // 忇 + 0x5FCB, KANJI_LEVEL4, // 忋 + 0x5FD2, KANJI_LEVEL4, // 忒 + 0x5FD3, KANJI_LEVEL4, // 忓 + 0x5FD4, KANJI_LEVEL4, // 忔 + 0x5FE2, KANJI_LEVEL4, // å¿¢ + 0x5FEE, KANJI_LEVEL4, // å¿® + 0x5FEF, KANJI_LEVEL4, // 忯 + 0x5FF3, KANJI_LEVEL4, // 忳 + 0x5FFC, KANJI_LEVEL4, // 忌 + 0x3917, KANJI_LEVEL4, // 〗 + 0x6017, KANJI_LEVEL4, // 怗 + 0x6022, KANJI_LEVEL4, // 怢 + 0x6024, KANJI_LEVEL4, // 怀 + 0x391A, KANJI_LEVEL4, // 〚 + 0x604C, KANJI_LEVEL4, // 恌 + 0x607F, KANJI_LEVEL4, // 恿 + 0x608A, KANJI_LEVEL4, // 悊 + 0x6095, KANJI_LEVEL4, // 悕 + 0x60A8, KANJI_LEVEL4, // 悚 + 0xD849, KANJI_LEVEL4, // ᅵ + 0xDEF3, KANJI_LEVEL4, // ᅵ + 0x60B0, KANJI_LEVEL4, // 悰 + 0x60B1, KANJI_LEVEL4, // 悱 + 0x60BE, KANJI_LEVEL4, // 悟 + 0x60C8, KANJI_LEVEL4, // 惈 + 0x60D9, KANJI_LEVEL4, // 惙 + 0x60DB, KANJI_LEVEL4, // 惛 + 0x60EE, KANJI_LEVEL4, // 惮 + 0x60F2, KANJI_LEVEL4, // 惲 + 0x60F5, KANJI_LEVEL4, // 惵 + 0x6110, KANJI_LEVEL4, // 愐 + 0x6112, KANJI_LEVEL4, // 愒 + 0x6113, KANJI_LEVEL4, // 愓 + 0x6119, KANJI_LEVEL4, // 愙 + 0x611E, KANJI_LEVEL4, // 愞 + 0x613A, KANJI_LEVEL4, // 愺 + 0x396F, KANJI_LEVEL4, // 㥯 + 0x6141, KANJI_LEVEL4, // 慁 + 0x6146, KANJI_LEVEL4, // 慆 + 0x6160, KANJI_LEVEL4, // 慠 + 0x617C, KANJI_LEVEL4, // æ…Œ + 0xD84A, KANJI_LEVEL4, // ᅵ + 0xDC5B, KANJI_LEVEL4, // ᅵ + 0x6192, KANJI_LEVEL4, // 憒 + 0x6193, KANJI_LEVEL4, // 憓 + 0x6197, KANJI_LEVEL4, // 憗 + 0x6198, KANJI_LEVEL4, // 憘 + 0x61A5, KANJI_LEVEL4, // 憥 + 0x61A8, KANJI_LEVEL4, // 憚 + 0x61AD, KANJI_LEVEL4, // 憭 + 0xD84A, KANJI_LEVEL4, // ᅵ + 0xDCAB, KANJI_LEVEL4, // ᅵ + 0x61D5, KANJI_LEVEL4, // 懕 + 0x61DD, KANJI_LEVEL4, // 懝 + 0x61DF, KANJI_LEVEL4, // 懟 + 0x61F5, KANJI_LEVEL4, // 懵 + 0xD84A, KANJI_LEVEL4, // ᅵ + 0xDD8F, KANJI_LEVEL4, // ᅵ + 0x6215, KANJI_LEVEL4, // 戕 + 0x6223, KANJI_LEVEL4, // 戣 + 0x6229, KANJI_LEVEL4, // 戩 + 0x6246, KANJI_LEVEL4, // 扆 + 0x624C, KANJI_LEVEL4, // 扌 + 0x6251, KANJI_LEVEL4, // 扑 + 0x6252, KANJI_LEVEL4, // 扒 + 0x6261, KANJI_LEVEL4, // 扡 + 0x6264, KANJI_LEVEL4, // 所 + 0x627B, KANJI_LEVEL4, // 扻 + 0x626D, KANJI_LEVEL4, // 扭 + 0x6273, KANJI_LEVEL4, // 扳 + 0x6299, KANJI_LEVEL4, // 抙 + 0x62A6, KANJI_LEVEL4, // 把 + 0x62D5, KANJI_LEVEL4, // 拕 + 0xD84A, KANJI_LEVEL4, // ᅵ + 0xDEB8, KANJI_LEVEL4, // ᅵ + 0x62FD, KANJI_LEVEL4, // 拜 + 0x6303, KANJI_LEVEL4, // 挃 + 0x630D, KANJI_LEVEL4, // 挍 + 0x6310, KANJI_LEVEL4, // 挐 + 0xD84A, KANJI_LEVEL4, // ᅵ + 0xDF4F, KANJI_LEVEL4, // ᅵ + 0xD84A, KANJI_LEVEL4, // ᅵ + 0xDF50, KANJI_LEVEL4, // ᅵ + 0x6332, KANJI_LEVEL4, // 挲 + 0x6335, KANJI_LEVEL4, // 挵 + 0x633B, KANJI_LEVEL4, // 挻 + 0x633C, KANJI_LEVEL4, // 挌 + 0x6341, KANJI_LEVEL4, // 捁 + 0x6344, KANJI_LEVEL4, // 捄 + 0x634E, KANJI_LEVEL4, // 捎 + 0xD84A, KANJI_LEVEL4, // ᅵ + 0xDF46, KANJI_LEVEL4, // ᅵ + 0x6359, KANJI_LEVEL4, // 捙 + 0xD84B, KANJI_LEVEL4, // ᅵ + 0xDC1D, KANJI_LEVEL4, // ᅵ + 0xD84A, KANJI_LEVEL4, // ᅵ + 0xDFA6, KANJI_LEVEL4, // ᅵ + 0x636C, KANJI_LEVEL4, // 捬 + 0x6384, KANJI_LEVEL4, // 掄 + 0x6399, KANJI_LEVEL4, // 掙 + 0xD84B, KANJI_LEVEL4, // ᅵ + 0xDC24, KANJI_LEVEL4, // ᅵ + 0x6394, KANJI_LEVEL4, // 掔 + 0x63BD, KANJI_LEVEL4, // 掜 + 0x63F7, KANJI_LEVEL4, // 揷 + 0x63D4, KANJI_LEVEL4, // 揔 + 0x63D5, KANJI_LEVEL4, // 揕 + 0x63DC, KANJI_LEVEL4, // 揜 + 0x63E0, KANJI_LEVEL4, // 揠 + 0x63EB, KANJI_LEVEL4, // 揫 + 0x63EC, KANJI_LEVEL4, // 揬 + 0x63F2, KANJI_LEVEL4, // 揲 + 0x6409, KANJI_LEVEL4, // 搉 + 0x641E, KANJI_LEVEL4, // 搞 + 0x6425, KANJI_LEVEL4, // 搥 + 0x6429, KANJI_LEVEL4, // 搩 + 0x642F, KANJI_LEVEL4, // 搯 + 0x645A, KANJI_LEVEL4, // 摚 + 0x645B, KANJI_LEVEL4, // 摛 + 0x645D, KANJI_LEVEL4, // 摝 + 0x6473, KANJI_LEVEL4, // 摳 + 0x647D, KANJI_LEVEL4, // 摜 + 0x6487, KANJI_LEVEL4, // 撇 + 0x6491, KANJI_LEVEL4, // 撑 + 0x649D, KANJI_LEVEL4, // 撝 + 0x649F, KANJI_LEVEL4, // 撟 + 0x64CB, KANJI_LEVEL4, // 擋 + 0x64CC, KANJI_LEVEL4, // 擌 + 0x64D5, KANJI_LEVEL4, // 擕 + 0x64D7, KANJI_LEVEL4, // 擗 + 0xD84B, KANJI_LEVEL4, // ᅵ + 0xDDE1, KANJI_LEVEL4, // ᅵ + 0x64E4, KANJI_LEVEL4, // æ“€ + 0x64E5, KANJI_LEVEL4, // 擥 + 0x64FF, KANJI_LEVEL4, // 擿 + 0x6504, KANJI_LEVEL4, // 攄 + 0x3A6E, KANJI_LEVEL4, // ã©® + 0x650F, KANJI_LEVEL4, // 攏 + 0x6514, KANJI_LEVEL4, // 攔 + 0x6516, KANJI_LEVEL4, // 攖 + 0x3A73, KANJI_LEVEL4, // 㩳 + 0x651E, KANJI_LEVEL4, // 攞 + 0x6532, KANJI_LEVEL4, // 攲 + 0x6544, KANJI_LEVEL4, // 敄 + 0x6554, KANJI_LEVEL4, // 敔 + 0x656B, KANJI_LEVEL4, // 敫 + 0x657A, KANJI_LEVEL4, // 敺 + 0x6581, KANJI_LEVEL4, // 斁 + 0x6584, KANJI_LEVEL4, // 斄 + 0x6585, KANJI_LEVEL4, // 斅 + 0x658A, KANJI_LEVEL4, // 斊 + 0x65B2, KANJI_LEVEL4, // 斲 + 0x65B5, KANJI_LEVEL4, // 斵 + 0x65B8, KANJI_LEVEL4, // æ–ž + 0x65BF, KANJI_LEVEL4, // 斿 + 0x65C2, KANJI_LEVEL4, // 旂 + 0x65C9, KANJI_LEVEL4, // 旉 + 0x65D4, KANJI_LEVEL4, // 旔 + 0x3AD6, KANJI_LEVEL4, // 㫖 + 0x65F2, KANJI_LEVEL4, // 旲 + 0x65F9, KANJI_LEVEL4, // 旹 + 0x65FC, KANJI_LEVEL4, // æ—Œ + 0x6604, KANJI_LEVEL4, // 昄 + 0x6608, KANJI_LEVEL4, // 昈 + 0x6621, KANJI_LEVEL4, // 昡 + 0x662A, KANJI_LEVEL4, // 昪 + 0x6645, KANJI_LEVEL4, // 晅 + 0x6651, KANJI_LEVEL4, // 晑 + 0x664E, KANJI_LEVEL4, // 晎 + 0x3AEA, KANJI_LEVEL4, // 㫪 + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDDC3, KANJI_LEVEL4, // ᅵ + 0x6657, KANJI_LEVEL4, // 晗 + 0x665B, KANJI_LEVEL4, // 晛 + 0x6663, KANJI_LEVEL4, // 晣 + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDDF5, KANJI_LEVEL4, // ᅵ + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDDB6, KANJI_LEVEL4, // ᅵ + 0x666A, KANJI_LEVEL4, // 晪 + 0x666B, KANJI_LEVEL4, // 晫 + 0x666C, KANJI_LEVEL4, // 晬 + 0x666D, KANJI_LEVEL4, // 晭 + 0x667B, KANJI_LEVEL4, // 晻 + 0x6680, KANJI_LEVEL4, // 暀 + 0x6690, KANJI_LEVEL4, // 暐 + 0x6692, KANJI_LEVEL4, // 暒 + 0x6699, KANJI_LEVEL4, // 暙 + 0x3B0E, KANJI_LEVEL4, // 㬎 + 0x66AD, KANJI_LEVEL4, // 暭 + 0x66B1, KANJI_LEVEL4, // 暱 + 0x66B5, KANJI_LEVEL4, // 暵 + 0x3B1A, KANJI_LEVEL4, // 㬚 + 0x66BF, KANJI_LEVEL4, // 暿 + 0x3B1C, KANJI_LEVEL4, // 㬜 + 0x66EC, KANJI_LEVEL4, // 曬 + 0x3AD7, KANJI_LEVEL4, // 㫗 + 0x6701, KANJI_LEVEL4, // 朁 + 0x6705, KANJI_LEVEL4, // 朅 + 0x6712, KANJI_LEVEL4, // 朒 + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDF72, KANJI_LEVEL4, // ᅵ + 0x6719, KANJI_LEVEL4, // 朙 + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDFD3, KANJI_LEVEL4, // ᅵ + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDFD2, KANJI_LEVEL4, // ᅵ + 0x674C, KANJI_LEVEL4, // 杌 + 0x674D, KANJI_LEVEL4, // 杍 + 0x6754, KANJI_LEVEL4, // 杔 + 0x675D, KANJI_LEVEL4, // 杝 + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDFD0, KANJI_LEVEL4, // ᅵ + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDFE4, KANJI_LEVEL4, // ᅵ + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDFD5, KANJI_LEVEL4, // ᅵ + 0x6774, KANJI_LEVEL4, // 李 + 0x6776, KANJI_LEVEL4, // 杶 + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDFDA, KANJI_LEVEL4, // ᅵ + 0x6792, KANJI_LEVEL4, // 枒 + 0xD84C, KANJI_LEVEL4, // ᅵ + 0xDFDF, KANJI_LEVEL4, // ᅵ + 0x8363, KANJI_LEVEL4, // 荣 + 0x6810, KANJI_LEVEL4, // 栐 + 0x67B0, KANJI_LEVEL4, // 枰 + 0x67B2, KANJI_LEVEL4, // 枲 + 0x67C3, KANJI_LEVEL4, // 柃 + 0x67C8, KANJI_LEVEL4, // 柈 + 0x67D2, KANJI_LEVEL4, // 柒 + 0x67D9, KANJI_LEVEL4, // 柙 + 0x67DB, KANJI_LEVEL4, // 柛 + 0x67F0, KANJI_LEVEL4, // 柰 + 0x67F7, KANJI_LEVEL4, // 柷 + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDC4A, KANJI_LEVEL4, // ᅵ + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDC51, KANJI_LEVEL4, // ᅵ + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDC4B, KANJI_LEVEL4, // ᅵ + 0x6818, KANJI_LEVEL4, // 栘 + 0x681F, KANJI_LEVEL4, // 栟 + 0x682D, KANJI_LEVEL4, // æ ­ + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDC65, KANJI_LEVEL4, // ᅵ + 0x6833, KANJI_LEVEL4, // æ ³ + 0x683B, KANJI_LEVEL4, // æ » + 0x683E, KANJI_LEVEL4, // æ Ÿ + 0x6844, KANJI_LEVEL4, // 桄 + 0x6845, KANJI_LEVEL4, // 桅 + 0x6849, KANJI_LEVEL4, // 桉 + 0x684C, KANJI_LEVEL4, // 桌 + 0x6855, KANJI_LEVEL4, // 桕 + 0x6857, KANJI_LEVEL4, // 桗 + 0x3B77, KANJI_LEVEL4, // ã­· + 0x686B, KANJI_LEVEL4, // æ¡« + 0x686E, KANJI_LEVEL4, // æ¡® + 0x687A, KANJI_LEVEL4, // 桺 + 0x687C, KANJI_LEVEL4, // 桌 + 0x6882, KANJI_LEVEL4, // 梂 + 0x6890, KANJI_LEVEL4, // 梐 + 0x6896, KANJI_LEVEL4, // 梖 + 0x3B6D, KANJI_LEVEL4, // ã­­ + 0x6898, KANJI_LEVEL4, // 梘 + 0x6899, KANJI_LEVEL4, // 梙 + 0x689A, KANJI_LEVEL4, // 梚 + 0x689C, KANJI_LEVEL4, // 梜 + 0x68AA, KANJI_LEVEL4, // 梪 + 0x68AB, KANJI_LEVEL4, // 梫 + 0x68B4, KANJI_LEVEL4, // 梎 + 0x68BB, KANJI_LEVEL4, // 梻 + 0x68FB, KANJI_LEVEL4, // 棻 + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDCE4, KANJI_LEVEL4, // ᅵ + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDD5A, KANJI_LEVEL4, // ᅵ + 0xFA13, KANJI_LEVEL4, // ïš“ + 0x68C3, KANJI_LEVEL4, // 棃 + 0x68C5, KANJI_LEVEL4, // 棅 + 0x68CC, KANJI_LEVEL4, // 棌 + 0x68CF, KANJI_LEVEL4, // 棏 + 0x68D6, KANJI_LEVEL4, // 棖 + 0x68D9, KANJI_LEVEL4, // 棙 + 0x68E4, KANJI_LEVEL4, // 检 + 0x68E5, KANJI_LEVEL4, // 棥 + 0x68EC, KANJI_LEVEL4, // 棬 + 0x68F7, KANJI_LEVEL4, // 棷 + 0x6903, KANJI_LEVEL4, // 怃 + 0x6907, KANJI_LEVEL4, // 怇 + 0x3B87, KANJI_LEVEL4, // 㮇 + 0x3B88, KANJI_LEVEL4, // 㮈 + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDD94, KANJI_LEVEL4, // ᅵ + 0x693B, KANJI_LEVEL4, // 总 + 0x3B8D, KANJI_LEVEL4, // 㮍 + 0x6946, KANJI_LEVEL4, // 楆 + 0x6969, KANJI_LEVEL4, // 楩 + 0x696C, KANJI_LEVEL4, // 楬 + 0x6972, KANJI_LEVEL4, // 楲 + 0x697A, KANJI_LEVEL4, // 楺 + 0x697F, KANJI_LEVEL4, // 楿 + 0x6992, KANJI_LEVEL4, // 抒 + 0x3BA4, KANJI_LEVEL4, // 㮀 + 0x6996, KANJI_LEVEL4, // 抖 + 0x6998, KANJI_LEVEL4, // 折 + 0x69A6, KANJI_LEVEL4, // 把 + 0x69B0, KANJI_LEVEL4, // 抰 + 0x69B7, KANJI_LEVEL4, // 抷 + 0x69BA, KANJI_LEVEL4, // 抺 + 0x69BC, KANJI_LEVEL4, // 抌 + 0x69C0, KANJI_LEVEL4, // 槀 + 0x69D1, KANJI_LEVEL4, // 槑 + 0x69D6, KANJI_LEVEL4, // 槖 + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDE39, KANJI_LEVEL4, // ᅵ + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDE47, KANJI_LEVEL4, // ᅵ + 0x6A30, KANJI_LEVEL4, // æš° + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDE38, KANJI_LEVEL4, // ᅵ + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDE3A, KANJI_LEVEL4, // ᅵ + 0x69E3, KANJI_LEVEL4, // æ§£ + 0x69EE, KANJI_LEVEL4, // æ§® + 0x69EF, KANJI_LEVEL4, // 槯 + 0x69F3, KANJI_LEVEL4, // æ§³ + 0x3BCD, KANJI_LEVEL4, // 㯍 + 0x69F4, KANJI_LEVEL4, // æ§Ž + 0x69FE, KANJI_LEVEL4, // æ§Ÿ + 0x6A11, KANJI_LEVEL4, // æš‘ + 0x6A1A, KANJI_LEVEL4, // æšš + 0x6A1D, KANJI_LEVEL4, // 暝 + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDF1C, KANJI_LEVEL4, // ᅵ + 0x6A32, KANJI_LEVEL4, // æš² + 0x6A33, KANJI_LEVEL4, // æš³ + 0x6A34, KANJI_LEVEL4, // 暎 + 0x6A3F, KANJI_LEVEL4, // æš¿ + 0x6A46, KANJI_LEVEL4, // 橆 + 0x6A49, KANJI_LEVEL4, // 橉 + 0x6A7A, KANJI_LEVEL4, // 橺 + 0x6A4E, KANJI_LEVEL4, // 橎 + 0x6A52, KANJI_LEVEL4, // 橒 + 0x6A64, KANJI_LEVEL4, // æ©€ + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDF0C, KANJI_LEVEL4, // ᅵ + 0x6A7E, KANJI_LEVEL4, // 機 + 0x6A83, KANJI_LEVEL4, // 檃 + 0x6A8B, KANJI_LEVEL4, // 檋 + 0x3BF0, KANJI_LEVEL4, // 㯰 + 0x6A91, KANJI_LEVEL4, // 檑 + 0x6A9F, KANJI_LEVEL4, // 檟 + 0x6AA1, KANJI_LEVEL4, // 檡 + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDF64, KANJI_LEVEL4, // ᅵ + 0x6AAB, KANJI_LEVEL4, // 檫 + 0x6ABD, KANJI_LEVEL4, // 檜 + 0x6AC6, KANJI_LEVEL4, // 櫆 + 0x6AD4, KANJI_LEVEL4, // 櫔 + 0x6AD0, KANJI_LEVEL4, // 櫐 + 0x6ADC, KANJI_LEVEL4, // 櫜 + 0x6ADD, KANJI_LEVEL4, // 櫝 + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDFFF, KANJI_LEVEL4, // ᅵ + 0xD84D, KANJI_LEVEL4, // ᅵ + 0xDFE7, KANJI_LEVEL4, // ᅵ + 0x6AEC, KANJI_LEVEL4, // 櫬 + 0x6AF1, KANJI_LEVEL4, // 櫱 + 0x6AF2, KANJI_LEVEL4, // 櫲 + 0x6AF3, KANJI_LEVEL4, // 櫳 + 0x6AFD, KANJI_LEVEL4, // 櫜 + 0xD84E, KANJI_LEVEL4, // ᅵ + 0xDC24, KANJI_LEVEL4, // ᅵ + 0x6B0B, KANJI_LEVEL4, // 欋 + 0x6B0F, KANJI_LEVEL4, // 欏 + 0x6B10, KANJI_LEVEL4, // 欐 + 0x6B11, KANJI_LEVEL4, // 欑 + 0xD84E, KANJI_LEVEL4, // ᅵ + 0xDC3D, KANJI_LEVEL4, // ᅵ + 0x6B17, KANJI_LEVEL4, // 欗 + 0x3C26, KANJI_LEVEL4, // ã°Š + 0x6B2F, KANJI_LEVEL4, // 欯 + 0x6B4A, KANJI_LEVEL4, // 歊 + 0x6B58, KANJI_LEVEL4, // 歘 + 0x6B6C, KANJI_LEVEL4, // æ­¬ + 0x6B75, KANJI_LEVEL4, // æ­µ + 0x6B7A, KANJI_LEVEL4, // æ­º + 0x6B81, KANJI_LEVEL4, // 殁 + 0x6B9B, KANJI_LEVEL4, // 殛 + 0x6BAE, KANJI_LEVEL4, // æ®® + 0xD84E, KANJI_LEVEL4, // ᅵ + 0xDE98, KANJI_LEVEL4, // ᅵ + 0x6BBD, KANJI_LEVEL4, // 殜 + 0x6BBE, KANJI_LEVEL4, // 殟 + 0x6BC7, KANJI_LEVEL4, // 毇 + 0x6BC8, KANJI_LEVEL4, // 毈 + 0x6BC9, KANJI_LEVEL4, // 毉 + 0x6BDA, KANJI_LEVEL4, // 毚 + 0x6BE6, KANJI_LEVEL4, // 毊 + 0x6BE7, KANJI_LEVEL4, // 毧 + 0x6BEE, KANJI_LEVEL4, // 毮 + 0x6BF1, KANJI_LEVEL4, // 毱 + 0x6C02, KANJI_LEVEL4, // 氂 + 0x6C0A, KANJI_LEVEL4, // 氊 + 0x6C0E, KANJI_LEVEL4, // 氎 + 0x6C35, KANJI_LEVEL4, // æ°µ + 0x6C36, KANJI_LEVEL4, // æ°¶ + 0x6C3A, KANJI_LEVEL4, // æ°º + 0xD84F, KANJI_LEVEL4, // ᅵ + 0xDC7F, KANJI_LEVEL4, // ᅵ + 0x6C3F, KANJI_LEVEL4, // æ°¿ + 0x6C4D, KANJI_LEVEL4, // 汍 + 0x6C5B, KANJI_LEVEL4, // 汛 + 0x6C6D, KANJI_LEVEL4, // æ±­ + 0x6C84, KANJI_LEVEL4, // 沄 + 0x6C89, KANJI_LEVEL4, // 沉 + 0x3CC3, KANJI_LEVEL4, // 㳃 + 0x6C94, KANJI_LEVEL4, // 沔 + 0x6C95, KANJI_LEVEL4, // 沕 + 0x6C97, KANJI_LEVEL4, // 沗 + 0x6CAD, KANJI_LEVEL4, // æ²­ + 0x6CC2, KANJI_LEVEL4, // 泂 + 0x6CD0, KANJI_LEVEL4, // 泐 + 0x3CD2, KANJI_LEVEL4, // 㳒 + 0x6CD6, KANJI_LEVEL4, // 泖 + 0x6CDA, KANJI_LEVEL4, // 泚 + 0x6CDC, KANJI_LEVEL4, // 泜 + 0x6CE9, KANJI_LEVEL4, // 泩 + 0x6CEC, KANJI_LEVEL4, // 泬 + 0x6CED, KANJI_LEVEL4, // æ³­ + 0xD84F, KANJI_LEVEL4, // ᅵ + 0xDD00, KANJI_LEVEL4, // ᅵ + 0x6D00, KANJI_LEVEL4, // 掀 + 0x6D0A, KANJI_LEVEL4, // 掊 + 0x6D24, KANJI_LEVEL4, // 掀 + 0x6D26, KANJI_LEVEL4, // 掊 + 0x6D27, KANJI_LEVEL4, // 控 + 0x6C67, KANJI_LEVEL4, // æ±§ + 0x6D2F, KANJI_LEVEL4, // 掯 + 0x6D3C, KANJI_LEVEL4, // 掌 + 0x6D5B, KANJI_LEVEL4, // 浛 + 0x6D5E, KANJI_LEVEL4, // 浞 + 0x6D60, KANJI_LEVEL4, // æµ  + 0x6D70, KANJI_LEVEL4, // æµ° + 0x6D80, KANJI_LEVEL4, // 涀 + 0x6D81, KANJI_LEVEL4, // 涁 + 0x6D8A, KANJI_LEVEL4, // 涊 + 0x6D8D, KANJI_LEVEL4, // 涍 + 0x6D91, KANJI_LEVEL4, // 涑 + 0x6D98, KANJI_LEVEL4, // 涘 + 0xD84F, KANJI_LEVEL4, // ᅵ + 0xDD40, KANJI_LEVEL4, // ᅵ + 0x6E17, KANJI_LEVEL4, // æž— + 0xD84F, KANJI_LEVEL4, // ᅵ + 0xDDFA, KANJI_LEVEL4, // ᅵ + 0xD84F, KANJI_LEVEL4, // ᅵ + 0xDDF9, KANJI_LEVEL4, // ᅵ + 0xD84F, KANJI_LEVEL4, // ᅵ + 0xDDD3, KANJI_LEVEL4, // ᅵ + 0x6DAB, KANJI_LEVEL4, // æ¶« + 0x6DAE, KANJI_LEVEL4, // æ¶® + 0x6DB4, KANJI_LEVEL4, // æ¶Ž + 0x6DC2, KANJI_LEVEL4, // 淂 + 0x6D34, KANJI_LEVEL4, // 掎 + 0x6DC8, KANJI_LEVEL4, // 淈 + 0x6DCE, KANJI_LEVEL4, // 淎 + 0x6DCF, KANJI_LEVEL4, // 淏 + 0x6DD0, KANJI_LEVEL4, // 淐 + 0x6DDF, KANJI_LEVEL4, // 淟 + 0x6DE9, KANJI_LEVEL4, // æ·© + 0x6DF6, KANJI_LEVEL4, // æ·¶ + 0x6E36, KANJI_LEVEL4, // æž¶ + 0x6E1E, KANJI_LEVEL4, // æžž + 0x6E22, KANJI_LEVEL4, // 枢 + 0x6E27, KANJI_LEVEL4, // æž§ + 0x3D11, KANJI_LEVEL4, // ㎑ + 0x6E32, KANJI_LEVEL4, // æž² + 0x6E3C, KANJI_LEVEL4, // 枌 + 0x6E48, KANJI_LEVEL4, // 湈 + 0x6E49, KANJI_LEVEL4, // 湉 + 0x6E4B, KANJI_LEVEL4, // 湋 + 0x6E4C, KANJI_LEVEL4, // 湌 + 0x6E4F, KANJI_LEVEL4, // 湏 + 0x6E51, KANJI_LEVEL4, // 湑 + 0x6E53, KANJI_LEVEL4, // 湓 + 0x6E54, KANJI_LEVEL4, // 湔 + 0x6E57, KANJI_LEVEL4, // 湗 + 0x6E63, KANJI_LEVEL4, // æ¹£ + 0x3D1E, KANJI_LEVEL4, // ㎞ + 0x6E93, KANJI_LEVEL4, // 溓 + 0x6EA7, KANJI_LEVEL4, // 溧 + 0x6EB4, KANJI_LEVEL4, // 溎 + 0x6EBF, KANJI_LEVEL4, // 溿 + 0x6EC3, KANJI_LEVEL4, // 滃 + 0x6ECA, KANJI_LEVEL4, // 滊 + 0x6ED9, KANJI_LEVEL4, // 滙 + 0x6F35, KANJI_LEVEL4, // 挵 + 0x6EEB, KANJI_LEVEL4, // 滫 + 0x6EF9, KANJI_LEVEL4, // 滹 + 0x6EFB, KANJI_LEVEL4, // æ»» + 0x6F0A, KANJI_LEVEL4, // 挊 + 0x6F0C, KANJI_LEVEL4, // 挌 + 0x6F18, KANJI_LEVEL4, // 挘 + 0x6F25, KANJI_LEVEL4, // 挥 + 0x6F36, KANJI_LEVEL4, // 挶 + 0x6F3C, KANJI_LEVEL4, // 挌 + 0xD84F, KANJI_LEVEL4, // ᅵ + 0xDF7E, KANJI_LEVEL4, // ᅵ + 0x6F52, KANJI_LEVEL4, // 朒 + 0x6F57, KANJI_LEVEL4, // 朗 + 0x6F5A, KANJI_LEVEL4, // 朚 + 0x6F60, KANJI_LEVEL4, // 朠 + 0x6F68, KANJI_LEVEL4, // 朚 + 0x6F98, KANJI_LEVEL4, // 柘 + 0x6F7D, KANJI_LEVEL4, // 朜 + 0x6F90, KANJI_LEVEL4, // 某 + 0x6F96, KANJI_LEVEL4, // 柖 + 0x6FBE, KANJI_LEVEL4, // 柟 + 0x6F9F, KANJI_LEVEL4, // 柟 + 0x6FA5, KANJI_LEVEL4, // 查 + 0x6FAF, KANJI_LEVEL4, // 柯 + 0x3D64, KANJI_LEVEL4, // ãµ€ + 0x6FB5, KANJI_LEVEL4, // 柵 + 0x6FC8, KANJI_LEVEL4, // 濈 + 0x6FC9, KANJI_LEVEL4, // 濉 + 0x6FDA, KANJI_LEVEL4, // 濚 + 0x6FDE, KANJI_LEVEL4, // 濞 + 0x6FE9, KANJI_LEVEL4, // æ¿© + 0xD850, KANJI_LEVEL4, // ᅵ + 0xDC96, KANJI_LEVEL4, // ᅵ + 0x6FFC, KANJI_LEVEL4, // 濌 + 0x7000, KANJI_LEVEL4, // 瀀 + 0x7007, KANJI_LEVEL4, // 瀇 + 0x700A, KANJI_LEVEL4, // 瀊 + 0x7023, KANJI_LEVEL4, // 瀣 + 0xD850, KANJI_LEVEL4, // ᅵ + 0xDD03, KANJI_LEVEL4, // ᅵ + 0x7039, KANJI_LEVEL4, // 瀹 + 0x703A, KANJI_LEVEL4, // 瀺 + 0x703C, KANJI_LEVEL4, // 瀌 + 0x7043, KANJI_LEVEL4, // 灃 + 0x7047, KANJI_LEVEL4, // 灇 + 0x704B, KANJI_LEVEL4, // 灋 + 0x3D9A, KANJI_LEVEL4, // 㶚 + 0x7054, KANJI_LEVEL4, // 灔 + 0x7065, KANJI_LEVEL4, // 灥 + 0x7069, KANJI_LEVEL4, // 灩 + 0x706C, KANJI_LEVEL4, // 灬 + 0x706E, KANJI_LEVEL4, // 灮 + 0x7076, KANJI_LEVEL4, // 灶 + 0x707E, KANJI_LEVEL4, // 灟 + 0x7081, KANJI_LEVEL4, // 炁 + 0x7086, KANJI_LEVEL4, // 炆 + 0x7095, KANJI_LEVEL4, // 炕 + 0x7097, KANJI_LEVEL4, // 炗 + 0x70BB, KANJI_LEVEL4, // 炻 + 0xD850, KANJI_LEVEL4, // ᅵ + 0xDDC6, KANJI_LEVEL4, // ᅵ + 0x709F, KANJI_LEVEL4, // 炟 + 0x70B1, KANJI_LEVEL4, // 炱 + 0xD850, KANJI_LEVEL4, // ᅵ + 0xDDFE, KANJI_LEVEL4, // ᅵ + 0x70EC, KANJI_LEVEL4, // 烬 + 0x70CA, KANJI_LEVEL4, // 烊 + 0x70D1, KANJI_LEVEL4, // 烑 + 0x70D3, KANJI_LEVEL4, // 烓 + 0x70DC, KANJI_LEVEL4, // 烜 + 0x7103, KANJI_LEVEL4, // 焃 + 0x7104, KANJI_LEVEL4, // 焄 + 0x7106, KANJI_LEVEL4, // 焆 + 0x7107, KANJI_LEVEL4, // 焇 + 0x7108, KANJI_LEVEL4, // 焈 + 0x710C, KANJI_LEVEL4, // 焌 + 0x3DC0, KANJI_LEVEL4, // 㷀 + 0x712F, KANJI_LEVEL4, // 焯 + 0x7131, KANJI_LEVEL4, // 焱 + 0x7150, KANJI_LEVEL4, // 煐 + 0x714A, KANJI_LEVEL4, // 煊 + 0x7153, KANJI_LEVEL4, // 煓 + 0x715E, KANJI_LEVEL4, // 煞 + 0x3DD4, KANJI_LEVEL4, // 㷔 + 0x7196, KANJI_LEVEL4, // 熖 + 0x7180, KANJI_LEVEL4, // 熀 + 0x719B, KANJI_LEVEL4, // 熛 + 0x71A0, KANJI_LEVEL4, // 熠 + 0x71A2, KANJI_LEVEL4, // 熢 + 0x71AE, KANJI_LEVEL4, // 熮 + 0x71AF, KANJI_LEVEL4, // 熯 + 0x71B3, KANJI_LEVEL4, // 熳 + 0xD850, KANJI_LEVEL4, // ᅵ + 0xDFBC, KANJI_LEVEL4, // ᅵ + 0x71CB, KANJI_LEVEL4, // 燋 + 0x71D3, KANJI_LEVEL4, // 燓 + 0x71D9, KANJI_LEVEL4, // 燙 + 0x71DC, KANJI_LEVEL4, // 燜 + 0x7207, KANJI_LEVEL4, // 爇 + 0x3E05, KANJI_LEVEL4, // ãž… + 0xFA49, KANJI_LEVEL4, // 爫 + 0x722B, KANJI_LEVEL4, // 爫 + 0x7234, KANJI_LEVEL4, // 爎 + 0x7238, KANJI_LEVEL4, // 爞 + 0x7239, KANJI_LEVEL4, // 爹 + 0x4E2C, KANJI_LEVEL4, // 䞬 + 0x7242, KANJI_LEVEL4, // 牂 + 0x7253, KANJI_LEVEL4, // 牓 + 0x7257, KANJI_LEVEL4, // 牗 + 0x7263, KANJI_LEVEL4, // 牣 + 0xD851, KANJI_LEVEL4, // ᅵ + 0xDE29, KANJI_LEVEL4, // ᅵ + 0x726E, KANJI_LEVEL4, // 牮 + 0x726F, KANJI_LEVEL4, // 牯 + 0x7278, KANJI_LEVEL4, // 牾 + 0x727F, KANJI_LEVEL4, // 牿 + 0x728E, KANJI_LEVEL4, // 犎 + 0xD851, KANJI_LEVEL4, // ᅵ + 0xDEA5, KANJI_LEVEL4, // ᅵ + 0x72AD, KANJI_LEVEL4, // 犭 + 0x72AE, KANJI_LEVEL4, // 犮 + 0x72B0, KANJI_LEVEL4, // 犰 + 0x72B1, KANJI_LEVEL4, // 犱 + 0x72C1, KANJI_LEVEL4, // 狁 + 0x3E60, KANJI_LEVEL4, // ã¹  + 0x72CC, KANJI_LEVEL4, // 狌 + 0x3E66, KANJI_LEVEL4, // 㹊 + 0x3E68, KANJI_LEVEL4, // 㹚 + 0x72F3, KANJI_LEVEL4, // 狳 + 0x72FA, KANJI_LEVEL4, // 狺 + 0x7307, KANJI_LEVEL4, // 猇 + 0x7312, KANJI_LEVEL4, // 猒 + 0x7318, KANJI_LEVEL4, // 猘 + 0x7319, KANJI_LEVEL4, // 猙 + 0x3E83, KANJI_LEVEL4, // 㺃 + 0x7339, KANJI_LEVEL4, // 猹 + 0x732C, KANJI_LEVEL4, // 猬 + 0x7331, KANJI_LEVEL4, // 猱 + 0x7333, KANJI_LEVEL4, // 猳 + 0x733D, KANJI_LEVEL4, // 猜 + 0x7352, KANJI_LEVEL4, // 獒 + 0x3E94, KANJI_LEVEL4, // 㺔 + 0x736B, KANJI_LEVEL4, // 獫 + 0x736C, KANJI_LEVEL4, // 獬 + 0xD852, KANJI_LEVEL4, // ᅵ + 0xDC96, KANJI_LEVEL4, // ᅵ + 0x736E, KANJI_LEVEL4, // 獮 + 0x736F, KANJI_LEVEL4, // 獯 + 0x7371, KANJI_LEVEL4, // 獱 + 0x7377, KANJI_LEVEL4, // 獷 + 0x7381, KANJI_LEVEL4, // 玁 + 0x7385, KANJI_LEVEL4, // 玅 + 0x738A, KANJI_LEVEL4, // 玊 + 0x7394, KANJI_LEVEL4, // 玔 + 0x7398, KANJI_LEVEL4, // 玘 + 0x739C, KANJI_LEVEL4, // 玜 + 0x739E, KANJI_LEVEL4, // 玞 + 0x73A5, KANJI_LEVEL4, // 玥 + 0x73A8, KANJI_LEVEL4, // 玚 + 0x73B5, KANJI_LEVEL4, // 玵 + 0x73B7, KANJI_LEVEL4, // 玷 + 0x73B9, KANJI_LEVEL4, // 玹 + 0x73BC, KANJI_LEVEL4, // 玌 + 0x73BF, KANJI_LEVEL4, // 玿 + 0x73C5, KANJI_LEVEL4, // 珅 + 0x73CB, KANJI_LEVEL4, // 珋 + 0x73E1, KANJI_LEVEL4, // 珡 + 0x73E7, KANJI_LEVEL4, // 珧 + 0x73F9, KANJI_LEVEL4, // 珹 + 0x7413, KANJI_LEVEL4, // 琓 + 0x73FA, KANJI_LEVEL4, // 珺 + 0x7401, KANJI_LEVEL4, // 琁 + 0x7424, KANJI_LEVEL4, // 琀 + 0x7431, KANJI_LEVEL4, // 琱 + 0x7439, KANJI_LEVEL4, // 琹 + 0x7453, KANJI_LEVEL4, // 瑓 + 0x7440, KANJI_LEVEL4, // 瑀 + 0x7443, KANJI_LEVEL4, // 瑃 + 0x744D, KANJI_LEVEL4, // 瑍 + 0x7452, KANJI_LEVEL4, // 瑒 + 0x745D, KANJI_LEVEL4, // 瑝 + 0x7471, KANJI_LEVEL4, // 瑱 + 0x7481, KANJI_LEVEL4, // 璁 + 0x7485, KANJI_LEVEL4, // 璅 + 0x7488, KANJI_LEVEL4, // 璈 + 0xD852, KANJI_LEVEL4, // ᅵ + 0xDE4D, KANJI_LEVEL4, // ᅵ + 0x7492, KANJI_LEVEL4, // 璒 + 0x7497, KANJI_LEVEL4, // 璗 + 0x7499, KANJI_LEVEL4, // 璙 + 0x74A0, KANJI_LEVEL4, // 璠 + 0x74A1, KANJI_LEVEL4, // 璡 + 0x74A5, KANJI_LEVEL4, // 璥 + 0x74AA, KANJI_LEVEL4, // 璪 + 0x74AB, KANJI_LEVEL4, // 璫 + 0x74B9, KANJI_LEVEL4, // 璹 + 0x74BB, KANJI_LEVEL4, // 璻 + 0x74BA, KANJI_LEVEL4, // 璺 + 0x74D6, KANJI_LEVEL4, // 瓖 + 0x74D8, KANJI_LEVEL4, // 瓘 + 0x74DE, KANJI_LEVEL4, // 瓞 + 0x74EF, KANJI_LEVEL4, // 瓯 + 0x74EB, KANJI_LEVEL4, // 瓫 + 0xD852, KANJI_LEVEL4, // ᅵ + 0xDF56, KANJI_LEVEL4, // ᅵ + 0x74FA, KANJI_LEVEL4, // 瓺 + 0xD852, KANJI_LEVEL4, // ᅵ + 0xDF6F, KANJI_LEVEL4, // ᅵ + 0x7520, KANJI_LEVEL4, // 甠 + 0x7524, KANJI_LEVEL4, // 甀 + 0x752A, KANJI_LEVEL4, // 甪 + 0x3F57, KANJI_LEVEL4, // 㜗 + 0xD853, KANJI_LEVEL4, // ᅵ + 0xDC16, KANJI_LEVEL4, // ᅵ + 0x753D, KANJI_LEVEL4, // 甜 + 0x753E, KANJI_LEVEL4, // 生 + 0x7540, KANJI_LEVEL4, // 畀 + 0x7548, KANJI_LEVEL4, // 畈 + 0x754E, KANJI_LEVEL4, // 畎 + 0x7550, KANJI_LEVEL4, // 畐 + 0x7552, KANJI_LEVEL4, // 畒 + 0x756C, KANJI_LEVEL4, // 畬 + 0x7572, KANJI_LEVEL4, // 畲 + 0x7571, KANJI_LEVEL4, // 畱 + 0x757A, KANJI_LEVEL4, // 畺 + 0x757D, KANJI_LEVEL4, // 畜 + 0x757E, KANJI_LEVEL4, // 畟 + 0x7581, KANJI_LEVEL4, // 疁 + 0xD853, KANJI_LEVEL4, // ᅵ + 0xDD14, KANJI_LEVEL4, // ᅵ + 0x758C, KANJI_LEVEL4, // 疌 + 0x3F75, KANJI_LEVEL4, // 㜵 + 0x75A2, KANJI_LEVEL4, // 疢 + 0x3F77, KANJI_LEVEL4, // 㜷 + 0x75B0, KANJI_LEVEL4, // 疰 + 0x75B7, KANJI_LEVEL4, // 疷 + 0x75BF, KANJI_LEVEL4, // 疿 + 0x75C0, KANJI_LEVEL4, // 痀 + 0x75C6, KANJI_LEVEL4, // 痆 + 0x75CF, KANJI_LEVEL4, // 痏 + 0x75D3, KANJI_LEVEL4, // 痓 + 0x75DD, KANJI_LEVEL4, // 痝 + 0x75DF, KANJI_LEVEL4, // 痟 + 0x75E0, KANJI_LEVEL4, // 痠 + 0x75E7, KANJI_LEVEL4, // 痧 + 0x75EC, KANJI_LEVEL4, // 痬 + 0x75EE, KANJI_LEVEL4, // 痮 + 0x75F1, KANJI_LEVEL4, // 痱 + 0x75F9, KANJI_LEVEL4, // 痹 + 0x7603, KANJI_LEVEL4, // 瘃 + 0x7618, KANJI_LEVEL4, // 瘘 + 0x7607, KANJI_LEVEL4, // 瘇 + 0x760F, KANJI_LEVEL4, // 瘏 + 0x3FAE, KANJI_LEVEL4, // 㟮 + 0xD853, KANJI_LEVEL4, // ᅵ + 0xDE0E, KANJI_LEVEL4, // ᅵ + 0x7613, KANJI_LEVEL4, // 瘓 + 0x761B, KANJI_LEVEL4, // 瘛 + 0x761C, KANJI_LEVEL4, // 瘜 + 0xD853, KANJI_LEVEL4, // ᅵ + 0xDE37, KANJI_LEVEL4, // ᅵ + 0x7625, KANJI_LEVEL4, // 瘥 + 0x7628, KANJI_LEVEL4, // 瘚 + 0x763C, KANJI_LEVEL4, // 瘌 + 0x7633, KANJI_LEVEL4, // 瘳 + 0xD853, KANJI_LEVEL4, // ᅵ + 0xDE6A, KANJI_LEVEL4, // ᅵ + 0x3FC9, KANJI_LEVEL4, // 㿉 + 0x7641, KANJI_LEVEL4, // 癁 + 0xD853, KANJI_LEVEL4, // ᅵ + 0xDE8B, KANJI_LEVEL4, // ᅵ + 0x7649, KANJI_LEVEL4, // 癉 + 0x7655, KANJI_LEVEL4, // 癕 + 0x3FD7, KANJI_LEVEL4, // 㿗 + 0x766E, KANJI_LEVEL4, // 癮 + 0x7695, KANJI_LEVEL4, // 皕 + 0x769C, KANJI_LEVEL4, // 皜 + 0x76A1, KANJI_LEVEL4, // 皡 + 0x76A0, KANJI_LEVEL4, // 皠 + 0x76A7, KANJI_LEVEL4, // 皧 + 0x76A8, KANJI_LEVEL4, // 皹 + 0x76AF, KANJI_LEVEL4, // 皯 + 0xD854, KANJI_LEVEL4, // ᅵ + 0xDC4A, KANJI_LEVEL4, // ᅵ + 0x76C9, KANJI_LEVEL4, // 盉 + 0xD854, KANJI_LEVEL4, // ᅵ + 0xDC55, KANJI_LEVEL4, // ᅵ + 0x76E8, KANJI_LEVEL4, // 盹 + 0x76EC, KANJI_LEVEL4, // 盬 + 0xD854, KANJI_LEVEL4, // ᅵ + 0xDD22, KANJI_LEVEL4, // ᅵ + 0x7717, KANJI_LEVEL4, // 眗 + 0x771A, KANJI_LEVEL4, // 眚 + 0x772D, KANJI_LEVEL4, // 眭 + 0x7735, KANJI_LEVEL4, // 眵 + 0xD854, KANJI_LEVEL4, // ᅵ + 0xDDA9, KANJI_LEVEL4, // ᅵ + 0x4039, KANJI_LEVEL4, // 䀹 + 0xD854, KANJI_LEVEL4, // ᅵ + 0xDDE5, KANJI_LEVEL4, // ᅵ + 0xD854, KANJI_LEVEL4, // ᅵ + 0xDDCD, KANJI_LEVEL4, // ᅵ + 0x7758, KANJI_LEVEL4, // 睘 + 0x7760, KANJI_LEVEL4, // 睠 + 0x776A, KANJI_LEVEL4, // 睪 + 0xD854, KANJI_LEVEL4, // ᅵ + 0xDE1E, KANJI_LEVEL4, // ᅵ + 0x7772, KANJI_LEVEL4, // 睲 + 0x777C, KANJI_LEVEL4, // 睌 + 0x777D, KANJI_LEVEL4, // 睜 + 0xD854, KANJI_LEVEL4, // ᅵ + 0xDE4C, KANJI_LEVEL4, // ᅵ + 0x4058, KANJI_LEVEL4, // 䁘 + 0x779A, KANJI_LEVEL4, // 瞚 + 0x779F, KANJI_LEVEL4, // 瞟 + 0x77A2, KANJI_LEVEL4, // 瞢 + 0x77A4, KANJI_LEVEL4, // 瞀 + 0x77A9, KANJI_LEVEL4, // 瞩 + 0x77DE, KANJI_LEVEL4, // 矞 + 0x77DF, KANJI_LEVEL4, // 矟 + 0x77E4, KANJI_LEVEL4, // 矀 + 0x77E6, KANJI_LEVEL4, // 矩 + 0x77EA, KANJI_LEVEL4, // 矪 + 0x77EC, KANJI_LEVEL4, // 矬 + 0x4093, KANJI_LEVEL4, // 䂓 + 0x77F0, KANJI_LEVEL4, // 矰 + 0x77F4, KANJI_LEVEL4, // 矮 + 0x77FB, KANJI_LEVEL4, // 矻 + 0xD855, KANJI_LEVEL4, // ᅵ + 0xDC2E, KANJI_LEVEL4, // ᅵ + 0x7805, KANJI_LEVEL4, // 砅 + 0x7806, KANJI_LEVEL4, // 砆 + 0x7809, KANJI_LEVEL4, // 砉 + 0x780D, KANJI_LEVEL4, // 砍 + 0x7819, KANJI_LEVEL4, // 砙 + 0x7821, KANJI_LEVEL4, // ç ¡ + 0x782C, KANJI_LEVEL4, // ç ¬ + 0x7847, KANJI_LEVEL4, // 硇 + 0x7864, KANJI_LEVEL4, // ç¡€ + 0x786A, KANJI_LEVEL4, // 硪 + 0xD855, KANJI_LEVEL4, // ᅵ + 0xDCD9, KANJI_LEVEL4, // ᅵ + 0x788A, KANJI_LEVEL4, // 碊 + 0x7894, KANJI_LEVEL4, // 碔 + 0x78A4, KANJI_LEVEL4, // 碀 + 0x789D, KANJI_LEVEL4, // 碝 + 0x789E, KANJI_LEVEL4, // 碞 + 0x789F, KANJI_LEVEL4, // 碟 + 0x78BB, KANJI_LEVEL4, // 碻 + 0x78C8, KANJI_LEVEL4, // 磈 + 0x78CC, KANJI_LEVEL4, // 磌 + 0x78CE, KANJI_LEVEL4, // 磎 + 0x78D5, KANJI_LEVEL4, // 磕 + 0x78E0, KANJI_LEVEL4, // 磠 + 0x78E1, KANJI_LEVEL4, // 磡 + 0x78E6, KANJI_LEVEL4, // 磊 + 0x78F9, KANJI_LEVEL4, // 磹 + 0x78FA, KANJI_LEVEL4, // 磺 + 0x78FB, KANJI_LEVEL4, // 磻 + 0x78FE, KANJI_LEVEL4, // 磟 + 0xD855, KANJI_LEVEL4, // ᅵ + 0xDDA7, KANJI_LEVEL4, // ᅵ + 0x7910, KANJI_LEVEL4, // 瀐 + 0x791B, KANJI_LEVEL4, // 瀛 + 0x7930, KANJI_LEVEL4, // 瀰 + 0x7925, KANJI_LEVEL4, // 瀥 + 0x793B, KANJI_LEVEL4, // 瀻 + 0x794A, KANJI_LEVEL4, // 祊 + 0x7958, KANJI_LEVEL4, // 祘 + 0x795B, KANJI_LEVEL4, // 祛 + 0x4105, KANJI_LEVEL4, // 䄅 + 0x7967, KANJI_LEVEL4, // 祧 + 0x7972, KANJI_LEVEL4, // 祲 + 0x7994, KANJI_LEVEL4, // 穔 + 0x7995, KANJI_LEVEL4, // 穕 + 0x7996, KANJI_LEVEL4, // 穖 + 0x799B, KANJI_LEVEL4, // 穛 + 0x79A1, KANJI_LEVEL4, // 犡 + 0x79A9, KANJI_LEVEL4, // 犩 + 0x79B4, KANJI_LEVEL4, // 犎 + 0x79BB, KANJI_LEVEL4, // 犻 + 0x79C2, KANJI_LEVEL4, // 秂 + 0x79C7, KANJI_LEVEL4, // 秇 + 0x79CC, KANJI_LEVEL4, // 秌 + 0x79CD, KANJI_LEVEL4, // 种 + 0x79D6, KANJI_LEVEL4, // 秖 + 0x4148, KANJI_LEVEL4, // 䅈 + 0xD855, KANJI_LEVEL4, // ᅵ + 0xDFA9, KANJI_LEVEL4, // ᅵ + 0xD855, KANJI_LEVEL4, // ᅵ + 0xDFB4, KANJI_LEVEL4, // ᅵ + 0x414F, KANJI_LEVEL4, // 䅏 + 0x7A0A, KANJI_LEVEL4, // 繊 + 0x7A11, KANJI_LEVEL4, // 繑 + 0x7A15, KANJI_LEVEL4, // 繕 + 0x7A1B, KANJI_LEVEL4, // 繛 + 0x7A1E, KANJI_LEVEL4, // 皞 + 0x4163, KANJI_LEVEL4, // 䅣 + 0x7A2D, KANJI_LEVEL4, // çš­ + 0x7A38, KANJI_LEVEL4, // çšž + 0x7A47, KANJI_LEVEL4, // 穇 + 0x7A4C, KANJI_LEVEL4, // 穌 + 0x7A56, KANJI_LEVEL4, // 穖 + 0x7A59, KANJI_LEVEL4, // 穙 + 0x7A5C, KANJI_LEVEL4, // 穜 + 0x7A5F, KANJI_LEVEL4, // 穟 + 0x7A60, KANJI_LEVEL4, // ç©  + 0x7A67, KANJI_LEVEL4, // ç©§ + 0x7A6A, KANJI_LEVEL4, // 穪 + 0x7A75, KANJI_LEVEL4, // 穵 + 0x7A78, KANJI_LEVEL4, // 穞 + 0x7A82, KANJI_LEVEL4, // 窂 + 0x7A8A, KANJI_LEVEL4, // 窊 + 0x7A90, KANJI_LEVEL4, // 窐 + 0x7AA3, KANJI_LEVEL4, // 窣 + 0x7AAC, KANJI_LEVEL4, // 窬 + 0xD856, KANJI_LEVEL4, // ᅵ + 0xDDD4, KANJI_LEVEL4, // ᅵ + 0x41B4, KANJI_LEVEL4, // 䆮 + 0x7AB9, KANJI_LEVEL4, // 窹 + 0x7ABC, KANJI_LEVEL4, // 窌 + 0x7ABE, KANJI_LEVEL4, // 窟 + 0x41BF, KANJI_LEVEL4, // 䆿 + 0x7ACC, KANJI_LEVEL4, // 竌 + 0x7AD1, KANJI_LEVEL4, // 竑 + 0x7AE7, KANJI_LEVEL4, // ç«§ + 0x7AE8, KANJI_LEVEL4, // 竚 + 0x7AF4, KANJI_LEVEL4, // 竎 + 0xD856, KANJI_LEVEL4, // ᅵ + 0xDEE4, KANJI_LEVEL4, // ᅵ + 0xD856, KANJI_LEVEL4, // ᅵ + 0xDEE3, KANJI_LEVEL4, // ᅵ + 0x7B07, KANJI_LEVEL4, // 笇 + 0xD856, KANJI_LEVEL4, // ᅵ + 0xDEF1, KANJI_LEVEL4, // ᅵ + 0x7B3D, KANJI_LEVEL4, // 笜 + 0x7B27, KANJI_LEVEL4, // 笧 + 0x7B2A, KANJI_LEVEL4, // 笪 + 0x7B2E, KANJI_LEVEL4, // 笮 + 0x7B2F, KANJI_LEVEL4, // 笯 + 0x7B31, KANJI_LEVEL4, // 笱 + 0x41E6, KANJI_LEVEL4, // 䇩 + 0x41F3, KANJI_LEVEL4, // 䇳 + 0x7B7F, KANJI_LEVEL4, // ç­¿ + 0x7B41, KANJI_LEVEL4, // 筁 + 0x41EE, KANJI_LEVEL4, // 䇮 + 0x7B55, KANJI_LEVEL4, // 筕 + 0x7B79, KANJI_LEVEL4, // ç­¹ + 0x7B64, KANJI_LEVEL4, // ç­€ + 0x7B66, KANJI_LEVEL4, // ç­Š + 0x7B69, KANJI_LEVEL4, // ç­© + 0x7B73, KANJI_LEVEL4, // ç­³ + 0xD856, KANJI_LEVEL4, // ᅵ + 0xDFB2, KANJI_LEVEL4, // ᅵ + 0x4207, KANJI_LEVEL4, // 䈇 + 0x7B90, KANJI_LEVEL4, // 箐 + 0x7B91, KANJI_LEVEL4, // 箑 + 0x7B9B, KANJI_LEVEL4, // 箛 + 0x420E, KANJI_LEVEL4, // 䈎 + 0x7BAF, KANJI_LEVEL4, // 箯 + 0x7BB5, KANJI_LEVEL4, // 箵 + 0x7BBC, KANJI_LEVEL4, // 箌 + 0x7BC5, KANJI_LEVEL4, // 篅 + 0x7BCA, KANJI_LEVEL4, // 篊 + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDC4B, KANJI_LEVEL4, // ᅵ + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDC64, KANJI_LEVEL4, // ᅵ + 0x7BD4, KANJI_LEVEL4, // 篔 + 0x7BD6, KANJI_LEVEL4, // 篖 + 0x7BDA, KANJI_LEVEL4, // 篚 + 0x7BEA, KANJI_LEVEL4, // 篪 + 0x7BF0, KANJI_LEVEL4, // 篰 + 0x7C03, KANJI_LEVEL4, // 簃 + 0x7C0B, KANJI_LEVEL4, // 簋 + 0x7C0E, KANJI_LEVEL4, // 簎 + 0x7C0F, KANJI_LEVEL4, // 簏 + 0x7C26, KANJI_LEVEL4, // ç°Š + 0x7C45, KANJI_LEVEL4, // 籅 + 0x7C4A, KANJI_LEVEL4, // 籊 + 0x7C51, KANJI_LEVEL4, // 籑 + 0x7C57, KANJI_LEVEL4, // 籗 + 0x7C5E, KANJI_LEVEL4, // 籞 + 0x7C61, KANJI_LEVEL4, // 籡 + 0x7C69, KANJI_LEVEL4, // 籩 + 0x7C6E, KANJI_LEVEL4, // ç±® + 0x7C6F, KANJI_LEVEL4, // 籯 + 0x7C70, KANJI_LEVEL4, // ç±° + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDE2E, KANJI_LEVEL4, // ᅵ + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDE56, KANJI_LEVEL4, // ᅵ + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDE65, KANJI_LEVEL4, // ᅵ + 0x7CA6, KANJI_LEVEL4, // 粊 + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDE62, KANJI_LEVEL4, // ᅵ + 0x7CB6, KANJI_LEVEL4, // ç²¶ + 0x7CB7, KANJI_LEVEL4, // ç²· + 0x7CBF, KANJI_LEVEL4, // 粿 + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDED8, KANJI_LEVEL4, // ᅵ + 0x7CC4, KANJI_LEVEL4, // 糄 + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDEC2, KANJI_LEVEL4, // ᅵ + 0x7CC8, KANJI_LEVEL4, // 糈 + 0x7CCD, KANJI_LEVEL4, // 糍 + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDEE8, KANJI_LEVEL4, // ᅵ + 0x7CD7, KANJI_LEVEL4, // 糗 + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDF23, KANJI_LEVEL4, // ᅵ + 0x7CE6, KANJI_LEVEL4, // 糊 + 0x7CEB, KANJI_LEVEL4, // 糫 + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDF5C, KANJI_LEVEL4, // ᅵ + 0x7CF5, KANJI_LEVEL4, // ç³µ + 0x7D03, KANJI_LEVEL4, // 玃 + 0x7D09, KANJI_LEVEL4, // 箉 + 0x42C6, KANJI_LEVEL4, // 䋆 + 0x7D12, KANJI_LEVEL4, // 箒 + 0x7D1E, KANJI_LEVEL4, // 箞 + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDFE0, KANJI_LEVEL4, // ᅵ + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDFD4, KANJI_LEVEL4, // ᅵ + 0x7D3D, KANJI_LEVEL4, // 玜 + 0x7D3E, KANJI_LEVEL4, // 玟 + 0x7D40, KANJI_LEVEL4, // 絀 + 0x7D47, KANJI_LEVEL4, // 絇 + 0xD858, KANJI_LEVEL4, // ᅵ + 0xDC0C, KANJI_LEVEL4, // ᅵ + 0xD857, KANJI_LEVEL4, // ᅵ + 0xDFFB, KANJI_LEVEL4, // ᅵ + 0x42D6, KANJI_LEVEL4, // 䋖 + 0x7D59, KANJI_LEVEL4, // 絙 + 0x7D5A, KANJI_LEVEL4, // 絚 + 0x7D6A, KANJI_LEVEL4, // 絪 + 0x7D70, KANJI_LEVEL4, // çµ° + 0x42DD, KANJI_LEVEL4, // 䋝 + 0x7D7F, KANJI_LEVEL4, // 絿 + 0xD858, KANJI_LEVEL4, // ᅵ + 0xDC17, KANJI_LEVEL4, // ᅵ + 0x7D86, KANJI_LEVEL4, // 綆 + 0x7D88, KANJI_LEVEL4, // 綈 + 0x7D8C, KANJI_LEVEL4, // 綌 + 0x7D97, KANJI_LEVEL4, // 綗 + 0xD858, KANJI_LEVEL4, // ᅵ + 0xDC60, KANJI_LEVEL4, // ᅵ + 0x7D9D, KANJI_LEVEL4, // 綝 + 0x7DA7, KANJI_LEVEL4, // ç¶§ + 0x7DAA, KANJI_LEVEL4, // 綪 + 0x7DB6, KANJI_LEVEL4, // ç¶¶ + 0x7DB7, KANJI_LEVEL4, // ç¶· + 0x7DC0, KANJI_LEVEL4, // 緀 + 0x7DD7, KANJI_LEVEL4, // 緗 + 0x7DD9, KANJI_LEVEL4, // 緙 + 0x7DE6, KANJI_LEVEL4, // ç·Š + 0x7DF1, KANJI_LEVEL4, // ç·± + 0x7DF9, KANJI_LEVEL4, // ç·¹ + 0x4302, KANJI_LEVEL4, // 䌂 + 0xD858, KANJI_LEVEL4, // ᅵ + 0xDCED, KANJI_LEVEL4, // ᅵ + 0xFA58, KANJI_LEVEL4, // 縉 + 0x7E10, KANJI_LEVEL4, // 瞐 + 0x7E17, KANJI_LEVEL4, // 羗 + 0x7E1D, KANJI_LEVEL4, // 瞝 + 0x7E20, KANJI_LEVEL4, // çž  + 0x7E27, KANJI_LEVEL4, // çž§ + 0x7E2C, KANJI_LEVEL4, // 瞬 + 0x7E45, KANJI_LEVEL4, // 繅 + 0x7E73, KANJI_LEVEL4, // ç¹³ + 0x7E75, KANJI_LEVEL4, // ç¹µ + 0x7E7E, KANJI_LEVEL4, // 繟 + 0x7E86, KANJI_LEVEL4, // 纆 + 0x7E87, KANJI_LEVEL4, // 纇 + 0x432B, KANJI_LEVEL4, // 䌫 + 0x7E91, KANJI_LEVEL4, // 纑 + 0x7E98, KANJI_LEVEL4, // 纘 + 0x7E9A, KANJI_LEVEL4, // 纚 + 0x4343, KANJI_LEVEL4, // 䍃 + 0x7F3C, KANJI_LEVEL4, // 猌 + 0x7F3B, KANJI_LEVEL4, // 猻 + 0x7F3E, KANJI_LEVEL4, // 猟 + 0x7F43, KANJI_LEVEL4, // 眃 + 0x7F44, KANJI_LEVEL4, // 眄 + 0x7F4F, KANJI_LEVEL4, // 眏 + 0x34C1, KANJI_LEVEL4, // 㓁 + 0xD858, KANJI_LEVEL4, // ᅵ + 0xDE70, KANJI_LEVEL4, // ᅵ + 0x7F52, KANJI_LEVEL4, // 眒 + 0xD858, KANJI_LEVEL4, // ᅵ + 0xDE86, KANJI_LEVEL4, // ᅵ + 0x7F61, KANJI_LEVEL4, // 眡 + 0x7F63, KANJI_LEVEL4, // 眣 + 0x7F64, KANJI_LEVEL4, // 眀 + 0x7F6D, KANJI_LEVEL4, // 眭 + 0x7F7D, KANJI_LEVEL4, // 眜 + 0x7F7E, KANJI_LEVEL4, // 真 + 0xD858, KANJI_LEVEL4, // ᅵ + 0xDF4C, KANJI_LEVEL4, // ᅵ + 0x7F90, KANJI_LEVEL4, // 矐 + 0x517B, KANJI_LEVEL4, // 养 + 0xD84F, KANJI_LEVEL4, // ᅵ + 0xDD0E, KANJI_LEVEL4, // ᅵ + 0x7F96, KANJI_LEVEL4, // 矖 + 0x7F9C, KANJI_LEVEL4, // 矜 + 0x7FAD, KANJI_LEVEL4, // 短 + 0xD859, KANJI_LEVEL4, // ᅵ + 0xDC02, KANJI_LEVEL4, // ᅵ + 0x7FC3, KANJI_LEVEL4, // 翃 + 0x7FCF, KANJI_LEVEL4, // 翏 + 0x7FE3, KANJI_LEVEL4, // ç¿£ + 0x7FE5, KANJI_LEVEL4, // ç¿¥ + 0x7FEF, KANJI_LEVEL4, // 翯 + 0x7FF2, KANJI_LEVEL4, // 翲 + 0x8002, KANJI_LEVEL4, // 耂 + 0x800A, KANJI_LEVEL4, // 耊 + 0x8008, KANJI_LEVEL4, // 耈 + 0x800E, KANJI_LEVEL4, // 耎 + 0x8011, KANJI_LEVEL4, // 耑 + 0x8016, KANJI_LEVEL4, // 耖 + 0x8024, KANJI_LEVEL4, // 耀 + 0x802C, KANJI_LEVEL4, // 耬 + 0x8030, KANJI_LEVEL4, // 耰 + 0x8043, KANJI_LEVEL4, // 聃 + 0x8066, KANJI_LEVEL4, // 聊 + 0x8071, KANJI_LEVEL4, // 聱 + 0x8075, KANJI_LEVEL4, // 聵 + 0x807B, KANJI_LEVEL4, // 聻 + 0x8099, KANJI_LEVEL4, // 肙 + 0x809C, KANJI_LEVEL4, // 肜 + 0x80A4, KANJI_LEVEL4, // è‚€ + 0x80A7, KANJI_LEVEL4, // 肧 + 0x80B8, KANJI_LEVEL4, // 肞 + 0xD859, KANJI_LEVEL4, // ᅵ + 0xDE7E, KANJI_LEVEL4, // ᅵ + 0x80C5, KANJI_LEVEL4, // 胅 + 0x80D5, KANJI_LEVEL4, // 胕 + 0x80D8, KANJI_LEVEL4, // 胘 + 0x80E6, KANJI_LEVEL4, // 胊 + 0xD859, KANJI_LEVEL4, // ᅵ + 0xDEB0, KANJI_LEVEL4, // ᅵ + 0x810D, KANJI_LEVEL4, // 脍 + 0x80F5, KANJI_LEVEL4, // 胵 + 0x80FB, KANJI_LEVEL4, // 胻 + 0x43EE, KANJI_LEVEL4, // 䏮 + 0x8135, KANJI_LEVEL4, // 脵 + 0x8116, KANJI_LEVEL4, // 脖 + 0x811E, KANJI_LEVEL4, // 脞 + 0x43F0, KANJI_LEVEL4, // 䏰 + 0x8124, KANJI_LEVEL4, // è„€ + 0x8127, KANJI_LEVEL4, // 脧 + 0x812C, KANJI_LEVEL4, // 脬 + 0xD859, KANJI_LEVEL4, // ᅵ + 0xDF1D, KANJI_LEVEL4, // ᅵ + 0x813D, KANJI_LEVEL4, // 脜 + 0x4408, KANJI_LEVEL4, // 䐈 + 0x8169, KANJI_LEVEL4, // 腩 + 0x4417, KANJI_LEVEL4, // 䐗 + 0x8181, KANJI_LEVEL4, // 膁 + 0x441C, KANJI_LEVEL4, // 䐜 + 0x8184, KANJI_LEVEL4, // 膄 + 0x8185, KANJI_LEVEL4, // 膅 + 0x4422, KANJI_LEVEL4, // 䐢 + 0x8198, KANJI_LEVEL4, // 膘 + 0x81B2, KANJI_LEVEL4, // 膲 + 0x81C1, KANJI_LEVEL4, // 臁 + 0x81C3, KANJI_LEVEL4, // 臃 + 0x81D6, KANJI_LEVEL4, // 臖 + 0x81DB, KANJI_LEVEL4, // 臛 + 0xD85A, KANJI_LEVEL4, // ᅵ + 0xDCDD, KANJI_LEVEL4, // ᅵ + 0x81E4, KANJI_LEVEL4, // 臀 + 0xD85A, KANJI_LEVEL4, // ᅵ + 0xDCEA, KANJI_LEVEL4, // ᅵ + 0x81EC, KANJI_LEVEL4, // 臬 + 0xD85A, KANJI_LEVEL4, // ᅵ + 0xDD51, KANJI_LEVEL4, // ᅵ + 0x81FD, KANJI_LEVEL4, // 臜 + 0x81FF, KANJI_LEVEL4, // 臿 + 0xD85A, KANJI_LEVEL4, // ᅵ + 0xDD6F, KANJI_LEVEL4, // ᅵ + 0x8204, KANJI_LEVEL4, // 舄 + 0xD85A, KANJI_LEVEL4, // ᅵ + 0xDDDD, KANJI_LEVEL4, // ᅵ + 0x8219, KANJI_LEVEL4, // 舙 + 0x8221, KANJI_LEVEL4, // 舡 + 0x8222, KANJI_LEVEL4, // 舢 + 0xD85A, KANJI_LEVEL4, // ᅵ + 0xDE1E, KANJI_LEVEL4, // ᅵ + 0x8232, KANJI_LEVEL4, // 舲 + 0x8234, KANJI_LEVEL4, // 舎 + 0x823C, KANJI_LEVEL4, // 舌 + 0x8246, KANJI_LEVEL4, // 艆 + 0x8249, KANJI_LEVEL4, // 艉 + 0x8245, KANJI_LEVEL4, // 艅 + 0xD85A, KANJI_LEVEL4, // ᅵ + 0xDE58, KANJI_LEVEL4, // ᅵ + 0x824B, KANJI_LEVEL4, // 艋 + 0x4476, KANJI_LEVEL4, // 䑶 + 0x824F, KANJI_LEVEL4, // 艏 + 0x447A, KANJI_LEVEL4, // 䑺 + 0x8257, KANJI_LEVEL4, // 艗 + 0xD85A, KANJI_LEVEL4, // ᅵ + 0xDE8C, KANJI_LEVEL4, // ᅵ + 0x825C, KANJI_LEVEL4, // 艜 + 0x8263, KANJI_LEVEL4, // 艣 + 0xD85A, KANJI_LEVEL4, // ᅵ + 0xDEB7, KANJI_LEVEL4, // ᅵ + 0xFA5D, KANJI_LEVEL4, // 艹 + 0xFA5E, KANJI_LEVEL4, // 艹 + 0x8279, KANJI_LEVEL4, // 艹 + 0x4491, KANJI_LEVEL4, // 䒑 + 0x827D, KANJI_LEVEL4, // 艜 + 0x827F, KANJI_LEVEL4, // 艿 + 0x8283, KANJI_LEVEL4, // 芃 + 0x828A, KANJI_LEVEL4, // 芊 + 0x8293, KANJI_LEVEL4, // 芓 + 0x82A7, KANJI_LEVEL4, // 芧 + 0x82A8, KANJI_LEVEL4, // 芚 + 0x82B2, KANJI_LEVEL4, // 芲 + 0x82B4, KANJI_LEVEL4, // 芎 + 0x82BA, KANJI_LEVEL4, // 芺 + 0x82BC, KANJI_LEVEL4, // 芌 + 0x82E2, KANJI_LEVEL4, // 苢 + 0x82E8, KANJI_LEVEL4, // 苚 + 0x82F7, KANJI_LEVEL4, // 苷 + 0x8307, KANJI_LEVEL4, // 茇 + 0x8308, KANJI_LEVEL4, // 茈 + 0x830C, KANJI_LEVEL4, // 茌 + 0x8354, KANJI_LEVEL4, // 荔 + 0x831B, KANJI_LEVEL4, // 茛 + 0x831D, KANJI_LEVEL4, // 茝 + 0x8330, KANJI_LEVEL4, // 茰 + 0x833C, KANJI_LEVEL4, // 茌 + 0x8344, KANJI_LEVEL4, // 荄 + 0x8357, KANJI_LEVEL4, // 荗 + 0x44BE, KANJI_LEVEL4, // ä’Ÿ + 0x837F, KANJI_LEVEL4, // 荿 + 0x44D4, KANJI_LEVEL4, // 䓔 + 0x44B3, KANJI_LEVEL4, // 䒳 + 0x838D, KANJI_LEVEL4, // 莍 + 0x8394, KANJI_LEVEL4, // 莔 + 0x8395, KANJI_LEVEL4, // 莕 + 0x839B, KANJI_LEVEL4, // 莛 + 0x839D, KANJI_LEVEL4, // 莝 + 0x83C9, KANJI_LEVEL4, // 菉 + 0x83D0, KANJI_LEVEL4, // 菐 + 0x83D4, KANJI_LEVEL4, // 菔 + 0x83DD, KANJI_LEVEL4, // 菝 + 0x83E5, KANJI_LEVEL4, // 菥 + 0x83F9, KANJI_LEVEL4, // 菹 + 0x840F, KANJI_LEVEL4, // 萏 + 0x8411, KANJI_LEVEL4, // 萑 + 0x8415, KANJI_LEVEL4, // 萕 + 0xD85B, KANJI_LEVEL4, // ᅵ + 0xDC73, KANJI_LEVEL4, // ᅵ + 0x8417, KANJI_LEVEL4, // 萗 + 0x8439, KANJI_LEVEL4, // 萹 + 0x844A, KANJI_LEVEL4, // 葊 + 0x844F, KANJI_LEVEL4, // 葏 + 0x8451, KANJI_LEVEL4, // 葑 + 0x8452, KANJI_LEVEL4, // 葒 + 0x8459, KANJI_LEVEL4, // 葙 + 0x845A, KANJI_LEVEL4, // 葚 + 0x845C, KANJI_LEVEL4, // 葜 + 0xD85B, KANJI_LEVEL4, // ᅵ + 0xDCDD, KANJI_LEVEL4, // ᅵ + 0x8465, KANJI_LEVEL4, // 葥 + 0x8476, KANJI_LEVEL4, // 葶 + 0x8478, KANJI_LEVEL4, // 葞 + 0x847C, KANJI_LEVEL4, // 葌 + 0x8481, KANJI_LEVEL4, // 蒁 + 0x450D, KANJI_LEVEL4, // 䔍 + 0x84DC, KANJI_LEVEL4, // 蓜 + 0x8497, KANJI_LEVEL4, // 蒗 + 0x84A6, KANJI_LEVEL4, // è’Š + 0x84BE, KANJI_LEVEL4, // è’Ÿ + 0x4508, KANJI_LEVEL4, // 䔈 + 0x84CE, KANJI_LEVEL4, // 蓎 + 0x84CF, KANJI_LEVEL4, // 蓏 + 0x84D3, KANJI_LEVEL4, // 蓓 + 0xD85B, KANJI_LEVEL4, // ᅵ + 0xDE65, KANJI_LEVEL4, // ᅵ + 0x84E7, KANJI_LEVEL4, // 蓧 + 0x84EA, KANJI_LEVEL4, // 蓪 + 0x84EF, KANJI_LEVEL4, // 蓯 + 0x84F0, KANJI_LEVEL4, // 蓰 + 0x84F1, KANJI_LEVEL4, // 蓱 + 0x84FA, KANJI_LEVEL4, // 蓺 + 0x84FD, KANJI_LEVEL4, // 蓜 + 0x850C, KANJI_LEVEL4, // 蔌 + 0x851B, KANJI_LEVEL4, // 蔛 + 0x8524, KANJI_LEVEL4, // 蔀 + 0x8525, KANJI_LEVEL4, // 蔥 + 0x852B, KANJI_LEVEL4, // 蔫 + 0x8534, KANJI_LEVEL4, // 蔎 + 0x854F, KANJI_LEVEL4, // 蕏 + 0x856F, KANJI_LEVEL4, // 蕯 + 0x4525, KANJI_LEVEL4, // 䔥 + 0x4543, KANJI_LEVEL4, // 䕃 + 0x853E, KANJI_LEVEL4, // 蔟 + 0x8551, KANJI_LEVEL4, // 蕑 + 0x8553, KANJI_LEVEL4, // 蕓 + 0x855E, KANJI_LEVEL4, // 蕞 + 0x8561, KANJI_LEVEL4, // 蕡 + 0x8562, KANJI_LEVEL4, // 蕢 + 0xD85B, KANJI_LEVEL4, // ᅵ + 0xDF94, KANJI_LEVEL4, // ᅵ + 0x857B, KANJI_LEVEL4, // 蕻 + 0x857D, KANJI_LEVEL4, // 蕜 + 0x857F, KANJI_LEVEL4, // 蕿 + 0x8581, KANJI_LEVEL4, // 薁 + 0x8586, KANJI_LEVEL4, // 薆 + 0x8593, KANJI_LEVEL4, // 薓 + 0x859D, KANJI_LEVEL4, // 薝 + 0x859F, KANJI_LEVEL4, // 薟 + 0xD85B, KANJI_LEVEL4, // ᅵ + 0xDFF8, KANJI_LEVEL4, // ᅵ + 0xD85B, KANJI_LEVEL4, // ᅵ + 0xDFF6, KANJI_LEVEL4, // ᅵ + 0xD85B, KANJI_LEVEL4, // ᅵ + 0xDFF7, KANJI_LEVEL4, // ᅵ + 0x85B7, KANJI_LEVEL4, // 薷 + 0x85BC, KANJI_LEVEL4, // è–Œ + 0x85C7, KANJI_LEVEL4, // 藇 + 0x85CA, KANJI_LEVEL4, // 藊 + 0x85D8, KANJI_LEVEL4, // 藘 + 0x85D9, KANJI_LEVEL4, // 藙 + 0x85DF, KANJI_LEVEL4, // 藟 + 0x85E1, KANJI_LEVEL4, // 藡 + 0x85E6, KANJI_LEVEL4, // è—Š + 0x85F6, KANJI_LEVEL4, // 藶 + 0x8600, KANJI_LEVEL4, // 蘀 + 0x8611, KANJI_LEVEL4, // 蘑 + 0x861E, KANJI_LEVEL4, // 蘞 + 0x8621, KANJI_LEVEL4, // 蘡 + 0x8624, KANJI_LEVEL4, // 蘀 + 0x8627, KANJI_LEVEL4, // 蘧 + 0xD85C, KANJI_LEVEL4, // ᅵ + 0xDD0D, KANJI_LEVEL4, // ᅵ + 0x8639, KANJI_LEVEL4, // 蘹 + 0x863C, KANJI_LEVEL4, // 蘌 + 0xD85C, KANJI_LEVEL4, // ᅵ + 0xDD39, KANJI_LEVEL4, // ᅵ + 0x8640, KANJI_LEVEL4, // 虀 + 0xFA20, KANJI_LEVEL4, // ïš  + 0x8653, KANJI_LEVEL4, // 虓 + 0x8656, KANJI_LEVEL4, // 虖 + 0x866F, KANJI_LEVEL4, // 虯 + 0x8677, KANJI_LEVEL4, // 虷 + 0x867A, KANJI_LEVEL4, // 虺 + 0x8687, KANJI_LEVEL4, // 蚇 + 0x8689, KANJI_LEVEL4, // 蚉 + 0x868D, KANJI_LEVEL4, // 蚍 + 0x8691, KANJI_LEVEL4, // 蚑 + 0x869C, KANJI_LEVEL4, // 蚜 + 0x869D, KANJI_LEVEL4, // 蚝 + 0x86A8, KANJI_LEVEL4, // èšš + 0xFA21, KANJI_LEVEL4, // ïš¡ + 0x86B1, KANJI_LEVEL4, // 蚱 + 0x86B3, KANJI_LEVEL4, // 蚳 + 0x86C1, KANJI_LEVEL4, // 蛁 + 0x86C3, KANJI_LEVEL4, // 蛃 + 0x86D1, KANJI_LEVEL4, // 蛑 + 0x86D5, KANJI_LEVEL4, // 蛕 + 0x86D7, KANJI_LEVEL4, // 蛗 + 0x86E3, KANJI_LEVEL4, // 蛣 + 0x86E6, KANJI_LEVEL4, // 蛊 + 0x45B8, KANJI_LEVEL4, // 䖾 + 0x8705, KANJI_LEVEL4, // 蜅 + 0x8707, KANJI_LEVEL4, // 蜇 + 0x870E, KANJI_LEVEL4, // 蜎 + 0x8710, KANJI_LEVEL4, // 蜐 + 0x8713, KANJI_LEVEL4, // 蜓 + 0x8719, KANJI_LEVEL4, // 蜙 + 0x871F, KANJI_LEVEL4, // 蜟 + 0x8721, KANJI_LEVEL4, // 蜡 + 0x8723, KANJI_LEVEL4, // 蜣 + 0x8731, KANJI_LEVEL4, // 蜱 + 0x873A, KANJI_LEVEL4, // 蜺 + 0x873E, KANJI_LEVEL4, // 蜟 + 0x8740, KANJI_LEVEL4, // 蝀 + 0x8743, KANJI_LEVEL4, // 蝃 + 0x8751, KANJI_LEVEL4, // 蝑 + 0x8758, KANJI_LEVEL4, // 蝘 + 0x8764, KANJI_LEVEL4, // 蝀 + 0x8765, KANJI_LEVEL4, // 蝥 + 0x8772, KANJI_LEVEL4, // 蝲 + 0x877C, KANJI_LEVEL4, // 蝌 + 0xD85C, KANJI_LEVEL4, // ᅵ + 0xDFDB, KANJI_LEVEL4, // ᅵ + 0xD85C, KANJI_LEVEL4, // ᅵ + 0xDFDA, KANJI_LEVEL4, // ᅵ + 0x87A7, KANJI_LEVEL4, // 螧 + 0x8789, KANJI_LEVEL4, // 螉 + 0x878B, KANJI_LEVEL4, // 螋 + 0x8793, KANJI_LEVEL4, // 螓 + 0x87A0, KANJI_LEVEL4, // 螠 + 0xD85C, KANJI_LEVEL4, // ᅵ + 0xDFFE, KANJI_LEVEL4, // ᅵ + 0x45E5, KANJI_LEVEL4, // 䗥 + 0x87BE, KANJI_LEVEL4, // 螟 + 0xD85D, KANJI_LEVEL4, // ᅵ + 0xDC10, KANJI_LEVEL4, // ᅵ + 0x87C1, KANJI_LEVEL4, // 蟁 + 0x87CE, KANJI_LEVEL4, // 蟎 + 0x87F5, KANJI_LEVEL4, // 蟵 + 0x87DF, KANJI_LEVEL4, // 蟟 + 0xD85D, KANJI_LEVEL4, // ᅵ + 0xDC49, KANJI_LEVEL4, // ᅵ + 0x87E3, KANJI_LEVEL4, // 蟣 + 0x87E5, KANJI_LEVEL4, // 蟥 + 0x87E6, KANJI_LEVEL4, // 蟊 + 0x87EA, KANJI_LEVEL4, // 蟪 + 0x87EB, KANJI_LEVEL4, // 蟫 + 0x87ED, KANJI_LEVEL4, // 蟭 + 0x8801, KANJI_LEVEL4, // 蠁 + 0x8803, KANJI_LEVEL4, // 蠃 + 0x880B, KANJI_LEVEL4, // 蠋 + 0x8813, KANJI_LEVEL4, // 蠓 + 0x8828, KANJI_LEVEL4, // è š + 0x882E, KANJI_LEVEL4, // è ® + 0x8832, KANJI_LEVEL4, // è ² + 0x883C, KANJI_LEVEL4, // è Œ + 0x460F, KANJI_LEVEL4, // 䘏 + 0x884A, KANJI_LEVEL4, // 衊 + 0x8858, KANJI_LEVEL4, // 衘 + 0x885F, KANJI_LEVEL4, // 衟 + 0x8864, KANJI_LEVEL4, // è¡€ + 0xD85D, KANJI_LEVEL4, // ᅵ + 0xDE15, KANJI_LEVEL4, // ᅵ + 0xD85D, KANJI_LEVEL4, // ᅵ + 0xDE14, KANJI_LEVEL4, // ᅵ + 0x8869, KANJI_LEVEL4, // è¡© + 0xD85D, KANJI_LEVEL4, // ᅵ + 0xDE31, KANJI_LEVEL4, // ᅵ + 0x886F, KANJI_LEVEL4, // 衯 + 0x88A0, KANJI_LEVEL4, // 袠 + 0x88BC, KANJI_LEVEL4, // 袌 + 0x88BD, KANJI_LEVEL4, // 袜 + 0x88BE, KANJI_LEVEL4, // 袟 + 0x88C0, KANJI_LEVEL4, // 裀 + 0x88D2, KANJI_LEVEL4, // 裒 + 0xD85D, KANJI_LEVEL4, // ᅵ + 0xDE93, KANJI_LEVEL4, // ᅵ + 0x88D1, KANJI_LEVEL4, // 裑 + 0x88D3, KANJI_LEVEL4, // 裓 + 0x88DB, KANJI_LEVEL4, // 裛 + 0x88F0, KANJI_LEVEL4, // 裰 + 0x88F1, KANJI_LEVEL4, // 裱 + 0x4641, KANJI_LEVEL4, // 䙁 + 0x8901, KANJI_LEVEL4, // 老 + 0xD85D, KANJI_LEVEL4, // ᅵ + 0xDF0E, KANJI_LEVEL4, // ᅵ + 0x8937, KANJI_LEVEL4, // 耷 + 0xD85D, KANJI_LEVEL4, // ᅵ + 0xDF23, KANJI_LEVEL4, // ᅵ + 0x8942, KANJI_LEVEL4, // 襂 + 0x8945, KANJI_LEVEL4, // 襅 + 0x8949, KANJI_LEVEL4, // 襉 + 0xD85D, KANJI_LEVEL4, // ᅵ + 0xDF52, KANJI_LEVEL4, // ᅵ + 0x4665, KANJI_LEVEL4, // 䙥 + 0x8962, KANJI_LEVEL4, // 襢 + 0x8980, KANJI_LEVEL4, // 芀 + 0x8989, KANJI_LEVEL4, // 芉 + 0x8990, KANJI_LEVEL4, // 芐 + 0x899F, KANJI_LEVEL4, // 芟 + 0x89B0, KANJI_LEVEL4, // 芰 + 0x89B7, KANJI_LEVEL4, // 芷 + 0x89D6, KANJI_LEVEL4, // 觖 + 0x89D8, KANJI_LEVEL4, // 觘 + 0x89EB, KANJI_LEVEL4, // è§« + 0x46A1, KANJI_LEVEL4, // 䚡 + 0x89F1, KANJI_LEVEL4, // è§± + 0x89F3, KANJI_LEVEL4, // è§³ + 0x89FD, KANJI_LEVEL4, // è§œ + 0x89FF, KANJI_LEVEL4, // è§¿ + 0x46AF, KANJI_LEVEL4, // 䚯 + 0x8A11, KANJI_LEVEL4, // èš‘ + 0x8A14, KANJI_LEVEL4, // èš” + 0xD85E, KANJI_LEVEL4, // ᅵ + 0xDD85, KANJI_LEVEL4, // ᅵ + 0x8A21, KANJI_LEVEL4, // èš¡ + 0x8A35, KANJI_LEVEL4, // èšµ + 0x8A3E, KANJI_LEVEL4, // 蚟 + 0x8A45, KANJI_LEVEL4, // 詅 + 0x8A4D, KANJI_LEVEL4, // 詍 + 0x8A58, KANJI_LEVEL4, // 詘 + 0x8AAE, KANJI_LEVEL4, // 誮 + 0x8A90, KANJI_LEVEL4, // 誐 + 0x8AB7, KANJI_LEVEL4, // 誷 + 0x8ABE, KANJI_LEVEL4, // 誟 + 0x8AD7, KANJI_LEVEL4, // 諗 + 0x8AFC, KANJI_LEVEL4, // 諌 + 0xD85E, KANJI_LEVEL4, // ᅵ + 0xDE84, KANJI_LEVEL4, // ᅵ + 0x8B0A, KANJI_LEVEL4, // 謊 + 0x8B05, KANJI_LEVEL4, // 謅 + 0x8B0D, KANJI_LEVEL4, // 謍 + 0x8B1C, KANJI_LEVEL4, // 謜 + 0x8B1F, KANJI_LEVEL4, // 謟 + 0x8B2D, KANJI_LEVEL4, // 謭 + 0x8B43, KANJI_LEVEL4, // 譃 + 0x470C, KANJI_LEVEL4, // 䜌 + 0x8B51, KANJI_LEVEL4, // 譑 + 0x8B5E, KANJI_LEVEL4, // 譞 + 0x8B76, KANJI_LEVEL4, // è­¶ + 0x8B7F, KANJI_LEVEL4, // è­¿ + 0x8B81, KANJI_LEVEL4, // 讁 + 0x8B8B, KANJI_LEVEL4, // 讋 + 0x8B94, KANJI_LEVEL4, // 讔 + 0x8B95, KANJI_LEVEL4, // 讕 + 0x8B9C, KANJI_LEVEL4, // 讜 + 0x8B9E, KANJI_LEVEL4, // 讞 + 0x8C39, KANJI_LEVEL4, // è°¹ + 0xD85E, KANJI_LEVEL4, // ᅵ + 0xDFB3, KANJI_LEVEL4, // ᅵ + 0x8C3D, KANJI_LEVEL4, // è°œ + 0xD85E, KANJI_LEVEL4, // ᅵ + 0xDFBE, KANJI_LEVEL4, // ᅵ + 0xD85E, KANJI_LEVEL4, // ᅵ + 0xDFC7, KANJI_LEVEL4, // ᅵ + 0x8C45, KANJI_LEVEL4, // 豅 + 0x8C47, KANJI_LEVEL4, // 豇 + 0x8C4F, KANJI_LEVEL4, // 豏 + 0x8C54, KANJI_LEVEL4, // 豔 + 0x8C57, KANJI_LEVEL4, // 豗 + 0x8C69, KANJI_LEVEL4, // 豩 + 0x8C6D, KANJI_LEVEL4, // è±­ + 0x8C73, KANJI_LEVEL4, // è±³ + 0xD85F, KANJI_LEVEL4, // ᅵ + 0xDCB8, KANJI_LEVEL4, // ᅵ + 0x8C93, KANJI_LEVEL4, // 貓 + 0x8C92, KANJI_LEVEL4, // 貒 + 0x8C99, KANJI_LEVEL4, // 貙 + 0x4764, KANJI_LEVEL4, // 䝀 + 0x8C9B, KANJI_LEVEL4, // 貛 + 0x8CA4, KANJI_LEVEL4, // è²€ + 0x8CD6, KANJI_LEVEL4, // 賖 + 0x8CD5, KANJI_LEVEL4, // 賕 + 0x8CD9, KANJI_LEVEL4, // 賙 + 0xD85F, KANJI_LEVEL4, // ᅵ + 0xDDA0, KANJI_LEVEL4, // ᅵ + 0x8CF0, KANJI_LEVEL4, // è³° + 0x8CF1, KANJI_LEVEL4, // è³± + 0xD85F, KANJI_LEVEL4, // ᅵ + 0xDE10, KANJI_LEVEL4, // ᅵ + 0x8D09, KANJI_LEVEL4, // 莉 + 0x8D0E, KANJI_LEVEL4, // 莎 + 0x8D6C, KANJI_LEVEL4, // 赬 + 0x8D84, KANJI_LEVEL4, // 趄 + 0x8D95, KANJI_LEVEL4, // 趕 + 0x8DA6, KANJI_LEVEL4, // è¶Š + 0xD85F, KANJI_LEVEL4, // ᅵ + 0xDFB7, KANJI_LEVEL4, // ᅵ + 0x8DC6, KANJI_LEVEL4, // 跆 + 0x8DC8, KANJI_LEVEL4, // 跈 + 0x8DD9, KANJI_LEVEL4, // 跙 + 0x8DEC, KANJI_LEVEL4, // è·¬ + 0x8E0C, KANJI_LEVEL4, // 螌 + 0x47FD, KANJI_LEVEL4, // 䟜 + 0x8DFD, KANJI_LEVEL4, // è·œ + 0x8E06, KANJI_LEVEL4, // 螆 + 0xD860, KANJI_LEVEL4, // ᅵ + 0xDC8A, KANJI_LEVEL4, // ᅵ + 0x8E14, KANJI_LEVEL4, // èž” + 0x8E16, KANJI_LEVEL4, // èž– + 0x8E21, KANJI_LEVEL4, // èž¡ + 0x8E22, KANJI_LEVEL4, // 螢 + 0x8E27, KANJI_LEVEL4, // èž§ + 0xD860, KANJI_LEVEL4, // ᅵ + 0xDCBB, KANJI_LEVEL4, // ᅵ + 0x4816, KANJI_LEVEL4, // 䠖 + 0x8E36, KANJI_LEVEL4, // èž¶ + 0x8E39, KANJI_LEVEL4, // èž¹ + 0x8E4B, KANJI_LEVEL4, // 蹋 + 0x8E54, KANJI_LEVEL4, // 蹔 + 0x8E62, KANJI_LEVEL4, // è¹¢ + 0x8E6C, KANJI_LEVEL4, // 蹬 + 0x8E6D, KANJI_LEVEL4, // è¹­ + 0x8E6F, KANJI_LEVEL4, // 蹯 + 0x8E98, KANJI_LEVEL4, // 躘 + 0x8E9E, KANJI_LEVEL4, // 躞 + 0x8EAE, KANJI_LEVEL4, // 躮 + 0x8EB3, KANJI_LEVEL4, // 躳 + 0x8EB5, KANJI_LEVEL4, // 躵 + 0x8EB6, KANJI_LEVEL4, // 躶 + 0x8EBB, KANJI_LEVEL4, // 躻 + 0xD860, KANJI_LEVEL4, // ᅵ + 0xDE82, KANJI_LEVEL4, // ᅵ + 0x8ED1, KANJI_LEVEL4, // 軑 + 0x8ED4, KANJI_LEVEL4, // 軔 + 0x484E, KANJI_LEVEL4, // 䡎 + 0x8EF9, KANJI_LEVEL4, // 軹 + 0xD860, KANJI_LEVEL4, // ᅵ + 0xDEF3, KANJI_LEVEL4, // ᅵ + 0x8F00, KANJI_LEVEL4, // 茀 + 0x8F08, KANJI_LEVEL4, // 茈 + 0x8F17, KANJI_LEVEL4, // 茗 + 0x8F2B, KANJI_LEVEL4, // 茫 + 0x8F40, KANJI_LEVEL4, // 蜀 + 0x8F4A, KANJI_LEVEL4, // 蜊 + 0x8F58, KANJI_LEVEL4, // 蜘 + 0xD861, KANJI_LEVEL4, // ᅵ + 0xDC0C, KANJI_LEVEL4, // ᅵ + 0x8FA4, KANJI_LEVEL4, // 蟀 + 0x8FB4, KANJI_LEVEL4, // 蟎 + 0xFA66, KANJI_LEVEL4, // 琢 + 0x8FB6, KANJI_LEVEL4, // 蟶 + 0xD861, KANJI_LEVEL4, // ᅵ + 0xDC55, KANJI_LEVEL4, // ᅵ + 0x8FC1, KANJI_LEVEL4, // 迁 + 0x8FC6, KANJI_LEVEL4, // 迆 + 0xFA24, KANJI_LEVEL4, //  + 0x8FCA, KANJI_LEVEL4, // 迊 + 0x8FCD, KANJI_LEVEL4, // 迍 + 0x8FD3, KANJI_LEVEL4, // 迓 + 0x8FD5, KANJI_LEVEL4, // 迕 + 0x8FE0, KANJI_LEVEL4, // è¿  + 0x8FF1, KANJI_LEVEL4, // 迱 + 0x8FF5, KANJI_LEVEL4, // 迵 + 0x8FFB, KANJI_LEVEL4, // è¿» + 0x9002, KANJI_LEVEL4, // 适 + 0x900C, KANJI_LEVEL4, // 逌 + 0x9037, KANJI_LEVEL4, // 逷 + 0xD861, KANJI_LEVEL4, // ᅵ + 0xDD6B, KANJI_LEVEL4, // ᅵ + 0x9043, KANJI_LEVEL4, // 遃 + 0x9044, KANJI_LEVEL4, // 遄 + 0x905D, KANJI_LEVEL4, // 遝 + 0xD861, KANJI_LEVEL4, // ᅵ + 0xDDC8, KANJI_LEVEL4, // ᅵ + 0xD861, KANJI_LEVEL4, // ᅵ + 0xDDC9, KANJI_LEVEL4, // ᅵ + 0x9085, KANJI_LEVEL4, // 邅 + 0x908C, KANJI_LEVEL4, // 邌 + 0x9090, KANJI_LEVEL4, // 邐 + 0x961D, KANJI_LEVEL4, // 阝 + 0x90A1, KANJI_LEVEL4, // 邡 + 0x48B5, KANJI_LEVEL4, // 䢵 + 0x90B0, KANJI_LEVEL4, // 邰 + 0x90B6, KANJI_LEVEL4, // 邶 + 0x90C3, KANJI_LEVEL4, // 郃 + 0x90C8, KANJI_LEVEL4, // 郈 + 0xD861, KANJI_LEVEL4, // ᅵ + 0xDED7, KANJI_LEVEL4, // ᅵ + 0x90DC, KANJI_LEVEL4, // 郜 + 0x90DF, KANJI_LEVEL4, // 郟 + 0xD861, KANJI_LEVEL4, // ᅵ + 0xDEFA, KANJI_LEVEL4, // ᅵ + 0x90F6, KANJI_LEVEL4, // 郶 + 0x90F2, KANJI_LEVEL4, // 郲 + 0x9100, KANJI_LEVEL4, // 鄀 + 0x90EB, KANJI_LEVEL4, // 郫 + 0x90FE, KANJI_LEVEL4, // 郟 + 0x90FF, KANJI_LEVEL4, // 郿 + 0x9104, KANJI_LEVEL4, // 鄄 + 0x9106, KANJI_LEVEL4, // 鄆 + 0x9118, KANJI_LEVEL4, // 鄘 + 0x911C, KANJI_LEVEL4, // 鄜 + 0x911E, KANJI_LEVEL4, // 鄞 + 0x9137, KANJI_LEVEL4, // 鄷 + 0x9139, KANJI_LEVEL4, // 鄹 + 0x913A, KANJI_LEVEL4, // 鄺 + 0x9146, KANJI_LEVEL4, // 酆 + 0x9147, KANJI_LEVEL4, // 酇 + 0x9157, KANJI_LEVEL4, // 酗 + 0x9159, KANJI_LEVEL4, // 酙 + 0x9161, KANJI_LEVEL4, // 酡 + 0x9164, KANJI_LEVEL4, // é…€ + 0x9174, KANJI_LEVEL4, // 酮 + 0x9179, KANJI_LEVEL4, // 酹 + 0x9185, KANJI_LEVEL4, // 醅 + 0x918E, KANJI_LEVEL4, // 醎 + 0x91A8, KANJI_LEVEL4, // 醹 + 0x91AE, KANJI_LEVEL4, // 醮 + 0x91B3, KANJI_LEVEL4, // 醳 + 0x91B6, KANJI_LEVEL4, // 醶 + 0x91C3, KANJI_LEVEL4, // 釃 + 0x91C4, KANJI_LEVEL4, // 釄 + 0x91DA, KANJI_LEVEL4, // 釚 + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDD49, KANJI_LEVEL4, // ᅵ + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDD46, KANJI_LEVEL4, // ᅵ + 0x91EC, KANJI_LEVEL4, // 釬 + 0x91EE, KANJI_LEVEL4, // 釮 + 0x9201, KANJI_LEVEL4, // 鈁 + 0x920A, KANJI_LEVEL4, // 鈊 + 0x9216, KANJI_LEVEL4, // 鈖 + 0x9217, KANJI_LEVEL4, // 鈗 + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDD6B, KANJI_LEVEL4, // ᅵ + 0x9233, KANJI_LEVEL4, // 鈳 + 0x9242, KANJI_LEVEL4, // 鉂 + 0x9247, KANJI_LEVEL4, // 鉇 + 0x924A, KANJI_LEVEL4, // 鉊 + 0x924E, KANJI_LEVEL4, // 鉎 + 0x9251, KANJI_LEVEL4, // 鉑 + 0x9256, KANJI_LEVEL4, // 鉖 + 0x9259, KANJI_LEVEL4, // 鉙 + 0x9260, KANJI_LEVEL4, // 鉠 + 0x9261, KANJI_LEVEL4, // 鉡 + 0x9265, KANJI_LEVEL4, // 鉥 + 0x9267, KANJI_LEVEL4, // 鉧 + 0x9268, KANJI_LEVEL4, // 鉹 + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDD87, KANJI_LEVEL4, // ᅵ + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDD88, KANJI_LEVEL4, // ᅵ + 0x927C, KANJI_LEVEL4, // 鉌 + 0x927D, KANJI_LEVEL4, // 鉜 + 0x927F, KANJI_LEVEL4, // 鉿 + 0x9289, KANJI_LEVEL4, // 銉 + 0x928D, KANJI_LEVEL4, // 銍 + 0x9297, KANJI_LEVEL4, // 銗 + 0x9299, KANJI_LEVEL4, // 銙 + 0x929F, KANJI_LEVEL4, // 銟 + 0x92A7, KANJI_LEVEL4, // 銧 + 0x92AB, KANJI_LEVEL4, // 銫 + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDDBA, KANJI_LEVEL4, // ᅵ + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDDBB, KANJI_LEVEL4, // ᅵ + 0x92B2, KANJI_LEVEL4, // 銲 + 0x92BF, KANJI_LEVEL4, // 銿 + 0x92C0, KANJI_LEVEL4, // 鋀 + 0x92C6, KANJI_LEVEL4, // 鋆 + 0x92CE, KANJI_LEVEL4, // 鋎 + 0x92D0, KANJI_LEVEL4, // 鋐 + 0x92D7, KANJI_LEVEL4, // 鋗 + 0x92D9, KANJI_LEVEL4, // 鋙 + 0x92E5, KANJI_LEVEL4, // 鋥 + 0x92E7, KANJI_LEVEL4, // 鋧 + 0x9311, KANJI_LEVEL4, // 錑 + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDE1E, KANJI_LEVEL4, // ᅵ + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDE29, KANJI_LEVEL4, // ᅵ + 0x92F7, KANJI_LEVEL4, // 鋷 + 0x92F9, KANJI_LEVEL4, // 鋹 + 0x92FB, KANJI_LEVEL4, // 鋻 + 0x9302, KANJI_LEVEL4, // 錂 + 0x930D, KANJI_LEVEL4, // 錍 + 0x9315, KANJI_LEVEL4, // 錕 + 0x931D, KANJI_LEVEL4, // 錝 + 0x931E, KANJI_LEVEL4, // 錞 + 0x9327, KANJI_LEVEL4, // 錧 + 0x9329, KANJI_LEVEL4, // 錩 + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDE71, KANJI_LEVEL4, // ᅵ + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDE43, KANJI_LEVEL4, // ᅵ + 0x9347, KANJI_LEVEL4, // 鍇 + 0x9351, KANJI_LEVEL4, // 鍑 + 0x9357, KANJI_LEVEL4, // 鍗 + 0x935A, KANJI_LEVEL4, // 鍚 + 0x936B, KANJI_LEVEL4, // 鍫 + 0x9371, KANJI_LEVEL4, // 鍱 + 0x9373, KANJI_LEVEL4, // 鍳 + 0x93A1, KANJI_LEVEL4, // 鎡 + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDE99, KANJI_LEVEL4, // ᅵ + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDECD, KANJI_LEVEL4, // ᅵ + 0x9388, KANJI_LEVEL4, // 鎈 + 0x938B, KANJI_LEVEL4, // 鎋 + 0x938F, KANJI_LEVEL4, // 鎏 + 0x939E, KANJI_LEVEL4, // 鎞 + 0x93F5, KANJI_LEVEL4, // 鏵 + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDEE4, KANJI_LEVEL4, // ᅵ + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDEDD, KANJI_LEVEL4, // ᅵ + 0x93F1, KANJI_LEVEL4, // 鏱 + 0x93C1, KANJI_LEVEL4, // 鏁 + 0x93C7, KANJI_LEVEL4, // 鏇 + 0x93DC, KANJI_LEVEL4, // 鏜 + 0x93E2, KANJI_LEVEL4, // 鏢 + 0x93E7, KANJI_LEVEL4, // 鏧 + 0x9409, KANJI_LEVEL4, // 鐉 + 0x940F, KANJI_LEVEL4, // 鐏 + 0x9416, KANJI_LEVEL4, // 鐖 + 0x9417, KANJI_LEVEL4, // 鐗 + 0x93FB, KANJI_LEVEL4, // 鏻 + 0x9432, KANJI_LEVEL4, // 鐲 + 0x9434, KANJI_LEVEL4, // 鐎 + 0x943B, KANJI_LEVEL4, // 鐻 + 0x9445, KANJI_LEVEL4, // 鑅 + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDFC1, KANJI_LEVEL4, // ᅵ + 0xD862, KANJI_LEVEL4, // ᅵ + 0xDFEF, KANJI_LEVEL4, // ᅵ + 0x946D, KANJI_LEVEL4, // 鑭 + 0x946F, KANJI_LEVEL4, // 鑯 + 0x9578, KANJI_LEVEL4, // 镾 + 0x9579, KANJI_LEVEL4, // 镹 + 0x9586, KANJI_LEVEL4, // 閆 + 0x958C, KANJI_LEVEL4, // 閌 + 0x958D, KANJI_LEVEL4, // 閍 + 0xD863, KANJI_LEVEL4, // ᅵ + 0xDD10, KANJI_LEVEL4, // ᅵ + 0x95AB, KANJI_LEVEL4, // 閫 + 0x95B4, KANJI_LEVEL4, // 閮 + 0xD863, KANJI_LEVEL4, // ᅵ + 0xDD71, KANJI_LEVEL4, // ᅵ + 0x95C8, KANJI_LEVEL4, // 闈 + 0xD863, KANJI_LEVEL4, // ᅵ + 0xDDFB, KANJI_LEVEL4, // ᅵ + 0xD863, KANJI_LEVEL4, // ᅵ + 0xDE1F, KANJI_LEVEL4, // ᅵ + 0x962C, KANJI_LEVEL4, // 阬 + 0x9633, KANJI_LEVEL4, // 阳 + 0x9634, KANJI_LEVEL4, // 阎 + 0xD863, KANJI_LEVEL4, // ᅵ + 0xDE36, KANJI_LEVEL4, // ᅵ + 0x963C, KANJI_LEVEL4, // 阌 + 0x9641, KANJI_LEVEL4, // 陁 + 0x9661, KANJI_LEVEL4, // 陡 + 0xD863, KANJI_LEVEL4, // ᅵ + 0xDE89, KANJI_LEVEL4, // ᅵ + 0x9682, KANJI_LEVEL4, // 隂 + 0xD863, KANJI_LEVEL4, // ᅵ + 0xDEEB, KANJI_LEVEL4, // ᅵ + 0x969A, KANJI_LEVEL4, // 隚 + 0xD863, KANJI_LEVEL4, // ᅵ + 0xDF32, KANJI_LEVEL4, // ᅵ + 0x49E7, KANJI_LEVEL4, // ä§§ + 0x96A9, KANJI_LEVEL4, // 隩 + 0x96AF, KANJI_LEVEL4, // 隯 + 0x96B3, KANJI_LEVEL4, // 隳 + 0x96BA, KANJI_LEVEL4, // 隺 + 0x96BD, KANJI_LEVEL4, // éšœ + 0x49FA, KANJI_LEVEL4, // 䧺 + 0xD863, KANJI_LEVEL4, // ᅵ + 0xDFF8, KANJI_LEVEL4, // ᅵ + 0x96D8, KANJI_LEVEL4, // 雘 + 0x96DA, KANJI_LEVEL4, // 雚 + 0x96DD, KANJI_LEVEL4, // 雝 + 0x4A04, KANJI_LEVEL4, // 乄 + 0x9714, KANJI_LEVEL4, // 霔 + 0x9723, KANJI_LEVEL4, // 霣 + 0x4A29, KANJI_LEVEL4, // äš© + 0x9736, KANJI_LEVEL4, // 霶 + 0x9741, KANJI_LEVEL4, // 靁 + 0x9747, KANJI_LEVEL4, // 靇 + 0x9755, KANJI_LEVEL4, // 靕 + 0x9757, KANJI_LEVEL4, // 靗 + 0x975B, KANJI_LEVEL4, // 靛 + 0x976A, KANJI_LEVEL4, // 靪 + 0xD864, KANJI_LEVEL4, // ᅵ + 0xDEA0, KANJI_LEVEL4, // ᅵ + 0xD864, KANJI_LEVEL4, // ᅵ + 0xDEB1, KANJI_LEVEL4, // ᅵ + 0x9796, KANJI_LEVEL4, // 鞖 + 0x979A, KANJI_LEVEL4, // 鞚 + 0x979E, KANJI_LEVEL4, // 鞞 + 0x97A2, KANJI_LEVEL4, // 鞢 + 0x97B1, KANJI_LEVEL4, // 鞱 + 0x97B2, KANJI_LEVEL4, // 鞲 + 0x97BE, KANJI_LEVEL4, // 鞟 + 0x97CC, KANJI_LEVEL4, // 韌 + 0x97D1, KANJI_LEVEL4, // 韑 + 0x97D4, KANJI_LEVEL4, // 韔 + 0x97D8, KANJI_LEVEL4, // 韘 + 0x97D9, KANJI_LEVEL4, // 韙 + 0x97E1, KANJI_LEVEL4, // 韡 + 0x97F1, KANJI_LEVEL4, // 韱 + 0x9804, KANJI_LEVEL4, // 頄 + 0x980D, KANJI_LEVEL4, // 頍 + 0x980E, KANJI_LEVEL4, // 頎 + 0x9814, KANJI_LEVEL4, // 頔 + 0x9816, KANJI_LEVEL4, // 頖 + 0x4ABC, KANJI_LEVEL4, // 䪌 + 0xD865, KANJI_LEVEL4, // ᅵ + 0xDC90, KANJI_LEVEL4, // ᅵ + 0x9823, KANJI_LEVEL4, // é £ + 0x9832, KANJI_LEVEL4, // é ² + 0x9833, KANJI_LEVEL4, // é ³ + 0x9825, KANJI_LEVEL4, // é ¥ + 0x9847, KANJI_LEVEL4, // 顇 + 0x9866, KANJI_LEVEL4, // 顊 + 0x98AB, KANJI_LEVEL4, // 颫 + 0x98AD, KANJI_LEVEL4, // 颭 + 0x98B0, KANJI_LEVEL4, // 颰 + 0xD865, KANJI_LEVEL4, // ᅵ + 0xDDCF, KANJI_LEVEL4, // ᅵ + 0x98B7, KANJI_LEVEL4, // 颷 + 0x98B8, KANJI_LEVEL4, // 颞 + 0x98BB, KANJI_LEVEL4, // 颻 + 0x98BC, KANJI_LEVEL4, // 颌 + 0x98BF, KANJI_LEVEL4, // 颿 + 0x98C2, KANJI_LEVEL4, // 飂 + 0x98C7, KANJI_LEVEL4, // 飇 + 0x98CB, KANJI_LEVEL4, // 飋 + 0x98E0, KANJI_LEVEL4, // 飠 + 0xD865, KANJI_LEVEL4, // ᅵ + 0xDE7F, KANJI_LEVEL4, // ᅵ + 0x98E1, KANJI_LEVEL4, // 飡 + 0x98E3, KANJI_LEVEL4, // 飣 + 0x98E5, KANJI_LEVEL4, // 飥 + 0x98EA, KANJI_LEVEL4, // 飪 + 0x98F0, KANJI_LEVEL4, // 飰 + 0x98F1, KANJI_LEVEL4, // 飱 + 0x98F3, KANJI_LEVEL4, // 飳 + 0x9908, KANJI_LEVEL4, // 逈 + 0x4B3B, KANJI_LEVEL4, // 䬻 + 0xD865, KANJI_LEVEL4, // ᅵ + 0xDEF0, KANJI_LEVEL4, // ᅵ + 0x9916, KANJI_LEVEL4, // 逖 + 0x9917, KANJI_LEVEL4, // 逗 + 0xD865, KANJI_LEVEL4, // ᅵ + 0xDF19, KANJI_LEVEL4, // ᅵ + 0x991A, KANJI_LEVEL4, // 通 + 0x991B, KANJI_LEVEL4, // 逛 + 0x991C, KANJI_LEVEL4, // 逜 + 0xD865, KANJI_LEVEL4, // ᅵ + 0xDF50, KANJI_LEVEL4, // ᅵ + 0x9931, KANJI_LEVEL4, // 週 + 0x9932, KANJI_LEVEL4, // 進 + 0x9933, KANJI_LEVEL4, // 逳 + 0x993A, KANJI_LEVEL4, // 逺 + 0x993B, KANJI_LEVEL4, // 逻 + 0x993C, KANJI_LEVEL4, // 逌 + 0x9940, KANJI_LEVEL4, // 饀 + 0x9941, KANJI_LEVEL4, // 饁 + 0x9946, KANJI_LEVEL4, // 饆 + 0x994D, KANJI_LEVEL4, // 饍 + 0x994E, KANJI_LEVEL4, // 饎 + 0x995C, KANJI_LEVEL4, // 饜 + 0x995F, KANJI_LEVEL4, // 饟 + 0x9960, KANJI_LEVEL4, // 饠 + 0x99A3, KANJI_LEVEL4, // 銣 + 0x99A6, KANJI_LEVEL4, // 銊 + 0x99B9, KANJI_LEVEL4, // 銹 + 0x99BD, KANJI_LEVEL4, // 銜 + 0x99BF, KANJI_LEVEL4, // 銿 + 0x99C3, KANJI_LEVEL4, // 駃 + 0x99C9, KANJI_LEVEL4, // 駉 + 0x99D4, KANJI_LEVEL4, // 駔 + 0x99D9, KANJI_LEVEL4, // 駙 + 0x99DE, KANJI_LEVEL4, // 駞 + 0xD866, KANJI_LEVEL4, // ᅵ + 0xDCC6, KANJI_LEVEL4, // ᅵ + 0x99F0, KANJI_LEVEL4, // é§° + 0x99F9, KANJI_LEVEL4, // é§¹ + 0x99FC, KANJI_LEVEL4, // é§Œ + 0x9A0A, KANJI_LEVEL4, // 鹊 + 0x9A11, KANJI_LEVEL4, // 鹑 + 0x9A16, KANJI_LEVEL4, // 鹖 + 0x9A1A, KANJI_LEVEL4, // 鹚 + 0x9A20, KANJI_LEVEL4, // éš  + 0x9A31, KANJI_LEVEL4, // éš± + 0x9A36, KANJI_LEVEL4, // éš¶ + 0x9A44, KANJI_LEVEL4, // 驄 + 0x9A4C, KANJI_LEVEL4, // 驌 + 0x9A58, KANJI_LEVEL4, // 驘 + 0x4BC2, KANJI_LEVEL4, // 䯂 + 0x9AAF, KANJI_LEVEL4, // 骯 + 0x4BCA, KANJI_LEVEL4, // 䯊 + 0x9AB7, KANJI_LEVEL4, // 骷 + 0x4BD2, KANJI_LEVEL4, // 䯒 + 0x9AB9, KANJI_LEVEL4, // 骹 + 0xD866, KANJI_LEVEL4, // ᅵ + 0xDE72, KANJI_LEVEL4, // ᅵ + 0x9AC6, KANJI_LEVEL4, // 髆 + 0x9AD0, KANJI_LEVEL4, // 髐 + 0x9AD2, KANJI_LEVEL4, // 髒 + 0x9AD5, KANJI_LEVEL4, // 髕 + 0x4BE8, KANJI_LEVEL4, // 䯚 + 0x9ADC, KANJI_LEVEL4, // 髜 + 0x9AE0, KANJI_LEVEL4, // é«  + 0x9AE5, KANJI_LEVEL4, // é«¥ + 0x9AE9, KANJI_LEVEL4, // é«© + 0x9B03, KANJI_LEVEL4, // 鬃 + 0x9B0C, KANJI_LEVEL4, // 鬌 + 0x9B10, KANJI_LEVEL4, // 鬐 + 0x9B12, KANJI_LEVEL4, // 鬒 + 0x9B16, KANJI_LEVEL4, // 鬖 + 0x9B1C, KANJI_LEVEL4, // 鬜 + 0x9B2B, KANJI_LEVEL4, // 鬫 + 0x9B33, KANJI_LEVEL4, // 鬳 + 0x9B3D, KANJI_LEVEL4, // 鬜 + 0x4C20, KANJI_LEVEL4, // ä°  + 0x9B4B, KANJI_LEVEL4, // 魋 + 0x9B63, KANJI_LEVEL4, // é­£ + 0x9B65, KANJI_LEVEL4, // é­¥ + 0x9B6B, KANJI_LEVEL4, // é­« + 0x9B6C, KANJI_LEVEL4, // é­¬ + 0x9B73, KANJI_LEVEL4, // é­³ + 0x9B76, KANJI_LEVEL4, // é­¶ + 0x9B77, KANJI_LEVEL4, // é­· + 0x9BA6, KANJI_LEVEL4, // 鮊 + 0x9BAC, KANJI_LEVEL4, // 鮬 + 0x9BB1, KANJI_LEVEL4, // é®± + 0xD867, KANJI_LEVEL4, // ᅵ + 0xDDDB, KANJI_LEVEL4, // ᅵ + 0xD867, KANJI_LEVEL4, // ᅵ + 0xDE3D, KANJI_LEVEL4, // ᅵ + 0x9BB2, KANJI_LEVEL4, // 鮲 + 0x9BB8, KANJI_LEVEL4, // 鮞 + 0x9BBE, KANJI_LEVEL4, // 鮟 + 0x9BC7, KANJI_LEVEL4, // 鯇 + 0x9BF3, KANJI_LEVEL4, // 鯳 + 0x9BD8, KANJI_LEVEL4, // 鯘 + 0x9BDD, KANJI_LEVEL4, // 鯝 + 0x9BE7, KANJI_LEVEL4, // 鯧 + 0x9BEA, KANJI_LEVEL4, // 鯪 + 0x9BEB, KANJI_LEVEL4, // 鯫 + 0x9BEF, KANJI_LEVEL4, // 鯯 + 0x9BEE, KANJI_LEVEL4, // 鯮 + 0xD867, KANJI_LEVEL4, // ᅵ + 0xDE15, KANJI_LEVEL4, // ᅵ + 0x9BFA, KANJI_LEVEL4, // 鯺 + 0xD867, KANJI_LEVEL4, // ᅵ + 0xDE8A, KANJI_LEVEL4, // ᅵ + 0x9BF7, KANJI_LEVEL4, // 鯷 + 0xD867, KANJI_LEVEL4, // ᅵ + 0xDE49, KANJI_LEVEL4, // ᅵ + 0x9C16, KANJI_LEVEL4, // 鰖 + 0x9C18, KANJI_LEVEL4, // 鰘 + 0x9C19, KANJI_LEVEL4, // 鰙 + 0x9C1A, KANJI_LEVEL4, // 鰚 + 0x9C1D, KANJI_LEVEL4, // 鰝 + 0x9C22, KANJI_LEVEL4, // é°¢ + 0x9C27, KANJI_LEVEL4, // é°§ + 0x9C29, KANJI_LEVEL4, // é°© + 0x9C2A, KANJI_LEVEL4, // é°ª + 0xD867, KANJI_LEVEL4, // ᅵ + 0xDEC4, KANJI_LEVEL4, // ᅵ + 0x9C31, KANJI_LEVEL4, // é°± + 0x9C36, KANJI_LEVEL4, // é°¶ + 0x9C37, KANJI_LEVEL4, // é°· + 0x9C45, KANJI_LEVEL4, // 鱅 + 0x9C5C, KANJI_LEVEL4, // 鱜 + 0xD867, KANJI_LEVEL4, // ᅵ + 0xDEE9, KANJI_LEVEL4, // ᅵ + 0x9C49, KANJI_LEVEL4, // 鱉 + 0x9C4A, KANJI_LEVEL4, // 鱊 + 0xD867, KANJI_LEVEL4, // ᅵ + 0xDEDB, KANJI_LEVEL4, // ᅵ + 0x9C54, KANJI_LEVEL4, // 鱔 + 0x9C58, KANJI_LEVEL4, // 鱘 + 0x9C5B, KANJI_LEVEL4, // 鱛 + 0x9C5D, KANJI_LEVEL4, // 鱝 + 0x9C5F, KANJI_LEVEL4, // 鱟 + 0x9C69, KANJI_LEVEL4, // 鱩 + 0x9C6A, KANJI_LEVEL4, // 鱪 + 0x9C6B, KANJI_LEVEL4, // 鱫 + 0x9C6D, KANJI_LEVEL4, // é±­ + 0x9C6E, KANJI_LEVEL4, // é±® + 0x9C70, KANJI_LEVEL4, // é±° + 0x9C72, KANJI_LEVEL4, // é±² + 0x9C75, KANJI_LEVEL4, // é±µ + 0x9C7A, KANJI_LEVEL4, // 鱺 + 0x9CE6, KANJI_LEVEL4, // 鳊 + 0x9CF2, KANJI_LEVEL4, // é³² + 0x9D0B, KANJI_LEVEL4, // 鮋 + 0x9D02, KANJI_LEVEL4, // 鮂 + 0xD867, KANJI_LEVEL4, // ᅵ + 0xDFCE, KANJI_LEVEL4, // ᅵ + 0x9D11, KANJI_LEVEL4, // 鮑 + 0x9D17, KANJI_LEVEL4, // 鮗 + 0x9D18, KANJI_LEVEL4, // 鎘 + 0xD868, KANJI_LEVEL4, // ᅵ + 0xDC2F, KANJI_LEVEL4, // ᅵ + 0x4CC4, KANJI_LEVEL4, // 䳄 + 0xD868, KANJI_LEVEL4, // ᅵ + 0xDC1A, KANJI_LEVEL4, // ᅵ + 0x9D32, KANJI_LEVEL4, // 鎲 + 0x4CD1, KANJI_LEVEL4, // 䳑 + 0x9D42, KANJI_LEVEL4, // 鵂 + 0x9D4A, KANJI_LEVEL4, // 鵊 + 0x9D5F, KANJI_LEVEL4, // 鵟 + 0x9D62, KANJI_LEVEL4, // éµ¢ + 0xD868, KANJI_LEVEL4, // ᅵ + 0xDCF9, KANJI_LEVEL4, // ᅵ + 0x9D69, KANJI_LEVEL4, // 鵩 + 0x9D6B, KANJI_LEVEL4, // 鵫 + 0xD868, KANJI_LEVEL4, // ᅵ + 0xDC82, KANJI_LEVEL4, // ᅵ + 0x9D73, KANJI_LEVEL4, // éµ³ + 0x9D76, KANJI_LEVEL4, // éµ¶ + 0x9D77, KANJI_LEVEL4, // éµ· + 0x9D7E, KANJI_LEVEL4, // 鵟 + 0x9D84, KANJI_LEVEL4, // 鶄 + 0x9D8D, KANJI_LEVEL4, // 鶍 + 0x9D99, KANJI_LEVEL4, // 鶙 + 0x9DA1, KANJI_LEVEL4, // é¶¡ + 0x9DBF, KANJI_LEVEL4, // é¶¿ + 0x9DB5, KANJI_LEVEL4, // é¶µ + 0x9DB9, KANJI_LEVEL4, // é¶¹ + 0x9DBD, KANJI_LEVEL4, // é¶œ + 0x9DC3, KANJI_LEVEL4, // 鷃 + 0x9DC7, KANJI_LEVEL4, // 鷇 + 0x9DC9, KANJI_LEVEL4, // 鷉 + 0x9DD6, KANJI_LEVEL4, // 鷖 + 0x9DDA, KANJI_LEVEL4, // 鷚 + 0x9DDF, KANJI_LEVEL4, // 鷟 + 0x9DE0, KANJI_LEVEL4, // é·  + 0x9DE3, KANJI_LEVEL4, // é·£ + 0x9DF4, KANJI_LEVEL4, // é·Ž + 0x4D07, KANJI_LEVEL4, // 䮇 + 0x9E0A, KANJI_LEVEL4, // 龊 + 0x9E02, KANJI_LEVEL4, // 龂 + 0x9E0D, KANJI_LEVEL4, // 鞍 + 0x9E19, KANJI_LEVEL4, // 龙 + 0x9E1C, KANJI_LEVEL4, // 龜 + 0x9E1D, KANJI_LEVEL4, // 鞝 + 0x9E7B, KANJI_LEVEL4, // é¹» + 0xD848, KANJI_LEVEL4, // ᅵ + 0xDE18, KANJI_LEVEL4, // ᅵ + 0x9E80, KANJI_LEVEL4, // 麀 + 0x9E85, KANJI_LEVEL4, // 麅 + 0x9E9B, KANJI_LEVEL4, // 麛 + 0x9EA8, KANJI_LEVEL4, // 麚 + 0xD868, KANJI_LEVEL4, // ᅵ + 0xDF8C, KANJI_LEVEL4, // ᅵ + 0x9EBD, KANJI_LEVEL4, // 麜 + 0xD869, KANJI_LEVEL4, // ᅵ + 0xDC37, KANJI_LEVEL4, // ᅵ + 0x9EDF, KANJI_LEVEL4, // 黟 + 0x9EE7, KANJI_LEVEL4, // é»§ + 0x9EEE, KANJI_LEVEL4, // é»® + 0x9EFF, KANJI_LEVEL4, // 黿 + 0x9F02, KANJI_LEVEL4, // 錂 + 0x4D77, KANJI_LEVEL4, // äµ· + 0x9F03, KANJI_LEVEL4, // 錃 + 0x9F17, KANJI_LEVEL4, // 錗 + 0x9F19, KANJI_LEVEL4, // 錙 + 0x9F2F, KANJI_LEVEL4, // 錯 + 0x9F37, KANJI_LEVEL4, // 錷 + 0x9F3A, KANJI_LEVEL4, // 錺 + 0x9F3D, KANJI_LEVEL4, // 錜 + 0x9F41, KANJI_LEVEL4, // 霁 + 0x9F45, KANJI_LEVEL4, // 霅 + 0x9F46, KANJI_LEVEL4, // 霆 + 0x9F53, KANJI_LEVEL4, // 霓 + 0x9F55, KANJI_LEVEL4, // 霕 + 0x9F58, KANJI_LEVEL4, // 霘 + 0xD869, KANJI_LEVEL4, // ᅵ + 0xDDF1, KANJI_LEVEL4, // ᅵ + 0x9F5D, KANJI_LEVEL4, // 霝 + 0xD869, KANJI_LEVEL4, // ᅵ + 0xDE02, KANJI_LEVEL4, // ᅵ + 0x9F69, KANJI_LEVEL4, // 霩 + 0xD869, KANJI_LEVEL4, // ᅵ + 0xDE1A, KANJI_LEVEL4, // ᅵ + 0x9F6D, KANJI_LEVEL4, // 霭 + 0x9F70, KANJI_LEVEL4, // 霰 + 0x9F75, KANJI_LEVEL4, // 霵 + 0xD869, KANJI_LEVEL4, // ᅵ + 0xDEB2, KANJI_LEVEL4, // ᅵ +}; \ No newline at end of file From 07fb9d1cf5c510320a5db8ca28d3247a1656db83 Mon Sep 17 00:00:00 2001 From: nachume Date: Thu, 2 May 2013 01:08:07 +0900 Subject: [PATCH 0378/1445] Add a brief description of the USE_KANJI --- tools/atlastool.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 5ce4155919..ecebb7ce84 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -28,8 +28,13 @@ #include "image/zim_save.h" #include "kanjifilter.h" +// ShiftJIS perfect support case. // #define USE_KANJI KANJI_STANDARD | KANJI_RARELY_USED | KANJI_LEVEL4 +// daily-use character only. However, it is too enough this. // #define USE_KANJI KANJI_STANDARD +// more conpact daily-use character. but, not enough this. +// if when you find the unintelligible sequence of characters, +// add kanjiFilter Array with KANJI_LEARNING_ORDER_ADDTIONAL. #define USE_KANJI KANJI_LEARNING_ORDER_ALL #include "util/text/utf8.h" @@ -680,7 +685,7 @@ void GetLocales(const char *locales, std::vector &ranges) std::set hangul1, hangul2, hangul3; for (int i = 0; i < sizeof(kanjiFilter)/sizeof(kanjiFilter[0]); i+=2) { - // TODO: learning level check? + // Kanji filtering. if ((kanjiFilter[i+1] & USE_KANJI) > 0) { kanji.insert(kanjiFilter[i]); } From eb3c3cd21742f9a168f485930592194a144ade8e Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 2 May 2013 15:45:51 +1000 Subject: [PATCH 0379/1445] Use boost to do C++11 features on Symbian. Use namespaces. --- thread/threadpool.cpp | 14 +++++++++----- thread/threadpool.h | 16 ++++++++++++---- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp index 8da01601a9..593b309c09 100644 --- a/thread/threadpool.cpp +++ b/thread/threadpool.cpp @@ -3,7 +3,7 @@ ///////////////////////////// WorkerThread WorkerThread::WorkerThread() : active(true), started(false) { - thread = new std::thread(std::bind(&WorkerThread::WorkFunc, this)); + thread = new std::thread(bind(&WorkerThread::WorkFunc, this)); doneMutex.lock(); while(!started) { }; } @@ -17,7 +17,7 @@ WorkerThread::~WorkerThread() { delete thread; } -void WorkerThread::Process(const std::function& work) { +void WorkerThread::Process(const function& work) { mutex.lock(); work_ = work; signal.notify_one(); @@ -50,13 +50,17 @@ ThreadPool::ThreadPool(int numThreads) : numThreads(numThreads), workersStarted( void ThreadPool::StartWorkers() { if(!workersStarted) { for(int i=0; i()); +#ifdef __SYMBIAN32__ + workers.push_back(make_shared(weak_ptr())); +#else + workers.push_back(make_shared()); +#endif } workersStarted = true; } } -void ThreadPool::ParallelLoop(std::function loop, int lower, int upper) { +void ThreadPool::ParallelLoop(function loop, int lower, int upper) { mutex.lock(); StartWorkers(); int range = upper-lower; @@ -65,7 +69,7 @@ void ThreadPool::ParallelLoop(std::function loop, int lower, int // but doesn't matter since all our loops are power of 2 int chunk = range/numThreads; for(int s=lower, i=0; iProcess(std::bind(loop, s, std::min(s+chunk,upper))); + workers[i]->Process(bind(loop, s, std::min(s+chunk,upper))); } for(int i=0; iWaitForCompletion(); diff --git a/thread/threadpool.h b/thread/threadpool.h index 6f90073d8c..4bcddba33a 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -4,6 +4,14 @@ #include "base/mutex.h" #include +#ifdef __SYMBIAN32__ +#include +#include +#include +using namespace boost; +#else +using namespace std; +#endif #include // This is the simplest possible worker implementation I can think of @@ -15,7 +23,7 @@ public: ~WorkerThread(); // submit a new work item - void Process(const std::function& work); + void Process(const function& work); // wait for a submitted work item to be completed void WaitForCompletion(); @@ -25,7 +33,7 @@ private: condition_variable done; // used to signal work completion recursive_mutex mutex, doneMutex; // associated with each respective condition variable volatile bool active, started; - std::function work_; // the work to be done by this thread + function work_; // the work to be done by this thread void WorkFunc(); @@ -42,11 +50,11 @@ public: // don't need a destructor, "workers" is cleared on delete, // leading to the stopping and joining of all worker threads (RAII and all that) - void ParallelLoop(std::function loop, int lower, int upper); + void ParallelLoop(function loop, int lower, int upper); private: const int numThreads; - std::vector> workers; + std::vector> workers; recursive_mutex mutex; // used to sequentialize loop execution bool workersStarted; From 8d7fd418387451dd5f4140374959519c09b75a47 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 1 May 2013 23:30:11 -0700 Subject: [PATCH 0380/1445] Buildfix for iOS. --- thread/threadpool.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/thread/threadpool.h b/thread/threadpool.h index 4bcddba33a..44b104f1c5 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -10,10 +10,33 @@ #include using namespace boost; #else +#include using namespace std; #endif #include +#if defined(IOS) || (defined(__APPLE__) && !defined(__MAC_10_7)) +#include +#include +namespace std { + using tr1::bind; + using tr1::function; + using tr1::shared_ptr; + + template + inline shared_ptr make_shared() + { + return shared_ptr(new T()); + } + + template + inline shared_ptr make_shared(Arg1& arg1) + { + return shared_ptr(new T(arg1)); + } +} +#endif + // This is the simplest possible worker implementation I can think of // but entirely sufficient for the given purpose. // Only handles a single item of work at a time. From 0388a8e23a2664766503996579dc10511b1db524 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 2 May 2013 17:05:34 +1000 Subject: [PATCH 0381/1445] Buildfix for Symbian. --- thread/threadpool.cpp | 6 +----- thread/threadpool.h | 6 +++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp index 593b309c09..30fbb9af96 100644 --- a/thread/threadpool.cpp +++ b/thread/threadpool.cpp @@ -50,11 +50,7 @@ ThreadPool::ThreadPool(int numThreads) : numThreads(numThreads), workersStarted( void ThreadPool::StartWorkers() { if(!workersStarted) { for(int i=0; i(weak_ptr())); -#else - workers.push_back(make_shared()); -#endif + workers.push_back(std::make_shared()); } workersStarted = true; } diff --git a/thread/threadpool.h b/thread/threadpool.h index 44b104f1c5..2dc412dd75 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -15,13 +15,17 @@ using namespace std; #endif #include -#if defined(IOS) || (defined(__APPLE__) && !defined(__MAC_10_7)) +#if defined(__SYMBIAN32__) || defined(IOS) || (defined(__APPLE__) && !defined(__MAC_10_7)) +#ifndef __SYMBIAN32__ #include #include +#endif namespace std { +#ifndef __SYMBIAN32__ using tr1::bind; using tr1::function; using tr1::shared_ptr; +#endif template inline shared_ptr make_shared() From f9c50c822a9a12bcd3952dda58876d1fc2afa2a9 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 2 May 2013 17:34:06 +1000 Subject: [PATCH 0382/1445] Fix name collision by prefixing '::'. --- thread/threadpool.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/thread/threadpool.h b/thread/threadpool.h index 2dc412dd75..e89c93e8cd 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -56,9 +56,9 @@ public: private: std::thread *thread; // the worker thread - condition_variable signal; // used to signal new work - condition_variable done; // used to signal work completion - recursive_mutex mutex, doneMutex; // associated with each respective condition variable + ::condition_variable signal; // used to signal new work + ::condition_variable done; // used to signal work completion + ::recursive_mutex mutex, doneMutex; // associated with each respective condition variable volatile bool active, started; function work_; // the work to be done by this thread @@ -82,7 +82,7 @@ public: private: const int numThreads; std::vector> workers; - recursive_mutex mutex; // used to sequentialize loop execution + ::recursive_mutex mutex; // used to sequentialize loop execution bool workersStarted; void StartWorkers(); From bfe5aea1d1c4e0bc3e87a28a2bc9aaae4605a3c0 Mon Sep 17 00:00:00 2001 From: aquanull Date: Fri, 3 May 2013 00:19:27 +0800 Subject: [PATCH 0383/1445] Shrink UICheckBox heights This makes it much easier to check/uncheck the right items in a compact list. --- ui/ui.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/ui.cpp b/ui/ui.cpp index 301fc9cda8..9fd6769a06 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -315,9 +315,12 @@ int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w return clicked; } - int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { - const int h = 64; +#ifdef _WIN32 + const int h = 32; +#else + const int h = 48; +#endif float tw, th; ui_draw2d.MeasureText(theme.uiFont, text, &tw, &th); int w = themeAtlas->images[theme.checkOn].w + UI_SPACE + tw; From b41eca41c2e559839e7ce4bf184f0beb8c989d42 Mon Sep 17 00:00:00 2001 From: nachume Date: Fri, 3 May 2013 02:49:53 +0900 Subject: [PATCH 0384/1445] I must every time stash before push to git. It's too much trouble. Can you use the "%LOCALAPPDATA%\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props" file instead of the [VC++ Directories] Property Page? --- native.vcxproj | 32 ++++++++----------------------- tools/atlastool/atlastool.vcxproj | 4 ---- tools/zimtool/zimtool.vcxproj | 4 ---- 3 files changed, 8 insertions(+), 32 deletions(-) diff --git a/native.vcxproj b/native.vcxproj index e9a230f557..18f197eb4f 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -63,30 +63,14 @@ - - D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; - - - D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; - - - D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib - - - D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib - - - D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; - - - D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; - - - D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib - - - D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib - + + + + + + + + diff --git a/tools/atlastool/atlastool.vcxproj b/tools/atlastool/atlastool.vcxproj index 2cee3d51d5..a9d29da7f2 100644 --- a/tools/atlastool/atlastool.vcxproj +++ b/tools/atlastool/atlastool.vcxproj @@ -40,13 +40,9 @@ true - D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; - D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib false - D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; - D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib $(ProjectDir)\..\build diff --git a/tools/zimtool/zimtool.vcxproj b/tools/zimtool/zimtool.vcxproj index 46dfd90a1a..d43b7f8414 100644 --- a/tools/zimtool/zimtool.vcxproj +++ b/tools/zimtool/zimtool.vcxproj @@ -40,13 +40,9 @@ true - D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; - D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib false - D:\dev\LIB;C:\DXSDK\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; - D:\dev\LIB;C:\DXSDK\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib $(ProjectDir)\..\build From 5835fe293ab693afac377d6341bda0a6b706f48b Mon Sep 17 00:00:00 2001 From: Peter Thoman Date: Fri, 3 May 2013 14:27:02 +0200 Subject: [PATCH 0385/1445] When processing a parallel loop, save some context switching by processing one chunk on the calling thread --- thread/threadpool.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp index 30fbb9af96..dcc733025d 100644 --- a/thread/threadpool.cpp +++ b/thread/threadpool.cpp @@ -64,10 +64,13 @@ void ThreadPool::ParallelLoop(function loop, int lower, int upper // could do slightly better load balancing for the generic case, // but doesn't matter since all our loops are power of 2 int chunk = range/numThreads; - for(int s=lower, i=0; iProcess(bind(loop, s, std::min(s+chunk,upper))); + int s = lower; + for(int i=0; iProcess(bind(loop, s, s+chunk)); + s+=chunk; } - for(int i=0; iWaitForCompletion(); } } else { From 3edf239571e8132eed1fa6baaf7b8e269d889103 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 May 2013 17:55:01 +0200 Subject: [PATCH 0386/1445] Remove use of clock_gettime in favor of gettimeofday. --- base/mutex.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index ead43f36a2..142c378b6e 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -146,15 +146,12 @@ public: // mtx.lock(); #else timespec timeout; -#ifdef __APPLE__ - timeval tv; - gettimeofday(&tv, NULL); - timeout.tv_sec = tv.tv_sec; - timeout.tv_nsec = tv.tv_usec * 1000; -#else - clock_gettime(CLOCK_REALTIME, &timeout); -#endif - timeout.tv_sec += milliseconds / 1000; + timeval tv; + gettimeofday(&tv, NULL); + timeout.tv_sec = tv.tv_sec; + timeout.tv_nsec = tv.tv_usec * 1000; + + timeout.tv_sec += milliseconds / 1000; timeout.tv_nsec += milliseconds * 1000000; pthread_mutex_lock(&mtx.native_handle()); pthread_cond_timedwait(&event_, &mtx.native_handle(), &timeout); From 4821d7f7bd3f4dc128345f5c7ca3cf423d46dcc3 Mon Sep 17 00:00:00 2001 From: nachume Date: Sun, 5 May 2013 06:25:00 +0900 Subject: [PATCH 0387/1445] =?UTF-8?q?Add=20Symbol=20of=20some=20of=20the?= =?UTF-8?q?=20SJIS.=20Add=20"=E7=A2=A7"=20to=20KANJI=5FLEARNING=5FORDER=5F?= =?UTF-8?q?ADDTIONAL=20Add=20kanjifilter=20SJIS=20partition=20table=20(KAN?= =?UTF-8?q?JI=5FSJIS=5FLX)=20FIX=20Not=20float=20variable=20initialization?= =?UTF-8?q?=20vertOffset.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/atlastool.cpp | 16 +- tools/kanjifilter.h | 7123 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 7130 insertions(+), 9 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index ecebb7ce84..28d50d6acc 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -28,14 +28,17 @@ #include "image/zim_save.h" #include "kanjifilter.h" -// ShiftJIS perfect support case. -// #define USE_KANJI KANJI_STANDARD | KANJI_RARELY_USED | KANJI_LEVEL4 +// extracted only JIS Kanji on the CJK Unified Ideographs of UCS2. Cannot reading BlockAllocator. (texture size over) +//#define USE_KANJI KANJI_STANDARD | KANJI_RARELY_USED | KANJI_LEVEL4 // daily-use character only. However, it is too enough this. -// #define USE_KANJI KANJI_STANDARD +//#define USE_KANJI KANJI_STANDARD (texture size over) +// Shift-JIS filtering. (texture size over) +//#define USE_KANJI KANJI_SJIS_L1 | KANJI_SJIS_L2 // more conpact daily-use character. but, not enough this. // if when you find the unintelligible sequence of characters, // add kanjiFilter Array with KANJI_LEARNING_ORDER_ADDTIONAL. #define USE_KANJI KANJI_LEARNING_ORDER_ALL + #include "util/text/utf8.h" #define CHECK(x) if (!(x)) { printf("%i: CHECK failed on this line\n", __LINE__); exit(1); } @@ -707,7 +710,7 @@ void GetLocales(const char *locales, std::vector &ranges) case 'W': // Latin-1 extras 1 ranges.push_back(range(0x80, 0x80)); // euro sign ranges.push_back(range(0xA2, 0xFF)); // 80 - A0 appears to contain nothing interesting - ranges.push_back(range(0x2122, 0x2122)); // trademark symbol + ranges.push_back(range(0x2121, 0x2122)); // TEL symbol and trademark symbol break; case 'E': // Latin-1 Extended A (needed for Hungarian etc) ranges.push_back(range(0x100, 0x17F)); @@ -729,6 +732,9 @@ void GetLocales(const char *locales, std::vector &ranges) // Mathematical Operators, Miscellaneous Technical ranges.push_back(range(0x2500, 0x254B)); // Box drawing ranges.push_back(range(0x25A0, 0x266F)); // Geometric Shapes, Miscellaneous Symbols + ranges.push_back(range(0x3231, 0x3231)); // Co,.Ltd. symbol + ranges.push_back(range(0x2116, 0x2116)); // "No." symbol + ranges.push_back(range(0x33CD, 0x33CD)); // "K.K." symbol case 'H': // Hebrew ranges.push_back(range(0x0590, 0x05FF)); break; @@ -801,7 +807,7 @@ int main(int argc, char **argv) { char fontfile[256]; char locales[256]; int pixheight; - float vertOffset; + float vertOffset = 0; sscanf(rest, "%s %s %s %i %f", fontname, fontfile, locales, &pixheight, &vertOffset); printf("Font: %s (%s) in size %i. Locales: %s\n", fontname, fontfile, pixheight, locales); diff --git a/tools/kanjifilter.h b/tools/kanjifilter.h index 7ab817124e..e44afad1ed 100644 --- a/tools/kanjifilter.h +++ b/tools/kanjifilter.h @@ -1,4 +1,5 @@ // http://www.asahi-net.or.jp/~ax2s-kmtn/character/japan.html +// http://charset.uic.jp/show/shiftjis2004/ enum KANJI_LEVEL { KANJI_LEARNING_ORDER_1 = 0x0001, @@ -8,19 +9,26 @@ enum KANJI_LEVEL KANJI_LEARNING_ORDER_5 = 0x0010, KANJI_LEARNING_ORDER_6 = 0x0020, KANJI_LEARNING_ORDER_7 = 0x0040, - KANJI_LEARNING_ORDER_ADDTIONAL = 0x1000, // if you find garbled character when playing. + KANJI_LEARNING_ORDER_ADDTIONAL = 0x0100, // if you find garbled character when playing. - KANJI_LEARNING_ORDER_ALL = 0x1FFF, + KANJI_LEARNING_ORDER_ALL = 0x01FF, + + KANJI_SJIS_L1 = 0x0200, // daily use. this is ShiftJIS based The level 1 JIS. Almost the same as KANJI_STANDARD. + KANJI_SJIS_L2 = 0x0400, // daily use. this is ShiftJIS based The level 2 JIS. Almost the same as KANJI_STANDARD. + KANJI_SJIS_L3 = 0x0800, // not daily use. part of the level 3 and 4 JIS. + + KANJI_SJIS_ALL = 0x0E00, // ShiftJIS Kanji full support. It is not able to display all the CJK Unified Ideographs. // warning Cannot used. BlockAllocator size over. 2048x4096 size = 0x00400000 KANJI_STANDARD = 0x2000, // daily use (JIS X 2008 = The level 1 JIS and The leve 2 JIS) KANJI_RARELY_USED = 0x4000, // not daily use. but, The Chinese characters that may be used in a visual novel game maybe. (JIS X 2012 = The level 3 JIS) - KANJI_LEVEL4 = 0x8000, // JIS X 2008 extend. (JIS X 2008 + 1259 characters of JIS X 2012 + The level 4 JIS) + KANJI_LEVEL4 = 0x8000, // JIS X 2008 extend. (JIS X 2013 = JIS X 2008 + 1259 characters of JIS X 2012 + The level 4 JIS) }; // The parameter is the learning order. const unsigned short kanjiFilter[] = { + 0x78A7, KANJI_LEARNING_ORDER_ADDTIONAL, // 碧 0x7A9F, KANJI_LEARNING_ORDER_ADDTIONAL, // 窟 0x4E00, KANJI_LEARNING_ORDER_1, // 侀 0x4E01, KANJI_LEARNING_ORDER_3, // 䞁 @@ -1968,7 +1976,6 @@ const unsigned short kanjiFilter[] = { 0x9F13, KANJI_LEARNING_ORDER_7, // 錓 0x9F3B, KANJI_LEARNING_ORDER_3, // 錻 0x9F62, KANJI_LEARNING_ORDER_7, // 霢 - 0x4E9C, KANJI_STANDARD, // 亜 0x5516, KANJI_STANDARD, // 唖 0x5A03, KANJI_STANDARD, // 嚃 @@ -24478,4 +24485,7112 @@ const unsigned short kanjiFilter[] = { 0x9F75, KANJI_LEVEL4, // 霵 0xD869, KANJI_LEVEL4, // ᅵ 0xDEB2, KANJI_LEVEL4, // ᅵ + 0x4E9C, KANJI_SJIS_L1, // 亜 + 0x5516, KANJI_SJIS_L1, // 唖 + 0x5A03, KANJI_SJIS_L1, // 嚃 + 0x963F, KANJI_SJIS_L1, // 阿 + 0x54C0, KANJI_SJIS_L1, // 哀 + 0x611B, KANJI_SJIS_L1, // 愛 + 0x6328, KANJI_SJIS_L1, // 挚 + 0x59F6, KANJI_SJIS_L1, // å§¶ + 0x9022, KANJI_SJIS_L1, // 逢 + 0x8475, KANJI_SJIS_L1, // 葵 + 0x831C, KANJI_SJIS_L1, // 茜 + 0x7A50, KANJI_SJIS_L1, // 穐 + 0x60AA, KANJI_SJIS_L1, // 悪 + 0x63E1, KANJI_SJIS_L1, // 握 + 0x6E25, KANJI_SJIS_L1, // 枥 + 0x65ED, KANJI_SJIS_L1, // 旭 + 0x8466, KANJI_SJIS_L1, // 葊 + 0x82A6, KANJI_SJIS_L1, // 芊 + 0x9BF5, KANJI_SJIS_L1, // 鯵 + 0x6893, KANJI_SJIS_L1, // 梓 + 0x5727, KANJI_SJIS_L1, // 圧 + 0x65A1, KANJI_SJIS_L1, // 斡 + 0x6271, KANJI_SJIS_L1, // 扱 + 0x5B9B, KANJI_SJIS_L1, // 宛 + 0x59D0, KANJI_SJIS_L1, // 姐 + 0x867B, KANJI_SJIS_L1, // 虻 + 0x98F4, KANJI_SJIS_L1, // 风 + 0x7D62, KANJI_SJIS_L1, // çµ¢ + 0x7DBE, KANJI_SJIS_L1, // ç¶Ÿ + 0x9B8E, KANJI_SJIS_L1, // 鮎 + 0x6216, KANJI_SJIS_L1, // 或 + 0x7C9F, KANJI_SJIS_L1, // 粟 + 0x88B7, KANJI_SJIS_L1, // 袷 + 0x5B89, KANJI_SJIS_L1, // 安 + 0x5EB5, KANJI_SJIS_L1, // 庵 + 0x6309, KANJI_SJIS_L1, // 按 + 0x6697, KANJI_SJIS_L1, // 暗 + 0x6848, KANJI_SJIS_L1, // 案 + 0x95C7, KANJI_SJIS_L1, // 闇 + 0x978D, KANJI_SJIS_L1, // 鞍 + 0x674F, KANJI_SJIS_L1, // 杏 + 0x4EE5, KANJI_SJIS_L1, // 以 + 0x4F0A, KANJI_SJIS_L1, // 䌊 + 0x4F4D, KANJI_SJIS_L1, // 䜍 + 0x4F9D, KANJI_SJIS_L1, // 䟝 + 0x5049, KANJI_SJIS_L1, // 偉 + 0x56F2, KANJI_SJIS_L1, // 囲 + 0x5937, KANJI_SJIS_L1, // 倷 + 0x59D4, KANJI_SJIS_L1, // 委 + 0x5A01, KANJI_SJIS_L1, // 嚁 + 0x5C09, KANJI_SJIS_L1, // 尉 + 0x60DF, KANJI_SJIS_L1, // 惟 + 0x610F, KANJI_SJIS_L1, // 意 + 0x6170, KANJI_SJIS_L1, // 慰 + 0x6613, KANJI_SJIS_L1, // 易 + 0x6905, KANJI_SJIS_L1, // 怅 + 0x70BA, KANJI_SJIS_L1, // 為 + 0x754F, KANJI_SJIS_L1, // 畏 + 0x7570, KANJI_SJIS_L1, // 異 + 0x79FB, KANJI_SJIS_L1, // ç§» + 0x7DAD, KANJI_SJIS_L1, // ç¶­ + 0x7DEF, KANJI_SJIS_L1, // ç·¯ + 0x80C3, KANJI_SJIS_L1, // 胃 + 0x840E, KANJI_SJIS_L1, // 萎 + 0x8863, KANJI_SJIS_L1, // è¡£ + 0x8B02, KANJI_SJIS_L1, // 謂 + 0x9055, KANJI_SJIS_L1, // 違 + 0x907A, KANJI_SJIS_L1, // 遺 + 0x533B, KANJI_SJIS_L1, // 医 + 0x4E95, KANJI_SJIS_L1, // 井 + 0x4EA5, KANJI_SJIS_L1, // 亥 + 0x57DF, KANJI_SJIS_L1, // 域 + 0x80B2, KANJI_SJIS_L1, // 育 + 0x90C1, KANJI_SJIS_L1, // 郁 + 0x78EF, KANJI_SJIS_L1, // 磯 + 0x4E00, KANJI_SJIS_L1, // 侀 + 0x58F1, KANJI_SJIS_L1, // 壱 + 0x6EA2, KANJI_SJIS_L1, // 溢 + 0x9038, KANJI_SJIS_L1, // 逾 + 0x7A32, KANJI_SJIS_L1, // çš² + 0x8328, KANJI_SJIS_L1, // 茚 + 0x828B, KANJI_SJIS_L1, // 芋 + 0x9C2F, KANJI_SJIS_L1, // é°¯ + 0x5141, KANJI_SJIS_L1, // 允 + 0x5370, KANJI_SJIS_L1, // 印 + 0x54BD, KANJI_SJIS_L1, // å’œ + 0x54E1, KANJI_SJIS_L1, // 員 + 0x56E0, KANJI_SJIS_L1, // 因 + 0x59FB, KANJI_SJIS_L1, // å§» + 0x5F15, KANJI_SJIS_L1, // 匕 + 0x98F2, KANJI_SJIS_L1, // 飲 + 0x6DEB, KANJI_SJIS_L1, // æ·« + 0x80E4, KANJI_SJIS_L1, // 胀 + 0x852D, KANJI_SJIS_L1, // 蔭 + 0x9662, KANJI_SJIS_L1, // 院 + 0x9670, KANJI_SJIS_L1, // 陰 + 0x96A0, KANJI_SJIS_L1, // 隠 + 0x97FB, KANJI_SJIS_L1, // 韻 + 0x540B, KANJI_SJIS_L1, // 吋 + 0x53F3, KANJI_SJIS_L1, // 右 + 0x5B87, KANJI_SJIS_L1, // 宇 + 0x70CF, KANJI_SJIS_L1, // 烏 + 0x7FBD, KANJI_SJIS_L1, // 矜 + 0x8FC2, KANJI_SJIS_L1, // 迂 + 0x96E8, KANJI_SJIS_L1, // 雹 + 0x536F, KANJI_SJIS_L1, // 卯 + 0x9D5C, KANJI_SJIS_L1, // 鵜 + 0x7ABA, KANJI_SJIS_L1, // 窺 + 0x4E11, KANJI_SJIS_L1, // 侑 + 0x7893, KANJI_SJIS_L1, // 碓 + 0x81FC, KANJI_SJIS_L1, // 臌 + 0x6E26, KANJI_SJIS_L1, // 枊 + 0x5618, KANJI_SJIS_L1, // 嘘 + 0x5504, KANJI_SJIS_L1, // 唄 + 0x6B1D, KANJI_SJIS_L1, // 欝 + 0x851A, KANJI_SJIS_L1, // 蔚 + 0x9C3B, KANJI_SJIS_L1, // é°» + 0x59E5, KANJI_SJIS_L1, // å§¥ + 0x53A9, KANJI_SJIS_L1, // 厩 + 0x6D66, KANJI_SJIS_L1, // 浊 + 0x74DC, KANJI_SJIS_L1, // 瓜 + 0x958F, KANJI_SJIS_L1, // 閏 + 0x5642, KANJI_SJIS_L1, // 噂 + 0x4E91, KANJI_SJIS_L1, // 云 + 0x904B, KANJI_SJIS_L1, // 運 + 0x96F2, KANJI_SJIS_L1, // 雲 + 0x834F, KANJI_SJIS_L1, // 荏 + 0x990C, KANJI_SJIS_L1, // 逌 + 0x53E1, KANJI_SJIS_L1, // 叡 + 0x55B6, KANJI_SJIS_L1, // 営 + 0x5B30, KANJI_SJIS_L1, // 嬰 + 0x5F71, KANJI_SJIS_L1, // 圱 + 0x6620, KANJI_SJIS_L1, // 映 + 0x66F3, KANJI_SJIS_L1, // 曳 + 0x6804, KANJI_SJIS_L1, // 栄 + 0x6C38, KANJI_SJIS_L1, // æ°ž + 0x6CF3, KANJI_SJIS_L1, // æ³³ + 0x6D29, KANJI_SJIS_L1, // 掩 + 0x745B, KANJI_SJIS_L1, // 瑛 + 0x76C8, KANJI_SJIS_L1, // 盈 + 0x7A4E, KANJI_SJIS_L1, // 穎 + 0x9834, KANJI_SJIS_L1, // é Ž + 0x82F1, KANJI_SJIS_L1, // 英 + 0x885B, KANJI_SJIS_L1, // 衛 + 0x8A60, KANJI_SJIS_L1, // è©  + 0x92ED, KANJI_SJIS_L1, // 鋭 + 0x6DB2, KANJI_SJIS_L1, // æ¶² + 0x75AB, KANJI_SJIS_L1, // 疫 + 0x76CA, KANJI_SJIS_L1, // 益 + 0x99C5, KANJI_SJIS_L1, // 駅 + 0x60A6, KANJI_SJIS_L1, // 悊 + 0x8B01, KANJI_SJIS_L1, // 謁 + 0x8D8A, KANJI_SJIS_L1, // 越 + 0x95B2, KANJI_SJIS_L1, // 閲 + 0x698E, KANJI_SJIS_L1, // 抎 + 0x53AD, KANJI_SJIS_L1, // 厭 + 0x5186, KANJI_SJIS_L1, // 円 + 0x3000, KANJI_SJIS_L1, //   + 0x5712, KANJI_SJIS_L1, // 園 + 0x5830, KANJI_SJIS_L1, // å ° + 0x5944, KANJI_SJIS_L1, // 奄 + 0x5BB4, KANJI_SJIS_L1, // 宎 + 0x5EF6, KANJI_SJIS_L1, // å»¶ + 0x6028, KANJI_SJIS_L1, // 怚 + 0x63A9, KANJI_SJIS_L1, // 掩 + 0x63F4, KANJI_SJIS_L1, // 揎 + 0x6CBF, KANJI_SJIS_L1, // 沿 + 0x6F14, KANJI_SJIS_L1, // 挔 + 0x708E, KANJI_SJIS_L1, // 炎 + 0x7114, KANJI_SJIS_L1, // 焔 + 0x7159, KANJI_SJIS_L1, // 煙 + 0x71D5, KANJI_SJIS_L1, // 燕 + 0x733F, KANJI_SJIS_L1, // 猿 + 0x7E01, KANJI_SJIS_L1, // 瞁 + 0x8276, KANJI_SJIS_L1, // 艶 + 0x82D1, KANJI_SJIS_L1, // 苑 + 0x8597, KANJI_SJIS_L1, // 薗 + 0x9060, KANJI_SJIS_L1, // 遠 + 0x925B, KANJI_SJIS_L1, // 鉛 + 0x9D1B, KANJI_SJIS_L1, // 鮛 + 0x5869, KANJI_SJIS_L1, // å¡© + 0x65BC, KANJI_SJIS_L1, // æ–Œ + 0x6C5A, KANJI_SJIS_L1, // 汚 + 0x7525, KANJI_SJIS_L1, // 甥 + 0x51F9, KANJI_SJIS_L1, // 凹 + 0x592E, KANJI_SJIS_L1, // 倮 + 0x5965, KANJI_SJIS_L1, // 奥 + 0x5F80, KANJI_SJIS_L1, // 埀 + 0x5FDC, KANJI_SJIS_L1, // 応 + 0x62BC, KANJI_SJIS_L1, // 抌 + 0x65FA, KANJI_SJIS_L1, // 旺 + 0x6A2A, KANJI_SJIS_L1, // 暪 + 0x6B27, KANJI_SJIS_L1, // 欧 + 0x6BB4, KANJI_SJIS_L1, // 殎 + 0x738B, KANJI_SJIS_L1, // 王 + 0x7FC1, KANJI_SJIS_L1, // 翁 + 0x8956, KANJI_SJIS_L1, // 襖 + 0x9D2C, KANJI_SJIS_L1, // 鎬 + 0x9D0E, KANJI_SJIS_L1, // 鮎 + 0x9EC4, KANJI_SJIS_L1, // 黄 + 0x5CA1, KANJI_SJIS_L1, // 岡 + 0x6C96, KANJI_SJIS_L1, // 沖 + 0x837B, KANJI_SJIS_L1, // 荻 + 0x5104, KANJI_SJIS_L1, // 億 + 0x5C4B, KANJI_SJIS_L1, // 屋 + 0x61B6, KANJI_SJIS_L1, // 憶 + 0x81C6, KANJI_SJIS_L1, // 臆 + 0x6876, KANJI_SJIS_L1, // æ¡¶ + 0x7261, KANJI_SJIS_L1, // 牡 + 0x4E59, KANJI_SJIS_L1, // 乙 + 0x4FFA, KANJI_SJIS_L1, // 俺 + 0x5378, KANJI_SJIS_L1, // 卞 + 0x6069, KANJI_SJIS_L1, // 恩 + 0x6E29, KANJI_SJIS_L1, // æž© + 0x7A4F, KANJI_SJIS_L1, // 穏 + 0x97F3, KANJI_SJIS_L1, // 音 + 0x4E0B, KANJI_SJIS_L1, // 例 + 0x5316, KANJI_SJIS_L1, // 化 + 0x4EEE, KANJI_SJIS_L1, // ä»® + 0x4F55, KANJI_SJIS_L1, // 䜕 + 0x4F3D, KANJI_SJIS_L1, // 䌜 + 0x4FA1, KANJI_SJIS_L1, // 䟡 + 0x4F73, KANJI_SJIS_L1, // 䜳 + 0x52A0, KANJI_SJIS_L1, // 加 + 0x53EF, KANJI_SJIS_L1, // 可 + 0x5609, KANJI_SJIS_L1, // 嘉 + 0x590F, KANJI_SJIS_L1, // 倏 + 0x5AC1, KANJI_SJIS_L1, // 嫁 + 0x5BB6, KANJI_SJIS_L1, // å®¶ + 0x5BE1, KANJI_SJIS_L1, // 寡 + 0x79D1, KANJI_SJIS_L1, // 科 + 0x6687, KANJI_SJIS_L1, // 暇 + 0x679C, KANJI_SJIS_L1, // 果 + 0x67B6, KANJI_SJIS_L1, // 架 + 0x6B4C, KANJI_SJIS_L1, // 歌 + 0x6CB3, KANJI_SJIS_L1, // æ²³ + 0x706B, KANJI_SJIS_L1, // 火 + 0x73C2, KANJI_SJIS_L1, // 珂 + 0x798D, KANJI_SJIS_L1, // 犍 + 0x79BE, KANJI_SJIS_L1, // 犟 + 0x7A3C, KANJI_SJIS_L1, // 皌 + 0x7B87, KANJI_SJIS_L1, // 箇 + 0x82B1, KANJI_SJIS_L1, // 花 + 0x82DB, KANJI_SJIS_L1, // 苛 + 0x8304, KANJI_SJIS_L1, // 茄 + 0x8377, KANJI_SJIS_L1, // 荷 + 0x83EF, KANJI_SJIS_L1, // 華 + 0x83D3, KANJI_SJIS_L1, // 菓 + 0x8766, KANJI_SJIS_L1, // 蝊 + 0x8AB2, KANJI_SJIS_L1, // 課 + 0x5629, KANJI_SJIS_L1, // 嘩 + 0x8CA8, KANJI_SJIS_L1, // 貚 + 0x8FE6, KANJI_SJIS_L1, // 迊 + 0x904E, KANJI_SJIS_L1, // 過 + 0x971E, KANJI_SJIS_L1, // 霞 + 0x868A, KANJI_SJIS_L1, // 蚊 + 0x4FC4, KANJI_SJIS_L1, // 俄 + 0x5CE8, KANJI_SJIS_L1, // 峚 + 0x6211, KANJI_SJIS_L1, // 我 + 0x7259, KANJI_SJIS_L1, // 牙 + 0x753B, KANJI_SJIS_L1, // 画 + 0x81E5, KANJI_SJIS_L1, // 臥 + 0x82BD, KANJI_SJIS_L1, // 芜 + 0x86FE, KANJI_SJIS_L1, // 蛟 + 0x8CC0, KANJI_SJIS_L1, // 賀 + 0x96C5, KANJI_SJIS_L1, // 雅 + 0x9913, KANJI_SJIS_L1, // 逓 + 0x99D5, KANJI_SJIS_L1, // 駕 + 0x4ECB, KANJI_SJIS_L1, // 介 + 0x4F1A, KANJI_SJIS_L1, // 䌚 + 0x89E3, KANJI_SJIS_L1, // è§£ + 0x56DE, KANJI_SJIS_L1, // 回 + 0x584A, KANJI_SJIS_L1, // 塊 + 0x58CA, KANJI_SJIS_L1, // 壊 + 0x5EFB, KANJI_SJIS_L1, // å»» + 0x5FEB, KANJI_SJIS_L1, // å¿« + 0x602A, KANJI_SJIS_L1, // 怪 + 0x6094, KANJI_SJIS_L1, // 悔 + 0x6062, KANJI_SJIS_L1, // 恢 + 0x61D0, KANJI_SJIS_L1, // 懐 + 0x6212, KANJI_SJIS_L1, // 戒 + 0x62D0, KANJI_SJIS_L1, // 拐 + 0x6539, KANJI_SJIS_L1, // 改 + 0x9B41, KANJI_SJIS_L1, // 魁 + 0x6666, KANJI_SJIS_L1, // 晊 + 0x68B0, KANJI_SJIS_L1, // 械 + 0x6D77, KANJI_SJIS_L1, // æµ· + 0x7070, KANJI_SJIS_L1, // 灰 + 0x754C, KANJI_SJIS_L1, // 界 + 0x7686, KANJI_SJIS_L1, // 皆 + 0x7D75, KANJI_SJIS_L1, // çµµ + 0x82A5, KANJI_SJIS_L1, // 芥 + 0x87F9, KANJI_SJIS_L1, // 蟹 + 0x958B, KANJI_SJIS_L1, // 開 + 0x968E, KANJI_SJIS_L1, // 階 + 0x8C9D, KANJI_SJIS_L1, // 貝 + 0x51F1, KANJI_SJIS_L1, // 凱 + 0x52BE, KANJI_SJIS_L1, // 功 + 0x5916, KANJI_SJIS_L1, // 倖 + 0x54B3, KANJI_SJIS_L1, // 咳 + 0x5BB3, KANJI_SJIS_L1, // 害 + 0x5D16, KANJI_SJIS_L1, // 厖 + 0x6168, KANJI_SJIS_L1, // æ…š + 0x6982, KANJI_SJIS_L1, // 抂 + 0x6DAF, KANJI_SJIS_L1, // 涯 + 0x788D, KANJI_SJIS_L1, // 碍 + 0x84CB, KANJI_SJIS_L1, // 蓋 + 0x8857, KANJI_SJIS_L1, // 街 + 0x8A72, KANJI_SJIS_L1, // 該 + 0x93A7, KANJI_SJIS_L1, // 鎧 + 0x9AB8, KANJI_SJIS_L1, // 骞 + 0x6D6C, KANJI_SJIS_L1, // 浬 + 0x99A8, KANJI_SJIS_L1, // 銚 + 0x86D9, KANJI_SJIS_L1, // 蛙 + 0x57A3, KANJI_SJIS_L1, // 垣 + 0x67FF, KANJI_SJIS_L1, // 柿 + 0x86CE, KANJI_SJIS_L1, // 蛎 + 0x920E, KANJI_SJIS_L1, // 鈎 + 0x5283, KANJI_SJIS_L1, // 劃 + 0x5687, KANJI_SJIS_L1, // 嚇 + 0x5404, KANJI_SJIS_L1, // 各 + 0x5ED3, KANJI_SJIS_L1, // 廓 + 0x62E1, KANJI_SJIS_L1, // 拡 + 0x64B9, KANJI_SJIS_L1, // 撹 + 0x683C, KANJI_SJIS_L1, // æ Œ + 0x6838, KANJI_SJIS_L1, // æ ž + 0x6BBB, KANJI_SJIS_L1, // æ®» + 0x7372, KANJI_SJIS_L1, // 獲 + 0x78BA, KANJI_SJIS_L1, // 確 + 0x7A6B, KANJI_SJIS_L1, // ç©« + 0x899A, KANJI_SJIS_L1, // 芚 + 0x89D2, KANJI_SJIS_L1, // 角 + 0x8D6B, KANJI_SJIS_L1, // 赫 + 0x8F03, KANJI_SJIS_L1, // 范 + 0x90ED, KANJI_SJIS_L1, // 郭 + 0x95A3, KANJI_SJIS_L1, // 閣 + 0x9694, KANJI_SJIS_L1, // 隔 + 0x9769, KANJI_SJIS_L1, // 革 + 0x5B66, KANJI_SJIS_L1, // å­Š + 0x5CB3, KANJI_SJIS_L1, // å²³ + 0x697D, KANJI_SJIS_L1, // 楜 + 0x984D, KANJI_SJIS_L1, // 額 + 0x984E, KANJI_SJIS_L1, // 顎 + 0x639B, KANJI_SJIS_L1, // 掛 + 0x7B20, KANJI_SJIS_L1, // 笠 + 0x6A2B, KANJI_SJIS_L1, // æš« + 0x3000, KANJI_SJIS_L1, //   + 0x6A7F, KANJI_SJIS_L1, // æ©¿ + 0x68B6, KANJI_SJIS_L1, // 梶 + 0x9C0D, KANJI_SJIS_L1, // 鰍 + 0x6F5F, KANJI_SJIS_L1, // 期 + 0x5272, KANJI_SJIS_L1, // 割 + 0x559D, KANJI_SJIS_L1, // 喝 + 0x6070, KANJI_SJIS_L1, // 恰 + 0x62EC, KANJI_SJIS_L1, // 括 + 0x6D3B, KANJI_SJIS_L1, // 掻 + 0x6E07, KANJI_SJIS_L1, // 枇 + 0x6ED1, KANJI_SJIS_L1, // 滑 + 0x845B, KANJI_SJIS_L1, // 葛 + 0x8910, KANJI_SJIS_L1, // 耐 + 0x8F44, KANJI_SJIS_L1, // 蜄 + 0x4E14, KANJI_SJIS_L1, // 侔 + 0x9C39, KANJI_SJIS_L1, // é°¹ + 0x53F6, KANJI_SJIS_L1, // 叶 + 0x691B, KANJI_SJIS_L1, // 怛 + 0x6A3A, KANJI_SJIS_L1, // 暺 + 0x9784, KANJI_SJIS_L1, // 鞄 + 0x682A, KANJI_SJIS_L1, // æ ª + 0x515C, KANJI_SJIS_L1, // 兜 + 0x7AC3, KANJI_SJIS_L1, // 竃 + 0x84B2, KANJI_SJIS_L1, // 蒲 + 0x91DC, KANJI_SJIS_L1, // 釜 + 0x938C, KANJI_SJIS_L1, // 鎌 + 0x565B, KANJI_SJIS_L1, // 噛 + 0x9D28, KANJI_SJIS_L1, // 鎚 + 0x6822, KANJI_SJIS_L1, // æ ¢ + 0x8305, KANJI_SJIS_L1, // 茅 + 0x8431, KANJI_SJIS_L1, // 萱 + 0x7CA5, KANJI_SJIS_L1, // ç²¥ + 0x5208, KANJI_SJIS_L1, // 刈 + 0x82C5, KANJI_SJIS_L1, // 苅 + 0x74E6, KANJI_SJIS_L1, // 瓩 + 0x4E7E, KANJI_SJIS_L1, // 也 + 0x4F83, KANJI_SJIS_L1, // 䟃 + 0x51A0, KANJI_SJIS_L1, // 冠 + 0x5BD2, KANJI_SJIS_L1, // 寒 + 0x520A, KANJI_SJIS_L1, // 刊 + 0x52D8, KANJI_SJIS_L1, // 勘 + 0x52E7, KANJI_SJIS_L1, // 勧 + 0x5DFB, KANJI_SJIS_L1, // å·» + 0x559A, KANJI_SJIS_L1, // 喚 + 0x582A, KANJI_SJIS_L1, // å ª + 0x59E6, KANJI_SJIS_L1, // å§Š + 0x5B8C, KANJI_SJIS_L1, // 完 + 0x5B98, KANJI_SJIS_L1, // 官 + 0x5BDB, KANJI_SJIS_L1, // 寛 + 0x5E72, KANJI_SJIS_L1, // å¹² + 0x5E79, KANJI_SJIS_L1, // å¹¹ + 0x60A3, KANJI_SJIS_L1, // 患 + 0x611F, KANJI_SJIS_L1, // 感 + 0x6163, KANJI_SJIS_L1, // 慣 + 0x61BE, KANJI_SJIS_L1, // 憟 + 0x63DB, KANJI_SJIS_L1, // 換 + 0x6562, KANJI_SJIS_L1, // 敢 + 0x67D1, KANJI_SJIS_L1, // 柑 + 0x6853, KANJI_SJIS_L1, // 桓 + 0x68FA, KANJI_SJIS_L1, // 棺 + 0x6B3E, KANJI_SJIS_L1, // 欟 + 0x6B53, KANJI_SJIS_L1, // 歓 + 0x6C57, KANJI_SJIS_L1, // 汗 + 0x6F22, KANJI_SJIS_L1, // 挢 + 0x6F97, KANJI_SJIS_L1, // 柗 + 0x6F45, KANJI_SJIS_L1, // 朅 + 0x74B0, KANJI_SJIS_L1, // 環 + 0x7518, KANJI_SJIS_L1, // 甘 + 0x76E3, KANJI_SJIS_L1, // 監 + 0x770B, KANJI_SJIS_L1, // 看 + 0x7AFF, KANJI_SJIS_L1, // ç«¿ + 0x7BA1, KANJI_SJIS_L1, // 管 + 0x7C21, KANJI_SJIS_L1, // ç°¡ + 0x7DE9, KANJI_SJIS_L1, // ç·© + 0x7F36, KANJI_SJIS_L1, // 猶 + 0x7FF0, KANJI_SJIS_L1, // ç¿° + 0x809D, KANJI_SJIS_L1, // 肝 + 0x8266, KANJI_SJIS_L1, // 艊 + 0x839E, KANJI_SJIS_L1, // 莞 + 0x89B3, KANJI_SJIS_L1, // 芳 + 0x8ACC, KANJI_SJIS_L1, // 諌 + 0x8CAB, KANJI_SJIS_L1, // 貫 + 0x9084, KANJI_SJIS_L1, // 還 + 0x9451, KANJI_SJIS_L1, // 鑑 + 0x9593, KANJI_SJIS_L1, // 間 + 0x9591, KANJI_SJIS_L1, // 閑 + 0x95A2, KANJI_SJIS_L1, // 関 + 0x9665, KANJI_SJIS_L1, // 陥 + 0x97D3, KANJI_SJIS_L1, // 韓 + 0x9928, KANJI_SJIS_L1, // 通 + 0x8218, KANJI_SJIS_L1, // 舘 + 0x4E38, KANJI_SJIS_L1, // äžž + 0x542B, KANJI_SJIS_L1, // 含 + 0x5CB8, KANJI_SJIS_L1, // 岞 + 0x5DCC, KANJI_SJIS_L1, // 巌 + 0x73A9, KANJI_SJIS_L1, // 玩 + 0x764C, KANJI_SJIS_L1, // 癌 + 0x773C, KANJI_SJIS_L1, // 県 + 0x5CA9, KANJI_SJIS_L1, // 岩 + 0x7FEB, KANJI_SJIS_L1, // ç¿« + 0x8D0B, KANJI_SJIS_L1, // 莋 + 0x96C1, KANJI_SJIS_L1, // 雁 + 0x9811, KANJI_SJIS_L1, // 頑 + 0x9854, KANJI_SJIS_L1, // 顔 + 0x9858, KANJI_SJIS_L1, // 願 + 0x4F01, KANJI_SJIS_L1, // 䌁 + 0x4F0E, KANJI_SJIS_L1, // 䌎 + 0x5371, KANJI_SJIS_L1, // 危 + 0x559C, KANJI_SJIS_L1, // 喜 + 0x5668, KANJI_SJIS_L1, // 噚 + 0x57FA, KANJI_SJIS_L1, // 基 + 0x5947, KANJI_SJIS_L1, // 奇 + 0x5B09, KANJI_SJIS_L1, // 嬉 + 0x5BC4, KANJI_SJIS_L1, // 寄 + 0x5C90, KANJI_SJIS_L1, // 岐 + 0x5E0C, KANJI_SJIS_L1, // 垌 + 0x5E7E, KANJI_SJIS_L1, // 幟 + 0x5FCC, KANJI_SJIS_L1, // 忌 + 0x63EE, KANJI_SJIS_L1, // 揮 + 0x673A, KANJI_SJIS_L1, // 机 + 0x65D7, KANJI_SJIS_L1, // 旗 + 0x65E2, KANJI_SJIS_L1, // 既 + 0x671F, KANJI_SJIS_L1, // 期 + 0x68CB, KANJI_SJIS_L1, // 棋 + 0x68C4, KANJI_SJIS_L1, // 棄 + 0x6A5F, KANJI_SJIS_L1, // 機 + 0x5E30, KANJI_SJIS_L1, // åž° + 0x6BC5, KANJI_SJIS_L1, // 毅 + 0x6C17, KANJI_SJIS_L1, // 気 + 0x6C7D, KANJI_SJIS_L1, // 汜 + 0x757F, KANJI_SJIS_L1, // 畿 + 0x7948, KANJI_SJIS_L1, // 祈 + 0x5B63, KANJI_SJIS_L1, // å­£ + 0x7A00, KANJI_SJIS_L1, // 繀 + 0x7D00, KANJI_SJIS_L1, // 简 + 0x5FBD, KANJI_SJIS_L1, // 埜 + 0x898F, KANJI_SJIS_L1, // 芏 + 0x8A18, KANJI_SJIS_L1, // 蚘 + 0x8CB4, KANJI_SJIS_L1, // 貎 + 0x8D77, KANJI_SJIS_L1, // èµ· + 0x8ECC, KANJI_SJIS_L1, // 軌 + 0x8F1D, KANJI_SJIS_L1, // 茝 + 0x98E2, KANJI_SJIS_L1, // 飢 + 0x9A0E, KANJI_SJIS_L1, // 階 + 0x9B3C, KANJI_SJIS_L1, // 鬌 + 0x4E80, KANJI_SJIS_L1, // 亀 + 0x507D, KANJI_SJIS_L1, // 停 + 0x5100, KANJI_SJIS_L1, // 儀 + 0x5993, KANJI_SJIS_L1, // 劓 + 0x5B9C, KANJI_SJIS_L1, // 宜 + 0x622F, KANJI_SJIS_L1, // 戯 + 0x6280, KANJI_SJIS_L1, // 技 + 0x64EC, KANJI_SJIS_L1, // 擬 + 0x6B3A, KANJI_SJIS_L1, // 欺 + 0x72A0, KANJI_SJIS_L1, // 犠 + 0x7591, KANJI_SJIS_L1, // 疑 + 0x7947, KANJI_SJIS_L1, // 祇 + 0x7FA9, KANJI_SJIS_L1, // 矩 + 0x87FB, KANJI_SJIS_L1, // 蟻 + 0x8ABC, KANJI_SJIS_L1, // 誌 + 0x8B70, KANJI_SJIS_L1, // è­° + 0x63AC, KANJI_SJIS_L1, // 掬 + 0x83CA, KANJI_SJIS_L1, // 菊 + 0x97A0, KANJI_SJIS_L1, // 鞠 + 0x5409, KANJI_SJIS_L1, // 吉 + 0x5403, KANJI_SJIS_L1, // 吃 + 0x55AB, KANJI_SJIS_L1, // 喫 + 0x6854, KANJI_SJIS_L1, // 桔 + 0x6A58, KANJI_SJIS_L1, // 橘 + 0x8A70, KANJI_SJIS_L1, // è©° + 0x7827, KANJI_SJIS_L1, // ç § + 0x6775, KANJI_SJIS_L1, // 杵 + 0x9ECD, KANJI_SJIS_L1, // 黍 + 0x5374, KANJI_SJIS_L1, // 华 + 0x5BA2, KANJI_SJIS_L1, // 客 + 0x811A, KANJI_SJIS_L1, // 脚 + 0x8650, KANJI_SJIS_L1, // 虐 + 0x9006, KANJI_SJIS_L1, // 逆 + 0x4E18, KANJI_SJIS_L1, // 䞘 + 0x4E45, KANJI_SJIS_L1, // 久 + 0x4EC7, KANJI_SJIS_L1, // 仇 + 0x4F11, KANJI_SJIS_L1, // 䌑 + 0x53CA, KANJI_SJIS_L1, // 及 + 0x5438, KANJI_SJIS_L1, // 吞 + 0x5BAE, KANJI_SJIS_L1, // å®® + 0x5F13, KANJI_SJIS_L1, // 匓 + 0x6025, KANJI_SJIS_L1, // 急 + 0x6551, KANJI_SJIS_L1, // 救 + 0x3000, KANJI_SJIS_L1, //   + 0x673D, KANJI_SJIS_L1, // 朜 + 0x6C42, KANJI_SJIS_L1, // 求 + 0x6C72, KANJI_SJIS_L1, // æ±² + 0x6CE3, KANJI_SJIS_L1, // æ³£ + 0x7078, KANJI_SJIS_L1, // 灞 + 0x7403, KANJI_SJIS_L1, // 球 + 0x7A76, KANJI_SJIS_L1, // ç©¶ + 0x7AAE, KANJI_SJIS_L1, // 窮 + 0x7B08, KANJI_SJIS_L1, // 笈 + 0x7D1A, KANJI_SJIS_L1, // 箚 + 0x7CFE, KANJI_SJIS_L1, // 糟 + 0x7D66, KANJI_SJIS_L1, // 絊 + 0x65E7, KANJI_SJIS_L1, // 旧 + 0x725B, KANJI_SJIS_L1, // 牛 + 0x53BB, KANJI_SJIS_L1, // 去 + 0x5C45, KANJI_SJIS_L1, // 居 + 0x5DE8, KANJI_SJIS_L1, // å·š + 0x62D2, KANJI_SJIS_L1, // 拒 + 0x62E0, KANJI_SJIS_L1, // 拠 + 0x6319, KANJI_SJIS_L1, // 挙 + 0x6E20, KANJI_SJIS_L1, // æž  + 0x865A, KANJI_SJIS_L1, // 虚 + 0x8A31, KANJI_SJIS_L1, // èš± + 0x8DDD, KANJI_SJIS_L1, // 距 + 0x92F8, KANJI_SJIS_L1, // 鋾 + 0x6F01, KANJI_SJIS_L1, // 持 + 0x79A6, KANJI_SJIS_L1, // 犊 + 0x9B5A, KANJI_SJIS_L1, // 魚 + 0x4EA8, KANJI_SJIS_L1, // 亚 + 0x4EAB, KANJI_SJIS_L1, // 享 + 0x4EAC, KANJI_SJIS_L1, // 京 + 0x4F9B, KANJI_SJIS_L1, // 䟛 + 0x4FA0, KANJI_SJIS_L1, // 䟠 + 0x50D1, KANJI_SJIS_L1, // 僑 + 0x5147, KANJI_SJIS_L1, // 兇 + 0x7AF6, KANJI_SJIS_L1, // ç«¶ + 0x5171, KANJI_SJIS_L1, // 共 + 0x51F6, KANJI_SJIS_L1, // 凶 + 0x5354, KANJI_SJIS_L1, // 協 + 0x5321, KANJI_SJIS_L1, // 匡 + 0x537F, KANJI_SJIS_L1, // 卿 + 0x53EB, KANJI_SJIS_L1, // 叫 + 0x55AC, KANJI_SJIS_L1, // 喬 + 0x5883, KANJI_SJIS_L1, // 境 + 0x5CE1, KANJI_SJIS_L1, // 峡 + 0x5F37, KANJI_SJIS_L1, // 匷 + 0x5F4A, KANJI_SJIS_L1, // 圊 + 0x602F, KANJI_SJIS_L1, // 怯 + 0x6050, KANJI_SJIS_L1, // 恐 + 0x606D, KANJI_SJIS_L1, // 恭 + 0x631F, KANJI_SJIS_L1, // 挟 + 0x6559, KANJI_SJIS_L1, // 教 + 0x6A4B, KANJI_SJIS_L1, // 橋 + 0x6CC1, KANJI_SJIS_L1, // 況 + 0x72C2, KANJI_SJIS_L1, // 狂 + 0x72ED, KANJI_SJIS_L1, // 狭 + 0x77EF, KANJI_SJIS_L1, // 矯 + 0x80F8, KANJI_SJIS_L1, // 胞 + 0x8105, KANJI_SJIS_L1, // 脅 + 0x8208, KANJI_SJIS_L1, // 興 + 0x854E, KANJI_SJIS_L1, // 蕎 + 0x90F7, KANJI_SJIS_L1, // 郷 + 0x93E1, KANJI_SJIS_L1, // 鏡 + 0x97FF, KANJI_SJIS_L1, // 響 + 0x9957, KANJI_SJIS_L1, // 饗 + 0x9A5A, KANJI_SJIS_L1, // 驚 + 0x4EF0, KANJI_SJIS_L1, // ä»° + 0x51DD, KANJI_SJIS_L1, // 凝 + 0x5C2D, KANJI_SJIS_L1, // å°­ + 0x6681, KANJI_SJIS_L1, // 暁 + 0x696D, KANJI_SJIS_L1, // 業 + 0x5C40, KANJI_SJIS_L1, // 局 + 0x66F2, KANJI_SJIS_L1, // 曲 + 0x6975, KANJI_SJIS_L1, // 極 + 0x7389, KANJI_SJIS_L1, // 玉 + 0x6850, KANJI_SJIS_L1, // 桐 + 0x7C81, KANJI_SJIS_L1, // 粁 + 0x50C5, KANJI_SJIS_L1, // 僅 + 0x52E4, KANJI_SJIS_L1, // å‹€ + 0x5747, KANJI_SJIS_L1, // 均 + 0x5DFE, KANJI_SJIS_L1, // å·Ÿ + 0x9326, KANJI_SJIS_L1, // 錩 + 0x65A4, KANJI_SJIS_L1, // æ–€ + 0x6B23, KANJI_SJIS_L1, // 欣 + 0x6B3D, KANJI_SJIS_L1, // 欜 + 0x7434, KANJI_SJIS_L1, // 琎 + 0x7981, KANJI_SJIS_L1, // 犁 + 0x79BD, KANJI_SJIS_L1, // 犜 + 0x7B4B, KANJI_SJIS_L1, // 筋 + 0x7DCA, KANJI_SJIS_L1, // 緊 + 0x82B9, KANJI_SJIS_L1, // 芹 + 0x83CC, KANJI_SJIS_L1, // 菌 + 0x887F, KANJI_SJIS_L1, // è¡¿ + 0x895F, KANJI_SJIS_L1, // 襟 + 0x8B39, KANJI_SJIS_L1, // 謹 + 0x8FD1, KANJI_SJIS_L1, // 近 + 0x91D1, KANJI_SJIS_L1, // 金 + 0x541F, KANJI_SJIS_L1, // 吟 + 0x9280, KANJI_SJIS_L1, // 銀 + 0x4E5D, KANJI_SJIS_L1, // 九 + 0x5036, KANJI_SJIS_L1, // 倶 + 0x53E5, KANJI_SJIS_L1, // 句 + 0x533A, KANJI_SJIS_L1, // 区 + 0x72D7, KANJI_SJIS_L1, // 狗 + 0x7396, KANJI_SJIS_L1, // 玖 + 0x77E9, KANJI_SJIS_L1, // 矩 + 0x82E6, KANJI_SJIS_L1, // 苊 + 0x8EAF, KANJI_SJIS_L1, // 躯 + 0x99C6, KANJI_SJIS_L1, // 駆 + 0x99C8, KANJI_SJIS_L1, // 駈 + 0x99D2, KANJI_SJIS_L1, // 駒 + 0x5177, KANJI_SJIS_L1, // 具 + 0x611A, KANJI_SJIS_L1, // 愚 + 0x865E, KANJI_SJIS_L1, // 虞 + 0x55B0, KANJI_SJIS_L1, // 喰 + 0x7A7A, KANJI_SJIS_L1, // 空 + 0x5076, KANJI_SJIS_L1, // 偶 + 0x5BD3, KANJI_SJIS_L1, // 寓 + 0x9047, KANJI_SJIS_L1, // 遇 + 0x9685, KANJI_SJIS_L1, // 隅 + 0x4E32, KANJI_SJIS_L1, // äž² + 0x6ADB, KANJI_SJIS_L1, // 櫛 + 0x91E7, KANJI_SJIS_L1, // 釧 + 0x5C51, KANJI_SJIS_L1, // 屑 + 0x5C48, KANJI_SJIS_L1, // 屈 + 0x6398, KANJI_SJIS_L1, // 掘 + 0x7A9F, KANJI_SJIS_L1, // 窟 + 0x6C93, KANJI_SJIS_L1, // 沓 + 0x9774, KANJI_SJIS_L1, // 靎 + 0x8F61, KANJI_SJIS_L1, // 蜡 + 0x7AAA, KANJI_SJIS_L1, // 窪 + 0x718A, KANJI_SJIS_L1, // 熊 + 0x9688, KANJI_SJIS_L1, // 隈 + 0x7C82, KANJI_SJIS_L1, // 粂 + 0x6817, KANJI_SJIS_L1, // 栗 + 0x7E70, KANJI_SJIS_L1, // ç¹° + 0x6851, KANJI_SJIS_L1, // 桑 + 0x936C, KANJI_SJIS_L1, // 鍬 + 0x52F2, KANJI_SJIS_L1, // 勲 + 0x541B, KANJI_SJIS_L1, // 君 + 0x85AB, KANJI_SJIS_L1, // 薫 + 0x8A13, KANJI_SJIS_L1, // èš“ + 0x7FA4, KANJI_SJIS_L1, // 矀 + 0x8ECD, KANJI_SJIS_L1, // 軍 + 0x90E1, KANJI_SJIS_L1, // 郡 + 0x5366, KANJI_SJIS_L1, // 半 + 0x8888, KANJI_SJIS_L1, // 袈 + 0x7941, KANJI_SJIS_L1, // 祁 + 0x4FC2, KANJI_SJIS_L1, // 係 + 0x50BE, KANJI_SJIS_L1, // 傟 + 0x5211, KANJI_SJIS_L1, // 刑 + 0x5144, KANJI_SJIS_L1, // 兄 + 0x5553, KANJI_SJIS_L1, // 啓 + 0x572D, KANJI_SJIS_L1, // 圭 + 0x73EA, KANJI_SJIS_L1, // 珪 + 0x578B, KANJI_SJIS_L1, // 型 + 0x5951, KANJI_SJIS_L1, // 契 + 0x5F62, KANJI_SJIS_L1, // 圢 + 0x5F84, KANJI_SJIS_L1, // 埄 + 0x6075, KANJI_SJIS_L1, // 恵 + 0x6176, KANJI_SJIS_L1, // 慶 + 0x6167, KANJI_SJIS_L1, // 慧 + 0x61A9, KANJI_SJIS_L1, // 憩 + 0x63B2, KANJI_SJIS_L1, // 掲 + 0x643A, KANJI_SJIS_L1, // 携 + 0x656C, KANJI_SJIS_L1, // 敬 + 0x666F, KANJI_SJIS_L1, // 景 + 0x6842, KANJI_SJIS_L1, // 桂 + 0x6E13, KANJI_SJIS_L1, // æž“ + 0x7566, KANJI_SJIS_L1, // 畩 + 0x7A3D, KANJI_SJIS_L1, // çšœ + 0x7CFB, KANJI_SJIS_L1, // ç³» + 0x7D4C, KANJI_SJIS_L1, // 経 + 0x7D99, KANJI_SJIS_L1, // 継 + 0x7E4B, KANJI_SJIS_L1, // 繋 + 0x7F6B, KANJI_SJIS_L1, // 眫 + 0x830E, KANJI_SJIS_L1, // 茎 + 0x834A, KANJI_SJIS_L1, // 荊 + 0x86CD, KANJI_SJIS_L1, // 蛍 + 0x8A08, KANJI_SJIS_L1, // 蚈 + 0x8A63, KANJI_SJIS_L1, // è©£ + 0x8B66, KANJI_SJIS_L1, // è­Š + 0x8EFD, KANJI_SJIS_L1, // 軜 + 0x981A, KANJI_SJIS_L1, // 頚 + 0x9D8F, KANJI_SJIS_L1, // 鶏 + 0x82B8, KANJI_SJIS_L1, // 芞 + 0x8FCE, KANJI_SJIS_L1, // 迎 + 0x9BE8, KANJI_SJIS_L1, // 鯚 + 0x3000, KANJI_SJIS_L1, //   + 0x5287, KANJI_SJIS_L1, // 劇 + 0x621F, KANJI_SJIS_L1, // 戟 + 0x6483, KANJI_SJIS_L1, // 撃 + 0x6FC0, KANJI_SJIS_L1, // 激 + 0x9699, KANJI_SJIS_L1, // 隙 + 0x6841, KANJI_SJIS_L1, // 桁 + 0x5091, KANJI_SJIS_L1, // 傑 + 0x6B20, KANJI_SJIS_L1, // 欠 + 0x6C7A, KANJI_SJIS_L1, // 決 + 0x6F54, KANJI_SJIS_L1, // 朔 + 0x7A74, KANJI_SJIS_L1, // 穎 + 0x7D50, KANJI_SJIS_L1, // 結 + 0x8840, KANJI_SJIS_L1, // 血 + 0x8A23, KANJI_SJIS_L1, // 蚣 + 0x6708, KANJI_SJIS_L1, // 月 + 0x4EF6, KANJI_SJIS_L1, // ä»¶ + 0x5039, KANJI_SJIS_L1, // 倹 + 0x5026, KANJI_SJIS_L1, // 倊 + 0x5065, KANJI_SJIS_L1, // 健 + 0x517C, KANJI_SJIS_L1, // å…Œ + 0x5238, KANJI_SJIS_L1, // 刞 + 0x5263, KANJI_SJIS_L1, // 剣 + 0x55A7, KANJI_SJIS_L1, // 喧 + 0x570F, KANJI_SJIS_L1, // 圏 + 0x5805, KANJI_SJIS_L1, // 堅 + 0x5ACC, KANJI_SJIS_L1, // 嫌 + 0x5EFA, KANJI_SJIS_L1, // 建 + 0x61B2, KANJI_SJIS_L1, // 憲 + 0x61F8, KANJI_SJIS_L1, // 懞 + 0x62F3, KANJI_SJIS_L1, // 拳 + 0x6372, KANJI_SJIS_L1, // 捲 + 0x691C, KANJI_SJIS_L1, // 怜 + 0x6A29, KANJI_SJIS_L1, // æš© + 0x727D, KANJI_SJIS_L1, // 牜 + 0x72AC, KANJI_SJIS_L1, // 犬 + 0x732E, KANJI_SJIS_L1, // 献 + 0x7814, KANJI_SJIS_L1, // 研 + 0x786F, KANJI_SJIS_L1, // 硯 + 0x7D79, KANJI_SJIS_L1, // çµ¹ + 0x770C, KANJI_SJIS_L1, // 県 + 0x80A9, KANJI_SJIS_L1, // 肩 + 0x898B, KANJI_SJIS_L1, // 芋 + 0x8B19, KANJI_SJIS_L1, // 謙 + 0x8CE2, KANJI_SJIS_L1, // è³¢ + 0x8ED2, KANJI_SJIS_L1, // 軒 + 0x9063, KANJI_SJIS_L1, // 遣 + 0x9375, KANJI_SJIS_L1, // 鍵 + 0x967A, KANJI_SJIS_L1, // 険 + 0x9855, KANJI_SJIS_L1, // 顕 + 0x9A13, KANJI_SJIS_L1, // 鹓 + 0x9E78, KANJI_SJIS_L1, // 鹞 + 0x5143, KANJI_SJIS_L1, // 元 + 0x539F, KANJI_SJIS_L1, // 原 + 0x53B3, KANJI_SJIS_L1, // 厳 + 0x5E7B, KANJI_SJIS_L1, // å¹» + 0x5F26, KANJI_SJIS_L1, // 匊 + 0x6E1B, KANJI_SJIS_L1, // æž› + 0x6E90, KANJI_SJIS_L1, // 源 + 0x7384, KANJI_SJIS_L1, // 玄 + 0x73FE, KANJI_SJIS_L1, // 珟 + 0x7D43, KANJI_SJIS_L1, // 絃 + 0x8237, KANJI_SJIS_L1, // 舷 + 0x8A00, KANJI_SJIS_L1, // 蚀 + 0x8AFA, KANJI_SJIS_L1, // 諺 + 0x9650, KANJI_SJIS_L1, // 限 + 0x4E4E, KANJI_SJIS_L1, // 乎 + 0x500B, KANJI_SJIS_L1, // 個 + 0x53E4, KANJI_SJIS_L1, // 叀 + 0x547C, KANJI_SJIS_L1, // 呌 + 0x56FA, KANJI_SJIS_L1, // 固 + 0x59D1, KANJI_SJIS_L1, // 姑 + 0x5B64, KANJI_SJIS_L1, // å­€ + 0x5DF1, KANJI_SJIS_L1, // å·± + 0x5EAB, KANJI_SJIS_L1, // 庫 + 0x5F27, KANJI_SJIS_L1, // 匧 + 0x6238, KANJI_SJIS_L1, // 戞 + 0x6545, KANJI_SJIS_L1, // 故 + 0x67AF, KANJI_SJIS_L1, // 枯 + 0x6E56, KANJI_SJIS_L1, // 湖 + 0x72D0, KANJI_SJIS_L1, // 狐 + 0x7CCA, KANJI_SJIS_L1, // 糊 + 0x88B4, KANJI_SJIS_L1, // 袎 + 0x80A1, KANJI_SJIS_L1, // 股 + 0x80E1, KANJI_SJIS_L1, // 胡 + 0x83F0, KANJI_SJIS_L1, // 菰 + 0x864E, KANJI_SJIS_L1, // 虎 + 0x8A87, KANJI_SJIS_L1, // 誇 + 0x8DE8, KANJI_SJIS_L1, // è·š + 0x9237, KANJI_SJIS_L1, // 鈷 + 0x96C7, KANJI_SJIS_L1, // 雇 + 0x9867, KANJI_SJIS_L1, // é¡§ + 0x9F13, KANJI_SJIS_L1, // 錓 + 0x4E94, KANJI_SJIS_L1, // 五 + 0x4E92, KANJI_SJIS_L1, // 互 + 0x4F0D, KANJI_SJIS_L1, // 䌍 + 0x5348, KANJI_SJIS_L1, // 午 + 0x5449, KANJI_SJIS_L1, // 呉 + 0x543E, KANJI_SJIS_L1, // 吟 + 0x5A2F, KANJI_SJIS_L1, // 嚯 + 0x5F8C, KANJI_SJIS_L1, // 埌 + 0x5FA1, KANJI_SJIS_L1, // 埡 + 0x609F, KANJI_SJIS_L1, // 悟 + 0x68A7, KANJI_SJIS_L1, // 梧 + 0x6A8E, KANJI_SJIS_L1, // 檎 + 0x745A, KANJI_SJIS_L1, // 瑚 + 0x7881, KANJI_SJIS_L1, // 碁 + 0x8A9E, KANJI_SJIS_L1, // 語 + 0x8AA4, KANJI_SJIS_L1, // 誀 + 0x8B77, KANJI_SJIS_L1, // è­· + 0x9190, KANJI_SJIS_L1, // 醐 + 0x4E5E, KANJI_SJIS_L1, // 乞 + 0x9BC9, KANJI_SJIS_L1, // 鯉 + 0x4EA4, KANJI_SJIS_L1, // 亀 + 0x4F7C, KANJI_SJIS_L1, // 䜌 + 0x4FAF, KANJI_SJIS_L1, // 䟯 + 0x5019, KANJI_SJIS_L1, // 候 + 0x5016, KANJI_SJIS_L1, // 倖 + 0x5149, KANJI_SJIS_L1, // 光 + 0x516C, KANJI_SJIS_L1, // 公 + 0x529F, KANJI_SJIS_L1, // 功 + 0x52B9, KANJI_SJIS_L1, // 効 + 0x52FE, KANJI_SJIS_L1, // 募 + 0x539A, KANJI_SJIS_L1, // 厚 + 0x53E3, KANJI_SJIS_L1, // 口 + 0x5411, KANJI_SJIS_L1, // 向 + 0x540E, KANJI_SJIS_L1, // 后 + 0x5589, KANJI_SJIS_L1, // 喉 + 0x5751, KANJI_SJIS_L1, // 坑 + 0x57A2, KANJI_SJIS_L1, // 垢 + 0x597D, KANJI_SJIS_L1, // 奜 + 0x5B54, KANJI_SJIS_L1, // 孔 + 0x5B5D, KANJI_SJIS_L1, // 孝 + 0x5B8F, KANJI_SJIS_L1, // 宏 + 0x5DE5, KANJI_SJIS_L1, // å·¥ + 0x5DE7, KANJI_SJIS_L1, // å·§ + 0x5DF7, KANJI_SJIS_L1, // å·· + 0x5E78, KANJI_SJIS_L1, // 幞 + 0x5E83, KANJI_SJIS_L1, // 広 + 0x5E9A, KANJI_SJIS_L1, // 庚 + 0x5EB7, KANJI_SJIS_L1, // 康 + 0x5F18, KANJI_SJIS_L1, // 匘 + 0x6052, KANJI_SJIS_L1, // 恒 + 0x614C, KANJI_SJIS_L1, // 慌 + 0x6297, KANJI_SJIS_L1, // 抗 + 0x62D8, KANJI_SJIS_L1, // 拘 + 0x63A7, KANJI_SJIS_L1, // 控 + 0x653B, KANJI_SJIS_L1, // 攻 + 0x6602, KANJI_SJIS_L1, // 昂 + 0x6643, KANJI_SJIS_L1, // 晃 + 0x66F4, KANJI_SJIS_L1, // 曎 + 0x676D, KANJI_SJIS_L1, // 杭 + 0x6821, KANJI_SJIS_L1, // æ ¡ + 0x6897, KANJI_SJIS_L1, // 梗 + 0x69CB, KANJI_SJIS_L1, // 構 + 0x6C5F, KANJI_SJIS_L1, // 江 + 0x6D2A, KANJI_SJIS_L1, // 措 + 0x6D69, KANJI_SJIS_L1, // 浩 + 0x6E2F, KANJI_SJIS_L1, // 枯 + 0x6E9D, KANJI_SJIS_L1, // 溝 + 0x7532, KANJI_SJIS_L1, // 甲 + 0x7687, KANJI_SJIS_L1, // 皇 + 0x786C, KANJI_SJIS_L1, // 硬 + 0x7A3F, KANJI_SJIS_L1, // çš¿ + 0x7CE0, KANJI_SJIS_L1, // ç³  + 0x7D05, KANJI_SJIS_L1, // 箅 + 0x7D18, KANJI_SJIS_L1, // 玘 + 0x7D5E, KANJI_SJIS_L1, // 絞 + 0x7DB1, KANJI_SJIS_L1, // ç¶± + 0x8015, KANJI_SJIS_L1, // 耕 + 0x8003, KANJI_SJIS_L1, // 考 + 0x80AF, KANJI_SJIS_L1, // 肯 + 0x80B1, KANJI_SJIS_L1, // 肱 + 0x8154, KANJI_SJIS_L1, // 腔 + 0x818F, KANJI_SJIS_L1, // 膏 + 0x822A, KANJI_SJIS_L1, // 航 + 0x8352, KANJI_SJIS_L1, // 荒 + 0x884C, KANJI_SJIS_L1, // 行 + 0x8861, KANJI_SJIS_L1, // è¡¡ + 0x8B1B, KANJI_SJIS_L1, // 講 + 0x8CA2, KANJI_SJIS_L1, // è²¢ + 0x8CFC, KANJI_SJIS_L1, // 賌 + 0x90CA, KANJI_SJIS_L1, // 郊 + 0x9175, KANJI_SJIS_L1, // 酵 + 0x9271, KANJI_SJIS_L1, // 鉱 + 0x783F, KANJI_SJIS_L1, // ç ¿ + 0x92FC, KANJI_SJIS_L1, // 鋌 + 0x95A4, KANJI_SJIS_L1, // é–€ + 0x964D, KANJI_SJIS_L1, // 降 + 0x3000, KANJI_SJIS_L1, //   + 0x9805, KANJI_SJIS_L1, // 項 + 0x9999, KANJI_SJIS_L1, // 驙 + 0x9AD8, KANJI_SJIS_L1, // 高 + 0x9D3B, KANJI_SJIS_L1, // 鎻 + 0x525B, KANJI_SJIS_L1, // 剛 + 0x52AB, KANJI_SJIS_L1, // 劫 + 0x53F7, KANJI_SJIS_L1, // 号 + 0x5408, KANJI_SJIS_L1, // 合 + 0x58D5, KANJI_SJIS_L1, // 壕 + 0x62F7, KANJI_SJIS_L1, // 拷 + 0x6FE0, KANJI_SJIS_L1, // æ¿  + 0x8C6A, KANJI_SJIS_L1, // 豪 + 0x8F5F, KANJI_SJIS_L1, // 蜟 + 0x9EB9, KANJI_SJIS_L1, // 麹 + 0x514B, KANJI_SJIS_L1, // 克 + 0x523B, KANJI_SJIS_L1, // 刻 + 0x544A, KANJI_SJIS_L1, // 告 + 0x56FD, KANJI_SJIS_L1, // 囜 + 0x7A40, KANJI_SJIS_L1, // 穀 + 0x9177, KANJI_SJIS_L1, // 酷 + 0x9D60, KANJI_SJIS_L1, // éµ  + 0x9ED2, KANJI_SJIS_L1, // 黒 + 0x7344, KANJI_SJIS_L1, // 獄 + 0x6F09, KANJI_SJIS_L1, // 按 + 0x8170, KANJI_SJIS_L1, // 腰 + 0x7511, KANJI_SJIS_L1, // 甑 + 0x5FFD, KANJI_SJIS_L1, // 応 + 0x60DA, KANJI_SJIS_L1, // 惚 + 0x9AA8, KANJI_SJIS_L1, // 骚 + 0x72DB, KANJI_SJIS_L1, // 狛 + 0x8FBC, KANJI_SJIS_L1, // 蟌 + 0x6B64, KANJI_SJIS_L1, // æ­€ + 0x9803, KANJI_SJIS_L1, // 頃 + 0x4ECA, KANJI_SJIS_L1, // 今 + 0x56F0, KANJI_SJIS_L1, // 困 + 0x5764, KANJI_SJIS_L1, // 址 + 0x58BE, KANJI_SJIS_L1, // 墟 + 0x5A5A, KANJI_SJIS_L1, // 婚 + 0x6068, KANJI_SJIS_L1, // 恚 + 0x61C7, KANJI_SJIS_L1, // 懇 + 0x660F, KANJI_SJIS_L1, // 昏 + 0x6606, KANJI_SJIS_L1, // 昆 + 0x6839, KANJI_SJIS_L1, // æ ¹ + 0x68B1, KANJI_SJIS_L1, // 梱 + 0x6DF7, KANJI_SJIS_L1, // æ·· + 0x75D5, KANJI_SJIS_L1, // 痕 + 0x7D3A, KANJI_SJIS_L1, // 玺 + 0x826E, KANJI_SJIS_L1, // 艮 + 0x9B42, KANJI_SJIS_L1, // 魂 + 0x4E9B, KANJI_SJIS_L1, // 些 + 0x4F50, KANJI_SJIS_L1, // 䜐 + 0x53C9, KANJI_SJIS_L1, // 叉 + 0x5506, KANJI_SJIS_L1, // 唆 + 0x5D6F, KANJI_SJIS_L1, // 嵯 + 0x5DE6, KANJI_SJIS_L1, // å·Š + 0x5DEE, KANJI_SJIS_L1, // å·® + 0x67FB, KANJI_SJIS_L1, // 査 + 0x6C99, KANJI_SJIS_L1, // 沙 + 0x7473, KANJI_SJIS_L1, // 瑳 + 0x7802, KANJI_SJIS_L1, // 砂 + 0x8A50, KANJI_SJIS_L1, // 詐 + 0x9396, KANJI_SJIS_L1, // 鎖 + 0x88DF, KANJI_SJIS_L1, // 裟 + 0x5750, KANJI_SJIS_L1, // 坐 + 0x5EA7, KANJI_SJIS_L1, // 座 + 0x632B, KANJI_SJIS_L1, // 挫 + 0x50B5, KANJI_SJIS_L1, // 債 + 0x50AC, KANJI_SJIS_L1, // 催 + 0x518D, KANJI_SJIS_L1, // 再 + 0x6700, KANJI_SJIS_L1, // 最 + 0x54C9, KANJI_SJIS_L1, // 哉 + 0x585E, KANJI_SJIS_L1, // 塞 + 0x59BB, KANJI_SJIS_L1, // 劻 + 0x5BB0, KANJI_SJIS_L1, // å®° + 0x5F69, KANJI_SJIS_L1, // 圩 + 0x624D, KANJI_SJIS_L1, // 才 + 0x63A1, KANJI_SJIS_L1, // 採 + 0x683D, KANJI_SJIS_L1, // æ œ + 0x6B73, KANJI_SJIS_L1, // æ­³ + 0x6E08, KANJI_SJIS_L1, // 枈 + 0x707D, KANJI_SJIS_L1, // 灜 + 0x91C7, KANJI_SJIS_L1, // 采 + 0x7280, KANJI_SJIS_L1, // 犀 + 0x7815, KANJI_SJIS_L1, // 砕 + 0x7826, KANJI_SJIS_L1, // ç Š + 0x796D, KANJI_SJIS_L1, // 祭 + 0x658E, KANJI_SJIS_L1, // 斎 + 0x7D30, KANJI_SJIS_L1, // 现 + 0x83DC, KANJI_SJIS_L1, // 菜 + 0x88C1, KANJI_SJIS_L1, // 裁 + 0x8F09, KANJI_SJIS_L1, // 茉 + 0x969B, KANJI_SJIS_L1, // 際 + 0x5264, KANJI_SJIS_L1, // 剀 + 0x5728, KANJI_SJIS_L1, // 圚 + 0x6750, KANJI_SJIS_L1, // 材 + 0x7F6A, KANJI_SJIS_L1, // 眪 + 0x8CA1, KANJI_SJIS_L1, // 財 + 0x51B4, KANJI_SJIS_L1, // 冎 + 0x5742, KANJI_SJIS_L1, // 坂 + 0x962A, KANJI_SJIS_L1, // 阪 + 0x583A, KANJI_SJIS_L1, // å º + 0x698A, KANJI_SJIS_L1, // 把 + 0x80B4, KANJI_SJIS_L1, // 肎 + 0x54B2, KANJI_SJIS_L1, // 咲 + 0x5D0E, KANJI_SJIS_L1, // 厎 + 0x57FC, KANJI_SJIS_L1, // 埌 + 0x7895, KANJI_SJIS_L1, // 碕 + 0x9DFA, KANJI_SJIS_L1, // é·º + 0x4F5C, KANJI_SJIS_L1, // 䜜 + 0x524A, KANJI_SJIS_L1, // 削 + 0x548B, KANJI_SJIS_L1, // 咋 + 0x643E, KANJI_SJIS_L1, // 搟 + 0x6628, KANJI_SJIS_L1, // 昚 + 0x6714, KANJI_SJIS_L1, // 朔 + 0x67F5, KANJI_SJIS_L1, // 柵 + 0x7A84, KANJI_SJIS_L1, // 窄 + 0x7B56, KANJI_SJIS_L1, // 策 + 0x7D22, KANJI_SJIS_L1, // 玢 + 0x932F, KANJI_SJIS_L1, // 錯 + 0x685C, KANJI_SJIS_L1, // 桜 + 0x9BAD, KANJI_SJIS_L1, // é®­ + 0x7B39, KANJI_SJIS_L1, // 笹 + 0x5319, KANJI_SJIS_L1, // 匙 + 0x518A, KANJI_SJIS_L1, // 冊 + 0x5237, KANJI_SJIS_L1, // 刷 + 0x5BDF, KANJI_SJIS_L1, // 察 + 0x62F6, KANJI_SJIS_L1, // 拶 + 0x64AE, KANJI_SJIS_L1, // 撮 + 0x64E6, KANJI_SJIS_L1, // 擊 + 0x672D, KANJI_SJIS_L1, // 札 + 0x6BBA, KANJI_SJIS_L1, // 殺 + 0x85A9, KANJI_SJIS_L1, // 薩 + 0x96D1, KANJI_SJIS_L1, // 雑 + 0x7690, KANJI_SJIS_L1, // 皐 + 0x9BD6, KANJI_SJIS_L1, // 鯖 + 0x634C, KANJI_SJIS_L1, // 捌 + 0x9306, KANJI_SJIS_L1, // 錆 + 0x9BAB, KANJI_SJIS_L1, // 鮫 + 0x76BF, KANJI_SJIS_L1, // 皿 + 0x6652, KANJI_SJIS_L1, // 晒 + 0x4E09, KANJI_SJIS_L1, // 侉 + 0x5098, KANJI_SJIS_L1, // 傘 + 0x53C2, KANJI_SJIS_L1, // 参 + 0x5C71, KANJI_SJIS_L1, // å±± + 0x60E8, KANJI_SJIS_L1, // 惚 + 0x6492, KANJI_SJIS_L1, // 撒 + 0x6563, KANJI_SJIS_L1, // 散 + 0x685F, KANJI_SJIS_L1, // 桟 + 0x71E6, KANJI_SJIS_L1, // 燩 + 0x73CA, KANJI_SJIS_L1, // 珊 + 0x7523, KANJI_SJIS_L1, // 産 + 0x7B97, KANJI_SJIS_L1, // 算 + 0x7E82, KANJI_SJIS_L1, // 纂 + 0x8695, KANJI_SJIS_L1, // 蚕 + 0x8B83, KANJI_SJIS_L1, // 讃 + 0x8CDB, KANJI_SJIS_L1, // 賛 + 0x9178, KANJI_SJIS_L1, // 酾 + 0x9910, KANJI_SJIS_L1, // 逐 + 0x65AC, KANJI_SJIS_L1, // 斬 + 0x66AB, KANJI_SJIS_L1, // 暫 + 0x6B8B, KANJI_SJIS_L1, // 残 + 0x4ED5, KANJI_SJIS_L1, // 仕 + 0x4ED4, KANJI_SJIS_L1, // 仔 + 0x4F3A, KANJI_SJIS_L1, // 䌺 + 0x4F7F, KANJI_SJIS_L1, // 䜿 + 0x523A, KANJI_SJIS_L1, // 刺 + 0x53F8, KANJI_SJIS_L1, // 叞 + 0x53F2, KANJI_SJIS_L1, // 史 + 0x55E3, KANJI_SJIS_L1, // 嗣 + 0x56DB, KANJI_SJIS_L1, // 四 + 0x58EB, KANJI_SJIS_L1, // 士 + 0x59CB, KANJI_SJIS_L1, // 始 + 0x59C9, KANJI_SJIS_L1, // 姉 + 0x59FF, KANJI_SJIS_L1, // å§¿ + 0x5B50, KANJI_SJIS_L1, // 子 + 0x5C4D, KANJI_SJIS_L1, // 屍 + 0x5E02, KANJI_SJIS_L1, // åž‚ + 0x5E2B, KANJI_SJIS_L1, // åž« + 0x5FD7, KANJI_SJIS_L1, // 志 + 0x601D, KANJI_SJIS_L1, // 思 + 0x6307, KANJI_SJIS_L1, // 指 + 0x652F, KANJI_SJIS_L1, // 支 + 0x5B5C, KANJI_SJIS_L1, // 孜 + 0x65AF, KANJI_SJIS_L1, // 斯 + 0x65BD, KANJI_SJIS_L1, // æ–œ + 0x65E8, KANJI_SJIS_L1, // æ—š + 0x679D, KANJI_SJIS_L1, // 枝 + 0x6B62, KANJI_SJIS_L1, // æ­¢ + 0x3000, KANJI_SJIS_L1, //   + 0x6B7B, KANJI_SJIS_L1, // æ­» + 0x6C0F, KANJI_SJIS_L1, // 氏 + 0x7345, KANJI_SJIS_L1, // 獅 + 0x7949, KANJI_SJIS_L1, // 祉 + 0x79C1, KANJI_SJIS_L1, // 私 + 0x7CF8, KANJI_SJIS_L1, // 糞 + 0x7D19, KANJI_SJIS_L1, // 箙 + 0x7D2B, KANJI_SJIS_L1, // 玫 + 0x80A2, KANJI_SJIS_L1, // 肢 + 0x8102, KANJI_SJIS_L1, // 脂 + 0x81F3, KANJI_SJIS_L1, // 至 + 0x8996, KANJI_SJIS_L1, // 芖 + 0x8A5E, KANJI_SJIS_L1, // 詞 + 0x8A69, KANJI_SJIS_L1, // è©© + 0x8A66, KANJI_SJIS_L1, // 詊 + 0x8A8C, KANJI_SJIS_L1, // 誌 + 0x8AEE, KANJI_SJIS_L1, // è«® + 0x8CC7, KANJI_SJIS_L1, // 資 + 0x8CDC, KANJI_SJIS_L1, // 賜 + 0x96CC, KANJI_SJIS_L1, // 雌 + 0x98FC, KANJI_SJIS_L1, // 飌 + 0x6B6F, KANJI_SJIS_L1, // æ­¯ + 0x4E8B, KANJI_SJIS_L1, // 事 + 0x4F3C, KANJI_SJIS_L1, // 䌌 + 0x4F8D, KANJI_SJIS_L1, // 䟍 + 0x5150, KANJI_SJIS_L1, // 児 + 0x5B57, KANJI_SJIS_L1, // 字 + 0x5BFA, KANJI_SJIS_L1, // 寺 + 0x6148, KANJI_SJIS_L1, // 慈 + 0x6301, KANJI_SJIS_L1, // 持 + 0x6642, KANJI_SJIS_L1, // 時 + 0x6B21, KANJI_SJIS_L1, // 次 + 0x6ECB, KANJI_SJIS_L1, // 滋 + 0x6CBB, KANJI_SJIS_L1, // æ²» + 0x723E, KANJI_SJIS_L1, // 爟 + 0x74BD, KANJI_SJIS_L1, // ç’œ + 0x75D4, KANJI_SJIS_L1, // 痔 + 0x78C1, KANJI_SJIS_L1, // 磁 + 0x793A, KANJI_SJIS_L1, // 瀺 + 0x800C, KANJI_SJIS_L1, // 而 + 0x8033, KANJI_SJIS_L1, // 耳 + 0x81EA, KANJI_SJIS_L1, // 自 + 0x8494, KANJI_SJIS_L1, // 蒔 + 0x8F9E, KANJI_SJIS_L1, // 蟞 + 0x6C50, KANJI_SJIS_L1, // 汐 + 0x9E7F, KANJI_SJIS_L1, // 鹿 + 0x5F0F, KANJI_SJIS_L1, // 匏 + 0x8B58, KANJI_SJIS_L1, // 識 + 0x9D2B, KANJI_SJIS_L1, // 鎫 + 0x7AFA, KANJI_SJIS_L1, // 竺 + 0x8EF8, KANJI_SJIS_L1, // 軞 + 0x5B8D, KANJI_SJIS_L1, // 宍 + 0x96EB, KANJI_SJIS_L1, // 雫 + 0x4E03, KANJI_SJIS_L1, // 䞃 + 0x53F1, KANJI_SJIS_L1, // 叱 + 0x57F7, KANJI_SJIS_L1, // 執 + 0x5931, KANJI_SJIS_L1, // 倱 + 0x5AC9, KANJI_SJIS_L1, // 嫉 + 0x5BA4, KANJI_SJIS_L1, // 宀 + 0x6089, KANJI_SJIS_L1, // 悉 + 0x6E7F, KANJI_SJIS_L1, // 湿 + 0x6F06, KANJI_SJIS_L1, // 挆 + 0x75BE, KANJI_SJIS_L1, // ç–Ÿ + 0x8CEA, KANJI_SJIS_L1, // 質 + 0x5B9F, KANJI_SJIS_L1, // 実 + 0x8500, KANJI_SJIS_L1, // 蔀 + 0x7BE0, KANJI_SJIS_L1, // 篠 + 0x5072, KANJI_SJIS_L1, // 偲 + 0x67F4, KANJI_SJIS_L1, // 柎 + 0x829D, KANJI_SJIS_L1, // 芝 + 0x5C61, KANJI_SJIS_L1, // 屡 + 0x854A, KANJI_SJIS_L1, // 蕊 + 0x7E1E, KANJI_SJIS_L1, // 羞 + 0x820E, KANJI_SJIS_L1, // 舎 + 0x5199, KANJI_SJIS_L1, // 写 + 0x5C04, KANJI_SJIS_L1, // 射 + 0x6368, KANJI_SJIS_L1, // 捚 + 0x8D66, KANJI_SJIS_L1, // 赊 + 0x659C, KANJI_SJIS_L1, // 斜 + 0x716E, KANJI_SJIS_L1, // 煮 + 0x793E, KANJI_SJIS_L1, // 瀟 + 0x7D17, KANJI_SJIS_L1, // 算 + 0x8005, KANJI_SJIS_L1, // 者 + 0x8B1D, KANJI_SJIS_L1, // 謝 + 0x8ECA, KANJI_SJIS_L1, // 車 + 0x906E, KANJI_SJIS_L1, // 遮 + 0x86C7, KANJI_SJIS_L1, // 蛇 + 0x90AA, KANJI_SJIS_L1, // 邪 + 0x501F, KANJI_SJIS_L1, // 借 + 0x52FA, KANJI_SJIS_L1, // 勺 + 0x5C3A, KANJI_SJIS_L1, // å°º + 0x6753, KANJI_SJIS_L1, // 杓 + 0x707C, KANJI_SJIS_L1, // 灌 + 0x7235, KANJI_SJIS_L1, // 爵 + 0x914C, KANJI_SJIS_L1, // 酌 + 0x91C8, KANJI_SJIS_L1, // 釈 + 0x932B, KANJI_SJIS_L1, // 錫 + 0x82E5, KANJI_SJIS_L1, // 若 + 0x5BC2, KANJI_SJIS_L1, // 寂 + 0x5F31, KANJI_SJIS_L1, // 匱 + 0x60F9, KANJI_SJIS_L1, // 惹 + 0x4E3B, KANJI_SJIS_L1, // äž» + 0x53D6, KANJI_SJIS_L1, // 取 + 0x5B88, KANJI_SJIS_L1, // 守 + 0x624B, KANJI_SJIS_L1, // 手 + 0x6731, KANJI_SJIS_L1, // 朱 + 0x6B8A, KANJI_SJIS_L1, // 殊 + 0x72E9, KANJI_SJIS_L1, // 狩 + 0x73E0, KANJI_SJIS_L1, // 珠 + 0x7A2E, KANJI_SJIS_L1, // çš® + 0x816B, KANJI_SJIS_L1, // 腫 + 0x8DA3, KANJI_SJIS_L1, // è¶£ + 0x9152, KANJI_SJIS_L1, // 酒 + 0x9996, KANJI_SJIS_L1, // 驖 + 0x5112, KANJI_SJIS_L1, // 儒 + 0x53D7, KANJI_SJIS_L1, // 受 + 0x546A, KANJI_SJIS_L1, // 呪 + 0x5BFF, KANJI_SJIS_L1, // 寿 + 0x6388, KANJI_SJIS_L1, // 授 + 0x6A39, KANJI_SJIS_L1, // æš¹ + 0x7DAC, KANJI_SJIS_L1, // 綬 + 0x9700, KANJI_SJIS_L1, // 需 + 0x56DA, KANJI_SJIS_L1, // 囚 + 0x53CE, KANJI_SJIS_L1, // 収 + 0x5468, KANJI_SJIS_L1, // 呚 + 0x5B97, KANJI_SJIS_L1, // 宗 + 0x5C31, KANJI_SJIS_L1, // å°± + 0x5DDE, KANJI_SJIS_L1, // 州 + 0x4FEE, KANJI_SJIS_L1, // ä¿® + 0x6101, KANJI_SJIS_L1, // 愁 + 0x62FE, KANJI_SJIS_L1, // 拟 + 0x6D32, KANJI_SJIS_L1, // 掲 + 0x79C0, KANJI_SJIS_L1, // 秀 + 0x79CB, KANJI_SJIS_L1, // 秋 + 0x7D42, KANJI_SJIS_L1, // 終 + 0x7E4D, KANJI_SJIS_L1, // 繍 + 0x7FD2, KANJI_SJIS_L1, // 習 + 0x81ED, KANJI_SJIS_L1, // 臭 + 0x821F, KANJI_SJIS_L1, // 舟 + 0x8490, KANJI_SJIS_L1, // 蒐 + 0x8846, KANJI_SJIS_L1, // 衆 + 0x8972, KANJI_SJIS_L1, // 襲 + 0x8B90, KANJI_SJIS_L1, // 讐 + 0x8E74, KANJI_SJIS_L1, // 蹎 + 0x8F2F, KANJI_SJIS_L1, // 茯 + 0x9031, KANJI_SJIS_L1, // 週 + 0x914B, KANJI_SJIS_L1, // 酋 + 0x916C, KANJI_SJIS_L1, // 酬 + 0x96C6, KANJI_SJIS_L1, // 集 + 0x919C, KANJI_SJIS_L1, // 醜 + 0x4EC0, KANJI_SJIS_L1, // 什 + 0x4F4F, KANJI_SJIS_L1, // 䜏 + 0x5145, KANJI_SJIS_L1, // 充 + 0x5341, KANJI_SJIS_L1, // 十 + 0x5F93, KANJI_SJIS_L1, // 埓 + 0x620E, KANJI_SJIS_L1, // 戎 + 0x67D4, KANJI_SJIS_L1, // 柔 + 0x6C41, KANJI_SJIS_L1, // 汁 + 0x6E0B, KANJI_SJIS_L1, // æž‹ + 0x7363, KANJI_SJIS_L1, // 獣 + 0x7E26, KANJI_SJIS_L1, // 瞊 + 0x91CD, KANJI_SJIS_L1, // 重 + 0x9283, KANJI_SJIS_L1, // 銃 + 0x53D4, KANJI_SJIS_L1, // 叔 + 0x5919, KANJI_SJIS_L1, // 候 + 0x5BBF, KANJI_SJIS_L1, // 宿 + 0x6DD1, KANJI_SJIS_L1, // 淑 + 0x795D, KANJI_SJIS_L1, // 祝 + 0x7E2E, KANJI_SJIS_L1, // çž® + 0x7C9B, KANJI_SJIS_L1, // 粛 + 0x587E, KANJI_SJIS_L1, // 塟 + 0x719F, KANJI_SJIS_L1, // 熟 + 0x51FA, KANJI_SJIS_L1, // 出 + 0x8853, KANJI_SJIS_L1, // 術 + 0x8FF0, KANJI_SJIS_L1, // è¿° + 0x4FCA, KANJI_SJIS_L1, // 俊 + 0x5CFB, KANJI_SJIS_L1, // å³» + 0x6625, KANJI_SJIS_L1, // 春 + 0x77AC, KANJI_SJIS_L1, // 瞬 + 0x7AE3, KANJI_SJIS_L1, // ç«£ + 0x821C, KANJI_SJIS_L1, // 舜 + 0x99FF, KANJI_SJIS_L1, // é§¿ + 0x51C6, KANJI_SJIS_L1, // 准 + 0x5FAA, KANJI_SJIS_L1, // 埪 + 0x65EC, KANJI_SJIS_L1, // 旬 + 0x696F, KANJI_SJIS_L1, // 楯 + 0x6B89, KANJI_SJIS_L1, // 殉 + 0x6DF3, KANJI_SJIS_L1, // æ·³ + 0x3000, KANJI_SJIS_L1, //   + 0x6E96, KANJI_SJIS_L1, // 準 + 0x6F64, KANJI_SJIS_L1, // 最 + 0x76FE, KANJI_SJIS_L1, // 盟 + 0x7D14, KANJI_SJIS_L1, // 箔 + 0x5DE1, KANJI_SJIS_L1, // å·¡ + 0x9075, KANJI_SJIS_L1, // 遵 + 0x9187, KANJI_SJIS_L1, // 醇 + 0x9806, KANJI_SJIS_L1, // 順 + 0x51E6, KANJI_SJIS_L1, // 凊 + 0x521D, KANJI_SJIS_L1, // 初 + 0x6240, KANJI_SJIS_L1, // 所 + 0x6691, KANJI_SJIS_L1, // 暑 + 0x66D9, KANJI_SJIS_L1, // 曙 + 0x6E1A, KANJI_SJIS_L1, // æžš + 0x5EB6, KANJI_SJIS_L1, // 庶 + 0x7DD2, KANJI_SJIS_L1, // 緒 + 0x7F72, KANJI_SJIS_L1, // 眲 + 0x66F8, KANJI_SJIS_L1, // 曞 + 0x85AF, KANJI_SJIS_L1, // 薯 + 0x85F7, KANJI_SJIS_L1, // 藷 + 0x8AF8, KANJI_SJIS_L1, // 諞 + 0x52A9, KANJI_SJIS_L1, // 助 + 0x53D9, KANJI_SJIS_L1, // 叙 + 0x5973, KANJI_SJIS_L1, // 女 + 0x5E8F, KANJI_SJIS_L1, // 序 + 0x5F90, KANJI_SJIS_L1, // 埐 + 0x6055, KANJI_SJIS_L1, // 恕 + 0x92E4, KANJI_SJIS_L1, // é‹€ + 0x9664, KANJI_SJIS_L1, // 陀 + 0x50B7, KANJI_SJIS_L1, // 傷 + 0x511F, KANJI_SJIS_L1, // 償 + 0x52DD, KANJI_SJIS_L1, // 勝 + 0x5320, KANJI_SJIS_L1, // 匠 + 0x5347, KANJI_SJIS_L1, // 升 + 0x53EC, KANJI_SJIS_L1, // 召 + 0x54E8, KANJI_SJIS_L1, // 哚 + 0x5546, KANJI_SJIS_L1, // 商 + 0x5531, KANJI_SJIS_L1, // 唱 + 0x5617, KANJI_SJIS_L1, // 嘗 + 0x5968, KANJI_SJIS_L1, // 奚 + 0x59BE, KANJI_SJIS_L1, // 功 + 0x5A3C, KANJI_SJIS_L1, // 嚌 + 0x5BB5, KANJI_SJIS_L1, // 宵 + 0x5C06, KANJI_SJIS_L1, // 将 + 0x5C0F, KANJI_SJIS_L1, // 小 + 0x5C11, KANJI_SJIS_L1, // 少 + 0x5C1A, KANJI_SJIS_L1, // 尚 + 0x5E84, KANJI_SJIS_L1, // 庄 + 0x5E8A, KANJI_SJIS_L1, // 床 + 0x5EE0, KANJI_SJIS_L1, // å»  + 0x5F70, KANJI_SJIS_L1, // 地 + 0x627F, KANJI_SJIS_L1, // 承 + 0x6284, KANJI_SJIS_L1, // 抄 + 0x62DB, KANJI_SJIS_L1, // 招 + 0x638C, KANJI_SJIS_L1, // 掌 + 0x6377, KANJI_SJIS_L1, // 捷 + 0x6607, KANJI_SJIS_L1, // 昇 + 0x660C, KANJI_SJIS_L1, // 昌 + 0x662D, KANJI_SJIS_L1, // 昭 + 0x6676, KANJI_SJIS_L1, // 晶 + 0x677E, KANJI_SJIS_L1, // 束 + 0x68A2, KANJI_SJIS_L1, // 梢 + 0x6A1F, KANJI_SJIS_L1, // 暟 + 0x6A35, KANJI_SJIS_L1, // æšµ + 0x6CBC, KANJI_SJIS_L1, // 沌 + 0x6D88, KANJI_SJIS_L1, // 消 + 0x6E09, KANJI_SJIS_L1, // 枉 + 0x6E58, KANJI_SJIS_L1, // 湘 + 0x713C, KANJI_SJIS_L1, // 焌 + 0x7126, KANJI_SJIS_L1, // 焩 + 0x7167, KANJI_SJIS_L1, // 照 + 0x75C7, KANJI_SJIS_L1, // 症 + 0x7701, KANJI_SJIS_L1, // 省 + 0x785D, KANJI_SJIS_L1, // 硝 + 0x7901, KANJI_SJIS_L1, // 瀁 + 0x7965, KANJI_SJIS_L1, // 祥 + 0x79F0, KANJI_SJIS_L1, // ç§° + 0x7AE0, KANJI_SJIS_L1, // ç«  + 0x7B11, KANJI_SJIS_L1, // 笑 + 0x7CA7, KANJI_SJIS_L1, // ç²§ + 0x7D39, KANJI_SJIS_L1, // 玹 + 0x8096, KANJI_SJIS_L1, // 肖 + 0x83D6, KANJI_SJIS_L1, // 菖 + 0x848B, KANJI_SJIS_L1, // 蒋 + 0x8549, KANJI_SJIS_L1, // 蕉 + 0x885D, KANJI_SJIS_L1, // 衝 + 0x88F3, KANJI_SJIS_L1, // 裳 + 0x8A1F, KANJI_SJIS_L1, // 蚟 + 0x8A3C, KANJI_SJIS_L1, // 蚌 + 0x8A54, KANJI_SJIS_L1, // 詔 + 0x8A73, KANJI_SJIS_L1, // 詳 + 0x8C61, KANJI_SJIS_L1, // 象 + 0x8CDE, KANJI_SJIS_L1, // 賞 + 0x91A4, KANJI_SJIS_L1, // 醀 + 0x9266, KANJI_SJIS_L1, // 鉩 + 0x937E, KANJI_SJIS_L1, // 鍟 + 0x9418, KANJI_SJIS_L1, // 鐘 + 0x969C, KANJI_SJIS_L1, // 障 + 0x9798, KANJI_SJIS_L1, // 鞘 + 0x4E0A, KANJI_SJIS_L1, // 侊 + 0x4E08, KANJI_SJIS_L1, // 䞈 + 0x4E1E, KANJI_SJIS_L1, // 侞 + 0x4E57, KANJI_SJIS_L1, // 乗 + 0x5197, KANJI_SJIS_L1, // 冗 + 0x5270, KANJI_SJIS_L1, // 剰 + 0x57CE, KANJI_SJIS_L1, // 城 + 0x5834, KANJI_SJIS_L1, // å Ž + 0x58CC, KANJI_SJIS_L1, // 壌 + 0x5B22, KANJI_SJIS_L1, // 嬢 + 0x5E38, KANJI_SJIS_L1, // åžž + 0x60C5, KANJI_SJIS_L1, // 情 + 0x64FE, KANJI_SJIS_L1, // 擟 + 0x6761, KANJI_SJIS_L1, // 条 + 0x6756, KANJI_SJIS_L1, // 杖 + 0x6D44, KANJI_SJIS_L1, // 浄 + 0x72B6, KANJI_SJIS_L1, // 状 + 0x7573, KANJI_SJIS_L1, // 畳 + 0x7A63, KANJI_SJIS_L1, // ç©£ + 0x84B8, KANJI_SJIS_L1, // è’ž + 0x8B72, KANJI_SJIS_L1, // è­² + 0x91B8, KANJI_SJIS_L1, // 醾 + 0x9320, KANJI_SJIS_L1, // 錠 + 0x5631, KANJI_SJIS_L1, // 嘱 + 0x57F4, KANJI_SJIS_L1, // 城 + 0x98FE, KANJI_SJIS_L1, // 食 + 0x62ED, KANJI_SJIS_L1, // 拭 + 0x690D, KANJI_SJIS_L1, // 怍 + 0x6B96, KANJI_SJIS_L1, // 殖 + 0x71ED, KANJI_SJIS_L1, // 燭 + 0x7E54, KANJI_SJIS_L1, // 織 + 0x8077, KANJI_SJIS_L1, // 職 + 0x8272, KANJI_SJIS_L1, // 色 + 0x89E6, KANJI_SJIS_L1, // è§Š + 0x98DF, KANJI_SJIS_L1, // 食 + 0x8755, KANJI_SJIS_L1, // 蝕 + 0x8FB1, KANJI_SJIS_L1, // 蟱 + 0x5C3B, KANJI_SJIS_L1, // å°» + 0x4F38, KANJI_SJIS_L1, // 䌞 + 0x4FE1, KANJI_SJIS_L1, // ä¿¡ + 0x4FB5, KANJI_SJIS_L1, // 䟵 + 0x5507, KANJI_SJIS_L1, // 唇 + 0x5A20, KANJI_SJIS_L1, // åš  + 0x5BDD, KANJI_SJIS_L1, // 寝 + 0x5BE9, KANJI_SJIS_L1, // 審 + 0x5FC3, KANJI_SJIS_L1, // 心 + 0x614E, KANJI_SJIS_L1, // 慎 + 0x632F, KANJI_SJIS_L1, // 振 + 0x65B0, KANJI_SJIS_L1, // 新 + 0x664B, KANJI_SJIS_L1, // 晋 + 0x68EE, KANJI_SJIS_L1, // 森 + 0x699B, KANJI_SJIS_L1, // 抛 + 0x6D78, KANJI_SJIS_L1, // 浞 + 0x6DF1, KANJI_SJIS_L1, // æ·± + 0x7533, KANJI_SJIS_L1, // 申 + 0x75B9, KANJI_SJIS_L1, // 疹 + 0x771F, KANJI_SJIS_L1, // 真 + 0x795E, KANJI_SJIS_L1, // 神 + 0x79E6, KANJI_SJIS_L1, // ç§Š + 0x7D33, KANJI_SJIS_L1, // 玳 + 0x81E3, KANJI_SJIS_L1, // 臣 + 0x82AF, KANJI_SJIS_L1, // 芯 + 0x85AA, KANJI_SJIS_L1, // 薪 + 0x89AA, KANJI_SJIS_L1, // 芪 + 0x8A3A, KANJI_SJIS_L1, // 蚺 + 0x8EAB, KANJI_SJIS_L1, // 身 + 0x8F9B, KANJI_SJIS_L1, // 蟛 + 0x9032, KANJI_SJIS_L1, // 進 + 0x91DD, KANJI_SJIS_L1, // 針 + 0x9707, KANJI_SJIS_L1, // 震 + 0x4EBA, KANJI_SJIS_L1, // 人 + 0x4EC1, KANJI_SJIS_L1, // 仁 + 0x5203, KANJI_SJIS_L1, // 刃 + 0x5875, KANJI_SJIS_L1, // 塵 + 0x58EC, KANJI_SJIS_L1, // 壬 + 0x5C0B, KANJI_SJIS_L1, // 尋 + 0x751A, KANJI_SJIS_L1, // 甚 + 0x5C3D, KANJI_SJIS_L1, // å°œ + 0x814E, KANJI_SJIS_L1, // 腎 + 0x8A0A, KANJI_SJIS_L1, // 蚊 + 0x8FC5, KANJI_SJIS_L1, // 迅 + 0x9663, KANJI_SJIS_L1, // 陣 + 0x976D, KANJI_SJIS_L1, // 靭 + 0x7B25, KANJI_SJIS_L1, // 笥 + 0x8ACF, KANJI_SJIS_L1, // 諏 + 0x9808, KANJI_SJIS_L1, // 須 + 0x9162, KANJI_SJIS_L1, // 酢 + 0x56F3, KANJI_SJIS_L1, // 図 + 0x53A8, KANJI_SJIS_L1, // 厚 + 0x3000, KANJI_SJIS_L1, //   + 0x9017, KANJI_SJIS_L1, // 逗 + 0x5439, KANJI_SJIS_L1, // 吹 + 0x5782, KANJI_SJIS_L1, // 垂 + 0x5E25, KANJI_SJIS_L1, // 垥 + 0x63A8, KANJI_SJIS_L1, // 掚 + 0x6C34, KANJI_SJIS_L1, // æ°Ž + 0x708A, KANJI_SJIS_L1, // 炊 + 0x7761, KANJI_SJIS_L1, // 睡 + 0x7C8B, KANJI_SJIS_L1, // 粋 + 0x7FE0, KANJI_SJIS_L1, // ç¿  + 0x8870, KANJI_SJIS_L1, // è¡° + 0x9042, KANJI_SJIS_L1, // 遂 + 0x9154, KANJI_SJIS_L1, // 酔 + 0x9310, KANJI_SJIS_L1, // 錐 + 0x9318, KANJI_SJIS_L1, // 錘 + 0x968F, KANJI_SJIS_L1, // 随 + 0x745E, KANJI_SJIS_L1, // 瑞 + 0x9AC4, KANJI_SJIS_L1, // 髄 + 0x5D07, KANJI_SJIS_L1, // 厇 + 0x5D69, KANJI_SJIS_L1, // 嵩 + 0x6570, KANJI_SJIS_L1, // 数 + 0x67A2, KANJI_SJIS_L1, // 枢 + 0x8DA8, KANJI_SJIS_L1, // è¶š + 0x96DB, KANJI_SJIS_L1, // 雛 + 0x636E, KANJI_SJIS_L1, // 据 + 0x6749, KANJI_SJIS_L1, // 杉 + 0x6919, KANJI_SJIS_L1, // 怙 + 0x83C5, KANJI_SJIS_L1, // 菅 + 0x9817, KANJI_SJIS_L1, // 頗 + 0x96C0, KANJI_SJIS_L1, // 雀 + 0x88FE, KANJI_SJIS_L1, // 裟 + 0x6F84, KANJI_SJIS_L1, // 柄 + 0x647A, KANJI_SJIS_L1, // 摺 + 0x5BF8, KANJI_SJIS_L1, // 寞 + 0x4E16, KANJI_SJIS_L1, // 侖 + 0x702C, KANJI_SJIS_L1, // 瀬 + 0x755D, KANJI_SJIS_L1, // 畝 + 0x662F, KANJI_SJIS_L1, // 是 + 0x51C4, KANJI_SJIS_L1, // 凄 + 0x5236, KANJI_SJIS_L1, // 制 + 0x52E2, KANJI_SJIS_L1, // 勢 + 0x59D3, KANJI_SJIS_L1, // 姓 + 0x5F81, KANJI_SJIS_L1, // 埁 + 0x6027, KANJI_SJIS_L1, // 性 + 0x6210, KANJI_SJIS_L1, // 成 + 0x653F, KANJI_SJIS_L1, // 政 + 0x6574, KANJI_SJIS_L1, // 敎 + 0x661F, KANJI_SJIS_L1, // 星 + 0x6674, KANJI_SJIS_L1, // 晎 + 0x68F2, KANJI_SJIS_L1, // 棲 + 0x6816, KANJI_SJIS_L1, // 栖 + 0x6B63, KANJI_SJIS_L1, // æ­£ + 0x6E05, KANJI_SJIS_L1, // æž… + 0x7272, KANJI_SJIS_L1, // 牲 + 0x751F, KANJI_SJIS_L1, // 生 + 0x76DB, KANJI_SJIS_L1, // 盛 + 0x7CBE, KANJI_SJIS_L1, // 粟 + 0x8056, KANJI_SJIS_L1, // 聖 + 0x58F0, KANJI_SJIS_L1, // 声 + 0x88FD, KANJI_SJIS_L1, // 補 + 0x897F, KANJI_SJIS_L1, // 西 + 0x8AA0, KANJI_SJIS_L1, // 誠 + 0x8A93, KANJI_SJIS_L1, // 誓 + 0x8ACB, KANJI_SJIS_L1, // 請 + 0x901D, KANJI_SJIS_L1, // 逝 + 0x9192, KANJI_SJIS_L1, // 醒 + 0x9752, KANJI_SJIS_L1, // 青 + 0x9759, KANJI_SJIS_L1, // 静 + 0x6589, KANJI_SJIS_L1, // 斉 + 0x7A0E, KANJI_SJIS_L1, // 皎 + 0x8106, KANJI_SJIS_L1, // 脆 + 0x96BB, KANJI_SJIS_L1, // 隻 + 0x5E2D, KANJI_SJIS_L1, // åž­ + 0x60DC, KANJI_SJIS_L1, // 惜 + 0x621A, KANJI_SJIS_L1, // 戚 + 0x65A5, KANJI_SJIS_L1, // 斥 + 0x6614, KANJI_SJIS_L1, // 昔 + 0x6790, KANJI_SJIS_L1, // 析 + 0x77F3, KANJI_SJIS_L1, // 石 + 0x7A4D, KANJI_SJIS_L1, // 積 + 0x7C4D, KANJI_SJIS_L1, // 籍 + 0x7E3E, KANJI_SJIS_L1, // 瞟 + 0x810A, KANJI_SJIS_L1, // 脊 + 0x8CAC, KANJI_SJIS_L1, // 責 + 0x8D64, KANJI_SJIS_L1, // èµ€ + 0x8DE1, KANJI_SJIS_L1, // è·¡ + 0x8E5F, KANJI_SJIS_L1, // 蹟 + 0x78A9, KANJI_SJIS_L1, // 碩 + 0x5207, KANJI_SJIS_L1, // 切 + 0x62D9, KANJI_SJIS_L1, // 拙 + 0x63A5, KANJI_SJIS_L1, // 接 + 0x6442, KANJI_SJIS_L1, // 摂 + 0x6298, KANJI_SJIS_L1, // 折 + 0x8A2D, KANJI_SJIS_L1, // èš­ + 0x7A83, KANJI_SJIS_L1, // 窃 + 0x7BC0, KANJI_SJIS_L1, // 節 + 0x8AAC, KANJI_SJIS_L1, // 説 + 0x96EA, KANJI_SJIS_L1, // 雪 + 0x7D76, KANJI_SJIS_L1, // çµ¶ + 0x820C, KANJI_SJIS_L1, // 舌 + 0x8749, KANJI_SJIS_L1, // 蝉 + 0x4ED9, KANJI_SJIS_L1, // 仙 + 0x5148, KANJI_SJIS_L1, // 先 + 0x5343, KANJI_SJIS_L1, // 千 + 0x5360, KANJI_SJIS_L1, // 占 + 0x5BA3, KANJI_SJIS_L1, // 宣 + 0x5C02, KANJI_SJIS_L1, // 専 + 0x5C16, KANJI_SJIS_L1, // 尖 + 0x5DDD, KANJI_SJIS_L1, // 川 + 0x6226, KANJI_SJIS_L1, // 戊 + 0x6247, KANJI_SJIS_L1, // 扇 + 0x64B0, KANJI_SJIS_L1, // 撰 + 0x6813, KANJI_SJIS_L1, // 栓 + 0x6834, KANJI_SJIS_L1, // æ Ž + 0x6CC9, KANJI_SJIS_L1, // 泉 + 0x6D45, KANJI_SJIS_L1, // 浅 + 0x6D17, KANJI_SJIS_L1, // 掗 + 0x67D3, KANJI_SJIS_L1, // 染 + 0x6F5C, KANJI_SJIS_L1, // 朜 + 0x714E, KANJI_SJIS_L1, // 煎 + 0x717D, KANJI_SJIS_L1, // ç…œ + 0x65CB, KANJI_SJIS_L1, // 旋 + 0x7A7F, KANJI_SJIS_L1, // ç©¿ + 0x7BAD, KANJI_SJIS_L1, // ç®­ + 0x7DDA, KANJI_SJIS_L1, // 線 + 0x7E4A, KANJI_SJIS_L1, // 繊 + 0x7FA8, KANJI_SJIS_L1, // 矚 + 0x817A, KANJI_SJIS_L1, // 腺 + 0x821B, KANJI_SJIS_L1, // 舛 + 0x8239, KANJI_SJIS_L1, // 船 + 0x85A6, KANJI_SJIS_L1, // è–Š + 0x8A6E, KANJI_SJIS_L1, // è©® + 0x8CCE, KANJI_SJIS_L1, // 賎 + 0x8DF5, KANJI_SJIS_L1, // è·µ + 0x9078, KANJI_SJIS_L1, // 遞 + 0x9077, KANJI_SJIS_L1, // 遷 + 0x92AD, KANJI_SJIS_L1, // 銭 + 0x9291, KANJI_SJIS_L1, // 銑 + 0x9583, KANJI_SJIS_L1, // 閃 + 0x9BAE, KANJI_SJIS_L1, // é®® + 0x524D, KANJI_SJIS_L1, // 前 + 0x5584, KANJI_SJIS_L1, // 善 + 0x6F38, KANJI_SJIS_L1, // 挞 + 0x7136, KANJI_SJIS_L1, // 然 + 0x5168, KANJI_SJIS_L1, // å…š + 0x7985, KANJI_SJIS_L1, // 穅 + 0x7E55, KANJI_SJIS_L1, // 繕 + 0x81B3, KANJI_SJIS_L1, // 膳 + 0x7CCE, KANJI_SJIS_L1, // 糎 + 0x564C, KANJI_SJIS_L1, // 噌 + 0x5851, KANJI_SJIS_L1, // 塑 + 0x5CA8, KANJI_SJIS_L1, // 岚 + 0x63AA, KANJI_SJIS_L1, // 措 + 0x66FE, KANJI_SJIS_L1, // 曟 + 0x66FD, KANJI_SJIS_L1, // 曜 + 0x695A, KANJI_SJIS_L1, // 楚 + 0x72D9, KANJI_SJIS_L1, // 狙 + 0x758F, KANJI_SJIS_L1, // 疏 + 0x758E, KANJI_SJIS_L1, // 疎 + 0x790E, KANJI_SJIS_L1, // 瀎 + 0x7956, KANJI_SJIS_L1, // 祖 + 0x79DF, KANJI_SJIS_L1, // 租 + 0x7C97, KANJI_SJIS_L1, // 粗 + 0x7D20, KANJI_SJIS_L1, // 玠 + 0x7D44, KANJI_SJIS_L1, // 組 + 0x8607, KANJI_SJIS_L1, // 蘇 + 0x8A34, KANJI_SJIS_L1, // 蚎 + 0x963B, KANJI_SJIS_L1, // 阻 + 0x9061, KANJI_SJIS_L1, // 遡 + 0x9F20, KANJI_SJIS_L1, // 錠 + 0x50E7, KANJI_SJIS_L1, // 僧 + 0x5275, KANJI_SJIS_L1, // 創 + 0x53CC, KANJI_SJIS_L1, // 双 + 0x53E2, KANJI_SJIS_L1, // 叢 + 0x5009, KANJI_SJIS_L1, // 倉 + 0x55AA, KANJI_SJIS_L1, // 喪 + 0x58EE, KANJI_SJIS_L1, // 壮 + 0x594F, KANJI_SJIS_L1, // 奏 + 0x723D, KANJI_SJIS_L1, // 爜 + 0x5B8B, KANJI_SJIS_L1, // 宋 + 0x5C64, KANJI_SJIS_L1, // å±€ + 0x531D, KANJI_SJIS_L1, // 匝 + 0x60E3, KANJI_SJIS_L1, // 惣 + 0x60F3, KANJI_SJIS_L1, // 想 + 0x635C, KANJI_SJIS_L1, // 捜 + 0x6383, KANJI_SJIS_L1, // 掃 + 0x633F, KANJI_SJIS_L1, // 挿 + 0x63BB, KANJI_SJIS_L1, // 掻 + 0x3000, KANJI_SJIS_L1, //   + 0x64CD, KANJI_SJIS_L1, // 操 + 0x65E9, KANJI_SJIS_L1, // 早 + 0x66F9, KANJI_SJIS_L1, // 曹 + 0x5DE3, KANJI_SJIS_L1, // å·£ + 0x69CD, KANJI_SJIS_L1, // 槍 + 0x69FD, KANJI_SJIS_L1, // æ§œ + 0x6F15, KANJI_SJIS_L1, // 挕 + 0x71E5, KANJI_SJIS_L1, // 燥 + 0x4E89, KANJI_SJIS_L1, // 争 + 0x75E9, KANJI_SJIS_L1, // 痩 + 0x76F8, KANJI_SJIS_L1, // 盾 + 0x7A93, KANJI_SJIS_L1, // 窓 + 0x7CDF, KANJI_SJIS_L1, // 糟 + 0x7DCF, KANJI_SJIS_L1, // 総 + 0x7D9C, KANJI_SJIS_L1, // 綜 + 0x8061, KANJI_SJIS_L1, // 聡 + 0x8349, KANJI_SJIS_L1, // 草 + 0x8358, KANJI_SJIS_L1, // 荘 + 0x846C, KANJI_SJIS_L1, // 葬 + 0x84BC, KANJI_SJIS_L1, // è’Œ + 0x85FB, KANJI_SJIS_L1, // 藻 + 0x88C5, KANJI_SJIS_L1, // 装 + 0x8D70, KANJI_SJIS_L1, // èµ° + 0x9001, KANJI_SJIS_L1, // 送 + 0x906D, KANJI_SJIS_L1, // 遭 + 0x9397, KANJI_SJIS_L1, // 鎗 + 0x971C, KANJI_SJIS_L1, // 霜 + 0x9A12, KANJI_SJIS_L1, // 鹒 + 0x50CF, KANJI_SJIS_L1, // 像 + 0x5897, KANJI_SJIS_L1, // 増 + 0x618E, KANJI_SJIS_L1, // 憎 + 0x81D3, KANJI_SJIS_L1, // 臓 + 0x8535, KANJI_SJIS_L1, // 蔵 + 0x8D08, KANJI_SJIS_L1, // 莈 + 0x9020, KANJI_SJIS_L1, // 造 + 0x4FC3, KANJI_SJIS_L1, // 促 + 0x5074, KANJI_SJIS_L1, // 偎 + 0x5247, KANJI_SJIS_L1, // 則 + 0x5373, KANJI_SJIS_L1, // 即 + 0x606F, KANJI_SJIS_L1, // 息 + 0x6349, KANJI_SJIS_L1, // 捉 + 0x675F, KANJI_SJIS_L1, // 束 + 0x6E2C, KANJI_SJIS_L1, // 枬 + 0x8DB3, KANJI_SJIS_L1, // è¶³ + 0x901F, KANJI_SJIS_L1, // 速 + 0x4FD7, KANJI_SJIS_L1, // 俗 + 0x5C5E, KANJI_SJIS_L1, // 属 + 0x8CCA, KANJI_SJIS_L1, // 賊 + 0x65CF, KANJI_SJIS_L1, // 族 + 0x7D9A, KANJI_SJIS_L1, // 続 + 0x5352, KANJI_SJIS_L1, // 卒 + 0x8896, KANJI_SJIS_L1, // 袖 + 0x5176, KANJI_SJIS_L1, // 其 + 0x63C3, KANJI_SJIS_L1, // 揃 + 0x5B58, KANJI_SJIS_L1, // 存 + 0x5B6B, KANJI_SJIS_L1, // å­« + 0x5C0A, KANJI_SJIS_L1, // 尊 + 0x640D, KANJI_SJIS_L1, // 損 + 0x6751, KANJI_SJIS_L1, // 村 + 0x905C, KANJI_SJIS_L1, // 遜 + 0x4ED6, KANJI_SJIS_L1, // 他 + 0x591A, KANJI_SJIS_L1, // 倚 + 0x592A, KANJI_SJIS_L1, // 倪 + 0x6C70, KANJI_SJIS_L1, // æ±° + 0x8A51, KANJI_SJIS_L1, // 詑 + 0x553E, KANJI_SJIS_L1, // 唟 + 0x5815, KANJI_SJIS_L1, // 堕 + 0x59A5, KANJI_SJIS_L1, // 劥 + 0x60F0, KANJI_SJIS_L1, // 惰 + 0x6253, KANJI_SJIS_L1, // 打 + 0x67C1, KANJI_SJIS_L1, // 柁 + 0x8235, KANJI_SJIS_L1, // 舵 + 0x6955, KANJI_SJIS_L1, // 楕 + 0x9640, KANJI_SJIS_L1, // 陀 + 0x99C4, KANJI_SJIS_L1, // 駄 + 0x9A28, KANJI_SJIS_L1, // éšš + 0x4F53, KANJI_SJIS_L1, // 䜓 + 0x5806, KANJI_SJIS_L1, // 堆 + 0x5BFE, KANJI_SJIS_L1, // 察 + 0x8010, KANJI_SJIS_L1, // 耐 + 0x5CB1, KANJI_SJIS_L1, // å²± + 0x5E2F, KANJI_SJIS_L1, // 垯 + 0x5F85, KANJI_SJIS_L1, // 埅 + 0x6020, KANJI_SJIS_L1, // 怠 + 0x614B, KANJI_SJIS_L1, // 態 + 0x6234, KANJI_SJIS_L1, // 戎 + 0x66FF, KANJI_SJIS_L1, // 替 + 0x6CF0, KANJI_SJIS_L1, // æ³° + 0x6EDE, KANJI_SJIS_L1, // 滞 + 0x80CE, KANJI_SJIS_L1, // 胎 + 0x817F, KANJI_SJIS_L1, // 腿 + 0x82D4, KANJI_SJIS_L1, // 苔 + 0x888B, KANJI_SJIS_L1, // 袋 + 0x8CB8, KANJI_SJIS_L1, // 貞 + 0x9000, KANJI_SJIS_L1, // 退 + 0x902E, KANJI_SJIS_L1, // 逮 + 0x968A, KANJI_SJIS_L1, // 隊 + 0x9EDB, KANJI_SJIS_L1, // 黛 + 0x9BDB, KANJI_SJIS_L1, // 鯛 + 0x4EE3, KANJI_SJIS_L1, // 代 + 0x53F0, KANJI_SJIS_L1, // 台 + 0x5927, KANJI_SJIS_L1, // 倧 + 0x7B2C, KANJI_SJIS_L1, // 第 + 0x918D, KANJI_SJIS_L1, // 醍 + 0x984C, KANJI_SJIS_L1, // 題 + 0x9DF9, KANJI_SJIS_L1, // é·¹ + 0x6EDD, KANJI_SJIS_L1, // 滝 + 0x7027, KANJI_SJIS_L1, // 瀧 + 0x5353, KANJI_SJIS_L1, // 卓 + 0x5544, KANJI_SJIS_L1, // 啄 + 0x5B85, KANJI_SJIS_L1, // 宅 + 0x6258, KANJI_SJIS_L1, // 托 + 0x629E, KANJI_SJIS_L1, // 択 + 0x62D3, KANJI_SJIS_L1, // 拓 + 0x6CA2, KANJI_SJIS_L1, // æ²¢ + 0x6FEF, KANJI_SJIS_L1, // 濯 + 0x7422, KANJI_SJIS_L1, // 琢 + 0x8A17, KANJI_SJIS_L1, // èš— + 0x9438, KANJI_SJIS_L1, // 鐞 + 0x6FC1, KANJI_SJIS_L1, // 濁 + 0x8AFE, KANJI_SJIS_L1, // 諟 + 0x8338, KANJI_SJIS_L1, // 茞 + 0x51E7, KANJI_SJIS_L1, // 凧 + 0x86F8, KANJI_SJIS_L1, // 蛞 + 0x53EA, KANJI_SJIS_L1, // 只 + 0x53E9, KANJI_SJIS_L1, // 叩 + 0x4F46, KANJI_SJIS_L1, // 䜆 + 0x9054, KANJI_SJIS_L1, // 達 + 0x8FB0, KANJI_SJIS_L1, // 蟰 + 0x596A, KANJI_SJIS_L1, // 奪 + 0x8131, KANJI_SJIS_L1, // 脱 + 0x5DFD, KANJI_SJIS_L1, // å·œ + 0x7AEA, KANJI_SJIS_L1, // 竪 + 0x8FBF, KANJI_SJIS_L1, // 蟿 + 0x68DA, KANJI_SJIS_L1, // 棚 + 0x8C37, KANJI_SJIS_L1, // è°· + 0x72F8, KANJI_SJIS_L1, // 狾 + 0x9C48, KANJI_SJIS_L1, // 鱈 + 0x6A3D, KANJI_SJIS_L1, // æšœ + 0x8AB0, KANJI_SJIS_L1, // 誰 + 0x4E39, KANJI_SJIS_L1, // äž¹ + 0x5358, KANJI_SJIS_L1, // 単 + 0x5606, KANJI_SJIS_L1, // 嘆 + 0x5766, KANJI_SJIS_L1, // 坊 + 0x62C5, KANJI_SJIS_L1, // 担 + 0x63A2, KANJI_SJIS_L1, // 探 + 0x65E6, KANJI_SJIS_L1, // æ—Š + 0x6B4E, KANJI_SJIS_L1, // 歎 + 0x6DE1, KANJI_SJIS_L1, // æ·¡ + 0x6E5B, KANJI_SJIS_L1, // 湛 + 0x70AD, KANJI_SJIS_L1, // 炭 + 0x77ED, KANJI_SJIS_L1, // 短 + 0x7AEF, KANJI_SJIS_L1, // 端 + 0x7BAA, KANJI_SJIS_L1, // 箪 + 0x7DBB, KANJI_SJIS_L1, // ç¶» + 0x803D, KANJI_SJIS_L1, // 耜 + 0x80C6, KANJI_SJIS_L1, // 胆 + 0x86CB, KANJI_SJIS_L1, // 蛋 + 0x8A95, KANJI_SJIS_L1, // 誕 + 0x935B, KANJI_SJIS_L1, // 鍛 + 0x56E3, KANJI_SJIS_L1, // 団 + 0x58C7, KANJI_SJIS_L1, // 壇 + 0x5F3E, KANJI_SJIS_L1, // 匟 + 0x65AD, KANJI_SJIS_L1, // 断 + 0x6696, KANJI_SJIS_L1, // 暖 + 0x6A80, KANJI_SJIS_L1, // 檀 + 0x6BB5, KANJI_SJIS_L1, // 段 + 0x7537, KANJI_SJIS_L1, // 男 + 0x8AC7, KANJI_SJIS_L1, // 談 + 0x5024, KANJI_SJIS_L1, // 倀 + 0x77E5, KANJI_SJIS_L1, // 知 + 0x5730, KANJI_SJIS_L1, // 地 + 0x5F1B, KANJI_SJIS_L1, // 匛 + 0x6065, KANJI_SJIS_L1, // 恥 + 0x667A, KANJI_SJIS_L1, // 智 + 0x6C60, KANJI_SJIS_L1, // æ±  + 0x75F4, KANJI_SJIS_L1, // 痮 + 0x7A1A, KANJI_SJIS_L1, // 繚 + 0x7F6E, KANJI_SJIS_L1, // 眮 + 0x81F4, KANJI_SJIS_L1, // 臎 + 0x8718, KANJI_SJIS_L1, // 蜘 + 0x9045, KANJI_SJIS_L1, // 遅 + 0x99B3, KANJI_SJIS_L1, // 銳 + 0x7BC9, KANJI_SJIS_L1, // 築 + 0x755C, KANJI_SJIS_L1, // 畜 + 0x7AF9, KANJI_SJIS_L1, // 竹 + 0x7B51, KANJI_SJIS_L1, // 筑 + 0x84C4, KANJI_SJIS_L1, // 蓄 + 0x3000, KANJI_SJIS_L1, //   + 0x9010, KANJI_SJIS_L1, // 逐 + 0x79E9, KANJI_SJIS_L1, // ç§© + 0x7A92, KANJI_SJIS_L1, // 窒 + 0x8336, KANJI_SJIS_L1, // 茶 + 0x5AE1, KANJI_SJIS_L1, // å«¡ + 0x7740, KANJI_SJIS_L1, // 着 + 0x4E2D, KANJI_SJIS_L1, // äž­ + 0x4EF2, KANJI_SJIS_L1, // 仲 + 0x5B99, KANJI_SJIS_L1, // 宙 + 0x5FE0, KANJI_SJIS_L1, // å¿  + 0x62BD, KANJI_SJIS_L1, // 抜 + 0x663C, KANJI_SJIS_L1, // 昌 + 0x67F1, KANJI_SJIS_L1, // 柱 + 0x6CE8, KANJI_SJIS_L1, // 泚 + 0x866B, KANJI_SJIS_L1, // 虫 + 0x8877, KANJI_SJIS_L1, // è¡· + 0x8A3B, KANJI_SJIS_L1, // èš» + 0x914E, KANJI_SJIS_L1, // 酎 + 0x92F3, KANJI_SJIS_L1, // 鋳 + 0x99D0, KANJI_SJIS_L1, // 駐 + 0x6A17, KANJI_SJIS_L1, // æš— + 0x7026, KANJI_SJIS_L1, // 瀩 + 0x732A, KANJI_SJIS_L1, // 猪 + 0x82E7, KANJI_SJIS_L1, // 苧 + 0x8457, KANJI_SJIS_L1, // 著 + 0x8CAF, KANJI_SJIS_L1, // 貯 + 0x4E01, KANJI_SJIS_L1, // 䞁 + 0x5146, KANJI_SJIS_L1, // 兆 + 0x51CB, KANJI_SJIS_L1, // 凋 + 0x558B, KANJI_SJIS_L1, // 喋 + 0x5BF5, KANJI_SJIS_L1, // 寵 + 0x5E16, KANJI_SJIS_L1, // åž– + 0x5E33, KANJI_SJIS_L1, // åž³ + 0x5E81, KANJI_SJIS_L1, // 庁 + 0x5F14, KANJI_SJIS_L1, // 匔 + 0x5F35, KANJI_SJIS_L1, // 匵 + 0x5F6B, KANJI_SJIS_L1, // 圫 + 0x5FB4, KANJI_SJIS_L1, // 城 + 0x61F2, KANJI_SJIS_L1, // 懲 + 0x6311, KANJI_SJIS_L1, // 挑 + 0x66A2, KANJI_SJIS_L1, // 暢 + 0x671D, KANJI_SJIS_L1, // 朝 + 0x6F6E, KANJI_SJIS_L1, // 朮 + 0x7252, KANJI_SJIS_L1, // 牒 + 0x753A, KANJI_SJIS_L1, // 町 + 0x773A, KANJI_SJIS_L1, // 眺 + 0x8074, KANJI_SJIS_L1, // 聎 + 0x8139, KANJI_SJIS_L1, // 脹 + 0x8178, KANJI_SJIS_L1, // è…ž + 0x8776, KANJI_SJIS_L1, // 蝶 + 0x8ABF, KANJI_SJIS_L1, // 調 + 0x8ADC, KANJI_SJIS_L1, // 諜 + 0x8D85, KANJI_SJIS_L1, // 超 + 0x8DF3, KANJI_SJIS_L1, // è·³ + 0x929A, KANJI_SJIS_L1, // 銚 + 0x9577, KANJI_SJIS_L1, // 長 + 0x9802, KANJI_SJIS_L1, // 頂 + 0x9CE5, KANJI_SJIS_L1, // é³¥ + 0x52C5, KANJI_SJIS_L1, // 勅 + 0x6357, KANJI_SJIS_L1, // 捗 + 0x76F4, KANJI_SJIS_L1, // 目 + 0x6715, KANJI_SJIS_L1, // 朕 + 0x6C88, KANJI_SJIS_L1, // 沈 + 0x73CD, KANJI_SJIS_L1, // 珍 + 0x8CC3, KANJI_SJIS_L1, // 賃 + 0x93AE, KANJI_SJIS_L1, // 鎮 + 0x9673, KANJI_SJIS_L1, // 陳 + 0x6D25, KANJI_SJIS_L1, // 接 + 0x589C, KANJI_SJIS_L1, // 墜 + 0x690E, KANJI_SJIS_L1, // 怎 + 0x69CC, KANJI_SJIS_L1, // 槌 + 0x8FFD, KANJI_SJIS_L1, // 远 + 0x939A, KANJI_SJIS_L1, // 鎚 + 0x75DB, KANJI_SJIS_L1, // 痛 + 0x901A, KANJI_SJIS_L1, // 通 + 0x585A, KANJI_SJIS_L1, // 塚 + 0x6802, KANJI_SJIS_L1, // 栂 + 0x63B4, KANJI_SJIS_L1, // 掎 + 0x69FB, KANJI_SJIS_L1, // æ§» + 0x4F43, KANJI_SJIS_L1, // 䜃 + 0x6F2C, KANJI_SJIS_L1, // 挬 + 0x67D8, KANJI_SJIS_L1, // 柘 + 0x8FBB, KANJI_SJIS_L1, // 蟻 + 0x8526, KANJI_SJIS_L1, // 蔊 + 0x7DB4, KANJI_SJIS_L1, // ç¶Ž + 0x9354, KANJI_SJIS_L1, // 鍔 + 0x693F, KANJI_SJIS_L1, // 怿 + 0x6F70, KANJI_SJIS_L1, // 朰 + 0x576A, KANJI_SJIS_L1, // 坪 + 0x58F7, KANJI_SJIS_L1, // 壷 + 0x5B2C, KANJI_SJIS_L1, // 嬬 + 0x7D2C, KANJI_SJIS_L1, // 玬 + 0x722A, KANJI_SJIS_L1, // 爪 + 0x540A, KANJI_SJIS_L1, // 吊 + 0x91E3, KANJI_SJIS_L1, // 釣 + 0x9DB4, KANJI_SJIS_L1, // é¶Ž + 0x4EAD, KANJI_SJIS_L1, // 亭 + 0x4F4E, KANJI_SJIS_L1, // 䜎 + 0x505C, KANJI_SJIS_L1, // 停 + 0x5075, KANJI_SJIS_L1, // 偵 + 0x5243, KANJI_SJIS_L1, // 剃 + 0x8C9E, KANJI_SJIS_L1, // 貞 + 0x5448, KANJI_SJIS_L1, // 呈 + 0x5824, KANJI_SJIS_L1, // å € + 0x5B9A, KANJI_SJIS_L1, // 定 + 0x5E1D, KANJI_SJIS_L1, // 垝 + 0x5E95, KANJI_SJIS_L1, // 底 + 0x5EAD, KANJI_SJIS_L1, // 庭 + 0x5EF7, KANJI_SJIS_L1, // å»· + 0x5F1F, KANJI_SJIS_L1, // 匟 + 0x608C, KANJI_SJIS_L1, // 悌 + 0x62B5, KANJI_SJIS_L1, // 抵 + 0x633A, KANJI_SJIS_L1, // 挺 + 0x63D0, KANJI_SJIS_L1, // 提 + 0x68AF, KANJI_SJIS_L1, // 梯 + 0x6C40, KANJI_SJIS_L1, // 汀 + 0x7887, KANJI_SJIS_L1, // 碇 + 0x798E, KANJI_SJIS_L1, // 犎 + 0x7A0B, KANJI_SJIS_L1, // 繋 + 0x7DE0, KANJI_SJIS_L1, // ç·  + 0x8247, KANJI_SJIS_L1, // 艇 + 0x8A02, KANJI_SJIS_L1, // èš‚ + 0x8AE6, KANJI_SJIS_L1, // 諊 + 0x8E44, KANJI_SJIS_L1, // 蹄 + 0x9013, KANJI_SJIS_L1, // 逓 + 0x90B8, KANJI_SJIS_L1, // 邾 + 0x912D, KANJI_SJIS_L1, // 鄭 + 0x91D8, KANJI_SJIS_L1, // 釘 + 0x9F0E, KANJI_SJIS_L1, // 錎 + 0x6CE5, KANJI_SJIS_L1, // æ³¥ + 0x6458, KANJI_SJIS_L1, // 摘 + 0x64E2, KANJI_SJIS_L1, // 擢 + 0x6575, KANJI_SJIS_L1, // 敵 + 0x6EF4, KANJI_SJIS_L1, // 滎 + 0x7684, KANJI_SJIS_L1, // 的 + 0x7B1B, KANJI_SJIS_L1, // 笛 + 0x9069, KANJI_SJIS_L1, // 適 + 0x93D1, KANJI_SJIS_L1, // 鏑 + 0x6EBA, KANJI_SJIS_L1, // 溺 + 0x54F2, KANJI_SJIS_L1, // 哲 + 0x5FB9, KANJI_SJIS_L1, // 培 + 0x64A4, KANJI_SJIS_L1, // æ’€ + 0x8F4D, KANJI_SJIS_L1, // 蜍 + 0x8FED, KANJI_SJIS_L1, // è¿­ + 0x9244, KANJI_SJIS_L1, // 鉄 + 0x5178, KANJI_SJIS_L1, // å…ž + 0x586B, KANJI_SJIS_L1, // å¡« + 0x5929, KANJI_SJIS_L1, // 倩 + 0x5C55, KANJI_SJIS_L1, // 展 + 0x5E97, KANJI_SJIS_L1, // 店 + 0x6DFB, KANJI_SJIS_L1, // æ·» + 0x7E8F, KANJI_SJIS_L1, // 纏 + 0x751C, KANJI_SJIS_L1, // 甜 + 0x8CBC, KANJI_SJIS_L1, // 貌 + 0x8EE2, KANJI_SJIS_L1, // 転 + 0x985B, KANJI_SJIS_L1, // 顛 + 0x70B9, KANJI_SJIS_L1, // 点 + 0x4F1D, KANJI_SJIS_L1, // 䌝 + 0x6BBF, KANJI_SJIS_L1, // 殿 + 0x6FB1, KANJI_SJIS_L1, // 柱 + 0x7530, KANJI_SJIS_L1, // 田 + 0x96FB, KANJI_SJIS_L1, // 電 + 0x514E, KANJI_SJIS_L1, // 兎 + 0x5410, KANJI_SJIS_L1, // 吐 + 0x5835, KANJI_SJIS_L1, // å µ + 0x5857, KANJI_SJIS_L1, // 塗 + 0x59AC, KANJI_SJIS_L1, // 劬 + 0x5C60, KANJI_SJIS_L1, // å±  + 0x5F92, KANJI_SJIS_L1, // 埒 + 0x6597, KANJI_SJIS_L1, // 斗 + 0x675C, KANJI_SJIS_L1, // 杜 + 0x6E21, KANJI_SJIS_L1, // æž¡ + 0x767B, KANJI_SJIS_L1, // 登 + 0x83DF, KANJI_SJIS_L1, // 菟 + 0x8CED, KANJI_SJIS_L1, // è³­ + 0x9014, KANJI_SJIS_L1, // 途 + 0x90FD, KANJI_SJIS_L1, // 郜 + 0x934D, KANJI_SJIS_L1, // 鍍 + 0x7825, KANJI_SJIS_L1, // ç ¥ + 0x783A, KANJI_SJIS_L1, // ç º + 0x52AA, KANJI_SJIS_L1, // 努 + 0x5EA6, KANJI_SJIS_L1, // 床 + 0x571F, KANJI_SJIS_L1, // 土 + 0x5974, KANJI_SJIS_L1, // 奎 + 0x6012, KANJI_SJIS_L1, // 怒 + 0x5012, KANJI_SJIS_L1, // 倒 + 0x515A, KANJI_SJIS_L1, // 党 + 0x51AC, KANJI_SJIS_L1, // 冬 + 0x3000, KANJI_SJIS_L1, //   + 0x51CD, KANJI_SJIS_L1, // 凍 + 0x5200, KANJI_SJIS_L1, // 刀 + 0x5510, KANJI_SJIS_L1, // 唐 + 0x5854, KANJI_SJIS_L1, // 塔 + 0x5858, KANJI_SJIS_L1, // 塘 + 0x5957, KANJI_SJIS_L1, // 套 + 0x5B95, KANJI_SJIS_L1, // 宕 + 0x5CF6, KANJI_SJIS_L1, // å³¶ + 0x5D8B, KANJI_SJIS_L1, // 嶋 + 0x60BC, KANJI_SJIS_L1, // 悌 + 0x6295, KANJI_SJIS_L1, // 投 + 0x642D, KANJI_SJIS_L1, // 搭 + 0x6771, KANJI_SJIS_L1, // 東 + 0x6843, KANJI_SJIS_L1, // 桃 + 0x68BC, KANJI_SJIS_L1, // 梌 + 0x68DF, KANJI_SJIS_L1, // 棟 + 0x76D7, KANJI_SJIS_L1, // 盗 + 0x6DD8, KANJI_SJIS_L1, // 淘 + 0x6E6F, KANJI_SJIS_L1, // 湯 + 0x6D9B, KANJI_SJIS_L1, // 涛 + 0x706F, KANJI_SJIS_L1, // 灯 + 0x71C8, KANJI_SJIS_L1, // 燈 + 0x5F53, KANJI_SJIS_L1, // 圓 + 0x75D8, KANJI_SJIS_L1, // 痘 + 0x7977, KANJI_SJIS_L1, // 祷 + 0x7B49, KANJI_SJIS_L1, // 等 + 0x7B54, KANJI_SJIS_L1, // 答 + 0x7B52, KANJI_SJIS_L1, // 筒 + 0x7CD6, KANJI_SJIS_L1, // 糖 + 0x7D71, KANJI_SJIS_L1, // çµ± + 0x5230, KANJI_SJIS_L1, // 到 + 0x8463, KANJI_SJIS_L1, // 董 + 0x8569, KANJI_SJIS_L1, // 蕩 + 0x85E4, KANJI_SJIS_L1, // è—€ + 0x8A0E, KANJI_SJIS_L1, // 蚎 + 0x8B04, KANJI_SJIS_L1, // 謄 + 0x8C46, KANJI_SJIS_L1, // 豆 + 0x8E0F, KANJI_SJIS_L1, // 螏 + 0x9003, KANJI_SJIS_L1, // 逃 + 0x900F, KANJI_SJIS_L1, // 透 + 0x9419, KANJI_SJIS_L1, // 鐙 + 0x9676, KANJI_SJIS_L1, // 陶 + 0x982D, KANJI_SJIS_L1, // é ­ + 0x9A30, KANJI_SJIS_L1, // éš° + 0x95D8, KANJI_SJIS_L1, // 闘 + 0x50CD, KANJI_SJIS_L1, // 働 + 0x52D5, KANJI_SJIS_L1, // 動 + 0x540C, KANJI_SJIS_L1, // 同 + 0x5802, KANJI_SJIS_L1, // 堂 + 0x5C0E, KANJI_SJIS_L1, // 導 + 0x61A7, KANJI_SJIS_L1, // 憧 + 0x649E, KANJI_SJIS_L1, // 撞 + 0x6D1E, KANJI_SJIS_L1, // 掞 + 0x77B3, KANJI_SJIS_L1, // 瞳 + 0x7AE5, KANJI_SJIS_L1, // ç«¥ + 0x80F4, KANJI_SJIS_L1, // 胎 + 0x8404, KANJI_SJIS_L1, // 萄 + 0x9053, KANJI_SJIS_L1, // 道 + 0x9285, KANJI_SJIS_L1, // 銅 + 0x5CE0, KANJI_SJIS_L1, // å³  + 0x9D07, KANJI_SJIS_L1, // 鮇 + 0x533F, KANJI_SJIS_L1, // 匿 + 0x5F97, KANJI_SJIS_L1, // 埗 + 0x5FB3, KANJI_SJIS_L1, // 埳 + 0x6D9C, KANJI_SJIS_L1, // 涜 + 0x7279, KANJI_SJIS_L1, // 特 + 0x7763, KANJI_SJIS_L1, // 督 + 0x79BF, KANJI_SJIS_L1, // 犿 + 0x7BE4, KANJI_SJIS_L1, // 節 + 0x6BD2, KANJI_SJIS_L1, // 毒 + 0x72EC, KANJI_SJIS_L1, // 独 + 0x8AAD, KANJI_SJIS_L1, // 読 + 0x6803, KANJI_SJIS_L1, // 栃 + 0x6A61, KANJI_SJIS_L1, // æ©¡ + 0x51F8, KANJI_SJIS_L1, // 凞 + 0x7A81, KANJI_SJIS_L1, // 突 + 0x6934, KANJI_SJIS_L1, // 怎 + 0x5C4A, KANJI_SJIS_L1, // 届 + 0x9CF6, KANJI_SJIS_L1, // é³¶ + 0x82EB, KANJI_SJIS_L1, // 苫 + 0x5BC5, KANJI_SJIS_L1, // 寅 + 0x9149, KANJI_SJIS_L1, // 酉 + 0x701E, KANJI_SJIS_L1, // 瀞 + 0x5678, KANJI_SJIS_L1, // 噞 + 0x5C6F, KANJI_SJIS_L1, // 屯 + 0x60C7, KANJI_SJIS_L1, // 惇 + 0x6566, KANJI_SJIS_L1, // 敊 + 0x6C8C, KANJI_SJIS_L1, // 沌 + 0x8C5A, KANJI_SJIS_L1, // 豚 + 0x9041, KANJI_SJIS_L1, // 遁 + 0x9813, KANJI_SJIS_L1, // 頓 + 0x5451, KANJI_SJIS_L1, // 呑 + 0x66C7, KANJI_SJIS_L1, // 曇 + 0x920D, KANJI_SJIS_L1, // 鈍 + 0x5948, KANJI_SJIS_L1, // 奈 + 0x90A3, KANJI_SJIS_L1, // 那 + 0x5185, KANJI_SJIS_L1, // 内 + 0x4E4D, KANJI_SJIS_L1, // 乍 + 0x51EA, KANJI_SJIS_L1, // 凪 + 0x8599, KANJI_SJIS_L1, // 薙 + 0x8B0E, KANJI_SJIS_L1, // 謎 + 0x7058, KANJI_SJIS_L1, // 灘 + 0x637A, KANJI_SJIS_L1, // 捺 + 0x934B, KANJI_SJIS_L1, // 鍋 + 0x6962, KANJI_SJIS_L1, // 楢 + 0x99B4, KANJI_SJIS_L1, // 銎 + 0x7E04, KANJI_SJIS_L1, // 羄 + 0x7577, KANJI_SJIS_L1, // 畷 + 0x5357, KANJI_SJIS_L1, // 南 + 0x6960, KANJI_SJIS_L1, // 楠 + 0x8EDF, KANJI_SJIS_L1, // 軟 + 0x96E3, KANJI_SJIS_L1, // 難 + 0x6C5D, KANJI_SJIS_L1, // 汝 + 0x4E8C, KANJI_SJIS_L1, // 二 + 0x5C3C, KANJI_SJIS_L1, // å°Œ + 0x5F10, KANJI_SJIS_L1, // 匐 + 0x8FE9, KANJI_SJIS_L1, // è¿© + 0x5302, KANJI_SJIS_L1, // 匂 + 0x8CD1, KANJI_SJIS_L1, // 賑 + 0x8089, KANJI_SJIS_L1, // 肉 + 0x8679, KANJI_SJIS_L1, // 虹 + 0x5EFF, KANJI_SJIS_L1, // 廿 + 0x65E5, KANJI_SJIS_L1, // 日 + 0x4E73, KANJI_SJIS_L1, // ä¹³ + 0x5165, KANJI_SJIS_L1, // 入 + 0x5982, KANJI_SJIS_L1, // 劂 + 0x5C3F, KANJI_SJIS_L1, // å°¿ + 0x97EE, KANJI_SJIS_L1, // 韮 + 0x4EFB, KANJI_SJIS_L1, // ä»» + 0x598A, KANJI_SJIS_L1, // 劊 + 0x5FCD, KANJI_SJIS_L1, // 忍 + 0x8A8D, KANJI_SJIS_L1, // 認 + 0x6FE1, KANJI_SJIS_L1, // æ¿¡ + 0x79B0, KANJI_SJIS_L1, // 犰 + 0x7962, KANJI_SJIS_L1, // 祢 + 0x5BE7, KANJI_SJIS_L1, // 寧 + 0x8471, KANJI_SJIS_L1, // 葱 + 0x732B, KANJI_SJIS_L1, // 猫 + 0x71B1, KANJI_SJIS_L1, // 熱 + 0x5E74, KANJI_SJIS_L1, // 幎 + 0x5FF5, KANJI_SJIS_L1, // 念 + 0x637B, KANJI_SJIS_L1, // 捻 + 0x649A, KANJI_SJIS_L1, // 撚 + 0x71C3, KANJI_SJIS_L1, // 燃 + 0x7C98, KANJI_SJIS_L1, // 粘 + 0x4E43, KANJI_SJIS_L1, // 乃 + 0x5EFC, KANJI_SJIS_L1, // 廌 + 0x4E4B, KANJI_SJIS_L1, // 之 + 0x57DC, KANJI_SJIS_L1, // 埜 + 0x56A2, KANJI_SJIS_L1, // 嚢 + 0x60A9, KANJI_SJIS_L1, // 悩 + 0x6FC3, KANJI_SJIS_L1, // 濃 + 0x7D0D, KANJI_SJIS_L1, // 玍 + 0x80FD, KANJI_SJIS_L1, // 胜 + 0x8133, KANJI_SJIS_L1, // 脳 + 0x81BF, KANJI_SJIS_L1, // 膿 + 0x8FB2, KANJI_SJIS_L1, // 蟲 + 0x8997, KANJI_SJIS_L1, // 芗 + 0x86A4, KANJI_SJIS_L1, // 蚀 + 0x5DF4, KANJI_SJIS_L1, // å·Ž + 0x628A, KANJI_SJIS_L1, // 把 + 0x64AD, KANJI_SJIS_L1, // 播 + 0x8987, KANJI_SJIS_L1, // 芇 + 0x6777, KANJI_SJIS_L1, // 杷 + 0x6CE2, KANJI_SJIS_L1, // æ³¢ + 0x6D3E, KANJI_SJIS_L1, // 掟 + 0x7436, KANJI_SJIS_L1, // 琶 + 0x7834, KANJI_SJIS_L1, // ç Ž + 0x5A46, KANJI_SJIS_L1, // 婆 + 0x7F75, KANJI_SJIS_L1, // 眵 + 0x82AD, KANJI_SJIS_L1, // 芭 + 0x99AC, KANJI_SJIS_L1, // 銬 + 0x4FF3, KANJI_SJIS_L1, // 俳 + 0x5EC3, KANJI_SJIS_L1, // 廃 + 0x62DD, KANJI_SJIS_L1, // 拝 + 0x6392, KANJI_SJIS_L1, // 排 + 0x6557, KANJI_SJIS_L1, // 敗 + 0x676F, KANJI_SJIS_L1, // 杯 + 0x76C3, KANJI_SJIS_L1, // 盃 + 0x724C, KANJI_SJIS_L1, // 牌 + 0x80CC, KANJI_SJIS_L1, // 背 + 0x80BA, KANJI_SJIS_L1, // 肺 + 0x8F29, KANJI_SJIS_L1, // 茩 + 0x914D, KANJI_SJIS_L1, // 配 + 0x500D, KANJI_SJIS_L1, // 倍 + 0x57F9, KANJI_SJIS_L1, // 培 + 0x5A92, KANJI_SJIS_L1, // 媒 + 0x6885, KANJI_SJIS_L1, // 梅 + 0x3000, KANJI_SJIS_L1, //   + 0x6973, KANJI_SJIS_L1, // 楳 + 0x7164, KANJI_SJIS_L1, // ç…€ + 0x72FD, KANJI_SJIS_L1, // 狜 + 0x8CB7, KANJI_SJIS_L1, // è²· + 0x58F2, KANJI_SJIS_L1, // 売 + 0x8CE0, KANJI_SJIS_L1, // è³  + 0x966A, KANJI_SJIS_L1, // 陪 + 0x9019, KANJI_SJIS_L1, // 這 + 0x877F, KANJI_SJIS_L1, // 蝿 + 0x79E4, KANJI_SJIS_L1, // ç§€ + 0x77E7, KANJI_SJIS_L1, // 矧 + 0x8429, KANJI_SJIS_L1, // 萩 + 0x4F2F, KANJI_SJIS_L1, // 䌯 + 0x5265, KANJI_SJIS_L1, // 剥 + 0x535A, KANJI_SJIS_L1, // 博 + 0x62CD, KANJI_SJIS_L1, // 拍 + 0x67CF, KANJI_SJIS_L1, // 柏 + 0x6CCA, KANJI_SJIS_L1, // 泊 + 0x767D, KANJI_SJIS_L1, // 癜 + 0x7B94, KANJI_SJIS_L1, // 箔 + 0x7C95, KANJI_SJIS_L1, // 粕 + 0x8236, KANJI_SJIS_L1, // 舶 + 0x8584, KANJI_SJIS_L1, // 薄 + 0x8FEB, KANJI_SJIS_L1, // è¿« + 0x66DD, KANJI_SJIS_L1, // 曝 + 0x6F20, KANJI_SJIS_L1, // 挠 + 0x7206, KANJI_SJIS_L1, // 爆 + 0x7E1B, KANJI_SJIS_L1, // 羛 + 0x83AB, KANJI_SJIS_L1, // 莫 + 0x99C1, KANJI_SJIS_L1, // 駁 + 0x9EA6, KANJI_SJIS_L1, // 麊 + 0x51FD, KANJI_SJIS_L1, // 凜 + 0x7BB1, KANJI_SJIS_L1, // ç®± + 0x7872, KANJI_SJIS_L1, // 硲 + 0x7BB8, KANJI_SJIS_L1, // 箞 + 0x8087, KANJI_SJIS_L1, // 肇 + 0x7B48, KANJI_SJIS_L1, // 筈 + 0x6AE8, KANJI_SJIS_L1, // 櫚 + 0x5E61, KANJI_SJIS_L1, // 幡 + 0x808C, KANJI_SJIS_L1, // 肌 + 0x7551, KANJI_SJIS_L1, // 畑 + 0x7560, KANJI_SJIS_L1, // 畠 + 0x516B, KANJI_SJIS_L1, // 八 + 0x9262, KANJI_SJIS_L1, // 鉢 + 0x6E8C, KANJI_SJIS_L1, // 溌 + 0x767A, KANJI_SJIS_L1, // 発 + 0x9197, KANJI_SJIS_L1, // 醗 + 0x9AEA, KANJI_SJIS_L1, // 髪 + 0x4F10, KANJI_SJIS_L1, // 䌐 + 0x7F70, KANJI_SJIS_L1, // 眰 + 0x629C, KANJI_SJIS_L1, // 抜 + 0x7B4F, KANJI_SJIS_L1, // 筏 + 0x95A5, KANJI_SJIS_L1, // 閥 + 0x9CE9, KANJI_SJIS_L1, // 鳩 + 0x567A, KANJI_SJIS_L1, // 噺 + 0x5859, KANJI_SJIS_L1, // 塙 + 0x86E4, KANJI_SJIS_L1, // 蛀 + 0x96BC, KANJI_SJIS_L1, // 隌 + 0x4F34, KANJI_SJIS_L1, // 䌎 + 0x5224, KANJI_SJIS_L1, // 刀 + 0x534A, KANJI_SJIS_L1, // 半 + 0x53CD, KANJI_SJIS_L1, // 反 + 0x53DB, KANJI_SJIS_L1, // 叛 + 0x5E06, KANJI_SJIS_L1, // 垆 + 0x642C, KANJI_SJIS_L1, // 搬 + 0x6591, KANJI_SJIS_L1, // 斑 + 0x677F, KANJI_SJIS_L1, // 板 + 0x6C3E, KANJI_SJIS_L1, // æ°Ÿ + 0x6C4E, KANJI_SJIS_L1, // 汎 + 0x7248, KANJI_SJIS_L1, // 版 + 0x72AF, KANJI_SJIS_L1, // 犯 + 0x73ED, KANJI_SJIS_L1, // 班 + 0x7554, KANJI_SJIS_L1, // 畔 + 0x7E41, KANJI_SJIS_L1, // 繁 + 0x822C, KANJI_SJIS_L1, // 般 + 0x85E9, KANJI_SJIS_L1, // 藩 + 0x8CA9, KANJI_SJIS_L1, // 販 + 0x7BC4, KANJI_SJIS_L1, // 範 + 0x91C6, KANJI_SJIS_L1, // 釆 + 0x7169, KANJI_SJIS_L1, // 煩 + 0x9812, KANJI_SJIS_L1, // 頒 + 0x98EF, KANJI_SJIS_L1, // 飯 + 0x633D, KANJI_SJIS_L1, // 挜 + 0x6669, KANJI_SJIS_L1, // 晩 + 0x756A, KANJI_SJIS_L1, // 番 + 0x76E4, KANJI_SJIS_L1, // 盀 + 0x78D0, KANJI_SJIS_L1, // 磐 + 0x8543, KANJI_SJIS_L1, // 蕃 + 0x86EE, KANJI_SJIS_L1, // 蛮 + 0x532A, KANJI_SJIS_L1, // 匪 + 0x5351, KANJI_SJIS_L1, // 卑 + 0x5426, KANJI_SJIS_L1, // 吊 + 0x5983, KANJI_SJIS_L1, // 劃 + 0x5E87, KANJI_SJIS_L1, // 庇 + 0x5F7C, KANJI_SJIS_L1, // 圌 + 0x60B2, KANJI_SJIS_L1, // 悲 + 0x6249, KANJI_SJIS_L1, // 扉 + 0x6279, KANJI_SJIS_L1, // 批 + 0x62AB, KANJI_SJIS_L1, // 披 + 0x6590, KANJI_SJIS_L1, // 斐 + 0x6BD4, KANJI_SJIS_L1, // 比 + 0x6CCC, KANJI_SJIS_L1, // 泌 + 0x75B2, KANJI_SJIS_L1, // 疲 + 0x76AE, KANJI_SJIS_L1, // 皮 + 0x7891, KANJI_SJIS_L1, // 碑 + 0x79D8, KANJI_SJIS_L1, // 秘 + 0x7DCB, KANJI_SJIS_L1, // 緋 + 0x7F77, KANJI_SJIS_L1, // 眷 + 0x80A5, KANJI_SJIS_L1, // 肥 + 0x88AB, KANJI_SJIS_L1, // 被 + 0x8AB9, KANJI_SJIS_L1, // 誹 + 0x8CBB, KANJI_SJIS_L1, // è²» + 0x907F, KANJI_SJIS_L1, // 避 + 0x975E, KANJI_SJIS_L1, // 非 + 0x98DB, KANJI_SJIS_L1, // 飛 + 0x6A0B, KANJI_SJIS_L1, // æš‹ + 0x7C38, KANJI_SJIS_L1, // ç°ž + 0x5099, KANJI_SJIS_L1, // 備 + 0x5C3E, KANJI_SJIS_L1, // å°Ÿ + 0x5FAE, KANJI_SJIS_L1, // 埮 + 0x6787, KANJI_SJIS_L1, // 枇 + 0x6BD8, KANJI_SJIS_L1, // 毘 + 0x7435, KANJI_SJIS_L1, // 琵 + 0x7709, KANJI_SJIS_L1, // 眉 + 0x7F8E, KANJI_SJIS_L1, // 矎 + 0x9F3B, KANJI_SJIS_L1, // 錻 + 0x67CA, KANJI_SJIS_L1, // 柊 + 0x7A17, KANJI_SJIS_L1, // 繗 + 0x5339, KANJI_SJIS_L1, // 匹 + 0x758B, KANJI_SJIS_L1, // 疋 + 0x9AED, KANJI_SJIS_L1, // é«­ + 0x5F66, KANJI_SJIS_L1, // 圊 + 0x819D, KANJI_SJIS_L1, // 膝 + 0x83F1, KANJI_SJIS_L1, // 菱 + 0x8098, KANJI_SJIS_L1, // 肘 + 0x5F3C, KANJI_SJIS_L1, // 匌 + 0x5FC5, KANJI_SJIS_L1, // 必 + 0x7562, KANJI_SJIS_L1, // 畢 + 0x7B46, KANJI_SJIS_L1, // 筆 + 0x903C, KANJI_SJIS_L1, // 逌 + 0x6867, KANJI_SJIS_L1, // æ¡§ + 0x59EB, KANJI_SJIS_L1, // å§« + 0x5A9B, KANJI_SJIS_L1, // 媛 + 0x7D10, KANJI_SJIS_L1, // 玐 + 0x767E, KANJI_SJIS_L1, // 癟 + 0x8B2C, KANJI_SJIS_L1, // 謬 + 0x4FF5, KANJI_SJIS_L1, // 俵 + 0x5F6A, KANJI_SJIS_L1, // 圪 + 0x6A19, KANJI_SJIS_L1, // æš™ + 0x6C37, KANJI_SJIS_L1, // æ°· + 0x6F02, KANJI_SJIS_L1, // 挂 + 0x74E2, KANJI_SJIS_L1, // 瓢 + 0x7968, KANJI_SJIS_L1, // 祚 + 0x8868, KANJI_SJIS_L1, // 衚 + 0x8A55, KANJI_SJIS_L1, // 評 + 0x8C79, KANJI_SJIS_L1, // è±¹ + 0x5EDF, KANJI_SJIS_L1, // 廟 + 0x63CF, KANJI_SJIS_L1, // 描 + 0x75C5, KANJI_SJIS_L1, // 病 + 0x79D2, KANJI_SJIS_L1, // 秒 + 0x82D7, KANJI_SJIS_L1, // 苗 + 0x9328, KANJI_SJIS_L1, // 錹 + 0x92F2, KANJI_SJIS_L1, // 鋲 + 0x849C, KANJI_SJIS_L1, // 蒜 + 0x86ED, KANJI_SJIS_L1, // 蛭 + 0x9C2D, KANJI_SJIS_L1, // é°­ + 0x54C1, KANJI_SJIS_L1, // 品 + 0x5F6C, KANJI_SJIS_L1, // 圬 + 0x658C, KANJI_SJIS_L1, // 斌 + 0x6D5C, KANJI_SJIS_L1, // 浜 + 0x7015, KANJI_SJIS_L1, // 瀕 + 0x8CA7, KANJI_SJIS_L1, // è²§ + 0x8CD3, KANJI_SJIS_L1, // 賓 + 0x983B, KANJI_SJIS_L1, // é » + 0x654F, KANJI_SJIS_L1, // 敏 + 0x74F6, KANJI_SJIS_L1, // 瓶 + 0x4E0D, KANJI_SJIS_L1, // 䞍 + 0x4ED8, KANJI_SJIS_L1, // 付 + 0x57E0, KANJI_SJIS_L1, // 埠 + 0x592B, KANJI_SJIS_L1, // 倫 + 0x5A66, KANJI_SJIS_L1, // 婊 + 0x5BCC, KANJI_SJIS_L1, // 富 + 0x51A8, KANJI_SJIS_L1, // 冚 + 0x5E03, KANJI_SJIS_L1, // 垃 + 0x5E9C, KANJI_SJIS_L1, // 府 + 0x6016, KANJI_SJIS_L1, // 怖 + 0x6276, KANJI_SJIS_L1, // 扶 + 0x6577, KANJI_SJIS_L1, // 敷 + 0x3000, KANJI_SJIS_L1, //   + 0x65A7, KANJI_SJIS_L1, // 斧 + 0x666E, KANJI_SJIS_L1, // 普 + 0x6D6E, KANJI_SJIS_L1, // æµ® + 0x7236, KANJI_SJIS_L1, // 父 + 0x7B26, KANJI_SJIS_L1, // 笊 + 0x8150, KANJI_SJIS_L1, // 腐 + 0x819A, KANJI_SJIS_L1, // 膚 + 0x8299, KANJI_SJIS_L1, // 芙 + 0x8B5C, KANJI_SJIS_L1, // 譜 + 0x8CA0, KANJI_SJIS_L1, // è²  + 0x8CE6, KANJI_SJIS_L1, // 賊 + 0x8D74, KANJI_SJIS_L1, // 赎 + 0x961C, KANJI_SJIS_L1, // 阜 + 0x9644, KANJI_SJIS_L1, // 附 + 0x4FAE, KANJI_SJIS_L1, // 䟮 + 0x64AB, KANJI_SJIS_L1, // 撫 + 0x6B66, KANJI_SJIS_L1, // æ­Š + 0x821E, KANJI_SJIS_L1, // 舞 + 0x8461, KANJI_SJIS_L1, // 葡 + 0x856A, KANJI_SJIS_L1, // 蕪 + 0x90E8, KANJI_SJIS_L1, // 郚 + 0x5C01, KANJI_SJIS_L1, // 封 + 0x6953, KANJI_SJIS_L1, // 楓 + 0x98A8, KANJI_SJIS_L1, // 颚 + 0x847A, KANJI_SJIS_L1, // 葺 + 0x8557, KANJI_SJIS_L1, // 蕗 + 0x4F0F, KANJI_SJIS_L1, // 䌏 + 0x526F, KANJI_SJIS_L1, // 副 + 0x5FA9, KANJI_SJIS_L1, // 埩 + 0x5E45, KANJI_SJIS_L1, // 幅 + 0x670D, KANJI_SJIS_L1, // 服 + 0x798F, KANJI_SJIS_L1, // 犏 + 0x8179, KANJI_SJIS_L1, // 腹 + 0x8907, KANJI_SJIS_L1, // 耇 + 0x8986, KANJI_SJIS_L1, // 芆 + 0x6DF5, KANJI_SJIS_L1, // æ·µ + 0x5F17, KANJI_SJIS_L1, // 北 + 0x6255, KANJI_SJIS_L1, // 払 + 0x6CB8, KANJI_SJIS_L1, // 沞 + 0x4ECF, KANJI_SJIS_L1, // 仏 + 0x7269, KANJI_SJIS_L1, // 物 + 0x9B92, KANJI_SJIS_L1, // 鮒 + 0x5206, KANJI_SJIS_L1, // 分 + 0x543B, KANJI_SJIS_L1, // 吻 + 0x5674, KANJI_SJIS_L1, // 噎 + 0x58B3, KANJI_SJIS_L1, // 墳 + 0x61A4, KANJI_SJIS_L1, // 憀 + 0x626E, KANJI_SJIS_L1, // 扮 + 0x711A, KANJI_SJIS_L1, // 焚 + 0x596E, KANJI_SJIS_L1, // 奮 + 0x7C89, KANJI_SJIS_L1, // 粉 + 0x7CDE, KANJI_SJIS_L1, // 糞 + 0x7D1B, KANJI_SJIS_L1, // 箛 + 0x96F0, KANJI_SJIS_L1, // 雰 + 0x6587, KANJI_SJIS_L1, // 文 + 0x805E, KANJI_SJIS_L1, // 聞 + 0x4E19, KANJI_SJIS_L1, // 侙 + 0x4F75, KANJI_SJIS_L1, // 䜵 + 0x5175, KANJI_SJIS_L1, // 兵 + 0x5840, KANJI_SJIS_L1, // 塀 + 0x5E63, KANJI_SJIS_L1, // å¹£ + 0x5E73, KANJI_SJIS_L1, // å¹³ + 0x5F0A, KANJI_SJIS_L1, // 匊 + 0x67C4, KANJI_SJIS_L1, // 柄 + 0x4E26, KANJI_SJIS_L1, // 䞊 + 0x853D, KANJI_SJIS_L1, // 蔜 + 0x9589, KANJI_SJIS_L1, // 閉 + 0x965B, KANJI_SJIS_L1, // 陛 + 0x7C73, KANJI_SJIS_L1, // ç±³ + 0x9801, KANJI_SJIS_L1, // 頁 + 0x50FB, KANJI_SJIS_L1, // 僻 + 0x58C1, KANJI_SJIS_L1, // 壁 + 0x7656, KANJI_SJIS_L1, // 癖 + 0x78A7, KANJI_SJIS_L1, // 碧 + 0x5225, KANJI_SJIS_L1, // 別 + 0x77A5, KANJI_SJIS_L1, // 瞥 + 0x8511, KANJI_SJIS_L1, // 蔑 + 0x7B86, KANJI_SJIS_L1, // 箆 + 0x504F, KANJI_SJIS_L1, // 偏 + 0x5909, KANJI_SJIS_L1, // 倉 + 0x7247, KANJI_SJIS_L1, // 片 + 0x7BC7, KANJI_SJIS_L1, // 篇 + 0x7DE8, KANJI_SJIS_L1, // ç·š + 0x8FBA, KANJI_SJIS_L1, // 蟺 + 0x8FD4, KANJI_SJIS_L1, // 返 + 0x904D, KANJI_SJIS_L1, // 遍 + 0x4FBF, KANJI_SJIS_L1, // 䟿 + 0x52C9, KANJI_SJIS_L1, // 勉 + 0x5A29, KANJI_SJIS_L1, // åš© + 0x5F01, KANJI_SJIS_L1, // 匁 + 0x97AD, KANJI_SJIS_L1, // 鞭 + 0x4FDD, KANJI_SJIS_L1, // 保 + 0x8217, KANJI_SJIS_L1, // 舗 + 0x92EA, KANJI_SJIS_L1, // 鋪 + 0x5703, KANJI_SJIS_L1, // 圃 + 0x6355, KANJI_SJIS_L1, // 捕 + 0x6B69, KANJI_SJIS_L1, // æ­© + 0x752B, KANJI_SJIS_L1, // 甫 + 0x88DC, KANJI_SJIS_L1, // 補 + 0x8F14, KANJI_SJIS_L1, // 茔 + 0x7A42, KANJI_SJIS_L1, // 穂 + 0x52DF, KANJI_SJIS_L1, // 募 + 0x5893, KANJI_SJIS_L1, // 墓 + 0x6155, KANJI_SJIS_L1, // 慕 + 0x620A, KANJI_SJIS_L1, // 戊 + 0x66AE, KANJI_SJIS_L1, // 暮 + 0x6BCD, KANJI_SJIS_L1, // 母 + 0x7C3F, KANJI_SJIS_L1, // ç°¿ + 0x83E9, KANJI_SJIS_L1, // 菩 + 0x5023, KANJI_SJIS_L1, // 倣 + 0x4FF8, KANJI_SJIS_L1, // 俞 + 0x5305, KANJI_SJIS_L1, // 包 + 0x5446, KANJI_SJIS_L1, // 呆 + 0x5831, KANJI_SJIS_L1, // å ± + 0x5949, KANJI_SJIS_L1, // 奉 + 0x5B9D, KANJI_SJIS_L1, // 宝 + 0x5CF0, KANJI_SJIS_L1, // å³° + 0x5CEF, KANJI_SJIS_L1, // 峯 + 0x5D29, KANJI_SJIS_L1, // 厩 + 0x5E96, KANJI_SJIS_L1, // 庖 + 0x62B1, KANJI_SJIS_L1, // 抱 + 0x6367, KANJI_SJIS_L1, // 捧 + 0x653E, KANJI_SJIS_L1, // 攟 + 0x65B9, KANJI_SJIS_L1, // 方 + 0x670B, KANJI_SJIS_L1, // 朋 + 0x6CD5, KANJI_SJIS_L1, // 法 + 0x6CE1, KANJI_SJIS_L1, // 泡 + 0x70F9, KANJI_SJIS_L1, // 烹 + 0x7832, KANJI_SJIS_L1, // ç ² + 0x7E2B, KANJI_SJIS_L1, // çž« + 0x80DE, KANJI_SJIS_L1, // 胞 + 0x82B3, KANJI_SJIS_L1, // 芳 + 0x840C, KANJI_SJIS_L1, // 萌 + 0x84EC, KANJI_SJIS_L1, // 蓬 + 0x8702, KANJI_SJIS_L1, // 蜂 + 0x8912, KANJI_SJIS_L1, // 耒 + 0x8A2A, KANJI_SJIS_L1, // 蚪 + 0x8C4A, KANJI_SJIS_L1, // 豊 + 0x90A6, KANJI_SJIS_L1, // 邩 + 0x92D2, KANJI_SJIS_L1, // 鋒 + 0x98FD, KANJI_SJIS_L1, // 飜 + 0x9CF3, KANJI_SJIS_L1, // é³³ + 0x9D6C, KANJI_SJIS_L1, // 鵬 + 0x4E4F, KANJI_SJIS_L1, // 乏 + 0x4EA1, KANJI_SJIS_L1, // 亡 + 0x508D, KANJI_SJIS_L1, // 傍 + 0x5256, KANJI_SJIS_L1, // 剖 + 0x574A, KANJI_SJIS_L1, // 坊 + 0x59A8, KANJI_SJIS_L1, // 劚 + 0x5E3D, KANJI_SJIS_L1, // åžœ + 0x5FD8, KANJI_SJIS_L1, // 忘 + 0x5FD9, KANJI_SJIS_L1, // 忙 + 0x623F, KANJI_SJIS_L1, // 房 + 0x66B4, KANJI_SJIS_L1, // 暎 + 0x671B, KANJI_SJIS_L1, // 望 + 0x67D0, KANJI_SJIS_L1, // 某 + 0x68D2, KANJI_SJIS_L1, // 棒 + 0x5192, KANJI_SJIS_L1, // 冒 + 0x7D21, KANJI_SJIS_L1, // 玡 + 0x80AA, KANJI_SJIS_L1, // 肪 + 0x81A8, KANJI_SJIS_L1, // 膚 + 0x8B00, KANJI_SJIS_L1, // 謀 + 0x8C8C, KANJI_SJIS_L1, // 貌 + 0x8CBF, KANJI_SJIS_L1, // 貿 + 0x927E, KANJI_SJIS_L1, // 鉟 + 0x9632, KANJI_SJIS_L1, // 防 + 0x5420, KANJI_SJIS_L1, // 吠 + 0x982C, KANJI_SJIS_L1, // é ¬ + 0x5317, KANJI_SJIS_L1, // 北 + 0x50D5, KANJI_SJIS_L1, // 僕 + 0x535C, KANJI_SJIS_L1, // 卜 + 0x58A8, KANJI_SJIS_L1, // 墚 + 0x64B2, KANJI_SJIS_L1, // 撲 + 0x6734, KANJI_SJIS_L1, // 朎 + 0x7267, KANJI_SJIS_L1, // 牧 + 0x7766, KANJI_SJIS_L1, // 睊 + 0x7A46, KANJI_SJIS_L1, // 穆 + 0x91E6, KANJI_SJIS_L1, // 釩 + 0x52C3, KANJI_SJIS_L1, // 勃 + 0x6CA1, KANJI_SJIS_L1, // 没 + 0x6B86, KANJI_SJIS_L1, // 殆 + 0x5800, KANJI_SJIS_L1, // 堀 + 0x5E4C, KANJI_SJIS_L1, // 幌 + 0x5954, KANJI_SJIS_L1, // 奔 + 0x672C, KANJI_SJIS_L1, // 本 + 0x7FFB, KANJI_SJIS_L1, // ç¿» + 0x51E1, KANJI_SJIS_L1, // 凡 + 0x76C6, KANJI_SJIS_L1, // 盆 + 0x3000, KANJI_SJIS_L1, //   + 0x6469, KANJI_SJIS_L1, // 摩 + 0x78E8, KANJI_SJIS_L1, // 磚 + 0x9B54, KANJI_SJIS_L1, // 魔 + 0x9EBB, KANJI_SJIS_L1, // 麻 + 0x57CB, KANJI_SJIS_L1, // 埋 + 0x59B9, KANJI_SJIS_L1, // 効 + 0x6627, KANJI_SJIS_L1, // 昧 + 0x679A, KANJI_SJIS_L1, // 枚 + 0x6BCE, KANJI_SJIS_L1, // 毎 + 0x54E9, KANJI_SJIS_L1, // 哩 + 0x69D9, KANJI_SJIS_L1, // 槙 + 0x5E55, KANJI_SJIS_L1, // 幕 + 0x819C, KANJI_SJIS_L1, // 膜 + 0x6795, KANJI_SJIS_L1, // 枕 + 0x9BAA, KANJI_SJIS_L1, // 鮪 + 0x67FE, KANJI_SJIS_L1, // 柟 + 0x9C52, KANJI_SJIS_L1, // 鱒 + 0x685D, KANJI_SJIS_L1, // 桝 + 0x4EA6, KANJI_SJIS_L1, // 亊 + 0x4FE3, KANJI_SJIS_L1, // ä¿£ + 0x53C8, KANJI_SJIS_L1, // 又 + 0x62B9, KANJI_SJIS_L1, // 抹 + 0x672B, KANJI_SJIS_L1, // 末 + 0x6CAB, KANJI_SJIS_L1, // 沫 + 0x8FC4, KANJI_SJIS_L1, // 迄 + 0x4FAD, KANJI_SJIS_L1, // 䟭 + 0x7E6D, KANJI_SJIS_L1, // ç¹­ + 0x9EBF, KANJI_SJIS_L1, // 麿 + 0x4E07, KANJI_SJIS_L1, // 侇 + 0x6162, KANJI_SJIS_L1, // 慢 + 0x6E80, KANJI_SJIS_L1, // 満 + 0x6F2B, KANJI_SJIS_L1, // 挫 + 0x8513, KANJI_SJIS_L1, // 蔓 + 0x5473, KANJI_SJIS_L1, // 味 + 0x672A, KANJI_SJIS_L1, // 未 + 0x9B45, KANJI_SJIS_L1, // 魅 + 0x5DF3, KANJI_SJIS_L1, // å·³ + 0x7B95, KANJI_SJIS_L1, // 箕 + 0x5CAC, KANJI_SJIS_L1, // 岬 + 0x5BC6, KANJI_SJIS_L1, // 密 + 0x871C, KANJI_SJIS_L1, // 蜜 + 0x6E4A, KANJI_SJIS_L1, // 湊 + 0x84D1, KANJI_SJIS_L1, // 蓑 + 0x7A14, KANJI_SJIS_L1, // 織 + 0x8108, KANJI_SJIS_L1, // 脈 + 0x5999, KANJI_SJIS_L1, // 劙 + 0x7C8D, KANJI_SJIS_L1, // 粍 + 0x6C11, KANJI_SJIS_L1, // 民 + 0x7720, KANJI_SJIS_L1, // 眠 + 0x52D9, KANJI_SJIS_L1, // 務 + 0x5922, KANJI_SJIS_L1, // 倢 + 0x7121, KANJI_SJIS_L1, // 無 + 0x725F, KANJI_SJIS_L1, // 牟 + 0x77DB, KANJI_SJIS_L1, // 矛 + 0x9727, KANJI_SJIS_L1, // 霧 + 0x9D61, KANJI_SJIS_L1, // 鵡 + 0x690B, KANJI_SJIS_L1, // 怋 + 0x5A7F, KANJI_SJIS_L1, // å©¿ + 0x5A18, KANJI_SJIS_L1, // 嚘 + 0x51A5, KANJI_SJIS_L1, // 冥 + 0x540D, KANJI_SJIS_L1, // 名 + 0x547D, KANJI_SJIS_L1, // 呜 + 0x660E, KANJI_SJIS_L1, // 明 + 0x76DF, KANJI_SJIS_L1, // 盟 + 0x8FF7, KANJI_SJIS_L1, // è¿· + 0x9298, KANJI_SJIS_L1, // 銘 + 0x9CF4, KANJI_SJIS_L1, // 鳎 + 0x59EA, KANJI_SJIS_L1, // 姪 + 0x725D, KANJI_SJIS_L1, // 牝 + 0x6EC5, KANJI_SJIS_L1, // 滅 + 0x514D, KANJI_SJIS_L1, // 免 + 0x68C9, KANJI_SJIS_L1, // 棉 + 0x7DBF, KANJI_SJIS_L1, // ç¶¿ + 0x7DEC, KANJI_SJIS_L1, // ç·¬ + 0x9762, KANJI_SJIS_L1, // 面 + 0x9EBA, KANJI_SJIS_L1, // 麺 + 0x6478, KANJI_SJIS_L1, // 摞 + 0x6A21, KANJI_SJIS_L1, // æš¡ + 0x8302, KANJI_SJIS_L1, // 茂 + 0x5984, KANJI_SJIS_L1, // 劄 + 0x5B5F, KANJI_SJIS_L1, // 孟 + 0x6BDB, KANJI_SJIS_L1, // 毛 + 0x731B, KANJI_SJIS_L1, // 猛 + 0x76F2, KANJI_SJIS_L1, // 盲 + 0x7DB2, KANJI_SJIS_L1, // ç¶² + 0x8017, KANJI_SJIS_L1, // 耗 + 0x8499, KANJI_SJIS_L1, // 蒙 + 0x5132, KANJI_SJIS_L1, // 儲 + 0x6728, KANJI_SJIS_L1, // 朚 + 0x9ED9, KANJI_SJIS_L1, // 黙 + 0x76EE, KANJI_SJIS_L1, // 目 + 0x6762, KANJI_SJIS_L1, // 杢 + 0x52FF, KANJI_SJIS_L1, // 勿 + 0x9905, KANJI_SJIS_L1, // 逅 + 0x5C24, KANJI_SJIS_L1, // å°€ + 0x623B, KANJI_SJIS_L1, // 戻 + 0x7C7E, KANJI_SJIS_L1, // 籟 + 0x8CB0, KANJI_SJIS_L1, // è²° + 0x554F, KANJI_SJIS_L1, // 問 + 0x60B6, KANJI_SJIS_L1, // 悶 + 0x7D0B, KANJI_SJIS_L1, // 箋 + 0x9580, KANJI_SJIS_L1, // 門 + 0x5301, KANJI_SJIS_L1, // 匁 + 0x4E5F, KANJI_SJIS_L1, // 也 + 0x51B6, KANJI_SJIS_L1, // 冶 + 0x591C, KANJI_SJIS_L1, // 倜 + 0x723A, KANJI_SJIS_L1, // 爺 + 0x8036, KANJI_SJIS_L1, // 耶 + 0x91CE, KANJI_SJIS_L1, // 野 + 0x5F25, KANJI_SJIS_L1, // 匥 + 0x77E2, KANJI_SJIS_L1, // 矢 + 0x5384, KANJI_SJIS_L1, // 厄 + 0x5F79, KANJI_SJIS_L1, // 圹 + 0x7D04, KANJI_SJIS_L1, // 箄 + 0x85AC, KANJI_SJIS_L1, // 薬 + 0x8A33, KANJI_SJIS_L1, // èš³ + 0x8E8D, KANJI_SJIS_L1, // 躍 + 0x9756, KANJI_SJIS_L1, // 靖 + 0x67F3, KANJI_SJIS_L1, // 柳 + 0x85AE, KANJI_SJIS_L1, // 薮 + 0x9453, KANJI_SJIS_L1, // 鑓 + 0x6109, KANJI_SJIS_L1, // 愉 + 0x6108, KANJI_SJIS_L1, // 愈 + 0x6CB9, KANJI_SJIS_L1, // æ²¹ + 0x7652, KANJI_SJIS_L1, // 癒 + 0x8AED, KANJI_SJIS_L1, // è«­ + 0x8F38, KANJI_SJIS_L1, // 茞 + 0x552F, KANJI_SJIS_L1, // 唯 + 0x4F51, KANJI_SJIS_L1, // 䜑 + 0x512A, KANJI_SJIS_L1, // 優 + 0x52C7, KANJI_SJIS_L1, // 勇 + 0x53CB, KANJI_SJIS_L1, // 友 + 0x5BA5, KANJI_SJIS_L1, // 宥 + 0x5E7D, KANJI_SJIS_L1, // 幜 + 0x60A0, KANJI_SJIS_L1, // 悠 + 0x6182, KANJI_SJIS_L1, // 憂 + 0x63D6, KANJI_SJIS_L1, // 揖 + 0x6709, KANJI_SJIS_L1, // 有 + 0x67DA, KANJI_SJIS_L1, // 柚 + 0x6E67, KANJI_SJIS_L1, // æ¹§ + 0x6D8C, KANJI_SJIS_L1, // 涌 + 0x7336, KANJI_SJIS_L1, // 猶 + 0x7337, KANJI_SJIS_L1, // 猷 + 0x7531, KANJI_SJIS_L1, // 由 + 0x7950, KANJI_SJIS_L1, // 祐 + 0x88D5, KANJI_SJIS_L1, // 裕 + 0x8A98, KANJI_SJIS_L1, // 誘 + 0x904A, KANJI_SJIS_L1, // 遊 + 0x9091, KANJI_SJIS_L1, // 邑 + 0x90F5, KANJI_SJIS_L1, // 郵 + 0x96C4, KANJI_SJIS_L1, // 雄 + 0x878D, KANJI_SJIS_L1, // 融 + 0x5915, KANJI_SJIS_L1, // 倕 + 0x4E88, KANJI_SJIS_L1, // 予 + 0x4F59, KANJI_SJIS_L1, // 䜙 + 0x4E0E, KANJI_SJIS_L1, // 侎 + 0x8A89, KANJI_SJIS_L1, // 誉 + 0x8F3F, KANJI_SJIS_L1, // 茿 + 0x9810, KANJI_SJIS_L1, // 預 + 0x50AD, KANJI_SJIS_L1, // 傭 + 0x5E7C, KANJI_SJIS_L1, // 幌 + 0x5996, KANJI_SJIS_L1, // 劖 + 0x5BB9, KANJI_SJIS_L1, // 容 + 0x5EB8, KANJI_SJIS_L1, // 庞 + 0x63DA, KANJI_SJIS_L1, // 揚 + 0x63FA, KANJI_SJIS_L1, // 揺 + 0x64C1, KANJI_SJIS_L1, // 擁 + 0x66DC, KANJI_SJIS_L1, // 曜 + 0x694A, KANJI_SJIS_L1, // 楊 + 0x69D8, KANJI_SJIS_L1, // 様 + 0x6D0B, KANJI_SJIS_L1, // 掋 + 0x6EB6, KANJI_SJIS_L1, // 溶 + 0x7194, KANJI_SJIS_L1, // 熔 + 0x7528, KANJI_SJIS_L1, // 甹 + 0x7AAF, KANJI_SJIS_L1, // 窯 + 0x7F8A, KANJI_SJIS_L1, // 矊 + 0x8000, KANJI_SJIS_L1, // 耀 + 0x8449, KANJI_SJIS_L1, // 葉 + 0x84C9, KANJI_SJIS_L1, // 蓉 + 0x8981, KANJI_SJIS_L1, // 芁 + 0x8B21, KANJI_SJIS_L1, // 謡 + 0x8E0A, KANJI_SJIS_L1, // 螊 + 0x9065, KANJI_SJIS_L1, // 遥 + 0x967D, KANJI_SJIS_L1, // 陜 + 0x990A, KANJI_SJIS_L1, // 逊 + 0x617E, KANJI_SJIS_L1, // æ…Ÿ + 0x6291, KANJI_SJIS_L1, // 抑 + 0x6B32, KANJI_SJIS_L1, // 欲 + 0x3000, KANJI_SJIS_L1, //   + 0x6C83, KANJI_SJIS_L1, // 沃 + 0x6D74, KANJI_SJIS_L1, // 济 + 0x7FCC, KANJI_SJIS_L1, // 翌 + 0x7FFC, KANJI_SJIS_L1, // 翌 + 0x6DC0, KANJI_SJIS_L1, // 淀 + 0x7F85, KANJI_SJIS_L1, // 矅 + 0x87BA, KANJI_SJIS_L1, // 螺 + 0x88F8, KANJI_SJIS_L1, // 裞 + 0x6765, KANJI_SJIS_L1, // 来 + 0x83B1, KANJI_SJIS_L1, // 莱 + 0x983C, KANJI_SJIS_L1, // é Œ + 0x96F7, KANJI_SJIS_L1, // 雷 + 0x6D1B, KANJI_SJIS_L1, // 掛 + 0x7D61, KANJI_SJIS_L1, // 絡 + 0x843D, KANJI_SJIS_L1, // 萜 + 0x916A, KANJI_SJIS_L1, // 酪 + 0x4E71, KANJI_SJIS_L1, // ä¹± + 0x5375, KANJI_SJIS_L1, // 卵 + 0x5D50, KANJI_SJIS_L1, // 嵐 + 0x6B04, KANJI_SJIS_L1, // 欄 + 0x6FEB, KANJI_SJIS_L1, // æ¿« + 0x85CD, KANJI_SJIS_L1, // 藍 + 0x862D, KANJI_SJIS_L1, // 蘭 + 0x89A7, KANJI_SJIS_L1, // 芧 + 0x5229, KANJI_SJIS_L1, // 利 + 0x540F, KANJI_SJIS_L1, // 吏 + 0x5C65, KANJI_SJIS_L1, // å±¥ + 0x674E, KANJI_SJIS_L1, // 李 + 0x68A8, KANJI_SJIS_L1, // 梚 + 0x7406, KANJI_SJIS_L1, // 理 + 0x7483, KANJI_SJIS_L1, // 璃 + 0x75E2, KANJI_SJIS_L1, // 痢 + 0x88CF, KANJI_SJIS_L1, // 裏 + 0x88E1, KANJI_SJIS_L1, // 裡 + 0x91CC, KANJI_SJIS_L1, // 里 + 0x96E2, KANJI_SJIS_L1, // 離 + 0x9678, KANJI_SJIS_L1, // 陾 + 0x5F8B, KANJI_SJIS_L1, // 埋 + 0x7387, KANJI_SJIS_L1, // 率 + 0x7ACB, KANJI_SJIS_L1, // 立 + 0x844E, KANJI_SJIS_L1, // 葎 + 0x63A0, KANJI_SJIS_L1, // 掠 + 0x7565, KANJI_SJIS_L1, // 略 + 0x5289, KANJI_SJIS_L1, // 劉 + 0x6D41, KANJI_SJIS_L1, // 流 + 0x6E9C, KANJI_SJIS_L1, // 溜 + 0x7409, KANJI_SJIS_L1, // 琉 + 0x7559, KANJI_SJIS_L1, // 留 + 0x786B, KANJI_SJIS_L1, // ç¡« + 0x7C92, KANJI_SJIS_L1, // 粒 + 0x9686, KANJI_SJIS_L1, // 隆 + 0x7ADC, KANJI_SJIS_L1, // 竜 + 0x9F8D, KANJI_SJIS_L1, // 韍 + 0x4FB6, KANJI_SJIS_L1, // 䟶 + 0x616E, KANJI_SJIS_L1, // 慮 + 0x65C5, KANJI_SJIS_L1, // 旅 + 0x865C, KANJI_SJIS_L1, // 虜 + 0x4E86, KANJI_SJIS_L1, // 了 + 0x4EAE, KANJI_SJIS_L1, // 亮 + 0x50DA, KANJI_SJIS_L1, // 僚 + 0x4E21, KANJI_SJIS_L1, // äž¡ + 0x51CC, KANJI_SJIS_L1, // 凌 + 0x5BEE, KANJI_SJIS_L1, // 寮 + 0x6599, KANJI_SJIS_L1, // 料 + 0x6881, KANJI_SJIS_L1, // 梁 + 0x6DBC, KANJI_SJIS_L1, // æ¶Œ + 0x731F, KANJI_SJIS_L1, // 猟 + 0x7642, KANJI_SJIS_L1, // 療 + 0x77AD, KANJI_SJIS_L1, // 瞭 + 0x7A1C, KANJI_SJIS_L1, // 繜 + 0x7CE7, KANJI_SJIS_L1, // ç³§ + 0x826F, KANJI_SJIS_L1, // 良 + 0x8AD2, KANJI_SJIS_L1, // 諒 + 0x907C, KANJI_SJIS_L1, // 遌 + 0x91CF, KANJI_SJIS_L1, // 量 + 0x9675, KANJI_SJIS_L1, // 陵 + 0x9818, KANJI_SJIS_L1, // 領 + 0x529B, KANJI_SJIS_L1, // 力 + 0x7DD1, KANJI_SJIS_L1, // 緑 + 0x502B, KANJI_SJIS_L1, // 倫 + 0x5398, KANJI_SJIS_L1, // 厘 + 0x6797, KANJI_SJIS_L1, // 林 + 0x6DCB, KANJI_SJIS_L1, // 淋 + 0x71D0, KANJI_SJIS_L1, // 燐 + 0x7433, KANJI_SJIS_L1, // 琳 + 0x81E8, KANJI_SJIS_L1, // 臚 + 0x8F2A, KANJI_SJIS_L1, // 茪 + 0x96A3, KANJI_SJIS_L1, // 隣 + 0x9C57, KANJI_SJIS_L1, // 鱗 + 0x9E9F, KANJI_SJIS_L1, // 麟 + 0x7460, KANJI_SJIS_L1, // 瑠 + 0x5841, KANJI_SJIS_L1, // 塁 + 0x6D99, KANJI_SJIS_L1, // 涙 + 0x7D2F, KANJI_SJIS_L1, // 环 + 0x985E, KANJI_SJIS_L1, // 類 + 0x4EE4, KANJI_SJIS_L1, // 什 + 0x4F36, KANJI_SJIS_L1, // 䌶 + 0x4F8B, KANJI_SJIS_L1, // 䟋 + 0x51B7, KANJI_SJIS_L1, // 冷 + 0x52B1, KANJI_SJIS_L1, // 励 + 0x5DBA, KANJI_SJIS_L1, // 嶺 + 0x601C, KANJI_SJIS_L1, // 怜 + 0x73B2, KANJI_SJIS_L1, // 玲 + 0x793C, KANJI_SJIS_L1, // 瀌 + 0x82D3, KANJI_SJIS_L1, // 苓 + 0x9234, KANJI_SJIS_L1, // 鈎 + 0x96B7, KANJI_SJIS_L1, // 隷 + 0x96F6, KANJI_SJIS_L1, // 零 + 0x970A, KANJI_SJIS_L1, // 霊 + 0x9E97, KANJI_SJIS_L1, // 麗 + 0x9F62, KANJI_SJIS_L1, // 霢 + 0x66A6, KANJI_SJIS_L1, // 暊 + 0x6B74, KANJI_SJIS_L1, // æ­Ž + 0x5217, KANJI_SJIS_L1, // 列 + 0x52A3, KANJI_SJIS_L1, // 劣 + 0x70C8, KANJI_SJIS_L1, // 烈 + 0x88C2, KANJI_SJIS_L1, // 裂 + 0x5EC9, KANJI_SJIS_L1, // 廉 + 0x604B, KANJI_SJIS_L1, // 恋 + 0x6190, KANJI_SJIS_L1, // 憐 + 0x6F23, KANJI_SJIS_L1, // 挣 + 0x7149, KANJI_SJIS_L1, // 煉 + 0x7C3E, KANJI_SJIS_L1, // ç°Ÿ + 0x7DF4, KANJI_SJIS_L1, // ç·Ž + 0x806F, KANJI_SJIS_L1, // 聯 + 0x84EE, KANJI_SJIS_L1, // 蓮 + 0x9023, KANJI_SJIS_L1, // 連 + 0x932C, KANJI_SJIS_L1, // 錬 + 0x5442, KANJI_SJIS_L1, // 呂 + 0x9B6F, KANJI_SJIS_L1, // é­¯ + 0x6AD3, KANJI_SJIS_L1, // 櫓 + 0x7089, KANJI_SJIS_L1, // 炉 + 0x8CC2, KANJI_SJIS_L1, // 賂 + 0x8DEF, KANJI_SJIS_L1, // è·¯ + 0x9732, KANJI_SJIS_L1, // 露 + 0x52B4, KANJI_SJIS_L1, // 劎 + 0x5A41, KANJI_SJIS_L1, // 婁 + 0x5ECA, KANJI_SJIS_L1, // 廊 + 0x5F04, KANJI_SJIS_L1, // 匄 + 0x6717, KANJI_SJIS_L1, // 朗 + 0x697C, KANJI_SJIS_L1, // 楌 + 0x6994, KANJI_SJIS_L1, // 抔 + 0x6D6A, KANJI_SJIS_L1, // 浪 + 0x6F0F, KANJI_SJIS_L1, // 挏 + 0x7262, KANJI_SJIS_L1, // 牢 + 0x72FC, KANJI_SJIS_L1, // 狌 + 0x7BED, KANJI_SJIS_L1, // 篭 + 0x8001, KANJI_SJIS_L1, // 老 + 0x807E, KANJI_SJIS_L1, // 聟 + 0x874B, KANJI_SJIS_L1, // 蝋 + 0x90CE, KANJI_SJIS_L1, // 郎 + 0x516D, KANJI_SJIS_L1, // 六 + 0x9E93, KANJI_SJIS_L1, // 麓 + 0x7984, KANJI_SJIS_L1, // 穄 + 0x808B, KANJI_SJIS_L1, // 肋 + 0x9332, KANJI_SJIS_L1, // 録 + 0x8AD6, KANJI_SJIS_L1, // 論 + 0x502D, KANJI_SJIS_L1, // 倭 + 0x548C, KANJI_SJIS_L1, // 和 + 0x8A71, KANJI_SJIS_L1, // 話 + 0x6B6A, KANJI_SJIS_L1, // æ­ª + 0x8CC4, KANJI_SJIS_L1, // 賄 + 0x8107, KANJI_SJIS_L1, // 脇 + 0x60D1, KANJI_SJIS_L1, // 惑 + 0x67A0, KANJI_SJIS_L1, // 枠 + 0x9DF2, KANJI_SJIS_L1, // é·² + 0x4E99, KANJI_SJIS_L1, // 亙 + 0x4E98, KANJI_SJIS_L1, // 亘 + 0x9C10, KANJI_SJIS_L1, // 鰐 + 0x8A6B, KANJI_SJIS_L1, // è©« + 0x85C1, KANJI_SJIS_L1, // 藁 + 0x8568, KANJI_SJIS_L1, // 蕚 + 0x6900, KANJI_SJIS_L1, // 怀 + 0x6E7E, KANJI_SJIS_L1, // 湟 + 0x7897, KANJI_SJIS_L1, // 碗 + 0x8155, KANJI_SJIS_L1, // 腕 + 0x5F0C, KANJI_SJIS_L2, // 匌 + 0x4E10, KANJI_SJIS_L2, // 䞐 + 0x4E15, KANJI_SJIS_L2, // 侕 + 0x4E2A, KANJI_SJIS_L2, // 䞪 + 0x4E31, KANJI_SJIS_L2, // äž± + 0x4E36, KANJI_SJIS_L2, // äž¶ + 0x4E3C, KANJI_SJIS_L2, // 䞌 + 0x4E3F, KANJI_SJIS_L2, // äž¿ + 0x4E42, KANJI_SJIS_L2, // 乂 + 0x4E56, KANJI_SJIS_L2, // 乖 + 0x4E58, KANJI_SJIS_L2, // 乘 + 0x4E82, KANJI_SJIS_L2, // 亂 + 0x4E85, KANJI_SJIS_L2, // 亅 + 0x8C6B, KANJI_SJIS_L2, // 豫 + 0x4E8A, KANJI_SJIS_L2, // 亊 + 0x8212, KANJI_SJIS_L2, // 舒 + 0x5F0D, KANJI_SJIS_L2, // 匍 + 0x4E8E, KANJI_SJIS_L2, // 于 + 0x4E9E, KANJI_SJIS_L2, // 亞 + 0x4E9F, KANJI_SJIS_L2, // 亟 + 0x4EA0, KANJI_SJIS_L2, // 亠 + 0x4EA2, KANJI_SJIS_L2, // 亢 + 0x4EB0, KANJI_SJIS_L2, // 亰 + 0x4EB3, KANJI_SJIS_L2, // 亳 + 0x4EB6, KANJI_SJIS_L2, // 亶 + 0x4ECE, KANJI_SJIS_L2, // 从 + 0x4ECD, KANJI_SJIS_L2, // 仍 + 0x4EC4, KANJI_SJIS_L2, // 仄 + 0x4EC6, KANJI_SJIS_L2, // 仆 + 0x4EC2, KANJI_SJIS_L2, // 仂 + 0x4ED7, KANJI_SJIS_L2, // 仗 + 0x4EDE, KANJI_SJIS_L2, // 仞 + 0x4EED, KANJI_SJIS_L2, // ä»­ + 0x4EDF, KANJI_SJIS_L2, // 仟 + 0x4EF7, KANJI_SJIS_L2, // ä»· + 0x4F09, KANJI_SJIS_L2, // 䌉 + 0x4F5A, KANJI_SJIS_L2, // 䜚 + 0x4F30, KANJI_SJIS_L2, // 䌰 + 0x4F5B, KANJI_SJIS_L2, // 䜛 + 0x4F5D, KANJI_SJIS_L2, // 䜝 + 0x4F57, KANJI_SJIS_L2, // 䜗 + 0x4F47, KANJI_SJIS_L2, // 䜇 + 0x4F76, KANJI_SJIS_L2, // 䜶 + 0x4F88, KANJI_SJIS_L2, // 䟈 + 0x4F8F, KANJI_SJIS_L2, // 䟏 + 0x4F98, KANJI_SJIS_L2, // 䟘 + 0x4F7B, KANJI_SJIS_L2, // 䜻 + 0x4F69, KANJI_SJIS_L2, // 䜩 + 0x4F70, KANJI_SJIS_L2, // 䜰 + 0x4F91, KANJI_SJIS_L2, // 䟑 + 0x4F6F, KANJI_SJIS_L2, // 䜯 + 0x4F86, KANJI_SJIS_L2, // 䟆 + 0x4F96, KANJI_SJIS_L2, // 䟖 + 0x5118, KANJI_SJIS_L2, // 儘 + 0x4FD4, KANJI_SJIS_L2, // 俔 + 0x4FDF, KANJI_SJIS_L2, // 俟 + 0x4FCE, KANJI_SJIS_L2, // 俎 + 0x4FD8, KANJI_SJIS_L2, // 俘 + 0x4FDB, KANJI_SJIS_L2, // 俛 + 0x4FD1, KANJI_SJIS_L2, // 俑 + 0x4FDA, KANJI_SJIS_L2, // 俚 + 0x4FD0, KANJI_SJIS_L2, // 俐 + 0x4FE4, KANJI_SJIS_L2, // ä¿€ + 0x4FE5, KANJI_SJIS_L2, // ä¿¥ + 0x501A, KANJI_SJIS_L2, // 倚 + 0x5028, KANJI_SJIS_L2, // 倚 + 0x5014, KANJI_SJIS_L2, // 倔 + 0x502A, KANJI_SJIS_L2, // 倪 + 0x5025, KANJI_SJIS_L2, // 倥 + 0x5005, KANJI_SJIS_L2, // 倅 + 0x4F1C, KANJI_SJIS_L2, // 䌜 + 0x4FF6, KANJI_SJIS_L2, // ä¿¶ + 0x5021, KANJI_SJIS_L2, // 倡 + 0x5029, KANJI_SJIS_L2, // 倩 + 0x502C, KANJI_SJIS_L2, // 倬 + 0x4FFE, KANJI_SJIS_L2, // 俟 + 0x4FEF, KANJI_SJIS_L2, // 俯 + 0x5011, KANJI_SJIS_L2, // 們 + 0x5006, KANJI_SJIS_L2, // 倆 + 0x5043, KANJI_SJIS_L2, // 偃 + 0x5047, KANJI_SJIS_L2, // 假 + 0x6703, KANJI_SJIS_L2, // 會 + 0x5055, KANJI_SJIS_L2, // 偕 + 0x5050, KANJI_SJIS_L2, // 偐 + 0x5048, KANJI_SJIS_L2, // 偈 + 0x505A, KANJI_SJIS_L2, // 做 + 0x5056, KANJI_SJIS_L2, // 偖 + 0x506C, KANJI_SJIS_L2, // 偬 + 0x5078, KANJI_SJIS_L2, // 偞 + 0x5080, KANJI_SJIS_L2, // 傀 + 0x509A, KANJI_SJIS_L2, // 傚 + 0x5085, KANJI_SJIS_L2, // 傅 + 0x50B4, KANJI_SJIS_L2, // 傎 + 0x50B2, KANJI_SJIS_L2, // 傲 + 0x50C9, KANJI_SJIS_L2, // 僉 + 0x50CA, KANJI_SJIS_L2, // 僊 + 0x50B3, KANJI_SJIS_L2, // 傳 + 0x50C2, KANJI_SJIS_L2, // 僂 + 0x50D6, KANJI_SJIS_L2, // 僖 + 0x50DE, KANJI_SJIS_L2, // 僞 + 0x50E5, KANJI_SJIS_L2, // 僥 + 0x50ED, KANJI_SJIS_L2, // 僭 + 0x50E3, KANJI_SJIS_L2, // 僣 + 0x50EE, KANJI_SJIS_L2, // 僮 + 0x50F9, KANJI_SJIS_L2, // 價 + 0x50F5, KANJI_SJIS_L2, // 僵 + 0x5109, KANJI_SJIS_L2, // 儉 + 0x5101, KANJI_SJIS_L2, // 儁 + 0x5102, KANJI_SJIS_L2, // 儂 + 0x5116, KANJI_SJIS_L2, // 儖 + 0x5115, KANJI_SJIS_L2, // 儕 + 0x5114, KANJI_SJIS_L2, // 儔 + 0x511A, KANJI_SJIS_L2, // 儚 + 0x5121, KANJI_SJIS_L2, // 儡 + 0x513A, KANJI_SJIS_L2, // 儺 + 0x5137, KANJI_SJIS_L2, // 儷 + 0x513C, KANJI_SJIS_L2, // 儌 + 0x513B, KANJI_SJIS_L2, // 儻 + 0x513F, KANJI_SJIS_L2, // 儿 + 0x5140, KANJI_SJIS_L2, // 兀 + 0x5152, KANJI_SJIS_L2, // 兒 + 0x514C, KANJI_SJIS_L2, // 兌 + 0x5154, KANJI_SJIS_L2, // 兔 + 0x5162, KANJI_SJIS_L2, // 兢 + 0x7AF8, KANJI_SJIS_L2, // 竞 + 0x5169, KANJI_SJIS_L2, // 兩 + 0x516A, KANJI_SJIS_L2, // 兪 + 0x516E, KANJI_SJIS_L2, // 兮 + 0x5180, KANJI_SJIS_L2, // 冀 + 0x5182, KANJI_SJIS_L2, // 冂 + 0x56D8, KANJI_SJIS_L2, // 囘 + 0x518C, KANJI_SJIS_L2, // 册 + 0x5189, KANJI_SJIS_L2, // 冉 + 0x518F, KANJI_SJIS_L2, // 冏 + 0x5191, KANJI_SJIS_L2, // 冑 + 0x5193, KANJI_SJIS_L2, // 冓 + 0x5195, KANJI_SJIS_L2, // 冕 + 0x5196, KANJI_SJIS_L2, // 冖 + 0x51A4, KANJI_SJIS_L2, // 冀 + 0x51A6, KANJI_SJIS_L2, // 冊 + 0x51A2, KANJI_SJIS_L2, // 冢 + 0x51A9, KANJI_SJIS_L2, // 冩 + 0x51AA, KANJI_SJIS_L2, // 冪 + 0x51AB, KANJI_SJIS_L2, // 冫 + 0x51B3, KANJI_SJIS_L2, // 决 + 0x51B1, KANJI_SJIS_L2, // 冱 + 0x51B2, KANJI_SJIS_L2, // 冲 + 0x51B0, KANJI_SJIS_L2, // 冰 + 0x51B5, KANJI_SJIS_L2, // 况 + 0x51BD, KANJI_SJIS_L2, // 农 + 0x51C5, KANJI_SJIS_L2, // 凅 + 0x51C9, KANJI_SJIS_L2, // 凉 + 0x51DB, KANJI_SJIS_L2, // 凛 + 0x51E0, KANJI_SJIS_L2, // 几 + 0x8655, KANJI_SJIS_L2, // 處 + 0x51E9, KANJI_SJIS_L2, // 凩 + 0x51ED, KANJI_SJIS_L2, // 凭 + 0x3000, KANJI_SJIS_L2, //   + 0x51F0, KANJI_SJIS_L2, // 凰 + 0x51F5, KANJI_SJIS_L2, // 凵 + 0x51FE, KANJI_SJIS_L2, // 凟 + 0x5204, KANJI_SJIS_L2, // 刄 + 0x520B, KANJI_SJIS_L2, // 刋 + 0x5214, KANJI_SJIS_L2, // 刔 + 0x520E, KANJI_SJIS_L2, // 刎 + 0x5227, KANJI_SJIS_L2, // 刧 + 0x522A, KANJI_SJIS_L2, // 刪 + 0x522E, KANJI_SJIS_L2, // 刮 + 0x5233, KANJI_SJIS_L2, // 刳 + 0x5239, KANJI_SJIS_L2, // 刹 + 0x524F, KANJI_SJIS_L2, // 剏 + 0x5244, KANJI_SJIS_L2, // 剄 + 0x524B, KANJI_SJIS_L2, // 剋 + 0x524C, KANJI_SJIS_L2, // 剌 + 0x525E, KANJI_SJIS_L2, // 剞 + 0x5254, KANJI_SJIS_L2, // 剔 + 0x526A, KANJI_SJIS_L2, // 剪 + 0x5274, KANJI_SJIS_L2, // 剎 + 0x5269, KANJI_SJIS_L2, // 剩 + 0x5273, KANJI_SJIS_L2, // 剳 + 0x527F, KANJI_SJIS_L2, // 剿 + 0x527D, KANJI_SJIS_L2, // 剜 + 0x528D, KANJI_SJIS_L2, // 劍 + 0x5294, KANJI_SJIS_L2, // 劔 + 0x5292, KANJI_SJIS_L2, // 劒 + 0x5271, KANJI_SJIS_L2, // 剱 + 0x5288, KANJI_SJIS_L2, // 劈 + 0x5291, KANJI_SJIS_L2, // 劑 + 0x8FA8, KANJI_SJIS_L2, // 蟚 + 0x8FA7, KANJI_SJIS_L2, // 蟧 + 0x52AC, KANJI_SJIS_L2, // 劬 + 0x52AD, KANJI_SJIS_L2, // 劭 + 0x52BC, KANJI_SJIS_L2, // 劌 + 0x52B5, KANJI_SJIS_L2, // 劵 + 0x52C1, KANJI_SJIS_L2, // 勁 + 0x52CD, KANJI_SJIS_L2, // 勍 + 0x52D7, KANJI_SJIS_L2, // 勗 + 0x52DE, KANJI_SJIS_L2, // 勞 + 0x52E3, KANJI_SJIS_L2, // 勣 + 0x52E6, KANJI_SJIS_L2, // 勊 + 0x98ED, KANJI_SJIS_L2, // 飭 + 0x52E0, KANJI_SJIS_L2, // 勠 + 0x52F3, KANJI_SJIS_L2, // 勳 + 0x52F5, KANJI_SJIS_L2, // 勵 + 0x52F8, KANJI_SJIS_L2, // 勞 + 0x52F9, KANJI_SJIS_L2, // 勹 + 0x5306, KANJI_SJIS_L2, // 匆 + 0x5308, KANJI_SJIS_L2, // 匈 + 0x7538, KANJI_SJIS_L2, // 甾 + 0x530D, KANJI_SJIS_L2, // 匍 + 0x5310, KANJI_SJIS_L2, // 匐 + 0x530F, KANJI_SJIS_L2, // 匏 + 0x5315, KANJI_SJIS_L2, // 匕 + 0x531A, KANJI_SJIS_L2, // 匚 + 0x5323, KANJI_SJIS_L2, // 匣 + 0x532F, KANJI_SJIS_L2, // 匯 + 0x5331, KANJI_SJIS_L2, // 匱 + 0x5333, KANJI_SJIS_L2, // 匳 + 0x5338, KANJI_SJIS_L2, // 匞 + 0x5340, KANJI_SJIS_L2, // 區 + 0x5346, KANJI_SJIS_L2, // 卆 + 0x5345, KANJI_SJIS_L2, // 卅 + 0x4E17, KANJI_SJIS_L2, // 侗 + 0x5349, KANJI_SJIS_L2, // 卉 + 0x534D, KANJI_SJIS_L2, // 卍 + 0x51D6, KANJI_SJIS_L2, // 凖 + 0x535E, KANJI_SJIS_L2, // 卞 + 0x5369, KANJI_SJIS_L2, // 卩 + 0x536E, KANJI_SJIS_L2, // 卮 + 0x5918, KANJI_SJIS_L2, // 倘 + 0x537B, KANJI_SJIS_L2, // 卻 + 0x5377, KANJI_SJIS_L2, // 卷 + 0x5382, KANJI_SJIS_L2, // 厂 + 0x5396, KANJI_SJIS_L2, // 厖 + 0x53A0, KANJI_SJIS_L2, // 厠 + 0x53A6, KANJI_SJIS_L2, // 厊 + 0x53A5, KANJI_SJIS_L2, // 厥 + 0x53AE, KANJI_SJIS_L2, // 厮 + 0x53B0, KANJI_SJIS_L2, // 厰 + 0x53B6, KANJI_SJIS_L2, // 厶 + 0x53C3, KANJI_SJIS_L2, // 參 + 0x7C12, KANJI_SJIS_L2, // 簒 + 0x96D9, KANJI_SJIS_L2, // 雙 + 0x53DF, KANJI_SJIS_L2, // 叟 + 0x66FC, KANJI_SJIS_L2, // 曌 + 0x71EE, KANJI_SJIS_L2, // 燮 + 0x53EE, KANJI_SJIS_L2, // 叮 + 0x53E8, KANJI_SJIS_L2, // 叚 + 0x53ED, KANJI_SJIS_L2, // 叭 + 0x53FA, KANJI_SJIS_L2, // 叺 + 0x5401, KANJI_SJIS_L2, // 吁 + 0x543D, KANJI_SJIS_L2, // 吜 + 0x5440, KANJI_SJIS_L2, // 呀 + 0x542C, KANJI_SJIS_L2, // 听 + 0x542D, KANJI_SJIS_L2, // 吭 + 0x543C, KANJI_SJIS_L2, // 同 + 0x542E, KANJI_SJIS_L2, // 吮 + 0x5436, KANJI_SJIS_L2, // 吶 + 0x5429, KANJI_SJIS_L2, // 吩 + 0x541D, KANJI_SJIS_L2, // 吝 + 0x544E, KANJI_SJIS_L2, // 呎 + 0x548F, KANJI_SJIS_L2, // 咏 + 0x5475, KANJI_SJIS_L2, // 呵 + 0x548E, KANJI_SJIS_L2, // 咎 + 0x545F, KANJI_SJIS_L2, // 呟 + 0x5471, KANJI_SJIS_L2, // 呱 + 0x5477, KANJI_SJIS_L2, // 呷 + 0x5470, KANJI_SJIS_L2, // 呰 + 0x5492, KANJI_SJIS_L2, // 咒 + 0x547B, KANJI_SJIS_L2, // 呻 + 0x5480, KANJI_SJIS_L2, // 咀 + 0x5476, KANJI_SJIS_L2, // 呶 + 0x5484, KANJI_SJIS_L2, // 咄 + 0x5490, KANJI_SJIS_L2, // 咐 + 0x5486, KANJI_SJIS_L2, // 咆 + 0x54C7, KANJI_SJIS_L2, // 哇 + 0x54A2, KANJI_SJIS_L2, // 咢 + 0x54B8, KANJI_SJIS_L2, // å’ž + 0x54A5, KANJI_SJIS_L2, // 咥 + 0x54AC, KANJI_SJIS_L2, // 咬 + 0x54C4, KANJI_SJIS_L2, // 哄 + 0x54C8, KANJI_SJIS_L2, // 哈 + 0x54A8, KANJI_SJIS_L2, // å’š + 0x54AB, KANJI_SJIS_L2, // 咫 + 0x54C2, KANJI_SJIS_L2, // 哂 + 0x54A4, KANJI_SJIS_L2, // å’€ + 0x54BE, KANJI_SJIS_L2, // å’Ÿ + 0x54BC, KANJI_SJIS_L2, // å’Œ + 0x54D8, KANJI_SJIS_L2, // 哘 + 0x54E5, KANJI_SJIS_L2, // 哥 + 0x54E6, KANJI_SJIS_L2, // 哊 + 0x550F, KANJI_SJIS_L2, // 唏 + 0x5514, KANJI_SJIS_L2, // 唔 + 0x54FD, KANJI_SJIS_L2, // 哜 + 0x54EE, KANJI_SJIS_L2, // 哮 + 0x54ED, KANJI_SJIS_L2, // 哭 + 0x54FA, KANJI_SJIS_L2, // 哺 + 0x54E2, KANJI_SJIS_L2, // 哢 + 0x5539, KANJI_SJIS_L2, // 唹 + 0x5540, KANJI_SJIS_L2, // 啀 + 0x5563, KANJI_SJIS_L2, // 啣 + 0x554C, KANJI_SJIS_L2, // 啌 + 0x552E, KANJI_SJIS_L2, // 售 + 0x555C, KANJI_SJIS_L2, // 啜 + 0x5545, KANJI_SJIS_L2, // 啅 + 0x5556, KANJI_SJIS_L2, // 啖 + 0x5557, KANJI_SJIS_L2, // 啗 + 0x5538, KANJI_SJIS_L2, // 唞 + 0x5533, KANJI_SJIS_L2, // 唳 + 0x555D, KANJI_SJIS_L2, // 啝 + 0x5599, KANJI_SJIS_L2, // 喙 + 0x5580, KANJI_SJIS_L2, // 喀 + 0x54AF, KANJI_SJIS_L2, // 咯 + 0x558A, KANJI_SJIS_L2, // 喊 + 0x559F, KANJI_SJIS_L2, // 喟 + 0x557B, KANJI_SJIS_L2, // 啻 + 0x557E, KANJI_SJIS_L2, // 啟 + 0x5598, KANJI_SJIS_L2, // 喘 + 0x559E, KANJI_SJIS_L2, // 喞 + 0x55AE, KANJI_SJIS_L2, // 單 + 0x557C, KANJI_SJIS_L2, // 啌 + 0x5583, KANJI_SJIS_L2, // 喃 + 0x55A9, KANJI_SJIS_L2, // 喩 + 0x5587, KANJI_SJIS_L2, // 喇 + 0x55A8, KANJI_SJIS_L2, // å–š + 0x55DA, KANJI_SJIS_L2, // 嗚 + 0x55C5, KANJI_SJIS_L2, // 嗅 + 0x55DF, KANJI_SJIS_L2, // 嗟 + 0x55C4, KANJI_SJIS_L2, // 嗄 + 0x55DC, KANJI_SJIS_L2, // 嗜 + 0x55E4, KANJI_SJIS_L2, // å—€ + 0x55D4, KANJI_SJIS_L2, // 嗔 + 0x5614, KANJI_SJIS_L2, // 嘔 + 0x55F7, KANJI_SJIS_L2, // 嗷 + 0x5616, KANJI_SJIS_L2, // 嘖 + 0x55FE, KANJI_SJIS_L2, // å—Ÿ + 0x55FD, KANJI_SJIS_L2, // å—œ + 0x561B, KANJI_SJIS_L2, // 嘛 + 0x55F9, KANJI_SJIS_L2, // 嗹 + 0x564E, KANJI_SJIS_L2, // 噎 + 0x5650, KANJI_SJIS_L2, // 噐 + 0x71DF, KANJI_SJIS_L2, // 營 + 0x5634, KANJI_SJIS_L2, // 嘎 + 0x5636, KANJI_SJIS_L2, // 嘶 + 0x5632, KANJI_SJIS_L2, // 嘲 + 0x5638, KANJI_SJIS_L2, // 嘞 + 0x3000, KANJI_SJIS_L2, //   + 0x566B, KANJI_SJIS_L2, // 噫 + 0x5664, KANJI_SJIS_L2, // 噀 + 0x562F, KANJI_SJIS_L2, // 嘯 + 0x566C, KANJI_SJIS_L2, // 噬 + 0x566A, KANJI_SJIS_L2, // 噪 + 0x5686, KANJI_SJIS_L2, // 嚆 + 0x5680, KANJI_SJIS_L2, // 嚀 + 0x568A, KANJI_SJIS_L2, // 嚊 + 0x56A0, KANJI_SJIS_L2, // 嚠 + 0x5694, KANJI_SJIS_L2, // 嚔 + 0x568F, KANJI_SJIS_L2, // 嚏 + 0x56A5, KANJI_SJIS_L2, // 嚥 + 0x56AE, KANJI_SJIS_L2, // 嚮 + 0x56B6, KANJI_SJIS_L2, // 嚶 + 0x56B4, KANJI_SJIS_L2, // 嚎 + 0x56C2, KANJI_SJIS_L2, // 囂 + 0x56BC, KANJI_SJIS_L2, // 嚌 + 0x56C1, KANJI_SJIS_L2, // 囁 + 0x56C3, KANJI_SJIS_L2, // 囃 + 0x56C0, KANJI_SJIS_L2, // 囀 + 0x56C8, KANJI_SJIS_L2, // 囈 + 0x56CE, KANJI_SJIS_L2, // 囎 + 0x56D1, KANJI_SJIS_L2, // 囑 + 0x56D3, KANJI_SJIS_L2, // 囓 + 0x56D7, KANJI_SJIS_L2, // 囗 + 0x56EE, KANJI_SJIS_L2, // 囮 + 0x56F9, KANJI_SJIS_L2, // 囹 + 0x5700, KANJI_SJIS_L2, // 圀 + 0x56FF, KANJI_SJIS_L2, // 囿 + 0x5704, KANJI_SJIS_L2, // 圄 + 0x5709, KANJI_SJIS_L2, // 圉 + 0x5708, KANJI_SJIS_L2, // 圈 + 0x570B, KANJI_SJIS_L2, // 國 + 0x570D, KANJI_SJIS_L2, // 圍 + 0x5713, KANJI_SJIS_L2, // 圓 + 0x5718, KANJI_SJIS_L2, // 團 + 0x5716, KANJI_SJIS_L2, // 圖 + 0x55C7, KANJI_SJIS_L2, // 嗇 + 0x571C, KANJI_SJIS_L2, // 圜 + 0x5726, KANJI_SJIS_L2, // 圊 + 0x5737, KANJI_SJIS_L2, // 圷 + 0x5738, KANJI_SJIS_L2, // 圞 + 0x574E, KANJI_SJIS_L2, // 坎 + 0x573B, KANJI_SJIS_L2, // 圻 + 0x5740, KANJI_SJIS_L2, // 址 + 0x574F, KANJI_SJIS_L2, // 坏 + 0x5769, KANJI_SJIS_L2, // 坩 + 0x57C0, KANJI_SJIS_L2, // 埀 + 0x5788, KANJI_SJIS_L2, // 垈 + 0x5761, KANJI_SJIS_L2, // 坡 + 0x577F, KANJI_SJIS_L2, // 坿 + 0x5789, KANJI_SJIS_L2, // 垉 + 0x5793, KANJI_SJIS_L2, // 垓 + 0x57A0, KANJI_SJIS_L2, // 垠 + 0x57B3, KANJI_SJIS_L2, // 垳 + 0x57A4, KANJI_SJIS_L2, // 垀 + 0x57AA, KANJI_SJIS_L2, // 垪 + 0x57B0, KANJI_SJIS_L2, // 垰 + 0x57C3, KANJI_SJIS_L2, // 埃 + 0x57C6, KANJI_SJIS_L2, // 埆 + 0x57D4, KANJI_SJIS_L2, // 埔 + 0x57D2, KANJI_SJIS_L2, // 埒 + 0x57D3, KANJI_SJIS_L2, // 埓 + 0x580A, KANJI_SJIS_L2, // 堊 + 0x57D6, KANJI_SJIS_L2, // 埖 + 0x57E3, KANJI_SJIS_L2, // 埣 + 0x580B, KANJI_SJIS_L2, // 堋 + 0x5819, KANJI_SJIS_L2, // 堙 + 0x581D, KANJI_SJIS_L2, // 堝 + 0x5872, KANJI_SJIS_L2, // 塲 + 0x5821, KANJI_SJIS_L2, // å ¡ + 0x5862, KANJI_SJIS_L2, // å¡¢ + 0x584B, KANJI_SJIS_L2, // 塋 + 0x5870, KANJI_SJIS_L2, // å¡° + 0x6BC0, KANJI_SJIS_L2, // 毀 + 0x5852, KANJI_SJIS_L2, // 塒 + 0x583D, KANJI_SJIS_L2, // å œ + 0x5879, KANJI_SJIS_L2, // 塹 + 0x5885, KANJI_SJIS_L2, // 墅 + 0x58B9, KANJI_SJIS_L2, // 墹 + 0x589F, KANJI_SJIS_L2, // 墟 + 0x58AB, KANJI_SJIS_L2, // 墫 + 0x58BA, KANJI_SJIS_L2, // 墺 + 0x58DE, KANJI_SJIS_L2, // 壞 + 0x58BB, KANJI_SJIS_L2, // 墻 + 0x58B8, KANJI_SJIS_L2, // 增 + 0x58AE, KANJI_SJIS_L2, // 墮 + 0x58C5, KANJI_SJIS_L2, // 壅 + 0x58D3, KANJI_SJIS_L2, // 壓 + 0x58D1, KANJI_SJIS_L2, // 壑 + 0x58D7, KANJI_SJIS_L2, // 壗 + 0x58D9, KANJI_SJIS_L2, // 壙 + 0x58D8, KANJI_SJIS_L2, // 壘 + 0x58E5, KANJI_SJIS_L2, // 壥 + 0x58DC, KANJI_SJIS_L2, // 壜 + 0x58E4, KANJI_SJIS_L2, // 壀 + 0x58DF, KANJI_SJIS_L2, // 壟 + 0x58EF, KANJI_SJIS_L2, // 壯 + 0x58FA, KANJI_SJIS_L2, // 壺 + 0x58F9, KANJI_SJIS_L2, // 壹 + 0x58FB, KANJI_SJIS_L2, // 壻 + 0x58FC, KANJI_SJIS_L2, // 壌 + 0x58FD, KANJI_SJIS_L2, // 壜 + 0x5902, KANJI_SJIS_L2, // 倂 + 0x590A, KANJI_SJIS_L2, // 倊 + 0x5910, KANJI_SJIS_L2, // 倐 + 0x591B, KANJI_SJIS_L2, // 倛 + 0x68A6, KANJI_SJIS_L2, // 梊 + 0x5925, KANJI_SJIS_L2, // 倥 + 0x592C, KANJI_SJIS_L2, // 倬 + 0x592D, KANJI_SJIS_L2, // 倭 + 0x5932, KANJI_SJIS_L2, // 倲 + 0x5938, KANJI_SJIS_L2, // 倞 + 0x593E, KANJI_SJIS_L2, // 借 + 0x7AD2, KANJI_SJIS_L2, // 竒 + 0x5955, KANJI_SJIS_L2, // 奕 + 0x5950, KANJI_SJIS_L2, // 奐 + 0x594E, KANJI_SJIS_L2, // 奎 + 0x595A, KANJI_SJIS_L2, // 奚 + 0x5958, KANJI_SJIS_L2, // 奘 + 0x5962, KANJI_SJIS_L2, // 奢 + 0x5960, KANJI_SJIS_L2, // 奠 + 0x5967, KANJI_SJIS_L2, // 奧 + 0x596C, KANJI_SJIS_L2, // 奬 + 0x5969, KANJI_SJIS_L2, // 奩 + 0x5978, KANJI_SJIS_L2, // 奞 + 0x5981, KANJI_SJIS_L2, // 劁 + 0x599D, KANJI_SJIS_L2, // 劝 + 0x4F5E, KANJI_SJIS_L2, // 䜞 + 0x4FAB, KANJI_SJIS_L2, // 䟫 + 0x59A3, KANJI_SJIS_L2, // 劣 + 0x59B2, KANJI_SJIS_L2, // 劲 + 0x59C6, KANJI_SJIS_L2, // 姆 + 0x59E8, KANJI_SJIS_L2, // å§š + 0x59DC, KANJI_SJIS_L2, // 姜 + 0x598D, KANJI_SJIS_L2, // 劍 + 0x59D9, KANJI_SJIS_L2, // 姙 + 0x59DA, KANJI_SJIS_L2, // 姚 + 0x5A25, KANJI_SJIS_L2, // 嚥 + 0x5A1F, KANJI_SJIS_L2, // 嚟 + 0x5A11, KANJI_SJIS_L2, // åš‘ + 0x5A1C, KANJI_SJIS_L2, // åšœ + 0x5A09, KANJI_SJIS_L2, // 嚉 + 0x5A1A, KANJI_SJIS_L2, // åšš + 0x5A40, KANJI_SJIS_L2, // 婀 + 0x5A6C, KANJI_SJIS_L2, // 婬 + 0x5A49, KANJI_SJIS_L2, // 婉 + 0x5A35, KANJI_SJIS_L2, // åšµ + 0x5A36, KANJI_SJIS_L2, // åš¶ + 0x5A62, KANJI_SJIS_L2, // å©¢ + 0x5A6A, KANJI_SJIS_L2, // 婪 + 0x5A9A, KANJI_SJIS_L2, // 媚 + 0x5ABC, KANJI_SJIS_L2, // 媌 + 0x5ABE, KANJI_SJIS_L2, // 媟 + 0x5ACB, KANJI_SJIS_L2, // 嫋 + 0x5AC2, KANJI_SJIS_L2, // 嫂 + 0x5ABD, KANJI_SJIS_L2, // 媜 + 0x5AE3, KANJI_SJIS_L2, // å«£ + 0x5AD7, KANJI_SJIS_L2, // 嫗 + 0x5AE6, KANJI_SJIS_L2, // 嫊 + 0x5AE9, KANJI_SJIS_L2, // å«© + 0x5AD6, KANJI_SJIS_L2, // 嫖 + 0x5AFA, KANJI_SJIS_L2, // 嫺 + 0x5AFB, KANJI_SJIS_L2, // å«» + 0x5B0C, KANJI_SJIS_L2, // 嬌 + 0x5B0B, KANJI_SJIS_L2, // 嬋 + 0x5B16, KANJI_SJIS_L2, // 嬖 + 0x5B32, KANJI_SJIS_L2, // 嬲 + 0x5AD0, KANJI_SJIS_L2, // 嫐 + 0x5B2A, KANJI_SJIS_L2, // 嬪 + 0x5B36, KANJI_SJIS_L2, // 嬶 + 0x5B3E, KANJI_SJIS_L2, // 嬟 + 0x5B43, KANJI_SJIS_L2, // 孃 + 0x5B45, KANJI_SJIS_L2, // 孅 + 0x5B40, KANJI_SJIS_L2, // 孀 + 0x5B51, KANJI_SJIS_L2, // 孑 + 0x5B55, KANJI_SJIS_L2, // 孕 + 0x5B5A, KANJI_SJIS_L2, // 孚 + 0x5B5B, KANJI_SJIS_L2, // 孛 + 0x5B65, KANJI_SJIS_L2, // å­¥ + 0x5B69, KANJI_SJIS_L2, // å­© + 0x5B70, KANJI_SJIS_L2, // å­° + 0x5B73, KANJI_SJIS_L2, // å­³ + 0x5B75, KANJI_SJIS_L2, // å­µ + 0x5B78, KANJI_SJIS_L2, // å­ž + 0x6588, KANJI_SJIS_L2, // 斈 + 0x5B7A, KANJI_SJIS_L2, // å­º + 0x5B80, KANJI_SJIS_L2, // 宀 + 0x3000, KANJI_SJIS_L2, //   + 0x5B83, KANJI_SJIS_L2, // 它 + 0x5BA6, KANJI_SJIS_L2, // 宊 + 0x5BB8, KANJI_SJIS_L2, // 实 + 0x5BC3, KANJI_SJIS_L2, // 寃 + 0x5BC7, KANJI_SJIS_L2, // 寇 + 0x5BC9, KANJI_SJIS_L2, // 寉 + 0x5BD4, KANJI_SJIS_L2, // 寔 + 0x5BD0, KANJI_SJIS_L2, // 寐 + 0x5BE4, KANJI_SJIS_L2, // 寀 + 0x5BE6, KANJI_SJIS_L2, // 寊 + 0x5BE2, KANJI_SJIS_L2, // 寢 + 0x5BDE, KANJI_SJIS_L2, // 寞 + 0x5BE5, KANJI_SJIS_L2, // 寥 + 0x5BEB, KANJI_SJIS_L2, // 寫 + 0x5BF0, KANJI_SJIS_L2, // 寰 + 0x5BF6, KANJI_SJIS_L2, // 寶 + 0x5BF3, KANJI_SJIS_L2, // 寳 + 0x5C05, KANJI_SJIS_L2, // 尅 + 0x5C07, KANJI_SJIS_L2, // 將 + 0x5C08, KANJI_SJIS_L2, // 專 + 0x5C0D, KANJI_SJIS_L2, // 對 + 0x5C13, KANJI_SJIS_L2, // 尓 + 0x5C20, KANJI_SJIS_L2, // å°  + 0x5C22, KANJI_SJIS_L2, // å°¢ + 0x5C28, KANJI_SJIS_L2, // å°š + 0x5C38, KANJI_SJIS_L2, // å°ž + 0x5C39, KANJI_SJIS_L2, // å°¹ + 0x5C41, KANJI_SJIS_L2, // 屁 + 0x5C46, KANJI_SJIS_L2, // 屆 + 0x5C4E, KANJI_SJIS_L2, // 屎 + 0x5C53, KANJI_SJIS_L2, // 屓 + 0x5C50, KANJI_SJIS_L2, // 屐 + 0x5C4F, KANJI_SJIS_L2, // 屏 + 0x5B71, KANJI_SJIS_L2, // å­± + 0x5C6C, KANJI_SJIS_L2, // 屬 + 0x5C6E, KANJI_SJIS_L2, // å±® + 0x4E62, KANJI_SJIS_L2, // ä¹¢ + 0x5C76, KANJI_SJIS_L2, // å±¶ + 0x5C79, KANJI_SJIS_L2, // å±¹ + 0x5C8C, KANJI_SJIS_L2, // 岌 + 0x5C91, KANJI_SJIS_L2, // 岑 + 0x5C94, KANJI_SJIS_L2, // 岔 + 0x599B, KANJI_SJIS_L2, // 力 + 0x5CAB, KANJI_SJIS_L2, // 岫 + 0x5CBB, KANJI_SJIS_L2, // å²» + 0x5CB6, KANJI_SJIS_L2, // å²¶ + 0x5CBC, KANJI_SJIS_L2, // 岌 + 0x5CB7, KANJI_SJIS_L2, // å²· + 0x5CC5, KANJI_SJIS_L2, // 峅 + 0x5CBE, KANJI_SJIS_L2, // 岟 + 0x5CC7, KANJI_SJIS_L2, // 峇 + 0x5CD9, KANJI_SJIS_L2, // 峙 + 0x5CE9, KANJI_SJIS_L2, // 峩 + 0x5CFD, KANJI_SJIS_L2, // 峜 + 0x5CFA, KANJI_SJIS_L2, // 峺 + 0x5CED, KANJI_SJIS_L2, // å³­ + 0x5D8C, KANJI_SJIS_L2, // 嶌 + 0x5CEA, KANJI_SJIS_L2, // 峪 + 0x5D0B, KANJI_SJIS_L2, // 压 + 0x5D15, KANJI_SJIS_L2, // 厕 + 0x5D17, KANJI_SJIS_L2, // 厗 + 0x5D5C, KANJI_SJIS_L2, // 嵜 + 0x5D1F, KANJI_SJIS_L2, // 原 + 0x5D1B, KANJI_SJIS_L2, // 厛 + 0x5D11, KANJI_SJIS_L2, // 厑 + 0x5D14, KANJI_SJIS_L2, // 厔 + 0x5D22, KANJI_SJIS_L2, // 厢 + 0x5D1A, KANJI_SJIS_L2, // 厚 + 0x5D19, KANJI_SJIS_L2, // 厙 + 0x5D18, KANJI_SJIS_L2, // 厘 + 0x5D4C, KANJI_SJIS_L2, // 嵌 + 0x5D52, KANJI_SJIS_L2, // 嵒 + 0x5D4E, KANJI_SJIS_L2, // 嵎 + 0x5D4B, KANJI_SJIS_L2, // 嵋 + 0x5D6C, KANJI_SJIS_L2, // 嵬 + 0x5D73, KANJI_SJIS_L2, // åµ³ + 0x5D76, KANJI_SJIS_L2, // åµ¶ + 0x5D87, KANJI_SJIS_L2, // 嶇 + 0x5D84, KANJI_SJIS_L2, // 嶄 + 0x5D82, KANJI_SJIS_L2, // 嶂 + 0x5DA2, KANJI_SJIS_L2, // å¶¢ + 0x5D9D, KANJI_SJIS_L2, // 嶝 + 0x5DAC, KANJI_SJIS_L2, // 嶬 + 0x5DAE, KANJI_SJIS_L2, // å¶® + 0x5DBD, KANJI_SJIS_L2, // å¶œ + 0x5D90, KANJI_SJIS_L2, // 嶐 + 0x5DB7, KANJI_SJIS_L2, // å¶· + 0x5DBC, KANJI_SJIS_L2, // å¶Œ + 0x5DC9, KANJI_SJIS_L2, // 巉 + 0x5DCD, KANJI_SJIS_L2, // 巍 + 0x5DD3, KANJI_SJIS_L2, // 巓 + 0x5DD2, KANJI_SJIS_L2, // 巒 + 0x5DD6, KANJI_SJIS_L2, // 巖 + 0x5DDB, KANJI_SJIS_L2, // 巛 + 0x5DEB, KANJI_SJIS_L2, // å·« + 0x5DF2, KANJI_SJIS_L2, // å·² + 0x5DF5, KANJI_SJIS_L2, // å·µ + 0x5E0B, KANJI_SJIS_L2, // åž‹ + 0x5E1A, KANJI_SJIS_L2, // åžš + 0x5E19, KANJI_SJIS_L2, // åž™ + 0x5E11, KANJI_SJIS_L2, // åž‘ + 0x5E1B, KANJI_SJIS_L2, // åž› + 0x5E36, KANJI_SJIS_L2, // åž¶ + 0x5E37, KANJI_SJIS_L2, // åž· + 0x5E44, KANJI_SJIS_L2, // 幄 + 0x5E43, KANJI_SJIS_L2, // 幃 + 0x5E40, KANJI_SJIS_L2, // 幀 + 0x5E4E, KANJI_SJIS_L2, // 幎 + 0x5E57, KANJI_SJIS_L2, // 幗 + 0x5E54, KANJI_SJIS_L2, // 幔 + 0x5E5F, KANJI_SJIS_L2, // 幟 + 0x5E62, KANJI_SJIS_L2, // å¹¢ + 0x5E64, KANJI_SJIS_L2, // å¹€ + 0x5E47, KANJI_SJIS_L2, // 幇 + 0x5E75, KANJI_SJIS_L2, // å¹µ + 0x5E76, KANJI_SJIS_L2, // å¹¶ + 0x5E7A, KANJI_SJIS_L2, // 幺 + 0x9EBC, KANJI_SJIS_L2, // 麌 + 0x5E7F, KANJI_SJIS_L2, // 广 + 0x5EA0, KANJI_SJIS_L2, // 庠 + 0x5EC1, KANJI_SJIS_L2, // 廁 + 0x5EC2, KANJI_SJIS_L2, // 廂 + 0x5EC8, KANJI_SJIS_L2, // 廈 + 0x5ED0, KANJI_SJIS_L2, // 廐 + 0x5ECF, KANJI_SJIS_L2, // 廏 + 0x5ED6, KANJI_SJIS_L2, // 廖 + 0x5EE3, KANJI_SJIS_L2, // 廣 + 0x5EDD, KANJI_SJIS_L2, // 廝 + 0x5EDA, KANJI_SJIS_L2, // 廚 + 0x5EDB, KANJI_SJIS_L2, // 廛 + 0x5EE2, KANJI_SJIS_L2, // 廢 + 0x5EE1, KANJI_SJIS_L2, // 廡 + 0x5EE8, KANJI_SJIS_L2, // 廚 + 0x5EE9, KANJI_SJIS_L2, // 廩 + 0x5EEC, KANJI_SJIS_L2, // 廬 + 0x5EF1, KANJI_SJIS_L2, // å»± + 0x5EF3, KANJI_SJIS_L2, // 廳 + 0x5EF0, KANJI_SJIS_L2, // å»° + 0x5EF4, KANJI_SJIS_L2, // 廎 + 0x5EF8, KANJI_SJIS_L2, // 廞 + 0x5EFE, KANJI_SJIS_L2, // 廟 + 0x5F03, KANJI_SJIS_L2, // 匃 + 0x5F09, KANJI_SJIS_L2, // 匉 + 0x5F5D, KANJI_SJIS_L2, // 圝 + 0x5F5C, KANJI_SJIS_L2, // 圜 + 0x5F0B, KANJI_SJIS_L2, // 匋 + 0x5F11, KANJI_SJIS_L2, // 匑 + 0x5F16, KANJI_SJIS_L2, // 化 + 0x5F29, KANJI_SJIS_L2, // 匩 + 0x5F2D, KANJI_SJIS_L2, // 匭 + 0x5F38, KANJI_SJIS_L2, // 匞 + 0x5F41, KANJI_SJIS_L2, // 圁 + 0x5F48, KANJI_SJIS_L2, // 圈 + 0x5F4C, KANJI_SJIS_L2, // 圌 + 0x5F4E, KANJI_SJIS_L2, // 圎 + 0x5F2F, KANJI_SJIS_L2, // 匯 + 0x5F51, KANJI_SJIS_L2, // 圑 + 0x5F56, KANJI_SJIS_L2, // 圖 + 0x5F57, KANJI_SJIS_L2, // 圗 + 0x5F59, KANJI_SJIS_L2, // 圙 + 0x5F61, KANJI_SJIS_L2, // 圡 + 0x5F6D, KANJI_SJIS_L2, // 圭 + 0x5F73, KANJI_SJIS_L2, // 圳 + 0x5F77, KANJI_SJIS_L2, // 圷 + 0x5F83, KANJI_SJIS_L2, // 埃 + 0x5F82, KANJI_SJIS_L2, // 埂 + 0x5F7F, KANJI_SJIS_L2, // 圿 + 0x5F8A, KANJI_SJIS_L2, // 埊 + 0x5F88, KANJI_SJIS_L2, // 埈 + 0x5F91, KANJI_SJIS_L2, // 埑 + 0x5F87, KANJI_SJIS_L2, // 埇 + 0x5F9E, KANJI_SJIS_L2, // 埞 + 0x5F99, KANJI_SJIS_L2, // 埙 + 0x5F98, KANJI_SJIS_L2, // 埘 + 0x5FA0, KANJI_SJIS_L2, // 埠 + 0x5FA8, KANJI_SJIS_L2, // 埚 + 0x5FAD, KANJI_SJIS_L2, // 埭 + 0x5FBC, KANJI_SJIS_L2, // 埌 + 0x5FD6, KANJI_SJIS_L2, // 忖 + 0x5FFB, KANJI_SJIS_L2, // å¿» + 0x5FE4, KANJI_SJIS_L2, // å¿€ + 0x5FF8, KANJI_SJIS_L2, // 忞 + 0x5FF1, KANJI_SJIS_L2, // 忱 + 0x5FDD, KANJI_SJIS_L2, // 忝 + 0x60B3, KANJI_SJIS_L2, // 悳 + 0x5FFF, KANJI_SJIS_L2, // å¿¿ + 0x6021, KANJI_SJIS_L2, // 怡 + 0x6060, KANJI_SJIS_L2, // 恠 + 0x3000, KANJI_SJIS_L2, //   + 0x6019, KANJI_SJIS_L2, // 怙 + 0x6010, KANJI_SJIS_L2, // 怐 + 0x6029, KANJI_SJIS_L2, // 怩 + 0x600E, KANJI_SJIS_L2, // 怎 + 0x6031, KANJI_SJIS_L2, // 怱 + 0x601B, KANJI_SJIS_L2, // 怛 + 0x6015, KANJI_SJIS_L2, // 怕 + 0x602B, KANJI_SJIS_L2, // 怫 + 0x6026, KANJI_SJIS_L2, // 怊 + 0x600F, KANJI_SJIS_L2, // 怏 + 0x603A, KANJI_SJIS_L2, // 怺 + 0x605A, KANJI_SJIS_L2, // 恚 + 0x6041, KANJI_SJIS_L2, // 恁 + 0x606A, KANJI_SJIS_L2, // 恪 + 0x6077, KANJI_SJIS_L2, // 恷 + 0x605F, KANJI_SJIS_L2, // 恟 + 0x604A, KANJI_SJIS_L2, // 恊 + 0x6046, KANJI_SJIS_L2, // 恆 + 0x604D, KANJI_SJIS_L2, // 恍 + 0x6063, KANJI_SJIS_L2, // 恣 + 0x6043, KANJI_SJIS_L2, // 恃 + 0x6064, KANJI_SJIS_L2, // 恀 + 0x6042, KANJI_SJIS_L2, // 恂 + 0x606C, KANJI_SJIS_L2, // 恬 + 0x606B, KANJI_SJIS_L2, // 恫 + 0x6059, KANJI_SJIS_L2, // 恙 + 0x6081, KANJI_SJIS_L2, // 悁 + 0x608D, KANJI_SJIS_L2, // 悍 + 0x60E7, KANJI_SJIS_L2, // 惧 + 0x6083, KANJI_SJIS_L2, // 悃 + 0x609A, KANJI_SJIS_L2, // 悚 + 0x6084, KANJI_SJIS_L2, // 悄 + 0x609B, KANJI_SJIS_L2, // 悛 + 0x6096, KANJI_SJIS_L2, // 悖 + 0x6097, KANJI_SJIS_L2, // 悗 + 0x6092, KANJI_SJIS_L2, // 悒 + 0x60A7, KANJI_SJIS_L2, // 悧 + 0x608B, KANJI_SJIS_L2, // 悋 + 0x60E1, KANJI_SJIS_L2, // 惡 + 0x60B8, KANJI_SJIS_L2, // 悞 + 0x60E0, KANJI_SJIS_L2, // 惠 + 0x60D3, KANJI_SJIS_L2, // 惓 + 0x60B4, KANJI_SJIS_L2, // 悎 + 0x5FF0, KANJI_SJIS_L2, // å¿° + 0x60BD, KANJI_SJIS_L2, // 悜 + 0x60C6, KANJI_SJIS_L2, // 惆 + 0x60B5, KANJI_SJIS_L2, // 悵 + 0x60D8, KANJI_SJIS_L2, // 惘 + 0x614D, KANJI_SJIS_L2, // 慍 + 0x6115, KANJI_SJIS_L2, // 愕 + 0x6106, KANJI_SJIS_L2, // 愆 + 0x60F6, KANJI_SJIS_L2, // 惶 + 0x60F7, KANJI_SJIS_L2, // 惷 + 0x6100, KANJI_SJIS_L2, // 愀 + 0x60F4, KANJI_SJIS_L2, // 惎 + 0x60FA, KANJI_SJIS_L2, // 惺 + 0x6103, KANJI_SJIS_L2, // 愃 + 0x6121, KANJI_SJIS_L2, // 愡 + 0x60FB, KANJI_SJIS_L2, // 惻 + 0x60F1, KANJI_SJIS_L2, // 惱 + 0x610D, KANJI_SJIS_L2, // 愍 + 0x610E, KANJI_SJIS_L2, // 愎 + 0x6147, KANJI_SJIS_L2, // 慇 + 0x613E, KANJI_SJIS_L2, // 感 + 0x6128, KANJI_SJIS_L2, // 愚 + 0x6127, KANJI_SJIS_L2, // 愧 + 0x614A, KANJI_SJIS_L2, // 慊 + 0x613F, KANJI_SJIS_L2, // 愿 + 0x613C, KANJI_SJIS_L2, // 愌 + 0x612C, KANJI_SJIS_L2, // 愬 + 0x6134, KANJI_SJIS_L2, // 愎 + 0x613D, KANJI_SJIS_L2, // 愜 + 0x6142, KANJI_SJIS_L2, // 慂 + 0x6144, KANJI_SJIS_L2, // 慄 + 0x6173, KANJI_SJIS_L2, // 慳 + 0x6177, KANJI_SJIS_L2, // 慷 + 0x6158, KANJI_SJIS_L2, // 慘 + 0x6159, KANJI_SJIS_L2, // 慙 + 0x615A, KANJI_SJIS_L2, // 慚 + 0x616B, KANJI_SJIS_L2, // 慫 + 0x6174, KANJI_SJIS_L2, // æ…Ž + 0x616F, KANJI_SJIS_L2, // 慯 + 0x6165, KANJI_SJIS_L2, // 慥 + 0x6171, KANJI_SJIS_L2, // 慱 + 0x615F, KANJI_SJIS_L2, // 慟 + 0x615D, KANJI_SJIS_L2, // 慝 + 0x6153, KANJI_SJIS_L2, // 慓 + 0x6175, KANJI_SJIS_L2, // 慵 + 0x6199, KANJI_SJIS_L2, // 憙 + 0x6196, KANJI_SJIS_L2, // 憖 + 0x6187, KANJI_SJIS_L2, // 憇 + 0x61AC, KANJI_SJIS_L2, // 憬 + 0x6194, KANJI_SJIS_L2, // 憔 + 0x619A, KANJI_SJIS_L2, // 憚 + 0x618A, KANJI_SJIS_L2, // 憊 + 0x6191, KANJI_SJIS_L2, // 憑 + 0x61AB, KANJI_SJIS_L2, // 憫 + 0x61AE, KANJI_SJIS_L2, // 憮 + 0x61CC, KANJI_SJIS_L2, // 懌 + 0x61CA, KANJI_SJIS_L2, // 懊 + 0x61C9, KANJI_SJIS_L2, // 應 + 0x61F7, KANJI_SJIS_L2, // 懷 + 0x61C8, KANJI_SJIS_L2, // 懈 + 0x61C3, KANJI_SJIS_L2, // 懃 + 0x61C6, KANJI_SJIS_L2, // 懆 + 0x61BA, KANJI_SJIS_L2, // 憺 + 0x61CB, KANJI_SJIS_L2, // 懋 + 0x7F79, KANJI_SJIS_L2, // 眹 + 0x61CD, KANJI_SJIS_L2, // 懍 + 0x61E6, KANJI_SJIS_L2, // 懊 + 0x61E3, KANJI_SJIS_L2, // 懣 + 0x61F6, KANJI_SJIS_L2, // 懶 + 0x61FA, KANJI_SJIS_L2, // 懺 + 0x61F4, KANJI_SJIS_L2, // 懎 + 0x61FF, KANJI_SJIS_L2, // 懿 + 0x61FD, KANJI_SJIS_L2, // 懜 + 0x61FC, KANJI_SJIS_L2, // 懌 + 0x61FE, KANJI_SJIS_L2, // 懟 + 0x6200, KANJI_SJIS_L2, // 戀 + 0x6208, KANJI_SJIS_L2, // 戈 + 0x6209, KANJI_SJIS_L2, // 戉 + 0x620D, KANJI_SJIS_L2, // 戍 + 0x620C, KANJI_SJIS_L2, // 戌 + 0x6214, KANJI_SJIS_L2, // 戔 + 0x621B, KANJI_SJIS_L2, // 戛 + 0x621E, KANJI_SJIS_L2, // 戞 + 0x6221, KANJI_SJIS_L2, // 戡 + 0x622A, KANJI_SJIS_L2, // 截 + 0x622E, KANJI_SJIS_L2, // 戮 + 0x6230, KANJI_SJIS_L2, // 戰 + 0x6232, KANJI_SJIS_L2, // 戲 + 0x6233, KANJI_SJIS_L2, // 戳 + 0x6241, KANJI_SJIS_L2, // 扁 + 0x624E, KANJI_SJIS_L2, // 扎 + 0x625E, KANJI_SJIS_L2, // 扞 + 0x6263, KANJI_SJIS_L2, // 扣 + 0x625B, KANJI_SJIS_L2, // 扛 + 0x6260, KANJI_SJIS_L2, // 扠 + 0x6268, KANJI_SJIS_L2, // 扚 + 0x627C, KANJI_SJIS_L2, // 扌 + 0x6282, KANJI_SJIS_L2, // 抂 + 0x6289, KANJI_SJIS_L2, // 抉 + 0x627E, KANJI_SJIS_L2, // 扟 + 0x6292, KANJI_SJIS_L2, // 抒 + 0x6293, KANJI_SJIS_L2, // 抓 + 0x6296, KANJI_SJIS_L2, // 抖 + 0x62D4, KANJI_SJIS_L2, // 拔 + 0x6283, KANJI_SJIS_L2, // 抃 + 0x6294, KANJI_SJIS_L2, // 抔 + 0x62D7, KANJI_SJIS_L2, // 拗 + 0x62D1, KANJI_SJIS_L2, // 拑 + 0x62BB, KANJI_SJIS_L2, // 抻 + 0x62CF, KANJI_SJIS_L2, // 拏 + 0x62FF, KANJI_SJIS_L2, // 拿 + 0x62C6, KANJI_SJIS_L2, // 拆 + 0x64D4, KANJI_SJIS_L2, // 擔 + 0x62C8, KANJI_SJIS_L2, // 拈 + 0x62DC, KANJI_SJIS_L2, // 拜 + 0x62CC, KANJI_SJIS_L2, // 拌 + 0x62CA, KANJI_SJIS_L2, // 拊 + 0x62C2, KANJI_SJIS_L2, // 拂 + 0x62C7, KANJI_SJIS_L2, // 拇 + 0x629B, KANJI_SJIS_L2, // 抛 + 0x62C9, KANJI_SJIS_L2, // 拉 + 0x630C, KANJI_SJIS_L2, // 挌 + 0x62EE, KANJI_SJIS_L2, // 拮 + 0x62F1, KANJI_SJIS_L2, // 拱 + 0x6327, KANJI_SJIS_L2, // 挧 + 0x6302, KANJI_SJIS_L2, // 挂 + 0x6308, KANJI_SJIS_L2, // 挈 + 0x62EF, KANJI_SJIS_L2, // 拯 + 0x62F5, KANJI_SJIS_L2, // 拵 + 0x6350, KANJI_SJIS_L2, // 捐 + 0x633E, KANJI_SJIS_L2, // 挟 + 0x634D, KANJI_SJIS_L2, // 捍 + 0x641C, KANJI_SJIS_L2, // 搜 + 0x634F, KANJI_SJIS_L2, // 捏 + 0x6396, KANJI_SJIS_L2, // 掖 + 0x638E, KANJI_SJIS_L2, // 掎 + 0x6380, KANJI_SJIS_L2, // 掀 + 0x63AB, KANJI_SJIS_L2, // 掫 + 0x6376, KANJI_SJIS_L2, // 捶 + 0x63A3, KANJI_SJIS_L2, // 掣 + 0x638F, KANJI_SJIS_L2, // 掏 + 0x6389, KANJI_SJIS_L2, // 掉 + 0x639F, KANJI_SJIS_L2, // 掟 + 0x63B5, KANJI_SJIS_L2, // 掵 + 0x636B, KANJI_SJIS_L2, // 捫 + 0x3000, KANJI_SJIS_L2, //   + 0x6369, KANJI_SJIS_L2, // 捩 + 0x63BE, KANJI_SJIS_L2, // 掟 + 0x63E9, KANJI_SJIS_L2, // 揩 + 0x63C0, KANJI_SJIS_L2, // 揀 + 0x63C6, KANJI_SJIS_L2, // 揆 + 0x63E3, KANJI_SJIS_L2, // 揣 + 0x63C9, KANJI_SJIS_L2, // 揉 + 0x63D2, KANJI_SJIS_L2, // 插 + 0x63F6, KANJI_SJIS_L2, // 揶 + 0x63C4, KANJI_SJIS_L2, // 揄 + 0x6416, KANJI_SJIS_L2, // 搖 + 0x6434, KANJI_SJIS_L2, // 搎 + 0x6406, KANJI_SJIS_L2, // 搆 + 0x6413, KANJI_SJIS_L2, // 搓 + 0x6426, KANJI_SJIS_L2, // 搊 + 0x6436, KANJI_SJIS_L2, // 搶 + 0x651D, KANJI_SJIS_L2, // 攝 + 0x6417, KANJI_SJIS_L2, // 搗 + 0x6428, KANJI_SJIS_L2, // 搚 + 0x640F, KANJI_SJIS_L2, // 搏 + 0x6467, KANJI_SJIS_L2, // 摧 + 0x646F, KANJI_SJIS_L2, // 摯 + 0x6476, KANJI_SJIS_L2, // 摶 + 0x644E, KANJI_SJIS_L2, // 摎 + 0x652A, KANJI_SJIS_L2, // 攪 + 0x6495, KANJI_SJIS_L2, // 撕 + 0x6493, KANJI_SJIS_L2, // 撓 + 0x64A5, KANJI_SJIS_L2, // 撥 + 0x64A9, KANJI_SJIS_L2, // 撩 + 0x6488, KANJI_SJIS_L2, // 撈 + 0x64BC, KANJI_SJIS_L2, // æ’Œ + 0x64DA, KANJI_SJIS_L2, // 據 + 0x64D2, KANJI_SJIS_L2, // 擒 + 0x64C5, KANJI_SJIS_L2, // 擅 + 0x64C7, KANJI_SJIS_L2, // 擇 + 0x64BB, KANJI_SJIS_L2, // 撻 + 0x64D8, KANJI_SJIS_L2, // 擘 + 0x64C2, KANJI_SJIS_L2, // 擂 + 0x64F1, KANJI_SJIS_L2, // 擱 + 0x64E7, KANJI_SJIS_L2, // 擧 + 0x8209, KANJI_SJIS_L2, // 舉 + 0x64E0, KANJI_SJIS_L2, // 擠 + 0x64E1, KANJI_SJIS_L2, // 擡 + 0x62AC, KANJI_SJIS_L2, // 抬 + 0x64E3, KANJI_SJIS_L2, // 擣 + 0x64EF, KANJI_SJIS_L2, // 擯 + 0x652C, KANJI_SJIS_L2, // 攬 + 0x64F6, KANJI_SJIS_L2, // 擶 + 0x64F4, KANJI_SJIS_L2, // 擎 + 0x64F2, KANJI_SJIS_L2, // 擲 + 0x64FA, KANJI_SJIS_L2, // 擺 + 0x6500, KANJI_SJIS_L2, // 攀 + 0x64FD, KANJI_SJIS_L2, // 擜 + 0x6518, KANJI_SJIS_L2, // 攘 + 0x651C, KANJI_SJIS_L2, // 攜 + 0x6505, KANJI_SJIS_L2, // 攅 + 0x6524, KANJI_SJIS_L2, // 攀 + 0x6523, KANJI_SJIS_L2, // 攣 + 0x652B, KANJI_SJIS_L2, // 攫 + 0x6534, KANJI_SJIS_L2, // 攎 + 0x6535, KANJI_SJIS_L2, // 攵 + 0x6537, KANJI_SJIS_L2, // 攷 + 0x6536, KANJI_SJIS_L2, // 收 + 0x6538, KANJI_SJIS_L2, // 攞 + 0x754B, KANJI_SJIS_L2, // 畋 + 0x6548, KANJI_SJIS_L2, // 效 + 0x6556, KANJI_SJIS_L2, // 敖 + 0x6555, KANJI_SJIS_L2, // 敕 + 0x654D, KANJI_SJIS_L2, // 敍 + 0x6558, KANJI_SJIS_L2, // 敘 + 0x655E, KANJI_SJIS_L2, // 敞 + 0x655D, KANJI_SJIS_L2, // 敝 + 0x6572, KANJI_SJIS_L2, // 敲 + 0x6578, KANJI_SJIS_L2, // 敞 + 0x6582, KANJI_SJIS_L2, // 斂 + 0x6583, KANJI_SJIS_L2, // 斃 + 0x8B8A, KANJI_SJIS_L2, // 變 + 0x659B, KANJI_SJIS_L2, // 斛 + 0x659F, KANJI_SJIS_L2, // 斟 + 0x65AB, KANJI_SJIS_L2, // 斫 + 0x65B7, KANJI_SJIS_L2, // 斷 + 0x65C3, KANJI_SJIS_L2, // 旃 + 0x65C6, KANJI_SJIS_L2, // 旆 + 0x65C1, KANJI_SJIS_L2, // 旁 + 0x65C4, KANJI_SJIS_L2, // 旄 + 0x65CC, KANJI_SJIS_L2, // 旌 + 0x65D2, KANJI_SJIS_L2, // 旒 + 0x65DB, KANJI_SJIS_L2, // 旛 + 0x65D9, KANJI_SJIS_L2, // 旙 + 0x65E0, KANJI_SJIS_L2, // 无 + 0x65E1, KANJI_SJIS_L2, // 旡 + 0x65F1, KANJI_SJIS_L2, // 旱 + 0x6772, KANJI_SJIS_L2, // 杲 + 0x660A, KANJI_SJIS_L2, // 昊 + 0x6603, KANJI_SJIS_L2, // 昃 + 0x65FB, KANJI_SJIS_L2, // 旻 + 0x6773, KANJI_SJIS_L2, // 杳 + 0x6635, KANJI_SJIS_L2, // 昵 + 0x6636, KANJI_SJIS_L2, // 昶 + 0x6634, KANJI_SJIS_L2, // 明 + 0x661C, KANJI_SJIS_L2, // 昜 + 0x664F, KANJI_SJIS_L2, // 晏 + 0x6644, KANJI_SJIS_L2, // 晄 + 0x6649, KANJI_SJIS_L2, // 晉 + 0x6641, KANJI_SJIS_L2, // 晁 + 0x665E, KANJI_SJIS_L2, // 晞 + 0x665D, KANJI_SJIS_L2, // 晝 + 0x6664, KANJI_SJIS_L2, // 晀 + 0x6667, KANJI_SJIS_L2, // 晧 + 0x6668, KANJI_SJIS_L2, // 晚 + 0x665F, KANJI_SJIS_L2, // 晟 + 0x6662, KANJI_SJIS_L2, // 晢 + 0x6670, KANJI_SJIS_L2, // 晰 + 0x6683, KANJI_SJIS_L2, // 暃 + 0x6688, KANJI_SJIS_L2, // 暈 + 0x668E, KANJI_SJIS_L2, // 暎 + 0x6689, KANJI_SJIS_L2, // 暉 + 0x6684, KANJI_SJIS_L2, // 暄 + 0x6698, KANJI_SJIS_L2, // 暘 + 0x669D, KANJI_SJIS_L2, // 暝 + 0x66C1, KANJI_SJIS_L2, // 曁 + 0x66B9, KANJI_SJIS_L2, // 暹 + 0x66C9, KANJI_SJIS_L2, // 曉 + 0x66BE, KANJI_SJIS_L2, // 暟 + 0x66BC, KANJI_SJIS_L2, // 暌 + 0x66C4, KANJI_SJIS_L2, // 曄 + 0x66B8, KANJI_SJIS_L2, // æšž + 0x66D6, KANJI_SJIS_L2, // 曖 + 0x66DA, KANJI_SJIS_L2, // 曚 + 0x66E0, KANJI_SJIS_L2, // 曠 + 0x663F, KANJI_SJIS_L2, // 昿 + 0x66E6, KANJI_SJIS_L2, // 曊 + 0x66E9, KANJI_SJIS_L2, // 曩 + 0x66F0, KANJI_SJIS_L2, // 曰 + 0x66F5, KANJI_SJIS_L2, // 曵 + 0x66F7, KANJI_SJIS_L2, // 曷 + 0x670F, KANJI_SJIS_L2, // 朏 + 0x6716, KANJI_SJIS_L2, // 朖 + 0x671E, KANJI_SJIS_L2, // 朞 + 0x6726, KANJI_SJIS_L2, // 朊 + 0x6727, KANJI_SJIS_L2, // 朧 + 0x9738, KANJI_SJIS_L2, // 霾 + 0x672E, KANJI_SJIS_L2, // 朮 + 0x673F, KANJI_SJIS_L2, // 朿 + 0x6736, KANJI_SJIS_L2, // 朶 + 0x6741, KANJI_SJIS_L2, // 杁 + 0x6738, KANJI_SJIS_L2, // 朞 + 0x6737, KANJI_SJIS_L2, // 朷 + 0x6746, KANJI_SJIS_L2, // 杆 + 0x675E, KANJI_SJIS_L2, // 杞 + 0x6760, KANJI_SJIS_L2, // 杠 + 0x6759, KANJI_SJIS_L2, // 杙 + 0x6763, KANJI_SJIS_L2, // 杣 + 0x6764, KANJI_SJIS_L2, // 杀 + 0x6789, KANJI_SJIS_L2, // 枉 + 0x6770, KANJI_SJIS_L2, // 杰 + 0x67A9, KANJI_SJIS_L2, // 枩 + 0x677C, KANJI_SJIS_L2, // 杌 + 0x676A, KANJI_SJIS_L2, // 杪 + 0x678C, KANJI_SJIS_L2, // 枌 + 0x678B, KANJI_SJIS_L2, // 枋 + 0x67A6, KANJI_SJIS_L2, // 枊 + 0x67A1, KANJI_SJIS_L2, // 枡 + 0x6785, KANJI_SJIS_L2, // 枅 + 0x67B7, KANJI_SJIS_L2, // 枷 + 0x67EF, KANJI_SJIS_L2, // 柯 + 0x67B4, KANJI_SJIS_L2, // 枎 + 0x67EC, KANJI_SJIS_L2, // 柬 + 0x67B3, KANJI_SJIS_L2, // 枳 + 0x67E9, KANJI_SJIS_L2, // 柩 + 0x67B8, KANJI_SJIS_L2, // æžž + 0x67E4, KANJI_SJIS_L2, // 柀 + 0x67DE, KANJI_SJIS_L2, // 柞 + 0x67DD, KANJI_SJIS_L2, // 柝 + 0x67E2, KANJI_SJIS_L2, // 柢 + 0x67EE, KANJI_SJIS_L2, // 柮 + 0x67B9, KANJI_SJIS_L2, // 枹 + 0x67CE, KANJI_SJIS_L2, // 柎 + 0x67C6, KANJI_SJIS_L2, // 柆 + 0x67E7, KANJI_SJIS_L2, // 柧 + 0x6A9C, KANJI_SJIS_L2, // 檜 + 0x681E, KANJI_SJIS_L2, // 栞 + 0x6846, KANJI_SJIS_L2, // 框 + 0x6829, KANJI_SJIS_L2, // æ © + 0x6840, KANJI_SJIS_L2, // 桀 + 0x684D, KANJI_SJIS_L2, // 桍 + 0x6832, KANJI_SJIS_L2, // æ ² + 0x684E, KANJI_SJIS_L2, // 桎 + 0x3000, KANJI_SJIS_L2, //   + 0x68B3, KANJI_SJIS_L2, // 梳 + 0x682B, KANJI_SJIS_L2, // æ « + 0x6859, KANJI_SJIS_L2, // 桙 + 0x6863, KANJI_SJIS_L2, // æ¡£ + 0x6877, KANJI_SJIS_L2, // æ¡· + 0x687F, KANJI_SJIS_L2, // æ¡¿ + 0x689F, KANJI_SJIS_L2, // 梟 + 0x688F, KANJI_SJIS_L2, // 梏 + 0x68AD, KANJI_SJIS_L2, // 梭 + 0x6894, KANJI_SJIS_L2, // 梔 + 0x689D, KANJI_SJIS_L2, // 條 + 0x689B, KANJI_SJIS_L2, // 梛 + 0x6883, KANJI_SJIS_L2, // 梃 + 0x6AAE, KANJI_SJIS_L2, // 檮 + 0x68B9, KANJI_SJIS_L2, // 梹 + 0x6874, KANJI_SJIS_L2, // 桎 + 0x68B5, KANJI_SJIS_L2, // 梵 + 0x68A0, KANJI_SJIS_L2, // 梠 + 0x68BA, KANJI_SJIS_L2, // 梺 + 0x690F, KANJI_SJIS_L2, // 怏 + 0x688D, KANJI_SJIS_L2, // 梍 + 0x687E, KANJI_SJIS_L2, // 桟 + 0x6901, KANJI_SJIS_L2, // 态 + 0x68CA, KANJI_SJIS_L2, // 棊 + 0x6908, KANJI_SJIS_L2, // 怈 + 0x68D8, KANJI_SJIS_L2, // 棘 + 0x6922, KANJI_SJIS_L2, // 怢 + 0x6926, KANJI_SJIS_L2, // 怊 + 0x68E1, KANJI_SJIS_L2, // 棡 + 0x690C, KANJI_SJIS_L2, // 怌 + 0x68CD, KANJI_SJIS_L2, // 棍 + 0x68D4, KANJI_SJIS_L2, // 棔 + 0x68E7, KANJI_SJIS_L2, // 棧 + 0x68D5, KANJI_SJIS_L2, // 棕 + 0x6936, KANJI_SJIS_L2, // 怶 + 0x6912, KANJI_SJIS_L2, // 怒 + 0x6904, KANJI_SJIS_L2, // 怄 + 0x68D7, KANJI_SJIS_L2, // 棗 + 0x68E3, KANJI_SJIS_L2, // 棣 + 0x6925, KANJI_SJIS_L2, // 急 + 0x68F9, KANJI_SJIS_L2, // 棹 + 0x68E0, KANJI_SJIS_L2, // 棠 + 0x68EF, KANJI_SJIS_L2, // 棯 + 0x6928, KANJI_SJIS_L2, // 怚 + 0x692A, KANJI_SJIS_L2, // 怪 + 0x691A, KANJI_SJIS_L2, // 怚 + 0x6923, KANJI_SJIS_L2, // 怣 + 0x6921, KANJI_SJIS_L2, // 怡 + 0x68C6, KANJI_SJIS_L2, // 棆 + 0x6979, KANJI_SJIS_L2, // 楹 + 0x6977, KANJI_SJIS_L2, // 楷 + 0x695C, KANJI_SJIS_L2, // 楜 + 0x6978, KANJI_SJIS_L2, // 楞 + 0x696B, KANJI_SJIS_L2, // 楫 + 0x6954, KANJI_SJIS_L2, // 楔 + 0x697E, KANJI_SJIS_L2, // 楟 + 0x696E, KANJI_SJIS_L2, // 楮 + 0x6939, KANJI_SJIS_L2, // 怹 + 0x6974, KANJI_SJIS_L2, // 楎 + 0x693D, KANJI_SJIS_L2, // 怜 + 0x6959, KANJI_SJIS_L2, // 楙 + 0x6930, KANJI_SJIS_L2, // 怰 + 0x6961, KANJI_SJIS_L2, // 楡 + 0x695E, KANJI_SJIS_L2, // 楞 + 0x695D, KANJI_SJIS_L2, // 楝 + 0x6981, KANJI_SJIS_L2, // 抁 + 0x696A, KANJI_SJIS_L2, // 楪 + 0x69B2, KANJI_SJIS_L2, // 抲 + 0x69AE, KANJI_SJIS_L2, // 抮 + 0x69D0, KANJI_SJIS_L2, // 槐 + 0x69BF, KANJI_SJIS_L2, // 抿 + 0x69C1, KANJI_SJIS_L2, // 槁 + 0x69D3, KANJI_SJIS_L2, // 槓 + 0x69BE, KANJI_SJIS_L2, // 抟 + 0x69CE, KANJI_SJIS_L2, // 槎 + 0x5BE8, KANJI_SJIS_L2, // 寚 + 0x69CA, KANJI_SJIS_L2, // 槊 + 0x69DD, KANJI_SJIS_L2, // 槝 + 0x69BB, KANJI_SJIS_L2, // 抻 + 0x69C3, KANJI_SJIS_L2, // 槃 + 0x69A7, KANJI_SJIS_L2, // 抧 + 0x6A2E, KANJI_SJIS_L2, // æš® + 0x6991, KANJI_SJIS_L2, // 抑 + 0x69A0, KANJI_SJIS_L2, // 抠 + 0x699C, KANJI_SJIS_L2, // 抜 + 0x6995, KANJI_SJIS_L2, // 投 + 0x69B4, KANJI_SJIS_L2, // 抎 + 0x69DE, KANJI_SJIS_L2, // 槞 + 0x69E8, KANJI_SJIS_L2, // æ§š + 0x6A02, KANJI_SJIS_L2, // æš‚ + 0x6A1B, KANJI_SJIS_L2, // æš› + 0x69FF, KANJI_SJIS_L2, // æ§¿ + 0x6B0A, KANJI_SJIS_L2, // 權 + 0x69F9, KANJI_SJIS_L2, // æ§¹ + 0x69F2, KANJI_SJIS_L2, // æ§² + 0x69E7, KANJI_SJIS_L2, // æ§§ + 0x6A05, KANJI_SJIS_L2, // æš… + 0x69B1, KANJI_SJIS_L2, // 抱 + 0x6A1E, KANJI_SJIS_L2, // 暞 + 0x69ED, KANJI_SJIS_L2, // æ§­ + 0x6A14, KANJI_SJIS_L2, // æš” + 0x69EB, KANJI_SJIS_L2, // æ§« + 0x6A0A, KANJI_SJIS_L2, // 暊 + 0x6A12, KANJI_SJIS_L2, // æš’ + 0x6AC1, KANJI_SJIS_L2, // 櫁 + 0x6A23, KANJI_SJIS_L2, // 暣 + 0x6A13, KANJI_SJIS_L2, // æš“ + 0x6A44, KANJI_SJIS_L2, // 橄 + 0x6A0C, KANJI_SJIS_L2, // 暌 + 0x6A72, KANJI_SJIS_L2, // 橲 + 0x6A36, KANJI_SJIS_L2, // æš¶ + 0x6A78, KANJI_SJIS_L2, // 橞 + 0x6A47, KANJI_SJIS_L2, // 橇 + 0x6A62, KANJI_SJIS_L2, // æ©¢ + 0x6A59, KANJI_SJIS_L2, // 橙 + 0x6A66, KANJI_SJIS_L2, // 橊 + 0x6A48, KANJI_SJIS_L2, // 橈 + 0x6A38, KANJI_SJIS_L2, // æšž + 0x6A22, KANJI_SJIS_L2, // 暢 + 0x6A90, KANJI_SJIS_L2, // 檐 + 0x6A8D, KANJI_SJIS_L2, // 檍 + 0x6AA0, KANJI_SJIS_L2, // 檠 + 0x6A84, KANJI_SJIS_L2, // 檄 + 0x6AA2, KANJI_SJIS_L2, // 檢 + 0x6AA3, KANJI_SJIS_L2, // 檣 + 0x6A97, KANJI_SJIS_L2, // 檗 + 0x8617, KANJI_SJIS_L2, // 蘗 + 0x6ABB, KANJI_SJIS_L2, // 檻 + 0x6AC3, KANJI_SJIS_L2, // 櫃 + 0x6AC2, KANJI_SJIS_L2, // 櫂 + 0x6AB8, KANJI_SJIS_L2, // 檞 + 0x6AB3, KANJI_SJIS_L2, // 檳 + 0x6AAC, KANJI_SJIS_L2, // 檬 + 0x6ADE, KANJI_SJIS_L2, // 櫞 + 0x6AD1, KANJI_SJIS_L2, // 櫑 + 0x6ADF, KANJI_SJIS_L2, // 櫟 + 0x6AAA, KANJI_SJIS_L2, // 檪 + 0x6ADA, KANJI_SJIS_L2, // 櫚 + 0x6AEA, KANJI_SJIS_L2, // 櫪 + 0x6AFB, KANJI_SJIS_L2, // æ«» + 0x6B05, KANJI_SJIS_L2, // 欅 + 0x8616, KANJI_SJIS_L2, // 蘖 + 0x6AFA, KANJI_SJIS_L2, // 櫺 + 0x6B12, KANJI_SJIS_L2, // 欒 + 0x6B16, KANJI_SJIS_L2, // 欖 + 0x9B31, KANJI_SJIS_L2, // 鬱 + 0x6B1F, KANJI_SJIS_L2, // 欟 + 0x6B38, KANJI_SJIS_L2, // 欞 + 0x6B37, KANJI_SJIS_L2, // 欷 + 0x76DC, KANJI_SJIS_L2, // 盜 + 0x6B39, KANJI_SJIS_L2, // 欹 + 0x98EE, KANJI_SJIS_L2, // 飮 + 0x6B47, KANJI_SJIS_L2, // 歇 + 0x6B43, KANJI_SJIS_L2, // 歃 + 0x6B49, KANJI_SJIS_L2, // 歉 + 0x6B50, KANJI_SJIS_L2, // 歐 + 0x6B59, KANJI_SJIS_L2, // 歙 + 0x6B54, KANJI_SJIS_L2, // 歔 + 0x6B5B, KANJI_SJIS_L2, // 歛 + 0x6B5F, KANJI_SJIS_L2, // 歟 + 0x6B61, KANJI_SJIS_L2, // æ­¡ + 0x6B78, KANJI_SJIS_L2, // æ­ž + 0x6B79, KANJI_SJIS_L2, // æ­¹ + 0x6B7F, KANJI_SJIS_L2, // æ­¿ + 0x6B80, KANJI_SJIS_L2, // 殀 + 0x6B84, KANJI_SJIS_L2, // 殄 + 0x6B83, KANJI_SJIS_L2, // 殃 + 0x6B8D, KANJI_SJIS_L2, // 殍 + 0x6B98, KANJI_SJIS_L2, // 殘 + 0x6B95, KANJI_SJIS_L2, // 殕 + 0x6B9E, KANJI_SJIS_L2, // 殞 + 0x6BA4, KANJI_SJIS_L2, // 殀 + 0x6BAA, KANJI_SJIS_L2, // 殪 + 0x6BAB, KANJI_SJIS_L2, // 殫 + 0x6BAF, KANJI_SJIS_L2, // 殯 + 0x6BB2, KANJI_SJIS_L2, // 殲 + 0x6BB1, KANJI_SJIS_L2, // æ®± + 0x6BB3, KANJI_SJIS_L2, // 殳 + 0x6BB7, KANJI_SJIS_L2, // æ®· + 0x6BBC, KANJI_SJIS_L2, // 殌 + 0x6BC6, KANJI_SJIS_L2, // 毆 + 0x6BCB, KANJI_SJIS_L2, // 毋 + 0x6BD3, KANJI_SJIS_L2, // 毓 + 0x6BDF, KANJI_SJIS_L2, // 毟 + 0x6BEC, KANJI_SJIS_L2, // 毬 + 0x6BEB, KANJI_SJIS_L2, // 毫 + 0x6BF3, KANJI_SJIS_L2, // 毳 + 0x6BEF, KANJI_SJIS_L2, // 毯 + 0x3000, KANJI_SJIS_L2, //   + 0x9EBE, KANJI_SJIS_L2, // 麟 + 0x6C08, KANJI_SJIS_L2, // 氈 + 0x6C13, KANJI_SJIS_L2, // 氓 + 0x6C14, KANJI_SJIS_L2, // 气 + 0x6C1B, KANJI_SJIS_L2, // 氛 + 0x6C24, KANJI_SJIS_L2, // æ°€ + 0x6C23, KANJI_SJIS_L2, // æ°£ + 0x6C5E, KANJI_SJIS_L2, // 汞 + 0x6C55, KANJI_SJIS_L2, // 汕 + 0x6C62, KANJI_SJIS_L2, // æ±¢ + 0x6C6A, KANJI_SJIS_L2, // 汪 + 0x6C82, KANJI_SJIS_L2, // 沂 + 0x6C8D, KANJI_SJIS_L2, // 沍 + 0x6C9A, KANJI_SJIS_L2, // 沚 + 0x6C81, KANJI_SJIS_L2, // 沁 + 0x6C9B, KANJI_SJIS_L2, // 沛 + 0x6C7E, KANJI_SJIS_L2, // 江 + 0x6C68, KANJI_SJIS_L2, // 汚 + 0x6C73, KANJI_SJIS_L2, // æ±³ + 0x6C92, KANJI_SJIS_L2, // 沒 + 0x6C90, KANJI_SJIS_L2, // 沐 + 0x6CC4, KANJI_SJIS_L2, // 泄 + 0x6CF1, KANJI_SJIS_L2, // æ³± + 0x6CD3, KANJI_SJIS_L2, // 泓 + 0x6CBD, KANJI_SJIS_L2, // 沜 + 0x6CD7, KANJI_SJIS_L2, // 泗 + 0x6CC5, KANJI_SJIS_L2, // 泅 + 0x6CDD, KANJI_SJIS_L2, // 泝 + 0x6CAE, KANJI_SJIS_L2, // æ²® + 0x6CB1, KANJI_SJIS_L2, // æ²± + 0x6CBE, KANJI_SJIS_L2, // 沟 + 0x6CBA, KANJI_SJIS_L2, // 沺 + 0x6CDB, KANJI_SJIS_L2, // 泛 + 0x6CEF, KANJI_SJIS_L2, // 泯 + 0x6CD9, KANJI_SJIS_L2, // 泙 + 0x6CEA, KANJI_SJIS_L2, // 泪 + 0x6D1F, KANJI_SJIS_L2, // 掟 + 0x884D, KANJI_SJIS_L2, // 衍 + 0x6D36, KANJI_SJIS_L2, // 掶 + 0x6D2B, KANJI_SJIS_L2, // 掫 + 0x6D3D, KANJI_SJIS_L2, // 掜 + 0x6D38, KANJI_SJIS_L2, // 掞 + 0x6D19, KANJI_SJIS_L2, // 掙 + 0x6D35, KANJI_SJIS_L2, // 掵 + 0x6D33, KANJI_SJIS_L2, // 掳 + 0x6D12, KANJI_SJIS_L2, // 排 + 0x6D0C, KANJI_SJIS_L2, // 掌 + 0x6D63, KANJI_SJIS_L2, // æµ£ + 0x6D93, KANJI_SJIS_L2, // 涓 + 0x6D64, KANJI_SJIS_L2, // æµ€ + 0x6D5A, KANJI_SJIS_L2, // 浚 + 0x6D79, KANJI_SJIS_L2, // æµ¹ + 0x6D59, KANJI_SJIS_L2, // 浙 + 0x6D8E, KANJI_SJIS_L2, // 涎 + 0x6D95, KANJI_SJIS_L2, // 涕 + 0x6FE4, KANJI_SJIS_L2, // æ¿€ + 0x6D85, KANJI_SJIS_L2, // 涅 + 0x6DF9, KANJI_SJIS_L2, // æ·¹ + 0x6E15, KANJI_SJIS_L2, // æž• + 0x6E0A, KANJI_SJIS_L2, // 枊 + 0x6DB5, KANJI_SJIS_L2, // æ¶µ + 0x6DC7, KANJI_SJIS_L2, // 淇 + 0x6DE6, KANJI_SJIS_L2, // æ·Š + 0x6DB8, KANJI_SJIS_L2, // æ¶ž + 0x6DC6, KANJI_SJIS_L2, // 淆 + 0x6DEC, KANJI_SJIS_L2, // æ·¬ + 0x6DDE, KANJI_SJIS_L2, // 淞 + 0x6DCC, KANJI_SJIS_L2, // 淌 + 0x6DE8, KANJI_SJIS_L2, // æ·š + 0x6DD2, KANJI_SJIS_L2, // 淒 + 0x6DC5, KANJI_SJIS_L2, // 淅 + 0x6DFA, KANJI_SJIS_L2, // æ·º + 0x6DD9, KANJI_SJIS_L2, // 淙 + 0x6DE4, KANJI_SJIS_L2, // æ·€ + 0x6DD5, KANJI_SJIS_L2, // 淕 + 0x6DEA, KANJI_SJIS_L2, // æ·ª + 0x6DEE, KANJI_SJIS_L2, // æ·® + 0x6E2D, KANJI_SJIS_L2, // æž­ + 0x6E6E, KANJI_SJIS_L2, // æ¹® + 0x6E2E, KANJI_SJIS_L2, // æž® + 0x6E19, KANJI_SJIS_L2, // æž™ + 0x6E72, KANJI_SJIS_L2, // æ¹² + 0x6E5F, KANJI_SJIS_L2, // 湟 + 0x6E3E, KANJI_SJIS_L2, // 枟 + 0x6E23, KANJI_SJIS_L2, // 枣 + 0x6E6B, KANJI_SJIS_L2, // 湫 + 0x6E2B, KANJI_SJIS_L2, // æž« + 0x6E76, KANJI_SJIS_L2, // æ¹¶ + 0x6E4D, KANJI_SJIS_L2, // 湍 + 0x6E1F, KANJI_SJIS_L2, // 枟 + 0x6E43, KANJI_SJIS_L2, // 湃 + 0x6E3A, KANJI_SJIS_L2, // 枺 + 0x6E4E, KANJI_SJIS_L2, // 湎 + 0x6E24, KANJI_SJIS_L2, // 枀 + 0x6EFF, KANJI_SJIS_L2, // 滿 + 0x6E1D, KANJI_SJIS_L2, // 枝 + 0x6E38, KANJI_SJIS_L2, // æžž + 0x6E82, KANJI_SJIS_L2, // 溂 + 0x6EAA, KANJI_SJIS_L2, // 溪 + 0x6E98, KANJI_SJIS_L2, // 溘 + 0x6EC9, KANJI_SJIS_L2, // 滉 + 0x6EB7, KANJI_SJIS_L2, // 溷 + 0x6ED3, KANJI_SJIS_L2, // 滓 + 0x6EBD, KANJI_SJIS_L2, // 溜 + 0x6EAF, KANJI_SJIS_L2, // 溯 + 0x6EC4, KANJI_SJIS_L2, // 滄 + 0x6EB2, KANJI_SJIS_L2, // 溲 + 0x6ED4, KANJI_SJIS_L2, // 滔 + 0x6ED5, KANJI_SJIS_L2, // 滕 + 0x6E8F, KANJI_SJIS_L2, // 溏 + 0x6EA5, KANJI_SJIS_L2, // 溥 + 0x6EC2, KANJI_SJIS_L2, // 滂 + 0x6E9F, KANJI_SJIS_L2, // 溟 + 0x6F41, KANJI_SJIS_L2, // 朁 + 0x6F11, KANJI_SJIS_L2, // 挑 + 0x704C, KANJI_SJIS_L2, // 灌 + 0x6EEC, KANJI_SJIS_L2, // 滬 + 0x6EF8, KANJI_SJIS_L2, // 滞 + 0x6EFE, KANJI_SJIS_L2, // 滟 + 0x6F3F, KANJI_SJIS_L2, // 挿 + 0x6EF2, KANJI_SJIS_L2, // 滲 + 0x6F31, KANJI_SJIS_L2, // 挱 + 0x6EEF, KANJI_SJIS_L2, // 滯 + 0x6F32, KANJI_SJIS_L2, // 挲 + 0x6ECC, KANJI_SJIS_L2, // 滌 + 0x6F3E, KANJI_SJIS_L2, // 挟 + 0x6F13, KANJI_SJIS_L2, // 挓 + 0x6EF7, KANJI_SJIS_L2, // æ»· + 0x6F86, KANJI_SJIS_L2, // 柆 + 0x6F7A, KANJI_SJIS_L2, // 机 + 0x6F78, KANJI_SJIS_L2, // 朞 + 0x6F81, KANJI_SJIS_L2, // 柁 + 0x6F80, KANJI_SJIS_L2, // 柀 + 0x6F6F, KANJI_SJIS_L2, // 术 + 0x6F5B, KANJI_SJIS_L2, // 望 + 0x6FF3, KANJI_SJIS_L2, // 濳 + 0x6F6D, KANJI_SJIS_L2, // 札 + 0x6F82, KANJI_SJIS_L2, // 柂 + 0x6F7C, KANJI_SJIS_L2, // 朌 + 0x6F58, KANJI_SJIS_L2, // 朘 + 0x6F8E, KANJI_SJIS_L2, // 柎 + 0x6F91, KANJI_SJIS_L2, // 柑 + 0x6FC2, KANJI_SJIS_L2, // 濂 + 0x6F66, KANJI_SJIS_L2, // 朊 + 0x6FB3, KANJI_SJIS_L2, // 柳 + 0x6FA3, KANJI_SJIS_L2, // 柣 + 0x6FA1, KANJI_SJIS_L2, // 柡 + 0x6FA4, KANJI_SJIS_L2, // 柀 + 0x6FB9, KANJI_SJIS_L2, // 柹 + 0x6FC6, KANJI_SJIS_L2, // 濆 + 0x6FAA, KANJI_SJIS_L2, // 柪 + 0x6FDF, KANJI_SJIS_L2, // 濟 + 0x6FD5, KANJI_SJIS_L2, // 濕 + 0x6FEC, KANJI_SJIS_L2, // 濬 + 0x6FD4, KANJI_SJIS_L2, // 濔 + 0x6FD8, KANJI_SJIS_L2, // 濘 + 0x6FF1, KANJI_SJIS_L2, // 濱 + 0x6FEE, KANJI_SJIS_L2, // æ¿® + 0x6FDB, KANJI_SJIS_L2, // 濛 + 0x7009, KANJI_SJIS_L2, // 瀉 + 0x700B, KANJI_SJIS_L2, // 瀋 + 0x6FFA, KANJI_SJIS_L2, // 濺 + 0x7011, KANJI_SJIS_L2, // 瀑 + 0x7001, KANJI_SJIS_L2, // 瀁 + 0x700F, KANJI_SJIS_L2, // 瀏 + 0x6FFE, KANJI_SJIS_L2, // 濟 + 0x701B, KANJI_SJIS_L2, // 瀛 + 0x701A, KANJI_SJIS_L2, // 瀚 + 0x6F74, KANJI_SJIS_L2, // 朎 + 0x701D, KANJI_SJIS_L2, // 瀝 + 0x7018, KANJI_SJIS_L2, // 瀘 + 0x701F, KANJI_SJIS_L2, // 瀟 + 0x7030, KANJI_SJIS_L2, // 瀰 + 0x703E, KANJI_SJIS_L2, // 瀟 + 0x7032, KANJI_SJIS_L2, // 瀲 + 0x7051, KANJI_SJIS_L2, // 灑 + 0x7063, KANJI_SJIS_L2, // 灣 + 0x7099, KANJI_SJIS_L2, // 炙 + 0x7092, KANJI_SJIS_L2, // 炒 + 0x70AF, KANJI_SJIS_L2, // 炯 + 0x70F1, KANJI_SJIS_L2, // 烱 + 0x70AC, KANJI_SJIS_L2, // 炬 + 0x70B8, KANJI_SJIS_L2, // 炾 + 0x70B3, KANJI_SJIS_L2, // 炳 + 0x70AE, KANJI_SJIS_L2, // 炮 + 0x70DF, KANJI_SJIS_L2, // 烟 + 0x70CB, KANJI_SJIS_L2, // 烋 + 0x70DD, KANJI_SJIS_L2, // 烝 + 0x3000, KANJI_SJIS_L2, //   + 0x70D9, KANJI_SJIS_L2, // 烙 + 0x7109, KANJI_SJIS_L2, // 焉 + 0x70FD, KANJI_SJIS_L2, // 烜 + 0x711C, KANJI_SJIS_L2, // 焜 + 0x7119, KANJI_SJIS_L2, // 焙 + 0x7165, KANJI_SJIS_L2, // 煥 + 0x7155, KANJI_SJIS_L2, // 煕 + 0x7188, KANJI_SJIS_L2, // 熈 + 0x7166, KANJI_SJIS_L2, // 煩 + 0x7162, KANJI_SJIS_L2, // 煢 + 0x714C, KANJI_SJIS_L2, // 煌 + 0x7156, KANJI_SJIS_L2, // 煖 + 0x716C, KANJI_SJIS_L2, // 煬 + 0x718F, KANJI_SJIS_L2, // 熏 + 0x71FB, KANJI_SJIS_L2, // 燻 + 0x7184, KANJI_SJIS_L2, // 熄 + 0x7195, KANJI_SJIS_L2, // 熕 + 0x71A8, KANJI_SJIS_L2, // 熹 + 0x71AC, KANJI_SJIS_L2, // 熬 + 0x71D7, KANJI_SJIS_L2, // 燗 + 0x71B9, KANJI_SJIS_L2, // 熹 + 0x71BE, KANJI_SJIS_L2, // 熟 + 0x71D2, KANJI_SJIS_L2, // 燒 + 0x71C9, KANJI_SJIS_L2, // 燉 + 0x71D4, KANJI_SJIS_L2, // 燔 + 0x71CE, KANJI_SJIS_L2, // 燎 + 0x71E0, KANJI_SJIS_L2, // 燠 + 0x71EC, KANJI_SJIS_L2, // 燬 + 0x71E7, KANJI_SJIS_L2, // 燧 + 0x71F5, KANJI_SJIS_L2, // 燵 + 0x71FC, KANJI_SJIS_L2, // 燌 + 0x71F9, KANJI_SJIS_L2, // 燹 + 0x71FF, KANJI_SJIS_L2, // 燿 + 0x720D, KANJI_SJIS_L2, // 爍 + 0x7210, KANJI_SJIS_L2, // 爐 + 0x721B, KANJI_SJIS_L2, // 爛 + 0x7228, KANJI_SJIS_L2, // 爚 + 0x722D, KANJI_SJIS_L2, // 爭 + 0x722C, KANJI_SJIS_L2, // 爬 + 0x7230, KANJI_SJIS_L2, // 爰 + 0x7232, KANJI_SJIS_L2, // 爲 + 0x723B, KANJI_SJIS_L2, // 爻 + 0x723C, KANJI_SJIS_L2, // 爌 + 0x723F, KANJI_SJIS_L2, // 爿 + 0x7240, KANJI_SJIS_L2, // 牀 + 0x7246, KANJI_SJIS_L2, // 牆 + 0x724B, KANJI_SJIS_L2, // 牋 + 0x7258, KANJI_SJIS_L2, // 牘 + 0x7274, KANJI_SJIS_L2, // 牮 + 0x727E, KANJI_SJIS_L2, // 牟 + 0x7282, KANJI_SJIS_L2, // 犂 + 0x7281, KANJI_SJIS_L2, // 犁 + 0x7287, KANJI_SJIS_L2, // 犇 + 0x7292, KANJI_SJIS_L2, // 犒 + 0x7296, KANJI_SJIS_L2, // 犖 + 0x72A2, KANJI_SJIS_L2, // 犢 + 0x72A7, KANJI_SJIS_L2, // 犧 + 0x72B9, KANJI_SJIS_L2, // 犹 + 0x72B2, KANJI_SJIS_L2, // 犲 + 0x72C3, KANJI_SJIS_L2, // 狃 + 0x72C6, KANJI_SJIS_L2, // 狆 + 0x72C4, KANJI_SJIS_L2, // 狄 + 0x72CE, KANJI_SJIS_L2, // 狎 + 0x72D2, KANJI_SJIS_L2, // 狒 + 0x72E2, KANJI_SJIS_L2, // 狢 + 0x72E0, KANJI_SJIS_L2, // 狠 + 0x72E1, KANJI_SJIS_L2, // 狡 + 0x72F9, KANJI_SJIS_L2, // 狹 + 0x72F7, KANJI_SJIS_L2, // 狷 + 0x500F, KANJI_SJIS_L2, // 倏 + 0x7317, KANJI_SJIS_L2, // 猗 + 0x730A, KANJI_SJIS_L2, // 猊 + 0x731C, KANJI_SJIS_L2, // 猜 + 0x7316, KANJI_SJIS_L2, // 猖 + 0x731D, KANJI_SJIS_L2, // 猝 + 0x7334, KANJI_SJIS_L2, // 献 + 0x732F, KANJI_SJIS_L2, // 猯 + 0x7329, KANJI_SJIS_L2, // 猩 + 0x7325, KANJI_SJIS_L2, // 猥 + 0x733E, KANJI_SJIS_L2, // 猟 + 0x734E, KANJI_SJIS_L2, // 獎 + 0x734F, KANJI_SJIS_L2, // 獏 + 0x9ED8, KANJI_SJIS_L2, // 默 + 0x7357, KANJI_SJIS_L2, // 獗 + 0x736A, KANJI_SJIS_L2, // 獪 + 0x7368, KANJI_SJIS_L2, // 獚 + 0x7370, KANJI_SJIS_L2, // 獰 + 0x7378, KANJI_SJIS_L2, // 獞 + 0x7375, KANJI_SJIS_L2, // 獵 + 0x737B, KANJI_SJIS_L2, // 獻 + 0x737A, KANJI_SJIS_L2, // 獺 + 0x73C8, KANJI_SJIS_L2, // 珈 + 0x73B3, KANJI_SJIS_L2, // 玳 + 0x73CE, KANJI_SJIS_L2, // 珎 + 0x73BB, KANJI_SJIS_L2, // 玻 + 0x73C0, KANJI_SJIS_L2, // 珀 + 0x73E5, KANJI_SJIS_L2, // 珥 + 0x73EE, KANJI_SJIS_L2, // 珮 + 0x73DE, KANJI_SJIS_L2, // 珞 + 0x74A2, KANJI_SJIS_L2, // 璢 + 0x7405, KANJI_SJIS_L2, // 琅 + 0x746F, KANJI_SJIS_L2, // 瑯 + 0x7425, KANJI_SJIS_L2, // 琥 + 0x73F8, KANJI_SJIS_L2, // 珞 + 0x7432, KANJI_SJIS_L2, // 琲 + 0x743A, KANJI_SJIS_L2, // 琺 + 0x7455, KANJI_SJIS_L2, // 瑕 + 0x743F, KANJI_SJIS_L2, // 琿 + 0x745F, KANJI_SJIS_L2, // 瑟 + 0x7459, KANJI_SJIS_L2, // 瑙 + 0x7441, KANJI_SJIS_L2, // 瑁 + 0x745C, KANJI_SJIS_L2, // 瑜 + 0x7469, KANJI_SJIS_L2, // 瑩 + 0x7470, KANJI_SJIS_L2, // 瑰 + 0x7463, KANJI_SJIS_L2, // 瑣 + 0x746A, KANJI_SJIS_L2, // 瑪 + 0x7476, KANJI_SJIS_L2, // 瑶 + 0x747E, KANJI_SJIS_L2, // 瑟 + 0x748B, KANJI_SJIS_L2, // 璋 + 0x749E, KANJI_SJIS_L2, // 璞 + 0x74A7, KANJI_SJIS_L2, // 璧 + 0x74CA, KANJI_SJIS_L2, // 瓊 + 0x74CF, KANJI_SJIS_L2, // 瓏 + 0x74D4, KANJI_SJIS_L2, // 瓔 + 0x73F1, KANJI_SJIS_L2, // 珱 + 0x74E0, KANJI_SJIS_L2, // 瓠 + 0x74E3, KANJI_SJIS_L2, // 瓣 + 0x74E7, KANJI_SJIS_L2, // 瓧 + 0x74E9, KANJI_SJIS_L2, // 瓩 + 0x74EE, KANJI_SJIS_L2, // 瓮 + 0x74F2, KANJI_SJIS_L2, // 瓲 + 0x74F0, KANJI_SJIS_L2, // 瓰 + 0x74F1, KANJI_SJIS_L2, // 瓱 + 0x74F8, KANJI_SJIS_L2, // 瓾 + 0x74F7, KANJI_SJIS_L2, // 瓷 + 0x7504, KANJI_SJIS_L2, // 甄 + 0x7503, KANJI_SJIS_L2, // 甃 + 0x7505, KANJI_SJIS_L2, // 甅 + 0x750C, KANJI_SJIS_L2, // 甌 + 0x750E, KANJI_SJIS_L2, // 甎 + 0x750D, KANJI_SJIS_L2, // 甍 + 0x7515, KANJI_SJIS_L2, // 甕 + 0x7513, KANJI_SJIS_L2, // 甓 + 0x751E, KANJI_SJIS_L2, // 甞 + 0x7526, KANJI_SJIS_L2, // 甩 + 0x752C, KANJI_SJIS_L2, // 甬 + 0x753C, KANJI_SJIS_L2, // 甌 + 0x7544, KANJI_SJIS_L2, // 畄 + 0x754D, KANJI_SJIS_L2, // 畍 + 0x754A, KANJI_SJIS_L2, // 畊 + 0x7549, KANJI_SJIS_L2, // 畉 + 0x755B, KANJI_SJIS_L2, // 畛 + 0x7546, KANJI_SJIS_L2, // 畆 + 0x755A, KANJI_SJIS_L2, // 畚 + 0x7569, KANJI_SJIS_L2, // 畩 + 0x7564, KANJI_SJIS_L2, // ç•€ + 0x7567, KANJI_SJIS_L2, // 畧 + 0x756B, KANJI_SJIS_L2, // 畫 + 0x756D, KANJI_SJIS_L2, // 畭 + 0x7578, KANJI_SJIS_L2, // 畾 + 0x7576, KANJI_SJIS_L2, // 當 + 0x7586, KANJI_SJIS_L2, // 疆 + 0x7587, KANJI_SJIS_L2, // 疇 + 0x7574, KANJI_SJIS_L2, // 畮 + 0x758A, KANJI_SJIS_L2, // 疊 + 0x7589, KANJI_SJIS_L2, // 疉 + 0x7582, KANJI_SJIS_L2, // 疂 + 0x7594, KANJI_SJIS_L2, // 疔 + 0x759A, KANJI_SJIS_L2, // 疚 + 0x759D, KANJI_SJIS_L2, // 疝 + 0x75A5, KANJI_SJIS_L2, // 疥 + 0x75A3, KANJI_SJIS_L2, // 疣 + 0x75C2, KANJI_SJIS_L2, // 痂 + 0x75B3, KANJI_SJIS_L2, // 疳 + 0x75C3, KANJI_SJIS_L2, // 痃 + 0x75B5, KANJI_SJIS_L2, // 疵 + 0x75BD, KANJI_SJIS_L2, // ç–œ + 0x75B8, KANJI_SJIS_L2, // 疾 + 0x75BC, KANJI_SJIS_L2, // ç–Œ + 0x75B1, KANJI_SJIS_L2, // 疱 + 0x75CD, KANJI_SJIS_L2, // 痍 + 0x75CA, KANJI_SJIS_L2, // 痊 + 0x75D2, KANJI_SJIS_L2, // 痒 + 0x75D9, KANJI_SJIS_L2, // 痙 + 0x75E3, KANJI_SJIS_L2, // 痣 + 0x75DE, KANJI_SJIS_L2, // 痞 + 0x75FE, KANJI_SJIS_L2, // ç—Ÿ + 0x75FF, KANJI_SJIS_L2, // 痿 + 0x3000, KANJI_SJIS_L2, //   + 0x75FC, KANJI_SJIS_L2, // ç—Œ + 0x7601, KANJI_SJIS_L2, // 瘁 + 0x75F0, KANJI_SJIS_L2, // 痰 + 0x75FA, KANJI_SJIS_L2, // 痺 + 0x75F2, KANJI_SJIS_L2, // 痲 + 0x75F3, KANJI_SJIS_L2, // 痳 + 0x760B, KANJI_SJIS_L2, // 瘋 + 0x760D, KANJI_SJIS_L2, // 瘍 + 0x7609, KANJI_SJIS_L2, // 瘉 + 0x761F, KANJI_SJIS_L2, // 瘟 + 0x7627, KANJI_SJIS_L2, // 瘧 + 0x7620, KANJI_SJIS_L2, // 瘠 + 0x7621, KANJI_SJIS_L2, // 瘡 + 0x7622, KANJI_SJIS_L2, // 瘢 + 0x7624, KANJI_SJIS_L2, // 瘀 + 0x7634, KANJI_SJIS_L2, // 瘎 + 0x7630, KANJI_SJIS_L2, // 瘰 + 0x763B, KANJI_SJIS_L2, // 瘻 + 0x7647, KANJI_SJIS_L2, // 癇 + 0x7648, KANJI_SJIS_L2, // 癈 + 0x7646, KANJI_SJIS_L2, // 癆 + 0x765C, KANJI_SJIS_L2, // 癜 + 0x7658, KANJI_SJIS_L2, // 癘 + 0x7661, KANJI_SJIS_L2, // 癡 + 0x7662, KANJI_SJIS_L2, // 癢 + 0x7668, KANJI_SJIS_L2, // 癹 + 0x7669, KANJI_SJIS_L2, // 癩 + 0x766A, KANJI_SJIS_L2, // 癪 + 0x7667, KANJI_SJIS_L2, // 癧 + 0x766C, KANJI_SJIS_L2, // 癬 + 0x7670, KANJI_SJIS_L2, // 癰 + 0x7672, KANJI_SJIS_L2, // 癲 + 0x7676, KANJI_SJIS_L2, // 癶 + 0x7678, KANJI_SJIS_L2, // 百 + 0x767C, KANJI_SJIS_L2, // 癌 + 0x7680, KANJI_SJIS_L2, // 皀 + 0x7683, KANJI_SJIS_L2, // 皃 + 0x7688, KANJI_SJIS_L2, // 皈 + 0x768B, KANJI_SJIS_L2, // 皋 + 0x768E, KANJI_SJIS_L2, // 皎 + 0x7696, KANJI_SJIS_L2, // 皖 + 0x7693, KANJI_SJIS_L2, // 皓 + 0x7699, KANJI_SJIS_L2, // 皙 + 0x769A, KANJI_SJIS_L2, // 皚 + 0x76B0, KANJI_SJIS_L2, // 皰 + 0x76B4, KANJI_SJIS_L2, // 皮 + 0x76B8, KANJI_SJIS_L2, // 皾 + 0x76B9, KANJI_SJIS_L2, // 皹 + 0x76BA, KANJI_SJIS_L2, // 皺 + 0x76C2, KANJI_SJIS_L2, // 盂 + 0x76CD, KANJI_SJIS_L2, // 盍 + 0x76D6, KANJI_SJIS_L2, // 盖 + 0x76D2, KANJI_SJIS_L2, // 盒 + 0x76DE, KANJI_SJIS_L2, // 盞 + 0x76E1, KANJI_SJIS_L2, // 盡 + 0x76E5, KANJI_SJIS_L2, // 盥 + 0x76E7, KANJI_SJIS_L2, // 盧 + 0x76EA, KANJI_SJIS_L2, // 盪 + 0x862F, KANJI_SJIS_L2, // 蘯 + 0x76FB, KANJI_SJIS_L2, // 盻 + 0x7708, KANJI_SJIS_L2, // 眈 + 0x7707, KANJI_SJIS_L2, // 眇 + 0x7704, KANJI_SJIS_L2, // 眄 + 0x7729, KANJI_SJIS_L2, // 眩 + 0x7724, KANJI_SJIS_L2, // 眀 + 0x771E, KANJI_SJIS_L2, // 眞 + 0x7725, KANJI_SJIS_L2, // 眥 + 0x7726, KANJI_SJIS_L2, // 眩 + 0x771B, KANJI_SJIS_L2, // 眛 + 0x7737, KANJI_SJIS_L2, // 眷 + 0x7738, KANJI_SJIS_L2, // 眾 + 0x7747, KANJI_SJIS_L2, // 睇 + 0x775A, KANJI_SJIS_L2, // 睚 + 0x7768, KANJI_SJIS_L2, // 睚 + 0x776B, KANJI_SJIS_L2, // 睫 + 0x775B, KANJI_SJIS_L2, // 睛 + 0x7765, KANJI_SJIS_L2, // 睥 + 0x777F, KANJI_SJIS_L2, // 睿 + 0x777E, KANJI_SJIS_L2, // 睟 + 0x7779, KANJI_SJIS_L2, // 睹 + 0x778E, KANJI_SJIS_L2, // 瞎 + 0x778B, KANJI_SJIS_L2, // 瞋 + 0x7791, KANJI_SJIS_L2, // 瞑 + 0x77A0, KANJI_SJIS_L2, // 瞠 + 0x779E, KANJI_SJIS_L2, // 瞞 + 0x77B0, KANJI_SJIS_L2, // 瞰 + 0x77B6, KANJI_SJIS_L2, // 瞶 + 0x77B9, KANJI_SJIS_L2, // 瞹 + 0x77BF, KANJI_SJIS_L2, // 瞿 + 0x77BC, KANJI_SJIS_L2, // 瞌 + 0x77BD, KANJI_SJIS_L2, // 瞜 + 0x77BB, KANJI_SJIS_L2, // 瞻 + 0x77C7, KANJI_SJIS_L2, // 矇 + 0x77CD, KANJI_SJIS_L2, // 矍 + 0x77D7, KANJI_SJIS_L2, // 矗 + 0x77DA, KANJI_SJIS_L2, // 矚 + 0x77DC, KANJI_SJIS_L2, // 矜 + 0x77E3, KANJI_SJIS_L2, // 矣 + 0x77EE, KANJI_SJIS_L2, // 矮 + 0x77FC, KANJI_SJIS_L2, // 矌 + 0x780C, KANJI_SJIS_L2, // 砌 + 0x7812, KANJI_SJIS_L2, // 砒 + 0x7926, KANJI_SJIS_L2, // 瀊 + 0x7820, KANJI_SJIS_L2, // ç   + 0x792A, KANJI_SJIS_L2, // 瀪 + 0x7845, KANJI_SJIS_L2, // 硅 + 0x788E, KANJI_SJIS_L2, // 碎 + 0x7874, KANJI_SJIS_L2, // 硎 + 0x7886, KANJI_SJIS_L2, // 碆 + 0x787C, KANJI_SJIS_L2, // 硌 + 0x789A, KANJI_SJIS_L2, // 碚 + 0x788C, KANJI_SJIS_L2, // 碌 + 0x78A3, KANJI_SJIS_L2, // 碣 + 0x78B5, KANJI_SJIS_L2, // 碵 + 0x78AA, KANJI_SJIS_L2, // 碪 + 0x78AF, KANJI_SJIS_L2, // 碯 + 0x78D1, KANJI_SJIS_L2, // 磑 + 0x78C6, KANJI_SJIS_L2, // 磆 + 0x78CB, KANJI_SJIS_L2, // 磋 + 0x78D4, KANJI_SJIS_L2, // 磔 + 0x78BE, KANJI_SJIS_L2, // 碟 + 0x78BC, KANJI_SJIS_L2, // 碌 + 0x78C5, KANJI_SJIS_L2, // 磅 + 0x78CA, KANJI_SJIS_L2, // 磊 + 0x78EC, KANJI_SJIS_L2, // 磬 + 0x78E7, KANJI_SJIS_L2, // 磧 + 0x78DA, KANJI_SJIS_L2, // 磚 + 0x78FD, KANJI_SJIS_L2, // 磜 + 0x78F4, KANJI_SJIS_L2, // 磎 + 0x7907, KANJI_SJIS_L2, // 瀇 + 0x7912, KANJI_SJIS_L2, // 瀒 + 0x7911, KANJI_SJIS_L2, // 瀑 + 0x7919, KANJI_SJIS_L2, // 瀙 + 0x792C, KANJI_SJIS_L2, // 瀬 + 0x792B, KANJI_SJIS_L2, // 瀫 + 0x7940, KANJI_SJIS_L2, // 祀 + 0x7960, KANJI_SJIS_L2, // 祠 + 0x7957, KANJI_SJIS_L2, // 祗 + 0x795F, KANJI_SJIS_L2, // 祟 + 0x795A, KANJI_SJIS_L2, // 祚 + 0x7955, KANJI_SJIS_L2, // 祕 + 0x7953, KANJI_SJIS_L2, // 祓 + 0x797A, KANJI_SJIS_L2, // 祺 + 0x797F, KANJI_SJIS_L2, // 祿 + 0x798A, KANJI_SJIS_L2, // 穊 + 0x799D, KANJI_SJIS_L2, // 犝 + 0x79A7, KANJI_SJIS_L2, // 犧 + 0x9F4B, KANJI_SJIS_L2, // 霋 + 0x79AA, KANJI_SJIS_L2, // 犪 + 0x79AE, KANJI_SJIS_L2, // 犮 + 0x79B3, KANJI_SJIS_L2, // 犳 + 0x79B9, KANJI_SJIS_L2, // 犹 + 0x79BA, KANJI_SJIS_L2, // 犺 + 0x79C9, KANJI_SJIS_L2, // 秉 + 0x79D5, KANJI_SJIS_L2, // 秕 + 0x79E7, KANJI_SJIS_L2, // ç§§ + 0x79EC, KANJI_SJIS_L2, // 秬 + 0x79E1, KANJI_SJIS_L2, // ç§¡ + 0x79E3, KANJI_SJIS_L2, // ç§£ + 0x7A08, KANJI_SJIS_L2, // 皈 + 0x7A0D, KANJI_SJIS_L2, // 皍 + 0x7A18, KANJI_SJIS_L2, // 皘 + 0x7A19, KANJI_SJIS_L2, // 繙 + 0x7A20, KANJI_SJIS_L2, // çš  + 0x7A1F, KANJI_SJIS_L2, // 繟 + 0x7980, KANJI_SJIS_L2, // 穀 + 0x7A31, KANJI_SJIS_L2, // çš± + 0x7A3B, KANJI_SJIS_L2, // çš» + 0x7A3E, KANJI_SJIS_L2, // 皟 + 0x7A37, KANJI_SJIS_L2, // çš· + 0x7A43, KANJI_SJIS_L2, // 穃 + 0x7A57, KANJI_SJIS_L2, // 穗 + 0x7A49, KANJI_SJIS_L2, // 穉 + 0x7A61, KANJI_SJIS_L2, // ç©¡ + 0x7A62, KANJI_SJIS_L2, // ç©¢ + 0x7A69, KANJI_SJIS_L2, // ç©© + 0x9F9D, KANJI_SJIS_L2, // 韝 + 0x7A70, KANJI_SJIS_L2, // ç©° + 0x7A79, KANJI_SJIS_L2, // 穹 + 0x7A7D, KANJI_SJIS_L2, // 穜 + 0x7A88, KANJI_SJIS_L2, // 窈 + 0x7A97, KANJI_SJIS_L2, // 窗 + 0x7A95, KANJI_SJIS_L2, // 窕 + 0x7A98, KANJI_SJIS_L2, // 窘 + 0x7A96, KANJI_SJIS_L2, // 窖 + 0x7AA9, KANJI_SJIS_L2, // 窩 + 0x7AC8, KANJI_SJIS_L2, // 竈 + 0x7AB0, KANJI_SJIS_L2, // 窰 + 0x3000, KANJI_SJIS_L2, //   + 0x7AB6, KANJI_SJIS_L2, // 窶 + 0x7AC5, KANJI_SJIS_L2, // 竅 + 0x7AC4, KANJI_SJIS_L2, // 竄 + 0x7ABF, KANJI_SJIS_L2, // 窿 + 0x9083, KANJI_SJIS_L2, // 邃 + 0x7AC7, KANJI_SJIS_L2, // 竇 + 0x7ACA, KANJI_SJIS_L2, // 竊 + 0x7ACD, KANJI_SJIS_L2, // 竍 + 0x7ACF, KANJI_SJIS_L2, // 竏 + 0x7AD5, KANJI_SJIS_L2, // 竕 + 0x7AD3, KANJI_SJIS_L2, // 竓 + 0x7AD9, KANJI_SJIS_L2, // 站 + 0x7ADA, KANJI_SJIS_L2, // 竚 + 0x7ADD, KANJI_SJIS_L2, // 竝 + 0x7AE1, KANJI_SJIS_L2, // ç«¡ + 0x7AE2, KANJI_SJIS_L2, // ç«¢ + 0x7AE6, KANJI_SJIS_L2, // 竊 + 0x7AED, KANJI_SJIS_L2, // ç«­ + 0x7AF0, KANJI_SJIS_L2, // ç«° + 0x7B02, KANJI_SJIS_L2, // 笂 + 0x7B0F, KANJI_SJIS_L2, // 笏 + 0x7B0A, KANJI_SJIS_L2, // 笊 + 0x7B06, KANJI_SJIS_L2, // 笆 + 0x7B33, KANJI_SJIS_L2, // 笳 + 0x7B18, KANJI_SJIS_L2, // 笘 + 0x7B19, KANJI_SJIS_L2, // 笙 + 0x7B1E, KANJI_SJIS_L2, // 笞 + 0x7B35, KANJI_SJIS_L2, // 笵 + 0x7B28, KANJI_SJIS_L2, // 笚 + 0x7B36, KANJI_SJIS_L2, // 笶 + 0x7B50, KANJI_SJIS_L2, // 筐 + 0x7B7A, KANJI_SJIS_L2, // ç­º + 0x7B04, KANJI_SJIS_L2, // 笄 + 0x7B4D, KANJI_SJIS_L2, // 筍 + 0x7B0B, KANJI_SJIS_L2, // 笋 + 0x7B4C, KANJI_SJIS_L2, // 筌 + 0x7B45, KANJI_SJIS_L2, // 筅 + 0x7B75, KANJI_SJIS_L2, // ç­µ + 0x7B65, KANJI_SJIS_L2, // ç­¥ + 0x7B74, KANJI_SJIS_L2, // ç­Ž + 0x7B67, KANJI_SJIS_L2, // ç­§ + 0x7B70, KANJI_SJIS_L2, // ç­° + 0x7B71, KANJI_SJIS_L2, // ç­± + 0x7B6C, KANJI_SJIS_L2, // ç­¬ + 0x7B6E, KANJI_SJIS_L2, // ç­® + 0x7B9D, KANJI_SJIS_L2, // 箝 + 0x7B98, KANJI_SJIS_L2, // 箘 + 0x7B9F, KANJI_SJIS_L2, // 箟 + 0x7B8D, KANJI_SJIS_L2, // 箍 + 0x7B9C, KANJI_SJIS_L2, // 箜 + 0x7B9A, KANJI_SJIS_L2, // 箚 + 0x7B8B, KANJI_SJIS_L2, // 箋 + 0x7B92, KANJI_SJIS_L2, // 箒 + 0x7B8F, KANJI_SJIS_L2, // 箏 + 0x7B5D, KANJI_SJIS_L2, // 筝 + 0x7B99, KANJI_SJIS_L2, // 箙 + 0x7BCB, KANJI_SJIS_L2, // 篋 + 0x7BC1, KANJI_SJIS_L2, // 篁 + 0x7BCC, KANJI_SJIS_L2, // 篌 + 0x7BCF, KANJI_SJIS_L2, // 篏 + 0x7BB4, KANJI_SJIS_L2, // 箎 + 0x7BC6, KANJI_SJIS_L2, // 篆 + 0x7BDD, KANJI_SJIS_L2, // 篝 + 0x7BE9, KANJI_SJIS_L2, // 篩 + 0x7C11, KANJI_SJIS_L2, // 簑 + 0x7C14, KANJI_SJIS_L2, // 簔 + 0x7BE6, KANJI_SJIS_L2, // 篊 + 0x7BE5, KANJI_SJIS_L2, // 篥 + 0x7C60, KANJI_SJIS_L2, // ç±  + 0x7C00, KANJI_SJIS_L2, // 簀 + 0x7C07, KANJI_SJIS_L2, // 簇 + 0x7C13, KANJI_SJIS_L2, // 簓 + 0x7BF3, KANJI_SJIS_L2, // 篳 + 0x7BF7, KANJI_SJIS_L2, // 篷 + 0x7C17, KANJI_SJIS_L2, // 簗 + 0x7C0D, KANJI_SJIS_L2, // 簍 + 0x7BF6, KANJI_SJIS_L2, // 篶 + 0x7C23, KANJI_SJIS_L2, // ç°£ + 0x7C27, KANJI_SJIS_L2, // ç°§ + 0x7C2A, KANJI_SJIS_L2, // ç°ª + 0x7C1F, KANJI_SJIS_L2, // 簟 + 0x7C37, KANJI_SJIS_L2, // ç°· + 0x7C2B, KANJI_SJIS_L2, // ç°« + 0x7C3D, KANJI_SJIS_L2, // ç°œ + 0x7C4C, KANJI_SJIS_L2, // 籌 + 0x7C43, KANJI_SJIS_L2, // 籃 + 0x7C54, KANJI_SJIS_L2, // 籔 + 0x7C4F, KANJI_SJIS_L2, // 籏 + 0x7C40, KANJI_SJIS_L2, // 籀 + 0x7C50, KANJI_SJIS_L2, // 籐 + 0x7C58, KANJI_SJIS_L2, // 籘 + 0x7C5F, KANJI_SJIS_L2, // 籟 + 0x7C64, KANJI_SJIS_L2, // ç±€ + 0x7C56, KANJI_SJIS_L2, // 籖 + 0x7C65, KANJI_SJIS_L2, // ç±¥ + 0x7C6C, KANJI_SJIS_L2, // 籬 + 0x7C75, KANJI_SJIS_L2, // ç±µ + 0x7C83, KANJI_SJIS_L2, // 粃 + 0x7C90, KANJI_SJIS_L2, // 粐 + 0x7CA4, KANJI_SJIS_L2, // ç²€ + 0x7CAD, KANJI_SJIS_L2, // ç²­ + 0x7CA2, KANJI_SJIS_L2, // ç²¢ + 0x7CAB, KANJI_SJIS_L2, // 粫 + 0x7CA1, KANJI_SJIS_L2, // 粡 + 0x7CA8, KANJI_SJIS_L2, // 粚 + 0x7CB3, KANJI_SJIS_L2, // ç²³ + 0x7CB2, KANJI_SJIS_L2, // ç²² + 0x7CB1, KANJI_SJIS_L2, // ç²± + 0x7CAE, KANJI_SJIS_L2, // ç²® + 0x7CB9, KANJI_SJIS_L2, // ç²¹ + 0x7CBD, KANJI_SJIS_L2, // 粜 + 0x7CC0, KANJI_SJIS_L2, // 糀 + 0x7CC5, KANJI_SJIS_L2, // 糅 + 0x7CC2, KANJI_SJIS_L2, // 糂 + 0x7CD8, KANJI_SJIS_L2, // 糘 + 0x7CD2, KANJI_SJIS_L2, // 糒 + 0x7CDC, KANJI_SJIS_L2, // 糜 + 0x7CE2, KANJI_SJIS_L2, // ç³¢ + 0x9B3B, KANJI_SJIS_L2, // 鬻 + 0x7CEF, KANJI_SJIS_L2, // 糯 + 0x7CF2, KANJI_SJIS_L2, // ç³² + 0x7CF4, KANJI_SJIS_L2, // 糎 + 0x7CF6, KANJI_SJIS_L2, // ç³¶ + 0x7CFA, KANJI_SJIS_L2, // 糺 + 0x7D06, KANJI_SJIS_L2, // 箆 + 0x7D02, KANJI_SJIS_L2, // 箂 + 0x7D1C, KANJI_SJIS_L2, // 箜 + 0x7D15, KANJI_SJIS_L2, // 箕 + 0x7D0A, KANJI_SJIS_L2, // 箊 + 0x7D45, KANJI_SJIS_L2, // 絅 + 0x7D4B, KANJI_SJIS_L2, // 絋 + 0x7D2E, KANJI_SJIS_L2, // 玮 + 0x7D32, KANJI_SJIS_L2, // 玲 + 0x7D3F, KANJI_SJIS_L2, // 玿 + 0x7D35, KANJI_SJIS_L2, // 玵 + 0x7D46, KANJI_SJIS_L2, // 絆 + 0x7D73, KANJI_SJIS_L2, // çµ³ + 0x7D56, KANJI_SJIS_L2, // 絖 + 0x7D4E, KANJI_SJIS_L2, // 絎 + 0x7D72, KANJI_SJIS_L2, // çµ² + 0x7D68, KANJI_SJIS_L2, // 絚 + 0x7D6E, KANJI_SJIS_L2, // çµ® + 0x7D4F, KANJI_SJIS_L2, // 絏 + 0x7D63, KANJI_SJIS_L2, // çµ£ + 0x7D93, KANJI_SJIS_L2, // 經 + 0x7D89, KANJI_SJIS_L2, // 綉 + 0x7D5B, KANJI_SJIS_L2, // 絛 + 0x7D8F, KANJI_SJIS_L2, // 綏 + 0x7D7D, KANJI_SJIS_L2, // 絜 + 0x7D9B, KANJI_SJIS_L2, // 綛 + 0x7DBA, KANJI_SJIS_L2, // 綺 + 0x7DAE, KANJI_SJIS_L2, // ç¶® + 0x7DA3, KANJI_SJIS_L2, // ç¶£ + 0x7DB5, KANJI_SJIS_L2, // ç¶µ + 0x7DC7, KANJI_SJIS_L2, // 緇 + 0x7DBD, KANJI_SJIS_L2, // ç¶œ + 0x7DAB, KANJI_SJIS_L2, // ç¶« + 0x7E3D, KANJI_SJIS_L2, // çžœ + 0x7DA2, KANJI_SJIS_L2, // ç¶¢ + 0x7DAF, KANJI_SJIS_L2, // 綯 + 0x7DDC, KANJI_SJIS_L2, // 緜 + 0x7DB8, KANJI_SJIS_L2, // ç¶ž + 0x7D9F, KANJI_SJIS_L2, // 綟 + 0x7DB0, KANJI_SJIS_L2, // ç¶° + 0x7DD8, KANJI_SJIS_L2, // 緘 + 0x7DDD, KANJI_SJIS_L2, // 緝 + 0x7DE4, KANJI_SJIS_L2, // ç·€ + 0x7DDE, KANJI_SJIS_L2, // 緞 + 0x7DFB, KANJI_SJIS_L2, // ç·» + 0x7DF2, KANJI_SJIS_L2, // ç·² + 0x7DE1, KANJI_SJIS_L2, // ç·¡ + 0x7E05, KANJI_SJIS_L2, // 羅 + 0x7E0A, KANJI_SJIS_L2, // 羊 + 0x7E23, KANJI_SJIS_L2, // 瞣 + 0x7E21, KANJI_SJIS_L2, // çž¡ + 0x7E12, KANJI_SJIS_L2, // 羒 + 0x7E31, KANJI_SJIS_L2, // çž± + 0x7E1F, KANJI_SJIS_L2, // 羟 + 0x7E09, KANJI_SJIS_L2, // 羉 + 0x7E0B, KANJI_SJIS_L2, // 羋 + 0x7E22, KANJI_SJIS_L2, // 瞢 + 0x7E46, KANJI_SJIS_L2, // 繆 + 0x7E66, KANJI_SJIS_L2, // 繊 + 0x7E3B, KANJI_SJIS_L2, // çž» + 0x7E35, KANJI_SJIS_L2, // çžµ + 0x7E39, KANJI_SJIS_L2, // çž¹ + 0x7E43, KANJI_SJIS_L2, // 繃 + 0x7E37, KANJI_SJIS_L2, // çž· + 0x3000, KANJI_SJIS_L2, //   + 0x7E32, KANJI_SJIS_L2, // çž² + 0x7E3A, KANJI_SJIS_L2, // 瞺 + 0x7E67, KANJI_SJIS_L2, // ç¹§ + 0x7E5D, KANJI_SJIS_L2, // 繝 + 0x7E56, KANJI_SJIS_L2, // 繖 + 0x7E5E, KANJI_SJIS_L2, // 繞 + 0x7E59, KANJI_SJIS_L2, // 繙 + 0x7E5A, KANJI_SJIS_L2, // 繚 + 0x7E79, KANJI_SJIS_L2, // ç¹¹ + 0x7E6A, KANJI_SJIS_L2, // 繪 + 0x7E69, KANJI_SJIS_L2, // 繩 + 0x7E7C, KANJI_SJIS_L2, // 繌 + 0x7E7B, KANJI_SJIS_L2, // ç¹» + 0x7E83, KANJI_SJIS_L2, // 纃 + 0x7DD5, KANJI_SJIS_L2, // 緕 + 0x7E7D, KANJI_SJIS_L2, // 繜 + 0x8FAE, KANJI_SJIS_L2, // 蟮 + 0x7E7F, KANJI_SJIS_L2, // 繿 + 0x7E88, KANJI_SJIS_L2, // 纈 + 0x7E89, KANJI_SJIS_L2, // 纉 + 0x7E8C, KANJI_SJIS_L2, // 續 + 0x7E92, KANJI_SJIS_L2, // 纒 + 0x7E90, KANJI_SJIS_L2, // 纐 + 0x7E93, KANJI_SJIS_L2, // 纓 + 0x7E94, KANJI_SJIS_L2, // 纔 + 0x7E96, KANJI_SJIS_L2, // 纖 + 0x7E8E, KANJI_SJIS_L2, // 纎 + 0x7E9B, KANJI_SJIS_L2, // 纛 + 0x7E9C, KANJI_SJIS_L2, // 纜 + 0x7F38, KANJI_SJIS_L2, // 猞 + 0x7F3A, KANJI_SJIS_L2, // 猺 + 0x7F45, KANJI_SJIS_L2, // 眅 + 0x7F4C, KANJI_SJIS_L2, // 県 + 0x7F4D, KANJI_SJIS_L2, // 眍 + 0x7F4E, KANJI_SJIS_L2, // 眎 + 0x7F50, KANJI_SJIS_L2, // 眐 + 0x7F51, KANJI_SJIS_L2, // 眑 + 0x7F55, KANJI_SJIS_L2, // 眕 + 0x7F54, KANJI_SJIS_L2, // 眔 + 0x7F58, KANJI_SJIS_L2, // 眘 + 0x7F5F, KANJI_SJIS_L2, // 真 + 0x7F60, KANJI_SJIS_L2, // 眠 + 0x7F68, KANJI_SJIS_L2, // 眚 + 0x7F69, KANJI_SJIS_L2, // 眩 + 0x7F67, KANJI_SJIS_L2, // 眧 + 0x7F78, KANJI_SJIS_L2, // 眞 + 0x7F82, KANJI_SJIS_L2, // 矂 + 0x7F86, KANJI_SJIS_L2, // 矆 + 0x7F83, KANJI_SJIS_L2, // 矃 + 0x7F88, KANJI_SJIS_L2, // 矈 + 0x7F87, KANJI_SJIS_L2, // 矇 + 0x7F8C, KANJI_SJIS_L2, // 矌 + 0x7F94, KANJI_SJIS_L2, // 矔 + 0x7F9E, KANJI_SJIS_L2, // 矞 + 0x7F9D, KANJI_SJIS_L2, // 矝 + 0x7F9A, KANJI_SJIS_L2, // 矚 + 0x7FA3, KANJI_SJIS_L2, // 矣 + 0x7FAF, KANJI_SJIS_L2, // 矯 + 0x7FB2, KANJI_SJIS_L2, // 矲 + 0x7FB9, KANJI_SJIS_L2, // 矹 + 0x7FAE, KANJI_SJIS_L2, // 矮 + 0x7FB6, KANJI_SJIS_L2, // 矶 + 0x7FB8, KANJI_SJIS_L2, // 矞 + 0x8B71, KANJI_SJIS_L2, // è­± + 0x7FC5, KANJI_SJIS_L2, // 翅 + 0x7FC6, KANJI_SJIS_L2, // 翆 + 0x7FCA, KANJI_SJIS_L2, // 翊 + 0x7FD5, KANJI_SJIS_L2, // 翕 + 0x7FD4, KANJI_SJIS_L2, // 翔 + 0x7FE1, KANJI_SJIS_L2, // ç¿¡ + 0x7FE6, KANJI_SJIS_L2, // 翊 + 0x7FE9, KANJI_SJIS_L2, // ç¿© + 0x7FF3, KANJI_SJIS_L2, // 翳 + 0x7FF9, KANJI_SJIS_L2, // 翹 + 0x98DC, KANJI_SJIS_L2, // 飜 + 0x8006, KANJI_SJIS_L2, // 耆 + 0x8004, KANJI_SJIS_L2, // 耄 + 0x800B, KANJI_SJIS_L2, // 耋 + 0x8012, KANJI_SJIS_L2, // 耒 + 0x8018, KANJI_SJIS_L2, // 耘 + 0x8019, KANJI_SJIS_L2, // 耙 + 0x801C, KANJI_SJIS_L2, // 耜 + 0x8021, KANJI_SJIS_L2, // 耡 + 0x8028, KANJI_SJIS_L2, // 耚 + 0x803F, KANJI_SJIS_L2, // 耿 + 0x803B, KANJI_SJIS_L2, // 耻 + 0x804A, KANJI_SJIS_L2, // 聊 + 0x8046, KANJI_SJIS_L2, // 聆 + 0x8052, KANJI_SJIS_L2, // 聒 + 0x8058, KANJI_SJIS_L2, // 聘 + 0x805A, KANJI_SJIS_L2, // 聚 + 0x805F, KANJI_SJIS_L2, // 聟 + 0x8062, KANJI_SJIS_L2, // 聢 + 0x8068, KANJI_SJIS_L2, // 聚 + 0x8073, KANJI_SJIS_L2, // 聳 + 0x8072, KANJI_SJIS_L2, // 聲 + 0x8070, KANJI_SJIS_L2, // 聰 + 0x8076, KANJI_SJIS_L2, // 聶 + 0x8079, KANJI_SJIS_L2, // 聹 + 0x807D, KANJI_SJIS_L2, // 聜 + 0x807F, KANJI_SJIS_L2, // 聿 + 0x8084, KANJI_SJIS_L2, // 肄 + 0x8086, KANJI_SJIS_L2, // 肆 + 0x8085, KANJI_SJIS_L2, // 肅 + 0x809B, KANJI_SJIS_L2, // 肛 + 0x8093, KANJI_SJIS_L2, // 肓 + 0x809A, KANJI_SJIS_L2, // 肚 + 0x80AD, KANJI_SJIS_L2, // 肭 + 0x5190, KANJI_SJIS_L2, // 冐 + 0x80AC, KANJI_SJIS_L2, // 肬 + 0x80DB, KANJI_SJIS_L2, // 胛 + 0x80E5, KANJI_SJIS_L2, // 胥 + 0x80D9, KANJI_SJIS_L2, // 胙 + 0x80DD, KANJI_SJIS_L2, // 胝 + 0x80C4, KANJI_SJIS_L2, // 胄 + 0x80DA, KANJI_SJIS_L2, // 胚 + 0x80D6, KANJI_SJIS_L2, // 胖 + 0x8109, KANJI_SJIS_L2, // 脉 + 0x80EF, KANJI_SJIS_L2, // 胯 + 0x80F1, KANJI_SJIS_L2, // 胱 + 0x811B, KANJI_SJIS_L2, // 脛 + 0x8129, KANJI_SJIS_L2, // 脩 + 0x8123, KANJI_SJIS_L2, // 脣 + 0x812F, KANJI_SJIS_L2, // 脯 + 0x814B, KANJI_SJIS_L2, // 腋 + 0x968B, KANJI_SJIS_L2, // 隋 + 0x8146, KANJI_SJIS_L2, // 腆 + 0x813E, KANJI_SJIS_L2, // 脟 + 0x8153, KANJI_SJIS_L2, // 腓 + 0x8151, KANJI_SJIS_L2, // 腑 + 0x80FC, KANJI_SJIS_L2, // 背 + 0x8171, KANJI_SJIS_L2, // 腱 + 0x816E, KANJI_SJIS_L2, // 腮 + 0x8165, KANJI_SJIS_L2, // 腥 + 0x8166, KANJI_SJIS_L2, // è…Š + 0x8174, KANJI_SJIS_L2, // è…Ž + 0x8183, KANJI_SJIS_L2, // 膃 + 0x8188, KANJI_SJIS_L2, // 膈 + 0x818A, KANJI_SJIS_L2, // 膊 + 0x8180, KANJI_SJIS_L2, // 膀 + 0x8182, KANJI_SJIS_L2, // 膂 + 0x81A0, KANJI_SJIS_L2, // 膠 + 0x8195, KANJI_SJIS_L2, // 膕 + 0x81A4, KANJI_SJIS_L2, // 膀 + 0x81A3, KANJI_SJIS_L2, // 膣 + 0x815F, KANJI_SJIS_L2, // 腟 + 0x8193, KANJI_SJIS_L2, // 膓 + 0x81A9, KANJI_SJIS_L2, // 膩 + 0x81B0, KANJI_SJIS_L2, // 膰 + 0x81B5, KANJI_SJIS_L2, // 膵 + 0x81BE, KANJI_SJIS_L2, // 膟 + 0x81B8, KANJI_SJIS_L2, // 膞 + 0x81BD, KANJI_SJIS_L2, // 膜 + 0x81C0, KANJI_SJIS_L2, // 臀 + 0x81C2, KANJI_SJIS_L2, // 臂 + 0x81BA, KANJI_SJIS_L2, // 膺 + 0x81C9, KANJI_SJIS_L2, // 臉 + 0x81CD, KANJI_SJIS_L2, // 臍 + 0x81D1, KANJI_SJIS_L2, // 臑 + 0x81D9, KANJI_SJIS_L2, // 臙 + 0x81D8, KANJI_SJIS_L2, // 臘 + 0x81C8, KANJI_SJIS_L2, // 臈 + 0x81DA, KANJI_SJIS_L2, // 臚 + 0x81DF, KANJI_SJIS_L2, // 臟 + 0x81E0, KANJI_SJIS_L2, // 臠 + 0x81E7, KANJI_SJIS_L2, // 臧 + 0x81FA, KANJI_SJIS_L2, // 臺 + 0x81FB, KANJI_SJIS_L2, // 臻 + 0x81FE, KANJI_SJIS_L2, // 臟 + 0x8201, KANJI_SJIS_L2, // 舁 + 0x8202, KANJI_SJIS_L2, // 舂 + 0x8205, KANJI_SJIS_L2, // 舅 + 0x8207, KANJI_SJIS_L2, // 與 + 0x820A, KANJI_SJIS_L2, // 舊 + 0x820D, KANJI_SJIS_L2, // 舍 + 0x8210, KANJI_SJIS_L2, // 舐 + 0x8216, KANJI_SJIS_L2, // 舖 + 0x8229, KANJI_SJIS_L2, // 舩 + 0x822B, KANJI_SJIS_L2, // 舫 + 0x8238, KANJI_SJIS_L2, // 舞 + 0x8233, KANJI_SJIS_L2, // 舳 + 0x8240, KANJI_SJIS_L2, // 艀 + 0x8259, KANJI_SJIS_L2, // 艙 + 0x8258, KANJI_SJIS_L2, // 艘 + 0x825D, KANJI_SJIS_L2, // 艝 + 0x825A, KANJI_SJIS_L2, // 艚 + 0x825F, KANJI_SJIS_L2, // 艟 + 0x8264, KANJI_SJIS_L2, // 艀 + 0x3000, KANJI_SJIS_L2, //   + 0x8262, KANJI_SJIS_L2, // 艢 + 0x8268, KANJI_SJIS_L2, // 艚 + 0x826A, KANJI_SJIS_L2, // 艪 + 0x826B, KANJI_SJIS_L2, // 艫 + 0x822E, KANJI_SJIS_L2, // 舮 + 0x8271, KANJI_SJIS_L2, // 艱 + 0x8277, KANJI_SJIS_L2, // 艷 + 0x8278, KANJI_SJIS_L2, // 艞 + 0x827E, KANJI_SJIS_L2, // 艟 + 0x828D, KANJI_SJIS_L2, // 芍 + 0x8292, KANJI_SJIS_L2, // 芒 + 0x82AB, KANJI_SJIS_L2, // 芫 + 0x829F, KANJI_SJIS_L2, // 芟 + 0x82BB, KANJI_SJIS_L2, // 芻 + 0x82AC, KANJI_SJIS_L2, // 芬 + 0x82E1, KANJI_SJIS_L2, // 苡 + 0x82E3, KANJI_SJIS_L2, // 苣 + 0x82DF, KANJI_SJIS_L2, // 苟 + 0x82D2, KANJI_SJIS_L2, // 苒 + 0x82F4, KANJI_SJIS_L2, // 苎 + 0x82F3, KANJI_SJIS_L2, // 苳 + 0x82FA, KANJI_SJIS_L2, // 苺 + 0x8393, KANJI_SJIS_L2, // 莓 + 0x8303, KANJI_SJIS_L2, // 范 + 0x82FB, KANJI_SJIS_L2, // 苻 + 0x82F9, KANJI_SJIS_L2, // 苹 + 0x82DE, KANJI_SJIS_L2, // 苞 + 0x8306, KANJI_SJIS_L2, // 茆 + 0x82DC, KANJI_SJIS_L2, // 苜 + 0x8309, KANJI_SJIS_L2, // 茉 + 0x82D9, KANJI_SJIS_L2, // 苙 + 0x8335, KANJI_SJIS_L2, // 茵 + 0x8334, KANJI_SJIS_L2, // 茎 + 0x8316, KANJI_SJIS_L2, // 茖 + 0x8332, KANJI_SJIS_L2, // 茲 + 0x8331, KANJI_SJIS_L2, // 茱 + 0x8340, KANJI_SJIS_L2, // 荀 + 0x8339, KANJI_SJIS_L2, // 茹 + 0x8350, KANJI_SJIS_L2, // 荐 + 0x8345, KANJI_SJIS_L2, // 荅 + 0x832F, KANJI_SJIS_L2, // 茯 + 0x832B, KANJI_SJIS_L2, // 茫 + 0x8317, KANJI_SJIS_L2, // 茗 + 0x8318, KANJI_SJIS_L2, // 茘 + 0x8385, KANJI_SJIS_L2, // 莅 + 0x839A, KANJI_SJIS_L2, // 莚 + 0x83AA, KANJI_SJIS_L2, // 莪 + 0x839F, KANJI_SJIS_L2, // 莟 + 0x83A2, KANJI_SJIS_L2, // 莢 + 0x8396, KANJI_SJIS_L2, // 莖 + 0x8323, KANJI_SJIS_L2, // 茣 + 0x838E, KANJI_SJIS_L2, // 莎 + 0x8387, KANJI_SJIS_L2, // 莇 + 0x838A, KANJI_SJIS_L2, // 莊 + 0x837C, KANJI_SJIS_L2, // 荌 + 0x83B5, KANJI_SJIS_L2, // 莵 + 0x8373, KANJI_SJIS_L2, // 荳 + 0x8375, KANJI_SJIS_L2, // 荵 + 0x83A0, KANJI_SJIS_L2, // 莠 + 0x8389, KANJI_SJIS_L2, // 莉 + 0x83A8, KANJI_SJIS_L2, // 莚 + 0x83F4, KANJI_SJIS_L2, // 菎 + 0x8413, KANJI_SJIS_L2, // 萓 + 0x83EB, KANJI_SJIS_L2, // 菫 + 0x83CE, KANJI_SJIS_L2, // 菎 + 0x83FD, KANJI_SJIS_L2, // 菜 + 0x8403, KANJI_SJIS_L2, // 萃 + 0x83D8, KANJI_SJIS_L2, // 菘 + 0x840B, KANJI_SJIS_L2, // 萋 + 0x83C1, KANJI_SJIS_L2, // 菁 + 0x83F7, KANJI_SJIS_L2, // 菷 + 0x8407, KANJI_SJIS_L2, // 萇 + 0x83E0, KANJI_SJIS_L2, // 菠 + 0x83F2, KANJI_SJIS_L2, // 菲 + 0x840D, KANJI_SJIS_L2, // 萍 + 0x8422, KANJI_SJIS_L2, // 萢 + 0x8420, KANJI_SJIS_L2, // 萠 + 0x83BD, KANJI_SJIS_L2, // 莜 + 0x8438, KANJI_SJIS_L2, // 萞 + 0x8506, KANJI_SJIS_L2, // 蔆 + 0x83FB, KANJI_SJIS_L2, // 菻 + 0x846D, KANJI_SJIS_L2, // 葭 + 0x842A, KANJI_SJIS_L2, // 萪 + 0x843C, KANJI_SJIS_L2, // 萌 + 0x855A, KANJI_SJIS_L2, // 蕚 + 0x8484, KANJI_SJIS_L2, // 蒄 + 0x8477, KANJI_SJIS_L2, // 葷 + 0x846B, KANJI_SJIS_L2, // 葫 + 0x84AD, KANJI_SJIS_L2, // 蒭 + 0x846E, KANJI_SJIS_L2, // 葮 + 0x8482, KANJI_SJIS_L2, // 蒂 + 0x8469, KANJI_SJIS_L2, // 葩 + 0x8446, KANJI_SJIS_L2, // 葆 + 0x842C, KANJI_SJIS_L2, // 萬 + 0x846F, KANJI_SJIS_L2, // 葯 + 0x8479, KANJI_SJIS_L2, // 葹 + 0x8435, KANJI_SJIS_L2, // 萵 + 0x84CA, KANJI_SJIS_L2, // 蓊 + 0x8462, KANJI_SJIS_L2, // 葢 + 0x84B9, KANJI_SJIS_L2, // 蒹 + 0x84BF, KANJI_SJIS_L2, // 蒿 + 0x849F, KANJI_SJIS_L2, // 蒟 + 0x84D9, KANJI_SJIS_L2, // 蓙 + 0x84CD, KANJI_SJIS_L2, // 蓍 + 0x84BB, KANJI_SJIS_L2, // 蒻 + 0x84DA, KANJI_SJIS_L2, // 蓚 + 0x84D0, KANJI_SJIS_L2, // 蓐 + 0x84C1, KANJI_SJIS_L2, // 蓁 + 0x84C6, KANJI_SJIS_L2, // 蓆 + 0x84D6, KANJI_SJIS_L2, // 蓖 + 0x84A1, KANJI_SJIS_L2, // 蒡 + 0x8521, KANJI_SJIS_L2, // 蔡 + 0x84FF, KANJI_SJIS_L2, // 蓿 + 0x84F4, KANJI_SJIS_L2, // 蓎 + 0x8517, KANJI_SJIS_L2, // 蔗 + 0x8518, KANJI_SJIS_L2, // 蔘 + 0x852C, KANJI_SJIS_L2, // 蔬 + 0x851F, KANJI_SJIS_L2, // 蔟 + 0x8515, KANJI_SJIS_L2, // 蔕 + 0x8514, KANJI_SJIS_L2, // 蔔 + 0x84FC, KANJI_SJIS_L2, // 蓌 + 0x8540, KANJI_SJIS_L2, // 蕀 + 0x8563, KANJI_SJIS_L2, // 蕣 + 0x8558, KANJI_SJIS_L2, // 蕘 + 0x8548, KANJI_SJIS_L2, // 蕈 + 0x8541, KANJI_SJIS_L2, // 蕁 + 0x8602, KANJI_SJIS_L2, // 蘂 + 0x854B, KANJI_SJIS_L2, // 蕋 + 0x8555, KANJI_SJIS_L2, // 蕕 + 0x8580, KANJI_SJIS_L2, // 薀 + 0x85A4, KANJI_SJIS_L2, // è–€ + 0x8588, KANJI_SJIS_L2, // 薈 + 0x8591, KANJI_SJIS_L2, // 薑 + 0x858A, KANJI_SJIS_L2, // 薊 + 0x85A8, KANJI_SJIS_L2, // è–š + 0x856D, KANJI_SJIS_L2, // 蕭 + 0x8594, KANJI_SJIS_L2, // 薔 + 0x859B, KANJI_SJIS_L2, // 薛 + 0x85EA, KANJI_SJIS_L2, // 藪 + 0x8587, KANJI_SJIS_L2, // 薇 + 0x859C, KANJI_SJIS_L2, // 薜 + 0x8577, KANJI_SJIS_L2, // 蕷 + 0x857E, KANJI_SJIS_L2, // 蕟 + 0x8590, KANJI_SJIS_L2, // 薐 + 0x85C9, KANJI_SJIS_L2, // 藉 + 0x85BA, KANJI_SJIS_L2, // 薺 + 0x85CF, KANJI_SJIS_L2, // 藏 + 0x85B9, KANJI_SJIS_L2, // 薹 + 0x85D0, KANJI_SJIS_L2, // 藐 + 0x85D5, KANJI_SJIS_L2, // 藕 + 0x85DD, KANJI_SJIS_L2, // 藝 + 0x85E5, KANJI_SJIS_L2, // 藥 + 0x85DC, KANJI_SJIS_L2, // 藜 + 0x85F9, KANJI_SJIS_L2, // 藹 + 0x860A, KANJI_SJIS_L2, // 蘊 + 0x8613, KANJI_SJIS_L2, // 蘓 + 0x860B, KANJI_SJIS_L2, // 蘋 + 0x85FE, KANJI_SJIS_L2, // è—Ÿ + 0x85FA, KANJI_SJIS_L2, // 藺 + 0x8606, KANJI_SJIS_L2, // 蘆 + 0x8622, KANJI_SJIS_L2, // 蘢 + 0x861A, KANJI_SJIS_L2, // 蘚 + 0x8630, KANJI_SJIS_L2, // 蘰 + 0x863F, KANJI_SJIS_L2, // 蘿 + 0x864D, KANJI_SJIS_L2, // 虍 + 0x4E55, KANJI_SJIS_L2, // 乕 + 0x8654, KANJI_SJIS_L2, // 虔 + 0x865F, KANJI_SJIS_L2, // 號 + 0x8667, KANJI_SJIS_L2, // 虧 + 0x8671, KANJI_SJIS_L2, // 虱 + 0x8693, KANJI_SJIS_L2, // 蚓 + 0x86A3, KANJI_SJIS_L2, // 蚣 + 0x86A9, KANJI_SJIS_L2, // 蚩 + 0x86AA, KANJI_SJIS_L2, // 蚪 + 0x868B, KANJI_SJIS_L2, // 蚋 + 0x868C, KANJI_SJIS_L2, // 蚌 + 0x86B6, KANJI_SJIS_L2, // 蚶 + 0x86AF, KANJI_SJIS_L2, // 蚯 + 0x86C4, KANJI_SJIS_L2, // 蛄 + 0x86C6, KANJI_SJIS_L2, // 蛆 + 0x86B0, KANJI_SJIS_L2, // 蚰 + 0x86C9, KANJI_SJIS_L2, // 蛉 + 0x8823, KANJI_SJIS_L2, // è £ + 0x86AB, KANJI_SJIS_L2, // 蚫 + 0x86D4, KANJI_SJIS_L2, // 蛔 + 0x86DE, KANJI_SJIS_L2, // 蛞 + 0x86E9, KANJI_SJIS_L2, // 蛩 + 0x86EC, KANJI_SJIS_L2, // 蛬 + 0x3000, KANJI_SJIS_L2, //   + 0x86DF, KANJI_SJIS_L2, // 蛟 + 0x86DB, KANJI_SJIS_L2, // 蛛 + 0x86EF, KANJI_SJIS_L2, // 蛯 + 0x8712, KANJI_SJIS_L2, // 蜒 + 0x8706, KANJI_SJIS_L2, // 蜆 + 0x8708, KANJI_SJIS_L2, // 蜈 + 0x8700, KANJI_SJIS_L2, // 蜀 + 0x8703, KANJI_SJIS_L2, // 蜃 + 0x86FB, KANJI_SJIS_L2, // 蛻 + 0x8711, KANJI_SJIS_L2, // 蜑 + 0x8709, KANJI_SJIS_L2, // 蜉 + 0x870D, KANJI_SJIS_L2, // 蜍 + 0x86F9, KANJI_SJIS_L2, // 蛹 + 0x870A, KANJI_SJIS_L2, // 蜊 + 0x8734, KANJI_SJIS_L2, // 蜎 + 0x873F, KANJI_SJIS_L2, // 蜿 + 0x8737, KANJI_SJIS_L2, // 蜷 + 0x873B, KANJI_SJIS_L2, // 蜻 + 0x8725, KANJI_SJIS_L2, // 蜥 + 0x8729, KANJI_SJIS_L2, // 蜩 + 0x871A, KANJI_SJIS_L2, // 蜚 + 0x8760, KANJI_SJIS_L2, // 蝠 + 0x875F, KANJI_SJIS_L2, // 蝟 + 0x8778, KANJI_SJIS_L2, // 蝞 + 0x874C, KANJI_SJIS_L2, // 蝌 + 0x874E, KANJI_SJIS_L2, // 蝎 + 0x8774, KANJI_SJIS_L2, // 蝎 + 0x8757, KANJI_SJIS_L2, // 蝗 + 0x8768, KANJI_SJIS_L2, // 蝚 + 0x876E, KANJI_SJIS_L2, // 蝮 + 0x8759, KANJI_SJIS_L2, // 蝙 + 0x8753, KANJI_SJIS_L2, // 蝓 + 0x8763, KANJI_SJIS_L2, // 蝣 + 0x876A, KANJI_SJIS_L2, // 蝪 + 0x8805, KANJI_SJIS_L2, // 蠅 + 0x87A2, KANJI_SJIS_L2, // 螢 + 0x879F, KANJI_SJIS_L2, // 螟 + 0x8782, KANJI_SJIS_L2, // 螂 + 0x87AF, KANJI_SJIS_L2, // 螯 + 0x87CB, KANJI_SJIS_L2, // 蟋 + 0x87BD, KANJI_SJIS_L2, // 螜 + 0x87C0, KANJI_SJIS_L2, // 蟀 + 0x87D0, KANJI_SJIS_L2, // 蟐 + 0x96D6, KANJI_SJIS_L2, // 雖 + 0x87AB, KANJI_SJIS_L2, // 螫 + 0x87C4, KANJI_SJIS_L2, // 蟄 + 0x87B3, KANJI_SJIS_L2, // 螳 + 0x87C7, KANJI_SJIS_L2, // 蟇 + 0x87C6, KANJI_SJIS_L2, // 蟆 + 0x87BB, KANJI_SJIS_L2, // 螻 + 0x87EF, KANJI_SJIS_L2, // 蟯 + 0x87F2, KANJI_SJIS_L2, // 蟲 + 0x87E0, KANJI_SJIS_L2, // 蟠 + 0x880F, KANJI_SJIS_L2, // 蠏 + 0x880D, KANJI_SJIS_L2, // 蠍 + 0x87FE, KANJI_SJIS_L2, // 蟟 + 0x87F6, KANJI_SJIS_L2, // 蟶 + 0x87F7, KANJI_SJIS_L2, // 蟷 + 0x880E, KANJI_SJIS_L2, // 蠎 + 0x87D2, KANJI_SJIS_L2, // 蟒 + 0x8811, KANJI_SJIS_L2, // 蠑 + 0x8816, KANJI_SJIS_L2, // 蠖 + 0x8815, KANJI_SJIS_L2, // 蠕 + 0x8822, KANJI_SJIS_L2, // è ¢ + 0x8821, KANJI_SJIS_L2, // è ¡ + 0x8831, KANJI_SJIS_L2, // è ± + 0x8836, KANJI_SJIS_L2, // è ¶ + 0x8839, KANJI_SJIS_L2, // è ¹ + 0x8827, KANJI_SJIS_L2, // è § + 0x883B, KANJI_SJIS_L2, // è » + 0x8844, KANJI_SJIS_L2, // 衄 + 0x8842, KANJI_SJIS_L2, // 衂 + 0x8852, KANJI_SJIS_L2, // 衒 + 0x8859, KANJI_SJIS_L2, // 衙 + 0x885E, KANJI_SJIS_L2, // 衞 + 0x8862, KANJI_SJIS_L2, // è¡¢ + 0x886B, KANJI_SJIS_L2, // è¡« + 0x8881, KANJI_SJIS_L2, // 袁 + 0x887E, KANJI_SJIS_L2, // 衟 + 0x889E, KANJI_SJIS_L2, // 袞 + 0x8875, KANJI_SJIS_L2, // 衵 + 0x887D, KANJI_SJIS_L2, // 衜 + 0x88B5, KANJI_SJIS_L2, // 袵 + 0x8872, KANJI_SJIS_L2, // 衲 + 0x8882, KANJI_SJIS_L2, // 袂 + 0x8897, KANJI_SJIS_L2, // 袗 + 0x8892, KANJI_SJIS_L2, // 袒 + 0x88AE, KANJI_SJIS_L2, // 袮 + 0x8899, KANJI_SJIS_L2, // 袙 + 0x88A2, KANJI_SJIS_L2, // 袢 + 0x888D, KANJI_SJIS_L2, // 袍 + 0x88A4, KANJI_SJIS_L2, // 袀 + 0x88B0, KANJI_SJIS_L2, // 袰 + 0x88BF, KANJI_SJIS_L2, // 袿 + 0x88B1, KANJI_SJIS_L2, // 袱 + 0x88C3, KANJI_SJIS_L2, // 裃 + 0x88C4, KANJI_SJIS_L2, // 裄 + 0x88D4, KANJI_SJIS_L2, // 裔 + 0x88D8, KANJI_SJIS_L2, // 裘 + 0x88D9, KANJI_SJIS_L2, // 裙 + 0x88DD, KANJI_SJIS_L2, // 裝 + 0x88F9, KANJI_SJIS_L2, // 裹 + 0x8902, KANJI_SJIS_L2, // 耂 + 0x88FC, KANJI_SJIS_L2, // 裌 + 0x88F4, KANJI_SJIS_L2, // 裎 + 0x88E8, KANJI_SJIS_L2, // 裚 + 0x88F2, KANJI_SJIS_L2, // 裲 + 0x8904, KANJI_SJIS_L2, // 耄 + 0x890C, KANJI_SJIS_L2, // 而 + 0x890A, KANJI_SJIS_L2, // 耊 + 0x8913, KANJI_SJIS_L2, // 耓 + 0x8943, KANJI_SJIS_L2, // 襃 + 0x891E, KANJI_SJIS_L2, // 耞 + 0x8925, KANJI_SJIS_L2, // 耥 + 0x892A, KANJI_SJIS_L2, // 耪 + 0x892B, KANJI_SJIS_L2, // 耫 + 0x8941, KANJI_SJIS_L2, // 襁 + 0x8944, KANJI_SJIS_L2, // 襄 + 0x893B, KANJI_SJIS_L2, // 耻 + 0x8936, KANJI_SJIS_L2, // 耶 + 0x8938, KANJI_SJIS_L2, // 耞 + 0x894C, KANJI_SJIS_L2, // 襌 + 0x891D, KANJI_SJIS_L2, // 耝 + 0x8960, KANJI_SJIS_L2, // 襠 + 0x895E, KANJI_SJIS_L2, // 襞 + 0x8966, KANJI_SJIS_L2, // 襊 + 0x8964, KANJI_SJIS_L2, // 襀 + 0x896D, KANJI_SJIS_L2, // 襭 + 0x896A, KANJI_SJIS_L2, // 襪 + 0x896F, KANJI_SJIS_L2, // 襯 + 0x8974, KANJI_SJIS_L2, // 襎 + 0x8977, KANJI_SJIS_L2, // 襷 + 0x897E, KANJI_SJIS_L2, // 襟 + 0x8983, KANJI_SJIS_L2, // 芃 + 0x8988, KANJI_SJIS_L2, // 芈 + 0x898A, KANJI_SJIS_L2, // 芊 + 0x8993, KANJI_SJIS_L2, // 芓 + 0x8998, KANJI_SJIS_L2, // 芘 + 0x89A1, KANJI_SJIS_L2, // 芡 + 0x89A9, KANJI_SJIS_L2, // 芩 + 0x89A6, KANJI_SJIS_L2, // 芊 + 0x89AC, KANJI_SJIS_L2, // 芬 + 0x89AF, KANJI_SJIS_L2, // 芯 + 0x89B2, KANJI_SJIS_L2, // 芲 + 0x89BA, KANJI_SJIS_L2, // 芺 + 0x89BD, KANJI_SJIS_L2, // 芜 + 0x89BF, KANJI_SJIS_L2, // 芿 + 0x89C0, KANJI_SJIS_L2, // 觀 + 0x89DA, KANJI_SJIS_L2, // 觚 + 0x89DC, KANJI_SJIS_L2, // 觜 + 0x89DD, KANJI_SJIS_L2, // 觝 + 0x89E7, KANJI_SJIS_L2, // è§§ + 0x89F4, KANJI_SJIS_L2, // è§Ž + 0x89F8, KANJI_SJIS_L2, // è§ž + 0x8A03, KANJI_SJIS_L2, // 蚃 + 0x8A16, KANJI_SJIS_L2, // èš– + 0x8A10, KANJI_SJIS_L2, // 蚐 + 0x8A0C, KANJI_SJIS_L2, // 蚌 + 0x8A1B, KANJI_SJIS_L2, // èš› + 0x8A1D, KANJI_SJIS_L2, // 蚝 + 0x8A25, KANJI_SJIS_L2, // 蚥 + 0x8A36, KANJI_SJIS_L2, // èš¶ + 0x8A41, KANJI_SJIS_L2, // 詁 + 0x8A5B, KANJI_SJIS_L2, // 詛 + 0x8A52, KANJI_SJIS_L2, // 詒 + 0x8A46, KANJI_SJIS_L2, // 詆 + 0x8A48, KANJI_SJIS_L2, // 詈 + 0x8A7C, KANJI_SJIS_L2, // 詌 + 0x8A6D, KANJI_SJIS_L2, // è©­ + 0x8A6C, KANJI_SJIS_L2, // 詬 + 0x8A62, KANJI_SJIS_L2, // è©¢ + 0x8A85, KANJI_SJIS_L2, // 誅 + 0x8A82, KANJI_SJIS_L2, // 誂 + 0x8A84, KANJI_SJIS_L2, // 誄 + 0x8AA8, KANJI_SJIS_L2, // 誚 + 0x8AA1, KANJI_SJIS_L2, // 誡 + 0x8A91, KANJI_SJIS_L2, // 誑 + 0x8AA5, KANJI_SJIS_L2, // 誥 + 0x8AA6, KANJI_SJIS_L2, // 誊 + 0x8A9A, KANJI_SJIS_L2, // 誚 + 0x8AA3, KANJI_SJIS_L2, // 誣 + 0x8AC4, KANJI_SJIS_L2, // 諄 + 0x8ACD, KANJI_SJIS_L2, // 諍 + 0x8AC2, KANJI_SJIS_L2, // 諂 + 0x8ADA, KANJI_SJIS_L2, // 諚 + 0x8AEB, KANJI_SJIS_L2, // è«« + 0x8AF3, KANJI_SJIS_L2, // 諳 + 0x8AE7, KANJI_SJIS_L2, // è«§ + 0x3000, KANJI_SJIS_L2, //   + 0x8AE4, KANJI_SJIS_L2, // è«€ + 0x8AF1, KANJI_SJIS_L2, // 諱 + 0x8B14, KANJI_SJIS_L2, // 謔 + 0x8AE0, KANJI_SJIS_L2, // è«  + 0x8AE2, KANJI_SJIS_L2, // è«¢ + 0x8AF7, KANJI_SJIS_L2, // è«· + 0x8ADE, KANJI_SJIS_L2, // 諞 + 0x8ADB, KANJI_SJIS_L2, // 諛 + 0x8B0C, KANJI_SJIS_L2, // 謌 + 0x8B07, KANJI_SJIS_L2, // 謇 + 0x8B1A, KANJI_SJIS_L2, // 謚 + 0x8AE1, KANJI_SJIS_L2, // è«¡ + 0x8B16, KANJI_SJIS_L2, // 謖 + 0x8B10, KANJI_SJIS_L2, // 謐 + 0x8B17, KANJI_SJIS_L2, // 謗 + 0x8B20, KANJI_SJIS_L2, // 謠 + 0x8B33, KANJI_SJIS_L2, // 謳 + 0x97AB, KANJI_SJIS_L2, // 鞫 + 0x8B26, KANJI_SJIS_L2, // 謊 + 0x8B2B, KANJI_SJIS_L2, // 謫 + 0x8B3E, KANJI_SJIS_L2, // 謟 + 0x8B28, KANJI_SJIS_L2, // 謚 + 0x8B41, KANJI_SJIS_L2, // 譁 + 0x8B4C, KANJI_SJIS_L2, // 譌 + 0x8B4F, KANJI_SJIS_L2, // 譏 + 0x8B4E, KANJI_SJIS_L2, // 譎 + 0x8B49, KANJI_SJIS_L2, // 證 + 0x8B56, KANJI_SJIS_L2, // 譖 + 0x8B5B, KANJI_SJIS_L2, // 譛 + 0x8B5A, KANJI_SJIS_L2, // 譚 + 0x8B6B, KANJI_SJIS_L2, // è­« + 0x8B5F, KANJI_SJIS_L2, // 譟 + 0x8B6C, KANJI_SJIS_L2, // è­¬ + 0x8B6F, KANJI_SJIS_L2, // è­¯ + 0x8B74, KANJI_SJIS_L2, // è­Ž + 0x8B7D, KANJI_SJIS_L2, // è­œ + 0x8B80, KANJI_SJIS_L2, // 讀 + 0x8B8C, KANJI_SJIS_L2, // 讌 + 0x8B8E, KANJI_SJIS_L2, // 讎 + 0x8B92, KANJI_SJIS_L2, // 讒 + 0x8B93, KANJI_SJIS_L2, // 讓 + 0x8B96, KANJI_SJIS_L2, // 讖 + 0x8B99, KANJI_SJIS_L2, // 讙 + 0x8B9A, KANJI_SJIS_L2, // 讚 + 0x8C3A, KANJI_SJIS_L2, // è°º + 0x8C41, KANJI_SJIS_L2, // 豁 + 0x8C3F, KANJI_SJIS_L2, // è°¿ + 0x8C48, KANJI_SJIS_L2, // 豈 + 0x8C4C, KANJI_SJIS_L2, // 豌 + 0x8C4E, KANJI_SJIS_L2, // 豎 + 0x8C50, KANJI_SJIS_L2, // 豐 + 0x8C55, KANJI_SJIS_L2, // 豕 + 0x8C62, KANJI_SJIS_L2, // è±¢ + 0x8C6C, KANJI_SJIS_L2, // 豬 + 0x8C78, KANJI_SJIS_L2, // 豞 + 0x8C7A, KANJI_SJIS_L2, // 豺 + 0x8C82, KANJI_SJIS_L2, // 貂 + 0x8C89, KANJI_SJIS_L2, // 貉 + 0x8C85, KANJI_SJIS_L2, // 貅 + 0x8C8A, KANJI_SJIS_L2, // 貊 + 0x8C8D, KANJI_SJIS_L2, // 貍 + 0x8C8E, KANJI_SJIS_L2, // 貎 + 0x8C94, KANJI_SJIS_L2, // 貔 + 0x8C7C, KANJI_SJIS_L2, // 豌 + 0x8C98, KANJI_SJIS_L2, // 貘 + 0x621D, KANJI_SJIS_L2, // 戝 + 0x8CAD, KANJI_SJIS_L2, // è²­ + 0x8CAA, KANJI_SJIS_L2, // 貪 + 0x8CBD, KANJI_SJIS_L2, // 貜 + 0x8CB2, KANJI_SJIS_L2, // è²² + 0x8CB3, KANJI_SJIS_L2, // è²³ + 0x8CAE, KANJI_SJIS_L2, // è²® + 0x8CB6, KANJI_SJIS_L2, // è²¶ + 0x8CC8, KANJI_SJIS_L2, // 賈 + 0x8CC1, KANJI_SJIS_L2, // 賁 + 0x8CE4, KANJI_SJIS_L2, // è³€ + 0x8CE3, KANJI_SJIS_L2, // è³£ + 0x8CDA, KANJI_SJIS_L2, // 賚 + 0x8CFD, KANJI_SJIS_L2, // 賜 + 0x8CFA, KANJI_SJIS_L2, // 賺 + 0x8CFB, KANJI_SJIS_L2, // è³» + 0x8D04, KANJI_SJIS_L2, // 莄 + 0x8D05, KANJI_SJIS_L2, // 莅 + 0x8D0A, KANJI_SJIS_L2, // 莊 + 0x8D07, KANJI_SJIS_L2, // 莇 + 0x8D0F, KANJI_SJIS_L2, // 莏 + 0x8D0D, KANJI_SJIS_L2, // 莍 + 0x8D10, KANJI_SJIS_L2, // 莐 + 0x9F4E, KANJI_SJIS_L2, // 霎 + 0x8D13, KANJI_SJIS_L2, // 莓 + 0x8CCD, KANJI_SJIS_L2, // 賍 + 0x8D14, KANJI_SJIS_L2, // 莔 + 0x8D16, KANJI_SJIS_L2, // 莖 + 0x8D67, KANJI_SJIS_L2, // èµ§ + 0x8D6D, KANJI_SJIS_L2, // èµ­ + 0x8D71, KANJI_SJIS_L2, // èµ± + 0x8D73, KANJI_SJIS_L2, // èµ³ + 0x8D81, KANJI_SJIS_L2, // 趁 + 0x8D99, KANJI_SJIS_L2, // 趙 + 0x8DC2, KANJI_SJIS_L2, // 跂 + 0x8DBE, KANJI_SJIS_L2, // è¶Ÿ + 0x8DBA, KANJI_SJIS_L2, // 趺 + 0x8DCF, KANJI_SJIS_L2, // 跏 + 0x8DDA, KANJI_SJIS_L2, // 跚 + 0x8DD6, KANJI_SJIS_L2, // 跖 + 0x8DCC, KANJI_SJIS_L2, // 跌 + 0x8DDB, KANJI_SJIS_L2, // 跛 + 0x8DCB, KANJI_SJIS_L2, // 跋 + 0x8DEA, KANJI_SJIS_L2, // è·ª + 0x8DEB, KANJI_SJIS_L2, // è·« + 0x8DDF, KANJI_SJIS_L2, // 跟 + 0x8DE3, KANJI_SJIS_L2, // è·£ + 0x8DFC, KANJI_SJIS_L2, // è·Œ + 0x8E08, KANJI_SJIS_L2, // 螈 + 0x8E09, KANJI_SJIS_L2, // 螉 + 0x8DFF, KANJI_SJIS_L2, // è·¿ + 0x8E1D, KANJI_SJIS_L2, // 螝 + 0x8E1E, KANJI_SJIS_L2, // èžž + 0x8E10, KANJI_SJIS_L2, // 螐 + 0x8E1F, KANJI_SJIS_L2, // 螟 + 0x8E42, KANJI_SJIS_L2, // 蹂 + 0x8E35, KANJI_SJIS_L2, // èžµ + 0x8E30, KANJI_SJIS_L2, // èž° + 0x8E34, KANJI_SJIS_L2, // 螎 + 0x8E4A, KANJI_SJIS_L2, // 蹊 + 0x8E47, KANJI_SJIS_L2, // 蹇 + 0x8E49, KANJI_SJIS_L2, // 蹉 + 0x8E4C, KANJI_SJIS_L2, // 蹌 + 0x8E50, KANJI_SJIS_L2, // 蹐 + 0x8E48, KANJI_SJIS_L2, // 蹈 + 0x8E59, KANJI_SJIS_L2, // 蹙 + 0x8E64, KANJI_SJIS_L2, // è¹€ + 0x8E60, KANJI_SJIS_L2, // è¹  + 0x8E2A, KANJI_SJIS_L2, // 螪 + 0x8E63, KANJI_SJIS_L2, // è¹£ + 0x8E55, KANJI_SJIS_L2, // 蹕 + 0x8E76, KANJI_SJIS_L2, // è¹¶ + 0x8E72, KANJI_SJIS_L2, // è¹² + 0x8E7C, KANJI_SJIS_L2, // 蹌 + 0x8E81, KANJI_SJIS_L2, // 躁 + 0x8E87, KANJI_SJIS_L2, // 躇 + 0x8E85, KANJI_SJIS_L2, // 躅 + 0x8E84, KANJI_SJIS_L2, // 躄 + 0x8E8B, KANJI_SJIS_L2, // 躋 + 0x8E8A, KANJI_SJIS_L2, // 躊 + 0x8E93, KANJI_SJIS_L2, // 躓 + 0x8E91, KANJI_SJIS_L2, // 躑 + 0x8E94, KANJI_SJIS_L2, // 躔 + 0x8E99, KANJI_SJIS_L2, // 躙 + 0x8EAA, KANJI_SJIS_L2, // 躪 + 0x8EA1, KANJI_SJIS_L2, // 躡 + 0x8EAC, KANJI_SJIS_L2, // 躬 + 0x8EB0, KANJI_SJIS_L2, // 躰 + 0x8EC6, KANJI_SJIS_L2, // 軆 + 0x8EB1, KANJI_SJIS_L2, // 躱 + 0x8EBE, KANJI_SJIS_L2, // 躟 + 0x8EC5, KANJI_SJIS_L2, // 軅 + 0x8EC8, KANJI_SJIS_L2, // 軈 + 0x8ECB, KANJI_SJIS_L2, // 軋 + 0x8EDB, KANJI_SJIS_L2, // 軛 + 0x8EE3, KANJI_SJIS_L2, // 軣 + 0x8EFC, KANJI_SJIS_L2, // 軌 + 0x8EFB, KANJI_SJIS_L2, // è»» + 0x8EEB, KANJI_SJIS_L2, // 軫 + 0x8EFE, KANJI_SJIS_L2, // 軟 + 0x8F0A, KANJI_SJIS_L2, // 茊 + 0x8F05, KANJI_SJIS_L2, // 茅 + 0x8F15, KANJI_SJIS_L2, // 茕 + 0x8F12, KANJI_SJIS_L2, // 茒 + 0x8F19, KANJI_SJIS_L2, // 茙 + 0x8F13, KANJI_SJIS_L2, // 茓 + 0x8F1C, KANJI_SJIS_L2, // 茜 + 0x8F1F, KANJI_SJIS_L2, // 茟 + 0x8F1B, KANJI_SJIS_L2, // 茛 + 0x8F0C, KANJI_SJIS_L2, // 茌 + 0x8F26, KANJI_SJIS_L2, // 茊 + 0x8F33, KANJI_SJIS_L2, // 茳 + 0x8F3B, KANJI_SJIS_L2, // 茻 + 0x8F39, KANJI_SJIS_L2, // 茹 + 0x8F45, KANJI_SJIS_L2, // 蜅 + 0x8F42, KANJI_SJIS_L2, // 蜂 + 0x8F3E, KANJI_SJIS_L2, // 茟 + 0x8F4C, KANJI_SJIS_L2, // 蜌 + 0x8F49, KANJI_SJIS_L2, // 蜉 + 0x8F46, KANJI_SJIS_L2, // 蜆 + 0x8F4E, KANJI_SJIS_L2, // 蜎 + 0x8F57, KANJI_SJIS_L2, // 蜗 + 0x8F5C, KANJI_SJIS_L2, // 蜜 + 0x3000, KANJI_SJIS_L2, //   + 0x8F62, KANJI_SJIS_L2, // 蜢 + 0x8F63, KANJI_SJIS_L2, // 蜣 + 0x8F64, KANJI_SJIS_L2, // 蜀 + 0x8F9C, KANJI_SJIS_L2, // 蟜 + 0x8F9F, KANJI_SJIS_L2, // 蟟 + 0x8FA3, KANJI_SJIS_L2, // 蟣 + 0x8FAD, KANJI_SJIS_L2, // 蟭 + 0x8FAF, KANJI_SJIS_L2, // 蟯 + 0x8FB7, KANJI_SJIS_L2, // 蟷 + 0x8FDA, KANJI_SJIS_L2, // 迚 + 0x8FE5, KANJI_SJIS_L2, // è¿¥ + 0x8FE2, KANJI_SJIS_L2, // è¿¢ + 0x8FEA, KANJI_SJIS_L2, // 迪 + 0x8FEF, KANJI_SJIS_L2, // 迯 + 0x9087, KANJI_SJIS_L2, // 邇 + 0x8FF4, KANJI_SJIS_L2, // 迎 + 0x9005, KANJI_SJIS_L2, // 逅 + 0x8FF9, KANJI_SJIS_L2, // 迹 + 0x8FFA, KANJI_SJIS_L2, // 迺 + 0x9011, KANJI_SJIS_L2, // 逑 + 0x9015, KANJI_SJIS_L2, // 逕 + 0x9021, KANJI_SJIS_L2, // 逡 + 0x900D, KANJI_SJIS_L2, // 逍 + 0x901E, KANJI_SJIS_L2, // 逞 + 0x9016, KANJI_SJIS_L2, // 逖 + 0x900B, KANJI_SJIS_L2, // 逋 + 0x9027, KANJI_SJIS_L2, // 逧 + 0x9036, KANJI_SJIS_L2, // 逶 + 0x9035, KANJI_SJIS_L2, // 逵 + 0x9039, KANJI_SJIS_L2, // 逹 + 0x8FF8, KANJI_SJIS_L2, // 连 + 0x904F, KANJI_SJIS_L2, // 遏 + 0x9050, KANJI_SJIS_L2, // 遐 + 0x9051, KANJI_SJIS_L2, // 遑 + 0x9052, KANJI_SJIS_L2, // 遒 + 0x900E, KANJI_SJIS_L2, // 逎 + 0x9049, KANJI_SJIS_L2, // 遉 + 0x903E, KANJI_SJIS_L2, // 速 + 0x9056, KANJI_SJIS_L2, // 遖 + 0x9058, KANJI_SJIS_L2, // 遘 + 0x905E, KANJI_SJIS_L2, // 遞 + 0x9068, KANJI_SJIS_L2, // 遚 + 0x906F, KANJI_SJIS_L2, // 遯 + 0x9076, KANJI_SJIS_L2, // 遶 + 0x96A8, KANJI_SJIS_L2, // 隹 + 0x9072, KANJI_SJIS_L2, // 遲 + 0x9082, KANJI_SJIS_L2, // 邂 + 0x907D, KANJI_SJIS_L2, // 遜 + 0x9081, KANJI_SJIS_L2, // 邁 + 0x9080, KANJI_SJIS_L2, // 邀 + 0x908A, KANJI_SJIS_L2, // 邊 + 0x9089, KANJI_SJIS_L2, // 邉 + 0x908F, KANJI_SJIS_L2, // 邏 + 0x90A8, KANJI_SJIS_L2, // 邹 + 0x90AF, KANJI_SJIS_L2, // 邯 + 0x90B1, KANJI_SJIS_L2, // 邱 + 0x90B5, KANJI_SJIS_L2, // 邵 + 0x90E2, KANJI_SJIS_L2, // 郢 + 0x90E4, KANJI_SJIS_L2, // 郀 + 0x6248, KANJI_SJIS_L2, // 扈 + 0x90DB, KANJI_SJIS_L2, // 郛 + 0x9102, KANJI_SJIS_L2, // 鄂 + 0x9112, KANJI_SJIS_L2, // 鄒 + 0x9119, KANJI_SJIS_L2, // 鄙 + 0x9132, KANJI_SJIS_L2, // 鄲 + 0x9130, KANJI_SJIS_L2, // 鄰 + 0x914A, KANJI_SJIS_L2, // 酊 + 0x9156, KANJI_SJIS_L2, // 酖 + 0x9158, KANJI_SJIS_L2, // 酘 + 0x9163, KANJI_SJIS_L2, // 酣 + 0x9165, KANJI_SJIS_L2, // 酥 + 0x9169, KANJI_SJIS_L2, // 酩 + 0x9173, KANJI_SJIS_L2, // 酳 + 0x9172, KANJI_SJIS_L2, // 酲 + 0x918B, KANJI_SJIS_L2, // 醋 + 0x9189, KANJI_SJIS_L2, // 醉 + 0x9182, KANJI_SJIS_L2, // 醂 + 0x91A2, KANJI_SJIS_L2, // 醢 + 0x91AB, KANJI_SJIS_L2, // 醫 + 0x91AF, KANJI_SJIS_L2, // 醯 + 0x91AA, KANJI_SJIS_L2, // 醪 + 0x91B5, KANJI_SJIS_L2, // 醵 + 0x91B4, KANJI_SJIS_L2, // 醮 + 0x91BA, KANJI_SJIS_L2, // 醺 + 0x91C0, KANJI_SJIS_L2, // 釀 + 0x91C1, KANJI_SJIS_L2, // 釁 + 0x91C9, KANJI_SJIS_L2, // 釉 + 0x91CB, KANJI_SJIS_L2, // 釋 + 0x91D0, KANJI_SJIS_L2, // 釐 + 0x91D6, KANJI_SJIS_L2, // 釖 + 0x91DF, KANJI_SJIS_L2, // 釟 + 0x91E1, KANJI_SJIS_L2, // 釡 + 0x91DB, KANJI_SJIS_L2, // 釛 + 0x91FC, KANJI_SJIS_L2, // 里 + 0x91F5, KANJI_SJIS_L2, // 釵 + 0x91F6, KANJI_SJIS_L2, // 釶 + 0x921E, KANJI_SJIS_L2, // 鈞 + 0x91FF, KANJI_SJIS_L2, // 釿 + 0x9214, KANJI_SJIS_L2, // 鈔 + 0x922C, KANJI_SJIS_L2, // 鈬 + 0x9215, KANJI_SJIS_L2, // 鈕 + 0x9211, KANJI_SJIS_L2, // 鈑 + 0x925E, KANJI_SJIS_L2, // 鉞 + 0x9257, KANJI_SJIS_L2, // 鉗 + 0x9245, KANJI_SJIS_L2, // 鉅 + 0x9249, KANJI_SJIS_L2, // 鉉 + 0x9264, KANJI_SJIS_L2, // 鉀 + 0x9248, KANJI_SJIS_L2, // 鉈 + 0x9295, KANJI_SJIS_L2, // 銕 + 0x923F, KANJI_SJIS_L2, // 鈿 + 0x924B, KANJI_SJIS_L2, // 鉋 + 0x9250, KANJI_SJIS_L2, // 鉐 + 0x929C, KANJI_SJIS_L2, // 銜 + 0x9296, KANJI_SJIS_L2, // 銖 + 0x9293, KANJI_SJIS_L2, // 銓 + 0x929B, KANJI_SJIS_L2, // 銛 + 0x925A, KANJI_SJIS_L2, // 鉚 + 0x92CF, KANJI_SJIS_L2, // 鋏 + 0x92B9, KANJI_SJIS_L2, // 銹 + 0x92B7, KANJI_SJIS_L2, // 銷 + 0x92E9, KANJI_SJIS_L2, // 鋩 + 0x930F, KANJI_SJIS_L2, // 錏 + 0x92FA, KANJI_SJIS_L2, // 鋺 + 0x9344, KANJI_SJIS_L2, // 鍄 + 0x932E, KANJI_SJIS_L2, // 錮 + 0x9319, KANJI_SJIS_L2, // 錙 + 0x9322, KANJI_SJIS_L2, // 錢 + 0x931A, KANJI_SJIS_L2, // 錚 + 0x9323, KANJI_SJIS_L2, // 錣 + 0x933A, KANJI_SJIS_L2, // 錺 + 0x9335, KANJI_SJIS_L2, // 錵 + 0x933B, KANJI_SJIS_L2, // 錻 + 0x935C, KANJI_SJIS_L2, // 鍜 + 0x9360, KANJI_SJIS_L2, // 鍠 + 0x937C, KANJI_SJIS_L2, // 鍌 + 0x936E, KANJI_SJIS_L2, // 鍮 + 0x9356, KANJI_SJIS_L2, // 鍖 + 0x93B0, KANJI_SJIS_L2, // 鎰 + 0x93AC, KANJI_SJIS_L2, // 鎬 + 0x93AD, KANJI_SJIS_L2, // 鎭 + 0x9394, KANJI_SJIS_L2, // 鎔 + 0x93B9, KANJI_SJIS_L2, // 鎹 + 0x93D6, KANJI_SJIS_L2, // 鏖 + 0x93D7, KANJI_SJIS_L2, // 鏗 + 0x93E8, KANJI_SJIS_L2, // 鏚 + 0x93E5, KANJI_SJIS_L2, // 鏥 + 0x93D8, KANJI_SJIS_L2, // 鏘 + 0x93C3, KANJI_SJIS_L2, // 鏃 + 0x93DD, KANJI_SJIS_L2, // 鏝 + 0x93D0, KANJI_SJIS_L2, // 鏐 + 0x93C8, KANJI_SJIS_L2, // 鏈 + 0x93E4, KANJI_SJIS_L2, // 鏀 + 0x941A, KANJI_SJIS_L2, // 鐚 + 0x9414, KANJI_SJIS_L2, // 鐔 + 0x9413, KANJI_SJIS_L2, // 鐓 + 0x9403, KANJI_SJIS_L2, // 鐃 + 0x9407, KANJI_SJIS_L2, // 鐇 + 0x9410, KANJI_SJIS_L2, // 鐐 + 0x9436, KANJI_SJIS_L2, // 鐶 + 0x942B, KANJI_SJIS_L2, // 鐫 + 0x9435, KANJI_SJIS_L2, // 鐵 + 0x9421, KANJI_SJIS_L2, // 鐡 + 0x943A, KANJI_SJIS_L2, // 鐺 + 0x9441, KANJI_SJIS_L2, // 鑁 + 0x9452, KANJI_SJIS_L2, // 鑒 + 0x9444, KANJI_SJIS_L2, // 鑄 + 0x945B, KANJI_SJIS_L2, // 鑛 + 0x9460, KANJI_SJIS_L2, // 鑠 + 0x9462, KANJI_SJIS_L2, // 鑢 + 0x945E, KANJI_SJIS_L2, // 鑞 + 0x946A, KANJI_SJIS_L2, // 鑪 + 0x9229, KANJI_SJIS_L2, // 鈩 + 0x9470, KANJI_SJIS_L2, // 鑰 + 0x9475, KANJI_SJIS_L2, // 鑵 + 0x9477, KANJI_SJIS_L2, // 鑷 + 0x947D, KANJI_SJIS_L2, // 鑜 + 0x945A, KANJI_SJIS_L2, // 鑚 + 0x947C, KANJI_SJIS_L2, // 鑌 + 0x947E, KANJI_SJIS_L2, // 鑟 + 0x9481, KANJI_SJIS_L2, // 钁 + 0x947F, KANJI_SJIS_L2, // 鑿 + 0x9582, KANJI_SJIS_L2, // 閂 + 0x9587, KANJI_SJIS_L2, // 閇 + 0x958A, KANJI_SJIS_L2, // 閊 + 0x9594, KANJI_SJIS_L2, // 閔 + 0x9596, KANJI_SJIS_L2, // 閖 + 0x9598, KANJI_SJIS_L2, // 閘 + 0x9599, KANJI_SJIS_L2, // 閙 + 0x3000, KANJI_SJIS_L2, //   + 0x95A0, KANJI_SJIS_L2, // 閠 + 0x95A8, KANJI_SJIS_L2, // 閹 + 0x95A7, KANJI_SJIS_L2, // 閧 + 0x95AD, KANJI_SJIS_L2, // 閭 + 0x95BC, KANJI_SJIS_L2, // é–Œ + 0x95BB, KANJI_SJIS_L2, // 閻 + 0x95B9, KANJI_SJIS_L2, // 閹 + 0x95BE, KANJI_SJIS_L2, // é–Ÿ + 0x95CA, KANJI_SJIS_L2, // 闊 + 0x6FF6, KANJI_SJIS_L2, // æ¿¶ + 0x95C3, KANJI_SJIS_L2, // 闃 + 0x95CD, KANJI_SJIS_L2, // 闍 + 0x95CC, KANJI_SJIS_L2, // 闌 + 0x95D5, KANJI_SJIS_L2, // 闕 + 0x95D4, KANJI_SJIS_L2, // 闔 + 0x95D6, KANJI_SJIS_L2, // 闖 + 0x95DC, KANJI_SJIS_L2, // 關 + 0x95E1, KANJI_SJIS_L2, // 闡 + 0x95E5, KANJI_SJIS_L2, // 闥 + 0x95E2, KANJI_SJIS_L2, // 闢 + 0x9621, KANJI_SJIS_L2, // 阡 + 0x9628, KANJI_SJIS_L2, // 阚 + 0x962E, KANJI_SJIS_L2, // 阮 + 0x962F, KANJI_SJIS_L2, // 阯 + 0x9642, KANJI_SJIS_L2, // 陂 + 0x964C, KANJI_SJIS_L2, // 陌 + 0x964F, KANJI_SJIS_L2, // 陏 + 0x964B, KANJI_SJIS_L2, // 陋 + 0x9677, KANJI_SJIS_L2, // 陷 + 0x965C, KANJI_SJIS_L2, // 陜 + 0x965E, KANJI_SJIS_L2, // 陞 + 0x965D, KANJI_SJIS_L2, // 陝 + 0x965F, KANJI_SJIS_L2, // 陟 + 0x9666, KANJI_SJIS_L2, // 险 + 0x9672, KANJI_SJIS_L2, // 陲 + 0x966C, KANJI_SJIS_L2, // 陬 + 0x968D, KANJI_SJIS_L2, // 隍 + 0x9698, KANJI_SJIS_L2, // 隘 + 0x9695, KANJI_SJIS_L2, // 隕 + 0x9697, KANJI_SJIS_L2, // 隗 + 0x96AA, KANJI_SJIS_L2, // 險 + 0x96A7, KANJI_SJIS_L2, // 隧 + 0x96B1, KANJI_SJIS_L2, // 隱 + 0x96B2, KANJI_SJIS_L2, // 隲 + 0x96B0, KANJI_SJIS_L2, // 隰 + 0x96B4, KANJI_SJIS_L2, // 隮 + 0x96B6, KANJI_SJIS_L2, // 隶 + 0x96B8, KANJI_SJIS_L2, // 难 + 0x96B9, KANJI_SJIS_L2, // 隹 + 0x96CE, KANJI_SJIS_L2, // 雎 + 0x96CB, KANJI_SJIS_L2, // 雋 + 0x96C9, KANJI_SJIS_L2, // 雉 + 0x96CD, KANJI_SJIS_L2, // 雍 + 0x894D, KANJI_SJIS_L2, // 襍 + 0x96DC, KANJI_SJIS_L2, // 雜 + 0x970D, KANJI_SJIS_L2, // 霍 + 0x96D5, KANJI_SJIS_L2, // 雕 + 0x96F9, KANJI_SJIS_L2, // 雹 + 0x9704, KANJI_SJIS_L2, // 霄 + 0x9706, KANJI_SJIS_L2, // 霆 + 0x9708, KANJI_SJIS_L2, // 霈 + 0x9713, KANJI_SJIS_L2, // 霓 + 0x970E, KANJI_SJIS_L2, // 霎 + 0x9711, KANJI_SJIS_L2, // 霑 + 0x970F, KANJI_SJIS_L2, // 霏 + 0x9716, KANJI_SJIS_L2, // 霖 + 0x9719, KANJI_SJIS_L2, // 霙 + 0x9724, KANJI_SJIS_L2, // 需 + 0x972A, KANJI_SJIS_L2, // 霪 + 0x9730, KANJI_SJIS_L2, // 霰 + 0x9739, KANJI_SJIS_L2, // 霹 + 0x973D, KANJI_SJIS_L2, // 霜 + 0x973E, KANJI_SJIS_L2, // 霟 + 0x9744, KANJI_SJIS_L2, // 靄 + 0x9746, KANJI_SJIS_L2, // 靆 + 0x9748, KANJI_SJIS_L2, // 靈 + 0x9742, KANJI_SJIS_L2, // 靂 + 0x9749, KANJI_SJIS_L2, // 靉 + 0x975C, KANJI_SJIS_L2, // 靜 + 0x9760, KANJI_SJIS_L2, // 靠 + 0x9764, KANJI_SJIS_L2, // 靀 + 0x9766, KANJI_SJIS_L2, // 靊 + 0x9768, KANJI_SJIS_L2, // 靚 + 0x52D2, KANJI_SJIS_L2, // 勒 + 0x976B, KANJI_SJIS_L2, // 靫 + 0x9771, KANJI_SJIS_L2, // 靱 + 0x9779, KANJI_SJIS_L2, // 靹 + 0x9785, KANJI_SJIS_L2, // 鞅 + 0x977C, KANJI_SJIS_L2, // 靌 + 0x9781, KANJI_SJIS_L2, // 鞁 + 0x977A, KANJI_SJIS_L2, // 靺 + 0x9786, KANJI_SJIS_L2, // 鞆 + 0x978B, KANJI_SJIS_L2, // 鞋 + 0x978F, KANJI_SJIS_L2, // 鞏 + 0x9790, KANJI_SJIS_L2, // 鞐 + 0x979C, KANJI_SJIS_L2, // 鞜 + 0x97A8, KANJI_SJIS_L2, // 鞚 + 0x97A6, KANJI_SJIS_L2, // 鞊 + 0x97A3, KANJI_SJIS_L2, // 鞣 + 0x97B3, KANJI_SJIS_L2, // 鞳 + 0x97B4, KANJI_SJIS_L2, // 鞮 + 0x97C3, KANJI_SJIS_L2, // 韃 + 0x97C6, KANJI_SJIS_L2, // 韆 + 0x97C8, KANJI_SJIS_L2, // 韈 + 0x97CB, KANJI_SJIS_L2, // 韋 + 0x97DC, KANJI_SJIS_L2, // 韜 + 0x97ED, KANJI_SJIS_L2, // 韭 + 0x9F4F, KANJI_SJIS_L2, // 霏 + 0x97F2, KANJI_SJIS_L2, // 韲 + 0x7ADF, KANJI_SJIS_L2, // 竟 + 0x97F6, KANJI_SJIS_L2, // 韶 + 0x97F5, KANJI_SJIS_L2, // 韵 + 0x980F, KANJI_SJIS_L2, // 頏 + 0x980C, KANJI_SJIS_L2, // 頌 + 0x9838, KANJI_SJIS_L2, // é ž + 0x9824, KANJI_SJIS_L2, // é € + 0x9821, KANJI_SJIS_L2, // é ¡ + 0x9837, KANJI_SJIS_L2, // é · + 0x983D, KANJI_SJIS_L2, // é œ + 0x9846, KANJI_SJIS_L2, // 顆 + 0x984F, KANJI_SJIS_L2, // 顏 + 0x984B, KANJI_SJIS_L2, // 顋 + 0x986B, KANJI_SJIS_L2, // é¡« + 0x986F, KANJI_SJIS_L2, // 顯 + 0x9870, KANJI_SJIS_L2, // é¡° + 0x9871, KANJI_SJIS_L2, // 顱 + 0x9874, KANJI_SJIS_L2, // 顎 + 0x9873, KANJI_SJIS_L2, // 顳 + 0x98AA, KANJI_SJIS_L2, // 颪 + 0x98AF, KANJI_SJIS_L2, // 颯 + 0x98B1, KANJI_SJIS_L2, // 颱 + 0x98B6, KANJI_SJIS_L2, // 颶 + 0x98C4, KANJI_SJIS_L2, // 飄 + 0x98C3, KANJI_SJIS_L2, // 飃 + 0x98C6, KANJI_SJIS_L2, // 飆 + 0x98E9, KANJI_SJIS_L2, // 飩 + 0x98EB, KANJI_SJIS_L2, // 飫 + 0x9903, KANJI_SJIS_L2, // 逃 + 0x9909, KANJI_SJIS_L2, // 选 + 0x9912, KANJI_SJIS_L2, // 递 + 0x9914, KANJI_SJIS_L2, // 途 + 0x9918, KANJI_SJIS_L2, // 逘 + 0x9921, KANJI_SJIS_L2, // 逡 + 0x991D, KANJI_SJIS_L2, // 逝 + 0x991E, KANJI_SJIS_L2, // 逞 + 0x9924, KANJI_SJIS_L2, // 退 + 0x9920, KANJI_SJIS_L2, // 造 + 0x992C, KANJI_SJIS_L2, // 逬 + 0x992E, KANJI_SJIS_L2, // 逮 + 0x993D, KANJI_SJIS_L2, // 逜 + 0x993E, KANJI_SJIS_L2, // 速 + 0x9942, KANJI_SJIS_L2, // 饂 + 0x9949, KANJI_SJIS_L2, // 饉 + 0x9945, KANJI_SJIS_L2, // 饅 + 0x9950, KANJI_SJIS_L2, // 饐 + 0x994B, KANJI_SJIS_L2, // 饋 + 0x9951, KANJI_SJIS_L2, // 饑 + 0x9952, KANJI_SJIS_L2, // 饒 + 0x994C, KANJI_SJIS_L2, // 饌 + 0x9955, KANJI_SJIS_L2, // 饕 + 0x9997, KANJI_SJIS_L2, // 驗 + 0x9998, KANJI_SJIS_L2, // 銘 + 0x99A5, KANJI_SJIS_L2, // 銥 + 0x99AD, KANJI_SJIS_L2, // 銭 + 0x99AE, KANJI_SJIS_L2, // 銮 + 0x99BC, KANJI_SJIS_L2, // 銌 + 0x99DF, KANJI_SJIS_L2, // 駟 + 0x99DB, KANJI_SJIS_L2, // 駛 + 0x99DD, KANJI_SJIS_L2, // 駝 + 0x99D8, KANJI_SJIS_L2, // 駘 + 0x99D1, KANJI_SJIS_L2, // 駑 + 0x99ED, KANJI_SJIS_L2, // é§­ + 0x99EE, KANJI_SJIS_L2, // é§® + 0x99F1, KANJI_SJIS_L2, // é§± + 0x99F2, KANJI_SJIS_L2, // é§² + 0x99FB, KANJI_SJIS_L2, // é§» + 0x99F8, KANJI_SJIS_L2, // é§ž + 0x9A01, KANJI_SJIS_L2, // 隁 + 0x9A0F, KANJI_SJIS_L2, // 随 + 0x9A05, KANJI_SJIS_L2, // 鹅 + 0x99E2, KANJI_SJIS_L2, // é§¢ + 0x9A19, KANJI_SJIS_L2, // 鹙 + 0x9A2B, KANJI_SJIS_L2, // éš« + 0x9A37, KANJI_SJIS_L2, // éš· + 0x9A45, KANJI_SJIS_L2, // 驅 + 0x9A42, KANJI_SJIS_L2, // 驂 + 0x9A40, KANJI_SJIS_L2, // 驀 + 0x9A43, KANJI_SJIS_L2, // 驃 + 0x3000, KANJI_SJIS_L2, //   + 0x9A3E, KANJI_SJIS_L2, // 隟 + 0x9A55, KANJI_SJIS_L2, // 驕 + 0x9A4D, KANJI_SJIS_L2, // 驍 + 0x9A5B, KANJI_SJIS_L2, // 驛 + 0x9A57, KANJI_SJIS_L2, // 驗 + 0x9A5F, KANJI_SJIS_L2, // 驟 + 0x9A62, KANJI_SJIS_L2, // é©¢ + 0x9A65, KANJI_SJIS_L2, // é©¥ + 0x9A64, KANJI_SJIS_L2, // é©€ + 0x9A69, KANJI_SJIS_L2, // é©© + 0x9A6B, KANJI_SJIS_L2, // é©« + 0x9A6A, KANJI_SJIS_L2, // 驪 + 0x9AAD, KANJI_SJIS_L2, // 骭 + 0x9AB0, KANJI_SJIS_L2, // 骰 + 0x9ABC, KANJI_SJIS_L2, // 验 + 0x9AC0, KANJI_SJIS_L2, // 髀 + 0x9ACF, KANJI_SJIS_L2, // 髏 + 0x9AD1, KANJI_SJIS_L2, // 髑 + 0x9AD3, KANJI_SJIS_L2, // 髓 + 0x9AD4, KANJI_SJIS_L2, // 體 + 0x9ADE, KANJI_SJIS_L2, // 髞 + 0x9ADF, KANJI_SJIS_L2, // 髟 + 0x9AE2, KANJI_SJIS_L2, // é«¢ + 0x9AE3, KANJI_SJIS_L2, // é«£ + 0x9AE6, KANJI_SJIS_L2, // 髊 + 0x9AEF, KANJI_SJIS_L2, // 髯 + 0x9AEB, KANJI_SJIS_L2, // é«« + 0x9AEE, KANJI_SJIS_L2, // é«® + 0x9AF4, KANJI_SJIS_L2, // 髎 + 0x9AF1, KANJI_SJIS_L2, // 髱 + 0x9AF7, KANJI_SJIS_L2, // é«· + 0x9AFB, KANJI_SJIS_L2, // é«» + 0x9B06, KANJI_SJIS_L2, // 鬆 + 0x9B18, KANJI_SJIS_L2, // 鬘 + 0x9B1A, KANJI_SJIS_L2, // 鬚 + 0x9B1F, KANJI_SJIS_L2, // 鬟 + 0x9B22, KANJI_SJIS_L2, // 鬢 + 0x9B23, KANJI_SJIS_L2, // 鬣 + 0x9B25, KANJI_SJIS_L2, // 鬥 + 0x9B27, KANJI_SJIS_L2, // 鬧 + 0x9B28, KANJI_SJIS_L2, // 鬚 + 0x9B29, KANJI_SJIS_L2, // 鬩 + 0x9B2A, KANJI_SJIS_L2, // 鬪 + 0x9B2E, KANJI_SJIS_L2, // 鬮 + 0x9B2F, KANJI_SJIS_L2, // 鬯 + 0x9B32, KANJI_SJIS_L2, // 鬲 + 0x9B44, KANJI_SJIS_L2, // 魄 + 0x9B43, KANJI_SJIS_L2, // 魃 + 0x9B4F, KANJI_SJIS_L2, // 魏 + 0x9B4D, KANJI_SJIS_L2, // 魍 + 0x9B4E, KANJI_SJIS_L2, // 魎 + 0x9B51, KANJI_SJIS_L2, // 魑 + 0x9B58, KANJI_SJIS_L2, // 魘 + 0x9B74, KANJI_SJIS_L2, // é­Ž + 0x9B93, KANJI_SJIS_L2, // 鮓 + 0x9B83, KANJI_SJIS_L2, // 鮃 + 0x9B91, KANJI_SJIS_L2, // 鮑 + 0x9B96, KANJI_SJIS_L2, // 鮖 + 0x9B97, KANJI_SJIS_L2, // 鮗 + 0x9B9F, KANJI_SJIS_L2, // 鮟 + 0x9BA0, KANJI_SJIS_L2, // é®  + 0x9BA8, KANJI_SJIS_L2, // 鮚 + 0x9BB4, KANJI_SJIS_L2, // 鮎 + 0x9BC0, KANJI_SJIS_L2, // 鯀 + 0x9BCA, KANJI_SJIS_L2, // 鯊 + 0x9BB9, KANJI_SJIS_L2, // 鮹 + 0x9BC6, KANJI_SJIS_L2, // 鯆 + 0x9BCF, KANJI_SJIS_L2, // 鯏 + 0x9BD1, KANJI_SJIS_L2, // 鯑 + 0x9BD2, KANJI_SJIS_L2, // 鯒 + 0x9BE3, KANJI_SJIS_L2, // 鯣 + 0x9BE2, KANJI_SJIS_L2, // 鯢 + 0x9BE4, KANJI_SJIS_L2, // 鯀 + 0x9BD4, KANJI_SJIS_L2, // 鯔 + 0x9BE1, KANJI_SJIS_L2, // 鯡 + 0x9C3A, KANJI_SJIS_L2, // é°º + 0x9BF2, KANJI_SJIS_L2, // 鯲 + 0x9BF1, KANJI_SJIS_L2, // 鯱 + 0x9BF0, KANJI_SJIS_L2, // 鯰 + 0x9C15, KANJI_SJIS_L2, // 鰕 + 0x9C14, KANJI_SJIS_L2, // 鰔 + 0x9C09, KANJI_SJIS_L2, // 鰉 + 0x9C13, KANJI_SJIS_L2, // 鰓 + 0x9C0C, KANJI_SJIS_L2, // 鰌 + 0x9C06, KANJI_SJIS_L2, // 鰆 + 0x9C08, KANJI_SJIS_L2, // 鰈 + 0x9C12, KANJI_SJIS_L2, // 鰒 + 0x9C0A, KANJI_SJIS_L2, // 鰊 + 0x9C04, KANJI_SJIS_L2, // 鰄 + 0x9C2E, KANJI_SJIS_L2, // é°® + 0x9C1B, KANJI_SJIS_L2, // 鰛 + 0x9C25, KANJI_SJIS_L2, // é°¥ + 0x9C24, KANJI_SJIS_L2, // é°€ + 0x9C21, KANJI_SJIS_L2, // é°¡ + 0x9C30, KANJI_SJIS_L2, // é°° + 0x9C47, KANJI_SJIS_L2, // 鱇 + 0x9C32, KANJI_SJIS_L2, // é°² + 0x9C46, KANJI_SJIS_L2, // 鱆 + 0x9C3E, KANJI_SJIS_L2, // é°Ÿ + 0x9C5A, KANJI_SJIS_L2, // 鱚 + 0x9C60, KANJI_SJIS_L2, // é±  + 0x9C67, KANJI_SJIS_L2, // é±§ + 0x9C76, KANJI_SJIS_L2, // é±¶ + 0x9C78, KANJI_SJIS_L2, // 鱞 + 0x9CE7, KANJI_SJIS_L2, // é³§ + 0x9CEC, KANJI_SJIS_L2, // 鳬 + 0x9CF0, KANJI_SJIS_L2, // é³° + 0x9D09, KANJI_SJIS_L2, // 鮉 + 0x9D08, KANJI_SJIS_L2, // 鎈 + 0x9CEB, KANJI_SJIS_L2, // 鳫 + 0x9D03, KANJI_SJIS_L2, // 鎃 + 0x9D06, KANJI_SJIS_L2, // 鮆 + 0x9D2A, KANJI_SJIS_L2, // 鎪 + 0x9D26, KANJI_SJIS_L2, // 鎊 + 0x9DAF, KANJI_SJIS_L2, // 鶯 + 0x9D23, KANJI_SJIS_L2, // 鎣 + 0x9D1F, KANJI_SJIS_L2, // 鮟 + 0x9D44, KANJI_SJIS_L2, // 鵄 + 0x9D15, KANJI_SJIS_L2, // 鮕 + 0x9D12, KANJI_SJIS_L2, // 鮒 + 0x9D41, KANJI_SJIS_L2, // 鵁 + 0x9D3F, KANJI_SJIS_L2, // 鎿 + 0x9D3E, KANJI_SJIS_L2, // 鎟 + 0x9D46, KANJI_SJIS_L2, // 鵆 + 0x9D48, KANJI_SJIS_L2, // 鵈 + 0x9D5D, KANJI_SJIS_L2, // 鵝 + 0x9D5E, KANJI_SJIS_L2, // 鵞 + 0x9D64, KANJI_SJIS_L2, // éµ€ + 0x9D51, KANJI_SJIS_L2, // 鵑 + 0x9D50, KANJI_SJIS_L2, // 鵐 + 0x9D59, KANJI_SJIS_L2, // 鵙 + 0x9D72, KANJI_SJIS_L2, // éµ² + 0x9D89, KANJI_SJIS_L2, // 鶉 + 0x9D87, KANJI_SJIS_L2, // 鶇 + 0x9DAB, KANJI_SJIS_L2, // é¶« + 0x9D6F, KANJI_SJIS_L2, // 鵯 + 0x9D7A, KANJI_SJIS_L2, // 鵺 + 0x9D9A, KANJI_SJIS_L2, // 鶚 + 0x9DA4, KANJI_SJIS_L2, // é¶€ + 0x9DA9, KANJI_SJIS_L2, // é¶© + 0x9DB2, KANJI_SJIS_L2, // é¶² + 0x9DC4, KANJI_SJIS_L2, // 鷄 + 0x9DC1, KANJI_SJIS_L2, // 鷁 + 0x9DBB, KANJI_SJIS_L2, // é¶» + 0x9DB8, KANJI_SJIS_L2, // é¶ž + 0x9DBA, KANJI_SJIS_L2, // 鶺 + 0x9DC6, KANJI_SJIS_L2, // 鷆 + 0x9DCF, KANJI_SJIS_L2, // 鷏 + 0x9DC2, KANJI_SJIS_L2, // 鷂 + 0x9DD9, KANJI_SJIS_L2, // 鷙 + 0x9DD3, KANJI_SJIS_L2, // 鷓 + 0x9DF8, KANJI_SJIS_L2, // é·ž + 0x9DE6, KANJI_SJIS_L2, // é·Š + 0x9DED, KANJI_SJIS_L2, // é·­ + 0x9DEF, KANJI_SJIS_L2, // é·¯ + 0x9DFD, KANJI_SJIS_L2, // é·œ + 0x9E1A, KANJI_SJIS_L2, // 龚 + 0x9E1B, KANJI_SJIS_L2, // 龛 + 0x9E1E, KANJI_SJIS_L2, // 龞 + 0x9E75, KANJI_SJIS_L2, // é¹µ + 0x9E79, KANJI_SJIS_L2, // é¹¹ + 0x9E7D, KANJI_SJIS_L2, // 鹜 + 0x9E81, KANJI_SJIS_L2, // 麁 + 0x9E88, KANJI_SJIS_L2, // 麈 + 0x9E8B, KANJI_SJIS_L2, // 麋 + 0x9E8C, KANJI_SJIS_L2, // 麌 + 0x9E92, KANJI_SJIS_L2, // 麒 + 0x9E95, KANJI_SJIS_L2, // 麕 + 0x9E91, KANJI_SJIS_L2, // 麑 + 0x9E9D, KANJI_SJIS_L2, // 麝 + 0x9EA5, KANJI_SJIS_L2, // 麥 + 0x9EA9, KANJI_SJIS_L2, // 麩 + 0x9EB8, KANJI_SJIS_L2, // 麞 + 0x9EAA, KANJI_SJIS_L2, // 麪 + 0x9EAD, KANJI_SJIS_L2, // 麭 + 0x9761, KANJI_SJIS_L2, // 靡 + 0x9ECC, KANJI_SJIS_L2, // 黌 + 0x9ECE, KANJI_SJIS_L2, // 黎 + 0x9ECF, KANJI_SJIS_L2, // 黏 + 0x9ED0, KANJI_SJIS_L2, // 黐 + 0x9ED4, KANJI_SJIS_L2, // 黔 + 0x9EDC, KANJI_SJIS_L2, // 黜 + 0x9EDE, KANJI_SJIS_L2, // 點 + 0x9EDD, KANJI_SJIS_L2, // 黝 + 0x9EE0, KANJI_SJIS_L2, // é»  + 0x9EE5, KANJI_SJIS_L2, // 黥 + 0x9EE8, KANJI_SJIS_L2, // 黚 + 0x9EEF, KANJI_SJIS_L2, // 黯 + 0x3000, KANJI_SJIS_L2, //   + 0x9EF4, KANJI_SJIS_L2, // 黎 + 0x9EF6, KANJI_SJIS_L2, // é»¶ + 0x9EF7, KANJI_SJIS_L2, // é»· + 0x9EF9, KANJI_SJIS_L2, // 黹 + 0x9EFB, KANJI_SJIS_L2, // é»» + 0x9EFC, KANJI_SJIS_L2, // 黌 + 0x9EFD, KANJI_SJIS_L2, // 黜 + 0x9F07, KANJI_SJIS_L2, // 錇 + 0x9F08, KANJI_SJIS_L2, // 錈 + 0x76B7, KANJI_SJIS_L2, // 皷 + 0x9F15, KANJI_SJIS_L2, // 錕 + 0x9F21, KANJI_SJIS_L2, // 錡 + 0x9F2C, KANJI_SJIS_L2, // 錬 + 0x9F3E, KANJI_SJIS_L2, // 錟 + 0x9F4A, KANJI_SJIS_L2, // 霊 + 0x9F52, KANJI_SJIS_L2, // 霒 + 0x9F54, KANJI_SJIS_L2, // 霔 + 0x9F63, KANJI_SJIS_L2, // 霣 + 0x9F5F, KANJI_SJIS_L2, // 霟 + 0x9F60, KANJI_SJIS_L2, // 霠 + 0x9F61, KANJI_SJIS_L2, // 霡 + 0x9F66, KANJI_SJIS_L2, // 霊 + 0x9F67, KANJI_SJIS_L2, // 霧 + 0x9F6C, KANJI_SJIS_L2, // 霬 + 0x9F6A, KANJI_SJIS_L2, // 霪 + 0x9F77, KANJI_SJIS_L2, // 霷 + 0x9F72, KANJI_SJIS_L2, // 露 + 0x9F76, KANJI_SJIS_L2, // 霶 + 0x9F95, KANJI_SJIS_L2, // 韕 + 0x9F9C, KANJI_SJIS_L2, // 韜 + 0x9FA0, KANJI_SJIS_L2, // 韠 + 0x582F, KANJI_SJIS_L2, // å ¯ + 0x69C7, KANJI_SJIS_L2, // 槇 + 0x9059, KANJI_SJIS_L2, // 遙 + 0x7464, KANJI_SJIS_L2, // ç‘€ + 0x51DC, KANJI_SJIS_L2, // 凜 + 0x7199, KANJI_SJIS_L2, // 熙 + 0x7E8A, KANJI_SJIS_L3, // 纊 + 0x891C, KANJI_SJIS_L3, // 耜 + 0x9348, KANJI_SJIS_L3, // 鍈 + 0x9288, KANJI_SJIS_L3, // 銈 + 0x84DC, KANJI_SJIS_L3, // 蓜 + 0x4FC9, KANJI_SJIS_L3, // 俉 + 0x70BB, KANJI_SJIS_L3, // 炻 + 0x6631, KANJI_SJIS_L3, // 昱 + 0x68C8, KANJI_SJIS_L3, // 棈 + 0x92F9, KANJI_SJIS_L3, // 鋹 + 0x66FB, KANJI_SJIS_L3, // 曻 + 0x5F45, KANJI_SJIS_L3, // 圅 + 0x4E28, KANJI_SJIS_L3, // äžš + 0x4EE1, KANJI_SJIS_L3, // 仡 + 0x4EFC, KANJI_SJIS_L3, // 仌 + 0x4F00, KANJI_SJIS_L3, // 䌀 + 0x4F03, KANJI_SJIS_L3, // 䌃 + 0x4F39, KANJI_SJIS_L3, // 䌹 + 0x4F56, KANJI_SJIS_L3, // 䜖 + 0x4F92, KANJI_SJIS_L3, // 䟒 + 0x4F8A, KANJI_SJIS_L3, // 䟊 + 0x4F9A, KANJI_SJIS_L3, // 䟚 + 0x4F94, KANJI_SJIS_L3, // 䟔 + 0x4FCD, KANJI_SJIS_L3, // 俍 + 0x5040, KANJI_SJIS_L3, // 偀 + 0x5022, KANJI_SJIS_L3, // 倢 + 0x4FFF, KANJI_SJIS_L3, // ä¿¿ + 0x501E, KANJI_SJIS_L3, // 倞 + 0x5046, KANJI_SJIS_L3, // 偆 + 0x5070, KANJI_SJIS_L3, // 偰 + 0x5042, KANJI_SJIS_L3, // 偂 + 0x5094, KANJI_SJIS_L3, // 傔 + 0x50F4, KANJI_SJIS_L3, // 僎 + 0x50D8, KANJI_SJIS_L3, // 僘 + 0x514A, KANJI_SJIS_L3, // 兊 + 0x5164, KANJI_SJIS_L3, // å…€ + 0x519D, KANJI_SJIS_L3, // 冝 + 0x51BE, KANJI_SJIS_L3, // 冟 + 0x51EC, KANJI_SJIS_L3, // 凬 + 0x5215, KANJI_SJIS_L3, // 刕 + 0x529C, KANJI_SJIS_L3, // 劜 + 0x52A6, KANJI_SJIS_L3, // 劊 + 0x52C0, KANJI_SJIS_L3, // 勀 + 0x52DB, KANJI_SJIS_L3, // 勛 + 0x5300, KANJI_SJIS_L3, // 匀 + 0x5307, KANJI_SJIS_L3, // 匇 + 0x5324, KANJI_SJIS_L3, // 匀 + 0x5372, KANJI_SJIS_L3, // 卲 + 0x5393, KANJI_SJIS_L3, // 厓 + 0x53B2, KANJI_SJIS_L3, // 厲 + 0x53DD, KANJI_SJIS_L3, // 叝 + 0xFA0E, KANJI_SJIS_L3, //  + 0x549C, KANJI_SJIS_L3, // 咜 + 0x548A, KANJI_SJIS_L3, // 咊 + 0x54A9, KANJI_SJIS_L3, // 咩 + 0x54FF, KANJI_SJIS_L3, // 哿 + 0x5586, KANJI_SJIS_L3, // 喆 + 0x5759, KANJI_SJIS_L3, // 坙 + 0x5765, KANJI_SJIS_L3, // 坥 + 0x57AC, KANJI_SJIS_L3, // 垬 + 0x57C8, KANJI_SJIS_L3, // 埈 + 0x57C7, KANJI_SJIS_L3, // 埇 + 0xFA0F, KANJI_SJIS_L3, //  + 0x3000, KANJI_SJIS_L3, //   + 0xFA10, KANJI_SJIS_L3, //  + 0x589E, KANJI_SJIS_L3, // 增 + 0x58B2, KANJI_SJIS_L3, // 墲 + 0x590B, KANJI_SJIS_L3, // 個 + 0x5953, KANJI_SJIS_L3, // 奓 + 0x595B, KANJI_SJIS_L3, // 奛 + 0x595D, KANJI_SJIS_L3, // 奝 + 0x5963, KANJI_SJIS_L3, // 奣 + 0x59A4, KANJI_SJIS_L3, // 劀 + 0x59BA, KANJI_SJIS_L3, // 劺 + 0x5B56, KANJI_SJIS_L3, // 孖 + 0x5BC0, KANJI_SJIS_L3, // 寀 + 0x752F, KANJI_SJIS_L3, // 甯 + 0x5BD8, KANJI_SJIS_L3, // 寘 + 0x5BEC, KANJI_SJIS_L3, // 寬 + 0x5C1E, KANJI_SJIS_L3, // 尞 + 0x5CA6, KANJI_SJIS_L3, // 岊 + 0x5CBA, KANJI_SJIS_L3, // 岺 + 0x5CF5, KANJI_SJIS_L3, // å³µ + 0x5D27, KANJI_SJIS_L3, // 厧 + 0x5D53, KANJI_SJIS_L3, // 嵓 + 0xFA11, KANJI_SJIS_L3, // ïš‘ + 0x5D42, KANJI_SJIS_L3, // 嵂 + 0x5D6D, KANJI_SJIS_L3, // åµ­ + 0x5DB8, KANJI_SJIS_L3, // å¶ž + 0x5DB9, KANJI_SJIS_L3, // å¶¹ + 0x5DD0, KANJI_SJIS_L3, // 巐 + 0x5F21, KANJI_SJIS_L3, // 匡 + 0x5F34, KANJI_SJIS_L3, // 匎 + 0x5F67, KANJI_SJIS_L3, // 圧 + 0x5FB7, KANJI_SJIS_L3, // 執 + 0x5FDE, KANJI_SJIS_L3, // 忞 + 0x605D, KANJI_SJIS_L3, // 恝 + 0x6085, KANJI_SJIS_L3, // 悅 + 0x608A, KANJI_SJIS_L3, // 悊 + 0x60DE, KANJI_SJIS_L3, // 惞 + 0x60D5, KANJI_SJIS_L3, // 惕 + 0x6120, KANJI_SJIS_L3, // 愠 + 0x60F2, KANJI_SJIS_L3, // 惲 + 0x6111, KANJI_SJIS_L3, // 愑 + 0x6137, KANJI_SJIS_L3, // 愷 + 0x6130, KANJI_SJIS_L3, // 愰 + 0x6198, KANJI_SJIS_L3, // 憘 + 0x6213, KANJI_SJIS_L3, // 戓 + 0x62A6, KANJI_SJIS_L3, // 把 + 0x63F5, KANJI_SJIS_L3, // 揵 + 0x6460, KANJI_SJIS_L3, // 摠 + 0x649D, KANJI_SJIS_L3, // 撝 + 0x64CE, KANJI_SJIS_L3, // 擎 + 0x654E, KANJI_SJIS_L3, // 敎 + 0x6600, KANJI_SJIS_L3, // 昀 + 0x6615, KANJI_SJIS_L3, // 昕 + 0x663B, KANJI_SJIS_L3, // 昻 + 0x6609, KANJI_SJIS_L3, // 昉 + 0x662E, KANJI_SJIS_L3, // 昮 + 0x661E, KANJI_SJIS_L3, // 昞 + 0x6624, KANJI_SJIS_L3, // 昀 + 0x6665, KANJI_SJIS_L3, // 晥 + 0x6657, KANJI_SJIS_L3, // 晗 + 0x6659, KANJI_SJIS_L3, // 晙 + 0xFA12, KANJI_SJIS_L3, // ïš’ + 0x6673, KANJI_SJIS_L3, // 晳 + 0x6699, KANJI_SJIS_L3, // 暙 + 0x66A0, KANJI_SJIS_L3, // 暠 + 0x66B2, KANJI_SJIS_L3, // 暲 + 0x66BF, KANJI_SJIS_L3, // 暿 + 0x66FA, KANJI_SJIS_L3, // 曺 + 0x670E, KANJI_SJIS_L3, // 朎 + 0xF929, KANJI_SJIS_L3, //  + 0x6766, KANJI_SJIS_L3, // 杊 + 0x67BB, KANJI_SJIS_L3, // 枻 + 0x6852, KANJI_SJIS_L3, // 桒 + 0x67C0, KANJI_SJIS_L3, // 柀 + 0x6801, KANJI_SJIS_L3, // 栁 + 0x6844, KANJI_SJIS_L3, // 桄 + 0x68CF, KANJI_SJIS_L3, // 棏 + 0xFA13, KANJI_SJIS_L3, // ïš“ + 0x6968, KANJI_SJIS_L3, // 楚 + 0xFA14, KANJI_SJIS_L3, // ïš” + 0x6998, KANJI_SJIS_L3, // 折 + 0x69E2, KANJI_SJIS_L3, // æ§¢ + 0x6A30, KANJI_SJIS_L3, // æš° + 0x6A6B, KANJI_SJIS_L3, // æ©« + 0x6A46, KANJI_SJIS_L3, // 橆 + 0x6A73, KANJI_SJIS_L3, // 橳 + 0x6A7E, KANJI_SJIS_L3, // 機 + 0x6AE2, KANJI_SJIS_L3, // æ«¢ + 0x6AE4, KANJI_SJIS_L3, // æ«€ + 0x6BD6, KANJI_SJIS_L3, // 毖 + 0x6C3F, KANJI_SJIS_L3, // æ°¿ + 0x6C5C, KANJI_SJIS_L3, // 汜 + 0x6C86, KANJI_SJIS_L3, // 沆 + 0x6C6F, KANJI_SJIS_L3, // 汯 + 0x6CDA, KANJI_SJIS_L3, // 泚 + 0x6D04, KANJI_SJIS_L3, // 掄 + 0x6D87, KANJI_SJIS_L3, // 涇 + 0x6D6F, KANJI_SJIS_L3, // 浯 + 0x6D96, KANJI_SJIS_L3, // 涖 + 0x6DAC, KANJI_SJIS_L3, // 涬 + 0x6DCF, KANJI_SJIS_L3, // 淏 + 0x6DF8, KANJI_SJIS_L3, // æ·ž + 0x6DF2, KANJI_SJIS_L3, // æ·² + 0x6DFC, KANJI_SJIS_L3, // æ·Œ + 0x6E39, KANJI_SJIS_L3, // æž¹ + 0x6E5C, KANJI_SJIS_L3, // 湜 + 0x6E27, KANJI_SJIS_L3, // æž§ + 0x6E3C, KANJI_SJIS_L3, // 枌 + 0x6EBF, KANJI_SJIS_L3, // 溿 + 0x6F88, KANJI_SJIS_L3, // 柈 + 0x6FB5, KANJI_SJIS_L3, // 柵 + 0x6FF5, KANJI_SJIS_L3, // 濵 + 0x7005, KANJI_SJIS_L3, // 瀅 + 0x7007, KANJI_SJIS_L3, // 瀇 + 0x7028, KANJI_SJIS_L3, // 瀹 + 0x7085, KANJI_SJIS_L3, // 炅 + 0x70AB, KANJI_SJIS_L3, // 炫 + 0x710F, KANJI_SJIS_L3, // 焏 + 0x7104, KANJI_SJIS_L3, // 焄 + 0x715C, KANJI_SJIS_L3, // 煜 + 0x7146, KANJI_SJIS_L3, // 煆 + 0x7147, KANJI_SJIS_L3, // 煇 + 0xFA15, KANJI_SJIS_L3, // ïš• + 0x71C1, KANJI_SJIS_L3, // 燁 + 0x71FE, KANJI_SJIS_L3, // 營 + 0x72B1, KANJI_SJIS_L3, // 犱 + 0x72BE, KANJI_SJIS_L3, // 犟 + 0x7324, KANJI_SJIS_L3, // 猀 + 0xFA16, KANJI_SJIS_L3, // ïš– + 0x7377, KANJI_SJIS_L3, // 獷 + 0x73BD, KANJI_SJIS_L3, // 玜 + 0x73C9, KANJI_SJIS_L3, // 珉 + 0x73D6, KANJI_SJIS_L3, // 珖 + 0x73E3, KANJI_SJIS_L3, // 珣 + 0x73D2, KANJI_SJIS_L3, // 珒 + 0x7407, KANJI_SJIS_L3, // 琇 + 0x73F5, KANJI_SJIS_L3, // 珵 + 0x7426, KANJI_SJIS_L3, // 琊 + 0x742A, KANJI_SJIS_L3, // 琪 + 0x7429, KANJI_SJIS_L3, // 琩 + 0x742E, KANJI_SJIS_L3, // 琮 + 0x7462, KANJI_SJIS_L3, // 瑢 + 0x7489, KANJI_SJIS_L3, // 璉 + 0x749F, KANJI_SJIS_L3, // 璟 + 0x7501, KANJI_SJIS_L3, // 甁 + 0x756F, KANJI_SJIS_L3, // 畯 + 0x7682, KANJI_SJIS_L3, // 皂 + 0x769C, KANJI_SJIS_L3, // 皜 + 0x769E, KANJI_SJIS_L3, // 皞 + 0x769B, KANJI_SJIS_L3, // 皛 + 0x76A6, KANJI_SJIS_L3, // 皩 + 0xFA17, KANJI_SJIS_L3, // ïš— + 0x7746, KANJI_SJIS_L3, // 睆 + 0x52AF, KANJI_SJIS_L3, // 劯 + 0x7821, KANJI_SJIS_L3, // ç ¡ + 0x784E, KANJI_SJIS_L3, // 硎 + 0x7864, KANJI_SJIS_L3, // ç¡€ + 0x787A, KANJI_SJIS_L3, // 硺 + 0x7930, KANJI_SJIS_L3, // 瀰 + 0xFA18, KANJI_SJIS_L3, //  + 0xFA19, KANJI_SJIS_L3, // ïš™ + 0xFA1A, KANJI_SJIS_L3, // ïšš + 0x7994, KANJI_SJIS_L3, // 穔 + 0xFA1B, KANJI_SJIS_L3, // ïš› + 0x799B, KANJI_SJIS_L3, // 穛 + 0x7AD1, KANJI_SJIS_L3, // 竑 + 0x7AE7, KANJI_SJIS_L3, // ç«§ + 0xFA1C, KANJI_SJIS_L3, // ïšœ + 0x7AEB, KANJI_SJIS_L3, // ç«« + 0x7B9E, KANJI_SJIS_L3, // 箞 + 0xFA1D, KANJI_SJIS_L3, //  + 0x7D48, KANJI_SJIS_L3, // 絈 + 0x7D5C, KANJI_SJIS_L3, // 絜 + 0x7DB7, KANJI_SJIS_L3, // ç¶· + 0x7DA0, KANJI_SJIS_L3, // ç¶  + 0x7DD6, KANJI_SJIS_L3, // 緖 + 0x7E52, KANJI_SJIS_L3, // 繒 + 0x7F47, KANJI_SJIS_L3, // 眇 + 0x7FA1, KANJI_SJIS_L3, // 矡 + 0xFA1E, KANJI_SJIS_L3, //  + 0x8301, KANJI_SJIS_L3, // 茁 + 0x8362, KANJI_SJIS_L3, // 荢 + 0x837F, KANJI_SJIS_L3, // 荿 + 0x83C7, KANJI_SJIS_L3, // 菇 + 0x83F6, KANJI_SJIS_L3, // 菶 + 0x8448, KANJI_SJIS_L3, // 葈 + 0x84B4, KANJI_SJIS_L3, // è’Ž + 0x8553, KANJI_SJIS_L3, // 蕓 + 0x8559, KANJI_SJIS_L3, // 蕙 + 0x3000, KANJI_SJIS_L3, //   + 0x856B, KANJI_SJIS_L3, // 蕫 + 0xFA1F, KANJI_SJIS_L3, //  + 0x85B0, KANJI_SJIS_L3, // 薰 + 0xFA20, KANJI_SJIS_L3, // ïš  + 0xFA21, KANJI_SJIS_L3, // ïš¡ + 0x8807, KANJI_SJIS_L3, // 蠇 + 0x88F5, KANJI_SJIS_L3, // 裵 + 0x8A12, KANJI_SJIS_L3, // èš’ + 0x8A37, KANJI_SJIS_L3, // èš· + 0x8A79, KANJI_SJIS_L3, // 詹 + 0x8AA7, KANJI_SJIS_L3, // 誧 + 0x8ABE, KANJI_SJIS_L3, // 誟 + 0x8ADF, KANJI_SJIS_L3, // 諟 + 0xFA22, KANJI_SJIS_L3, //  + 0x8AF6, KANJI_SJIS_L3, // è«¶ + 0x8B53, KANJI_SJIS_L3, // 譓 + 0x8B7F, KANJI_SJIS_L3, // è­¿ + 0x8CF0, KANJI_SJIS_L3, // è³° + 0x8CF4, KANJI_SJIS_L3, // 賎 + 0x8D12, KANJI_SJIS_L3, // 莒 + 0x8D76, KANJI_SJIS_L3, // èµ¶ + 0xFA23, KANJI_SJIS_L3, //  + 0x8ECF, KANJI_SJIS_L3, // 軏 + 0xFA24, KANJI_SJIS_L3, //  + 0xFA25, KANJI_SJIS_L3, //  + 0x9067, KANJI_SJIS_L3, // 遧 + 0x90DE, KANJI_SJIS_L3, // 郞 + 0xFA26, KANJI_SJIS_L3, //  + 0x9115, KANJI_SJIS_L3, // 鄕 + 0x9127, KANJI_SJIS_L3, // 鄧 + 0x91DA, KANJI_SJIS_L3, // 釚 + 0x91D7, KANJI_SJIS_L3, // 釗 + 0x91DE, KANJI_SJIS_L3, // 釞 + 0x91ED, KANJI_SJIS_L3, // 釭 + 0x91EE, KANJI_SJIS_L3, // 釮 + 0x91E4, KANJI_SJIS_L3, // 釀 + 0x91E5, KANJI_SJIS_L3, // 釥 + 0x9206, KANJI_SJIS_L3, // 鈆 + 0x9210, KANJI_SJIS_L3, // 鈐 + 0x920A, KANJI_SJIS_L3, // 鈊 + 0x923A, KANJI_SJIS_L3, // 鈺 + 0x9240, KANJI_SJIS_L3, // 鉀 + 0x923C, KANJI_SJIS_L3, // 鈌 + 0x924E, KANJI_SJIS_L3, // 鉎 + 0x9259, KANJI_SJIS_L3, // 鉙 + 0x9251, KANJI_SJIS_L3, // 鉑 + 0x9239, KANJI_SJIS_L3, // 鈹 + 0x9267, KANJI_SJIS_L3, // 鉧 + 0x92A7, KANJI_SJIS_L3, // 銧 + 0x9277, KANJI_SJIS_L3, // 鉷 + 0x9278, KANJI_SJIS_L3, // 鉾 + 0x92E7, KANJI_SJIS_L3, // 鋧 + 0x92D7, KANJI_SJIS_L3, // 鋗 + 0x92D9, KANJI_SJIS_L3, // 鋙 + 0x92D0, KANJI_SJIS_L3, // 鋐 + 0xFA27, KANJI_SJIS_L3, // ïš§ + 0x92D5, KANJI_SJIS_L3, // 鋕 + 0x92E0, KANJI_SJIS_L3, // 鋠 + 0x92D3, KANJI_SJIS_L3, // 鋓 + 0x9325, KANJI_SJIS_L3, // 錥 + 0x9321, KANJI_SJIS_L3, // 錡 + 0x92FB, KANJI_SJIS_L3, // 鋻 + 0xFA28, KANJI_SJIS_L3, // ïšš + 0x931E, KANJI_SJIS_L3, // 錞 + 0x92FF, KANJI_SJIS_L3, // 鋿 + 0x931D, KANJI_SJIS_L3, // 錝 + 0x9302, KANJI_SJIS_L3, // 錂 + 0x9370, KANJI_SJIS_L3, // 鍰 + 0x9357, KANJI_SJIS_L3, // 鍗 + 0x93A4, KANJI_SJIS_L3, // 鎀 + 0x93C6, KANJI_SJIS_L3, // 鏆 + 0x93DE, KANJI_SJIS_L3, // 鏞 + 0x93F8, KANJI_SJIS_L3, // 鏞 + 0x9431, KANJI_SJIS_L3, // 鐱 + 0x9445, KANJI_SJIS_L3, // 鑅 + 0x9448, KANJI_SJIS_L3, // 鑈 + 0x9592, KANJI_SJIS_L3, // 閒 + 0xF9DC, KANJI_SJIS_L3, // 隆 + 0xFA29, KANJI_SJIS_L3, // ïš© + 0x969D, KANJI_SJIS_L3, // 隝 + 0x96AF, KANJI_SJIS_L3, // 隯 + 0x9733, KANJI_SJIS_L3, // 霳 + 0x973B, KANJI_SJIS_L3, // 霻 + 0x9743, KANJI_SJIS_L3, // 靃 + 0x974D, KANJI_SJIS_L3, // 靍 + 0x974F, KANJI_SJIS_L3, // 靏 + 0x9751, KANJI_SJIS_L3, // 靑 + 0x9755, KANJI_SJIS_L3, // 靕 + 0x9857, KANJI_SJIS_L3, // 顗 + 0x9865, KANJI_SJIS_L3, // é¡¥ + 0xFA2A, KANJI_SJIS_L3, //  + 0xFA2B, KANJI_SJIS_L3, // ïš« + 0x9927, KANJI_SJIS_L3, // 逧 + 0xFA2C, KANJI_SJIS_L3, //  + 0x999E, KANJI_SJIS_L3, // 銞 + 0x9A4E, KANJI_SJIS_L3, // 驎 + 0x9AD9, KANJI_SJIS_L3, // 髙 + 0x9ADC, KANJI_SJIS_L3, // 髜 + 0x9B75, KANJI_SJIS_L3, // é­µ + 0x9B72, KANJI_SJIS_L3, // é­² + 0x9B8F, KANJI_SJIS_L3, // 鮏 + 0x9BB1, KANJI_SJIS_L3, // é®± + 0x9BBB, KANJI_SJIS_L3, // é®» + 0x9C00, KANJI_SJIS_L3, // 鰀 + 0x9D70, KANJI_SJIS_L3, // éµ° + 0x9D6B, KANJI_SJIS_L3, // 鵫 + 0xFA2D, KANJI_SJIS_L3, // ïš­ + 0x9E19, KANJI_SJIS_L3, // 龙 + 0x9ED1, KANJI_SJIS_L3, // 黑 + 0x7E8A, KANJI_SJIS_L3, // 纊 + 0x891C, KANJI_SJIS_L3, // 耜 + 0x9348, KANJI_SJIS_L3, // 鍈 + 0x9288, KANJI_SJIS_L3, // 銈 + 0x84DC, KANJI_SJIS_L3, // 蓜 + 0x4FC9, KANJI_SJIS_L3, // 俉 + 0x70BB, KANJI_SJIS_L3, // 炻 + 0x6631, KANJI_SJIS_L3, // 昱 + 0x68C8, KANJI_SJIS_L3, // 棈 + 0x92F9, KANJI_SJIS_L3, // 鋹 + 0x66FB, KANJI_SJIS_L3, // 曻 + 0x5F45, KANJI_SJIS_L3, // 圅 + 0x4E28, KANJI_SJIS_L3, // äžš + 0x4EE1, KANJI_SJIS_L3, // 仡 + 0x4EFC, KANJI_SJIS_L3, // 仌 + 0x4F00, KANJI_SJIS_L3, // 䌀 + 0x4F03, KANJI_SJIS_L3, // 䌃 + 0x4F39, KANJI_SJIS_L3, // 䌹 + 0x4F56, KANJI_SJIS_L3, // 䜖 + 0x4F92, KANJI_SJIS_L3, // 䟒 + 0x4F8A, KANJI_SJIS_L3, // 䟊 + 0x4F9A, KANJI_SJIS_L3, // 䟚 + 0x4F94, KANJI_SJIS_L3, // 䟔 + 0x4FCD, KANJI_SJIS_L3, // 俍 + 0x5040, KANJI_SJIS_L3, // 偀 + 0x5022, KANJI_SJIS_L3, // 倢 + 0x4FFF, KANJI_SJIS_L3, // ä¿¿ + 0x501E, KANJI_SJIS_L3, // 倞 + 0x5046, KANJI_SJIS_L3, // 偆 + 0x5070, KANJI_SJIS_L3, // 偰 + 0x5042, KANJI_SJIS_L3, // 偂 + 0x5094, KANJI_SJIS_L3, // 傔 + 0x50F4, KANJI_SJIS_L3, // 僎 + 0x50D8, KANJI_SJIS_L3, // 僘 + 0x514A, KANJI_SJIS_L3, // 兊 + 0x3000, KANJI_SJIS_L3, //   + 0x5164, KANJI_SJIS_L3, // å…€ + 0x519D, KANJI_SJIS_L3, // 冝 + 0x51BE, KANJI_SJIS_L3, // 冟 + 0x51EC, KANJI_SJIS_L3, // 凬 + 0x5215, KANJI_SJIS_L3, // 刕 + 0x529C, KANJI_SJIS_L3, // 劜 + 0x52A6, KANJI_SJIS_L3, // 劊 + 0x52C0, KANJI_SJIS_L3, // 勀 + 0x52DB, KANJI_SJIS_L3, // 勛 + 0x5300, KANJI_SJIS_L3, // 匀 + 0x5307, KANJI_SJIS_L3, // 匇 + 0x5324, KANJI_SJIS_L3, // 匀 + 0x5372, KANJI_SJIS_L3, // 卲 + 0x5393, KANJI_SJIS_L3, // 厓 + 0x53B2, KANJI_SJIS_L3, // 厲 + 0x53DD, KANJI_SJIS_L3, // 叝 + 0xFA0E, KANJI_SJIS_L3, //  + 0x549C, KANJI_SJIS_L3, // 咜 + 0x548A, KANJI_SJIS_L3, // 咊 + 0x54A9, KANJI_SJIS_L3, // 咩 + 0x54FF, KANJI_SJIS_L3, // 哿 + 0x5586, KANJI_SJIS_L3, // 喆 + 0x5759, KANJI_SJIS_L3, // 坙 + 0x5765, KANJI_SJIS_L3, // 坥 + 0x57AC, KANJI_SJIS_L3, // 垬 + 0x57C8, KANJI_SJIS_L3, // 埈 + 0x57C7, KANJI_SJIS_L3, // 埇 + 0xFA0F, KANJI_SJIS_L3, //  + 0xFA10, KANJI_SJIS_L3, //  + 0x589E, KANJI_SJIS_L3, // 增 + 0x58B2, KANJI_SJIS_L3, // 墲 + 0x590B, KANJI_SJIS_L3, // 個 + 0x5953, KANJI_SJIS_L3, // 奓 + 0x595B, KANJI_SJIS_L3, // 奛 + 0x595D, KANJI_SJIS_L3, // 奝 + 0x5963, KANJI_SJIS_L3, // 奣 + 0x59A4, KANJI_SJIS_L3, // 劀 + 0x59BA, KANJI_SJIS_L3, // 劺 + 0x5B56, KANJI_SJIS_L3, // 孖 + 0x5BC0, KANJI_SJIS_L3, // 寀 + 0x752F, KANJI_SJIS_L3, // 甯 + 0x5BD8, KANJI_SJIS_L3, // 寘 + 0x5BEC, KANJI_SJIS_L3, // 寬 + 0x5C1E, KANJI_SJIS_L3, // 尞 + 0x5CA6, KANJI_SJIS_L3, // 岊 + 0x5CBA, KANJI_SJIS_L3, // 岺 + 0x5CF5, KANJI_SJIS_L3, // å³µ + 0x5D27, KANJI_SJIS_L3, // 厧 + 0x5D53, KANJI_SJIS_L3, // 嵓 + 0xFA11, KANJI_SJIS_L3, // ïš‘ + 0x5D42, KANJI_SJIS_L3, // 嵂 + 0x5D6D, KANJI_SJIS_L3, // åµ­ + 0x5DB8, KANJI_SJIS_L3, // å¶ž + 0x5DB9, KANJI_SJIS_L3, // å¶¹ + 0x5DD0, KANJI_SJIS_L3, // 巐 + 0x5F21, KANJI_SJIS_L3, // 匡 + 0x5F34, KANJI_SJIS_L3, // 匎 + 0x5F67, KANJI_SJIS_L3, // 圧 + 0x5FB7, KANJI_SJIS_L3, // 執 + 0x5FDE, KANJI_SJIS_L3, // 忞 + 0x605D, KANJI_SJIS_L3, // 恝 + 0x6085, KANJI_SJIS_L3, // 悅 + 0x608A, KANJI_SJIS_L3, // 悊 + 0x60DE, KANJI_SJIS_L3, // 惞 + 0x60D5, KANJI_SJIS_L3, // 惕 + 0x6120, KANJI_SJIS_L3, // 愠 + 0x60F2, KANJI_SJIS_L3, // 惲 + 0x6111, KANJI_SJIS_L3, // 愑 + 0x6137, KANJI_SJIS_L3, // 愷 + 0x6130, KANJI_SJIS_L3, // 愰 + 0x6198, KANJI_SJIS_L3, // 憘 + 0x6213, KANJI_SJIS_L3, // 戓 + 0x62A6, KANJI_SJIS_L3, // 把 + 0x63F5, KANJI_SJIS_L3, // 揵 + 0x6460, KANJI_SJIS_L3, // 摠 + 0x649D, KANJI_SJIS_L3, // 撝 + 0x64CE, KANJI_SJIS_L3, // 擎 + 0x654E, KANJI_SJIS_L3, // 敎 + 0x6600, KANJI_SJIS_L3, // 昀 + 0x6615, KANJI_SJIS_L3, // 昕 + 0x663B, KANJI_SJIS_L3, // 昻 + 0x6609, KANJI_SJIS_L3, // 昉 + 0x662E, KANJI_SJIS_L3, // 昮 + 0x661E, KANJI_SJIS_L3, // 昞 + 0x6624, KANJI_SJIS_L3, // 昀 + 0x6665, KANJI_SJIS_L3, // 晥 + 0x6657, KANJI_SJIS_L3, // 晗 + 0x6659, KANJI_SJIS_L3, // 晙 + 0xFA12, KANJI_SJIS_L3, // ïš’ + 0x6673, KANJI_SJIS_L3, // 晳 + 0x6699, KANJI_SJIS_L3, // 暙 + 0x66A0, KANJI_SJIS_L3, // 暠 + 0x66B2, KANJI_SJIS_L3, // 暲 + 0x66BF, KANJI_SJIS_L3, // 暿 + 0x66FA, KANJI_SJIS_L3, // 曺 + 0x670E, KANJI_SJIS_L3, // 朎 + 0xF929, KANJI_SJIS_L3, //  + 0x6766, KANJI_SJIS_L3, // 杊 + 0x67BB, KANJI_SJIS_L3, // 枻 + 0x6852, KANJI_SJIS_L3, // 桒 + 0x67C0, KANJI_SJIS_L3, // 柀 + 0x6801, KANJI_SJIS_L3, // 栁 + 0x6844, KANJI_SJIS_L3, // 桄 + 0x68CF, KANJI_SJIS_L3, // 棏 + 0xFA13, KANJI_SJIS_L3, // ïš“ + 0x6968, KANJI_SJIS_L3, // 楚 + 0xFA14, KANJI_SJIS_L3, // ïš” + 0x6998, KANJI_SJIS_L3, // 折 + 0x69E2, KANJI_SJIS_L3, // æ§¢ + 0x6A30, KANJI_SJIS_L3, // æš° + 0x6A6B, KANJI_SJIS_L3, // æ©« + 0x6A46, KANJI_SJIS_L3, // 橆 + 0x6A73, KANJI_SJIS_L3, // 橳 + 0x6A7E, KANJI_SJIS_L3, // 機 + 0x6AE2, KANJI_SJIS_L3, // æ«¢ + 0x6AE4, KANJI_SJIS_L3, // æ«€ + 0x6BD6, KANJI_SJIS_L3, // 毖 + 0x6C3F, KANJI_SJIS_L3, // æ°¿ + 0x6C5C, KANJI_SJIS_L3, // 汜 + 0x6C86, KANJI_SJIS_L3, // 沆 + 0x6C6F, KANJI_SJIS_L3, // 汯 + 0x6CDA, KANJI_SJIS_L3, // 泚 + 0x6D04, KANJI_SJIS_L3, // 掄 + 0x6D87, KANJI_SJIS_L3, // 涇 + 0x6D6F, KANJI_SJIS_L3, // 浯 + 0x6D96, KANJI_SJIS_L3, // 涖 + 0x6DAC, KANJI_SJIS_L3, // 涬 + 0x6DCF, KANJI_SJIS_L3, // 淏 + 0x6DF8, KANJI_SJIS_L3, // æ·ž + 0x6DF2, KANJI_SJIS_L3, // æ·² + 0x6DFC, KANJI_SJIS_L3, // æ·Œ + 0x6E39, KANJI_SJIS_L3, // æž¹ + 0x6E5C, KANJI_SJIS_L3, // 湜 + 0x6E27, KANJI_SJIS_L3, // æž§ + 0x6E3C, KANJI_SJIS_L3, // 枌 + 0x6EBF, KANJI_SJIS_L3, // 溿 + 0x6F88, KANJI_SJIS_L3, // 柈 + 0x6FB5, KANJI_SJIS_L3, // 柵 + 0x6FF5, KANJI_SJIS_L3, // 濵 + 0x7005, KANJI_SJIS_L3, // 瀅 + 0x7007, KANJI_SJIS_L3, // 瀇 + 0x7028, KANJI_SJIS_L3, // 瀹 + 0x7085, KANJI_SJIS_L3, // 炅 + 0x70AB, KANJI_SJIS_L3, // 炫 + 0x710F, KANJI_SJIS_L3, // 焏 + 0x7104, KANJI_SJIS_L3, // 焄 + 0x715C, KANJI_SJIS_L3, // 煜 + 0x7146, KANJI_SJIS_L3, // 煆 + 0x7147, KANJI_SJIS_L3, // 煇 + 0xFA15, KANJI_SJIS_L3, // ïš• + 0x71C1, KANJI_SJIS_L3, // 燁 + 0x71FE, KANJI_SJIS_L3, // 營 + 0x72B1, KANJI_SJIS_L3, // 犱 + 0x72BE, KANJI_SJIS_L3, // 犟 + 0x7324, KANJI_SJIS_L3, // 猀 + 0xFA16, KANJI_SJIS_L3, // ïš– + 0x7377, KANJI_SJIS_L3, // 獷 + 0x73BD, KANJI_SJIS_L3, // 玜 + 0x73C9, KANJI_SJIS_L3, // 珉 + 0x73D6, KANJI_SJIS_L3, // 珖 + 0x73E3, KANJI_SJIS_L3, // 珣 + 0x73D2, KANJI_SJIS_L3, // 珒 + 0x7407, KANJI_SJIS_L3, // 琇 + 0x73F5, KANJI_SJIS_L3, // 珵 + 0x7426, KANJI_SJIS_L3, // 琊 + 0x742A, KANJI_SJIS_L3, // 琪 + 0x7429, KANJI_SJIS_L3, // 琩 + 0x742E, KANJI_SJIS_L3, // 琮 + 0x7462, KANJI_SJIS_L3, // 瑢 + 0x7489, KANJI_SJIS_L3, // 璉 + 0x749F, KANJI_SJIS_L3, // 璟 + 0x7501, KANJI_SJIS_L3, // 甁 + 0x756F, KANJI_SJIS_L3, // 畯 + 0x7682, KANJI_SJIS_L3, // 皂 + 0x769C, KANJI_SJIS_L3, // 皜 + 0x769E, KANJI_SJIS_L3, // 皞 + 0x769B, KANJI_SJIS_L3, // 皛 + 0x76A6, KANJI_SJIS_L3, // 皩 + 0xFA17, KANJI_SJIS_L3, // ïš— + 0x7746, KANJI_SJIS_L3, // 睆 + 0x52AF, KANJI_SJIS_L3, // 劯 + 0x7821, KANJI_SJIS_L3, // ç ¡ + 0x784E, KANJI_SJIS_L3, // 硎 + 0x7864, KANJI_SJIS_L3, // ç¡€ + 0x787A, KANJI_SJIS_L3, // 硺 + 0x7930, KANJI_SJIS_L3, // 瀰 + 0xFA18, KANJI_SJIS_L3, //  + 0xFA19, KANJI_SJIS_L3, // ïš™ + 0x3000, KANJI_SJIS_L3, //   + 0xFA1A, KANJI_SJIS_L3, // ïšš + 0x7994, KANJI_SJIS_L3, // 穔 + 0xFA1B, KANJI_SJIS_L3, // ïš› + 0x799B, KANJI_SJIS_L3, // 穛 + 0x7AD1, KANJI_SJIS_L3, // 竑 + 0x7AE7, KANJI_SJIS_L3, // ç«§ + 0xFA1C, KANJI_SJIS_L3, // ïšœ + 0x7AEB, KANJI_SJIS_L3, // ç«« + 0x7B9E, KANJI_SJIS_L3, // 箞 + 0xFA1D, KANJI_SJIS_L3, //  + 0x7D48, KANJI_SJIS_L3, // 絈 + 0x7D5C, KANJI_SJIS_L3, // 絜 + 0x7DB7, KANJI_SJIS_L3, // ç¶· + 0x7DA0, KANJI_SJIS_L3, // ç¶  + 0x7DD6, KANJI_SJIS_L3, // 緖 + 0x7E52, KANJI_SJIS_L3, // 繒 + 0x7F47, KANJI_SJIS_L3, // 眇 + 0x7FA1, KANJI_SJIS_L3, // 矡 + 0xFA1E, KANJI_SJIS_L3, //  + 0x8301, KANJI_SJIS_L3, // 茁 + 0x8362, KANJI_SJIS_L3, // 荢 + 0x837F, KANJI_SJIS_L3, // 荿 + 0x83C7, KANJI_SJIS_L3, // 菇 + 0x83F6, KANJI_SJIS_L3, // 菶 + 0x8448, KANJI_SJIS_L3, // 葈 + 0x84B4, KANJI_SJIS_L3, // è’Ž + 0x8553, KANJI_SJIS_L3, // 蕓 + 0x8559, KANJI_SJIS_L3, // 蕙 + 0x856B, KANJI_SJIS_L3, // 蕫 + 0xFA1F, KANJI_SJIS_L3, //  + 0x85B0, KANJI_SJIS_L3, // 薰 + 0xFA20, KANJI_SJIS_L3, // ïš  + 0xFA21, KANJI_SJIS_L3, // ïš¡ + 0x8807, KANJI_SJIS_L3, // 蠇 + 0x88F5, KANJI_SJIS_L3, // 裵 + 0x8A12, KANJI_SJIS_L3, // èš’ + 0x8A37, KANJI_SJIS_L3, // èš· + 0x8A79, KANJI_SJIS_L3, // 詹 + 0x8AA7, KANJI_SJIS_L3, // 誧 + 0x8ABE, KANJI_SJIS_L3, // 誟 + 0x8ADF, KANJI_SJIS_L3, // 諟 + 0xFA22, KANJI_SJIS_L3, //  + 0x8AF6, KANJI_SJIS_L3, // è«¶ + 0x8B53, KANJI_SJIS_L3, // 譓 + 0x8B7F, KANJI_SJIS_L3, // è­¿ + 0x8CF0, KANJI_SJIS_L3, // è³° + 0x8CF4, KANJI_SJIS_L3, // 賎 + 0x8D12, KANJI_SJIS_L3, // 莒 + 0x8D76, KANJI_SJIS_L3, // èµ¶ + 0xFA23, KANJI_SJIS_L3, //  + 0x8ECF, KANJI_SJIS_L3, // 軏 + 0xFA24, KANJI_SJIS_L3, //  + 0xFA25, KANJI_SJIS_L3, //  + 0x9067, KANJI_SJIS_L3, // 遧 + 0x90DE, KANJI_SJIS_L3, // 郞 + 0xFA26, KANJI_SJIS_L3, //  + 0x9115, KANJI_SJIS_L3, // 鄕 + 0x9127, KANJI_SJIS_L3, // 鄧 + 0x91DA, KANJI_SJIS_L3, // 釚 + 0x91D7, KANJI_SJIS_L3, // 釗 + 0x91DE, KANJI_SJIS_L3, // 釞 + 0x91ED, KANJI_SJIS_L3, // 釭 + 0x91EE, KANJI_SJIS_L3, // 釮 + 0x91E4, KANJI_SJIS_L3, // 釀 + 0x91E5, KANJI_SJIS_L3, // 釥 + 0x9206, KANJI_SJIS_L3, // 鈆 + 0x9210, KANJI_SJIS_L3, // 鈐 + 0x920A, KANJI_SJIS_L3, // 鈊 + 0x923A, KANJI_SJIS_L3, // 鈺 + 0x9240, KANJI_SJIS_L3, // 鉀 + 0x923C, KANJI_SJIS_L3, // 鈌 + 0x924E, KANJI_SJIS_L3, // 鉎 + 0x9259, KANJI_SJIS_L3, // 鉙 + 0x9251, KANJI_SJIS_L3, // 鉑 + 0x9239, KANJI_SJIS_L3, // 鈹 + 0x9267, KANJI_SJIS_L3, // 鉧 + 0x92A7, KANJI_SJIS_L3, // 銧 + 0x9277, KANJI_SJIS_L3, // 鉷 + 0x9278, KANJI_SJIS_L3, // 鉾 + 0x92E7, KANJI_SJIS_L3, // 鋧 + 0x92D7, KANJI_SJIS_L3, // 鋗 + 0x92D9, KANJI_SJIS_L3, // 鋙 + 0x92D0, KANJI_SJIS_L3, // 鋐 + 0xFA27, KANJI_SJIS_L3, // ïš§ + 0x92D5, KANJI_SJIS_L3, // 鋕 + 0x92E0, KANJI_SJIS_L3, // 鋠 + 0x92D3, KANJI_SJIS_L3, // 鋓 + 0x9325, KANJI_SJIS_L3, // 錥 + 0x9321, KANJI_SJIS_L3, // 錡 + 0x92FB, KANJI_SJIS_L3, // 鋻 + 0xFA28, KANJI_SJIS_L3, // ïšš + 0x931E, KANJI_SJIS_L3, // 錞 + 0x9357, KANJI_SJIS_L3, // 鍗 + 0x93A4, KANJI_SJIS_L3, // 鎀 + 0x93C6, KANJI_SJIS_L3, // 鏆 + 0x93DE, KANJI_SJIS_L3, // 鏞 + 0x93F8, KANJI_SJIS_L3, // 鏞 + 0x9431, KANJI_SJIS_L3, // 鐱 + 0x9445, KANJI_SJIS_L3, // 鑅 + 0x9448, KANJI_SJIS_L3, // 鑈 + 0x9592, KANJI_SJIS_L3, // 閒 + 0xF9DC, KANJI_SJIS_L3, // 隆 + 0xFA29, KANJI_SJIS_L3, // ïš© + 0x969D, KANJI_SJIS_L3, // 隝 + 0x96AF, KANJI_SJIS_L3, // 隯 + 0x9733, KANJI_SJIS_L3, // 霳 + 0x973B, KANJI_SJIS_L3, // 霻 + 0x9743, KANJI_SJIS_L3, // 靃 + 0x974D, KANJI_SJIS_L3, // 靍 + 0x974F, KANJI_SJIS_L3, // 靏 + 0x9751, KANJI_SJIS_L3, // 靑 + 0x9755, KANJI_SJIS_L3, // 靕 + 0x9857, KANJI_SJIS_L3, // 顗 + 0x9865, KANJI_SJIS_L3, // é¡¥ + 0xFA2A, KANJI_SJIS_L3, //  + 0xFA2B, KANJI_SJIS_L3, // ïš« + 0x9927, KANJI_SJIS_L3, // 逧 + 0xFA2C, KANJI_SJIS_L3, //  + 0x999E, KANJI_SJIS_L3, // 銞 + 0x9A4E, KANJI_SJIS_L3, // 驎 + 0x9AD9, KANJI_SJIS_L3, // 髙 + 0x9ADC, KANJI_SJIS_L3, // 髜 + 0x9B75, KANJI_SJIS_L3, // é­µ + 0x9B72, KANJI_SJIS_L3, // é­² + 0x9B8F, KANJI_SJIS_L3, // 鮏 + 0x9BB1, KANJI_SJIS_L3, // é®± + 0x9BBB, KANJI_SJIS_L3, // é®» + 0x9C00, KANJI_SJIS_L3, // 鰀 + 0x9D70, KANJI_SJIS_L3, // éµ° + 0x9D6B, KANJI_SJIS_L3, // 鵫 + 0xFA2D, KANJI_SJIS_L3, // ïš­ + 0x9E19, KANJI_SJIS_L3, // 龙 + 0x9ED1, KANJI_SJIS_L3, // 黑 }; \ No newline at end of file From 8f29b167653adf185bb3a1bbc3d726f5fc4bddaf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 5 May 2013 15:01:57 -0700 Subject: [PATCH 0388/1445] Fix compilation errors in 32-bit debug. --- math/lin/aabb.cpp | 2 +- native.vcxproj | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/math/lin/aabb.cpp b/math/lin/aabb.cpp index 6a04ddab14..eb9ca9088a 100644 --- a/math/lin/aabb.cpp +++ b/math/lin/aabb.cpp @@ -74,7 +74,7 @@ bool AABB::IntersectRay(const Ray &ray, float &tnear, float &tfar) const { // Possible orientation of the splitting plane in the interior node of the kd-tree, -// ”No axis” denotes a leaf. +// "No axis" denotes a leaf. enum Axes { Xaxis, diff --git a/native.vcxproj b/native.vcxproj index 18f197eb4f..805dff1e02 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -79,6 +79,7 @@ Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ProgramDatabase Windows From 30802a1120b9c2d9a4e4d17d2b1a539e9684332c Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 6 May 2013 23:56:41 +1000 Subject: [PATCH 0389/1445] Buildfix and improvements to Pandora --- base/PCMain.cpp | 63 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 803b24f242..62c2a19364 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -36,22 +36,34 @@ #include "net/resolve.h" -#ifdef MAEMO +#if defined(MAEMO) || defined(PANDORA) #define EGL -#endif - -#ifdef PANDORA -#define EGL -#endif - -#ifdef EGL #include "EGL/egl.h" #include #include #include "SDL_syswm.h" +#include "math.h" + +#ifdef PANDORA SDL_Joystick *ljoy = NULL; SDL_Joystick *rjoy = NULL; +void enable_runfast() +{ + static const unsigned int x = 0x04086060; + static const unsigned int y = 0x03000000; + int r; + asm volatile ( + "fmrx %0, fpscr \n\t" //r0 = FPSCR + "and %0, %0, %1 \n\t" //r0 = r0 & 0x04086060 + "orr %0, %0, %2 \n\t" //r0 = r0 | 0x03000000 + "fmxr fpscr, %0 \n\t" //FPSCR = r0 + : "=r"(r) + : "r"(x), "r"(y) + ); +} +#endif + EGLDisplay g_eglDisplay = NULL; EGLContext g_eglContext = NULL; EGLSurface g_eglSurface = NULL; @@ -91,8 +103,12 @@ int8_t CheckEGLErrors(const std::string& file, uint16_t line) { } int8_t EGL_Open() { +#ifdef PANDORA + g_Display = EGL_DEFAULT_DISPLAY; +#else if ((g_Display = XOpenDisplay(NULL)) == NULL) EGL_ERROR("Unable to get display!", false); +#endif if ((g_eglDisplay = eglGetDisplay((NativeDisplayType)g_Display)) == EGL_NO_DISPLAY) EGL_ERROR("Unable to create EGL display.", true); if (eglInitialize(g_eglDisplay, NULL, NULL) != EGL_TRUE) @@ -136,12 +152,17 @@ int8_t EGL_Init() { return 1; } +#ifdef PANDORA + g_Window = (NativeWindowType)NULL; +#else g_Window = (NativeWindowType)sysInfo.info.x11.window; +#endif g_eglSurface = eglCreateWindowSurface(g_eglDisplay, g_eglConfig, g_Window, 0); if (g_eglSurface == EGL_NO_SURFACE) EGL_ERROR("Unable to create EGL surface!", true); if (eglMakeCurrent(g_eglDisplay, g_eglSurface, g_eglSurface, g_eglContext) != EGL_TRUE) EGL_ERROR("Unable to make GLES context current.", true); + return 0; } @@ -250,7 +271,11 @@ const int buttonMappings[14] = { SDLK_DOWN, //DOWN SDLK_LEFT, //LEFT SDLK_RIGHT, //RIGHT +#ifdef PANDORA + SDLK_SPACE, //MENU +#else SDLK_m, //MENU +#endif SDLK_BACKSPACE, //BACK }; @@ -269,12 +294,12 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { if ((ljoy)||(rjoy)) { SDL_JoystickUpdate(); if (ljoy) { - input->pad_lstick_x = SDL_JoystickGetAxis(ljoy, 0) / 32768.0f; - input->pad_lstick_y = SDL_JoystickGetAxis(ljoy, 1) / 32768.0f; + input->pad_lstick_x = max(min(SDL_JoystickGetAxis(ljoy, 0) / 32000.0f, 1.0f, -1.0f); + input->pad_lstick_y = max(min(-SDL_JoystickGetAxis(ljoy, 1) / 32000.0f, 1.0f, -1.0f); } if (rjoy) { - input->pad_rstick_x = SDL_JoystickGetAxis(rjoy, 0) / 32768.0f; - input->pad_rstick_y = SDL_JoystickGetAxis(rjoy, 1) / 32768.0f; + input->pad_rstick_x = max(min(SDL_JoystickGetAxis(rjoy, 0) / 32000.0f, 1.0f, -1.0f); + input->pad_rstick_y = max(min(SDL_JoystickGetAxis(rjoy, 1) / 32000.0f, 1.0f, -1.0f); } } #else @@ -368,7 +393,7 @@ int main(int argc, char *argv[]) { //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); #endif - if (SDL_Init(SDL_INIT_VIDEO) < 0) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } @@ -479,13 +504,11 @@ int main(int argc, char *argv[]) { // Joysticks init, we the nubs if setup as Joystick int numjoys = SDL_NumJoysticks(); if (numjoys>0) - for (int i=0; i1) rjoy=SDL_JoystickOpen(1); + } + enable_runfast(); // VFPv2 RunFast #endif int framecount = 0; From f9ab24cb3de114f05769267fd7c3e50882eaa5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 May 2013 23:29:48 +0200 Subject: [PATCH 0390/1445] define changes for mac from vit6969. --- .gitignore | 1 + thread/prioritizedworkqueue.cpp | 2 +- thread/threadpool.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f7708b4298..2f3dc5a3ff 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ Debug *.vcxproj.user android/.settings local.properties +.DS_Store diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index 997f835cfb..746c3fb3c6 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -4,7 +4,7 @@ #include "thread/thread.h" #include "thread/prioritizedworkqueue.h" -#if defined(IOS) || (defined(__APPLE__) && !defined(__MAC_10_7)) +#if defined(IOS) || defined(MACGNUSTD) #include namespace std { using tr1::bind; diff --git a/thread/threadpool.h b/thread/threadpool.h index e89c93e8cd..d7d427cb49 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -15,7 +15,7 @@ using namespace std; #endif #include -#if defined(__SYMBIAN32__) || defined(IOS) || (defined(__APPLE__) && !defined(__MAC_10_7)) +#if defined(__SYMBIAN32__) || defined(IOS) || defined(MACGNUSTD) #ifndef __SYMBIAN32__ #include #include From 78ba6209747e8ad78538df7b3b83479454e9a0f3 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 8 May 2013 21:21:02 +1000 Subject: [PATCH 0391/1445] Improve input on Blackberry Q10 keyboard. --- base/BlackberryMain.cpp | 47 ++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index e586618318..a84ba92194 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -101,25 +101,25 @@ void LaunchEmail(const char *email_address) InputState input_state; // Input -const int buttonMappings[18] = { - KEYCODE_X, //A - KEYCODE_S, //B - KEYCODE_Z, //X - KEYCODE_A, //Y +const unsigned int buttonMappings[18] = { + KEYCODE_K, //Cross + KEYCODE_L, //Circle + KEYCODE_J, //Square + KEYCODE_I, //Triangle KEYCODE_Q, //LBUMPER - KEYCODE_W, //RBUMPER - KEYCODE_ONE, //START - KEYCODE_TWO, //SELECT - KEYCODE_UP, //UP - KEYCODE_DOWN, //DOWN - KEYCODE_LEFT, //LEFT - KEYCODE_RIGHT, //RIGHT + KEYCODE_P, //RBUMPER + KEYCODE_SPACE, //START + KEYCODE_ZERO, //SELECT + KEYCODE_W, //UP + KEYCODE_S, //DOWN + KEYCODE_A, //LEFT + KEYCODE_D, //RIGHT 0, //MENU (SwipeDown) KEYCODE_BACKSPACE, //BACK - KEYCODE_I, //JOY UP - KEYCODE_K, //JOY DOWN - KEYCODE_J, //JOY LEFT - KEYCODE_L, //JOY RIGHT + KEYCODE_W, //JOY UP + KEYCODE_S, //JOY DOWN + KEYCODE_A, //JOY LEFT + KEYCODE_D, //JOY RIGHT }; void SimulateGamepad(InputState *input) { @@ -360,7 +360,7 @@ int main(int argc, char *argv[]) { static screen_context_t screen_cxt; // Receive events from window manager screen_create_context(&screen_cxt, 0); - //Initialise Blackberry Platform Services + // Initialise Blackberry Platform Services bps_initialize(); // TODO: Enable/disable based on setting #ifdef BLACKBERRY10 @@ -452,15 +452,11 @@ int main(int argc, char *argv[]) { int flags, value; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value); - if (flags & (KEY_DOWN | KEY_SYM_VALID)) { - for (int b = 0; b < 14; b++) { - if (value == buttonMappings[b]) + for (int b = 0; b < 14; b++) { + if (value == buttonMappings[b] & 0xFF) { + if (flags & KEY_DOWN) pad_buttons |= (1< Date: Thu, 9 May 2013 00:27:18 +1000 Subject: [PATCH 0392/1445] Blackberry: Save settings when killed by OS. Clear menu key after use. --- base/BlackberryMain.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index a84ba92194..ab6b4db3f2 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -470,7 +470,8 @@ int main(int argc, char *argv[]) { pad_buttons |= PAD_BUTTON_MENU; break; case NAVIGATOR_EXIT: - running = false; + NativeShutdown(); + exit(0); break; } #ifdef BLACKBERRY10 @@ -492,6 +493,7 @@ int main(int argc, char *argv[]) { } } input_state.pad_buttons = pad_buttons; + pad_buttons &= ~PAD_BUTTON_MENU; #ifndef BLACKBERRY10 // Handle accelerometer double x, y, z; From 2078efcb17dbc96931f103ce68d72be2ea4d295a Mon Sep 17 00:00:00 2001 From: Steven Cherry Date: Mon, 13 May 2013 20:04:09 -0500 Subject: [PATCH 0393/1445] Change tab to Unthrottle --- input/input_state.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/input/input_state.h b/input/input_state.h index 6c7191269f..aca6708331 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -29,6 +29,8 @@ enum { PAD_BUTTON_LEFT_THUMB = 1 << 18, // Click left thumb stick on X360 PAD_BUTTON_RIGHT_THUMB = 1 << 19, // Click right thumb stick on X360 + PAD_BUTTON_UNTHROTTLE = 1 << 20, // Click Tab to unthrottle + }; #ifndef MAX_POINTERS From f6dd98570bc65b83d6674aab66fee0b00730b012 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 16 May 2013 13:50:30 +1000 Subject: [PATCH 0394/1445] Be like other emulators on Blackberry and use the 'misc' dir. --- base/BlackberryMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index ab6b4db3f2..83b9f8f1bf 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -390,7 +390,7 @@ int main(int argc, char *argv[]) { if (pixel_xres == 720) dpi_scale *= 1.4; dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); - NativeInit(argc, (const char **)argv, "/accounts/1000/shared/documents/", "data/", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "data/", "BADCOFFEE"); NativeInitGraphics(); screen_request_events(screen_cxt); navigator_request_events(0); From 5bcf145f887cdce092fc9207709d8f9eccc3fa8b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 20 May 2013 00:54:49 +0200 Subject: [PATCH 0395/1445] Add Mersenne Twister random number generator --- input/input_state.h | 1 - util/random/rng.h | 45 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/input/input_state.h b/input/input_state.h index aca6708331..37bacd460e 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -30,7 +30,6 @@ enum { PAD_BUTTON_LEFT_THUMB = 1 << 18, // Click left thumb stick on X360 PAD_BUTTON_RIGHT_THUMB = 1 << 19, // Click right thumb stick on X360 PAD_BUTTON_UNTHROTTLE = 1 << 20, // Click Tab to unthrottle - }; #ifndef MAX_POINTERS diff --git a/util/random/rng.h b/util/random/rng.h index fbc125bc46..d1355f8cac 100644 --- a/util/random/rng.h +++ b/util/random/rng.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "base/basictypes.h" @@ -24,7 +24,48 @@ public: return (float)R32() / (float)(0xFFFFFFFF); } -private: + // public for easy save/load. Yes a bit ugly but better than moving DoState into native. uint32 m_w; uint32 m_z; }; + + +// Data must consist only of the index and the twister array. This matches the PSP +// MT context exactly. +class MersenneTwister { +public: + MersenneTwister(uint32_t seed) : index_(0) { + mt_[0] = seed; + for (uint32_t i = 1; i < MT_SIZE; i++) + mt_[i] = (1812433253 * (mt_[i - 1] ^ (mt_[i - 1] >> 30)) + i); + } + + uint32_t R32() { + if (index_ == 0) + gen(); + uint32_t y = mt_[index_]; + y ^= y >> 11; + y ^= (y << 7) & 2636928640; + y ^= (y << 15) & 4022730752; + y ^= y >> 18; + index_ = (index_ + 1) % MT_SIZE; + return y; + } + +private: + enum { + MT_SIZE = 624, + }; + + uint32_t index_; + uint32_t mt_[MT_SIZE]; + + void gen() { + for(uint32_t i = 0; i < MT_SIZE; i++){ + uint32_t y = (mt_[i] & 0x80000000) + (mt_[(i + 1) % MT_SIZE] & 0x80000000); + mt_[i] = mt_[(i + 397) % MT_SIZE] ^ (y >> 1); + if (y % 2) mt_[i] ^= 2567483615; + } + return; + } +}; From a6dc54e67872a5783d23dbe82d96a2dae6949ae1 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 20 May 2013 22:43:18 +1000 Subject: [PATCH 0396/1445] Remove Playbook OS support. Remove the #ifdef's for BB10. Switch asound to OpenAL (which is included in BB10). Fixes some glitches with sound. --- base/BlackberryMain.cpp | 232 ++++++++++++---------------------------- 1 file changed, 68 insertions(+), 164 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 83b9f8f1bf..887f5383e2 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -8,16 +8,14 @@ #include #include -#include -#include +#include +#include #include #include #include #include -#include "base/display.h" -#include "base/logging.h" #include "base/timeutil.h" #include "gfx_es2/glsl_program.h" #include "file/zip_read.h" @@ -31,16 +29,10 @@ #include // Blackberry Window Manager #include // Invoke Service #include // Keyboard Service -#ifdef BLACKBERRY10 #include // Accelerometer -#else -#include // Accelerometer -#endif #include #include // Dialog Service (Toast=BB10) -#ifdef BLACKBERRY10 #include // Vibrate Service (BB10) -#endif EGLDisplay egl_disp; EGLSurface egl_surf; @@ -55,15 +47,11 @@ static screen_display_t screen_disp; // Simple implementations of System functions void SystemToast(const char *text) { -#ifdef BLACKBERRY10 dialog_instance_t dialog = 0; dialog_create_toast(&dialog); dialog_set_toast_message_text(dialog, text); dialog_set_toast_position(dialog, DIALOG_POSITION_TOP_CENTER); dialog_show(dialog); -#else - puts(text); -#endif } void ShowAd(int x, int y, bool center_x) { @@ -75,9 +63,7 @@ void ShowKeyboard() { } void Vibrate(int length_ms) { -#ifdef BLACKBERRY10 vibration_request(VIBRATION_INTENSITY_LOW, 500 /* intensity (1-100), duration (ms) */); -#endif } void LaunchBrowser(const char *url) @@ -163,10 +149,8 @@ int init_GLES2(screen_context_t ctx) { screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage); screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp); - // This must be landscape. int screen_resolution[2]; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution); - int angle = atoi(getenv("ORIENTATION")); pixel_xres = screen_resolution[0]; pixel_yres = screen_resolution[1]; screen_display_mode_t screen_mode; @@ -177,25 +161,29 @@ int init_GLES2(screen_context_t ctx) { int buffer_size[2] = {size[0], size[1]}; - if ((angle == 0) || (angle == 180)) { - if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) || - ((screen_mode.width < screen_mode.height) && (size[0] > size[1]))) { - buffer_size[1] = size[0]; - buffer_size[0] = size[1]; - pixel_yres = screen_resolution[0]; - pixel_xres = screen_resolution[1]; - } - } else if ((angle == 90) || (angle == 270)){ - if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) || - ((screen_mode.width < screen_mode.height && size[0] < size[1]))) { - buffer_size[1] = size[0]; - buffer_size[0] = size[1]; - pixel_yres = screen_resolution[0]; - pixel_xres = screen_resolution[1]; + // This must be landscape, unless 1:1. + if (pixel_xres != pixel_yres) { + int angle = atoi(getenv("ORIENTATION")); + if ((angle == 0) || (angle == 180)) { + if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) || + ((screen_mode.width < screen_mode.height) && (size[0] > size[1]))) { + buffer_size[1] = size[0]; + buffer_size[0] = size[1]; + pixel_yres = screen_resolution[0]; + pixel_xres = screen_resolution[1]; + } + } else if ((angle == 90) || (angle == 270)){ + if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) || + ((screen_mode.width < screen_mode.height && size[0] < size[1]))) { + buffer_size[1] = size[0]; + buffer_size[0] = size[1]; + pixel_yres = screen_resolution[0]; + pixel_xres = screen_resolution[1]; + } } + screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size); + screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle); } - screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size); - screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle); screen_create_window_buffers(screen_win, 2); // Double buffered egl_disp = eglGetDisplay(EGL_DEFAULT_DISPLAY); @@ -234,125 +222,73 @@ void kill_GLES2() { } // Audio -#define AUDIO_CHANNELS 2 -#define AUDIO_FREQ 44100 -#define AUDIO_SAMPLES 1024 +#define SAMPLE_SIZE 44100 class BlackberryAudio { public: BlackberryAudio() { - paused = false; - OpenAudio(); + alcDevice = alcOpenDevice(NULL); + if (alContext = alcCreateContext(alcDevice, NULL)) + alcMakeContextCurrent(alContext); + alGenSources(1, &source); + alGenBuffers(1, &buffer); + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&thread_handle, &attr, &BlackberryAudio::staticThreadProc, this); } ~BlackberryAudio() { pthread_cancel(thread_handle); - snd_pcm_plugin_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK); - snd_mixer_close(mixer_handle); - snd_pcm_close(pcm_handle); - free(mixer_handle); - free(pcm_handle); - } - void setPaused(bool pause) - { - paused = pause; + alcMakeContextCurrent(NULL); + if (alContext) + { + alcDestroyContext(alContext); + alContext = NULL; + } + if (alcDevice) + { + alcCloseDevice(alcDevice); + alcDevice = NULL; + } } static void* staticThreadProc(void* arg) { return reinterpret_cast(arg)->RunAudio(); } private: - void OpenAudio() - { - int card = -1, dev = 0; - - snd_pcm_channel_info_t pi; - snd_mixer_group_t group; - snd_pcm_channel_params_t pp; - snd_pcm_channel_setup_t setup; - - mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; - mixbuf = (uint8_t*)malloc(mixlen); - if (mixbuf == NULL) - return; - memset(mixbuf, 0, mixlen); - - if ((snd_pcm_open_preferred(&pcm_handle, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0) - return; - - memset(&pi, 0, sizeof (pi)); - pi.channel = SND_PCM_CHANNEL_PLAYBACK; - if ((snd_pcm_plugin_info (pcm_handle, &pi)) < 0) - return; - - memset(&pp, 0, sizeof (pp)); - pp.mode = SND_PCM_MODE_BLOCK; - pp.channel = SND_PCM_CHANNEL_PLAYBACK; - pp.start_mode = SND_PCM_START_FULL; - pp.stop_mode = SND_PCM_STOP_STOP; - - pp.buf.block.frag_size = pi.max_fragment_size; - pp.buf.block.frags_max = -1; - pp.buf.block.frags_min = 1; - - pp.format.interleave = 1; - pp.format.rate = AUDIO_FREQ; - pp.format.voices = AUDIO_CHANNELS; - pp.format.format = SND_PCM_SFMT_S16_LE; - - if ((snd_pcm_plugin_params (pcm_handle, &pp)) < 0) - return; - - snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK); - - memset (&setup, 0, sizeof(setup)); - memset (&group, 0, sizeof(group)); - setup.channel = SND_PCM_CHANNEL_PLAYBACK; - setup.mixer_gid = &group.gid; - if ((snd_pcm_plugin_setup (pcm_handle, &setup)) < 0) - return; - setup.buf.block.frag_size; - if ((snd_mixer_open(&mixer_handle, card, setup.mixer_device)) < 0) - return; - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&thread_handle, &attr, &BlackberryAudio::staticThreadProc, this); - } void* RunAudio() { while(true) { - if (!paused) + size_t frames_ready; + alGetSourcei(source, AL_SOURCE_STATE, &state); + if (state != AL_PLAYING) + frames_ready = NativeMix(stream, SAMPLE_SIZE / 2); + else + frames_ready = 0; + if (frames_ready > 0) { - memset(mixbuf, 0, mixlen); - NativeMix((short *)mixbuf, mixlen / 4); - - fd_set rfds, wfds; - int nflds; - if (FD_ISSET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds)) - { - snd_pcm_plugin_write(pcm_handle, mixbuf, mixlen); - } - FD_ZERO(&rfds); - FD_ZERO(&wfds); - - FD_SET(snd_mixer_file_descriptor(mixer_handle), &rfds); - FD_SET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds); - nflds = std::max(snd_mixer_file_descriptor(mixer_handle), snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK)); - select (nflds+1, &rfds, &wfds, NULL, NULL); + const size_t bytes_ready = frames_ready * sizeof(short) * 2; + alSourcei(source, AL_BUFFER, 0); + alBufferData(buffer, AL_FORMAT_STEREO16, stream, bytes_ready, SAMPLE_SIZE); + alSourcei(source, AL_BUFFER, buffer); + alSourcePlay(source); + // TODO: Maybe this could get behind? + usleep((1000000 * frames_ready) / SAMPLE_SIZE); } else - delay((AUDIO_SAMPLES*1000)/AUDIO_FREQ); + usleep(100); } } - snd_pcm_t* pcm_handle; - snd_mixer_t* mixer_handle; - int mixlen; - uint8_t* mixbuf; + ALCdevice *alcDevice; + ALCcontext *alContext; + ALenum state; + ALuint buffer; + ALuint source; + short stream[SAMPLE_SIZE]; pthread_t thread_handle; - bool paused; }; // Entry Point @@ -363,31 +299,17 @@ int main(int argc, char *argv[]) { // Initialise Blackberry Platform Services bps_initialize(); // TODO: Enable/disable based on setting -#ifdef BLACKBERRY10 sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, 25000); sensor_request_events(SENSOR_TYPE_ACCELEROMETER); -#else - accelerometer_set_update_frequency(FREQ_40_HZ); -#endif net::Init(); init_GLES2(screen_cxt); -#ifdef BLACKBERRY10 - // Dev Alpha: 1280x768, 4.2", 356DPI, 0.6f scale + // Z10: 1280x768, 4.2", 356DPI, 0.6f scale + // Q10: 720x720, 3.1", 328DPI, 0.65f*1.4f=0.91f scale int dpi; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_DPI, &dpi); -#else - // Playbook: 1024x600, 7", 170DPI, 1.25f scale - int screen_phys_size[2]; - screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_PHYSICAL_SIZE, screen_phys_size); - int screen_resolution[2]; - screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution); - double diagonal_pixels = sqrt((double)(screen_resolution[0] * screen_resolution[0] + screen_resolution[1] * screen_resolution[1])); - double diagonal_inches = 0.0393700787 * sqrt((double)(screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1])); - int dpi = (int)(diagonal_pixels / diagonal_inches + 0.5); -#endif float dpi_scale = 213.6f / dpi; - if (pixel_xres == 720) dpi_scale *= 1.4; + if (pixel_xres == pixel_yres) dpi_scale *= 1.4; dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "data/", "BADCOFFEE"); @@ -395,9 +317,7 @@ int main(int argc, char *argv[]) { screen_request_events(screen_cxt); navigator_request_events(0); dialog_request_events(0); -#ifdef BLACKBERRY10 vibration_request_events(0); -#endif static int pad_buttons = 0; BlackberryAudio* audio = new BlackberryAudio(); bool running = true; @@ -474,7 +394,6 @@ int main(int argc, char *argv[]) { exit(0); break; } -#ifdef BLACKBERRY10 } else if (domain == sensor_get_domain()) { if (SENSOR_ACCELEROMETER_READING == bps_event_get_code(event)) { float x, y, z; @@ -489,25 +408,10 @@ int main(int argc, char *argv[]) { } input_state.acc.z = z; } -#endif } } input_state.pad_buttons = pad_buttons; pad_buttons &= ~PAD_BUTTON_MENU; -#ifndef BLACKBERRY10 - // Handle accelerometer - double x, y, z; - accelerometer_read_forces(&x, &y, &z); - if (pixel_xres == 1024 || pixel_xres == 720) // Playbook has this reversed - { - input_state.acc.x = y; - input_state.acc.y = x; - } else { - input_state.acc.x = x; - input_state.acc.y = y; - } - input_state.acc.z = z; -#endif UpdateInputState(&input_state); NativeUpdate(input_state); EndInputState(&input_state); From 6c3a381781953d567c6ea449af445a959736c78c Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 21 May 2013 23:46:12 +1000 Subject: [PATCH 0397/1445] Remove code that is redundant for Blackberry 10. --- base/BlackberryMain.cpp | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 887f5383e2..5abd32d92f 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -149,41 +149,9 @@ int init_GLES2(screen_context_t ctx) { screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage); screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp); - int screen_resolution[2]; - screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution); - pixel_xres = screen_resolution[0]; pixel_yres = screen_resolution[1]; - - screen_display_mode_t screen_mode; - screen_get_display_property_pv(screen_disp, SCREEN_PROPERTY_MODE, (void**)&screen_mode); - - int size[2]; - screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size); - - int buffer_size[2] = {size[0], size[1]}; - - // This must be landscape, unless 1:1. - if (pixel_xres != pixel_yres) { - int angle = atoi(getenv("ORIENTATION")); - if ((angle == 0) || (angle == 180)) { - if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) || - ((screen_mode.width < screen_mode.height) && (size[0] > size[1]))) { - buffer_size[1] = size[0]; - buffer_size[0] = size[1]; - pixel_yres = screen_resolution[0]; - pixel_xres = screen_resolution[1]; - } - } else if ((angle == 90) || (angle == 270)){ - if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) || - ((screen_mode.width < screen_mode.height && size[0] < size[1]))) { - buffer_size[1] = size[0]; - buffer_size[0] = size[1]; - pixel_yres = screen_resolution[0]; - pixel_xres = screen_resolution[1]; - } - } - screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size); - screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle); - } + pixel_xres = atoi(getenv("WIDTH")); pixel_yres = atoi(getenv("HEIGHT")); + int size[2] = { pixel_xres, pixel_yres }; + screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size); screen_create_window_buffers(screen_win, 2); // Double buffered egl_disp = eglGetDisplay(EGL_DEFAULT_DISPLAY); From cc80e0292f4c8479d4d143fe4cdc7f00bf73111e Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 22 May 2013 01:30:43 +1000 Subject: [PATCH 0398/1445] Add controller/gamepad support to Blackberry 10. --- base/BlackberryMain.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 5abd32d92f..15d70c7726 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -286,7 +286,7 @@ int main(int argc, char *argv[]) { navigator_request_events(0); dialog_request_events(0); vibration_request_events(0); - static int pad_buttons = 0; + static int pad_buttons = 0, controller_buttons = 0; BlackberryAudio* audio = new BlackberryAudio(); bool running = true; while (running) { @@ -349,6 +349,18 @@ int main(int argc, char *argv[]) { } } break; + // Gamepad + case SCREEN_EVENT_GAMEPAD: + case SCREEN_EVENT_JOYSTICK: + int buttons; + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); + // Map the buttons integer to our mappings + controller_buttons = (buttons & (SCREEN_A_GAME_BUTTON | SCREEN_B_GAME_BUTTON)) | + (buttons & (SCREEN_X_GAME_BUTTON | SCREEN_Y_GAME_BUTTON)) >> 1 | + (buttons & (SCREEN_MENU1_GAME_BUTTON | SCREEN_MENU2_GAME_BUTTON)) | + (buttons & SCREEN_L1_GAME_BUTTON) >> 6 | (buttons & SCREEN_R1_GAME_BUTTON) >> 8 | + (buttons & (SCREEN_DPAD_UP_GAME_BUTTON | SCREEN_DPAD_DOWN_GAME_BUTTON | SCREEN_DPAD_LEFT_GAME_BUTTON | SCREEN_DPAD_RIGHT_GAME_BUTTON)) >> 8; + break; } } else if (domain == navigator_get_domain()) { switch(bps_event_get_code(event)) @@ -378,7 +390,7 @@ int main(int argc, char *argv[]) { } } } - input_state.pad_buttons = pad_buttons; + input_state.pad_buttons = pad_buttons | controller_buttons; pad_buttons &= ~PAD_BUTTON_MENU; UpdateInputState(&input_state); NativeUpdate(input_state); From 42e5c184c25edcc471e477db4acc6eecf0f350cc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 22 May 2013 11:04:14 +0200 Subject: [PATCH 0399/1445] Warning fix --- util/random/rng.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/random/rng.h b/util/random/rng.h index d1355f8cac..89e0808deb 100644 --- a/util/random/rng.h +++ b/util/random/rng.h @@ -37,7 +37,7 @@ public: MersenneTwister(uint32_t seed) : index_(0) { mt_[0] = seed; for (uint32_t i = 1; i < MT_SIZE; i++) - mt_[i] = (1812433253 * (mt_[i - 1] ^ (mt_[i - 1] >> 30)) + i); + mt_[i] = (1812433253UL * (mt_[i - 1] ^ (mt_[i - 1] >> 30)) + i); } uint32_t R32() { @@ -45,8 +45,8 @@ public: gen(); uint32_t y = mt_[index_]; y ^= y >> 11; - y ^= (y << 7) & 2636928640; - y ^= (y << 15) & 4022730752; + y ^= (y << 7) & 2636928640UL; + y ^= (y << 15) & 4022730752UL; y ^= y >> 18; index_ = (index_ + 1) % MT_SIZE; return y; @@ -64,7 +64,7 @@ private: for(uint32_t i = 0; i < MT_SIZE; i++){ uint32_t y = (mt_[i] & 0x80000000) + (mt_[(i + 1) % MT_SIZE] & 0x80000000); mt_[i] = mt_[(i + 397) % MT_SIZE] ^ (y >> 1); - if (y % 2) mt_[i] ^= 2567483615; + if (y % 2) mt_[i] ^= 2567483615UL; } return; } From dfe03d3d978063a6a56ce7a82e572b045fead14e Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 23 May 2013 18:20:53 +1000 Subject: [PATCH 0400/1445] Blackberry: Improve Wiimote key mappings. Also, map dpad to analog. --- base/BlackberryMain.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 15d70c7726..f70b985dc5 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -353,13 +353,22 @@ int main(int argc, char *argv[]) { case SCREEN_EVENT_GAMEPAD: case SCREEN_EVENT_JOYSTICK: int buttons; + char device_id[16]; + screen_device_t device; + screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DEVICE, (void**)&device); + screen_get_device_property_cv(device, SCREEN_PROPERTY_ID_STRING, sizeof(device_id), device_id); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); // Map the buttons integer to our mappings - controller_buttons = (buttons & (SCREEN_A_GAME_BUTTON | SCREEN_B_GAME_BUTTON)) | - (buttons & (SCREEN_X_GAME_BUTTON | SCREEN_Y_GAME_BUTTON)) >> 1 | - (buttons & (SCREEN_MENU1_GAME_BUTTON | SCREEN_MENU2_GAME_BUTTON)) | - (buttons & SCREEN_L1_GAME_BUTTON) >> 6 | (buttons & SCREEN_R1_GAME_BUTTON) >> 8 | - (buttons & (SCREEN_DPAD_UP_GAME_BUTTON | SCREEN_DPAD_DOWN_GAME_BUTTON | SCREEN_DPAD_LEFT_GAME_BUTTON | SCREEN_DPAD_RIGHT_GAME_BUTTON)) >> 8; + if (strstr(device_id, "057E-0306")) // Wiimote + controller_buttons = (buttons & (SCREEN_A_GAME_BUTTON | SCREEN_B_GAME_BUTTON)) << 2 | + (buttons & (SCREEN_X_GAME_BUTTON | SCREEN_Y_GAME_BUTTON)) >> 3; + else + controller_buttons = (buttons & (SCREEN_A_GAME_BUTTON | SCREEN_B_GAME_BUTTON)) | + (buttons & (SCREEN_X_GAME_BUTTON | SCREEN_Y_GAME_BUTTON)) >> 1; + controller_buttons |= (buttons & (SCREEN_MENU1_GAME_BUTTON | SCREEN_MENU2_GAME_BUTTON)) | + (buttons & SCREEN_L1_GAME_BUTTON) >> 6 | (buttons & SCREEN_R1_GAME_BUTTON) >> 8 | + (buttons & (SCREEN_DPAD_UP_GAME_BUTTON | SCREEN_DPAD_DOWN_GAME_BUTTON | SCREEN_DPAD_LEFT_GAME_BUTTON | SCREEN_DPAD_RIGHT_GAME_BUTTON)) >> 8 | + (buttons & (SCREEN_DPAD_UP_GAME_BUTTON | SCREEN_DPAD_DOWN_GAME_BUTTON | SCREEN_DPAD_LEFT_GAME_BUTTON | SCREEN_DPAD_RIGHT_GAME_BUTTON)) >> 2; break; } } else if (domain == navigator_get_domain()) { From 8b7576327530e18432a4c7f090ca122d06b9b633 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 3 May 2013 00:21:39 +0200 Subject: [PATCH 0401/1445] WIP new UI layout system! --- android/app-android.cpp | 852 ++++++++++++++--------------- base/NativeApp.h | 194 ++++--- base/PCMain.cpp | 21 +- base/display.h | 24 +- base/scoped_ptr.h | 3 +- gfx_es2/draw_buffer.cpp | 16 +- gfx_es2/draw_buffer.h | 3 +- input/gesture_detector.cpp | 131 +++-- input/gesture_detector.h | 64 ++- input/input_state.h | 18 + native.vcxproj | 728 ++++++++++++------------- native.vcxproj.filters | 1048 ++++++++++++++++++------------------ ui/screen.cpp | 350 ++++++------ ui/screen.h | 228 ++++---- ui/view.cpp | 193 +++++++ ui/view.h | 416 ++++++++++++++ ui/viewgroup.cpp | 274 ++++++++++ ui/viewgroup.h | 110 ++++ 18 files changed, 2868 insertions(+), 1805 deletions(-) create mode 100644 ui/view.cpp create mode 100644 ui/view.h create mode 100644 ui/viewgroup.cpp create mode 100644 ui/viewgroup.h diff --git a/android/app-android.cpp b/android/app-android.cpp index d893aeb6b9..2a9314899a 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -1,424 +1,428 @@ -// This is generic code that is included in all Android apps that use the -// Native framework by Henrik Rydgård (https://github.com/hrydgard/native). - -// It calls a set of methods defined in NativeApp.h. These should be implemented -// by your game or app. - -#include -#include -#include -#include -#include -#include - -#include "base/basictypes.h" -#include "base/display.h" -#include "base/NativeApp.h" -#include "base/logging.h" -#include "base/timeutil.h" -#include "file/zip_read.h" -#include "input/input_state.h" -#include "audio/mixer.h" -#include "math/math_util.h" -#include "net/resolve.h" -#include "android/native_audio.h" -#include "gfx_es2/gl_state.h" - -// For Xperia Play support -enum AndroidKeyCodes { - KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed - KEYCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed - KEYCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) - KEYCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed - KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed - KEYCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed - KEYCODE_DPAD_LEFT = 21, - KEYCODE_DPAD_UP = 19, - KEYCODE_DPAD_RIGHT = 22, - KEYCODE_DPAD_DOWN = 20, - KEYCODE_BUTTON_L1 = 102, - KEYCODE_BUTTON_R1 = 103, - KEYCODE_BUTTON_START = 108, - KEYCODE_BUTTON_SELECT = 109, -}; - -static JNIEnv *jniEnvUI; - -std::string frameCommand; -std::string frameCommandParam; - -const bool extraLog = true; - -static uint32_t pad_buttons_async_set; -static uint32_t pad_buttons_async_clear; -static float left_joystick_x_async; -static float left_joystick_y_async; - -static uint32_t pad_buttons_down; - -// Android implementation of callbacks to the Java part of the app -void SystemToast(const char *text) { - frameCommand = "toast"; - frameCommandParam = text; -} - -// TODO: need a Hide or bool show; -void ShowAd(int x, int y, bool center_x) { - ELOG("TODO! ShowAd!"); -} - -void ShowKeyboard() { - frameCommand = "showKeyboard"; - frameCommandParam = ""; -} - -void Vibrate(int length_ms) { - frameCommand = "vibrate"; - frameCommandParam = "100"; -} - -void LaunchBrowser(const char *url) { - frameCommand = "launchBrowser"; - frameCommandParam = url; -} - -void LaunchMarket(const char *url) { - frameCommand = "launchMarket"; - frameCommandParam = url; -} - -void LaunchEmail(const char *email_address) { - frameCommand = "launchEmail"; - frameCommandParam = email_address; -} - -void System_InputBox(const char *title, const char *defaultValue) { - frameCommand = "inputBox"; - frameCommandParam = title; -} - -// Remember that all of these need initialization on init! The process -// may be reused when restarting the game. Globals are DANGEROUS. - -float dp_xscale = 1; -float dp_yscale = 1; - -InputState input_state; - -static bool renderer_inited = false; -static bool first_lost = true; -static bool use_native_audio = false; - -std::string GetJavaString(JNIEnv *env, jstring jstr) -{ - const char *str = env->GetStringUTFChars(jstr, 0); - std::string cpp_string = std::string(str); - env->ReleaseStringUTFChars(jstr, str); - return cpp_string; -} - -extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) -{ - std::string app_name, app_nice_name; - bool landscape; - NativeGetAppInfo(&app_name, &app_nice_name, &landscape); - return landscape; -} - -// For the Back button to work right. -extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isAtTopLevel(JNIEnv *env, jclass) { - if (extraLog) { - ILOG("isAtTopLevel"); - } - return NativeIsAtTopLevel(); -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init - (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring japkpath, - jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { - jniEnvUI = env; - - ILOG("NativeApp.init() -- begin"); - - memset(&input_state, 0, sizeof(input_state)); - renderer_inited = false; - first_lost = true; - - pad_buttons_down = 0; - pad_buttons_async_set = 0; - pad_buttons_async_clear = 0; - - std::string apkPath = GetJavaString(env, japkpath); - ILOG("NativeApp::Init: APK path: %s", apkPath.c_str()); - VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); - - std::string externalDir = GetJavaString(env, jexternalDir); - std::string user_data_path = GetJavaString(env, jdataDir) + "/"; - std::string library_path = GetJavaString(env, jlibraryDir) + "/"; - std::string installID = GetJavaString(env, jinstallID); - - ILOG("NativeApp.init(): External storage path: %s", externalDir.c_str()); - - std::string app_name; - std::string app_nice_name; - bool landscape; - - net::Init(); - - g_dpi = dpi; - g_dpi_scale = 240.0f / (float)g_dpi; - pixel_xres = xxres; - pixel_yres = yyres; - pixel_in_dps = (float)pixel_xres / (float)dp_xres; - - NativeGetAppInfo(&app_name, &app_nice_name, &landscape); - - const char *argv[2] = {app_name.c_str(), 0}; - NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); - - use_native_audio = juseNativeAudio; - if (use_native_audio) { - AndroidAudio_Init(&NativeMix, library_path); - } - ILOG("NativeApp.init() -- end"); -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_resume(JNIEnv *, jclass) { - ILOG("NativeApp.resume() - resuming audio"); - if (use_native_audio) { - AndroidAudio_Resume(); - } -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclass) { - ILOG("NativeApp.pause() - pausing audio"); - if (use_native_audio) { - AndroidAudio_Pause(); - } -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { - ILOG("NativeApp.shutdown() -- begin"); - if (use_native_audio) { - AndroidAudio_Shutdown(); - } - if (renderer_inited) { - NativeShutdownGraphics(); - renderer_inited = false; - } - NativeShutdown(); - ILOG("VFSShutdown."); - VFSShutdown(); - net::Shutdown(); - ILOG("NativeApp.shutdown() -- end"); -} - -static jmethodID postCommand; - -extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { - ILOG("NativeApp.displayInit()"); - if (!renderer_inited) { - // We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S). - // Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo - // can change the dp resolution if it feels like it. - dp_xres = pixel_xres * g_dpi_scale; - dp_yres = pixel_yres * g_dpi_scale; - - ILOG("Calling NativeInitGraphics(): dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); - NativeInitGraphics(); - - dp_xscale = (float)dp_xres / pixel_xres; - dp_yscale = (float)dp_yres / pixel_yres; - renderer_inited = true; - } else { - ILOG("Calling NativeDeviceLost();"); - NativeDeviceLost(); - ILOG("NativeDeviceLost completed.;"); - } - ILOG("(Re)-fetching method ID to postCommand..."); - jclass cls = env->GetObjectClass(obj); - postCommand = env->GetMethodID(cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); - ILOG("MethodID: %i", (int)postCommand); -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { - ILOG("NativeApp.displayResize(%i, %i)", w, h); - // TODO: Move some of the logic from displayInit here? -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { - // Too spammy - // ILOG("NativeApp.displayRender()"); - if (renderer_inited) { - // TODO: Look into if these locks are a perf loss - { - lock_guard guard(input_state.lock); - pad_buttons_down |= pad_buttons_async_set; - pad_buttons_down &= ~pad_buttons_async_clear; - input_state.pad_buttons = pad_buttons_down; - UpdateInputState(&input_state); - } - - { - lock_guard guard(input_state.lock); - input_state.pad_lstick_x = left_joystick_x_async; - input_state.pad_lstick_y = left_joystick_y_async; - NativeUpdate(input_state); - } - - { - lock_guard guard(input_state.lock); - EndInputState(&input_state); - } - - NativeRender(); - time_update(); - } else { - ELOG("BAD: Ended up in nativeRender even though app has quit.%s", ""); - // Shouldn't really get here. Let's draw magenta. - glstate.depthWrite.set(GL_TRUE); - glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glClearColor(1.0, 0.0, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - } - - if (!frameCommand.empty()) { - ILOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str()); - - jstring cmd = env->NewStringUTF(frameCommand.c_str()); - jstring param = env->NewStringUTF(frameCommandParam.c_str()); - env->CallVoidMethod(obj, postCommand, cmd, param); - - frameCommand = ""; - frameCommandParam = ""; - } -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { - // Too spammy - // ILOG("NativeApp.audioRender"); - - // The audio thread can pretty safely enable Flush-to-Zero mode on the FPU. - EnableFZ(); - - int buf_size = env->GetArrayLength(array); - if (buf_size) { - short *data = env->GetShortArrayElements(array, 0); - int samples = buf_size / 2; - NativeMix(data, samples); - env->ReleaseShortArrayElements(array, data, 0); - } -} - -extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch - (JNIEnv *, jclass, float x, float y, int code, int pointerId) { - lock_guard guard(input_state.lock); - - if (pointerId >= MAX_POINTERS) { - ELOG("Too many pointers: %i", pointerId); - return; // We ignore 8+ pointers entirely. - } - float scaledX = (int)(x * dp_xscale); // why the (int) cast? - float scaledY = (int)(y * dp_yscale); - input_state.pointer_x[pointerId] = scaledX; - input_state.pointer_y[pointerId] = scaledY; - if (code == 1) { - input_state.pointer_down[pointerId] = true; - NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_DOWN); - } else if (code == 2) { - input_state.pointer_down[pointerId] = false; - NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_UP); - } else { - NativeTouch(pointerId, scaledX, scaledY, 0, TOUCH_MOVE); - } - input_state.mouse_valid = true; -} - -static void AsyncDown(int padbutton) { - pad_buttons_async_set |= padbutton; - pad_buttons_async_clear &= ~padbutton; -} - -static void AsyncUp(int padbutton) { - pad_buttons_async_set &= ~padbutton; - pad_buttons_async_clear |= padbutton; -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) { - switch (key) { - case 1: AsyncDown (PAD_BUTTON_BACK); break; // Back - case 2: AsyncDown (PAD_BUTTON_MENU); break; // Menu - case 3: AsyncDown (PAD_BUTTON_A); break; // Search - case KEYCODE_BUTTON_CROSS: - case KEYCODE_BUTTON_CROSS_PS3: - AsyncDown(PAD_BUTTON_A); - break; - case KEYCODE_BUTTON_CIRCLE: - case KEYCODE_BUTTON_CIRCLE_PS3: - AsyncDown (PAD_BUTTON_B); - break; - case KEYCODE_BUTTON_SQUARE: AsyncDown (PAD_BUTTON_X); break; - case KEYCODE_BUTTON_TRIANGLE: AsyncDown (PAD_BUTTON_Y); break; - case KEYCODE_DPAD_LEFT: AsyncDown (PAD_BUTTON_LEFT); break; - case KEYCODE_DPAD_UP: AsyncDown (PAD_BUTTON_UP); break; - case KEYCODE_DPAD_RIGHT: AsyncDown (PAD_BUTTON_RIGHT); break; - case KEYCODE_DPAD_DOWN: AsyncDown (PAD_BUTTON_DOWN); break; - case KEYCODE_BUTTON_L1: AsyncDown (PAD_BUTTON_LBUMPER); break; - case KEYCODE_BUTTON_R1: AsyncDown (PAD_BUTTON_RBUMPER); break; - case KEYCODE_BUTTON_START: AsyncDown (PAD_BUTTON_START); break; - case KEYCODE_BUTTON_SELECT: AsyncDown (PAD_BUTTON_SELECT); break; - default: break; - } -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) { - switch (key) { - case 1: AsyncUp (PAD_BUTTON_BACK); break; // Back - case 2: AsyncUp (PAD_BUTTON_MENU); break; // Menu - case 3: AsyncUp (PAD_BUTTON_A); break; // Search - case KEYCODE_BUTTON_CROSS: - case KEYCODE_BUTTON_CROSS_PS3: - AsyncUp(PAD_BUTTON_A); - break; - case KEYCODE_BUTTON_CIRCLE: - case KEYCODE_BUTTON_CIRCLE_PS3: - AsyncUp (PAD_BUTTON_B); - break; - case KEYCODE_BUTTON_SQUARE: AsyncUp (PAD_BUTTON_X); break; - case KEYCODE_BUTTON_TRIANGLE: AsyncUp (PAD_BUTTON_Y); break; - case KEYCODE_DPAD_LEFT: AsyncUp (PAD_BUTTON_LEFT); break; - case KEYCODE_DPAD_UP: AsyncUp (PAD_BUTTON_UP); break; - case KEYCODE_DPAD_RIGHT: AsyncUp (PAD_BUTTON_RIGHT); break; - case KEYCODE_DPAD_DOWN: AsyncUp (PAD_BUTTON_DOWN); break; - case KEYCODE_BUTTON_L1: AsyncUp (PAD_BUTTON_LBUMPER); break; - case KEYCODE_BUTTON_R1: AsyncUp (PAD_BUTTON_RBUMPER); break; - case KEYCODE_BUTTON_START: AsyncUp (PAD_BUTTON_START); break; - case KEYCODE_BUTTON_SELECT: AsyncUp (PAD_BUTTON_SELECT); break; - default: break; - } -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickEvent( - JNIEnv *env, jclass, jfloat x, jfloat y) { - left_joystick_x_async = x; - left_joystick_y_async = y; -} - -extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) { - // Theoretically this needs locking but I doubt it matters. Worst case, the X - // from one "sensor frame" will be used together with Y from the next. - // Should look into quantization though, for compressed movement storage. - input_state.accelerometer_valid = true; - input_state.acc.x = x; - input_state.acc.y = y; - input_state.acc.z = z; -} - -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) { - jboolean isCopy; - std::string msg = GetJavaString(env, message); - std::string prm = GetJavaString(env, param); - ILOG("Message received: %s %s", msg.c_str(), prm.c_str()); - NativeMessageReceived(msg.c_str(), prm.c_str()); -} - +// This is generic code that is included in all Android apps that use the +// Native framework by Henrik Rydgård (https://github.com/hrydgard/native). + +// It calls a set of methods defined in NativeApp.h. These should be implemented +// by your game or app. + +#include +#include +#include +#include +#include +#include + +#include "base/basictypes.h" +#include "base/display.h" +#include "base/NativeApp.h" +#include "base/logging.h" +#include "base/timeutil.h" +#include "file/zip_read.h" +#include "input/input_state.h" +#include "audio/mixer.h" +#include "math/math_util.h" +#include "net/resolve.h" +#include "android/native_audio.h" +#include "gfx_es2/gl_state.h" + +// For Xperia Play support +enum AndroidKeyCodes { + KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed + KEYCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed + KEYCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) + KEYCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed + KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed + KEYCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed + KEYCODE_DPAD_LEFT = 21, + KEYCODE_DPAD_UP = 19, + KEYCODE_DPAD_RIGHT = 22, + KEYCODE_DPAD_DOWN = 20, + KEYCODE_BUTTON_L1 = 102, + KEYCODE_BUTTON_R1 = 103, + KEYCODE_BUTTON_START = 108, + KEYCODE_BUTTON_SELECT = 109, +}; + +static JNIEnv *jniEnvUI; + +std::string frameCommand; +std::string frameCommandParam; + +const bool extraLog = true; + +static uint32_t pad_buttons_async_set; +static uint32_t pad_buttons_async_clear; +static float left_joystick_x_async; +static float left_joystick_y_async; + +static uint32_t pad_buttons_down; + +// Android implementation of callbacks to the Java part of the app +void SystemToast(const char *text) { + frameCommand = "toast"; + frameCommandParam = text; +} + +// TODO: need a Hide or bool show; +void ShowAd(int x, int y, bool center_x) { + ELOG("TODO! ShowAd!"); +} + +void ShowKeyboard() { + frameCommand = "showKeyboard"; + frameCommandParam = ""; +} + +void Vibrate(int length_ms) { + frameCommand = "vibrate"; + frameCommandParam = "100"; +} + +void LaunchBrowser(const char *url) { + frameCommand = "launchBrowser"; + frameCommandParam = url; +} + +void LaunchMarket(const char *url) { + frameCommand = "launchMarket"; + frameCommandParam = url; +} + +void LaunchEmail(const char *email_address) { + frameCommand = "launchEmail"; + frameCommandParam = email_address; +} + +void System_InputBox(const char *title, const char *defaultValue) { + frameCommand = "inputBox"; + frameCommandParam = title; +} + +// Remember that all of these need initialization on init! The process +// may be reused when restarting the game. Globals are DANGEROUS. + +float dp_xscale = 1; +float dp_yscale = 1; + +InputState input_state; + +static bool renderer_inited = false; +static bool first_lost = true; +static bool use_native_audio = false; + +std::string GetJavaString(JNIEnv *env, jstring jstr) +{ + const char *str = env->GetStringUTFChars(jstr, 0); + std::string cpp_string = std::string(str); + env->ReleaseStringUTFChars(jstr, str); + return cpp_string; +} + +extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) +{ + std::string app_name, app_nice_name; + bool landscape; + NativeGetAppInfo(&app_name, &app_nice_name, &landscape); + return landscape; +} + +// For the Back button to work right. +extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isAtTopLevel(JNIEnv *env, jclass) { + if (extraLog) { + ILOG("isAtTopLevel"); + } + return NativeIsAtTopLevel(); +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init + (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring japkpath, + jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { + jniEnvUI = env; + + ILOG("NativeApp.init() -- begin"); + + memset(&input_state, 0, sizeof(input_state)); + renderer_inited = false; + first_lost = true; + + pad_buttons_down = 0; + pad_buttons_async_set = 0; + pad_buttons_async_clear = 0; + + std::string apkPath = GetJavaString(env, japkpath); + ILOG("NativeApp::Init: APK path: %s", apkPath.c_str()); + VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); + + std::string externalDir = GetJavaString(env, jexternalDir); + std::string user_data_path = GetJavaString(env, jdataDir) + "/"; + std::string library_path = GetJavaString(env, jlibraryDir) + "/"; + std::string installID = GetJavaString(env, jinstallID); + + ILOG("NativeApp.init(): External storage path: %s", externalDir.c_str()); + + std::string app_name; + std::string app_nice_name; + bool landscape; + + net::Init(); + + g_dpi = dpi; + g_dpi_scale = 240.0f / (float)g_dpi; + pixel_xres = xxres; + pixel_yres = yyres; + pixel_in_dps = (float)pixel_xres / (float)dp_xres; + + NativeGetAppInfo(&app_name, &app_nice_name, &landscape); + + const char *argv[2] = {app_name.c_str(), 0}; + NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); + + use_native_audio = juseNativeAudio; + if (use_native_audio) { + AndroidAudio_Init(&NativeMix, library_path); + } + ILOG("NativeApp.init() -- end"); +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_resume(JNIEnv *, jclass) { + ILOG("NativeApp.resume() - resuming audio"); + if (use_native_audio) { + AndroidAudio_Resume(); + } +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclass) { + ILOG("NativeApp.pause() - pausing audio"); + if (use_native_audio) { + AndroidAudio_Pause(); + } +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { + ILOG("NativeApp.shutdown() -- begin"); + if (use_native_audio) { + AndroidAudio_Shutdown(); + } + if (renderer_inited) { + NativeShutdownGraphics(); + renderer_inited = false; + } + NativeShutdown(); + ILOG("VFSShutdown."); + VFSShutdown(); + net::Shutdown(); + ILOG("NativeApp.shutdown() -- end"); +} + +static jmethodID postCommand; + +extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { + ILOG("NativeApp.displayInit()"); + if (!renderer_inited) { + // We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S). + // Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo + // can change the dp resolution if it feels like it. + dp_xres = pixel_xres * g_dpi_scale; + dp_yres = pixel_yres * g_dpi_scale; + + ILOG("Calling NativeInitGraphics(): dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); + NativeInitGraphics(); + + dp_xscale = (float)dp_xres / pixel_xres; + dp_yscale = (float)dp_yres / pixel_yres; + renderer_inited = true; + } else { + ILOG("Calling NativeDeviceLost();"); + NativeDeviceLost(); + ILOG("NativeDeviceLost completed.;"); + } + ILOG("(Re)-fetching method ID to postCommand..."); + jclass cls = env->GetObjectClass(obj); + postCommand = env->GetMethodID(cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); + ILOG("MethodID: %i", (int)postCommand); +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { + ILOG("NativeApp.displayResize(%i, %i)", w, h); + // TODO: Move some of the logic from displayInit here? +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { + // Too spammy + // ILOG("NativeApp.displayRender()"); + if (renderer_inited) { + // TODO: Look into if these locks are a perf loss + { + lock_guard guard(input_state.lock); + pad_buttons_down |= pad_buttons_async_set; + pad_buttons_down &= ~pad_buttons_async_clear; + input_state.pad_buttons = pad_buttons_down; + UpdateInputState(&input_state); + } + + { + lock_guard guard(input_state.lock); + input_state.pad_lstick_x = left_joystick_x_async; + input_state.pad_lstick_y = left_joystick_y_async; + NativeUpdate(input_state); + } + + { + lock_guard guard(input_state.lock); + EndInputState(&input_state); + } + + NativeRender(); + time_update(); + } else { + ELOG("BAD: Ended up in nativeRender even though app has quit.%s", ""); + // Shouldn't really get here. Let's draw magenta. + glstate.depthWrite.set(GL_TRUE); + glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glClearColor(1.0, 0.0, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } + + if (!frameCommand.empty()) { + ILOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str()); + + jstring cmd = env->NewStringUTF(frameCommand.c_str()); + jstring param = env->NewStringUTF(frameCommandParam.c_str()); + env->CallVoidMethod(obj, postCommand, cmd, param); + + frameCommand = ""; + frameCommandParam = ""; + } +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { + // Too spammy + // ILOG("NativeApp.audioRender"); + + // The audio thread can pretty safely enable Flush-to-Zero mode on the FPU. + EnableFZ(); + + int buf_size = env->GetArrayLength(array); + if (buf_size) { + short *data = env->GetShortArrayElements(array, 0); + int samples = buf_size / 2; + NativeMix(data, samples); + env->ReleaseShortArrayElements(array, data, 0); + } +} + +extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch + (JNIEnv *, jclass, float x, float y, int code, int pointerId) { + lock_guard guard(input_state.lock); + + if (pointerId >= MAX_POINTERS) { + ELOG("Too many pointers: %i", pointerId); + return; // We ignore 8+ pointers entirely. + } + float scaledX = (int)(x * dp_xscale); // why the (int) cast? + float scaledY = (int)(y * dp_yscale); + input_state.pointer_x[pointerId] = scaledX; + input_state.pointer_y[pointerId] = scaledY; + TouchInput touch; + touch.x = scaledX; + touch.y = scaledY; + if (code == 1) { + input_state.pointer_down[pointerId] = true; + touch.flags = TOUCH_DOWN; + } else if (code == 2) { + input_state.pointer_down[pointerId] = false; + touch.flags = TOUCH_UP; + } else { + touch.flags = TOUCH_MOVE; + } + NativeTouch(touch); + input_state.mouse_valid = true; +} + +static void AsyncDown(int padbutton) { + pad_buttons_async_set |= padbutton; + pad_buttons_async_clear &= ~padbutton; +} + +static void AsyncUp(int padbutton) { + pad_buttons_async_set &= ~padbutton; + pad_buttons_async_clear |= padbutton; +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) { + switch (key) { + case 1: AsyncDown (PAD_BUTTON_BACK); break; // Back + case 2: AsyncDown (PAD_BUTTON_MENU); break; // Menu + case 3: AsyncDown (PAD_BUTTON_A); break; // Search + case KEYCODE_BUTTON_CROSS: + case KEYCODE_BUTTON_CROSS_PS3: + AsyncDown(PAD_BUTTON_A); + break; + case KEYCODE_BUTTON_CIRCLE: + case KEYCODE_BUTTON_CIRCLE_PS3: + AsyncDown (PAD_BUTTON_B); + break; + case KEYCODE_BUTTON_SQUARE: AsyncDown (PAD_BUTTON_X); break; + case KEYCODE_BUTTON_TRIANGLE: AsyncDown (PAD_BUTTON_Y); break; + case KEYCODE_DPAD_LEFT: AsyncDown (PAD_BUTTON_LEFT); break; + case KEYCODE_DPAD_UP: AsyncDown (PAD_BUTTON_UP); break; + case KEYCODE_DPAD_RIGHT: AsyncDown (PAD_BUTTON_RIGHT); break; + case KEYCODE_DPAD_DOWN: AsyncDown (PAD_BUTTON_DOWN); break; + case KEYCODE_BUTTON_L1: AsyncDown (PAD_BUTTON_LBUMPER); break; + case KEYCODE_BUTTON_R1: AsyncDown (PAD_BUTTON_RBUMPER); break; + case KEYCODE_BUTTON_START: AsyncDown (PAD_BUTTON_START); break; + case KEYCODE_BUTTON_SELECT: AsyncDown (PAD_BUTTON_SELECT); break; + default: break; + } +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) { + switch (key) { + case 1: AsyncUp (PAD_BUTTON_BACK); break; // Back + case 2: AsyncUp (PAD_BUTTON_MENU); break; // Menu + case 3: AsyncUp (PAD_BUTTON_A); break; // Search + case KEYCODE_BUTTON_CROSS: + case KEYCODE_BUTTON_CROSS_PS3: + AsyncUp(PAD_BUTTON_A); + break; + case KEYCODE_BUTTON_CIRCLE: + case KEYCODE_BUTTON_CIRCLE_PS3: + AsyncUp (PAD_BUTTON_B); + break; + case KEYCODE_BUTTON_SQUARE: AsyncUp (PAD_BUTTON_X); break; + case KEYCODE_BUTTON_TRIANGLE: AsyncUp (PAD_BUTTON_Y); break; + case KEYCODE_DPAD_LEFT: AsyncUp (PAD_BUTTON_LEFT); break; + case KEYCODE_DPAD_UP: AsyncUp (PAD_BUTTON_UP); break; + case KEYCODE_DPAD_RIGHT: AsyncUp (PAD_BUTTON_RIGHT); break; + case KEYCODE_DPAD_DOWN: AsyncUp (PAD_BUTTON_DOWN); break; + case KEYCODE_BUTTON_L1: AsyncUp (PAD_BUTTON_LBUMPER); break; + case KEYCODE_BUTTON_R1: AsyncUp (PAD_BUTTON_RBUMPER); break; + case KEYCODE_BUTTON_START: AsyncUp (PAD_BUTTON_START); break; + case KEYCODE_BUTTON_SELECT: AsyncUp (PAD_BUTTON_SELECT); break; + default: break; + } +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickEvent( + JNIEnv *env, jclass, jfloat x, jfloat y) { + left_joystick_x_async = x; + left_joystick_y_async = y; +} + +extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) { + // Theoretically this needs locking but I doubt it matters. Worst case, the X + // from one "sensor frame" will be used together with Y from the next. + // Should look into quantization though, for compressed movement storage. + input_state.accelerometer_valid = true; + input_state.acc.x = x; + input_state.acc.y = y; + input_state.acc.z = z; +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) { + jboolean isCopy; + std::string msg = GetJavaString(env, message); + std::string prm = GetJavaString(env, param); + ILOG("Message received: %s %s", msg.c_str(), prm.c_str()); + NativeMessageReceived(msg.c_str(), prm.c_str()); +} + diff --git a/base/NativeApp.h b/base/NativeApp.h index 04630fbb9c..cd807d449e 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -1,99 +1,95 @@ -#pragma once - -#include - -// The Native App API. -// -// Implement these functions and you've got a native app. These are called -// from the framework, which exposes the native JNI api which is a bit -// more complicated. - -// This is defined in input/input_state.h. -struct InputState; - -// The first function to get called, just write strings to the two pointers. -// This might get called multiple times in some implementations, you must be able to handle that. -// The detected DP dimensions of the screen are set as dp_xres and dp_yres and you're free to change -// them if you have a fixed-size app that needs to stretch a little to fit. -void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape); - -// Generic host->C++ messaging, used for functionality like system-native popup input boxes. -void NativeMessageReceived(const char *message, const char *value); - -// For the back button to work right, this should return true on your main or title screen. -// Otherwise, just return false. -bool NativeIsAtTopLevel(); - -// The very first function to be called after NativeGetAppInfo. Even NativeMix is not called -// before this, although it may be called at any point in time afterwards (on any thread!) -// This functions must NOT call OpenGL. Main thread. -void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *external_directory, const char *installID); - -// Runs after NativeInit() at some point. May (and probably should) call OpenGL. -void NativeInitGraphics(); - -// Signals that you need to recreate all buffered OpenGL resources, -// like textures, vbo etc. Also, if you have modified dp_xres and dp_yres, you have to -// do it again here. Main thread. -void NativeDeviceLost(); - -// Called ~sixty times a second, delivers the current input state. -// Main thread. -void NativeUpdate(InputState &input); - -// Delivers touch events "instantly", without waiting for the next frame so that NativeUpdate can deliver. -// Useful for triggering audio events, saving a few ms. -// If you don't care about touch latency, just do a no-op implementation of this. -// time is not yet implemented. finger can be from 0 to 7, inclusive. -enum TouchEvent { - TOUCH_DOWN, - TOUCH_MOVE, - TOUCH_UP, -}; -void NativeTouch(int finger, float x, float y, double time, TouchEvent event); - -// Called when it's time to render. If the device can keep up, this -// will also be called sixty times per second. Main thread. -void NativeRender(); - -// This should render num_samples 44khz stereo samples. -// Try not to make too many assumptions on the granularity -// of num_samples. -// This function may be called from a totally separate thread from -// the rest of the game, so be careful with synchronization. -// Returns the number of samples actually output. The app should do everything it can -// to fill the buffer completely. -int NativeMix(short *audio, int num_samples); -void NativeSetMixer(void* mixer); - -// Called when it's time to shutdown. After this has been called, -// no more calls to any other function will be made from the framework -// before process exit. -// The graphics context should still be active when calling this, as freeing -// of graphics resources happens here. -// Main thread. -void NativeShutdownGraphics(); -void NativeShutdown(); - -// Called on app.onCreate and app.onDestroy (?). Tells the app to save/restore -// light state. If app was fully rebooted between these calls, it's okay if some minor -// state is lost (position in level) but the level currently playihg, or the song -// currently being edited, or whatever, should be restored properly. In this case, -// firstTime will be set so that appropriate action can be taken (or not taken when -// it's not set). -// -// Note that NativeRestore is always called on bootup. -void NativeRestoreState(bool firstTime); // onCreate -void NativeSaveState(); // onDestroy - -// Calls back into Java / SDL -// These APIs must be implemented by every port (for example app-android.cpp, PCMain.cpp). -// You are free to call these. -void SystemToast(const char *text); -void ShowKeyboard(); -void ShowAd(int x, int y, bool center_x); -void Vibrate(int length_ms); -void LaunchBrowser(const char *url); -void LaunchMarket(const char *url); -void LaunchEmail(const char *email_address); -void System_InputBox(const char *title, const char *defaultValue); +#pragma once + +#include + +// The Native App API. +// +// Implement these functions and you've got a native app. These are called +// from the framework, which exposes the native JNI api which is a bit +// more complicated. + +// This is defined in input/input_state.h. +struct InputState; +struct TouchInput; + +// The first function to get called, just write strings to the two pointers. +// This might get called multiple times in some implementations, you must be able to handle that. +// The detected DP dimensions of the screen are set as dp_xres and dp_yres and you're free to change +// them if you have a fixed-size app that needs to stretch a little to fit. +void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape); + +// Generic host->C++ messaging, used for functionality like system-native popup input boxes. +void NativeMessageReceived(const char *message, const char *value); + +// For the back button to work right, this should return true on your main or title screen. +// Otherwise, just return false. +bool NativeIsAtTopLevel(); + +// The very first function to be called after NativeGetAppInfo. Even NativeMix is not called +// before this, although it may be called at any point in time afterwards (on any thread!) +// This functions must NOT call OpenGL. Main thread. +void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *external_directory, const char *installID); + +// Runs after NativeInit() at some point. May (and probably should) call OpenGL. +void NativeInitGraphics(); + +// Signals that you need to recreate all buffered OpenGL resources, +// like textures, vbo etc. Also, if you have modified dp_xres and dp_yres, you have to +// do it again here. Main thread. +void NativeDeviceLost(); + +// Called ~sixty times a second, delivers the current input state. +// Main thread. +void NativeUpdate(InputState &input); + +// Delivers touch events "instantly", without waiting for the next frame so that NativeUpdate can deliver. +// Useful for triggering audio events, saving a few ms. +// If you don't care about touch latency, just do a no-op implementation of this. +// time is not yet implemented. finger can be from 0 to 7, inclusive. +void NativeTouch(const TouchInput &touch); + +// Called when it's time to render. If the device can keep up, this +// will also be called sixty times per second. Main thread. +void NativeRender(); + +// This should render num_samples 44khz stereo samples. +// Try not to make too many assumptions on the granularity +// of num_samples. +// This function may be called from a totally separate thread from +// the rest of the game, so be careful with synchronization. +// Returns the number of samples actually output. The app should do everything it can +// to fill the buffer completely. +int NativeMix(short *audio, int num_samples); +void NativeSetMixer(void* mixer); + +// Called when it's time to shutdown. After this has been called, +// no more calls to any other function will be made from the framework +// before process exit. +// The graphics context should still be active when calling this, as freeing +// of graphics resources happens here. +// Main thread. +void NativeShutdownGraphics(); +void NativeShutdown(); + +// Called on app.onCreate and app.onDestroy (?). Tells the app to save/restore +// light state. If app was fully rebooted between these calls, it's okay if some minor +// state is lost (position in level) but the level currently playihg, or the song +// currently being edited, or whatever, should be restored properly. In this case, +// firstTime will be set so that appropriate action can be taken (or not taken when +// it's not set). +// +// Note that NativeRestore is always called on bootup. +void NativeRestoreState(bool firstTime); // onCreate +void NativeSaveState(); // onDestroy + +// Calls back into Java / SDL +// These APIs must be implemented by every port (for example app-android.cpp, PCMain.cpp). +// You are free to call these. +void SystemToast(const char *text); +void ShowKeyboard(); +void ShowAd(int x, int y, bool center_x); +void Vibrate(int length_ms); +void LaunchBrowser(const char *url); +void LaunchMarket(const char *url); +void LaunchEmail(const char *email_address); +void System_InputBox(const char *title, const char *defaultValue); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 62c2a19364..4aec8c6c81 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -533,20 +533,35 @@ int main(int argc, char *argv[]) { } else if (event.type == SDL_MOUSEMOTION) { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; - NativeTouch(0, mx, my, 0, TOUCH_MOVE); + TouchInput input; + input.x = mx; + input.y = my; + input.flags = TOUCH_MOVE; + input.id = 0; + NativeTouch(input); } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { //input_state.mouse_buttons_down = 1; input_state.pointer_down[0] = true; nextFrameMD = true; - NativeTouch(0, mx, my, 0, TOUCH_DOWN); + TouchInput input; + input.x = mx; + input.y = my; + input.flags = TOUCH_DOWN; + input.id = 0; + NativeTouch(input); } } else if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { input_state.pointer_down[0] = false; nextFrameMD = false; //input_state.mouse_buttons_up = 1; - NativeTouch(0, mx, my, 0, TOUCH_UP); + TouchInput input; + input.x = mx; + input.y = my; + input.flags = TOUCH_UP; + input.id = 0; + NativeTouch(input); } } } diff --git a/base/display.h b/base/display.h index d72ba4dafd..761af3b55b 100644 --- a/base/display.h +++ b/base/display.h @@ -1,13 +1,13 @@ -#pragma once - -// This is meant to be a framework for handling DPI scaling etc. -// For now, it just consists of these two ugly globals. - -extern int dp_xres; -extern int dp_yres; -extern int pixel_xres; -extern int pixel_yres; - -extern int g_dpi; -extern float g_dpi_scale; +#pragma once + +// This is meant to be a framework for handling DPI scaling etc. +// For now, it just consists of these ugly globals. + +extern int dp_xres; +extern int dp_yres; +extern int pixel_xres; +extern int pixel_yres; + +extern int g_dpi; +extern float g_dpi_scale; extern float pixel_in_dps; \ No newline at end of file diff --git a/base/scoped_ptr.h b/base/scoped_ptr.h index 1a31890164..d1af1c81d0 100644 --- a/base/scoped_ptr.h +++ b/base/scoped_ptr.h @@ -21,7 +21,8 @@ public: } T *operator->() { return ptr_; } const T *operator->() const { return ptr_; } - + const T *get() const { return ptr_; } + T *get() { return ptr_; } private: scoped_ptr(const scoped_ptr &other); void operator=(const scoped_ptr &other); diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 51bc62bad7..27115863fc 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -28,6 +28,7 @@ DrawBuffer::DrawBuffer() : count_(0), atlas(0) { fontscaley = 1.0f; inited_ = false; } + DrawBuffer::~DrawBuffer() { delete [] verts_; } @@ -368,18 +369,21 @@ void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) { // U+3040–U+309F Hiragana // U+30A0–U+30FF Katakana +void DrawBuffer::DrawTextRect(int font, const char *text, float x, float y, float w, float h, Color color, int align) { + DrawText(font, text, x, y, color, align); +} // ROTATE_* doesn't yet work right. -void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int flags) { +void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int align) { const AtlasFont &atlasfont = *atlas->fonts[font]; unsigned int cval; float w, h; MeasureText(font, text, &w, &h); - if (flags) { - DoAlign(flags, &x, &y, &w, &h); + if (align) { + DoAlign(align, &x, &y, &w, &h); } - if (flags & ROTATE_90DEG_LEFT) { + if (align & ROTATE_90DEG_LEFT) { x -= atlasfont.ascend*fontscaley; // y += h; } @@ -402,7 +406,7 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co if (ch) { const AtlasChar &c = *ch; float cx1, cy1, cx2, cy2; - if (flags & ROTATE_90DEG_LEFT) { + if (align & ROTATE_90DEG_LEFT) { cy1 = y - c.ox * fontscalex; cx1 = x + c.oy * fontscaley; cy2 = y - (c.ox + c.pw) * fontscalex; @@ -419,7 +423,7 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co V(cx1, cy1, color, c.sx, c.sy); V(cx2, cy2, color, c.ex, c.ey); V(cx1, cy2, color, c.sx, c.ey); - if (flags & ROTATE_90DEG_LEFT) + if (align & ROTATE_90DEG_LEFT) y -= c.wx * fontscalex; else x += c.wx * fontscalex; diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 74355542d5..002237fc0f 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -97,6 +97,7 @@ public: void SetAtlas(const Atlas *_atlas) { atlas = _atlas; } + const Atlas *GetAtlas() const { return atlas; } void MeasureImage(int atlas_image, float *w, float *h); void DrawImage(int atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT); void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); @@ -108,6 +109,7 @@ public: void DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); void MeasureText(int font, const char *text, float *w, float *h); + void DrawTextRect(int font, const char *text, float x, float y, float w, float h, Color color = 0xFFFFFFFF, int align = 0); void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); void DrawTextShadow(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); @@ -120,7 +122,6 @@ public: // Utility to avoid having to include gl.h just for this in UI code. void EnableBlend(bool enable); - // Rectangular clipping, implemented using scissoring. // Must flush before and after. void SetClipRect(float x1, float y1, float x2, float y2); diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index e9264762dc..880dab4c92 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -1,71 +1,60 @@ -// Unfinished. -// TODO: -// Zoom gesture a la http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-6-implementing-the-pinch-zoom-gesture/1847 - -#include "input/gesture_detector.h" - -namespace GestureDetector { - -struct Finger { - bool down; - float X; - float Y; - float lastX; - float lastY; - float downX; - float downY; - float deltaX; - float deltaY; - float smoothDeltaX; - float smoothDeltaY; -}; - -// State -#define MAX_FINGERS 4 - -static Finger fingers[MAX_FINGERS]; - -void update(const InputState &state) { - // Mouse / 1-finger-touch control. - if (state.pointer_down[0]) { - fingers[0].down = true; - fingers[0].downX = state.pointer_x[0]; - fingers[0].downY = state.pointer_y[0]; - } else { - fingers[0].down = false; - } - - fingers[0].lastX = fingers[0].X; - fingers[0].lastY = fingers[0].Y; - - // TODO: real multitouch -} - -bool down(int i, float *xdelta, float *ydelta) { - if (!fingers[i].down) { - return false; - } - *xdelta = fingers[i].downX; - *ydelta = fingers[i].downY; - return true; -} - -bool dragDistance(int i, float *xdelta, float *ydelta) { - if (!fingers[i].down) - return false; - - *xdelta = fingers[i].X - fingers[i].downX; - *ydelta = fingers[i].Y - fingers[i].downY; - return true; -} - -bool dragDelta(int i, float *xdelta, float *ydelta) { - if (!fingers[i].down) - return false; - - *xdelta = fingers[i].X - fingers[i].lastX; - *ydelta = fingers[i].Y - fingers[i].lastY; - return true; -} - -} +// Unfinished. +// TODO: +// Zoom gesture a la http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-6-implementing-the-pinch-zoom-gesture/1847 + +#include "input/gesture_detector.h" + +void GestureDetector::Update(const TouchInput &touch) { + // Mouse / 1-finger-touch control. + if (touch.flags & TOUCH_DOWN) { + pointers[0].down = true; + pointers[0].downX = touch.x; + pointers[0].downY = touch.y; + } else if (touch.flags & TOUCH_UP) { + pointers[0].down = false; + } + + pointers[0].lastX = pointers[0].X; + pointers[0].lastY = pointers[0].Y; + + // TODO: real multitouch +} + +bool GestureDetector::IsGestureActive(Gesture gesture) const { + // TODO + return false; +} + +void GestureDetector::GetGestureInfo(Gesture gesture, float info[4]) +{ +/* + +bool down(int i, float *xdelta, float *ydelta) { + if (!pointers[i].down) { + return false; + } + *xdelta = pointers[i].downX; + *ydelta = pointers[i].downY; + return true; +} + +bool dragDistance(int i, float *xdelta, float *ydelta) { + if (!pointers[i].down) + return false; + + *xdelta = pointers[i].X - pointers[i].downX; + *ydelta = pointers[i].Y - pointers[i].downY; + return true; +} + +bool dragDelta(int i, float *xdelta, float *ydelta) { + if (!pointers[i].down) + return false; + + *xdelta = pointers[i].X - pointers[i].lastX; + *ydelta = pointers[i].Y - pointers[i].lastY; + return true; +} +*/ + +} diff --git a/input/gesture_detector.h b/input/gesture_detector.h index dc3911edf3..b8457022be 100644 --- a/input/gesture_detector.h +++ b/input/gesture_detector.h @@ -1,19 +1,45 @@ -#include "input/input_state.h" - -// WIP - doesn't do much yet -// Mainly for detecting (multi-)touch gestures but also useable for left button mouse dragging etc. - -namespace GestureDetector -{ - void update(const InputState &state); - - bool down(int finger, float *xdown, float *ydown); - - // x/ydelta is difference from current location to the start of the drag. - // Returns true if button/finger is down, for convenience. - bool dragDistance(int finger, float *xdelta, float *ydelta); - - // x/ydelta is (smoothed?) difference from current location to the position from the last frame. - // Returns true if button/finger is down, for convenience. - bool dragDelta(int finger, float *xdelta, float *ydelta); -}; +#include "input/input_state.h" + +// WIP - doesn't do much yet +// Mainly for detecting (multi-)touch gestures but also useable for left button mouse dragging etc. + + +enum Gesture { + GESTURE_DRAG_VERTICAL = 1, + GESTURE_DRAG_HORIZONTAL = 2, + GESTURE_TWO_FINGER_ZOOM = 4, + GESTURE_TWO_FINGER_ZOOM_ROTATE = 4, +}; + +// May track multiple gestures at the same time. You simply call GetGestureInfo +// with the gesture you are interested in. +class GestureDetector +{ +public: + void Update(const TouchInput &touch); + bool IsGestureActive(Gesture gesture) const; + void GetGestureInfo(Gesture gesture, float info[4]); + +private: + // jazzhands! + enum Locals { + MAX_PTRS = 10 + }; + + struct Pointer { + bool down; + float X; + float Y; + float lastX; + float lastY; + float downX; + float downY; + float deltaX; + float deltaY; + float smoothDeltaX; + float smoothDeltaY; + }; + + Pointer pointers[MAX_PTRS]; + // ... +}; diff --git a/input/input_state.h b/input/input_state.h index 37bacd460e..fdf98f229c 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -89,3 +89,21 @@ inline void UpdateInputState(InputState *input) { inline void EndInputState(InputState *input) { input->pad_last_buttons = input->pad_buttons; } + +enum { + TOUCH_MOVE = 1, + TOUCH_DOWN = 2, + TOUCH_UP = 4, +}; + +// Used for asynchronous touch input. +// DOWN is always on its own. +// MOVE and UP can be combined. +struct TouchInput { + float x; + float y; + int id; // can be relied upon to be 0...MAX_POINTERS + int flags; + double timestamp; +}; + diff --git a/native.vcxproj b/native.vcxproj index 805dff1e02..63827c8b78 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -1,363 +1,367 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {C4DF647E-80EA-4111-A0A8-218B1B711E18} - Win32Proj - native - - - - StaticLibrary - true - MultiByte - - - StaticLibrary - true - MultiByte - - - StaticLibrary - false - false - MultiByte - v100 - - - StaticLibrary - false - false - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); - ProgramDatabase - - - Windows - true - - - Ws2_32.lib - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); - - - Windows - true - - - Ws2_32.lib - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); - StreamingSIMDExtensions2 - Fast - - - Windows - true - true - true - - - Ws2_32.lib - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); - StreamingSIMDExtensions2 - Fast - - - Windows - true - true - true - - - Ws2_32.lib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - - - - true - true - true - true - - - - - - - true - true - true - true - - - - - AnySuitable - true - Speed - AnySuitable - Speed - AnySuitable - true - Speed - false - AnySuitable - Speed - false - StreamingSIMDExtensions2 - Fast - StreamingSIMDExtensions2 - Fast - MaxSpeed - MaxSpeed - Default - Default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AssemblyAndSourceCode - AssemblyAndSourceCode - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {C4DF647E-80EA-4111-A0A8-218B1B711E18} + Win32Proj + native + + + + StaticLibrary + true + MultiByte + + + StaticLibrary + true + MultiByte + + + StaticLibrary + false + false + MultiByte + v100 + + + StaticLibrary + false + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ProgramDatabase + + + Windows + true + + + Ws2_32.lib + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + + + Windows + true + + + Ws2_32.lib + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + StreamingSIMDExtensions2 + Fast + + + Windows + true + true + true + + + Ws2_32.lib + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + StreamingSIMDExtensions2 + Fast + + + Windows + true + true + true + + + Ws2_32.lib + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + + + + true + true + true + true + + + + + + + true + true + true + true + + + + + AnySuitable + true + Speed + AnySuitable + Speed + AnySuitable + true + Speed + false + AnySuitable + Speed + false + StreamingSIMDExtensions2 + Fast + StreamingSIMDExtensions2 + Fast + MaxSpeed + MaxSpeed + Default + Default + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AssemblyAndSourceCode + AssemblyAndSourceCode + + + + + + \ No newline at end of file diff --git a/native.vcxproj.filters b/native.vcxproj.filters index da9f3d708f..86008ceba8 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -1,519 +1,531 @@ - - - - - file - - - - base - - - - ext - - - tools - - - ui - - - - - gfx - - - image - - - image - - - image - - - image - - - math - - - math - - - math - - - gfx - - - gfx - - - gfx - - - audio - - - audio - - - profiler - - - input - - - file - - - file - - - file - - - file - - - base - - - base - - - base - - - gfx - - - gfx - - - math - - - base - - - base - - - ext - - - ext - - - gfx - - - input - - - base - - - ext - - - base - - - gfx - - - json - - - file - - - math - - - gfx - - - base - - - base - - - ui - - - midi - - - file - - - base - - - util - - - data - - - base - - - net - - - base - - - file - - - net - - - android - - - android - - - ui - - - base - - - base - - - base - - - math - - - math - - - util - - - util - - - ext - - - ui - - - math - - - ui - - - ext - - - gfx - - - util - - - ext - - - ext - - - ext - - - thread - - - thread - - - thread - - - i18n - - - file - - - thread - - - - - gfx - - - image - - - image - - - image - - - math - - - math - - - math - - - gfx - - - gfx - - - gfx - - - audio - - - audio - - - profiler - - - file - - - file - - - file - - - gfx - - - gfx - - - base - - - base - - - ext - - - ext - - - gfx - - - input - - - ext - - - base - - - gfx - - - json - - - file - - - gfx - - - base - - - ui - - - midi - - - file - - - util - - - math - - - net - - - base - - - file - - - base - - - net - - - android - - - android - - - android - - - ui - - - base - - - math - - - math - - - util - - - ext - - - ui - - - math - - - ui - - - - - ext - - - base - - - gfx - - - util - - - ext - - - ext - - - thread - - - thread - - - i18n - - - file - - - thread - - - - - {9da89505-72a1-40e6-86e5-705372db1608} - - - {828bddaf-63e5-4311-985b-bf377f86ff00} - - - {f3f83007-7c3b-473f-a2f7-423c5087fbfa} - - - {5c54b5e2-1bb2-4783-9df6-de4ff7105570} - - - {4ea45f6c-de87-44a9-95b2-e1ec7e3601d0} - - - {c57b41dd-cc33-46ac-b479-19676455ae54} - - - {4ba4474c-b80f-40da-95e8-2de57eb1b327} - - - {49afd06e-eb44-41ac-b038-e109e444a834} - - - {a52d761c-4c72-4261-be17-50d071bd5cc8} - - - {95e41110-57a2-497f-a938-b4c8e9dd6a27} - - - {cda27e9f-5763-4bf2-b6bc-85a377f7020e} - - - {d738c2d1-749d-4b60-b98f-f3da0bbbf40c} - - - {4710a9a2-d1fa-4920-ba1b-a7527902be53} - - - {e36ca540-863c-496b-b0f4-b1ece3e72feb} - - - {d5fa3d62-88bf-4dc4-9814-28f3c0444e62} - - - {1e85f968-7106-483c-ae7d-77d0ef58d787} - - - {6a548b3d-3a4c-4114-aa2f-0b42bf7bf2ce} - - - {b7bc9a09-29c1-447b-9255-fe0709d10689} - - - {4515306f-4664-46bf-a89b-abfec5520a15} - - - {caa41117-1d90-47cc-9fba-f7e670e315a3} - - - {02e8ef95-82c7-4420-b029-a189a5e0fcbd} - - + + + + + file + + + + base + + + + ext + + + tools + + + ui + + + + + gfx + + + image + + + image + + + image + + + image + + + math + + + math + + + math + + + gfx + + + gfx + + + gfx + + + audio + + + audio + + + profiler + + + input + + + file + + + file + + + file + + + file + + + base + + + base + + + base + + + gfx + + + gfx + + + math + + + base + + + base + + + ext + + + ext + + + gfx + + + input + + + base + + + ext + + + base + + + gfx + + + json + + + file + + + math + + + gfx + + + base + + + base + + + ui + + + midi + + + file + + + base + + + util + + + data + + + base + + + net + + + base + + + file + + + net + + + android + + + android + + + ui + + + base + + + base + + + base + + + math + + + math + + + util + + + util + + + ext + + + ui + + + math + + + ui + + + ext + + + gfx + + + util + + + ext + + + ext + + + ext + + + thread + + + thread + + + thread + + + i18n + + + file + + + thread + + + ui + + + ui + + + + + gfx + + + image + + + image + + + image + + + math + + + math + + + math + + + gfx + + + gfx + + + gfx + + + audio + + + audio + + + profiler + + + file + + + file + + + file + + + gfx + + + gfx + + + base + + + base + + + ext + + + ext + + + gfx + + + input + + + ext + + + base + + + gfx + + + json + + + file + + + gfx + + + base + + + ui + + + midi + + + file + + + util + + + math + + + net + + + base + + + file + + + base + + + net + + + android + + + android + + + android + + + ui + + + base + + + math + + + math + + + util + + + ext + + + ui + + + math + + + ui + + + + + ext + + + base + + + gfx + + + util + + + ext + + + ext + + + thread + + + thread + + + i18n + + + file + + + thread + + + ui + + + ui + + + + + {9da89505-72a1-40e6-86e5-705372db1608} + + + {828bddaf-63e5-4311-985b-bf377f86ff00} + + + {f3f83007-7c3b-473f-a2f7-423c5087fbfa} + + + {5c54b5e2-1bb2-4783-9df6-de4ff7105570} + + + {4ea45f6c-de87-44a9-95b2-e1ec7e3601d0} + + + {c57b41dd-cc33-46ac-b479-19676455ae54} + + + {4ba4474c-b80f-40da-95e8-2de57eb1b327} + + + {49afd06e-eb44-41ac-b038-e109e444a834} + + + {a52d761c-4c72-4261-be17-50d071bd5cc8} + + + {95e41110-57a2-497f-a938-b4c8e9dd6a27} + + + {cda27e9f-5763-4bf2-b6bc-85a377f7020e} + + + {d738c2d1-749d-4b60-b98f-f3da0bbbf40c} + + + {4710a9a2-d1fa-4920-ba1b-a7527902be53} + + + {e36ca540-863c-496b-b0f4-b1ece3e72feb} + + + {d5fa3d62-88bf-4dc4-9814-28f3c0444e62} + + + {1e85f968-7106-483c-ae7d-77d0ef58d787} + + + {6a548b3d-3a4c-4114-aa2f-0b42bf7bf2ce} + + + {b7bc9a09-29c1-447b-9255-fe0709d10689} + + + {4515306f-4664-46bf-a89b-abfec5520a15} + + + {caa41117-1d90-47cc-9fba-f7e670e315a3} + + + {02e8ef95-82c7-4420-b029-a189a5e0fcbd} + + \ No newline at end of file diff --git a/ui/screen.cpp b/ui/screen.cpp index fd7661fab6..d74ceb627a 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -1,175 +1,175 @@ -#include "base/logging.h" -#include "input/input_state.h" -#include "ui/screen.h" -#include "ui/ui.h" - -ScreenManager::ScreenManager() { - nextScreen_ = 0; - uiContext_ = 0; - dialogFinished_ = 0; -} - -ScreenManager::~ScreenManager() { - shutdown(); -} - -void ScreenManager::switchScreen(Screen *screen) { - // Note that if a dialog is found, this will be a silent background switch that - // will only become apparent if the dialog is closed. The previous screen will stick around - // until that switch. - // TODO: is this still true? - if (nextScreen_ != 0) { - FLOG("WTF? Already had a nextScreen_"); - } - if (stack_.empty() || screen != stack_.back().screen) { - nextScreen_ = screen; - nextScreen_->setScreenManager(this); - } -} - -void ScreenManager::update(InputState &input) { - if (nextScreen_) { - ILOG("Screen switch! Top of the stack switches."); - switchToNext(); - } - - if (stack_.size()) { - stack_.back().screen->update(input); - } -} - -void ScreenManager::switchToNext() -{ - Layer temp = {0, 0}; - if (!stack_.empty()) - { - temp = stack_.back(); - stack_.pop_back(); - } - Layer newLayer = {nextScreen_, 0}; - stack_.push_back(newLayer); - delete temp.screen; - nextScreen_ = 0; -} - -void ScreenManager::touch(int pointer, float x, float y, double time, TouchEvent event) -{ - if (stack_.size()) { - stack_.back().screen->touch(pointer, x, y, time, event); - return; - } -} - -void ScreenManager::render() { - if (stack_.size()) { - switch (stack_.back().flags) - { - case LAYER_SIDEMENU: - if (stack_.size() == 1) - { - ELOG("Can't have sidemenu over nothing"); - break; - } - else - { - auto iter = stack_.end(); - iter--; - iter--; - Layer backback = *iter; - UIDisableBegin(); - // Also shift to the right somehow... - backback.screen->render(); - UIDisableEnd(); - stack_.back().screen->render(); - break; - } - default: - stack_.back().screen->render(); - break; - } - } else { - ELOG("No current screen!"); - } - - processFinishDialog(); -} - -void ScreenManager::sendMessage(const char *msg, const char *value) -{ - if (stack_.size()) - stack_.back().screen->sendMessage(msg, value); -} - -void ScreenManager::deviceLost() -{ - if (stack_.size()) - stack_.back().screen->deviceLost(); - // Dialogs too? Nah, they should only use the standard UI texture anyway. - // TODO: Change this when it becomes necessary. -} - -Screen *ScreenManager::topScreen() { - if (stack_.size()) - return stack_.back().screen; - else - return 0; -} - -void ScreenManager::shutdown() { - for (auto x = stack_.begin(); x != stack_.end(); x++) - { - delete x->screen; - } - stack_.clear(); - delete nextScreen_; - nextScreen_ = 0; -} - -void ScreenManager::push(Screen *screen, int layerFlags) { - if (nextScreen_ && stack_.empty()) { - // we're during init, this is OK - switchToNext(); - } - screen->setScreenManager(this); - Layer layer = {screen, layerFlags}; - stack_.push_back(layer); -} - -void ScreenManager::pop() { - if (stack_.size()) { - delete stack_.back().screen; - stack_.pop_back(); - } else { - ELOG("Can't pop when stack empty"); - } -} - -void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) -{ - if (dialog != stack_.back().screen) - { - ELOG("Wrong dialog being finished!"); - return; - } - if (!stack_.size()) { - ELOG("Must be in a dialog to finishDialog"); - return; - } - dialogFinished_ = dialog; - dialogResult_ = result; -} - -void ScreenManager::processFinishDialog() -{ - if (dialogFinished_) - { - if (stack_.size()) { - stack_.pop_back(); - } - - Screen *caller = topScreen(); - caller->dialogFinished(dialogFinished_, dialogResult_); - delete dialogFinished_; - dialogFinished_ = 0; - } -} +#include "base/logging.h" +#include "input/input_state.h" +#include "ui/screen.h" +#include "ui/ui.h" + +ScreenManager::ScreenManager() { + nextScreen_ = 0; + uiContext_ = 0; + dialogFinished_ = 0; +} + +ScreenManager::~ScreenManager() { + shutdown(); +} + +void ScreenManager::switchScreen(Screen *screen) { + // Note that if a dialog is found, this will be a silent background switch that + // will only become apparent if the dialog is closed. The previous screen will stick around + // until that switch. + // TODO: is this still true? + if (nextScreen_ != 0) { + FLOG("WTF? Already had a nextScreen_"); + } + if (stack_.empty() || screen != stack_.back().screen) { + nextScreen_ = screen; + nextScreen_->setScreenManager(this); + } +} + +void ScreenManager::update(InputState &input) { + if (nextScreen_) { + ILOG("Screen switch! Top of the stack switches."); + switchToNext(); + } + + if (stack_.size()) { + stack_.back().screen->update(input); + } +} + +void ScreenManager::switchToNext() +{ + Layer temp = {0, 0}; + if (!stack_.empty()) + { + temp = stack_.back(); + stack_.pop_back(); + } + Layer newLayer = {nextScreen_, 0}; + stack_.push_back(newLayer); + delete temp.screen; + nextScreen_ = 0; +} + +void ScreenManager::touch(const TouchInput &touch) +{ + if (stack_.size()) { + stack_.back().screen->touch(touch); + return; + } +} + +void ScreenManager::render() { + if (stack_.size()) { + switch (stack_.back().flags) + { + case LAYER_SIDEMENU: + if (stack_.size() == 1) + { + ELOG("Can't have sidemenu over nothing"); + break; + } + else + { + auto iter = stack_.end(); + iter--; + iter--; + Layer backback = *iter; + UIDisableBegin(); + // Also shift to the right somehow... + backback.screen->render(); + UIDisableEnd(); + stack_.back().screen->render(); + break; + } + default: + stack_.back().screen->render(); + break; + } + } else { + ELOG("No current screen!"); + } + + processFinishDialog(); +} + +void ScreenManager::sendMessage(const char *msg, const char *value) +{ + if (stack_.size()) + stack_.back().screen->sendMessage(msg, value); +} + +void ScreenManager::deviceLost() +{ + if (stack_.size()) + stack_.back().screen->deviceLost(); + // Dialogs too? Nah, they should only use the standard UI texture anyway. + // TODO: Change this when it becomes necessary. +} + +Screen *ScreenManager::topScreen() { + if (stack_.size()) + return stack_.back().screen; + else + return 0; +} + +void ScreenManager::shutdown() { + for (auto x = stack_.begin(); x != stack_.end(); x++) + { + delete x->screen; + } + stack_.clear(); + delete nextScreen_; + nextScreen_ = 0; +} + +void ScreenManager::push(Screen *screen, int layerFlags) { + if (nextScreen_ && stack_.empty()) { + // we're during init, this is OK + switchToNext(); + } + screen->setScreenManager(this); + Layer layer = {screen, layerFlags}; + stack_.push_back(layer); +} + +void ScreenManager::pop() { + if (stack_.size()) { + delete stack_.back().screen; + stack_.pop_back(); + } else { + ELOG("Can't pop when stack empty"); + } +} + +void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) +{ + if (dialog != stack_.back().screen) + { + ELOG("Wrong dialog being finished!"); + return; + } + if (!stack_.size()) { + ELOG("Must be in a dialog to finishDialog"); + return; + } + dialogFinished_ = dialog; + dialogResult_ = result; +} + +void ScreenManager::processFinishDialog() +{ + if (dialogFinished_) + { + if (stack_.size()) { + stack_.pop_back(); + } + + Screen *caller = topScreen(); + caller->dialogFinished(dialogFinished_, dialogResult_); + delete dialogFinished_; + dialogFinished_ = 0; + } +} diff --git a/ui/screen.h b/ui/screen.h index f77becca33..54376b2227 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -1,114 +1,114 @@ -// Super basic screen manager. Let's you, well, switch between screens. Can also be used -// to pop one screen in front for a bit while keeping another one running, it's basically -// a native "activity stack". Well actually that part is still a TODO. -// -// Semantics -// -// switchScreen: When you call this, on a newed screen, the ScreenManager takes ownership. -// On the next update, it switches to the new screen and deletes the previous screen. -// -// TODO: A way to do smooth transitions between screens. Will probably involve screenshotting -// the previous screen and then animating it on top of the current screen with transparency -// and/or other similar effects. - -#pragma once - -#include - -#include "base/basictypes.h" -#include "base/display.h" -#include "base/NativeApp.h" - -struct InputState; - -enum DialogResult { - DR_OK, - DR_CANCEL, - DR_YES, - DR_NO, -}; - -class ScreenManager; -class UIContext; - -class Screen { -public: - Screen(bool isUiScreen = false) : screenManager_(0), isUiScreen_(isUiScreen) { } - virtual ~Screen() {} - - virtual void update(InputState &input) = 0; - virtual void render() {} - virtual void deviceLost() {} - virtual void dialogFinished(const Screen *dialog, DialogResult result) {} - virtual void touch(int pointer, float x, float y, double time, TouchEvent event) {} - virtual void sendMessage(const char *msg, const char *value) {} - - ScreenManager *screenManager() { return screenManager_; } - void setScreenManager(ScreenManager *sm) { screenManager_ = sm; } - - virtual void *dialogData() { return 0; } - -private: - ScreenManager *screenManager_; - bool isUiScreen_; - DISALLOW_COPY_AND_ASSIGN(Screen); -}; - -class Transition { -public: - Transition() {} -}; - -enum { - LAYER_SIDEMENU = 1, - LAYER_TRANSPARENT = 2, -}; - -class ScreenManager { -public: - ScreenManager(); - virtual ~ScreenManager(); - - void switchScreen(Screen *screen); - void update(InputState &input); - - void setUIContext(UIContext *context) { uiContext_ = context; } - UIContext *getUIContext() { return uiContext_; } - - void render(); - void deviceLost(); - void shutdown(); - - // Push a dialog box in front. Currently 1-level only. - void push(Screen *screen, int layerFlags = 0); - - // Pops the dialog away. - void finishDialog(const Screen *dialog, DialogResult result = DR_OK); - - // Instant touch, separate from the update() mechanism. - void touch(int pointer, float x, float y, double time, TouchEvent event); - - // Generic facility for gross hacks :P - void sendMessage(const char *msg, const char *value); - -private: - void pop(); - void switchToNext(); - void processFinishDialog(); - Screen *topScreen(); - - Screen *nextScreen_; - UIContext *uiContext_; - - const Screen *dialogFinished_; - DialogResult dialogResult_; - - struct Layer { - Screen *screen; - int flags; // From LAYER_ enum above - }; - - // Dialog stack. These are shown "on top" of base screens and the Android back button works as expected. - // Used for options, in-game menus and other things you expect to be able to back out from onto something. - std::list stack_; -}; +// Super basic screen manager. Let's you, well, switch between screens. Can also be used +// to pop one screen in front for a bit while keeping another one running, it's basically +// a native "activity stack". Well actually that part is still a TODO. +// +// Semantics +// +// switchScreen: When you call this, on a newed screen, the ScreenManager takes ownership. +// On the next update, it switches to the new screen and deletes the previous screen. +// +// TODO: A way to do smooth transitions between screens. Will probably involve screenshotting +// the previous screen and then animating it on top of the current screen with transparency +// and/or other similar effects. + +#pragma once + +#include + +#include "base/basictypes.h" +#include "base/display.h" +#include "base/NativeApp.h" + +struct InputState; + +enum DialogResult { + DR_OK, + DR_CANCEL, + DR_YES, + DR_NO, +}; + +class ScreenManager; +class UIContext; + +class Screen { +public: + Screen(bool isUiScreen = false) : screenManager_(0), isUiScreen_(isUiScreen) { } + virtual ~Screen() {} + + virtual void update(InputState &input) = 0; + virtual void render() {} + virtual void deviceLost() {} + virtual void dialogFinished(const Screen *dialog, DialogResult result) {} + virtual void touch(const TouchInput &touch) {} + virtual void sendMessage(const char *msg, const char *value) {} + + ScreenManager *screenManager() { return screenManager_; } + void setScreenManager(ScreenManager *sm) { screenManager_ = sm; } + + virtual void *dialogData() { return 0; } + +private: + ScreenManager *screenManager_; + bool isUiScreen_; + DISALLOW_COPY_AND_ASSIGN(Screen); +}; + +class Transition { +public: + Transition() {} +}; + +enum { + LAYER_SIDEMENU = 1, + LAYER_TRANSPARENT = 2, +}; + +class ScreenManager { +public: + ScreenManager(); + virtual ~ScreenManager(); + + void switchScreen(Screen *screen); + void update(InputState &input); + + void setUIContext(UIContext *context) { uiContext_ = context; } + UIContext *getUIContext() { return uiContext_; } + + void render(); + void deviceLost(); + void shutdown(); + + // Push a dialog box in front. Currently 1-level only. + void push(Screen *screen, int layerFlags = 0); + + // Pops the dialog away. + void finishDialog(const Screen *dialog, DialogResult result = DR_OK); + + // Instant touch, separate from the update() mechanism. + void touch(const TouchInput &touch); + + // Generic facility for gross hacks :P + void sendMessage(const char *msg, const char *value); + +private: + void pop(); + void switchToNext(); + void processFinishDialog(); + Screen *topScreen(); + + Screen *nextScreen_; + UIContext *uiContext_; + + const Screen *dialogFinished_; + DialogResult dialogResult_; + + struct Layer { + Screen *screen; + int flags; // From LAYER_ enum above + }; + + // Dialog stack. These are shown "on top" of base screens and the Android back button works as expected. + // Used for options, in-game menus and other things you expect to be able to back out from onto something. + std::list stack_; +}; diff --git a/ui/view.cpp b/ui/view.cpp new file mode 100644 index 0000000000..bd0cad34fb --- /dev/null +++ b/ui/view.cpp @@ -0,0 +1,193 @@ +#include "base/display.h" +#include "base/mutex.h" +#include "input/input_state.h" +#include "gfx_es2/draw_buffer.h" +#include "gfx/texture_atlas.h" +#include "ui/ui.h" +#include "ui/view.h" + +namespace UI { + +static View *focusedView; + +const float ITEM_HEIGHT = 48.f; + +View *GetFocusedView() { + return focusedView; +} + +void SetFocusedView(View *view) { + focusedView = view; +} + +void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured) { + *measured = sz; + if (sz == WRAP_CONTENT) { + if (spec.type == UNSPECIFIED || spec.type == AT_MOST) + *measured = contentWidth; + else if (spec.type == EXACTLY) + *measured = spec.size; + } else if (sz == FILL_PARENT) { + if (spec.type == UNSPECIFIED) + *measured = 0.0; // We have no value to set + else + *measured = spec.size; + } else if (spec.type == EXACTLY || (spec.type == AT_MOST && *measured > spec.size)) { + *measured = spec.size; + } +} + + +void Event::Add(std::function func) { + HandlerRegistration reg; + reg.func = func; + handlers_.push_back(reg); +} + +// Call this from input thread or whatever, it doesn't matter +void Event::Trigger(const EventParams &e) { + lock_guard guard(mutex_); + if (!triggered_) { + triggered_ = true; + eventParams_ = e; + } +} + +// Call this from UI thread +void Event::Update() { + lock_guard guard(mutex_); + if (triggered_) { + for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { + (iter->func)(eventParams_); + } + triggered_ = false; + } +} + + +void View::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { + float contentW = 0.0f, contentH = 0.0f; + GetContentDimensions(dc, contentW, contentH); + MeasureBySpec(layoutParams_->width, contentW, horiz, &measuredWidth_); + MeasureBySpec(layoutParams_->height, contentH, vert, &measuredHeight_); +} + +// Default values + +void View::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { + w = 10.0f; + h = 10.0f; +} + +void Clickable::Click() { + UI::EventParams e; + e.v = this; + OnClick.Trigger(e); +}; + +void Clickable::Touch(const TouchInput &input) { + if (input.flags & (TOUCH_DOWN | TOUCH_MOVE)) { + if (bounds_.Contains(input.x, input.y)) { + SetFocusedView(this); + down_ = true; + } else { + down_ = false; + } + } + if (input.flags & TOUCH_UP) { + if (bounds_.Contains(input.x, input.y)) { + Click(); + } + down_ = false; + } +} + +void Choice::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { + // Will be sized to fill parent horizontally. + w = 0.0f; + h = ITEM_HEIGHT; +} + +void Choice::Draw(DrawContext &dc) { + int paddingX = 4; + int paddingY = 4; + dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); + // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); +} + +void Button::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { + dc.draw->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); +} + +void Button::Draw(DrawContext &dc) { + int image = down_ ? dc.theme->buttonImage : dc.theme->buttonSelected; + + dc.draw->DrawImage4Grid(dc.theme->buttonImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style_.bgColor); + dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.centerX(), bounds_.centerY(), style_.fgColor, ALIGN_CENTER); +} + +void ImageView::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { + const AtlasImage &img = dc.draw->GetAtlas()->images[atlasImage_]; + // TODO: involve sizemode + w = img.w; + h = img.h; +} + +void ImageView::Draw(DrawContext &dc) { + // TODO: involve sizemode + dc.draw->DrawImage(atlasImage_, bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF); +} + +void TextView::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { + dc.draw->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); +} + +void TextView::Draw(DrawContext &dc) { + // TODO: involve sizemode + dc.draw->DrawTextRect(dc.theme->uiFont, text_.c_str(), bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF); +} + +/* +TabStrip::TabStrip() + : selected_(0) { +} + +void TabStrip::Touch(const TouchInput &touch) { + int tabw = bounds_.w / tabs_.size(); + int h = 20; + if (touch.flags & TOUCH_DOWN) { + for (int i = 0; i < MAX_POINTERS; i++) { + if (UIRegionHit(i, bounds_.x, bounds_.y, bounds_.w, h, 8)) { + selected_ = (touch.x - bounds_.x) / tabw; + } + } + if (selected_ < 0) selected_ = 0; + if (selected_ >= (int)tabs_.size()) selected_ = (int)tabs_.size() - 1; + } +} + +void TabStrip::Draw(DrawContext &dc) { + int tabw = bounds_.w / tabs_.size(); + int h = 20; + for (int i = 0; i < numTabs; i++) { + dc.draw->DrawImageStretch(WHITE, x + 1, y + 2, x + tabw - 1, y + h, 0xFF202020); + dc.draw->DrawText(font, tabs_[i].title.c_str(), x + tabw/2, y + h/2, 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_HCENTER); + if (selected_ == i) { + float tw, th; + ui_draw2d.MeasureText(font, names[i], &tw, &th); + // TODO: better image + ui_draw2d.DrawImageStretch(WHITE, x + 1, y + h - 6, x + tabw - 1, y + h, tabColors ? tabColors[i] : 0xFFFFFFFF); + } else { + ui_draw2d.DrawImageStretch(WHITE, x + 1, y + h - 1, x + tabw - 1, y + h, tabColors ? tabColors[i] : 0xFFFFFFFF); + } + x += tabw; + } +}*/ + +void Fill(DrawContext &dc, const Bounds &bounds, const Drawable &drawable) { + if (drawable.type == DRAW_SOLID_COLOR) { + + } +} + +} // namespace diff --git a/ui/view.h b/ui/view.h new file mode 100644 index 0000000000..50d0ea1d87 --- /dev/null +++ b/ui/view.h @@ -0,0 +1,416 @@ +#pragma once + +// More traditional UI framework than ui/ui.h. + +// Still very simple to use. + +// Works very similarly to Android, there's a Measure pass and a Layout pass which you don't +// really need to care about if you just use the standard containers and widgets. + +#include +#include + +#include "base/mutex.h" +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "math/lin/matrix4x4.h" + +struct TouchInput; + +class DrawBuffer; +class DrawContext; + +// I don't generally like namespaces but I think we do need one for UI, so many potentially-clashing names. +namespace UI { + +enum DrawableType { + DRAW_NOTHING, + DRAW_SOLID_COLOR, + DRAW_4GRID, +}; + +struct Drawable { + Drawable() : type(DRAW_NOTHING) {} + + DrawableType type; + uint32_t data; +}; + +struct Style { + Style() : fgColor(0xFFFFFFFF), bgColor(0xFF303030) {} + + uint32_t fgColor; + uint32_t bgColor; +}; + +// To use with an UI atlas. +struct Theme { + int uiFont; + int uiFontSmall; + int uiFontSmaller; + int buttonImage; + int buttonSelected; + int checkOn; + int checkOff; + Style buttonStyle; +}; + +enum { + WRAP_CONTENT = -1, + FILL_PARENT = -2, +}; + +// Gravity +enum Gravity { + G_LEFT = 0, + G_RIGHT = 1, + G_HCENTER = 2, + + G_HORIZMASK = 3, + + G_TOP = 0, + G_BOTTOM = 4, + G_VCENTER = 8, + + G_TOPLEFT = G_TOP | G_LEFT, + G_TOPRIGHT = G_TOP | G_RIGHT, + + G_BOTTOMLEFT = G_BOTTOM | G_LEFT, + G_BOTTOMRIGHT = G_BOTTOM | G_RIGHT, + + G_VERTMASK = 3 << 2, +}; + +typedef float Size; // can also be WRAP_CONTENT or FILL_PARENT. + +enum Orientation { + ORIENT_HORIZONTAL, + ORIENT_VERTICAL, +}; + +enum MeasureSpecType { + UNSPECIFIED, + EXACTLY, + AT_MOST, +}; + +enum EventReturn { + EVENT_DONE, + EVENT_SKIPPED, +}; + +class ViewGroup; + +// Resolved bounds on screen after layout. +struct Bounds { + bool Contains(float px, float py) const { + return (px >= x && py >= y && px < x + w && py < y + h); + } + + float x2() const { return x + w; } + float y2() const { return y + h; } + float centerX() const { return x + w * 0.5f; } + float centerY() const { return y + h * 0.5f; } + + float x; + float y; + float w; + float h; +}; + + +void Fill(DrawContext &dc, const Bounds &bounds, const Drawable &drawable); + + +struct MeasureSpec { + MeasureSpec(MeasureSpecType t, float s = 0.0f) : type(t), size(s) {} + MeasureSpec() : type(UNSPECIFIED), size(0) {} + + MeasureSpec operator -(float amount) { + // TODO: Check type + return MeasureSpec(type, size - amount); + } + MeasureSpecType type; + float size; +}; + +class View; + +struct DrawContext { + DrawBuffer *draw; + DrawBuffer *drawTop; + const Theme *theme; +}; + +// Should cover all bases. +struct EventParams { + View *v; + uint32_t a, b, x, y; + const char *c; +}; + +struct HandlerRegistration { + std::function func; +}; + +class Event { +public: + Event() : triggered_(false) {} + + void Add(std::function func); + + // Call this from input thread or whatever, it doesn't matter + void Trigger(const EventParams &e); + // Call this from UI thread + void Update(); + +private: + recursive_mutex mutex_; + std::vector handlers_; + bool triggered_; + EventParams eventParams_; + + DISALLOW_COPY_AND_ASSIGN(Event); +}; + +struct Margins { + Margins() : top(0), bottom(0), left(0), right(0) {} + explicit Margins(uint8_t all) : top(all), bottom(all), left(all), right(all) {} + uint8_t top; + uint8_t bottom; + uint8_t left; + uint8_t right; +}; + +// Need a virtual destructor so vtables are created, otherwise RTTI can't work +class LayoutParams { +public: + LayoutParams() + : width(WRAP_CONTENT), height(WRAP_CONTENT) {} + LayoutParams(Size w, Size h) + : width(w), height(h) {} + virtual ~LayoutParams() {} + + Size width; + Size height; +private: +}; + +class LinearLayoutParams : public LayoutParams { +public: + LinearLayoutParams() + : LayoutParams(), weight(0.0f), gravity(G_TOPLEFT), hasMargins_(false) {} + LinearLayoutParams(Size w, Size h, float wgt = 0.0f, Gravity grav = G_TOPLEFT) + : LayoutParams(w, h), weight(wgt), gravity(grav), hasMargins_(false) {} + LinearLayoutParams(Size w, Size h, float wgt, Gravity grav, const Margins &mgn) + : LayoutParams(w, h), weight(wgt), gravity(grav), margins(mgn), hasMargins_(true) {} + LinearLayoutParams(const Margins &mgn) + : LayoutParams(WRAP_CONTENT, WRAP_CONTENT), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} + + float weight; + Gravity gravity; + Margins margins; + + bool HasMargins() const { return hasMargins_; } + +private: + bool hasMargins_; +}; + +View *GetFocusedView(); + +class View { +public: + View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams) { + if (!layoutParams) + layoutParams_.reset(new LayoutParams()); + } + + virtual ~View() {} + + // Please note that Touch is called ENTIRELY asynchronously from drawing! + // Can even be called on a different thread! This is to really minimize latency, and decouple + // touch response from the frame rate. + virtual void Touch(const TouchInput &input) = 0; + + void Move(Bounds bounds) { + bounds_ = bounds; + } + + // Views don't do anything here in Layout, only containers implement this. + virtual void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + virtual void Layout() {} + virtual void Draw(DrawContext &dc) {} + + virtual float GetMeasuredWidth() const { return measuredWidth_; } + virtual float GetMeasuredHeight() const { return measuredHeight_; } + + // Override this for easy standard behaviour. No need to override Measure. + virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; + + // Called when the layout is done. + void SetBounds(Bounds bounds) { bounds_ = bounds; } + virtual const LayoutParams *GetLayoutParams() const { return layoutParams_.get(); } + const Bounds &GetBounds() const { return bounds_; } + + virtual bool CanBeFocused() const { return true; } + + bool Focused() const { + return GetFocusedView() == this; + } + +protected: + // Inputs to layout + scoped_ptr layoutParams_; + + // Results of measure pass. Set these in Measure. + float measuredWidth_; + float measuredHeight_; + + // Outputs of layout. X/Y are absolute screen coordinates, hierarchy is "gone" here. + Bounds bounds_; + + scoped_ptr transform_; + +private: + DISALLOW_COPY_AND_ASSIGN(View); +}; + +// These don't do anything when touched. +class InertView : public View { +public: + InertView(LayoutParams *layoutParams) + : View(layoutParams) {} + + virtual void Touch(const TouchInput &input) {} +}; + + +// All these light up their background when touched, or have focus. +class Clickable : public View { +public: + Clickable(LayoutParams *layoutParams) + : View(layoutParams) {} + + virtual void Touch(const TouchInput &input); + + Event OnClick; + +protected: + // Internal method that fires on a click. Default behaviour is to trigger + // the event. + // Use it for checking/unchecking checkboxes, etc. + virtual void Click(); + + bool down_; +}; + +class Button : public Clickable { +public: + Button(const std::string &text, LayoutParams *layoutParams = 0) + : Clickable(layoutParams), text_(text) {} + + virtual void Draw(DrawContext &dc); + virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; + +private: + Style style_; + std::string text_; + DISALLOW_COPY_AND_ASSIGN(Button); +}; + +// The following classes are mostly suitable as items in ListView which +// really is just a LinearLayout in a ScrollView, possibly with some special optimizations. + +// Use to trigger something or open a submenu screen. +class Choice : public Clickable { +public: + Choice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) + : Clickable(layoutParams), text_(text), smallText_(smallText) {} + + virtual void Draw(DrawContext &dc); + virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; + +private: + std::string text_; + std::string smallText_; +}; + +class CheckBox : public Clickable { +public: + CheckBox(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) + : Clickable(layoutParams), text_(text), smallText_(smallText) {} + + virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; + virtual void Draw(DrawContext &dc); + +private: + std::string text_; + std::string smallText_; +}; + +enum ImageSizeMode { + +}; + +class TextView : public InertView { +public: + TextView(int font, const std::string &text, LayoutParams *layoutParams = 0) + : InertView(layoutParams), font_(font), text_(text) {} + + virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; + virtual void Draw(DrawContext &dc); + virtual bool CanBeFocused() const { return false; } + +private: + std::string text_; + int font_; +}; + +class ImageView : public InertView { +public: + ImageView(int atlasImage, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0) + : InertView(layoutParams), atlasImage_(atlasImage), sizeMode_(sizeMode) {} + + virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; + virtual void Draw(DrawContext &dc); + virtual bool CanBeFocused() const { return false; } + +private: + int atlasImage_; + ImageSizeMode sizeMode_; +}; + +// This tab strip is a little special. +/* +class TabStrip : public View { +public: + TabStrip(); + + virtual void Touch(const TouchInput &input); + virtual void Draw(DrawContext &dc); + + void AddTab(const std::string &title, uint32_t color) { + Tab tab; + tab.title = title; + tab.color = color; + tabs_.push_back(tab); + } + +private: + int selected_; + struct Tab { + std::string title; + uint32_t color; + }; + std::vector tabs_; +};*/ + +// The ONLY global is the currently focused item. +// Can be and often is null. + +View *GetFocusedView(); +void SetFocusedView(View *view); +void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured); + +} // namespace \ No newline at end of file diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp new file mode 100644 index 0000000000..466ebfe15a --- /dev/null +++ b/ui/viewgroup.cpp @@ -0,0 +1,274 @@ +#include "base/display.h" +#include "base/logging.h" +#include "ui/view.h" +#include "ui/viewgroup.h" + +namespace UI { + +void ApplyGravity(const Bounds outer, const Margins &margins, float w, float h, int gravity, Bounds &inner) { + inner.w = w - (margins.left + margins.right); + inner.h = h - (margins.right + margins.left); + + switch (gravity & G_HORIZMASK) { + case G_LEFT: inner.x = outer.x + margins.left; break; + case G_RIGHT: inner.x = outer.x + outer.w - w - margins.right; break; + case G_HCENTER: inner.x = outer.x + (outer.w - w) / 2; break; + } + + switch (gravity & G_VERTMASK) { + case G_TOP: inner.y = outer.y + margins.top; break; + case G_BOTTOM: inner.y = outer.y + outer.h - h - margins.bottom; break; + case G_VCENTER: inner.y = outer.y + (outer.h - h) / 2; break; + } +} + +ViewGroup::~ViewGroup() { + // Tear down the contents recursively. + for (auto iter = views_.begin(); iter != views_.end(); ++iter) + delete *iter; +} + +void ViewGroup::Touch(const TouchInput &input) { + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + // TODO: If there is a transformation active, transform input coordinates accordingly. + (*iter)->Touch(input); + } +} + +void ViewGroup::Draw(DrawContext &dc) { + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + // TODO: If there is a transformation active, transform input coordinates accordingly. + (*iter)->Draw(dc); + } +} + +View *ViewGroup::FindNeighbor(View *view, FocusDirection direction) { + // First, find the position of the view in the list. + size_t num = -1; + for (size_t i = 0; i < views_.size(); i++) { + if (views_[i] == view) { + num = i; + break; + } + } + + // If view not found, no neighbor to find. + if (num == -1) + return 0; + + // TODO: Do the cardinal directions right. Now we just map to + // prev/next. + + switch (direction) { + case FOCUS_UP: + case FOCUS_LEFT: + case FOCUS_PREV: + return views_[(num + views_.size() - 1) % views_.size()]; + case FOCUS_RIGHT: + case FOCUS_DOWN: + case FOCUS_NEXT: + return views_[(num + 1) % views_.size()]; + + default: + return view; + } +} + +void FrameLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { + if (views_.empty()) { + ELOG("A FrameLayout must have a child view"); + return; + } +} + +void LinearLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { + if (!views_.size()) { + MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); + MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); + return; + } + + float sum = 0.0f; + float maxOther = 0.0f; + float totalWeight = 0.0f; + float weightSum = 0.0f; + float weightZeroSum = 0.0f; + + for (size_t i = 0; i < views_.size(); i++) { + const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); + const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); + Margins margins = defaultMargins_; + + if (linLayoutParams) { + totalWeight += linLayoutParams->weight; + if (linLayoutParams->HasMargins()) + margins = linLayoutParams->margins; + } + + if (orientation_ == ORIENT_HORIZONTAL) { + views_[i]->Measure(dc, MeasureSpec(UNSPECIFIED), vert - (float)(margins.top + margins.bottom)); + } else if (orientation_ == ORIENT_VERTICAL) { + views_[i]->Measure(dc, horiz - (float)(margins.left + margins.right), MeasureSpec(UNSPECIFIED)); + } + + float amount; + if (orientation_ == ORIENT_HORIZONTAL) { + amount = views_[i]->GetMeasuredWidth() + margins.left + margins.right; + maxOther = std::max(maxOther, views_[i]->GetMeasuredHeight() + margins.top + margins.bottom); + } else { + amount = views_[i]->GetMeasuredHeight() + margins.top + margins.bottom; + maxOther = std::max(maxOther, views_[i]->GetMeasuredWidth() + margins.left + margins.right); + } + + sum += amount; + if (linLayoutParams) { + if (linLayoutParams->weight == 0.0f) + weightZeroSum += amount; + + weightSum += linLayoutParams->weight; + } else { + weightZeroSum += amount; + } + } + + weightZeroSum += spacing_ * (views_.size() - 1); + + // Awright, got the sum. Let's take the remaining space after the fixed-size views, + // and distribute among the weighted ones. + if (orientation_ == ORIENT_HORIZONTAL) { + MeasureBySpec(layoutParams_->width, sum, horiz, &measuredWidth_); + MeasureBySpec(layoutParams_->height, maxOther, vert, &measuredHeight_); + + float unit = (measuredWidth_ - weightZeroSum) / weightSum; + // Redistribute the stretchy ones! and remeasure the children! + for (size_t i = 0; i < views_.size(); i++) { + const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); + const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); + + if (linLayoutParams && linLayoutParams->weight > 0.0) + views_[i]->Measure(dc, MeasureSpec(EXACTLY, unit * linLayoutParams->weight), vert); + } + } else { + MeasureBySpec(layoutParams_->height, sum, vert, &measuredHeight_); + MeasureBySpec(layoutParams_->width, maxOther, horiz, &measuredWidth_); + + float unit = (measuredHeight_ - weightZeroSum) / weightSum; + + // Redistribute! and remeasure children! + for (size_t i = 0; i < views_.size(); i++) { + const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); + const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); + + if (linLayoutParams && linLayoutParams->weight) + views_[i]->Measure(dc, horiz, MeasureSpec(EXACTLY, unit * linLayoutParams->weight)); + } + } +} + +// TODO: Stretch and squeeze! +// weight != 0 = fill remaining space. +void LinearLayout::Layout() { + const Bounds &bounds = bounds_; + + Bounds itemBounds; + float pos; + + if (orientation_ == ORIENT_HORIZONTAL) { + pos = bounds.x; + itemBounds.y = bounds.y; + itemBounds.h = measuredHeight_; + } else { + pos = bounds.y; + itemBounds.x = bounds.x; + itemBounds.w = measuredWidth_; + } + + for (size_t i = 0; i < views_.size(); i++) { + const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); + const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); + + Gravity gravity = G_TOPLEFT; + Margins margins = defaultMargins_; + if (linLayoutParams) { + if (linLayoutParams->HasMargins()) + margins = linLayoutParams->margins; + gravity = linLayoutParams->gravity; + } + + if (orientation_ == ORIENT_HORIZONTAL) { + itemBounds.x = pos; + itemBounds.w = views_[i]->GetMeasuredWidth() + margins.left + margins.right; + } else { + itemBounds.y = pos; + itemBounds.h = views_[i]->GetMeasuredHeight() + margins.top + margins.bottom; + } + + Bounds innerBounds; + ApplyGravity(itemBounds, margins, + views_[i]->GetMeasuredWidth(), views_[i]->GetMeasuredHeight(), + gravity, innerBounds); + + views_[i]->SetBounds(innerBounds); + views_[i]->Layout(); + + pos += spacing_ + (orientation_ == ORIENT_HORIZONTAL ? itemBounds.w : itemBounds.h); + } +} + +void ScrollView::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { + +} + +void ScrollView::Layout() { + Bounds scrolled = bounds_; + + switch (orientation_) { + case ORIENT_HORIZONTAL: + scrolled.x -= scrollPos_; + break; + case ORIENT_VERTICAL: + scrolled.y -= scrollPos_; + break; + } + views_[0]->SetBounds(scrolled); +} + +void ScrollView::Touch(const TouchInput &input) { + if ((input.flags & TOUCH_DOWN) && input.id == 0) { + scrollStart_ = orientation_ == ORIENT_HORIZONTAL ? input.x : input.y; + } + + gesture_.Update(input); + + if (gesture_.IsGestureActive(GESTURE_DRAG_VERTICAL)) { + float info[4]; + gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info); + } +} + +void GridLayout::Layout() { + +} + +void RelativeLayout::Layout() { + +} + +void LayoutViewHierarchy(const DrawContext &dc, ViewGroup *root) { + Bounds rootBounds; + rootBounds.x = 0; + rootBounds.y = 0; + rootBounds.w = dp_xres; + rootBounds.h = dp_yres; + + MeasureSpec horiz(EXACTLY, rootBounds.w); + MeasureSpec vert(EXACTLY, rootBounds.h); + + // Two phases - measure contents, layout. + root->Measure(dc, horiz, vert); + // Root has a specified size. Set it, then let root layout all its children. + root->SetBounds(rootBounds); + root->Layout(); +} + +} // namespace UI \ No newline at end of file diff --git a/ui/viewgroup.h b/ui/viewgroup.h new file mode 100644 index 0000000000..cbd43aabd4 --- /dev/null +++ b/ui/viewgroup.h @@ -0,0 +1,110 @@ +#pragma once + +#include "ui/view.h" +#include "input/gesture_detector.h" + +namespace UI { + +// The four cardinal directions should be enough, plus Prev/Next in "element order". +enum FocusDirection { + FOCUS_UP, + FOCUS_DOWN, + FOCUS_LEFT, + FOCUS_RIGHT, + FOCUS_NEXT, + FOCUS_PREV, +}; + +class ViewGroup : public View { +public: + ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams) {} + virtual ~ViewGroup(); + + // Pass through external events to children. + virtual void Touch(const TouchInput &input); + + // By default, a container will layout to its own bounds. + virtual void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) = 0; + virtual void Layout() = 0; + + virtual void Draw(DrawContext &dc); + + // These should be unused. + virtual float GetContentWidth() const { return 0.0f; } + virtual float GetContentHeight() const { return 0.0f; } + + // Takes ownership! DO NOT add a view to multiple parents! + void Add(View *view) { views_.push_back(view); } + + // Assumes that layout has taken place. + View *FindNeighbor(View *view, FocusDirection direction); + +protected: + std::vector views_; +}; + +// A frame layout contains a single child view (normally). +class FrameLayout : public ViewGroup { +public: + void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + void Layout(); +}; + +class RelativeLayout : public ViewGroup { +public: + void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + void Layout(); +}; + +class LinearLayout : public ViewGroup { +public: + LinearLayout(Orientation orientation, LayoutParams *layoutParams = 0) + : ViewGroup(layoutParams), spacing_(5), orientation_(orientation), defaultMargins_(0) {} + + void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + void Layout(); + +private: + Orientation orientation_; + Margins defaultMargins_; + float spacing_; +}; + +class GridLayout : public ViewGroup { +public: + GridLayout(Orientation orientation, int colsOrRows) : + orientation_(orientation), colsOrRows_(colsOrRows) {} + + void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + void Layout(); + +private: + Orientation orientation_; + int colsOrRows_; +}; + +// A scrollview usually contains just a single child - a linear layout or similar. +class ScrollView : public ViewGroup { +public: + ScrollView(Orientation orientation) : + orientation_(orientation) {} + + void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + void Layout(); + + void Touch(const TouchInput &input); + +private: + GestureDetector gesture_; + Orientation orientation_; + float scrollPos_; + float scrollStart_; +}; + +class ViewPager : public ScrollView { +public: +}; + +void LayoutViewHierarchy(const DrawContext &dc, ViewGroup *root); + +} // namespace UI \ No newline at end of file From f482d3c85742a25ede6cd8d45550e9ebef50167e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 25 May 2013 12:40:57 +0200 Subject: [PATCH 0402/1445] NewUI: Add basic keyboard focus movement --- ui/view.cpp | 47 ++++++++++++++---- ui/view.h | 121 ++++++++++++++++++++++++++++++++++++++++------- ui/viewgroup.cpp | 80 +++++++++++++++++++++++++++---- ui/viewgroup.h | 23 ++++----- 4 files changed, 223 insertions(+), 48 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index bd0cad34fb..39af395ff9 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -9,6 +9,7 @@ namespace UI { static View *focusedView; +static bool focusMovementEnabled; const float ITEM_HEIGHT = 48.f; @@ -20,6 +21,14 @@ void SetFocusedView(View *view) { focusedView = view; } +void EnableFocusMovement(bool enable) { + focusMovementEnabled = true; +} + +bool IsFocusMovementEnabled() { + return focusMovementEnabled; +} + void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured) { *measured = sz; if (sz == WRAP_CONTENT) { @@ -64,7 +73,6 @@ void Event::Update() { } } - void View::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { float contentW = 0.0f, contentH = 0.0f; GetContentDimensions(dc, contentW, contentH); @@ -88,7 +96,8 @@ void Clickable::Click() { void Clickable::Touch(const TouchInput &input) { if (input.flags & (TOUCH_DOWN | TOUCH_MOVE)) { if (bounds_.Contains(input.x, input.y)) { - SetFocusedView(this); + if (IsFocusMovementEnabled()) + SetFocusedView(this); down_ = true; } else { down_ = false; @@ -102,10 +111,18 @@ void Clickable::Touch(const TouchInput &input) { } } -void Choice::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { - // Will be sized to fill parent horizontally. - w = 0.0f; - h = ITEM_HEIGHT; +void Clickable::Update(const InputState &input_state) { + if (!HasFocus()) + return; + if (input_state.pad_buttons_down & PAD_BUTTON_A) { + down_ = true; + } else if (input_state.pad_buttons_up & PAD_BUTTON_A) { + if (down_) { + UI::EventParams e; + OnClick.Trigger(e); + } + down_ = false; + } } void Choice::Draw(DrawContext &dc) { @@ -115,15 +132,27 @@ void Choice::Draw(DrawContext &dc) { // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); } +void CheckBox::Draw(DrawContext &dc) { + int paddingX = 80; + int paddingY = 4; + dc.draw->DrawImage(dc.theme->checkOn, bounds_.x + 30, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); + dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.y + paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); + // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); +} + void Button::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { dc.draw->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); } void Button::Draw(DrawContext &dc) { int image = down_ ? dc.theme->buttonImage : dc.theme->buttonSelected; - - dc.draw->DrawImage4Grid(dc.theme->buttonImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style_.bgColor); - dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.centerX(), bounds_.centerY(), style_.fgColor, ALIGN_CENTER); + + Style style = dc.theme->buttonStyle; + if (HasFocus()) style = dc.theme->buttonFocusedStyle; + if (down_) style = dc.theme->buttonDownStyle; + + dc.draw->DrawImage4Grid(dc.theme->buttonImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); + dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); } void ImageView::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { diff --git a/ui/view.h b/ui/view.h index 50d0ea1d87..1944464876 100644 --- a/ui/view.h +++ b/ui/view.h @@ -16,6 +16,7 @@ #include "math/lin/matrix4x4.h" struct TouchInput; +struct InputState; class DrawBuffer; class DrawContext; @@ -23,6 +24,15 @@ class DrawContext; // I don't generally like namespaces but I think we do need one for UI, so many potentially-clashing names. namespace UI { +class View; + +// The ONLY global is the currently focused item. +// Can be and often is null. +void EnableFocusMovement(bool enable); +bool IsFocusMovementEnabled(); +View *GetFocusedView(); +void SetFocusedView(View *view); + enum DrawableType { DRAW_NOTHING, DRAW_SOLID_COLOR, @@ -52,7 +62,20 @@ struct Theme { int buttonSelected; int checkOn; int checkOff; + Style buttonStyle; + Style buttonFocusedStyle; + Style buttonDownStyle; +}; + +// The four cardinal directions should be enough, plus Prev/Next in "element order". +enum FocusDirection { + FOCUS_UP, + FOCUS_DOWN, + FOCUS_LEFT, + FOCUS_RIGHT, + FOCUS_NEXT, + FOCUS_PREV, }; enum { @@ -118,10 +141,8 @@ struct Bounds { float h; }; - void Fill(DrawContext &dc, const Bounds &bounds, const Drawable &drawable); - struct MeasureSpec { MeasureSpec(MeasureSpecType t, float s = 0.0f) : type(t), size(s) {} MeasureSpec() : type(UNSPECIFIED), size(0) {} @@ -232,6 +253,7 @@ public: // Can even be called on a different thread! This is to really minimize latency, and decouple // touch response from the frame rate. virtual void Touch(const TouchInput &input) = 0; + virtual void Update(const InputState &input_state) = 0; void Move(Bounds bounds) { bounds_ = bounds; @@ -253,9 +275,17 @@ public: virtual const LayoutParams *GetLayoutParams() const { return layoutParams_.get(); } const Bounds &GetBounds() const { return bounds_; } + virtual bool SetFocus() { + if (CanBeFocused()) { + SetFocusedView(this); + return true; + } + return false; + } + virtual void MoveFocus(FocusDirection direction) {} virtual bool CanBeFocused() const { return true; } - bool Focused() const { + bool HasFocus() const { return GetFocusedView() == this; } @@ -283,6 +313,8 @@ public: : View(layoutParams) {} virtual void Touch(const TouchInput &input) {} + virtual bool CanBeFocused() const { return false; } + virtual void Update(const InputState &input_state) {} }; @@ -290,9 +322,10 @@ public: class Clickable : public View { public: Clickable(LayoutParams *layoutParams) - : View(layoutParams) {} + : View(layoutParams), down_(false) {} virtual void Touch(const TouchInput &input); + virtual void Update(const InputState &input_state); Event OnClick; @@ -319,38 +352,93 @@ private: DISALLOW_COPY_AND_ASSIGN(Button); }; +class Item : public InertView { +public: + Item(LayoutParams *layoutParams) : InertView(layoutParams) { + layoutParams_->width = FILL_PARENT; + layoutParams_->height = 80; + } + + virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const { + w = 0.0f; + h = 0.0f; + } +}; + +class ClickableItem : public Clickable { +public: + ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParams) { + layoutParams_->width = FILL_PARENT; + layoutParams_->height = 80; + } + + virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const { + w = 0.0f; + h = 0.0f; + } +}; + + + // The following classes are mostly suitable as items in ListView which // really is just a LinearLayout in a ScrollView, possibly with some special optimizations. // Use to trigger something or open a submenu screen. -class Choice : public Clickable { +class Choice : public ClickableItem { public: Choice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) - : Clickable(layoutParams), text_(text), smallText_(smallText) {} + : ClickableItem(layoutParams), text_(text), smallText_(smallText) {} virtual void Draw(DrawContext &dc); - virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; private: std::string text_; std::string smallText_; }; +class InfoItem : public Item { +public: + InfoItem(const std::string &text, const std::string &rightText, LayoutParams *layoutParams = 0) + : Item(layoutParams), text_(text), rightText_(rightText) {} + + virtual void Draw(DrawContext &dc); + +private: + std::string text_; + std::string rightText_; +}; + class CheckBox : public Clickable { public: - CheckBox(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) - : Clickable(layoutParams), text_(text), smallText_(smallText) {} + CheckBox(bool *toggle, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) + : Clickable(layoutParams), text_(text), smallText_(smallText) { + OnClick.Add(std::bind(&CheckBox::OnClicked, this, std::placeholders::_1)); + } - virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; virtual void Draw(DrawContext &dc); + EventReturn OnClicked(const EventParams &e) { + if (toggle_) + *toggle_ = !(*toggle_); + return EVENT_DONE; + } private: + bool *toggle_; std::string text_; std::string smallText_; }; -enum ImageSizeMode { +// These are for generic use. + +class Spacer : public InertView { +public: + Spacer(LayoutParams *layoutParams = 0) + : InertView(layoutParams) {} + virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) { + w = 0.0f; h = 0.0f; + } + virtual void Draw(DrawContext &dc) {} }; class TextView : public InertView { @@ -360,13 +448,16 @@ public: virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; virtual void Draw(DrawContext &dc); - virtual bool CanBeFocused() const { return false; } private: std::string text_; int font_; }; +enum ImageSizeMode { + IS_DEFAULT, +}; + class ImageView : public InertView { public: ImageView(int atlasImage, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0) @@ -374,7 +465,6 @@ public: virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; virtual void Draw(DrawContext &dc); - virtual bool CanBeFocused() const { return false; } private: int atlasImage_; @@ -406,11 +496,6 @@ private: std::vector tabs_; };*/ -// The ONLY global is the currently focused item. -// Can be and often is null. - -View *GetFocusedView(); -void SetFocusedView(View *view); void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured); } // namespace \ No newline at end of file diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 466ebfe15a..26c5501c30 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -42,6 +42,39 @@ void ViewGroup::Draw(DrawContext &dc) { } } +void ViewGroup::Update(const InputState &input_state) { + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + // TODO: If there is a transformation active, transform input coordinates accordingly. + (*iter)->Update(input_state); + } +} + +bool ViewGroup::SetFocus() { + if (!CanBeFocused() && !views_.empty()) { + for (size_t i = 0; i < views_.size(); i++) { + if (views_[i]->SetFocus()) + return true; + } + } + return false; +} + +void ViewGroup::MoveFocus(FocusDirection direction) { + if (!GetFocusedView()) { + SetFocus(); + return; + } + + View *neighbor = FindNeighbor(GetFocusedView(), direction); + if (neighbor) { + neighbor->SetFocus(); + } else { + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + (*iter)->MoveFocus(direction); + } + } +} + View *ViewGroup::FindNeighbor(View *view, FocusDirection direction) { // First, find the position of the view in the list. size_t num = -1; @@ -74,15 +107,9 @@ View *ViewGroup::FindNeighbor(View *view, FocusDirection direction) { } } -void FrameLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { - if (views_.empty()) { - ELOG("A FrameLayout must have a child view"); - return; - } -} void LinearLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { - if (!views_.size()) { + if (views_.empty()) { MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); return; @@ -215,8 +242,26 @@ void LinearLayout::Layout() { } } +void FrameLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { + if (views_.empty()) { + MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); + MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); + return; + } + + for (size_t i = 0; i < views_.size(); i++) { + views_[i]->Measure(dc, horiz, vert); + } +} + +void FrameLayout::Layout() { + +} + void ScrollView::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { - + // The scroll view itself simply obeys its parent. + MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); + MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); } void ScrollView::Layout() { @@ -246,6 +291,7 @@ void ScrollView::Touch(const TouchInput &input) { } } + void GridLayout::Layout() { } @@ -271,4 +317,22 @@ void LayoutViewHierarchy(const DrawContext &dc, ViewGroup *root) { root->Layout(); } +void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { + if (input_state.pad_buttons_down & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) + EnableFocusMovement(true); + + if (input_state.pad_last_buttons == 0) { + if (input_state.pad_buttons_down & PAD_BUTTON_RIGHT) + root->MoveFocus(FOCUS_RIGHT); + if (input_state.pad_buttons_down & PAD_BUTTON_UP) + root->MoveFocus(FOCUS_UP); + if (input_state.pad_buttons_down & PAD_BUTTON_LEFT) + root->MoveFocus(FOCUS_LEFT); + if (input_state.pad_buttons_down & PAD_BUTTON_DOWN) + root->MoveFocus(FOCUS_DOWN); + } + + root->Update(input_state); +} + } // namespace UI \ No newline at end of file diff --git a/ui/viewgroup.h b/ui/viewgroup.h index cbd43aabd4..68d75d1c43 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -5,16 +5,6 @@ namespace UI { -// The four cardinal directions should be enough, plus Prev/Next in "element order". -enum FocusDirection { - FOCUS_UP, - FOCUS_DOWN, - FOCUS_LEFT, - FOCUS_RIGHT, - FOCUS_NEXT, - FOCUS_PREV, -}; - class ViewGroup : public View { public: ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams) {} @@ -26,6 +16,7 @@ public: // By default, a container will layout to its own bounds. virtual void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) = 0; virtual void Layout() = 0; + virtual void Update(const InputState &input_state); virtual void Draw(DrawContext &dc); @@ -36,9 +27,14 @@ public: // Takes ownership! DO NOT add a view to multiple parents! void Add(View *view) { views_.push_back(view); } + virtual bool SetFocus(); + virtual void MoveFocus(FocusDirection direction); + // Assumes that layout has taken place. View *FindNeighbor(View *view, FocusDirection direction); + virtual bool CanBeFocused() const { return false; } + protected: std::vector views_; }; @@ -72,15 +68,15 @@ private: class GridLayout : public ViewGroup { public: - GridLayout(Orientation orientation, int colsOrRows) : - orientation_(orientation), colsOrRows_(colsOrRows) {} + GridLayout(Orientation orientation, int numPerLine) : + orientation_(orientation), numPerLine_(numPerLine) {} void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); private: Orientation orientation_; - int colsOrRows_; + int numPerLine_; }; // A scrollview usually contains just a single child - a linear layout or similar. @@ -106,5 +102,6 @@ public: }; void LayoutViewHierarchy(const DrawContext &dc, ViewGroup *root); +void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root); } // namespace UI \ No newline at end of file From 02a3cc1b5b3d32a421f39246e17290c03abbe630 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 25 May 2013 15:12:46 +0200 Subject: [PATCH 0403/1445] ScrollView kinda working --- base/PCMain.cpp | 18 ++--- input/gesture_detector.cpp | 143 +++++++++++++++++++++---------------- input/gesture_detector.h | 92 ++++++++++++------------ ui/view.cpp | 11 ++- ui/view.h | 10 ++- ui/viewgroup.cpp | 41 +++++++++-- ui/viewgroup.h | 9 +-- 7 files changed, 198 insertions(+), 126 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 4aec8c6c81..0f0b694ac4 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -531,14 +531,16 @@ int main(int argc, char *argv[]) { quitRequested = 1; } } else if (event.type == SDL_MOUSEMOTION) { - input_state.pointer_x[0] = mx; - input_state.pointer_y[0] = my; - TouchInput input; - input.x = mx; - input.y = my; - input.flags = TOUCH_MOVE; - input.id = 0; - NativeTouch(input); + if (input_state.pointer_down[0]) { + input_state.pointer_x[0] = mx; + input_state.pointer_y[0] = my; + TouchInput input; + input.x = mx; + input.y = my; + input.flags = TOUCH_MOVE; + input.id = 0; + NativeTouch(input); + } } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { //input_state.mouse_buttons_down = 1; diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 880dab4c92..4a4e701e6f 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -1,60 +1,83 @@ -// Unfinished. -// TODO: -// Zoom gesture a la http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-6-implementing-the-pinch-zoom-gesture/1847 - -#include "input/gesture_detector.h" - -void GestureDetector::Update(const TouchInput &touch) { - // Mouse / 1-finger-touch control. - if (touch.flags & TOUCH_DOWN) { - pointers[0].down = true; - pointers[0].downX = touch.x; - pointers[0].downY = touch.y; - } else if (touch.flags & TOUCH_UP) { - pointers[0].down = false; - } - - pointers[0].lastX = pointers[0].X; - pointers[0].lastY = pointers[0].Y; - - // TODO: real multitouch -} - -bool GestureDetector::IsGestureActive(Gesture gesture) const { - // TODO - return false; -} - -void GestureDetector::GetGestureInfo(Gesture gesture, float info[4]) -{ -/* - -bool down(int i, float *xdelta, float *ydelta) { - if (!pointers[i].down) { - return false; - } - *xdelta = pointers[i].downX; - *ydelta = pointers[i].downY; - return true; -} - -bool dragDistance(int i, float *xdelta, float *ydelta) { - if (!pointers[i].down) - return false; - - *xdelta = pointers[i].X - pointers[i].downX; - *ydelta = pointers[i].Y - pointers[i].downY; - return true; -} - -bool dragDelta(int i, float *xdelta, float *ydelta) { - if (!pointers[i].down) - return false; - - *xdelta = pointers[i].X - pointers[i].lastX; - *ydelta = pointers[i].Y - pointers[i].lastY; - return true; -} -*/ - -} +// Unfinished. +// TODO: +// Zoom gesture a la http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-6-implementing-the-pinch-zoom-gesture/1847 + +#include "base/timeutil.h" +#include "input/gesture_detector.h" + +GestureDetector::GestureDetector() : active_(0) { + +} + +void GestureDetector::Update(const TouchInput &touch) { + // Mouse / 1-finger-touch control. + Pointer &p = pointers[touch.id]; + if (touch.flags & TOUCH_DOWN) { + p.down = true; + p.downTime = time_now_d(); + p.downX = touch.x; + p.downY = touch.y; + p.lastX = touch.x; + p.lastY = touch.y; + p.distanceX = 0.0f; + p.distanceY = 0.0f; + } else if (touch.flags & TOUCH_UP) { + p.down = false; + } else { + p.distanceX += fabsf(touch.x - p.lastX); + p.distanceY += fabsf(touch.y - p.lastY); + p.lastX = touch.x; + p.lastY = touch.y; + } + + if (touch.id == 0 && p.distanceY > p.distanceX) { + if (p.down) { + double timeDown = time_now_d() - p.downTime; + if (p.distanceY * timeDown > 3) { + active_ |= GESTURE_DRAG_VERTICAL; + } + } else { + active_ = 0; + } + } +} + +bool GestureDetector::IsGestureActive(Gesture gesture) const { + return (active_ & gesture) != 0; +} + +void GestureDetector::GetGestureInfo(Gesture gesture, float info[4]) { + if (gesture == GESTURE_DRAG_VERTICAL) { + info[0] = pointers[0].lastY - pointers[0].downY; + } +/* + +bool down(int i, float *xdelta, float *ydelta) { + if (!pointers[i].down) { + return false; + } + *xdelta = pointers[i].downX; + *ydelta = pointers[i].downY; + return true; +} + +bool dragDistance(int i, float *xdelta, float *ydelta) { + if (!pointers[i].down) + return false; + + *xdelta = pointers[i].X - pointers[i].downX; + *ydelta = pointers[i].Y - pointers[i].downY; + return true; +} + +bool dragDelta(int i, float *xdelta, float *ydelta) { + if (!pointers[i].down) + return false; + + *xdelta = pointers[i].X - pointers[i].lastX; + *ydelta = pointers[i].Y - pointers[i].lastY; + return true; +} +*/ + +} diff --git a/input/gesture_detector.h b/input/gesture_detector.h index b8457022be..8d0d2a2c9f 100644 --- a/input/gesture_detector.h +++ b/input/gesture_detector.h @@ -1,45 +1,47 @@ -#include "input/input_state.h" - -// WIP - doesn't do much yet -// Mainly for detecting (multi-)touch gestures but also useable for left button mouse dragging etc. - - -enum Gesture { - GESTURE_DRAG_VERTICAL = 1, - GESTURE_DRAG_HORIZONTAL = 2, - GESTURE_TWO_FINGER_ZOOM = 4, - GESTURE_TWO_FINGER_ZOOM_ROTATE = 4, -}; - -// May track multiple gestures at the same time. You simply call GetGestureInfo -// with the gesture you are interested in. -class GestureDetector -{ -public: - void Update(const TouchInput &touch); - bool IsGestureActive(Gesture gesture) const; - void GetGestureInfo(Gesture gesture, float info[4]); - -private: - // jazzhands! - enum Locals { - MAX_PTRS = 10 - }; - - struct Pointer { - bool down; - float X; - float Y; - float lastX; - float lastY; - float downX; - float downY; - float deltaX; - float deltaY; - float smoothDeltaX; - float smoothDeltaY; - }; - - Pointer pointers[MAX_PTRS]; - // ... -}; +#include "input/input_state.h" + +// WIP - doesn't do much yet +// Mainly for detecting (multi-)touch gestures but also useable for left button mouse dragging etc. + + +enum Gesture { + GESTURE_DRAG_VERTICAL = 1, + GESTURE_DRAG_HORIZONTAL = 2, + GESTURE_TWO_FINGER_ZOOM = 4, + GESTURE_TWO_FINGER_ZOOM_ROTATE = 8, +}; + +// May track multiple gestures at the same time. You simply call GetGestureInfo +// with the gesture you are interested in. +class GestureDetector +{ +public: + GestureDetector(); + void Update(const TouchInput &touch); + bool IsGestureActive(Gesture gesture) const; + void GetGestureInfo(Gesture gesture, float info[4]); + +private: + // jazzhands! + enum Locals { + MAX_PTRS = 10 + }; + + struct Pointer { + bool down; + double downTime; + float lastX; + float lastY; + float downX; + float downY; + float deltaX; + float deltaY; + float distanceX; + float distanceY; + }; + + Pointer pointers[MAX_PTRS]; + // ... + + uint32_t active_; +}; diff --git a/ui/view.cpp b/ui/view.cpp index 39af395ff9..3fe8a30df1 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -132,12 +132,21 @@ void Choice::Draw(DrawContext &dc) { // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); } +void InfoItem::Draw(DrawContext &dc) { + int paddingX = 4; + int paddingY = 4; + dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); + dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); + dc.draw->hLine(bounds_.x, bounds_.y, bounds_.x2(), 0xFFFFFFFF); +} + void CheckBox::Draw(DrawContext &dc) { int paddingX = 80; int paddingY = 4; dc.draw->DrawImage(dc.theme->checkOn, bounds_.x + 30, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); - dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.y + paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); + dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); + dc.draw->hLine(bounds_.x, bounds_.y, bounds_.x2(), 0xFFFFFFFF); } void Button::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { diff --git a/ui/view.h b/ui/view.h index 1944464876..732b762a65 100644 --- a/ui/view.h +++ b/ui/view.h @@ -161,6 +161,9 @@ struct DrawContext { DrawBuffer *draw; DrawBuffer *drawTop; const Theme *theme; + + void PushStencil(const Bounds &bounds) {} + void PopStencil() {} }; // Should cover all bases. @@ -221,6 +224,8 @@ class LinearLayoutParams : public LayoutParams { public: LinearLayoutParams() : LayoutParams(), weight(0.0f), gravity(G_TOPLEFT), hasMargins_(false) {} + explicit LinearLayoutParams(float wgt) + : LayoutParams(), weight(wgt), gravity(G_TOPLEFT), hasMargins_(false) {} LinearLayoutParams(Size w, Size h, float wgt = 0.0f, Gravity grav = G_TOPLEFT) : LayoutParams(w, h), weight(wgt), gravity(grav), hasMargins_(false) {} LinearLayoutParams(Size w, Size h, float wgt, Gravity grav, const Margins &mgn) @@ -408,10 +413,10 @@ private: std::string rightText_; }; -class CheckBox : public Clickable { +class CheckBox : public ClickableItem { public: CheckBox(bool *toggle, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) - : Clickable(layoutParams), text_(text), smallText_(smallText) { + : ClickableItem(layoutParams), text_(text), smallText_(smallText) { OnClick.Add(std::bind(&CheckBox::OnClicked, this, std::placeholders::_1)); } @@ -422,6 +427,7 @@ public: *toggle_ = !(*toggle_); return EVENT_DONE; } + private: bool *toggle_; std::string text_; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 26c5501c30..197113583c 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -163,7 +163,7 @@ void LinearLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec // Awright, got the sum. Let's take the remaining space after the fixed-size views, // and distribute among the weighted ones. if (orientation_ == ORIENT_HORIZONTAL) { - MeasureBySpec(layoutParams_->width, sum, horiz, &measuredWidth_); + MeasureBySpec(layoutParams_->width, weightZeroSum, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, maxOther, vert, &measuredHeight_); float unit = (measuredWidth_ - weightZeroSum) / weightSum; @@ -176,7 +176,7 @@ void LinearLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec views_[i]->Measure(dc, MeasureSpec(EXACTLY, unit * linLayoutParams->weight), vert); } } else { - MeasureBySpec(layoutParams_->height, sum, vert, &measuredHeight_); + MeasureBySpec(layoutParams_->height, weightZeroSum, vert, &measuredHeight_); MeasureBySpec(layoutParams_->width, maxOther, horiz, &measuredWidth_); float unit = (measuredHeight_ - weightZeroSum) / weightSum; @@ -262,25 +262,36 @@ void ScrollView::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec v // The scroll view itself simply obeys its parent. MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); + + if (orientation_ == ORIENT_HORIZONTAL) { + views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED), vert); + } else { + views_[0]->Measure(dc, horiz, MeasureSpec(UNSPECIFIED)); + } } void ScrollView::Layout() { - Bounds scrolled = bounds_; + Bounds scrolled; + scrolled.w = views_[0]->GetMeasuredWidth(); + scrolled.h = views_[0]->GetMeasuredHeight(); switch (orientation_) { case ORIENT_HORIZONTAL: - scrolled.x -= scrollPos_; + scrolled.x = bounds_.x - scrollPos_; + scrolled.y = bounds_.y; break; case ORIENT_VERTICAL: - scrolled.y -= scrollPos_; + scrolled.x = bounds_.x; + scrolled.y = bounds_.y - scrollPos_; break; } views_[0]->SetBounds(scrolled); + views_[0]->Layout(); } void ScrollView::Touch(const TouchInput &input) { if ((input.flags & TOUCH_DOWN) && input.id == 0) { - scrollStart_ = orientation_ == ORIENT_HORIZONTAL ? input.x : input.y; + scrollStart_ = scrollPos_; } gesture_.Update(input); @@ -288,9 +299,27 @@ void ScrollView::Touch(const TouchInput &input) { if (gesture_.IsGestureActive(GESTURE_DRAG_VERTICAL)) { float info[4]; gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info); + scrollPos_ = scrollStart_ - info[0]; + } else { + ViewGroup::Touch(input); + } + + // Clamp scrollPos_. TODO: flinging, bouncing, etc. + if (scrollPos_ < 0.0f) { + scrollPos_ = 0.0f; + } + float childHeight = views_[0]->GetBounds().h; + float scrollMax = std::max(0.0f, childHeight - bounds_.h); + if (scrollPos_ > scrollMax) { + scrollPos_ = scrollMax; } } +void ScrollView::Draw(DrawContext &dc) { + dc.PushStencil(bounds_); + views_[0]->Draw(dc); + dc.PopStencil(); +} void GridLayout::Layout() { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 68d75d1c43..0d7c9fabce 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -68,8 +68,8 @@ private: class GridLayout : public ViewGroup { public: - GridLayout(Orientation orientation, int numPerLine) : - orientation_(orientation), numPerLine_(numPerLine) {} + GridLayout(Orientation orientation, int numPerLine, LayoutParams *layoutParams = 0) + : ViewGroup(layoutParams), orientation_(orientation), numPerLine_(numPerLine) {} void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); @@ -82,13 +82,14 @@ private: // A scrollview usually contains just a single child - a linear layout or similar. class ScrollView : public ViewGroup { public: - ScrollView(Orientation orientation) : - orientation_(orientation) {} + ScrollView(Orientation orientation, LayoutParams *layoutParams = 0) : + ViewGroup(layoutParams), orientation_(orientation), scrollPos_(0) {} void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); void Touch(const TouchInput &input); + void Draw(DrawContext &dc); private: GestureDetector gesture_; From 7bad683cae918891bb28018b1efe5155259c019d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 25 May 2013 16:52:27 +0200 Subject: [PATCH 0404/1445] More new UI work --- Android.mk | 1 + input/gesture_detector.cpp | 11 ++++++--- input/gesture_detector.h | 9 +++---- math/geom2d.h | 42 ++++++++++++++++++++++++++++++++ native.vcxproj | 3 +++ native.vcxproj.filters | 5 ++++ ui/drawing.cpp | 3 +++ ui/drawing.h | 0 ui/view.cpp | 39 +++++++++++++++++++++++++----- ui/view.h | 49 +++++++++++++++++++++----------------- ui/viewgroup.cpp | 38 ++++++++++++++++++++--------- 11 files changed, 154 insertions(+), 46 deletions(-) create mode 100644 math/geom2d.h create mode 100644 ui/drawing.cpp create mode 100644 ui/drawing.h diff --git a/Android.mk b/Android.mk index 2311998a62..9edfc363db 100644 --- a/Android.mk +++ b/Android.mk @@ -63,6 +63,7 @@ LOCAL_SRC_FILES :=\ ui/ui_context.cpp \ ui/screen.cpp \ ui/virtual_input.cpp \ + ui/drawing.cpp \ util/random/perlin.cpp \ util/text/utf8.cpp diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 4a4e701e6f..852b8fae60 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -9,10 +9,10 @@ GestureDetector::GestureDetector() : active_(0) { } -void GestureDetector::Update(const TouchInput &touch) { +TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds) { // Mouse / 1-finger-touch control. Pointer &p = pointers[touch.id]; - if (touch.flags & TOUCH_DOWN) { + if ((touch.flags & TOUCH_DOWN) && bounds.Contains(touch.x, touch.y)) { p.down = true; p.downTime = time_now_d(); p.downX = touch.x; @@ -33,13 +33,18 @@ void GestureDetector::Update(const TouchInput &touch) { if (touch.id == 0 && p.distanceY > p.distanceX) { if (p.down) { double timeDown = time_now_d() - p.downTime; - if (p.distanceY * timeDown > 3) { + if (!active_ && p.distanceY * timeDown > 3) { active_ |= GESTURE_DRAG_VERTICAL; + // Kill the drag + TouchInput inp2 = touch; + inp2.flags = TOUCH_UP; + return inp2; } } else { active_ = 0; } } + return touch; } bool GestureDetector::IsGestureActive(Gesture gesture) const { diff --git a/input/gesture_detector.h b/input/gesture_detector.h index 8d0d2a2c9f..4c8178fd41 100644 --- a/input/gesture_detector.h +++ b/input/gesture_detector.h @@ -1,4 +1,5 @@ #include "input/input_state.h" +#include "math/geom2d.h" // WIP - doesn't do much yet // Mainly for detecting (multi-)touch gestures but also useable for left button mouse dragging etc. @@ -13,15 +14,16 @@ enum Gesture { // May track multiple gestures at the same time. You simply call GetGestureInfo // with the gesture you are interested in. -class GestureDetector -{ +class GestureDetector { public: GestureDetector(); - void Update(const TouchInput &touch); + TouchInput Update(const TouchInput &touch, const Bounds &bounds); bool IsGestureActive(Gesture gesture) const; void GetGestureInfo(Gesture gesture, float info[4]); private: + Bounds bounds_; + // jazzhands! enum Locals { MAX_PTRS = 10 @@ -41,7 +43,6 @@ private: }; Pointer pointers[MAX_PTRS]; - // ... uint32_t active_; }; diff --git a/math/geom2d.h b/math/geom2d.h new file mode 100644 index 0000000000..d165c80e4e --- /dev/null +++ b/math/geom2d.h @@ -0,0 +1,42 @@ +#pragma once + +struct Point { + Point() {} + Point(float x_, float y_) : x(x_), y(y_) {} + + float x; + float y; + + float distanceTo(const Point &other) const { + float dx = other.x - x, dy = other.y - y; + return sqrtf(dx*dx + dy*dy); + } + + /* + FocusDirection directionTo(const Point &other) const { + int angle = atan2f(other.y - y, other.x - x) / (2 * M_PI) - 0.125; + + }*/ +}; + + +// Resolved bounds on screen after layout. +struct Bounds { + bool Contains(float px, float py) const { + return (px >= x && py >= y && px < x + w && py < y + h); + } + float x2() const { return x + w; } + float y2() const { return y + h; } + float centerX() const { return x + w * 0.5f; } + float centerY() const { return y + h * 0.5f; } + Point Center() const { + return Point(centerX(), centerY()); + } + + float x; + float y; + float w; + float h; +}; + + diff --git a/native.vcxproj b/native.vcxproj index 63827c8b78..0fc33aa6a5 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -218,6 +218,7 @@ + @@ -232,6 +233,7 @@ + @@ -348,6 +350,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 86008ceba8..ffe8acd256 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -260,6 +260,10 @@ ui + + math + + @@ -462,6 +466,7 @@ ui + diff --git a/ui/drawing.cpp b/ui/drawing.cpp new file mode 100644 index 0000000000..ddc9c5ac25 --- /dev/null +++ b/ui/drawing.cpp @@ -0,0 +1,3 @@ +namespace UI { + +} \ No newline at end of file diff --git a/ui/drawing.h b/ui/drawing.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ui/view.cpp b/ui/view.cpp index 3fe8a30df1..9e9f7c7ba0 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -94,24 +94,37 @@ void Clickable::Click() { }; void Clickable::Touch(const TouchInput &input) { - if (input.flags & (TOUCH_DOWN | TOUCH_MOVE)) { + if (input.flags & TOUCH_DOWN) { if (bounds_.Contains(input.x, input.y)) { if (IsFocusMovementEnabled()) SetFocusedView(this); - down_ = true; + downCountDown_ = 8; } else { down_ = false; + dragging_ = false; } + } else if (input.flags & TOUCH_MOVE) { + if (dragging_) + down_ = bounds_.Contains(input.x, input.y); } if (input.flags & TOUCH_UP) { - if (bounds_.Contains(input.x, input.y)) { + if (dragging_ && bounds_.Contains(input.x, input.y)) { Click(); } + downCountDown_ = 0; down_ = false; + dragging_ = false; } } void Clickable::Update(const InputState &input_state) { + if (downCountDown_ == 1) { + downCountDown_ = 0; + dragging_ = true; + down_ = true; + } else if (downCountDown_ > 0) { + downCountDown_--; + } if (!HasFocus()) return; if (input_state.pad_buttons_down & PAD_BUTTON_A) { @@ -125,10 +138,19 @@ void Clickable::Update(const InputState &input_state) { } } +void ClickableItem::Draw(DrawContext &dc) { + if (down_) { + dc.draw->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.bgColor); + } else if (HasFocus()) { + dc.draw->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), dc.theme->itemFocusedStyle.bgColor); + } +} + void Choice::Draw(DrawContext &dc) { + ClickableItem::Draw(dc); int paddingX = 4; int paddingY = 4; - dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); + dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); } @@ -137,16 +159,21 @@ void InfoItem::Draw(DrawContext &dc) { int paddingY = 4; dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); - dc.draw->hLine(bounds_.x, bounds_.y, bounds_.x2(), 0xFFFFFFFF); + dc.draw->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor); +} + +void ItemHeader::Draw(DrawContext &dc) { + dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.y, 0xFF707070, ALIGN_LEFT); + dc.draw->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.bgColor); } void CheckBox::Draw(DrawContext &dc) { + ClickableItem::Draw(dc); int paddingX = 80; int paddingY = 4; dc.draw->DrawImage(dc.theme->checkOn, bounds_.x + 30, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); - dc.draw->hLine(bounds_.x, bounds_.y, bounds_.x2(), 0xFFFFFFFF); } void Button::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { diff --git a/ui/view.h b/ui/view.h index 732b762a65..ba151b1c55 100644 --- a/ui/view.h +++ b/ui/view.h @@ -9,11 +9,14 @@ #include #include +#include #include "base/mutex.h" #include "base/basictypes.h" #include "base/scoped_ptr.h" #include "math/lin/matrix4x4.h" +#include "math/math_util.h" +#include "math/geom2d.h" struct TouchInput; struct InputState; @@ -62,10 +65,14 @@ struct Theme { int buttonSelected; int checkOn; int checkOff; + int whiteImage; Style buttonStyle; Style buttonFocusedStyle; Style buttonDownStyle; + + Style itemDownStyle; + Style itemFocusedStyle; }; // The four cardinal directions should be enough, plus Prev/Next in "element order". @@ -124,23 +131,6 @@ enum EventReturn { class ViewGroup; -// Resolved bounds on screen after layout. -struct Bounds { - bool Contains(float px, float py) const { - return (px >= x && py >= y && px < x + w && py < y + h); - } - - float x2() const { return x + w; } - float y2() const { return y + h; } - float centerX() const { return x + w * 0.5f; } - float centerY() const { return y + h * 0.5f; } - - float x; - float y; - float w; - float h; -}; - void Fill(DrawContext &dc, const Bounds &bounds, const Drawable &drawable); struct MeasureSpec { @@ -200,6 +190,7 @@ private: struct Margins { Margins() : top(0), bottom(0), left(0), right(0) {} explicit Margins(uint8_t all) : top(all), bottom(all), left(all), right(all) {} + explicit Margins(uint8_t horiz, uint8_t vert) : top(vert), bottom(vert), left(horiz), right(horiz) {} uint8_t top; uint8_t bottom; uint8_t left; @@ -217,7 +208,6 @@ public: Size width; Size height; -private: }; class LinearLayoutParams : public LayoutParams { @@ -327,7 +317,7 @@ public: class Clickable : public View { public: Clickable(LayoutParams *layoutParams) - : View(layoutParams), down_(false) {} + : View(layoutParams), downCountDown_(0), down_(false), dragging_(false) {} virtual void Touch(const TouchInput &input); virtual void Update(const InputState &input_state); @@ -340,6 +330,8 @@ protected: // Use it for checking/unchecking checkboxes, etc. virtual void Click(); + int downCountDown_; + bool dragging_; bool down_; }; @@ -354,7 +346,6 @@ public: private: Style style_; std::string text_; - DISALLOW_COPY_AND_ASSIGN(Button); }; class Item : public InertView { @@ -381,10 +372,12 @@ public: w = 0.0f; h = 0.0f; } + + // Draws the item background. + virtual void Draw(DrawContext &dc); + }; - - // The following classes are mostly suitable as items in ListView which // really is just a LinearLayout in a ScrollView, possibly with some special optimizations. @@ -413,6 +406,18 @@ private: std::string rightText_; }; +class ItemHeader : public Item { +public: + ItemHeader(const std::string &text, LayoutParams *layoutParams = 0) + : Item(layoutParams), text_(text) { + layoutParams_->width = FILL_PARENT; + layoutParams_->height = 26; + } + virtual void Draw(DrawContext &dc); +private: + std::string text_; +}; + class CheckBox : public ClickableItem { public: CheckBox(bool *toggle, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 197113583c..8a882c70e5 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -259,29 +259,44 @@ void FrameLayout::Layout() { } void ScrollView::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { + // Respect margins + Margins margins; + const LinearLayoutParams *params = dynamic_cast(views_[0]->GetLayoutParams()); + if (params) { + margins = params->margins; + } + // The scroll view itself simply obeys its parent. MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); if (orientation_ == ORIENT_HORIZONTAL) { - views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED), vert); + views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED), vert - (margins.top + margins.bottom)); } else { - views_[0]->Measure(dc, horiz, MeasureSpec(UNSPECIFIED)); + views_[0]->Measure(dc, horiz - (margins.left + margins.right), MeasureSpec(UNSPECIFIED)); } } void ScrollView::Layout() { Bounds scrolled; - scrolled.w = views_[0]->GetMeasuredWidth(); - scrolled.h = views_[0]->GetMeasuredHeight(); + + // Respect margins + Margins margins; + const LinearLayoutParams *params = dynamic_cast(views_[0]->GetLayoutParams()); + if (params) { + margins = params->margins; + } + + scrolled.w = views_[0]->GetMeasuredWidth() - (margins.left + margins.right); + scrolled.h = views_[0]->GetMeasuredHeight() - (margins.top + margins.bottom); switch (orientation_) { case ORIENT_HORIZONTAL: scrolled.x = bounds_.x - scrollPos_; - scrolled.y = bounds_.y; + scrolled.y = bounds_.y + margins.top; break; case ORIENT_VERTICAL: - scrolled.x = bounds_.x; + scrolled.x = bounds_.x + margins.left; scrolled.y = bounds_.y - scrollPos_; break; } @@ -293,17 +308,18 @@ void ScrollView::Touch(const TouchInput &input) { if ((input.flags & TOUCH_DOWN) && input.id == 0) { scrollStart_ = scrollPos_; } - - gesture_.Update(input); + + TouchInput input2 = gesture_.Update(input, bounds_); if (gesture_.IsGestureActive(GESTURE_DRAG_VERTICAL)) { float info[4]; gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info); scrollPos_ = scrollStart_ - info[0]; - } else { - ViewGroup::Touch(input); } - + + if (!(input.flags & TOUCH_DOWN) || bounds_.Contains(input.x, input.y)) + ViewGroup::Touch(input2); + // Clamp scrollPos_. TODO: flinging, bouncing, etc. if (scrollPos_ < 0.0f) { scrollPos_ = 0.0f; From 85f386c38bec144c993120fb1c3854e04ece8e60 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 25 May 2013 11:44:32 -0700 Subject: [PATCH 0405/1445] Return number of samples in NativeApp::audioRender(). This way we can try to avoid writing invalid data to the buffer. --- android/.classpath | 1 + android/app-android.cpp | 6 ++++-- android/src/com/henrikrydgard/libnative/NativeApp.java | 2 +- .../src/com/henrikrydgard/libnative/NativeAudioPlayer.java | 7 +++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/android/.classpath b/android/.classpath index a4763d1eec..bb0c759770 100644 --- a/android/.classpath +++ b/android/.classpath @@ -4,5 +4,6 @@ + diff --git a/android/app-android.cpp b/android/app-android.cpp index 2a9314899a..210fa34a8a 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -294,7 +294,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN } } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { +extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { // Too spammy // ILOG("NativeApp.audioRender"); @@ -305,9 +305,11 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* e if (buf_size) { short *data = env->GetShortArrayElements(array, 0); int samples = buf_size / 2; - NativeMix(data, samples); + samples = NativeMix(data, samples); env->ReleaseShortArrayElements(array, data, 0); + return samples * 2; } + return 0; } extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 4e02203621..79fa414ff5 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -21,7 +21,7 @@ public class NativeApp { public static native void joystickEvent(float x, float y); // will only be called between init() and shutdown() - public static native void audioRender(short[] buffer); + public static native int audioRender(short[] buffer); // Sensor/input data. These are asynchronous, beware! public static native void touch(float x, float y, int data, int pointerId); diff --git a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java index d6fd249407..4b1c7a2fd7 100644 --- a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java +++ b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java @@ -81,8 +81,11 @@ public class NativeAudioPlayer { audioTrack.play(); Log.i(TAG, "Playing... minBuffersize = " + buffer_size); while (playing_) { - NativeApp.audioRender(buffer); - audioTrack.write(buffer, 0, buffer_size); + int validShorts = NativeApp.audioRender(buffer); + if (validShorts != 0) { + audioTrack.write(buffer, 0, validShorts); + } + Thread.yield(); } audioTrack.stop(); audioTrack.release(); From a17a16eda2d7c0fd9d729dcd9d416f17fa285527 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 25 May 2013 12:11:06 -0700 Subject: [PATCH 0406/1445] Avoid a memory copy when audio is ahead. --- android/app-android.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 210fa34a8a..2d9a7dc322 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -306,8 +306,13 @@ extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* e short *data = env->GetShortArrayElements(array, 0); int samples = buf_size / 2; samples = NativeMix(data, samples); - env->ReleaseShortArrayElements(array, data, 0); - return samples * 2; + if (samples != 0) { + env->ReleaseShortArrayElements(array, data, 0); + return samples * 2; + } else { + env->ReleaseShortArrayElements(array, data, JNI_ABORT); + return 0; + } } return 0; } From 23d73664c4c929b4c4a3c7b3e040a01e69fffe82 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 25 May 2013 14:30:31 -0700 Subject: [PATCH 0407/1445] Play only the rendered/valid samples in SLES. --- android/native-audio-so.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 64a6b05b97..0fba729dc9 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -6,6 +6,7 @@ #include #include +#include // for native audio #include @@ -46,8 +47,16 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { assert(bq == bqPlayerBufferQueue); assert(NULL == context); + int nextSamples = audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); + // We can't enqueue nothing, the callback will never be called again. + // Delay until we get some audio. + while (nextSamples == 0) { + usleep(40); + nextSamples = audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); + } + short *nextBuffer = buffer[curBuffer]; - int nextSize = sizeof(buffer[0]); + int nextSize = nextSamples * 2 * sizeof(short); SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); @@ -57,8 +66,6 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { assert(SL_RESULT_SUCCESS == result); curBuffer ^= 1; // Switch buffer - // Render to the fresh buffer - audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); } // create the engine and output mix objects From 2a821db448ae590483985ac44ece7724125d7d6e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 27 May 2013 00:54:02 +0200 Subject: [PATCH 0408/1445] NewUI: Gridlayout. Fully directional keyboard focus movement. --- ui/view.h | 11 ++- ui/viewgroup.cpp | 176 +++++++++++++++++++++++++++++++++++++++-------- ui/viewgroup.h | 41 +++++++++-- 3 files changed, 192 insertions(+), 36 deletions(-) diff --git a/ui/view.h b/ui/view.h index ba151b1c55..e7767ceb87 100644 --- a/ui/view.h +++ b/ui/view.h @@ -11,6 +11,14 @@ #include #include +// fix +#if defined(IOS) || defined(MACGNUSTD) +#include +namespace std { + using tr1::bind; +} +#endif + #include "base/mutex.h" #include "base/basictypes.h" #include "base/scoped_ptr.h" @@ -277,7 +285,7 @@ public: } return false; } - virtual void MoveFocus(FocusDirection direction) {} + virtual bool CanBeFocused() const { return true; } bool HasFocus() const { @@ -375,7 +383,6 @@ public: // Draws the item background. virtual void Draw(DrawContext &dc); - }; // The following classes are mostly suitable as items in ListView which diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 8a882c70e5..623fd60523 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -59,23 +59,42 @@ bool ViewGroup::SetFocus() { return false; } -void ViewGroup::MoveFocus(FocusDirection direction) { - if (!GetFocusedView()) { - SetFocus(); - return; +float GetDirectionScore(View *origin, View *destination, FocusDirection direction) { + // Skip labels and things like that. + if (!destination->CanBeFocused()) + return 0.0f; + + float dx = destination->GetBounds().centerX() - origin->GetBounds().centerX(); + float dy = destination->GetBounds().centerY() - origin->GetBounds().centerY(); + + float distance = sqrtf(dx*dx+dy*dy); + float dirX = dx / distance; + float dirY = dy / distance; + + switch (direction) { + case FOCUS_LEFT: + if (dirX > 0.0f) return 0.0f; + if (fabsf(dirY) > fabsf(dirX)) return 0.0f; + break; + case FOCUS_UP: + if (dirY > 0.0f) return 0.0f; + if (fabsf(dirX) > fabsf(dirY)) return 0.0f; + break; + case FOCUS_RIGHT: + if (dirX < 0.0f) return 0.0f; + if (fabsf(dirY) > fabsf(dirX)) return 0.0f; + break; + case FOCUS_DOWN: + if (dirY < 0.0f) return 0.0f; + if (fabsf(dirX) > fabsf(dirY)) return 0.0f; + break; } - View *neighbor = FindNeighbor(GetFocusedView(), direction); - if (neighbor) { - neighbor->SetFocus(); - } else { - for (auto iter = views_.begin(); iter != views_.end(); ++iter) { - (*iter)->MoveFocus(direction); - } - } + return 100.0f / distance; } -View *ViewGroup::FindNeighbor(View *view, FocusDirection direction) { + +NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, NeighborResult result) { // First, find the position of the view in the list. size_t num = -1; for (size_t i = 0; i < views_.size(); i++) { @@ -85,28 +104,78 @@ View *ViewGroup::FindNeighbor(View *view, FocusDirection direction) { } } - // If view not found, no neighbor to find. - if (num == -1) - return 0; - // TODO: Do the cardinal directions right. Now we just map to // prev/next. - + switch (direction) { + case FOCUS_PREV: + // If view not found, no neighbor to find. + if (num == -1) + return NeighborResult(0, 0.0f); + return NeighborResult(views_[(num + views_.size() - 1) % views_.size()], 0.0f); + + case FOCUS_NEXT: + // If view not found, no neighbor to find. + if (num == -1) + return NeighborResult(0, 0.0f); + return NeighborResult(views_[(num + 1) % views_.size()], 0.0f); + case FOCUS_UP: case FOCUS_LEFT: - case FOCUS_PREV: - return views_[(num + views_.size() - 1) % views_.size()]; case FOCUS_RIGHT: case FOCUS_DOWN: - case FOCUS_NEXT: - return views_[(num + 1) % views_.size()]; + { + // First, try the child views themselves as candidates + for (size_t i = 0; i < views_.size(); i++) { + if (views_[i] == view) + continue; + + float score = GetDirectionScore(view, views_[i], direction); + if (score > result.score) { + result.score = score; + result.view = views_[i]; + result.parent = this; + } + } + + // Then go right ahead and see if any of the children contain any better candidates. + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + ViewGroup *vg = dynamic_cast(*iter); + if (vg) + result = vg->FindNeighbor(view, direction, result); + } + + // Boost neighbors with the same parent + if (num != -1) { + result.score += 100.0f; + } + + return result; + } default: - return view; + return result; } } +void MoveFocus(ViewGroup *root, FocusDirection direction) { + if (!GetFocusedView()) { + // Nothing was focused when we got in here. Focus the first non-group in the hierarchy. + root->SetFocus(); + return; + } + + NeighborResult neigh(0, 0); + neigh = root->FindNeighbor(GetFocusedView(), direction, neigh); + + if (neigh.view) { + neigh.view->SetFocus(); + if (neigh.parent != 0) { + // Let scrollviews and similar know that a child has been focused. + neigh.parent->FocusView(neigh.view); + } + } +} void LinearLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { if (views_.empty()) { @@ -300,6 +369,7 @@ void ScrollView::Layout() { scrolled.y = bounds_.y - scrollPos_; break; } + views_[0]->SetBounds(scrolled); views_[0]->Layout(); } @@ -337,8 +407,57 @@ void ScrollView::Draw(DrawContext &dc) { dc.PopStencil(); } -void GridLayout::Layout() { +void ScrollView::FocusView(View *view) { + // Moved the focus to a child view (can be any level deep). + // Figure out if it's currently in view, if not, let's scroll there. + // TODO: the above. +} +void GridLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { + MeasureSpecType measureType = settings_.fillCells ? EXACTLY : AT_MOST; + + for (size_t i = 0; i < views_.size(); i++) { + views_[i]->Measure(dc, MeasureSpec(measureType, settings_.columnWidth), MeasureSpec(measureType, settings_.rowHeight)); + } + + MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); + + // Okay, got the width we are supposed to adjust to. Now we can calculate the number of columns. + int numColumns = (measuredWidth_ - settings_.spacing) / (settings_.columnWidth + settings_.spacing); + int numRows = (views_.size() + (numColumns - 1)) / numColumns; + + float estimatedHeight = settings_.rowHeight * numRows; + + MeasureBySpec(layoutParams_->height, estimatedHeight, vert, &measuredHeight_); +} + + +void GridLayout::Layout() { + int y = 0; + int x = 0; + for (size_t i = 0; i < views_.size(); i++) { + Bounds itemBounds, innerBounds; + + itemBounds.x = bounds_.x + x; + itemBounds.y = bounds_.y + y; + itemBounds.w = settings_.columnWidth; + itemBounds.h = settings_.rowHeight; + + ApplyGravity(itemBounds, Margins(0.0f), + views_[i]->GetMeasuredWidth(), views_[i]->GetMeasuredHeight(), + G_HCENTER | G_VCENTER, innerBounds); + + views_[i]->SetBounds(innerBounds); + views_[i]->Layout(); + + x += itemBounds.w; + if (x >= bounds_.w) { + x = 0; + y += itemBounds.h + settings_.spacing; + } else { + x += settings_.spacing; + } + } } void RelativeLayout::Layout() { @@ -362,19 +481,20 @@ void LayoutViewHierarchy(const DrawContext &dc, ViewGroup *root) { root->Layout(); } + void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { if (input_state.pad_buttons_down & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) EnableFocusMovement(true); if (input_state.pad_last_buttons == 0) { if (input_state.pad_buttons_down & PAD_BUTTON_RIGHT) - root->MoveFocus(FOCUS_RIGHT); + MoveFocus(root, FOCUS_RIGHT); if (input_state.pad_buttons_down & PAD_BUTTON_UP) - root->MoveFocus(FOCUS_UP); + MoveFocus(root, FOCUS_UP); if (input_state.pad_buttons_down & PAD_BUTTON_LEFT) - root->MoveFocus(FOCUS_LEFT); + MoveFocus(root, FOCUS_LEFT); if (input_state.pad_buttons_down & PAD_BUTTON_DOWN) - root->MoveFocus(FOCUS_DOWN); + MoveFocus(root, FOCUS_DOWN); } root->Update(input_state); diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 0d7c9fabce..dfefe701c1 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -5,6 +5,15 @@ namespace UI { +struct NeighborResult { + NeighborResult() : view(0), score(0) {} + NeighborResult(View *v, float s) : view(v), score(s) {} + + View *view; + ViewGroup *parent; + float score; +}; + class ViewGroup : public View { public: ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams) {} @@ -28,10 +37,10 @@ public: void Add(View *view) { views_.push_back(view); } virtual bool SetFocus(); - virtual void MoveFocus(FocusDirection direction); + virtual void FocusView(View *view) {} // Assumes that layout has taken place. - View *FindNeighbor(View *view, FocusDirection direction); + NeighborResult FindNeighbor(View *view, FocusDirection direction, NeighborResult best); virtual bool CanBeFocused() const { return false; } @@ -66,17 +75,34 @@ private: float spacing_; }; + +// GridLayout is a little different from the Android layout. This one has fixed size +// rows and columns. Items are not allowed to deviate from the set sizes. +// Initially, only horizontal layout is supported. +struct GridLayoutSettings { + GridLayoutSettings() : orientation(ORIENT_HORIZONTAL), columnWidth(100), rowHeight(50), spacing(5), fillCells(false) {} + GridLayoutSettings(int colW, int colH, int spac = 5) : orientation(ORIENT_HORIZONTAL), columnWidth(colW), rowHeight(colH), spacing(spac), fillCells(false) {} + + Orientation orientation; + int columnWidth; + int rowHeight; + int spacing; + bool fillCells; +}; + class GridLayout : public ViewGroup { public: - GridLayout(Orientation orientation, int numPerLine, LayoutParams *layoutParams = 0) - : ViewGroup(layoutParams), orientation_(orientation), numPerLine_(numPerLine) {} + GridLayout(GridLayoutSettings settings, LayoutParams *layoutParams = 0) + : ViewGroup(layoutParams), settings_(settings) { + if (settings.orientation != ORIENT_HORIZONTAL) + ELOG("GridLayout: Vertical layouts not yet supported"); + } void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); private: - Orientation orientation_; - int numPerLine_; + GridLayoutSettings settings_; }; // A scrollview usually contains just a single child - a linear layout or similar. @@ -91,6 +117,9 @@ public: void Touch(const TouchInput &input); void Draw(DrawContext &dc); + // Override so that we can scroll to the active one after moving the focus. + virtual void FocusView(View *view); + private: GestureDetector gesture_; Orientation orientation_; From 0244a26544f807a921258bee30b3b6bc5b685972 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 27 May 2013 21:39:56 +0200 Subject: [PATCH 0409/1445] More newUI work: better focus movement, autoscroll --- ui/view.cpp | 14 ++++------- ui/view.h | 2 +- ui/viewgroup.cpp | 62 ++++++++++++++++++++++++++++++++++++++++-------- ui/viewgroup.h | 8 ++++--- 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 9e9f7c7ba0..68f295510a 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -22,7 +22,9 @@ void SetFocusedView(View *view) { } void EnableFocusMovement(bool enable) { - focusMovementEnabled = true; + focusMovementEnabled = enable; + if (!enable) + focusedView = 0; } bool IsFocusMovementEnabled() { @@ -98,7 +100,8 @@ void Clickable::Touch(const TouchInput &input) { if (bounds_.Contains(input.x, input.y)) { if (IsFocusMovementEnabled()) SetFocusedView(this); - downCountDown_ = 8; + dragging_ = true; + down_ = true; } else { down_ = false; dragging_ = false; @@ -118,13 +121,6 @@ void Clickable::Touch(const TouchInput &input) { } void Clickable::Update(const InputState &input_state) { - if (downCountDown_ == 1) { - downCountDown_ = 0; - dragging_ = true; - down_ = true; - } else if (downCountDown_ > 0) { - downCountDown_--; - } if (!HasFocus()) return; if (input_state.pad_buttons_down & PAD_BUTTON_A) { diff --git a/ui/view.h b/ui/view.h index e7767ceb87..f251c5f785 100644 --- a/ui/view.h +++ b/ui/view.h @@ -287,7 +287,7 @@ public: } virtual bool CanBeFocused() const { return true; } - + virtual bool SubviewFocused(View *view) { return false; } bool HasFocus() const { return GetFocusedView() == this; } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 623fd60523..1d160f1dce 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -59,6 +59,16 @@ bool ViewGroup::SetFocus() { return false; } +bool ViewGroup::SubviewFocused(View *view) { + for (size_t i = 0; i < views_.size(); i++) { + if (views_[i] == view) + return true; + if (views_[i]->SubviewFocused(view)) + return true; + } + return false; +} + float GetDirectionScore(View *origin, View *destination, FocusDirection direction) { // Skip labels and things like that. if (!destination->CanBeFocused()) @@ -170,10 +180,13 @@ void MoveFocus(ViewGroup *root, FocusDirection direction) { if (neigh.view) { neigh.view->SetFocus(); - if (neigh.parent != 0) { + + root->SubviewFocused(neigh.view); + + //if (neigh.parent != 0) { // Let scrollviews and similar know that a child has been focused. - neigh.parent->FocusView(neigh.view); - } + //neigh.parent->SubviewFocused(neigh.view); + //} } } @@ -407,10 +420,38 @@ void ScrollView::Draw(DrawContext &dc) { dc.PopStencil(); } -void ScrollView::FocusView(View *view) { - // Moved the focus to a child view (can be any level deep). - // Figure out if it's currently in view, if not, let's scroll there. - // TODO: the above. +bool ScrollView::SubviewFocused(View *view) { + if (!ViewGroup::SubviewFocused(view)) + return false; + + const Bounds &vBounds = view->GetBounds(); + + // Scroll so that the focused view is visible. + switch (orientation_) { + case ORIENT_HORIZONTAL: + if (vBounds.x2() > bounds_.x2()) { + ScrollTo(scrollPos_ + vBounds.x2() - bounds_.x2()); + } + if (vBounds.x < bounds_.x) { + ScrollTo(scrollPos_ + (vBounds.x - bounds_.x)); + } + break; + case ORIENT_VERTICAL: + if (vBounds.y2() > bounds_.y2()) { + ScrollTo(scrollPos_ + vBounds.y2() - bounds_.y2()); + } + if (vBounds.y < bounds_.y) { + ScrollTo(scrollPos_ + (vBounds.y - bounds_.y - 30)); + } + break; + } + + return true; +} + +void ScrollView::ScrollTo(float newScrollPos) { + // TODO: Smooth scrolling + scrollPos_ = newScrollPos; } void GridLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { @@ -431,7 +472,6 @@ void GridLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec v MeasureBySpec(layoutParams_->height, estimatedHeight, vert, &measuredHeight_); } - void GridLayout::Layout() { int y = 0; int x = 0; @@ -485,8 +525,10 @@ void LayoutViewHierarchy(const DrawContext &dc, ViewGroup *root) { void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { if (input_state.pad_buttons_down & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) EnableFocusMovement(true); + if (input_state.pointer_down[0]) + EnableFocusMovement(false); - if (input_state.pad_last_buttons == 0) { + //if (input_state.pad_last_buttons == 0) { if (input_state.pad_buttons_down & PAD_BUTTON_RIGHT) MoveFocus(root, FOCUS_RIGHT); if (input_state.pad_buttons_down & PAD_BUTTON_UP) @@ -495,7 +537,7 @@ void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { MoveFocus(root, FOCUS_LEFT); if (input_state.pad_buttons_down & PAD_BUTTON_DOWN) MoveFocus(root, FOCUS_DOWN); - } + //} root->Update(input_state); } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index dfefe701c1..4d16a71ba1 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -37,7 +37,7 @@ public: void Add(View *view) { views_.push_back(view); } virtual bool SetFocus(); - virtual void FocusView(View *view) {} + virtual bool SubviewFocused(View *view); // Assumes that layout has taken place. NeighborResult FindNeighbor(View *view, FocusDirection direction, NeighborResult best); @@ -75,7 +75,6 @@ private: float spacing_; }; - // GridLayout is a little different from the Android layout. This one has fixed size // rows and columns. Items are not allowed to deviate from the set sizes. // Initially, only horizontal layout is supported. @@ -117,14 +116,17 @@ public: void Touch(const TouchInput &input); void Draw(DrawContext &dc); + void ScrollTo(float newScrollPos); + // Override so that we can scroll to the active one after moving the focus. - virtual void FocusView(View *view); + virtual bool SubviewFocused(View *view); private: GestureDetector gesture_; Orientation orientation_; float scrollPos_; float scrollStart_; + float scrollMax_; }; class ViewPager : public ScrollView { From 0d4e1e820121252b2886a662ca50f5a22c426592 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 27 May 2013 22:22:35 +0200 Subject: [PATCH 0410/1445] Add AnchorLayout, TriggerButton --- ui/view.cpp | 36 +++++++++++++++++++++++++++++ ui/view.h | 53 +++++++++++++++++++++--------------------- ui/viewgroup.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++---- ui/viewgroup.h | 44 ++++++++++++++++++++++++++++++++++- 4 files changed, 162 insertions(+), 31 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 68f295510a..537d98ee2f 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -208,6 +208,42 @@ void TextView::Draw(DrawContext &dc) { dc.draw->DrawTextRect(dc.theme->uiFont, text_.c_str(), bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF); } +void TriggerButton::Touch(const TouchInput &input) { + if (input.flags & TOUCH_DOWN) { + if (bounds_.Contains(input.x, input.y)) { + down_ |= 1 << input.id; + } + } + if (input.flags & TOUCH_MOVE) { + if (bounds_.Contains(input.x, input.y)) + down_ |= 1 << input.id; + else + down_ &= ~(1 << input.id); + } + + if (input.flags & TOUCH_UP) { + down_ &= ~(1 << input.id); + } + + if (down_ != 0) { + *bitField_ |= bit_; + } else { + *bitField_ &= ~bit_; + } +} + +void TriggerButton::Draw(DrawContext &dc) { + dc.draw->DrawImage(imageBackground_, bounds_.centerX(), bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + dc.draw->DrawImage(imageForeground_, bounds_.centerX(), bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); +} + +void TriggerButton::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { + const AtlasImage &image = dc.draw->GetAtlas()->images[imageBackground_]; + w = image.w; + h = image.h; +} + + /* TabStrip::TabStrip() : selected_(0) { diff --git a/ui/view.h b/ui/view.h index f251c5f785..602041c3a2 100644 --- a/ui/view.h +++ b/ui/view.h @@ -218,29 +218,6 @@ public: Size height; }; -class LinearLayoutParams : public LayoutParams { -public: - LinearLayoutParams() - : LayoutParams(), weight(0.0f), gravity(G_TOPLEFT), hasMargins_(false) {} - explicit LinearLayoutParams(float wgt) - : LayoutParams(), weight(wgt), gravity(G_TOPLEFT), hasMargins_(false) {} - LinearLayoutParams(Size w, Size h, float wgt = 0.0f, Gravity grav = G_TOPLEFT) - : LayoutParams(w, h), weight(wgt), gravity(grav), hasMargins_(false) {} - LinearLayoutParams(Size w, Size h, float wgt, Gravity grav, const Margins &mgn) - : LayoutParams(w, h), weight(wgt), gravity(grav), margins(mgn), hasMargins_(true) {} - LinearLayoutParams(const Margins &mgn) - : LayoutParams(WRAP_CONTENT, WRAP_CONTENT), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} - - float weight; - Gravity gravity; - Margins margins; - - bool HasMargins() const { return hasMargins_; } - -private: - bool hasMargins_; -}; - View *GetFocusedView(); class View { @@ -356,6 +333,31 @@ private: std::string text_; }; +// Basic button that modifies a bitfield based on the pressed status. Supports multitouch. +// Suitable for controller simulation (ABXY etc). +class TriggerButton : public View { +public: + TriggerButton(uint32_t *bitField, uint32_t bit, int imageBackground, int imageForeground, LayoutParams *layoutParams) + : View(layoutParams), down_(0.0), bitField_(bitField), bit_(bit), imageBackground_(imageBackground), imageForeground_(imageForeground) {} + + virtual void Touch(const TouchInput &input); + virtual void Draw(DrawContext &dc); + virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; + +private: + int down_; // bitfield of pressed fingers, translates into bitField + + uint32_t *bitField_; + uint32_t bit_; + + int imageBackground_; + int imageForeground_; +}; + + +// The following classes are mostly suitable as items in ListView which +// really is just a LinearLayout in a ScrollView, possibly with some special optimizations. + class Item : public InertView { public: Item(LayoutParams *layoutParams) : InertView(layoutParams) { @@ -385,9 +387,6 @@ public: virtual void Draw(DrawContext &dc); }; -// The following classes are mostly suitable as items in ListView which -// really is just a LinearLayout in a ScrollView, possibly with some special optimizations. - // Use to trigger something or open a submenu screen. class Choice : public ClickableItem { public: @@ -489,6 +488,8 @@ private: ImageSizeMode sizeMode_; }; + + // This tab strip is a little special. /* class TabStrip : public View { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 1d160f1dce..d40bd278fe 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -472,6 +472,62 @@ void GridLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec v MeasureBySpec(layoutParams_->height, estimatedHeight, vert, &measuredHeight_); } +void AnchorLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { + MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); + MeasureBySpec(layoutParams_->height, 0.0f, horiz, &measuredHeight_); + + for (size_t i = 0; i < views_.size(); i++) { + Size width = WRAP_CONTENT; + Size height = WRAP_CONTENT; + + MeasureSpec specW(UNSPECIFIED, 0.0f); + MeasureSpec specH(UNSPECIFIED, 0.0f); + + const AnchorLayoutParams *params = dynamic_cast(views_[i]->GetLayoutParams()); + if (params) { + width = params->width; + height = params->height; + + if (params->left >= 0 && params->right >= 0) { + width = measuredWidth_ - params->left - params->right; + specW = MeasureSpec(EXACTLY, width); + } + if (params->top >= 0 && params->bottom >= 0) { + height = measuredHeight_ - params->top - params->bottom; + specH = MeasureSpec(EXACTLY, height); + } + } + + views_[i]->Measure(dc, specW, specH); + } +} + +void AnchorLayout::Layout() { + for (size_t i = 0; i < views_.size(); i++) { + const AnchorLayoutParams *params = dynamic_cast(views_[i]->GetLayoutParams()); + + Bounds vBounds; + vBounds.w = views_[i]->GetMeasuredWidth(); + vBounds.h = views_[i]->GetMeasuredHeight(); + + float left = 0, top = 0, right = 0, bottom = 0; + + if (params) { + left = params->left; + top = params->top; + right = params->right; + bottom = params->bottom; + } + + if (left >= 0) vBounds.x = bounds_.x + left; + if (top >= 0) vBounds.y = bounds_.y + top; + if (right >= 0) vBounds.x = bounds_.x2() - right - vBounds.w; + if (bottom >= 0) vBounds.y = bounds_.y2() - bottom - vBounds.y; + + views_[i]->SetBounds(vBounds); + } +} + void GridLayout::Layout() { int y = 0; int x = 0; @@ -500,10 +556,6 @@ void GridLayout::Layout() { } } -void RelativeLayout::Layout() { - -} - void LayoutViewHierarchy(const DrawContext &dc, ViewGroup *root) { Bounds rootBounds; rootBounds.x = 0; diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 4d16a71ba1..de4c691198 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -55,12 +55,54 @@ public: void Layout(); }; -class RelativeLayout : public ViewGroup { + +enum { + NONE = -1, +}; + +class AnchorLayoutParams : public LayoutParams { public: + AnchorLayoutParams(Size w, Size h, float l, float t, float r, float b) + : LayoutParams(w, h), left(l), top(t), right(r), bottom(b) {} + + AnchorLayoutParams(float l, float t, float r, float b) + : LayoutParams(WRAP_CONTENT, WRAP_CONTENT), left(l), top(t), right(r), bottom(b) {} + + // These are not bounds, but distances from the container edges. + // Set to NONE to not attach this edge to the container. + float left, top, right, bottom; +}; + +class AnchorLayout : public ViewGroup { +public: + AnchorLayout(LayoutParams *layoutParams = 0) : ViewGroup(layoutParams) {} void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); }; +class LinearLayoutParams : public LayoutParams { +public: + LinearLayoutParams() + : LayoutParams(), weight(0.0f), gravity(G_TOPLEFT), hasMargins_(false) {} + explicit LinearLayoutParams(float wgt) + : LayoutParams(), weight(wgt), gravity(G_TOPLEFT), hasMargins_(false) {} + LinearLayoutParams(Size w, Size h, float wgt = 0.0f, Gravity grav = G_TOPLEFT) + : LayoutParams(w, h), weight(wgt), gravity(grav), hasMargins_(false) {} + LinearLayoutParams(Size w, Size h, float wgt, Gravity grav, const Margins &mgn) + : LayoutParams(w, h), weight(wgt), gravity(grav), margins(mgn), hasMargins_(true) {} + LinearLayoutParams(const Margins &mgn) + : LayoutParams(WRAP_CONTENT, WRAP_CONTENT), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} + + float weight; + Gravity gravity; + Margins margins; + + bool HasMargins() const { return hasMargins_; } + +private: + bool hasMargins_; +}; + class LinearLayout : public ViewGroup { public: LinearLayout(Orientation orientation, LayoutParams *layoutParams = 0) From cbf1b2d29d406567a7e635f79882243b34a00285 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 27 May 2013 22:57:06 +0200 Subject: [PATCH 0411/1445] Use scissor to clip scrollviews correctly. --- base/PCMain.cpp | 3 +++ ui/drawing.cpp | 44 +++++++++++++++++++++++++++++++++++++++++++- ui/drawing.h | 34 ++++++++++++++++++++++++++++++++++ ui/view.cpp | 1 + ui/view.h | 8 -------- ui/viewgroup.cpp | 5 +++-- 6 files changed, 84 insertions(+), 11 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 0f0b694ac4..22b951e7d8 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -384,6 +384,7 @@ int main(int argc, char *argv[]) { } } + net::Init(); #ifdef __APPLE__ // Make sure to request a somewhat modern GL context at least - the @@ -481,6 +482,8 @@ int main(int argc, char *argv[]) { float dp_xscale = (float)dp_xres / pixel_xres; float dp_yscale = (float)dp_yres / pixel_yres; + g_dpi_scale = pixel_xres / dp_xres; + printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); diff --git a/ui/drawing.cpp b/ui/drawing.cpp index ddc9c5ac25..01a1e3f0be 100644 --- a/ui/drawing.cpp +++ b/ui/drawing.cpp @@ -1,3 +1,45 @@ -namespace UI { +#include "base/display.h" +#include "ui/drawing.h" +#include "gfx_es2/draw_buffer.h" +#include "gfx_es2/gl_state.h" +DrawContext::DrawContext() { + +} + +DrawContext::~DrawContext() { + +} + +// TODO: Support transformed bounds using stencil +void DrawContext::PushScissor(const Bounds &bounds) { + Flush(); + scissorStack_.push_back(bounds); + ActivateTopScissor(); +} + +void DrawContext::PopScissor() { + Flush(); + scissorStack_.pop_back(); + ActivateTopScissor(); +} + +void DrawContext::ActivateTopScissor() { + if (scissorStack_.size()) { + const Bounds &bounds = scissorStack_.back(); + int x = g_dpi_scale * bounds.x; + int y = g_dpi_scale * (dp_yres - bounds.y2()); + int w = g_dpi_scale * bounds.w; + int h = g_dpi_scale * bounds.h; + + glstate.scissorRect.set(x,y,w,h); + glstate.scissorTest.enable(); + } else { + glstate.scissorTest.disable(); + } +} + +void DrawContext::Flush() { + draw->Flush(true); + drawTop->Flush(true); } \ No newline at end of file diff --git a/ui/drawing.h b/ui/drawing.h index e69de29bb2..f7677f4ede 100644 --- a/ui/drawing.h +++ b/ui/drawing.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "math/geom2d.h" +#include "gfx/texture_atlas.h" + +// Kind of ugly connection to UI. +namespace UI { + struct Theme; +} + +class DrawBuffer; + +class DrawContext { +public: + DrawContext(); + ~DrawContext(); + + DrawBuffer *draw; + DrawBuffer *drawTop; + const UI::Theme *theme; + + // TODO: Support transformed bounds using stencil + void PushScissor(const Bounds &bounds); + void PopScissor(); + + void ActivateTopScissor(); + + void Flush(); + +private: + std::vector scissorStack_; +}; \ No newline at end of file diff --git a/ui/view.cpp b/ui/view.cpp index 537d98ee2f..89151bc95f 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -5,6 +5,7 @@ #include "gfx/texture_atlas.h" #include "ui/ui.h" #include "ui/view.h" +#include "ui/drawing.h" namespace UI { diff --git a/ui/view.h b/ui/view.h index 602041c3a2..90799b4421 100644 --- a/ui/view.h +++ b/ui/view.h @@ -155,14 +155,6 @@ struct MeasureSpec { class View; -struct DrawContext { - DrawBuffer *draw; - DrawBuffer *drawTop; - const Theme *theme; - - void PushStencil(const Bounds &bounds) {} - void PopStencil() {} -}; // Should cover all bases. struct EventParams { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index d40bd278fe..2c9d4e72e7 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1,5 +1,6 @@ #include "base/display.h" #include "base/logging.h" +#include "ui/drawing.h" #include "ui/view.h" #include "ui/viewgroup.h" @@ -415,9 +416,9 @@ void ScrollView::Touch(const TouchInput &input) { } void ScrollView::Draw(DrawContext &dc) { - dc.PushStencil(bounds_); + dc.PushScissor(bounds_); views_[0]->Draw(dc); - dc.PopStencil(); + dc.PopScissor(); } bool ScrollView::SubviewFocused(View *view) { From f075c8fd560588a672bc27806b8929a5f19ca7cc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 28 May 2013 00:32:00 +0200 Subject: [PATCH 0412/1445] Merge DrawContext into UIContext. --- Android.mk | 4 ++- math/geom2d.h | 2 ++ native.vcxproj | 2 -- native.vcxproj.filters | 2 -- ui/drawing.cpp | 45 ------------------------- ui/drawing.h | 34 ------------------- ui/screen.cpp | 34 +++++++------------ ui/ui_context.cpp | 28 ++++++++++++++++ ui/ui_context.h | 24 ++++++++++++++ ui/view.cpp | 74 +++++++++++++++++++++--------------------- ui/view.h | 44 ++++++++++++------------- ui/viewgroup.cpp | 18 +++++----- ui/viewgroup.h | 18 +++++----- 13 files changed, 145 insertions(+), 184 deletions(-) delete mode 100644 ui/drawing.cpp delete mode 100644 ui/drawing.h diff --git a/Android.mk b/Android.mk index 9edfc363db..711551eae3 100644 --- a/Android.mk +++ b/Android.mk @@ -59,11 +59,13 @@ LOCAL_SRC_FILES :=\ image/zim_load.cpp \ image/zim_save.cpp \ image/png_load.cpp \ + ui/view.cpp \ + ui/viewgroup.cpp \ + ui/drawing.cpp \ ui/ui.cpp \ ui/ui_context.cpp \ ui/screen.cpp \ ui/virtual_input.cpp \ - ui/drawing.cpp \ util/random/perlin.cpp \ util/text/utf8.cpp diff --git a/math/geom2d.h b/math/geom2d.h index d165c80e4e..fd8357de40 100644 --- a/math/geom2d.h +++ b/math/geom2d.h @@ -1,5 +1,7 @@ #pragma once +#include + struct Point { Point() {} Point(float x_, float y_) : x(x_), y(y_) {} diff --git a/native.vcxproj b/native.vcxproj index 0fc33aa6a5..e40dd0368e 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -233,7 +233,6 @@ - @@ -350,7 +349,6 @@ - diff --git a/native.vcxproj.filters b/native.vcxproj.filters index ffe8acd256..4f0491e784 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -263,7 +263,6 @@ math - @@ -466,7 +465,6 @@ ui - diff --git a/ui/drawing.cpp b/ui/drawing.cpp deleted file mode 100644 index 01a1e3f0be..0000000000 --- a/ui/drawing.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "base/display.h" -#include "ui/drawing.h" -#include "gfx_es2/draw_buffer.h" -#include "gfx_es2/gl_state.h" - -DrawContext::DrawContext() { - -} - -DrawContext::~DrawContext() { - -} - -// TODO: Support transformed bounds using stencil -void DrawContext::PushScissor(const Bounds &bounds) { - Flush(); - scissorStack_.push_back(bounds); - ActivateTopScissor(); -} - -void DrawContext::PopScissor() { - Flush(); - scissorStack_.pop_back(); - ActivateTopScissor(); -} - -void DrawContext::ActivateTopScissor() { - if (scissorStack_.size()) { - const Bounds &bounds = scissorStack_.back(); - int x = g_dpi_scale * bounds.x; - int y = g_dpi_scale * (dp_yres - bounds.y2()); - int w = g_dpi_scale * bounds.w; - int h = g_dpi_scale * bounds.h; - - glstate.scissorRect.set(x,y,w,h); - glstate.scissorTest.enable(); - } else { - glstate.scissorTest.disable(); - } -} - -void DrawContext::Flush() { - draw->Flush(true); - drawTop->Flush(true); -} \ No newline at end of file diff --git a/ui/drawing.h b/ui/drawing.h deleted file mode 100644 index f7677f4ede..0000000000 --- a/ui/drawing.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - -#include "math/geom2d.h" -#include "gfx/texture_atlas.h" - -// Kind of ugly connection to UI. -namespace UI { - struct Theme; -} - -class DrawBuffer; - -class DrawContext { -public: - DrawContext(); - ~DrawContext(); - - DrawBuffer *draw; - DrawBuffer *drawTop; - const UI::Theme *theme; - - // TODO: Support transformed bounds using stencil - void PushScissor(const Bounds &bounds); - void PopScissor(); - - void ActivateTopScissor(); - - void Flush(); - -private: - std::vector scissorStack_; -}; \ No newline at end of file diff --git a/ui/screen.cpp b/ui/screen.cpp index d74ceb627a..db81e59155 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -38,11 +38,9 @@ void ScreenManager::update(InputState &input) { } } -void ScreenManager::switchToNext() -{ +void ScreenManager::switchToNext() { Layer temp = {0, 0}; - if (!stack_.empty()) - { + if (!stack_.empty()) { temp = stack_.back(); stack_.pop_back(); } @@ -52,8 +50,7 @@ void ScreenManager::switchToNext() nextScreen_ = 0; } -void ScreenManager::touch(const TouchInput &touch) -{ +void ScreenManager::touch(const TouchInput &touch) { if (stack_.size()) { stack_.back().screen->touch(touch); return; @@ -62,16 +59,12 @@ void ScreenManager::touch(const TouchInput &touch) void ScreenManager::render() { if (stack_.size()) { - switch (stack_.back().flags) - { + switch (stack_.back().flags) { case LAYER_SIDEMENU: - if (stack_.size() == 1) - { + if (stack_.size() == 1) { ELOG("Can't have sidemenu over nothing"); break; - } - else - { + } else { auto iter = stack_.end(); iter--; iter--; @@ -94,8 +87,7 @@ void ScreenManager::render() { processFinishDialog(); } -void ScreenManager::sendMessage(const char *msg, const char *value) -{ +void ScreenManager::sendMessage(const char *msg, const char *value) { if (stack_.size()) stack_.back().screen->sendMessage(msg, value); } @@ -144,10 +136,8 @@ void ScreenManager::pop() { } } -void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) -{ - if (dialog != stack_.back().screen) - { +void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) { + if (dialog != stack_.back().screen) { ELOG("Wrong dialog being finished!"); return; } @@ -159,10 +149,8 @@ void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) dialogResult_ = result; } -void ScreenManager::processFinishDialog() -{ - if (dialogFinished_) - { +void ScreenManager::processFinishDialog() { + if (dialogFinished_) { if (stack_.size()) { stack_.pop_back(); } diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 731b105982..00fd157cf8 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -68,4 +68,32 @@ void UIContext::End() { UIEnd(); Flush(); +} + +// TODO: Support transformed bounds using stencil +void UIContext::PushScissor(const Bounds &bounds) { + Flush(); + scissorStack_.push_back(bounds); + ActivateTopScissor(); +} + +void UIContext::PopScissor() { + Flush(); + scissorStack_.pop_back(); + ActivateTopScissor(); +} + +void UIContext::ActivateTopScissor() { + if (scissorStack_.size()) { + const Bounds &bounds = scissorStack_.back(); + int x = g_dpi_scale * bounds.x; + int y = g_dpi_scale * (dp_yres - bounds.y2()); + int w = g_dpi_scale * bounds.w; + int h = g_dpi_scale * bounds.h; + + glstate.scissorRect.set(x,y,w,h); + glstate.scissorTest.enable(); + } else { + glstate.scissorTest.disable(); + } } \ No newline at end of file diff --git a/ui/ui_context.h b/ui/ui_context.h index ba87378d87..5552290f98 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -1,5 +1,10 @@ #pragma once +#include + +#include "math/geom2d.h" +#include "gfx/texture_atlas.h" + // Everything you need to draw a UI collected into a single unit that can be passed around. // Everything forward declared so this header is safe everywhere. @@ -7,6 +12,13 @@ struct GLSLProgram; class Texture; class DrawBuffer; +// Kind of ugly connection to UI. +namespace UI { + struct Theme; +} + +class DrawBuffer; + // Who should own this? Really not sure. class UIContext { public: @@ -27,6 +39,16 @@ public: void RebindTexture() const; + // TODO: Support transformed bounds using stencil + void PushScissor(const Bounds &bounds); + void PopScissor(); + + void ActivateTopScissor(); + + DrawBuffer *Draw() const { return uidrawbuffer_; } + + const UI::Theme *theme; + private: // TODO: Collect these into a UIContext const GLSLProgram *uishader_; @@ -34,4 +56,6 @@ private: Texture *uitexture_; DrawBuffer *uidrawbuffer_; DrawBuffer *uidrawbufferTop_; + + std::vector scissorStack_; }; diff --git a/ui/view.cpp b/ui/view.cpp index 89151bc95f..6234d6533a 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -5,7 +5,7 @@ #include "gfx/texture_atlas.h" #include "ui/ui.h" #include "ui/view.h" -#include "ui/drawing.h" +#include "ui/ui_context.h" namespace UI { @@ -76,7 +76,7 @@ void Event::Update() { } } -void View::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { +void View::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { float contentW = 0.0f, contentH = 0.0f; GetContentDimensions(dc, contentW, contentH); MeasureBySpec(layoutParams_->width, contentW, horiz, &measuredWidth_); @@ -85,7 +85,7 @@ void View::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { // Default values -void View::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { +void View::GetContentDimensions(const UIContext &dc, float &w, float &h) const { w = 10.0f; h = 10.0f; } @@ -135,78 +135,78 @@ void Clickable::Update(const InputState &input_state) { } } -void ClickableItem::Draw(DrawContext &dc) { +void ClickableItem::Draw(UIContext &dc) { if (down_) { - dc.draw->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.bgColor); + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.bgColor); } else if (HasFocus()) { - dc.draw->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), dc.theme->itemFocusedStyle.bgColor); + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), dc.theme->itemFocusedStyle.bgColor); } } -void Choice::Draw(DrawContext &dc) { +void Choice::Draw(UIContext &dc) { ClickableItem::Draw(dc); int paddingX = 4; int paddingY = 4; - dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); + dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); } -void InfoItem::Draw(DrawContext &dc) { +void InfoItem::Draw(UIContext &dc) { int paddingX = 4; int paddingY = 4; - dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); - dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); - dc.draw->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor); + dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); + dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor); } -void ItemHeader::Draw(DrawContext &dc) { - dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.y, 0xFF707070, ALIGN_LEFT); - dc.draw->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.bgColor); +void ItemHeader::Draw(UIContext &dc) { + dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.y, 0xFF707070, ALIGN_LEFT); + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.bgColor); } -void CheckBox::Draw(DrawContext &dc) { +void CheckBox::Draw(UIContext &dc) { ClickableItem::Draw(dc); int paddingX = 80; int paddingY = 4; - dc.draw->DrawImage(dc.theme->checkOn, bounds_.x + 30, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); - dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); + dc.Draw()->DrawImage(dc.theme->checkOn, bounds_.x + 30, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); + dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); } -void Button::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { - dc.draw->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); +void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); } -void Button::Draw(DrawContext &dc) { +void Button::Draw(UIContext &dc) { int image = down_ ? dc.theme->buttonImage : dc.theme->buttonSelected; Style style = dc.theme->buttonStyle; if (HasFocus()) style = dc.theme->buttonFocusedStyle; if (down_) style = dc.theme->buttonDownStyle; - dc.draw->DrawImage4Grid(dc.theme->buttonImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); - dc.draw->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); + dc.Draw()->DrawImage4Grid(dc.theme->buttonImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); + dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); } -void ImageView::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { - const AtlasImage &img = dc.draw->GetAtlas()->images[atlasImage_]; +void ImageView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + const AtlasImage &img = dc.Draw()->GetAtlas()->images[atlasImage_]; // TODO: involve sizemode w = img.w; h = img.h; } -void ImageView::Draw(DrawContext &dc) { +void ImageView::Draw(UIContext &dc) { // TODO: involve sizemode - dc.draw->DrawImage(atlasImage_, bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF); + dc.Draw()->DrawImage(atlasImage_, bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF); } -void TextView::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { - dc.draw->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); +void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); } -void TextView::Draw(DrawContext &dc) { +void TextView::Draw(UIContext &dc) { // TODO: involve sizemode - dc.draw->DrawTextRect(dc.theme->uiFont, text_.c_str(), bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF); + dc.Draw()->DrawTextRect(dc.theme->uiFont, text_.c_str(), bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF); } void TriggerButton::Touch(const TouchInput &input) { @@ -233,13 +233,13 @@ void TriggerButton::Touch(const TouchInput &input) { } } -void TriggerButton::Draw(DrawContext &dc) { - dc.draw->DrawImage(imageBackground_, bounds_.centerX(), bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); - dc.draw->DrawImage(imageForeground_, bounds_.centerX(), bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); +void TriggerButton::Draw(UIContext &dc) { + dc.Draw()->DrawImage(imageBackground_, bounds_.centerX(), bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + dc.Draw()->DrawImage(imageForeground_, bounds_.centerX(), bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); } -void TriggerButton::GetContentDimensions(const DrawContext &dc, float &w, float &h) const { - const AtlasImage &image = dc.draw->GetAtlas()->images[imageBackground_]; +void TriggerButton::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + const AtlasImage &image = dc.Draw()->GetAtlas()->images[imageBackground_]; w = image.w; h = image.h; } @@ -282,7 +282,7 @@ void TabStrip::Draw(DrawContext &dc) { } }*/ -void Fill(DrawContext &dc, const Bounds &bounds, const Drawable &drawable) { +void Fill(UIContext &dc, const Bounds &bounds, const Drawable &drawable) { if (drawable.type == DRAW_SOLID_COLOR) { } diff --git a/ui/view.h b/ui/view.h index 90799b4421..7d5f4466a3 100644 --- a/ui/view.h +++ b/ui/view.h @@ -30,7 +30,7 @@ struct TouchInput; struct InputState; class DrawBuffer; -class DrawContext; +class UIContext; // I don't generally like namespaces but I think we do need one for UI, so many potentially-clashing names. namespace UI { @@ -139,7 +139,7 @@ enum EventReturn { class ViewGroup; -void Fill(DrawContext &dc, const Bounds &bounds, const Drawable &drawable); +void Fill(UIContext &dc, const Bounds &bounds, const Drawable &drawable); struct MeasureSpec { MeasureSpec(MeasureSpecType t, float s = 0.0f) : type(t), size(s) {} @@ -232,15 +232,15 @@ public: } // Views don't do anything here in Layout, only containers implement this. - virtual void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); virtual void Layout() {} - virtual void Draw(DrawContext &dc) {} + virtual void Draw(UIContext &dc) {} virtual float GetMeasuredWidth() const { return measuredWidth_; } virtual float GetMeasuredHeight() const { return measuredHeight_; } // Override this for easy standard behaviour. No need to override Measure. - virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; // Called when the layout is done. void SetBounds(Bounds bounds) { bounds_ = bounds; } @@ -317,8 +317,8 @@ public: Button(const std::string &text, LayoutParams *layoutParams = 0) : Clickable(layoutParams), text_(text) {} - virtual void Draw(DrawContext &dc); - virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; + virtual void Draw(UIContext &dc); + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; private: Style style_; @@ -333,8 +333,8 @@ public: : View(layoutParams), down_(0.0), bitField_(bitField), bit_(bit), imageBackground_(imageBackground), imageForeground_(imageForeground) {} virtual void Touch(const TouchInput &input); - virtual void Draw(DrawContext &dc); - virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; + virtual void Draw(UIContext &dc); + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; private: int down_; // bitfield of pressed fingers, translates into bitField @@ -357,7 +357,7 @@ public: layoutParams_->height = 80; } - virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const { + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { w = 0.0f; h = 0.0f; } @@ -370,13 +370,13 @@ public: layoutParams_->height = 80; } - virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const { + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { w = 0.0f; h = 0.0f; } // Draws the item background. - virtual void Draw(DrawContext &dc); + virtual void Draw(UIContext &dc); }; // Use to trigger something or open a submenu screen. @@ -385,7 +385,7 @@ public: Choice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), text_(text), smallText_(smallText) {} - virtual void Draw(DrawContext &dc); + virtual void Draw(UIContext &dc); private: std::string text_; @@ -397,7 +397,7 @@ public: InfoItem(const std::string &text, const std::string &rightText, LayoutParams *layoutParams = 0) : Item(layoutParams), text_(text), rightText_(rightText) {} - virtual void Draw(DrawContext &dc); + virtual void Draw(UIContext &dc); private: std::string text_; @@ -411,7 +411,7 @@ public: layoutParams_->width = FILL_PARENT; layoutParams_->height = 26; } - virtual void Draw(DrawContext &dc); + virtual void Draw(UIContext &dc); private: std::string text_; }; @@ -423,7 +423,7 @@ public: OnClick.Add(std::bind(&CheckBox::OnClicked, this, std::placeholders::_1)); } - virtual void Draw(DrawContext &dc); + virtual void Draw(UIContext &dc); EventReturn OnClicked(const EventParams &e) { if (toggle_) @@ -444,10 +444,10 @@ class Spacer : public InertView { public: Spacer(LayoutParams *layoutParams = 0) : InertView(layoutParams) {} - virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) { + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) { w = 0.0f; h = 0.0f; } - virtual void Draw(DrawContext &dc) {} + virtual void Draw(UIContext &dc) {} }; class TextView : public InertView { @@ -455,8 +455,8 @@ public: TextView(int font, const std::string &text, LayoutParams *layoutParams = 0) : InertView(layoutParams), font_(font), text_(text) {} - virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; - virtual void Draw(DrawContext &dc); + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + virtual void Draw(UIContext &dc); private: std::string text_; @@ -472,8 +472,8 @@ public: ImageView(int atlasImage, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0) : InertView(layoutParams), atlasImage_(atlasImage), sizeMode_(sizeMode) {} - virtual void GetContentDimensions(const DrawContext &dc, float &w, float &h) const; - virtual void Draw(DrawContext &dc); + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + virtual void Draw(UIContext &dc); private: int atlasImage_; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 2c9d4e72e7..03ec7757a3 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1,6 +1,6 @@ #include "base/display.h" #include "base/logging.h" -#include "ui/drawing.h" +#include "ui/ui_context.h" #include "ui/view.h" #include "ui/viewgroup.h" @@ -36,7 +36,7 @@ void ViewGroup::Touch(const TouchInput &input) { } } -void ViewGroup::Draw(DrawContext &dc) { +void ViewGroup::Draw(UIContext &dc) { for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. (*iter)->Draw(dc); @@ -191,7 +191,7 @@ void MoveFocus(ViewGroup *root, FocusDirection direction) { } } -void LinearLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { +void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { if (views_.empty()) { MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); @@ -325,7 +325,7 @@ void LinearLayout::Layout() { } } -void FrameLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { +void FrameLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { if (views_.empty()) { MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); @@ -341,7 +341,7 @@ void FrameLayout::Layout() { } -void ScrollView::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { +void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { // Respect margins Margins margins; const LinearLayoutParams *params = dynamic_cast(views_[0]->GetLayoutParams()); @@ -415,7 +415,7 @@ void ScrollView::Touch(const TouchInput &input) { } } -void ScrollView::Draw(DrawContext &dc) { +void ScrollView::Draw(UIContext &dc) { dc.PushScissor(bounds_); views_[0]->Draw(dc); dc.PopScissor(); @@ -455,7 +455,7 @@ void ScrollView::ScrollTo(float newScrollPos) { scrollPos_ = newScrollPos; } -void GridLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { +void GridLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { MeasureSpecType measureType = settings_.fillCells ? EXACTLY : AT_MOST; for (size_t i = 0; i < views_.size(); i++) { @@ -473,7 +473,7 @@ void GridLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec v MeasureBySpec(layoutParams_->height, estimatedHeight, vert, &measuredHeight_); } -void AnchorLayout::Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) { +void AnchorLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, horiz, &measuredHeight_); @@ -557,7 +557,7 @@ void GridLayout::Layout() { } } -void LayoutViewHierarchy(const DrawContext &dc, ViewGroup *root) { +void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { Bounds rootBounds; rootBounds.x = 0; rootBounds.y = 0; diff --git a/ui/viewgroup.h b/ui/viewgroup.h index de4c691198..8c55a3387a 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -23,11 +23,11 @@ public: virtual void Touch(const TouchInput &input); // By default, a container will layout to its own bounds. - virtual void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert) = 0; + virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) = 0; virtual void Layout() = 0; virtual void Update(const InputState &input_state); - virtual void Draw(DrawContext &dc); + virtual void Draw(UIContext &dc); // These should be unused. virtual float GetContentWidth() const { return 0.0f; } @@ -51,7 +51,7 @@ protected: // A frame layout contains a single child view (normally). class FrameLayout : public ViewGroup { public: - void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); }; @@ -76,7 +76,7 @@ public: class AnchorLayout : public ViewGroup { public: AnchorLayout(LayoutParams *layoutParams = 0) : ViewGroup(layoutParams) {} - void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); }; @@ -108,7 +108,7 @@ public: LinearLayout(Orientation orientation, LayoutParams *layoutParams = 0) : ViewGroup(layoutParams), spacing_(5), orientation_(orientation), defaultMargins_(0) {} - void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); private: @@ -139,7 +139,7 @@ public: ELOG("GridLayout: Vertical layouts not yet supported"); } - void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); private: @@ -152,11 +152,11 @@ public: ScrollView(Orientation orientation, LayoutParams *layoutParams = 0) : ViewGroup(layoutParams), orientation_(orientation), scrollPos_(0) {} - void Measure(const DrawContext &dc, MeasureSpec horiz, MeasureSpec vert); + void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); void Touch(const TouchInput &input); - void Draw(DrawContext &dc); + void Draw(UIContext &dc); void ScrollTo(float newScrollPos); @@ -175,7 +175,7 @@ class ViewPager : public ScrollView { public: }; -void LayoutViewHierarchy(const DrawContext &dc, ViewGroup *root); +void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root); void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root); } // namespace UI \ No newline at end of file From 7b7c44eb501cdd7d03a71dfbd471912a8310fae2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 28 May 2013 00:50:19 +0200 Subject: [PATCH 0413/1445] Smooth autoscroll --- ui/view.cpp | 13 +++++++++++-- ui/view.h | 12 ++---------- ui/viewgroup.cpp | 43 +++++++++++++++++++++++++++++-------------- ui/viewgroup.h | 6 ++++-- 4 files changed, 46 insertions(+), 28 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 6234d6533a..7cff1d5d12 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -12,7 +12,7 @@ namespace UI { static View *focusedView; static bool focusMovementEnabled; -const float ITEM_HEIGHT = 48.f; +const float ITEM_HEIGHT = 64.f; View *GetFocusedView() { return focusedView; @@ -49,7 +49,6 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure } } - void Event::Add(std::function func) { HandlerRegistration reg; reg.func = func; @@ -135,6 +134,16 @@ void Clickable::Update(const InputState &input_state) { } } +Item::Item(LayoutParams *layoutParams) : InertView(layoutParams) { + layoutParams_->width = FILL_PARENT; + layoutParams_->height = ITEM_HEIGHT; +} + +ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParams) { + layoutParams_->width = FILL_PARENT; + layoutParams_->height = ITEM_HEIGHT; +} + void ClickableItem::Draw(UIContext &dc) { if (down_) { dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.bgColor); diff --git a/ui/view.h b/ui/view.h index 7d5f4466a3..813231eff0 100644 --- a/ui/view.h +++ b/ui/view.h @@ -352,11 +352,7 @@ private: class Item : public InertView { public: - Item(LayoutParams *layoutParams) : InertView(layoutParams) { - layoutParams_->width = FILL_PARENT; - layoutParams_->height = 80; - } - + Item(LayoutParams *layoutParams); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { w = 0.0f; h = 0.0f; @@ -365,11 +361,7 @@ public: class ClickableItem : public Clickable { public: - ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParams) { - layoutParams_->width = FILL_PARENT; - layoutParams_->height = 80; - } - + ClickableItem(LayoutParams *layoutParams); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { w = 0.0f; h = 0.0f; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 03ec7757a3..51377993e4 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -145,7 +145,6 @@ NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, Nei if (score > result.score) { result.score = score; result.view = views_[i]; - result.parent = this; } } @@ -451,8 +450,20 @@ bool ScrollView::SubviewFocused(View *view) { } void ScrollView::ScrollTo(float newScrollPos) { - // TODO: Smooth scrolling - scrollPos_ = newScrollPos; + scrollTarget_ = newScrollPos; + scrollToTarget_ = true; +} + +void ScrollView::Update(const InputState &input_state) { + ViewGroup::Update(input_state); + if (scrollToTarget_) { + if (fabsf(scrollTarget_ - scrollPos_) < 0.5f) { + scrollPos_ = scrollTarget_; + scrollToTarget_ = false; + } else { + scrollPos_ += (scrollTarget_ - scrollPos_) * 0.3f; + } + } } void GridLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { @@ -577,21 +588,25 @@ void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { if (input_state.pad_buttons_down & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) + { EnableFocusMovement(true); + if (!GetFocusedView()) { + root->SetFocus(); + root->SubviewFocused(GetFocusedView()); + } else { + if (input_state.pad_buttons_down & PAD_BUTTON_RIGHT) + MoveFocus(root, FOCUS_RIGHT); + if (input_state.pad_buttons_down & PAD_BUTTON_UP) + MoveFocus(root, FOCUS_UP); + if (input_state.pad_buttons_down & PAD_BUTTON_LEFT) + MoveFocus(root, FOCUS_LEFT); + if (input_state.pad_buttons_down & PAD_BUTTON_DOWN) + MoveFocus(root, FOCUS_DOWN); + } + } if (input_state.pointer_down[0]) EnableFocusMovement(false); - //if (input_state.pad_last_buttons == 0) { - if (input_state.pad_buttons_down & PAD_BUTTON_RIGHT) - MoveFocus(root, FOCUS_RIGHT); - if (input_state.pad_buttons_down & PAD_BUTTON_UP) - MoveFocus(root, FOCUS_UP); - if (input_state.pad_buttons_down & PAD_BUTTON_LEFT) - MoveFocus(root, FOCUS_LEFT); - if (input_state.pad_buttons_down & PAD_BUTTON_DOWN) - MoveFocus(root, FOCUS_DOWN); - //} - root->Update(input_state); } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 8c55a3387a..a3fe54470e 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -10,7 +10,6 @@ struct NeighborResult { NeighborResult(View *v, float s) : view(v), score(s) {} View *view; - ViewGroup *parent; float score; }; @@ -150,7 +149,7 @@ private: class ScrollView : public ViewGroup { public: ScrollView(Orientation orientation, LayoutParams *layoutParams = 0) : - ViewGroup(layoutParams), orientation_(orientation), scrollPos_(0) {} + ViewGroup(layoutParams), orientation_(orientation), scrollPos_(0), scrollTarget_(0), scrollToTarget_(false) {} void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); @@ -159,6 +158,7 @@ public: void Draw(UIContext &dc); void ScrollTo(float newScrollPos); + void Update(const InputState &input_state); // Override so that we can scroll to the active one after moving the focus. virtual bool SubviewFocused(View *view); @@ -169,6 +169,8 @@ private: float scrollPos_; float scrollStart_; float scrollMax_; + float scrollTarget_; + bool scrollToTarget_; }; class ViewPager : public ScrollView { From ceefd214c4a7799b47fbd2c6ba322649d3462700 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Thu, 30 May 2013 15:17:00 +0200 Subject: [PATCH 0414/1445] Warning fix on Intel compiler. --- math/lin/quat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/math/lin/quat.h b/math/lin/quat.h index 89746e5aab..85b4d94c94 100644 --- a/math/lin/quat.h +++ b/math/lin/quat.h @@ -76,7 +76,7 @@ public: float &operator [] (int i) { return *((&x) + i); } - const float operator [] (int i) const { + float operator [] (int i) const { return *((&x) + i); } //not sure about this, maybe mag is supposed to sqrt From 5f16de66678047c6697673e42a767ed09541336a Mon Sep 17 00:00:00 2001 From: lioncash Date: Thu, 30 May 2013 15:08:51 -0400 Subject: [PATCH 0415/1445] Fix a memleak in function DNSResolveTry in resolve.cpp. --- net/resolve.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/net/resolve.cpp b/net/resolve.cpp index 6b0af606f0..738f7d3aee 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -49,6 +49,7 @@ char *DNSResolveTry(const char *host, const char **err) if (iptoa == NULL) { *err = "Can't resolve host"; + free(ip); return NULL; } strncpy(ip, iptoa, iplen); From 5f659ce2828932c35fd038d894f80470bea7c1e6 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 31 May 2013 23:04:42 +0200 Subject: [PATCH 0416/1445] Add some network stuff (background downloader, URL splitter) --- Android.mk | 1 + android/.classpath | 1 + base/buffer.cpp | 34 +++++++-- base/buffer.h | 5 +- base/functional.h | 24 ++++++ input/input_state.h | 4 + native.vcxproj | 3 + native.vcxproj.filters | 9 +++ net/http_client.cpp | 75 +++++++++++++++++-- net/http_client.h | 39 +++++++++- net/resolve.cpp | 1 + net/url.cpp | 22 ++++++ net/url.h | 126 ++++++++++++++++++++++++++++++++ thread/prioritizedworkqueue.cpp | 10 +-- 14 files changed, 329 insertions(+), 25 deletions(-) create mode 100644 base/functional.h create mode 100644 net/url.cpp create mode 100644 net/url.h diff --git a/Android.mk b/Android.mk index 2311998a62..301d6ab62e 100644 --- a/Android.mk +++ b/Android.mk @@ -42,6 +42,7 @@ LOCAL_SRC_FILES :=\ midi/midi_input.cpp \ net/http_client.cpp \ net/resolve.cpp \ + net/url.cpp \ profiler/profiler.cpp \ thread/threadutil.cpp \ thread/prioritizedworkqueue.cpp \ diff --git a/android/.classpath b/android/.classpath index a4763d1eec..bb0c759770 100644 --- a/android/.classpath +++ b/android/.classpath @@ -4,5 +4,6 @@ + diff --git a/base/buffer.cpp b/base/buffer.cpp index 9abcfe8eab..55b9e11015 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -76,7 +76,7 @@ int Buffer::SkipLineCRLF() { } int Buffer::OffsetToAfterNextCRLF() { - for (size_t i = 0; i < data_.size() - 1; i++) { + for (int i = 0; i < (int)data_.size() - 1; i++) { if (data_[i] == '\r' && data_[i + 1] == '\n') { return i + 2; } @@ -109,6 +109,17 @@ bool Buffer::Flush(int fd) { return success; } +bool Buffer::FlushToFile(const char *filename) { + FILE *f = fopen(filename, "wb"); + if (!f) + return false; + if (data_.size()) { + fwrite(&data_[0], 1, data_.size(), f); + } + fclose(f); + return true; +} + bool Buffer::FlushSocket(uintptr_t sock) { for (size_t pos = 0, end = data_.size(); pos < end; ) { int sent = send(sock, &data_[pos], end - pos, 0); @@ -132,13 +143,20 @@ bool Buffer::FlushSocket(uintptr_t sock) { return true; } -void Buffer::ReadAll(int fd) { - char buf[1024]; - int retval; - while ((retval = recv(fd, buf, sizeof(buf), 0)) > 0) { - char *p = Append((size_t)retval); - memcpy(p, buf, retval); - } +bool Buffer::ReadAll(int fd) { + char buf[1024]; + while (true) { + int retval = recv(fd, buf, sizeof(buf), 0); + if (retval == 0) + return true; + else if (retval < 0) { + ELOG("Error reading from buffer: %i", retval); + return false; + } + char *p = Append((size_t)retval); + memcpy(p, buf, retval); + } + return true; } void Buffer::Read(int fd, size_t sz) { diff --git a/base/buffer.h b/base/buffer.h index 5f716edbb6..440eb5015f 100644 --- a/base/buffer.h +++ b/base/buffer.h @@ -60,10 +60,11 @@ class Buffer { // Writes the entire buffer to the file descriptor. Also resets the // size to zero. On failure, data remains in buffer and nothing is // written. - bool Flush(int fd); + bool Flush(int fd); + bool FlushToFile(const char *filename); bool FlushSocket(uintptr_t sock); // Windows portability - void ReadAll(int fd); + bool ReadAll(int fd); void Read(int fd, size_t sz); // Utilities. Try to avoid checking for size. diff --git a/base/functional.h b/base/functional.h new file mode 100644 index 0000000000..46c516f941 --- /dev/null +++ b/base/functional.h @@ -0,0 +1,24 @@ +// This file simply includes and applies any necessary compatibility fixes for +// strange platforms like iOS. + +// Use p as the namespace for placeholders. + +#pragma once + +#include + +#if defined(IOS) || defined(MACGNUSTD) +#include +namespace std { + using tr1::bind; +} +#endif + +#ifdef __SYMBIAN32__ +#define p +#elif defined(IOS) +#include +namespace p = std::tr1::placeholders; +#else +namespace p = std::placeholders; +#endif diff --git a/input/input_state.h b/input/input_state.h index 37bacd460e..553bafb810 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -29,6 +29,10 @@ enum { PAD_BUTTON_LEFT_THUMB = 1 << 18, // Click left thumb stick on X360 PAD_BUTTON_RIGHT_THUMB = 1 << 19, // Click right thumb stick on X360 + + PAD_BUTTON_LEFT_TRIGGER = 1 << 21, // Click left thumb stick on X360 + PAD_BUTTON_RIGHT_TRIGGER = 1 << 22, // Click left thumb stick on X360 + PAD_BUTTON_UNTHROTTLE = 1 << 20, // Click Tab to unthrottle }; diff --git a/native.vcxproj b/native.vcxproj index 805dff1e02..83d833ed9a 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -174,6 +174,7 @@ + @@ -227,6 +228,7 @@ + @@ -342,6 +344,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index da9f3d708f..d4dee4c0f5 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -254,6 +254,12 @@ thread + + base + + + net + @@ -450,6 +456,9 @@ thread + + net + diff --git a/net/http_client.cpp b/net/http_client.cpp index 739546af5d..90aec31764 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -18,6 +18,9 @@ #include "base/buffer.h" #include "base/stringutil.h" #include "net/resolve.h" +#include "net/url.h" +#include "base/functional.h" + // #include "strings/strutil.h" namespace net { @@ -99,24 +102,30 @@ namespace http { Client::Client() { } Client::~Client() { + Disconnect(); } #define USERAGENT "METAGET 1.0" -void Client::GET(const char *resource, Buffer *output) { +int Client::GET(const char *resource, Buffer *output) { Buffer buffer; const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " USERAGENT "\r\n\r\n"; buffer.Printf(tpl, resource, host_.c_str()); - CHECK(buffer.FlushSocket(sock())); + bool flushed = buffer.FlushSocket(sock()); + if (!flushed) { + return -1; // TODO error code. + } // Snarf all the data we can. - output->ReadAll(sock()); + if (!output->ReadAll(sock())) + return -1; - // Skip the header. + // Skip the header. TODO: read HTTP code and file size so we can make progress bars. while (output->SkipLineCRLF() > 0) ; // output now contains the rest of the reply. + return 200; } int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output) { @@ -148,7 +157,7 @@ int Client::POST(const char *resource, const std::string &data, const std::strin // Tear off the http headers, leaving the actual response data. std::string firstline; CHECK_GT(output->TakeLineCRLF(&firstline), 0); - int code = atoi(&firstline[9]); // ugggly hardcoding + int code = atoi(&firstline[9]); //VLOG(1) << "HTTP result code: " << code; while (true) { int skipped = output->SkipLineCRLF(); @@ -163,4 +172,60 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) return POST(resource, data, "", output); } +Download::Download(const std::string &url, const std::string &outfile) + : url_(url), outfile_(outfile), progress_(0.0f), failed_(false) { + + std::thread th(std::bind(&Download::Do, this)); + th.detach(); +} + +Download::~Download() { + +} + + +void Download::Do() { + Url fileUrl(url_); + if (!fileUrl.Valid()) { + failed_ = true; + return; + } + net::Init(); + + http::Client client; + if (!client.Resolve(fileUrl.Host().c_str(), 80)) { + ELOG("Failed resolving %s", url_.c_str()); + failed_ = true; + return; + } + client.Connect(); + if (client.GET(fileUrl.Resource().c_str(), &buffer_)) { + progress_ = 1.0f; + ILOG("Completed downloading %s to %s", url_.c_str(), outfile_.c_str()); + if (!buffer_.FlushToFile(outfile_.c_str())) { + ELOG("Failed writing download to %s", outfile_.c_str()); + } + } else { + ELOG("Error downloading %s to %s", url_.c_str(), outfile_.c_str()); + } + + net::Shutdown(); +} + +std::shared_ptr Downloader::StartDownload(const std::string &url, const std::string &outfile) { + std::shared_ptr dl(new Download(url, outfile)); + downloads_.push_back(dl); + return dl; +} + +void Downloader::Update() { + restart: + for (size_t i = 0; i < downloads_.size(); i++) { + if (downloads_[i]->Progress() == 1.0f || downloads_[i]->Failed()) { + downloads_.erase(downloads_.begin() + i); + goto restart; + } + } +} + } // http diff --git a/net/http_client.h b/net/http_client.h index 2b36360541..9de4e64f1a 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -3,6 +3,7 @@ #include "base/basictypes.h" #include "base/buffer.h" +#include "thread/thread.h" #ifdef _WIN32 #include @@ -56,7 +57,8 @@ public: Client(); ~Client(); - void GET(const char *resource, Buffer *output); + // Return value is the HTTP return code. 200 means OK. < 0 means some local error. + int GET(const char *resource, Buffer *output); // Return value is the HTTP return code. int POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output); @@ -65,6 +67,41 @@ public: // HEAD, PUT, DELETE aren't implemented yet. }; +// Not particularly efficient, but hey - it's a background download, that's pretty cool :P +class Download { +public: + Download(const std::string &url, const std::string &outfile); + ~Download(); + + // Returns 1.0 when done. That one value can be compared exactly. + float Progress() const { return progress_; } + bool Failed() const { return failed_; } + + std::string url() const { return url_; } + std::string outfile() const { return outfile_; } + +private: + void Do(); // Actually does the download. Runs on thread. + + float progress_; + Buffer buffer_; + std::string url_; + std::string outfile_; + bool failed_; +}; + +class Downloader { +public: + std::shared_ptr StartDownload(const std::string &url, const std::string &outfile); + + // Drops finished downloads from the list. + void Update(); + +private: + std::vector> downloads_; +}; + + } // http #endif // _NET_HTTP_HTTP_CLIENT diff --git a/net/resolve.cpp b/net/resolve.cpp index 6b0af606f0..79d0162096 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -22,6 +22,7 @@ namespace net { void Init() { #ifdef _WIN32 + // WSA does its own internal reference counting, no need to keep track of if we inited or not. WSADATA wsaData = {0}; WSAStartup(MAKEWORD(2, 2), &wsaData); #endif diff --git a/net/url.cpp b/net/url.cpp new file mode 100644 index 0000000000..7b788260ee --- /dev/null +++ b/net/url.cpp @@ -0,0 +1,22 @@ +#include "base/logging.h" +#include "net/url.h" + +const char *UrlEncoder::unreservedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~"; +const char *UrlEncoder::hexChars = "0123456789ABCDEF"; + +void Url::Split() { + size_t colonSlashSlash = url_.find("://"); + if (colonSlashSlash == std::string::npos) { + ELOG("Invalid URL: %s", url_.c_str()); + return; + } + + protocol_ = url_.substr(0, colonSlashSlash); + + size_t sep = url_.find('/', colonSlashSlash + 3); + + host_ = url_.substr(colonSlashSlash + 3, sep - colonSlashSlash - 3); + resource_ = url_.substr(sep); // include the slash! + + valid_ = protocol_.size() > 1 && host_.size() > 1; +} \ No newline at end of file diff --git a/net/url.h b/net/url.h new file mode 100644 index 0000000000..2358dfb446 --- /dev/null +++ b/net/url.h @@ -0,0 +1,126 @@ +#pragma once + +#include +#include +#include +#include + +#include "base/basictypes.h" + +#if defined(_MSC_VER) +#undef snprintf +#define snprintf _snprintf +#endif + +struct UrlEncoder +{ + UrlEncoder() : paramCount(0) + { + data.reserve(256); + }; + + void Add(const std::string &key, const std::string &value) + { + if (++paramCount > 1) + data += '&'; + AppendEscaped(key); + data += '='; + AppendEscaped(value); + } + + void Add(const std::string &key, const char *value) + { + Add(key, std::string(value)); + } + + template + void AddT(const std::string &key, const char *fmt, const T value) + { + char temp[64]; + snprintf(temp, sizeof(temp), fmt, value); + temp[sizeof(temp) - 1] = '\0'; + Add(key, temp); + } + + void Add(const std::string &key, const int value) + { + AddT(key, "%d", value); + } + + void Add(const std::string &key, const uint32_t value) + { + AddT(key, "%u", value); + } + + void Add(const std::string &key, const uint64_t value) + { + AddT(key, "%llu", value); + } + + void Add(const std::string &key, const double value) + { + AddT(key, "%f", value); + } + + void Add(const std::string &key, const bool value) + { + Add(key, value ? "true" : "false"); + } + + // Percent encoding, aka application/x-www-form-urlencoded. + void AppendEscaped(const std::string &value) + { + for (size_t lastEnd = 0; lastEnd < value.length(); ) + { + size_t pos = value.find_first_not_of(unreservedChars, lastEnd); + if (pos == value.npos) + { + data += value.substr(lastEnd); + break; + } + + if (pos != lastEnd) + data += value.substr(lastEnd, pos - lastEnd); + lastEnd = pos; + + // Encode the reserved character. + char c = value[pos]; + data += '%'; + data += hexChars[(c >> 4) & 15]; + data += hexChars[(c >> 0) & 15]; + ++lastEnd; + } + } + + std::string &ToString() + { + return data; + } + + std::string data; + int paramCount; + static const char *unreservedChars; + static const char *hexChars; +}; + + +class Url { +public: + Url(const std::string url) : url_(url), valid_(false) { + Split(); + } + + bool Valid() const { return valid_; } + + std::string Host() const { return host_; } + std::string Protocol() const { return protocol_; } + std::string Resource() const { return resource_; } + +private: + void Split(); + bool valid_; + std::string url_; + std::string host_; + std::string resource_; + std::string protocol_; +}; \ No newline at end of file diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index 746c3fb3c6..18369ed617 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -1,16 +1,8 @@ -#include - +#include "base/functional.h" #include "base/logging.h" #include "thread/thread.h" #include "thread/prioritizedworkqueue.h" -#if defined(IOS) || defined(MACGNUSTD) -#include -namespace std { - using tr1::bind; -} -#endif - PrioritizedWorkQueue::~PrioritizedWorkQueue() { if (!done_) { ELOG("PrioritizedWorkQueue destroyed but not done!"); From 4a208872c55ae8cd77688d6ef06d50fbedc6ac21 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 1 Jun 2013 00:50:08 +0200 Subject: [PATCH 0417/1445] Android buildfixing --- Android.mk | 3 +-- base/buffer.h | 2 +- image/zim_load.h | 2 +- net/http_client.cpp | 1 - net/http_client.h | 1 + ui/view.h | 1 + 6 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Android.mk b/Android.mk index 1825b7561c..680165f278 100644 --- a/Android.mk +++ b/Android.mk @@ -62,7 +62,6 @@ LOCAL_SRC_FILES :=\ image/png_load.cpp \ ui/view.cpp \ ui/viewgroup.cpp \ - ui/drawing.cpp \ ui/ui.cpp \ ui/ui_context.cpp \ ui/screen.cpp \ @@ -71,7 +70,7 @@ LOCAL_SRC_FILES :=\ util/text/utf8.cpp LOCAL_CFLAGS := -O3 -DGL_GLEXT_PROTOTYPES -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 +LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -frtti LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip diff --git a/base/buffer.h b/base/buffer.h index 440eb5015f..ead85cb450 100644 --- a/base/buffer.h +++ b/base/buffer.h @@ -20,7 +20,7 @@ class Buffer { char *Append(size_t length) { return Append((ssize_t)length); } // These work pretty much like you'd expect. - void Append(const char *str); // str null-terminated. The null is not copied. + void Append(const char *str); // str null-terminated. The null is not copied. void Append(const std::string &str); // Various types. Useful for varz etc. Appends a string representation of the diff --git a/image/zim_load.h b/image/zim_load.h index 4e90c717c9..cc4d514269 100644 --- a/image/zim_load.h +++ b/image/zim_load.h @@ -48,4 +48,4 @@ enum { // Watch out! If the image has mipmaps, multiple values will be written // to width, height, and image, as if they were arrays, up to 12 (max texture size is 4096 which is 2^12). int LoadZIM(const char *filename, int *width, int *height, int *flags, uint8_t **image); -int LoadZIMPtr(char *zim, int datasize, int *width, int *height, int *flags, uint8_t **image); +int LoadZIMPtr(char *zim, int datasize, int *width, int *height, int *flags, uint8_t **image); \ No newline at end of file diff --git a/net/http_client.cpp b/net/http_client.cpp index 90aec31764..361d22f3f1 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -183,7 +183,6 @@ Download::~Download() { } - void Download::Do() { Url fileUrl(url_); if (!fileUrl.Valid()) { diff --git a/net/http_client.h b/net/http_client.h index 9de4e64f1a..07986551f6 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -1,6 +1,7 @@ #ifndef _NET_HTTP_HTTP_CLIENT #define _NET_HTTP_HTTP_CLIENT +#include #include "base/basictypes.h" #include "base/buffer.h" #include "thread/thread.h" diff --git a/ui/view.h b/ui/view.h index 813231eff0..658ab2bb3a 100644 --- a/ui/view.h +++ b/ui/view.h @@ -7,6 +7,7 @@ // Works very similarly to Android, there's a Measure pass and a Layout pass which you don't // really need to care about if you just use the standard containers and widgets. +#include #include #include #include From e2378dd970c2f876fcd3638c80493f3b938cfad8 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 1 Jun 2013 16:04:10 +1000 Subject: [PATCH 0418/1445] New Blackberry 10 frontend New BlackberryMain class, separated in to main, display and audio. Multiple display support (such as HDMI, AV out or Blackberry dock). Switchable display support. Starts in internal display for menus. Switches to external display for in game. Currently does not work properly for hotplugging screens so the switchable displays is disabled. --- base/BlackberryAudio.h | 83 ++++++++ base/BlackberryDisplay.cpp | 176 +++++++++++++++++ base/BlackberryMain.cpp | 392 +++++++++++++------------------------ base/BlackberryMain.h | 83 ++++++++ 4 files changed, 475 insertions(+), 259 deletions(-) create mode 100644 base/BlackberryAudio.h create mode 100644 base/BlackberryDisplay.cpp create mode 100644 base/BlackberryMain.h diff --git a/base/BlackberryAudio.h b/base/BlackberryAudio.h new file mode 100644 index 0000000000..4911be23d3 --- /dev/null +++ b/base/BlackberryAudio.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013 Sacha Refshauge + * + */ +// Blackberry implementation of the framework. +#ifndef BLACKBERRYAUDIO_H +#define BLACKBERRYAUDIO_H + +#include +#include + +#include "base/NativeApp.h" + +#define SAMPLE_SIZE 44100 +class BlackberryAudio +{ +public: + BlackberryAudio() + { + alcDevice = alcOpenDevice(NULL); + if (alContext = alcCreateContext(alcDevice, NULL)) + alcMakeContextCurrent(alContext); + alGenSources(1, &source); + alGenBuffers(1, &buffer); + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&thread_handle, &attr, &BlackberryAudio::staticThreadProc, this); + } + ~BlackberryAudio() + { + pthread_cancel(thread_handle); + alcMakeContextCurrent(NULL); + if (alContext) + { + alcDestroyContext(alContext); + alContext = NULL; + } + if (alcDevice) + { + alcCloseDevice(alcDevice); + alcDevice = NULL; + } + } + static void* staticThreadProc(void* arg) + { + return reinterpret_cast(arg)->RunAudio(); + } +private: + void* RunAudio() + { + while(true) + { + size_t frames_ready; + alGetSourcei(source, AL_SOURCE_STATE, &state); + if (state != AL_PLAYING) + frames_ready = NativeMix(stream, SAMPLE_SIZE / 2); + else + frames_ready = 0; + if (frames_ready > 0) + { + const size_t bytes_ready = frames_ready * sizeof(short) * 2; + alSourcei(source, AL_BUFFER, 0); + alBufferData(buffer, AL_FORMAT_STEREO16, stream, bytes_ready, SAMPLE_SIZE); + alSourcei(source, AL_BUFFER, buffer); + alSourcePlay(source); + // TODO: Maybe this could get behind? + usleep((1000000 * frames_ready) / SAMPLE_SIZE); + } + else + usleep(100); + } + } + ALCdevice *alcDevice; + ALCcontext *alContext; + ALenum state; + ALuint buffer; + ALuint source; + short stream[SAMPLE_SIZE]; + pthread_t thread_handle; +}; +#endif + diff --git a/base/BlackberryDisplay.cpp b/base/BlackberryDisplay.cpp new file mode 100644 index 0000000000..95712476c1 --- /dev/null +++ b/base/BlackberryDisplay.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2013 Sacha Refshauge + * + */ +// Blackberry implementation of the framework. +#include "BlackberryMain.h" + +char* BlackberryMain::displayTypeString(int type) +{ + switch (type) + { + case SCREEN_DISPLAY_TYPE_INTERNAL: + return "Internal"; break; + case SCREEN_DISPLAY_TYPE_COMPOSITE: + return "Composite"; break; + case SCREEN_DISPLAY_TYPE_DVI: + return "DVI"; break; + case SCREEN_DISPLAY_TYPE_HDMI: + return "HDMI"; break; + case SCREEN_DISPLAY_TYPE_DISPLAYPORT: + return "DisplayPort"; break; + case SCREEN_DISPLAY_TYPE_OTHER: + default: + break; + } + return "Unknown Port"; +} + +void BlackberryMain::startDisplays() { + screen_get_context_property_iv(screen_cxt, SCREEN_PROPERTY_DISPLAY_COUNT, &ndisplays); + egl_disp = (EGLDisplay*)calloc(ndisplays, sizeof(EGLDisplay)); + egl_surf = (EGLSurface*)calloc(ndisplays, sizeof(EGLSurface)); + egl_cont = (EGLContext*)calloc(ndisplays, sizeof(EGLContext)); + displays = (dispdata_t*)calloc(ndisplays, sizeof(dispdata_t)); + screen_win = (screen_window_t *)calloc(ndisplays, sizeof(screen_window_t )); + screen_dpy = (screen_display_t*)calloc(ndisplays, sizeof(screen_display_t)); + screen_get_context_property_pv(screen_cxt, SCREEN_PROPERTY_DISPLAYS, (void **)screen_dpy); + + // Common data + int usage = SCREEN_USAGE_ROTATION | SCREEN_USAGE_OPENGL_ES2; + int format = SCREEN_FORMAT_RGBX8888; + int sensitivity = SCREEN_SENSITIVITY_ALWAYS; + + // Initialise every display + emulating = false; + screen_ui = 0; + screen_emu = 0; + for (int i = 0; i < ndisplays; i++) { + screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_TYPE, &(displays[i].type)); + screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_ATTACHED, &(displays[i].attached)); + + screen_create_window(&screen_win[i], screen_cxt); + screen_set_window_property_iv(screen_win[i], SCREEN_PROPERTY_FORMAT, &format); + screen_set_window_property_iv(screen_win[i], SCREEN_PROPERTY_USAGE, &usage); + screen_set_window_property_iv(screen_win[i], SCREEN_PROPERTY_SENSITIVITY, &sensitivity); + screen_set_window_property_pv(screen_win[i], SCREEN_PROPERTY_DISPLAY, (void **)&screen_dpy[i]); + + egl_disp[i] = eglGetDisplay((EGLNativeDisplayType)i); + eglInitialize(egl_disp[i], NULL, NULL); + fprintf(stderr, "Display %i: %s, %s\n", i, displayTypeString(displays[i].type), displays[i].attached ? "Attached" : "Detached"); + if (displays[i].attached) + realiseDisplay(i); + } + screen_get_display_property_iv(screen_dpy[0], SCREEN_PROPERTY_DPI, &dpi); // Only internal display has DPI + dpi_scale = ((pixel_xres == pixel_yres) ? 300.0f : 213.6f) / dpi; + switchDisplay(screen_ui); +} + +void BlackberryMain::realiseDisplay(int idx) { + EGLConfig egl_conf; + int num_configs; + EGLint attrib_list[]= { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE}; + + const EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + const EGLint egl_surfaceAttr[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE }; + + int size[2] = { atoi(getenv("WIDTH")), atoi(getenv("HEIGHT")) }; + if (idx != 0) + screen_get_display_property_iv(screen_dpy[idx], SCREEN_PROPERTY_SIZE, size); + displays[idx].width = size[0]; + displays[idx].height = size[1]; + screen_set_window_property_iv(screen_win[idx], SCREEN_PROPERTY_BUFFER_SIZE, size); + screen_create_window_buffers(screen_win[idx], 2); // Double buffered + fprintf(stderr, "Display %i realised with %ix%i\n", idx, size[0], size[1]); + + eglChooseConfig(egl_disp[idx], attrib_list, &egl_conf, 1, &num_configs); + if (!egl_cont[idx]) + egl_cont[idx] = eglCreateContext(egl_disp[idx], egl_conf, EGL_NO_CONTEXT, attributes); + egl_surf[idx] = eglCreateWindowSurface(egl_disp[idx], egl_conf, screen_win[idx], egl_surfaceAttr); + eglSwapInterval(egl_disp[idx], 1); + // Temporarily disabled +#if 0 + if (displays[idx].type != SCREEN_DISPLAY_TYPE_INTERNAL) + { + screen_emu = idx; + if (emulating) + switchDisplay(idx); + } +#endif + displays[idx].realised = true; +} + +// Note: Only hotpluggable displays can unrealise. Internal (0) is not possible. +void BlackberryMain::unrealiseDisplay(int idx) { + killDisplay(idx, false); + screen_destroy_window_buffers(screen_win[idx]); + screen_flush_context(screen_cxt, 0); + if (displays[idx].type != SCREEN_DISPLAY_TYPE_INTERNAL) + { + screen_emu = screen_ui; + if (emulating) + switchDisplay(screen_ui); + eglMakeCurrent(egl_disp[screen_ui], egl_surf[screen_ui], egl_surf[screen_ui], egl_cont[screen_ui]); + } + displays[idx].realised = false; +} + +void BlackberryMain::switchDisplay(int idx) { + static int screen_curr = -1; + if (idx != screen_curr) { + pixel_xres = displays[idx].width; + pixel_yres = displays[idx].height; + dp_xres = (int)(pixel_xres * dpi_scale); + dp_yres = (int)(pixel_yres * dpi_scale); + if (emulating) { + PSP_CoreParameter().pixelWidth = pixel_xres; + PSP_CoreParameter().pixelHeight = pixel_yres; + PSP_CoreParameter().outputWidth = dp_xres; + PSP_CoreParameter().outputHeight = dp_yres; + } + screen_curr = idx; + eglMakeCurrent(egl_disp[idx], egl_surf[idx], egl_surf[idx], egl_cont[idx]); + } +} + +void BlackberryMain::killDisplays() { + for (int i = 0; i < ndisplays; i++) { + killDisplay(i, true); + } + free(egl_disp); + free(egl_surf); + eglReleaseThread(); + free(screen_dpy); +} + +void BlackberryMain::killDisplay(int idx, bool killContext) { + if (egl_disp[idx] != EGL_NO_DISPLAY) { + eglMakeCurrent(egl_disp[idx], EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (egl_surf[idx] != EGL_NO_SURFACE) { + eglDestroySurface(egl_disp[idx], egl_surf[idx]); + egl_surf[idx] = EGL_NO_SURFACE; + } + if (killContext && egl_cont[idx] != EGL_NO_CONTEXT) { + eglDestroyContext(egl_disp[idx], egl_cont[idx]); + egl_cont[idx] = EGL_NO_CONTEXT; + } + if (killContext) + { + eglTerminate(egl_disp[idx]); + egl_disp[idx] = EGL_NO_DISPLAY; + } + } + if (killContext && screen_win[idx] != NULL) { + screen_destroy_window(screen_win[idx]); + screen_win[idx] = NULL; + } +} + diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index f70b985dc5..4e98bd51d0 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Sacha Refshauge + * Copyright (c) 2013 Sacha Refshauge * */ // Blackberry implementation of the framework. @@ -8,41 +8,7 @@ #include #include -#include -#include - -#include -#include -#include -#include - -#include "base/timeutil.h" -#include "gfx_es2/glsl_program.h" -#include "file/zip_read.h" -#include "input/input_state.h" -#include "base/NativeApp.h" -#include "net/resolve.h" -#include "display.h" - -// Blackberry specific -#include // Blackberry Platform Services -#include // Blackberry Window Manager -#include // Invoke Service -#include // Keyboard Service -#include // Accelerometer -#include -#include // Dialog Service (Toast=BB10) -#include // Vibrate Service (BB10) - -EGLDisplay egl_disp; -EGLSurface egl_surf; - -static EGLConfig egl_conf; -static EGLContext egl_ctx; - -static screen_context_t screen_ctx; -static screen_window_t screen_win; -static screen_display_t screen_disp; +#include "BlackberryMain.h" // Simple implementations of System functions @@ -55,7 +21,6 @@ void SystemToast(const char *text) { } void ShowAd(int x, int y, bool center_x) { - // Ads on Blackberry? } void ShowKeyboard() { @@ -63,7 +28,7 @@ void ShowKeyboard() { } void Vibrate(int length_ms) { - vibration_request(VIBRATION_INTENSITY_LOW, 500 /* intensity (1-100), duration (ms) */); + vibration_request(VIBRATION_INTENSITY_LOW, 200 /* intensity (1-100), duration (ms) */); } void LaunchBrowser(const char *url) @@ -124,144 +89,101 @@ void SimulateGamepad(InputState *input) { input->pad_lstick_x=1; } -// Video -int init_GLES2(screen_context_t ctx) { - int usage = SCREEN_USAGE_ROTATION | SCREEN_USAGE_OPENGL_ES2; - int format = SCREEN_FORMAT_RGBX8888; - int num_configs; - - EGLint attrib_list[]= { - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_DEPTH_SIZE, 24, - EGL_STENCIL_SIZE, 8, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE}; - - const EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - const EGLint egl_surfaceAttr[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE }; - - screen_ctx = ctx; - screen_create_window(&screen_win, screen_ctx); - screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &format); - screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage); - screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp); - - pixel_xres = atoi(getenv("WIDTH")); pixel_yres = atoi(getenv("HEIGHT")); - int size[2] = { pixel_xres, pixel_yres }; - screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size); - - screen_create_window_buffers(screen_win, 2); // Double buffered - egl_disp = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(egl_disp, NULL, NULL); - - eglChooseConfig(egl_disp, attrib_list, &egl_conf, 1, &num_configs); - egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, attributes); - - egl_surf = eglCreateWindowSurface(egl_disp, egl_conf, screen_win, egl_surfaceAttr); - - eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx); - eglSwapInterval(egl_disp, 1); - - return 0; -} - -void kill_GLES2() { - if (egl_disp != EGL_NO_DISPLAY) { - eglMakeCurrent(egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (egl_surf != EGL_NO_SURFACE) { - eglDestroySurface(egl_disp, egl_surf); - egl_surf = EGL_NO_SURFACE; - } - if (egl_ctx != EGL_NO_CONTEXT) { - eglDestroyContext(egl_disp, egl_ctx); - egl_ctx = EGL_NO_CONTEXT; - } - if (screen_win != NULL) { - screen_destroy_window(screen_win); - screen_win = NULL; - } - eglTerminate(egl_disp); - egl_disp = EGL_NO_DISPLAY; - } - eglReleaseThread(); -} - -// Audio -#define SAMPLE_SIZE 44100 -class BlackberryAudio +void BlackberryMain::handleInput(screen_event_t screen_event) { -public: - BlackberryAudio() - { - alcDevice = alcOpenDevice(NULL); - if (alContext = alcCreateContext(alcDevice, NULL)) - alcMakeContextCurrent(alContext); - alGenSources(1, &source); - alGenBuffers(1, &buffer); - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&thread_handle, &attr, &BlackberryAudio::staticThreadProc, this); - } - ~BlackberryAudio() - { - pthread_cancel(thread_handle); - alcMakeContextCurrent(NULL); - if (alContext) - { - alcDestroyContext(alContext); - alContext = NULL; - } - if (alcDevice) - { - alcCloseDevice(alcDevice); - alcDevice = NULL; - } - } - static void* staticThreadProc(void* arg) - { - return reinterpret_cast(arg)->RunAudio(); - } -private: - void* RunAudio() - { - while(true) - { - size_t frames_ready; - alGetSourcei(source, AL_SOURCE_STATE, &state); - if (state != AL_PLAYING) - frames_ready = NativeMix(stream, SAMPLE_SIZE / 2); - else - frames_ready = 0; - if (frames_ready > 0) - { - const size_t bytes_ready = frames_ready * sizeof(short) * 2; - alSourcei(source, AL_BUFFER, 0); - alBufferData(buffer, AL_FORMAT_STEREO16, stream, bytes_ready, SAMPLE_SIZE); - alSourcei(source, AL_BUFFER, buffer); - alSourcePlay(source); - // TODO: Maybe this could get behind? - usleep((1000000 * frames_ready) / SAMPLE_SIZE); - } - else - usleep(100); - } - } - ALCdevice *alcDevice; - ALCcontext *alContext; - ALenum state; - ALuint buffer; - ALuint source; - short stream[SAMPLE_SIZE]; - pthread_t thread_handle; -}; + int val, buttons, pointerId; + int pair[2]; + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &val); + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pair); + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId); -// Entry Point -int main(int argc, char *argv[]) { - static screen_context_t screen_cxt; + input_state.mouse_valid = true; + switch(val) + { + // Touchscreen + case SCREEN_EVENT_MTOUCH_TOUCH: + case SCREEN_EVENT_MTOUCH_RELEASE: // Up, down + input_state.pointer_down[pointerId] = (val == SCREEN_EVENT_MTOUCH_TOUCH); + case SCREEN_EVENT_MTOUCH_MOVE: + input_state.pointer_x[pointerId] = pair[0] * dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * dpi_scale; + break; + // Mouse, Simulator + case SCREEN_EVENT_POINTER: + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, + &buttons); + if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down + input_state.pointer_x[pointerId] = pair[0] * dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * dpi_scale; + input_state.pointer_down[pointerId] = true; + } else if (input_state.pointer_down[pointerId]) { // Up + input_state.pointer_x[pointerId] = pair[0] * dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * dpi_scale; + input_state.pointer_down[pointerId] = false; + } + break; + // Keyboard + case SCREEN_EVENT_KEYBOARD: + int flags, value; + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags); + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value); + for (int b = 0; b < 14; b++) { + if (value == buttonMappings[b] & 0xFF) { + if (flags & KEY_DOWN) + pad_buttons |= (1<> 3; + else + controller_buttons = (buttons & (SCREEN_A_GAME_BUTTON | SCREEN_B_GAME_BUTTON)) | + (buttons & (SCREEN_X_GAME_BUTTON | SCREEN_Y_GAME_BUTTON)) >> 1; + controller_buttons |= (buttons & (SCREEN_MENU1_GAME_BUTTON | SCREEN_MENU2_GAME_BUTTON)) | + (buttons & SCREEN_L1_GAME_BUTTON) >> 6 | (buttons & SCREEN_R1_GAME_BUTTON) >> 8 | + (buttons & DIR_KEYS) >> 8 | + (buttons & DIR_KEYS) >> 2; + break; + case SCREEN_EVENT_DISPLAY: + screen_display_t new_dpy = NULL; + screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DISPLAY, (void **)&new_dpy); + static int hits = 0; + hits++; + for (int i = 0; i < ndisplays; i++) { + if (new_dpy != screen_dpy[i]) + continue; + int active = 0; + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ATTACHED, &active); + if (active) { + int size[2]; + screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_SIZE, size); + if (size[0] == 0 || size[1] == 0) + active = 0; + } + if (active && !displays[i].attached) + realiseDisplay(i); + else if (!active && displays[i].attached && displays[i].realised) + unrealiseDisplay(i); + displays[i].attached = active; + } + break; + } +} + +void BlackberryMain::startMain(int argc, char *argv[]) { // Receive events from window manager screen_create_context(&screen_cxt, 0); // Initialise Blackberry Platform Services @@ -271,23 +193,19 @@ int main(int argc, char *argv[]) { sensor_request_events(SENSOR_TYPE_ACCELEROMETER); net::Init(); - init_GLES2(screen_cxt); - // Z10: 1280x768, 4.2", 356DPI, 0.6f scale - // Q10: 720x720, 3.1", 328DPI, 0.65f*1.4f=0.91f scale - int dpi; - screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_DPI, &dpi); - float dpi_scale = 213.6f / dpi; - if (pixel_xres == pixel_yres) dpi_scale *= 1.4; - dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); - + startDisplays(); + //eglMakeCurrent(egl_disp[0], egl_surf[0], egl_surf[0], egl_ctx[0]); NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "data/", "BADCOFFEE"); NativeInitGraphics(); screen_request_events(screen_cxt); navigator_request_events(0); dialog_request_events(0); vibration_request_events(0); - static int pad_buttons = 0, controller_buttons = 0; - BlackberryAudio* audio = new BlackberryAudio(); + audio = new BlackberryAudio(); + runMain(); +} + +void BlackberryMain::runMain() { bool running = true; while (running) { input_state.mouse_valid = false; @@ -301,76 +219,7 @@ int main(int argc, char *argv[]) { break; // Ran out of events int domain = bps_event_get_domain(event); if (domain == screen_get_domain()) { - int screen_val, buttons, pointerId; - int pair[2]; - - screen_event_t screen_event = screen_event_get_event(event); - - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val); - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pair); - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId); - - input_state.mouse_valid = true; - switch(screen_val) - { - // Touchscreen - case SCREEN_EVENT_MTOUCH_TOUCH: - case SCREEN_EVENT_MTOUCH_RELEASE: // Up, down - input_state.pointer_down[pointerId] = (screen_val == SCREEN_EVENT_MTOUCH_TOUCH); - case SCREEN_EVENT_MTOUCH_MOVE: - input_state.pointer_x[pointerId] = pair[0] * dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * dpi_scale; - break; - // Mouse, Simulator - case SCREEN_EVENT_POINTER: - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, - &buttons); - if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down - input_state.pointer_x[pointerId] = pair[0] * dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * dpi_scale; - input_state.pointer_down[pointerId] = true; - } else if (input_state.pointer_down[pointerId]) { // Up - input_state.pointer_x[pointerId] = pair[0] * dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * dpi_scale; - input_state.pointer_down[pointerId] = false; - } - break; - // Keyboard - case SCREEN_EVENT_KEYBOARD: - int flags, value; - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags); - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value); - for (int b = 0; b < 14; b++) { - if (value == buttonMappings[b] & 0xFF) { - if (flags & KEY_DOWN) - pad_buttons |= (1<> 3; - else - controller_buttons = (buttons & (SCREEN_A_GAME_BUTTON | SCREEN_B_GAME_BUTTON)) | - (buttons & (SCREEN_X_GAME_BUTTON | SCREEN_Y_GAME_BUTTON)) >> 1; - controller_buttons |= (buttons & (SCREEN_MENU1_GAME_BUTTON | SCREEN_MENU2_GAME_BUTTON)) | - (buttons & SCREEN_L1_GAME_BUTTON) >> 6 | (buttons & SCREEN_R1_GAME_BUTTON) >> 8 | - (buttons & (SCREEN_DPAD_UP_GAME_BUTTON | SCREEN_DPAD_DOWN_GAME_BUTTON | SCREEN_DPAD_LEFT_GAME_BUTTON | SCREEN_DPAD_RIGHT_GAME_BUTTON)) >> 8 | - (buttons & (SCREEN_DPAD_UP_GAME_BUTTON | SCREEN_DPAD_DOWN_GAME_BUTTON | SCREEN_DPAD_LEFT_GAME_BUTTON | SCREEN_DPAD_RIGHT_GAME_BUTTON)) >> 2; - break; - } + handleInput(screen_event_get_event(event)); } else if (domain == navigator_get_domain()) { switch(bps_event_get_code(event)) { @@ -404,21 +253,46 @@ int main(int argc, char *argv[]) { UpdateInputState(&input_state); NativeUpdate(input_state); EndInputState(&input_state); + // Work in Progress + // Currently: Render to HDMI port (eg. 1080p) when in game. Render to device when in menu. + // Right now, hotswapping displays is not working. Temporarily disable. + // Idea: Render to all displays. Controls go to internal, game goes to external(s). +#if 0 + if (globalUIState == UISTATE_INGAME && !emulating) + { + emulating = true; + switchDisplay(screen_emu); + } else if (globalUIState != UISTATE_INGAME && emulating) { + emulating = false; + switchDisplay(screen_ui); + } +#endif NativeRender(); time_update(); - // On Blackberry, this handles VSync for us - eglSwapBuffers(egl_disp, egl_surf); + // This handles VSync + if (false && emulating) // Temporarily disable + eglSwapBuffers(egl_disp[screen_emu], egl_surf[screen_emu]); + else + eglSwapBuffers(egl_disp[screen_ui], egl_surf[screen_ui]); } + endMain(); +} +void BlackberryMain::endMain() { screen_stop_events(screen_cxt); bps_shutdown(); - NativeShutdownGraphics(); delete audio; NativeShutdown(); - kill_GLES2(); + killDisplays(); net::Shutdown(); screen_destroy_context(screen_cxt); +} + +// Entry Point +int main(int argc, char *argv[]) { + BlackberryMain emu; + emu.startMain(argc, argv); exit(0); return 0; } diff --git a/base/BlackberryMain.h b/base/BlackberryMain.h new file mode 100644 index 0000000000..de320475b0 --- /dev/null +++ b/base/BlackberryMain.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013 Sacha Refshauge + * + */ +// Blackberry implementation of the framework. +#ifndef BLACKBERRYMAIN_H +#define BLACKBERRYMAIN_H + +// Blackberry specific +#include // Blackberry Platform Services +#include // Blackberry Window Manager +#include // Invoke Service +#include // Keyboard Service +#include // Accelerometer +#include +#include // Dialog Service (Toast=BB10) +#include // Vibrate Service (BB10) + +// Display +#include +#include +#include +#include +#include "Core/System.h" + +// Native +#include "base/timeutil.h" +#include "gfx_es2/glsl_program.h" +#include "file/zip_read.h" +#include "base/NativeApp.h" +#include "input/input_state.h" +#include "net/resolve.h" +#include "display.h" + +#include "BlackberryAudio.h" + +struct dispdata_t { + int attached; + int type; + bool realised; + int width, height; +}; + +class BlackberryMain +{ +public: + BlackberryMain() { } + ~BlackberryMain() { } + void startMain(int argc, char *argv[]); + +private: + void runMain(); + void endMain(); + + void handleInput(screen_event_t screen_event); + + char* displayTypeString(int type); + void startDisplays(); + void* startDisplay(int idx); + void realiseDisplay(int idx); + void unrealiseDisplay(int idx); + void switchDisplay(int idx); + void killDisplays(); + void killDisplay(int idx, bool killContext); + + BlackberryAudio* audio; + dispdata_t *displays; + int dpi; + float dpi_scale; + int ndisplays; + int screen_ui, screen_emu; + bool emulating; + int pad_buttons, controller_buttons; + EGLDisplay* egl_disp; + EGLSurface* egl_surf; + EGLContext* egl_cont; + screen_context_t screen_cxt; + screen_display_t *screen_dpy; + screen_window_t *screen_win; +}; + +#endif + From 4267d9903c7eb45769c81c48713bc15a4c7039e4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 1 Jun 2013 18:59:03 +0200 Subject: [PATCH 0419/1445] More networking and UI stuff --- ext/vjson/json.h | 3 ++- gfx_es2/draw_buffer.cpp | 11 +++++++++++ net/http_client.cpp | 2 +- net/http_client.h | 7 ++++++- ui/view.cpp | 18 ++++++++++++++---- ui/view.h | 37 ++++++++++++++++++------------------- ui/viewgroup.h | 10 +++++++--- 7 files changed, 59 insertions(+), 29 deletions(-) diff --git a/ext/vjson/json.h b/ext/vjson/json.h index f798aec0d8..57a8063586 100644 --- a/ext/vjson/json.h +++ b/ext/vjson/json.h @@ -82,7 +82,8 @@ public: } ~JsonReader() { - free(buffer_); + if (buffer_) + free(buffer_); } void parse() { diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 27115863fc..bbadb37731 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -370,6 +370,17 @@ void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) { // U+30A0–U+30FF Katakana void DrawBuffer::DrawTextRect(int font, const char *text, float x, float y, float w, float h, Color color, int align) { + if (align & ALIGN_HCENTER) { + x += w / 2; + } else if (align & ALIGN_RIGHT) { + x += w; + } + if (align & ALIGN_VCENTER) { + y += h / 2; + } else if (align & ALIGN_BOTTOM) { + y += h; + } + DrawText(font, text, x, y, color, align); } diff --git a/net/http_client.cpp b/net/http_client.cpp index 361d22f3f1..9860a89420 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -201,7 +201,7 @@ void Download::Do() { if (client.GET(fileUrl.Resource().c_str(), &buffer_)) { progress_ = 1.0f; ILOG("Completed downloading %s to %s", url_.c_str(), outfile_.c_str()); - if (!buffer_.FlushToFile(outfile_.c_str())) { + if (!outfile_.empty() && !buffer_.FlushToFile(outfile_.c_str())) { ELOG("Failed writing download to %s", outfile_.c_str()); } } else { diff --git a/net/http_client.h b/net/http_client.h index 07986551f6..8035d586e7 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -74,13 +74,18 @@ public: Download(const std::string &url, const std::string &outfile); ~Download(); - // Returns 1.0 when done. That one value can be compared exactly. + // Returns 1.0 when done. That one value can be compared exactly - or just use Done(). float Progress() const { return progress_; } + bool Done() const { return progress_ == 1.0f; } + bool Failed() const { return failed_; } std::string url() const { return url_; } std::string outfile() const { return outfile_; } + // If not downloading to a file, access this to get the result. + Buffer &buffer() { return buffer_; } + private: void Do(); // Actually does the download. Runs on thread. diff --git a/ui/view.cpp b/ui/view.cpp index 7cff1d5d12..9de1542e21 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -49,14 +49,14 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure } } -void Event::Add(std::function func) { +void Event::Add(std::function func) { HandlerRegistration reg; reg.func = func; handlers_.push_back(reg); } // Call this from input thread or whatever, it doesn't matter -void Event::Trigger(const EventParams &e) { +void Event::Trigger(EventParams &e) { lock_guard guard(mutex_); if (!triggered_) { triggered_ = true; @@ -96,6 +96,12 @@ void Clickable::Click() { }; void Clickable::Touch(const TouchInput &input) { + if (!enabled_) { + dragging_ = false; + down_ = false; + return; + } + if (input.flags & TOUCH_DOWN) { if (bounds_.Contains(input.x, input.y)) { if (IsFocusMovementEnabled()) @@ -128,6 +134,7 @@ void Clickable::Update(const InputState &input_state) { } else if (input_state.pad_buttons_up & PAD_BUTTON_A) { if (down_) { UI::EventParams e; + e.v = this; OnClick.Trigger(e); } down_ = false; @@ -210,12 +217,15 @@ void ImageView::Draw(UIContext &dc) { } void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + dc.Draw()->SetFontScale(textScale_, textScale_); dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); + dc.Draw()->SetFontScale(1.0f, 1.0f); } void TextView::Draw(UIContext &dc) { - // TODO: involve sizemode - dc.Draw()->DrawTextRect(dc.theme->uiFont, text_.c_str(), bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF); + dc.Draw()->SetFontScale(textScale_, textScale_); + dc.Draw()->DrawTextRect(dc.theme->uiFont, text_.c_str(), bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF, textAlign_); + dc.Draw()->SetFontScale(1.0f, 1.0f); } void TriggerButton::Touch(const TouchInput &input) { diff --git a/ui/view.h b/ui/view.h index 658ab2bb3a..8fb3539a00 100644 --- a/ui/view.h +++ b/ui/view.h @@ -9,17 +9,9 @@ #include #include -#include #include -// fix -#if defined(IOS) || defined(MACGNUSTD) -#include -namespace std { - using tr1::bind; -} -#endif - +#include "base/functional.h" #include "base/mutex.h" #include "base/basictypes.h" #include "base/scoped_ptr.h" @@ -165,17 +157,17 @@ struct EventParams { }; struct HandlerRegistration { - std::function func; + std::function func; }; class Event { public: Event() : triggered_(false) {} - void Add(std::function func); + void Add(std::function func); // Call this from input thread or whatever, it doesn't matter - void Trigger(const EventParams &e); + void Trigger(EventParams &e); // Call this from UI thread void Update(); @@ -215,7 +207,7 @@ View *GetFocusedView(); class View { public: - View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams) { + View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), enabled_(true) { if (!layoutParams) layoutParams_.reset(new LayoutParams()); } @@ -262,10 +254,15 @@ public: return GetFocusedView() == this; } + void SetEnabled(bool enabled) { enabled_ = enabled; } + bool Enabled() const { return enabled_; } + protected: // Inputs to layout scoped_ptr layoutParams_; + bool enabled_; + // Results of measure pass. Set these in Measure. float measuredWidth_; float measuredHeight_; @@ -295,7 +292,7 @@ public: class Clickable : public View { public: Clickable(LayoutParams *layoutParams) - : View(layoutParams), downCountDown_(0), down_(false), dragging_(false) {} + : View(layoutParams), downCountDown_(0), dragging_(false), down_(false) {} virtual void Touch(const TouchInput &input); virtual void Update(const InputState &input_state); @@ -413,12 +410,12 @@ class CheckBox : public ClickableItem { public: CheckBox(bool *toggle, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), text_(text), smallText_(smallText) { - OnClick.Add(std::bind(&CheckBox::OnClicked, this, std::placeholders::_1)); + OnClick.Add(std::bind(&CheckBox::OnClicked, this, p::_1)); } virtual void Draw(UIContext &dc); - EventReturn OnClicked(const EventParams &e) { + EventReturn OnClicked(EventParams &e) { if (toggle_) *toggle_ = !(*toggle_); return EVENT_DONE; @@ -445,15 +442,17 @@ public: class TextView : public InertView { public: - TextView(int font, const std::string &text, LayoutParams *layoutParams = 0) - : InertView(layoutParams), font_(font), text_(text) {} + TextView(int font, const std::string &text, int textAlign, float textScale, LayoutParams *layoutParams = 0) + : InertView(layoutParams), font_(font), text_(text), textScale_(textScale), textAlign_(textAlign) {} virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); private: - std::string text_; int font_; + std::string text_; + float textScale_; + int textAlign_; }; enum ImageSizeMode { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index a3fe54470e..b9bb0038bd 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -1,5 +1,6 @@ #pragma once +#include "base/logging.h" #include "ui/view.h" #include "input/gesture_detector.h" @@ -33,7 +34,8 @@ public: virtual float GetContentHeight() const { return 0.0f; } // Takes ownership! DO NOT add a view to multiple parents! - void Add(View *view) { views_.push_back(view); } + template + T *Add(T *view) { views_.push_back(view); return view; } virtual bool SetFocus(); virtual bool SubviewFocused(View *view); @@ -83,8 +85,10 @@ class LinearLayoutParams : public LayoutParams { public: LinearLayoutParams() : LayoutParams(), weight(0.0f), gravity(G_TOPLEFT), hasMargins_(false) {} - explicit LinearLayoutParams(float wgt) - : LayoutParams(), weight(wgt), gravity(G_TOPLEFT), hasMargins_(false) {} + explicit LinearLayoutParams(float wgt, Gravity grav = G_TOPLEFT) + : LayoutParams(), weight(wgt), gravity(grav), hasMargins_(false) {} + LinearLayoutParams(float wgt, const Margins &mgn) + : LayoutParams(), weight(wgt), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} LinearLayoutParams(Size w, Size h, float wgt = 0.0f, Gravity grav = G_TOPLEFT) : LayoutParams(w, h), weight(wgt), gravity(grav), hasMargins_(false) {} LinearLayoutParams(Size w, Size h, float wgt, Gravity grav, const Margins &mgn) From 58c40dabb103eb38fe5c16ee70722be3185b7afa Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 2 Jun 2013 13:06:40 +1000 Subject: [PATCH 0420/1445] Fix C++11 usage in native with platform-specific hacks. --- base/functional.h | 43 ++++++++++++++++++++++++++++++++++++------- net/http_client.cpp | 7 +++---- net/http_client.h | 5 +++-- thread/threadpool.h | 40 ++-------------------------------------- ui/view.cpp | 2 +- ui/view.h | 8 ++++---- 6 files changed, 49 insertions(+), 56 deletions(-) diff --git a/base/functional.h b/base/functional.h index 46c516f941..05e7d15ae2 100644 --- a/base/functional.h +++ b/base/functional.h @@ -1,24 +1,53 @@ // This file simply includes and applies any necessary compatibility fixes for // strange platforms like iOS. -// Use p as the namespace for placeholders. +// Use placeholder as the namespace for placeholders. #pragma once #include +#ifdef __SYMBIAN32__ +#include +#include +#include +using namespace boost; +#else +#include +using namespace std; +#endif +#include -#if defined(IOS) || defined(MACGNUSTD) +#if defined(__SYMBIAN32__) || defined(IOS) || defined(MACGNUSTD) +#ifndef __SYMBIAN32__ #include +#include +#endif namespace std { - using tr1::bind; +#ifndef __SYMBIAN32__ + using tr1::bind; + using tr1::function; + using tr1::shared_ptr; +#endif + + template + inline shared_ptr make_shared() + { + return shared_ptr(new T()); + } + + template + inline shared_ptr make_shared(Arg1& arg1) + { + return shared_ptr(new T(arg1)); + } } #endif #ifdef __SYMBIAN32__ -#define p +#define placeholder #elif defined(IOS) -#include -namespace p = std::tr1::placeholders; +namespace placeholder = std::tr1::placeholders; #else -namespace p = std::placeholders; +namespace placeholder = std::placeholders; #endif + diff --git a/net/http_client.cpp b/net/http_client.cpp index 9860a89420..7e9128c056 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -19,7 +19,6 @@ #include "base/stringutil.h" #include "net/resolve.h" #include "net/url.h" -#include "base/functional.h" // #include "strings/strutil.h" @@ -175,7 +174,7 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) Download::Download(const std::string &url, const std::string &outfile) : url_(url), outfile_(outfile), progress_(0.0f), failed_(false) { - std::thread th(std::bind(&Download::Do, this)); + std::thread th(bind(&Download::Do, this)); th.detach(); } @@ -211,8 +210,8 @@ void Download::Do() { net::Shutdown(); } -std::shared_ptr Downloader::StartDownload(const std::string &url, const std::string &outfile) { - std::shared_ptr dl(new Download(url, outfile)); +shared_ptr Downloader::StartDownload(const std::string &url, const std::string &outfile) { + shared_ptr dl(new Download(url, outfile)); downloads_.push_back(dl); return dl; } diff --git a/net/http_client.h b/net/http_client.h index 8035d586e7..6b56a846fc 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -5,6 +5,7 @@ #include "base/basictypes.h" #include "base/buffer.h" #include "thread/thread.h" +#include "base/functional.h" #ifdef _WIN32 #include @@ -98,13 +99,13 @@ private: class Downloader { public: - std::shared_ptr StartDownload(const std::string &url, const std::string &outfile); + shared_ptr StartDownload(const std::string &url, const std::string &outfile); // Drops finished downloads from the list. void Update(); private: - std::vector> downloads_; + std::vector> downloads_; }; diff --git a/thread/threadpool.h b/thread/threadpool.h index d7d427cb49..c4bff05f06 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -2,44 +2,7 @@ #include "thread.h" #include "base/mutex.h" - -#include -#ifdef __SYMBIAN32__ -#include -#include -#include -using namespace boost; -#else -#include -using namespace std; -#endif -#include - -#if defined(__SYMBIAN32__) || defined(IOS) || defined(MACGNUSTD) -#ifndef __SYMBIAN32__ -#include -#include -#endif -namespace std { -#ifndef __SYMBIAN32__ - using tr1::bind; - using tr1::function; - using tr1::shared_ptr; -#endif - - template - inline shared_ptr make_shared() - { - return shared_ptr(new T()); - } - - template - inline shared_ptr make_shared(Arg1& arg1) - { - return shared_ptr(new T(arg1)); - } -} -#endif +#include "base/functional.h" // This is the simplest possible worker implementation I can think of // but entirely sufficient for the given purpose. @@ -90,3 +53,4 @@ private: ThreadPool(const ThreadPool& other); // prevent copies void operator =(const WorkerThread &other); }; + diff --git a/ui/view.cpp b/ui/view.cpp index 9de1542e21..db6f6c0fc4 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -49,7 +49,7 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure } } -void Event::Add(std::function func) { +void Event::Add(function func) { HandlerRegistration reg; reg.func = func; handlers_.push_back(reg); diff --git a/ui/view.h b/ui/view.h index 8fb3539a00..3ae7a30495 100644 --- a/ui/view.h +++ b/ui/view.h @@ -157,14 +157,14 @@ struct EventParams { }; struct HandlerRegistration { - std::function func; + function func; }; class Event { public: Event() : triggered_(false) {} - void Add(std::function func); + void Add(function func); // Call this from input thread or whatever, it doesn't matter void Trigger(EventParams &e); @@ -410,7 +410,7 @@ class CheckBox : public ClickableItem { public: CheckBox(bool *toggle, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), text_(text), smallText_(smallText) { - OnClick.Add(std::bind(&CheckBox::OnClicked, this, p::_1)); + OnClick.Add(bind(&CheckBox::OnClicked, this, placeholder::_1)); } virtual void Draw(UIContext &dc); @@ -501,4 +501,4 @@ private: void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured); -} // namespace \ No newline at end of file +} // namespace From 396a232b78e5a66bca53765d5879f4b822575bea Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 2 Jun 2013 10:36:05 +0200 Subject: [PATCH 0421/1445] Increase the size of some char arrays that hold paths. --- file/zip_read.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index de669a1f52..21b45c193d 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -164,7 +164,7 @@ bool ZipAssetReader::GetFileInfo(const char *path, FileInfo *info) { #endif uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { - char new_path[256] = {0}; + char new_path[1024] = {0}; // Check if it already contains the path if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { } @@ -177,7 +177,7 @@ uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { bool DirectoryAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) { - char new_path[256] = {0}; + char new_path[1024] = {0}; // Check if it already contains the path if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { } @@ -202,7 +202,7 @@ bool DirectoryAssetReader::GetFileListing(const char *path, std::vector strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { } From 476021d5a46807a49f1d0dc25588fbe8e82507e5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 2 Jun 2013 13:43:48 +0200 Subject: [PATCH 0422/1445] Fix namespace issues in base/functional.h --- base/functional.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/base/functional.h b/base/functional.h index 05e7d15ae2..3cab9d8620 100644 --- a/base/functional.h +++ b/base/functional.h @@ -1,7 +1,7 @@ // This file simply includes and applies any necessary compatibility fixes for // strange platforms like iOS. -// Use placeholder as the namespace for placeholders. +// Use p or placeholder as the namespace for placeholders. #pragma once @@ -10,10 +10,10 @@ #include #include #include -using namespace boost; +using boost::shared_ptr; #else #include -using namespace std; +using std::shared_ptr; #endif #include @@ -40,14 +40,21 @@ namespace std { { return shared_ptr(new T(arg1)); } -} + +#else +using std::bind; +using std::function; +using std::shared_ptr; #endif #ifdef __SYMBIAN32__ #define placeholder +#define p #elif defined(IOS) namespace placeholder = std::tr1::placeholders; +namespace p = std::tr1::placeholders; #else namespace placeholder = std::placeholders; +namespace p = std::placeholders; #endif From 8206163dae8b1000b90272bf84a6107ef3ea1311 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 2 Jun 2013 21:45:35 +1000 Subject: [PATCH 0423/1445] Fix up spacing/tabs in mutex.h --- base/mutex.h | 152 ++++++++++++++++++++++++++------------------------- 1 file changed, 77 insertions(+), 75 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index 142c378b6e..8e70009dc0 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -26,68 +26,70 @@ class recursive_mutex { #ifdef _WIN32 - typedef CRITICAL_SECTION mutexType; + typedef CRITICAL_SECTION mutexType; #else - typedef pthread_mutex_t mutexType; + typedef pthread_mutex_t mutexType; #endif public: - recursive_mutex() { + recursive_mutex() { #ifdef _WIN32 - InitializeCriticalSection(&mut_); + InitializeCriticalSection(&mut_); #else // Critical sections are recursive so let's make these recursive too. pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&mut_, &attr); + pthread_mutex_init(&mut_, &attr); #endif - } - ~recursive_mutex() { + } + ~recursive_mutex() { #ifdef _WIN32 - DeleteCriticalSection(&mut_); + DeleteCriticalSection(&mut_); #else - pthread_mutex_destroy(&mut_); + pthread_mutex_destroy(&mut_); #endif - } + } - bool trylock() { + bool trylock() { #ifdef _WIN32 - return TryEnterCriticalSection(&mut_) == TRUE; + return TryEnterCriticalSection(&mut_) == TRUE; #else - return pthread_mutex_trylock(&mut_) != EBUSY; + return pthread_mutex_trylock(&mut_) != EBUSY; #endif - } - void lock() { -#ifdef _WIN32 - EnterCriticalSection(&mut_); -#else - pthread_mutex_lock(&mut_); -#endif - } - void unlock() { -#ifdef _WIN32 - LeaveCriticalSection(&mut_); -#else - pthread_mutex_unlock(&mut_); -#endif - } + } - mutexType &native_handle() { - return mut_; - } + void lock() { +#ifdef _WIN32 + EnterCriticalSection(&mut_); +#else + pthread_mutex_lock(&mut_); +#endif + } + + void unlock() { +#ifdef _WIN32 + LeaveCriticalSection(&mut_); +#else + pthread_mutex_unlock(&mut_); +#endif + } + + mutexType &native_handle() { + return mut_; + } private: - mutexType mut_; - recursive_mutex(const recursive_mutex &other); + mutexType mut_; + recursive_mutex(const recursive_mutex &other); }; class lock_guard { public: - lock_guard(recursive_mutex &mtx) : mtx_(mtx) {mtx_.lock();} - ~lock_guard() {mtx_.unlock();} + lock_guard(recursive_mutex &mtx) : mtx_(mtx) {mtx_.lock();} + ~lock_guard() {mtx_.unlock();} private: - recursive_mutex &mtx_; + recursive_mutex &mtx_; }; @@ -98,77 +100,77 @@ public: #ifdef _WIN32 #else #endif - event() { + event() { #ifdef _WIN32 - event_ = CreateEvent(0, FALSE, FALSE, 0); + event_ = CreateEvent(0, FALSE, FALSE, 0); #else - pthread_cond_init(&event_, NULL); + pthread_cond_init(&event_, NULL); #endif - } - ~event() { + } + ~event() { #ifdef _WIN32 - CloseHandle(event_); + CloseHandle(event_); #else - pthread_cond_destroy(&event_); + pthread_cond_destroy(&event_); #endif - } + } - void notify_one() { + void notify_one() { #ifdef _WIN32 - SetEvent(event_); + SetEvent(event_); #else - pthread_cond_signal(&event_); + pthread_cond_signal(&event_); #endif - } + } - // notify_all is not really possible to implement with win32 events? + // notify_all is not really possible to implement with win32 events? - void wait(recursive_mutex &mtx) { - // broken + void wait(recursive_mutex &mtx) { + // broken #ifdef _WIN32 // This has to be horribly racy. - mtx.lock(); - WaitForSingleObject(event_, INFINITE); - ResetEvent(event_); // necessary? - mtx.unlock(); + mtx.lock(); + WaitForSingleObject(event_, INFINITE); + ResetEvent(event_); // necessary? + mtx.unlock(); #else - pthread_mutex_lock(&mtx.native_handle()); - pthread_cond_wait(&event_, &mtx.native_handle()); - pthread_mutex_unlock(&mtx.native_handle()); + pthread_mutex_lock(&mtx.native_handle()); + pthread_cond_wait(&event_, &mtx.native_handle()); + pthread_mutex_unlock(&mtx.native_handle()); #endif - } + } - void wait_for(recursive_mutex &mtx, int milliseconds) { + void wait_for(recursive_mutex &mtx, int milliseconds) { #ifdef _WIN32 - //mtx.unlock(); - WaitForSingleObject(event_, milliseconds); - ResetEvent(event_); // necessary? - // mtx.lock(); + //mtx.unlock(); + WaitForSingleObject(event_, milliseconds); + ResetEvent(event_); // necessary? + // mtx.lock(); #else - timespec timeout; + timespec timeout; timeval tv; gettimeofday(&tv, NULL); timeout.tv_sec = tv.tv_sec; timeout.tv_nsec = tv.tv_usec * 1000; timeout.tv_sec += milliseconds / 1000; - timeout.tv_nsec += milliseconds * 1000000; - pthread_mutex_lock(&mtx.native_handle()); - pthread_cond_timedwait(&event_, &mtx.native_handle(), &timeout); - pthread_mutex_unlock(&mtx.native_handle()); + timeout.tv_nsec += milliseconds * 1000000; + pthread_mutex_lock(&mtx.native_handle()); + pthread_cond_timedwait(&event_, &mtx.native_handle(), &timeout); + pthread_mutex_unlock(&mtx.native_handle()); #endif - } + } - void reset() { + void reset() { #ifdef _WIN32 - ResetEvent(event_); + ResetEvent(event_); #endif - } + } private: #ifdef _WIN32 - HANDLE event_; + HANDLE event_; #else - pthread_cond_t event_; + pthread_cond_t event_; #endif }; From 0ef45bd23d48769674fe734f90b96bee82893fe1 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 2 Jun 2013 22:25:57 +1000 Subject: [PATCH 0424/1445] Move C++11 functions to std namespace. --- base/functional.h | 16 ++++++---------- net/http_client.cpp | 2 +- thread/threadpool.cpp | 8 ++++---- thread/threadpool.h | 6 +++--- ui/view.cpp | 2 +- ui/view.h | 6 +++--- 6 files changed, 18 insertions(+), 22 deletions(-) diff --git a/base/functional.h b/base/functional.h index 3cab9d8620..1fdae0bb9e 100644 --- a/base/functional.h +++ b/base/functional.h @@ -10,7 +10,6 @@ #include #include #include -using boost::shared_ptr; #else #include using std::shared_ptr; @@ -23,7 +22,11 @@ using std::shared_ptr; #include #endif namespace std { -#ifndef __SYMBIAN32__ +#ifdef __SYMBIAN32__ + using boost::bind; + using boost::function; + using boost::shared_ptr; +#else using tr1::bind; using tr1::function; using tr1::shared_ptr; @@ -40,21 +43,14 @@ namespace std { { return shared_ptr(new T(arg1)); } - -#else -using std::bind; -using std::function; -using std::shared_ptr; +} #endif #ifdef __SYMBIAN32__ #define placeholder -#define p #elif defined(IOS) namespace placeholder = std::tr1::placeholders; -namespace p = std::tr1::placeholders; #else namespace placeholder = std::placeholders; -namespace p = std::placeholders; #endif diff --git a/net/http_client.cpp b/net/http_client.cpp index 7e9128c056..3e434cd6ff 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -174,7 +174,7 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) Download::Download(const std::string &url, const std::string &outfile) : url_(url), outfile_(outfile), progress_(0.0f), failed_(false) { - std::thread th(bind(&Download::Do, this)); + std::thread th(std::bind(&Download::Do, this)); th.detach(); } diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp index dcc733025d..d79f2cd6c9 100644 --- a/thread/threadpool.cpp +++ b/thread/threadpool.cpp @@ -3,7 +3,7 @@ ///////////////////////////// WorkerThread WorkerThread::WorkerThread() : active(true), started(false) { - thread = new std::thread(bind(&WorkerThread::WorkFunc, this)); + thread = new std::thread(std::bind(&WorkerThread::WorkFunc, this)); doneMutex.lock(); while(!started) { }; } @@ -17,7 +17,7 @@ WorkerThread::~WorkerThread() { delete thread; } -void WorkerThread::Process(const function& work) { +void WorkerThread::Process(const std::function& work) { mutex.lock(); work_ = work; signal.notify_one(); @@ -56,7 +56,7 @@ void ThreadPool::StartWorkers() { } } -void ThreadPool::ParallelLoop(function loop, int lower, int upper) { +void ThreadPool::ParallelLoop(std::function loop, int lower, int upper) { mutex.lock(); StartWorkers(); int range = upper-lower; @@ -66,7 +66,7 @@ void ThreadPool::ParallelLoop(function loop, int lower, int upper int chunk = range/numThreads; int s = lower; for(int i=0; iProcess(bind(loop, s, s+chunk)); + workers[i]->Process(std::bind(loop, s, s+chunk)); s+=chunk; } loop(s, upper); diff --git a/thread/threadpool.h b/thread/threadpool.h index c4bff05f06..04caa96bd6 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -13,7 +13,7 @@ public: ~WorkerThread(); // submit a new work item - void Process(const function& work); + void Process(const std::function& work); // wait for a submitted work item to be completed void WaitForCompletion(); @@ -23,7 +23,7 @@ private: ::condition_variable done; // used to signal work completion ::recursive_mutex mutex, doneMutex; // associated with each respective condition variable volatile bool active, started; - function work_; // the work to be done by this thread + std::function work_; // the work to be done by this thread void WorkFunc(); @@ -40,7 +40,7 @@ public: // don't need a destructor, "workers" is cleared on delete, // leading to the stopping and joining of all worker threads (RAII and all that) - void ParallelLoop(function loop, int lower, int upper); + void ParallelLoop(std::function loop, int lower, int upper); private: const int numThreads; diff --git a/ui/view.cpp b/ui/view.cpp index db6f6c0fc4..9de1542e21 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -49,7 +49,7 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure } } -void Event::Add(function func) { +void Event::Add(std::function func) { HandlerRegistration reg; reg.func = func; handlers_.push_back(reg); diff --git a/ui/view.h b/ui/view.h index 3ae7a30495..b6f8a439fe 100644 --- a/ui/view.h +++ b/ui/view.h @@ -157,14 +157,14 @@ struct EventParams { }; struct HandlerRegistration { - function func; + std::function func; }; class Event { public: Event() : triggered_(false) {} - void Add(function func); + void Add(std::function func); // Call this from input thread or whatever, it doesn't matter void Trigger(EventParams &e); @@ -410,7 +410,7 @@ class CheckBox : public ClickableItem { public: CheckBox(bool *toggle, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), text_(text), smallText_(smallText) { - OnClick.Add(bind(&CheckBox::OnClicked, this, placeholder::_1)); + OnClick.Add(std::bind(&CheckBox::OnClicked, this, placeholder::_1)); } virtual void Draw(UIContext &dc); From b7a01dc2fee6866c6f9e41b04c0cf3705e0f7343 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 2 Jun 2013 22:58:55 +1000 Subject: [PATCH 0425/1445] Fix shared_ptr as well. --- base/functional.h | 1 - net/http_client.cpp | 4 ++-- net/http_client.h | 4 ++-- thread/threadpool.h | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/base/functional.h b/base/functional.h index 1fdae0bb9e..42819b1ce0 100644 --- a/base/functional.h +++ b/base/functional.h @@ -12,7 +12,6 @@ #include #else #include -using std::shared_ptr; #endif #include diff --git a/net/http_client.cpp b/net/http_client.cpp index 3e434cd6ff..ad467b6f25 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -210,8 +210,8 @@ void Download::Do() { net::Shutdown(); } -shared_ptr Downloader::StartDownload(const std::string &url, const std::string &outfile) { - shared_ptr dl(new Download(url, outfile)); +std::shared_ptr Downloader::StartDownload(const std::string &url, const std::string &outfile) { + std::shared_ptr dl(new Download(url, outfile)); downloads_.push_back(dl); return dl; } diff --git a/net/http_client.h b/net/http_client.h index 6b56a846fc..8895b60841 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -99,13 +99,13 @@ private: class Downloader { public: - shared_ptr StartDownload(const std::string &url, const std::string &outfile); + std::shared_ptr StartDownload(const std::string &url, const std::string &outfile); // Drops finished downloads from the list. void Update(); private: - std::vector> downloads_; + std::vector> downloads_; }; diff --git a/thread/threadpool.h b/thread/threadpool.h index 04caa96bd6..e5b26df623 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -44,7 +44,7 @@ public: private: const int numThreads; - std::vector> workers; + std::vector> workers; ::recursive_mutex mutex; // used to sequentialize loop execution bool workersStarted; From b8f2a756772ab458ef981ba0d999b7998904ece2 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 3 Jun 2013 03:39:02 +1000 Subject: [PATCH 0426/1445] Initialise buttons so we don't get stuck keys. --- base/BlackberryMain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 4e98bd51d0..704d195cea 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -191,6 +191,8 @@ void BlackberryMain::startMain(int argc, char *argv[]) { // TODO: Enable/disable based on setting sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, 25000); sensor_request_events(SENSOR_TYPE_ACCELEROMETER); + pad_buttons = 0; + controller_buttons = 0; net::Init(); startDisplays(); From 27db010dde8b82af87975d83b65226828865882e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 2 Jun 2013 13:58:38 +0200 Subject: [PATCH 0427/1445] Remove 'p' alias for functional placeholders --- base/functional.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/functional.h b/base/functional.h index 42819b1ce0..4a0ddab9eb 100644 --- a/base/functional.h +++ b/base/functional.h @@ -1,7 +1,7 @@ // This file simply includes and applies any necessary compatibility fixes for // strange platforms like iOS. -// Use p or placeholder as the namespace for placeholders. +// Use placeholder as the namespace for placeholders. #pragma once From 2b3e1355ada42579c166026a764f6e2d7bfa4940 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 2 Jun 2013 23:44:28 +0200 Subject: [PATCH 0428/1445] More UI fixes --- ext/vjson/json.h | 23 +++++++++++++---------- native.vcxproj | 6 ++++++ net/http_client.cpp | 20 +++++++++++++++----- net/http_client.h | 5 +++++ ui/view.cpp | 21 ++++++++++++++++++++- ui/view.h | 32 +++++++++++++++++++++++++++++--- ui/viewgroup.cpp | 22 ++++++++++++++++++---- 7 files changed, 106 insertions(+), 23 deletions(-) diff --git a/ext/vjson/json.h b/ext/vjson/json.h index 57a8063586..99b6558476 100644 --- a/ext/vjson/json.h +++ b/ext/vjson/json.h @@ -86,16 +86,7 @@ public: free(buffer_); } - void parse() { - char *error_pos; - char *error_desc; - int error_line; - root_ = json_parse((char *)buffer_, &error_pos, &error_desc, &error_line, &alloc_); - if (!root_) { - ELOG("Error at (%i): %s\n%s\n\n", error_line, error_desc, error_pos); - } - } - + bool ok() const { return root_ != 0; } json_value *root() { return root_; } @@ -106,6 +97,18 @@ public: } private: + bool parse() { + char *error_pos; + char *error_desc; + int error_line; + root_ = json_parse((char *)buffer_, &error_pos, &error_desc, &error_line, &alloc_); + if (!root_) { + ELOG("Error at (%i): %s\n%s\n\n", error_line, error_desc, error_pos); + return false; + } + return true; + } + char *buffer_; block_allocator alloc_; json_value *root_; diff --git a/native.vcxproj b/native.vcxproj index d89eaeaa4b..cd4dcc375c 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -80,6 +80,8 @@ WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); ProgramDatabase + true + false Windows @@ -97,6 +99,8 @@ Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + true + false Windows @@ -118,6 +122,7 @@ ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast + true Windows @@ -141,6 +146,7 @@ ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast + true Windows diff --git a/net/http_client.cpp b/net/http_client.cpp index ad467b6f25..5a520a9048 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -119,12 +119,20 @@ int Client::GET(const char *resource, Buffer *output) { if (!output->ReadAll(sock())) return -1; + // Grab the first header line that contains the http code. + // Skip the header. TODO: read HTTP code and file size so we can make progress bars. + + std::string firstline; + CHECK_GT(output->TakeLineCRLF(&firstline), 0); + int code = atoi(&firstline[9]); + + while (output->SkipLineCRLF() > 0) ; // output now contains the rest of the reply. - return 200; + return code; } int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output) { @@ -172,7 +180,7 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) } Download::Download(const std::string &url, const std::string &outfile) - : url_(url), outfile_(outfile), progress_(0.0f), failed_(false) { + : url_(url), outfile_(outfile), progress_(0.0f), failed_(false), resultCode_(0) { std::thread th(std::bind(&Download::Do, this)); th.detach(); @@ -197,16 +205,18 @@ void Download::Do() { return; } client.Connect(); - if (client.GET(fileUrl.Resource().c_str(), &buffer_)) { + int resultCode = client.GET(fileUrl.Resource().c_str(), &buffer_); + if (resultCode == 200) { progress_ = 1.0f; ILOG("Completed downloading %s to %s", url_.c_str(), outfile_.c_str()); if (!outfile_.empty() && !buffer_.FlushToFile(outfile_.c_str())) { ELOG("Failed writing download to %s", outfile_.c_str()); } } else { - ELOG("Error downloading %s to %s", url_.c_str(), outfile_.c_str()); + progress_ = 1.0f; + ELOG("Error downloading %s to %s: %i", url_.c_str(), outfile_.c_str(), resultCode); } - + resultCode_ = resultCode; net::Shutdown(); } diff --git a/net/http_client.h b/net/http_client.h index 8895b60841..7a4c71fb2b 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -81,6 +81,8 @@ public: bool Failed() const { return failed_; } + int ResultCode() const { return resultCode_; } + std::string url() const { return url_; } std::string outfile() const { return outfile_; } @@ -94,9 +96,12 @@ private: Buffer buffer_; std::string url_; std::string outfile_; + int resultCode_; bool failed_; }; +using std::shared_ptr; + class Downloader { public: std::shared_ptr StartDownload(const std::string &url, const std::string &outfile); diff --git a/ui/view.cpp b/ui/view.cpp index 9de1542e21..366333e6e0 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -127,8 +127,15 @@ void Clickable::Touch(const TouchInput &input) { } void Clickable::Update(const InputState &input_state) { + OnClick.Update(); if (!HasFocus()) return; + + if (!enabled_) { + down_ = false; + return; + } + if (input_state.pad_buttons_down & PAD_BUTTON_A) { down_ = true; } else if (input_state.pad_buttons_up & PAD_BUTTON_A) { @@ -199,7 +206,8 @@ void Button::Draw(UIContext &dc) { Style style = dc.theme->buttonStyle; if (HasFocus()) style = dc.theme->buttonFocusedStyle; if (down_) style = dc.theme->buttonDownStyle; - + if (!enabled_) style = dc.theme->buttonDisabledStyle; + dc.Draw()->DrawImage4Grid(dc.theme->buttonImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); } @@ -228,6 +236,17 @@ void TextView::Draw(UIContext &dc) { dc.Draw()->SetFontScale(1.0f, 1.0f); } +void ProgressBar::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + dc.Draw()->MeasureText(dc.theme->uiFont, " 100% ", &w, &h); +} + +void ProgressBar::Draw(UIContext &dc) { + char temp[32]; + sprintf(temp, "%i%%", (int)(progress_ * 100.0f)); + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x + bounds_.w * progress_, bounds_.h); + dc.Draw()->DrawTextRect(dc.theme->uiFont, temp, bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF, ALIGN_CENTER); +} + void TriggerButton::Touch(const TouchInput &input) { if (input.flags & TOUCH_DOWN) { if (bounds_.Contains(input.x, input.y)) { diff --git a/ui/view.h b/ui/view.h index b6f8a439fe..a4534ea9be 100644 --- a/ui/view.h +++ b/ui/view.h @@ -43,6 +43,12 @@ enum DrawableType { DRAW_4GRID, }; +enum Visibility { + V_VISIBLE, + V_INVISIBLE, // Keeps position, not drawn or interacted with + V_GONE, // Does not participate in layout +}; + struct Drawable { Drawable() : type(DRAW_NOTHING) {} @@ -71,6 +77,7 @@ struct Theme { Style buttonStyle; Style buttonFocusedStyle; Style buttonDownStyle; + Style buttonDisabledStyle; Style itemDownStyle; Style itemFocusedStyle; @@ -207,7 +214,7 @@ View *GetFocusedView(); class View { public: - View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), enabled_(true) { + View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), enabled_(true), visibility_(V_VISIBLE) { if (!layoutParams) layoutParams_.reset(new LayoutParams()); } @@ -255,13 +262,17 @@ public: } void SetEnabled(bool enabled) { enabled_ = enabled; } - bool Enabled() const { return enabled_; } + bool GetEnabled() const { return enabled_; } + + void SetVisibility(Visibility visibility) { visibility_ = visibility; } + Visibility GetVisibility() const { return visibility_; } protected: // Inputs to layout scoped_ptr layoutParams_; bool enabled_; + Visibility visibility_; // Results of measure pass. Set these in Measure. float measuredWidth_; @@ -447,7 +458,7 @@ public: virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); - + virtual void SetText(const std::string &text) { text_ = text; } private: int font_; std::string text_; @@ -472,6 +483,21 @@ private: ImageSizeMode sizeMode_; }; +class ProgressBar : public InertView { +public: + ProgressBar(LayoutParams *layoutParams = 0) + : InertView(layoutParams), progress_(0.0) {} + + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + virtual void Draw(UIContext &dc); + + void SetProgress(float progress) { progress_ = progress; } + float GetProgress() const { return progress_; } + +private: + float progress_; +}; + // This tab strip is a little special. diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 51377993e4..c47d572638 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -32,21 +32,24 @@ ViewGroup::~ViewGroup() { void ViewGroup::Touch(const TouchInput &input) { for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. - (*iter)->Touch(input); + if ((*iter)->GetVisibility() == V_VISIBLE) + (*iter)->Touch(input); } } void ViewGroup::Draw(UIContext &dc) { for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. - (*iter)->Draw(dc); + if ((*iter)->GetVisibility() == V_VISIBLE) + (*iter)->Draw(dc); } } void ViewGroup::Update(const InputState &input_state) { for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. - (*iter)->Update(input_state); + if ((*iter)->GetVisibility() != V_GONE) + (*iter)->Update(input_state); } } @@ -74,6 +77,8 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio // Skip labels and things like that. if (!destination->CanBeFocused()) return 0.0f; + if (destination->GetEnabled() == false) + return 0.0f; float dx = destination->GetBounds().centerX() - origin->GetBounds().centerX(); float dy = destination->GetBounds().centerY() - origin->GetBounds().centerY(); @@ -203,7 +208,13 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v float weightSum = 0.0f; float weightZeroSum = 0.0f; + int numVisible = 0; + for (size_t i = 0; i < views_.size(); i++) { + if (views_[i]->GetVisibility() == V_GONE) + continue; + numVisible++; + const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); Margins margins = defaultMargins_; @@ -240,7 +251,7 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v } } - weightZeroSum += spacing_ * (views_.size() - 1); + weightZeroSum += spacing_ * (numVisible - 1); // Awright, got the sum. Let's take the remaining space after the fixed-size views, // and distribute among the weighted ones. @@ -293,6 +304,9 @@ void LinearLayout::Layout() { } for (size_t i = 0; i < views_.size(); i++) { + if (views_[i]->GetVisibility() == V_GONE) + continue; + const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); From c87fe2f782652e34b157dc9f1bddfe1df4d1fc7e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 3 Jun 2013 19:57:40 +0200 Subject: [PATCH 0429/1445] UIScreen helper class, derive your newUI screens from this. --- Android.mk | 1 + native.vcxproj | 2 ++ native.vcxproj.filters | 6 ++++++ ui/ui_screen.cpp | 37 +++++++++++++++++++++++++++++++++++++ ui/ui_screen.h | 24 ++++++++++++++++++++++++ 5 files changed, 70 insertions(+) create mode 100644 ui/ui_screen.cpp create mode 100644 ui/ui_screen.h diff --git a/Android.mk b/Android.mk index 680165f278..ced4092156 100644 --- a/Android.mk +++ b/Android.mk @@ -63,6 +63,7 @@ LOCAL_SRC_FILES :=\ ui/view.cpp \ ui/viewgroup.cpp \ ui/ui.cpp \ + ui/ui_screen.cpp \ ui/ui_context.cpp \ ui/screen.cpp \ ui/virtual_input.cpp \ diff --git a/native.vcxproj b/native.vcxproj index cd4dcc375c..bf22e8df3d 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -244,6 +244,7 @@ + @@ -361,6 +362,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index bb0c7d07c8..c6f8ae6f15 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -269,6 +269,9 @@ base + + ui + @@ -474,6 +477,9 @@ net + + ui + diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp new file mode 100644 index 0000000000..09fe04791b --- /dev/null +++ b/ui/ui_screen.cpp @@ -0,0 +1,37 @@ + +#include "ui/ui_screen.h" +#include "ui/ui_context.h" +#include "ui/screen.h" + +void UIScreen::update(InputState &input) { + if (!root_) { + CreateViews(); + } + + if (orientationChanged_) { + delete root_; + root_ = 0; + CreateViews(); + } + + UpdateViewHierarchy(input, root_); +} + +void UIScreen::render() { + UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_); + + screenManager()->getUIContext()->Begin(); + DrawBackground(); + root_->Draw(*screenManager()->getUIContext()); + screenManager()->getUIContext()->End(); + screenManager()->getUIContext()->Flush(); +} + +void UIScreen::touch(const TouchInput &touch) { + root_->Touch(touch); +} + +UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { + screenManager()->finishDialog(this, DR_OK); + return UI::EVENT_DONE; +} diff --git a/ui/ui_screen.h b/ui/ui_screen.h new file mode 100644 index 0000000000..e8111d3727 --- /dev/null +++ b/ui/ui_screen.h @@ -0,0 +1,24 @@ +#pragma once + +#include "ui/screen.h" +#include "ui/viewgroup.h" + +class UIScreen : public Screen { +public: + UIScreen() : Screen(), root_(0), orientationChanged_(false) {} + ~UIScreen() { delete root_; } + + virtual void update(InputState &input); + virtual void render(); + virtual void touch(const TouchInput &touch); + + // Some useful default event handlers + UI::EventReturn OnBack(UI::EventParams &e); + +protected: + virtual void CreateViews() = 0; + virtual void DrawBackground() {} + + UI::ViewGroup *root_; + bool orientationChanged_; +}; From f9e9ed6e27134436708463872c6e5b3d4b5d2f1c Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 4 Jun 2013 14:40:02 +1000 Subject: [PATCH 0430/1445] Update BlackberryMain. Now can push game output to external display and render at external display native resolution. Very useful for Q5/Q10 owners. Maybe not so good for Z10 right now as controls are not shown on device. Known issue: HDMI only works if it was plugged in when the application started. Hotplugging still has issues. --- base/BlackberryDisplay.cpp | 135 ++++++++++++++++++------------------- base/BlackberryMain.cpp | 19 +----- base/BlackberryMain.h | 38 +++++++---- 3 files changed, 94 insertions(+), 98 deletions(-) diff --git a/base/BlackberryDisplay.cpp b/base/BlackberryDisplay.cpp index 95712476c1..3411592058 100644 --- a/base/BlackberryDisplay.cpp +++ b/base/BlackberryDisplay.cpp @@ -27,47 +27,6 @@ char* BlackberryMain::displayTypeString(int type) } void BlackberryMain::startDisplays() { - screen_get_context_property_iv(screen_cxt, SCREEN_PROPERTY_DISPLAY_COUNT, &ndisplays); - egl_disp = (EGLDisplay*)calloc(ndisplays, sizeof(EGLDisplay)); - egl_surf = (EGLSurface*)calloc(ndisplays, sizeof(EGLSurface)); - egl_cont = (EGLContext*)calloc(ndisplays, sizeof(EGLContext)); - displays = (dispdata_t*)calloc(ndisplays, sizeof(dispdata_t)); - screen_win = (screen_window_t *)calloc(ndisplays, sizeof(screen_window_t )); - screen_dpy = (screen_display_t*)calloc(ndisplays, sizeof(screen_display_t)); - screen_get_context_property_pv(screen_cxt, SCREEN_PROPERTY_DISPLAYS, (void **)screen_dpy); - - // Common data - int usage = SCREEN_USAGE_ROTATION | SCREEN_USAGE_OPENGL_ES2; - int format = SCREEN_FORMAT_RGBX8888; - int sensitivity = SCREEN_SENSITIVITY_ALWAYS; - - // Initialise every display - emulating = false; - screen_ui = 0; - screen_emu = 0; - for (int i = 0; i < ndisplays; i++) { - screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_TYPE, &(displays[i].type)); - screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_ATTACHED, &(displays[i].attached)); - - screen_create_window(&screen_win[i], screen_cxt); - screen_set_window_property_iv(screen_win[i], SCREEN_PROPERTY_FORMAT, &format); - screen_set_window_property_iv(screen_win[i], SCREEN_PROPERTY_USAGE, &usage); - screen_set_window_property_iv(screen_win[i], SCREEN_PROPERTY_SENSITIVITY, &sensitivity); - screen_set_window_property_pv(screen_win[i], SCREEN_PROPERTY_DISPLAY, (void **)&screen_dpy[i]); - - egl_disp[i] = eglGetDisplay((EGLNativeDisplayType)i); - eglInitialize(egl_disp[i], NULL, NULL); - fprintf(stderr, "Display %i: %s, %s\n", i, displayTypeString(displays[i].type), displays[i].attached ? "Attached" : "Detached"); - if (displays[i].attached) - realiseDisplay(i); - } - screen_get_display_property_iv(screen_dpy[0], SCREEN_PROPERTY_DPI, &dpi); // Only internal display has DPI - dpi_scale = ((pixel_xres == pixel_yres) ? 300.0f : 213.6f) / dpi; - switchDisplay(screen_ui); -} - -void BlackberryMain::realiseDisplay(int idx) { - EGLConfig egl_conf; int num_configs; EGLint attrib_list[]= { EGL_RED_SIZE, 8, @@ -80,6 +39,49 @@ void BlackberryMain::realiseDisplay(int idx) { EGL_NONE}; const EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + + screen_get_context_property_iv(screen_cxt, SCREEN_PROPERTY_DISPLAY_COUNT, &ndisplays); + egl_disp = (EGLDisplay*)calloc(ndisplays, sizeof(EGLDisplay)); + egl_surf = (EGLSurface*)calloc(ndisplays, sizeof(EGLSurface)); + displays = (dispdata_t*)calloc(ndisplays, sizeof(dispdata_t)); + screen_win = (screen_window_t *)calloc(ndisplays, sizeof(screen_window_t )); + screen_dpy = (screen_display_t*)calloc(ndisplays, sizeof(screen_display_t)); + screen_get_context_property_pv(screen_cxt, SCREEN_PROPERTY_DISPLAYS, (void **)screen_dpy); + + // Common data + int usage = SCREEN_USAGE_ROTATION | SCREEN_USAGE_OPENGL_ES2; + int format = SCREEN_FORMAT_RGBX8888; + int sensitivity = SCREEN_SENSITIVITY_ALWAYS; + + // Initialise every display + for (int i = 0; i < ndisplays; i++) { + screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_TYPE, &(displays[i].type)); + screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_ATTACHED, &(displays[i].attached)); + + screen_create_window(&screen_win[i], screen_cxt); + screen_set_window_property_iv(screen_win[i], SCREEN_PROPERTY_FORMAT, &format); + screen_set_window_property_iv(screen_win[i], SCREEN_PROPERTY_USAGE, &usage); + screen_set_window_property_iv(screen_win[i], SCREEN_PROPERTY_SENSITIVITY, &sensitivity); + screen_set_window_property_pv(screen_win[i], SCREEN_PROPERTY_DISPLAY, (void **)&screen_dpy[i]); + + egl_disp[i] = eglGetDisplay((EGLNativeDisplayType)i); + eglInitialize(egl_disp[i], NULL, NULL); + //eglSwapInterval(egl_disp[idx], 1); + if (egl_cont == EGL_NO_CONTEXT) { + eglChooseConfig(egl_disp[0], attrib_list, &egl_conf, 1, &num_configs); + egl_cont = eglCreateContext(egl_disp[0], egl_conf, EGL_NO_CONTEXT, attributes); + } + + fprintf(stderr, "Display %i: %s, %s\n", i, displayTypeString(displays[i].type), displays[i].attached ? "Attached" : "Detached"); + if (displays[i].attached) + realiseDisplay(i); + } + screen_get_display_property_iv(screen_dpy[0], SCREEN_PROPERTY_DPI, &dpi); // Only internal display has DPI + dpi_scale = ((pixel_xres == pixel_yres) ? 300.0f : 213.6f) / dpi; + switchDisplay(screen_ui); +} + +void BlackberryMain::realiseDisplay(int idx) { const EGLint egl_surfaceAttr[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE }; int size[2] = { atoi(getenv("WIDTH")), atoi(getenv("HEIGHT")) }; @@ -87,57 +89,52 @@ void BlackberryMain::realiseDisplay(int idx) { screen_get_display_property_iv(screen_dpy[idx], SCREEN_PROPERTY_SIZE, size); displays[idx].width = size[0]; displays[idx].height = size[1]; - screen_set_window_property_iv(screen_win[idx], SCREEN_PROPERTY_BUFFER_SIZE, size); - screen_create_window_buffers(screen_win[idx], 2); // Double buffered + int err_1 = screen_set_window_property_iv(screen_win[idx], SCREEN_PROPERTY_BUFFER_SIZE, size); + int err_2 = screen_create_window_buffers(screen_win[idx], 2); // Double buffered fprintf(stderr, "Display %i realised with %ix%i\n", idx, size[0], size[1]); - eglChooseConfig(egl_disp[idx], attrib_list, &egl_conf, 1, &num_configs); - if (!egl_cont[idx]) - egl_cont[idx] = eglCreateContext(egl_disp[idx], egl_conf, EGL_NO_CONTEXT, attributes); egl_surf[idx] = eglCreateWindowSurface(egl_disp[idx], egl_conf, screen_win[idx], egl_surfaceAttr); - eglSwapInterval(egl_disp[idx], 1); - // Temporarily disabled -#if 0 + fprintf(stderr, "Stats: %i %i %i\n", err_1, err_2, egl_surf[idx]); + if (displays[idx].type != SCREEN_DISPLAY_TYPE_INTERNAL) { screen_emu = idx; if (emulating) switchDisplay(idx); } -#endif + displays[idx].realised = true; } -// Note: Only hotpluggable displays can unrealise. Internal (0) is not possible. void BlackberryMain::unrealiseDisplay(int idx) { - killDisplay(idx, false); - screen_destroy_window_buffers(screen_win[idx]); - screen_flush_context(screen_cxt, 0); - if (displays[idx].type != SCREEN_DISPLAY_TYPE_INTERNAL) + if (displays[idx].type != SCREEN_DISPLAY_TYPE_INTERNAL) // Always true, only external can unrealise { screen_emu = screen_ui; if (emulating) switchDisplay(screen_ui); - eglMakeCurrent(egl_disp[screen_ui], egl_surf[screen_ui], egl_surf[screen_ui], egl_cont[screen_ui]); } + killDisplay(idx, false); +// screen_flush_context(screen_cxt, 0); + fprintf(stderr, "Unrealising %i\n", idx); displays[idx].realised = false; } void BlackberryMain::switchDisplay(int idx) { static int screen_curr = -1; if (idx != screen_curr) { + fprintf(stderr, "Switching to %i\n", idx); pixel_xres = displays[idx].width; pixel_yres = displays[idx].height; dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); - if (emulating) { - PSP_CoreParameter().pixelWidth = pixel_xres; - PSP_CoreParameter().pixelHeight = pixel_yres; - PSP_CoreParameter().outputWidth = dp_xres; - PSP_CoreParameter().outputHeight = dp_yres; - } screen_curr = idx; - eglMakeCurrent(egl_disp[idx], egl_surf[idx], egl_surf[idx], egl_cont[idx]); + eglMakeCurrent(egl_disp[idx], egl_surf[idx], egl_surf[idx], egl_cont); + } + if (emulating) { + PSP_CoreParameter().pixelWidth = pixel_xres; + PSP_CoreParameter().pixelHeight = pixel_yres; + PSP_CoreParameter().outputWidth = dp_xres; + PSP_CoreParameter().outputHeight = dp_yres; } } @@ -145,6 +142,10 @@ void BlackberryMain::killDisplays() { for (int i = 0; i < ndisplays; i++) { killDisplay(i, true); } + if (egl_cont != EGL_NO_CONTEXT) { + eglDestroyContext(egl_disp[0], egl_cont); + egl_cont = EGL_NO_CONTEXT; + } free(egl_disp); free(egl_surf); eglReleaseThread(); @@ -153,15 +154,12 @@ void BlackberryMain::killDisplays() { void BlackberryMain::killDisplay(int idx, bool killContext) { if (egl_disp[idx] != EGL_NO_DISPLAY) { - eglMakeCurrent(egl_disp[idx], EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (killContext) + eglMakeCurrent(egl_disp[idx], EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (egl_surf[idx] != EGL_NO_SURFACE) { eglDestroySurface(egl_disp[idx], egl_surf[idx]); egl_surf[idx] = EGL_NO_SURFACE; } - if (killContext && egl_cont[idx] != EGL_NO_CONTEXT) { - eglDestroyContext(egl_disp[idx], egl_cont[idx]); - egl_cont[idx] = EGL_NO_CONTEXT; - } if (killContext) { eglTerminate(egl_disp[idx]); @@ -172,5 +170,6 @@ void BlackberryMain::killDisplay(int idx, bool killContext) { screen_destroy_window(screen_win[idx]); screen_win[idx] = NULL; } + screen_destroy_window_buffers(screen_win[idx]); } diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 704d195cea..7a0288efff 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -160,8 +160,6 @@ void BlackberryMain::handleInput(screen_event_t screen_event) case SCREEN_EVENT_DISPLAY: screen_display_t new_dpy = NULL; screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DISPLAY, (void **)&new_dpy); - static int hits = 0; - hits++; for (int i = 0; i < ndisplays; i++) { if (new_dpy != screen_dpy[i]) continue; @@ -191,12 +189,9 @@ void BlackberryMain::startMain(int argc, char *argv[]) { // TODO: Enable/disable based on setting sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, 25000); sensor_request_events(SENSOR_TYPE_ACCELEROMETER); - pad_buttons = 0; - controller_buttons = 0; net::Init(); startDisplays(); - //eglMakeCurrent(egl_disp[0], egl_surf[0], egl_surf[0], egl_ctx[0]); NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "data/", "BADCOFFEE"); NativeInitGraphics(); screen_request_events(screen_cxt); @@ -230,9 +225,7 @@ void BlackberryMain::runMain() { pad_buttons |= PAD_BUTTON_MENU; break; case NAVIGATOR_EXIT: - NativeShutdown(); - exit(0); - break; + return; } } else if (domain == sensor_get_domain()) { if (SENSOR_ACCELEROMETER_READING == bps_event_get_code(event)) { @@ -257,9 +250,7 @@ void BlackberryMain::runMain() { EndInputState(&input_state); // Work in Progress // Currently: Render to HDMI port (eg. 1080p) when in game. Render to device when in menu. - // Right now, hotswapping displays is not working. Temporarily disable. // Idea: Render to all displays. Controls go to internal, game goes to external(s). -#if 0 if (globalUIState == UISTATE_INGAME && !emulating) { emulating = true; @@ -268,16 +259,14 @@ void BlackberryMain::runMain() { emulating = false; switchDisplay(screen_ui); } -#endif NativeRender(); time_update(); // This handles VSync - if (false && emulating) // Temporarily disable + if (emulating) eglSwapBuffers(egl_disp[screen_emu], egl_surf[screen_emu]); else eglSwapBuffers(egl_disp[screen_ui], egl_surf[screen_ui]); } - endMain(); } void BlackberryMain::endMain() { @@ -293,8 +282,6 @@ void BlackberryMain::endMain() { // Entry Point int main(int argc, char *argv[]) { - BlackberryMain emu; - emu.startMain(argc, argv); - exit(0); + delete new BlackberryMain(argc, argv); return 0; } diff --git a/base/BlackberryMain.h b/base/BlackberryMain.h index de320475b0..0d20442f6d 100644 --- a/base/BlackberryMain.h +++ b/base/BlackberryMain.h @@ -44,24 +44,33 @@ struct dispdata_t { class BlackberryMain { public: - BlackberryMain() { } - ~BlackberryMain() { } - void startMain(int argc, char *argv[]); + BlackberryMain(int argc, char *argv[]) : + emulating(false), + screen_ui(0), screen_emu(0), + pad_buttons(0), controller_buttons(0), + egl_cont(EGL_NO_CONTEXT) + { + startMain(argc, argv); + } + ~BlackberryMain() { + endMain(); + } + void startMain(int argc, char *argv[]); private: - void runMain(); - void endMain(); + void runMain(); + void endMain(); - void handleInput(screen_event_t screen_event); + void handleInput(screen_event_t screen_event); char* displayTypeString(int type); - void startDisplays(); + void startDisplays(); void* startDisplay(int idx); - void realiseDisplay(int idx); - void unrealiseDisplay(int idx); - void switchDisplay(int idx); - void killDisplays(); - void killDisplay(int idx, bool killContext); + void realiseDisplay(int idx); + void unrealiseDisplay(int idx); + void switchDisplay(int idx); + void killDisplays(); + void killDisplay(int idx, bool killContext); BlackberryAudio* audio; dispdata_t *displays; @@ -73,10 +82,11 @@ private: int pad_buttons, controller_buttons; EGLDisplay* egl_disp; EGLSurface* egl_surf; - EGLContext* egl_cont; + EGLContext egl_cont; + EGLConfig egl_conf; screen_context_t screen_cxt; screen_display_t *screen_dpy; - screen_window_t *screen_win; + screen_window_t *screen_win; }; #endif From a4e9197fb4207d3e357f4c0c9590f17d4c5f3d0f Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 4 Jun 2013 22:50:22 +1000 Subject: [PATCH 0431/1445] Buildfix for Blackberry and Meego. Disable external display for Blackberry devices with 16:9 aspect ratio and no keyboard. Cleanup BlackberryMain. --- base/BlackberryDisplay.cpp | 12 ++++-------- ui/view.h | 1 + 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/base/BlackberryDisplay.cpp b/base/BlackberryDisplay.cpp index 3411592058..7d02f5d2bc 100644 --- a/base/BlackberryDisplay.cpp +++ b/base/BlackberryDisplay.cpp @@ -66,7 +66,6 @@ void BlackberryMain::startDisplays() { egl_disp[i] = eglGetDisplay((EGLNativeDisplayType)i); eglInitialize(egl_disp[i], NULL, NULL); - //eglSwapInterval(egl_disp[idx], 1); if (egl_cont == EGL_NO_CONTEXT) { eglChooseConfig(egl_disp[0], attrib_list, &egl_conf, 1, &num_configs); egl_cont = eglCreateContext(egl_disp[0], egl_conf, EGL_NO_CONTEXT, attributes); @@ -89,14 +88,14 @@ void BlackberryMain::realiseDisplay(int idx) { screen_get_display_property_iv(screen_dpy[idx], SCREEN_PROPERTY_SIZE, size); displays[idx].width = size[0]; displays[idx].height = size[1]; - int err_1 = screen_set_window_property_iv(screen_win[idx], SCREEN_PROPERTY_BUFFER_SIZE, size); - int err_2 = screen_create_window_buffers(screen_win[idx], 2); // Double buffered + screen_set_window_property_iv(screen_win[idx], SCREEN_PROPERTY_BUFFER_SIZE, size); + screen_create_window_buffers(screen_win[idx], 2); // Double buffered fprintf(stderr, "Display %i realised with %ix%i\n", idx, size[0], size[1]); egl_surf[idx] = eglCreateWindowSurface(egl_disp[idx], egl_conf, screen_win[idx], egl_surfaceAttr); - fprintf(stderr, "Stats: %i %i %i\n", err_1, err_2, egl_surf[idx]); - if (displays[idx].type != SCREEN_DISPLAY_TYPE_INTERNAL) + // Only enable for devices with hardware QWERTY, 1:1 aspect ratio + if ((pixel_xres == pixel_yres) && displays[idx].type != SCREEN_DISPLAY_TYPE_INTERNAL) { screen_emu = idx; if (emulating) @@ -114,15 +113,12 @@ void BlackberryMain::unrealiseDisplay(int idx) { switchDisplay(screen_ui); } killDisplay(idx, false); -// screen_flush_context(screen_cxt, 0); - fprintf(stderr, "Unrealising %i\n", idx); displays[idx].realised = false; } void BlackberryMain::switchDisplay(int idx) { static int screen_curr = -1; if (idx != screen_curr) { - fprintf(stderr, "Switching to %i\n", idx); pixel_xres = displays[idx].width; pixel_yres = displays[idx].height; dp_xres = (int)(pixel_xres * dpi_scale); diff --git a/ui/view.h b/ui/view.h index a4534ea9be..c882c1a7ce 100644 --- a/ui/view.h +++ b/ui/view.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "base/functional.h" #include "base/mutex.h" From 3b9750ee495be05809f7784981433c74f36d4748 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 4 Jun 2013 01:24:49 +0200 Subject: [PATCH 0432/1445] Fix a race condition in downloader, some ui style stuff --- base/buffer.cpp | 27 +++++++++++++++------------ base/buffer.h | 2 +- net/http_client.cpp | 9 +++++---- ui/view.cpp | 14 +++++++------- ui/view.h | 5 ++--- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index 55b9e11015..9d0c160fcf 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -159,19 +159,22 @@ bool Buffer::ReadAll(int fd) { return true; } -void Buffer::Read(int fd, size_t sz) { - char buf[1024]; - int retval; - while ((retval = recv(fd, buf, std::min(sz, sizeof(buf)), 0)) > 0) { - char *p = Append((size_t)retval); - memcpy(p, buf, retval); - sz -= retval; - if (sz == 0) - break; - } +size_t Buffer::Read(int fd, size_t sz) { + char buf[1024]; + int retval; + size_t received = 0; + while ((retval = recv(fd, buf, std::min(sz, sizeof(buf)), 0)) > 0) { + char *p = Append((size_t)retval); + memcpy(p, buf, retval); + sz -= retval; + received += retval; + if (sz == 0) + return 0; + } + return received; } void Buffer::PeekAll(std::string *dest) { - dest->resize(data_.size()); - memcpy(&(*dest)[0], &data_[0], data_.size()); + dest->resize(data_.size()); + memcpy(&(*dest)[0], &data_[0], data_.size()); } \ No newline at end of file diff --git a/base/buffer.h b/base/buffer.h index ead85cb450..ff6fa9e1ab 100644 --- a/base/buffer.h +++ b/base/buffer.h @@ -65,7 +65,7 @@ class Buffer { bool FlushSocket(uintptr_t sock); // Windows portability bool ReadAll(int fd); - void Read(int fd, size_t sz); + size_t Read(int fd, size_t sz); // Utilities. Try to avoid checking for size. size_t size() const { return data_.size(); } diff --git a/net/http_client.cpp b/net/http_client.cpp index 5a520a9048..4963fc01d2 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -127,7 +127,6 @@ int Client::GET(const char *resource, Buffer *output) { CHECK_GT(output->TakeLineCRLF(&firstline), 0); int code = atoi(&firstline[9]); - while (output->SkipLineCRLF() > 0) ; @@ -181,7 +180,6 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) Download::Download(const std::string &url, const std::string &outfile) : url_(url), outfile_(outfile), progress_(0.0f), failed_(false), resultCode_(0) { - std::thread th(std::bind(&Download::Do, this)); th.detach(); } @@ -191,9 +189,12 @@ Download::~Download() { } void Download::Do() { + resultCode_ = 0; + Url fileUrl(url_); if (!fileUrl.Valid()) { failed_ = true; + progress_ = 1.0f; return; } net::Init(); @@ -202,22 +203,22 @@ void Download::Do() { if (!client.Resolve(fileUrl.Host().c_str(), 80)) { ELOG("Failed resolving %s", url_.c_str()); failed_ = true; + progress_ = 1.0f; return; } client.Connect(); int resultCode = client.GET(fileUrl.Resource().c_str(), &buffer_); if (resultCode == 200) { - progress_ = 1.0f; ILOG("Completed downloading %s to %s", url_.c_str(), outfile_.c_str()); if (!outfile_.empty() && !buffer_.FlushToFile(outfile_.c_str())) { ELOG("Failed writing download to %s", outfile_.c_str()); } } else { - progress_ = 1.0f; ELOG("Error downloading %s to %s: %i", url_.c_str(), outfile_.c_str(), resultCode); } resultCode_ = resultCode; net::Shutdown(); + progress_ = 1.0f; } std::shared_ptr Downloader::StartDownload(const std::string &url, const std::string &outfile) { diff --git a/ui/view.cpp b/ui/view.cpp index 366333e6e0..2a73699012 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -189,11 +189,13 @@ void ItemHeader::Draw(UIContext &dc) { void CheckBox::Draw(UIContext &dc) { ClickableItem::Draw(dc); - int paddingX = 80; + int paddingX = 4; int paddingY = 4; - dc.Draw()->DrawImage(dc.theme->checkOn, bounds_.x + 30, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); + + int image = *toggle_ ? dc.theme->checkOn : dc.theme->checkOff; + dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); - // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); + dc.Draw()->DrawImage(image, bounds_.x2() - 4, bounds_.centerY(), 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); } void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const { @@ -201,14 +203,12 @@ void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const } void Button::Draw(UIContext &dc) { - int image = down_ ? dc.theme->buttonImage : dc.theme->buttonSelected; - Style style = dc.theme->buttonStyle; if (HasFocus()) style = dc.theme->buttonFocusedStyle; if (down_) style = dc.theme->buttonDownStyle; if (!enabled_) style = dc.theme->buttonDisabledStyle; - dc.Draw()->DrawImage4Grid(dc.theme->buttonImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); + dc.Draw()->DrawImage4Grid(style.image, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); } @@ -243,7 +243,7 @@ void ProgressBar::GetContentDimensions(const UIContext &dc, float &w, float &h) void ProgressBar::Draw(UIContext &dc) { char temp[32]; sprintf(temp, "%i%%", (int)(progress_ * 100.0f)); - dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x + bounds_.w * progress_, bounds_.h); + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x + bounds_.w * progress_, bounds_.y2(), 0xc0c0c0c0); dc.Draw()->DrawTextRect(dc.theme->uiFont, temp, bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF, ALIGN_CENTER); } diff --git a/ui/view.h b/ui/view.h index c882c1a7ce..02b017342c 100644 --- a/ui/view.h +++ b/ui/view.h @@ -58,10 +58,11 @@ struct Drawable { }; struct Style { - Style() : fgColor(0xFFFFFFFF), bgColor(0xFF303030) {} + Style() : fgColor(0xFFFFFFFF), bgColor(0xFF303030), image(-1) {} uint32_t fgColor; uint32_t bgColor; + int image; // where applicable. }; // To use with an UI atlas. @@ -69,8 +70,6 @@ struct Theme { int uiFont; int uiFontSmall; int uiFontSmaller; - int buttonImage; - int buttonSelected; int checkOn; int checkOff; int whiteImage; From a509d38357c8ccff9efb4208957965c1aaf46e92 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 4 Jun 2013 22:05:17 +0200 Subject: [PATCH 0433/1445] UI, http with gzip, etc. --- Android.mk | 2 + android/app-android.cpp | 21 ++++--- base/buffer.cpp | 6 +- base/stringutil.h | 4 ++ data/compression.cpp | 103 +++++++++++++++++++++++++++++++++++ {math => data}/compression.h | 6 ++ native.vcxproj | 3 +- native.vcxproj.filters | 9 ++- net/http_client.cpp | 88 ++++++++++++++++++++++++++---- ui/ui_context.cpp | 9 +-- ui/viewgroup.h | 10 +++- 11 files changed, 229 insertions(+), 32 deletions(-) create mode 100644 data/compression.cpp rename {math => data}/compression.h (71%) diff --git a/Android.mk b/Android.mk index ced4092156..f5266360a0 100644 --- a/Android.mk +++ b/Android.mk @@ -16,6 +16,7 @@ LOCAL_SRC_FILES :=\ base/colorutil.cpp \ base/error_context.cpp \ base/stringutil.cpp \ + data/compression.cpp \ ext/rg_etc1/rg_etc1.cpp \ ext/cityhash/city.cpp \ ext/sha1/sha1.cpp \ @@ -32,6 +33,7 @@ LOCAL_SRC_FILES :=\ file/zip_read.cpp \ json/json_writer.cpp \ i18n/i18n.cpp \ + input/gesture_detector.cpp \ math/math_util.cpp \ math/curves.cpp \ math/lin/aabb.cpp.arm \ diff --git a/android/app-android.cpp b/android/app-android.cpp index 2d9a7dc322..9fb4009f0d 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -263,8 +263,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN lock_guard guard(input_state.lock); input_state.pad_lstick_x = left_joystick_x_async; input_state.pad_lstick_y = left_joystick_y_async; - NativeUpdate(input_state); } + NativeUpdate(input_state); { lock_guard guard(input_state.lock); @@ -319,17 +319,14 @@ extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* e extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch (JNIEnv *, jclass, float x, float y, int code, int pointerId) { + ELOG("Touch Enter %i", pointerId); lock_guard guard(input_state.lock); - if (pointerId >= MAX_POINTERS) { - ELOG("Too many pointers: %i", pointerId); - return; // We ignore 8+ pointers entirely. - } float scaledX = (int)(x * dp_xscale); // why the (int) cast? float scaledY = (int)(y * dp_yscale); - input_state.pointer_x[pointerId] = scaledX; - input_state.pointer_y[pointerId] = scaledY; + TouchInput touch; + touch.id = pointerId; touch.x = scaledX; touch.y = scaledY; if (code == 1) { @@ -341,8 +338,16 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch } else { touch.flags = TOUCH_MOVE; } - NativeTouch(touch); + + if (pointerId >= MAX_POINTERS) { + ELOG("Too many pointers: %i", pointerId); + return; // We ignore 8+ pointers entirely. + } + input_state.pointer_x[pointerId] = scaledX; + input_state.pointer_y[pointerId] = scaledY; input_state.mouse_valid = true; + NativeTouch(touch); + ELOG("Touch Exit %i", pointerId); } static void AsyncDown(int padbutton) { diff --git a/base/buffer.cpp b/base/buffer.cpp index 9d0c160fcf..f618727c02 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -46,8 +46,10 @@ void Buffer::AppendValue(int value) { void Buffer::Take(size_t length, std::string *dest) { CHECK_LE(length, data_.size()); dest->resize(length); - memcpy(&(*dest)[0], &data_[0], length); - data_.erase(data_.begin(), data_.begin() + length); + if (length > 0) { + memcpy(&(*dest)[0], &data_[0], length); + data_.erase(data_.begin(), data_.begin() + length); + } } int Buffer::TakeLineCRLF(std::string *dest) { diff --git a/base/stringutil.h b/base/stringutil.h index fe607fa9aa..d56880189a 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -63,10 +63,14 @@ public: // Other simple string utilities. inline bool startsWith(const std::string &str, const std::string &what) { + if (str.size() < what.size()) + return false; return str.substr(0, what.size()) == what; } inline bool endsWith(const std::string &str, const std::string &what) { + if (str.size() < what.size()) + return false; return str.substr(str.size() - what.size()) == what; } diff --git a/data/compression.cpp b/data/compression.cpp new file mode 100644 index 0000000000..1446b4993c --- /dev/null +++ b/data/compression.cpp @@ -0,0 +1,103 @@ +// Little utility functions for data compression. +// Taken from http://panthema.net/2007/0328-ZLibString.html + + +#include +#include +#include +#include +#include + +#include + +#include "base/logging.h" + +/** Compress a STL string using zlib with given compression level and return +* the binary data. */ +bool compress_string(const std::string& str, std::string *dest, int compressionlevel) { + z_stream zs; // z_stream is zlib's control structure + memset(&zs, 0, sizeof(zs)); + + if (deflateInit(&zs, compressionlevel) != Z_OK) { + ELOG("deflateInit failed while compressing."); + return false; + } + + zs.next_in = (Bytef*)str.data(); + zs.avail_in = str.size(); // set the z_stream's input + + int ret; + char outbuffer[32768]; + std::string outstring; + + // retrieve the compressed bytes blockwise + do { + zs.next_out = reinterpret_cast(outbuffer); + zs.avail_out = sizeof(outbuffer); + + ret = deflate(&zs, Z_FINISH); + + if (outstring.size() < zs.total_out) { + // append the block to the output string + outstring.append(outbuffer, + zs.total_out - outstring.size()); + } + } while (ret == Z_OK); + + deflateEnd(&zs); + + if (ret != Z_STREAM_END) { // an error occurred that was not EOF + std::ostringstream oss; + oss << "Exception during zlib compression: (" << ret << ") " << zs.msg; + return false; + } + + *dest = outstring; + return true; +} + +/** Decompress an STL string using zlib and return the original data. */ +bool decompress_string(const std::string& str, std::string *dest) { + if (!str.size()) + return false; + + z_stream zs; // z_stream is zlib's control structure + memset(&zs, 0, sizeof(zs)); + + // modification by hrydgard: inflateInit2, 16+MAXWBITS makes it read gzip data too + if (inflateInit2(&zs, 32+MAX_WBITS) != Z_OK) { + ELOG("inflateInit failed while decompressing."); + return false; + } + + zs.next_in = (Bytef*)str.data(); + zs.avail_in = str.size(); + + int ret; + char outbuffer[32768]; + std::string outstring; + + // get the decompressed bytes blockwise using repeated calls to inflate + do { + zs.next_out = reinterpret_cast(outbuffer); + zs.avail_out = sizeof(outbuffer); + + ret = inflate(&zs, 0); + + if (outstring.size() < zs.total_out) { + outstring.append(outbuffer, + zs.total_out - outstring.size()); + } + + } while (ret == Z_OK); + + inflateEnd(&zs); + + if (ret != Z_STREAM_END) { // an error occurred that was not EOF + std::ostringstream oss; + ELOG("Exception during zlib decompression: (%i) %s", ret, zs.msg); + return false; + } + + *dest = outstring; +} \ No newline at end of file diff --git a/math/compression.h b/data/compression.h similarity index 71% rename from math/compression.h rename to data/compression.h index f9e457c8d0..2199c5591e 100644 --- a/math/compression.h +++ b/data/compression.h @@ -1,5 +1,11 @@ #pragma once +#include + +bool compress_string(const std::string& str, std::string *dest, int compressionlevel = Z_BEST_COMPRESSION); +bool decompress_string(const std::string& str, std::string *dest); + + // Delta encoding/decoding - many formats benefit from a pass of this before zlibbing. // WARNING : Do not use these with floating point data, especially not float16... diff --git a/native.vcxproj b/native.vcxproj index bf22e8df3d..b06a52b24a 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -189,6 +189,7 @@ + @@ -223,7 +224,6 @@ - @@ -293,6 +293,7 @@ + AnySuitable true diff --git a/native.vcxproj.filters b/native.vcxproj.filters index c6f8ae6f15..cae63ba799 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -131,9 +131,6 @@ file - - math - gfx @@ -272,6 +269,9 @@ ui + + data + @@ -480,6 +480,9 @@ ui + + data + diff --git a/net/http_client.cpp b/net/http_client.cpp index 4963fc01d2..17e7ac8a35 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -17,6 +17,7 @@ #include "base/logging.h" #include "base/buffer.h" #include "base/stringutil.h" +#include "data/compression.h" #include "net/resolve.h" #include "net/url.h" @@ -84,8 +85,6 @@ void Connection::Disconnect() { if ((intptr_t)sock_ != -1) { closesocket(sock_); sock_ = -1; - } else { - WLOG("Socket was already disconnected."); } } @@ -99,38 +98,103 @@ void Connection::Reconnect() { namespace http { Client::Client() { + } + Client::~Client() { Disconnect(); } -#define USERAGENT "METAGET 1.0" +// TODO: do something sane here +#define USERAGENT "NATIVEAPP 1.0" + + +void DeChunk(Buffer *inbuffer, Buffer *outbuffer) { + while (true) { + std::string line; + inbuffer->TakeLineCRLF(&line); + if (!line.size()) + return; + int chunkSize; + sscanf(line.c_str(), "%x", &chunkSize); + if (chunkSize) { + std::string data; + inbuffer->Take(chunkSize, &data); + outbuffer->Append(data); + } else { + // a zero size chunk should mean the end. + inbuffer->clear(); + return; + } + inbuffer->Skip(2); + } +} int Client::GET(const char *resource, Buffer *output) { Buffer buffer; - const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " USERAGENT "\r\n\r\n"; + const char *tpl = + "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: " USERAGENT "\r\n" + "Accept: */*\r\n" + "Accept-Encoding: gzip\r\n" + "Connection: close\r\n" + "\r\n"; + buffer.Printf(tpl, resource, host_.c_str()); bool flushed = buffer.FlushSocket(sock()); if (!flushed) { return -1; // TODO error code. } - // Snarf all the data we can. - if (!output->ReadAll(sock())) + Buffer readbuf; + + // Snarf all the data we can into RAM. A little unsafe but hey. + if (!readbuf.ReadAll(sock())) return -1; // Grab the first header line that contains the http code. // Skip the header. TODO: read HTTP code and file size so we can make progress bars. - std::string firstline; - CHECK_GT(output->TakeLineCRLF(&firstline), 0); - int code = atoi(&firstline[9]); + std::string line; + CHECK_GT(readbuf.TakeLineCRLF(&line), 0); + int code = atoi(&line[line.find(" ") + 1]); - while (output->SkipLineCRLF() > 0) - ; + bool gzip = false; + int contentLength = 0; + while (true) { + int sz = readbuf.TakeLineCRLF(&line); + if (!sz) + break; + if (startsWith(line, "Content-Length:")) { + contentLength = atoi(&line[16]); + } else if (startsWith(line, "Content-Encoding:")) { + if (line.find("gzip") != std::string::npos) { + gzip = true; + } + } + } + + // output now contains the rest of the reply. Dechunk it. + DeChunk(&readbuf, output); + + // If it's gzipped, we decompress it and put it back in the buffer. + if (gzip) { + std::string compressed; + output->TakeAll(&compressed); + // What is this garbage? + //if (compressed[0] == 0x8e) +// compressed = compressed.substr(4); + std::string decompressed; + bool result = decompress_string(compressed, &decompressed); + if (!result) { + ELOG("Error decompressing using zlib"); + return -1; + } + output->Append(decompressed); + } - // output now contains the rest of the reply. return code; } diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 00fd157cf8..9a92458971 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -86,10 +86,11 @@ void UIContext::PopScissor() { void UIContext::ActivateTopScissor() { if (scissorStack_.size()) { const Bounds &bounds = scissorStack_.back(); - int x = g_dpi_scale * bounds.x; - int y = g_dpi_scale * (dp_yres - bounds.y2()); - int w = g_dpi_scale * bounds.w; - int h = g_dpi_scale * bounds.h; + float scale = 1.0f / g_dpi_scale; + int x = scale * bounds.x; + int y = scale * (dp_yres - bounds.y2()); + int w = scale * bounds.w; + int h = scale * bounds.h; glstate.scissorRect.set(x,y,w,h); glstate.scissorTest.enable(); diff --git a/ui/viewgroup.h b/ui/viewgroup.h index b9bb0038bd..1ad1a4a067 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -109,7 +109,7 @@ private: class LinearLayout : public ViewGroup { public: LinearLayout(Orientation orientation, LayoutParams *layoutParams = 0) - : ViewGroup(layoutParams), spacing_(5), orientation_(orientation), defaultMargins_(0) {} + : ViewGroup(layoutParams), orientation_(orientation), defaultMargins_(0), spacing_(10) {} void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); @@ -153,7 +153,13 @@ private: class ScrollView : public ViewGroup { public: ScrollView(Orientation orientation, LayoutParams *layoutParams = 0) : - ViewGroup(layoutParams), orientation_(orientation), scrollPos_(0), scrollTarget_(0), scrollToTarget_(false) {} + ViewGroup(layoutParams), + orientation_(orientation), + scrollPos_(0), + scrollStart_(0), + scrollMax_(0), + scrollTarget_(0), + scrollToTarget_(false) {} void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); From 04f6a3503110d29aa41577a9e443a0ffd029067a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 4 Jun 2013 23:53:41 +0200 Subject: [PATCH 0434/1445] More logging, making things slightly more robust somehow (fixed a hang issue without knowing what actually fixed it..) --- android/app-android.cpp | 41 ++++++++--- android/native-audio-so.cpp | 17 ++++- android/native_audio.cpp | 72 +++++++++++++------ .../libnative/NativeActivity.java | 17 ++++- .../henrikrydgard/libnative/NativeApp.java | 3 +- file/zip_read.cpp | 2 +- ui/view.h | 11 ++- 7 files changed, 125 insertions(+), 38 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 9fb4009f0d..9bc0009a77 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -53,6 +53,8 @@ static uint32_t pad_buttons_async_set; static uint32_t pad_buttons_async_clear; static float left_joystick_x_async; static float left_joystick_y_async; +static float right_joystick_x_async; +static float right_joystick_y_async; static uint32_t pad_buttons_down; @@ -148,6 +150,11 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init pad_buttons_async_set = 0; pad_buttons_async_clear = 0; + left_joystick_x_async = 0; + left_joystick_y_async = 0; + right_joystick_x_async = 0; + right_joystick_y_async = 0; + std::string apkPath = GetJavaString(env, japkpath); ILOG("NativeApp::Init: APK path: %s", apkPath.c_str()); VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); @@ -178,6 +185,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init use_native_audio = juseNativeAudio; if (use_native_audio) { + ILOG("Using OpenSL audio!"); AndroidAudio_Init(&NativeMix, library_path); } ILOG("NativeApp.init() -- end"); @@ -195,6 +203,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclas if (use_native_audio) { AndroidAudio_Pause(); } + ILOG("NativeApp.pause() - paused audio"); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { @@ -294,6 +303,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN } } +// This path is not used if OpenSL ES is available. extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { // Too spammy // ILOG("NativeApp.audioRender"); @@ -319,8 +329,7 @@ extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* e extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch (JNIEnv *, jclass, float x, float y, int code, int pointerId) { - ELOG("Touch Enter %i", pointerId); - lock_guard guard(input_state.lock); + // ELOG("Touch Enter %i", pointerId); float scaledX = (int)(x * dp_xscale); // why the (int) cast? float scaledY = (int)(y * dp_yscale); @@ -338,6 +347,10 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch } else { touch.flags = TOUCH_MOVE; } + NativeTouch(touch); + + + lock_guard guard(input_state.lock); if (pointerId >= MAX_POINTERS) { ELOG("Too many pointers: %i", pointerId); @@ -346,16 +359,16 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch input_state.pointer_x[pointerId] = scaledX; input_state.pointer_y[pointerId] = scaledY; input_state.mouse_valid = true; - NativeTouch(touch); - ELOG("Touch Exit %i", pointerId); + + // ELOG("Touch Exit %i", pointerId); } -static void AsyncDown(int padbutton) { +static inline void AsyncDown(int padbutton) { pad_buttons_async_set |= padbutton; pad_buttons_async_clear &= ~padbutton; } -static void AsyncUp(int padbutton) { +static inline void AsyncUp(int padbutton) { pad_buttons_async_set &= ~padbutton; pad_buttons_async_clear |= padbutton; } @@ -415,9 +428,19 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclas } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickEvent( - JNIEnv *env, jclass, jfloat x, jfloat y) { - left_joystick_x_async = x; - left_joystick_y_async = y; + JNIEnv *env, jclass, jint stick, jfloat x, jfloat y) { + if (stick == 0) { + left_joystick_x_async = x; + left_joystick_y_async = y; + } else if (stick == 1) { + right_joystick_x_async = x; + right_joystick_y_async = y; + } +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_mouseWheelEvent( + JNIEnv *env, jclass, jint stick, jfloat x, jfloat y) { + // TODO } extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) { diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 0fba729dc9..d399103c53 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -136,6 +136,13 @@ extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb) { // shut down the native audio system extern "C" void OpenSLWrap_Shutdown() { + SLresult result; + ILOG("OpenSLWrap_Shutdown - stopping playback"); + result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); + assert(SL_RESULT_SUCCESS == result); + + ILOG("OpenSLWrap_Shutdown - deleting player object"); + if (bqPlayerObject != NULL) { (*bqPlayerObject)->Destroy(bqPlayerObject); bqPlayerObject = NULL; @@ -144,13 +151,21 @@ extern "C" void OpenSLWrap_Shutdown() { bqPlayerMuteSolo = NULL; bqPlayerVolume = NULL; } + + ILOG("OpenSLWrap_Shutdown - deleting mix object"); + if (outputMixObject != NULL) { (*outputMixObject)->Destroy(outputMixObject); outputMixObject = NULL; } + + ILOG("OpenSLWrap_Shutdown - deleting engine object"); + if (engineObject != NULL) { (*engineObject)->Destroy(engineObject); engineObject = NULL; engineEngine = NULL; } -} + ILOG("OpenSLWrap_Shutdown - finished"); +} + diff --git a/android/native_audio.cpp b/android/native_audio.cpp index 871a2ca67a..cb92e1ee3f 100644 --- a/android/native_audio.cpp +++ b/android/native_audio.cpp @@ -5,54 +5,84 @@ #include "android/native_audio.h" #include "android/native-audio-so.h" -static void *so; -static AndroidAudioCallback s_cb; -static OpenSLWrap_Init_T init_func; -static OpenSLWrap_Shutdown_T shutdown_func; -static bool playing; +struct AudioState { + void *so; + AndroidAudioCallback s_cb; + OpenSLWrap_Init_T init_func; + OpenSLWrap_Shutdown_T shutdown_func; + bool playing; +}; + +static AudioState *state = 0; bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir) { - s_cb = cb; - playing = false; + if (state != 0) { + ELOG("Audio state already exists"); + return false; + } + ILOG("Loading native audio library..."); std::string so_filename = libraryDir + "/libnative_audio.so"; - so = dlopen(so_filename.c_str(), RTLD_LAZY); - if (!so) { + void *the_so = dlopen(so_filename.c_str(), RTLD_LAZY); + if (!the_so) { ELOG("Failed to find native audio library: %i: %s ", errno, dlerror()); return false; } - init_func = (OpenSLWrap_Init_T)dlsym(so, "OpenSLWrap_Init"); - shutdown_func = (OpenSLWrap_Shutdown_T)dlsym(so, "OpenSLWrap_Shutdown"); + + state = new AudioState(); + state->so = the_so; + state->s_cb = cb; + state->playing = false; + state->init_func = (OpenSLWrap_Init_T)dlsym(state->so, "OpenSLWrap_Init"); + state->shutdown_func = (OpenSLWrap_Shutdown_T)dlsym(state->so, "OpenSLWrap_Shutdown"); + ILOG("OpenSLWrap init_func: %p shutdown_func: %p", (void *)state->init_func, (void *)state->shutdown_func); + return true; } bool AndroidAudio_Resume() { - if (!playing) { + if (!state) { + ELOG("Audio was shutdown, cannot resume!"); + return false; + } + if (!state->playing) { ILOG("Calling OpenSLWrap_Init_T..."); - bool init_retval = init_func(s_cb); + bool init_retval = state->init_func(state->s_cb); ILOG("Returned from OpenSLWrap_Init_T"); - playing = true; + state->playing = true; return init_retval; } return false; } bool AndroidAudio_Pause() { - if (playing) { + if (!state) { + ELOG("Audio was shutdown, cannot pause!"); + return false; + } + if (state->playing) { ILOG("Calling OpenSLWrap_Shutdown_T..."); - shutdown_func(); - playing = false; + state->shutdown_func(); + ILOG("Returned from OpenSLWrap_Shutdown_T ..."); + state->playing = false; return true; } return false; } void AndroidAudio_Shutdown() { - if (playing) { + if (!state) { + ELOG("Audio already shutdown!"); + return; + } + if (state->playing) { ELOG("Should not shut down when playing! Something is wrong!"); } - ILOG("Returned from OpenSLWrap_Shutdown_T"); - dlclose(so); - so = 0; + ILOG("dlclose"); + dlclose(state->so); + ILOG("Returned from dlclose"); + state->so = 0; + delete state; + state = 0; ILOG("OpenSLWrap completely unloaded."); } diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 2f2edb526d..29dd063bef 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -207,8 +207,11 @@ public class NativeActivity extends Activity { if (audioPlayer != null) { audioPlayer.stop(); } + Log.i(TAG, "nativeapp pause"); NativeApp.pause(); + Log.i(TAG, "gl pause"); mGLSurfaceView.onPause(); + Log.i(TAG, "onPause returning"); } @Override @@ -297,9 +300,19 @@ public class NativeActivity extends Activity { if (event.getSource() == InputDevice.SOURCE_JOYSTICK) { float leftJoystickX = event.getAxisValue(MotionEvent.AXIS_X) * 1f; float leftJoystickY = event.getAxisValue(MotionEvent.AXIS_Y) * -1f; - NativeApp.joystickEvent(leftJoystickX, leftJoystickY); + NativeApp.joystickEvent(0, leftJoystickX, leftJoystickY); } - return false; + if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { + switch (event.getAction()) { + case MotionEvent.ACTION_HOVER_MOVE: + // process the mouse hover movement... + return true; + case MotionEvent.ACTION_SCROLL: + NativeApp.mouseWheelEvent(event.getX(), event.getY()); + return true; + } + } + return super.onGenericMotionEvent(event); } @SuppressLint("NewApi") diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 79fa414ff5..8b7f0e86e3 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -18,7 +18,8 @@ public class NativeApp { public static native void keyUp(int key); - public static native void joystickEvent(float x, float y); + public static native void joystickEvent(int stick, float x, float y); + public static native void mouseWheelEvent(float x, float y); // will only be called between init() and shutdown() public static native int audioRender(short[] buffer); diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 21b45c193d..02add6f0f8 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -96,7 +96,7 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis const char* name = zip_get_name(zip_file_, i, 0); if (!name) continue; - ILOG("Comparing %s %s %i", name, path, pathlen); + // ILOG("Comparing %s %s %i", name, path, pathlen); if (!memcmp(name, path, pathlen)) { // The prefix is right. Let's see if this is a file or path. char *slashPos = strchr(name + pathlen + 1, '/'); diff --git a/ui/view.h b/ui/view.h index 02b017342c..9bee17ace5 100644 --- a/ui/view.h +++ b/ui/view.h @@ -171,14 +171,19 @@ class Event { public: Event() : triggered_(false) {} - void Add(std::function func); - // Call this from input thread or whatever, it doesn't matter void Trigger(EventParams &e); // Call this from UI thread void Update(); + template + void Handle(T *thiz, EventReturn (T::* theCallback)(EventParams &e)) { + Add(std::bind(theCallback, thiz, placeholder::_1)); + } + private: + void Add(std::function func); + recursive_mutex mutex_; std::vector handlers_; bool triggered_; @@ -421,7 +426,7 @@ class CheckBox : public ClickableItem { public: CheckBox(bool *toggle, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), text_(text), smallText_(smallText) { - OnClick.Add(std::bind(&CheckBox::OnClicked, this, placeholder::_1)); + OnClick.Handle(this, &CheckBox::OnClicked); } virtual void Draw(UIContext &dc); From 628005799f57aff04694d618dc59d1efb0a3fe44 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 6 Jun 2013 03:40:45 +1000 Subject: [PATCH 0435/1445] Meego Harmattan buildfix. --- data/compression.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/compression.cpp b/data/compression.cpp index 1446b4993c..78d7d11259 100644 --- a/data/compression.cpp +++ b/data/compression.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -100,4 +101,4 @@ bool decompress_string(const std::string& str, std::string *dest) { } *dest = outstring; -} \ No newline at end of file +} From c94767905aa6fc1f0853e052948d2ebc27eb1b9b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 5 Jun 2013 21:23:33 +0200 Subject: [PATCH 0436/1445] Add missing return true; --- data/compression.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/data/compression.cpp b/data/compression.cpp index 78d7d11259..63ce4b1dc7 100644 --- a/data/compression.cpp +++ b/data/compression.cpp @@ -101,4 +101,5 @@ bool decompress_string(const std::string& str, std::string *dest) { } *dest = outstring; + return true; } From 8e5890a7e28af03f237eafaaa25e7a10d16899da Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 8 Jun 2013 17:43:27 +0200 Subject: [PATCH 0437/1445] Warning fixes, add deleteDir() --- audio/mixer.cpp | 2 +- file/chunk_file.cpp | 4 ++-- file/easy_file.cpp | 4 ++-- file/easy_file.h | 4 ++-- file/file_util.cpp | 18 +++++++++++++++++- file/file_util.h | 1 + file/zip_read.cpp | 12 ++++++------ image/zim_load.cpp | 2 +- 8 files changed, 32 insertions(+), 15 deletions(-) diff --git a/audio/mixer.cpp b/audio/mixer.cpp index de19807f4b..45d6c4c3b2 100644 --- a/audio/mixer.cpp +++ b/audio/mixer.cpp @@ -98,7 +98,7 @@ Clip *clip_load(const char *filename) { uint8_t *filedata; size_t size; filedata = VFSReadFile(filename, &size); - num_samples = stb_vorbis_decode_memory(filedata, size, &num_channels, &data); + num_samples = (int)stb_vorbis_decode_memory(filedata, size, &num_channels, &data); if (num_samples <= 0) return NULL; sample_rate = 44100; diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index 738c32ad27..396b07753b 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -216,7 +216,7 @@ void ChunkFile::writeWString(String str) { void ChunkFile::writeWString(const std::string &str) { unsigned short *text; - int len=str.length(); + size_t len = str.length(); #ifdef UNICODE #error text = str.c_str(); @@ -234,7 +234,7 @@ void ChunkFile::writeWString(const std::string &str) { } static void toUnicode(const std::string &str, uint16 *t) { - for (int i=0; i<(int)str.size(); i++) { + for (size_t i = 0; i < str.size(); i++) { *t++ = str[i]; } *t++ = '\0'; diff --git a/file/easy_file.cpp b/file/easy_file.cpp index 30851dff43..f8d73d125b 100644 --- a/file/easy_file.cpp +++ b/file/easy_file.cpp @@ -49,7 +49,7 @@ std::string LAMEFile::readAll() { return s; } -int LAMEFile::write(const void *data, int size) { +int LAMEFile::write(const void *data, size_t size) { if (isOpen) { return fwrite(data, 1, size, file_); //we return the number of bytes that actually got written } else { @@ -57,7 +57,7 @@ int LAMEFile::write(const void *data, int size) { } } -int LAMEFile::read(void *data, int size) { +int LAMEFile::read(void *data, size_t size) { if (isOpen) { return fread(data, 1, size, file_); } else { diff --git a/file/easy_file.h b/file/easy_file.h index b7114050bd..fbc439adf9 100644 --- a/file/easy_file.h +++ b/file/easy_file.h @@ -29,14 +29,14 @@ public: void writeInt(int i); void writeChar(char i); - int write(const void *data, int size); + int write(const void *data, size_t size); void write(const std::string &str) { write((void *)str.data(), str.size()); } int readInt(); char readChar(); - int read(void *data, int size); + int read(void *data, size_t size); std::string readAll(); diff --git a/file/file_util.cpp b/file/file_util.cpp index 681a6464b8..c95422841a 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -171,11 +171,13 @@ bool getFileInfo(const char *path, FileInfo *fileInfo) if (!GetFileAttributesExA(path, GetFileExInfoStandard, &attrs)) { fileInfo->size = 0; fileInfo->isDirectory = false; + fileInfo->exists = false; return false; } fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32); fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0; + fileInfo->exists = true; #else struct stat64 file_info; @@ -186,12 +188,14 @@ bool getFileInfo(const char *path, FileInfo *fileInfo) if (result < 0) { WLOG("IsDirectory: stat failed on %s", path); + fileInfo->exists = false; return false; } fileInfo->isDirectory = S_ISDIR(file_info.st_mode); fileInfo->isWritable = false; fileInfo->size = file_info.st_size; + fileInfo->exists = true; // HACK: approximation if (file_info.st_mode & 0200) fileInfo->isWritable = true; @@ -303,13 +307,25 @@ void deleteFile(const char *file) } #endif } + +void deleteDir(const char *dir) +{ +#ifdef _WIN32 + if (!RemoveDirectory(dir)) { + ELOG("Error deleting directory %s: %i", dir, GetLastError()); + } +#else + rmdir(dir); +#endif +} + #endif std::string getDir(const std::string &path) { if (path == "/") return path; - int n = path.size() - 1; + int n = (int)path.size() - 1; while (n >= 0 && path[n] != '\\' && path[n] != '/') n--; std::string cutpath = n > 0 ? path.substr(0, n) : ""; diff --git a/file/file_util.h b/file/file_util.h index b17a804d07..867f1a9d3a 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -37,6 +37,7 @@ std::string getFileExtension(const std::string &fn); bool getFileInfo(const char *path, FileInfo *fileInfo); size_t getFilesInDir(const char *directory, std::vector *files, const char *filter = 0); void deleteFile(const char *file); +void deleteDir(const char *file); bool exists(const std::string &filename); void mkDir(const std::string &path); std::string getDir(const std::string &path); diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 02add6f0f8..cb210b703f 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -236,9 +236,9 @@ void VFSShutdown() { } uint8_t *VFSReadFile(const char *filename, size_t *size) { - int fn_len = strlen(filename); + int fn_len = (int)strlen(filename); for (int i = 0; i < num_entries; i++) { - int prefix_len = strlen(entries[i].prefix); + int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); @@ -256,9 +256,9 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter) { - int fn_len = strlen(path); + int fn_len = (int)strlen(path); for (int i = 0; i < num_entries; i++) { - int prefix_len = strlen(entries[i].prefix); + int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(path, entries[i].prefix, prefix_len)) { if (entries[i].reader->GetFileListing(path + prefix_len, listing, filter)) @@ -273,9 +273,9 @@ bool VFSGetFileListing(const char *path, std::vector *listing, const c bool VFSGetFileInfo(const char *path, FileInfo *info) { - int fn_len = strlen(path); + int fn_len = (int)strlen(path); for (int i = 0; i < num_entries; i++) { - int prefix_len = strlen(entries[i].prefix); + int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(path, entries[i].prefix, prefix_len)) { return entries[i].reader->GetFileInfo(path + prefix_len, info); diff --git a/image/zim_load.cpp b/image/zim_load.cpp index 7b5bf3e859..5f78345ed5 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -147,7 +147,7 @@ int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t if (!buffer) { return 0; } - int retval = LoadZIMPtr(buffer, size, width, height, format, image); + int retval = LoadZIMPtr(buffer, (int)size, width, height, format, image); if (!retval) { ELOG("Not a valid ZIM file: %s", filename); } From 166acebeffb5b90efc0e40704943731aedee9969 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 8 Jun 2013 22:41:17 +0200 Subject: [PATCH 0438/1445] A lot of NewUI work: layout and focus fixes, "TabHolder" --- input/gesture_detector.cpp | 2 +- input/input_state.h | 1 + math/geom2d.h | 3 ++ ui/ui_context.cpp | 40 ++++++++++++++++----------- ui/ui_context.h | 7 +++++ ui/ui_screen.cpp | 29 ++++++++++++++------ ui/ui_screen.h | 8 ++++-- ui/view.cpp | 42 +++++++++++++++++++++++----- ui/view.h | 45 +++++++++++++++++++++++++----- ui/viewgroup.cpp | 56 +++++++++++++++++++++++++++----------- ui/viewgroup.h | 45 ++++++++++++++++++++++++++++++ 11 files changed, 221 insertions(+), 57 deletions(-) diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 852b8fae60..585e077adb 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -37,7 +37,7 @@ TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds active_ |= GESTURE_DRAG_VERTICAL; // Kill the drag TouchInput inp2 = touch; - inp2.flags = TOUCH_UP; + inp2.flags = TOUCH_UP | TOUCH_CANCEL; return inp2; } } else { diff --git a/input/input_state.h b/input/input_state.h index 11903f651e..5be7b48280 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -98,6 +98,7 @@ enum { TOUCH_MOVE = 1, TOUCH_DOWN = 2, TOUCH_UP = 4, + TOUCH_CANCEL = 8, // Sent by scrollviews to their children when they detect a scroll }; // Used for asynchronous touch input. diff --git a/math/geom2d.h b/math/geom2d.h index fd8357de40..4e0749746d 100644 --- a/math/geom2d.h +++ b/math/geom2d.h @@ -24,6 +24,9 @@ struct Point { // Resolved bounds on screen after layout. struct Bounds { + Bounds() {} + Bounds(float x_, float y_, float w_, float h_) : x(x_), y(y_), w(w_), h(h_) {} + bool Contains(float px, float py) const { return (px >= x && py >= y && px < x + w && py < y + h); } diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 9a92458971..8751109c21 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -1,12 +1,12 @@ -#include "ui.h" -#include "ui_context.h" +#include "ui/ui.h" +#include "ui/view.h" +#include "ui/ui_context.h" #include "gfx/texture.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/glsl_program.h" #include "gfx_es2/gl_state.h" -void UIContext::Begin() -{ +void UIContext::Begin() { glstate.blend.enable(); glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glstate.cullFace.disable(); @@ -24,8 +24,7 @@ void UIContext::Begin() uidrawbufferTop_->Begin();*/ } -void UIContext::BeginNoTex() -{ +void UIContext::BeginNoTex() { glstate.blend.enable(); glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glstate.cullFace.disable(); @@ -44,28 +43,23 @@ void UIContext::BeginNoTex() } -void UIContext::RebindTexture() const -{ +void UIContext::RebindTexture() const { if (uitexture_) uitexture_->Bind(0); } -void UIContext::Flush() -{ - if (uidrawbuffer_) - { +void UIContext::Flush() { + if (uidrawbuffer_) { uidrawbuffer_->End(); uidrawbuffer_->Flush(); } - if (uidrawbufferTop_) - { + if (uidrawbufferTop_) { uidrawbufferTop_->End(); uidrawbufferTop_->Flush(); } } -void UIContext::End() -{ +void UIContext::End() { UIEnd(); Flush(); } @@ -97,4 +91,18 @@ void UIContext::ActivateTopScissor() { } else { glstate.scissorTest.disable(); } +} + +void UIContext::FillRect(const UI::Drawable &drawable, const Bounds &bounds) { + switch (drawable.type) { + case UI::DRAW_SOLID_COLOR: + uidrawbuffer_->DrawImageStretch(theme->whiteImage, bounds.x, bounds.y, bounds.x2(), bounds.y2(), drawable.color); + break; + case UI::DRAW_4GRID: + uidrawbuffer_->DrawImage4Grid(drawable.image, bounds.x, bounds.y, bounds.x2(), bounds.y2(), drawable.color); + break; + case UI::DRAW_STRETCH_IMAGE: + uidrawbuffer_->DrawImageStretch(drawable.image, bounds.x, bounds.y, bounds.x2(), bounds.y2(), drawable.color); + break; + } } \ No newline at end of file diff --git a/ui/ui_context.h b/ui/ui_context.h index 5552290f98..ed9e17aa40 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -14,6 +14,7 @@ class DrawBuffer; // Kind of ugly connection to UI. namespace UI { + struct Drawable; struct Theme; } @@ -49,6 +50,12 @@ public: const UI::Theme *theme; + + // Utility methods + void FillRect(const UI::Drawable &drawable, const Bounds &bounds); + + + private: // TODO: Collect these into a UIContext const GLSLProgram *uishader_; diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 09fe04791b..5a0389ed3a 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -3,12 +3,17 @@ #include "ui/ui_context.h" #include "ui/screen.h" +UIScreen::UIScreen() + : Screen(), root_(0), recreateViews_(false) { + +} + void UIScreen::update(InputState &input) { if (!root_) { CreateViews(); } - if (orientationChanged_) { + if (recreateViews_) { delete root_; root_ = 0; CreateViews(); @@ -18,17 +23,25 @@ void UIScreen::update(InputState &input) { } void UIScreen::render() { - UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_); + if (root_) { + UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_); - screenManager()->getUIContext()->Begin(); - DrawBackground(); - root_->Draw(*screenManager()->getUIContext()); - screenManager()->getUIContext()->End(); - screenManager()->getUIContext()->Flush(); + screenManager()->getUIContext()->Begin(); + DrawBackground(); + root_->Draw(*screenManager()->getUIContext()); + screenManager()->getUIContext()->End(); + screenManager()->getUIContext()->Flush(); + } else { + ELOG("Tried to render without a view root"); + } } void UIScreen::touch(const TouchInput &touch) { - root_->Touch(touch); + if (root_) { + root_->Touch(touch); + } else { + ELOG("Tried to touch without a view root"); + } } UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { diff --git a/ui/ui_screen.h b/ui/ui_screen.h index e8111d3727..bcf2ab2297 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -5,7 +5,7 @@ class UIScreen : public Screen { public: - UIScreen() : Screen(), root_(0), orientationChanged_(false) {} + UIScreen(); ~UIScreen() { delete root_; } virtual void update(InputState &input); @@ -19,6 +19,10 @@ protected: virtual void CreateViews() = 0; virtual void DrawBackground() {} + void RecreateViews() { recreateViews_ = true; } + UI::ViewGroup *root_; - bool orientationChanged_; + +private: + bool recreateViews_; }; diff --git a/ui/view.cpp b/ui/view.cpp index 2a73699012..1f57254942 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -2,6 +2,7 @@ #include "base/mutex.h" #include "input/input_state.h" #include "gfx_es2/draw_buffer.h" +#include "gfx/texture.h" #include "gfx/texture_atlas.h" #include "ui/ui.h" #include "ui/view.h" @@ -117,7 +118,7 @@ void Clickable::Touch(const TouchInput &input) { down_ = bounds_.Contains(input.x, input.y); } if (input.flags & TOUCH_UP) { - if (dragging_ && bounds_.Contains(input.x, input.y)) { + if ((input.flags & TOUCH_CANCEL) == 0 && dragging_ && bounds_.Contains(input.x, input.y)) { Click(); } downCountDown_ = 0; @@ -159,15 +160,18 @@ ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParam } void ClickableItem::Draw(UIContext &dc) { + Style style = dc.theme->itemStyle; if (down_) { - dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.bgColor); + style = dc.theme->itemDownStyle; } else if (HasFocus()) { - dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), dc.theme->itemFocusedStyle.bgColor); + style = dc.theme->itemFocusedStyle; } + dc.FillRect(style.background, bounds_); } void Choice::Draw(UIContext &dc) { ClickableItem::Draw(dc); + int paddingX = 4; int paddingY = 4; dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); @@ -175,16 +179,17 @@ void Choice::Draw(UIContext &dc) { } void InfoItem::Draw(UIContext &dc) { + Item::Draw(dc); int paddingX = 4; int paddingY = 4; dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); - dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor); +// dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor); } void ItemHeader::Draw(UIContext &dc) { dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.y, 0xFF707070, ALIGN_LEFT); - dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.bgColor); + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), 0xFFFFFFFF); } void CheckBox::Draw(UIContext &dc) { @@ -195,7 +200,7 @@ void CheckBox::Draw(UIContext &dc) { int image = *toggle_ ? dc.theme->checkOn : dc.theme->checkOff; dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); - dc.Draw()->DrawImage(image, bounds_.x2() - 4, bounds_.centerY(), 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); + dc.Draw()->DrawImage(image, bounds_.x2() - 4, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); } void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const { @@ -208,7 +213,8 @@ void Button::Draw(UIContext &dc) { if (down_) style = dc.theme->buttonDownStyle; if (!enabled_) style = dc.theme->buttonDisabledStyle; - dc.Draw()->DrawImage4Grid(style.image, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); + // dc.Draw()->DrawImage4Grid(style.image, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); + dc.FillRect(style.background, bounds_); dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); } @@ -224,6 +230,28 @@ void ImageView::Draw(UIContext &dc) { dc.Draw()->DrawImage(atlasImage_, bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF); } +void TextureView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + // TODO: involve sizemode + if (texture_) { + w = (float)texture_->Width(); + h = (float)texture_->Height(); + } else { + w = 16; + h = 16; + } +} + +void TextureView::Draw(UIContext &dc) { + // TODO: involve sizemode + if (texture_) { + dc.Flush(); + texture_->Bind(0); + dc.Draw()->Rect(bounds_.x, bounds_.y, bounds_.w, bounds_.h, color_); + dc.Flush(); + dc.RebindTexture(); + } +} + void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { dc.Draw()->SetFontScale(textScale_, textScale_); dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); diff --git a/ui/view.h b/ui/view.h index 9bee17ace5..eef7e3958e 100644 --- a/ui/view.h +++ b/ui/view.h @@ -24,6 +24,7 @@ struct TouchInput; struct InputState; class DrawBuffer; +class Texture; class UIContext; // I don't generally like namespaces but I think we do need one for UI, so many potentially-clashing names. @@ -42,6 +43,7 @@ enum DrawableType { DRAW_NOTHING, DRAW_SOLID_COLOR, DRAW_4GRID, + DRAW_STRETCH_IMAGE, }; enum Visibility { @@ -51,17 +53,20 @@ enum Visibility { }; struct Drawable { - Drawable() : type(DRAW_NOTHING) {} + Drawable() : type(DRAW_NOTHING), image(-1), color(0xFFFFFFFF) {} + explicit Drawable(uint32_t col) : type(DRAW_SOLID_COLOR), image(-1), color(col) {} + Drawable(DrawableType t, int img, uint32_t col = 0xFFFFFFFF) : type(t), image(img), color(col) {} DrawableType type; - uint32_t data; + uint32_t image; + uint32_t color; }; struct Style { - Style() : fgColor(0xFFFFFFFF), bgColor(0xFF303030), image(-1) {} + Style() : fgColor(0xFFFFFFFF), background(0xFF303030), image(-1) {} uint32_t fgColor; - uint32_t bgColor; + Drawable background; int image; // where applicable. }; @@ -79,6 +84,7 @@ struct Theme { Style buttonDownStyle; Style buttonDisabledStyle; + Style itemStyle; Style itemDownStyle; Style itemFocusedStyle; }; @@ -195,7 +201,9 @@ private: struct Margins { Margins() : top(0), bottom(0), left(0), right(0) {} explicit Margins(uint8_t all) : top(all), bottom(all), left(all), right(all) {} - explicit Margins(uint8_t horiz, uint8_t vert) : top(vert), bottom(vert), left(horiz), right(horiz) {} + Margins(uint8_t horiz, uint8_t vert) : top(vert), bottom(vert), left(horiz), right(horiz) {} + Margins(uint8_t l, uint8_t t, uint8_t r, uint8_t b) : top(t), bottom(b), left(l), right(r) {} + uint8_t top; uint8_t bottom; uint8_t left; @@ -250,6 +258,7 @@ public: // Called when the layout is done. void SetBounds(Bounds bounds) { bounds_ = bounds; } virtual const LayoutParams *GetLayoutParams() const { return layoutParams_.get(); } + virtual void ReplaceLayoutParams(LayoutParams *newLayoutParams) { layoutParams_.reset(newLayoutParams); } const Bounds &GetBounds() const { return bounds_; } virtual bool SetFocus() { @@ -272,10 +281,14 @@ public: void SetVisibility(Visibility visibility) { visibility_ = visibility; } Visibility GetVisibility() const { return visibility_; } + const std::string &Tag() const { return tag_; } + void SetTag(const std::string &str) { tag_ = str; } + protected: // Inputs to layout scoped_ptr layoutParams_; - + + std::string tag_; bool enabled_; Visibility visibility_; @@ -425,7 +438,7 @@ private: class CheckBox : public ClickableItem { public: CheckBox(bool *toggle, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(smallText) { + : ClickableItem(layoutParams), toggle_(toggle), text_(text), smallText_(smallText) { OnClick.Handle(this, &CheckBox::OnClicked); } @@ -488,6 +501,24 @@ private: ImageSizeMode sizeMode_; }; +class TextureView : public InertView { +public: + TextureView(Texture *texture, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0) + : InertView(layoutParams), texture_(texture), sizeMode_(sizeMode) {} + + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + virtual void Draw(UIContext &dc); + + void SetTexture(Texture *texture) { texture_ = texture; } + void SetColor(uint32_t color) { color_ = color; } + +private: + Texture *texture_; + uint32_t color_; + ImageSizeMode sizeMode_; +}; + + class ProgressBar : public InertView { public: ProgressBar(LayoutParams *layoutParams = 0) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index c47d572638..eda02f61d0 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -3,9 +3,12 @@ #include "ui/ui_context.h" #include "ui/view.h" #include "ui/viewgroup.h" +#include "gfx_es2/draw_buffer.h" namespace UI { +const float ITEM_HEIGHT = 64.f; + void ApplyGravity(const Bounds outer, const Margins &margins, float w, float h, int gravity, Bounds &inner) { inner.w = w - (margins.left + margins.right); inner.h = h - (margins.right + margins.left); @@ -79,6 +82,8 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio return 0.0f; if (destination->GetEnabled() == false) return 0.0f; + if (destination->GetVisibility() != V_VISIBLE) + return 0.0f; float dx = destination->GetBounds().centerX() - origin->GetBounds().centerX(); float dy = destination->GetBounds().centerY() - origin->GetBounds().centerY(); @@ -111,6 +116,11 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, NeighborResult result) { + if (!GetEnabled()) + return result; + if (GetVisibility() != V_VISIBLE) + return result; + // First, find the position of the view in the list. size_t num = -1; for (size_t i = 0; i < views_.size(); i++) { @@ -162,7 +172,7 @@ NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, Nei // Boost neighbors with the same parent if (num != -1) { - result.score += 100.0f; + //result.score += 100.0f; } return result; @@ -196,11 +206,11 @@ void MoveFocus(ViewGroup *root, FocusDirection direction) { } void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { - if (views_.empty()) { - MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); - MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); + MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); + MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); + + if (views_.empty()) return; - } float sum = 0.0f; float maxOther = 0.0f; @@ -226,9 +236,13 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v } if (orientation_ == ORIENT_HORIZONTAL) { - views_[i]->Measure(dc, MeasureSpec(UNSPECIFIED), vert - (float)(margins.top + margins.bottom)); + MeasureSpec v = vert; + if (v.type == UNSPECIFIED) v = MeasureSpec(AT_MOST, measuredHeight_); + views_[i]->Measure(dc, MeasureSpec(UNSPECIFIED, measuredWidth_), vert - (float)(margins.top + margins.bottom)); } else if (orientation_ == ORIENT_VERTICAL) { - views_[i]->Measure(dc, horiz - (float)(margins.left + margins.right), MeasureSpec(UNSPECIFIED)); + MeasureSpec h = horiz; + if (h.type == UNSPECIFIED) h = MeasureSpec(AT_MOST, measuredWidth_); + views_[i]->Measure(dc, h - (float)(margins.left + margins.right), MeasureSpec(UNSPECIFIED, measuredHeight_)); } float amount; @@ -265,8 +279,8 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); - if (linLayoutParams && linLayoutParams->weight > 0.0) - views_[i]->Measure(dc, MeasureSpec(EXACTLY, unit * linLayoutParams->weight), vert); + if (linLayoutParams && linLayoutParams->weight > 0.0f) + views_[i]->Measure(dc, MeasureSpec(EXACTLY, unit * linLayoutParams->weight), MeasureSpec(EXACTLY, measuredHeight_)); } } else { MeasureBySpec(layoutParams_->height, weightZeroSum, vert, &measuredHeight_); @@ -279,8 +293,8 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); - if (linLayoutParams && linLayoutParams->weight) - views_[i]->Measure(dc, horiz, MeasureSpec(EXACTLY, unit * linLayoutParams->weight)); + if (linLayoutParams && linLayoutParams->weight > 0.0f) + views_[i]->Measure(dc, MeasureSpec(EXACTLY, measuredWidth_), MeasureSpec(EXACTLY, unit * linLayoutParams->weight)); } } } @@ -367,9 +381,9 @@ void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); if (orientation_ == ORIENT_HORIZONTAL) { - views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED), vert - (margins.top + margins.bottom)); + views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED), MeasureSpec(AT_MOST, measuredHeight_ - (margins.top + margins.bottom))); } else { - views_[0]->Measure(dc, horiz - (margins.left + margins.right), MeasureSpec(UNSPECIFIED)); + views_[0]->Measure(dc, MeasureSpec(AT_MOST, measuredWidth_ - (margins.left + margins.right)), MeasureSpec(UNSPECIFIED)); } } @@ -491,7 +505,7 @@ void GridLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver // Okay, got the width we are supposed to adjust to. Now we can calculate the number of columns. int numColumns = (measuredWidth_ - settings_.spacing) / (settings_.columnWidth + settings_.spacing); - int numRows = (views_.size() + (numColumns - 1)) / numColumns; + int numRows = (int)(views_.size() + (numColumns - 1)) / numColumns; float estimatedHeight = settings_.rowHeight * numRows; @@ -500,7 +514,7 @@ void GridLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver void AnchorLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); - MeasureBySpec(layoutParams_->height, 0.0f, horiz, &measuredHeight_); + MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); for (size_t i = 0; i < views_.size(); i++) { Size width = WRAP_CONTENT; @@ -582,6 +596,17 @@ void GridLayout::Layout() { } } +EventReturn TabHolder::OnTabClick(EventParams &e) { + tabs_[currentTab_]->SetVisibility(V_GONE); + for (int i = 0; i < tabChoices_.size(); i++) { + if (e.v == tabChoices_[i]) { + currentTab_ = i; + } + } + tabs_[currentTab_]->SetVisibility(V_VISIBLE); + return EVENT_DONE; +} + void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { Bounds rootBounds; rootBounds.x = 0; @@ -599,7 +624,6 @@ void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { root->Layout(); } - void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { if (input_state.pad_buttons_down & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 1ad1a4a067..011e8a27ba 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -2,6 +2,7 @@ #include "base/logging.h" #include "ui/view.h" +#include "math/geom2d.h" #include "input/gesture_detector.h" namespace UI { @@ -93,6 +94,8 @@ public: : LayoutParams(w, h), weight(wgt), gravity(grav), hasMargins_(false) {} LinearLayoutParams(Size w, Size h, float wgt, Gravity grav, const Margins &mgn) : LayoutParams(w, h), weight(wgt), gravity(grav), margins(mgn), hasMargins_(true) {} + LinearLayoutParams(Size w, Size h, const Margins &mgn) + : LayoutParams(w, h), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} LinearLayoutParams(const Margins &mgn) : LayoutParams(WRAP_CONTENT, WRAP_CONTENT), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} @@ -187,6 +190,48 @@ class ViewPager : public ScrollView { public: }; +class TabHolder : public LinearLayout { +public: + TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0) + : LinearLayout(ORIENT_HORIZONTAL, layoutParams), + orientation_(orientation), stripSize_(stripSize), currentTab_(0) { + tabStrip_ = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(stripSize, WRAP_CONTENT)); + Add(tabStrip_); + } + + template + T *AddTab(const std::string &title, T *tabContents) { + tabContents->ReplaceLayoutParams(new LinearLayoutParams(1.0f)); + tabTitles_.push_back(title); + tabs_.push_back(tabContents); + Choice *choice = new Choice(title); + tabStrip_->Add(choice)->OnClick.Handle(this, &TabHolder::OnTabClick); + tabChoices_.push_back(choice); + Add(tabContents); + if (tabs_.size() > 1) + tabContents->SetVisibility(V_GONE); + return tabContents; + } + + void SetCurrentTab(int tab) { + tabs_[currentTab_]->SetVisibility(V_GONE); + currentTab_ = tab; + tabs_[currentTab_]->SetVisibility(V_VISIBLE); + } + +private: + EventReturn OnTabClick(EventParams &e); + + ViewGroup *tabStrip_; + + Orientation orientation_; + int currentTab_; + float stripSize_; + std::vector tabTitles_; + std::vector tabChoices_; + std::vector tabs_; +}; + void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root); void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root); From c448f67b9ddd14f1485eb85daa2a6e111dc4bc06 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Jun 2013 18:59:11 -0700 Subject: [PATCH 0439/1445] Use getaddrinfo() instead of gethostbyname(). The latter is not re-entrant, so not thread-safe. At the same time, support round-robin DNS in a sort of trivial way. --- net/http_client.cpp | 37 +++++++++++++++++++----------------- net/http_client.h | 3 ++- net/resolve.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++-- net/resolve.h | 11 ++++++++--- 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 17e7ac8a35..6c65fce952 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -26,11 +26,13 @@ namespace net { Connection::Connection() - : port_(-1), sock_(-1) { + : port_(-1), sock_(-1), resolved_(NULL) { } Connection::~Connection() { Disconnect(); + if (resolved_ != NULL) + DNSResolveFree(resolved_); } // For whatever crazy reason, htons isn't available on android x86 on the build server. so here we go. @@ -45,21 +47,17 @@ bool Connection::Resolve(const char *host, int port) { host_ = host; port_ = port; - const char *err; - const char *ip = net::DNSResolveTry(host, &err); - if (ip == NULL) { - ELOG("Failed to resolve host %s", host); + char port_str[10]; + snprintf(port_str, sizeof(port_str), "%d", port); + + std::string err; + if (!net::DNSResolve(host, port_str, &resolved_, err)) { + ELOG("Failed to resolve host %s: %s", host, err.c_str()); // So that future calls fail. port_ = 0; return false; } - // VLOG(1) << "Resolved " << host << " to " << ip; - remote_.sin_family = AF_INET; - int tmpres = net::inet_pton(AF_INET, ip, (void *)(&(remote_.sin_addr.s_addr))); - CHECK_GE(tmpres, 0); // << "inet_pton failed"; - CHECK_NE(0, tmpres); // << ip << " not a valid IP address"; - remote_.sin_port = myhtons(port); - free((void *)ip); + return true; } @@ -68,11 +66,16 @@ void Connection::Connect() { sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); CHECK_GE(sock_, 0); - // poll once per second.. should find a way to do this blocking. - int retval = -1; - while (retval < 0) { - retval = connect(sock_, (sockaddr *)&remote_, sizeof(struct sockaddr)); - if (retval >= 0) break; + for (int tries = 100; tries > 0; --tries) { + for (addrinfo *possible = resolved_; possible != NULL; possible = possible->ai_next) { + // TODO: Could support ipv6 without huge difficulty... + if (possible->ai_family != AF_INET) + continue; + + int retval = connect(sock_, possible->ai_addr, (int)possible->ai_addrlen); + if (retval >= 0) + return; + } #ifdef _WIN32 Sleep(1); #else diff --git a/net/http_client.h b/net/http_client.h index 7a4c71fb2b..5fc1b87b8d 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -16,6 +16,7 @@ #include #endif #include +#include #endif namespace net { @@ -43,7 +44,7 @@ protected: std::string host_; int port_; - sockaddr_in remote_; + addrinfo *resolved_; private: uintptr_t sock_; diff --git a/net/resolve.cpp b/net/resolve.cpp index f8d586715c..d238b7cd5a 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -1,13 +1,15 @@ - #include "net/resolve.h" +#include "net/resolve.h" +#include "base/logging.h" #include #include #include +#include #ifndef _WIN32 #include -#include // gethostbyname +#include #include #else #include @@ -69,6 +71,46 @@ char *DNSResolve(const char *host) return ip; } +bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error) +{ + addrinfo hints = {0}; + // TODO: Might be uses to lookup other values. + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; + hints.ai_protocol = IPPROTO_TCP; + + const char *servicep = service.length() == 0 ? NULL : service.c_str(); + + *res = NULL; + int result = getaddrinfo(host.c_str(), servicep, &hints, res); + if (result == EAI_AGAIN) + { + // Temporary failure. Since this already blocks, let's just try once more. +#ifdef _WIN32 + Sleep(1); +#else + sleep(1); +#endif + result = getaddrinfo(host.c_str(), servicep, &hints, res); + } + + if (result != 0) + { + error = gai_strerror(result); + if (*res != NULL) + freeaddrinfo(*res); + *res = NULL; + return false; + } + + return true; +} + +void DNSResolveFree(addrinfo *res) +{ + freeaddrinfo(res); +} + int inet_pton(int af, const char* src, void* dst) { if (af == AF_INET) diff --git a/net/resolve.h b/net/resolve.h index 4a82d84971..46a8b3e598 100644 --- a/net/resolve.h +++ b/net/resolve.h @@ -1,5 +1,8 @@ -#ifndef _NET_RESOLVE_H -#define _NET_RESOLVE_H +#pragma once + +#include + +struct addrinfo; namespace net { @@ -11,6 +14,8 @@ void Shutdown(); char *DNSResolveTry(const char *host, const char **err); char *DNSResolve(const char *host); +bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error); +void DNSResolveFree(addrinfo *res); + int inet_pton(int af, const char* src, void* dst); } // namespace net -#endif From 2143b5b6089496212d6366275b319e4bc2c642ae Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 9 Jun 2013 01:21:08 +0200 Subject: [PATCH 0440/1445] Minor fixes. Use OutputDebugString for native logging on Windows. --- base/logging.h | 12 ++++++++++++ base/stringutil.cpp | 5 +++++ math/geom2d.h | 2 +- ui/screen.cpp | 17 +++++++++-------- ui/screen.h | 12 +++++++----- ui/ui_screen.cpp | 7 ++----- ui/view.h | 3 ++- ui/viewgroup.cpp | 11 +++++++---- 8 files changed, 45 insertions(+), 24 deletions(-) diff --git a/base/logging.h b/base/logging.h index e21ccf7ae2..2e0dbd3992 100644 --- a/base/logging.h +++ b/base/logging.h @@ -11,6 +11,7 @@ #undef Crash +#include // Logging #ifdef _WIN32 @@ -61,7 +62,17 @@ inline void Crash() { #else +#ifdef _WIN32 + +void __ods__(const char *p); + +#define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "I: " __VA_ARGS__); p += sprintf(p, "\n"); __ods__(temp);} +#define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "W: " __VA_ARGS__); p += sprintf(p, "\n"); __ods__(temp);} +#define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "E: " __VA_ARGS__); p += sprintf(p, "\n"); __ods__(temp);} +#define FLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "F: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "F: " __VA_ARGS__); p += sprintf(p, "\n"); __ods__(temp); Crash();} + // TODO: Win32 version using OutputDebugString +#else #include @@ -70,6 +81,7 @@ inline void Crash() { #define ELOG(...) {printf("E: %s:%i: ", __FILE__, __LINE__); printf("E: " __VA_ARGS__); printf("\n");} #define FLOG(...) {printf("F: %s:%i: ", __FILE__, __LINE__); printf("F: " __VA_ARGS__); printf("\n"); Crash();} +#endif #endif #undef CHECK diff --git a/base/stringutil.cpp b/base/stringutil.cpp index 69a4844f29..f229569671 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -15,6 +16,10 @@ #define strcasecmp _stricmp #endif +void __ods__(const char *p) { + OutputDebugString(p); +} + unsigned int parseHex(const char *_szValue) { int Value = 0; diff --git a/math/geom2d.h b/math/geom2d.h index 4e0749746d..d72dd0ae29 100644 --- a/math/geom2d.h +++ b/math/geom2d.h @@ -24,7 +24,7 @@ struct Point { // Resolved bounds on screen after layout. struct Bounds { - Bounds() {} + Bounds() : x(0), y(0), w(0), h(0) {} Bounds(float x_, float y_, float w_, float h_) : x(x_), y(y_), w(w_), h(h_) {} bool Contains(float px, float py) const { diff --git a/ui/screen.cpp b/ui/screen.cpp index db81e59155..63774199e6 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -46,19 +46,22 @@ void ScreenManager::switchToNext() { } Layer newLayer = {nextScreen_, 0}; stack_.push_back(newLayer); - delete temp.screen; + if (temp.screen) { + ELOG("Deleting screen"); + delete temp.screen; + } nextScreen_ = 0; } void ScreenManager::touch(const TouchInput &touch) { - if (stack_.size()) { + if (!stack_.empty()) { stack_.back().screen->touch(touch); return; } } void ScreenManager::render() { - if (stack_.size()) { + if (!stack_.empty()) { switch (stack_.back().flags) { case LAYER_SIDEMENU: if (stack_.size() == 1) { @@ -88,20 +91,20 @@ void ScreenManager::render() { } void ScreenManager::sendMessage(const char *msg, const char *value) { - if (stack_.size()) + if (!stack_.empty()) stack_.back().screen->sendMessage(msg, value); } void ScreenManager::deviceLost() { - if (stack_.size()) + if (!stack_.empty()) stack_.back().screen->deviceLost(); // Dialogs too? Nah, they should only use the standard UI texture anyway. // TODO: Change this when it becomes necessary. } Screen *ScreenManager::topScreen() { - if (stack_.size()) + if (!stack_.empty()) return stack_.back().screen; else return 0; @@ -109,9 +112,7 @@ Screen *ScreenManager::topScreen() { void ScreenManager::shutdown() { for (auto x = stack_.begin(); x != stack_.end(); x++) - { delete x->screen; - } stack_.clear(); delete nextScreen_; nextScreen_ = 0; diff --git a/ui/screen.h b/ui/screen.h index 54376b2227..ca2983dae2 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -13,9 +13,10 @@ #pragma once -#include +#include #include "base/basictypes.h" +#include "base/logging.h" #include "base/display.h" #include "base/NativeApp.h" @@ -33,8 +34,10 @@ class UIContext; class Screen { public: - Screen(bool isUiScreen = false) : screenManager_(0), isUiScreen_(isUiScreen) { } - virtual ~Screen() {} + Screen() : screenManager_(0) { } + virtual ~Screen() { + screenManager_ = 0; + } virtual void update(InputState &input) = 0; virtual void render() {} @@ -50,7 +53,6 @@ public: private: ScreenManager *screenManager_; - bool isUiScreen_; DISALLOW_COPY_AND_ASSIGN(Screen); }; @@ -110,5 +112,5 @@ private: // Dialog stack. These are shown "on top" of base screens and the Android back button works as expected. // Used for options, in-game menus and other things you expect to be able to back out from onto something. - std::list stack_; + std::vector stack_; }; diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 5a0389ed3a..b55f590c85 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -4,19 +4,16 @@ #include "ui/screen.h" UIScreen::UIScreen() - : Screen(), root_(0), recreateViews_(false) { + : Screen(), root_(0), recreateViews_(true) { } void UIScreen::update(InputState &input) { - if (!root_) { - CreateViews(); - } - if (recreateViews_) { delete root_; root_ = 0; CreateViews(); + recreateViews_ = false; } UpdateViewHierarchy(input, root_); diff --git a/ui/view.h b/ui/view.h index eef7e3958e..c371122f4c 100644 --- a/ui/view.h +++ b/ui/view.h @@ -12,6 +12,7 @@ #include #include +#include "base/logging.h" #include "base/functional.h" #include "base/mutex.h" #include "base/basictypes.h" @@ -227,7 +228,7 @@ View *GetFocusedView(); class View { public: - View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), enabled_(true), visibility_(V_VISIBLE) { + View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), enabled_(true), visibility_(V_VISIBLE), measuredWidth_(0), measuredHeight_(0) { if (!layoutParams) layoutParams_.reset(new LayoutParams()); } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index eda02f61d0..00f314043c 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -28,8 +28,11 @@ void ApplyGravity(const Bounds outer, const Margins &margins, float w, float h, ViewGroup::~ViewGroup() { // Tear down the contents recursively. - for (auto iter = views_.begin(); iter != views_.end(); ++iter) - delete *iter; + for (size_t i = 0; i < views_.size(); i++) { + delete views_[i]; + views_[i] = 0; + } + views_.clear(); } void ViewGroup::Touch(const TouchInput &input) { @@ -530,12 +533,12 @@ void AnchorLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v if (params->left >= 0 && params->right >= 0) { width = measuredWidth_ - params->left - params->right; - specW = MeasureSpec(EXACTLY, width); } if (params->top >= 0 && params->bottom >= 0) { height = measuredHeight_ - params->top - params->bottom; - specH = MeasureSpec(EXACTLY, height); } + specW = MeasureSpec(EXACTLY, width); + specH = MeasureSpec(EXACTLY, height); } views_[i]->Measure(dc, specW, specH); From bc2a18eeeef66c5ab37d3efd08d5c2e0001cfa4a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 9 Jun 2013 11:18:57 +0200 Subject: [PATCH 0441/1445] Add ListView, make FrameLayout do something --- ui/screen.cpp | 12 +++++++--- ui/screen.h | 2 ++ ui/ui_screen.cpp | 2 +- ui/ui_screen.h | 2 +- ui/view.cpp | 13 ++++++++++- ui/view.h | 14 ++++------- ui/viewgroup.cpp | 60 +++++++++++++++++++++++++++++++++++++++++------- ui/viewgroup.h | 39 ++++++++++++++++++++++++++++++- 8 files changed, 120 insertions(+), 24 deletions(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index 63774199e6..7bd05e619c 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -95,8 +95,7 @@ void ScreenManager::sendMessage(const char *msg, const char *value) { stack_.back().screen->sendMessage(msg, value); } -void ScreenManager::deviceLost() -{ +void ScreenManager::deviceLost() { if (!stack_.empty()) stack_.back().screen->deviceLost(); // Dialogs too? Nah, they should only use the standard UI texture anyway. @@ -124,6 +123,9 @@ void ScreenManager::push(Screen *screen, int layerFlags) { switchToNext(); } screen->setScreenManager(this); + if (screen->isTransparent()) { + layerFlags |= LAYER_TRANSPARENT; + } Layer layer = {screen, layerFlags}; stack_.push_back(layer); } @@ -157,7 +159,11 @@ void ScreenManager::processFinishDialog() { } Screen *caller = topScreen(); - caller->dialogFinished(dialogFinished_, dialogResult_); + if (caller) { + caller->dialogFinished(dialogFinished_, dialogResult_); + } else { + ELOG("ERROR: no top screen when finishing dialog"); + } delete dialogFinished_; dialogFinished_ = 0; } diff --git a/ui/screen.h b/ui/screen.h index ca2983dae2..80c8d36650 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -51,6 +51,8 @@ public: virtual void *dialogData() { return 0; } + virtual bool isTransparent() { return false; } + private: ScreenManager *screenManager_; DISALLOW_COPY_AND_ASSIGN(Screen); diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index b55f590c85..8b913e8165 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -24,7 +24,7 @@ void UIScreen::render() { UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_); screenManager()->getUIContext()->Begin(); - DrawBackground(); + DrawBackground(*screenManager()->getUIContext()); root_->Draw(*screenManager()->getUIContext()); screenManager()->getUIContext()->End(); screenManager()->getUIContext()->Flush(); diff --git a/ui/ui_screen.h b/ui/ui_screen.h index bcf2ab2297..ff5dab0255 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -17,7 +17,7 @@ public: protected: virtual void CreateViews() = 0; - virtual void DrawBackground() {} + virtual void DrawBackground(UIContext &dc) {} void RecreateViews() { recreateViews_ = true; } diff --git a/ui/view.cpp b/ui/view.cpp index 1f57254942..87df3a150e 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -154,8 +154,19 @@ Item::Item(LayoutParams *layoutParams) : InertView(layoutParams) { layoutParams_->height = ITEM_HEIGHT; } +void Item::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + w = 0.0f; + h = 0.0f; +} + +void ClickableItem::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + w = 0.0f; + h = 0.0f; +} + ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParams) { - layoutParams_->width = FILL_PARENT; + if (layoutParams_->width == WRAP_CONTENT) + layoutParams_->width = FILL_PARENT; layoutParams_->height = ITEM_HEIGHT; } diff --git a/ui/view.h b/ui/view.h index c371122f4c..bbe0b8b374 100644 --- a/ui/view.h +++ b/ui/view.h @@ -183,14 +183,16 @@ public: // Call this from UI thread void Update(); + // This is suggested for use in most cases. Autobinds, allowing for neat syntax. template void Handle(T *thiz, EventReturn (T::* theCallback)(EventParams &e)) { Add(std::bind(theCallback, thiz, placeholder::_1)); } -private: + // Sometimes you have an already-bound function<>, just use this then. void Add(std::function func); +private: recursive_mutex mutex_; std::vector handlers_; bool triggered_; @@ -381,19 +383,13 @@ private: class Item : public InertView { public: Item(LayoutParams *layoutParams); - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { - w = 0.0f; - h = 0.0f; - } + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; }; class ClickableItem : public Clickable { public: ClickableItem(LayoutParams *layoutParams); - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { - w = 0.0f; - h = 0.0f; - } + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; // Draws the item background. virtual void Draw(UIContext &dc); diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 00f314043c..e93b070cab 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1,4 +1,5 @@ #include "base/display.h" +#include "base/functional.h" #include "base/logging.h" #include "ui/ui_context.h" #include "ui/view.h" @@ -368,7 +369,18 @@ void FrameLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ve } void FrameLayout::Layout() { + for (size_t i = 0; i < views_.size(); i++) { + float w = views_[i]->GetMeasuredWidth(); + float h = views_[i]->GetMeasuredHeight(); + Bounds bounds; + bounds.w = w; + bounds.h = h; + + bounds.x = bounds_.x + (measuredWidth_ - w) / 2; + bounds.y = bounds_.y + (measuredWidth_ - h) / 2; + views_[i]->SetBounds(bounds); + } } void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { @@ -537,8 +549,8 @@ void AnchorLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v if (params->top >= 0 && params->bottom >= 0) { height = measuredHeight_ - params->top - params->bottom; } - specW = MeasureSpec(EXACTLY, width); - specH = MeasureSpec(EXACTLY, height); + specW = width < 0 ? MeasureSpec(UNSPECIFIED) : MeasureSpec(EXACTLY, width); + specH = height < 0 ? MeasureSpec(UNSPECIFIED) : MeasureSpec(EXACTLY, height); } views_[i]->Measure(dc, specW, specH); @@ -562,12 +574,18 @@ void AnchorLayout::Layout() { bottom = params->bottom; } - if (left >= 0) vBounds.x = bounds_.x + left; - if (top >= 0) vBounds.y = bounds_.y + top; - if (right >= 0) vBounds.x = bounds_.x2() - right - vBounds.w; - if (bottom >= 0) vBounds.y = bounds_.y2() - bottom - vBounds.y; + if (left >= 0) + vBounds.x = bounds_.x + left; + else if (right >= 0) + vBounds.x = bounds_.x2() - right - vBounds.w; + + if (top >= 0) + vBounds.y = bounds_.y + top; + else if (bottom >= 0) + vBounds.y = bounds_.y2() - bottom - vBounds.h; views_[i]->SetBounds(vBounds); + views_[i]->Layout(); } } @@ -628,8 +646,7 @@ void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { } void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { - if (input_state.pad_buttons_down & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) - { + if (input_state.pad_buttons_down & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) { EnableFocusMovement(true); if (!GetFocusedView()) { root->SetFocus(); @@ -651,4 +668,31 @@ void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { root->Update(input_state); } +ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) + : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a) { + // Let's not be clever yet, we'll just create them all up front and add them all in. + for (int i = 0; i < adaptor_->GetNumItems(); i++) { + View * v = Add(adaptor_->CreateItemView(i)); + adaptor_->AddEventCallback(v, std::bind(&ListView::OnItemCallback, this, i, placeholder::_1)); + } +} + +EventReturn ListView::OnItemCallback(int num, EventParams &e) { + EventParams ev; + ev.v = e.v; + ev.a = num; + OnChoice.Trigger(ev); + return EVENT_DONE; +} + +View *ChoiceListAdaptor::CreateItemView(int index) { + return new Choice(items_[index]); +} + +bool ChoiceListAdaptor::AddEventCallback(View *view, std::function callback) { + Choice *choice = (Choice *)view; + choice->OnClick.Add(callback); + return EVENT_DONE; +} + } // namespace UI \ No newline at end of file diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 011e8a27ba..8bf8784730 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -51,6 +51,7 @@ protected: }; // A frame layout contains a single child view (normally). +// It simply centers the child view. class FrameLayout : public ViewGroup { public: void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); @@ -65,7 +66,9 @@ enum { class AnchorLayoutParams : public LayoutParams { public: AnchorLayoutParams(Size w, Size h, float l, float t, float r, float b) - : LayoutParams(w, h), left(l), top(t), right(r), bottom(b) {} + : LayoutParams(w, h), left(l), top(t), right(r), bottom(b) { + + } AnchorLayoutParams(float l, float t, float r, float b) : LayoutParams(WRAP_CONTENT, WRAP_CONTENT), left(l), top(t), right(r), bottom(b) {} @@ -232,6 +235,40 @@ private: std::vector tabs_; }; +// Yes, this feels a bit Java-ish... +class ListAdaptor { +public: + virtual ~ListAdaptor() {} + virtual View *CreateItemView(int index) = 0; + virtual int GetNumItems() = 0; + virtual bool AddEventCallback(View *view, std::function callback) { return false; } +}; + +class ChoiceListAdaptor { +public: + ChoiceListAdaptor(const char *items[], int numItems) : items_(items), numItems_(numItems) {} + virtual View *CreateItemView(int index); + virtual int GetNumItems() { return numItems_; } + virtual bool AddEventCallback(View *view, std::function callback); + +private: + const char **items_; + int numItems_; +}; + +// A list view is a scroll view with autogenerated items. +// In the future, it might be smart and load/unload items as they go, but currently not. +class ListView : public ScrollView { +public: + ListView(ListAdaptor *a, LayoutParams *layoutParams); + + Event OnChoice; + +private: + EventReturn OnItemCallback(int num, EventParams &e); + ListAdaptor *adaptor_; +}; + void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root); void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root); From 976ef3b7140cb14ef2cdaba59a12d767abd37483 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 9 Jun 2013 12:40:53 +0200 Subject: [PATCH 0442/1445] Minor fixes --- file/file_util.cpp | 1 + ui/view.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index c95422841a..30666c86fd 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -274,6 +274,7 @@ size_t getFilesInDir(const char *directory, std::vector *files, const info.fullName = std::string(directory) + "/" + virtualName; info.isDirectory = isDirectory(info.fullName); info.exists = true; + info.size = 0; if (!info.isDirectory) { std::string ext = getFileExtension(info.fullName); if (filter) { diff --git a/ui/view.h b/ui/view.h index bbe0b8b374..4d42e9f54d 100644 --- a/ui/view.h +++ b/ui/view.h @@ -185,8 +185,9 @@ public: // This is suggested for use in most cases. Autobinds, allowing for neat syntax. template - void Handle(T *thiz, EventReturn (T::* theCallback)(EventParams &e)) { + T *Handle(T *thiz, EventReturn (T::* theCallback)(EventParams &e)) { Add(std::bind(theCallback, thiz, placeholder::_1)); + return thiz; } // Sometimes you have an already-bound function<>, just use this then. @@ -474,6 +475,7 @@ public: virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); virtual void SetText(const std::string &text) { text_ = text; } + private: int font_; std::string text_; From 1d609c9b0868245f844ad98e026f61fb54c63c5d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 9 Jun 2013 13:01:36 +0200 Subject: [PATCH 0443/1445] Simulate RTTI where needed. --- native.vcxproj | 4 ++++ ui/view.h | 24 +++++++++++++++++++----- ui/viewgroup.cpp | 42 +++++++++++++++++++++++++++--------------- ui/viewgroup.h | 19 ++++++++++--------- 4 files changed, 60 insertions(+), 29 deletions(-) diff --git a/native.vcxproj b/native.vcxproj index b06a52b24a..9b818fe9a0 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -82,6 +82,7 @@ ProgramDatabase true false + false Windows @@ -101,6 +102,7 @@ ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); true false + false Windows @@ -123,6 +125,7 @@ StreamingSIMDExtensions2 Fast true + false Windows @@ -147,6 +150,7 @@ StreamingSIMDExtensions2 Fast true + false Windows diff --git a/ui/view.h b/ui/view.h index 4d42e9f54d..093c518718 100644 --- a/ui/view.h +++ b/ui/view.h @@ -214,17 +214,28 @@ struct Margins { uint8_t right; }; +enum LayoutParamsType { + LP_PLAIN = 0, + LP_LINEAR = 1, + LP_ANCHOR = 2, +}; + // Need a virtual destructor so vtables are created, otherwise RTTI can't work class LayoutParams { public: - LayoutParams() - : width(WRAP_CONTENT), height(WRAP_CONTENT) {} - LayoutParams(Size w, Size h) - : width(w), height(h) {} + LayoutParams(LayoutParamsType type = LP_PLAIN) + : type_(type), width(WRAP_CONTENT), height(WRAP_CONTENT) {} + LayoutParams(Size w, Size h, LayoutParamsType type = LP_PLAIN) + : width(w), height(h), type_(type) {} virtual ~LayoutParams() {} - Size width; Size height; + + // Fake RTTI + bool Is(LayoutParamsType type) const { return type_ == type; } + +private: + LayoutParamsType type_; }; View *GetFocusedView(); @@ -288,6 +299,9 @@ public: const std::string &Tag() const { return tag_; } void SetTag(const std::string &str) { tag_ = str; } + // Fake RTTI + virtual bool IsViewGroup() const { return false; } + protected: // Inputs to layout scoped_ptr layoutParams_; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index e93b070cab..e02cf1cc53 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -169,9 +169,11 @@ NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, Nei // Then go right ahead and see if any of the children contain any better candidates. for (auto iter = views_.begin(); iter != views_.end(); ++iter) { - ViewGroup *vg = dynamic_cast(*iter); - if (vg) - result = vg->FindNeighbor(view, direction, result); + if ((*iter)->IsViewGroup()) { + ViewGroup *vg = static_cast(*iter); + if (vg) + result = vg->FindNeighbor(view, direction, result); + } } // Boost neighbors with the same parent @@ -230,7 +232,9 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v numVisible++; const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); - const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); + const LinearLayoutParams *linLayoutParams = static_cast(layoutParams); + if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; + Margins margins = defaultMargins_; if (linLayoutParams) { @@ -281,7 +285,8 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v // Redistribute the stretchy ones! and remeasure the children! for (size_t i = 0; i < views_.size(); i++) { const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); - const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); + const LinearLayoutParams *linLayoutParams = static_cast(layoutParams); + if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; if (linLayoutParams && linLayoutParams->weight > 0.0f) views_[i]->Measure(dc, MeasureSpec(EXACTLY, unit * linLayoutParams->weight), MeasureSpec(EXACTLY, measuredHeight_)); @@ -295,7 +300,8 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v // Redistribute! and remeasure children! for (size_t i = 0; i < views_.size(); i++) { const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); - const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); + const LinearLayoutParams *linLayoutParams = static_cast(layoutParams); + if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; if (linLayoutParams && linLayoutParams->weight > 0.0f) views_[i]->Measure(dc, MeasureSpec(EXACTLY, measuredWidth_), MeasureSpec(EXACTLY, unit * linLayoutParams->weight)); @@ -326,7 +332,8 @@ void LinearLayout::Layout() { continue; const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); - const LinearLayoutParams *linLayoutParams = dynamic_cast(layoutParams); + const LinearLayoutParams *linLayoutParams = static_cast(layoutParams); + if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; Gravity gravity = G_TOPLEFT; Margins margins = defaultMargins_; @@ -386,9 +393,11 @@ void FrameLayout::Layout() { void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { // Respect margins Margins margins; - const LinearLayoutParams *params = dynamic_cast(views_[0]->GetLayoutParams()); - if (params) { - margins = params->margins; + const LinearLayoutParams *linLayoutParams = static_cast(views_[0]->GetLayoutParams()); + if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; + + if (linLayoutParams) { + margins = linLayoutParams->margins; } // The scroll view itself simply obeys its parent. @@ -407,9 +416,10 @@ void ScrollView::Layout() { // Respect margins Margins margins; - const LinearLayoutParams *params = dynamic_cast(views_[0]->GetLayoutParams()); - if (params) { - margins = params->margins; + const LinearLayoutParams *linLayoutParams = static_cast(views_[0]->GetLayoutParams()); + if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; + if (linLayoutParams) { + margins = linLayoutParams->margins; } scrolled.w = views_[0]->GetMeasuredWidth() - (margins.left + margins.right); @@ -538,7 +548,8 @@ void AnchorLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v MeasureSpec specW(UNSPECIFIED, 0.0f); MeasureSpec specH(UNSPECIFIED, 0.0f); - const AnchorLayoutParams *params = dynamic_cast(views_[i]->GetLayoutParams()); + const AnchorLayoutParams *params = static_cast(views_[i]->GetLayoutParams()); + if (!params->Is(LP_ANCHOR)) params = 0; if (params) { width = params->width; height = params->height; @@ -559,7 +570,8 @@ void AnchorLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v void AnchorLayout::Layout() { for (size_t i = 0; i < views_.size(); i++) { - const AnchorLayoutParams *params = dynamic_cast(views_[i]->GetLayoutParams()); + const AnchorLayoutParams *params = static_cast(views_[i]->GetLayoutParams()); + if (!params->Is(LP_ANCHOR)) params = 0; Bounds vBounds; vBounds.w = views_[i]->GetMeasuredWidth(); diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 8bf8784730..27c40ecda5 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -45,6 +45,7 @@ public: NeighborResult FindNeighbor(View *view, FocusDirection direction, NeighborResult best); virtual bool CanBeFocused() const { return false; } + virtual bool IsViewGroup() const { return true; } protected: std::vector views_; @@ -66,12 +67,12 @@ enum { class AnchorLayoutParams : public LayoutParams { public: AnchorLayoutParams(Size w, Size h, float l, float t, float r, float b) - : LayoutParams(w, h), left(l), top(t), right(r), bottom(b) { + : LayoutParams(w, h, LP_ANCHOR), left(l), top(t), right(r), bottom(b) { } AnchorLayoutParams(float l, float t, float r, float b) - : LayoutParams(WRAP_CONTENT, WRAP_CONTENT), left(l), top(t), right(r), bottom(b) {} + : LayoutParams(WRAP_CONTENT, WRAP_CONTENT, LP_ANCHOR), left(l), top(t), right(r), bottom(b) {} // These are not bounds, but distances from the container edges. // Set to NONE to not attach this edge to the container. @@ -88,19 +89,19 @@ public: class LinearLayoutParams : public LayoutParams { public: LinearLayoutParams() - : LayoutParams(), weight(0.0f), gravity(G_TOPLEFT), hasMargins_(false) {} + : LayoutParams(LP_LINEAR), weight(0.0f), gravity(G_TOPLEFT), hasMargins_(false) {} explicit LinearLayoutParams(float wgt, Gravity grav = G_TOPLEFT) - : LayoutParams(), weight(wgt), gravity(grav), hasMargins_(false) {} + : LayoutParams(LP_LINEAR), weight(wgt), gravity(grav), hasMargins_(false) {} LinearLayoutParams(float wgt, const Margins &mgn) - : LayoutParams(), weight(wgt), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} + : LayoutParams(LP_LINEAR), weight(wgt), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} LinearLayoutParams(Size w, Size h, float wgt = 0.0f, Gravity grav = G_TOPLEFT) - : LayoutParams(w, h), weight(wgt), gravity(grav), hasMargins_(false) {} + : LayoutParams(w, h, LP_LINEAR), weight(wgt), gravity(grav), hasMargins_(false) {} LinearLayoutParams(Size w, Size h, float wgt, Gravity grav, const Margins &mgn) - : LayoutParams(w, h), weight(wgt), gravity(grav), margins(mgn), hasMargins_(true) {} + : LayoutParams(w, h, LP_LINEAR), weight(wgt), gravity(grav), margins(mgn), hasMargins_(true) {} LinearLayoutParams(Size w, Size h, const Margins &mgn) - : LayoutParams(w, h), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} + : LayoutParams(w, h, LP_LINEAR), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} LinearLayoutParams(const Margins &mgn) - : LayoutParams(WRAP_CONTENT, WRAP_CONTENT), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} + : LayoutParams(WRAP_CONTENT, WRAP_CONTENT, LP_LINEAR), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} float weight; Gravity gravity; From 73f587009694f3860f00600dc4c7723de0c1f85e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 9 Jun 2013 13:06:02 +0200 Subject: [PATCH 0444/1445] Android buildfix --- base/stringutil.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/stringutil.cpp b/base/stringutil.cpp index f229569671..2dc4ccea9b 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -1,4 +1,6 @@ +#ifdef _WIN32 #include +#endif #include #include #include @@ -14,11 +16,11 @@ #ifdef _WIN32 // Function Cross-Compatibility #define strcasecmp _stricmp -#endif void __ods__(const char *p) { OutputDebugString(p); } +#endif unsigned int parseHex(const char *_szValue) { From 2f46baa138febef0cb6ef8f1a086056dde09a5f1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 9 Jun 2013 13:39:16 +0200 Subject: [PATCH 0445/1445] Add "\n" parsing to i18n code. Move some code from Common. --- base/stringutil.cpp | 11 ++++ base/stringutil.h | 1 + file/file_util.cpp | 8 +++ file/file_util.h | 2 + i18n/i18n.cpp | 3 +- net/url.cpp | 127 +++++++++++++++++++++++++++++++++++++++++++- net/url.h | 6 ++- 7 files changed, 155 insertions(+), 3 deletions(-) diff --git a/base/stringutil.cpp b/base/stringutil.cpp index 2dc4ccea9b..fa5f4a4c07 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -211,3 +211,14 @@ void SplitString(const std::string& str, const char delim, std::vector& output); +std::string ReplaceAll(std::string input, const std::string& src, const std::string& dest); template static std::string ValueToString(const N value) diff --git a/file/file_util.cpp b/file/file_util.cpp index 30666c86fd..52c2d0ae88 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -342,6 +342,14 @@ std::string getDir(const std::string &path) return cutpath; } +std::string getFilename(std::string path) { + size_t off = getDir(path).size() + 1; + if (off < path.size()) + return path.substr(off); + else + return path; +} + void mkDir(const std::string &path) { #ifdef _WIN32 diff --git a/file/file_util.h b/file/file_util.h index 867f1a9d3a..ed69d8cd86 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -34,6 +34,8 @@ struct FileInfo }; std::string getFileExtension(const std::string &fn); +std::string getDir(const std::string &path); +std::string getFilename(std::string path); bool getFileInfo(const char *path, FileInfo *fileInfo); size_t getFilesInDir(const char *directory, std::vector *files, const char *filter = 0); void deleteFile(const char *file); diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp index 883fd58688..43a3db5626 100644 --- a/i18n/i18n.cpp +++ b/i18n/i18n.cpp @@ -31,7 +31,8 @@ const char *I18NCategory::T(const char *key, const char *def) { void I18NCategory::SetMap(const std::map &m) { for (auto iter = m.begin(); iter != m.end(); ++iter) { if (map_.find(iter->first) == map_.end()) { - map_[iter->first] = I18NEntry(iter->second); + std::string text = ReplaceAll(iter->second, "\\n", "\n"); + map_[iter->first] = I18NEntry(text); } } } diff --git a/net/url.cpp b/net/url.cpp index 7b788260ee..4b1c068f57 100644 --- a/net/url.cpp +++ b/net/url.cpp @@ -19,4 +19,129 @@ void Url::Split() { resource_ = url_.substr(sep); // include the slash! valid_ = protocol_.size() > 1 && host_.size() > 1; -} \ No newline at end of file +} + +// UriDecode and UriEncode are from http://www.codeguru.com/cpp/cpp/string/conversions/print.php/c12759 +// by jinq0123 (November 2, 2006) + +// Uri encode and decode. +// RFC1630, RFC1738, RFC2396 + +// Some compilers don't like to assume (int)-1 will safely cast to (char)-1 as +// the MSBs aren't 0's. Workaround the issue while maintaining table spacing. +#define N1 (char)-1 +const char HEX2DEC[256] = +{ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 0 */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* 1 */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* 2 */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,N1,N1, N1,N1,N1,N1, + + /* 4 */ N1,10,11,12, 13,14,15,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* 5 */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* 6 */ N1,10,11,12, 13,14,15,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* 7 */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + + /* 8 */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* 9 */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* A */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* B */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + + /* C */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* D */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* E */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, + /* F */ N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1, N1,N1,N1,N1 +}; + +std::string UriDecode(const std::string & sSrc) +{ + // Note from RFC1630: "Sequences which start with a percent sign + // but are not followed by two hexadecimal characters (0-9, A-F) are reserved + // for future extension" + + const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); + const size_t SRC_LEN = sSrc.length(); + const unsigned char * const SRC_END = pSrc + SRC_LEN; + const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%' + + char * const pStart = new char[SRC_LEN]; + char * pEnd = pStart; + + while (pSrc < SRC_LAST_DEC) + { + if (*pSrc == '%') + { + char dec1, dec2; + if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)]) + && -1 != (dec2 = HEX2DEC[*(pSrc + 2)])) + { + *pEnd++ = (dec1 << 4) + dec2; + pSrc += 3; + continue; + } + } + + *pEnd++ = *pSrc++; + } + + // the last 2- chars + while (pSrc < SRC_END) + *pEnd++ = *pSrc++; + + std::string sResult(pStart, pEnd); + delete [] pStart; + return sResult; +} + +// Only alphanum is safe. +const char SAFE[256] = +{ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, + + /* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, + /* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, + /* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, + /* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, + + /* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + + /* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 +}; + +std::string UriEncode(const std::string & sSrc) +{ + const char DEC2HEX[16 + 1] = "0123456789ABCDEF"; + const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); + const size_t SRC_LEN = sSrc.length(); + unsigned char * const pStart = new unsigned char[SRC_LEN * 3]; + unsigned char * pEnd = pStart; + const unsigned char * const SRC_END = pSrc + SRC_LEN; + + for (; pSrc < SRC_END; ++pSrc) + { + if (SAFE[*pSrc]) + *pEnd++ = *pSrc; + else + { + // escape this char + *pEnd++ = '%'; + *pEnd++ = DEC2HEX[*pSrc >> 4]; + *pEnd++ = DEC2HEX[*pSrc & 0x0F]; + } + } + + std::string sResult((char *)pStart, (char *)pEnd); + delete [] pStart; + return sResult; +} diff --git a/net/url.h b/net/url.h index 2358dfb446..a5c3b51c35 100644 --- a/net/url.h +++ b/net/url.h @@ -123,4 +123,8 @@ private: std::string host_; std::string resource_; std::string protocol_; -}; \ No newline at end of file +}; + + +std::string UriDecode(const std::string & sSrc); +std::string UriEncode(const std::string & sSrc); From 786480b090572db1414153d6dec3970703b95942 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 9 Jun 2013 22:14:19 +1000 Subject: [PATCH 0446/1445] Buildfix for Blackberry, Symbian --- net/resolve.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/net/resolve.cpp b/net/resolve.cpp index d238b7cd5a..5c739a57d1 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -7,15 +7,19 @@ #include -#ifndef _WIN32 -#include -#include -#include -#else +#ifdef _WIN32 #include #include #undef min #undef max +#else +#if defined(__FreeBSD__) || defined(__SYMBIAN32__) +#include +#else +#include +#endif +#include +#include #endif @@ -76,7 +80,11 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo ** addrinfo hints = {0}; // TODO: Might be uses to lookup other values. hints.ai_socktype = SOCK_STREAM; +#ifdef BLACKBERRY + hints.ai_flags = 0; +#else hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; +#endif hints.ai_protocol = IPPROTO_TCP; const char *servicep = service.length() == 0 ? NULL : service.c_str(); From 3a51252fb9c44f1d95941ce11c5cd53a3d0cf05c Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 9 Jun 2013 22:42:34 +1000 Subject: [PATCH 0447/1445] Buildfix for Symbian, Linux. --- net/resolve.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/net/resolve.cpp b/net/resolve.cpp index 5c739a57d1..9ba7d6634c 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -20,6 +20,7 @@ #endif #include #include +#include #endif From cf7ccddf1e936ec1eeaf34160ec6bfd9c85ece74 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 10 Jun 2013 22:05:58 +0200 Subject: [PATCH 0448/1445] Add horizontal orientation to TabHolder. Don't draw things outside current scissor rect. --- math/geom2d.h | 5 +++++ ui/ui_context.cpp | 8 ++++++++ ui/ui_context.h | 1 + ui/view.cpp | 6 +++++- ui/view.h | 7 ++++++- ui/viewgroup.cpp | 10 +++++++--- ui/viewgroup.h | 4 ++-- 7 files changed, 34 insertions(+), 7 deletions(-) diff --git a/math/geom2d.h b/math/geom2d.h index d72dd0ae29..a2faca80b1 100644 --- a/math/geom2d.h +++ b/math/geom2d.h @@ -30,6 +30,11 @@ struct Bounds { bool Contains(float px, float py) const { return (px >= x && py >= y && px < x + w && py < y + h); } + + bool Intersects(const Bounds &other) const { + return !(x > other.x2() || x2() < other.x || y > other.y2() || y2() < other.y); + } + float x2() const { return x + w; } float y2() const { return y + h; } float centerX() const { return x + w * 0.5f; } diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 8751109c21..34d5edb732 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -77,6 +77,14 @@ void UIContext::PopScissor() { ActivateTopScissor(); } +Bounds UIContext::GetScissorBounds() { + if (!scissorStack_.empty()) + return scissorStack_.back(); + else + return Bounds(0, 0, dp_xres, dp_yres); +} + + void UIContext::ActivateTopScissor() { if (scissorStack_.size()) { const Bounds &bounds = scissorStack_.back(); diff --git a/ui/ui_context.h b/ui/ui_context.h index ed9e17aa40..146d92f106 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -43,6 +43,7 @@ public: // TODO: Support transformed bounds using stencil void PushScissor(const Bounds &bounds); void PopScissor(); + Bounds GetScissorBounds(); void ActivateTopScissor(); diff --git a/ui/view.cpp b/ui/view.cpp index 87df3a150e..476345108c 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -42,7 +42,7 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure *measured = spec.size; } else if (sz == FILL_PARENT) { if (spec.type == UNSPECIFIED) - *measured = 0.0; // We have no value to set + *measured = contentWidth; // We have no value to set else *measured = spec.size; } else if (spec.type == EXACTLY || (spec.type == AT_MOST && *measured > spec.size)) { @@ -180,6 +180,10 @@ void ClickableItem::Draw(UIContext &dc) { dc.FillRect(style.background, bounds_); } +void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); +} + void Choice::Draw(UIContext &dc) { ClickableItem::Draw(dc); diff --git a/ui/view.h b/ui/view.h index 093c518718..9771654901 100644 --- a/ui/view.h +++ b/ui/view.h @@ -133,6 +133,10 @@ enum Orientation { ORIENT_VERTICAL, }; +inline Orientation Opposite(Orientation o) { + if (o == ORIENT_HORIZONTAL) return ORIENT_VERTICAL; else return ORIENT_HORIZONTAL; +} + enum MeasureSpecType { UNSPECIFIED, EXACTLY, @@ -167,7 +171,7 @@ class View; struct EventParams { View *v; uint32_t a, b, x, y; - const char *c; + std::string s; }; struct HandlerRegistration { @@ -416,6 +420,7 @@ public: Choice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), text_(text), smallText_(smallText) {} + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); private: diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index e02cf1cc53..a928c5f7ad 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -47,8 +47,11 @@ void ViewGroup::Touch(const TouchInput &input) { void ViewGroup::Draw(UIContext &dc) { for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. - if ((*iter)->GetVisibility() == V_VISIBLE) - (*iter)->Draw(dc); + if ((*iter)->GetVisibility() == V_VISIBLE) { + // Check if bounds are in current scissor rectangle. + if (dc.GetScissorBounds().Intersects((*iter)->GetBounds())) + (*iter)->Draw(dc); + } } } @@ -530,6 +533,7 @@ void GridLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver // Okay, got the width we are supposed to adjust to. Now we can calculate the number of columns. int numColumns = (measuredWidth_ - settings_.spacing) / (settings_.columnWidth + settings_.spacing); + if (!numColumns) numColumns = 1; int numRows = (int)(views_.size() + (numColumns - 1)) / numColumns; float estimatedHeight = settings_.rowHeight * numRows; @@ -620,7 +624,7 @@ void GridLayout::Layout() { views_[i]->Layout(); x += itemBounds.w; - if (x >= bounds_.w) { + if (x + itemBounds.w >= bounds_.w) { x = 0; y += itemBounds.h + settings_.spacing; } else { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 27c40ecda5..d70d7bf4dd 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -197,9 +197,9 @@ public: class TabHolder : public LinearLayout { public: TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0) - : LinearLayout(ORIENT_HORIZONTAL, layoutParams), + : LinearLayout(Opposite(orientation), layoutParams), orientation_(orientation), stripSize_(stripSize), currentTab_(0) { - tabStrip_ = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(stripSize, WRAP_CONTENT)); + tabStrip_ = new LinearLayout(orientation, new LinearLayoutParams(stripSize, WRAP_CONTENT)); Add(tabStrip_); } From dbdcee2d2554090597a2fb66162082c1cdc14a49 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 10 Jun 2013 23:20:45 +0200 Subject: [PATCH 0449/1445] Android really dislikes the AI_V4MAPPED flag to getaddrinfo. --- net/resolve.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/resolve.cpp b/net/resolve.cpp index 9ba7d6634c..bbc9708f3f 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -83,7 +83,11 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo ** hints.ai_socktype = SOCK_STREAM; #ifdef BLACKBERRY hints.ai_flags = 0; +#elif ANDROID + hints.ai_flags = AI_ADDRCONFIG; #else + // AI_V4MAPPED seems to have issues on some platforms, not sure we should include it: + // http://stackoverflow.com/questions/1408030/what-is-the-purpose-of-the-ai-v4mapped-flag-in-getaddrinfo hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; #endif hints.ai_protocol = IPPROTO_TCP; From 842590a73737000b5822f6003140df0837897085 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 11 Jun 2013 09:30:19 +0200 Subject: [PATCH 0450/1445] Disable AI_V4MAPPED on all platforms. --- net/resolve.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/resolve.cpp b/net/resolve.cpp index bbc9708f3f..4b18a05a3b 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -88,7 +88,7 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo ** #else // AI_V4MAPPED seems to have issues on some platforms, not sure we should include it: // http://stackoverflow.com/questions/1408030/what-is-the-purpose-of-the-ai-v4mapped-flag-in-getaddrinfo - hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; + hints.ai_flags = /*AI_V4MAPPED |*/ AI_ADDRCONFIG; #endif hints.ai_protocol = IPPROTO_TCP; From 2715225db1245141316dda98a7882ffc47e8fa80 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 11 Jun 2013 20:33:41 +0200 Subject: [PATCH 0451/1445] Warning fixes --- ui/view.h | 2 +- ui/viewgroup.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/view.h b/ui/view.h index 9771654901..8825e3e5d2 100644 --- a/ui/view.h +++ b/ui/view.h @@ -228,7 +228,7 @@ enum LayoutParamsType { class LayoutParams { public: LayoutParams(LayoutParamsType type = LP_PLAIN) - : type_(type), width(WRAP_CONTENT), height(WRAP_CONTENT) {} + : width(WRAP_CONTENT), height(WRAP_CONTENT), type_(type) {} LayoutParams(Size w, Size h, LayoutParamsType type = LP_PLAIN) : width(w), height(h), type_(type) {} virtual ~LayoutParams() {} diff --git a/ui/viewgroup.h b/ui/viewgroup.h index d70d7bf4dd..2d460b266d 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -229,8 +229,8 @@ private: ViewGroup *tabStrip_; Orientation orientation_; - int currentTab_; float stripSize_; + int currentTab_; std::vector tabTitles_; std::vector tabChoices_; std::vector tabs_; From be287c71d920645ff1c666b4f03f9217b26e0e31 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 11 Jun 2013 20:34:09 +0200 Subject: [PATCH 0452/1445] Add a bunch of Android controller axises and button constants, for use later. --- android/app-android.cpp | 18 +-- android/app-android.h | 253 ++++++++++++++++++++++++++++++++++++++++ native.vcxproj | 1 + native.vcxproj.filters | 1 + 4 files changed, 256 insertions(+), 17 deletions(-) create mode 100644 android/app-android.h diff --git a/android/app-android.cpp b/android/app-android.cpp index 9bc0009a77..9151bc0487 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -24,23 +24,7 @@ #include "android/native_audio.h" #include "gfx_es2/gl_state.h" -// For Xperia Play support -enum AndroidKeyCodes { - KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed - KEYCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed - KEYCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) - KEYCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed - KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed - KEYCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed - KEYCODE_DPAD_LEFT = 21, - KEYCODE_DPAD_UP = 19, - KEYCODE_DPAD_RIGHT = 22, - KEYCODE_DPAD_DOWN = 20, - KEYCODE_BUTTON_L1 = 102, - KEYCODE_BUTTON_R1 = 103, - KEYCODE_BUTTON_START = 108, - KEYCODE_BUTTON_SELECT = 109, -}; +#include "app-android.h" static JNIEnv *jniEnvUI; diff --git a/android/app-android.h b/android/app-android.h new file mode 100644 index 0000000000..a034ea635b --- /dev/null +++ b/android/app-android.h @@ -0,0 +1,253 @@ +#pragma once + +// For Xperia Play support +enum AndroidKeyCodes { + KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed + KEYCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed + KEYCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) + KEYCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed + KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed + KEYCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed + KEYCODE_DPAD_LEFT = 21, + KEYCODE_DPAD_UP = 19, + KEYCODE_DPAD_RIGHT = 22, + KEYCODE_DPAD_DOWN = 20, + KEYCODE_BUTTON_L1 = 102, + KEYCODE_BUTTON_R1 = 103, + KEYCODE_BUTTON_START = 108, + KEYCODE_BUTTON_SELECT = 109, + KEYCODE_UNKNOWN = 0, + KEYCODE_SOFT_LEFT = 1, + KEYCODE_SOFT_RIGHT = 2, + KEYCODE_HOME = 3, + KEYCODE_BACK = 4, + KEYCODE_CALL = 5, + KEYCODE_ENDCALL = 6, + KEYCODE_0 = 7, + KEYCODE_1 = 8, + KEYCODE_2 = 9, + KEYCODE_3 = 10, + KEYCODE_4 = 11, + KEYCODE_5 = 12, + KEYCODE_6 = 13, + KEYCODE_7 = 14, + KEYCODE_8 = 15, + KEYCODE_9 = 16, + KEYCODE_STAR = 17, + KEYCODE_POUND = 18, + KEYCODE_DPAD_UP = 19, + KEYCODE_DPAD_DOWN = 20, + KEYCODE_DPAD_LEFT = 21, + KEYCODE_DPAD_RIGHT = 22, + KEYCODE_DPAD_CENTER = 23, + KEYCODE_VOLUME_UP = 24, + KEYCODE_VOLUME_DOWN = 25, + KEYCODE_POWER = 26, + KEYCODE_CAMERA = 27, + KEYCODE_CLEAR = 28, + KEYCODE_A = 29, + KEYCODE_B = 30, + KEYCODE_C = 31, + KEYCODE_D = 32, + KEYCODE_E = 33, + KEYCODE_F = 34, + KEYCODE_G = 35, + KEYCODE_H = 36, + KEYCODE_I = 37, + KEYCODE_J = 38, + KEYCODE_K = 39, + KEYCODE_L = 40, + KEYCODE_M = 41, + KEYCODE_N = 42, + KEYCODE_O = 43, + KEYCODE_P = 44, + KEYCODE_Q = 45, + KEYCODE_R = 46, + KEYCODE_S = 47, + KEYCODE_T = 48, + KEYCODE_U = 49, + KEYCODE_V = 50, + KEYCODE_W = 51, + KEYCODE_X = 52, + KEYCODE_Y = 53, + KEYCODE_Z = 54, + KEYCODE_COMMA = 55, + KEYCODE_PERIOD = 56, + KEYCODE_ALT_LEFT = 57, + KEYCODE_ALT_RIGHT = 58, + KEYCODE_SHIFT_LEFT = 59, + KEYCODE_SHIFT_RIGHT = 60, + KEYCODE_TAB = 61, + KEYCODE_SPACE = 62, + KEYCODE_SYM = 63, + KEYCODE_EXPLORER = 64, + KEYCODE_ENVELOPE = 65, + KEYCODE_ENTER = 66, + KEYCODE_DEL = 67, + KEYCODE_GRAVE = 68, + KEYCODE_MINUS = 69, + KEYCODE_EQUALS = 70, + KEYCODE_LEFT_BRACKET = 71, + KEYCODE_RIGHT_BRACKET = 72, + KEYCODE_BACKSLASH = 73, + KEYCODE_SEMICOLON = 74, + KEYCODE_APOSTROPHE = 75, + KEYCODE_SLASH = 76, + KEYCODE_AT = 77, + KEYCODE_NUM = 78, + KEYCODE_HEADSETHOOK = 79, + KEYCODE_FOCUS = 80, + KEYCODE_PLUS = 81, + KEYCODE_MENU = 82, + KEYCODE_NOTIFICATION = 83, + KEYCODE_SEARCH = 84, + KEYCODE_MEDIA_PLAY_PAUSE = 85, + KEYCODE_MEDIA_STOP = 86, + KEYCODE_MEDIA_NEXT = 87, + KEYCODE_MEDIA_PREVIOUS = 88, + KEYCODE_MEDIA_REWIND = 89, + KEYCODE_MEDIA_FAST_FORWARD = 90, + KEYCODE_MUTE = 91, + KEYCODE_PAGE_UP = 92, + KEYCODE_PAGE_DOWN = 93, + KEYCODE_PICTSYMBOLS = 94, + KEYCODE_SWITCH_CHARSET = 95, + KEYCODE_BUTTON_A = 96, + KEYCODE_BUTTON_B = 97, + KEYCODE_BUTTON_C = 98, + KEYCODE_BUTTON_X = 99, + KEYCODE_BUTTON_Y = 100, + KEYCODE_BUTTON_Z = 101, + KEYCODE_BUTTON_L1 = 102, + KEYCODE_BUTTON_R1 = 103, + KEYCODE_BUTTON_L2 = 104, + KEYCODE_BUTTON_R2 = 105, + KEYCODE_BUTTON_THUMBL = 106, + KEYCODE_BUTTON_THUMBR = 107, + KEYCODE_BUTTON_START = 108, + KEYCODE_BUTTON_SELECT = 109, + KEYCODE_BUTTON_MODE = 110, + KEYCODE_ESCAPE = 111, + KEYCODE_FORWARD_DEL = 112, + KEYCODE_CTRL_LEFT = 113, + KEYCODE_CTRL_RIGHT = 114, + KEYCODE_CAPS_LOCK = 115, + KEYCODE_SCROLL_LOCK = 116, + KEYCODE_META_LEFT = 117, + KEYCODE_META_RIGHT = 118, + KEYCODE_FUNCTION = 119, + KEYCODE_SYSRQ = 120, + KEYCODE_BREAK = 121, + KEYCODE_MOVE_HOME = 122, + KEYCODE_MOVE_END = 123, + KEYCODE_INSERT = 124, + KEYCODE_FORWARD = 125, + KEYCODE_MEDIA_PLAY = 126, + KEYCODE_MEDIA_PAUSE = 127, + KEYCODE_MEDIA_CLOSE = 128, + KEYCODE_MEDIA_EJECT = 129, + KEYCODE_MEDIA_RECORD = 130, + KEYCODE_F1 = 131, + KEYCODE_F2 = 132, + KEYCODE_F3 = 133, + KEYCODE_F4 = 134, + KEYCODE_F5 = 135, + KEYCODE_F6 = 136, + KEYCODE_F7 = 137, + KEYCODE_F8 = 138, + KEYCODE_F9 = 139, + KEYCODE_F10 = 140, + KEYCODE_F11 = 141, + KEYCODE_F12 = 142, + KEYCODE_NUM_LOCK = 143, + KEYCODE_NUMPAD_0 = 144, + KEYCODE_NUMPAD_1 = 145, + KEYCODE_NUMPAD_2 = 146, + KEYCODE_NUMPAD_3 = 147, + KEYCODE_NUMPAD_4 = 148, + KEYCODE_NUMPAD_5 = 149, + KEYCODE_NUMPAD_6 = 150, + KEYCODE_NUMPAD_7 = 151, + KEYCODE_NUMPAD_8 = 152, + KEYCODE_NUMPAD_9 = 153, + KEYCODE_NUMPAD_DIVIDE = 154, + KEYCODE_NUMPAD_MULTIPLY = 155, + KEYCODE_NUMPAD_SUBTRACT = 156, + KEYCODE_NUMPAD_ADD = 157, + KEYCODE_NUMPAD_DOT = 158, + KEYCODE_NUMPAD_COMMA = 159, + KEYCODE_NUMPAD_ENTER = 160, + KEYCODE_NUMPAD_EQUALS = 161, + KEYCODE_NUMPAD_LEFT_PAREN = 162, + KEYCODE_NUMPAD_RIGHT_PAREN = 163, + KEYCODE_VOLUME_MUTE = 164, + KEYCODE_INFO = 165, + KEYCODE_CHANNEL_UP = 166, + KEYCODE_CHANNEL_DOWN = 167, + KEYCODE_ZOOM_IN = 168, + KEYCODE_ZOOM_OUT = 169, + KEYCODE_TV = 170, + KEYCODE_WINDOW = 171, + KEYCODE_GUIDE = 172, + KEYCODE_DVR = 173, + KEYCODE_BOOKMARK = 174, + KEYCODE_CAPTIONS = 175, + KEYCODE_SETTINGS = 176, + KEYCODE_TV_POWER = 177, + KEYCODE_TV_INPUT = 178, + KEYCODE_STB_POWER = 179, + KEYCODE_STB_INPUT = 180, + KEYCODE_AVR_POWER = 181, + KEYCODE_AVR_INPUT = 182, + KEYCODE_PROG_RED = 183, + KEYCODE_PROG_GREEN = 184, + KEYCODE_PROG_YELLOW = 185, + KEYCODE_PROG_BLUE = 186, + KEYCODE_APP_SWITCH = 187, + KEYCODE_BUTTON_1 = 188, + KEYCODE_BUTTON_2 = 189, + KEYCODE_BUTTON_3 = 190, + KEYCODE_BUTTON_4 = 191, + KEYCODE_BUTTON_5 = 192, + KEYCODE_BUTTON_6 = 193, + KEYCODE_BUTTON_7 = 194, + KEYCODE_BUTTON_8 = 195, + KEYCODE_BUTTON_9 = 196, + KEYCODE_BUTTON_10 = 197, + KEYCODE_BUTTON_11 = 198, + KEYCODE_BUTTON_12 = 199, + KEYCODE_BUTTON_13 = 200, + KEYCODE_BUTTON_14 = 201, + KEYCODE_BUTTON_15 = 202, + KEYCODE_BUTTON_16 = 203, +}; + +enum AndroidJoystickAxis { + // Field descriptor #15 I + JOYSTICK_AXIS_X = 0, + JOYSTICK_AXIS_Y = 1, + JOYSTICK_AXIS_PRESSURE = 2, + JOYSTICK_AXIS_SIZE = 3, + JOYSTICK_AXIS_TOUCH_MAJOR = 4, + JOYSTICK_AXIS_TOUCH_MINOR = 5, + JOYSTICK_AXIS_TOOL_MAJOR = 6, + JOYSTICK_AXIS_TOOL_MINOR = 7, + JOYSTICK_AXIS_ORIENTATION = 8, + JOYSTICK_AXIS_VSCROLL = 9, + JOYSTICK_AXIS_HSCROLL = 10, + JOYSTICK_AXIS_Z = 11, + JOYSTICK_AXIS_RX = 12, + JOYSTICK_AXIS_RY = 13, + JOYSTICK_AXIS_RZ = 14, + JOYSTICK_AXIS_HAT_X = 15, + JOYSTICK_AXIS_HAT_Y = 16, + JOYSTICK_AXIS_LTRIGGER = 17, + JOYSTICK_AXIS_RTRIGGER = 18, + JOYSTICK_AXIS_THROTTLE = 19, + JOYSTICK_AXIS_RUDDER = 20, + JOYSTICK_AXIS_WHEEL = 21, + JOYSTICK_AXIS_GAS = 22, + JOYSTICK_AXIS_BRAKE = 23, + JOYSTICK_AXIS_DISTANCE = 24, + JOYSTICK_AXIS_TILT = 25, +}; diff --git a/native.vcxproj b/native.vcxproj index 9b818fe9a0..71ed381080 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -172,6 +172,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index cae63ba799..a2bf0c0750 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -272,6 +272,7 @@ data + From 7afe501be2186dc7fa5924d1080581c0d048b4ea Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 11 Jun 2013 20:34:09 +0200 Subject: [PATCH 0453/1445] Add a bunch of Android controller axises and button constants, for use later. --- android/app-android.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/android/app-android.h b/android/app-android.h index a034ea635b..c741f37361 100644 --- a/android/app-android.h +++ b/android/app-android.h @@ -12,10 +12,7 @@ enum AndroidKeyCodes { KEYCODE_DPAD_UP = 19, KEYCODE_DPAD_RIGHT = 22, KEYCODE_DPAD_DOWN = 20, - KEYCODE_BUTTON_L1 = 102, - KEYCODE_BUTTON_R1 = 103, - KEYCODE_BUTTON_START = 108, - KEYCODE_BUTTON_SELECT = 109, + KEYCODE_DPAD_CENTER = 23, KEYCODE_UNKNOWN = 0, KEYCODE_SOFT_LEFT = 1, KEYCODE_SOFT_RIGHT = 2, @@ -35,11 +32,6 @@ enum AndroidKeyCodes { KEYCODE_9 = 16, KEYCODE_STAR = 17, KEYCODE_POUND = 18, - KEYCODE_DPAD_UP = 19, - KEYCODE_DPAD_DOWN = 20, - KEYCODE_DPAD_LEFT = 21, - KEYCODE_DPAD_RIGHT = 22, - KEYCODE_DPAD_CENTER = 23, KEYCODE_VOLUME_UP = 24, KEYCODE_VOLUME_DOWN = 25, KEYCODE_POWER = 26, From ce962bdf95717c52f29c211b6b242f899dcb9174 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 11 Jun 2013 21:53:59 +0200 Subject: [PATCH 0454/1445] Fix multiline text measuring bug. --- gfx_es2/draw_buffer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index bbadb37731..48cda85819 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -327,6 +327,7 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { unsigned int cval; float wacc = 0; + float maxX = 0.0f; int lines = 1; UTF8 utf(text); while (true) { @@ -334,6 +335,7 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { break; cval = utf.next(); if (cval == '\n') { + maxX = std::max(maxX, wacc); wacc = 0; lines++; continue; @@ -343,7 +345,7 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { wacc += c->wx * fontscalex; } } - if (w) *w = wacc; + if (w) *w = std::max(wacc, maxX); if (h) *h = atlasfont.height * fontscaley * lines; } From 131c222bbacc4024e643fd00e949a8a2d87226ab Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 14 Jun 2013 22:06:27 +0200 Subject: [PATCH 0455/1445] Add to ext/vjson/block_allocator.cpp, required on some platforms --- ext/vjson/block_allocator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/vjson/block_allocator.cpp b/ext/vjson/block_allocator.cpp index 16f3c4f9ec..f85de3a5ba 100644 --- a/ext/vjson/block_allocator.cpp +++ b/ext/vjson/block_allocator.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "block_allocator.h" block_allocator::block_allocator(size_t blocksize) From 5e50ceca86e4f8b3580662a1a5619fb660c5e066 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 14 Jun 2013 22:06:58 +0200 Subject: [PATCH 0456/1445] Add TOUCH_WHEEL flag. (yeah, "touch" doesn't quite make sense together with wheel.. it's for mouse users) --- input/input_state.h | 1 + 1 file changed, 1 insertion(+) diff --git a/input/input_state.h b/input/input_state.h index 5be7b48280..b34f051ac1 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -99,6 +99,7 @@ enum { TOUCH_DOWN = 2, TOUCH_UP = 4, TOUCH_CANCEL = 8, // Sent by scrollviews to their children when they detect a scroll + TOUCH_WHEEL = 16, // Scrollwheel event. Usually only affects Y. }; // Used for asynchronous touch input. From 5d098ca88bd11f0af09c95c9e91166fb82faa07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 15 Jun 2013 15:12:18 +0200 Subject: [PATCH 0457/1445] Fix mouse bug in SDL port --- base/PCMain.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 22b951e7d8..74b8d31f77 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -515,7 +515,6 @@ int main(int argc, char *argv[]) { #endif int framecount = 0; - bool nextFrameMD = 0; float t = 0, lastT = 0; while (true) { input_state.accelerometer_valid = false; @@ -533,6 +532,19 @@ int main(int argc, char *argv[]) { if (event.key.keysym.sym == SDLK_ESCAPE) { quitRequested = 1; } + } else if (event.type == SDL_MOUSEBUTTONDOWN) { + if (event.button.button == SDL_BUTTON_LEFT) { + input_state.pointer_x[0] = mx; + input_state.pointer_y[0] = my; + //input_state.mouse_buttons_down = 1; + input_state.pointer_down[0] = true; + TouchInput input; + input.x = mx; + input.y = my; + input.flags = TOUCH_DOWN; + input.id = 0; + NativeTouch(input); + } } else if (event.type == SDL_MOUSEMOTION) { if (input_state.pointer_down[0]) { input_state.pointer_x[0] = mx; @@ -544,22 +556,11 @@ int main(int argc, char *argv[]) { input.id = 0; NativeTouch(input); } - } else if (event.type == SDL_MOUSEBUTTONDOWN) { - if (event.button.button == SDL_BUTTON_LEFT) { - //input_state.mouse_buttons_down = 1; - input_state.pointer_down[0] = true; - nextFrameMD = true; - TouchInput input; - input.x = mx; - input.y = my; - input.flags = TOUCH_DOWN; - input.id = 0; - NativeTouch(input); - } } else if (event.type == SDL_MOUSEBUTTONUP) { if (event.button.button == SDL_BUTTON_LEFT) { + input_state.pointer_x[0] = mx; + input_state.pointer_y[0] = my; input_state.pointer_down[0] = false; - nextFrameMD = false; //input_state.mouse_buttons_up = 1; TouchInput input; input.x = mx; From bebb3ae397212883cf3c51a93ef803b72aca1860 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 16 Jun 2013 22:19:25 +0200 Subject: [PATCH 0458/1445] Android: Remove some too-verbose logging as onAccuracyChanged is called extremely often on some (buggy?) devices --- android/src/com/henrikrydgard/libnative/NativeGLView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 8a1f9c45d3..1f383b15cd 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -88,7 +88,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener { // Sensor management public void onAccuracyChanged(Sensor sensor, int arg1) { - Log.i(TAG, "onAccuracyChanged"); + // Log.i(TAG, "onAccuracyChanged"); } public void onSensorChanged(SensorEvent event) { From 4c2f26ff35b9833752d956a97265261f1e149e58 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 16 Jun 2013 23:43:35 +0200 Subject: [PATCH 0459/1445] Add controls for vsync (win-only) --- gfx_es2/gl_state.cpp | 11 +++++++++++ gfx_es2/gl_state.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index ee84087ed0..53fc98733a 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -1,5 +1,9 @@ #include #include "gl_state.h" +#ifdef _WIN32 +#include "GL/wglew.h" +#endif + OpenGLState glstate; GLExtensions gl_extensions; @@ -67,3 +71,10 @@ void CheckGLExtensions() { gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; #endif } + +void OpenGLState::SetVSyncInterval(int interval) { +#ifdef _WIN32 + if( wglSwapIntervalEXT ) + wglSwapIntervalEXT(interval); +#endif +} \ No newline at end of file diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 14dbd48e23..cb72e5a0ae 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -190,6 +190,9 @@ public: BoolState stencilTest; STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp; STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; + + // Only works on Win32, all other platforms are "force-vsync" + void SetVSyncInterval(int interval); // one of the above VSYNC, or a higher number for multi-frame waits (could be useful for 30hz games) }; #undef STATE1 From 9f510771bd9aeb9452635cb7fc0d48ee2d0374b4 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 19 Jun 2013 05:10:32 +1000 Subject: [PATCH 0460/1445] Fix 'external dir' for new 'Home' button in PPSSPP file manager. --- base/BlackberryMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 7a0288efff..8f8ee40e47 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -192,7 +192,7 @@ void BlackberryMain::startMain(int argc, char *argv[]) { net::Init(); startDisplays(); - NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "data/", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "/accounts/1000/shared/misc/", "BADCOFFEE"); NativeInitGraphics(); screen_request_events(screen_cxt); navigator_request_events(0); From 0e5cab2b0c2eb3fb1dac5bccc107e77697d65969 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Jun 2013 14:27:13 +0200 Subject: [PATCH 0461/1445] Android 4.2+: Ask for optimal audio buffer size + sample rate. Ignore sample rate for now. --- android/app-android.cpp | 27 +++++++---- android/native-audio-so.cpp | 47 ++++++++++++++----- android/native-audio-so.h | 2 +- android/native_audio.cpp | 9 +++- android/native_audio.h | 3 +- .../libnative/NativeActivity.java | 18 ++++++- .../henrikrydgard/libnative/NativeApp.java | 3 +- .../libnative/NativeAudioPlayer.java | 5 +- .../henrikrydgard/libnative/NativeGLView.java | 9 +--- 9 files changed, 89 insertions(+), 34 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 9151bc0487..5525e23d73 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -42,6 +42,9 @@ static float right_joystick_y_async; static uint32_t pad_buttons_down; +int optimalFramesPerBuffer = 0; +int optimalSampleRate = 0; + // Android implementation of callbacks to the Java part of the app void SystemToast(const char *text) { frameCommand = "toast"; @@ -93,7 +96,7 @@ InputState input_state; static bool renderer_inited = false; static bool first_lost = true; -static bool use_native_audio = false; +static bool use_opensl_audio = false; std::string GetJavaString(JNIEnv *env, jstring jstr) { @@ -119,6 +122,12 @@ extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isAtTopLevel(JNIE return NativeIsAtTopLevel(); } +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioConfig + (JNIEnv *env, jclass, jint optimalFPB, jint optimalSR) { + optimalFramesPerBuffer = optimalFPB; + optimalSampleRate = optimalSR; +} + extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { @@ -167,24 +176,26 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init const char *argv[2] = {app_name.c_str(), 0}; NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); - use_native_audio = juseNativeAudio; - if (use_native_audio) { - ILOG("Using OpenSL audio!"); - AndroidAudio_Init(&NativeMix, library_path); + use_opensl_audio = juseNativeAudio; + if (use_opensl_audio) { + // TODO: PPSSPP doesn't support 48khz yet so let's not use that yet. + ILOG("Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: 44100", optimalFramesPerBuffer, optimalSampleRate); + optimalSampleRate = 44100; + AndroidAudio_Init(&NativeMix, library_path, optimalFramesPerBuffer, optimalSampleRate); } ILOG("NativeApp.init() -- end"); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_resume(JNIEnv *, jclass) { ILOG("NativeApp.resume() - resuming audio"); - if (use_native_audio) { + if (use_opensl_audio) { AndroidAudio_Resume(); } } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclass) { ILOG("NativeApp.pause() - pausing audio"); - if (use_native_audio) { + if (use_opensl_audio) { AndroidAudio_Pause(); } ILOG("NativeApp.pause() - paused audio"); @@ -192,7 +203,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclas extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { ILOG("NativeApp.shutdown() -- begin"); - if (use_native_audio) { + if (use_opensl_audio) { AndroidAudio_Shutdown(); } if (renderer_inited) { diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index d399103c53..3142f22f56 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -30,12 +30,11 @@ static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; static SLMuteSoloItf bqPlayerMuteSolo; static SLVolumeItf bqPlayerVolume; -#define BUFFER_SIZE 512 -#define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2) - // Double buffering. -static short buffer[2][BUFFER_SIZE]; +static short *buffer[2]; static int curBuffer = 0; +static int framesPerBuffer; +int sampleRate; static AndroidAudioCallback audioCallback; @@ -44,15 +43,17 @@ static AndroidAudioCallback audioCallback; // I've chosen to this approach: Instantly enqueue a buffer that was rendered to the last time, // and then render the next. Hopefully it's okay to spend time in this callback after having enqueued. static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { - assert(bq == bqPlayerBufferQueue); - assert(NULL == context); + if (bq != bqPlayerBufferQueue) { + ELOG("Wrong bq!"); + return; + } - int nextSamples = audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); + int nextSamples = audioCallback(buffer[curBuffer], framesPerBuffer); // We can't enqueue nothing, the callback will never be called again. // Delay until we get some audio. while (nextSamples == 0) { usleep(40); - nextSamples = audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); + nextSamples = audioCallback(buffer[curBuffer], framesPerBuffer); } short *nextBuffer = buffer[curBuffer]; @@ -63,14 +64,29 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { // Comment from sample code: // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, // which for this code example would indicate a programming error - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ELOG("OpenSL ES: Failed to enqueue! %i %i", nextBuffer, nextSize); + } curBuffer ^= 1; // Switch buffer } // create the engine and output mix objects -extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb) { +extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate) { audioCallback = cb; + framesPerBuffer = _FramesPerBuffer; + if (framesPerBuffer == 0) + framesPerBuffer = 256; + if (framesPerBuffer < 32) + framesPerBuffer = 32; + sampleRate = _SampleRate; + if (sampleRate != 44100 && sampleRate != 48000) { + ELOG("Invalid sample rate %s - choosing 44100", sampleRate); + sampleRate = 44100; + } + + buffer[0] = new short[framesPerBuffer * 2]; + buffer[1] = new short[framesPerBuffer * 2]; SLresult result; // create engine @@ -85,11 +101,16 @@ extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb) { result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); assert(SL_RESULT_SUCCESS == result); + int sr = SL_SAMPLINGRATE_44_1; + if (sampleRate == 48000) { + sr = SL_SAMPLINGRATE_48; + } + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; SLDataFormat_PCM format_pcm = { SL_DATAFORMAT_PCM, 2, - SL_SAMPLINGRATE_44_1, + sr, SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, @@ -124,7 +145,7 @@ extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb) { // Render and enqueue a first buffer. (or should we just play the buffer empty?) curBuffer = 0; - audioCallback(buffer[curBuffer], BUFFER_SIZE_IN_SAMPLES); + audioCallback(buffer[curBuffer], framesPerBuffer); result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[curBuffer])); if (SL_RESULT_SUCCESS != result) { @@ -166,6 +187,8 @@ extern "C" void OpenSLWrap_Shutdown() { engineObject = NULL; engineEngine = NULL; } + delete [] buffer[0]; + delete [] buffer[1]; ILOG("OpenSLWrap_Shutdown - finished"); } diff --git a/android/native-audio-so.h b/android/native-audio-so.h index c44e7a50a3..c48123db41 100644 --- a/android/native-audio-so.h +++ b/android/native-audio-so.h @@ -4,5 +4,5 @@ typedef int (*AndroidAudioCallback)(short *buffer, int num_samples); -typedef bool (*OpenSLWrap_Init_T)(AndroidAudioCallback cb); +typedef bool (*OpenSLWrap_Init_T)(AndroidAudioCallback cb, int framesPerBuffer, int sampleRate); typedef void (*OpenSLWrap_Shutdown_T)(); diff --git a/android/native_audio.cpp b/android/native_audio.cpp index cb92e1ee3f..0e0f8d455b 100644 --- a/android/native_audio.cpp +++ b/android/native_audio.cpp @@ -11,11 +11,13 @@ struct AudioState { OpenSLWrap_Init_T init_func; OpenSLWrap_Shutdown_T shutdown_func; bool playing; + int frames_per_buffer; + int sample_rate; }; static AudioState *state = 0; -bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir) { +bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir, int optimalFramesPerBuffer, int optimalSampleRate) { if (state != 0) { ELOG("Audio state already exists"); return false; @@ -35,6 +37,9 @@ bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir) { state->playing = false; state->init_func = (OpenSLWrap_Init_T)dlsym(state->so, "OpenSLWrap_Init"); state->shutdown_func = (OpenSLWrap_Shutdown_T)dlsym(state->so, "OpenSLWrap_Shutdown"); + state->frames_per_buffer = optimalFramesPerBuffer ? optimalFramesPerBuffer : 256; + state->sample_rate = optimalSampleRate ? optimalSampleRate : 44100; + ILOG("OpenSLWrap init_func: %p shutdown_func: %p", (void *)state->init_func, (void *)state->shutdown_func); return true; @@ -47,7 +52,7 @@ bool AndroidAudio_Resume() { } if (!state->playing) { ILOG("Calling OpenSLWrap_Init_T..."); - bool init_retval = state->init_func(state->s_cb); + bool init_retval = state->init_func(state->s_cb, state->frames_per_buffer, state->sample_rate); ILOG("Returned from OpenSLWrap_Init_T"); state->playing = true; return init_retval; diff --git a/android/native_audio.h b/android/native_audio.h index 8e6679f772..82b3de7ee2 100644 --- a/android/native_audio.h +++ b/android/native_audio.h @@ -9,7 +9,8 @@ // Do not call this if you have detected that the android version is below // 2.2, as it will fail miserably. -bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir); +// It's okay for optimalFramesPerBuffer and optimalSampleRate to be 0. Defaults will be used. +bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir, int optimalFramesPerBuffer, int optimalSampleRate); bool AndroidAudio_Pause(); bool AndroidAudio_Resume(); void AndroidAudio_Shutdown(); diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 29dd063bef..5dc8ab583e 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -91,6 +91,17 @@ public class NativeActivity extends Activity { public static String commandParameter; public static String installID; + // Settings for best audio latency + private int optimalFramesPerBuffer; + private int optimalSampleRate; + + @TargetApi(17) + private void detectOptimalAudioSettings() { + AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE); + optimalFramesPerBuffer = Integer.parseInt(am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); + optimalSampleRate = Integer.parseInt(am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)); + } + String getApplicationLibraryDir(ApplicationInfo application) { String libdir = null; try { @@ -116,6 +127,10 @@ public class NativeActivity extends Activity { // Native OpenSL is available. Let's use it! useOpenSL = true; } + if (Build.VERSION.SDK_INT >= 17) { + // Get the optimal buffer sz + detectOptimalAudioSettings(); + } if (NativeApp.isLandscape()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); @@ -154,8 +169,9 @@ public class NativeActivity extends Activity { int dpi = metrics.densityDpi; // INIT! + NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); NativeApp.init(scrWidth, scrHeight, dpi, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); - + // Keep the screen bright - very annoying if it goes dark when tilting away Window window = this.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 8b7f0e86e3..2612bec744 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -2,7 +2,8 @@ package com.henrikrydgard.libnative; public class NativeApp { public static native void init(int xxres, int yyres, int dpi, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); - + public static native void audioConfig(int optimalFramesPerBuffer, int optimalSampleRate); + public static native boolean isLandscape(); public static native boolean isAtTopLevel(); diff --git a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java index 4b1c7a2fd7..2d98e25f08 100644 --- a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java +++ b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java @@ -10,7 +10,10 @@ public class NativeAudioPlayer { private String TAG = "NativeAudioPlayer"; private Thread thread; private boolean playing_; - + + public NativeAudioPlayer() { + } + // Calling stop() is allowed at any time, whether stopped or not. // If playing, blocks until not. public synchronized void stop() { diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 1f383b15cd..a3654036ed 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -3,17 +3,14 @@ package com.henrikrydgard.libnative; // Touch- and sensor-enabled GLSurfaceView. // Supports simple multitouch and pressure. -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.opengl.GLSurfaceView; -import android.os.Build; -import android.util.Log; +// import android.os.Build; +// import android.util.Log; import android.view.MotionEvent; public class NativeGLView extends GLSurfaceView implements SensorEventListener { @@ -21,8 +18,6 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener { private SensorManager mSensorManager; private Sensor mAccelerometer; - - public NativeGLView(NativeActivity activity) { super(activity); setEGLContextClientVersion(2); From d1df63036a93139ca66615f143bc390659c689da Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Jun 2013 20:46:06 +0200 Subject: [PATCH 0462/1445] Don't clamp to a circle in the virtual stick. --- ui/virtual_input.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index dbc3924574..a5862ae577 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -130,12 +130,15 @@ void TouchStick::update(InputState &input_state) if (!dragging_[i]) goto skip; - // Clamp to a circle - float len = sqrtf(dx * dx + dy * dy); - if (len > 1.0f) { - dx /= len; - dy /= len; - } + // Do not clamp to a circle! The PSP has nearly square range! + + // Old code to clamp to a circle + // float len = sqrtf(dx * dx + dy * dy); + // if (len > 1.0f) { + // dx /= len; + // dy /= len; + //} + if (stick_ == 0) { input_state.pad_lstick_x = dx; input_state.pad_lstick_y = -dy; From deb4ba83235a86491d073db73a1e5bab2a5ce523 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Jun 2013 22:18:05 +0200 Subject: [PATCH 0463/1445] Still need to clamp to a square, sigh. --- ui/virtual_input.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index a5862ae577..cf1ff447b9 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -1,4 +1,6 @@ #include +#include + #include "base/logging.h" #include "gfx_es2/draw_buffer.h" #include "gfx/texture_atlas.h" @@ -139,6 +141,10 @@ void TouchStick::update(InputState &input_state) // dy /= len; //} + // Still need to clamp to a square + dx = std::min(1.0f, std::max(-1.0f, dx)); + dy = std::min(1.0f, std::max(-1.0f, dy)); + if (stick_ == 0) { input_state.pad_lstick_x = dx; input_state.pad_lstick_y = -dy; @@ -146,6 +152,7 @@ void TouchStick::update(InputState &input_state) input_state.pad_rstick_x = dx; input_state.pad_rstick_y = -dy; } + } else { dragging_[i] = false; } From 0a26fae856aecdaa426d92fa5dde101b19487796 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 20 Jun 2013 21:51:42 +0200 Subject: [PATCH 0464/1445] More control over text scaling in TextViews --- ui/view.cpp | 4 ++-- ui/view.h | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 476345108c..cc550d0194 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -268,13 +268,13 @@ void TextureView::Draw(UIContext &dc) { } void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - dc.Draw()->SetFontScale(textScale_, textScale_); + dc.Draw()->SetFontScale(textScaleX_, textScaleY_); dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); dc.Draw()->SetFontScale(1.0f, 1.0f); } void TextView::Draw(UIContext &dc) { - dc.Draw()->SetFontScale(textScale_, textScale_); + dc.Draw()->SetFontScale(textScaleX_, textScaleY_); dc.Draw()->DrawTextRect(dc.theme->uiFont, text_.c_str(), bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF, textAlign_); dc.Draw()->SetFontScale(1.0f, 1.0f); } diff --git a/ui/view.h b/ui/view.h index 8825e3e5d2..99f3430096 100644 --- a/ui/view.h +++ b/ui/view.h @@ -489,16 +489,19 @@ public: class TextView : public InertView { public: TextView(int font, const std::string &text, int textAlign, float textScale, LayoutParams *layoutParams = 0) - : InertView(layoutParams), font_(font), text_(text), textScale_(textScale), textAlign_(textAlign) {} + : InertView(layoutParams), font_(font), text_(text), textScaleX_(textScale), textScaleY_(textScale), textAlign_(textAlign) {} virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); - virtual void SetText(const std::string &text) { text_ = text; } + void SetText(const std::string &text) { text_ = text; } + void SetTextScaleXY(float sx, float sy) { textScaleX_ = sx; textScaleY_ = sy; } + void SetTextScale(float scale) { textScaleX_ = scale; textScaleY_ = scale; } private: int font_; std::string text_; - float textScale_; + float textScaleX_; + float textScaleY_; int textAlign_; }; From d37f1254a494cb866aa22a24d70979946522d947 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 22 Jun 2013 01:08:57 +0200 Subject: [PATCH 0465/1445] Less CHECKs, more manual error checking and response. --- net/http_client.cpp | 36 ++++++++++++++++++++++++------------ net/http_client.h | 5 +---- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 6c65fce952..9c01458663 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -43,7 +43,11 @@ inline unsigned short myhtons(unsigned short x) { } bool Connection::Resolve(const char *host, int port) { - CHECK_EQ(-1, (intptr_t)sock_); + if ((intptr_t)sock_ != -1) { + ELOG("Resolve: Already have a socket"); + return false; + } + host_ = host; port_ = port; @@ -61,10 +65,13 @@ bool Connection::Resolve(const char *host, int port) { return true; } -void Connection::Connect() { +bool Connection::Connect() { CHECK_GE(port_, 0); sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - CHECK_GE(sock_, 0); + if ((intptr_t)sock_ < 0) { + ELOG("Bad socket"); + return false; + } for (int tries = 100; tries > 0; --tries) { for (addrinfo *possible = resolved_; possible != NULL; possible = possible->ai_next) { @@ -74,7 +81,7 @@ void Connection::Connect() { int retval = connect(sock_, possible->ai_addr, (int)possible->ai_addrlen); if (retval >= 0) - return; + return true; } #ifdef _WIN32 Sleep(1); @@ -82,6 +89,7 @@ void Connection::Connect() { sleep(1); #endif } + return false; } void Connection::Disconnect() { @@ -91,11 +99,6 @@ void Connection::Disconnect() { } } -void Connection::Reconnect() { - Disconnect(); - Connect(); -} - } // net namespace http { @@ -161,7 +164,7 @@ int Client::GET(const char *resource, Buffer *output) { // Skip the header. TODO: read HTTP code and file size so we can make progress bars. std::string line; - CHECK_GT(readbuf.TakeLineCRLF(&line), 0); + readbuf.TakeLineCRLF(&line); int code = atoi(&line[line.find(" ") + 1]); bool gzip = false; @@ -210,7 +213,9 @@ int Client::POST(const char *resource, const std::string &data, const std::strin } buffer.Append("\r\n"); buffer.Append(data); - CHECK(buffer.FlushSocket(sock())); + if (!buffer.FlushSocket(sock())) { + ELOG("Failed posting"); + } // I guess we could add a deadline here. output->ReadAll(sock()); @@ -271,9 +276,16 @@ void Download::Do() { ELOG("Failed resolving %s", url_.c_str()); failed_ = true; progress_ = 1.0f; + net::Shutdown(); + return; + } + if (!client.Connect()) { + ELOG("Failed connecting to server."); + resultCode_ = -1; + net::Shutdown(); + progress_ = 1.0f; return; } - client.Connect(); int resultCode = client.GET(fileUrl.Resource().c_str(), &buffer_); if (resultCode == 200) { ILOG("Completed downloading %s to %s", url_.c_str(), outfile_.c_str()); diff --git a/net/http_client.h b/net/http_client.h index 5fc1b87b8d..7ca3a74ada 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -29,12 +29,9 @@ public: // Inits the sockaddr_in. bool Resolve(const char *host, int port); - void Connect(); + bool Connect(); void Disconnect(); - // Disconnects, and connects. Doesn't re-resolve. - void Reconnect(); - // Only to be used for bring-up and debugging. uintptr_t sock() const { return sock_; } From ca9301fedf879f28d6f11fda59709a66c5368bec Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 22 Jun 2013 17:30:05 +0200 Subject: [PATCH 0466/1445] Audio: If we're behind, fill buffer with zeros instead of waiting. --- android/native-audio-so.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 3142f22f56..15a9b98fbd 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -48,24 +48,17 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { return; } - int nextSamples = audioCallback(buffer[curBuffer], framesPerBuffer); - // We can't enqueue nothing, the callback will never be called again. - // Delay until we get some audio. - while (nextSamples == 0) { - usleep(40); - nextSamples = audioCallback(buffer[curBuffer], framesPerBuffer); - } + int renderedFrames = audioCallback(buffer[curBuffer], framesPerBuffer); - short *nextBuffer = buffer[curBuffer]; - int nextSize = nextSamples * 2 * sizeof(short); - - SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); + int sizeInBytes = framesPerBuffer * 2 * sizeof(short); + memset(buffer[curBuffer] + renderedFrames * 2, 0, (framesPerBuffer - renderedFrames) * 4); + SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeInBytes); // Comment from sample code: // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, // which for this code example would indicate a programming error if (result != SL_RESULT_SUCCESS) { - ELOG("OpenSL ES: Failed to enqueue! %i %i", nextBuffer, nextSize); + ELOG("OpenSL ES: Failed to enqueue! %i %i", renderedFrames, sizeInBytes); } curBuffer ^= 1; // Switch buffer @@ -81,7 +74,7 @@ extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, i framesPerBuffer = 32; sampleRate = _SampleRate; if (sampleRate != 44100 && sampleRate != 48000) { - ELOG("Invalid sample rate %s - choosing 44100", sampleRate); + ELOG("Invalid sample rate %i - choosing 44100", sampleRate); sampleRate = 44100; } From bd78a060158aa7ee12713727164541be29f8355a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 22 Jun 2013 22:27:09 +0200 Subject: [PATCH 0467/1445] Add a nice public domain jpeg encoder --- Android.mk | 1 + ext/jpge/jpge.cpp | 1038 +++++++++++++++++++++++++++++++++++++ ext/jpge/jpge.h | 169 ++++++ ext/jpge/publicdomain.txt | 1 + native.vcxproj | 2 + native.vcxproj.filters | 2 + 6 files changed, 1213 insertions(+) create mode 100644 ext/jpge/jpge.cpp create mode 100644 ext/jpge/jpge.h create mode 100644 ext/jpge/publicdomain.txt diff --git a/Android.mk b/Android.mk index f5266360a0..d14d699f6a 100644 --- a/Android.mk +++ b/Android.mk @@ -19,6 +19,7 @@ LOCAL_SRC_FILES :=\ data/compression.cpp \ ext/rg_etc1/rg_etc1.cpp \ ext/cityhash/city.cpp \ + ext/jpge/jpge.cpp \ ext/sha1/sha1.cpp \ ext/stb_image/stb_image.c \ ext/stb_vorbis/stb_vorbis.c.arm \ diff --git a/ext/jpge/jpge.cpp b/ext/jpge/jpge.cpp new file mode 100644 index 0000000000..c82d73ff06 --- /dev/null +++ b/ext/jpge/jpge.cpp @@ -0,0 +1,1038 @@ +// jpge.cpp - C++ class for JPEG compression. +// Public domain, Rich Geldreich +// v1.01, Dec. 18, 2010 - Initial release +// v1.02, Apr. 6, 2011 - Removed 2x2 ordered dither in H2V1 chroma subsampling method load_block_16_8_8(). (The rounding factor was 2, when it should have been 1. Either way, it wasn't helping.) +// v1.03, Apr. 16, 2011 - Added support for optimized Huffman code tables, optimized dynamic memory allocation down to only 1 alloc. +// Also from Alex Evans: Added RGBA support, linear memory allocator (no longer needed in v1.03). +// v1.04, May. 19, 2012: Forgot to set m_pFile ptr to NULL in cfile_stream::close(). Thanks to Owen Kaluza for reporting this bug. +// Code tweaks to fix VS2008 static code analysis warnings (all looked harmless). +// Code review revealed method load_block_16_8_8() (used for the non-default H2V1 sampling mode to downsample chroma) somehow didn't get the rounding factor fix from v1.02. + +#include "jpge.h" + +#include +#include +#include + +#define JPGE_MAX(a,b) (((a)>(b))?(a):(b)) +#define JPGE_MIN(a,b) (((a)<(b))?(a):(b)) + +namespace jpge { + +static inline void *jpge_malloc(size_t nSize) { return malloc(nSize); } +static inline void jpge_free(void *p) { free(p); } + +// Various JPEG enums and tables. +enum { M_SOF0 = 0xC0, M_DHT = 0xC4, M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_APP0 = 0xE0 }; +enum { DC_LUM_CODES = 12, AC_LUM_CODES = 256, DC_CHROMA_CODES = 12, AC_CHROMA_CODES = 256, MAX_HUFF_SYMBOLS = 257, MAX_HUFF_CODESIZE = 32 }; + +static uint8 s_zag[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 }; +static int16 s_std_lum_quant[64] = { 16,11,12,14,12,10,16,14,13,14,18,17,16,19,24,40,26,24,22,22,24,49,35,37,29,40,58,51,61,60,57,51,56,55,64,72,92,78,64,68,87,69,55,56,80,109,81,87,95,98,103,104,103,62,77,113,121,112,100,120,92,101,103,99 }; +static int16 s_std_croma_quant[64] = { 17,18,18,24,21,24,47,26,26,47,99,66,56,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99 }; +static uint8 s_dc_lum_bits[17] = { 0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0 }; +static uint8 s_dc_lum_val[DC_LUM_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 }; +static uint8 s_ac_lum_bits[17] = { 0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d }; +static uint8 s_ac_lum_val[AC_LUM_CODES] = +{ + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0, + 0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49, + 0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5, + 0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa +}; +static uint8 s_dc_chroma_bits[17] = { 0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0 }; +static uint8 s_dc_chroma_val[DC_CHROMA_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 }; +static uint8 s_ac_chroma_bits[17] = { 0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77 }; +static uint8 s_ac_chroma_val[AC_CHROMA_CODES] = +{ + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0, + 0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48, + 0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3, + 0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa +}; + +// Low-level helper functions. +template inline void clear_obj(T &obj) { memset(&obj, 0, sizeof(obj)); } + +const int YR = 19595, YG = 38470, YB = 7471, CB_R = -11059, CB_G = -21709, CB_B = 32768, CR_R = 32768, CR_G = -27439, CR_B = -5329; +static inline uint8 clamp(int i) { if (static_cast(i) > 255U) { if (i < 0) i = 0; else if (i > 255) i = 255; } return static_cast(i); } + +static void RGB_to_YCC(uint8* pDst, const uint8 *pSrc, int num_pixels) +{ + for ( ; num_pixels; pDst += 3, pSrc += 3, num_pixels--) + { + const int r = pSrc[0], g = pSrc[1], b = pSrc[2]; + pDst[0] = static_cast((r * YR + g * YG + b * YB + 32768) >> 16); + pDst[1] = clamp(128 + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16)); + pDst[2] = clamp(128 + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16)); + } +} + +static void RGB_to_Y(uint8* pDst, const uint8 *pSrc, int num_pixels) +{ + for ( ; num_pixels; pDst++, pSrc += 3, num_pixels--) + pDst[0] = static_cast((pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) >> 16); +} + +static void RGBA_to_YCC(uint8* pDst, const uint8 *pSrc, int num_pixels) +{ + for ( ; num_pixels; pDst += 3, pSrc += 4, num_pixels--) + { + const int r = pSrc[0], g = pSrc[1], b = pSrc[2]; + pDst[0] = static_cast((r * YR + g * YG + b * YB + 32768) >> 16); + pDst[1] = clamp(128 + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16)); + pDst[2] = clamp(128 + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16)); + } +} + +static void RGBA_to_Y(uint8* pDst, const uint8 *pSrc, int num_pixels) +{ + for ( ; num_pixels; pDst++, pSrc += 4, num_pixels--) + pDst[0] = static_cast((pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) >> 16); +} + +static void Y_to_YCC(uint8* pDst, const uint8* pSrc, int num_pixels) +{ + for( ; num_pixels; pDst += 3, pSrc++, num_pixels--) { pDst[0] = pSrc[0]; pDst[1] = 128; pDst[2] = 128; } +} + +// Forward DCT - DCT derived from jfdctint. +enum { CONST_BITS = 13, ROW_BITS = 2 }; +#define DCT_DESCALE(x, n) (((x) + (((int32)1) << ((n) - 1))) >> (n)) +#define DCT_MUL(var, c) (static_cast(var) * static_cast(c)) +#define DCT1D(s0, s1, s2, s3, s4, s5, s6, s7) \ + int32 t0 = s0 + s7, t7 = s0 - s7, t1 = s1 + s6, t6 = s1 - s6, t2 = s2 + s5, t5 = s2 - s5, t3 = s3 + s4, t4 = s3 - s4; \ + int32 t10 = t0 + t3, t13 = t0 - t3, t11 = t1 + t2, t12 = t1 - t2; \ + int32 u1 = DCT_MUL(t12 + t13, 4433); \ + s2 = u1 + DCT_MUL(t13, 6270); \ + s6 = u1 + DCT_MUL(t12, -15137); \ + u1 = t4 + t7; \ + int32 u2 = t5 + t6, u3 = t4 + t6, u4 = t5 + t7; \ + int32 z5 = DCT_MUL(u3 + u4, 9633); \ + t4 = DCT_MUL(t4, 2446); t5 = DCT_MUL(t5, 16819); \ + t6 = DCT_MUL(t6, 25172); t7 = DCT_MUL(t7, 12299); \ + u1 = DCT_MUL(u1, -7373); u2 = DCT_MUL(u2, -20995); \ + u3 = DCT_MUL(u3, -16069); u4 = DCT_MUL(u4, -3196); \ + u3 += z5; u4 += z5; \ + s0 = t10 + t11; s1 = t7 + u1 + u4; s3 = t6 + u2 + u3; s4 = t10 - t11; s5 = t5 + u2 + u4; s7 = t4 + u1 + u3; + +static void DCT2D(int32 *p) +{ + int32 c, *q = p; + for (c = 7; c >= 0; c--, q += 8) + { + int32 s0 = q[0], s1 = q[1], s2 = q[2], s3 = q[3], s4 = q[4], s5 = q[5], s6 = q[6], s7 = q[7]; + DCT1D(s0, s1, s2, s3, s4, s5, s6, s7); + q[0] = s0 << ROW_BITS; q[1] = DCT_DESCALE(s1, CONST_BITS-ROW_BITS); q[2] = DCT_DESCALE(s2, CONST_BITS-ROW_BITS); q[3] = DCT_DESCALE(s3, CONST_BITS-ROW_BITS); + q[4] = s4 << ROW_BITS; q[5] = DCT_DESCALE(s5, CONST_BITS-ROW_BITS); q[6] = DCT_DESCALE(s6, CONST_BITS-ROW_BITS); q[7] = DCT_DESCALE(s7, CONST_BITS-ROW_BITS); + } + for (q = p, c = 7; c >= 0; c--, q++) + { + int32 s0 = q[0*8], s1 = q[1*8], s2 = q[2*8], s3 = q[3*8], s4 = q[4*8], s5 = q[5*8], s6 = q[6*8], s7 = q[7*8]; + DCT1D(s0, s1, s2, s3, s4, s5, s6, s7); + q[0*8] = DCT_DESCALE(s0, ROW_BITS+3); q[1*8] = DCT_DESCALE(s1, CONST_BITS+ROW_BITS+3); q[2*8] = DCT_DESCALE(s2, CONST_BITS+ROW_BITS+3); q[3*8] = DCT_DESCALE(s3, CONST_BITS+ROW_BITS+3); + q[4*8] = DCT_DESCALE(s4, ROW_BITS+3); q[5*8] = DCT_DESCALE(s5, CONST_BITS+ROW_BITS+3); q[6*8] = DCT_DESCALE(s6, CONST_BITS+ROW_BITS+3); q[7*8] = DCT_DESCALE(s7, CONST_BITS+ROW_BITS+3); + } +} + +struct sym_freq { uint m_key, m_sym_index; }; + +// Radix sorts sym_freq[] array by 32-bit key m_key. Returns ptr to sorted values. +static inline sym_freq* radix_sort_syms(uint num_syms, sym_freq* pSyms0, sym_freq* pSyms1) +{ + const uint cMaxPasses = 4; + uint32 hist[256 * cMaxPasses]; clear_obj(hist); + for (uint i = 0; i < num_syms; i++) { uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; hist[256*2 + ((freq >> 16) & 0xFF)]++; hist[256*3 + ((freq >> 24) & 0xFF)]++; } + sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; + uint total_passes = cMaxPasses; while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; + for (uint pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) + { + const uint32* pHist = &hist[pass << 8]; + uint offsets[256], cur_ofs = 0; + for (uint i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } + for (uint i = 0; i < num_syms; i++) + pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; + sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; + } + return pCur_syms; +} + +// calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. +static void calculate_minimum_redundancy(sym_freq *A, int n) +{ + int root, leaf, next, avbl, used, dpth; + if (n==0) return; else if (n==1) { A[0].m_key = 1; return; } + A[0].m_key += A[1].m_key; root = 0; leaf = 2; + for (next=1; next < n-1; next++) + { + if (leaf>=n || A[root].m_key=n || (root=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; + avbl = 1; used = dpth = 0; root = n-2; next = n-1; + while (avbl>0) + { + while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; } + while (avbl>used) { A[next--].m_key = dpth; avbl--; } + avbl = 2*used; dpth++; used = 0; + } +} + +// Limits canonical Huffman code table's max code size to max_code_size. +static void huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) +{ + if (code_list_len <= 1) return; + + for (int i = max_code_size + 1; i <= MAX_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; + + uint32 total = 0; + for (int i = max_code_size; i > 0; i--) + total += (((uint32)pNum_codes[i]) << (max_code_size - i)); + + while (total != (1UL << max_code_size)) + { + pNum_codes[max_code_size]--; + for (int i = max_code_size - 1; i > 0; i--) + { + if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; } + } + total--; + } +} + +// Generates an optimized offman table. +void jpeg_encoder::optimize_huffman_table(int table_num, int table_len) +{ + sym_freq syms0[MAX_HUFF_SYMBOLS], syms1[MAX_HUFF_SYMBOLS]; + syms0[0].m_key = 1; syms0[0].m_sym_index = 0; // dummy symbol, assures that no valid code contains all 1's + int num_used_syms = 1; + const uint32 *pSym_count = &m_huff_count[table_num][0]; + for (int i = 0; i < table_len; i++) + if (pSym_count[i]) { syms0[num_used_syms].m_key = pSym_count[i]; syms0[num_used_syms++].m_sym_index = i + 1; } + sym_freq* pSyms = radix_sort_syms(num_used_syms, syms0, syms1); + calculate_minimum_redundancy(pSyms, num_used_syms); + + // Count the # of symbols of each code size. + int num_codes[1 + MAX_HUFF_CODESIZE]; clear_obj(num_codes); + for (int i = 0; i < num_used_syms; i++) + num_codes[pSyms[i].m_key]++; + + const uint JPGE_CODE_SIZE_LIMIT = 16; // the maximum possible size of a JPEG Huffman code (valid range is [9,16] - 9 vs. 8 because of the dummy symbol) + huffman_enforce_max_code_size(num_codes, num_used_syms, JPGE_CODE_SIZE_LIMIT); + + // Compute m_huff_bits array, which contains the # of symbols per code size. + clear_obj(m_huff_bits[table_num]); + for (int i = 1; i <= (int)JPGE_CODE_SIZE_LIMIT; i++) + m_huff_bits[table_num][i] = static_cast(num_codes[i]); + + // Remove the dummy symbol added above, which must be in largest bucket. + for (int i = JPGE_CODE_SIZE_LIMIT; i >= 1; i--) + { + if (m_huff_bits[table_num][i]) { m_huff_bits[table_num][i]--; break; } + } + + // Compute the m_huff_val array, which contains the symbol indices sorted by code size (smallest to largest). + for (int i = num_used_syms - 1; i >= 1; i--) + m_huff_val[table_num][num_used_syms - 1 - i] = static_cast(pSyms[i].m_sym_index - 1); +} + +// JPEG marker generation. +void jpeg_encoder::emit_byte(uint8 i) +{ + m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_obj(i); +} + +void jpeg_encoder::emit_word(uint i) +{ + emit_byte(uint8(i >> 8)); emit_byte(uint8(i & 0xFF)); +} + +void jpeg_encoder::emit_marker(int marker) +{ + emit_byte(uint8(0xFF)); emit_byte(uint8(marker)); +} + +// Emit JFIF marker +void jpeg_encoder::emit_jfif_app0() +{ + emit_marker(M_APP0); + emit_word(2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); + emit_byte(0x4A); emit_byte(0x46); emit_byte(0x49); emit_byte(0x46); /* Identifier: ASCII "JFIF" */ + emit_byte(0); + emit_byte(1); /* Major version */ + emit_byte(1); /* Minor version */ + emit_byte(0); /* Density unit */ + emit_word(1); + emit_word(1); + emit_byte(0); /* No thumbnail image */ + emit_byte(0); +} + +// Emit quantization tables +void jpeg_encoder::emit_dqt() +{ + for (int i = 0; i < ((m_num_components == 3) ? 2 : 1); i++) + { + emit_marker(M_DQT); + emit_word(64 + 1 + 2); + emit_byte(static_cast(i)); + for (int j = 0; j < 64; j++) + emit_byte(static_cast(m_quantization_tables[i][j])); + } +} + +// Emit start of frame marker +void jpeg_encoder::emit_sof() +{ + emit_marker(M_SOF0); /* baseline */ + emit_word(3 * m_num_components + 2 + 5 + 1); + emit_byte(8); /* precision */ + emit_word(m_image_y); + emit_word(m_image_x); + emit_byte(m_num_components); + for (int i = 0; i < m_num_components; i++) + { + emit_byte(static_cast(i + 1)); /* component ID */ + emit_byte((m_comp_h_samp[i] << 4) + m_comp_v_samp[i]); /* h and v sampling */ + emit_byte(i > 0); /* quant. table num */ + } +} + +// Emit Huffman table. +void jpeg_encoder::emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag) +{ + emit_marker(M_DHT); + + int length = 0; + for (int i = 1; i <= 16; i++) + length += bits[i]; + + emit_word(length + 2 + 1 + 16); + emit_byte(static_cast(index + (ac_flag << 4))); + + for (int i = 1; i <= 16; i++) + emit_byte(bits[i]); + + for (int i = 0; i < length; i++) + emit_byte(val[i]); +} + +// Emit all Huffman tables. +void jpeg_encoder::emit_dhts() +{ + emit_dht(m_huff_bits[0+0], m_huff_val[0+0], 0, false); + emit_dht(m_huff_bits[2+0], m_huff_val[2+0], 0, true); + if (m_num_components == 3) + { + emit_dht(m_huff_bits[0+1], m_huff_val[0+1], 1, false); + emit_dht(m_huff_bits[2+1], m_huff_val[2+1], 1, true); + } +} + +// emit start of scan +void jpeg_encoder::emit_sos() +{ + emit_marker(M_SOS); + emit_word(2 * m_num_components + 2 + 1 + 3); + emit_byte(m_num_components); + for (int i = 0; i < m_num_components; i++) + { + emit_byte(static_cast(i + 1)); + if (i == 0) + emit_byte((0 << 4) + 0); + else + emit_byte((1 << 4) + 1); + } + emit_byte(0); /* spectral selection */ + emit_byte(63); + emit_byte(0); +} + +// Emit all markers at beginning of image file. +void jpeg_encoder::emit_markers() +{ + emit_marker(M_SOI); + emit_jfif_app0(); + emit_dqt(); + emit_sof(); + emit_dhts(); + emit_sos(); +} + +// Compute the actual canonical Huffman codes/code sizes given the JPEG huff bits and val arrays. +void jpeg_encoder::compute_huffman_table(uint *codes, uint8 *code_sizes, uint8 *bits, uint8 *val) +{ + int i, l, last_p, si; + uint8 huff_size[257]; + uint huff_code[257]; + uint code; + + int p = 0; + for (l = 1; l <= 16; l++) + for (i = 1; i <= bits[l]; i++) + huff_size[p++] = (char)l; + + huff_size[p] = 0; last_p = p; // write sentinel + + code = 0; si = huff_size[0]; p = 0; + + while (huff_size[p]) + { + while (huff_size[p] == si) + huff_code[p++] = code++; + code <<= 1; + si++; + } + + memset(codes, 0, sizeof(codes[0])*256); + memset(code_sizes, 0, sizeof(code_sizes[0])*256); + for (p = 0; p < last_p; p++) + { + codes[val[p]] = huff_code[p]; + code_sizes[val[p]] = huff_size[p]; + } +} + +// Quantization table generation. +void jpeg_encoder::compute_quant_table(int32 *pDst, int16 *pSrc) +{ + int32 q; + if (m_params.m_quality < 50) + q = 5000 / m_params.m_quality; + else + q = 200 - m_params.m_quality * 2; + for (int i = 0; i < 64; i++) + { + int32 j = *pSrc++; j = (j * q + 50L) / 100L; + *pDst++ = JPGE_MIN(JPGE_MAX(j, 1), 255); + } +} + +// Higher-level methods. +void jpeg_encoder::first_pass_init() +{ + m_bit_buffer = 0; m_bits_in = 0; + memset(m_last_dc_val, 0, 3 * sizeof(m_last_dc_val[0])); + m_mcu_y_ofs = 0; + m_pass_num = 1; +} + +bool jpeg_encoder::second_pass_init() +{ + compute_huffman_table(&m_huff_codes[0+0][0], &m_huff_code_sizes[0+0][0], m_huff_bits[0+0], m_huff_val[0+0]); + compute_huffman_table(&m_huff_codes[2+0][0], &m_huff_code_sizes[2+0][0], m_huff_bits[2+0], m_huff_val[2+0]); + if (m_num_components > 1) + { + compute_huffman_table(&m_huff_codes[0+1][0], &m_huff_code_sizes[0+1][0], m_huff_bits[0+1], m_huff_val[0+1]); + compute_huffman_table(&m_huff_codes[2+1][0], &m_huff_code_sizes[2+1][0], m_huff_bits[2+1], m_huff_val[2+1]); + } + first_pass_init(); + emit_markers(); + m_pass_num = 2; + return true; +} + +bool jpeg_encoder::jpg_open(int p_x_res, int p_y_res, int src_channels) +{ + m_num_components = 3; + switch (m_params.m_subsampling) + { + case Y_ONLY: + { + m_num_components = 1; + m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1; + m_mcu_x = 8; m_mcu_y = 8; + break; + } + case H1V1: + { + m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1; + m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; + m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; + m_mcu_x = 8; m_mcu_y = 8; + break; + } + case H2V1: + { + m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 1; + m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; + m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; + m_mcu_x = 16; m_mcu_y = 8; + break; + } + case H2V2: + { + m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 2; + m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; + m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; + m_mcu_x = 16; m_mcu_y = 16; + } + } + + m_image_x = p_x_res; m_image_y = p_y_res; + m_image_bpp = src_channels; + m_image_bpl = m_image_x * src_channels; + m_image_x_mcu = (m_image_x + m_mcu_x - 1) & (~(m_mcu_x - 1)); + m_image_y_mcu = (m_image_y + m_mcu_y - 1) & (~(m_mcu_y - 1)); + m_image_bpl_xlt = m_image_x * m_num_components; + m_image_bpl_mcu = m_image_x_mcu * m_num_components; + m_mcus_per_row = m_image_x_mcu / m_mcu_x; + + if ((m_mcu_lines[0] = static_cast(jpge_malloc(m_image_bpl_mcu * m_mcu_y))) == NULL) return false; + for (int i = 1; i < m_mcu_y; i++) + m_mcu_lines[i] = m_mcu_lines[i-1] + m_image_bpl_mcu; + + compute_quant_table(m_quantization_tables[0], s_std_lum_quant); + compute_quant_table(m_quantization_tables[1], m_params.m_no_chroma_discrim_flag ? s_std_lum_quant : s_std_croma_quant); + + m_out_buf_left = JPGE_OUT_BUF_SIZE; + m_pOut_buf = m_out_buf; + + if (m_params.m_two_pass_flag) + { + clear_obj(m_huff_count); + first_pass_init(); + } + else + { + memcpy(m_huff_bits[0+0], s_dc_lum_bits, 17); memcpy(m_huff_val [0+0], s_dc_lum_val, DC_LUM_CODES); + memcpy(m_huff_bits[2+0], s_ac_lum_bits, 17); memcpy(m_huff_val [2+0], s_ac_lum_val, AC_LUM_CODES); + memcpy(m_huff_bits[0+1], s_dc_chroma_bits, 17); memcpy(m_huff_val [0+1], s_dc_chroma_val, DC_CHROMA_CODES); + memcpy(m_huff_bits[2+1], s_ac_chroma_bits, 17); memcpy(m_huff_val [2+1], s_ac_chroma_val, AC_CHROMA_CODES); + if (!second_pass_init()) return false; // in effect, skip over the first pass + } + return m_all_stream_writes_succeeded; +} + +void jpeg_encoder::load_block_8_8_grey(int x) +{ + uint8 *pSrc; + sample_array_t *pDst = m_sample_array; + x <<= 3; + for (int i = 0; i < 8; i++, pDst += 8) + { + pSrc = m_mcu_lines[i] + x; + pDst[0] = pSrc[0] - 128; pDst[1] = pSrc[1] - 128; pDst[2] = pSrc[2] - 128; pDst[3] = pSrc[3] - 128; + pDst[4] = pSrc[4] - 128; pDst[5] = pSrc[5] - 128; pDst[6] = pSrc[6] - 128; pDst[7] = pSrc[7] - 128; + } +} + +void jpeg_encoder::load_block_8_8(int x, int y, int c) +{ + uint8 *pSrc; + sample_array_t *pDst = m_sample_array; + x = (x * (8 * 3)) + c; + y <<= 3; + for (int i = 0; i < 8; i++, pDst += 8) + { + pSrc = m_mcu_lines[y + i] + x; + pDst[0] = pSrc[0 * 3] - 128; pDst[1] = pSrc[1 * 3] - 128; pDst[2] = pSrc[2 * 3] - 128; pDst[3] = pSrc[3 * 3] - 128; + pDst[4] = pSrc[4 * 3] - 128; pDst[5] = pSrc[5 * 3] - 128; pDst[6] = pSrc[6 * 3] - 128; pDst[7] = pSrc[7 * 3] - 128; + } +} + +void jpeg_encoder::load_block_16_8(int x, int c) +{ + uint8 *pSrc1, *pSrc2; + sample_array_t *pDst = m_sample_array; + x = (x * (16 * 3)) + c; + int a = 0, b = 2; + for (int i = 0; i < 16; i += 2, pDst += 8) + { + pSrc1 = m_mcu_lines[i + 0] + x; + pSrc2 = m_mcu_lines[i + 1] + x; + pDst[0] = ((pSrc1[ 0 * 3] + pSrc1[ 1 * 3] + pSrc2[ 0 * 3] + pSrc2[ 1 * 3] + a) >> 2) - 128; pDst[1] = ((pSrc1[ 2 * 3] + pSrc1[ 3 * 3] + pSrc2[ 2 * 3] + pSrc2[ 3 * 3] + b) >> 2) - 128; + pDst[2] = ((pSrc1[ 4 * 3] + pSrc1[ 5 * 3] + pSrc2[ 4 * 3] + pSrc2[ 5 * 3] + a) >> 2) - 128; pDst[3] = ((pSrc1[ 6 * 3] + pSrc1[ 7 * 3] + pSrc2[ 6 * 3] + pSrc2[ 7 * 3] + b) >> 2) - 128; + pDst[4] = ((pSrc1[ 8 * 3] + pSrc1[ 9 * 3] + pSrc2[ 8 * 3] + pSrc2[ 9 * 3] + a) >> 2) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3] + pSrc2[10 * 3] + pSrc2[11 * 3] + b) >> 2) - 128; + pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3] + pSrc2[12 * 3] + pSrc2[13 * 3] + a) >> 2) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3] + pSrc2[14 * 3] + pSrc2[15 * 3] + b) >> 2) - 128; + int temp = a; a = b; b = temp; + } +} + +void jpeg_encoder::load_block_16_8_8(int x, int c) +{ + uint8 *pSrc1; + sample_array_t *pDst = m_sample_array; + x = (x * (16 * 3)) + c; + for (int i = 0; i < 8; i++, pDst += 8) + { + pSrc1 = m_mcu_lines[i + 0] + x; + pDst[0] = ((pSrc1[ 0 * 3] + pSrc1[ 1 * 3]) >> 1) - 128; pDst[1] = ((pSrc1[ 2 * 3] + pSrc1[ 3 * 3]) >> 1) - 128; + pDst[2] = ((pSrc1[ 4 * 3] + pSrc1[ 5 * 3]) >> 1) - 128; pDst[3] = ((pSrc1[ 6 * 3] + pSrc1[ 7 * 3]) >> 1) - 128; + pDst[4] = ((pSrc1[ 8 * 3] + pSrc1[ 9 * 3]) >> 1) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3]) >> 1) - 128; + pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3]) >> 1) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3]) >> 1) - 128; + } +} + +void jpeg_encoder::load_quantized_coefficients(int component_num) +{ + int32 *q = m_quantization_tables[component_num > 0]; + int16 *pDst = m_coefficient_array; + for (int i = 0; i < 64; i++) + { + sample_array_t j = m_sample_array[s_zag[i]]; + if (j < 0) + { + if ((j = -j + (*q >> 1)) < *q) + *pDst++ = 0; + else + *pDst++ = static_cast(-(j / *q)); + } + else + { + if ((j = j + (*q >> 1)) < *q) + *pDst++ = 0; + else + *pDst++ = static_cast((j / *q)); + } + q++; + } +} + +void jpeg_encoder::flush_output_buffer() +{ + if (m_out_buf_left != JPGE_OUT_BUF_SIZE) + m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_buf(m_out_buf, JPGE_OUT_BUF_SIZE - m_out_buf_left); + m_pOut_buf = m_out_buf; + m_out_buf_left = JPGE_OUT_BUF_SIZE; +} + +void jpeg_encoder::put_bits(uint bits, uint len) +{ + m_bit_buffer |= ((uint32)bits << (24 - (m_bits_in += len))); + while (m_bits_in >= 8) + { + uint8 c; + #define JPGE_PUT_BYTE(c) { *m_pOut_buf++ = (c); if (--m_out_buf_left == 0) flush_output_buffer(); } + JPGE_PUT_BYTE(c = (uint8)((m_bit_buffer >> 16) & 0xFF)); + if (c == 0xFF) JPGE_PUT_BYTE(0); + m_bit_buffer <<= 8; + m_bits_in -= 8; + } +} + +void jpeg_encoder::code_coefficients_pass_one(int component_num) +{ + if (component_num >= 3) return; // just to shut up static analysis + int i, run_len, nbits, temp1; + int16 *src = m_coefficient_array; + uint32 *dc_count = component_num ? m_huff_count[0 + 1] : m_huff_count[0 + 0], *ac_count = component_num ? m_huff_count[2 + 1] : m_huff_count[2 + 0]; + + temp1 = src[0] - m_last_dc_val[component_num]; + m_last_dc_val[component_num] = src[0]; + if (temp1 < 0) temp1 = -temp1; + + nbits = 0; + while (temp1) + { + nbits++; temp1 >>= 1; + } + + dc_count[nbits]++; + for (run_len = 0, i = 1; i < 64; i++) + { + if ((temp1 = m_coefficient_array[i]) == 0) + run_len++; + else + { + while (run_len >= 16) + { + ac_count[0xF0]++; + run_len -= 16; + } + if (temp1 < 0) temp1 = -temp1; + nbits = 1; + while (temp1 >>= 1) nbits++; + ac_count[(run_len << 4) + nbits]++; + run_len = 0; + } + } + if (run_len) ac_count[0]++; +} + +void jpeg_encoder::code_coefficients_pass_two(int component_num) +{ + int i, j, run_len, nbits, temp1, temp2; + int16 *pSrc = m_coefficient_array; + uint *codes[2]; + uint8 *code_sizes[2]; + + if (component_num == 0) + { + codes[0] = m_huff_codes[0 + 0]; codes[1] = m_huff_codes[2 + 0]; + code_sizes[0] = m_huff_code_sizes[0 + 0]; code_sizes[1] = m_huff_code_sizes[2 + 0]; + } + else + { + codes[0] = m_huff_codes[0 + 1]; codes[1] = m_huff_codes[2 + 1]; + code_sizes[0] = m_huff_code_sizes[0 + 1]; code_sizes[1] = m_huff_code_sizes[2 + 1]; + } + + temp1 = temp2 = pSrc[0] - m_last_dc_val[component_num]; + m_last_dc_val[component_num] = pSrc[0]; + + if (temp1 < 0) + { + temp1 = -temp1; temp2--; + } + + nbits = 0; + while (temp1) + { + nbits++; temp1 >>= 1; + } + + put_bits(codes[0][nbits], code_sizes[0][nbits]); + if (nbits) put_bits(temp2 & ((1 << nbits) - 1), nbits); + + for (run_len = 0, i = 1; i < 64; i++) + { + if ((temp1 = m_coefficient_array[i]) == 0) + run_len++; + else + { + while (run_len >= 16) + { + put_bits(codes[1][0xF0], code_sizes[1][0xF0]); + run_len -= 16; + } + if ((temp2 = temp1) < 0) + { + temp1 = -temp1; + temp2--; + } + nbits = 1; + while (temp1 >>= 1) + nbits++; + j = (run_len << 4) + nbits; + put_bits(codes[1][j], code_sizes[1][j]); + put_bits(temp2 & ((1 << nbits) - 1), nbits); + run_len = 0; + } + } + if (run_len) + put_bits(codes[1][0], code_sizes[1][0]); +} + +void jpeg_encoder::code_block(int component_num) +{ + DCT2D(m_sample_array); + load_quantized_coefficients(component_num); + if (m_pass_num == 1) + code_coefficients_pass_one(component_num); + else + code_coefficients_pass_two(component_num); +} + +void jpeg_encoder::process_mcu_row() +{ + if (m_num_components == 1) + { + for (int i = 0; i < m_mcus_per_row; i++) + { + load_block_8_8_grey(i); code_block(0); + } + } + else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1)) + { + for (int i = 0; i < m_mcus_per_row; i++) + { + load_block_8_8(i, 0, 0); code_block(0); load_block_8_8(i, 0, 1); code_block(1); load_block_8_8(i, 0, 2); code_block(2); + } + } + else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1)) + { + for (int i = 0; i < m_mcus_per_row; i++) + { + load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0); + load_block_16_8_8(i, 1); code_block(1); load_block_16_8_8(i, 2); code_block(2); + } + } + else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2)) + { + for (int i = 0; i < m_mcus_per_row; i++) + { + load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0); + load_block_8_8(i * 2 + 0, 1, 0); code_block(0); load_block_8_8(i * 2 + 1, 1, 0); code_block(0); + load_block_16_8(i, 1); code_block(1); load_block_16_8(i, 2); code_block(2); + } + } +} + +bool jpeg_encoder::terminate_pass_one() +{ + optimize_huffman_table(0+0, DC_LUM_CODES); optimize_huffman_table(2+0, AC_LUM_CODES); + if (m_num_components > 1) + { + optimize_huffman_table(0+1, DC_CHROMA_CODES); optimize_huffman_table(2+1, AC_CHROMA_CODES); + } + return second_pass_init(); +} + +bool jpeg_encoder::terminate_pass_two() +{ + put_bits(0x7F, 7); + flush_output_buffer(); + emit_marker(M_EOI); + m_pass_num++; // purposely bump up m_pass_num, for debugging + return true; +} + +bool jpeg_encoder::process_end_of_image() +{ + if (m_mcu_y_ofs) + { + if (m_mcu_y_ofs < 16) // check here just to shut up static analysis + { + for (int i = m_mcu_y_ofs; i < m_mcu_y; i++) + memcpy(m_mcu_lines[i], m_mcu_lines[m_mcu_y_ofs - 1], m_image_bpl_mcu); + } + + process_mcu_row(); + } + + if (m_pass_num == 1) + return terminate_pass_one(); + else + return terminate_pass_two(); +} + +void jpeg_encoder::load_mcu(const void *pSrc) +{ + const uint8* Psrc = reinterpret_cast(pSrc); + + uint8* pDst = m_mcu_lines[m_mcu_y_ofs]; // OK to write up to m_image_bpl_xlt bytes to pDst + + if (m_num_components == 1) + { + if (m_image_bpp == 4) + RGBA_to_Y(pDst, Psrc, m_image_x); + else if (m_image_bpp == 3) + RGB_to_Y(pDst, Psrc, m_image_x); + else + memcpy(pDst, Psrc, m_image_x); + } + else + { + if (m_image_bpp == 4) + RGBA_to_YCC(pDst, Psrc, m_image_x); + else if (m_image_bpp == 3) + RGB_to_YCC(pDst, Psrc, m_image_x); + else + Y_to_YCC(pDst, Psrc, m_image_x); + } + + // Possibly duplicate pixels at end of scanline if not a multiple of 8 or 16 + if (m_num_components == 1) + memset(m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt, pDst[m_image_bpl_xlt - 1], m_image_x_mcu - m_image_x); + else + { + const uint8 y = pDst[m_image_bpl_xlt - 3 + 0], cb = pDst[m_image_bpl_xlt - 3 + 1], cr = pDst[m_image_bpl_xlt - 3 + 2]; + uint8 *q = m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt; + for (int i = m_image_x; i < m_image_x_mcu; i++) + { + *q++ = y; *q++ = cb; *q++ = cr; + } + } + + if (++m_mcu_y_ofs == m_mcu_y) + { + process_mcu_row(); + m_mcu_y_ofs = 0; + } +} + +void jpeg_encoder::clear() +{ + m_mcu_lines[0] = NULL; + m_pass_num = 0; + m_all_stream_writes_succeeded = true; +} + +jpeg_encoder::jpeg_encoder() +{ + clear(); +} + +jpeg_encoder::~jpeg_encoder() +{ + deinit(); +} + +bool jpeg_encoder::init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params) +{ + deinit(); + if (((!pStream) || (width < 1) || (height < 1)) || ((src_channels != 1) && (src_channels != 3) && (src_channels != 4)) || (!comp_params.check())) return false; + m_pStream = pStream; + m_params = comp_params; + return jpg_open(width, height, src_channels); +} + +void jpeg_encoder::deinit() +{ + jpge_free(m_mcu_lines[0]); + clear(); +} + +bool jpeg_encoder::process_scanline(const void* pScanline) +{ + if ((m_pass_num < 1) || (m_pass_num > 2)) return false; + if (m_all_stream_writes_succeeded) + { + if (!pScanline) + { + if (!process_end_of_image()) return false; + } + else + { + load_mcu(pScanline); + } + } + return m_all_stream_writes_succeeded; +} + +// Higher level wrappers/examples (optional). +#include + +class cfile_stream : public output_stream +{ + cfile_stream(const cfile_stream &); + cfile_stream &operator= (const cfile_stream &); + + FILE* m_pFile; + bool m_bStatus; + +public: + cfile_stream() : m_pFile(NULL), m_bStatus(false) { } + + virtual ~cfile_stream() + { + close(); + } + + bool open(const char *pFilename) + { + close(); + m_pFile = fopen(pFilename, "wb"); + m_bStatus = (m_pFile != NULL); + return m_bStatus; + } + + bool close() + { + if (m_pFile) + { + if (fclose(m_pFile) == EOF) + { + m_bStatus = false; + } + m_pFile = NULL; + } + return m_bStatus; + } + + virtual bool put_buf(const void* pBuf, int len) + { + m_bStatus = m_bStatus && (fwrite(pBuf, len, 1, m_pFile) == 1); + return m_bStatus; + } + + uint get_size() const + { + return m_pFile ? ftell(m_pFile) : 0; + } +}; + +// Writes JPEG image to file. +bool compress_image_to_jpeg_file(const char *pFilename, int width, int height, int num_channels, const uint8 *pImage_data, const params &comp_params) +{ + cfile_stream dst_stream; + if (!dst_stream.open(pFilename)) + return false; + + jpge::jpeg_encoder dst_image; + if (!dst_image.init(&dst_stream, width, height, num_channels, comp_params)) + return false; + + for (uint pass_index = 0; pass_index < dst_image.get_total_passes(); pass_index++) + { + for (int i = 0; i < height; i++) + { + const uint8* pBuf = pImage_data + i * width * num_channels; + if (!dst_image.process_scanline(pBuf)) + return false; + } + if (!dst_image.process_scanline(NULL)) + return false; + } + + dst_image.deinit(); + + return dst_stream.close(); +} + +class memory_stream : public output_stream +{ + memory_stream(const memory_stream &); + memory_stream &operator= (const memory_stream &); + + uint8 *m_pBuf; + uint m_buf_size, m_buf_ofs; + +public: + memory_stream(void *pBuf, uint buf_size) : m_pBuf(static_cast(pBuf)), m_buf_size(buf_size), m_buf_ofs(0) { } + + virtual ~memory_stream() { } + + virtual bool put_buf(const void* pBuf, int len) + { + uint buf_remaining = m_buf_size - m_buf_ofs; + if ((uint)len > buf_remaining) + return false; + memcpy(m_pBuf + m_buf_ofs, pBuf, len); + m_buf_ofs += len; + return true; + } + + uint get_size() const + { + return m_buf_ofs; + } +}; + +bool compress_image_to_jpeg_file_in_memory(void *pDstBuf, int &buf_size, int width, int height, int num_channels, const uint8 *pImage_data, const params &comp_params) +{ + if ((!pDstBuf) || (!buf_size)) + return false; + + memory_stream dst_stream(pDstBuf, buf_size); + + buf_size = 0; + + jpge::jpeg_encoder dst_image; + if (!dst_image.init(&dst_stream, width, height, num_channels, comp_params)) + return false; + + for (uint pass_index = 0; pass_index < dst_image.get_total_passes(); pass_index++) + { + for (int i = 0; i < height; i++) + { + const uint8* pScanline = pImage_data + i * width * num_channels; + if (!dst_image.process_scanline(pScanline)) + return false; + } + if (!dst_image.process_scanline(NULL)) + return false; + } + + dst_image.deinit(); + + buf_size = dst_stream.get_size(); + return true; +} + +} // namespace jpge diff --git a/ext/jpge/jpge.h b/ext/jpge/jpge.h new file mode 100644 index 0000000000..262bbfbb38 --- /dev/null +++ b/ext/jpge/jpge.h @@ -0,0 +1,169 @@ +// jpge.h - C++ class for JPEG compression. +// Public domain, Rich Geldreich +// Alex Evans: Added RGBA support, linear memory allocator. +#ifndef JPEG_ENCODER_H +#define JPEG_ENCODER_H + +namespace jpge +{ + typedef unsigned char uint8; + typedef signed short int16; + typedef signed int int32; + typedef unsigned short uint16; + typedef unsigned int uint32; + typedef unsigned int uint; + + // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common. + enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 }; + + // JPEG compression parameters structure. + struct params + { + inline params() : m_quality(85), m_subsampling(H2V2), m_no_chroma_discrim_flag(false), m_two_pass_flag(false) { } + + inline bool check() const + { + if ((m_quality < 1) || (m_quality > 100)) return false; + if ((uint)m_subsampling > (uint)H2V2) return false; + return true; + } + + // Quality: 1-100, higher is better. Typical values are around 50-95. + int m_quality; + + // m_subsampling: + // 0 = Y (grayscale) only + // 1 = YCbCr, no subsampling (H1V1, YCbCr 1x1x1, 3 blocks per MCU) + // 2 = YCbCr, H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU) + // 3 = YCbCr, H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common) + subsampling_t m_subsampling; + + // Disables CbCr discrimination - only intended for testing. + // If true, the Y quantization table is also used for the CbCr channels. + bool m_no_chroma_discrim_flag; + + bool m_two_pass_flag; + }; + + // Writes JPEG image to a file. + // num_channels must be 1 (Y) or 3 (RGB), image pitch must be width*num_channels. + bool compress_image_to_jpeg_file(const char *pFilename, int width, int height, int num_channels, const uint8 *pImage_data, const params &comp_params = params()); + + // Writes JPEG image to memory buffer. + // On entry, buf_size is the size of the output buffer pointed at by pBuf, which should be at least ~1024 bytes. + // If return value is true, buf_size will be set to the size of the compressed data. + bool compress_image_to_jpeg_file_in_memory(void *pBuf, int &buf_size, int width, int height, int num_channels, const uint8 *pImage_data, const params &comp_params = params()); + + // Output stream abstract class - used by the jpeg_encoder class to write to the output stream. + // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts. + class output_stream + { + public: + virtual ~output_stream() { }; + virtual bool put_buf(const void* Pbuf, int len) = 0; + template inline bool put_obj(const T& obj) { return put_buf(&obj, sizeof(T)); } + }; + + // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions. + class jpeg_encoder + { + public: + jpeg_encoder(); + ~jpeg_encoder(); + + // Initializes the compressor. + // pStream: The stream object to use for writing compressed data. + // params - Compression parameters structure, defined above. + // width, height - Image dimensions. + // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data. + // Returns false on out of memory or if a stream write fails. + bool init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params = params()); + + const params &get_params() const { return m_params; } + + // Deinitializes the compressor, freeing any allocated memory. May be called at any time. + void deinit(); + + uint get_total_passes() const { return m_params.m_two_pass_flag ? 2 : 1; } + inline uint get_cur_pass() { return m_pass_num; } + + // Call this method with each source scanline. + // width * src_channels bytes per scanline is expected (RGB or Y format). + // You must call with NULL after all scanlines are processed to finish compression. + // Returns false on out of memory or if a stream write fails. + bool process_scanline(const void* pScanline); + + private: + jpeg_encoder(const jpeg_encoder &); + jpeg_encoder &operator =(const jpeg_encoder &); + + typedef int32 sample_array_t; + + output_stream *m_pStream; + params m_params; + uint8 m_num_components; + uint8 m_comp_h_samp[3], m_comp_v_samp[3]; + int m_image_x, m_image_y, m_image_bpp, m_image_bpl; + int m_image_x_mcu, m_image_y_mcu; + int m_image_bpl_xlt, m_image_bpl_mcu; + int m_mcus_per_row; + int m_mcu_x, m_mcu_y; + uint8 *m_mcu_lines[16]; + uint8 m_mcu_y_ofs; + sample_array_t m_sample_array[64]; + int16 m_coefficient_array[64]; + int32 m_quantization_tables[2][64]; + uint m_huff_codes[4][256]; + uint8 m_huff_code_sizes[4][256]; + uint8 m_huff_bits[4][17]; + uint8 m_huff_val[4][256]; + uint32 m_huff_count[4][256]; + int m_last_dc_val[3]; + enum { JPGE_OUT_BUF_SIZE = 2048 }; + uint8 m_out_buf[JPGE_OUT_BUF_SIZE]; + uint8 *m_pOut_buf; + uint m_out_buf_left; + uint32 m_bit_buffer; + uint m_bits_in; + uint8 m_pass_num; + bool m_all_stream_writes_succeeded; + + void optimize_huffman_table(int table_num, int table_len); + void emit_byte(uint8 i); + void emit_word(uint i); + void emit_marker(int marker); + void emit_jfif_app0(); + void emit_dqt(); + void emit_sof(); + void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag); + void emit_dhts(); + void emit_sos(); + void emit_markers(); + void compute_huffman_table(uint *codes, uint8 *code_sizes, uint8 *bits, uint8 *val); + void compute_quant_table(int32 *dst, int16 *src); + void adjust_quant_table(int32 *dst, int32 *src); + void first_pass_init(); + bool second_pass_init(); + bool jpg_open(int p_x_res, int p_y_res, int src_channels); + void load_block_8_8_grey(int x); + void load_block_8_8(int x, int y, int c); + void load_block_16_8(int x, int c); + void load_block_16_8_8(int x, int c); + void load_quantized_coefficients(int component_num); + void flush_output_buffer(); + void put_bits(uint bits, uint len); + void code_coefficients_pass_one(int component_num); + void code_coefficients_pass_two(int component_num); + void code_block(int component_num); + void process_mcu_row(); + bool terminate_pass_one(); + bool terminate_pass_two(); + bool process_end_of_image(); + void load_mcu(const void* src); + void clear(); + void init(); + }; + +} // namespace jpge + +#endif // JPEG_ENCODER diff --git a/ext/jpge/publicdomain.txt b/ext/jpge/publicdomain.txt new file mode 100644 index 0000000000..639860563a --- /dev/null +++ b/ext/jpge/publicdomain.txt @@ -0,0 +1 @@ +This is https://code.google.com/p/jpeg-compressor/ , public domain code. \ No newline at end of file diff --git a/native.vcxproj b/native.vcxproj index 71ed381080..bc4efef2cd 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -198,6 +198,7 @@ + @@ -321,6 +322,7 @@ Default Default + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index a2bf0c0750..99f79b14a8 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -273,6 +273,7 @@ data + @@ -484,6 +485,7 @@ data + From 80c85b1c604ccead734d595dd7f67656f3fd9d85 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 23 Jun 2013 17:15:29 +0200 Subject: [PATCH 0468/1445] Notify all the screens in the stack that the device was lost. --- ui/screen.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index 7bd05e619c..12b9da6118 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -96,8 +96,9 @@ void ScreenManager::sendMessage(const char *msg, const char *value) { } void ScreenManager::deviceLost() { - if (!stack_.empty()) - stack_.back().screen->deviceLost(); + for (size_t i = 0; i < stack_.size(); i++) { + stack_[i].screen->deviceLost(); + } // Dialogs too? Nah, they should only use the standard UI texture anyway. // TODO: Change this when it becomes necessary. } From 9963d004475eb65a2015d5bb2d7df0fd44903d68 Mon Sep 17 00:00:00 2001 From: Daniel Dressler Date: Sun, 23 Jun 2013 22:06:41 -0700 Subject: [PATCH 0469/1445] Add platform independent keyboard key codes --- input/keyboard_keys.h | 151 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 input/keyboard_keys.h diff --git a/input/keyboard_keys.h b/input/keyboard_keys.h new file mode 100644 index 0000000000..b147baeb1f --- /dev/null +++ b/input/keyboard_keys.h @@ -0,0 +1,151 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program 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.0 or later versions. + +// This program 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. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +typedef enum { + // Lower class latin + KEY_q = 1, // top row + KEY_w, + KEY_e, + KEY_r, + KEY_t, + KEY_y, + KEY_u, + KEY_i, + KEY_o, + KEY_p, + + KEY_a, // mid row + KEY_s, + KEY_d, + KEY_f, + KEY_g, + KEY_h, + KEY_j, + KEY_k, + KEY_l, + + KEY_z, // low row + KEY_x, + KEY_c, + KEY_v, + KEY_b, + KEY_n, + KEY_m, + + // Upper class latin + KEY_Q, // top row + KEY_W, + KEY_E, + KEY_R, + KEY_T, + KEY_Y, + KEY_U, + KEY_I, + KEY_O, + KEY_P, + + KEY_A, // mid row + KEY_S, + KEY_D, + KEY_F, + KEY_G, + KEY_H, + KEY_J, + KEY_K, + KEY_L, + + KEY_Z, // low row + KEY_X, + KEY_C, + KEY_V, + KEY_B, + KEY_N, + KEY_M, + + + // Numeric + KEY_1, + KEY_2, + KEY_3, + KEY_4, + KEY_5, + KEY_6, + KEY_7, + KEY_8, + KEY_9, + KEY_0, + + // Special keys + KEY_ARROW_LEFT, + KEY_ARROW_RIGHT, + KEY_ARROW_UP, + KEY_ARROW_DOWN, + + KEY_ANALOG_LEFT, + KEY_ANALOG_RIGHT, + KEY_ANALOG_UP, + KEY_ANALOG_DOWN, + + KEY_ANALOG_ALT_LEFT, + KEY_ANALOG_ALT_RIGHT, + KEY_ANALOG_ALT_UP, + KEY_ANALOG_ALT_DOWN, + + KEY_SPACE, + KEY_ENTER, + KEY_CTRL_LEFT, + KEY_CTRL_RIGHT, + KEY_SHIFT_LEFT, + KEY_SHIFT_RIGHT, + KEY_ALT_LEFT, + KEY_ALT_RIGHT, + KEY_BACKSPACE, + KEY_SUPER, + KEY_TAB, + + // Mobile Keys + KEY_VOLUME_UP, + KEY_VOLUME_DOWN, + KEY_HOME, + KEY_CALL_START, + KEY_CALL_END, + + // Special PPSSPP keys + KEY_FASTFORWARD, + + // Extra keys + // Use for platform specific keys. + // Example: android's back btn + KEY_EXTRA1, + KEY_EXTRA2, + KEY_EXTRA3, + KEY_EXTRA4, + KEY_EXTRA5, + KEY_EXTRA6, + KEY_EXTRA7, + KEY_EXTRA8, + KEY_EXTRA9, + KEY_EXTRA0, + + // TODO: Add any missing keys. + // Many can be found in the + // window's port's keyboard + // files. +} kb_key_t; + From ec66427904188875cdda2f72a64e3e6769d55f8b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Jun 2013 19:36:53 -0700 Subject: [PATCH 0470/1445] Cut down on CHECK() and FLOG() in Buffer. Also add a buffer copy (would rather not read into the wrong buffer to start, but it happens...) --- base/buffer.cpp | 28 +++++++++++++++++++++------- base/buffer.h | 5 +++-- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index f618727c02..38900e0017 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -36,6 +36,12 @@ void Buffer::Append(const char *str) { memcpy(dest, str, len); } +void Buffer::Append(const Buffer &other) { + size_t len = other.size(); + char *dest = Append(len); + memcpy(dest, &other.data_[0], len); +} + void Buffer::AppendValue(int value) { char buf[16]; // This is slow. @@ -44,8 +50,11 @@ void Buffer::AppendValue(int value) { } void Buffer::Take(size_t length, std::string *dest) { - CHECK_LE(length, data_.size()); - dest->resize(length); + if (length > data_.size()) { + ELOG("Truncating length in Buffer::Take()"); + length = data_.size(); + } + dest->resize(length); if (length > 0) { memcpy(&(*dest)[0], &data_[0], length); data_.erase(data_.begin(), data_.begin() + length); @@ -64,7 +73,11 @@ int Buffer::TakeLineCRLF(std::string *dest) { } void Buffer::Skip(size_t length) { - data_.erase(data_.begin(), data_.begin() + length); + if (length > data_.size()) { + ELOG("Truncating length in Buffer::Skip()"); + length = data_.size(); + } + data_.erase(data_.begin(), data_.begin() + length); } int Buffer::SkipLineCRLF() { @@ -87,18 +100,19 @@ int Buffer::OffsetToAfterNextCRLF() { } void Buffer::Printf(const char *fmt, ...) { - char buffer[512]; + char buffer[2048]; va_list vl; va_start(vl, fmt); ssize_t retval = vsnprintf(buffer, sizeof(buffer), fmt, vl); if (retval >= (ssize_t)sizeof(buffer)) { // Output was truncated. TODO: Do something. - FLOG("Buffer::Printf truncated output"); + ELOG("Buffer::Printf truncated output"); + } + if (retval < 0) { + ELOG("Buffer::Printf failed"); } - CHECK_GE(retval, 0); va_end(vl); char *ptr = Append(retval); - CHECK(ptr); memcpy(ptr, buffer, retval); } diff --git a/base/buffer.h b/base/buffer.h index ff6fa9e1ab..0ebf7e3f2b 100644 --- a/base/buffer.h +++ b/base/buffer.h @@ -19,9 +19,10 @@ class Buffer { char *Append(ssize_t length); char *Append(size_t length) { return Append((ssize_t)length); } - // These work pretty much like you'd expect. + // These work pretty much like you'd expect. void Append(const char *str); // str null-terminated. The null is not copied. - void Append(const std::string &str); + void Append(const std::string &str); + void Append(const Buffer &other); // Various types. Useful for varz etc. Appends a string representation of the // value, rather than a binary representation. From 760c919408fdafe4873a8d2f273b926c32a7ec62 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Jun 2013 19:37:47 -0700 Subject: [PATCH 0471/1445] Add a NULL check, even though this is already called via a check. --- net/resolve.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/resolve.cpp b/net/resolve.cpp index 4b18a05a3b..304f3356cb 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -121,7 +121,8 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo ** void DNSResolveFree(addrinfo *res) { - freeaddrinfo(res); + if (res != NULL) + freeaddrinfo(res); } int inet_pton(int af, const char* src, void* dst) From 6c638a5f841bee02146a26b299be8add1ed14fb8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Jun 2013 19:38:57 -0700 Subject: [PATCH 0472/1445] Avoid a CHECK() in Connect(), and invalidate sock(). --- net/http_client.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 9c01458663..b362b9b202 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -66,9 +66,12 @@ bool Connection::Resolve(const char *host, int port) { } bool Connection::Connect() { - CHECK_GE(port_, 0); + if (port_ <= 0) { + ELOG("Bad port"); + return false; + } sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if ((intptr_t)sock_ < 0) { + if ((intptr_t)sock_ == -1) { ELOG("Bad socket"); return false; } @@ -89,6 +92,10 @@ bool Connection::Connect() { sleep(1); #endif } + + // Let's not leak this socket. + closesocket(sock_); + sock_ = -1; return false; } From 8c999885d8bd74113ef4231641b75e71430aab16 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Jun 2013 19:40:24 -0700 Subject: [PATCH 0473/1445] Support non-chunked HTTP responses. --- net/http_client.cpp | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index b362b9b202..a48585f045 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -172,25 +172,52 @@ int Client::GET(const char *resource, Buffer *output) { std::string line; readbuf.TakeLineCRLF(&line); - int code = atoi(&line[line.find(" ") + 1]); + + int code; + size_t code_pos = line.find(' '); + if (code_pos != line.npos) { + code_pos = line.find_first_not_of(' ', code_pos); + } + if (code_pos != line.npos) { + code = atoi(&line[code_pos]); + } else { + return -1; + } bool gzip = false; + bool chunked = false; int contentLength = 0; while (true) { int sz = readbuf.TakeLineCRLF(&line); if (!sz) break; + // TODO: Case folding. if (startsWith(line, "Content-Length:")) { - contentLength = atoi(&line[16]); + size_t size_pos = line.find_first_of(' '); + if (size_pos != line.npos) { + size_pos = line.find_first_not_of(' ', size_pos); + } + if (size_pos != line.npos) { + contentLength = atoi(&line[size_pos]); + chunked = false; + } } else if (startsWith(line, "Content-Encoding:")) { if (line.find("gzip") != std::string::npos) { gzip = true; } + } else if (startsWith(line, "Transfer-Encoding:")) { + if (line.find("chunked") != std::string::npos) { + chunked = true; + } } } // output now contains the rest of the reply. Dechunk it. - DeChunk(&readbuf, output); + if (chunked) { + DeChunk(&readbuf, output); + } else { + output->Append(readbuf); + } // If it's gzipped, we decompress it and put it back in the buffer. if (gzip) { From 697c0df4fd2ae4012fa10f73c999351b2fd8722d Mon Sep 17 00:00:00 2001 From: Daniel Dressler Date: Mon, 24 Jun 2013 21:46:56 -0700 Subject: [PATCH 0474/1445] Make native's keycodes based on android's keycods --- android/app-android.h | 217 +-------------------------------------- input/keyboard_keys.h | 151 --------------------------- input/keycodes.h | 232 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 236 insertions(+), 364 deletions(-) delete mode 100644 input/keyboard_keys.h create mode 100644 input/keycodes.h diff --git a/android/app-android.h b/android/app-android.h index c741f37361..002e68ed12 100644 --- a/android/app-android.h +++ b/android/app-android.h @@ -1,218 +1,9 @@ #pragma once -// For Xperia Play support -enum AndroidKeyCodes { - KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed - KEYCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed - KEYCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) - KEYCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed - KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed - KEYCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed - KEYCODE_DPAD_LEFT = 21, - KEYCODE_DPAD_UP = 19, - KEYCODE_DPAD_RIGHT = 22, - KEYCODE_DPAD_DOWN = 20, - KEYCODE_DPAD_CENTER = 23, - KEYCODE_UNKNOWN = 0, - KEYCODE_SOFT_LEFT = 1, - KEYCODE_SOFT_RIGHT = 2, - KEYCODE_HOME = 3, - KEYCODE_BACK = 4, - KEYCODE_CALL = 5, - KEYCODE_ENDCALL = 6, - KEYCODE_0 = 7, - KEYCODE_1 = 8, - KEYCODE_2 = 9, - KEYCODE_3 = 10, - KEYCODE_4 = 11, - KEYCODE_5 = 12, - KEYCODE_6 = 13, - KEYCODE_7 = 14, - KEYCODE_8 = 15, - KEYCODE_9 = 16, - KEYCODE_STAR = 17, - KEYCODE_POUND = 18, - KEYCODE_VOLUME_UP = 24, - KEYCODE_VOLUME_DOWN = 25, - KEYCODE_POWER = 26, - KEYCODE_CAMERA = 27, - KEYCODE_CLEAR = 28, - KEYCODE_A = 29, - KEYCODE_B = 30, - KEYCODE_C = 31, - KEYCODE_D = 32, - KEYCODE_E = 33, - KEYCODE_F = 34, - KEYCODE_G = 35, - KEYCODE_H = 36, - KEYCODE_I = 37, - KEYCODE_J = 38, - KEYCODE_K = 39, - KEYCODE_L = 40, - KEYCODE_M = 41, - KEYCODE_N = 42, - KEYCODE_O = 43, - KEYCODE_P = 44, - KEYCODE_Q = 45, - KEYCODE_R = 46, - KEYCODE_S = 47, - KEYCODE_T = 48, - KEYCODE_U = 49, - KEYCODE_V = 50, - KEYCODE_W = 51, - KEYCODE_X = 52, - KEYCODE_Y = 53, - KEYCODE_Z = 54, - KEYCODE_COMMA = 55, - KEYCODE_PERIOD = 56, - KEYCODE_ALT_LEFT = 57, - KEYCODE_ALT_RIGHT = 58, - KEYCODE_SHIFT_LEFT = 59, - KEYCODE_SHIFT_RIGHT = 60, - KEYCODE_TAB = 61, - KEYCODE_SPACE = 62, - KEYCODE_SYM = 63, - KEYCODE_EXPLORER = 64, - KEYCODE_ENVELOPE = 65, - KEYCODE_ENTER = 66, - KEYCODE_DEL = 67, - KEYCODE_GRAVE = 68, - KEYCODE_MINUS = 69, - KEYCODE_EQUALS = 70, - KEYCODE_LEFT_BRACKET = 71, - KEYCODE_RIGHT_BRACKET = 72, - KEYCODE_BACKSLASH = 73, - KEYCODE_SEMICOLON = 74, - KEYCODE_APOSTROPHE = 75, - KEYCODE_SLASH = 76, - KEYCODE_AT = 77, - KEYCODE_NUM = 78, - KEYCODE_HEADSETHOOK = 79, - KEYCODE_FOCUS = 80, - KEYCODE_PLUS = 81, - KEYCODE_MENU = 82, - KEYCODE_NOTIFICATION = 83, - KEYCODE_SEARCH = 84, - KEYCODE_MEDIA_PLAY_PAUSE = 85, - KEYCODE_MEDIA_STOP = 86, - KEYCODE_MEDIA_NEXT = 87, - KEYCODE_MEDIA_PREVIOUS = 88, - KEYCODE_MEDIA_REWIND = 89, - KEYCODE_MEDIA_FAST_FORWARD = 90, - KEYCODE_MUTE = 91, - KEYCODE_PAGE_UP = 92, - KEYCODE_PAGE_DOWN = 93, - KEYCODE_PICTSYMBOLS = 94, - KEYCODE_SWITCH_CHARSET = 95, - KEYCODE_BUTTON_A = 96, - KEYCODE_BUTTON_B = 97, - KEYCODE_BUTTON_C = 98, - KEYCODE_BUTTON_X = 99, - KEYCODE_BUTTON_Y = 100, - KEYCODE_BUTTON_Z = 101, - KEYCODE_BUTTON_L1 = 102, - KEYCODE_BUTTON_R1 = 103, - KEYCODE_BUTTON_L2 = 104, - KEYCODE_BUTTON_R2 = 105, - KEYCODE_BUTTON_THUMBL = 106, - KEYCODE_BUTTON_THUMBR = 107, - KEYCODE_BUTTON_START = 108, - KEYCODE_BUTTON_SELECT = 109, - KEYCODE_BUTTON_MODE = 110, - KEYCODE_ESCAPE = 111, - KEYCODE_FORWARD_DEL = 112, - KEYCODE_CTRL_LEFT = 113, - KEYCODE_CTRL_RIGHT = 114, - KEYCODE_CAPS_LOCK = 115, - KEYCODE_SCROLL_LOCK = 116, - KEYCODE_META_LEFT = 117, - KEYCODE_META_RIGHT = 118, - KEYCODE_FUNCTION = 119, - KEYCODE_SYSRQ = 120, - KEYCODE_BREAK = 121, - KEYCODE_MOVE_HOME = 122, - KEYCODE_MOVE_END = 123, - KEYCODE_INSERT = 124, - KEYCODE_FORWARD = 125, - KEYCODE_MEDIA_PLAY = 126, - KEYCODE_MEDIA_PAUSE = 127, - KEYCODE_MEDIA_CLOSE = 128, - KEYCODE_MEDIA_EJECT = 129, - KEYCODE_MEDIA_RECORD = 130, - KEYCODE_F1 = 131, - KEYCODE_F2 = 132, - KEYCODE_F3 = 133, - KEYCODE_F4 = 134, - KEYCODE_F5 = 135, - KEYCODE_F6 = 136, - KEYCODE_F7 = 137, - KEYCODE_F8 = 138, - KEYCODE_F9 = 139, - KEYCODE_F10 = 140, - KEYCODE_F11 = 141, - KEYCODE_F12 = 142, - KEYCODE_NUM_LOCK = 143, - KEYCODE_NUMPAD_0 = 144, - KEYCODE_NUMPAD_1 = 145, - KEYCODE_NUMPAD_2 = 146, - KEYCODE_NUMPAD_3 = 147, - KEYCODE_NUMPAD_4 = 148, - KEYCODE_NUMPAD_5 = 149, - KEYCODE_NUMPAD_6 = 150, - KEYCODE_NUMPAD_7 = 151, - KEYCODE_NUMPAD_8 = 152, - KEYCODE_NUMPAD_9 = 153, - KEYCODE_NUMPAD_DIVIDE = 154, - KEYCODE_NUMPAD_MULTIPLY = 155, - KEYCODE_NUMPAD_SUBTRACT = 156, - KEYCODE_NUMPAD_ADD = 157, - KEYCODE_NUMPAD_DOT = 158, - KEYCODE_NUMPAD_COMMA = 159, - KEYCODE_NUMPAD_ENTER = 160, - KEYCODE_NUMPAD_EQUALS = 161, - KEYCODE_NUMPAD_LEFT_PAREN = 162, - KEYCODE_NUMPAD_RIGHT_PAREN = 163, - KEYCODE_VOLUME_MUTE = 164, - KEYCODE_INFO = 165, - KEYCODE_CHANNEL_UP = 166, - KEYCODE_CHANNEL_DOWN = 167, - KEYCODE_ZOOM_IN = 168, - KEYCODE_ZOOM_OUT = 169, - KEYCODE_TV = 170, - KEYCODE_WINDOW = 171, - KEYCODE_GUIDE = 172, - KEYCODE_DVR = 173, - KEYCODE_BOOKMARK = 174, - KEYCODE_CAPTIONS = 175, - KEYCODE_SETTINGS = 176, - KEYCODE_TV_POWER = 177, - KEYCODE_TV_INPUT = 178, - KEYCODE_STB_POWER = 179, - KEYCODE_STB_INPUT = 180, - KEYCODE_AVR_POWER = 181, - KEYCODE_AVR_INPUT = 182, - KEYCODE_PROG_RED = 183, - KEYCODE_PROG_GREEN = 184, - KEYCODE_PROG_YELLOW = 185, - KEYCODE_PROG_BLUE = 186, - KEYCODE_APP_SWITCH = 187, - KEYCODE_BUTTON_1 = 188, - KEYCODE_BUTTON_2 = 189, - KEYCODE_BUTTON_3 = 190, - KEYCODE_BUTTON_4 = 191, - KEYCODE_BUTTON_5 = 192, - KEYCODE_BUTTON_6 = 193, - KEYCODE_BUTTON_7 = 194, - KEYCODE_BUTTON_8 = 195, - KEYCODE_BUTTON_9 = 196, - KEYCODE_BUTTON_10 = 197, - KEYCODE_BUTTON_11 = 198, - KEYCODE_BUTTON_12 = 199, - KEYCODE_BUTTON_13 = 200, - KEYCODE_BUTTON_14 = 201, - KEYCODE_BUTTON_15 = 202, - KEYCODE_BUTTON_16 = 203, -}; +// Compatability we alias the keycodes +// since native's keycodes are based on +// android keycodes. +typedef enum _keycode_t enum AndroidKeyCodes; enum AndroidJoystickAxis { // Field descriptor #15 I diff --git a/input/keyboard_keys.h b/input/keyboard_keys.h deleted file mode 100644 index b147baeb1f..0000000000 --- a/input/keyboard_keys.h +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2013- PPSSPP Project. - -// This program 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.0 or later versions. - -// This program 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. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -typedef enum { - // Lower class latin - KEY_q = 1, // top row - KEY_w, - KEY_e, - KEY_r, - KEY_t, - KEY_y, - KEY_u, - KEY_i, - KEY_o, - KEY_p, - - KEY_a, // mid row - KEY_s, - KEY_d, - KEY_f, - KEY_g, - KEY_h, - KEY_j, - KEY_k, - KEY_l, - - KEY_z, // low row - KEY_x, - KEY_c, - KEY_v, - KEY_b, - KEY_n, - KEY_m, - - // Upper class latin - KEY_Q, // top row - KEY_W, - KEY_E, - KEY_R, - KEY_T, - KEY_Y, - KEY_U, - KEY_I, - KEY_O, - KEY_P, - - KEY_A, // mid row - KEY_S, - KEY_D, - KEY_F, - KEY_G, - KEY_H, - KEY_J, - KEY_K, - KEY_L, - - KEY_Z, // low row - KEY_X, - KEY_C, - KEY_V, - KEY_B, - KEY_N, - KEY_M, - - - // Numeric - KEY_1, - KEY_2, - KEY_3, - KEY_4, - KEY_5, - KEY_6, - KEY_7, - KEY_8, - KEY_9, - KEY_0, - - // Special keys - KEY_ARROW_LEFT, - KEY_ARROW_RIGHT, - KEY_ARROW_UP, - KEY_ARROW_DOWN, - - KEY_ANALOG_LEFT, - KEY_ANALOG_RIGHT, - KEY_ANALOG_UP, - KEY_ANALOG_DOWN, - - KEY_ANALOG_ALT_LEFT, - KEY_ANALOG_ALT_RIGHT, - KEY_ANALOG_ALT_UP, - KEY_ANALOG_ALT_DOWN, - - KEY_SPACE, - KEY_ENTER, - KEY_CTRL_LEFT, - KEY_CTRL_RIGHT, - KEY_SHIFT_LEFT, - KEY_SHIFT_RIGHT, - KEY_ALT_LEFT, - KEY_ALT_RIGHT, - KEY_BACKSPACE, - KEY_SUPER, - KEY_TAB, - - // Mobile Keys - KEY_VOLUME_UP, - KEY_VOLUME_DOWN, - KEY_HOME, - KEY_CALL_START, - KEY_CALL_END, - - // Special PPSSPP keys - KEY_FASTFORWARD, - - // Extra keys - // Use for platform specific keys. - // Example: android's back btn - KEY_EXTRA1, - KEY_EXTRA2, - KEY_EXTRA3, - KEY_EXTRA4, - KEY_EXTRA5, - KEY_EXTRA6, - KEY_EXTRA7, - KEY_EXTRA8, - KEY_EXTRA9, - KEY_EXTRA0, - - // TODO: Add any missing keys. - // Many can be found in the - // window's port's keyboard - // files. -} kb_key_t; - diff --git a/input/keycodes.h b/input/keycodes.h new file mode 100644 index 0000000000..6323e1a468 --- /dev/null +++ b/input/keycodes.h @@ -0,0 +1,232 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program 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.0 or later versions. + +// This program 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. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +typedef enum _keycode_t { + KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed + KEYCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed + KEYCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) + KEYCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed + KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed + KEYCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed + KEYCODE_DPAD_LEFT = 21, + KEYCODE_DPAD_UP = 19, + KEYCODE_DPAD_RIGHT = 22, + KEYCODE_DPAD_DOWN = 20, + KEYCODE_DPAD_CENTER = 23, + KEYCODE_UNKNOWN = 0, + KEYCODE_SOFT_LEFT = 1, + KEYCODE_SOFT_RIGHT = 2, + KEYCODE_HOME = 3, + KEYCODE_BACK = 4, + KEYCODE_CALL = 5, + KEYCODE_ENDCALL = 6, + KEYCODE_0 = 7, + KEYCODE_1 = 8, + KEYCODE_2 = 9, + KEYCODE_3 = 10, + KEYCODE_4 = 11, + KEYCODE_5 = 12, + KEYCODE_6 = 13, + KEYCODE_7 = 14, + KEYCODE_8 = 15, + KEYCODE_9 = 16, + KEYCODE_STAR = 17, + KEYCODE_POUND = 18, + KEYCODE_VOLUME_UP = 24, + KEYCODE_VOLUME_DOWN = 25, + KEYCODE_POWER = 26, + KEYCODE_CAMERA = 27, + KEYCODE_CLEAR = 28, + KEYCODE_A = 29, + KEYCODE_B = 30, + KEYCODE_C = 31, + KEYCODE_D = 32, + KEYCODE_E = 33, + KEYCODE_F = 34, + KEYCODE_G = 35, + KEYCODE_H = 36, + KEYCODE_I = 37, + KEYCODE_J = 38, + KEYCODE_K = 39, + KEYCODE_L = 40, + KEYCODE_M = 41, + KEYCODE_N = 42, + KEYCODE_O = 43, + KEYCODE_P = 44, + KEYCODE_Q = 45, + KEYCODE_R = 46, + KEYCODE_S = 47, + KEYCODE_T = 48, + KEYCODE_U = 49, + KEYCODE_V = 50, + KEYCODE_W = 51, + KEYCODE_X = 52, + KEYCODE_Y = 53, + KEYCODE_Z = 54, + KEYCODE_COMMA = 55, + KEYCODE_PERIOD = 56, + KEYCODE_ALT_LEFT = 57, + KEYCODE_ALT_RIGHT = 58, + KEYCODE_SHIFT_LEFT = 59, + KEYCODE_SHIFT_RIGHT = 60, + KEYCODE_TAB = 61, + KEYCODE_SPACE = 62, + KEYCODE_SYM = 63, + KEYCODE_EXPLORER = 64, + KEYCODE_ENVELOPE = 65, + KEYCODE_ENTER = 66, + KEYCODE_DEL = 67, + KEYCODE_GRAVE = 68, + KEYCODE_MINUS = 69, + KEYCODE_EQUALS = 70, + KEYCODE_LEFT_BRACKET = 71, + KEYCODE_RIGHT_BRACKET = 72, + KEYCODE_BACKSLASH = 73, + KEYCODE_SEMICOLON = 74, + KEYCODE_APOSTROPHE = 75, + KEYCODE_SLASH = 76, + KEYCODE_AT = 77, + KEYCODE_NUM = 78, + KEYCODE_HEADSETHOOK = 79, + KEYCODE_FOCUS = 80, + KEYCODE_PLUS = 81, + KEYCODE_MENU = 82, + KEYCODE_NOTIFICATION = 83, + KEYCODE_SEARCH = 84, + KEYCODE_MEDIA_PLAY_PAUSE = 85, + KEYCODE_MEDIA_STOP = 86, + KEYCODE_MEDIA_NEXT = 87, + KEYCODE_MEDIA_PREVIOUS = 88, + KEYCODE_MEDIA_REWIND = 89, + KEYCODE_MEDIA_FAST_FORWARD = 90, + KEYCODE_MUTE = 91, + KEYCODE_PAGE_UP = 92, + KEYCODE_PAGE_DOWN = 93, + KEYCODE_PICTSYMBOLS = 94, + KEYCODE_SWITCH_CHARSET = 95, + KEYCODE_BUTTON_A = 96, + KEYCODE_BUTTON_B = 97, + KEYCODE_BUTTON_C = 98, + KEYCODE_BUTTON_X = 99, + KEYCODE_BUTTON_Y = 100, + KEYCODE_BUTTON_Z = 101, + KEYCODE_BUTTON_L1 = 102, + KEYCODE_BUTTON_R1 = 103, + KEYCODE_BUTTON_L2 = 104, + KEYCODE_BUTTON_R2 = 105, + KEYCODE_BUTTON_THUMBL = 106, + KEYCODE_BUTTON_THUMBR = 107, + KEYCODE_BUTTON_START = 108, + KEYCODE_BUTTON_SELECT = 109, + KEYCODE_BUTTON_MODE = 110, + KEYCODE_ESCAPE = 111, + KEYCODE_FORWARD_DEL = 112, + KEYCODE_CTRL_LEFT = 113, + KEYCODE_CTRL_RIGHT = 114, + KEYCODE_CAPS_LOCK = 115, + KEYCODE_SCROLL_LOCK = 116, + KEYCODE_META_LEFT = 117, + KEYCODE_META_RIGHT = 118, + KEYCODE_FUNCTION = 119, + KEYCODE_SYSRQ = 120, + KEYCODE_BREAK = 121, + KEYCODE_MOVE_HOME = 122, + KEYCODE_MOVE_END = 123, + KEYCODE_INSERT = 124, + KEYCODE_FORWARD = 125, + KEYCODE_MEDIA_PLAY = 126, + KEYCODE_MEDIA_PAUSE = 127, + KEYCODE_MEDIA_CLOSE = 128, + KEYCODE_MEDIA_EJECT = 129, + KEYCODE_MEDIA_RECORD = 130, + KEYCODE_F1 = 131, + KEYCODE_F2 = 132, + KEYCODE_F3 = 133, + KEYCODE_F4 = 134, + KEYCODE_F5 = 135, + KEYCODE_F6 = 136, + KEYCODE_F7 = 137, + KEYCODE_F8 = 138, + KEYCODE_F9 = 139, + KEYCODE_F10 = 140, + KEYCODE_F11 = 141, + KEYCODE_F12 = 142, + KEYCODE_NUM_LOCK = 143, + KEYCODE_NUMPAD_0 = 144, + KEYCODE_NUMPAD_1 = 145, + KEYCODE_NUMPAD_2 = 146, + KEYCODE_NUMPAD_3 = 147, + KEYCODE_NUMPAD_4 = 148, + KEYCODE_NUMPAD_5 = 149, + KEYCODE_NUMPAD_6 = 150, + KEYCODE_NUMPAD_7 = 151, + KEYCODE_NUMPAD_8 = 152, + KEYCODE_NUMPAD_9 = 153, + KEYCODE_NUMPAD_DIVIDE = 154, + KEYCODE_NUMPAD_MULTIPLY = 155, + KEYCODE_NUMPAD_SUBTRACT = 156, + KEYCODE_NUMPAD_ADD = 157, + KEYCODE_NUMPAD_DOT = 158, + KEYCODE_NUMPAD_COMMA = 159, + KEYCODE_NUMPAD_ENTER = 160, + KEYCODE_NUMPAD_EQUALS = 161, + KEYCODE_NUMPAD_LEFT_PAREN = 162, + KEYCODE_NUMPAD_RIGHT_PAREN = 163, + KEYCODE_VOLUME_MUTE = 164, + KEYCODE_INFO = 165, + KEYCODE_CHANNEL_UP = 166, + KEYCODE_CHANNEL_DOWN = 167, + KEYCODE_ZOOM_IN = 168, + KEYCODE_ZOOM_OUT = 169, + KEYCODE_TV = 170, + KEYCODE_WINDOW = 171, + KEYCODE_GUIDE = 172, + KEYCODE_DVR = 173, + KEYCODE_BOOKMARK = 174, + KEYCODE_CAPTIONS = 175, + KEYCODE_SETTINGS = 176, + KEYCODE_TV_POWER = 177, + KEYCODE_TV_INPUT = 178, + KEYCODE_STB_POWER = 179, + KEYCODE_STB_INPUT = 180, + KEYCODE_AVR_POWER = 181, + KEYCODE_AVR_INPUT = 182, + KEYCODE_PROG_RED = 183, + KEYCODE_PROG_GREEN = 184, + KEYCODE_PROG_YELLOW = 185, + KEYCODE_PROG_BLUE = 186, + KEYCODE_APP_SWITCH = 187, + KEYCODE_BUTTON_1 = 188, + KEYCODE_BUTTON_2 = 189, + KEYCODE_BUTTON_3 = 190, + KEYCODE_BUTTON_4 = 191, + KEYCODE_BUTTON_5 = 192, + KEYCODE_BUTTON_6 = 193, + KEYCODE_BUTTON_7 = 194, + KEYCODE_BUTTON_8 = 195, + KEYCODE_BUTTON_9 = 196, + KEYCODE_BUTTON_10 = 197, + KEYCODE_BUTTON_11 = 198, + KEYCODE_BUTTON_12 = 199, + KEYCODE_BUTTON_13 = 200, + KEYCODE_BUTTON_14 = 201, + KEYCODE_BUTTON_15 = 202, + KEYCODE_BUTTON_16 = 203, +} keycode_t; + From 824f4fb4573026188dddae7042fd336b5cfe882a Mon Sep 17 00:00:00 2001 From: Daniel Dressler Date: Mon, 24 Jun 2013 21:47:29 -0700 Subject: [PATCH 0475/1445] Add queue of pressed keys to input_state --- android/app-android.cpp | 8 ++++++ input/input_state.cpp | 56 +++++++++++++++++++++++++++++++++++++++++ input/input_state.h | 12 ++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 input/input_state.cpp diff --git a/android/app-android.cpp b/android/app-android.cpp index 5525e23d73..4f03c0549a 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -39,6 +39,7 @@ static float left_joystick_x_async; static float left_joystick_y_async; static float right_joystick_x_async; static float right_joystick_y_async; +static int key_queue_async[MAX_KEYQUEUESIZE]; static uint32_t pad_buttons_down; @@ -148,6 +149,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init right_joystick_x_async = 0; right_joystick_y_async = 0; + KeyQueueBlank(key_queue_async); + std::string apkPath = GetJavaString(env, japkpath); ILOG("NativeApp::Init: APK path: %s", apkPath.c_str()); VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); @@ -260,6 +263,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN pad_buttons_down |= pad_buttons_async_set; pad_buttons_down &= ~pad_buttons_async_clear; input_state.pad_buttons = pad_buttons_down; + KeyQueueCopyQueue(key_queue_async, input_state.key_queue); UpdateInputState(&input_state); } @@ -369,6 +373,8 @@ static inline void AsyncUp(int padbutton) { } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) { + KeyQueueAddKey(key_queue_async, key); + switch (key) { case 1: AsyncDown (PAD_BUTTON_BACK); break; // Back case 2: AsyncDown (PAD_BUTTON_MENU); break; // Menu @@ -396,6 +402,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jcl } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) { + KeyQueueRemoveKey(key_queue_async, key); + switch (key) { case 1: AsyncUp (PAD_BUTTON_BACK); break; // Back case 2: AsyncUp (PAD_BUTTON_MENU); break; // Menu diff --git a/input/input_state.cpp b/input/input_state.cpp new file mode 100644 index 0000000000..af84381b56 --- /dev/null +++ b/input/input_state.cpp @@ -0,0 +1,56 @@ +#include "input_state.h" + +#define max_queue MAX_KEYQUEUESIZE + +void MakeRoomInQueueFront(int queue[]) +{ + // shift queue elements from front towards back + for (int i = max_queue - 1; i > 0; i--) { + queue[i] = queue[i - 1]; + } + queue[0] = 0; +} + +void FillGap(int queue[], int gap_loc) +{ + // shift elements from back towards front + // until gap location is filled + for (int i = gap_loc; i < max_queue; i++) { + queue[i] = queue[i + 1]; + } + queue[max_queue - 1] = 0; +} + +void KeyQueueAddKey(int queue[], int key) +{ + for (int i = 0; i < max_queue; i++) { + if (queue[i] == key) + return; + if (queue[i] == 0) { + queue[i] = key; + return; + } + } + + // queue was full + MakeRoomInQueueFront(queue); + queue[0] = key; +} + +void KeyQueueRemoveKey(int queue[], int key) +{ + for (int i = 0; i < max_queue; i++) + if (queue[i] == key) + FillGap(queue, i); +} + +void KeyQueueCopyQueue(int src[], int dst[]) +{ + for (int i = 0; i < max_queue; i++) + dst[i] = src[i]; +} +void KeyQueueBlank(int queue[]) +{ + for (int i = 0; i < max_queue; i++) + queue[i] = 0; +} diff --git a/input/input_state.h b/input/input_state.h index b34f051ac1..fba97a4c02 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -39,6 +39,10 @@ enum { #ifndef MAX_POINTERS #define MAX_POINTERS 8 #endif + +#ifndef MAX_KEYQUEUESIZE +#define MAX_KEYQUEUESIZE 20 +#endif // Collection of all possible inputs, and automatically computed // deltas where applicable. @@ -79,7 +83,7 @@ struct InputState { bool accelerometer_valid; Vec3 acc; - // TODO: Add key arrays + int key_queue[MAX_KEYQUEUESIZE]; private: DISALLOW_COPY_AND_ASSIGN(InputState); @@ -113,3 +117,9 @@ struct TouchInput { double timestamp; }; + +// Key Queue Helpers +void KeyQueueAddKey(int [], int); +void KeyQueueRemoveKey(int [], int); +void KeyQueueCopyQueue(int src[], int dst[]); +void KeyQueueBlank(int []); From c9e10892611df10426c3c84a3c1071674b015a8f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 25 Jun 2013 23:27:45 +0200 Subject: [PATCH 0476/1445] Very basic download cancellation support. At least doesn't try to download if cancelled during Connect, etc. --- net/http_client.cpp | 29 ++++++++++++++++++++++++++++- net/http_client.h | 13 ++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index a48585f045..2b91df8b68 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -285,7 +285,7 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) } Download::Download(const std::string &url, const std::string &outfile) - : url_(url), outfile_(outfile), progress_(0.0f), failed_(false), resultCode_(0) { + : url_(url), outfile_(outfile), progress_(0.0f), failed_(false), resultCode_(0), cancelled_(false) { std::thread th(std::bind(&Download::Do, this)); th.detach(); } @@ -294,6 +294,11 @@ Download::~Download() { } +void Download::SetFailed(int code) { + failed_ = true; + progress_ = 1.0f; +} + void Download::Do() { resultCode_ = 0; @@ -313,6 +318,13 @@ void Download::Do() { net::Shutdown(); return; } + + if (cancelled_) { + SetFailed(-1); + net::Shutdown(); + return; + } + if (!client.Connect()) { ELOG("Failed connecting to server."); resultCode_ = -1; @@ -320,6 +332,14 @@ void Download::Do() { progress_ = 1.0f; return; } + + if (cancelled_) { + SetFailed(-1); + net::Shutdown(); + return; + } + + // TODO: Allow cancelling during a GET somehow... int resultCode = client.GET(fileUrl.Resource().c_str(), &buffer_); if (resultCode == 200) { ILOG("Completed downloading %s to %s", url_.c_str(), outfile_.c_str()); @@ -350,4 +370,11 @@ void Downloader::Update() { } } +void Downloader::CancelAll() { + for (size_t i = 0; i < downloads_.size(); i++) { + downloads_[i]->Cancel(); + } +} + + } // http diff --git a/net/http_client.h b/net/http_client.h index 7ca3a74ada..2c8eeb2fdf 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -87,26 +87,37 @@ public: // If not downloading to a file, access this to get the result. Buffer &buffer() { return buffer_; } + void Cancel() { + cancelled_ = true; + } + private: void Do(); // Actually does the download. Runs on thread. - + void SetFailed(int code); float progress_; Buffer buffer_; std::string url_; std::string outfile_; int resultCode_; bool failed_; + volatile bool cancelled_; }; using std::shared_ptr; class Downloader { public: + ~Downloader() { + CancelAll(); + } std::shared_ptr StartDownload(const std::string &url, const std::string &outfile); // Drops finished downloads from the list. void Update(); + + void CancelAll(); + private: std::vector> downloads_; }; From 1777d9e835b7f7b6270a29ecbe5feb8372029ba4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 26 Jun 2013 19:24:49 +0200 Subject: [PATCH 0477/1445] Keep a reference to download objects for their lifetime. Should fix cancelling crashes. --- net/http_client.cpp | 16 +++++++++++++--- net/http_client.h | 6 +++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 2b91df8b68..068bc5c1c2 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -1,4 +1,5 @@ #include "net/http_client.h" +#include "base/timeutil.h" #ifndef _WIN32 #include @@ -286,20 +287,27 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) Download::Download(const std::string &url, const std::string &outfile) : url_(url), outfile_(outfile), progress_(0.0f), failed_(false), resultCode_(0), cancelled_(false) { - std::thread th(std::bind(&Download::Do, this)); - th.detach(); } Download::~Download() { } +void Download::Start(std::shared_ptr self) +{ + std::thread th(std::bind(&Download::Do, this, self)); + th.detach(); +} + void Download::SetFailed(int code) { failed_ = true; progress_ = 1.0f; } -void Download::Do() { +void Download::Do(std::shared_ptr self) { + // as long as this is in scope, we won't get destructed. + // yeah this is ugly, I need to think about how life time should be managed for these... + std::shared_ptr self_ = self; resultCode_ = 0; Url fileUrl(url_); @@ -349,6 +357,7 @@ void Download::Do() { } else { ELOG("Error downloading %s to %s: %i", url_.c_str(), outfile_.c_str(), resultCode); } + resultCode_ = resultCode; net::Shutdown(); progress_ = 1.0f; @@ -357,6 +366,7 @@ void Download::Do() { std::shared_ptr Downloader::StartDownload(const std::string &url, const std::string &outfile) { std::shared_ptr dl(new Download(url, outfile)); downloads_.push_back(dl); + dl->Start(dl); return dl; } diff --git a/net/http_client.h b/net/http_client.h index 2c8eeb2fdf..c9b18acfe6 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -73,6 +73,10 @@ public: Download(const std::string &url, const std::string &outfile); ~Download(); + // Keeps around an instance of the shared_ptr, so that it doesn't get destructed + // until done. + void Start(std::shared_ptr self); + // Returns 1.0 when done. That one value can be compared exactly - or just use Done(). float Progress() const { return progress_; } bool Done() const { return progress_ == 1.0f; } @@ -92,7 +96,7 @@ public: } private: - void Do(); // Actually does the download. Runs on thread. + void Do(std::shared_ptr self); // Actually does the download. Runs on thread. void SetFailed(int code); float progress_; Buffer buffer_; From f1ccdc11b5765b8c45c0bde97b8a48dc8c720ba0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 27 Jun 2013 16:20:18 +0200 Subject: [PATCH 0478/1445] Add utility to get a list of Windows disk drives. Rework UI events. --- file/file_util.cpp | 30 ++++++++++++++++++++++ file/file_util.h | 4 +++ ui/view.cpp | 64 ++++++++++++++++++++++++++++++++-------------- ui/view.h | 17 +++++++----- ui/viewgroup.cpp | 1 + 5 files changed, 90 insertions(+), 26 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index 52c2d0ae88..a4ec706d63 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -251,6 +251,10 @@ size_t getFilesInDir(const char *directory, std::vector *files, const struct dirent_large diren; struct dirent *result = NULL; + //std::string directoryWithSlash = directory; + //if (directoryWithSlash.back() != '/') + // directoryWithSlash += "/"; + DIR *dirp = opendir(directory); if (!dirp) return 0; @@ -358,3 +362,29 @@ void mkDir(const std::string &path) mkdir(path.c_str(), 0777); #endif } + +#ifdef _WIN32 +// Returns a vector with the device names +std::vector getWindowsDrives() +{ + std::vector drives; + + const DWORD buffsize = GetLogicalDriveStrings(0, NULL); + std::vector buff(buffsize); + if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1) + { + auto drive = buff.data(); + while (*drive) + { + std::string str(drive); + str.pop_back(); // we don't want the final backslash + str += "/"; + drives.push_back(str); + + // advance to next drive + while (*drive++) {} + } + } + return drives; +} +#endif \ No newline at end of file diff --git a/file/file_util.h b/file/file_util.h index ed69d8cd86..6b65bebb7c 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -43,3 +43,7 @@ void deleteDir(const char *file); bool exists(const std::string &filename); void mkDir(const std::string &path); std::string getDir(const std::string &path); + +#ifdef _WIN32 +std::vector getWindowsDrives(); +#endif \ No newline at end of file diff --git a/ui/view.cpp b/ui/view.cpp index cc550d0194..b85da47bcc 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -1,4 +1,5 @@ -#include "base/display.h" +#include +#include "base/display.h" #include "base/mutex.h" #include "input/input_state.h" #include "gfx_es2/draw_buffer.h" @@ -13,8 +14,39 @@ namespace UI { static View *focusedView; static bool focusMovementEnabled; +static recursive_mutex mutex_; + const float ITEM_HEIGHT = 64.f; + +struct DispatchQueueItem { + Event *e; + EventParams params; +}; + +std::queue g_dispatchQueue; + + +void EventTriggered(Event *e, EventParams params) { + lock_guard guard(mutex_); + + DispatchQueueItem item; + item.e = e; + item.params = params; + g_dispatchQueue.push(item); +} + +void DispatchEvents() { + lock_guard guard(mutex_); + + while (!g_dispatchQueue.empty()) { + DispatchQueueItem item = g_dispatchQueue.back(); + g_dispatchQueue.pop(); + item.e->Dispatch(item.params); + } +} + + View *GetFocusedView() { return focusedView; } @@ -58,21 +90,16 @@ void Event::Add(std::function func) { // Call this from input thread or whatever, it doesn't matter void Event::Trigger(EventParams &e) { - lock_guard guard(mutex_); - if (!triggered_) { - triggered_ = true; - eventParams_ = e; - } + EventTriggered(this, e); } // Call this from UI thread -void Event::Update() { - lock_guard guard(mutex_); - if (triggered_) { - for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { - (iter->func)(eventParams_); +void Event::Dispatch(EventParams &e) { + for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { + if ((iter->func)(e) == UI::EVENT_DONE) { + // Event is handled, stop looping immediately. This event might even have gotten deleted. + return; } - triggered_ = false; } } @@ -128,7 +155,6 @@ void Clickable::Touch(const TouchInput &input) { } void Clickable::Update(const InputState &input_state) { - OnClick.Update(); if (!HasFocus()) return; @@ -182,21 +208,21 @@ void ClickableItem::Draw(UIContext &dc) { void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const { dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); + w += 16; + h += 16; } void Choice::Draw(UIContext &dc) { ClickableItem::Draw(dc); - int paddingX = 4; - int paddingY = 4; + int paddingX = 8; dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); } void InfoItem::Draw(UIContext &dc) { Item::Draw(dc); - int paddingX = 4; - int paddingY = 4; + int paddingX = 8; dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); // dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor); @@ -209,8 +235,8 @@ void ItemHeader::Draw(UIContext &dc) { void CheckBox::Draw(UIContext &dc) { ClickableItem::Draw(dc); - int paddingX = 4; - int paddingY = 4; + int paddingX = 8; + int paddingY = 8; int image = *toggle_ ? dc.theme->checkOn : dc.theme->checkOff; diff --git a/ui/view.h b/ui/view.h index 99f3430096..ab9c5c2d9b 100644 --- a/ui/view.h +++ b/ui/view.h @@ -180,12 +180,14 @@ struct HandlerRegistration { class Event { public: - Event() : triggered_(false) {} - + Event() {} + ~Event() { + handlers_.clear(); + } // Call this from input thread or whatever, it doesn't matter void Trigger(EventParams &e); // Call this from UI thread - void Update(); + void Dispatch(EventParams &e); // This is suggested for use in most cases. Autobinds, allowing for neat syntax. template @@ -198,11 +200,8 @@ public: void Add(std::function func); private: - recursive_mutex mutex_; std::vector handlers_; - bool triggered_; - EventParams eventParams_; - + DISALLOW_COPY_AND_ASSIGN(Event); }; @@ -368,6 +367,7 @@ public: virtual void Draw(UIContext &dc); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + const std::string &GetText() const { return text_; } private: Style style_; @@ -584,4 +584,7 @@ private: void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured); +void EventTriggered(Event *e, EventParams params); +void DispatchEvents(); + } // namespace diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index a928c5f7ad..3d8f96170d 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -682,6 +682,7 @@ void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { EnableFocusMovement(false); root->Update(input_state); + DispatchEvents(); } ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) From 5127d746333e125193dd68c253ffcb96446c13b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 29 Jun 2013 21:51:10 +0200 Subject: [PATCH 0479/1445] Increase default landscape window size of SDL builds --- base/PCMain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 74b8d31f77..c59aab1708 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -365,8 +365,8 @@ int main(int argc, char *argv[]) { pixel_xres = 1024 * zoom; pixel_yres = 768 * zoom; } else { - pixel_xres = 800 * zoom; - pixel_yres = 480 * zoom; + pixel_xres = 960 * zoom; + pixel_yres = 544 * zoom; } } else { // PC development hack for more space From a51474d255b2a607c178ebdf7732716781b3bccf Mon Sep 17 00:00:00 2001 From: Daniel Dressler Date: Sat, 29 Jun 2013 19:15:55 -0700 Subject: [PATCH 0480/1445] Add SDL support for keycode pass through --- base/KeyCodeTranslationFromSDL.h | 32 ++++++++++++++++++++++++++ base/PCMain.cpp | 14 +++++++++++- input/input_state.cpp | 39 ++++++++++++++++++++++++++++++++ input/input_state.h | 3 +++ util/const_map.h | 24 ++++++++++++++++++++ 5 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 base/KeyCodeTranslationFromSDL.h create mode 100644 util/const_map.h diff --git a/base/KeyCodeTranslationFromSDL.h b/base/KeyCodeTranslationFromSDL.h new file mode 100644 index 0000000000..b9f443bc17 --- /dev/null +++ b/base/KeyCodeTranslationFromSDL.h @@ -0,0 +1,32 @@ +#include "util/const_map.h" +#include + +// TODO: fill out this with a full mapping +static const std::map KeyMapRawSDLtoNative = InitConstMap + (SDLK_p, KEYCODE_P) + (SDLK_o, KEYCODE_O) + (SDLK_i, KEYCODE_I) + (SDLK_u, KEYCODE_U) + (SDLK_y, KEYCODE_Y) + (SDLK_t, KEYCODE_T) + (SDLK_r, KEYCODE_R) + (SDLK_e, KEYCODE_E) + (SDLK_w, KEYCODE_W) + (SDLK_q, KEYCODE_Q) + (SDLK_l, KEYCODE_L) + (SDLK_k, KEYCODE_K) + (SDLK_j, KEYCODE_J) + (SDLK_h, KEYCODE_H) + (SDLK_g, KEYCODE_G) + (SDLK_f, KEYCODE_F) + (SDLK_d, KEYCODE_D) + (SDLK_s, KEYCODE_S) + (SDLK_a, KEYCODE_A) + (SDLK_m, KEYCODE_M) + (SDLK_n, KEYCODE_N) + (SDLK_b, KEYCODE_B) + (SDLK_v, KEYCODE_V) + (SDLK_c, KEYCODE_C) + (SDLK_x, KEYCODE_X) + (SDLK_z, KEYCODE_Z); + diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 74b8d31f77..e9ab582470 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -14,6 +14,7 @@ #endif #include +#include #ifdef _WIN32 #include "SDL/SDL.h" #include "SDL/SDL_timer.h" @@ -32,9 +33,11 @@ #include "gfx_es2/glsl_program.h" #include "file/zip_read.h" #include "input/input_state.h" +#include "input/keycodes.h" +#include "base/KeyCodeTranslationFromSDL.h" #include "base/NativeApp.h" #include "net/resolve.h" - +#include "util/const_map.h" #if defined(MAEMO) || defined(PANDORA) #define EGL @@ -247,6 +250,7 @@ void LaunchEmail(const char *email_address) InputState input_state; + const int buttonMappings[14] = { #ifdef PANDORA SDLK_PAGEDOWN, //X => cross @@ -532,6 +536,14 @@ int main(int argc, char *argv[]) { if (event.key.keysym.sym == SDLK_ESCAPE) { quitRequested = 1; } + + KeyQueueAttemptTranslatedAdd(input_state.key_queue, + KeyMapRawSDLtoNative, + event.key.keysym.sym); + } else if (event.type == SDL_KEYUP) { + KeyQueueAttemptTranslatedRemove(input_state.key_queue, + KeyMapRawSDLtoNative, + event.key.keysym.sym); } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { input_state.pointer_x[0] = mx; diff --git a/input/input_state.cpp b/input/input_state.cpp index af84381b56..4846936781 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -1,4 +1,5 @@ #include "input_state.h" +#include #define max_queue MAX_KEYQUEUESIZE @@ -54,3 +55,41 @@ void KeyQueueBlank(int queue[]) for (int i = 0; i < max_queue; i++) queue[i] = 0; } + +int AttemptTranslate(const std::map trans_table, int plat_key) +{ + std::map::const_iterator iter; + iter = trans_table.find(plat_key); + if (iter == trans_table.end()) + return 0; + + return iter->second; +} + + +void KeyQueueAttemptTranslatedAdd(int queue[], + const std::map translation_table, + int platform_key) +{ + int key = AttemptTranslate(translation_table, platform_key); + + if (key == 0) { + std::cerr << "Warning: Platform key code translation table missing %d"; + return; + } + + KeyQueueAddKey(queue, key); +} + + +void KeyQueueAttemptTranslatedRemove(int queue[], + const std::map translation_table, + int platform_key) +{ + int key = AttemptTranslate(translation_table, platform_key); + + if (key == 0) + return; + + KeyQueueRemoveKey(queue, key); +} diff --git a/input/input_state.h b/input/input_state.h index fba97a4c02..1bb054bf2a 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -3,6 +3,7 @@ #include "math/lin/vec3.h" #include "base/mutex.h" #include "base/basictypes.h" +#include enum { PAD_BUTTON_A = 1, @@ -123,3 +124,5 @@ void KeyQueueAddKey(int [], int); void KeyQueueRemoveKey(int [], int); void KeyQueueCopyQueue(int src[], int dst[]); void KeyQueueBlank(int []); +void KeyQueueAttemptTranslatedAdd(int [], const std::map, int); +void KeyQueueAttemptTranslatedRemove(int [], const std::map, int); diff --git a/util/const_map.h b/util/const_map.h new file mode 100644 index 0000000000..6b1fe0e165 --- /dev/null +++ b/util/const_map.h @@ -0,0 +1,24 @@ +#pragma once + +template +class InitConstMap +{ +private: + std::map m_map; +public: + InitConstMap(const T& key, const U& val) + { + m_map[key] = val; + } + + InitConstMap& operator()(const T& key, const U& val) + { + m_map[key] = val; + return *this; + } + + operator std::map() + { + return m_map; + } +}; From 033a3437fbf8894dbd617eb2447b1e55cdc57a61 Mon Sep 17 00:00:00 2001 From: Kingcom Date: Mon, 1 Jul 2013 01:31:47 +0200 Subject: [PATCH 0481/1445] Moved expression parser to native --- math/expression_parser.cpp | 462 +++++++++++++++++++++++++++++++++++++ math/expression_parser.h | 20 ++ native.vcxproj | 2 + native.vcxproj.filters | 6 + 4 files changed, 490 insertions(+) create mode 100644 math/expression_parser.cpp create mode 100644 math/expression_parser.h diff --git a/math/expression_parser.cpp b/math/expression_parser.cpp new file mode 100644 index 0000000000..e150c00b5b --- /dev/null +++ b/math/expression_parser.cpp @@ -0,0 +1,462 @@ +#include "expression_parser.h" +#include +#include + +typedef enum { + EXOP_BRACKETL, EXOP_BRACKETR, EXOP_SIGNPLUS, EXOP_SIGNMINUS, + EXOP_BITNOT, EXOP_LOGNOT, EXOP_MUL, EXOP_DIV, EXOP_MOD, EXOP_ADD, EXOP_SUB, + EXOP_SHL, EXOP_SHR, EXOP_GREATEREQUAL, EXOP_GREATER, EXOP_LOWEREQUAL, EXOP_LOWER, + EXOP_EQUAL, EXOP_NOTEQUAL, EXOP_BITAND, EXOP_XOR, EXOP_BITOR, EXOP_LOGAND, + EXOP_LOGOR, EXOP_TERTIF, EXOP_TERTELSE, EXOP_NUMBER, EXOP_NONE, EXOP_COUNT +} ExpressionOpcodeType; + +typedef enum { EXCOMM_CONST, EXCOMM_REF, EXCOMM_OP } ExpressionCommand; + +static char expressionError[256]; + +typedef struct { + char Name[4]; + unsigned char Priority; + unsigned char len; + unsigned char args; + bool sign; +} ExpressionOpcode; + +const ExpressionOpcode ExpressionOpcodes[] = { + { "(", 15, 1, 0, false }, // EXOP_BRACKETL + { ")", 15, 1, 0, false }, // EXOP_BRACKETR + { "+", 12, 1, 1, true }, // EXOP_SIGNPLUS + { "-", 12, 1, 1, true }, // EXOP_SIGNMINUS + { "~", 12, 1, 1, false }, // EXOP_BITNOT + { "!", 12, 1, 1, false }, // EXOP_LOGNOT + { "*", 11, 1, 2, false }, // EXOP_MUL + { "/", 11, 1, 2, false }, // EXOP_DIV + { "%", 11, 1, 2, false }, // EXOP_MOD + { "+", 10, 1, 2, false }, // EXOP_ADD + { "-", 10, 1, 2, false }, // EXOP_SUB + { "<<", 9, 2, 2, false }, // EXOP_SHL + { ">>", 9, 2, 2, false }, // EXOP_SHR + { ">=", 8, 2, 2, false }, // EXOP_GREATEREQUAL + { ">", 8, 1, 2, false }, // EXOP_GREATER + { "<=", 8, 2, 2, false }, // EXOP_LOWEREQUAL + { "<", 8, 1, 2, false }, // EXOP_LOWER + { "==", 7, 2, 2, false }, // EXOP_EQUAL + { "!=", 7, 2, 2, false }, // EXOP_NOTEQUAL + { "&", 6, 1, 2, false }, // EXOP_BITAND + { "^", 5, 1, 2, false }, // EXOP_XOR + { "|", 4, 1, 2, false }, // EXOP_BITOR + { "&&", 3, 2, 2, false }, // EXOP_LOGAND + { "||", 2, 2, 2, false }, // EXOP_LOGOR + { "?", 0, 1, 0, false }, // EXOP_TERTIF + { ":", 1, 1, 3, false }, // EXOP_TERTELSE + { "", 0, 0, 0, false }, // EXOP_NUMBER + { "", 0, 0, 0, false } // EXOP_NONE +}; + +bool parseNumber(char* str, int defaultrad, int len, uint32& result) +{ + int val = 0; + int r = 0; + if (len == 0) len = (int) strlen(str); + + if (str[0] == '0' && tolower(str[1]) == 'x') + { + r = 16; + str+=2; + len-=2; + } else if (str[0] == '$') + { + r = 16; + str++; + len--; + } else if (str[0] == '0' && tolower(str[1]) == 'o') + { + r = 8; + str+=2; + len-=2; + } else { + if (!(str[0] >= '0' && str[0] <= '9')) return false; + + if (tolower(str[len-1]) == 'b') + { + r = 2; + len--; + } else if (tolower(str[len-1]) == 'o') + { + r = 8; + len--; + } else if (tolower(str[len-1]) == 'h') + { + r = 16; + len--; + } else { + r = defaultrad; + } + } + + switch (r) + { + case 2: // bin + while (len--) + { + if (*str != '0' && *str != '1') return false; + val = val << 1; + if (*str++ == '1') + { + val++; + } + } + break; + case 8: // oct + while (len--) + { + if (*str < '0' || *str > '7') return false; + val = val << 3; + val+=(*str++-'0'); + } + break; + case 10: // dec + while (len--) + { + if (*str < '0' || *str > '9') return false; + val = val * 10; + val += (*str++ - '0'); + } + break; + case 16: // hex + while (len--) + { + char c = tolower(*str++); + if ((c < '0' || c > '9') && (c < 'a' || c > 'f')) return false; + val = val << 4; + + if (c >= 'a') val += c-'a'+10; + else val += c-'0'; + } + break; + default: + return false; + } + + result = val; + return true; +} + +ExpressionOpcodeType getExpressionOpcode(char* str, int& ReturnLen, ExpressionOpcodeType LastOpcode) +{ + int longestlen = 0; + ExpressionOpcodeType result = EXOP_NONE; + + for (int i = 0; i < EXOP_NUMBER; i++) + { + if (ExpressionOpcodes[i].sign == true && + (LastOpcode == EXOP_NUMBER || LastOpcode == EXOP_BRACKETR)) continue; + + int len = ExpressionOpcodes[i].len; + if (len > longestlen) + { + if (strncmp(ExpressionOpcodes[i].Name,str,len) == 0) + { + result = (ExpressionOpcodeType) i; + longestlen = len; + } + } + } + + ReturnLen = longestlen; + return result; +} + +bool isAlphaNum(char c) +{ + if ((c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + c == '@' || c == '_' || c == '$') + { + return true; + } else { + return false; + } +} + +bool initPostfixExpression(char* infix, IExpressionFunctions* funcs, PostfixExpression& dest) +{ + expressionError[0] = 0; + + int infixPos = 0; + int infixLen = strlen(infix); + ExpressionOpcodeType lastOpcode = EXOP_NONE; + std::vector opcodeStack; + dest.clear(); + + while (infixPos < infixLen) + { + char first = tolower(infix[infixPos]); + char subStr[256]; + int subPos = 0; + + if (first == ' ' || first == '\t') + { + infixPos++; + continue; + } + + if (first >= '0' && first <= '9') + { + while (isAlphaNum(infix[infixPos])) + { + subStr[subPos++] = infix[infixPos++]; + } + subStr[subPos] = 0; + + uint32 value; + if (parseNumber(subStr,16,subPos,value) == false) + { + sprintf(expressionError,"Invalid number \"%s\"",subStr); + return false; + } + + dest.push_back(ExpressionPair(EXCOMM_CONST,value)); + lastOpcode = EXOP_NUMBER; + } else if ((first >= 'a' && first <= 'z') || first == '@') + { + while (isAlphaNum(infix[infixPos])) + { + subStr[subPos++] = infix[infixPos++]; + } + subStr[subPos] = 0; + + uint32 value; + if (funcs->parseReference(subStr,value) == true) + { + dest.push_back(ExpressionPair(EXCOMM_REF,value)); + lastOpcode = EXOP_NUMBER; + continue; + } + + if (funcs->parseSymbol(subStr,value) == true) + { + dest.push_back(ExpressionPair(EXCOMM_CONST,value)); + lastOpcode = EXOP_NUMBER; + continue; + } + + sprintf(expressionError,"Invalid symbol \"%s\"",subStr); + return false; + } else { + int len; + ExpressionOpcodeType type = getExpressionOpcode(&infix[infixPos],len,lastOpcode); + if (type == EXOP_NONE) + { + sprintf(expressionError,"Invalid operator at \"%s\"",&infix[infixPos]); + return false; + } + + switch (type) + { + case EXOP_BRACKETL: + opcodeStack.push_back(type); + break; + case EXOP_BRACKETR: + while (true) + { + if (opcodeStack.empty()) + { + sprintf(expressionError,"Closing parenthesis without opening one"); + return false; + } + ExpressionOpcodeType t = opcodeStack[opcodeStack.size()-1]; + opcodeStack.pop_back(); + if (t == EXOP_BRACKETL) break; + dest.push_back(ExpressionPair(EXCOMM_OP,t)); + } + break; + default: + if (opcodeStack.empty() == false) + { + int CurrentPriority = ExpressionOpcodes[type].Priority; + while (!opcodeStack.empty()) + { + ExpressionOpcodeType t = opcodeStack[opcodeStack.size()-1]; + opcodeStack.pop_back(); + + if (t == EXOP_BRACKETL) + { + opcodeStack.push_back(t); + break; + } + + if (ExpressionOpcodes[t].Priority >= CurrentPriority) + { + dest.push_back(ExpressionPair(EXCOMM_OP,t)); + } else { + opcodeStack.push_back(t); + break; + } + } + } + opcodeStack.push_back(type); + break; + } + infixPos += len; + lastOpcode = type; + } + } + + while (!opcodeStack.empty()) + { + ExpressionOpcodeType t = opcodeStack[opcodeStack.size()-1]; + opcodeStack.pop_back(); + + if (t == EXOP_BRACKETL) // opening bracket without closing one + { + sprintf(expressionError,"Parenthesis not closed"); + return false; + } + dest.push_back(ExpressionPair(EXCOMM_OP,t)); + } + + return true; +} + +bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, uint32& dest) +{ + int num = 0; + uint32 opcode; + std::vector valueStack; + unsigned int arg[5]; + + while (num < exp.size()) + { + switch (exp[num].first) + { + case EXCOMM_CONST: // konstante zahl + valueStack.push_back(exp[num++].second); + break; + case EXCOMM_REF: + opcode = funcs->getReferenceValue(exp[num++].second); + valueStack.push_back(opcode); + break; + case EXCOMM_OP: // opcode + opcode = exp[num++].second; + if (valueStack.size() < ExpressionOpcodes[opcode].args) + { + sprintf(expressionError,"Not enough arguments"); + return false; + } + for (int l = 0; l < ExpressionOpcodes[opcode].args; l++) + { + arg[l] = valueStack[valueStack.size()-1]; + valueStack.pop_back(); + } + + switch (opcode) + { + case EXOP_SIGNPLUS: // keine aktion nötig + break; + case EXOP_SIGNMINUS: // -0 + valueStack.push_back(0-arg[0]); + break; + case EXOP_BITNOT: // ~b + valueStack.push_back(~arg[0]); + break; + case EXOP_LOGNOT: // !b + valueStack.push_back(!arg[0]); + break; + case EXOP_MUL: // a*b + valueStack.push_back(arg[1]*arg[0]); + break; + case EXOP_DIV: // a/b + if (arg[0] == 0) + { + sprintf(expressionError,"Division by zero"); + return false; + } + valueStack.push_back(arg[1]/arg[0]); + break; + case EXOP_MOD: // a%b + if (arg[0] == 0) + { + sprintf(expressionError,"Modulo by zero"); + return false; + } + valueStack.push_back(arg[1]%arg[0]); + break; + case EXOP_ADD: // a+b + valueStack.push_back(arg[1]+arg[0]); + break; + case EXOP_SUB: // a-b + valueStack.push_back(arg[1]-arg[0]); + break; + case EXOP_SHL: // a<>b + valueStack.push_back(arg[1]>>arg[0]); + break; + case EXOP_GREATEREQUAL: // a >= b + valueStack.push_back(arg[1]>=arg[0]); + break; + case EXOP_GREATER: // a > b + valueStack.push_back(arg[1]>arg[0]); + break; + case EXOP_LOWEREQUAL: // a <= b + valueStack.push_back(arg[1]<=arg[0]); + break; + case EXOP_LOWER: // a < b + valueStack.push_back(arg[1] + +typedef std::pair ExpressionPair; +typedef std::vector PostfixExpression; + +class IExpressionFunctions +{ +public: + virtual bool parseReference(char* str, uint32& referenceIndex) = 0; + virtual bool parseSymbol(char* str, uint32& symbolValue) = 0; + virtual uint32 getReferenceValue(uint32 referenceIndex) = 0; +}; + +bool initPostfixExpression(char* infix, IExpressionFunctions* funcs, PostfixExpression& dest); +bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, uint32& dest); +bool parseExpression(char* exp, IExpressionFunctions* funcs, uint32& dest); +const char* getExpressionError(); diff --git a/native.vcxproj b/native.vcxproj index bc4efef2cd..ea3cfa3ecb 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -231,6 +231,7 @@ + @@ -353,6 +354,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 99f79b14a8..eca9e19926 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -274,6 +274,9 @@ + + math + @@ -486,6 +489,9 @@ data + + math + From 91114ba60554713da98d4c23aeb533e2da650397 Mon Sep 17 00:00:00 2001 From: Daniel Dressler Date: Sun, 30 Jun 2013 22:25:16 -0700 Subject: [PATCH 0482/1445] Add missing SDL keycode translation pairs --- base/KeyCodeTranslationFromSDL.h | 67 +++++++++++++++++++++++++++++++- base/PCMain.cpp | 2 + input/input_state.cpp | 3 +- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/base/KeyCodeTranslationFromSDL.h b/base/KeyCodeTranslationFromSDL.h index b9f443bc17..7f349be88a 100644 --- a/base/KeyCodeTranslationFromSDL.h +++ b/base/KeyCodeTranslationFromSDL.h @@ -1,7 +1,7 @@ #include "util/const_map.h" #include -// TODO: fill out this with a full mapping +// TODO: Add any missing keys static const std::map KeyMapRawSDLtoNative = InitConstMap (SDLK_p, KEYCODE_P) (SDLK_o, KEYCODE_O) @@ -28,5 +28,68 @@ static const std::map KeyMapRawSDLtoNative = InitConstMap (SDLK_v, KEYCODE_V) (SDLK_c, KEYCODE_C) (SDLK_x, KEYCODE_X) - (SDLK_z, KEYCODE_Z); + (SDLK_z, KEYCODE_Z) + (SDLK_COMMA, KEYCODE_COMMA) + (SDLK_PERIOD, KEYCODE_PERIOD) + (SDLK_LALT, KEYCODE_ALT_LEFT) + (SDLK_RALT, KEYCODE_ALT_RIGHT) + (SDLK_LSHIFT, KEYCODE_SHIFT_LEFT) + (SDLK_RSHIFT, KEYCODE_SHIFT_RIGHT) + (SDLK_TAB, KEYCODE_TAB) + (SDLK_SPACE, KEYCODE_SPACE) + (SDLK_RETURN, KEYCODE_ENTER) + (SDLK_MINUS, KEYCODE_MINUS) + (SDLK_EQUALS, KEYCODE_EQUALS) + (SDLK_LEFTBRACKET, KEYCODE_LEFT_BRACKET) + (SDLK_RIGHTBRACKET, KEYCODE_RIGHT_BRACKET) + (SDLK_BACKSLASH, KEYCODE_BACKSLASH) + (SDLK_SEMICOLON, KEYCODE_SEMICOLON) + // (SDLK_, KEYCODE_APOSTROPHE) // I cannot find the SDL equiv + (SDLK_SLASH, KEYCODE_SLASH) + (SDLK_AT, KEYCODE_AT) + (SDLK_PLUS, KEYCODE_PLUS) + (SDLK_PAGEUP, KEYCODE_PAGE_UP) + (SDLK_PAGEDOWN, KEYCODE_PAGE_DOWN) + (SDLK_ESCAPE, KEYCODE_ESCAPE) + (SDLK_DELETE, KEYCODE_FORWARD_DEL) + (SDLK_LCTRL, KEYCODE_CTRL_LEFT) + (SDLK_RCTRL, KEYCODE_CTRL_RIGHT) + (SDLK_CAPSLOCK, KEYCODE_CAPS_LOCK) + (SDLK_HOME, KEYCODE_MOVE_HOME) + (SDLK_END, KEYCODE_MOVE_END) + (SDLK_INSERT, KEYCODE_INSERT) + /* Somehow these are undefined + * on my comp? + (SDLK_KP_0, KEYCODE_NUMPAD_0) + (SDLK_KP_1, KEYCODE_NUMPAD_1) + (SDLK_KP_2, KEYCODE_NUMPAD_2) + (SDLK_KP_3, KEYCODE_NUMPAD_3) + (SDLK_KP_4, KEYCODE_NUMPAD_4) + (SDLK_KP_5, KEYCODE_NUMPAD_5) + (SDLK_KP_6, KEYCODE_NUMPAD_6) + (SDLK_KP_7, KEYCODE_NUMPAD_7) + (SDLK_KP_8, KEYCODE_NUMPAD_8) + (SDLK_KP_9, KEYCODE_NUMPAD_9) + */ + (SDLK_KP_DIVIDE, KEYCODE_NUMPAD_DIVIDE) + (SDLK_KP_MULTIPLY, KEYCODE_NUMPAD_MULTIPLY) + (SDLK_KP_MINUS, KEYCODE_NUMPAD_SUBTRACT) + (SDLK_KP_PLUS, KEYCODE_NUMPAD_ADD) + (SDLK_KP_PERIOD, KEYCODE_NUMPAD_DOT) + (SDLK_KP_ENTER, KEYCODE_NUMPAD_ENTER) + (SDLK_KP_EQUALS, KEYCODE_NUMPAD_EQUALS) + (SDLK_1, KEYCODE_1) + (SDLK_2, KEYCODE_2) + (SDLK_3, KEYCODE_3) + (SDLK_4, KEYCODE_4) + (SDLK_5, KEYCODE_5) + (SDLK_6, KEYCODE_6) + (SDLK_7, KEYCODE_7) + (SDLK_8, KEYCODE_8) + (SDLK_9, KEYCODE_9) + (SDLK_0, KEYCODE_0) + (SDLK_LEFT, KEYCODE_DPAD_LEFT) + (SDLK_UP, KEYCODE_DPAD_UP) + (SDLK_RIGHT, KEYCODE_DPAD_RIGHT) + (SDLK_DOWN, KEYCODE_DPAD_DOWN); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index e9ab582470..f98bbe230b 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -289,10 +289,12 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_lstick_y = 0; input->pad_rstick_x = 0; input->pad_rstick_y = 0; + /* for (int b = 0; b < 14; b++) { if (keys[buttonMappings[b]]) input->pad_buttons |= (1< Date: Sun, 30 Jun 2013 23:38:28 -0700 Subject: [PATCH 0483/1445] Remove wrong copyright notice Copy & paste error. File itself was copied from a file I created in ppsspp. --- input/keycodes.h | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/input/keycodes.h b/input/keycodes.h index 6323e1a468..fadad418cf 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -1,20 +1,3 @@ -// Copyright (c) 2013- PPSSPP Project. - -// This program 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.0 or later versions. - -// This program 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. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - #pragma once typedef enum _keycode_t { From 42877f5a1fd94a95a4a3df5d47abeae96d6f9ca9 Mon Sep 17 00:00:00 2001 From: Kingcom Date: Mon, 1 Jul 2013 10:00:45 +0200 Subject: [PATCH 0484/1445] Disable binary detection when defaultrad is 16 --- math/expression_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/math/expression_parser.cpp b/math/expression_parser.cpp index e150c00b5b..72742b2c2d 100644 --- a/math/expression_parser.cpp +++ b/math/expression_parser.cpp @@ -77,7 +77,7 @@ bool parseNumber(char* str, int defaultrad, int len, uint32& result) } else { if (!(str[0] >= '0' && str[0] <= '9')) return false; - if (tolower(str[len-1]) == 'b') + if (tolower(str[len-1]) == 'b' && defaultrad != 16) { r = 2; len--; From fb2025774a6f7f535d70b27af8c10ac8d88ce1d5 Mon Sep 17 00:00:00 2001 From: Kingcom Date: Mon, 1 Jul 2013 10:24:36 +0200 Subject: [PATCH 0485/1445] Added reference to android makefile --- Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/Android.mk b/Android.mk index d14d699f6a..5b072d4607 100644 --- a/Android.mk +++ b/Android.mk @@ -37,6 +37,7 @@ LOCAL_SRC_FILES :=\ input/gesture_detector.cpp \ math/math_util.cpp \ math/curves.cpp \ + math/expression_parser.cpp \ math/lin/aabb.cpp.arm \ math/lin/plane.cpp.arm \ math/lin/quat.cpp.arm \ From 57c3f97c0a23a1201b0ddc03e0f97e7e4d84c566 Mon Sep 17 00:00:00 2001 From: Kingcom Date: Mon, 1 Jul 2013 17:58:51 +0200 Subject: [PATCH 0486/1445] Fix android build. --- math/expression_parser.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/math/expression_parser.cpp b/math/expression_parser.cpp index 72742b2c2d..97fc86786b 100644 --- a/math/expression_parser.cpp +++ b/math/expression_parser.cpp @@ -1,6 +1,7 @@ #include "expression_parser.h" #include #include +#include typedef enum { EXOP_BRACKETL, EXOP_BRACKETR, EXOP_SIGNPLUS, EXOP_SIGNMINUS, From 3db24e97c11ba5639845ad827afca90094f88943 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 3 Jul 2013 01:17:57 -0700 Subject: [PATCH 0487/1445] Android buildfix. --- Android.mk | 3 ++- android/app-android.h | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Android.mk b/Android.mk index 5b072d4607..cb258cf85a 100644 --- a/Android.mk +++ b/Android.mk @@ -34,7 +34,8 @@ LOCAL_SRC_FILES :=\ file/zip_read.cpp \ json/json_writer.cpp \ i18n/i18n.cpp \ - input/gesture_detector.cpp \ + input/gesture_detector.cpp \ + input/input_state.cpp \ math/math_util.cpp \ math/curves.cpp \ math/expression_parser.cpp \ diff --git a/android/app-android.h b/android/app-android.h index 002e68ed12..fbe4d59932 100644 --- a/android/app-android.h +++ b/android/app-android.h @@ -1,9 +1,11 @@ #pragma once +#include "input/keycodes.h" + // Compatability we alias the keycodes // since native's keycodes are based on // android keycodes. -typedef enum _keycode_t enum AndroidKeyCodes; +typedef enum _keycode_t AndroidKeyCodes; enum AndroidJoystickAxis { // Field descriptor #15 I From bba8285b94833cb82cbe50f4500b5f17ba0dab37 Mon Sep 17 00:00:00 2001 From: Daniel Dressler Date: Wed, 3 Jul 2013 19:54:16 -0700 Subject: [PATCH 0488/1445] Fix android doubling key presses --- android/app-android.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 4f03c0549a..9f1cbbf048 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -378,25 +378,12 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jcl switch (key) { case 1: AsyncDown (PAD_BUTTON_BACK); break; // Back case 2: AsyncDown (PAD_BUTTON_MENU); break; // Menu - case 3: AsyncDown (PAD_BUTTON_A); break; // Search - case KEYCODE_BUTTON_CROSS: case KEYCODE_BUTTON_CROSS_PS3: AsyncDown(PAD_BUTTON_A); break; - case KEYCODE_BUTTON_CIRCLE: case KEYCODE_BUTTON_CIRCLE_PS3: AsyncDown (PAD_BUTTON_B); break; - case KEYCODE_BUTTON_SQUARE: AsyncDown (PAD_BUTTON_X); break; - case KEYCODE_BUTTON_TRIANGLE: AsyncDown (PAD_BUTTON_Y); break; - case KEYCODE_DPAD_LEFT: AsyncDown (PAD_BUTTON_LEFT); break; - case KEYCODE_DPAD_UP: AsyncDown (PAD_BUTTON_UP); break; - case KEYCODE_DPAD_RIGHT: AsyncDown (PAD_BUTTON_RIGHT); break; - case KEYCODE_DPAD_DOWN: AsyncDown (PAD_BUTTON_DOWN); break; - case KEYCODE_BUTTON_L1: AsyncDown (PAD_BUTTON_LBUMPER); break; - case KEYCODE_BUTTON_R1: AsyncDown (PAD_BUTTON_RBUMPER); break; - case KEYCODE_BUTTON_START: AsyncDown (PAD_BUTTON_START); break; - case KEYCODE_BUTTON_SELECT: AsyncDown (PAD_BUTTON_SELECT); break; default: break; } } @@ -407,25 +394,12 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclas switch (key) { case 1: AsyncUp (PAD_BUTTON_BACK); break; // Back case 2: AsyncUp (PAD_BUTTON_MENU); break; // Menu - case 3: AsyncUp (PAD_BUTTON_A); break; // Search - case KEYCODE_BUTTON_CROSS: case KEYCODE_BUTTON_CROSS_PS3: AsyncUp(PAD_BUTTON_A); break; - case KEYCODE_BUTTON_CIRCLE: case KEYCODE_BUTTON_CIRCLE_PS3: AsyncUp (PAD_BUTTON_B); break; - case KEYCODE_BUTTON_SQUARE: AsyncUp (PAD_BUTTON_X); break; - case KEYCODE_BUTTON_TRIANGLE: AsyncUp (PAD_BUTTON_Y); break; - case KEYCODE_DPAD_LEFT: AsyncUp (PAD_BUTTON_LEFT); break; - case KEYCODE_DPAD_UP: AsyncUp (PAD_BUTTON_UP); break; - case KEYCODE_DPAD_RIGHT: AsyncUp (PAD_BUTTON_RIGHT); break; - case KEYCODE_DPAD_DOWN: AsyncUp (PAD_BUTTON_DOWN); break; - case KEYCODE_BUTTON_L1: AsyncUp (PAD_BUTTON_LBUMPER); break; - case KEYCODE_BUTTON_R1: AsyncUp (PAD_BUTTON_RBUMPER); break; - case KEYCODE_BUTTON_START: AsyncUp (PAD_BUTTON_START); break; - case KEYCODE_BUTTON_SELECT: AsyncUp (PAD_BUTTON_SELECT); break; default: break; } } From c97ed9fa3f8a6fc8da53d18c208b8cd0beece334 Mon Sep 17 00:00:00 2001 From: Daniel Dressler Date: Wed, 3 Jul 2013 20:52:29 -0700 Subject: [PATCH 0489/1445] Add xbox keys to native keycodes for platforms --- input/keycodes.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/input/keycodes.h b/input/keycodes.h index fadad418cf..2f46c0e2bf 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -1,4 +1,6 @@ #pragma once +#include +#define NEWKEY (INT_MAX - __LINE__) typedef enum _keycode_t { KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed @@ -211,5 +213,25 @@ typedef enum _keycode_t { KEYCODE_BUTTON_14 = 201, KEYCODE_BUTTON_15 = 202, KEYCODE_BUTTON_16 = 203, + + // == Extended Keys ==== + // Not native to android + + // Xbox 360 controller + KEYCODE_XBOX_A = NEWKEY, + KEYCODE_XBOX_B = NEWKEY, + KEYCODE_XBOX_X = NEWKEY, + KEYCODE_XBOX_Y = NEWKEY, + KEYCODE_XBOX_START = NEWKEY, + KEYCODE_XBOX_SELECT = NEWKEY, + KEYCODE_XBOX_TRIGGER_R = NEWKEY, + KEYCODE_XBOX_TRIGGER_L = NEWKEY, + KEYCODE_XBOX_BUMPER_R = NEWKEY, + KEYCODE_XBOX_BUMPER_L = NEWKEY, + KEYCODE_XBOX_DPAD_UP = NEWKEY, + KEYCODE_XBOX_DPAD_LEFT = NEWKEY, + KEYCODE_XBOX_DPAD_RIGHT = NEWKEY, + KEYCODE_XBOX_DPAD_DOWN = NEWKEY, + KEYCODE_XBOX_HOME = NEWKEY, } keycode_t; From 230ee0533b5676378a2b7bca609195eb7a55a322 Mon Sep 17 00:00:00 2001 From: The Dax Date: Thu, 4 Jul 2013 02:20:56 -0400 Subject: [PATCH 0490/1445] Fix Windows build error relating to keymapping. --- native.vcxproj | 1 + native.vcxproj.filters | 3 +++ 2 files changed, 4 insertions(+) diff --git a/native.vcxproj b/native.vcxproj index ea3cfa3ecb..e859bb83ae 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -352,6 +352,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index eca9e19926..a1c4a273eb 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -492,6 +492,9 @@ math + + input + From ac9bab015becee234371f3752ed2e9e6b4966106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 4 Jul 2013 10:20:40 +0200 Subject: [PATCH 0491/1445] Don't autogen key IDs --- input/keycodes.h | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/input/keycodes.h b/input/keycodes.h index 2f46c0e2bf..b8ec82b9ec 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -1,6 +1,4 @@ #pragma once -#include -#define NEWKEY (INT_MAX - __LINE__) typedef enum _keycode_t { KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed @@ -218,20 +216,21 @@ typedef enum _keycode_t { // Not native to android // Xbox 360 controller - KEYCODE_XBOX_A = NEWKEY, - KEYCODE_XBOX_B = NEWKEY, - KEYCODE_XBOX_X = NEWKEY, - KEYCODE_XBOX_Y = NEWKEY, - KEYCODE_XBOX_START = NEWKEY, - KEYCODE_XBOX_SELECT = NEWKEY, - KEYCODE_XBOX_TRIGGER_R = NEWKEY, - KEYCODE_XBOX_TRIGGER_L = NEWKEY, - KEYCODE_XBOX_BUMPER_R = NEWKEY, - KEYCODE_XBOX_BUMPER_L = NEWKEY, - KEYCODE_XBOX_DPAD_UP = NEWKEY, - KEYCODE_XBOX_DPAD_LEFT = NEWKEY, - KEYCODE_XBOX_DPAD_RIGHT = NEWKEY, - KEYCODE_XBOX_DPAD_DOWN = NEWKEY, - KEYCODE_XBOX_HOME = NEWKEY, + KEYCODE_XBOX_A = 5001, + KEYCODE_XBOX_B = 5002, + KEYCODE_XBOX_X = 5003, + KEYCODE_XBOX_Y = 5004, + KEYCODE_XBOX_START = 5005, + KEYCODE_XBOX_SELECT = 5006, + KEYCODE_XBOX_BUMPER_L = 5007, + KEYCODE_XBOX_BUMPER_R = 5008, + KEYCODE_XBOX_DPAD_UP = 5009, + KEYCODE_XBOX_DPAD_LEFT = 5010, + KEYCODE_XBOX_DPAD_RIGHT = 5011, + KEYCODE_XBOX_DPAD_DOWN = 5012, + // These are really axes, not buttons. But good to be able to map them as buttons. + KEYCODE_XBOX_TRIGGER_L = 5013, + KEYCODE_XBOX_TRIGGER_R = 5014, + // KEYCODE_XBOX_HOME = NEWKEY, // this can't be read on PC, right? } keycode_t; From 15f5a97a4e328fcb54cf7632ec67c1f542f71746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 4 Jul 2013 10:37:16 +0200 Subject: [PATCH 0492/1445] getFilesInDir: Sort files with case sensitivity --- file/file_util.cpp | 36 +++++++++++++++++++++++++----------- file/file_util.h | 16 +++------------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index a4ec706d63..48d7da5a0d 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -2,6 +2,9 @@ #define WIN32_LEAN_AND_MEAN #include #include +#ifndef strcasecmp +#define strcasecmp _stricmp +#endif #else #include #include @@ -11,7 +14,7 @@ #include #include #include -#include +#include #include #include @@ -26,17 +29,17 @@ // Hack #ifdef __SYMBIAN32__ static inline int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) { - struct dirent *readdir_entry; + struct dirent *readdir_entry; - readdir_entry = readdir(dirp); - if (readdir_entry == NULL) { - *result = NULL; - return errno; - } + readdir_entry = readdir(dirp); + if (readdir_entry == NULL) { + *result = NULL; + return errno; + } - *entry = *readdir_entry; - *result = entry; - return 0; + *entry = *readdir_entry; + *result = entry; + return 0; } #endif @@ -213,6 +216,17 @@ std::string getFileExtension(const std::string &fn) { return ext; } +bool FileInfo::operator <(const FileInfo &other) const { + if (isDirectory && !other.isDirectory) + return true; + else if (!isDirectory && other.isDirectory) + return false; + if (strcasecmp(name.c_str(), other.name.c_str()) < 0) + return true; + else + return false; +} + size_t getFilesInDir(const char *directory, std::vector *files, const char *filter) { size_t foundEntries = 0; std::set filters; @@ -387,4 +401,4 @@ std::vector getWindowsDrives() } return drives; } -#endif \ No newline at end of file +#endif diff --git a/file/file_util.h b/file/file_util.h index 6b65bebb7c..34ee8e61ba 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -12,8 +12,7 @@ bool readDataFromFile(bool text_file, unsigned char* &data, const unsigned int s // Beginnings of a directory utility system. TODO: Improve. -struct FileInfo -{ +struct FileInfo { std::string name; std::string fullName; bool exists; @@ -21,16 +20,7 @@ struct FileInfo bool isWritable; size_t size; - bool operator <(const FileInfo &other) const { - if (isDirectory && !other.isDirectory) - return true; - else if (!isDirectory && other.isDirectory) - return false; - if (name < other.name) - return true; - else - return false; - } + bool operator <(const FileInfo &other) const; }; std::string getFileExtension(const std::string &fn); @@ -46,4 +36,4 @@ std::string getDir(const std::string &path); #ifdef _WIN32 std::vector getWindowsDrives(); -#endif \ No newline at end of file +#endif From 72eefa450f89a58971a2343f0f60aebfe23bac92 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 5 Jul 2013 00:06:24 +0200 Subject: [PATCH 0493/1445] Add jpgd (public domain) --- Android.mk | 1 + ext/jpge/jpgd.cpp | 3172 ++++++++++++++++++++++++++++++++++++++++ ext/jpge/jpgd.h | 319 ++++ native.vcxproj | 2 + native.vcxproj.filters | 2 + 5 files changed, 3496 insertions(+) create mode 100644 ext/jpge/jpgd.cpp create mode 100644 ext/jpge/jpgd.h diff --git a/Android.mk b/Android.mk index cb258cf85a..03f39c302f 100644 --- a/Android.mk +++ b/Android.mk @@ -19,6 +19,7 @@ LOCAL_SRC_FILES :=\ data/compression.cpp \ ext/rg_etc1/rg_etc1.cpp \ ext/cityhash/city.cpp \ + ext/jpgd/jpgd.cpp \ ext/jpge/jpge.cpp \ ext/sha1/sha1.cpp \ ext/stb_image/stb_image.c \ diff --git a/ext/jpge/jpgd.cpp b/ext/jpge/jpgd.cpp new file mode 100644 index 0000000000..fad9a37a9a --- /dev/null +++ b/ext/jpge/jpgd.cpp @@ -0,0 +1,3172 @@ +// jpgd.cpp - C++ class for JPEG decompression. +// Public domain, Rich Geldreich +// Alex Evans: Linear memory allocator (taken from jpge.h). +// v1.04, May. 19, 2012: Code tweaks to fix VS2008 static code analysis warnings (all looked harmless) +// +// Supports progressive and baseline sequential JPEG image files, and the most common chroma subsampling factors: Y, H1V1, H2V1, H1V2, and H2V2. +// +// Chroma upsampling quality: H2V2 is upsampled in the frequency domain, H2V1 and H1V2 are upsampled using point sampling. +// Chroma upsampling reference: "Fast Scheme for Image Size Change in the Compressed Domain" +// http://vision.ai.uiuc.edu/~dugad/research/dct/index.html + +#include "jpgd.h" +#include + +#include +#define JPGD_ASSERT(x) assert(x) + +#ifdef _MSC_VER +#pragma warning (disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable +#endif + +// Set to 1 to enable freq. domain chroma upsampling on images using H2V2 subsampling (0=faster nearest neighbor sampling). +// This is slower, but results in higher quality on images with highly saturated colors. +#define JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING 1 + +#define JPGD_TRUE (1) +#define JPGD_FALSE (0) + +#define JPGD_MAX(a,b) (((a)>(b)) ? (a) : (b)) +#define JPGD_MIN(a,b) (((a)<(b)) ? (a) : (b)) + +namespace jpgd { + +static inline void *jpgd_malloc(size_t nSize) { return malloc(nSize); } +static inline void jpgd_free(void *p) { free(p); } + +// DCT coefficients are stored in this sequence. +static int g_ZAG[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 }; + +enum JPEG_MARKER +{ + M_SOF0 = 0xC0, M_SOF1 = 0xC1, M_SOF2 = 0xC2, M_SOF3 = 0xC3, M_SOF5 = 0xC5, M_SOF6 = 0xC6, M_SOF7 = 0xC7, M_JPG = 0xC8, + M_SOF9 = 0xC9, M_SOF10 = 0xCA, M_SOF11 = 0xCB, M_SOF13 = 0xCD, M_SOF14 = 0xCE, M_SOF15 = 0xCF, M_DHT = 0xC4, M_DAC = 0xCC, + M_RST0 = 0xD0, M_RST1 = 0xD1, M_RST2 = 0xD2, M_RST3 = 0xD3, M_RST4 = 0xD4, M_RST5 = 0xD5, M_RST6 = 0xD6, M_RST7 = 0xD7, + M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_DNL = 0xDC, M_DRI = 0xDD, M_DHP = 0xDE, M_EXP = 0xDF, + M_APP0 = 0xE0, M_APP15 = 0xEF, M_JPG0 = 0xF0, M_JPG13 = 0xFD, M_COM = 0xFE, M_TEM = 0x01, M_ERROR = 0x100, RST0 = 0xD0 +}; + +enum JPEG_SUBSAMPLING { JPGD_GRAYSCALE = 0, JPGD_YH1V1, JPGD_YH2V1, JPGD_YH1V2, JPGD_YH2V2 }; + +#define CONST_BITS 13 +#define PASS1_BITS 2 +#define SCALEDONE ((int32)1) + +#define FIX_0_298631336 ((int32)2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((int32)3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((int32)4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((int32)6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((int32)7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((int32)9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((int32)12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((int32)15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((int32)16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((int32)16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((int32)20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((int32)25172) /* FIX(3.072711026) */ + +#define DESCALE(x,n) (((x) + (SCALEDONE << ((n)-1))) >> (n)) +#define DESCALE_ZEROSHIFT(x,n) (((x) + (128 << (n)) + (SCALEDONE << ((n)-1))) >> (n)) + +#define MULTIPLY(var, cnst) ((var) * (cnst)) + +#define CLAMP(i) ((static_cast(i) > 255) ? (((~i) >> 31) & 0xFF) : (i)) + +// Compiler creates a fast path 1D IDCT for X non-zero columns +template +struct Row +{ + static void idct(int* pTemp, const jpgd_block_t* pSrc) + { + // ACCESS_COL() will be optimized at compile time to either an array access, or 0. + #define ACCESS_COL(x) (((x) < NONZERO_COLS) ? (int)pSrc[x] : 0) + + const int z2 = ACCESS_COL(2), z3 = ACCESS_COL(6); + + const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + const int tmp0 = (ACCESS_COL(0) + ACCESS_COL(4)) << CONST_BITS; + const int tmp1 = (ACCESS_COL(0) - ACCESS_COL(4)) << CONST_BITS; + + const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2; + + const int atmp0 = ACCESS_COL(7), atmp1 = ACCESS_COL(5), atmp2 = ACCESS_COL(3), atmp3 = ACCESS_COL(1); + + const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3; + const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602); + + const int az1 = MULTIPLY(bz1, - FIX_0_899976223); + const int az2 = MULTIPLY(bz2, - FIX_2_562915447); + const int az3 = MULTIPLY(bz3, - FIX_1_961570560) + bz5; + const int az4 = MULTIPLY(bz4, - FIX_0_390180644) + bz5; + + const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3; + const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4; + const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3; + const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4; + + pTemp[0] = DESCALE(tmp10 + btmp3, CONST_BITS-PASS1_BITS); + pTemp[7] = DESCALE(tmp10 - btmp3, CONST_BITS-PASS1_BITS); + pTemp[1] = DESCALE(tmp11 + btmp2, CONST_BITS-PASS1_BITS); + pTemp[6] = DESCALE(tmp11 - btmp2, CONST_BITS-PASS1_BITS); + pTemp[2] = DESCALE(tmp12 + btmp1, CONST_BITS-PASS1_BITS); + pTemp[5] = DESCALE(tmp12 - btmp1, CONST_BITS-PASS1_BITS); + pTemp[3] = DESCALE(tmp13 + btmp0, CONST_BITS-PASS1_BITS); + pTemp[4] = DESCALE(tmp13 - btmp0, CONST_BITS-PASS1_BITS); + } +}; + +template <> +struct Row<0> +{ + static void idct(int* pTemp, const jpgd_block_t* pSrc) + { +#ifdef _MSC_VER + pTemp; pSrc; +#endif + } +}; + +template <> +struct Row<1> +{ + static void idct(int* pTemp, const jpgd_block_t* pSrc) + { + const int dcval = (pSrc[0] << PASS1_BITS); + + pTemp[0] = dcval; + pTemp[1] = dcval; + pTemp[2] = dcval; + pTemp[3] = dcval; + pTemp[4] = dcval; + pTemp[5] = dcval; + pTemp[6] = dcval; + pTemp[7] = dcval; + } +}; + +// Compiler creates a fast path 1D IDCT for X non-zero rows +template +struct Col +{ + static void idct(uint8* pDst_ptr, const int* pTemp) + { + // ACCESS_ROW() will be optimized at compile time to either an array access, or 0. + #define ACCESS_ROW(x) (((x) < NONZERO_ROWS) ? pTemp[x * 8] : 0) + + const int z2 = ACCESS_ROW(2); + const int z3 = ACCESS_ROW(6); + + const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + const int tmp0 = (ACCESS_ROW(0) + ACCESS_ROW(4)) << CONST_BITS; + const int tmp1 = (ACCESS_ROW(0) - ACCESS_ROW(4)) << CONST_BITS; + + const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2; + + const int atmp0 = ACCESS_ROW(7), atmp1 = ACCESS_ROW(5), atmp2 = ACCESS_ROW(3), atmp3 = ACCESS_ROW(1); + + const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3; + const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602); + + const int az1 = MULTIPLY(bz1, - FIX_0_899976223); + const int az2 = MULTIPLY(bz2, - FIX_2_562915447); + const int az3 = MULTIPLY(bz3, - FIX_1_961570560) + bz5; + const int az4 = MULTIPLY(bz4, - FIX_0_390180644) + bz5; + + const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3; + const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4; + const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3; + const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4; + + int i = DESCALE_ZEROSHIFT(tmp10 + btmp3, CONST_BITS+PASS1_BITS+3); + pDst_ptr[8*0] = (uint8)CLAMP(i); + + i = DESCALE_ZEROSHIFT(tmp10 - btmp3, CONST_BITS+PASS1_BITS+3); + pDst_ptr[8*7] = (uint8)CLAMP(i); + + i = DESCALE_ZEROSHIFT(tmp11 + btmp2, CONST_BITS+PASS1_BITS+3); + pDst_ptr[8*1] = (uint8)CLAMP(i); + + i = DESCALE_ZEROSHIFT(tmp11 - btmp2, CONST_BITS+PASS1_BITS+3); + pDst_ptr[8*6] = (uint8)CLAMP(i); + + i = DESCALE_ZEROSHIFT(tmp12 + btmp1, CONST_BITS+PASS1_BITS+3); + pDst_ptr[8*2] = (uint8)CLAMP(i); + + i = DESCALE_ZEROSHIFT(tmp12 - btmp1, CONST_BITS+PASS1_BITS+3); + pDst_ptr[8*5] = (uint8)CLAMP(i); + + i = DESCALE_ZEROSHIFT(tmp13 + btmp0, CONST_BITS+PASS1_BITS+3); + pDst_ptr[8*3] = (uint8)CLAMP(i); + + i = DESCALE_ZEROSHIFT(tmp13 - btmp0, CONST_BITS+PASS1_BITS+3); + pDst_ptr[8*4] = (uint8)CLAMP(i); + } +}; + +template <> +struct Col<1> +{ + static void idct(uint8* pDst_ptr, const int* pTemp) + { + int dcval = DESCALE_ZEROSHIFT(pTemp[0], PASS1_BITS+3); + const uint8 dcval_clamped = (uint8)CLAMP(dcval); + pDst_ptr[0*8] = dcval_clamped; + pDst_ptr[1*8] = dcval_clamped; + pDst_ptr[2*8] = dcval_clamped; + pDst_ptr[3*8] = dcval_clamped; + pDst_ptr[4*8] = dcval_clamped; + pDst_ptr[5*8] = dcval_clamped; + pDst_ptr[6*8] = dcval_clamped; + pDst_ptr[7*8] = dcval_clamped; + } +}; + +static const uint8 s_idct_row_table[] = +{ + 1,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0, 2,1,0,0,0,0,0,0, 2,1,1,0,0,0,0,0, 2,2,1,0,0,0,0,0, 3,2,1,0,0,0,0,0, 4,2,1,0,0,0,0,0, 4,3,1,0,0,0,0,0, + 4,3,2,0,0,0,0,0, 4,3,2,1,0,0,0,0, 4,3,2,1,1,0,0,0, 4,3,2,2,1,0,0,0, 4,3,3,2,1,0,0,0, 4,4,3,2,1,0,0,0, 5,4,3,2,1,0,0,0, 6,4,3,2,1,0,0,0, + 6,5,3,2,1,0,0,0, 6,5,4,2,1,0,0,0, 6,5,4,3,1,0,0,0, 6,5,4,3,2,0,0,0, 6,5,4,3,2,1,0,0, 6,5,4,3,2,1,1,0, 6,5,4,3,2,2,1,0, 6,5,4,3,3,2,1,0, + 6,5,4,4,3,2,1,0, 6,5,5,4,3,2,1,0, 6,6,5,4,3,2,1,0, 7,6,5,4,3,2,1,0, 8,6,5,4,3,2,1,0, 8,7,5,4,3,2,1,0, 8,7,6,4,3,2,1,0, 8,7,6,5,3,2,1,0, + 8,7,6,5,4,2,1,0, 8,7,6,5,4,3,1,0, 8,7,6,5,4,3,2,0, 8,7,6,5,4,3,2,1, 8,7,6,5,4,3,2,2, 8,7,6,5,4,3,3,2, 8,7,6,5,4,4,3,2, 8,7,6,5,5,4,3,2, + 8,7,6,6,5,4,3,2, 8,7,7,6,5,4,3,2, 8,8,7,6,5,4,3,2, 8,8,8,6,5,4,3,2, 8,8,8,7,5,4,3,2, 8,8,8,7,6,4,3,2, 8,8,8,7,6,5,3,2, 8,8,8,7,6,5,4,2, + 8,8,8,7,6,5,4,3, 8,8,8,7,6,5,4,4, 8,8,8,7,6,5,5,4, 8,8,8,7,6,6,5,4, 8,8,8,7,7,6,5,4, 8,8,8,8,7,6,5,4, 8,8,8,8,8,6,5,4, 8,8,8,8,8,7,5,4, + 8,8,8,8,8,7,6,4, 8,8,8,8,8,7,6,5, 8,8,8,8,8,7,6,6, 8,8,8,8,8,7,7,6, 8,8,8,8,8,8,7,6, 8,8,8,8,8,8,8,6, 8,8,8,8,8,8,8,7, 8,8,8,8,8,8,8,8, +}; + +static const uint8 s_idct_col_table[] = { 1, 1, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }; + +void idct(const jpgd_block_t* pSrc_ptr, uint8* pDst_ptr, int block_max_zag) +{ + JPGD_ASSERT(block_max_zag >= 1); + JPGD_ASSERT(block_max_zag <= 64); + + if (block_max_zag <= 1) + { + int k = ((pSrc_ptr[0] + 4) >> 3) + 128; + k = CLAMP(k); + k = k | (k<<8); + k = k | (k<<16); + + for (int i = 8; i > 0; i--) + { + *(int*)&pDst_ptr[0] = k; + *(int*)&pDst_ptr[4] = k; + pDst_ptr += 8; + } + return; + } + + int temp[64]; + + const jpgd_block_t* pSrc = pSrc_ptr; + int* pTemp = temp; + + const uint8* pRow_tab = &s_idct_row_table[(block_max_zag - 1) * 8]; + int i; + for (i = 8; i > 0; i--, pRow_tab++) + { + switch (*pRow_tab) + { + case 0: Row<0>::idct(pTemp, pSrc); break; + case 1: Row<1>::idct(pTemp, pSrc); break; + case 2: Row<2>::idct(pTemp, pSrc); break; + case 3: Row<3>::idct(pTemp, pSrc); break; + case 4: Row<4>::idct(pTemp, pSrc); break; + case 5: Row<5>::idct(pTemp, pSrc); break; + case 6: Row<6>::idct(pTemp, pSrc); break; + case 7: Row<7>::idct(pTemp, pSrc); break; + case 8: Row<8>::idct(pTemp, pSrc); break; + } + + pSrc += 8; + pTemp += 8; + } + + pTemp = temp; + + const int nonzero_rows = s_idct_col_table[block_max_zag - 1]; + for (i = 8; i > 0; i--) + { + switch (nonzero_rows) + { + case 1: Col<1>::idct(pDst_ptr, pTemp); break; + case 2: Col<2>::idct(pDst_ptr, pTemp); break; + case 3: Col<3>::idct(pDst_ptr, pTemp); break; + case 4: Col<4>::idct(pDst_ptr, pTemp); break; + case 5: Col<5>::idct(pDst_ptr, pTemp); break; + case 6: Col<6>::idct(pDst_ptr, pTemp); break; + case 7: Col<7>::idct(pDst_ptr, pTemp); break; + case 8: Col<8>::idct(pDst_ptr, pTemp); break; + } + + pTemp++; + pDst_ptr++; + } +} + +void idct_4x4(const jpgd_block_t* pSrc_ptr, uint8* pDst_ptr) +{ + int temp[64]; + int* pTemp = temp; + const jpgd_block_t* pSrc = pSrc_ptr; + + for (int i = 4; i > 0; i--) + { + Row<4>::idct(pTemp, pSrc); + pSrc += 8; + pTemp += 8; + } + + pTemp = temp; + for (int i = 8; i > 0; i--) + { + Col<4>::idct(pDst_ptr, pTemp); + pTemp++; + pDst_ptr++; + } +} + +// Retrieve one character from the input stream. +inline uint jpeg_decoder::get_char() +{ + // Any bytes remaining in buffer? + if (!m_in_buf_left) + { + // Try to get more bytes. + prep_in_buffer(); + // Still nothing to get? + if (!m_in_buf_left) + { + // Pad the end of the stream with 0xFF 0xD9 (EOI marker) + int t = m_tem_flag; + m_tem_flag ^= 1; + if (t) + return 0xD9; + else + return 0xFF; + } + } + + uint c = *m_pIn_buf_ofs++; + m_in_buf_left--; + + return c; +} + +// Same as previous method, except can indicate if the character is a pad character or not. +inline uint jpeg_decoder::get_char(bool *pPadding_flag) +{ + if (!m_in_buf_left) + { + prep_in_buffer(); + if (!m_in_buf_left) + { + *pPadding_flag = true; + int t = m_tem_flag; + m_tem_flag ^= 1; + if (t) + return 0xD9; + else + return 0xFF; + } + } + + *pPadding_flag = false; + + uint c = *m_pIn_buf_ofs++; + m_in_buf_left--; + + return c; +} + +// Inserts a previously retrieved character back into the input buffer. +inline void jpeg_decoder::stuff_char(uint8 q) +{ + *(--m_pIn_buf_ofs) = q; + m_in_buf_left++; +} + +// Retrieves one character from the input stream, but does not read past markers. Will continue to return 0xFF when a marker is encountered. +inline uint8 jpeg_decoder::get_octet() +{ + bool padding_flag; + int c = get_char(&padding_flag); + + if (c == 0xFF) + { + if (padding_flag) + return 0xFF; + + c = get_char(&padding_flag); + if (padding_flag) + { + stuff_char(0xFF); + return 0xFF; + } + + if (c == 0x00) + return 0xFF; + else + { + stuff_char(static_cast(c)); + stuff_char(0xFF); + return 0xFF; + } + } + + return static_cast(c); +} + +// Retrieves a variable number of bits from the input stream. Does not recognize markers. +inline uint jpeg_decoder::get_bits(int num_bits) +{ + if (!num_bits) + return 0; + + uint i = m_bit_buf >> (32 - num_bits); + + if ((m_bits_left -= num_bits) <= 0) + { + m_bit_buf <<= (num_bits += m_bits_left); + + uint c1 = get_char(); + uint c2 = get_char(); + m_bit_buf = (m_bit_buf & 0xFFFF0000) | (c1 << 8) | c2; + + m_bit_buf <<= -m_bits_left; + + m_bits_left += 16; + + JPGD_ASSERT(m_bits_left >= 0); + } + else + m_bit_buf <<= num_bits; + + return i; +} + +// Retrieves a variable number of bits from the input stream. Markers will not be read into the input bit buffer. Instead, an infinite number of all 1's will be returned when a marker is encountered. +inline uint jpeg_decoder::get_bits_no_markers(int num_bits) +{ + if (!num_bits) + return 0; + + uint i = m_bit_buf >> (32 - num_bits); + + if ((m_bits_left -= num_bits) <= 0) + { + m_bit_buf <<= (num_bits += m_bits_left); + + if ((m_in_buf_left < 2) || (m_pIn_buf_ofs[0] == 0xFF) || (m_pIn_buf_ofs[1] == 0xFF)) + { + uint c1 = get_octet(); + uint c2 = get_octet(); + m_bit_buf |= (c1 << 8) | c2; + } + else + { + m_bit_buf |= ((uint)m_pIn_buf_ofs[0] << 8) | m_pIn_buf_ofs[1]; + m_in_buf_left -= 2; + m_pIn_buf_ofs += 2; + } + + m_bit_buf <<= -m_bits_left; + + m_bits_left += 16; + + JPGD_ASSERT(m_bits_left >= 0); + } + else + m_bit_buf <<= num_bits; + + return i; +} + +// Decodes a Huffman encoded symbol. +inline int jpeg_decoder::huff_decode(huff_tables *pH) +{ + int symbol; + + // Check first 8-bits: do we have a complete symbol? + if ((symbol = pH->look_up[m_bit_buf >> 24]) < 0) + { + // Decode more bits, use a tree traversal to find symbol. + int ofs = 23; + do + { + symbol = pH->tree[-(int)(symbol + ((m_bit_buf >> ofs) & 1))]; + ofs--; + } while (symbol < 0); + + get_bits_no_markers(8 + (23 - ofs)); + } + else + get_bits_no_markers(pH->code_size[symbol]); + + return symbol; +} + +// Decodes a Huffman encoded symbol. +inline int jpeg_decoder::huff_decode(huff_tables *pH, int& extra_bits) +{ + int symbol; + + // Check first 8-bits: do we have a complete symbol? + if ((symbol = pH->look_up2[m_bit_buf >> 24]) < 0) + { + // Use a tree traversal to find symbol. + int ofs = 23; + do + { + symbol = pH->tree[-(int)(symbol + ((m_bit_buf >> ofs) & 1))]; + ofs--; + } while (symbol < 0); + + get_bits_no_markers(8 + (23 - ofs)); + + extra_bits = get_bits_no_markers(symbol & 0xF); + } + else + { + JPGD_ASSERT(((symbol >> 8) & 31) == pH->code_size[symbol & 255] + ((symbol & 0x8000) ? (symbol & 15) : 0)); + + if (symbol & 0x8000) + { + get_bits_no_markers((symbol >> 8) & 31); + extra_bits = symbol >> 16; + } + else + { + int code_size = (symbol >> 8) & 31; + int num_extra_bits = symbol & 0xF; + int bits = code_size + num_extra_bits; + if (bits <= (m_bits_left + 16)) + extra_bits = get_bits_no_markers(bits) & ((1 << num_extra_bits) - 1); + else + { + get_bits_no_markers(code_size); + extra_bits = get_bits_no_markers(num_extra_bits); + } + } + + symbol &= 0xFF; + } + + return symbol; +} + +// Tables and macro used to fully decode the DPCM differences. +static const int s_extend_test[16] = { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; +static const int s_extend_offset[16] = { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; +static const int s_extend_mask[] = { 0, (1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7), (1<<8), (1<<9), (1<<10), (1<<11), (1<<12), (1<<13), (1<<14), (1<<15), (1<<16) }; +// The logical AND's in this macro are to shut up static code analysis (aren't really necessary - couldn't find another way to do this) +#define JPGD_HUFF_EXTEND(x, s) (((x) < s_extend_test[s & 15]) ? ((x) + s_extend_offset[s & 15]) : (x)) + +// Clamps a value between 0-255. +inline uint8 jpeg_decoder::clamp(int i) +{ + if (static_cast(i) > 255) + i = (((~i) >> 31) & 0xFF); + + return static_cast(i); +} + +namespace DCT_Upsample +{ + struct Matrix44 + { + typedef int Element_Type; + enum { NUM_ROWS = 4, NUM_COLS = 4 }; + + Element_Type v[NUM_ROWS][NUM_COLS]; + + inline int rows() const { return NUM_ROWS; } + inline int cols() const { return NUM_COLS; } + + inline const Element_Type & at(int r, int c) const { return v[r][c]; } + inline Element_Type & at(int r, int c) { return v[r][c]; } + + inline Matrix44() { } + + inline Matrix44& operator += (const Matrix44& a) + { + for (int r = 0; r < NUM_ROWS; r++) + { + at(r, 0) += a.at(r, 0); + at(r, 1) += a.at(r, 1); + at(r, 2) += a.at(r, 2); + at(r, 3) += a.at(r, 3); + } + return *this; + } + + inline Matrix44& operator -= (const Matrix44& a) + { + for (int r = 0; r < NUM_ROWS; r++) + { + at(r, 0) -= a.at(r, 0); + at(r, 1) -= a.at(r, 1); + at(r, 2) -= a.at(r, 2); + at(r, 3) -= a.at(r, 3); + } + return *this; + } + + friend inline Matrix44 operator + (const Matrix44& a, const Matrix44& b) + { + Matrix44 ret; + for (int r = 0; r < NUM_ROWS; r++) + { + ret.at(r, 0) = a.at(r, 0) + b.at(r, 0); + ret.at(r, 1) = a.at(r, 1) + b.at(r, 1); + ret.at(r, 2) = a.at(r, 2) + b.at(r, 2); + ret.at(r, 3) = a.at(r, 3) + b.at(r, 3); + } + return ret; + } + + friend inline Matrix44 operator - (const Matrix44& a, const Matrix44& b) + { + Matrix44 ret; + for (int r = 0; r < NUM_ROWS; r++) + { + ret.at(r, 0) = a.at(r, 0) - b.at(r, 0); + ret.at(r, 1) = a.at(r, 1) - b.at(r, 1); + ret.at(r, 2) = a.at(r, 2) - b.at(r, 2); + ret.at(r, 3) = a.at(r, 3) - b.at(r, 3); + } + return ret; + } + + static inline void add_and_store(jpgd_block_t* pDst, const Matrix44& a, const Matrix44& b) + { + for (int r = 0; r < 4; r++) + { + pDst[0*8 + r] = static_cast(a.at(r, 0) + b.at(r, 0)); + pDst[1*8 + r] = static_cast(a.at(r, 1) + b.at(r, 1)); + pDst[2*8 + r] = static_cast(a.at(r, 2) + b.at(r, 2)); + pDst[3*8 + r] = static_cast(a.at(r, 3) + b.at(r, 3)); + } + } + + static inline void sub_and_store(jpgd_block_t* pDst, const Matrix44& a, const Matrix44& b) + { + for (int r = 0; r < 4; r++) + { + pDst[0*8 + r] = static_cast(a.at(r, 0) - b.at(r, 0)); + pDst[1*8 + r] = static_cast(a.at(r, 1) - b.at(r, 1)); + pDst[2*8 + r] = static_cast(a.at(r, 2) - b.at(r, 2)); + pDst[3*8 + r] = static_cast(a.at(r, 3) - b.at(r, 3)); + } + } + }; + + const int FRACT_BITS = 10; + const int SCALE = 1 << FRACT_BITS; + + typedef int Temp_Type; + #define D(i) (((i) + (SCALE >> 1)) >> FRACT_BITS) + #define F(i) ((int)((i) * SCALE + .5f)) + + // Any decent C++ compiler will optimize this at compile time to a 0, or an array access. + #define AT(c, r) ((((c)>=NUM_COLS)||((r)>=NUM_ROWS)) ? 0 : pSrc[(c)+(r)*8]) + + // NUM_ROWS/NUM_COLS = # of non-zero rows/cols in input matrix + template + struct P_Q + { + static void calc(Matrix44& P, Matrix44& Q, const jpgd_block_t* pSrc) + { + // 4x8 = 4x8 times 8x8, matrix 0 is constant + const Temp_Type X000 = AT(0, 0); + const Temp_Type X001 = AT(0, 1); + const Temp_Type X002 = AT(0, 2); + const Temp_Type X003 = AT(0, 3); + const Temp_Type X004 = AT(0, 4); + const Temp_Type X005 = AT(0, 5); + const Temp_Type X006 = AT(0, 6); + const Temp_Type X007 = AT(0, 7); + const Temp_Type X010 = D(F(0.415735f) * AT(1, 0) + F(0.791065f) * AT(3, 0) + F(-0.352443f) * AT(5, 0) + F(0.277785f) * AT(7, 0)); + const Temp_Type X011 = D(F(0.415735f) * AT(1, 1) + F(0.791065f) * AT(3, 1) + F(-0.352443f) * AT(5, 1) + F(0.277785f) * AT(7, 1)); + const Temp_Type X012 = D(F(0.415735f) * AT(1, 2) + F(0.791065f) * AT(3, 2) + F(-0.352443f) * AT(5, 2) + F(0.277785f) * AT(7, 2)); + const Temp_Type X013 = D(F(0.415735f) * AT(1, 3) + F(0.791065f) * AT(3, 3) + F(-0.352443f) * AT(5, 3) + F(0.277785f) * AT(7, 3)); + const Temp_Type X014 = D(F(0.415735f) * AT(1, 4) + F(0.791065f) * AT(3, 4) + F(-0.352443f) * AT(5, 4) + F(0.277785f) * AT(7, 4)); + const Temp_Type X015 = D(F(0.415735f) * AT(1, 5) + F(0.791065f) * AT(3, 5) + F(-0.352443f) * AT(5, 5) + F(0.277785f) * AT(7, 5)); + const Temp_Type X016 = D(F(0.415735f) * AT(1, 6) + F(0.791065f) * AT(3, 6) + F(-0.352443f) * AT(5, 6) + F(0.277785f) * AT(7, 6)); + const Temp_Type X017 = D(F(0.415735f) * AT(1, 7) + F(0.791065f) * AT(3, 7) + F(-0.352443f) * AT(5, 7) + F(0.277785f) * AT(7, 7)); + const Temp_Type X020 = AT(4, 0); + const Temp_Type X021 = AT(4, 1); + const Temp_Type X022 = AT(4, 2); + const Temp_Type X023 = AT(4, 3); + const Temp_Type X024 = AT(4, 4); + const Temp_Type X025 = AT(4, 5); + const Temp_Type X026 = AT(4, 6); + const Temp_Type X027 = AT(4, 7); + const Temp_Type X030 = D(F(0.022887f) * AT(1, 0) + F(-0.097545f) * AT(3, 0) + F(0.490393f) * AT(5, 0) + F(0.865723f) * AT(7, 0)); + const Temp_Type X031 = D(F(0.022887f) * AT(1, 1) + F(-0.097545f) * AT(3, 1) + F(0.490393f) * AT(5, 1) + F(0.865723f) * AT(7, 1)); + const Temp_Type X032 = D(F(0.022887f) * AT(1, 2) + F(-0.097545f) * AT(3, 2) + F(0.490393f) * AT(5, 2) + F(0.865723f) * AT(7, 2)); + const Temp_Type X033 = D(F(0.022887f) * AT(1, 3) + F(-0.097545f) * AT(3, 3) + F(0.490393f) * AT(5, 3) + F(0.865723f) * AT(7, 3)); + const Temp_Type X034 = D(F(0.022887f) * AT(1, 4) + F(-0.097545f) * AT(3, 4) + F(0.490393f) * AT(5, 4) + F(0.865723f) * AT(7, 4)); + const Temp_Type X035 = D(F(0.022887f) * AT(1, 5) + F(-0.097545f) * AT(3, 5) + F(0.490393f) * AT(5, 5) + F(0.865723f) * AT(7, 5)); + const Temp_Type X036 = D(F(0.022887f) * AT(1, 6) + F(-0.097545f) * AT(3, 6) + F(0.490393f) * AT(5, 6) + F(0.865723f) * AT(7, 6)); + const Temp_Type X037 = D(F(0.022887f) * AT(1, 7) + F(-0.097545f) * AT(3, 7) + F(0.490393f) * AT(5, 7) + F(0.865723f) * AT(7, 7)); + + // 4x4 = 4x8 times 8x4, matrix 1 is constant + P.at(0, 0) = X000; + P.at(0, 1) = D(X001 * F(0.415735f) + X003 * F(0.791065f) + X005 * F(-0.352443f) + X007 * F(0.277785f)); + P.at(0, 2) = X004; + P.at(0, 3) = D(X001 * F(0.022887f) + X003 * F(-0.097545f) + X005 * F(0.490393f) + X007 * F(0.865723f)); + P.at(1, 0) = X010; + P.at(1, 1) = D(X011 * F(0.415735f) + X013 * F(0.791065f) + X015 * F(-0.352443f) + X017 * F(0.277785f)); + P.at(1, 2) = X014; + P.at(1, 3) = D(X011 * F(0.022887f) + X013 * F(-0.097545f) + X015 * F(0.490393f) + X017 * F(0.865723f)); + P.at(2, 0) = X020; + P.at(2, 1) = D(X021 * F(0.415735f) + X023 * F(0.791065f) + X025 * F(-0.352443f) + X027 * F(0.277785f)); + P.at(2, 2) = X024; + P.at(2, 3) = D(X021 * F(0.022887f) + X023 * F(-0.097545f) + X025 * F(0.490393f) + X027 * F(0.865723f)); + P.at(3, 0) = X030; + P.at(3, 1) = D(X031 * F(0.415735f) + X033 * F(0.791065f) + X035 * F(-0.352443f) + X037 * F(0.277785f)); + P.at(3, 2) = X034; + P.at(3, 3) = D(X031 * F(0.022887f) + X033 * F(-0.097545f) + X035 * F(0.490393f) + X037 * F(0.865723f)); + // 40 muls 24 adds + + // 4x4 = 4x8 times 8x4, matrix 1 is constant + Q.at(0, 0) = D(X001 * F(0.906127f) + X003 * F(-0.318190f) + X005 * F(0.212608f) + X007 * F(-0.180240f)); + Q.at(0, 1) = X002; + Q.at(0, 2) = D(X001 * F(-0.074658f) + X003 * F(0.513280f) + X005 * F(0.768178f) + X007 * F(-0.375330f)); + Q.at(0, 3) = X006; + Q.at(1, 0) = D(X011 * F(0.906127f) + X013 * F(-0.318190f) + X015 * F(0.212608f) + X017 * F(-0.180240f)); + Q.at(1, 1) = X012; + Q.at(1, 2) = D(X011 * F(-0.074658f) + X013 * F(0.513280f) + X015 * F(0.768178f) + X017 * F(-0.375330f)); + Q.at(1, 3) = X016; + Q.at(2, 0) = D(X021 * F(0.906127f) + X023 * F(-0.318190f) + X025 * F(0.212608f) + X027 * F(-0.180240f)); + Q.at(2, 1) = X022; + Q.at(2, 2) = D(X021 * F(-0.074658f) + X023 * F(0.513280f) + X025 * F(0.768178f) + X027 * F(-0.375330f)); + Q.at(2, 3) = X026; + Q.at(3, 0) = D(X031 * F(0.906127f) + X033 * F(-0.318190f) + X035 * F(0.212608f) + X037 * F(-0.180240f)); + Q.at(3, 1) = X032; + Q.at(3, 2) = D(X031 * F(-0.074658f) + X033 * F(0.513280f) + X035 * F(0.768178f) + X037 * F(-0.375330f)); + Q.at(3, 3) = X036; + // 40 muls 24 adds + } + }; + + template + struct R_S + { + static void calc(Matrix44& R, Matrix44& S, const jpgd_block_t* pSrc) + { + // 4x8 = 4x8 times 8x8, matrix 0 is constant + const Temp_Type X100 = D(F(0.906127f) * AT(1, 0) + F(-0.318190f) * AT(3, 0) + F(0.212608f) * AT(5, 0) + F(-0.180240f) * AT(7, 0)); + const Temp_Type X101 = D(F(0.906127f) * AT(1, 1) + F(-0.318190f) * AT(3, 1) + F(0.212608f) * AT(5, 1) + F(-0.180240f) * AT(7, 1)); + const Temp_Type X102 = D(F(0.906127f) * AT(1, 2) + F(-0.318190f) * AT(3, 2) + F(0.212608f) * AT(5, 2) + F(-0.180240f) * AT(7, 2)); + const Temp_Type X103 = D(F(0.906127f) * AT(1, 3) + F(-0.318190f) * AT(3, 3) + F(0.212608f) * AT(5, 3) + F(-0.180240f) * AT(7, 3)); + const Temp_Type X104 = D(F(0.906127f) * AT(1, 4) + F(-0.318190f) * AT(3, 4) + F(0.212608f) * AT(5, 4) + F(-0.180240f) * AT(7, 4)); + const Temp_Type X105 = D(F(0.906127f) * AT(1, 5) + F(-0.318190f) * AT(3, 5) + F(0.212608f) * AT(5, 5) + F(-0.180240f) * AT(7, 5)); + const Temp_Type X106 = D(F(0.906127f) * AT(1, 6) + F(-0.318190f) * AT(3, 6) + F(0.212608f) * AT(5, 6) + F(-0.180240f) * AT(7, 6)); + const Temp_Type X107 = D(F(0.906127f) * AT(1, 7) + F(-0.318190f) * AT(3, 7) + F(0.212608f) * AT(5, 7) + F(-0.180240f) * AT(7, 7)); + const Temp_Type X110 = AT(2, 0); + const Temp_Type X111 = AT(2, 1); + const Temp_Type X112 = AT(2, 2); + const Temp_Type X113 = AT(2, 3); + const Temp_Type X114 = AT(2, 4); + const Temp_Type X115 = AT(2, 5); + const Temp_Type X116 = AT(2, 6); + const Temp_Type X117 = AT(2, 7); + const Temp_Type X120 = D(F(-0.074658f) * AT(1, 0) + F(0.513280f) * AT(3, 0) + F(0.768178f) * AT(5, 0) + F(-0.375330f) * AT(7, 0)); + const Temp_Type X121 = D(F(-0.074658f) * AT(1, 1) + F(0.513280f) * AT(3, 1) + F(0.768178f) * AT(5, 1) + F(-0.375330f) * AT(7, 1)); + const Temp_Type X122 = D(F(-0.074658f) * AT(1, 2) + F(0.513280f) * AT(3, 2) + F(0.768178f) * AT(5, 2) + F(-0.375330f) * AT(7, 2)); + const Temp_Type X123 = D(F(-0.074658f) * AT(1, 3) + F(0.513280f) * AT(3, 3) + F(0.768178f) * AT(5, 3) + F(-0.375330f) * AT(7, 3)); + const Temp_Type X124 = D(F(-0.074658f) * AT(1, 4) + F(0.513280f) * AT(3, 4) + F(0.768178f) * AT(5, 4) + F(-0.375330f) * AT(7, 4)); + const Temp_Type X125 = D(F(-0.074658f) * AT(1, 5) + F(0.513280f) * AT(3, 5) + F(0.768178f) * AT(5, 5) + F(-0.375330f) * AT(7, 5)); + const Temp_Type X126 = D(F(-0.074658f) * AT(1, 6) + F(0.513280f) * AT(3, 6) + F(0.768178f) * AT(5, 6) + F(-0.375330f) * AT(7, 6)); + const Temp_Type X127 = D(F(-0.074658f) * AT(1, 7) + F(0.513280f) * AT(3, 7) + F(0.768178f) * AT(5, 7) + F(-0.375330f) * AT(7, 7)); + const Temp_Type X130 = AT(6, 0); + const Temp_Type X131 = AT(6, 1); + const Temp_Type X132 = AT(6, 2); + const Temp_Type X133 = AT(6, 3); + const Temp_Type X134 = AT(6, 4); + const Temp_Type X135 = AT(6, 5); + const Temp_Type X136 = AT(6, 6); + const Temp_Type X137 = AT(6, 7); + // 80 muls 48 adds + + // 4x4 = 4x8 times 8x4, matrix 1 is constant + R.at(0, 0) = X100; + R.at(0, 1) = D(X101 * F(0.415735f) + X103 * F(0.791065f) + X105 * F(-0.352443f) + X107 * F(0.277785f)); + R.at(0, 2) = X104; + R.at(0, 3) = D(X101 * F(0.022887f) + X103 * F(-0.097545f) + X105 * F(0.490393f) + X107 * F(0.865723f)); + R.at(1, 0) = X110; + R.at(1, 1) = D(X111 * F(0.415735f) + X113 * F(0.791065f) + X115 * F(-0.352443f) + X117 * F(0.277785f)); + R.at(1, 2) = X114; + R.at(1, 3) = D(X111 * F(0.022887f) + X113 * F(-0.097545f) + X115 * F(0.490393f) + X117 * F(0.865723f)); + R.at(2, 0) = X120; + R.at(2, 1) = D(X121 * F(0.415735f) + X123 * F(0.791065f) + X125 * F(-0.352443f) + X127 * F(0.277785f)); + R.at(2, 2) = X124; + R.at(2, 3) = D(X121 * F(0.022887f) + X123 * F(-0.097545f) + X125 * F(0.490393f) + X127 * F(0.865723f)); + R.at(3, 0) = X130; + R.at(3, 1) = D(X131 * F(0.415735f) + X133 * F(0.791065f) + X135 * F(-0.352443f) + X137 * F(0.277785f)); + R.at(3, 2) = X134; + R.at(3, 3) = D(X131 * F(0.022887f) + X133 * F(-0.097545f) + X135 * F(0.490393f) + X137 * F(0.865723f)); + // 40 muls 24 adds + // 4x4 = 4x8 times 8x4, matrix 1 is constant + S.at(0, 0) = D(X101 * F(0.906127f) + X103 * F(-0.318190f) + X105 * F(0.212608f) + X107 * F(-0.180240f)); + S.at(0, 1) = X102; + S.at(0, 2) = D(X101 * F(-0.074658f) + X103 * F(0.513280f) + X105 * F(0.768178f) + X107 * F(-0.375330f)); + S.at(0, 3) = X106; + S.at(1, 0) = D(X111 * F(0.906127f) + X113 * F(-0.318190f) + X115 * F(0.212608f) + X117 * F(-0.180240f)); + S.at(1, 1) = X112; + S.at(1, 2) = D(X111 * F(-0.074658f) + X113 * F(0.513280f) + X115 * F(0.768178f) + X117 * F(-0.375330f)); + S.at(1, 3) = X116; + S.at(2, 0) = D(X121 * F(0.906127f) + X123 * F(-0.318190f) + X125 * F(0.212608f) + X127 * F(-0.180240f)); + S.at(2, 1) = X122; + S.at(2, 2) = D(X121 * F(-0.074658f) + X123 * F(0.513280f) + X125 * F(0.768178f) + X127 * F(-0.375330f)); + S.at(2, 3) = X126; + S.at(3, 0) = D(X131 * F(0.906127f) + X133 * F(-0.318190f) + X135 * F(0.212608f) + X137 * F(-0.180240f)); + S.at(3, 1) = X132; + S.at(3, 2) = D(X131 * F(-0.074658f) + X133 * F(0.513280f) + X135 * F(0.768178f) + X137 * F(-0.375330f)); + S.at(3, 3) = X136; + // 40 muls 24 adds + } + }; +} // end namespace DCT_Upsample + +// Unconditionally frees all allocated m_blocks. +void jpeg_decoder::free_all_blocks() +{ + m_pStream = NULL; + for (mem_block *b = m_pMem_blocks; b; ) + { + mem_block *n = b->m_pNext; + jpgd_free(b); + b = n; + } + m_pMem_blocks = NULL; +} + +// This method handles all errors. It will never return. +// It could easily be changed to use C++ exceptions. +JPGD_NORETURN void jpeg_decoder::stop_decoding(jpgd_status status) +{ + m_error_code = status; + free_all_blocks(); + longjmp(m_jmp_state, status); +} + +void *jpeg_decoder::alloc(size_t nSize, bool zero) +{ + nSize = (JPGD_MAX(nSize, 1) + 3) & ~3; + char *rv = NULL; + for (mem_block *b = m_pMem_blocks; b; b = b->m_pNext) + { + if ((b->m_used_count + nSize) <= b->m_size) + { + rv = b->m_data + b->m_used_count; + b->m_used_count += nSize; + break; + } + } + if (!rv) + { + int capacity = JPGD_MAX(32768 - 256, (nSize + 2047) & ~2047); + mem_block *b = (mem_block*)jpgd_malloc(sizeof(mem_block) + capacity); + if (!b) { stop_decoding(JPGD_NOTENOUGHMEM); } + b->m_pNext = m_pMem_blocks; m_pMem_blocks = b; + b->m_used_count = nSize; + b->m_size = capacity; + rv = b->m_data; + } + if (zero) memset(rv, 0, nSize); + return rv; +} + +void jpeg_decoder::word_clear(void *p, uint16 c, uint n) +{ + uint8 *pD = (uint8*)p; + const uint8 l = c & 0xFF, h = (c >> 8) & 0xFF; + while (n) + { + pD[0] = l; pD[1] = h; pD += 2; + n--; + } +} + +// Refill the input buffer. +// This method will sit in a loop until (A) the buffer is full or (B) +// the stream's read() method reports and end of file condition. +void jpeg_decoder::prep_in_buffer() +{ + m_in_buf_left = 0; + m_pIn_buf_ofs = m_in_buf; + + if (m_eof_flag) + return; + + do + { + int bytes_read = m_pStream->read(m_in_buf + m_in_buf_left, JPGD_IN_BUF_SIZE - m_in_buf_left, &m_eof_flag); + if (bytes_read == -1) + stop_decoding(JPGD_STREAM_READ); + + m_in_buf_left += bytes_read; + } while ((m_in_buf_left < JPGD_IN_BUF_SIZE) && (!m_eof_flag)); + + m_total_bytes_read += m_in_buf_left; + + // Pad the end of the block with M_EOI (prevents the decompressor from going off the rails if the stream is invalid). + // (This dates way back to when this decompressor was written in C/asm, and the all-asm Huffman decoder did some fancy things to increase perf.) + word_clear(m_pIn_buf_ofs + m_in_buf_left, 0xD9FF, 64); +} + +// Read a Huffman code table. +void jpeg_decoder::read_dht_marker() +{ + int i, index, count; + uint8 huff_num[17]; + uint8 huff_val[256]; + + uint num_left = get_bits(16); + + if (num_left < 2) + stop_decoding(JPGD_BAD_DHT_MARKER); + + num_left -= 2; + + while (num_left) + { + index = get_bits(8); + + huff_num[0] = 0; + + count = 0; + + for (i = 1; i <= 16; i++) + { + huff_num[i] = static_cast(get_bits(8)); + count += huff_num[i]; + } + + if (count > 255) + stop_decoding(JPGD_BAD_DHT_COUNTS); + + for (i = 0; i < count; i++) + huff_val[i] = static_cast(get_bits(8)); + + i = 1 + 16 + count; + + if (num_left < (uint)i) + stop_decoding(JPGD_BAD_DHT_MARKER); + + num_left -= i; + + if ((index & 0x10) > 0x10) + stop_decoding(JPGD_BAD_DHT_INDEX); + + index = (index & 0x0F) + ((index & 0x10) >> 4) * (JPGD_MAX_HUFF_TABLES >> 1); + + if (index >= JPGD_MAX_HUFF_TABLES) + stop_decoding(JPGD_BAD_DHT_INDEX); + + if (!m_huff_num[index]) + m_huff_num[index] = (uint8 *)alloc(17); + + if (!m_huff_val[index]) + m_huff_val[index] = (uint8 *)alloc(256); + + m_huff_ac[index] = (index & 0x10) != 0; + memcpy(m_huff_num[index], huff_num, 17); + memcpy(m_huff_val[index], huff_val, 256); + } +} + +// Read a quantization table. +void jpeg_decoder::read_dqt_marker() +{ + int n, i, prec; + uint num_left; + uint temp; + + num_left = get_bits(16); + + if (num_left < 2) + stop_decoding(JPGD_BAD_DQT_MARKER); + + num_left -= 2; + + while (num_left) + { + n = get_bits(8); + prec = n >> 4; + n &= 0x0F; + + if (n >= JPGD_MAX_QUANT_TABLES) + stop_decoding(JPGD_BAD_DQT_TABLE); + + if (!m_quant[n]) + m_quant[n] = (jpgd_quant_t *)alloc(64 * sizeof(jpgd_quant_t)); + + // read quantization entries, in zag order + for (i = 0; i < 64; i++) + { + temp = get_bits(8); + + if (prec) + temp = (temp << 8) + get_bits(8); + + m_quant[n][i] = static_cast(temp); + } + + i = 64 + 1; + + if (prec) + i += 64; + + if (num_left < (uint)i) + stop_decoding(JPGD_BAD_DQT_LENGTH); + + num_left -= i; + } +} + +// Read the start of frame (SOF) marker. +void jpeg_decoder::read_sof_marker() +{ + int i; + uint num_left; + + num_left = get_bits(16); + + if (get_bits(8) != 8) /* precision: sorry, only 8-bit precision is supported right now */ + stop_decoding(JPGD_BAD_PRECISION); + + m_image_y_size = get_bits(16); + + if ((m_image_y_size < 1) || (m_image_y_size > JPGD_MAX_HEIGHT)) + stop_decoding(JPGD_BAD_HEIGHT); + + m_image_x_size = get_bits(16); + + if ((m_image_x_size < 1) || (m_image_x_size > JPGD_MAX_WIDTH)) + stop_decoding(JPGD_BAD_WIDTH); + + m_comps_in_frame = get_bits(8); + + if (m_comps_in_frame > JPGD_MAX_COMPONENTS) + stop_decoding(JPGD_TOO_MANY_COMPONENTS); + + if (num_left != (uint)(m_comps_in_frame * 3 + 8)) + stop_decoding(JPGD_BAD_SOF_LENGTH); + + for (i = 0; i < m_comps_in_frame; i++) + { + m_comp_ident[i] = get_bits(8); + m_comp_h_samp[i] = get_bits(4); + m_comp_v_samp[i] = get_bits(4); + m_comp_quant[i] = get_bits(8); + } +} + +// Used to skip unrecognized markers. +void jpeg_decoder::skip_variable_marker() +{ + uint num_left; + + num_left = get_bits(16); + + if (num_left < 2) + stop_decoding(JPGD_BAD_VARIABLE_MARKER); + + num_left -= 2; + + while (num_left) + { + get_bits(8); + num_left--; + } +} + +// Read a define restart interval (DRI) marker. +void jpeg_decoder::read_dri_marker() +{ + if (get_bits(16) != 4) + stop_decoding(JPGD_BAD_DRI_LENGTH); + + m_restart_interval = get_bits(16); +} + +// Read a start of scan (SOS) marker. +void jpeg_decoder::read_sos_marker() +{ + uint num_left; + int i, ci, n, c, cc; + + num_left = get_bits(16); + + n = get_bits(8); + + m_comps_in_scan = n; + + num_left -= 3; + + if ( (num_left != (uint)(n * 2 + 3)) || (n < 1) || (n > JPGD_MAX_COMPS_IN_SCAN) ) + stop_decoding(JPGD_BAD_SOS_LENGTH); + + for (i = 0; i < n; i++) + { + cc = get_bits(8); + c = get_bits(8); + num_left -= 2; + + for (ci = 0; ci < m_comps_in_frame; ci++) + if (cc == m_comp_ident[ci]) + break; + + if (ci >= m_comps_in_frame) + stop_decoding(JPGD_BAD_SOS_COMP_ID); + + m_comp_list[i] = ci; + m_comp_dc_tab[ci] = (c >> 4) & 15; + m_comp_ac_tab[ci] = (c & 15) + (JPGD_MAX_HUFF_TABLES >> 1); + } + + m_spectral_start = get_bits(8); + m_spectral_end = get_bits(8); + m_successive_high = get_bits(4); + m_successive_low = get_bits(4); + + if (!m_progressive_flag) + { + m_spectral_start = 0; + m_spectral_end = 63; + } + + num_left -= 3; + + while (num_left) /* read past whatever is num_left */ + { + get_bits(8); + num_left--; + } +} + +// Finds the next marker. +int jpeg_decoder::next_marker() +{ + uint c, bytes; + + bytes = 0; + + do + { + do + { + bytes++; + c = get_bits(8); + } while (c != 0xFF); + + do + { + c = get_bits(8); + } while (c == 0xFF); + + } while (c == 0); + + // If bytes > 0 here, there where extra bytes before the marker (not good). + + return c; +} + +// Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is +// encountered. +int jpeg_decoder::process_markers() +{ + int c; + + for ( ; ; ) + { + c = next_marker(); + + switch (c) + { + case M_SOF0: + case M_SOF1: + case M_SOF2: + case M_SOF3: + case M_SOF5: + case M_SOF6: + case M_SOF7: +// case M_JPG: + case M_SOF9: + case M_SOF10: + case M_SOF11: + case M_SOF13: + case M_SOF14: + case M_SOF15: + case M_SOI: + case M_EOI: + case M_SOS: + { + return c; + } + case M_DHT: + { + read_dht_marker(); + break; + } + // No arithmitic support - dumb patents! + case M_DAC: + { + stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT); + break; + } + case M_DQT: + { + read_dqt_marker(); + break; + } + case M_DRI: + { + read_dri_marker(); + break; + } + //case M_APP0: /* no need to read the JFIF marker */ + + case M_JPG: + case M_RST0: /* no parameters */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + { + stop_decoding(JPGD_UNEXPECTED_MARKER); + break; + } + default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */ + { + skip_variable_marker(); + break; + } + } + } +} + +// Finds the start of image (SOI) marker. +// This code is rather defensive: it only checks the first 512 bytes to avoid +// false positives. +void jpeg_decoder::locate_soi_marker() +{ + uint lastchar, thischar; + uint bytesleft; + + lastchar = get_bits(8); + + thischar = get_bits(8); + + /* ok if it's a normal JPEG file without a special header */ + + if ((lastchar == 0xFF) && (thischar == M_SOI)) + return; + + bytesleft = 4096; //512; + + for ( ; ; ) + { + if (--bytesleft == 0) + stop_decoding(JPGD_NOT_JPEG); + + lastchar = thischar; + + thischar = get_bits(8); + + if (lastchar == 0xFF) + { + if (thischar == M_SOI) + break; + else if (thischar == M_EOI) // get_bits will keep returning M_EOI if we read past the end + stop_decoding(JPGD_NOT_JPEG); + } + } + + // Check the next character after marker: if it's not 0xFF, it can't be the start of the next marker, so the file is bad. + thischar = (m_bit_buf >> 24) & 0xFF; + + if (thischar != 0xFF) + stop_decoding(JPGD_NOT_JPEG); +} + +// Find a start of frame (SOF) marker. +void jpeg_decoder::locate_sof_marker() +{ + locate_soi_marker(); + + int c = process_markers(); + + switch (c) + { + case M_SOF2: + m_progressive_flag = JPGD_TRUE; + case M_SOF0: /* baseline DCT */ + case M_SOF1: /* extended sequential DCT */ + { + read_sof_marker(); + break; + } + case M_SOF9: /* Arithmitic coding */ + { + stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT); + break; + } + default: + { + stop_decoding(JPGD_UNSUPPORTED_MARKER); + break; + } + } +} + +// Find a start of scan (SOS) marker. +int jpeg_decoder::locate_sos_marker() +{ + int c; + + c = process_markers(); + + if (c == M_EOI) + return JPGD_FALSE; + else if (c != M_SOS) + stop_decoding(JPGD_UNEXPECTED_MARKER); + + read_sos_marker(); + + return JPGD_TRUE; +} + +// Reset everything to default/uninitialized state. +void jpeg_decoder::init(jpeg_decoder_stream *pStream) +{ + m_pMem_blocks = NULL; + m_error_code = JPGD_SUCCESS; + m_ready_flag = false; + m_image_x_size = m_image_y_size = 0; + m_pStream = pStream; + m_progressive_flag = JPGD_FALSE; + + memset(m_huff_ac, 0, sizeof(m_huff_ac)); + memset(m_huff_num, 0, sizeof(m_huff_num)); + memset(m_huff_val, 0, sizeof(m_huff_val)); + memset(m_quant, 0, sizeof(m_quant)); + + m_scan_type = 0; + m_comps_in_frame = 0; + + memset(m_comp_h_samp, 0, sizeof(m_comp_h_samp)); + memset(m_comp_v_samp, 0, sizeof(m_comp_v_samp)); + memset(m_comp_quant, 0, sizeof(m_comp_quant)); + memset(m_comp_ident, 0, sizeof(m_comp_ident)); + memset(m_comp_h_blocks, 0, sizeof(m_comp_h_blocks)); + memset(m_comp_v_blocks, 0, sizeof(m_comp_v_blocks)); + + m_comps_in_scan = 0; + memset(m_comp_list, 0, sizeof(m_comp_list)); + memset(m_comp_dc_tab, 0, sizeof(m_comp_dc_tab)); + memset(m_comp_ac_tab, 0, sizeof(m_comp_ac_tab)); + + m_spectral_start = 0; + m_spectral_end = 0; + m_successive_low = 0; + m_successive_high = 0; + m_max_mcu_x_size = 0; + m_max_mcu_y_size = 0; + m_blocks_per_mcu = 0; + m_max_blocks_per_row = 0; + m_mcus_per_row = 0; + m_mcus_per_col = 0; + m_expanded_blocks_per_component = 0; + m_expanded_blocks_per_mcu = 0; + m_expanded_blocks_per_row = 0; + m_freq_domain_chroma_upsample = false; + + memset(m_mcu_org, 0, sizeof(m_mcu_org)); + + m_total_lines_left = 0; + m_mcu_lines_left = 0; + m_real_dest_bytes_per_scan_line = 0; + m_dest_bytes_per_scan_line = 0; + m_dest_bytes_per_pixel = 0; + + memset(m_pHuff_tabs, 0, sizeof(m_pHuff_tabs)); + + memset(m_dc_coeffs, 0, sizeof(m_dc_coeffs)); + memset(m_ac_coeffs, 0, sizeof(m_ac_coeffs)); + memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu)); + + m_eob_run = 0; + + memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu)); + + m_pIn_buf_ofs = m_in_buf; + m_in_buf_left = 0; + m_eof_flag = false; + m_tem_flag = 0; + + memset(m_in_buf_pad_start, 0, sizeof(m_in_buf_pad_start)); + memset(m_in_buf, 0, sizeof(m_in_buf)); + memset(m_in_buf_pad_end, 0, sizeof(m_in_buf_pad_end)); + + m_restart_interval = 0; + m_restarts_left = 0; + m_next_restart_num = 0; + + m_max_mcus_per_row = 0; + m_max_blocks_per_mcu = 0; + m_max_mcus_per_col = 0; + + memset(m_last_dc_val, 0, sizeof(m_last_dc_val)); + m_pMCU_coefficients = NULL; + m_pSample_buf = NULL; + + m_total_bytes_read = 0; + + m_pScan_line_0 = NULL; + m_pScan_line_1 = NULL; + + // Ready the input buffer. + prep_in_buffer(); + + // Prime the bit buffer. + m_bits_left = 16; + m_bit_buf = 0; + + get_bits(16); + get_bits(16); + + for (int i = 0; i < JPGD_MAX_BLOCKS_PER_MCU; i++) + m_mcu_block_max_zag[i] = 64; +} + +#define SCALEBITS 16 +#define ONE_HALF ((int) 1 << (SCALEBITS-1)) +#define FIX(x) ((int) ((x) * (1L<> SCALEBITS; + m_cbb[i] = ( FIX(1.77200f) * k + ONE_HALF) >> SCALEBITS; + m_crg[i] = (-FIX(0.71414f)) * k; + m_cbg[i] = (-FIX(0.34414f)) * k + ONE_HALF; + } +} + +// This method throws back into the stream any bytes that where read +// into the bit buffer during initial marker scanning. +void jpeg_decoder::fix_in_buffer() +{ + // In case any 0xFF's where pulled into the buffer during marker scanning. + JPGD_ASSERT((m_bits_left & 7) == 0); + + if (m_bits_left == 16) + stuff_char( (uint8)(m_bit_buf & 0xFF)); + + if (m_bits_left >= 8) + stuff_char( (uint8)((m_bit_buf >> 8) & 0xFF)); + + stuff_char((uint8)((m_bit_buf >> 16) & 0xFF)); + stuff_char((uint8)((m_bit_buf >> 24) & 0xFF)); + + m_bits_left = 16; + get_bits_no_markers(16); + get_bits_no_markers(16); +} + +void jpeg_decoder::transform_mcu(int mcu_row) +{ + jpgd_block_t* pSrc_ptr = m_pMCU_coefficients; + uint8* pDst_ptr = m_pSample_buf + mcu_row * m_blocks_per_mcu * 64; + + for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++) + { + idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]); + pSrc_ptr += 64; + pDst_ptr += 64; + } +} + +static const uint8 s_max_rc[64] = +{ + 17, 18, 34, 50, 50, 51, 52, 52, 52, 68, 84, 84, 84, 84, 85, 86, 86, 86, 86, 86, + 102, 118, 118, 118, 118, 118, 118, 119, 120, 120, 120, 120, 120, 120, 120, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136 +}; + +void jpeg_decoder::transform_mcu_expand(int mcu_row) +{ + jpgd_block_t* pSrc_ptr = m_pMCU_coefficients; + uint8* pDst_ptr = m_pSample_buf + mcu_row * m_expanded_blocks_per_mcu * 64; + + // Y IDCT + int mcu_block; + for (mcu_block = 0; mcu_block < m_expanded_blocks_per_component; mcu_block++) + { + idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]); + pSrc_ptr += 64; + pDst_ptr += 64; + } + + // Chroma IDCT, with upsampling + jpgd_block_t temp_block[64]; + + for (int i = 0; i < 2; i++) + { + DCT_Upsample::Matrix44 P, Q, R, S; + + JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] >= 1); + JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] <= 64); + + int max_zag = m_mcu_block_max_zag[mcu_block++] - 1; + if (max_zag <= 0) max_zag = 0; // should never happen, only here to shut up static analysis + switch (s_max_rc[max_zag]) + { + case 1*16+1: + DCT_Upsample::P_Q<1, 1>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<1, 1>::calc(R, S, pSrc_ptr); + break; + case 1*16+2: + DCT_Upsample::P_Q<1, 2>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<1, 2>::calc(R, S, pSrc_ptr); + break; + case 2*16+2: + DCT_Upsample::P_Q<2, 2>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<2, 2>::calc(R, S, pSrc_ptr); + break; + case 3*16+2: + DCT_Upsample::P_Q<3, 2>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<3, 2>::calc(R, S, pSrc_ptr); + break; + case 3*16+3: + DCT_Upsample::P_Q<3, 3>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<3, 3>::calc(R, S, pSrc_ptr); + break; + case 3*16+4: + DCT_Upsample::P_Q<3, 4>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<3, 4>::calc(R, S, pSrc_ptr); + break; + case 4*16+4: + DCT_Upsample::P_Q<4, 4>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<4, 4>::calc(R, S, pSrc_ptr); + break; + case 5*16+4: + DCT_Upsample::P_Q<5, 4>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<5, 4>::calc(R, S, pSrc_ptr); + break; + case 5*16+5: + DCT_Upsample::P_Q<5, 5>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<5, 5>::calc(R, S, pSrc_ptr); + break; + case 5*16+6: + DCT_Upsample::P_Q<5, 6>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<5, 6>::calc(R, S, pSrc_ptr); + break; + case 6*16+6: + DCT_Upsample::P_Q<6, 6>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<6, 6>::calc(R, S, pSrc_ptr); + break; + case 7*16+6: + DCT_Upsample::P_Q<7, 6>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<7, 6>::calc(R, S, pSrc_ptr); + break; + case 7*16+7: + DCT_Upsample::P_Q<7, 7>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<7, 7>::calc(R, S, pSrc_ptr); + break; + case 7*16+8: + DCT_Upsample::P_Q<7, 8>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<7, 8>::calc(R, S, pSrc_ptr); + break; + case 8*16+8: + DCT_Upsample::P_Q<8, 8>::calc(P, Q, pSrc_ptr); + DCT_Upsample::R_S<8, 8>::calc(R, S, pSrc_ptr); + break; + default: + JPGD_ASSERT(false); + } + + DCT_Upsample::Matrix44 a(P + Q); P -= Q; + DCT_Upsample::Matrix44& b = P; + DCT_Upsample::Matrix44 c(R + S); R -= S; + DCT_Upsample::Matrix44& d = R; + + DCT_Upsample::Matrix44::add_and_store(temp_block, a, c); + idct_4x4(temp_block, pDst_ptr); + pDst_ptr += 64; + + DCT_Upsample::Matrix44::sub_and_store(temp_block, a, c); + idct_4x4(temp_block, pDst_ptr); + pDst_ptr += 64; + + DCT_Upsample::Matrix44::add_and_store(temp_block, b, d); + idct_4x4(temp_block, pDst_ptr); + pDst_ptr += 64; + + DCT_Upsample::Matrix44::sub_and_store(temp_block, b, d); + idct_4x4(temp_block, pDst_ptr); + pDst_ptr += 64; + + pSrc_ptr += 64; + } +} + +// Loads and dequantizes the next row of (already decoded) coefficients. +// Progressive images only. +void jpeg_decoder::load_next_row() +{ + int i; + jpgd_block_t *p; + jpgd_quant_t *q; + int mcu_row, mcu_block, row_block = 0; + int component_num, component_id; + int block_x_mcu[JPGD_MAX_COMPONENTS]; + + memset(block_x_mcu, 0, JPGD_MAX_COMPONENTS * sizeof(int)); + + for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++) + { + int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0; + + for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++) + { + component_id = m_mcu_org[mcu_block]; + q = m_quant[m_comp_quant[component_id]]; + + p = m_pMCU_coefficients + 64 * mcu_block; + + jpgd_block_t* pAC = coeff_buf_getp(m_ac_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs); + jpgd_block_t* pDC = coeff_buf_getp(m_dc_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs); + p[0] = pDC[0]; + memcpy(&p[1], &pAC[1], 63 * sizeof(jpgd_block_t)); + + for (i = 63; i > 0; i--) + if (p[g_ZAG[i]]) + break; + + m_mcu_block_max_zag[mcu_block] = i + 1; + + for ( ; i >= 0; i--) + if (p[g_ZAG[i]]) + p[g_ZAG[i]] = static_cast(p[g_ZAG[i]] * q[i]); + + row_block++; + + if (m_comps_in_scan == 1) + block_x_mcu[component_id]++; + else + { + if (++block_x_mcu_ofs == m_comp_h_samp[component_id]) + { + block_x_mcu_ofs = 0; + + if (++block_y_mcu_ofs == m_comp_v_samp[component_id]) + { + block_y_mcu_ofs = 0; + + block_x_mcu[component_id] += m_comp_h_samp[component_id]; + } + } + } + } + + if (m_freq_domain_chroma_upsample) + transform_mcu_expand(mcu_row); + else + transform_mcu(mcu_row); + } + + if (m_comps_in_scan == 1) + m_block_y_mcu[m_comp_list[0]]++; + else + { + for (component_num = 0; component_num < m_comps_in_scan; component_num++) + { + component_id = m_comp_list[component_num]; + + m_block_y_mcu[component_id] += m_comp_v_samp[component_id]; + } + } +} + +// Restart interval processing. +void jpeg_decoder::process_restart() +{ + int i; + int c = 0; + + // Align to a byte boundry + // FIXME: Is this really necessary? get_bits_no_markers() never reads in markers! + //get_bits_no_markers(m_bits_left & 7); + + // Let's scan a little bit to find the marker, but not _too_ far. + // 1536 is a "fudge factor" that determines how much to scan. + for (i = 1536; i > 0; i--) + if (get_char() == 0xFF) + break; + + if (i == 0) + stop_decoding(JPGD_BAD_RESTART_MARKER); + + for ( ; i > 0; i--) + if ((c = get_char()) != 0xFF) + break; + + if (i == 0) + stop_decoding(JPGD_BAD_RESTART_MARKER); + + // Is it the expected marker? If not, something bad happened. + if (c != (m_next_restart_num + M_RST0)) + stop_decoding(JPGD_BAD_RESTART_MARKER); + + // Reset each component's DC prediction values. + memset(&m_last_dc_val, 0, m_comps_in_frame * sizeof(uint)); + + m_eob_run = 0; + + m_restarts_left = m_restart_interval; + + m_next_restart_num = (m_next_restart_num + 1) & 7; + + // Get the bit buffer going again... + + m_bits_left = 16; + get_bits_no_markers(16); + get_bits_no_markers(16); +} + +static inline int dequantize_ac(int c, int q) { c *= q; return c; } + +// Decodes and dequantizes the next row of coefficients. +void jpeg_decoder::decode_next_row() +{ + int row_block = 0; + + for (int mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++) + { + if ((m_restart_interval) && (m_restarts_left == 0)) + process_restart(); + + jpgd_block_t* p = m_pMCU_coefficients; + for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++, p += 64) + { + int component_id = m_mcu_org[mcu_block]; + jpgd_quant_t* q = m_quant[m_comp_quant[component_id]]; + + int r, s; + s = huff_decode(m_pHuff_tabs[m_comp_dc_tab[component_id]], r); + s = JPGD_HUFF_EXTEND(r, s); + + m_last_dc_val[component_id] = (s += m_last_dc_val[component_id]); + + p[0] = static_cast(s * q[0]); + + int prev_num_set = m_mcu_block_max_zag[mcu_block]; + + huff_tables *pH = m_pHuff_tabs[m_comp_ac_tab[component_id]]; + + int k; + for (k = 1; k < 64; k++) + { + int extra_bits; + s = huff_decode(pH, extra_bits); + + r = s >> 4; + s &= 15; + + if (s) + { + if (r) + { + if ((k + r) > 63) + stop_decoding(JPGD_DECODE_ERROR); + + if (k < prev_num_set) + { + int n = JPGD_MIN(r, prev_num_set - k); + int kt = k; + while (n--) + p[g_ZAG[kt++]] = 0; + } + + k += r; + } + + s = JPGD_HUFF_EXTEND(extra_bits, s); + + JPGD_ASSERT(k < 64); + + p[g_ZAG[k]] = static_cast(dequantize_ac(s, q[k])); //s * q[k]; + } + else + { + if (r == 15) + { + if ((k + 16) > 64) + stop_decoding(JPGD_DECODE_ERROR); + + if (k < prev_num_set) + { + int n = JPGD_MIN(16, prev_num_set - k); + int kt = k; + while (n--) + { + JPGD_ASSERT(kt <= 63); + p[g_ZAG[kt++]] = 0; + } + } + + k += 16 - 1; // - 1 because the loop counter is k + JPGD_ASSERT(p[g_ZAG[k]] == 0); + } + else + break; + } + } + + if (k < prev_num_set) + { + int kt = k; + while (kt < prev_num_set) + p[g_ZAG[kt++]] = 0; + } + + m_mcu_block_max_zag[mcu_block] = k; + + row_block++; + } + + if (m_freq_domain_chroma_upsample) + transform_mcu_expand(mcu_row); + else + transform_mcu(mcu_row); + + m_restarts_left--; + } +} + +// YCbCr H1V1 (1x1:1:1, 3 m_blocks per MCU) to RGB +void jpeg_decoder::H1V1Convert() +{ + int row = m_max_mcu_y_size - m_mcu_lines_left; + uint8 *d = m_pScan_line_0; + uint8 *s = m_pSample_buf + row * 8; + + for (int i = m_max_mcus_per_row; i > 0; i--) + { + for (int j = 0; j < 8; j++) + { + int y = s[j]; + int cb = s[64+j]; + int cr = s[128+j]; + + d[0] = clamp(y + m_crr[cr]); + d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16)); + d[2] = clamp(y + m_cbb[cb]); + d[3] = 255; + + d += 4; + } + + s += 64*3; + } +} + +// YCbCr H2V1 (2x1:1:1, 4 m_blocks per MCU) to RGB +void jpeg_decoder::H2V1Convert() +{ + int row = m_max_mcu_y_size - m_mcu_lines_left; + uint8 *d0 = m_pScan_line_0; + uint8 *y = m_pSample_buf + row * 8; + uint8 *c = m_pSample_buf + 2*64 + row * 8; + + for (int i = m_max_mcus_per_row; i > 0; i--) + { + for (int l = 0; l < 2; l++) + { + for (int j = 0; j < 4; j++) + { + int cb = c[0]; + int cr = c[64]; + + int rc = m_crr[cr]; + int gc = ((m_crg[cr] + m_cbg[cb]) >> 16); + int bc = m_cbb[cb]; + + int yy = y[j<<1]; + d0[0] = clamp(yy+rc); + d0[1] = clamp(yy+gc); + d0[2] = clamp(yy+bc); + d0[3] = 255; + + yy = y[(j<<1)+1]; + d0[4] = clamp(yy+rc); + d0[5] = clamp(yy+gc); + d0[6] = clamp(yy+bc); + d0[7] = 255; + + d0 += 8; + + c++; + } + y += 64; + } + + y += 64*4 - 64*2; + c += 64*4 - 8; + } +} + +// YCbCr H2V1 (1x2:1:1, 4 m_blocks per MCU) to RGB +void jpeg_decoder::H1V2Convert() +{ + int row = m_max_mcu_y_size - m_mcu_lines_left; + uint8 *d0 = m_pScan_line_0; + uint8 *d1 = m_pScan_line_1; + uint8 *y; + uint8 *c; + + if (row < 8) + y = m_pSample_buf + row * 8; + else + y = m_pSample_buf + 64*1 + (row & 7) * 8; + + c = m_pSample_buf + 64*2 + (row >> 1) * 8; + + for (int i = m_max_mcus_per_row; i > 0; i--) + { + for (int j = 0; j < 8; j++) + { + int cb = c[0+j]; + int cr = c[64+j]; + + int rc = m_crr[cr]; + int gc = ((m_crg[cr] + m_cbg[cb]) >> 16); + int bc = m_cbb[cb]; + + int yy = y[j]; + d0[0] = clamp(yy+rc); + d0[1] = clamp(yy+gc); + d0[2] = clamp(yy+bc); + d0[3] = 255; + + yy = y[8+j]; + d1[0] = clamp(yy+rc); + d1[1] = clamp(yy+gc); + d1[2] = clamp(yy+bc); + d1[3] = 255; + + d0 += 4; + d1 += 4; + } + + y += 64*4; + c += 64*4; + } +} + +// YCbCr H2V2 (2x2:1:1, 6 m_blocks per MCU) to RGB +void jpeg_decoder::H2V2Convert() +{ + int row = m_max_mcu_y_size - m_mcu_lines_left; + uint8 *d0 = m_pScan_line_0; + uint8 *d1 = m_pScan_line_1; + uint8 *y; + uint8 *c; + + if (row < 8) + y = m_pSample_buf + row * 8; + else + y = m_pSample_buf + 64*2 + (row & 7) * 8; + + c = m_pSample_buf + 64*4 + (row >> 1) * 8; + + for (int i = m_max_mcus_per_row; i > 0; i--) + { + for (int l = 0; l < 2; l++) + { + for (int j = 0; j < 8; j += 2) + { + int cb = c[0]; + int cr = c[64]; + + int rc = m_crr[cr]; + int gc = ((m_crg[cr] + m_cbg[cb]) >> 16); + int bc = m_cbb[cb]; + + int yy = y[j]; + d0[0] = clamp(yy+rc); + d0[1] = clamp(yy+gc); + d0[2] = clamp(yy+bc); + d0[3] = 255; + + yy = y[j+1]; + d0[4] = clamp(yy+rc); + d0[5] = clamp(yy+gc); + d0[6] = clamp(yy+bc); + d0[7] = 255; + + yy = y[j+8]; + d1[0] = clamp(yy+rc); + d1[1] = clamp(yy+gc); + d1[2] = clamp(yy+bc); + d1[3] = 255; + + yy = y[j+8+1]; + d1[4] = clamp(yy+rc); + d1[5] = clamp(yy+gc); + d1[6] = clamp(yy+bc); + d1[7] = 255; + + d0 += 8; + d1 += 8; + + c++; + } + y += 64; + } + + y += 64*6 - 64*2; + c += 64*6 - 8; + } +} + +// Y (1 block per MCU) to 8-bit grayscale +void jpeg_decoder::gray_convert() +{ + int row = m_max_mcu_y_size - m_mcu_lines_left; + uint8 *d = m_pScan_line_0; + uint8 *s = m_pSample_buf + row * 8; + + for (int i = m_max_mcus_per_row; i > 0; i--) + { + *(uint *)d = *(uint *)s; + *(uint *)(&d[4]) = *(uint *)(&s[4]); + + s += 64; + d += 8; + } +} + +void jpeg_decoder::expanded_convert() +{ + int row = m_max_mcu_y_size - m_mcu_lines_left; + + uint8* Py = m_pSample_buf + (row / 8) * 64 * m_comp_h_samp[0] + (row & 7) * 8; + + uint8* d = m_pScan_line_0; + + for (int i = m_max_mcus_per_row; i > 0; i--) + { + for (int k = 0; k < m_max_mcu_x_size; k += 8) + { + const int Y_ofs = k * 8; + const int Cb_ofs = Y_ofs + 64 * m_expanded_blocks_per_component; + const int Cr_ofs = Y_ofs + 64 * m_expanded_blocks_per_component * 2; + for (int j = 0; j < 8; j++) + { + int y = Py[Y_ofs + j]; + int cb = Py[Cb_ofs + j]; + int cr = Py[Cr_ofs + j]; + + d[0] = clamp(y + m_crr[cr]); + d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16)); + d[2] = clamp(y + m_cbb[cb]); + d[3] = 255; + + d += 4; + } + } + + Py += 64 * m_expanded_blocks_per_mcu; + } +} + +// Find end of image (EOI) marker, so we can return to the user the exact size of the input stream. +void jpeg_decoder::find_eoi() +{ + if (!m_progressive_flag) + { + // Attempt to read the EOI marker. + //get_bits_no_markers(m_bits_left & 7); + + // Prime the bit buffer + m_bits_left = 16; + get_bits(16); + get_bits(16); + + // The next marker _should_ be EOI + process_markers(); + } + + m_total_bytes_read -= m_in_buf_left; +} + +int jpeg_decoder::decode(const void** pScan_line, uint* pScan_line_len) +{ + if ((m_error_code) || (!m_ready_flag)) + return JPGD_FAILED; + + if (m_total_lines_left == 0) + return JPGD_DONE; + + if (m_mcu_lines_left == 0) + { + if (setjmp(m_jmp_state)) + return JPGD_FAILED; + + if (m_progressive_flag) + load_next_row(); + else + decode_next_row(); + + // Find the EOI marker if that was the last row. + if (m_total_lines_left <= m_max_mcu_y_size) + find_eoi(); + + m_mcu_lines_left = m_max_mcu_y_size; + } + + if (m_freq_domain_chroma_upsample) + { + expanded_convert(); + *pScan_line = m_pScan_line_0; + } + else + { + switch (m_scan_type) + { + case JPGD_YH2V2: + { + if ((m_mcu_lines_left & 1) == 0) + { + H2V2Convert(); + *pScan_line = m_pScan_line_0; + } + else + *pScan_line = m_pScan_line_1; + + break; + } + case JPGD_YH2V1: + { + H2V1Convert(); + *pScan_line = m_pScan_line_0; + break; + } + case JPGD_YH1V2: + { + if ((m_mcu_lines_left & 1) == 0) + { + H1V2Convert(); + *pScan_line = m_pScan_line_0; + } + else + *pScan_line = m_pScan_line_1; + + break; + } + case JPGD_YH1V1: + { + H1V1Convert(); + *pScan_line = m_pScan_line_0; + break; + } + case JPGD_GRAYSCALE: + { + gray_convert(); + *pScan_line = m_pScan_line_0; + + break; + } + } + } + + *pScan_line_len = m_real_dest_bytes_per_scan_line; + + m_mcu_lines_left--; + m_total_lines_left--; + + return JPGD_SUCCESS; +} + +// Creates the tables needed for efficient Huffman decoding. +void jpeg_decoder::make_huff_table(int index, huff_tables *pH) +{ + int p, i, l, si; + uint8 huffsize[257]; + uint huffcode[257]; + uint code; + uint subtree; + int code_size; + int lastp; + int nextfreeentry; + int currententry; + + pH->ac_table = m_huff_ac[index] != 0; + + p = 0; + + for (l = 1; l <= 16; l++) + { + for (i = 1; i <= m_huff_num[index][l]; i++) + huffsize[p++] = static_cast(l); + } + + huffsize[p] = 0; + + lastp = p; + + code = 0; + si = huffsize[0]; + p = 0; + + while (huffsize[p]) + { + while (huffsize[p] == si) + { + huffcode[p++] = code; + code++; + } + + code <<= 1; + si++; + } + + memset(pH->look_up, 0, sizeof(pH->look_up)); + memset(pH->look_up2, 0, sizeof(pH->look_up2)); + memset(pH->tree, 0, sizeof(pH->tree)); + memset(pH->code_size, 0, sizeof(pH->code_size)); + + nextfreeentry = -1; + + p = 0; + + while (p < lastp) + { + i = m_huff_val[index][p]; + code = huffcode[p]; + code_size = huffsize[p]; + + pH->code_size[i] = static_cast(code_size); + + if (code_size <= 8) + { + code <<= (8 - code_size); + + for (l = 1 << (8 - code_size); l > 0; l--) + { + JPGD_ASSERT(i < 256); + + pH->look_up[code] = i; + + bool has_extrabits = false; + int extra_bits = 0; + int num_extra_bits = i & 15; + + int bits_to_fetch = code_size; + if (num_extra_bits) + { + int total_codesize = code_size + num_extra_bits; + if (total_codesize <= 8) + { + has_extrabits = true; + extra_bits = ((1 << num_extra_bits) - 1) & (code >> (8 - total_codesize)); + JPGD_ASSERT(extra_bits <= 0x7FFF); + bits_to_fetch += num_extra_bits; + } + } + + if (!has_extrabits) + pH->look_up2[code] = i | (bits_to_fetch << 8); + else + pH->look_up2[code] = i | 0x8000 | (extra_bits << 16) | (bits_to_fetch << 8); + + code++; + } + } + else + { + subtree = (code >> (code_size - 8)) & 0xFF; + + currententry = pH->look_up[subtree]; + + if (currententry == 0) + { + pH->look_up[subtree] = currententry = nextfreeentry; + pH->look_up2[subtree] = currententry = nextfreeentry; + + nextfreeentry -= 2; + } + + code <<= (16 - (code_size - 8)); + + for (l = code_size; l > 9; l--) + { + if ((code & 0x8000) == 0) + currententry--; + + if (pH->tree[-currententry - 1] == 0) + { + pH->tree[-currententry - 1] = nextfreeentry; + + currententry = nextfreeentry; + + nextfreeentry -= 2; + } + else + currententry = pH->tree[-currententry - 1]; + + code <<= 1; + } + + if ((code & 0x8000) == 0) + currententry--; + + pH->tree[-currententry - 1] = i; + } + + p++; + } +} + +// Verifies the quantization tables needed for this scan are available. +void jpeg_decoder::check_quant_tables() +{ + for (int i = 0; i < m_comps_in_scan; i++) + if (m_quant[m_comp_quant[m_comp_list[i]]] == NULL) + stop_decoding(JPGD_UNDEFINED_QUANT_TABLE); +} + +// Verifies that all the Huffman tables needed for this scan are available. +void jpeg_decoder::check_huff_tables() +{ + for (int i = 0; i < m_comps_in_scan; i++) + { + if ((m_spectral_start == 0) && (m_huff_num[m_comp_dc_tab[m_comp_list[i]]] == NULL)) + stop_decoding(JPGD_UNDEFINED_HUFF_TABLE); + + if ((m_spectral_end > 0) && (m_huff_num[m_comp_ac_tab[m_comp_list[i]]] == NULL)) + stop_decoding(JPGD_UNDEFINED_HUFF_TABLE); + } + + for (int i = 0; i < JPGD_MAX_HUFF_TABLES; i++) + if (m_huff_num[i]) + { + if (!m_pHuff_tabs[i]) + m_pHuff_tabs[i] = (huff_tables *)alloc(sizeof(huff_tables)); + + make_huff_table(i, m_pHuff_tabs[i]); + } +} + +// Determines the component order inside each MCU. +// Also calcs how many MCU's are on each row, etc. +void jpeg_decoder::calc_mcu_block_order() +{ + int component_num, component_id; + int max_h_samp = 0, max_v_samp = 0; + + for (component_id = 0; component_id < m_comps_in_frame; component_id++) + { + if (m_comp_h_samp[component_id] > max_h_samp) + max_h_samp = m_comp_h_samp[component_id]; + + if (m_comp_v_samp[component_id] > max_v_samp) + max_v_samp = m_comp_v_samp[component_id]; + } + + for (component_id = 0; component_id < m_comps_in_frame; component_id++) + { + m_comp_h_blocks[component_id] = ((((m_image_x_size * m_comp_h_samp[component_id]) + (max_h_samp - 1)) / max_h_samp) + 7) / 8; + m_comp_v_blocks[component_id] = ((((m_image_y_size * m_comp_v_samp[component_id]) + (max_v_samp - 1)) / max_v_samp) + 7) / 8; + } + + if (m_comps_in_scan == 1) + { + m_mcus_per_row = m_comp_h_blocks[m_comp_list[0]]; + m_mcus_per_col = m_comp_v_blocks[m_comp_list[0]]; + } + else + { + m_mcus_per_row = (((m_image_x_size + 7) / 8) + (max_h_samp - 1)) / max_h_samp; + m_mcus_per_col = (((m_image_y_size + 7) / 8) + (max_v_samp - 1)) / max_v_samp; + } + + if (m_comps_in_scan == 1) + { + m_mcu_org[0] = m_comp_list[0]; + + m_blocks_per_mcu = 1; + } + else + { + m_blocks_per_mcu = 0; + + for (component_num = 0; component_num < m_comps_in_scan; component_num++) + { + int num_blocks; + + component_id = m_comp_list[component_num]; + + num_blocks = m_comp_h_samp[component_id] * m_comp_v_samp[component_id]; + + while (num_blocks--) + m_mcu_org[m_blocks_per_mcu++] = component_id; + } + } +} + +// Starts a new scan. +int jpeg_decoder::init_scan() +{ + if (!locate_sos_marker()) + return JPGD_FALSE; + + calc_mcu_block_order(); + + check_huff_tables(); + + check_quant_tables(); + + memset(m_last_dc_val, 0, m_comps_in_frame * sizeof(uint)); + + m_eob_run = 0; + + if (m_restart_interval) + { + m_restarts_left = m_restart_interval; + m_next_restart_num = 0; + } + + fix_in_buffer(); + + return JPGD_TRUE; +} + +// Starts a frame. Determines if the number of components or sampling factors +// are supported. +void jpeg_decoder::init_frame() +{ + int i; + + if (m_comps_in_frame == 1) + { + if ((m_comp_h_samp[0] != 1) || (m_comp_v_samp[0] != 1)) + stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); + + m_scan_type = JPGD_GRAYSCALE; + m_max_blocks_per_mcu = 1; + m_max_mcu_x_size = 8; + m_max_mcu_y_size = 8; + } + else if (m_comps_in_frame == 3) + { + if ( ((m_comp_h_samp[1] != 1) || (m_comp_v_samp[1] != 1)) || + ((m_comp_h_samp[2] != 1) || (m_comp_v_samp[2] != 1)) ) + stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); + + if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1)) + { + m_scan_type = JPGD_YH1V1; + + m_max_blocks_per_mcu = 3; + m_max_mcu_x_size = 8; + m_max_mcu_y_size = 8; + } + else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1)) + { + m_scan_type = JPGD_YH2V1; + m_max_blocks_per_mcu = 4; + m_max_mcu_x_size = 16; + m_max_mcu_y_size = 8; + } + else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 2)) + { + m_scan_type = JPGD_YH1V2; + m_max_blocks_per_mcu = 4; + m_max_mcu_x_size = 8; + m_max_mcu_y_size = 16; + } + else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2)) + { + m_scan_type = JPGD_YH2V2; + m_max_blocks_per_mcu = 6; + m_max_mcu_x_size = 16; + m_max_mcu_y_size = 16; + } + else + stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); + } + else + stop_decoding(JPGD_UNSUPPORTED_COLORSPACE); + + m_max_mcus_per_row = (m_image_x_size + (m_max_mcu_x_size - 1)) / m_max_mcu_x_size; + m_max_mcus_per_col = (m_image_y_size + (m_max_mcu_y_size - 1)) / m_max_mcu_y_size; + + // These values are for the *destination* pixels: after conversion. + if (m_scan_type == JPGD_GRAYSCALE) + m_dest_bytes_per_pixel = 1; + else + m_dest_bytes_per_pixel = 4; + + m_dest_bytes_per_scan_line = ((m_image_x_size + 15) & 0xFFF0) * m_dest_bytes_per_pixel; + + m_real_dest_bytes_per_scan_line = (m_image_x_size * m_dest_bytes_per_pixel); + + // Initialize two scan line buffers. + m_pScan_line_0 = (uint8 *)alloc(m_dest_bytes_per_scan_line, true); + if ((m_scan_type == JPGD_YH1V2) || (m_scan_type == JPGD_YH2V2)) + m_pScan_line_1 = (uint8 *)alloc(m_dest_bytes_per_scan_line, true); + + m_max_blocks_per_row = m_max_mcus_per_row * m_max_blocks_per_mcu; + + // Should never happen + if (m_max_blocks_per_row > JPGD_MAX_BLOCKS_PER_ROW) + stop_decoding(JPGD_ASSERTION_ERROR); + + // Allocate the coefficient buffer, enough for one MCU + m_pMCU_coefficients = (jpgd_block_t*)alloc(m_max_blocks_per_mcu * 64 * sizeof(jpgd_block_t)); + + for (i = 0; i < m_max_blocks_per_mcu; i++) + m_mcu_block_max_zag[i] = 64; + + m_expanded_blocks_per_component = m_comp_h_samp[0] * m_comp_v_samp[0]; + m_expanded_blocks_per_mcu = m_expanded_blocks_per_component * m_comps_in_frame; + m_expanded_blocks_per_row = m_max_mcus_per_row * m_expanded_blocks_per_mcu; + // Freq. domain chroma upsampling is only supported for H2V2 subsampling factor (the most common one I've seen). + m_freq_domain_chroma_upsample = false; +#if JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING + m_freq_domain_chroma_upsample = (m_expanded_blocks_per_mcu == 4*3); +#endif + + if (m_freq_domain_chroma_upsample) + m_pSample_buf = (uint8 *)alloc(m_expanded_blocks_per_row * 64); + else + m_pSample_buf = (uint8 *)alloc(m_max_blocks_per_row * 64); + + m_total_lines_left = m_image_y_size; + + m_mcu_lines_left = 0; + + create_look_ups(); +} + +// The coeff_buf series of methods originally stored the coefficients +// into a "virtual" file which was located in EMS, XMS, or a disk file. A cache +// was used to make this process more efficient. Now, we can store the entire +// thing in RAM. +jpeg_decoder::coeff_buf* jpeg_decoder::coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y) +{ + coeff_buf* cb = (coeff_buf*)alloc(sizeof(coeff_buf)); + + cb->block_num_x = block_num_x; + cb->block_num_y = block_num_y; + cb->block_len_x = block_len_x; + cb->block_len_y = block_len_y; + cb->block_size = (block_len_x * block_len_y) * sizeof(jpgd_block_t); + cb->pData = (uint8 *)alloc(cb->block_size * block_num_x * block_num_y, true); + return cb; +} + +inline jpgd_block_t *jpeg_decoder::coeff_buf_getp(coeff_buf *cb, int block_x, int block_y) +{ + JPGD_ASSERT((block_x < cb->block_num_x) && (block_y < cb->block_num_y)); + return (jpgd_block_t *)(cb->pData + block_x * cb->block_size + block_y * (cb->block_size * cb->block_num_x)); +} + +// The following methods decode the various types of m_blocks encountered +// in progressively encoded images. +void jpeg_decoder::decode_block_dc_first(jpeg_decoder *pD, int component_id, int block_x, int block_y) +{ + int s, r; + jpgd_block_t *p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y); + + if ((s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_dc_tab[component_id]])) != 0) + { + r = pD->get_bits_no_markers(s); + s = JPGD_HUFF_EXTEND(r, s); + } + + pD->m_last_dc_val[component_id] = (s += pD->m_last_dc_val[component_id]); + + p[0] = static_cast(s << pD->m_successive_low); +} + +void jpeg_decoder::decode_block_dc_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y) +{ + if (pD->get_bits_no_markers(1)) + { + jpgd_block_t *p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y); + + p[0] |= (1 << pD->m_successive_low); + } +} + +void jpeg_decoder::decode_block_ac_first(jpeg_decoder *pD, int component_id, int block_x, int block_y) +{ + int k, s, r; + + if (pD->m_eob_run) + { + pD->m_eob_run--; + return; + } + + jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y); + + for (k = pD->m_spectral_start; k <= pD->m_spectral_end; k++) + { + s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]); + + r = s >> 4; + s &= 15; + + if (s) + { + if ((k += r) > 63) + pD->stop_decoding(JPGD_DECODE_ERROR); + + r = pD->get_bits_no_markers(s); + s = JPGD_HUFF_EXTEND(r, s); + + p[g_ZAG[k]] = static_cast(s << pD->m_successive_low); + } + else + { + if (r == 15) + { + if ((k += 15) > 63) + pD->stop_decoding(JPGD_DECODE_ERROR); + } + else + { + pD->m_eob_run = 1 << r; + + if (r) + pD->m_eob_run += pD->get_bits_no_markers(r); + + pD->m_eob_run--; + + break; + } + } + } +} + +void jpeg_decoder::decode_block_ac_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y) +{ + int s, k, r; + int p1 = 1 << pD->m_successive_low; + int m1 = (-1) << pD->m_successive_low; + jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y); + + JPGD_ASSERT(pD->m_spectral_end <= 63); + + k = pD->m_spectral_start; + + if (pD->m_eob_run == 0) + { + for ( ; k <= pD->m_spectral_end; k++) + { + s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]); + + r = s >> 4; + s &= 15; + + if (s) + { + if (s != 1) + pD->stop_decoding(JPGD_DECODE_ERROR); + + if (pD->get_bits_no_markers(1)) + s = p1; + else + s = m1; + } + else + { + if (r != 15) + { + pD->m_eob_run = 1 << r; + + if (r) + pD->m_eob_run += pD->get_bits_no_markers(r); + + break; + } + } + + do + { + jpgd_block_t *this_coef = p + g_ZAG[k & 63]; + + if (*this_coef != 0) + { + if (pD->get_bits_no_markers(1)) + { + if ((*this_coef & p1) == 0) + { + if (*this_coef >= 0) + *this_coef = static_cast(*this_coef + p1); + else + *this_coef = static_cast(*this_coef + m1); + } + } + } + else + { + if (--r < 0) + break; + } + + k++; + + } while (k <= pD->m_spectral_end); + + if ((s) && (k < 64)) + { + p[g_ZAG[k]] = static_cast(s); + } + } + } + + if (pD->m_eob_run > 0) + { + for ( ; k <= pD->m_spectral_end; k++) + { + jpgd_block_t *this_coef = p + g_ZAG[k & 63]; // logical AND to shut up static code analysis + + if (*this_coef != 0) + { + if (pD->get_bits_no_markers(1)) + { + if ((*this_coef & p1) == 0) + { + if (*this_coef >= 0) + *this_coef = static_cast(*this_coef + p1); + else + *this_coef = static_cast(*this_coef + m1); + } + } + } + } + + pD->m_eob_run--; + } +} + +// Decode a scan in a progressively encoded image. +void jpeg_decoder::decode_scan(pDecode_block_func decode_block_func) +{ + int mcu_row, mcu_col, mcu_block; + int block_x_mcu[JPGD_MAX_COMPONENTS], m_block_y_mcu[JPGD_MAX_COMPONENTS]; + + memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu)); + + for (mcu_col = 0; mcu_col < m_mcus_per_col; mcu_col++) + { + int component_num, component_id; + + memset(block_x_mcu, 0, sizeof(block_x_mcu)); + + for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++) + { + int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0; + + if ((m_restart_interval) && (m_restarts_left == 0)) + process_restart(); + + for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++) + { + component_id = m_mcu_org[mcu_block]; + + decode_block_func(this, component_id, block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs); + + if (m_comps_in_scan == 1) + block_x_mcu[component_id]++; + else + { + if (++block_x_mcu_ofs == m_comp_h_samp[component_id]) + { + block_x_mcu_ofs = 0; + + if (++block_y_mcu_ofs == m_comp_v_samp[component_id]) + { + block_y_mcu_ofs = 0; + block_x_mcu[component_id] += m_comp_h_samp[component_id]; + } + } + } + } + + m_restarts_left--; + } + + if (m_comps_in_scan == 1) + m_block_y_mcu[m_comp_list[0]]++; + else + { + for (component_num = 0; component_num < m_comps_in_scan; component_num++) + { + component_id = m_comp_list[component_num]; + m_block_y_mcu[component_id] += m_comp_v_samp[component_id]; + } + } + } +} + +// Decode a progressively encoded image. +void jpeg_decoder::init_progressive() +{ + int i; + + if (m_comps_in_frame == 4) + stop_decoding(JPGD_UNSUPPORTED_COLORSPACE); + + // Allocate the coefficient buffers. + for (i = 0; i < m_comps_in_frame; i++) + { + m_dc_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 1, 1); + m_ac_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 8, 8); + } + + for ( ; ; ) + { + int dc_only_scan, refinement_scan; + pDecode_block_func decode_block_func; + + if (!init_scan()) + break; + + dc_only_scan = (m_spectral_start == 0); + refinement_scan = (m_successive_high != 0); + + if ((m_spectral_start > m_spectral_end) || (m_spectral_end > 63)) + stop_decoding(JPGD_BAD_SOS_SPECTRAL); + + if (dc_only_scan) + { + if (m_spectral_end) + stop_decoding(JPGD_BAD_SOS_SPECTRAL); + } + else if (m_comps_in_scan != 1) /* AC scans can only contain one component */ + stop_decoding(JPGD_BAD_SOS_SPECTRAL); + + if ((refinement_scan) && (m_successive_low != m_successive_high - 1)) + stop_decoding(JPGD_BAD_SOS_SUCCESSIVE); + + if (dc_only_scan) + { + if (refinement_scan) + decode_block_func = decode_block_dc_refine; + else + decode_block_func = decode_block_dc_first; + } + else + { + if (refinement_scan) + decode_block_func = decode_block_ac_refine; + else + decode_block_func = decode_block_ac_first; + } + + decode_scan(decode_block_func); + + m_bits_left = 16; + get_bits(16); + get_bits(16); + } + + m_comps_in_scan = m_comps_in_frame; + + for (i = 0; i < m_comps_in_frame; i++) + m_comp_list[i] = i; + + calc_mcu_block_order(); +} + +void jpeg_decoder::init_sequential() +{ + if (!init_scan()) + stop_decoding(JPGD_UNEXPECTED_MARKER); +} + +void jpeg_decoder::decode_start() +{ + init_frame(); + + if (m_progressive_flag) + init_progressive(); + else + init_sequential(); +} + +void jpeg_decoder::decode_init(jpeg_decoder_stream *pStream) +{ + init(pStream); + locate_sof_marker(); +} + +jpeg_decoder::jpeg_decoder(jpeg_decoder_stream *pStream) +{ + if (setjmp(m_jmp_state)) + return; + decode_init(pStream); +} + +int jpeg_decoder::begin_decoding() +{ + if (m_ready_flag) + return JPGD_SUCCESS; + + if (m_error_code) + return JPGD_FAILED; + + if (setjmp(m_jmp_state)) + return JPGD_FAILED; + + decode_start(); + + m_ready_flag = true; + + return JPGD_SUCCESS; +} + +jpeg_decoder::~jpeg_decoder() +{ + free_all_blocks(); +} + +jpeg_decoder_file_stream::jpeg_decoder_file_stream() +{ + m_pFile = NULL; + m_eof_flag = false; + m_error_flag = false; +} + +void jpeg_decoder_file_stream::close() +{ + if (m_pFile) + { + fclose(m_pFile); + m_pFile = NULL; + } + + m_eof_flag = false; + m_error_flag = false; +} + +jpeg_decoder_file_stream::~jpeg_decoder_file_stream() +{ + close(); +} + +bool jpeg_decoder_file_stream::open(const char *Pfilename) +{ + close(); + + m_eof_flag = false; + m_error_flag = false; + +#if defined(_MSC_VER) + m_pFile = NULL; + fopen_s(&m_pFile, Pfilename, "rb"); +#else + m_pFile = fopen(Pfilename, "rb"); +#endif + return m_pFile != NULL; +} + +int jpeg_decoder_file_stream::read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag) +{ + if (!m_pFile) + return -1; + + if (m_eof_flag) + { + *pEOF_flag = true; + return 0; + } + + if (m_error_flag) + return -1; + + int bytes_read = static_cast(fread(pBuf, 1, max_bytes_to_read, m_pFile)); + if (bytes_read < max_bytes_to_read) + { + if (ferror(m_pFile)) + { + m_error_flag = true; + return -1; + } + + m_eof_flag = true; + *pEOF_flag = true; + } + + return bytes_read; +} + +bool jpeg_decoder_mem_stream::open(const uint8 *pSrc_data, uint size) +{ + close(); + m_pSrc_data = pSrc_data; + m_ofs = 0; + m_size = size; + return true; +} + +int jpeg_decoder_mem_stream::read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag) +{ + *pEOF_flag = false; + + if (!m_pSrc_data) + return -1; + + uint bytes_remaining = m_size - m_ofs; + if ((uint)max_bytes_to_read > bytes_remaining) + { + max_bytes_to_read = bytes_remaining; + *pEOF_flag = true; + } + + memcpy(pBuf, m_pSrc_data + m_ofs, max_bytes_to_read); + m_ofs += max_bytes_to_read; + + return max_bytes_to_read; +} + +unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps) +{ + if (!actual_comps) + return NULL; + *actual_comps = 0; + + if ((!pStream) || (!width) || (!height) || (!req_comps)) + return NULL; + + if ((req_comps != 1) && (req_comps != 3) && (req_comps != 4)) + return NULL; + + jpeg_decoder decoder(pStream); + if (decoder.get_error_code() != JPGD_SUCCESS) + return NULL; + + const int image_width = decoder.get_width(), image_height = decoder.get_height(); + *width = image_width; + *height = image_height; + *actual_comps = decoder.get_num_components(); + + if (decoder.begin_decoding() != JPGD_SUCCESS) + return NULL; + + const int dst_bpl = image_width * req_comps; + + uint8 *pImage_data = (uint8*)jpgd_malloc(dst_bpl * image_height); + if (!pImage_data) + return NULL; + + for (int y = 0; y < image_height; y++) + { + const uint8* pScan_line; + uint scan_line_len; + if (decoder.decode((const void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS) + { + jpgd_free(pImage_data); + return NULL; + } + + uint8 *pDst = pImage_data + y * dst_bpl; + + if (((req_comps == 1) && (decoder.get_num_components() == 1)) || ((req_comps == 4) && (decoder.get_num_components() == 3))) + memcpy(pDst, pScan_line, dst_bpl); + else if (decoder.get_num_components() == 1) + { + if (req_comps == 3) + { + for (int x = 0; x < image_width; x++) + { + uint8 luma = pScan_line[x]; + pDst[0] = luma; + pDst[1] = luma; + pDst[2] = luma; + pDst += 3; + } + } + else + { + for (int x = 0; x < image_width; x++) + { + uint8 luma = pScan_line[x]; + pDst[0] = luma; + pDst[1] = luma; + pDst[2] = luma; + pDst[3] = 255; + pDst += 4; + } + } + } + else if (decoder.get_num_components() == 3) + { + if (req_comps == 1) + { + const int YR = 19595, YG = 38470, YB = 7471; + for (int x = 0; x < image_width; x++) + { + int r = pScan_line[x*4+0]; + int g = pScan_line[x*4+1]; + int b = pScan_line[x*4+2]; + *pDst++ = static_cast((r * YR + g * YG + b * YB + 32768) >> 16); + } + } + else + { + for (int x = 0; x < image_width; x++) + { + pDst[0] = pScan_line[x*4+0]; + pDst[1] = pScan_line[x*4+1]; + pDst[2] = pScan_line[x*4+2]; + pDst += 3; + } + } + } + } + + return pImage_data; +} + +unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps) +{ + jpgd::jpeg_decoder_mem_stream mem_stream(pSrc_data, src_data_size); + return decompress_jpeg_image_from_stream(&mem_stream, width, height, actual_comps, req_comps); +} + +unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps) +{ + jpgd::jpeg_decoder_file_stream file_stream; + if (!file_stream.open(pSrc_filename)) + return NULL; + return decompress_jpeg_image_from_stream(&file_stream, width, height, actual_comps, req_comps); +} + +} // namespace jpgd \ No newline at end of file diff --git a/ext/jpge/jpgd.h b/ext/jpge/jpgd.h new file mode 100644 index 0000000000..150b9a0b26 --- /dev/null +++ b/ext/jpge/jpgd.h @@ -0,0 +1,319 @@ +// jpgd.h - C++ class for JPEG decompression. +// Public domain, Rich Geldreich +#ifndef JPEG_DECODER_H +#define JPEG_DECODER_H + +#include +#include +#include + +#ifdef _MSC_VER + #define JPGD_NORETURN __declspec(noreturn) +#elif defined(__GNUC__) + #define JPGD_NORETURN __attribute__ ((noreturn)) +#else + #define JPGD_NORETURN +#endif + +namespace jpgd +{ + typedef unsigned char uint8; + typedef signed short int16; + typedef unsigned short uint16; + typedef unsigned int uint; + typedef signed int int32; + + // Loads a JPEG image from a memory buffer or a file. + // req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA). + // On return, width/height will be set to the image's dimensions, and actual_comps will be set to the either 1 (grayscale) or 3 (RGB). + // Notes: For more control over where and how the source data is read, see the decompress_jpeg_image_from_stream() function below, or call the jpeg_decoder class directly. + // Requesting a 8 or 32bpp image is currently a little faster than 24bpp because the jpeg_decoder class itself currently always unpacks to either 8 or 32bpp. + unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps); + unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps); + + // Success/failure error codes. + enum jpgd_status + { + JPGD_SUCCESS = 0, JPGD_FAILED = -1, JPGD_DONE = 1, + JPGD_BAD_DHT_COUNTS = -256, JPGD_BAD_DHT_INDEX, JPGD_BAD_DHT_MARKER, JPGD_BAD_DQT_MARKER, JPGD_BAD_DQT_TABLE, + JPGD_BAD_PRECISION, JPGD_BAD_HEIGHT, JPGD_BAD_WIDTH, JPGD_TOO_MANY_COMPONENTS, + JPGD_BAD_SOF_LENGTH, JPGD_BAD_VARIABLE_MARKER, JPGD_BAD_DRI_LENGTH, JPGD_BAD_SOS_LENGTH, + JPGD_BAD_SOS_COMP_ID, JPGD_W_EXTRA_BYTES_BEFORE_MARKER, JPGD_NO_ARITHMITIC_SUPPORT, JPGD_UNEXPECTED_MARKER, + JPGD_NOT_JPEG, JPGD_UNSUPPORTED_MARKER, JPGD_BAD_DQT_LENGTH, JPGD_TOO_MANY_BLOCKS, + JPGD_UNDEFINED_QUANT_TABLE, JPGD_UNDEFINED_HUFF_TABLE, JPGD_NOT_SINGLE_SCAN, JPGD_UNSUPPORTED_COLORSPACE, + JPGD_UNSUPPORTED_SAMP_FACTORS, JPGD_DECODE_ERROR, JPGD_BAD_RESTART_MARKER, JPGD_ASSERTION_ERROR, + JPGD_BAD_SOS_SPECTRAL, JPGD_BAD_SOS_SUCCESSIVE, JPGD_STREAM_READ, JPGD_NOTENOUGHMEM + }; + + // Input stream interface. + // Derive from this class to read input data from sources other than files or memory. Set m_eof_flag to true when no more data is available. + // The decoder is rather greedy: it will keep on calling this method until its internal input buffer is full, or until the EOF flag is set. + // It the input stream contains data after the JPEG stream's EOI (end of image) marker it will probably be pulled into the internal buffer. + // Call the get_total_bytes_read() method to determine the actual size of the JPEG stream after successful decoding. + class jpeg_decoder_stream + { + public: + jpeg_decoder_stream() { } + virtual ~jpeg_decoder_stream() { } + + // The read() method is called when the internal input buffer is empty. + // Parameters: + // pBuf - input buffer + // max_bytes_to_read - maximum bytes that can be written to pBuf + // pEOF_flag - set this to true if at end of stream (no more bytes remaining) + // Returns -1 on error, otherwise return the number of bytes actually written to the buffer (which may be 0). + // Notes: This method will be called in a loop until you set *pEOF_flag to true or the internal buffer is full. + virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag) = 0; + }; + + // stdio FILE stream class. + class jpeg_decoder_file_stream : public jpeg_decoder_stream + { + jpeg_decoder_file_stream(const jpeg_decoder_file_stream &); + jpeg_decoder_file_stream &operator =(const jpeg_decoder_file_stream &); + + FILE *m_pFile; + bool m_eof_flag, m_error_flag; + + public: + jpeg_decoder_file_stream(); + virtual ~jpeg_decoder_file_stream(); + + bool open(const char *Pfilename); + void close(); + + virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag); + }; + + // Memory stream class. + class jpeg_decoder_mem_stream : public jpeg_decoder_stream + { + const uint8 *m_pSrc_data; + uint m_ofs, m_size; + + public: + jpeg_decoder_mem_stream() : m_pSrc_data(NULL), m_ofs(0), m_size(0) { } + jpeg_decoder_mem_stream(const uint8 *pSrc_data, uint size) : m_pSrc_data(pSrc_data), m_ofs(0), m_size(size) { } + + virtual ~jpeg_decoder_mem_stream() { } + + bool open(const uint8 *pSrc_data, uint size); + void close() { m_pSrc_data = NULL; m_ofs = 0; m_size = 0; } + + virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag); + }; + + // Loads JPEG file from a jpeg_decoder_stream. + unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps); + + enum + { + JPGD_IN_BUF_SIZE = 8192, JPGD_MAX_BLOCKS_PER_MCU = 10, JPGD_MAX_HUFF_TABLES = 8, JPGD_MAX_QUANT_TABLES = 4, + JPGD_MAX_COMPONENTS = 4, JPGD_MAX_COMPS_IN_SCAN = 4, JPGD_MAX_BLOCKS_PER_ROW = 8192, JPGD_MAX_HEIGHT = 16384, JPGD_MAX_WIDTH = 16384 + }; + + typedef int16 jpgd_quant_t; + typedef int16 jpgd_block_t; + + class jpeg_decoder + { + public: + // Call get_error_code() after constructing to determine if the stream is valid or not. You may call the get_width(), get_height(), etc. + // methods after the constructor is called. You may then either destruct the object, or begin decoding the image by calling begin_decoding(), then decode() on each scanline. + jpeg_decoder(jpeg_decoder_stream *pStream); + + ~jpeg_decoder(); + + // Call this method after constructing the object to begin decompression. + // If JPGD_SUCCESS is returned you may then call decode() on each scanline. + int begin_decoding(); + + // Returns the next scan line. + // For grayscale images, pScan_line will point to a buffer containing 8-bit pixels (get_bytes_per_pixel() will return 1). + // Otherwise, it will always point to a buffer containing 32-bit RGBA pixels (A will always be 255, and get_bytes_per_pixel() will return 4). + // Returns JPGD_SUCCESS if a scan line has been returned. + // Returns JPGD_DONE if all scan lines have been returned. + // Returns JPGD_FAILED if an error occurred. Call get_error_code() for a more info. + int decode(const void** pScan_line, uint* pScan_line_len); + + inline jpgd_status get_error_code() const { return m_error_code; } + + inline int get_width() const { return m_image_x_size; } + inline int get_height() const { return m_image_y_size; } + + inline int get_num_components() const { return m_comps_in_frame; } + + inline int get_bytes_per_pixel() const { return m_dest_bytes_per_pixel; } + inline int get_bytes_per_scan_line() const { return m_image_x_size * get_bytes_per_pixel(); } + + // Returns the total number of bytes actually consumed by the decoder (which should equal the actual size of the JPEG file). + inline int get_total_bytes_read() const { return m_total_bytes_read; } + + private: + jpeg_decoder(const jpeg_decoder &); + jpeg_decoder &operator =(const jpeg_decoder &); + + typedef void (*pDecode_block_func)(jpeg_decoder *, int, int, int); + + struct huff_tables + { + bool ac_table; + uint look_up[256]; + uint look_up2[256]; + uint8 code_size[256]; + uint tree[512]; + }; + + struct coeff_buf + { + uint8 *pData; + int block_num_x, block_num_y; + int block_len_x, block_len_y; + int block_size; + }; + + struct mem_block + { + mem_block *m_pNext; + size_t m_used_count; + size_t m_size; + char m_data[1]; + }; + + jmp_buf m_jmp_state; + mem_block *m_pMem_blocks; + int m_image_x_size; + int m_image_y_size; + jpeg_decoder_stream *m_pStream; + int m_progressive_flag; + uint8 m_huff_ac[JPGD_MAX_HUFF_TABLES]; + uint8* m_huff_num[JPGD_MAX_HUFF_TABLES]; // pointer to number of Huffman codes per bit size + uint8* m_huff_val[JPGD_MAX_HUFF_TABLES]; // pointer to Huffman codes per bit size + jpgd_quant_t* m_quant[JPGD_MAX_QUANT_TABLES]; // pointer to quantization tables + int m_scan_type; // Gray, Yh1v1, Yh1v2, Yh2v1, Yh2v2 (CMYK111, CMYK4114 no longer supported) + int m_comps_in_frame; // # of components in frame + int m_comp_h_samp[JPGD_MAX_COMPONENTS]; // component's horizontal sampling factor + int m_comp_v_samp[JPGD_MAX_COMPONENTS]; // component's vertical sampling factor + int m_comp_quant[JPGD_MAX_COMPONENTS]; // component's quantization table selector + int m_comp_ident[JPGD_MAX_COMPONENTS]; // component's ID + int m_comp_h_blocks[JPGD_MAX_COMPONENTS]; + int m_comp_v_blocks[JPGD_MAX_COMPONENTS]; + int m_comps_in_scan; // # of components in scan + int m_comp_list[JPGD_MAX_COMPS_IN_SCAN]; // components in this scan + int m_comp_dc_tab[JPGD_MAX_COMPONENTS]; // component's DC Huffman coding table selector + int m_comp_ac_tab[JPGD_MAX_COMPONENTS]; // component's AC Huffman coding table selector + int m_spectral_start; // spectral selection start + int m_spectral_end; // spectral selection end + int m_successive_low; // successive approximation low + int m_successive_high; // successive approximation high + int m_max_mcu_x_size; // MCU's max. X size in pixels + int m_max_mcu_y_size; // MCU's max. Y size in pixels + int m_blocks_per_mcu; + int m_max_blocks_per_row; + int m_mcus_per_row, m_mcus_per_col; + int m_mcu_org[JPGD_MAX_BLOCKS_PER_MCU]; + int m_total_lines_left; // total # lines left in image + int m_mcu_lines_left; // total # lines left in this MCU + int m_real_dest_bytes_per_scan_line; + int m_dest_bytes_per_scan_line; // rounded up + int m_dest_bytes_per_pixel; // 4 (RGB) or 1 (Y) + huff_tables* m_pHuff_tabs[JPGD_MAX_HUFF_TABLES]; + coeff_buf* m_dc_coeffs[JPGD_MAX_COMPONENTS]; + coeff_buf* m_ac_coeffs[JPGD_MAX_COMPONENTS]; + int m_eob_run; + int m_block_y_mcu[JPGD_MAX_COMPONENTS]; + uint8* m_pIn_buf_ofs; + int m_in_buf_left; + int m_tem_flag; + bool m_eof_flag; + uint8 m_in_buf_pad_start[128]; + uint8 m_in_buf[JPGD_IN_BUF_SIZE + 128]; + uint8 m_in_buf_pad_end[128]; + int m_bits_left; + uint m_bit_buf; + int m_restart_interval; + int m_restarts_left; + int m_next_restart_num; + int m_max_mcus_per_row; + int m_max_blocks_per_mcu; + int m_expanded_blocks_per_mcu; + int m_expanded_blocks_per_row; + int m_expanded_blocks_per_component; + bool m_freq_domain_chroma_upsample; + int m_max_mcus_per_col; + uint m_last_dc_val[JPGD_MAX_COMPONENTS]; + jpgd_block_t* m_pMCU_coefficients; + int m_mcu_block_max_zag[JPGD_MAX_BLOCKS_PER_MCU]; + uint8* m_pSample_buf; + int m_crr[256]; + int m_cbb[256]; + int m_crg[256]; + int m_cbg[256]; + uint8* m_pScan_line_0; + uint8* m_pScan_line_1; + jpgd_status m_error_code; + bool m_ready_flag; + int m_total_bytes_read; + + void free_all_blocks(); + JPGD_NORETURN void stop_decoding(jpgd_status status); + void *alloc(size_t n, bool zero = false); + void word_clear(void *p, uint16 c, uint n); + void prep_in_buffer(); + void read_dht_marker(); + void read_dqt_marker(); + void read_sof_marker(); + void skip_variable_marker(); + void read_dri_marker(); + void read_sos_marker(); + int next_marker(); + int process_markers(); + void locate_soi_marker(); + void locate_sof_marker(); + int locate_sos_marker(); + void init(jpeg_decoder_stream * pStream); + void create_look_ups(); + void fix_in_buffer(); + void transform_mcu(int mcu_row); + void transform_mcu_expand(int mcu_row); + coeff_buf* coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y); + inline jpgd_block_t *coeff_buf_getp(coeff_buf *cb, int block_x, int block_y); + void load_next_row(); + void decode_next_row(); + void make_huff_table(int index, huff_tables *pH); + void check_quant_tables(); + void check_huff_tables(); + void calc_mcu_block_order(); + int init_scan(); + void init_frame(); + void process_restart(); + void decode_scan(pDecode_block_func decode_block_func); + void init_progressive(); + void init_sequential(); + void decode_start(); + void decode_init(jpeg_decoder_stream * pStream); + void H2V2Convert(); + void H2V1Convert(); + void H1V2Convert(); + void H1V1Convert(); + void gray_convert(); + void expanded_convert(); + void find_eoi(); + inline uint get_char(); + inline uint get_char(bool *pPadding_flag); + inline void stuff_char(uint8 q); + inline uint8 get_octet(); + inline uint get_bits(int num_bits); + inline uint get_bits_no_markers(int numbits); + inline int huff_decode(huff_tables *pH); + inline int huff_decode(huff_tables *pH, int& extrabits); + static inline uint8 clamp(int i); + static void decode_block_dc_first(jpeg_decoder *pD, int component_id, int block_x, int block_y); + static void decode_block_dc_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y); + static void decode_block_ac_first(jpeg_decoder *pD, int component_id, int block_x, int block_y); + static void decode_block_ac_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y); + }; + +} // namespace jpgd + +#endif // JPEG_DECODER_H diff --git a/native.vcxproj b/native.vcxproj index e859bb83ae..3980989fea 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -198,6 +198,7 @@ + @@ -323,6 +324,7 @@ Default Default + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index a1c4a273eb..dabb7db32e 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -277,6 +277,7 @@ math + @@ -495,6 +496,7 @@ input + From 4736b26fc3d55fd1aaa2c86a13fafe94b82e4e6e Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 5 Jul 2013 14:51:33 +1000 Subject: [PATCH 0494/1445] Blackberry buildfix: Include should not occur inside namespace. --- ext/jpge/jpge.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/jpge/jpge.cpp b/ext/jpge/jpge.cpp index c82d73ff06..b095f16a9f 100644 --- a/ext/jpge/jpge.cpp +++ b/ext/jpge/jpge.cpp @@ -13,6 +13,8 @@ #include #include #include +// Higher level wrappers/examples (optional). +#include #define JPGE_MAX(a,b) (((a)>(b))?(a):(b)) #define JPGE_MIN(a,b) (((a)<(b))?(a):(b)) @@ -895,9 +897,6 @@ bool jpeg_encoder::process_scanline(const void* pScanline) return m_all_stream_writes_succeeded; } -// Higher level wrappers/examples (optional). -#include - class cfile_stream : public output_stream { cfile_stream(const cfile_stream &); From a8277742ad3b9257dd6d49a4115adec18a915e69 Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 5 Jul 2013 19:31:28 +1000 Subject: [PATCH 0495/1445] Buildfix for Symbian and OSX --- ext/jpge/jpge.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/jpge/jpge.cpp b/ext/jpge/jpge.cpp index b095f16a9f..556985927e 100644 --- a/ext/jpge/jpge.cpp +++ b/ext/jpge/jpge.cpp @@ -12,7 +12,9 @@ #include #include +#if !defined(__SYMBIAN32__) && !defined(__MAC_10_6) #include +#endif // Higher level wrappers/examples (optional). #include From 594c1f769546610a80d9854a0611782abbabdef2 Mon Sep 17 00:00:00 2001 From: Kingcom Date: Fri, 5 Jul 2013 20:23:33 +0200 Subject: [PATCH 0496/1445] Added [x,y] operator to expression parser --- math/expression_parser.cpp | 126 ++++++++++++++++++++++++++++--------- math/expression_parser.h | 1 + 2 files changed, 98 insertions(+), 29 deletions(-) diff --git a/math/expression_parser.cpp b/math/expression_parser.cpp index 97fc86786b..505d1160c7 100644 --- a/math/expression_parser.cpp +++ b/math/expression_parser.cpp @@ -4,11 +4,11 @@ #include typedef enum { - EXOP_BRACKETL, EXOP_BRACKETR, EXOP_SIGNPLUS, EXOP_SIGNMINUS, + EXOP_BRACKETL, EXOP_BRACKETR, EXOP_MEML, EXOP_MEMR, EXOP_MEMSIZE, EXOP_SIGNPLUS, EXOP_SIGNMINUS, EXOP_BITNOT, EXOP_LOGNOT, EXOP_MUL, EXOP_DIV, EXOP_MOD, EXOP_ADD, EXOP_SUB, EXOP_SHL, EXOP_SHR, EXOP_GREATEREQUAL, EXOP_GREATER, EXOP_LOWEREQUAL, EXOP_LOWER, EXOP_EQUAL, EXOP_NOTEQUAL, EXOP_BITAND, EXOP_XOR, EXOP_BITOR, EXOP_LOGAND, - EXOP_LOGOR, EXOP_TERTIF, EXOP_TERTELSE, EXOP_NUMBER, EXOP_NONE, EXOP_COUNT + EXOP_LOGOR, EXOP_TERTIF, EXOP_TERTELSE, EXOP_NUMBER, EXOP_MEM, EXOP_NONE, EXOP_COUNT } ExpressionOpcodeType; typedef enum { EXCOMM_CONST, EXCOMM_REF, EXCOMM_OP } ExpressionCommand; @@ -24,33 +24,37 @@ typedef struct { } ExpressionOpcode; const ExpressionOpcode ExpressionOpcodes[] = { - { "(", 15, 1, 0, false }, // EXOP_BRACKETL - { ")", 15, 1, 0, false }, // EXOP_BRACKETR - { "+", 12, 1, 1, true }, // EXOP_SIGNPLUS - { "-", 12, 1, 1, true }, // EXOP_SIGNMINUS - { "~", 12, 1, 1, false }, // EXOP_BITNOT - { "!", 12, 1, 1, false }, // EXOP_LOGNOT - { "*", 11, 1, 2, false }, // EXOP_MUL - { "/", 11, 1, 2, false }, // EXOP_DIV - { "%", 11, 1, 2, false }, // EXOP_MOD - { "+", 10, 1, 2, false }, // EXOP_ADD - { "-", 10, 1, 2, false }, // EXOP_SUB - { "<<", 9, 2, 2, false }, // EXOP_SHL - { ">>", 9, 2, 2, false }, // EXOP_SHR - { ">=", 8, 2, 2, false }, // EXOP_GREATEREQUAL - { ">", 8, 1, 2, false }, // EXOP_GREATER - { "<=", 8, 2, 2, false }, // EXOP_LOWEREQUAL - { "<", 8, 1, 2, false }, // EXOP_LOWER - { "==", 7, 2, 2, false }, // EXOP_EQUAL - { "!=", 7, 2, 2, false }, // EXOP_NOTEQUAL - { "&", 6, 1, 2, false }, // EXOP_BITAND - { "^", 5, 1, 2, false }, // EXOP_XOR - { "|", 4, 1, 2, false }, // EXOP_BITOR - { "&&", 3, 2, 2, false }, // EXOP_LOGAND - { "||", 2, 2, 2, false }, // EXOP_LOGOR - { "?", 0, 1, 0, false }, // EXOP_TERTIF - { ":", 1, 1, 3, false }, // EXOP_TERTELSE + { "(", 25, 1, 0, false }, // EXOP_BRACKETL + { ")", 25, 1, 0, false }, // EXOP_BRACKETR + { "[", 4, 1, 0, false }, // EXOP_MEML + { "]", 4, 1, 0, false }, // EXOP_MEMR + { ",", 5, 1, 2, false }, // EXOP_MEMSIZE + { "+", 22, 1, 1, true }, // EXOP_SIGNPLUS + { "-", 22, 1, 1, true }, // EXOP_SIGNMINUS + { "~", 22, 1, 1, false }, // EXOP_BITNOT + { "!", 22, 1, 1, false }, // EXOP_LOGNOT + { "*", 21, 1, 2, false }, // EXOP_MUL + { "/", 21, 1, 2, false }, // EXOP_DIV + { "%", 21, 1, 2, false }, // EXOP_MOD + { "+", 20, 1, 2, false }, // EXOP_ADD + { "-", 20, 1, 2, false }, // EXOP_SUB + { "<<", 19, 2, 2, false }, // EXOP_SHL + { ">>", 19, 2, 2, false }, // EXOP_SHR + { ">=", 18, 2, 2, false }, // EXOP_GREATEREQUAL + { ">", 18, 1, 2, false }, // EXOP_GREATER + { "<=", 18, 2, 2, false }, // EXOP_LOWEREQUAL + { "<", 18, 1, 2, false }, // EXOP_LOWER + { "==", 17, 2, 2, false }, // EXOP_EQUAL + { "!=", 17, 2, 2, false }, // EXOP_NOTEQUAL + { "&", 16, 1, 2, false }, // EXOP_BITAND + { "^", 15, 1, 2, false }, // EXOP_XOR + { "|", 14, 1, 2, false }, // EXOP_BITOR + { "&&", 13, 2, 2, false }, // EXOP_LOGAND + { "||", 12, 2, 2, false }, // EXOP_LOGOR + { "?", 10, 1, 0, false }, // EXOP_TERTIF + { ":", 11, 1, 3, false }, // EXOP_TERTELSE { "", 0, 0, 0, false }, // EXOP_NUMBER + { "[]", 0, 0, 1, false }, // EXOP_MEM { "", 0, 0, 0, false } // EXOP_NONE }; @@ -257,6 +261,7 @@ bool initPostfixExpression(char* infix, IExpressionFunctions* funcs, PostfixExpr switch (type) { case EXOP_BRACKETL: + case EXOP_MEML: opcodeStack.push_back(type); break; case EXOP_BRACKETR: @@ -273,6 +278,25 @@ bool initPostfixExpression(char* infix, IExpressionFunctions* funcs, PostfixExpr dest.push_back(ExpressionPair(EXCOMM_OP,t)); } break; + case EXOP_MEMR: + while (true) + { + if (opcodeStack.empty()) + { + sprintf(expressionError,"Closing bracket without opening one"); + return false; + } + ExpressionOpcodeType t = opcodeStack[opcodeStack.size()-1]; + opcodeStack.pop_back(); + if (t == EXOP_MEML) + { + dest.push_back(ExpressionPair(EXCOMM_OP,EXOP_MEM)); + break; + } + dest.push_back(ExpressionPair(EXCOMM_OP,t)); + } + type = EXOP_NUMBER; + break; default: if (opcodeStack.empty() == false) { @@ -282,7 +306,7 @@ bool initPostfixExpression(char* infix, IExpressionFunctions* funcs, PostfixExpr ExpressionOpcodeType t = opcodeStack[opcodeStack.size()-1]; opcodeStack.pop_back(); - if (t == EXOP_BRACKETL) + if (t == EXOP_BRACKETL || t == EXOP_MEML) { opcodeStack.push_back(t); break; @@ -318,6 +342,26 @@ bool initPostfixExpression(char* infix, IExpressionFunctions* funcs, PostfixExpr dest.push_back(ExpressionPair(EXCOMM_OP,t)); } +#if 0 // only for testing + char test[1024]; + int testPos = 0; + for (int i = 0; i < dest.size(); i++) + { + switch (dest[i].first) + { + case EXCOMM_CONST: + testPos += sprintf(&test[testPos],"0x%04X ",dest[i].second); + break; + case EXCOMM_REF: + testPos += sprintf(&test[testPos],"r%d ",dest[i].second); + break; + case EXCOMM_OP: + testPos += sprintf(&test[testPos],"%s ",ExpressionOpcodes[dest[i].second].Name); + break; + }; + } +#endif + return true; } @@ -354,6 +398,30 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, switch (opcode) { + case EXOP_MEMSIZE: // must be followed by EXOP_MEM + if (exp[num++].second != EXOP_MEM) + { + sprintf(expressionError,"Invalid memsize operator"); + return false; + } + + uint32 val; + if(funcs->getMemoryValue(arg[1],arg[0],val,expressionError) == false) + { + return false; + } + valueStack.push_back(val); + break; + case EXOP_MEM: + { + uint32 val; + if (funcs->getMemoryValue(arg[0],4,val,expressionError) == false) + { + return false; + } + valueStack.push_back(val); + } + break; case EXOP_SIGNPLUS: // keine aktion nötig break; case EXOP_SIGNMINUS: // -0 diff --git a/math/expression_parser.h b/math/expression_parser.h index 0f42ba98e6..7d1f8e67da 100644 --- a/math/expression_parser.h +++ b/math/expression_parser.h @@ -12,6 +12,7 @@ public: virtual bool parseReference(char* str, uint32& referenceIndex) = 0; virtual bool parseSymbol(char* str, uint32& symbolValue) = 0; virtual uint32 getReferenceValue(uint32 referenceIndex) = 0; + virtual bool getMemoryValue(uint32 address, int size, uint32& dest, char* error) = 0; }; bool initPostfixExpression(char* infix, IExpressionFunctions* funcs, PostfixExpression& dest); From e9a261ea9dd34e077560dae152aa94539a1b14d7 Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Fri, 5 Jul 2013 21:30:25 +0200 Subject: [PATCH 0497/1445] Fix path for jpgd.cpp for Android --- Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index 03f39c302f..357c260272 100644 --- a/Android.mk +++ b/Android.mk @@ -19,7 +19,7 @@ LOCAL_SRC_FILES :=\ data/compression.cpp \ ext/rg_etc1/rg_etc1.cpp \ ext/cityhash/city.cpp \ - ext/jpgd/jpgd.cpp \ + ext/jpge/jpgd.cpp \ ext/jpge/jpge.cpp \ ext/sha1/sha1.cpp \ ext/stb_image/stb_image.c \ From f4578129effa92bc6dc9b2240249ae8fb996c793 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 6 Jul 2013 11:27:06 +0200 Subject: [PATCH 0498/1445] Darken on-screen back/home/taskswitch buttons on Android devices that have them --- .../libnative/NativeActivity.java | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 5dc8ab583e..a47fd9838d 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -34,6 +34,7 @@ import android.view.Gravity; import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.EditText; @@ -191,7 +192,10 @@ public class NativeActivity extends Activity { setContentView(mGLSurfaceView); if (!useOpenSL) audioPlayer = new NativeAudioPlayer(); - lightsOut(); + + if (Build.VERSION.SDK_INT >= 14) { + darkenOnScreenButtons(); + } /* editText = new EditText(this); @@ -201,12 +205,11 @@ public class NativeActivity extends Activity { */ // inputBox("Please ener a s", "", "Save"); // Toast.makeText(this, "Value: " + input.getText().toString(), Toast.LENGTH_LONG).show(); - } - - public void lightsOut() { - if (Build.VERSION.SDK_INT >= 11) { - // mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); - } + } + + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + public void darkenOnScreenButtons() { + mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); } private boolean detectOpenGLES20() { @@ -214,7 +217,6 @@ public class NativeActivity extends Activity { ConfigurationInfo info = am.getDeviceConfigurationInfo(); return info.reqGlEsVersion >= 0x20000; } - @Override protected void onPause() { @@ -230,16 +232,19 @@ public class NativeActivity extends Activity { Log.i(TAG, "onPause returning"); } - @Override - protected void onResume() { - super.onResume(); - Log.i(TAG, "onResume"); - mGLSurfaceView.onResume(); - if (audioPlayer != null) { - audioPlayer.play(); - } - NativeApp.resume(); - } + @Override + protected void onResume() { + super.onResume(); + Log.i(TAG, "onResume"); + mGLSurfaceView.onResume(); + if (audioPlayer != null) { + audioPlayer.play(); + } + NativeApp.resume(); + if (Build.VERSION.SDK_INT >= 14) { + darkenOnScreenButtons(); + } + } @Override protected void onStop() { From 1dec6e8154610699e99a479a01e26ed03ea044df Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 6 Jul 2013 19:07:48 +0200 Subject: [PATCH 0499/1445] Work towards full android joystick support. --- android/app-android.cpp | 105 +++++++--- android/app-android.h | 30 --- .../libnative/InputDeviceState.java | 103 ++++++++++ .../libnative/NativeActivity.java | 187 +++++++++++++----- .../henrikrydgard/libnative/NativeApp.java | 10 +- base/NativeApp.h | 4 + base/PCMain.cpp | 17 +- input/input_state.cpp | 100 +--------- input/input_state.h | 49 +++-- input/keycodes.h | 36 +++- native.vcxproj | 1 + native.vcxproj.filters | 1 + ui/screen.cpp | 15 +- ui/screen.h | 4 + 14 files changed, 431 insertions(+), 231 deletions(-) create mode 100644 android/src/com/henrikrydgard/libnative/InputDeviceState.java diff --git a/android/app-android.cpp b/android/app-android.cpp index 9f1cbbf048..c1ad471908 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -39,7 +39,8 @@ static float left_joystick_x_async; static float left_joystick_y_async; static float right_joystick_x_async; static float right_joystick_y_async; -static int key_queue_async[MAX_KEYQUEUESIZE]; +static float hat_joystick_x_async; +static float hat_joystick_y_async; static uint32_t pad_buttons_down; @@ -117,10 +118,11 @@ extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isLandscape(JNIEn // For the Back button to work right. extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isAtTopLevel(JNIEnv *env, jclass) { + bool isAtTop = NativeIsAtTopLevel(); if (extraLog) { - ILOG("isAtTopLevel"); + ILOG("isAtTopLevel %i", (int)isAtTop); } - return NativeIsAtTopLevel(); + return isAtTop; } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioConfig @@ -148,8 +150,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init left_joystick_y_async = 0; right_joystick_x_async = 0; right_joystick_y_async = 0; - - KeyQueueBlank(key_queue_async); + hat_joystick_x_async = 0; + hat_joystick_y_async = 0; std::string apkPath = GetJavaString(env, japkpath); ILOG("NativeApp::Init: APK path: %s", apkPath.c_str()); @@ -262,8 +264,9 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN lock_guard guard(input_state.lock); pad_buttons_down |= pad_buttons_async_set; pad_buttons_down &= ~pad_buttons_async_clear; + input_state.pad_buttons = pad_buttons_down; - KeyQueueCopyQueue(key_queue_async, input_state.key_queue); + UpdateInputState(&input_state); } @@ -271,6 +274,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN lock_guard guard(input_state.lock); input_state.pad_lstick_x = left_joystick_x_async; input_state.pad_lstick_y = left_joystick_y_async; + input_state.pad_rstick_x = right_joystick_x_async; + input_state.pad_rstick_y = right_joystick_y_async; } NativeUpdate(input_state); @@ -372,49 +377,96 @@ static inline void AsyncUp(int padbutton) { pad_buttons_async_clear |= padbutton; } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint key) { - KeyQueueAddKey(key_queue_async, key); +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint deviceId, jint key) { + KeyInput keyInput; + keyInput.deviceId = deviceId; + keyInput.keyCode = key; + keyInput.flags = KEY_DOWN; + NativeKey(keyInput); + // Pad mapping switch (key) { - case 1: AsyncDown (PAD_BUTTON_BACK); break; // Back - case 2: AsyncDown (PAD_BUTTON_MENU); break; // Menu + case KEYCODE_BACK: AsyncDown(PAD_BUTTON_BACK); break; // Back + case KEYCODE_MENU: AsyncDown(PAD_BUTTON_MENU); break; // Menu case KEYCODE_BUTTON_CROSS_PS3: AsyncDown(PAD_BUTTON_A); break; case KEYCODE_BUTTON_CIRCLE_PS3: - AsyncDown (PAD_BUTTON_B); + AsyncDown(PAD_BUTTON_B); break; default: break; } } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint key) { - KeyQueueRemoveKey(key_queue_async, key); +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint deviceId, jint key) { + KeyInput keyInput; + keyInput.deviceId = deviceId; + keyInput.keyCode = key; + keyInput.flags = KEY_UP; + NativeKey(keyInput); + // Pad mapping switch (key) { - case 1: AsyncUp (PAD_BUTTON_BACK); break; // Back - case 2: AsyncUp (PAD_BUTTON_MENU); break; // Menu + case KEYCODE_BACK: + AsyncUp(PAD_BUTTON_BACK); + break; // Back + case KEYCODE_MENU: + AsyncUp(PAD_BUTTON_MENU); + break; // Menu case KEYCODE_BUTTON_CROSS_PS3: AsyncUp(PAD_BUTTON_A); break; case KEYCODE_BUTTON_CIRCLE_PS3: - AsyncUp (PAD_BUTTON_B); + AsyncUp(PAD_BUTTON_B); + break; + default: break; - default: break; } } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickEvent( - JNIEnv *env, jclass, jint stick, jfloat x, jfloat y) { - if (stick == 0) { - left_joystick_x_async = x; - left_joystick_y_async = y; - } else if (stick == 1) { - right_joystick_x_async = x; - right_joystick_y_async = y; - } +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_beginJoystickEvent( + JNIEnv *env, jclass) { + // mutex lock? } +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickEvent( + JNIEnv *env, jclass, jint deviceId, jint axisId, jfloat value) { + switch (axisId) { + case JOYSTICK_AXIS_X: + left_joystick_x_async = value; + break; + case JOYSTICK_AXIS_Y: + left_joystick_y_async = -value; + break; + case JOYSTICK_AXIS_Z: + right_joystick_x_async = value; + break; + case JOYSTICK_AXIS_RZ: + right_joystick_y_async = -value; + break; + case JOYSTICK_AXIS_HAT_X: + hat_joystick_x_async = value; + break; + case JOYSTICK_AXIS_HAT_Y: + hat_joystick_y_async = -value; + break; + } + + // Hat is just stupid. Force translate it to dpad events. TODO + + AxisInput axis; + axis.axisId = axisId; + axis.deviceId = deviceId; + axis.value = value; + NativeAxis(axis); +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_endJoystickEvent( + JNIEnv *env, jclass) { + // mutex unlock? +} + + extern "C" void Java_com_henrikrydgard_libnative_NativeApp_mouseWheelEvent( JNIEnv *env, jclass, jint stick, jfloat x, jfloat y) { // TODO @@ -437,4 +489,3 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *e ILOG("Message received: %s %s", msg.c_str(), prm.c_str()); NativeMessageReceived(msg.c_str(), prm.c_str()); } - diff --git a/android/app-android.h b/android/app-android.h index fbe4d59932..bf842ac54a 100644 --- a/android/app-android.h +++ b/android/app-android.h @@ -6,33 +6,3 @@ // since native's keycodes are based on // android keycodes. typedef enum _keycode_t AndroidKeyCodes; - -enum AndroidJoystickAxis { - // Field descriptor #15 I - JOYSTICK_AXIS_X = 0, - JOYSTICK_AXIS_Y = 1, - JOYSTICK_AXIS_PRESSURE = 2, - JOYSTICK_AXIS_SIZE = 3, - JOYSTICK_AXIS_TOUCH_MAJOR = 4, - JOYSTICK_AXIS_TOUCH_MINOR = 5, - JOYSTICK_AXIS_TOOL_MAJOR = 6, - JOYSTICK_AXIS_TOOL_MINOR = 7, - JOYSTICK_AXIS_ORIENTATION = 8, - JOYSTICK_AXIS_VSCROLL = 9, - JOYSTICK_AXIS_HSCROLL = 10, - JOYSTICK_AXIS_Z = 11, - JOYSTICK_AXIS_RX = 12, - JOYSTICK_AXIS_RY = 13, - JOYSTICK_AXIS_RZ = 14, - JOYSTICK_AXIS_HAT_X = 15, - JOYSTICK_AXIS_HAT_Y = 16, - JOYSTICK_AXIS_LTRIGGER = 17, - JOYSTICK_AXIS_RTRIGGER = 18, - JOYSTICK_AXIS_THROTTLE = 19, - JOYSTICK_AXIS_RUDDER = 20, - JOYSTICK_AXIS_WHEEL = 21, - JOYSTICK_AXIS_GAS = 22, - JOYSTICK_AXIS_BRAKE = 23, - JOYSTICK_AXIS_DISTANCE = 24, - JOYSTICK_AXIS_TILT = 25, -}; diff --git a/android/src/com/henrikrydgard/libnative/InputDeviceState.java b/android/src/com/henrikrydgard/libnative/InputDeviceState.java new file mode 100644 index 0000000000..77b83560aa --- /dev/null +++ b/android/src/com/henrikrydgard/libnative/InputDeviceState.java @@ -0,0 +1,103 @@ +package com.henrikrydgard.libnative; + +import android.annotation.TargetApi; +import android.os.Build; +import android.util.SparseIntArray; +import android.view.InputDevice; +import android.view.InputDevice.MotionRange; +import android.view.KeyEvent; +import android.view.MotionEvent; + +@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) +public class InputDeviceState { + // DEVICE_ID_PAD_0 from the cpp code. TODO: allocate these sequentially if we get more controllers. + private static int deviceId = 10; + + private InputDevice mDevice; + private int[] mAxes; + + InputDevice getDevice() { return mDevice; } + + public InputDeviceState(InputDevice device) { + mDevice = device; + int numAxes = 0; + for (MotionRange range : device.getMotionRanges()) { + if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { + numAxes += 1; + } + } + + mAxes = new int[numAxes]; + + int i = 0; + for (MotionRange range : device.getMotionRanges()) { + if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { + mAxes[i++] = range.getAxis(); + } + } + } + + public static float ProcessAxis(InputDevice.MotionRange range, float axisvalue) { + float absaxisvalue = Math.abs(axisvalue); + float deadzone = range.getFlat(); + if (absaxisvalue <= deadzone) { + return 0.0f; + } + float normalizedvalue; + if (axisvalue < 0.0f) { + normalizedvalue = absaxisvalue / range.getMin(); + } else { + normalizedvalue = absaxisvalue / range.getMax(); + } + + return normalizedvalue; + } + + private static boolean isGameKey(int keyCode) { + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + return true; + default: + return KeyEvent.isGamepadButton(keyCode); + } + } + + public boolean onKeyDown(KeyEvent event) { + int keyCode = event.getKeyCode(); + if (event.getRepeatCount() == 0) { + if (isGameKey(keyCode)) { + NativeApp.keyDown(deviceId, keyCode); + return true; + } + } + return false; + } + + public boolean onKeyUp(KeyEvent event) { + int keyCode = event.getKeyCode(); + if (isGameKey(keyCode)) { + NativeApp.keyUp(deviceId, keyCode); + return true; + } + return false; + } + + public boolean onJoystickMotion(MotionEvent event) { + if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0) { + return false; + } + NativeApp.beginJoystickEvent(); + for (int i = 0; i < mAxes.length; i++) { + int axisId = mAxes[i]; + float value = event.getAxisValue(axisId); + // TODO: Use processAxis or move that to the C++ code + NativeApp.joystickAxis(deviceId, axisId, value); + } + NativeApp.endJoystickEvent(); + + return true; + } +} diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index a47fd9838d..5a21c14083 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -5,6 +5,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.lang.reflect.Field; +import java.util.List; import java.util.UUID; import android.annotation.SuppressLint; @@ -32,6 +33,7 @@ import android.util.Log; import android.view.Display; import android.view.Gravity; import android.view.InputDevice; +import android.view.InputEvent; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -275,54 +277,91 @@ public class NativeActivity extends Activity { public static boolean inputBoxCancelled; - @SuppressLint("NewApi") - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - // Eat these keys, to avoid accidental exits / other screwups. - // Maybe there's even more we need to eat on tablets? - switch (keyCode) { - case KeyEvent.KEYCODE_BACK: - if (event.isAltPressed()) { - NativeApp.keyDown(1004); // special custom keycode - } else { - NativeApp.keyDown(1); + + InputDeviceState inputPlayerA; + String inputPlayerADesc; + + // We simply grab the first input device to produce an event and ignore all others that are connected. + @TargetApi(Build.VERSION_CODES.GINGERBREAD) + private InputDeviceState getInputDeviceState(InputEvent event) { + InputDevice device = event.getDevice(); + if (device == null) { + return null; + } + if (inputPlayerA == null) { + inputPlayerA = new InputDeviceState(device); + inputPlayerADesc = getInputDesc(device); + } + + if (inputPlayerA.getDevice() == device) { + return inputPlayerA; + } + + /* + if (inputPlayerB == null) { + inputPlyerB = new InputDeviceStats(device); + } + + if (inputPlayerB.getDevice() == device) { + return inputPlayerB; + }*/ + + return null; + } + + // We grab the keys before onKeyDown/... even see them. This is also better because it lets us + // distinguish devices. + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { + InputDeviceState state = getInputDeviceState(event); + if (state == null) { + return super.dispatchKeyEvent(event); } - return true; - case KeyEvent.KEYCODE_MENU: - NativeApp.keyDown(2); - return true; - case KeyEvent.KEYCODE_SEARCH: - NativeApp.keyDown(3); - return true; - case KeyEvent.KEYCODE_VOLUME_DOWN: - case KeyEvent.KEYCODE_VOLUME_UP: - return false; - case KeyEvent.KEYCODE_DPAD_UP: - case KeyEvent.KEYCODE_DPAD_DOWN: - case KeyEvent.KEYCODE_DPAD_LEFT: - case KeyEvent.KEYCODE_DPAD_RIGHT: - // Joysticks are supported in Honeycomb MR1 and later via the onGenericMotionEvent method. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && event.getSource() == InputDevice.SOURCE_JOYSTICK) { - return false; + + switch (event.getAction()) { + case KeyEvent.ACTION_DOWN: + if (state.onKeyDown(event)) { + return true; + } + break; + + case KeyEvent.ACTION_UP: + if (state.onKeyUp(event)) { + return true; + } + break; } - default: - // send the rest of the keys through. - // TODO: get rid of the three special cases above by adjusting the native side of the code. - Log.d("JAMIE", "Key code: " + keyCode + ", KeyEvent: " + event); - NativeApp.keyDown(keyCode); - return true; + } + + // Let's go through the old path (onKeyUp, onKeyDown). + return super.dispatchKeyEvent(event); + } + + @TargetApi(16) + static public String getInputDesc(InputDevice input) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + return input.getDescriptor(); + } else { + List motions = input.getMotionRanges(); + String fakeid = ""; + for (InputDevice.MotionRange range : motions) + fakeid += range.getAxis(); + return fakeid; } } @Override @TargetApi(12) public boolean onGenericMotionEvent(MotionEvent event) { - Log.d("JAMIE", "onGenericMotionEvent: " + event); - if (event.getSource() == InputDevice.SOURCE_JOYSTICK) { - float leftJoystickX = event.getAxisValue(MotionEvent.AXIS_X) * 1f; - float leftJoystickY = event.getAxisValue(MotionEvent.AXIS_Y) * -1f; - NativeApp.joystickEvent(0, leftJoystickX, leftJoystickY); + Log.d(TAG, "onGenericMotionEvent: " + event); + if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) { + if (Build.VERSION.SDK_INT >= 12) { + InputDeviceState state = getInputDeviceState(event); + state.onJoystickMotion(event); + } } + if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { switch (event.getAction()) { case MotionEvent.ACTION_HOVER_MOVE: @@ -335,49 +374,90 @@ public class NativeActivity extends Activity { } return super.onGenericMotionEvent(event); } - + @SuppressLint("NewApi") @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { + public boolean onKeyDown(int keyCode, KeyEvent event) { // Eat these keys, to avoid accidental exits / other screwups. // Maybe there's even more we need to eat on tablets? - Log.d("JAMIE", "KeyEvent: " + event); switch (keyCode) { case KeyEvent.KEYCODE_BACK: if (event.isAltPressed()) { - NativeApp.keyUp(1004); // special custom keycode + NativeApp.keyDown(0, 1004); // special custom keycode } else if (NativeApp.isAtTopLevel()) { - return false; + Log.i(TAG, "IsAtTopLevel returned false."); + return super.onKeyUp(keyCode, event); } else { - NativeApp.keyUp(1); + NativeApp.keyDown(0, keyCode); } return true; case KeyEvent.KEYCODE_MENU: - // Menu should be ignored from SDK 11 forwards. We send it to the app. - NativeApp.keyUp(2); - return true; case KeyEvent.KEYCODE_SEARCH: - // Search probably should also be ignored. We send it to the app. - NativeApp.keyUp(3); + NativeApp.keyDown(0, keyCode); return true; case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: - return false; + // NativeApp should ignore these. + return super.onKeyDown(keyCode, event); + case KeyEvent.KEYCODE_DPAD_UP: case KeyEvent.KEYCODE_DPAD_DOWN: case KeyEvent.KEYCODE_DPAD_LEFT: case KeyEvent.KEYCODE_DPAD_RIGHT: // Joysticks are supported in Honeycomb MR1 and later via the onGenericMotionEvent method. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && event.getSource() == InputDevice.SOURCE_JOYSTICK) { - return false; + return super.onKeyUp(keyCode, event); } + // Fall through default: // send the rest of the keys through. // TODO: get rid of the three special cases above by adjusting the native side of the code. - NativeApp.keyUp(keyCode); + // Log.d(TAG, "Key down: " + keyCode + ", KeyEvent: " + event); + NativeApp.keyDown(0, keyCode); return true; } } + + @SuppressLint("NewApi") + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_BACK: + if (event.isAltPressed()) { + NativeApp.keyUp(0, 1004); // special custom keycode + } else if (NativeApp.isAtTopLevel()) { + Log.i(TAG, "IsAtTopLevel returned false."); + return super.onKeyUp(keyCode, event); + } else { + NativeApp.keyUp(0, keyCode); + } + return true; + case KeyEvent.KEYCODE_MENU: + case KeyEvent.KEYCODE_SEARCH: + // Search probably should also be ignored. We send it to the app. + NativeApp.keyUp(0, keyCode); + return true; + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_VOLUME_UP: + return super.onKeyUp(keyCode, event); + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + // Joysticks are supported in Honeycomb MR1 and later via the onGenericMotionEvent method. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && event.getSource() == InputDevice.SOURCE_JOYSTICK) { + return super.onKeyUp(keyCode, event); + } + // Fall through + default: + // send the rest of the keys through. + // TODO: get rid of the three special cases above by adjusting the native side of the code. + // Log.d(TAG, "Key down: " + keyCode + ", KeyEvent: " + event); + NativeApp.keyUp(0, keyCode); + return true; + } + } + public String inputBox(String title, String defaultText, String defaultAction) { final FrameLayout fl = new FrameLayout(this); final EditText input = new EditText(this); @@ -428,6 +508,7 @@ public class NativeActivity extends Activity { send.setData(uri); startActivity(Intent.createChooser(send, "E-mail the app author!")); } else if (command.equals("launchMarket")) { + // Don't need this, can just use launchBrowser with a market: // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app // http://developer.android.com/guide/publishing/publishing.html#marketintent } else if (command.equals("toast")) { diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 2612bec744..25cec55bf6 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -15,11 +15,13 @@ public class NativeApp { public static native void shutdown(); - public static native void keyDown(int key); + public static native void keyDown(int deviceId, int key); + public static native void keyUp(int deviceId, int key); - public static native void keyUp(int key); - - public static native void joystickEvent(int stick, float x, float y); + public static native void beginJoystickEvent(); + public static native void joystickAxis(int deviceId, int axis, float value); + public static native void endJoystickEvent(); + public static native void mouseWheelEvent(float x, float y); // will only be called between init() and shutdown() diff --git a/base/NativeApp.h b/base/NativeApp.h index cd807d449e..a00d9af144 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -11,6 +11,8 @@ // This is defined in input/input_state.h. struct InputState; struct TouchInput; +struct KeyInput; +struct AxisInput; // The first function to get called, just write strings to the two pointers. // This might get called multiple times in some implementations, you must be able to handle that. @@ -47,6 +49,8 @@ void NativeUpdate(InputState &input); // If you don't care about touch latency, just do a no-op implementation of this. // time is not yet implemented. finger can be from 0 to 7, inclusive. void NativeTouch(const TouchInput &touch); +void NativeKey(const KeyInput &key); +void NativeAxis(const AxisInput &axis); // Called when it's time to render. If the device can keep up, this // will also be called sixty times per second. Main thread. diff --git a/base/PCMain.cpp b/base/PCMain.cpp index d26a225163..4c10aae547 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -538,14 +538,17 @@ int main(int argc, char *argv[]) { if (event.key.keysym.sym == SDLK_ESCAPE) { quitRequested = 1; } - - KeyQueueAttemptTranslatedAdd(input_state.key_queue, - KeyMapRawSDLtoNative, - event.key.keysym.sym); + KeyInput key; + key.flags = KEY_DOWN; + key.keyCode = KeyMapRawSDLtoNative[event.key.keysym.sym]; + key.deviceId = 0; + NativeKey(key); } else if (event.type == SDL_KEYUP) { - KeyQueueAttemptTranslatedRemove(input_state.key_queue, - KeyMapRawSDLtoNative, - event.key.keysym.sym); + KeyInput key; + key.flags = KEY_UP; + key.keyCode = KeyMapRawSDLtoNative[event.key.keysym.sym]; + key.deviceId = 0; + NativeKey(key); } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { input_state.pointer_x[0] = mx; diff --git a/input/input_state.cpp b/input/input_state.cpp index 949828bc08..51a262c88d 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -1,96 +1,14 @@ #include "input_state.h" #include -#define max_queue MAX_KEYQUEUESIZE - -void MakeRoomInQueueFront(int queue[]) -{ - // shift queue elements from front towards back - for (int i = max_queue - 1; i > 0; i--) { - queue[i] = queue[i - 1]; +const char *GetDeviceName(int deviceId) { + switch (deviceId) { + case DEVICE_ID_DEFAULT: return "built-in"; + case DEVICE_ID_KEYBOARD: return "kbd"; + case DEVICE_ID_PAD_0: return "pad"; + case DEVICE_ID_X360_0: return "x360"; + case DEVICE_ID_ACCELEROMETER: return "accelerometer"; + default: + return "unknown"; } - queue[0] = 0; -} - -void FillGap(int queue[], int gap_loc) -{ - // shift elements from back towards front - // until gap location is filled - for (int i = gap_loc; i < max_queue; i++) { - queue[i] = queue[i + 1]; - } - queue[max_queue - 1] = 0; -} - -void KeyQueueAddKey(int queue[], int key) -{ - for (int i = 0; i < max_queue; i++) { - if (queue[i] == key) - return; - if (queue[i] == 0) { - queue[i] = key; - return; - } - } - - // queue was full - MakeRoomInQueueFront(queue); - queue[0] = key; -} - -void KeyQueueRemoveKey(int queue[], int key) -{ - for (int i = 0; i < max_queue; i++) - if (queue[i] == key) - FillGap(queue, i); -} - -void KeyQueueCopyQueue(int src[], int dst[]) -{ - for (int i = 0; i < max_queue; i++) - dst[i] = src[i]; -} -void KeyQueueBlank(int queue[]) -{ - for (int i = 0; i < max_queue; i++) - queue[i] = 0; -} - -int AttemptTranslate(const std::map trans_table, int plat_key) -{ - std::map::const_iterator iter; - iter = trans_table.find(plat_key); - if (iter == trans_table.end()) - return 0; - - return iter->second; -} - - -void KeyQueueAttemptTranslatedAdd(int queue[], - const std::map translation_table, - int platform_key) -{ - int key = AttemptTranslate(translation_table, platform_key); - - if (key == 0) { - std::cerr << "Warning: Platform key code translation table missing " - << "(" << platform_key << ")\n"; - return; - } - - KeyQueueAddKey(queue, key); -} - - -void KeyQueueAttemptTranslatedRemove(int queue[], - const std::map translation_table, - int platform_key) -{ - int key = AttemptTranslate(translation_table, platform_key); - - if (key == 0) - return; - - KeyQueueRemoveKey(queue, key); } diff --git a/input/input_state.h b/input/input_state.h index 1bb054bf2a..e9e4c84bc7 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -1,10 +1,30 @@ #pragma once +// InputState is the simple way of getting input. All the input we have is collected +// to a canonical Xbox360-style pad fully automatically. +// +// Recommended for use in game UIs and games that don't have advanced needs. +// +// For more detailed and configurable input, implement NativeTouch, NativeKey and NativeAxis and do your +// own mapping. Might later move the mapping system from PPSSPP to native. + #include "math/lin/vec3.h" #include "base/mutex.h" #include "base/basictypes.h" #include +// Default device IDs + +enum { + DEVICE_ID_DEFAULT = 0, // Old Android + DEVICE_ID_KEYBOARD = 1, // PC keyboard, android keyboards + DEVICE_ID_PAD_0 = 10, // Generic joypads + DEVICE_ID_X360_0 = 20, // XInput joypads + DEVICE_ID_ACCELEROMETER = 30, +}; + +const char *GetDeviceName(int deviceId); + enum { PAD_BUTTON_A = 1, PAD_BUTTON_B = 2, @@ -44,7 +64,7 @@ enum { #ifndef MAX_KEYQUEUESIZE #define MAX_KEYQUEUESIZE 20 #endif - + // Collection of all possible inputs, and automatically computed // deltas where applicable. struct InputState { @@ -60,7 +80,7 @@ struct InputState { memset(pointer_down, 0, sizeof(pointer_down)); } - // Gamepad style input + // Gamepad style input. For ease of use. int pad_buttons; // bitfield int pad_last_buttons; int pad_buttons_down; // buttons just pressed this frame @@ -84,8 +104,6 @@ struct InputState { bool accelerometer_valid; Vec3 acc; - int key_queue[MAX_KEYQUEUESIZE]; - private: DISALLOW_COPY_AND_ASSIGN(InputState); }; @@ -118,11 +136,20 @@ struct TouchInput { double timestamp; }; +enum { + KEY_DOWN = 1, + KEY_UP = 2, +}; -// Key Queue Helpers -void KeyQueueAddKey(int [], int); -void KeyQueueRemoveKey(int [], int); -void KeyQueueCopyQueue(int src[], int dst[]); -void KeyQueueBlank(int []); -void KeyQueueAttemptTranslatedAdd(int [], const std::map, int); -void KeyQueueAttemptTranslatedRemove(int [], const std::map, int); +struct KeyInput { + int deviceId; + int keyCode; // Android keycodes are the canonical keycodes, everyone else map to them. + int flags; +}; + +struct AxisInput { + int deviceId; + int axisId; // Android axis Ids are the canonical ones. + float value; + int flags; +}; diff --git a/input/keycodes.h b/input/keycodes.h index b8ec82b9ec..1bf90a8814 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -216,12 +216,8 @@ typedef enum _keycode_t { // Not native to android // Xbox 360 controller - KEYCODE_XBOX_A = 5001, - KEYCODE_XBOX_B = 5002, - KEYCODE_XBOX_X = 5003, - KEYCODE_XBOX_Y = 5004, KEYCODE_XBOX_START = 5005, - KEYCODE_XBOX_SELECT = 5006, + KEYCODE_XBOX_BACK = 5006, KEYCODE_XBOX_BUMPER_L = 5007, KEYCODE_XBOX_BUMPER_R = 5008, KEYCODE_XBOX_DPAD_UP = 5009, @@ -234,3 +230,33 @@ typedef enum _keycode_t { // KEYCODE_XBOX_HOME = NEWKEY, // this can't be read on PC, right? } keycode_t; + +enum AndroidJoystickAxis { + // Field descriptor #15 I + JOYSTICK_AXIS_X = 0, + JOYSTICK_AXIS_Y = 1, + JOYSTICK_AXIS_PRESSURE = 2, + JOYSTICK_AXIS_SIZE = 3, + JOYSTICK_AXIS_TOUCH_MAJOR = 4, + JOYSTICK_AXIS_TOUCH_MINOR = 5, + JOYSTICK_AXIS_TOOL_MAJOR = 6, + JOYSTICK_AXIS_TOOL_MINOR = 7, + JOYSTICK_AXIS_ORIENTATION = 8, + JOYSTICK_AXIS_VSCROLL = 9, + JOYSTICK_AXIS_HSCROLL = 10, + JOYSTICK_AXIS_Z = 11, + JOYSTICK_AXIS_RX = 12, + JOYSTICK_AXIS_RY = 13, + JOYSTICK_AXIS_RZ = 14, + JOYSTICK_AXIS_HAT_X = 15, + JOYSTICK_AXIS_HAT_Y = 16, + JOYSTICK_AXIS_LTRIGGER = 17, + JOYSTICK_AXIS_RTRIGGER = 18, + JOYSTICK_AXIS_THROTTLE = 19, + JOYSTICK_AXIS_RUDDER = 20, + JOYSTICK_AXIS_WHEEL = 21, + JOYSTICK_AXIS_GAS = 22, + JOYSTICK_AXIS_BRAKE = 23, + JOYSTICK_AXIS_DISTANCE = 24, + JOYSTICK_AXIS_TILT = 25, +}; diff --git a/native.vcxproj b/native.vcxproj index 3980989fea..0883830a00 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -230,6 +230,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index dabb7db32e..ed978de906 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -278,6 +278,7 @@ math + diff --git a/ui/screen.cpp b/ui/screen.cpp index 12b9da6118..a79128d9ce 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -54,12 +54,21 @@ void ScreenManager::switchToNext() { } void ScreenManager::touch(const TouchInput &touch) { - if (!stack_.empty()) { + if (!stack_.empty()) stack_.back().screen->touch(touch); - return; - } } +void ScreenManager::key(const KeyInput &key) { + if (!stack_.empty()) + stack_.back().screen->key(key); +} + +void ScreenManager::axis(const AxisInput &axis) { + if (!stack_.empty()) + stack_.back().screen->axis(axis); +} + + void ScreenManager::render() { if (!stack_.empty()) { switch (stack_.back().flags) { diff --git a/ui/screen.h b/ui/screen.h index 80c8d36650..4c2b2af5cc 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -44,6 +44,8 @@ public: virtual void deviceLost() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} virtual void touch(const TouchInput &touch) {} + virtual void key(const KeyInput &key) {} + virtual void axis(const AxisInput &touch) {} virtual void sendMessage(const char *msg, const char *value) {} ScreenManager *screenManager() { return screenManager_; } @@ -91,6 +93,8 @@ public: // Instant touch, separate from the update() mechanism. void touch(const TouchInput &touch); + void key(const KeyInput &key); + void axis(const AxisInput &touch); // Generic facility for gross hacks :P void sendMessage(const char *msg, const char *value); From 4aa16ddb86994c1246f96707b94d21917befe7ad Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 6 Jul 2013 20:44:12 +0200 Subject: [PATCH 0500/1445] Minor stuff --- file/ini_file.h | 2 ++ input/keycodes.h | 16 ---------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/file/ini_file.h b/file/ini_file.h index aa5146e34e..638295b08b 100644 --- a/file/ini_file.h +++ b/file/ini_file.h @@ -170,6 +170,8 @@ public: void SortSections(); const std::vector
&Sections() { return sections; } + bool HasSection(const char *section) { return GetSection(section) != 0; } + Section* GetOrCreateSection(const char* section); private: diff --git a/input/keycodes.h b/input/keycodes.h index 1bf90a8814..4b71ff3e29 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -212,22 +212,6 @@ typedef enum _keycode_t { KEYCODE_BUTTON_15 = 202, KEYCODE_BUTTON_16 = 203, - // == Extended Keys ==== - // Not native to android - - // Xbox 360 controller - KEYCODE_XBOX_START = 5005, - KEYCODE_XBOX_BACK = 5006, - KEYCODE_XBOX_BUMPER_L = 5007, - KEYCODE_XBOX_BUMPER_R = 5008, - KEYCODE_XBOX_DPAD_UP = 5009, - KEYCODE_XBOX_DPAD_LEFT = 5010, - KEYCODE_XBOX_DPAD_RIGHT = 5011, - KEYCODE_XBOX_DPAD_DOWN = 5012, - // These are really axes, not buttons. But good to be able to map them as buttons. - KEYCODE_XBOX_TRIGGER_L = 5013, - KEYCODE_XBOX_TRIGGER_R = 5014, - // KEYCODE_XBOX_HOME = NEWKEY, // this can't be read on PC, right? } keycode_t; From cae8c040031dd53f20929ad65951a823868ed800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 6 Jul 2013 20:54:32 +0200 Subject: [PATCH 0501/1445] SDL keymapping fix --- base/PCMain.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 4c10aae547..7bf303efb0 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -538,16 +538,18 @@ int main(int argc, char *argv[]) { if (event.key.keysym.sym == SDLK_ESCAPE) { quitRequested = 1; } + int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_DOWN; - key.keyCode = KeyMapRawSDLtoNative[event.key.keysym.sym]; - key.deviceId = 0; + key.keyCode = KeyMapRawSDLtoNative.find(k)->second; + key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); } else if (event.type == SDL_KEYUP) { + int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_UP; - key.keyCode = KeyMapRawSDLtoNative[event.key.keysym.sym]; - key.deviceId = 0; + key.keyCode = KeyMapRawSDLtoNative.find(k)->second; + key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); } else if (event.type == SDL_MOUSEBUTTONDOWN) { if (event.button.button == SDL_BUTTON_LEFT) { From 585081e1c0651c782411212464571691503239bd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 6 Jul 2013 21:27:30 +0200 Subject: [PATCH 0502/1445] IniFile: Add way to clear a section --- file/ini_file.cpp | 4 ++++ file/ini_file.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index 045edc9d5f..dbe0e23e82 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -57,6 +57,10 @@ static bool ParseLine(const std::string& line, std::string* keyOut, std::string* return false; } +void IniFile::Section::Clear() { + lines.clear(); +} + std::string* IniFile::Section::GetLine(const char* key, std::string* valueOut, std::string* commentOut) { for (std::vector::iterator iter = lines.begin(); iter != lines.end(); ++iter) diff --git a/file/ini_file.h b/file/ini_file.h index 638295b08b..0205bbf1cf 100644 --- a/file/ini_file.h +++ b/file/ini_file.h @@ -24,6 +24,8 @@ public: bool Exists(const char *key) const; bool Delete(const char *key); + void Clear(); + std::map ToMap() const; std::string* GetLine(const char* key, std::string* valueOut, std::string* commentOut); From 35ccbc6df3bcde28c30d838dc6f8ef5715d34114 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 7 Jul 2013 17:46:37 +1000 Subject: [PATCH 0503/1445] Blackberry buildfix. --- input/input_state.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/input/input_state.h b/input/input_state.h index e9e4c84bc7..32e196a1e2 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -136,6 +136,8 @@ struct TouchInput { double timestamp; }; +#undef KEY_DOWN + enum { KEY_DOWN = 1, KEY_UP = 2, From 3fe24760e64143aecc4bb887ccf033cb8806f84d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 7 Jul 2013 10:52:23 +0200 Subject: [PATCH 0504/1445] Detect EXT_swap_control_tear on Windows --- gfx_es2/gl_state.cpp | 7 +++++++ gfx_es2/gl_state.h | 1 + 2 files changed, 8 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 53fc98733a..367e61f72c 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -59,6 +59,13 @@ void CheckGLExtensions() { const char *extString = (const char *)glGetString(GL_EXTENSIONS); +#ifdef WIN32 + const char *wglString = wglGetExtensionsStringEXT(); + gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0; +#elif !defined(USING_GLES2) + // const char *glXString = glXQueryExtensionString(); + // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; +#endif gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0; gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index cb72e5a0ae..a325cb916b 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -207,6 +207,7 @@ struct GLExtensions { bool EXT_discard_framebuffer; bool FBO_ARB; bool FBO_EXT; + bool EXT_swap_control_tear; }; extern GLExtensions gl_extensions; From 127d9d38544ddb02ada012796f1b273f05720666 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 7 Jul 2013 10:53:09 +0200 Subject: [PATCH 0505/1445] Fix minor bug processing joystick data on android --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 5a21c14083..022304a753 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -359,6 +359,7 @@ public class NativeActivity extends Activity { if (Build.VERSION.SDK_INT >= 12) { InputDeviceState state = getInputDeviceState(event); state.onJoystickMotion(event); + return true; } } From 839222a4fa2b5d7d5f9b69ee87085d7cda0d4e89 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 7 Jul 2013 14:37:37 +0200 Subject: [PATCH 0506/1445] Add keycode for the 102th key on euro keyboards. --- input/keycodes.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/input/keycodes.h b/input/keycodes.h index 4b71ff3e29..d90fcda983 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -212,6 +212,11 @@ typedef enum _keycode_t { KEYCODE_BUTTON_15 = 202, KEYCODE_BUTTON_16 = 203, + + + // Extended keycodes, not available on Android + KEYCODE_EXT_PIPE = 1001, // The key next to Z on euro 102-key keyboards. + } keycode_t; From 151b377506b7c760d8405b971d6ab4c808b19b45 Mon Sep 17 00:00:00 2001 From: dykebeard Date: Sun, 7 Jul 2013 14:32:03 -0400 Subject: [PATCH 0507/1445] Simple PNG screenshot support --- ext/stb_image_write/stb_image_write.c | 2 + ext/stb_image_write/stb_image_writer.h | 511 +++++++++++++++++++++++++ 2 files changed, 513 insertions(+) create mode 100644 ext/stb_image_write/stb_image_write.c create mode 100644 ext/stb_image_write/stb_image_writer.h diff --git a/ext/stb_image_write/stb_image_write.c b/ext/stb_image_write/stb_image_write.c new file mode 100644 index 0000000000..cbbabf0d3b --- /dev/null +++ b/ext/stb_image_write/stb_image_write.c @@ -0,0 +1,2 @@ +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "ext/stb_image_write/stb_image_writer.h" \ No newline at end of file diff --git a/ext/stb_image_write/stb_image_writer.h b/ext/stb_image_write/stb_image_writer.h new file mode 100644 index 0000000000..b7c4f490b2 --- /dev/null +++ b/ext/stb_image_write/stb_image_writer.h @@ -0,0 +1,511 @@ +/* stbiw-0.92 - public domain - http://nothings.org/stb/stb_image_write.h + writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 + no warranty implied; use at your own risk + + +Before including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + +in the file that you want to have the implementation. + + +ABOUT: + + This header file is a library for writing images to C stdio. It could be + adapted to write to memory or a general streaming interface; let me know. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation. This library is designed + for source code compactness and simplicitly, not optimal image file size + or run-time performance. + +USAGE: + + There are three functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP and TGA formats expand Y to RGB in the file format. BMP does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + +#ifdef __cplusplus +} +#endif + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#include +#include +#include +#include +#include + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +static void writefv(FILE *f, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; } + case '2': { int x = va_arg(v,int); unsigned char b[2]; + b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8); + fwrite(b,2,1,f); break; } + case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4]; + b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8); + b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24); + fwrite(b,4,1,f); break; } + default: + assert(0); + return; + } + } +} + +static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c) +{ + unsigned char arr[3]; + arr[0] = a, arr[1] = b, arr[2] = c; + fwrite(arr, 3, 1, f); +} + +static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + stbiw_uint32 zero = 0; + int i,j,k, j_end; + + if (y <= 0) + return; + + if (vdir < 0) + j_end = -1, j = y-1; + else + j_end = y, j = 0; + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + if (write_alpha < 0) + fwrite(&d[comp-1], 1, 1, f); + switch (comp) { + case 1: + case 2: write3(f, d[0],d[0],d[0]); + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k=0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255; + write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]); + break; + } + if (write_alpha > 0) + fwrite(&d[comp-1], 1, 1, f); + } + fwrite(&zero,scanline_pad,1,f); + } +} + +static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...) +{ + FILE *f; + if (y < 0 || x < 0) return 0; + f = fopen(filename, "wb"); + if (f) { + va_list v; + va_start(v, fmt); + writefv(f, fmt, v); + va_end(v); + write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad); + fclose(f); + } + return f != NULL; +} + +int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + int pad = (-x*3) & 3; + return outfile(filename,-1,-1,x,y,comp,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header +} + +int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + int has_alpha = !(comp & 1); + return outfile(filename, -1,-1, x, y, comp, (void *) data, has_alpha, 0, + "111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha); +} + +// stretchy buffer; stbi__sbpush() == vector<>::push_back() -- stbi__sbcount() == vector<>::size() +#define stbi__sbraw(a) ((int *) (a) - 2) +#define stbi__sbm(a) stbi__sbraw(a)[0] +#define stbi__sbn(a) stbi__sbraw(a)[1] + +#define stbi__sbneedgrow(a,n) ((a)==0 || stbi__sbn(a)+n >= stbi__sbm(a)) +#define stbi__sbmaybegrow(a,n) (stbi__sbneedgrow(a,(n)) ? stbi__sbgrow(a,n) : 0) +#define stbi__sbgrow(a,n) stbi__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbi__sbpush(a, v) (stbi__sbmaybegrow(a,1), (a)[stbi__sbn(a)++] = (v)) +#define stbi__sbcount(a) ((a) ? stbi__sbn(a) : 0) +#define stbi__sbfree(a) ((a) ? free(stbi__sbraw(a)),0 : 0) + +static void *stbi__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbi__sbm(*arr)+increment : increment+1; + void *p = realloc(*arr ? stbi__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); + assert(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbi__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbi__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbi__sbpush(data, (unsigned char) *bitbuffer); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbi__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbi__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbi__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbi__zlib_flush() (out = stbi__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbi__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbi__zlib_flush()) +#define stbi__zlib_huffa(b,c) stbi__zlib_add(stbi__zlib_bitrev(b,c),c) +// default huffman tables +#define stbi__zlib_huff1(n) stbi__zlib_huffa(0x30 + (n), 8) +#define stbi__zlib_huff2(n) stbi__zlib_huffa(0x190 + (n)-144, 9) +#define stbi__zlib_huff3(n) stbi__zlib_huffa(0 + (n)-256,7) +#define stbi__zlib_huff4(n) stbi__zlib_huffa(0xc0 + (n)-280,8) +#define stbi__zlib_huff(n) ((n) <= 143 ? stbi__zlib_huff1(n) : (n) <= 255 ? stbi__zlib_huff2(n) : (n) <= 279 ? stbi__zlib_huff3(n) : stbi__zlib_huff4(n)) +#define stbi__zlib_huffb(n) ((n) <= 143 ? stbi__zlib_huff1(n) : stbi__zlib_huff2(n)) + +#define stbi__ZHASH 16384 + +unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char **hash_table[stbi__ZHASH]; // 64KB on the stack! + if (quality < 5) quality = 5; + + stbi__sbpush(out, 0x78); // DEFLATE 32K window + stbi__sbpush(out, 0x5e); // FLEVEL = 1 + stbi__zlib_add(1,1); // BFINAL = 1 + stbi__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbi__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbi__zhash(data+i)&(stbi__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbi__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbi__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) best=d,bestloc=hlist[j]; + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbi__sbn(hash_table[h]) == 2*quality) { + memcpy(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbi__sbn(hash_table[h]) = quality; + } + stbi__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbi__zhash(data+i+1)&(stbi__ZHASH-1); + hlist = hash_table[h]; + n = stbi__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbi__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = data+i - bestloc; // distance back + assert(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbi__zlib_huff(j+257); + if (lengtheb[j]) stbi__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbi__zlib_add(stbi__zlib_bitrev(j,5),5); + if (disteb[j]) stbi__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbi__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbi__zlib_huffb(data[i]); + stbi__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbi__zlib_add(0,1); + + for (i=0; i < stbi__ZHASH; ++i) + (void) stbi__sbfree(hash_table[i]); + + { + // compute adler32 on input + unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552; + int j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; + s1 %= 65521, s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbi__sbpush(out, (unsigned char) (s2 >> 8)); + stbi__sbpush(out, (unsigned char) s2); + stbi__sbpush(out, (unsigned char) (s1 >> 8)); + stbi__sbpush(out, (unsigned char) s1); + } + *out_len = stbi__sbn(out); + // make returned pointer freeable + memmove(stbi__sbraw(out), out, *out_len); + return (unsigned char *) stbi__sbraw(out); +} + +unsigned int stbi__crc32(unsigned char *buffer, int len) +{ + static unsigned int crc_table[256]; + unsigned int crc = ~0u; + int i,j; + if (crc_table[1] == 0) + for(i=0; i < 256; i++) + for (crc_table[i]=i, j=0; j < 8; ++j) + crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0); + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +} + +#define stbi__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4) +#define stbi__wp32(data,v) stbi__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbi__wptag(data,s) stbi__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbi__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbi__crc32(*data - len - 4, len+4); + stbi__wp32(*data, crc); +} + +static unsigned char stbi__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return (unsigned char) a; + if (pb <= pc) return (unsigned char) b; + return (unsigned char) c; +} + +unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int i,j,k,p,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + filt = (unsigned char *) malloc((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) malloc(x * n); if (!line_buffer) { free(filt); return 0; } + for (j=0; j < y; ++j) { + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = j ? mapping : firstmap; + int best = 0, bestval = 0x7fffffff; + for (p=0; p < 2; ++p) { + for (k= p?best:0; k < 5; ++k) { + int type = mymap[k],est=0; + unsigned char *z = pixels + stride_bytes*j; + for (i=0; i < n; ++i) + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbi__paeth(0,z[i-stride_bytes],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + for (i=n; i < x*n; ++i) { + switch (type) { + case 0: line_buffer[i] = z[i]; break; + case 1: line_buffer[i] = z[i] - z[i-n]; break; + case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; + case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; + case 4: line_buffer[i] = z[i] - stbi__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; + case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: line_buffer[i] = z[i] - stbi__paeth(z[i-n], 0,0); break; + } + } + if (p) break; + for (i=0; i < x*n; ++i) + est += abs((signed char) line_buffer[i]); + if (est < bestval) { bestval = est; best = k; } + } + } + // when we get here, best contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) best; + memcpy(filt+j*(x*n+1)+1, line_buffer, x*n); + } + free(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory + free(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) malloc(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + memcpy(o,sig,8); o+= 8; + stbi__wp32(o, 13); // header length + stbi__wptag(o, "IHDR"); + stbi__wp32(o, x); + stbi__wp32(o, y); + *o++ = 8; + *o++ = (unsigned char) ctype[n]; + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbi__wpcrc(&o,13); + + stbi__wp32(o, zlen); + stbi__wptag(o, "IDAT"); + memcpy(o, zlib, zlen); o += zlen; free(zlib); + stbi__wpcrc(&o, zlen); + + stbi__wp32(o,0); + stbi__wptag(o, "IEND"); + stbi__wpcrc(&o,0); + + assert(o == out + *out_len); + + return out; +} + +int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); + if (!png) return 0; + f = fopen(filename, "wb"); + if (!f) { free(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + free(png); + return 1; +} +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ \ No newline at end of file From 70921b27d38aed92a7e4482bf592b82945d95bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 7 Jul 2013 21:28:04 +0200 Subject: [PATCH 0508/1445] Add stb_image_write to Android.mk --- Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/Android.mk b/Android.mk index 357c260272..5d92f1f757 100644 --- a/Android.mk +++ b/Android.mk @@ -23,6 +23,7 @@ LOCAL_SRC_FILES :=\ ext/jpge/jpge.cpp \ ext/sha1/sha1.cpp \ ext/stb_image/stb_image.c \ + ext/stb_image_write/stb_image_write.c \ ext/stb_vorbis/stb_vorbis.c.arm \ ext/vjson/json.cpp \ ext/vjson/block_allocator.cpp \ From 05f620f5b20e2368e998eaedf4b26426cf6e2345 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 7 Jul 2013 23:36:55 +0200 Subject: [PATCH 0509/1445] Make sure stb_image_write.c is "included in the project". --- native.vcxproj | 1 + native.vcxproj.filters | 1 + 2 files changed, 2 insertions(+) diff --git a/native.vcxproj b/native.vcxproj index 0883830a00..264f78d557 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -330,6 +330,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index ed978de906..30e2b489d0 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -498,6 +498,7 @@ input + From 7a8076f3b216a2577f1fa52f67622f7ace4b525b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 8 Jul 2013 10:23:40 +0200 Subject: [PATCH 0510/1445] SDL main: Don't exit on ESC. --- base/PCMain.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 7bf303efb0..0d9b3e028d 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -535,9 +535,6 @@ int main(int argc, char *argv[]) { if (event.type == SDL_QUIT) { quitRequested = 1; } else if (event.type == SDL_KEYDOWN) { - if (event.key.keysym.sym == SDLK_ESCAPE) { - quitRequested = 1; - } int k = event.key.keysym.sym; KeyInput key; key.flags = KEY_DOWN; @@ -595,8 +592,6 @@ int main(int argc, char *argv[]) { break; const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); - if (keys[SDLK_ESCAPE]) - break; SimulateGamepad(keys, &input_state); UpdateInputState(&input_state); NativeUpdate(input_state); From 57d3fa01345d447cad3d943838a74c71e4e08a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 8 Jul 2013 11:03:14 +0200 Subject: [PATCH 0511/1445] Basic mousewheel support (SDL) --- base/PCMain.cpp | 88 ++++++++++++++++++++++++++++++++++++------------ input/keycodes.h | 5 +++ ui/ui.h | 4 +++ 3 files changed, 75 insertions(+), 22 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 0d9b3e028d..c0411fd100 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -549,17 +549,39 @@ int main(int argc, char *argv[]) { key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); } else if (event.type == SDL_MOUSEBUTTONDOWN) { - if (event.button.button == SDL_BUTTON_LEFT) { - input_state.pointer_x[0] = mx; - input_state.pointer_y[0] = my; - //input_state.mouse_buttons_down = 1; - input_state.pointer_down[0] = true; - TouchInput input; - input.x = mx; - input.y = my; - input.flags = TOUCH_DOWN; - input.id = 0; - NativeTouch(input); + switch (event.button.button) { + case SDL_BUTTON_LEFT: + { + input_state.pointer_x[0] = mx; + input_state.pointer_y[0] = my; + //input_state.mouse_buttons_down = 1; + input_state.pointer_down[0] = true; + TouchInput input; + input.x = mx; + input.y = my; + input.flags = TOUCH_DOWN; + input.id = 0; + NativeTouch(input); + } + break; + case SDL_BUTTON_WHEELUP: + { + KeyInput key; + key.deviceId = DEVICE_ID_DEFAULT; + key.keyCode = KEYCODE_EXT_MOUSEWHEEL_UP; + key.flags = KEY_DOWN; + NativeKey(key); + } + break; + case SDL_BUTTON_WHEELDOWN: + { + KeyInput key; + key.deviceId = DEVICE_ID_DEFAULT; + key.keyCode = KEYCODE_EXT_MOUSEWHEEL_DOWN; + key.flags = KEY_DOWN; + NativeKey(key); + } + break; } } else if (event.type == SDL_MOUSEMOTION) { if (input_state.pointer_down[0]) { @@ -573,17 +595,39 @@ int main(int argc, char *argv[]) { NativeTouch(input); } } else if (event.type == SDL_MOUSEBUTTONUP) { - if (event.button.button == SDL_BUTTON_LEFT) { - input_state.pointer_x[0] = mx; - input_state.pointer_y[0] = my; - input_state.pointer_down[0] = false; - //input_state.mouse_buttons_up = 1; - TouchInput input; - input.x = mx; - input.y = my; - input.flags = TOUCH_UP; - input.id = 0; - NativeTouch(input); + switch (event.button.button) { + case SDL_BUTTON_LEFT: + { + input_state.pointer_x[0] = mx; + input_state.pointer_y[0] = my; + input_state.pointer_down[0] = false; + //input_state.mouse_buttons_up = 1; + TouchInput input; + input.x = mx; + input.y = my; + input.flags = TOUCH_UP; + input.id = 0; + NativeTouch(input); + } + break; + case SDL_BUTTON_WHEELUP: + { + KeyInput key; + key.deviceId = DEVICE_ID_DEFAULT; + key.keyCode = KEYCODE_EXT_MOUSEWHEEL_UP; + key.flags = KEY_UP; + NativeKey(key); + } + break; + case SDL_BUTTON_WHEELDOWN: + { + KeyInput key; + key.deviceId = DEVICE_ID_DEFAULT; + key.keyCode = KEYCODE_EXT_MOUSEWHEEL_DOWN; + key.flags = KEY_UP; + NativeKey(key); + } + break; } } } diff --git a/input/keycodes.h b/input/keycodes.h index d90fcda983..369daae47e 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -217,6 +217,11 @@ typedef enum _keycode_t { // Extended keycodes, not available on Android KEYCODE_EXT_PIPE = 1001, // The key next to Z on euro 102-key keyboards. + KEYCODE_EXT_MOUSEBUTTON_1 = 1002, + KEYCODE_EXT_MOUSEBUTTON_2 = 1003, + KEYCODE_EXT_MOUSEBUTTON_3 = 1004, + KEYCODE_EXT_MOUSEWHEEL_UP = 1008, + KEYCODE_EXT_MOUSEWHEEL_DOWN = 1009 } keycode_t; diff --git a/ui/ui.h b/ui/ui.h index 0d39fc4c5f..9c8770ffd1 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -289,6 +289,10 @@ public: scrollY = 0.0f; inertiaY = 0.0f; } + + void scrollRelative(float delta) { + scrollY += delta; + } private: // TODO: Migrate to using these directly. void pointerDown(int pointer, float x, float y); From 28fb341cb2a43fbab66ac7c4baa3abaca7cbe7aa Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 8 Jul 2013 12:34:39 +0200 Subject: [PATCH 0512/1445] More mousewheel support --- base/PCMain.cpp | 4 ++-- input/input_state.h | 3 +++ input/keycodes.h | 1 - ui/ui_screen.cpp | 8 ++++++++ ui/ui_screen.h | 1 + ui/view.cpp | 5 +++++ ui/view.h | 4 ++++ ui/viewgroup.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ ui/viewgroup.h | 5 +++++ 9 files changed, 71 insertions(+), 3 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index c0411fd100..0f10e27518 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -567,7 +567,7 @@ int main(int argc, char *argv[]) { case SDL_BUTTON_WHEELUP: { KeyInput key; - key.deviceId = DEVICE_ID_DEFAULT; + key.deviceId = DEVICE_ID_MOUSE; key.keyCode = KEYCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_DOWN; NativeKey(key); @@ -576,7 +576,7 @@ int main(int argc, char *argv[]) { case SDL_BUTTON_WHEELDOWN: { KeyInput key; - key.deviceId = DEVICE_ID_DEFAULT; + key.deviceId = DEVICE_ID_MOUSE; key.keyCode = KEYCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_DOWN; NativeKey(key); diff --git a/input/input_state.h b/input/input_state.h index 32e196a1e2..63435d8676 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -18,6 +18,7 @@ enum { DEVICE_ID_DEFAULT = 0, // Old Android DEVICE_ID_KEYBOARD = 1, // PC keyboard, android keyboards + DEVICE_ID_MOUSE = 2, // PC mouse only (not touchscreen!) DEVICE_ID_PAD_0 = 10, // Generic joypads DEVICE_ID_X360_0 = 20, // XInput joypads DEVICE_ID_ACCELEROMETER = 30, @@ -137,10 +138,12 @@ struct TouchInput { }; #undef KEY_DOWN +#undef KEY_UP enum { KEY_DOWN = 1, KEY_UP = 2, + KEY_HASWHEELDELTA = 4, }; struct KeyInput { diff --git a/input/keycodes.h b/input/keycodes.h index 369daae47e..5611cacc2c 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -224,7 +224,6 @@ typedef enum _keycode_t { KEYCODE_EXT_MOUSEWHEEL_DOWN = 1009 } keycode_t; - enum AndroidJoystickAxis { // Field descriptor #15 I JOYSTICK_AXIS_X = 0, diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 8b913e8165..f3aeb597aa 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -41,6 +41,14 @@ void UIScreen::touch(const TouchInput &touch) { } } +void UIScreen::key(const KeyInput &key) { + if (root_) { + root_->Key(key); + } else { + ELOG("Tried to key without a view root"); + } +} + UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { screenManager()->finishDialog(this, DR_OK); return UI::EVENT_DONE; diff --git a/ui/ui_screen.h b/ui/ui_screen.h index ff5dab0255..ae4e86d7c7 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -11,6 +11,7 @@ public: virtual void update(InputState &input); virtual void render(); virtual void touch(const TouchInput &touch); + virtual void key(const KeyInput &touch); // Some useful default event handlers UI::EventReturn OnBack(UI::EventParams &e); diff --git a/ui/view.cpp b/ui/view.cpp index b85da47bcc..0902ea4812 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -154,6 +154,11 @@ void Clickable::Touch(const TouchInput &input) { } } +void Clickable::Key(const KeyInput &input) { + // TODO: Replace most of Update with this. +} + + void Clickable::Update(const InputState &input_state) { if (!HasFocus()) return; diff --git a/ui/view.h b/ui/view.h index ab9c5c2d9b..ee6a4c23b2 100644 --- a/ui/view.h +++ b/ui/view.h @@ -21,6 +21,7 @@ #include "math/math_util.h" #include "math/geom2d.h" +struct KeyInput; struct TouchInput; struct InputState; @@ -255,6 +256,7 @@ public: // Please note that Touch is called ENTIRELY asynchronously from drawing! // Can even be called on a different thread! This is to really minimize latency, and decouple // touch response from the frame rate. + virtual void Key(const KeyInput &input) = 0; virtual void Touch(const TouchInput &input) = 0; virtual void Update(const InputState &input_state) = 0; @@ -332,6 +334,7 @@ public: InertView(LayoutParams *layoutParams) : View(layoutParams) {} + virtual void Key(const KeyInput &input) {} virtual void Touch(const TouchInput &input) {} virtual bool CanBeFocused() const { return false; } virtual void Update(const InputState &input_state) {} @@ -344,6 +347,7 @@ public: Clickable(LayoutParams *layoutParams) : View(layoutParams), downCountDown_(0), dragging_(false), down_(false) {} + virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); virtual void Update(const InputState &input_state); diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 3d8f96170d..33fa15435a 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1,6 +1,7 @@ #include "base/display.h" #include "base/functional.h" #include "base/logging.h" +#include "input/keycodes.h" #include "ui/ui_context.h" #include "ui/view.h" #include "ui/viewgroup.h" @@ -44,6 +45,15 @@ void ViewGroup::Touch(const TouchInput &input) { } } +void ViewGroup::Key(const KeyInput &input) { + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + // TODO: If there is a transformation active, transform input coordinates accordingly. + if ((*iter)->GetVisibility() == V_VISIBLE) + (*iter)->Key(input); + } +} + + void ViewGroup::Draw(UIContext &dc) { for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. @@ -443,6 +453,19 @@ void ScrollView::Layout() { views_[0]->Layout(); } +void ScrollView::Key(const KeyInput &input) { + if (input.flags & KEY_DOWN) { + switch (input.keyCode) { + case KEYCODE_EXT_MOUSEWHEEL_UP: + ScrollRelative(-250); + break; + case KEYCODE_EXT_MOUSEWHEEL_DOWN: + ScrollRelative(250); + break; + } + } +} + void ScrollView::Touch(const TouchInput &input) { if ((input.flags & TOUCH_DOWN) && input.id == 0) { scrollStart_ = scrollPos_; @@ -508,8 +531,28 @@ bool ScrollView::SubviewFocused(View *view) { void ScrollView::ScrollTo(float newScrollPos) { scrollTarget_ = newScrollPos; scrollToTarget_ = true; + ClampScrollTarget(); } +void ScrollView::ScrollRelative(float distance) { + scrollTarget_ = scrollPos_ + distance; + scrollToTarget_ = true; + ClampScrollTarget(); +} + +void ScrollView::ClampScrollTarget() { + // Clamp scrollTarget. + if (scrollTarget_ < 0.0f) { + scrollTarget_ = 0.0f; + } + float childHeight = views_[0]->GetBounds().h; + float scrollMax = std::max(0.0f, childHeight - bounds_.h); + if (scrollTarget_ > scrollMax) { + scrollTarget_ = scrollMax; + } +} + + void ScrollView::Update(const InputState &input_state) { ViewGroup::Update(input_state); if (scrollToTarget_) { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 2d460b266d..0321aef12e 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -21,6 +21,7 @@ public: virtual ~ViewGroup(); // Pass through external events to children. + virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); // By default, a container will layout to its own bounds. @@ -171,16 +172,20 @@ public: void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); + void Key(const KeyInput &input); void Touch(const TouchInput &input); void Draw(UIContext &dc); void ScrollTo(float newScrollPos); + void ScrollRelative(float distance); void Update(const InputState &input_state); // Override so that we can scroll to the active one after moving the focus. virtual bool SubviewFocused(View *view); private: + void ClampScrollTarget(); + GestureDetector gesture_; Orientation orientation_; float scrollPos_; From 94a163ca3521ca4aa122d2685262a2dc4a432a48 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 8 Jul 2013 17:16:59 +0200 Subject: [PATCH 0513/1445] Rename JNI method to match the Java side. Fixes gamepad related crash on Android. --- android/app-android.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index c1ad471908..48e55b2f2e 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -429,7 +429,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_beginJoystickEvent( // mutex lock? } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickEvent( +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickAxis( JNIEnv *env, jclass, jint deviceId, jint axisId, jfloat value) { switch (axisId) { case JOYSTICK_AXIS_X: From 611faf62031f9431a595e5d72dcc9aaa4bab4468 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 8 Jul 2013 17:39:29 +0200 Subject: [PATCH 0514/1445] Comment out annoying motionevent logging --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 022304a753..e620a819d4 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -354,7 +354,7 @@ public class NativeActivity extends Activity { @Override @TargetApi(12) public boolean onGenericMotionEvent(MotionEvent event) { - Log.d(TAG, "onGenericMotionEvent: " + event); + // Log.d(TAG, "onGenericMotionEvent: " + event); if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) { if (Build.VERSION.SDK_INT >= 12) { InputDeviceState state = getInputDeviceState(event); From f4bc31be4e08b588d102568df37cb39cd847b628 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 8 Jul 2013 17:45:58 +0200 Subject: [PATCH 0515/1445] Typo fix --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index e620a819d4..d2e6b327af 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -386,7 +386,7 @@ public class NativeActivity extends Activity { if (event.isAltPressed()) { NativeApp.keyDown(0, 1004); // special custom keycode } else if (NativeApp.isAtTopLevel()) { - Log.i(TAG, "IsAtTopLevel returned false."); + Log.i(TAG, "IsAtTopLevel returned true."); return super.onKeyUp(keyCode, event); } else { NativeApp.keyDown(0, keyCode); @@ -427,7 +427,7 @@ public class NativeActivity extends Activity { if (event.isAltPressed()) { NativeApp.keyUp(0, 1004); // special custom keycode } else if (NativeApp.isAtTopLevel()) { - Log.i(TAG, "IsAtTopLevel returned false."); + Log.i(TAG, "IsAtTopLevel returned true."); return super.onKeyUp(keyCode, event); } else { NativeApp.keyUp(0, keyCode); From 3fe63c3171d5d5f23541b249f5f5acbe1b1ef874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 9 Jul 2013 16:33:05 +0200 Subject: [PATCH 0516/1445] Make mouse buttons mappable keys --- base/PCMain.cpp | 16 ++++++++++++++++ input/input_state.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 0f10e27518..4d5b330748 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -562,6 +562,14 @@ int main(int argc, char *argv[]) { input.flags = TOUCH_DOWN; input.id = 0; NativeTouch(input); + KeyInput key(DEVICE_ID_MOUSE, KEYCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); + NativeKey(key); + } + break; + case SDL_BUTTON_RIGHT: + { + KeyInput key(DEVICE_ID_MOUSE, KEYCODE_EXT_MOUSEBUTTON_2, KEY_DOWN); + NativeKey(key); } break; case SDL_BUTTON_WHEELUP: @@ -608,6 +616,14 @@ int main(int argc, char *argv[]) { input.flags = TOUCH_UP; input.id = 0; NativeTouch(input); + KeyInput key(DEVICE_ID_MOUSE, KEYCODE_EXT_MOUSEBUTTON_1, KEY_UP); + NativeKey(key); + } + break; + case SDL_BUTTON_RIGHT: + { + KeyInput key(DEVICE_ID_MOUSE, KEYCODE_EXT_MOUSEBUTTON_2, KEY_UP); + NativeKey(key); } break; case SDL_BUTTON_WHEELUP: diff --git a/input/input_state.h b/input/input_state.h index 63435d8676..1b2ebc84cb 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -147,6 +147,8 @@ enum { }; struct KeyInput { + KeyInput() {} + KeyInput(int devId, int code, int fl) : deviceId(devId), keyCode(code), flags(fl) {} int deviceId; int keyCode; // Android keycodes are the canonical keycodes, everyone else map to them. int flags; From 9e2723b7816c7b8eac1b07a2dc4224b12ebc88a0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 8 Jul 2013 10:04:20 +1000 Subject: [PATCH 0517/1445] Rearrange dirs for NativeInit --- base/BlackberryMain.cpp | 2 +- base/QtMain.cpp | 8 ++++++-- base/QtMain.h | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 8f8ee40e47..4e1e41e8d3 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -192,7 +192,7 @@ void BlackberryMain::startMain(int argc, char *argv[]) { net::Init(); startDisplays(); - NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "/accounts/1000/shared/misc/", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "app/native/assets/", "BADCOFFEE"); NativeInitGraphics(); screen_request_events(screen_cxt); navigator_request_events(0); diff --git a/base/QtMain.cpp b/base/QtMain.cpp index bd12b67818..9a13a0209b 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -67,17 +67,21 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) net::Init(); #ifdef __SYMBIAN32__ char* savegame_dir = "E:/PPSSPP/"; + char* assets_dir = "E:/PPSSPP/"; #elif defined(BLACKBERRY) - char* savegame_dir = "data/"; + char* savegame_dir = "/accounts/1000/shared/misc/"; + char* assets_dir = "app/native/assets/"; #elif defined(MEEGO_EDITION_HARMATTAN) char* savegame_dir = "/home/user/MyDocs/PPSSPP/"; QDir myDocs("/home/user/MyDocs/"); if (!myDocs.exists("PPSSPP")) myDocs.mkdir("PPSSPP"); + char* assets_dir = "/opt/PPSSPP/"; #else char* savegame_dir = "./"; + char* assets_dir = "./"; #endif - NativeInit(argc, (const char **)argv, savegame_dir, QDir::tempPath().toStdString().c_str(), "BADCOFFEE"); + NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); #if !defined(Q_WS_X11) || defined(ARM) MainUI w(dpi_scale); diff --git a/base/QtMain.h b/base/QtMain.h index 73eda8676b..90365da1b0 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -18,6 +18,7 @@ QTM_USE_NAMESPACE #include "base/timeutil.h" #include "file/zip_read.h" #include "input/input_state.h" +#include "input/keycodes.h" #include "base/NativeApp.h" #include "net/resolve.h" #include "display.h" From ffcdf5ea800ba02ef0be4bd4f7f385d1815da83a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 10 Jul 2013 21:14:35 +0200 Subject: [PATCH 0518/1445] Ouya keycodes --- input/keycodes.h | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/input/keycodes.h b/input/keycodes.h index 5611cacc2c..07fef97740 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -212,7 +212,23 @@ typedef enum _keycode_t { KEYCODE_BUTTON_15 = 202, KEYCODE_BUTTON_16 = 203, - + // Ouya buttons. Just here for reference, they map straight to regular android buttons + // and will be mapped the same way. + KEYCODE_OUYA_BUTTON_A = 97, + KEYCODE_OUYA_BUTTON_DPAD_DOWN = 20, + KEYCODE_OUYA_BUTTON_DPAD_LEFT = 21, + KEYCODE_OUYA_BUTTON_DPAD_RIGHT = 22, + KEYCODE_OUYA_BUTTON_DPAD_UP = 19, + KEYCODE_OUYA_BUTTON_L1 = 102, + KEYCODE_OUYA_BUTTON_L2 = 104, + KEYCODE_OUYA_BUTTON_L3 = 106, + KEYCODE_OUYA_BUTTON_MENU = 82, + KEYCODE_OUYA_BUTTON_O = 96, + KEYCODE_OUYA_BUTTON_R1 = 103, + KEYCODE_OUYA_BUTTON_R2 = 105, + KEYCODE_OUYA_BUTTON_R3 = 107, + KEYCODE_OUYA_BUTTON_U = 99, + KEYCODE_OUYA_BUTTON_Y = 100, // Extended keycodes, not available on Android KEYCODE_EXT_PIPE = 1001, // The key next to Z on euro 102-key keyboards. @@ -252,4 +268,13 @@ enum AndroidJoystickAxis { JOYSTICK_AXIS_BRAKE = 23, JOYSTICK_AXIS_DISTANCE = 24, JOYSTICK_AXIS_TILT = 25, + + // Ouya axises. Just here for reference, they map straight to regular android axises + // and will be mapped the same way. + JOYSTICK_OUYA_AXIS_L2 = 17, + JOYSTICK_OUYA_AXIS_LS_X = 0, + JOYSTICK_OUYA_AXIS_LS_Y = 1, + JOYSTICK_OUYA_AXIS_R2 = 18, + JOYSTICK_OUYA_AXIS_RS_X = 11, + JOYSTICK_OUYA_AXIS_RS_Y = 14, }; From bd93cd2f1e02fbd25696a1ea21720d4fb3f48280 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 10 Jul 2013 21:58:35 +0200 Subject: [PATCH 0519/1445] Fix scrollview bugs (distance, flicker at end) --- ui/viewgroup.cpp | 36 ++++++++++++++++-------------------- ui/viewgroup.h | 2 +- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 33fa15435a..1657a5cbd4 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -476,21 +476,16 @@ void ScrollView::Touch(const TouchInput &input) { if (gesture_.IsGestureActive(GESTURE_DRAG_VERTICAL)) { float info[4]; gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info); - scrollPos_ = scrollStart_ - info[0]; + + float pos = scrollStart_ - info[0]; + ClampScrollPos(pos); + scrollPos_ = pos; + scrollTarget_ = pos; + scrollToTarget_ = false; } if (!(input.flags & TOUCH_DOWN) || bounds_.Contains(input.x, input.y)) ViewGroup::Touch(input2); - - // Clamp scrollPos_. TODO: flinging, bouncing, etc. - if (scrollPos_ < 0.0f) { - scrollPos_ = 0.0f; - } - float childHeight = views_[0]->GetBounds().h; - float scrollMax = std::max(0.0f, childHeight - bounds_.h); - if (scrollPos_ > scrollMax) { - scrollPos_ = scrollMax; - } } void ScrollView::Draw(UIContext &dc) { @@ -531,24 +526,25 @@ bool ScrollView::SubviewFocused(View *view) { void ScrollView::ScrollTo(float newScrollPos) { scrollTarget_ = newScrollPos; scrollToTarget_ = true; - ClampScrollTarget(); + ClampScrollPos(scrollTarget_); } void ScrollView::ScrollRelative(float distance) { scrollTarget_ = scrollPos_ + distance; scrollToTarget_ = true; - ClampScrollTarget(); + ClampScrollPos(scrollTarget_); } -void ScrollView::ClampScrollTarget() { +void ScrollView::ClampScrollPos(float &pos) { // Clamp scrollTarget. - if (scrollTarget_ < 0.0f) { - scrollTarget_ = 0.0f; - } float childHeight = views_[0]->GetBounds().h; float scrollMax = std::max(0.0f, childHeight - bounds_.h); - if (scrollTarget_ > scrollMax) { - scrollTarget_ = scrollMax; + + if (pos < 0.0f) { + pos = 0.0f; + } + if (pos > scrollMax) { + pos = scrollMax; } } @@ -579,7 +575,7 @@ void GridLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver if (!numColumns) numColumns = 1; int numRows = (int)(views_.size() + (numColumns - 1)) / numColumns; - float estimatedHeight = settings_.rowHeight * numRows; + float estimatedHeight = (settings_.rowHeight + settings_.spacing) * numRows; MeasureBySpec(layoutParams_->height, estimatedHeight, vert, &measuredHeight_); } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 0321aef12e..7bdf0fadd6 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -184,7 +184,7 @@ public: virtual bool SubviewFocused(View *view); private: - void ClampScrollTarget(); + void ClampScrollPos(float &pos); GestureDetector gesture_; Orientation orientation_; From ca7eb305e44b75307ff904f73e4e946f5a9f1395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 11 Jul 2013 14:08:58 +0200 Subject: [PATCH 0520/1445] Comment out annoying logging --- file/zip_read.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index cb210b703f..4d2664d442 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -241,7 +241,7 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { - ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); + // ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); if (data) return data; From ed1f13a33fdb5a210d35ac57a4cfc59b0a67a1a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 14 Jul 2013 13:51:30 +0200 Subject: [PATCH 0521/1445] Initial SDL gamepad support --- base/PCMain.cpp | 147 +++++++++++++++++++++++++++++++++++++----------- ui/viewgroup.h | 4 +- 2 files changed, 117 insertions(+), 34 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 4d5b330748..3ddec3e08a 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -189,6 +189,8 @@ void EGL_Close() { g_eglSurface = NULL; g_eglContext = NULL; } +#else +SDL_Joystick *joy = NULL; #endif // Simple implementations of System functions @@ -300,12 +302,12 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { if ((ljoy)||(rjoy)) { SDL_JoystickUpdate(); if (ljoy) { - input->pad_lstick_x = max(min(SDL_JoystickGetAxis(ljoy, 0) / 32000.0f, 1.0f, -1.0f); - input->pad_lstick_y = max(min(-SDL_JoystickGetAxis(ljoy, 1) / 32000.0f, 1.0f, -1.0f); + input->pad_lstick_x = max(min(SDL_JoystickGetAxis(ljoy, 0) / 32000.0f, 1.0f), -1.0f); + input->pad_lstick_y = max(min(-SDL_JoystickGetAxis(ljoy, 1) / 32000.0f, 1.0f), -1.0f); } if (rjoy) { - input->pad_rstick_x = max(min(SDL_JoystickGetAxis(rjoy, 0) / 32000.0f, 1.0f, -1.0f); - input->pad_rstick_y = max(min(SDL_JoystickGetAxis(rjoy, 1) / 32000.0f, 1.0f, -1.0f); + input->pad_rstick_x = max(min(SDL_JoystickGetAxis(rjoy, 0) / 32000.0f, 1.0f), -1.0f); + input->pad_rstick_y = max(min(SDL_JoystickGetAxis(rjoy, 1) / 32000.0f, 1.0f), -1.0f); } } #else @@ -352,11 +354,13 @@ int main(int argc, char *argv[]) { if (tabletenv) { tablet = atoi(tabletenv) ? true : false; } - if (ipad) aspect43 = true; - + if (ipad) { + aspect43 = true; + } + bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); - + // Change these to temporarily test other resolutions. aspect43 = false; tablet = false; @@ -418,7 +422,7 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); - if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, + if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, #ifdef USING_GLES2 SDL_SWSURFACE | SDL_FULLSCREEN #else @@ -509,19 +513,52 @@ int main(int argc, char *argv[]) { // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); + int numjoys = SDL_NumJoysticks(); #ifdef PANDORA // Joysticks init, we the nubs if setup as Joystick - int numjoys = SDL_NumJoysticks(); - if (numjoys>0) - { - ljoy=SDL_JoystickOpen(0); - if (numjoys>1) rjoy=SDL_JoystickOpen(1); + if (numjoys > 0) { + ljoy = SDL_JoystickOpen(0); + if (numjoys > 1) + rjoy = SDL_JoystickOpen(1); } enable_runfast(); // VFPv2 RunFast +#else + SDL_JoystickEventState(SDL_ENABLE); + if (numjoys > 0) { + joy = SDL_JoystickOpen(0); + } #endif + // This is just a standard mapping that matches the X360 controller on MacOSX. Names will probably be all wrong + // on other controllers. + std::map SDLJoyButtonMap; + SDLJoyButtonMap[0] = KEYCODE_DPAD_UP; + SDLJoyButtonMap[1] = KEYCODE_DPAD_DOWN; + SDLJoyButtonMap[2] = KEYCODE_DPAD_LEFT; + SDLJoyButtonMap[3] = KEYCODE_DPAD_RIGHT; + SDLJoyButtonMap[4] = KEYCODE_BUTTON_START; + SDLJoyButtonMap[5] = KEYCODE_BUTTON_SELECT; + SDLJoyButtonMap[6] = KEYCODE_BUTTON_THUMBL; + SDLJoyButtonMap[7] = KEYCODE_BUTTON_THUMBL; + SDLJoyButtonMap[8] = KEYCODE_BUTTON_L1; + SDLJoyButtonMap[9] = KEYCODE_BUTTON_R1; + SDLJoyButtonMap[10] = KEYCODE_BACK; + SDLJoyButtonMap[11] = KEYCODE_BUTTON_A; + SDLJoyButtonMap[12] = KEYCODE_BUTTON_B; + SDLJoyButtonMap[13] = KEYCODE_BUTTON_X; + SDLJoyButtonMap[14] = KEYCODE_BUTTON_Y; + + std::map SDLJoyAxisMap; + SDLJoyAxisMap[0] = JOYSTICK_AXIS_X; + SDLJoyAxisMap[1] = JOYSTICK_AXIS_Y; + SDLJoyAxisMap[2] = JOYSTICK_AXIS_Z; + SDLJoyAxisMap[3] = JOYSTICK_AXIS_RZ; + SDLJoyAxisMap[4] = JOYSTICK_AXIS_LTRIGGER; + SDLJoyAxisMap[5] = JOYSTICK_AXIS_RTRIGGER; + int framecount = 0; - float t = 0, lastT = 0; + float t = 0; + float lastT = 0; while (true) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; @@ -532,23 +569,66 @@ int main(int argc, char *argv[]) { float mx = event.motion.x * dp_xscale; float my = event.motion.y * dp_yscale; - if (event.type == SDL_QUIT) { + switch (event.type) { + case SDL_QUIT: quitRequested = 1; - } else if (event.type == SDL_KEYDOWN) { - int k = event.key.keysym.sym; - KeyInput key; - key.flags = KEY_DOWN; - key.keyCode = KeyMapRawSDLtoNative.find(k)->second; - key.deviceId = DEVICE_ID_KEYBOARD; - NativeKey(key); - } else if (event.type == SDL_KEYUP) { - int k = event.key.keysym.sym; - KeyInput key; - key.flags = KEY_UP; - key.keyCode = KeyMapRawSDLtoNative.find(k)->second; - key.deviceId = DEVICE_ID_KEYBOARD; - NativeKey(key); - } else if (event.type == SDL_MOUSEBUTTONDOWN) { + break; + + case SDL_JOYAXISMOTION: + { + AxisInput axis; + axis.axisId = SDLJoyAxisMap[event.jaxis.axis]; + // 1.2 to try to approximate the PSP's clamped rectangular range. + axis.value = 1.2 * event.jaxis.value / 32767.0f; + if (axis.value > 1.0f) axis.value = 1.0f; + if (axis.value < -1.0f) axis.value = -1.0f; + axis.deviceId = DEVICE_ID_PAD_0; + axis.flags = 0; + NativeAxis(axis); + break; + } + + case SDL_JOYBUTTONDOWN: + { + KeyInput key; + key.flags = KEY_DOWN; + key.keyCode = SDLJoyButtonMap[event.jbutton.button]; + key.deviceId = DEVICE_ID_PAD_0; + NativeKey(key); + break; + } + + case SDL_JOYBUTTONUP: + { + KeyInput key; + key.flags = KEY_UP; + key.keyCode = SDLJoyButtonMap[event.jbutton.button]; + key.deviceId = DEVICE_ID_PAD_0; + NativeKey(key); + break; + } + + case SDL_KEYDOWN: + { + int k = event.key.keysym.sym; + KeyInput key; + key.flags = KEY_DOWN; + key.keyCode = KeyMapRawSDLtoNative.find(k)->second; + key.deviceId = DEVICE_ID_KEYBOARD; + NativeKey(key); + break; + } + case SDL_KEYUP: + { + int k = event.key.keysym.sym; + KeyInput key; + key.flags = KEY_UP; + key.keyCode = KeyMapRawSDLtoNative.find(k)->second; + key.deviceId = DEVICE_ID_KEYBOARD; + NativeKey(key); + break; + } + case SDL_MOUSEBUTTONDOWN: switch (event.button.button) { case SDL_BUTTON_LEFT: { @@ -591,7 +671,8 @@ int main(int argc, char *argv[]) { } break; } - } else if (event.type == SDL_MOUSEMOTION) { + break; + case SDL_MOUSEMOTION: if (input_state.pointer_down[0]) { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; @@ -602,7 +683,8 @@ int main(int argc, char *argv[]) { input.id = 0; NativeTouch(input); } - } else if (event.type == SDL_MOUSEBUTTONUP) { + break; + case SDL_MOUSEBUTTONUP: switch (event.button.button) { case SDL_BUTTON_LEFT: { @@ -645,6 +727,7 @@ int main(int argc, char *argv[]) { } break; } + break; } } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 7bdf0fadd6..a7756522fd 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -203,7 +203,7 @@ class TabHolder : public LinearLayout { public: TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0) : LinearLayout(Opposite(orientation), layoutParams), - orientation_(orientation), stripSize_(stripSize), currentTab_(0) { + orientation_(orientation), stripSize_(stripSize), currentTab_(0) { tabStrip_ = new LinearLayout(orientation, new LinearLayoutParams(stripSize, WRAP_CONTENT)); Add(tabStrip_); } @@ -278,4 +278,4 @@ private: void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root); void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root); -} // namespace UI \ No newline at end of file +} // namespace UI From 9ad07c3db082a88816bddff7218835208ee94adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 14 Jul 2013 14:34:24 +0200 Subject: [PATCH 0522/1445] Change SDL button mapping to (seem to) match DInput buttons --- base/PCMain.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 3ddec3e08a..71dceb5d41 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -536,17 +536,17 @@ int main(int argc, char *argv[]) { SDLJoyButtonMap[1] = KEYCODE_DPAD_DOWN; SDLJoyButtonMap[2] = KEYCODE_DPAD_LEFT; SDLJoyButtonMap[3] = KEYCODE_DPAD_RIGHT; - SDLJoyButtonMap[4] = KEYCODE_BUTTON_START; - SDLJoyButtonMap[5] = KEYCODE_BUTTON_SELECT; - SDLJoyButtonMap[6] = KEYCODE_BUTTON_THUMBL; - SDLJoyButtonMap[7] = KEYCODE_BUTTON_THUMBL; - SDLJoyButtonMap[8] = KEYCODE_BUTTON_L1; - SDLJoyButtonMap[9] = KEYCODE_BUTTON_R1; + SDLJoyButtonMap[4] = KEYCODE_BUTTON_10; + SDLJoyButtonMap[5] = KEYCODE_BUTTON_9; + SDLJoyButtonMap[6] = KEYCODE_BUTTON_5; + SDLJoyButtonMap[7] = KEYCODE_BUTTON_6; + SDLJoyButtonMap[8] = KEYCODE_BUTTON_7; + SDLJoyButtonMap[9] = KEYCODE_BUTTON_8; SDLJoyButtonMap[10] = KEYCODE_BACK; - SDLJoyButtonMap[11] = KEYCODE_BUTTON_A; - SDLJoyButtonMap[12] = KEYCODE_BUTTON_B; - SDLJoyButtonMap[13] = KEYCODE_BUTTON_X; - SDLJoyButtonMap[14] = KEYCODE_BUTTON_Y; + SDLJoyButtonMap[11] = KEYCODE_BUTTON_2; + SDLJoyButtonMap[12] = KEYCODE_BUTTON_3; + SDLJoyButtonMap[13] = KEYCODE_BUTTON_4; + SDLJoyButtonMap[14] = KEYCODE_BUTTON_1; std::map SDLJoyAxisMap; SDLJoyAxisMap[0] = JOYSTICK_AXIS_X; From 693944a0a5b07bd4ef4690168c03fefefc475ac5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Jul 2013 14:53:06 +0200 Subject: [PATCH 0523/1445] SDL: Fix silly dpi scaling bug --- base/PCMain.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 71dceb5d41..84c75d021d 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -492,8 +492,7 @@ int main(int argc, char *argv[]) { float dp_xscale = (float)dp_xres / pixel_xres; float dp_yscale = (float)dp_yres / pixel_yres; - g_dpi_scale = pixel_xres / dp_xres; - + g_dpi_scale = dp_xres / (float)pixel_xres; printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); From 7151e4c06e5d782ef7da8e853f57ddbbb339ea60 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Jul 2013 17:37:16 +0200 Subject: [PATCH 0524/1445] Generalize the code mapping android key events into pad button bits, add support for keys needed to navigate UI. --- android/app-android.cpp | 61 ++++---------------------------------- base/BlackberryMain.cpp | 6 ++-- base/PCMain.cpp | 2 ++ input/input_state.cpp | 65 +++++++++++++++++++++++++++++++++++++++-- input/input_state.h | 32 +++++++++++++++----- ui/ui.cpp | 2 +- 6 files changed, 99 insertions(+), 69 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 48e55b2f2e..93863c0325 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -33,8 +33,6 @@ std::string frameCommandParam; const bool extraLog = true; -static uint32_t pad_buttons_async_set; -static uint32_t pad_buttons_async_clear; static float left_joystick_x_async; static float left_joystick_y_async; static float right_joystick_x_async; @@ -42,8 +40,6 @@ static float right_joystick_y_async; static float hat_joystick_x_async; static float hat_joystick_y_async; -static uint32_t pad_buttons_down; - int optimalFramesPerBuffer = 0; int optimalSampleRate = 0; @@ -142,9 +138,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init renderer_inited = false; first_lost = true; - pad_buttons_down = 0; - pad_buttons_async_set = 0; - pad_buttons_async_clear = 0; + g_buttonTracker.Reset(); left_joystick_x_async = 0; left_joystick_y_async = 0; @@ -262,20 +256,13 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN // TODO: Look into if these locks are a perf loss { lock_guard guard(input_state.lock); - pad_buttons_down |= pad_buttons_async_set; - pad_buttons_down &= ~pad_buttons_async_clear; - input_state.pad_buttons = pad_buttons_down; - - UpdateInputState(&input_state); - } - - { - lock_guard guard(input_state.lock); input_state.pad_lstick_x = left_joystick_x_async; input_state.pad_lstick_y = left_joystick_y_async; input_state.pad_rstick_x = right_joystick_x_async; input_state.pad_rstick_y = right_joystick_y_async; + + UpdateInputState(&input_state); } NativeUpdate(input_state); @@ -367,15 +354,6 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch // ELOG("Touch Exit %i", pointerId); } -static inline void AsyncDown(int padbutton) { - pad_buttons_async_set |= padbutton; - pad_buttons_async_clear &= ~padbutton; -} - -static inline void AsyncUp(int padbutton) { - pad_buttons_async_set &= ~padbutton; - pad_buttons_async_clear |= padbutton; -} extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint deviceId, jint key) { KeyInput keyInput; @@ -383,19 +361,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jcl keyInput.keyCode = key; keyInput.flags = KEY_DOWN; NativeKey(keyInput); - - // Pad mapping - switch (key) { - case KEYCODE_BACK: AsyncDown(PAD_BUTTON_BACK); break; // Back - case KEYCODE_MENU: AsyncDown(PAD_BUTTON_MENU); break; // Menu - case KEYCODE_BUTTON_CROSS_PS3: - AsyncDown(PAD_BUTTON_A); - break; - case KEYCODE_BUTTON_CIRCLE_PS3: - AsyncDown(PAD_BUTTON_B); - break; - default: break; - } + g_buttonTracker.Process(keyInput); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint deviceId, jint key) { @@ -404,24 +370,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclas keyInput.keyCode = key; keyInput.flags = KEY_UP; NativeKey(keyInput); - - // Pad mapping - switch (key) { - case KEYCODE_BACK: - AsyncUp(PAD_BUTTON_BACK); - break; // Back - case KEYCODE_MENU: - AsyncUp(PAD_BUTTON_MENU); - break; // Menu - case KEYCODE_BUTTON_CROSS_PS3: - AsyncUp(PAD_BUTTON_A); - break; - case KEYCODE_BUTTON_CIRCLE_PS3: - AsyncUp(PAD_BUTTON_B); - break; - default: - break; - } + g_buttonTracker.Process(keyInput); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_beginJoystickEvent( diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 4e1e41e8d3..c4633abf98 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -51,7 +51,7 @@ void LaunchEmail(const char *email_address) InputState input_state; -// Input +// Input - urgh, these may collide with the android keycodes when we bring in input/keycodes.h const unsigned int buttonMappings[18] = { KEYCODE_K, //Cross KEYCODE_L, //Circle @@ -131,7 +131,7 @@ void BlackberryMain::handleInput(screen_event_t screen_event) if (value == buttonMappings[b] & 0xFF) { if (flags & KEY_DOWN) pad_buttons |= (1<second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); + g_buttonTracker.Process(key); break; } case SDL_KEYUP: @@ -625,6 +626,7 @@ int main(int argc, char *argv[]) { key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); + g_buttonTracker.Process(key); break; } case SDL_MOUSEBUTTONDOWN: diff --git a/input/input_state.cpp b/input/input_state.cpp index 51a262c88d..9f1e8798db 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -1,5 +1,5 @@ -#include "input_state.h" -#include +#include "input/input_state.h" +#include "input/keycodes.h" const char *GetDeviceName(int deviceId) { switch (deviceId) { @@ -12,3 +12,64 @@ const char *GetDeviceName(int deviceId) { return "unknown"; } } + +// Default pad mapping to button bits. Used for UI and stuff that doesn't use PPSSPP's key mapping system. +int MapPadButtonFixed(int keycode) { + switch (keycode) { + case KEYCODE_BACK: return PAD_BUTTON_BACK; // Back + case KEYCODE_MENU: return PAD_BUTTON_MENU; // Menu + + case KEYCODE_Z: + case KEYCODE_SPACE: + case KEYCODE_BUTTON_1: + case KEYCODE_BUTTON_A: // same as KEYCODE_OUYA_BUTTON_O and KEYCODE_BUTTON_CROSS_PS3 + return PAD_BUTTON_A; + + case KEYCODE_ESCAPE: + case KEYCODE_BUTTON_2: + case KEYCODE_BUTTON_B: // same as KEYCODE_OUYA_BUTTON_A and KEYCODE_BUTTON_CIRCLE_PS3: + return PAD_BUTTON_B; + + case KEYCODE_DPAD_LEFT: return PAD_BUTTON_LEFT; + case KEYCODE_DPAD_RIGHT: return PAD_BUTTON_RIGHT; + case KEYCODE_DPAD_UP: return PAD_BUTTON_UP; + case KEYCODE_DPAD_DOWN: return PAD_BUTTON_DOWN; + + default: + return 0; + } +} + +void ButtonTracker::Update(InputState &input_state) { + pad_buttons_ |= pad_buttons_async_set; + pad_buttons_ &= ~pad_buttons_async_clear; + input_state.pad_buttons = pad_buttons_; +} + +void ButtonTracker::Process(const KeyInput &input) { + int btn = MapPadButtonFixed(input.keyCode); + if (btn == 0) + return; + + // For now, use a fixed mapping. Good enough for the basics on most platforms. + if (input.flags & KEY_DOWN) { + pad_buttons_async_set |= btn; + pad_buttons_async_clear &= ~btn; + } + if (input.flags & KEY_UP) { + pad_buttons_async_set &= ~btn; + pad_buttons_async_clear |= btn; + } +} + +ButtonTracker g_buttonTracker; + +void UpdateInputState(InputState *input) { + g_buttonTracker.Update(*input); + input->pad_buttons_down = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_buttons; + input->pad_buttons_up = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_last_buttons; +} + +void EndInputState(InputState *input) { + input->pad_last_buttons = input->pad_buttons; +} \ No newline at end of file diff --git a/input/input_state.h b/input/input_state.h index 1b2ebc84cb..735d81e0f5 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -109,14 +109,8 @@ private: DISALLOW_COPY_AND_ASSIGN(InputState); }; -inline void UpdateInputState(InputState *input) { - input->pad_buttons_down = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_buttons; - input->pad_buttons_up = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_last_buttons; -} - -inline void EndInputState(InputState *input) { - input->pad_last_buttons = input->pad_buttons; -} +void UpdateInputState(InputState *input); +void EndInputState(InputState *input); enum { TOUCH_MOVE = 1, @@ -160,3 +154,25 @@ struct AxisInput { float value; int flags; }; + + +class ButtonTracker { +public: + ButtonTracker() { Reset(); } + void Reset() { + pad_buttons_ = 0; + pad_buttons_async_set = 0; + pad_buttons_async_clear = 0; + } + void Process(const KeyInput &input); + void Update(InputState &input_state); + uint32_t GetPadButtons() const { return pad_buttons_; } + +private: + uint32_t pad_buttons_; + uint32_t pad_buttons_async_set; + uint32_t pad_buttons_async_clear; +}; + +// Platforms should call g_buttonTracker.Process(). +extern ButtonTracker g_buttonTracker; \ No newline at end of file diff --git a/ui/ui.cpp b/ui/ui.cpp index 9fd6769a06..80a1f5166c 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -294,7 +294,7 @@ int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w y += txOffset * 2; } ui_draw2d.DrawImage4Grid(drop_shadow, x - dropsize, y, x+w + dropsize, y+h+dropsize*1.5, - alphaMul(color,0.5f), 1.0f); + blackAlpha(0.5f), 1.0f); ui_draw2d.Flush(true); } From 7aa8aabc3dfcc0ba3cca6e858d24dac5f1a7addf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Jul 2013 17:51:12 +0200 Subject: [PATCH 0525/1445] Focus fixes. --- ui/view.cpp | 23 ++++++++++++++++++++++- ui/view.h | 24 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/ui/view.cpp b/ui/view.cpp index 0902ea4812..5fa3969662 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -52,7 +52,13 @@ View *GetFocusedView() { } void SetFocusedView(View *view) { + if (focusedView) { + focusedView->FocusChanged(FF_LOSTFOCUS); + } focusedView = view; + if (focusedView) { + focusedView->FocusChanged(FF_GOTFOCUS); + } } void EnableFocusMovement(bool enable) { @@ -123,6 +129,13 @@ void Clickable::Click() { OnClick.Trigger(e); }; +void Clickable::FocusChanged(int focusFlags) { + if (focusFlags & FF_LOSTFOCUS) { + down_ = false; + dragging_ = false; + } +} + void Clickable::Touch(const TouchInput &input) { if (!enabled_) { dragging_ = false; @@ -176,8 +189,8 @@ void Clickable::Update(const InputState &input_state) { e.v = this; OnClick.Trigger(e); } - down_ = false; } + OnClick.Update(); } Item::Item(LayoutParams *layoutParams) : InertView(layoutParams) { @@ -249,6 +262,14 @@ void CheckBox::Draw(UIContext &dc) { dc.Draw()->DrawImage(image, bounds_.x2() - 4, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); } +void Slider::Draw(UIContext &dc) { + // TODO +} + +void Slider::Touch(UIContext &dc) { + // TODO +} + void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const { dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); } diff --git a/ui/view.h b/ui/view.h index ee6a4c23b2..76f8156494 100644 --- a/ui/view.h +++ b/ui/view.h @@ -149,6 +149,11 @@ enum EventReturn { EVENT_SKIPPED, }; +enum FocusFlags { + FF_LOSTFOCUS = 1, + FF_GOTFOCUS = 2 +}; + class ViewGroup; void Fill(UIContext &dc, const Bounds &bounds, const Drawable &drawable); @@ -260,6 +265,8 @@ public: virtual void Touch(const TouchInput &input) = 0; virtual void Update(const InputState &input_state) = 0; + virtual void FocusChanged(int focusFlags) {} + void Move(Bounds bounds) { bounds_ = bounds; } @@ -351,6 +358,8 @@ public: virtual void Touch(const TouchInput &input); virtual void Update(const InputState &input_state); + virtual void FocusChanged(int focusFlags); + Event OnClick; protected: @@ -444,6 +453,21 @@ private: std::string rightText_; }; +// Not really using the click action, but the background lightup works well. +class Slider : public ClickableItem { +public: + Slider(const std::string &text, int min, int max, int *value, LayoutParams *layoutParams = 0) + : ClickableItem(layoutParams), text_(text), min_(min), max_(max), value_(value) {} + + virtual void Draw(UIContext &dc); + virtual void Touch(UIContext &dc); + +private: + std::string text_; + int min_, max_; + int *value_; +}; + class ItemHeader : public Item { public: ItemHeader(const std::string &text, LayoutParams *layoutParams = 0) From d34495a23fefaf6630c3e8a7603853a9ee96e46f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Jul 2013 18:03:34 +0200 Subject: [PATCH 0526/1445] Cleanup --- data/compression.h | 4 ++-- ui/view.cpp | 9 --------- ui/view.h | 15 --------------- 3 files changed, 2 insertions(+), 26 deletions(-) diff --git a/data/compression.h b/data/compression.h index 2199c5591e..e37ff85794 100644 --- a/data/compression.h +++ b/data/compression.h @@ -1,8 +1,8 @@ #pragma once -#include +#include -bool compress_string(const std::string& str, std::string *dest, int compressionlevel = Z_BEST_COMPRESSION); +bool compress_string(const std::string& str, std::string *dest, int compressionlevel = 9); bool decompress_string(const std::string& str, std::string *dest); diff --git a/ui/view.cpp b/ui/view.cpp index 5fa3969662..b63a544e63 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -190,7 +190,6 @@ void Clickable::Update(const InputState &input_state) { OnClick.Trigger(e); } } - OnClick.Update(); } Item::Item(LayoutParams *layoutParams) : InertView(layoutParams) { @@ -262,14 +261,6 @@ void CheckBox::Draw(UIContext &dc) { dc.Draw()->DrawImage(image, bounds_.x2() - 4, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); } -void Slider::Draw(UIContext &dc) { - // TODO -} - -void Slider::Touch(UIContext &dc) { - // TODO -} - void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const { dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); } diff --git a/ui/view.h b/ui/view.h index 76f8156494..9117e93689 100644 --- a/ui/view.h +++ b/ui/view.h @@ -453,21 +453,6 @@ private: std::string rightText_; }; -// Not really using the click action, but the background lightup works well. -class Slider : public ClickableItem { -public: - Slider(const std::string &text, int min, int max, int *value, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), min_(min), max_(max), value_(value) {} - - virtual void Draw(UIContext &dc); - virtual void Touch(UIContext &dc); - -private: - std::string text_; - int min_, max_; - int *value_; -}; - class ItemHeader : public Item { public: ItemHeader(const std::string &text, LayoutParams *layoutParams = 0) From b0181dfe8fe1294d10bf9ceee399072dbabd7360 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Jul 2013 18:45:00 +0200 Subject: [PATCH 0527/1445] Warning fix --- net/url.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/url.h b/net/url.h index a5c3b51c35..734ef0ccd2 100644 --- a/net/url.h +++ b/net/url.h @@ -17,7 +17,7 @@ struct UrlEncoder UrlEncoder() : paramCount(0) { data.reserve(256); - }; + } void Add(const std::string &key, const std::string &value) { @@ -106,7 +106,7 @@ struct UrlEncoder class Url { public: - Url(const std::string url) : url_(url), valid_(false) { + Url(const std::string url) : valid_(false), url_(url) { Split(); } From 70a5970d4551c62989e5354fb5218cc257bbc56d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Jul 2013 19:56:36 +0200 Subject: [PATCH 0528/1445] Make tabs look a bit more like tabs (color sticks). Also saner focus movement. --- ui/view.cpp | 52 +++++++++++++++++--- ui/view.h | 32 +++++++++++- ui/viewgroup.cpp | 123 ++++++++++++++++++++++++++++++----------------- ui/viewgroup.h | 30 +++++++++--- 4 files changed, 176 insertions(+), 61 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index b63a544e63..935523dea1 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -100,13 +100,14 @@ void Event::Trigger(EventParams &e) { } // Call this from UI thread -void Event::Dispatch(EventParams &e) { +EventReturn Event::Dispatch(EventParams &e) { for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { if ((iter->func)(e) == UI::EVENT_DONE) { // Event is handled, stop looping immediately. This event might even have gotten deleted. - return; + return UI::EVENT_DONE; } } + return UI::EVENT_SKIPPED; } void View::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { @@ -123,6 +124,19 @@ void View::GetContentDimensions(const UIContext &dc, float &w, float &h) const { h = 10.0f; } +Point View::GetFocusPosition(FocusDirection dir) { + switch (dir) { + case FOCUS_LEFT: return Point(bounds_.x, bounds_.centerY()); + case FOCUS_RIGHT: return Point(bounds_.x2(), bounds_.centerY()); + case FOCUS_UP: return Point(bounds_.centerX(), bounds_.y); + case FOCUS_DOWN: return Point(bounds_.centerX(), bounds_.y2()); + + default: + return bounds_.Center(); + } +} + + void Clickable::Click() { UI::EventParams e; e.v = this; @@ -160,9 +174,9 @@ void Clickable::Touch(const TouchInput &input) { if (input.flags & TOUCH_UP) { if ((input.flags & TOUCH_CANCEL) == 0 && dragging_ && bounds_.Contains(input.x, input.y)) { Click(); - } - downCountDown_ = 0; + } down_ = false; + downCountDown_ = 0; dragging_ = false; } } @@ -185,13 +199,37 @@ void Clickable::Update(const InputState &input_state) { down_ = true; } else if (input_state.pad_buttons_up & PAD_BUTTON_A) { if (down_) { - UI::EventParams e; - e.v = this; - OnClick.Trigger(e); + Click(); } } } +void StickyChoice::Touch(const TouchInput &input) { + dragging_ = false; + if (!enabled_) { + down_ = false; + return; + } + + if (input.flags & TOUCH_DOWN) { + if (bounds_.Contains(input.x, input.y)) { + if (IsFocusMovementEnabled()) + SetFocusedView(this); + down_ = true; + Click(); + } + } +} + +void StickyChoice::Key(const KeyInput &input) { +} + +void StickyChoice::FocusChanged(int focusFlags) { + // Override Clickable's FocusChanged to do nothing. +} + + + Item::Item(LayoutParams *layoutParams) : InertView(layoutParams) { layoutParams_->width = FILL_PARENT; layoutParams_->height = ITEM_HEIGHT; diff --git a/ui/view.h b/ui/view.h index 9117e93689..5d1e6514d3 100644 --- a/ui/view.h +++ b/ui/view.h @@ -138,6 +138,17 @@ inline Orientation Opposite(Orientation o) { if (o == ORIENT_HORIZONTAL) return ORIENT_VERTICAL; else return ORIENT_HORIZONTAL; } +inline FocusDirection Opposite(FocusDirection d) { + switch (d) { + case FOCUS_UP: return FOCUS_DOWN; + case FOCUS_DOWN: return FOCUS_UP; + case FOCUS_LEFT: return FOCUS_RIGHT; + case FOCUS_RIGHT: return FOCUS_LEFT; + case FOCUS_PREV: return FOCUS_NEXT; + case FOCUS_NEXT: return FOCUS_PREV; + } +} + enum MeasureSpecType { UNSPECIFIED, EXACTLY, @@ -193,7 +204,7 @@ public: // Call this from input thread or whatever, it doesn't matter void Trigger(EventParams &e); // Call this from UI thread - void Dispatch(EventParams &e); + EventReturn Dispatch(EventParams &e); // This is suggested for use in most cases. Autobinds, allowing for neat syntax. template @@ -256,7 +267,7 @@ public: layoutParams_.reset(new LayoutParams()); } - virtual ~View() {} + virtual ~View() { if (HasFocus()) SetFocusedView(0); } // Please note that Touch is called ENTIRELY asynchronously from drawing! // Can even be called on a different thread! This is to really minimize latency, and decouple @@ -314,6 +325,8 @@ public: // Fake RTTI virtual bool IsViewGroup() const { return false; } + Point GetFocusPosition(FocusDirection dir); + protected: // Inputs to layout scoped_ptr layoutParams_; @@ -441,6 +454,21 @@ private: std::string smallText_; }; +// Different key handling. +class StickyChoice : public Choice { +public: + StickyChoice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) + : Choice(text, smallText, layoutParams) {} + + virtual void Key(const KeyInput &input); + virtual void Touch(const TouchInput &input); + virtual void FocusChanged(int focusFlags); + + void Press() { down_ = true; dragging_ = false; } + void Release() { down_ = false; dragging_ = false; } + bool IsDown() { return down_; } +}; + class InfoItem : public Item { public: InfoItem(const std::string &text, const std::string &rightText, LayoutParams *layoutParams = 0) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 1657a5cbd4..1a0a3b6fc2 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -102,8 +102,13 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio if (destination->GetVisibility() != V_VISIBLE) return 0.0f; - float dx = destination->GetBounds().centerX() - origin->GetBounds().centerX(); - float dy = destination->GetBounds().centerY() - origin->GetBounds().centerY(); + // Point originPos = origin->GetBounds().Center(); + // Point destPos = destination->GetBounds().Center(); + Point originPos = origin->GetFocusPosition(direction); + Point destPos = destination->GetFocusPosition(Opposite(direction)); + + float dx = destPos.x - originPos.x; + float dy = destPos.y - originPos.y; float distance = sqrtf(dx*dx+dy*dy); float dirX = dx / distance; @@ -111,24 +116,28 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio switch (direction) { case FOCUS_LEFT: - if (dirX > 0.0f) return 0.0f; - if (fabsf(dirY) > fabsf(dirX)) return 0.0f; + distance = -dirX / distance; + //if (dirX > 0.0f) return 0.0f; + //if (fabsf(dirY) > fabsf(dirX)) return 0.0f; break; case FOCUS_UP: - if (dirY > 0.0f) return 0.0f; - if (fabsf(dirX) > fabsf(dirY)) return 0.0f; + distance = -dirY / distance; + //if (dirY > 0.0f) return 0.0f; + //if (fabsf(dirX) > fabsf(dirY)) return 0.0f; break; case FOCUS_RIGHT: - if (dirX < 0.0f) return 0.0f; - if (fabsf(dirY) > fabsf(dirX)) return 0.0f; + //if (dirX < 0.0f) return 0.0f; + //if (fabsf(dirY) > fabsf(dirX)) return 0.0f; + distance = dirX / distance; break; case FOCUS_DOWN: - if (dirY < 0.0f) return 0.0f; - if (fabsf(dirX) > fabsf(dirY)) return 0.0f; + //if (dirY < 0.0f) return 0.0f; + //if (fabsf(dirX) > fabsf(dirY)) return 0.0f; + distance = dirY / distance; break; } - return 100.0f / distance; + return distance; } @@ -674,15 +683,69 @@ void GridLayout::Layout() { EventReturn TabHolder::OnTabClick(EventParams &e) { tabs_[currentTab_]->SetVisibility(V_GONE); - for (int i = 0; i < tabChoices_.size(); i++) { - if (e.v == tabChoices_[i]) { - currentTab_ = i; - } - } + currentTab_ = e.a; tabs_[currentTab_]->SetVisibility(V_VISIBLE); return EVENT_DONE; } +void ChoiceStrip::AddChoice(const std::string &title) { + StickyChoice *c = new StickyChoice(title, "", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + c->OnClick.Handle(this, &ChoiceStrip::OnChoiceClick); + Add(c); + if (selected_ == views_.size() - 1) + c->Press(); +} + +EventReturn ChoiceStrip::OnChoiceClick(EventParams &e) { + // Unstick the other choices that weren't clicked. + for (size_t i = 0; i < views_.size(); i++) { + if (views_[i] != e.v) + static_cast(views_[i])->Release(); + else + selected_ = i; + } + + EventParams e2; + e.a = selected_; + // Dispatch immediately (we're already on the UI thread as we're in an event handler). + return OnChoice.Dispatch(e); +} + +void ChoiceStrip::SetSelection(int sel) { + if (selected_ < views_.size()) + static_cast(views_[selected_])->Release(); + selected_ = sel; + if (selected_ < views_.size()) + static_cast(views_[selected_])->Press(); +} + +ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) + : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a) { + // Let's not be clever yet, we'll just create them all up front and add them all in. + for (int i = 0; i < adaptor_->GetNumItems(); i++) { + View * v = Add(adaptor_->CreateItemView(i)); + adaptor_->AddEventCallback(v, std::bind(&ListView::OnItemCallback, this, i, placeholder::_1)); + } +} + +EventReturn ListView::OnItemCallback(int num, EventParams &e) { + EventParams ev; + ev.v = e.v; + ev.a = num; + OnChoice.Trigger(ev); + return EVENT_DONE; +} + +View *ChoiceListAdaptor::CreateItemView(int index) { + return new Choice(items_[index]); +} + +bool ChoiceListAdaptor::AddEventCallback(View *view, std::function callback) { + Choice *choice = (Choice *)view; + choice->OnClick.Add(callback); + return EVENT_DONE; +} + void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { Bounds rootBounds; rootBounds.x = 0; @@ -723,32 +786,4 @@ void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { root->Update(input_state); DispatchEvents(); } - -ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) - : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a) { - // Let's not be clever yet, we'll just create them all up front and add them all in. - for (int i = 0; i < adaptor_->GetNumItems(); i++) { - View * v = Add(adaptor_->CreateItemView(i)); - adaptor_->AddEventCallback(v, std::bind(&ListView::OnItemCallback, this, i, placeholder::_1)); - } -} - -EventReturn ListView::OnItemCallback(int num, EventParams &e) { - EventParams ev; - ev.v = e.v; - ev.a = num; - OnChoice.Trigger(ev); - return EVENT_DONE; -} - -View *ChoiceListAdaptor::CreateItemView(int index) { - return new Choice(items_[index]); -} - -bool ChoiceListAdaptor::AddEventCallback(View *view, std::function callback) { - Choice *choice = (Choice *)view; - choice->OnClick.Add(callback); - return EVENT_DONE; -} - } // namespace UI \ No newline at end of file diff --git a/ui/viewgroup.h b/ui/viewgroup.h index a7756522fd..478de7ce18 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -199,23 +199,39 @@ class ViewPager : public ScrollView { public: }; + +class ChoiceStrip : public LinearLayout { +public: + ChoiceStrip(Orientation orientation, LayoutParams *layoutParams = 0) + : LinearLayout(orientation, layoutParams), selected_(0) {} + + void AddChoice(const std::string &title); + int GetSelection() const { return selected_; } + void SetSelection(int sel); + Event OnChoice; + +private: + EventReturn OnChoiceClick(EventParams &e); + + int selected_; +}; + + class TabHolder : public LinearLayout { public: TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0) : LinearLayout(Opposite(orientation), layoutParams), orientation_(orientation), stripSize_(stripSize), currentTab_(0) { - tabStrip_ = new LinearLayout(orientation, new LinearLayoutParams(stripSize, WRAP_CONTENT)); + tabStrip_ = new ChoiceStrip(orientation, new LinearLayoutParams(stripSize, WRAP_CONTENT)); Add(tabStrip_); + tabStrip_->OnChoice.Handle(this, &TabHolder::OnTabClick); } template T *AddTab(const std::string &title, T *tabContents) { tabContents->ReplaceLayoutParams(new LinearLayoutParams(1.0f)); - tabTitles_.push_back(title); tabs_.push_back(tabContents); - Choice *choice = new Choice(title); - tabStrip_->Add(choice)->OnClick.Handle(this, &TabHolder::OnTabClick); - tabChoices_.push_back(choice); + tabStrip_->AddChoice(title); Add(tabContents); if (tabs_.size() > 1) tabContents->SetVisibility(V_GONE); @@ -231,13 +247,11 @@ public: private: EventReturn OnTabClick(EventParams &e); - ViewGroup *tabStrip_; + ChoiceStrip *tabStrip_; Orientation orientation_; float stripSize_; int currentTab_; - std::vector tabTitles_; - std::vector tabChoices_; std::vector tabs_; }; From 46c9fd38199263700ca721366923863d0d2cc025 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Jul 2013 20:29:50 +0200 Subject: [PATCH 0529/1445] Can now merge the result from the buttontracker. --- input/input_state.cpp | 9 +++++---- input/input_state.h | 4 ++-- ui/viewgroup.cpp | 12 +++++------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/input/input_state.cpp b/input/input_state.cpp index 9f1e8798db..f8bb1144ae 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -40,10 +40,10 @@ int MapPadButtonFixed(int keycode) { } } -void ButtonTracker::Update(InputState &input_state) { +uint32_t ButtonTracker::Update() { pad_buttons_ |= pad_buttons_async_set; pad_buttons_ &= ~pad_buttons_async_clear; - input_state.pad_buttons = pad_buttons_; + return pad_buttons_; } void ButtonTracker::Process(const KeyInput &input) { @@ -64,8 +64,9 @@ void ButtonTracker::Process(const KeyInput &input) { ButtonTracker g_buttonTracker; -void UpdateInputState(InputState *input) { - g_buttonTracker.Update(*input); +void UpdateInputState(InputState *input, bool merge) { + uint32_t btns = g_buttonTracker.Update(); + input->pad_buttons = merge ? (input->pad_buttons | btns) : btns; input->pad_buttons_down = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_buttons; input->pad_buttons_up = (input->pad_last_buttons ^ input->pad_buttons) & input->pad_last_buttons; } diff --git a/input/input_state.h b/input/input_state.h index 735d81e0f5..fd414b3646 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -109,7 +109,7 @@ private: DISALLOW_COPY_AND_ASSIGN(InputState); }; -void UpdateInputState(InputState *input); +void UpdateInputState(InputState *input, bool merge = false); void EndInputState(InputState *input); enum { @@ -165,7 +165,7 @@ public: pad_buttons_async_clear = 0; } void Process(const KeyInput &input); - void Update(InputState &input_state); + uint32_t Update(); uint32_t GetPadButtons() const { return pad_buttons_; } private: diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 1a0a3b6fc2..eee28a923e 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -102,8 +102,6 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio if (destination->GetVisibility() != V_VISIBLE) return 0.0f; - // Point originPos = origin->GetBounds().Center(); - // Point destPos = destination->GetBounds().Center(); Point originPos = origin->GetFocusPosition(direction); Point destPos = destination->GetFocusPosition(Opposite(direction)); @@ -116,24 +114,24 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio switch (direction) { case FOCUS_LEFT: - distance = -dirX / distance; + distance = -dirX / sqrtf(distance); //if (dirX > 0.0f) return 0.0f; //if (fabsf(dirY) > fabsf(dirX)) return 0.0f; break; case FOCUS_UP: - distance = -dirY / distance; + distance = -dirY / sqrtf(distance); //if (dirY > 0.0f) return 0.0f; //if (fabsf(dirX) > fabsf(dirY)) return 0.0f; break; case FOCUS_RIGHT: //if (dirX < 0.0f) return 0.0f; //if (fabsf(dirY) > fabsf(dirX)) return 0.0f; - distance = dirX / distance; + distance = dirX / sqrtf(distance); break; case FOCUS_DOWN: //if (dirY < 0.0f) return 0.0f; //if (fabsf(dirX) > fabsf(dirY)) return 0.0f; - distance = dirY / distance; + distance = dirY / sqrtf(distance); break; } @@ -524,7 +522,7 @@ bool ScrollView::SubviewFocused(View *view) { ScrollTo(scrollPos_ + vBounds.y2() - bounds_.y2()); } if (vBounds.y < bounds_.y) { - ScrollTo(scrollPos_ + (vBounds.y - bounds_.y - 30)); + ScrollTo(scrollPos_ + (vBounds.y - bounds_.y)); } break; } From a7b92d63d6a51f41b3fe8c89fee0bd5f85b8f4a6 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 16 Jul 2013 00:25:08 +0200 Subject: [PATCH 0530/1445] NewUI work (popup lists) --- ui/screen.cpp | 1 + ui/ui_screen.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++ ui/ui_screen.h | 38 ++++++++++++++++++++++++++++++ ui/view.cpp | 4 ++++ ui/view.h | 8 ++++--- ui/viewgroup.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++----- ui/viewgroup.h | 40 +++++++++++++++++++++++++++++--- 7 files changed, 192 insertions(+), 12 deletions(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index a79128d9ce..f763eba600 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -73,6 +73,7 @@ void ScreenManager::render() { if (!stack_.empty()) { switch (stack_.back().flags) { case LAYER_SIDEMENU: + case LAYER_TRANSPARENT: if (stack_.size() == 1) { ELOG("Can't have sidemenu over nothing"); break; diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index f3aeb597aa..bc0a94e371 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -53,3 +53,56 @@ UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { screenManager()->finishDialog(this, DR_OK); return UI::EVENT_DONE; } + + +PopupScreen::PopupScreen(const std::string &title) + : title_(title) {} + +void PopupScreen::CreateViews() { + using namespace UI; + + root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); + ViewGroup *box = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(30, 30, 30, 30)); + root_->Add(box); + box->SetBG(UI::Drawable(0xFF303030)); + box->SetHasDropShadow(true); + + View *title = new ItemHeader(title_); + box->Add(title); + + CreatePopupContents(box); + + // And the two buttons at the bottom. + ViewGroup *buttonRow = new LinearLayout(ORIENT_HORIZONTAL); + buttonRow->Add(new Button("OK", new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); + buttonRow->Add(new Button("Cancel", new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); + box->Add(buttonRow); +} + +UI::EventReturn PopupScreen::OnOK(UI::EventParams &e) { + // callback_(true); + OnCompleted(); + screenManager()->finishDialog(this, DR_OK); + return UI::EVENT_DONE; +} + +UI::EventReturn PopupScreen::OnCancel(UI::EventParams &e) { + // callback_(false); + screenManager()->finishDialog(this, DR_CANCEL); + return UI::EVENT_DONE; +} + + +void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { + using namespace UI; + + listView_ = parent->Add(new ListView(&adaptor_, new LinearLayoutParams(1.0))); + listView_->OnChoice.Handle(this, &ListPopupScreen::OnListChoice); +} + +UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) { + adaptor_.SetSelected(e.a); + OnChoice.Dispatch(e); + return UI::EVENT_DONE; +} + diff --git a/ui/ui_screen.h b/ui/ui_screen.h index ae4e86d7c7..6cf1b3a126 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -27,3 +27,41 @@ protected: private: bool recreateViews_; }; + +class PopupScreen : public UIScreen { +public: + PopupScreen(const std::string &title); + + virtual void CreatePopupContents(UI::ViewGroup *parent) = 0; + virtual void CreateViews(); + virtual bool isTransparent() { return true; } + +protected: + virtual void OnCompleted() {} + +private: + UI::EventReturn OnOK(UI::EventParams &e); + UI::EventReturn OnCancel(UI::EventParams &e); + + std::string title_; +}; + +class ListPopupScreen : public PopupScreen { +public: + ListPopupScreen(const std::string &title) : PopupScreen(title) {} + ListPopupScreen(const std::string &title, const std::vector &items, int selected) + : PopupScreen(title), adaptor_(items, selected) { + } + + UI::Event OnChoice; + +protected: + void CreatePopupContents(UI::ViewGroup *parent); + UI::StringVectorListAdaptor adaptor_; + UI::ListView *listView_; + +private: + UI::EventReturn OnListChoice(UI::EventParams &e); + + std::function callback_; +}; diff --git a/ui/view.cpp b/ui/view.cpp index 935523dea1..55664285b3 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -272,6 +272,10 @@ void Choice::Draw(UIContext &dc) { int paddingX = 8; dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); + + if (selected_) { + dc.Draw()->DrawImage(dc.theme->checkOn, bounds_.x2() - 40, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + } // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); } diff --git a/ui/view.h b/ui/view.h index 5d1e6514d3..2107f6c9ec 100644 --- a/ui/view.h +++ b/ui/view.h @@ -147,6 +147,7 @@ inline FocusDirection Opposite(FocusDirection d) { case FOCUS_PREV: return FOCUS_NEXT; case FOCUS_NEXT: return FOCUS_PREV; } + return d; } enum MeasureSpecType { @@ -443,8 +444,8 @@ public: // Use to trigger something or open a submenu screen. class Choice : public ClickableItem { public: - Choice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(smallText) {} + Choice(const std::string &text, const std::string &smallText = "", bool selected = false, LayoutParams *layoutParams = 0) + : ClickableItem(layoutParams), text_(text), smallText_(smallText), selected_(selected) {} virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); @@ -452,13 +453,14 @@ public: private: std::string text_; std::string smallText_; + bool selected_; }; // Different key handling. class StickyChoice : public Choice { public: StickyChoice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) - : Choice(text, smallText, layoutParams) {} + : Choice(text, smallText, false, layoutParams) {} virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index eee28a923e..3280a4825c 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -30,6 +30,10 @@ void ApplyGravity(const Bounds outer, const Margins &margins, float w, float h, ViewGroup::~ViewGroup() { // Tear down the contents recursively. + Clear(); +} + +void ViewGroup::Clear() { for (size_t i = 0; i < views_.size(); i++) { delete views_[i]; views_[i] = 0; @@ -55,6 +59,13 @@ void ViewGroup::Key(const KeyInput &input) { void ViewGroup::Draw(UIContext &dc) { + if (hasDropShadow_) { + // Darken things behind. + dc.FillRect(UI::Drawable(0x60000000), Bounds(0,0,dp_xres, dp_yres)); + // dc.Draw()->DrawImage4Grid(dc.theme->dropShadow, ) + } + + dc.FillRect(bg_, bounds_); for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. if ((*iter)->GetVisibility() == V_VISIBLE) { @@ -499,6 +510,18 @@ void ScrollView::Draw(UIContext &dc) { dc.PushScissor(bounds_); views_[0]->Draw(dc); dc.PopScissor(); + + float childHeight = views_[0]->GetBounds().h; + float scrollMax = std::max(0.0f, childHeight - bounds_.h); + + float ratio = bounds_.h / views_[0]->GetBounds().h; + if (ratio < 1.0f && scrollMax > 0.0f) { + float bobHeight = ratio * bounds_.h; + float bobOffset = (scrollPos_ / scrollMax) * (bounds_.h - bobHeight); + + Bounds bob(bounds_.x2() - 10, bounds_.y + bobOffset, 5, bobHeight); + dc.FillRect(Drawable(0x80FFFFFF), bob); + } } bool ScrollView::SubviewFocused(View *view) { @@ -690,17 +713,18 @@ void ChoiceStrip::AddChoice(const std::string &title) { StickyChoice *c = new StickyChoice(title, "", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)); c->OnClick.Handle(this, &ChoiceStrip::OnChoiceClick); Add(c); - if (selected_ == views_.size() - 1) + if (selected_ == (int)views_.size() - 1) c->Press(); } EventReturn ChoiceStrip::OnChoiceClick(EventParams &e) { // Unstick the other choices that weren't clicked. - for (size_t i = 0; i < views_.size(); i++) { - if (views_[i] != e.v) + for (int i = 0; i < (int)views_.size(); i++) { + if (views_[i] != e.v) { static_cast(views_[i])->Release(); - else + } else { selected_ = i; + } } EventParams e2; @@ -719,18 +743,31 @@ void ChoiceStrip::SetSelection(int sel) { ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a) { + + linLayout_ = new LinearLayout(ORIENT_VERTICAL); + Add(linLayout_); + CreateAllItems(); +} + +void ListView::CreateAllItems() { + linLayout_->Clear(); // Let's not be clever yet, we'll just create them all up front and add them all in. for (int i = 0; i < adaptor_->GetNumItems(); i++) { - View * v = Add(adaptor_->CreateItemView(i)); + View * v = linLayout_->Add(adaptor_->CreateItemView(i)); adaptor_->AddEventCallback(v, std::bind(&ListView::OnItemCallback, this, i, placeholder::_1)); } } EventReturn ListView::OnItemCallback(int num, EventParams &e) { EventParams ev; - ev.v = e.v; + ev.v = 0; ev.a = num; + adaptor_->SetSelected(num); + View *focused = GetFocusedView(); OnChoice.Trigger(ev); + CreateAllItems(); + if (focused) + SetFocusedView(linLayout_->GetViewByIndex(num)); return EVENT_DONE; } @@ -744,6 +781,17 @@ bool ChoiceListAdaptor::AddEventCallback(View *view, std::function callback) { + Choice *choice = (Choice *)view; + choice->OnClick.Add(callback); + return EVENT_DONE; +} + void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { Bounds rootBounds; rootBounds.x = 0; diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 478de7ce18..f009802cb6 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -17,7 +17,7 @@ struct NeighborResult { class ViewGroup : public View { public: - ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams) {} + ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams), hasDropShadow_(false) {} virtual ~ViewGroup(); // Pass through external events to children. @@ -48,8 +48,17 @@ public: virtual bool CanBeFocused() const { return false; } virtual bool IsViewGroup() const { return true; } + virtual void SetBG(const Drawable &bg) { bg_ = bg; } + + virtual void Clear(); + View *GetViewByIndex(int index) { return views_[index]; } + + void SetHasDropShadow(bool has) { hasDropShadow_ = has; } + protected: std::vector views_; + Drawable bg_; + bool hasDropShadow_; }; // A frame layout contains a single child view (normally). @@ -262,9 +271,12 @@ public: virtual View *CreateItemView(int index) = 0; virtual int GetNumItems() = 0; virtual bool AddEventCallback(View *view, std::function callback) { return false; } + virtual std::string GetTitle(int index) { return ""; } + virtual void SetSelected(int sel) { } + virtual int GetSelected() { return -1; } }; -class ChoiceListAdaptor { +class ChoiceListAdaptor : public ListAdaptor { public: ChoiceListAdaptor(const char *items[], int numItems) : items_(items), numItems_(numItems) {} virtual View *CreateItemView(int index); @@ -276,17 +288,39 @@ private: int numItems_; }; + +// The "selected" item is what was previously selected (optional). This items will be drawn differently. +class StringVectorListAdaptor : public ListAdaptor { +public: + StringVectorListAdaptor() : selected_(-1) {} + StringVectorListAdaptor(const std::vector &items, int selected = -1) : items_(items), selected_(selected) {} + virtual View *CreateItemView(int index); + virtual int GetNumItems() { return (int)items_.size(); } + virtual bool AddEventCallback(View *view, std::function callback); + void SetSelected(int sel) { selected_ = sel; } + virtual std::string GetTitle(int index) { return items_[index]; } + virtual int GetSelected() { return selected_; } + +private: + std::vector items_; + int selected_; +}; + // A list view is a scroll view with autogenerated items. // In the future, it might be smart and load/unload items as they go, but currently not. class ListView : public ScrollView { public: - ListView(ListAdaptor *a, LayoutParams *layoutParams); + ListView(ListAdaptor *a, LayoutParams *layoutParams = 0); + int GetSelected() { return adaptor_->GetSelected(); } + Event OnChoice; private: + void CreateAllItems(); EventReturn OnItemCallback(int num, EventParams &e); ListAdaptor *adaptor_; + LinearLayout *linLayout_; }; void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root); From 8559d298f86338c779dee368249edc7087d8dd46 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 16 Jul 2013 22:49:57 +0200 Subject: [PATCH 0531/1445] Android: Make preparations to let the app survive an activity shutdown. Lets us deal with orientation change natively. --- android/app-android.cpp | 49 +++++-- .../libnative/NativeActivity.java | 128 ++++++++++++------ .../henrikrydgard/libnative/NativeApp.java | 7 +- .../libnative/NativeRenderer.java | 5 +- file/fd_util.cpp | 4 +- gfx_es2/glsl_program.cpp | 3 - 6 files changed, 135 insertions(+), 61 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 93863c0325..e318d4199a 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -95,6 +95,7 @@ InputState input_state; static bool renderer_inited = false; static bool first_lost = true; static bool use_opensl_audio = false; +static std::string library_path; std::string GetJavaString(JNIEnv *env, jstring jstr) { @@ -153,7 +154,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init std::string externalDir = GetJavaString(env, jexternalDir); std::string user_data_path = GetJavaString(env, jdataDir) + "/"; - std::string library_path = GetJavaString(env, jlibraryDir) + "/"; + library_path = GetJavaString(env, jlibraryDir) + "/"; std::string installID = GetJavaString(env, jinstallID); ILOG("NativeApp.init(): External storage path: %s", externalDir.c_str()); @@ -176,14 +177,27 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); use_opensl_audio = juseNativeAudio; + ILOG("NativeApp.init() -- end"); +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioInit(JNIEnv *, jclass) { + ILOG("NativeApp.audioInit() -- begin"); if (use_opensl_audio) { // TODO: PPSSPP doesn't support 48khz yet so let's not use that yet. ILOG("Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: 44100", optimalFramesPerBuffer, optimalSampleRate); optimalSampleRate = 44100; AndroidAudio_Init(&NativeMix, library_path, optimalFramesPerBuffer, optimalSampleRate); } - ILOG("NativeApp.init() -- end"); -} + ILOG("NativeApp.audioShutdown() -- end"); +} + +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioShutdown(JNIEnv *, jclass) { + ILOG("NativeApp.audioShutdown() -- begin"); + if (use_opensl_audio) { + AndroidAudio_Shutdown(); + } + ILOG("NativeApp.audioShutdown() -- end"); +} extern "C" void Java_com_henrikrydgard_libnative_NativeApp_resume(JNIEnv *, jclass) { ILOG("NativeApp.resume() - resuming audio"); @@ -193,22 +207,15 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_resume(JNIEnv *, jcla } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclass) { - ILOG("NativeApp.pause() - pausing audio"); + ILOG("NativeApp.pause() - begin"); if (use_opensl_audio) { AndroidAudio_Pause(); } - ILOG("NativeApp.pause() - paused audio"); + ILOG("NativeApp.pause() - end"); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { ILOG("NativeApp.shutdown() -- begin"); - if (use_opensl_audio) { - AndroidAudio_Shutdown(); - } - if (renderer_inited) { - NativeShutdownGraphics(); - renderer_inited = false; - } NativeShutdown(); ILOG("VFSShutdown."); VFSShutdown(); @@ -244,6 +251,16 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIE ILOG("MethodID: %i", (int)postCommand); } +extern "C" void Java_com_henrikrydgard_libnative_NativeApp_resized + (JNIEnv *env, jclass, jint xxres, jint yyres) { + pixel_xres = xxres; + pixel_yres = yyres; + dp_xres = pixel_xres * g_dpi_scale; + dp_yres = pixel_yres * g_dpi_scale; + dp_xscale = (float)dp_xres / pixel_xres; + dp_yscale = (float)dp_yres / pixel_yres; +} + extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { ILOG("NativeApp.displayResize(%i, %i)", w, h); // TODO: Move some of the logic from displayInit here? @@ -294,6 +311,14 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN } } +extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayShutdown(JNIEnv *env, jobject obj) { + if (renderer_inited) { + NativeShutdownGraphics(); + renderer_inited = false; + } +} + + // This path is not used if OpenSL ES is available. extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { // Too spammy diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index d2e6b327af..3ed6537871 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -22,6 +22,7 @@ import android.content.pm.ConfigurationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; +import android.graphics.Point; import android.media.AudioManager; import android.net.Uri; import android.opengl.GLSurfaceView; @@ -84,9 +85,14 @@ public class NativeActivity extends Activity { // Adjust these as necessary private static String TAG = "NativeActivity"; + + // Allows us to skip a lot of initialization on secondary calls to onCreate. + private static boolean initialized = false; + // Graphics and audio interfaces private GLSurfaceView mGLSurfaceView; private NativeAudioPlayer audioPlayer; + private NativeRenderer nativeRenderer; boolean useOpenSL = false; @@ -123,9 +129,24 @@ public class NativeActivity extends Activity { return libdir; } + @TargetApi(13) + void GetScreenSizeHC(Point size) { + WindowManager w = getWindowManager(); + w.getDefaultDisplay().getSize(size); + } - @Override - public void onCreate(Bundle savedInstanceState) { + void GetScreenSize(Point size) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + GetScreenSizeHC(size); + } else { + WindowManager w = getWindowManager(); + Display d = w.getDefaultDisplay(); + size.x = d.getWidth(); + size.y = d.getHeight(); + } + } + + public void Initialize() { if (Build.VERSION.SDK_INT >= 9) { // Native OpenSL is available. Let's use it! useOpenSL = true; @@ -135,14 +156,13 @@ public class NativeActivity extends Activity { detectOptimalAudioSettings(); } + /* if (NativeApp.isLandscape()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - } - super.onCreate(savedInstanceState); + }*/ Log.i(TAG, "onCreate"); - installID = Installation.id(this); // Get system information ApplicationInfo appInfo = null; PackageManager packMgmr = getPackageManager(); @@ -158,10 +178,11 @@ public class NativeActivity extends Activity { Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); @SuppressWarnings("deprecation") int scrPixelFormat = display.getPixelFormat(); - @SuppressWarnings("deprecation") - int scrWidth = display.getWidth(); - @SuppressWarnings("deprecation") - int scrHeight = display.getHeight(); + Point size = new Point(); + GetScreenSize(size); + int scrWidth = size.x; + int scrHeight = size.y; + float scrRefreshRate = display.getRefreshRate(); String externalStorageDir = sdcard.getAbsolutePath(); String dataDir = this.getFilesDir().getAbsolutePath(); @@ -174,14 +195,9 @@ public class NativeActivity extends Activity { // INIT! NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); NativeApp.init(scrWidth, scrHeight, dpi, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); + Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat); - // Keep the screen bright - very annoying if it goes dark when tilting away - Window window = this.getWindow(); - window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - setVolumeControlStream(AudioManager.STREAM_MUSIC); - Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat); - - // Initialize Graphics + // Initialize Graphics if (!detectOpenGLES20()) { Log.i(TAG, "OpenGL ES 2.0 NOT detected."); @@ -189,16 +205,6 @@ public class NativeActivity extends Activity { Log.i(TAG, "OpenGL ES 2.0 detected."); } - mGLSurfaceView = new NativeGLView(this); - mGLSurfaceView.setRenderer(new NativeRenderer(this)); - setContentView(mGLSurfaceView); - if (!useOpenSL) - audioPlayer = new NativeAudioPlayer(); - - if (Build.VERSION.SDK_INT >= 14) { - darkenOnScreenButtons(); - } - /* editText = new EditText(this); editText.setText("Hello world"); @@ -207,8 +213,57 @@ public class NativeActivity extends Activity { */ // inputBox("Please ener a s", "", "Save"); // Toast.makeText(this, "Value: " + input.getText().toString(), Toast.LENGTH_LONG).show(); + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + installID = Installation.id(this); + + if (!initialized) { + Initialize(); + initialized = true; + } + // Keep the screen bright - very annoying if it goes dark when tilting away + Window window = this.getWindow(); + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + setVolumeControlStream(AudioManager.STREAM_MUSIC); + + if (!useOpenSL) + audioPlayer = new NativeAudioPlayer(); + NativeApp.audioInit(); + + Point size = new Point(); + GetScreenSize(size); + NativeApp.resized(size.x, size.y); + + mGLSurfaceView = new NativeGLView(this); + nativeRenderer = new NativeRenderer(this); + mGLSurfaceView.setRenderer(nativeRenderer); + setContentView(mGLSurfaceView); + + if (Build.VERSION.SDK_INT >= 14) { + darkenOnScreenButtons(); + } } + @Override + protected void onStop() { + super.onStop(); + Log.i(TAG, "onStop - do nothing, just let's switch away"); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + nativeRenderer.onDestroyed(); + Log.e(TAG, "onDestroy"); + NativeApp.audioShutdown(); + audioPlayer = null; + mGLSurfaceView = null; + } + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public void darkenOnScreenButtons() { mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); @@ -238,7 +293,11 @@ public class NativeActivity extends Activity { protected void onResume() { super.onResume(); Log.i(TAG, "onResume"); - mGLSurfaceView.onResume(); + if (mGLSurfaceView != null) { + mGLSurfaceView.onResume(); + } else { + Log.e(TAG, "mGLSurfaceView really shouldn't be null in onResume"); + } if (audioPlayer != null) { audioPlayer.play(); } @@ -247,21 +306,6 @@ public class NativeActivity extends Activity { darkenOnScreenButtons(); } } - - @Override - protected void onStop() { - super.onStop(); - Log.i(TAG, "onStop - do nothing"); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - Log.e(TAG, "onDestroy"); - NativeApp.shutdown(); - audioPlayer = null; - mGLSurfaceView = null; - } public boolean overrideKeys() { return true; diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 25cec55bf6..9c4f1da198 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -2,6 +2,11 @@ package com.henrikrydgard.libnative; public class NativeApp { public static native void init(int xxres, int yyres, int dpi, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); + public static native void resized(int xxres, int yyres); + + + public static native void audioInit(); + public static native void audioShutdown(); public static native void audioConfig(int optimalFramesPerBuffer, int optimalSampleRate); public static native boolean isLandscape(); @@ -10,9 +15,9 @@ public class NativeApp { // These have Android semantics: Resume is always called on bootup, after init public static native void pause(); - public static native void resume(); + // There's not really any reason to ever call shutdown as we can recover from a killed activity. public static native void shutdown(); public static native void keyDown(int deviceId, int key); diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index bb63f4b07b..81b6e31e88 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -31,15 +31,18 @@ public class NativeRenderer implements GLSurfaceView.Renderer { displayResize(width, height); } + public void onDestroyed() { + displayShutdown(); + } // NATIVE METHODS // Note: This also means "device lost" and you should reload // all buffered objects. public native void displayInit(); - public native void displayResize(int w, int h); public native void displayRender(); + public native void displayShutdown(); // called by the C++ code through JNI. Dispatch anything we can't directly handle // on the gfx thread to the UI thread. diff --git a/file/fd_util.cpp b/file/fd_util.cpp index e2cb775c67..daf1fd4119 100644 --- a/file/fd_util.cpp +++ b/file/fd_util.cpp @@ -105,7 +105,7 @@ void SetNonBlocking(int sock, bool non_blocking) { int opts = fcntl(sock, F_GETFL); if (opts < 0) { perror("fcntl(F_GETFL)"); - exit(EXIT_FAILURE); + ELOG("Error getting socket status while changing nonblocking status"); } if (non_blocking) { opts = (opts | O_NONBLOCK); @@ -115,7 +115,7 @@ void SetNonBlocking(int sock, bool non_blocking) { if (fcntl(sock, F_SETFL, opts) < 0) { perror("fcntl(F_SETFL)"); - exit(EXIT_FAILURE); + ELOG("Error setting socket nonblocking status"); } #else WLOG("NonBlocking mode not supported on Win32"); diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 21483470a3..8e60b644e8 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -24,9 +24,6 @@ bool CompileShader(const char *source, GLuint shader, const char *filename) { ELOG("Error in shader compilation of %s!\n", filename); ELOG("Info log: %s\n", infoLog); ELOG("Shader source:\n%s\n", (const char *)source); -#if defined(ARM) - exit(1); -#endif return false; } return true; From 07feef3f445eba07958eb5c86dfc5a299ca4a1ac Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 17 Jul 2013 01:03:29 +0200 Subject: [PATCH 0532/1445] Various newui tweaks --- ui/ui_screen.cpp | 8 +++++--- ui/ui_screen.h | 7 ++++--- ui/view.cpp | 18 +++++++++++++----- ui/view.h | 3 ++- ui/viewgroup.cpp | 2 +- ui/viewgroup.h | 6 ++++-- 6 files changed, 29 insertions(+), 15 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index bc0a94e371..c00b3cb91b 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -62,7 +62,8 @@ void PopupScreen::CreateViews() { using namespace UI; root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); - ViewGroup *box = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(30, 30, 30, 30)); + LinearLayout *box = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(30, 30, 30, 30)); + root_->Add(box); box->SetBG(UI::Drawable(0xFF303030)); box->SetHasDropShadow(true); @@ -80,14 +81,12 @@ void PopupScreen::CreateViews() { } UI::EventReturn PopupScreen::OnOK(UI::EventParams &e) { - // callback_(true); OnCompleted(); screenManager()->finishDialog(this, DR_OK); return UI::EVENT_DONE; } UI::EventReturn PopupScreen::OnCancel(UI::EventParams &e) { - // callback_(false); screenManager()->finishDialog(this, DR_CANCEL); return UI::EVENT_DONE; } @@ -106,3 +105,6 @@ UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) { return UI::EVENT_DONE; } +void ListPopupScreen::OnCompleted() { + callback_(adaptor_.GetSelected()); +} diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 6cf1b3a126..66a87e4c5d 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -49,13 +49,14 @@ private: class ListPopupScreen : public PopupScreen { public: ListPopupScreen(const std::string &title) : PopupScreen(title) {} - ListPopupScreen(const std::string &title, const std::vector &items, int selected) - : PopupScreen(title), adaptor_(items, selected) { + ListPopupScreen(const std::string &title, const std::vector &items, int selected, std::function callback) + : PopupScreen(title), adaptor_(items, selected), callback_(callback) { } UI::Event OnChoice; protected: + virtual void OnCompleted(); void CreatePopupContents(UI::ViewGroup *parent); UI::StringVectorListAdaptor adaptor_; UI::ListView *listView_; @@ -63,5 +64,5 @@ protected: private: UI::EventReturn OnListChoice(UI::EventParams &e); - std::function callback_; + std::function callback_; }; diff --git a/ui/view.cpp b/ui/view.cpp index 55664285b3..b9c29bc310 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -125,11 +125,13 @@ void View::GetContentDimensions(const UIContext &dc, float &w, float &h) const { } Point View::GetFocusPosition(FocusDirection dir) { + // The +2/-2 is some extra fudge factor to cover for views sitting right next to each other. + // Distance zero yields strange results otherwise. switch (dir) { - case FOCUS_LEFT: return Point(bounds_.x, bounds_.centerY()); - case FOCUS_RIGHT: return Point(bounds_.x2(), bounds_.centerY()); - case FOCUS_UP: return Point(bounds_.centerX(), bounds_.y); - case FOCUS_DOWN: return Point(bounds_.centerX(), bounds_.y2()); + case FOCUS_LEFT: return Point(bounds_.x + 2, bounds_.centerY()); + case FOCUS_RIGHT: return Point(bounds_.x2() - 2, bounds_.centerY()); + case FOCUS_UP: return Point(bounds_.centerX(), bounds_.y + 2); + case FOCUS_DOWN: return Point(bounds_.centerX(), bounds_.y2() - 2); default: return bounds_.Center(); @@ -288,7 +290,13 @@ void InfoItem::Draw(UIContext &dc) { } void ItemHeader::Draw(UIContext &dc) { - dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.y, 0xFF707070, ALIGN_LEFT); + float scale = 1.0f; + if (dc.theme->uiFontSmaller == dc.theme->uiFont) { + scale = 0.6f; + } + dc.Draw()->SetFontScale(scale, scale); + dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.y, 0xFFa0a0a0, ALIGN_LEFT); + dc.Draw()->SetFontScale(1.0f, 1.0f); dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), 0xFFFFFFFF); } diff --git a/ui/view.h b/ui/view.h index 2107f6c9ec..c574b2cb64 100644 --- a/ui/view.h +++ b/ui/view.h @@ -450,9 +450,10 @@ public: virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); -private: +protected: std::string text_; std::string smallText_; +private: bool selected_; }; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 3280a4825c..31dea8ccd4 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -743,8 +743,8 @@ void ChoiceStrip::SetSelection(int sel) { ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a) { - linLayout_ = new LinearLayout(ORIENT_VERTICAL); + linLayout_->SetSpacing(0.0f); Add(linLayout_); CreateAllItems(); } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index f009802cb6..a4902ee75f 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -130,7 +130,9 @@ public: void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); - + void SetSpacing(float spacing) { + spacing_ = spacing; + } private: Orientation orientation_; Margins defaultMargins_; @@ -212,7 +214,7 @@ public: class ChoiceStrip : public LinearLayout { public: ChoiceStrip(Orientation orientation, LayoutParams *layoutParams = 0) - : LinearLayout(orientation, layoutParams), selected_(0) {} + : LinearLayout(orientation, layoutParams), selected_(0) { SetSpacing(0.0f); } void AddChoice(const std::string &title); int GetSelection() const { return selected_; } From cd8987b33bbe299af0383609db28fecd6546bffe Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Jul 2013 10:25:30 +0200 Subject: [PATCH 0533/1445] Add basic slider control --- ui/ui_screen.cpp | 6 ++++++ ui/ui_screen.h | 12 ++++++++++++ ui/view.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ ui/view.h | 19 ++++++++++++++++++- 4 files changed, 81 insertions(+), 1 deletion(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index c00b3cb91b..97143bfb39 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -108,3 +108,9 @@ UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) { void ListPopupScreen::OnCompleted() { callback_(adaptor_.GetSelected()); } + + +void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { + using namespace UI; + slider_ = parent->Add(new Slider(value_, minValue_, maxValue_)); +} diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 66a87e4c5d..81c6ba4523 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -66,3 +66,15 @@ private: std::function callback_; }; + +class SliderPopupScreen : public PopupScreen { +public: + SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title) : PopupScreen(title), value_(value), minValue_(minValue), maxValue_(maxValue) {} + void CreatePopupContents(UI::ViewGroup *parent); + +private: + UI::Slider *slider_; + int *value_; + int minValue_; + int maxValue_; +}; \ No newline at end of file diff --git a/ui/view.cpp b/ui/view.cpp index b9c29bc310..dea4038e08 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -2,6 +2,7 @@ #include "base/display.h" #include "base/mutex.h" #include "input/input_state.h" +#include "input/keycodes.h" #include "gfx_es2/draw_buffer.h" #include "gfx/texture.h" #include "gfx/texture_atlas.h" @@ -418,6 +419,50 @@ void TriggerButton::GetContentDimensions(const UIContext &dc, float &w, float &h h = image.h; } +void Slider::Key(const KeyInput &input) { + if (HasFocus() && input.flags & KEY_DOWN) { + switch (input.keyCode) { + case KEYCODE_DPAD_LEFT: + case KEYCODE_MINUS: + case KEYCODE_NUMPAD_SUBTRACT: + *value_ -= 1; + break; + case KEYCODE_DPAD_RIGHT: + case KEYCODE_PLUS: + case KEYCODE_NUMPAD_ADD: + *value_ -= 1; + break; + } + Clamp(); + } +} + +void Slider::Touch(const TouchInput &input) { + if (dragging_ || bounds_.Contains(input.x, input.y)) { + float relativeX = (input.x - bounds_.x) / bounds_.w; + *value_ = floorf(relativeX * (maxValue_ - minValue_) + minValue_ + 0.5f); + Clamp(); + } +} + +void Slider::Clamp() { + if (*value_ < minValue_) *value_ = minValue_; + else if (*value_ > maxValue_) *value_ = maxValue_; +} + +void Slider::Draw(UIContext &dc) { + float knobX = ((float)(*value_) - minValue_) / (maxValue_ - minValue_) * bounds_.w + bounds_.x; + dc.FillRect(Drawable(0xFFFFFFFF), Bounds(bounds_.x, bounds_.centerY() - 2, knobX - bounds_.x, 4)); + dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, bounds_.x + bounds_.w - knobX, 4)); + dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); +} + +void Slider::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + // TODO + w = 100; + h = 50; +} + /* TabStrip::TabStrip() diff --git a/ui/view.h b/ui/view.h index c574b2cb64..1af686aa88 100644 --- a/ui/view.h +++ b/ui/view.h @@ -79,6 +79,7 @@ struct Theme { int uiFontSmaller; int checkOn; int checkOff; + int sliderKnob; int whiteImage; Style buttonStyle; @@ -401,6 +402,23 @@ private: std::string text_; }; +class Slider : public Clickable { +public: + Slider(int *value, int minValue, int maxValue, LayoutParams *layoutParams = 0) + : Clickable(layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue) {} + virtual void Draw(UIContext &dc); + virtual void Key(const KeyInput &input); + virtual void Touch(const TouchInput &input); + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + +private: + void Clamp(); + int *value_; + int minValue_; + int maxValue_; +}; + + // Basic button that modifies a bitfield based on the pressed status. Supports multitouch. // Suitable for controller simulation (ABXY etc). class TriggerButton : public View { @@ -517,7 +535,6 @@ private: std::string smallText_; }; - // These are for generic use. class Spacer : public InertView { From d5d969fc6a2332e7ac930aa397bd109f9e771d2c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Jul 2013 16:56:47 +0200 Subject: [PATCH 0534/1445] Fix measuring bug in GridLayout --- ui/viewgroup.cpp | 46 ++++++++++++++++++++++++---------------------- ui/viewgroup.h | 3 ++- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 31dea8ccd4..712bc4c8cc 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -591,25 +591,6 @@ void ScrollView::Update(const InputState &input_state) { } } -void GridLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { - MeasureSpecType measureType = settings_.fillCells ? EXACTLY : AT_MOST; - - for (size_t i = 0; i < views_.size(); i++) { - views_[i]->Measure(dc, MeasureSpec(measureType, settings_.columnWidth), MeasureSpec(measureType, settings_.rowHeight)); - } - - MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); - - // Okay, got the width we are supposed to adjust to. Now we can calculate the number of columns. - int numColumns = (measuredWidth_ - settings_.spacing) / (settings_.columnWidth + settings_.spacing); - if (!numColumns) numColumns = 1; - int numRows = (int)(views_.size() + (numColumns - 1)) / numColumns; - - float estimatedHeight = (settings_.rowHeight + settings_.spacing) * numRows; - - MeasureBySpec(layoutParams_->height, estimatedHeight, vert, &measuredHeight_); -} - void AnchorLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); @@ -674,9 +655,29 @@ void AnchorLayout::Layout() { } } +void GridLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { + MeasureSpecType measureType = settings_.fillCells ? EXACTLY : AT_MOST; + + for (size_t i = 0; i < views_.size(); i++) { + views_[i]->Measure(dc, MeasureSpec(measureType, settings_.columnWidth), MeasureSpec(measureType, settings_.rowHeight)); + } + + MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); + + // Okay, got the width we are supposed to adjust to. Now we can calculate the number of columns. + numColumns_ = (measuredWidth_ - settings_.spacing) / (settings_.columnWidth + settings_.spacing); + if (!numColumns_) numColumns_ = 1; + int numRows = (int)(views_.size() + (numColumns_ - 1)) / numColumns_; + + float estimatedHeight = (settings_.rowHeight + settings_.spacing) * numRows; + + MeasureBySpec(layoutParams_->height, estimatedHeight, vert, &measuredHeight_); +} + void GridLayout::Layout() { int y = 0; int x = 0; + int count = 0; for (size_t i = 0; i < views_.size(); i++) { Bounds itemBounds, innerBounds; @@ -692,12 +693,13 @@ void GridLayout::Layout() { views_[i]->SetBounds(innerBounds); views_[i]->Layout(); - x += itemBounds.w; - if (x + itemBounds.w >= bounds_.w) { + count++; + if (count == numColumns_) { + count = 0; x = 0; y += itemBounds.h + settings_.spacing; } else { - x += settings_.spacing; + x += itemBounds.w + settings_.spacing; } } } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index a4902ee75f..8adf9584c4 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -156,7 +156,7 @@ struct GridLayoutSettings { class GridLayout : public ViewGroup { public: GridLayout(GridLayoutSettings settings, LayoutParams *layoutParams = 0) - : ViewGroup(layoutParams), settings_(settings) { + : ViewGroup(layoutParams), settings_(settings), numColumns_(1) { if (settings.orientation != ORIENT_HORIZONTAL) ELOG("GridLayout: Vertical layouts not yet supported"); } @@ -166,6 +166,7 @@ public: private: GridLayoutSettings settings_; + int numColumns_; }; // A scrollview usually contains just a single child - a linear layout or similar. From 60dcf8fae9358a332cda14c00f37bd701e157518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 20 Jul 2013 09:37:57 +0200 Subject: [PATCH 0535/1445] Send KEYCODE_BUTTON_SELECT for a button code in SDL. --- base/PCMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index ef45ec1450..52695d0393 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -541,7 +541,7 @@ int main(int argc, char *argv[]) { SDLJoyButtonMap[7] = KEYCODE_BUTTON_6; SDLJoyButtonMap[8] = KEYCODE_BUTTON_7; SDLJoyButtonMap[9] = KEYCODE_BUTTON_8; - SDLJoyButtonMap[10] = KEYCODE_BACK; + SDLJoyButtonMap[10] = KEYCODE_BUTTON_SELECT; SDLJoyButtonMap[11] = KEYCODE_BUTTON_2; SDLJoyButtonMap[12] = KEYCODE_BUTTON_3; SDLJoyButtonMap[13] = KEYCODE_BUTTON_4; From 13b8277bd3229fe2ea56b082fc34de773be42257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 20 Jul 2013 09:42:44 +0200 Subject: [PATCH 0536/1445] Fix some confusing code noticed by unknown, typo fix --- android/app-android.cpp | 2 +- ui/viewgroup.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index e318d4199a..b6cf02e05b 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -188,7 +188,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioInit(JNIEnv *, j optimalSampleRate = 44100; AndroidAudio_Init(&NativeMix, library_path, optimalFramesPerBuffer, optimalSampleRate); } - ILOG("NativeApp.audioShutdown() -- end"); + ILOG("NativeApp.audioInit() -- end"); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioShutdown(JNIEnv *, jclass) { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 712bc4c8cc..99b8b7c81a 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -730,9 +730,10 @@ EventReturn ChoiceStrip::OnChoiceClick(EventParams &e) { } EventParams e2; - e.a = selected_; + e2.v = views_[selected_]; + e2.a = selected_; // Dispatch immediately (we're already on the UI thread as we're in an event handler). - return OnChoice.Dispatch(e); + return OnChoice.Dispatch(e2); } void ChoiceStrip::SetSelection(int sel) { @@ -834,4 +835,4 @@ void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { root->Update(input_state); DispatchEvents(); } -} // namespace UI \ No newline at end of file +} // namespace UI From b059027359d69dec21fc5b392378fd00a1d45043 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 20 Jul 2013 12:04:24 +0200 Subject: [PATCH 0537/1445] Add centering mode to AnchorLayout. --- ui/ui_screen.cpp | 6 +++++- ui/viewgroup.cpp | 43 ++++++++++++++++++++++++++++++++----------- ui/viewgroup.h | 9 +++++---- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 97143bfb39..38f5b64c81 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -16,7 +16,11 @@ void UIScreen::update(InputState &input) { recreateViews_ = false; } - UpdateViewHierarchy(input, root_); + if (root_) { + UpdateViewHierarchy(input, root_); + } else { + ELOG("Tried to update without a view root"); + } } void UIScreen::render() { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 99b8b7c81a..936e7285db 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -608,11 +608,13 @@ void AnchorLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v width = params->width; height = params->height; - if (params->left >= 0 && params->right >= 0) { - width = measuredWidth_ - params->left - params->right; - } - if (params->top >= 0 && params->bottom >= 0) { - height = measuredHeight_ - params->top - params->bottom; + if (!params->center) { + if (params->left >= 0 && params->right >= 0) { + width = measuredWidth_ - params->left - params->right; + } + if (params->top >= 0 && params->bottom >= 0) { + height = measuredHeight_ - params->top - params->bottom; + } } specW = width < 0 ? MeasureSpec(UNSPECIFIED) : MeasureSpec(EXACTLY, width); specH = height < 0 ? MeasureSpec(UNSPECIFIED) : MeasureSpec(EXACTLY, height); @@ -631,24 +633,35 @@ void AnchorLayout::Layout() { vBounds.w = views_[i]->GetMeasuredWidth(); vBounds.h = views_[i]->GetMeasuredHeight(); - float left = 0, top = 0, right = 0, bottom = 0; - + float left = 0, top = 0, right = 0, bottom = 0, center = false; if (params) { left = params->left; top = params->top; right = params->right; bottom = params->bottom; + center = params->center; } - if (left >= 0) + if (left >= 0) { vBounds.x = bounds_.x + left; - else if (right >= 0) + if (center) + vBounds.x -= vBounds.w * 0.5f; + } else if (right >= 0) { vBounds.x = bounds_.x2() - right - vBounds.w; + if (center) { + vBounds.x += vBounds.w * 0.5f; + } + } - if (top >= 0) + if (top >= 0) { vBounds.y = bounds_.y + top; - else if (bottom >= 0) + if (center) + vBounds.y -= vBounds.h * 0.5f; + } else if (bottom >= 0) { vBounds.y = bounds_.y2() - bottom - vBounds.h; + if (center) + vBounds.y += vBounds.h * 0.5f; + } views_[i]->SetBounds(vBounds); views_[i]->Layout(); @@ -796,6 +809,10 @@ bool StringVectorListAdaptor::AddEventCallback(View *view, std::function Date: Sat, 20 Jul 2013 13:54:09 +0200 Subject: [PATCH 0538/1445] Add SliderFloat --- ui/ui_screen.cpp | 6 +++++- ui/ui_screen.h | 12 ++++++++++++ ui/view.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ ui/view.h | 15 +++++++++++++++ 4 files changed, 76 insertions(+), 1 deletion(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 38f5b64c81..f904cc28ec 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -113,8 +113,12 @@ void ListPopupScreen::OnCompleted() { callback_(adaptor_.GetSelected()); } - void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; slider_ = parent->Add(new Slider(value_, minValue_, maxValue_)); } + +void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { + using namespace UI; + slider_ = parent->Add(new SliderFloat(value_, minValue_, maxValue_)); +} diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 81c6ba4523..0901481eac 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -77,4 +77,16 @@ private: int *value_; int minValue_; int maxValue_; +}; + +class SliderFloatPopupScreen : public PopupScreen { +public: + SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title) : PopupScreen(title), value_(value), minValue_(minValue), maxValue_(maxValue) {} + void CreatePopupContents(UI::ViewGroup *parent); + +private: + UI::SliderFloat *slider_; + float *value_; + float minValue_; + float maxValue_; }; \ No newline at end of file diff --git a/ui/view.cpp b/ui/view.cpp index dea4038e08..de91e11693 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -463,6 +463,50 @@ void Slider::GetContentDimensions(const UIContext &dc, float &w, float &h) const h = 50; } +void SliderFloat::Key(const KeyInput &input) { + if (HasFocus() && input.flags & KEY_DOWN) { + switch (input.keyCode) { + case KEYCODE_DPAD_LEFT: + case KEYCODE_MINUS: + case KEYCODE_NUMPAD_SUBTRACT: + *value_ -= 1; + break; + case KEYCODE_DPAD_RIGHT: + case KEYCODE_PLUS: + case KEYCODE_NUMPAD_ADD: + *value_ -= 1; + break; + } + Clamp(); + } +} + +void SliderFloat::Touch(const TouchInput &input) { + if (dragging_ || bounds_.Contains(input.x, input.y)) { + float relativeX = (input.x - bounds_.x) / bounds_.w; + *value_ = floorf(relativeX * (maxValue_ - minValue_) + minValue_ + 0.5f); + Clamp(); + } +} + +void SliderFloat::Clamp() { + if (*value_ < minValue_) *value_ = minValue_; + else if (*value_ > maxValue_) *value_ = maxValue_; +} + +void SliderFloat::Draw(UIContext &dc) { + float knobX = ((float)(*value_) - minValue_) / (maxValue_ - minValue_) * bounds_.w + bounds_.x; + dc.FillRect(Drawable(0xFFFFFFFF), Bounds(bounds_.x, bounds_.centerY() - 2, knobX - bounds_.x, 4)); + dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, bounds_.x + bounds_.w - knobX, 4)); + dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); +} + +void SliderFloat::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + // TODO + w = 100; + h = 50; +} + /* TabStrip::TabStrip() diff --git a/ui/view.h b/ui/view.h index 1af686aa88..f09c6810e2 100644 --- a/ui/view.h +++ b/ui/view.h @@ -418,6 +418,21 @@ private: int maxValue_; }; +class SliderFloat : public Clickable { +public: + SliderFloat(float *value, float minValue, float maxValue, LayoutParams *layoutParams = 0) + : Clickable(layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue) {} + virtual void Draw(UIContext &dc); + virtual void Key(const KeyInput &input); + virtual void Touch(const TouchInput &input); + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + +private: + void Clamp(); + float *value_; + float minValue_; + float maxValue_; +}; // Basic button that modifies a bitfield based on the pressed status. Supports multitouch. // Suitable for controller simulation (ABXY etc). From f3da7ce00a7e5153c959ceb5c421a038b02b1474 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Jul 2013 21:46:18 -0700 Subject: [PATCH 0539/1445] Add UTF16 and Shift-JIS decode/encoders. May not entirely be perfect, not enough error checking. Shift-JIS encoder is not complete but does most things. --- util/text/shiftjis.h | 133 +++++++++++++++++++++++++++++++++++++++++++ util/text/utf16.h | 73 ++++++++++++++++++++++++ util/text/utf8.h | 8 +++ 3 files changed, 214 insertions(+) create mode 100644 util/text/shiftjis.h create mode 100644 util/text/utf16.h diff --git a/util/text/shiftjis.h b/util/text/shiftjis.h new file mode 100644 index 0000000000..72f9438c48 --- /dev/null +++ b/util/text/shiftjis.h @@ -0,0 +1,133 @@ +#pragma once + +#include "base/basictypes.h" + +// Warning: decodes/encodes JIS, not Unicode. +// Use a table to map. +struct ShiftJIS { + static const uint32_t INVALID = (uint32_t) -1; + + ShiftJIS(const char *c) : c_(c), index_(0) {} + + uint32_t next() { + uint32_t j = (uint8_t)c_[index_++]; + + int row; + bool emojiAdjust = false; + switch (j >> 4) { + case 0x8: + if (j == 0x80) { + return INVALID; + } + // Intentional fall-through. + case 0x9: + case 0xE: + row = ((j & 0x3F) << 1) - 0x01; + break; + + case 0xF: + emojiAdjust = true; + if (j < 0xF4) { + row = ((j & 0x7F) << 1) - 0x59; + } else if (j < 0xFD) { + row = ((j & 0x7F) << 1) - 0x1B; + } else { + return j; + } + break; + + // Anything else (i.e. <= 0x7x, 0xAx, 0xBx, 0xCx, and 0xDx) is JIS X 0201, return directly. + default: + return j; + } + + // Okay, if we didn't return, it's time for the second byte (the cell.) + j = (uint8_t)c_[index_++]; + // Not a valid second byte. + if (j < 0x40 || j == 0x7F || j >= 0xFD) { + return INVALID; + } + + if (j >= 0x9F) { + // This range means the row was even. + ++row; + j -= 0x7E; + } else { + if (j >= 0x80) { + j -= 0x20; + } else { + // Yuck. They wrapped around 0x7F, so we subtract one less. + j -= 0x20 - 1; + } + + if (emojiAdjust) { + // These are shoved in where they'll fit. + if (row == 0x87) { + // First byte was 0xF0. + row = 0x81; + } else if (row == 0x8B) { + // First byte was 0xF2. + row = 0x85; + } else if (row == 0xCD) { + // First byte was 0xF4. + row = 0x8F; + } + } + } + + // j is already the cell + 0x20. + return ((row + 0x20) << 8) | j; + } + + bool end() const { + return c_[index_] == 0; + } + + int length() const { + int len = 0; + for (ShiftJIS dec(c_); !dec.end(); dec.next()) + ++len; + return len; + } + + int byteIndex() const { + return index_; + } + + static int encode(char *dest, uint32_t j) { + int row = (j >> 8) - 0x20; + int offsetCell = j & 0xFF; + + // JIS X 0201. + if ((j & ~0xFF) == 0) { + *dest = j; + return 1; + } + + if (row < 0x3F) { + *dest++ = 0x80 + ((row + 1) >> 1); + } else if (row < 0x5F) { + // Reduce by 0x40 to account for the above range. + *dest++ = 0xE0 + ((row - 0x40 + 1) >> 1); + } else if (row >= 0x80) { + // TODO + } + + if (row & 1) { + if (offsetCell < 0x60) { + // Subtract one to shift around 0x7F. + *dest++ = offsetCell + 0x20 - 1; + } else { + *dest++ = offsetCell + 0x20; + } + } else { + *dest++ = offsetCell + 0x7E; + } + + return 2; + } + +private: + const char *c_; + int index_; +}; \ No newline at end of file diff --git a/util/text/utf16.h b/util/text/utf16.h new file mode 100644 index 0000000000..e84ca82079 --- /dev/null +++ b/util/text/utf16.h @@ -0,0 +1,73 @@ +#pragma once + +#include "base/basictypes.h" + +#if defined(__LITTLE_ENDIAN__) +#define UTF16_IS_LITTLE_ENDIAN 1 +#elif defined(__BIG_ENDIAN__) +#define UTF16_IS_LITTLE_ENDIAN 0 +#else +// Should optimize out. +#define UTF16_IS_LITTLE_ENDIAN (*(const uint16_t *)"\0\xff" >= 0x100) +#endif + +template +uint16_t UTF16_Swap(uint16_t u) { + if (is_little) { + return UTF16_IS_LITTLE_ENDIAN ? u : swap16(u); + } else { + return UTF16_IS_LITTLE_ENDIAN ? swap16(u) : u; + } +} + +template +struct UTF16_Type { +public: + static const uint32_t INVALID = (uint32_t)-1; + + UTF16_Type(const uint16_t *c) : c_(c), index_(0) {} + + uint32_t next() { + const uint32_t u = UTF16_Swap(c_[index_++]); + + // Surrogate pair. UTF-16 is so simple. We assume it's valid. + if ((u & 0xD800) == 0xD800) { + return 0x10000 + (((u & 0x3FF) << 10) | (UTF16_Swap(c_[index_++]) & 0x3FF)); + } + return u; + } + + bool end() const { + return c_[index_] == 0; + } + + int length() const { + int len = 0; + for (UTF16_Type dec(c_); !dec.end(); dec.next()) + ++len; + return len; + } + + int byteIndex() const { + return index_; + } + + static int encode(uint16_t *dest, uint32_t u) { + if (u >= 0x10000) { + u -= 0x10000; + *dest = UTF16_Swap(0xD800 + ((u >> 10) & 0x3FF)); + *dest = UTF16_Swap(0xDC00 + ((u >> 0) & 0x3FF)); + return 2; + } else { + *dest = UTF16_Swap((uint16_t)u); + return 1; + } + } + +private: + const uint16_t *c_; + int index_; +}; + +typedef UTF16_Type UTF16LE; +typedef UTF16_Type UTF16BE; diff --git a/util/text/utf8.h b/util/text/utf8.h index bd320979f8..5d46a67648 100644 --- a/util/text/utf8.h +++ b/util/text/utf8.h @@ -17,10 +17,12 @@ #include "base/basictypes.h" uint32_t u8_nextchar(const char *s, int *i); +int u8_wc_toutf8(char *dest, uint32_t ch); int u8_strlen(const char *s); class UTF8 { public: + static const uint32_t INVALID = (uint32_t)-1; UTF8(const char *c) : c_(c), index_(0) {} bool end() const { return c_[index_] == 0; } uint32_t next() { @@ -29,6 +31,12 @@ public: int length() const { return u8_strlen(c_); } + int byteIndex() const { + return index_; + } + static int encode(char *dest, uint32_t ch) { + return u8_wc_toutf8(dest, ch); + } private: const char *c_; From 7421e1de67fd97918c6f0da83fc84a9679ef3464 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 21 Jul 2013 13:30:47 +0200 Subject: [PATCH 0540/1445] NewUI: Fix some flicker when switching between screens. --- ui/ui_screen.cpp | 9 +++++++-- ui/ui_screen.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index f904cc28ec..64bba67f3b 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -5,16 +5,19 @@ UIScreen::UIScreen() : Screen(), root_(0), recreateViews_(true) { - } -void UIScreen::update(InputState &input) { +void UIScreen::DoRecreateViews() { if (recreateViews_) { delete root_; root_ = 0; CreateViews(); recreateViews_ = false; } +} + +void UIScreen::update(InputState &input) { + DoRecreateViews(); if (root_) { UpdateViewHierarchy(input, root_); @@ -24,6 +27,8 @@ void UIScreen::update(InputState &input) { } void UIScreen::render() { + DoRecreateViews(); + if (root_) { UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_); diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 0901481eac..a2257f7a8b 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -25,6 +25,7 @@ protected: UI::ViewGroup *root_; private: + void DoRecreateViews(); bool recreateViews_; }; From dd99cfbbe808a62528cfb2f51864ad596812c1f6 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Jul 2013 12:55:28 -0700 Subject: [PATCH 0541/1445] Fix typo in UTF-16 surrogate pairs. --- util/text/utf16.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/text/utf16.h b/util/text/utf16.h index e84ca82079..174ec163e1 100644 --- a/util/text/utf16.h +++ b/util/text/utf16.h @@ -55,7 +55,7 @@ public: static int encode(uint16_t *dest, uint32_t u) { if (u >= 0x10000) { u -= 0x10000; - *dest = UTF16_Swap(0xD800 + ((u >> 10) & 0x3FF)); + *dest++ = UTF16_Swap(0xD800 + ((u >> 10) & 0x3FF)); *dest = UTF16_Swap(0xDC00 + ((u >> 0) & 0x3FF)); return 2; } else { From f2f153633cdb8c8876e2c68185b7d728ec293d75 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 22 Jul 2013 01:22:06 +0200 Subject: [PATCH 0542/1445] Load the GL_QCOM_alpha_test extension on Android. --- gfx/gl_common.h | 20 ++++++++++++++++++++ gfx_es2/gl_state.cpp | 15 +++++++++++++++ gfx_es2/gl_state.h | 1 + 3 files changed, 36 insertions(+) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 7722ed3133..9a5b7df67f 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -8,6 +8,26 @@ #else #include #include +#include + +// Additional extensions not included in GLES2/gl2ext.h from the NDK + +/* GL_QCOM_alpha_test */ +#ifndef GL_QCOM_alpha_test +#define GL_ALPHA_TEST_QCOM 0x0BC0 +#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 +#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 +#endif + +#ifndef GL_QCOM_alpha_test +#define GL_QCOM_alpha_test 1 +#ifdef GL_GLEXT_PROTOTYPES +//GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref); +#endif +typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); +extern PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; +#endif + #endif #else // OpenGL #include diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 367e61f72c..7244a50476 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -5,6 +5,11 @@ #endif +#ifdef USING_GLES2 +PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; +#endif + + OpenGLState glstate; GLExtensions gl_extensions; @@ -49,6 +54,8 @@ void OpenGLState::Restore() { assert(count == state_count && "OpenGLState::Restore is missing some states"); } +// http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array + void CheckGLExtensions() { static bool done = false; if (done) @@ -70,6 +77,14 @@ void CheckGLExtensions() { gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; + + // TODO: Change to USING_GLES2 if it works on those other platforms too +#ifdef ANDROID + gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0; + // Load extensions that are not auto-loaded by Android. + glAlphaFuncQCOM = (PFNGLALPHAFUNCQCOMPROC)eglGetProcAddress("glAlphaFuncQCOM"); +#endif + #ifdef USING_GLES2 gl_extensions.FBO_ARB = true; gl_extensions.FBO_EXT = false; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index a325cb916b..3ef1093137 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -208,6 +208,7 @@ struct GLExtensions { bool FBO_ARB; bool FBO_EXT; bool EXT_swap_control_tear; + bool QCOM_alpha_test; }; extern GLExtensions gl_extensions; From ee0f3848272b6eb5446b468a1c55868e3b3c455c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 22 Jul 2013 01:23:39 +0200 Subject: [PATCH 0543/1445] Just for cleanness, check first. --- gfx_es2/gl_state.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 7244a50476..bd5d6edef4 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -82,7 +82,9 @@ void CheckGLExtensions() { #ifdef ANDROID gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0; // Load extensions that are not auto-loaded by Android. - glAlphaFuncQCOM = (PFNGLALPHAFUNCQCOMPROC)eglGetProcAddress("glAlphaFuncQCOM"); + if (gl_extensions.QCOM_alpha_test) { + glAlphaFuncQCOM = (PFNGLALPHAFUNCQCOMPROC)eglGetProcAddress("glAlphaFuncQCOM"); + } #endif #ifdef USING_GLES2 From b7c8b8ddef4e22324b768129f53a10382684259a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 22 Jul 2013 22:36:30 +0200 Subject: [PATCH 0544/1445] Detect OES_mapbuffer extension --- gfx_es2/gl_state.cpp | 2 ++ gfx_es2/gl_state.h | 1 + 2 files changed, 3 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index bd5d6edef4..d4506aca4d 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -76,8 +76,10 @@ void CheckGLExtensions() { gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0; gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; + gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; + // TODO: Change to USING_GLES2 if it works on those other platforms too #ifdef ANDROID gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 3ef1093137..5e04220157 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -209,6 +209,7 @@ struct GLExtensions { bool FBO_EXT; bool EXT_swap_control_tear; bool QCOM_alpha_test; + bool OES_mapbuffer; }; extern GLExtensions gl_extensions; From 4871c1192d54adb9be8f642d4c0303cf359104db Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 25 Jul 2013 14:28:18 +1000 Subject: [PATCH 0545/1445] Implement parts of the new input system for Blackberry and Qt. --- base/BlackberryMain.cpp | 43 ++++++++++++++++++++++++++++++++--------- base/QtMain.h | 35 ++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index c4633abf98..3d48b716f0 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -8,6 +8,8 @@ #include #include +#include "input/keycodes.h" + #include "BlackberryMain.h" // Simple implementations of System functions @@ -91,6 +93,8 @@ void SimulateGamepad(InputState *input) { void BlackberryMain::handleInput(screen_event_t screen_event) { + TouchInput input; + KeyInput key; int val, buttons, pointerId; int pair[2]; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &val); @@ -104,9 +108,24 @@ void BlackberryMain::handleInput(screen_event_t screen_event) case SCREEN_EVENT_MTOUCH_TOUCH: case SCREEN_EVENT_MTOUCH_RELEASE: // Up, down input_state.pointer_down[pointerId] = (val == SCREEN_EVENT_MTOUCH_TOUCH); + input_state.pointer_x[pointerId] = pair[0] * dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * dpi_scale; + + input.x = pair[0] * dpi_scale; + input.y = pair[1] * dpi_scale; + input.flags = (val == SCREEN_EVENT_MTOUCH_TOUCH) ? TOUCH_DOWN : TOUCH_UP; + input.id = pointerId; + NativeTouch(input); + break; case SCREEN_EVENT_MTOUCH_MOVE: input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; + + input.x = pair[0] * dpi_scale; + input.y = pair[1] * dpi_scale; + input.flags = TOUCH_MOVE; + input.id = pointerId; + NativeTouch(input); break; // Mouse, Simulator case SCREEN_EVENT_POINTER: @@ -116,10 +135,22 @@ void BlackberryMain::handleInput(screen_event_t screen_event) input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = true; + + input.x = pair[0] * dpi_scale; + input.y = pair[1] * dpi_scale; + input.flags = TOUCH_DOWN; + input.id = pointerId; + NativeTouch(input); } else if (input_state.pointer_down[pointerId]) { // Up input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = false; + + input.x = pair[0] * dpi_scale; + input.y = pair[1] * dpi_scale; + input.flags = TOUCH_UP; + input.id = pointerId; + NativeTouch(input); } break; // Keyboard @@ -127,16 +158,10 @@ void BlackberryMain::handleInput(screen_event_t screen_event) int flags, value; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value); - for (int b = 0; b < 14; b++) { - if (value == buttonMappings[b] & 0xFF) { - if (flags & KEY_DOWN) - pad_buttons |= (1< touchPoints; switch(e->type()) { @@ -94,9 +95,24 @@ protected: case Qt::TouchPointPressed: case Qt::TouchPointReleased: input_state.pointer_down[touchPoint.id()] = (touchPoint.state() == Qt::TouchPointPressed); + input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * dpi_scale; + input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * dpi_scale; + + input.x = touchPoint.pos().x() * dpi_scale; + input.y = touchPoint.pos().y() * dpi_scale; + input.flags = (touchPoint.state() == Qt::TouchPointPressed) ? TOUCH_DOWN : TOUCH_UP; + input.id = touchPoint.id(); + NativeTouch(input); + break; case Qt::TouchPointMoved: input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * dpi_scale; input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * dpi_scale; + + input.x = touchPoint.pos().x() * dpi_scale; + input.y = touchPoint.pos().y() * dpi_scale; + input.flags = TOUCH_MOVE; + input.id = touchPoint.id(); + NativeTouch(input); break; default: break; @@ -106,21 +122,38 @@ protected: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: input_state.pointer_down[0] = (e->type() == QEvent::MouseButtonPress); + input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * dpi_scale; + input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * dpi_scale; + + input.x = ((QMouseEvent*)e)->pos().x() * dpi_scale; + input.y = ((QMouseEvent*)e)->pos().y() * dpi_scale; + input.flags = (e->type() == QEvent::MouseButtonPress) ? TOUCH_DOWN : TOUCH_UP; + input.id = 0; + NativeTouch(input); + break; case QEvent::MouseMove: input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * dpi_scale; input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * dpi_scale; + + input.x = ((QMouseEvent*)e)->pos().x() * dpi_scale; + input.y = ((QMouseEvent*)e)->pos().y() * dpi_scale; + input.flags = TOUCH_MOVE; + input.id = 0; + NativeTouch(input); break; case QEvent::KeyPress: for (int b = 0; b < 18; b++) { if (((QKeyEvent*)e)->key() == buttonMappings[b]) pad_buttons |= (1<key(), KEY_DOWN)); break; case QEvent::KeyRelease: for (int b = 0; b < 18; b++) { if (((QKeyEvent*)e)->key() == buttonMappings[b]) pad_buttons &= ~(1<key(), KEY_UP)); break; default: return QWidget::event(e); @@ -144,8 +177,8 @@ protected: updateAccelerometer(); UpdateInputState(&input_state); NativeUpdate(input_state); - EndInputState(&input_state); NativeRender(); + EndInputState(&input_state); time_update(); update(); } From ea3376b9146e8f0c9bb873b9126f9d709d3ce16b Mon Sep 17 00:00:00 2001 From: The Dax Date: Thu, 25 Jul 2013 18:37:21 -0400 Subject: [PATCH 0546/1445] Update basictypes.h for Visual Studio 2012 support. --- base/basictypes.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/base/basictypes.h b/base/basictypes.h index 32efa91cdd..bb86be3668 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -3,6 +3,17 @@ #include #include // for byte swapping +#ifdef _WIN32 +// We need this to compile without hundreds of std::bind errors in Visual Studio 2012 +// since by default VARIADIC_MAX is something low like 3, 4, or 5. +// It's a good idea to include this file wherever std::bind is being used with more than 3, 4 or 5 args. +#if _MSC_VER >= 1700 +#undef _VARIADIC_MAX +#define _VARIADIC_MAX 10 +#endif + +#endif + #ifdef _WIN32 #pragma warning(disable:4244) #pragma warning(disable:4996) From 230d061fb2c19dd0aedc91c8529db0a1ad94980f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 25 Jul 2013 22:24:53 -0700 Subject: [PATCH 0547/1445] When possible always use a runtime check for endian. --- util/text/utf16.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/util/text/utf16.h b/util/text/utf16.h index 174ec163e1..75f8b3ee02 100644 --- a/util/text/utf16.h +++ b/util/text/utf16.h @@ -2,14 +2,8 @@ #include "base/basictypes.h" -#if defined(__LITTLE_ENDIAN__) -#define UTF16_IS_LITTLE_ENDIAN 1 -#elif defined(__BIG_ENDIAN__) -#define UTF16_IS_LITTLE_ENDIAN 0 -#else // Should optimize out. #define UTF16_IS_LITTLE_ENDIAN (*(const uint16_t *)"\0\xff" >= 0x100) -#endif template uint16_t UTF16_Swap(uint16_t u) { From f72b981395c31b566270d7c3125c981e3263adb7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 25 Jul 2013 22:34:09 -0700 Subject: [PATCH 0548/1445] iOS buildfix. --- gfx_es2/gl_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index d4506aca4d..02da1b34ec 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -5,7 +5,7 @@ #endif -#ifdef USING_GLES2 +#if defined(USING_GLES2) && !defined(IOS) PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; #endif From 96d7a58ba0a85c7c4dc07806e5e263792a20c484 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 26 Jul 2013 22:21:09 +0200 Subject: [PATCH 0549/1445] Print slightly more debug info on link fail. --- gfx_es2/glsl_program.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 8e60b644e8..4dfd17dcae 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -146,16 +146,18 @@ bool glsl_recompile(GLSLProgram *program) { GLint linkStatus; glGetProgramiv(prog, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { + if (linkStatus == GL_FALSE) { GLint bufLength = 0; glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength); if (bufLength) { char* buf = new char[bufLength]; glGetProgramInfoLog(prog, bufLength, NULL, buf); - FLOG("Could not link program:\n %s", buf); + ILOG("vsh: %i fsh: %i", vsh, fsh); + FLOG("Could not link shader program (linkstatus=%i):\n %s \n", linkStatus, buf); delete [] buf; // we're dead! } else { - FLOG("Could not link program."); + ILOG("vsh: %i fsh: %i", vsh, fsh); + FLOG("Could not link shader program (linkstatus=%i). No OpenGL error log was available.", linkStatus); } glDeleteShader(vsh); glDeleteShader(fsh); From 5d3f2e8b5d270a7d274b58a68a0c94ee3c9263bf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 27 Jul 2013 00:34:36 +0200 Subject: [PATCH 0550/1445] Add some disabled code to use EGL_NV_system_time for timing. This gives NV PerfHud ES some interesting capabilities (can pause, speedup, slow down from the debugger UI). --- Android.mk | 2 +- android/.classpath | 2 +- base/timeutil.cpp | 19 +++++++++++++++++++ gfx/gl_common.h | 18 ------------------ gfx_es2/gl_state.cpp | 25 +++++++++++++++++++++++-- gfx_es2/gl_state.h | 30 ++++++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 22 deletions(-) diff --git a/Android.mk b/Android.mk index 5d92f1f757..2486b7ec38 100644 --- a/Android.mk +++ b/Android.mk @@ -77,7 +77,7 @@ LOCAL_SRC_FILES :=\ util/random/perlin.cpp \ util/text/utf8.cpp -LOCAL_CFLAGS := -O3 -DGL_GLEXT_PROTOTYPES -DUSING_GLES2 -fsigned-char -fno-strict-aliasing +LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -frtti LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip diff --git a/android/.classpath b/android/.classpath index bb0c759770..7bc01d9a9c 100644 --- a/android/.classpath +++ b/android/.classpath @@ -3,7 +3,7 @@ - + diff --git a/base/timeutil.cpp b/base/timeutil.cpp index 0f18c16fbc..7aceef6c32 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -2,6 +2,9 @@ #include "base/logging.h" #include "base/timeutil.h" +// For NV time functions. Ugly! +#include "gfx_es2/gl_state.h" + #ifdef _WIN32 #include #else @@ -31,7 +34,23 @@ double real_time_now(){ #else +uint64_t _frequency = 0; +uint64_t _starttime = 0; + double real_time_now() { + if (false && gl_extensions.EGL_NV_system_time) { + // This is needed to profile using PerfHUD on Tegra + if (_frequency == 0) { + _frequency = eglGetSystemTimeFrequencyNV(); + _starttime = eglGetSystemTimeNV(); + } + + uint64_t cur = eglGetSystemTimeNV(); + int64_t diff = cur - _starttime; + + return (double)diff / (double)_frequency; + } + static time_t start; struct timeval tv; gettimeofday(&tv, NULL); diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 9a5b7df67f..3d70b21465 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -10,24 +10,6 @@ #include #include -// Additional extensions not included in GLES2/gl2ext.h from the NDK - -/* GL_QCOM_alpha_test */ -#ifndef GL_QCOM_alpha_test -#define GL_ALPHA_TEST_QCOM 0x0BC0 -#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 -#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 -#endif - -#ifndef GL_QCOM_alpha_test -#define GL_QCOM_alpha_test 1 -#ifdef GL_GLEXT_PROTOTYPES -//GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref); -#endif -typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); -extern PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; -#endif - #endif #else // OpenGL #include diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 02da1b34ec..bdf778cf46 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -7,6 +7,9 @@ #if defined(USING_GLES2) && !defined(IOS) PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; +PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; +PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; +PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; #endif @@ -77,16 +80,34 @@ void CheckGLExtensions() { gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; - gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; +#ifdef USING_GLES2 + gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer"); + if (gl_extensions.EXT_discard_framebuffer) { + glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); + } +#endif - // TODO: Change to USING_GLES2 if it works on those other platforms too #ifdef ANDROID gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0; // Load extensions that are not auto-loaded by Android. if (gl_extensions.QCOM_alpha_test) { glAlphaFuncQCOM = (PFNGLALPHAFUNCQCOMPROC)eglGetProcAddress("glAlphaFuncQCOM"); } + + // Look for EGL extensions + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + const char *eglString = eglQueryString(display, EGL_EXTENSIONS); + + gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0; + gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0; + + if (gl_extensions.EGL_NV_system_time) { + eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV"); + eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV"); + } + #endif #ifdef USING_GLES2 diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 5e04220157..bacbd7b62a 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -4,6 +4,31 @@ #include #include "gfx/gl_common.h" +#ifdef USING_GLES2 + +#ifdef ANDROID +// Additional extensions not included in GLES2/gl2ext.h from the NDK + +/* GL_QCOM_alpha_test */ +#define GL_ALPHA_TEST_QCOM 0x0BC0 +#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 +#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 + +typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); +extern PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; + +#endif + +typedef uint64_t EGLuint64NV; +typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); +typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); +extern PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; +extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; + +extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; + +#endif /* EGL_NV_system_time */ + // OpenGL state cache. Should convert all code to use this instead of directly calling glEnable etc, // as GL state changes can be expensive on some hardware. @@ -210,6 +235,11 @@ struct GLExtensions { bool EXT_swap_control_tear; bool QCOM_alpha_test; bool OES_mapbuffer; + + // EGL extensions + + bool EGL_NV_system_time; + bool EGL_NV_coverage_sample; }; extern GLExtensions gl_extensions; From 7d1601d682fd295227fb8e55b3873afdc1fb6cfa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 26 Jul 2013 23:04:53 -0700 Subject: [PATCH 0551/1445] Fix and override/overload warning. --- ui/view.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/view.h b/ui/view.h index f09c6810e2..a49371512b 100644 --- a/ui/view.h +++ b/ui/view.h @@ -556,7 +556,7 @@ class Spacer : public InertView { public: Spacer(LayoutParams *layoutParams = 0) : InertView(layoutParams) {} - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) { + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { w = 0.0f; h = 0.0f; } virtual void Draw(UIContext &dc) {} From 5c7383546d5ac1140c9cfbf8e37219aed392bc1f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 26 Jul 2013 23:05:04 -0700 Subject: [PATCH 0552/1445] Fix a signed/unsigned warning. --- android/native-audio-so.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 15a9b98fbd..4448b8173e 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -94,7 +94,7 @@ extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, i result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); assert(SL_RESULT_SUCCESS == result); - int sr = SL_SAMPLINGRATE_44_1; + SLuint32 sr = SL_SAMPLINGRATE_44_1; if (sampleRate == 48000) { sr = SL_SAMPLINGRATE_48; } From 24aed4003130a7618c060f21dc4fabbe1d97abef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 27 Jul 2013 10:15:53 +0200 Subject: [PATCH 0553/1445] Only try to use NV_system_time on Android. --- base/timeutil.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/timeutil.cpp b/base/timeutil.cpp index 7aceef6c32..375b545ec9 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -38,6 +38,7 @@ uint64_t _frequency = 0; uint64_t _starttime = 0; double real_time_now() { +#ifdef ANDROID if (false && gl_extensions.EGL_NV_system_time) { // This is needed to profile using PerfHUD on Tegra if (_frequency == 0) { @@ -47,9 +48,10 @@ double real_time_now() { uint64_t cur = eglGetSystemTimeNV(); int64_t diff = cur - _starttime; - + return (double)diff / (double)_frequency; } +#endif static time_t start; struct timeval tv; From 31274a78c53fe0609ec4f50fb3daccdb4c89ceac Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 27 Jul 2013 18:15:59 +0200 Subject: [PATCH 0554/1445] More GLES extension loading --- gfx_es2/gl_state.cpp | 36 +++++++++++++++++++++++++++--------- gfx_es2/gl_state.h | 17 +++++++++++++++-- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index bdf778cf46..5b42ff264c 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -1,17 +1,23 @@ -#include +#include "base/logging.h" #include "gl_state.h" #ifdef _WIN32 #include "GL/wglew.h" #endif - -#if defined(USING_GLES2) && !defined(IOS) +#if defined(USING_GLES2) +#if defined(ANDROID) PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; -PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; #endif - +#if !defined(IOS) +PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; +PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; +PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; +PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES; +PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; +#endif +#endif OpenGLState glstate; GLExtensions gl_extensions; @@ -53,8 +59,10 @@ void OpenGLState::Restore() { stencilFunc.restore(); count++; dither.restore(); count++; - - assert(count == state_count && "OpenGLState::Restore is missing some states"); + + if (count != state_count) { + FLOG("OpenGLState::Restore is missing some states"); + } } // http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array @@ -76,12 +84,22 @@ void CheckGLExtensions() { // const char *glXString = glXQueryExtensionString(); // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; #endif + +#ifdef USING_GLES2 gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0; gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; -#ifdef USING_GLES2 + gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0; + if (gl_extensions.OES_vertex_array_object) { + glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" ); + glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress ( "glBindVertexArrayOES" ); + glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress ( "glDeleteVertexArraysOES" ); + glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" ); + ILOG("VAO available"); + } + gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer"); if (gl_extensions.EXT_discard_framebuffer) { glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); @@ -124,4 +142,4 @@ void OpenGLState::SetVSyncInterval(int interval) { if( wglSwapIntervalEXT ) wglSwapIntervalEXT(interval); #endif -} \ No newline at end of file +} diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index bacbd7b62a..007fbc2d33 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -17,15 +17,27 @@ typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); extern PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; -#endif - typedef uint64_t EGLuint64NV; typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); extern PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; +#endif + +#if !defined(IOS) extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; +extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; +extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; +extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES; +extern PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; +#endif + +// Rename standard functions to the OES version. +#define glGenVertexArrays glGenVertexArraysOES +#define glBindVertexArray glBindVertexArrayOES +#define glDeleteVertexArrays glDeleteVertexArraysOES +#define glIsVertexArray glIsVertexArrayOES #endif /* EGL_NV_system_time */ @@ -235,6 +247,7 @@ struct GLExtensions { bool EXT_swap_control_tear; bool QCOM_alpha_test; bool OES_mapbuffer; + bool OES_vertex_array_object; // EGL extensions From cdfa331775a8edc170f89d3b4af5b0c51ed6195c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 27 Jul 2013 20:07:02 +0200 Subject: [PATCH 0555/1445] Just a sanity check --- gfx_es2/glsl_program.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 4dfd17dcae..c900bee8fb 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -223,11 +223,15 @@ int glsl_uniform_loc(const GLSLProgram *program, const char *name) { } void glsl_destroy(GLSLProgram *program) { - unregister_gl_resource_holder(program); - glDeleteShader(program->vsh_); - glDeleteShader(program->fsh_); - glDeleteProgram(program->program_); - active_programs.erase(program); + if (program) { + unregister_gl_resource_holder(program); + glDeleteShader(program->vsh_); + glDeleteShader(program->fsh_); + glDeleteProgram(program->program_); + active_programs.erase(program); + } else { + ELOG("Deleting null GLSL program!"); + } delete program; } From d0442bc2a0eb53e5c7c9398a6e58f3df3e1f6de0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 29 Jul 2013 00:25:25 +1000 Subject: [PATCH 0556/1445] Buildfix for Symbian. --- gfx_es2/gl_state.cpp | 9 +++++++-- gfx_es2/gl_state.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 5b42ff264c..042bef617f 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -10,7 +10,7 @@ PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; #endif -#if !defined(IOS) +#if !defined(IOS) && !defined(__SYMBIAN32__) PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; @@ -91,6 +91,10 @@ void CheckGLExtensions() { gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; +#ifdef __SYMBIAN32__ + gl_extensions.OES_vertex_array_object = false; + gl_extensions.EXT_discard_framebuffer = false; +#else gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0; if (gl_extensions.OES_vertex_array_object) { glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" ); @@ -100,11 +104,12 @@ void CheckGLExtensions() { ILOG("VAO available"); } - gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer"); + gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; if (gl_extensions.EXT_discard_framebuffer) { glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); } #endif +#endif #ifdef ANDROID gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 007fbc2d33..3b4c8784cd 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -25,7 +25,7 @@ extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; #endif -#if !defined(IOS) +#if !defined(IOS) && !defined(__SYMBIAN32__) extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; From 345a67144a5d71325421da6477834d2f9c81d5f7 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 29 Jul 2013 12:22:20 +1000 Subject: [PATCH 0557/1445] Meego buildfix. --- gfx_es2/gl_state.cpp | 4 ++-- gfx_es2/gl_state.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 042bef617f..6351c0f997 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -10,7 +10,7 @@ PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; #endif -#if !defined(IOS) && !defined(__SYMBIAN32__) +#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; @@ -91,7 +91,7 @@ void CheckGLExtensions() { gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; -#ifdef __SYMBIAN32__ +#if defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) gl_extensions.OES_vertex_array_object = false; gl_extensions.EXT_discard_framebuffer = false; #else diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 3b4c8784cd..889bc2f9fe 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -25,7 +25,7 @@ extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; #endif -#if !defined(IOS) && !defined(__SYMBIAN32__) +#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; From 411a41e948de1244a8583ac2ac7e798155657400 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 29 Jul 2013 22:35:34 +0200 Subject: [PATCH 0558/1445] Move a couple of math functions heret: --- math/math_util.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/math/math_util.h b/math/math_util.h index 6a7ff6b3b4..dd5450ab37 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -95,6 +95,27 @@ inline bool my_isnan(float f) { return ((f2u.u & 0x7F800000) == 0x7F800000) && (f2u.u & 0x7FFFFF); } +inline int is_even(float d) { + float int_part; + modff(d / 2.0f, &int_part); + return 2.0f * int_part == d; +} + +// Rounds *.5 to closest even number +inline float round_ieee_754(float d) { + float i = floorf(d); + d -= i; + if(d < 0.5f) + return i; + if(d > 0.5f) + return i + 1.0f; + if(is_even(i)) + return i; + return i + 1.0f; +} + + + // FPU control. void EnableFZ(); void DisableFZ(); From 08376fe8c2449d4bc3931c7e9ed7867dbba69cd1 Mon Sep 17 00:00:00 2001 From: The Dax Date: Mon, 29 Jul 2013 18:46:23 -0400 Subject: [PATCH 0559/1445] Visual Studio 2012 build fix. --- thread/thread.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thread/thread.h b/thread/thread.h index 21ea1f0c41..6a79c7a8a4 100644 --- a/thread/thread.h +++ b/thread/thread.h @@ -245,7 +245,7 @@ private: void Run() { func(); } private: - C const func; + C func; }; template From 45c5da2b777fe4c7a57b54f9aab575c4f6519838 Mon Sep 17 00:00:00 2001 From: The Dax Date: Mon, 29 Jul 2013 18:55:52 -0400 Subject: [PATCH 0560/1445] Ifdef it instead. --- thread/thread.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/thread/thread.h b/thread/thread.h index 6a79c7a8a4..58d60b725f 100644 --- a/thread/thread.h +++ b/thread/thread.h @@ -245,7 +245,12 @@ private: void Run() { func(); } private: +// Visual Studio 2012 needs this, or else it complains about losing const-volatile qualifiers. +#if _MSC_VER >= 1700 C func; +#else + C const func; +#endif }; template From b7fbb7fbc1ca19a0192d631e8a0be60477ddcccd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 30 Jul 2013 22:26:02 +0200 Subject: [PATCH 0561/1445] Move some fp16 math utils here. --- math/math_util.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/math/math_util.h b/math/math_util.h index dd5450ab37..ad18ee8fb0 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -114,7 +114,72 @@ inline float round_ieee_754(float d) { return i + 1.0f; } +union FP32 { + uint32_t u; + float f; +}; +struct FP16 { + uint16_t u; +}; + +// magic code from ryg: http://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/ +// See also SSE2 version: https://gist.github.com/rygorous/2144712 +inline FP32 half_to_float_fast5(FP16 h) +{ + static const FP32 magic = { (127 + (127 - 15)) << 23 }; + static const FP32 was_infnan = { (127 + 16) << 23 }; + FP32 o; + o.u = (h.u & 0x7fff) << 13; // exponent/mantissa bits + o.f *= magic.f; // exponent adjust + if (o.f >= was_infnan.f) // make sure Inf/NaN survive + o.u |= 255 << 23; + o.u |= (h.u & 0x8000) << 16; // sign bit + return o; +} + +inline float ExpandHalf(uint16_t half) { + FP16 fp16; + fp16.u = half; + FP32 fp = half_to_float_fast5(fp16); + return fp.f; +} + +// More magic code: https://gist.github.com/rygorous/2156668 +inline FP16 float_to_half_fast3(FP32 f) +{ + static const FP32 f32infty = { 255 << 23 }; + static const FP32 f16infty = { 31 << 23 }; + static const FP32 magic = { 15 << 23 }; + static const uint32_t sign_mask = 0x80000000u; + static const uint32_t round_mask = ~0xfffu; + FP16 o = { 0 }; + + uint32_t sign = f.u & sign_mask; + f.u ^= sign; + + if (f.u >= f32infty.u) // Inf or NaN (all exponent bits set) + o.u = (f.u > f32infty.u) ? 0x7e00 : 0x7c00; // NaN->qNaN and Inf->Inf + else // (De)normalized number or zero + { + f.u &= round_mask; + f.f *= magic.f; + f.u -= round_mask; + if (f.u > f16infty.u) f.u = f16infty.u; // Clamp to signed infinity if overflowed + + o.u = f.u >> 13; // Take the bits! + } + + o.u |= sign >> 16; + return o; +} + +inline uint16_t ShrinkToHalf(float full) { + FP32 fp32; + fp32.f = full; + FP16 fp = float_to_half_fast3(fp32); + return fp.u; +} // FPU control. void EnableFZ(); From 9ae2e857f8590af93a303301b7fb1174189bee95 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 31 Jul 2013 20:12:20 +0200 Subject: [PATCH 0562/1445] Prevent crashing from bogus motioninput events (with no device) --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 3ed6537871..a363e6b1ba 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -402,6 +402,10 @@ public class NativeActivity extends Activity { if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) { if (Build.VERSION.SDK_INT >= 12) { InputDeviceState state = getInputDeviceState(event); + if (state == null) { + Log.w(TAG, "Joystick event but failed to get input device state."); + return super.onGenericMotionEvent(event); + } state.onJoystickMotion(event); return true; } From adee7f9c90132402c6570a63854becfaf797d9ba Mon Sep 17 00:00:00 2001 From: Jake Traynham Date: Fri, 2 Aug 2013 16:44:21 -0500 Subject: [PATCH 0563/1445] Fix for iOS build errors --- gfx_es2/gl_state.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 6351c0f997..026d24989e 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -4,7 +4,7 @@ #include "GL/wglew.h" #endif -#if defined(USING_GLES2) +#if defined(USING_GLES2) #if defined(ANDROID) PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; @@ -59,7 +59,7 @@ void OpenGLState::Restore() { stencilFunc.restore(); count++; dither.restore(); count++; - + if (count != state_count) { FLOG("OpenGLState::Restore is missing some states"); } @@ -91,7 +91,7 @@ void CheckGLExtensions() { gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; -#if defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) +#if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) gl_extensions.OES_vertex_array_object = false; gl_extensions.EXT_discard_framebuffer = false; #else @@ -120,7 +120,7 @@ void CheckGLExtensions() { // Look for EGL extensions EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - + const char *eglString = eglQueryString(display, EGL_EXTENSIONS); gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0; From 48498d183324901176b77807e71c7f1448562f82 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 5 Aug 2013 03:30:34 +1000 Subject: [PATCH 0564/1445] Rename KEYCODE to NKCODE (native key code) to kill name collision. Implement keymapping for Blackberry. --- base/BlackberryMain.cpp | 32 +- base/BlackberryMain.h | 7 +- base/KeyCodeTranslationFromBlackberry.h | 78 ++++ base/KeyCodeTranslationFromSDL.h | 172 ++++----- base/PCMain.cpp | 46 +-- input/input_state.cpp | 28 +- input/keycodes.h | 462 ++++++++++++------------ ui/view.cpp | 24 +- ui/viewgroup.cpp | 4 +- 9 files changed, 454 insertions(+), 399 deletions(-) create mode 100644 base/KeyCodeTranslationFromBlackberry.h diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 3d48b716f0..30c69e96b2 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -8,9 +8,8 @@ #include #include -#include "input/keycodes.h" - #include "BlackberryMain.h" +#include "base/KeyCodeTranslationFromBlackberry.h" // Simple implementations of System functions @@ -53,28 +52,6 @@ void LaunchEmail(const char *email_address) InputState input_state; -// Input - urgh, these may collide with the android keycodes when we bring in input/keycodes.h -const unsigned int buttonMappings[18] = { - KEYCODE_K, //Cross - KEYCODE_L, //Circle - KEYCODE_J, //Square - KEYCODE_I, //Triangle - KEYCODE_Q, //LBUMPER - KEYCODE_P, //RBUMPER - KEYCODE_SPACE, //START - KEYCODE_ZERO, //SELECT - KEYCODE_W, //UP - KEYCODE_S, //DOWN - KEYCODE_A, //LEFT - KEYCODE_D, //RIGHT - 0, //MENU (SwipeDown) - KEYCODE_BACKSPACE, //BACK - KEYCODE_W, //JOY UP - KEYCODE_S, //JOY DOWN - KEYCODE_A, //JOY LEFT - KEYCODE_D, //JOY RIGHT -}; - void SimulateGamepad(InputState *input) { input->pad_lstick_x = 0; input->pad_lstick_y = 0; @@ -158,7 +135,7 @@ void BlackberryMain::handleInput(screen_event_t screen_event) int flags, value; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value); - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, value, flags)); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawBlackberrytoNative.find(value)->second, (flags & KEY_DOWN) ? KEY_DOWN : KEY_UP)); break; // Gamepad // TODO: Isn't using new input system yet @@ -247,7 +224,7 @@ void BlackberryMain::runMain() { { case NAVIGATOR_BACK: case NAVIGATOR_SWIPE_DOWN: - pad_buttons |= PAD_BUTTON_MENU; + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE, KEY_DOWN)); break; case NAVIGATOR_EXIT: return; @@ -270,8 +247,7 @@ void BlackberryMain::runMain() { } // TODO: This is broken. Instead we should just send keyboard events through using NativeKey and not // even bother with these bitfields. - input_state.pad_buttons = pad_buttons | controller_buttons; - pad_buttons &= ~PAD_BUTTON_MENU; + input_state.pad_buttons = controller_buttons; UpdateInputState(&input_state); NativeUpdate(input_state); // Work in Progress diff --git a/base/BlackberryMain.h b/base/BlackberryMain.h index 0d20442f6d..4a69c49afc 100644 --- a/base/BlackberryMain.h +++ b/base/BlackberryMain.h @@ -12,9 +12,10 @@ #include // Invoke Service #include // Keyboard Service #include // Accelerometer -#include #include // Dialog Service (Toast=BB10) #include // Vibrate Service (BB10) +#include "sys/keycodes.h" +#include "input/keycodes.h" // Display #include @@ -47,7 +48,7 @@ public: BlackberryMain(int argc, char *argv[]) : emulating(false), screen_ui(0), screen_emu(0), - pad_buttons(0), controller_buttons(0), + controller_buttons(0), egl_cont(EGL_NO_CONTEXT) { startMain(argc, argv); @@ -79,7 +80,7 @@ private: int ndisplays; int screen_ui, screen_emu; bool emulating; - int pad_buttons, controller_buttons; + int controller_buttons; EGLDisplay* egl_disp; EGLSurface* egl_surf; EGLContext egl_cont; diff --git a/base/KeyCodeTranslationFromBlackberry.h b/base/KeyCodeTranslationFromBlackberry.h new file mode 100644 index 0000000000..e0a929c717 --- /dev/null +++ b/base/KeyCodeTranslationFromBlackberry.h @@ -0,0 +1,78 @@ +#include +#include "util/const_map.h" + +// TODO: Add any missing keys +static const std::map KeyMapRawBlackberrytoNative = InitConstMap + (KEYCODE_P, NKCODE_P) + (KEYCODE_O, NKCODE_O) + (KEYCODE_I, NKCODE_I) + (KEYCODE_U, NKCODE_U) + (KEYCODE_Y, NKCODE_Y) + (KEYCODE_T, NKCODE_T) + (KEYCODE_R, NKCODE_R) + (KEYCODE_E, NKCODE_E) + (KEYCODE_W, NKCODE_W) + (KEYCODE_Q, NKCODE_Q) + (KEYCODE_L, NKCODE_L) + (KEYCODE_K, NKCODE_K) + (KEYCODE_J, NKCODE_J) + (KEYCODE_H, NKCODE_H) + (KEYCODE_G, NKCODE_G) + (KEYCODE_F, NKCODE_F) + (KEYCODE_D, NKCODE_D) + (KEYCODE_S, NKCODE_S) + (KEYCODE_A, NKCODE_A) + (KEYCODE_M, NKCODE_M) + (KEYCODE_N, NKCODE_N) + (KEYCODE_B, NKCODE_B) + (KEYCODE_V, NKCODE_V) + (KEYCODE_C, NKCODE_C) + (KEYCODE_X, NKCODE_X) + (KEYCODE_Z, NKCODE_Z) + (KEYCODE_COMMA, NKCODE_COMMA) + (KEYCODE_PERIOD, NKCODE_PERIOD) + (KEYCODE_LEFT_ALT, NKCODE_ALT_LEFT) + (KEYCODE_RIGHT_ALT, NKCODE_ALT_RIGHT) + (KEYCODE_LEFT_SHIFT, NKCODE_SHIFT_LEFT) + (KEYCODE_RIGHT_SHIFT, NKCODE_SHIFT_RIGHT) + (KEYCODE_TAB, NKCODE_TAB) + (KEYCODE_SPACE, NKCODE_SPACE) + (KEYCODE_RETURN, NKCODE_ENTER) + (KEYCODE_MINUS, NKCODE_MINUS) + (KEYCODE_EQUAL, NKCODE_EQUALS) + (KEYCODE_LEFT_BRACKET, NKCODE_LEFT_BRACKET) + (KEYCODE_RIGHT_BRACKET, NKCODE_RIGHT_BRACKET) + (KEYCODE_BACK_SLASH, NKCODE_BACKSLASH) + (KEYCODE_SEMICOLON, NKCODE_SEMICOLON) + (KEYCODE_APOSTROPHE, NKCODE_APOSTROPHE) + (KEYCODE_SLASH, NKCODE_SLASH) + (KEYCODE_AT, NKCODE_AT) + (KEYCODE_PLUS, NKCODE_PLUS) + (KEYCODE_ESCAPE, NKCODE_ESCAPE) + (KEYCODE_DELETE, NKCODE_FORWARD_DEL) + (KEYCODE_LEFT_CTRL, NKCODE_CTRL_LEFT) + (KEYCODE_RIGHT_CTRL, NKCODE_CTRL_RIGHT) + (KEYCODE_CAPS_LOCK, NKCODE_CAPS_LOCK) + (KEYCODE_HOME, NKCODE_MOVE_HOME) + (KEYCODE_END, NKCODE_MOVE_END) + (KEYCODE_INSERT, NKCODE_INSERT) + (KEYCODE_ZERO, NKCODE_0) + (KEYCODE_ONE, NKCODE_1) + (KEYCODE_TWO, NKCODE_2) + (KEYCODE_THREE, NKCODE_3) + (KEYCODE_FOUR, NKCODE_4) + (KEYCODE_FIVE, NKCODE_5) + (KEYCODE_SIX, NKCODE_6) + (KEYCODE_SEVEN, NKCODE_7) + (KEYCODE_EIGHT, NKCODE_8) + (KEYCODE_NINE, NKCODE_9) + (KEYCODE_KP_DIVIDE, NKCODE_NUMPAD_DIVIDE) + (KEYCODE_KP_MULTIPLY, NKCODE_NUMPAD_MULTIPLY) + (KEYCODE_KP_MINUS, NKCODE_NUMPAD_SUBTRACT) + (KEYCODE_KP_PLUS, NKCODE_NUMPAD_ADD) + (KEYCODE_KP_ENTER, NKCODE_NUMPAD_ENTER) + (KEYCODE_LEFT, NKCODE_DPAD_LEFT) + (KEYCODE_UP, NKCODE_DPAD_UP) + (KEYCODE_RIGHT, NKCODE_DPAD_RIGHT) + (KEYCODE_DOWN, NKCODE_DPAD_DOWN); + diff --git a/base/KeyCodeTranslationFromSDL.h b/base/KeyCodeTranslationFromSDL.h index 7f349be88a..bccc8e237c 100644 --- a/base/KeyCodeTranslationFromSDL.h +++ b/base/KeyCodeTranslationFromSDL.h @@ -3,93 +3,93 @@ // TODO: Add any missing keys static const std::map KeyMapRawSDLtoNative = InitConstMap - (SDLK_p, KEYCODE_P) - (SDLK_o, KEYCODE_O) - (SDLK_i, KEYCODE_I) - (SDLK_u, KEYCODE_U) - (SDLK_y, KEYCODE_Y) - (SDLK_t, KEYCODE_T) - (SDLK_r, KEYCODE_R) - (SDLK_e, KEYCODE_E) - (SDLK_w, KEYCODE_W) - (SDLK_q, KEYCODE_Q) - (SDLK_l, KEYCODE_L) - (SDLK_k, KEYCODE_K) - (SDLK_j, KEYCODE_J) - (SDLK_h, KEYCODE_H) - (SDLK_g, KEYCODE_G) - (SDLK_f, KEYCODE_F) - (SDLK_d, KEYCODE_D) - (SDLK_s, KEYCODE_S) - (SDLK_a, KEYCODE_A) - (SDLK_m, KEYCODE_M) - (SDLK_n, KEYCODE_N) - (SDLK_b, KEYCODE_B) - (SDLK_v, KEYCODE_V) - (SDLK_c, KEYCODE_C) - (SDLK_x, KEYCODE_X) - (SDLK_z, KEYCODE_Z) - (SDLK_COMMA, KEYCODE_COMMA) - (SDLK_PERIOD, KEYCODE_PERIOD) - (SDLK_LALT, KEYCODE_ALT_LEFT) - (SDLK_RALT, KEYCODE_ALT_RIGHT) - (SDLK_LSHIFT, KEYCODE_SHIFT_LEFT) - (SDLK_RSHIFT, KEYCODE_SHIFT_RIGHT) - (SDLK_TAB, KEYCODE_TAB) - (SDLK_SPACE, KEYCODE_SPACE) - (SDLK_RETURN, KEYCODE_ENTER) - (SDLK_MINUS, KEYCODE_MINUS) - (SDLK_EQUALS, KEYCODE_EQUALS) - (SDLK_LEFTBRACKET, KEYCODE_LEFT_BRACKET) - (SDLK_RIGHTBRACKET, KEYCODE_RIGHT_BRACKET) - (SDLK_BACKSLASH, KEYCODE_BACKSLASH) - (SDLK_SEMICOLON, KEYCODE_SEMICOLON) - // (SDLK_, KEYCODE_APOSTROPHE) // I cannot find the SDL equiv - (SDLK_SLASH, KEYCODE_SLASH) - (SDLK_AT, KEYCODE_AT) - (SDLK_PLUS, KEYCODE_PLUS) - (SDLK_PAGEUP, KEYCODE_PAGE_UP) - (SDLK_PAGEDOWN, KEYCODE_PAGE_DOWN) - (SDLK_ESCAPE, KEYCODE_ESCAPE) - (SDLK_DELETE, KEYCODE_FORWARD_DEL) - (SDLK_LCTRL, KEYCODE_CTRL_LEFT) - (SDLK_RCTRL, KEYCODE_CTRL_RIGHT) - (SDLK_CAPSLOCK, KEYCODE_CAPS_LOCK) - (SDLK_HOME, KEYCODE_MOVE_HOME) - (SDLK_END, KEYCODE_MOVE_END) - (SDLK_INSERT, KEYCODE_INSERT) + (SDLK_p, NKCODE_P) + (SDLK_o, NKCODE_O) + (SDLK_i, NKCODE_I) + (SDLK_u, NKCODE_U) + (SDLK_y, NKCODE_Y) + (SDLK_t, NKCODE_T) + (SDLK_r, NKCODE_R) + (SDLK_e, NKCODE_E) + (SDLK_w, NKCODE_W) + (SDLK_q, NKCODE_Q) + (SDLK_l, NKCODE_L) + (SDLK_k, NKCODE_K) + (SDLK_j, NKCODE_J) + (SDLK_h, NKCODE_H) + (SDLK_g, NKCODE_G) + (SDLK_f, NKCODE_F) + (SDLK_d, NKCODE_D) + (SDLK_s, NKCODE_S) + (SDLK_a, NKCODE_A) + (SDLK_m, NKCODE_M) + (SDLK_n, NKCODE_N) + (SDLK_b, NKCODE_B) + (SDLK_v, NKCODE_V) + (SDLK_c, NKCODE_C) + (SDLK_x, NKCODE_X) + (SDLK_z, NKCODE_Z) + (SDLK_COMMA, NKCODE_COMMA) + (SDLK_PERIOD, NKCODE_PERIOD) + (SDLK_LALT, NKCODE_ALT_LEFT) + (SDLK_RALT, NKCODE_ALT_RIGHT) + (SDLK_LSHIFT, NKCODE_SHIFT_LEFT) + (SDLK_RSHIFT, NKCODE_SHIFT_RIGHT) + (SDLK_TAB, NKCODE_TAB) + (SDLK_SPACE, NKCODE_SPACE) + (SDLK_RETURN, NKCODE_ENTER) + (SDLK_MINUS, NKCODE_MINUS) + (SDLK_EQUALS, NKCODE_EQUALS) + (SDLK_LEFTBRACKET, NKCODE_LEFT_BRACKET) + (SDLK_RIGHTBRACKET, NKCODE_RIGHT_BRACKET) + (SDLK_BACKSLASH, NKCODE_BACKSLASH) + (SDLK_SEMICOLON, NKCODE_SEMICOLON) + // (SDLK_, NKCODE_APOSTROPHE) // I cannot find the SDL equiv + (SDLK_SLASH, NKCODE_SLASH) + (SDLK_AT, NKCODE_AT) + (SDLK_PLUS, NKCODE_PLUS) + (SDLK_PAGEUP, NKCODE_PAGE_UP) + (SDLK_PAGEDOWN, NKCODE_PAGE_DOWN) + (SDLK_ESCAPE, NKCODE_ESCAPE) + (SDLK_DELETE, NKCODE_FORWARD_DEL) + (SDLK_LCTRL, NKCODE_CTRL_LEFT) + (SDLK_RCTRL, NKCODE_CTRL_RIGHT) + (SDLK_CAPSLOCK, NKCODE_CAPS_LOCK) + (SDLK_HOME, NKCODE_MOVE_HOME) + (SDLK_END, NKCODE_MOVE_END) + (SDLK_INSERT, NKCODE_INSERT) /* Somehow these are undefined * on my comp? - (SDLK_KP_0, KEYCODE_NUMPAD_0) - (SDLK_KP_1, KEYCODE_NUMPAD_1) - (SDLK_KP_2, KEYCODE_NUMPAD_2) - (SDLK_KP_3, KEYCODE_NUMPAD_3) - (SDLK_KP_4, KEYCODE_NUMPAD_4) - (SDLK_KP_5, KEYCODE_NUMPAD_5) - (SDLK_KP_6, KEYCODE_NUMPAD_6) - (SDLK_KP_7, KEYCODE_NUMPAD_7) - (SDLK_KP_8, KEYCODE_NUMPAD_8) - (SDLK_KP_9, KEYCODE_NUMPAD_9) + (SDLK_KP_0, NKCODE_NUMPAD_0) + (SDLK_KP_1, NKCODE_NUMPAD_1) + (SDLK_KP_2, NKCODE_NUMPAD_2) + (SDLK_KP_3, NKCODE_NUMPAD_3) + (SDLK_KP_4, NKCODE_NUMPAD_4) + (SDLK_KP_5, NKCODE_NUMPAD_5) + (SDLK_KP_6, NKCODE_NUMPAD_6) + (SDLK_KP_7, NKCODE_NUMPAD_7) + (SDLK_KP_8, NKCODE_NUMPAD_8) + (SDLK_KP_9, NKCODE_NUMPAD_9) */ - (SDLK_KP_DIVIDE, KEYCODE_NUMPAD_DIVIDE) - (SDLK_KP_MULTIPLY, KEYCODE_NUMPAD_MULTIPLY) - (SDLK_KP_MINUS, KEYCODE_NUMPAD_SUBTRACT) - (SDLK_KP_PLUS, KEYCODE_NUMPAD_ADD) - (SDLK_KP_PERIOD, KEYCODE_NUMPAD_DOT) - (SDLK_KP_ENTER, KEYCODE_NUMPAD_ENTER) - (SDLK_KP_EQUALS, KEYCODE_NUMPAD_EQUALS) - (SDLK_1, KEYCODE_1) - (SDLK_2, KEYCODE_2) - (SDLK_3, KEYCODE_3) - (SDLK_4, KEYCODE_4) - (SDLK_5, KEYCODE_5) - (SDLK_6, KEYCODE_6) - (SDLK_7, KEYCODE_7) - (SDLK_8, KEYCODE_8) - (SDLK_9, KEYCODE_9) - (SDLK_0, KEYCODE_0) - (SDLK_LEFT, KEYCODE_DPAD_LEFT) - (SDLK_UP, KEYCODE_DPAD_UP) - (SDLK_RIGHT, KEYCODE_DPAD_RIGHT) - (SDLK_DOWN, KEYCODE_DPAD_DOWN); + (SDLK_KP_DIVIDE, NKCODE_NUMPAD_DIVIDE) + (SDLK_KP_MULTIPLY, NKCODE_NUMPAD_MULTIPLY) + (SDLK_KP_MINUS, NKCODE_NUMPAD_SUBTRACT) + (SDLK_KP_PLUS, NKCODE_NUMPAD_ADD) + (SDLK_KP_PERIOD, NKCODE_NUMPAD_DOT) + (SDLK_KP_ENTER, NKCODE_NUMPAD_ENTER) + (SDLK_KP_EQUALS, NKCODE_NUMPAD_EQUALS) + (SDLK_1, NKCODE_1) + (SDLK_2, NKCODE_2) + (SDLK_3, NKCODE_3) + (SDLK_4, NKCODE_4) + (SDLK_5, NKCODE_5) + (SDLK_6, NKCODE_6) + (SDLK_7, NKCODE_7) + (SDLK_8, NKCODE_8) + (SDLK_9, NKCODE_9) + (SDLK_0, NKCODE_0) + (SDLK_LEFT, NKCODE_DPAD_LEFT) + (SDLK_UP, NKCODE_DPAD_UP) + (SDLK_RIGHT, NKCODE_DPAD_RIGHT) + (SDLK_DOWN, NKCODE_DPAD_DOWN); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 52695d0393..b4a7b6795a 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -531,21 +531,21 @@ int main(int argc, char *argv[]) { // This is just a standard mapping that matches the X360 controller on MacOSX. Names will probably be all wrong // on other controllers. std::map SDLJoyButtonMap; - SDLJoyButtonMap[0] = KEYCODE_DPAD_UP; - SDLJoyButtonMap[1] = KEYCODE_DPAD_DOWN; - SDLJoyButtonMap[2] = KEYCODE_DPAD_LEFT; - SDLJoyButtonMap[3] = KEYCODE_DPAD_RIGHT; - SDLJoyButtonMap[4] = KEYCODE_BUTTON_10; - SDLJoyButtonMap[5] = KEYCODE_BUTTON_9; - SDLJoyButtonMap[6] = KEYCODE_BUTTON_5; - SDLJoyButtonMap[7] = KEYCODE_BUTTON_6; - SDLJoyButtonMap[8] = KEYCODE_BUTTON_7; - SDLJoyButtonMap[9] = KEYCODE_BUTTON_8; - SDLJoyButtonMap[10] = KEYCODE_BUTTON_SELECT; - SDLJoyButtonMap[11] = KEYCODE_BUTTON_2; - SDLJoyButtonMap[12] = KEYCODE_BUTTON_3; - SDLJoyButtonMap[13] = KEYCODE_BUTTON_4; - SDLJoyButtonMap[14] = KEYCODE_BUTTON_1; + SDLJoyButtonMap[0] = NKCODE_DPAD_UP; + SDLJoyButtonMap[1] = NKCODE_DPAD_DOWN; + SDLJoyButtonMap[2] = NKCODE_DPAD_LEFT; + SDLJoyButtonMap[3] = NKCODE_DPAD_RIGHT; + SDLJoyButtonMap[4] = NKCODE_BUTTON_10; + SDLJoyButtonMap[5] = NKCODE_BUTTON_9; + SDLJoyButtonMap[6] = NKCODE_BUTTON_5; + SDLJoyButtonMap[7] = NKCODE_BUTTON_6; + SDLJoyButtonMap[8] = NKCODE_BUTTON_7; + SDLJoyButtonMap[9] = NKCODE_BUTTON_8; + SDLJoyButtonMap[10] = NKCODE_BUTTON_SELECT; + SDLJoyButtonMap[11] = NKCODE_BUTTON_2; + SDLJoyButtonMap[12] = NKCODE_BUTTON_3; + SDLJoyButtonMap[13] = NKCODE_BUTTON_4; + SDLJoyButtonMap[14] = NKCODE_BUTTON_1; std::map SDLJoyAxisMap; SDLJoyAxisMap[0] = JOYSTICK_AXIS_X; @@ -643,13 +643,13 @@ int main(int argc, char *argv[]) { input.flags = TOUCH_DOWN; input.id = 0; NativeTouch(input); - KeyInput key(DEVICE_ID_MOUSE, KEYCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { - KeyInput key(DEVICE_ID_MOUSE, KEYCODE_EXT_MOUSEBUTTON_2, KEY_DOWN); + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN); NativeKey(key); } break; @@ -657,7 +657,7 @@ int main(int argc, char *argv[]) { { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = KEYCODE_EXT_MOUSEWHEEL_UP; + key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_DOWN; NativeKey(key); } @@ -666,7 +666,7 @@ int main(int argc, char *argv[]) { { KeyInput key; key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = KEYCODE_EXT_MOUSEWHEEL_DOWN; + key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_DOWN; NativeKey(key); } @@ -699,13 +699,13 @@ int main(int argc, char *argv[]) { input.flags = TOUCH_UP; input.id = 0; NativeTouch(input); - KeyInput key(DEVICE_ID_MOUSE, KEYCODE_EXT_MOUSEBUTTON_1, KEY_UP); + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP); NativeKey(key); } break; case SDL_BUTTON_RIGHT: { - KeyInput key(DEVICE_ID_MOUSE, KEYCODE_EXT_MOUSEBUTTON_2, KEY_UP); + KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP); NativeKey(key); } break; @@ -713,7 +713,7 @@ int main(int argc, char *argv[]) { { KeyInput key; key.deviceId = DEVICE_ID_DEFAULT; - key.keyCode = KEYCODE_EXT_MOUSEWHEEL_UP; + key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_UP; NativeKey(key); } @@ -722,7 +722,7 @@ int main(int argc, char *argv[]) { { KeyInput key; key.deviceId = DEVICE_ID_DEFAULT; - key.keyCode = KEYCODE_EXT_MOUSEWHEEL_DOWN; + key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_UP; NativeKey(key); } diff --git a/input/input_state.cpp b/input/input_state.cpp index f8bb1144ae..3261f3882e 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -16,24 +16,24 @@ const char *GetDeviceName(int deviceId) { // Default pad mapping to button bits. Used for UI and stuff that doesn't use PPSSPP's key mapping system. int MapPadButtonFixed(int keycode) { switch (keycode) { - case KEYCODE_BACK: return PAD_BUTTON_BACK; // Back - case KEYCODE_MENU: return PAD_BUTTON_MENU; // Menu + case NKCODE_BACK: return PAD_BUTTON_BACK; // Back + case NKCODE_MENU: return PAD_BUTTON_MENU; // Menu - case KEYCODE_Z: - case KEYCODE_SPACE: - case KEYCODE_BUTTON_1: - case KEYCODE_BUTTON_A: // same as KEYCODE_OUYA_BUTTON_O and KEYCODE_BUTTON_CROSS_PS3 + case NKCODE_Z: + case NKCODE_SPACE: + case NKCODE_BUTTON_1: + case NKCODE_BUTTON_A: // same as NKCODE_OUYA_BUTTON_O and NKCODE_BUTTON_CROSS_PS3 return PAD_BUTTON_A; - case KEYCODE_ESCAPE: - case KEYCODE_BUTTON_2: - case KEYCODE_BUTTON_B: // same as KEYCODE_OUYA_BUTTON_A and KEYCODE_BUTTON_CIRCLE_PS3: + case NKCODE_ESCAPE: + case NKCODE_BUTTON_2: + case NKCODE_BUTTON_B: // same as NKCODE_OUYA_BUTTON_A and NKCODE_BUTTON_CIRCLE_PS3: return PAD_BUTTON_B; - case KEYCODE_DPAD_LEFT: return PAD_BUTTON_LEFT; - case KEYCODE_DPAD_RIGHT: return PAD_BUTTON_RIGHT; - case KEYCODE_DPAD_UP: return PAD_BUTTON_UP; - case KEYCODE_DPAD_DOWN: return PAD_BUTTON_DOWN; + case NKCODE_DPAD_LEFT: return PAD_BUTTON_LEFT; + case NKCODE_DPAD_RIGHT: return PAD_BUTTON_RIGHT; + case NKCODE_DPAD_UP: return PAD_BUTTON_UP; + case NKCODE_DPAD_DOWN: return PAD_BUTTON_DOWN; default: return 0; @@ -73,4 +73,4 @@ void UpdateInputState(InputState *input, bool merge) { void EndInputState(InputState *input) { input->pad_last_buttons = input->pad_buttons; -} \ No newline at end of file +} diff --git a/input/keycodes.h b/input/keycodes.h index 07fef97740..1d7dfa3209 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -1,243 +1,243 @@ #pragma once typedef enum _keycode_t { - KEYCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed - KEYCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed - KEYCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) - KEYCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed - KEYCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed - KEYCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed - KEYCODE_DPAD_LEFT = 21, - KEYCODE_DPAD_UP = 19, - KEYCODE_DPAD_RIGHT = 22, - KEYCODE_DPAD_DOWN = 20, - KEYCODE_DPAD_CENTER = 23, - KEYCODE_UNKNOWN = 0, - KEYCODE_SOFT_LEFT = 1, - KEYCODE_SOFT_RIGHT = 2, - KEYCODE_HOME = 3, - KEYCODE_BACK = 4, - KEYCODE_CALL = 5, - KEYCODE_ENDCALL = 6, - KEYCODE_0 = 7, - KEYCODE_1 = 8, - KEYCODE_2 = 9, - KEYCODE_3 = 10, - KEYCODE_4 = 11, - KEYCODE_5 = 12, - KEYCODE_6 = 13, - KEYCODE_7 = 14, - KEYCODE_8 = 15, - KEYCODE_9 = 16, - KEYCODE_STAR = 17, - KEYCODE_POUND = 18, - KEYCODE_VOLUME_UP = 24, - KEYCODE_VOLUME_DOWN = 25, - KEYCODE_POWER = 26, - KEYCODE_CAMERA = 27, - KEYCODE_CLEAR = 28, - KEYCODE_A = 29, - KEYCODE_B = 30, - KEYCODE_C = 31, - KEYCODE_D = 32, - KEYCODE_E = 33, - KEYCODE_F = 34, - KEYCODE_G = 35, - KEYCODE_H = 36, - KEYCODE_I = 37, - KEYCODE_J = 38, - KEYCODE_K = 39, - KEYCODE_L = 40, - KEYCODE_M = 41, - KEYCODE_N = 42, - KEYCODE_O = 43, - KEYCODE_P = 44, - KEYCODE_Q = 45, - KEYCODE_R = 46, - KEYCODE_S = 47, - KEYCODE_T = 48, - KEYCODE_U = 49, - KEYCODE_V = 50, - KEYCODE_W = 51, - KEYCODE_X = 52, - KEYCODE_Y = 53, - KEYCODE_Z = 54, - KEYCODE_COMMA = 55, - KEYCODE_PERIOD = 56, - KEYCODE_ALT_LEFT = 57, - KEYCODE_ALT_RIGHT = 58, - KEYCODE_SHIFT_LEFT = 59, - KEYCODE_SHIFT_RIGHT = 60, - KEYCODE_TAB = 61, - KEYCODE_SPACE = 62, - KEYCODE_SYM = 63, - KEYCODE_EXPLORER = 64, - KEYCODE_ENVELOPE = 65, - KEYCODE_ENTER = 66, - KEYCODE_DEL = 67, - KEYCODE_GRAVE = 68, - KEYCODE_MINUS = 69, - KEYCODE_EQUALS = 70, - KEYCODE_LEFT_BRACKET = 71, - KEYCODE_RIGHT_BRACKET = 72, - KEYCODE_BACKSLASH = 73, - KEYCODE_SEMICOLON = 74, - KEYCODE_APOSTROPHE = 75, - KEYCODE_SLASH = 76, - KEYCODE_AT = 77, - KEYCODE_NUM = 78, - KEYCODE_HEADSETHOOK = 79, - KEYCODE_FOCUS = 80, - KEYCODE_PLUS = 81, - KEYCODE_MENU = 82, - KEYCODE_NOTIFICATION = 83, - KEYCODE_SEARCH = 84, - KEYCODE_MEDIA_PLAY_PAUSE = 85, - KEYCODE_MEDIA_STOP = 86, - KEYCODE_MEDIA_NEXT = 87, - KEYCODE_MEDIA_PREVIOUS = 88, - KEYCODE_MEDIA_REWIND = 89, - KEYCODE_MEDIA_FAST_FORWARD = 90, - KEYCODE_MUTE = 91, - KEYCODE_PAGE_UP = 92, - KEYCODE_PAGE_DOWN = 93, - KEYCODE_PICTSYMBOLS = 94, - KEYCODE_SWITCH_CHARSET = 95, - KEYCODE_BUTTON_A = 96, - KEYCODE_BUTTON_B = 97, - KEYCODE_BUTTON_C = 98, - KEYCODE_BUTTON_X = 99, - KEYCODE_BUTTON_Y = 100, - KEYCODE_BUTTON_Z = 101, - KEYCODE_BUTTON_L1 = 102, - KEYCODE_BUTTON_R1 = 103, - KEYCODE_BUTTON_L2 = 104, - KEYCODE_BUTTON_R2 = 105, - KEYCODE_BUTTON_THUMBL = 106, - KEYCODE_BUTTON_THUMBR = 107, - KEYCODE_BUTTON_START = 108, - KEYCODE_BUTTON_SELECT = 109, - KEYCODE_BUTTON_MODE = 110, - KEYCODE_ESCAPE = 111, - KEYCODE_FORWARD_DEL = 112, - KEYCODE_CTRL_LEFT = 113, - KEYCODE_CTRL_RIGHT = 114, - KEYCODE_CAPS_LOCK = 115, - KEYCODE_SCROLL_LOCK = 116, - KEYCODE_META_LEFT = 117, - KEYCODE_META_RIGHT = 118, - KEYCODE_FUNCTION = 119, - KEYCODE_SYSRQ = 120, - KEYCODE_BREAK = 121, - KEYCODE_MOVE_HOME = 122, - KEYCODE_MOVE_END = 123, - KEYCODE_INSERT = 124, - KEYCODE_FORWARD = 125, - KEYCODE_MEDIA_PLAY = 126, - KEYCODE_MEDIA_PAUSE = 127, - KEYCODE_MEDIA_CLOSE = 128, - KEYCODE_MEDIA_EJECT = 129, - KEYCODE_MEDIA_RECORD = 130, - KEYCODE_F1 = 131, - KEYCODE_F2 = 132, - KEYCODE_F3 = 133, - KEYCODE_F4 = 134, - KEYCODE_F5 = 135, - KEYCODE_F6 = 136, - KEYCODE_F7 = 137, - KEYCODE_F8 = 138, - KEYCODE_F9 = 139, - KEYCODE_F10 = 140, - KEYCODE_F11 = 141, - KEYCODE_F12 = 142, - KEYCODE_NUM_LOCK = 143, - KEYCODE_NUMPAD_0 = 144, - KEYCODE_NUMPAD_1 = 145, - KEYCODE_NUMPAD_2 = 146, - KEYCODE_NUMPAD_3 = 147, - KEYCODE_NUMPAD_4 = 148, - KEYCODE_NUMPAD_5 = 149, - KEYCODE_NUMPAD_6 = 150, - KEYCODE_NUMPAD_7 = 151, - KEYCODE_NUMPAD_8 = 152, - KEYCODE_NUMPAD_9 = 153, - KEYCODE_NUMPAD_DIVIDE = 154, - KEYCODE_NUMPAD_MULTIPLY = 155, - KEYCODE_NUMPAD_SUBTRACT = 156, - KEYCODE_NUMPAD_ADD = 157, - KEYCODE_NUMPAD_DOT = 158, - KEYCODE_NUMPAD_COMMA = 159, - KEYCODE_NUMPAD_ENTER = 160, - KEYCODE_NUMPAD_EQUALS = 161, - KEYCODE_NUMPAD_LEFT_PAREN = 162, - KEYCODE_NUMPAD_RIGHT_PAREN = 163, - KEYCODE_VOLUME_MUTE = 164, - KEYCODE_INFO = 165, - KEYCODE_CHANNEL_UP = 166, - KEYCODE_CHANNEL_DOWN = 167, - KEYCODE_ZOOM_IN = 168, - KEYCODE_ZOOM_OUT = 169, - KEYCODE_TV = 170, - KEYCODE_WINDOW = 171, - KEYCODE_GUIDE = 172, - KEYCODE_DVR = 173, - KEYCODE_BOOKMARK = 174, - KEYCODE_CAPTIONS = 175, - KEYCODE_SETTINGS = 176, - KEYCODE_TV_POWER = 177, - KEYCODE_TV_INPUT = 178, - KEYCODE_STB_POWER = 179, - KEYCODE_STB_INPUT = 180, - KEYCODE_AVR_POWER = 181, - KEYCODE_AVR_INPUT = 182, - KEYCODE_PROG_RED = 183, - KEYCODE_PROG_GREEN = 184, - KEYCODE_PROG_YELLOW = 185, - KEYCODE_PROG_BLUE = 186, - KEYCODE_APP_SWITCH = 187, - KEYCODE_BUTTON_1 = 188, - KEYCODE_BUTTON_2 = 189, - KEYCODE_BUTTON_3 = 190, - KEYCODE_BUTTON_4 = 191, - KEYCODE_BUTTON_5 = 192, - KEYCODE_BUTTON_6 = 193, - KEYCODE_BUTTON_7 = 194, - KEYCODE_BUTTON_8 = 195, - KEYCODE_BUTTON_9 = 196, - KEYCODE_BUTTON_10 = 197, - KEYCODE_BUTTON_11 = 198, - KEYCODE_BUTTON_12 = 199, - KEYCODE_BUTTON_13 = 200, - KEYCODE_BUTTON_14 = 201, - KEYCODE_BUTTON_15 = 202, - KEYCODE_BUTTON_16 = 203, + NKCODE_BUTTON_CROSS = 23, // trackpad or X button(Xperia Play) is pressed + NKCODE_BUTTON_CROSS_PS3 = 96, // PS3 X button is pressed + NKCODE_BUTTON_CIRCLE = 1004, // Special custom keycode generated from 'O' button by our java code. Or 'O' button if Alt is pressed (TODO) + NKCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed + NKCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed + NKCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed + NKCODE_DPAD_LEFT = 21, + NKCODE_DPAD_UP = 19, + NKCODE_DPAD_RIGHT = 22, + NKCODE_DPAD_DOWN = 20, + NKCODE_DPAD_CENTER = 23, + NKCODE_UNKNOWN = 0, + NKCODE_SOFT_LEFT = 1, + NKCODE_SOFT_RIGHT = 2, + NKCODE_HOME = 3, + NKCODE_BACK = 4, + NKCODE_CALL = 5, + NKCODE_ENDCALL = 6, + NKCODE_0 = 7, + NKCODE_1 = 8, + NKCODE_2 = 9, + NKCODE_3 = 10, + NKCODE_4 = 11, + NKCODE_5 = 12, + NKCODE_6 = 13, + NKCODE_7 = 14, + NKCODE_8 = 15, + NKCODE_9 = 16, + NKCODE_STAR = 17, + NKCODE_POUND = 18, + NKCODE_VOLUME_UP = 24, + NKCODE_VOLUME_DOWN = 25, + NKCODE_POWER = 26, + NKCODE_CAMERA = 27, + NKCODE_CLEAR = 28, + NKCODE_A = 29, + NKCODE_B = 30, + NKCODE_C = 31, + NKCODE_D = 32, + NKCODE_E = 33, + NKCODE_F = 34, + NKCODE_G = 35, + NKCODE_H = 36, + NKCODE_I = 37, + NKCODE_J = 38, + NKCODE_K = 39, + NKCODE_L = 40, + NKCODE_M = 41, + NKCODE_N = 42, + NKCODE_O = 43, + NKCODE_P = 44, + NKCODE_Q = 45, + NKCODE_R = 46, + NKCODE_S = 47, + NKCODE_T = 48, + NKCODE_U = 49, + NKCODE_V = 50, + NKCODE_W = 51, + NKCODE_X = 52, + NKCODE_Y = 53, + NKCODE_Z = 54, + NKCODE_COMMA = 55, + NKCODE_PERIOD = 56, + NKCODE_ALT_LEFT = 57, + NKCODE_ALT_RIGHT = 58, + NKCODE_SHIFT_LEFT = 59, + NKCODE_SHIFT_RIGHT = 60, + NKCODE_TAB = 61, + NKCODE_SPACE = 62, + NKCODE_SYM = 63, + NKCODE_EXPLORER = 64, + NKCODE_ENVELOPE = 65, + NKCODE_ENTER = 66, + NKCODE_DEL = 67, + NKCODE_GRAVE = 68, + NKCODE_MINUS = 69, + NKCODE_EQUALS = 70, + NKCODE_LEFT_BRACKET = 71, + NKCODE_RIGHT_BRACKET = 72, + NKCODE_BACKSLASH = 73, + NKCODE_SEMICOLON = 74, + NKCODE_APOSTROPHE = 75, + NKCODE_SLASH = 76, + NKCODE_AT = 77, + NKCODE_NUM = 78, + NKCODE_HEADSETHOOK = 79, + NKCODE_FOCUS = 80, + NKCODE_PLUS = 81, + NKCODE_MENU = 82, + NKCODE_NOTIFICATION = 83, + NKCODE_SEARCH = 84, + NKCODE_MEDIA_PLAY_PAUSE = 85, + NKCODE_MEDIA_STOP = 86, + NKCODE_MEDIA_NEXT = 87, + NKCODE_MEDIA_PREVIOUS = 88, + NKCODE_MEDIA_REWIND = 89, + NKCODE_MEDIA_FAST_FORWARD = 90, + NKCODE_MUTE = 91, + NKCODE_PAGE_UP = 92, + NKCODE_PAGE_DOWN = 93, + NKCODE_PICTSYMBOLS = 94, + NKCODE_SWITCH_CHARSET = 95, + NKCODE_BUTTON_A = 96, + NKCODE_BUTTON_B = 97, + NKCODE_BUTTON_C = 98, + NKCODE_BUTTON_X = 99, + NKCODE_BUTTON_Y = 100, + NKCODE_BUTTON_Z = 101, + NKCODE_BUTTON_L1 = 102, + NKCODE_BUTTON_R1 = 103, + NKCODE_BUTTON_L2 = 104, + NKCODE_BUTTON_R2 = 105, + NKCODE_BUTTON_THUMBL = 106, + NKCODE_BUTTON_THUMBR = 107, + NKCODE_BUTTON_START = 108, + NKCODE_BUTTON_SELECT = 109, + NKCODE_BUTTON_MODE = 110, + NKCODE_ESCAPE = 111, + NKCODE_FORWARD_DEL = 112, + NKCODE_CTRL_LEFT = 113, + NKCODE_CTRL_RIGHT = 114, + NKCODE_CAPS_LOCK = 115, + NKCODE_SCROLL_LOCK = 116, + NKCODE_META_LEFT = 117, + NKCODE_META_RIGHT = 118, + NKCODE_FUNCTION = 119, + NKCODE_SYSRQ = 120, + NKCODE_BREAK = 121, + NKCODE_MOVE_HOME = 122, + NKCODE_MOVE_END = 123, + NKCODE_INSERT = 124, + NKCODE_FORWARD = 125, + NKCODE_MEDIA_PLAY = 126, + NKCODE_MEDIA_PAUSE = 127, + NKCODE_MEDIA_CLOSE = 128, + NKCODE_MEDIA_EJECT = 129, + NKCODE_MEDIA_RECORD = 130, + NKCODE_F1 = 131, + NKCODE_F2 = 132, + NKCODE_F3 = 133, + NKCODE_F4 = 134, + NKCODE_F5 = 135, + NKCODE_F6 = 136, + NKCODE_F7 = 137, + NKCODE_F8 = 138, + NKCODE_F9 = 139, + NKCODE_F10 = 140, + NKCODE_F11 = 141, + NKCODE_F12 = 142, + NKCODE_NUM_LOCK = 143, + NKCODE_NUMPAD_0 = 144, + NKCODE_NUMPAD_1 = 145, + NKCODE_NUMPAD_2 = 146, + NKCODE_NUMPAD_3 = 147, + NKCODE_NUMPAD_4 = 148, + NKCODE_NUMPAD_5 = 149, + NKCODE_NUMPAD_6 = 150, + NKCODE_NUMPAD_7 = 151, + NKCODE_NUMPAD_8 = 152, + NKCODE_NUMPAD_9 = 153, + NKCODE_NUMPAD_DIVIDE = 154, + NKCODE_NUMPAD_MULTIPLY = 155, + NKCODE_NUMPAD_SUBTRACT = 156, + NKCODE_NUMPAD_ADD = 157, + NKCODE_NUMPAD_DOT = 158, + NKCODE_NUMPAD_COMMA = 159, + NKCODE_NUMPAD_ENTER = 160, + NKCODE_NUMPAD_EQUALS = 161, + NKCODE_NUMPAD_LEFT_PAREN = 162, + NKCODE_NUMPAD_RIGHT_PAREN = 163, + NKCODE_VOLUME_MUTE = 164, + NKCODE_INFO = 165, + NKCODE_CHANNEL_UP = 166, + NKCODE_CHANNEL_DOWN = 167, + NKCODE_ZOOM_IN = 168, + NKCODE_ZOOM_OUT = 169, + NKCODE_TV = 170, + NKCODE_WINDOW = 171, + NKCODE_GUIDE = 172, + NKCODE_DVR = 173, + NKCODE_BOOKMARK = 174, + NKCODE_CAPTIONS = 175, + NKCODE_SETTINGS = 176, + NKCODE_TV_POWER = 177, + NKCODE_TV_INPUT = 178, + NKCODE_STB_POWER = 179, + NKCODE_STB_INPUT = 180, + NKCODE_AVR_POWER = 181, + NKCODE_AVR_INPUT = 182, + NKCODE_PROG_RED = 183, + NKCODE_PROG_GREEN = 184, + NKCODE_PROG_YELLOW = 185, + NKCODE_PROG_BLUE = 186, + NKCODE_APP_SWITCH = 187, + NKCODE_BUTTON_1 = 188, + NKCODE_BUTTON_2 = 189, + NKCODE_BUTTON_3 = 190, + NKCODE_BUTTON_4 = 191, + NKCODE_BUTTON_5 = 192, + NKCODE_BUTTON_6 = 193, + NKCODE_BUTTON_7 = 194, + NKCODE_BUTTON_8 = 195, + NKCODE_BUTTON_9 = 196, + NKCODE_BUTTON_10 = 197, + NKCODE_BUTTON_11 = 198, + NKCODE_BUTTON_12 = 199, + NKCODE_BUTTON_13 = 200, + NKCODE_BUTTON_14 = 201, + NKCODE_BUTTON_15 = 202, + NKCODE_BUTTON_16 = 203, // Ouya buttons. Just here for reference, they map straight to regular android buttons // and will be mapped the same way. - KEYCODE_OUYA_BUTTON_A = 97, - KEYCODE_OUYA_BUTTON_DPAD_DOWN = 20, - KEYCODE_OUYA_BUTTON_DPAD_LEFT = 21, - KEYCODE_OUYA_BUTTON_DPAD_RIGHT = 22, - KEYCODE_OUYA_BUTTON_DPAD_UP = 19, - KEYCODE_OUYA_BUTTON_L1 = 102, - KEYCODE_OUYA_BUTTON_L2 = 104, - KEYCODE_OUYA_BUTTON_L3 = 106, - KEYCODE_OUYA_BUTTON_MENU = 82, - KEYCODE_OUYA_BUTTON_O = 96, - KEYCODE_OUYA_BUTTON_R1 = 103, - KEYCODE_OUYA_BUTTON_R2 = 105, - KEYCODE_OUYA_BUTTON_R3 = 107, - KEYCODE_OUYA_BUTTON_U = 99, - KEYCODE_OUYA_BUTTON_Y = 100, + NKCODE_OUYA_BUTTON_A = 97, + NKCODE_OUYA_BUTTON_DPAD_DOWN = 20, + NKCODE_OUYA_BUTTON_DPAD_LEFT = 21, + NKCODE_OUYA_BUTTON_DPAD_RIGHT = 22, + NKCODE_OUYA_BUTTON_DPAD_UP = 19, + NKCODE_OUYA_BUTTON_L1 = 102, + NKCODE_OUYA_BUTTON_L2 = 104, + NKCODE_OUYA_BUTTON_L3 = 106, + NKCODE_OUYA_BUTTON_MENU = 82, + NKCODE_OUYA_BUTTON_O = 96, + NKCODE_OUYA_BUTTON_R1 = 103, + NKCODE_OUYA_BUTTON_R2 = 105, + NKCODE_OUYA_BUTTON_R3 = 107, + NKCODE_OUYA_BUTTON_U = 99, + NKCODE_OUYA_BUTTON_Y = 100, // Extended keycodes, not available on Android - KEYCODE_EXT_PIPE = 1001, // The key next to Z on euro 102-key keyboards. + NKCODE_EXT_PIPE = 1001, // The key next to Z on euro 102-key keyboards. - KEYCODE_EXT_MOUSEBUTTON_1 = 1002, - KEYCODE_EXT_MOUSEBUTTON_2 = 1003, - KEYCODE_EXT_MOUSEBUTTON_3 = 1004, - KEYCODE_EXT_MOUSEWHEEL_UP = 1008, - KEYCODE_EXT_MOUSEWHEEL_DOWN = 1009 + NKCODE_EXT_MOUSEBUTTON_1 = 1002, + NKCODE_EXT_MOUSEBUTTON_2 = 1003, + NKCODE_EXT_MOUSEBUTTON_3 = 1004, + NKCODE_EXT_MOUSEWHEEL_UP = 1008, + NKCODE_EXT_MOUSEWHEEL_DOWN = 1009 } keycode_t; enum AndroidJoystickAxis { diff --git a/ui/view.cpp b/ui/view.cpp index de91e11693..5202203184 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -422,14 +422,14 @@ void TriggerButton::GetContentDimensions(const UIContext &dc, float &w, float &h void Slider::Key(const KeyInput &input) { if (HasFocus() && input.flags & KEY_DOWN) { switch (input.keyCode) { - case KEYCODE_DPAD_LEFT: - case KEYCODE_MINUS: - case KEYCODE_NUMPAD_SUBTRACT: + case NKCODE_DPAD_LEFT: + case NKCODE_MINUS: + case NKCODE_NUMPAD_SUBTRACT: *value_ -= 1; break; - case KEYCODE_DPAD_RIGHT: - case KEYCODE_PLUS: - case KEYCODE_NUMPAD_ADD: + case NKCODE_DPAD_RIGHT: + case NKCODE_PLUS: + case NKCODE_NUMPAD_ADD: *value_ -= 1; break; } @@ -466,14 +466,14 @@ void Slider::GetContentDimensions(const UIContext &dc, float &w, float &h) const void SliderFloat::Key(const KeyInput &input) { if (HasFocus() && input.flags & KEY_DOWN) { switch (input.keyCode) { - case KEYCODE_DPAD_LEFT: - case KEYCODE_MINUS: - case KEYCODE_NUMPAD_SUBTRACT: + case NKCODE_DPAD_LEFT: + case NKCODE_MINUS: + case NKCODE_NUMPAD_SUBTRACT: *value_ -= 1; break; - case KEYCODE_DPAD_RIGHT: - case KEYCODE_PLUS: - case KEYCODE_NUMPAD_ADD: + case NKCODE_DPAD_RIGHT: + case NKCODE_PLUS: + case NKCODE_NUMPAD_ADD: *value_ -= 1; break; } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 936e7285db..0a09cd1dbb 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -474,10 +474,10 @@ void ScrollView::Layout() { void ScrollView::Key(const KeyInput &input) { if (input.flags & KEY_DOWN) { switch (input.keyCode) { - case KEYCODE_EXT_MOUSEWHEEL_UP: + case NKCODE_EXT_MOUSEWHEEL_UP: ScrollRelative(-250); break; - case KEYCODE_EXT_MOUSEWHEEL_DOWN: + case NKCODE_EXT_MOUSEWHEEL_DOWN: ScrollRelative(250); break; } From 14833656898f4c711201d95446228f51722cf0cc Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 5 Aug 2013 20:08:38 +1000 Subject: [PATCH 0565/1445] Implement Qt keymapping. --- base/BlackberryMain.cpp | 2 +- ...romBlackberry.h => NKCodeFromBlackberry.h} | 0 base/NKCodeFromQt.h | 74 +++++++++++++++++++ ...deTranslationFromSDL.h => NKCodeFromSDL.h} | 0 base/PCMain.cpp | 2 +- base/QtMain.h | 16 +--- 6 files changed, 79 insertions(+), 15 deletions(-) rename base/{KeyCodeTranslationFromBlackberry.h => NKCodeFromBlackberry.h} (100%) create mode 100644 base/NKCodeFromQt.h rename base/{KeyCodeTranslationFromSDL.h => NKCodeFromSDL.h} (100%) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 30c69e96b2..085ca135fd 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -9,7 +9,7 @@ #include #include "BlackberryMain.h" -#include "base/KeyCodeTranslationFromBlackberry.h" +#include "base/NKCodeFromBlackberry.h" // Simple implementations of System functions diff --git a/base/KeyCodeTranslationFromBlackberry.h b/base/NKCodeFromBlackberry.h similarity index 100% rename from base/KeyCodeTranslationFromBlackberry.h rename to base/NKCodeFromBlackberry.h diff --git a/base/NKCodeFromQt.h b/base/NKCodeFromQt.h new file mode 100644 index 0000000000..63553582c4 --- /dev/null +++ b/base/NKCodeFromQt.h @@ -0,0 +1,74 @@ +#include "util/const_map.h" +#include + +// TODO: Add any missing keys +static const std::map KeyMapRawQttoNative = InitConstMap + (Qt::Key_P + 0x20, NKCODE_P) + (Qt::Key_O + 0x20, NKCODE_O) + (Qt::Key_I + 0x20, NKCODE_I) + (Qt::Key_U + 0x20, NKCODE_U) + (Qt::Key_Y + 0x20, NKCODE_Y) + (Qt::Key_T + 0x20, NKCODE_T) + (Qt::Key_R + 0x20, NKCODE_R) + (Qt::Key_E + 0x20, NKCODE_E) + (Qt::Key_W + 0x20, NKCODE_W) + (Qt::Key_Q + 0x20, NKCODE_Q) + (Qt::Key_L + 0x20, NKCODE_L) + (Qt::Key_K + 0x20, NKCODE_K) + (Qt::Key_J + 0x20, NKCODE_J) + (Qt::Key_H + 0x20, NKCODE_H) + (Qt::Key_G + 0x20, NKCODE_G) + (Qt::Key_F + 0x20, NKCODE_F) + (Qt::Key_D + 0x20, NKCODE_D) + (Qt::Key_S + 0x20, NKCODE_S) + (Qt::Key_A + 0x20, NKCODE_A) + (Qt::Key_M + 0x20, NKCODE_M) + (Qt::Key_N + 0x20, NKCODE_N) + (Qt::Key_B + 0x20, NKCODE_B) + (Qt::Key_V + 0x20, NKCODE_V) + (Qt::Key_C + 0x20, NKCODE_C) + (Qt::Key_X + 0x20, NKCODE_X) + (Qt::Key_Z + 0x20, NKCODE_Z) + (Qt::Key_Comma, NKCODE_COMMA) + (Qt::Key_Period, NKCODE_PERIOD) + (Qt::Key_Alt, NKCODE_ALT_LEFT) + (Qt::Key_Shift, NKCODE_SHIFT_LEFT) + (Qt::Key_Tab, NKCODE_TAB) + (Qt::Key_Space, NKCODE_SPACE) + (Qt::Key_Return, NKCODE_ENTER) + (Qt::Key_Minus, NKCODE_MINUS) + (Qt::Key_Minus, NKCODE_PLUS) + (Qt::Key_Equal, NKCODE_EQUALS) + (Qt::Key_BracketLeft, NKCODE_LEFT_BRACKET) + (Qt::Key_BracketRight, NKCODE_RIGHT_BRACKET) + (Qt::Key_Backslash, NKCODE_BACKSLASH) + (Qt::Key_Semicolon, NKCODE_SEMICOLON) + (Qt::Key_Apostrophe, NKCODE_APOSTROPHE) + (Qt::Key_Slash, NKCODE_SLASH) + (Qt::Key_At, NKCODE_AT) + (Qt::Key_PageUp, NKCODE_PAGE_UP) + (Qt::Key_PageDown, NKCODE_PAGE_DOWN) + (Qt::Key_Escape, NKCODE_ESCAPE) + (Qt::Key_Delete, NKCODE_FORWARD_DEL) + (Qt::Key_Control, NKCODE_CTRL_LEFT) + (Qt::Key_CapsLock, NKCODE_CAPS_LOCK) + (Qt::Key_Home, NKCODE_MOVE_HOME) + (Qt::Key_End, NKCODE_MOVE_END) + (Qt::Key_Insert, NKCODE_INSERT) + (Qt::Key_Period, NKCODE_NUMPAD_DOT) + (Qt::Key_Enter, NKCODE_NUMPAD_ENTER) + (Qt::Key_1, NKCODE_1) + (Qt::Key_2, NKCODE_2) + (Qt::Key_3, NKCODE_3) + (Qt::Key_4, NKCODE_4) + (Qt::Key_5, NKCODE_5) + (Qt::Key_6, NKCODE_6) + (Qt::Key_7, NKCODE_7) + (Qt::Key_8, NKCODE_8) + (Qt::Key_9, NKCODE_9) + (Qt::Key_0, NKCODE_0) + (Qt::Key_Left, NKCODE_DPAD_LEFT) + (Qt::Key_Up, NKCODE_DPAD_UP) + (Qt::Key_Right, NKCODE_DPAD_RIGHT) + (Qt::Key_Down, NKCODE_DPAD_DOWN); + diff --git a/base/KeyCodeTranslationFromSDL.h b/base/NKCodeFromSDL.h similarity index 100% rename from base/KeyCodeTranslationFromSDL.h rename to base/NKCodeFromSDL.h diff --git a/base/PCMain.cpp b/base/PCMain.cpp index b4a7b6795a..00ac7fcaf9 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -34,7 +34,7 @@ #include "file/zip_read.h" #include "input/input_state.h" #include "input/keycodes.h" -#include "base/KeyCodeTranslationFromSDL.h" +#include "base/NKCodeFromSDL.h" #include "base/NativeApp.h" #include "net/resolve.h" #include "util/const_map.h" diff --git a/base/QtMain.h b/base/QtMain.h index e49be160cd..894de3caf6 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -22,6 +22,7 @@ QTM_USE_NAMESPACE #include "base/NativeApp.h" #include "net/resolve.h" #include "display.h" +#include "base/NKCodeFromQt.h" // Input const int buttonMappings[18] = { @@ -56,7 +57,6 @@ public: { setAttribute(Qt::WA_AcceptTouchEvents); setAttribute(Qt::WA_LockLandscapeOrientation); - pad_buttons = 0; #ifdef USING_GLES2 acc = new QAccelerometer(this); acc->start(); @@ -142,18 +142,10 @@ protected: NativeTouch(input); break; case QEvent::KeyPress: - for (int b = 0; b < 18; b++) { - if (((QKeyEvent*)e)->key() == buttonMappings[b]) - pad_buttons |= (1<key(), KEY_DOWN)); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(((QKeyEvent*)e)->key())->second, KEY_DOWN)); break; case QEvent::KeyRelease: - for (int b = 0; b < 18; b++) { - if (((QKeyEvent*)e)->key() == buttonMappings[b]) - pad_buttons &= ~(1<key(), KEY_UP)); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(((QKeyEvent*)e)->key())->second, KEY_UP)); break; default: return QWidget::event(e); @@ -172,7 +164,6 @@ protected: void paintGL() { - input_state.pad_buttons = pad_buttons; SimulateGamepad(&input_state); updateAccelerometer(); UpdateInputState(&input_state); @@ -197,7 +188,6 @@ protected: } private: - int pad_buttons; InputState input_state; #ifdef USING_GLES2 QAccelerometer* acc; From 4b7376692c9afc025aa3fbe361a4a6bf9df8c5f9 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 6 Aug 2013 15:58:04 +0800 Subject: [PATCH 0566/1445] Add restore() for logicop --- gfx_es2/gl_state.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 026d24989e..3cbe18d2d7 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -39,6 +39,9 @@ void OpenGLState::Restore() { blendFunc.restore(); count++; blendColor.restore(); count++; + colorLogicOp.restore(); count++; + logicOp.restore(); count++; + scissorTest.restore(); count++; scissorRect.restore(); count++; From 6692390d6486d5c4e12b951eea2ce2deb7acc128 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 6 Aug 2013 15:59:48 +0800 Subject: [PATCH 0567/1445] Add Boolstate and STATE1 for logicop --- gfx_es2/gl_state.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 889bc2f9fe..edda664824 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -202,6 +202,9 @@ public: STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; STATEFLOAT4(glBlendColor, 1.0f) blendColor; + BoolState colorLogicOp; + STATE1(glLogicOp, GLenum, GL_COPY) logicOp; + BoolState scissorTest; BoolState cullFace; From f00bfc546401e93803f1b41ba64804247b8ac6c7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 6 Aug 2013 11:08:20 +0200 Subject: [PATCH 0568/1445] Get device manufacturer + type --- android/app-android.cpp | 4 +++- .../src/com/henrikrydgard/libnative/NativeActivity.java | 7 +++++-- android/src/com/henrikrydgard/libnative/NativeApp.java | 3 ++- ui/screen.cpp | 2 -- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index b6cf02e05b..446ed77dcd 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -129,7 +129,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioConfig } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init - (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring japkpath, + (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring jdevicetype, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; @@ -152,6 +152,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init ILOG("NativeApp::Init: APK path: %s", apkPath.c_str()); VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); + std::string deviceType = GetJavaString(env, jdevicetype); + std::string externalDir = GetJavaString(env, jexternalDir); std::string user_data_path = GetJavaString(env, jdataDir) + "/"; library_path = GetJavaString(env, jlibraryDir) + "/"; diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index a363e6b1ba..2f5a611e64 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -192,10 +192,13 @@ public class NativeActivity extends Activity { getWindowManager().getDefaultDisplay().getMetrics(metrics); int dpi = metrics.densityDpi; + String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; + // INIT! NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(scrWidth, scrHeight, dpi, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); - Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat); + NativeApp.init(scrWidth, scrHeight, dpi, deviceType, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); + Log.i(TAG, "Device: " + deviceType); + Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat + " dpi: " + dpi); // Initialize Graphics diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 9c4f1da198..62e9e3af5b 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -1,7 +1,7 @@ package com.henrikrydgard.libnative; public class NativeApp { - public static native void init(int xxres, int yyres, int dpi, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); + public static native void init(int xxres, int yyres, int dpi, String deviceType, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); public static native void resized(int xxres, int yyres); @@ -39,3 +39,4 @@ public class NativeApp { public static native void sendMessage(String msg, String arg); } + \ No newline at end of file diff --git a/ui/screen.cpp b/ui/screen.cpp index f763eba600..22b6ed9cdc 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -29,7 +29,6 @@ void ScreenManager::switchScreen(Screen *screen) { void ScreenManager::update(InputState &input) { if (nextScreen_) { - ILOG("Screen switch! Top of the stack switches."); switchToNext(); } @@ -47,7 +46,6 @@ void ScreenManager::switchToNext() { Layer newLayer = {nextScreen_, 0}; stack_.push_back(newLayer); if (temp.screen) { - ELOG("Deleting screen"); delete temp.screen; } nextScreen_ = 0; From d83c2ab94182e41ab1590057b287b72432528550 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 6 Aug 2013 11:22:57 +0200 Subject: [PATCH 0569/1445] Android buildfix --- gfx_es2/gl_state.cpp | 4 +++- gfx_es2/gl_state.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 3cbe18d2d7..0391639d0a 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -39,9 +39,11 @@ void OpenGLState::Restore() { blendFunc.restore(); count++; blendColor.restore(); count++; +#if !defined(USING_GLES2) colorLogicOp.restore(); count++; logicOp.restore(); count++; - +#endif + scissorTest.restore(); count++; scissorRect.restore(); count++; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index edda664824..33f20ebac7 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -202,9 +202,11 @@ public: STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; STATEFLOAT4(glBlendColor, 1.0f) blendColor; +#if !defined(USING_GLES2) BoolState colorLogicOp; STATE1(glLogicOp, GLenum, GL_COPY) logicOp; - +#endif + BoolState scissorTest; BoolState cullFace; From 2a4672eb59107800ac3eba826fe3d330b1a4d5ed Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 6 Aug 2013 21:41:05 +0800 Subject: [PATCH 0570/1445] glstate code cleanup --- gfx_es2/gl_state.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 33f20ebac7..a6ae8885a3 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -197,23 +197,28 @@ public: void Restore(); // When adding a state here, don't forget to add it to OpenGLState::Restore() too + + // Blend BoolState blend; STATE2(glBlendFunc, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFunc; STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; STATEFLOAT4(glBlendColor, 1.0f) blendColor; + // Logic Ops #if !defined(USING_GLES2) BoolState colorLogicOp; STATE1(glLogicOp, GLenum, GL_COPY) logicOp; #endif - BoolState scissorTest; - - BoolState cullFace; + // Dither BoolState dither; + + // Cull Face + BoolState cullFace; STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode; STATE1(glFrontFace, GLenum, GL_CCW) frontFace; + // Depth Test BoolState depthTest; #if defined(USING_GLES2) STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; @@ -223,12 +228,17 @@ public: STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite; + // Color Mask STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask; + // Viewport STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport; + // Scissor Test + BoolState scissorTest; STATE4(glScissor, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) scissorRect; + // Stencil Test BoolState stencilTest; STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp; STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; From 0bff9046f68ede01b08f6859a2b49ef35a31d27f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 7 Aug 2013 22:32:55 +0200 Subject: [PATCH 0571/1445] round_ieee_754 needs to use double to pass all the tests correctly --- math/math_util.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/math/math_util.h b/math/math_util.h index ad18ee8fb0..c2cc9f38e5 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -102,14 +102,14 @@ inline int is_even(float d) { } // Rounds *.5 to closest even number -inline float round_ieee_754(float d) { - float i = floorf(d); +inline double round_ieee_754(double d) { + float i = floor(d); d -= i; - if(d < 0.5f) + if (d < 0.5f) return i; - if(d > 0.5f) + if (d > 0.5f) return i + 1.0f; - if(is_even(i)) + if (is_even(i)) return i; return i + 1.0f; } From 44c239ef182e2904aada4b1424165a1adf45b2cf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 8 Aug 2013 21:29:49 +0200 Subject: [PATCH 0572/1445] In 64-bit builds, use Win32 native condition variables. In 32-bit builds we cant use it as we want to be XP compatible. --- base/mutex.h | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/base/mutex.h b/base/mutex.h index 8e70009dc0..9ead7724eb 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -174,6 +174,8 @@ private: #endif }; +// Win32 CONDITION_VARIABLE is Vista+ only. We thus limit it to our 64-bit builds where +// we can be almost certain that the user isn't running XP. class condition_variable { public: @@ -182,14 +184,21 @@ public: #endif condition_variable() { #ifdef _WIN32 +#ifdef _WIN64 + InitializeConditionVariable(&cond_); +#else event_ = CreateEvent(0, FALSE, FALSE, 0); +#endif #else pthread_cond_init(&event_, NULL); #endif } ~condition_variable() { #ifdef _WIN32 +#ifdef _WIN64 +#else CloseHandle(event_); +#endif #else pthread_cond_destroy(&event_); #endif @@ -197,22 +206,31 @@ public: void notify_one() { #ifdef _WIN32 +#ifdef _M_X64 + WakeConditionVariable(&cond_); +#else SetEvent(event_); +#endif #else pthread_cond_signal(&event_); #endif } // notify_all is not really possible to implement with win32 events? + // Can be done just fine using WakeAllConditionVariable though. void wait(recursive_mutex &mtx) { - // broken + // broken http://msdn.microsoft.com/en-us/library/windows/desktop/ms686301(v=vs.85).aspx #ifdef _WIN32 +#ifdef _M_X64 + SleepConditionVariableCS(&cond_, &mtx.native_handle(), INFINITE); +#else // This has to be horribly racy. mtx.unlock(); WaitForSingleObject(event_, INFINITE); ResetEvent(event_); // necessary? mtx.lock(); +#endif #else pthread_cond_wait(&event_, &mtx.native_handle()); #endif @@ -220,10 +238,15 @@ public: void wait_for(recursive_mutex &mtx, int milliseconds) { #ifdef _WIN32 +#ifdef _M_X64 + SleepConditionVariableCS(&cond_, &mtx.native_handle(), milliseconds); +#else + //mtx.unlock(); WaitForSingleObject(event_, milliseconds); ResetEvent(event_); // necessary? // mtx.lock(); +#endif #else timespec timeout; #ifdef __APPLE__ @@ -242,7 +265,11 @@ public: private: #ifdef _WIN32 +#ifdef _M_X64 + CONDITION_VARIABLE cond_; +#else HANDLE event_; +#endif #else pthread_cond_t event_; #endif From 0c8692bc44715aa64b0e592c0001413fe0b80b1c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 10 Aug 2013 23:03:12 +0200 Subject: [PATCH 0573/1445] Layout changes for popup views --- ui/ui_screen.cpp | 9 +++++---- ui/ui_screen.h | 2 ++ ui/viewgroup.cpp | 41 ++++++++++++++++++++++++++++------------- ui/viewgroup.h | 5 ++++- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 64bba67f3b..d8f012922a 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -71,7 +71,9 @@ void PopupScreen::CreateViews() { using namespace UI; root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); - LinearLayout *box = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(30, 30, 30, 30)); + + LinearLayout *box = new LinearLayout(ORIENT_VERTICAL, + new AnchorLayoutParams(450, FillVertical() ? dp_yres - 30 : WRAP_CONTENT, dp_xres / 2, dp_yres / 2, NONE, NONE, true)); root_->Add(box); box->SetBG(UI::Drawable(0xFF303030)); @@ -83,7 +85,7 @@ void PopupScreen::CreateViews() { CreatePopupContents(box); // And the two buttons at the bottom. - ViewGroup *buttonRow = new LinearLayout(ORIENT_HORIZONTAL); + ViewGroup *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT)); buttonRow->Add(new Button("OK", new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); buttonRow->Add(new Button("Cancel", new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); box->Add(buttonRow); @@ -100,7 +102,6 @@ UI::EventReturn PopupScreen::OnCancel(UI::EventParams &e) { return UI::EVENT_DONE; } - void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; @@ -120,7 +121,7 @@ void ListPopupScreen::OnCompleted() { void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; - slider_ = parent->Add(new Slider(value_, minValue_, maxValue_)); + slider_ = parent->Add(new Slider(value_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5)))); } void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { diff --git a/ui/ui_screen.h b/ui/ui_screen.h index a2257f7a8b..e106d18402 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -38,6 +38,7 @@ public: virtual bool isTransparent() { return true; } protected: + virtual bool FillVertical() { return false; } virtual void OnCompleted() {} private: @@ -57,6 +58,7 @@ public: UI::Event OnChoice; protected: + virtual bool FillVertical() { return true; } virtual void OnCompleted(); void CreatePopupContents(UI::ViewGroup *parent); UI::StringVectorListAdaptor adaptor_; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 0a09cd1dbb..2261a98f2a 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -323,6 +323,7 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v views_[i]->Measure(dc, MeasureSpec(EXACTLY, unit * linLayoutParams->weight), MeasureSpec(EXACTLY, measuredHeight_)); } } else { + //MeasureBySpec(layoutParams_->height, vert.type == UNSPECIFIED ? sum : weightZeroSum, vert, &measuredHeight_); MeasureBySpec(layoutParams_->height, weightZeroSum, vert, &measuredHeight_); MeasureBySpec(layoutParams_->width, maxOther, horiz, &measuredWidth_); @@ -431,7 +432,7 @@ void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver margins = linLayoutParams->margins; } - // The scroll view itself simply obeys its parent. + // The scroll view itself simply obeys its parent - but also tries to fit the child if possible. MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); @@ -440,6 +441,8 @@ void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver } else { views_[0]->Measure(dc, MeasureSpec(AT_MOST, measuredWidth_ - (margins.left + margins.right)), MeasureSpec(UNSPECIFIED)); } + if (orientation_ == ORIENT_VERTICAL && vert.type != EXACTLY && measuredHeight_ < views_[0]->GetBounds().h) + measuredHeight_ = views_[0]->GetBounds().h; } void ScrollView::Layout() { @@ -489,21 +492,26 @@ void ScrollView::Touch(const TouchInput &input) { scrollStart_ = scrollPos_; } - TouchInput input2 = gesture_.Update(input, bounds_); + TouchInput input2; + if (CanScroll()) { + input2 = gesture_.Update(input, bounds_); + if (gesture_.IsGestureActive(GESTURE_DRAG_VERTICAL)) { + float info[4]; + gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info); - if (gesture_.IsGestureActive(GESTURE_DRAG_VERTICAL)) { - float info[4]; - gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info); - - float pos = scrollStart_ - info[0]; - ClampScrollPos(pos); - scrollPos_ = pos; - scrollTarget_ = pos; - scrollToTarget_ = false; + float pos = scrollStart_ - info[0]; + ClampScrollPos(pos); + scrollPos_ = pos; + scrollTarget_ = pos; + scrollToTarget_ = false; + } + } else { + input2 = input; } - - if (!(input.flags & TOUCH_DOWN) || bounds_.Contains(input.x, input.y)) + + if (!(input.flags & TOUCH_DOWN) || bounds_.Contains(input.x, input.y)) { ViewGroup::Touch(input2); + } } void ScrollView::Draw(UIContext &dc) { @@ -578,6 +586,9 @@ void ScrollView::ClampScrollPos(float &pos) { } } +bool ScrollView::CanScroll() const { + return views_[0]->GetBounds().h > bounds_.h; +} void ScrollView::Update(const InputState &input_state) { ViewGroup::Update(input_state); @@ -633,6 +644,10 @@ void AnchorLayout::Layout() { vBounds.w = views_[i]->GetMeasuredWidth(); vBounds.h = views_[i]->GetMeasuredHeight(); + // Clamp width/height to our own + if (vBounds.w > bounds_.w) vBounds.w = bounds_.w; + if (vBounds.h > bounds_.h) vBounds.h = bounds_.h; + float left = 0, top = 0, right = 0, bottom = 0, center = false; if (params) { left = params->left; diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 772999551d..d617340c0a 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -80,7 +80,9 @@ public: : LayoutParams(w, h, LP_ANCHOR), left(l), top(t), right(r), bottom(b), center(c) { } - + AnchorLayoutParams(Size w, Size h, bool c = false) + : LayoutParams(w, h, LP_ANCHOR), left(0), top(0), right(NONE), bottom(NONE), center(c) { + } AnchorLayoutParams(float l, float t, float r, float b, bool c = false) : LayoutParams(WRAP_CONTENT, WRAP_CONTENT, LP_ANCHOR), left(l), top(t), right(r), bottom(b), center(c) {} @@ -191,6 +193,7 @@ public: void ScrollTo(float newScrollPos); void ScrollRelative(float distance); + bool CanScroll() const; void Update(const InputState &input_state); // Override so that we can scroll to the active one after moving the focus. From 1be25472a51dd0b64b279a7ef5378cbd1730b527 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Aug 2013 14:53:37 -0700 Subject: [PATCH 0574/1445] Use semaphores instead of events on win32. And correctly unlock during the wait, even if there's holes. --- base/mutex.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index 9ead7724eb..c2b3343379 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -11,6 +11,7 @@ #define WIN32_LEAN_AND_MEAN #define NOMINMAX #include +#include // Zap stupid windows defines // Should move these somewhere clever. @@ -187,7 +188,7 @@ public: #ifdef _WIN64 InitializeConditionVariable(&cond_); #else - event_ = CreateEvent(0, FALSE, FALSE, 0); + sema_ = CreateSemaphore(NULL, 0, LONG_MAX, NULL); #endif #else pthread_cond_init(&event_, NULL); @@ -197,7 +198,7 @@ public: #ifdef _WIN32 #ifdef _WIN64 #else - CloseHandle(event_); + CloseHandle(sema_); #endif #else pthread_cond_destroy(&event_); @@ -209,7 +210,7 @@ public: #ifdef _M_X64 WakeConditionVariable(&cond_); #else - SetEvent(event_); + ReleaseSemaphore(sema_, 1, NULL); #endif #else pthread_cond_signal(&event_); @@ -225,10 +226,11 @@ public: #ifdef _M_X64 SleepConditionVariableCS(&cond_, &mtx.native_handle(), INFINITE); #else - // This has to be horribly racy. + // Since a semaphore keeps a count, the window between unlock and lock won't cause us to deadlock. + // However, we could wake early incorrectly (if the semaphore is signalled already.) + // That's better than deadlocking or forgetting to wake. mtx.unlock(); - WaitForSingleObject(event_, INFINITE); - ResetEvent(event_); // necessary? + WaitForSingleObject(sema_, INFINITE); mtx.lock(); #endif #else @@ -241,11 +243,12 @@ public: #ifdef _M_X64 SleepConditionVariableCS(&cond_, &mtx.native_handle(), milliseconds); #else - - //mtx.unlock(); - WaitForSingleObject(event_, milliseconds); - ResetEvent(event_); // necessary? - // mtx.lock(); + // Since a semaphore keeps a count, the window between unlock and lock won't cause us to deadlock. + // However, we could wake early incorrectly (if the semaphore is signalled already.) + // That's better than deadlocking or forgetting to wake. + mtx.unlock(); + WaitForSingleObject(sema_, milliseconds); + mtx.lock(); #endif #else timespec timeout; @@ -268,7 +271,7 @@ private: #ifdef _M_X64 CONDITION_VARIABLE cond_; #else - HANDLE event_; + HANDLE sema_; #endif #else pthread_cond_t event_; From 46f7415bc99f89c508dd07aa02ac4452a7281465 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 12 Aug 2013 23:07:27 +0200 Subject: [PATCH 0575/1445] Various UI key navigatation improvements --- .../libnative/InputDeviceState.java | 2 +- .../libnative/NativeActivity.java | 9 ++- input/keycodes.h | 4 +- ui/ui_screen.cpp | 48 +++++++++++++-- ui/ui_screen.h | 4 ++ ui/view.cpp | 44 +++++++++----- ui/view.h | 7 ++- ui/viewgroup.cpp | 60 +++++++++++++++---- ui/viewgroup.h | 5 ++ 9 files changed, 145 insertions(+), 38 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/InputDeviceState.java b/android/src/com/henrikrydgard/libnative/InputDeviceState.java index 77b83560aa..f1bf23e383 100644 --- a/android/src/com/henrikrydgard/libnative/InputDeviceState.java +++ b/android/src/com/henrikrydgard/libnative/InputDeviceState.java @@ -27,7 +27,7 @@ public class InputDeviceState { } } - mAxes = new int[numAxes]; + mAxes = new int[numAxes]; int i = 0; for (MotionRange range : device.getMotionRanges()) { diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 2f5a611e64..51a976e9cc 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -325,7 +325,9 @@ public class NativeActivity extends Activity { public static boolean inputBoxCancelled; + // Allow for two connected joysticks but just consider them the same for now. InputDeviceState inputPlayerA; + InputDeviceState inputPlayerB; String inputPlayerADesc; // We simply grab the first input device to produce an event and ignore all others that are connected. @@ -336,6 +338,7 @@ public class NativeActivity extends Activity { return null; } if (inputPlayerA == null) { + Log.i(TAG, "Input player A registered"); inputPlayerA = new InputDeviceState(device); inputPlayerADesc = getInputDesc(device); } @@ -344,14 +347,14 @@ public class NativeActivity extends Activity { return inputPlayerA; } - /* if (inputPlayerB == null) { - inputPlyerB = new InputDeviceStats(device); + Log.i(TAG, "Input player B registered"); + inputPlayerB = new InputDeviceState(device); } if (inputPlayerB.getDevice() == device) { return inputPlayerB; - }*/ + } return null; } diff --git a/input/keycodes.h b/input/keycodes.h index 1d7dfa3209..2d0955e69d 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -7,10 +7,10 @@ typedef enum _keycode_t { NKCODE_BUTTON_CIRCLE_PS3 = 97, // PS3 O button is pressed NKCODE_BUTTON_SQUARE = 99, // Square button(Xperia Play) is pressed NKCODE_BUTTON_TRIANGLE = 100, // 'Triangle button(Xperia Play) is pressed - NKCODE_DPAD_LEFT = 21, NKCODE_DPAD_UP = 19, - NKCODE_DPAD_RIGHT = 22, NKCODE_DPAD_DOWN = 20, + NKCODE_DPAD_LEFT = 21, + NKCODE_DPAD_RIGHT = 22, NKCODE_DPAD_CENTER = 23, NKCODE_UNKNOWN = 0, NKCODE_SOFT_LEFT = 1, diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index d8f012922a..c7872831d0 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -1,10 +1,11 @@ - +#include "input/input_state.h" +#include "input/keycodes.h" #include "ui/ui_screen.h" #include "ui/ui_context.h" #include "ui/screen.h" UIScreen::UIScreen() - : Screen(), root_(0), recreateViews_(true) { + : Screen(), root_(0), recreateViews_(true), hatDown_(0) { } void UIScreen::DoRecreateViews() { @@ -44,7 +45,7 @@ void UIScreen::render() { void UIScreen::touch(const TouchInput &touch) { if (root_) { - root_->Touch(touch); + UI::TouchEvent(touch, root_); } else { ELOG("Tried to touch without a view root"); } @@ -52,12 +53,45 @@ void UIScreen::touch(const TouchInput &touch) { void UIScreen::key(const KeyInput &key) { if (root_) { - root_->Key(key); + UI::KeyEvent(key, root_); } else { ELOG("Tried to key without a view root"); } } +void UIScreen::axis(const AxisInput &axis) { + // Simple translation of hat to keys for Shield and other modern pads. + // TODO: Use some variant of keymap? + int flags = 0; + if (axis.axisId == JOYSTICK_AXIS_HAT_X) { + if (axis.value < -0.7f) + flags |= PAD_BUTTON_LEFT; + if (axis.value > 0.7f) + flags |= PAD_BUTTON_RIGHT; + } + if (axis.axisId == JOYSTICK_AXIS_HAT_Y) { + if (axis.value < -0.7f) + flags |= PAD_BUTTON_UP; + if (axis.value > 0.7f) + flags |= PAD_BUTTON_DOWN; + } + + // Yeah yeah, this should be table driven.. + int pressed = flags & ~hatDown_; + int released = ~flags & hatDown_; + if (pressed & PAD_BUTTON_LEFT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT, KEY_DOWN)); + if (pressed & PAD_BUTTON_RIGHT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT, KEY_DOWN)); + if (pressed & PAD_BUTTON_UP) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP, KEY_DOWN)); + if (pressed & PAD_BUTTON_DOWN) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN, KEY_DOWN)); + if (released & PAD_BUTTON_LEFT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT, KEY_UP)); + if (released & PAD_BUTTON_RIGHT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT, KEY_UP)); + if (released & PAD_BUTTON_UP) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP, KEY_UP)); + if (released & PAD_BUTTON_DOWN) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN, KEY_UP)); + hatDown_ = flags; + UI::AxisEvent(axis, root_); +} + + UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { screenManager()->finishDialog(this, DR_OK); return UI::EVENT_DONE; @@ -91,6 +125,12 @@ void PopupScreen::CreateViews() { box->Add(buttonRow); } +void PopupScreen::key(const KeyInput &key) { + if ((key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) + screenManager()->finishDialog(this, DR_CANCEL); + UIScreen::key(key); +} + UI::EventReturn PopupScreen::OnOK(UI::EventParams &e) { OnCompleted(); screenManager()->finishDialog(this, DR_OK); diff --git a/ui/ui_screen.h b/ui/ui_screen.h index e106d18402..de889883c6 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -12,6 +12,7 @@ public: virtual void render(); virtual void touch(const TouchInput &touch); virtual void key(const KeyInput &touch); + virtual void axis(const AxisInput &touch); // Some useful default event handlers UI::EventReturn OnBack(UI::EventParams &e); @@ -27,6 +28,8 @@ protected: private: void DoRecreateViews(); bool recreateViews_; + + int hatDown_; }; class PopupScreen : public UIScreen { @@ -36,6 +39,7 @@ public: virtual void CreatePopupContents(UI::ViewGroup *parent) = 0; virtual void CreateViews(); virtual bool isTransparent() { return true; } + virtual void key(const KeyInput &key); protected: virtual bool FillVertical() { return false; } diff --git a/ui/view.cpp b/ui/view.cpp index 5202203184..268dde3e9b 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -184,25 +184,30 @@ void Clickable::Touch(const TouchInput &input) { } } -void Clickable::Key(const KeyInput &input) { - // TODO: Replace most of Update with this. +bool IsAcceptKeyCode(int keyCode) { + return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_X || keyCode == NKCODE_BUTTON_A; } +bool IsEscapeKeyCode(int keyCode) { + return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK; +} -void Clickable::Update(const InputState &input_state) { - if (!HasFocus()) - return; - - if (!enabled_) { +void Clickable::Key(const KeyInput &key) { + if (!HasFocus()) { down_ = false; return; } - - if (input_state.pad_buttons_down & PAD_BUTTON_A) { - down_ = true; - } else if (input_state.pad_buttons_up & PAD_BUTTON_A) { - if (down_) { - Click(); + // TODO: Replace most of Update with this. + if (key.flags & KEY_DOWN) { + if (IsAcceptKeyCode(key.keyCode)) { + down_ = true; + } + } + if (key.flags & KEY_UP) { + if (IsAcceptKeyCode(key.keyCode)) { + if (down_) { + Click(); + } } } } @@ -224,7 +229,18 @@ void StickyChoice::Touch(const TouchInput &input) { } } -void StickyChoice::Key(const KeyInput &input) { +void StickyChoice::Key(const KeyInput &key) { + if (!HasFocus()) { + return; + } + + // TODO: Replace most of Update with this. + if (key.flags & KEY_DOWN) { + if (IsAcceptKeyCode(key.keyCode)) { + down_ = true; + Click(); + } + } } void StickyChoice::FocusChanged(int focusFlags) { diff --git a/ui/view.h b/ui/view.h index a49371512b..58fb9f3cb4 100644 --- a/ui/view.h +++ b/ui/view.h @@ -23,6 +23,7 @@ struct KeyInput; struct TouchInput; +struct AxisInput; struct InputState; class DrawBuffer; @@ -276,7 +277,8 @@ public: // touch response from the frame rate. virtual void Key(const KeyInput &input) = 0; virtual void Touch(const TouchInput &input) = 0; - virtual void Update(const InputState &input_state) = 0; + virtual void Axis(const AxisInput &input) {} + virtual void Update(const InputState &input_state) {} virtual void FocusChanged(int focusFlags) {} @@ -371,7 +373,6 @@ public: virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); - virtual void Update(const InputState &input_state); virtual void FocusChanged(int focusFlags); @@ -662,5 +663,7 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure void EventTriggered(Event *e, EventParams params); void DispatchEvents(); +bool IsAcceptKeyCode(int keyCode); +bool IsEscapeKeyCode(int keyCode); } // namespace diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 2261a98f2a..929363723d 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1,6 +1,7 @@ #include "base/display.h" #include "base/functional.h" #include "base/logging.h" +#include "base/mutex.h" #include "input/keycodes.h" #include "ui/ui_context.h" #include "ui/view.h" @@ -57,6 +58,13 @@ void ViewGroup::Key(const KeyInput &input) { } } +void ViewGroup::Axis(const AxisInput &input) { + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + // TODO: If there is a transformation active, transform input coordinates accordingly. + if ((*iter)->GetVisibility() == V_VISIBLE) + (*iter)->Axis(input); + } +} void ViewGroup::Draw(UIContext &dc) { if (hasDropShadow_) { @@ -475,7 +483,7 @@ void ScrollView::Layout() { } void ScrollView::Key(const KeyInput &input) { - if (input.flags & KEY_DOWN) { + if (input.flags & KEY_DOWN) { switch (input.keyCode) { case NKCODE_EXT_MOUSEWHEEL_UP: ScrollRelative(-250); @@ -485,6 +493,7 @@ void ScrollView::Key(const KeyInput &input) { break; } } + ViewGroup::Key(input); } void ScrollView::Touch(const TouchInput &input) { @@ -844,31 +853,58 @@ void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { root->Layout(); } +static recursive_mutex focusLock; +static std::vector focusMoves; + +void KeyEvent(const KeyInput &key, ViewGroup *root) { + if (key.flags & KEY_DOWN) { + ILOG("ke: %i %02x", key.deviceId, key.keyCode); + // We ignore the device ID here. Anything with a DPAD is OK. + if (key.keyCode >= NKCODE_DPAD_UP && key.keyCode <= NKCODE_DPAD_RIGHT) { + lock_guard lock(focusLock); + focusMoves.push_back(key.keyCode); + } + } + root->Key(key); +} + +void TouchEvent(const TouchInput &touch, ViewGroup *root) { + EnableFocusMovement(false); + + root->Touch(touch); +} + +void AxisEvent(const AxisInput &axis, ViewGroup *root) { + root->Axis(axis); +} + void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { if (!root) { ELOG("Tried to update a view hierarchy from a zero pointer root"); return; } - if (input_state.pad_buttons_down & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) { + + if (focusMoves.size()) { + lock_guard lock(focusLock); EnableFocusMovement(true); if (!GetFocusedView()) { root->SetFocus(); root->SubviewFocused(GetFocusedView()); } else { - if (input_state.pad_buttons_down & PAD_BUTTON_RIGHT) - MoveFocus(root, FOCUS_RIGHT); - if (input_state.pad_buttons_down & PAD_BUTTON_UP) - MoveFocus(root, FOCUS_UP); - if (input_state.pad_buttons_down & PAD_BUTTON_LEFT) - MoveFocus(root, FOCUS_LEFT); - if (input_state.pad_buttons_down & PAD_BUTTON_DOWN) - MoveFocus(root, FOCUS_DOWN); + for (size_t i = 0; i < focusMoves.size(); i++) { + switch (focusMoves[i]) { + case NKCODE_DPAD_LEFT: MoveFocus(root, FOCUS_LEFT); break; + case NKCODE_DPAD_RIGHT: MoveFocus(root, FOCUS_RIGHT); break; + case NKCODE_DPAD_UP: MoveFocus(root, FOCUS_UP); break; + case NKCODE_DPAD_DOWN: MoveFocus(root, FOCUS_DOWN); break; + } + } } + focusMoves.clear(); } - if (input_state.pointer_down[0]) - EnableFocusMovement(false); root->Update(input_state); DispatchEvents(); } + } // namespace UI diff --git a/ui/viewgroup.h b/ui/viewgroup.h index d617340c0a..78dc2a82ec 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -23,6 +23,7 @@ public: // Pass through external events to children. virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); + virtual void Axis(const AxisInput &input); // By default, a container will layout to its own bounds. virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) = 0; @@ -332,5 +333,9 @@ private: void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root); void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root); +// Hooks arrow keys for navigation +void KeyEvent(const KeyInput &key, ViewGroup *root); +void TouchEvent(const TouchInput &touch, ViewGroup *root); +void AxisEvent(const AxisInput &axis, ViewGroup *root); } // namespace UI From 76d0d5ceb38b6c50225a82501e88f96e503b2ee9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 12 Aug 2013 23:25:35 +0200 Subject: [PATCH 0576/1445] Add axis for relative mouse --- input/keycodes.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/input/keycodes.h b/input/keycodes.h index 2d0955e69d..e9a128937e 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -277,4 +277,8 @@ enum AndroidJoystickAxis { JOYSTICK_OUYA_AXIS_R2 = 18, JOYSTICK_OUYA_AXIS_RS_X = 11, JOYSTICK_OUYA_AXIS_RS_Y = 14, + + // Relative mouse axis for PC. + JOYSTICK_AXIS_MOUSE_REL_X = 26, + JOYSTICK_AXIS_MOUSE_REL_Y = 27, }; From 77fcfd0f2058c1acc91c7a68598df259f6628e2f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 13 Aug 2013 00:06:23 +0200 Subject: [PATCH 0577/1445] More UI tweaks --- ui/ui_screen.cpp | 8 ++++++++ ui/ui_screen.h | 6 ++++++ ui/view.cpp | 3 +++ ui/viewgroup.cpp | 11 ++++++++++- ui/viewgroup.h | 2 ++ 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index c7872831d0..9535221eca 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -59,6 +59,14 @@ void UIScreen::key(const KeyInput &key) { } } +void DialogScreen::key(const KeyInput &key) { + if ((key.flags & KEY_DOWN) && key.keyCode == NKCODE_ESCAPE || key.keyCode == NKCODE_BACK || key.keyCode == NKCODE_BUTTON_B) { + screenManager()->finishDialog(this, DR_CANCEL); + } else { + UIScreen::key(key); + } +} + void UIScreen::axis(const AxisInput &axis) { // Simple translation of hat to keys for Shield and other modern pads. // TODO: Use some variant of keymap? diff --git a/ui/ui_screen.h b/ui/ui_screen.h index de889883c6..430ffca612 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -32,6 +32,12 @@ private: int hatDown_; }; +class DialogScreen : public UIScreen { +public: + virtual void key(const KeyInput &key); +}; + + class PopupScreen : public UIScreen { public: PopupScreen(const std::string &title); diff --git a/ui/view.cpp b/ui/view.cpp index 268dde3e9b..b0e5a32cd2 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -207,7 +207,10 @@ void Clickable::Key(const KeyInput &key) { if (IsAcceptKeyCode(key.keyCode)) { if (down_) { Click(); + down_ = false; } + } else if (IsEscapeKeyCode(key.keyCode)) { + down_ = false; } } } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 929363723d..941abc69f3 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -781,6 +781,16 @@ void ChoiceStrip::SetSelection(int sel) { static_cast(views_[selected_])->Press(); } +void ChoiceStrip::Key(const KeyInput &input) { + if (input.flags & KEY_DOWN) { + if (input.keyCode == NKCODE_BUTTON_L1 && selected_ > 0) { + SetSelection(selected_ - 1); + } else if (input.keyCode == NKCODE_BUTTON_R1 && selected_ < views_.size() - 1) { + SetSelection(selected_ + 1); + } + } +} + ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a) { linLayout_ = new LinearLayout(ORIENT_VERTICAL); @@ -858,7 +868,6 @@ static std::vector focusMoves; void KeyEvent(const KeyInput &key, ViewGroup *root) { if (key.flags & KEY_DOWN) { - ILOG("ke: %i %02x", key.deviceId, key.keyCode); // We ignore the device ID here. Anything with a DPAD is OK. if (key.keyCode >= NKCODE_DPAD_UP && key.keyCode <= NKCODE_DPAD_RIGHT) { lock_guard lock(focusLock); diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 78dc2a82ec..f4feab42fb 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -225,6 +225,8 @@ public: void AddChoice(const std::string &title); int GetSelection() const { return selected_; } void SetSelection(int sel); + virtual void Key(const KeyInput &input); + Event OnChoice; private: From 1be5ce83d732c4ebf3179ada40ef895586cb875e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 14 Aug 2013 23:04:35 +0200 Subject: [PATCH 0578/1445] error handling changes --- gfx_es2/draw_buffer.cpp | 4 ++++ ui/ui_context.cpp | 1 - ui/ui_screen.cpp | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 48cda85819..d79f441f0d 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -66,6 +66,10 @@ void DrawBuffer::End() { } void DrawBuffer::Flush(bool set_blend_state) { + if (!program_) { + ELOG("No program set!"); + return; + } glsl_bind(program_); if (count_ == 0) return; diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 34d5edb732..b8bd28466b 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -84,7 +84,6 @@ Bounds UIContext::GetScissorBounds() { return Bounds(0, 0, dp_xres, dp_yres); } - void UIContext::ActivateTopScissor() { if (scissorStack_.size()) { const Bounds &bounds = scissorStack_.back(); diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 9535221eca..9e315c0e8e 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -39,7 +39,8 @@ void UIScreen::render() { screenManager()->getUIContext()->End(); screenManager()->getUIContext()->Flush(); } else { - ELOG("Tried to render without a view root"); + // This isn't really an error if you customize the view a bit. + // ELOG("Tried to render without a view root"); } } From 357966447d0eb9560dc5477cd8654c246eae2a8f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 14 Aug 2013 23:29:27 +0200 Subject: [PATCH 0579/1445] More UI --- ui/ui_screen.cpp | 18 ++++++++++++++---- ui/ui_screen.h | 4 ++++ ui/view.cpp | 5 +++++ ui/view.h | 14 ++++++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 9e315c0e8e..ec6bc3f468 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -116,13 +116,13 @@ void PopupScreen::CreateViews() { root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); LinearLayout *box = new LinearLayout(ORIENT_VERTICAL, - new AnchorLayoutParams(450, FillVertical() ? dp_yres - 30 : WRAP_CONTENT, dp_xres / 2, dp_yres / 2, NONE, NONE, true)); + new AnchorLayoutParams(550, FillVertical() ? dp_yres - 30 : WRAP_CONTENT, dp_xres / 2, dp_yres / 2, NONE, NONE, true)); root_->Add(box); box->SetBG(UI::Drawable(0xFF303030)); box->SetHasDropShadow(true); - View *title = new ItemHeader(title_); + View *title = new PopupHeader(title_); box->Add(title); CreatePopupContents(box); @@ -170,10 +170,20 @@ void ListPopupScreen::OnCompleted() { void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; - slider_ = parent->Add(new Slider(value_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5)))); + sliderValue_ = *value_; + slider_ = parent->Add(new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5)))); } void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; - slider_ = parent->Add(new SliderFloat(value_, minValue_, maxValue_)); + sliderValue_ = *value_; + slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_)); +} + +void SliderPopupScreen::OnCompleted() { + *value_ = sliderValue_; +} + +void SliderFloatPopupScreen::OnCompleted() { + *value_ = sliderValue_; } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 430ffca612..39bad3d894 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -86,8 +86,10 @@ public: void CreatePopupContents(UI::ViewGroup *parent); private: + virtual void OnCompleted(); UI::Slider *slider_; int *value_; + int sliderValue_; int minValue_; int maxValue_; }; @@ -98,7 +100,9 @@ public: void CreatePopupContents(UI::ViewGroup *parent); private: + virtual void OnCompleted(); UI::SliderFloat *slider_; + float sliderValue_; float *value_; float minValue_; float maxValue_; diff --git a/ui/view.cpp b/ui/view.cpp index b0e5a32cd2..fa2154e297 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -320,6 +320,11 @@ void ItemHeader::Draw(UIContext &dc) { dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), 0xFFFFFFFF); } +void PopupHeader::Draw(UIContext &dc) { + dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 12, bounds_.centerY(), dc.theme->popupTitle.fgColor, ALIGN_LEFT | ALIGN_VCENTER); + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), 0xFFFFFFFF); +} + void CheckBox::Draw(UIContext &dc) { ClickableItem::Draw(dc); int paddingX = 8; diff --git a/ui/view.h b/ui/view.h index 58fb9f3cb4..5a40bacf9a 100644 --- a/ui/view.h +++ b/ui/view.h @@ -91,6 +91,8 @@ struct Theme { Style itemStyle; Style itemDownStyle; Style itemFocusedStyle; + + Style popupTitle; }; // The four cardinal directions should be enough, plus Prev/Next in "element order". @@ -530,6 +532,18 @@ private: std::string text_; }; +class PopupHeader : public Item { +public: + PopupHeader(const std::string &text, LayoutParams *layoutParams = 0) + : Item(layoutParams), text_(text) { + layoutParams_->width = FILL_PARENT; + layoutParams_->height = 64; + } + virtual void Draw(UIContext &dc); +private: + std::string text_; +}; + class CheckBox : public ClickableItem { public: CheckBox(bool *toggle, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) From e8d07b02c2072b159c83e074b68bcfdd8a872c2f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 15 Aug 2013 22:13:57 +0200 Subject: [PATCH 0580/1445] Fix a potential crash bug with axis input. Remove ok/cancel buttons from popup lists. --- ui/ui_screen.cpp | 22 ++++++++++++---------- ui/ui_screen.h | 3 ++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index ec6bc3f468..766bf4175b 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -97,7 +97,9 @@ void UIScreen::axis(const AxisInput &axis) { if (released & PAD_BUTTON_UP) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP, KEY_UP)); if (released & PAD_BUTTON_DOWN) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN, KEY_UP)); hatDown_ = flags; - UI::AxisEvent(axis, root_); + if (root_) { + UI::AxisEvent(axis, root_); + } } @@ -127,11 +129,13 @@ void PopupScreen::CreateViews() { CreatePopupContents(box); - // And the two buttons at the bottom. - ViewGroup *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT)); - buttonRow->Add(new Button("OK", new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); - buttonRow->Add(new Button("Cancel", new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); - box->Add(buttonRow); + if (ShowButtons()) { + // And the two buttons at the bottom. + ViewGroup *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT)); + buttonRow->Add(new Button("OK", new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); + buttonRow->Add(new Button("Cancel", new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); + box->Add(buttonRow); + } } void PopupScreen::key(const KeyInput &key) { @@ -160,14 +164,12 @@ void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) { adaptor_.SetSelected(e.a); + callback_(adaptor_.GetSelected()); + screenManager()->finishDialog(this, DR_OK); OnChoice.Dispatch(e); return UI::EVENT_DONE; } -void ListPopupScreen::OnCompleted() { - callback_(adaptor_.GetSelected()); -} - void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; sliderValue_ = *value_; diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 39bad3d894..eeea4126ad 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -49,6 +49,7 @@ public: protected: virtual bool FillVertical() { return false; } + virtual bool ShowButtons() { return true; } virtual void OnCompleted() {} private: @@ -69,7 +70,7 @@ public: protected: virtual bool FillVertical() { return true; } - virtual void OnCompleted(); + virtual bool ShowButtons() { return false; } void CreatePopupContents(UI::ViewGroup *parent); UI::StringVectorListAdaptor adaptor_; UI::ListView *listView_; From 612dd6abed7f63dfc3e21aaafd86a9811eec4886 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 15 Aug 2013 22:34:02 +0200 Subject: [PATCH 0581/1445] Remove some more unnecessary logging --- ui/ui_screen.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 766bf4175b..5b669b993b 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -22,8 +22,6 @@ void UIScreen::update(InputState &input) { if (root_) { UpdateViewHierarchy(input, root_); - } else { - ELOG("Tried to update without a view root"); } } @@ -38,25 +36,18 @@ void UIScreen::render() { root_->Draw(*screenManager()->getUIContext()); screenManager()->getUIContext()->End(); screenManager()->getUIContext()->Flush(); - } else { - // This isn't really an error if you customize the view a bit. - // ELOG("Tried to render without a view root"); } } void UIScreen::touch(const TouchInput &touch) { if (root_) { UI::TouchEvent(touch, root_); - } else { - ELOG("Tried to touch without a view root"); } } void UIScreen::key(const KeyInput &key) { if (root_) { UI::KeyEvent(key, root_); - } else { - ELOG("Tried to key without a view root"); } } From 1353a9d73d1cdc0935b87f3e1d37edf516cf936a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 15 Aug 2013 22:43:42 +0200 Subject: [PATCH 0582/1445] Bugfixes --- ui/ui_screen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 5b669b993b..6dc9a7c9a1 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -155,8 +155,10 @@ void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) { adaptor_.SetSelected(e.a); - callback_(adaptor_.GetSelected()); + if (callback_) + callback_(adaptor_.GetSelected()); screenManager()->finishDialog(this, DR_OK); + OnCompleted(); OnChoice.Dispatch(e); return UI::EVENT_DONE; } From c3ea52bad545439454ca60612efd56071e0b94d9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 16 Aug 2013 12:51:57 +0200 Subject: [PATCH 0583/1445] More UI stuff --- ui/ui_screen.cpp | 35 +++++++++++++++++++++++++---------- ui/ui_screen.h | 30 ++++++++++++++++++++++++------ ui/view.h | 8 +++++--- ui/viewgroup.cpp | 10 ++++++++++ ui/viewgroup.h | 1 + 5 files changed, 65 insertions(+), 19 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 6dc9a7c9a1..39df32a739 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -100,8 +100,8 @@ UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { } -PopupScreen::PopupScreen(const std::string &title) - : title_(title) {} +PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2) + : title_(title), button1_(button1), button2_(button2) {} void PopupScreen::CreateViews() { using namespace UI; @@ -123,8 +123,16 @@ void PopupScreen::CreateViews() { if (ShowButtons()) { // And the two buttons at the bottom. ViewGroup *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT)); - buttonRow->Add(new Button("OK", new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); - buttonRow->Add(new Button("Cancel", new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); + + // Adjust button order to the platform default. +#if defined(_WIN32) + buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); + buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); +#else + buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); + buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); +#endif + box->Add(buttonRow); } } @@ -135,13 +143,18 @@ void PopupScreen::key(const KeyInput &key) { UIScreen::key(key); } +void MessagePopupScreen::CreatePopupContents(UI::ViewGroup *parent) { + parent->Add(new UI::TextView(message_)); +} + UI::EventReturn PopupScreen::OnOK(UI::EventParams &e) { - OnCompleted(); + OnCompleted(DR_OK); screenManager()->finishDialog(this, DR_OK); return UI::EVENT_DONE; } UI::EventReturn PopupScreen::OnCancel(UI::EventParams &e) { + OnCompleted(DR_CANCEL); screenManager()->finishDialog(this, DR_CANCEL); return UI::EVENT_DONE; } @@ -158,7 +171,7 @@ UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) { if (callback_) callback_(adaptor_.GetSelected()); screenManager()->finishDialog(this, DR_OK); - OnCompleted(); + OnCompleted(DR_OK); OnChoice.Dispatch(e); return UI::EVENT_DONE; } @@ -175,10 +188,12 @@ void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_)); } -void SliderPopupScreen::OnCompleted() { - *value_ = sliderValue_; +void SliderPopupScreen::OnCompleted(DialogResult result) { + if (result == DR_OK) + *value_ = sliderValue_; } -void SliderFloatPopupScreen::OnCompleted() { - *value_ = sliderValue_; +void SliderFloatPopupScreen::OnCompleted(DialogResult result) { + if (result == DR_OK) + *value_ = sliderValue_; } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index eeea4126ad..9f323524a3 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -40,7 +40,7 @@ public: class PopupScreen : public UIScreen { public: - PopupScreen(const std::string &title); + PopupScreen(std::string title, std::string button1 = "", std::string button2 = ""); virtual void CreatePopupContents(UI::ViewGroup *parent) = 0; virtual void CreateViews(); @@ -50,19 +50,21 @@ public: protected: virtual bool FillVertical() { return false; } virtual bool ShowButtons() { return true; } - virtual void OnCompleted() {} + virtual void OnCompleted(DialogResult result) {} private: UI::EventReturn OnOK(UI::EventParams &e); UI::EventReturn OnCancel(UI::EventParams &e); std::string title_; + std::string button1_; + std::string button2_; }; class ListPopupScreen : public PopupScreen { public: - ListPopupScreen(const std::string &title) : PopupScreen(title) {} - ListPopupScreen(const std::string &title, const std::vector &items, int selected, std::function callback) + ListPopupScreen(std::string title) : PopupScreen(title) {} + ListPopupScreen(std::string title, const std::vector &items, int selected, std::function callback) : PopupScreen(title), adaptor_(items, selected), callback_(callback) { } @@ -81,13 +83,29 @@ private: std::function callback_; }; +class MessagePopupScreen : public PopupScreen { +public: + MessagePopupScreen(std::string title, std::string message, std::string button1, std::string button2, std::function callback) : PopupScreen(title) {} + UI::Event OnChoice; + +protected: + virtual bool FillVertical() { return false; } + virtual bool ShowButtons() { return true; } + void CreatePopupContents(UI::ViewGroup *parent); + virtual void OnCompleted(DialogResult result); + +private: + std::string message_; + std::function callback_; +}; + class SliderPopupScreen : public PopupScreen { public: SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title) : PopupScreen(title), value_(value), minValue_(minValue), maxValue_(maxValue) {} void CreatePopupContents(UI::ViewGroup *parent); private: - virtual void OnCompleted(); + virtual void OnCompleted(DialogResult result); UI::Slider *slider_; int *value_; int sliderValue_; @@ -101,7 +119,7 @@ public: void CreatePopupContents(UI::ViewGroup *parent); private: - virtual void OnCompleted(); + virtual void OnCompleted(DialogResult result); UI::SliderFloat *slider_; float sliderValue_; float *value_; diff --git a/ui/view.h b/ui/view.h index 5a40bacf9a..9bb36f2559 100644 --- a/ui/view.h +++ b/ui/view.h @@ -579,8 +579,11 @@ public: class TextView : public InertView { public: - TextView(int font, const std::string &text, int textAlign, float textScale, LayoutParams *layoutParams = 0) - : InertView(layoutParams), font_(font), text_(text), textScaleX_(textScale), textScaleY_(textScale), textAlign_(textAlign) {} + TextView(const std::string &text, LayoutParams *layoutParams = 0) + : InertView(layoutParams), text_(text), textScaleX_(1.0f), textScaleY_(1.0f), textAlign_(0) {} + + TextView(const std::string &text, int textAlign, float textScale, LayoutParams *layoutParams = 0) + : InertView(layoutParams), text_(text), textScaleX_(textScale), textScaleY_(textScale), textAlign_(textAlign) {} virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); @@ -589,7 +592,6 @@ public: void SetTextScale(float scale) { textScaleX_ = scale; textScaleY_ = scale; } private: - int font_; std::string text_; float textScaleX_; float textScaleY_; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 941abc69f3..17904971e6 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -34,6 +34,16 @@ ViewGroup::~ViewGroup() { Clear(); } +void ViewGroup::RemoveSubview(View *view) { + for (size_t i = 0; i < views_.size(); i++) { + if (views_[i] == view) { + views_.erase(views_.begin() + i); + delete view; + return; + } + } +} + void ViewGroup::Clear() { for (size_t i = 0; i < views_.size(); i++) { delete views_[i]; diff --git a/ui/viewgroup.h b/ui/viewgroup.h index f4feab42fb..ade56511d8 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -42,6 +42,7 @@ public: virtual bool SetFocus(); virtual bool SubviewFocused(View *view); + virtual void RemoveSubview(View *view); // Assumes that layout has taken place. NeighborResult FindNeighbor(View *view, FocusDirection direction, NeighborResult best); From 569cdb9c081e7af82125510dbd38ba2cedfff6f3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 16 Aug 2013 14:02:28 +0200 Subject: [PATCH 0584/1445] Hold a lock while modifying viewgroups to prevent crashing from asynchronous input --- ui/viewgroup.cpp | 6 ++++++ ui/viewgroup.h | 1 + 2 files changed, 7 insertions(+) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 17904971e6..c4c83cb4e9 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -35,6 +35,7 @@ ViewGroup::~ViewGroup() { } void ViewGroup::RemoveSubview(View *view) { + lock_guard guard(modifyLock_); for (size_t i = 0; i < views_.size(); i++) { if (views_[i] == view) { views_.erase(views_.begin() + i); @@ -45,6 +46,7 @@ void ViewGroup::RemoveSubview(View *view) { } void ViewGroup::Clear() { + lock_guard guard(modifyLock_); for (size_t i = 0; i < views_.size(); i++) { delete views_[i]; views_[i] = 0; @@ -53,6 +55,7 @@ void ViewGroup::Clear() { } void ViewGroup::Touch(const TouchInput &input) { + lock_guard guard(modifyLock_); for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. if ((*iter)->GetVisibility() == V_VISIBLE) @@ -61,6 +64,7 @@ void ViewGroup::Touch(const TouchInput &input) { } void ViewGroup::Key(const KeyInput &input) { + lock_guard guard(modifyLock_); for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. if ((*iter)->GetVisibility() == V_VISIBLE) @@ -69,6 +73,7 @@ void ViewGroup::Key(const KeyInput &input) { } void ViewGroup::Axis(const AxisInput &input) { + lock_guard guard(modifyLock_); for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. if ((*iter)->GetVisibility() == V_VISIBLE) @@ -103,6 +108,7 @@ void ViewGroup::Update(const InputState &input_state) { } bool ViewGroup::SetFocus() { + lock_guard guard(modifyLock_); if (!CanBeFocused() && !views_.empty()) { for (size_t i = 0; i < views_.size(); i++) { if (views_[i]->SetFocus()) diff --git a/ui/viewgroup.h b/ui/viewgroup.h index ade56511d8..181b91e1a0 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -58,6 +58,7 @@ public: void SetHasDropShadow(bool has) { hasDropShadow_ = has; } protected: + recursive_mutex modifyLock_; // Hold this when changing the subviews. std::vector views_; Drawable bg_; bool hasDropShadow_; From 4a1c3c4f83ee1f3ba4b0bc63d3d82b7a698df519 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 16 Aug 2013 16:47:25 +0200 Subject: [PATCH 0585/1445] More UI stuff, add glMapBuffer --- android/app-android.cpp | 16 ++++++++++++++++ base/colorutil.h | 1 + gfx_es2/gl_state.cpp | 7 ++++++- gfx_es2/gl_state.h | 2 ++ input/keycodes.h | 5 +++++ ui/ui_screen.cpp | 12 ++++++++---- ui/ui_screen.h | 7 ++++--- ui/view.cpp | 25 ++++++++++++------------- ui/view.h | 12 +++++++++--- ui/viewgroup.cpp | 20 +++++++++++++++----- 10 files changed, 78 insertions(+), 29 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 446ed77dcd..faa4d4494e 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -456,6 +456,22 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer input_state.acc.x = x; input_state.acc.y = y; input_state.acc.z = z; + + AxisInput axis; + axis.deviceId = DEVICE_ID_ACCELEROMETER; + axis.flags = 0; + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_X; + axis.value = x; + NativeAxis(axis); + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Y; + axis.value = y; + NativeAxis(axis); + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Z; + axis.value = z; + NativeAxis(axis); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) { diff --git a/base/colorutil.h b/base/colorutil.h index 61d6f8b127..cc5d27bcaf 100644 --- a/base/colorutil.h +++ b/base/colorutil.h @@ -5,6 +5,7 @@ uint32_t whiteAlpha(float alpha); uint32_t blackAlpha(float alpha); uint32_t colorAlpha(uint32_t color, float alpha); +uint32_t colorBlend(uint32_t color, uint32_t color2, float alpha); uint32_t alphaMul(uint32_t color, float alphaMul); uint32_t rgba(float r, float g, float b, float alpha); uint32_t rgba_clamp(float r, float g, float b, float alpha); diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 0391639d0a..e0a61f9ddb 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -9,6 +9,7 @@ PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; +PFNGLMAPBUFFERPROC glMapBuffer; #endif #if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; @@ -95,7 +96,6 @@ void CheckGLExtensions() { gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; - #if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) gl_extensions.OES_vertex_array_object = false; gl_extensions.EXT_discard_framebuffer = false; @@ -113,10 +113,15 @@ void CheckGLExtensions() { if (gl_extensions.EXT_discard_framebuffer) { glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); } + #endif #endif #ifdef ANDROID + if (gl_extensions.OES_mapbuffer) { + glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" ); + } + gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0; // Load extensions that are not auto-loaded by Android. if (gl_extensions.QCOM_alpha_test) { diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index a6ae8885a3..1d692435bc 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -23,6 +23,8 @@ typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); extern PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; +typedef GLvoid* (GL_APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +extern PFNGLMAPBUFFERPROC glMapBuffer; #endif #if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) diff --git a/input/keycodes.h b/input/keycodes.h index e9a128937e..97ce3453b9 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -281,4 +281,9 @@ enum AndroidJoystickAxis { // Relative mouse axis for PC. JOYSTICK_AXIS_MOUSE_REL_X = 26, JOYSTICK_AXIS_MOUSE_REL_Y = 27, + + // Mobile device accelerometer/gyro + JOYSTICK_AXIS_ACCELEROMETER_X, + JOYSTICK_AXIS_ACCELEROMETER_Y, + JOYSTICK_AXIS_ACCELEROMETER_Z, }; diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 39df32a739..49ebb23992 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -122,14 +122,18 @@ void PopupScreen::CreateViews() { if (ShowButtons()) { // And the two buttons at the bottom. - ViewGroup *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT)); + LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT)); + buttonRow->SetSpacing(0); + Margins buttonMargins(5, 5); // Adjust button order to the platform default. #if defined(_WIN32) - buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); - buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); + buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle(this, &PopupScreen::OnOK); + if (!button2_.empty()) + buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle(this, &PopupScreen::OnCancel); #else - buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); + if (!button2_.empty()) + buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); #endif diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 9f323524a3..f1999f6c70 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -92,16 +92,17 @@ protected: virtual bool FillVertical() { return false; } virtual bool ShowButtons() { return true; } void CreatePopupContents(UI::ViewGroup *parent); - virtual void OnCompleted(DialogResult result); private: std::string message_; std::function callback_; }; +// TODO: Need a way to translate OK and Cancel + class SliderPopupScreen : public PopupScreen { public: - SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title) : PopupScreen(title), value_(value), minValue_(minValue), maxValue_(maxValue) {} + SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title) : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue) {} void CreatePopupContents(UI::ViewGroup *parent); private: @@ -115,7 +116,7 @@ private: class SliderFloatPopupScreen : public PopupScreen { public: - SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title) : PopupScreen(title), value_(value), minValue_(minValue), maxValue_(maxValue) {} + SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title) : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue) {} void CreatePopupContents(UI::ViewGroup *parent); private: diff --git a/ui/view.cpp b/ui/view.cpp index fa2154e297..caae38cdbc 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -250,8 +250,6 @@ void StickyChoice::FocusChanged(int focusFlags) { // Override Clickable's FocusChanged to do nothing. } - - Item::Item(LayoutParams *layoutParams) : InertView(layoutParams) { layoutParams_->width = FILL_PARENT; layoutParams_->height = ITEM_HEIGHT; @@ -275,24 +273,25 @@ ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParam void ClickableItem::Draw(UIContext &dc) { Style style = dc.theme->itemStyle; - if (down_) { - style = dc.theme->itemDownStyle; - } else if (HasFocus()) { + if (HasFocus()) { style = dc.theme->itemFocusedStyle; } + if (down_) { + style = dc.theme->itemDownStyle; + } dc.FillRect(style.background, bounds_); } void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const { dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); - w += 16; + w += 24; h += 16; } void Choice::Draw(UIContext &dc) { ClickableItem::Draw(dc); - int paddingX = 8; + int paddingX = 12; dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); if (selected_) { @@ -303,7 +302,7 @@ void Choice::Draw(UIContext &dc) { void InfoItem::Draw(UIContext &dc) { Item::Draw(dc); - int paddingX = 8; + int paddingX = 12; dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); // dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor); @@ -312,28 +311,28 @@ void InfoItem::Draw(UIContext &dc) { void ItemHeader::Draw(UIContext &dc) { float scale = 1.0f; if (dc.theme->uiFontSmaller == dc.theme->uiFont) { - scale = 0.6f; + scale = 0.7f; } dc.Draw()->SetFontScale(scale, scale); - dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.y, 0xFFa0a0a0, ALIGN_LEFT); + dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.y, 0xFFFFFFFF, ALIGN_LEFT); dc.Draw()->SetFontScale(1.0f, 1.0f); dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), 0xFFFFFFFF); } void PopupHeader::Draw(UIContext &dc) { dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 12, bounds_.centerY(), dc.theme->popupTitle.fgColor, ALIGN_LEFT | ALIGN_VCENTER); - dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), 0xFFFFFFFF); + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->popupTitle.fgColor); } void CheckBox::Draw(UIContext &dc) { ClickableItem::Draw(dc); - int paddingX = 8; + int paddingX = 12; int paddingY = 8; int image = *toggle_ ? dc.theme->checkOn : dc.theme->checkOff; dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); - dc.Draw()->DrawImage(image, bounds_.x2() - 4, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); + dc.Draw()->DrawImage(image, bounds_.x2() - paddingX, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); } void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const { diff --git a/ui/view.h b/ui/view.h index 9bb36f2559..d3eeea8ee2 100644 --- a/ui/view.h +++ b/ui/view.h @@ -82,6 +82,7 @@ struct Theme { int checkOff; int sliderKnob; int whiteImage; + int dropShadow4Grid; Style buttonStyle; Style buttonFocusedStyle; @@ -91,6 +92,9 @@ struct Theme { Style itemStyle; Style itemDownStyle; Style itemFocusedStyle; + Style itemDisabledStyle; + + Style headerStyle; Style popupTitle; }; @@ -480,7 +484,9 @@ public: // Use to trigger something or open a submenu screen. class Choice : public ClickableItem { public: - Choice(const std::string &text, const std::string &smallText = "", bool selected = false, LayoutParams *layoutParams = 0) + Choice(const std::string &text, LayoutParams *layoutParams = 0) + : ClickableItem(layoutParams), text_(text), smallText_(), selected_(false) {} + Choice(const std::string &text, const std::string &smallText, bool selected = false, LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), text_(text), smallText_(smallText), selected_(selected) {} virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; @@ -499,8 +505,8 @@ public: StickyChoice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) : Choice(text, smallText, false, layoutParams) {} - virtual void Key(const KeyInput &input); - virtual void Touch(const TouchInput &input); + virtual void Key(const KeyInput &key); + virtual void Touch(const TouchInput &touch); virtual void FocusChanged(int focusFlags); void Press() { down_ = true; dragging_ = false; } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index c4c83cb4e9..35487441e9 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -85,6 +85,9 @@ void ViewGroup::Draw(UIContext &dc) { if (hasDropShadow_) { // Darken things behind. dc.FillRect(UI::Drawable(0x60000000), Bounds(0,0,dp_xres, dp_yres)); + float dropsize = 30; + dc.Draw()->DrawImage4Grid(dc.theme->dropShadow4Grid, bounds_.x - dropsize, bounds_.y, bounds_.x2() + dropsize, bounds_.y2()+dropsize*1.5, 0xDF000000, 3.0f); + // dc.Draw()->DrawImage4Grid(dc.theme->dropShadow, ) } @@ -343,8 +346,10 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v const LinearLayoutParams *linLayoutParams = static_cast(layoutParams); if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; - if (linLayoutParams && linLayoutParams->weight > 0.0f) - views_[i]->Measure(dc, MeasureSpec(EXACTLY, unit * linLayoutParams->weight), MeasureSpec(EXACTLY, measuredHeight_)); + if (linLayoutParams && linLayoutParams->weight > 0.0f) { + int marginSum = linLayoutParams->margins.left + linLayoutParams->margins.right; + views_[i]->Measure(dc, MeasureSpec(EXACTLY, unit * linLayoutParams->weight - marginSum), MeasureSpec(EXACTLY, measuredHeight_)); + } } } else { //MeasureBySpec(layoutParams_->height, vert.type == UNSPECIFIED ? sum : weightZeroSum, vert, &measuredHeight_); @@ -359,8 +364,10 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v const LinearLayoutParams *linLayoutParams = static_cast(layoutParams); if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; - if (linLayoutParams && linLayoutParams->weight > 0.0f) - views_[i]->Measure(dc, MeasureSpec(EXACTLY, measuredWidth_), MeasureSpec(EXACTLY, unit * linLayoutParams->weight)); + if (linLayoutParams && linLayoutParams->weight > 0.0f) { + int marginSum = linLayoutParams->margins.top + linLayoutParams->margins.bottom; + views_[i]->Measure(dc, MeasureSpec(EXACTLY, measuredWidth_), MeasureSpec(EXACTLY, unit * linLayoutParams->weight - marginSum)); + } } } } @@ -548,11 +555,13 @@ void ScrollView::Draw(UIContext &dc) { float scrollMax = std::max(0.0f, childHeight - bounds_.h); float ratio = bounds_.h / views_[0]->GetBounds().h; + + float bobWidth = 5; if (ratio < 1.0f && scrollMax > 0.0f) { float bobHeight = ratio * bounds_.h; float bobOffset = (scrollPos_ / scrollMax) * (bounds_.h - bobHeight); - Bounds bob(bounds_.x2() - 10, bounds_.y + bobOffset, 5, bobHeight); + Bounds bob(bounds_.x2() - bobWidth, bounds_.y + bobOffset, bobWidth, bobHeight); dc.FillRect(Drawable(0x80FFFFFF), bob); } } @@ -805,6 +814,7 @@ void ChoiceStrip::Key(const KeyInput &input) { SetSelection(selected_ + 1); } } + ViewGroup::Key(input); } ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) From 5422dead6ab36cd450bf02c4d2ec9350a5943b8c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 17 Aug 2013 10:33:49 +0200 Subject: [PATCH 0586/1445] Fix bug with float sliders. minor stuff. --- input/input_state.cpp | 1 + ui/ui_screen.h | 9 +++++---- ui/view.cpp | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/input/input_state.cpp b/input/input_state.cpp index 3261f3882e..2a75fbc2bb 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -8,6 +8,7 @@ const char *GetDeviceName(int deviceId) { case DEVICE_ID_PAD_0: return "pad"; case DEVICE_ID_X360_0: return "x360"; case DEVICE_ID_ACCELEROMETER: return "accelerometer"; + case DEVICE_ID_MOUSE: return "mouse"; default: return "unknown"; } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index f1999f6c70..5ac4c29608 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -63,16 +63,16 @@ private: class ListPopupScreen : public PopupScreen { public: - ListPopupScreen(std::string title) : PopupScreen(title) {} - ListPopupScreen(std::string title, const std::vector &items, int selected, std::function callback) - : PopupScreen(title), adaptor_(items, selected), callback_(callback) { + ListPopupScreen(std::string title) : PopupScreen(title), showButtons_(false) {} + ListPopupScreen(std::string title, const std::vector &items, int selected, std::function callback, bool showButtons = false) + : PopupScreen(title), adaptor_(items, selected), callback_(callback), showButtons_(showButtons) { } UI::Event OnChoice; protected: virtual bool FillVertical() { return true; } - virtual bool ShowButtons() { return false; } + virtual bool ShowButtons() { return showButtons_; } void CreatePopupContents(UI::ViewGroup *parent); UI::StringVectorListAdaptor adaptor_; UI::ListView *listView_; @@ -81,6 +81,7 @@ private: UI::EventReturn OnListChoice(UI::EventParams &e); std::function callback_; + bool showButtons_; }; class MessagePopupScreen : public PopupScreen { diff --git a/ui/view.cpp b/ui/view.cpp index caae38cdbc..8e17e48600 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -507,7 +507,7 @@ void SliderFloat::Key(const KeyInput &input) { void SliderFloat::Touch(const TouchInput &input) { if (dragging_ || bounds_.Contains(input.x, input.y)) { float relativeX = (input.x - bounds_.x) / bounds_.w; - *value_ = floorf(relativeX * (maxValue_ - minValue_) + minValue_ + 0.5f); + *value_ = relativeX * (maxValue_ - minValue_) + minValue_; Clamp(); } } From 17996ccd4c133e2f930e9b7141875a6ed5e24558 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 17 Aug 2013 12:06:08 +0200 Subject: [PATCH 0587/1445] Fix some kb control bugs (slider, etc) --- ui/ui_screen.cpp | 12 ++---------- ui/ui_screen.h | 5 ++--- ui/view.cpp | 9 +++++---- ui/view.h | 2 +- ui/viewgroup.cpp | 18 +++++++++++++----- ui/viewgroup.h | 6 ++++-- 6 files changed, 27 insertions(+), 25 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 49ebb23992..c739305bed 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -51,8 +51,8 @@ void UIScreen::key(const KeyInput &key) { } } -void DialogScreen::key(const KeyInput &key) { - if ((key.flags & KEY_DOWN) && key.keyCode == NKCODE_ESCAPE || key.keyCode == NKCODE_BACK || key.keyCode == NKCODE_BUTTON_B) { +void UIDialogScreen::key(const KeyInput &key) { + if ((key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) { screenManager()->finishDialog(this, DR_CANCEL); } else { UIScreen::key(key); @@ -93,13 +93,11 @@ void UIScreen::axis(const AxisInput &axis) { } } - UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { screenManager()->finishDialog(this, DR_OK); return UI::EVENT_DONE; } - PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2) : title_(title), button1_(button1), button2_(button2) {} @@ -141,12 +139,6 @@ void PopupScreen::CreateViews() { } } -void PopupScreen::key(const KeyInput &key) { - if ((key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) - screenManager()->finishDialog(this, DR_CANCEL); - UIScreen::key(key); -} - void MessagePopupScreen::CreatePopupContents(UI::ViewGroup *parent) { parent->Add(new UI::TextView(message_)); } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 5ac4c29608..18847c9bbb 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -32,20 +32,19 @@ private: int hatDown_; }; -class DialogScreen : public UIScreen { +class UIDialogScreen : public UIScreen { public: virtual void key(const KeyInput &key); }; -class PopupScreen : public UIScreen { +class PopupScreen : public UIDialogScreen { public: PopupScreen(std::string title, std::string button1 = "", std::string button2 = ""); virtual void CreatePopupContents(UI::ViewGroup *parent) = 0; virtual void CreateViews(); virtual bool isTransparent() { return true; } - virtual void key(const KeyInput &key); protected: virtual bool FillVertical() { return false; } diff --git a/ui/view.cpp b/ui/view.cpp index 8e17e48600..5d4f7f265d 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -453,7 +453,7 @@ void Slider::Key(const KeyInput &input) { case NKCODE_DPAD_RIGHT: case NKCODE_PLUS: case NKCODE_NUMPAD_ADD: - *value_ -= 1; + *value_ += 1; break; } Clamp(); @@ -474,8 +474,9 @@ void Slider::Clamp() { } void Slider::Draw(UIContext &dc) { + bool focus = HasFocus(); float knobX = ((float)(*value_) - minValue_) / (maxValue_ - minValue_) * bounds_.w + bounds_.x; - dc.FillRect(Drawable(0xFFFFFFFF), Bounds(bounds_.x, bounds_.centerY() - 2, knobX - bounds_.x, 4)); + dc.FillRect(Drawable(focus ? dc.theme->popupTitle.fgColor : 0xFFFFFFFF), Bounds(bounds_.x, bounds_.centerY() - 2, knobX - bounds_.x, 4)); dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, bounds_.x + bounds_.w - knobX, 4)); dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); } @@ -492,12 +493,12 @@ void SliderFloat::Key(const KeyInput &input) { case NKCODE_DPAD_LEFT: case NKCODE_MINUS: case NKCODE_NUMPAD_SUBTRACT: - *value_ -= 1; + *value_ -= (maxValue_ - minValue_) / 20.0f; break; case NKCODE_DPAD_RIGHT: case NKCODE_PLUS: case NKCODE_NUMPAD_ADD: - *value_ -= 1; + *value_ += (maxValue_ - minValue_) / 20.0f; break; } Clamp(); diff --git a/ui/view.h b/ui/view.h index d3eeea8ee2..635a4ef21e 100644 --- a/ui/view.h +++ b/ui/view.h @@ -509,7 +509,7 @@ public: virtual void Touch(const TouchInput &touch); virtual void FocusChanged(int focusFlags); - void Press() { down_ = true; dragging_ = false; } + void Press() { down_ = true; dragging_ = false; } void Release() { down_ = false; dragging_ = false; } bool IsDown() { return down_; } }; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 35487441e9..2fd1c39968 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -799,11 +799,19 @@ EventReturn ChoiceStrip::OnChoiceClick(EventParams &e) { } void ChoiceStrip::SetSelection(int sel) { - if (selected_ < views_.size()) - static_cast(views_[selected_])->Release(); - selected_ = sel; - if (selected_ < views_.size()) - static_cast(views_[selected_])->Press(); + if (topTabs_) { + int prevSelected = selected_; + if (selected_ < views_.size()) + static_cast(views_[selected_])->Release(); + selected_ = sel; + if (selected_ < views_.size()) + static_cast(views_[selected_])->Press(); + if (prevSelected != selected_) { + EventParams e; + e.v = views_[selected_]; + static_cast(views_[selected_])->OnClick.Trigger(e); + } + } } void ChoiceStrip::Key(const KeyInput &input) { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 181b91e1a0..579e671ac4 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -222,19 +222,20 @@ public: class ChoiceStrip : public LinearLayout { public: ChoiceStrip(Orientation orientation, LayoutParams *layoutParams = 0) - : LinearLayout(orientation, layoutParams), selected_(0) { SetSpacing(0.0f); } + : LinearLayout(orientation, layoutParams), selected_(0), topTabs_(false) { SetSpacing(0.0f); } void AddChoice(const std::string &title); int GetSelection() const { return selected_; } void SetSelection(int sel); virtual void Key(const KeyInput &input); - + void SetTopTabs(bool tabs) { topTabs_ = tabs; } Event OnChoice; private: EventReturn OnChoiceClick(EventParams &e); int selected_; + bool topTabs_; // Can be controlled with L/R. }; @@ -244,6 +245,7 @@ public: : LinearLayout(Opposite(orientation), layoutParams), orientation_(orientation), stripSize_(stripSize), currentTab_(0) { tabStrip_ = new ChoiceStrip(orientation, new LinearLayoutParams(stripSize, WRAP_CONTENT)); + tabStrip_->SetTopTabs(true); Add(tabStrip_); tabStrip_->OnChoice.Handle(this, &TabHolder::OnTabClick); } From 1effa138697927d5e74b40bd5f26133c6a7bc0d2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 17 Aug 2013 13:20:28 +0200 Subject: [PATCH 0588/1445] Fix minor bug in ChoiceStrips --- ui/viewgroup.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 2fd1c39968..bd30df40ca 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -799,18 +799,16 @@ EventReturn ChoiceStrip::OnChoiceClick(EventParams &e) { } void ChoiceStrip::SetSelection(int sel) { - if (topTabs_) { - int prevSelected = selected_; - if (selected_ < views_.size()) - static_cast(views_[selected_])->Release(); - selected_ = sel; - if (selected_ < views_.size()) - static_cast(views_[selected_])->Press(); - if (prevSelected != selected_) { - EventParams e; - e.v = views_[selected_]; - static_cast(views_[selected_])->OnClick.Trigger(e); - } + int prevSelected = selected_; + if (selected_ < views_.size()) + static_cast(views_[selected_])->Release(); + selected_ = sel; + if (selected_ < views_.size()) + static_cast(views_[selected_])->Press(); + if (topTabs_ && prevSelected != selected_) { + EventParams e; + e.v = views_[selected_]; + static_cast(views_[selected_])->OnClick.Trigger(e); } } From 217549921782067d433fc8e449a9aa3e186798a6 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 17 Aug 2013 23:49:33 +0200 Subject: [PATCH 0589/1445] Typo fixes --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 51a976e9cc..90efe45bcf 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -441,7 +441,7 @@ public class NativeActivity extends Activity { NativeApp.keyDown(0, 1004); // special custom keycode } else if (NativeApp.isAtTopLevel()) { Log.i(TAG, "IsAtTopLevel returned true."); - return super.onKeyUp(keyCode, event); + return super.onKeyDown(keyCode, event); } else { NativeApp.keyDown(0, keyCode); } @@ -461,7 +461,7 @@ public class NativeActivity extends Activity { case KeyEvent.KEYCODE_DPAD_RIGHT: // Joysticks are supported in Honeycomb MR1 and later via the onGenericMotionEvent method. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && event.getSource() == InputDevice.SOURCE_JOYSTICK) { - return super.onKeyUp(keyCode, event); + return super.onKeyDown(keyCode, event); } // Fall through default: From 0a857fe4a1430c3567f5eb92442e771985d05d11 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Aug 2013 00:14:25 +0200 Subject: [PATCH 0590/1445] Add a way to get the "System name" (will be mostly useful for android). Tweaks. --- android/app-android.cpp | 8 +++++++- base/NativeApp.h | 1 + base/PCMain.cpp | 5 +++++ gfx_es2/gl_state.cpp | 3 +++ gfx_es2/gl_state.h | 3 +++ ui/view.cpp | 2 +- 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index faa4d4494e..a3347bae2e 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -31,6 +31,8 @@ static JNIEnv *jniEnvUI; std::string frameCommand; std::string frameCommandParam; +std::string systemName; + const bool extraLog = true; static float left_joystick_x_async; @@ -84,6 +86,10 @@ void System_InputBox(const char *title, const char *defaultValue) { frameCommandParam = title; } +std::string System_GetName() { + return systemName; +} + // Remember that all of these need initialization on init! The process // may be reused when restarting the game. Globals are DANGEROUS. @@ -152,7 +158,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init ILOG("NativeApp::Init: APK path: %s", apkPath.c_str()); VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); - std::string deviceType = GetJavaString(env, jdevicetype); + systemName = GetJavaString(env, jdevicetype); std::string externalDir = GetJavaString(env, jexternalDir); std::string user_data_path = GetJavaString(env, jdataDir) + "/"; diff --git a/base/NativeApp.h b/base/NativeApp.h index a00d9af144..ca7bdad320 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -97,3 +97,4 @@ void LaunchBrowser(const char *url); void LaunchMarket(const char *url); void LaunchEmail(const char *email_address); void System_InputBox(const char *title, const char *defaultValue); +std::string System_GetName(); \ No newline at end of file diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 00ac7fcaf9..7b5598c1da 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -248,6 +248,11 @@ void LaunchEmail(const char *email_address) #endif } +std::string System_GetName() { + // TODO + return "SDL"; +} + InputState input_state; diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index e0a61f9ddb..5c733d48d0 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -82,10 +82,12 @@ void CheckGLExtensions() { memset(&gl_extensions, 0, sizeof(gl_extensions)); const char *extString = (const char *)glGetString(GL_EXTENSIONS); + gl_extensions.all_gl_extensions = extString; #ifdef WIN32 const char *wglString = wglGetExtensionsStringEXT(); gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0; + gl_extensions.all_egl_extensions = wglString; #elif !defined(USING_GLES2) // const char *glXString = glXQueryExtensionString(); // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; @@ -132,6 +134,7 @@ void CheckGLExtensions() { EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); const char *eglString = eglQueryString(display, EGL_EXTENSIONS); + gl_extensions.all_egl_extensions = eglString; gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0; gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 1d692435bc..dd20241d4d 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -270,6 +270,9 @@ struct GLExtensions { bool EGL_NV_system_time; bool EGL_NV_coverage_sample; + + std::string all_gl_extensions; + std::string all_egl_extensions; }; extern GLExtensions gl_extensions; diff --git a/ui/view.cpp b/ui/view.cpp index 5d4f7f265d..29b76848cc 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -304,7 +304,7 @@ void InfoItem::Draw(UIContext &dc) { Item::Draw(dc); int paddingX = 12; dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); - dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); + dc.Draw()->DrawText(dc.theme->uiFont, rightText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); // dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor); } From 581db21304e1abcc7795a6f3ab77b64f58cb31e9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Aug 2013 00:16:17 +0200 Subject: [PATCH 0591/1445] Buildfix --- gfx_es2/gl_state.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index dd20241d4d..2fc32fe02b 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -2,6 +2,7 @@ #include #include +#include #include "gfx/gl_common.h" #ifdef USING_GLES2 From 89361d002f7755b4effedf67cf2fc1bf0d38e4bc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Aug 2013 00:39:21 +0200 Subject: [PATCH 0592/1445] Bugfixes --- android/app-android.cpp | 1 + gfx_es2/gl_state.cpp | 33 +++++++++++++++++++++++---------- gfx_es2/gl_state.h | 10 +++++++--- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index a3347bae2e..94e4bf9efc 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -244,6 +244,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIE ILOG("Calling NativeInitGraphics(): dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); NativeInitGraphics(); + ILOG("NativeInitGraphics() completed"); dp_xscale = (float)dp_xres / pixel_xres; dp_yscale = (float)dp_yres / pixel_yres; diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 5c733d48d0..c5ab9c209f 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -22,6 +22,8 @@ PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; OpenGLState glstate; GLExtensions gl_extensions; +std::string g_all_gl_extensions; +std::string g_all_egl_extensions; int OpenGLState::state_count = 0; @@ -82,12 +84,20 @@ void CheckGLExtensions() { memset(&gl_extensions, 0, sizeof(gl_extensions)); const char *extString = (const char *)glGetString(GL_EXTENSIONS); - gl_extensions.all_gl_extensions = extString; + if (extString) { + g_all_gl_extensions = extString; + } else { + g_all_gl_extensions = ""; + } #ifdef WIN32 const char *wglString = wglGetExtensionsStringEXT(); - gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0; - gl_extensions.all_egl_extensions = wglString; + if (wglString) { + gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0; + g_all_egl_extensions = wglString; + } else { + g_all_egl_extensions = ""; + } #elif !defined(USING_GLES2) // const char *glXString = glXQueryExtensionString(); // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; @@ -108,7 +118,6 @@ void CheckGLExtensions() { glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress ( "glBindVertexArrayOES" ); glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress ( "glDeleteVertexArraysOES" ); glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" ); - ILOG("VAO available"); } gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; @@ -134,14 +143,18 @@ void CheckGLExtensions() { EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); const char *eglString = eglQueryString(display, EGL_EXTENSIONS); - gl_extensions.all_egl_extensions = eglString; + if (eglString) { + g_all_egl_extensions = eglString; - gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0; - gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0; + gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0; + gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0; - if (gl_extensions.EGL_NV_system_time) { - eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV"); - eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV"); + if (gl_extensions.EGL_NV_system_time) { + eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV"); + eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV"); + } + } else { + g_all_egl_extensions = ""; } #endif diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 2fc32fe02b..5a2bc24d0e 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -255,6 +255,8 @@ public: extern OpenGLState glstate; + +// WARNING: This gets memset-d - so no strings please struct GLExtensions { bool OES_depth24; bool OES_packed_depth_stencil; @@ -271,11 +273,13 @@ struct GLExtensions { bool EGL_NV_system_time; bool EGL_NV_coverage_sample; - - std::string all_gl_extensions; - std::string all_egl_extensions; }; + +extern std::string g_all_gl_extensions; +extern std::string g_all_egl_extensions; + + extern GLExtensions gl_extensions; void CheckGLExtensions(); From 0dda25890a3f5870b35c4b6ccff9270cd11cdc9f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Aug 2013 01:12:40 +0200 Subject: [PATCH 0593/1445] Consider "X" on xperia play an "accept" button in the UI. --- ui/view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/view.cpp b/ui/view.cpp index 29b76848cc..8de3a9f8d6 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -185,7 +185,7 @@ void Clickable::Touch(const TouchInput &input) { } bool IsAcceptKeyCode(int keyCode) { - return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_X || keyCode == NKCODE_BUTTON_A; + return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_Z || keyCode == NKCODE_BUTTON_A || keyCode == NKCODE_BUTTON_X; } bool IsEscapeKeyCode(int keyCode) { From 987aaa26d80fc897b2678cabbd09733e67b34303 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Aug 2013 01:17:45 +0200 Subject: [PATCH 0594/1445] Accept Xperia Play's circle/cross as accept/cancel, correctly this time --- ui/view.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 8de3a9f8d6..cb8a2022dc 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -184,12 +184,14 @@ void Clickable::Touch(const TouchInput &input) { } } +// TODO: O/X confirm preference for xperia play? + bool IsAcceptKeyCode(int keyCode) { - return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_Z || keyCode == NKCODE_BUTTON_A || keyCode == NKCODE_BUTTON_X; + return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_Z || keyCode == NKCODE_BUTTON_A || keyCode == NKCODE_BUTTON_CROSS; } bool IsEscapeKeyCode(int keyCode) { - return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK; + return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE; } void Clickable::Key(const KeyInput &key) { From a0560859e2160b185d86239ff2b44e872cfc3dd4 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 18 Aug 2013 17:28:34 +1000 Subject: [PATCH 0595/1445] System strings for Qt and Blackberry frontends. --- base/BlackberryMain.cpp | 4 ++++ base/QtMain.cpp | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 085ca135fd..1e9d104c17 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -13,6 +13,10 @@ // Simple implementations of System functions +std::string System_GetName() { + return "Blackberry10"; +} + void SystemToast(const char *text) { dialog_instance_t dialog = 0; dialog_create_toast(&dialog); diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 9a13a0209b..ee08a84bb6 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -19,6 +19,22 @@ InputState* input_state; +std::string System_GetName() { +#ifdef __SYMBIAN32__ + return "Qt:Symbian"; +#elif defined(BLACKBERRY) + return "Qt:Blackberry10"; +#elif defined(MEEGO_EDITION_HARMATTAN) + return "Qt:Meego"; +#elif defined(Q_WS_X11) + return "Qt:Linux"; +#elif defined(_WIN32) + return "Qt:Windows"; +#else + return "Qt"; +#endif +} + void LaunchBrowser(const char *url) { QDesktopServices::openUrl(QUrl(url)); From f7c51bbeee023293e6338f6f664fcb85c6dbb89f Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 18 Aug 2013 18:15:56 +1000 Subject: [PATCH 0596/1445] Fix -lz order. --- tools/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 48b888df4f..0a54bfd97f 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -52,7 +52,7 @@ add_subdirectory(../ext/stb_image stb_image) add_executable(atlastool atlastool.cpp) -target_link_libraries(atlastool ${PNG_LIBRARY} freetype util z image stb_image rg_etc1 file zip gomp) +target_link_libraries(atlastool ${PNG_LIBRARY} freetype util image z stb_image rg_etc1 file zip gomp) add_executable(zimtool zimtool.cpp) -target_link_libraries(zimtool ${PNG_LIBRARY} freetype z image stb_image rg_etc1 file zip gomp) +target_link_libraries(zimtool ${PNG_LIBRARY} freetype image z stb_image rg_etc1 file zip gomp) From dd01ff5d9688d54555090d652ca6fae570217356 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 18 Aug 2013 18:39:32 +1000 Subject: [PATCH 0597/1445] Use 'HIGH_MEM' defines to choose what text is added to atlas. Could change atlasscript.txt input instead but this is a bit more flexible. --- tools/atlastool.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 28d50d6acc..be52872d7e 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -41,6 +41,8 @@ #include "util/text/utf8.h" +#define HIGH_MEM 1 + #define CHECK(x) if (!(x)) { printf("%i: CHECK failed on this line\n", __LINE__); exit(1); } using namespace std; @@ -684,6 +686,7 @@ void LearnFile(const char *filename, const char *desc, std::set &chars, uin void GetLocales(const char *locales, std::vector &ranges) { +#if HIGH_MEM std::set kanji; std::set hangul1, hangul2, hangul3; for (int i = 0; i < sizeof(kanjiFilter)/sizeof(kanjiFilter[0]); i+=2) @@ -699,6 +702,7 @@ void GetLocales(const char *locales, std::vector &ranges) LearnFile("korean.txt", "Korean", hangul1, 0x1100, 0x11FF); LearnFile("korean.txt", "Korean", hangul2, 0x3130, 0x318F); LearnFile("korean.txt", "Korean", hangul3, 0xAC00, 0xD7A3); +#endif // The end point of a range is now inclusive! @@ -715,6 +719,7 @@ void GetLocales(const char *locales, std::vector &ranges) case 'E': // Latin-1 Extended A (needed for Hungarian etc) ranges.push_back(range(0x100, 0x17F)); break; +#if HIGH_MEM case 'e': // Latin-1 Extended B (for some African and latinized asian languages?) ranges.push_back(range(0x180, 0x250)); break; @@ -727,6 +732,7 @@ void GetLocales(const char *locales, std::vector &ranges) ranges.push_back(range(0x3041, 0x3097)); ranges.push_back(range(0x3099, 0x309F)); break; +#endif case 's': // ShiftJIS symbols ranges.push_back(range(0x2010, 0x2312)); // General Punctuation, Letterlike Symbols, Arrows, // Mathematical Operators, Miscellaneous Technical @@ -735,6 +741,8 @@ void GetLocales(const char *locales, std::vector &ranges) ranges.push_back(range(0x3231, 0x3231)); // Co,.Ltd. symbol ranges.push_back(range(0x2116, 0x2116)); // "No." symbol ranges.push_back(range(0x33CD, 0x33CD)); // "K.K." symbol + break; +#if HIGH_MEM case 'H': // Hebrew ranges.push_back(range(0x0590, 0x05FF)); break; @@ -755,6 +763,7 @@ void GetLocales(const char *locales, std::vector &ranges) case 'K': // Korean (hangul) ranges.push_back(range(0xAC00, 0xD7A3, hangul3)); break; +#endif } } From b8b4add22254942fbb2174cfae2371835c2954bb Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 19 Aug 2013 00:01:59 +1000 Subject: [PATCH 0598/1445] Use new input method for controllers on Blackberry. --- base/BlackberryMain.cpp | 40 +++++++------------------------------ base/BlackberryMain.h | 2 +- base/NKCodeFromBlackberry.h | 22 ++++++++++++++++++++ 3 files changed, 30 insertions(+), 34 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 1e9d104c17..d0e990c239 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -56,22 +56,6 @@ void LaunchEmail(const char *email_address) InputState input_state; -void SimulateGamepad(InputState *input) { - input->pad_lstick_x = 0; - input->pad_lstick_y = 0; - input->pad_rstick_x = 0; - input->pad_rstick_y = 0; - - if (input->pad_buttons & PAD_BUTTON_JOY_UP) - input->pad_lstick_y=1; - else if (input->pad_buttons & PAD_BUTTON_JOY_DOWN) - input->pad_lstick_y=-1; - if (input->pad_buttons & PAD_BUTTON_JOY_LEFT) - input->pad_lstick_x=-1; - else if (input->pad_buttons & PAD_BUTTON_JOY_RIGHT) - input->pad_lstick_x=1; -} - void BlackberryMain::handleInput(screen_event_t screen_event) { TouchInput input; @@ -142,26 +126,19 @@ void BlackberryMain::handleInput(screen_event_t screen_event) NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawBlackberrytoNative.find(value)->second, (flags & KEY_DOWN) ? KEY_DOWN : KEY_UP)); break; // Gamepad - // TODO: Isn't using new input system yet case SCREEN_EVENT_GAMEPAD: case SCREEN_EVENT_JOYSTICK: char device_id[16]; -#define DIR_KEYS SCREEN_DPAD_UP_GAME_BUTTON | SCREEN_DPAD_DOWN_GAME_BUTTON | SCREEN_DPAD_LEFT_GAME_BUTTON | SCREEN_DPAD_RIGHT_GAME_BUTTON screen_device_t device; screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DEVICE, (void**)&device); screen_get_device_property_cv(device, SCREEN_PROPERTY_ID_STRING, sizeof(device_id), device_id); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); - // Map the buttons integer to our mappings - if (strstr(device_id, "057E-0306")) // Wiimote - controller_buttons = (buttons & (SCREEN_A_GAME_BUTTON | SCREEN_B_GAME_BUTTON)) << 2 | - (buttons & (SCREEN_X_GAME_BUTTON | SCREEN_Y_GAME_BUTTON)) >> 3; - else - controller_buttons = (buttons & (SCREEN_A_GAME_BUTTON | SCREEN_B_GAME_BUTTON)) | - (buttons & (SCREEN_X_GAME_BUTTON | SCREEN_Y_GAME_BUTTON)) >> 1; - controller_buttons |= (buttons & (SCREEN_MENU1_GAME_BUTTON | SCREEN_MENU2_GAME_BUTTON)) | - (buttons & SCREEN_L1_GAME_BUTTON) >> 6 | (buttons & SCREEN_R1_GAME_BUTTON) >> 8 | - (buttons & DIR_KEYS) >> 8 | - (buttons & DIR_KEYS) >> 2; + for (int i = 0; i < 32; i++) { + int mask = 1 << i; + if ((old_buttons & mask) != (buttons & mask)) + NativeKey(KeyInput(DEVICE_ID_PAD_0, KeyMapPadBlackberrytoNative.find(mask)->second, (buttons & mask) ? KEY_DOWN : KEY_UP)); + } + old_buttons = buttons; break; case SCREEN_EVENT_DISPLAY: screen_display_t new_dpy = NULL; @@ -195,6 +172,7 @@ void BlackberryMain::startMain(int argc, char *argv[]) { // TODO: Enable/disable based on setting sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, 25000); sensor_request_events(SENSOR_TYPE_ACCELEROMETER); + old_buttons = 0; net::Init(); startDisplays(); @@ -213,7 +191,6 @@ void BlackberryMain::runMain() { while (running) { input_state.mouse_valid = false; input_state.accelerometer_valid = false; - SimulateGamepad(&input_state); while (true) { // Handle Blackberry events bps_event_t *event = NULL; @@ -249,9 +226,6 @@ void BlackberryMain::runMain() { } } } - // TODO: This is broken. Instead we should just send keyboard events through using NativeKey and not - // even bother with these bitfields. - input_state.pad_buttons = controller_buttons; UpdateInputState(&input_state); NativeUpdate(input_state); // Work in Progress diff --git a/base/BlackberryMain.h b/base/BlackberryMain.h index 4a69c49afc..1a370ae0b6 100644 --- a/base/BlackberryMain.h +++ b/base/BlackberryMain.h @@ -80,7 +80,7 @@ private: int ndisplays; int screen_ui, screen_emu; bool emulating; - int controller_buttons; + int old_buttons; EGLDisplay* egl_disp; EGLSurface* egl_surf; EGLContext egl_cont; diff --git a/base/NKCodeFromBlackberry.h b/base/NKCodeFromBlackberry.h index e0a929c717..2436a38d33 100644 --- a/base/NKCodeFromBlackberry.h +++ b/base/NKCodeFromBlackberry.h @@ -1,6 +1,28 @@ #include #include "util/const_map.h" +static const std::map KeyMapPadBlackberrytoNative = InitConstMap + (SCREEN_A_GAME_BUTTON, NKCODE_BUTTON_A) + (SCREEN_B_GAME_BUTTON, NKCODE_BUTTON_B) + (SCREEN_C_GAME_BUTTON, NKCODE_BUTTON_C) + (SCREEN_X_GAME_BUTTON, NKCODE_BUTTON_X) + (SCREEN_Y_GAME_BUTTON, NKCODE_BUTTON_Y) + (SCREEN_Z_GAME_BUTTON, NKCODE_BUTTON_Z) + (SCREEN_MENU1_GAME_BUTTON, NKCODE_BUTTON_START) + (SCREEN_MENU2_GAME_BUTTON, NKCODE_BUTTON_SELECT) + (SCREEN_MENU3_GAME_BUTTON, NKCODE_BUTTON_MENU) + (SCREEN_MENU4_GAME_BUTTON, NKCODE_BUTTON_ESCAPE) + (SCREEN_L1_GAME_BUTTON, NKCODE_BUTTON_L1) + (SCREEN_L2_GAME_BUTTON, NKCODE_BUTTON_L2) + (SCREEN_L3_GAME_BUTTON, NKCODE_OUYA_BUTTON_L3) + (SCREEN_R1_GAME_BUTTON, NKCODE_BUTTON_R1) + (SCREEN_R2_GAME_BUTTON, NKCODE_BUTTON_R2) + (SCREEN_R3_GAME_BUTTON, NKCODE_OUYA_BUTTON_R3) + (SCREEN_DPAD_UP_GAME_BUTTON, NKCODE_DPAD_UP) + (SCREEN_DPAD_DOWN_GAME_BUTTON, NKCODE_DPAD_DOWN) + (SCREEN_DPAD_LEFT_GAME_BUTTON, NKCODE_DPAD_LEFT) + (SCREEN_DPAD_RIGHT_GAME_BUTTON, NKCODE_DPAD_RIGHT) + // TODO: Add any missing keys static const std::map KeyMapRawBlackberrytoNative = InitConstMap (KEYCODE_P, NKCODE_P) From 2f7f6adfd2cfdc36ff6d9a1e6d537ed053e4c5e9 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 19 Aug 2013 00:26:00 +1000 Subject: [PATCH 0599/1445] Blackberry buildfix. --- base/BlackberryMain.cpp | 1 - base/BlackberryMain.h | 2 +- base/NKCodeFromBlackberry.h | 6 +++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index d0e990c239..2caa26f8ef 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -172,7 +172,6 @@ void BlackberryMain::startMain(int argc, char *argv[]) { // TODO: Enable/disable based on setting sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, 25000); sensor_request_events(SENSOR_TYPE_ACCELEROMETER); - old_buttons = 0; net::Init(); startDisplays(); diff --git a/base/BlackberryMain.h b/base/BlackberryMain.h index 1a370ae0b6..01b4750699 100644 --- a/base/BlackberryMain.h +++ b/base/BlackberryMain.h @@ -48,7 +48,7 @@ public: BlackberryMain(int argc, char *argv[]) : emulating(false), screen_ui(0), screen_emu(0), - controller_buttons(0), + old_buttons(0), egl_cont(EGL_NO_CONTEXT) { startMain(argc, argv); diff --git a/base/NKCodeFromBlackberry.h b/base/NKCodeFromBlackberry.h index 2436a38d33..2b73c6a8d4 100644 --- a/base/NKCodeFromBlackberry.h +++ b/base/NKCodeFromBlackberry.h @@ -10,8 +10,8 @@ static const std::map KeyMapPadBlackberrytoNative = InitConstMap KeyMapPadBlackberrytoNative = InitConstMap KeyMapRawBlackberrytoNative = InitConstMap From 0819b421716f01cb46b4c36dcb99468b8bb5ad9a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Aug 2013 18:53:06 +0200 Subject: [PATCH 0600/1445] Reset logicop state when drawing UI --- ui/ui_context.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index b8bd28466b..7ed68f129c 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -11,17 +11,15 @@ void UIContext::Begin() { glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glstate.cullFace.disable(); glstate.depthTest.disable(); +#if !defined(USING_GLES2) + glstate.colorLogicOp.disable(); +#endif if (uishader_) glsl_bind(uishader_); if (uitexture_) uitexture_->Bind(0); UIBegin(uishader_); - /* - if (uidrawbuffer_ && uishader_) - uidrawbuffer_->Begin(); - if (uidrawbufferTop_ && uishader_) - uidrawbufferTop_->Begin();*/ } void UIContext::BeginNoTex() { @@ -29,20 +27,17 @@ void UIContext::BeginNoTex() { glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glstate.cullFace.disable(); glstate.depthTest.disable(); +#if !defined(USING_GLES2) + glstate.colorLogicOp.disable(); +#endif if (uishader_) glsl_bind(uishader_); if (uitexture_) uitexture_->Bind(0); UIBegin(uishadernotex_); - /* - if (uidrawbuffer_ && uishader_) - uidrawbuffer_->Begin(); - if (uidrawbufferTop_ && uishader_) - uidrawbufferTop_->Begin();*/ } - void UIContext::RebindTexture() const { if (uitexture_) uitexture_->Bind(0); From 2d6f742694d1de6d58ee99af3707c9592671311b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Aug 2013 19:51:19 +0200 Subject: [PATCH 0601/1445] Minor fixes --- ui/ui_screen.h | 2 +- ui/view.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 18847c9bbb..83456dad4d 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -64,7 +64,7 @@ class ListPopupScreen : public PopupScreen { public: ListPopupScreen(std::string title) : PopupScreen(title), showButtons_(false) {} ListPopupScreen(std::string title, const std::vector &items, int selected, std::function callback, bool showButtons = false) - : PopupScreen(title), adaptor_(items, selected), callback_(callback), showButtons_(showButtons) { + : PopupScreen(title, "OK", "Cancel"), adaptor_(items, selected), callback_(callback), showButtons_(showButtons) { } UI::Event OnChoice; diff --git a/ui/view.cpp b/ui/view.cpp index cb8a2022dc..46350f7fde 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -191,7 +191,7 @@ bool IsAcceptKeyCode(int keyCode) { } bool IsEscapeKeyCode(int keyCode) { - return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE; + return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B; } void Clickable::Key(const KeyInput &key) { From 267f1052611ecf280aad00d1fba650caf3220c24 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Aug 2013 22:29:50 +0200 Subject: [PATCH 0602/1445] Fix recursive scissor rects. Clip text to buttons if necessary. --- math/geom2d.h | 17 +++++++++++++++++ ui/ui_context.cpp | 5 ++++- ui/view.cpp | 8 ++++++++ ui/viewgroup.cpp | 44 +++++++++++++++++++++++++++++++++----------- ui/viewgroup.h | 7 ++++++- 5 files changed, 68 insertions(+), 13 deletions(-) diff --git a/math/geom2d.h b/math/geom2d.h index a2faca80b1..0a94a42b8c 100644 --- a/math/geom2d.h +++ b/math/geom2d.h @@ -35,6 +35,23 @@ struct Bounds { return !(x > other.x2() || x2() < other.x || y > other.y2() || y2() < other.y); } + void Clip(const Bounds &clipTo) { + if (x < clipTo.x) { + w -= clipTo.x - x; + x = clipTo.x; + } + if (y < clipTo.y) { + h -= clipTo.y - y; + y = clipTo.y; + } + if (x2() > clipTo.x2()) { + w = clipTo.x2() - x; + } + if (y2() > clipTo.y2()) { + h = clipTo.y2() - y; + } + } + float x2() const { return x + w; } float y2() const { return y + h; } float centerX() const { return x + w * 0.5f; } diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 7ed68f129c..b66e917cf1 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -62,7 +62,10 @@ void UIContext::End() { // TODO: Support transformed bounds using stencil void UIContext::PushScissor(const Bounds &bounds) { Flush(); - scissorStack_.push_back(bounds); + Bounds clipped = bounds; + if (scissorStack_.size()) + clipped.Clip(scissorStack_.back()); + scissorStack_.push_back(clipped); ActivateTopScissor(); } diff --git a/ui/view.cpp b/ui/view.cpp index 46350f7fde..a7a8f82217 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -349,7 +349,15 @@ void Button::Draw(UIContext &dc) { // dc.Draw()->DrawImage4Grid(style.image, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); dc.FillRect(style.background, bounds_); + float tw, th; + dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &tw, &th); + if (tw > bounds_.w) { + dc.PushScissor(bounds_); + } dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); + if (tw > bounds_.w) { + dc.PopScissor(); + } } void ImageView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index bd30df40ca..4f8b5e3560 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -456,27 +456,32 @@ void FrameLayout::Layout() { void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { // Respect margins Margins margins; - const LinearLayoutParams *linLayoutParams = static_cast(views_[0]->GetLayoutParams()); - if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; - - if (linLayoutParams) { - margins = linLayoutParams->margins; + if (views_.size()) { + const LinearLayoutParams *linLayoutParams = static_cast(views_[0]->GetLayoutParams()); + if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; + if (linLayoutParams) { + margins = linLayoutParams->margins; + } } // The scroll view itself simply obeys its parent - but also tries to fit the child if possible. MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); - if (orientation_ == ORIENT_HORIZONTAL) { - views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED), MeasureSpec(AT_MOST, measuredHeight_ - (margins.top + margins.bottom))); - } else { - views_[0]->Measure(dc, MeasureSpec(AT_MOST, measuredWidth_ - (margins.left + margins.right)), MeasureSpec(UNSPECIFIED)); + if (views_.size()) { + if (orientation_ == ORIENT_HORIZONTAL) { + views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED), MeasureSpec(AT_MOST, measuredHeight_ - (margins.top + margins.bottom))); + } else { + views_[0]->Measure(dc, MeasureSpec(AT_MOST, measuredWidth_ - (margins.left + margins.right)), MeasureSpec(UNSPECIFIED)); + } + if (orientation_ == ORIENT_VERTICAL && vert.type != EXACTLY && measuredHeight_ < views_[0]->GetBounds().h) + measuredHeight_ = views_[0]->GetBounds().h; } - if (orientation_ == ORIENT_VERTICAL && vert.type != EXACTLY && measuredHeight_ < views_[0]->GetBounds().h) - measuredHeight_ = views_[0]->GetBounds().h; } void ScrollView::Layout() { + if (!views_.size()) + return; Bounds scrolled; // Respect margins @@ -490,12 +495,21 @@ void ScrollView::Layout() { scrolled.w = views_[0]->GetMeasuredWidth() - (margins.left + margins.right); scrolled.h = views_[0]->GetMeasuredHeight() - (margins.top + margins.bottom); + switch (orientation_) { case ORIENT_HORIZONTAL: + if (scrolled.w != lastViewSize_) { + ScrollTo(0.0f); + lastViewSize_ = scrolled.w; + } scrolled.x = bounds_.x - scrollPos_; scrolled.y = bounds_.y + margins.top; break; case ORIENT_VERTICAL: + if (scrolled.h != lastViewSize_) { + ScrollTo(0.0f); + lastViewSize_ = scrolled.h; + } scrolled.x = bounds_.x + margins.left; scrolled.y = bounds_.y - scrollPos_; break; @@ -547,6 +561,10 @@ void ScrollView::Touch(const TouchInput &input) { } void ScrollView::Draw(UIContext &dc) { + if (!views_.size()) { + ViewGroup::Draw(dc); + return; + } dc.PushScissor(bounds_); views_[0]->Draw(dc); dc.PopScissor(); @@ -608,6 +626,8 @@ void ScrollView::ScrollRelative(float distance) { } void ScrollView::ClampScrollPos(float &pos) { + if (!views_.size()) + pos = 0.0f; // Clamp scrollTarget. float childHeight = views_[0]->GetBounds().h; float scrollMax = std::max(0.0f, childHeight - bounds_.h); @@ -621,6 +641,8 @@ void ScrollView::ClampScrollPos(float &pos) { } bool ScrollView::CanScroll() const { + if (!views_.size()) + return false; return views_[0]->GetBounds().h > bounds_.h; } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 579e671ac4..c10f6373db 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -57,6 +57,8 @@ public: void SetHasDropShadow(bool has) { hasDropShadow_ = has; } + void Lock() { modifyLock_.lock(); } + void Unlock() { modifyLock_.unlock(); } protected: recursive_mutex modifyLock_; // Hold this when changing the subviews. std::vector views_; @@ -185,7 +187,8 @@ public: scrollStart_(0), scrollMax_(0), scrollTarget_(0), - scrollToTarget_(false) {} + scrollToTarget_(false), + lastViewSize_(0.0f) {} void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); @@ -212,6 +215,8 @@ private: float scrollMax_; float scrollTarget_; bool scrollToTarget_; + + float lastViewSize_; }; class ViewPager : public ScrollView { From ce62b5bb470666cbee33476c480202024daf42f6 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Aug 2013 22:33:23 +0200 Subject: [PATCH 0603/1445] Fix linebreaks when saving language inis --- i18n/i18n.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp index 43a3db5626..56061bd751 100644 --- a/i18n/i18n.cpp +++ b/i18n/i18n.cpp @@ -95,13 +95,15 @@ void I18NRepo::SaveSection(IniFile &ini, IniFile::Section *section, I18NCategory for (auto iter = missed.begin(); iter != missed.end(); ++iter) { if (!section->Exists(iter->first.c_str())) { - section->Set(iter->first, iter->second); + std::string text = ReplaceAll(iter->second, "\n", "\\n"); + section->Set(iter->first, text); } } const std::map &entries = cat->GetMap(); for (auto iter = entries.begin(); iter != entries.end(); ++iter) { - section->Set(iter->first, iter->second.text); + std::string text = ReplaceAll(iter->second.text, "\n", "\\n"); + section->Set(iter->first, text); } cat->ClearMissed(); From 85d0fc61c546fc28ab351b7be18e96dbe9fc6a3e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 18 Aug 2013 23:11:26 +0200 Subject: [PATCH 0604/1445] Fix the disabled state of choices and checkboxes --- ui/view.cpp | 16 ++++++++++++---- ui/view.h | 2 +- ui/viewgroup.cpp | 4 ++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index a7a8f82217..5398e5f4c5 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -293,11 +293,15 @@ void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const void Choice::Draw(UIContext &dc) { ClickableItem::Draw(dc); + Style style = dc.theme->itemStyle; + if (!IsEnabled()) + style = dc.theme->itemDisabledStyle; + int paddingX = 12; - dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); + dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); if (selected_) { - dc.Draw()->DrawImage(dc.theme->checkOn, bounds_.x2() - 40, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + dc.Draw()->DrawImage(dc.theme->checkOn, bounds_.x2() - 40, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER); } // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); } @@ -333,8 +337,12 @@ void CheckBox::Draw(UIContext &dc) { int image = *toggle_ ? dc.theme->checkOn : dc.theme->checkOff; - dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); - dc.Draw()->DrawImage(image, bounds_.x2() - paddingX, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); + Style style = dc.theme->itemStyle; + if (!IsEnabled()) + style = dc.theme->itemDisabledStyle; + + dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + dc.Draw()->DrawImage(image, bounds_.x2() - paddingX, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); } void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const { diff --git a/ui/view.h b/ui/view.h index 635a4ef21e..08e01aaab4 100644 --- a/ui/view.h +++ b/ui/view.h @@ -324,7 +324,7 @@ public: } void SetEnabled(bool enabled) { enabled_ = enabled; } - bool GetEnabled() const { return enabled_; } + bool IsEnabled() const { return enabled_; } void SetVisibility(Visibility visibility) { visibility_ = visibility; } Visibility GetVisibility() const { return visibility_; } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 4f8b5e3560..943dfb1759 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -135,7 +135,7 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio // Skip labels and things like that. if (!destination->CanBeFocused()) return 0.0f; - if (destination->GetEnabled() == false) + if (destination->IsEnabled() == false) return 0.0f; if (destination->GetVisibility() != V_VISIBLE) return 0.0f; @@ -178,7 +178,7 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, NeighborResult result) { - if (!GetEnabled()) + if (!IsEnabled()) return result; if (GetVisibility() != V_VISIBLE) return result; From ddf5c379c3b2d368031990c81f96a062dc46bee4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 19 Aug 2013 22:05:22 +0200 Subject: [PATCH 0605/1445] Quickfix for mapping dialog --- ui/viewgroup.cpp | 2 +- ui/viewgroup.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 943dfb1759..94aa679c30 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -506,7 +506,7 @@ void ScrollView::Layout() { scrolled.y = bounds_.y + margins.top; break; case ORIENT_VERTICAL: - if (scrolled.h != lastViewSize_) { + if (scrolled.h != lastViewSize_ && scrollToTopOnSizeChange_) { ScrollTo(0.0f); lastViewSize_ = scrolled.h; } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index c10f6373db..f5469cd802 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -188,7 +188,8 @@ public: scrollMax_(0), scrollTarget_(0), scrollToTarget_(false), - lastViewSize_(0.0f) {} + lastViewSize_(0.0f), + scrollToTopOnSizeChange_(true) {} void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); @@ -205,6 +206,9 @@ public: // Override so that we can scroll to the active one after moving the focus. virtual bool SubviewFocused(View *view); + // Quick hack to prevent scrolling to top in some lists + void SetScrollToTop(bool t) { scrollToTopOnSizeChange_ = t; } + private: void ClampScrollPos(float &pos); @@ -217,6 +221,7 @@ private: bool scrollToTarget_; float lastViewSize_; + bool scrollToTopOnSizeChange_; }; class ViewPager : public ScrollView { From ba28246dd267badbea61e943597e05fa739a55c2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 00:34:54 +0200 Subject: [PATCH 0606/1445] Allow images on choice buttons, misc --- gfx/texture_atlas.h | 2 ++ gfx_es2/draw_buffer.cpp | 12 ++++++------ gfx_es2/draw_buffer.h | 16 +++++++++------- ui/view.cpp | 32 +++++++++++++++++++++++++------- ui/view.h | 31 +++++++++++++++++-------------- ui/viewgroup.cpp | 8 ++++++++ ui/viewgroup.h | 1 + 7 files changed, 68 insertions(+), 34 deletions(-) diff --git a/gfx/texture_atlas.h b/gfx/texture_atlas.h index 7aeda2bd6f..bbaa16de59 100644 --- a/gfx/texture_atlas.h +++ b/gfx/texture_atlas.h @@ -1,5 +1,7 @@ #pragma once +typedef int ImageID; + struct AtlasChar { // texcoords float sx, sy, ex, ey; diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index d79f441f0d..7d3e26d2dd 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -174,13 +174,13 @@ void DrawBuffer::Rect(float x, float y, float w, float h, V(x, y + h, 0, color, u, v + uh); } -void DrawBuffer::MeasureImage(int atlas_image, float *w, float *h) { +void DrawBuffer::MeasureImage(ImageID atlas_image, float *w, float *h) { const AtlasImage &image = atlas->images[atlas_image]; *w = (float)image.w; *h = (float)image.h; } -void DrawBuffer::DrawImage(int atlas_image, float x, float y, float scale, Color color, int align) { +void DrawBuffer::DrawImage(ImageID atlas_image, float x, float y, float scale, Color color, int align) { const AtlasImage &image = atlas->images[atlas_image]; float w = (float)image.w * scale; float h = (float)image.h * scale; @@ -191,7 +191,7 @@ void DrawBuffer::DrawImage(int atlas_image, float x, float y, float scale, Color DrawImageStretch(atlas_image, x, y, x + w, y + h, color); } -void DrawBuffer::DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color) { +void DrawBuffer::DrawImageStretch(ImageID atlas_image, float x1, float y1, float x2, float y2, Color color) { const AtlasImage &image = atlas->images[atlas_image]; V(x1, y1, color, image.u1, image.v1); V(x2, y1, color, image.u2, image.v1); @@ -215,7 +215,7 @@ inline void rot(float *v, float angle, float xc, float yc) { } -void DrawBuffer::DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color, bool mirror_h) { +void DrawBuffer::DrawImageRotated(ImageID atlas_image, float x, float y, float scale, float angle, Color color, bool mirror_h) { const AtlasImage &image = atlas->images[atlas_image]; float w = (float)image.w * scale; float h = (float)image.h * scale; @@ -287,7 +287,7 @@ void DrawBuffer::DrawTexRect(float x1, float y1, float x2, float y2, float u1, f V(x1, y2, color, u1, v2); } -void DrawBuffer::DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color, float corner_scale) { +void DrawBuffer::DrawImage4Grid(ImageID atlas_image, float x1, float y1, float x2, float y2, Color color, float corner_scale) { const AtlasImage &image = atlas->images[atlas_image]; float u1 = image.u1, v1 = image.v1, u2 = image.u2, v2 = image.v2; @@ -313,7 +313,7 @@ void DrawBuffer::DrawImage4Grid(int atlas_image, float x1, float y1, float x2, f DrawTexRect(xb, yb, x2, y2, um, vm, u2, v2, color); } -void DrawBuffer::DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color, float corner_scale) { +void DrawBuffer::DrawImage2GridH(ImageID atlas_image, float x1, float y1, float x2, Color color, float corner_scale) { const AtlasImage &image = atlas->images[atlas_image]; float um = (image.u1 + image.u2) * 0.5f; float iw2 = (image.w * 0.5f) * corner_scale; diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 002237fc0f..e8d7453801 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -6,6 +6,7 @@ #include "base/color.h" #include "base/display.h" #include "gfx/gl_lost_manager.h" +#include "gfx/texture_atlas.h" struct Atlas; @@ -98,22 +99,23 @@ public: atlas = _atlas; } const Atlas *GetAtlas() const { return atlas; } - void MeasureImage(int atlas_image, float *w, float *h); - void DrawImage(int atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT); - void DrawImageStretch(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); - void DrawImageRotated(int atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF), bool mirror_h = false); // Always centers + void MeasureImage(ImageID atlas_image, float *w, float *h); + void DrawImage(ImageID atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT); + void DrawImageStretch(ImageID atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); + void DrawImageRotated(ImageID atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF), bool mirror_h = false); // Always centers void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); // Results in 18 triangles. Kind of expensive for a button. - void DrawImage4Grid(int atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); + void DrawImage4Grid(ImageID atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); // This is only 6 triangles, much cheaper. - void DrawImage2GridH(int atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); + void DrawImage2GridH(ImageID atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); void MeasureText(int font, const char *text, float *w, float *h); void DrawTextRect(int font, const char *text, float x, float y, float w, float h, Color color = 0xFFFFFFFF, int align = 0); void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); void DrawTextShadow(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); - void RotateSprite(int atlas_entry, float x, float y, float angle, float scale, Color color); + void RotateSprite(ImageID atlas_image, float x, float y, float angle, float scale, Color color); + void SetFontScale(float xs, float ys) { fontscalex = xs; fontscaley = ys; diff --git a/ui/view.cpp b/ui/view.cpp index 5398e5f4c5..d5161c0c08 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -274,18 +274,24 @@ ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParam } void ClickableItem::Draw(UIContext &dc) { - Style style = dc.theme->itemStyle; + Style style = dc.theme->itemStyle; if (HasFocus()) { style = dc.theme->itemFocusedStyle; } if (down_) { style = dc.theme->itemDownStyle; - } + } dc.FillRect(style.background, bounds_); } void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); + if (atlasImage_ != -1) { + const AtlasImage &img = dc.Draw()->GetAtlas()->images[atlasImage_]; + w = img.w; + h = img.h; + } else { + dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); + } w += 24; h += 16; } @@ -297,8 +303,12 @@ void Choice::Draw(UIContext &dc) { if (!IsEnabled()) style = dc.theme->itemDisabledStyle; - int paddingX = 12; - dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + if (atlasImage_ != -1) { + dc.Draw()->DrawImage(atlasImage_, bounds_.centerX(), bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER); + } else { + int paddingX = 12; + dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + } if (selected_) { dc.Draw()->DrawImage(dc.theme->checkOn, bounds_.x2() - 40, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER); @@ -314,13 +324,19 @@ void InfoItem::Draw(UIContext &dc) { // dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor); } +ItemHeader::ItemHeader(const std::string &text, LayoutParams *layoutParams) + : Item(layoutParams), text_(text) { + layoutParams_->width = FILL_PARENT; + layoutParams_->height = 40; +} + void ItemHeader::Draw(UIContext &dc) { float scale = 1.0f; if (dc.theme->uiFontSmaller == dc.theme->uiFont) { scale = 0.7f; } dc.Draw()->SetFontScale(scale, scale); - dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.y, 0xFFFFFFFF, ALIGN_LEFT); + dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.centerY(), 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); dc.Draw()->SetFontScale(1.0f, 1.0f); dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), 0xFFFFFFFF); } @@ -376,8 +392,10 @@ void ImageView::GetContentDimensions(const UIContext &dc, float &w, float &h) co } void ImageView::Draw(UIContext &dc) { + const AtlasImage &img = dc.Draw()->GetAtlas()->images[atlasImage_]; // TODO: involve sizemode - dc.Draw()->DrawImage(atlasImage_, bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF); + float scale = bounds_.w / img.w; + dc.Draw()->DrawImage(atlasImage_, bounds_.x, bounds_.y, scale, 0xFFFFFFFF, ALIGN_TOPLEFT); } void TextureView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { diff --git a/ui/view.h b/ui/view.h index 08e01aaab4..a7e8f9c2e4 100644 --- a/ui/view.h +++ b/ui/view.h @@ -17,6 +17,7 @@ #include "base/mutex.h" #include "base/basictypes.h" #include "base/scoped_ptr.h" +#include "gfx/texture_atlas.h" #include "math/lin/matrix4x4.h" #include "math/math_util.h" #include "math/geom2d.h" @@ -233,14 +234,14 @@ private: struct Margins { Margins() : top(0), bottom(0), left(0), right(0) {} - explicit Margins(uint8_t all) : top(all), bottom(all), left(all), right(all) {} - Margins(uint8_t horiz, uint8_t vert) : top(vert), bottom(vert), left(horiz), right(horiz) {} - Margins(uint8_t l, uint8_t t, uint8_t r, uint8_t b) : top(t), bottom(b), left(l), right(r) {} + explicit Margins(int8_t all) : top(all), bottom(all), left(all), right(all) {} + Margins(int8_t horiz, int8_t vert) : top(vert), bottom(vert), left(horiz), right(horiz) {} + Margins(int8_t l, int8_t t, int8_t r, int8_t b) : top(t), bottom(b), left(l), right(r) {} - uint8_t top; - uint8_t bottom; - uint8_t left; - uint8_t right; + int8_t top; + int8_t bottom; + int8_t left; + int8_t right; }; enum LayoutParamsType { @@ -485,9 +486,12 @@ public: class Choice : public ClickableItem { public: Choice(const std::string &text, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(), selected_(false) {} + : ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), selected_(false) {} Choice(const std::string &text, const std::string &smallText, bool selected = false, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(smallText), selected_(selected) {} + : ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), selected_(selected) {} + + Choice(ImageID image, LayoutParams *layoutParams = 0) + : ClickableItem(layoutParams), atlasImage_(image), selected_(false) {} virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); @@ -495,6 +499,7 @@ public: protected: std::string text_; std::string smallText_; + ImageID atlasImage_; private: bool selected_; }; @@ -504,6 +509,8 @@ class StickyChoice : public Choice { public: StickyChoice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0) : Choice(text, smallText, false, layoutParams) {} + StickyChoice(ImageID buttonImage, LayoutParams *layoutParams = 0) + : Choice(buttonImage, layoutParams) {} virtual void Key(const KeyInput &key); virtual void Touch(const TouchInput &touch); @@ -528,11 +535,7 @@ private: class ItemHeader : public Item { public: - ItemHeader(const std::string &text, LayoutParams *layoutParams = 0) - : Item(layoutParams), text_(text) { - layoutParams_->width = FILL_PARENT; - layoutParams_->height = 26; - } + ItemHeader(const std::string &text, LayoutParams *layoutParams = 0); virtual void Draw(UIContext &dc); private: std::string text_; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 94aa679c30..a32a6c9ed8 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -803,6 +803,14 @@ void ChoiceStrip::AddChoice(const std::string &title) { c->Press(); } +void ChoiceStrip::AddChoice(ImageID buttonImage) { + StickyChoice *c = new StickyChoice(buttonImage, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + c->OnClick.Handle(this, &ChoiceStrip::OnChoiceClick); + Add(c); + if (selected_ == (int)views_.size() - 1) + c->Press(); +} + EventReturn ChoiceStrip::OnChoiceClick(EventParams &e) { // Unstick the other choices that weren't clicked. for (int i = 0; i < (int)views_.size(); i++) { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index f5469cd802..1ca23863ff 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -235,6 +235,7 @@ public: : LinearLayout(orientation, layoutParams), selected_(0), topTabs_(false) { SetSpacing(0.0f); } void AddChoice(const std::string &title); + void AddChoice(ImageID buttonImage); int GetSelection() const { return selected_; } void SetSelection(int sel); virtual void Key(const KeyInput &input); From 3e65b41753bb3fdb6413e46c93a277c3793aa4fa Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 11:35:54 +0200 Subject: [PATCH 0607/1445] Basic inertia scrolling --- input/gesture_detector.cpp | 37 +++++++++++++++++++++++++++++++++++-- input/gesture_detector.h | 5 +++++ ui/view.cpp | 4 ++-- ui/viewgroup.cpp | 19 ++++++++++++++++++- ui/viewgroup.h | 3 ++- 5 files changed, 62 insertions(+), 6 deletions(-) diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 585e077adb..2815555bbb 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -2,11 +2,17 @@ // TODO: // Zoom gesture a la http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-6-implementing-the-pinch-zoom-gesture/1847 +#include "base/logging.h" #include "base/timeutil.h" #include "input/gesture_detector.h" -GestureDetector::GestureDetector() : active_(0) { +const float estimatedInertiaDamping = 0.75f; + +GestureDetector::GestureDetector() + : active_(0), + estimatedInertiaX_(0.0f), + estimatedInertiaY_(0.0f) { } TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds) { @@ -21,11 +27,21 @@ TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds p.lastY = touch.y; p.distanceX = 0.0f; p.distanceY = 0.0f; + estimatedInertiaX_ = 0.0f; + estimatedInertiaY_ = 0.0f; } else if (touch.flags & TOUCH_UP) { p.down = false; } else { p.distanceX += fabsf(touch.x - p.lastX); p.distanceY += fabsf(touch.y - p.lastY); + + estimatedInertiaX_ += touch.x - p.lastX; + estimatedInertiaY_ += touch.y - p.lastY; + estimatedInertiaX_ *= estimatedInertiaDamping; + estimatedInertiaY_ *= estimatedInertiaDamping; + + ILOG("%f %f", estimatedInertiaX_, estimatedInertiaY_); + p.lastX = touch.x; p.lastY = touch.y; } @@ -47,13 +63,30 @@ TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds return touch; } +void GestureDetector::UpdateFrame() { + estimatedInertiaX_ *= estimatedInertiaDamping; + estimatedInertiaY_ *= estimatedInertiaDamping; +} + bool GestureDetector::IsGestureActive(Gesture gesture) const { return (active_ & gesture) != 0; } void GestureDetector::GetGestureInfo(Gesture gesture, float info[4]) { - if (gesture == GESTURE_DRAG_VERTICAL) { + if (!(active_ & gesture)) { + memset(info, 0, sizeof(info)); + return; + } + + switch (gesture) { + case GESTURE_DRAG_HORIZONTAL: + info[0] = pointers[0].lastX - pointers[0].downX; + info[1] = estimatedInertiaX_; + break; + case GESTURE_DRAG_VERTICAL: info[0] = pointers[0].lastY - pointers[0].downY; + info[1] = estimatedInertiaY_; + break; } /* diff --git a/input/gesture_detector.h b/input/gesture_detector.h index 4c8178fd41..bbc1ad7cd4 100644 --- a/input/gesture_detector.h +++ b/input/gesture_detector.h @@ -18,6 +18,7 @@ class GestureDetector { public: GestureDetector(); TouchInput Update(const TouchInput &touch, const Bounds &bounds); + void UpdateFrame(); bool IsGestureActive(Gesture gesture) const; void GetGestureInfo(Gesture gesture, float info[4]); @@ -45,4 +46,8 @@ private: Pointer pointers[MAX_PTRS]; uint32_t active_; + + // For inertia estimation + float estimatedInertiaX_; + float estimatedInertiaY_; }; diff --git a/ui/view.cpp b/ui/view.cpp index d5161c0c08..79112e09a5 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -187,11 +187,11 @@ void Clickable::Touch(const TouchInput &input) { // TODO: O/X confirm preference for xperia play? bool IsAcceptKeyCode(int keyCode) { - return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_Z || keyCode == NKCODE_BUTTON_A || keyCode == NKCODE_BUTTON_CROSS; + return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_Z || keyCode == NKCODE_BUTTON_A || keyCode == NKCODE_BUTTON_CROSS || keyCode == NKCODE_BUTTON_1; } bool IsEscapeKeyCode(int keyCode) { - return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B; + return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B || keyCode == NKCODE_BUTTON_2; } void Clickable::Key(const KeyInput &key) { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index a32a6c9ed8..85631cd787 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -533,11 +533,20 @@ void ScrollView::Key(const KeyInput &input) { ViewGroup::Key(input); } +const float friction = 0.92f; +const float stop_threshold = 0.1f; + void ScrollView::Touch(const TouchInput &input) { if ((input.flags & TOUCH_DOWN) && input.id == 0) { scrollStart_ = scrollPos_; + inertia_ = 0.0f; } - + if (input.flags & TOUCH_UP) { + float info[4]; + gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info); + inertia_ = info[1]; + } + TouchInput input2; if (CanScroll()) { input2 = gesture_.Update(input, bounds_); @@ -648,13 +657,21 @@ bool ScrollView::CanScroll() const { void ScrollView::Update(const InputState &input_state) { ViewGroup::Update(input_state); + gesture_.UpdateFrame(); if (scrollToTarget_) { + inertia_ = 0.0f; if (fabsf(scrollTarget_ - scrollPos_) < 0.5f) { scrollPos_ = scrollTarget_; scrollToTarget_ = false; } else { scrollPos_ += (scrollTarget_ - scrollPos_) * 0.3f; } + } else if (inertia_ != 0.0f && !gesture_.IsGestureActive(GESTURE_DRAG_VERTICAL)) { + scrollPos_ -= inertia_; + inertia_ *= friction; + if (fabsf(inertia_) < stop_threshold) + inertia_ = 0.0f; + ClampScrollPos(scrollPos_); } } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 1ca23863ff..2caca0a935 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -188,6 +188,7 @@ public: scrollMax_(0), scrollTarget_(0), scrollToTarget_(false), + inertia_(0), lastViewSize_(0.0f), scrollToTopOnSizeChange_(true) {} @@ -219,7 +220,7 @@ private: float scrollMax_; float scrollTarget_; bool scrollToTarget_; - + float inertia_; float lastViewSize_; bool scrollToTopOnSizeChange_; }; From ecd8e52e0aadbf7680ad83671f85d6d351a784cf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 12:27:42 +0200 Subject: [PATCH 0608/1445] Make tabs look more tab-like. Custom size spacers. --- ui/view.h | 8 ++++++-- ui/viewgroup.cpp | 18 ++++++++++++++++++ ui/viewgroup.h | 11 +++++++++-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/ui/view.h b/ui/view.h index a7e8f9c2e4..dde16021b8 100644 --- a/ui/view.h +++ b/ui/view.h @@ -579,11 +579,15 @@ private: class Spacer : public InertView { public: Spacer(LayoutParams *layoutParams = 0) - : InertView(layoutParams) {} + : InertView(layoutParams), size_(0.0f) {} + Spacer(float size, LayoutParams *layoutParams = 0) + : InertView(layoutParams), size_(size) {} virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { - w = 0.0f; h = 0.0f; + w = size_; h = size_; } virtual void Draw(UIContext &dc) {} +private: + float size_; }; class TextView : public InertView { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 85631cd787..b3519ea33c 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -91,6 +91,10 @@ void ViewGroup::Draw(UIContext &dc) { // dc.Draw()->DrawImage4Grid(dc.theme->dropShadow, ) } + if (clip_) { + dc.PushScissor(bounds_); + } + dc.FillRect(bg_, bounds_); for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. @@ -100,6 +104,9 @@ void ViewGroup::Draw(UIContext &dc) { (*iter)->Draw(dc); } } + if (clip_) { + dc.PopScissor(); + } } void ViewGroup::Update(const InputState &input_state) { @@ -870,6 +877,17 @@ void ChoiceStrip::Key(const KeyInput &input) { ViewGroup::Key(input); } +void ChoiceStrip::Draw(UIContext &dc) { + ViewGroup::Draw(dc); + if (topTabs_) { + if (orientation_ == ORIENT_HORIZONTAL) + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2() - 4, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.background.color ); + else if (orientation_ == ORIENT_VERTICAL) + dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x2() - 4, bounds_.y, bounds_.x2(), bounds_.y2(), dc.theme->itemDownStyle.background.color ); + } +} + + ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a) { linLayout_ = new LinearLayout(ORIENT_VERTICAL); diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 2caca0a935..86f2667936 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -17,7 +17,7 @@ struct NeighborResult { class ViewGroup : public View { public: - ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams), hasDropShadow_(false) {} + ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams), hasDropShadow_(false), clip_(false) {} virtual ~ViewGroup(); // Pass through external events to children. @@ -59,11 +59,15 @@ public: void Lock() { modifyLock_.lock(); } void Unlock() { modifyLock_.unlock(); } + + void SetClip(bool clip) { clip_ = clip; } + protected: recursive_mutex modifyLock_; // Hold this when changing the subviews. std::vector views_; Drawable bg_; bool hasDropShadow_; + bool clip_; }; // A frame layout contains a single child view (normally). @@ -141,8 +145,9 @@ public: void SetSpacing(float spacing) { spacing_ = spacing; } -private: +protected: Orientation orientation_; +private: Margins defaultMargins_; float spacing_; }; @@ -241,6 +246,7 @@ public: void SetSelection(int sel); virtual void Key(const KeyInput &input); void SetTopTabs(bool tabs) { topTabs_ = tabs; } + void Draw(UIContext &dc); Event OnChoice; private: @@ -256,6 +262,7 @@ public: TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0) : LinearLayout(Opposite(orientation), layoutParams), orientation_(orientation), stripSize_(stripSize), currentTab_(0) { + SetSpacing(0.0f); tabStrip_ = new ChoiceStrip(orientation, new LinearLayoutParams(stripSize, WRAP_CONTENT)); tabStrip_->SetTopTabs(true); Add(tabStrip_); From 6fe1102ab4f8adf0ca695782422ce01e67795c51 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 20 Aug 2013 20:30:03 +1000 Subject: [PATCH 0609/1445] Fix DPI issue on Qt + Blackberry. --- base/BlackberryDisplay.cpp | 6 +++--- base/BlackberryMain.cpp | 32 ++++++++++++++--------------- base/BlackberryMain.h | 3 +-- base/QtMain.cpp | 6 +++--- base/QtMain.h | 41 +++++++++++++++++++------------------- 5 files changed, 43 insertions(+), 45 deletions(-) diff --git a/base/BlackberryDisplay.cpp b/base/BlackberryDisplay.cpp index 7d02f5d2bc..89001b200f 100644 --- a/base/BlackberryDisplay.cpp +++ b/base/BlackberryDisplay.cpp @@ -76,7 +76,7 @@ void BlackberryMain::startDisplays() { realiseDisplay(i); } screen_get_display_property_iv(screen_dpy[0], SCREEN_PROPERTY_DPI, &dpi); // Only internal display has DPI - dpi_scale = ((pixel_xres == pixel_yres) ? 300.0f : 213.6f) / dpi; + g_dpi_scale = ((pixel_xres == pixel_yres) ? 300.0f : 213.6f) / dpi; switchDisplay(screen_ui); } @@ -121,8 +121,8 @@ void BlackberryMain::switchDisplay(int idx) { if (idx != screen_curr) { pixel_xres = displays[idx].width; pixel_yres = displays[idx].height; - dp_xres = (int)(pixel_xres * dpi_scale); - dp_yres = (int)(pixel_yres * dpi_scale); + dp_xres = (int)(pixel_xres * g_dpi_scale); + dp_yres = (int)(pixel_yres * g_dpi_scale); screen_curr = idx; eglMakeCurrent(egl_disp[idx], egl_surf[idx], egl_surf[idx], egl_cont); } diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 2caa26f8ef..6263fa3498 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -73,21 +73,21 @@ void BlackberryMain::handleInput(screen_event_t screen_event) case SCREEN_EVENT_MTOUCH_TOUCH: case SCREEN_EVENT_MTOUCH_RELEASE: // Up, down input_state.pointer_down[pointerId] = (val == SCREEN_EVENT_MTOUCH_TOUCH); - input_state.pointer_x[pointerId] = pair[0] * dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * dpi_scale; + input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale; - input.x = pair[0] * dpi_scale; - input.y = pair[1] * dpi_scale; + input.x = pair[0] * g_dpi_scale; + input.y = pair[1] * g_dpi_scale; input.flags = (val == SCREEN_EVENT_MTOUCH_TOUCH) ? TOUCH_DOWN : TOUCH_UP; input.id = pointerId; NativeTouch(input); break; case SCREEN_EVENT_MTOUCH_MOVE: - input_state.pointer_x[pointerId] = pair[0] * dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * dpi_scale; + input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale; - input.x = pair[0] * dpi_scale; - input.y = pair[1] * dpi_scale; + input.x = pair[0] * g_dpi_scale; + input.y = pair[1] * g_dpi_scale; input.flags = TOUCH_MOVE; input.id = pointerId; NativeTouch(input); @@ -97,22 +97,22 @@ void BlackberryMain::handleInput(screen_event_t screen_event) screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down - input_state.pointer_x[pointerId] = pair[0] * dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * dpi_scale; + input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale; input_state.pointer_down[pointerId] = true; - input.x = pair[0] * dpi_scale; - input.y = pair[1] * dpi_scale; + input.x = pair[0] * g_dpi_scale; + input.y = pair[1] * g_dpi_scale; input.flags = TOUCH_DOWN; input.id = pointerId; NativeTouch(input); } else if (input_state.pointer_down[pointerId]) { // Up - input_state.pointer_x[pointerId] = pair[0] * dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * dpi_scale; + input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale; + input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale; input_state.pointer_down[pointerId] = false; - input.x = pair[0] * dpi_scale; - input.y = pair[1] * dpi_scale; + input.x = pair[0] * g_dpi_scale; + input.y = pair[1] * g_dpi_scale; input.flags = TOUCH_UP; input.id = pointerId; NativeTouch(input); diff --git a/base/BlackberryMain.h b/base/BlackberryMain.h index 01b4750699..78eb164c8f 100644 --- a/base/BlackberryMain.h +++ b/base/BlackberryMain.h @@ -31,7 +31,7 @@ #include "base/NativeApp.h" #include "input/input_state.h" #include "net/resolve.h" -#include "display.h" +#include "base/display.h" #include "BlackberryAudio.h" @@ -76,7 +76,6 @@ private: BlackberryAudio* audio; dispdata_t *displays; int dpi; - float dpi_scale; int ndisplays; int screen_ui, screen_emu; bool emulating; diff --git a/base/QtMain.cpp b/base/QtMain.cpp index ee08a84bb6..b4175a80dc 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -78,8 +78,8 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) pixel_xres = res.width(); pixel_yres = res.height(); - float dpi_scale = CalculateDPIScale(); - dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); + g_dpi_scale = CalculateDPIScale(); + dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); #ifdef __SYMBIAN32__ char* savegame_dir = "E:/PPSSPP/"; @@ -100,7 +100,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); #if !defined(Q_WS_X11) || defined(ARM) - MainUI w(dpi_scale); + MainUI w; w.resize(pixel_xres, pixel_yres); w.showFullScreen(); #endif diff --git a/base/QtMain.h b/base/QtMain.h index 894de3caf6..74ea9da4df 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -52,8 +52,8 @@ class MainUI : public QGLWidget { Q_OBJECT public: - explicit MainUI(float scale, QWidget *parent = 0): - QGLWidget(parent), dpi_scale(scale) + explicit MainUI(QWidget *parent = 0): + QGLWidget(parent) { setAttribute(Qt::WA_AcceptTouchEvents); setAttribute(Qt::WA_LockLandscapeOrientation); @@ -74,8 +74,8 @@ protected: { pixel_xres = e->size().width(); pixel_yres = e->size().height(); - dp_xres = pixel_xres * dpi_scale; - dp_yres = pixel_yres * dpi_scale; + dp_xres = pixel_xres * g_dpi_scale; + dp_yres = pixel_yres * g_dpi_scale; } bool event(QEvent *e) @@ -95,21 +95,21 @@ protected: case Qt::TouchPointPressed: case Qt::TouchPointReleased: input_state.pointer_down[touchPoint.id()] = (touchPoint.state() == Qt::TouchPointPressed); - input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * dpi_scale; - input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * dpi_scale; + input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * g_dpi_scale; + input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * g_dpi_scale; - input.x = touchPoint.pos().x() * dpi_scale; - input.y = touchPoint.pos().y() * dpi_scale; + input.x = touchPoint.pos().x() * g_dpi_scale; + input.y = touchPoint.pos().y() * g_dpi_scale; input.flags = (touchPoint.state() == Qt::TouchPointPressed) ? TOUCH_DOWN : TOUCH_UP; input.id = touchPoint.id(); NativeTouch(input); break; case Qt::TouchPointMoved: - input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * dpi_scale; - input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * dpi_scale; + input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * g_dpi_scale; + input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * g_dpi_scale; - input.x = touchPoint.pos().x() * dpi_scale; - input.y = touchPoint.pos().y() * dpi_scale; + input.x = touchPoint.pos().x() * g_dpi_scale; + input.y = touchPoint.pos().y() * g_dpi_scale; input.flags = TOUCH_MOVE; input.id = touchPoint.id(); NativeTouch(input); @@ -122,21 +122,21 @@ protected: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: input_state.pointer_down[0] = (e->type() == QEvent::MouseButtonPress); - input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * dpi_scale; - input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * dpi_scale; + input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * g_dpi_scale; + input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * g_dpi_scale; - input.x = ((QMouseEvent*)e)->pos().x() * dpi_scale; - input.y = ((QMouseEvent*)e)->pos().y() * dpi_scale; + input.x = ((QMouseEvent*)e)->pos().x() * g_dpi_scale; + input.y = ((QMouseEvent*)e)->pos().y() * g_dpi_scale; input.flags = (e->type() == QEvent::MouseButtonPress) ? TOUCH_DOWN : TOUCH_UP; input.id = 0; NativeTouch(input); break; case QEvent::MouseMove: - input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * dpi_scale; - input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * dpi_scale; + input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * g_dpi_scale; + input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * g_dpi_scale; - input.x = ((QMouseEvent*)e)->pos().x() * dpi_scale; - input.y = ((QMouseEvent*)e)->pos().y() * dpi_scale; + input.x = ((QMouseEvent*)e)->pos().x() * g_dpi_scale; + input.y = ((QMouseEvent*)e)->pos().y() * g_dpi_scale; input.flags = TOUCH_MOVE; input.id = 0; NativeTouch(input); @@ -192,7 +192,6 @@ private: #ifdef USING_GLES2 QAccelerometer* acc; #endif - float dpi_scale; }; // Audio From 40193a7d125e78e52dbc01d1f4eb7d6e631e82eb Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 12:48:48 +0200 Subject: [PATCH 0610/1445] Show numbers on sliders --- ui/view.cpp | 28 +++++++++++++++++++--------- ui/view.h | 11 ++++++++--- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 79112e09a5..3c00098ed6 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -498,7 +498,7 @@ void Slider::Key(const KeyInput &input) { void Slider::Touch(const TouchInput &input) { if (dragging_ || bounds_.Contains(input.x, input.y)) { - float relativeX = (input.x - bounds_.x) / bounds_.w; + float relativeX = (input.x - (bounds_.x + paddingLeft_)) / (bounds_.w - paddingLeft_ - paddingRight_); *value_ = floorf(relativeX * (maxValue_ - minValue_) + minValue_ + 0.5f); Clamp(); } @@ -511,10 +511,16 @@ void Slider::Clamp() { void Slider::Draw(UIContext &dc) { bool focus = HasFocus(); - float knobX = ((float)(*value_) - minValue_) / (maxValue_ - minValue_) * bounds_.w + bounds_.x; - dc.FillRect(Drawable(focus ? dc.theme->popupTitle.fgColor : 0xFFFFFFFF), Bounds(bounds_.x, bounds_.centerY() - 2, knobX - bounds_.x, 4)); - dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, bounds_.x + bounds_.w - knobX, 4)); + float knobX = ((float)(*value_) - minValue_) / (maxValue_ - minValue_) * (bounds_.w - paddingLeft_ - paddingRight_) + (bounds_.x + paddingLeft_); + dc.FillRect(Drawable(focus ? dc.theme->popupTitle.fgColor : 0xFFFFFFFF), Bounds(bounds_.x + paddingLeft_, bounds_.centerY() - 2, knobX - (bounds_.x + paddingLeft_), 4)); + dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, (bounds_.x + bounds_.w - paddingRight_ - knobX), 4)); dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + char temp[64]; + if (showPercent_) + sprintf(temp, "%i%%", *value_); + else + sprintf(temp, "%i", *value_); + dc.Draw()->DrawText(dc.theme->uiFont, temp, bounds_.x2() - 22, bounds_.centerY(), 0xFFFFFFFF, ALIGN_CENTER); } void Slider::GetContentDimensions(const UIContext &dc, float &w, float &h) const { @@ -543,8 +549,8 @@ void SliderFloat::Key(const KeyInput &input) { void SliderFloat::Touch(const TouchInput &input) { if (dragging_ || bounds_.Contains(input.x, input.y)) { - float relativeX = (input.x - bounds_.x) / bounds_.w; - *value_ = relativeX * (maxValue_ - minValue_) + minValue_; + float relativeX = (input.x - (bounds_.x + paddingLeft_)) / (bounds_.w - paddingLeft_ - paddingRight_); + *value_ = (relativeX * (maxValue_ - minValue_) + minValue_); Clamp(); } } @@ -555,10 +561,14 @@ void SliderFloat::Clamp() { } void SliderFloat::Draw(UIContext &dc) { - float knobX = ((float)(*value_) - minValue_) / (maxValue_ - minValue_) * bounds_.w + bounds_.x; - dc.FillRect(Drawable(0xFFFFFFFF), Bounds(bounds_.x, bounds_.centerY() - 2, knobX - bounds_.x, 4)); - dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, bounds_.x + bounds_.w - knobX, 4)); + bool focus = HasFocus(); + float knobX = (*value_ - minValue_) / (maxValue_ - minValue_) * (bounds_.w - paddingLeft_ - paddingRight_) + (bounds_.x + paddingLeft_); + dc.FillRect(Drawable(focus ? dc.theme->popupTitle.fgColor : 0xFFFFFFFF), Bounds(bounds_.x + paddingLeft_, bounds_.centerY() - 2, knobX - (bounds_.x + paddingLeft_), 4)); + dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, (bounds_.x + bounds_.w - paddingRight_ - knobX), 4)); dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + char temp[64]; + sprintf(temp, "%0.2f", *value_); + dc.Draw()->DrawText(dc.theme->uiFont, temp, bounds_.x2() - 22, bounds_.centerY(), 0xFFFFFFFF, ALIGN_CENTER); } void SliderFloat::GetContentDimensions(const UIContext &dc, float &w, float &h) const { diff --git a/ui/view.h b/ui/view.h index dde16021b8..2c4d45310a 100644 --- a/ui/view.h +++ b/ui/view.h @@ -413,23 +413,26 @@ private: class Slider : public Clickable { public: Slider(int *value, int minValue, int maxValue, LayoutParams *layoutParams = 0) - : Clickable(layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue) {} + : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(50) {} virtual void Draw(UIContext &dc); virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; - + void SetShowPercent(bool s) { showPercent_ = s; } private: void Clamp(); int *value_; + bool showPercent_; int minValue_; int maxValue_; + float paddingLeft_; + float paddingRight_; }; class SliderFloat : public Clickable { public: SliderFloat(float *value, float minValue, float maxValue, LayoutParams *layoutParams = 0) - : Clickable(layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue) {} + : Clickable(layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(50) {} virtual void Draw(UIContext &dc); virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); @@ -440,6 +443,8 @@ private: float *value_; float minValue_; float maxValue_; + float paddingLeft_; + float paddingRight_; }; // Basic button that modifies a bitfield based on the pressed status. Supports multitouch. From 8f0d82ffb72efb7fe138e7d1c83635691ba3f4e7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 13:03:42 +0200 Subject: [PATCH 0611/1445] Click outside popups to dismiss them. Fix focus display of active tabs. --- ui/ui_screen.cpp | 28 ++++++++++++++++++++-------- ui/ui_screen.h | 2 ++ ui/view.cpp | 14 ++++++++++++-- ui/view.h | 6 ++++++ 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index c739305bed..090f250730 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -99,24 +99,36 @@ UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { } PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2) - : title_(title), button1_(button1), button2_(button2) {} + : title_(title), button1_(button1), button2_(button2), box_(0) {} + +void PopupScreen::touch(const TouchInput &touch) { + if (!box_ || (touch.flags & TOUCH_DOWN) == 0 || touch.id != 0) { + UIDialogScreen::touch(touch); + return; + } + + if (!box_->GetBounds().Contains(touch.x, touch.y)) + screenManager()->finishDialog(this, DR_CANCEL); + + UIDialogScreen::touch(touch); +} void PopupScreen::CreateViews() { using namespace UI; root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); - LinearLayout *box = new LinearLayout(ORIENT_VERTICAL, + box_ = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(550, FillVertical() ? dp_yres - 30 : WRAP_CONTENT, dp_xres / 2, dp_yres / 2, NONE, NONE, true)); - root_->Add(box); - box->SetBG(UI::Drawable(0xFF303030)); - box->SetHasDropShadow(true); + root_->Add(box_); + box_->SetBG(UI::Drawable(0xFF303030)); + box_->SetHasDropShadow(true); View *title = new PopupHeader(title_); - box->Add(title); + box_->Add(title); - CreatePopupContents(box); + CreatePopupContents(box_); if (ShowButtons()) { // And the two buttons at the bottom. @@ -135,7 +147,7 @@ void PopupScreen::CreateViews() { buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); #endif - box->Add(buttonRow); + box_->Add(buttonRow); } } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 83456dad4d..e4eee000a8 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -45,6 +45,7 @@ public: virtual void CreatePopupContents(UI::ViewGroup *parent) = 0; virtual void CreateViews(); virtual bool isTransparent() { return true; } + virtual void touch(const TouchInput &touch); protected: virtual bool FillVertical() { return false; } @@ -55,6 +56,7 @@ private: UI::EventReturn OnOK(UI::EventParams &e); UI::EventReturn OnCancel(UI::EventParams &e); + UI::ViewGroup *box_; std::string title_; std::string button1_; std::string button2_; diff --git a/ui/view.cpp b/ui/view.cpp index 3c00098ed6..210c5a364c 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -297,7 +297,18 @@ void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const } void Choice::Draw(UIContext &dc) { - ClickableItem::Draw(dc); + if (!IsSticky()) { + ClickableItem::Draw(dc); + } else { + Style style = dc.theme->itemStyle; + if (down_) { + style = dc.theme->itemDownStyle; + } + if (HasFocus()) { + style = dc.theme->itemFocusedStyle; + } + dc.FillRect(style.background, bounds_); + } Style style = dc.theme->itemStyle; if (!IsEnabled()) @@ -313,7 +324,6 @@ void Choice::Draw(UIContext &dc) { if (selected_) { dc.Draw()->DrawImage(dc.theme->checkOn, bounds_.x2() - 40, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER); } - // dc.draw->DrawText(dc.theme->uiFontSmaller, text_.c_str(), paddingX, paddingY, 0xFFFFFFFF, ALIGN_TOPLEFT); } void InfoItem::Draw(UIContext &dc) { diff --git a/ui/view.h b/ui/view.h index 2c4d45310a..1ad958ccc3 100644 --- a/ui/view.h +++ b/ui/view.h @@ -502,6 +502,9 @@ public: virtual void Draw(UIContext &dc); protected: + // hackery + virtual bool IsSticky() const { return false; } + std::string text_; std::string smallText_; ImageID atlasImage_; @@ -524,6 +527,9 @@ public: void Press() { down_ = true; dragging_ = false; } void Release() { down_ = false; dragging_ = false; } bool IsDown() { return down_; } +protected: + // hackery + virtual bool IsSticky() const { return true; } }; class InfoItem : public Item { From 2a02b538942602c10cc84f55bbaae3cabaab9551 Mon Sep 17 00:00:00 2001 From: The Dax Date: Tue, 20 Aug 2013 08:37:39 -0400 Subject: [PATCH 0612/1445] Native: Remove hard-coded accept and escape keys. --- input/input_state.cpp | 17 +++++++++++++++++ input/input_state.h | 9 +++++++++ ui/view.cpp | 5 ++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/input/input_state.cpp b/input/input_state.cpp index 2a75fbc2bb..bb8f1bacfc 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -1,5 +1,6 @@ #include "input/input_state.h" #include "input/keycodes.h" +#include const char *GetDeviceName(int deviceId) { switch (deviceId) { @@ -41,6 +42,22 @@ int MapPadButtonFixed(int keycode) { } } +std::vector confirmKeys; +std::vector cancelKeys; + +void SetConfirmCancelKeys(std::vector confirm, std::vector cancel) { + confirmKeys = confirm; + cancelKeys = cancel; +} + +void AddConfirmKey(keycode_t confirmKey) { + confirmKeys.push_back(confirmKey); +} + +void AddCancelKey(keycode_t cancelKey) { + cancelKeys.push_back(cancelKey); +} + uint32_t ButtonTracker::Update() { pad_buttons_ |= pad_buttons_async_set; pad_buttons_ &= ~pad_buttons_async_clear; diff --git a/input/input_state.h b/input/input_state.h index fd414b3646..95bb5855f3 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -11,7 +11,9 @@ #include "math/lin/vec3.h" #include "base/mutex.h" #include "base/basictypes.h" +#include "input/keycodes.h" #include +#include // Default device IDs @@ -112,6 +114,13 @@ private: void UpdateInputState(InputState *input, bool merge = false); void EndInputState(InputState *input); +// Is there a nicer place for this stuff? It's here to avoid dozens of linking errors in UnitTest.. +extern std::vector confirmKeys; +extern std::vector cancelKeys; +void SetConfirmCancelKeys(std::vector confirm, std::vector cancel); +void AddConfirmKey(keycode_t confirmKey); +void AddCancelKey(keycode_t confirmKey); + enum { TOUCH_MOVE = 1, TOUCH_DOWN = 2, diff --git a/ui/view.cpp b/ui/view.cpp index 210c5a364c..9f593b8e89 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -27,7 +27,6 @@ struct DispatchQueueItem { std::queue g_dispatchQueue; - void EventTriggered(Event *e, EventParams params) { lock_guard guard(mutex_); @@ -187,11 +186,11 @@ void Clickable::Touch(const TouchInput &input) { // TODO: O/X confirm preference for xperia play? bool IsAcceptKeyCode(int keyCode) { - return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_Z || keyCode == NKCODE_BUTTON_A || keyCode == NKCODE_BUTTON_CROSS || keyCode == NKCODE_BUTTON_1; + return std::find(confirmKeys.begin(), confirmKeys.end(), (keycode_t)keyCode) != confirmKeys.end(); } bool IsEscapeKeyCode(int keyCode) { - return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B || keyCode == NKCODE_BUTTON_2; + return std::find(cancelKeys.begin(), cancelKeys.end(), (keycode_t)keyCode) != cancelKeys.end(); } void Clickable::Key(const KeyInput &key) { From d45ea84599f9d1a9d1f804d3c982abf569807b8a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 15:04:42 +0200 Subject: [PATCH 0613/1445] Revert "Merge pull request #110 from thedax/master" This reverts commit d2bdffcc54baa6ce1c42534cc4be952c2b76422f, reversing changes made to 8f0d82ffb72efb7fe138e7d1c83635691ba3f4e7. --- input/input_state.cpp | 17 ----------------- input/input_state.h | 9 --------- ui/view.cpp | 5 +++-- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/input/input_state.cpp b/input/input_state.cpp index bb8f1bacfc..2a75fbc2bb 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -1,6 +1,5 @@ #include "input/input_state.h" #include "input/keycodes.h" -#include const char *GetDeviceName(int deviceId) { switch (deviceId) { @@ -42,22 +41,6 @@ int MapPadButtonFixed(int keycode) { } } -std::vector confirmKeys; -std::vector cancelKeys; - -void SetConfirmCancelKeys(std::vector confirm, std::vector cancel) { - confirmKeys = confirm; - cancelKeys = cancel; -} - -void AddConfirmKey(keycode_t confirmKey) { - confirmKeys.push_back(confirmKey); -} - -void AddCancelKey(keycode_t cancelKey) { - cancelKeys.push_back(cancelKey); -} - uint32_t ButtonTracker::Update() { pad_buttons_ |= pad_buttons_async_set; pad_buttons_ &= ~pad_buttons_async_clear; diff --git a/input/input_state.h b/input/input_state.h index 95bb5855f3..fd414b3646 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -11,9 +11,7 @@ #include "math/lin/vec3.h" #include "base/mutex.h" #include "base/basictypes.h" -#include "input/keycodes.h" #include -#include // Default device IDs @@ -114,13 +112,6 @@ private: void UpdateInputState(InputState *input, bool merge = false); void EndInputState(InputState *input); -// Is there a nicer place for this stuff? It's here to avoid dozens of linking errors in UnitTest.. -extern std::vector confirmKeys; -extern std::vector cancelKeys; -void SetConfirmCancelKeys(std::vector confirm, std::vector cancel); -void AddConfirmKey(keycode_t confirmKey); -void AddCancelKey(keycode_t confirmKey); - enum { TOUCH_MOVE = 1, TOUCH_DOWN = 2, diff --git a/ui/view.cpp b/ui/view.cpp index 9f593b8e89..210c5a364c 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -27,6 +27,7 @@ struct DispatchQueueItem { std::queue g_dispatchQueue; + void EventTriggered(Event *e, EventParams params) { lock_guard guard(mutex_); @@ -186,11 +187,11 @@ void Clickable::Touch(const TouchInput &input) { // TODO: O/X confirm preference for xperia play? bool IsAcceptKeyCode(int keyCode) { - return std::find(confirmKeys.begin(), confirmKeys.end(), (keycode_t)keyCode) != confirmKeys.end(); + return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_Z || keyCode == NKCODE_BUTTON_A || keyCode == NKCODE_BUTTON_CROSS || keyCode == NKCODE_BUTTON_1; } bool IsEscapeKeyCode(int keyCode) { - return std::find(cancelKeys.begin(), cancelKeys.end(), (keycode_t)keyCode) != cancelKeys.end(); + return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B || keyCode == NKCODE_BUTTON_2; } void Clickable::Key(const KeyInput &key) { From 3ea9d45299a8066f451878e3ace127c947cc7a2f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 15:25:03 +0200 Subject: [PATCH 0614/1445] Focus on the slider when the popup opens --- ui/ui_screen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 090f250730..2f5f0ea1ea 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -188,12 +188,14 @@ void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; sliderValue_ = *value_; slider_ = parent->Add(new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5)))); + UI::SetFocusedView(slider_); } void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; sliderValue_ = *value_; slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_)); + UI::SetFocusedView(slider_); } void SliderPopupScreen::OnCompleted(DialogResult result) { From ae0847cecbac76c7c7901ab76824a91c29b7329e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 15:30:47 +0200 Subject: [PATCH 0615/1445] Stop inertia-scrolling when switching away from a tab. --- ui/viewgroup.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index b3519ea33c..4d7dba3f2d 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -663,6 +663,9 @@ bool ScrollView::CanScroll() const { } void ScrollView::Update(const InputState &input_state) { + if (visibility_ != V_VISIBLE) { + inertia_ = 0.0f; + } ViewGroup::Update(input_state); gesture_.UpdateFrame(); if (scrollToTarget_) { From 7b6245946372dd4ba140e287a53974d417676309 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 16:31:47 +0200 Subject: [PATCH 0616/1445] Fix some gesture detection for scrolling --- input/gesture_detector.cpp | 11 +++++++---- input/gesture_detector.h | 2 +- ui/viewgroup.cpp | 13 +++++++------ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 2815555bbb..5f06f0eb16 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -13,6 +13,7 @@ GestureDetector::GestureDetector() : active_(0), estimatedInertiaX_(0.0f), estimatedInertiaY_(0.0f) { + memset(pointers, 0, sizeof(pointers)); } TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds) { @@ -72,21 +73,23 @@ bool GestureDetector::IsGestureActive(Gesture gesture) const { return (active_ & gesture) != 0; } -void GestureDetector::GetGestureInfo(Gesture gesture, float info[4]) { +bool GestureDetector::GetGestureInfo(Gesture gesture, float info[4]) const { if (!(active_ & gesture)) { memset(info, 0, sizeof(info)); - return; + return false; } switch (gesture) { case GESTURE_DRAG_HORIZONTAL: info[0] = pointers[0].lastX - pointers[0].downX; info[1] = estimatedInertiaX_; - break; + return true; case GESTURE_DRAG_VERTICAL: info[0] = pointers[0].lastY - pointers[0].downY; info[1] = estimatedInertiaY_; - break; + return true; + default: + return false; } /* diff --git a/input/gesture_detector.h b/input/gesture_detector.h index bbc1ad7cd4..f7fa15f171 100644 --- a/input/gesture_detector.h +++ b/input/gesture_detector.h @@ -20,7 +20,7 @@ public: TouchInput Update(const TouchInput &touch, const Bounds &bounds); void UpdateFrame(); bool IsGestureActive(Gesture gesture) const; - void GetGestureInfo(Gesture gesture, float info[4]); + bool GetGestureInfo(Gesture gesture, float info[4]) const; private: Bounds bounds_; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 4d7dba3f2d..4105408a8c 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -527,6 +527,9 @@ void ScrollView::Layout() { } void ScrollView::Key(const KeyInput &input) { + if (visibility_ != V_VISIBLE) + return ViewGroup::Key(input); + if (input.flags & KEY_DOWN) { switch (input.keyCode) { case NKCODE_EXT_MOUSEWHEEL_UP: @@ -550,17 +553,15 @@ void ScrollView::Touch(const TouchInput &input) { } if (input.flags & TOUCH_UP) { float info[4]; - gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info); - inertia_ = info[1]; + if (gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info)) + inertia_ = info[1]; } TouchInput input2; if (CanScroll()) { input2 = gesture_.Update(input, bounds_); - if (gesture_.IsGestureActive(GESTURE_DRAG_VERTICAL)) { - float info[4]; - gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info); - + float info[4]; + if (gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info)) { float pos = scrollStart_ - info[0]; ClampScrollPos(pos); scrollPos_ = pos; From 0761e3cb21bb3e409aad8d9e8f46e86ed73af4f4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 18:03:25 +0200 Subject: [PATCH 0617/1445] Enable dithering in the UI (helpful for the new soft gradient) --- ui/ui_context.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index b66e917cf1..fdbc9ee297 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -11,6 +11,7 @@ void UIContext::Begin() { glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glstate.cullFace.disable(); glstate.depthTest.disable(); + glstate.dither.enable(); #if !defined(USING_GLES2) glstate.colorLogicOp.disable(); #endif @@ -27,6 +28,7 @@ void UIContext::BeginNoTex() { glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glstate.cullFace.disable(); glstate.depthTest.disable(); + glstate.dither.enable(); #if !defined(USING_GLES2) glstate.colorLogicOp.disable(); #endif From 2ef42213955f54e61b8599fceed7eacf0d698a31 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 18:58:00 +0200 Subject: [PATCH 0618/1445] PgUp/PgDn/Home/End in scrollviews --- ui/viewgroup.cpp | 13 +++++++++++++ ui/viewgroup.h | 2 -- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 4105408a8c..9a5bcb3ec2 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -538,6 +538,19 @@ void ScrollView::Key(const KeyInput &input) { case NKCODE_EXT_MOUSEWHEEL_DOWN: ScrollRelative(250); break; + case NKCODE_PAGE_DOWN: + ScrollRelative(bounds_.h - 50); + break; + case NKCODE_PAGE_UP: + ScrollRelative(-bounds_.h + 50); + break; + case NKCODE_MOVE_HOME: + ScrollTo(0); + break; + case NKCODE_MOVE_END: + if (views_.size()) + ScrollTo(views_[0]->GetBounds().h); + break; } } ViewGroup::Key(input); diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 86f2667936..60570a5b68 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -190,7 +190,6 @@ public: orientation_(orientation), scrollPos_(0), scrollStart_(0), - scrollMax_(0), scrollTarget_(0), scrollToTarget_(false), inertia_(0), @@ -222,7 +221,6 @@ private: Orientation orientation_; float scrollPos_; float scrollStart_; - float scrollMax_; float scrollTarget_; bool scrollToTarget_; float inertia_; From 91efd71ff9bd3b8ce879966c3f423241f4d94fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 20 Aug 2013 19:19:39 +0200 Subject: [PATCH 0619/1445] Fix bug found by clang warning --- input/gesture_detector.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 5f06f0eb16..478f40ec05 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -11,7 +11,7 @@ const float estimatedInertiaDamping = 0.75f; GestureDetector::GestureDetector() : active_(0), - estimatedInertiaX_(0.0f), + estimatedInertiaX_(0.0f), estimatedInertiaY_(0.0f) { memset(pointers, 0, sizeof(pointers)); } @@ -75,7 +75,7 @@ bool GestureDetector::IsGestureActive(Gesture gesture) const { bool GestureDetector::GetGestureInfo(Gesture gesture, float info[4]) const { if (!(active_ & gesture)) { - memset(info, 0, sizeof(info)); + memset(info, 0, sizeof(float) * 4); return false; } From 4da02355ac5a1606ba1bf31661dee44445dad80d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 20:19:07 +0200 Subject: [PATCH 0620/1445] Forgot to add margin to float slider --- ui/ui_screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 2f5f0ea1ea..5f677dca3b 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -194,7 +194,7 @@ void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; sliderValue_ = *value_; - slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_)); + slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5)))); UI::SetFocusedView(slider_); } From e2301a5a75943059771320c364d77e135330d341 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 20 Aug 2013 20:43:15 +0200 Subject: [PATCH 0621/1445] Remove annoying logging --- input/gesture_detector.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 478f40ec05..6b919ab614 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -41,8 +41,6 @@ TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds estimatedInertiaX_ *= estimatedInertiaDamping; estimatedInertiaY_ *= estimatedInertiaDamping; - ILOG("%f %f", estimatedInertiaX_, estimatedInertiaY_); - p.lastX = touch.x; p.lastY = touch.y; } From a242bcdd3af3e16f03ad274a91e45c0ed4c87fea Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 21 Aug 2013 12:11:06 +1000 Subject: [PATCH 0622/1445] Remove 'HIGH_MEM' define. --- tools/atlastool.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index be52872d7e..cab032bd33 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -41,8 +41,6 @@ #include "util/text/utf8.h" -#define HIGH_MEM 1 - #define CHECK(x) if (!(x)) { printf("%i: CHECK failed on this line\n", __LINE__); exit(1); } using namespace std; @@ -686,7 +684,6 @@ void LearnFile(const char *filename, const char *desc, std::set &chars, uin void GetLocales(const char *locales, std::vector &ranges) { -#if HIGH_MEM std::set kanji; std::set hangul1, hangul2, hangul3; for (int i = 0; i < sizeof(kanjiFilter)/sizeof(kanjiFilter[0]); i+=2) @@ -702,7 +699,6 @@ void GetLocales(const char *locales, std::vector &ranges) LearnFile("korean.txt", "Korean", hangul1, 0x1100, 0x11FF); LearnFile("korean.txt", "Korean", hangul2, 0x3130, 0x318F); LearnFile("korean.txt", "Korean", hangul3, 0xAC00, 0xD7A3); -#endif // The end point of a range is now inclusive! @@ -719,7 +715,6 @@ void GetLocales(const char *locales, std::vector &ranges) case 'E': // Latin-1 Extended A (needed for Hungarian etc) ranges.push_back(range(0x100, 0x17F)); break; -#if HIGH_MEM case 'e': // Latin-1 Extended B (for some African and latinized asian languages?) ranges.push_back(range(0x180, 0x250)); break; @@ -732,7 +727,6 @@ void GetLocales(const char *locales, std::vector &ranges) ranges.push_back(range(0x3041, 0x3097)); ranges.push_back(range(0x3099, 0x309F)); break; -#endif case 's': // ShiftJIS symbols ranges.push_back(range(0x2010, 0x2312)); // General Punctuation, Letterlike Symbols, Arrows, // Mathematical Operators, Miscellaneous Technical @@ -742,7 +736,6 @@ void GetLocales(const char *locales, std::vector &ranges) ranges.push_back(range(0x2116, 0x2116)); // "No." symbol ranges.push_back(range(0x33CD, 0x33CD)); // "K.K." symbol break; -#if HIGH_MEM case 'H': // Hebrew ranges.push_back(range(0x0590, 0x05FF)); break; @@ -763,7 +756,6 @@ void GetLocales(const char *locales, std::vector &ranges) case 'K': // Korean (hangul) ranges.push_back(range(0xAC00, 0xD7A3, hangul3)); break; -#endif } } From ceb7f6dea6de9becbaeb059a97ce6f8000454585 Mon Sep 17 00:00:00 2001 From: The Dax Date: Wed, 21 Aug 2013 06:00:11 -0400 Subject: [PATCH 0623/1445] Allow right mouse button to act as a cancel button. --- ui/view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/view.cpp b/ui/view.cpp index 210c5a364c..4636ae8a1f 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -191,7 +191,7 @@ bool IsAcceptKeyCode(int keyCode) { } bool IsEscapeKeyCode(int keyCode) { - return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B || keyCode == NKCODE_BUTTON_2; + return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B || keyCode == NKCODE_BUTTON_2 || keyCode == NKCODE_EXT_MOUSEBUTTON_2; } void Clickable::Key(const KeyInput &key) { From 17b4ac55c5ffb7636e5e3e90d69e64f19090baf4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 21 Aug 2013 19:00:40 +0200 Subject: [PATCH 0624/1445] Temporarily (for 0.9.1) revert "Merge pull request #111 from thedax/master" Will put it back after 0.9.1, and then later this will be mappable anyway. This reverts commit 81da5fa32adbb60eb810bec628599a8a513b119a, reversing changes made to a242bcdd3af3e16f03ad274a91e45c0ed4c87fea. --- ui/view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/view.cpp b/ui/view.cpp index 4636ae8a1f..210c5a364c 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -191,7 +191,7 @@ bool IsAcceptKeyCode(int keyCode) { } bool IsEscapeKeyCode(int keyCode) { - return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B || keyCode == NKCODE_BUTTON_2 || keyCode == NKCODE_EXT_MOUSEBUTTON_2; + return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B || keyCode == NKCODE_BUTTON_2; } void Clickable::Key(const KeyInput &key) { From 92dd9cd7989394e1a5d69dceed0175519d3ffcd9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 21 Aug 2013 22:09:30 +0200 Subject: [PATCH 0625/1445] Android: Don't discard "non-game" keys when listening for modern style key events. --- .../com/henrikrydgard/libnative/InputDeviceState.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/InputDeviceState.java b/android/src/com/henrikrydgard/libnative/InputDeviceState.java index f1bf23e383..043c046475 100644 --- a/android/src/com/henrikrydgard/libnative/InputDeviceState.java +++ b/android/src/com/henrikrydgard/libnative/InputDeviceState.java @@ -68,21 +68,21 @@ public class InputDeviceState { public boolean onKeyDown(KeyEvent event) { int keyCode = event.getKeyCode(); if (event.getRepeatCount() == 0) { - if (isGameKey(keyCode)) { + // if (isGameKey(keyCode)) { NativeApp.keyDown(deviceId, keyCode); return true; - } + // } } return false; } public boolean onKeyUp(KeyEvent event) { int keyCode = event.getKeyCode(); - if (isGameKey(keyCode)) { + // if (isGameKey(keyCode)) { NativeApp.keyUp(deviceId, keyCode); return true; - } - return false; + // } + //return false; } public boolean onJoystickMotion(MotionEvent event) { From a8b45a68b961d655b68c7166a798cb0b6447f039 Mon Sep 17 00:00:00 2001 From: The Dax Date: Thu, 22 Aug 2013 06:45:45 -0400 Subject: [PATCH 0626/1445] Remove hard-coded accept and cancel buttons. --- input/input_state.cpp | 9 +++++++++ input/input_state.h | 9 ++++++++- ui/view.cpp | 4 ++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/input/input_state.cpp b/input/input_state.cpp index 2a75fbc2bb..af6cc6ae63 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -1,5 +1,6 @@ #include "input/input_state.h" #include "input/keycodes.h" +#include const char *GetDeviceName(int deviceId) { switch (deviceId) { @@ -41,6 +42,14 @@ int MapPadButtonFixed(int keycode) { } } +std::vector confirmKeys; +std::vector cancelKeys; + +void SetConfirmCancelKeys(std::vector confirm, std::vector cancel) { + confirmKeys = confirm; + cancelKeys = cancel; +} + uint32_t ButtonTracker::Update() { pad_buttons_ |= pad_buttons_async_set; pad_buttons_ &= ~pad_buttons_async_clear; diff --git a/input/input_state.h b/input/input_state.h index fd414b3646..f4784d477f 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -11,7 +11,9 @@ #include "math/lin/vec3.h" #include "base/mutex.h" #include "base/basictypes.h" +#include "input/keycodes.h" #include +#include // Default device IDs @@ -175,4 +177,9 @@ private: }; // Platforms should call g_buttonTracker.Process(). -extern ButtonTracker g_buttonTracker; \ No newline at end of file +extern ButtonTracker g_buttonTracker; + +// Is there a nicer place for this stuff? It's here to avoid dozens of linking errors in UnitTest.. +extern std::vector confirmKeys; +extern std::vector cancelKeys; +void SetConfirmCancelKeys(std::vector confirm, std::vector cancel); diff --git a/ui/view.cpp b/ui/view.cpp index 210c5a364c..9c09ac97bc 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -187,11 +187,11 @@ void Clickable::Touch(const TouchInput &input) { // TODO: O/X confirm preference for xperia play? bool IsAcceptKeyCode(int keyCode) { - return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_Z || keyCode == NKCODE_BUTTON_A || keyCode == NKCODE_BUTTON_CROSS || keyCode == NKCODE_BUTTON_1; + return std::find(confirmKeys.begin(), confirmKeys.end(), (keycode_t)keyCode) != confirmKeys.end(); } bool IsEscapeKeyCode(int keyCode) { - return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B || keyCode == NKCODE_BUTTON_2; + return std::find(cancelKeys.begin(), cancelKeys.end(), (keycode_t)keyCode) != cancelKeys.end(); } void Clickable::Key(const KeyInput &key) { From 45d65225a6f2fe8b8befe43786d6e54b066a7fbf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 22 Aug 2013 19:10:43 +0200 Subject: [PATCH 0627/1445] glstate: Switch to glBlendFuncSeparate for more flexibility. --- gfx_es2/draw_buffer.cpp | 6 +++--- gfx_es2/gl_state.cpp | 2 +- gfx_es2/gl_state.h | 23 ++++++++++++++++++++++- ui/ui_context.cpp | 4 ++-- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 7d3e26d2dd..ba9e0cc75f 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -79,7 +79,7 @@ void DrawBuffer::Flush(bool set_blend_state) { glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * count_, verts_, GL_STREAM_DRAW); if (set_blend_state) { glstate.blend.enable(); - glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glUniform1i(program_->sampler0, 0); glEnableVertexAttribArray(program_->a_position); @@ -102,7 +102,7 @@ void DrawBuffer::Flush(bool set_blend_state) { #else if (set_blend_state) { glstate.blend.enable(); - glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glBindBuffer(GL_ARRAY_BUFFER, 0); glUniform1i(program_->sampler0, 0); @@ -450,7 +450,7 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co void DrawBuffer::EnableBlend(bool enable) { glstate.blend.set(enable); - glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } void DrawBuffer::SetClipRect(float x, float y, float w, float h) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index c5ab9c209f..2a52ff6a4d 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -39,7 +39,7 @@ void OpenGLState::Restore() { int count = 0; blend.restore(); count++; blendEquation.restore(); count++; - blendFunc.restore(); count++; + blendFuncSeparate.restore(); count++; blendColor.restore(); count++; #if !defined(USING_GLES2) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 5a2bc24d0e..a88c6907e0 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -126,6 +126,26 @@ private: } \ } +#define STATE2_4(func, p1type, p2type, p1def, p2def, p3def, p4def) \ + class SavedState2_##func { \ + p1type p1; \ + p2type p2; \ + public: \ + SavedState2_##func() : p1(p1def), p2(p2def) { \ + OpenGLState::state_count++; \ + }; \ + inline void set(p1type newp1, p2type newp2) { \ + if(newp1 != p1 || newp2 != p2) { \ + p1 = newp1; \ + p2 = newp2; \ + func(p1, p2, p3def, p4def); \ + } \ + } \ + inline void restore() { \ + func(p1, p2, p3def, p4def); \ + } \ + } + #define STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \ class SavedState3_##func { \ p1type p1; \ @@ -203,7 +223,8 @@ public: // Blend BoolState blend; - STATE2(glBlendFunc, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFunc; + STATE4(glBlendFuncSeparate, GLenum, GLenum, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFuncSeparate; + STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; STATEFLOAT4(glBlendColor, 1.0f) blendColor; diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index fdbc9ee297..7a257f8c7e 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -8,7 +8,7 @@ void UIContext::Begin() { glstate.blend.enable(); - glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glstate.cullFace.disable(); glstate.depthTest.disable(); glstate.dither.enable(); @@ -25,7 +25,7 @@ void UIContext::Begin() { void UIContext::BeginNoTex() { glstate.blend.enable(); - glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glstate.cullFace.disable(); glstate.depthTest.disable(); glstate.dither.enable(); From 2bf829cdc18148388ed9ce73a8dc0f88736ddb16 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 23 Aug 2013 00:53:52 +0200 Subject: [PATCH 0628/1445] Android buildfix --- ui/view.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/view.cpp b/ui/view.cpp index 9c09ac97bc..7e4c7a5de0 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -1,4 +1,5 @@ #include +#include #include "base/display.h" #include "base/mutex.h" #include "input/input_state.h" From 74c9731d7c160eb48ad4a4722bd4699eab7a9000 Mon Sep 17 00:00:00 2001 From: Aapo Rantalainen Date: Fri, 23 Aug 2013 11:15:08 +0300 Subject: [PATCH 0629/1445] Maemo: *joy was not defined when MAEMO --- base/PCMain.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 7b5598c1da..102f747faa 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -48,9 +48,6 @@ #include "math.h" #ifdef PANDORA -SDL_Joystick *ljoy = NULL; -SDL_Joystick *rjoy = NULL; - void enable_runfast() { static const unsigned int x = 0x04086060; @@ -190,6 +187,12 @@ void EGL_Close() { g_eglContext = NULL; } #else +#endif + +#ifdef PANDORA +SDL_Joystick *ljoy = NULL; +SDL_Joystick *rjoy = NULL; +#else SDL_Joystick *joy = NULL; #endif From fbcacc340d429879a292dae8599cd0b42493575b Mon Sep 17 00:00:00 2001 From: Aapo Rantalainen Date: Fri, 23 Aug 2013 11:22:59 +0300 Subject: [PATCH 0630/1445] Maemo: don't include , it will fetch XLib.h and it breaks compiling --- gfx/gl_common.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 3d70b21465..5dedd12e64 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -8,7 +8,9 @@ #else #include #include +#ifndef MAEMO #include +#endif #endif #else // OpenGL From 3673bf6b0ea19beca6d163b2bc7ea9a5ee27230b Mon Sep 17 00:00:00 2001 From: Aapo Rantalainen Date: Fri, 23 Aug 2013 11:25:24 +0300 Subject: [PATCH 0631/1445] Maemo: There are no Escape on Maemo, use SDL_BACKSPACE --- base/NKCodeFromSDL.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/NKCodeFromSDL.h b/base/NKCodeFromSDL.h index bccc8e237c..f0f158dd8d 100644 --- a/base/NKCodeFromSDL.h +++ b/base/NKCodeFromSDL.h @@ -50,7 +50,11 @@ static const std::map KeyMapRawSDLtoNative = InitConstMap (SDLK_PLUS, NKCODE_PLUS) (SDLK_PAGEUP, NKCODE_PAGE_UP) (SDLK_PAGEDOWN, NKCODE_PAGE_DOWN) +#ifdef MAEMO + (SDLK_BACKSPACE, NKCODE_ESCAPE) +#else (SDLK_ESCAPE, NKCODE_ESCAPE) +#endif (SDLK_DELETE, NKCODE_FORWARD_DEL) (SDLK_LCTRL, NKCODE_CTRL_LEFT) (SDLK_RCTRL, NKCODE_CTRL_RIGHT) From 2f7f8b1e3cb7aca1b936406e62dbeaeef1b782a7 Mon Sep 17 00:00:00 2001 From: Aapo Rantalainen Date: Fri, 23 Aug 2013 11:26:17 +0300 Subject: [PATCH 0632/1445] Maemo: Maemo needs same PFNGLDISCARDFRAMEBUFFEREXTPROC etc than Meego --- gfx_es2/gl_state.cpp | 4 ++-- gfx_es2/gl_state.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 2a52ff6a4d..4c905f91d1 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -11,7 +11,7 @@ PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; PFNGLMAPBUFFERPROC glMapBuffer; #endif -#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) +#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; @@ -108,7 +108,7 @@ void CheckGLExtensions() { gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; -#if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) +#if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) gl_extensions.OES_vertex_array_object = false; gl_extensions.EXT_discard_framebuffer = false; #else diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index a88c6907e0..a6b7a53bf6 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -28,7 +28,7 @@ typedef GLvoid* (GL_APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access) extern PFNGLMAPBUFFERPROC glMapBuffer; #endif -#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) +#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; From 788cbf6e003a71c99f8550ddabc6e110047c7997 Mon Sep 17 00:00:00 2001 From: Aapo Rantalainen Date: Fri, 23 Aug 2013 11:44:43 +0300 Subject: [PATCH 0633/1445] Fix: landscape and portrait should be same resolution --- base/PCMain.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 102f747faa..f6f65b1bc5 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -383,8 +383,13 @@ int main(int argc, char *argv[]) { pixel_xres = 1024 * zoom; pixel_yres = 768 * zoom; } else { +#ifdef MAEMO + pixel_xres = 800 * zoom; + pixel_yres = 480 * zoom; +#else pixel_xres = 960 * zoom; pixel_yres = 544 * zoom; +#endif } } else { // PC development hack for more space @@ -397,8 +402,13 @@ int main(int argc, char *argv[]) { pixel_xres = 768 * zoom; pixel_yres = 1024 * zoom; } else { +#ifdef MAEMO pixel_xres = 480 * zoom; pixel_yres = 800 * zoom; +#else + pixel_xres = 544 * zoom; + pixel_yres = 960 * zoom; +#endif } } From cd162639ed50a3aa4fcec79d39ea59fd00741f3a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 25 Aug 2013 21:48:43 +0200 Subject: [PATCH 0634/1445] Fix ridiculous bug that would ignore (and thus delete when resaved) the last line of ini files if it didn't end with a line break. --- file/ini_file.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index dbe0e23e82..4da6e14b2c 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -454,8 +454,6 @@ bool IniFile::Load(std::istream &in) { } #endif - if (in.eof()) break; - if (line.size() > 0) { if (line[0] == '[') From a038f612bdd02f44eee2177194d0a83d641bd41e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 26 Aug 2013 18:59:08 +0200 Subject: [PATCH 0635/1445] Unicode prep --- audio/mixer.cpp | 2 +- base/basictypes.h | 2 +- base/logging.h | 10 +++---- base/stringutil.cpp | 12 +++++++-- data/compression.cpp | 4 +-- file/chunk_file.cpp | 8 +----- file/chunk_file.h | 3 ++- file/file_util.cpp | 29 ++++++++++---------- math/expression_parser.cpp | 6 ++--- math/expression_parser.h | 4 +-- midi/midi_input.cpp | 4 ++- native.vcxproj | 8 +++--- net/resolve.cpp | 8 +++--- util/text/utf8.cpp | 55 +++++++++++++++++++++++++++++++++++++- util/text/utf8.h | 17 +++++++++++- 15 files changed, 121 insertions(+), 51 deletions(-) diff --git a/audio/mixer.cpp b/audio/mixer.cpp index 45d6c4c3b2..ac621cd380 100644 --- a/audio/mixer.cpp +++ b/audio/mixer.cpp @@ -98,7 +98,7 @@ Clip *clip_load(const char *filename) { uint8_t *filedata; size_t size; filedata = VFSReadFile(filename, &size); - num_samples = (int)stb_vorbis_decode_memory(filedata, size, &num_channels, &data); + num_samples = (int)stb_vorbis_decode_memory(filedata, (int)size, &num_channels, &data); if (num_samples <= 0) return NULL; sample_rate = 44100; diff --git a/base/basictypes.h b/base/basictypes.h index bb86be3668..d8de8c0713 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -99,6 +99,6 @@ inline uint64 swap64(const uint8* _pData) {return swap64(*(const uint64*)_pData) #endif // For really basic windows code compat -#ifndef TCHAR +#ifndef _TCHAR_DEFINED typedef char TCHAR; #endif diff --git a/base/logging.h b/base/logging.h index 2e0dbd3992..95bfe176d0 100644 --- a/base/logging.h +++ b/base/logging.h @@ -64,12 +64,12 @@ inline void Crash() { #ifdef _WIN32 -void __ods__(const char *p); +void OutputDebugStringUTF8(const char *p); -#define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "I: " __VA_ARGS__); p += sprintf(p, "\n"); __ods__(temp);} -#define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "W: " __VA_ARGS__); p += sprintf(p, "\n"); __ods__(temp);} -#define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "E: " __VA_ARGS__); p += sprintf(p, "\n"); __ods__(temp);} -#define FLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "F: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "F: " __VA_ARGS__); p += sprintf(p, "\n"); __ods__(temp); Crash();} +#define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "I: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "W: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "E: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define FLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "F: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "F: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp); Crash();} // TODO: Win32 version using OutputDebugString #else diff --git a/base/stringutil.cpp b/base/stringutil.cpp index fa5f4a4c07..8e14ede96c 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -1,5 +1,7 @@ #ifdef _WIN32 #include +#undef min +#undef max #endif #include #include @@ -8,6 +10,7 @@ #include #include +#include #include #include "base/buffer.h" @@ -17,9 +20,14 @@ // Function Cross-Compatibility #define strcasecmp _stricmp -void __ods__(const char *p) { - OutputDebugString(p); +void OutputDebugStringUTF8(const char *p) { + wchar_t temp[2048]; + int len = std::min(2047, (int)strlen(p)); + int size = (int)MultiByteToWideChar(CP_UTF8, 0, p, len, NULL, 0); + MultiByteToWideChar(CP_UTF8, 0, p, len, temp, size); + OutputDebugString(temp); } + #endif unsigned int parseHex(const char *_szValue) diff --git a/data/compression.cpp b/data/compression.cpp index 63ce4b1dc7..f2bc6494ee 100644 --- a/data/compression.cpp +++ b/data/compression.cpp @@ -25,7 +25,7 @@ bool compress_string(const std::string& str, std::string *dest, int compressionl } zs.next_in = (Bytef*)str.data(); - zs.avail_in = str.size(); // set the z_stream's input + zs.avail_in = (uInt)str.size(); // set the z_stream's input int ret; char outbuffer[32768]; @@ -72,7 +72,7 @@ bool decompress_string(const std::string& str, std::string *dest) { } zs.next_in = (Bytef*)str.data(); - zs.avail_in = str.size(); + zs.avail_in = (uInt)str.size(); int ret; char outbuffer[32768]; diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index 396b07753b..6d61f11841 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -214,23 +214,17 @@ void ChunkFile::writeWString(String str) { } */ +// Takes utf-8 void ChunkFile::writeWString(const std::string &str) { unsigned short *text; size_t len = str.length(); -#ifdef UNICODE -#error - text = str.c_str(); -#else text = new unsigned short[len+1]; for (int i=0; ifullName = path; @@ -207,7 +205,7 @@ bool getFileInfo(const char *path, FileInfo *fileInfo) } std::string getFileExtension(const std::string &fn) { - int pos = fn.rfind("."); + int pos = (int)fn.rfind("."); if (pos < 0) return ""; std::string ext = fn.substr(pos+1); for (size_t i = 0; i < ext.size(); i++) { @@ -248,7 +246,8 @@ size_t getFilesInDir(const char *directory, std::vector *files, const // Find the first file in the directory. WIN32_FIND_DATA ffd; #ifdef UNICODE - HANDLE hFind = FindFirstFile((std::wstring(directory) + "\\*").c_str(), &ffd); + + HANDLE hFind = FindFirstFile((ConvertUTF8ToWString(directory) + L"\\*").c_str(), &ffd); #else HANDLE hFind = FindFirstFile((std::string(directory) + "\\*").c_str(), &ffd); #endif @@ -259,7 +258,7 @@ size_t getFilesInDir(const char *directory, std::vector *files, const // windows loop do { - const std::string virtualName(ffd.cFileName); + const std::string virtualName = ConvertWStringToUTF8(ffd.cFileName); #else struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; }; struct dirent_large diren; @@ -316,7 +315,7 @@ size_t getFilesInDir(const char *directory, std::vector *files, const void deleteFile(const char *file) { #ifdef _WIN32 - if (!DeleteFile(file)) { + if (!DeleteFile(ConvertUTF8ToWString(file).c_str())) { ELOG("Error deleting %s: %i", file, GetLastError()); } #else @@ -330,7 +329,7 @@ void deleteFile(const char *file) void deleteDir(const char *dir) { #ifdef _WIN32 - if (!RemoveDirectory(dir)) { + if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str())) { ELOG("Error deleting directory %s: %i", dir, GetLastError()); } #else @@ -390,7 +389,7 @@ std::vector getWindowsDrives() auto drive = buff.data(); while (*drive) { - std::string str(drive); + std::string str(ConvertWStringToUTF8(drive)); str.pop_back(); // we don't want the final backslash str += "/"; drives.push_back(str); diff --git a/math/expression_parser.cpp b/math/expression_parser.cpp index 505d1160c7..d95f4f0b23 100644 --- a/math/expression_parser.cpp +++ b/math/expression_parser.cpp @@ -147,7 +147,7 @@ bool parseNumber(char* str, int defaultrad, int len, uint32& result) return true; } -ExpressionOpcodeType getExpressionOpcode(char* str, int& ReturnLen, ExpressionOpcodeType LastOpcode) +ExpressionOpcodeType getExpressionOpcode(const char* str, int& ReturnLen, ExpressionOpcodeType LastOpcode) { int longestlen = 0; ExpressionOpcodeType result = EXOP_NONE; @@ -185,12 +185,12 @@ bool isAlphaNum(char c) } } -bool initPostfixExpression(char* infix, IExpressionFunctions* funcs, PostfixExpression& dest) +bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, PostfixExpression& dest) { expressionError[0] = 0; int infixPos = 0; - int infixLen = strlen(infix); + int infixLen = (int)strlen(infix); ExpressionOpcodeType lastOpcode = EXOP_NONE; std::vector opcodeStack; dest.clear(); diff --git a/math/expression_parser.h b/math/expression_parser.h index 7d1f8e67da..bbf7b78306 100644 --- a/math/expression_parser.h +++ b/math/expression_parser.h @@ -15,7 +15,7 @@ public: virtual bool getMemoryValue(uint32 address, int size, uint32& dest, char* error) = 0; }; -bool initPostfixExpression(char* infix, IExpressionFunctions* funcs, PostfixExpression& dest); +bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, PostfixExpression& dest); bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, uint32& dest); -bool parseExpression(char* exp, IExpressionFunctions* funcs, uint32& dest); +bool parseExpression(const char* exp, IExpressionFunctions* funcs, uint32& dest); const char* getExpressionError(); diff --git a/midi/midi_input.cpp b/midi/midi_input.cpp index d42ccff13d..cb11625e19 100644 --- a/midi/midi_input.cpp +++ b/midi/midi_input.cpp @@ -11,14 +11,16 @@ #include "base/basictypes.h" #include "base/logging.h" #include "midi/midi_input.h" +#include "util/text/utf8.h" std::vector MidiInGetDevices() { int numDevs = midiInGetNumDevs(); + std::vector devices; for (int i = 0; i < numDevs; i++) { MIDIINCAPS caps; midiInGetDevCaps(i, &caps, sizeof(caps)); - devices.push_back(caps.szPname); + devices.push_back(ConvertWStringToUTF8(caps.szPname)); } return devices; } diff --git a/native.vcxproj b/native.vcxproj index 264f78d557..b67686a97c 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -27,25 +27,25 @@ StaticLibrary true - MultiByte + Unicode StaticLibrary true - MultiByte + Unicode StaticLibrary false false - MultiByte + Unicode v100 StaticLibrary false false - MultiByte + Unicode diff --git a/net/resolve.cpp b/net/resolve.cpp index 304f3356cb..27fee57fea 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -96,8 +96,7 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo ** *res = NULL; int result = getaddrinfo(host.c_str(), servicep, &hints, res); - if (result == EAI_AGAIN) - { + if (result == EAI_AGAIN) { // Temporary failure. Since this already blocks, let's just try once more. #ifdef _WIN32 Sleep(1); @@ -107,9 +106,8 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo ** result = getaddrinfo(host.c_str(), servicep, &hints, res); } - if (result != 0) - { - error = gai_strerror(result); + if (result != 0) { + error = gai_strerrorA(result); if (*res != NULL) freeaddrinfo(*res); *res = NULL; diff --git a/util/text/utf8.cpp b/util/text/utf8.cpp index e77eb076bb..378fd236c6 100644 --- a/util/text/utf8.cpp +++ b/util/text/utf8.cpp @@ -11,11 +11,21 @@ with these routines reserved for higher performance on data known to be valid. */ + +#ifdef _WIN32 +#include +#undef min +#undef max +#endif + #include #include #include #include +#include +#include + #include "base/basictypes.h" #include "utf8.h" @@ -407,4 +417,47 @@ int UTF8StringNonASCIICount(const char *utf8string) { bool UTF8StringHasNonASCII(const char *utf8string) { return UTF8StringNonASCIICount(utf8string) > 0; -} \ No newline at end of file +} + +#ifdef _WIN32 + +std::string ConvertWStringToUTF8(const wchar_t *wstr) { + int len = (int)wcslen(wstr); + int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, NULL, NULL); + std::string s; + s.resize(size); + if (size > 0) { + WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, NULL, NULL); + } + return s; +} + +std::string ConvertWStringToUTF8(const std::wstring &wstr) { + int len = (int)wstr.size(); + int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL); + std::string s; + s.resize(size); + if (size > 0) { + WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, NULL, NULL); + } + return s; +} + +void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) { + int len = (int)source.size(); + int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0); + MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size)); +} + +std::wstring ConvertUTF8ToWString(const std::string &source) { + int len = (int)source.size(); + int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0); + std::wstring str; + str.resize(size); + if (size > 0) { + MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, &str[0], size); + } + return str; +} + +#endif diff --git a/util/text/utf8.h b/util/text/utf8.h index 5d46a67648..1cfd55aed0 100644 --- a/util/text/utf8.h +++ b/util/text/utf8.h @@ -14,7 +14,10 @@ // Further modified, and C++ stuff added, by hrydgard@gmail.com. +#pragma once + #include "base/basictypes.h" +#include uint32_t u8_nextchar(const char *s, int *i); int u8_wc_toutf8(char *dest, uint32_t ch); @@ -45,4 +48,16 @@ private: int UTF8StringNonASCIICount(const char *utf8string); -bool UTF8StringHasNonASCII(const char *utf8string); \ No newline at end of file +bool UTF8StringHasNonASCII(const char *utf8string); + + +// UTF8 to Win32 UCS-16 +// Should be used when calling Win32 api calls +#ifdef _WIN32 + +std::string ConvertWStringToUTF8(const std::wstring &wstr); +std::string ConvertWStringToUTF8(const wchar_t *wstr); +void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source); +std::wstring ConvertUTF8ToWString(const std::string &source); + +#endif \ No newline at end of file From c7bb4d2d6fd4259af7d7a2436bf84899c1331572 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 26 Aug 2013 19:17:54 +0200 Subject: [PATCH 0636/1445] Android buildfix --- net/resolve.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/resolve.cpp b/net/resolve.cpp index 27fee57fea..683484ad40 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -107,7 +107,11 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo ** } if (result != 0) { +#ifdef _WIN32 error = gai_strerrorA(result); +#else + error = gai_strerror(result); +#endif if (*res != NULL) freeaddrinfo(*res); *res = NULL; From 1ac2bd895df0f15a6a7493408dead83064a443bb Mon Sep 17 00:00:00 2001 From: The Dax Date: Mon, 26 Aug 2013 13:20:58 -0400 Subject: [PATCH 0637/1445] Windows build fix. --- file/dialog.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/file/dialog.cpp b/file/dialog.cpp index 70864cc3e7..0cffd2f834 100644 --- a/file/dialog.cpp +++ b/file/dialog.cpp @@ -8,18 +8,18 @@ // For desktop operating systems only. Stubbed out on Android. // Simplified as this will only be used in utilities / temp code. // An false returned means cancel; -bool OpenFileDialog(const char *title, const char *extension, std::string *filename) +bool OpenFileDialog(const wchar_t *title, const wchar_t *extension, std::wstring *filename) { OPENFILENAME of; memset(&of, 0, sizeof(of)); - char buffer[512] = {0}; + wchar_t buffer[512] = {0}; of.lStructSize = sizeof(OPENFILENAME); of.hInstance = 0; of.hwndOwner = GetActiveWindow(); // These weird strings with zeroes in them can't be dealt with using normal string // functions, so here we go - evil hackery. - char filter[256] = "XXX files\0*.XXX\0\0"; + wchar_t filter[256] = L"XXX files\0*.XXX\0\0"; memcpy(filter, extension, 3); memcpy(filter + 12, extension, 3); of.lpstrFilter = filter; @@ -34,18 +34,18 @@ bool OpenFileDialog(const char *title, const char *extension, std::string *filen return true; } -bool SaveFileDialog(const char *title, const char *extension, std::string *filename) +bool SaveFileDialog(const wchar_t *title, const wchar_t *extension, std::wstring *filename) { OPENFILENAME of; memset(&of, 0, sizeof(of)); - char buffer[512] = {0}; + wchar_t buffer[512] = {0}; of.lStructSize = sizeof(OPENFILENAME); of.hInstance = 0; of.hwndOwner = GetActiveWindow(); // These weird strings with zeroes in them can't be dealt with using normal string // functions, so here we go - evil hackery. - char filter[256] = "XXX files\0*.XXX\0\0"; + wchar_t filter[256] = L"XXX files\0*.XXX\0\0"; memcpy(filter, extension, 3); memcpy(filter + 12, extension, 3); of.lpstrFilter = filter; From cec2e6cea9eed78fb49e0d0a36d03182adabc5b0 Mon Sep 17 00:00:00 2001 From: The Dax Date: Mon, 26 Aug 2013 13:53:52 -0400 Subject: [PATCH 0638/1445] Allow newlines in translation keys. --- i18n/i18n.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp index 56061bd751..20e7fc547c 100644 --- a/i18n/i18n.cpp +++ b/i18n/i18n.cpp @@ -16,14 +16,18 @@ void I18NRepo::Clear() { } const char *I18NCategory::T(const char *key, const char *def) { - auto iter = map_.find(key); + // Replace the \n's with \\n's so that we can use newlines in ini key values. + std::string modifiedKey = key; + modifiedKey = ReplaceAll(modifiedKey, "\n", "\\n"); + + auto iter = map_.find(modifiedKey); if (iter != map_.end()) { return iter->second.text.c_str(); } else { if (def) missedKeyLog_[key] = def; else - missedKeyLog_[key] = key; + missedKeyLog_[key] = modifiedKey.c_str(); return def ? def : key; } } From 94087bbc6a05398b591f6e67c1696660a317a903 Mon Sep 17 00:00:00 2001 From: The Dax Date: Mon, 26 Aug 2013 14:01:35 -0400 Subject: [PATCH 0639/1445] Amend comment. --- i18n/i18n.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp index 20e7fc547c..7bfa5ae5d7 100644 --- a/i18n/i18n.cpp +++ b/i18n/i18n.cpp @@ -16,7 +16,7 @@ void I18NRepo::Clear() { } const char *I18NCategory::T(const char *key, const char *def) { - // Replace the \n's with \\n's so that we can use newlines in ini key values. + // Replace the \n's with \\n's so that key values with newlines will be found correctly. std::string modifiedKey = key; modifiedKey = ReplaceAll(modifiedKey, "\n", "\\n"); From 885e7163ed316406d966184e89f2ca06362e9cbc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 27 Aug 2013 00:27:06 -0700 Subject: [PATCH 0640/1445] Open filenames using wide functions on win32. --- file/file_util.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index cfaa9d4d50..58e24122a9 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -44,9 +44,18 @@ static inline int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **res } #endif +FILE *openCFile(const std::string &filename, const char *mode) +{ +#if defined(_WIN32) && defined(UNICODE) + return _wfopen(ConvertUTF8ToWString(filename).c_str(), ConvertUTF8ToWString(mode).c_str()); +#else + return fopen(filename.c_str(), mode); +#endif +} + bool writeStringToFile(bool text_file, const std::string &str, const char *filename) { - FILE *f = fopen(filename, text_file ? "w" : "wb"); + FILE *f = openCFile(filename, text_file ? "w" : "wb"); if (!f) return false; size_t len = str.size(); @@ -61,7 +70,7 @@ bool writeStringToFile(bool text_file, const std::string &str, const char *filen bool writeDataToFile(bool text_file, const void* data, const unsigned int size, const char *filename) { - FILE *f = fopen(filename, text_file ? "w" : "wb"); + FILE *f = openCFile(filename, text_file ? "w" : "wb"); if (!f) return false; size_t len = size; @@ -92,7 +101,7 @@ uint64_t GetSize(FILE *f) bool ReadFileToString(bool text_file, const char *filename, std::string &str) { - FILE *f = fopen(filename, text_file ? "r" : "rb"); + FILE *f = openCFile(filename, text_file ? "r" : "rb"); if (!f) return false; size_t len = (size_t)GetSize(f); @@ -107,7 +116,7 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str) bool readDataFromFile(bool text_file, unsigned char* &data, const unsigned int size, const char *filename) { - FILE *f = fopen(filename, text_file ? "r" : "rb"); + FILE *f = openCFile(filename, text_file ? "r" : "rb"); if (!f) return false; size_t len = (size_t)GetSize(f); @@ -169,7 +178,7 @@ bool getFileInfo(const char *path, FileInfo *fileInfo) { #ifdef _WIN32 WIN32_FILE_ATTRIBUTE_DATA attrs; - if (!GetFileAttributesExA(path, GetFileExInfoStandard, &attrs)) { + if (!GetFileAttributesExW(ConvertUTF8ToWString(path).c_str(), GetFileExInfoStandard, &attrs)) { fileInfo->size = 0; fileInfo->isDirectory = false; fileInfo->exists = false; From 379230bd61c3367d1cc208ba1bfc31a52b76f5a3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 27 Aug 2013 00:35:52 -0700 Subject: [PATCH 0641/1445] Fix a small typo. --- util/text/utf8.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/text/utf8.h b/util/text/utf8.h index 1cfd55aed0..7519526428 100644 --- a/util/text/utf8.h +++ b/util/text/utf8.h @@ -51,7 +51,7 @@ int UTF8StringNonASCIICount(const char *utf8string); bool UTF8StringHasNonASCII(const char *utf8string); -// UTF8 to Win32 UCS-16 +// UTF8 to Win32 UTF-16 // Should be used when calling Win32 api calls #ifdef _WIN32 @@ -60,4 +60,4 @@ std::string ConvertWStringToUTF8(const wchar_t *wstr); void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source); std::wstring ConvertUTF8ToWString(const std::string &source); -#endif \ No newline at end of file +#endif From bb8f38a14593e198134cfc4f880b9dc0020ca9fe Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Jul 2013 17:04:08 +0200 Subject: [PATCH 0642/1445] Provide empty default implementation for update. --- ui/screen.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/screen.h b/ui/screen.h index 4c2b2af5cc..40a3fed67c 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -39,7 +39,7 @@ public: screenManager_ = 0; } - virtual void update(InputState &input) = 0; + virtual void update(InputState &input) {} virtual void render() {} virtual void deviceLost() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} From b063724c9e4364613fe8af66439d56ed0fbf049c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 27 Aug 2013 19:43:40 +0200 Subject: [PATCH 0643/1445] Logging bug fix and some warning fixes. --- base/PCMain.cpp | 3 +++ base/stringutil.cpp | 1 + gfx_es2/draw_buffer.h | 4 ++++ input/input_state.h | 2 +- ui/ui_context.h | 1 + ui/view.h | 8 ++++---- ui/viewgroup.cpp | 6 +++--- ui/viewgroup.h | 2 ++ 8 files changed, 19 insertions(+), 8 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 102f747faa..c0b82c2148 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -645,6 +645,7 @@ int main(int argc, char *argv[]) { input_state.pointer_y[0] = my; //input_state.mouse_buttons_down = 1; input_state.pointer_down[0] = true; + input_state.mouse_valid = true; TouchInput input; input.x = mx; input.y = my; @@ -685,6 +686,7 @@ int main(int argc, char *argv[]) { if (input_state.pointer_down[0]) { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; + input_state.mouse_valid = true; TouchInput input; input.x = mx; input.y = my; @@ -700,6 +702,7 @@ int main(int argc, char *argv[]) { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; input_state.pointer_down[0] = false; + input_state.mouse_valid = true; //input_state.mouse_buttons_up = 1; TouchInput input; input.x = mx; diff --git a/base/stringutil.cpp b/base/stringutil.cpp index 8e14ede96c..d3bb4b6923 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -25,6 +25,7 @@ void OutputDebugStringUTF8(const char *p) { int len = std::min(2047, (int)strlen(p)); int size = (int)MultiByteToWideChar(CP_UTF8, 0, p, len, NULL, 0); MultiByteToWideChar(CP_UTF8, 0, p, len, temp, size); + temp[size] = 0; OutputDebugString(temp); } diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index e8d7453801..1f3d106f86 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -7,6 +7,7 @@ #include "base/display.h" #include "gfx/gl_lost_manager.h" #include "gfx/texture_atlas.h" +#include "math/geom2d.h" struct Atlas; @@ -102,6 +103,9 @@ public: void MeasureImage(ImageID atlas_image, float *w, float *h); void DrawImage(ImageID atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT); void DrawImageStretch(ImageID atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF)); + void DrawImageStretch(int atlas_image, const Bounds &bounds, Color color = COLOR(0xFFFFFF)) { + DrawImageStretch(atlas_image, bounds.x, bounds.y, bounds.x2(), bounds.y2(), color); + } void DrawImageRotated(ImageID atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF), bool mirror_h = false); // Always centers void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); // Results in 18 triangles. Kind of expensive for a button. diff --git a/input/input_state.h b/input/input_state.h index f4784d477f..8a86e6d575 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -61,7 +61,7 @@ enum { }; #ifndef MAX_POINTERS -#define MAX_POINTERS 8 +#define MAX_POINTERS 10 #endif #ifndef MAX_KEYQUEUESIZE diff --git a/ui/ui_context.h b/ui/ui_context.h index 146d92f106..dce72c62c6 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -48,6 +48,7 @@ public: void ActivateTopScissor(); DrawBuffer *Draw() const { return uidrawbuffer_; } + DrawBuffer *DrawTop() const { return uidrawbufferTop_; } const UI::Theme *theme; diff --git a/ui/view.h b/ui/view.h index 1ad958ccc3..a3236b7608 100644 --- a/ui/view.h +++ b/ui/view.h @@ -281,9 +281,9 @@ public: // Please note that Touch is called ENTIRELY asynchronously from drawing! // Can even be called on a different thread! This is to really minimize latency, and decouple - // touch response from the frame rate. - virtual void Key(const KeyInput &input) = 0; - virtual void Touch(const TouchInput &input) = 0; + // touch response from the frame rate. Same with Key and Axis. + virtual void Key(const KeyInput &input) {} + virtual void Touch(const TouchInput &input) {} virtual void Axis(const AxisInput &input) {} virtual void Update(const InputState &input_state) {} @@ -400,7 +400,7 @@ class Button : public Clickable { public: Button(const std::string &text, LayoutParams *layoutParams = 0) : Clickable(layoutParams), text_(text) {} - + virtual void Draw(UIContext &dc); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; const std::string &GetText() const { return text_; } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 9a5bcb3ec2..a00621728b 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -871,10 +871,10 @@ EventReturn ChoiceStrip::OnChoiceClick(EventParams &e) { void ChoiceStrip::SetSelection(int sel) { int prevSelected = selected_; - if (selected_ < views_.size()) + if (selected_ < (int)views_.size()) static_cast(views_[selected_])->Release(); selected_ = sel; - if (selected_ < views_.size()) + if (selected_ < (int)views_.size()) static_cast(views_[selected_])->Press(); if (topTabs_ && prevSelected != selected_) { EventParams e; @@ -887,7 +887,7 @@ void ChoiceStrip::Key(const KeyInput &input) { if (input.flags & KEY_DOWN) { if (input.keyCode == NKCODE_BUTTON_L1 && selected_ > 0) { SetSelection(selected_ - 1); - } else if (input.keyCode == NKCODE_BUTTON_R1 && selected_ < views_.size() - 1) { + } else if (input.keyCode == NKCODE_BUTTON_R1 && selected_ < (int)views_.size() - 1) { SetSelection(selected_ + 1); } } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 60570a5b68..1729830c56 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -284,6 +284,8 @@ public: tabs_[currentTab_]->SetVisibility(V_VISIBLE); } + int GetCurrentTab() const { return currentTab_; } + private: EventReturn OnTabClick(EventParams &e); From 0931f784b6c231706d3dd3e499597edf7ceef25e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 30 Aug 2013 14:44:23 +0200 Subject: [PATCH 0644/1445] Win32: Add a sentence-caching text drawing engine using Win32 fonts. --- Android.mk | 4 +- gfx_es2/draw_buffer.cpp | 6 +- gfx_es2/draw_buffer.h | 13 +- gfx_es2/draw_text.cpp | 254 ++++++++++++++++++++++++++++++++++++++++ gfx_es2/draw_text.h | 65 ++++++++++ native.vcxproj | 3 + native.vcxproj.filters | 9 ++ ui/ui_context.cpp | 72 ++++++++++++ ui/ui_context.h | 32 ++--- ui/view.cpp | 52 ++++---- ui/view.h | 33 ++++-- util/hash/hash.cpp | 6 +- 12 files changed, 489 insertions(+), 60 deletions(-) create mode 100644 gfx_es2/draw_text.cpp create mode 100644 gfx_es2/draw_text.h diff --git a/Android.mk b/Android.mk index 2486b7ec38..9f2f4baf93 100644 --- a/Android.mk +++ b/Android.mk @@ -57,6 +57,7 @@ LOCAL_SRC_FILES :=\ gfx_es2/glsl_program.cpp \ gfx_es2/gl_state.cpp \ gfx_es2/draw_buffer.cpp.arm \ + gfx_es2/draw_text.cpp \ gfx_es2/vertex_format.cpp \ gfx_es2/fbo.cpp \ gfx/gl_debug_log.cpp \ @@ -75,7 +76,8 @@ LOCAL_SRC_FILES :=\ ui/screen.cpp \ ui/virtual_input.cpp \ util/random/perlin.cpp \ - util/text/utf8.cpp + util/text/utf8.cpp \ + util/hash/hash.cpp LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -frtti diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index ba9e0cc75f..900bfafe13 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -8,6 +8,7 @@ #include "base/logging.h" #include "math/math_util.h" #include "gfx_es2/draw_buffer.h" +#include "gfx_es2/draw_text.h" #include "gfx_es2/glsl_program.h" #include "gfx_es2/gl_state.h" #include "gfx/texture_atlas.h" @@ -370,11 +371,8 @@ void DrawBuffer::DoAlign(int flags, float *x, float *y, float *w, float *h) { } } -// TODO: Unicode support. -// U+4E00–U+9FBF Kanji -// U+3040–U+309F Hiragana -// U+30A0–U+30FF Katakana +// TODO: Actually use the rect properly, take bounds. void DrawBuffer::DrawTextRect(int font, const char *text, float x, float y, float w, float h, Color color, int align) { if (align & ALIGN_HCENTER) { x += w / 2; diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 1f3d106f86..64b9c3232b 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -30,6 +30,11 @@ enum { ROTATE_90DEG_LEFT = 256, ROTATE_90DEG_RIGHT = 512, ROTATE_180DEG = 1024, + + // For "uncachable" text like debug log. + // Avoids using system font drawing as it's too slow. + // Not actually used here but is reserved for whatever system wraps DrawBuffer. + FLAG_DYNAMIC_ASCII = 2048, }; struct GLSLProgram; @@ -44,6 +49,8 @@ struct GradientStop { uint32_t color; }; +class TextDrawer; + class DrawBuffer : public GfxResourceHolder { public: DrawBuffer(); @@ -55,6 +62,7 @@ public: // TODO: Enforce these. Now Init is autocalled and shutdown not called. void Init(bool registerAsHolder = true); void Shutdown(); + virtual void GLLost(); int Count() const { return count_; } @@ -114,6 +122,8 @@ public: void DrawImage2GridH(ImageID atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); void MeasureText(int font, const char *text, float *w, float *h); + + void DrawTextRect(int font, const char *text, float x, float y, float w, float h, Color color = 0xFFFFFFFF, int align = 0); void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); void DrawTextShadow(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); @@ -133,8 +143,9 @@ public: void SetClipRect(float x1, float y1, float x2, float y2); void NoClip(); + static void DoAlign(int flags, float *x, float *y, float *w, float *h); + private: - void DoAlign(int flags, float *x, float *y, float *w, float *h); struct Vertex { float x, y, z; uint32_t rgba; diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp new file mode 100644 index 0000000000..1a1eca68c4 --- /dev/null +++ b/gfx_es2/draw_text.cpp @@ -0,0 +1,254 @@ +#include "base/logging.h" +#include "gfx/gl_common.h" +#include "gfx_es2/draw_text.h" +#include "util/hash/hash.h" +#include "util/text/utf8.h" + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include + +struct TextDrawerFontContext { + HFONT hFont; +}; + +struct TextDrawerContext { + HDC hDC; + HBITMAP hbmBitmap; + int *pBitmapBits; +}; + +TextDrawer::TextDrawer() { + fontScaleX_ = 1.0f; + fontScaleY_ = 1.0f; + ctx_ = new TextDrawerContext(); + ctx_->hDC = CreateCompatibleDC(NULL); + + BITMAPINFO bmi; + ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) ); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = MAX_TEXT_WIDTH; + bmi.bmiHeader.biHeight = -MAX_TEXT_HEIGHT; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biBitCount = 32; + + ctx_->hbmBitmap = CreateDIBSection(ctx_->hDC, &bmi, DIB_RGB_COLORS, (VOID**)&ctx_->pBitmapBits, NULL, 0); + SetMapMode(ctx_->hDC, MM_TEXT); + + SelectObject(ctx_->hDC, ctx_->hbmBitmap); +} + +TextDrawer::~TextDrawer() { + for (auto iter = cache_.begin(); iter != cache_.end(); ++iter) { + glDeleteTextures(1, &iter->second->textureHandle); + delete iter->second; + } + cache_.clear(); + + for (auto iter = fontMap_.begin(); iter != fontMap_.end(); ++iter) { + DeleteObject(iter->second->hFont); + delete iter->second; + } + fontMap_.clear(); + + DeleteObject(ctx_->hbmBitmap); + DeleteDC(ctx_->hDC); +} + +uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) { + std::wstring fname; + if (fontName) + fname = ConvertUTF8ToWString(fontName); + else + fname = L"Tahoma"; + + uint32_t fontHash = hash::Fletcher((const uint8_t *)fontName, strlen(fontName)); + fontHash ^= size; + fontHash ^= flags << 10; + + auto iter = fontMap_.find(fontHash); + if (iter != fontMap_.end()) { + fontHash_ = fontHash; + return fontHash; + } + + TextDrawerFontContext *font = new TextDrawerFontContext(); + + float textScale = 1.0f; + + INT nHeight = -MulDiv( size, (INT)(GetDeviceCaps(ctx_->hDC, LOGPIXELSY) * textScale), 72 ); + int dwBold = FW_LIGHT; ///FW_BOLD + font->hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0, + FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, PROOF_QUALITY, + VARIABLE_PITCH, fname.c_str()); + fontMap_[fontHash] = font; + fontHash_ = fontHash; + return fontHash; +} + +void TextDrawer::SetFont(uint32_t fontHandle) { + auto iter = fontMap_.find(fontHandle); + if (iter != fontMap_.end()) { + fontHash_ = fontHandle; + } +} + +void TextDrawer::MeasureString(const char *str, float *w, float *h) { + auto iter = fontMap_.find(fontHash_); + if (iter != fontMap_.end()) { + SelectObject(ctx_->hDC, iter->second->hFont); + } + + SIZE size; + std::wstring wstr = ConvertUTF8ToWString(str); + GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size); + *w = size.cx * fontScaleX_; + *h = size.cy * fontScaleY_; +} + +void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align) { + uint32_t stringHash = hash::Fletcher((const uint8_t *)str, strlen(str)); + uint32_t entryHash = stringHash ^ fontHash_; + + target.Flush(true); + + TextStringEntry *entry; + + auto iter = cache_.find(entryHash); + if (iter != cache_.end()) { + entry = iter->second; + entry->lastUsedFrame = frameCount_; + glBindTexture(GL_TEXTURE_2D, entry->textureHandle); + } else { + // Render the string to our bitmap and save to a GL texture. + std::wstring wstr = ConvertUTF8ToWString(str); + SIZE size; + + auto iter = fontMap_.find(fontHash_); + if (iter != fontMap_.end()) { + SelectObject(ctx_->hDC, iter->second->hFont); + } + // Set text properties + SetTextColor(ctx_->hDC, 0xFFFFFF); + SetBkColor(ctx_->hDC, 0); + SetTextAlign(ctx_->hDC, TA_TOP); + + GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size); + RECT rc = {0}; + rc.right = size.cx + 4; + rc.bottom = size.cy + 4; + FillRect(ctx_->hDC, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); + ExtTextOut(ctx_->hDC, 0, 0, ETO_OPAQUE | ETO_CLIPPED, NULL, wstr.c_str(), (int)wstr.size(), NULL); + + entry = new TextStringEntry(); + glGenTextures(1, &entry->textureHandle); + glBindTexture(GL_TEXTURE_2D, entry->textureHandle); + entry->width = size.cx; + entry->height = size.cy; + entry->bmWidth = (size.cx + 3) & ~3; + entry->bmHeight = (size.cy + 3) & ~3; + entry->lastUsedFrame = frameCount_; + + // Convert the bitmap to a gl-compatible array of pixels. + uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight]; + + for (int y = 0; y < entry->bmHeight; y++) { + for (int x = 0; x < entry->bmWidth; x++) { + BYTE bAlpha = (BYTE)((ctx_->pBitmapBits[MAX_TEXT_WIDTH * y + x] & 0xff) >> 4); + bitmapData[entry->bmWidth * y + x] = (bAlpha) | 0xfff0; // ^ rand(); + } + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, entry->bmWidth, entry->bmHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, bitmapData); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + delete [] bitmapData; + + cache_[entryHash] = entry; + } + + // Okay, the texture is bound, let's draw. + float w = entry->bmWidth * fontScaleX_; + float h = entry->bmHeight * fontScaleY_; + DrawBuffer::DoAlign(align, &x, &y, &w, &h); + target.DrawTexRect(x, y, x + entry->bmWidth, y + entry->bmHeight, 0.0f, 0.0f, 1.0f, 1.0f, color); + target.Flush(true); +} + +void TextDrawer::OncePerFrame() { + frameCount_++; + // Use a prime number to reduce clashing with other rhythms + if (frameCount_ % 23 == 0) { + for (auto iter = cache_.begin(); iter != cache_.end();) { + if (frameCount_ - iter->second->lastUsedFrame > 100) { + delete iter->second; + cache_.erase(iter++); + } else { + iter++; + } + } + } +} + +#else + +TextDrawer::TextDrawer() { + fontScaleX_ = 1.0f; + fontScaleY_ = 1.0f; +} + +TextDrawer::~TextDrawer() { + +} + +uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) { + ELOG("System fonts not supported on this platform"); + return 0; +} + +void TextDrawer::SetFont(uint32_t fontHandle) { + +} + +void TextDrawer::MeasureString(const char *str, float *w, float *h) { + *w = 0; + *h = 0; +} + +void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align) { + +} + +void TextDrawer::OncePerFrame() { + +} + +#endif + +void TextDrawer::SetFontScale(float xscale, float yscale) { + fontScaleX_ = xscale; + fontScaleY_ = xscale; +} + +void TextDrawer::DrawStringRect(DrawBuffer &target, const char *str, const Bounds &bounds, uint32_t color, int align) { + float x = bounds.x; + float y = bounds.y; + if (align & ALIGN_HCENTER) { + x = bounds.centerX(); + } else if (align & ALIGN_RIGHT) { + x = bounds.x2(); + } + if (align & ALIGN_VCENTER) { + y = bounds.centerY(); + } else if (align & ALIGN_BOTTOM) { + y = bounds.y2(); + } + + DrawString(target, str, x, y, color, align); +} diff --git a/gfx_es2/draw_text.h b/gfx_es2/draw_text.h new file mode 100644 index 0000000000..85e3cad59a --- /dev/null +++ b/gfx_es2/draw_text.h @@ -0,0 +1,65 @@ +// draw_text + +// Uses system fonts to draw text. +// Platform support will be added over time, initially just Win32. + +// Caches strings in individual textures. Might later combine them into a big one +// with dynamically allocated space but too much trouble for now. + +#pragma once + +#include + +#include "base/basictypes.h" +#include "gfx_es2/draw_buffer.h" + +struct TextStringEntry { + uint32_t textureHandle; + int width; + int height; + int bmWidth; + int bmHeight; + int lastUsedFrame; +}; + +// Not yet functional +enum { + FONTSTYLE_BOLD = 1, + FONTSTYLE_ITALIC = 2, +}; + +// Internal struct but all details in .cpp file (pimpl to avoid pulling in excessive headers here) +struct TextDrawerContext; +struct TextDrawerFontContext; + +class TextDrawer { +public: + TextDrawer(); + ~TextDrawer(); + + uint32_t SetFont(const char *fontName, int size, int flags); + void SetFont(uint32_t fontHandle); // Shortcut once you've set the font once. + + void SetFontScale(float xscale, float yscale); + void MeasureString(const char *str, float *w, float *h); + void DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT); + void DrawStringRect(DrawBuffer &target, const char *str, const Bounds &bounds, uint32_t color, int align); + // Use for housekeeping like throwing out old strings. + void OncePerFrame(); + +private: + enum { + MAX_TEXT_WIDTH = 512, + MAX_TEXT_HEIGHT = 128 + }; + int frameCount_; + float fontScaleX_; + float fontScaleY_; + + TextDrawerContext *ctx_; + std::map fontMap_; + + uint32_t fontHash_; + // The key is the CityHash of the string xor the fontHash_. + std::map cache_; +}; \ No newline at end of file diff --git a/native.vcxproj b/native.vcxproj index b67686a97c..6ac3d9d086 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -220,6 +220,7 @@ + @@ -347,6 +348,7 @@ + @@ -382,6 +384,7 @@ + AssemblyAndSourceCode AssemblyAndSourceCode diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 30e2b489d0..9e3b94243d 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -279,6 +279,9 @@ + + gfx + @@ -499,6 +502,12 @@ + + gfx + + + util + diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 7a257f8c7e..f9f1c5e822 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -3,9 +3,35 @@ #include "ui/ui_context.h" #include "gfx/texture.h" #include "gfx_es2/draw_buffer.h" +#include "gfx_es2/draw_text.h" #include "gfx_es2/glsl_program.h" #include "gfx_es2/gl_state.h" +UIContext::UIContext() + : uishader_(0), uitexture_(0), uidrawbuffer_(0), uidrawbufferTop_(0) { + fontScaleX_ = 1.0f; + fontScaleY_ = 1.0f; + fontStyle_ = new UI::FontStyle(); +} + +UIContext::~UIContext() { + delete fontStyle_; + delete textDrawer_; +} + +void UIContext::Init(const GLSLProgram *uishader, const GLSLProgram *uishadernotex, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) { + uishader_ = uishader; + uishadernotex_ = uishadernotex; + uitexture_ = uitexture; + uidrawbuffer_ = uidrawbuffer; + uidrawbufferTop_ = uidrawbufferTop; +#ifdef _WIN32 + textDrawer_ = new TextDrawer(); +#else + textDrawer_ = 0; +#endif +} + void UIContext::Begin() { glstate.blend.enable(); glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -100,6 +126,52 @@ void UIContext::ActivateTopScissor() { } } +void UIContext::SetFontScale(float scaleX, float scaleY) { + fontScaleX_ = scaleX; + fontScaleY_ = scaleY; +} + +void UIContext::SetFontStyle(const UI::FontStyle &fontStyle) { + *fontStyle_ = fontStyle; + if (textDrawer_) { + textDrawer_->SetFontScale(fontScaleX_, fontScaleY_); + Text()->SetFont(fontStyle.fontName.c_str(), fontStyle.sizePts, fontStyle.flags); + } +} + +void UIContext::MeasureText(const UI::FontStyle &style, const char *str, float *x, float *y, int align) const { + if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) { + float sizeFactor = (float)style.sizePts / 24.0f; + Draw()->SetFontScale(fontScaleX_ * sizeFactor, fontScaleY_ * sizeFactor); + Draw()->MeasureText(style.atlasFont, str, x, y); + } else { + textDrawer_->SetFontScale(fontScaleX_, fontScaleY_); + textDrawer_->MeasureString(str, x, y); + } +} + +void UIContext::DrawText(const char *str, float x, float y, uint32_t color, int align) { + if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) { + float sizeFactor = (float)fontStyle_->sizePts / 24.0f; + Draw()->SetFontScale(fontScaleX_ * sizeFactor, fontScaleY_ * sizeFactor); + Draw()->DrawText(fontStyle_->atlasFont, str, x, y, color, align); + } else { + textDrawer_->SetFontScale(fontScaleX_, fontScaleY_); + textDrawer_->DrawString(*Draw(), str, x, y, color, align); + RebindTexture(); + } +} + +void UIContext::DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align) { + if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) { + Draw()->DrawTextRect(fontStyle_->atlasFont, str, bounds.x, bounds.y, bounds.w, bounds.h, color, align); + } else { + textDrawer_->SetFontScale(fontScaleX_, fontScaleY_); + textDrawer_->DrawStringRect(*Draw(), str, bounds, color, align); + RebindTexture(); + } +} + void UIContext::FillRect(const UI::Drawable &drawable, const Bounds &bounds) { switch (drawable.type) { case UI::DRAW_SOLID_COLOR: diff --git a/ui/ui_context.h b/ui/ui_context.h index dce72c62c6..59bbe1fcac 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -2,6 +2,7 @@ #include +#include "base/basictypes.h" #include "math/geom2d.h" #include "gfx/texture_atlas.h" @@ -11,27 +12,22 @@ struct GLSLProgram; class Texture; class DrawBuffer; +class TextDrawer; -// Kind of ugly connection to UI. namespace UI { struct Drawable; struct Theme; + struct FontStyle; } class DrawBuffer; -// Who should own this? Really not sure. class UIContext { public: - UIContext() : uishader_(0), uitexture_(0), uidrawbuffer_(0), uidrawbufferTop_(0) {} + UIContext(); + ~UIContext(); - void Init(const GLSLProgram *uishader, const GLSLProgram *uishadernotex, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) { - uishader_ = uishader; - uishadernotex_ = uishadernotex; - uitexture_ = uitexture; - uidrawbuffer_ = uidrawbuffer; - uidrawbufferTop_ = uidrawbufferTop; - } + void Init(const GLSLProgram *uishader, const GLSLProgram *uishadernotex, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop); void Begin(); void BeginNoTex(); @@ -49,16 +45,24 @@ public: DrawBuffer *Draw() const { return uidrawbuffer_; } DrawBuffer *DrawTop() const { return uidrawbufferTop_; } - const UI::Theme *theme; - // Utility methods + + TextDrawer *Text() const { return textDrawer_; } + + void SetFontStyle(const UI::FontStyle &style); + void SetFontScale(float scaleX, float scaleY); + void MeasureText(const UI::FontStyle &style, const char *str, float *x, float *y, int align = 0) const; + void DrawText(const char *str, float x, float y, uint32_t color, int align = 0); + void DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align = 0); void FillRect(const UI::Drawable &drawable, const Bounds &bounds); - - private: + float fontScaleX_; + float fontScaleY_; + UI::FontStyle *fontStyle_; + TextDrawer *textDrawer_; // TODO: Collect these into a UIContext const GLSLProgram *uishader_; const GLSLProgram *uishadernotex_; diff --git a/ui/view.cpp b/ui/view.cpp index 7e4c7a5de0..077ae29d8c 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -291,7 +291,7 @@ void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const w = img.w; h = img.h; } else { - dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); + dc.MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); } w += 24; h += 16; @@ -319,7 +319,8 @@ void Choice::Draw(UIContext &dc) { dc.Draw()->DrawImage(atlasImage_, bounds_.centerX(), bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER); } else { int paddingX = 12; - dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); } if (selected_) { @@ -330,8 +331,9 @@ void Choice::Draw(UIContext &dc) { void InfoItem::Draw(UIContext &dc) { Item::Draw(dc); int paddingX = 12; - dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); - dc.Draw()->DrawText(dc.theme->uiFont, rightText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); + dc.DrawText(rightText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); // dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y + 2, dc.theme->itemDownStyle.bgColor); } @@ -342,18 +344,14 @@ ItemHeader::ItemHeader(const std::string &text, LayoutParams *layoutParams) } void ItemHeader::Draw(UIContext &dc) { - float scale = 1.0f; - if (dc.theme->uiFontSmaller == dc.theme->uiFont) { - scale = 0.7f; - } - dc.Draw()->SetFontScale(scale, scale); - dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 4, bounds_.centerY(), 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); - dc.Draw()->SetFontScale(1.0f, 1.0f); + dc.SetFontStyle(dc.theme->uiFontSmall); + dc.DrawText(text_.c_str(), bounds_.x + 4, bounds_.centerY(), 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), 0xFFFFFFFF); } void PopupHeader::Draw(UIContext &dc) { - dc.Draw()->DrawText(dc.theme->uiFontSmaller, text_.c_str(), bounds_.x + 12, bounds_.centerY(), dc.theme->popupTitle.fgColor, ALIGN_LEFT | ALIGN_VCENTER); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(text_.c_str(), bounds_.x + 12, bounds_.centerY(), dc.theme->popupTitle.fgColor, ALIGN_LEFT | ALIGN_VCENTER); dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->popupTitle.fgColor); } @@ -368,12 +366,13 @@ void CheckBox::Draw(UIContext &dc) { if (!IsEnabled()) style = dc.theme->itemDisabledStyle; - dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); dc.Draw()->DrawImage(image, bounds_.x2() - paddingX, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); } void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); + dc.MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); } void Button::Draw(UIContext &dc) { @@ -385,11 +384,12 @@ void Button::Draw(UIContext &dc) { // dc.Draw()->DrawImage4Grid(style.image, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); dc.FillRect(style.background, bounds_); float tw, th; - dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &tw, &th); + dc.MeasureText(dc.theme->uiFont, text_.c_str(), &tw, &th); if (tw > bounds_.w) { dc.PushScissor(bounds_); } - dc.Draw()->DrawText(dc.theme->uiFont, text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); if (tw > bounds_.w) { dc.PopScissor(); } @@ -432,26 +432,24 @@ void TextureView::Draw(UIContext &dc) { } void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - dc.Draw()->SetFontScale(textScaleX_, textScaleY_); - dc.Draw()->MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); - dc.Draw()->SetFontScale(1.0f, 1.0f); + dc.MeasureText(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont, text_.c_str(), &w, &h); } void TextView::Draw(UIContext &dc) { - dc.Draw()->SetFontScale(textScaleX_, textScaleY_); - dc.Draw()->DrawTextRect(dc.theme->uiFont, text_.c_str(), bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF, textAlign_); - dc.Draw()->SetFontScale(1.0f, 1.0f); + dc.SetFontStyle(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont); + dc.DrawTextRect(text_.c_str(), bounds_, 0xFFFFFFFF, textAlign_); } void ProgressBar::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - dc.Draw()->MeasureText(dc.theme->uiFont, " 100% ", &w, &h); + dc.MeasureText(dc.theme->uiFont, " 100% ", &w, &h); } void ProgressBar::Draw(UIContext &dc) { char temp[32]; sprintf(temp, "%i%%", (int)(progress_ * 100.0f)); dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y, bounds_.x + bounds_.w * progress_, bounds_.y2(), 0xc0c0c0c0); - dc.Draw()->DrawTextRect(dc.theme->uiFont, temp, bounds_.x, bounds_.y, bounds_.w, bounds_.h, 0xFFFFFFFF, ALIGN_CENTER); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawTextRect(temp, bounds_, 0xFFFFFFFF, ALIGN_CENTER); } void TriggerButton::Touch(const TouchInput &input) { @@ -531,7 +529,8 @@ void Slider::Draw(UIContext &dc) { sprintf(temp, "%i%%", *value_); else sprintf(temp, "%i", *value_); - dc.Draw()->DrawText(dc.theme->uiFont, temp, bounds_.x2() - 22, bounds_.centerY(), 0xFFFFFFFF, ALIGN_CENTER); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(temp, bounds_.x2() - 22, bounds_.centerY(), 0xFFFFFFFF, ALIGN_CENTER); } void Slider::GetContentDimensions(const UIContext &dc, float &w, float &h) const { @@ -579,7 +578,8 @@ void SliderFloat::Draw(UIContext &dc) { dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); char temp[64]; sprintf(temp, "%0.2f", *value_); - dc.Draw()->DrawText(dc.theme->uiFont, temp, bounds_.x2() - 22, bounds_.centerY(), 0xFFFFFFFF, ALIGN_CENTER); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(temp, bounds_.x2() - 22, bounds_.centerY(), 0xFFFFFFFF, ALIGN_CENTER); } void SliderFloat::GetContentDimensions(const UIContext &dc, float &w, float &h) const { diff --git a/ui/view.h b/ui/view.h index a3236b7608..361833836f 100644 --- a/ui/view.h +++ b/ui/view.h @@ -74,11 +74,24 @@ struct Style { int image; // where applicable. }; +struct FontStyle { + FontStyle() : atlasFont(0), sizePts(0), flags(0) {} + FontStyle(const char *name, int size) : atlasFont(0), fontName(name), sizePts(size), flags(0) {} + FontStyle(int atlasFnt, const char *name, int size) : atlasFont(atlasFnt), fontName(name), sizePts(size), flags(0) {} + + int atlasFont; + // For native fonts: + std::string fontName; + int sizePts; + int flags; +}; + + // To use with an UI atlas. struct Theme { - int uiFont; - int uiFontSmall; - int uiFontSmaller; + FontStyle uiFont; + FontStyle uiFontSmall; + FontStyle uiFontSmaller; int checkOn; int checkOff; int sliderKnob; @@ -508,6 +521,7 @@ protected: std::string text_; std::string smallText_; ImageID atlasImage_; + private: bool selected_; }; @@ -604,21 +618,18 @@ private: class TextView : public InertView { public: TextView(const std::string &text, LayoutParams *layoutParams = 0) - : InertView(layoutParams), text_(text), textScaleX_(1.0f), textScaleY_(1.0f), textAlign_(0) {} + : InertView(layoutParams), text_(text), textAlign_(0), small_(false) {} - TextView(const std::string &text, int textAlign, float textScale, LayoutParams *layoutParams = 0) - : InertView(layoutParams), text_(text), textScaleX_(textScale), textScaleY_(textScale), textAlign_(textAlign) {} + TextView(const std::string &text, int textAlign, bool small, LayoutParams *layoutParams = 0) + : InertView(layoutParams), text_(text), textAlign_(textAlign), small_(small) {} virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); void SetText(const std::string &text) { text_ = text; } - void SetTextScaleXY(float sx, float sy) { textScaleX_ = sx; textScaleY_ = sy; } - void SetTextScale(float scale) { textScaleX_ = scale; textScaleY_ = scale; } - + void SetSmall(bool small) { small_ = small; } private: + bool small_; std::string text_; - float textScaleX_; - float textScaleY_; int textAlign_; }; diff --git a/util/hash/hash.cpp b/util/hash/hash.cpp index 277509ac89..911486cdcb 100644 --- a/util/hash/hash.cpp +++ b/util/hash/hash.cpp @@ -4,9 +4,9 @@ namespace hash { // uint32_t -// WARNING - may read one more byte! +// WARNING - may read one more byte! Fine if the input is a null-terminated string. // Implementation from Wikipedia. -uint32 HashFletcher(const uint8 *data_uint8, size_t length) { +uint32 Fletcher(const uint8 *data_uint8, size_t length) { const uint16 *data = (const uint16 *)data_uint8; size_t len = (length + 1) / 2; uint32 sum1 = 0xffff, sum2 = 0xffff; @@ -34,7 +34,7 @@ uint32 HashFletcher(const uint8 *data_uint8, size_t length) { // Slightly slower than Fletcher above, but slighly more reliable. #define MOD_ADLER 65521 // data: Pointer to the data to be summed; len is in bytes -uint32 HashAdler32(const uint8 *data, size_t len) { +uint32 Adler32(const uint8 *data, size_t len) { uint32 a = 1, b = 0; while (len) { size_t tlen = len > 5550 ? 5550 : len; From 00bc06e2972a8647c1d6f922180639eca11a46bc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 30 Aug 2013 15:31:42 +0200 Subject: [PATCH 0645/1445] Win32: Increase size of temporary font rendering bitmap --- gfx_es2/draw_text.cpp | 5 +++++ gfx_es2/draw_text.h | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 1a1eca68c4..2bd5f3f33b 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -9,6 +9,11 @@ #define WIN32_LEAN_AND_MEAN #include +enum { + MAX_TEXT_WIDTH = 1024, + MAX_TEXT_HEIGHT = 128 +}; + struct TextDrawerFontContext { HFONT hFont; }; diff --git a/gfx_es2/draw_text.h b/gfx_es2/draw_text.h index 85e3cad59a..301e16b088 100644 --- a/gfx_es2/draw_text.h +++ b/gfx_es2/draw_text.h @@ -48,10 +48,6 @@ public: void OncePerFrame(); private: - enum { - MAX_TEXT_WIDTH = 512, - MAX_TEXT_HEIGHT = 128 - }; int frameCount_; float fontScaleX_; float fontScaleY_; From b505648c9920659868fff62aba64d68d06895a5b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 30 Aug 2013 17:44:44 +0200 Subject: [PATCH 0646/1445] Fix issues with line breaks in system font --- base/stringutil.cpp | 7 +++++-- gfx_es2/draw_text.cpp | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/base/stringutil.cpp b/base/stringutil.cpp index d3bb4b6923..414fe117c9 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -223,11 +223,14 @@ void SplitString(const std::string& str, const char delim, std::vectorhDC, wstr.c_str(), (int)wstr.size(), &size); *w = size.cx * fontScaleX_; *h = size.cy * fontScaleY_; @@ -129,7 +130,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float glBindTexture(GL_TEXTURE_2D, entry->textureHandle); } else { // Render the string to our bitmap and save to a GL texture. - std::wstring wstr = ConvertUTF8ToWString(str); + std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(str, "\n", "\r\n")); SIZE size; auto iter = fontMap_.find(fontHash_); @@ -141,12 +142,18 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float SetBkColor(ctx_->hDC, 0); SetTextAlign(ctx_->hDC, TA_TOP); - GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size); + RECT textRect = {0}; + DrawTextExW(ctx_->hDC, (LPWSTR)wstr.c_str(), wstr.size(), &textRect, DT_HIDEPREFIX|DT_TOP|DT_LEFT|DT_CALCRECT, 0); + size.cx = textRect.right; + size.cy = textRect.bottom; + + // GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size); RECT rc = {0}; rc.right = size.cx + 4; rc.bottom = size.cy + 4; FillRect(ctx_->hDC, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); - ExtTextOut(ctx_->hDC, 0, 0, ETO_OPAQUE | ETO_CLIPPED, NULL, wstr.c_str(), (int)wstr.size(), NULL); + //ExtTextOut(ctx_->hDC, 0, 0, ETO_OPAQUE | ETO_CLIPPED, NULL, wstr.c_str(), (int)wstr.size(), NULL); + DrawTextExW(ctx_->hDC, (LPWSTR)wstr.c_str(), wstr.size(), &rc, DT_HIDEPREFIX|DT_TOP|DT_LEFT, 0); entry = new TextStringEntry(); glGenTextures(1, &entry->textureHandle); From ed48ad9c223794126939bfdd8a1b5a0023096a9c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 30 Aug 2013 18:14:44 +0200 Subject: [PATCH 0647/1445] Eat lone ampersands, so that we can share strings with the top level Windows menus. --- gfx_es2/draw_buffer.cpp | 6 ++++++ gfx_es2/draw_buffer.h | 1 + util/text/utf8.h | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 900bfafe13..20413f2bdd 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -344,6 +344,9 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { wacc = 0; lines++; continue; + } else if (cval == '&' && utf.peek() != '&') { + // Ignore lone ampersands + continue; } const AtlasChar *c = atlasfont.getChar(cval); if (c) { @@ -414,6 +417,9 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co y += atlasfont.height * fontscaley; x = sx; continue; + } else if (cval == '&' && utf.peek() != '&') { + // Ignore lone ampersands + continue; } const AtlasChar *ch = atlasfont.getChar(cval); if (!ch) diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 64b9c3232b..d75febf6b5 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -35,6 +35,7 @@ enum { // Avoids using system font drawing as it's too slow. // Not actually used here but is reserved for whatever system wraps DrawBuffer. FLAG_DYNAMIC_ASCII = 2048, + FLAG_NO_PREFIX = 4096 // means to not process ampersands }; struct GLSLProgram; diff --git a/util/text/utf8.h b/util/text/utf8.h index 7519526428..32312ee35a 100644 --- a/util/text/utf8.h +++ b/util/text/utf8.h @@ -31,6 +31,10 @@ public: uint32_t next() { return u8_nextchar(c_, &index_); } + uint32_t peek() { + int tempIndex = index_; + return u8_nextchar(c_, &tempIndex); + } int length() const { return u8_strlen(c_); } From f12d369b51b1ec83c26c5a01047d16d1c94f9c49 Mon Sep 17 00:00:00 2001 From: PewnyPL Date: Fri, 30 Aug 2013 18:34:21 +0200 Subject: [PATCH 0648/1445] An (ugly) hack to make some Bluetooth Gamepads to work. The problem with BT gamepads is the fact they tend to show up as multiple gamepads, while PPSSPP only recognises two. Until the whole gamepad code is reworked, this will allow them to work by always returning inputPlayerA in case of an additional recognised gamepad. Fixes issue #3314 --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 90efe45bcf..ae72ed4e40 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -356,7 +356,7 @@ public class NativeActivity extends Activity { return inputPlayerB; } - return null; + return inputPlayerA; } // We grab the keys before onKeyDown/... even see them. This is also better because it lets us From 685a1f7e6f13a4809b3dc1fb845c16a7402c1bff Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 30 Aug 2013 20:18:16 +0200 Subject: [PATCH 0649/1445] Harmonize compiler options, warning fix --- Android.mk | 8 ++++---- ui/ui.cpp | 1 - ui/view.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Android.mk b/Android.mk index 9f2f4baf93..c9552b5fc1 100644 --- a/Android.mk +++ b/Android.mk @@ -79,8 +79,8 @@ LOCAL_SRC_FILES :=\ util/text/utf8.cpp \ util/hash/hash.cpp -LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -frtti +LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -ffast-math -fno-strict-aliasing -Wall -Wno-multichar +LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -fno-rtti -Wno-reorder -Wno-literal-suffix LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip @@ -89,10 +89,10 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) LOCAL_SRC_FILES += math/math_util.cpp -LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM +LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI_V7A -DARMV7 else ifeq ($(TARGET_ARCH_ABI),armeabi) LOCAL_SRC_FILES += math/math_utilarmv6.cpp -LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM +LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI else ifeq ($(TARGET_ARCH_ABI),x86) LOCAL_SRC_FILES += math/math_util.cpp LOCAL_CFLAGS := $(LOCAL_CFLAGS) -D_M_IX86 diff --git a/ui/ui.cpp b/ui/ui.cpp index 80a1f5166c..08520698a2 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -471,7 +471,6 @@ int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) { if (inertiaY > 20) inertiaY = 20; if (inertiaY < -20) inertiaY = -20; - float mouseY = uistate.mousey[0]; if (!uistate.mousedown[0]) { // Let it slide if the pointer is not down scrollY += inertiaY; diff --git a/ui/view.h b/ui/view.h index 361833836f..c0d78fa434 100644 --- a/ui/view.h +++ b/ui/view.h @@ -628,9 +628,9 @@ public: void SetText(const std::string &text) { text_ = text; } void SetSmall(bool small) { small_ = small; } private: - bool small_; std::string text_; int textAlign_; + bool small_; }; enum ImageSizeMode { From 9282fa59cadc1faad6c247d413fb96231293acd2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 30 Aug 2013 22:42:02 +0200 Subject: [PATCH 0650/1445] Allow centering text on choices --- ui/view.cpp | 6 +++++- ui/view.h | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 077ae29d8c..bd5dc891be 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -320,7 +320,11 @@ void Choice::Draw(UIContext &dc) { } else { int paddingX = 12; dc.SetFontStyle(dc.theme->uiFont); - dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + if (centered_) { + dc.DrawText(text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); + } else { + dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); + } } if (selected_) { diff --git a/ui/view.h b/ui/view.h index c0d78fa434..d99624d857 100644 --- a/ui/view.h +++ b/ui/view.h @@ -504,15 +504,18 @@ public: class Choice : public ClickableItem { public: Choice(const std::string &text, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), selected_(false) {} + : ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), selected_(false), centered_(false) {} Choice(const std::string &text, const std::string &smallText, bool selected = false, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), selected_(selected) {} + : ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), selected_(selected), centered_(false) {} Choice(ImageID image, LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), atlasImage_(image), selected_(false) {} virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); + virtual void SetCentered(bool c) { + centered_ = c; + } protected: // hackery @@ -521,6 +524,7 @@ protected: std::string text_; std::string smallText_; ImageID atlasImage_; + bool centered_; private: bool selected_; From dc5f2a662b56b4e3b73d9d37a0e094277d294d25 Mon Sep 17 00:00:00 2001 From: wuspring Date: Sat, 31 Aug 2013 05:33:23 +0800 Subject: [PATCH 0651/1445] Update UI_Screen.cpp for the "OK" and "Cancel" button in Dialoag can be translatable. --- ui/ui_screen.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 5f677dca3b..ee1d46f10f 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -3,6 +3,7 @@ #include "ui/ui_screen.h" #include "ui/ui_context.h" #include "ui/screen.h" +#include "i18n/i18n.h" UIScreen::UIScreen() : Screen(), root_(0), recreateViews_(true), hatDown_(0) { @@ -99,7 +100,11 @@ UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { } PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2) - : title_(title), button1_(button1), button2_(button2), box_(0) {} + : title_(title), box_(0) { + I18NCategory *d = GetI18NCategory("Dialog"); + button1_ = d->T(button1.c_str()); + button2_ = d->T(button2.c_str()); +} void PopupScreen::touch(const TouchInput &touch) { if (!box_ || (touch.flags & TOUCH_DOWN) == 0 || touch.id != 0) { From 28826069d67992d00952454dceb478b73b1ef7d3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 31 Aug 2013 01:00:45 -0700 Subject: [PATCH 0652/1445] Warning fix. --- gfx_es2/draw_text.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index f531bca2eb..0acac10a8d 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -143,7 +143,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float SetTextAlign(ctx_->hDC, TA_TOP); RECT textRect = {0}; - DrawTextExW(ctx_->hDC, (LPWSTR)wstr.c_str(), wstr.size(), &textRect, DT_HIDEPREFIX|DT_TOP|DT_LEFT|DT_CALCRECT, 0); + DrawTextExW(ctx_->hDC, (LPWSTR)wstr.c_str(), (int)wstr.size(), &textRect, DT_HIDEPREFIX|DT_TOP|DT_LEFT|DT_CALCRECT, 0); size.cx = textRect.right; size.cy = textRect.bottom; @@ -153,7 +153,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float rc.bottom = size.cy + 4; FillRect(ctx_->hDC, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); //ExtTextOut(ctx_->hDC, 0, 0, ETO_OPAQUE | ETO_CLIPPED, NULL, wstr.c_str(), (int)wstr.size(), NULL); - DrawTextExW(ctx_->hDC, (LPWSTR)wstr.c_str(), wstr.size(), &rc, DT_HIDEPREFIX|DT_TOP|DT_LEFT, 0); + DrawTextExW(ctx_->hDC, (LPWSTR)wstr.c_str(), (int)wstr.size(), &rc, DT_HIDEPREFIX|DT_TOP|DT_LEFT, 0); entry = new TextStringEntry(); glGenTextures(1, &entry->textureHandle); From 4df34ffc014e2765b45d72f94dc23925f8b13ece Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 31 Aug 2013 01:00:57 -0700 Subject: [PATCH 0653/1445] Correctly resize text on Android / non sys fonts. --- ui/ui_context.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index f9f1c5e822..a34d881f93 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -164,6 +164,8 @@ void UIContext::DrawText(const char *str, float x, float y, uint32_t color, int void UIContext::DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align) { if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) { + float sizeFactor = (float)fontStyle_->sizePts / 24.0f; + Draw()->SetFontScale(fontScaleX_ * sizeFactor, fontScaleY_ * sizeFactor); Draw()->DrawTextRect(fontStyle_->atlasFont, str, bounds.x, bounds.y, bounds.w, bounds.h, color, align); } else { textDrawer_->SetFontScale(fontScaleX_, fontScaleY_); From faf9714b563fb6343fe6d17305330bc715d8e532 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 31 Aug 2013 23:16:20 +0200 Subject: [PATCH 0654/1445] -ffast-math doesn't seem like a good idea. --- Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index c9552b5fc1..e17e64e6a9 100644 --- a/Android.mk +++ b/Android.mk @@ -79,7 +79,7 @@ LOCAL_SRC_FILES :=\ util/text/utf8.cpp \ util/hash/hash.cpp -LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -ffast-math -fno-strict-aliasing -Wall -Wno-multichar +LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -Wall -Wno-multichar LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -fno-rtti -Wno-reorder -Wno-literal-suffix LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip From 0d2699614691d71db6bfd8bbf5e46973d343c05e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 4 Sep 2013 10:50:00 +0200 Subject: [PATCH 0655/1445] Add isTopLevel query for screens --- ui/screen.cpp | 2 +- ui/screen.h | 6 ++++-- ui/ui_screen.h | 14 +++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index 22b6ed9cdc..c9dfd8af89 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -111,7 +111,7 @@ void ScreenManager::deviceLost() { // TODO: Change this when it becomes necessary. } -Screen *ScreenManager::topScreen() { +Screen *ScreenManager::topScreen() const { if (!stack_.empty()) return stack_.back().screen; else diff --git a/ui/screen.h b/ui/screen.h index 40a3fed67c..9b4adcf905 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -53,7 +53,8 @@ public: virtual void *dialogData() { return 0; } - virtual bool isTransparent() { return false; } + virtual bool isTransparent() const { return false; } + virtual bool isTopLevel() const { return false; } private: ScreenManager *screenManager_; @@ -99,11 +100,12 @@ public: // Generic facility for gross hacks :P void sendMessage(const char *msg, const char *value); + Screen *topScreen() const; + private: void pop(); void switchToNext(); void processFinishDialog(); - Screen *topScreen(); Screen *nextScreen_; UIContext *uiContext_; diff --git a/ui/ui_screen.h b/ui/ui_screen.h index e4eee000a8..c71f5d0cc5 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -44,12 +44,12 @@ public: virtual void CreatePopupContents(UI::ViewGroup *parent) = 0; virtual void CreateViews(); - virtual bool isTransparent() { return true; } + virtual bool isTransparent() const { return true; } virtual void touch(const TouchInput &touch); protected: - virtual bool FillVertical() { return false; } - virtual bool ShowButtons() { return true; } + virtual bool FillVertical() const { return false; } + virtual bool ShowButtons() const { return true; } virtual void OnCompleted(DialogResult result) {} private: @@ -72,8 +72,8 @@ public: UI::Event OnChoice; protected: - virtual bool FillVertical() { return true; } - virtual bool ShowButtons() { return showButtons_; } + virtual bool FillVertical() const { return true; } + virtual bool ShowButtons() const { return showButtons_; } void CreatePopupContents(UI::ViewGroup *parent); UI::StringVectorListAdaptor adaptor_; UI::ListView *listView_; @@ -91,8 +91,8 @@ public: UI::Event OnChoice; protected: - virtual bool FillVertical() { return false; } - virtual bool ShowButtons() { return true; } + virtual bool FillVertical() const { return false; } + virtual bool ShowButtons() const { return true; } void CreatePopupContents(UI::ViewGroup *parent); private: From 1790bd8b7ef1318abccc4d92ad5b89464d42fd0e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 4 Sep 2013 11:28:19 +0200 Subject: [PATCH 0656/1445] Replace System_GetName with System_GetProperty so we can return more info --- android/app-android.cpp | 12 ++++++++++-- base/BlackberryMain.cpp | 11 +++++++++-- base/NativeApp.h | 8 +++++++- base/PCMain.cpp | 14 +++++++++----- base/QtMain.cpp | 21 ++++++++++++++------- native.vcxproj | 12 ++++++++++++ native.vcxproj.filters | 2 ++ 7 files changed, 63 insertions(+), 17 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 94e4bf9efc..696e8005d0 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -32,6 +32,7 @@ std::string frameCommand; std::string frameCommandParam; std::string systemName; +std::string langRegion; const bool extraLog = true; @@ -86,8 +87,15 @@ void System_InputBox(const char *title, const char *defaultValue) { frameCommandParam = title; } -std::string System_GetName() { - return systemName; +std::string System_GetProperty(SystemProperty prop) { + switch (prop) { + case SYSPROP_NAME: + return systemName; + case SYSPROP_LANGREGION: // "en_US" + return langRegion; + default: + return ""; + } } // Remember that all of these need initialization on init! The process diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 6263fa3498..65b74f5cff 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -13,8 +13,15 @@ // Simple implementations of System functions -std::string System_GetName() { - return "Blackberry10"; +std::string System_GetProperty(SystemProperty prop) { + switch (prop) { + case SYSPROP_NAME: + return "Blackberry10"; + case SYSPROP_LANGREGION: + return "en_US"; + default: + return ""; + } } void SystemToast(const char *text) { diff --git a/base/NativeApp.h b/base/NativeApp.h index ca7bdad320..5c4f6522ca 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -97,4 +97,10 @@ void LaunchBrowser(const char *url); void LaunchMarket(const char *url); void LaunchEmail(const char *email_address); void System_InputBox(const char *title, const char *defaultValue); -std::string System_GetName(); \ No newline at end of file + +enum SystemProperty { + SYSPROP_NAME, + SYSPROP_LANGREGION, +}; + +std::string System_GetProperty(SystemProperty prop); \ No newline at end of file diff --git a/base/PCMain.cpp b/base/PCMain.cpp index c0b82c2148..544f6b5938 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -251,13 +251,17 @@ void LaunchEmail(const char *email_address) #endif } -std::string System_GetName() { - // TODO - return "SDL"; +std::string System_GetProperty(SystemProperty prop) { + switch (prop) { + case SYSPROP_NAME: + return "SDL:"; + case SYSPROP_LANGREGION: + return "en_US"; + default: + return ""; + } } - - InputState input_state; diff --git a/base/QtMain.cpp b/base/QtMain.cpp index b4175a80dc..5170f1c99b 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -19,20 +19,27 @@ InputState* input_state; -std::string System_GetName() { +std::string System_GetProperty(SystemProperty prop) { + switch (prop) { + case SYSPROP_NAME: #ifdef __SYMBIAN32__ - return "Qt:Symbian"; + return "Qt:Symbian"; #elif defined(BLACKBERRY) - return "Qt:Blackberry10"; + return "Qt:Blackberry10"; #elif defined(MEEGO_EDITION_HARMATTAN) - return "Qt:Meego"; + return "Qt:Meego"; #elif defined(Q_WS_X11) - return "Qt:Linux"; + return "Qt:Linux"; #elif defined(_WIN32) - return "Qt:Windows"; + return "Qt:Windows"; #else - return "Qt"; + return "Qt"; #endif + case SYSPROP_LANGREGION: + return "en_US"; + default: + return ""; + } } void LaunchBrowser(const char *url) diff --git a/native.vcxproj b/native.vcxproj index 6ac3d9d086..68e8fd52e6 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -163,6 +163,12 @@ + + true + true + true + true + @@ -301,6 +307,12 @@ true true + + true + true + true + true + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 9e3b94243d..1df5dde379 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -18,6 +18,7 @@ ui + @@ -508,6 +509,7 @@ util + From fee82ce2883af4627dd23060cf76226594925482 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 4 Sep 2013 12:07:05 +0200 Subject: [PATCH 0657/1445] Fetch language/region code, fix bug in VFSGetFileInfo --- android/app-android.cpp | 3 ++- .../com/henrikrydgard/libnative/NativeActivity.java | 6 ++++-- .../src/com/henrikrydgard/libnative/NativeApp.java | 2 +- file/zip_read.cpp | 5 ++++- i18n/i18n.cpp | 11 +++++++++++ i18n/i18n.h | 1 + 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 696e8005d0..59f10dff0d 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -143,7 +143,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioConfig } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init - (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring jdevicetype, jstring japkpath, + (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring jdevicetype, jstring jlangRegion, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; @@ -167,6 +167,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); systemName = GetJavaString(env, jdevicetype); + langRegion = GetJavaString(env, jlangRegion); std::string externalDir = GetJavaString(env, jexternalDir); std::string user_data_path = GetJavaString(env, jdataDir) + "/"; diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index ae72ed4e40..f0cb66d8d6 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.lang.reflect.Field; import java.util.List; +import java.util.Locale; import java.util.UUID; import android.annotation.SuppressLint; @@ -193,10 +194,11 @@ public class NativeActivity extends Activity { int dpi = metrics.densityDpi; String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; - + String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); + // INIT! NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(scrWidth, scrHeight, dpi, deviceType, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); + NativeApp.init(scrWidth, scrHeight, dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); Log.i(TAG, "Device: " + deviceType); Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat + " dpi: " + dpi); diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 62e9e3af5b..a39e00ea45 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -1,7 +1,7 @@ package com.henrikrydgard.libnative; public class NativeApp { - public static native void init(int xxres, int yyres, int dpi, String deviceType, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); + public static native void init(int xxres, int yyres, int dpi, String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); public static native void resized(int xxres, int yyres); diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 4d2664d442..44c9ac491f 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -278,7 +278,10 @@ bool VFSGetFileInfo(const char *path, FileInfo *info) int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(path, entries[i].prefix, prefix_len)) { - return entries[i].reader->GetFileInfo(path + prefix_len, info); + if (entries[i].reader->GetFileInfo(path + prefix_len, info)) + return true; + else + continue; } } ELOG("Missing filesystem for %s", path); diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp index 7bfa5ae5d7..44d2769fa5 100644 --- a/i18n/i18n.cpp +++ b/i18n/i18n.cpp @@ -1,6 +1,7 @@ #include "base/logging.h" #include "i18n/i18n.h" #include "file/ini_file.h" +#include "file/vfs.h" I18NRepo i18nrepo; @@ -56,6 +57,16 @@ std::string I18NRepo::GetIniPath(const std::string &languageID) const { return "lang/" + languageID + ".ini"; } +bool I18NRepo::IniExists(const std::string &languageID) const { + FileInfo info; + if (!VFSGetFileInfo(GetIniPath(languageID).c_str(), &info)) + return false; + if (!info.exists) + return false; + return true; +} + + bool I18NRepo::LoadIni(const std::string &languageID) { IniFile ini; if (!ini.LoadFromVFS(GetIniPath(languageID))) { diff --git a/i18n/i18n.h b/i18n/i18n.h index b91d6840da..052f6221c4 100644 --- a/i18n/i18n.h +++ b/i18n/i18n.h @@ -62,6 +62,7 @@ public: I18NRepo() {} ~I18NRepo(); + bool IniExists(const std::string &languageID) const; bool LoadIni(const std::string &languageID); // NOT the filename! void SaveIni(const std::string &languageID); From 8cf9d3aef5d3cf5803d3f37ff0d8102f916f8da7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 4 Sep 2013 12:38:11 +0200 Subject: [PATCH 0658/1445] Respect font scale properly in textdrawer --- gfx_es2/draw_text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 0acac10a8d..83d39459a0 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -189,7 +189,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float float w = entry->bmWidth * fontScaleX_; float h = entry->bmHeight * fontScaleY_; DrawBuffer::DoAlign(align, &x, &y, &w, &h); - target.DrawTexRect(x, y, x + entry->bmWidth, y + entry->bmHeight, 0.0f, 0.0f, 1.0f, 1.0f, color); + target.DrawTexRect(x, y, x + w, y + h, 0.0f, 0.0f, 1.0f, 1.0f, color); target.Flush(true); } From 107d2986d49322f8e258f3c5af7773a5dfce046b Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 5 Sep 2013 15:03:51 +0800 Subject: [PATCH 0659/1445] Add glstate.alphaTestQCOM & alphaFuncQCOM --- gfx_es2/gl_state.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index a6b7a53bf6..bdba14f99d 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -267,6 +267,12 @@ public: STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp; STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; +#ifdef ANDROID + // QCOM Alpha Test + BoolState alphaTestQCOM; + STATE2(glAlphaFuncQCOM, GLenum, GLclampf, GL_ALWAYS, 0.0f) alphaFuncQCOM; +#endif + // Only works on Win32, all other platforms are "force-vsync" void SetVSyncInterval(int interval); // one of the above VSYNC, or a higher number for multi-frame waits (could be useful for 30hz games) }; From bb028539174e2071dd8450077268c090a9cba025 Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 5 Sep 2013 15:05:28 +0800 Subject: [PATCH 0660/1445] Restore() for alphaTestQCOM & alphaFuncQCOM --- gfx_es2/gl_state.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 4c905f91d1..2a1cfcd3d0 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -47,6 +47,13 @@ void OpenGLState::Restore() { logicOp.restore(); count++; #endif +#ifdef ANDROID + if (gl_extensions.QCOM_alpha_test) { + alphaTestQCOM.restore(); count++; + alphaFuncQCOM.restore(); count++; + } +#endif + scissorTest.restore(); count++; scissorRect.restore(); count++; From 51725a2588f4a06447c6bf38489aead9e009cfad Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 5 Sep 2013 16:03:47 +0800 Subject: [PATCH 0661/1445] Add gl_extensions.QCOM_binning_control --- gfx_es2/gl_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 2a1cfcd3d0..cf538bc596 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -139,7 +139,7 @@ void CheckGLExtensions() { if (gl_extensions.OES_mapbuffer) { glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" ); } - + gl_extensions.QCOM_binning_control = strstr(extString, "GL_QCOM_binning_control") != 0; gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0; // Load extensions that are not auto-loaded by Android. if (gl_extensions.QCOM_alpha_test) { From c130e1ed0f01aec3522ea51d7303b3d10cf34c91 Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 5 Sep 2013 16:06:07 +0800 Subject: [PATCH 0662/1445] Add hints for GL_QCOM_binning_control --- gfx_es2/gl_state.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index bdba14f99d..ab5bce7ed2 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -11,9 +11,16 @@ // Additional extensions not included in GLES2/gl2ext.h from the NDK /* GL_QCOM_alpha_test */ -#define GL_ALPHA_TEST_QCOM 0x0BC0 -#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 -#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 +#define GL_ALPHA_TEST_QCOM 0x0BC0 +#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 +#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 + +/* GL_QCOM_binning_control */ +#define BINNING_CONTROL_HINT_QCOM 0x8FB0 +#define CPU_OPTIMIZED_QCOM 0x8FB1 +#define GPU_OPTIMIZED_QCOM 0x8FB2 +#define RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3 +#define DONT_CARE 0x1100 typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); extern PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; @@ -293,6 +300,7 @@ struct GLExtensions { bool FBO_EXT; bool EXT_swap_control_tear; bool QCOM_alpha_test; + bool QCOM_binning_control; bool OES_mapbuffer; bool OES_vertex_array_object; From b16ff1362de4c9f4a244ad0d0c5e59f0a6d22bda Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 5 Sep 2013 16:23:01 +0800 Subject: [PATCH 0663/1445] 'Don't Care' token should not require since it is default --- gfx_es2/gl_state.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index ab5bce7ed2..7ee8d519eb 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -11,16 +11,15 @@ // Additional extensions not included in GLES2/gl2ext.h from the NDK /* GL_QCOM_alpha_test */ -#define GL_ALPHA_TEST_QCOM 0x0BC0 -#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 -#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 +#define GL_ALPHA_TEST_QCOM 0x0BC0 +#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 +#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 /* GL_QCOM_binning_control */ -#define BINNING_CONTROL_HINT_QCOM 0x8FB0 -#define CPU_OPTIMIZED_QCOM 0x8FB1 -#define GPU_OPTIMIZED_QCOM 0x8FB2 -#define RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3 -#define DONT_CARE 0x1100 +#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0 +#define GL_CPU_OPTIMIZED_QCOM 0x8FB1 +#define GL_GPU_OPTIMIZED_QCOM 0x8FB2 +#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3 typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); extern PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; From 0b752abc4139a24d705a4a059af76b98d030c6f7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 6 Sep 2013 23:16:44 +0200 Subject: [PATCH 0664/1445] Fix android build on non-QCOM (it failed the gstate count check). --- gfx_es2/gl_state.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index cf538bc596..6a5548a0f2 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -49,9 +49,13 @@ void OpenGLState::Restore() { #ifdef ANDROID if (gl_extensions.QCOM_alpha_test) { - alphaTestQCOM.restore(); count++; - alphaFuncQCOM.restore(); count++; + alphaTestQCOM.restore(); } + count++; + if (gl_extensions.QCOM_alpha_test) { + alphaFuncQCOM.restore(); + } + count++; #endif scissorTest.restore(); count++; From 997aae346bae42ef5a8d047bb3d09d757385d855 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 7 Sep 2013 13:38:12 +0200 Subject: [PATCH 0665/1445] Move some popup utility classes here --- ui/ui_screen.cpp | 70 +++++++++++++++++++++++++++++++++++++++++ ui/ui_screen.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 148 insertions(+), 3 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index ee1d46f10f..5626e9012e 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -4,6 +4,7 @@ #include "ui/ui_context.h" #include "ui/screen.h" #include "i18n/i18n.h" +#include "gfx_es2/draw_buffer.h" UIScreen::UIScreen() : Screen(), root_(0), recreateViews_(true), hatDown_(0) { @@ -189,6 +190,73 @@ UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) { return UI::EVENT_DONE; } +namespace UI { + +UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) { + std::vector choices; + for (int i = 0; i < numChoices_; i++) { + choices.push_back(category_ ? category_->T(choices_[i]) : choices_[i]); + } + + Screen *popupScreen = new ListPopupScreen(text_, choices, *value_ - minVal_, + std::bind(&PopupMultiChoice::ChoiceCallback, this, placeholder::_1)); + screenManager_->push(popupScreen); + return UI::EVENT_DONE; +} + +void PopupMultiChoice::UpdateText() { + valueText_ = category_ ? category_->T(choices_[*value_ - minVal_]) : choices_[*value_ - minVal_]; +} + +void PopupMultiChoice::ChoiceCallback(int num) { + if (num != -1) { + *value_ = num + minVal_; + UpdateText(); + + UI::EventParams e; + e.v = this; + e.a = num; + OnChoice.Trigger(e); + } +} + +void PopupMultiChoice::Draw(UIContext &dc) { + Choice::Draw(dc); + int paddingX = 12; + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(valueText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); +} + + +EventReturn PopupSliderChoice::HandleClick(EventParams &e) { + Screen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_); + screenManager_->push(popupScreen); + return EVENT_DONE; +} + + +void PopupSliderChoice::Draw(UIContext &dc) { + Choice::Draw(dc); + char temp[32]; + sprintf(temp, "%i", *value_); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); +} + +EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) { + Screen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_); + screenManager_->push(popupScreen); + return EVENT_DONE; +} + +void PopupSliderChoiceFloat::Draw(UIContext &dc) { + Choice::Draw(dc); + char temp[32]; + sprintf(temp, "%2.2f", *value_); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); +} + void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; sliderValue_ = *value_; @@ -212,3 +280,5 @@ void SliderFloatPopupScreen::OnCompleted(DialogResult result) { if (result == DR_OK) *value_ = sliderValue_; } + +} // namespace UI \ No newline at end of file diff --git a/ui/ui_screen.h b/ui/ui_screen.h index c71f5d0cc5..e761afb33d 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -3,6 +3,8 @@ #include "ui/screen.h" #include "ui/viewgroup.h" +class I18NCategory; + class UIScreen : public Screen { public: UIScreen(); @@ -102,14 +104,16 @@ private: // TODO: Need a way to translate OK and Cancel +namespace UI { + class SliderPopupScreen : public PopupScreen { public: SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title) : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue) {} - void CreatePopupContents(UI::ViewGroup *parent); + void CreatePopupContents(ViewGroup *parent); private: virtual void OnCompleted(DialogResult result); - UI::Slider *slider_; + Slider *slider_; int *value_; int sliderValue_; int minValue_; @@ -128,4 +132,75 @@ private: float *value_; float minValue_; float maxValue_; -}; \ No newline at end of file +}; + +// Reads and writes value to determine the current selection. +class PopupMultiChoice : public UI::Choice { +public: + PopupMultiChoice(int *value, const std::string &text, const char **choices, int minVal, int numChoices, + I18NCategory *category, ScreenManager *screenManager, UI::LayoutParams *layoutParams = 0) + : UI::Choice(text, "", false, layoutParams), value_(value), choices_(choices), minVal_(minVal), numChoices_(numChoices), + category_(category), screenManager_(screenManager) { + if (*value >= numChoices+minVal) *value = numChoices+minVal-1; + if (*value < minVal) *value = minVal; + OnClick.Handle(this, &PopupMultiChoice::HandleClick); + UpdateText(); + } + + virtual void Draw(UIContext &dc); + + UI::Event OnChoice; + +private: + void UpdateText(); + UI::EventReturn HandleClick(UI::EventParams &e); + + void ChoiceCallback(int num); + + int *value_; + const char **choices_; + int minVal_; + int numChoices_; + I18NCategory *category_; + ScreenManager *screenManager_; + std::string valueText_; +}; + + +class PopupSliderChoice : public Choice { +public: + PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0) + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) { + OnClick.Handle(this, &PopupSliderChoice::HandleClick); + } + + void Draw(UIContext &dc); + +private: + EventReturn HandleClick(EventParams &e); + + int *value_; + int minValue_; + int maxValue_; + ScreenManager *screenManager_; +}; + +class PopupSliderChoiceFloat : public Choice { +public: + PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0) + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) { + OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); + } + + void Draw(UIContext &dc); + +private: + EventReturn HandleClick(EventParams &e); + + float *value_; + float minValue_; + float maxValue_; + ScreenManager *screenManager_; +}; + +} // namespace UI \ No newline at end of file From c9dcf024b922b8866e69dcf9d76ad6e16f9a8a35 Mon Sep 17 00:00:00 2001 From: Vality Date: Mon, 9 Sep 2013 23:48:08 +0100 Subject: [PATCH 0666/1445] Disabled (forced to 1) broken scaling on Linux Qt environments. --- base/QtMain.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 5170f1c99b..11d12ffd4f 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -84,8 +84,11 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); - +#ifdef defined(Q_WS_X11) + g_dpi_scale = 1.0f; +#else g_dpi_scale = CalculateDPIScale(); +#endif dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); #ifdef __SYMBIAN32__ From bf065b74041dfa65305f902f83acd9c15401e09c Mon Sep 17 00:00:00 2001 From: Vality Date: Mon, 9 Sep 2013 23:48:35 +0100 Subject: [PATCH 0667/1445] Update QtMain.cpp --- base/QtMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 11d12ffd4f..cf5c85b7e1 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -84,7 +84,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); -#ifdef defined(Q_WS_X11) +#ifdef Q_WS_X11 g_dpi_scale = 1.0f; #else g_dpi_scale = CalculateDPIScale(); From d43247f4a0f53666c843ac4ce57b7c2e2e1e2b03 Mon Sep 17 00:00:00 2001 From: Vality Date: Tue, 10 Sep 2013 08:22:33 +0100 Subject: [PATCH 0668/1445] Updated ifdef to exclude mobile platforms. --- base/QtMain.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index cf5c85b7e1..69abb96679 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -17,6 +17,10 @@ #endif #include "QtMain.h" +#if defined(Q_WS_X11) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(__SYMBIAN32__) && !defined(BLACKBERRY) +#define X11LINUXDESKTOP +#endif + InputState* input_state; std::string System_GetProperty(SystemProperty prop) { @@ -84,7 +88,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); -#ifdef Q_WS_X11 +#ifdef X11LINUXDESKTOP g_dpi_scale = 1.0f; #else g_dpi_scale = CalculateDPIScale(); From 080fa6ff78718e2229ff786cbaa1a9daa6a6f5eb Mon Sep 17 00:00:00 2001 From: Zetro Date: Tue, 10 Sep 2013 19:24:03 +0200 Subject: [PATCH 0669/1445] Add uppercase keys in Qt->native key mapping --- base/NKCodeFromQt.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/base/NKCodeFromQt.h b/base/NKCodeFromQt.h index 63553582c4..0c1176f9ac 100644 --- a/base/NKCodeFromQt.h +++ b/base/NKCodeFromQt.h @@ -3,6 +3,32 @@ // TODO: Add any missing keys static const std::map KeyMapRawQttoNative = InitConstMap + (Qt::Key_P, NKCODE_P) + (Qt::Key_O, NKCODE_O) + (Qt::Key_I, NKCODE_I) + (Qt::Key_U, NKCODE_U) + (Qt::Key_Y, NKCODE_Y) + (Qt::Key_T, NKCODE_T) + (Qt::Key_R, NKCODE_R) + (Qt::Key_E, NKCODE_E) + (Qt::Key_W, NKCODE_W) + (Qt::Key_Q, NKCODE_Q) + (Qt::Key_L, NKCODE_L) + (Qt::Key_K, NKCODE_K) + (Qt::Key_J, NKCODE_J) + (Qt::Key_H, NKCODE_H) + (Qt::Key_G, NKCODE_G) + (Qt::Key_F, NKCODE_F) + (Qt::Key_D, NKCODE_D) + (Qt::Key_S, NKCODE_S) + (Qt::Key_A, NKCODE_A) + (Qt::Key_M, NKCODE_M) + (Qt::Key_N, NKCODE_N) + (Qt::Key_B, NKCODE_B) + (Qt::Key_V, NKCODE_V) + (Qt::Key_C, NKCODE_C) + (Qt::Key_X, NKCODE_X) + (Qt::Key_Z, NKCODE_Z) (Qt::Key_P + 0x20, NKCODE_P) (Qt::Key_O + 0x20, NKCODE_O) (Qt::Key_I + 0x20, NKCODE_I) From 4b39a99110b6affc3a76887f39b89ff5444db2bf Mon Sep 17 00:00:00 2001 From: wuspring Date: Wed, 11 Sep 2013 17:19:41 +0800 Subject: [PATCH 0670/1445] Shorten the slider, at maxvalue, it doesn't cover the text now. --- ui/view.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/view.h b/ui/view.h index d99624d857..69628ffc27 100644 --- a/ui/view.h +++ b/ui/view.h @@ -426,7 +426,7 @@ private: class Slider : public Clickable { public: Slider(int *value, int minValue, int maxValue, LayoutParams *layoutParams = 0) - : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(50) {} + : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) {} virtual void Draw(UIContext &dc); virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); @@ -445,7 +445,7 @@ private: class SliderFloat : public Clickable { public: SliderFloat(float *value, float minValue, float maxValue, LayoutParams *layoutParams = 0) - : Clickable(layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(50) {} + : Clickable(layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) {} virtual void Draw(UIContext &dc); virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); From 1eeaf32822ccd494cacda3813a76aa098b31c1e7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 11 Sep 2013 21:33:29 +0200 Subject: [PATCH 0671/1445] Make CheckExtensions safe from broken drivers --- gfx_es2/gl_state.cpp | 23 +++++++++++++++-------- gfx_es2/gl_state.h | 4 ++-- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 6a5548a0f2..bd06890537 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -37,16 +37,12 @@ void OpenGLState::Initialize() { void OpenGLState::Restore() { int count = 0; + blend.restore(); count++; blendEquation.restore(); count++; blendFuncSeparate.restore(); count++; blendColor.restore(); count++; -#if !defined(USING_GLES2) - colorLogicOp.restore(); count++; - logicOp.restore(); count++; -#endif - #ifdef ANDROID if (gl_extensions.QCOM_alpha_test) { alphaTestQCOM.restore(); @@ -79,6 +75,11 @@ void OpenGLState::Restore() { dither.restore(); count++; +#if !defined(USING_GLES2) + colorLogicOp.restore(); count++; + logicOp.restore(); count++; +#endif + if (count != state_count) { FLOG("OpenGLState::Restore is missing some states"); } @@ -102,7 +103,9 @@ void CheckGLExtensions() { } #ifdef WIN32 - const char *wglString = wglGetExtensionsStringEXT(); + const char *wglString = 0; + if (wglGetExtensionsStringEXT) + wglString = wglGetExtensionsStringEXT(); if (wglString) { gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0; g_all_egl_extensions = wglString; @@ -174,8 +177,12 @@ void CheckGLExtensions() { gl_extensions.FBO_ARB = true; gl_extensions.FBO_EXT = false; #else - gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; - gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; + gl_extensions.FBO_ARB = false; + gl_extensions.FBO_EXT = false; + if (extString) { + gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; + gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; + } #endif } diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 7ee8d519eb..8094dcd45b 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -62,7 +62,7 @@ private: public: BoolState() : _value(init) { OpenGLState::state_count++; - } + } inline void set(bool value) { if(value && value != _value) { @@ -100,7 +100,7 @@ private: public: \ SavedState1_##func() : p1(p1def) { \ OpenGLState::state_count++; \ - }; \ + }; \ void set(p1type newp1) { \ if(newp1 != p1) { \ p1 = newp1; \ From f1b7580be8d6d51adb9769cfb7d9d60d3dbf4496 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 11 Sep 2013 22:15:10 +0200 Subject: [PATCH 0672/1445] Workaround some obscure crashes reported through Android crash reporting --- .../com/henrikrydgard/libnative/NativeActivity.java | 13 +++++++++---- gfx_es2/fbo.cpp | 4 +++- i18n/i18n.cpp | 4 +++- ui/screen.cpp | 7 +++++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index f0cb66d8d6..4b4a548290 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -57,7 +57,8 @@ class Installation { writeInstallationFile(installation); sID = readInstallationFile(installation); } catch (Exception e) { - throw new RuntimeException(e); + // We can't even open a file for writing? Then we can't get a unique-ish installation id. + return "BROKENAPPUSERFILESYSTEM"; } } return sID; @@ -108,8 +109,12 @@ public class NativeActivity extends Activity { @TargetApi(17) private void detectOptimalAudioSettings() { AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE); - optimalFramesPerBuffer = Integer.parseInt(am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); - optimalSampleRate = Integer.parseInt(am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)); + try { + optimalFramesPerBuffer = Integer.parseInt(am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); + optimalSampleRate = Integer.parseInt(am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)); + } catch (NumberFormatException e) { + // Ignore, if we can't parse it it's bogus and zero is a fine value (means we couldn't detect it). + } } String getApplicationLibraryDir(ApplicationInfo application) { @@ -137,7 +142,7 @@ public class NativeActivity extends Activity { } void GetScreenSize(Point size) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { GetScreenSizeHC(size); } else { WindowManager w = getWindowManager(); diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 27ecaa92b1..c2b5d6d2ec 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -266,7 +266,9 @@ void fbo_bind_for_read(FBO *fbo) { } void fbo_bind_color_as_texture(FBO *fbo, int color) { - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + if (fbo) { + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + } } void fbo_destroy(FBO *fbo) { diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp index 44d2769fa5..30587c35dc 100644 --- a/i18n/i18n.cpp +++ b/i18n/i18n.cpp @@ -17,6 +17,9 @@ void I18NRepo::Clear() { } const char *I18NCategory::T(const char *key, const char *def) { + if (!key) { + return "ERROR"; + } // Replace the \n's with \\n's so that key values with newlines will be found correctly. std::string modifiedKey = key; modifiedKey = ReplaceAll(modifiedKey, "\n", "\\n"); @@ -66,7 +69,6 @@ bool I18NRepo::IniExists(const std::string &languageID) const { return true; } - bool I18NRepo::LoadIni(const std::string &languageID) { IniFile ini; if (!ini.LoadFromVFS(GetIniPath(languageID))) { diff --git a/ui/screen.cpp b/ui/screen.cpp index c9dfd8af89..11ea16d079 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -21,6 +21,9 @@ void ScreenManager::switchScreen(Screen *screen) { if (nextScreen_ != 0) { FLOG("WTF? Already had a nextScreen_"); } + if (screen == 0) { + WLOG("Swiching to a zero screen, this can't be good"); + } if (stack_.empty() || screen != stack_.back().screen) { nextScreen_ = screen; nextScreen_->setScreenManager(this); @@ -38,6 +41,10 @@ void ScreenManager::update(InputState &input) { } void ScreenManager::switchToNext() { + if (!nextScreen_) { + ELOG("switchToNext: No nextScreen_!"); + } + Layer temp = {0, 0}; if (!stack_.empty()) { temp = stack_.back(); From 67183f5822c3e28b51bb06b754e002c737feeccf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 11 Sep 2013 22:20:30 +0200 Subject: [PATCH 0673/1445] Make sure we don't access outside the choices_ array in PopupMultiChoice --- ui/ui_screen.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 5626e9012e..1b2c908442 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -205,7 +205,12 @@ UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) { } void PopupMultiChoice::UpdateText() { - valueText_ = category_ ? category_->T(choices_[*value_ - minVal_]) : choices_[*value_ - minVal_]; + // Clamp the value to be safe. + if (*value_ < minVal_ || *value_ > minVal_ + numChoices_ - 1) { + valueText_ = "(invalid choice)"; // Shouldn't happen. Should be no need to translate this. + } else { + valueText_ = category_ ? category_->T(choices_[*value_ - minVal_]) : choices_[*value_ - minVal_]; + } } void PopupMultiChoice::ChoiceCallback(int num) { From fd4501b91aec364ae09f0f6f8244f4ffb21ca38c Mon Sep 17 00:00:00 2001 From: shenweip <1037567878@qq.com> Date: Sat, 14 Sep 2013 13:47:08 +0800 Subject: [PATCH 0674/1445] Add RecreateAllViews function --- ui/screen.cpp | 6 ++++++ ui/screen.h | 5 +++++ ui/ui_screen.h | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index 11ea16d079..61a369b8bf 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -155,6 +155,12 @@ void ScreenManager::pop() { } } +void ScreenManager::RecreateAllViews() { + for (auto it = stack_.begin(); it != stack_.end(); ++it) { + it->screen->RecreateViews(); + } +} + void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) { if (dialog != stack_.back().screen) { ELOG("Wrong dialog being finished!"); diff --git a/ui/screen.h b/ui/screen.h index 9b4adcf905..bd0e871acc 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -48,6 +48,8 @@ public: virtual void axis(const AxisInput &touch) {} virtual void sendMessage(const char *msg, const char *value) {} + virtual void RecreateViews() {} + ScreenManager *screenManager() { return screenManager_; } void setScreenManager(ScreenManager *sm) { screenManager_ = sm; } @@ -89,6 +91,9 @@ public: // Push a dialog box in front. Currently 1-level only. void push(Screen *screen, int layerFlags = 0); + // Recreate all views + void RecreateAllViews(); + // Pops the dialog away. void finishDialog(const Screen *dialog, DialogResult result = DR_OK); diff --git a/ui/ui_screen.h b/ui/ui_screen.h index e761afb33d..fee4d99f96 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -23,7 +23,7 @@ protected: virtual void CreateViews() = 0; virtual void DrawBackground(UIContext &dc) {} - void RecreateViews() { recreateViews_ = true; } + virtual void RecreateViews() { recreateViews_ = true; } UI::ViewGroup *root_; From e508a712133a9d8a7084f68e9e3825a044c29265 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 15 Sep 2013 12:52:27 +0200 Subject: [PATCH 0675/1445] Add a function to math_util --- math/math_util.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/math/math_util.h b/math/math_util.h index c2cc9f38e5..278dd49bb5 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -26,6 +26,16 @@ inline float Float16ToFloat(float16 ix) { return x; } +inline uint32_t RoundUpToPowerOf2(uint32_t v) { + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; +} #define PI 3.141592653589793f #ifndef M_PI From fabb3f66ea9251ea11cf6fd0bb717079e8111f8c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 15 Sep 2013 09:43:50 -0700 Subject: [PATCH 0676/1445] Skip blank lines in IniFile::GetKeys(). Fixes hrydgard/ppsspp#3783. --- file/ini_file.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index 4da6e14b2c..714d569dd9 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -360,7 +360,8 @@ bool IniFile::GetKeys(const char* sectionName, std::vector& keys) c { std::string key; ParseLine(*liter, &key, 0, 0); - keys.push_back(key); + if (!key.empty()) + keys.push_back(key); } return true; } From ef158f52ef0bac2e4ec9d35a96693ea1ee5c5e56 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 15 Sep 2013 18:06:07 -0700 Subject: [PATCH 0677/1445] Don't crash if another dialog is added while finishing. --- ui/screen.cpp | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index 61a369b8bf..aced41b9f6 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -162,12 +162,12 @@ void ScreenManager::RecreateAllViews() { } void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) { - if (dialog != stack_.back().screen) { - ELOG("Wrong dialog being finished!"); + if (stack_.empty()) { + ELOG("Must be in a dialog to finishDialog"); return; } - if (!stack_.size()) { - ELOG("Must be in a dialog to finishDialog"); + if (dialog != stack_.back().screen) { + ELOG("Wrong dialog being finished!"); return; } dialogFinished_ = dialog; @@ -176,15 +176,27 @@ void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) { void ScreenManager::processFinishDialog() { if (dialogFinished_) { - if (stack_.size()) { - stack_.pop_back(); + // Another dialog may have been pushed before the render, so search for it. + Screen *caller = 0; + for (size_t i = 0; i < stack_.size(); ++i) { + if (stack_[i].screen != dialogFinished_) { + continue; + } + + stack_.erase(stack_.begin() + i); + // The previous screen was the caller (not necessarily the topmost.) + if (i > 0) { + caller = stack_[i - 1].screen; + } } - Screen *caller = topScreen(); - if (caller) { - caller->dialogFinished(dialogFinished_, dialogResult_); - } else { + if (!caller) { ELOG("ERROR: no top screen when finishing dialog"); + } else if (caller != topScreen()) { + // The caller may get confused if we call dialogFinished() now. + WLOG("Skipping non-top dialog when finishing dialog."); + } else { + caller->dialogFinished(dialogFinished_, dialogResult_); } delete dialogFinished_; dialogFinished_ = 0; From b275a5366d89f609429415fe86b3a98de33b2dec Mon Sep 17 00:00:00 2001 From: The Dax Date: Tue, 17 Sep 2013 00:48:09 -0400 Subject: [PATCH 0678/1445] Prepare native for Visual Studio 2013. --- ui/viewgroup.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index a00621728b..bfa8489884 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -8,6 +8,8 @@ #include "ui/viewgroup.h" #include "gfx_es2/draw_buffer.h" +#include + namespace UI { const float ITEM_HEIGHT = 64.f; From 705239de2eeb4be5bbdf623afff04a4d745f5f2a Mon Sep 17 00:00:00 2001 From: The Dax Date: Tue, 17 Sep 2013 01:43:47 -0400 Subject: [PATCH 0679/1445] Remove previously required define stuff. 2013 doesn't need this. --- base/basictypes.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/base/basictypes.h b/base/basictypes.h index d8de8c0713..58a858625e 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -3,17 +3,6 @@ #include #include // for byte swapping -#ifdef _WIN32 -// We need this to compile without hundreds of std::bind errors in Visual Studio 2012 -// since by default VARIADIC_MAX is something low like 3, 4, or 5. -// It's a good idea to include this file wherever std::bind is being used with more than 3, 4 or 5 args. -#if _MSC_VER >= 1700 -#undef _VARIADIC_MAX -#define _VARIADIC_MAX 10 -#endif - -#endif - #ifdef _WIN32 #pragma warning(disable:4244) #pragma warning(disable:4996) From 15d92565d85d87040d770706744a78898f95377b Mon Sep 17 00:00:00 2001 From: Aapo Rantalainen Date: Fri, 23 Aug 2013 11:44:43 +0300 Subject: [PATCH 0680/1445] Fix: landscape and portrait should be same resolution --- base/PCMain.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 544f6b5938..34ddf020b4 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -387,8 +387,13 @@ int main(int argc, char *argv[]) { pixel_xres = 1024 * zoom; pixel_yres = 768 * zoom; } else { +#ifdef MAEMO + pixel_xres = 800 * zoom; + pixel_yres = 480 * zoom; +#else pixel_xres = 960 * zoom; pixel_yres = 544 * zoom; +#endif } } else { // PC development hack for more space @@ -401,8 +406,13 @@ int main(int argc, char *argv[]) { pixel_xres = 768 * zoom; pixel_yres = 1024 * zoom; } else { +#ifdef MAEMO pixel_xres = 480 * zoom; pixel_yres = 800 * zoom; +#else + pixel_xres = 544 * zoom; + pixel_yres = 960 * zoom; +#endif } } From b93475bcbe4edc42d4ef88f7225fe37566944c35 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 17 Sep 2013 15:28:53 +0800 Subject: [PATCH 0681/1445] Add bool GL_NV_shader_framebuffer_fetch --- gfx_es2/gl_state.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 8094dcd45b..e6975e11c3 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -302,6 +302,7 @@ struct GLExtensions { bool QCOM_binning_control; bool OES_mapbuffer; bool OES_vertex_array_object; + bool GL_NV_shader_framebuffer_fetch; // EGL extensions From 23f00940e04c25678b58a6523cbd5dbce1a4934f Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 17 Sep 2013 15:30:27 +0800 Subject: [PATCH 0682/1445] CheckGLExtensions() : GL_NV_shader_framebuffer_fetch --- gfx_es2/gl_state.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index bd06890537..d289f73d30 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -112,6 +112,7 @@ void CheckGLExtensions() { } else { g_all_egl_extensions = ""; } + gl_extensions.GL_NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; #elif !defined(USING_GLES2) // const char *glXString = glXQueryExtensionString(); // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; From 21cacad2c71b8a44fb3dff930eecb915f642c154 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 17 Sep 2013 21:23:51 +0800 Subject: [PATCH 0683/1445] Add support for iOS 6.0 as well (GL_EXT_shader_framebuffer_fetch) --- gfx_es2/gl_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index d289f73d30..722a713a32 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -112,7 +112,6 @@ void CheckGLExtensions() { } else { g_all_egl_extensions = ""; } - gl_extensions.GL_NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; #elif !defined(USING_GLES2) // const char *glXString = glXQueryExtensionString(); // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; @@ -123,6 +122,7 @@ void CheckGLExtensions() { gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; + gl_extensions.GL_EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0); #if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) gl_extensions.OES_vertex_array_object = false; gl_extensions.EXT_discard_framebuffer = false; From 0efe40bf97a51166a417d6c51773eb0e59e28528 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 17 Sep 2013 21:25:01 +0800 Subject: [PATCH 0684/1445] Change name to GL_EXT_shader_framebuffer_fetch --- gfx_es2/gl_state.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index e6975e11c3..71dff26811 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -302,7 +302,7 @@ struct GLExtensions { bool QCOM_binning_control; bool OES_mapbuffer; bool OES_vertex_array_object; - bool GL_NV_shader_framebuffer_fetch; + bool GL_EXT_shader_framebuffer_fetch; // EGL extensions From 26d037f4ad48bc997f6d99dd4c4b3a8fa921674e Mon Sep 17 00:00:00 2001 From: The Dax Date: Tue, 17 Sep 2013 10:15:08 -0400 Subject: [PATCH 0685/1445] Put previously removed ifdef back, and add some comments with the reason why. Also clarify the situation with "C const func" in thread.h with a few comments. --- base/basictypes.h | 12 ++++++++++++ thread/thread.h | 12 +++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/base/basictypes.h b/base/basictypes.h index 58a858625e..e54af02ad6 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -3,6 +3,18 @@ #include #include // for byte swapping +#ifdef _WIN32 +// We need this to compile without hundreds of std::bind errors in Visual Studio 2012 +// since by default VARIADIC_MAX is something low like 3, 4, or 5. +// It's a good idea to include this file wherever std::bind is being used with more than 3, 4 or 5 args. +// Visual Studio 2013 doesn't need this after all, so we can simply check for equality. +#if _MSC_VER == 1700 + #undef _VARIADIC_MAX + #define _VARIADIC_MAX 10 + #endif + +#endif + #ifdef _WIN32 #pragma warning(disable:4244) #pragma warning(disable:4996) diff --git a/thread/thread.h b/thread/thread.h index 58d60b725f..1a1b37615d 100644 --- a/thread/thread.h +++ b/thread/thread.h @@ -245,7 +245,17 @@ private: void Run() { func(); } private: -// Visual Studio 2012 needs this, or else it complains about losing const-volatile qualifiers. +// Both Visual Studio 2012 & 2013 need the following ifdef, or else they complain about losing const-volatile qualifiers: +// Error 23 error C3848: expression having type 'const std::_Bind' would lose some const-volatile qualifiers in order to call 'void std::_Bind::operator ()<>(void)' (thread\prioritizedworkqueue.cpp) + +// Error 24 error C3848: expression having type 'const std::_Bind,WorkerThread *const >' +// would lose some const-volatile qualifiers in order to call +// 'void std::_Bind,WorkerThread *const >::operator ()<>(void)' (thread\threadpool.cpp) + +// Error 25 error C3848 : expression having type 'const std::_Bind),void,http::Download,std::shared_ptr>,http::Download *const ,std::shared_ptr &>' +// would lose some const - volatile qualifiers in order to call +// 'void std::_Bind),void,http::Download,std::shared_ptr>,http::Download *const ,std::shared_ptr &>::operator ()<>(void)' (net\http_client.cpp) #if _MSC_VER >= 1700 C func; #else From 0b53ecb1ef6d8306094eefb08ede42c2f5e5ee22 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 18 Sep 2013 12:21:43 +1000 Subject: [PATCH 0686/1445] Check extra extensions on Blackberry too. Buildfix: Use different naming. --- gfx_es2/gl_state.cpp | 8 ++++---- gfx_es2/gl_state.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 722a713a32..4749da90d7 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -5,7 +5,7 @@ #endif #if defined(USING_GLES2) -#if defined(ANDROID) +#if defined(ANDROID) || defined(BLACKBERRY) PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; @@ -43,7 +43,7 @@ void OpenGLState::Restore() { blendFuncSeparate.restore(); count++; blendColor.restore(); count++; -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) if (gl_extensions.QCOM_alpha_test) { alphaTestQCOM.restore(); } @@ -122,7 +122,7 @@ void CheckGLExtensions() { gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; - gl_extensions.GL_EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0); + gl_extensions.EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0); #if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) gl_extensions.OES_vertex_array_object = false; gl_extensions.EXT_discard_framebuffer = false; @@ -143,7 +143,7 @@ void CheckGLExtensions() { #endif #endif -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) if (gl_extensions.OES_mapbuffer) { glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" ); } diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 71dff26811..1003adc447 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -7,7 +7,7 @@ #ifdef USING_GLES2 -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) // Additional extensions not included in GLES2/gl2ext.h from the NDK /* GL_QCOM_alpha_test */ @@ -273,7 +273,7 @@ public: STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp; STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; -#ifdef ANDROID +#if defined(ANDROID) || defined(BLACKBERRY) // QCOM Alpha Test BoolState alphaTestQCOM; STATE2(glAlphaFuncQCOM, GLenum, GLclampf, GL_ALWAYS, 0.0f) alphaFuncQCOM; @@ -302,7 +302,7 @@ struct GLExtensions { bool QCOM_binning_control; bool OES_mapbuffer; bool OES_vertex_array_object; - bool GL_EXT_shader_framebuffer_fetch; + bool EXT_shader_framebuffer_fetch; // EGL extensions From 6668ba8da696a33d7799a216994c851819257b07 Mon Sep 17 00:00:00 2001 From: danyalzia Date: Sat, 21 Sep 2013 14:51:16 +0500 Subject: [PATCH 0687/1445] Add new extension --- gfx_es2/gl_state.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 1003adc447..b9fcd83fd3 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -297,6 +297,7 @@ struct GLExtensions { bool EXT_discard_framebuffer; bool FBO_ARB; bool FBO_EXT; + bool PBO_ARB; bool EXT_swap_control_tear; bool QCOM_alpha_test; bool QCOM_binning_control; From ff8ac3d4b35405cd483114dabfde6da4cab449aa Mon Sep 17 00:00:00 2001 From: danyalzia Date: Sat, 21 Sep 2013 14:54:28 +0500 Subject: [PATCH 0688/1445] Add GL_ARB_pixel_buffer_object detection --- gfx_es2/gl_state.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 4749da90d7..6a5e46db79 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -180,9 +180,11 @@ void CheckGLExtensions() { #else gl_extensions.FBO_ARB = false; gl_extensions.FBO_EXT = false; + gl_extensions.PBO_ARB = true; if (extString) { gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; + gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; } #endif } From 46af0731fcd291d880a90883eae9b0a8cde18e05 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 26 Sep 2013 14:25:58 +0200 Subject: [PATCH 0689/1445] Android: Add native Moga controller support --- android/libs/com.bda.controller.jar | Bin 0 -> 30211 bytes .../libnative/InputDeviceState.java | 25 +--- .../libnative/NativeActivity.java | 3 +- .../henrikrydgard/libnative/NativeApp.java | 5 + .../henrikrydgard/libnative/NativeGLView.java | 114 +++++++++++++++++- .../libnative/NativeRenderer.java | 1 - 6 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 android/libs/com.bda.controller.jar diff --git a/android/libs/com.bda.controller.jar b/android/libs/com.bda.controller.jar new file mode 100644 index 0000000000000000000000000000000000000000..f71dbece3486a143c4fe6feba4152a71587ebba6 GIT binary patch literal 30211 zcmbrl1CVUn7Oq*lY}>YN+qP|6yKLLGxy!a~yK0xQ%XoF}z1{ty-#h2_i_VA@kr5f0 zx#pbz_~t+67)xFX2pAav92^`VG)O=Y;D34{0{{cah$sutNXUxP$q2|wh>9pF)5?f` zjspN3903BzOM!t`1s5O#e}4z?`;!0LUt<3L)X2_;&d}I^&dAQz+0oA0+QgAg(7?$= z#MQ*snONSy(a6Nwz|h)6$kD{W+0K#H$lAckDOqX5c7Y$BCowV`c%g(ACaFnV(%eaa zC4ekRkwREF0@*=9fn;!DSOY~ZhNe23@R`!xf&|_h053Srr9eIbK0I_QeT(O0a_Atp zr~4D&1{_Yh2>i{K-T4)0uhjs)a`vg%F(+J{moHI3+k+&D%4hD$L`wo8bX+(@o*Tui z|5n6)zw;tjl8w~>{+9^7d_J3f|LDs=rF0nZK`&J2b6i}_atuVeD|;MBk;70xIJQCa z3CP`$`D*I#Xj8-s-BZXfb#l2}vefkFE;Iz($4|Oj($Y&yHCJVJY(6AhH7_R(HY=&( zOwwfttqFXP)zw**Wboo(gjQc7NHK5xDmnmoNB{R(MM-bs3+0Yxw+W~HU&7mDsD-o! zb`A=Sc-0yJd%uDSmz^^>hXqGtf@L;|kz*2qxN<%rsTNk>GK5F*JjndR#3JzYW}v3b zoITiKQ`Fo>|7dLC$5mWLk|)H6V;UIc6Zd7wZmw@4@4})b9VZ{@@zdpS^B%1^ttNC= z>*d`9XCqT@M;|r>S9WR{0jSoEr#PRG9+pyP7-oKfzS$fAuJF!)J0tqfqcbDSZo6!X z?>mN)Dax%{D*t-Nd90GYPLOt`OccS;$}@~)TF)81U=%Hk@;tz9F?AuI+jBd%CY5=~ zRN@`k`svuZ>=mxo_c3^77+XE1i>k61&241E9QOwEm)0PraQPs=g=YONxWCsL;eXNE zzm?^qY$b=J0MFBMof6EOCxY9of*=)HWw&?-PnpIV4PS=NYrA2k)3C*|0rHjPOAkq$ z@eK5?Fx=K66*=1^acy**!^C7(@^SxkVh0d=LkbQzU_D@2`KP3Wm3pC`W?=VMd%4T= zG6Y*TzBhC|(WS5w%#?LG*B_#7d@DbK@^qPv`OJzX1vi$CKA37-`w($0LMzWq+Nyr~ zb=p5^6EY3S7y-py)zRzIxI!hIab`8fPE++4ghK9mcIg>T)<`?AH!D<221CdzVKhzi z^v+6d%jlhL!9bvTW0rUL!x$+c{wJ?B38v=EMG`=lfTfA8nEzd-#BK34lII0`LS5X)R>3lw#hJ|a-O3{(BOME1yVP8bgF8b0QM8~9rjTOd7 zd5L=B*ttgr-K2dJ;Y!V;#my2P(MyU^fTawELGTpW@h<1yIZW@*$ffuL_E2pnP8BxutJ1iq2nf3 z>};K!4Q!pAhy{$CEnF>}J^qF7e}`0byp-GqKXUL430x{O_e3E@?472(vH?npvUq&D zWc)nv8mXe1xuK}O@o)l9_~49T@FEDGAD+se7>ZGAc{ZnOx06YXsq_)P9y|bS{gFOk z13F2&&AnjfLgh?q8N}o^-3lk7<}tVR`0$bXHWZ`c=s-$?N6nbxOmUyH$Iul@#-R3- zNLO<3MFMFaJls*^B1&&0ge)Y4Am6W4k?uy+ARE3Wc>?9Yx}TO_thH~1>~9p*OX{xc zyiky3NXLMCaGW{pPp@4$H-Zj^Y}mZ_Jj?YQq{^;6(5ur@bjm;|O&RKghz2ECR!dl0 z&?>0o1_j{vTg(Y#{HFCsKL;w>BAohHuD(tjgw27^$RihHS2d-3P9JT=gG|M&l0CvF zoszj$39Gt~ruVw;M%ZpDFR11OVO&T@K*QW76G?38d*~bzJt_tlCYeZbOme7hx$i>} z>Fn7I77p4c6NPGwzl^VO@vb4q$aJx^{Z*9fV^FR#`b?(y*lo1Umjt1vEN*j!NC+5TL#MO z3WZNB5JwoBvxUvtW<69x1eBueImQDC63=pm}}=N+5ULK**vpi2pwr3n+l z3RggWEHK}ZB_qIwR{Hu#(2tA}Mju8~hGhI?D-}TwII^HoB16?6shd;6` zzcX{AU@5hGUtk9+rBo~k#au=|ucA~pQ>B<^uys5Mh)1{jP*bNXE*@Jl24(`XX-d=B zAyw5XE>&8#xk%FOr_JSg=>Auv6^&jDF@LYY$oKX4Yryrlk@g>#L@e>W9{+hSZQ zVr$~4#5l)2re#?J}Gcjb4`J3G#K#a zM-rZc9bxm>HdqYPvpn0=N8A4OY0C9p;yx}*QWiXLC=_b`>L|=bs<>JHvNPm>;WS(G z(1tULDb5nvVrD_7N$Ik3iKY1=ukLv&0Emw(q3IKFqlpp+`3_!J6((yzF_DLUH!yA7 zj+EIFn=NKWL``ri6(WmtPex-?!2`|pre+QQC=_)P0}_K|sai2$?a@l_Q=H#0F zk~E#v0Q`0cm$Q!xW63zW@MQOlT9}E`AyNo}>A;>I%GD^EEa(N(5ViVZCRdHFiV(#L z2L|O`STI?r2VRhkEaJunPy_!IttVAA`H;rDuA9&D1Pc;Xhk;iJEg9|b%7qu_YPRTB z3P++``*TW8bwYzw;|o*^W?^%u6-jhb=Z=G;!=a%leP!xn-2TxoYEupiV4u#&3JQoW z7459ZF&N|peJT&9BkxM@VPq88NdW_`s=H+hNfPV|Z_1Qi_TL2-4%i4KI3&~9@TE`p&FMhOR z=7Iy8$zvw&4%!eW;8>rR5qlq$qWoYxfGpl^3QCEsknDGNdV)ABZ|uJVLx1{hqI6Eg zVvx7IOa+SiE;oQapvz!W5r#yGn4@+XFr?I3mM`ELq%W+<#0;r-1U%JkdI5dtxZ&>z zY!E$g`+X(3Lrv=oajW6D2OWDa`oQs!*$V7CR-$(gV{}I|2*}Bc$<0a6%*xIn}&8MH~j;u z@u$h7-Q;KX+Rw=eUWN(Zswf`XRUY;$<7Hx5`?aAp@O! zWp6=}pE#zMVnNNHiy>grK9~)67zTy+cvp`MeZR}&s{-gx3_(%AOeQ<(>iNmtnDdw6 zkX{@S;Y>Vcxd{&?Ka=h`H0Z?;y zN(~rUWwTGN0X-5zDaWj-5i|)giYc)@DDQR0)Q|469S(Z`f95Jt(8`VsnKOj5$@)6a^zkdDFHz_)QD5)Fr^ z`DNz$yTM)LJ5C!)n}Jv45YrzC<4qEN4(+RSv`DRXE??d1EkRb@dnS3DlCKVP-i=?8Z8qmwrOI4_Tt@iz=I5Hv(=8Ofsp&k-ngcz_?4YhkNrKuKMmEDq zlUO=77(v@LVpCJs=Y`|kzYsiD{r;E8)Q5vpKfZUGKi@+8``w1_zlu!C#6!`=*7mPd z{6Dr%QRaJxf%h>YbGU4k$l&)+n&(%_U`G+vj@*U!55nXxP`Sc#1EHP9_ddL%_@e&Nb80o zy9^D=Ht8KQVSaEZ>wkdQvpB(9P0rdP$e)dsD~1tV3Wgc+4~IcBS%fexdzbWOBfIrM_x9ruxgi zJ`lAJ7p`A|GFck@ty1EocYyIK-^L)d?nw`X_R&6fchHg+H@{i=t!Ge&PgdmSv-mkq z>HvFWfjDkP=u#Pt8SY^heiJRC?KM74nwUzxn-D?s9f7o#5PI?9CqQ$?Cj+iw;DJeN zXKka~VE35W(z#B-zK`e>SF7-W5@_eNmq_UunsuN}&WB8ljbn_IJrJA!Wcv_uy93gn z&RhC>f0}E+WGHJNF`|}dbMHPKpo~H7ICK$qQ3x3$8X^a?BaSiOkYZA|OJle5{(}Vr z_*>uyzn#CpL?YooyYj7>qJPv3xnCtZ;$I4m~DO(A?^jFcowG4`X8>CSYf2UCylౖz!nQ zf^5>FpEtxe1Hz`?-jVQ+*U#GOLgGlo7hggX`lw)k#6BLVX&^q>L$R-|8|k2Qe-lBQ z<1Rs@6fwG);7RbQPwWhf3v7qc)eC0KmK^wBCkAE|6sL{iqH9k5k&iU18|GXjr`SC7U()0425lIT!@i=81gsZhAOpp8e+^E#W z_qD3#-^|yQn%%9~2B@iQA4#mP?}5&Ig4D8GU4E(Zd`q?OthMjDBKfW7xQlrm#<6v#jeFPp}> zL+1AU>t@Ypj6L^boXlmpH^sSv@ljAp4f=&_0wWK48h4Egx^c>ZC(5Ne?U zVl-pR7^=sZ4Vb;3yU{87qf6YGEst&2qfhRP6d;UMa3!7VXoy+&n?FlM5)BH!@j;_f z>vPx^^ysdo+-^WeU%e8u5d}HV5N?5@1bxISSe28IR<8~hiv@bMk1Lb`hRX1Q*CqpE zllsc|P%2gtquCh^AKt#b$%Q)rM{njemh_3lzlI?1;>&asPS-_1&DOi`i#GIN(TY>-7g6y znOcfduu+Q}{E$GL3znAzl%=)Gx=K%I%>7T?My}h7!bQ<-4bC>Z|CW>R9;cYNjpr8E zqs{Gfd^%%SP4!sjh`xH#bgkq^z$WMVNro*G_2wz?=>0tR=)#f2EE90b)Hs*0UN|rh zrgMf2k|$uWub-|iZ=k|wOgxgO620WtKojUVvttlUxW$T1)Es++gY+Oqx1wnJy~Ydj z@HpHi$3RrjN$XDr?zjPp6vZ8S0s}^um?dyy6+yCi(lItE$oxtC>Pf=VNdw8T!m>#t z6$*VN3Q^8GH0^rW@a40P5yA)diernUSR2K080%p|w|z#Iu?ca5T1g$yBt*q=#X)+9 z`nrj{A!ta3QJ$IGfMIL`(Fm#_vijguiA%b_c>0Dinb7#1afkfl*$Tsdj|yi4XOsUo zP8IAH=;1#voS`HdS)1tdjI5(#n$PfoAcB~Kf+*wQgC($jcVueB(YTZlZ+!`_2krWc z;XW&bIb|U57asII`kY)}HC|u6#nS2h;2tc2n4X3D-iFuFzPDlOe{aL7YugjTq;6!A z;R?hu%IKRw4%F}BWlx{er~IJl;T|EPXFNtsld*c(QppTe(9;TIN+&@!1*UlYO~1eqbz5U-s&e=;C8zcO!_2_+NCn zCjj4>lnHbtwbzP;5$jUSpNkR7m~ckZLItZ>h6z}~V%JY`hVjCAEyD3;G&OOOc zcbJ{$8c=L!j*5yiHPbqkFA}vQjN5k{JGU?Ah+u}P8)ki|yc)l>vM-#8A!u>OM@hr`r%W8htYZC zQ-zjZDWxfyh9K5Ltf%3%JZzXU2$y zfx)wW`^}{Hc9}q z#0#-TxNt%dmtR_yt7Kz^l5}pc1`uf!lzKwpcoA18Zmd#2k)E__s$2HL%E@DmkYon- zPdByH6*PO!SI;b7zU78#LxCe$BX--M012Rc%g1Qp#J#XNB-x<1P-rh^OexSr1LF2P zP`46lMz0isJb)snhChXArYHSwFP$-0G5nSol#1B}8z)YlfG>BNN18*Y=MOc%fSLi& zv=k~N>&CAhxtI(fpWCxBbYN5UJf_b4@K9FzE2d4`xGUTCyK?+y&RqwZX{#)pxzske zJl`OfguYr0iv||K-LQ?gFr^x~&~d^>`hgnoFy@Rq5NQrfY6izw#gY9Hu+ko|Zf*AB z2u|7E{ArKJn;4qmIZH$~_kbS)QnCFNM&ufpnmuvpMtphZF(N|}8Jd0eh&Pt@7q2ps z#?%o+h(t&sG?m50M29*%Y2=kL>W$iIvNrcNLCNZwmU|u4V<2Ta=u^zqw5=(ma=o#C z9^q-eYU2pZzK64wyR0fPm=o*V(eAEhZFAa+Z;&p7tB~N-|0u*p8#B%B-|Ub~4gJw5 zI6Dck_?UOKwO6)>5&nI<{P4w4I~_*(yYh1MxTcy6&2ep|SrHV&@B;x6S{t6@02nJ{ zazAoNTz;3}M*o7)WOS&4G=>fB&Js1}s@x$kmpvygWu2p&wZN%fIYkPPrhev*rvn%Uw7#QXX%lJAH8YeXv%{X;XwhL%UF( zE6Dv;AZr#6_e0tiwoqd_hkJhb(LRC5r&)Gowt2K5D1OrTB0{1wMRrYaY-f2OqNi#B zcRdmoZs@GYHdEM+vQlG6?aT^OCsveIcK__brTqtuDe*d93~W*6!uz}Q6rIKNn#HFv zeN!_NdsTvx7|vQtDAJt(2wZdfx~j@7jdP}G3nb@bm}ZVF+Z-E+jD?Fqqo^BrhJi!e zOxR#Th?CbSI;)q0ggsZNR3b_zg=s)L`U7tEjC^)<~?j>T_@xAxBV8XP>5u?|PPF(-0X z-J6q@J;U;lhAy7g^r5*s>LKZtUFsWrAPm+69xfSOxvO02o-EOb`>Yt5Ra^W>VdYs#yF z$qN}?YRBLJe~Azy@N0^^_U?jb8*0HSP)Ml$o_p9MeV0W2Q!o2-paToEKfGTmF6iM0 zodqP>MJJ#}Mo*dgNNuf{{P5?hIJa>Xq*G6N&g~>b*6BMFT*rQcb`nO(J`ccKlyVN+WRRAa8YmSR#((k_HWPt73eL$a6hMQNonVW=8^f2}bZPIX<}<#Jb7F zx>p5rfnSZGx_}=jP%{o(GJUmvhPCLAB=X2N&G_|d35L9+Y4it=Ok2P!YnGcAfu zM8x_~U?Znd^0HCefgUQbGgVJkn@Gj3#^ZC-iS#mw+|07e!#NudWe)3Sb!T-nIFyI3 z6+I}qua3e>dAci~+i1i(Q;x#WYLgDSsKh#5kHT7Nuy5y&z8LxnelYsgK`ct#WcRAO zh6&eR`eJsf_1mhz5_@Ka+*D^qk{3w#$zc`m(o*($7RXx1tVf8QX=kE;A9uh<*LB~E zo_SBY-MuFkIujhD-M%vwI@ecMI49BW9p#?X>by5^{L)XN-N|J&WXOY9@qpm@@l2-B zBbPs%BZ|WfwAMIUn@c2?BZSHw+u8-L*Fy|rOCMc8H-|F6D{H~IPNgF;F#bUE`@+da zFltVP)mz7mi~r;*UlTg@!08s@`N~!%*sY7mnAaB6HpiVsJjn5E(ZJQ7!2PU5E%nxtO+jNzs zo_AKtYDgNnYTN-!xiMb9(oLmM!Isjg=KM5q=H5-xw1{OIP4oOTk;{E@P3o9@5<}dz zq53AprZFRI8lOFJya55YQKQ9t3EUzuf2TrjZ3?bCAItuyq=M#W-`HpO(D@N8x||)_ z>1P(YoPA_;PfTbXNTJkNq?u5tp?j`}Fu-o%rESFN^{%EHc%F4FrwMeQYv0%UOeOa| z^bh0gEPKY(sJX;*YZC1O^&UE|ViB+lhh9{&Da1;1e{~r$$kd@4lJOeOO^ca=-@=q_ zazQdP#gV_IRg_&S+NJzl#?X1}unJQdO>Ei$qGhv07J}hyZ?q~(Wd&3gYUe$5B<-qg zej8hQSwyVzC+}MuUvi)}H(ShfXQ_Je57|;YTyjd2WfE}bfO$`wB?Ug58@5MhY^_c1 zFg6xB@#RrDB+m%gAMbN=v)~*TwgyM?wz?2Sot1JB3OfZ0lt#!nXRKN}Tq>HZY8zvj z<(#dXQeKIT@&$24Fe767c)(|JYD=Vaph0X{em!7Vk+-%lV-E zI(NGJ2}Vzs=UJbKIT)N0U@a|H9{-s~n=krGWGX^|)viLKEwn<36;RQ*M2Pn}s5VNw zA=s_j&@jM#PD_c9s+hhSeXkn=-L@H!Jr<|=3YC&)F&^)@RRM?Bf(YaCc{Kq;SOqcIwV-fcR&bni@J|-vqb&fvLz`U z@KgWSDxPU~a2sC@8-UR>EVaLHuUOj#6-FH^#0Ue4hAoKqG8HSqIodpxh%YtBQT;Z$$tj47RDNxt{w7Rr zqTjKBG~nfza3Qy}41cevt}AL?1m;~H?C&A#-YH~%(`6cWxxXfa{M@Of^?SIS-?`b} zpQ%&+w+Z=AvF6|N!S%;(g%=bQln7MT6_ivIH2Lsd`=cmH_~Y=sGoj!;D{GO^$Bcb} zjgPL8xF;;zKR8|hpQ@f(fsc%VPG^UYf{LXrDBhoiZ-$I7J6=G0U||7_07qLfDLvJ; z8e@307bQziGb!tLN_yh>D1L}R9j-VM77-8;5EBqMJ>aE*i9S$0`l>%M5)jzGiqrvN z!Y`5E1E~AH{(gvT|N9~SZz|Kof0d+&by0{Nh zU|%@7F7H>i8KB@p{luA0(>XhT?%%SRUe0%Re8KGDXU@aGvFWqhoV)QCN{qZ}l&C4$ zvN38V8&$`YemQoOb_RPt6`fPloX-Mh%#4Yo(@J`g^2GC%O3R65_kMnvN%QA&l^)7K|#<@zKO(IOtlDo<0*^V~QT-Wu+2-EoISp2YAr6^-BFlV0is|K7Co^b|3 z&;0S-QX``=p?U!2FoC^QbL_he2keXUa_RPVtWZCW-HoT zc;A@Ud;`cYy-Y81=2I5qRDL0@O(daXRG)Cmu+ zw_*c1VZkrf@zsDrZ~XX;^0J)z-D|EZ9Fv&aLE!cfaNrtMY^(D8#Ta_|xz*N5EEwaA z36%z9WfsidwL_q}kKHT_D~$;mZwDx!=DRbxlt~a5Db806rS)fq z8?2|aG?3`AGy58T2u0Uq{HT%w{*-(DEETsBQtXI{zBV#S z!pMx=E1*tBj-7412$9jox8Ao817U;U^sp0o8GIIgKaW&%#>oX8d@+SG8+qpKXV`vY zirPMuGjAVP0j7E1lGND+F?Wy0M6A|s4xL{OVZ~3gDOKr{<8n>1DG6kOKmS0G;ZvSm z0-=NQ#~?x`&m=&&pr(3CPA;s*S*e^>Ef=M#a5G{nezdP~XlA3oW0M(Sm;DUz8h(x{ z)#Orj(7TgsDr!<8PAosAoTn;#8Y#jnN%Vx*BbMg2M!jU13cbIQJEnGzTzAA_T8tyN z7fV33tEtzWN}KGK*rqXu8)#rLZ1xo*${y8ZihpOF?{sl)s5WK6VRIy*PpKu;unAM- zB1XPbV#m(m#HPSKw7g3S`5Iy9P5AbQg12~dY}h`bg0>+i9@3CVL8~xw?k4ikv#El# z{N*osZk_0Ys~CB2$(>w>6Q_dbfN~!RWIcqT72#VL1#hWnl!8`iWVN(uH(`f#@*4Wr zYr6=-77k&?C@ihxU_QIE+7P1E%gI_>@fjCCa0$1R>>$CkIE9if7u=;nD z`Zu4FRkiGp#E?ISQ>`zkgQWcU!S@mZjJOz*bd53)r2(~~64yy-Qdx0o$qWJ;v6iv$ zX%G?RxSM=_L;Z#;s~{AhVgZk%eC4P5L-&xYT=qMCZLmH$IDq6jEB)nIyW8pb;`7h- z!45!YcqXPGG{r*tjB*9H5$CTH&gKkzCea##lj?Rd>%GU+&Y_49@Bvd>HJyMK z!hscD;q}nvCO8nw9bMWORLR1&1_p&R*9#^?i;Ijp9#GRD3d`Z|UD#pymU=`L9|B*r zUF!!)tXDxjo~b#P=~@a~KfEloG=s3CtjZw5Ff5MN912+aY&{eYboS7OdK$WFoW|Ykv-aS@C@iu#2$W4Hf5@AsDVKdl81) z`IfpMgAUL{n7rm)OWlk(c>C-qV=gOqLAj`q6y$13ic=6c9N{~}7Z{<_Z2QTXMx4VA z5duyiwU~FD^IHst^!B0yV$eK4Fm$@wIq%q|#GHoe6_%J@m%(T$u4m#MXX2CD{bO0A z86Ucl%L>B~IjqOa(cQ8=@CNM35qdBAl@5`TISf2CJXU7T()!6L4Xmb2?FdiTtFCJ4 zU3Eu5oa2Ea_5v10C81M^>2et^AZF(m>xw=saP<6?KAM{tLxB8gnFU58(WNcQB&9+0 zS1@y%mvBB@3hQz=`zldhIu}-ngc{?q5 zLs{tGZ3)fTG%*%D0D9gL{31)#+MhW6)F5zMa3bpejX}VJQ&g%(=)?V(7dwppXt)zm zqZI@@mnQxhPVU7&j%)A}{ACgERQe<4RHvylhwyb50`X)_`_A86jFPKkR&>U;p)s)t zH$tDS`cFbIuZdGfEm|OYL4Be;1~zG>SQ1$Nuanc|Q>x%Sn$E6$=?u{`bMf@s0ShH6 zu#A52>YzU3vAGML1QLO3DVz&CLT%2+suQx&9iwI_m%B1fn09%2Vjm_Q^4Ntm%p`16 zqNjOBY#F+PLmlUjfQ2(L@}L{!VfzQLS8&W2Qa9051zhdn((_(4wZ2r%-dwN%s!IJv z5NdDx1~Q&jnmhRAF3=68K|K2~a!CXW3&KnK5DCoUya?ezj)FZx1$vpvEJ|b45rc&* znyf(^%V{@zNWBB*?qb_F9LVRKj8h&?4?L51$x=LpRIh;hh+~inEJFKWQwkl0CGuj- zW0c?-@wZOGTMX>==(ukB>`uvt+(O}(d70+p1ZS;ki8HZgRkE{g&BTPN@Q+h*tF9S@ zdHwf5SiSbeIO&AZhEm1WFsll{0pmZMDeH#6b9^wu6}lL_gP(u?1!V>hXdBk=N*4&! zKUqiW|IgO(-#m_1_^aC#-X~Mk$f)v9Az_ZN2y!1tEv{6sz6kxUPhwO;!qvE`)B;5W$T^lD)CKSjaEuaDyhMqyWm97b`RKTL-KdzynRp`1 zF4V)YWr=bALt&@Pa8f(K1fWkblhvJchN5V^t1+IkBw+sB$^&Coyer@vSz(9(-&1Po z(BFI8;RHY>pcl&)R|dKmQ~>|VDV9?4&TDA&E6eywSj=3#5;e0Or@8g3$z(1{ zX1UB6C7pZe7O2%Um6|%&yf!qXO3EOVHB{Ee%zELf4APGtNb6Gm$Qi_+3XwE$b^R)t zRJlf@;$T~RqnOL*;M@=FPu~sPF$6|h-mkuINdHPlWMw(fzEhF6e@sVM|LcVRCm;D= zta`Gtj@yDLe3zA!>V8;JTHGQ;lQ(c3j^W%xVp>Tsa9QsQ0GB_I4TqJ76>tQrSuwzi zNM}DsTncY57hi;{Dx>WDvp=p@<=R@Co7vU$?~l-)9l*398z_trsGLoEO`9us#;9ay zzT=@v|FFIB6%w58MBNS1AdfW+M^S2)%By-baoq|-*u zEde8pj8I>nR%qDnoE1%BkW1nOhdgy3ugPOlqJVcJaTqRX75bOOx#(oqh?F;zg*sHv zMTZYXW-!)Z@3UVywQB(TuXd68z@iUXrftImDSxpi>U5Ab>ILqED~y~bQp*r zbpd~4Ju{}*_oFq-3Wg-r7ABn&XT(muRh|8#k+?dv4!UyY7tDE512-HIIycg2Sv1n` zXr4}R%o~BY0}c_dgym6tQZoIJ!Zz_{mvmWKOb_~~(fxz4(!h)mAI_MZT^>=ht&*AB1<9Z<8N|bw zB)?)7T7}pSXhn7kdAnk%o|BoMVc14>2|B`e5*v=o#U)$GE-*cOB_(wRW{gb`&l&d` zn`S6+#t2ce$P{W4Oy&gu6Gz{Lu#TwdhpDw&>?1z$7jQ@eGQ)FRsOLKPmm5eKA4)wn z$UgtoHlPf<1nT@<`i%qqCy@TlBN_jbyZxWz`advLwo$@TLH4z67!y<oG zCPt?6fvBEGcD4ae8#F(Ma*{x8XSvunox2;`*|Up-dk&7_JUB(mzQyA>VCQv1GU5!v z7`2~S^P2XV_L$~)`h1y@>j6;jN8=O(46o?OT`M1xUUKoCsa~O>Gdf;>4LM)!KA%c? zAHc!M=#6u>%&}Twv?aQqb+t?>C8D%H5TpmJ7qcqXp4+6fLj?)BpE+7#R7#!JEjjf1 z)tHKMdQu)jhtorN9;yoWnz3sUQ2GTX=LUpFiKYfsyrjLhNp0OByS;@3Z<=Nu%aPG~gpP(D*G*SBBR$g6siV;hta$4UX47ahmP3+P z2X^<%2nF`Zjk=cF?RSddZ&i~nLLM!j7FL$8^eue%&wUzwpI75TqQVw=XDP=A~viVi}0_lG2=Z9T3c3(-v(N8d_X*n3n8fJQFE_xX^%Ng zaJN)lVqRjvlwIX*pCM@{>EL#6pvW7mvh*c#}?dDZQS zlBo~cpuQL8eX!QObOA}>Vx=O|$4!3|bBEWIrIUKH;hpTT)GKrd>^zgeq8SirL^+Y+ z@6tI^lzh}fPE<9XPXAjq9hA4%$Y1k){VM>rmJfxrE@Josz}}u&ck?1^~vG=g1bbe05If? zJtehrLUe#IqogDWzc0&jMVxW+3tTWQAO`n$m$#E(m;oT@>&8xMp2CUMfJ+z`T!52b zynFbbupzr^L_8kg3`9*TJgjQ;r_XnSl_T?WIKAXz2)d@JuDjSRj4|gK2*E+H4)0bI z{N?Z(UHmg-)a_K_Gh%dXCe5ec-Y#dB4SO(MFzFolKw2@=)R$?qqrY^|65gpQJko=h z9IQ1}I6?s}09tUahasP6Dq3XInxt@&a!!7~NQMmaLi;)o!Ez41qV~OALAcX((~y}FGka0)_OqYj zZr#CG%Xn-dqKOLx?Az2Tfxco>C;D9eggl4BR+|fV*h!!7bU3wbJJ# z$Fz)$nwchDQnDKk!!N+UOoM@<6x!D}Tn54Z2`+zgsQbUd(L$^%-OIao5j&r#<>;6RYEk2kQtfrx zX)gDv=iaC*fPMzAo#nakB&$3UbY2aeqh_IkbjK1#(H}F&|0!(P*_%_BU#DFs91?$s z0c%gLE_o@w&yM%`uQO8WsA`ypg|EKTzPqX9y;=6{@tfaA5FhX`3CmZUhL5%`| zeqrISg1QrM3tk( zl$BCvT=Ns!E66}Hyx1lL+AY=@?-q^MS^OK;+b=T4hntnzTQzXP|lNWj;Ef?MGV|%AfqCu6JDu#U6{Q?gSql%Sz2;|!lMcWlRu=AHg zITxWWGFbj39ou8DlCo6pXcD@_0|L*U3Iz7{MO)nGLwg-s%kW}{q~dBdI`9)Q5TRvZ^gv&1VGUL4fIm?2~qlWVh4mhzkl zg+gx%Dk&LJ-MGHmYc9J>({SP?D`brHM#q-VN%+IiRrz^ovMf>jKq&FyC@E0}oY{w0 zyJ#qv896zdl#gh9C|_89yxHaUqNW+TQCUc9W?PUpv{^(kiFk#+(!<#N{Il7t^-HT0 z?C@1rn=PKb5N~~VSNny;Eqfc+N=%nwegY@u@cMqwSG!@fl7R{_O;ucOuG$sXP;z=u z(ya&GcbO7_kIO=vXja>aCv ztS^a%jcY+sTF$h(RZ1==vT{y4>n*0j<4-Ek}5Tp?oI|#yjqcSC1A77!njH z_Ql;EklZhjXONovtxiAvfo>3HDZbmHNghnrbDO&WWvB_D31n z#Ms2nBCPo?)&f9ZaWLP(47@^cJ^>Wph`?uzn7tG07pSa$ItSDqK{(&&`zA1RxC6G7 zqC)4?X-;`Ddr+N}NrcC<5^fN*Hsup`Jzh_aVUCm_jU7mn_}495a5%uu$``WB-y&mf zCiN4qyq|GkPpFO$+m}C1wi#P@=KXi-kDq{_zyjWg`aZ&UKPOXulC-Kp?6E|AV)b=N z+Sej%?(B%#`<(7Dw?bL<9ob@Ro;&a2RlSh)eMIhl%GiGqw6d+<$pmN(YBZc81niR*%~GL-f>vlD4GX3;!7E#F76Pdd(G`$(W<{vLD+5t zge{rgZ;>P=X?qeoqE>^LZb)o2b{JY=b00+A-hI?nE2VKL=G8dyec)^HNJpF@8(Rp{ zIM8GUsbnl{Hn`|c)dWhCa>h?l@)Lqez>Y!P`SnmBLq5!*Epx}{+ z_CX%h@|Y$!*m8K$u~0j5#6)lHtlEM7L?FIvF!jp3?DhE+W7QukggT1gW*Bu|JAQKA z#JGbU%Rx#UA@X1?ID-U; z6(-a#7*anjP+`c?qRWs35G@JQO`F1rh@Fy*V+e%bxG$j!h6)xFAD8o)!$PSg=i9AE zlzNcl47hS));c$I5M!49eUft^edC;u%%j{jiRGOWy#nBC2x* zJV<00(a#2U&FGzmS4Z=AK~fLvokmcH^A85U!1fPb0dY0K(LaE#yZz(e#(uiQ6KL(ae?R`jkpQ~>>A!H3USfr;(xY*V}O*Vomi&Z zf~4|X?SEv)Sc!Ms%&5jAElbHEGDaaPi^-uwQ0jn<${7;|(U36+fk0LXVfrj#`dn_J z!E-?mNo30e$)(Y?VX)XnUAaTzfvr0sWO`Xn4OV4|C2D*CR%LiiI_7+%DRGPdYmp!w zVQiY#S9|Nj7KzFb3VTb=Ib?K-dM&En3D(s_H;;>Ots_dh9~aI}Ruv{>I!mz7GK92j zlBvBv{iM_Pc-b)`ap_a^=&Se!aBvnFRSL(D!#nBogfKiW)^?qvPt7yt^Tcq~LDqVm zbJ+d%{KeOZrG32gc7@tO=|})xsfLUAj!GAqFoRb|08-_*K1Ub(!#DgeIm%^$6LIlo zT;HNZ3O*MWM-l4w4C zS&=n|XCldli3D{bqE(!cNC=Vqr+oHyQF}j4*&E@KPx$X{X_uAqD=OtDl?tzn-?s8w zD`i&}6&(UDGuDyqV)``-PiPg1ShZx4?Ko76w=vuxaIvnEvZ35N6d1ur5k#&(U)@`{ zO@8IYS=uRHvXwn*ROsZbpQK^un6-PyL+Tau+uf=^*^q{(+K0G`cXm=!Jg`U1a7J+b zkIud_Age8C7wHZG>F!35?(XjH?vjv@4(SHz5NV{lL!`UAyQHM<%Q@#>(a)pjyTc#& z^Q^Vk9@cvHteI!5y26yv$*yMr_q1ZroYMDb-ml(DkHoR{)kXT;7W4R8+|p(;^-*l1 zUd!yNaY7&cEiXVyOSk+P5(p>+?RRwZ&)>37xzgX9GgZaHR&fI7A@%)&<+LU&@j4%H zPN#140E}7KXYp5{Sug~;&t1)+SQ=RL^c>KRtRX)s<`b${UXf1%SEIi3i4!TpM2XA~ z9~)#%oxBjpTf*jXydB@Etj1I4$Zc`BXd5v0#);WaJM&6;xNaHZNxwa6Hv*EdodJ<* zMGFnDgbxUv)Ey6*8xifS)Bs7{@klp2f`=HGZNA#hfS~oB2|z8+UXitUHCaz+=`T6w z>+UVY7L0UUqB$`&gQdFEQlgSk`zG+yoM{;Pq^*U{JiJDSr*{%3>N_lDcV8q7CK%a7 z#6|uU8WsNjRN?N*qGQiUp~LM9+i6 z&l3$oLyW-J^txrscYv9st7TbV!wn_@S4j`r76~vgkbO8?B#!hlN#wRh`&?)P_a~y>|ROU8JjRR1;k? z_zwP1SKEXr1|435(;cpAnlq5u7|+IUZY&$5_3@^ zQm6z3Sc>Kz9EYj!t(vTN01aooxy-{$-Bo_*VSNkM;7BbW(r3gejYfoQMzUhs}Hvo|Cs&u|d*;exBp{9LHb;mD}Z^{J{| z>3OkA@x~OLW%(vXzy&hyEH*5}qje}>j3WUHtVV^%87YlCQ)}&DuO=!|9Nb?oTE;Gg zBzCV*5CP@>BHz3p%zjI!yA$-~T}U1em^LS9_i*zHN0Q~W*;Z$Z^-D6a>st|__` zOF?@3|YGe;w^aFT)Kvz_F_0yMkP8^;>*2vxPVLiR@{Dx=(y}?!}HPf zsS}@A?MSy7;?uHlv=gF9zcn$55XC^xqO~B{jeRql2 zzB%HZ9;Zgi9iy3aIzaJukA+LB%|+EBP27~mI!#qd;SEDNa)~yWg3WsWfK{q`dD^jO05p2Nrst9vs^ENrtE_7dDiMw02 zO%zRV6#TGe1EYSYK55~mhqs2kLX5U3Y+`~ntJnvL*5XCfDSmdI2t1Y$SttbP+H?X4 zRu{QvIE-V*Qhx8SkEz=$aBN?$Jcr;6w9N;hCDJ^6OLfID^-Se?iGAxC?COLuP?XVV#v!Jhq#ssUk5$D*LH|eHtMS!6``@ zq-1GH{`|9dQoTvbJvFxPv0-Mat!2Kr#m-|+xh>hS=1I#=->4R3Hk?e6o8KZH5|NwU zqRu0ujWj1sEpQQR={d=eoL+0Sz1g%^5sDZhvgW2KRd$XiS>c4o%h4+6dhchpcMEqYUiZH zXD^)C#(VQ7%$AE7fUkVnp>7r6cMK_1F8StZd#p=9>^nEV<;Y{KreG)3-D?kaX+C5+ z`Y2QMsOMMPb5H$xw>FrVez%PZmv5Vy%mFHlF{!u zR}=nFvHwLEqv>Uz3wWRI`#F`}w9dt9cQLbg&YKUTFq*$y%g0g2yPNi1K1|9r#df$32Zc3*Z;J9d#t$b0~@=%f*$SpZz zb!AtA)2Cv#*9p9nZ125K z_2wyOzVElcO4&FDgITqaJfurnd}#N$3Q@?0xrCt$Y}U6#F`6c(JkC&kTbvaSqJ>-? z+?6sqOHUrJFIs8Ppc;&$&-6OPQ?QdXRF+4=a?ORY)0@O+p}jkCx{pr}ue<9RCv{po z(JJCaaEFT|_6D{s@J$y5C&A$A+r(DBHrWsfR$}f|j(eyy_eMXNw2O$)%dt==6wcAK4Sb_DFA^pq!UnO;){a zQLK&I_kfx=zi0y0@rvHfY*A3;kXk7GXcObcD#exjAx$*BDYp3_yAnJ-w=!=^p_Yn* z;;V~1^j%skzs=yvA=W0D8k@|z zm}hR0CbG>hoZBP(LvAZBn7{{ppMkIO`wRCCPfc!Vvb|Cv9Xd-cd|^-szFv&jtl!T@j8A7+orN3?JZwbb~%)UmSa|&WAf)o9TIm+9?FmI zII|pW?}qK1axvET8r$+Efkm#S#|fMkbheIc6PNFOE71rK9Zv{+fmh;@!-pe$|CC7dr zAw#Wxn_ybm@Hz0cJL|UCxjZA(YZga;FY?&DsU2fx&ov>?yc?Znjs4k){CR~HT}R33 z0w*%bn%#<64bphXIE)}dOX|JoFMg+r9<+-=?F4j?5(+?m?)XcGlqAwndsWhR=aM3~ z#8H>wRUZYWQ?y5}0;@vsi`2;Vm^B%6#7Yt@5op4~_BAKiuq!BnyyZyNGxP z1%?b=kU5dUX&t^hNUA!pby6mS%rU^+~3Q7;NN*-AVxk*^{l zV?{C)c}=G5i0TrSSmNCJ<+APLY|46!xV58uwLY)Qw$aF%CEyf)V899;A^QK) z5qG>wVWaBJz8%O<(Ys5>E;-kZR#+qI?b%+;$gUfDJ#gbb0diLmU_l;>z@PM*l zqu=Tl68zrX{@z_YlpZhi(79^X!w{)KA@%tRviME0+9nI|F{5RH%~}!p<){{jVW=%% z?-{oN?qJAtJcD(xt&&DC{wj{2e^0VNie%i*y~TFPb~&>}a=o?0^8j8JB#b@CG>5pVFXB_y27QjA87Zh!oz7{E+ZC&xnzYgsbce8 z;3*b|o1|jPL*1HMwfR{p=%B_{-R|n-65~450nV|TL}+)BiaCJp-eI+41SD+B`k=hP z^XybXf*R%c&P3i@lB`&-vXVr<)?t#0dJS3|RD{vdhn%?<$~*O%hp4Yp^>;U;I+wZY z*Dx^Atox+mA*{PdpU8vPaFIgjRd?XC8k=uytMGec9tb3&IZ@FM@SVTxL>Gk4;MB%Y ztuusJLc-=SZg8fmO|*I}9Rr zoE?0Q>KsZW;V^_vS)}RVR%hE)L|ZINU9QOp*JrB&`ptNY68Kq?IyxTod^6$e%`UA) zCAs;Yo|n`sX}qRtViyjQJi#km)V7*10l8>Hm`V#2HO5@pWfsY5BiI7^Ll|ibpSR8& z;>f?1QBE)b^L^W-l&41Pz!A(j#}7au?4RUfP6k#`X(p5SAdzkP%EfpX?pIE$W_ZnFw*d$(Vz==KLx?R09Y=^QdmR;>4%{ikX-6M> zXz-c`ST>&z<3>}pZu!mApS}z6(os62JsdfE#zpaMeW_Kaw#Cak!n5bpW_KC-K?L$N&9-N+;6B6K*o7R@5_ku@@ONa!@<%B0MwehV-_Zg72)J29ilK&;Dv}*@Pd&u zMu^k85;)OxE2)33l5Y4e8VrINSgcYG2~n-?;yLOfzJfUM7F}6tidT4aW6Syem*vC} zaFY$cJ8mTmV)c;&*yk>O9_BFa-dsoF8qf;)M^n|>qONI_VXE)WUj>{PaWHHMfya31 z7BgPG(XlPVxm6lkwlq0L;PUa;G^A5CI50f#jya1#V@*uJ9Lnt7!c0%~zm6*Bv9t3u zeR%A&Dy&>s56KPrBZ`ExlQWgJnw(ypd~nJ+8c`I&`wtKd4%YI}8AE@oy8QmEQ?RgjJnL9WrB)|DXkZn8I!B%3?4$t$6QhaMB|t1hqzFnUeV=JP zv){h|A*)5ar7~mtQ6JEmSt3mA)s^1GViMcde9!#d$yuK>P=kvpzRD|X~;^ZQ3Sx3Fq(S*>k-msaDl!JZ;P!FA+Gdyw9hWH}Wi1)l; zhpq7ZH!P*eh){K0Q_k5Q{PoH_q=vI?yf31*QE=;EexH1$#>lRf{Pijh;GqO|4y!*oYxa0vdd&!FzO0`2w$v8_11qZ?O zv6t+MNE4RAnX=Bp$Q1yeEtt6p6P3I|AnV!5$8< ztxD7tBnwS`x1mA`mM}VcO=jB5vw0NWsj3;A;3UAa4dGaJnuqp;=ds1YMpR3>Qhl6B zk-geq4CMeP-OgLaSy97k^lZ60;WO;_3ha&XtH|^wT-IOGQ@*er-p6%REk-m^;< znX{z1DF2ulMMXc!k9@83=x?NxxG=DQlg{n8Cmr#xPr4`m_V;1uucBd#yoGx2X`xc6 zMF);$xQ2zu-rfoS^SF%e2EfbECCxRrx@+A8=5BnSB$Q` z^kZfg>{5X{0_p4?2LdYGE7nDEv$*ZvtH5VlOTmE zo^O|zXy-7fIfxpB(4Rv_HwYP2*&3h8->mrhbi<6SX1zNRloGQd8X5I4W!)SMwo8h< zI{YF8CpB3#o!!ZvA9|0fJvgY$J3s)L4C2F}G~_;Raq>)aX4YOTOqcdEhtc;#92>cW zV>m92ua~yh+IA1}cs%rUyQrWl{hH&yXwx#)ZKFsW@_yQ$&lqhJ!MzC6c8X6`9PAy+ z3vdAIaWBT6Y6UKu9bMlD(3I?Y|Mxd)DP*?X$cOMV!_!!5F z^49S1l|iY`VpC1b-)wzEX=vlXFgZq%iYpvc79{JY5Ux|g0755$r>HZ{TzC@}(&1FW z6gJ+FL1X(8lUf%H*6b3m{Y&+lt&g1)GCq7}u^<^0+!OX2!DeFET&*{S$>d1q=AqUp z?+H-Eu-hr!^to8F0+QX(nQpYW+|~<9 zyL?Bf$qc%ie4D=dT*;C54s|?V1XDz<8v5CopNM6@LyEwciyeKPO(wS1#aB z5**n?3sCJgBum+2WT+dObCF^nCw~tWVZ1SdW?7^hZagENkCa5%J0yI)CsevGjoJ-T z^uB2l2x_EuT(FmiCIy(nb2JuqG ziN|e*JsE_mVYG`1$N{jY;hNQLVg^M*o1rO=`S5ukn@Ji?H7SflzwLAkjIqZ0CQdXh zlpcFJSsGiOqP+yTHB2SXYuCO!e*c1{N(ei@tM02&J^OQX(Maa&SNYyT&CKn66O|YH25yx=rH6m9y>vfvFEEJx3<)%>A%BNNcC!_T^4dgRYVj&FIDmMfd{fk|T zIxG1)lwBb1HRCHtp4K9P(O&}hxgEcC6M}_-0ZC{z%pGO*ZGWog?rc+Aqm^%I8!6FQ zGc6Lkq2X>0Sc@J>{_13`VWq&?KEZ^+op(7-Nmg$^I@EEmsz5ltKb0(*t|oK#QG6AB zl~r2NEm#EaVinY4Z|lYZy$xtk7jcW;&y_QRLAt>H#S9c_gv=>+2xd-z?D&}=#fOhE z=*CIW>_Xxy<1jg^A>uI%C{D?W{BlG&lJ{Hm;=x_h5cI+Y%HGbTKu08QaVHYoE(5bo zX?_KqNyjJe&J&Nag|fzqNCpH3+(tR~6PnFKa*`zHJ&#K_ubObjY8X6P^||70CYG>e z)B}^la+E%m3yz8>S4Iza5f107^+U#BY+Qxfy&9C~7Dgn4>?cM}TYY#{a@-V@1nHQI zST7H$Md4Q>$g>7r|6DtVPD?H(whNU>D2b0p1w|4nd=uFvIGxl3SLtn1<(bioHD9R- zTzamtx5Iwk32^;aN4MpH-8Z+hBce3ix`c>*n?;UJOI>w`OpW&ZdJ`{z<{!8(M9m_) zFY65IJJ~U$cg!U#YZg3@5%Nb$_h+dPEl>pjHK-)>VoeOgg~_7kmA5zSgT9RctyG=M zN|W|cXcy1-QVpCi(oE{U(b*|(|qkw0ZymIEy>QXZIQH?L|$#?@8vA4 z`bZ)d3$sk&uNvCyJgnh^j=ijYGJXu7B|?BjRDKhe*3H_SHfY+ct(mz%JYwxHTnVQc ziCD8BQfO*WTWITZck+tIXwE_(&+qbO39(UJ*+Duu)Ko>0rtVCKOr5N`IkWnre0fKcumxT<``PVpO~l@XO_2%gNTS64asxdMY>u?P}!py=jJb%F*ndF zCkwRW@86nC+TKYYq?W}wiJ#yAU(yn|$@ovNVFeN-`yxiy=g%?}?+YPkd%7{Y%nCzt ze}rB%VfL+ox>(`?ZhX%-knWFF;>lCLSQRj2<#!kn1^SiVd#Vs~Y1Z_1tDw8ozguLy zL#~=ex!B4pI1vl!Y(OibO8Mo(7E!%6-|{;>TrwZd>cYJK4xFXsuS-!W)q!lq$`oRS z%A;Nd@s;Yi#Kq!bg!f1!O>#}d2X-XE0hA(&b{QI5nY%Q)b)%^}?@NT6@1vC!T@_8+|$~Gr8Ym_BB)zQSb@&Rvs z>YU3hWeP!`Y&FZDXZ6}BVDF>ae!J(V_dF|rK0?enL->~dKhYE`G?db3n8ML&vX@>9nj`fc`?kDFY z*3v11yaLkCD!j)z6x~^@?Rg+?frJ098l&HcI_3n#_h^xR7v}jFkvfG(4X!_sU#-8% zFJ6O~rc`~^2xj4AH#6R9))isC|8r_kpO7e@uV&G(PJPB`#w@5F=Urr8@0!08V2zmR z)sFrqMu)*Vyf>FqM>agqINLptDSQ|qg{8g7r@uu(bIMTWp#l0+aKw5ldQgn>{y+K~ z44}XG@cwI1UQ4bcJdwVi{rFUo?q$IahoShlVpXJqKn=#u7fjzpmP|MU`cu%y0{T<* z0{T;APCI#AyL0YJoU1>^dC(zkRLE7*WBMe&PQpPUG(04^zB|J;RXO~q`^uG+v&6|{ z)OuoQ$~sAP-F~PGMb|(K?UDX=FTX(7qu&J4vx9#ddA8ADmD~BIUACZbcmo(OQFCk8dmAxBoHH6N=@>PdDh&Goh2^f_dw0jC9K7yo5HQda_rj zmOB$WDE)a8?A*%EU%BTp*Zd73tdS`o(vw^$MlZ8zt!Ip48z>=u_T@A^18oQ|{dAwr zQf!GiT<+?NG&CRy!2KF2!L^1INRuy$W@nM)p9U51H&SQlDlL*w?jc}bkYx!onk;H@ zdp24dLHqgG7PdH| zqWhSRs*)~k)Jy$_aJXvbH)`X<^rxX!BZ7y21(a;dPBOongnY^s;HqBkbF@w<3*mJR7e$#|| zS>>h+p~`csV{(ZGn1l@rB?9Gy zvOf|dB9)spPuW6-*=4vZq+-y>eny#UvEtV(BSk90LG%IG)hcrdmbndc2|qqJJH!$e z^Qr=~o!r+7EPDl1o#bk(LmrE5r1hck{RS+y;Vxr49QaDMS_pFvygqUtZc{zjfU$&5%`ov5=xUMV%QbuX#y2eawLD{%x0)~fi4uWuE!XHgUZg2sw$*Fr>cZ} zLoLHORh2b#(0Z1skadV%|JrsRWaV&TVs3+q%*q17_T)f%$SzekP>#G|(GZ2!O$#^M zNq9DH!2)eBebE@lr&`l_8>g!>JmWmK|km>)+=*Kj?<6pl4A|%;Kt#2;+?_Spk<< zop0ZENb343+1mZp(Y0lb0|GmN2}o|A!tS$g1yXQ_vIFCt?-A(ysX4Tb-E+0vrckQdeIN+*M^+Qrk;h~rAO9T6A*oz7jTPmyF>7Rdc}Aw@FgA0=W1Xr zILrJQfcrRoB;@);$mqug<7M|*ro+q1Z)_AYZ%X9UCUiYPCxxgWW{Z*dhgF~f=q*gm&TW3J?zEnc((7Bj4}frawNIi-=uLz%AK?=WgsY> zU7`fQ3c}P)#3|IrNd)Q)r)sjF`Y_Y+ZpsOc^Xeg6Y8>N9l+CfetQ^hznq*kUt5FH3 ztLH(>gfFpR6F& zQ=L$+@^2e)4kw?dD`IUv1QhG69@eI|Iguh+mXS}C2_;r*Zy=(EHEePc@z&HNd|c1mME_ z_p9|QMev{TpQ`0PlJM`whw>-cR^v^>)6;^#zhxl$Pfc(VYKf+&p>_-va zpW&YhCOxvc?-qga2l!t*=u^R=$Gn5@_JZ^efIq4({XEmBGCz-cMc<8#><_^IIN`4+ z{8X6ZQ6%WQL6iRy_en+3|DEywsE7G^@=puRe|(E&fa>yJyv2VTv0DAR z2?5;xzrp_+`DtP2<0Z>?s|F+&{2uvfG3Qe~rJon)X?@p^J8(GQh5Yw1e*FYbOP_vp z$UVRY`k&B$4g54u_{XK8<@yuwKmYuH^qZ&oJwGmuy72#Ij9)*&(?G(I1BR^_-tF&>vS} f*zA{p|AX4gN`L{1%z=P#0YA0SKtN0ukAM9i2(pxg literal 0 HcmV?d00001 diff --git a/android/src/com/henrikrydgard/libnative/InputDeviceState.java b/android/src/com/henrikrydgard/libnative/InputDeviceState.java index 043c046475..a91e7301a5 100644 --- a/android/src/com/henrikrydgard/libnative/InputDeviceState.java +++ b/android/src/com/henrikrydgard/libnative/InputDeviceState.java @@ -53,36 +53,19 @@ public class InputDeviceState { return normalizedvalue; } - private static boolean isGameKey(int keyCode) { - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_UP: - case KeyEvent.KEYCODE_DPAD_DOWN: - case KeyEvent.KEYCODE_DPAD_LEFT: - case KeyEvent.KEYCODE_DPAD_RIGHT: - return true; - default: - return KeyEvent.isGamepadButton(keyCode); - } - } - public boolean onKeyDown(KeyEvent event) { int keyCode = event.getKeyCode(); if (event.getRepeatCount() == 0) { - // if (isGameKey(keyCode)) { - NativeApp.keyDown(deviceId, keyCode); - return true; - // } + NativeApp.keyDown(deviceId, keyCode); + return true; } return false; } public boolean onKeyUp(KeyEvent event) { int keyCode = event.getKeyCode(); - // if (isGameKey(keyCode)) { - NativeApp.keyUp(deviceId, keyCode); - return true; - // } - //return false; + NativeApp.keyUp(deviceId, keyCode); + return true; } public boolean onJoystickMotion(MotionEvent event) { diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 4b4a548290..d00741044d 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -92,7 +92,7 @@ public class NativeActivity extends Activity { private static boolean initialized = false; // Graphics and audio interfaces - private GLSurfaceView mGLSurfaceView; + private NativeGLView mGLSurfaceView; private NativeAudioPlayer audioPlayer; private NativeRenderer nativeRenderer; @@ -267,6 +267,7 @@ public class NativeActivity extends Activity { @Override protected void onDestroy() { super.onDestroy(); + mGLSurfaceView.onDestroy(); nativeRenderer.onDestroyed(); Log.e(TAG, "onDestroy"); NativeApp.audioShutdown(); diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index a39e00ea45..79f1f1725b 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -1,6 +1,11 @@ package com.henrikrydgard.libnative; public class NativeApp { + public final static int DEVICE_ID_DEFAULT = 0; + public final static int DEVICE_ID_KEYBOARD = 1; + public final static int DEVICE_ID_MOUSE = 2; + public final static int DEVICE_ID_PAD_0 = 10; + public static native void init(int xxres, int yyres, int dpi, String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); public static native void resized(int xxres, int yyres); diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index a3654036ed..fce2228ed4 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -3,21 +3,29 @@ package com.henrikrydgard.libnative; // Touch- and sensor-enabled GLSurfaceView. // Supports simple multitouch and pressure. + import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.opengl.GLSurfaceView; +import android.os.Handler; // import android.os.Build; // import android.util.Log; +import android.util.Log; import android.view.MotionEvent; +import com.bda.controller.*; -public class NativeGLView extends GLSurfaceView implements SensorEventListener { +public class NativeGLView extends GLSurfaceView implements SensorEventListener, ControllerListener { private static String TAG = "NativeGLView"; private SensorManager mSensorManager; private Sensor mAccelerometer; + // Moga controller + private Controller mController = null; + boolean isMogaPro = false; + public NativeGLView(NativeActivity activity) { super(activity); setEGLContextClientVersion(2); @@ -43,6 +51,18 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener { // setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); mSensorManager = (SensorManager)activity.getSystemService(Activity.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + + Log.i(TAG, "Initializing MOGA"); + mController = Controller.getInstance(activity); + if (mController.init()) { + Log.i(TAG, "MOGA initialized"); + mController.setListener(this, new Handler()); + if (mController.getState(mController.STATE_CURRENT_PRODUCT_VERSION) == mController.ACTION_VERSION_MOGAPRO) { + isMogaPro = true; + } + } else { + Log.i(TAG, "MOGA failed to initialize"); + } } // This needs fleshing out. A lot. @@ -98,11 +118,103 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener { public void onPause() { super.onPause(); mSensorManager.unregisterListener(this); + if (mController != null) { + mController.onPause(); + } } @Override public void onResume() { super.onResume(); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); + if (mController != null) { + mController.onResume(); + + // According to the docs, the Moga's state can be inconsistent here. + // We should do a one time poll. TODO + } + } + + public void onDestroy() { + if (mController != null) { + mController.exit(); + } + } + + // MOGA Controller - from ControllerListener + @Override + public void onKeyEvent(KeyEvent event) { + // The Moga left stick doubles as a D-pad. This creates mapping conflicts so let's turn it off. + // Unfortunately this breaks menu navigation in PPSSPP currently but meh. + // This is different on Moga Pro though. + + if (!isMogaPro) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + return; + default: + break; + } + } + Log.i(TAG, "Moga KeyEvent " + event.getKeyCode()); + + // TODO Auto-generated method stub + switch (event.getAction()) { + case KeyEvent.ACTION_DOWN: + NativeApp.keyDown(NativeApp.DEVICE_ID_PAD_0, event.getKeyCode()); + break; + case KeyEvent.ACTION_UP: + NativeApp.keyUp(NativeApp.DEVICE_ID_PAD_0, event.getKeyCode()); + break; + } + } + + // MOGA Controller - from ControllerListener + @Override + public void onMotionEvent(com.bda.controller.MotionEvent event) { + Log.i(TAG, "Moga MotionEvent"); + // TODO Auto-generated method stub + NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_X, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_X)); + NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_Y, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_Y)); + NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_Z, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_Z)); + NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_RZ, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_RZ)); + NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_LTRIGGER, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_LTRIGGER)); + NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_RTRIGGER, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_RTRIGGER)); + } + + // MOGA Controller - from ControllerListener + @Override + public void onStateEvent(StateEvent state) { + switch (state.getState()) { + case StateEvent.STATE_CONNECTION: + switch (state.getAction()) { + case StateEvent.ACTION_CONNECTED: + Log.i(TAG, "Moga Connected"); + break; + case StateEvent.ACTION_CONNECTING: + Log.i(TAG, "Moga Connecting..."); + break; + case StateEvent.ACTION_DISCONNECTED: + Log.i(TAG, "Moga Disonnected"); + break; + } + break; + case StateEvent.STATE_POWER_LOW: + switch (state.getAction()) { + case StateEvent.ACTION_TRUE: + Log.i(TAG, "Moga Power Low"); + break; + case StateEvent.ACTION_FALSE: + Log.i(TAG, "Moga Power OK"); + break; + } + + default: + break; + } + } } diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index 81b6e31e88..55c1743c1a 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -15,7 +15,6 @@ public class NativeRenderer implements GLSurfaceView.Renderer { mActivity = act; } - public void onDrawFrame(GL10 unused /*use GLES20*/) { displayRender(); } From 9e3175138673893b25cf91c9f16266178850389e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 26 Sep 2013 14:44:03 +0200 Subject: [PATCH 0690/1445] Reduce Moga logging --- android/src/com/henrikrydgard/libnative/NativeGLView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index fce2228ed4..9430e3d34d 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -159,7 +159,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, break; } } - Log.i(TAG, "Moga KeyEvent " + event.getKeyCode()); + //Log.i(TAG, "Moga KeyEvent " + event.getKeyCode()); // TODO Auto-generated method stub switch (event.getAction()) { @@ -175,7 +175,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, // MOGA Controller - from ControllerListener @Override public void onMotionEvent(com.bda.controller.MotionEvent event) { - Log.i(TAG, "Moga MotionEvent"); + //Log.i(TAG, "Moga MotionEvent"); // TODO Auto-generated method stub NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_X, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_X)); NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_Y, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_Y)); From 4688d00d1f1edb1c28292e2f0625c2d364b78cf2 Mon Sep 17 00:00:00 2001 From: danyalzia Date: Sat, 28 Sep 2013 15:33:04 +0500 Subject: [PATCH 0691/1445] Add ATIClampBug --- gfx_es2/gl_state.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index b9fcd83fd3..b5ac5057a8 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -304,6 +304,7 @@ struct GLExtensions { bool OES_mapbuffer; bool OES_vertex_array_object; bool EXT_shader_framebuffer_fetch; + bool ATIClampBug; // EGL extensions From 7ab16d7122af4f77f733626958800dc477bf4847 Mon Sep 17 00:00:00 2001 From: danyalzia Date: Sat, 28 Sep 2013 15:36:09 +0500 Subject: [PATCH 0692/1445] Add gl_extensions.ATIClampBug --- gfx_es2/gl_state.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 6a5e46db79..b40d783108 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -185,6 +185,7 @@ void CheckGLExtensions() { gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; + gl_extensions.ATIClampBug = ((strncmp ((char *)glGetString(GL_RENDERER), "ATI RADEON X", 12) != 0) || (strncmp ((char *)glGetString(GL_RENDERER), "ATI MOBILITY RADEON X",21) != 0)); } #endif } From 74fd618e39b12c7dd6d5c3b2c8854f989f323d3f Mon Sep 17 00:00:00 2001 From: adrian17 Date: Sat, 28 Sep 2013 16:30:55 +0200 Subject: [PATCH 0693/1445] Changed function name to be consistent with header --- file/file_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index 58e24122a9..426b45054c 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -99,7 +99,7 @@ uint64_t GetSize(FILE *f) return size; } -bool ReadFileToString(bool text_file, const char *filename, std::string &str) +bool readFileToString(bool text_file, const char *filename, std::string &str) { FILE *f = openCFile(filename, text_file ? "r" : "rb"); if (!f) From 6f76e02f4a9a1be9700d9478be1d968ea4b0c6f0 Mon Sep 17 00:00:00 2001 From: adrian17 Date: Sun, 29 Sep 2013 18:39:12 +0200 Subject: [PATCH 0694/1445] Fixed compiler warnings --- file/chunk_file.cpp | 2 +- math/expression_parser.cpp | 2 +- util/text/utf8.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index 6d61f11841..fde65fe970 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -219,7 +219,7 @@ void ChunkFile::writeWString(const std::string &str) { unsigned short *text; size_t len = str.length(); text = new unsigned short[len+1]; - for (int i=0; i valueStack; unsigned int arg[5]; diff --git a/util/text/utf8.cpp b/util/text/utf8.cpp index 378fd236c6..c236125b04 100644 --- a/util/text/utf8.cpp +++ b/util/text/utf8.cpp @@ -362,7 +362,7 @@ const char *u8_strchr(const char *s, uint32_t ch, int *charn) const char *u8_memchr(const char *s, uint32_t ch, size_t sz, int *charn) { - int i = 0, lasti=0; + size_t i = 0, lasti=0; uint32_t c; int csz; From ffb6a41d08a616f19c644434886522bb44187565 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Sep 2013 17:49:47 -0700 Subject: [PATCH 0695/1445] Add an auto class for net::Init(). Fixes http::Client destructing after net::Shutdown(), calling freeaddrinfo() too late. --- net/http_client.cpp | 7 +------ net/resolve.h | 9 +++++++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 068bc5c1c2..37a53b9d30 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -316,34 +316,30 @@ void Download::Do(std::shared_ptr self) { progress_ = 1.0f; return; } - net::Init(); + net::AutoInit netInit; http::Client client; if (!client.Resolve(fileUrl.Host().c_str(), 80)) { ELOG("Failed resolving %s", url_.c_str()); failed_ = true; progress_ = 1.0f; - net::Shutdown(); return; } if (cancelled_) { SetFailed(-1); - net::Shutdown(); return; } if (!client.Connect()) { ELOG("Failed connecting to server."); resultCode_ = -1; - net::Shutdown(); progress_ = 1.0f; return; } if (cancelled_) { SetFailed(-1); - net::Shutdown(); return; } @@ -359,7 +355,6 @@ void Download::Do(std::shared_ptr self) { } resultCode_ = resultCode; - net::Shutdown(); progress_ = 1.0f; } diff --git a/net/resolve.h b/net/resolve.h index 46a8b3e598..7de2c1c66f 100644 --- a/net/resolve.h +++ b/net/resolve.h @@ -10,6 +10,15 @@ namespace net { void Init(); void Shutdown(); +struct AutoInit { + AutoInit() { + Init(); + } + ~AutoInit() { + Shutdown(); + } +}; + // use free() to free the returned string. char *DNSResolveTry(const char *host, const char **err); char *DNSResolve(const char *host); From b7eb60d2b7f6a9314eae8194343cd52de4fde13b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 30 Sep 2013 10:11:16 +0200 Subject: [PATCH 0696/1445] OpenGL ES 2.0: Detect EXT_blend_minmax --- gfx_es2/gl_state.cpp | 4 ++++ gfx_es2/gl_state.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index b40d783108..2d3af0b83a 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -122,6 +122,7 @@ void CheckGLExtensions() { gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; + gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0; gl_extensions.EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0); #if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) gl_extensions.OES_vertex_array_object = false; @@ -141,6 +142,9 @@ void CheckGLExtensions() { } #endif +#else + // Desktops support minmax + gl_extensions.EXT_blend_minmax = true; #endif #if defined(ANDROID) || defined(BLACKBERRY) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index b5ac5057a8..53c87ce4ab 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -231,6 +231,7 @@ public: BoolState blend; STATE4(glBlendFuncSeparate, GLenum, GLenum, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFuncSeparate; + // On OpenGL ES, using minmax blend requires glBlendEquationEXT (in theory at least). STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; STATEFLOAT4(glBlendColor, 1.0f) blendColor; @@ -304,6 +305,7 @@ struct GLExtensions { bool OES_mapbuffer; bool OES_vertex_array_object; bool EXT_shader_framebuffer_fetch; + bool EXT_blend_minmax; bool ATIClampBug; // EGL extensions From a747241619a58e3d0230546da403a5a213b13537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 1 Oct 2013 12:10:56 +0200 Subject: [PATCH 0697/1445] Minor bugfix in gl_lost_manager --- gfx/gl_lost_manager.cpp | 2 ++ gfx/gl_lost_manager.h | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/gfx/gl_lost_manager.cpp b/gfx/gl_lost_manager.cpp index 50a87449c2..dd8d2f4a17 100644 --- a/gfx/gl_lost_manager.cpp +++ b/gfx/gl_lost_manager.cpp @@ -41,6 +41,7 @@ void gl_lost() { inLost = true; if (!holders) { WLOG("GL resource holder not initialized, cannot process lost request"); + inLost = false; return; } ILOG("gl_lost() restoring %i items:", (int)holders->size()); @@ -55,6 +56,7 @@ void gl_lost() { void gl_lost_manager_init() { if (holders) { FLOG("Double GL lost manager init"); + // Dead here (FLOG), no need to delete holders } holders = new std::vector(); } diff --git a/gfx/gl_lost_manager.h b/gfx/gl_lost_manager.h index a8fb0249b3..3d26ec3f3c 100644 --- a/gfx/gl_lost_manager.h +++ b/gfx/gl_lost_manager.h @@ -4,9 +4,9 @@ // track of them. class GfxResourceHolder { - public: - virtual ~GfxResourceHolder() {} - virtual void GLLost() = 0; +public: + virtual ~GfxResourceHolder() {} + virtual void GLLost() = 0; }; void gl_lost_manager_init(); From 6615ad5dd6386bb0db648c4f1b583e0d4905fa43 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Tue, 1 Oct 2013 16:14:51 +0530 Subject: [PATCH 0698/1445] fixed the 4xMSAA crash on android --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index d00741044d..0afcd398b5 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -249,6 +249,10 @@ public class NativeActivity extends Activity { NativeApp.resized(size.x, size.y); mGLSurfaceView = new NativeGLView(this); + //setup the GLSurface and ask android for the correct + //number of bits for r, g, b, a, depth and stencil components + mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8); + nativeRenderer = new NativeRenderer(this); mGLSurfaceView.setRenderer(nativeRenderer); setContentView(mGLSurfaceView); From b1065271c9a284696b15028f4efe981042f5e309 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 1 Oct 2013 16:18:47 +0200 Subject: [PATCH 0699/1445] Add a couple of NV gl extensions --- gfx_es2/fbo.cpp | 4 ++++ gfx_es2/fbo.h | 4 +++- gfx_es2/gl_state.cpp | 10 ++++++++++ gfx_es2/gl_state.h | 16 ++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index c2b5d6d2ec..a8e175280d 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -298,3 +298,7 @@ void fbo_get_dimensions(FBO *fbo, int *w, int *h) { *w = fbo->width; *h = fbo->height; } + +int fbo_get_color_texture(FBO *fbo) { + return fbo->color_texture; +} \ No newline at end of file diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index 9641dc7225..fdcb76a15c 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -31,4 +31,6 @@ void fbo_bind_color_as_texture(FBO *fbo, int color); void fbo_bind_for_read(FBO *fbo); void fbo_unbind(); void fbo_destroy(FBO *fbo); -void fbo_get_dimensions(FBO *fbo, int *w, int *h); \ No newline at end of file +void fbo_get_dimensions(FBO *fbo, int *w, int *h); + +int fbo_get_color_texture(FBO *fbo); \ No newline at end of file diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 2d3af0b83a..d4070894d5 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -9,6 +9,8 @@ PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; +PFNGLDRAWTEXTURENVPROC glDrawTextureNV; +PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV ; PFNGLMAPBUFFERPROC glMapBuffer; #endif #if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) @@ -124,6 +126,14 @@ void CheckGLExtensions() { gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0; gl_extensions.EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0); + gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; + gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; + if (gl_extensions.NV_draw_texture) { + glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)eglGetProcAddress("glDrawTextureNV"); + } + if (gl_extensions.NV_copy_image) { + glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV"); + } #if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) gl_extensions.OES_vertex_array_object = false; gl_extensions.EXT_discard_framebuffer = false; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 53c87ce4ab..f9cd1224fd 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -32,8 +32,18 @@ extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; typedef GLvoid* (GL_APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); extern PFNGLMAPBUFFERPROC glMapBuffer; + #endif + +typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); +extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV; +typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum + srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, + GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei + width, GLsizei height, GLsizei depth); +extern PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV; + #if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; @@ -289,6 +299,10 @@ public: extern OpenGLState glstate; +// Extensions to look at using: +// GL_NV_draw_texture +// GL_NV_copy_image +// GL_NV_map_buffer_range (same as GL_ARB_map_buffer_range ?) // WARNING: This gets memset-d - so no strings please struct GLExtensions { @@ -307,6 +321,8 @@ struct GLExtensions { bool EXT_shader_framebuffer_fetch; bool EXT_blend_minmax; bool ATIClampBug; + bool NV_draw_texture; + bool NV_copy_image; // EGL extensions From 8f4a25c64a2240d4f7e4a77fdde72b855f4bad73 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 2 Oct 2013 00:04:14 -0700 Subject: [PATCH 0700/1445] Add an atomic_flag implementation. --- base/mutex.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/base/mutex.h b/base/mutex.h index c2b3343379..9c0b92e9f2 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -12,6 +12,7 @@ #define NOMINMAX #include #include +#include // Zap stupid windows defines // Should move these somewhere clever. @@ -23,7 +24,62 @@ #include #include #include + +#ifdef BLACKBERRY +#include +#elif defined(__SYMBIAN32__) +#include #endif +#endif + +#include "base/basictypes.h" + +struct atomic_flag_init { + atomic_flag_init() : v(false) { + } + + bool v; +}; +static const atomic_flag_init NATIVE_ATOMIC_FLAG_INIT; + +class atomic_flag { + atomic_flag() { + } + + atomic_flag(atomic_flag_init &v) : value(0) { + } + + void clear() { +#if defined(_WIN32) + _WriteBarrier(); + value = 0; +#elif defined(BLACKBERRY) + atomic_set(&value, 0); +#elif defined(__SYMBIAN32__) + g_atomic_int_set(&value, 0); +#else + __sync_lock_release(&value); +#endif + } + + // Returns the previous value. + bool test_and_set() { +#if defined(_WIN32) + return InterlockedExchange(&value, 1) != 0; +#elif defined(BLACKBERRY) + return atomic_set_value(&value, 1) != 0; +#elif defined(__SYMBIAN32__) + return !g_atomic_int_compare_and_exchange(&value, 0, 1); +#else + return __sync_lock_test_and_set(&value, 1) != 0; +#endif + } + +private: + volatile unsigned int value; + + DISALLOW_COPY_AND_ASSIGN(atomic_flag); +}; class recursive_mutex { #ifdef _WIN32 From 5a5b02d79cec235b3c89aa48508f37db606a7fc4 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Wed, 2 Oct 2013 19:13:44 +0530 Subject: [PATCH 0701/1445] fixed bugs in atomic_flag --- base/mutex.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/base/mutex.h b/base/mutex.h index c2b3343379..08a46db10d 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -12,6 +12,7 @@ #define NOMINMAX #include #include +#include // Zap stupid windows defines // Should move these somewhere clever. @@ -23,7 +24,63 @@ #include #include #include + +#ifdef BLACKBERRY +#include +#elif defined(__SYMBIAN32__) +#include #endif +#endif + +#include "base/basictypes.h" + +struct atomic_flag_init { + atomic_flag_init() : v(false) { + } + + bool v; +}; +static const atomic_flag_init NATIVE_ATOMIC_FLAG_INIT; + +class atomic_flag { +public: + atomic_flag() { + } + + atomic_flag(const atomic_flag_init &v) : value(0) { + } + + void clear() { +#if defined(_WIN32) + _WriteBarrier(); + value = 0; +#elif defined(BLACKBERRY) + atomic_set(&value, 0); +#elif defined(__SYMBIAN32__) + g_atomic_int_set(&value, 0); +#else + __sync_lock_release(&value); +#endif + } + + // Returns the previous value. + bool test_and_set() { +#if defined(_WIN32) + return InterlockedExchange(&value, 1) != 0; +#elif defined(BLACKBERRY) + return atomic_set_value(&value, 1) != 0; +#elif defined(__SYMBIAN32__) + return !g_atomic_int_compare_and_exchange(&value, 0, 1); +#else + return __sync_lock_test_and_set(&value, 1) != 0; +#endif + } + +private: + volatile unsigned int value; + + DISALLOW_COPY_AND_ASSIGN(atomic_flag); +}; class recursive_mutex { #ifdef _WIN32 From 36b82e6159243cbf74d63f0d80c342a7291418e3 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Wed, 2 Oct 2013 20:17:44 +0530 Subject: [PATCH 0702/1445] fixed bugs in the atomic_flag class --- base/mutex.h | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index d59cf45000..ae108ff12c 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -43,20 +43,11 @@ struct atomic_flag_init { static const atomic_flag_init NATIVE_ATOMIC_FLAG_INIT; class atomic_flag { -<<<<<<< HEAD public: - atomic_flag() { - } - atomic_flag(const atomic_flag_init &v) : value(0) { -======= - atomic_flag() { - } - - atomic_flag(atomic_flag_init &v) : value(0) { ->>>>>>> upstream/master - } + atomic_flag(const atomic_flag_init &v) : value(0) {} + void clear() { #if defined(_WIN32) _WriteBarrier(); From dfbc5f3644b0ae85b522c9fe8c5a612cfd48868a Mon Sep 17 00:00:00 2001 From: Siddharth Date: Wed, 2 Oct 2013 07:49:45 -0700 Subject: [PATCH 0703/1445] atomic_flag needs to have public methods. --- base/mutex.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/mutex.h b/base/mutex.h index 9c0b92e9f2..9191ace08e 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -43,10 +43,11 @@ struct atomic_flag_init { static const atomic_flag_init NATIVE_ATOMIC_FLAG_INIT; class atomic_flag { +public: atomic_flag() { } - atomic_flag(atomic_flag_init &v) : value(0) { + atomic_flag(const atomic_flag_init &v) : value(0) { } void clear() { From 85648db42f0ab91b990f5f881ec84986ab57b1b0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 5 Oct 2013 00:12:43 +1000 Subject: [PATCH 0704/1445] Build fixes for Symbian. --- base/mutex.h | 2 +- gfx_es2/gl_state.cpp | 8 ++++---- gfx_es2/gl_state.h | 8 ++++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index 9191ace08e..9b92e831e2 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -70,7 +70,7 @@ public: #elif defined(BLACKBERRY) return atomic_set_value(&value, 1) != 0; #elif defined(__SYMBIAN32__) - return !g_atomic_int_compare_and_exchange(&value, 0, 1); + return !g_atomic_int_compare_and_exchange((volatile int*)&value, 0, 1); #else return __sync_lock_test_and_set(&value, 1) != 0; #endif diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index d4070894d5..a6e986376a 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -128,16 +128,16 @@ void CheckGLExtensions() { gl_extensions.EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0); gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; +#if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) + gl_extensions.OES_vertex_array_object = false; + gl_extensions.EXT_discard_framebuffer = false; +#else if (gl_extensions.NV_draw_texture) { glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)eglGetProcAddress("glDrawTextureNV"); } if (gl_extensions.NV_copy_image) { glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV"); } -#if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) - gl_extensions.OES_vertex_array_object = false; - gl_extensions.EXT_discard_framebuffer = false; -#else gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0; if (gl_extensions.OES_vertex_array_object) { glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" ); diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index f9cd1224fd..b0314f7d5f 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -7,6 +7,14 @@ #ifdef USING_GLES2 +#ifndef GL_MIN_EXT +#define GL_MIN_EXT 0x8007 +#endif + +#ifndef GL_MAX_EXT +#define GL_MAX_EXT 0x8008 +#endif + #if defined(ANDROID) || defined(BLACKBERRY) // Additional extensions not included in GLES2/gl2ext.h from the NDK From 5d1c9739e1c0d5251e04297d6c512ef0ec60b0c3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 5 Oct 2013 10:01:46 -0700 Subject: [PATCH 0705/1445] Buildfix for iOS. --- gfx_es2/gl_state.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index b0314f7d5f..74050d9cba 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -43,7 +43,7 @@ extern PFNGLMAPBUFFERPROC glMapBuffer; #endif - +#if !defined(IOS) typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV; typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum @@ -51,6 +51,7 @@ typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); extern PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV; +#endif #if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; From 6f95936da9665d7f8f4e5549ee800e751e888b50 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Sun, 6 Oct 2013 18:09:42 +0530 Subject: [PATCH 0706/1445] ppsspp on Android gains and loses audio focus --- .../libnative/AudioFocusChangeListener.java | 25 +++++++++++++ .../libnative/NativeActivity.java | 37 +++++++++++++++---- .../libnative/NativeAudioPlayer.java | 23 ++++++++++-- 3 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 android/src/com/henrikrydgard/libnative/AudioFocusChangeListener.java diff --git a/android/src/com/henrikrydgard/libnative/AudioFocusChangeListener.java b/android/src/com/henrikrydgard/libnative/AudioFocusChangeListener.java new file mode 100644 index 0000000000..c3dbfb7d9f --- /dev/null +++ b/android/src/com/henrikrydgard/libnative/AudioFocusChangeListener.java @@ -0,0 +1,25 @@ +package com.henrikrydgard.libnative; +import android.media.AudioManager; +import android.media.AudioManager.OnAudioFocusChangeListener; + +public class AudioFocusChangeListener implements OnAudioFocusChangeListener{ + //not used right now, but we may need to use it sometime. So just store it + //for now. + private boolean hasAudioFocus = false; + + @Override + public void onAudioFocusChange(int focusChange) { + switch (focusChange){ + case AudioManager.AUDIOFOCUS_GAIN: + hasAudioFocus = true; + break; + + case AudioManager.AUDIOFOCUS_LOSS: + hasAudioFocus = false; + } + + // TODO Auto-generated method stub + + } + +} diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 0afcd398b5..4f608ff7b8 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -106,12 +106,15 @@ public class NativeActivity extends Activity { private int optimalFramesPerBuffer; private int optimalSampleRate; + //audioFocusChangeListener to listen to changes in audio state + private AudioFocusChangeListener audioFocusChangeListener; + private AudioManager audioManager; + @TargetApi(17) private void detectOptimalAudioSettings() { - AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE); try { - optimalFramesPerBuffer = Integer.parseInt(am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); - optimalSampleRate = Integer.parseInt(am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)); + optimalFramesPerBuffer = Integer.parseInt(this.audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); + optimalSampleRate = Integer.parseInt(this.audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)); } catch (NumberFormatException e) { // Ignore, if we can't parse it it's bogus and zero is a fine value (means we couldn't detect it). } @@ -153,6 +156,12 @@ public class NativeActivity extends Activity { } public void Initialize() { + + //initialise audio classes. Do this here since detectOptimalAudioSettings() + //needs audioManager + this.audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); + this.audioFocusChangeListener = new AudioFocusChangeListener(); + if (Build.VERSION.SDK_INT >= 9) { // Native OpenSL is available. Let's use it! useOpenSL = true; @@ -214,7 +223,8 @@ public class NativeActivity extends Activity { } else { Log.i(TAG, "OpenGL ES 2.0 detected."); } - + + /* editText = new EditText(this); editText.setText("Hello world"); @@ -239,9 +249,13 @@ public class NativeActivity extends Activity { Window window = this.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setVolumeControlStream(AudioManager.STREAM_MUSIC); - - if (!useOpenSL) - audioPlayer = new NativeAudioPlayer(); + + + //intialize audio and tell PPSSPP to gain audio focus + if (!useOpenSL){ + audioPlayer = new NativeAudioPlayer(); + } + NativeAudioPlayer.gainAudioFocus(this.audioManager, this.audioFocusChangeListener); NativeApp.audioInit(); Point size = new Point(); @@ -277,6 +291,9 @@ public class NativeActivity extends Activity { NativeApp.audioShutdown(); audioPlayer = null; mGLSurfaceView = null; + audioFocusChangeListener = null; + audioManager = null; + } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @@ -294,6 +311,8 @@ public class NativeActivity extends Activity { protected void onPause() { super.onPause(); Log.i(TAG, "onPause"); + + NativeAudioPlayer.loseAudioFocus(this.audioManager, this.audioFocusChangeListener); if (audioPlayer != null) { audioPlayer.stop(); } @@ -313,7 +332,9 @@ public class NativeActivity extends Activity { } else { Log.e(TAG, "mGLSurfaceView really shouldn't be null in onResume"); } - if (audioPlayer != null) { + + NativeAudioPlayer.gainAudioFocus(this.audioManager, this.audioFocusChangeListener); + if (audioPlayer != null) { audioPlayer.play(); } NativeApp.resume(); diff --git a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java index 2d98e25f08..34e7b94cdc 100644 --- a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java +++ b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java @@ -2,23 +2,24 @@ package com.henrikrydgard.libnative; import android.media.AudioFormat; import android.media.AudioManager; +import android.media.AudioManager.OnAudioFocusChangeListener; import android.media.AudioTrack; import android.util.Log; - +import com.henrikrydgard.libnative.AudioFocusChangeListener; public class NativeAudioPlayer { private String TAG = "NativeAudioPlayer"; private Thread thread; private boolean playing_; - public NativeAudioPlayer() { - } + // Calling stop() is allowed at any time, whether stopped or not. // If playing, blocks until not. public synchronized void stop() { if (thread != null) { waitUntilDone(); + } else { Log.e(TAG, "Was already stopped"); } @@ -32,7 +33,21 @@ public class NativeAudioPlayer { Log.e(TAG, "Was already playing"); } } - + + //keep this static so we can call this even if we don't + //instantiate NativeAudioPlayer + public static void gainAudioFocus(AudioManager audioManager,AudioFocusChangeListener focusChangeListener) { + audioManager.requestAudioFocus(focusChangeListener, + AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); + } + + //keep this static so we can call this even if we don't + //instantiate NativeAudioPlayer + public static void loseAudioFocus(AudioManager audioManager,AudioFocusChangeListener focusChangeListener){ + audioManager.abandonAudioFocus(focusChangeListener); + } + + private void playStreaming() { playing_ = true; thread = new Thread(new Runnable() { From 1a4ba9ef86228425e738c6c23aa926c44807b5ef Mon Sep 17 00:00:00 2001 From: Siddharth Date: Sun, 6 Oct 2013 18:19:09 +0530 Subject: [PATCH 0707/1445] made unwated changes to base/mutex. changing --- base/mutex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/mutex.h b/base/mutex.h index 0c7d1c5eec..9b92e831e2 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -47,7 +47,7 @@ public: atomic_flag() { } - atomic_flag(atomic_flag_init &v) : value(0) { + atomic_flag(const atomic_flag_init &v) : value(0) { } void clear() { From 1f8e262730cbac4f3476d799d0b4e21215b7c736 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Sun, 6 Oct 2013 18:26:57 +0530 Subject: [PATCH 0708/1445] made a mistake while merging base/mutex. --- base/mutex.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index ae108ff12c..9b92e831e2 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -44,10 +44,12 @@ static const atomic_flag_init NATIVE_ATOMIC_FLAG_INIT; class atomic_flag { public: - - atomic_flag(const atomic_flag_init &v) : value(0) {} + atomic_flag() { + } + + atomic_flag(const atomic_flag_init &v) : value(0) { + } - void clear() { #if defined(_WIN32) _WriteBarrier(); @@ -68,7 +70,7 @@ public: #elif defined(BLACKBERRY) return atomic_set_value(&value, 1) != 0; #elif defined(__SYMBIAN32__) - return !g_atomic_int_compare_and_exchange(&value, 0, 1); + return !g_atomic_int_compare_and_exchange((volatile int*)&value, 0, 1); #else return __sync_lock_test_and_set(&value, 1) != 0; #endif From 0b1f4ad3c9da9e00eb3c74aba31bfbe582b15f16 Mon Sep 17 00:00:00 2001 From: "Nassim \"Nass\" Eddequiouaq" Date: Mon, 7 Oct 2013 03:42:42 +0200 Subject: [PATCH 0709/1445] =?UTF-8?q?Fix:=20SDL=20not=20finding=20a=20ddev?= =?UTF-8?q?ice=20doesn=E2=80=99t=20stop=20the=20program=20anymore.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/PCMain.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 34ddf020b4..c40f469581 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -527,10 +527,8 @@ int main(int argc, char *argv[]) { fmt.callback = &mixaudio; fmt.userdata = (void *)0; - if (SDL_OpenAudio(&fmt, NULL) < 0) { + if (SDL_OpenAudio(&fmt, NULL) < 0) ELOG("Failed to open audio: %s", SDL_GetError()); - return 1; - } // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); From 5d198025a5c53975f5ce6c41f2ebab303f4b8e90 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Mon, 7 Oct 2013 21:45:25 +0530 Subject: [PATCH 0710/1445] enable items to be highlighted. Will be used to highlight save slots in use --- ui/view.cpp | 27 +++++++++++++++++++++++++-- ui/view.h | 6 +++++- ui/viewgroup.cpp | 10 ++++++++++ ui/viewgroup.h | 7 +++++++ 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index bd5dc891be..8d4ad085f3 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -152,8 +152,15 @@ void Clickable::FocusChanged(int focusFlags) { down_ = false; dragging_ = false; } + else if(focusFlags & FF_GOTFOCUS){ + highlighted_ = true; + } } + void Clickable::HighlightChanged(bool highlighted){ + highlighted_ = highlighted; + }; + void Clickable::Touch(const TouchInput &input) { if (!enabled_) { dragging_ = false; @@ -250,6 +257,12 @@ void StickyChoice::Key(const KeyInput &key) { } void StickyChoice::FocusChanged(int focusFlags) { + if(focusFlags & FF_GOTFOCUS){ + highlighted_ = true; + } + if(focusFlags & FF_LOSTFOCUS){ + highlighted_ = false; + } // Override Clickable's FocusChanged to do nothing. } @@ -276,12 +289,16 @@ ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParam void ClickableItem::Draw(UIContext &dc) { Style style = dc.theme->itemStyle; + if(highlighted_) { + style = dc.theme->itemHighlightedStyle; + } if (HasFocus()) { style = dc.theme->itemFocusedStyle; } if (down_) { style = dc.theme->itemDownStyle; } + dc.FillRect(style.background, bounds_); } @@ -302,6 +319,9 @@ void Choice::Draw(UIContext &dc) { ClickableItem::Draw(dc); } else { Style style = dc.theme->itemStyle; + if(highlighted_) { + style = dc.theme->itemHighlightedStyle; + } if (down_) { style = dc.theme->itemDownStyle; } @@ -369,7 +389,9 @@ void CheckBox::Draw(UIContext &dc) { Style style = dc.theme->itemStyle; if (!IsEnabled()) style = dc.theme->itemDisabledStyle; - + if(highlighted_) + style = dc.theme->itemHighlightedStyle; + dc.SetFontStyle(dc.theme->uiFont); dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); dc.Draw()->DrawImage(image, bounds_.x2() - paddingX, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); @@ -381,10 +403,11 @@ void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const void Button::Draw(UIContext &dc) { Style style = dc.theme->buttonStyle; + if(highlighted_) style = dc.theme->itemHighlightedStyle; if (HasFocus()) style = dc.theme->buttonFocusedStyle; if (down_) style = dc.theme->buttonDownStyle; if (!enabled_) style = dc.theme->buttonDisabledStyle; - + // dc.Draw()->DrawImage4Grid(style.image, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); dc.FillRect(style.background, bounds_); float tw, th; diff --git a/ui/view.h b/ui/view.h index 69628ffc27..e11ed40501 100644 --- a/ui/view.h +++ b/ui/view.h @@ -102,11 +102,13 @@ struct Theme { Style buttonFocusedStyle; Style buttonDownStyle; Style buttonDisabledStyle; + Style buttonHighlightedStyle; Style itemStyle; Style itemDownStyle; Style itemFocusedStyle; Style itemDisabledStyle; + Style itemHighlightedStyle; Style headerStyle; @@ -389,12 +391,13 @@ public: class Clickable : public View { public: Clickable(LayoutParams *layoutParams) - : View(layoutParams), downCountDown_(0), dragging_(false), down_(false) {} + : View(layoutParams), downCountDown_(0), dragging_(false), down_(false), highlighted_(false) {} virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); virtual void FocusChanged(int focusFlags); + virtual void HighlightChanged(bool highlighted); Event OnClick; @@ -407,6 +410,7 @@ protected: int downCountDown_; bool dragging_; bool down_; + bool highlighted_; }; class Button : public Clickable { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index bfa8489884..c9c7d192c4 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -885,6 +885,16 @@ void ChoiceStrip::SetSelection(int sel) { } } + + +void ChoiceStrip::HighlightChoice(int choice){ + if (choice < (int)views_.size()){ + //hack of the worst kind + static_cast(views_[choice])->HighlightChanged(true); + } + +}; + void ChoiceStrip::Key(const KeyInput &input) { if (input.flags & KEY_DOWN) { if (input.keyCode == NKCODE_BUTTON_L1 && selected_ > 0) { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 1729830c56..9ea581f3ff 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -240,11 +240,18 @@ public: void AddChoice(const std::string &title); void AddChoice(ImageID buttonImage); + int GetSelection() const { return selected_; } void SetSelection(int sel); + + void HighlightChoice(int choice); + + virtual void Key(const KeyInput &input); + void SetTopTabs(bool tabs) { topTabs_ = tabs; } void Draw(UIContext &dc); + Event OnChoice; private: From c747582b4ce7c740a60eebbdf03eaa038044f897 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Mon, 7 Oct 2013 23:16:28 +0530 Subject: [PATCH 0711/1445] removed testing code from onFocusChanged --- ui/view.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 8d4ad085f3..f5c2b54724 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -152,9 +152,6 @@ void Clickable::FocusChanged(int focusFlags) { down_ = false; dragging_ = false; } - else if(focusFlags & FF_GOTFOCUS){ - highlighted_ = true; - } } void Clickable::HighlightChanged(bool highlighted){ @@ -257,12 +254,6 @@ void StickyChoice::Key(const KeyInput &key) { } void StickyChoice::FocusChanged(int focusFlags) { - if(focusFlags & FF_GOTFOCUS){ - highlighted_ = true; - } - if(focusFlags & FF_LOSTFOCUS){ - highlighted_ = false; - } // Override Clickable's FocusChanged to do nothing. } From d7cfc12cdad2af33f2926037a213ff6ed99f2d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 8 Oct 2013 11:06:38 +0200 Subject: [PATCH 0712/1445] Add another constructor to LinearLayoutParams --- ui/viewgroup.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 1729830c56..5e87227f9c 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -122,6 +122,8 @@ public: : LayoutParams(w, h, LP_LINEAR), weight(wgt), gravity(grav), margins(mgn), hasMargins_(true) {} LinearLayoutParams(Size w, Size h, const Margins &mgn) : LayoutParams(w, h, LP_LINEAR), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} + LinearLayoutParams(Size w, Size h, float wgt, const Margins &mgn) + : LayoutParams(w, h, LP_LINEAR), weight(wgt), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} LinearLayoutParams(const Margins &mgn) : LayoutParams(WRAP_CONTENT, WRAP_CONTENT, LP_LINEAR), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {} From 2382e34a2a14a3d7087cc0ad760d376d07858ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 8 Oct 2013 12:03:02 +0200 Subject: [PATCH 0713/1445] Initial support for loading OpenGL ES 3.0 on Android, and checking for it. --- Android.mk | 5 +- gfx/gl_common.h | 10 +- gfx_es2/gl3stub.c | 342 ++++++++++++++++++++++++++++++ gfx_es2/gl3stub.h | 491 +++++++++++++++++++++++++++++++++++++++++++ gfx_es2/gl_state.cpp | 11 +- gfx_es2/gl_state.h | 30 ++- 6 files changed, 869 insertions(+), 20 deletions(-) create mode 100644 gfx_es2/gl3stub.c create mode 100644 gfx_es2/gl3stub.h diff --git a/Android.mk b/Android.mk index e17e64e6a9..a7cb3c08db 100644 --- a/Android.mk +++ b/Android.mk @@ -55,9 +55,10 @@ LOCAL_SRC_FILES :=\ thread/prioritizedworkqueue.cpp \ thread/threadpool.cpp \ gfx_es2/glsl_program.cpp \ - gfx_es2/gl_state.cpp \ + gfx_es2/gl_state.cpp.arm \ + gfx_es2/gl3stub.c \ gfx_es2/draw_buffer.cpp.arm \ - gfx_es2/draw_text.cpp \ + gfx_es2/draw_text.cpp.arm \ gfx_es2/vertex_format.cpp \ gfx_es2/fbo.cpp \ gfx/gl_debug_log.cpp \ diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 5dedd12e64..1b395331b1 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -6,7 +6,14 @@ #include #include #else -#include + +// Support OpenGL ES 3.0 +// This uses the "DYNAMIC" approach from the gles3jni NDK sample. +// Should work on non-Android mobile platforms too. +#include "../gfx_es2/gl3stub.h" +#define MAY_HAVE_GLES3 1 +// Old way: #include + #include #ifndef MAEMO #include @@ -14,6 +21,7 @@ #endif #else // OpenGL +#define MAY_HAVE_GLES3 1 #include #if defined(__APPLE__) #include diff --git a/gfx_es2/gl3stub.c b/gfx_es2/gl3stub.c new file mode 100644 index 0000000000..19b78e7b67 --- /dev/null +++ b/gfx_es2/gl3stub.c @@ -0,0 +1,342 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gl3stub.h" + +GLboolean gl3stubInit() { + #define FIND_PROC(s) s = (void*)eglGetProcAddress(#s) + FIND_PROC(glReadBuffer); + FIND_PROC(glDrawRangeElements); + FIND_PROC(glTexImage3D); + FIND_PROC(glTexSubImage3D); + FIND_PROC(glCopyTexSubImage3D); + FIND_PROC(glCompressedTexImage3D); + FIND_PROC(glCompressedTexSubImage3D); + FIND_PROC(glGenQueries); + FIND_PROC(glDeleteQueries); + FIND_PROC(glIsQuery); + FIND_PROC(glBeginQuery); + FIND_PROC(glEndQuery); + FIND_PROC(glGetQueryiv); + FIND_PROC(glGetQueryObjectuiv); + FIND_PROC(glUnmapBuffer); + FIND_PROC(glGetBufferPointerv); + FIND_PROC(glDrawBuffers); + FIND_PROC(glUniformMatrix2x3fv); + FIND_PROC(glUniformMatrix3x2fv); + FIND_PROC(glUniformMatrix2x4fv); + FIND_PROC(glUniformMatrix4x2fv); + FIND_PROC(glUniformMatrix3x4fv); + FIND_PROC(glUniformMatrix4x3fv); + FIND_PROC(glBlitFramebuffer); + FIND_PROC(glRenderbufferStorageMultisample); + FIND_PROC(glFramebufferTextureLayer); + FIND_PROC(glMapBufferRange); + FIND_PROC(glFlushMappedBufferRange); + FIND_PROC(glBindVertexArray); + FIND_PROC(glDeleteVertexArrays); + FIND_PROC(glGenVertexArrays); + FIND_PROC(glIsVertexArray); + FIND_PROC(glGetIntegeri_v); + FIND_PROC(glBeginTransformFeedback); + FIND_PROC(glEndTransformFeedback); + FIND_PROC(glBindBufferRange); + FIND_PROC(glBindBufferBase); + FIND_PROC(glTransformFeedbackVaryings); + FIND_PROC(glGetTransformFeedbackVarying); + FIND_PROC(glVertexAttribIPointer); + FIND_PROC(glGetVertexAttribIiv); + FIND_PROC(glGetVertexAttribIuiv); + FIND_PROC(glVertexAttribI4i); + FIND_PROC(glVertexAttribI4ui); + FIND_PROC(glVertexAttribI4iv); + FIND_PROC(glVertexAttribI4uiv); + FIND_PROC(glGetUniformuiv); + FIND_PROC(glGetFragDataLocation); + FIND_PROC(glUniform1ui); + FIND_PROC(glUniform2ui); + FIND_PROC(glUniform3ui); + FIND_PROC(glUniform4ui); + FIND_PROC(glUniform1uiv); + FIND_PROC(glUniform2uiv); + FIND_PROC(glUniform3uiv); + FIND_PROC(glUniform4uiv); + FIND_PROC(glClearBufferiv); + FIND_PROC(glClearBufferuiv); + FIND_PROC(glClearBufferfv); + FIND_PROC(glClearBufferfi); + FIND_PROC(glGetStringi); + FIND_PROC(glCopyBufferSubData); + FIND_PROC(glGetUniformIndices); + FIND_PROC(glGetActiveUniformsiv); + FIND_PROC(glGetUniformBlockIndex); + FIND_PROC(glGetActiveUniformBlockiv); + FIND_PROC(glGetActiveUniformBlockName); + FIND_PROC(glUniformBlockBinding); + FIND_PROC(glDrawArraysInstanced); + FIND_PROC(glDrawElementsInstanced); + FIND_PROC(glFenceSync); + FIND_PROC(glIsSync); + FIND_PROC(glDeleteSync); + FIND_PROC(glClientWaitSync); + FIND_PROC(glWaitSync); + FIND_PROC(glGetInteger64v); + FIND_PROC(glGetSynciv); + FIND_PROC(glGetInteger64i_v); + FIND_PROC(glGetBufferParameteri64v); + FIND_PROC(glGenSamplers); + FIND_PROC(glDeleteSamplers); + FIND_PROC(glIsSampler); + FIND_PROC(glBindSampler); + FIND_PROC(glSamplerParameteri); + FIND_PROC(glSamplerParameteriv); + FIND_PROC(glSamplerParameterf); + FIND_PROC(glSamplerParameterfv); + FIND_PROC(glGetSamplerParameteriv); + FIND_PROC(glGetSamplerParameterfv); + FIND_PROC(glVertexAttribDivisor); + FIND_PROC(glBindTransformFeedback); + FIND_PROC(glDeleteTransformFeedbacks); + FIND_PROC(glGenTransformFeedbacks); + FIND_PROC(glIsTransformFeedback); + FIND_PROC(glPauseTransformFeedback); + FIND_PROC(glResumeTransformFeedback); + FIND_PROC(glGetProgramBinary); + FIND_PROC(glProgramBinary); + FIND_PROC(glProgramParameteri); + FIND_PROC(glInvalidateFramebuffer); + FIND_PROC(glInvalidateSubFramebuffer); + FIND_PROC(glTexStorage2D); + FIND_PROC(glTexStorage3D); + FIND_PROC(glGetInternalformativ); + #undef FIND_PROC + + if (!glReadBuffer || + !glDrawRangeElements || + !glTexImage3D || + !glTexSubImage3D || + !glCopyTexSubImage3D || + !glCompressedTexImage3D || + !glCompressedTexSubImage3D || + !glGenQueries || + !glDeleteQueries || + !glIsQuery || + !glBeginQuery || + !glEndQuery || + !glGetQueryiv || + !glGetQueryObjectuiv || + !glUnmapBuffer || + !glGetBufferPointerv || + !glDrawBuffers || + !glUniformMatrix2x3fv || + !glUniformMatrix3x2fv || + !glUniformMatrix2x4fv || + !glUniformMatrix4x2fv || + !glUniformMatrix3x4fv || + !glUniformMatrix4x3fv || + !glBlitFramebuffer || + !glRenderbufferStorageMultisample || + !glFramebufferTextureLayer || + !glMapBufferRange || + !glFlushMappedBufferRange || + !glBindVertexArray || + !glDeleteVertexArrays || + !glGenVertexArrays || + !glIsVertexArray || + !glGetIntegeri_v || + !glBeginTransformFeedback || + !glEndTransformFeedback || + !glBindBufferRange || + !glBindBufferBase || + !glTransformFeedbackVaryings || + !glGetTransformFeedbackVarying || + !glVertexAttribIPointer || + !glGetVertexAttribIiv || + !glGetVertexAttribIuiv || + !glVertexAttribI4i || + !glVertexAttribI4ui || + !glVertexAttribI4iv || + !glVertexAttribI4uiv || + !glGetUniformuiv || + !glGetFragDataLocation || + !glUniform1ui || + !glUniform2ui || + !glUniform3ui || + !glUniform4ui || + !glUniform1uiv || + !glUniform2uiv || + !glUniform3uiv || + !glUniform4uiv || + !glClearBufferiv || + !glClearBufferuiv || + !glClearBufferfv || + !glClearBufferfi || + !glGetStringi || + !glCopyBufferSubData || + !glGetUniformIndices || + !glGetActiveUniformsiv || + !glGetUniformBlockIndex || + !glGetActiveUniformBlockiv || + !glGetActiveUniformBlockName || + !glUniformBlockBinding || + !glDrawArraysInstanced || + !glDrawElementsInstanced || + !glFenceSync || + !glIsSync || + !glDeleteSync || + !glClientWaitSync || + !glWaitSync || + !glGetInteger64v || + !glGetSynciv || + !glGetInteger64i_v || + !glGetBufferParameteri64v || + !glGenSamplers || + !glDeleteSamplers || + !glIsSampler || + !glBindSampler || + !glSamplerParameteri || + !glSamplerParameteriv || + !glSamplerParameterf || + !glSamplerParameterfv || + !glGetSamplerParameteriv || + !glGetSamplerParameterfv || + !glVertexAttribDivisor || + !glBindTransformFeedback || + !glDeleteTransformFeedbacks || + !glGenTransformFeedbacks || + !glIsTransformFeedback || + !glPauseTransformFeedback || + !glResumeTransformFeedback || + !glGetProgramBinary || + !glProgramBinary || + !glProgramParameteri || + !glInvalidateFramebuffer || + !glInvalidateSubFramebuffer || + !glTexStorage2D || + !glTexStorage3D || + !glGetInternalformativ) + { + return GL_FALSE; + } + + return GL_TRUE; +} + +/* Function pointer definitions */ +GL_APICALL void (* GL_APIENTRY glReadBuffer) (GLenum mode); +GL_APICALL void (* GL_APIENTRY glDrawRangeElements) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices); +GL_APICALL void (* GL_APIENTRY glTexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void (* GL_APIENTRY glTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void (* GL_APIENTRY glCopyTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void (* GL_APIENTRY glCompressedTexImage3D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); +GL_APICALL void (* GL_APIENTRY glCompressedTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); +GL_APICALL void (* GL_APIENTRY glGenQueries) (GLsizei n, GLuint* ids); +GL_APICALL void (* GL_APIENTRY glDeleteQueries) (GLsizei n, const GLuint* ids); +GL_APICALL GLboolean (* GL_APIENTRY glIsQuery) (GLuint id); +GL_APICALL void (* GL_APIENTRY glBeginQuery) (GLenum target, GLuint id); +GL_APICALL void (* GL_APIENTRY glEndQuery) (GLenum target); +GL_APICALL void (* GL_APIENTRY glGetQueryiv) (GLenum target, GLenum pname, GLint* params); +GL_APICALL void (* GL_APIENTRY glGetQueryObjectuiv) (GLuint id, GLenum pname, GLuint* params); +GL_APICALL GLboolean (* GL_APIENTRY glUnmapBuffer) (GLenum target); +GL_APICALL void (* GL_APIENTRY glGetBufferPointerv) (GLenum target, GLenum pname, GLvoid** params); +GL_APICALL void (* GL_APIENTRY glDrawBuffers) (GLsizei n, const GLenum* bufs); +GL_APICALL void (* GL_APIENTRY glUniformMatrix2x3fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void (* GL_APIENTRY glUniformMatrix3x2fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void (* GL_APIENTRY glUniformMatrix2x4fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void (* GL_APIENTRY glUniformMatrix4x2fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void (* GL_APIENTRY glUniformMatrix3x4fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void (* GL_APIENTRY glUniformMatrix4x3fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void (* GL_APIENTRY glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void (* GL_APIENTRY glRenderbufferStorageMultisample) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void (* GL_APIENTRY glFramebufferTextureLayer) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GL_APICALL GLvoid* (* GL_APIENTRY glMapBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GL_APICALL void (* GL_APIENTRY glFlushMappedBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length); +GL_APICALL void (* GL_APIENTRY glBindVertexArray) (GLuint array); +GL_APICALL void (* GL_APIENTRY glDeleteVertexArrays) (GLsizei n, const GLuint* arrays); +GL_APICALL void (* GL_APIENTRY glGenVertexArrays) (GLsizei n, GLuint* arrays); +GL_APICALL GLboolean (* GL_APIENTRY glIsVertexArray) (GLuint array); +GL_APICALL void (* GL_APIENTRY glGetIntegeri_v) (GLenum target, GLuint index, GLint* data); +GL_APICALL void (* GL_APIENTRY glBeginTransformFeedback) (GLenum primitiveMode); +GL_APICALL void (* GL_APIENTRY glEndTransformFeedback) (void); +GL_APICALL void (* GL_APIENTRY glBindBufferRange) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GL_APICALL void (* GL_APIENTRY glBindBufferBase) (GLenum target, GLuint index, GLuint buffer); +GL_APICALL void (* GL_APIENTRY glTransformFeedbackVaryings) (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode); +GL_APICALL void (* GL_APIENTRY glGetTransformFeedbackVarying) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name); +GL_APICALL void (* GL_APIENTRY glVertexAttribIPointer) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); +GL_APICALL void (* GL_APIENTRY glGetVertexAttribIiv) (GLuint index, GLenum pname, GLint* params); +GL_APICALL void (* GL_APIENTRY glGetVertexAttribIuiv) (GLuint index, GLenum pname, GLuint* params); +GL_APICALL void (* GL_APIENTRY glVertexAttribI4i) (GLuint index, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void (* GL_APIENTRY glVertexAttribI4ui) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GL_APICALL void (* GL_APIENTRY glVertexAttribI4iv) (GLuint index, const GLint* v); +GL_APICALL void (* GL_APIENTRY glVertexAttribI4uiv) (GLuint index, const GLuint* v); +GL_APICALL void (* GL_APIENTRY glGetUniformuiv) (GLuint program, GLint location, GLuint* params); +GL_APICALL GLint (* GL_APIENTRY glGetFragDataLocation) (GLuint program, const GLchar *name); +GL_APICALL void (* GL_APIENTRY glUniform1ui) (GLint location, GLuint v0); +GL_APICALL void (* GL_APIENTRY glUniform2ui) (GLint location, GLuint v0, GLuint v1); +GL_APICALL void (* GL_APIENTRY glUniform3ui) (GLint location, GLuint v0, GLuint v1, GLuint v2); +GL_APICALL void (* GL_APIENTRY glUniform4ui) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void (* GL_APIENTRY glUniform1uiv) (GLint location, GLsizei count, const GLuint* value); +GL_APICALL void (* GL_APIENTRY glUniform2uiv) (GLint location, GLsizei count, const GLuint* value); +GL_APICALL void (* GL_APIENTRY glUniform3uiv) (GLint location, GLsizei count, const GLuint* value); +GL_APICALL void (* GL_APIENTRY glUniform4uiv) (GLint location, GLsizei count, const GLuint* value); +GL_APICALL void (* GL_APIENTRY glClearBufferiv) (GLenum buffer, GLint drawbuffer, const GLint* value); +GL_APICALL void (* GL_APIENTRY glClearBufferuiv) (GLenum buffer, GLint drawbuffer, const GLuint* value); +GL_APICALL void (* GL_APIENTRY glClearBufferfv) (GLenum buffer, GLint drawbuffer, const GLfloat* value); +GL_APICALL void (* GL_APIENTRY glClearBufferfi) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +GL_APICALL const GLubyte* (* GL_APIENTRY glGetStringi) (GLenum name, GLuint index); +GL_APICALL void (* GL_APIENTRY glCopyBufferSubData) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GL_APICALL void (* GL_APIENTRY glGetUniformIndices) (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices); +GL_APICALL void (* GL_APIENTRY glGetActiveUniformsiv) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); +GL_APICALL GLuint (* GL_APIENTRY glGetUniformBlockIndex) (GLuint program, const GLchar* uniformBlockName); +GL_APICALL void (* GL_APIENTRY glGetActiveUniformBlockiv) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +GL_APICALL void (* GL_APIENTRY glGetActiveUniformBlockName) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName); +GL_APICALL void (* GL_APIENTRY glUniformBlockBinding) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +GL_APICALL void (* GL_APIENTRY glDrawArraysInstanced) (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); +GL_APICALL void (* GL_APIENTRY glDrawElementsInstanced) (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount); +GL_APICALL GLsync (* GL_APIENTRY glFenceSync) (GLenum condition, GLbitfield flags); +GL_APICALL GLboolean (* GL_APIENTRY glIsSync) (GLsync sync); +GL_APICALL void (* GL_APIENTRY glDeleteSync) (GLsync sync); +GL_APICALL GLenum (* GL_APIENTRY glClientWaitSync) (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void (* GL_APIENTRY glWaitSync) (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void (* GL_APIENTRY glGetInteger64v) (GLenum pname, GLint64* params); +GL_APICALL void (* GL_APIENTRY glGetSynciv) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values); +GL_APICALL void (* GL_APIENTRY glGetInteger64i_v) (GLenum target, GLuint index, GLint64* data); +GL_APICALL void (* GL_APIENTRY glGetBufferParameteri64v) (GLenum target, GLenum pname, GLint64* params); +GL_APICALL void (* GL_APIENTRY glGenSamplers) (GLsizei count, GLuint* samplers); +GL_APICALL void (* GL_APIENTRY glDeleteSamplers) (GLsizei count, const GLuint* samplers); +GL_APICALL GLboolean (* GL_APIENTRY glIsSampler) (GLuint sampler); +GL_APICALL void (* GL_APIENTRY glBindSampler) (GLuint unit, GLuint sampler); +GL_APICALL void (* GL_APIENTRY glSamplerParameteri) (GLuint sampler, GLenum pname, GLint param); +GL_APICALL void (* GL_APIENTRY glSamplerParameteriv) (GLuint sampler, GLenum pname, const GLint* param); +GL_APICALL void (* GL_APIENTRY glSamplerParameterf) (GLuint sampler, GLenum pname, GLfloat param); +GL_APICALL void (* GL_APIENTRY glSamplerParameterfv) (GLuint sampler, GLenum pname, const GLfloat* param); +GL_APICALL void (* GL_APIENTRY glGetSamplerParameteriv) (GLuint sampler, GLenum pname, GLint* params); +GL_APICALL void (* GL_APIENTRY glGetSamplerParameterfv) (GLuint sampler, GLenum pname, GLfloat* params); +GL_APICALL void (* GL_APIENTRY glVertexAttribDivisor) (GLuint index, GLuint divisor); +GL_APICALL void (* GL_APIENTRY glBindTransformFeedback) (GLenum target, GLuint id); +GL_APICALL void (* GL_APIENTRY glDeleteTransformFeedbacks) (GLsizei n, const GLuint* ids); +GL_APICALL void (* GL_APIENTRY glGenTransformFeedbacks) (GLsizei n, GLuint* ids); +GL_APICALL GLboolean (* GL_APIENTRY glIsTransformFeedback) (GLuint id); +GL_APICALL void (* GL_APIENTRY glPauseTransformFeedback) (void); +GL_APICALL void (* GL_APIENTRY glResumeTransformFeedback) (void); +GL_APICALL void (* GL_APIENTRY glGetProgramBinary) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary); +GL_APICALL void (* GL_APIENTRY glProgramBinary) (GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length); +GL_APICALL void (* GL_APIENTRY glProgramParameteri) (GLuint program, GLenum pname, GLint value); +GL_APICALL void (* GL_APIENTRY glInvalidateFramebuffer) (GLenum target, GLsizei numAttachments, const GLenum* attachments); +GL_APICALL void (* GL_APIENTRY glInvalidateSubFramebuffer) (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void (* GL_APIENTRY glTexStorage2D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void (* GL_APIENTRY glTexStorage3D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); diff --git a/gfx_es2/gl3stub.h b/gfx_es2/gl3stub.h new file mode 100644 index 0000000000..7a02bf2725 --- /dev/null +++ b/gfx_es2/gl3stub.h @@ -0,0 +1,491 @@ +#ifndef __gl3_h_ +#define __gl3_h_ + +/* + * stub gl3.h for dynamic loading, based on: + * gl3.h last updated on $Date: 2013-02-12 14:37:24 -0800 (Tue, 12 Feb 2013) $ + * + * Changes: + * - Added #include + * - Removed duplicate OpenGL ES 2.0 declarations + * - Converted OpenGL ES 3.0 function prototypes to function pointer + * declarations + * - Added gl3stubInit() declaration + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2007-2013 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Call this function before calling any OpenGL ES 3.0 functions. It will + * return GL_TRUE if the OpenGL ES 3.0 was successfully initialized, GL_FALSE + * otherwise. */ +GLboolean gl3stubInit(); + +/*------------------------------------------------------------------------- + * Data type definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES 3.0 */ + +typedef unsigned short GLhalf; +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef struct __GLsync *GLsync; + +/*------------------------------------------------------------------------- + * Token definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES core versions */ +#define GL_ES_VERSION_3_0 1 + +/* OpenGL ES 3.0 */ + +#define GL_READ_BUFFER 0x0C02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_RED 0x1903 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_READ_BUFFER_BINDING GL_COPY_READ_BUFFER +#define GL_COPY_WRITE_BUFFER_BINDING GL_COPY_WRITE_BUFFER +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF + +/*------------------------------------------------------------------------- + * Entrypoint definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES 3.0 */ + +extern GL_APICALL void (* GL_APIENTRY glReadBuffer) (GLenum mode); +extern GL_APICALL void (* GL_APIENTRY glDrawRangeElements) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices); +extern GL_APICALL void (* GL_APIENTRY glTexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +extern GL_APICALL void (* GL_APIENTRY glTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +extern GL_APICALL void (* GL_APIENTRY glCopyTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +extern GL_APICALL void (* GL_APIENTRY glCompressedTexImage3D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); +extern GL_APICALL void (* GL_APIENTRY glCompressedTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); +extern GL_APICALL void (* GL_APIENTRY glGenQueries) (GLsizei n, GLuint* ids); +extern GL_APICALL void (* GL_APIENTRY glDeleteQueries) (GLsizei n, const GLuint* ids); +extern GL_APICALL GLboolean (* GL_APIENTRY glIsQuery) (GLuint id); +extern GL_APICALL void (* GL_APIENTRY glBeginQuery) (GLenum target, GLuint id); +extern GL_APICALL void (* GL_APIENTRY glEndQuery) (GLenum target); +extern GL_APICALL void (* GL_APIENTRY glGetQueryiv) (GLenum target, GLenum pname, GLint* params); +extern GL_APICALL void (* GL_APIENTRY glGetQueryObjectuiv) (GLuint id, GLenum pname, GLuint* params); +extern GL_APICALL GLboolean (* GL_APIENTRY glUnmapBuffer) (GLenum target); +extern GL_APICALL void (* GL_APIENTRY glGetBufferPointerv) (GLenum target, GLenum pname, GLvoid** params); +extern GL_APICALL void (* GL_APIENTRY glDrawBuffers) (GLsizei n, const GLenum* bufs); +extern GL_APICALL void (* GL_APIENTRY glUniformMatrix2x3fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (* GL_APIENTRY glUniformMatrix3x2fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (* GL_APIENTRY glUniformMatrix2x4fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (* GL_APIENTRY glUniformMatrix4x2fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (* GL_APIENTRY glUniformMatrix3x4fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (* GL_APIENTRY glUniformMatrix4x3fv) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +extern GL_APICALL void (* GL_APIENTRY glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +extern GL_APICALL void (* GL_APIENTRY glRenderbufferStorageMultisample) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +extern GL_APICALL void (* GL_APIENTRY glFramebufferTextureLayer) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +extern GL_APICALL GLvoid* (* GL_APIENTRY glMapBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +extern GL_APICALL void (* GL_APIENTRY glFlushMappedBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length); +extern GL_APICALL void (* GL_APIENTRY glBindVertexArray) (GLuint array); +extern GL_APICALL void (* GL_APIENTRY glDeleteVertexArrays) (GLsizei n, const GLuint* arrays); +extern GL_APICALL void (* GL_APIENTRY glGenVertexArrays) (GLsizei n, GLuint* arrays); +extern GL_APICALL GLboolean (* GL_APIENTRY glIsVertexArray) (GLuint array); +extern GL_APICALL void (* GL_APIENTRY glGetIntegeri_v) (GLenum target, GLuint index, GLint* data); +extern GL_APICALL void (* GL_APIENTRY glBeginTransformFeedback) (GLenum primitiveMode); +extern GL_APICALL void (* GL_APIENTRY glEndTransformFeedback) (void); +extern GL_APICALL void (* GL_APIENTRY glBindBufferRange) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +extern GL_APICALL void (* GL_APIENTRY glBindBufferBase) (GLenum target, GLuint index, GLuint buffer); +extern GL_APICALL void (* GL_APIENTRY glTransformFeedbackVaryings) (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode); +extern GL_APICALL void (* GL_APIENTRY glGetTransformFeedbackVarying) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name); +extern GL_APICALL void (* GL_APIENTRY glVertexAttribIPointer) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); +extern GL_APICALL void (* GL_APIENTRY glGetVertexAttribIiv) (GLuint index, GLenum pname, GLint* params); +extern GL_APICALL void (* GL_APIENTRY glGetVertexAttribIuiv) (GLuint index, GLenum pname, GLuint* params); +extern GL_APICALL void (* GL_APIENTRY glVertexAttribI4i) (GLuint index, GLint x, GLint y, GLint z, GLint w); +extern GL_APICALL void (* GL_APIENTRY glVertexAttribI4ui) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +extern GL_APICALL void (* GL_APIENTRY glVertexAttribI4iv) (GLuint index, const GLint* v); +extern GL_APICALL void (* GL_APIENTRY glVertexAttribI4uiv) (GLuint index, const GLuint* v); +extern GL_APICALL void (* GL_APIENTRY glGetUniformuiv) (GLuint program, GLint location, GLuint* params); +extern GL_APICALL GLint (* GL_APIENTRY glGetFragDataLocation) (GLuint program, const GLchar *name); +extern GL_APICALL void (* GL_APIENTRY glUniform1ui) (GLint location, GLuint v0); +extern GL_APICALL void (* GL_APIENTRY glUniform2ui) (GLint location, GLuint v0, GLuint v1); +extern GL_APICALL void (* GL_APIENTRY glUniform3ui) (GLint location, GLuint v0, GLuint v1, GLuint v2); +extern GL_APICALL void (* GL_APIENTRY glUniform4ui) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +extern GL_APICALL void (* GL_APIENTRY glUniform1uiv) (GLint location, GLsizei count, const GLuint* value); +extern GL_APICALL void (* GL_APIENTRY glUniform2uiv) (GLint location, GLsizei count, const GLuint* value); +extern GL_APICALL void (* GL_APIENTRY glUniform3uiv) (GLint location, GLsizei count, const GLuint* value); +extern GL_APICALL void (* GL_APIENTRY glUniform4uiv) (GLint location, GLsizei count, const GLuint* value); +extern GL_APICALL void (* GL_APIENTRY glClearBufferiv) (GLenum buffer, GLint drawbuffer, const GLint* value); +extern GL_APICALL void (* GL_APIENTRY glClearBufferuiv) (GLenum buffer, GLint drawbuffer, const GLuint* value); +extern GL_APICALL void (* GL_APIENTRY glClearBufferfv) (GLenum buffer, GLint drawbuffer, const GLfloat* value); +extern GL_APICALL void (* GL_APIENTRY glClearBufferfi) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +extern GL_APICALL const GLubyte* (* GL_APIENTRY glGetStringi) (GLenum name, GLuint index); +extern GL_APICALL void (* GL_APIENTRY glCopyBufferSubData) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +extern GL_APICALL void (* GL_APIENTRY glGetUniformIndices) (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices); +extern GL_APICALL void (* GL_APIENTRY glGetActiveUniformsiv) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); +extern GL_APICALL GLuint (* GL_APIENTRY glGetUniformBlockIndex) (GLuint program, const GLchar* uniformBlockName); +extern GL_APICALL void (* GL_APIENTRY glGetActiveUniformBlockiv) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +extern GL_APICALL void (* GL_APIENTRY glGetActiveUniformBlockName) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName); +extern GL_APICALL void (* GL_APIENTRY glUniformBlockBinding) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +extern GL_APICALL void (* GL_APIENTRY glDrawArraysInstanced) (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); +extern GL_APICALL void (* GL_APIENTRY glDrawElementsInstanced) (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount); +extern GL_APICALL GLsync (* GL_APIENTRY glFenceSync) (GLenum condition, GLbitfield flags); +extern GL_APICALL GLboolean (* GL_APIENTRY glIsSync) (GLsync sync); +extern GL_APICALL void (* GL_APIENTRY glDeleteSync) (GLsync sync); +extern GL_APICALL GLenum (* GL_APIENTRY glClientWaitSync) (GLsync sync, GLbitfield flags, GLuint64 timeout); +extern GL_APICALL void (* GL_APIENTRY glWaitSync) (GLsync sync, GLbitfield flags, GLuint64 timeout); +extern GL_APICALL void (* GL_APIENTRY glGetInteger64v) (GLenum pname, GLint64* params); +extern GL_APICALL void (* GL_APIENTRY glGetSynciv) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values); +extern GL_APICALL void (* GL_APIENTRY glGetInteger64i_v) (GLenum target, GLuint index, GLint64* data); +extern GL_APICALL void (* GL_APIENTRY glGetBufferParameteri64v) (GLenum target, GLenum pname, GLint64* params); +extern GL_APICALL void (* GL_APIENTRY glGenSamplers) (GLsizei count, GLuint* samplers); +extern GL_APICALL void (* GL_APIENTRY glDeleteSamplers) (GLsizei count, const GLuint* samplers); +extern GL_APICALL GLboolean (* GL_APIENTRY glIsSampler) (GLuint sampler); +extern GL_APICALL void (* GL_APIENTRY glBindSampler) (GLuint unit, GLuint sampler); +extern GL_APICALL void (* GL_APIENTRY glSamplerParameteri) (GLuint sampler, GLenum pname, GLint param); +extern GL_APICALL void (* GL_APIENTRY glSamplerParameteriv) (GLuint sampler, GLenum pname, const GLint* param); +extern GL_APICALL void (* GL_APIENTRY glSamplerParameterf) (GLuint sampler, GLenum pname, GLfloat param); +extern GL_APICALL void (* GL_APIENTRY glSamplerParameterfv) (GLuint sampler, GLenum pname, const GLfloat* param); +extern GL_APICALL void (* GL_APIENTRY glGetSamplerParameteriv) (GLuint sampler, GLenum pname, GLint* params); +extern GL_APICALL void (* GL_APIENTRY glGetSamplerParameterfv) (GLuint sampler, GLenum pname, GLfloat* params); +extern GL_APICALL void (* GL_APIENTRY glVertexAttribDivisor) (GLuint index, GLuint divisor); +extern GL_APICALL void (* GL_APIENTRY glBindTransformFeedback) (GLenum target, GLuint id); +extern GL_APICALL void (* GL_APIENTRY glDeleteTransformFeedbacks) (GLsizei n, const GLuint* ids); +extern GL_APICALL void (* GL_APIENTRY glGenTransformFeedbacks) (GLsizei n, GLuint* ids); +extern GL_APICALL GLboolean (* GL_APIENTRY glIsTransformFeedback) (GLuint id); +extern GL_APICALL void (* GL_APIENTRY glPauseTransformFeedback) (void); +extern GL_APICALL void (* GL_APIENTRY glResumeTransformFeedback) (void); +extern GL_APICALL void (* GL_APIENTRY glGetProgramBinary) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary); +extern GL_APICALL void (* GL_APIENTRY glProgramBinary) (GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length); +extern GL_APICALL void (* GL_APIENTRY glProgramParameteri) (GLuint program, GLenum pname, GLint value); +extern GL_APICALL void (* GL_APIENTRY glInvalidateFramebuffer) (GLenum target, GLsizei numAttachments, const GLenum* attachments); +extern GL_APICALL void (* GL_APIENTRY glInvalidateSubFramebuffer) (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height); +extern GL_APICALL void (* GL_APIENTRY glTexStorage2D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +extern GL_APICALL void (* GL_APIENTRY glTexStorage3D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +extern GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index a6e986376a..4b0c30ed35 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -1,5 +1,6 @@ #include "base/logging.h" #include "gl_state.h" + #ifdef _WIN32 #include "GL/wglew.h" #endif @@ -90,13 +91,21 @@ void OpenGLState::Restore() { // http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array void CheckGLExtensions() { + // Make sure to only do this once. It's okay to call CheckGLExtensions from wherever. static bool done = false; if (done) return; done = true; - memset(&gl_extensions, 0, sizeof(gl_extensions)); +#if defined(USING_GLES2) && defined(MAY_HAVE_GLES3) + // Try to load GLES 3.0 + if (GL_TRUE == gl3stubInit()) { + gl_extensions.GLES3 = true; + ILOG("Full OpenGL ES 3.0 support detected!\n"); + } +#endif + const char *extString = (const char *)glGetString(GL_EXTENSIONS); if (extString) { g_all_gl_extensions = extString; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 74050d9cba..6d35b5931d 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -72,11 +72,11 @@ extern PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; // OpenGL state cache. Should convert all code to use this instead of directly calling glEnable etc, // as GL state changes can be expensive on some hardware. -class OpenGLState -{ +class OpenGLState { private: template class BoolState { + private: bool _value; public: BoolState() : _value(init) { @@ -119,7 +119,7 @@ private: public: \ SavedState1_##func() : p1(p1def) { \ OpenGLState::state_count++; \ - }; \ + }; \ void set(p1type newp1) { \ if(newp1 != p1) { \ p1 = newp1; \ @@ -138,7 +138,7 @@ private: public: \ SavedState2_##func() : p1(p1def), p2(p2def) { \ OpenGLState::state_count++; \ - }; \ + }; \ inline void set(p1type newp1, p2type newp2) { \ if(newp1 != p1 || newp2 != p2) { \ p1 = newp1; \ @@ -179,7 +179,7 @@ private: public: \ SavedState3_##func() : p1(p1def), p2(p2def), p3(p3def) { \ OpenGLState::state_count++; \ - }; \ + }; \ inline void set(p1type newp1, p2type newp2, p3type newp3) { \ if(newp1 != p1 || newp2 != p2 || newp3 != p3) { \ p1 = newp1; \ @@ -202,7 +202,7 @@ private: public: \ SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) { \ OpenGLState::state_count++; \ - }; \ + }; \ inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \ if(newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \ p1 = newp1; \ @@ -246,15 +246,15 @@ public: // When adding a state here, don't forget to add it to OpenGLState::Restore() too - // Blend + // Blending BoolState blend; STATE4(glBlendFuncSeparate, GLenum, GLenum, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFuncSeparate; - // On OpenGL ES, using minmax blend requires glBlendEquationEXT (in theory at least). + // On OpenGL ES, using minmax blend requires glBlendEquationEXT (in theory at least but I don't think it's true in practice) STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; STATEFLOAT4(glBlendColor, 1.0f) blendColor; - // Logic Ops + // Logic Ops. Not available on OpenGL ES at all. #if !defined(USING_GLES2) BoolState colorLogicOp; STATE1(glLogicOp, GLenum, GL_COPY) logicOp; @@ -294,7 +294,8 @@ public: STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; #if defined(ANDROID) || defined(BLACKBERRY) - // QCOM Alpha Test + // QCOM Alpha Test. Old school alpha test but ported to GLES2. Does not seem to benefit + // speed very much so probably not worth the trouble. BoolState alphaTestQCOM; STATE2(glAlphaFuncQCOM, GLenum, GLclampf, GL_ALWAYS, 0.0f) alphaFuncQCOM; #endif @@ -308,13 +309,12 @@ public: extern OpenGLState glstate; -// Extensions to look at using: -// GL_NV_draw_texture -// GL_NV_copy_image +// Extensions to look at using: // GL_NV_map_buffer_range (same as GL_ARB_map_buffer_range ?) // WARNING: This gets memset-d - so no strings please struct GLExtensions { + bool GLES3; // true if the full OpenGL ES 3.0 is supported bool OES_depth24; bool OES_packed_depth_stencil; bool OES_depth_texture; @@ -332,18 +332,16 @@ struct GLExtensions { bool ATIClampBug; bool NV_draw_texture; bool NV_copy_image; - + // EGL extensions bool EGL_NV_system_time; bool EGL_NV_coverage_sample; }; - extern std::string g_all_gl_extensions; extern std::string g_all_egl_extensions; - extern GLExtensions gl_extensions; void CheckGLExtensions(); From 2ffdb4ce30030fccabac330b5329e5faf0576fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 8 Oct 2013 13:14:42 +0200 Subject: [PATCH 0714/1445] Must update glew before I can enable MAY_HAVE_GLES3 for desktops --- gfx/gl_common.h | 1 - 1 file changed, 1 deletion(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 1b395331b1..0576ca4fe5 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -21,7 +21,6 @@ #endif #else // OpenGL -#define MAY_HAVE_GLES3 1 #include #if defined(__APPLE__) #include From 0d0177dfc12de1b63d0de990c8c5699d88c05cc3 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Tue, 8 Oct 2013 18:04:56 +0530 Subject: [PATCH 0715/1445] moved Highlight into Choice. corrected code style. --- ui/view.cpp | 18 ++++++++---------- ui/view.h | 15 ++++++++------- ui/viewgroup.cpp | 3 +-- ui/viewgroup.h | 2 +- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index f5c2b54724..77ecd55ed7 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -154,9 +154,6 @@ void Clickable::FocusChanged(int focusFlags) { } } - void Clickable::HighlightChanged(bool highlighted){ - highlighted_ = highlighted; - }; void Clickable::Touch(const TouchInput &input) { if (!enabled_) { @@ -280,9 +277,7 @@ ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParam void ClickableItem::Draw(UIContext &dc) { Style style = dc.theme->itemStyle; - if(highlighted_) { - style = dc.theme->itemHighlightedStyle; - } + if (HasFocus()) { style = dc.theme->itemFocusedStyle; } @@ -305,12 +300,17 @@ void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const h += 16; } + void Choice::HighlightChanged(bool highlighted){ + highlighted_ = highlighted; + }; + + void Choice::Draw(UIContext &dc) { if (!IsSticky()) { ClickableItem::Draw(dc); } else { Style style = dc.theme->itemStyle; - if(highlighted_) { + if (highlighted_) { style = dc.theme->itemHighlightedStyle; } if (down_) { @@ -380,8 +380,6 @@ void CheckBox::Draw(UIContext &dc) { Style style = dc.theme->itemStyle; if (!IsEnabled()) style = dc.theme->itemDisabledStyle; - if(highlighted_) - style = dc.theme->itemHighlightedStyle; dc.SetFontStyle(dc.theme->uiFont); dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); @@ -394,7 +392,7 @@ void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const void Button::Draw(UIContext &dc) { Style style = dc.theme->buttonStyle; - if(highlighted_) style = dc.theme->itemHighlightedStyle; + if (HasFocus()) style = dc.theme->buttonFocusedStyle; if (down_) style = dc.theme->buttonDownStyle; if (!enabled_) style = dc.theme->buttonDisabledStyle; diff --git a/ui/view.h b/ui/view.h index e11ed40501..f636088e50 100644 --- a/ui/view.h +++ b/ui/view.h @@ -391,13 +391,12 @@ public: class Clickable : public View { public: Clickable(LayoutParams *layoutParams) - : View(layoutParams), downCountDown_(0), dragging_(false), down_(false), highlighted_(false) {} + : View(layoutParams), downCountDown_(0), dragging_(false), down_(false){} virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); virtual void FocusChanged(int focusFlags); - virtual void HighlightChanged(bool highlighted); Event OnClick; @@ -410,7 +409,6 @@ protected: int downCountDown_; bool dragging_; bool down_; - bool highlighted_; }; class Button : public Clickable { @@ -508,13 +506,14 @@ public: class Choice : public ClickableItem { public: Choice(const std::string &text, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), selected_(false), centered_(false) {} + : ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), selected_(false), centered_(false), highlighted_(false) {} Choice(const std::string &text, const std::string &smallText, bool selected = false, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), selected_(selected), centered_(false) {} + : ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), selected_(selected), centered_(false), highlighted_(false) {} Choice(ImageID image, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), atlasImage_(image), selected_(false) {} + : ClickableItem(layoutParams), atlasImage_(image), selected_(false), highlighted_(false) {} + virtual void HighlightChanged(bool highlighted); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); virtual void SetCentered(bool c) { @@ -529,6 +528,7 @@ protected: std::string smallText_; ImageID atlasImage_; bool centered_; + bool highlighted_; private: bool selected_; @@ -545,10 +545,11 @@ public: virtual void Key(const KeyInput &key); virtual void Touch(const TouchInput &touch); virtual void FocusChanged(int focusFlags); - + void Press() { down_ = true; dragging_ = false; } void Release() { down_ = false; dragging_ = false; } bool IsDown() { return down_; } + protected: // hackery virtual bool IsSticky() const { return true; } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index c9c7d192c4..e06a2bbf79 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -887,9 +887,8 @@ void ChoiceStrip::SetSelection(int sel) { -void ChoiceStrip::HighlightChoice(int choice){ +void ChoiceStrip::HighlightChoice(unsigned int choice){ if (choice < (int)views_.size()){ - //hack of the worst kind static_cast(views_[choice])->HighlightChanged(true); } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 9ea581f3ff..9239c622df 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -244,7 +244,7 @@ public: int GetSelection() const { return selected_; } void SetSelection(int sel); - void HighlightChoice(int choice); + void HighlightChoice(unsigned int choice); virtual void Key(const KeyInput &input); From 92cd84e54e4ba639b244e521a24c40fb0136e50f Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 9 Oct 2013 02:23:12 +1000 Subject: [PATCH 0716/1445] Include KHR platform for GLES3 defines. Fixes Symbian. --- gfx_es2/gl3stub.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gl3stub.h b/gfx_es2/gl3stub.h index 7a02bf2725..d86d3a0fd1 100644 --- a/gfx_es2/gl3stub.h +++ b/gfx_es2/gl3stub.h @@ -14,6 +14,7 @@ */ #include +#include #ifdef __cplusplus extern "C" { From e409b65e85b6f1b0cc06f8b5db220aca0505ed5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 8 Oct 2013 19:54:56 +0200 Subject: [PATCH 0717/1445] Don't even try to build the gl3stub on desktop platforms --- gfx_es2/gl3stub.c | 4 ++++ gfx_es2/gl3stub.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/gfx_es2/gl3stub.c b/gfx_es2/gl3stub.c index 19b78e7b67..38af6c902c 100644 --- a/gfx_es2/gl3stub.c +++ b/gfx_es2/gl3stub.c @@ -16,6 +16,8 @@ #include "gl3stub.h" +#if defined(USING_GLES2) + GLboolean gl3stubInit() { #define FIND_PROC(s) s = (void*)eglGetProcAddress(#s) FIND_PROC(glReadBuffer); @@ -340,3 +342,5 @@ GL_APICALL void (* GL_APIENTRY glInvalidateSubFramebuffer) (GLenum tar GL_APICALL void (* GL_APIENTRY glTexStorage2D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); GL_APICALL void (* GL_APIENTRY glTexStorage3D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); + +#endif diff --git a/gfx_es2/gl3stub.h b/gfx_es2/gl3stub.h index d86d3a0fd1..a7fe92b353 100644 --- a/gfx_es2/gl3stub.h +++ b/gfx_es2/gl3stub.h @@ -13,6 +13,7 @@ * - Added gl3stubInit() declaration */ +#if defined(USING_GLES2) #include #include @@ -489,4 +490,6 @@ extern GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum t } #endif +#endif // USING_GLES2 + #endif From 5bbab2794a009061a3b5bbf6b69b3ef32d34c152 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 8 Oct 2013 20:08:33 +0200 Subject: [PATCH 0718/1445] Let's not use GLES3 features on Mali for now (see #4078). --- gfx_es2/gl_state.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 4b0c30ed35..2fb4b8d49f 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -98,11 +98,17 @@ void CheckGLExtensions() { done = true; memset(&gl_extensions, 0, sizeof(gl_extensions)); + const char *renderer = (const char *)glGetString(GL_RENDERER); + #if defined(USING_GLES2) && defined(MAY_HAVE_GLES3) // Try to load GLES 3.0 if (GL_TRUE == gl3stubInit()) { gl_extensions.GLES3 = true; ILOG("Full OpenGL ES 3.0 support detected!\n"); + // Though, let's ban Mali from the GLES 3 path for now, see #4078 + if (strstr(renderer, "Mali") != 0) { + gl_extensions.GLES3 = false; + } } #endif @@ -208,7 +214,7 @@ void CheckGLExtensions() { gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; - gl_extensions.ATIClampBug = ((strncmp ((char *)glGetString(GL_RENDERER), "ATI RADEON X", 12) != 0) || (strncmp ((char *)glGetString(GL_RENDERER), "ATI MOBILITY RADEON X",21) != 0)); + gl_extensions.ATIClampBug = ((strncmp (renderer, "ATI RADEON X", 12) != 0) || (strncmp (renderer, "ATI MOBILITY RADEON X",21) != 0)); } #endif } From 81bbc65216b9dd7f53a46027c7c7f932b41bb6cd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 8 Oct 2013 21:15:09 +0200 Subject: [PATCH 0719/1445] Update glew --- ext/glew/GL/glew.h | 3102 +++++++++++++++++++++++++++++++++++++---- ext/glew/GL/glxew.h | 445 +++--- ext/glew/GL/wglew.h | 402 +++--- ext/glew/glew.c | 2798 +++++++++++++++++++++++++++++++++++-- ext/glew/glewinfo.c | 1644 +++++++++++++++++++++- ext/glew/visualinfo.c | 2 + 6 files changed, 7675 insertions(+), 718 deletions(-) diff --git a/ext/glew/GL/glew.h b/ext/glew/GL/glew.h index 68ffbd8b7d..d4151518e3 100644 --- a/ext/glew/GL/glew.h +++ b/ext/glew/GL/glew.h @@ -76,6 +76,8 @@ ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ +#define GLEW_STATIC + #ifndef __glew_h__ #define __glew_h__ #define __GLEW_H__ @@ -83,6 +85,15 @@ #if defined(__gl_h_) || defined(__GL_H__) || defined(__X_GL_H) #error gl.h included before glew.h #endif +#if defined(__gl2_h_) +#error gl2.h included before glew.h +#endif +#if defined(__gltypes_h_) +#error gltypes.h included before glew.h +#endif +#if defined(__REGAL_H__) +#error Regal.h included before glew.h +#endif #if defined(__glext_h_) || defined(__GLEXT_H_) #error glext.h included before glew.h #endif @@ -91,7 +102,10 @@ #endif #define __gl_h_ +#define __gl2_h_ #define __GL_H__ +#define __gltypes_h_ +#define __REGAL_H__ #define __X_GL_H #define __glext_h_ #define __GLEXT_H_ @@ -171,11 +185,14 @@ typedef _W64 int ptrdiff_t; #define GLAPIENTRY APIENTRY #endif +#ifndef GLEWAPIENTRY +#define GLEWAPIENTRY APIENTRY +#endif + /* * GLEW_STATIC is defined for static library. * GLEW_BUILD is defined for building the DLL library. */ -#define GLEW_STATIC #ifdef GLEW_STATIC # define GLEWAPI extern @@ -200,9 +217,10 @@ typedef _W64 int ptrdiff_t; #include -/* SGI MIPSPro doesn't like stdint.h in C++ mode */ +/* SGI MIPSPro doesn't like stdint.h in C++ mode */ +/* ID: 3376260 Solaris 9 has inttypes.h, but not stdint.h */ -#if defined(__sgi) && !defined(__GNUC__) +#if (defined(__sgi) || defined(__sun)) && !defined(__GNUC__) #include #else #include @@ -231,10 +249,15 @@ typedef _W64 int ptrdiff_t; #ifndef GLAPI #define GLAPI extern #endif + #ifndef GLAPIENTRY #define GLAPIENTRY #endif +#ifndef GLEWAPIENTRY +#define GLEWAPIENTRY +#endif + #endif /* _WIN32 */ #ifdef __cplusplus @@ -1211,7 +1234,6 @@ GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei heigh #define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 #define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 #define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 #define GL_ALIASED_POINT_SIZE_RANGE 0x846D #define GL_ALIASED_LINE_WIDTH_RANGE 0x846E @@ -1491,8 +1513,8 @@ typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord); typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord); typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord); typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei drawcount); typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); @@ -2036,8 +2058,6 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei #define GL_CONTEXT_FLAGS 0x821E #define GL_DEPTH_BUFFER 0x8223 #define GL_STENCIL_BUFFER 0x8224 -#define GL_COMPRESSED_RED 0x8225 -#define GL_COMPRESSED_RG 0x8226 #define GL_RGBA32F 0x8814 #define GL_RGB32F 0x8815 #define GL_RGBA16F 0x881A @@ -2057,7 +2077,6 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei #define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 #define GL_TEXTURE_INTENSITY_TYPE 0x8C15 #define GL_TEXTURE_DEPTH_TYPE 0x8C16 -#define GL_UNSIGNED_NORMALIZED 0x8C17 #define GL_TEXTURE_1D_ARRAY 0x8C18 #define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 #define GL_TEXTURE_2D_ARRAY 0x8C1A @@ -2345,12 +2364,6 @@ typedef void (GLAPIENTRY * PFNGLGETINTEGER64I_VPROC) (GLenum, GLuint, GLint64 *) #define GL_VERSION_3_3 1 #define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE -#define GL_ANY_SAMPLES_PASSED 0x8C2F -#define GL_TEXTURE_SWIZZLE_R 0x8E42 -#define GL_TEXTURE_SWIZZLE_G 0x8E43 -#define GL_TEXTURE_SWIZZLE_B 0x8E44 -#define GL_TEXTURE_SWIZZLE_A 0x8E45 -#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 #define GL_RGB10_A2UI 0x906F typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); @@ -2366,13 +2379,8 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint d #ifndef GL_VERSION_4_0 #define GL_VERSION_4_0 1 -#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F #define GL_SAMPLE_SHADING 0x8C36 #define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 -#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A -#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B -#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C -#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D #define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E #define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F #define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F @@ -2409,6 +2417,43 @@ typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGPROC) (GLclampf value); #endif /* GL_VERSION_4_1 */ +/* ----------------------------- GL_VERSION_4_2 ---------------------------- */ + +#ifndef GL_VERSION_4_2 +#define GL_VERSION_4_2 1 + +#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F + +#define GLEW_VERSION_4_2 GLEW_GET_VAR(__GLEW_VERSION_4_2) + +#endif /* GL_VERSION_4_2 */ + +/* ----------------------------- GL_VERSION_4_3 ---------------------------- */ + +#ifndef GL_VERSION_4_3 +#define GL_VERSION_4_3 1 + +#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9 +#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E + +#define GLEW_VERSION_4_3 GLEW_GET_VAR(__GLEW_VERSION_4_3) + +#endif /* GL_VERSION_4_3 */ + +/* ----------------------------- GL_VERSION_4_4 ---------------------------- */ + +#ifndef GL_VERSION_4_4 +#define GL_VERSION_4_4 1 + +#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 + +#define GLEW_VERSION_4_4 GLEW_GET_VAR(__GLEW_VERSION_4_4) + +#endif /* GL_VERSION_4_4 */ + /* -------------------------- GL_3DFX_multisample -------------------------- */ #ifndef GL_3DFX_multisample @@ -2491,10 +2536,10 @@ typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void* userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, GLvoid *userParam); typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const char* buf); -typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, char* message); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar* buf); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, GLchar* message); #define glDebugMessageCallbackAMD GLEW_GET_FUN(__glewDebugMessageCallbackAMD) #define glDebugMessageEnableAMD GLEW_GET_FUN(__glewDebugMessageEnableAMD) @@ -2536,6 +2581,44 @@ typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GL #endif /* GL_AMD_draw_buffers_blend */ +/* ---------------------- GL_AMD_interleaved_elements ---------------------- */ + +#ifndef GL_AMD_interleaved_elements +#define GL_AMD_interleaved_elements 1 + +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RG8UI 0x8238 +#define GL_RG16UI 0x823A +#define GL_RGBA8UI 0x8D7C +#define GL_VERTEX_ELEMENT_SWIZZLE_AMD 0x91A4 +#define GL_VERTEX_ID_SWIZZLE_AMD 0x91A5 + +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPARAMETERIAMDPROC) (GLuint index, GLenum pname, GLint param); + +#define glVertexAttribParameteriAMD GLEW_GET_FUN(__glewVertexAttribParameteriAMD) + +#define GLEW_AMD_interleaved_elements GLEW_GET_VAR(__GLEW_AMD_interleaved_elements) + +#endif /* GL_AMD_interleaved_elements */ + +/* ----------------------- GL_AMD_multi_draw_indirect ---------------------- */ + +#ifndef GL_AMD_multi_draw_indirect +#define GL_AMD_multi_draw_indirect 1 + +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const GLvoid *indirect, GLsizei primcount, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLsizei primcount, GLsizei stride); + +#define glMultiDrawArraysIndirectAMD GLEW_GET_FUN(__glewMultiDrawArraysIndirectAMD) +#define glMultiDrawElementsIndirectAMD GLEW_GET_FUN(__glewMultiDrawElementsIndirectAMD) + +#define GLEW_AMD_multi_draw_indirect GLEW_GET_VAR(__GLEW_AMD_multi_draw_indirect) + +#endif /* GL_AMD_multi_draw_indirect */ + /* ------------------------- GL_AMD_name_gen_delete ------------------------ */ #ifndef GL_AMD_name_gen_delete @@ -2564,8 +2647,6 @@ typedef GLboolean (GLAPIENTRY * PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint n #ifndef GL_AMD_performance_monitor #define GL_AMD_performance_monitor 1 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 #define GL_COUNTER_TYPE_AMD 0x8BC0 #define GL_COUNTER_RANGE_AMD 0x8BC1 #define GL_UNSIGNED_INT64_AMD 0x8BC2 @@ -2579,10 +2660,10 @@ typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* m typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors); typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten); -typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void* data); -typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, char *counterString); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, GLchar *counterString); typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters); -typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, char *groupString); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, GLchar *groupString); typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint* numGroups, GLsizei groupsSize, GLuint *groups); typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint* counterList); @@ -2602,6 +2683,30 @@ typedef void (GLAPIENTRY * PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monito #endif /* GL_AMD_performance_monitor */ +/* -------------------------- GL_AMD_pinned_memory ------------------------- */ + +#ifndef GL_AMD_pinned_memory +#define GL_AMD_pinned_memory 1 + +#define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160 + +#define GLEW_AMD_pinned_memory GLEW_GET_VAR(__GLEW_AMD_pinned_memory) + +#endif /* GL_AMD_pinned_memory */ + +/* ----------------------- GL_AMD_query_buffer_object ---------------------- */ + +#ifndef GL_AMD_query_buffer_object +#define GL_AMD_query_buffer_object 1 + +#define GL_QUERY_BUFFER_AMD 0x9192 +#define GL_QUERY_BUFFER_BINDING_AMD 0x9193 +#define GL_QUERY_RESULT_NO_WAIT_AMD 0x9194 + +#define GLEW_AMD_query_buffer_object GLEW_GET_VAR(__GLEW_AMD_query_buffer_object) + +#endif /* GL_AMD_query_buffer_object */ + /* ------------------------ GL_AMD_sample_positions ------------------------ */ #ifndef GL_AMD_sample_positions @@ -2637,6 +2742,58 @@ typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint i #endif /* GL_AMD_shader_stencil_export */ +/* ---------------------- GL_AMD_shader_trinary_minmax --------------------- */ + +#ifndef GL_AMD_shader_trinary_minmax +#define GL_AMD_shader_trinary_minmax 1 + +#define GLEW_AMD_shader_trinary_minmax GLEW_GET_VAR(__GLEW_AMD_shader_trinary_minmax) + +#endif /* GL_AMD_shader_trinary_minmax */ + +/* ------------------------- GL_AMD_sparse_texture ------------------------- */ + +#ifndef GL_AMD_sparse_texture +#define GL_AMD_sparse_texture 1 + +#define GL_TEXTURE_STORAGE_SPARSE_BIT_AMD 0x00000001 +#define GL_VIRTUAL_PAGE_SIZE_X_AMD 0x9195 +#define GL_VIRTUAL_PAGE_SIZE_Y_AMD 0x9196 +#define GL_VIRTUAL_PAGE_SIZE_Z_AMD 0x9197 +#define GL_MAX_SPARSE_TEXTURE_SIZE_AMD 0x9198 +#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD 0x9199 +#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS 0x919A +#define GL_MIN_SPARSE_LEVEL_AMD 0x919B +#define GL_MIN_LOD_WARNING_AMD 0x919C + +typedef void (GLAPIENTRY * PFNGLTEXSTORAGESPARSEAMDPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags); +typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGESPARSEAMDPROC) (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags); + +#define glTexStorageSparseAMD GLEW_GET_FUN(__glewTexStorageSparseAMD) +#define glTextureStorageSparseAMD GLEW_GET_FUN(__glewTextureStorageSparseAMD) + +#define GLEW_AMD_sparse_texture GLEW_GET_VAR(__GLEW_AMD_sparse_texture) + +#endif /* GL_AMD_sparse_texture */ + +/* ------------------- GL_AMD_stencil_operation_extended ------------------- */ + +#ifndef GL_AMD_stencil_operation_extended +#define GL_AMD_stencil_operation_extended 1 + +#define GL_SET_AMD 0x874A +#define GL_REPLACE_VALUE_AMD 0x874B +#define GL_STENCIL_OP_VALUE_AMD 0x874C +#define GL_STENCIL_BACK_OP_VALUE_AMD 0x874D + +typedef void (GLAPIENTRY * PFNGLSTENCILOPVALUEAMDPROC) (GLenum face, GLuint value); + +#define glStencilOpValueAMD GLEW_GET_FUN(__glewStencilOpValueAMD) + +#define GLEW_AMD_stencil_operation_extended GLEW_GET_VAR(__GLEW_AMD_stencil_operation_extended) + +#endif /* GL_AMD_stencil_operation_extended */ + /* ------------------------ GL_AMD_texture_texture4 ------------------------ */ #ifndef GL_AMD_texture_texture4 @@ -2655,6 +2812,15 @@ typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint i #endif /* GL_AMD_transform_feedback3_lines_triangles */ +/* ----------------------- GL_AMD_vertex_shader_layer ---------------------- */ + +#ifndef GL_AMD_vertex_shader_layer +#define GL_AMD_vertex_shader_layer 1 + +#define GLEW_AMD_vertex_shader_layer GLEW_GET_VAR(__GLEW_AMD_vertex_shader_layer) + +#endif /* GL_AMD_vertex_shader_layer */ + /* -------------------- GL_AMD_vertex_shader_tessellator ------------------- */ #ifndef GL_AMD_vertex_shader_tessellator @@ -2678,6 +2844,209 @@ typedef void (GLAPIENTRY * PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode); #endif /* GL_AMD_vertex_shader_tessellator */ +/* ------------------ GL_AMD_vertex_shader_viewport_index ------------------ */ + +#ifndef GL_AMD_vertex_shader_viewport_index +#define GL_AMD_vertex_shader_viewport_index 1 + +#define GLEW_AMD_vertex_shader_viewport_index GLEW_GET_VAR(__GLEW_AMD_vertex_shader_viewport_index) + +#endif /* GL_AMD_vertex_shader_viewport_index */ + +/* ------------------------- GL_ANGLE_depth_texture ------------------------ */ + +#ifndef GL_ANGLE_depth_texture +#define GL_ANGLE_depth_texture 1 + +#define GLEW_ANGLE_depth_texture GLEW_GET_VAR(__GLEW_ANGLE_depth_texture) + +#endif /* GL_ANGLE_depth_texture */ + +/* ----------------------- GL_ANGLE_framebuffer_blit ----------------------- */ + +#ifndef GL_ANGLE_framebuffer_blit +#define GL_ANGLE_framebuffer_blit 1 + +#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6 +#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA + +typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + +#define glBlitFramebufferANGLE GLEW_GET_FUN(__glewBlitFramebufferANGLE) + +#define GLEW_ANGLE_framebuffer_blit GLEW_GET_VAR(__GLEW_ANGLE_framebuffer_blit) + +#endif /* GL_ANGLE_framebuffer_blit */ + +/* -------------------- GL_ANGLE_framebuffer_multisample ------------------- */ + +#ifndef GL_ANGLE_framebuffer_multisample +#define GL_ANGLE_framebuffer_multisample 1 + +#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56 +#define GL_MAX_SAMPLES_ANGLE 0x8D57 + +typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +#define glRenderbufferStorageMultisampleANGLE GLEW_GET_FUN(__glewRenderbufferStorageMultisampleANGLE) + +#define GLEW_ANGLE_framebuffer_multisample GLEW_GET_VAR(__GLEW_ANGLE_framebuffer_multisample) + +#endif /* GL_ANGLE_framebuffer_multisample */ + +/* ----------------------- GL_ANGLE_instanced_arrays ----------------------- */ + +#ifndef GL_ANGLE_instanced_arrays +#define GL_ANGLE_instanced_arrays 1 + +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); + +#define glDrawArraysInstancedANGLE GLEW_GET_FUN(__glewDrawArraysInstancedANGLE) +#define glDrawElementsInstancedANGLE GLEW_GET_FUN(__glewDrawElementsInstancedANGLE) +#define glVertexAttribDivisorANGLE GLEW_GET_FUN(__glewVertexAttribDivisorANGLE) + +#define GLEW_ANGLE_instanced_arrays GLEW_GET_VAR(__GLEW_ANGLE_instanced_arrays) + +#endif /* GL_ANGLE_instanced_arrays */ + +/* -------------------- GL_ANGLE_pack_reverse_row_order -------------------- */ + +#ifndef GL_ANGLE_pack_reverse_row_order +#define GL_ANGLE_pack_reverse_row_order 1 + +#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4 + +#define GLEW_ANGLE_pack_reverse_row_order GLEW_GET_VAR(__GLEW_ANGLE_pack_reverse_row_order) + +#endif /* GL_ANGLE_pack_reverse_row_order */ + +/* ------------------------ GL_ANGLE_program_binary ------------------------ */ + +#ifndef GL_ANGLE_program_binary +#define GL_ANGLE_program_binary 1 + +#define GL_PROGRAM_BINARY_ANGLE 0x93A6 + +#define GLEW_ANGLE_program_binary GLEW_GET_VAR(__GLEW_ANGLE_program_binary) + +#endif /* GL_ANGLE_program_binary */ + +/* ------------------- GL_ANGLE_texture_compression_dxt1 ------------------- */ + +#ifndef GL_ANGLE_texture_compression_dxt1 +#define GL_ANGLE_texture_compression_dxt1 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_ANGLE 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_ANGLE 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3 + +#define GLEW_ANGLE_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_ANGLE_texture_compression_dxt1) + +#endif /* GL_ANGLE_texture_compression_dxt1 */ + +/* ------------------- GL_ANGLE_texture_compression_dxt3 ------------------- */ + +#ifndef GL_ANGLE_texture_compression_dxt3 +#define GL_ANGLE_texture_compression_dxt3 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_ANGLE 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_ANGLE 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3 + +#define GLEW_ANGLE_texture_compression_dxt3 GLEW_GET_VAR(__GLEW_ANGLE_texture_compression_dxt3) + +#endif /* GL_ANGLE_texture_compression_dxt3 */ + +/* ------------------- GL_ANGLE_texture_compression_dxt5 ------------------- */ + +#ifndef GL_ANGLE_texture_compression_dxt5 +#define GL_ANGLE_texture_compression_dxt5 1 + +#define GL_COMPRESSED_RGB_S3TC_DXT1_ANGLE 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_ANGLE 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3 + +#define GLEW_ANGLE_texture_compression_dxt5 GLEW_GET_VAR(__GLEW_ANGLE_texture_compression_dxt5) + +#endif /* GL_ANGLE_texture_compression_dxt5 */ + +/* ------------------------- GL_ANGLE_texture_usage ------------------------ */ + +#ifndef GL_ANGLE_texture_usage +#define GL_ANGLE_texture_usage 1 + +#define GL_TEXTURE_USAGE_ANGLE 0x93A2 +#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3 + +#define GLEW_ANGLE_texture_usage GLEW_GET_VAR(__GLEW_ANGLE_texture_usage) + +#endif /* GL_ANGLE_texture_usage */ + +/* -------------------------- GL_ANGLE_timer_query ------------------------- */ + +#ifndef GL_ANGLE_timer_query +#define GL_ANGLE_timer_query 1 + +#define GL_QUERY_COUNTER_BITS_ANGLE 0x8864 +#define GL_CURRENT_QUERY_ANGLE 0x8865 +#define GL_QUERY_RESULT_ANGLE 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ANGLE 0x8867 +#define GL_TIME_ELAPSED_ANGLE 0x88BF +#define GL_TIMESTAMP_ANGLE 0x8E28 + +typedef void (GLAPIENTRY * PFNGLBEGINQUERYANGLEPROC) (GLenum target, GLuint id); +typedef void (GLAPIENTRY * PFNGLDELETEQUERIESANGLEPROC) (GLsizei n, const GLuint* ids); +typedef void (GLAPIENTRY * PFNGLENDQUERYANGLEPROC) (GLenum target); +typedef void (GLAPIENTRY * PFNGLGENQUERIESANGLEPROC) (GLsizei n, GLuint* ids); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VANGLEPROC) (GLuint id, GLenum pname, GLint64* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVANGLEPROC) (GLuint id, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VANGLEPROC) (GLuint id, GLenum pname, GLuint64* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVANGLEPROC) (GLuint id, GLenum pname, GLuint* params); +typedef void (GLAPIENTRY * PFNGLGETQUERYIVANGLEPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GLAPIENTRY * PFNGLISQUERYANGLEPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERANGLEPROC) (GLuint id, GLenum target); + +#define glBeginQueryANGLE GLEW_GET_FUN(__glewBeginQueryANGLE) +#define glDeleteQueriesANGLE GLEW_GET_FUN(__glewDeleteQueriesANGLE) +#define glEndQueryANGLE GLEW_GET_FUN(__glewEndQueryANGLE) +#define glGenQueriesANGLE GLEW_GET_FUN(__glewGenQueriesANGLE) +#define glGetQueryObjecti64vANGLE GLEW_GET_FUN(__glewGetQueryObjecti64vANGLE) +#define glGetQueryObjectivANGLE GLEW_GET_FUN(__glewGetQueryObjectivANGLE) +#define glGetQueryObjectui64vANGLE GLEW_GET_FUN(__glewGetQueryObjectui64vANGLE) +#define glGetQueryObjectuivANGLE GLEW_GET_FUN(__glewGetQueryObjectuivANGLE) +#define glGetQueryivANGLE GLEW_GET_FUN(__glewGetQueryivANGLE) +#define glIsQueryANGLE GLEW_GET_FUN(__glewIsQueryANGLE) +#define glQueryCounterANGLE GLEW_GET_FUN(__glewQueryCounterANGLE) + +#define GLEW_ANGLE_timer_query GLEW_GET_VAR(__GLEW_ANGLE_timer_query) + +#endif /* GL_ANGLE_timer_query */ + +/* ------------------- GL_ANGLE_translated_shader_source ------------------- */ + +#ifndef GL_ANGLE_translated_shader_source +#define GL_ANGLE_translated_shader_source 1 + +#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 + +typedef void (GLAPIENTRY * PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source); + +#define glGetTranslatedShaderSourceANGLE GLEW_GET_FUN(__glewGetTranslatedShaderSourceANGLE) + +#define GLEW_ANGLE_translated_shader_source GLEW_GET_VAR(__GLEW_ANGLE_translated_shader_source) + +#endif /* GL_ANGLE_translated_shader_source */ + /* ----------------------- GL_APPLE_aux_depth_stencil ---------------------- */ #ifndef GL_APPLE_aux_depth_stencil @@ -2711,7 +3080,7 @@ typedef void (GLAPIENTRY * PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode); typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); -typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void* pointer); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer); typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount); @@ -2936,9 +3305,9 @@ typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); #define GL_STORAGE_CACHED_APPLE 0x85BE #define GL_STORAGE_SHARED_APPLE 0x85BF -typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); +typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); #define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE) #define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE) @@ -2990,8 +3359,6 @@ typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuin #define GL_APPLE_ycbcr_422 1 #define GL_YCBCR_422_APPLE 0x85B9 -#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA -#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB #define GLEW_APPLE_ycbcr_422 GLEW_GET_VAR(__GLEW_APPLE_ycbcr_422) @@ -3005,6 +3372,7 @@ typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuin #define GL_FIXED 0x140C #define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A #define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_RGB565 0x8D62 #define GL_LOW_FLOAT 0x8DF0 #define GL_MEDIUM_FLOAT 0x8DF1 #define GL_HIGH_FLOAT 0x8DF2 @@ -3018,6 +3386,8 @@ typedef void (GLAPIENTRY * PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuin #define GL_MAX_VARYING_VECTORS 0x8DFC #define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +typedef int GLfixed; + typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf d); typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f); typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint *precision); @@ -3034,6 +3404,101 @@ typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* #endif /* GL_ARB_ES2_compatibility */ +/* ------------------------ GL_ARB_ES3_compatibility ----------------------- */ + +#ifndef GL_ARB_ES3_compatibility +#define GL_ARB_ES3_compatibility 1 + +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 + +#define GLEW_ARB_ES3_compatibility GLEW_GET_VAR(__GLEW_ARB_ES3_compatibility) + +#endif /* GL_ARB_ES3_compatibility */ + +/* ------------------------ GL_ARB_arrays_of_arrays ------------------------ */ + +#ifndef GL_ARB_arrays_of_arrays +#define GL_ARB_arrays_of_arrays 1 + +#define GLEW_ARB_arrays_of_arrays GLEW_GET_VAR(__GLEW_ARB_arrays_of_arrays) + +#endif /* GL_ARB_arrays_of_arrays */ + +/* -------------------------- GL_ARB_base_instance ------------------------- */ + +#ifndef GL_ARB_base_instance +#define GL_ARB_base_instance 1 + +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount, GLuint baseinstance); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLuint baseinstance); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex, GLuint baseinstance); + +#define glDrawArraysInstancedBaseInstance GLEW_GET_FUN(__glewDrawArraysInstancedBaseInstance) +#define glDrawElementsInstancedBaseInstance GLEW_GET_FUN(__glewDrawElementsInstancedBaseInstance) +#define glDrawElementsInstancedBaseVertexBaseInstance GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertexBaseInstance) + +#define GLEW_ARB_base_instance GLEW_GET_VAR(__GLEW_ARB_base_instance) + +#endif /* GL_ARB_base_instance */ + +/* ------------------------ GL_ARB_bindless_texture ------------------------ */ + +#ifndef GL_ARB_bindless_texture +#define GL_ARB_bindless_texture 1 + +#define GL_UNSIGNED_INT64_ARB 0x140F + +typedef GLuint64 (GLAPIENTRY * PFNGLGETIMAGEHANDLEARBPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +typedef GLuint64 (GLAPIENTRY * PFNGLGETTEXTUREHANDLEARBPROC) (GLuint texture); +typedef GLuint64 (GLAPIENTRY * PFNGLGETTEXTURESAMPLERHANDLEARBPROC) (GLuint texture, GLuint sampler); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLUI64VARBPROC) (GLuint index, GLenum pname, GLuint64EXT* params); +typedef GLboolean (GLAPIENTRY * PFNGLISIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle); +typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle); +typedef void (GLAPIENTRY * PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC) (GLuint64 handle); +typedef void (GLAPIENTRY * PFNGLMAKEIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle, GLenum access); +typedef void (GLAPIENTRY * PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC) (GLuint64 handle); +typedef void (GLAPIENTRY * PFNGLMAKETEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC) (GLuint program, GLint location, GLuint64 value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64* values); +typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64ARBPROC) (GLint location, GLuint64 value); +typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64VARBPROC) (GLint location, GLsizei count, const GLuint64* value); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64ARBPROC) (GLuint index, GLuint64EXT x); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1UI64VARBPROC) (GLuint index, const GLuint64EXT* v); + +#define glGetImageHandleARB GLEW_GET_FUN(__glewGetImageHandleARB) +#define glGetTextureHandleARB GLEW_GET_FUN(__glewGetTextureHandleARB) +#define glGetTextureSamplerHandleARB GLEW_GET_FUN(__glewGetTextureSamplerHandleARB) +#define glGetVertexAttribLui64vARB GLEW_GET_FUN(__glewGetVertexAttribLui64vARB) +#define glIsImageHandleResidentARB GLEW_GET_FUN(__glewIsImageHandleResidentARB) +#define glIsTextureHandleResidentARB GLEW_GET_FUN(__glewIsTextureHandleResidentARB) +#define glMakeImageHandleNonResidentARB GLEW_GET_FUN(__glewMakeImageHandleNonResidentARB) +#define glMakeImageHandleResidentARB GLEW_GET_FUN(__glewMakeImageHandleResidentARB) +#define glMakeTextureHandleNonResidentARB GLEW_GET_FUN(__glewMakeTextureHandleNonResidentARB) +#define glMakeTextureHandleResidentARB GLEW_GET_FUN(__glewMakeTextureHandleResidentARB) +#define glProgramUniformHandleui64ARB GLEW_GET_FUN(__glewProgramUniformHandleui64ARB) +#define glProgramUniformHandleui64vARB GLEW_GET_FUN(__glewProgramUniformHandleui64vARB) +#define glUniformHandleui64ARB GLEW_GET_FUN(__glewUniformHandleui64ARB) +#define glUniformHandleui64vARB GLEW_GET_FUN(__glewUniformHandleui64vARB) +#define glVertexAttribL1ui64ARB GLEW_GET_FUN(__glewVertexAttribL1ui64ARB) +#define glVertexAttribL1ui64vARB GLEW_GET_FUN(__glewVertexAttribL1ui64vARB) + +#define GLEW_ARB_bindless_texture GLEW_GET_VAR(__GLEW_ARB_bindless_texture) + +#endif /* GL_ARB_bindless_texture */ + /* ----------------------- GL_ARB_blend_func_extended ---------------------- */ #ifndef GL_ARB_blend_func_extended @@ -3044,8 +3509,8 @@ typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* #define GL_ONE_MINUS_SRC1_ALPHA 0x88FB #define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC -typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const char * name); -typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const char * name); +typedef void (GLAPIENTRY * PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar * name); +typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar * name); #define glBindFragDataLocationIndexed GLEW_GET_FUN(__glewBindFragDataLocationIndexed) #define glGetFragDataIndex GLEW_GET_FUN(__glewGetFragDataIndex) @@ -3054,6 +3519,31 @@ typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const ch #endif /* GL_ARB_blend_func_extended */ +/* ------------------------- GL_ARB_buffer_storage ------------------------- */ + +#ifndef GL_ARB_buffer_storage +#define GL_ARB_buffer_storage 1 + +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_PERSISTENT_BIT 0x00000040 +#define GL_MAP_COHERENT_BIT 0x00000080 +#define GL_DYNAMIC_STORAGE_BIT 0x0100 +#define GL_CLIENT_STORAGE_BIT 0x0200 +#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000 +#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F +#define GL_BUFFER_STORAGE_FLAGS 0x8220 + +typedef void (GLAPIENTRY * PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLbitfield flags); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSTORAGEEXTPROC) (GLuint buffer, GLsizeiptr size, const GLvoid* data, GLbitfield flags); + +#define glBufferStorage GLEW_GET_FUN(__glewBufferStorage) +#define glNamedBufferStorageEXT GLEW_GET_FUN(__glewNamedBufferStorageEXT) + +#define GLEW_ARB_buffer_storage GLEW_GET_VAR(__GLEW_ARB_buffer_storage) + +#endif /* GL_ARB_buffer_storage */ + /* ---------------------------- GL_ARB_cl_event ---------------------------- */ #ifndef GL_ARB_cl_event @@ -3073,6 +3563,42 @@ typedef GLsync (GLAPIENTRY * PFNGLCREATESYNCFROMCLEVENTARBPROC) (cl_context cont #endif /* GL_ARB_cl_event */ +/* ----------------------- GL_ARB_clear_buffer_object ---------------------- */ + +#ifndef GL_ARB_clear_buffer_object +#define GL_ARB_clear_buffer_object 1 + +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data); + +#define glClearBufferData GLEW_GET_FUN(__glewClearBufferData) +#define glClearBufferSubData GLEW_GET_FUN(__glewClearBufferSubData) +#define glClearNamedBufferDataEXT GLEW_GET_FUN(__glewClearNamedBufferDataEXT) +#define glClearNamedBufferSubDataEXT GLEW_GET_FUN(__glewClearNamedBufferSubDataEXT) + +#define GLEW_ARB_clear_buffer_object GLEW_GET_VAR(__GLEW_ARB_clear_buffer_object) + +#endif /* GL_ARB_clear_buffer_object */ + +/* -------------------------- GL_ARB_clear_texture ------------------------- */ + +#ifndef GL_ARB_clear_texture +#define GL_ARB_clear_texture 1 + +#define GL_CLEAR_TEXTURE 0x9365 + +typedef void (GLAPIENTRY * PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* data); + +#define glClearTexImage GLEW_GET_FUN(__glewClearTexImage) +#define glClearTexSubImage GLEW_GET_FUN(__glewClearTexSubImage) + +#define GLEW_ARB_clear_texture GLEW_GET_VAR(__GLEW_ARB_clear_texture) + +#endif /* GL_ARB_clear_texture */ + /* ----------------------- GL_ARB_color_buffer_float ----------------------- */ #ifndef GL_ARB_color_buffer_float @@ -3101,6 +3627,85 @@ typedef void (GLAPIENTRY * PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp) #endif /* GL_ARB_compatibility */ +/* ---------------- GL_ARB_compressed_texture_pixel_storage ---------------- */ + +#ifndef GL_ARB_compressed_texture_pixel_storage +#define GL_ARB_compressed_texture_pixel_storage 1 + +#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127 +#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128 +#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129 +#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A +#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B +#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C +#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D +#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E + +#define GLEW_ARB_compressed_texture_pixel_storage GLEW_GET_VAR(__GLEW_ARB_compressed_texture_pixel_storage) + +#endif /* GL_ARB_compressed_texture_pixel_storage */ + +/* ------------------------- GL_ARB_compute_shader ------------------------- */ + +#ifndef GL_ARB_compute_shader +#define GL_ARB_compute_shader 1 + +#define GL_COMPUTE_SHADER_BIT 0x00000020 +#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 +#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 +#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267 +#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB +#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED +#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE +#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB +#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE +#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF + +typedef void (GLAPIENTRY * PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (GLAPIENTRY * PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect); + +#define glDispatchCompute GLEW_GET_FUN(__glewDispatchCompute) +#define glDispatchComputeIndirect GLEW_GET_FUN(__glewDispatchComputeIndirect) + +#define GLEW_ARB_compute_shader GLEW_GET_VAR(__GLEW_ARB_compute_shader) + +#endif /* GL_ARB_compute_shader */ + +/* ------------------- GL_ARB_compute_variable_group_size ------------------ */ + +#ifndef GL_ARB_compute_variable_group_size +#define GL_ARB_compute_variable_group_size 1 + +#define GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB 0x90EB +#define GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB 0x91BF +#define GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB 0x9344 +#define GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB 0x9345 + +typedef void (GLAPIENTRY * PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z); + +#define glDispatchComputeGroupSizeARB GLEW_GET_FUN(__glewDispatchComputeGroupSizeARB) + +#define GLEW_ARB_compute_variable_group_size GLEW_GET_VAR(__GLEW_ARB_compute_variable_group_size) + +#endif /* GL_ARB_compute_variable_group_size */ + +/* ----------------------- GL_ARB_conservative_depth ----------------------- */ + +#ifndef GL_ARB_conservative_depth +#define GL_ARB_conservative_depth 1 + +#define GLEW_ARB_conservative_depth GLEW_GET_VAR(__GLEW_ARB_conservative_depth) + +#endif /* GL_ARB_conservative_depth */ + /* --------------------------- GL_ARB_copy_buffer -------------------------- */ #ifndef GL_ARB_copy_buffer @@ -3117,6 +3722,19 @@ typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readtarget, GLenu #endif /* GL_ARB_copy_buffer */ +/* --------------------------- GL_ARB_copy_image --------------------------- */ + +#ifndef GL_ARB_copy_image +#define GL_ARB_copy_image 1 + +typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); + +#define glCopyImageSubData GLEW_GET_FUN(__glewCopyImageSubData) + +#define GLEW_ARB_copy_image GLEW_GET_VAR(__GLEW_ARB_copy_image) + +#endif /* GL_ARB_copy_image */ + /* -------------------------- GL_ARB_debug_output -------------------------- */ #ifndef GL_ARB_debug_output @@ -3147,10 +3765,10 @@ typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readtarget, GLenu typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, void* userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const GLvoid *userParam); typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* buf); -typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, char* messageLog); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog); #define glDebugMessageCallbackARB GLEW_GET_FUN(__glewDebugMessageCallbackARB) #define glDebugMessageControlARB GLEW_GET_FUN(__glewDebugMessageControlARB) @@ -3255,10 +3873,10 @@ typedef void (GLAPIENTRY * PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLen #ifndef GL_ARB_draw_elements_base_vertex #define GL_ARB_draw_elements_base_vertex 1 -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, void* indices, GLint basevertex); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei primcount, GLint basevertex); -typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, void* indices, GLint basevertex); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei* count, GLenum type, GLvoid**indices, GLsizei primcount, GLint *basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const *indices, GLsizei primcount, const GLint *basevertex); #define glDrawElementsBaseVertex GLEW_GET_FUN(__glewDrawElementsBaseVertex) #define glDrawElementsInstancedBaseVertex GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertex) @@ -3277,8 +3895,8 @@ typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, G #define GL_DRAW_INDIRECT_BUFFER 0x8F3F #define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 -typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void* indirect); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void* indirect); +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const GLvoid *indirect); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect); #define glDrawArraysIndirect GLEW_GET_FUN(__glewDrawArraysIndirect) #define glDrawElementsIndirect GLEW_GET_FUN(__glewDrawElementsIndirect) @@ -3296,6 +3914,19 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum t #endif /* GL_ARB_draw_instanced */ +/* ------------------------ GL_ARB_enhanced_layouts ------------------------ */ + +#ifndef GL_ARB_enhanced_layouts +#define GL_ARB_enhanced_layouts 1 + +#define GL_LOCATION_COMPONENT 0x934A +#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B +#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C + +#define GLEW_ARB_enhanced_layouts GLEW_GET_VAR(__GLEW_ARB_enhanced_layouts) + +#endif /* GL_ARB_enhanced_layouts */ + /* -------------------- GL_ARB_explicit_attrib_location -------------------- */ #ifndef GL_ARB_explicit_attrib_location @@ -3305,6 +3936,17 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum t #endif /* GL_ARB_explicit_attrib_location */ +/* -------------------- GL_ARB_explicit_uniform_location ------------------- */ + +#ifndef GL_ARB_explicit_uniform_location +#define GL_ARB_explicit_uniform_location 1 + +#define GL_MAX_UNIFORM_LOCATIONS 0x826E + +#define GLEW_ARB_explicit_uniform_location GLEW_GET_VAR(__GLEW_ARB_explicit_uniform_location) + +#endif /* GL_ARB_explicit_uniform_location */ + /* ------------------- GL_ARB_fragment_coord_conventions ------------------- */ #ifndef GL_ARB_fragment_coord_conventions @@ -3314,6 +3956,15 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum t #endif /* GL_ARB_fragment_coord_conventions */ +/* --------------------- GL_ARB_fragment_layer_viewport -------------------- */ + +#ifndef GL_ARB_fragment_layer_viewport +#define GL_ARB_fragment_layer_viewport 1 + +#define GLEW_ARB_fragment_layer_viewport GLEW_GET_VAR(__GLEW_ARB_fragment_layer_viewport) + +#endif /* GL_ARB_fragment_layer_viewport */ + /* ------------------------ GL_ARB_fragment_program ------------------------ */ #ifndef GL_ARB_fragment_program @@ -3361,6 +4012,35 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum t #endif /* GL_ARB_fragment_shader */ +/* ------------------- GL_ARB_framebuffer_no_attachments ------------------- */ + +#ifndef GL_ARB_framebuffer_no_attachments +#define GL_ARB_framebuffer_no_attachments 1 + +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 +#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 +#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 +#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317 +#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 + +typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint* params); +typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) (GLuint framebuffer, GLenum pname, GLint param); + +#define glFramebufferParameteri GLEW_GET_FUN(__glewFramebufferParameteri) +#define glGetFramebufferParameteriv GLEW_GET_FUN(__glewGetFramebufferParameteriv) +#define glGetNamedFramebufferParameterivEXT GLEW_GET_FUN(__glewGetNamedFramebufferParameterivEXT) +#define glNamedFramebufferParameteriEXT GLEW_GET_FUN(__glewNamedFramebufferParameteriEXT) + +#define GLEW_ARB_framebuffer_no_attachments GLEW_GET_VAR(__GLEW_ARB_framebuffer_no_attachments) + +#endif /* GL_ARB_framebuffer_no_attachments */ + /* ----------------------- GL_ARB_framebuffer_object ----------------------- */ #ifndef GL_ARB_framebuffer_object @@ -3548,7 +4228,7 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenu #define GL_PROGRAM_BINARY_FORMATS 0x87FF typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary); -typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void* binary, GLsizei length); +typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length); typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); #define glGetProgramBinary GLEW_GET_FUN(__glewGetProgramBinary) @@ -3594,23 +4274,6 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum p #define GL_DOUBLE_VEC4 0x8FFE typedef void (GLAPIENTRY * PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); -typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); typedef void (GLAPIENTRY * PFNGLUNIFORM1DPROC) (GLint location, GLdouble x); typedef void (GLAPIENTRY * PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble* value); typedef void (GLAPIENTRY * PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y); @@ -3630,23 +4293,6 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble* value); #define glGetUniformdv GLEW_GET_FUN(__glewGetUniformdv) -#define glProgramUniform1dEXT GLEW_GET_FUN(__glewProgramUniform1dEXT) -#define glProgramUniform1dvEXT GLEW_GET_FUN(__glewProgramUniform1dvEXT) -#define glProgramUniform2dEXT GLEW_GET_FUN(__glewProgramUniform2dEXT) -#define glProgramUniform2dvEXT GLEW_GET_FUN(__glewProgramUniform2dvEXT) -#define glProgramUniform3dEXT GLEW_GET_FUN(__glewProgramUniform3dEXT) -#define glProgramUniform3dvEXT GLEW_GET_FUN(__glewProgramUniform3dvEXT) -#define glProgramUniform4dEXT GLEW_GET_FUN(__glewProgramUniform4dEXT) -#define glProgramUniform4dvEXT GLEW_GET_FUN(__glewProgramUniform4dvEXT) -#define glProgramUniformMatrix2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2dvEXT) -#define glProgramUniformMatrix2x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x3dvEXT) -#define glProgramUniformMatrix2x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix2x4dvEXT) -#define glProgramUniformMatrix3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3dvEXT) -#define glProgramUniformMatrix3x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x2dvEXT) -#define glProgramUniformMatrix3x4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix3x4dvEXT) -#define glProgramUniformMatrix4dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4dvEXT) -#define glProgramUniformMatrix4x2dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x2dvEXT) -#define glProgramUniformMatrix4x3dvEXT GLEW_GET_FUN(__glewProgramUniformMatrix4x3dvEXT) #define glUniform1d GLEW_GET_FUN(__glewUniform1d) #define glUniform1dv GLEW_GET_FUN(__glewUniform1dv) #define glUniform2d GLEW_GET_FUN(__glewUniform2d) @@ -3844,6 +4490,24 @@ typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum in #endif /* GL_ARB_imaging */ +/* ----------------------- GL_ARB_indirect_parameters ---------------------- */ + +#ifndef GL_ARB_indirect_parameters +#define GL_ARB_indirect_parameters 1 + +#define GL_PARAMETER_BUFFER_ARB 0x80EE +#define GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF + +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, const GLvoid *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); + +#define glMultiDrawArraysIndirectCountARB GLEW_GET_FUN(__glewMultiDrawArraysIndirectCountARB) +#define glMultiDrawElementsIndirectCountARB GLEW_GET_FUN(__glewMultiDrawElementsIndirectCountARB) + +#define GLEW_ARB_indirect_parameters GLEW_GET_VAR(__GLEW_ARB_indirect_parameters) + +#endif /* GL_ARB_indirect_parameters */ + /* ------------------------ GL_ARB_instanced_arrays ------------------------ */ #ifndef GL_ARB_instanced_arrays @@ -3863,6 +4527,168 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuin #endif /* GL_ARB_instanced_arrays */ +/* ---------------------- GL_ARB_internalformat_query ---------------------- */ + +#ifndef GL_ARB_internalformat_query +#define GL_ARB_internalformat_query 1 + +#define GL_NUM_SAMPLE_COUNTS 0x9380 + +typedef void (GLAPIENTRY * PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); + +#define glGetInternalformativ GLEW_GET_FUN(__glewGetInternalformativ) + +#define GLEW_ARB_internalformat_query GLEW_GET_VAR(__GLEW_ARB_internalformat_query) + +#endif /* GL_ARB_internalformat_query */ + +/* ---------------------- GL_ARB_internalformat_query2 --------------------- */ + +#ifndef GL_ARB_internalformat_query2 +#define GL_ARB_internalformat_query2 1 + +#define GL_INTERNALFORMAT_SUPPORTED 0x826F +#define GL_INTERNALFORMAT_PREFERRED 0x8270 +#define GL_INTERNALFORMAT_RED_SIZE 0x8271 +#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272 +#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273 +#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274 +#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275 +#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276 +#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277 +#define GL_INTERNALFORMAT_RED_TYPE 0x8278 +#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279 +#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A +#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B +#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C +#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D +#define GL_MAX_WIDTH 0x827E +#define GL_MAX_HEIGHT 0x827F +#define GL_MAX_DEPTH 0x8280 +#define GL_MAX_LAYERS 0x8281 +#define GL_MAX_COMBINED_DIMENSIONS 0x8282 +#define GL_COLOR_COMPONENTS 0x8283 +#define GL_DEPTH_COMPONENTS 0x8284 +#define GL_STENCIL_COMPONENTS 0x8285 +#define GL_COLOR_RENDERABLE 0x8286 +#define GL_DEPTH_RENDERABLE 0x8287 +#define GL_STENCIL_RENDERABLE 0x8288 +#define GL_FRAMEBUFFER_RENDERABLE 0x8289 +#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A +#define GL_FRAMEBUFFER_BLEND 0x828B +#define GL_READ_PIXELS 0x828C +#define GL_READ_PIXELS_FORMAT 0x828D +#define GL_READ_PIXELS_TYPE 0x828E +#define GL_TEXTURE_IMAGE_FORMAT 0x828F +#define GL_TEXTURE_IMAGE_TYPE 0x8290 +#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291 +#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292 +#define GL_MIPMAP 0x8293 +#define GL_MANUAL_GENERATE_MIPMAP 0x8294 +#define GL_AUTO_GENERATE_MIPMAP 0x8295 +#define GL_COLOR_ENCODING 0x8296 +#define GL_SRGB_READ 0x8297 +#define GL_SRGB_WRITE 0x8298 +#define GL_SRGB_DECODE_ARB 0x8299 +#define GL_FILTER 0x829A +#define GL_VERTEX_TEXTURE 0x829B +#define GL_TESS_CONTROL_TEXTURE 0x829C +#define GL_TESS_EVALUATION_TEXTURE 0x829D +#define GL_GEOMETRY_TEXTURE 0x829E +#define GL_FRAGMENT_TEXTURE 0x829F +#define GL_COMPUTE_TEXTURE 0x82A0 +#define GL_TEXTURE_SHADOW 0x82A1 +#define GL_TEXTURE_GATHER 0x82A2 +#define GL_TEXTURE_GATHER_SHADOW 0x82A3 +#define GL_SHADER_IMAGE_LOAD 0x82A4 +#define GL_SHADER_IMAGE_STORE 0x82A5 +#define GL_SHADER_IMAGE_ATOMIC 0x82A6 +#define GL_IMAGE_TEXEL_SIZE 0x82A7 +#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8 +#define GL_IMAGE_PIXEL_FORMAT 0x82A9 +#define GL_IMAGE_PIXEL_TYPE 0x82AA +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF +#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1 +#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2 +#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3 +#define GL_CLEAR_BUFFER 0x82B4 +#define GL_TEXTURE_VIEW 0x82B5 +#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6 +#define GL_FULL_SUPPORT 0x82B7 +#define GL_CAVEAT_SUPPORT 0x82B8 +#define GL_IMAGE_CLASS_4_X_32 0x82B9 +#define GL_IMAGE_CLASS_2_X_32 0x82BA +#define GL_IMAGE_CLASS_1_X_32 0x82BB +#define GL_IMAGE_CLASS_4_X_16 0x82BC +#define GL_IMAGE_CLASS_2_X_16 0x82BD +#define GL_IMAGE_CLASS_1_X_16 0x82BE +#define GL_IMAGE_CLASS_4_X_8 0x82BF +#define GL_IMAGE_CLASS_2_X_8 0x82C0 +#define GL_IMAGE_CLASS_1_X_8 0x82C1 +#define GL_IMAGE_CLASS_11_11_10 0x82C2 +#define GL_IMAGE_CLASS_10_10_10_2 0x82C3 +#define GL_VIEW_CLASS_128_BITS 0x82C4 +#define GL_VIEW_CLASS_96_BITS 0x82C5 +#define GL_VIEW_CLASS_64_BITS 0x82C6 +#define GL_VIEW_CLASS_48_BITS 0x82C7 +#define GL_VIEW_CLASS_32_BITS 0x82C8 +#define GL_VIEW_CLASS_24_BITS 0x82C9 +#define GL_VIEW_CLASS_16_BITS 0x82CA +#define GL_VIEW_CLASS_8_BITS 0x82CB +#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC +#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD +#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE +#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF +#define GL_VIEW_CLASS_RGTC1_RED 0x82D0 +#define GL_VIEW_CLASS_RGTC2_RG 0x82D1 +#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2 +#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3 + +typedef void (GLAPIENTRY * PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64* params); + +#define glGetInternalformati64v GLEW_GET_FUN(__glewGetInternalformati64v) + +#define GLEW_ARB_internalformat_query2 GLEW_GET_VAR(__GLEW_ARB_internalformat_query2) + +#endif /* GL_ARB_internalformat_query2 */ + +/* ----------------------- GL_ARB_invalidate_subdata ----------------------- */ + +#ifndef GL_ARB_invalidate_subdata +#define GL_ARB_invalidate_subdata 1 + +typedef void (GLAPIENTRY * PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer); +typedef void (GLAPIENTRY * PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (GLAPIENTRY * PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum* attachments); +typedef void (GLAPIENTRY * PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level); +typedef void (GLAPIENTRY * PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); + +#define glInvalidateBufferData GLEW_GET_FUN(__glewInvalidateBufferData) +#define glInvalidateBufferSubData GLEW_GET_FUN(__glewInvalidateBufferSubData) +#define glInvalidateFramebuffer GLEW_GET_FUN(__glewInvalidateFramebuffer) +#define glInvalidateSubFramebuffer GLEW_GET_FUN(__glewInvalidateSubFramebuffer) +#define glInvalidateTexImage GLEW_GET_FUN(__glewInvalidateTexImage) +#define glInvalidateTexSubImage GLEW_GET_FUN(__glewInvalidateTexSubImage) + +#define GLEW_ARB_invalidate_subdata GLEW_GET_VAR(__GLEW_ARB_invalidate_subdata) + +#endif /* GL_ARB_invalidate_subdata */ + +/* ---------------------- GL_ARB_map_buffer_alignment ---------------------- */ + +#ifndef GL_ARB_map_buffer_alignment +#define GL_ARB_map_buffer_alignment 1 + +#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC + +#define GLEW_ARB_map_buffer_alignment GLEW_GET_VAR(__GLEW_ARB_map_buffer_alignment) + +#endif /* GL_ARB_map_buffer_alignment */ + /* ------------------------ GL_ARB_map_buffer_range ------------------------ */ #ifndef GL_ARB_map_buffer_range @@ -3917,6 +4743,44 @@ typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *in #endif /* GL_ARB_matrix_palette */ +/* --------------------------- GL_ARB_multi_bind --------------------------- */ + +#ifndef GL_ARB_multi_bind +#define GL_ARB_multi_bind 1 + +typedef void (GLAPIENTRY * PFNGLBINDBUFFERSBASEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint* buffers); +typedef void (GLAPIENTRY * PFNGLBINDBUFFERSRANGEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint* buffers, const GLintptr *offsets, const GLsizeiptr *sizes); +typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint* textures); +typedef void (GLAPIENTRY * PFNGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint* samplers); +typedef void (GLAPIENTRY * PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint* textures); +typedef void (GLAPIENTRY * PFNGLBINDVERTEXBUFFERSPROC) (GLuint first, GLsizei count, const GLuint* buffers, const GLintptr *offsets, const GLsizei *strides); + +#define glBindBuffersBase GLEW_GET_FUN(__glewBindBuffersBase) +#define glBindBuffersRange GLEW_GET_FUN(__glewBindBuffersRange) +#define glBindImageTextures GLEW_GET_FUN(__glewBindImageTextures) +#define glBindSamplers GLEW_GET_FUN(__glewBindSamplers) +#define glBindTextures GLEW_GET_FUN(__glewBindTextures) +#define glBindVertexBuffers GLEW_GET_FUN(__glewBindVertexBuffers) + +#define GLEW_ARB_multi_bind GLEW_GET_VAR(__GLEW_ARB_multi_bind) + +#endif /* GL_ARB_multi_bind */ + +/* ----------------------- GL_ARB_multi_draw_indirect ---------------------- */ + +#ifndef GL_ARB_multi_draw_indirect +#define GL_ARB_multi_draw_indirect 1 + +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const GLvoid *indirect, GLsizei primcount, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLsizei primcount, GLsizei stride); + +#define glMultiDrawArraysIndirect GLEW_GET_FUN(__glewMultiDrawArraysIndirect) +#define glMultiDrawElementsIndirect GLEW_GET_FUN(__glewMultiDrawElementsIndirect) + +#define GLEW_ARB_multi_draw_indirect GLEW_GET_VAR(__GLEW_ARB_multi_draw_indirect) + +#endif /* GL_ARB_multi_draw_indirect */ + /* --------------------------- GL_ARB_multisample -------------------------- */ #ifndef GL_ARB_multisample @@ -4145,6 +5009,77 @@ typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GL #endif /* GL_ARB_point_sprite */ +/* --------------------- GL_ARB_program_interface_query -------------------- */ + +#ifndef GL_ARB_program_interface_query +#define GL_ARB_program_interface_query 1 + +#define GL_UNIFORM 0x92E1 +#define GL_UNIFORM_BLOCK 0x92E2 +#define GL_PROGRAM_INPUT 0x92E3 +#define GL_PROGRAM_OUTPUT 0x92E4 +#define GL_BUFFER_VARIABLE 0x92E5 +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#define GL_IS_PER_PATCH 0x92E7 +#define GL_VERTEX_SUBROUTINE 0x92E8 +#define GL_TESS_CONTROL_SUBROUTINE 0x92E9 +#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA +#define GL_GEOMETRY_SUBROUTINE 0x92EB +#define GL_FRAGMENT_SUBROUTINE 0x92EC +#define GL_COMPUTE_SUBROUTINE 0x92ED +#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE +#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF +#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0 +#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1 +#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2 +#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3 +#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 +#define GL_ACTIVE_RESOURCES 0x92F5 +#define GL_MAX_NAME_LENGTH 0x92F6 +#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 +#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8 +#define GL_NAME_LENGTH 0x92F9 +#define GL_TYPE 0x92FA +#define GL_ARRAY_SIZE 0x92FB +#define GL_OFFSET 0x92FC +#define GL_BLOCK_INDEX 0x92FD +#define GL_ARRAY_STRIDE 0x92FE +#define GL_MATRIX_STRIDE 0x92FF +#define GL_IS_ROW_MAJOR 0x9300 +#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 +#define GL_BUFFER_BINDING 0x9302 +#define GL_BUFFER_DATA_SIZE 0x9303 +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#define GL_ACTIVE_VARIABLES 0x9305 +#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308 +#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309 +#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A +#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B +#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C +#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D +#define GL_LOCATION 0x930E +#define GL_LOCATION_INDEX 0x930F + +typedef void (GLAPIENTRY * PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint* params); +typedef GLuint (GLAPIENTRY * PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar* name); +typedef GLint (GLAPIENTRY * PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar* name); +typedef GLint (GLAPIENTRY * PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, GLchar *name); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum* props, GLsizei bufSize, GLsizei *length, GLint *params); + +#define glGetProgramInterfaceiv GLEW_GET_FUN(__glewGetProgramInterfaceiv) +#define glGetProgramResourceIndex GLEW_GET_FUN(__glewGetProgramResourceIndex) +#define glGetProgramResourceLocation GLEW_GET_FUN(__glewGetProgramResourceLocation) +#define glGetProgramResourceLocationIndex GLEW_GET_FUN(__glewGetProgramResourceLocationIndex) +#define glGetProgramResourceName GLEW_GET_FUN(__glewGetProgramResourceName) +#define glGetProgramResourceiv GLEW_GET_FUN(__glewGetProgramResourceiv) + +#define GLEW_ARB_program_interface_query GLEW_GET_VAR(__GLEW_ARB_program_interface_query) + +#endif /* GL_ARB_program_interface_query */ + /* ------------------------ GL_ARB_provoking_vertex ------------------------ */ #ifndef GL_ARB_provoking_vertex @@ -4163,6 +5098,29 @@ typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXPROC) (GLenum mode); #endif /* GL_ARB_provoking_vertex */ +/* ----------------------- GL_ARB_query_buffer_object ---------------------- */ + +#ifndef GL_ARB_query_buffer_object +#define GL_ARB_query_buffer_object 1 + +#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000 +#define GL_QUERY_BUFFER 0x9192 +#define GL_QUERY_BUFFER_BINDING 0x9193 +#define GL_QUERY_RESULT_NO_WAIT 0x9194 + +#define GLEW_ARB_query_buffer_object GLEW_GET_VAR(__GLEW_ARB_query_buffer_object) + +#endif /* GL_ARB_query_buffer_object */ + +/* ------------------ GL_ARB_robust_buffer_access_behavior ----------------- */ + +#ifndef GL_ARB_robust_buffer_access_behavior +#define GL_ARB_robust_buffer_access_behavior 1 + +#define GLEW_ARB_robust_buffer_access_behavior GLEW_GET_VAR(__GLEW_ARB_robust_buffer_access_behavior) + +#endif /* GL_ARB_robust_buffer_access_behavior */ + /* --------------------------- GL_ARB_robustness --------------------------- */ #ifndef GL_ARB_robustness @@ -4176,6 +5134,7 @@ typedef void (GLAPIENTRY * PFNGLPROVOKINGVERTEXPROC) (GLenum mode); #define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 #define GL_NO_RESET_NOTIFICATION_ARB 0x8261 +typedef GLenum (GLAPIENTRY * PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void); typedef void (GLAPIENTRY * PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* table); typedef void (GLAPIENTRY * PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void* img); typedef void (GLAPIENTRY * PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void* image); @@ -4196,6 +5155,7 @@ typedef void (GLAPIENTRY * PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint loc typedef void (GLAPIENTRY * PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint* params); typedef void (GLAPIENTRY * PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void* data); +#define glGetGraphicsResetStatusARB GLEW_GET_FUN(__glewGetGraphicsResetStatusARB) #define glGetnColorTableARB GLEW_GET_FUN(__glewGetnColorTableARB) #define glGetnCompressedTexImageARB GLEW_GET_FUN(__glewGetnCompressedTexImageARB) #define glGetnConvolutionFilterARB GLEW_GET_FUN(__glewGetnConvolutionFilterARB) @@ -4220,6 +5180,24 @@ typedef void (GLAPIENTRY * PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei w #endif /* GL_ARB_robustness */ +/* ---------------- GL_ARB_robustness_application_isolation ---------------- */ + +#ifndef GL_ARB_robustness_application_isolation +#define GL_ARB_robustness_application_isolation 1 + +#define GLEW_ARB_robustness_application_isolation GLEW_GET_VAR(__GLEW_ARB_robustness_application_isolation) + +#endif /* GL_ARB_robustness_application_isolation */ + +/* ---------------- GL_ARB_robustness_share_group_isolation ---------------- */ + +#ifndef GL_ARB_robustness_share_group_isolation +#define GL_ARB_robustness_share_group_isolation 1 + +#define GLEW_ARB_robustness_share_group_isolation GLEW_GET_VAR(__GLEW_ARB_robustness_share_group_isolation) + +#endif /* GL_ARB_robustness_share_group_isolation */ + /* ------------------------- GL_ARB_sample_shading ------------------------- */ #ifndef GL_ARB_sample_shading @@ -4288,6 +5266,17 @@ typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum #endif /* GL_ARB_seamless_cube_map */ +/* ------------------ GL_ARB_seamless_cubemap_per_texture ------------------ */ + +#ifndef GL_ARB_seamless_cubemap_per_texture +#define GL_ARB_seamless_cubemap_per_texture 1 + +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F + +#define GLEW_ARB_seamless_cubemap_per_texture GLEW_GET_VAR(__GLEW_ARB_seamless_cubemap_per_texture) + +#endif /* GL_ARB_seamless_cubemap_per_texture */ + /* --------------------- GL_ARB_separate_shader_objects -------------------- */ #ifndef GL_ARB_separate_shader_objects @@ -4305,10 +5294,10 @@ typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum typedef void (GLAPIENTRY * PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); typedef void (GLAPIENTRY * PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); -typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const char ** strings); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar ** strings); typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines); typedef void (GLAPIENTRY * PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, char *infoLog); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar *infoLog); typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint* params); typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline); typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble x); @@ -4429,6 +5418,49 @@ typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); #endif /* GL_ARB_separate_shader_objects */ +/* --------------------- GL_ARB_shader_atomic_counters --------------------- */ + +#ifndef GL_ARB_shader_atomic_counters +#define GL_ARB_shader_atomic_counters 1 + +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 +#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2 +#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 +#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4 +#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5 +#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB +#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF +#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 +#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 +#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3 +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 +#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 +#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 +#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB +#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC + +typedef void (GLAPIENTRY * PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint* params); + +#define glGetActiveAtomicCounterBufferiv GLEW_GET_FUN(__glewGetActiveAtomicCounterBufferiv) + +#define GLEW_ARB_shader_atomic_counters GLEW_GET_VAR(__GLEW_ARB_shader_atomic_counters) + +#endif /* GL_ARB_shader_atomic_counters */ + /* ----------------------- GL_ARB_shader_bit_encoding ---------------------- */ #ifndef GL_ARB_shader_bit_encoding @@ -4438,6 +5470,113 @@ typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); #endif /* GL_ARB_shader_bit_encoding */ +/* --------------------- GL_ARB_shader_draw_parameters --------------------- */ + +#ifndef GL_ARB_shader_draw_parameters +#define GL_ARB_shader_draw_parameters 1 + +#define GLEW_ARB_shader_draw_parameters GLEW_GET_VAR(__GLEW_ARB_shader_draw_parameters) + +#endif /* GL_ARB_shader_draw_parameters */ + +/* ------------------------ GL_ARB_shader_group_vote ----------------------- */ + +#ifndef GL_ARB_shader_group_vote +#define GL_ARB_shader_group_vote 1 + +#define GLEW_ARB_shader_group_vote GLEW_GET_VAR(__GLEW_ARB_shader_group_vote) + +#endif /* GL_ARB_shader_group_vote */ + +/* --------------------- GL_ARB_shader_image_load_store -------------------- */ + +#ifndef GL_ARB_shader_image_load_store +#define GL_ARB_shader_image_load_store 1 + +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39 +#define GL_IMAGE_BINDING_NAME 0x8F3A +#define GL_IMAGE_BINDING_LEVEL 0x8F3B +#define GL_IMAGE_BINDING_LAYERED 0x8F3C +#define GL_IMAGE_BINDING_LAYER 0x8F3D +#define GL_IMAGE_BINDING_ACCESS 0x8F3E +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C +#define GL_MAX_IMAGE_SAMPLES 0x906D +#define GL_IMAGE_BINDING_FORMAT 0x906E +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 +#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD +#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE +#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +typedef void (GLAPIENTRY * PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); + +#define glBindImageTexture GLEW_GET_FUN(__glewBindImageTexture) +#define glMemoryBarrier GLEW_GET_FUN(__glewMemoryBarrier) + +#define GLEW_ARB_shader_image_load_store GLEW_GET_VAR(__GLEW_ARB_shader_image_load_store) + +#endif /* GL_ARB_shader_image_load_store */ + +/* ------------------------ GL_ARB_shader_image_size ----------------------- */ + +#ifndef GL_ARB_shader_image_size +#define GL_ARB_shader_image_size 1 + +#define GLEW_ARB_shader_image_size GLEW_GET_VAR(__GLEW_ARB_shader_image_size) + +#endif /* GL_ARB_shader_image_size */ + /* ------------------------- GL_ARB_shader_objects ------------------------- */ #ifndef GL_ARB_shader_objects @@ -4583,6 +5722,36 @@ typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj) #endif /* GL_ARB_shader_stencil_export */ +/* ------------------ GL_ARB_shader_storage_buffer_object ------------------ */ + +#ifndef GL_ARB_shader_storage_buffer_object +#define GL_ARB_shader_storage_buffer_object 1 + +#define GL_SHADER_STORAGE_BARRIER_BIT 0x2000 +#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 +#define GL_SHADER_STORAGE_BUFFER 0x90D2 +#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 +#define GL_SHADER_STORAGE_BUFFER_START 0x90D4 +#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5 +#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6 +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7 +#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8 +#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9 +#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA +#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB +#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC +#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD +#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE +#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF + +typedef void (GLAPIENTRY * PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); + +#define glShaderStorageBlockBinding GLEW_GET_FUN(__glewShaderStorageBlockBinding) + +#define GLEW_ARB_shader_storage_buffer_object GLEW_GET_VAR(__GLEW_ARB_shader_storage_buffer_object) + +#endif /* GL_ARB_shader_storage_buffer_object */ + /* ------------------------ GL_ARB_shader_subroutine ----------------------- */ #ifndef GL_ARB_shader_subroutine @@ -4598,12 +5767,12 @@ typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj) #define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A #define GL_COMPATIBLE_SUBROUTINES 0x8E4B -typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name); -typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, char *name); +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, GLchar *name); +typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei* length, GLchar *name); typedef void (GLAPIENTRY * PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint* values); typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint* values); -typedef GLuint (GLAPIENTRY * PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const char* name); -typedef GLint (GLAPIENTRY * PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const char* name); +typedef GLuint (GLAPIENTRY * PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar* name); +typedef GLint (GLAPIENTRY * PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar* name); typedef void (GLAPIENTRY * PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint* params); typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint* indices); @@ -4640,6 +5809,15 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, G #endif /* GL_ARB_shading_language_100 */ +/* -------------------- GL_ARB_shading_language_420pack -------------------- */ + +#ifndef GL_ARB_shading_language_420pack +#define GL_ARB_shading_language_420pack 1 + +#define GLEW_ARB_shading_language_420pack GLEW_GET_VAR(__GLEW_ARB_shading_language_420pack) + +#endif /* GL_ARB_shading_language_420pack */ + /* -------------------- GL_ARB_shading_language_include -------------------- */ #ifndef GL_ARB_shading_language_include @@ -4649,12 +5827,12 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, G #define GL_NAMED_STRING_LENGTH_ARB 0x8DE9 #define GL_NAMED_STRING_TYPE_ARB 0x8DEA -typedef void (GLAPIENTRY * PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const char ** path, const GLint *length); -typedef void (GLAPIENTRY * PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const char* name); -typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const char* name, GLsizei bufSize, GLint *stringlen, char *string); -typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const char* name, GLenum pname, GLint *params); -typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const char* name); -typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const char* name, GLint stringlen, const char *string); +typedef void (GLAPIENTRY * PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar* const *path, const GLint *length); +typedef void (GLAPIENTRY * PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar* name, GLsizei bufSize, GLint *stringlen, GLchar *string); +typedef void (GLAPIENTRY * PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar* name, GLenum pname, GLint *params); +typedef GLboolean (GLAPIENTRY * PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar* name); +typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar* name, GLint stringlen, const GLchar *string); #define glCompileShaderIncludeARB GLEW_GET_FUN(__glewCompileShaderIncludeARB) #define glDeleteNamedStringARB GLEW_GET_FUN(__glewDeleteNamedStringARB) @@ -4667,6 +5845,15 @@ typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, #endif /* GL_ARB_shading_language_include */ +/* -------------------- GL_ARB_shading_language_packing -------------------- */ + +#ifndef GL_ARB_shading_language_packing +#define GL_ARB_shading_language_packing 1 + +#define GLEW_ARB_shading_language_packing GLEW_GET_VAR(__GLEW_ARB_shading_language_packing) + +#endif /* GL_ARB_shading_language_packing */ + /* ----------------------------- GL_ARB_shadow ----------------------------- */ #ifndef GL_ARB_shadow @@ -4691,6 +5878,44 @@ typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, #endif /* GL_ARB_shadow_ambient */ +/* ------------------------- GL_ARB_sparse_texture ------------------------- */ + +#ifndef GL_ARB_sparse_texture +#define GL_ARB_sparse_texture 1 + +#define GL_VIRTUAL_PAGE_SIZE_X_ARB 0x9195 +#define GL_VIRTUAL_PAGE_SIZE_Y_ARB 0x9196 +#define GL_VIRTUAL_PAGE_SIZE_Z_ARB 0x9197 +#define GL_MAX_SPARSE_TEXTURE_SIZE_ARB 0x9198 +#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199 +#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A +#define GL_TEXTURE_SPARSE_ARB 0x91A6 +#define GL_VIRTUAL_PAGE_SIZE_INDEX_ARB 0x91A7 +#define GL_NUM_VIRTUAL_PAGE_SIZES_ARB 0x91A8 +#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9 +#define GL_NUM_SPARSE_LEVELS_ARB 0x91AA + +typedef void (GLAPIENTRY * PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); +typedef void (GLAPIENTRY * PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); + +#define glTexPageCommitmentARB GLEW_GET_FUN(__glewTexPageCommitmentARB) +#define glTexturePageCommitmentEXT GLEW_GET_FUN(__glewTexturePageCommitmentEXT) + +#define GLEW_ARB_sparse_texture GLEW_GET_VAR(__GLEW_ARB_sparse_texture) + +#endif /* GL_ARB_sparse_texture */ + +/* ------------------------ GL_ARB_stencil_texturing ----------------------- */ + +#ifndef GL_ARB_stencil_texturing +#define GL_ARB_stencil_texturing 1 + +#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA + +#define GLEW_ARB_stencil_texturing GLEW_GET_VAR(__GLEW_ARB_stencil_texturing) + +#endif /* GL_ARB_stencil_texturing */ + /* ------------------------------ GL_ARB_sync ------------------------------ */ #ifndef GL_ARB_sync @@ -4819,6 +6044,25 @@ typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum interna #endif /* GL_ARB_texture_buffer_object_rgb32 */ +/* ---------------------- GL_ARB_texture_buffer_range ---------------------- */ + +#ifndef GL_ARB_texture_buffer_range +#define GL_ARB_texture_buffer_range 1 + +#define GL_TEXTURE_BUFFER_OFFSET 0x919D +#define GL_TEXTURE_BUFFER_SIZE 0x919E +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F + +typedef void (GLAPIENTRY * PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFERRANGEEXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); + +#define glTexBufferRange GLEW_GET_FUN(__glewTexBufferRange) +#define glTextureBufferRangeEXT GLEW_GET_FUN(__glewTextureBufferRangeEXT) + +#define GLEW_ARB_texture_buffer_range GLEW_GET_VAR(__GLEW_ARB_texture_buffer_range) + +#endif /* GL_ARB_texture_buffer_range */ + /* ----------------------- GL_ARB_texture_compression ---------------------- */ #ifndef GL_ARB_texture_compression @@ -4836,13 +6080,13 @@ typedef void (GLAPIENTRY * PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum interna #define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 #define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void* img); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLvoid *img); #define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB) #define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB) @@ -5028,6 +6272,17 @@ typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GL #endif /* GL_ARB_texture_gather */ +/* ------------------ GL_ARB_texture_mirror_clamp_to_edge ------------------ */ + +#ifndef GL_ARB_texture_mirror_clamp_to_edge +#define GL_ARB_texture_mirror_clamp_to_edge 1 + +#define GL_MIRROR_CLAMP_TO_EDGE 0x8743 + +#define GLEW_ARB_texture_mirror_clamp_to_edge GLEW_GET_VAR(__GLEW_ARB_texture_mirror_clamp_to_edge) + +#endif /* GL_ARB_texture_mirror_clamp_to_edge */ + /* --------------------- GL_ARB_texture_mirrored_repeat -------------------- */ #ifndef GL_ARB_texture_mirrored_repeat @@ -5089,6 +6344,15 @@ typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsiz #endif /* GL_ARB_texture_non_power_of_two */ +/* ---------------------- GL_ARB_texture_query_levels ---------------------- */ + +#ifndef GL_ARB_texture_query_levels +#define GL_ARB_texture_query_levels 1 + +#define GLEW_ARB_texture_query_levels GLEW_GET_VAR(__GLEW_ARB_texture_query_levels) + +#endif /* GL_ARB_texture_query_levels */ + /* ------------------------ GL_ARB_texture_query_lod ----------------------- */ #ifndef GL_ARB_texture_query_lod @@ -5119,7 +6383,6 @@ typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsiz #ifndef GL_ARB_texture_rg #define GL_ARB_texture_rg 1 -#define GL_RED 0x1903 #define GL_COMPRESSED_RED 0x8225 #define GL_COMPRESSED_RG 0x8226 #define GL_RG 0x8227 @@ -5160,6 +6423,62 @@ typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsiz #endif /* GL_ARB_texture_rgb10_a2ui */ +/* ------------------------ GL_ARB_texture_stencil8 ------------------------ */ + +#ifndef GL_ARB_texture_stencil8 +#define GL_ARB_texture_stencil8 1 + +#define GL_STENCIL_INDEX 0x1901 +#define GL_STENCIL_INDEX8 0x8D48 + +#define GLEW_ARB_texture_stencil8 GLEW_GET_VAR(__GLEW_ARB_texture_stencil8) + +#endif /* GL_ARB_texture_stencil8 */ + +/* ------------------------- GL_ARB_texture_storage ------------------------ */ + +#ifndef GL_ARB_texture_storage +#define GL_ARB_texture_storage 1 + +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F + +typedef void (GLAPIENTRY * PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GLAPIENTRY * PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + +#define glTexStorage1D GLEW_GET_FUN(__glewTexStorage1D) +#define glTexStorage2D GLEW_GET_FUN(__glewTexStorage2D) +#define glTexStorage3D GLEW_GET_FUN(__glewTexStorage3D) +#define glTextureStorage1DEXT GLEW_GET_FUN(__glewTextureStorage1DEXT) +#define glTextureStorage2DEXT GLEW_GET_FUN(__glewTextureStorage2DEXT) +#define glTextureStorage3DEXT GLEW_GET_FUN(__glewTextureStorage3DEXT) + +#define GLEW_ARB_texture_storage GLEW_GET_VAR(__GLEW_ARB_texture_storage) + +#endif /* GL_ARB_texture_storage */ + +/* ------------------- GL_ARB_texture_storage_multisample ------------------ */ + +#ifndef GL_ARB_texture_storage_multisample +#define GL_ARB_texture_storage_multisample 1 + +typedef void (GLAPIENTRY * PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAPIENTRY * PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAPIENTRY * PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); + +#define glTexStorage2DMultisample GLEW_GET_FUN(__glewTexStorage2DMultisample) +#define glTexStorage3DMultisample GLEW_GET_FUN(__glewTexStorage3DMultisample) +#define glTextureStorage2DMultisampleEXT GLEW_GET_FUN(__glewTextureStorage2DMultisampleEXT) +#define glTextureStorage3DMultisampleEXT GLEW_GET_FUN(__glewTextureStorage3DMultisampleEXT) + +#define GLEW_ARB_texture_storage_multisample GLEW_GET_VAR(__GLEW_ARB_texture_storage_multisample) + +#endif /* GL_ARB_texture_storage_multisample */ + /* ------------------------- GL_ARB_texture_swizzle ------------------------ */ #ifndef GL_ARB_texture_swizzle @@ -5175,6 +6494,25 @@ typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsiz #endif /* GL_ARB_texture_swizzle */ +/* -------------------------- GL_ARB_texture_view -------------------------- */ + +#ifndef GL_ARB_texture_view +#define GL_ARB_texture_view 1 + +#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB +#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC +#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD +#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF + +typedef void (GLAPIENTRY * PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); + +#define glTextureView GLEW_GET_FUN(__glewTextureView) + +#define GLEW_ARB_texture_view GLEW_GET_VAR(__GLEW_ARB_texture_view) + +#endif /* GL_ARB_texture_view */ + /* --------------------------- GL_ARB_timer_query -------------------------- */ #ifndef GL_ARB_timer_query @@ -5247,6 +6585,21 @@ typedef void (GLAPIENTRY * PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint in #endif /* GL_ARB_transform_feedback3 */ +/* ------------------ GL_ARB_transform_feedback_instanced ------------------ */ + +#ifndef GL_ARB_transform_feedback_instanced +#define GL_ARB_transform_feedback_instanced 1 + +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei primcount); + +#define glDrawTransformFeedbackInstanced GLEW_GET_FUN(__glewDrawTransformFeedbackInstanced) +#define glDrawTransformFeedbackStreamInstanced GLEW_GET_FUN(__glewDrawTransformFeedbackStreamInstanced) + +#define GLEW_ARB_transform_feedback_instanced GLEW_GET_VAR(__GLEW_ARB_transform_feedback_instanced) + +#endif /* GL_ARB_transform_feedback_instanced */ + /* ------------------------ GL_ARB_transpose_matrix ------------------------ */ #ifndef GL_ARB_transpose_matrix @@ -5312,13 +6665,13 @@ typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXFARBPROC) (GLfloat m[16]); typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, char* uniformBlockName); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName); typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, char* uniformName); +typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformName); typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint* data); -typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const char* uniformBlockName); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const char** uniformNames, GLuint* uniformIndices); +typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar* uniformBlockName); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar** uniformNames, GLuint* uniformIndices); typedef void (GLAPIENTRY * PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); #define glBindBufferBase GLEW_GET_FUN(__glewBindBufferBase) @@ -5373,13 +6726,6 @@ typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYPROC) (GLuint array); #ifndef GL_ARB_vertex_attrib_64bit #define GL_ARB_vertex_attrib_64bit 1 -#define GL_DOUBLE_MAT2 0x8F46 -#define GL_DOUBLE_MAT3 0x8F47 -#define GL_DOUBLE_MAT4 0x8F48 -#define GL_DOUBLE_VEC2 0x8FFC -#define GL_DOUBLE_VEC3 0x8FFD -#define GL_DOUBLE_VEC4 0x8FFE - typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble* params); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble* v); @@ -5406,6 +6752,37 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint s #endif /* GL_ARB_vertex_attrib_64bit */ +/* ---------------------- GL_ARB_vertex_attrib_binding --------------------- */ + +#ifndef GL_ARB_vertex_attrib_binding +#define GL_ARB_vertex_attrib_binding 1 + +#define GL_VERTEX_ATTRIB_BINDING 0x82D4 +#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 +#define GL_VERTEX_BINDING_DIVISOR 0x82D6 +#define GL_VERTEX_BINDING_OFFSET 0x82D7 +#define GL_VERTEX_BINDING_STRIDE 0x82D8 +#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 +#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA + +typedef void (GLAPIENTRY * PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAPIENTRY * PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor); + +#define glBindVertexBuffer GLEW_GET_FUN(__glewBindVertexBuffer) +#define glVertexAttribBinding GLEW_GET_FUN(__glewVertexAttribBinding) +#define glVertexAttribFormat GLEW_GET_FUN(__glewVertexAttribFormat) +#define glVertexAttribIFormat GLEW_GET_FUN(__glewVertexAttribIFormat) +#define glVertexAttribLFormat GLEW_GET_FUN(__glewVertexAttribLFormat) +#define glVertexBindingDivisor GLEW_GET_FUN(__glewVertexBindingDivisor) + +#define GLEW_ARB_vertex_attrib_binding GLEW_GET_VAR(__GLEW_ARB_vertex_attrib_binding) + +#endif /* GL_ARB_vertex_attrib_binding */ + /* -------------------------- GL_ARB_vertex_blend -------------------------- */ #ifndef GL_ARB_vertex_blend @@ -5521,13 +6898,13 @@ typedef ptrdiff_t GLintptrARB; typedef ptrdiff_t GLsizeiptrARB; typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid* data, GLenum usage); -typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers); typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers); typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params); -typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid* data); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer); typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target); @@ -5642,7 +7019,7 @@ typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void* string); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string); typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params); @@ -5657,7 +7034,7 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); @@ -5694,7 +7071,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLs typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); #define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB) #define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB) @@ -5788,6 +7165,17 @@ typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programO #endif /* GL_ARB_vertex_shader */ +/* ------------------- GL_ARB_vertex_type_10f_11f_11f_rev ------------------ */ + +#ifndef GL_ARB_vertex_type_10f_11f_11f_rev +#define GL_ARB_vertex_type_10f_11f_11f_rev 1 + +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B + +#define GLEW_ARB_vertex_type_10f_11f_11f_rev GLEW_GET_VAR(__GLEW_ARB_vertex_type_10f_11f_11f_rev) + +#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */ + /* ------------------- GL_ARB_vertex_type_2_10_10_10_rev ------------------- */ #ifndef GL_ARB_vertex_type_2_10_10_10_rev @@ -6061,7 +7449,7 @@ typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bu typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); -typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void* pointer); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer); #define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI) #define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI) @@ -6198,7 +7586,7 @@ typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, c #ifndef GL_ATI_map_object_buffer #define GL_ATI_map_object_buffer 1 -typedef void* (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); +typedef GLvoid * (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); #define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI) @@ -6367,8 +7755,8 @@ typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params); typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); -typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void* pointer, GLenum usage); -typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void* pointer, GLenum preserve); +typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage); +typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve); typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); #define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI) @@ -6423,41 +7811,49 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, G typedef void (GLAPIENTRY * PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte x, GLbyte y, GLbyte z); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords); typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); -typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); typedef void (GLAPIENTRY * PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords); typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); -typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *v); +typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords); #define glClientActiveVertexStreamATI GLEW_GET_FUN(__glewClientActiveVertexStreamATI) #define glNormalStream3bATI GLEW_GET_FUN(__glewNormalStream3bATI) @@ -6472,6 +7868,14 @@ typedef void (GLAPIENTRY * PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GL #define glNormalStream3svATI GLEW_GET_FUN(__glewNormalStream3svATI) #define glVertexBlendEnvfATI GLEW_GET_FUN(__glewVertexBlendEnvfATI) #define glVertexBlendEnviATI GLEW_GET_FUN(__glewVertexBlendEnviATI) +#define glVertexStream1dATI GLEW_GET_FUN(__glewVertexStream1dATI) +#define glVertexStream1dvATI GLEW_GET_FUN(__glewVertexStream1dvATI) +#define glVertexStream1fATI GLEW_GET_FUN(__glewVertexStream1fATI) +#define glVertexStream1fvATI GLEW_GET_FUN(__glewVertexStream1fvATI) +#define glVertexStream1iATI GLEW_GET_FUN(__glewVertexStream1iATI) +#define glVertexStream1ivATI GLEW_GET_FUN(__glewVertexStream1ivATI) +#define glVertexStream1sATI GLEW_GET_FUN(__glewVertexStream1sATI) +#define glVertexStream1svATI GLEW_GET_FUN(__glewVertexStream1svATI) #define glVertexStream2dATI GLEW_GET_FUN(__glewVertexStream2dATI) #define glVertexStream2dvATI GLEW_GET_FUN(__glewVertexStream2dvATI) #define glVertexStream2fATI GLEW_GET_FUN(__glewVertexStream2fATI) @@ -6696,7 +8100,7 @@ typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); #ifndef GL_EXT_color_subtable #define GL_EXT_color_subtable 1 -typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void* data); +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); #define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT) @@ -6750,19 +8154,19 @@ typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); #define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 #define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* image); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void* row, void* column, void* span); -typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* row, const void* column); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); #define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT) #define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT) @@ -6802,8 +8206,8 @@ typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum #define GL_MAP1_BINORMAL_EXT 0x8446 #define GL_MAP2_BINORMAL_EXT 0x8447 -typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); -typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void* pointer); +typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, GLvoid *pointer); #define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT) #define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT) @@ -6852,6 +8256,23 @@ typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat* #endif /* GL_EXT_cull_vertex */ +/* -------------------------- GL_EXT_debug_marker -------------------------- */ + +#ifndef GL_EXT_debug_marker +#define GL_EXT_debug_marker 1 + +typedef void (GLAPIENTRY * PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar* marker); +typedef void (GLAPIENTRY * PFNGLPOPGROUPMARKEREXTPROC) (void); +typedef void (GLAPIENTRY * PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar* marker); + +#define glInsertEventMarkerEXT GLEW_GET_FUN(__glewInsertEventMarkerEXT) +#define glPopGroupMarkerEXT GLEW_GET_FUN(__glewPopGroupMarkerEXT) +#define glPushGroupMarkerEXT GLEW_GET_FUN(__glewPushGroupMarkerEXT) + +#define GLEW_EXT_debug_marker GLEW_GET_VAR(__GLEW_EXT_debug_marker) + +#endif /* GL_EXT_debug_marker */ + /* ------------------------ GL_EXT_depth_bounds_test ----------------------- */ #ifndef GL_EXT_depth_bounds_test @@ -6880,18 +8301,18 @@ typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zma typedef void (GLAPIENTRY * PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); typedef void (GLAPIENTRY * PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); @@ -6916,8 +8337,8 @@ typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuff typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); typedef void (GLAPIENTRY * PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, void* img); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, void* img); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLvoid *img); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLvoid *img); typedef void (GLAPIENTRY * PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat* params); @@ -6928,7 +8349,7 @@ typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); @@ -6937,18 +8358,18 @@ typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void** params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void* data); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid *data); typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void* string); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, GLvoid *string); typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid** params); typedef void (GLAPIENTRY * PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, GLvoid** params); -typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void* pixels); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); @@ -6981,7 +8402,7 @@ typedef void (GLAPIENTRY * PFNGLMATRIXSCALEFEXTPROC) (GLenum matrixMode, GLfloat typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); typedef void (GLAPIENTRY * PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (GLAPIENTRY * PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); typedef void (GLAPIENTRY * PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); @@ -6992,9 +8413,9 @@ typedef void (GLAPIENTRY * PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coo typedef void (GLAPIENTRY * PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); typedef void (GLAPIENTRY * PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint* params); typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); @@ -7002,11 +8423,11 @@ typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLe typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* param); typedef void (GLAPIENTRY * PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void* data, GLenum usage); -typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const GLvoid *data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data); typedef void (GLAPIENTRY * PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); @@ -7026,7 +8447,7 @@ typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint* params); typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint* params); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const GLvoid *string); typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); @@ -7065,9 +8486,9 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint progra typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* params); typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint* params); typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); @@ -7075,9 +8496,9 @@ typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLen typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* param); typedef void (GLAPIENTRY * PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); @@ -7490,6 +8911,18 @@ typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum t #endif /* GL_EXT_framebuffer_multisample */ +/* --------------- GL_EXT_framebuffer_multisample_blit_scaled -------------- */ + +#ifndef GL_EXT_framebuffer_multisample_blit_scaled +#define GL_EXT_framebuffer_multisample_blit_scaled 1 + +#define GL_SCALED_RESOLVE_FASTEST_EXT 0x90BA +#define GL_SCALED_RESOLVE_NICEST_EXT 0x90BB + +#define GLEW_EXT_framebuffer_multisample_blit_scaled GLEW_GET_VAR(__GLEW_EXT_framebuffer_multisample_blit_scaled) + +#endif /* GL_EXT_framebuffer_multisample_blit_scaled */ + /* ----------------------- GL_EXT_framebuffer_object ----------------------- */ #ifndef GL_EXT_framebuffer_object @@ -7777,10 +9210,10 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLin #define GL_MINMAX_FORMAT_EXT 0x802F #define GL_MINMAX_SINK_EXT 0x8030 -typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void* values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); @@ -7861,7 +9294,6 @@ typedef void (GLAPIENTRY * PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode) #define GL_TEXTURE_LIGHT_EXT 0x8350 #define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 #define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 -#define GL_FRAGMENT_DEPTH_EXT 0x8452 typedef void (GLAPIENTRY * PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); typedef void (GLAPIENTRY * PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); @@ -7890,7 +9322,7 @@ typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mod #define GL_EXT_multi_draw_arrays 1 typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid **indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid * const *indices, GLsizei primcount); #define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT) #define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT) @@ -7983,8 +9415,6 @@ typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); #define GL_TEXTURE_2D 0x0DE1 #define GL_PROXY_TEXTURE_1D 0x8063 #define GL_PROXY_TEXTURE_2D 0x8064 -#define GL_TEXTURE_3D_EXT 0x806F -#define GL_PROXY_TEXTURE_3D_EXT 0x8070 #define GL_COLOR_TABLE_FORMAT_EXT 0x80D8 #define GL_COLOR_TABLE_WIDTH_EXT 0x80D9 #define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA @@ -8003,8 +9433,8 @@ typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); #define GL_TEXTURE_CUBE_MAP_ARB 0x8513 #define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B -typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void* data); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void* data); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data); typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); @@ -8215,7 +9645,7 @@ typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenu #define GL_ACTIVE_PROGRAM_EXT 0x8B8D typedef void (GLAPIENTRY * PFNGLACTIVEPROGRAMEXTPROC) (GLuint program); -typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const char* string); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const GLchar* string); typedef void (GLAPIENTRY * PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program); #define glActiveProgramEXT GLEW_GET_FUN(__glewActiveProgramEXT) @@ -8375,9 +9805,9 @@ typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); #ifndef GL_EXT_subtexture #define GL_EXT_subtexture 1 -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); #define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT) #define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT) @@ -8454,7 +9884,7 @@ typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint leve #define GL_TEXTURE_WRAP_R_EXT 0x8072 #define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 -typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); #define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT) @@ -8508,9 +9938,6 @@ typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum interna #ifndef GL_EXT_texture_compression_dxt1 #define GL_EXT_texture_compression_dxt1 1 -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 - #define GLEW_EXT_texture_compression_dxt1 GLEW_GET_VAR(__GLEW_EXT_texture_compression_dxt1) #endif /* GL_EXT_texture_compression_dxt1 */ @@ -8595,18 +10022,6 @@ typedef void (GLAPIENTRY * PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum interna #ifndef GL_EXT_texture_env #define GL_EXT_texture_env 1 -#define GL_TEXTURE_ENV0_EXT 0 -#define GL_ENV_BLEND_EXT 0 -#define GL_TEXTURE_ENV_SHIFT_EXT 0 -#define GL_ENV_REPLACE_EXT 0 -#define GL_ENV_ADD_EXT 0 -#define GL_ENV_SUBTRACT_EXT 0 -#define GL_TEXTURE_ENV_MODE_ALPHA_EXT 0 -#define GL_ENV_REVERSE_SUBTRACT_EXT 0 -#define GL_ENV_REVERSE_BLEND_EXT 0 -#define GL_ENV_COPY_EXT 0 -#define GL_ENV_MODULATE_EXT 0 - #define GLEW_EXT_texture_env GLEW_GET_VAR(__GLEW_EXT_texture_env) #endif /* GL_EXT_texture_env */ @@ -8976,8 +10391,8 @@ typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint in typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void); -typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, char *name); -typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const char ** varyings, GLenum bufferMode); +typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const GLchar * const* varyings, GLenum bufferMode); #define glBeginTransformFeedbackEXT GLEW_GET_FUN(__glewBeginTransformFeedbackEXT) #define glBindBufferBaseEXT GLEW_GET_FUN(__glewBindBufferBaseEXT) @@ -9031,13 +10446,13 @@ typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint progra #define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i); -typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer); -typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); -typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void* pointer); -typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); -typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void* pointer); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); #define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT) #define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT) @@ -9091,7 +10506,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); #define glGetVertexAttribLdvEXT GLEW_GET_FUN(__glewGetVertexAttribLdvEXT) #define glVertexArrayVertexAttribLOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribLOffsetEXT) @@ -9334,7 +10749,7 @@ typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum #define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F #define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 -typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight); @@ -9379,7 +10794,7 @@ typedef void (GLAPIENTRY * PFNGLFRAMETERMINATORGREMEDYPROC) (void); #ifndef GL_GREMEDY_string_marker #define GL_GREMEDY_string_marker 1 -typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void* string); +typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string); #define glStringMarkerGREMEDY GLEW_GET_FUN(__glewStringMarkerGREMEDY) @@ -9424,9 +10839,6 @@ typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, #ifndef GL_HP_occlusion_test #define GL_HP_occlusion_test 1 -#define GL_OCCLUSION_TEST_HP 0x8165 -#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 - #define GLEW_HP_occlusion_test GLEW_GET_VAR(__GLEW_HP_occlusion_test) #endif /* GL_HP_occlusion_test */ @@ -9573,6 +10985,28 @@ typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum ty #endif /* GL_INGR_interlace_read */ +/* -------------------------- GL_INTEL_map_texture ------------------------- */ + +#ifndef GL_INTEL_map_texture +#define GL_INTEL_map_texture 1 + +#define GL_LAYOUT_DEFAULT_INTEL 0 +#define GL_LAYOUT_LINEAR_INTEL 1 +#define GL_LAYOUT_LINEAR_CPU_CACHED_INTEL 2 +#define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF + +typedef GLvoid * (GLAPIENTRY * PFNGLMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level, GLbitfield access, GLint* stride, GLenum *layout); +typedef void (GLAPIENTRY * PFNGLSYNCTEXTUREINTELPROC) (GLuint texture); +typedef void (GLAPIENTRY * PFNGLUNMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level); + +#define glMapTexture2DINTEL GLEW_GET_FUN(__glewMapTexture2DINTEL) +#define glSyncTextureINTEL GLEW_GET_FUN(__glewSyncTextureINTEL) +#define glUnmapTexture2DINTEL GLEW_GET_FUN(__glewUnmapTexture2DINTEL) + +#define GLEW_INTEL_map_texture GLEW_GET_VAR(__GLEW_INTEL_map_texture) + +#endif /* GL_INTEL_map_texture */ + /* ------------------------ GL_INTEL_parallel_arrays ----------------------- */ #ifndef GL_INTEL_parallel_arrays @@ -9613,6 +11047,118 @@ typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tl #endif /* GL_INTEL_texture_scissor */ +/* ------------------------------ GL_KHR_debug ----------------------------- */ + +#ifndef GL_KHR_debug +#define GL_KHR_debug 1 + +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C +#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D +#define GL_BUFFER 0x82E0 +#define GL_SHADER 0x82E1 +#define GL_PROGRAM 0x82E2 +#define GL_QUERY 0x82E3 +#define GL_PROGRAM_PIPELINE 0x82E4 +#define GL_SAMPLER 0x82E6 +#define GL_DISPLAY_LIST 0x82E7 +#define GL_MAX_LABEL_LENGTH 0x82E8 +#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES 0x9145 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_OUTPUT 0x92E0 + +typedef void (APIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); + +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const GLvoid *userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog); +typedef void (GLAPIENTRY * PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar *label); +typedef void (GLAPIENTRY * PFNGLGETOBJECTPTRLABELPROC) (void* ptr, GLsizei bufSize, GLsizei* length, GLchar *label); +typedef void (GLAPIENTRY * PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar* label); +typedef void (GLAPIENTRY * PFNGLOBJECTPTRLABELPROC) (void* ptr, GLsizei length, const GLchar* label); +typedef void (GLAPIENTRY * PFNGLPOPDEBUGGROUPPROC) (void); +typedef void (GLAPIENTRY * PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar * message); + +#define glDebugMessageCallback GLEW_GET_FUN(__glewDebugMessageCallback) +#define glDebugMessageControl GLEW_GET_FUN(__glewDebugMessageControl) +#define glDebugMessageInsert GLEW_GET_FUN(__glewDebugMessageInsert) +#define glGetDebugMessageLog GLEW_GET_FUN(__glewGetDebugMessageLog) +#define glGetObjectLabel GLEW_GET_FUN(__glewGetObjectLabel) +#define glGetObjectPtrLabel GLEW_GET_FUN(__glewGetObjectPtrLabel) +#define glObjectLabel GLEW_GET_FUN(__glewObjectLabel) +#define glObjectPtrLabel GLEW_GET_FUN(__glewObjectPtrLabel) +#define glPopDebugGroup GLEW_GET_FUN(__glewPopDebugGroup) +#define glPushDebugGroup GLEW_GET_FUN(__glewPushDebugGroup) + +#define GLEW_KHR_debug GLEW_GET_VAR(__GLEW_KHR_debug) + +#endif /* GL_KHR_debug */ + +/* ------------------ GL_KHR_texture_compression_astc_ldr ------------------ */ + +#ifndef GL_KHR_texture_compression_astc_ldr +#define GL_KHR_texture_compression_astc_ldr 1 + +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD + +#define GLEW_KHR_texture_compression_astc_ldr GLEW_GET_VAR(__GLEW_KHR_texture_compression_astc_ldr) + +#endif /* GL_KHR_texture_compression_astc_ldr */ + /* -------------------------- GL_KTX_buffer_region ------------------------- */ #ifndef GL_KTX_buffer_region @@ -9623,17 +11169,17 @@ typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tl #define GL_KTX_Z_REGION 0x2 #define GL_KTX_STENCIL_REGION 0x3 -typedef GLuint (GLAPIENTRY * PFNGLBUFFERREGIONENABLEDEXTPROC) (void); -typedef void (GLAPIENTRY * PFNGLDELETEBUFFERREGIONEXTPROC) (GLenum region); -typedef void (GLAPIENTRY * PFNGLDRAWBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height, GLint xDest, GLint yDest); -typedef GLuint (GLAPIENTRY * PFNGLNEWBUFFERREGIONEXTPROC) (GLenum region); -typedef void (GLAPIENTRY * PFNGLREADBUFFERREGIONEXTPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height); +typedef GLuint (GLAPIENTRY * PFNGLBUFFERREGIONENABLEDPROC) (void); +typedef void (GLAPIENTRY * PFNGLDELETEBUFFERREGIONPROC) (GLenum region); +typedef void (GLAPIENTRY * PFNGLDRAWBUFFERREGIONPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height, GLint xDest, GLint yDest); +typedef GLuint (GLAPIENTRY * PFNGLNEWBUFFERREGIONPROC) (GLenum region); +typedef void (GLAPIENTRY * PFNGLREADBUFFERREGIONPROC) (GLuint region, GLint x, GLint y, GLsizei width, GLsizei height); -#define glBufferRegionEnabledEXT GLEW_GET_FUN(__glewBufferRegionEnabledEXT) -#define glDeleteBufferRegionEXT GLEW_GET_FUN(__glewDeleteBufferRegionEXT) -#define glDrawBufferRegionEXT GLEW_GET_FUN(__glewDrawBufferRegionEXT) -#define glNewBufferRegionEXT GLEW_GET_FUN(__glewNewBufferRegionEXT) -#define glReadBufferRegionEXT GLEW_GET_FUN(__glewReadBufferRegionEXT) +#define glBufferRegionEnabled GLEW_GET_FUN(__glewBufferRegionEnabled) +#define glDeleteBufferRegion GLEW_GET_FUN(__glewDeleteBufferRegion) +#define glDrawBufferRegion GLEW_GET_FUN(__glewDrawBufferRegion) +#define glNewBufferRegion GLEW_GET_FUN(__glewNewBufferRegion) +#define glReadBufferRegion GLEW_GET_FUN(__glewReadBufferRegion) #define GLEW_KTX_buffer_region GLEW_GET_VAR(__GLEW_KTX_buffer_region) @@ -9751,6 +11297,21 @@ typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p); #endif /* GL_MESA_ycbcr_texture */ +/* ----------------------- GL_NVX_conditional_render ----------------------- */ + +#ifndef GL_NVX_conditional_render +#define GL_NVX_conditional_render 1 + +typedef void (GLAPIENTRY * PFNGLBEGINCONDITIONALRENDERNVXPROC) (GLuint id); +typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVXPROC) (void); + +#define glBeginConditionalRenderNVX GLEW_GET_FUN(__glewBeginConditionalRenderNVX) +#define glEndConditionalRenderNVX GLEW_GET_FUN(__glewEndConditionalRenderNVX) + +#define GLEW_NVX_conditional_render GLEW_GET_VAR(__GLEW_NVX_conditional_render) + +#endif /* GL_NVX_conditional_render */ + /* ------------------------- GL_NVX_gpu_memory_info ------------------------ */ #ifndef GL_NVX_gpu_memory_info @@ -9766,6 +11327,129 @@ typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p); #endif /* GL_NVX_gpu_memory_info */ +/* ------------------- GL_NV_bindless_multi_draw_indirect ------------------ */ + +#ifndef GL_NV_bindless_multi_draw_indirect +#define GL_NV_bindless_multi_draw_indirect 1 + +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const GLvoid *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); + +#define glMultiDrawArraysIndirectBindlessNV GLEW_GET_FUN(__glewMultiDrawArraysIndirectBindlessNV) +#define glMultiDrawElementsIndirectBindlessNV GLEW_GET_FUN(__glewMultiDrawElementsIndirectBindlessNV) + +#define GLEW_NV_bindless_multi_draw_indirect GLEW_GET_VAR(__GLEW_NV_bindless_multi_draw_indirect) + +#endif /* GL_NV_bindless_multi_draw_indirect */ + +/* ------------------------- GL_NV_bindless_texture ------------------------ */ + +#ifndef GL_NV_bindless_texture +#define GL_NV_bindless_texture 1 + +typedef GLuint64 (GLAPIENTRY * PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); +typedef GLuint64 (GLAPIENTRY * PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture); +typedef GLuint64 (GLAPIENTRY * PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler); +typedef GLboolean (GLAPIENTRY * PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle); +typedef GLboolean (GLAPIENTRY * PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle); +typedef void (GLAPIENTRY * PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle); +typedef void (GLAPIENTRY * PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access); +typedef void (GLAPIENTRY * PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle); +typedef void (GLAPIENTRY * PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value); +typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64* values); +typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value); +typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64* value); + +#define glGetImageHandleNV GLEW_GET_FUN(__glewGetImageHandleNV) +#define glGetTextureHandleNV GLEW_GET_FUN(__glewGetTextureHandleNV) +#define glGetTextureSamplerHandleNV GLEW_GET_FUN(__glewGetTextureSamplerHandleNV) +#define glIsImageHandleResidentNV GLEW_GET_FUN(__glewIsImageHandleResidentNV) +#define glIsTextureHandleResidentNV GLEW_GET_FUN(__glewIsTextureHandleResidentNV) +#define glMakeImageHandleNonResidentNV GLEW_GET_FUN(__glewMakeImageHandleNonResidentNV) +#define glMakeImageHandleResidentNV GLEW_GET_FUN(__glewMakeImageHandleResidentNV) +#define glMakeTextureHandleNonResidentNV GLEW_GET_FUN(__glewMakeTextureHandleNonResidentNV) +#define glMakeTextureHandleResidentNV GLEW_GET_FUN(__glewMakeTextureHandleResidentNV) +#define glProgramUniformHandleui64NV GLEW_GET_FUN(__glewProgramUniformHandleui64NV) +#define glProgramUniformHandleui64vNV GLEW_GET_FUN(__glewProgramUniformHandleui64vNV) +#define glUniformHandleui64NV GLEW_GET_FUN(__glewUniformHandleui64NV) +#define glUniformHandleui64vNV GLEW_GET_FUN(__glewUniformHandleui64vNV) + +#define GLEW_NV_bindless_texture GLEW_GET_VAR(__GLEW_NV_bindless_texture) + +#endif /* GL_NV_bindless_texture */ + +/* --------------------- GL_NV_blend_equation_advanced --------------------- */ + +#ifndef GL_NV_blend_equation_advanced +#define GL_NV_blend_equation_advanced 1 + +#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280 +#define GL_BLEND_OVERLAP_NV 0x9281 +#define GL_UNCORRELATED_NV 0x9282 +#define GL_DISJOINT_NV 0x9283 +#define GL_CONJOINT_NV 0x9284 +#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285 +#define GL_SRC_NV 0x9286 +#define GL_DST_NV 0x9287 +#define GL_SRC_OVER_NV 0x9288 +#define GL_DST_OVER_NV 0x9289 +#define GL_SRC_IN_NV 0x928A +#define GL_DST_IN_NV 0x928B +#define GL_SRC_OUT_NV 0x928C +#define GL_DST_OUT_NV 0x928D +#define GL_SRC_ATOP_NV 0x928E +#define GL_DST_ATOP_NV 0x928F +#define GL_PLUS_NV 0x9291 +#define GL_PLUS_DARKER_NV 0x9292 +#define GL_MULTIPLY_NV 0x9294 +#define GL_SCREEN_NV 0x9295 +#define GL_OVERLAY_NV 0x9296 +#define GL_DARKEN_NV 0x9297 +#define GL_LIGHTEN_NV 0x9298 +#define GL_COLORDODGE_NV 0x9299 +#define GL_COLORBURN_NV 0x929A +#define GL_HARDLIGHT_NV 0x929B +#define GL_SOFTLIGHT_NV 0x929C +#define GL_DIFFERENCE_NV 0x929E +#define GL_MINUS_NV 0x929F +#define GL_EXCLUSION_NV 0x92A0 +#define GL_CONTRAST_NV 0x92A1 +#define GL_INVERT_RGB_NV 0x92A3 +#define GL_LINEARDODGE_NV 0x92A4 +#define GL_LINEARBURN_NV 0x92A5 +#define GL_VIVIDLIGHT_NV 0x92A6 +#define GL_LINEARLIGHT_NV 0x92A7 +#define GL_PINLIGHT_NV 0x92A8 +#define GL_HARDMIX_NV 0x92A9 +#define GL_HSL_HUE_NV 0x92AD +#define GL_HSL_SATURATION_NV 0x92AE +#define GL_HSL_COLOR_NV 0x92AF +#define GL_HSL_LUMINOSITY_NV 0x92B0 +#define GL_PLUS_CLAMPED_NV 0x92B1 +#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2 +#define GL_MINUS_CLAMPED_NV 0x92B3 +#define GL_INVERT_OVG_NV 0x92B4 + +typedef void (GLAPIENTRY * PFNGLBLENDBARRIERNVPROC) (void); +typedef void (GLAPIENTRY * PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value); + +#define glBlendBarrierNV GLEW_GET_FUN(__glewBlendBarrierNV) +#define glBlendParameteriNV GLEW_GET_FUN(__glewBlendParameteriNV) + +#define GLEW_NV_blend_equation_advanced GLEW_GET_VAR(__GLEW_NV_blend_equation_advanced) + +#endif /* GL_NV_blend_equation_advanced */ + +/* ----------------- GL_NV_blend_equation_advanced_coherent ---------------- */ + +#ifndef GL_NV_blend_equation_advanced_coherent +#define GL_NV_blend_equation_advanced_coherent 1 + +#define GLEW_NV_blend_equation_advanced_coherent GLEW_GET_VAR(__GLEW_NV_blend_equation_advanced_coherent) + +#endif /* GL_NV_blend_equation_advanced_coherent */ + /* --------------------------- GL_NV_blend_square -------------------------- */ #ifndef GL_NV_blend_square @@ -9775,6 +11459,18 @@ typedef void (GLAPIENTRY * PFNGLWINDOWPOS4SVMESAPROC) (const GLshort* p); #endif /* GL_NV_blend_square */ +/* ------------------------- GL_NV_compute_program5 ------------------------ */ + +#ifndef GL_NV_compute_program5 +#define GL_NV_compute_program5 1 + +#define GL_COMPUTE_PROGRAM_NV 0x90FB +#define GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC + +#define GLEW_NV_compute_program5 GLEW_GET_VAR(__GLEW_NV_compute_program5) + +#endif /* GL_NV_compute_program5 */ + /* ------------------------ GL_NV_conditional_render ----------------------- */ #ifndef GL_NV_conditional_render @@ -9820,6 +11516,18 @@ typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum #endif /* GL_NV_copy_image */ +/* -------------------------- GL_NV_deep_texture3D ------------------------- */ + +#ifndef GL_NV_deep_texture3D +#define GL_NV_deep_texture3D 1 + +#define GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV 0x90D0 +#define GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV 0x90D1 + +#define GLEW_NV_deep_texture3D GLEW_GET_VAR(__GLEW_NV_deep_texture3D) + +#endif /* GL_NV_deep_texture3D */ + /* ------------------------ GL_NV_depth_buffer_float ----------------------- */ #ifndef GL_NV_depth_buffer_float @@ -9868,6 +11576,19 @@ typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFa #endif /* GL_NV_depth_range_unclamped */ +/* --------------------------- GL_NV_draw_texture -------------------------- */ + +#ifndef GL_NV_draw_texture +#define GL_NV_draw_texture 1 + +typedef void (GLAPIENTRY * PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); + +#define glDrawTextureNV GLEW_GET_FUN(__glewDrawTextureNV) + +#define GLEW_NV_draw_texture GLEW_GET_VAR(__GLEW_NV_draw_texture) + +#endif /* GL_NV_draw_texture */ + /* ---------------------------- GL_NV_evaluators --------------------------- */ #ifndef GL_NV_evaluators @@ -9901,10 +11622,10 @@ typedef void (GLAPIENTRY * PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFa typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void* points); +typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void* points); +typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params); @@ -10184,6 +11905,15 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum targe #endif /* GL_NV_gpu_program5 */ +/* -------------------- GL_NV_gpu_program5_mem_extended -------------------- */ + +#ifndef GL_NV_gpu_program5_mem_extended +#define GL_NV_gpu_program5_mem_extended 1 + +#define GLEW_NV_gpu_program5_mem_extended GLEW_GET_VAR(__GLEW_NV_gpu_program5_mem_extended) + +#endif /* GL_NV_gpu_program5_mem_extended */ + /* ------------------------- GL_NV_gpu_program_fp64 ------------------------ */ #ifndef GL_NV_gpu_program_fp64 @@ -10425,7 +12155,6 @@ typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalf* weight); #ifndef GL_NV_multisample_coverage #define GL_NV_multisample_coverage 1 -#define GL_COVERAGE_SAMPLES_NV 0x80A9 #define GL_COLOR_SAMPLES_NV 0x8E20 #define GLEW_NV_multisample_coverage GLEW_GET_VAR(__GLEW_NV_multisample_coverage) @@ -10517,6 +12246,244 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, #endif /* GL_NV_parameter_buffer_object2 */ +/* -------------------------- GL_NV_path_rendering ------------------------- */ + +#ifndef GL_NV_path_rendering +#define GL_NV_path_rendering 1 + +#define GL_CLOSE_PATH_NV 0x00 +#define GL_BOLD_BIT_NV 0x01 +#define GL_GLYPH_WIDTH_BIT_NV 0x01 +#define GL_GLYPH_HEIGHT_BIT_NV 0x02 +#define GL_ITALIC_BIT_NV 0x02 +#define GL_MOVE_TO_NV 0x02 +#define GL_RELATIVE_MOVE_TO_NV 0x03 +#define GL_LINE_TO_NV 0x04 +#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04 +#define GL_RELATIVE_LINE_TO_NV 0x05 +#define GL_HORIZONTAL_LINE_TO_NV 0x06 +#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07 +#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08 +#define GL_VERTICAL_LINE_TO_NV 0x08 +#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09 +#define GL_QUADRATIC_CURVE_TO_NV 0x0A +#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B +#define GL_CUBIC_CURVE_TO_NV 0x0C +#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D +#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E +#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F +#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10 +#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10 +#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11 +#define GL_SMALL_CCW_ARC_TO_NV 0x12 +#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13 +#define GL_SMALL_CW_ARC_TO_NV 0x14 +#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15 +#define GL_LARGE_CCW_ARC_TO_NV 0x16 +#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17 +#define GL_LARGE_CW_ARC_TO_NV 0x18 +#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19 +#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20 +#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40 +#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80 +#define GL_RESTART_PATH_NV 0xF0 +#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2 +#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4 +#define GL_RECT_NV 0xF6 +#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8 +#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA +#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC +#define GL_ARC_TO_NV 0xFE +#define GL_RELATIVE_ARC_TO_NV 0xFF +#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PATH_FORMAT_SVG_NV 0x9070 +#define GL_PATH_FORMAT_PS_NV 0x9071 +#define GL_STANDARD_FONT_NAME_NV 0x9072 +#define GL_SYSTEM_FONT_NAME_NV 0x9073 +#define GL_FILE_NAME_NV 0x9074 +#define GL_PATH_STROKE_WIDTH_NV 0x9075 +#define GL_PATH_END_CAPS_NV 0x9076 +#define GL_PATH_INITIAL_END_CAP_NV 0x9077 +#define GL_PATH_TERMINAL_END_CAP_NV 0x9078 +#define GL_PATH_JOIN_STYLE_NV 0x9079 +#define GL_PATH_MITER_LIMIT_NV 0x907A +#define GL_PATH_DASH_CAPS_NV 0x907B +#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C +#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D +#define GL_PATH_DASH_OFFSET_NV 0x907E +#define GL_PATH_CLIENT_LENGTH_NV 0x907F +#define GL_PATH_FILL_MODE_NV 0x9080 +#define GL_PATH_FILL_MASK_NV 0x9081 +#define GL_PATH_FILL_COVER_MODE_NV 0x9082 +#define GL_PATH_STROKE_COVER_MODE_NV 0x9083 +#define GL_PATH_STROKE_MASK_NV 0x9084 +#define GL_COUNT_UP_NV 0x9088 +#define GL_COUNT_DOWN_NV 0x9089 +#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A +#define GL_CONVEX_HULL_NV 0x908B +#define GL_BOUNDING_BOX_NV 0x908D +#define GL_TRANSLATE_X_NV 0x908E +#define GL_TRANSLATE_Y_NV 0x908F +#define GL_TRANSLATE_2D_NV 0x9090 +#define GL_TRANSLATE_3D_NV 0x9091 +#define GL_AFFINE_2D_NV 0x9092 +#define GL_AFFINE_3D_NV 0x9094 +#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096 +#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098 +#define GL_UTF8_NV 0x909A +#define GL_UTF16_NV 0x909B +#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C +#define GL_PATH_COMMAND_COUNT_NV 0x909D +#define GL_PATH_COORD_COUNT_NV 0x909E +#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F +#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0 +#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1 +#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2 +#define GL_SQUARE_NV 0x90A3 +#define GL_ROUND_NV 0x90A4 +#define GL_TRIANGULAR_NV 0x90A5 +#define GL_BEVEL_NV 0x90A6 +#define GL_MITER_REVERT_NV 0x90A7 +#define GL_MITER_TRUNCATE_NV 0x90A8 +#define GL_SKIP_MISSING_GLYPH_NV 0x90A9 +#define GL_USE_MISSING_GLYPH_NV 0x90AA +#define GL_PATH_ERROR_POSITION_NV 0x90AB +#define GL_PATH_FOG_GEN_MODE_NV 0x90AC +#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD +#define GL_ADJACENT_PAIRS_NV 0x90AE +#define GL_FIRST_TO_REST_NV 0x90AF +#define GL_PATH_GEN_MODE_NV 0x90B0 +#define GL_PATH_GEN_COEFF_NV 0x90B1 +#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2 +#define GL_PATH_GEN_COMPONENTS_NV 0x90B3 +#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4 +#define GL_MOVE_TO_RESETS_NV 0x90B5 +#define GL_MOVE_TO_CONTINUES_NV 0x90B6 +#define GL_PATH_STENCIL_FUNC_NV 0x90B7 +#define GL_PATH_STENCIL_REF_NV 0x90B8 +#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9 +#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD +#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE +#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF +#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000 +#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000 +#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000 +#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000 +#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000 +#define GL_FONT_ASCENDER_BIT_NV 0x00200000 +#define GL_FONT_DESCENDER_BIT_NV 0x00400000 +#define GL_FONT_HEIGHT_BIT_NV 0x00800000 +#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000 +#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000 +#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000 +#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000 +#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000 + +typedef void (GLAPIENTRY * PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath); +typedef void (GLAPIENTRY * PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef void (GLAPIENTRY * PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode); +typedef void (GLAPIENTRY * PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); +typedef void (GLAPIENTRY * PFNGLCOVERSTROKEPATHNVPROC) (GLuint name, GLenum coverMode); +typedef void (GLAPIENTRY * PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range); +typedef GLuint (GLAPIENTRY * PFNGLGENPATHSNVPROC) (GLsizei range); +typedef void (GLAPIENTRY * PFNGLGETPATHCOLORGENFVNVPROC) (GLenum color, GLenum pname, GLfloat* value); +typedef void (GLAPIENTRY * PFNGLGETPATHCOLORGENIVNVPROC) (GLenum color, GLenum pname, GLint* value); +typedef void (GLAPIENTRY * PFNGLGETPATHCOMMANDSNVPROC) (GLuint name, GLubyte* commands); +typedef void (GLAPIENTRY * PFNGLGETPATHCOORDSNVPROC) (GLuint name, GLfloat* coords); +typedef void (GLAPIENTRY * PFNGLGETPATHDASHARRAYNVPROC) (GLuint name, GLfloat* dashArray); +typedef GLfloat (GLAPIENTRY * PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments); +typedef void (GLAPIENTRY * PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint fistPathName, GLsizei numPaths, GLsizei stride, GLfloat* metrics); +typedef void (GLAPIENTRY * PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLsizei stride, GLfloat *metrics); +typedef void (GLAPIENTRY * PFNGLGETPATHPARAMETERFVNVPROC) (GLuint name, GLenum param, GLfloat* value); +typedef void (GLAPIENTRY * PFNGLGETPATHPARAMETERIVNVPROC) (GLuint name, GLenum param, GLint* value); +typedef void (GLAPIENTRY * PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); +typedef void (GLAPIENTRY * PFNGLGETPATHTEXGENFVNVPROC) (GLenum texCoordSet, GLenum pname, GLfloat* value); +typedef void (GLAPIENTRY * PFNGLGETPATHTEXGENIVNVPROC) (GLenum texCoordSet, GLenum pname, GLint* value); +typedef void (GLAPIENTRY * PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight); +typedef GLboolean (GLAPIENTRY * PFNGLISPATHNVPROC) (GLuint path); +typedef GLboolean (GLAPIENTRY * PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y); +typedef GLboolean (GLAPIENTRY * PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y); +typedef void (GLAPIENTRY * PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat* coeffs); +typedef void (GLAPIENTRY * PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const GLvoid*coords); +typedef void (GLAPIENTRY * PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void* coords); +typedef void (GLAPIENTRY * PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum zfunc); +typedef void (GLAPIENTRY * PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat* dashArray); +typedef void (GLAPIENTRY * PFNGLPATHFOGGENNVPROC) (GLenum genMode); +typedef void (GLAPIENTRY * PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void* fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (GLAPIENTRY * PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void* fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const GLvoid*charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (GLAPIENTRY * PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value); +typedef void (GLAPIENTRY * PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat* value); +typedef void (GLAPIENTRY * PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value); +typedef void (GLAPIENTRY * PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint* value); +typedef void (GLAPIENTRY * PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units); +typedef void (GLAPIENTRY * PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask); +typedef void (GLAPIENTRY * PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void* pathString); +typedef void (GLAPIENTRY * PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const GLvoid*coords); +typedef void (GLAPIENTRY * PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void* coords); +typedef void (GLAPIENTRY * PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat* coeffs); +typedef GLboolean (GLAPIENTRY * PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat* x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY); +typedef void (GLAPIENTRY * PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues); +typedef void (GLAPIENTRY * PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask); +typedef void (GLAPIENTRY * PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void* paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues); +typedef void (GLAPIENTRY * PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask); +typedef void (GLAPIENTRY * PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat* transformValues); +typedef void (GLAPIENTRY * PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint paths[], const GLfloat weights[]); + +#define glCopyPathNV GLEW_GET_FUN(__glewCopyPathNV) +#define glCoverFillPathInstancedNV GLEW_GET_FUN(__glewCoverFillPathInstancedNV) +#define glCoverFillPathNV GLEW_GET_FUN(__glewCoverFillPathNV) +#define glCoverStrokePathInstancedNV GLEW_GET_FUN(__glewCoverStrokePathInstancedNV) +#define glCoverStrokePathNV GLEW_GET_FUN(__glewCoverStrokePathNV) +#define glDeletePathsNV GLEW_GET_FUN(__glewDeletePathsNV) +#define glGenPathsNV GLEW_GET_FUN(__glewGenPathsNV) +#define glGetPathColorGenfvNV GLEW_GET_FUN(__glewGetPathColorGenfvNV) +#define glGetPathColorGenivNV GLEW_GET_FUN(__glewGetPathColorGenivNV) +#define glGetPathCommandsNV GLEW_GET_FUN(__glewGetPathCommandsNV) +#define glGetPathCoordsNV GLEW_GET_FUN(__glewGetPathCoordsNV) +#define glGetPathDashArrayNV GLEW_GET_FUN(__glewGetPathDashArrayNV) +#define glGetPathLengthNV GLEW_GET_FUN(__glewGetPathLengthNV) +#define glGetPathMetricRangeNV GLEW_GET_FUN(__glewGetPathMetricRangeNV) +#define glGetPathMetricsNV GLEW_GET_FUN(__glewGetPathMetricsNV) +#define glGetPathParameterfvNV GLEW_GET_FUN(__glewGetPathParameterfvNV) +#define glGetPathParameterivNV GLEW_GET_FUN(__glewGetPathParameterivNV) +#define glGetPathSpacingNV GLEW_GET_FUN(__glewGetPathSpacingNV) +#define glGetPathTexGenfvNV GLEW_GET_FUN(__glewGetPathTexGenfvNV) +#define glGetPathTexGenivNV GLEW_GET_FUN(__glewGetPathTexGenivNV) +#define glInterpolatePathsNV GLEW_GET_FUN(__glewInterpolatePathsNV) +#define glIsPathNV GLEW_GET_FUN(__glewIsPathNV) +#define glIsPointInFillPathNV GLEW_GET_FUN(__glewIsPointInFillPathNV) +#define glIsPointInStrokePathNV GLEW_GET_FUN(__glewIsPointInStrokePathNV) +#define glPathColorGenNV GLEW_GET_FUN(__glewPathColorGenNV) +#define glPathCommandsNV GLEW_GET_FUN(__glewPathCommandsNV) +#define glPathCoordsNV GLEW_GET_FUN(__glewPathCoordsNV) +#define glPathCoverDepthFuncNV GLEW_GET_FUN(__glewPathCoverDepthFuncNV) +#define glPathDashArrayNV GLEW_GET_FUN(__glewPathDashArrayNV) +#define glPathFogGenNV GLEW_GET_FUN(__glewPathFogGenNV) +#define glPathGlyphRangeNV GLEW_GET_FUN(__glewPathGlyphRangeNV) +#define glPathGlyphsNV GLEW_GET_FUN(__glewPathGlyphsNV) +#define glPathParameterfNV GLEW_GET_FUN(__glewPathParameterfNV) +#define glPathParameterfvNV GLEW_GET_FUN(__glewPathParameterfvNV) +#define glPathParameteriNV GLEW_GET_FUN(__glewPathParameteriNV) +#define glPathParameterivNV GLEW_GET_FUN(__glewPathParameterivNV) +#define glPathStencilDepthOffsetNV GLEW_GET_FUN(__glewPathStencilDepthOffsetNV) +#define glPathStencilFuncNV GLEW_GET_FUN(__glewPathStencilFuncNV) +#define glPathStringNV GLEW_GET_FUN(__glewPathStringNV) +#define glPathSubCommandsNV GLEW_GET_FUN(__glewPathSubCommandsNV) +#define glPathSubCoordsNV GLEW_GET_FUN(__glewPathSubCoordsNV) +#define glPathTexGenNV GLEW_GET_FUN(__glewPathTexGenNV) +#define glPointAlongPathNV GLEW_GET_FUN(__glewPointAlongPathNV) +#define glStencilFillPathInstancedNV GLEW_GET_FUN(__glewStencilFillPathInstancedNV) +#define glStencilFillPathNV GLEW_GET_FUN(__glewStencilFillPathNV) +#define glStencilStrokePathInstancedNV GLEW_GET_FUN(__glewStencilStrokePathInstancedNV) +#define glStencilStrokePathNV GLEW_GET_FUN(__glewStencilStrokePathNV) +#define glTransformPathNV GLEW_GET_FUN(__glewTransformPathNV) +#define glWeightPathsNV GLEW_GET_FUN(__glewWeightPathsNV) + +#define GLEW_NV_path_rendering GLEW_GET_VAR(__GLEW_NV_path_rendering) + +#endif /* GL_NV_path_rendering */ + /* ------------------------- GL_NV_pixel_data_range ------------------------ */ #ifndef GL_NV_pixel_data_range @@ -10530,7 +12497,7 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, #define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void* pointer); +typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer); #define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV) #define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV) @@ -10712,6 +12679,24 @@ typedef void (GLAPIENTRY * PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage #endif /* GL_NV_register_combiners2 */ +/* ---------------------- GL_NV_shader_atomic_counters --------------------- */ + +#ifndef GL_NV_shader_atomic_counters +#define GL_NV_shader_atomic_counters 1 + +#define GLEW_NV_shader_atomic_counters GLEW_GET_VAR(__GLEW_NV_shader_atomic_counters) + +#endif /* GL_NV_shader_atomic_counters */ + +/* ----------------------- GL_NV_shader_atomic_float ----------------------- */ + +#ifndef GL_NV_shader_atomic_float +#define GL_NV_shader_atomic_float 1 + +#define GLEW_NV_shader_atomic_float GLEW_GET_VAR(__GLEW_NV_shader_atomic_float) + +#endif /* GL_NV_shader_atomic_float */ + /* ------------------------ GL_NV_shader_buffer_load ----------------------- */ #ifndef GL_NV_shader_buffer_load @@ -10753,6 +12738,15 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei cou #endif /* GL_NV_shader_buffer_load */ +/* ------------------- GL_NV_shader_storage_buffer_object ------------------ */ + +#ifndef GL_NV_shader_storage_buffer_object +#define GL_NV_shader_storage_buffer_object 1 + +#define GLEW_NV_shader_storage_buffer_object GLEW_GET_VAR(__GLEW_NV_shader_storage_buffer_object) + +#endif /* GL_NV_shader_storage_buffer_object */ + /* ---------------------- GL_NV_tessellation_program5 ---------------------- */ #ifndef GL_NV_tessellation_program5 @@ -11168,7 +13162,7 @@ typedef void (GLAPIENTRY * PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV #define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, GLvoid *pointer); #define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV) #define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV) @@ -11440,7 +13434,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); @@ -11646,8 +13640,6 @@ typedef void (GLAPIENTRY * PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint vid #ifndef GL_OES_byte_coordinates #define GL_OES_byte_coordinates 1 -#define GL_BYTE 0x1400 - #define GLEW_OES_byte_coordinates GLEW_GET_VAR(__GLEW_OES_byte_coordinates) #endif /* GL_OES_byte_coordinates */ @@ -11809,6 +13801,191 @@ typedef void (GLAPIENTRY * PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, #endif /* GL_PGI_vertex_hints */ +/* ---------------------- GL_REGAL_ES1_0_compatibility --------------------- */ + +#ifndef GL_REGAL_ES1_0_compatibility +#define GL_REGAL_ES1_0_compatibility 1 + +typedef int GLclampx; + +typedef void (GLAPIENTRY * PFNGLALPHAFUNCXPROC) (GLenum func, GLclampx ref); +typedef void (GLAPIENTRY * PFNGLCLEARCOLORXPROC) (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha); +typedef void (GLAPIENTRY * PFNGLCLEARDEPTHXPROC) (GLclampx depth); +typedef void (GLAPIENTRY * PFNGLCOLOR4XPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +typedef void (GLAPIENTRY * PFNGLDEPTHRANGEXPROC) (GLclampx zNear, GLclampx zFar); +typedef void (GLAPIENTRY * PFNGLFOGXPROC) (GLenum pname, GLfixed param); +typedef void (GLAPIENTRY * PFNGLFOGXVPROC) (GLenum pname, const GLfixed* params); +typedef void (GLAPIENTRY * PFNGLFRUSTUMFPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +typedef void (GLAPIENTRY * PFNGLFRUSTUMXPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); +typedef void (GLAPIENTRY * PFNGLLIGHTMODELXPROC) (GLenum pname, GLfixed param); +typedef void (GLAPIENTRY * PFNGLLIGHTMODELXVPROC) (GLenum pname, const GLfixed* params); +typedef void (GLAPIENTRY * PFNGLLIGHTXPROC) (GLenum light, GLenum pname, GLfixed param); +typedef void (GLAPIENTRY * PFNGLLIGHTXVPROC) (GLenum light, GLenum pname, const GLfixed* params); +typedef void (GLAPIENTRY * PFNGLLINEWIDTHXPROC) (GLfixed width); +typedef void (GLAPIENTRY * PFNGLLOADMATRIXXPROC) (const GLfixed* m); +typedef void (GLAPIENTRY * PFNGLMATERIALXPROC) (GLenum face, GLenum pname, GLfixed param); +typedef void (GLAPIENTRY * PFNGLMATERIALXVPROC) (GLenum face, GLenum pname, const GLfixed* params); +typedef void (GLAPIENTRY * PFNGLMULTMATRIXXPROC) (const GLfixed* m); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORD4XPROC) (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q); +typedef void (GLAPIENTRY * PFNGLNORMAL3XPROC) (GLfixed nx, GLfixed ny, GLfixed nz); +typedef void (GLAPIENTRY * PFNGLORTHOFPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +typedef void (GLAPIENTRY * PFNGLORTHOXPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); +typedef void (GLAPIENTRY * PFNGLPOINTSIZEXPROC) (GLfixed size); +typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETXPROC) (GLfixed factor, GLfixed units); +typedef void (GLAPIENTRY * PFNGLROTATEXPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); +typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEXPROC) (GLclampx value, GLboolean invert); +typedef void (GLAPIENTRY * PFNGLSCALEXPROC) (GLfixed x, GLfixed y, GLfixed z); +typedef void (GLAPIENTRY * PFNGLTEXENVXPROC) (GLenum target, GLenum pname, GLfixed param); +typedef void (GLAPIENTRY * PFNGLTEXENVXVPROC) (GLenum target, GLenum pname, const GLfixed* params); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERXPROC) (GLenum target, GLenum pname, GLfixed param); +typedef void (GLAPIENTRY * PFNGLTRANSLATEXPROC) (GLfixed x, GLfixed y, GLfixed z); + +#define glAlphaFuncx GLEW_GET_FUN(__glewAlphaFuncx) +#define glClearColorx GLEW_GET_FUN(__glewClearColorx) +#define glClearDepthx GLEW_GET_FUN(__glewClearDepthx) +#define glColor4x GLEW_GET_FUN(__glewColor4x) +#define glDepthRangex GLEW_GET_FUN(__glewDepthRangex) +#define glFogx GLEW_GET_FUN(__glewFogx) +#define glFogxv GLEW_GET_FUN(__glewFogxv) +#define glFrustumf GLEW_GET_FUN(__glewFrustumf) +#define glFrustumx GLEW_GET_FUN(__glewFrustumx) +#define glLightModelx GLEW_GET_FUN(__glewLightModelx) +#define glLightModelxv GLEW_GET_FUN(__glewLightModelxv) +#define glLightx GLEW_GET_FUN(__glewLightx) +#define glLightxv GLEW_GET_FUN(__glewLightxv) +#define glLineWidthx GLEW_GET_FUN(__glewLineWidthx) +#define glLoadMatrixx GLEW_GET_FUN(__glewLoadMatrixx) +#define glMaterialx GLEW_GET_FUN(__glewMaterialx) +#define glMaterialxv GLEW_GET_FUN(__glewMaterialxv) +#define glMultMatrixx GLEW_GET_FUN(__glewMultMatrixx) +#define glMultiTexCoord4x GLEW_GET_FUN(__glewMultiTexCoord4x) +#define glNormal3x GLEW_GET_FUN(__glewNormal3x) +#define glOrthof GLEW_GET_FUN(__glewOrthof) +#define glOrthox GLEW_GET_FUN(__glewOrthox) +#define glPointSizex GLEW_GET_FUN(__glewPointSizex) +#define glPolygonOffsetx GLEW_GET_FUN(__glewPolygonOffsetx) +#define glRotatex GLEW_GET_FUN(__glewRotatex) +#define glSampleCoveragex GLEW_GET_FUN(__glewSampleCoveragex) +#define glScalex GLEW_GET_FUN(__glewScalex) +#define glTexEnvx GLEW_GET_FUN(__glewTexEnvx) +#define glTexEnvxv GLEW_GET_FUN(__glewTexEnvxv) +#define glTexParameterx GLEW_GET_FUN(__glewTexParameterx) +#define glTranslatex GLEW_GET_FUN(__glewTranslatex) + +#define GLEW_REGAL_ES1_0_compatibility GLEW_GET_VAR(__GLEW_REGAL_ES1_0_compatibility) + +#endif /* GL_REGAL_ES1_0_compatibility */ + +/* ---------------------- GL_REGAL_ES1_1_compatibility --------------------- */ + +#ifndef GL_REGAL_ES1_1_compatibility +#define GL_REGAL_ES1_1_compatibility 1 + +typedef void (GLAPIENTRY * PFNGLCLIPPLANEFPROC) (GLenum plane, const GLfloat* equation); +typedef void (GLAPIENTRY * PFNGLCLIPPLANEXPROC) (GLenum plane, const GLfixed* equation); +typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEFPROC) (GLenum pname, GLfloat eqn[4]); +typedef void (GLAPIENTRY * PFNGLGETCLIPPLANEXPROC) (GLenum pname, GLfixed eqn[4]); +typedef void (GLAPIENTRY * PFNGLGETFIXEDVPROC) (GLenum pname, GLfixed* params); +typedef void (GLAPIENTRY * PFNGLGETLIGHTXVPROC) (GLenum light, GLenum pname, GLfixed* params); +typedef void (GLAPIENTRY * PFNGLGETMATERIALXVPROC) (GLenum face, GLenum pname, GLfixed* params); +typedef void (GLAPIENTRY * PFNGLGETTEXENVXVPROC) (GLenum env, GLenum pname, GLfixed* params); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERXVPROC) (GLenum target, GLenum pname, GLfixed* params); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERXPROC) (GLenum pname, GLfixed param); +typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERXVPROC) (GLenum pname, const GLfixed* params); +typedef void (GLAPIENTRY * PFNGLPOINTSIZEPOINTEROESPROC) (GLenum type, GLsizei stride, const GLvoid* pointer); +typedef void (GLAPIENTRY * PFNGLTEXPARAMETERXVPROC) (GLenum target, GLenum pname, const GLfixed* params); + +#define glClipPlanef GLEW_GET_FUN(__glewClipPlanef) +#define glClipPlanex GLEW_GET_FUN(__glewClipPlanex) +#define glGetClipPlanef GLEW_GET_FUN(__glewGetClipPlanef) +#define glGetClipPlanex GLEW_GET_FUN(__glewGetClipPlanex) +#define glGetFixedv GLEW_GET_FUN(__glewGetFixedv) +#define glGetLightxv GLEW_GET_FUN(__glewGetLightxv) +#define glGetMaterialxv GLEW_GET_FUN(__glewGetMaterialxv) +#define glGetTexEnvxv GLEW_GET_FUN(__glewGetTexEnvxv) +#define glGetTexParameterxv GLEW_GET_FUN(__glewGetTexParameterxv) +#define glPointParameterx GLEW_GET_FUN(__glewPointParameterx) +#define glPointParameterxv GLEW_GET_FUN(__glewPointParameterxv) +#define glPointSizePointerOES GLEW_GET_FUN(__glewPointSizePointerOES) +#define glTexParameterxv GLEW_GET_FUN(__glewTexParameterxv) + +#define GLEW_REGAL_ES1_1_compatibility GLEW_GET_VAR(__GLEW_REGAL_ES1_1_compatibility) + +#endif /* GL_REGAL_ES1_1_compatibility */ + +/* ---------------------------- GL_REGAL_enable ---------------------------- */ + +#ifndef GL_REGAL_enable +#define GL_REGAL_enable 1 + +#define GL_ERROR_REGAL 0x9322 +#define GL_DEBUG_REGAL 0x9323 +#define GL_LOG_REGAL 0x9324 +#define GL_EMULATION_REGAL 0x9325 +#define GL_DRIVER_REGAL 0x9326 +#define GL_MISSING_REGAL 0x9360 +#define GL_TRACE_REGAL 0x9361 +#define GL_CACHE_REGAL 0x9362 +#define GL_CODE_REGAL 0x9363 +#define GL_STATISTICS_REGAL 0x9364 + +#define GLEW_REGAL_enable GLEW_GET_VAR(__GLEW_REGAL_enable) + +#endif /* GL_REGAL_enable */ + +/* ------------------------- GL_REGAL_error_string ------------------------- */ + +#ifndef GL_REGAL_error_string +#define GL_REGAL_error_string 1 + +typedef const GLchar* (GLAPIENTRY * PFNGLERRORSTRINGREGALPROC) (GLenum error); + +#define glErrorStringREGAL GLEW_GET_FUN(__glewErrorStringREGAL) + +#define GLEW_REGAL_error_string GLEW_GET_VAR(__GLEW_REGAL_error_string) + +#endif /* GL_REGAL_error_string */ + +/* ------------------------ GL_REGAL_extension_query ----------------------- */ + +#ifndef GL_REGAL_extension_query +#define GL_REGAL_extension_query 1 + +typedef GLboolean (GLAPIENTRY * PFNGLGETEXTENSIONREGALPROC) (const GLchar* ext); +typedef GLboolean (GLAPIENTRY * PFNGLISSUPPORTEDREGALPROC) (const GLchar* ext); + +#define glGetExtensionREGAL GLEW_GET_FUN(__glewGetExtensionREGAL) +#define glIsSupportedREGAL GLEW_GET_FUN(__glewIsSupportedREGAL) + +#define GLEW_REGAL_extension_query GLEW_GET_VAR(__GLEW_REGAL_extension_query) + +#endif /* GL_REGAL_extension_query */ + +/* ------------------------------ GL_REGAL_log ----------------------------- */ + +#ifndef GL_REGAL_log +#define GL_REGAL_log 1 + +#define GL_LOG_ERROR_REGAL 0x9319 +#define GL_LOG_WARNING_REGAL 0x931A +#define GL_LOG_INFO_REGAL 0x931B +#define GL_LOG_APP_REGAL 0x931C +#define GL_LOG_DRIVER_REGAL 0x931D +#define GL_LOG_INTERNAL_REGAL 0x931E +#define GL_LOG_DEBUG_REGAL 0x931F +#define GL_LOG_STATUS_REGAL 0x9320 +#define GL_LOG_HTTP_REGAL 0x9321 + +typedef void (APIENTRY *GLLOGPROCREGAL)(GLenum stream, GLsizei length, const GLchar *message, GLvoid *context); + +typedef void (GLAPIENTRY * PFNGLLOGMESSAGECALLBACKREGALPROC) (GLLOGPROCREGAL callback); + +#define glLogMessageCallbackREGAL GLEW_GET_FUN(__glewLogMessageCallbackREGAL) + +#define GLEW_REGAL_log GLEW_GET_VAR(__GLEW_REGAL_log) + +#endif /* GL_REGAL_log */ + /* ----------------------- GL_REND_screen_coordinates ---------------------- */ #ifndef GL_REND_screen_coordinates @@ -11919,7 +14096,6 @@ typedef void (GLAPIENTRY * PFNGLGETFOGFUNCSGISPROC) (GLfloat* points); #define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA #define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB #define GL_SAMPLE_PATTERN_SGIS 0x80AC -#define GL_MULTISAMPLE_BIT_EXT 0x20000000 typedef void (GLAPIENTRY * PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); @@ -11978,8 +14154,8 @@ typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei #ifndef GL_SGIS_texture4D #define GL_SGIS_texture4D 1 -typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void* pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void* pixels); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const GLvoid *pixels); #define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS) #define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS) @@ -12554,11 +14730,11 @@ typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void* table); +typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void* table); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); #define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI) #define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI) @@ -12700,7 +14876,7 @@ typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsiz #define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA #define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void* pointer); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code); typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); @@ -13172,6 +15348,11 @@ GLEW_FUN_EXPORT PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSepa GLEW_FUN_EXPORT PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD; GLEW_FUN_EXPORT PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBPARAMETERIAMDPROC __glewVertexAttribParameteriAMD; + +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC __glewMultiDrawArraysIndirectAMD; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC __glewMultiDrawElementsIndirectAMD; + GLEW_FUN_EXPORT PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD; GLEW_FUN_EXPORT PFNGLGENNAMESAMDPROC __glewGenNamesAMD; GLEW_FUN_EXPORT PFNGLISNAMEAMDPROC __glewIsNameAMD; @@ -13190,9 +15371,36 @@ GLEW_FUN_EXPORT PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCou GLEW_FUN_EXPORT PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD; +GLEW_FUN_EXPORT PFNGLTEXSTORAGESPARSEAMDPROC __glewTexStorageSparseAMD; +GLEW_FUN_EXPORT PFNGLTEXTURESTORAGESPARSEAMDPROC __glewTextureStorageSparseAMD; + +GLEW_FUN_EXPORT PFNGLSTENCILOPVALUEAMDPROC __glewStencilOpValueAMD; + GLEW_FUN_EXPORT PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD; GLEW_FUN_EXPORT PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD; +GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERANGLEPROC __glewBlitFramebufferANGLE; + +GLEW_FUN_EXPORT PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC __glewRenderbufferStorageMultisampleANGLE; + +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDANGLEPROC __glewDrawArraysInstancedANGLE; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDANGLEPROC __glewDrawElementsInstancedANGLE; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORANGLEPROC __glewVertexAttribDivisorANGLE; + +GLEW_FUN_EXPORT PFNGLBEGINQUERYANGLEPROC __glewBeginQueryANGLE; +GLEW_FUN_EXPORT PFNGLDELETEQUERIESANGLEPROC __glewDeleteQueriesANGLE; +GLEW_FUN_EXPORT PFNGLENDQUERYANGLEPROC __glewEndQueryANGLE; +GLEW_FUN_EXPORT PFNGLGENQUERIESANGLEPROC __glewGenQueriesANGLE; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VANGLEPROC __glewGetQueryObjecti64vANGLE; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTIVANGLEPROC __glewGetQueryObjectivANGLE; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VANGLEPROC __glewGetQueryObjectui64vANGLE; +GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUIVANGLEPROC __glewGetQueryObjectuivANGLE; +GLEW_FUN_EXPORT PFNGLGETQUERYIVANGLEPROC __glewGetQueryivANGLE; +GLEW_FUN_EXPORT PFNGLISQUERYANGLEPROC __glewIsQueryANGLE; +GLEW_FUN_EXPORT PFNGLQUERYCOUNTERANGLEPROC __glewQueryCounterANGLE; + +GLEW_FUN_EXPORT PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC __glewGetTranslatedShaderSourceANGLE; + GLEW_FUN_EXPORT PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE; GLEW_FUN_EXPORT PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE; GLEW_FUN_EXPORT PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE; @@ -13241,15 +15449,54 @@ GLEW_FUN_EXPORT PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat GLEW_FUN_EXPORT PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler; GLEW_FUN_EXPORT PFNGLSHADERBINARYPROC __glewShaderBinary; +GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC __glewDrawArraysInstancedBaseInstance; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC __glewDrawElementsInstancedBaseInstance; +GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC __glewDrawElementsInstancedBaseVertexBaseInstance; + +GLEW_FUN_EXPORT PFNGLGETIMAGEHANDLEARBPROC __glewGetImageHandleARB; +GLEW_FUN_EXPORT PFNGLGETTEXTUREHANDLEARBPROC __glewGetTextureHandleARB; +GLEW_FUN_EXPORT PFNGLGETTEXTURESAMPLERHANDLEARBPROC __glewGetTextureSamplerHandleARB; +GLEW_FUN_EXPORT PFNGLGETVERTEXATTRIBLUI64VARBPROC __glewGetVertexAttribLui64vARB; +GLEW_FUN_EXPORT PFNGLISIMAGEHANDLERESIDENTARBPROC __glewIsImageHandleResidentARB; +GLEW_FUN_EXPORT PFNGLISTEXTUREHANDLERESIDENTARBPROC __glewIsTextureHandleResidentARB; +GLEW_FUN_EXPORT PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC __glewMakeImageHandleNonResidentARB; +GLEW_FUN_EXPORT PFNGLMAKEIMAGEHANDLERESIDENTARBPROC __glewMakeImageHandleResidentARB; +GLEW_FUN_EXPORT PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC __glewMakeTextureHandleNonResidentARB; +GLEW_FUN_EXPORT PFNGLMAKETEXTUREHANDLERESIDENTARBPROC __glewMakeTextureHandleResidentARB; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC __glewProgramUniformHandleui64ARB; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC __glewProgramUniformHandleui64vARB; +GLEW_FUN_EXPORT PFNGLUNIFORMHANDLEUI64ARBPROC __glewUniformHandleui64ARB; +GLEW_FUN_EXPORT PFNGLUNIFORMHANDLEUI64VARBPROC __glewUniformHandleui64vARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64ARBPROC __glewVertexAttribL1ui64ARB; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL1UI64VARBPROC __glewVertexAttribL1ui64vARB; + GLEW_FUN_EXPORT PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed; GLEW_FUN_EXPORT PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex; +GLEW_FUN_EXPORT PFNGLBUFFERSTORAGEPROC __glewBufferStorage; +GLEW_FUN_EXPORT PFNGLNAMEDBUFFERSTORAGEEXTPROC __glewNamedBufferStorageEXT; + GLEW_FUN_EXPORT PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERDATAPROC __glewClearBufferData; +GLEW_FUN_EXPORT PFNGLCLEARBUFFERSUBDATAPROC __glewClearBufferSubData; +GLEW_FUN_EXPORT PFNGLCLEARNAMEDBUFFERDATAEXTPROC __glewClearNamedBufferDataEXT; +GLEW_FUN_EXPORT PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC __glewClearNamedBufferSubDataEXT; + +GLEW_FUN_EXPORT PFNGLCLEARTEXIMAGEPROC __glewClearTexImage; +GLEW_FUN_EXPORT PFNGLCLEARTEXSUBIMAGEPROC __glewClearTexSubImage; + GLEW_FUN_EXPORT PFNGLCLAMPCOLORARBPROC __glewClampColorARB; +GLEW_FUN_EXPORT PFNGLDISPATCHCOMPUTEPROC __glewDispatchCompute; +GLEW_FUN_EXPORT PFNGLDISPATCHCOMPUTEINDIRECTPROC __glewDispatchComputeIndirect; + +GLEW_FUN_EXPORT PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC __glewDispatchComputeGroupSizeARB; + GLEW_FUN_EXPORT PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData; +GLEW_FUN_EXPORT PFNGLCOPYIMAGESUBDATAPROC __glewCopyImageSubData; + GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB; GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB; GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB; @@ -13270,6 +15517,11 @@ GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBase GLEW_FUN_EXPORT PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect; GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect; +GLEW_FUN_EXPORT PFNGLFRAMEBUFFERPARAMETERIPROC __glewFramebufferParameteri; +GLEW_FUN_EXPORT PFNGLGETFRAMEBUFFERPARAMETERIVPROC __glewGetFramebufferParameteriv; +GLEW_FUN_EXPORT PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC __glewGetNamedFramebufferParameterivEXT; +GLEW_FUN_EXPORT PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC __glewNamedFramebufferParameteriEXT; + GLEW_FUN_EXPORT PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer; GLEW_FUN_EXPORT PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer; GLEW_FUN_EXPORT PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer; @@ -13301,23 +15553,6 @@ GLEW_FUN_EXPORT PFNGLPROGRAMBINARYPROC __glewProgramBinary; GLEW_FUN_EXPORT PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri; GLEW_FUN_EXPORT PFNGLGETUNIFORMDVPROC __glewGetUniformdv; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT; -GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT; GLEW_FUN_EXPORT PFNGLUNIFORM1DPROC __glewUniform1d; GLEW_FUN_EXPORT PFNGLUNIFORM1DVPROC __glewUniform1dv; GLEW_FUN_EXPORT PFNGLUNIFORM2DPROC __glewUniform2d; @@ -13369,10 +15604,24 @@ GLEW_FUN_EXPORT PFNGLRESETHISTOGRAMPROC __glewResetHistogram; GLEW_FUN_EXPORT PFNGLRESETMINMAXPROC __glewResetMinmax; GLEW_FUN_EXPORT PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D; +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC __glewMultiDrawArraysIndirectCountARB; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC __glewMultiDrawElementsIndirectCountARB; + GLEW_FUN_EXPORT PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB; GLEW_FUN_EXPORT PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB; GLEW_FUN_EXPORT PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB; +GLEW_FUN_EXPORT PFNGLGETINTERNALFORMATIVPROC __glewGetInternalformativ; + +GLEW_FUN_EXPORT PFNGLGETINTERNALFORMATI64VPROC __glewGetInternalformati64v; + +GLEW_FUN_EXPORT PFNGLINVALIDATEBUFFERDATAPROC __glewInvalidateBufferData; +GLEW_FUN_EXPORT PFNGLINVALIDATEBUFFERSUBDATAPROC __glewInvalidateBufferSubData; +GLEW_FUN_EXPORT PFNGLINVALIDATEFRAMEBUFFERPROC __glewInvalidateFramebuffer; +GLEW_FUN_EXPORT PFNGLINVALIDATESUBFRAMEBUFFERPROC __glewInvalidateSubFramebuffer; +GLEW_FUN_EXPORT PFNGLINVALIDATETEXIMAGEPROC __glewInvalidateTexImage; +GLEW_FUN_EXPORT PFNGLINVALIDATETEXSUBIMAGEPROC __glewInvalidateTexSubImage; + GLEW_FUN_EXPORT PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange; GLEW_FUN_EXPORT PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange; @@ -13382,6 +15631,16 @@ GLEW_FUN_EXPORT PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB; GLEW_FUN_EXPORT PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB; GLEW_FUN_EXPORT PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB; +GLEW_FUN_EXPORT PFNGLBINDBUFFERSBASEPROC __glewBindBuffersBase; +GLEW_FUN_EXPORT PFNGLBINDBUFFERSRANGEPROC __glewBindBuffersRange; +GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTURESPROC __glewBindImageTextures; +GLEW_FUN_EXPORT PFNGLBINDSAMPLERSPROC __glewBindSamplers; +GLEW_FUN_EXPORT PFNGLBINDTEXTURESPROC __glewBindTextures; +GLEW_FUN_EXPORT PFNGLBINDVERTEXBUFFERSPROC __glewBindVertexBuffers; + +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTPROC __glewMultiDrawArraysIndirect; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTPROC __glewMultiDrawElementsIndirect; + GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB; GLEW_FUN_EXPORT PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB; @@ -13431,8 +15690,16 @@ GLEW_FUN_EXPORT PFNGLISQUERYARBPROC __glewIsQueryARB; GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB; GLEW_FUN_EXPORT PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB; +GLEW_FUN_EXPORT PFNGLGETPROGRAMINTERFACEIVPROC __glewGetProgramInterfaceiv; +GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCEINDEXPROC __glewGetProgramResourceIndex; +GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCELOCATIONPROC __glewGetProgramResourceLocation; +GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC __glewGetProgramResourceLocationIndex; +GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCENAMEPROC __glewGetProgramResourceName; +GLEW_FUN_EXPORT PFNGLGETPROGRAMRESOURCEIVPROC __glewGetProgramResourceiv; + GLEW_FUN_EXPORT PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex; +GLEW_FUN_EXPORT PFNGLGETGRAPHICSRESETSTATUSARBPROC __glewGetGraphicsResetStatusARB; GLEW_FUN_EXPORT PFNGLGETNCOLORTABLEARBPROC __glewGetnColorTableARB; GLEW_FUN_EXPORT PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC __glewGetnCompressedTexImageARB; GLEW_FUN_EXPORT PFNGLGETNCONVOLUTIONFILTERARBPROC __glewGetnConvolutionFilterARB; @@ -13531,6 +15798,11 @@ GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC __glewProgramUniformMatrix4x3 GLEW_FUN_EXPORT PFNGLUSEPROGRAMSTAGESPROC __glewUseProgramStages; GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMPIPELINEPROC __glewValidateProgramPipeline; +GLEW_FUN_EXPORT PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC __glewGetActiveAtomicCounterBufferiv; + +GLEW_FUN_EXPORT PFNGLBINDIMAGETEXTUREPROC __glewBindImageTexture; +GLEW_FUN_EXPORT PFNGLMEMORYBARRIERPROC __glewMemoryBarrier; + GLEW_FUN_EXPORT PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB; GLEW_FUN_EXPORT PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB; GLEW_FUN_EXPORT PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB; @@ -13571,6 +15843,8 @@ GLEW_FUN_EXPORT PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB; GLEW_FUN_EXPORT PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB; GLEW_FUN_EXPORT PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB; +GLEW_FUN_EXPORT PFNGLSHADERSTORAGEBLOCKBINDINGPROC __glewShaderStorageBlockBinding; + GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName; GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName; GLEW_FUN_EXPORT PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv; @@ -13587,6 +15861,9 @@ GLEW_FUN_EXPORT PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB; GLEW_FUN_EXPORT PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB; GLEW_FUN_EXPORT PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB; +GLEW_FUN_EXPORT PFNGLTEXPAGECOMMITMENTARBPROC __glewTexPageCommitmentARB; +GLEW_FUN_EXPORT PFNGLTEXTUREPAGECOMMITMENTEXTPROC __glewTexturePageCommitmentEXT; + GLEW_FUN_EXPORT PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync; GLEW_FUN_EXPORT PFNGLDELETESYNCPROC __glewDeleteSync; GLEW_FUN_EXPORT PFNGLFENCESYNCPROC __glewFenceSync; @@ -13600,6 +15877,9 @@ GLEW_FUN_EXPORT PFNGLPATCHPARAMETERIPROC __glewPatchParameteri; GLEW_FUN_EXPORT PFNGLTEXBUFFERARBPROC __glewTexBufferARB; +GLEW_FUN_EXPORT PFNGLTEXBUFFERRANGEPROC __glewTexBufferRange; +GLEW_FUN_EXPORT PFNGLTEXTUREBUFFERRANGEEXTPROC __glewTextureBufferRangeEXT; + GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB; GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB; GLEW_FUN_EXPORT PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB; @@ -13613,6 +15893,20 @@ GLEW_FUN_EXPORT PFNGLSAMPLEMASKIPROC __glewSampleMaski; GLEW_FUN_EXPORT PFNGLTEXIMAGE2DMULTISAMPLEPROC __glewTexImage2DMultisample; GLEW_FUN_EXPORT PFNGLTEXIMAGE3DMULTISAMPLEPROC __glewTexImage3DMultisample; +GLEW_FUN_EXPORT PFNGLTEXSTORAGE1DPROC __glewTexStorage1D; +GLEW_FUN_EXPORT PFNGLTEXSTORAGE2DPROC __glewTexStorage2D; +GLEW_FUN_EXPORT PFNGLTEXSTORAGE3DPROC __glewTexStorage3D; +GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT; + +GLEW_FUN_EXPORT PFNGLTEXSTORAGE2DMULTISAMPLEPROC __glewTexStorage2DMultisample; +GLEW_FUN_EXPORT PFNGLTEXSTORAGE3DMULTISAMPLEPROC __glewTexStorage3DMultisample; +GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC __glewTextureStorage2DMultisampleEXT; +GLEW_FUN_EXPORT PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC __glewTextureStorage3DMultisampleEXT; + +GLEW_FUN_EXPORT PFNGLTEXTUREVIEWPROC __glewTextureView; + GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v; GLEW_FUN_EXPORT PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v; GLEW_FUN_EXPORT PFNGLQUERYCOUNTERPROC __glewQueryCounter; @@ -13630,6 +15924,9 @@ GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC __glewDrawTransformFeedback GLEW_FUN_EXPORT PFNGLENDQUERYINDEXEDPROC __glewEndQueryIndexed; GLEW_FUN_EXPORT PFNGLGETQUERYINDEXEDIVPROC __glewGetQueryIndexediv; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC __glewDrawTransformFeedbackInstanced; +GLEW_FUN_EXPORT PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC __glewDrawTransformFeedbackStreamInstanced; + GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB; GLEW_FUN_EXPORT PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB; GLEW_FUN_EXPORT PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB; @@ -13662,6 +15959,13 @@ GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d; GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv; GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer; +GLEW_FUN_EXPORT PFNGLBINDVERTEXBUFFERPROC __glewBindVertexBuffer; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBBINDINGPROC __glewVertexAttribBinding; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBFORMATPROC __glewVertexAttribFormat; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIFORMATPROC __glewVertexAttribIFormat; +GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLFORMATPROC __glewVertexAttribLFormat; +GLEW_FUN_EXPORT PFNGLVERTEXBINDINGDIVISORPROC __glewVertexBindingDivisor; + GLEW_FUN_EXPORT PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB; GLEW_FUN_EXPORT PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB; GLEW_FUN_EXPORT PFNGLWEIGHTBVARBPROC __glewWeightbvARB; @@ -13884,6 +16188,14 @@ GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI; GLEW_FUN_EXPORT PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI; GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI; GLEW_FUN_EXPORT PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1DATIPROC __glewVertexStream1dATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1DVATIPROC __glewVertexStream1dvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1FATIPROC __glewVertexStream1fATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1FVATIPROC __glewVertexStream1fvATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1IATIPROC __glewVertexStream1iATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1IVATIPROC __glewVertexStream1ivATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1SATIPROC __glewVertexStream1sATI; +GLEW_FUN_EXPORT PFNGLVERTEXSTREAM1SVATIPROC __glewVertexStream1svATI; GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI; GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI; GLEW_FUN_EXPORT PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI; @@ -13953,6 +16265,10 @@ GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT; GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT; GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT; +GLEW_FUN_EXPORT PFNGLINSERTEVENTMARKEREXTPROC __glewInsertEventMarkerEXT; +GLEW_FUN_EXPORT PFNGLPOPGROUPMARKEREXTPROC __glewPopGroupMarkerEXT; +GLEW_FUN_EXPORT PFNGLPUSHGROUPMARKEREXTPROC __glewPushGroupMarkerEXT; + GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT; GLEW_FUN_EXPORT PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT; @@ -14474,6 +16790,10 @@ GLEW_FUN_EXPORT PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointe GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM; GLEW_FUN_EXPORT PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM; +GLEW_FUN_EXPORT PFNGLMAPTEXTURE2DINTELPROC __glewMapTexture2DINTEL; +GLEW_FUN_EXPORT PFNGLSYNCTEXTUREINTELPROC __glewSyncTextureINTEL; +GLEW_FUN_EXPORT PFNGLUNMAPTEXTURE2DINTELPROC __glewUnmapTexture2DINTEL; + GLEW_FUN_EXPORT PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL; GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL; GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL; @@ -14482,11 +16802,22 @@ GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL; GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL; GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL; -GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT; -GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT; -GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT; -GLEW_FUN_EXPORT PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT; -GLEW_FUN_EXPORT PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECALLBACKPROC __glewDebugMessageCallback; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGECONTROLPROC __glewDebugMessageControl; +GLEW_FUN_EXPORT PFNGLDEBUGMESSAGEINSERTPROC __glewDebugMessageInsert; +GLEW_FUN_EXPORT PFNGLGETDEBUGMESSAGELOGPROC __glewGetDebugMessageLog; +GLEW_FUN_EXPORT PFNGLGETOBJECTLABELPROC __glewGetObjectLabel; +GLEW_FUN_EXPORT PFNGLGETOBJECTPTRLABELPROC __glewGetObjectPtrLabel; +GLEW_FUN_EXPORT PFNGLOBJECTLABELPROC __glewObjectLabel; +GLEW_FUN_EXPORT PFNGLOBJECTPTRLABELPROC __glewObjectPtrLabel; +GLEW_FUN_EXPORT PFNGLPOPDEBUGGROUPPROC __glewPopDebugGroup; +GLEW_FUN_EXPORT PFNGLPUSHDEBUGGROUPPROC __glewPushDebugGroup; + +GLEW_FUN_EXPORT PFNGLBUFFERREGIONENABLEDPROC __glewBufferRegionEnabled; +GLEW_FUN_EXPORT PFNGLDELETEBUFFERREGIONPROC __glewDeleteBufferRegion; +GLEW_FUN_EXPORT PFNGLDRAWBUFFERREGIONPROC __glewDrawBufferRegion; +GLEW_FUN_EXPORT PFNGLNEWBUFFERREGIONPROC __glewNewBufferRegion; +GLEW_FUN_EXPORT PFNGLREADBUFFERREGIONPROC __glewReadBufferRegion; GLEW_FUN_EXPORT PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA; @@ -14515,6 +16846,29 @@ GLEW_FUN_EXPORT PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA; GLEW_FUN_EXPORT PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA; GLEW_FUN_EXPORT PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA; +GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVXPROC __glewBeginConditionalRenderNVX; +GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVXPROC __glewEndConditionalRenderNVX; + +GLEW_FUN_EXPORT PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC __glewMultiDrawArraysIndirectBindlessNV; +GLEW_FUN_EXPORT PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC __glewMultiDrawElementsIndirectBindlessNV; + +GLEW_FUN_EXPORT PFNGLGETIMAGEHANDLENVPROC __glewGetImageHandleNV; +GLEW_FUN_EXPORT PFNGLGETTEXTUREHANDLENVPROC __glewGetTextureHandleNV; +GLEW_FUN_EXPORT PFNGLGETTEXTURESAMPLERHANDLENVPROC __glewGetTextureSamplerHandleNV; +GLEW_FUN_EXPORT PFNGLISIMAGEHANDLERESIDENTNVPROC __glewIsImageHandleResidentNV; +GLEW_FUN_EXPORT PFNGLISTEXTUREHANDLERESIDENTNVPROC __glewIsTextureHandleResidentNV; +GLEW_FUN_EXPORT PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC __glewMakeImageHandleNonResidentNV; +GLEW_FUN_EXPORT PFNGLMAKEIMAGEHANDLERESIDENTNVPROC __glewMakeImageHandleResidentNV; +GLEW_FUN_EXPORT PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC __glewMakeTextureHandleNonResidentNV; +GLEW_FUN_EXPORT PFNGLMAKETEXTUREHANDLERESIDENTNVPROC __glewMakeTextureHandleResidentNV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC __glewProgramUniformHandleui64NV; +GLEW_FUN_EXPORT PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC __glewProgramUniformHandleui64vNV; +GLEW_FUN_EXPORT PFNGLUNIFORMHANDLEUI64NVPROC __glewUniformHandleui64NV; +GLEW_FUN_EXPORT PFNGLUNIFORMHANDLEUI64VNVPROC __glewUniformHandleui64vNV; + +GLEW_FUN_EXPORT PFNGLBLENDBARRIERNVPROC __glewBlendBarrierNV; +GLEW_FUN_EXPORT PFNGLBLENDPARAMETERINVPROC __glewBlendParameteriNV; + GLEW_FUN_EXPORT PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV; GLEW_FUN_EXPORT PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV; @@ -14524,6 +16878,8 @@ GLEW_FUN_EXPORT PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV; GLEW_FUN_EXPORT PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV; GLEW_FUN_EXPORT PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV; +GLEW_FUN_EXPORT PFNGLDRAWTEXTURENVPROC __glewDrawTextureNV; + GLEW_FUN_EXPORT PFNGLEVALMAPSNVPROC __glewEvalMapsNV; GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV; GLEW_FUN_EXPORT PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV; @@ -14664,6 +17020,56 @@ GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParamet GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV; GLEW_FUN_EXPORT PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV; +GLEW_FUN_EXPORT PFNGLCOPYPATHNVPROC __glewCopyPathNV; +GLEW_FUN_EXPORT PFNGLCOVERFILLPATHINSTANCEDNVPROC __glewCoverFillPathInstancedNV; +GLEW_FUN_EXPORT PFNGLCOVERFILLPATHNVPROC __glewCoverFillPathNV; +GLEW_FUN_EXPORT PFNGLCOVERSTROKEPATHINSTANCEDNVPROC __glewCoverStrokePathInstancedNV; +GLEW_FUN_EXPORT PFNGLCOVERSTROKEPATHNVPROC __glewCoverStrokePathNV; +GLEW_FUN_EXPORT PFNGLDELETEPATHSNVPROC __glewDeletePathsNV; +GLEW_FUN_EXPORT PFNGLGENPATHSNVPROC __glewGenPathsNV; +GLEW_FUN_EXPORT PFNGLGETPATHCOLORGENFVNVPROC __glewGetPathColorGenfvNV; +GLEW_FUN_EXPORT PFNGLGETPATHCOLORGENIVNVPROC __glewGetPathColorGenivNV; +GLEW_FUN_EXPORT PFNGLGETPATHCOMMANDSNVPROC __glewGetPathCommandsNV; +GLEW_FUN_EXPORT PFNGLGETPATHCOORDSNVPROC __glewGetPathCoordsNV; +GLEW_FUN_EXPORT PFNGLGETPATHDASHARRAYNVPROC __glewGetPathDashArrayNV; +GLEW_FUN_EXPORT PFNGLGETPATHLENGTHNVPROC __glewGetPathLengthNV; +GLEW_FUN_EXPORT PFNGLGETPATHMETRICRANGENVPROC __glewGetPathMetricRangeNV; +GLEW_FUN_EXPORT PFNGLGETPATHMETRICSNVPROC __glewGetPathMetricsNV; +GLEW_FUN_EXPORT PFNGLGETPATHPARAMETERFVNVPROC __glewGetPathParameterfvNV; +GLEW_FUN_EXPORT PFNGLGETPATHPARAMETERIVNVPROC __glewGetPathParameterivNV; +GLEW_FUN_EXPORT PFNGLGETPATHSPACINGNVPROC __glewGetPathSpacingNV; +GLEW_FUN_EXPORT PFNGLGETPATHTEXGENFVNVPROC __glewGetPathTexGenfvNV; +GLEW_FUN_EXPORT PFNGLGETPATHTEXGENIVNVPROC __glewGetPathTexGenivNV; +GLEW_FUN_EXPORT PFNGLINTERPOLATEPATHSNVPROC __glewInterpolatePathsNV; +GLEW_FUN_EXPORT PFNGLISPATHNVPROC __glewIsPathNV; +GLEW_FUN_EXPORT PFNGLISPOINTINFILLPATHNVPROC __glewIsPointInFillPathNV; +GLEW_FUN_EXPORT PFNGLISPOINTINSTROKEPATHNVPROC __glewIsPointInStrokePathNV; +GLEW_FUN_EXPORT PFNGLPATHCOLORGENNVPROC __glewPathColorGenNV; +GLEW_FUN_EXPORT PFNGLPATHCOMMANDSNVPROC __glewPathCommandsNV; +GLEW_FUN_EXPORT PFNGLPATHCOORDSNVPROC __glewPathCoordsNV; +GLEW_FUN_EXPORT PFNGLPATHCOVERDEPTHFUNCNVPROC __glewPathCoverDepthFuncNV; +GLEW_FUN_EXPORT PFNGLPATHDASHARRAYNVPROC __glewPathDashArrayNV; +GLEW_FUN_EXPORT PFNGLPATHFOGGENNVPROC __glewPathFogGenNV; +GLEW_FUN_EXPORT PFNGLPATHGLYPHRANGENVPROC __glewPathGlyphRangeNV; +GLEW_FUN_EXPORT PFNGLPATHGLYPHSNVPROC __glewPathGlyphsNV; +GLEW_FUN_EXPORT PFNGLPATHPARAMETERFNVPROC __glewPathParameterfNV; +GLEW_FUN_EXPORT PFNGLPATHPARAMETERFVNVPROC __glewPathParameterfvNV; +GLEW_FUN_EXPORT PFNGLPATHPARAMETERINVPROC __glewPathParameteriNV; +GLEW_FUN_EXPORT PFNGLPATHPARAMETERIVNVPROC __glewPathParameterivNV; +GLEW_FUN_EXPORT PFNGLPATHSTENCILDEPTHOFFSETNVPROC __glewPathStencilDepthOffsetNV; +GLEW_FUN_EXPORT PFNGLPATHSTENCILFUNCNVPROC __glewPathStencilFuncNV; +GLEW_FUN_EXPORT PFNGLPATHSTRINGNVPROC __glewPathStringNV; +GLEW_FUN_EXPORT PFNGLPATHSUBCOMMANDSNVPROC __glewPathSubCommandsNV; +GLEW_FUN_EXPORT PFNGLPATHSUBCOORDSNVPROC __glewPathSubCoordsNV; +GLEW_FUN_EXPORT PFNGLPATHTEXGENNVPROC __glewPathTexGenNV; +GLEW_FUN_EXPORT PFNGLPOINTALONGPATHNVPROC __glewPointAlongPathNV; +GLEW_FUN_EXPORT PFNGLSTENCILFILLPATHINSTANCEDNVPROC __glewStencilFillPathInstancedNV; +GLEW_FUN_EXPORT PFNGLSTENCILFILLPATHNVPROC __glewStencilFillPathNV; +GLEW_FUN_EXPORT PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC __glewStencilStrokePathInstancedNV; +GLEW_FUN_EXPORT PFNGLSTENCILSTROKEPATHNVPROC __glewStencilStrokePathNV; +GLEW_FUN_EXPORT PFNGLTRANSFORMPATHNVPROC __glewTransformPathNV; +GLEW_FUN_EXPORT PFNGLWEIGHTPATHSNVPROC __glewWeightPathsNV; + GLEW_FUN_EXPORT PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV; GLEW_FUN_EXPORT PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV; @@ -14872,6 +17278,59 @@ GLEW_FUN_EXPORT PFNGLFRUSTUMFOESPROC __glewFrustumfOES; GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES; GLEW_FUN_EXPORT PFNGLORTHOFOESPROC __glewOrthofOES; +GLEW_FUN_EXPORT PFNGLALPHAFUNCXPROC __glewAlphaFuncx; +GLEW_FUN_EXPORT PFNGLCLEARCOLORXPROC __glewClearColorx; +GLEW_FUN_EXPORT PFNGLCLEARDEPTHXPROC __glewClearDepthx; +GLEW_FUN_EXPORT PFNGLCOLOR4XPROC __glewColor4x; +GLEW_FUN_EXPORT PFNGLDEPTHRANGEXPROC __glewDepthRangex; +GLEW_FUN_EXPORT PFNGLFOGXPROC __glewFogx; +GLEW_FUN_EXPORT PFNGLFOGXVPROC __glewFogxv; +GLEW_FUN_EXPORT PFNGLFRUSTUMFPROC __glewFrustumf; +GLEW_FUN_EXPORT PFNGLFRUSTUMXPROC __glewFrustumx; +GLEW_FUN_EXPORT PFNGLLIGHTMODELXPROC __glewLightModelx; +GLEW_FUN_EXPORT PFNGLLIGHTMODELXVPROC __glewLightModelxv; +GLEW_FUN_EXPORT PFNGLLIGHTXPROC __glewLightx; +GLEW_FUN_EXPORT PFNGLLIGHTXVPROC __glewLightxv; +GLEW_FUN_EXPORT PFNGLLINEWIDTHXPROC __glewLineWidthx; +GLEW_FUN_EXPORT PFNGLLOADMATRIXXPROC __glewLoadMatrixx; +GLEW_FUN_EXPORT PFNGLMATERIALXPROC __glewMaterialx; +GLEW_FUN_EXPORT PFNGLMATERIALXVPROC __glewMaterialxv; +GLEW_FUN_EXPORT PFNGLMULTMATRIXXPROC __glewMultMatrixx; +GLEW_FUN_EXPORT PFNGLMULTITEXCOORD4XPROC __glewMultiTexCoord4x; +GLEW_FUN_EXPORT PFNGLNORMAL3XPROC __glewNormal3x; +GLEW_FUN_EXPORT PFNGLORTHOFPROC __glewOrthof; +GLEW_FUN_EXPORT PFNGLORTHOXPROC __glewOrthox; +GLEW_FUN_EXPORT PFNGLPOINTSIZEXPROC __glewPointSizex; +GLEW_FUN_EXPORT PFNGLPOLYGONOFFSETXPROC __glewPolygonOffsetx; +GLEW_FUN_EXPORT PFNGLROTATEXPROC __glewRotatex; +GLEW_FUN_EXPORT PFNGLSAMPLECOVERAGEXPROC __glewSampleCoveragex; +GLEW_FUN_EXPORT PFNGLSCALEXPROC __glewScalex; +GLEW_FUN_EXPORT PFNGLTEXENVXPROC __glewTexEnvx; +GLEW_FUN_EXPORT PFNGLTEXENVXVPROC __glewTexEnvxv; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERXPROC __glewTexParameterx; +GLEW_FUN_EXPORT PFNGLTRANSLATEXPROC __glewTranslatex; + +GLEW_FUN_EXPORT PFNGLCLIPPLANEFPROC __glewClipPlanef; +GLEW_FUN_EXPORT PFNGLCLIPPLANEXPROC __glewClipPlanex; +GLEW_FUN_EXPORT PFNGLGETCLIPPLANEFPROC __glewGetClipPlanef; +GLEW_FUN_EXPORT PFNGLGETCLIPPLANEXPROC __glewGetClipPlanex; +GLEW_FUN_EXPORT PFNGLGETFIXEDVPROC __glewGetFixedv; +GLEW_FUN_EXPORT PFNGLGETLIGHTXVPROC __glewGetLightxv; +GLEW_FUN_EXPORT PFNGLGETMATERIALXVPROC __glewGetMaterialxv; +GLEW_FUN_EXPORT PFNGLGETTEXENVXVPROC __glewGetTexEnvxv; +GLEW_FUN_EXPORT PFNGLGETTEXPARAMETERXVPROC __glewGetTexParameterxv; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERXPROC __glewPointParameterx; +GLEW_FUN_EXPORT PFNGLPOINTPARAMETERXVPROC __glewPointParameterxv; +GLEW_FUN_EXPORT PFNGLPOINTSIZEPOINTEROESPROC __glewPointSizePointerOES; +GLEW_FUN_EXPORT PFNGLTEXPARAMETERXVPROC __glewTexParameterxv; + +GLEW_FUN_EXPORT PFNGLERRORSTRINGREGALPROC __glewErrorStringREGAL; + +GLEW_FUN_EXPORT PFNGLGETEXTENSIONREGALPROC __glewGetExtensionREGAL; +GLEW_FUN_EXPORT PFNGLISSUPPORTEDREGALPROC __glewIsSupportedREGAL; + +GLEW_FUN_EXPORT PFNGLLOGMESSAGECALLBACKREGALPROC __glewLogMessageCallbackREGAL; + GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS; GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS; @@ -15023,6 +17482,9 @@ GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_2; GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_3_3; GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_0; GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_1; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_2; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_3; +GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_4_4; GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_multisample; GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_tbuffer; GLEW_VAR_EXPORT GLboolean __GLEW_3DFX_texture_compression_FXT1; @@ -15031,14 +17493,35 @@ GLEW_VAR_EXPORT GLboolean __GLEW_AMD_conservative_depth; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_debug_output; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_depth_clamp_separate; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_draw_buffers_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_interleaved_elements; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_multi_draw_indirect; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_name_gen_delete; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_performance_monitor; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_pinned_memory; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_query_buffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sample_positions; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_seamless_cubemap_per_texture; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_stencil_export; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_trinary_minmax; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sparse_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_stencil_operation_extended; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_texture_texture4; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_transform_feedback3_lines_triangles; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_layer; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_tessellator; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_viewport_index; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_depth_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_framebuffer_blit; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_framebuffer_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_instanced_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_pack_reverse_row_order; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_program_binary; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_compression_dxt1; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_compression_dxt3; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_compression_dxt5; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_texture_usage; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_timer_query; +GLEW_VAR_EXPORT GLboolean __GLEW_ANGLE_translated_shader_source; GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_aux_depth_stencil; GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_client_storage; GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_element_array; @@ -15057,11 +17540,23 @@ GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_array_range; GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_vertex_program_evaluators; GLEW_VAR_EXPORT GLboolean __GLEW_APPLE_ycbcr_422; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES2_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_ES3_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_arrays_of_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_base_instance; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_bindless_texture; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_blend_func_extended; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_buffer_storage; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_cl_event; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_clear_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_clear_texture; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_color_buffer_float; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compressed_texture_pixel_storage; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compute_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_compute_variable_group_size; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_conservative_depth; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_buffer; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_copy_image; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_debug_output; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_buffer_float; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_depth_clamp; @@ -15071,11 +17566,15 @@ GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_buffers_blend; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_elements_base_vertex; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_indirect; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_draw_instanced; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_enhanced_layouts; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_attrib_location; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_explicit_uniform_location; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_coord_conventions; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_layer_viewport; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_program_shadow; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_fragment_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_no_attachments; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_framebuffer_sRGB; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_geometry_shader4; @@ -15085,9 +17584,16 @@ GLEW_VAR_EXPORT GLboolean __GLEW_ARB_gpu_shader_fp64; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_pixel; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_half_float_vertex; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_imaging; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_indirect_parameters; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_instanced_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_internalformat_query; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_internalformat_query2; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_invalidate_subdata; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_alignment; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_map_buffer_range; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_matrix_palette; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multi_bind; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multi_draw_indirect; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multisample; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_multitexture; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query; @@ -15095,27 +17601,44 @@ GLEW_VAR_EXPORT GLboolean __GLEW_ARB_occlusion_query2; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_pixel_buffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_parameters; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_point_sprite; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_program_interface_query; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_provoking_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_query_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robust_buffer_access_behavior; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness_application_isolation; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_robustness_share_group_isolation; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sample_shading; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sampler_objects; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_seamless_cube_map; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_seamless_cubemap_per_texture; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_separate_shader_objects; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_atomic_counters; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_bit_encoding; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_draw_parameters; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_group_vote; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_image_load_store; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_image_size; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_objects; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_precision; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_stencil_export; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_storage_buffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_subroutine; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shader_texture_lod; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_100; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_420pack; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_include; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shading_language_packing; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_shadow_ambient; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sparse_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_stencil_texturing; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_sync; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_tessellation_shader; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_border_clamp; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_object_rgb32; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_buffer_range; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_bptc; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_compression_rgtc; @@ -15127,26 +17650,35 @@ GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_crossbar; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_env_dot3; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_float; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_gather; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirror_clamp_to_edge; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_mirrored_repeat; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_multisample; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_non_power_of_two; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_levels; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_query_lod; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rectangle; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rg; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_rgb10_a2ui; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_stencil8; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_storage; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_storage_multisample; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_swizzle; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_texture_view; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_timer_query; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback2; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback3; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transform_feedback_instanced; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_transpose_matrix; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_uniform_buffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_bgra; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_array_object; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_64bit; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_attrib_binding; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_blend; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_buffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_program; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_type_10f_11f_11f_rev; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_viewport_array; GLEW_VAR_EXPORT GLboolean __GLEW_ARB_window_pos; @@ -15190,6 +17722,7 @@ GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_debug_marker; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_direct_state_access; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_draw_buffers2; @@ -15199,6 +17732,7 @@ GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fog_coord; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_fragment_lighting; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_blit; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_multisample_blit_scaled; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_framebuffer_sRGB; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_geometry_shader4; @@ -15283,22 +17817,33 @@ GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat; GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists; GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp; GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_map_texture; GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays; GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor; +GLEW_VAR_EXPORT GLboolean __GLEW_KHR_debug; +GLEW_VAR_EXPORT GLboolean __GLEW_KHR_texture_compression_astc_ldr; GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region; GLEW_VAR_EXPORT GLboolean __GLEW_MESAX_texture_stack; GLEW_VAR_EXPORT GLboolean __GLEW_MESA_pack_invert; GLEW_VAR_EXPORT GLboolean __GLEW_MESA_resize_buffers; GLEW_VAR_EXPORT GLboolean __GLEW_MESA_window_pos; GLEW_VAR_EXPORT GLboolean __GLEW_MESA_ycbcr_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_NVX_conditional_render; GLEW_VAR_EXPORT GLboolean __GLEW_NVX_gpu_memory_info; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_bindless_multi_draw_indirect; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_bindless_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_equation_advanced; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_equation_advanced_coherent; GLEW_VAR_EXPORT GLboolean __GLEW_NV_blend_square; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_compute_program5; GLEW_VAR_EXPORT GLboolean __GLEW_NV_conditional_render; GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_depth_to_color; GLEW_VAR_EXPORT GLboolean __GLEW_NV_copy_image; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_deep_texture3D; GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_buffer_float; GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_clamp; GLEW_VAR_EXPORT GLboolean __GLEW_NV_depth_range_unclamped; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_draw_texture; GLEW_VAR_EXPORT GLboolean __GLEW_NV_evaluators; GLEW_VAR_EXPORT GLboolean __GLEW_NV_explicit_multisample; GLEW_VAR_EXPORT GLboolean __GLEW_NV_fence; @@ -15313,6 +17858,7 @@ GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_program4; GLEW_VAR_EXPORT GLboolean __GLEW_NV_geometry_shader4; GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program4; GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program5; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program5_mem_extended; GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_program_fp64; GLEW_VAR_EXPORT GLboolean __GLEW_NV_gpu_shader5; GLEW_VAR_EXPORT GLboolean __GLEW_NV_half_float; @@ -15323,13 +17869,17 @@ GLEW_VAR_EXPORT GLboolean __GLEW_NV_occlusion_query; GLEW_VAR_EXPORT GLboolean __GLEW_NV_packed_depth_stencil; GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_NV_parameter_buffer_object2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_path_rendering; GLEW_VAR_EXPORT GLboolean __GLEW_NV_pixel_data_range; GLEW_VAR_EXPORT GLboolean __GLEW_NV_point_sprite; GLEW_VAR_EXPORT GLboolean __GLEW_NV_present_video; GLEW_VAR_EXPORT GLboolean __GLEW_NV_primitive_restart; GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners; GLEW_VAR_EXPORT GLboolean __GLEW_NV_register_combiners2; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_atomic_counters; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_atomic_float; GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_buffer_load; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_storage_buffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_NV_tessellation_program5; GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss; GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection; @@ -15365,6 +17915,12 @@ GLEW_VAR_EXPORT GLboolean __GLEW_OML_resample; GLEW_VAR_EXPORT GLboolean __GLEW_OML_subsample; GLEW_VAR_EXPORT GLboolean __GLEW_PGI_misc_hints; GLEW_VAR_EXPORT GLboolean __GLEW_PGI_vertex_hints; +GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_ES1_0_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_ES1_1_compatibility; +GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_enable; +GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_error_string; +GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_extension_query; +GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_log; GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates; GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc; GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range; @@ -15451,8 +18007,8 @@ GLEW_VAR_EXPORT GLboolean __GLEW_WIN_swap_hint; #ifdef GLEW_MX typedef struct GLEWContextStruct GLEWContext; -GLEWAPI GLenum glewContextInit (GLEWContext* ctx); -GLEWAPI GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name); +GLEWAPI GLenum GLEWAPIENTRY glewContextInit (GLEWContext *ctx); +GLEWAPI GLboolean GLEWAPIENTRY glewContextIsSupported (const GLEWContext *ctx, const char *name); #define glewInit() glewContextInit(glewGetContext()) #define glewIsSupported(x) glewContextIsSupported(glewGetContext(), x) @@ -15467,8 +18023,8 @@ GLEWAPI GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* na #else /* GLEW_MX */ -GLEWAPI GLenum glewInit (); -GLEWAPI GLboolean glewIsSupported (const char* name); +GLEWAPI GLenum GLEWAPIENTRY glewInit (void); +GLEWAPI GLboolean GLEWAPIENTRY glewIsSupported (const char *name); #define glewIsExtensionSupported(x) glewIsSupported(x) #define GLEW_GET_VAR(x) (*(const GLboolean*)&x) @@ -15477,9 +18033,9 @@ GLEWAPI GLboolean glewIsSupported (const char* name); #endif /* GLEW_MX */ GLEWAPI GLboolean glewExperimental; -GLEWAPI GLboolean glewGetExtension (const char* name); -GLEWAPI const GLubyte* glewGetErrorString (GLenum error); -GLEWAPI const GLubyte* glewGetString (GLenum name); +GLEWAPI GLboolean GLEWAPIENTRY glewGetExtension (const char *name); +GLEWAPI const GLubyte * GLEWAPIENTRY glewGetErrorString (GLenum error); +GLEWAPI const GLubyte * GLEWAPIENTRY glewGetString (GLenum name); #ifdef __cplusplus } diff --git a/ext/glew/GL/glxew.h b/ext/glew/GL/glxew.h index 2995318f69..76a5f0d82a 100644 --- a/ext/glew/GL/glxew.h +++ b/ext/glew/GL/glxew.h @@ -362,6 +362,26 @@ extern void ( * glXGetProcAddress (const GLubyte *procName)) (void); #define GLX_GPU_NUM_RB_AMD 0x21A7 #define GLX_GPU_NUM_SPI_AMD 0x21A8 +typedef void ( * PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC) (GLXContext dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef GLXContext ( * PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC) (unsigned int id, GLXContext share_list); +typedef GLXContext ( * PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (unsigned int id, GLXContext share_context, const int* attribList); +typedef Bool ( * PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC) (GLXContext ctx); +typedef unsigned int ( * PFNGLXGETCONTEXTGPUIDAMDPROC) (GLXContext ctx); +typedef GLXContext ( * PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void); +typedef unsigned int ( * PFNGLXGETGPUIDSAMDPROC) (unsigned int maxCount, unsigned int* ids); +typedef int ( * PFNGLXGETGPUINFOAMDPROC) (unsigned int id, int property, GLenum dataType, unsigned int size, void* data); +typedef Bool ( * PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (GLXContext ctx); + +#define glXBlitContextFramebufferAMD GLXEW_GET_FUN(__glewXBlitContextFramebufferAMD) +#define glXCreateAssociatedContextAMD GLXEW_GET_FUN(__glewXCreateAssociatedContextAMD) +#define glXCreateAssociatedContextAttribsAMD GLXEW_GET_FUN(__glewXCreateAssociatedContextAttribsAMD) +#define glXDeleteAssociatedContextAMD GLXEW_GET_FUN(__glewXDeleteAssociatedContextAMD) +#define glXGetContextGPUIDAMD GLXEW_GET_FUN(__glewXGetContextGPUIDAMD) +#define glXGetCurrentAssociatedContextAMD GLXEW_GET_FUN(__glewXGetCurrentAssociatedContextAMD) +#define glXGetGPUIDsAMD GLXEW_GET_FUN(__glewXGetGPUIDsAMD) +#define glXGetGPUInfoAMD GLXEW_GET_FUN(__glewXGetGPUInfoAMD) +#define glXMakeAssociatedContextCurrentAMD GLXEW_GET_FUN(__glewXMakeAssociatedContextCurrentAMD) + #define GLXEW_AMD_gpu_association GLXEW_GET_VAR(__GLXEW_AMD_gpu_association) #endif /* GLX_AMD_gpu_association */ @@ -458,6 +478,28 @@ extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void); #endif /* GLX_ARB_multisample */ +/* ---------------- GLX_ARB_robustness_application_isolation --------------- */ + +#ifndef GLX_ARB_robustness_application_isolation +#define GLX_ARB_robustness_application_isolation 1 + +#define GLX_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008 + +#define GLXEW_ARB_robustness_application_isolation GLXEW_GET_VAR(__GLXEW_ARB_robustness_application_isolation) + +#endif /* GLX_ARB_robustness_application_isolation */ + +/* ---------------- GLX_ARB_robustness_share_group_isolation --------------- */ + +#ifndef GLX_ARB_robustness_share_group_isolation +#define GLX_ARB_robustness_share_group_isolation 1 + +#define GLX_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008 + +#define GLXEW_ARB_robustness_share_group_isolation GLXEW_GET_VAR(__GLXEW_ARB_robustness_share_group_isolation) + +#endif /* GLX_ARB_robustness_share_group_isolation */ + /* ---------------------- GLX_ARB_vertex_buffer_object --------------------- */ #ifndef GLX_ARB_vertex_buffer_object @@ -533,6 +575,17 @@ typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, i #endif /* GLX_ATI_render_texture */ +/* --------------------------- GLX_EXT_buffer_age -------------------------- */ + +#ifndef GLX_EXT_buffer_age +#define GLX_EXT_buffer_age 1 + +#define GLX_BACK_BUFFER_AGE_EXT 0x20F4 + +#define GLXEW_EXT_buffer_age GLXEW_GET_VAR(__GLXEW_EXT_buffer_age) + +#endif /* GLX_EXT_buffer_age */ + /* ------------------- GLX_EXT_create_context_es2_profile ------------------ */ #ifndef GLX_EXT_create_context_es2_profile @@ -544,6 +597,17 @@ typedef void ( * PFNGLXRELEASETEXIMAGEATIPROC) (Display *dpy, GLXPbuffer pbuf, i #endif /* GLX_EXT_create_context_es2_profile */ +/* ------------------- GLX_EXT_create_context_es_profile ------------------- */ + +#ifndef GLX_EXT_create_context_es_profile +#define GLX_EXT_create_context_es_profile 1 + +#define GLX_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004 + +#define GLXEW_EXT_create_context_es_profile GLXEW_GET_VAR(__GLXEW_EXT_create_context_es_profile) + +#endif /* GLX_EXT_create_context_es_profile */ + /* --------------------- GLX_EXT_fbconfig_packed_float --------------------- */ #ifndef GLX_EXT_fbconfig_packed_float @@ -617,6 +681,17 @@ typedef void ( * PFNGLXSWAPINTERVALEXTPROC) (Display* dpy, GLXDrawable drawable, #endif /* GLX_EXT_swap_control */ +/* ----------------------- GLX_EXT_swap_control_tear ----------------------- */ + +#ifndef GLX_EXT_swap_control_tear +#define GLX_EXT_swap_control_tear 1 + +#define GLX_LATE_SWAPS_TEAR_EXT 0x20F3 + +#define GLXEW_EXT_swap_control_tear GLXEW_GET_VAR(__GLXEW_EXT_swap_control_tear) + +#endif /* GLX_EXT_swap_control_tear */ + /* ---------------------- GLX_EXT_texture_from_pixmap ---------------------- */ #ifndef GLX_EXT_texture_from_pixmap @@ -785,6 +860,21 @@ typedef GLboolean ( * PFNGLXSET3DFXMODEMESAPROC) (GLint mode); #endif /* GLX_MESA_set_3dfx_mode */ +/* ------------------------- GLX_MESA_swap_control ------------------------- */ + +#ifndef GLX_MESA_swap_control +#define GLX_MESA_swap_control 1 + +typedef int ( * PFNGLXGETSWAPINTERVALMESAPROC) (void); +typedef int ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned int interval); + +#define glXGetSwapIntervalMESA GLXEW_GET_FUN(__glewXGetSwapIntervalMESA) +#define glXSwapIntervalMESA GLXEW_GET_FUN(__glewXSwapIntervalMESA) + +#define GLXEW_MESA_swap_control GLXEW_GET_VAR(__GLXEW_MESA_swap_control) + +#endif /* GLX_MESA_swap_control */ + /* --------------------------- GLX_NV_copy_image --------------------------- */ #ifndef GLX_NV_copy_image @@ -988,16 +1078,6 @@ typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, i #ifndef GLX_SGIS_color_range #define GLX_SGIS_color_range 1 -#define GLX_MIN_RED_SGIS 0 -#define GLX_MAX_GREEN_SGIS 0 -#define GLX_MIN_BLUE_SGIS 0 -#define GLX_MAX_ALPHA_SGIS 0 -#define GLX_MIN_GREEN_SGIS 0 -#define GLX_MIN_ALPHA_SGIS 0 -#define GLX_MAX_RED_SGIS 0 -#define GLX_EXTENDED_RANGE_SGIS 0 -#define GLX_MAX_BLUE_SGIS 0 - #define GLXEW_SGIS_color_range GLXEW_GET_VAR(__GLXEW_SGIS_color_range) #endif /* GLX_SGIS_color_range */ @@ -1334,203 +1414,224 @@ typedef int ( * PFNGLXVIDEORESIZESUNPROC) (Display* display, GLXDrawable window, /* ------------------------------------------------------------------------- */ #ifdef GLEW_MX -#define GLXEW_EXPORT +#define GLXEW_FUN_EXPORT GLEW_FUN_EXPORT +#define GLXEW_VAR_EXPORT #else -#define GLXEW_EXPORT extern +#define GLXEW_FUN_EXPORT GLEW_FUN_EXPORT +#define GLXEW_VAR_EXPORT GLEW_VAR_EXPORT #endif /* GLEW_MX */ -extern PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay; +GLXEW_FUN_EXPORT PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay; -extern PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig; -extern PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext; -extern PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer; -extern PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap; -extern PFNGLXCREATEWINDOWPROC __glewXCreateWindow; -extern PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer; -extern PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap; -extern PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow; -extern PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable; -extern PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib; -extern PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs; -extern PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent; -extern PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig; -extern PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent; -extern PFNGLXQUERYCONTEXTPROC __glewXQueryContext; -extern PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable; -extern PFNGLXSELECTEVENTPROC __glewXSelectEvent; +GLXEW_FUN_EXPORT PFNGLXCHOOSEFBCONFIGPROC __glewXChooseFBConfig; +GLXEW_FUN_EXPORT PFNGLXCREATENEWCONTEXTPROC __glewXCreateNewContext; +GLXEW_FUN_EXPORT PFNGLXCREATEPBUFFERPROC __glewXCreatePbuffer; +GLXEW_FUN_EXPORT PFNGLXCREATEPIXMAPPROC __glewXCreatePixmap; +GLXEW_FUN_EXPORT PFNGLXCREATEWINDOWPROC __glewXCreateWindow; +GLXEW_FUN_EXPORT PFNGLXDESTROYPBUFFERPROC __glewXDestroyPbuffer; +GLXEW_FUN_EXPORT PFNGLXDESTROYPIXMAPPROC __glewXDestroyPixmap; +GLXEW_FUN_EXPORT PFNGLXDESTROYWINDOWPROC __glewXDestroyWindow; +GLXEW_FUN_EXPORT PFNGLXGETCURRENTREADDRAWABLEPROC __glewXGetCurrentReadDrawable; +GLXEW_FUN_EXPORT PFNGLXGETFBCONFIGATTRIBPROC __glewXGetFBConfigAttrib; +GLXEW_FUN_EXPORT PFNGLXGETFBCONFIGSPROC __glewXGetFBConfigs; +GLXEW_FUN_EXPORT PFNGLXGETSELECTEDEVENTPROC __glewXGetSelectedEvent; +GLXEW_FUN_EXPORT PFNGLXGETVISUALFROMFBCONFIGPROC __glewXGetVisualFromFBConfig; +GLXEW_FUN_EXPORT PFNGLXMAKECONTEXTCURRENTPROC __glewXMakeContextCurrent; +GLXEW_FUN_EXPORT PFNGLXQUERYCONTEXTPROC __glewXQueryContext; +GLXEW_FUN_EXPORT PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable; +GLXEW_FUN_EXPORT PFNGLXSELECTEVENTPROC __glewXSelectEvent; -extern PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB; +GLXEW_FUN_EXPORT PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC __glewXBlitContextFramebufferAMD; +GLXEW_FUN_EXPORT PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC __glewXCreateAssociatedContextAMD; +GLXEW_FUN_EXPORT PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __glewXCreateAssociatedContextAttribsAMD; +GLXEW_FUN_EXPORT PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC __glewXDeleteAssociatedContextAMD; +GLXEW_FUN_EXPORT PFNGLXGETCONTEXTGPUIDAMDPROC __glewXGetContextGPUIDAMD; +GLXEW_FUN_EXPORT PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC __glewXGetCurrentAssociatedContextAMD; +GLXEW_FUN_EXPORT PFNGLXGETGPUIDSAMDPROC __glewXGetGPUIDsAMD; +GLXEW_FUN_EXPORT PFNGLXGETGPUINFOAMDPROC __glewXGetGPUInfoAMD; +GLXEW_FUN_EXPORT PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __glewXMakeAssociatedContextCurrentAMD; -extern PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI; -extern PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI; -extern PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI; +GLXEW_FUN_EXPORT PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB; -extern PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT; -extern PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT; -extern PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT; -extern PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT; +GLXEW_FUN_EXPORT PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI; +GLXEW_FUN_EXPORT PFNGLXDRAWABLEATTRIBATIPROC __glewXDrawableAttribATI; +GLXEW_FUN_EXPORT PFNGLXRELEASETEXIMAGEATIPROC __glewXReleaseTexImageATI; -extern PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT; +GLXEW_FUN_EXPORT PFNGLXFREECONTEXTEXTPROC __glewXFreeContextEXT; +GLXEW_FUN_EXPORT PFNGLXGETCONTEXTIDEXTPROC __glewXGetContextIDEXT; +GLXEW_FUN_EXPORT PFNGLXIMPORTCONTEXTEXTPROC __glewXImportContextEXT; +GLXEW_FUN_EXPORT PFNGLXQUERYCONTEXTINFOEXTPROC __glewXQueryContextInfoEXT; -extern PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT; -extern PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT; +GLXEW_FUN_EXPORT PFNGLXSWAPINTERVALEXTPROC __glewXSwapIntervalEXT; -extern PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA; +GLXEW_FUN_EXPORT PFNGLXBINDTEXIMAGEEXTPROC __glewXBindTexImageEXT; +GLXEW_FUN_EXPORT PFNGLXRELEASETEXIMAGEEXTPROC __glewXReleaseTexImageEXT; -extern PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA; +GLXEW_FUN_EXPORT PFNGLXGETAGPOFFSETMESAPROC __glewXGetAGPOffsetMESA; -extern PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA; +GLXEW_FUN_EXPORT PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA; -extern PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA; +GLXEW_FUN_EXPORT PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA; -extern PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA; +GLXEW_FUN_EXPORT PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA; -extern PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV; +GLXEW_FUN_EXPORT PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA; -extern PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV; -extern PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV; +GLXEW_FUN_EXPORT PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA; +GLXEW_FUN_EXPORT PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA; -extern PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV; -extern PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV; -extern PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV; -extern PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV; -extern PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV; -extern PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV; +GLXEW_FUN_EXPORT PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV; -extern PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV; -extern PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV; +GLXEW_FUN_EXPORT PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV; +GLXEW_FUN_EXPORT PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV; -extern PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV; -extern PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV; -extern PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV; -extern PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV; -extern PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV; +GLXEW_FUN_EXPORT PFNGLXBINDSWAPBARRIERNVPROC __glewXBindSwapBarrierNV; +GLXEW_FUN_EXPORT PFNGLXJOINSWAPGROUPNVPROC __glewXJoinSwapGroupNV; +GLXEW_FUN_EXPORT PFNGLXQUERYFRAMECOUNTNVPROC __glewXQueryFrameCountNV; +GLXEW_FUN_EXPORT PFNGLXQUERYMAXSWAPGROUPSNVPROC __glewXQueryMaxSwapGroupsNV; +GLXEW_FUN_EXPORT PFNGLXQUERYSWAPGROUPNVPROC __glewXQuerySwapGroupNV; +GLXEW_FUN_EXPORT PFNGLXRESETFRAMECOUNTNVPROC __glewXResetFrameCountNV; -extern PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV; -extern PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV; -extern PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV; -extern PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV; -extern PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV; -extern PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV; +GLXEW_FUN_EXPORT PFNGLXALLOCATEMEMORYNVPROC __glewXAllocateMemoryNV; +GLXEW_FUN_EXPORT PFNGLXFREEMEMORYNVPROC __glewXFreeMemoryNV; -extern PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML; -extern PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML; -extern PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML; -extern PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML; -extern PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML; +GLXEW_FUN_EXPORT PFNGLXBINDVIDEOCAPTUREDEVICENVPROC __glewXBindVideoCaptureDeviceNV; +GLXEW_FUN_EXPORT PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC __glewXEnumerateVideoCaptureDevicesNV; +GLXEW_FUN_EXPORT PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC __glewXLockVideoCaptureDeviceNV; +GLXEW_FUN_EXPORT PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC __glewXQueryVideoCaptureDeviceNV; +GLXEW_FUN_EXPORT PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC __glewXReleaseVideoCaptureDeviceNV; -extern PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX; -extern PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX; -extern PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX; -extern PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX; -extern PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX; -extern PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX; +GLXEW_FUN_EXPORT PFNGLXBINDVIDEOIMAGENVPROC __glewXBindVideoImageNV; +GLXEW_FUN_EXPORT PFNGLXGETVIDEODEVICENVPROC __glewXGetVideoDeviceNV; +GLXEW_FUN_EXPORT PFNGLXGETVIDEOINFONVPROC __glewXGetVideoInfoNV; +GLXEW_FUN_EXPORT PFNGLXRELEASEVIDEODEVICENVPROC __glewXReleaseVideoDeviceNV; +GLXEW_FUN_EXPORT PFNGLXRELEASEVIDEOIMAGENVPROC __glewXReleaseVideoImageNV; +GLXEW_FUN_EXPORT PFNGLXSENDPBUFFERTOVIDEONVPROC __glewXSendPbufferToVideoNV; -extern PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX; -extern PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX; -extern PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX; -extern PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX; -extern PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX; -extern PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX; -extern PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX; -extern PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX; +GLXEW_FUN_EXPORT PFNGLXGETMSCRATEOMLPROC __glewXGetMscRateOML; +GLXEW_FUN_EXPORT PFNGLXGETSYNCVALUESOMLPROC __glewXGetSyncValuesOML; +GLXEW_FUN_EXPORT PFNGLXSWAPBUFFERSMSCOMLPROC __glewXSwapBuffersMscOML; +GLXEW_FUN_EXPORT PFNGLXWAITFORMSCOMLPROC __glewXWaitForMscOML; +GLXEW_FUN_EXPORT PFNGLXWAITFORSBCOMLPROC __glewXWaitForSbcOML; -extern PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX; -extern PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX; -extern PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX; -extern PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX; -extern PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX; +GLXEW_FUN_EXPORT PFNGLXCHOOSEFBCONFIGSGIXPROC __glewXChooseFBConfigSGIX; +GLXEW_FUN_EXPORT PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC __glewXCreateContextWithConfigSGIX; +GLXEW_FUN_EXPORT PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC __glewXCreateGLXPixmapWithConfigSGIX; +GLXEW_FUN_EXPORT PFNGLXGETFBCONFIGATTRIBSGIXPROC __glewXGetFBConfigAttribSGIX; +GLXEW_FUN_EXPORT PFNGLXGETFBCONFIGFROMVISUALSGIXPROC __glewXGetFBConfigFromVisualSGIX; +GLXEW_FUN_EXPORT PFNGLXGETVISUALFROMFBCONFIGSGIXPROC __glewXGetVisualFromFBConfigSGIX; -extern PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX; -extern PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX; +GLXEW_FUN_EXPORT PFNGLXBINDHYPERPIPESGIXPROC __glewXBindHyperpipeSGIX; +GLXEW_FUN_EXPORT PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC __glewXDestroyHyperpipeConfigSGIX; +GLXEW_FUN_EXPORT PFNGLXHYPERPIPEATTRIBSGIXPROC __glewXHyperpipeAttribSGIX; +GLXEW_FUN_EXPORT PFNGLXHYPERPIPECONFIGSGIXPROC __glewXHyperpipeConfigSGIX; +GLXEW_FUN_EXPORT PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC __glewXQueryHyperpipeAttribSGIX; +GLXEW_FUN_EXPORT PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC __glewXQueryHyperpipeBestAttribSGIX; +GLXEW_FUN_EXPORT PFNGLXQUERYHYPERPIPECONFIGSGIXPROC __glewXQueryHyperpipeConfigSGIX; +GLXEW_FUN_EXPORT PFNGLXQUERYHYPERPIPENETWORKSGIXPROC __glewXQueryHyperpipeNetworkSGIX; -extern PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX; +GLXEW_FUN_EXPORT PFNGLXCREATEGLXPBUFFERSGIXPROC __glewXCreateGLXPbufferSGIX; +GLXEW_FUN_EXPORT PFNGLXDESTROYGLXPBUFFERSGIXPROC __glewXDestroyGLXPbufferSGIX; +GLXEW_FUN_EXPORT PFNGLXGETSELECTEDEVENTSGIXPROC __glewXGetSelectedEventSGIX; +GLXEW_FUN_EXPORT PFNGLXQUERYGLXPBUFFERSGIXPROC __glewXQueryGLXPbufferSGIX; +GLXEW_FUN_EXPORT PFNGLXSELECTEVENTSGIXPROC __glewXSelectEventSGIX; -extern PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX; -extern PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX; -extern PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX; -extern PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX; -extern PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX; +GLXEW_FUN_EXPORT PFNGLXBINDSWAPBARRIERSGIXPROC __glewXBindSwapBarrierSGIX; +GLXEW_FUN_EXPORT PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC __glewXQueryMaxSwapBarriersSGIX; -extern PFNGLXCUSHIONSGIPROC __glewXCushionSGI; +GLXEW_FUN_EXPORT PFNGLXJOINSWAPGROUPSGIXPROC __glewXJoinSwapGroupSGIX; -extern PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI; -extern PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI; +GLXEW_FUN_EXPORT PFNGLXBINDCHANNELTOWINDOWSGIXPROC __glewXBindChannelToWindowSGIX; +GLXEW_FUN_EXPORT PFNGLXCHANNELRECTSGIXPROC __glewXChannelRectSGIX; +GLXEW_FUN_EXPORT PFNGLXCHANNELRECTSYNCSGIXPROC __glewXChannelRectSyncSGIX; +GLXEW_FUN_EXPORT PFNGLXQUERYCHANNELDELTASSGIXPROC __glewXQueryChannelDeltasSGIX; +GLXEW_FUN_EXPORT PFNGLXQUERYCHANNELRECTSGIXPROC __glewXQueryChannelRectSGIX; -extern PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI; +GLXEW_FUN_EXPORT PFNGLXCUSHIONSGIPROC __glewXCushionSGI; -extern PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI; -extern PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI; +GLXEW_FUN_EXPORT PFNGLXGETCURRENTREADDRAWABLESGIPROC __glewXGetCurrentReadDrawableSGI; +GLXEW_FUN_EXPORT PFNGLXMAKECURRENTREADSGIPROC __glewXMakeCurrentReadSGI; -extern PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN; +GLXEW_FUN_EXPORT PFNGLXSWAPINTERVALSGIPROC __glewXSwapIntervalSGI; -extern PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN; -extern PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN; +GLXEW_FUN_EXPORT PFNGLXGETVIDEOSYNCSGIPROC __glewXGetVideoSyncSGI; +GLXEW_FUN_EXPORT PFNGLXWAITVIDEOSYNCSGIPROC __glewXWaitVideoSyncSGI; + +GLXEW_FUN_EXPORT PFNGLXGETTRANSPARENTINDEXSUNPROC __glewXGetTransparentIndexSUN; + +GLXEW_FUN_EXPORT PFNGLXGETVIDEORESIZESUNPROC __glewXGetVideoResizeSUN; +GLXEW_FUN_EXPORT PFNGLXVIDEORESIZESUNPROC __glewXVideoResizeSUN; #if defined(GLEW_MX) struct GLXEWContextStruct { #endif /* GLEW_MX */ -GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_0; -GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_1; -GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_2; -GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_3; -GLXEW_EXPORT GLboolean __GLXEW_VERSION_1_4; -GLXEW_EXPORT GLboolean __GLXEW_3DFX_multisample; -GLXEW_EXPORT GLboolean __GLXEW_AMD_gpu_association; -GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context; -GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_profile; -GLXEW_EXPORT GLboolean __GLXEW_ARB_create_context_robustness; -GLXEW_EXPORT GLboolean __GLXEW_ARB_fbconfig_float; -GLXEW_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB; -GLXEW_EXPORT GLboolean __GLXEW_ARB_get_proc_address; -GLXEW_EXPORT GLboolean __GLXEW_ARB_multisample; -GLXEW_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object; -GLXEW_EXPORT GLboolean __GLXEW_ATI_pixel_format_float; -GLXEW_EXPORT GLboolean __GLXEW_ATI_render_texture; -GLXEW_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile; -GLXEW_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float; -GLXEW_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB; -GLXEW_EXPORT GLboolean __GLXEW_EXT_import_context; -GLXEW_EXPORT GLboolean __GLXEW_EXT_scene_marker; -GLXEW_EXPORT GLboolean __GLXEW_EXT_swap_control; -GLXEW_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap; -GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_info; -GLXEW_EXPORT GLboolean __GLXEW_EXT_visual_rating; -GLXEW_EXPORT GLboolean __GLXEW_INTEL_swap_event; -GLXEW_EXPORT GLboolean __GLXEW_MESA_agp_offset; -GLXEW_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer; -GLXEW_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap; -GLXEW_EXPORT GLboolean __GLXEW_MESA_release_buffers; -GLXEW_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode; -GLXEW_EXPORT GLboolean __GLXEW_NV_copy_image; -GLXEW_EXPORT GLboolean __GLXEW_NV_float_buffer; -GLXEW_EXPORT GLboolean __GLXEW_NV_multisample_coverage; -GLXEW_EXPORT GLboolean __GLXEW_NV_present_video; -GLXEW_EXPORT GLboolean __GLXEW_NV_swap_group; -GLXEW_EXPORT GLboolean __GLXEW_NV_vertex_array_range; -GLXEW_EXPORT GLboolean __GLXEW_NV_video_capture; -GLXEW_EXPORT GLboolean __GLXEW_NV_video_output; -GLXEW_EXPORT GLboolean __GLXEW_OML_swap_method; -GLXEW_EXPORT GLboolean __GLXEW_OML_sync_control; -GLXEW_EXPORT GLboolean __GLXEW_SGIS_blended_overlay; -GLXEW_EXPORT GLboolean __GLXEW_SGIS_color_range; -GLXEW_EXPORT GLboolean __GLXEW_SGIS_multisample; -GLXEW_EXPORT GLboolean __GLXEW_SGIS_shared_multisample; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_fbconfig; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_hyperpipe; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_pbuffer; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_barrier; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_swap_group; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_video_resize; -GLXEW_EXPORT GLboolean __GLXEW_SGIX_visual_select_group; -GLXEW_EXPORT GLboolean __GLXEW_SGI_cushion; -GLXEW_EXPORT GLboolean __GLXEW_SGI_make_current_read; -GLXEW_EXPORT GLboolean __GLXEW_SGI_swap_control; -GLXEW_EXPORT GLboolean __GLXEW_SGI_video_sync; -GLXEW_EXPORT GLboolean __GLXEW_SUN_get_transparent_index; -GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize; +GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_0; +GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_1; +GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_2; +GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_3; +GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_4; +GLXEW_VAR_EXPORT GLboolean __GLXEW_3DFX_multisample; +GLXEW_VAR_EXPORT GLboolean __GLXEW_AMD_gpu_association; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context_profile; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_create_context_robustness; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_fbconfig_float; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_framebuffer_sRGB; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_get_proc_address; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_multisample; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_robustness_application_isolation; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_robustness_share_group_isolation; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ARB_vertex_buffer_object; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ATI_pixel_format_float; +GLXEW_VAR_EXPORT GLboolean __GLXEW_ATI_render_texture; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_buffer_age; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_create_context_es2_profile; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_create_context_es_profile; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_import_context; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_scene_marker; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_swap_control; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_swap_control_tear; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_visual_info; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_visual_rating; +GLXEW_VAR_EXPORT GLboolean __GLXEW_INTEL_swap_event; +GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_agp_offset; +GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer; +GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap; +GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_release_buffers; +GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode; +GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_swap_control; +GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_copy_image; +GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_float_buffer; +GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_multisample_coverage; +GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_present_video; +GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_swap_group; +GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_vertex_array_range; +GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_video_capture; +GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_video_output; +GLXEW_VAR_EXPORT GLboolean __GLXEW_OML_swap_method; +GLXEW_VAR_EXPORT GLboolean __GLXEW_OML_sync_control; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIS_blended_overlay; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIS_color_range; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIS_multisample; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIS_shared_multisample; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_fbconfig; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_hyperpipe; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_pbuffer; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_swap_barrier; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_swap_group; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_video_resize; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIX_visual_select_group; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGI_cushion; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGI_make_current_read; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGI_swap_control; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SGI_video_sync; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SUN_get_transparent_index; +GLXEW_VAR_EXPORT GLboolean __GLXEW_SUN_video_resize; #ifdef GLEW_MX }; /* GLXEWContextStruct */ @@ -1541,8 +1642,8 @@ GLXEW_EXPORT GLboolean __GLXEW_SUN_video_resize; #ifdef GLEW_MX typedef struct GLXEWContextStruct GLXEWContext; -extern GLenum glxewContextInit (GLXEWContext* ctx); -extern GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name); +GLEWAPI GLenum GLEWAPIENTRY glxewContextInit (GLXEWContext *ctx); +GLEWAPI GLboolean GLEWAPIENTRY glxewContextIsSupported (const GLXEWContext *ctx, const char *name); #define glxewInit() glxewContextInit(glxewGetContext()) #define glxewIsSupported(x) glxewContextIsSupported(glxewGetContext(), x) @@ -1555,11 +1656,11 @@ extern GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* n #define GLXEW_GET_VAR(x) (*(const GLboolean*)&x) #define GLXEW_GET_FUN(x) x -extern GLboolean glxewIsSupported (const char* name); +GLEWAPI GLboolean GLEWAPIENTRY glxewIsSupported (const char *name); #endif /* GLEW_MX */ -extern GLboolean glxewGetExtension (const char* name); +GLEWAPI GLboolean GLEWAPIENTRY glxewGetExtension (const char *name); #ifdef __cplusplus } diff --git a/ext/glew/GL/wglew.h b/ext/glew/GL/wglew.h index deb6468281..8659841d35 100644 --- a/ext/glew/GL/wglew.h +++ b/ext/glew/GL/wglew.h @@ -193,6 +193,8 @@ typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, in #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 #define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define ERROR_INVALID_VERSION_ARB 0x2095 +#define ERROR_INVALID_PROFILE_ARB 0x2096 typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList); @@ -444,6 +446,28 @@ typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, con #endif /* WGL_ARB_render_texture */ +/* ---------------- WGL_ARB_robustness_application_isolation --------------- */ + +#ifndef WGL_ARB_robustness_application_isolation +#define WGL_ARB_robustness_application_isolation 1 + +#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008 + +#define WGLEW_ARB_robustness_application_isolation WGLEW_GET_VAR(__WGLEW_ARB_robustness_application_isolation) + +#endif /* WGL_ARB_robustness_application_isolation */ + +/* ---------------- WGL_ARB_robustness_share_group_isolation --------------- */ + +#ifndef WGL_ARB_robustness_share_group_isolation +#define WGL_ARB_robustness_share_group_isolation 1 + +#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008 + +#define WGLEW_ARB_robustness_share_group_isolation WGLEW_GET_VAR(__WGLEW_ARB_robustness_share_group_isolation) + +#endif /* WGL_ARB_robustness_share_group_isolation */ + /* ----------------------- WGL_ATI_pixel_format_float ---------------------- */ #ifndef WGL_ATI_pixel_format_float @@ -479,6 +503,17 @@ typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, con #endif /* WGL_EXT_create_context_es2_profile */ +/* ------------------- WGL_EXT_create_context_es_profile ------------------- */ + +#ifndef WGL_EXT_create_context_es_profile +#define WGL_EXT_create_context_es_profile 1 + +#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004 + +#define WGLEW_EXT_create_context_es_profile WGLEW_GET_VAR(__WGLEW_EXT_create_context_es_profile) + +#endif /* WGL_EXT_create_context_es_profile */ + /* -------------------------- WGL_EXT_depth_float -------------------------- */ #ifndef WGL_EXT_depth_float @@ -684,6 +719,15 @@ typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); #endif /* WGL_EXT_swap_control */ +/* ----------------------- WGL_EXT_swap_control_tear ----------------------- */ + +#ifndef WGL_EXT_swap_control_tear +#define WGL_EXT_swap_control_tear 1 + +#define WGLEW_EXT_swap_control_tear WGLEW_GET_VAR(__WGLEW_EXT_swap_control_tear) + +#endif /* WGL_EXT_swap_control_tear */ + /* --------------------- WGL_I3D_digital_video_control --------------------- */ #ifndef WGL_I3D_digital_video_control @@ -862,6 +906,15 @@ typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE h #endif /* WGL_NV_DX_interop */ +/* --------------------------- WGL_NV_DX_interop2 -------------------------- */ + +#ifndef WGL_NV_DX_interop2 +#define WGL_NV_DX_interop2 1 + +#define WGLEW_NV_DX_interop2 WGLEW_GET_VAR(__WGLEW_NV_DX_interop2) + +#endif /* WGL_NV_DX_interop2 */ + /* --------------------------- WGL_NV_copy_image --------------------------- */ #ifndef WGL_NV_copy_image @@ -1118,9 +1171,11 @@ typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT6 /* ------------------------------------------------------------------------- */ #ifdef GLEW_MX -#define WGLEW_EXPORT +#define WGLEW_FUN_EXPORT +#define WGLEW_VAR_EXPORT #else -#define WGLEW_EXPORT GLEWAPI +#define WGLEW_FUN_EXPORT GLEW_FUN_EXPORT +#define WGLEW_VAR_EXPORT GLEW_VAR_EXPORT #endif /* GLEW_MX */ #ifdef GLEW_MX @@ -1128,200 +1183,205 @@ struct WGLEWContextStruct { #endif /* GLEW_MX */ -WGLEW_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL; +WGLEW_FUN_EXPORT PFNWGLSETSTEREOEMITTERSTATE3DLPROC __wglewSetStereoEmitterState3DL; -WGLEW_EXPORT PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD; -WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD; -WGLEW_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD; -WGLEW_EXPORT PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD; -WGLEW_EXPORT PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD; -WGLEW_EXPORT PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD; -WGLEW_EXPORT PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD; -WGLEW_EXPORT PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD; -WGLEW_EXPORT PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD; +WGLEW_FUN_EXPORT PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC __wglewBlitContextFramebufferAMD; +WGLEW_FUN_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC __wglewCreateAssociatedContextAMD; +WGLEW_FUN_EXPORT PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __wglewCreateAssociatedContextAttribsAMD; +WGLEW_FUN_EXPORT PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC __wglewDeleteAssociatedContextAMD; +WGLEW_FUN_EXPORT PFNWGLGETCONTEXTGPUIDAMDPROC __wglewGetContextGPUIDAMD; +WGLEW_FUN_EXPORT PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC __wglewGetCurrentAssociatedContextAMD; +WGLEW_FUN_EXPORT PFNWGLGETGPUIDSAMDPROC __wglewGetGPUIDsAMD; +WGLEW_FUN_EXPORT PFNWGLGETGPUINFOAMDPROC __wglewGetGPUInfoAMD; +WGLEW_FUN_EXPORT PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __wglewMakeAssociatedContextCurrentAMD; -WGLEW_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB; -WGLEW_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB; -WGLEW_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB; -WGLEW_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB; +WGLEW_FUN_EXPORT PFNWGLCREATEBUFFERREGIONARBPROC __wglewCreateBufferRegionARB; +WGLEW_FUN_EXPORT PFNWGLDELETEBUFFERREGIONARBPROC __wglewDeleteBufferRegionARB; +WGLEW_FUN_EXPORT PFNWGLRESTOREBUFFERREGIONARBPROC __wglewRestoreBufferRegionARB; +WGLEW_FUN_EXPORT PFNWGLSAVEBUFFERREGIONARBPROC __wglewSaveBufferRegionARB; -WGLEW_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB; +WGLEW_FUN_EXPORT PFNWGLCREATECONTEXTATTRIBSARBPROC __wglewCreateContextAttribsARB; -WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB; +WGLEW_FUN_EXPORT PFNWGLGETEXTENSIONSSTRINGARBPROC __wglewGetExtensionsStringARB; -WGLEW_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB; -WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB; +WGLEW_FUN_EXPORT PFNWGLGETCURRENTREADDCARBPROC __wglewGetCurrentReadDCARB; +WGLEW_FUN_EXPORT PFNWGLMAKECONTEXTCURRENTARBPROC __wglewMakeContextCurrentARB; -WGLEW_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB; -WGLEW_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB; -WGLEW_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB; -WGLEW_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB; -WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB; +WGLEW_FUN_EXPORT PFNWGLCREATEPBUFFERARBPROC __wglewCreatePbufferARB; +WGLEW_FUN_EXPORT PFNWGLDESTROYPBUFFERARBPROC __wglewDestroyPbufferARB; +WGLEW_FUN_EXPORT PFNWGLGETPBUFFERDCARBPROC __wglewGetPbufferDCARB; +WGLEW_FUN_EXPORT PFNWGLQUERYPBUFFERARBPROC __wglewQueryPbufferARB; +WGLEW_FUN_EXPORT PFNWGLRELEASEPBUFFERDCARBPROC __wglewReleasePbufferDCARB; -WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB; -WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB; -WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB; +WGLEW_FUN_EXPORT PFNWGLCHOOSEPIXELFORMATARBPROC __wglewChoosePixelFormatARB; +WGLEW_FUN_EXPORT PFNWGLGETPIXELFORMATATTRIBFVARBPROC __wglewGetPixelFormatAttribfvARB; +WGLEW_FUN_EXPORT PFNWGLGETPIXELFORMATATTRIBIVARBPROC __wglewGetPixelFormatAttribivARB; -WGLEW_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB; -WGLEW_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB; -WGLEW_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB; +WGLEW_FUN_EXPORT PFNWGLBINDTEXIMAGEARBPROC __wglewBindTexImageARB; +WGLEW_FUN_EXPORT PFNWGLRELEASETEXIMAGEARBPROC __wglewReleaseTexImageARB; +WGLEW_FUN_EXPORT PFNWGLSETPBUFFERATTRIBARBPROC __wglewSetPbufferAttribARB; -WGLEW_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT; -WGLEW_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT; -WGLEW_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT; -WGLEW_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT; +WGLEW_FUN_EXPORT PFNWGLBINDDISPLAYCOLORTABLEEXTPROC __wglewBindDisplayColorTableEXT; +WGLEW_FUN_EXPORT PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC __wglewCreateDisplayColorTableEXT; +WGLEW_FUN_EXPORT PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC __wglewDestroyDisplayColorTableEXT; +WGLEW_FUN_EXPORT PFNWGLLOADDISPLAYCOLORTABLEEXTPROC __wglewLoadDisplayColorTableEXT; -WGLEW_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT; +WGLEW_FUN_EXPORT PFNWGLGETEXTENSIONSSTRINGEXTPROC __wglewGetExtensionsStringEXT; -WGLEW_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT; -WGLEW_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT; +WGLEW_FUN_EXPORT PFNWGLGETCURRENTREADDCEXTPROC __wglewGetCurrentReadDCEXT; +WGLEW_FUN_EXPORT PFNWGLMAKECONTEXTCURRENTEXTPROC __wglewMakeContextCurrentEXT; -WGLEW_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT; -WGLEW_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT; -WGLEW_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT; -WGLEW_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT; -WGLEW_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT; +WGLEW_FUN_EXPORT PFNWGLCREATEPBUFFEREXTPROC __wglewCreatePbufferEXT; +WGLEW_FUN_EXPORT PFNWGLDESTROYPBUFFEREXTPROC __wglewDestroyPbufferEXT; +WGLEW_FUN_EXPORT PFNWGLGETPBUFFERDCEXTPROC __wglewGetPbufferDCEXT; +WGLEW_FUN_EXPORT PFNWGLQUERYPBUFFEREXTPROC __wglewQueryPbufferEXT; +WGLEW_FUN_EXPORT PFNWGLRELEASEPBUFFERDCEXTPROC __wglewReleasePbufferDCEXT; -WGLEW_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT; -WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT; -WGLEW_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT; +WGLEW_FUN_EXPORT PFNWGLCHOOSEPIXELFORMATEXTPROC __wglewChoosePixelFormatEXT; +WGLEW_FUN_EXPORT PFNWGLGETPIXELFORMATATTRIBFVEXTPROC __wglewGetPixelFormatAttribfvEXT; +WGLEW_FUN_EXPORT PFNWGLGETPIXELFORMATATTRIBIVEXTPROC __wglewGetPixelFormatAttribivEXT; -WGLEW_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT; -WGLEW_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT; +WGLEW_FUN_EXPORT PFNWGLGETSWAPINTERVALEXTPROC __wglewGetSwapIntervalEXT; +WGLEW_FUN_EXPORT PFNWGLSWAPINTERVALEXTPROC __wglewSwapIntervalEXT; -WGLEW_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D; -WGLEW_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D; +WGLEW_FUN_EXPORT PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC __wglewGetDigitalVideoParametersI3D; +WGLEW_FUN_EXPORT PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC __wglewSetDigitalVideoParametersI3D; -WGLEW_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D; -WGLEW_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D; -WGLEW_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D; -WGLEW_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D; +WGLEW_FUN_EXPORT PFNWGLGETGAMMATABLEI3DPROC __wglewGetGammaTableI3D; +WGLEW_FUN_EXPORT PFNWGLGETGAMMATABLEPARAMETERSI3DPROC __wglewGetGammaTableParametersI3D; +WGLEW_FUN_EXPORT PFNWGLSETGAMMATABLEI3DPROC __wglewSetGammaTableI3D; +WGLEW_FUN_EXPORT PFNWGLSETGAMMATABLEPARAMETERSI3DPROC __wglewSetGammaTableParametersI3D; -WGLEW_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D; -WGLEW_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D; -WGLEW_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D; -WGLEW_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D; -WGLEW_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D; -WGLEW_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D; -WGLEW_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D; -WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D; -WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D; -WGLEW_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D; -WGLEW_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D; -WGLEW_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D; +WGLEW_FUN_EXPORT PFNWGLDISABLEGENLOCKI3DPROC __wglewDisableGenlockI3D; +WGLEW_FUN_EXPORT PFNWGLENABLEGENLOCKI3DPROC __wglewEnableGenlockI3D; +WGLEW_FUN_EXPORT PFNWGLGENLOCKSAMPLERATEI3DPROC __wglewGenlockSampleRateI3D; +WGLEW_FUN_EXPORT PFNWGLGENLOCKSOURCEDELAYI3DPROC __wglewGenlockSourceDelayI3D; +WGLEW_FUN_EXPORT PFNWGLGENLOCKSOURCEEDGEI3DPROC __wglewGenlockSourceEdgeI3D; +WGLEW_FUN_EXPORT PFNWGLGENLOCKSOURCEI3DPROC __wglewGenlockSourceI3D; +WGLEW_FUN_EXPORT PFNWGLGETGENLOCKSAMPLERATEI3DPROC __wglewGetGenlockSampleRateI3D; +WGLEW_FUN_EXPORT PFNWGLGETGENLOCKSOURCEDELAYI3DPROC __wglewGetGenlockSourceDelayI3D; +WGLEW_FUN_EXPORT PFNWGLGETGENLOCKSOURCEEDGEI3DPROC __wglewGetGenlockSourceEdgeI3D; +WGLEW_FUN_EXPORT PFNWGLGETGENLOCKSOURCEI3DPROC __wglewGetGenlockSourceI3D; +WGLEW_FUN_EXPORT PFNWGLISENABLEDGENLOCKI3DPROC __wglewIsEnabledGenlockI3D; +WGLEW_FUN_EXPORT PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC __wglewQueryGenlockMaxSourceDelayI3D; -WGLEW_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D; -WGLEW_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D; -WGLEW_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D; -WGLEW_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D; +WGLEW_FUN_EXPORT PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC __wglewAssociateImageBufferEventsI3D; +WGLEW_FUN_EXPORT PFNWGLCREATEIMAGEBUFFERI3DPROC __wglewCreateImageBufferI3D; +WGLEW_FUN_EXPORT PFNWGLDESTROYIMAGEBUFFERI3DPROC __wglewDestroyImageBufferI3D; +WGLEW_FUN_EXPORT PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC __wglewReleaseImageBufferEventsI3D; -WGLEW_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D; -WGLEW_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D; -WGLEW_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D; -WGLEW_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D; +WGLEW_FUN_EXPORT PFNWGLDISABLEFRAMELOCKI3DPROC __wglewDisableFrameLockI3D; +WGLEW_FUN_EXPORT PFNWGLENABLEFRAMELOCKI3DPROC __wglewEnableFrameLockI3D; +WGLEW_FUN_EXPORT PFNWGLISENABLEDFRAMELOCKI3DPROC __wglewIsEnabledFrameLockI3D; +WGLEW_FUN_EXPORT PFNWGLQUERYFRAMELOCKMASTERI3DPROC __wglewQueryFrameLockMasterI3D; -WGLEW_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D; -WGLEW_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D; -WGLEW_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D; -WGLEW_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D; +WGLEW_FUN_EXPORT PFNWGLBEGINFRAMETRACKINGI3DPROC __wglewBeginFrameTrackingI3D; +WGLEW_FUN_EXPORT PFNWGLENDFRAMETRACKINGI3DPROC __wglewEndFrameTrackingI3D; +WGLEW_FUN_EXPORT PFNWGLGETFRAMEUSAGEI3DPROC __wglewGetFrameUsageI3D; +WGLEW_FUN_EXPORT PFNWGLQUERYFRAMETRACKINGI3DPROC __wglewQueryFrameTrackingI3D; -WGLEW_EXPORT PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV; -WGLEW_EXPORT PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV; -WGLEW_EXPORT PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV; -WGLEW_EXPORT PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV; -WGLEW_EXPORT PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV; -WGLEW_EXPORT PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV; -WGLEW_EXPORT PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV; -WGLEW_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV; +WGLEW_FUN_EXPORT PFNWGLDXCLOSEDEVICENVPROC __wglewDXCloseDeviceNV; +WGLEW_FUN_EXPORT PFNWGLDXLOCKOBJECTSNVPROC __wglewDXLockObjectsNV; +WGLEW_FUN_EXPORT PFNWGLDXOBJECTACCESSNVPROC __wglewDXObjectAccessNV; +WGLEW_FUN_EXPORT PFNWGLDXOPENDEVICENVPROC __wglewDXOpenDeviceNV; +WGLEW_FUN_EXPORT PFNWGLDXREGISTEROBJECTNVPROC __wglewDXRegisterObjectNV; +WGLEW_FUN_EXPORT PFNWGLDXSETRESOURCESHAREHANDLENVPROC __wglewDXSetResourceShareHandleNV; +WGLEW_FUN_EXPORT PFNWGLDXUNLOCKOBJECTSNVPROC __wglewDXUnlockObjectsNV; +WGLEW_FUN_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV; -WGLEW_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV; +WGLEW_FUN_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV; -WGLEW_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV; -WGLEW_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV; -WGLEW_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV; -WGLEW_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV; -WGLEW_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV; +WGLEW_FUN_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV; +WGLEW_FUN_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV; +WGLEW_FUN_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV; +WGLEW_FUN_EXPORT PFNWGLENUMGPUSFROMAFFINITYDCNVPROC __wglewEnumGpusFromAffinityDCNV; +WGLEW_FUN_EXPORT PFNWGLENUMGPUSNVPROC __wglewEnumGpusNV; -WGLEW_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV; -WGLEW_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV; -WGLEW_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV; +WGLEW_FUN_EXPORT PFNWGLBINDVIDEODEVICENVPROC __wglewBindVideoDeviceNV; +WGLEW_FUN_EXPORT PFNWGLENUMERATEVIDEODEVICESNVPROC __wglewEnumerateVideoDevicesNV; +WGLEW_FUN_EXPORT PFNWGLQUERYCURRENTCONTEXTNVPROC __wglewQueryCurrentContextNV; -WGLEW_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV; -WGLEW_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV; -WGLEW_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV; -WGLEW_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV; -WGLEW_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV; -WGLEW_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV; +WGLEW_FUN_EXPORT PFNWGLBINDSWAPBARRIERNVPROC __wglewBindSwapBarrierNV; +WGLEW_FUN_EXPORT PFNWGLJOINSWAPGROUPNVPROC __wglewJoinSwapGroupNV; +WGLEW_FUN_EXPORT PFNWGLQUERYFRAMECOUNTNVPROC __wglewQueryFrameCountNV; +WGLEW_FUN_EXPORT PFNWGLQUERYMAXSWAPGROUPSNVPROC __wglewQueryMaxSwapGroupsNV; +WGLEW_FUN_EXPORT PFNWGLQUERYSWAPGROUPNVPROC __wglewQuerySwapGroupNV; +WGLEW_FUN_EXPORT PFNWGLRESETFRAMECOUNTNVPROC __wglewResetFrameCountNV; -WGLEW_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV; -WGLEW_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV; +WGLEW_FUN_EXPORT PFNWGLALLOCATEMEMORYNVPROC __wglewAllocateMemoryNV; +WGLEW_FUN_EXPORT PFNWGLFREEMEMORYNVPROC __wglewFreeMemoryNV; -WGLEW_EXPORT PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV; -WGLEW_EXPORT PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV; -WGLEW_EXPORT PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV; -WGLEW_EXPORT PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV; -WGLEW_EXPORT PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV; +WGLEW_FUN_EXPORT PFNWGLBINDVIDEOCAPTUREDEVICENVPROC __wglewBindVideoCaptureDeviceNV; +WGLEW_FUN_EXPORT PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC __wglewEnumerateVideoCaptureDevicesNV; +WGLEW_FUN_EXPORT PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC __wglewLockVideoCaptureDeviceNV; +WGLEW_FUN_EXPORT PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC __wglewQueryVideoCaptureDeviceNV; +WGLEW_FUN_EXPORT PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC __wglewReleaseVideoCaptureDeviceNV; -WGLEW_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV; -WGLEW_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV; -WGLEW_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV; -WGLEW_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV; -WGLEW_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV; -WGLEW_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV; +WGLEW_FUN_EXPORT PFNWGLBINDVIDEOIMAGENVPROC __wglewBindVideoImageNV; +WGLEW_FUN_EXPORT PFNWGLGETVIDEODEVICENVPROC __wglewGetVideoDeviceNV; +WGLEW_FUN_EXPORT PFNWGLGETVIDEOINFONVPROC __wglewGetVideoInfoNV; +WGLEW_FUN_EXPORT PFNWGLRELEASEVIDEODEVICENVPROC __wglewReleaseVideoDeviceNV; +WGLEW_FUN_EXPORT PFNWGLRELEASEVIDEOIMAGENVPROC __wglewReleaseVideoImageNV; +WGLEW_FUN_EXPORT PFNWGLSENDPBUFFERTOVIDEONVPROC __wglewSendPbufferToVideoNV; -WGLEW_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML; -WGLEW_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML; -WGLEW_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML; -WGLEW_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML; -WGLEW_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML; -WGLEW_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML; -WGLEW_EXPORT GLboolean __WGLEW_3DFX_multisample; -WGLEW_EXPORT GLboolean __WGLEW_3DL_stereo_control; -WGLEW_EXPORT GLboolean __WGLEW_AMD_gpu_association; -WGLEW_EXPORT GLboolean __WGLEW_ARB_buffer_region; -WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context; -WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_profile; -WGLEW_EXPORT GLboolean __WGLEW_ARB_create_context_robustness; -WGLEW_EXPORT GLboolean __WGLEW_ARB_extensions_string; -WGLEW_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB; -WGLEW_EXPORT GLboolean __WGLEW_ARB_make_current_read; -WGLEW_EXPORT GLboolean __WGLEW_ARB_multisample; -WGLEW_EXPORT GLboolean __WGLEW_ARB_pbuffer; -WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format; -WGLEW_EXPORT GLboolean __WGLEW_ARB_pixel_format_float; -WGLEW_EXPORT GLboolean __WGLEW_ARB_render_texture; -WGLEW_EXPORT GLboolean __WGLEW_ATI_pixel_format_float; -WGLEW_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle; -WGLEW_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile; -WGLEW_EXPORT GLboolean __WGLEW_EXT_depth_float; -WGLEW_EXPORT GLboolean __WGLEW_EXT_display_color_table; -WGLEW_EXPORT GLboolean __WGLEW_EXT_extensions_string; -WGLEW_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB; -WGLEW_EXPORT GLboolean __WGLEW_EXT_make_current_read; -WGLEW_EXPORT GLboolean __WGLEW_EXT_multisample; -WGLEW_EXPORT GLboolean __WGLEW_EXT_pbuffer; -WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format; -WGLEW_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float; -WGLEW_EXPORT GLboolean __WGLEW_EXT_swap_control; -WGLEW_EXPORT GLboolean __WGLEW_I3D_digital_video_control; -WGLEW_EXPORT GLboolean __WGLEW_I3D_gamma; -WGLEW_EXPORT GLboolean __WGLEW_I3D_genlock; -WGLEW_EXPORT GLboolean __WGLEW_I3D_image_buffer; -WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock; -WGLEW_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage; -WGLEW_EXPORT GLboolean __WGLEW_NV_DX_interop; -WGLEW_EXPORT GLboolean __WGLEW_NV_copy_image; -WGLEW_EXPORT GLboolean __WGLEW_NV_float_buffer; -WGLEW_EXPORT GLboolean __WGLEW_NV_gpu_affinity; -WGLEW_EXPORT GLboolean __WGLEW_NV_multisample_coverage; -WGLEW_EXPORT GLboolean __WGLEW_NV_present_video; -WGLEW_EXPORT GLboolean __WGLEW_NV_render_depth_texture; -WGLEW_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle; -WGLEW_EXPORT GLboolean __WGLEW_NV_swap_group; -WGLEW_EXPORT GLboolean __WGLEW_NV_vertex_array_range; -WGLEW_EXPORT GLboolean __WGLEW_NV_video_capture; -WGLEW_EXPORT GLboolean __WGLEW_NV_video_output; -WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control; +WGLEW_FUN_EXPORT PFNWGLGETMSCRATEOMLPROC __wglewGetMscRateOML; +WGLEW_FUN_EXPORT PFNWGLGETSYNCVALUESOMLPROC __wglewGetSyncValuesOML; +WGLEW_FUN_EXPORT PFNWGLSWAPBUFFERSMSCOMLPROC __wglewSwapBuffersMscOML; +WGLEW_FUN_EXPORT PFNWGLSWAPLAYERBUFFERSMSCOMLPROC __wglewSwapLayerBuffersMscOML; +WGLEW_FUN_EXPORT PFNWGLWAITFORMSCOMLPROC __wglewWaitForMscOML; +WGLEW_FUN_EXPORT PFNWGLWAITFORSBCOMLPROC __wglewWaitForSbcOML; +WGLEW_VAR_EXPORT GLboolean __WGLEW_3DFX_multisample; +WGLEW_VAR_EXPORT GLboolean __WGLEW_3DL_stereo_control; +WGLEW_VAR_EXPORT GLboolean __WGLEW_AMD_gpu_association; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_buffer_region; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context_profile; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_create_context_robustness; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_extensions_string; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_framebuffer_sRGB; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_make_current_read; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_multisample; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pbuffer; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pixel_format; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_pixel_format_float; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_render_texture; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_robustness_application_isolation; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ARB_robustness_share_group_isolation; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ATI_pixel_format_float; +WGLEW_VAR_EXPORT GLboolean __WGLEW_ATI_render_texture_rectangle; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_create_context_es2_profile; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_create_context_es_profile; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_depth_float; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_display_color_table; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_extensions_string; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_framebuffer_sRGB; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_make_current_read; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_multisample; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_pbuffer; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_pixel_format; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_pixel_format_packed_float; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_swap_control; +WGLEW_VAR_EXPORT GLboolean __WGLEW_EXT_swap_control_tear; +WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_digital_video_control; +WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_gamma; +WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_genlock; +WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_image_buffer; +WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_swap_frame_lock; +WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_DX_interop; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_DX_interop2; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_copy_image; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_float_buffer; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_gpu_affinity; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_multisample_coverage; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_present_video; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_render_depth_texture; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_render_texture_rectangle; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_swap_group; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_vertex_array_range; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_video_capture; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_video_output; +WGLEW_VAR_EXPORT GLboolean __WGLEW_OML_sync_control; #ifdef GLEW_MX }; /* WGLEWContextStruct */ @@ -1332,8 +1392,8 @@ WGLEW_EXPORT GLboolean __WGLEW_OML_sync_control; #ifdef GLEW_MX typedef struct WGLEWContextStruct WGLEWContext; -GLEWAPI GLenum wglewContextInit (WGLEWContext* ctx); -GLEWAPI GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name); +GLEWAPI GLenum GLEWAPIENTRY wglewContextInit (WGLEWContext *ctx); +GLEWAPI GLboolean GLEWAPIENTRY wglewContextIsSupported (const WGLEWContext *ctx, const char *name); #define wglewInit() wglewContextInit(wglewGetContext()) #define wglewIsSupported(x) wglewContextIsSupported(wglewGetContext(), x) @@ -1346,11 +1406,11 @@ GLEWAPI GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* #define WGLEW_GET_VAR(x) (*(const GLboolean*)&x) #define WGLEW_GET_FUN(x) x -GLEWAPI GLboolean wglewIsSupported (const char* name); +GLEWAPI GLboolean GLEWAPIENTRY wglewIsSupported (const char *name); #endif /* GLEW_MX */ -GLEWAPI GLboolean wglewGetExtension (const char* name); +GLEWAPI GLboolean GLEWAPIENTRY wglewGetExtension (const char *name); #ifdef __cplusplus } diff --git a/ext/glew/glew.c b/ext/glew/glew.c index 72a81fef53..d075b52488 100644 --- a/ext/glew/glew.c +++ b/ext/glew/glew.c @@ -30,14 +30,13 @@ */ #include + #if defined(_WIN32) # include -#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) # include #endif -#pragma warning(disable:4273) - /* * Define glewGetContext and related helper macros. */ @@ -102,12 +101,17 @@ void* dlGetProcAddress (const GLubyte* name) void* NSGLGetProcAddress (const GLubyte *name) { static void* image = NULL; + void* addr; if (NULL == image) { +#ifdef GLEW_REGAL + image = dlopen("libRegal.dylib", RTLD_LAZY); +#else image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); +#endif } if( !image ) return NULL; - void* addr = dlsym(image, (const char*)name); + addr = dlsym(image, (const char*)name); if( addr ) return addr; #ifdef GLEW_APPLE_GLX return dlGetProcAddress( name ); // try next for glx symbols @@ -126,7 +130,11 @@ void* NSGLGetProcAddress (const GLubyte *name) char* symbolName; if (NULL == image) { +#ifdef GLEW_REGAL + image = NSAddImage("libRegal.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR); +#else image = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", NSADDIMAGE_OPTION_RETURN_ON_ERROR); +#endif } /* prepend a '_' for the Unix C symbol mangling convention */ symbolName = malloc(strlen((const char*)name) + 2); @@ -152,16 +160,16 @@ void* NSGLGetProcAddress (const GLubyte *name) */ #if defined(_WIN32) # define glewGetProcAddress(name) wglGetProcAddress((LPCSTR)name) -#else -# if defined(__APPLE__) -# define glewGetProcAddress(name) NSGLGetProcAddress(name) -# else -# if defined(__sgi) || defined(__sun) -# define glewGetProcAddress(name) dlGetProcAddress(name) -# else /* __linux */ -# define glewGetProcAddress(name) (*glXGetProcAddressARB)(name) -# endif -# endif +#elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) +# define glewGetProcAddress(name) NSGLGetProcAddress(name) +#elif defined(__sgi) || defined(__sun) +# define glewGetProcAddress(name) dlGetProcAddress(name) +#elif defined(__ANDROID__) +# define glewGetProcAddress(name) NULL /* TODO */ +#elif defined(__native_client__) +# define glewGetProcAddress(name) NULL /* TODO */ +#else /* __linux */ +# define glewGetProcAddress(name) (*glXGetProcAddressARB)(name) #endif /* @@ -579,6 +587,11 @@ PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC __glewBlendEquationSeparateIndexedAMD = PFNGLBLENDFUNCINDEXEDAMDPROC __glewBlendFuncIndexedAMD = NULL; PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC __glewBlendFuncSeparateIndexedAMD = NULL; +PFNGLVERTEXATTRIBPARAMETERIAMDPROC __glewVertexAttribParameteriAMD = NULL; + +PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC __glewMultiDrawArraysIndirectAMD = NULL; +PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC __glewMultiDrawElementsIndirectAMD = NULL; + PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD = NULL; PFNGLGENNAMESAMDPROC __glewGenNamesAMD = NULL; PFNGLISNAMEAMDPROC __glewIsNameAMD = NULL; @@ -597,9 +610,36 @@ PFNGLSELECTPERFMONITORCOUNTERSAMDPROC __glewSelectPerfMonitorCountersAMD = NULL; PFNGLSETMULTISAMPLEFVAMDPROC __glewSetMultisamplefvAMD = NULL; +PFNGLTEXSTORAGESPARSEAMDPROC __glewTexStorageSparseAMD = NULL; +PFNGLTEXTURESTORAGESPARSEAMDPROC __glewTextureStorageSparseAMD = NULL; + +PFNGLSTENCILOPVALUEAMDPROC __glewStencilOpValueAMD = NULL; + PFNGLTESSELLATIONFACTORAMDPROC __glewTessellationFactorAMD = NULL; PFNGLTESSELLATIONMODEAMDPROC __glewTessellationModeAMD = NULL; +PFNGLBLITFRAMEBUFFERANGLEPROC __glewBlitFramebufferANGLE = NULL; + +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC __glewRenderbufferStorageMultisampleANGLE = NULL; + +PFNGLDRAWARRAYSINSTANCEDANGLEPROC __glewDrawArraysInstancedANGLE = NULL; +PFNGLDRAWELEMENTSINSTANCEDANGLEPROC __glewDrawElementsInstancedANGLE = NULL; +PFNGLVERTEXATTRIBDIVISORANGLEPROC __glewVertexAttribDivisorANGLE = NULL; + +PFNGLBEGINQUERYANGLEPROC __glewBeginQueryANGLE = NULL; +PFNGLDELETEQUERIESANGLEPROC __glewDeleteQueriesANGLE = NULL; +PFNGLENDQUERYANGLEPROC __glewEndQueryANGLE = NULL; +PFNGLGENQUERIESANGLEPROC __glewGenQueriesANGLE = NULL; +PFNGLGETQUERYOBJECTI64VANGLEPROC __glewGetQueryObjecti64vANGLE = NULL; +PFNGLGETQUERYOBJECTIVANGLEPROC __glewGetQueryObjectivANGLE = NULL; +PFNGLGETQUERYOBJECTUI64VANGLEPROC __glewGetQueryObjectui64vANGLE = NULL; +PFNGLGETQUERYOBJECTUIVANGLEPROC __glewGetQueryObjectuivANGLE = NULL; +PFNGLGETQUERYIVANGLEPROC __glewGetQueryivANGLE = NULL; +PFNGLISQUERYANGLEPROC __glewIsQueryANGLE = NULL; +PFNGLQUERYCOUNTERANGLEPROC __glewQueryCounterANGLE = NULL; + +PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC __glewGetTranslatedShaderSourceANGLE = NULL; + PFNGLDRAWELEMENTARRAYAPPLEPROC __glewDrawElementArrayAPPLE = NULL; PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC __glewDrawRangeElementArrayAPPLE = NULL; PFNGLELEMENTPOINTERAPPLEPROC __glewElementPointerAPPLE = NULL; @@ -648,15 +688,54 @@ PFNGLGETSHADERPRECISIONFORMATPROC __glewGetShaderPrecisionFormat = NULL; PFNGLRELEASESHADERCOMPILERPROC __glewReleaseShaderCompiler = NULL; PFNGLSHADERBINARYPROC __glewShaderBinary = NULL; +PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC __glewDrawArraysInstancedBaseInstance = NULL; +PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC __glewDrawElementsInstancedBaseInstance = NULL; +PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC __glewDrawElementsInstancedBaseVertexBaseInstance = NULL; + +PFNGLGETIMAGEHANDLEARBPROC __glewGetImageHandleARB = NULL; +PFNGLGETTEXTUREHANDLEARBPROC __glewGetTextureHandleARB = NULL; +PFNGLGETTEXTURESAMPLERHANDLEARBPROC __glewGetTextureSamplerHandleARB = NULL; +PFNGLGETVERTEXATTRIBLUI64VARBPROC __glewGetVertexAttribLui64vARB = NULL; +PFNGLISIMAGEHANDLERESIDENTARBPROC __glewIsImageHandleResidentARB = NULL; +PFNGLISTEXTUREHANDLERESIDENTARBPROC __glewIsTextureHandleResidentARB = NULL; +PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC __glewMakeImageHandleNonResidentARB = NULL; +PFNGLMAKEIMAGEHANDLERESIDENTARBPROC __glewMakeImageHandleResidentARB = NULL; +PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC __glewMakeTextureHandleNonResidentARB = NULL; +PFNGLMAKETEXTUREHANDLERESIDENTARBPROC __glewMakeTextureHandleResidentARB = NULL; +PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC __glewProgramUniformHandleui64ARB = NULL; +PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC __glewProgramUniformHandleui64vARB = NULL; +PFNGLUNIFORMHANDLEUI64ARBPROC __glewUniformHandleui64ARB = NULL; +PFNGLUNIFORMHANDLEUI64VARBPROC __glewUniformHandleui64vARB = NULL; +PFNGLVERTEXATTRIBL1UI64ARBPROC __glewVertexAttribL1ui64ARB = NULL; +PFNGLVERTEXATTRIBL1UI64VARBPROC __glewVertexAttribL1ui64vARB = NULL; + PFNGLBINDFRAGDATALOCATIONINDEXEDPROC __glewBindFragDataLocationIndexed = NULL; PFNGLGETFRAGDATAINDEXPROC __glewGetFragDataIndex = NULL; +PFNGLBUFFERSTORAGEPROC __glewBufferStorage = NULL; +PFNGLNAMEDBUFFERSTORAGEEXTPROC __glewNamedBufferStorageEXT = NULL; + PFNGLCREATESYNCFROMCLEVENTARBPROC __glewCreateSyncFromCLeventARB = NULL; +PFNGLCLEARBUFFERDATAPROC __glewClearBufferData = NULL; +PFNGLCLEARBUFFERSUBDATAPROC __glewClearBufferSubData = NULL; +PFNGLCLEARNAMEDBUFFERDATAEXTPROC __glewClearNamedBufferDataEXT = NULL; +PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC __glewClearNamedBufferSubDataEXT = NULL; + +PFNGLCLEARTEXIMAGEPROC __glewClearTexImage = NULL; +PFNGLCLEARTEXSUBIMAGEPROC __glewClearTexSubImage = NULL; + PFNGLCLAMPCOLORARBPROC __glewClampColorARB = NULL; +PFNGLDISPATCHCOMPUTEPROC __glewDispatchCompute = NULL; +PFNGLDISPATCHCOMPUTEINDIRECTPROC __glewDispatchComputeIndirect = NULL; + +PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC __glewDispatchComputeGroupSizeARB = NULL; + PFNGLCOPYBUFFERSUBDATAPROC __glewCopyBufferSubData = NULL; +PFNGLCOPYIMAGESUBDATAPROC __glewCopyImageSubData = NULL; + PFNGLDEBUGMESSAGECALLBACKARBPROC __glewDebugMessageCallbackARB = NULL; PFNGLDEBUGMESSAGECONTROLARBPROC __glewDebugMessageControlARB = NULL; PFNGLDEBUGMESSAGEINSERTARBPROC __glewDebugMessageInsertARB = NULL; @@ -677,6 +756,11 @@ PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC __glewMultiDrawElementsBaseVertex = NULL; PFNGLDRAWARRAYSINDIRECTPROC __glewDrawArraysIndirect = NULL; PFNGLDRAWELEMENTSINDIRECTPROC __glewDrawElementsIndirect = NULL; +PFNGLFRAMEBUFFERPARAMETERIPROC __glewFramebufferParameteri = NULL; +PFNGLGETFRAMEBUFFERPARAMETERIVPROC __glewGetFramebufferParameteriv = NULL; +PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC __glewGetNamedFramebufferParameterivEXT = NULL; +PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC __glewNamedFramebufferParameteriEXT = NULL; + PFNGLBINDFRAMEBUFFERPROC __glewBindFramebuffer = NULL; PFNGLBINDRENDERBUFFERPROC __glewBindRenderbuffer = NULL; PFNGLBLITFRAMEBUFFERPROC __glewBlitFramebuffer = NULL; @@ -708,23 +792,6 @@ PFNGLPROGRAMBINARYPROC __glewProgramBinary = NULL; PFNGLPROGRAMPARAMETERIPROC __glewProgramParameteri = NULL; PFNGLGETUNIFORMDVPROC __glewGetUniformdv = NULL; -PFNGLPROGRAMUNIFORM1DEXTPROC __glewProgramUniform1dEXT = NULL; -PFNGLPROGRAMUNIFORM1DVEXTPROC __glewProgramUniform1dvEXT = NULL; -PFNGLPROGRAMUNIFORM2DEXTPROC __glewProgramUniform2dEXT = NULL; -PFNGLPROGRAMUNIFORM2DVEXTPROC __glewProgramUniform2dvEXT = NULL; -PFNGLPROGRAMUNIFORM3DEXTPROC __glewProgramUniform3dEXT = NULL; -PFNGLPROGRAMUNIFORM3DVEXTPROC __glewProgramUniform3dvEXT = NULL; -PFNGLPROGRAMUNIFORM4DEXTPROC __glewProgramUniform4dEXT = NULL; -PFNGLPROGRAMUNIFORM4DVEXTPROC __glewProgramUniform4dvEXT = NULL; -PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC __glewProgramUniformMatrix2dvEXT = NULL; -PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC __glewProgramUniformMatrix2x3dvEXT = NULL; -PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC __glewProgramUniformMatrix2x4dvEXT = NULL; -PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC __glewProgramUniformMatrix3dvEXT = NULL; -PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC __glewProgramUniformMatrix3x2dvEXT = NULL; -PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC __glewProgramUniformMatrix3x4dvEXT = NULL; -PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC __glewProgramUniformMatrix4dvEXT = NULL; -PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC __glewProgramUniformMatrix4x2dvEXT = NULL; -PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC __glewProgramUniformMatrix4x3dvEXT = NULL; PFNGLUNIFORM1DPROC __glewUniform1d = NULL; PFNGLUNIFORM1DVPROC __glewUniform1dv = NULL; PFNGLUNIFORM2DPROC __glewUniform2d = NULL; @@ -776,10 +843,24 @@ PFNGLRESETHISTOGRAMPROC __glewResetHistogram = NULL; PFNGLRESETMINMAXPROC __glewResetMinmax = NULL; PFNGLSEPARABLEFILTER2DPROC __glewSeparableFilter2D = NULL; +PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC __glewMultiDrawArraysIndirectCountARB = NULL; +PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC __glewMultiDrawElementsIndirectCountARB = NULL; + PFNGLDRAWARRAYSINSTANCEDARBPROC __glewDrawArraysInstancedARB = NULL; PFNGLDRAWELEMENTSINSTANCEDARBPROC __glewDrawElementsInstancedARB = NULL; PFNGLVERTEXATTRIBDIVISORARBPROC __glewVertexAttribDivisorARB = NULL; +PFNGLGETINTERNALFORMATIVPROC __glewGetInternalformativ = NULL; + +PFNGLGETINTERNALFORMATI64VPROC __glewGetInternalformati64v = NULL; + +PFNGLINVALIDATEBUFFERDATAPROC __glewInvalidateBufferData = NULL; +PFNGLINVALIDATEBUFFERSUBDATAPROC __glewInvalidateBufferSubData = NULL; +PFNGLINVALIDATEFRAMEBUFFERPROC __glewInvalidateFramebuffer = NULL; +PFNGLINVALIDATESUBFRAMEBUFFERPROC __glewInvalidateSubFramebuffer = NULL; +PFNGLINVALIDATETEXIMAGEPROC __glewInvalidateTexImage = NULL; +PFNGLINVALIDATETEXSUBIMAGEPROC __glewInvalidateTexSubImage = NULL; + PFNGLFLUSHMAPPEDBUFFERRANGEPROC __glewFlushMappedBufferRange = NULL; PFNGLMAPBUFFERRANGEPROC __glewMapBufferRange = NULL; @@ -789,6 +870,16 @@ PFNGLMATRIXINDEXUBVARBPROC __glewMatrixIndexubvARB = NULL; PFNGLMATRIXINDEXUIVARBPROC __glewMatrixIndexuivARB = NULL; PFNGLMATRIXINDEXUSVARBPROC __glewMatrixIndexusvARB = NULL; +PFNGLBINDBUFFERSBASEPROC __glewBindBuffersBase = NULL; +PFNGLBINDBUFFERSRANGEPROC __glewBindBuffersRange = NULL; +PFNGLBINDIMAGETEXTURESPROC __glewBindImageTextures = NULL; +PFNGLBINDSAMPLERSPROC __glewBindSamplers = NULL; +PFNGLBINDTEXTURESPROC __glewBindTextures = NULL; +PFNGLBINDVERTEXBUFFERSPROC __glewBindVertexBuffers = NULL; + +PFNGLMULTIDRAWARRAYSINDIRECTPROC __glewMultiDrawArraysIndirect = NULL; +PFNGLMULTIDRAWELEMENTSINDIRECTPROC __glewMultiDrawElementsIndirect = NULL; + PFNGLSAMPLECOVERAGEARBPROC __glewSampleCoverageARB = NULL; PFNGLACTIVETEXTUREARBPROC __glewActiveTextureARB = NULL; @@ -838,8 +929,16 @@ PFNGLISQUERYARBPROC __glewIsQueryARB = NULL; PFNGLPOINTPARAMETERFARBPROC __glewPointParameterfARB = NULL; PFNGLPOINTPARAMETERFVARBPROC __glewPointParameterfvARB = NULL; +PFNGLGETPROGRAMINTERFACEIVPROC __glewGetProgramInterfaceiv = NULL; +PFNGLGETPROGRAMRESOURCEINDEXPROC __glewGetProgramResourceIndex = NULL; +PFNGLGETPROGRAMRESOURCELOCATIONPROC __glewGetProgramResourceLocation = NULL; +PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC __glewGetProgramResourceLocationIndex = NULL; +PFNGLGETPROGRAMRESOURCENAMEPROC __glewGetProgramResourceName = NULL; +PFNGLGETPROGRAMRESOURCEIVPROC __glewGetProgramResourceiv = NULL; + PFNGLPROVOKINGVERTEXPROC __glewProvokingVertex = NULL; +PFNGLGETGRAPHICSRESETSTATUSARBPROC __glewGetGraphicsResetStatusARB = NULL; PFNGLGETNCOLORTABLEARBPROC __glewGetnColorTableARB = NULL; PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC __glewGetnCompressedTexImageARB = NULL; PFNGLGETNCONVOLUTIONFILTERARBPROC __glewGetnConvolutionFilterARB = NULL; @@ -938,6 +1037,11 @@ PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC __glewProgramUniformMatrix4x3fv = NULL; PFNGLUSEPROGRAMSTAGESPROC __glewUseProgramStages = NULL; PFNGLVALIDATEPROGRAMPIPELINEPROC __glewValidateProgramPipeline = NULL; +PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC __glewGetActiveAtomicCounterBufferiv = NULL; + +PFNGLBINDIMAGETEXTUREPROC __glewBindImageTexture = NULL; +PFNGLMEMORYBARRIERPROC __glewMemoryBarrier = NULL; + PFNGLATTACHOBJECTARBPROC __glewAttachObjectARB = NULL; PFNGLCOMPILESHADERARBPROC __glewCompileShaderARB = NULL; PFNGLCREATEPROGRAMOBJECTARBPROC __glewCreateProgramObjectARB = NULL; @@ -978,6 +1082,8 @@ PFNGLUNIFORMMATRIX4FVARBPROC __glewUniformMatrix4fvARB = NULL; PFNGLUSEPROGRAMOBJECTARBPROC __glewUseProgramObjectARB = NULL; PFNGLVALIDATEPROGRAMARBPROC __glewValidateProgramARB = NULL; +PFNGLSHADERSTORAGEBLOCKBINDINGPROC __glewShaderStorageBlockBinding = NULL; + PFNGLGETACTIVESUBROUTINENAMEPROC __glewGetActiveSubroutineName = NULL; PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC __glewGetActiveSubroutineUniformName = NULL; PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC __glewGetActiveSubroutineUniformiv = NULL; @@ -994,6 +1100,9 @@ PFNGLGETNAMEDSTRINGIVARBPROC __glewGetNamedStringivARB = NULL; PFNGLISNAMEDSTRINGARBPROC __glewIsNamedStringARB = NULL; PFNGLNAMEDSTRINGARBPROC __glewNamedStringARB = NULL; +PFNGLTEXPAGECOMMITMENTARBPROC __glewTexPageCommitmentARB = NULL; +PFNGLTEXTUREPAGECOMMITMENTEXTPROC __glewTexturePageCommitmentEXT = NULL; + PFNGLCLIENTWAITSYNCPROC __glewClientWaitSync = NULL; PFNGLDELETESYNCPROC __glewDeleteSync = NULL; PFNGLFENCESYNCPROC __glewFenceSync = NULL; @@ -1007,6 +1116,9 @@ PFNGLPATCHPARAMETERIPROC __glewPatchParameteri = NULL; PFNGLTEXBUFFERARBPROC __glewTexBufferARB = NULL; +PFNGLTEXBUFFERRANGEPROC __glewTexBufferRange = NULL; +PFNGLTEXTUREBUFFERRANGEEXTPROC __glewTextureBufferRangeEXT = NULL; + PFNGLCOMPRESSEDTEXIMAGE1DARBPROC __glewCompressedTexImage1DARB = NULL; PFNGLCOMPRESSEDTEXIMAGE2DARBPROC __glewCompressedTexImage2DARB = NULL; PFNGLCOMPRESSEDTEXIMAGE3DARBPROC __glewCompressedTexImage3DARB = NULL; @@ -1020,6 +1132,20 @@ PFNGLSAMPLEMASKIPROC __glewSampleMaski = NULL; PFNGLTEXIMAGE2DMULTISAMPLEPROC __glewTexImage2DMultisample = NULL; PFNGLTEXIMAGE3DMULTISAMPLEPROC __glewTexImage3DMultisample = NULL; +PFNGLTEXSTORAGE1DPROC __glewTexStorage1D = NULL; +PFNGLTEXSTORAGE2DPROC __glewTexStorage2D = NULL; +PFNGLTEXSTORAGE3DPROC __glewTexStorage3D = NULL; +PFNGLTEXTURESTORAGE1DEXTPROC __glewTextureStorage1DEXT = NULL; +PFNGLTEXTURESTORAGE2DEXTPROC __glewTextureStorage2DEXT = NULL; +PFNGLTEXTURESTORAGE3DEXTPROC __glewTextureStorage3DEXT = NULL; + +PFNGLTEXSTORAGE2DMULTISAMPLEPROC __glewTexStorage2DMultisample = NULL; +PFNGLTEXSTORAGE3DMULTISAMPLEPROC __glewTexStorage3DMultisample = NULL; +PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC __glewTextureStorage2DMultisampleEXT = NULL; +PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC __glewTextureStorage3DMultisampleEXT = NULL; + +PFNGLTEXTUREVIEWPROC __glewTextureView = NULL; + PFNGLGETQUERYOBJECTI64VPROC __glewGetQueryObjecti64v = NULL; PFNGLGETQUERYOBJECTUI64VPROC __glewGetQueryObjectui64v = NULL; PFNGLQUERYCOUNTERPROC __glewQueryCounter = NULL; @@ -1037,6 +1163,9 @@ PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC __glewDrawTransformFeedbackStream = NULL; PFNGLENDQUERYINDEXEDPROC __glewEndQueryIndexed = NULL; PFNGLGETQUERYINDEXEDIVPROC __glewGetQueryIndexediv = NULL; +PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC __glewDrawTransformFeedbackInstanced = NULL; +PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC __glewDrawTransformFeedbackStreamInstanced = NULL; + PFNGLLOADTRANSPOSEMATRIXDARBPROC __glewLoadTransposeMatrixdARB = NULL; PFNGLLOADTRANSPOSEMATRIXFARBPROC __glewLoadTransposeMatrixfARB = NULL; PFNGLMULTTRANSPOSEMATRIXDARBPROC __glewMultTransposeMatrixdARB = NULL; @@ -1069,6 +1198,13 @@ PFNGLVERTEXATTRIBL4DPROC __glewVertexAttribL4d = NULL; PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv = NULL; PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer = NULL; +PFNGLBINDVERTEXBUFFERPROC __glewBindVertexBuffer = NULL; +PFNGLVERTEXATTRIBBINDINGPROC __glewVertexAttribBinding = NULL; +PFNGLVERTEXATTRIBFORMATPROC __glewVertexAttribFormat = NULL; +PFNGLVERTEXATTRIBIFORMATPROC __glewVertexAttribIFormat = NULL; +PFNGLVERTEXATTRIBLFORMATPROC __glewVertexAttribLFormat = NULL; +PFNGLVERTEXBINDINGDIVISORPROC __glewVertexBindingDivisor = NULL; + PFNGLVERTEXBLENDARBPROC __glewVertexBlendARB = NULL; PFNGLWEIGHTPOINTERARBPROC __glewWeightPointerARB = NULL; PFNGLWEIGHTBVARBPROC __glewWeightbvARB = NULL; @@ -1291,6 +1427,14 @@ PFNGLNORMALSTREAM3SATIPROC __glewNormalStream3sATI = NULL; PFNGLNORMALSTREAM3SVATIPROC __glewNormalStream3svATI = NULL; PFNGLVERTEXBLENDENVFATIPROC __glewVertexBlendEnvfATI = NULL; PFNGLVERTEXBLENDENVIATIPROC __glewVertexBlendEnviATI = NULL; +PFNGLVERTEXSTREAM1DATIPROC __glewVertexStream1dATI = NULL; +PFNGLVERTEXSTREAM1DVATIPROC __glewVertexStream1dvATI = NULL; +PFNGLVERTEXSTREAM1FATIPROC __glewVertexStream1fATI = NULL; +PFNGLVERTEXSTREAM1FVATIPROC __glewVertexStream1fvATI = NULL; +PFNGLVERTEXSTREAM1IATIPROC __glewVertexStream1iATI = NULL; +PFNGLVERTEXSTREAM1IVATIPROC __glewVertexStream1ivATI = NULL; +PFNGLVERTEXSTREAM1SATIPROC __glewVertexStream1sATI = NULL; +PFNGLVERTEXSTREAM1SVATIPROC __glewVertexStream1svATI = NULL; PFNGLVERTEXSTREAM2DATIPROC __glewVertexStream2dATI = NULL; PFNGLVERTEXSTREAM2DVATIPROC __glewVertexStream2dvATI = NULL; PFNGLVERTEXSTREAM2FATIPROC __glewVertexStream2fATI = NULL; @@ -1360,6 +1504,10 @@ PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT = NULL; PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT = NULL; PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT = NULL; +PFNGLINSERTEVENTMARKEREXTPROC __glewInsertEventMarkerEXT = NULL; +PFNGLPOPGROUPMARKEREXTPROC __glewPopGroupMarkerEXT = NULL; +PFNGLPUSHGROUPMARKEREXTPROC __glewPushGroupMarkerEXT = NULL; + PFNGLDEPTHBOUNDSEXTPROC __glewDepthBoundsEXT = NULL; PFNGLBINDMULTITEXTUREEXTPROC __glewBindMultiTextureEXT = NULL; @@ -1881,6 +2029,10 @@ PFNGLSECONDARYCOLORPOINTERLISTIBMPROC __glewSecondaryColorPointerListIBM = NULL; PFNGLTEXCOORDPOINTERLISTIBMPROC __glewTexCoordPointerListIBM = NULL; PFNGLVERTEXPOINTERLISTIBMPROC __glewVertexPointerListIBM = NULL; +PFNGLMAPTEXTURE2DINTELPROC __glewMapTexture2DINTEL = NULL; +PFNGLSYNCTEXTUREINTELPROC __glewSyncTextureINTEL = NULL; +PFNGLUNMAPTEXTURE2DINTELPROC __glewUnmapTexture2DINTEL = NULL; + PFNGLCOLORPOINTERVINTELPROC __glewColorPointervINTEL = NULL; PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL = NULL; PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL = NULL; @@ -1889,11 +2041,22 @@ PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL = NULL; PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL = NULL; PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL = NULL; -PFNGLBUFFERREGIONENABLEDEXTPROC __glewBufferRegionEnabledEXT = NULL; -PFNGLDELETEBUFFERREGIONEXTPROC __glewDeleteBufferRegionEXT = NULL; -PFNGLDRAWBUFFERREGIONEXTPROC __glewDrawBufferRegionEXT = NULL; -PFNGLNEWBUFFERREGIONEXTPROC __glewNewBufferRegionEXT = NULL; -PFNGLREADBUFFERREGIONEXTPROC __glewReadBufferRegionEXT = NULL; +PFNGLDEBUGMESSAGECALLBACKPROC __glewDebugMessageCallback = NULL; +PFNGLDEBUGMESSAGECONTROLPROC __glewDebugMessageControl = NULL; +PFNGLDEBUGMESSAGEINSERTPROC __glewDebugMessageInsert = NULL; +PFNGLGETDEBUGMESSAGELOGPROC __glewGetDebugMessageLog = NULL; +PFNGLGETOBJECTLABELPROC __glewGetObjectLabel = NULL; +PFNGLGETOBJECTPTRLABELPROC __glewGetObjectPtrLabel = NULL; +PFNGLOBJECTLABELPROC __glewObjectLabel = NULL; +PFNGLOBJECTPTRLABELPROC __glewObjectPtrLabel = NULL; +PFNGLPOPDEBUGGROUPPROC __glewPopDebugGroup = NULL; +PFNGLPUSHDEBUGGROUPPROC __glewPushDebugGroup = NULL; + +PFNGLBUFFERREGIONENABLEDPROC __glewBufferRegionEnabled = NULL; +PFNGLDELETEBUFFERREGIONPROC __glewDeleteBufferRegion = NULL; +PFNGLDRAWBUFFERREGIONPROC __glewDrawBufferRegion = NULL; +PFNGLNEWBUFFERREGIONPROC __glewNewBufferRegion = NULL; +PFNGLREADBUFFERREGIONPROC __glewReadBufferRegion = NULL; PFNGLRESIZEBUFFERSMESAPROC __glewResizeBuffersMESA = NULL; @@ -1922,6 +2085,29 @@ PFNGLWINDOWPOS4IVMESAPROC __glewWindowPos4ivMESA = NULL; PFNGLWINDOWPOS4SMESAPROC __glewWindowPos4sMESA = NULL; PFNGLWINDOWPOS4SVMESAPROC __glewWindowPos4svMESA = NULL; +PFNGLBEGINCONDITIONALRENDERNVXPROC __glewBeginConditionalRenderNVX = NULL; +PFNGLENDCONDITIONALRENDERNVXPROC __glewEndConditionalRenderNVX = NULL; + +PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC __glewMultiDrawArraysIndirectBindlessNV = NULL; +PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC __glewMultiDrawElementsIndirectBindlessNV = NULL; + +PFNGLGETIMAGEHANDLENVPROC __glewGetImageHandleNV = NULL; +PFNGLGETTEXTUREHANDLENVPROC __glewGetTextureHandleNV = NULL; +PFNGLGETTEXTURESAMPLERHANDLENVPROC __glewGetTextureSamplerHandleNV = NULL; +PFNGLISIMAGEHANDLERESIDENTNVPROC __glewIsImageHandleResidentNV = NULL; +PFNGLISTEXTUREHANDLERESIDENTNVPROC __glewIsTextureHandleResidentNV = NULL; +PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC __glewMakeImageHandleNonResidentNV = NULL; +PFNGLMAKEIMAGEHANDLERESIDENTNVPROC __glewMakeImageHandleResidentNV = NULL; +PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC __glewMakeTextureHandleNonResidentNV = NULL; +PFNGLMAKETEXTUREHANDLERESIDENTNVPROC __glewMakeTextureHandleResidentNV = NULL; +PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC __glewProgramUniformHandleui64NV = NULL; +PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC __glewProgramUniformHandleui64vNV = NULL; +PFNGLUNIFORMHANDLEUI64NVPROC __glewUniformHandleui64NV = NULL; +PFNGLUNIFORMHANDLEUI64VNVPROC __glewUniformHandleui64vNV = NULL; + +PFNGLBLENDBARRIERNVPROC __glewBlendBarrierNV = NULL; +PFNGLBLENDPARAMETERINVPROC __glewBlendParameteriNV = NULL; + PFNGLBEGINCONDITIONALRENDERNVPROC __glewBeginConditionalRenderNV = NULL; PFNGLENDCONDITIONALRENDERNVPROC __glewEndConditionalRenderNV = NULL; @@ -1931,6 +2117,8 @@ PFNGLCLEARDEPTHDNVPROC __glewClearDepthdNV = NULL; PFNGLDEPTHBOUNDSDNVPROC __glewDepthBoundsdNV = NULL; PFNGLDEPTHRANGEDNVPROC __glewDepthRangedNV = NULL; +PFNGLDRAWTEXTURENVPROC __glewDrawTextureNV = NULL; + PFNGLEVALMAPSNVPROC __glewEvalMapsNV = NULL; PFNGLGETMAPATTRIBPARAMETERFVNVPROC __glewGetMapAttribParameterfvNV = NULL; PFNGLGETMAPATTRIBPARAMETERIVNVPROC __glewGetMapAttribParameterivNV = NULL; @@ -2071,6 +2259,56 @@ PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC __glewProgramBufferParametersIivNV = NULL; PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC __glewProgramBufferParametersIuivNV = NULL; PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC __glewProgramBufferParametersfvNV = NULL; +PFNGLCOPYPATHNVPROC __glewCopyPathNV = NULL; +PFNGLCOVERFILLPATHINSTANCEDNVPROC __glewCoverFillPathInstancedNV = NULL; +PFNGLCOVERFILLPATHNVPROC __glewCoverFillPathNV = NULL; +PFNGLCOVERSTROKEPATHINSTANCEDNVPROC __glewCoverStrokePathInstancedNV = NULL; +PFNGLCOVERSTROKEPATHNVPROC __glewCoverStrokePathNV = NULL; +PFNGLDELETEPATHSNVPROC __glewDeletePathsNV = NULL; +PFNGLGENPATHSNVPROC __glewGenPathsNV = NULL; +PFNGLGETPATHCOLORGENFVNVPROC __glewGetPathColorGenfvNV = NULL; +PFNGLGETPATHCOLORGENIVNVPROC __glewGetPathColorGenivNV = NULL; +PFNGLGETPATHCOMMANDSNVPROC __glewGetPathCommandsNV = NULL; +PFNGLGETPATHCOORDSNVPROC __glewGetPathCoordsNV = NULL; +PFNGLGETPATHDASHARRAYNVPROC __glewGetPathDashArrayNV = NULL; +PFNGLGETPATHLENGTHNVPROC __glewGetPathLengthNV = NULL; +PFNGLGETPATHMETRICRANGENVPROC __glewGetPathMetricRangeNV = NULL; +PFNGLGETPATHMETRICSNVPROC __glewGetPathMetricsNV = NULL; +PFNGLGETPATHPARAMETERFVNVPROC __glewGetPathParameterfvNV = NULL; +PFNGLGETPATHPARAMETERIVNVPROC __glewGetPathParameterivNV = NULL; +PFNGLGETPATHSPACINGNVPROC __glewGetPathSpacingNV = NULL; +PFNGLGETPATHTEXGENFVNVPROC __glewGetPathTexGenfvNV = NULL; +PFNGLGETPATHTEXGENIVNVPROC __glewGetPathTexGenivNV = NULL; +PFNGLINTERPOLATEPATHSNVPROC __glewInterpolatePathsNV = NULL; +PFNGLISPATHNVPROC __glewIsPathNV = NULL; +PFNGLISPOINTINFILLPATHNVPROC __glewIsPointInFillPathNV = NULL; +PFNGLISPOINTINSTROKEPATHNVPROC __glewIsPointInStrokePathNV = NULL; +PFNGLPATHCOLORGENNVPROC __glewPathColorGenNV = NULL; +PFNGLPATHCOMMANDSNVPROC __glewPathCommandsNV = NULL; +PFNGLPATHCOORDSNVPROC __glewPathCoordsNV = NULL; +PFNGLPATHCOVERDEPTHFUNCNVPROC __glewPathCoverDepthFuncNV = NULL; +PFNGLPATHDASHARRAYNVPROC __glewPathDashArrayNV = NULL; +PFNGLPATHFOGGENNVPROC __glewPathFogGenNV = NULL; +PFNGLPATHGLYPHRANGENVPROC __glewPathGlyphRangeNV = NULL; +PFNGLPATHGLYPHSNVPROC __glewPathGlyphsNV = NULL; +PFNGLPATHPARAMETERFNVPROC __glewPathParameterfNV = NULL; +PFNGLPATHPARAMETERFVNVPROC __glewPathParameterfvNV = NULL; +PFNGLPATHPARAMETERINVPROC __glewPathParameteriNV = NULL; +PFNGLPATHPARAMETERIVNVPROC __glewPathParameterivNV = NULL; +PFNGLPATHSTENCILDEPTHOFFSETNVPROC __glewPathStencilDepthOffsetNV = NULL; +PFNGLPATHSTENCILFUNCNVPROC __glewPathStencilFuncNV = NULL; +PFNGLPATHSTRINGNVPROC __glewPathStringNV = NULL; +PFNGLPATHSUBCOMMANDSNVPROC __glewPathSubCommandsNV = NULL; +PFNGLPATHSUBCOORDSNVPROC __glewPathSubCoordsNV = NULL; +PFNGLPATHTEXGENNVPROC __glewPathTexGenNV = NULL; +PFNGLPOINTALONGPATHNVPROC __glewPointAlongPathNV = NULL; +PFNGLSTENCILFILLPATHINSTANCEDNVPROC __glewStencilFillPathInstancedNV = NULL; +PFNGLSTENCILFILLPATHNVPROC __glewStencilFillPathNV = NULL; +PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC __glewStencilStrokePathInstancedNV = NULL; +PFNGLSTENCILSTROKEPATHNVPROC __glewStencilStrokePathNV = NULL; +PFNGLTRANSFORMPATHNVPROC __glewTransformPathNV = NULL; +PFNGLWEIGHTPATHSNVPROC __glewWeightPathsNV = NULL; + PFNGLFLUSHPIXELDATARANGENVPROC __glewFlushPixelDataRangeNV = NULL; PFNGLPIXELDATARANGENVPROC __glewPixelDataRangeNV = NULL; @@ -2279,6 +2517,59 @@ PFNGLFRUSTUMFOESPROC __glewFrustumfOES = NULL; PFNGLGETCLIPPLANEFOESPROC __glewGetClipPlanefOES = NULL; PFNGLORTHOFOESPROC __glewOrthofOES = NULL; +PFNGLALPHAFUNCXPROC __glewAlphaFuncx = NULL; +PFNGLCLEARCOLORXPROC __glewClearColorx = NULL; +PFNGLCLEARDEPTHXPROC __glewClearDepthx = NULL; +PFNGLCOLOR4XPROC __glewColor4x = NULL; +PFNGLDEPTHRANGEXPROC __glewDepthRangex = NULL; +PFNGLFOGXPROC __glewFogx = NULL; +PFNGLFOGXVPROC __glewFogxv = NULL; +PFNGLFRUSTUMFPROC __glewFrustumf = NULL; +PFNGLFRUSTUMXPROC __glewFrustumx = NULL; +PFNGLLIGHTMODELXPROC __glewLightModelx = NULL; +PFNGLLIGHTMODELXVPROC __glewLightModelxv = NULL; +PFNGLLIGHTXPROC __glewLightx = NULL; +PFNGLLIGHTXVPROC __glewLightxv = NULL; +PFNGLLINEWIDTHXPROC __glewLineWidthx = NULL; +PFNGLLOADMATRIXXPROC __glewLoadMatrixx = NULL; +PFNGLMATERIALXPROC __glewMaterialx = NULL; +PFNGLMATERIALXVPROC __glewMaterialxv = NULL; +PFNGLMULTMATRIXXPROC __glewMultMatrixx = NULL; +PFNGLMULTITEXCOORD4XPROC __glewMultiTexCoord4x = NULL; +PFNGLNORMAL3XPROC __glewNormal3x = NULL; +PFNGLORTHOFPROC __glewOrthof = NULL; +PFNGLORTHOXPROC __glewOrthox = NULL; +PFNGLPOINTSIZEXPROC __glewPointSizex = NULL; +PFNGLPOLYGONOFFSETXPROC __glewPolygonOffsetx = NULL; +PFNGLROTATEXPROC __glewRotatex = NULL; +PFNGLSAMPLECOVERAGEXPROC __glewSampleCoveragex = NULL; +PFNGLSCALEXPROC __glewScalex = NULL; +PFNGLTEXENVXPROC __glewTexEnvx = NULL; +PFNGLTEXENVXVPROC __glewTexEnvxv = NULL; +PFNGLTEXPARAMETERXPROC __glewTexParameterx = NULL; +PFNGLTRANSLATEXPROC __glewTranslatex = NULL; + +PFNGLCLIPPLANEFPROC __glewClipPlanef = NULL; +PFNGLCLIPPLANEXPROC __glewClipPlanex = NULL; +PFNGLGETCLIPPLANEFPROC __glewGetClipPlanef = NULL; +PFNGLGETCLIPPLANEXPROC __glewGetClipPlanex = NULL; +PFNGLGETFIXEDVPROC __glewGetFixedv = NULL; +PFNGLGETLIGHTXVPROC __glewGetLightxv = NULL; +PFNGLGETMATERIALXVPROC __glewGetMaterialxv = NULL; +PFNGLGETTEXENVXVPROC __glewGetTexEnvxv = NULL; +PFNGLGETTEXPARAMETERXVPROC __glewGetTexParameterxv = NULL; +PFNGLPOINTPARAMETERXPROC __glewPointParameterx = NULL; +PFNGLPOINTPARAMETERXVPROC __glewPointParameterxv = NULL; +PFNGLPOINTSIZEPOINTEROESPROC __glewPointSizePointerOES = NULL; +PFNGLTEXPARAMETERXVPROC __glewTexParameterxv = NULL; + +PFNGLERRORSTRINGREGALPROC __glewErrorStringREGAL = NULL; + +PFNGLGETEXTENSIONREGALPROC __glewGetExtensionREGAL = NULL; +PFNGLISSUPPORTEDREGALPROC __glewIsSupportedREGAL = NULL; + +PFNGLLOGMESSAGECALLBACKREGALPROC __glewLogMessageCallbackREGAL = NULL; + PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS = NULL; PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS = NULL; @@ -2429,6 +2720,9 @@ GLboolean __GLEW_VERSION_3_2 = GL_FALSE; GLboolean __GLEW_VERSION_3_3 = GL_FALSE; GLboolean __GLEW_VERSION_4_0 = GL_FALSE; GLboolean __GLEW_VERSION_4_1 = GL_FALSE; +GLboolean __GLEW_VERSION_4_2 = GL_FALSE; +GLboolean __GLEW_VERSION_4_3 = GL_FALSE; +GLboolean __GLEW_VERSION_4_4 = GL_FALSE; GLboolean __GLEW_3DFX_multisample = GL_FALSE; GLboolean __GLEW_3DFX_tbuffer = GL_FALSE; GLboolean __GLEW_3DFX_texture_compression_FXT1 = GL_FALSE; @@ -2437,14 +2731,35 @@ GLboolean __GLEW_AMD_conservative_depth = GL_FALSE; GLboolean __GLEW_AMD_debug_output = GL_FALSE; GLboolean __GLEW_AMD_depth_clamp_separate = GL_FALSE; GLboolean __GLEW_AMD_draw_buffers_blend = GL_FALSE; +GLboolean __GLEW_AMD_interleaved_elements = GL_FALSE; +GLboolean __GLEW_AMD_multi_draw_indirect = GL_FALSE; GLboolean __GLEW_AMD_name_gen_delete = GL_FALSE; GLboolean __GLEW_AMD_performance_monitor = GL_FALSE; +GLboolean __GLEW_AMD_pinned_memory = GL_FALSE; +GLboolean __GLEW_AMD_query_buffer_object = GL_FALSE; GLboolean __GLEW_AMD_sample_positions = GL_FALSE; GLboolean __GLEW_AMD_seamless_cubemap_per_texture = GL_FALSE; GLboolean __GLEW_AMD_shader_stencil_export = GL_FALSE; +GLboolean __GLEW_AMD_shader_trinary_minmax = GL_FALSE; +GLboolean __GLEW_AMD_sparse_texture = GL_FALSE; +GLboolean __GLEW_AMD_stencil_operation_extended = GL_FALSE; GLboolean __GLEW_AMD_texture_texture4 = GL_FALSE; GLboolean __GLEW_AMD_transform_feedback3_lines_triangles = GL_FALSE; +GLboolean __GLEW_AMD_vertex_shader_layer = GL_FALSE; GLboolean __GLEW_AMD_vertex_shader_tessellator = GL_FALSE; +GLboolean __GLEW_AMD_vertex_shader_viewport_index = GL_FALSE; +GLboolean __GLEW_ANGLE_depth_texture = GL_FALSE; +GLboolean __GLEW_ANGLE_framebuffer_blit = GL_FALSE; +GLboolean __GLEW_ANGLE_framebuffer_multisample = GL_FALSE; +GLboolean __GLEW_ANGLE_instanced_arrays = GL_FALSE; +GLboolean __GLEW_ANGLE_pack_reverse_row_order = GL_FALSE; +GLboolean __GLEW_ANGLE_program_binary = GL_FALSE; +GLboolean __GLEW_ANGLE_texture_compression_dxt1 = GL_FALSE; +GLboolean __GLEW_ANGLE_texture_compression_dxt3 = GL_FALSE; +GLboolean __GLEW_ANGLE_texture_compression_dxt5 = GL_FALSE; +GLboolean __GLEW_ANGLE_texture_usage = GL_FALSE; +GLboolean __GLEW_ANGLE_timer_query = GL_FALSE; +GLboolean __GLEW_ANGLE_translated_shader_source = GL_FALSE; GLboolean __GLEW_APPLE_aux_depth_stencil = GL_FALSE; GLboolean __GLEW_APPLE_client_storage = GL_FALSE; GLboolean __GLEW_APPLE_element_array = GL_FALSE; @@ -2463,11 +2778,23 @@ GLboolean __GLEW_APPLE_vertex_array_range = GL_FALSE; GLboolean __GLEW_APPLE_vertex_program_evaluators = GL_FALSE; GLboolean __GLEW_APPLE_ycbcr_422 = GL_FALSE; GLboolean __GLEW_ARB_ES2_compatibility = GL_FALSE; +GLboolean __GLEW_ARB_ES3_compatibility = GL_FALSE; +GLboolean __GLEW_ARB_arrays_of_arrays = GL_FALSE; +GLboolean __GLEW_ARB_base_instance = GL_FALSE; +GLboolean __GLEW_ARB_bindless_texture = GL_FALSE; GLboolean __GLEW_ARB_blend_func_extended = GL_FALSE; +GLboolean __GLEW_ARB_buffer_storage = GL_FALSE; GLboolean __GLEW_ARB_cl_event = GL_FALSE; +GLboolean __GLEW_ARB_clear_buffer_object = GL_FALSE; +GLboolean __GLEW_ARB_clear_texture = GL_FALSE; GLboolean __GLEW_ARB_color_buffer_float = GL_FALSE; GLboolean __GLEW_ARB_compatibility = GL_FALSE; +GLboolean __GLEW_ARB_compressed_texture_pixel_storage = GL_FALSE; +GLboolean __GLEW_ARB_compute_shader = GL_FALSE; +GLboolean __GLEW_ARB_compute_variable_group_size = GL_FALSE; +GLboolean __GLEW_ARB_conservative_depth = GL_FALSE; GLboolean __GLEW_ARB_copy_buffer = GL_FALSE; +GLboolean __GLEW_ARB_copy_image = GL_FALSE; GLboolean __GLEW_ARB_debug_output = GL_FALSE; GLboolean __GLEW_ARB_depth_buffer_float = GL_FALSE; GLboolean __GLEW_ARB_depth_clamp = GL_FALSE; @@ -2477,11 +2804,15 @@ GLboolean __GLEW_ARB_draw_buffers_blend = GL_FALSE; GLboolean __GLEW_ARB_draw_elements_base_vertex = GL_FALSE; GLboolean __GLEW_ARB_draw_indirect = GL_FALSE; GLboolean __GLEW_ARB_draw_instanced = GL_FALSE; +GLboolean __GLEW_ARB_enhanced_layouts = GL_FALSE; GLboolean __GLEW_ARB_explicit_attrib_location = GL_FALSE; +GLboolean __GLEW_ARB_explicit_uniform_location = GL_FALSE; GLboolean __GLEW_ARB_fragment_coord_conventions = GL_FALSE; +GLboolean __GLEW_ARB_fragment_layer_viewport = GL_FALSE; GLboolean __GLEW_ARB_fragment_program = GL_FALSE; GLboolean __GLEW_ARB_fragment_program_shadow = GL_FALSE; GLboolean __GLEW_ARB_fragment_shader = GL_FALSE; +GLboolean __GLEW_ARB_framebuffer_no_attachments = GL_FALSE; GLboolean __GLEW_ARB_framebuffer_object = GL_FALSE; GLboolean __GLEW_ARB_framebuffer_sRGB = GL_FALSE; GLboolean __GLEW_ARB_geometry_shader4 = GL_FALSE; @@ -2491,9 +2822,16 @@ GLboolean __GLEW_ARB_gpu_shader_fp64 = GL_FALSE; GLboolean __GLEW_ARB_half_float_pixel = GL_FALSE; GLboolean __GLEW_ARB_half_float_vertex = GL_FALSE; GLboolean __GLEW_ARB_imaging = GL_FALSE; +GLboolean __GLEW_ARB_indirect_parameters = GL_FALSE; GLboolean __GLEW_ARB_instanced_arrays = GL_FALSE; +GLboolean __GLEW_ARB_internalformat_query = GL_FALSE; +GLboolean __GLEW_ARB_internalformat_query2 = GL_FALSE; +GLboolean __GLEW_ARB_invalidate_subdata = GL_FALSE; +GLboolean __GLEW_ARB_map_buffer_alignment = GL_FALSE; GLboolean __GLEW_ARB_map_buffer_range = GL_FALSE; GLboolean __GLEW_ARB_matrix_palette = GL_FALSE; +GLboolean __GLEW_ARB_multi_bind = GL_FALSE; +GLboolean __GLEW_ARB_multi_draw_indirect = GL_FALSE; GLboolean __GLEW_ARB_multisample = GL_FALSE; GLboolean __GLEW_ARB_multitexture = GL_FALSE; GLboolean __GLEW_ARB_occlusion_query = GL_FALSE; @@ -2501,27 +2839,44 @@ GLboolean __GLEW_ARB_occlusion_query2 = GL_FALSE; GLboolean __GLEW_ARB_pixel_buffer_object = GL_FALSE; GLboolean __GLEW_ARB_point_parameters = GL_FALSE; GLboolean __GLEW_ARB_point_sprite = GL_FALSE; +GLboolean __GLEW_ARB_program_interface_query = GL_FALSE; GLboolean __GLEW_ARB_provoking_vertex = GL_FALSE; +GLboolean __GLEW_ARB_query_buffer_object = GL_FALSE; +GLboolean __GLEW_ARB_robust_buffer_access_behavior = GL_FALSE; GLboolean __GLEW_ARB_robustness = GL_FALSE; +GLboolean __GLEW_ARB_robustness_application_isolation = GL_FALSE; +GLboolean __GLEW_ARB_robustness_share_group_isolation = GL_FALSE; GLboolean __GLEW_ARB_sample_shading = GL_FALSE; GLboolean __GLEW_ARB_sampler_objects = GL_FALSE; GLboolean __GLEW_ARB_seamless_cube_map = GL_FALSE; +GLboolean __GLEW_ARB_seamless_cubemap_per_texture = GL_FALSE; GLboolean __GLEW_ARB_separate_shader_objects = GL_FALSE; +GLboolean __GLEW_ARB_shader_atomic_counters = GL_FALSE; GLboolean __GLEW_ARB_shader_bit_encoding = GL_FALSE; +GLboolean __GLEW_ARB_shader_draw_parameters = GL_FALSE; +GLboolean __GLEW_ARB_shader_group_vote = GL_FALSE; +GLboolean __GLEW_ARB_shader_image_load_store = GL_FALSE; +GLboolean __GLEW_ARB_shader_image_size = GL_FALSE; GLboolean __GLEW_ARB_shader_objects = GL_FALSE; GLboolean __GLEW_ARB_shader_precision = GL_FALSE; GLboolean __GLEW_ARB_shader_stencil_export = GL_FALSE; +GLboolean __GLEW_ARB_shader_storage_buffer_object = GL_FALSE; GLboolean __GLEW_ARB_shader_subroutine = GL_FALSE; GLboolean __GLEW_ARB_shader_texture_lod = GL_FALSE; GLboolean __GLEW_ARB_shading_language_100 = GL_FALSE; +GLboolean __GLEW_ARB_shading_language_420pack = GL_FALSE; GLboolean __GLEW_ARB_shading_language_include = GL_FALSE; +GLboolean __GLEW_ARB_shading_language_packing = GL_FALSE; GLboolean __GLEW_ARB_shadow = GL_FALSE; GLboolean __GLEW_ARB_shadow_ambient = GL_FALSE; +GLboolean __GLEW_ARB_sparse_texture = GL_FALSE; +GLboolean __GLEW_ARB_stencil_texturing = GL_FALSE; GLboolean __GLEW_ARB_sync = GL_FALSE; GLboolean __GLEW_ARB_tessellation_shader = GL_FALSE; GLboolean __GLEW_ARB_texture_border_clamp = GL_FALSE; GLboolean __GLEW_ARB_texture_buffer_object = GL_FALSE; GLboolean __GLEW_ARB_texture_buffer_object_rgb32 = GL_FALSE; +GLboolean __GLEW_ARB_texture_buffer_range = GL_FALSE; GLboolean __GLEW_ARB_texture_compression = GL_FALSE; GLboolean __GLEW_ARB_texture_compression_bptc = GL_FALSE; GLboolean __GLEW_ARB_texture_compression_rgtc = GL_FALSE; @@ -2533,26 +2888,35 @@ GLboolean __GLEW_ARB_texture_env_crossbar = GL_FALSE; GLboolean __GLEW_ARB_texture_env_dot3 = GL_FALSE; GLboolean __GLEW_ARB_texture_float = GL_FALSE; GLboolean __GLEW_ARB_texture_gather = GL_FALSE; +GLboolean __GLEW_ARB_texture_mirror_clamp_to_edge = GL_FALSE; GLboolean __GLEW_ARB_texture_mirrored_repeat = GL_FALSE; GLboolean __GLEW_ARB_texture_multisample = GL_FALSE; GLboolean __GLEW_ARB_texture_non_power_of_two = GL_FALSE; +GLboolean __GLEW_ARB_texture_query_levels = GL_FALSE; GLboolean __GLEW_ARB_texture_query_lod = GL_FALSE; GLboolean __GLEW_ARB_texture_rectangle = GL_FALSE; GLboolean __GLEW_ARB_texture_rg = GL_FALSE; GLboolean __GLEW_ARB_texture_rgb10_a2ui = GL_FALSE; +GLboolean __GLEW_ARB_texture_stencil8 = GL_FALSE; +GLboolean __GLEW_ARB_texture_storage = GL_FALSE; +GLboolean __GLEW_ARB_texture_storage_multisample = GL_FALSE; GLboolean __GLEW_ARB_texture_swizzle = GL_FALSE; +GLboolean __GLEW_ARB_texture_view = GL_FALSE; GLboolean __GLEW_ARB_timer_query = GL_FALSE; GLboolean __GLEW_ARB_transform_feedback2 = GL_FALSE; GLboolean __GLEW_ARB_transform_feedback3 = GL_FALSE; +GLboolean __GLEW_ARB_transform_feedback_instanced = GL_FALSE; GLboolean __GLEW_ARB_transpose_matrix = GL_FALSE; GLboolean __GLEW_ARB_uniform_buffer_object = GL_FALSE; GLboolean __GLEW_ARB_vertex_array_bgra = GL_FALSE; GLboolean __GLEW_ARB_vertex_array_object = GL_FALSE; GLboolean __GLEW_ARB_vertex_attrib_64bit = GL_FALSE; +GLboolean __GLEW_ARB_vertex_attrib_binding = GL_FALSE; GLboolean __GLEW_ARB_vertex_blend = GL_FALSE; GLboolean __GLEW_ARB_vertex_buffer_object = GL_FALSE; GLboolean __GLEW_ARB_vertex_program = GL_FALSE; GLboolean __GLEW_ARB_vertex_shader = GL_FALSE; +GLboolean __GLEW_ARB_vertex_type_10f_11f_11f_rev = GL_FALSE; GLboolean __GLEW_ARB_vertex_type_2_10_10_10_rev = GL_FALSE; GLboolean __GLEW_ARB_viewport_array = GL_FALSE; GLboolean __GLEW_ARB_window_pos = GL_FALSE; @@ -2596,6 +2960,7 @@ GLboolean __GLEW_EXT_convolution = GL_FALSE; GLboolean __GLEW_EXT_coordinate_frame = GL_FALSE; GLboolean __GLEW_EXT_copy_texture = GL_FALSE; GLboolean __GLEW_EXT_cull_vertex = GL_FALSE; +GLboolean __GLEW_EXT_debug_marker = GL_FALSE; GLboolean __GLEW_EXT_depth_bounds_test = GL_FALSE; GLboolean __GLEW_EXT_direct_state_access = GL_FALSE; GLboolean __GLEW_EXT_draw_buffers2 = GL_FALSE; @@ -2605,6 +2970,7 @@ GLboolean __GLEW_EXT_fog_coord = GL_FALSE; GLboolean __GLEW_EXT_fragment_lighting = GL_FALSE; GLboolean __GLEW_EXT_framebuffer_blit = GL_FALSE; GLboolean __GLEW_EXT_framebuffer_multisample = GL_FALSE; +GLboolean __GLEW_EXT_framebuffer_multisample_blit_scaled = GL_FALSE; GLboolean __GLEW_EXT_framebuffer_object = GL_FALSE; GLboolean __GLEW_EXT_framebuffer_sRGB = GL_FALSE; GLboolean __GLEW_EXT_geometry_shader4 = GL_FALSE; @@ -2689,22 +3055,33 @@ GLboolean __GLEW_IBM_texture_mirrored_repeat = GL_FALSE; GLboolean __GLEW_IBM_vertex_array_lists = GL_FALSE; GLboolean __GLEW_INGR_color_clamp = GL_FALSE; GLboolean __GLEW_INGR_interlace_read = GL_FALSE; +GLboolean __GLEW_INTEL_map_texture = GL_FALSE; GLboolean __GLEW_INTEL_parallel_arrays = GL_FALSE; GLboolean __GLEW_INTEL_texture_scissor = GL_FALSE; +GLboolean __GLEW_KHR_debug = GL_FALSE; +GLboolean __GLEW_KHR_texture_compression_astc_ldr = GL_FALSE; GLboolean __GLEW_KTX_buffer_region = GL_FALSE; GLboolean __GLEW_MESAX_texture_stack = GL_FALSE; GLboolean __GLEW_MESA_pack_invert = GL_FALSE; GLboolean __GLEW_MESA_resize_buffers = GL_FALSE; GLboolean __GLEW_MESA_window_pos = GL_FALSE; GLboolean __GLEW_MESA_ycbcr_texture = GL_FALSE; +GLboolean __GLEW_NVX_conditional_render = GL_FALSE; GLboolean __GLEW_NVX_gpu_memory_info = GL_FALSE; +GLboolean __GLEW_NV_bindless_multi_draw_indirect = GL_FALSE; +GLboolean __GLEW_NV_bindless_texture = GL_FALSE; +GLboolean __GLEW_NV_blend_equation_advanced = GL_FALSE; +GLboolean __GLEW_NV_blend_equation_advanced_coherent = GL_FALSE; GLboolean __GLEW_NV_blend_square = GL_FALSE; +GLboolean __GLEW_NV_compute_program5 = GL_FALSE; GLboolean __GLEW_NV_conditional_render = GL_FALSE; GLboolean __GLEW_NV_copy_depth_to_color = GL_FALSE; GLboolean __GLEW_NV_copy_image = GL_FALSE; +GLboolean __GLEW_NV_deep_texture3D = GL_FALSE; GLboolean __GLEW_NV_depth_buffer_float = GL_FALSE; GLboolean __GLEW_NV_depth_clamp = GL_FALSE; GLboolean __GLEW_NV_depth_range_unclamped = GL_FALSE; +GLboolean __GLEW_NV_draw_texture = GL_FALSE; GLboolean __GLEW_NV_evaluators = GL_FALSE; GLboolean __GLEW_NV_explicit_multisample = GL_FALSE; GLboolean __GLEW_NV_fence = GL_FALSE; @@ -2719,6 +3096,7 @@ GLboolean __GLEW_NV_geometry_program4 = GL_FALSE; GLboolean __GLEW_NV_geometry_shader4 = GL_FALSE; GLboolean __GLEW_NV_gpu_program4 = GL_FALSE; GLboolean __GLEW_NV_gpu_program5 = GL_FALSE; +GLboolean __GLEW_NV_gpu_program5_mem_extended = GL_FALSE; GLboolean __GLEW_NV_gpu_program_fp64 = GL_FALSE; GLboolean __GLEW_NV_gpu_shader5 = GL_FALSE; GLboolean __GLEW_NV_half_float = GL_FALSE; @@ -2729,13 +3107,17 @@ GLboolean __GLEW_NV_occlusion_query = GL_FALSE; GLboolean __GLEW_NV_packed_depth_stencil = GL_FALSE; GLboolean __GLEW_NV_parameter_buffer_object = GL_FALSE; GLboolean __GLEW_NV_parameter_buffer_object2 = GL_FALSE; +GLboolean __GLEW_NV_path_rendering = GL_FALSE; GLboolean __GLEW_NV_pixel_data_range = GL_FALSE; GLboolean __GLEW_NV_point_sprite = GL_FALSE; GLboolean __GLEW_NV_present_video = GL_FALSE; GLboolean __GLEW_NV_primitive_restart = GL_FALSE; GLboolean __GLEW_NV_register_combiners = GL_FALSE; GLboolean __GLEW_NV_register_combiners2 = GL_FALSE; +GLboolean __GLEW_NV_shader_atomic_counters = GL_FALSE; +GLboolean __GLEW_NV_shader_atomic_float = GL_FALSE; GLboolean __GLEW_NV_shader_buffer_load = GL_FALSE; +GLboolean __GLEW_NV_shader_storage_buffer_object = GL_FALSE; GLboolean __GLEW_NV_tessellation_program5 = GL_FALSE; GLboolean __GLEW_NV_texgen_emboss = GL_FALSE; GLboolean __GLEW_NV_texgen_reflection = GL_FALSE; @@ -2771,6 +3153,12 @@ GLboolean __GLEW_OML_resample = GL_FALSE; GLboolean __GLEW_OML_subsample = GL_FALSE; GLboolean __GLEW_PGI_misc_hints = GL_FALSE; GLboolean __GLEW_PGI_vertex_hints = GL_FALSE; +GLboolean __GLEW_REGAL_ES1_0_compatibility = GL_FALSE; +GLboolean __GLEW_REGAL_ES1_1_compatibility = GL_FALSE; +GLboolean __GLEW_REGAL_enable = GL_FALSE; +GLboolean __GLEW_REGAL_error_string = GL_FALSE; +GLboolean __GLEW_REGAL_extension_query = GL_FALSE; +GLboolean __GLEW_REGAL_log = GL_FALSE; GLboolean __GLEW_REND_screen_coordinates = GL_FALSE; GLboolean __GLEW_S3_s3tc = GL_FALSE; GLboolean __GLEW_SGIS_color_range = GL_FALSE; @@ -3259,6 +3647,18 @@ static GLboolean _glewInit_GL_VERSION_4_0 (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_VERSION_4_1 */ +#ifdef GL_VERSION_4_2 + +#endif /* GL_VERSION_4_2 */ + +#ifdef GL_VERSION_4_3 + +#endif /* GL_VERSION_4_3 */ + +#ifdef GL_VERSION_4_4 + +#endif /* GL_VERSION_4_4 */ + #ifdef GL_3DFX_multisample #endif /* GL_3DFX_multisample */ @@ -3324,6 +3724,33 @@ static GLboolean _glewInit_GL_AMD_draw_buffers_blend (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_AMD_draw_buffers_blend */ +#ifdef GL_AMD_interleaved_elements + +static GLboolean _glewInit_GL_AMD_interleaved_elements (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glVertexAttribParameteriAMD = (PFNGLVERTEXATTRIBPARAMETERIAMDPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribParameteriAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_interleaved_elements */ + +#ifdef GL_AMD_multi_draw_indirect + +static GLboolean _glewInit_GL_AMD_multi_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMultiDrawArraysIndirectAMD = (PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysIndirectAMD")) == NULL) || r; + r = ((glMultiDrawElementsIndirectAMD = (PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsIndirectAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_multi_draw_indirect */ + #ifdef GL_AMD_name_gen_delete static GLboolean _glewInit_GL_AMD_name_gen_delete (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3362,6 +3789,14 @@ static GLboolean _glewInit_GL_AMD_performance_monitor (GLEW_CONTEXT_ARG_DEF_INIT #endif /* GL_AMD_performance_monitor */ +#ifdef GL_AMD_pinned_memory + +#endif /* GL_AMD_pinned_memory */ + +#ifdef GL_AMD_query_buffer_object + +#endif /* GL_AMD_query_buffer_object */ + #ifdef GL_AMD_sample_positions static GLboolean _glewInit_GL_AMD_sample_positions (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3383,6 +3818,37 @@ static GLboolean _glewInit_GL_AMD_sample_positions (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_AMD_shader_stencil_export */ +#ifdef GL_AMD_shader_trinary_minmax + +#endif /* GL_AMD_shader_trinary_minmax */ + +#ifdef GL_AMD_sparse_texture + +static GLboolean _glewInit_GL_AMD_sparse_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexStorageSparseAMD = (PFNGLTEXSTORAGESPARSEAMDPROC)glewGetProcAddress((const GLubyte*)"glTexStorageSparseAMD")) == NULL) || r; + r = ((glTextureStorageSparseAMD = (PFNGLTEXTURESTORAGESPARSEAMDPROC)glewGetProcAddress((const GLubyte*)"glTextureStorageSparseAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_sparse_texture */ + +#ifdef GL_AMD_stencil_operation_extended + +static GLboolean _glewInit_GL_AMD_stencil_operation_extended (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glStencilOpValueAMD = (PFNGLSTENCILOPVALUEAMDPROC)glewGetProcAddress((const GLubyte*)"glStencilOpValueAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_stencil_operation_extended */ + #ifdef GL_AMD_texture_texture4 #endif /* GL_AMD_texture_texture4 */ @@ -3391,6 +3857,10 @@ static GLboolean _glewInit_GL_AMD_sample_positions (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_AMD_transform_feedback3_lines_triangles */ +#ifdef GL_AMD_vertex_shader_layer + +#endif /* GL_AMD_vertex_shader_layer */ + #ifdef GL_AMD_vertex_shader_tessellator static GLboolean _glewInit_GL_AMD_vertex_shader_tessellator (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3405,6 +3875,115 @@ static GLboolean _glewInit_GL_AMD_vertex_shader_tessellator (GLEW_CONTEXT_ARG_DE #endif /* GL_AMD_vertex_shader_tessellator */ +#ifdef GL_AMD_vertex_shader_viewport_index + +#endif /* GL_AMD_vertex_shader_viewport_index */ + +#ifdef GL_ANGLE_depth_texture + +#endif /* GL_ANGLE_depth_texture */ + +#ifdef GL_ANGLE_framebuffer_blit + +static GLboolean _glewInit_GL_ANGLE_framebuffer_blit (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlitFramebufferANGLE = (PFNGLBLITFRAMEBUFFERANGLEPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebufferANGLE")) == NULL) || r; + + return r; +} + +#endif /* GL_ANGLE_framebuffer_blit */ + +#ifdef GL_ANGLE_framebuffer_multisample + +static GLboolean _glewInit_GL_ANGLE_framebuffer_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glRenderbufferStorageMultisampleANGLE = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC)glewGetProcAddress((const GLubyte*)"glRenderbufferStorageMultisampleANGLE")) == NULL) || r; + + return r; +} + +#endif /* GL_ANGLE_framebuffer_multisample */ + +#ifdef GL_ANGLE_instanced_arrays + +static GLboolean _glewInit_GL_ANGLE_instanced_arrays (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawArraysInstancedANGLE = (PFNGLDRAWARRAYSINSTANCEDANGLEPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedANGLE")) == NULL) || r; + r = ((glDrawElementsInstancedANGLE = (PFNGLDRAWELEMENTSINSTANCEDANGLEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedANGLE")) == NULL) || r; + r = ((glVertexAttribDivisorANGLE = (PFNGLVERTEXATTRIBDIVISORANGLEPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribDivisorANGLE")) == NULL) || r; + + return r; +} + +#endif /* GL_ANGLE_instanced_arrays */ + +#ifdef GL_ANGLE_pack_reverse_row_order + +#endif /* GL_ANGLE_pack_reverse_row_order */ + +#ifdef GL_ANGLE_program_binary + +#endif /* GL_ANGLE_program_binary */ + +#ifdef GL_ANGLE_texture_compression_dxt1 + +#endif /* GL_ANGLE_texture_compression_dxt1 */ + +#ifdef GL_ANGLE_texture_compression_dxt3 + +#endif /* GL_ANGLE_texture_compression_dxt3 */ + +#ifdef GL_ANGLE_texture_compression_dxt5 + +#endif /* GL_ANGLE_texture_compression_dxt5 */ + +#ifdef GL_ANGLE_texture_usage + +#endif /* GL_ANGLE_texture_usage */ + +#ifdef GL_ANGLE_timer_query + +static GLboolean _glewInit_GL_ANGLE_timer_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginQueryANGLE = (PFNGLBEGINQUERYANGLEPROC)glewGetProcAddress((const GLubyte*)"glBeginQueryANGLE")) == NULL) || r; + r = ((glDeleteQueriesANGLE = (PFNGLDELETEQUERIESANGLEPROC)glewGetProcAddress((const GLubyte*)"glDeleteQueriesANGLE")) == NULL) || r; + r = ((glEndQueryANGLE = (PFNGLENDQUERYANGLEPROC)glewGetProcAddress((const GLubyte*)"glEndQueryANGLE")) == NULL) || r; + r = ((glGenQueriesANGLE = (PFNGLGENQUERIESANGLEPROC)glewGetProcAddress((const GLubyte*)"glGenQueriesANGLE")) == NULL) || r; + r = ((glGetQueryObjecti64vANGLE = (PFNGLGETQUERYOBJECTI64VANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjecti64vANGLE")) == NULL) || r; + r = ((glGetQueryObjectivANGLE = (PFNGLGETQUERYOBJECTIVANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectivANGLE")) == NULL) || r; + r = ((glGetQueryObjectui64vANGLE = (PFNGLGETQUERYOBJECTUI64VANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectui64vANGLE")) == NULL) || r; + r = ((glGetQueryObjectuivANGLE = (PFNGLGETQUERYOBJECTUIVANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetQueryObjectuivANGLE")) == NULL) || r; + r = ((glGetQueryivANGLE = (PFNGLGETQUERYIVANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetQueryivANGLE")) == NULL) || r; + r = ((glIsQueryANGLE = (PFNGLISQUERYANGLEPROC)glewGetProcAddress((const GLubyte*)"glIsQueryANGLE")) == NULL) || r; + r = ((glQueryCounterANGLE = (PFNGLQUERYCOUNTERANGLEPROC)glewGetProcAddress((const GLubyte*)"glQueryCounterANGLE")) == NULL) || r; + + return r; +} + +#endif /* GL_ANGLE_timer_query */ + +#ifdef GL_ANGLE_translated_shader_source + +static GLboolean _glewInit_GL_ANGLE_translated_shader_source (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetTranslatedShaderSourceANGLE = (PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC)glewGetProcAddress((const GLubyte*)"glGetTranslatedShaderSourceANGLE")) == NULL) || r; + + return r; +} + +#endif /* GL_ANGLE_translated_shader_source */ + #ifdef GL_APPLE_aux_depth_stencil #endif /* GL_APPLE_aux_depth_stencil */ @@ -3588,6 +4167,57 @@ static GLboolean _glewInit_GL_ARB_ES2_compatibility (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_ES2_compatibility */ +#ifdef GL_ARB_ES3_compatibility + +#endif /* GL_ARB_ES3_compatibility */ + +#ifdef GL_ARB_arrays_of_arrays + +#endif /* GL_ARB_arrays_of_arrays */ + +#ifdef GL_ARB_base_instance + +static GLboolean _glewInit_GL_ARB_base_instance (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawArraysInstancedBaseInstance = (PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)glewGetProcAddress((const GLubyte*)"glDrawArraysInstancedBaseInstance")) == NULL) || r; + r = ((glDrawElementsInstancedBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedBaseInstance")) == NULL) || r; + r = ((glDrawElementsInstancedBaseVertexBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)glewGetProcAddress((const GLubyte*)"glDrawElementsInstancedBaseVertexBaseInstance")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_base_instance */ + +#ifdef GL_ARB_bindless_texture + +static GLboolean _glewInit_GL_ARB_bindless_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetImageHandleARB = (PFNGLGETIMAGEHANDLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetImageHandleARB")) == NULL) || r; + r = ((glGetTextureHandleARB = (PFNGLGETTEXTUREHANDLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetTextureHandleARB")) == NULL) || r; + r = ((glGetTextureSamplerHandleARB = (PFNGLGETTEXTURESAMPLERHANDLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetTextureSamplerHandleARB")) == NULL) || r; + r = ((glGetVertexAttribLui64vARB = (PFNGLGETVERTEXATTRIBLUI64VARBPROC)glewGetProcAddress((const GLubyte*)"glGetVertexAttribLui64vARB")) == NULL) || r; + r = ((glIsImageHandleResidentARB = (PFNGLISIMAGEHANDLERESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glIsImageHandleResidentARB")) == NULL) || r; + r = ((glIsTextureHandleResidentARB = (PFNGLISTEXTUREHANDLERESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glIsTextureHandleResidentARB")) == NULL) || r; + r = ((glMakeImageHandleNonResidentARB = (PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glMakeImageHandleNonResidentARB")) == NULL) || r; + r = ((glMakeImageHandleResidentARB = (PFNGLMAKEIMAGEHANDLERESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glMakeImageHandleResidentARB")) == NULL) || r; + r = ((glMakeTextureHandleNonResidentARB = (PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glMakeTextureHandleNonResidentARB")) == NULL) || r; + r = ((glMakeTextureHandleResidentARB = (PFNGLMAKETEXTUREHANDLERESIDENTARBPROC)glewGetProcAddress((const GLubyte*)"glMakeTextureHandleResidentARB")) == NULL) || r; + r = ((glProgramUniformHandleui64ARB = (PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformHandleui64ARB")) == NULL) || r; + r = ((glProgramUniformHandleui64vARB = (PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformHandleui64vARB")) == NULL) || r; + r = ((glUniformHandleui64ARB = (PFNGLUNIFORMHANDLEUI64ARBPROC)glewGetProcAddress((const GLubyte*)"glUniformHandleui64ARB")) == NULL) || r; + r = ((glUniformHandleui64vARB = (PFNGLUNIFORMHANDLEUI64VARBPROC)glewGetProcAddress((const GLubyte*)"glUniformHandleui64vARB")) == NULL) || r; + r = ((glVertexAttribL1ui64ARB = (PFNGLVERTEXATTRIBL1UI64ARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1ui64ARB")) == NULL) || r; + r = ((glVertexAttribL1ui64vARB = (PFNGLVERTEXATTRIBL1UI64VARBPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribL1ui64vARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_bindless_texture */ + #ifdef GL_ARB_blend_func_extended static GLboolean _glewInit_GL_ARB_blend_func_extended (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3602,6 +4232,20 @@ static GLboolean _glewInit_GL_ARB_blend_func_extended (GLEW_CONTEXT_ARG_DEF_INIT #endif /* GL_ARB_blend_func_extended */ +#ifdef GL_ARB_buffer_storage + +static GLboolean _glewInit_GL_ARB_buffer_storage (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBufferStorage = (PFNGLBUFFERSTORAGEPROC)glewGetProcAddress((const GLubyte*)"glBufferStorage")) == NULL) || r; + r = ((glNamedBufferStorageEXT = (PFNGLNAMEDBUFFERSTORAGEEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedBufferStorageEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_buffer_storage */ + #ifdef GL_ARB_cl_event static GLboolean _glewInit_GL_ARB_cl_event (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3615,6 +4259,36 @@ static GLboolean _glewInit_GL_ARB_cl_event (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_cl_event */ +#ifdef GL_ARB_clear_buffer_object + +static GLboolean _glewInit_GL_ARB_clear_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClearBufferData = (PFNGLCLEARBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glClearBufferData")) == NULL) || r; + r = ((glClearBufferSubData = (PFNGLCLEARBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glClearBufferSubData")) == NULL) || r; + r = ((glClearNamedBufferDataEXT = (PFNGLCLEARNAMEDBUFFERDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glClearNamedBufferDataEXT")) == NULL) || r; + r = ((glClearNamedBufferSubDataEXT = (PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC)glewGetProcAddress((const GLubyte*)"glClearNamedBufferSubDataEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_clear_buffer_object */ + +#ifdef GL_ARB_clear_texture + +static GLboolean _glewInit_GL_ARB_clear_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClearTexImage = (PFNGLCLEARTEXIMAGEPROC)glewGetProcAddress((const GLubyte*)"glClearTexImage")) == NULL) || r; + r = ((glClearTexSubImage = (PFNGLCLEARTEXSUBIMAGEPROC)glewGetProcAddress((const GLubyte*)"glClearTexSubImage")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_clear_texture */ + #ifdef GL_ARB_color_buffer_float static GLboolean _glewInit_GL_ARB_color_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3632,6 +4306,41 @@ static GLboolean _glewInit_GL_ARB_color_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_compatibility */ +#ifdef GL_ARB_compressed_texture_pixel_storage + +#endif /* GL_ARB_compressed_texture_pixel_storage */ + +#ifdef GL_ARB_compute_shader + +static GLboolean _glewInit_GL_ARB_compute_shader (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC)glewGetProcAddress((const GLubyte*)"glDispatchCompute")) == NULL) || r; + r = ((glDispatchComputeIndirect = (PFNGLDISPATCHCOMPUTEINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glDispatchComputeIndirect")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_compute_shader */ + +#ifdef GL_ARB_compute_variable_group_size + +static GLboolean _glewInit_GL_ARB_compute_variable_group_size (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDispatchComputeGroupSizeARB = (PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC)glewGetProcAddress((const GLubyte*)"glDispatchComputeGroupSizeARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_compute_variable_group_size */ + +#ifdef GL_ARB_conservative_depth + +#endif /* GL_ARB_conservative_depth */ + #ifdef GL_ARB_copy_buffer static GLboolean _glewInit_GL_ARB_copy_buffer (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3645,6 +4354,19 @@ static GLboolean _glewInit_GL_ARB_copy_buffer (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_copy_buffer */ +#ifdef GL_ARB_copy_image + +static GLboolean _glewInit_GL_ARB_copy_image (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC)glewGetProcAddress((const GLubyte*)"glCopyImageSubData")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_copy_image */ + #ifdef GL_ARB_debug_output static GLboolean _glewInit_GL_ARB_debug_output (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3736,14 +4458,26 @@ static GLboolean _glewInit_GL_ARB_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_draw_instanced */ +#ifdef GL_ARB_enhanced_layouts + +#endif /* GL_ARB_enhanced_layouts */ + #ifdef GL_ARB_explicit_attrib_location #endif /* GL_ARB_explicit_attrib_location */ +#ifdef GL_ARB_explicit_uniform_location + +#endif /* GL_ARB_explicit_uniform_location */ + #ifdef GL_ARB_fragment_coord_conventions #endif /* GL_ARB_fragment_coord_conventions */ +#ifdef GL_ARB_fragment_layer_viewport + +#endif /* GL_ARB_fragment_layer_viewport */ + #ifdef GL_ARB_fragment_program #endif /* GL_ARB_fragment_program */ @@ -3756,6 +4490,22 @@ static GLboolean _glewInit_GL_ARB_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_fragment_shader */ +#ifdef GL_ARB_framebuffer_no_attachments + +static GLboolean _glewInit_GL_ARB_framebuffer_no_attachments (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glFramebufferParameteri = (PFNGLFRAMEBUFFERPARAMETERIPROC)glewGetProcAddress((const GLubyte*)"glFramebufferParameteri")) == NULL) || r; + r = ((glGetFramebufferParameteriv = (PFNGLGETFRAMEBUFFERPARAMETERIVPROC)glewGetProcAddress((const GLubyte*)"glGetFramebufferParameteriv")) == NULL) || r; + r = ((glGetNamedFramebufferParameterivEXT = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC)glewGetProcAddress((const GLubyte*)"glGetNamedFramebufferParameterivEXT")) == NULL) || r; + r = ((glNamedFramebufferParameteriEXT = (PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC)glewGetProcAddress((const GLubyte*)"glNamedFramebufferParameteriEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_framebuffer_no_attachments */ + #ifdef GL_ARB_framebuffer_object static GLboolean _glewInit_GL_ARB_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3834,23 +4584,6 @@ static GLboolean _glewInit_GL_ARB_gpu_shader_fp64 (GLEW_CONTEXT_ARG_DEF_INIT) GLboolean r = GL_FALSE; r = ((glGetUniformdv = (PFNGLGETUNIFORMDVPROC)glewGetProcAddress((const GLubyte*)"glGetUniformdv")) == NULL) || r; - r = ((glProgramUniform1dEXT = (PFNGLPROGRAMUNIFORM1DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1dEXT")) == NULL) || r; - r = ((glProgramUniform1dvEXT = (PFNGLPROGRAMUNIFORM1DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform1dvEXT")) == NULL) || r; - r = ((glProgramUniform2dEXT = (PFNGLPROGRAMUNIFORM2DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2dEXT")) == NULL) || r; - r = ((glProgramUniform2dvEXT = (PFNGLPROGRAMUNIFORM2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform2dvEXT")) == NULL) || r; - r = ((glProgramUniform3dEXT = (PFNGLPROGRAMUNIFORM3DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3dEXT")) == NULL) || r; - r = ((glProgramUniform3dvEXT = (PFNGLPROGRAMUNIFORM3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform3dvEXT")) == NULL) || r; - r = ((glProgramUniform4dEXT = (PFNGLPROGRAMUNIFORM4DEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4dEXT")) == NULL) || r; - r = ((glProgramUniform4dvEXT = (PFNGLPROGRAMUNIFORM4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniform4dvEXT")) == NULL) || r; - r = ((glProgramUniformMatrix2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2dvEXT")) == NULL) || r; - r = ((glProgramUniformMatrix2x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x3dvEXT")) == NULL) || r; - r = ((glProgramUniformMatrix2x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix2x4dvEXT")) == NULL) || r; - r = ((glProgramUniformMatrix3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3dvEXT")) == NULL) || r; - r = ((glProgramUniformMatrix3x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x2dvEXT")) == NULL) || r; - r = ((glProgramUniformMatrix3x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix3x4dvEXT")) == NULL) || r; - r = ((glProgramUniformMatrix4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4dvEXT")) == NULL) || r; - r = ((glProgramUniformMatrix4x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x2dvEXT")) == NULL) || r; - r = ((glProgramUniformMatrix4x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformMatrix4x3dvEXT")) == NULL) || r; r = ((glUniform1d = (PFNGLUNIFORM1DPROC)glewGetProcAddress((const GLubyte*)"glUniform1d")) == NULL) || r; r = ((glUniform1dv = (PFNGLUNIFORM1DVPROC)glewGetProcAddress((const GLubyte*)"glUniform1dv")) == NULL) || r; r = ((glUniform2d = (PFNGLUNIFORM2DPROC)glewGetProcAddress((const GLubyte*)"glUniform2d")) == NULL) || r; @@ -3927,6 +4660,20 @@ static GLboolean _glewInit_GL_ARB_imaging (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_imaging */ +#ifdef GL_ARB_indirect_parameters + +static GLboolean _glewInit_GL_ARB_indirect_parameters (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMultiDrawArraysIndirectCountARB = (PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysIndirectCountARB")) == NULL) || r; + r = ((glMultiDrawElementsIndirectCountARB = (PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsIndirectCountARB")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_indirect_parameters */ + #ifdef GL_ARB_instanced_arrays static GLboolean _glewInit_GL_ARB_instanced_arrays (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3942,6 +4689,54 @@ static GLboolean _glewInit_GL_ARB_instanced_arrays (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_instanced_arrays */ +#ifdef GL_ARB_internalformat_query + +static GLboolean _glewInit_GL_ARB_internalformat_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC)glewGetProcAddress((const GLubyte*)"glGetInternalformativ")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_internalformat_query */ + +#ifdef GL_ARB_internalformat_query2 + +static GLboolean _glewInit_GL_ARB_internalformat_query2 (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetInternalformati64v = (PFNGLGETINTERNALFORMATI64VPROC)glewGetProcAddress((const GLubyte*)"glGetInternalformati64v")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_internalformat_query2 */ + +#ifdef GL_ARB_invalidate_subdata + +static GLboolean _glewInit_GL_ARB_invalidate_subdata (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glInvalidateBufferData = (PFNGLINVALIDATEBUFFERDATAPROC)glewGetProcAddress((const GLubyte*)"glInvalidateBufferData")) == NULL) || r; + r = ((glInvalidateBufferSubData = (PFNGLINVALIDATEBUFFERSUBDATAPROC)glewGetProcAddress((const GLubyte*)"glInvalidateBufferSubData")) == NULL) || r; + r = ((glInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glInvalidateFramebuffer")) == NULL) || r; + r = ((glInvalidateSubFramebuffer = (PFNGLINVALIDATESUBFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glInvalidateSubFramebuffer")) == NULL) || r; + r = ((glInvalidateTexImage = (PFNGLINVALIDATETEXIMAGEPROC)glewGetProcAddress((const GLubyte*)"glInvalidateTexImage")) == NULL) || r; + r = ((glInvalidateTexSubImage = (PFNGLINVALIDATETEXSUBIMAGEPROC)glewGetProcAddress((const GLubyte*)"glInvalidateTexSubImage")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_invalidate_subdata */ + +#ifdef GL_ARB_map_buffer_alignment + +#endif /* GL_ARB_map_buffer_alignment */ + #ifdef GL_ARB_map_buffer_range static GLboolean _glewInit_GL_ARB_map_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3973,6 +4768,38 @@ static GLboolean _glewInit_GL_ARB_matrix_palette (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_matrix_palette */ +#ifdef GL_ARB_multi_bind + +static GLboolean _glewInit_GL_ARB_multi_bind (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindBuffersBase = (PFNGLBINDBUFFERSBASEPROC)glewGetProcAddress((const GLubyte*)"glBindBuffersBase")) == NULL) || r; + r = ((glBindBuffersRange = (PFNGLBINDBUFFERSRANGEPROC)glewGetProcAddress((const GLubyte*)"glBindBuffersRange")) == NULL) || r; + r = ((glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)glewGetProcAddress((const GLubyte*)"glBindImageTextures")) == NULL) || r; + r = ((glBindSamplers = (PFNGLBINDSAMPLERSPROC)glewGetProcAddress((const GLubyte*)"glBindSamplers")) == NULL) || r; + r = ((glBindTextures = (PFNGLBINDTEXTURESPROC)glewGetProcAddress((const GLubyte*)"glBindTextures")) == NULL) || r; + r = ((glBindVertexBuffers = (PFNGLBINDVERTEXBUFFERSPROC)glewGetProcAddress((const GLubyte*)"glBindVertexBuffers")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_multi_bind */ + +#ifdef GL_ARB_multi_draw_indirect + +static GLboolean _glewInit_GL_ARB_multi_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMultiDrawArraysIndirect = (PFNGLMULTIDRAWARRAYSINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysIndirect")) == NULL) || r; + r = ((glMultiDrawElementsIndirect = (PFNGLMULTIDRAWELEMENTSINDIRECTPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsIndirect")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_multi_draw_indirect */ + #ifdef GL_ARB_multisample static GLboolean _glewInit_GL_ARB_multisample (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4078,6 +4905,24 @@ static GLboolean _glewInit_GL_ARB_point_parameters (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_point_sprite */ +#ifdef GL_ARB_program_interface_query + +static GLboolean _glewInit_GL_ARB_program_interface_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramInterfaceiv")) == NULL) || r; + r = ((glGetProgramResourceIndex = (PFNGLGETPROGRAMRESOURCEINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceIndex")) == NULL) || r; + r = ((glGetProgramResourceLocation = (PFNGLGETPROGRAMRESOURCELOCATIONPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceLocation")) == NULL) || r; + r = ((glGetProgramResourceLocationIndex = (PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceLocationIndex")) == NULL) || r; + r = ((glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceName")) == NULL) || r; + r = ((glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC)glewGetProcAddress((const GLubyte*)"glGetProgramResourceiv")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_program_interface_query */ + #ifdef GL_ARB_provoking_vertex static GLboolean _glewInit_GL_ARB_provoking_vertex (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4091,12 +4936,21 @@ static GLboolean _glewInit_GL_ARB_provoking_vertex (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_provoking_vertex */ +#ifdef GL_ARB_query_buffer_object + +#endif /* GL_ARB_query_buffer_object */ + +#ifdef GL_ARB_robust_buffer_access_behavior + +#endif /* GL_ARB_robust_buffer_access_behavior */ + #ifdef GL_ARB_robustness static GLboolean _glewInit_GL_ARB_robustness (GLEW_CONTEXT_ARG_DEF_INIT) { GLboolean r = GL_FALSE; + r = ((glGetGraphicsResetStatusARB = (PFNGLGETGRAPHICSRESETSTATUSARBPROC)glewGetProcAddress((const GLubyte*)"glGetGraphicsResetStatusARB")) == NULL) || r; r = ((glGetnColorTableARB = (PFNGLGETNCOLORTABLEARBPROC)glewGetProcAddress((const GLubyte*)"glGetnColorTableARB")) == NULL) || r; r = ((glGetnCompressedTexImageARB = (PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC)glewGetProcAddress((const GLubyte*)"glGetnCompressedTexImageARB")) == NULL) || r; r = ((glGetnConvolutionFilterARB = (PFNGLGETNCONVOLUTIONFILTERARBPROC)glewGetProcAddress((const GLubyte*)"glGetnConvolutionFilterARB")) == NULL) || r; @@ -4122,6 +4976,14 @@ static GLboolean _glewInit_GL_ARB_robustness (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_robustness */ +#ifdef GL_ARB_robustness_application_isolation + +#endif /* GL_ARB_robustness_application_isolation */ + +#ifdef GL_ARB_robustness_share_group_isolation + +#endif /* GL_ARB_robustness_share_group_isolation */ + #ifdef GL_ARB_sample_shading static GLboolean _glewInit_GL_ARB_sample_shading (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4165,6 +5027,10 @@ static GLboolean _glewInit_GL_ARB_sampler_objects (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_seamless_cube_map */ +#ifdef GL_ARB_seamless_cubemap_per_texture + +#endif /* GL_ARB_seamless_cubemap_per_texture */ + #ifdef GL_ARB_separate_shader_objects static GLboolean _glewInit_GL_ARB_separate_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4237,10 +5103,49 @@ static GLboolean _glewInit_GL_ARB_separate_shader_objects (GLEW_CONTEXT_ARG_DEF_ #endif /* GL_ARB_separate_shader_objects */ +#ifdef GL_ARB_shader_atomic_counters + +static GLboolean _glewInit_GL_ARB_shader_atomic_counters (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetActiveAtomicCounterBufferiv = (PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC)glewGetProcAddress((const GLubyte*)"glGetActiveAtomicCounterBufferiv")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_shader_atomic_counters */ + #ifdef GL_ARB_shader_bit_encoding #endif /* GL_ARB_shader_bit_encoding */ +#ifdef GL_ARB_shader_draw_parameters + +#endif /* GL_ARB_shader_draw_parameters */ + +#ifdef GL_ARB_shader_group_vote + +#endif /* GL_ARB_shader_group_vote */ + +#ifdef GL_ARB_shader_image_load_store + +static GLboolean _glewInit_GL_ARB_shader_image_load_store (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC)glewGetProcAddress((const GLubyte*)"glBindImageTexture")) == NULL) || r; + r = ((glMemoryBarrier = (PFNGLMEMORYBARRIERPROC)glewGetProcAddress((const GLubyte*)"glMemoryBarrier")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_shader_image_load_store */ + +#ifdef GL_ARB_shader_image_size + +#endif /* GL_ARB_shader_image_size */ + #ifdef GL_ARB_shader_objects static GLboolean _glewInit_GL_ARB_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4300,6 +5205,19 @@ static GLboolean _glewInit_GL_ARB_shader_objects (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_shader_stencil_export */ +#ifdef GL_ARB_shader_storage_buffer_object + +static GLboolean _glewInit_GL_ARB_shader_storage_buffer_object (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC)glewGetProcAddress((const GLubyte*)"glShaderStorageBlockBinding")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_shader_storage_buffer_object */ + #ifdef GL_ARB_shader_subroutine static GLboolean _glewInit_GL_ARB_shader_subroutine (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4328,6 +5246,10 @@ static GLboolean _glewInit_GL_ARB_shader_subroutine (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_shading_language_100 */ +#ifdef GL_ARB_shading_language_420pack + +#endif /* GL_ARB_shading_language_420pack */ + #ifdef GL_ARB_shading_language_include static GLboolean _glewInit_GL_ARB_shading_language_include (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4346,6 +5268,10 @@ static GLboolean _glewInit_GL_ARB_shading_language_include (GLEW_CONTEXT_ARG_DEF #endif /* GL_ARB_shading_language_include */ +#ifdef GL_ARB_shading_language_packing + +#endif /* GL_ARB_shading_language_packing */ + #ifdef GL_ARB_shadow #endif /* GL_ARB_shadow */ @@ -4354,6 +5280,24 @@ static GLboolean _glewInit_GL_ARB_shading_language_include (GLEW_CONTEXT_ARG_DEF #endif /* GL_ARB_shadow_ambient */ +#ifdef GL_ARB_sparse_texture + +static GLboolean _glewInit_GL_ARB_sparse_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexPageCommitmentARB = (PFNGLTEXPAGECOMMITMENTARBPROC)glewGetProcAddress((const GLubyte*)"glTexPageCommitmentARB")) == NULL) || r; + r = ((glTexturePageCommitmentEXT = (PFNGLTEXTUREPAGECOMMITMENTEXTPROC)glewGetProcAddress((const GLubyte*)"glTexturePageCommitmentEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_sparse_texture */ + +#ifdef GL_ARB_stencil_texturing + +#endif /* GL_ARB_stencil_texturing */ + #ifdef GL_ARB_sync static GLboolean _glewInit_GL_ARB_sync (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4408,6 +5352,20 @@ static GLboolean _glewInit_GL_ARB_texture_buffer_object (GLEW_CONTEXT_ARG_DEF_IN #endif /* GL_ARB_texture_buffer_object_rgb32 */ +#ifdef GL_ARB_texture_buffer_range + +static GLboolean _glewInit_GL_ARB_texture_buffer_range (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexBufferRange = (PFNGLTEXBUFFERRANGEPROC)glewGetProcAddress((const GLubyte*)"glTexBufferRange")) == NULL) || r; + r = ((glTextureBufferRangeEXT = (PFNGLTEXTUREBUFFERRANGEEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureBufferRangeEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_texture_buffer_range */ + #ifdef GL_ARB_texture_compression static GLboolean _glewInit_GL_ARB_texture_compression (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4467,6 +5425,10 @@ static GLboolean _glewInit_GL_ARB_texture_compression (GLEW_CONTEXT_ARG_DEF_INIT #endif /* GL_ARB_texture_gather */ +#ifdef GL_ARB_texture_mirror_clamp_to_edge + +#endif /* GL_ARB_texture_mirror_clamp_to_edge */ + #ifdef GL_ARB_texture_mirrored_repeat #endif /* GL_ARB_texture_mirrored_repeat */ @@ -4491,6 +5453,10 @@ static GLboolean _glewInit_GL_ARB_texture_multisample (GLEW_CONTEXT_ARG_DEF_INIT #endif /* GL_ARB_texture_non_power_of_two */ +#ifdef GL_ARB_texture_query_levels + +#endif /* GL_ARB_texture_query_levels */ + #ifdef GL_ARB_texture_query_lod #endif /* GL_ARB_texture_query_lod */ @@ -4507,10 +5473,61 @@ static GLboolean _glewInit_GL_ARB_texture_multisample (GLEW_CONTEXT_ARG_DEF_INIT #endif /* GL_ARB_texture_rgb10_a2ui */ +#ifdef GL_ARB_texture_stencil8 + +#endif /* GL_ARB_texture_stencil8 */ + +#ifdef GL_ARB_texture_storage + +static GLboolean _glewInit_GL_ARB_texture_storage (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexStorage1D = (PFNGLTEXSTORAGE1DPROC)glewGetProcAddress((const GLubyte*)"glTexStorage1D")) == NULL) || r; + r = ((glTexStorage2D = (PFNGLTEXSTORAGE2DPROC)glewGetProcAddress((const GLubyte*)"glTexStorage2D")) == NULL) || r; + r = ((glTexStorage3D = (PFNGLTEXSTORAGE3DPROC)glewGetProcAddress((const GLubyte*)"glTexStorage3D")) == NULL) || r; + r = ((glTextureStorage1DEXT = (PFNGLTEXTURESTORAGE1DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage1DEXT")) == NULL) || r; + r = ((glTextureStorage2DEXT = (PFNGLTEXTURESTORAGE2DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage2DEXT")) == NULL) || r; + r = ((glTextureStorage3DEXT = (PFNGLTEXTURESTORAGE3DEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage3DEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_texture_storage */ + +#ifdef GL_ARB_texture_storage_multisample + +static GLboolean _glewInit_GL_ARB_texture_storage_multisample (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTexStorage2DMultisample = (PFNGLTEXSTORAGE2DMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glTexStorage2DMultisample")) == NULL) || r; + r = ((glTexStorage3DMultisample = (PFNGLTEXSTORAGE3DMULTISAMPLEPROC)glewGetProcAddress((const GLubyte*)"glTexStorage3DMultisample")) == NULL) || r; + r = ((glTextureStorage2DMultisampleEXT = (PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage2DMultisampleEXT")) == NULL) || r; + r = ((glTextureStorage3DMultisampleEXT = (PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC)glewGetProcAddress((const GLubyte*)"glTextureStorage3DMultisampleEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_texture_storage_multisample */ + #ifdef GL_ARB_texture_swizzle #endif /* GL_ARB_texture_swizzle */ +#ifdef GL_ARB_texture_view + +static GLboolean _glewInit_GL_ARB_texture_view (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glTextureView = (PFNGLTEXTUREVIEWPROC)glewGetProcAddress((const GLubyte*)"glTextureView")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_texture_view */ + #ifdef GL_ARB_timer_query static GLboolean _glewInit_GL_ARB_timer_query (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4561,6 +5578,20 @@ static GLboolean _glewInit_GL_ARB_transform_feedback3 (GLEW_CONTEXT_ARG_DEF_INIT #endif /* GL_ARB_transform_feedback3 */ +#ifdef GL_ARB_transform_feedback_instanced + +static GLboolean _glewInit_GL_ARB_transform_feedback_instanced (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawTransformFeedbackInstanced = (PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC)glewGetProcAddress((const GLubyte*)"glDrawTransformFeedbackInstanced")) == NULL) || r; + r = ((glDrawTransformFeedbackStreamInstanced = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC)glewGetProcAddress((const GLubyte*)"glDrawTransformFeedbackStreamInstanced")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_transform_feedback_instanced */ + #ifdef GL_ARB_transpose_matrix static GLboolean _glewInit_GL_ARB_transpose_matrix (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4641,6 +5672,24 @@ static GLboolean _glewInit_GL_ARB_vertex_attrib_64bit (GLEW_CONTEXT_ARG_DEF_INIT #endif /* GL_ARB_vertex_attrib_64bit */ +#ifdef GL_ARB_vertex_attrib_binding + +static GLboolean _glewInit_GL_ARB_vertex_attrib_binding (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindVertexBuffer")) == NULL) || r; + r = ((glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribBinding")) == NULL) || r; + r = ((glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribFormat")) == NULL) || r; + r = ((glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIFormat")) == NULL) || r; + r = ((glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribLFormat")) == NULL) || r; + r = ((glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC)glewGetProcAddress((const GLubyte*)"glVertexBindingDivisor")) == NULL) || r; + + return r; +} + +#endif /* GL_ARB_vertex_attrib_binding */ + #ifdef GL_ARB_vertex_blend static GLboolean _glewInit_GL_ARB_vertex_blend (GLEW_CONTEXT_ARG_DEF_INIT) @@ -4775,6 +5824,10 @@ static GLboolean _glewInit_GL_ARB_vertex_shader (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_ARB_vertex_shader */ +#ifdef GL_ARB_vertex_type_10f_11f_11f_rev + +#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */ + #ifdef GL_ARB_vertex_type_2_10_10_10_rev static GLboolean _glewInit_GL_ARB_vertex_type_2_10_10_10_rev (GLEW_CONTEXT_ARG_DEF_INIT) @@ -5089,6 +6142,14 @@ static GLboolean _glewInit_GL_ATI_vertex_streams (GLEW_CONTEXT_ARG_DEF_INIT) r = ((glNormalStream3svATI = (PFNGLNORMALSTREAM3SVATIPROC)glewGetProcAddress((const GLubyte*)"glNormalStream3svATI")) == NULL) || r; r = ((glVertexBlendEnvfATI = (PFNGLVERTEXBLENDENVFATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnvfATI")) == NULL) || r; r = ((glVertexBlendEnviATI = (PFNGLVERTEXBLENDENVIATIPROC)glewGetProcAddress((const GLubyte*)"glVertexBlendEnviATI")) == NULL) || r; + r = ((glVertexStream1dATI = (PFNGLVERTEXSTREAM1DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1dATI")) == NULL) || r; + r = ((glVertexStream1dvATI = (PFNGLVERTEXSTREAM1DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1dvATI")) == NULL) || r; + r = ((glVertexStream1fATI = (PFNGLVERTEXSTREAM1FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1fATI")) == NULL) || r; + r = ((glVertexStream1fvATI = (PFNGLVERTEXSTREAM1FVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1fvATI")) == NULL) || r; + r = ((glVertexStream1iATI = (PFNGLVERTEXSTREAM1IATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1iATI")) == NULL) || r; + r = ((glVertexStream1ivATI = (PFNGLVERTEXSTREAM1IVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1ivATI")) == NULL) || r; + r = ((glVertexStream1sATI = (PFNGLVERTEXSTREAM1SATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1sATI")) == NULL) || r; + r = ((glVertexStream1svATI = (PFNGLVERTEXSTREAM1SVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream1svATI")) == NULL) || r; r = ((glVertexStream2dATI = (PFNGLVERTEXSTREAM2DATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dATI")) == NULL) || r; r = ((glVertexStream2dvATI = (PFNGLVERTEXSTREAM2DVATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2dvATI")) == NULL) || r; r = ((glVertexStream2fATI = (PFNGLVERTEXSTREAM2FATIPROC)glewGetProcAddress((const GLubyte*)"glVertexStream2fATI")) == NULL) || r; @@ -5316,6 +6377,21 @@ static GLboolean _glewInit_GL_EXT_cull_vertex (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_EXT_cull_vertex */ +#ifdef GL_EXT_debug_marker + +static GLboolean _glewInit_GL_EXT_debug_marker (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glInsertEventMarkerEXT = (PFNGLINSERTEVENTMARKEREXTPROC)glewGetProcAddress((const GLubyte*)"glInsertEventMarkerEXT")) == NULL) || r; + r = ((glPopGroupMarkerEXT = (PFNGLPOPGROUPMARKEREXTPROC)glewGetProcAddress((const GLubyte*)"glPopGroupMarkerEXT")) == NULL) || r; + r = ((glPushGroupMarkerEXT = (PFNGLPUSHGROUPMARKEREXTPROC)glewGetProcAddress((const GLubyte*)"glPushGroupMarkerEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_debug_marker */ + #ifdef GL_EXT_depth_bounds_test static GLboolean _glewInit_GL_EXT_depth_bounds_test (GLEW_CONTEXT_ARG_DEF_INIT) @@ -5672,6 +6748,10 @@ static GLboolean _glewInit_GL_EXT_framebuffer_multisample (GLEW_CONTEXT_ARG_DEF_ #endif /* GL_EXT_framebuffer_multisample */ +#ifdef GL_EXT_framebuffer_multisample_blit_scaled + +#endif /* GL_EXT_framebuffer_multisample_blit_scaled */ + #ifdef GL_EXT_framebuffer_object static GLboolean _glewInit_GL_EXT_framebuffer_object (GLEW_CONTEXT_ARG_DEF_INIT) @@ -6545,6 +7625,21 @@ static GLboolean _glewInit_GL_IBM_vertex_array_lists (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_INGR_interlace_read */ +#ifdef GL_INTEL_map_texture + +static GLboolean _glewInit_GL_INTEL_map_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMapTexture2DINTEL = (PFNGLMAPTEXTURE2DINTELPROC)glewGetProcAddress((const GLubyte*)"glMapTexture2DINTEL")) == NULL) || r; + r = ((glSyncTextureINTEL = (PFNGLSYNCTEXTUREINTELPROC)glewGetProcAddress((const GLubyte*)"glSyncTextureINTEL")) == NULL) || r; + r = ((glUnmapTexture2DINTEL = (PFNGLUNMAPTEXTURE2DINTELPROC)glewGetProcAddress((const GLubyte*)"glUnmapTexture2DINTEL")) == NULL) || r; + + return r; +} + +#endif /* GL_INTEL_map_texture */ + #ifdef GL_INTEL_parallel_arrays static GLboolean _glewInit_GL_INTEL_parallel_arrays (GLEW_CONTEXT_ARG_DEF_INIT) @@ -6575,17 +7670,43 @@ static GLboolean _glewInit_GL_INTEL_texture_scissor (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_INTEL_texture_scissor */ +#ifdef GL_KHR_debug + +static GLboolean _glewInit_GL_KHR_debug (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageCallback")) == NULL) || r; + r = ((glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageControl")) == NULL) || r; + r = ((glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC)glewGetProcAddress((const GLubyte*)"glDebugMessageInsert")) == NULL) || r; + r = ((glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC)glewGetProcAddress((const GLubyte*)"glGetDebugMessageLog")) == NULL) || r; + r = ((glGetObjectLabel = (PFNGLGETOBJECTLABELPROC)glewGetProcAddress((const GLubyte*)"glGetObjectLabel")) == NULL) || r; + r = ((glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC)glewGetProcAddress((const GLubyte*)"glGetObjectPtrLabel")) == NULL) || r; + r = ((glObjectLabel = (PFNGLOBJECTLABELPROC)glewGetProcAddress((const GLubyte*)"glObjectLabel")) == NULL) || r; + r = ((glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC)glewGetProcAddress((const GLubyte*)"glObjectPtrLabel")) == NULL) || r; + r = ((glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC)glewGetProcAddress((const GLubyte*)"glPopDebugGroup")) == NULL) || r; + r = ((glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC)glewGetProcAddress((const GLubyte*)"glPushDebugGroup")) == NULL) || r; + + return r; +} + +#endif /* GL_KHR_debug */ + +#ifdef GL_KHR_texture_compression_astc_ldr + +#endif /* GL_KHR_texture_compression_astc_ldr */ + #ifdef GL_KTX_buffer_region static GLboolean _glewInit_GL_KTX_buffer_region (GLEW_CONTEXT_ARG_DEF_INIT) { GLboolean r = GL_FALSE; - r = ((glBufferRegionEnabledEXT = (PFNGLBUFFERREGIONENABLEDEXTPROC)glewGetProcAddress((const GLubyte*)"glBufferRegionEnabledEXT")) == NULL) || r; - r = ((glDeleteBufferRegionEXT = (PFNGLDELETEBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glDeleteBufferRegionEXT")) == NULL) || r; - r = ((glDrawBufferRegionEXT = (PFNGLDRAWBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glDrawBufferRegionEXT")) == NULL) || r; - r = ((glNewBufferRegionEXT = (PFNGLNEWBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glNewBufferRegionEXT")) == NULL) || r; - r = ((glReadBufferRegionEXT = (PFNGLREADBUFFERREGIONEXTPROC)glewGetProcAddress((const GLubyte*)"glReadBufferRegionEXT")) == NULL) || r; + r = ((glBufferRegionEnabled = (PFNGLBUFFERREGIONENABLEDPROC)glewGetProcAddress((const GLubyte*)"glBufferRegionEnabled")) == NULL) || r; + r = ((glDeleteBufferRegion = (PFNGLDELETEBUFFERREGIONPROC)glewGetProcAddress((const GLubyte*)"glDeleteBufferRegion")) == NULL) || r; + r = ((glDrawBufferRegion = (PFNGLDRAWBUFFERREGIONPROC)glewGetProcAddress((const GLubyte*)"glDrawBufferRegion")) == NULL) || r; + r = ((glNewBufferRegion = (PFNGLNEWBUFFERREGIONPROC)glewGetProcAddress((const GLubyte*)"glNewBufferRegion")) == NULL) || r; + r = ((glReadBufferRegion = (PFNGLREADBUFFERREGIONPROC)glewGetProcAddress((const GLubyte*)"glReadBufferRegion")) == NULL) || r; return r; } @@ -6653,14 +7774,89 @@ static GLboolean _glewInit_GL_MESA_window_pos (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_MESA_ycbcr_texture */ +#ifdef GL_NVX_conditional_render + +static GLboolean _glewInit_GL_NVX_conditional_render (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginConditionalRenderNVX = (PFNGLBEGINCONDITIONALRENDERNVXPROC)glewGetProcAddress((const GLubyte*)"glBeginConditionalRenderNVX")) == NULL) || r; + r = ((glEndConditionalRenderNVX = (PFNGLENDCONDITIONALRENDERNVXPROC)glewGetProcAddress((const GLubyte*)"glEndConditionalRenderNVX")) == NULL) || r; + + return r; +} + +#endif /* GL_NVX_conditional_render */ + #ifdef GL_NVX_gpu_memory_info #endif /* GL_NVX_gpu_memory_info */ +#ifdef GL_NV_bindless_multi_draw_indirect + +static GLboolean _glewInit_GL_NV_bindless_multi_draw_indirect (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glMultiDrawArraysIndirectBindlessNV = (PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawArraysIndirectBindlessNV")) == NULL) || r; + r = ((glMultiDrawElementsIndirectBindlessNV = (PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC)glewGetProcAddress((const GLubyte*)"glMultiDrawElementsIndirectBindlessNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_bindless_multi_draw_indirect */ + +#ifdef GL_NV_bindless_texture + +static GLboolean _glewInit_GL_NV_bindless_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetImageHandleNV = (PFNGLGETIMAGEHANDLENVPROC)glewGetProcAddress((const GLubyte*)"glGetImageHandleNV")) == NULL) || r; + r = ((glGetTextureHandleNV = (PFNGLGETTEXTUREHANDLENVPROC)glewGetProcAddress((const GLubyte*)"glGetTextureHandleNV")) == NULL) || r; + r = ((glGetTextureSamplerHandleNV = (PFNGLGETTEXTURESAMPLERHANDLENVPROC)glewGetProcAddress((const GLubyte*)"glGetTextureSamplerHandleNV")) == NULL) || r; + r = ((glIsImageHandleResidentNV = (PFNGLISIMAGEHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glIsImageHandleResidentNV")) == NULL) || r; + r = ((glIsTextureHandleResidentNV = (PFNGLISTEXTUREHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glIsTextureHandleResidentNV")) == NULL) || r; + r = ((glMakeImageHandleNonResidentNV = (PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeImageHandleNonResidentNV")) == NULL) || r; + r = ((glMakeImageHandleResidentNV = (PFNGLMAKEIMAGEHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeImageHandleResidentNV")) == NULL) || r; + r = ((glMakeTextureHandleNonResidentNV = (PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeTextureHandleNonResidentNV")) == NULL) || r; + r = ((glMakeTextureHandleResidentNV = (PFNGLMAKETEXTUREHANDLERESIDENTNVPROC)glewGetProcAddress((const GLubyte*)"glMakeTextureHandleResidentNV")) == NULL) || r; + r = ((glProgramUniformHandleui64NV = (PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformHandleui64NV")) == NULL) || r; + r = ((glProgramUniformHandleui64vNV = (PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glProgramUniformHandleui64vNV")) == NULL) || r; + r = ((glUniformHandleui64NV = (PFNGLUNIFORMHANDLEUI64NVPROC)glewGetProcAddress((const GLubyte*)"glUniformHandleui64NV")) == NULL) || r; + r = ((glUniformHandleui64vNV = (PFNGLUNIFORMHANDLEUI64VNVPROC)glewGetProcAddress((const GLubyte*)"glUniformHandleui64vNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_bindless_texture */ + +#ifdef GL_NV_blend_equation_advanced + +static GLboolean _glewInit_GL_NV_blend_equation_advanced (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBlendBarrierNV = (PFNGLBLENDBARRIERNVPROC)glewGetProcAddress((const GLubyte*)"glBlendBarrierNV")) == NULL) || r; + r = ((glBlendParameteriNV = (PFNGLBLENDPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glBlendParameteriNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_blend_equation_advanced */ + +#ifdef GL_NV_blend_equation_advanced_coherent + +#endif /* GL_NV_blend_equation_advanced_coherent */ + #ifdef GL_NV_blend_square #endif /* GL_NV_blend_square */ +#ifdef GL_NV_compute_program5 + +#endif /* GL_NV_compute_program5 */ + #ifdef GL_NV_conditional_render static GLboolean _glewInit_GL_NV_conditional_render (GLEW_CONTEXT_ARG_DEF_INIT) @@ -6692,6 +7888,10 @@ static GLboolean _glewInit_GL_NV_copy_image (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_NV_copy_image */ +#ifdef GL_NV_deep_texture3D + +#endif /* GL_NV_deep_texture3D */ + #ifdef GL_NV_depth_buffer_float static GLboolean _glewInit_GL_NV_depth_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT) @@ -6715,6 +7915,19 @@ static GLboolean _glewInit_GL_NV_depth_buffer_float (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_NV_depth_range_unclamped */ +#ifdef GL_NV_draw_texture + +static GLboolean _glewInit_GL_NV_draw_texture (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)glewGetProcAddress((const GLubyte*)"glDrawTextureNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_draw_texture */ + #ifdef GL_NV_evaluators static GLboolean _glewInit_GL_NV_evaluators (GLEW_CONTEXT_ARG_DEF_INIT) @@ -6866,6 +8079,10 @@ static GLboolean _glewInit_GL_NV_gpu_program4 (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_NV_gpu_program5 */ +#ifdef GL_NV_gpu_program5_mem_extended + +#endif /* GL_NV_gpu_program5_mem_extended */ + #ifdef GL_NV_gpu_program_fp64 #endif /* GL_NV_gpu_program_fp64 */ @@ -7028,6 +8245,67 @@ static GLboolean _glewInit_GL_NV_parameter_buffer_object (GLEW_CONTEXT_ARG_DEF_I #endif /* GL_NV_parameter_buffer_object2 */ +#ifdef GL_NV_path_rendering + +static GLboolean _glewInit_GL_NV_path_rendering (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glCopyPathNV = (PFNGLCOPYPATHNVPROC)glewGetProcAddress((const GLubyte*)"glCopyPathNV")) == NULL) || r; + r = ((glCoverFillPathInstancedNV = (PFNGLCOVERFILLPATHINSTANCEDNVPROC)glewGetProcAddress((const GLubyte*)"glCoverFillPathInstancedNV")) == NULL) || r; + r = ((glCoverFillPathNV = (PFNGLCOVERFILLPATHNVPROC)glewGetProcAddress((const GLubyte*)"glCoverFillPathNV")) == NULL) || r; + r = ((glCoverStrokePathInstancedNV = (PFNGLCOVERSTROKEPATHINSTANCEDNVPROC)glewGetProcAddress((const GLubyte*)"glCoverStrokePathInstancedNV")) == NULL) || r; + r = ((glCoverStrokePathNV = (PFNGLCOVERSTROKEPATHNVPROC)glewGetProcAddress((const GLubyte*)"glCoverStrokePathNV")) == NULL) || r; + r = ((glDeletePathsNV = (PFNGLDELETEPATHSNVPROC)glewGetProcAddress((const GLubyte*)"glDeletePathsNV")) == NULL) || r; + r = ((glGenPathsNV = (PFNGLGENPATHSNVPROC)glewGetProcAddress((const GLubyte*)"glGenPathsNV")) == NULL) || r; + r = ((glGetPathColorGenfvNV = (PFNGLGETPATHCOLORGENFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathColorGenfvNV")) == NULL) || r; + r = ((glGetPathColorGenivNV = (PFNGLGETPATHCOLORGENIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathColorGenivNV")) == NULL) || r; + r = ((glGetPathCommandsNV = (PFNGLGETPATHCOMMANDSNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathCommandsNV")) == NULL) || r; + r = ((glGetPathCoordsNV = (PFNGLGETPATHCOORDSNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathCoordsNV")) == NULL) || r; + r = ((glGetPathDashArrayNV = (PFNGLGETPATHDASHARRAYNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathDashArrayNV")) == NULL) || r; + r = ((glGetPathLengthNV = (PFNGLGETPATHLENGTHNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathLengthNV")) == NULL) || r; + r = ((glGetPathMetricRangeNV = (PFNGLGETPATHMETRICRANGENVPROC)glewGetProcAddress((const GLubyte*)"glGetPathMetricRangeNV")) == NULL) || r; + r = ((glGetPathMetricsNV = (PFNGLGETPATHMETRICSNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathMetricsNV")) == NULL) || r; + r = ((glGetPathParameterfvNV = (PFNGLGETPATHPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathParameterfvNV")) == NULL) || r; + r = ((glGetPathParameterivNV = (PFNGLGETPATHPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathParameterivNV")) == NULL) || r; + r = ((glGetPathSpacingNV = (PFNGLGETPATHSPACINGNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathSpacingNV")) == NULL) || r; + r = ((glGetPathTexGenfvNV = (PFNGLGETPATHTEXGENFVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathTexGenfvNV")) == NULL) || r; + r = ((glGetPathTexGenivNV = (PFNGLGETPATHTEXGENIVNVPROC)glewGetProcAddress((const GLubyte*)"glGetPathTexGenivNV")) == NULL) || r; + r = ((glInterpolatePathsNV = (PFNGLINTERPOLATEPATHSNVPROC)glewGetProcAddress((const GLubyte*)"glInterpolatePathsNV")) == NULL) || r; + r = ((glIsPathNV = (PFNGLISPATHNVPROC)glewGetProcAddress((const GLubyte*)"glIsPathNV")) == NULL) || r; + r = ((glIsPointInFillPathNV = (PFNGLISPOINTINFILLPATHNVPROC)glewGetProcAddress((const GLubyte*)"glIsPointInFillPathNV")) == NULL) || r; + r = ((glIsPointInStrokePathNV = (PFNGLISPOINTINSTROKEPATHNVPROC)glewGetProcAddress((const GLubyte*)"glIsPointInStrokePathNV")) == NULL) || r; + r = ((glPathColorGenNV = (PFNGLPATHCOLORGENNVPROC)glewGetProcAddress((const GLubyte*)"glPathColorGenNV")) == NULL) || r; + r = ((glPathCommandsNV = (PFNGLPATHCOMMANDSNVPROC)glewGetProcAddress((const GLubyte*)"glPathCommandsNV")) == NULL) || r; + r = ((glPathCoordsNV = (PFNGLPATHCOORDSNVPROC)glewGetProcAddress((const GLubyte*)"glPathCoordsNV")) == NULL) || r; + r = ((glPathCoverDepthFuncNV = (PFNGLPATHCOVERDEPTHFUNCNVPROC)glewGetProcAddress((const GLubyte*)"glPathCoverDepthFuncNV")) == NULL) || r; + r = ((glPathDashArrayNV = (PFNGLPATHDASHARRAYNVPROC)glewGetProcAddress((const GLubyte*)"glPathDashArrayNV")) == NULL) || r; + r = ((glPathFogGenNV = (PFNGLPATHFOGGENNVPROC)glewGetProcAddress((const GLubyte*)"glPathFogGenNV")) == NULL) || r; + r = ((glPathGlyphRangeNV = (PFNGLPATHGLYPHRANGENVPROC)glewGetProcAddress((const GLubyte*)"glPathGlyphRangeNV")) == NULL) || r; + r = ((glPathGlyphsNV = (PFNGLPATHGLYPHSNVPROC)glewGetProcAddress((const GLubyte*)"glPathGlyphsNV")) == NULL) || r; + r = ((glPathParameterfNV = (PFNGLPATHPARAMETERFNVPROC)glewGetProcAddress((const GLubyte*)"glPathParameterfNV")) == NULL) || r; + r = ((glPathParameterfvNV = (PFNGLPATHPARAMETERFVNVPROC)glewGetProcAddress((const GLubyte*)"glPathParameterfvNV")) == NULL) || r; + r = ((glPathParameteriNV = (PFNGLPATHPARAMETERINVPROC)glewGetProcAddress((const GLubyte*)"glPathParameteriNV")) == NULL) || r; + r = ((glPathParameterivNV = (PFNGLPATHPARAMETERIVNVPROC)glewGetProcAddress((const GLubyte*)"glPathParameterivNV")) == NULL) || r; + r = ((glPathStencilDepthOffsetNV = (PFNGLPATHSTENCILDEPTHOFFSETNVPROC)glewGetProcAddress((const GLubyte*)"glPathStencilDepthOffsetNV")) == NULL) || r; + r = ((glPathStencilFuncNV = (PFNGLPATHSTENCILFUNCNVPROC)glewGetProcAddress((const GLubyte*)"glPathStencilFuncNV")) == NULL) || r; + r = ((glPathStringNV = (PFNGLPATHSTRINGNVPROC)glewGetProcAddress((const GLubyte*)"glPathStringNV")) == NULL) || r; + r = ((glPathSubCommandsNV = (PFNGLPATHSUBCOMMANDSNVPROC)glewGetProcAddress((const GLubyte*)"glPathSubCommandsNV")) == NULL) || r; + r = ((glPathSubCoordsNV = (PFNGLPATHSUBCOORDSNVPROC)glewGetProcAddress((const GLubyte*)"glPathSubCoordsNV")) == NULL) || r; + r = ((glPathTexGenNV = (PFNGLPATHTEXGENNVPROC)glewGetProcAddress((const GLubyte*)"glPathTexGenNV")) == NULL) || r; + r = ((glPointAlongPathNV = (PFNGLPOINTALONGPATHNVPROC)glewGetProcAddress((const GLubyte*)"glPointAlongPathNV")) == NULL) || r; + r = ((glStencilFillPathInstancedNV = (PFNGLSTENCILFILLPATHINSTANCEDNVPROC)glewGetProcAddress((const GLubyte*)"glStencilFillPathInstancedNV")) == NULL) || r; + r = ((glStencilFillPathNV = (PFNGLSTENCILFILLPATHNVPROC)glewGetProcAddress((const GLubyte*)"glStencilFillPathNV")) == NULL) || r; + r = ((glStencilStrokePathInstancedNV = (PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC)glewGetProcAddress((const GLubyte*)"glStencilStrokePathInstancedNV")) == NULL) || r; + r = ((glStencilStrokePathNV = (PFNGLSTENCILSTROKEPATHNVPROC)glewGetProcAddress((const GLubyte*)"glStencilStrokePathNV")) == NULL) || r; + r = ((glTransformPathNV = (PFNGLTRANSFORMPATHNVPROC)glewGetProcAddress((const GLubyte*)"glTransformPathNV")) == NULL) || r; + r = ((glWeightPathsNV = (PFNGLWEIGHTPATHSNVPROC)glewGetProcAddress((const GLubyte*)"glWeightPathsNV")) == NULL) || r; + + return r; +} + +#endif /* GL_NV_path_rendering */ + #ifdef GL_NV_pixel_data_range static GLboolean _glewInit_GL_NV_pixel_data_range (GLEW_CONTEXT_ARG_DEF_INIT) @@ -7127,6 +8405,14 @@ static GLboolean _glewInit_GL_NV_register_combiners2 (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_NV_register_combiners2 */ +#ifdef GL_NV_shader_atomic_counters + +#endif /* GL_NV_shader_atomic_counters */ + +#ifdef GL_NV_shader_atomic_float + +#endif /* GL_NV_shader_atomic_float */ + #ifdef GL_NV_shader_buffer_load static GLboolean _glewInit_GL_NV_shader_buffer_load (GLEW_CONTEXT_ARG_DEF_INIT) @@ -7152,6 +8438,10 @@ static GLboolean _glewInit_GL_NV_shader_buffer_load (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_NV_shader_buffer_load */ +#ifdef GL_NV_shader_storage_buffer_object + +#endif /* GL_NV_shader_storage_buffer_object */ + #ifdef GL_NV_tessellation_program5 #endif /* GL_NV_tessellation_program5 */ @@ -7530,6 +8820,118 @@ static GLboolean _glewInit_GL_OES_single_precision (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_PGI_vertex_hints */ +#ifdef GL_REGAL_ES1_0_compatibility + +static GLboolean _glewInit_GL_REGAL_ES1_0_compatibility (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glAlphaFuncx = (PFNGLALPHAFUNCXPROC)glewGetProcAddress((const GLubyte*)"glAlphaFuncx")) == NULL) || r; + r = ((glClearColorx = (PFNGLCLEARCOLORXPROC)glewGetProcAddress((const GLubyte*)"glClearColorx")) == NULL) || r; + r = ((glClearDepthx = (PFNGLCLEARDEPTHXPROC)glewGetProcAddress((const GLubyte*)"glClearDepthx")) == NULL) || r; + r = ((glColor4x = (PFNGLCOLOR4XPROC)glewGetProcAddress((const GLubyte*)"glColor4x")) == NULL) || r; + r = ((glDepthRangex = (PFNGLDEPTHRANGEXPROC)glewGetProcAddress((const GLubyte*)"glDepthRangex")) == NULL) || r; + r = ((glFogx = (PFNGLFOGXPROC)glewGetProcAddress((const GLubyte*)"glFogx")) == NULL) || r; + r = ((glFogxv = (PFNGLFOGXVPROC)glewGetProcAddress((const GLubyte*)"glFogxv")) == NULL) || r; + r = ((glFrustumf = (PFNGLFRUSTUMFPROC)glewGetProcAddress((const GLubyte*)"glFrustumf")) == NULL) || r; + r = ((glFrustumx = (PFNGLFRUSTUMXPROC)glewGetProcAddress((const GLubyte*)"glFrustumx")) == NULL) || r; + r = ((glLightModelx = (PFNGLLIGHTMODELXPROC)glewGetProcAddress((const GLubyte*)"glLightModelx")) == NULL) || r; + r = ((glLightModelxv = (PFNGLLIGHTMODELXVPROC)glewGetProcAddress((const GLubyte*)"glLightModelxv")) == NULL) || r; + r = ((glLightx = (PFNGLLIGHTXPROC)glewGetProcAddress((const GLubyte*)"glLightx")) == NULL) || r; + r = ((glLightxv = (PFNGLLIGHTXVPROC)glewGetProcAddress((const GLubyte*)"glLightxv")) == NULL) || r; + r = ((glLineWidthx = (PFNGLLINEWIDTHXPROC)glewGetProcAddress((const GLubyte*)"glLineWidthx")) == NULL) || r; + r = ((glLoadMatrixx = (PFNGLLOADMATRIXXPROC)glewGetProcAddress((const GLubyte*)"glLoadMatrixx")) == NULL) || r; + r = ((glMaterialx = (PFNGLMATERIALXPROC)glewGetProcAddress((const GLubyte*)"glMaterialx")) == NULL) || r; + r = ((glMaterialxv = (PFNGLMATERIALXVPROC)glewGetProcAddress((const GLubyte*)"glMaterialxv")) == NULL) || r; + r = ((glMultMatrixx = (PFNGLMULTMATRIXXPROC)glewGetProcAddress((const GLubyte*)"glMultMatrixx")) == NULL) || r; + r = ((glMultiTexCoord4x = (PFNGLMULTITEXCOORD4XPROC)glewGetProcAddress((const GLubyte*)"glMultiTexCoord4x")) == NULL) || r; + r = ((glNormal3x = (PFNGLNORMAL3XPROC)glewGetProcAddress((const GLubyte*)"glNormal3x")) == NULL) || r; + r = ((glOrthof = (PFNGLORTHOFPROC)glewGetProcAddress((const GLubyte*)"glOrthof")) == NULL) || r; + r = ((glOrthox = (PFNGLORTHOXPROC)glewGetProcAddress((const GLubyte*)"glOrthox")) == NULL) || r; + r = ((glPointSizex = (PFNGLPOINTSIZEXPROC)glewGetProcAddress((const GLubyte*)"glPointSizex")) == NULL) || r; + r = ((glPolygonOffsetx = (PFNGLPOLYGONOFFSETXPROC)glewGetProcAddress((const GLubyte*)"glPolygonOffsetx")) == NULL) || r; + r = ((glRotatex = (PFNGLROTATEXPROC)glewGetProcAddress((const GLubyte*)"glRotatex")) == NULL) || r; + r = ((glSampleCoveragex = (PFNGLSAMPLECOVERAGEXPROC)glewGetProcAddress((const GLubyte*)"glSampleCoveragex")) == NULL) || r; + r = ((glScalex = (PFNGLSCALEXPROC)glewGetProcAddress((const GLubyte*)"glScalex")) == NULL) || r; + r = ((glTexEnvx = (PFNGLTEXENVXPROC)glewGetProcAddress((const GLubyte*)"glTexEnvx")) == NULL) || r; + r = ((glTexEnvxv = (PFNGLTEXENVXVPROC)glewGetProcAddress((const GLubyte*)"glTexEnvxv")) == NULL) || r; + r = ((glTexParameterx = (PFNGLTEXPARAMETERXPROC)glewGetProcAddress((const GLubyte*)"glTexParameterx")) == NULL) || r; + r = ((glTranslatex = (PFNGLTRANSLATEXPROC)glewGetProcAddress((const GLubyte*)"glTranslatex")) == NULL) || r; + + return r; +} + +#endif /* GL_REGAL_ES1_0_compatibility */ + +#ifdef GL_REGAL_ES1_1_compatibility + +static GLboolean _glewInit_GL_REGAL_ES1_1_compatibility (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glClipPlanef = (PFNGLCLIPPLANEFPROC)glewGetProcAddress((const GLubyte*)"glClipPlanef")) == NULL) || r; + r = ((glClipPlanex = (PFNGLCLIPPLANEXPROC)glewGetProcAddress((const GLubyte*)"glClipPlanex")) == NULL) || r; + r = ((glGetClipPlanef = (PFNGLGETCLIPPLANEFPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlanef")) == NULL) || r; + r = ((glGetClipPlanex = (PFNGLGETCLIPPLANEXPROC)glewGetProcAddress((const GLubyte*)"glGetClipPlanex")) == NULL) || r; + r = ((glGetFixedv = (PFNGLGETFIXEDVPROC)glewGetProcAddress((const GLubyte*)"glGetFixedv")) == NULL) || r; + r = ((glGetLightxv = (PFNGLGETLIGHTXVPROC)glewGetProcAddress((const GLubyte*)"glGetLightxv")) == NULL) || r; + r = ((glGetMaterialxv = (PFNGLGETMATERIALXVPROC)glewGetProcAddress((const GLubyte*)"glGetMaterialxv")) == NULL) || r; + r = ((glGetTexEnvxv = (PFNGLGETTEXENVXVPROC)glewGetProcAddress((const GLubyte*)"glGetTexEnvxv")) == NULL) || r; + r = ((glGetTexParameterxv = (PFNGLGETTEXPARAMETERXVPROC)glewGetProcAddress((const GLubyte*)"glGetTexParameterxv")) == NULL) || r; + r = ((glPointParameterx = (PFNGLPOINTPARAMETERXPROC)glewGetProcAddress((const GLubyte*)"glPointParameterx")) == NULL) || r; + r = ((glPointParameterxv = (PFNGLPOINTPARAMETERXVPROC)glewGetProcAddress((const GLubyte*)"glPointParameterxv")) == NULL) || r; + r = ((glPointSizePointerOES = (PFNGLPOINTSIZEPOINTEROESPROC)glewGetProcAddress((const GLubyte*)"glPointSizePointerOES")) == NULL) || r; + r = ((glTexParameterxv = (PFNGLTEXPARAMETERXVPROC)glewGetProcAddress((const GLubyte*)"glTexParameterxv")) == NULL) || r; + + return r; +} + +#endif /* GL_REGAL_ES1_1_compatibility */ + +#ifdef GL_REGAL_enable + +#endif /* GL_REGAL_enable */ + +#ifdef GL_REGAL_error_string + +static GLboolean _glewInit_GL_REGAL_error_string (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glErrorStringREGAL = (PFNGLERRORSTRINGREGALPROC)glewGetProcAddress((const GLubyte*)"glErrorStringREGAL")) == NULL) || r; + + return r; +} + +#endif /* GL_REGAL_error_string */ + +#ifdef GL_REGAL_extension_query + +static GLboolean _glewInit_GL_REGAL_extension_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetExtensionREGAL = (PFNGLGETEXTENSIONREGALPROC)glewGetProcAddress((const GLubyte*)"glGetExtensionREGAL")) == NULL) || r; + r = ((glIsSupportedREGAL = (PFNGLISSUPPORTEDREGALPROC)glewGetProcAddress((const GLubyte*)"glIsSupportedREGAL")) == NULL) || r; + + return r; +} + +#endif /* GL_REGAL_extension_query */ + +#ifdef GL_REGAL_log + +static GLboolean _glewInit_GL_REGAL_log (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glLogMessageCallbackREGAL = (PFNGLLOGMESSAGECALLBACKREGALPROC)glewGetProcAddress((const GLubyte*)"glLogMessageCallbackREGAL")) == NULL) || r; + + return r; +} + +#endif /* GL_REGAL_log */ + #ifdef GL_REND_screen_coordinates #endif /* GL_REND_screen_coordinates */ @@ -8066,7 +9468,7 @@ static GLboolean _glewInit_GL_WIN_swap_hint (GLEW_CONTEXT_ARG_DEF_INIT) /* ------------------------------------------------------------------------- */ -GLboolean glewGetExtension (const char* name) +GLboolean GLEWAPIENTRY glewGetExtension (const char* name) { const GLubyte* start; const GLubyte* end; @@ -8082,7 +9484,7 @@ GLboolean glewGetExtension (const char* name) #ifndef GLEW_MX static #endif -GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) +GLenum GLEWAPIENTRY glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) { const GLubyte* s; GLuint dot; @@ -8110,7 +9512,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) } else { - CONST_CAST(GLEW_VERSION_4_1) = ( major > 4 ) || ( major == 4 && minor >= 1 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_4_4) = ( major > 4 ) || ( major == 4 && minor >= 4 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_4_3) = GLEW_VERSION_4_4 == GL_TRUE || ( major == 4 && minor >= 3 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_4_2) = GLEW_VERSION_4_3 == GL_TRUE || ( major == 4 && minor >= 2 ) ? GL_TRUE : GL_FALSE; + CONST_CAST(GLEW_VERSION_4_1) = GLEW_VERSION_4_2 == GL_TRUE || ( major == 4 && minor >= 1 ) ? GL_TRUE : GL_FALSE; CONST_CAST(GLEW_VERSION_4_0) = GLEW_VERSION_4_1 == GL_TRUE || ( major == 4 ) ? GL_TRUE : GL_FALSE; CONST_CAST(GLEW_VERSION_3_3) = GLEW_VERSION_4_0 == GL_TRUE || ( major == 3 && minor >= 3 ) ? GL_TRUE : GL_FALSE; CONST_CAST(GLEW_VERSION_3_2) = GLEW_VERSION_3_3 == GL_TRUE || ( major == 3 && minor >= 2 ) ? GL_TRUE : GL_FALSE; @@ -8170,6 +9575,12 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #endif /* GL_VERSION_4_0 */ #ifdef GL_VERSION_4_1 #endif /* GL_VERSION_4_1 */ +#ifdef GL_VERSION_4_2 +#endif /* GL_VERSION_4_2 */ +#ifdef GL_VERSION_4_3 +#endif /* GL_VERSION_4_3 */ +#ifdef GL_VERSION_4_4 +#endif /* GL_VERSION_4_4 */ #ifdef GL_3DFX_multisample CONST_CAST(GLEW_3DFX_multisample) = _glewSearchExtension("GL_3DFX_multisample", extStart, extEnd); #endif /* GL_3DFX_multisample */ @@ -8197,6 +9608,14 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_AMD_draw_buffers_blend) = _glewSearchExtension("GL_AMD_draw_buffers_blend", extStart, extEnd); if (glewExperimental || GLEW_AMD_draw_buffers_blend) CONST_CAST(GLEW_AMD_draw_buffers_blend) = !_glewInit_GL_AMD_draw_buffers_blend(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_draw_buffers_blend */ +#ifdef GL_AMD_interleaved_elements + CONST_CAST(GLEW_AMD_interleaved_elements) = _glewSearchExtension("GL_AMD_interleaved_elements", extStart, extEnd); + if (glewExperimental || GLEW_AMD_interleaved_elements) CONST_CAST(GLEW_AMD_interleaved_elements) = !_glewInit_GL_AMD_interleaved_elements(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_interleaved_elements */ +#ifdef GL_AMD_multi_draw_indirect + CONST_CAST(GLEW_AMD_multi_draw_indirect) = _glewSearchExtension("GL_AMD_multi_draw_indirect", extStart, extEnd); + if (glewExperimental || GLEW_AMD_multi_draw_indirect) CONST_CAST(GLEW_AMD_multi_draw_indirect) = !_glewInit_GL_AMD_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_multi_draw_indirect */ #ifdef GL_AMD_name_gen_delete CONST_CAST(GLEW_AMD_name_gen_delete) = _glewSearchExtension("GL_AMD_name_gen_delete", extStart, extEnd); if (glewExperimental || GLEW_AMD_name_gen_delete) CONST_CAST(GLEW_AMD_name_gen_delete) = !_glewInit_GL_AMD_name_gen_delete(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8205,6 +9624,12 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_AMD_performance_monitor) = _glewSearchExtension("GL_AMD_performance_monitor", extStart, extEnd); if (glewExperimental || GLEW_AMD_performance_monitor) CONST_CAST(GLEW_AMD_performance_monitor) = !_glewInit_GL_AMD_performance_monitor(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_performance_monitor */ +#ifdef GL_AMD_pinned_memory + CONST_CAST(GLEW_AMD_pinned_memory) = _glewSearchExtension("GL_AMD_pinned_memory", extStart, extEnd); +#endif /* GL_AMD_pinned_memory */ +#ifdef GL_AMD_query_buffer_object + CONST_CAST(GLEW_AMD_query_buffer_object) = _glewSearchExtension("GL_AMD_query_buffer_object", extStart, extEnd); +#endif /* GL_AMD_query_buffer_object */ #ifdef GL_AMD_sample_positions CONST_CAST(GLEW_AMD_sample_positions) = _glewSearchExtension("GL_AMD_sample_positions", extStart, extEnd); if (glewExperimental || GLEW_AMD_sample_positions) CONST_CAST(GLEW_AMD_sample_positions) = !_glewInit_GL_AMD_sample_positions(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8215,16 +9640,74 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_AMD_shader_stencil_export CONST_CAST(GLEW_AMD_shader_stencil_export) = _glewSearchExtension("GL_AMD_shader_stencil_export", extStart, extEnd); #endif /* GL_AMD_shader_stencil_export */ +#ifdef GL_AMD_shader_trinary_minmax + CONST_CAST(GLEW_AMD_shader_trinary_minmax) = _glewSearchExtension("GL_AMD_shader_trinary_minmax", extStart, extEnd); +#endif /* GL_AMD_shader_trinary_minmax */ +#ifdef GL_AMD_sparse_texture + CONST_CAST(GLEW_AMD_sparse_texture) = _glewSearchExtension("GL_AMD_sparse_texture", extStart, extEnd); + if (glewExperimental || GLEW_AMD_sparse_texture) CONST_CAST(GLEW_AMD_sparse_texture) = !_glewInit_GL_AMD_sparse_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_sparse_texture */ +#ifdef GL_AMD_stencil_operation_extended + CONST_CAST(GLEW_AMD_stencil_operation_extended) = _glewSearchExtension("GL_AMD_stencil_operation_extended", extStart, extEnd); + if (glewExperimental || GLEW_AMD_stencil_operation_extended) CONST_CAST(GLEW_AMD_stencil_operation_extended) = !_glewInit_GL_AMD_stencil_operation_extended(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_stencil_operation_extended */ #ifdef GL_AMD_texture_texture4 CONST_CAST(GLEW_AMD_texture_texture4) = _glewSearchExtension("GL_AMD_texture_texture4", extStart, extEnd); #endif /* GL_AMD_texture_texture4 */ #ifdef GL_AMD_transform_feedback3_lines_triangles CONST_CAST(GLEW_AMD_transform_feedback3_lines_triangles) = _glewSearchExtension("GL_AMD_transform_feedback3_lines_triangles", extStart, extEnd); #endif /* GL_AMD_transform_feedback3_lines_triangles */ +#ifdef GL_AMD_vertex_shader_layer + CONST_CAST(GLEW_AMD_vertex_shader_layer) = _glewSearchExtension("GL_AMD_vertex_shader_layer", extStart, extEnd); +#endif /* GL_AMD_vertex_shader_layer */ #ifdef GL_AMD_vertex_shader_tessellator CONST_CAST(GLEW_AMD_vertex_shader_tessellator) = _glewSearchExtension("GL_AMD_vertex_shader_tessellator", extStart, extEnd); if (glewExperimental || GLEW_AMD_vertex_shader_tessellator) CONST_CAST(GLEW_AMD_vertex_shader_tessellator) = !_glewInit_GL_AMD_vertex_shader_tessellator(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_vertex_shader_tessellator */ +#ifdef GL_AMD_vertex_shader_viewport_index + CONST_CAST(GLEW_AMD_vertex_shader_viewport_index) = _glewSearchExtension("GL_AMD_vertex_shader_viewport_index", extStart, extEnd); +#endif /* GL_AMD_vertex_shader_viewport_index */ +#ifdef GL_ANGLE_depth_texture + CONST_CAST(GLEW_ANGLE_depth_texture) = _glewSearchExtension("GL_ANGLE_depth_texture", extStart, extEnd); +#endif /* GL_ANGLE_depth_texture */ +#ifdef GL_ANGLE_framebuffer_blit + CONST_CAST(GLEW_ANGLE_framebuffer_blit) = _glewSearchExtension("GL_ANGLE_framebuffer_blit", extStart, extEnd); + if (glewExperimental || GLEW_ANGLE_framebuffer_blit) CONST_CAST(GLEW_ANGLE_framebuffer_blit) = !_glewInit_GL_ANGLE_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ANGLE_framebuffer_blit */ +#ifdef GL_ANGLE_framebuffer_multisample + CONST_CAST(GLEW_ANGLE_framebuffer_multisample) = _glewSearchExtension("GL_ANGLE_framebuffer_multisample", extStart, extEnd); + if (glewExperimental || GLEW_ANGLE_framebuffer_multisample) CONST_CAST(GLEW_ANGLE_framebuffer_multisample) = !_glewInit_GL_ANGLE_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ANGLE_framebuffer_multisample */ +#ifdef GL_ANGLE_instanced_arrays + CONST_CAST(GLEW_ANGLE_instanced_arrays) = _glewSearchExtension("GL_ANGLE_instanced_arrays", extStart, extEnd); + if (glewExperimental || GLEW_ANGLE_instanced_arrays) CONST_CAST(GLEW_ANGLE_instanced_arrays) = !_glewInit_GL_ANGLE_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ANGLE_instanced_arrays */ +#ifdef GL_ANGLE_pack_reverse_row_order + CONST_CAST(GLEW_ANGLE_pack_reverse_row_order) = _glewSearchExtension("GL_ANGLE_pack_reverse_row_order", extStart, extEnd); +#endif /* GL_ANGLE_pack_reverse_row_order */ +#ifdef GL_ANGLE_program_binary + CONST_CAST(GLEW_ANGLE_program_binary) = _glewSearchExtension("GL_ANGLE_program_binary", extStart, extEnd); +#endif /* GL_ANGLE_program_binary */ +#ifdef GL_ANGLE_texture_compression_dxt1 + CONST_CAST(GLEW_ANGLE_texture_compression_dxt1) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt1", extStart, extEnd); +#endif /* GL_ANGLE_texture_compression_dxt1 */ +#ifdef GL_ANGLE_texture_compression_dxt3 + CONST_CAST(GLEW_ANGLE_texture_compression_dxt3) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt3", extStart, extEnd); +#endif /* GL_ANGLE_texture_compression_dxt3 */ +#ifdef GL_ANGLE_texture_compression_dxt5 + CONST_CAST(GLEW_ANGLE_texture_compression_dxt5) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt5", extStart, extEnd); +#endif /* GL_ANGLE_texture_compression_dxt5 */ +#ifdef GL_ANGLE_texture_usage + CONST_CAST(GLEW_ANGLE_texture_usage) = _glewSearchExtension("GL_ANGLE_texture_usage", extStart, extEnd); +#endif /* GL_ANGLE_texture_usage */ +#ifdef GL_ANGLE_timer_query + CONST_CAST(GLEW_ANGLE_timer_query) = _glewSearchExtension("GL_ANGLE_timer_query", extStart, extEnd); + if (glewExperimental || GLEW_ANGLE_timer_query) CONST_CAST(GLEW_ANGLE_timer_query) = !_glewInit_GL_ANGLE_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ANGLE_timer_query */ +#ifdef GL_ANGLE_translated_shader_source + CONST_CAST(GLEW_ANGLE_translated_shader_source) = _glewSearchExtension("GL_ANGLE_translated_shader_source", extStart, extEnd); + if (glewExperimental || GLEW_ANGLE_translated_shader_source) CONST_CAST(GLEW_ANGLE_translated_shader_source) = !_glewInit_GL_ANGLE_translated_shader_source(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ANGLE_translated_shader_source */ #ifdef GL_APPLE_aux_depth_stencil CONST_CAST(GLEW_APPLE_aux_depth_stencil) = _glewSearchExtension("GL_APPLE_aux_depth_stencil", extStart, extEnd); #endif /* GL_APPLE_aux_depth_stencil */ @@ -8288,14 +9771,40 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_ARB_ES2_compatibility) = _glewSearchExtension("GL_ARB_ES2_compatibility", extStart, extEnd); if (glewExperimental || GLEW_ARB_ES2_compatibility) CONST_CAST(GLEW_ARB_ES2_compatibility) = !_glewInit_GL_ARB_ES2_compatibility(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_ES2_compatibility */ +#ifdef GL_ARB_ES3_compatibility + CONST_CAST(GLEW_ARB_ES3_compatibility) = _glewSearchExtension("GL_ARB_ES3_compatibility", extStart, extEnd); +#endif /* GL_ARB_ES3_compatibility */ +#ifdef GL_ARB_arrays_of_arrays + CONST_CAST(GLEW_ARB_arrays_of_arrays) = _glewSearchExtension("GL_ARB_arrays_of_arrays", extStart, extEnd); +#endif /* GL_ARB_arrays_of_arrays */ +#ifdef GL_ARB_base_instance + CONST_CAST(GLEW_ARB_base_instance) = _glewSearchExtension("GL_ARB_base_instance", extStart, extEnd); + if (glewExperimental || GLEW_ARB_base_instance) CONST_CAST(GLEW_ARB_base_instance) = !_glewInit_GL_ARB_base_instance(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_base_instance */ +#ifdef GL_ARB_bindless_texture + CONST_CAST(GLEW_ARB_bindless_texture) = _glewSearchExtension("GL_ARB_bindless_texture", extStart, extEnd); + if (glewExperimental || GLEW_ARB_bindless_texture) CONST_CAST(GLEW_ARB_bindless_texture) = !_glewInit_GL_ARB_bindless_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_bindless_texture */ #ifdef GL_ARB_blend_func_extended CONST_CAST(GLEW_ARB_blend_func_extended) = _glewSearchExtension("GL_ARB_blend_func_extended", extStart, extEnd); if (glewExperimental || GLEW_ARB_blend_func_extended) CONST_CAST(GLEW_ARB_blend_func_extended) = !_glewInit_GL_ARB_blend_func_extended(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_blend_func_extended */ +#ifdef GL_ARB_buffer_storage + CONST_CAST(GLEW_ARB_buffer_storage) = _glewSearchExtension("GL_ARB_buffer_storage", extStart, extEnd); + if (glewExperimental || GLEW_ARB_buffer_storage) CONST_CAST(GLEW_ARB_buffer_storage) = !_glewInit_GL_ARB_buffer_storage(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_buffer_storage */ #ifdef GL_ARB_cl_event CONST_CAST(GLEW_ARB_cl_event) = _glewSearchExtension("GL_ARB_cl_event", extStart, extEnd); if (glewExperimental || GLEW_ARB_cl_event) CONST_CAST(GLEW_ARB_cl_event) = !_glewInit_GL_ARB_cl_event(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_cl_event */ +#ifdef GL_ARB_clear_buffer_object + CONST_CAST(GLEW_ARB_clear_buffer_object) = _glewSearchExtension("GL_ARB_clear_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_clear_buffer_object) CONST_CAST(GLEW_ARB_clear_buffer_object) = !_glewInit_GL_ARB_clear_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_clear_buffer_object */ +#ifdef GL_ARB_clear_texture + CONST_CAST(GLEW_ARB_clear_texture) = _glewSearchExtension("GL_ARB_clear_texture", extStart, extEnd); + if (glewExperimental || GLEW_ARB_clear_texture) CONST_CAST(GLEW_ARB_clear_texture) = !_glewInit_GL_ARB_clear_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_clear_texture */ #ifdef GL_ARB_color_buffer_float CONST_CAST(GLEW_ARB_color_buffer_float) = _glewSearchExtension("GL_ARB_color_buffer_float", extStart, extEnd); if (glewExperimental || GLEW_ARB_color_buffer_float) CONST_CAST(GLEW_ARB_color_buffer_float) = !_glewInit_GL_ARB_color_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8303,10 +9812,28 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_compatibility CONST_CAST(GLEW_ARB_compatibility) = _glewSearchExtension("GL_ARB_compatibility", extStart, extEnd); #endif /* GL_ARB_compatibility */ +#ifdef GL_ARB_compressed_texture_pixel_storage + CONST_CAST(GLEW_ARB_compressed_texture_pixel_storage) = _glewSearchExtension("GL_ARB_compressed_texture_pixel_storage", extStart, extEnd); +#endif /* GL_ARB_compressed_texture_pixel_storage */ +#ifdef GL_ARB_compute_shader + CONST_CAST(GLEW_ARB_compute_shader) = _glewSearchExtension("GL_ARB_compute_shader", extStart, extEnd); + if (glewExperimental || GLEW_ARB_compute_shader) CONST_CAST(GLEW_ARB_compute_shader) = !_glewInit_GL_ARB_compute_shader(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_compute_shader */ +#ifdef GL_ARB_compute_variable_group_size + CONST_CAST(GLEW_ARB_compute_variable_group_size) = _glewSearchExtension("GL_ARB_compute_variable_group_size", extStart, extEnd); + if (glewExperimental || GLEW_ARB_compute_variable_group_size) CONST_CAST(GLEW_ARB_compute_variable_group_size) = !_glewInit_GL_ARB_compute_variable_group_size(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_compute_variable_group_size */ +#ifdef GL_ARB_conservative_depth + CONST_CAST(GLEW_ARB_conservative_depth) = _glewSearchExtension("GL_ARB_conservative_depth", extStart, extEnd); +#endif /* GL_ARB_conservative_depth */ #ifdef GL_ARB_copy_buffer CONST_CAST(GLEW_ARB_copy_buffer) = _glewSearchExtension("GL_ARB_copy_buffer", extStart, extEnd); if (glewExperimental || GLEW_ARB_copy_buffer) CONST_CAST(GLEW_ARB_copy_buffer) = !_glewInit_GL_ARB_copy_buffer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_copy_buffer */ +#ifdef GL_ARB_copy_image + CONST_CAST(GLEW_ARB_copy_image) = _glewSearchExtension("GL_ARB_copy_image", extStart, extEnd); + if (glewExperimental || GLEW_ARB_copy_image) CONST_CAST(GLEW_ARB_copy_image) = !_glewInit_GL_ARB_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_copy_image */ #ifdef GL_ARB_debug_output CONST_CAST(GLEW_ARB_debug_output) = _glewSearchExtension("GL_ARB_debug_output", extStart, extEnd); if (glewExperimental || GLEW_ARB_debug_output) CONST_CAST(GLEW_ARB_debug_output) = !_glewInit_GL_ARB_debug_output(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8339,12 +9866,21 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_draw_instanced CONST_CAST(GLEW_ARB_draw_instanced) = _glewSearchExtension("GL_ARB_draw_instanced", extStart, extEnd); #endif /* GL_ARB_draw_instanced */ +#ifdef GL_ARB_enhanced_layouts + CONST_CAST(GLEW_ARB_enhanced_layouts) = _glewSearchExtension("GL_ARB_enhanced_layouts", extStart, extEnd); +#endif /* GL_ARB_enhanced_layouts */ #ifdef GL_ARB_explicit_attrib_location CONST_CAST(GLEW_ARB_explicit_attrib_location) = _glewSearchExtension("GL_ARB_explicit_attrib_location", extStart, extEnd); #endif /* GL_ARB_explicit_attrib_location */ +#ifdef GL_ARB_explicit_uniform_location + CONST_CAST(GLEW_ARB_explicit_uniform_location) = _glewSearchExtension("GL_ARB_explicit_uniform_location", extStart, extEnd); +#endif /* GL_ARB_explicit_uniform_location */ #ifdef GL_ARB_fragment_coord_conventions CONST_CAST(GLEW_ARB_fragment_coord_conventions) = _glewSearchExtension("GL_ARB_fragment_coord_conventions", extStart, extEnd); #endif /* GL_ARB_fragment_coord_conventions */ +#ifdef GL_ARB_fragment_layer_viewport + CONST_CAST(GLEW_ARB_fragment_layer_viewport) = _glewSearchExtension("GL_ARB_fragment_layer_viewport", extStart, extEnd); +#endif /* GL_ARB_fragment_layer_viewport */ #ifdef GL_ARB_fragment_program CONST_CAST(GLEW_ARB_fragment_program) = _glewSearchExtension("GL_ARB_fragment_program", extStart, extEnd); #endif /* GL_ARB_fragment_program */ @@ -8354,6 +9890,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_fragment_shader CONST_CAST(GLEW_ARB_fragment_shader) = _glewSearchExtension("GL_ARB_fragment_shader", extStart, extEnd); #endif /* GL_ARB_fragment_shader */ +#ifdef GL_ARB_framebuffer_no_attachments + CONST_CAST(GLEW_ARB_framebuffer_no_attachments) = _glewSearchExtension("GL_ARB_framebuffer_no_attachments", extStart, extEnd); + if (glewExperimental || GLEW_ARB_framebuffer_no_attachments) CONST_CAST(GLEW_ARB_framebuffer_no_attachments) = !_glewInit_GL_ARB_framebuffer_no_attachments(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_framebuffer_no_attachments */ #ifdef GL_ARB_framebuffer_object CONST_CAST(GLEW_ARB_framebuffer_object) = _glewSearchExtension("GL_ARB_framebuffer_object", extStart, extEnd); if (glewExperimental || GLEW_ARB_framebuffer_object) CONST_CAST(GLEW_ARB_framebuffer_object) = !_glewInit_GL_ARB_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8386,10 +9926,29 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_ARB_imaging) = _glewSearchExtension("GL_ARB_imaging", extStart, extEnd); if (glewExperimental || GLEW_ARB_imaging) CONST_CAST(GLEW_ARB_imaging) = !_glewInit_GL_ARB_imaging(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_imaging */ +#ifdef GL_ARB_indirect_parameters + CONST_CAST(GLEW_ARB_indirect_parameters) = _glewSearchExtension("GL_ARB_indirect_parameters", extStart, extEnd); + if (glewExperimental || GLEW_ARB_indirect_parameters) CONST_CAST(GLEW_ARB_indirect_parameters) = !_glewInit_GL_ARB_indirect_parameters(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_indirect_parameters */ #ifdef GL_ARB_instanced_arrays CONST_CAST(GLEW_ARB_instanced_arrays) = _glewSearchExtension("GL_ARB_instanced_arrays", extStart, extEnd); if (glewExperimental || GLEW_ARB_instanced_arrays) CONST_CAST(GLEW_ARB_instanced_arrays) = !_glewInit_GL_ARB_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_instanced_arrays */ +#ifdef GL_ARB_internalformat_query + CONST_CAST(GLEW_ARB_internalformat_query) = _glewSearchExtension("GL_ARB_internalformat_query", extStart, extEnd); + if (glewExperimental || GLEW_ARB_internalformat_query) CONST_CAST(GLEW_ARB_internalformat_query) = !_glewInit_GL_ARB_internalformat_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_internalformat_query */ +#ifdef GL_ARB_internalformat_query2 + CONST_CAST(GLEW_ARB_internalformat_query2) = _glewSearchExtension("GL_ARB_internalformat_query2", extStart, extEnd); + if (glewExperimental || GLEW_ARB_internalformat_query2) CONST_CAST(GLEW_ARB_internalformat_query2) = !_glewInit_GL_ARB_internalformat_query2(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_internalformat_query2 */ +#ifdef GL_ARB_invalidate_subdata + CONST_CAST(GLEW_ARB_invalidate_subdata) = _glewSearchExtension("GL_ARB_invalidate_subdata", extStart, extEnd); + if (glewExperimental || GLEW_ARB_invalidate_subdata) CONST_CAST(GLEW_ARB_invalidate_subdata) = !_glewInit_GL_ARB_invalidate_subdata(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_invalidate_subdata */ +#ifdef GL_ARB_map_buffer_alignment + CONST_CAST(GLEW_ARB_map_buffer_alignment) = _glewSearchExtension("GL_ARB_map_buffer_alignment", extStart, extEnd); +#endif /* GL_ARB_map_buffer_alignment */ #ifdef GL_ARB_map_buffer_range CONST_CAST(GLEW_ARB_map_buffer_range) = _glewSearchExtension("GL_ARB_map_buffer_range", extStart, extEnd); if (glewExperimental || GLEW_ARB_map_buffer_range) CONST_CAST(GLEW_ARB_map_buffer_range) = !_glewInit_GL_ARB_map_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8398,6 +9957,14 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_ARB_matrix_palette) = _glewSearchExtension("GL_ARB_matrix_palette", extStart, extEnd); if (glewExperimental || GLEW_ARB_matrix_palette) CONST_CAST(GLEW_ARB_matrix_palette) = !_glewInit_GL_ARB_matrix_palette(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_matrix_palette */ +#ifdef GL_ARB_multi_bind + CONST_CAST(GLEW_ARB_multi_bind) = _glewSearchExtension("GL_ARB_multi_bind", extStart, extEnd); + if (glewExperimental || GLEW_ARB_multi_bind) CONST_CAST(GLEW_ARB_multi_bind) = !_glewInit_GL_ARB_multi_bind(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_multi_bind */ +#ifdef GL_ARB_multi_draw_indirect + CONST_CAST(GLEW_ARB_multi_draw_indirect) = _glewSearchExtension("GL_ARB_multi_draw_indirect", extStart, extEnd); + if (glewExperimental || GLEW_ARB_multi_draw_indirect) CONST_CAST(GLEW_ARB_multi_draw_indirect) = !_glewInit_GL_ARB_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_multi_draw_indirect */ #ifdef GL_ARB_multisample CONST_CAST(GLEW_ARB_multisample) = _glewSearchExtension("GL_ARB_multisample", extStart, extEnd); if (glewExperimental || GLEW_ARB_multisample) CONST_CAST(GLEW_ARB_multisample) = !_glewInit_GL_ARB_multisample(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8423,14 +9990,30 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_point_sprite CONST_CAST(GLEW_ARB_point_sprite) = _glewSearchExtension("GL_ARB_point_sprite", extStart, extEnd); #endif /* GL_ARB_point_sprite */ +#ifdef GL_ARB_program_interface_query + CONST_CAST(GLEW_ARB_program_interface_query) = _glewSearchExtension("GL_ARB_program_interface_query", extStart, extEnd); + if (glewExperimental || GLEW_ARB_program_interface_query) CONST_CAST(GLEW_ARB_program_interface_query) = !_glewInit_GL_ARB_program_interface_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_program_interface_query */ #ifdef GL_ARB_provoking_vertex CONST_CAST(GLEW_ARB_provoking_vertex) = _glewSearchExtension("GL_ARB_provoking_vertex", extStart, extEnd); if (glewExperimental || GLEW_ARB_provoking_vertex) CONST_CAST(GLEW_ARB_provoking_vertex) = !_glewInit_GL_ARB_provoking_vertex(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_provoking_vertex */ +#ifdef GL_ARB_query_buffer_object + CONST_CAST(GLEW_ARB_query_buffer_object) = _glewSearchExtension("GL_ARB_query_buffer_object", extStart, extEnd); +#endif /* GL_ARB_query_buffer_object */ +#ifdef GL_ARB_robust_buffer_access_behavior + CONST_CAST(GLEW_ARB_robust_buffer_access_behavior) = _glewSearchExtension("GL_ARB_robust_buffer_access_behavior", extStart, extEnd); +#endif /* GL_ARB_robust_buffer_access_behavior */ #ifdef GL_ARB_robustness CONST_CAST(GLEW_ARB_robustness) = _glewSearchExtension("GL_ARB_robustness", extStart, extEnd); if (glewExperimental || GLEW_ARB_robustness) CONST_CAST(GLEW_ARB_robustness) = !_glewInit_GL_ARB_robustness(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_robustness */ +#ifdef GL_ARB_robustness_application_isolation + CONST_CAST(GLEW_ARB_robustness_application_isolation) = _glewSearchExtension("GL_ARB_robustness_application_isolation", extStart, extEnd); +#endif /* GL_ARB_robustness_application_isolation */ +#ifdef GL_ARB_robustness_share_group_isolation + CONST_CAST(GLEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("GL_ARB_robustness_share_group_isolation", extStart, extEnd); +#endif /* GL_ARB_robustness_share_group_isolation */ #ifdef GL_ARB_sample_shading CONST_CAST(GLEW_ARB_sample_shading) = _glewSearchExtension("GL_ARB_sample_shading", extStart, extEnd); if (glewExperimental || GLEW_ARB_sample_shading) CONST_CAST(GLEW_ARB_sample_shading) = !_glewInit_GL_ARB_sample_shading(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8442,13 +10025,33 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_seamless_cube_map CONST_CAST(GLEW_ARB_seamless_cube_map) = _glewSearchExtension("GL_ARB_seamless_cube_map", extStart, extEnd); #endif /* GL_ARB_seamless_cube_map */ +#ifdef GL_ARB_seamless_cubemap_per_texture + CONST_CAST(GLEW_ARB_seamless_cubemap_per_texture) = _glewSearchExtension("GL_ARB_seamless_cubemap_per_texture", extStart, extEnd); +#endif /* GL_ARB_seamless_cubemap_per_texture */ #ifdef GL_ARB_separate_shader_objects CONST_CAST(GLEW_ARB_separate_shader_objects) = _glewSearchExtension("GL_ARB_separate_shader_objects", extStart, extEnd); if (glewExperimental || GLEW_ARB_separate_shader_objects) CONST_CAST(GLEW_ARB_separate_shader_objects) = !_glewInit_GL_ARB_separate_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_separate_shader_objects */ +#ifdef GL_ARB_shader_atomic_counters + CONST_CAST(GLEW_ARB_shader_atomic_counters) = _glewSearchExtension("GL_ARB_shader_atomic_counters", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shader_atomic_counters) CONST_CAST(GLEW_ARB_shader_atomic_counters) = !_glewInit_GL_ARB_shader_atomic_counters(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_shader_atomic_counters */ #ifdef GL_ARB_shader_bit_encoding CONST_CAST(GLEW_ARB_shader_bit_encoding) = _glewSearchExtension("GL_ARB_shader_bit_encoding", extStart, extEnd); #endif /* GL_ARB_shader_bit_encoding */ +#ifdef GL_ARB_shader_draw_parameters + CONST_CAST(GLEW_ARB_shader_draw_parameters) = _glewSearchExtension("GL_ARB_shader_draw_parameters", extStart, extEnd); +#endif /* GL_ARB_shader_draw_parameters */ +#ifdef GL_ARB_shader_group_vote + CONST_CAST(GLEW_ARB_shader_group_vote) = _glewSearchExtension("GL_ARB_shader_group_vote", extStart, extEnd); +#endif /* GL_ARB_shader_group_vote */ +#ifdef GL_ARB_shader_image_load_store + CONST_CAST(GLEW_ARB_shader_image_load_store) = _glewSearchExtension("GL_ARB_shader_image_load_store", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shader_image_load_store) CONST_CAST(GLEW_ARB_shader_image_load_store) = !_glewInit_GL_ARB_shader_image_load_store(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_shader_image_load_store */ +#ifdef GL_ARB_shader_image_size + CONST_CAST(GLEW_ARB_shader_image_size) = _glewSearchExtension("GL_ARB_shader_image_size", extStart, extEnd); +#endif /* GL_ARB_shader_image_size */ #ifdef GL_ARB_shader_objects CONST_CAST(GLEW_ARB_shader_objects) = _glewSearchExtension("GL_ARB_shader_objects", extStart, extEnd); if (glewExperimental || GLEW_ARB_shader_objects) CONST_CAST(GLEW_ARB_shader_objects) = !_glewInit_GL_ARB_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8459,6 +10062,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_shader_stencil_export CONST_CAST(GLEW_ARB_shader_stencil_export) = _glewSearchExtension("GL_ARB_shader_stencil_export", extStart, extEnd); #endif /* GL_ARB_shader_stencil_export */ +#ifdef GL_ARB_shader_storage_buffer_object + CONST_CAST(GLEW_ARB_shader_storage_buffer_object) = _glewSearchExtension("GL_ARB_shader_storage_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shader_storage_buffer_object) CONST_CAST(GLEW_ARB_shader_storage_buffer_object) = !_glewInit_GL_ARB_shader_storage_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_shader_storage_buffer_object */ #ifdef GL_ARB_shader_subroutine CONST_CAST(GLEW_ARB_shader_subroutine) = _glewSearchExtension("GL_ARB_shader_subroutine", extStart, extEnd); if (glewExperimental || GLEW_ARB_shader_subroutine) CONST_CAST(GLEW_ARB_shader_subroutine) = !_glewInit_GL_ARB_shader_subroutine(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8469,16 +10076,29 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_shading_language_100 CONST_CAST(GLEW_ARB_shading_language_100) = _glewSearchExtension("GL_ARB_shading_language_100", extStart, extEnd); #endif /* GL_ARB_shading_language_100 */ +#ifdef GL_ARB_shading_language_420pack + CONST_CAST(GLEW_ARB_shading_language_420pack) = _glewSearchExtension("GL_ARB_shading_language_420pack", extStart, extEnd); +#endif /* GL_ARB_shading_language_420pack */ #ifdef GL_ARB_shading_language_include CONST_CAST(GLEW_ARB_shading_language_include) = _glewSearchExtension("GL_ARB_shading_language_include", extStart, extEnd); if (glewExperimental || GLEW_ARB_shading_language_include) CONST_CAST(GLEW_ARB_shading_language_include) = !_glewInit_GL_ARB_shading_language_include(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_shading_language_include */ +#ifdef GL_ARB_shading_language_packing + CONST_CAST(GLEW_ARB_shading_language_packing) = _glewSearchExtension("GL_ARB_shading_language_packing", extStart, extEnd); +#endif /* GL_ARB_shading_language_packing */ #ifdef GL_ARB_shadow CONST_CAST(GLEW_ARB_shadow) = _glewSearchExtension("GL_ARB_shadow", extStart, extEnd); #endif /* GL_ARB_shadow */ #ifdef GL_ARB_shadow_ambient CONST_CAST(GLEW_ARB_shadow_ambient) = _glewSearchExtension("GL_ARB_shadow_ambient", extStart, extEnd); #endif /* GL_ARB_shadow_ambient */ +#ifdef GL_ARB_sparse_texture + CONST_CAST(GLEW_ARB_sparse_texture) = _glewSearchExtension("GL_ARB_sparse_texture", extStart, extEnd); + if (glewExperimental || GLEW_ARB_sparse_texture) CONST_CAST(GLEW_ARB_sparse_texture) = !_glewInit_GL_ARB_sparse_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_sparse_texture */ +#ifdef GL_ARB_stencil_texturing + CONST_CAST(GLEW_ARB_stencil_texturing) = _glewSearchExtension("GL_ARB_stencil_texturing", extStart, extEnd); +#endif /* GL_ARB_stencil_texturing */ #ifdef GL_ARB_sync CONST_CAST(GLEW_ARB_sync) = _glewSearchExtension("GL_ARB_sync", extStart, extEnd); if (glewExperimental || GLEW_ARB_sync) CONST_CAST(GLEW_ARB_sync) = !_glewInit_GL_ARB_sync(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8497,6 +10117,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_texture_buffer_object_rgb32 CONST_CAST(GLEW_ARB_texture_buffer_object_rgb32) = _glewSearchExtension("GL_ARB_texture_buffer_object_rgb32", extStart, extEnd); #endif /* GL_ARB_texture_buffer_object_rgb32 */ +#ifdef GL_ARB_texture_buffer_range + CONST_CAST(GLEW_ARB_texture_buffer_range) = _glewSearchExtension("GL_ARB_texture_buffer_range", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_buffer_range) CONST_CAST(GLEW_ARB_texture_buffer_range) = !_glewInit_GL_ARB_texture_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_texture_buffer_range */ #ifdef GL_ARB_texture_compression CONST_CAST(GLEW_ARB_texture_compression) = _glewSearchExtension("GL_ARB_texture_compression", extStart, extEnd); if (glewExperimental || GLEW_ARB_texture_compression) CONST_CAST(GLEW_ARB_texture_compression) = !_glewInit_GL_ARB_texture_compression(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8531,6 +10155,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_texture_gather CONST_CAST(GLEW_ARB_texture_gather) = _glewSearchExtension("GL_ARB_texture_gather", extStart, extEnd); #endif /* GL_ARB_texture_gather */ +#ifdef GL_ARB_texture_mirror_clamp_to_edge + CONST_CAST(GLEW_ARB_texture_mirror_clamp_to_edge) = _glewSearchExtension("GL_ARB_texture_mirror_clamp_to_edge", extStart, extEnd); +#endif /* GL_ARB_texture_mirror_clamp_to_edge */ #ifdef GL_ARB_texture_mirrored_repeat CONST_CAST(GLEW_ARB_texture_mirrored_repeat) = _glewSearchExtension("GL_ARB_texture_mirrored_repeat", extStart, extEnd); #endif /* GL_ARB_texture_mirrored_repeat */ @@ -8541,6 +10168,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_texture_non_power_of_two CONST_CAST(GLEW_ARB_texture_non_power_of_two) = _glewSearchExtension("GL_ARB_texture_non_power_of_two", extStart, extEnd); #endif /* GL_ARB_texture_non_power_of_two */ +#ifdef GL_ARB_texture_query_levels + CONST_CAST(GLEW_ARB_texture_query_levels) = _glewSearchExtension("GL_ARB_texture_query_levels", extStart, extEnd); +#endif /* GL_ARB_texture_query_levels */ #ifdef GL_ARB_texture_query_lod CONST_CAST(GLEW_ARB_texture_query_lod) = _glewSearchExtension("GL_ARB_texture_query_lod", extStart, extEnd); #endif /* GL_ARB_texture_query_lod */ @@ -8553,9 +10183,24 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_ARB_texture_rgb10_a2ui CONST_CAST(GLEW_ARB_texture_rgb10_a2ui) = _glewSearchExtension("GL_ARB_texture_rgb10_a2ui", extStart, extEnd); #endif /* GL_ARB_texture_rgb10_a2ui */ +#ifdef GL_ARB_texture_stencil8 + CONST_CAST(GLEW_ARB_texture_stencil8) = _glewSearchExtension("GL_ARB_texture_stencil8", extStart, extEnd); +#endif /* GL_ARB_texture_stencil8 */ +#ifdef GL_ARB_texture_storage + CONST_CAST(GLEW_ARB_texture_storage) = _glewSearchExtension("GL_ARB_texture_storage", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_storage) CONST_CAST(GLEW_ARB_texture_storage) = !_glewInit_GL_ARB_texture_storage(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_texture_storage */ +#ifdef GL_ARB_texture_storage_multisample + CONST_CAST(GLEW_ARB_texture_storage_multisample) = _glewSearchExtension("GL_ARB_texture_storage_multisample", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_storage_multisample) CONST_CAST(GLEW_ARB_texture_storage_multisample) = !_glewInit_GL_ARB_texture_storage_multisample(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_texture_storage_multisample */ #ifdef GL_ARB_texture_swizzle CONST_CAST(GLEW_ARB_texture_swizzle) = _glewSearchExtension("GL_ARB_texture_swizzle", extStart, extEnd); #endif /* GL_ARB_texture_swizzle */ +#ifdef GL_ARB_texture_view + CONST_CAST(GLEW_ARB_texture_view) = _glewSearchExtension("GL_ARB_texture_view", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_view) CONST_CAST(GLEW_ARB_texture_view) = !_glewInit_GL_ARB_texture_view(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_texture_view */ #ifdef GL_ARB_timer_query CONST_CAST(GLEW_ARB_timer_query) = _glewSearchExtension("GL_ARB_timer_query", extStart, extEnd); if (glewExperimental || GLEW_ARB_timer_query) CONST_CAST(GLEW_ARB_timer_query) = !_glewInit_GL_ARB_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8568,6 +10213,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_ARB_transform_feedback3) = _glewSearchExtension("GL_ARB_transform_feedback3", extStart, extEnd); if (glewExperimental || GLEW_ARB_transform_feedback3) CONST_CAST(GLEW_ARB_transform_feedback3) = !_glewInit_GL_ARB_transform_feedback3(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_transform_feedback3 */ +#ifdef GL_ARB_transform_feedback_instanced + CONST_CAST(GLEW_ARB_transform_feedback_instanced) = _glewSearchExtension("GL_ARB_transform_feedback_instanced", extStart, extEnd); + if (glewExperimental || GLEW_ARB_transform_feedback_instanced) CONST_CAST(GLEW_ARB_transform_feedback_instanced) = !_glewInit_GL_ARB_transform_feedback_instanced(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_transform_feedback_instanced */ #ifdef GL_ARB_transpose_matrix CONST_CAST(GLEW_ARB_transpose_matrix) = _glewSearchExtension("GL_ARB_transpose_matrix", extStart, extEnd); if (glewExperimental || GLEW_ARB_transpose_matrix) CONST_CAST(GLEW_ARB_transpose_matrix) = !_glewInit_GL_ARB_transpose_matrix(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8587,6 +10236,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_ARB_vertex_attrib_64bit) = _glewSearchExtension("GL_ARB_vertex_attrib_64bit", extStart, extEnd); if (glewExperimental || GLEW_ARB_vertex_attrib_64bit) CONST_CAST(GLEW_ARB_vertex_attrib_64bit) = !_glewInit_GL_ARB_vertex_attrib_64bit(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_vertex_attrib_64bit */ +#ifdef GL_ARB_vertex_attrib_binding + CONST_CAST(GLEW_ARB_vertex_attrib_binding) = _glewSearchExtension("GL_ARB_vertex_attrib_binding", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_attrib_binding) CONST_CAST(GLEW_ARB_vertex_attrib_binding) = !_glewInit_GL_ARB_vertex_attrib_binding(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_ARB_vertex_attrib_binding */ #ifdef GL_ARB_vertex_blend CONST_CAST(GLEW_ARB_vertex_blend) = _glewSearchExtension("GL_ARB_vertex_blend", extStart, extEnd); if (glewExperimental || GLEW_ARB_vertex_blend) CONST_CAST(GLEW_ARB_vertex_blend) = !_glewInit_GL_ARB_vertex_blend(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8603,6 +10256,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_ARB_vertex_shader) = _glewSearchExtension("GL_ARB_vertex_shader", extStart, extEnd); if (glewExperimental || GLEW_ARB_vertex_shader) CONST_CAST(GLEW_ARB_vertex_shader) = !_glewInit_GL_ARB_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_vertex_shader */ +#ifdef GL_ARB_vertex_type_10f_11f_11f_rev + CONST_CAST(GLEW_ARB_vertex_type_10f_11f_11f_rev) = _glewSearchExtension("GL_ARB_vertex_type_10f_11f_11f_rev", extStart, extEnd); +#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */ #ifdef GL_ARB_vertex_type_2_10_10_10_rev CONST_CAST(GLEW_ARB_vertex_type_2_10_10_10_rev) = _glewSearchExtension("GL_ARB_vertex_type_2_10_10_10_rev", extStart, extEnd); if (glewExperimental || GLEW_ARB_vertex_type_2_10_10_10_rev) CONST_CAST(GLEW_ARB_vertex_type_2_10_10_10_rev) = !_glewInit_GL_ARB_vertex_type_2_10_10_10_rev(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8756,6 +10412,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_EXT_cull_vertex) = _glewSearchExtension("GL_EXT_cull_vertex", extStart, extEnd); if (glewExperimental || GLEW_EXT_cull_vertex) CONST_CAST(GLEW_EXT_cull_vertex) = !_glewInit_GL_EXT_cull_vertex(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_cull_vertex */ +#ifdef GL_EXT_debug_marker + CONST_CAST(GLEW_EXT_debug_marker) = _glewSearchExtension("GL_EXT_debug_marker", extStart, extEnd); + if (glewExperimental || GLEW_EXT_debug_marker) CONST_CAST(GLEW_EXT_debug_marker) = !_glewInit_GL_EXT_debug_marker(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_debug_marker */ #ifdef GL_EXT_depth_bounds_test CONST_CAST(GLEW_EXT_depth_bounds_test) = _glewSearchExtension("GL_EXT_depth_bounds_test", extStart, extEnd); if (glewExperimental || GLEW_EXT_depth_bounds_test) CONST_CAST(GLEW_EXT_depth_bounds_test) = !_glewInit_GL_EXT_depth_bounds_test(GLEW_CONTEXT_ARG_VAR_INIT); @@ -8792,6 +10452,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_EXT_framebuffer_multisample) = _glewSearchExtension("GL_EXT_framebuffer_multisample", extStart, extEnd); if (glewExperimental || GLEW_EXT_framebuffer_multisample) CONST_CAST(GLEW_EXT_framebuffer_multisample) = !_glewInit_GL_EXT_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_framebuffer_multisample */ +#ifdef GL_EXT_framebuffer_multisample_blit_scaled + CONST_CAST(GLEW_EXT_framebuffer_multisample_blit_scaled) = _glewSearchExtension("GL_EXT_framebuffer_multisample_blit_scaled", extStart, extEnd); +#endif /* GL_EXT_framebuffer_multisample_blit_scaled */ #ifdef GL_EXT_framebuffer_object CONST_CAST(GLEW_EXT_framebuffer_object) = _glewSearchExtension("GL_EXT_framebuffer_object", extStart, extEnd); if (glewExperimental || GLEW_EXT_framebuffer_object) CONST_CAST(GLEW_EXT_framebuffer_object) = !_glewInit_GL_EXT_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT); @@ -9083,6 +10746,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_INGR_interlace_read CONST_CAST(GLEW_INGR_interlace_read) = _glewSearchExtension("GL_INGR_interlace_read", extStart, extEnd); #endif /* GL_INGR_interlace_read */ +#ifdef GL_INTEL_map_texture + CONST_CAST(GLEW_INTEL_map_texture) = _glewSearchExtension("GL_INTEL_map_texture", extStart, extEnd); + if (glewExperimental || GLEW_INTEL_map_texture) CONST_CAST(GLEW_INTEL_map_texture) = !_glewInit_GL_INTEL_map_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_INTEL_map_texture */ #ifdef GL_INTEL_parallel_arrays CONST_CAST(GLEW_INTEL_parallel_arrays) = _glewSearchExtension("GL_INTEL_parallel_arrays", extStart, extEnd); if (glewExperimental || GLEW_INTEL_parallel_arrays) CONST_CAST(GLEW_INTEL_parallel_arrays) = !_glewInit_GL_INTEL_parallel_arrays(GLEW_CONTEXT_ARG_VAR_INIT); @@ -9091,6 +10758,13 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_INTEL_texture_scissor) = _glewSearchExtension("GL_INTEL_texture_scissor", extStart, extEnd); if (glewExperimental || GLEW_INTEL_texture_scissor) CONST_CAST(GLEW_INTEL_texture_scissor) = !_glewInit_GL_INTEL_texture_scissor(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_INTEL_texture_scissor */ +#ifdef GL_KHR_debug + CONST_CAST(GLEW_KHR_debug) = _glewSearchExtension("GL_KHR_debug", extStart, extEnd); + if (glewExperimental || GLEW_KHR_debug) CONST_CAST(GLEW_KHR_debug) = !_glewInit_GL_KHR_debug(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_KHR_debug */ +#ifdef GL_KHR_texture_compression_astc_ldr + CONST_CAST(GLEW_KHR_texture_compression_astc_ldr) = _glewSearchExtension("GL_KHR_texture_compression_astc_ldr", extStart, extEnd); +#endif /* GL_KHR_texture_compression_astc_ldr */ #ifdef GL_KTX_buffer_region CONST_CAST(GLEW_KTX_buffer_region) = _glewSearchExtension("GL_KTX_buffer_region", extStart, extEnd); if (glewExperimental || GLEW_KTX_buffer_region) CONST_CAST(GLEW_KTX_buffer_region) = !_glewInit_GL_KTX_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT); @@ -9112,12 +10786,34 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_MESA_ycbcr_texture CONST_CAST(GLEW_MESA_ycbcr_texture) = _glewSearchExtension("GL_MESA_ycbcr_texture", extStart, extEnd); #endif /* GL_MESA_ycbcr_texture */ +#ifdef GL_NVX_conditional_render + CONST_CAST(GLEW_NVX_conditional_render) = _glewSearchExtension("GL_NVX_conditional_render", extStart, extEnd); + if (glewExperimental || GLEW_NVX_conditional_render) CONST_CAST(GLEW_NVX_conditional_render) = !_glewInit_GL_NVX_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NVX_conditional_render */ #ifdef GL_NVX_gpu_memory_info CONST_CAST(GLEW_NVX_gpu_memory_info) = _glewSearchExtension("GL_NVX_gpu_memory_info", extStart, extEnd); #endif /* GL_NVX_gpu_memory_info */ +#ifdef GL_NV_bindless_multi_draw_indirect + CONST_CAST(GLEW_NV_bindless_multi_draw_indirect) = _glewSearchExtension("GL_NV_bindless_multi_draw_indirect", extStart, extEnd); + if (glewExperimental || GLEW_NV_bindless_multi_draw_indirect) CONST_CAST(GLEW_NV_bindless_multi_draw_indirect) = !_glewInit_GL_NV_bindless_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_bindless_multi_draw_indirect */ +#ifdef GL_NV_bindless_texture + CONST_CAST(GLEW_NV_bindless_texture) = _glewSearchExtension("GL_NV_bindless_texture", extStart, extEnd); + if (glewExperimental || GLEW_NV_bindless_texture) CONST_CAST(GLEW_NV_bindless_texture) = !_glewInit_GL_NV_bindless_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_bindless_texture */ +#ifdef GL_NV_blend_equation_advanced + CONST_CAST(GLEW_NV_blend_equation_advanced) = _glewSearchExtension("GL_NV_blend_equation_advanced", extStart, extEnd); + if (glewExperimental || GLEW_NV_blend_equation_advanced) CONST_CAST(GLEW_NV_blend_equation_advanced) = !_glewInit_GL_NV_blend_equation_advanced(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_blend_equation_advanced */ +#ifdef GL_NV_blend_equation_advanced_coherent + CONST_CAST(GLEW_NV_blend_equation_advanced_coherent) = _glewSearchExtension("GL_NV_blend_equation_advanced_coherent", extStart, extEnd); +#endif /* GL_NV_blend_equation_advanced_coherent */ #ifdef GL_NV_blend_square CONST_CAST(GLEW_NV_blend_square) = _glewSearchExtension("GL_NV_blend_square", extStart, extEnd); #endif /* GL_NV_blend_square */ +#ifdef GL_NV_compute_program5 + CONST_CAST(GLEW_NV_compute_program5) = _glewSearchExtension("GL_NV_compute_program5", extStart, extEnd); +#endif /* GL_NV_compute_program5 */ #ifdef GL_NV_conditional_render CONST_CAST(GLEW_NV_conditional_render) = _glewSearchExtension("GL_NV_conditional_render", extStart, extEnd); if (glewExperimental || GLEW_NV_conditional_render) CONST_CAST(GLEW_NV_conditional_render) = !_glewInit_GL_NV_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT); @@ -9129,6 +10825,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_NV_copy_image) = _glewSearchExtension("GL_NV_copy_image", extStart, extEnd); if (glewExperimental || GLEW_NV_copy_image) CONST_CAST(GLEW_NV_copy_image) = !_glewInit_GL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_copy_image */ +#ifdef GL_NV_deep_texture3D + CONST_CAST(GLEW_NV_deep_texture3D) = _glewSearchExtension("GL_NV_deep_texture3D", extStart, extEnd); +#endif /* GL_NV_deep_texture3D */ #ifdef GL_NV_depth_buffer_float CONST_CAST(GLEW_NV_depth_buffer_float) = _glewSearchExtension("GL_NV_depth_buffer_float", extStart, extEnd); if (glewExperimental || GLEW_NV_depth_buffer_float) CONST_CAST(GLEW_NV_depth_buffer_float) = !_glewInit_GL_NV_depth_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT); @@ -9139,6 +10838,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_NV_depth_range_unclamped CONST_CAST(GLEW_NV_depth_range_unclamped) = _glewSearchExtension("GL_NV_depth_range_unclamped", extStart, extEnd); #endif /* GL_NV_depth_range_unclamped */ +#ifdef GL_NV_draw_texture + CONST_CAST(GLEW_NV_draw_texture) = _glewSearchExtension("GL_NV_draw_texture", extStart, extEnd); + if (glewExperimental || GLEW_NV_draw_texture) CONST_CAST(GLEW_NV_draw_texture) = !_glewInit_GL_NV_draw_texture(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_draw_texture */ #ifdef GL_NV_evaluators CONST_CAST(GLEW_NV_evaluators) = _glewSearchExtension("GL_NV_evaluators", extStart, extEnd); if (glewExperimental || GLEW_NV_evaluators) CONST_CAST(GLEW_NV_evaluators) = !_glewInit_GL_NV_evaluators(GLEW_CONTEXT_ARG_VAR_INIT); @@ -9188,6 +10891,9 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_NV_gpu_program5 CONST_CAST(GLEW_NV_gpu_program5) = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd); #endif /* GL_NV_gpu_program5 */ +#ifdef GL_NV_gpu_program5_mem_extended + CONST_CAST(GLEW_NV_gpu_program5_mem_extended) = _glewSearchExtension("GL_NV_gpu_program5_mem_extended", extStart, extEnd); +#endif /* GL_NV_gpu_program5_mem_extended */ #ifdef GL_NV_gpu_program_fp64 CONST_CAST(GLEW_NV_gpu_program_fp64) = _glewSearchExtension("GL_NV_gpu_program_fp64", extStart, extEnd); #endif /* GL_NV_gpu_program_fp64 */ @@ -9222,6 +10928,10 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_NV_parameter_buffer_object2 CONST_CAST(GLEW_NV_parameter_buffer_object2) = _glewSearchExtension("GL_NV_parameter_buffer_object2", extStart, extEnd); #endif /* GL_NV_parameter_buffer_object2 */ +#ifdef GL_NV_path_rendering + CONST_CAST(GLEW_NV_path_rendering) = _glewSearchExtension("GL_NV_path_rendering", extStart, extEnd); + if (glewExperimental || GLEW_NV_path_rendering) CONST_CAST(GLEW_NV_path_rendering) = !_glewInit_GL_NV_path_rendering(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_NV_path_rendering */ #ifdef GL_NV_pixel_data_range CONST_CAST(GLEW_NV_pixel_data_range) = _glewSearchExtension("GL_NV_pixel_data_range", extStart, extEnd); if (glewExperimental || GLEW_NV_pixel_data_range) CONST_CAST(GLEW_NV_pixel_data_range) = !_glewInit_GL_NV_pixel_data_range(GLEW_CONTEXT_ARG_VAR_INIT); @@ -9246,10 +10956,19 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLEW_NV_register_combiners2) = _glewSearchExtension("GL_NV_register_combiners2", extStart, extEnd); if (glewExperimental || GLEW_NV_register_combiners2) CONST_CAST(GLEW_NV_register_combiners2) = !_glewInit_GL_NV_register_combiners2(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_register_combiners2 */ +#ifdef GL_NV_shader_atomic_counters + CONST_CAST(GLEW_NV_shader_atomic_counters) = _glewSearchExtension("GL_NV_shader_atomic_counters", extStart, extEnd); +#endif /* GL_NV_shader_atomic_counters */ +#ifdef GL_NV_shader_atomic_float + CONST_CAST(GLEW_NV_shader_atomic_float) = _glewSearchExtension("GL_NV_shader_atomic_float", extStart, extEnd); +#endif /* GL_NV_shader_atomic_float */ #ifdef GL_NV_shader_buffer_load CONST_CAST(GLEW_NV_shader_buffer_load) = _glewSearchExtension("GL_NV_shader_buffer_load", extStart, extEnd); if (glewExperimental || GLEW_NV_shader_buffer_load) CONST_CAST(GLEW_NV_shader_buffer_load) = !_glewInit_GL_NV_shader_buffer_load(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_shader_buffer_load */ +#ifdef GL_NV_shader_storage_buffer_object + CONST_CAST(GLEW_NV_shader_storage_buffer_object) = _glewSearchExtension("GL_NV_shader_storage_buffer_object", extStart, extEnd); +#endif /* GL_NV_shader_storage_buffer_object */ #ifdef GL_NV_tessellation_program5 CONST_CAST(GLEW_NV_tessellation_program5) = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd); #endif /* GL_NV_tessellation_program5 */ @@ -9366,6 +11085,29 @@ GLenum glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_PGI_vertex_hints CONST_CAST(GLEW_PGI_vertex_hints) = _glewSearchExtension("GL_PGI_vertex_hints", extStart, extEnd); #endif /* GL_PGI_vertex_hints */ +#ifdef GL_REGAL_ES1_0_compatibility + CONST_CAST(GLEW_REGAL_ES1_0_compatibility) = _glewSearchExtension("GL_REGAL_ES1_0_compatibility", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_ES1_0_compatibility) CONST_CAST(GLEW_REGAL_ES1_0_compatibility) = !_glewInit_GL_REGAL_ES1_0_compatibility(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_REGAL_ES1_0_compatibility */ +#ifdef GL_REGAL_ES1_1_compatibility + CONST_CAST(GLEW_REGAL_ES1_1_compatibility) = _glewSearchExtension("GL_REGAL_ES1_1_compatibility", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_ES1_1_compatibility) CONST_CAST(GLEW_REGAL_ES1_1_compatibility) = !_glewInit_GL_REGAL_ES1_1_compatibility(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_REGAL_ES1_1_compatibility */ +#ifdef GL_REGAL_enable + CONST_CAST(GLEW_REGAL_enable) = _glewSearchExtension("GL_REGAL_enable", extStart, extEnd); +#endif /* GL_REGAL_enable */ +#ifdef GL_REGAL_error_string + CONST_CAST(GLEW_REGAL_error_string) = _glewSearchExtension("GL_REGAL_error_string", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_error_string) CONST_CAST(GLEW_REGAL_error_string) = !_glewInit_GL_REGAL_error_string(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_REGAL_error_string */ +#ifdef GL_REGAL_extension_query + CONST_CAST(GLEW_REGAL_extension_query) = _glewSearchExtension("GL_REGAL_extension_query", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_extension_query) CONST_CAST(GLEW_REGAL_extension_query) = !_glewInit_GL_REGAL_extension_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_REGAL_extension_query */ +#ifdef GL_REGAL_log + CONST_CAST(GLEW_REGAL_log) = _glewSearchExtension("GL_REGAL_log", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_log) CONST_CAST(GLEW_REGAL_log) = !_glewInit_GL_REGAL_log(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_REGAL_log */ #ifdef GL_REND_screen_coordinates CONST_CAST(GLEW_REND_screen_coordinates) = _glewSearchExtension("GL_REND_screen_coordinates", extStart, extEnd); #endif /* GL_REND_screen_coordinates */ @@ -9745,9 +11487,12 @@ GLboolean __WGLEW_ARB_pbuffer = GL_FALSE; GLboolean __WGLEW_ARB_pixel_format = GL_FALSE; GLboolean __WGLEW_ARB_pixel_format_float = GL_FALSE; GLboolean __WGLEW_ARB_render_texture = GL_FALSE; +GLboolean __WGLEW_ARB_robustness_application_isolation = GL_FALSE; +GLboolean __WGLEW_ARB_robustness_share_group_isolation = GL_FALSE; GLboolean __WGLEW_ATI_pixel_format_float = GL_FALSE; GLboolean __WGLEW_ATI_render_texture_rectangle = GL_FALSE; GLboolean __WGLEW_EXT_create_context_es2_profile = GL_FALSE; +GLboolean __WGLEW_EXT_create_context_es_profile = GL_FALSE; GLboolean __WGLEW_EXT_depth_float = GL_FALSE; GLboolean __WGLEW_EXT_display_color_table = GL_FALSE; GLboolean __WGLEW_EXT_extensions_string = GL_FALSE; @@ -9758,6 +11503,7 @@ GLboolean __WGLEW_EXT_pbuffer = GL_FALSE; GLboolean __WGLEW_EXT_pixel_format = GL_FALSE; GLboolean __WGLEW_EXT_pixel_format_packed_float = GL_FALSE; GLboolean __WGLEW_EXT_swap_control = GL_FALSE; +GLboolean __WGLEW_EXT_swap_control_tear = GL_FALSE; GLboolean __WGLEW_I3D_digital_video_control = GL_FALSE; GLboolean __WGLEW_I3D_gamma = GL_FALSE; GLboolean __WGLEW_I3D_genlock = GL_FALSE; @@ -9765,6 +11511,7 @@ GLboolean __WGLEW_I3D_image_buffer = GL_FALSE; GLboolean __WGLEW_I3D_swap_frame_lock = GL_FALSE; GLboolean __WGLEW_I3D_swap_frame_usage = GL_FALSE; GLboolean __WGLEW_NV_DX_interop = GL_FALSE; +GLboolean __WGLEW_NV_DX_interop2 = GL_FALSE; GLboolean __WGLEW_NV_copy_image = GL_FALSE; GLboolean __WGLEW_NV_float_buffer = GL_FALSE; GLboolean __WGLEW_NV_gpu_affinity = GL_FALSE; @@ -9941,6 +11688,14 @@ static GLboolean _glewInit_WGL_ARB_render_texture (WGLEW_CONTEXT_ARG_DEF_INIT) #endif /* WGL_ARB_render_texture */ +#ifdef WGL_ARB_robustness_application_isolation + +#endif /* WGL_ARB_robustness_application_isolation */ + +#ifdef WGL_ARB_robustness_share_group_isolation + +#endif /* WGL_ARB_robustness_share_group_isolation */ + #ifdef WGL_ATI_pixel_format_float #endif /* WGL_ATI_pixel_format_float */ @@ -9953,6 +11708,10 @@ static GLboolean _glewInit_WGL_ARB_render_texture (WGLEW_CONTEXT_ARG_DEF_INIT) #endif /* WGL_EXT_create_context_es2_profile */ +#ifdef WGL_EXT_create_context_es_profile + +#endif /* WGL_EXT_create_context_es_profile */ + #ifdef WGL_EXT_depth_float #endif /* WGL_EXT_depth_float */ @@ -10058,6 +11817,10 @@ static GLboolean _glewInit_WGL_EXT_swap_control (WGLEW_CONTEXT_ARG_DEF_INIT) #endif /* WGL_EXT_swap_control */ +#ifdef WGL_EXT_swap_control_tear + +#endif /* WGL_EXT_swap_control_tear */ + #ifdef WGL_I3D_digital_video_control static GLboolean _glewInit_WGL_I3D_digital_video_control (WGLEW_CONTEXT_ARG_DEF_INIT) @@ -10180,6 +11943,10 @@ static GLboolean _glewInit_WGL_NV_DX_interop (WGLEW_CONTEXT_ARG_DEF_INIT) #endif /* WGL_NV_DX_interop */ +#ifdef WGL_NV_DX_interop2 + +#endif /* WGL_NV_DX_interop2 */ + #ifdef WGL_NV_copy_image static GLboolean _glewInit_WGL_NV_copy_image (WGLEW_CONTEXT_ARG_DEF_INIT) @@ -10331,7 +12098,7 @@ static GLboolean _glewInit_WGL_OML_sync_control (WGLEW_CONTEXT_ARG_DEF_INIT) static PFNWGLGETEXTENSIONSSTRINGARBPROC _wglewGetExtensionsStringARB = NULL; static PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglewGetExtensionsStringEXT = NULL; -GLboolean wglewGetExtension (const char* name) +GLboolean GLEWAPIENTRY wglewGetExtension (const char* name) { const GLubyte* start; const GLubyte* end; @@ -10348,7 +12115,7 @@ GLboolean wglewGetExtension (const char* name) return _glewSearchExtension(name, start, end); } -GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST) +GLenum GLEWAPIENTRY wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST) { GLboolean crippled; const GLubyte* extStart; @@ -10421,6 +12188,12 @@ GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(WGLEW_ARB_render_texture) = _glewSearchExtension("WGL_ARB_render_texture", extStart, extEnd); if (glewExperimental || WGLEW_ARB_render_texture|| crippled) CONST_CAST(WGLEW_ARB_render_texture)= !_glewInit_WGL_ARB_render_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_ARB_render_texture */ +#ifdef WGL_ARB_robustness_application_isolation + CONST_CAST(WGLEW_ARB_robustness_application_isolation) = _glewSearchExtension("WGL_ARB_robustness_application_isolation", extStart, extEnd); +#endif /* WGL_ARB_robustness_application_isolation */ +#ifdef WGL_ARB_robustness_share_group_isolation + CONST_CAST(WGLEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("WGL_ARB_robustness_share_group_isolation", extStart, extEnd); +#endif /* WGL_ARB_robustness_share_group_isolation */ #ifdef WGL_ATI_pixel_format_float CONST_CAST(WGLEW_ATI_pixel_format_float) = _glewSearchExtension("WGL_ATI_pixel_format_float", extStart, extEnd); #endif /* WGL_ATI_pixel_format_float */ @@ -10430,6 +12203,9 @@ GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST) #ifdef WGL_EXT_create_context_es2_profile CONST_CAST(WGLEW_EXT_create_context_es2_profile) = _glewSearchExtension("WGL_EXT_create_context_es2_profile", extStart, extEnd); #endif /* WGL_EXT_create_context_es2_profile */ +#ifdef WGL_EXT_create_context_es_profile + CONST_CAST(WGLEW_EXT_create_context_es_profile) = _glewSearchExtension("WGL_EXT_create_context_es_profile", extStart, extEnd); +#endif /* WGL_EXT_create_context_es_profile */ #ifdef WGL_EXT_depth_float CONST_CAST(WGLEW_EXT_depth_float) = _glewSearchExtension("WGL_EXT_depth_float", extStart, extEnd); #endif /* WGL_EXT_depth_float */ @@ -10466,6 +12242,9 @@ GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(WGLEW_EXT_swap_control) = _glewSearchExtension("WGL_EXT_swap_control", extStart, extEnd); if (glewExperimental || WGLEW_EXT_swap_control|| crippled) CONST_CAST(WGLEW_EXT_swap_control)= !_glewInit_WGL_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_EXT_swap_control */ +#ifdef WGL_EXT_swap_control_tear + CONST_CAST(WGLEW_EXT_swap_control_tear) = _glewSearchExtension("WGL_EXT_swap_control_tear", extStart, extEnd); +#endif /* WGL_EXT_swap_control_tear */ #ifdef WGL_I3D_digital_video_control CONST_CAST(WGLEW_I3D_digital_video_control) = _glewSearchExtension("WGL_I3D_digital_video_control", extStart, extEnd); if (glewExperimental || WGLEW_I3D_digital_video_control|| crippled) CONST_CAST(WGLEW_I3D_digital_video_control)= !_glewInit_WGL_I3D_digital_video_control(GLEW_CONTEXT_ARG_VAR_INIT); @@ -10494,6 +12273,9 @@ GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(WGLEW_NV_DX_interop) = _glewSearchExtension("WGL_NV_DX_interop", extStart, extEnd); if (glewExperimental || WGLEW_NV_DX_interop|| crippled) CONST_CAST(WGLEW_NV_DX_interop)= !_glewInit_WGL_NV_DX_interop(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_NV_DX_interop */ +#ifdef WGL_NV_DX_interop2 + CONST_CAST(WGLEW_NV_DX_interop2) = _glewSearchExtension("WGL_NV_DX_interop2", extStart, extEnd); +#endif /* WGL_NV_DX_interop2 */ #ifdef WGL_NV_copy_image CONST_CAST(WGLEW_NV_copy_image) = _glewSearchExtension("WGL_NV_copy_image", extStart, extEnd); if (glewExperimental || WGLEW_NV_copy_image|| crippled) CONST_CAST(WGLEW_NV_copy_image)= !_glewInit_WGL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); @@ -10542,7 +12324,7 @@ GLenum wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST) return GLEW_OK; } -#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay = NULL; @@ -10564,6 +12346,16 @@ PFNGLXQUERYCONTEXTPROC __glewXQueryContext = NULL; PFNGLXQUERYDRAWABLEPROC __glewXQueryDrawable = NULL; PFNGLXSELECTEVENTPROC __glewXSelectEvent = NULL; +PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC __glewXBlitContextFramebufferAMD = NULL; +PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC __glewXCreateAssociatedContextAMD = NULL; +PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC __glewXCreateAssociatedContextAttribsAMD = NULL; +PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC __glewXDeleteAssociatedContextAMD = NULL; +PFNGLXGETCONTEXTGPUIDAMDPROC __glewXGetContextGPUIDAMD = NULL; +PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC __glewXGetCurrentAssociatedContextAMD = NULL; +PFNGLXGETGPUIDSAMDPROC __glewXGetGPUIDsAMD = NULL; +PFNGLXGETGPUINFOAMDPROC __glewXGetGPUInfoAMD = NULL; +PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC __glewXMakeAssociatedContextCurrentAMD = NULL; + PFNGLXCREATECONTEXTATTRIBSARBPROC __glewXCreateContextAttribsARB = NULL; PFNGLXBINDTEXIMAGEATIPROC __glewXBindTexImageATI = NULL; @@ -10590,6 +12382,9 @@ PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA = NULL; PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA = NULL; +PFNGLXGETSWAPINTERVALMESAPROC __glewXGetSwapIntervalMESA = NULL; +PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA = NULL; + PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV = NULL; PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV = NULL; @@ -10688,15 +12483,20 @@ GLboolean __GLXEW_ARB_fbconfig_float = GL_FALSE; GLboolean __GLXEW_ARB_framebuffer_sRGB = GL_FALSE; GLboolean __GLXEW_ARB_get_proc_address = GL_FALSE; GLboolean __GLXEW_ARB_multisample = GL_FALSE; +GLboolean __GLXEW_ARB_robustness_application_isolation = GL_FALSE; +GLboolean __GLXEW_ARB_robustness_share_group_isolation = GL_FALSE; GLboolean __GLXEW_ARB_vertex_buffer_object = GL_FALSE; GLboolean __GLXEW_ATI_pixel_format_float = GL_FALSE; GLboolean __GLXEW_ATI_render_texture = GL_FALSE; +GLboolean __GLXEW_EXT_buffer_age = GL_FALSE; GLboolean __GLXEW_EXT_create_context_es2_profile = GL_FALSE; +GLboolean __GLXEW_EXT_create_context_es_profile = GL_FALSE; GLboolean __GLXEW_EXT_fbconfig_packed_float = GL_FALSE; GLboolean __GLXEW_EXT_framebuffer_sRGB = GL_FALSE; GLboolean __GLXEW_EXT_import_context = GL_FALSE; GLboolean __GLXEW_EXT_scene_marker = GL_FALSE; GLboolean __GLXEW_EXT_swap_control = GL_FALSE; +GLboolean __GLXEW_EXT_swap_control_tear = GL_FALSE; GLboolean __GLXEW_EXT_texture_from_pixmap = GL_FALSE; GLboolean __GLXEW_EXT_visual_info = GL_FALSE; GLboolean __GLXEW_EXT_visual_rating = GL_FALSE; @@ -10706,6 +12506,7 @@ GLboolean __GLXEW_MESA_copy_sub_buffer = GL_FALSE; GLboolean __GLXEW_MESA_pixmap_colormap = GL_FALSE; GLboolean __GLXEW_MESA_release_buffers = GL_FALSE; GLboolean __GLXEW_MESA_set_3dfx_mode = GL_FALSE; +GLboolean __GLXEW_MESA_swap_control = GL_FALSE; GLboolean __GLXEW_NV_copy_image = GL_FALSE; GLboolean __GLXEW_NV_float_buffer = GL_FALSE; GLboolean __GLXEW_NV_multisample_coverage = GL_FALSE; @@ -10788,6 +12589,23 @@ static GLboolean _glewInit_GLX_VERSION_1_3 (GLXEW_CONTEXT_ARG_DEF_INIT) #ifdef GLX_AMD_gpu_association +static GLboolean _glewInit_GLX_AMD_gpu_association (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXBlitContextFramebufferAMD = (PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC)glewGetProcAddress((const GLubyte*)"glXBlitContextFramebufferAMD")) == NULL) || r; + r = ((glXCreateAssociatedContextAMD = (PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"glXCreateAssociatedContextAMD")) == NULL) || r; + r = ((glXCreateAssociatedContextAttribsAMD = (PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC)glewGetProcAddress((const GLubyte*)"glXCreateAssociatedContextAttribsAMD")) == NULL) || r; + r = ((glXDeleteAssociatedContextAMD = (PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"glXDeleteAssociatedContextAMD")) == NULL) || r; + r = ((glXGetContextGPUIDAMD = (PFNGLXGETCONTEXTGPUIDAMDPROC)glewGetProcAddress((const GLubyte*)"glXGetContextGPUIDAMD")) == NULL) || r; + r = ((glXGetCurrentAssociatedContextAMD = (PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC)glewGetProcAddress((const GLubyte*)"glXGetCurrentAssociatedContextAMD")) == NULL) || r; + r = ((glXGetGPUIDsAMD = (PFNGLXGETGPUIDSAMDPROC)glewGetProcAddress((const GLubyte*)"glXGetGPUIDsAMD")) == NULL) || r; + r = ((glXGetGPUInfoAMD = (PFNGLXGETGPUINFOAMDPROC)glewGetProcAddress((const GLubyte*)"glXGetGPUInfoAMD")) == NULL) || r; + r = ((glXMakeAssociatedContextCurrentAMD = (PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC)glewGetProcAddress((const GLubyte*)"glXMakeAssociatedContextCurrentAMD")) == NULL) || r; + + return r; +} + #endif /* GLX_AMD_gpu_association */ #ifdef GLX_ARB_create_context @@ -10827,6 +12645,14 @@ static GLboolean _glewInit_GLX_ARB_create_context (GLXEW_CONTEXT_ARG_DEF_INIT) #endif /* GLX_ARB_multisample */ +#ifdef GLX_ARB_robustness_application_isolation + +#endif /* GLX_ARB_robustness_application_isolation */ + +#ifdef GLX_ARB_robustness_share_group_isolation + +#endif /* GLX_ARB_robustness_share_group_isolation */ + #ifdef GLX_ARB_vertex_buffer_object #endif /* GLX_ARB_vertex_buffer_object */ @@ -10850,10 +12676,18 @@ static GLboolean _glewInit_GLX_ATI_render_texture (GLXEW_CONTEXT_ARG_DEF_INIT) #endif /* GLX_ATI_render_texture */ +#ifdef GLX_EXT_buffer_age + +#endif /* GLX_EXT_buffer_age */ + #ifdef GLX_EXT_create_context_es2_profile #endif /* GLX_EXT_create_context_es2_profile */ +#ifdef GLX_EXT_create_context_es_profile + +#endif /* GLX_EXT_create_context_es_profile */ + #ifdef GLX_EXT_fbconfig_packed_float #endif /* GLX_EXT_fbconfig_packed_float */ @@ -10895,6 +12729,10 @@ static GLboolean _glewInit_GLX_EXT_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT) #endif /* GLX_EXT_swap_control */ +#ifdef GLX_EXT_swap_control_tear + +#endif /* GLX_EXT_swap_control_tear */ + #ifdef GLX_EXT_texture_from_pixmap static GLboolean _glewInit_GLX_EXT_texture_from_pixmap (GLXEW_CONTEXT_ARG_DEF_INIT) @@ -10986,6 +12824,20 @@ static GLboolean _glewInit_GLX_MESA_set_3dfx_mode (GLXEW_CONTEXT_ARG_DEF_INIT) #endif /* GLX_MESA_set_3dfx_mode */ +#ifdef GLX_MESA_swap_control + +static GLboolean _glewInit_GLX_MESA_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC)glewGetProcAddress((const GLubyte*)"glXGetSwapIntervalMESA")) == NULL) || r; + r = ((glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glewGetProcAddress((const GLubyte*)"glXSwapIntervalMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_swap_control */ + #ifdef GLX_NV_copy_image static GLboolean _glewInit_GLX_NV_copy_image (GLXEW_CONTEXT_ARG_DEF_INIT) @@ -11370,6 +13222,7 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) #endif /* GLX_3DFX_multisample */ #ifdef GLX_AMD_gpu_association CONST_CAST(GLXEW_AMD_gpu_association) = _glewSearchExtension("GLX_AMD_gpu_association", extStart, extEnd); + if (glewExperimental || GLXEW_AMD_gpu_association) CONST_CAST(GLXEW_AMD_gpu_association) = !_glewInit_GLX_AMD_gpu_association(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_AMD_gpu_association */ #ifdef GLX_ARB_create_context CONST_CAST(GLXEW_ARB_create_context) = _glewSearchExtension("GLX_ARB_create_context", extStart, extEnd); @@ -11393,6 +13246,12 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) #ifdef GLX_ARB_multisample CONST_CAST(GLXEW_ARB_multisample) = _glewSearchExtension("GLX_ARB_multisample", extStart, extEnd); #endif /* GLX_ARB_multisample */ +#ifdef GLX_ARB_robustness_application_isolation + CONST_CAST(GLXEW_ARB_robustness_application_isolation) = _glewSearchExtension("GLX_ARB_robustness_application_isolation", extStart, extEnd); +#endif /* GLX_ARB_robustness_application_isolation */ +#ifdef GLX_ARB_robustness_share_group_isolation + CONST_CAST(GLXEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("GLX_ARB_robustness_share_group_isolation", extStart, extEnd); +#endif /* GLX_ARB_robustness_share_group_isolation */ #ifdef GLX_ARB_vertex_buffer_object CONST_CAST(GLXEW_ARB_vertex_buffer_object) = _glewSearchExtension("GLX_ARB_vertex_buffer_object", extStart, extEnd); #endif /* GLX_ARB_vertex_buffer_object */ @@ -11403,9 +13262,15 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLXEW_ATI_render_texture) = _glewSearchExtension("GLX_ATI_render_texture", extStart, extEnd); if (glewExperimental || GLXEW_ATI_render_texture) CONST_CAST(GLXEW_ATI_render_texture) = !_glewInit_GLX_ATI_render_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_ATI_render_texture */ +#ifdef GLX_EXT_buffer_age + CONST_CAST(GLXEW_EXT_buffer_age) = _glewSearchExtension("GLX_EXT_buffer_age", extStart, extEnd); +#endif /* GLX_EXT_buffer_age */ #ifdef GLX_EXT_create_context_es2_profile CONST_CAST(GLXEW_EXT_create_context_es2_profile) = _glewSearchExtension("GLX_EXT_create_context_es2_profile", extStart, extEnd); #endif /* GLX_EXT_create_context_es2_profile */ +#ifdef GLX_EXT_create_context_es_profile + CONST_CAST(GLXEW_EXT_create_context_es_profile) = _glewSearchExtension("GLX_EXT_create_context_es_profile", extStart, extEnd); +#endif /* GLX_EXT_create_context_es_profile */ #ifdef GLX_EXT_fbconfig_packed_float CONST_CAST(GLXEW_EXT_fbconfig_packed_float) = _glewSearchExtension("GLX_EXT_fbconfig_packed_float", extStart, extEnd); #endif /* GLX_EXT_fbconfig_packed_float */ @@ -11423,6 +13288,9 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLXEW_EXT_swap_control) = _glewSearchExtension("GLX_EXT_swap_control", extStart, extEnd); if (glewExperimental || GLXEW_EXT_swap_control) CONST_CAST(GLXEW_EXT_swap_control) = !_glewInit_GLX_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_EXT_swap_control */ +#ifdef GLX_EXT_swap_control_tear + CONST_CAST(GLXEW_EXT_swap_control_tear) = _glewSearchExtension("GLX_EXT_swap_control_tear", extStart, extEnd); +#endif /* GLX_EXT_swap_control_tear */ #ifdef GLX_EXT_texture_from_pixmap CONST_CAST(GLXEW_EXT_texture_from_pixmap) = _glewSearchExtension("GLX_EXT_texture_from_pixmap", extStart, extEnd); if (glewExperimental || GLXEW_EXT_texture_from_pixmap) CONST_CAST(GLXEW_EXT_texture_from_pixmap) = !_glewInit_GLX_EXT_texture_from_pixmap(GLEW_CONTEXT_ARG_VAR_INIT); @@ -11456,6 +13324,10 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) CONST_CAST(GLXEW_MESA_set_3dfx_mode) = _glewSearchExtension("GLX_MESA_set_3dfx_mode", extStart, extEnd); if (glewExperimental || GLXEW_MESA_set_3dfx_mode) CONST_CAST(GLXEW_MESA_set_3dfx_mode) = !_glewInit_GLX_MESA_set_3dfx_mode(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_MESA_set_3dfx_mode */ +#ifdef GLX_MESA_swap_control + CONST_CAST(GLXEW_MESA_swap_control) = _glewSearchExtension("GLX_MESA_swap_control", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_swap_control) CONST_CAST(GLXEW_MESA_swap_control) = !_glewInit_GLX_MESA_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_swap_control */ #ifdef GLX_NV_copy_image CONST_CAST(GLXEW_NV_copy_image) = _glewSearchExtension("GLX_NV_copy_image", extStart, extEnd); if (glewExperimental || GLXEW_NV_copy_image) CONST_CAST(GLXEW_NV_copy_image) = !_glewInit_GLX_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); @@ -11560,11 +13432,11 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) return GLEW_OK; } -#endif /* !__APPLE__ || GLEW_APPLE_GLX */ +#endif /* !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) */ /* ------------------------------------------------------------------------ */ -const GLubyte* glewGetErrorString (GLenum error) +const GLubyte * GLEWAPIENTRY glewGetErrorString (GLenum error) { static const GLubyte* _glewErrorString[] = { @@ -11578,14 +13450,14 @@ const GLubyte* glewGetErrorString (GLenum error) return _glewErrorString[(int)error > max_error ? max_error : (int)error]; } -const GLubyte* glewGetString (GLenum name) +const GLubyte * GLEWAPIENTRY glewGetString (GLenum name) { static const GLubyte* _glewString[] = { (const GLubyte*)NULL, - (const GLubyte*)"1.6.0", + (const GLubyte*)"1.10.0", (const GLubyte*)"1", - (const GLubyte*)"6", + (const GLubyte*)"10", (const GLubyte*)"0" }; const int max_string = sizeof(_glewString)/sizeof(*_glewString) - 1; @@ -11599,18 +13471,19 @@ GLboolean glewExperimental = GL_FALSE; #if !defined(GLEW_MX) #if defined(_WIN32) -extern GLenum wglewContextInit (void); -#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */ -extern GLenum glxewContextInit (void); +extern GLenum GLEWAPIENTRY wglewContextInit (void); +#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) +extern GLenum GLEWAPIENTRY glxewContextInit (void); #endif /* _WIN32 */ -GLenum glewInit () +GLenum GLEWAPIENTRY glewInit (void) { GLenum r; - if ( (r = glewContextInit()) ) return r; + r = glewContextInit(); + if ( r != 0 ) return r; #if defined(_WIN32) return wglewContextInit(); -#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) /* _UNIX */ +#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) /* _UNIX */ return glxewContextInit(); #else return r; @@ -11619,9 +13492,9 @@ GLenum glewInit () #endif /* !GLEW_MX */ #ifdef GLEW_MX -GLboolean glewContextIsSupported (const GLEWContext* ctx, const char* name) +GLboolean GLEWAPIENTRY glewContextIsSupported (const GLEWContext* ctx, const char* name) #else -GLboolean glewIsSupported (const char* name) +GLboolean GLEWAPIENTRY glewIsSupported (const char* name) #endif { GLubyte* pos = (GLubyte*)name; @@ -11723,6 +13596,27 @@ GLboolean glewIsSupported (const char* name) ret = GLEW_VERSION_4_1; continue; } +#endif +#ifdef GL_VERSION_4_2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"4_2", 3)) + { + ret = GLEW_VERSION_4_2; + continue; + } +#endif +#ifdef GL_VERSION_4_3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"4_3", 3)) + { + ret = GLEW_VERSION_4_3; + continue; + } +#endif +#ifdef GL_VERSION_4_4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"4_4", 3)) + { + ret = GLEW_VERSION_4_4; + continue; + } #endif } if (_glewStrSame2(&pos, &len, (const GLubyte*)"3DFX_", 5)) @@ -11786,6 +13680,20 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_AMD_interleaved_elements + if (_glewStrSame3(&pos, &len, (const GLubyte*)"interleaved_elements", 20)) + { + ret = GLEW_AMD_interleaved_elements; + continue; + } +#endif +#ifdef GL_AMD_multi_draw_indirect + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_indirect", 19)) + { + ret = GLEW_AMD_multi_draw_indirect; + continue; + } +#endif #ifdef GL_AMD_name_gen_delete if (_glewStrSame3(&pos, &len, (const GLubyte*)"name_gen_delete", 15)) { @@ -11800,6 +13708,20 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_AMD_pinned_memory + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pinned_memory", 13)) + { + ret = GLEW_AMD_pinned_memory; + continue; + } +#endif +#ifdef GL_AMD_query_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"query_buffer_object", 19)) + { + ret = GLEW_AMD_query_buffer_object; + continue; + } +#endif #ifdef GL_AMD_sample_positions if (_glewStrSame3(&pos, &len, (const GLubyte*)"sample_positions", 16)) { @@ -11821,6 +13743,27 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_AMD_shader_trinary_minmax + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_trinary_minmax", 21)) + { + ret = GLEW_AMD_shader_trinary_minmax; + continue; + } +#endif +#ifdef GL_AMD_sparse_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sparse_texture", 14)) + { + ret = GLEW_AMD_sparse_texture; + continue; + } +#endif +#ifdef GL_AMD_stencil_operation_extended + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_operation_extended", 26)) + { + ret = GLEW_AMD_stencil_operation_extended; + continue; + } +#endif #ifdef GL_AMD_texture_texture4 if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_texture4", 16)) { @@ -11835,12 +13778,113 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_AMD_vertex_shader_layer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_layer", 19)) + { + ret = GLEW_AMD_vertex_shader_layer; + continue; + } +#endif #ifdef GL_AMD_vertex_shader_tessellator if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_tessellator", 25)) { ret = GLEW_AMD_vertex_shader_tessellator; continue; } +#endif +#ifdef GL_AMD_vertex_shader_viewport_index + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_viewport_index", 28)) + { + ret = GLEW_AMD_vertex_shader_viewport_index; + continue; + } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"ANGLE_", 6)) + { +#ifdef GL_ANGLE_depth_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_texture", 13)) + { + ret = GLEW_ANGLE_depth_texture; + continue; + } +#endif +#ifdef GL_ANGLE_framebuffer_blit + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_blit", 16)) + { + ret = GLEW_ANGLE_framebuffer_blit; + continue; + } +#endif +#ifdef GL_ANGLE_framebuffer_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample", 23)) + { + ret = GLEW_ANGLE_framebuffer_multisample; + continue; + } +#endif +#ifdef GL_ANGLE_instanced_arrays + if (_glewStrSame3(&pos, &len, (const GLubyte*)"instanced_arrays", 16)) + { + ret = GLEW_ANGLE_instanced_arrays; + continue; + } +#endif +#ifdef GL_ANGLE_pack_reverse_row_order + if (_glewStrSame3(&pos, &len, (const GLubyte*)"pack_reverse_row_order", 22)) + { + ret = GLEW_ANGLE_pack_reverse_row_order; + continue; + } +#endif +#ifdef GL_ANGLE_program_binary + if (_glewStrSame3(&pos, &len, (const GLubyte*)"program_binary", 14)) + { + ret = GLEW_ANGLE_program_binary; + continue; + } +#endif +#ifdef GL_ANGLE_texture_compression_dxt1 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt1", 24)) + { + ret = GLEW_ANGLE_texture_compression_dxt1; + continue; + } +#endif +#ifdef GL_ANGLE_texture_compression_dxt3 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt3", 24)) + { + ret = GLEW_ANGLE_texture_compression_dxt3; + continue; + } +#endif +#ifdef GL_ANGLE_texture_compression_dxt5 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_dxt5", 24)) + { + ret = GLEW_ANGLE_texture_compression_dxt5; + continue; + } +#endif +#ifdef GL_ANGLE_texture_usage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_usage", 13)) + { + ret = GLEW_ANGLE_texture_usage; + continue; + } +#endif +#ifdef GL_ANGLE_timer_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"timer_query", 11)) + { + ret = GLEW_ANGLE_timer_query; + continue; + } +#endif +#ifdef GL_ANGLE_translated_shader_source + if (_glewStrSame3(&pos, &len, (const GLubyte*)"translated_shader_source", 24)) + { + ret = GLEW_ANGLE_translated_shader_source; + continue; + } #endif } if (_glewStrSame2(&pos, &len, (const GLubyte*)"APPLE_", 6)) @@ -11974,6 +14018,34 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_ES3_compatibility + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ES3_compatibility", 17)) + { + ret = GLEW_ARB_ES3_compatibility; + continue; + } +#endif +#ifdef GL_ARB_arrays_of_arrays + if (_glewStrSame3(&pos, &len, (const GLubyte*)"arrays_of_arrays", 16)) + { + ret = GLEW_ARB_arrays_of_arrays; + continue; + } +#endif +#ifdef GL_ARB_base_instance + if (_glewStrSame3(&pos, &len, (const GLubyte*)"base_instance", 13)) + { + ret = GLEW_ARB_base_instance; + continue; + } +#endif +#ifdef GL_ARB_bindless_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindless_texture", 16)) + { + ret = GLEW_ARB_bindless_texture; + continue; + } +#endif #ifdef GL_ARB_blend_func_extended if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_func_extended", 19)) { @@ -11981,6 +14053,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_buffer_storage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_storage", 14)) + { + ret = GLEW_ARB_buffer_storage; + continue; + } +#endif #ifdef GL_ARB_cl_event if (_glewStrSame3(&pos, &len, (const GLubyte*)"cl_event", 8)) { @@ -11988,6 +14067,20 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_clear_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"clear_buffer_object", 19)) + { + ret = GLEW_ARB_clear_buffer_object; + continue; + } +#endif +#ifdef GL_ARB_clear_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"clear_texture", 13)) + { + ret = GLEW_ARB_clear_texture; + continue; + } +#endif #ifdef GL_ARB_color_buffer_float if (_glewStrSame3(&pos, &len, (const GLubyte*)"color_buffer_float", 18)) { @@ -12002,6 +14095,34 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_compressed_texture_pixel_storage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"compressed_texture_pixel_storage", 32)) + { + ret = GLEW_ARB_compressed_texture_pixel_storage; + continue; + } +#endif +#ifdef GL_ARB_compute_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"compute_shader", 14)) + { + ret = GLEW_ARB_compute_shader; + continue; + } +#endif +#ifdef GL_ARB_compute_variable_group_size + if (_glewStrSame3(&pos, &len, (const GLubyte*)"compute_variable_group_size", 27)) + { + ret = GLEW_ARB_compute_variable_group_size; + continue; + } +#endif +#ifdef GL_ARB_conservative_depth + if (_glewStrSame3(&pos, &len, (const GLubyte*)"conservative_depth", 18)) + { + ret = GLEW_ARB_conservative_depth; + continue; + } +#endif #ifdef GL_ARB_copy_buffer if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_buffer", 11)) { @@ -12009,6 +14130,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_copy_image + if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10)) + { + ret = GLEW_ARB_copy_image; + continue; + } +#endif #ifdef GL_ARB_debug_output if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_output", 12)) { @@ -12072,6 +14200,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_enhanced_layouts + if (_glewStrSame3(&pos, &len, (const GLubyte*)"enhanced_layouts", 16)) + { + ret = GLEW_ARB_enhanced_layouts; + continue; + } +#endif #ifdef GL_ARB_explicit_attrib_location if (_glewStrSame3(&pos, &len, (const GLubyte*)"explicit_attrib_location", 24)) { @@ -12079,6 +14214,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_explicit_uniform_location + if (_glewStrSame3(&pos, &len, (const GLubyte*)"explicit_uniform_location", 25)) + { + ret = GLEW_ARB_explicit_uniform_location; + continue; + } +#endif #ifdef GL_ARB_fragment_coord_conventions if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_coord_conventions", 26)) { @@ -12086,6 +14228,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_fragment_layer_viewport + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_layer_viewport", 23)) + { + ret = GLEW_ARB_fragment_layer_viewport; + continue; + } +#endif #ifdef GL_ARB_fragment_program if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_program", 16)) { @@ -12107,6 +14256,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_framebuffer_no_attachments + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_no_attachments", 26)) + { + ret = GLEW_ARB_framebuffer_no_attachments; + continue; + } +#endif #ifdef GL_ARB_framebuffer_object if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18)) { @@ -12170,6 +14326,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_indirect_parameters + if (_glewStrSame3(&pos, &len, (const GLubyte*)"indirect_parameters", 19)) + { + ret = GLEW_ARB_indirect_parameters; + continue; + } +#endif #ifdef GL_ARB_instanced_arrays if (_glewStrSame3(&pos, &len, (const GLubyte*)"instanced_arrays", 16)) { @@ -12177,6 +14340,34 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_internalformat_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"internalformat_query", 20)) + { + ret = GLEW_ARB_internalformat_query; + continue; + } +#endif +#ifdef GL_ARB_internalformat_query2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"internalformat_query2", 21)) + { + ret = GLEW_ARB_internalformat_query2; + continue; + } +#endif +#ifdef GL_ARB_invalidate_subdata + if (_glewStrSame3(&pos, &len, (const GLubyte*)"invalidate_subdata", 18)) + { + ret = GLEW_ARB_invalidate_subdata; + continue; + } +#endif +#ifdef GL_ARB_map_buffer_alignment + if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_buffer_alignment", 20)) + { + ret = GLEW_ARB_map_buffer_alignment; + continue; + } +#endif #ifdef GL_ARB_map_buffer_range if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_buffer_range", 16)) { @@ -12191,6 +14382,20 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_multi_bind + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_bind", 10)) + { + ret = GLEW_ARB_multi_bind; + continue; + } +#endif +#ifdef GL_ARB_multi_draw_indirect + if (_glewStrSame3(&pos, &len, (const GLubyte*)"multi_draw_indirect", 19)) + { + ret = GLEW_ARB_multi_draw_indirect; + continue; + } +#endif #ifdef GL_ARB_multisample if (_glewStrSame3(&pos, &len, (const GLubyte*)"multisample", 11)) { @@ -12240,6 +14445,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_program_interface_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"program_interface_query", 23)) + { + ret = GLEW_ARB_program_interface_query; + continue; + } +#endif #ifdef GL_ARB_provoking_vertex if (_glewStrSame3(&pos, &len, (const GLubyte*)"provoking_vertex", 16)) { @@ -12247,6 +14459,20 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_query_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"query_buffer_object", 19)) + { + ret = GLEW_ARB_query_buffer_object; + continue; + } +#endif +#ifdef GL_ARB_robust_buffer_access_behavior + if (_glewStrSame3(&pos, &len, (const GLubyte*)"robust_buffer_access_behavior", 29)) + { + ret = GLEW_ARB_robust_buffer_access_behavior; + continue; + } +#endif #ifdef GL_ARB_robustness if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness", 10)) { @@ -12254,6 +14480,20 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_robustness_application_isolation + if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_application_isolation", 32)) + { + ret = GLEW_ARB_robustness_application_isolation; + continue; + } +#endif +#ifdef GL_ARB_robustness_share_group_isolation + if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_share_group_isolation", 32)) + { + ret = GLEW_ARB_robustness_share_group_isolation; + continue; + } +#endif #ifdef GL_ARB_sample_shading if (_glewStrSame3(&pos, &len, (const GLubyte*)"sample_shading", 14)) { @@ -12275,6 +14515,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_seamless_cubemap_per_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"seamless_cubemap_per_texture", 28)) + { + ret = GLEW_ARB_seamless_cubemap_per_texture; + continue; + } +#endif #ifdef GL_ARB_separate_shader_objects if (_glewStrSame3(&pos, &len, (const GLubyte*)"separate_shader_objects", 23)) { @@ -12282,6 +14529,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_shader_atomic_counters + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_atomic_counters", 22)) + { + ret = GLEW_ARB_shader_atomic_counters; + continue; + } +#endif #ifdef GL_ARB_shader_bit_encoding if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_bit_encoding", 19)) { @@ -12289,6 +14543,34 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_shader_draw_parameters + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_draw_parameters", 22)) + { + ret = GLEW_ARB_shader_draw_parameters; + continue; + } +#endif +#ifdef GL_ARB_shader_group_vote + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_group_vote", 17)) + { + ret = GLEW_ARB_shader_group_vote; + continue; + } +#endif +#ifdef GL_ARB_shader_image_load_store + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_image_load_store", 23)) + { + ret = GLEW_ARB_shader_image_load_store; + continue; + } +#endif +#ifdef GL_ARB_shader_image_size + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_image_size", 17)) + { + ret = GLEW_ARB_shader_image_size; + continue; + } +#endif #ifdef GL_ARB_shader_objects if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_objects", 14)) { @@ -12310,6 +14592,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_shader_storage_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_storage_buffer_object", 28)) + { + ret = GLEW_ARB_shader_storage_buffer_object; + continue; + } +#endif #ifdef GL_ARB_shader_subroutine if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_subroutine", 17)) { @@ -12331,6 +14620,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_shading_language_420pack + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_420pack", 24)) + { + ret = GLEW_ARB_shading_language_420pack; + continue; + } +#endif #ifdef GL_ARB_shading_language_include if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_include", 24)) { @@ -12338,6 +14634,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_shading_language_packing + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shading_language_packing", 24)) + { + ret = GLEW_ARB_shading_language_packing; + continue; + } +#endif #ifdef GL_ARB_shadow if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow", 6)) { @@ -12352,6 +14655,20 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_sparse_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"sparse_texture", 14)) + { + ret = GLEW_ARB_sparse_texture; + continue; + } +#endif +#ifdef GL_ARB_stencil_texturing + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stencil_texturing", 17)) + { + ret = GLEW_ARB_stencil_texturing; + continue; + } +#endif #ifdef GL_ARB_sync if (_glewStrSame3(&pos, &len, (const GLubyte*)"sync", 4)) { @@ -12387,6 +14704,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_texture_buffer_range + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_buffer_range", 20)) + { + ret = GLEW_ARB_texture_buffer_range; + continue; + } +#endif #ifdef GL_ARB_texture_compression if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression", 19)) { @@ -12464,6 +14788,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_texture_mirror_clamp_to_edge + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirror_clamp_to_edge", 28)) + { + ret = GLEW_ARB_texture_mirror_clamp_to_edge; + continue; + } +#endif #ifdef GL_ARB_texture_mirrored_repeat if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_mirrored_repeat", 23)) { @@ -12485,6 +14816,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_texture_query_levels + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_query_levels", 20)) + { + ret = GLEW_ARB_texture_query_levels; + continue; + } +#endif #ifdef GL_ARB_texture_query_lod if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_query_lod", 17)) { @@ -12513,6 +14851,27 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_texture_stencil8 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_stencil8", 16)) + { + ret = GLEW_ARB_texture_stencil8; + continue; + } +#endif +#ifdef GL_ARB_texture_storage + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_storage", 15)) + { + ret = GLEW_ARB_texture_storage; + continue; + } +#endif +#ifdef GL_ARB_texture_storage_multisample + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_storage_multisample", 27)) + { + ret = GLEW_ARB_texture_storage_multisample; + continue; + } +#endif #ifdef GL_ARB_texture_swizzle if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_swizzle", 15)) { @@ -12520,6 +14879,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_texture_view + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_view", 12)) + { + ret = GLEW_ARB_texture_view; + continue; + } +#endif #ifdef GL_ARB_timer_query if (_glewStrSame3(&pos, &len, (const GLubyte*)"timer_query", 11)) { @@ -12541,6 +14907,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_transform_feedback_instanced + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback_instanced", 28)) + { + ret = GLEW_ARB_transform_feedback_instanced; + continue; + } +#endif #ifdef GL_ARB_transpose_matrix if (_glewStrSame3(&pos, &len, (const GLubyte*)"transpose_matrix", 16)) { @@ -12576,6 +14949,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_vertex_attrib_binding + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_attrib_binding", 21)) + { + ret = GLEW_ARB_vertex_attrib_binding; + continue; + } +#endif #ifdef GL_ARB_vertex_blend if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_blend", 12)) { @@ -12604,6 +14984,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_ARB_vertex_type_10f_11f_11f_rev + if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_type_10f_11f_11f_rev", 27)) + { + ret = GLEW_ARB_vertex_type_10f_11f_11f_rev; + continue; + } +#endif #ifdef GL_ARB_vertex_type_2_10_10_10_rev if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_type_2_10_10_10_rev", 26)) { @@ -12914,6 +15301,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_EXT_debug_marker + if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_marker", 12)) + { + ret = GLEW_EXT_debug_marker; + continue; + } +#endif #ifdef GL_EXT_depth_bounds_test if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_bounds_test", 17)) { @@ -12977,6 +15371,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_EXT_framebuffer_multisample_blit_scaled + if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_multisample_blit_scaled", 35)) + { + ret = GLEW_EXT_framebuffer_multisample_blit_scaled; + continue; + } +#endif #ifdef GL_EXT_framebuffer_object if (_glewStrSame3(&pos, &len, (const GLubyte*)"framebuffer_object", 18)) { @@ -13580,6 +15981,13 @@ GLboolean glewIsSupported (const char* name) } if (_glewStrSame2(&pos, &len, (const GLubyte*)"INTEL_", 6)) { +#ifdef GL_INTEL_map_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_texture", 11)) + { + ret = GLEW_INTEL_map_texture; + continue; + } +#endif #ifdef GL_INTEL_parallel_arrays if (_glewStrSame3(&pos, &len, (const GLubyte*)"parallel_arrays", 15)) { @@ -13593,6 +16001,23 @@ GLboolean glewIsSupported (const char* name) ret = GLEW_INTEL_texture_scissor; continue; } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"KHR_", 4)) + { +#ifdef GL_KHR_debug + if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug", 5)) + { + ret = GLEW_KHR_debug; + continue; + } +#endif +#ifdef GL_KHR_texture_compression_astc_ldr + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_astc_ldr", 28)) + { + ret = GLEW_KHR_texture_compression_astc_ldr; + continue; + } #endif } if (_glewStrSame2(&pos, &len, (const GLubyte*)"KTX_", 4)) @@ -13648,6 +16073,13 @@ GLboolean glewIsSupported (const char* name) } if (_glewStrSame2(&pos, &len, (const GLubyte*)"NVX_", 4)) { +#ifdef GL_NVX_conditional_render + if (_glewStrSame3(&pos, &len, (const GLubyte*)"conditional_render", 18)) + { + ret = GLEW_NVX_conditional_render; + continue; + } +#endif #ifdef GL_NVX_gpu_memory_info if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_memory_info", 15)) { @@ -13658,6 +16090,34 @@ GLboolean glewIsSupported (const char* name) } if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3)) { +#ifdef GL_NV_bindless_multi_draw_indirect + if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindless_multi_draw_indirect", 28)) + { + ret = GLEW_NV_bindless_multi_draw_indirect; + continue; + } +#endif +#ifdef GL_NV_bindless_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"bindless_texture", 16)) + { + ret = GLEW_NV_bindless_texture; + continue; + } +#endif +#ifdef GL_NV_blend_equation_advanced + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_equation_advanced", 23)) + { + ret = GLEW_NV_blend_equation_advanced; + continue; + } +#endif +#ifdef GL_NV_blend_equation_advanced_coherent + if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_equation_advanced_coherent", 32)) + { + ret = GLEW_NV_blend_equation_advanced_coherent; + continue; + } +#endif #ifdef GL_NV_blend_square if (_glewStrSame3(&pos, &len, (const GLubyte*)"blend_square", 12)) { @@ -13665,6 +16125,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_NV_compute_program5 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"compute_program5", 16)) + { + ret = GLEW_NV_compute_program5; + continue; + } +#endif #ifdef GL_NV_conditional_render if (_glewStrSame3(&pos, &len, (const GLubyte*)"conditional_render", 18)) { @@ -13686,6 +16153,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_NV_deep_texture3D + if (_glewStrSame3(&pos, &len, (const GLubyte*)"deep_texture3D", 14)) + { + ret = GLEW_NV_deep_texture3D; + continue; + } +#endif #ifdef GL_NV_depth_buffer_float if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_buffer_float", 18)) { @@ -13707,6 +16181,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_NV_draw_texture + if (_glewStrSame3(&pos, &len, (const GLubyte*)"draw_texture", 12)) + { + ret = GLEW_NV_draw_texture; + continue; + } +#endif #ifdef GL_NV_evaluators if (_glewStrSame3(&pos, &len, (const GLubyte*)"evaluators", 10)) { @@ -13805,6 +16286,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_NV_gpu_program5_mem_extended + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program5_mem_extended", 25)) + { + ret = GLEW_NV_gpu_program5_mem_extended; + continue; + } +#endif #ifdef GL_NV_gpu_program_fp64 if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_program_fp64", 16)) { @@ -13875,6 +16363,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_NV_path_rendering + if (_glewStrSame3(&pos, &len, (const GLubyte*)"path_rendering", 14)) + { + ret = GLEW_NV_path_rendering; + continue; + } +#endif #ifdef GL_NV_pixel_data_range if (_glewStrSame3(&pos, &len, (const GLubyte*)"pixel_data_range", 16)) { @@ -13917,6 +16412,20 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_NV_shader_atomic_counters + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_atomic_counters", 22)) + { + ret = GLEW_NV_shader_atomic_counters; + continue; + } +#endif +#ifdef GL_NV_shader_atomic_float + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_atomic_float", 19)) + { + ret = GLEW_NV_shader_atomic_float; + continue; + } +#endif #ifdef GL_NV_shader_buffer_load if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_buffer_load", 18)) { @@ -13924,6 +16433,13 @@ GLboolean glewIsSupported (const char* name) continue; } #endif +#ifdef GL_NV_shader_storage_buffer_object + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_storage_buffer_object", 28)) + { + ret = GLEW_NV_shader_storage_buffer_object; + continue; + } +#endif #ifdef GL_NV_tessellation_program5 if (_glewStrSame3(&pos, &len, (const GLubyte*)"tessellation_program5", 21)) { @@ -14177,6 +16693,51 @@ GLboolean glewIsSupported (const char* name) ret = GLEW_PGI_vertex_hints; continue; } +#endif + } + if (_glewStrSame2(&pos, &len, (const GLubyte*)"REGAL_", 6)) + { +#ifdef GL_REGAL_ES1_0_compatibility + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ES1_0_compatibility", 19)) + { + ret = GLEW_REGAL_ES1_0_compatibility; + continue; + } +#endif +#ifdef GL_REGAL_ES1_1_compatibility + if (_glewStrSame3(&pos, &len, (const GLubyte*)"ES1_1_compatibility", 19)) + { + ret = GLEW_REGAL_ES1_1_compatibility; + continue; + } +#endif +#ifdef GL_REGAL_enable + if (_glewStrSame3(&pos, &len, (const GLubyte*)"enable", 6)) + { + ret = GLEW_REGAL_enable; + continue; + } +#endif +#ifdef GL_REGAL_error_string + if (_glewStrSame3(&pos, &len, (const GLubyte*)"error_string", 12)) + { + ret = GLEW_REGAL_error_string; + continue; + } +#endif +#ifdef GL_REGAL_extension_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"extension_query", 15)) + { + ret = GLEW_REGAL_extension_query; + continue; + } +#endif +#ifdef GL_REGAL_log + if (_glewStrSame3(&pos, &len, (const GLubyte*)"log", 3)) + { + ret = GLEW_REGAL_log; + continue; + } #endif } if (_glewStrSame2(&pos, &len, (const GLubyte*)"REND_", 5)) @@ -14646,9 +17207,9 @@ GLboolean glewIsSupported (const char* name) #if defined(_WIN32) #if defined(GLEW_MX) -GLboolean wglewContextIsSupported (const WGLEWContext* ctx, const char* name) +GLboolean GLEWAPIENTRY wglewContextIsSupported (const WGLEWContext* ctx, const char* name) #else -GLboolean wglewIsSupported (const char* name) +GLboolean GLEWAPIENTRY wglewIsSupported (const char* name) #endif { GLubyte* pos = (GLubyte*)name; @@ -14773,6 +17334,20 @@ GLboolean wglewIsSupported (const char* name) ret = WGLEW_ARB_render_texture; continue; } +#endif +#ifdef WGL_ARB_robustness_application_isolation + if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_application_isolation", 32)) + { + ret = WGLEW_ARB_robustness_application_isolation; + continue; + } +#endif +#ifdef WGL_ARB_robustness_share_group_isolation + if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_share_group_isolation", 32)) + { + ret = WGLEW_ARB_robustness_share_group_isolation; + continue; + } #endif } if (_glewStrSame2(&pos, &len, (const GLubyte*)"ATI_", 4)) @@ -14801,6 +17376,13 @@ GLboolean wglewIsSupported (const char* name) continue; } #endif +#ifdef WGL_EXT_create_context_es_profile + if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es_profile", 25)) + { + ret = WGLEW_EXT_create_context_es_profile; + continue; + } +#endif #ifdef WGL_EXT_depth_float if (_glewStrSame3(&pos, &len, (const GLubyte*)"depth_float", 11)) { @@ -14870,6 +17452,13 @@ GLboolean wglewIsSupported (const char* name) ret = WGLEW_EXT_swap_control; continue; } +#endif +#ifdef WGL_EXT_swap_control_tear + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control_tear", 17)) + { + ret = WGLEW_EXT_swap_control_tear; + continue; + } #endif } if (_glewStrSame2(&pos, &len, (const GLubyte*)"I3D_", 4)) @@ -14926,6 +17515,13 @@ GLboolean wglewIsSupported (const char* name) continue; } #endif +#ifdef WGL_NV_DX_interop2 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"DX_interop2", 11)) + { + ret = WGLEW_NV_DX_interop2; + continue; + } +#endif #ifdef WGL_NV_copy_image if (_glewStrSame3(&pos, &len, (const GLubyte*)"copy_image", 10)) { @@ -15020,7 +17616,7 @@ GLboolean wglewIsSupported (const char* name) return ret; } -#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__APPLE__) || defined(GLEW_APPLE_GLX) #if defined(GLEW_MX) GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name) @@ -15130,6 +17726,20 @@ GLboolean glxewIsSupported (const char* name) continue; } #endif +#ifdef GLX_ARB_robustness_application_isolation + if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_application_isolation", 32)) + { + ret = GLXEW_ARB_robustness_application_isolation; + continue; + } +#endif +#ifdef GLX_ARB_robustness_share_group_isolation + if (_glewStrSame3(&pos, &len, (const GLubyte*)"robustness_share_group_isolation", 32)) + { + ret = GLXEW_ARB_robustness_share_group_isolation; + continue; + } +#endif #ifdef GLX_ARB_vertex_buffer_object if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_buffer_object", 20)) { @@ -15157,6 +17767,13 @@ GLboolean glxewIsSupported (const char* name) } if (_glewStrSame2(&pos, &len, (const GLubyte*)"EXT_", 4)) { +#ifdef GLX_EXT_buffer_age + if (_glewStrSame3(&pos, &len, (const GLubyte*)"buffer_age", 10)) + { + ret = GLXEW_EXT_buffer_age; + continue; + } +#endif #ifdef GLX_EXT_create_context_es2_profile if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es2_profile", 26)) { @@ -15164,6 +17781,13 @@ GLboolean glxewIsSupported (const char* name) continue; } #endif +#ifdef GLX_EXT_create_context_es_profile + if (_glewStrSame3(&pos, &len, (const GLubyte*)"create_context_es_profile", 25)) + { + ret = GLXEW_EXT_create_context_es_profile; + continue; + } +#endif #ifdef GLX_EXT_fbconfig_packed_float if (_glewStrSame3(&pos, &len, (const GLubyte*)"fbconfig_packed_float", 21)) { @@ -15199,6 +17823,13 @@ GLboolean glxewIsSupported (const char* name) continue; } #endif +#ifdef GLX_EXT_swap_control_tear + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control_tear", 17)) + { + ret = GLXEW_EXT_swap_control_tear; + continue; + } +#endif #ifdef GLX_EXT_texture_from_pixmap if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_from_pixmap", 19)) { @@ -15267,6 +17898,13 @@ GLboolean glxewIsSupported (const char* name) ret = GLXEW_MESA_set_3dfx_mode; continue; } +#endif +#ifdef GLX_MESA_swap_control + if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12)) + { + ret = GLXEW_MESA_swap_control; + continue; + } #endif } if (_glewStrSame2(&pos, &len, (const GLubyte*)"NV_", 3)) diff --git a/ext/glew/glewinfo.c b/ext/glew/glewinfo.c index 7f22c560b1..ad44f7256c 100644 --- a/ext/glew/glewinfo.c +++ b/ext/glew/glewinfo.c @@ -39,6 +39,10 @@ #include #endif +#ifdef GLEW_REGAL +#include +#endif + static FILE* f; #ifdef GLEW_MX @@ -517,6 +521,33 @@ static void _glewInfo_GL_VERSION_4_1 (void) #endif /* GL_VERSION_4_1 */ +#ifdef GL_VERSION_4_2 + +static void _glewInfo_GL_VERSION_4_2 (void) +{ + glewPrintExt("GL_VERSION_4_2", GLEW_VERSION_4_2, GLEW_VERSION_4_2, GLEW_VERSION_4_2); +} + +#endif /* GL_VERSION_4_2 */ + +#ifdef GL_VERSION_4_3 + +static void _glewInfo_GL_VERSION_4_3 (void) +{ + glewPrintExt("GL_VERSION_4_3", GLEW_VERSION_4_3, GLEW_VERSION_4_3, GLEW_VERSION_4_3); +} + +#endif /* GL_VERSION_4_3 */ + +#ifdef GL_VERSION_4_4 + +static void _glewInfo_GL_VERSION_4_4 (void) +{ + glewPrintExt("GL_VERSION_4_4", GLEW_VERSION_4_4, GLEW_VERSION_4_4, GLEW_VERSION_4_4); +} + +#endif /* GL_VERSION_4_4 */ + #ifdef GL_3DFX_multisample static void _glewInfo_GL_3DFX_multisample (void) @@ -601,6 +632,29 @@ static void _glewInfo_GL_AMD_draw_buffers_blend (void) #endif /* GL_AMD_draw_buffers_blend */ +#ifdef GL_AMD_interleaved_elements + +static void _glewInfo_GL_AMD_interleaved_elements (void) +{ + glewPrintExt("GL_AMD_interleaved_elements", GLEW_AMD_interleaved_elements, glewIsSupported("GL_AMD_interleaved_elements"), glewGetExtension("GL_AMD_interleaved_elements")); + + glewInfoFunc("glVertexAttribParameteriAMD", glVertexAttribParameteriAMD == NULL); +} + +#endif /* GL_AMD_interleaved_elements */ + +#ifdef GL_AMD_multi_draw_indirect + +static void _glewInfo_GL_AMD_multi_draw_indirect (void) +{ + glewPrintExt("GL_AMD_multi_draw_indirect", GLEW_AMD_multi_draw_indirect, glewIsSupported("GL_AMD_multi_draw_indirect"), glewGetExtension("GL_AMD_multi_draw_indirect")); + + glewInfoFunc("glMultiDrawArraysIndirectAMD", glMultiDrawArraysIndirectAMD == NULL); + glewInfoFunc("glMultiDrawElementsIndirectAMD", glMultiDrawElementsIndirectAMD == NULL); +} + +#endif /* GL_AMD_multi_draw_indirect */ + #ifdef GL_AMD_name_gen_delete static void _glewInfo_GL_AMD_name_gen_delete (void) @@ -635,6 +689,24 @@ static void _glewInfo_GL_AMD_performance_monitor (void) #endif /* GL_AMD_performance_monitor */ +#ifdef GL_AMD_pinned_memory + +static void _glewInfo_GL_AMD_pinned_memory (void) +{ + glewPrintExt("GL_AMD_pinned_memory", GLEW_AMD_pinned_memory, glewIsSupported("GL_AMD_pinned_memory"), glewGetExtension("GL_AMD_pinned_memory")); +} + +#endif /* GL_AMD_pinned_memory */ + +#ifdef GL_AMD_query_buffer_object + +static void _glewInfo_GL_AMD_query_buffer_object (void) +{ + glewPrintExt("GL_AMD_query_buffer_object", GLEW_AMD_query_buffer_object, glewIsSupported("GL_AMD_query_buffer_object"), glewGetExtension("GL_AMD_query_buffer_object")); +} + +#endif /* GL_AMD_query_buffer_object */ + #ifdef GL_AMD_sample_positions static void _glewInfo_GL_AMD_sample_positions (void) @@ -664,6 +736,38 @@ static void _glewInfo_GL_AMD_shader_stencil_export (void) #endif /* GL_AMD_shader_stencil_export */ +#ifdef GL_AMD_shader_trinary_minmax + +static void _glewInfo_GL_AMD_shader_trinary_minmax (void) +{ + glewPrintExt("GL_AMD_shader_trinary_minmax", GLEW_AMD_shader_trinary_minmax, glewIsSupported("GL_AMD_shader_trinary_minmax"), glewGetExtension("GL_AMD_shader_trinary_minmax")); +} + +#endif /* GL_AMD_shader_trinary_minmax */ + +#ifdef GL_AMD_sparse_texture + +static void _glewInfo_GL_AMD_sparse_texture (void) +{ + glewPrintExt("GL_AMD_sparse_texture", GLEW_AMD_sparse_texture, glewIsSupported("GL_AMD_sparse_texture"), glewGetExtension("GL_AMD_sparse_texture")); + + glewInfoFunc("glTexStorageSparseAMD", glTexStorageSparseAMD == NULL); + glewInfoFunc("glTextureStorageSparseAMD", glTextureStorageSparseAMD == NULL); +} + +#endif /* GL_AMD_sparse_texture */ + +#ifdef GL_AMD_stencil_operation_extended + +static void _glewInfo_GL_AMD_stencil_operation_extended (void) +{ + glewPrintExt("GL_AMD_stencil_operation_extended", GLEW_AMD_stencil_operation_extended, glewIsSupported("GL_AMD_stencil_operation_extended"), glewGetExtension("GL_AMD_stencil_operation_extended")); + + glewInfoFunc("glStencilOpValueAMD", glStencilOpValueAMD == NULL); +} + +#endif /* GL_AMD_stencil_operation_extended */ + #ifdef GL_AMD_texture_texture4 static void _glewInfo_GL_AMD_texture_texture4 (void) @@ -682,6 +786,15 @@ static void _glewInfo_GL_AMD_transform_feedback3_lines_triangles (void) #endif /* GL_AMD_transform_feedback3_lines_triangles */ +#ifdef GL_AMD_vertex_shader_layer + +static void _glewInfo_GL_AMD_vertex_shader_layer (void) +{ + glewPrintExt("GL_AMD_vertex_shader_layer", GLEW_AMD_vertex_shader_layer, glewIsSupported("GL_AMD_vertex_shader_layer"), glewGetExtension("GL_AMD_vertex_shader_layer")); +} + +#endif /* GL_AMD_vertex_shader_layer */ + #ifdef GL_AMD_vertex_shader_tessellator static void _glewInfo_GL_AMD_vertex_shader_tessellator (void) @@ -694,6 +807,145 @@ static void _glewInfo_GL_AMD_vertex_shader_tessellator (void) #endif /* GL_AMD_vertex_shader_tessellator */ +#ifdef GL_AMD_vertex_shader_viewport_index + +static void _glewInfo_GL_AMD_vertex_shader_viewport_index (void) +{ + glewPrintExt("GL_AMD_vertex_shader_viewport_index", GLEW_AMD_vertex_shader_viewport_index, glewIsSupported("GL_AMD_vertex_shader_viewport_index"), glewGetExtension("GL_AMD_vertex_shader_viewport_index")); +} + +#endif /* GL_AMD_vertex_shader_viewport_index */ + +#ifdef GL_ANGLE_depth_texture + +static void _glewInfo_GL_ANGLE_depth_texture (void) +{ + glewPrintExt("GL_ANGLE_depth_texture", GLEW_ANGLE_depth_texture, glewIsSupported("GL_ANGLE_depth_texture"), glewGetExtension("GL_ANGLE_depth_texture")); +} + +#endif /* GL_ANGLE_depth_texture */ + +#ifdef GL_ANGLE_framebuffer_blit + +static void _glewInfo_GL_ANGLE_framebuffer_blit (void) +{ + glewPrintExt("GL_ANGLE_framebuffer_blit", GLEW_ANGLE_framebuffer_blit, glewIsSupported("GL_ANGLE_framebuffer_blit"), glewGetExtension("GL_ANGLE_framebuffer_blit")); + + glewInfoFunc("glBlitFramebufferANGLE", glBlitFramebufferANGLE == NULL); +} + +#endif /* GL_ANGLE_framebuffer_blit */ + +#ifdef GL_ANGLE_framebuffer_multisample + +static void _glewInfo_GL_ANGLE_framebuffer_multisample (void) +{ + glewPrintExt("GL_ANGLE_framebuffer_multisample", GLEW_ANGLE_framebuffer_multisample, glewIsSupported("GL_ANGLE_framebuffer_multisample"), glewGetExtension("GL_ANGLE_framebuffer_multisample")); + + glewInfoFunc("glRenderbufferStorageMultisampleANGLE", glRenderbufferStorageMultisampleANGLE == NULL); +} + +#endif /* GL_ANGLE_framebuffer_multisample */ + +#ifdef GL_ANGLE_instanced_arrays + +static void _glewInfo_GL_ANGLE_instanced_arrays (void) +{ + glewPrintExt("GL_ANGLE_instanced_arrays", GLEW_ANGLE_instanced_arrays, glewIsSupported("GL_ANGLE_instanced_arrays"), glewGetExtension("GL_ANGLE_instanced_arrays")); + + glewInfoFunc("glDrawArraysInstancedANGLE", glDrawArraysInstancedANGLE == NULL); + glewInfoFunc("glDrawElementsInstancedANGLE", glDrawElementsInstancedANGLE == NULL); + glewInfoFunc("glVertexAttribDivisorANGLE", glVertexAttribDivisorANGLE == NULL); +} + +#endif /* GL_ANGLE_instanced_arrays */ + +#ifdef GL_ANGLE_pack_reverse_row_order + +static void _glewInfo_GL_ANGLE_pack_reverse_row_order (void) +{ + glewPrintExt("GL_ANGLE_pack_reverse_row_order", GLEW_ANGLE_pack_reverse_row_order, glewIsSupported("GL_ANGLE_pack_reverse_row_order"), glewGetExtension("GL_ANGLE_pack_reverse_row_order")); +} + +#endif /* GL_ANGLE_pack_reverse_row_order */ + +#ifdef GL_ANGLE_program_binary + +static void _glewInfo_GL_ANGLE_program_binary (void) +{ + glewPrintExt("GL_ANGLE_program_binary", GLEW_ANGLE_program_binary, glewIsSupported("GL_ANGLE_program_binary"), glewGetExtension("GL_ANGLE_program_binary")); +} + +#endif /* GL_ANGLE_program_binary */ + +#ifdef GL_ANGLE_texture_compression_dxt1 + +static void _glewInfo_GL_ANGLE_texture_compression_dxt1 (void) +{ + glewPrintExt("GL_ANGLE_texture_compression_dxt1", GLEW_ANGLE_texture_compression_dxt1, glewIsSupported("GL_ANGLE_texture_compression_dxt1"), glewGetExtension("GL_ANGLE_texture_compression_dxt1")); +} + +#endif /* GL_ANGLE_texture_compression_dxt1 */ + +#ifdef GL_ANGLE_texture_compression_dxt3 + +static void _glewInfo_GL_ANGLE_texture_compression_dxt3 (void) +{ + glewPrintExt("GL_ANGLE_texture_compression_dxt3", GLEW_ANGLE_texture_compression_dxt3, glewIsSupported("GL_ANGLE_texture_compression_dxt3"), glewGetExtension("GL_ANGLE_texture_compression_dxt3")); +} + +#endif /* GL_ANGLE_texture_compression_dxt3 */ + +#ifdef GL_ANGLE_texture_compression_dxt5 + +static void _glewInfo_GL_ANGLE_texture_compression_dxt5 (void) +{ + glewPrintExt("GL_ANGLE_texture_compression_dxt5", GLEW_ANGLE_texture_compression_dxt5, glewIsSupported("GL_ANGLE_texture_compression_dxt5"), glewGetExtension("GL_ANGLE_texture_compression_dxt5")); +} + +#endif /* GL_ANGLE_texture_compression_dxt5 */ + +#ifdef GL_ANGLE_texture_usage + +static void _glewInfo_GL_ANGLE_texture_usage (void) +{ + glewPrintExt("GL_ANGLE_texture_usage", GLEW_ANGLE_texture_usage, glewIsSupported("GL_ANGLE_texture_usage"), glewGetExtension("GL_ANGLE_texture_usage")); +} + +#endif /* GL_ANGLE_texture_usage */ + +#ifdef GL_ANGLE_timer_query + +static void _glewInfo_GL_ANGLE_timer_query (void) +{ + glewPrintExt("GL_ANGLE_timer_query", GLEW_ANGLE_timer_query, glewIsSupported("GL_ANGLE_timer_query"), glewGetExtension("GL_ANGLE_timer_query")); + + glewInfoFunc("glBeginQueryANGLE", glBeginQueryANGLE == NULL); + glewInfoFunc("glDeleteQueriesANGLE", glDeleteQueriesANGLE == NULL); + glewInfoFunc("glEndQueryANGLE", glEndQueryANGLE == NULL); + glewInfoFunc("glGenQueriesANGLE", glGenQueriesANGLE == NULL); + glewInfoFunc("glGetQueryObjecti64vANGLE", glGetQueryObjecti64vANGLE == NULL); + glewInfoFunc("glGetQueryObjectivANGLE", glGetQueryObjectivANGLE == NULL); + glewInfoFunc("glGetQueryObjectui64vANGLE", glGetQueryObjectui64vANGLE == NULL); + glewInfoFunc("glGetQueryObjectuivANGLE", glGetQueryObjectuivANGLE == NULL); + glewInfoFunc("glGetQueryivANGLE", glGetQueryivANGLE == NULL); + glewInfoFunc("glIsQueryANGLE", glIsQueryANGLE == NULL); + glewInfoFunc("glQueryCounterANGLE", glQueryCounterANGLE == NULL); +} + +#endif /* GL_ANGLE_timer_query */ + +#ifdef GL_ANGLE_translated_shader_source + +static void _glewInfo_GL_ANGLE_translated_shader_source (void) +{ + glewPrintExt("GL_ANGLE_translated_shader_source", GLEW_ANGLE_translated_shader_source, glewIsSupported("GL_ANGLE_translated_shader_source"), glewGetExtension("GL_ANGLE_translated_shader_source")); + + glewInfoFunc("glGetTranslatedShaderSourceANGLE", glGetTranslatedShaderSourceANGLE == NULL); +} + +#endif /* GL_ANGLE_translated_shader_source */ + #ifdef GL_APPLE_aux_depth_stencil static void _glewInfo_GL_APPLE_aux_depth_stencil (void) @@ -904,6 +1156,63 @@ static void _glewInfo_GL_ARB_ES2_compatibility (void) #endif /* GL_ARB_ES2_compatibility */ +#ifdef GL_ARB_ES3_compatibility + +static void _glewInfo_GL_ARB_ES3_compatibility (void) +{ + glewPrintExt("GL_ARB_ES3_compatibility", GLEW_ARB_ES3_compatibility, glewIsSupported("GL_ARB_ES3_compatibility"), glewGetExtension("GL_ARB_ES3_compatibility")); +} + +#endif /* GL_ARB_ES3_compatibility */ + +#ifdef GL_ARB_arrays_of_arrays + +static void _glewInfo_GL_ARB_arrays_of_arrays (void) +{ + glewPrintExt("GL_ARB_arrays_of_arrays", GLEW_ARB_arrays_of_arrays, glewIsSupported("GL_ARB_arrays_of_arrays"), glewGetExtension("GL_ARB_arrays_of_arrays")); +} + +#endif /* GL_ARB_arrays_of_arrays */ + +#ifdef GL_ARB_base_instance + +static void _glewInfo_GL_ARB_base_instance (void) +{ + glewPrintExt("GL_ARB_base_instance", GLEW_ARB_base_instance, glewIsSupported("GL_ARB_base_instance"), glewGetExtension("GL_ARB_base_instance")); + + glewInfoFunc("glDrawArraysInstancedBaseInstance", glDrawArraysInstancedBaseInstance == NULL); + glewInfoFunc("glDrawElementsInstancedBaseInstance", glDrawElementsInstancedBaseInstance == NULL); + glewInfoFunc("glDrawElementsInstancedBaseVertexBaseInstance", glDrawElementsInstancedBaseVertexBaseInstance == NULL); +} + +#endif /* GL_ARB_base_instance */ + +#ifdef GL_ARB_bindless_texture + +static void _glewInfo_GL_ARB_bindless_texture (void) +{ + glewPrintExt("GL_ARB_bindless_texture", GLEW_ARB_bindless_texture, glewIsSupported("GL_ARB_bindless_texture"), glewGetExtension("GL_ARB_bindless_texture")); + + glewInfoFunc("glGetImageHandleARB", glGetImageHandleARB == NULL); + glewInfoFunc("glGetTextureHandleARB", glGetTextureHandleARB == NULL); + glewInfoFunc("glGetTextureSamplerHandleARB", glGetTextureSamplerHandleARB == NULL); + glewInfoFunc("glGetVertexAttribLui64vARB", glGetVertexAttribLui64vARB == NULL); + glewInfoFunc("glIsImageHandleResidentARB", glIsImageHandleResidentARB == NULL); + glewInfoFunc("glIsTextureHandleResidentARB", glIsTextureHandleResidentARB == NULL); + glewInfoFunc("glMakeImageHandleNonResidentARB", glMakeImageHandleNonResidentARB == NULL); + glewInfoFunc("glMakeImageHandleResidentARB", glMakeImageHandleResidentARB == NULL); + glewInfoFunc("glMakeTextureHandleNonResidentARB", glMakeTextureHandleNonResidentARB == NULL); + glewInfoFunc("glMakeTextureHandleResidentARB", glMakeTextureHandleResidentARB == NULL); + glewInfoFunc("glProgramUniformHandleui64ARB", glProgramUniformHandleui64ARB == NULL); + glewInfoFunc("glProgramUniformHandleui64vARB", glProgramUniformHandleui64vARB == NULL); + glewInfoFunc("glUniformHandleui64ARB", glUniformHandleui64ARB == NULL); + glewInfoFunc("glUniformHandleui64vARB", glUniformHandleui64vARB == NULL); + glewInfoFunc("glVertexAttribL1ui64ARB", glVertexAttribL1ui64ARB == NULL); + glewInfoFunc("glVertexAttribL1ui64vARB", glVertexAttribL1ui64vARB == NULL); +} + +#endif /* GL_ARB_bindless_texture */ + #ifdef GL_ARB_blend_func_extended static void _glewInfo_GL_ARB_blend_func_extended (void) @@ -916,6 +1225,18 @@ static void _glewInfo_GL_ARB_blend_func_extended (void) #endif /* GL_ARB_blend_func_extended */ +#ifdef GL_ARB_buffer_storage + +static void _glewInfo_GL_ARB_buffer_storage (void) +{ + glewPrintExt("GL_ARB_buffer_storage", GLEW_ARB_buffer_storage, glewIsSupported("GL_ARB_buffer_storage"), glewGetExtension("GL_ARB_buffer_storage")); + + glewInfoFunc("glBufferStorage", glBufferStorage == NULL); + glewInfoFunc("glNamedBufferStorageEXT", glNamedBufferStorageEXT == NULL); +} + +#endif /* GL_ARB_buffer_storage */ + #ifdef GL_ARB_cl_event static void _glewInfo_GL_ARB_cl_event (void) @@ -927,6 +1248,32 @@ static void _glewInfo_GL_ARB_cl_event (void) #endif /* GL_ARB_cl_event */ +#ifdef GL_ARB_clear_buffer_object + +static void _glewInfo_GL_ARB_clear_buffer_object (void) +{ + glewPrintExt("GL_ARB_clear_buffer_object", GLEW_ARB_clear_buffer_object, glewIsSupported("GL_ARB_clear_buffer_object"), glewGetExtension("GL_ARB_clear_buffer_object")); + + glewInfoFunc("glClearBufferData", glClearBufferData == NULL); + glewInfoFunc("glClearBufferSubData", glClearBufferSubData == NULL); + glewInfoFunc("glClearNamedBufferDataEXT", glClearNamedBufferDataEXT == NULL); + glewInfoFunc("glClearNamedBufferSubDataEXT", glClearNamedBufferSubDataEXT == NULL); +} + +#endif /* GL_ARB_clear_buffer_object */ + +#ifdef GL_ARB_clear_texture + +static void _glewInfo_GL_ARB_clear_texture (void) +{ + glewPrintExt("GL_ARB_clear_texture", GLEW_ARB_clear_texture, glewIsSupported("GL_ARB_clear_texture"), glewGetExtension("GL_ARB_clear_texture")); + + glewInfoFunc("glClearTexImage", glClearTexImage == NULL); + glewInfoFunc("glClearTexSubImage", glClearTexSubImage == NULL); +} + +#endif /* GL_ARB_clear_texture */ + #ifdef GL_ARB_color_buffer_float static void _glewInfo_GL_ARB_color_buffer_float (void) @@ -947,6 +1294,47 @@ static void _glewInfo_GL_ARB_compatibility (void) #endif /* GL_ARB_compatibility */ +#ifdef GL_ARB_compressed_texture_pixel_storage + +static void _glewInfo_GL_ARB_compressed_texture_pixel_storage (void) +{ + glewPrintExt("GL_ARB_compressed_texture_pixel_storage", GLEW_ARB_compressed_texture_pixel_storage, glewIsSupported("GL_ARB_compressed_texture_pixel_storage"), glewGetExtension("GL_ARB_compressed_texture_pixel_storage")); +} + +#endif /* GL_ARB_compressed_texture_pixel_storage */ + +#ifdef GL_ARB_compute_shader + +static void _glewInfo_GL_ARB_compute_shader (void) +{ + glewPrintExt("GL_ARB_compute_shader", GLEW_ARB_compute_shader, glewIsSupported("GL_ARB_compute_shader"), glewGetExtension("GL_ARB_compute_shader")); + + glewInfoFunc("glDispatchCompute", glDispatchCompute == NULL); + glewInfoFunc("glDispatchComputeIndirect", glDispatchComputeIndirect == NULL); +} + +#endif /* GL_ARB_compute_shader */ + +#ifdef GL_ARB_compute_variable_group_size + +static void _glewInfo_GL_ARB_compute_variable_group_size (void) +{ + glewPrintExt("GL_ARB_compute_variable_group_size", GLEW_ARB_compute_variable_group_size, glewIsSupported("GL_ARB_compute_variable_group_size"), glewGetExtension("GL_ARB_compute_variable_group_size")); + + glewInfoFunc("glDispatchComputeGroupSizeARB", glDispatchComputeGroupSizeARB == NULL); +} + +#endif /* GL_ARB_compute_variable_group_size */ + +#ifdef GL_ARB_conservative_depth + +static void _glewInfo_GL_ARB_conservative_depth (void) +{ + glewPrintExt("GL_ARB_conservative_depth", GLEW_ARB_conservative_depth, glewIsSupported("GL_ARB_conservative_depth"), glewGetExtension("GL_ARB_conservative_depth")); +} + +#endif /* GL_ARB_conservative_depth */ + #ifdef GL_ARB_copy_buffer static void _glewInfo_GL_ARB_copy_buffer (void) @@ -958,6 +1346,17 @@ static void _glewInfo_GL_ARB_copy_buffer (void) #endif /* GL_ARB_copy_buffer */ +#ifdef GL_ARB_copy_image + +static void _glewInfo_GL_ARB_copy_image (void) +{ + glewPrintExt("GL_ARB_copy_image", GLEW_ARB_copy_image, glewIsSupported("GL_ARB_copy_image"), glewGetExtension("GL_ARB_copy_image")); + + glewInfoFunc("glCopyImageSubData", glCopyImageSubData == NULL); +} + +#endif /* GL_ARB_copy_image */ + #ifdef GL_ARB_debug_output static void _glewInfo_GL_ARB_debug_output (void) @@ -1059,6 +1458,15 @@ static void _glewInfo_GL_ARB_draw_instanced (void) #endif /* GL_ARB_draw_instanced */ +#ifdef GL_ARB_enhanced_layouts + +static void _glewInfo_GL_ARB_enhanced_layouts (void) +{ + glewPrintExt("GL_ARB_enhanced_layouts", GLEW_ARB_enhanced_layouts, glewIsSupported("GL_ARB_enhanced_layouts"), glewGetExtension("GL_ARB_enhanced_layouts")); +} + +#endif /* GL_ARB_enhanced_layouts */ + #ifdef GL_ARB_explicit_attrib_location static void _glewInfo_GL_ARB_explicit_attrib_location (void) @@ -1068,6 +1476,15 @@ static void _glewInfo_GL_ARB_explicit_attrib_location (void) #endif /* GL_ARB_explicit_attrib_location */ +#ifdef GL_ARB_explicit_uniform_location + +static void _glewInfo_GL_ARB_explicit_uniform_location (void) +{ + glewPrintExt("GL_ARB_explicit_uniform_location", GLEW_ARB_explicit_uniform_location, glewIsSupported("GL_ARB_explicit_uniform_location"), glewGetExtension("GL_ARB_explicit_uniform_location")); +} + +#endif /* GL_ARB_explicit_uniform_location */ + #ifdef GL_ARB_fragment_coord_conventions static void _glewInfo_GL_ARB_fragment_coord_conventions (void) @@ -1077,6 +1494,15 @@ static void _glewInfo_GL_ARB_fragment_coord_conventions (void) #endif /* GL_ARB_fragment_coord_conventions */ +#ifdef GL_ARB_fragment_layer_viewport + +static void _glewInfo_GL_ARB_fragment_layer_viewport (void) +{ + glewPrintExt("GL_ARB_fragment_layer_viewport", GLEW_ARB_fragment_layer_viewport, glewIsSupported("GL_ARB_fragment_layer_viewport"), glewGetExtension("GL_ARB_fragment_layer_viewport")); +} + +#endif /* GL_ARB_fragment_layer_viewport */ + #ifdef GL_ARB_fragment_program static void _glewInfo_GL_ARB_fragment_program (void) @@ -1104,6 +1530,20 @@ static void _glewInfo_GL_ARB_fragment_shader (void) #endif /* GL_ARB_fragment_shader */ +#ifdef GL_ARB_framebuffer_no_attachments + +static void _glewInfo_GL_ARB_framebuffer_no_attachments (void) +{ + glewPrintExt("GL_ARB_framebuffer_no_attachments", GLEW_ARB_framebuffer_no_attachments, glewIsSupported("GL_ARB_framebuffer_no_attachments"), glewGetExtension("GL_ARB_framebuffer_no_attachments")); + + glewInfoFunc("glFramebufferParameteri", glFramebufferParameteri == NULL); + glewInfoFunc("glGetFramebufferParameteriv", glGetFramebufferParameteriv == NULL); + glewInfoFunc("glGetNamedFramebufferParameterivEXT", glGetNamedFramebufferParameterivEXT == NULL); + glewInfoFunc("glNamedFramebufferParameteriEXT", glNamedFramebufferParameteriEXT == NULL); +} + +#endif /* GL_ARB_framebuffer_no_attachments */ + #ifdef GL_ARB_framebuffer_object static void _glewInfo_GL_ARB_framebuffer_object (void) @@ -1186,23 +1626,6 @@ static void _glewInfo_GL_ARB_gpu_shader_fp64 (void) glewPrintExt("GL_ARB_gpu_shader_fp64", GLEW_ARB_gpu_shader_fp64, glewIsSupported("GL_ARB_gpu_shader_fp64"), glewGetExtension("GL_ARB_gpu_shader_fp64")); glewInfoFunc("glGetUniformdv", glGetUniformdv == NULL); - glewInfoFunc("glProgramUniform1dEXT", glProgramUniform1dEXT == NULL); - glewInfoFunc("glProgramUniform1dvEXT", glProgramUniform1dvEXT == NULL); - glewInfoFunc("glProgramUniform2dEXT", glProgramUniform2dEXT == NULL); - glewInfoFunc("glProgramUniform2dvEXT", glProgramUniform2dvEXT == NULL); - glewInfoFunc("glProgramUniform3dEXT", glProgramUniform3dEXT == NULL); - glewInfoFunc("glProgramUniform3dvEXT", glProgramUniform3dvEXT == NULL); - glewInfoFunc("glProgramUniform4dEXT", glProgramUniform4dEXT == NULL); - glewInfoFunc("glProgramUniform4dvEXT", glProgramUniform4dvEXT == NULL); - glewInfoFunc("glProgramUniformMatrix2dvEXT", glProgramUniformMatrix2dvEXT == NULL); - glewInfoFunc("glProgramUniformMatrix2x3dvEXT", glProgramUniformMatrix2x3dvEXT == NULL); - glewInfoFunc("glProgramUniformMatrix2x4dvEXT", glProgramUniformMatrix2x4dvEXT == NULL); - glewInfoFunc("glProgramUniformMatrix3dvEXT", glProgramUniformMatrix3dvEXT == NULL); - glewInfoFunc("glProgramUniformMatrix3x2dvEXT", glProgramUniformMatrix3x2dvEXT == NULL); - glewInfoFunc("glProgramUniformMatrix3x4dvEXT", glProgramUniformMatrix3x4dvEXT == NULL); - glewInfoFunc("glProgramUniformMatrix4dvEXT", glProgramUniformMatrix4dvEXT == NULL); - glewInfoFunc("glProgramUniformMatrix4x2dvEXT", glProgramUniformMatrix4x2dvEXT == NULL); - glewInfoFunc("glProgramUniformMatrix4x3dvEXT", glProgramUniformMatrix4x3dvEXT == NULL); glewInfoFunc("glUniform1d", glUniform1d == NULL); glewInfoFunc("glUniform1dv", glUniform1dv == NULL); glewInfoFunc("glUniform2d", glUniform2d == NULL); @@ -1285,6 +1708,18 @@ static void _glewInfo_GL_ARB_imaging (void) #endif /* GL_ARB_imaging */ +#ifdef GL_ARB_indirect_parameters + +static void _glewInfo_GL_ARB_indirect_parameters (void) +{ + glewPrintExt("GL_ARB_indirect_parameters", GLEW_ARB_indirect_parameters, glewIsSupported("GL_ARB_indirect_parameters"), glewGetExtension("GL_ARB_indirect_parameters")); + + glewInfoFunc("glMultiDrawArraysIndirectCountARB", glMultiDrawArraysIndirectCountARB == NULL); + glewInfoFunc("glMultiDrawElementsIndirectCountARB", glMultiDrawElementsIndirectCountARB == NULL); +} + +#endif /* GL_ARB_indirect_parameters */ + #ifdef GL_ARB_instanced_arrays static void _glewInfo_GL_ARB_instanced_arrays (void) @@ -1298,6 +1733,53 @@ static void _glewInfo_GL_ARB_instanced_arrays (void) #endif /* GL_ARB_instanced_arrays */ +#ifdef GL_ARB_internalformat_query + +static void _glewInfo_GL_ARB_internalformat_query (void) +{ + glewPrintExt("GL_ARB_internalformat_query", GLEW_ARB_internalformat_query, glewIsSupported("GL_ARB_internalformat_query"), glewGetExtension("GL_ARB_internalformat_query")); + + glewInfoFunc("glGetInternalformativ", glGetInternalformativ == NULL); +} + +#endif /* GL_ARB_internalformat_query */ + +#ifdef GL_ARB_internalformat_query2 + +static void _glewInfo_GL_ARB_internalformat_query2 (void) +{ + glewPrintExt("GL_ARB_internalformat_query2", GLEW_ARB_internalformat_query2, glewIsSupported("GL_ARB_internalformat_query2"), glewGetExtension("GL_ARB_internalformat_query2")); + + glewInfoFunc("glGetInternalformati64v", glGetInternalformati64v == NULL); +} + +#endif /* GL_ARB_internalformat_query2 */ + +#ifdef GL_ARB_invalidate_subdata + +static void _glewInfo_GL_ARB_invalidate_subdata (void) +{ + glewPrintExt("GL_ARB_invalidate_subdata", GLEW_ARB_invalidate_subdata, glewIsSupported("GL_ARB_invalidate_subdata"), glewGetExtension("GL_ARB_invalidate_subdata")); + + glewInfoFunc("glInvalidateBufferData", glInvalidateBufferData == NULL); + glewInfoFunc("glInvalidateBufferSubData", glInvalidateBufferSubData == NULL); + glewInfoFunc("glInvalidateFramebuffer", glInvalidateFramebuffer == NULL); + glewInfoFunc("glInvalidateSubFramebuffer", glInvalidateSubFramebuffer == NULL); + glewInfoFunc("glInvalidateTexImage", glInvalidateTexImage == NULL); + glewInfoFunc("glInvalidateTexSubImage", glInvalidateTexSubImage == NULL); +} + +#endif /* GL_ARB_invalidate_subdata */ + +#ifdef GL_ARB_map_buffer_alignment + +static void _glewInfo_GL_ARB_map_buffer_alignment (void) +{ + glewPrintExt("GL_ARB_map_buffer_alignment", GLEW_ARB_map_buffer_alignment, glewIsSupported("GL_ARB_map_buffer_alignment"), glewGetExtension("GL_ARB_map_buffer_alignment")); +} + +#endif /* GL_ARB_map_buffer_alignment */ + #ifdef GL_ARB_map_buffer_range static void _glewInfo_GL_ARB_map_buffer_range (void) @@ -1325,6 +1807,34 @@ static void _glewInfo_GL_ARB_matrix_palette (void) #endif /* GL_ARB_matrix_palette */ +#ifdef GL_ARB_multi_bind + +static void _glewInfo_GL_ARB_multi_bind (void) +{ + glewPrintExt("GL_ARB_multi_bind", GLEW_ARB_multi_bind, glewIsSupported("GL_ARB_multi_bind"), glewGetExtension("GL_ARB_multi_bind")); + + glewInfoFunc("glBindBuffersBase", glBindBuffersBase == NULL); + glewInfoFunc("glBindBuffersRange", glBindBuffersRange == NULL); + glewInfoFunc("glBindImageTextures", glBindImageTextures == NULL); + glewInfoFunc("glBindSamplers", glBindSamplers == NULL); + glewInfoFunc("glBindTextures", glBindTextures == NULL); + glewInfoFunc("glBindVertexBuffers", glBindVertexBuffers == NULL); +} + +#endif /* GL_ARB_multi_bind */ + +#ifdef GL_ARB_multi_draw_indirect + +static void _glewInfo_GL_ARB_multi_draw_indirect (void) +{ + glewPrintExt("GL_ARB_multi_draw_indirect", GLEW_ARB_multi_draw_indirect, glewIsSupported("GL_ARB_multi_draw_indirect"), glewGetExtension("GL_ARB_multi_draw_indirect")); + + glewInfoFunc("glMultiDrawArraysIndirect", glMultiDrawArraysIndirect == NULL); + glewInfoFunc("glMultiDrawElementsIndirect", glMultiDrawElementsIndirect == NULL); +} + +#endif /* GL_ARB_multi_draw_indirect */ + #ifdef GL_ARB_multisample static void _glewInfo_GL_ARB_multisample (void) @@ -1437,6 +1947,22 @@ static void _glewInfo_GL_ARB_point_sprite (void) #endif /* GL_ARB_point_sprite */ +#ifdef GL_ARB_program_interface_query + +static void _glewInfo_GL_ARB_program_interface_query (void) +{ + glewPrintExt("GL_ARB_program_interface_query", GLEW_ARB_program_interface_query, glewIsSupported("GL_ARB_program_interface_query"), glewGetExtension("GL_ARB_program_interface_query")); + + glewInfoFunc("glGetProgramInterfaceiv", glGetProgramInterfaceiv == NULL); + glewInfoFunc("glGetProgramResourceIndex", glGetProgramResourceIndex == NULL); + glewInfoFunc("glGetProgramResourceLocation", glGetProgramResourceLocation == NULL); + glewInfoFunc("glGetProgramResourceLocationIndex", glGetProgramResourceLocationIndex == NULL); + glewInfoFunc("glGetProgramResourceName", glGetProgramResourceName == NULL); + glewInfoFunc("glGetProgramResourceiv", glGetProgramResourceiv == NULL); +} + +#endif /* GL_ARB_program_interface_query */ + #ifdef GL_ARB_provoking_vertex static void _glewInfo_GL_ARB_provoking_vertex (void) @@ -1448,12 +1974,31 @@ static void _glewInfo_GL_ARB_provoking_vertex (void) #endif /* GL_ARB_provoking_vertex */ +#ifdef GL_ARB_query_buffer_object + +static void _glewInfo_GL_ARB_query_buffer_object (void) +{ + glewPrintExt("GL_ARB_query_buffer_object", GLEW_ARB_query_buffer_object, glewIsSupported("GL_ARB_query_buffer_object"), glewGetExtension("GL_ARB_query_buffer_object")); +} + +#endif /* GL_ARB_query_buffer_object */ + +#ifdef GL_ARB_robust_buffer_access_behavior + +static void _glewInfo_GL_ARB_robust_buffer_access_behavior (void) +{ + glewPrintExt("GL_ARB_robust_buffer_access_behavior", GLEW_ARB_robust_buffer_access_behavior, glewIsSupported("GL_ARB_robust_buffer_access_behavior"), glewGetExtension("GL_ARB_robust_buffer_access_behavior")); +} + +#endif /* GL_ARB_robust_buffer_access_behavior */ + #ifdef GL_ARB_robustness static void _glewInfo_GL_ARB_robustness (void) { glewPrintExt("GL_ARB_robustness", GLEW_ARB_robustness, glewIsSupported("GL_ARB_robustness"), glewGetExtension("GL_ARB_robustness")); + glewInfoFunc("glGetGraphicsResetStatusARB", glGetGraphicsResetStatusARB == NULL); glewInfoFunc("glGetnColorTableARB", glGetnColorTableARB == NULL); glewInfoFunc("glGetnCompressedTexImageARB", glGetnCompressedTexImageARB == NULL); glewInfoFunc("glGetnConvolutionFilterARB", glGetnConvolutionFilterARB == NULL); @@ -1477,6 +2022,24 @@ static void _glewInfo_GL_ARB_robustness (void) #endif /* GL_ARB_robustness */ +#ifdef GL_ARB_robustness_application_isolation + +static void _glewInfo_GL_ARB_robustness_application_isolation (void) +{ + glewPrintExt("GL_ARB_robustness_application_isolation", GLEW_ARB_robustness_application_isolation, glewIsSupported("GL_ARB_robustness_application_isolation"), glewGetExtension("GL_ARB_robustness_application_isolation")); +} + +#endif /* GL_ARB_robustness_application_isolation */ + +#ifdef GL_ARB_robustness_share_group_isolation + +static void _glewInfo_GL_ARB_robustness_share_group_isolation (void) +{ + glewPrintExt("GL_ARB_robustness_share_group_isolation", GLEW_ARB_robustness_share_group_isolation, glewIsSupported("GL_ARB_robustness_share_group_isolation"), glewGetExtension("GL_ARB_robustness_share_group_isolation")); +} + +#endif /* GL_ARB_robustness_share_group_isolation */ + #ifdef GL_ARB_sample_shading static void _glewInfo_GL_ARB_sample_shading (void) @@ -1521,6 +2084,15 @@ static void _glewInfo_GL_ARB_seamless_cube_map (void) #endif /* GL_ARB_seamless_cube_map */ +#ifdef GL_ARB_seamless_cubemap_per_texture + +static void _glewInfo_GL_ARB_seamless_cubemap_per_texture (void) +{ + glewPrintExt("GL_ARB_seamless_cubemap_per_texture", GLEW_ARB_seamless_cubemap_per_texture, glewIsSupported("GL_ARB_seamless_cubemap_per_texture"), glewGetExtension("GL_ARB_seamless_cubemap_per_texture")); +} + +#endif /* GL_ARB_seamless_cubemap_per_texture */ + #ifdef GL_ARB_separate_shader_objects static void _glewInfo_GL_ARB_separate_shader_objects (void) @@ -1591,6 +2163,17 @@ static void _glewInfo_GL_ARB_separate_shader_objects (void) #endif /* GL_ARB_separate_shader_objects */ +#ifdef GL_ARB_shader_atomic_counters + +static void _glewInfo_GL_ARB_shader_atomic_counters (void) +{ + glewPrintExt("GL_ARB_shader_atomic_counters", GLEW_ARB_shader_atomic_counters, glewIsSupported("GL_ARB_shader_atomic_counters"), glewGetExtension("GL_ARB_shader_atomic_counters")); + + glewInfoFunc("glGetActiveAtomicCounterBufferiv", glGetActiveAtomicCounterBufferiv == NULL); +} + +#endif /* GL_ARB_shader_atomic_counters */ + #ifdef GL_ARB_shader_bit_encoding static void _glewInfo_GL_ARB_shader_bit_encoding (void) @@ -1600,6 +2183,45 @@ static void _glewInfo_GL_ARB_shader_bit_encoding (void) #endif /* GL_ARB_shader_bit_encoding */ +#ifdef GL_ARB_shader_draw_parameters + +static void _glewInfo_GL_ARB_shader_draw_parameters (void) +{ + glewPrintExt("GL_ARB_shader_draw_parameters", GLEW_ARB_shader_draw_parameters, glewIsSupported("GL_ARB_shader_draw_parameters"), glewGetExtension("GL_ARB_shader_draw_parameters")); +} + +#endif /* GL_ARB_shader_draw_parameters */ + +#ifdef GL_ARB_shader_group_vote + +static void _glewInfo_GL_ARB_shader_group_vote (void) +{ + glewPrintExt("GL_ARB_shader_group_vote", GLEW_ARB_shader_group_vote, glewIsSupported("GL_ARB_shader_group_vote"), glewGetExtension("GL_ARB_shader_group_vote")); +} + +#endif /* GL_ARB_shader_group_vote */ + +#ifdef GL_ARB_shader_image_load_store + +static void _glewInfo_GL_ARB_shader_image_load_store (void) +{ + glewPrintExt("GL_ARB_shader_image_load_store", GLEW_ARB_shader_image_load_store, glewIsSupported("GL_ARB_shader_image_load_store"), glewGetExtension("GL_ARB_shader_image_load_store")); + + glewInfoFunc("glBindImageTexture", glBindImageTexture == NULL); + glewInfoFunc("glMemoryBarrier", glMemoryBarrier == NULL); +} + +#endif /* GL_ARB_shader_image_load_store */ + +#ifdef GL_ARB_shader_image_size + +static void _glewInfo_GL_ARB_shader_image_size (void) +{ + glewPrintExt("GL_ARB_shader_image_size", GLEW_ARB_shader_image_size, glewIsSupported("GL_ARB_shader_image_size"), glewGetExtension("GL_ARB_shader_image_size")); +} + +#endif /* GL_ARB_shader_image_size */ + #ifdef GL_ARB_shader_objects static void _glewInfo_GL_ARB_shader_objects (void) @@ -1667,6 +2289,17 @@ static void _glewInfo_GL_ARB_shader_stencil_export (void) #endif /* GL_ARB_shader_stencil_export */ +#ifdef GL_ARB_shader_storage_buffer_object + +static void _glewInfo_GL_ARB_shader_storage_buffer_object (void) +{ + glewPrintExt("GL_ARB_shader_storage_buffer_object", GLEW_ARB_shader_storage_buffer_object, glewIsSupported("GL_ARB_shader_storage_buffer_object"), glewGetExtension("GL_ARB_shader_storage_buffer_object")); + + glewInfoFunc("glShaderStorageBlockBinding", glShaderStorageBlockBinding == NULL); +} + +#endif /* GL_ARB_shader_storage_buffer_object */ + #ifdef GL_ARB_shader_subroutine static void _glewInfo_GL_ARB_shader_subroutine (void) @@ -1703,6 +2336,15 @@ static void _glewInfo_GL_ARB_shading_language_100 (void) #endif /* GL_ARB_shading_language_100 */ +#ifdef GL_ARB_shading_language_420pack + +static void _glewInfo_GL_ARB_shading_language_420pack (void) +{ + glewPrintExt("GL_ARB_shading_language_420pack", GLEW_ARB_shading_language_420pack, glewIsSupported("GL_ARB_shading_language_420pack"), glewGetExtension("GL_ARB_shading_language_420pack")); +} + +#endif /* GL_ARB_shading_language_420pack */ + #ifdef GL_ARB_shading_language_include static void _glewInfo_GL_ARB_shading_language_include (void) @@ -1719,6 +2361,15 @@ static void _glewInfo_GL_ARB_shading_language_include (void) #endif /* GL_ARB_shading_language_include */ +#ifdef GL_ARB_shading_language_packing + +static void _glewInfo_GL_ARB_shading_language_packing (void) +{ + glewPrintExt("GL_ARB_shading_language_packing", GLEW_ARB_shading_language_packing, glewIsSupported("GL_ARB_shading_language_packing"), glewGetExtension("GL_ARB_shading_language_packing")); +} + +#endif /* GL_ARB_shading_language_packing */ + #ifdef GL_ARB_shadow static void _glewInfo_GL_ARB_shadow (void) @@ -1737,6 +2388,27 @@ static void _glewInfo_GL_ARB_shadow_ambient (void) #endif /* GL_ARB_shadow_ambient */ +#ifdef GL_ARB_sparse_texture + +static void _glewInfo_GL_ARB_sparse_texture (void) +{ + glewPrintExt("GL_ARB_sparse_texture", GLEW_ARB_sparse_texture, glewIsSupported("GL_ARB_sparse_texture"), glewGetExtension("GL_ARB_sparse_texture")); + + glewInfoFunc("glTexPageCommitmentARB", glTexPageCommitmentARB == NULL); + glewInfoFunc("glTexturePageCommitmentEXT", glTexturePageCommitmentEXT == NULL); +} + +#endif /* GL_ARB_sparse_texture */ + +#ifdef GL_ARB_stencil_texturing + +static void _glewInfo_GL_ARB_stencil_texturing (void) +{ + glewPrintExt("GL_ARB_stencil_texturing", GLEW_ARB_stencil_texturing, glewIsSupported("GL_ARB_stencil_texturing"), glewGetExtension("GL_ARB_stencil_texturing")); +} + +#endif /* GL_ARB_stencil_texturing */ + #ifdef GL_ARB_sync static void _glewInfo_GL_ARB_sync (void) @@ -1795,6 +2467,18 @@ static void _glewInfo_GL_ARB_texture_buffer_object_rgb32 (void) #endif /* GL_ARB_texture_buffer_object_rgb32 */ +#ifdef GL_ARB_texture_buffer_range + +static void _glewInfo_GL_ARB_texture_buffer_range (void) +{ + glewPrintExt("GL_ARB_texture_buffer_range", GLEW_ARB_texture_buffer_range, glewIsSupported("GL_ARB_texture_buffer_range"), glewGetExtension("GL_ARB_texture_buffer_range")); + + glewInfoFunc("glTexBufferRange", glTexBufferRange == NULL); + glewInfoFunc("glTextureBufferRangeEXT", glTextureBufferRangeEXT == NULL); +} + +#endif /* GL_ARB_texture_buffer_range */ + #ifdef GL_ARB_texture_compression static void _glewInfo_GL_ARB_texture_compression (void) @@ -1902,6 +2586,15 @@ static void _glewInfo_GL_ARB_texture_gather (void) #endif /* GL_ARB_texture_gather */ +#ifdef GL_ARB_texture_mirror_clamp_to_edge + +static void _glewInfo_GL_ARB_texture_mirror_clamp_to_edge (void) +{ + glewPrintExt("GL_ARB_texture_mirror_clamp_to_edge", GLEW_ARB_texture_mirror_clamp_to_edge, glewIsSupported("GL_ARB_texture_mirror_clamp_to_edge"), glewGetExtension("GL_ARB_texture_mirror_clamp_to_edge")); +} + +#endif /* GL_ARB_texture_mirror_clamp_to_edge */ + #ifdef GL_ARB_texture_mirrored_repeat static void _glewInfo_GL_ARB_texture_mirrored_repeat (void) @@ -1934,6 +2627,15 @@ static void _glewInfo_GL_ARB_texture_non_power_of_two (void) #endif /* GL_ARB_texture_non_power_of_two */ +#ifdef GL_ARB_texture_query_levels + +static void _glewInfo_GL_ARB_texture_query_levels (void) +{ + glewPrintExt("GL_ARB_texture_query_levels", GLEW_ARB_texture_query_levels, glewIsSupported("GL_ARB_texture_query_levels"), glewGetExtension("GL_ARB_texture_query_levels")); +} + +#endif /* GL_ARB_texture_query_levels */ + #ifdef GL_ARB_texture_query_lod static void _glewInfo_GL_ARB_texture_query_lod (void) @@ -1970,6 +2672,45 @@ static void _glewInfo_GL_ARB_texture_rgb10_a2ui (void) #endif /* GL_ARB_texture_rgb10_a2ui */ +#ifdef GL_ARB_texture_stencil8 + +static void _glewInfo_GL_ARB_texture_stencil8 (void) +{ + glewPrintExt("GL_ARB_texture_stencil8", GLEW_ARB_texture_stencil8, glewIsSupported("GL_ARB_texture_stencil8"), glewGetExtension("GL_ARB_texture_stencil8")); +} + +#endif /* GL_ARB_texture_stencil8 */ + +#ifdef GL_ARB_texture_storage + +static void _glewInfo_GL_ARB_texture_storage (void) +{ + glewPrintExt("GL_ARB_texture_storage", GLEW_ARB_texture_storage, glewIsSupported("GL_ARB_texture_storage"), glewGetExtension("GL_ARB_texture_storage")); + + glewInfoFunc("glTexStorage1D", glTexStorage1D == NULL); + glewInfoFunc("glTexStorage2D", glTexStorage2D == NULL); + glewInfoFunc("glTexStorage3D", glTexStorage3D == NULL); + glewInfoFunc("glTextureStorage1DEXT", glTextureStorage1DEXT == NULL); + glewInfoFunc("glTextureStorage2DEXT", glTextureStorage2DEXT == NULL); + glewInfoFunc("glTextureStorage3DEXT", glTextureStorage3DEXT == NULL); +} + +#endif /* GL_ARB_texture_storage */ + +#ifdef GL_ARB_texture_storage_multisample + +static void _glewInfo_GL_ARB_texture_storage_multisample (void) +{ + glewPrintExt("GL_ARB_texture_storage_multisample", GLEW_ARB_texture_storage_multisample, glewIsSupported("GL_ARB_texture_storage_multisample"), glewGetExtension("GL_ARB_texture_storage_multisample")); + + glewInfoFunc("glTexStorage2DMultisample", glTexStorage2DMultisample == NULL); + glewInfoFunc("glTexStorage3DMultisample", glTexStorage3DMultisample == NULL); + glewInfoFunc("glTextureStorage2DMultisampleEXT", glTextureStorage2DMultisampleEXT == NULL); + glewInfoFunc("glTextureStorage3DMultisampleEXT", glTextureStorage3DMultisampleEXT == NULL); +} + +#endif /* GL_ARB_texture_storage_multisample */ + #ifdef GL_ARB_texture_swizzle static void _glewInfo_GL_ARB_texture_swizzle (void) @@ -1979,6 +2720,17 @@ static void _glewInfo_GL_ARB_texture_swizzle (void) #endif /* GL_ARB_texture_swizzle */ +#ifdef GL_ARB_texture_view + +static void _glewInfo_GL_ARB_texture_view (void) +{ + glewPrintExt("GL_ARB_texture_view", GLEW_ARB_texture_view, glewIsSupported("GL_ARB_texture_view"), glewGetExtension("GL_ARB_texture_view")); + + glewInfoFunc("glTextureView", glTextureView == NULL); +} + +#endif /* GL_ARB_texture_view */ + #ifdef GL_ARB_timer_query static void _glewInfo_GL_ARB_timer_query (void) @@ -2023,6 +2775,18 @@ static void _glewInfo_GL_ARB_transform_feedback3 (void) #endif /* GL_ARB_transform_feedback3 */ +#ifdef GL_ARB_transform_feedback_instanced + +static void _glewInfo_GL_ARB_transform_feedback_instanced (void) +{ + glewPrintExt("GL_ARB_transform_feedback_instanced", GLEW_ARB_transform_feedback_instanced, glewIsSupported("GL_ARB_transform_feedback_instanced"), glewGetExtension("GL_ARB_transform_feedback_instanced")); + + glewInfoFunc("glDrawTransformFeedbackInstanced", glDrawTransformFeedbackInstanced == NULL); + glewInfoFunc("glDrawTransformFeedbackStreamInstanced", glDrawTransformFeedbackStreamInstanced == NULL); +} + +#endif /* GL_ARB_transform_feedback_instanced */ + #ifdef GL_ARB_transpose_matrix static void _glewInfo_GL_ARB_transpose_matrix (void) @@ -2100,6 +2864,22 @@ static void _glewInfo_GL_ARB_vertex_attrib_64bit (void) #endif /* GL_ARB_vertex_attrib_64bit */ +#ifdef GL_ARB_vertex_attrib_binding + +static void _glewInfo_GL_ARB_vertex_attrib_binding (void) +{ + glewPrintExt("GL_ARB_vertex_attrib_binding", GLEW_ARB_vertex_attrib_binding, glewIsSupported("GL_ARB_vertex_attrib_binding"), glewGetExtension("GL_ARB_vertex_attrib_binding")); + + glewInfoFunc("glBindVertexBuffer", glBindVertexBuffer == NULL); + glewInfoFunc("glVertexAttribBinding", glVertexAttribBinding == NULL); + glewInfoFunc("glVertexAttribFormat", glVertexAttribFormat == NULL); + glewInfoFunc("glVertexAttribIFormat", glVertexAttribIFormat == NULL); + glewInfoFunc("glVertexAttribLFormat", glVertexAttribLFormat == NULL); + glewInfoFunc("glVertexBindingDivisor", glVertexBindingDivisor == NULL); +} + +#endif /* GL_ARB_vertex_attrib_binding */ + #ifdef GL_ARB_vertex_blend static void _glewInfo_GL_ARB_vertex_blend (void) @@ -2226,6 +3006,15 @@ static void _glewInfo_GL_ARB_vertex_shader (void) #endif /* GL_ARB_vertex_shader */ +#ifdef GL_ARB_vertex_type_10f_11f_11f_rev + +static void _glewInfo_GL_ARB_vertex_type_10f_11f_11f_rev (void) +{ + glewPrintExt("GL_ARB_vertex_type_10f_11f_11f_rev", GLEW_ARB_vertex_type_10f_11f_11f_rev, glewIsSupported("GL_ARB_vertex_type_10f_11f_11f_rev"), glewGetExtension("GL_ARB_vertex_type_10f_11f_11f_rev")); +} + +#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */ + #ifdef GL_ARB_vertex_type_2_10_10_10_rev static void _glewInfo_GL_ARB_vertex_type_2_10_10_10_rev (void) @@ -2571,6 +3360,14 @@ static void _glewInfo_GL_ATI_vertex_streams (void) glewInfoFunc("glNormalStream3svATI", glNormalStream3svATI == NULL); glewInfoFunc("glVertexBlendEnvfATI", glVertexBlendEnvfATI == NULL); glewInfoFunc("glVertexBlendEnviATI", glVertexBlendEnviATI == NULL); + glewInfoFunc("glVertexStream1dATI", glVertexStream1dATI == NULL); + glewInfoFunc("glVertexStream1dvATI", glVertexStream1dvATI == NULL); + glewInfoFunc("glVertexStream1fATI", glVertexStream1fATI == NULL); + glewInfoFunc("glVertexStream1fvATI", glVertexStream1fvATI == NULL); + glewInfoFunc("glVertexStream1iATI", glVertexStream1iATI == NULL); + glewInfoFunc("glVertexStream1ivATI", glVertexStream1ivATI == NULL); + glewInfoFunc("glVertexStream1sATI", glVertexStream1sATI == NULL); + glewInfoFunc("glVertexStream1svATI", glVertexStream1svATI == NULL); glewInfoFunc("glVertexStream2dATI", glVertexStream2dATI == NULL); glewInfoFunc("glVertexStream2dvATI", glVertexStream2dvATI == NULL); glewInfoFunc("glVertexStream2fATI", glVertexStream2fATI == NULL); @@ -2814,6 +3611,19 @@ static void _glewInfo_GL_EXT_cull_vertex (void) #endif /* GL_EXT_cull_vertex */ +#ifdef GL_EXT_debug_marker + +static void _glewInfo_GL_EXT_debug_marker (void) +{ + glewPrintExt("GL_EXT_debug_marker", GLEW_EXT_debug_marker, glewIsSupported("GL_EXT_debug_marker"), glewGetExtension("GL_EXT_debug_marker")); + + glewInfoFunc("glInsertEventMarkerEXT", glInsertEventMarkerEXT == NULL); + glewInfoFunc("glPopGroupMarkerEXT", glPopGroupMarkerEXT == NULL); + glewInfoFunc("glPushGroupMarkerEXT", glPushGroupMarkerEXT == NULL); +} + +#endif /* GL_EXT_debug_marker */ + #ifdef GL_EXT_depth_bounds_test static void _glewInfo_GL_EXT_depth_bounds_test (void) @@ -3152,6 +3962,15 @@ static void _glewInfo_GL_EXT_framebuffer_multisample (void) #endif /* GL_EXT_framebuffer_multisample */ +#ifdef GL_EXT_framebuffer_multisample_blit_scaled + +static void _glewInfo_GL_EXT_framebuffer_multisample_blit_scaled (void) +{ + glewPrintExt("GL_EXT_framebuffer_multisample_blit_scaled", GLEW_EXT_framebuffer_multisample_blit_scaled, glewIsSupported("GL_EXT_framebuffer_multisample_blit_scaled"), glewGetExtension("GL_EXT_framebuffer_multisample_blit_scaled")); +} + +#endif /* GL_EXT_framebuffer_multisample_blit_scaled */ + #ifdef GL_EXT_framebuffer_object static void _glewInfo_GL_EXT_framebuffer_object (void) @@ -4172,6 +4991,19 @@ static void _glewInfo_GL_INGR_interlace_read (void) #endif /* GL_INGR_interlace_read */ +#ifdef GL_INTEL_map_texture + +static void _glewInfo_GL_INTEL_map_texture (void) +{ + glewPrintExt("GL_INTEL_map_texture", GLEW_INTEL_map_texture, glewIsSupported("GL_INTEL_map_texture"), glewGetExtension("GL_INTEL_map_texture")); + + glewInfoFunc("glMapTexture2DINTEL", glMapTexture2DINTEL == NULL); + glewInfoFunc("glSyncTextureINTEL", glSyncTextureINTEL == NULL); + glewInfoFunc("glUnmapTexture2DINTEL", glUnmapTexture2DINTEL == NULL); +} + +#endif /* GL_INTEL_map_texture */ + #ifdef GL_INTEL_parallel_arrays static void _glewInfo_GL_INTEL_parallel_arrays (void) @@ -4198,17 +5030,46 @@ static void _glewInfo_GL_INTEL_texture_scissor (void) #endif /* GL_INTEL_texture_scissor */ +#ifdef GL_KHR_debug + +static void _glewInfo_GL_KHR_debug (void) +{ + glewPrintExt("GL_KHR_debug", GLEW_KHR_debug, glewIsSupported("GL_KHR_debug"), glewGetExtension("GL_KHR_debug")); + + glewInfoFunc("glDebugMessageCallback", glDebugMessageCallback == NULL); + glewInfoFunc("glDebugMessageControl", glDebugMessageControl == NULL); + glewInfoFunc("glDebugMessageInsert", glDebugMessageInsert == NULL); + glewInfoFunc("glGetDebugMessageLog", glGetDebugMessageLog == NULL); + glewInfoFunc("glGetObjectLabel", glGetObjectLabel == NULL); + glewInfoFunc("glGetObjectPtrLabel", glGetObjectPtrLabel == NULL); + glewInfoFunc("glObjectLabel", glObjectLabel == NULL); + glewInfoFunc("glObjectPtrLabel", glObjectPtrLabel == NULL); + glewInfoFunc("glPopDebugGroup", glPopDebugGroup == NULL); + glewInfoFunc("glPushDebugGroup", glPushDebugGroup == NULL); +} + +#endif /* GL_KHR_debug */ + +#ifdef GL_KHR_texture_compression_astc_ldr + +static void _glewInfo_GL_KHR_texture_compression_astc_ldr (void) +{ + glewPrintExt("GL_KHR_texture_compression_astc_ldr", GLEW_KHR_texture_compression_astc_ldr, glewIsSupported("GL_KHR_texture_compression_astc_ldr"), glewGetExtension("GL_KHR_texture_compression_astc_ldr")); +} + +#endif /* GL_KHR_texture_compression_astc_ldr */ + #ifdef GL_KTX_buffer_region static void _glewInfo_GL_KTX_buffer_region (void) { glewPrintExt("GL_KTX_buffer_region", GLEW_KTX_buffer_region, glewIsSupported("GL_KTX_buffer_region"), glewGetExtension("GL_KTX_buffer_region")); - glewInfoFunc("glBufferRegionEnabledEXT", glBufferRegionEnabledEXT == NULL); - glewInfoFunc("glDeleteBufferRegionEXT", glDeleteBufferRegionEXT == NULL); - glewInfoFunc("glDrawBufferRegionEXT", glDrawBufferRegionEXT == NULL); - glewInfoFunc("glNewBufferRegionEXT", glNewBufferRegionEXT == NULL); - glewInfoFunc("glReadBufferRegionEXT", glReadBufferRegionEXT == NULL); + glewInfoFunc("glBufferRegionEnabled", glBufferRegionEnabled == NULL); + glewInfoFunc("glDeleteBufferRegion", glDeleteBufferRegion == NULL); + glewInfoFunc("glDrawBufferRegion", glDrawBufferRegion == NULL); + glewInfoFunc("glNewBufferRegion", glNewBufferRegion == NULL); + glewInfoFunc("glReadBufferRegion", glReadBufferRegion == NULL); } #endif /* GL_KTX_buffer_region */ @@ -4285,6 +5146,18 @@ static void _glewInfo_GL_MESA_ycbcr_texture (void) #endif /* GL_MESA_ycbcr_texture */ +#ifdef GL_NVX_conditional_render + +static void _glewInfo_GL_NVX_conditional_render (void) +{ + glewPrintExt("GL_NVX_conditional_render", GLEW_NVX_conditional_render, glewIsSupported("GL_NVX_conditional_render"), glewGetExtension("GL_NVX_conditional_render")); + + glewInfoFunc("glBeginConditionalRenderNVX", glBeginConditionalRenderNVX == NULL); + glewInfoFunc("glEndConditionalRenderNVX", glEndConditionalRenderNVX == NULL); +} + +#endif /* GL_NVX_conditional_render */ + #ifdef GL_NVX_gpu_memory_info static void _glewInfo_GL_NVX_gpu_memory_info (void) @@ -4294,6 +5167,62 @@ static void _glewInfo_GL_NVX_gpu_memory_info (void) #endif /* GL_NVX_gpu_memory_info */ +#ifdef GL_NV_bindless_multi_draw_indirect + +static void _glewInfo_GL_NV_bindless_multi_draw_indirect (void) +{ + glewPrintExt("GL_NV_bindless_multi_draw_indirect", GLEW_NV_bindless_multi_draw_indirect, glewIsSupported("GL_NV_bindless_multi_draw_indirect"), glewGetExtension("GL_NV_bindless_multi_draw_indirect")); + + glewInfoFunc("glMultiDrawArraysIndirectBindlessNV", glMultiDrawArraysIndirectBindlessNV == NULL); + glewInfoFunc("glMultiDrawElementsIndirectBindlessNV", glMultiDrawElementsIndirectBindlessNV == NULL); +} + +#endif /* GL_NV_bindless_multi_draw_indirect */ + +#ifdef GL_NV_bindless_texture + +static void _glewInfo_GL_NV_bindless_texture (void) +{ + glewPrintExt("GL_NV_bindless_texture", GLEW_NV_bindless_texture, glewIsSupported("GL_NV_bindless_texture"), glewGetExtension("GL_NV_bindless_texture")); + + glewInfoFunc("glGetImageHandleNV", glGetImageHandleNV == NULL); + glewInfoFunc("glGetTextureHandleNV", glGetTextureHandleNV == NULL); + glewInfoFunc("glGetTextureSamplerHandleNV", glGetTextureSamplerHandleNV == NULL); + glewInfoFunc("glIsImageHandleResidentNV", glIsImageHandleResidentNV == NULL); + glewInfoFunc("glIsTextureHandleResidentNV", glIsTextureHandleResidentNV == NULL); + glewInfoFunc("glMakeImageHandleNonResidentNV", glMakeImageHandleNonResidentNV == NULL); + glewInfoFunc("glMakeImageHandleResidentNV", glMakeImageHandleResidentNV == NULL); + glewInfoFunc("glMakeTextureHandleNonResidentNV", glMakeTextureHandleNonResidentNV == NULL); + glewInfoFunc("glMakeTextureHandleResidentNV", glMakeTextureHandleResidentNV == NULL); + glewInfoFunc("glProgramUniformHandleui64NV", glProgramUniformHandleui64NV == NULL); + glewInfoFunc("glProgramUniformHandleui64vNV", glProgramUniformHandleui64vNV == NULL); + glewInfoFunc("glUniformHandleui64NV", glUniformHandleui64NV == NULL); + glewInfoFunc("glUniformHandleui64vNV", glUniformHandleui64vNV == NULL); +} + +#endif /* GL_NV_bindless_texture */ + +#ifdef GL_NV_blend_equation_advanced + +static void _glewInfo_GL_NV_blend_equation_advanced (void) +{ + glewPrintExt("GL_NV_blend_equation_advanced", GLEW_NV_blend_equation_advanced, glewIsSupported("GL_NV_blend_equation_advanced"), glewGetExtension("GL_NV_blend_equation_advanced")); + + glewInfoFunc("glBlendBarrierNV", glBlendBarrierNV == NULL); + glewInfoFunc("glBlendParameteriNV", glBlendParameteriNV == NULL); +} + +#endif /* GL_NV_blend_equation_advanced */ + +#ifdef GL_NV_blend_equation_advanced_coherent + +static void _glewInfo_GL_NV_blend_equation_advanced_coherent (void) +{ + glewPrintExt("GL_NV_blend_equation_advanced_coherent", GLEW_NV_blend_equation_advanced_coherent, glewIsSupported("GL_NV_blend_equation_advanced_coherent"), glewGetExtension("GL_NV_blend_equation_advanced_coherent")); +} + +#endif /* GL_NV_blend_equation_advanced_coherent */ + #ifdef GL_NV_blend_square static void _glewInfo_GL_NV_blend_square (void) @@ -4303,6 +5232,15 @@ static void _glewInfo_GL_NV_blend_square (void) #endif /* GL_NV_blend_square */ +#ifdef GL_NV_compute_program5 + +static void _glewInfo_GL_NV_compute_program5 (void) +{ + glewPrintExt("GL_NV_compute_program5", GLEW_NV_compute_program5, glewIsSupported("GL_NV_compute_program5"), glewGetExtension("GL_NV_compute_program5")); +} + +#endif /* GL_NV_compute_program5 */ + #ifdef GL_NV_conditional_render static void _glewInfo_GL_NV_conditional_render (void) @@ -4335,6 +5273,15 @@ static void _glewInfo_GL_NV_copy_image (void) #endif /* GL_NV_copy_image */ +#ifdef GL_NV_deep_texture3D + +static void _glewInfo_GL_NV_deep_texture3D (void) +{ + glewPrintExt("GL_NV_deep_texture3D", GLEW_NV_deep_texture3D, glewIsSupported("GL_NV_deep_texture3D"), glewGetExtension("GL_NV_deep_texture3D")); +} + +#endif /* GL_NV_deep_texture3D */ + #ifdef GL_NV_depth_buffer_float static void _glewInfo_GL_NV_depth_buffer_float (void) @@ -4366,6 +5313,17 @@ static void _glewInfo_GL_NV_depth_range_unclamped (void) #endif /* GL_NV_depth_range_unclamped */ +#ifdef GL_NV_draw_texture + +static void _glewInfo_GL_NV_draw_texture (void) +{ + glewPrintExt("GL_NV_draw_texture", GLEW_NV_draw_texture, glewIsSupported("GL_NV_draw_texture"), glewGetExtension("GL_NV_draw_texture")); + + glewInfoFunc("glDrawTextureNV", glDrawTextureNV == NULL); +} + +#endif /* GL_NV_draw_texture */ + #ifdef GL_NV_evaluators static void _glewInfo_GL_NV_evaluators (void) @@ -4538,6 +5496,15 @@ static void _glewInfo_GL_NV_gpu_program5 (void) #endif /* GL_NV_gpu_program5 */ +#ifdef GL_NV_gpu_program5_mem_extended + +static void _glewInfo_GL_NV_gpu_program5_mem_extended (void) +{ + glewPrintExt("GL_NV_gpu_program5_mem_extended", GLEW_NV_gpu_program5_mem_extended, glewIsSupported("GL_NV_gpu_program5_mem_extended"), glewGetExtension("GL_NV_gpu_program5_mem_extended")); +} + +#endif /* GL_NV_gpu_program5_mem_extended */ + #ifdef GL_NV_gpu_program_fp64 static void _glewInfo_GL_NV_gpu_program_fp64 (void) @@ -4722,6 +5689,65 @@ static void _glewInfo_GL_NV_parameter_buffer_object2 (void) #endif /* GL_NV_parameter_buffer_object2 */ +#ifdef GL_NV_path_rendering + +static void _glewInfo_GL_NV_path_rendering (void) +{ + glewPrintExt("GL_NV_path_rendering", GLEW_NV_path_rendering, glewIsSupported("GL_NV_path_rendering"), glewGetExtension("GL_NV_path_rendering")); + + glewInfoFunc("glCopyPathNV", glCopyPathNV == NULL); + glewInfoFunc("glCoverFillPathInstancedNV", glCoverFillPathInstancedNV == NULL); + glewInfoFunc("glCoverFillPathNV", glCoverFillPathNV == NULL); + glewInfoFunc("glCoverStrokePathInstancedNV", glCoverStrokePathInstancedNV == NULL); + glewInfoFunc("glCoverStrokePathNV", glCoverStrokePathNV == NULL); + glewInfoFunc("glDeletePathsNV", glDeletePathsNV == NULL); + glewInfoFunc("glGenPathsNV", glGenPathsNV == NULL); + glewInfoFunc("glGetPathColorGenfvNV", glGetPathColorGenfvNV == NULL); + glewInfoFunc("glGetPathColorGenivNV", glGetPathColorGenivNV == NULL); + glewInfoFunc("glGetPathCommandsNV", glGetPathCommandsNV == NULL); + glewInfoFunc("glGetPathCoordsNV", glGetPathCoordsNV == NULL); + glewInfoFunc("glGetPathDashArrayNV", glGetPathDashArrayNV == NULL); + glewInfoFunc("glGetPathLengthNV", glGetPathLengthNV == NULL); + glewInfoFunc("glGetPathMetricRangeNV", glGetPathMetricRangeNV == NULL); + glewInfoFunc("glGetPathMetricsNV", glGetPathMetricsNV == NULL); + glewInfoFunc("glGetPathParameterfvNV", glGetPathParameterfvNV == NULL); + glewInfoFunc("glGetPathParameterivNV", glGetPathParameterivNV == NULL); + glewInfoFunc("glGetPathSpacingNV", glGetPathSpacingNV == NULL); + glewInfoFunc("glGetPathTexGenfvNV", glGetPathTexGenfvNV == NULL); + glewInfoFunc("glGetPathTexGenivNV", glGetPathTexGenivNV == NULL); + glewInfoFunc("glInterpolatePathsNV", glInterpolatePathsNV == NULL); + glewInfoFunc("glIsPathNV", glIsPathNV == NULL); + glewInfoFunc("glIsPointInFillPathNV", glIsPointInFillPathNV == NULL); + glewInfoFunc("glIsPointInStrokePathNV", glIsPointInStrokePathNV == NULL); + glewInfoFunc("glPathColorGenNV", glPathColorGenNV == NULL); + glewInfoFunc("glPathCommandsNV", glPathCommandsNV == NULL); + glewInfoFunc("glPathCoordsNV", glPathCoordsNV == NULL); + glewInfoFunc("glPathCoverDepthFuncNV", glPathCoverDepthFuncNV == NULL); + glewInfoFunc("glPathDashArrayNV", glPathDashArrayNV == NULL); + glewInfoFunc("glPathFogGenNV", glPathFogGenNV == NULL); + glewInfoFunc("glPathGlyphRangeNV", glPathGlyphRangeNV == NULL); + glewInfoFunc("glPathGlyphsNV", glPathGlyphsNV == NULL); + glewInfoFunc("glPathParameterfNV", glPathParameterfNV == NULL); + glewInfoFunc("glPathParameterfvNV", glPathParameterfvNV == NULL); + glewInfoFunc("glPathParameteriNV", glPathParameteriNV == NULL); + glewInfoFunc("glPathParameterivNV", glPathParameterivNV == NULL); + glewInfoFunc("glPathStencilDepthOffsetNV", glPathStencilDepthOffsetNV == NULL); + glewInfoFunc("glPathStencilFuncNV", glPathStencilFuncNV == NULL); + glewInfoFunc("glPathStringNV", glPathStringNV == NULL); + glewInfoFunc("glPathSubCommandsNV", glPathSubCommandsNV == NULL); + glewInfoFunc("glPathSubCoordsNV", glPathSubCoordsNV == NULL); + glewInfoFunc("glPathTexGenNV", glPathTexGenNV == NULL); + glewInfoFunc("glPointAlongPathNV", glPointAlongPathNV == NULL); + glewInfoFunc("glStencilFillPathInstancedNV", glStencilFillPathInstancedNV == NULL); + glewInfoFunc("glStencilFillPathNV", glStencilFillPathNV == NULL); + glewInfoFunc("glStencilStrokePathInstancedNV", glStencilStrokePathInstancedNV == NULL); + glewInfoFunc("glStencilStrokePathNV", glStencilStrokePathNV == NULL); + glewInfoFunc("glTransformPathNV", glTransformPathNV == NULL); + glewInfoFunc("glWeightPathsNV", glWeightPathsNV == NULL); +} + +#endif /* GL_NV_path_rendering */ + #ifdef GL_NV_pixel_data_range static void _glewInfo_GL_NV_pixel_data_range (void) @@ -4809,6 +5835,24 @@ static void _glewInfo_GL_NV_register_combiners2 (void) #endif /* GL_NV_register_combiners2 */ +#ifdef GL_NV_shader_atomic_counters + +static void _glewInfo_GL_NV_shader_atomic_counters (void) +{ + glewPrintExt("GL_NV_shader_atomic_counters", GLEW_NV_shader_atomic_counters, glewIsSupported("GL_NV_shader_atomic_counters"), glewGetExtension("GL_NV_shader_atomic_counters")); +} + +#endif /* GL_NV_shader_atomic_counters */ + +#ifdef GL_NV_shader_atomic_float + +static void _glewInfo_GL_NV_shader_atomic_float (void) +{ + glewPrintExt("GL_NV_shader_atomic_float", GLEW_NV_shader_atomic_float, glewIsSupported("GL_NV_shader_atomic_float"), glewGetExtension("GL_NV_shader_atomic_float")); +} + +#endif /* GL_NV_shader_atomic_float */ + #ifdef GL_NV_shader_buffer_load static void _glewInfo_GL_NV_shader_buffer_load (void) @@ -4832,6 +5876,15 @@ static void _glewInfo_GL_NV_shader_buffer_load (void) #endif /* GL_NV_shader_buffer_load */ +#ifdef GL_NV_shader_storage_buffer_object + +static void _glewInfo_GL_NV_shader_storage_buffer_object (void) +{ + glewPrintExt("GL_NV_shader_storage_buffer_object", GLEW_NV_shader_storage_buffer_object, glewIsSupported("GL_NV_shader_storage_buffer_object"), glewGetExtension("GL_NV_shader_storage_buffer_object")); +} + +#endif /* GL_NV_shader_storage_buffer_object */ + #ifdef GL_NV_tessellation_program5 static void _glewInfo_GL_NV_tessellation_program5 (void) @@ -5308,6 +6361,113 @@ static void _glewInfo_GL_PGI_vertex_hints (void) #endif /* GL_PGI_vertex_hints */ +#ifdef GL_REGAL_ES1_0_compatibility + +static void _glewInfo_GL_REGAL_ES1_0_compatibility (void) +{ + glewPrintExt("GL_REGAL_ES1_0_compatibility", GLEW_REGAL_ES1_0_compatibility, glewIsSupported("GL_REGAL_ES1_0_compatibility"), glewGetExtension("GL_REGAL_ES1_0_compatibility")); + + glewInfoFunc("glAlphaFuncx", glAlphaFuncx == NULL); + glewInfoFunc("glClearColorx", glClearColorx == NULL); + glewInfoFunc("glClearDepthx", glClearDepthx == NULL); + glewInfoFunc("glColor4x", glColor4x == NULL); + glewInfoFunc("glDepthRangex", glDepthRangex == NULL); + glewInfoFunc("glFogx", glFogx == NULL); + glewInfoFunc("glFogxv", glFogxv == NULL); + glewInfoFunc("glFrustumf", glFrustumf == NULL); + glewInfoFunc("glFrustumx", glFrustumx == NULL); + glewInfoFunc("glLightModelx", glLightModelx == NULL); + glewInfoFunc("glLightModelxv", glLightModelxv == NULL); + glewInfoFunc("glLightx", glLightx == NULL); + glewInfoFunc("glLightxv", glLightxv == NULL); + glewInfoFunc("glLineWidthx", glLineWidthx == NULL); + glewInfoFunc("glLoadMatrixx", glLoadMatrixx == NULL); + glewInfoFunc("glMaterialx", glMaterialx == NULL); + glewInfoFunc("glMaterialxv", glMaterialxv == NULL); + glewInfoFunc("glMultMatrixx", glMultMatrixx == NULL); + glewInfoFunc("glMultiTexCoord4x", glMultiTexCoord4x == NULL); + glewInfoFunc("glNormal3x", glNormal3x == NULL); + glewInfoFunc("glOrthof", glOrthof == NULL); + glewInfoFunc("glOrthox", glOrthox == NULL); + glewInfoFunc("glPointSizex", glPointSizex == NULL); + glewInfoFunc("glPolygonOffsetx", glPolygonOffsetx == NULL); + glewInfoFunc("glRotatex", glRotatex == NULL); + glewInfoFunc("glSampleCoveragex", glSampleCoveragex == NULL); + glewInfoFunc("glScalex", glScalex == NULL); + glewInfoFunc("glTexEnvx", glTexEnvx == NULL); + glewInfoFunc("glTexEnvxv", glTexEnvxv == NULL); + glewInfoFunc("glTexParameterx", glTexParameterx == NULL); + glewInfoFunc("glTranslatex", glTranslatex == NULL); +} + +#endif /* GL_REGAL_ES1_0_compatibility */ + +#ifdef GL_REGAL_ES1_1_compatibility + +static void _glewInfo_GL_REGAL_ES1_1_compatibility (void) +{ + glewPrintExt("GL_REGAL_ES1_1_compatibility", GLEW_REGAL_ES1_1_compatibility, glewIsSupported("GL_REGAL_ES1_1_compatibility"), glewGetExtension("GL_REGAL_ES1_1_compatibility")); + + glewInfoFunc("glClipPlanef", glClipPlanef == NULL); + glewInfoFunc("glClipPlanex", glClipPlanex == NULL); + glewInfoFunc("glGetClipPlanef", glGetClipPlanef == NULL); + glewInfoFunc("glGetClipPlanex", glGetClipPlanex == NULL); + glewInfoFunc("glGetFixedv", glGetFixedv == NULL); + glewInfoFunc("glGetLightxv", glGetLightxv == NULL); + glewInfoFunc("glGetMaterialxv", glGetMaterialxv == NULL); + glewInfoFunc("glGetTexEnvxv", glGetTexEnvxv == NULL); + glewInfoFunc("glGetTexParameterxv", glGetTexParameterxv == NULL); + glewInfoFunc("glPointParameterx", glPointParameterx == NULL); + glewInfoFunc("glPointParameterxv", glPointParameterxv == NULL); + glewInfoFunc("glPointSizePointerOES", glPointSizePointerOES == NULL); + glewInfoFunc("glTexParameterxv", glTexParameterxv == NULL); +} + +#endif /* GL_REGAL_ES1_1_compatibility */ + +#ifdef GL_REGAL_enable + +static void _glewInfo_GL_REGAL_enable (void) +{ + glewPrintExt("GL_REGAL_enable", GLEW_REGAL_enable, glewIsSupported("GL_REGAL_enable"), glewGetExtension("GL_REGAL_enable")); +} + +#endif /* GL_REGAL_enable */ + +#ifdef GL_REGAL_error_string + +static void _glewInfo_GL_REGAL_error_string (void) +{ + glewPrintExt("GL_REGAL_error_string", GLEW_REGAL_error_string, glewIsSupported("GL_REGAL_error_string"), glewGetExtension("GL_REGAL_error_string")); + + glewInfoFunc("glErrorStringREGAL", glErrorStringREGAL == NULL); +} + +#endif /* GL_REGAL_error_string */ + +#ifdef GL_REGAL_extension_query + +static void _glewInfo_GL_REGAL_extension_query (void) +{ + glewPrintExt("GL_REGAL_extension_query", GLEW_REGAL_extension_query, glewIsSupported("GL_REGAL_extension_query"), glewGetExtension("GL_REGAL_extension_query")); + + glewInfoFunc("glGetExtensionREGAL", glGetExtensionREGAL == NULL); + glewInfoFunc("glIsSupportedREGAL", glIsSupportedREGAL == NULL); +} + +#endif /* GL_REGAL_extension_query */ + +#ifdef GL_REGAL_log + +static void _glewInfo_GL_REGAL_log (void) +{ + glewPrintExt("GL_REGAL_log", GLEW_REGAL_log, glewIsSupported("GL_REGAL_log"), glewGetExtension("GL_REGAL_log")); + + glewInfoFunc("glLogMessageCallbackREGAL", glLogMessageCallbackREGAL == NULL); +} + +#endif /* GL_REGAL_log */ + #ifdef GL_REND_screen_coordinates static void _glewInfo_GL_REND_screen_coordinates (void) @@ -6173,6 +7333,24 @@ static void _glewInfo_WGL_ARB_render_texture (void) #endif /* WGL_ARB_render_texture */ +#ifdef WGL_ARB_robustness_application_isolation + +static void _glewInfo_WGL_ARB_robustness_application_isolation (void) +{ + glewPrintExt("WGL_ARB_robustness_application_isolation", WGLEW_ARB_robustness_application_isolation, wglewIsSupported("WGL_ARB_robustness_application_isolation"), wglewGetExtension("WGL_ARB_robustness_application_isolation")); +} + +#endif /* WGL_ARB_robustness_application_isolation */ + +#ifdef WGL_ARB_robustness_share_group_isolation + +static void _glewInfo_WGL_ARB_robustness_share_group_isolation (void) +{ + glewPrintExt("WGL_ARB_robustness_share_group_isolation", WGLEW_ARB_robustness_share_group_isolation, wglewIsSupported("WGL_ARB_robustness_share_group_isolation"), wglewGetExtension("WGL_ARB_robustness_share_group_isolation")); +} + +#endif /* WGL_ARB_robustness_share_group_isolation */ + #ifdef WGL_ATI_pixel_format_float static void _glewInfo_WGL_ATI_pixel_format_float (void) @@ -6200,6 +7378,15 @@ static void _glewInfo_WGL_EXT_create_context_es2_profile (void) #endif /* WGL_EXT_create_context_es2_profile */ +#ifdef WGL_EXT_create_context_es_profile + +static void _glewInfo_WGL_EXT_create_context_es_profile (void) +{ + glewPrintExt("WGL_EXT_create_context_es_profile", WGLEW_EXT_create_context_es_profile, wglewIsSupported("WGL_EXT_create_context_es_profile"), wglewGetExtension("WGL_EXT_create_context_es_profile")); +} + +#endif /* WGL_EXT_create_context_es_profile */ + #ifdef WGL_EXT_depth_float static void _glewInfo_WGL_EXT_depth_float (void) @@ -6313,6 +7500,15 @@ static void _glewInfo_WGL_EXT_swap_control (void) #endif /* WGL_EXT_swap_control */ +#ifdef WGL_EXT_swap_control_tear + +static void _glewInfo_WGL_EXT_swap_control_tear (void) +{ + glewPrintExt("WGL_EXT_swap_control_tear", WGLEW_EXT_swap_control_tear, wglewIsSupported("WGL_EXT_swap_control_tear"), wglewGetExtension("WGL_EXT_swap_control_tear")); +} + +#endif /* WGL_EXT_swap_control_tear */ + #ifdef WGL_I3D_digital_video_control static void _glewInfo_WGL_I3D_digital_video_control (void) @@ -6421,6 +7617,15 @@ static void _glewInfo_WGL_NV_DX_interop (void) #endif /* WGL_NV_DX_interop */ +#ifdef WGL_NV_DX_interop2 + +static void _glewInfo_WGL_NV_DX_interop2 (void) +{ + glewPrintExt("WGL_NV_DX_interop2", WGLEW_NV_DX_interop2, wglewIsSupported("WGL_NV_DX_interop2"), wglewGetExtension("WGL_NV_DX_interop2")); +} + +#endif /* WGL_NV_DX_interop2 */ + #ifdef WGL_NV_copy_image static void _glewInfo_WGL_NV_copy_image (void) @@ -6634,6 +7839,16 @@ static void _glewInfo_GLX_3DFX_multisample (void) static void _glewInfo_GLX_AMD_gpu_association (void) { glewPrintExt("GLX_AMD_gpu_association", GLXEW_AMD_gpu_association, glxewIsSupported("GLX_AMD_gpu_association"), glxewGetExtension("GLX_AMD_gpu_association")); + + glewInfoFunc("glXBlitContextFramebufferAMD", glXBlitContextFramebufferAMD == NULL); + glewInfoFunc("glXCreateAssociatedContextAMD", glXCreateAssociatedContextAMD == NULL); + glewInfoFunc("glXCreateAssociatedContextAttribsAMD", glXCreateAssociatedContextAttribsAMD == NULL); + glewInfoFunc("glXDeleteAssociatedContextAMD", glXDeleteAssociatedContextAMD == NULL); + glewInfoFunc("glXGetContextGPUIDAMD", glXGetContextGPUIDAMD == NULL); + glewInfoFunc("glXGetCurrentAssociatedContextAMD", glXGetCurrentAssociatedContextAMD == NULL); + glewInfoFunc("glXGetGPUIDsAMD", glXGetGPUIDsAMD == NULL); + glewInfoFunc("glXGetGPUInfoAMD", glXGetGPUInfoAMD == NULL); + glewInfoFunc("glXMakeAssociatedContextCurrentAMD", glXMakeAssociatedContextCurrentAMD == NULL); } #endif /* GLX_AMD_gpu_association */ @@ -6703,6 +7918,24 @@ static void _glewInfo_GLX_ARB_multisample (void) #endif /* GLX_ARB_multisample */ +#ifdef GLX_ARB_robustness_application_isolation + +static void _glewInfo_GLX_ARB_robustness_application_isolation (void) +{ + glewPrintExt("GLX_ARB_robustness_application_isolation", GLXEW_ARB_robustness_application_isolation, glxewIsSupported("GLX_ARB_robustness_application_isolation"), glxewGetExtension("GLX_ARB_robustness_application_isolation")); +} + +#endif /* GLX_ARB_robustness_application_isolation */ + +#ifdef GLX_ARB_robustness_share_group_isolation + +static void _glewInfo_GLX_ARB_robustness_share_group_isolation (void) +{ + glewPrintExt("GLX_ARB_robustness_share_group_isolation", GLXEW_ARB_robustness_share_group_isolation, glxewIsSupported("GLX_ARB_robustness_share_group_isolation"), glxewGetExtension("GLX_ARB_robustness_share_group_isolation")); +} + +#endif /* GLX_ARB_robustness_share_group_isolation */ + #ifdef GLX_ARB_vertex_buffer_object static void _glewInfo_GLX_ARB_vertex_buffer_object (void) @@ -6734,6 +7967,15 @@ static void _glewInfo_GLX_ATI_render_texture (void) #endif /* GLX_ATI_render_texture */ +#ifdef GLX_EXT_buffer_age + +static void _glewInfo_GLX_EXT_buffer_age (void) +{ + glewPrintExt("GLX_EXT_buffer_age", GLXEW_EXT_buffer_age, glxewIsSupported("GLX_EXT_buffer_age"), glxewGetExtension("GLX_EXT_buffer_age")); +} + +#endif /* GLX_EXT_buffer_age */ + #ifdef GLX_EXT_create_context_es2_profile static void _glewInfo_GLX_EXT_create_context_es2_profile (void) @@ -6743,6 +7985,15 @@ static void _glewInfo_GLX_EXT_create_context_es2_profile (void) #endif /* GLX_EXT_create_context_es2_profile */ +#ifdef GLX_EXT_create_context_es_profile + +static void _glewInfo_GLX_EXT_create_context_es_profile (void) +{ + glewPrintExt("GLX_EXT_create_context_es_profile", GLXEW_EXT_create_context_es_profile, glxewIsSupported("GLX_EXT_create_context_es_profile"), glxewGetExtension("GLX_EXT_create_context_es_profile")); +} + +#endif /* GLX_EXT_create_context_es_profile */ + #ifdef GLX_EXT_fbconfig_packed_float static void _glewInfo_GLX_EXT_fbconfig_packed_float (void) @@ -6795,6 +8046,15 @@ static void _glewInfo_GLX_EXT_swap_control (void) #endif /* GLX_EXT_swap_control */ +#ifdef GLX_EXT_swap_control_tear + +static void _glewInfo_GLX_EXT_swap_control_tear (void) +{ + glewPrintExt("GLX_EXT_swap_control_tear", GLXEW_EXT_swap_control_tear, glxewIsSupported("GLX_EXT_swap_control_tear"), glxewGetExtension("GLX_EXT_swap_control_tear")); +} + +#endif /* GLX_EXT_swap_control_tear */ + #ifdef GLX_EXT_texture_from_pixmap static void _glewInfo_GLX_EXT_texture_from_pixmap (void) @@ -6889,6 +8149,18 @@ static void _glewInfo_GLX_MESA_set_3dfx_mode (void) #endif /* GLX_MESA_set_3dfx_mode */ +#ifdef GLX_MESA_swap_control + +static void _glewInfo_GLX_MESA_swap_control (void) +{ + glewPrintExt("GLX_MESA_swap_control", GLXEW_MESA_swap_control, glxewIsSupported("GLX_MESA_swap_control"), glxewGetExtension("GLX_MESA_swap_control")); + + glewInfoFunc("glXGetSwapIntervalMESA", glXGetSwapIntervalMESA == NULL); + glewInfoFunc("glXSwapIntervalMESA", glXSwapIntervalMESA == NULL); +} + +#endif /* GLX_MESA_swap_control */ + #ifdef GLX_NV_copy_image static void _glewInfo_GLX_NV_copy_image (void) @@ -7262,6 +8534,15 @@ static void glewInfo (void) #ifdef GL_VERSION_4_1 _glewInfo_GL_VERSION_4_1(); #endif /* GL_VERSION_4_1 */ +#ifdef GL_VERSION_4_2 + _glewInfo_GL_VERSION_4_2(); +#endif /* GL_VERSION_4_2 */ +#ifdef GL_VERSION_4_3 + _glewInfo_GL_VERSION_4_3(); +#endif /* GL_VERSION_4_3 */ +#ifdef GL_VERSION_4_4 + _glewInfo_GL_VERSION_4_4(); +#endif /* GL_VERSION_4_4 */ #ifdef GL_3DFX_multisample _glewInfo_GL_3DFX_multisample(); #endif /* GL_3DFX_multisample */ @@ -7286,12 +8567,24 @@ static void glewInfo (void) #ifdef GL_AMD_draw_buffers_blend _glewInfo_GL_AMD_draw_buffers_blend(); #endif /* GL_AMD_draw_buffers_blend */ +#ifdef GL_AMD_interleaved_elements + _glewInfo_GL_AMD_interleaved_elements(); +#endif /* GL_AMD_interleaved_elements */ +#ifdef GL_AMD_multi_draw_indirect + _glewInfo_GL_AMD_multi_draw_indirect(); +#endif /* GL_AMD_multi_draw_indirect */ #ifdef GL_AMD_name_gen_delete _glewInfo_GL_AMD_name_gen_delete(); #endif /* GL_AMD_name_gen_delete */ #ifdef GL_AMD_performance_monitor _glewInfo_GL_AMD_performance_monitor(); #endif /* GL_AMD_performance_monitor */ +#ifdef GL_AMD_pinned_memory + _glewInfo_GL_AMD_pinned_memory(); +#endif /* GL_AMD_pinned_memory */ +#ifdef GL_AMD_query_buffer_object + _glewInfo_GL_AMD_query_buffer_object(); +#endif /* GL_AMD_query_buffer_object */ #ifdef GL_AMD_sample_positions _glewInfo_GL_AMD_sample_positions(); #endif /* GL_AMD_sample_positions */ @@ -7301,15 +8594,66 @@ static void glewInfo (void) #ifdef GL_AMD_shader_stencil_export _glewInfo_GL_AMD_shader_stencil_export(); #endif /* GL_AMD_shader_stencil_export */ +#ifdef GL_AMD_shader_trinary_minmax + _glewInfo_GL_AMD_shader_trinary_minmax(); +#endif /* GL_AMD_shader_trinary_minmax */ +#ifdef GL_AMD_sparse_texture + _glewInfo_GL_AMD_sparse_texture(); +#endif /* GL_AMD_sparse_texture */ +#ifdef GL_AMD_stencil_operation_extended + _glewInfo_GL_AMD_stencil_operation_extended(); +#endif /* GL_AMD_stencil_operation_extended */ #ifdef GL_AMD_texture_texture4 _glewInfo_GL_AMD_texture_texture4(); #endif /* GL_AMD_texture_texture4 */ #ifdef GL_AMD_transform_feedback3_lines_triangles _glewInfo_GL_AMD_transform_feedback3_lines_triangles(); #endif /* GL_AMD_transform_feedback3_lines_triangles */ +#ifdef GL_AMD_vertex_shader_layer + _glewInfo_GL_AMD_vertex_shader_layer(); +#endif /* GL_AMD_vertex_shader_layer */ #ifdef GL_AMD_vertex_shader_tessellator _glewInfo_GL_AMD_vertex_shader_tessellator(); #endif /* GL_AMD_vertex_shader_tessellator */ +#ifdef GL_AMD_vertex_shader_viewport_index + _glewInfo_GL_AMD_vertex_shader_viewport_index(); +#endif /* GL_AMD_vertex_shader_viewport_index */ +#ifdef GL_ANGLE_depth_texture + _glewInfo_GL_ANGLE_depth_texture(); +#endif /* GL_ANGLE_depth_texture */ +#ifdef GL_ANGLE_framebuffer_blit + _glewInfo_GL_ANGLE_framebuffer_blit(); +#endif /* GL_ANGLE_framebuffer_blit */ +#ifdef GL_ANGLE_framebuffer_multisample + _glewInfo_GL_ANGLE_framebuffer_multisample(); +#endif /* GL_ANGLE_framebuffer_multisample */ +#ifdef GL_ANGLE_instanced_arrays + _glewInfo_GL_ANGLE_instanced_arrays(); +#endif /* GL_ANGLE_instanced_arrays */ +#ifdef GL_ANGLE_pack_reverse_row_order + _glewInfo_GL_ANGLE_pack_reverse_row_order(); +#endif /* GL_ANGLE_pack_reverse_row_order */ +#ifdef GL_ANGLE_program_binary + _glewInfo_GL_ANGLE_program_binary(); +#endif /* GL_ANGLE_program_binary */ +#ifdef GL_ANGLE_texture_compression_dxt1 + _glewInfo_GL_ANGLE_texture_compression_dxt1(); +#endif /* GL_ANGLE_texture_compression_dxt1 */ +#ifdef GL_ANGLE_texture_compression_dxt3 + _glewInfo_GL_ANGLE_texture_compression_dxt3(); +#endif /* GL_ANGLE_texture_compression_dxt3 */ +#ifdef GL_ANGLE_texture_compression_dxt5 + _glewInfo_GL_ANGLE_texture_compression_dxt5(); +#endif /* GL_ANGLE_texture_compression_dxt5 */ +#ifdef GL_ANGLE_texture_usage + _glewInfo_GL_ANGLE_texture_usage(); +#endif /* GL_ANGLE_texture_usage */ +#ifdef GL_ANGLE_timer_query + _glewInfo_GL_ANGLE_timer_query(); +#endif /* GL_ANGLE_timer_query */ +#ifdef GL_ANGLE_translated_shader_source + _glewInfo_GL_ANGLE_translated_shader_source(); +#endif /* GL_ANGLE_translated_shader_source */ #ifdef GL_APPLE_aux_depth_stencil _glewInfo_GL_APPLE_aux_depth_stencil(); #endif /* GL_APPLE_aux_depth_stencil */ @@ -7364,21 +8708,57 @@ static void glewInfo (void) #ifdef GL_ARB_ES2_compatibility _glewInfo_GL_ARB_ES2_compatibility(); #endif /* GL_ARB_ES2_compatibility */ +#ifdef GL_ARB_ES3_compatibility + _glewInfo_GL_ARB_ES3_compatibility(); +#endif /* GL_ARB_ES3_compatibility */ +#ifdef GL_ARB_arrays_of_arrays + _glewInfo_GL_ARB_arrays_of_arrays(); +#endif /* GL_ARB_arrays_of_arrays */ +#ifdef GL_ARB_base_instance + _glewInfo_GL_ARB_base_instance(); +#endif /* GL_ARB_base_instance */ +#ifdef GL_ARB_bindless_texture + _glewInfo_GL_ARB_bindless_texture(); +#endif /* GL_ARB_bindless_texture */ #ifdef GL_ARB_blend_func_extended _glewInfo_GL_ARB_blend_func_extended(); #endif /* GL_ARB_blend_func_extended */ +#ifdef GL_ARB_buffer_storage + _glewInfo_GL_ARB_buffer_storage(); +#endif /* GL_ARB_buffer_storage */ #ifdef GL_ARB_cl_event _glewInfo_GL_ARB_cl_event(); #endif /* GL_ARB_cl_event */ +#ifdef GL_ARB_clear_buffer_object + _glewInfo_GL_ARB_clear_buffer_object(); +#endif /* GL_ARB_clear_buffer_object */ +#ifdef GL_ARB_clear_texture + _glewInfo_GL_ARB_clear_texture(); +#endif /* GL_ARB_clear_texture */ #ifdef GL_ARB_color_buffer_float _glewInfo_GL_ARB_color_buffer_float(); #endif /* GL_ARB_color_buffer_float */ #ifdef GL_ARB_compatibility _glewInfo_GL_ARB_compatibility(); #endif /* GL_ARB_compatibility */ +#ifdef GL_ARB_compressed_texture_pixel_storage + _glewInfo_GL_ARB_compressed_texture_pixel_storage(); +#endif /* GL_ARB_compressed_texture_pixel_storage */ +#ifdef GL_ARB_compute_shader + _glewInfo_GL_ARB_compute_shader(); +#endif /* GL_ARB_compute_shader */ +#ifdef GL_ARB_compute_variable_group_size + _glewInfo_GL_ARB_compute_variable_group_size(); +#endif /* GL_ARB_compute_variable_group_size */ +#ifdef GL_ARB_conservative_depth + _glewInfo_GL_ARB_conservative_depth(); +#endif /* GL_ARB_conservative_depth */ #ifdef GL_ARB_copy_buffer _glewInfo_GL_ARB_copy_buffer(); #endif /* GL_ARB_copy_buffer */ +#ifdef GL_ARB_copy_image + _glewInfo_GL_ARB_copy_image(); +#endif /* GL_ARB_copy_image */ #ifdef GL_ARB_debug_output _glewInfo_GL_ARB_debug_output(); #endif /* GL_ARB_debug_output */ @@ -7406,12 +8786,21 @@ static void glewInfo (void) #ifdef GL_ARB_draw_instanced _glewInfo_GL_ARB_draw_instanced(); #endif /* GL_ARB_draw_instanced */ +#ifdef GL_ARB_enhanced_layouts + _glewInfo_GL_ARB_enhanced_layouts(); +#endif /* GL_ARB_enhanced_layouts */ #ifdef GL_ARB_explicit_attrib_location _glewInfo_GL_ARB_explicit_attrib_location(); #endif /* GL_ARB_explicit_attrib_location */ +#ifdef GL_ARB_explicit_uniform_location + _glewInfo_GL_ARB_explicit_uniform_location(); +#endif /* GL_ARB_explicit_uniform_location */ #ifdef GL_ARB_fragment_coord_conventions _glewInfo_GL_ARB_fragment_coord_conventions(); #endif /* GL_ARB_fragment_coord_conventions */ +#ifdef GL_ARB_fragment_layer_viewport + _glewInfo_GL_ARB_fragment_layer_viewport(); +#endif /* GL_ARB_fragment_layer_viewport */ #ifdef GL_ARB_fragment_program _glewInfo_GL_ARB_fragment_program(); #endif /* GL_ARB_fragment_program */ @@ -7421,6 +8810,9 @@ static void glewInfo (void) #ifdef GL_ARB_fragment_shader _glewInfo_GL_ARB_fragment_shader(); #endif /* GL_ARB_fragment_shader */ +#ifdef GL_ARB_framebuffer_no_attachments + _glewInfo_GL_ARB_framebuffer_no_attachments(); +#endif /* GL_ARB_framebuffer_no_attachments */ #ifdef GL_ARB_framebuffer_object _glewInfo_GL_ARB_framebuffer_object(); #endif /* GL_ARB_framebuffer_object */ @@ -7448,15 +8840,36 @@ static void glewInfo (void) #ifdef GL_ARB_imaging _glewInfo_GL_ARB_imaging(); #endif /* GL_ARB_imaging */ +#ifdef GL_ARB_indirect_parameters + _glewInfo_GL_ARB_indirect_parameters(); +#endif /* GL_ARB_indirect_parameters */ #ifdef GL_ARB_instanced_arrays _glewInfo_GL_ARB_instanced_arrays(); #endif /* GL_ARB_instanced_arrays */ +#ifdef GL_ARB_internalformat_query + _glewInfo_GL_ARB_internalformat_query(); +#endif /* GL_ARB_internalformat_query */ +#ifdef GL_ARB_internalformat_query2 + _glewInfo_GL_ARB_internalformat_query2(); +#endif /* GL_ARB_internalformat_query2 */ +#ifdef GL_ARB_invalidate_subdata + _glewInfo_GL_ARB_invalidate_subdata(); +#endif /* GL_ARB_invalidate_subdata */ +#ifdef GL_ARB_map_buffer_alignment + _glewInfo_GL_ARB_map_buffer_alignment(); +#endif /* GL_ARB_map_buffer_alignment */ #ifdef GL_ARB_map_buffer_range _glewInfo_GL_ARB_map_buffer_range(); #endif /* GL_ARB_map_buffer_range */ #ifdef GL_ARB_matrix_palette _glewInfo_GL_ARB_matrix_palette(); #endif /* GL_ARB_matrix_palette */ +#ifdef GL_ARB_multi_bind + _glewInfo_GL_ARB_multi_bind(); +#endif /* GL_ARB_multi_bind */ +#ifdef GL_ARB_multi_draw_indirect + _glewInfo_GL_ARB_multi_draw_indirect(); +#endif /* GL_ARB_multi_draw_indirect */ #ifdef GL_ARB_multisample _glewInfo_GL_ARB_multisample(); #endif /* GL_ARB_multisample */ @@ -7478,12 +8891,27 @@ static void glewInfo (void) #ifdef GL_ARB_point_sprite _glewInfo_GL_ARB_point_sprite(); #endif /* GL_ARB_point_sprite */ +#ifdef GL_ARB_program_interface_query + _glewInfo_GL_ARB_program_interface_query(); +#endif /* GL_ARB_program_interface_query */ #ifdef GL_ARB_provoking_vertex _glewInfo_GL_ARB_provoking_vertex(); #endif /* GL_ARB_provoking_vertex */ +#ifdef GL_ARB_query_buffer_object + _glewInfo_GL_ARB_query_buffer_object(); +#endif /* GL_ARB_query_buffer_object */ +#ifdef GL_ARB_robust_buffer_access_behavior + _glewInfo_GL_ARB_robust_buffer_access_behavior(); +#endif /* GL_ARB_robust_buffer_access_behavior */ #ifdef GL_ARB_robustness _glewInfo_GL_ARB_robustness(); #endif /* GL_ARB_robustness */ +#ifdef GL_ARB_robustness_application_isolation + _glewInfo_GL_ARB_robustness_application_isolation(); +#endif /* GL_ARB_robustness_application_isolation */ +#ifdef GL_ARB_robustness_share_group_isolation + _glewInfo_GL_ARB_robustness_share_group_isolation(); +#endif /* GL_ARB_robustness_share_group_isolation */ #ifdef GL_ARB_sample_shading _glewInfo_GL_ARB_sample_shading(); #endif /* GL_ARB_sample_shading */ @@ -7493,12 +8921,30 @@ static void glewInfo (void) #ifdef GL_ARB_seamless_cube_map _glewInfo_GL_ARB_seamless_cube_map(); #endif /* GL_ARB_seamless_cube_map */ +#ifdef GL_ARB_seamless_cubemap_per_texture + _glewInfo_GL_ARB_seamless_cubemap_per_texture(); +#endif /* GL_ARB_seamless_cubemap_per_texture */ #ifdef GL_ARB_separate_shader_objects _glewInfo_GL_ARB_separate_shader_objects(); #endif /* GL_ARB_separate_shader_objects */ +#ifdef GL_ARB_shader_atomic_counters + _glewInfo_GL_ARB_shader_atomic_counters(); +#endif /* GL_ARB_shader_atomic_counters */ #ifdef GL_ARB_shader_bit_encoding _glewInfo_GL_ARB_shader_bit_encoding(); #endif /* GL_ARB_shader_bit_encoding */ +#ifdef GL_ARB_shader_draw_parameters + _glewInfo_GL_ARB_shader_draw_parameters(); +#endif /* GL_ARB_shader_draw_parameters */ +#ifdef GL_ARB_shader_group_vote + _glewInfo_GL_ARB_shader_group_vote(); +#endif /* GL_ARB_shader_group_vote */ +#ifdef GL_ARB_shader_image_load_store + _glewInfo_GL_ARB_shader_image_load_store(); +#endif /* GL_ARB_shader_image_load_store */ +#ifdef GL_ARB_shader_image_size + _glewInfo_GL_ARB_shader_image_size(); +#endif /* GL_ARB_shader_image_size */ #ifdef GL_ARB_shader_objects _glewInfo_GL_ARB_shader_objects(); #endif /* GL_ARB_shader_objects */ @@ -7508,6 +8954,9 @@ static void glewInfo (void) #ifdef GL_ARB_shader_stencil_export _glewInfo_GL_ARB_shader_stencil_export(); #endif /* GL_ARB_shader_stencil_export */ +#ifdef GL_ARB_shader_storage_buffer_object + _glewInfo_GL_ARB_shader_storage_buffer_object(); +#endif /* GL_ARB_shader_storage_buffer_object */ #ifdef GL_ARB_shader_subroutine _glewInfo_GL_ARB_shader_subroutine(); #endif /* GL_ARB_shader_subroutine */ @@ -7517,15 +8966,27 @@ static void glewInfo (void) #ifdef GL_ARB_shading_language_100 _glewInfo_GL_ARB_shading_language_100(); #endif /* GL_ARB_shading_language_100 */ +#ifdef GL_ARB_shading_language_420pack + _glewInfo_GL_ARB_shading_language_420pack(); +#endif /* GL_ARB_shading_language_420pack */ #ifdef GL_ARB_shading_language_include _glewInfo_GL_ARB_shading_language_include(); #endif /* GL_ARB_shading_language_include */ +#ifdef GL_ARB_shading_language_packing + _glewInfo_GL_ARB_shading_language_packing(); +#endif /* GL_ARB_shading_language_packing */ #ifdef GL_ARB_shadow _glewInfo_GL_ARB_shadow(); #endif /* GL_ARB_shadow */ #ifdef GL_ARB_shadow_ambient _glewInfo_GL_ARB_shadow_ambient(); #endif /* GL_ARB_shadow_ambient */ +#ifdef GL_ARB_sparse_texture + _glewInfo_GL_ARB_sparse_texture(); +#endif /* GL_ARB_sparse_texture */ +#ifdef GL_ARB_stencil_texturing + _glewInfo_GL_ARB_stencil_texturing(); +#endif /* GL_ARB_stencil_texturing */ #ifdef GL_ARB_sync _glewInfo_GL_ARB_sync(); #endif /* GL_ARB_sync */ @@ -7541,6 +9002,9 @@ static void glewInfo (void) #ifdef GL_ARB_texture_buffer_object_rgb32 _glewInfo_GL_ARB_texture_buffer_object_rgb32(); #endif /* GL_ARB_texture_buffer_object_rgb32 */ +#ifdef GL_ARB_texture_buffer_range + _glewInfo_GL_ARB_texture_buffer_range(); +#endif /* GL_ARB_texture_buffer_range */ #ifdef GL_ARB_texture_compression _glewInfo_GL_ARB_texture_compression(); #endif /* GL_ARB_texture_compression */ @@ -7574,6 +9038,9 @@ static void glewInfo (void) #ifdef GL_ARB_texture_gather _glewInfo_GL_ARB_texture_gather(); #endif /* GL_ARB_texture_gather */ +#ifdef GL_ARB_texture_mirror_clamp_to_edge + _glewInfo_GL_ARB_texture_mirror_clamp_to_edge(); +#endif /* GL_ARB_texture_mirror_clamp_to_edge */ #ifdef GL_ARB_texture_mirrored_repeat _glewInfo_GL_ARB_texture_mirrored_repeat(); #endif /* GL_ARB_texture_mirrored_repeat */ @@ -7583,6 +9050,9 @@ static void glewInfo (void) #ifdef GL_ARB_texture_non_power_of_two _glewInfo_GL_ARB_texture_non_power_of_two(); #endif /* GL_ARB_texture_non_power_of_two */ +#ifdef GL_ARB_texture_query_levels + _glewInfo_GL_ARB_texture_query_levels(); +#endif /* GL_ARB_texture_query_levels */ #ifdef GL_ARB_texture_query_lod _glewInfo_GL_ARB_texture_query_lod(); #endif /* GL_ARB_texture_query_lod */ @@ -7595,9 +9065,21 @@ static void glewInfo (void) #ifdef GL_ARB_texture_rgb10_a2ui _glewInfo_GL_ARB_texture_rgb10_a2ui(); #endif /* GL_ARB_texture_rgb10_a2ui */ +#ifdef GL_ARB_texture_stencil8 + _glewInfo_GL_ARB_texture_stencil8(); +#endif /* GL_ARB_texture_stencil8 */ +#ifdef GL_ARB_texture_storage + _glewInfo_GL_ARB_texture_storage(); +#endif /* GL_ARB_texture_storage */ +#ifdef GL_ARB_texture_storage_multisample + _glewInfo_GL_ARB_texture_storage_multisample(); +#endif /* GL_ARB_texture_storage_multisample */ #ifdef GL_ARB_texture_swizzle _glewInfo_GL_ARB_texture_swizzle(); #endif /* GL_ARB_texture_swizzle */ +#ifdef GL_ARB_texture_view + _glewInfo_GL_ARB_texture_view(); +#endif /* GL_ARB_texture_view */ #ifdef GL_ARB_timer_query _glewInfo_GL_ARB_timer_query(); #endif /* GL_ARB_timer_query */ @@ -7607,6 +9089,9 @@ static void glewInfo (void) #ifdef GL_ARB_transform_feedback3 _glewInfo_GL_ARB_transform_feedback3(); #endif /* GL_ARB_transform_feedback3 */ +#ifdef GL_ARB_transform_feedback_instanced + _glewInfo_GL_ARB_transform_feedback_instanced(); +#endif /* GL_ARB_transform_feedback_instanced */ #ifdef GL_ARB_transpose_matrix _glewInfo_GL_ARB_transpose_matrix(); #endif /* GL_ARB_transpose_matrix */ @@ -7622,6 +9107,9 @@ static void glewInfo (void) #ifdef GL_ARB_vertex_attrib_64bit _glewInfo_GL_ARB_vertex_attrib_64bit(); #endif /* GL_ARB_vertex_attrib_64bit */ +#ifdef GL_ARB_vertex_attrib_binding + _glewInfo_GL_ARB_vertex_attrib_binding(); +#endif /* GL_ARB_vertex_attrib_binding */ #ifdef GL_ARB_vertex_blend _glewInfo_GL_ARB_vertex_blend(); #endif /* GL_ARB_vertex_blend */ @@ -7634,6 +9122,9 @@ static void glewInfo (void) #ifdef GL_ARB_vertex_shader _glewInfo_GL_ARB_vertex_shader(); #endif /* GL_ARB_vertex_shader */ +#ifdef GL_ARB_vertex_type_10f_11f_11f_rev + _glewInfo_GL_ARB_vertex_type_10f_11f_11f_rev(); +#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */ #ifdef GL_ARB_vertex_type_2_10_10_10_rev _glewInfo_GL_ARB_vertex_type_2_10_10_10_rev(); #endif /* GL_ARB_vertex_type_2_10_10_10_rev */ @@ -7763,6 +9254,9 @@ static void glewInfo (void) #ifdef GL_EXT_cull_vertex _glewInfo_GL_EXT_cull_vertex(); #endif /* GL_EXT_cull_vertex */ +#ifdef GL_EXT_debug_marker + _glewInfo_GL_EXT_debug_marker(); +#endif /* GL_EXT_debug_marker */ #ifdef GL_EXT_depth_bounds_test _glewInfo_GL_EXT_depth_bounds_test(); #endif /* GL_EXT_depth_bounds_test */ @@ -7790,6 +9284,9 @@ static void glewInfo (void) #ifdef GL_EXT_framebuffer_multisample _glewInfo_GL_EXT_framebuffer_multisample(); #endif /* GL_EXT_framebuffer_multisample */ +#ifdef GL_EXT_framebuffer_multisample_blit_scaled + _glewInfo_GL_EXT_framebuffer_multisample_blit_scaled(); +#endif /* GL_EXT_framebuffer_multisample_blit_scaled */ #ifdef GL_EXT_framebuffer_object _glewInfo_GL_EXT_framebuffer_object(); #endif /* GL_EXT_framebuffer_object */ @@ -8042,12 +9539,21 @@ static void glewInfo (void) #ifdef GL_INGR_interlace_read _glewInfo_GL_INGR_interlace_read(); #endif /* GL_INGR_interlace_read */ +#ifdef GL_INTEL_map_texture + _glewInfo_GL_INTEL_map_texture(); +#endif /* GL_INTEL_map_texture */ #ifdef GL_INTEL_parallel_arrays _glewInfo_GL_INTEL_parallel_arrays(); #endif /* GL_INTEL_parallel_arrays */ #ifdef GL_INTEL_texture_scissor _glewInfo_GL_INTEL_texture_scissor(); #endif /* GL_INTEL_texture_scissor */ +#ifdef GL_KHR_debug + _glewInfo_GL_KHR_debug(); +#endif /* GL_KHR_debug */ +#ifdef GL_KHR_texture_compression_astc_ldr + _glewInfo_GL_KHR_texture_compression_astc_ldr(); +#endif /* GL_KHR_texture_compression_astc_ldr */ #ifdef GL_KTX_buffer_region _glewInfo_GL_KTX_buffer_region(); #endif /* GL_KTX_buffer_region */ @@ -8066,12 +9572,30 @@ static void glewInfo (void) #ifdef GL_MESA_ycbcr_texture _glewInfo_GL_MESA_ycbcr_texture(); #endif /* GL_MESA_ycbcr_texture */ +#ifdef GL_NVX_conditional_render + _glewInfo_GL_NVX_conditional_render(); +#endif /* GL_NVX_conditional_render */ #ifdef GL_NVX_gpu_memory_info _glewInfo_GL_NVX_gpu_memory_info(); #endif /* GL_NVX_gpu_memory_info */ +#ifdef GL_NV_bindless_multi_draw_indirect + _glewInfo_GL_NV_bindless_multi_draw_indirect(); +#endif /* GL_NV_bindless_multi_draw_indirect */ +#ifdef GL_NV_bindless_texture + _glewInfo_GL_NV_bindless_texture(); +#endif /* GL_NV_bindless_texture */ +#ifdef GL_NV_blend_equation_advanced + _glewInfo_GL_NV_blend_equation_advanced(); +#endif /* GL_NV_blend_equation_advanced */ +#ifdef GL_NV_blend_equation_advanced_coherent + _glewInfo_GL_NV_blend_equation_advanced_coherent(); +#endif /* GL_NV_blend_equation_advanced_coherent */ #ifdef GL_NV_blend_square _glewInfo_GL_NV_blend_square(); #endif /* GL_NV_blend_square */ +#ifdef GL_NV_compute_program5 + _glewInfo_GL_NV_compute_program5(); +#endif /* GL_NV_compute_program5 */ #ifdef GL_NV_conditional_render _glewInfo_GL_NV_conditional_render(); #endif /* GL_NV_conditional_render */ @@ -8081,6 +9605,9 @@ static void glewInfo (void) #ifdef GL_NV_copy_image _glewInfo_GL_NV_copy_image(); #endif /* GL_NV_copy_image */ +#ifdef GL_NV_deep_texture3D + _glewInfo_GL_NV_deep_texture3D(); +#endif /* GL_NV_deep_texture3D */ #ifdef GL_NV_depth_buffer_float _glewInfo_GL_NV_depth_buffer_float(); #endif /* GL_NV_depth_buffer_float */ @@ -8090,6 +9617,9 @@ static void glewInfo (void) #ifdef GL_NV_depth_range_unclamped _glewInfo_GL_NV_depth_range_unclamped(); #endif /* GL_NV_depth_range_unclamped */ +#ifdef GL_NV_draw_texture + _glewInfo_GL_NV_draw_texture(); +#endif /* GL_NV_draw_texture */ #ifdef GL_NV_evaluators _glewInfo_GL_NV_evaluators(); #endif /* GL_NV_evaluators */ @@ -8132,6 +9662,9 @@ static void glewInfo (void) #ifdef GL_NV_gpu_program5 _glewInfo_GL_NV_gpu_program5(); #endif /* GL_NV_gpu_program5 */ +#ifdef GL_NV_gpu_program5_mem_extended + _glewInfo_GL_NV_gpu_program5_mem_extended(); +#endif /* GL_NV_gpu_program5_mem_extended */ #ifdef GL_NV_gpu_program_fp64 _glewInfo_GL_NV_gpu_program_fp64(); #endif /* GL_NV_gpu_program_fp64 */ @@ -8162,6 +9695,9 @@ static void glewInfo (void) #ifdef GL_NV_parameter_buffer_object2 _glewInfo_GL_NV_parameter_buffer_object2(); #endif /* GL_NV_parameter_buffer_object2 */ +#ifdef GL_NV_path_rendering + _glewInfo_GL_NV_path_rendering(); +#endif /* GL_NV_path_rendering */ #ifdef GL_NV_pixel_data_range _glewInfo_GL_NV_pixel_data_range(); #endif /* GL_NV_pixel_data_range */ @@ -8180,9 +9716,18 @@ static void glewInfo (void) #ifdef GL_NV_register_combiners2 _glewInfo_GL_NV_register_combiners2(); #endif /* GL_NV_register_combiners2 */ +#ifdef GL_NV_shader_atomic_counters + _glewInfo_GL_NV_shader_atomic_counters(); +#endif /* GL_NV_shader_atomic_counters */ +#ifdef GL_NV_shader_atomic_float + _glewInfo_GL_NV_shader_atomic_float(); +#endif /* GL_NV_shader_atomic_float */ #ifdef GL_NV_shader_buffer_load _glewInfo_GL_NV_shader_buffer_load(); #endif /* GL_NV_shader_buffer_load */ +#ifdef GL_NV_shader_storage_buffer_object + _glewInfo_GL_NV_shader_storage_buffer_object(); +#endif /* GL_NV_shader_storage_buffer_object */ #ifdef GL_NV_tessellation_program5 _glewInfo_GL_NV_tessellation_program5(); #endif /* GL_NV_tessellation_program5 */ @@ -8288,6 +9833,24 @@ static void glewInfo (void) #ifdef GL_PGI_vertex_hints _glewInfo_GL_PGI_vertex_hints(); #endif /* GL_PGI_vertex_hints */ +#ifdef GL_REGAL_ES1_0_compatibility + _glewInfo_GL_REGAL_ES1_0_compatibility(); +#endif /* GL_REGAL_ES1_0_compatibility */ +#ifdef GL_REGAL_ES1_1_compatibility + _glewInfo_GL_REGAL_ES1_1_compatibility(); +#endif /* GL_REGAL_ES1_1_compatibility */ +#ifdef GL_REGAL_enable + _glewInfo_GL_REGAL_enable(); +#endif /* GL_REGAL_enable */ +#ifdef GL_REGAL_error_string + _glewInfo_GL_REGAL_error_string(); +#endif /* GL_REGAL_error_string */ +#ifdef GL_REGAL_extension_query + _glewInfo_GL_REGAL_extension_query(); +#endif /* GL_REGAL_extension_query */ +#ifdef GL_REGAL_log + _glewInfo_GL_REGAL_log(); +#endif /* GL_REGAL_log */ #ifdef GL_REND_screen_coordinates _glewInfo_GL_REND_screen_coordinates(); #endif /* GL_REND_screen_coordinates */ @@ -8527,6 +10090,12 @@ static void wglewInfo () #ifdef WGL_ARB_render_texture _glewInfo_WGL_ARB_render_texture(); #endif /* WGL_ARB_render_texture */ +#ifdef WGL_ARB_robustness_application_isolation + _glewInfo_WGL_ARB_robustness_application_isolation(); +#endif /* WGL_ARB_robustness_application_isolation */ +#ifdef WGL_ARB_robustness_share_group_isolation + _glewInfo_WGL_ARB_robustness_share_group_isolation(); +#endif /* WGL_ARB_robustness_share_group_isolation */ #ifdef WGL_ATI_pixel_format_float _glewInfo_WGL_ATI_pixel_format_float(); #endif /* WGL_ATI_pixel_format_float */ @@ -8536,6 +10105,9 @@ static void wglewInfo () #ifdef WGL_EXT_create_context_es2_profile _glewInfo_WGL_EXT_create_context_es2_profile(); #endif /* WGL_EXT_create_context_es2_profile */ +#ifdef WGL_EXT_create_context_es_profile + _glewInfo_WGL_EXT_create_context_es_profile(); +#endif /* WGL_EXT_create_context_es_profile */ #ifdef WGL_EXT_depth_float _glewInfo_WGL_EXT_depth_float(); #endif /* WGL_EXT_depth_float */ @@ -8566,6 +10138,9 @@ static void wglewInfo () #ifdef WGL_EXT_swap_control _glewInfo_WGL_EXT_swap_control(); #endif /* WGL_EXT_swap_control */ +#ifdef WGL_EXT_swap_control_tear + _glewInfo_WGL_EXT_swap_control_tear(); +#endif /* WGL_EXT_swap_control_tear */ #ifdef WGL_I3D_digital_video_control _glewInfo_WGL_I3D_digital_video_control(); #endif /* WGL_I3D_digital_video_control */ @@ -8587,6 +10162,9 @@ static void wglewInfo () #ifdef WGL_NV_DX_interop _glewInfo_WGL_NV_DX_interop(); #endif /* WGL_NV_DX_interop */ +#ifdef WGL_NV_DX_interop2 + _glewInfo_WGL_NV_DX_interop2(); +#endif /* WGL_NV_DX_interop2 */ #ifdef WGL_NV_copy_image _glewInfo_WGL_NV_copy_image(); #endif /* WGL_NV_copy_image */ @@ -8665,6 +10243,12 @@ static void glxewInfo () #ifdef GLX_ARB_multisample _glewInfo_GLX_ARB_multisample(); #endif /* GLX_ARB_multisample */ +#ifdef GLX_ARB_robustness_application_isolation + _glewInfo_GLX_ARB_robustness_application_isolation(); +#endif /* GLX_ARB_robustness_application_isolation */ +#ifdef GLX_ARB_robustness_share_group_isolation + _glewInfo_GLX_ARB_robustness_share_group_isolation(); +#endif /* GLX_ARB_robustness_share_group_isolation */ #ifdef GLX_ARB_vertex_buffer_object _glewInfo_GLX_ARB_vertex_buffer_object(); #endif /* GLX_ARB_vertex_buffer_object */ @@ -8674,9 +10258,15 @@ static void glxewInfo () #ifdef GLX_ATI_render_texture _glewInfo_GLX_ATI_render_texture(); #endif /* GLX_ATI_render_texture */ +#ifdef GLX_EXT_buffer_age + _glewInfo_GLX_EXT_buffer_age(); +#endif /* GLX_EXT_buffer_age */ #ifdef GLX_EXT_create_context_es2_profile _glewInfo_GLX_EXT_create_context_es2_profile(); #endif /* GLX_EXT_create_context_es2_profile */ +#ifdef GLX_EXT_create_context_es_profile + _glewInfo_GLX_EXT_create_context_es_profile(); +#endif /* GLX_EXT_create_context_es_profile */ #ifdef GLX_EXT_fbconfig_packed_float _glewInfo_GLX_EXT_fbconfig_packed_float(); #endif /* GLX_EXT_fbconfig_packed_float */ @@ -8692,6 +10282,9 @@ static void glxewInfo () #ifdef GLX_EXT_swap_control _glewInfo_GLX_EXT_swap_control(); #endif /* GLX_EXT_swap_control */ +#ifdef GLX_EXT_swap_control_tear + _glewInfo_GLX_EXT_swap_control_tear(); +#endif /* GLX_EXT_swap_control_tear */ #ifdef GLX_EXT_texture_from_pixmap _glewInfo_GLX_EXT_texture_from_pixmap(); #endif /* GLX_EXT_texture_from_pixmap */ @@ -8719,6 +10312,9 @@ static void glxewInfo () #ifdef GLX_MESA_set_3dfx_mode _glewInfo_GLX_MESA_set_3dfx_mode(); #endif /* GLX_MESA_set_3dfx_mode */ +#ifdef GLX_MESA_swap_control + _glewInfo_GLX_MESA_swap_control(); +#endif /* GLX_MESA_swap_control */ #ifdef GLX_NV_copy_image _glewInfo_GLX_NV_copy_image(); #endif /* GLX_NV_copy_image */ @@ -9002,6 +10598,10 @@ GLboolean glewCreateContext () /*aglSetDrawable(ctx, GetWindowPort(wnd));*/ octx = aglGetCurrentContext(); if (GL_FALSE == aglSetCurrentContext(ctx)) return GL_TRUE; + /* Needed for Regal on the Mac */ + #if defined(GLEW_REGAL) && defined(__APPLE__) + RegalMakeCurrent(octx); + #endif return GL_FALSE; } diff --git a/ext/glew/visualinfo.c b/ext/glew/visualinfo.c index 52839c5d2a..b8bb59ef60 100644 --- a/ext/glew/visualinfo.c +++ b/ext/glew/visualinfo.c @@ -353,6 +353,8 @@ VisualInfoARB (GLContext* ctx) else if (WGLEW_ATI_pixel_format_float && value[7] == WGL_TYPE_RGBA_FLOAT_ATI) fprintf(file, " f "); else if (value[7] == WGL_TYPE_RGBA_ARB) fprintf(file, " i "); else if (value[7] == WGL_TYPE_COLORINDEX_ARB) fprintf(file, " c "); + else if (value[7] == WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT) fprintf(file," p "); + else fprintf(file," ? "); /* double buffer */ fprintf(file, " %c ", value[5] ? 'y' : '.'); /* swap method */ From cf8ee8722367fceea64d5766395ccbed3e68bba7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 8 Oct 2013 21:49:37 +0200 Subject: [PATCH 0720/1445] Enable GLES3 on desktop where supported now that glew has been upgraded --- gfx/gl_common.h | 6 ++++++ gfx_es2/gl_state.cpp | 28 +++++++++++++++++++++++++++- gfx_es2/gl_state.h | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 0576ca4fe5..cc52df5996 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -5,6 +5,9 @@ #if defined(IOS) #include #include + +// I guess we can soon add ES 3.0 here too + #else // Support OpenGL ES 3.0 @@ -21,6 +24,9 @@ #endif #else // OpenGL +// Now that glew is upgraded beyond 4.3, we can define MAY_HAVE_GLES3 on all platforms +// that include glew. +#define MAY_HAVE_GLES3 #include #if defined(__APPLE__) #include diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 2fb4b8d49f..e31ab85a59 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -99,8 +99,26 @@ void CheckGLExtensions() { memset(&gl_extensions, 0, sizeof(gl_extensions)); const char *renderer = (const char *)glGetString(GL_RENDERER); + const char *versionStr = (const char *)glGetString(GL_VERSION); -#if defined(USING_GLES2) && defined(MAY_HAVE_GLES3) + char buffer[64]; + strcpy(buffer, versionStr); + const char *lastNumStart = buffer; + int numVer = 0; + int len = (int)strlen(buffer); + for (int i = 0; i < len && numVer < 3; i++) { + if (buffer[i] == '.') { + buffer[i] = 0; + gl_extensions.ver[numVer++] = atoi(lastNumStart); + i++; + lastNumStart = buffer + i; + } + } + if (numVer < 3) + gl_extensions.ver[numVer++] = atoi(lastNumStart); + +#if defined(USING_GLES2) +#if defined(MAY_HAVE_GLES3) // Try to load GLES 3.0 if (GL_TRUE == gl3stubInit()) { gl_extensions.GLES3 = true; @@ -111,6 +129,14 @@ void CheckGLExtensions() { } } #endif +#else + // If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable + // modern paths. + // Most of it could be enabled on lower GPUs as well, but let's start this way. + if ((gl_extensions.ver[0] == 4 && gl_extensions.ver[1] >= 3) || gl_extensions.ver[0] > 4) { + gl_extensions.GLES3 = true; + } +#endif const char *extString = (const char *)glGetString(GL_EXTENSIONS); if (extString) { diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 6d35b5931d..a2e974cabe 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -314,6 +314,7 @@ extern OpenGLState glstate; // WARNING: This gets memset-d - so no strings please struct GLExtensions { + int ver[3]; bool GLES3; // true if the full OpenGL ES 3.0 is supported bool OES_depth24; bool OES_packed_depth_stencil; From a9544d76dc26d31db2d7c4d785db3776e5d527bd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 8 Oct 2013 23:06:30 +0200 Subject: [PATCH 0721/1445] Android buildfix --- gfx_es2/gl_state.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index e31ab85a59..aa98d6858b 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -1,3 +1,5 @@ +#include + #include "base/logging.h" #include "gl_state.h" @@ -109,13 +111,13 @@ void CheckGLExtensions() { for (int i = 0; i < len && numVer < 3; i++) { if (buffer[i] == '.') { buffer[i] = 0; - gl_extensions.ver[numVer++] = atoi(lastNumStart); + gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); i++; lastNumStart = buffer + i; } } if (numVer < 3) - gl_extensions.ver[numVer++] = atoi(lastNumStart); + gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); #if defined(USING_GLES2) #if defined(MAY_HAVE_GLES3) From 3263ebcc4c43c49454705e2a488615f583dae61a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 8 Oct 2013 23:13:22 +0200 Subject: [PATCH 0722/1445] Fix gl version parsing (sort of) --- gfx_es2/gl_state.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index aa98d6858b..893cf296e8 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -101,10 +101,15 @@ void CheckGLExtensions() { memset(&gl_extensions, 0, sizeof(gl_extensions)); const char *renderer = (const char *)glGetString(GL_RENDERER); + +#ifndef USING_GLES2 const char *versionStr = (const char *)glGetString(GL_VERSION); - char buffer[64]; - strcpy(buffer, versionStr); + char buffer[64] = {0}; + if (versionStr) { + ILOG("GL version str: %s", versionStr); + strncpy(buffer, versionStr, 64); + } const char *lastNumStart = buffer; int numVer = 0; int len = (int)strlen(buffer); @@ -118,11 +123,15 @@ void CheckGLExtensions() { } if (numVer < 3) gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); +#else + gl_extensions.ver[0] = 2; +#endif #if defined(USING_GLES2) #if defined(MAY_HAVE_GLES3) // Try to load GLES 3.0 if (GL_TRUE == gl3stubInit()) { + gl_extensions.ver[0] = 3; gl_extensions.GLES3 = true; ILOG("Full OpenGL ES 3.0 support detected!\n"); // Though, let's ban Mali from the GLES 3 path for now, see #4078 From 0f68de275c54d504ca912ed5678582f8f1d0bb27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 9 Oct 2013 00:44:45 +0200 Subject: [PATCH 0723/1445] Minor fixes --- ext/glew/GL/glew.h | 2 ++ gfx_es2/gl_state.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ext/glew/GL/glew.h b/ext/glew/GL/glew.h index d4151518e3..a4ef6981dd 100644 --- a/ext/glew/GL/glew.h +++ b/ext/glew/GL/glew.h @@ -76,7 +76,9 @@ ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ +#ifndef GLEW_STATIC #define GLEW_STATIC +#endif #ifndef __glew_h__ #define __glew_h__ diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 893cf296e8..149bbbb91f 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -33,11 +33,11 @@ std::string g_all_egl_extensions; int OpenGLState::state_count = 0; void OpenGLState::Initialize() { - if(initialized) return; + if (initialized) + return; + initialized = true; Restore(); - - initialized = true; } void OpenGLState::Restore() { @@ -108,7 +108,7 @@ void CheckGLExtensions() { char buffer[64] = {0}; if (versionStr) { ILOG("GL version str: %s", versionStr); - strncpy(buffer, versionStr, 64); + strncpy(buffer, versionStr, 63); } const char *lastNumStart = buffer; int numVer = 0; From 3061347b41e0bd2860ebf77a27e22701bb19f35c Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 9 Oct 2013 14:15:52 +1000 Subject: [PATCH 0724/1445] Buildfix where GLchar isn't defined (Symbian). --- gfx_es2/gl3stub.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx_es2/gl3stub.h b/gfx_es2/gl3stub.h index a7fe92b353..9d64b62455 100644 --- a/gfx_es2/gl3stub.h +++ b/gfx_es2/gl3stub.h @@ -16,6 +16,9 @@ #if defined(USING_GLES2) #include #include +#ifndef GLchar +typedef char GLchar; +#endif #ifdef __cplusplus extern "C" { From c690d4c0e13dce9829e5d2101492b982b9295f06 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 9 Oct 2013 16:15:34 +1000 Subject: [PATCH 0725/1445] Buildfix for Symbian. Just don't compile GLES3 stuff at all. --- gfx_es2/gl3stub.c | 2 +- gfx_es2/gl3stub.h | 6 +----- gfx_es2/gl_state.cpp | 3 ++- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/gfx_es2/gl3stub.c b/gfx_es2/gl3stub.c index 38af6c902c..c9f7c87b9a 100644 --- a/gfx_es2/gl3stub.c +++ b/gfx_es2/gl3stub.c @@ -16,7 +16,7 @@ #include "gl3stub.h" -#if defined(USING_GLES2) +#if defined(USING_GLES2) && !defined(__SYMBIAN32__) GLboolean gl3stubInit() { #define FIND_PROC(s) s = (void*)eglGetProcAddress(#s) diff --git a/gfx_es2/gl3stub.h b/gfx_es2/gl3stub.h index 9d64b62455..a97a2749e2 100644 --- a/gfx_es2/gl3stub.h +++ b/gfx_es2/gl3stub.h @@ -13,12 +13,8 @@ * - Added gl3stubInit() declaration */ -#if defined(USING_GLES2) +#if defined(USING_GLES2) && !defined(__SYMBIAN32__) #include -#include -#ifndef GLchar -typedef char GLchar; -#endif #ifdef __cplusplus extern "C" { diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 149bbbb91f..23575d5130 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -128,7 +128,8 @@ void CheckGLExtensions() { #endif #if defined(USING_GLES2) -#if defined(MAY_HAVE_GLES3) +// MAY_HAVE_GLES3 defined on all platforms, maybe redundant. Otherwise exclude platforms like Symbian, Meego, Raspberry Pi +#if defined(MAY_HAVE_GLES3) && !defined(__SYMBIAN32__) // Try to load GLES 3.0 if (GL_TRUE == gl3stubInit()) { gl_extensions.ver[0] = 3; From 3778d8d8b1c3cc66470f1575b9959a04812b8f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 9 Oct 2013 15:29:02 +0200 Subject: [PATCH 0726/1445] Android: Reorganize the display resize stuff. Assorted cleanup and fixes. --- android/app-android.cpp | 23 ++--- .../libnative/AudioFocusChangeListener.java | 11 ++- .../libnative/InputDeviceState.java | 1 - .../libnative/NativeActivity.java | 92 ++++++++++--------- .../henrikrydgard/libnative/NativeApp.java | 4 +- .../libnative/NativeAudioPlayer.java | 15 +-- .../henrikrydgard/libnative/NativeGLView.java | 22 ++--- gfx_es2/gl_state.cpp | 10 +- 8 files changed, 90 insertions(+), 88 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 59f10dff0d..84b6d02ec4 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -143,7 +143,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioConfig } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init - (JNIEnv *env, jclass, jint xxres, jint yyres, jint dpi, jstring jdevicetype, jstring jlangRegion, jstring japkpath, + (JNIEnv *env, jclass, jint dpi, jstring jdevicetype, jstring jlangRegion, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; @@ -184,9 +184,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init g_dpi = dpi; g_dpi_scale = 240.0f / (float)g_dpi; - pixel_xres = xxres; - pixel_yres = yyres; - pixel_in_dps = (float)pixel_xres / (float)dp_xres; NativeGetAppInfo(&app_name, &app_nice_name, &landscape); @@ -195,7 +192,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init use_opensl_audio = juseNativeAudio; ILOG("NativeApp.init() -- end"); -} +} extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioInit(JNIEnv *, jclass) { ILOG("NativeApp.audioInit() -- begin"); @@ -230,7 +227,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclas } ILOG("NativeApp.pause() - end"); } - + extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { ILOG("NativeApp.shutdown() -- begin"); NativeShutdown(); @@ -269,21 +266,17 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIE ILOG("MethodID: %i", (int)postCommand); } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_resized - (JNIEnv *env, jclass, jint xxres, jint yyres) { - pixel_xres = xxres; - pixel_yres = yyres; +extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { + ILOG("NativeApp.displayResize(%i, %i)", w, h); + // TODO: Move some of the logic from displayInit here? + pixel_xres = w; + pixel_yres = h; dp_xres = pixel_xres * g_dpi_scale; dp_yres = pixel_yres * g_dpi_scale; dp_xscale = (float)dp_xres / pixel_xres; dp_yscale = (float)dp_yres / pixel_yres; } -extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { - ILOG("NativeApp.displayResize(%i, %i)", w, h); - // TODO: Move some of the logic from displayInit here? -} - extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { // Too spammy // ILOG("NativeApp.displayRender()"); diff --git a/android/src/com/henrikrydgard/libnative/AudioFocusChangeListener.java b/android/src/com/henrikrydgard/libnative/AudioFocusChangeListener.java index c3dbfb7d9f..1415e704ff 100644 --- a/android/src/com/henrikrydgard/libnative/AudioFocusChangeListener.java +++ b/android/src/com/henrikrydgard/libnative/AudioFocusChangeListener.java @@ -3,8 +3,8 @@ import android.media.AudioManager; import android.media.AudioManager.OnAudioFocusChangeListener; public class AudioFocusChangeListener implements OnAudioFocusChangeListener{ - //not used right now, but we may need to use it sometime. So just store it - //for now. + // not used right now, but we may need to use it sometime. So just store it + // for now. private boolean hasAudioFocus = false; @Override @@ -16,10 +16,11 @@ public class AudioFocusChangeListener implements OnAudioFocusChangeListener{ case AudioManager.AUDIOFOCUS_LOSS: hasAudioFocus = false; + break; } - - // TODO Auto-generated method stub - } + public boolean hasAudioFocus() { + return hasAudioFocus; + } } diff --git a/android/src/com/henrikrydgard/libnative/InputDeviceState.java b/android/src/com/henrikrydgard/libnative/InputDeviceState.java index a91e7301a5..5f0adf7e2a 100644 --- a/android/src/com/henrikrydgard/libnative/InputDeviceState.java +++ b/android/src/com/henrikrydgard/libnative/InputDeviceState.java @@ -2,7 +2,6 @@ package com.henrikrydgard.libnative; import android.annotation.TargetApi; import android.os.Build; -import android.util.SparseIntArray; import android.view.InputDevice; import android.view.InputDevice.MotionRange; import android.view.KeyEvent; diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 4f608ff7b8..b6e6379df0 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -17,7 +17,6 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; import android.content.pm.PackageManager; @@ -26,7 +25,6 @@ import android.content.res.Configuration; import android.graphics.Point; import android.media.AudioManager; import android.net.Uri; -import android.opengl.GLSurfaceView; import android.os.Build; import android.os.Bundle; import android.os.Environment; @@ -41,6 +39,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.Toast; @@ -79,7 +78,6 @@ class Installation { out.close(); } } - public class NativeActivity extends Activity { // Remember to loadLibrary your JNI .so in a static {} block @@ -87,7 +85,6 @@ public class NativeActivity extends Activity { // Adjust these as necessary private static String TAG = "NativeActivity"; - // Allows us to skip a lot of initialization on secondary calls to onCreate. private static boolean initialized = false; @@ -102,14 +99,23 @@ public class NativeActivity extends Activity { public static String commandParameter; public static String installID; - // Settings for best audio latency + // Remember settings for best audio latency private int optimalFramesPerBuffer; private int optimalSampleRate; - //audioFocusChangeListener to listen to changes in audio state + // audioFocusChangeListener to listen to changes in audio state private AudioFocusChangeListener audioFocusChangeListener; private AudioManager audioManager; - + + public static boolean inputBoxCancelled; + + // Allow for two connected gamepads but just consider them the same for now. + // Actually this is not entirely true, see the code. + InputDeviceState inputPlayerA; + InputDeviceState inputPlayerB; + String inputPlayerADesc; + + @TargetApi(17) private void detectOptimalAudioSettings() { try { @@ -143,7 +149,7 @@ public class NativeActivity extends Activity { WindowManager w = getWindowManager(); w.getDefaultDisplay().getSize(size); } - + void GetScreenSize(Point size) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { GetScreenSizeHC(size); @@ -194,6 +200,7 @@ public class NativeActivity extends Activity { @SuppressWarnings("deprecation") int scrPixelFormat = display.getPixelFormat(); Point size = new Point(); + GetScreenSize(size); int scrWidth = size.x; int scrHeight = size.y; @@ -212,16 +219,21 @@ public class NativeActivity extends Activity { // INIT! NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(scrWidth, scrHeight, dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); + NativeApp.init(dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); Log.i(TAG, "Device: " + deviceType); Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat + " dpi: " + dpi); - - // Initialize Graphics - + + // Detect OpenGL support. + // We don't currently use this detection for anything but good to have in the log. if (!detectOpenGLES20()) { - Log.i(TAG, "OpenGL ES 2.0 NOT detected."); + Log.i(TAG, "OpenGL ES 2.0 NOT detected. Things will likely go badly."); } else { - Log.i(TAG, "OpenGL ES 2.0 detected."); + if (detectOpenGLES30()) { + Log.i(TAG, "OpenGL ES 3.0 detected."); + } + else { + Log.i(TAG, "OpenGL ES 2.0 detected."); + } } @@ -232,8 +244,6 @@ public class NativeActivity extends Activity { addContentView(editText, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); */ // inputBox("Please ener a s", "", "Save"); - // Toast.makeText(this, "Value: " + input.getText().toString(), Toast.LENGTH_LONG).show(); - } @Override @@ -250,27 +260,26 @@ public class NativeActivity extends Activity { window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setVolumeControlStream(AudioManager.STREAM_MUSIC); - - //intialize audio and tell PPSSPP to gain audio focus - if (!useOpenSL){ + // Initialize audio and tell PPSSPP to gain audio focus + if (!useOpenSL) { audioPlayer = new NativeAudioPlayer(); } NativeAudioPlayer.gainAudioFocus(this.audioManager, this.audioFocusChangeListener); NativeApp.audioInit(); - Point size = new Point(); - GetScreenSize(size); - NativeApp.resized(size.x, size.y); - mGLSurfaceView = new NativeGLView(this); - //setup the GLSurface and ask android for the correct - //number of bits for r, g, b, a, depth and stencil components + + // Setup the GLSurface and ask android for the correct + // Number of bits for r, g, b, a, depth and stencil components + // The PSP only has 16-bit Z so that should be enough. + // Might want to change this for other apps (24-bit might be useful). + // Actually, we might be able to do without both stencil and depth in + // the back buffer, but that would kill non-buffered rendering. mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8); nativeRenderer = new NativeRenderer(this); mGLSurfaceView.setRenderer(nativeRenderer); setContentView(mGLSurfaceView); - if (Build.VERSION.SDK_INT >= 14) { darkenOnScreenButtons(); } @@ -279,21 +288,21 @@ public class NativeActivity extends Activity { @Override protected void onStop() { super.onStop(); - Log.i(TAG, "onStop - do nothing, just let's switch away"); + Log.i(TAG, "onStop - do nothing, just let Android switch away"); } @Override protected void onDestroy() { super.onDestroy(); + Log.e(TAG, "onDestroy"); mGLSurfaceView.onDestroy(); nativeRenderer.onDestroyed(); - Log.e(TAG, "onDestroy"); NativeApp.audioShutdown(); + // Probably vain attempt to help the garbage collector... audioPlayer = null; mGLSurfaceView = null; audioFocusChangeListener = null; audioManager = null; - } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @@ -306,12 +315,17 @@ public class NativeActivity extends Activity { ConfigurationInfo info = am.getDeviceConfigurationInfo(); return info.reqGlEsVersion >= 0x20000; } + + private boolean detectOpenGLES30() { + ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); + ConfigurationInfo info = am.getDeviceConfigurationInfo(); + return info.reqGlEsVersion >= 0x30000; + } @Override protected void onPause() { super.onPause(); Log.i(TAG, "onPause"); - NativeAudioPlayer.loseAudioFocus(this.audioManager, this.audioFocusChangeListener); if (audioPlayer != null) { audioPlayer.stop(); @@ -353,15 +367,7 @@ public class NativeActivity extends Activity { public void onConfigurationChanged(Configuration newConfig) { // Ignore orientation change super.onConfigurationChanged(newConfig); - } - - public static boolean inputBoxCancelled; - - - // Allow for two connected joysticks but just consider them the same for now. - InputDeviceState inputPlayerA; - InputDeviceState inputPlayerB; - String inputPlayerADesc; + } // We simply grab the first input device to produce an event and ignore all others that are connected. @TargetApi(Build.VERSION_CODES.GINGERBREAD) @@ -603,8 +609,12 @@ public class NativeActivity extends Activity { Toast toast = Toast.makeText(this, params, Toast.LENGTH_SHORT); toast.show(); } else if (command.equals("showKeyboard")) { - //InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); - //inputMethodManager.toggleSoftInputFromWindow(this, InputMethodManager.SHOW_FORCED, 0); + InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + // No idea what the point of the ApplicationWindowToken is or if it matters where we get it from... + inputMethodManager.toggleSoftInputFromWindow(mGLSurfaceView.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0); + } else if (command.equals("hideKeyboard")) { + InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.toggleSoftInputFromWindow(mGLSurfaceView.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0); } else if (command.equals("inputBox")) { inputBox(params, "", "OK"); } else { diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 79f1f1725b..9d97f339fe 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -6,9 +6,7 @@ public class NativeApp { public final static int DEVICE_ID_MOUSE = 2; public final static int DEVICE_ID_PAD_0 = 10; - public static native void init(int xxres, int yyres, int dpi, String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); - public static native void resized(int xxres, int yyres); - + public static native void init(int dpi, String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); public static native void audioInit(); public static native void audioShutdown(); diff --git a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java index 34e7b94cdc..41ee69307e 100644 --- a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java +++ b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java @@ -2,7 +2,6 @@ package com.henrikrydgard.libnative; import android.media.AudioFormat; import android.media.AudioManager; -import android.media.AudioManager.OnAudioFocusChangeListener; import android.media.AudioTrack; import android.util.Log; import com.henrikrydgard.libnative.AudioFocusChangeListener; @@ -12,8 +11,6 @@ public class NativeAudioPlayer { private Thread thread; private boolean playing_; - - // Calling stop() is allowed at any time, whether stopped or not. // If playing, blocks until not. public synchronized void stop() { @@ -36,15 +33,19 @@ public class NativeAudioPlayer { //keep this static so we can call this even if we don't //instantiate NativeAudioPlayer - public static void gainAudioFocus(AudioManager audioManager,AudioFocusChangeListener focusChangeListener) { - audioManager.requestAudioFocus(focusChangeListener, - AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); + public static void gainAudioFocus(AudioManager audioManager, AudioFocusChangeListener focusChangeListener) { + if (audioManager != null) { + audioManager.requestAudioFocus(focusChangeListener, + AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); + } } //keep this static so we can call this even if we don't //instantiate NativeAudioPlayer public static void loseAudioFocus(AudioManager audioManager,AudioFocusChangeListener focusChangeListener){ - audioManager.abandonAudioFocus(focusChangeListener); + if (audioManager != null) { + audioManager.abandonAudioFocus(focusChangeListener); + } } diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 9430e3d34d..9da7086a1e 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -3,7 +3,6 @@ package com.henrikrydgard.libnative; // Touch- and sensor-enabled GLSurfaceView. // Supports simple multitouch and pressure. - import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEvent; @@ -47,8 +46,6 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, } }*/ - // setEGLConfigChooser(5, 5, 5, 0, 16, 0); - // setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); mSensorManager = (SensorManager)activity.getSystemService(Activity.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); @@ -57,7 +54,8 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, if (mController.init()) { Log.i(TAG, "MOGA initialized"); mController.setListener(this, new Handler()); - if (mController.getState(mController.STATE_CURRENT_PRODUCT_VERSION) == mController.ACTION_VERSION_MOGAPRO) { + if (mController.getState(Controller.STATE_CURRENT_PRODUCT_VERSION) == Controller.ACTION_VERSION_MOGAPRO) { + Log.i(TAG, "MOGA pro detected"); isMogaPro = true; } } else { @@ -65,8 +63,6 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, } } - // This needs fleshing out. A lot. - // Going to want multitouch eventually. public boolean onTouchEvent(final MotionEvent ev) { for (int i = 0; i < ev.getPointerCount(); i++) { int pid = ev.getPointerId(i); @@ -91,8 +87,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, default: break; } - if (code != 0) - { + if (code != 0) { float x = ev.getX(i); float y = ev.getY(i); NativeApp.touch(x, y, code, pid); @@ -103,7 +98,6 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, // Sensor management public void onAccuracyChanged(Sensor sensor, int arg1) { - // Log.i(TAG, "onAccuracyChanged"); } public void onSensorChanged(SensorEvent event) { @@ -159,9 +153,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, break; } } - //Log.i(TAG, "Moga KeyEvent " + event.getKeyCode()); - - // TODO Auto-generated method stub + switch (event.getAction()) { case KeyEvent.ACTION_DOWN: NativeApp.keyDown(NativeApp.DEVICE_ID_PAD_0, event.getKeyCode()); @@ -175,8 +167,6 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, // MOGA Controller - from ControllerListener @Override public void onMotionEvent(com.bda.controller.MotionEvent event) { - //Log.i(TAG, "Moga MotionEvent"); - // TODO Auto-generated method stub NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_X, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_X)); NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_Y, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_Y)); NativeApp.joystickAxis(NativeApp.DEVICE_ID_PAD_0, com.bda.controller.MotionEvent.AXIS_Z, event.getAxisValue(com.bda.controller.MotionEvent.AXIS_Z)); @@ -198,10 +188,11 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, Log.i(TAG, "Moga Connecting..."); break; case StateEvent.ACTION_DISCONNECTED: - Log.i(TAG, "Moga Disonnected"); + Log.i(TAG, "Moga Disconnected (or simply Not connected)"); break; } break; + case StateEvent.STATE_POWER_LOW: switch (state.getAction()) { case StateEvent.ACTION_TRUE: @@ -211,6 +202,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, Log.i(TAG, "Moga Power OK"); break; } + break; default: break; diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 23575d5130..2b89fc5ffb 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -185,12 +185,19 @@ void CheckGLExtensions() { gl_extensions.OES_vertex_array_object = false; gl_extensions.EXT_discard_framebuffer = false; #else + // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. + // https://twitter.com/ID_AA_Carmack/status/387383037794603008 + void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1"); + void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2"); + ILOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2); if (gl_extensions.NV_draw_texture) { glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)eglGetProcAddress("glDrawTextureNV"); } + if (gl_extensions.NV_copy_image) { glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV"); } + gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0; if (gl_extensions.OES_vertex_array_object) { glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" ); @@ -214,6 +221,7 @@ void CheckGLExtensions() { if (gl_extensions.OES_mapbuffer) { glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" ); } + gl_extensions.QCOM_binning_control = strstr(extString, "GL_QCOM_binning_control") != 0; gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0; // Load extensions that are not auto-loaded by Android. @@ -259,7 +267,7 @@ void CheckGLExtensions() { void OpenGLState::SetVSyncInterval(int interval) { #ifdef _WIN32 - if( wglSwapIntervalEXT ) + if (wglSwapIntervalEXT) wglSwapIntervalEXT(interval); #endif } From 67bea6c7ed9eba715d42164944c70ba5a2838223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 9 Oct 2013 16:08:02 +0200 Subject: [PATCH 0727/1445] Run gl_lost() on gl shutdown --- android/app-android.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/android/app-android.cpp b/android/app-android.cpp index 84b6d02ec4..d754850f1a 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -324,6 +324,9 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayShutdown(JNIEnv *env, jobject obj) { if (renderer_inited) { + ILOG("Calling NativeDeviceLost();"); + NativeDeviceLost(); + ILOG("NativeDeviceLost completed.;"); NativeShutdownGraphics(); renderer_inited = false; } From c18d1bcc6d8690145211fd4f65260930d28d44e6 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 10 Oct 2013 01:31:55 +1000 Subject: [PATCH 0728/1445] Still expects gl2 header from gl3stub. --- gfx_es2/gl3stub.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl3stub.h b/gfx_es2/gl3stub.h index a97a2749e2..2d2aa682ca 100644 --- a/gfx_es2/gl3stub.h +++ b/gfx_es2/gl3stub.h @@ -13,8 +13,9 @@ * - Added gl3stubInit() declaration */ -#if defined(USING_GLES2) && !defined(__SYMBIAN32__) +#if defined(USING_GLES2) #include +#if !defined(__SYMBIAN32__) #ifdef __cplusplus extern "C" { @@ -489,6 +490,7 @@ extern GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum t } #endif +#endif // !__SYMBIAN32__ #endif // USING_GLES2 #endif From 615e01b2af46628c090f9544f6558eab7ad41087 Mon Sep 17 00:00:00 2001 From: The Dax Date: Wed, 9 Oct 2013 20:31:29 -0400 Subject: [PATCH 0729/1445] Add new System Property. --- base/NativeApp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/base/NativeApp.h b/base/NativeApp.h index 5c4f6522ca..aab1284f1f 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -101,6 +101,7 @@ void System_InputBox(const char *title, const char *defaultValue); enum SystemProperty { SYSPROP_NAME, SYSPROP_LANGREGION, + SYSPROP_CPUINFO, }; std::string System_GetProperty(SystemProperty prop); \ No newline at end of file From 357d22441430007787a0f38dd0956a4d8432f20c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 10 Oct 2013 11:06:53 +0200 Subject: [PATCH 0730/1445] Use an EGLConfigChooser to give us more control over which display config to use. --- android/app-android.cpp | 1 + .../libnative/NativeActivity.java | 11 +- .../libnative/NativeEGLConfigChooser.java | 167 ++++++++++++++++++ gfx_es2/gl_state.cpp | 8 +- ui/screen.cpp | 2 + 5 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java diff --git a/android/app-android.cpp b/android/app-android.cpp index d754850f1a..27ce230a6e 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -329,6 +329,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayShutdown( ILOG("NativeDeviceLost completed.;"); NativeShutdownGraphics(); renderer_inited = false; + NativeMessageReceived("recreateviews", ""); } } diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index b6e6379df0..b25e816435 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -22,6 +22,7 @@ import android.content.pm.ConfigurationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; +import android.graphics.PixelFormat; import android.graphics.Point; import android.media.AudioManager; import android.net.Uri; @@ -275,7 +276,15 @@ public class NativeActivity extends Activity { // Might want to change this for other apps (24-bit might be useful). // Actually, we might be able to do without both stencil and depth in // the back buffer, but that would kill non-buffered rendering. - mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8); + + // It appears some gingerbread devices blow up if you use a config chooser at all ???? (Xperia Play) + //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + + // On some (especially older devices), things blow up later (EGL_BAD_MATCH) if we don't set the format here, + // if we specify that we want destination alpha in the config chooser, which we do. + // http://grokbase.com/t/gg/android-developers/11bj40jm4w/fall-back + mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888); + mGLSurfaceView.setEGLConfigChooser(new NativeEGLConfigChooser()); nativeRenderer = new NativeRenderer(this); mGLSurfaceView.setRenderer(nativeRenderer); diff --git a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java new file mode 100644 index 0000000000..42eb02179b --- /dev/null +++ b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java @@ -0,0 +1,167 @@ +package com.henrikrydgard.libnative; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLDisplay; + +import android.opengl.GLSurfaceView.EGLConfigChooser; +import android.util.Log; + +public class NativeEGLConfigChooser implements EGLConfigChooser { + private static final String TAG = "NativeEGLConfigChooser"; + + private class ConfigAttribs { + EGLConfig config; + public int red; + public int green; + public int blue; + public int alpha; + public int stencil; + public int depth; + public int samples; + public void Log() { + Log.i(TAG, "EGLConfig: red=" + red + " green=" + green + " blue=" + blue + " alpha=" + alpha + " depth=" + depth + " stencil=" + stencil + " samples=" + samples); + } + } + + int getEglConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attr) { + int[] value = new int[1]; + try { + if (egl.eglGetConfigAttrib(display, config, attr, value)) + return value[0]; + else + return -1; + } catch (IllegalArgumentException e) { + if (config == null) { + Log.e(TAG, "Called getEglConfigAttrib with null config. Bad developer."); + } else { + Log.e(TAG, "Illegal argument to getEglConfigAttrib: attr=" + attr); + } + return -1; + } + } + + ConfigAttribs[] getConfigAttribs(EGL10 egl, EGLDisplay display, EGLConfig[] configs) { + ConfigAttribs[] attr = new ConfigAttribs[configs.length]; + for (int i = 0; i < configs.length; i++) { + ConfigAttribs cfg = new ConfigAttribs(); + cfg.config = configs[i]; + cfg.red = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_RED_SIZE); + cfg.green = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_GREEN_SIZE); + cfg.blue = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_BLUE_SIZE); + cfg.alpha = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_ALPHA_SIZE); + cfg.depth = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_DEPTH_SIZE); + cfg.stencil = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_STENCIL_SIZE); + cfg.samples = getEglConfigAttrib(egl, display, configs[i], EGL10.EGL_SAMPLES); + attr[i] = cfg; + } + return attr; + } + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { + // The absolute minimum. We will do our best to choose a better config though. + int[] configSpec = { + EGL10.EGL_RED_SIZE, 5, + EGL10.EGL_GREEN_SIZE, 6, + EGL10.EGL_BLUE_SIZE, 5, + EGL10.EGL_DEPTH_SIZE, 16, + EGL10.EGL_STENCIL_SIZE, 0, + EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, + EGL10.EGL_NONE + }; + + int[] num_config = new int[1]; + if (!egl.eglChooseConfig(display, configSpec, null, 0, num_config)) { + throw new IllegalArgumentException("eglChooseConfig failed when counting"); + } + + int numConfigs = num_config[0]; + Log.i(TAG, "There are " + numConfigs + " egl configs"); + if (numConfigs <= 0) { + throw new IllegalArgumentException("No configs match configSpec"); + } + + EGLConfig[] eglConfigs = new EGLConfig[numConfigs]; + if (!egl.eglChooseConfig(display, configSpec, eglConfigs, numConfigs, num_config)) { + throw new IllegalArgumentException("eglChooseConfig failed when retrieving"); + } + + ConfigAttribs [] configs = getConfigAttribs(egl, display, eglConfigs); + + ConfigAttribs chosen = null; + + // Log them all. + for (int i = 0; i < configs.length; i++) { + configs[i].Log(); + } + + // First, find our ideal configuration + for (int i = 0; i < configs.length; i++) { + ConfigAttribs c = configs[i]; + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth == 16) { + chosen = c; + break; + } + } + + if (chosen == null) { + // Second, accept one with bigger depth. + for (int i = 0; i < configs.length; i++) { + ConfigAttribs c = configs[i]; + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth > 16) { + chosen = c; + break; + } + } + } + + if (chosen == null) { + // Third, accept one with no stencil. + for (int i = 0; i < configs.length; i++) { + ConfigAttribs c = configs[i]; + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.depth >= 16) { + chosen = c; + break; + } + } + } + + if (chosen == null) { + // Third, accept one with no alpha but with stencil. + for (int i = 0; i < configs.length; i++) { + ConfigAttribs c = configs[i]; + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.stencil >= 8 && c.depth >= 16) { + chosen = c; + break; + } + } + } + + if (chosen == null) { + // Fourth, accept one with 16-bit color but depth required. + for (int i = 0; i < configs.length; i++) { + ConfigAttribs c = configs[i]; + if (c.red >= 5 && c.green >= 6 && c.blue >= 5 && c.depth >= 16) { + chosen = c; + break; + } + } + } + + if (chosen == null) { + // Final, accept the first one in the list. + if (configs.length > 0) + chosen = configs[0]; + } + + if (chosen == null) { + throw new IllegalArgumentException("Failed to find a valid EGL config"); + } + + Log.i(TAG, "Final chosen config: "); + chosen.Log(); + return chosen.config; + } + +} diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 2b89fc5ffb..661ddc1f0e 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -101,9 +101,9 @@ void CheckGLExtensions() { memset(&gl_extensions, 0, sizeof(gl_extensions)); const char *renderer = (const char *)glGetString(GL_RENDERER); + const char *versionStr = (const char *)glGetString(GL_VERSION); #ifndef USING_GLES2 - const char *versionStr = (const char *)glGetString(GL_VERSION); char buffer[64] = {0}; if (versionStr) { @@ -130,8 +130,10 @@ void CheckGLExtensions() { #if defined(USING_GLES2) // MAY_HAVE_GLES3 defined on all platforms, maybe redundant. Otherwise exclude platforms like Symbian, Meego, Raspberry Pi #if defined(MAY_HAVE_GLES3) && !defined(__SYMBIAN32__) - // Try to load GLES 3.0 - if (GL_TRUE == gl3stubInit()) { + // Try to load GLES 3.0 only if "3.0" found in version + // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited + // number of times. + if (strstr(versionStr, "3.0") && GL_TRUE == gl3stubInit()) { gl_extensions.ver[0] = 3; gl_extensions.GLES3 = true; ILOG("Full OpenGL ES 3.0 support detected!\n"); diff --git a/ui/screen.cpp b/ui/screen.cpp index aced41b9f6..d91d083e69 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -106,6 +106,8 @@ void ScreenManager::render() { } void ScreenManager::sendMessage(const char *msg, const char *value) { + if (!strcmp(msg, "recreateviews")) + RecreateAllViews(); if (!stack_.empty()) stack_.back().screen->sendMessage(msg, value); } From c0c8df61551fa4d7c205e84b23510bbfb8f065c4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 10 Oct 2013 11:08:10 +0200 Subject: [PATCH 0731/1445] Look for a format with stencil even if we only found RGB565. --- .../libnative/NativeEGLConfigChooser.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java index 42eb02179b..f4b7e210dc 100644 --- a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java +++ b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java @@ -139,7 +139,18 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { } if (chosen == null) { - // Fourth, accept one with 16-bit color but depth required. + // Fourth, accept one with 16-bit color but depth and stencil required. + for (int i = 0; i < configs.length; i++) { + ConfigAttribs c = configs[i]; + if (c.red >= 5 && c.green >= 6 && c.blue >= 5 && c.depth >= 16 && c.stencil >= 8) { + chosen = c; + break; + } + } + } + + if (chosen == null) { + // Fifth, accept one with 16-bit color but depth required. for (int i = 0; i < configs.length; i++) { ConfigAttribs c = configs[i]; if (c.red >= 5 && c.green >= 6 && c.blue >= 5 && c.depth >= 16) { From ac1620137f2bb804159afcee90f0dddffdcbf095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 10 Oct 2013 14:24:33 +0200 Subject: [PATCH 0732/1445] Android: Add simple haptic feedback support --- android/app-android.cpp | 4 ++- .../libnative/NativeActivity.java | 30 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 27ce230a6e..ef858beed9 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -64,7 +64,9 @@ void ShowKeyboard() { void Vibrate(int length_ms) { frameCommand = "vibrate"; - frameCommandParam = "100"; + char temp[32]; + sprintf(temp, "%i", length_ms); + frameCommandParam = temp; } void LaunchBrowser(const char *url) { diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index b25e816435..30e922fa18 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -29,6 +29,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.os.Vibrator; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; @@ -107,6 +108,8 @@ public class NativeActivity extends Activity { // audioFocusChangeListener to listen to changes in audio state private AudioFocusChangeListener audioFocusChangeListener; private AudioManager audioManager; + + private Vibrator vibrator; public static boolean inputBoxCancelled; @@ -237,7 +240,10 @@ public class NativeActivity extends Activity { } } - + vibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE); + if (Build.VERSION.SDK_INT >= 11) { + checkForVibrator(); + } /* editText = new EditText(this); editText.setText("Hello world"); @@ -246,6 +252,16 @@ public class NativeActivity extends Activity { */ // inputBox("Please ener a s", "", "Save"); } + + // Need API 11 to check for existence of a vibrator? Zany. + @TargetApi(11) + public void checkForVibrator() { + if (Build.VERSION.SDK_INT >= 11) { + if (!vibrator.hasVibrator()) { + vibrator = null; + } + } + } @Override public void onCreate(Bundle savedInstanceState) { @@ -626,6 +642,18 @@ public class NativeActivity extends Activity { inputMethodManager.toggleSoftInputFromWindow(mGLSurfaceView.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0); } else if (command.equals("inputBox")) { inputBox(params, "", "OK"); + } else if (command.equals("vibrate")) { + if (vibrator != null) { + int milliseconds = 50; + if (params != "") { + try { + milliseconds = Integer.parseInt(params); + } catch (NumberFormatException e) { + milliseconds = 50; + } + } + vibrator.vibrate(milliseconds); + } } else { Log.e(TAG, "Unsupported command " + command + " , param: " + params); } From 9aa30a69f6f4d64b7d5e9d492e857b8eb03e7b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 10 Oct 2013 15:59:57 +0200 Subject: [PATCH 0733/1445] Add support for standard Android haptic feedback, which does not require the VIBRATE permission. --- .../libnative/NativeActivity.java | 24 ++++++++++++++++--- base/NativeApp.h | 13 +++++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 30e922fa18..40335ef964 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -37,6 +37,7 @@ import android.view.Gravity; import android.view.InputDevice; import android.view.InputEvent; import android.view.KeyEvent; +import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import android.view.Window; @@ -644,15 +645,32 @@ public class NativeActivity extends Activity { inputBox(params, "", "OK"); } else if (command.equals("vibrate")) { if (vibrator != null) { - int milliseconds = 50; + int milliseconds = -1; if (params != "") { try { milliseconds = Integer.parseInt(params); } catch (NumberFormatException e) { - milliseconds = 50; } } - vibrator.vibrate(milliseconds); + // Special parameters to perform standard haptic feedback operations + // -1 = Standard keyboard press feedback + // -2 = Virtual key press + // -3 = Long press feedback + // Note that these three do not require the VIBRATE Android permission. + switch (milliseconds) { + case -1: + mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + break; + case -2: + mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + break; + case -3: + mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + break; + default: + vibrator.vibrate(milliseconds); + break; + } } } else { Log.e(TAG, "Unsupported command " + command + " , param: " + params); diff --git a/base/NativeApp.h b/base/NativeApp.h index aab1284f1f..a8de5d723a 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -92,6 +92,17 @@ void NativeSaveState(); // onDestroy void SystemToast(const char *text); void ShowKeyboard(); void ShowAd(int x, int y, bool center_x); + +// Vibrate either takes a number of milliseconds to vibrate unconditionally, +// or you can specify these constants for "standard" feedback. On Android, +// these will only be performed if haptic feedback is enabled globally. +// Also, on Android, these will work even if you don't have the VIBRATE permission, +// while generic vibration will not if you don't have it. +enum { + HAPTIC_SOFT_KEYBOARD = -1, + HAPTIC_VIRTUAL_KEY = -2, + HAPTIC_LONG_PRESS_ACTIVATED = -3, +}; void Vibrate(int length_ms); void LaunchBrowser(const char *url); void LaunchMarket(const char *url); @@ -104,4 +115,4 @@ enum SystemProperty { SYSPROP_CPUINFO, }; -std::string System_GetProperty(SystemProperty prop); \ No newline at end of file +std::string System_GetProperty(SystemProperty prop); From 75048fd002222462a117d6f89f95deec731161eb Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 11 Oct 2013 02:12:28 +1000 Subject: [PATCH 0734/1445] Make Blackberry vibrate compatible with haptic feedback option. --- base/BlackberryMain.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 65b74f5cff..e861c6b736 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -40,7 +40,22 @@ void ShowKeyboard() { } void Vibrate(int length_ms) { - vibration_request(VIBRATION_INTENSITY_LOW, 200 /* intensity (1-100), duration (ms) */); + // Vibration: intensity strength(1-100), duration ms(0-5000) + // Intensity: LOW = 1, MEDIUM = 10, HIGH = 100 + switch (length_ms) { + case -1: // Keyboard Tap + vibration_request(VIBRATION_INTENSITY_LOW, 50); + break; + case -2: // Virtual Key + vibration_request(VIBRATION_INTENSITY_LOW, 25); + break; + case -3: // Long Press + vibration_request(VIBRATION_INTENSITY_LOW, 50); + break; + default: + vibration_request(VIBRATION_INTENSITY_LOW, length_ms); + break; + } } void LaunchBrowser(const char *url) From 36bc59f006d4eebe5aef00071cf95f3d848e0444 Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 11 Oct 2013 02:49:09 +1000 Subject: [PATCH 0735/1445] Add vibration support for Symbian and stub for Qt. --- base/QtMain.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 69abb96679..df355de8d8 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -14,6 +14,7 @@ #ifdef __SYMBIAN32__ #include #include +#include #endif #include "QtMain.h" @@ -46,6 +47,31 @@ std::string System_GetProperty(SystemProperty prop) { } } +#ifdef __SYMBIAN32__ +CHWRMVibra* vibra; +#endif + +void Vibrate(int length_ms) { + if (length_ms == -1 || length_ms == -3) + length_ms = 50; + else if (length_ms == -2) + length_ms = 25; + // Qt 4.8 does not have any cross-platform Vibrate. Symbian-only for now. +#ifdef __SYMBIAN32__ + CHWRMVibra::TVibraModeState iState = vibra->VibraSettings(); + CHWRMVibra::TVibraStatus iStatus = vibra->VibraStatus(); + // User has not enabled vibration in settings. + if(iState != CHWRMVibra::EVibraModeON) + return; + if(iStatus != CHWRMVibra::EVibraStatusStopped) + vibra->StopVibraL(); +#endif + +#ifdef __SYMBIAN32__ + vibra->StartVibraL(length_ms, 20); +#endif +} + void LaunchBrowser(const char *url) { QDesktopServices::openUrl(QUrl(url)); @@ -124,12 +150,17 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) // Disable screensaver QSystemScreenSaver *ssObject = new QSystemScreenSaver(&w); ssObject->setScreenSaverInhibit(); + // Start vibration service + vibra = CHWRMVibra::NewL(); #endif MainAudio *audio = new MainAudio(); int ret = a.exec(); delete audio; +#ifdef __SYMBIAN32__ + delete vibra; +#endif NativeShutdown(); net::Shutdown(); return ret; From b16b67d8b6e2fd5127f9b84ec9f5496d8f782e71 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 10 Oct 2013 23:55:59 +0200 Subject: [PATCH 0736/1445] Fix OpenGL context creation on PowerVR --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 ++ .../com/henrikrydgard/libnative/NativeEGLConfigChooser.java | 3 +++ android/src/com/henrikrydgard/libnative/NativeGLView.java | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 40335ef964..2edfccb9dc 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -286,6 +286,8 @@ public class NativeActivity extends Activity { NativeApp.audioInit(); mGLSurfaceView = new NativeGLView(this); + + mGLSurfaceView.setEGLContextClientVersion(2); // Setup the GLSurface and ask android for the correct // Number of bits for r, g, b, a, depth and stencil components diff --git a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java index f4b7e210dc..d961095a68 100644 --- a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java +++ b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java @@ -10,6 +10,8 @@ import android.util.Log; public class NativeEGLConfigChooser implements EGLConfigChooser { private static final String TAG = "NativeEGLConfigChooser"; + private static final int EGL_OPENGL_ES2_BIT = 4; + private class ConfigAttribs { EGLConfig config; public int red; @@ -68,6 +70,7 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_STENCIL_SIZE, 0, EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, + EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE }; diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 9da7086a1e..644077cee6 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -27,7 +27,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, public NativeGLView(NativeActivity activity) { super(activity); - setEGLContextClientVersion(2); + /* if (Build.VERSION.SDK_INT >= 11) { try { From d0476f22a01e20ecd79decbe9d9cf0e2da502580 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 12 Oct 2013 01:29:10 +0200 Subject: [PATCH 0737/1445] Minor tweak to ini_file --- file/ini_file.cpp | 2 +- file/ini_file.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index 714d569dd9..b5351a3751 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -100,7 +100,7 @@ void IniFile::Section::Set(const char* key, const std::string& newValue, const s bool IniFile::Section::Get(const char* key, std::string* value, const char* defaultValue) { - std::string* line = GetLine(key, value, 0); + const std::string* line = GetLine(key, value, 0); if (!line) { if (defaultValue) diff --git a/file/ini_file.h b/file/ini_file.h index 0205bbf1cf..83626e1552 100644 --- a/file/ini_file.h +++ b/file/ini_file.h @@ -170,7 +170,7 @@ public: bool DeleteSection(const char* sectionName); void SortSections(); - const std::vector
&Sections() { return sections; } + std::vector
&Sections() { return sections; } bool HasSection(const char *section) { return GetSection(section) != 0; } From 5a4dec927289eb93fafc7bbd7facaee0c982accc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 12 Oct 2013 02:05:12 +0200 Subject: [PATCH 0738/1445] Add filter support to vfs directory listing --- file/zip_read.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 44c9ac491f..bf3bfadbac 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -85,6 +85,22 @@ uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { bool ZipAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) { ILOG("Zip path: %s", path); + std::set filters; + std::string tmp; + if (filter) { + while (*filter) { + if (*filter == ':') { + filters.insert(tmp); + tmp = ""; + } else { + tmp.push_back(*filter); + } + filter++; + } + } + if (tmp.size()) + filters.insert(tmp); + // We just loop through the whole ZIP file and deduce what files are in this directory, and what subdirectories there are. std::set files; std::set directories; @@ -96,7 +112,6 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis const char* name = zip_get_name(zip_file_, i, 0); if (!name) continue; - // ILOG("Comparing %s %s %i", name, path, pathlen); if (!memcmp(name, path, pathlen)) { // The prefix is right. Let's see if this is a file or path. char *slashPos = strchr(name + pathlen + 1, '/'); @@ -114,7 +129,7 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis FileInfo info; info.name = *diter; info.fullName = std::string(path); - if (info.fullName[info.fullName.size()-1] == '/') + if (info.fullName[info.fullName.size() - 1] == '/') info.fullName = info.fullName.substr(0, info.fullName.size() - 1); info.fullName += "/" + *diter; info.exists = true; @@ -127,12 +142,17 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis FileInfo info; info.name = *fiter; info.fullName = std::string(path); - if (info.fullName[info.fullName.size()-1] == '/') + if (info.fullName[info.fullName.size() - 1] == '/') info.fullName = info.fullName.substr(0, info.fullName.size() - 1); info.fullName += "/" + *fiter; info.exists = true; info.isWritable = false; info.isDirectory = false; + std::string ext = getFileExtension(info.fullName); + if (filter) { + if (filters.find(ext) == filters.end()) + continue; + } listing->push_back(info); } From a25169dc4c6a2e26c16b26faa0b37bb474c0d37e Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 12 Oct 2013 17:17:48 +1000 Subject: [PATCH 0739/1445] Distinguish between Touch and QWERTY Blackberry. --- base/BlackberryMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index e861c6b736..1daf87939b 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -16,7 +16,7 @@ std::string System_GetProperty(SystemProperty prop) { switch (prop) { case SYSPROP_NAME: - return "Blackberry10"; + return "Blackberry10:" + (pixel_xres != pixel_yres) ? "Touch" : "QWERTY"; case SYSPROP_LANGREGION: return "en_US"; default: From d19cef23951ce6e9ff8402f9fa1b9304e940805b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 13 Oct 2013 11:56:42 +0200 Subject: [PATCH 0740/1445] Do not crash on broken shaders, allow error message return --- base/logging.h | 12 +++++++---- gfx_es2/glsl_program.cpp | 44 +++++++++++++++++++++++++--------------- gfx_es2/glsl_program.h | 17 ++++++---------- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/base/logging.h b/base/logging.h index 95bfe176d0..9503313571 100644 --- a/base/logging.h +++ b/base/logging.h @@ -7,6 +7,10 @@ // Disable annoying warnings in VS #ifdef _MSC_VER #pragma warning (disable:4996) //strcpy may be dangerous + +#if !defined(snprintf) +#define snprintf _snprintf +#endif #endif #undef Crash @@ -66,10 +70,10 @@ inline void Crash() { void OutputDebugStringUTF8(const char *p); -#define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "I: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} -#define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "W: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} -#define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "E: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} -#define FLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "F: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "F: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp); Crash();} +#define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "I: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "W: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "E: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define FLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "F: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "F: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp); Crash();} // TODO: Win32 version using OutputDebugString #else diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index c900bee8fb..e5383896d3 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -10,7 +10,7 @@ static std::set active_programs; -bool CompileShader(const char *source, GLuint shader, const char *filename) { +bool CompileShader(const char *source, GLuint shader, const char *filename, std::string *error_message) { glShaderSource(shader, 1, &source, NULL); glCompileShader(shader); GLint success; @@ -24,12 +24,14 @@ bool CompileShader(const char *source, GLuint shader, const char *filename) { ELOG("Error in shader compilation of %s!\n", filename); ELOG("Info log: %s\n", infoLog); ELOG("Shader source:\n%s\n", (const char *)source); + if (error_message) + *error_message = infoLog; return false; } return true; } -GLSLProgram *glsl_create(const char *vshader, const char *fshader) { +GLSLProgram *glsl_create(const char *vshader, const char *fshader, std::string *error_message) { GLSLProgram *program = new GLSLProgram(); program->program_ = 0; program->vsh_ = 0; @@ -39,18 +41,18 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader) { strcpy(program->name, vshader + strlen(vshader) - 15); strcpy(program->vshader_filename, vshader); strcpy(program->fshader_filename, fshader); - if (glsl_recompile(program)) { + if (glsl_recompile(program, error_message)) { active_programs.insert(program); - } - else - { - FLOG("Failed building GLSL program: %s %s", vshader, fshader); + } else { + ELOG("Failed compiling GLSL program: %s %s", vshader, fshader); + delete program; + return 0; } register_gl_resource_holder(program); return program; } -GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src) { +GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src, std::string *error_message) { GLSLProgram *program = new GLSLProgram(); program->program_ = 0; program->vsh_ = 0; @@ -60,8 +62,12 @@ GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src strcpy(program->name, "[srcshader]"); strcpy(program->vshader_filename, ""); strcpy(program->fshader_filename, ""); - if (glsl_recompile(program)) { + if (glsl_recompile(program, error_message)) { active_programs.insert(program); + } else { + ELOG("Failed compiling GLSL program from source strings"); + delete program; + return 0; } register_gl_resource_holder(program); return program; @@ -89,7 +95,7 @@ void glsl_refresh() { } } -bool glsl_recompile(GLSLProgram *program) { +bool glsl_recompile(GLSLProgram *program, std::string *error_message) { struct stat vs, fs; if (0 == stat(program->vshader_filename, &vs)) program->vshader_mtime = vs.st_mtime; @@ -125,14 +131,14 @@ bool glsl_recompile(GLSLProgram *program) { GLuint vsh = glCreateShader(GL_VERTEX_SHADER); const GLchar *vsh_str = program->vshader_source ? program->vshader_source : (const GLchar *)(vsh_src); - if (!CompileShader(vsh_str, vsh, program->vshader_filename)) { + if (!CompileShader(vsh_str, vsh, program->vshader_filename, error_message)) { return false; } delete [] vsh_src; const GLchar *fsh_str = program->fshader_source ? program->fshader_source : (const GLchar *)(fsh_src); GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); - if (!CompileShader(fsh_str, fsh, program->fshader_filename)) { + if (!CompileShader(fsh_str, fsh, program->fshader_filename, error_message)) { glDeleteShader(vsh); return false; } @@ -150,14 +156,20 @@ bool glsl_recompile(GLSLProgram *program) { GLint bufLength = 0; glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength); if (bufLength) { - char* buf = new char[bufLength]; + char* buf = new char[bufLength + 1]; // safety glGetProgramInfoLog(prog, bufLength, NULL, buf); ILOG("vsh: %i fsh: %i", vsh, fsh); - FLOG("Could not link shader program (linkstatus=%i):\n %s \n", linkStatus, buf); - delete [] buf; // we're dead! + ELOG("Could not link shader program (linkstatus=%i):\n %s \n", linkStatus, buf); + if (error_message) { + *error_message = buf; + } + delete [] buf; } else { ILOG("vsh: %i fsh: %i", vsh, fsh); - FLOG("Could not link shader program (linkstatus=%i). No OpenGL error log was available.", linkStatus); + ELOG("Could not link shader program (linkstatus=%i). No OpenGL error log was available.", linkStatus); + if (error_message) { + *error_message = "(no error message available)"; + } } glDeleteShader(vsh); glDeleteShader(fsh); diff --git a/gfx_es2/glsl_program.h b/gfx_es2/glsl_program.h index f2417d40a3..c6ee880d27 100644 --- a/gfx_es2/glsl_program.h +++ b/gfx_es2/glsl_program.h @@ -1,10 +1,10 @@ // Utility code for loading GLSL shaders. // Has support for auto-reload, see glsl_refresh -#ifndef _RENDER_UTIL -#define _RENDER_UTIL +#pragma once #include +#include #include #include "gfx/gl_lost_manager.h" @@ -46,18 +46,17 @@ struct GLSLProgram : public GfxResourceHolder { void GLLost(); }; - -// C API, old skool +// C API, old skool. Not much point either... // From files (VFS) -GLSLProgram *glsl_create(const char *vshader_file, const char *fshader_file); +GLSLProgram *glsl_create(const char *vshader_file, const char *fshader_file, std::string *error_message = 0); // Directly from source code -GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src); +GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src, std::string *error_message = 0); void glsl_destroy(GLSLProgram *program); // If recompilation of the program fails, the program is untouched and error messages // are logged and the function returns false. -bool glsl_recompile(GLSLProgram *program); +bool glsl_recompile(GLSLProgram *program, std::string *error_message = 0); void glsl_bind(const GLSLProgram *program); void glsl_unbind(); int glsl_attrib_loc(const GLSLProgram *program, const char *name); @@ -67,7 +66,3 @@ int glsl_uniform_loc(const GLSLProgram *program, const char *name); // fstat-s all the source files of all the shaders to see if they // should be recompiled, and recompiles them if so. void glsl_refresh(); - -// Use glUseProgramObjectARB(NULL); to unset. - -#endif // _RENDER_UTIL From 788d5125150e95e3d57e095846a3e6a1fed94d3d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 13 Oct 2013 19:07:10 +0200 Subject: [PATCH 0741/1445] UI: Fix dispatching of events to multiple listeners. --- ui/view.cpp | 11 +++++++++-- ui/view.h | 6 +----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 77ecd55ed7..59ab6ca961 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -103,13 +103,14 @@ void Event::Trigger(EventParams &e) { // Call this from UI thread EventReturn Event::Dispatch(EventParams &e) { + bool eventHandled = false; for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { if ((iter->func)(e) == UI::EVENT_DONE) { // Event is handled, stop looping immediately. This event might even have gotten deleted. - return UI::EVENT_DONE; + eventHandled = true; } } - return UI::EVENT_SKIPPED; + return eventHandled ? UI::EVENT_DONE : UI::EVENT_SKIPPED; } void View::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { @@ -370,6 +371,12 @@ void PopupHeader::Draw(UIContext &dc) { dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->popupTitle.fgColor); } +EventReturn CheckBox::OnClicked(EventParams &e) { + if (toggle_) + *toggle_ = !(*toggle_); + return EVENT_DONE; +} + void CheckBox::Draw(UIContext &dc) { ClickableItem::Draw(dc); int paddingX = 12; diff --git a/ui/view.h b/ui/view.h index f636088e50..9e6a07b45d 100644 --- a/ui/view.h +++ b/ui/view.h @@ -596,11 +596,7 @@ public: virtual void Draw(UIContext &dc); - EventReturn OnClicked(EventParams &e) { - if (toggle_) - *toggle_ = !(*toggle_); - return EVENT_DONE; - } + EventReturn OnClicked(EventParams &e); private: bool *toggle_; From eed7159a065266fd7d70513c81fd6064286f4dcf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 13 Oct 2013 20:33:42 +0200 Subject: [PATCH 0742/1445] Improve event processing semantics a little. Add a safety check I'm not sure is needed. --- ui/view.cpp | 28 +++++++++++++++++++++------- ui/view.h | 8 +++++--- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 59ab6ca961..54745f8b35 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -26,7 +26,7 @@ struct DispatchQueueItem { EventParams params; }; -std::queue g_dispatchQueue; +std::deque g_dispatchQueue; void EventTriggered(Event *e, EventParams params) { @@ -35,7 +35,7 @@ void EventTriggered(Event *e, EventParams params) { DispatchQueueItem item; item.e = e; item.params = params; - g_dispatchQueue.push(item); + g_dispatchQueue.push_front(item); } void DispatchEvents() { @@ -43,11 +43,19 @@ void DispatchEvents() { while (!g_dispatchQueue.empty()) { DispatchQueueItem item = g_dispatchQueue.back(); - g_dispatchQueue.pop(); - item.e->Dispatch(item.params); + g_dispatchQueue.pop_back(); + if (item.e) { + item.e->Dispatch(item.params); + } } } +void RemoveQueuedEvents(View *v) { + for (int i = 0; i < g_dispatchQueue.size(); i++) { + if (g_dispatchQueue[i].params.v == v) + g_dispatchQueue.erase(g_dispatchQueue.begin() + i); + } +} View *GetFocusedView() { return focusedView; @@ -107,10 +115,16 @@ EventReturn Event::Dispatch(EventParams &e) { for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { if ((iter->func)(e) == UI::EVENT_DONE) { // Event is handled, stop looping immediately. This event might even have gotten deleted. - eventHandled = true; + return UI::EVENT_DONE; } } - return eventHandled ? UI::EVENT_DONE : UI::EVENT_SKIPPED; + return UI::EVENT_SKIPPED; +} + +View::~View() { + if (HasFocus()) + SetFocusedView(0); + RemoveQueuedEvents(this); } void View::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { @@ -374,7 +388,7 @@ void PopupHeader::Draw(UIContext &dc) { EventReturn CheckBox::OnClicked(EventParams &e) { if (toggle_) *toggle_ = !(*toggle_); - return EVENT_DONE; + return EVENT_CONTINUE; // It's safe to keep processing events. } void CheckBox::Draw(UIContext &dc) { diff --git a/ui/view.h b/ui/view.h index 9e6a07b45d..9e2aa1085f 100644 --- a/ui/view.h +++ b/ui/view.h @@ -180,9 +180,11 @@ enum MeasureSpecType { AT_MOST, }; +// I hope I can find a way to simplify this one day. enum EventReturn { - EVENT_DONE, - EVENT_SKIPPED, + EVENT_DONE, // Return this when no other view may process this event, for example if you changed the view hierarchy + EVENT_SKIPPED, // Return this if you ignored an event + EVENT_CONTINUE, // Return this if it's safe to send this event along. This hsould normally be the default choice but often EVENT_DONE is necessary. }; enum FocusFlags { @@ -292,7 +294,7 @@ public: layoutParams_.reset(new LayoutParams()); } - virtual ~View() { if (HasFocus()) SetFocusedView(0); } + virtual ~View(); // Please note that Touch is called ENTIRELY asynchronously from drawing! // Can even be called on a different thread! This is to really minimize latency, and decouple From b469bc8aff124f52255c5f27f96db455c178e982 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 13 Oct 2013 20:49:10 +0200 Subject: [PATCH 0743/1445] Comment fix. --- ui/view.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/view.h b/ui/view.h index 9e2aa1085f..ee0f1cface 100644 --- a/ui/view.h +++ b/ui/view.h @@ -184,7 +184,7 @@ enum MeasureSpecType { enum EventReturn { EVENT_DONE, // Return this when no other view may process this event, for example if you changed the view hierarchy EVENT_SKIPPED, // Return this if you ignored an event - EVENT_CONTINUE, // Return this if it's safe to send this event along. This hsould normally be the default choice but often EVENT_DONE is necessary. + EVENT_CONTINUE, // Return this if it's safe to send this event to further listeners. This should normally be the default choice but often EVENT_DONE is necessary. }; enum FocusFlags { From 1b5c59db75ea735c9a97b71e2abb17ce809b2372 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Oct 2013 11:59:43 -0700 Subject: [PATCH 0744/1445] Correctly exit work queue on done, race condition fix. done_ might've been set to true while processing the item, making the wait wait forever. --- thread/prioritizedworkqueue.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index 18369ed617..e2b3e7ef09 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -12,8 +12,8 @@ PrioritizedWorkQueue::~PrioritizedWorkQueue() { void PrioritizedWorkQueue::Add(PrioritizedWorkQueueItem *item) { mutex_.lock(); queue_.push_back(item); - mutex_.unlock(); notEmpty_.notify_one(); + mutex_.unlock(); } void PrioritizedWorkQueue::Stop() { @@ -38,7 +38,7 @@ void PrioritizedWorkQueue::Flush() { // The worker should simply call this in a loop. Will block when appropriate. PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { mutex_.lock(); - while (queue_.empty()) { + while (queue_.empty() && !done_) { notEmpty_.wait(mutex_); if (done_) { mutex_.unlock(); From 12fb5c4f32f56a09deff5a89d8d9c94075fb9588 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Oct 2013 12:02:52 -0700 Subject: [PATCH 0745/1445] iOS: Don't try to use GLES3 for now. --- gfx_es2/gl3stub.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx_es2/gl3stub.c b/gfx_es2/gl3stub.c index c9f7c87b9a..5e5d9abec5 100644 --- a/gfx_es2/gl3stub.c +++ b/gfx_es2/gl3stub.c @@ -14,6 +14,8 @@ * limitations under the License. */ +#ifndef IOS + #include "gl3stub.h" #if defined(USING_GLES2) && !defined(__SYMBIAN32__) @@ -344,3 +346,4 @@ GL_APICALL void (* GL_APIENTRY glTexStorage3D) (GLenum target, GLsizei GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); #endif +#endif From adca06c6963532902af1eed15d34f87f5112ed6d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Oct 2013 12:09:09 -0700 Subject: [PATCH 0746/1445] Use guards, avoid the "not sure how" case. --- thread/prioritizedworkqueue.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index e2b3e7ef09..0d10d9a0b2 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -10,38 +10,38 @@ PrioritizedWorkQueue::~PrioritizedWorkQueue() { } void PrioritizedWorkQueue::Add(PrioritizedWorkQueueItem *item) { - mutex_.lock(); + lock_guard guard(mutex_); queue_.push_back(item); notEmpty_.notify_one(); - mutex_.unlock(); } void PrioritizedWorkQueue::Stop() { - mutex_.lock(); + lock_guard guard(mutex_); done_ = true; notEmpty_.notify_one(); - mutex_.unlock(); } void PrioritizedWorkQueue::Flush() { if (queue_.empty()) return; - mutex_.lock(); + lock_guard guard(mutex_); for (auto iter = queue_.begin(); iter != queue_.end(); ++iter) { delete *iter; } queue_.clear(); - mutex_.unlock(); } // The worker should simply call this in a loop. Will block when appropriate. PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { - mutex_.lock(); - while (queue_.empty() && !done_) { + lock_guard guard(mutex_); + if (done_) { + return 0; + } + + while (queue_.empty()) { notEmpty_.wait(mutex_); if (done_) { - mutex_.unlock(); return 0; } } @@ -59,11 +59,9 @@ PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { if (best != queue_.end()) { PrioritizedWorkQueueItem *poppedItem = *best; queue_.erase(best); - mutex_.unlock(); return poppedItem; } else { // Not really sure how this can happen, but let's be safe. - mutex_.unlock(); return 0; } } From d63237c2af1f9888674dd959998e85e8b8921171 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Oct 2013 15:11:25 -0700 Subject: [PATCH 0747/1445] Allow shaders to be outside VFS as well. --- gfx_es2/glsl_program.cpp | 60 +++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index e5383896d3..3ae758d695 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -6,6 +6,7 @@ #include "base/logging.h" #include "file/vfs.h" +#include "file/zip_read.h" #include "glsl_program.h" static std::set active_programs; @@ -97,36 +98,51 @@ void glsl_refresh() { bool glsl_recompile(GLSLProgram *program, std::string *error_message) { struct stat vs, fs; - if (0 == stat(program->vshader_filename, &vs)) - program->vshader_mtime = vs.st_mtime; - else - program->vshader_mtime = 0; - - if (0 == stat(program->fshader_filename, &fs)) - program->fshader_mtime = fs.st_mtime; - else - program->fshader_mtime = 0; - char *vsh_src = 0, *fsh_src = 0; - if (!program->vshader_source) - { + if (strlen(program->vshader_filename) > 0 && 0 == stat(program->vshader_filename, &vs)) { + program->vshader_mtime = vs.st_mtime; + if (!program->vshader_source) { + size_t sz; + vsh_src = (char *)ReadLocalFile(program->vshader_filename, &sz); + } + } else { + program->vshader_mtime = 0; + } + + if (strlen(program->fshader_filename) > 0 && 0 == stat(program->fshader_filename, &fs)) { + program->fshader_mtime = fs.st_mtime; + if (!program->fshader_source) { + size_t sz; + fsh_src = (char *)ReadLocalFile(program->fshader_filename, &sz); + } + } else { + program->fshader_mtime = 0; + } + + if (!program->vshader_source && !vsh_src) { size_t sz; vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz); - if (!vsh_src) { - ELOG("File missing: %s", program->vshader_filename); - return false; - } } - if (!program->fshader_source) - { + if (!program->vshader_source && !vsh_src) { + ELOG("File missing: %s", program->vshader_filename); + if (error_message) { + *error_message = std::string("File missing: ") + program->vshader_filename; + } + delete [] fsh_src; + return false; + } + if (!program->fshader_source && !fsh_src) { size_t sz; fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz); - if (!fsh_src) { - ELOG("File missing: %s", program->fshader_filename); - delete [] vsh_src; - return false; + } + if (!program->fshader_source && !fsh_src) { + ELOG("File missing: %s", program->fshader_filename); + if (error_message) { + *error_message = std::string("File missing: ") + program->fshader_filename; } + delete [] vsh_src; + return false; } GLuint vsh = glCreateShader(GL_VERTEX_SHADER); From f64ca47304b86291f75c31493a1494c58e335763 Mon Sep 17 00:00:00 2001 From: The Dax Date: Mon, 14 Oct 2013 02:10:47 -0400 Subject: [PATCH 0748/1445] Use wide paths on Win32. --- file/ini_file.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index b5351a3751..9736f62e4d 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -20,6 +20,7 @@ #include "file/vfs.h" #ifdef _WIN32 +#include "../util/text/utf8.h" // Function Cross-Compatibility #define strcasecmp _stricmp #endif @@ -412,8 +413,9 @@ bool IniFile::Load(const char* filename) // Open file std::ifstream in; - in.open(filename, std::ios::in); - +#ifdef _WIN32 + in.open(ConvertUTF8ToWString(filename), std::ios::in); +#endif if (in.fail()) return false; bool success = Load(in); @@ -487,7 +489,11 @@ bool IniFile::Load(std::istream &in) { bool IniFile::Save(const char* filename) { std::ofstream out; +#ifdef _WIN32 + out.open(ConvertUTF8ToWString(filename), std::ios::out); +#else out.open(filename, std::ios::out); +#endif if (out.fail()) { @@ -521,7 +527,6 @@ bool IniFile::Save(const char* filename) return true; } - bool IniFile::Get(const char* sectionName, const char* key, std::string* value, const char* defaultValue) { Section* section = GetSection(sectionName); From 1524cc37f5aae34fe66f9c7360df814506f73b31 Mon Sep 17 00:00:00 2001 From: The Dax Date: Mon, 14 Oct 2013 02:28:30 -0400 Subject: [PATCH 0749/1445] Oops. --- file/ini_file.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index 9736f62e4d..e9e50b69f1 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -415,6 +415,8 @@ bool IniFile::Load(const char* filename) std::ifstream in; #ifdef _WIN32 in.open(ConvertUTF8ToWString(filename), std::ios::in); +#else + in.open(filename, std::ios::in); #endif if (in.fail()) return false; From adb73a884400bf448f0ee382227ae64f4a34e23e Mon Sep 17 00:00:00 2001 From: The Dax Date: Mon, 14 Oct 2013 13:15:32 -0400 Subject: [PATCH 0750/1445] Only append a slash to the directory if there isn't one on the end. --- file/file_util.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index 426b45054c..7cbe7a3c06 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -297,7 +297,14 @@ size_t getFilesInDir(const char *directory, std::vector *files, const FileInfo info; info.name = virtualName; - info.fullName = std::string(directory) + "/" + virtualName; + std::string dir = directory; + + // Only append a slash if there isn't one on the end. + size_t lastSlash = dir.find_last_of("/"); + if (lastSlash != (dir.length() - 1)) + dir.append("/"); + + info.fullName = dir + virtualName; info.isDirectory = isDirectory(info.fullName); info.exists = true; info.size = 0; From 5e1a52a84146f17e010dfbe8191f14eaf2d99dab Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 15 Oct 2013 15:27:40 +1000 Subject: [PATCH 0751/1445] Fix naming for Blackberry. --- base/BlackberryMain.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 1daf87939b..460b143b39 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -15,8 +15,10 @@ std::string System_GetProperty(SystemProperty prop) { switch (prop) { - case SYSPROP_NAME: - return "Blackberry10:" + (pixel_xres != pixel_yres) ? "Touch" : "QWERTY"; + case SYSPROP_NAME: { + std::string name = "Blackberry10:"; + return name + ((pixel_xres != pixel_yres) ? "Touch" : "QWERTY"); + } case SYSPROP_LANGREGION: return "en_US"; default: From aa67389dcd0be4ae00af1f048a7111804081a0f8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 16 Oct 2013 00:46:41 +0200 Subject: [PATCH 0752/1445] Move the GPU vendor detection to native --- gfx_es2/gl_state.cpp | 31 +++++++++++++++++++++++++++++++ gfx_es2/gl_state.h | 11 +++++++++++ 2 files changed, 42 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 661ddc1f0e..364538ab32 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -103,6 +103,37 @@ void CheckGLExtensions() { const char *renderer = (const char *)glGetString(GL_RENDERER); const char *versionStr = (const char *)glGetString(GL_VERSION); + // Check vendor string to try and guess GPU + const char *cvendor = (char *)glGetString(GL_VENDOR); + if (cvendor) { + const std::string vendor(cvendor); + if (vendor == "NVIDIA Corporation" + || vendor == "Nouveau" + || vendor == "nouveau") { + gl_extensions.gpuVendor = GPU_VENDOR_NVIDIA; + } else if (vendor == "Advanced Micro Devices, Inc." + || vendor == "ATI Technologies Inc.") { + gl_extensions.gpuVendor = GPU_VENDOR_AMD; + } else if (vendor == "Intel" + || vendor == "Intel Inc." + || vendor == "Intel Corporation" + || vendor == "Tungsten Graphics, Inc") { // We'll assume this last one means Intel + gl_extensions.gpuVendor = GPU_VENDOR_INTEL; + } else if (vendor == "ARM") { + gl_extensions.gpuVendor = GPU_VENDOR_ARM; + } else if (vendor == "Imagination Technologies") { + gl_extensions.gpuVendor = GPU_VENDOR_POWERVR; + } else if (vendor == "Qualcomm") { + gl_extensions.gpuVendor = GPU_VENDOR_ADRENO; + } else { + gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; + } + } else { + gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; + } + + ILOG("GPU Vendor : %s", cvendor); + #ifndef USING_GLES2 char buffer[64] = {0}; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index a2e974cabe..60bef80e4c 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -309,12 +309,23 @@ public: extern OpenGLState glstate; +enum { + GPU_VENDOR_NVIDIA = 1, + GPU_VENDOR_AMD = 2, + GPU_VENDOR_INTEL = 3, + GPU_VENDOR_ARM = 4, + GPU_VENDOR_POWERVR = 5, + GPU_VENDOR_ADRENO = 6, + GPU_VENDOR_UNKNOWN = 0, +}; + // Extensions to look at using: // GL_NV_map_buffer_range (same as GL_ARB_map_buffer_range ?) // WARNING: This gets memset-d - so no strings please struct GLExtensions { int ver[3]; + int gpuVendor; bool GLES3; // true if the full OpenGL ES 3.0 is supported bool OES_depth24; bool OES_packed_depth_stencil; From ce3eb186c7c63b2c802c9cea65846ff9e47a3163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 16 Oct 2013 11:29:58 +0200 Subject: [PATCH 0753/1445] Minor cleanup --- input/gesture_detector.cpp | 32 ++------------------------------ input/gesture_detector.h | 8 +++----- ui/viewgroup.h | 2 +- 3 files changed, 6 insertions(+), 36 deletions(-) diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index 6b919ab614..cd8b79a574 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -77,6 +77,8 @@ bool GestureDetector::GetGestureInfo(Gesture gesture, float info[4]) const { return false; } + memset(info, 0, sizeof(float) * 4); + switch (gesture) { case GESTURE_DRAG_HORIZONTAL: info[0] = pointers[0].lastX - pointers[0].downX; @@ -89,34 +91,4 @@ bool GestureDetector::GetGestureInfo(Gesture gesture, float info[4]) const { default: return false; } -/* - -bool down(int i, float *xdelta, float *ydelta) { - if (!pointers[i].down) { - return false; - } - *xdelta = pointers[i].downX; - *ydelta = pointers[i].downY; - return true; -} - -bool dragDistance(int i, float *xdelta, float *ydelta) { - if (!pointers[i].down) - return false; - - *xdelta = pointers[i].X - pointers[i].downX; - *ydelta = pointers[i].Y - pointers[i].downY; - return true; -} - -bool dragDelta(int i, float *xdelta, float *ydelta) { - if (!pointers[i].down) - return false; - - *xdelta = pointers[i].X - pointers[i].lastX; - *ydelta = pointers[i].Y - pointers[i].lastY; - return true; -} -*/ - } diff --git a/input/gesture_detector.h b/input/gesture_detector.h index f7fa15f171..f1a38ef874 100644 --- a/input/gesture_detector.h +++ b/input/gesture_detector.h @@ -1,9 +1,9 @@ #include "input/input_state.h" #include "math/geom2d.h" -// WIP - doesn't do much yet // Mainly for detecting (multi-)touch gestures but also useable for left button mouse dragging etc. - +// Currently only supports simple scroll-drags with inertia. +// TODO: Two-finger zoom/rotate etc. enum Gesture { GESTURE_DRAG_VERTICAL = 1, @@ -23,11 +23,9 @@ public: bool GetGestureInfo(Gesture gesture, float info[4]) const; private: - Bounds bounds_; - // jazzhands! enum Locals { - MAX_PTRS = 10 + MAX_PTRS = 10, }; struct Pointer { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index bd1c5a698c..8236baaf7a 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -188,7 +188,7 @@ private: class ScrollView : public ViewGroup { public: ScrollView(Orientation orientation, LayoutParams *layoutParams = 0) : - ViewGroup(layoutParams), + ViewGroup(layoutParams), orientation_(orientation), scrollPos_(0), scrollStart_(0), From d65859d16dfad501b945fe096c17d59e7eac48e3 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 17 Oct 2013 15:22:05 +1000 Subject: [PATCH 0754/1445] Support system language and region in Blackberry. --- base/BlackberryMain.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 460b143b39..01a74362cc 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -8,6 +8,7 @@ #include #include +#include // Get region and language #include "BlackberryMain.h" #include "base/NKCodeFromBlackberry.h" @@ -19,8 +20,12 @@ std::string System_GetProperty(SystemProperty prop) { std::string name = "Blackberry10:"; return name + ((pixel_xres != pixel_yres) ? "Touch" : "QWERTY"); } - case SYSPROP_LANGREGION: - return "en_US"; + case SYSPROP_LANGREGION: { + char *lang = 0; + char *region = 0; + region_get(&lang, ®ion); + return std::string(lang) + "_" + std::string(region); + } default: return ""; } From f08d4ccad56ed4a326bf0e1ce4614ffb70acdf54 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 17 Oct 2013 15:43:49 +1000 Subject: [PATCH 0755/1445] Correctly identify language and region on all Qt platforms. --- base/QtMain.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index df355de8d8..17afb92463 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef __SYMBIAN32__ #include @@ -40,8 +41,12 @@ std::string System_GetProperty(SystemProperty prop) { #else return "Qt"; #endif - case SYSPROP_LANGREGION: - return "en_US"; + case SYSPROP_LANGREGION: { + QString lang, region; + QSystemLocale::query(QSystemLocale::NativeLanguageName, lang); + QSystemLocale::query(QSystemLocale::NativeCountryName, region); + return lang.toStdString() + std::string("_") + region.toStdString(); + } default: return ""; } From 3b8f098e7a2df3b57e5e0efb9d9b410040edad15 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 17 Oct 2013 18:41:00 +1000 Subject: [PATCH 0756/1445] Use a better method for getting locale with Qt. Now works with Qt 4.7. --- base/QtMain.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 17afb92463..4c505fa9f1 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -41,12 +41,8 @@ std::string System_GetProperty(SystemProperty prop) { #else return "Qt"; #endif - case SYSPROP_LANGREGION: { - QString lang, region; - QSystemLocale::query(QSystemLocale::NativeLanguageName, lang); - QSystemLocale::query(QSystemLocale::NativeCountryName, region); - return lang.toStdString() + std::string("_") + region.toStdString(); - } + case SYSPROP_LANGREGION: + return QLocale::system().name().toStdString(); default: return ""; } From 6b48226f898382cebf89901977940a980502a119 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 19 Oct 2013 03:45:05 +1000 Subject: [PATCH 0757/1445] Buildfix for Qt on Windows. --- gfx_es2/draw_buffer.h | 2 ++ ui/view.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index d75febf6b5..88a62770e7 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -9,6 +9,8 @@ #include "gfx/texture_atlas.h" #include "math/geom2d.h" +#undef DrawText + struct Atlas; enum { diff --git a/ui/view.h b/ui/view.h index ee0f1cface..63daa9dbeb 100644 --- a/ui/view.h +++ b/ui/view.h @@ -22,6 +22,8 @@ #include "math/math_util.h" #include "math/geom2d.h" +#undef small + struct KeyInput; struct TouchInput; struct AxisInput; From 644b7816871673e6b9e9f441c2791f1bbe8e2cc5 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 19 Oct 2013 05:21:44 +1000 Subject: [PATCH 0758/1445] Make build work for Qt5 as well. --- base/QtMain.cpp | 4 ++-- base/QtMain.h | 24 +++--------------------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 4c505fa9f1..8b0264fa64 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -5,12 +5,12 @@ // Qt 4.7 implementation of the framework. // Currently supports: Symbian, Blackberry, Meego, Linux, Windows -#include +#include #include #include #include #include -#include +#include #ifdef __SYMBIAN32__ #include diff --git a/base/QtMain.h b/base/QtMain.h index 74ea9da4df..db7d4e078c 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -25,26 +25,6 @@ QTM_USE_NAMESPACE #include "base/NKCodeFromQt.h" // Input -const int buttonMappings[18] = { - Qt::Key_X + 0x20, //A - Qt::Key_S + 0x20, //B - Qt::Key_Z + 0x20, //X - Qt::Key_A + 0x20, //Y - Qt::Key_Q + 0x20, //LBUMPER - Qt::Key_W + 0x20, //RBUMPER - Qt::Key_1, //START - Qt::Key_2, //SELECT - Qt::Key_Up, //UP - Qt::Key_Down, //DOWN - Qt::Key_Left, //LEFT - Qt::Key_Right, //RIGHT - 0, //MENU (event) - Qt::Key_Backspace, //BACK - Qt::Key_I + 0x20, //JOY UP - Qt::Key_K + 0x20, //JOY DOWN - Qt::Key_J + 0x20, //JOY LEFT - Qt::Key_L + 0x20, //JOY RIGHT -}; void SimulateGamepad(InputState *input); //GUI @@ -56,7 +36,9 @@ public: QGLWidget(parent) { setAttribute(Qt::WA_AcceptTouchEvents); +#if QT_VERSION < 0x50000 setAttribute(Qt::WA_LockLandscapeOrientation); +#endif #ifdef USING_GLES2 acc = new QAccelerometer(this); acc->start(); @@ -205,7 +187,7 @@ class MainAudio: public QObject public: MainAudio() { QAudioFormat fmt; - fmt.setFrequency(AUDIO_FREQ); + fmt.setSampleRate(AUDIO_FREQ); fmt.setCodec("audio/pcm"); fmt.setChannelCount(AUDIO_CHANNELS); fmt.setSampleSize(AUDIO_SAMPLESIZE); From de16f5863d2493b240003cbc2d6d198553b27f11 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 19 Oct 2013 12:45:58 +0200 Subject: [PATCH 0759/1445] Initialize a variable --- gfx_es2/draw_buffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 20413f2bdd..99b73a6c96 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -23,7 +23,7 @@ enum { // #define USE_VBO -DrawBuffer::DrawBuffer() : count_(0), atlas(0) { +DrawBuffer::DrawBuffer() : count_(0), atlas(0), program_(0) { verts_ = new Vertex[MAX_VERTS]; fontscalex = 1.0f; fontscaley = 1.0f; From 70af7173e09d59e7e7daef188122f793f5dac1b4 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 20 Oct 2013 05:03:31 +1000 Subject: [PATCH 0760/1445] Linux Qt5 fix. --- base/QtMain.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 8b0264fa64..8bc4ba51ed 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -19,10 +19,6 @@ #endif #include "QtMain.h" -#if defined(Q_WS_X11) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(__SYMBIAN32__) && !defined(BLACKBERRY) -#define X11LINUXDESKTOP -#endif - InputState* input_state; std::string System_GetProperty(SystemProperty prop) { @@ -34,7 +30,7 @@ std::string System_GetProperty(SystemProperty prop) { return "Qt:Blackberry10"; #elif defined(MEEGO_EDITION_HARMATTAN) return "Qt:Meego"; -#elif defined(Q_WS_X11) +#elif defined(Q_OS_LINUX) return "Qt:Linux"; #elif defined(_WIN32) return "Qt:Windows"; @@ -106,7 +102,7 @@ float CalculateDPIScale() Q_DECL_EXPORT int main(int argc, char *argv[]) { -#ifdef Q_WS_X11 +#ifdef Q_OS_LINUX QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); @@ -115,7 +111,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); -#ifdef X11LINUXDESKTOP +#if defined(Q_OS_LINUX) && !defined(ARM) g_dpi_scale = 1.0f; #else g_dpi_scale = CalculateDPIScale(); @@ -140,7 +136,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) #endif NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); -#if !defined(Q_WS_X11) || defined(ARM) +#if !defined(Q_OS_LINUX) || defined(ARM) MainUI w; w.resize(pixel_xres, pixel_yres); w.showFullScreen(); From 29e6114fe1a9dad15ff86088480bfd63725f9022 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Oct 2013 12:37:54 -0700 Subject: [PATCH 0761/1445] Qt: Don't crash if audio feed is null. --- base/QtMain.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index db7d4e078c..1f64470aef 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -198,11 +198,14 @@ public: output = new QAudioOutput(fmt); output->setBufferSize(mixlen); feed = output->start(); - timer = startTimer(1000*AUDIO_SAMPLES / AUDIO_FREQ); + if (feed != NULL) + timer = startTimer(1000*AUDIO_SAMPLES / AUDIO_FREQ); } ~MainAudio() { - killTimer(timer); - feed->close(); + if (feed != NULL) { + killTimer(timer); + feed->close(); + } output->stop(); delete output; free(mixbuf); From ab7638a983d3255e3ad7bc2c3518dfe86ecce155 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Oct 2013 14:24:46 -0700 Subject: [PATCH 0762/1445] Fix some initialization order warnings. --- gfx_es2/draw_buffer.cpp | 2 +- net/http_client.cpp | 4 ++-- ui/ui_screen.cpp | 4 ++-- ui/view.h | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 99b73a6c96..d27bf439f1 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -23,7 +23,7 @@ enum { // #define USE_VBO -DrawBuffer::DrawBuffer() : count_(0), atlas(0), program_(0) { +DrawBuffer::DrawBuffer() : program_(0), count_(0), atlas(0) { verts_ = new Vertex[MAX_VERTS]; fontscalex = 1.0f; fontscaley = 1.0f; diff --git a/net/http_client.cpp b/net/http_client.cpp index 37a53b9d30..6671e5070c 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -27,7 +27,7 @@ namespace net { Connection::Connection() - : port_(-1), sock_(-1), resolved_(NULL) { + : port_(-1), resolved_(NULL), sock_(-1) { } Connection::~Connection() { @@ -286,7 +286,7 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) } Download::Download(const std::string &url, const std::string &outfile) - : url_(url), outfile_(outfile), progress_(0.0f), failed_(false), resultCode_(0), cancelled_(false) { + : progress_(0.0f), url_(url), outfile_(outfile), resultCode_(0), failed_(false), cancelled_(false) { } Download::~Download() { diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 1b2c908442..a92b06dd51 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -101,7 +101,7 @@ UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { } PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2) - : title_(title), box_(0) { + : box_(0), title_(title) { I18NCategory *d = GetI18NCategory("Dialog"); button1_ = d->T(button1.c_str()); button2_ = d->T(button2.c_str()); @@ -286,4 +286,4 @@ void SliderFloatPopupScreen::OnCompleted(DialogResult result) { *value_ = sliderValue_; } -} // namespace UI \ No newline at end of file +} // namespace UI diff --git a/ui/view.h b/ui/view.h index 63daa9dbeb..166a45735b 100644 --- a/ui/view.h +++ b/ui/view.h @@ -510,12 +510,12 @@ public: class Choice : public ClickableItem { public: Choice(const std::string &text, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), selected_(false), centered_(false), highlighted_(false) {} + : ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), centered_(false), highlighted_(false), selected_(false) {} Choice(const std::string &text, const std::string &smallText, bool selected = false, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), selected_(selected), centered_(false), highlighted_(false) {} + : ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), centered_(false), highlighted_(false), selected_(selected) {} Choice(ImageID image, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), atlasImage_(image), selected_(false), highlighted_(false) {} + : ClickableItem(layoutParams), atlasImage_(image), centered_(false), highlighted_(false), selected_(false) {} virtual void HighlightChanged(bool highlighted); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; From 774fa8f73ec0d8b7a0d4e0c11c82b0d7b2900270 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Oct 2013 14:29:05 -0700 Subject: [PATCH 0763/1445] Fix some switch/case warnings. --- ui/ui_context.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index a34d881f93..77d6df6aba 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -185,5 +185,7 @@ void UIContext::FillRect(const UI::Drawable &drawable, const Bounds &bounds) { case UI::DRAW_STRETCH_IMAGE: uidrawbuffer_->DrawImageStretch(drawable.image, bounds.x, bounds.y, bounds.x2(), bounds.y2(), drawable.color); break; + case UI::DRAW_NOTHING: + break; } -} \ No newline at end of file +} From 31690a3910064b9bb7dcd8eff14c5166f8fa6a93 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Oct 2013 14:29:32 -0700 Subject: [PATCH 0764/1445] Fix some type comparison warnings. --- ui/view.cpp | 2 +- ui/viewgroup.cpp | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 54745f8b35..5cf204736a 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -51,7 +51,7 @@ void DispatchEvents() { } void RemoveQueuedEvents(View *v) { - for (int i = 0; i < g_dispatchQueue.size(); i++) { + for (size_t i = 0; i < g_dispatchQueue.size(); i++) { if (g_dispatchQueue[i].params.v == v) g_dispatchQueue.erase(g_dispatchQueue.begin() + i); } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index e06a2bbf79..37709b42fa 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -180,6 +180,10 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio //if (fabsf(dirX) > fabsf(dirY)) return 0.0f; distance = dirY / sqrtf(distance); break; + case FOCUS_PREV: + case FOCUS_NEXT: + ELOG("Invalid focus direction"); + break; } return distance; @@ -193,10 +197,10 @@ NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, Nei return result; // First, find the position of the view in the list. - size_t num = -1; + int num = -1; for (size_t i = 0; i < views_.size(); i++) { if (views_[i] == view) { - num = i; + num = (int)i; break; } } @@ -888,7 +892,7 @@ void ChoiceStrip::SetSelection(int sel) { void ChoiceStrip::HighlightChoice(unsigned int choice){ - if (choice < (int)views_.size()){ + if (choice < (unsigned int)views_.size()){ static_cast(views_[choice])->HighlightChanged(true); } From 5406579d6df0a08c5dc5e57a761580f17523142b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Oct 2013 14:36:55 -0700 Subject: [PATCH 0765/1445] Fix some const usage warnings. --- base/QtMain.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 8bc4ba51ed..88df57123c 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -119,20 +119,20 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); #ifdef __SYMBIAN32__ - char* savegame_dir = "E:/PPSSPP/"; - char* assets_dir = "E:/PPSSPP/"; + const char *savegame_dir = "E:/PPSSPP/"; + cosnt char *assets_dir = "E:/PPSSPP/"; #elif defined(BLACKBERRY) - char* savegame_dir = "/accounts/1000/shared/misc/"; - char* assets_dir = "app/native/assets/"; + const char *savegame_dir = "/accounts/1000/shared/misc/"; + const char *assets_dir = "app/native/assets/"; #elif defined(MEEGO_EDITION_HARMATTAN) - char* savegame_dir = "/home/user/MyDocs/PPSSPP/"; + const char *savegame_dir = "/home/user/MyDocs/PPSSPP/"; QDir myDocs("/home/user/MyDocs/"); if (!myDocs.exists("PPSSPP")) myDocs.mkdir("PPSSPP"); - char* assets_dir = "/opt/PPSSPP/"; + const char *assets_dir = "/opt/PPSSPP/"; #else - char* savegame_dir = "./"; - char* assets_dir = "./"; + const char *savegame_dir = "./"; + const char *assets_dir = "./"; #endif NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); From 40e820b90516c9885443c5445473a69a33cf6d56 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Oct 2013 22:36:04 -0700 Subject: [PATCH 0766/1445] Dumb typo. --- base/QtMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 88df57123c..9fbefe9a3a 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -120,7 +120,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) net::Init(); #ifdef __SYMBIAN32__ const char *savegame_dir = "E:/PPSSPP/"; - cosnt char *assets_dir = "E:/PPSSPP/"; + const char *assets_dir = "E:/PPSSPP/"; #elif defined(BLACKBERRY) const char *savegame_dir = "/accounts/1000/shared/misc/"; const char *assets_dir = "app/native/assets/"; From 06a7ad40b298d815acbd5839a0e77258358ce015 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 20 Oct 2013 16:39:22 +1000 Subject: [PATCH 0767/1445] This define is redundant. __STDC_CONSTANT_MACROS should be defined globally instead. --- ext/cityhash/city.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 6b73ebe944..54cc2a727c 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -58,8 +58,6 @@ static uint32 UNALIGNED_LOAD32(const char *p) { #define bswap_32(x) OSSwapInt32(x) #define bswap_64(x) OSSwapInt64(x) #else -// Otherwise it doesn't exist (Symbian, Blackberry10) -#define UINT64_C(c) static_cast(c ## ULL) #define bswap_32(x) (0 | ((x & 0x000000ff) << 24) \ | ((x & 0x0000ff00) << 8) \ | ((x & 0x00ff0000) >> 8) \ From f8cab66c8c2eadbb9c8bdba515d76e946750e08e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 20 Oct 2013 13:18:56 +0200 Subject: [PATCH 0768/1445] Quickfix for android build (weirdly, works locally but not on teamcity) --- ext/cityhash/city.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 54cc2a727c..c1c932366c 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -58,6 +58,9 @@ static uint32 UNALIGNED_LOAD32(const char *p) { #define bswap_32(x) OSSwapInt32(x) #define bswap_64(x) OSSwapInt64(x) #else +#if defined(ANDROID) && !defined(UINT64_C) +#define UINT64_C(c) static_cast(c ## ULL) +#endif #define bswap_32(x) (0 | ((x & 0x000000ff) << 24) \ | ((x & 0x0000ff00) << 8) \ | ((x & 0x00ff0000) >> 8) \ From c1f05326c45a31c7e54464754c0f654cd2e2caaf Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 20 Oct 2013 13:51:10 +0200 Subject: [PATCH 0769/1445] Better fix for the UINT_64 errors. --- Android.mk | 2 +- ext/cityhash/city.cpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Android.mk b/Android.mk index a7cb3c08db..057b234b60 100644 --- a/Android.mk +++ b/Android.mk @@ -80,7 +80,7 @@ LOCAL_SRC_FILES :=\ util/text/utf8.cpp \ util/hash/hash.cpp -LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -Wall -Wno-multichar +LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -Wall -Wno-multichar -D__STDC_CONSTANT_MACROS LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -fno-rtti -Wno-reorder -Wno-literal-suffix LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index c1c932366c..54cc2a727c 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -58,9 +58,6 @@ static uint32 UNALIGNED_LOAD32(const char *p) { #define bswap_32(x) OSSwapInt32(x) #define bswap_64(x) OSSwapInt64(x) #else -#if defined(ANDROID) && !defined(UINT64_C) -#define UINT64_C(c) static_cast(c ## ULL) -#endif #define bswap_32(x) (0 | ((x & 0x000000ff) << 24) \ | ((x & 0x0000ff00) << 8) \ | ((x & 0x00ff0000) >> 8) \ From 5e0c4bc0a6df88300bc188b8f74a6a3626e68923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 20 Oct 2013 15:33:07 +0200 Subject: [PATCH 0770/1445] Just a sanity check --- ui/screen.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index d91d083e69..02ddf917b5 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -14,12 +14,16 @@ ScreenManager::~ScreenManager() { } void ScreenManager::switchScreen(Screen *screen) { + if (screen == nextScreen_) { + ELOG("Already switching to this screen"); + return; + } // Note that if a dialog is found, this will be a silent background switch that // will only become apparent if the dialog is closed. The previous screen will stick around // until that switch. // TODO: is this still true? if (nextScreen_ != 0) { - FLOG("WTF? Already had a nextScreen_"); + FLOG("Already had a nextScreen_"); } if (screen == 0) { WLOG("Swiching to a zero screen, this can't be good"); From e783dbd76bbffdd704bf409bb1a53297cb332a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 20 Oct 2013 19:39:54 +0200 Subject: [PATCH 0771/1445] Move the highlight when changing the current tab --- ui/viewgroup.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 8236baaf7a..183dc052b2 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -291,6 +291,7 @@ public: tabs_[currentTab_]->SetVisibility(V_GONE); currentTab_ = tab; tabs_[currentTab_]->SetVisibility(V_VISIBLE); + tabStrip_->SetSelection(tab); } int GetCurrentTab() const { return currentTab_; } From fff83ed237576c2132e5240de11963660b3f0315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 21 Oct 2013 11:00:09 +0200 Subject: [PATCH 0772/1445] Fix bug causing clickables not to highlight on mousedown in SDL builds --- ui/view.cpp | 20 +++++++++----------- ui/view.h | 1 - 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 5cf204736a..4341846563 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -169,7 +169,6 @@ void Clickable::FocusChanged(int focusFlags) { } } - void Clickable::Touch(const TouchInput &input) { if (!enabled_) { dragging_ = false; @@ -190,12 +189,12 @@ void Clickable::Touch(const TouchInput &input) { } else if (input.flags & TOUCH_MOVE) { if (dragging_) down_ = bounds_.Contains(input.x, input.y); - } + } if (input.flags & TOUCH_UP) { if ((input.flags & TOUCH_CANCEL) == 0 && dragging_ && bounds_.Contains(input.x, input.y)) { Click(); } - down_ = false; + down_ = false; downCountDown_ = 0; dragging_ = false; } @@ -212,7 +211,7 @@ bool IsEscapeKeyCode(int keyCode) { } void Clickable::Key(const KeyInput &key) { - if (!HasFocus()) { + if (!HasFocus() && key.deviceId != DEVICE_ID_MOUSE) { down_ = false; return; } @@ -285,7 +284,7 @@ void ClickableItem::GetContentDimensions(const UIContext &dc, float &w, float &h } ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParams) { - if (layoutParams_->width == WRAP_CONTENT) + if (layoutParams_->width == WRAP_CONTENT) layoutParams_->width = FILL_PARENT; layoutParams_->height = ITEM_HEIGHT; } @@ -299,7 +298,7 @@ void ClickableItem::Draw(UIContext &dc) { if (down_) { style = dc.theme->itemDownStyle; } - + dc.FillRect(style.background, bounds_); } @@ -315,10 +314,9 @@ void Choice::GetContentDimensions(const UIContext &dc, float &w, float &h) const h += 16; } - void Choice::HighlightChanged(bool highlighted){ - highlighted_ = highlighted; - }; - +void Choice::HighlightChanged(bool highlighted){ + highlighted_ = highlighted; +} void Choice::Draw(UIContext &dc) { if (!IsSticky()) { @@ -401,7 +399,7 @@ void CheckBox::Draw(UIContext &dc) { Style style = dc.theme->itemStyle; if (!IsEnabled()) style = dc.theme->itemDisabledStyle; - + dc.SetFontStyle(dc.theme->uiFont); dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); dc.Draw()->DrawImage(image, bounds_.x2() - paddingX, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); diff --git a/ui/view.h b/ui/view.h index 166a45735b..21917238f3 100644 --- a/ui/view.h +++ b/ui/view.h @@ -513,7 +513,6 @@ public: : ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), centered_(false), highlighted_(false), selected_(false) {} Choice(const std::string &text, const std::string &smallText, bool selected = false, LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), centered_(false), highlighted_(false), selected_(selected) {} - Choice(ImageID image, LayoutParams *layoutParams = 0) : ClickableItem(layoutParams), atlasImage_(image), centered_(false), highlighted_(false), selected_(false) {} From 887d140d55087bb1a829ef9bd1f9d1afdf7adb73 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 21 Oct 2013 22:44:07 +1000 Subject: [PATCH 0773/1445] Qt:Use ARM to define mobile platform. Don't show fullscreen on Windows. --- base/QtMain.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 9fbefe9a3a..92668ba963 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -111,10 +111,10 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); -#if defined(Q_OS_LINUX) && !defined(ARM) - g_dpi_scale = 1.0f; -#else +#ifdef ARM g_dpi_scale = CalculateDPIScale(); +#else + g_dpi_scale = 1.0f; #endif dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); @@ -139,7 +139,11 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) #if !defined(Q_OS_LINUX) || defined(ARM) MainUI w; w.resize(pixel_xres, pixel_yres); +#ifdef ARM w.showFullScreen(); +#else + w.show(); +#endif #endif #ifdef __SYMBIAN32__ // Set RunFast hardware mode for VFPv2. From edab3dc0fb04af493592abb31effedec1388b049 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 22 Oct 2013 01:35:03 +1000 Subject: [PATCH 0774/1445] Fix Qt Audio. --- base/QtMain.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index 1f64470aef..cf88bb9219 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -192,8 +192,8 @@ public: fmt.setChannelCount(AUDIO_CHANNELS); fmt.setSampleSize(AUDIO_SAMPLESIZE); fmt.setByteOrder(QAudioFormat::LittleEndian); - fmt.setSampleType(QAudioFormat::SignedInt); - mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; + fmt.setSampleType(QAudioFormat::Float); + mixlen = 4*AUDIO_CHANNELS*AUDIO_SAMPLES; mixbuf = (char*)malloc(mixlen); output = new QAudioOutput(fmt); output->setBufferSize(mixlen); From dbef0b21a90f23477371066f7dcdc7056d8a3371 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 22 Oct 2013 03:58:56 +1000 Subject: [PATCH 0775/1445] Fix #2 for Qt Audio. Increase samples as it seems to sound much better. --- base/QtMain.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index cf88bb9219..b3509a874c 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -179,7 +179,7 @@ private: // Audio #define AUDIO_FREQ 44100 #define AUDIO_CHANNELS 2 -#define AUDIO_SAMPLES 1024 +#define AUDIO_SAMPLES 2048 #define AUDIO_SAMPLESIZE 16 class MainAudio: public QObject { @@ -192,7 +192,7 @@ public: fmt.setChannelCount(AUDIO_CHANNELS); fmt.setSampleSize(AUDIO_SAMPLESIZE); fmt.setByteOrder(QAudioFormat::LittleEndian); - fmt.setSampleType(QAudioFormat::Float); + fmt.setSampleType(QAudioFormat::SignedInt); mixlen = 4*AUDIO_CHANNELS*AUDIO_SAMPLES; mixbuf = (char*)malloc(mixlen); output = new QAudioOutput(fmt); From 6986edb978bbd104c7d0845dd567cf36f1b3c7fb Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 22 Oct 2013 13:29:34 +1000 Subject: [PATCH 0776/1445] Audio: Best settings on all platforms. After numerous tests, I have found the perfect audio settings. It seems samples now needs to be 2048 for everyone. Buffer needs to be 8192. Anything else gets a patchy noise. None of these platforms were using the right audio settings. Qt and SDL now sound perfect but Blackberry still doesn't (OpenAL thing?). --- base/BlackberryAudio.h | 16 +++++++++------- base/PCMain.cpp | 2 +- base/QtMain.h | 4 ++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/base/BlackberryAudio.h b/base/BlackberryAudio.h index 4911be23d3..6856c5aaaf 100644 --- a/base/BlackberryAudio.h +++ b/base/BlackberryAudio.h @@ -11,7 +11,8 @@ #include "base/NativeApp.h" -#define SAMPLE_SIZE 44100 +#define AUDIO_FREQ 44100 +#define SAMPLE_SIZE 2048 class BlackberryAudio { public: @@ -53,22 +54,23 @@ private: { size_t frames_ready; alGetSourcei(source, AL_SOURCE_STATE, &state); - if (state != AL_PLAYING) - frames_ready = NativeMix(stream, SAMPLE_SIZE / 2); + if (state != AL_PLAYING) { + frames_ready = NativeMix((short*)stream, SAMPLE_SIZE); + } else frames_ready = 0; if (frames_ready > 0) { const size_t bytes_ready = frames_ready * sizeof(short) * 2; alSourcei(source, AL_BUFFER, 0); - alBufferData(buffer, AL_FORMAT_STEREO16, stream, bytes_ready, SAMPLE_SIZE); + alBufferData(buffer, AL_FORMAT_STEREO16, stream, bytes_ready, AUDIO_FREQ); alSourcei(source, AL_BUFFER, buffer); alSourcePlay(source); // TODO: Maybe this could get behind? - usleep((1000000 * frames_ready) / SAMPLE_SIZE); + usleep((1000000 * frames_ready) / AUDIO_FREQ); } else - usleep(100); + usleep(100000); } } ALCdevice *alcDevice; @@ -76,7 +78,7 @@ private: ALenum state; ALuint buffer; ALuint source; - short stream[SAMPLE_SIZE]; + char stream[4*SAMPLE_SIZE]; pthread_t thread_handle; }; #endif diff --git a/base/PCMain.cpp b/base/PCMain.cpp index c40f469581..32d0dcf87b 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -523,7 +523,7 @@ int main(int argc, char *argv[]) { fmt.freq = 44100; fmt.format = AUDIO_S16; fmt.channels = 2; - fmt.samples = 1024; + fmt.samples = 2048; fmt.callback = &mixaudio; fmt.userdata = (void *)0; diff --git a/base/QtMain.h b/base/QtMain.h index b3509a874c..834eb67ca3 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -193,7 +193,7 @@ public: fmt.setSampleSize(AUDIO_SAMPLESIZE); fmt.setByteOrder(QAudioFormat::LittleEndian); fmt.setSampleType(QAudioFormat::SignedInt); - mixlen = 4*AUDIO_CHANNELS*AUDIO_SAMPLES; + mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; mixbuf = (char*)malloc(mixlen); output = new QAudioOutput(fmt); output->setBufferSize(mixlen); @@ -214,7 +214,7 @@ public: protected: void timerEvent(QTimerEvent *) { memset(mixbuf, 0, mixlen); - NativeMix((short *)mixbuf, mixlen / 4); + NativeMix((short *)mixbuf, AUDIO_SAMPLES); feed->write(mixbuf, mixlen); } private: From 30edf6b894488167607b7148c18910be005debaa Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 22 Oct 2013 14:52:14 +1000 Subject: [PATCH 0777/1445] Simply stick the Qt audio in a thread. It will now run flawlessly at low frame rates or frameskipping as well. --- base/QtMain.cpp | 6 ++++++ base/QtMain.h | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 92668ba963..aab67674a1 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef __SYMBIAN32__ #include @@ -155,10 +156,15 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) vibra = CHWRMVibra::NewL(); #endif + QThread* thread = new QThread; MainAudio *audio = new MainAudio(); + audio->moveToThread(thread); + QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + thread->start(); int ret = a.exec(); delete audio; + thread->quit(); #ifdef __SYMBIAN32__ delete vibra; #endif diff --git a/base/QtMain.h b/base/QtMain.h index 834eb67ca3..76bde0c716 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -214,8 +214,9 @@ public: protected: void timerEvent(QTimerEvent *) { memset(mixbuf, 0, mixlen); - NativeMix((short *)mixbuf, AUDIO_SAMPLES); - feed->write(mixbuf, mixlen); + size_t frames = NativeMix((short *)mixbuf, AUDIO_SAMPLES); + if (frames > 0) + feed->write(mixbuf, sizeof(short) * 2 * frames); } private: QIODevice* feed; From b9c5c5fc3d61b5f933b34a542985f6723ee60737 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 23 Oct 2013 04:10:32 +1000 Subject: [PATCH 0778/1445] Crash fix for Symbian. Will have to put up with crummy music a little bit longer. --- base/QtMain.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index aab67674a1..cc6d552041 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -156,17 +156,22 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) vibra = CHWRMVibra::NewL(); #endif +#ifdef __SYMBIAN32__ + MainAudio *audio = new MainAudio(); +#else QThread* thread = new QThread; MainAudio *audio = new MainAudio(); audio->moveToThread(thread); QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); +#endif int ret = a.exec(); delete audio; - thread->quit(); #ifdef __SYMBIAN32__ delete vibra; +#else + thread->quit(); #endif NativeShutdown(); net::Shutdown(); From 404652ab0b63137b621a618cb18354ccc86e9895 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 23 Oct 2013 14:55:20 +1000 Subject: [PATCH 0779/1445] Clean up all the #ifdef's and GLES3 mess. Only Android and Blackberry (and later IOS) can run GLES3, so we'll just define those. --- gfx/gl_common.h | 26 +++++++++++--------------- gfx_es2/fbo.cpp | 4 ++-- gfx_es2/gl3stub.c | 6 +++--- gfx_es2/gl3stub.h | 4 ---- gfx_es2/gl_state.cpp | 16 +++++++--------- gfx_es2/gl_state.h | 2 +- 6 files changed, 24 insertions(+), 34 deletions(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index cc52df5996..b0856306f8 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -2,31 +2,27 @@ #define _GL_COMMON_H #if defined(USING_GLES2) -#if defined(IOS) +#ifdef IOS +// I guess we can soon add ES 3.0 here too #include #include - -// I guess we can soon add ES 3.0 here too - #else - +#include +#include +#ifndef MAEMO +#include +#endif // !MAEMO +#endif // IOS +#if defined(ANDROID) || defined(BLACKBERRY) // Support OpenGL ES 3.0 // This uses the "DYNAMIC" approach from the gles3jni NDK sample. // Should work on non-Android mobile platforms too. #include "../gfx_es2/gl3stub.h" #define MAY_HAVE_GLES3 1 -// Old way: #include - -#include -#ifndef MAEMO -#include -#endif - #endif #else // OpenGL -// Now that glew is upgraded beyond 4.3, we can define MAY_HAVE_GLES3 on all platforms -// that include glew. -#define MAY_HAVE_GLES3 +// Now that glew is upgraded beyond 4.3, we can define MAY_HAVE_GLES3 on GL platforms +#define MAY_HAVE_GLES3 1 #include #if defined(__APPLE__) #include diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index a8e175280d..4e767d120b 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -6,7 +6,7 @@ #include "gfx/gl_common.h" #include "gfx_es2/gl_state.h" -#if defined(USING_GLES2) +#if defined(USING_GLES2) && !defined(BLACKBERRY) #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER #define GL_RGBA8 GL_RGBA @@ -301,4 +301,4 @@ void fbo_get_dimensions(FBO *fbo, int *w, int *h) { int fbo_get_color_texture(FBO *fbo) { return fbo->color_texture; -} \ No newline at end of file +} diff --git a/gfx_es2/gl3stub.c b/gfx_es2/gl3stub.c index 5e5d9abec5..dd47a49e75 100644 --- a/gfx_es2/gl3stub.c +++ b/gfx_es2/gl3stub.c @@ -14,11 +14,11 @@ * limitations under the License. */ -#ifndef IOS +#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) -#include "gl3stub.h" +#include "../gfx/gl_common.h" -#if defined(USING_GLES2) && !defined(__SYMBIAN32__) +#if defined(USING_GLES2) GLboolean gl3stubInit() { #define FIND_PROC(s) s = (void*)eglGetProcAddress(#s) diff --git a/gfx_es2/gl3stub.h b/gfx_es2/gl3stub.h index 2d2aa682ca..2cfb91a7da 100644 --- a/gfx_es2/gl3stub.h +++ b/gfx_es2/gl3stub.h @@ -6,7 +6,6 @@ * gl3.h last updated on $Date: 2013-02-12 14:37:24 -0800 (Tue, 12 Feb 2013) $ * * Changes: - * - Added #include * - Removed duplicate OpenGL ES 2.0 declarations * - Converted OpenGL ES 3.0 function prototypes to function pointer * declarations @@ -14,8 +13,6 @@ */ #if defined(USING_GLES2) -#include -#if !defined(__SYMBIAN32__) #ifdef __cplusplus extern "C" { @@ -490,7 +487,6 @@ extern GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum t } #endif -#endif // !__SYMBIAN32__ #endif // USING_GLES2 #endif diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 364538ab32..c66dd4d4e3 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -15,8 +15,7 @@ PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; PFNGLDRAWTEXTURENVPROC glDrawTextureNV; PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV ; PFNGLMAPBUFFERPROC glMapBuffer; -#endif -#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) + PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; @@ -159,8 +158,8 @@ void CheckGLExtensions() { #endif #if defined(USING_GLES2) -// MAY_HAVE_GLES3 defined on all platforms, maybe redundant. Otherwise exclude platforms like Symbian, Meego, Raspberry Pi -#if defined(MAY_HAVE_GLES3) && !defined(__SYMBIAN32__) + // MAY_HAVE_GLES3 defined on all platforms that support it +#if defined(MAY_HAVE_GLES3) // Try to load GLES 3.0 only if "3.0" found in version // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited // number of times. @@ -214,10 +213,7 @@ void CheckGLExtensions() { gl_extensions.EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0); gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; -#if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) - gl_extensions.OES_vertex_array_object = false; - gl_extensions.EXT_discard_framebuffer = false; -#else +#if defined(ANDROID) || defined(BLACKBERRY) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. // https://twitter.com/ID_AA_Carmack/status/387383037794603008 void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1"); @@ -243,7 +239,9 @@ void CheckGLExtensions() { if (gl_extensions.EXT_discard_framebuffer) { glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); } - +#else + gl_extensions.OES_vertex_array_object = false; + gl_extensions.EXT_discard_framebuffer = false; #endif #else // Desktops support minmax diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 60bef80e4c..249bb4dfc4 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -53,7 +53,7 @@ typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum extern PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV; #endif -#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) +#if defined(ANDROID) || defined(BLACKBERRY) extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; From 72f980d456b910e288f7bf1c40425ab12b5c349f Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 23 Oct 2013 14:59:50 +1000 Subject: [PATCH 0780/1445] Remove QCOM_binning_control detection. Qualcomm suggests not to use the extension as the GPU automatically chooses the optimal output (on-the-fly) anyway. Also, each option causes crashes on every Adreno I have tested. --- gfx_es2/gl_state.cpp | 1 - gfx_es2/gl_state.h | 7 ------- 2 files changed, 8 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index c66dd4d4e3..5849ac4f0c 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -253,7 +253,6 @@ void CheckGLExtensions() { glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" ); } - gl_extensions.QCOM_binning_control = strstr(extString, "GL_QCOM_binning_control") != 0; gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0; // Load extensions that are not auto-loaded by Android. if (gl_extensions.QCOM_alpha_test) { diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 249bb4dfc4..f812d6e2a6 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -23,12 +23,6 @@ #define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 #define GL_ALPHA_TEST_REF_QCOM 0x0BC2 -/* GL_QCOM_binning_control */ -#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0 -#define GL_CPU_OPTIMIZED_QCOM 0x8FB1 -#define GL_GPU_OPTIMIZED_QCOM 0x8FB2 -#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3 - typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); extern PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; @@ -336,7 +330,6 @@ struct GLExtensions { bool PBO_ARB; bool EXT_swap_control_tear; bool QCOM_alpha_test; - bool QCOM_binning_control; bool OES_mapbuffer; bool OES_vertex_array_object; bool EXT_shader_framebuffer_fetch; From 4d49541aa532b99f17b2edbd836198c5e9143ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 23 Oct 2013 12:29:09 +0200 Subject: [PATCH 0781/1445] apple buildfix --- gfx/gl_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index b0856306f8..f209aa26f4 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -31,7 +31,7 @@ #endif #endif -#ifndef GLchar +#if !defined(GLchar) && !defined(__APPLE__) typedef char GLchar; #endif From 4c8157694a60e4922818431d73da9a3f983b343e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 23 Oct 2013 13:55:11 +0200 Subject: [PATCH 0782/1445] Make keyboard navigation act slightly less crazy. --- ui/screen.cpp | 3 ++ ui/screen.h | 5 +++ ui/view.h | 2 +- ui/viewgroup.cpp | 82 ++++++++++++++++++++++++++++++++++++------------ ui/viewgroup.h | 2 +- 5 files changed, 72 insertions(+), 22 deletions(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index 02ddf917b5..e36fc30fa1 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -2,6 +2,7 @@ #include "input/input_state.h" #include "ui/screen.h" #include "ui/ui.h" +#include "ui/view.h" ScreenManager::ScreenManager() { nextScreen_ = 0; @@ -60,6 +61,7 @@ void ScreenManager::switchToNext() { delete temp.screen; } nextScreen_ = 0; + UI::SetFocusedView(0); } void ScreenManager::touch(const TouchInput &touch) { @@ -148,6 +150,7 @@ void ScreenManager::push(Screen *screen, int layerFlags) { if (screen->isTransparent()) { layerFlags |= LAYER_TRANSPARENT; } + UI::SetFocusedView(0); Layer layer = {screen, layerFlags}; stack_.push_back(layer); } diff --git a/ui/screen.h b/ui/screen.h index bd0e871acc..1c0ce0b67c 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -20,6 +20,10 @@ #include "base/display.h" #include "base/NativeApp.h" +namespace UI { + class View; +} + struct InputState; enum DialogResult { @@ -121,6 +125,7 @@ private: struct Layer { Screen *screen; int flags; // From LAYER_ enum above + UI::View *focusedView; // TODO: save focus here. Going for quick solution now to reset focus. }; // Dialog stack. These are shown "on top" of base screens and the Android back button works as expected. diff --git a/ui/view.h b/ui/view.h index 21917238f3..6b9413731b 100644 --- a/ui/view.h +++ b/ui/view.h @@ -1,6 +1,6 @@ #pragma once -// More traditional UI framework than ui/ui.h. +// More traditional UI framework than ui/ui.h. // Still very simple to use. diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 37709b42fa..2f130d2a7d 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -14,6 +14,9 @@ namespace UI { const float ITEM_HEIGHT = 64.f; +static recursive_mutex focusLock; +static std::vector focusMoves; + void ApplyGravity(const Bounds outer, const Margins &margins, float w, float h, int gravity, Bounds &inner) { inner.w = w - (margins.left + margins.right); inner.h = h - (margins.right + margins.left); @@ -140,6 +143,33 @@ bool ViewGroup::SubviewFocused(View *view) { return false; } +static float HorizontalOverlap(const Bounds &a, const Bounds &b) { + if (a.x2() < b.x || b.x2() < a.x) + return 0.0f; + // okay they do overlap. Let's clip. + float maxMin = std::max(a.x, b.x); + float minMax = std::min(a.x2(), b.x2()); + float overlap = minMax - maxMin; + if (overlap < 0.0f) + return 0.0f; + else + return std::min(1.0f, overlap / std::min(a.w, b.w)); +} + +// Returns the percentage the smaller one overlaps the bigger one. +static float VerticalOverlap(const Bounds &a, const Bounds &b) { + if (a.y2() < b.y || b.y2() < a.y) + return 0.0f; + // okay they do overlap. Let's clip. + float maxMin = std::max(a.y, b.y); + float minMax = std::min(a.y2(), b.y2()); + float overlap = minMax - maxMin; + if (overlap < 0.0f) + return 0.0f; + else + return std::min(1.0f, overlap / std::min(a.h, b.h)); +} + float GetDirectionScore(View *origin, View *destination, FocusDirection direction) { // Skip labels and things like that. if (!destination->CanBeFocused()) @@ -155,30 +185,42 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio float dx = destPos.x - originPos.x; float dy = destPos.y - originPos.y; - float distance = sqrtf(dx*dx+dy*dy); + float distance = sqrtf(dx*dx + dy*dy); + float overlap = 0.0f; float dirX = dx / distance; float dirY = dy / distance; + bool wrongDirection = false; + float horizOverlap = HorizontalOverlap(origin->GetBounds(), destination->GetBounds()); + float vertOverlap = VerticalOverlap(origin->GetBounds(), destination->GetBounds()); + if (horizOverlap == 1.0f && vertOverlap == 1.0f) { + ILOG("Contain overlap"); + return 0.0; + } switch (direction) { case FOCUS_LEFT: - distance = -dirX / sqrtf(distance); - //if (dirX > 0.0f) return 0.0f; - //if (fabsf(dirY) > fabsf(dirX)) return 0.0f; + overlap = vertOverlap; + if (dirX > 0.0f) { + wrongDirection = true; + } break; case FOCUS_UP: - distance = -dirY / sqrtf(distance); - //if (dirY > 0.0f) return 0.0f; - //if (fabsf(dirX) > fabsf(dirY)) return 0.0f; + overlap = horizOverlap; + if (dirY > 0.0f) { + wrongDirection = true; + } break; case FOCUS_RIGHT: - //if (dirX < 0.0f) return 0.0f; - //if (fabsf(dirY) > fabsf(dirX)) return 0.0f; - distance = dirX / sqrtf(distance); + overlap = vertOverlap; + if (dirX < 0.0f) { + wrongDirection = true; + } break; case FOCUS_DOWN: - //if (dirY < 0.0f) return 0.0f; - //if (fabsf(dirX) > fabsf(dirY)) return 0.0f; - distance = dirY / sqrtf(distance); + overlap = horizOverlap; + if (dirY < 0.0f) { + wrongDirection = true; + } break; case FOCUS_PREV: case FOCUS_NEXT: @@ -186,7 +228,10 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio break; } - return distance; + if (wrongDirection) + return 0.0f; + else + return 1.0f/distance + overlap*10; } @@ -207,7 +252,7 @@ NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, Nei // TODO: Do the cardinal directions right. Now we just map to // prev/next. - + switch (direction) { case FOCUS_PREV: // If view not found, no neighbor to find. @@ -257,7 +302,7 @@ NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, Nei default: return result; - } + } } void MoveFocus(ViewGroup *root, FocusDirection direction) { @@ -287,7 +332,7 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); if (views_.empty()) - return; + return; float sum = 0.0f; float maxOther = 0.0f; @@ -992,9 +1037,6 @@ void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { root->Layout(); } -static recursive_mutex focusLock; -static std::vector focusMoves; - void KeyEvent(const KeyInput &key, ViewGroup *root) { if (key.flags & KEY_DOWN) { // We ignore the device ID here. Anything with a DPAD is OK. diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 183dc052b2..04b1291d6c 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -354,7 +354,7 @@ private: class ListView : public ScrollView { public: ListView(ListAdaptor *a, LayoutParams *layoutParams = 0); - + int GetSelected() { return adaptor_->GetSelected(); } Event OnChoice; From 83b65e7de117582b6d91c3090f8b675816af3724 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 24 Oct 2013 03:07:26 +1000 Subject: [PATCH 0783/1445] Remove DisableFZ. Use a working armv7 define. Add EnableFZ to Blackberry thread. --- Android.mk | 4 ---- base/BlackberryAudio.h | 2 ++ math/math_util.cpp | 33 +---------------------------- math/math_util.h | 1 - math/math_utilarmv6.cpp | 47 ----------------------------------------- 5 files changed, 3 insertions(+), 84 deletions(-) delete mode 100755 math/math_utilarmv6.cpp diff --git a/Android.mk b/Android.mk index 057b234b60..28cabdbd2d 100644 --- a/Android.mk +++ b/Android.mk @@ -87,15 +87,11 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip #Portable native and separate code on android in future is easy you needs add files #by ($(target_arch_ABI),arquitecture (armeabi-v7a , armeabi , x86 , MIPS) - ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) -LOCAL_SRC_FILES += math/math_util.cpp LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI_V7A -DARMV7 else ifeq ($(TARGET_ARCH_ABI),armeabi) -LOCAL_SRC_FILES += math/math_utilarmv6.cpp LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI else ifeq ($(TARGET_ARCH_ABI),x86) -LOCAL_SRC_FILES += math/math_util.cpp LOCAL_CFLAGS := $(LOCAL_CFLAGS) -D_M_IX86 endif diff --git a/base/BlackberryAudio.h b/base/BlackberryAudio.h index 6856c5aaaf..d047bfc64e 100644 --- a/base/BlackberryAudio.h +++ b/base/BlackberryAudio.h @@ -9,6 +9,7 @@ #include #include +#include "math/math_util.h" #include "base/NativeApp.h" #define AUDIO_FREQ 44100 @@ -50,6 +51,7 @@ public: private: void* RunAudio() { + EnableFZ(); while(true) { size_t frames_ready; diff --git a/math/math_util.cpp b/math/math_util.cpp index 5284cb893e..9d711445a4 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -1,23 +1,7 @@ #include "math/math_util.h" -#include #include -/* -static unsigned int randSeed = 22222; // Change this for different random sequences. - -void SetSeed(unsigned int seed) { - randSeed = seed * 382792592; -} - -unsigned int GenerateRandomNumber() { - randSeed = (randSeed * 196314165) + 907633515; - randSeed ^= _rotl(randSeed, 13); - return randSeed; -}*/ - -#include - -#if defined(ARMV7) +#if defined(__ARM_ARCH_7A__) void EnableFZ() { @@ -30,24 +14,9 @@ void EnableFZ() ); //printf("ARM FPSCR: %08x\n",x); } - -void DisableFZ( ) -{ - __asm__ volatile( - "fmrx r0, fpscr\n" - "bic r0, $(1 << 24)\n" - "fmxr fpscr, r0" : : : "r0"); -} #else - void EnableFZ() { // TODO } - -void DisableFZ() -{ - // TODO -} - #endif diff --git a/math/math_util.h b/math/math_util.h index 278dd49bb5..516ab716f1 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -193,6 +193,5 @@ inline uint16_t ShrinkToHalf(float full) { // FPU control. void EnableFZ(); -void DisableFZ(); #endif diff --git a/math/math_utilarmv6.cpp b/math/math_utilarmv6.cpp deleted file mode 100755 index 4271fb3460..0000000000 --- a/math/math_utilarmv6.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "math/math_util.h" -#include -#include - -/* -static unsigned int randSeed = 22222; // Change this for different random sequences. - -void SetSeed(unsigned int seed) { - randSeed = seed * 382792592; -} - -unsigned int GenerateRandomNumber() { - randSeed = (randSeed * 196314165) + 907633515; - randSeed ^= _rotl(randSeed, 13); - return randSeed; -}*/ - -#if defined(ARM) - -void EnableFZ() -{ - int x; - asm( - "orr %[result],%[result],#16777216 \r\n" - :[result] "=r" (x) : : - ); - -} - -void DisableFZ( ) -{ - __asm__ volatile( - "bic r0, $(1 << 24)\n"); -} -#else - -void EnableFZ() -{ - - -} -void DisableFZ() -{ - -} - -#endif From 26946b52e774b0853c10074ed078abf4b11cab36 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 24 Oct 2013 01:14:41 +0200 Subject: [PATCH 0784/1445] Terribly ugly workaround for destination alpha issues on Mali. Fixes #4272 . --- .../henrikrydgard/libnative/NativeActivity.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 2edfccb9dc..952d5410b1 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -302,7 +302,19 @@ public class NativeActivity extends Activity { // On some (especially older devices), things blow up later (EGL_BAD_MATCH) if we don't set the format here, // if we specify that we want destination alpha in the config chooser, which we do. // http://grokbase.com/t/gg/android-developers/11bj40jm4w/fall-back - mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888); + + // So what we really want is a RGBA8888 surface that is treated by the compositor as OPAQUE. + // Simply asking for OPAQUE here seems to do the trick on most devices, and seems to be required + // for some Mali devices to treat the surface as actually opaque (it seems to composite with blending + // agains a black background otherwise). However, on older devices like Xperia Play, this causes a + // BAD_MATCH exception later. Choosing RGBA_8888 here works fine though and everything is drawn correctly. + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { + mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888); + } else { + // Workaround for Mali but appears to work on other devices too + mGLSurfaceView.getHolder().setFormat(PixelFormat.OPAQUE); + } + mGLSurfaceView.setEGLConfigChooser(new NativeEGLConfigChooser()); nativeRenderer = new NativeRenderer(this); From 46dfa25ca4602f98e93944638aeda1dfbdf7603c Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 25 Oct 2013 12:34:15 +1000 Subject: [PATCH 0785/1445] Blackberry has FZ enabled by default. No need to add it manually. See: https://bugs.webkit.org/show_bug.cgi?id=97008 --- base/BlackberryAudio.h | 1 - math/math_util.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/base/BlackberryAudio.h b/base/BlackberryAudio.h index d047bfc64e..7bbba1609c 100644 --- a/base/BlackberryAudio.h +++ b/base/BlackberryAudio.h @@ -51,7 +51,6 @@ public: private: void* RunAudio() { - EnableFZ(); while(true) { size_t frames_ready; diff --git a/math/math_util.cpp b/math/math_util.cpp index 9d711445a4..29f7fea983 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -1,7 +1,7 @@ #include "math/math_util.h" #include -#if defined(__ARM_ARCH_7A__) +#if defined(__ARM_ARCH_7A__) && !defined(BLACKBERRY) void EnableFZ() { From b9ba2f27acced0f7df136cc6f7613a915623d50a Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 25 Oct 2013 14:13:27 +1000 Subject: [PATCH 0786/1445] Use clock_gettime instead of gettimeofday as recommended by QNX. --- base/mutex.h | 5 ++++- base/timeutil.cpp | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index 9b92e831e2..ef57a32d77 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -206,11 +206,14 @@ public: // mtx.lock(); #else timespec timeout; +#ifdef __APPLE__ timeval tv; gettimeofday(&tv, NULL); timeout.tv_sec = tv.tv_sec; timeout.tv_nsec = tv.tv_usec * 1000; - +#else + clock_gettime(CLOCK_REALTIME, &timeout); +#endif timeout.tv_sec += milliseconds / 1000; timeout.tv_nsec += milliseconds * 1000000; pthread_mutex_lock(&mtx.native_handle()); diff --git a/base/timeutil.cpp b/base/timeutil.cpp index 375b545ec9..c9df4901db 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -21,7 +21,7 @@ static float curtime_f = 0; __int64 _frequency = 0; __int64 _starttime = 0; -double real_time_now(){ +double real_time_now() { if (_frequency == 0) { QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); @@ -32,6 +32,12 @@ double real_time_now(){ return ((double) (time - _starttime) / (double) _frequency); } +#elif defined(BLACKBERRY) +double real_time_now() { + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); // Linux must use CLOCK_MONOTONIC_RAW due to time warps + return time.tv_sec + time.tv_nsec / 1.0e9; +} #else uint64_t _frequency = 0; From 421261de82dfd41191aa2ac0fdcca235237f4b76 Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 25 Oct 2013 19:05:27 +1000 Subject: [PATCH 0787/1445] Fix atomics on Blackberry. Was not clearing. --- base/mutex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/mutex.h b/base/mutex.h index ef57a32d77..89e40a7185 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -55,7 +55,7 @@ public: _WriteBarrier(); value = 0; #elif defined(BLACKBERRY) - atomic_set(&value, 0); + atomic_clr(&value, 1); #elif defined(__SYMBIAN32__) g_atomic_int_set(&value, 0); #else From 4c676c390448de2236c05df7648e9fc175f18896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 25 Oct 2013 10:57:26 +0200 Subject: [PATCH 0788/1445] Move GLExtensions to a new header that is not pulling in GL headers. Start moving out detection functionality that does not need GL headers to gpu_features.cpp. --- Android.mk | 1 + gfx_es2/gl_state.cpp | 4 +++ gfx_es2/gl_state.h | 43 +------------------------- gfx_es2/gpu_features.cpp | 9 ++++++ gfx_es2/gpu_features.h | 65 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 42 deletions(-) create mode 100644 gfx_es2/gpu_features.cpp create mode 100644 gfx_es2/gpu_features.h diff --git a/Android.mk b/Android.mk index 28cabdbd2d..2dbd07a8ef 100644 --- a/Android.mk +++ b/Android.mk @@ -55,6 +55,7 @@ LOCAL_SRC_FILES :=\ thread/prioritizedworkqueue.cpp \ thread/threadpool.cpp \ gfx_es2/glsl_program.cpp \ + gfx_es2/gpu_features.cpp \ gfx_es2/gl_state.cpp.arm \ gfx_es2/gl3stub.c \ gfx_es2/draw_buffer.cpp.arm \ diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 5849ac4f0c..971e186732 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -1,6 +1,7 @@ #include #include "base/logging.h" +#include "base/NativeApp.h" #include "gl_state.h" #ifdef _WIN32 @@ -104,6 +105,7 @@ void CheckGLExtensions() { // Check vendor string to try and guess GPU const char *cvendor = (char *)glGetString(GL_VENDOR); + // TODO: move this stuff to gpu_features.cpp if (cvendor) { const std::string vendor(cvendor); if (vendor == "NVIDIA Corporation" @@ -293,6 +295,8 @@ void CheckGLExtensions() { gl_extensions.ATIClampBug = ((strncmp (renderer, "ATI RADEON X", 12) != 0) || (strncmp (renderer, "ATI MOBILITY RADEON X",21) != 0)); } #endif + + ProcessGPUFeatures(); } void OpenGLState::SetVSyncInterval(int interval) { diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index f812d6e2a6..781599bb63 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -4,6 +4,7 @@ #include #include #include "gfx/gl_common.h" +#include "gfx_es2/gpu_features.h" #ifdef USING_GLES2 @@ -303,50 +304,8 @@ public: extern OpenGLState glstate; -enum { - GPU_VENDOR_NVIDIA = 1, - GPU_VENDOR_AMD = 2, - GPU_VENDOR_INTEL = 3, - GPU_VENDOR_ARM = 4, - GPU_VENDOR_POWERVR = 5, - GPU_VENDOR_ADRENO = 6, - GPU_VENDOR_UNKNOWN = 0, -}; - -// Extensions to look at using: -// GL_NV_map_buffer_range (same as GL_ARB_map_buffer_range ?) - -// WARNING: This gets memset-d - so no strings please -struct GLExtensions { - int ver[3]; - int gpuVendor; - bool GLES3; // true if the full OpenGL ES 3.0 is supported - bool OES_depth24; - bool OES_packed_depth_stencil; - bool OES_depth_texture; - bool EXT_discard_framebuffer; - bool FBO_ARB; - bool FBO_EXT; - bool PBO_ARB; - bool EXT_swap_control_tear; - bool QCOM_alpha_test; - bool OES_mapbuffer; - bool OES_vertex_array_object; - bool EXT_shader_framebuffer_fetch; - bool EXT_blend_minmax; - bool ATIClampBug; - bool NV_draw_texture; - bool NV_copy_image; - - // EGL extensions - - bool EGL_NV_system_time; - bool EGL_NV_coverage_sample; -}; extern std::string g_all_gl_extensions; extern std::string g_all_egl_extensions; -extern GLExtensions gl_extensions; - void CheckGLExtensions(); diff --git a/gfx_es2/gpu_features.cpp b/gfx_es2/gpu_features.cpp new file mode 100644 index 0000000000..85ef622a3d --- /dev/null +++ b/gfx_es2/gpu_features.cpp @@ -0,0 +1,9 @@ +#include "gfx_es2/gpu_features.h" + +void ProcessGPUFeatures() { + gl_extensions.bugs = 0; + // Should be table driven instead, this is a quick hack for Galaxy Y + if (System_GetProperty(SYSPROP_NAME) == "samsung:GT-S5360") { + gl_extensions.bugs |= BUG_FBO_UNUSABLE; + } +} diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h new file mode 100644 index 0000000000..7a452cb0ae --- /dev/null +++ b/gfx_es2/gpu_features.h @@ -0,0 +1,65 @@ +// This file will not pull in the OpenGL headers but will still let you +// access information about the features of the current GPU, for auto-config +// and similar purposes. + +#pragma once + +#include "base/NativeApp.h" + +enum { + GPU_VENDOR_NVIDIA = 1, + GPU_VENDOR_AMD = 2, + GPU_VENDOR_INTEL = 3, + GPU_VENDOR_ARM = 4, // Mali + GPU_VENDOR_POWERVR = 5, + GPU_VENDOR_ADRENO = 6, + GPU_VENDOR_BROADCOM = 7, + GPU_VENDOR_UNKNOWN = 0, +}; + +enum { + BUG_FBO_UNUSABLE=1 +}; + +// Extensions to look at using: +// GL_NV_map_buffer_range (same as GL_ARB_map_buffer_range ?) + +// WARNING: This gets memset-d - so no strings please +// TODO: Rename this GLFeatures or something. +struct GLExtensions { + int ver[3]; + int gpuVendor; + bool GLES3; // true if the full OpenGL ES 3.0 is supported + bool OES_depth24; + bool OES_packed_depth_stencil; + bool OES_depth_texture; + bool EXT_discard_framebuffer; + bool FBO_ARB; + bool FBO_EXT; + bool PBO_ARB; + bool EXT_swap_control_tear; + bool QCOM_alpha_test; + bool OES_mapbuffer; + bool OES_vertex_array_object; + bool EXT_shader_framebuffer_fetch; + bool EXT_blend_minmax; + bool ATIClampBug; + bool NV_draw_texture; + bool NV_copy_image; + + // EGL extensions + + bool EGL_NV_system_time; + bool EGL_NV_coverage_sample; + + // Bugs + int bugs; +}; + +extern GLExtensions gl_extensions; + + +// Call this after filling out vendor etc to lookup the bugs etc. +// Only needs to be called ones. Currently called by CheckGLExtensions(). +void ProcessGPUFeatures(); + From ad85b8e69df986b42934bb0a56f6c0c54efd812b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 25 Oct 2013 12:20:02 +0200 Subject: [PATCH 0789/1445] Ignore alpha when creating the backbuffer. Getting weird problems on some android devices. Add BroadCom to GPU vendors --- .../com/henrikrydgard/libnative/NativeActivity.java | 12 +----------- .../libnative/NativeEGLConfigChooser.java | 9 ++++++--- gfx_es2/gl_state.cpp | 3 +++ 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 952d5410b1..73348e71a0 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -303,17 +303,7 @@ public class NativeActivity extends Activity { // if we specify that we want destination alpha in the config chooser, which we do. // http://grokbase.com/t/gg/android-developers/11bj40jm4w/fall-back - // So what we really want is a RGBA8888 surface that is treated by the compositor as OPAQUE. - // Simply asking for OPAQUE here seems to do the trick on most devices, and seems to be required - // for some Mali devices to treat the surface as actually opaque (it seems to composite with blending - // agains a black background otherwise). However, on older devices like Xperia Play, this causes a - // BAD_MATCH exception later. Choosing RGBA_8888 here works fine though and everything is drawn correctly. - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { - mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888); - } else { - // Workaround for Mali but appears to work on other devices too - mGLSurfaceView.getHolder().setFormat(PixelFormat.OPAQUE); - } + mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBX_8888); mGLSurfaceView.setEGLConfigChooser(new NativeEGLConfigChooser()); diff --git a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java index d961095a68..1c8cf36d4c 100644 --- a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java +++ b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java @@ -99,10 +99,13 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { configs[i].Log(); } + // We now ignore destination alpha as a workaround for the Mali issue + // where we get badly composited if we use it. + // First, find our ideal configuration for (int i = 0; i < configs.length; i++) { ConfigAttribs c = configs[i]; - if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth == 16) { + if (c.red == 8 && c.green == 8 && c.blue == 8 && /* c.alpha == 0 &&*/ c.stencil >= 8 && c.depth == 16) { chosen = c; break; } @@ -112,7 +115,7 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { // Second, accept one with bigger depth. for (int i = 0; i < configs.length; i++) { ConfigAttribs c = configs[i]; - if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth > 16) { + if (c.red == 8 && c.green == 8 && c.blue == 8 && /* c.alpha == 8 && */ c.stencil >= 8 && c.depth > 16) { chosen = c; break; } @@ -123,7 +126,7 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { // Third, accept one with no stencil. for (int i = 0; i < configs.length; i++) { ConfigAttribs c = configs[i]; - if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.depth >= 16) { + if (c.red == 8 && c.green == 8 && c.blue == 8 && /* c.alpha == 8 && */ c.depth >= 16) { chosen = c; break; } diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 971e186732..78d120c317 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -126,6 +126,9 @@ void CheckGLExtensions() { gl_extensions.gpuVendor = GPU_VENDOR_POWERVR; } else if (vendor == "Qualcomm") { gl_extensions.gpuVendor = GPU_VENDOR_ADRENO; + } else if (vendor == "Broadcom") { + gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM; + // Just for reference: Galaxy Y has renderer == "VideoCore IV HW" } else { gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; } From 0c397c3e68dfeac2be8adaf205f483bd6c828466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 25 Oct 2013 12:44:03 +0200 Subject: [PATCH 0790/1445] Fix the vcxproj --- native.vcxproj | 4 +++- native.vcxproj.filters | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/native.vcxproj b/native.vcxproj index 68e8fd52e6..0f64ac0767 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -230,6 +230,7 @@ + @@ -364,6 +365,7 @@ + @@ -406,4 +408,4 @@ - \ No newline at end of file + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 1df5dde379..1ddb87dee8 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -222,6 +222,9 @@ gfx + + gfx + util @@ -455,6 +458,9 @@ gfx + + gfx + util @@ -576,4 +582,4 @@ {02e8ef95-82c7-4420-b029-a189a5e0fcbd} - \ No newline at end of file + From c53bf9235088c922b4a99d546323d2af6fff2c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 25 Oct 2013 13:07:13 +0200 Subject: [PATCH 0791/1445] Add onFinish callback to screens, hook up for UIScreen::OnBack --- ui/screen.cpp | 3 ++- ui/screen.h | 4 +++- ui/ui_screen.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ui/screen.cpp b/ui/screen.cpp index e36fc30fa1..27a0c6ffe0 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -170,7 +170,7 @@ void ScreenManager::RecreateAllViews() { } } -void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) { +void ScreenManager::finishDialog(Screen *dialog, DialogResult result) { if (stack_.empty()) { ELOG("Must be in a dialog to finishDialog"); return; @@ -179,6 +179,7 @@ void ScreenManager::finishDialog(const Screen *dialog, DialogResult result) { ELOG("Wrong dialog being finished!"); return; } + dialog->onFinish(result); dialogFinished_ = dialog; dialogResult_ = result; } diff --git a/ui/screen.h b/ui/screen.h index 1c0ce0b67c..db0d8532a3 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -31,6 +31,7 @@ enum DialogResult { DR_CANCEL, DR_YES, DR_NO, + DR_BACK, }; class ScreenManager; @@ -43,6 +44,7 @@ public: screenManager_ = 0; } + virtual void onFinish(DialogResult reason) {} virtual void update(InputState &input) {} virtual void render() {} virtual void deviceLost() {} @@ -99,7 +101,7 @@ public: void RecreateAllViews(); // Pops the dialog away. - void finishDialog(const Screen *dialog, DialogResult result = DR_OK); + void finishDialog(Screen *dialog, DialogResult result = DR_OK); // Instant touch, separate from the update() mechanism. void touch(const TouchInput &touch); diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index a92b06dd51..a3d63a7f96 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -55,7 +55,7 @@ void UIScreen::key(const KeyInput &key) { void UIDialogScreen::key(const KeyInput &key) { if ((key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) { - screenManager()->finishDialog(this, DR_CANCEL); + screenManager()->finishDialog(this, DR_BACK); } else { UIScreen::key(key); } @@ -96,7 +96,7 @@ void UIScreen::axis(const AxisInput &axis) { } UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { - screenManager()->finishDialog(this, DR_OK); + screenManager()->finishDialog(this, DR_BACK); return UI::EVENT_DONE; } @@ -114,7 +114,7 @@ void PopupScreen::touch(const TouchInput &touch) { } if (!box_->GetBounds().Contains(touch.x, touch.y)) - screenManager()->finishDialog(this, DR_CANCEL); + screenManager()->finishDialog(this, DR_BACK); UIDialogScreen::touch(touch); } @@ -183,7 +183,7 @@ void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) { adaptor_.SetSelected(e.a); if (callback_) - callback_(adaptor_.GetSelected()); + callback_(adaptor_.GetSelected()); screenManager()->finishDialog(this, DR_OK); OnCompleted(DR_OK); OnChoice.Dispatch(e); From 37cd71b2a4da4b7a15cd67d2d012dc12d4ee5f1a Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 26 Oct 2013 19:51:29 +1000 Subject: [PATCH 0792/1445] Enable threaded audio on Symbian. --- base/QtMain.cpp | 8 ++------ base/QtMain.h | 24 +++++++++++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index cc6d552041..98edad1dd7 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -156,23 +156,19 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) vibra = CHWRMVibra::NewL(); #endif -#ifdef __SYMBIAN32__ - MainAudio *audio = new MainAudio(); -#else QThread* thread = new QThread; MainAudio *audio = new MainAudio(); audio->moveToThread(thread); + QObject::connect(thread, SIGNAL(started()), audio, SLOT(run())); QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); -#endif int ret = a.exec(); delete audio; #ifdef __SYMBIAN32__ delete vibra; -#else - thread->quit(); #endif + thread->quit(); NativeShutdown(); net::Shutdown(); return ret; diff --git a/base/QtMain.h b/base/QtMain.h index 76bde0c716..d4f9a09e4e 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -186,6 +186,21 @@ class MainAudio: public QObject Q_OBJECT public: MainAudio() { + } + ~MainAudio() { + if (feed != NULL) { + killTimer(timer); + feed->close(); + } + if (output) { + output->stop(); + delete output; + } + if (mixbuf) + free(mixbuf); + } +public slots: + void run() { QAudioFormat fmt; fmt.setSampleRate(AUDIO_FREQ); fmt.setCodec("audio/pcm"); @@ -201,15 +216,6 @@ public: if (feed != NULL) timer = startTimer(1000*AUDIO_SAMPLES / AUDIO_FREQ); } - ~MainAudio() { - if (feed != NULL) { - killTimer(timer); - feed->close(); - } - output->stop(); - delete output; - free(mixbuf); - } protected: void timerEvent(QTimerEvent *) { From 90bc1a82185f71e72c42bad4b03ff4c5275b4fb8 Mon Sep 17 00:00:00 2001 From: Summeli Date: Sat, 26 Oct 2013 17:20:08 +0300 Subject: [PATCH 0793/1445] Added support for Symbian Mediakeys support for Symbian Mediakeys. Usually volume up/down, but it also support play/stop etc. if user has "remotecontrol" provided with nokia headset. --- base/QtMain.cpp | 3 + base/SymbianMediaKeys.cpp | 402 ++++++++++++++++++++++++++++++++++++++ base/SymbianMediaKeys.h | 78 ++++++++ 3 files changed, 483 insertions(+) create mode 100644 base/SymbianMediaKeys.cpp create mode 100644 base/SymbianMediaKeys.h diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 98edad1dd7..de05c871a1 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -17,6 +17,7 @@ #include #include #include +#include "SymbianMediaKeys.h" #endif #include "QtMain.h" @@ -154,6 +155,8 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) ssObject->setScreenSaverInhibit(); // Start vibration service vibra = CHWRMVibra::NewL(); + SymbianMediaKeys* mediakeys = new SymbianMediaKeys(); + mediakeys->subscribeKeyEvent(&w); #endif QThread* thread = new QThread; diff --git a/base/SymbianMediaKeys.cpp b/base/SymbianMediaKeys.cpp new file mode 100644 index 0000000000..91c56e2a7c --- /dev/null +++ b/base/SymbianMediaKeys.cpp @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2013 Antti Pohjola + * + */ +//Adds mediakey support for Symbian (volume up/down) + + +#include +#include +#include "SymbianMediakeys.h" + +#define KTimeOut 80 + +#define KPlayButtonPress 0x101 +#define KStopButtonPress 0x102 +#define KForwardButtonPress 0x103 +#define KBackwardButtonPress 0x104 +#define KVolUpButtonPress 0x105 +#define KVolDownButtonPress 0x106 + +SymbianMediaKeys::SymbianMediaKeys() + : CActive ( EPriorityNormal ){ + CActiveScheduler::Add( this ); + iInterfaceSelector = CRemConInterfaceSelector::NewL(); + iRemConCore = CRemConCoreApiTarget::NewL(*iInterfaceSelector, *this); + iInterfaceSelector->OpenTargetL(); + + playtimer = new QTimer(this); + connect(playtimer, SIGNAL(timeout()), this, SLOT(playtimerexpired())); + stoptimer = new QTimer(this); + connect(stoptimer, SIGNAL(timeout()), this, SLOT(stoptimerexpired())); + forwardtimer = new QTimer(this); + connect(forwardtimer, SIGNAL(timeout()), this, SLOT(forwardtimerexpired())); + backwardtimer = new QTimer(this); + connect(backwardtimer, SIGNAL(timeout()), this, SLOT(backwardtimerexpired())); + voluptimer = new QTimer(this); + connect(voluptimer, SIGNAL(timeout()), this, SLOT(voluptimerexpired())); + voldowntimer = new QTimer(this); + connect(voldowntimer, SIGNAL(timeout()), this, SLOT(voldowntimerexpired())); +} + +SymbianMediaKeys::~SymbianMediaKeys(){ + // TODO Auto-generated destructor stub + delete iInterfaceSelector; + iRemConCore = NULL; //owned by interfaceselector + Cancel(); + iResponseQ.Reset(); + iResponseQ.Close(); +} + +void SymbianMediaKeys::subscribeKeyEvent(QObject* aObject ){ + receiver = aObject; +} + +/* + * it seems that it takes about 600ms to get an update after buttonpress + * */ +void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, + TRemConCoreApiButtonAction aButtonAct){ + QKeyEvent *event = NULL; + TRequestStatus status; + switch( aOperationId ) + { + case ERemConCoreApiPausePlayFunction: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KPlayButtonPress, Qt::NoModifier, + KPlayButtonPress, KPlayButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonRelease: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KPlayButtonPress, Qt::NoModifier, + KPlayButtonPress, KPlayButtonPress,Qt::NoModifier); + // Play/Pause button released + break; + case ERemConCoreApiButtonClick: + // Play/Pause button clicked + playtimer->start(KTimeOut); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KPlayButtonPress, Qt::NoModifier, + KPlayButtonPress, KPlayButtonPress,Qt::NoModifier); + break; + default: + // Play/Pause unknown action + break; + } + break; + } + + case ERemConCoreApiStop: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KStopButtonPress, Qt::NoModifier, + KStopButtonPress, KStopButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonRelease: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KStopButtonPress, Qt::NoModifier, + KStopButtonPress, KStopButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonClick: + stoptimer->start(KTimeOut); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KStopButtonPress, Qt::NoModifier, + KStopButtonPress, KStopButtonPress,Qt::NoModifier); + break; + default: + + break; + } + break; + } + case ERemConCoreApiRewind: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KBackwardButtonPress, Qt::NoModifier, + KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonRelease: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KBackwardButtonPress, Qt::NoModifier, + KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonClick: + backwardtimer->start(KTimeOut); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KBackwardButtonPress, Qt::NoModifier, + KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + default: + break; + } + break; + } + case ERemConCoreApiFastForward: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KForwardButtonPress, Qt::NoModifier, + KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonRelease: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KForwardButtonPress, Qt::NoModifier, + KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonClick: + forwardtimer->start(KTimeOut); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KForwardButtonPress, Qt::NoModifier, + KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + default: + break; + } + break; + } + case ERemConCoreApiVolumeUp: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KVolUpButtonPress, Qt::NoModifier, + KVolUpButtonPress, KVolUpButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonRelease: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KVolUpButtonPress, Qt::NoModifier, + KVolUpButtonPress, KVolUpButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonClick: + voluptimer->start(KTimeOut); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KVolUpButtonPress, Qt::NoModifier, + KVolUpButtonPress, KVolUpButtonPress,Qt::NoModifier); + default: + break; + } + break; + } + case ERemConCoreApiVolumeDown: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KVolDownButtonPress, Qt::NoModifier, + KVolDownButtonPress, KVolDownButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonRelease: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KVolDownButtonPress, Qt::NoModifier, + KVolDownButtonPress, KVolDownButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonClick: + voldowntimer->start(KTimeOut); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KVolDownButtonPress, Qt::NoModifier, + KVolDownButtonPress, KVolDownButtonPress,Qt::NoModifier); + default: + break; + } + break; + } + case ERemConCoreApiBackward: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KBackwardButtonPress, Qt::NoModifier, + KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonRelease: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KBackwardButtonPress, Qt::NoModifier, + KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonClick: + backwardtimer->start(KTimeOut); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KBackwardButtonPress, Qt::NoModifier, + KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + default: + break; + } + break; + } + case ERemConCoreApiForward: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KForwardButtonPress, Qt::NoModifier, + KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonRelease: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KForwardButtonPress, Qt::NoModifier, + KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + break; + case ERemConCoreApiButtonClick: + forwardtimer->start(KTimeOut); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KForwardButtonPress, Qt::NoModifier, + KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + + default: + break; + } + break; + } + + default: + break; + } + //complete key event + QCoreApplication::postEvent (receiver, event); + CompleteMediaKeyEvent( aOperationId ); +} + +void SymbianMediaKeys::MrccatoPlay(TRemConCoreApiPlaybackSpeed aSpeed, + TRemConCoreApiButtonAction aButtonAct){ + +} + +void SymbianMediaKeys::MrccatoTuneFunction(TBool aTwoPart, + TUint aMajorChannel, + TUint aMinorChannel, + TRemConCoreApiButtonAction aButtonAct){ + +} + +void SymbianMediaKeys::MrccatoSelectDiskFunction(TUint aDisk, + TRemConCoreApiButtonAction aButtonAct){ + +} + +void SymbianMediaKeys::MrccatoSelectAvInputFunction(TUint8 aAvInputSignalNumber, + TRemConCoreApiButtonAction aButtonAct){ + +} + +void SymbianMediaKeys::MrccatoSelectAudioInputFunction(TUint8 aAudioInputSignalNumber, + TRemConCoreApiButtonAction aButtonAct){ + +} + +void SymbianMediaKeys::CompleteMediaKeyEvent( TRemConCoreApiOperationId aOperationId ){ + if ( !IsActive() ) + { + switch ( aOperationId ) + { + case ERemConCoreApiVolumeUp: + { + iRemConCore->VolumeUpResponse( iStatus, KErrNone ); + SetActive(); + } + break; + + case ERemConCoreApiVolumeDown: + { + iRemConCore->VolumeDownResponse( iStatus, KErrNone ); + SetActive(); + } + break; + case ERemConCoreApiPlay: + { + iRemConCore-> PlayResponse(iStatus, KErrNone); + SetActive(); + } + break; + case ERemConCoreApiStop: + { + iRemConCore->StopResponse(iStatus, KErrNone); + SetActive(); + } + break; + + case ERemConCoreApiPause: + { + iRemConCore->PauseResponse(iStatus, KErrNone); + SetActive(); + } + break; + case ERemConCoreApiRewind: + { + iRemConCore->RewindResponse(iStatus, KErrNone); + SetActive(); + } + break; + case ERemConCoreApiFastForward: + { + iRemConCore->FastForwardResponse(iStatus, KErrNone); + SetActive(); + } + break; + case ERemConCoreApiForward: + { + iRemConCore->ForwardResponse( iStatus, KErrNone ); + SetActive(); + } + break; + case ERemConCoreApiBackward: + { + iRemConCore->BackwardResponse(iStatus, KErrNone ); + SetActive(); + } + break; + default: + { + } + break; + } + } + else + { + //active, append to queue + iResponseQ.Append( aOperationId ); + } +} + +void SymbianMediaKeys::RunL(){ + if ( iResponseQ.Count() ){ + CompleteMediaKeyEvent( iResponseQ[0] ); + //remove old response from que + iResponseQ.Remove(0); + iResponseQ.Compress(); + } +} + +void SymbianMediaKeys::DoCancel(){ +} + +void SymbianMediaKeys::playtimerexpired(){ + playtimer->stop(); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KPlayButtonPress, Qt::NoModifier, + KPlayButtonPress, KPlayButtonPress,Qt::NoModifier); + QCoreApplication::postEvent (receiver, event); +} + +void SymbianMediaKeys::stoptimerexpired(){ + stoptimer->stop(); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KStopButtonPress, Qt::NoModifier, + KStopButtonPress, KStopButtonPress,Qt::NoModifier); + QCoreApplication::postEvent (receiver, event); +} + +void SymbianMediaKeys::forwardtimerexpired(){ + forwardtimer->stop(); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KForwardButtonPress, Qt::NoModifier, + KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + QCoreApplication::postEvent (receiver, event); +} + +void SymbianMediaKeys::backwardtimerexpired(){ + backwardtimer->stop(); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KBackwardButtonPress, Qt::NoModifier, + KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + QCoreApplication::postEvent (receiver, event); +} + +void SymbianMediaKeys::voluptimerexpired(){ + voluptimer->stop(); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KVolUpButtonPress, Qt::NoModifier, + KVolUpButtonPress, KVolUpButtonPress,Qt::NoModifier); + QCoreApplication::postEvent (receiver, event); +} + +void SymbianMediaKeys::voldowntimerexpired(){ + voldowntimer->stop(); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KVolDownButtonPress, Qt::NoModifier, + KVolDownButtonPress, KVolDownButtonPress,Qt::NoModifier); + QCoreApplication::postEvent (receiver, event); +} diff --git a/base/SymbianMediaKeys.h b/base/SymbianMediaKeys.h new file mode 100644 index 0000000000..bc4c4226bd --- /dev/null +++ b/base/SymbianMediaKeys.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 Antti Pohjola + * + */ +//Adds mediakey support for Symbian (volume up/down) + +#ifndef SYMBIANMEDIAKEYS_H_ +#define SYMBIANMEDIAKEYS_H_ + +#include +#include +#include + +#include // link against RemConCoreApi.lib +#include // and +#include // RemConInterfaceBase.lib + +class SymbianMediaKeys: public QObject, public CActive, public MRemConCoreApiTargetObserver + { + Q_OBJECT +public: + SymbianMediaKeys(); + virtual ~SymbianMediaKeys(); + +public: + void subscribeKeyEvent(QObject* aObject ); + +public: //From MRemConCoreApiTargetObserver + void MrccatoCommand(TRemConCoreApiOperationId aOperationId, + TRemConCoreApiButtonAction aButtonAct); + + void MrccatoPlay(TRemConCoreApiPlaybackSpeed aSpeed, + TRemConCoreApiButtonAction aButtonAct); + + void MrccatoTuneFunction(TBool aTwoPart, + TUint aMajorChannel, + TUint aMinorChannel, + TRemConCoreApiButtonAction aButtonAct); + + void MrccatoSelectDiskFunction(TUint aDisk, + TRemConCoreApiButtonAction aButtonAct); + + void MrccatoSelectAvInputFunction(TUint8 aAvInputSignalNumber, + TRemConCoreApiButtonAction aButtonAct); + + void MrccatoSelectAudioInputFunction(TUint8 aAudioInputSignalNumber, + TRemConCoreApiButtonAction aButtonAct); + +private: + void CompleteMediaKeyEvent( TRemConCoreApiOperationId aOperationId ); + void RunL(); + void DoCancel(); + +public slots: + void playtimerexpired(); + void stoptimerexpired(); + void forwardtimerexpired(); + void backwardtimerexpired(); + void voluptimerexpired(); + void voldowntimerexpired(); +private: + + RArray iResponseQ; //response queue + + CRemConCoreApiTarget* iRemConCore; //the controller + CRemConInterfaceSelector* iInterfaceSelector; + + QObject* receiver; + + QTimer* playtimer; + QTimer* stoptimer; + QTimer* forwardtimer; + QTimer* backwardtimer; + QTimer* voluptimer; + QTimer* voldowntimer; + }; + +#endif /* SYMBIANMEDIAKEYS_H_ */ From a1622cd5c838c7017cf1425a584439dba5202ef0 Mon Sep 17 00:00:00 2001 From: Summeli Date: Sat, 26 Oct 2013 18:14:52 +0300 Subject: [PATCH 0794/1445] using native keycodes instead of my own as symbian mediakeys --- base/SymbianMediaKeys.cpp | 129 ++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 68 deletions(-) diff --git a/base/SymbianMediaKeys.cpp b/base/SymbianMediaKeys.cpp index 91c56e2a7c..d632b9809a 100644 --- a/base/SymbianMediaKeys.cpp +++ b/base/SymbianMediaKeys.cpp @@ -8,16 +8,9 @@ #include #include #include "SymbianMediakeys.h" - +#include "input/keycodes.h" #define KTimeOut 80 -#define KPlayButtonPress 0x101 -#define KStopButtonPress 0x102 -#define KForwardButtonPress 0x103 -#define KBackwardButtonPress 0x104 -#define KVolUpButtonPress 0x105 -#define KVolDownButtonPress 0x106 - SymbianMediaKeys::SymbianMediaKeys() : CActive ( EPriorityNormal ){ CActiveScheduler::Add( this ); @@ -66,19 +59,19 @@ void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, switch (aButtonAct) { case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KPlayButtonPress, Qt::NoModifier, - KPlayButtonPress, KPlayButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PLAY_PAUSE, Qt::NoModifier, + NKCODE_MEDIA_PLAY_PAUSE, NKCODE_MEDIA_PLAY_PAUSE,Qt::NoModifier); break; case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KPlayButtonPress, Qt::NoModifier, - KPlayButtonPress, KPlayButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_PLAY_PAUSE, Qt::NoModifier, + NKCODE_MEDIA_PLAY_PAUSE, NKCODE_MEDIA_PLAY_PAUSE,Qt::NoModifier); // Play/Pause button released break; case ERemConCoreApiButtonClick: // Play/Pause button clicked playtimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KPlayButtonPress, Qt::NoModifier, - KPlayButtonPress, KPlayButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PLAY_PAUSE, Qt::NoModifier, + NKCODE_MEDIA_PLAY_PAUSE, NKCODE_MEDIA_PLAY_PAUSE,Qt::NoModifier); break; default: // Play/Pause unknown action @@ -92,17 +85,17 @@ void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, switch (aButtonAct) { case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KStopButtonPress, Qt::NoModifier, - KStopButtonPress, KStopButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_STOP, Qt::NoModifier, + NKCODE_MEDIA_STOP, NKCODE_MEDIA_STOP,Qt::NoModifier); break; case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KStopButtonPress, Qt::NoModifier, - KStopButtonPress, KStopButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_STOP, Qt::NoModifier, + NKCODE_MEDIA_STOP, NKCODE_MEDIA_STOP,Qt::NoModifier); break; case ERemConCoreApiButtonClick: stoptimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KStopButtonPress, Qt::NoModifier, - KStopButtonPress, KStopButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_STOP, Qt::NoModifier, + NKCODE_MEDIA_STOP, NKCODE_MEDIA_STOP,Qt::NoModifier); break; default: @@ -115,17 +108,17 @@ void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, switch (aButtonAct) { case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KBackwardButtonPress, Qt::NoModifier, - KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, + NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); break; case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KBackwardButtonPress, Qt::NoModifier, - KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, + NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); break; case ERemConCoreApiButtonClick: backwardtimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KBackwardButtonPress, Qt::NoModifier, - KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, + NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); default: break; } @@ -136,17 +129,17 @@ void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, switch (aButtonAct) { case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KForwardButtonPress, Qt::NoModifier, - KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_NEXT, Qt::NoModifier, + NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); break; case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KForwardButtonPress, Qt::NoModifier, - KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_NEXT, Qt::NoModifier, + NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); break; case ERemConCoreApiButtonClick: forwardtimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KForwardButtonPress, Qt::NoModifier, - KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_NEXT, Qt::NoModifier, + NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); default: break; } @@ -157,17 +150,17 @@ void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, switch (aButtonAct) { case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KVolUpButtonPress, Qt::NoModifier, - KVolUpButtonPress, KVolUpButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_UP, Qt::NoModifier, + NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); break; case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KVolUpButtonPress, Qt::NoModifier, - KVolUpButtonPress, KVolUpButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_VOLUME_UP, Qt::NoModifier, + NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); break; case ERemConCoreApiButtonClick: voluptimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KVolUpButtonPress, Qt::NoModifier, - KVolUpButtonPress, KVolUpButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_UP, Qt::NoModifier, + NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); default: break; } @@ -178,17 +171,17 @@ void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, switch (aButtonAct) { case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KVolDownButtonPress, Qt::NoModifier, - KVolDownButtonPress, KVolDownButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_DOWN, Qt::NoModifier, + NKCODE_VOLUME_DOWN, NKCODE_VOLUME_DOWN,Qt::NoModifier); break; case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KVolDownButtonPress, Qt::NoModifier, - KVolDownButtonPress, KVolDownButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_VOLUME_DOWN, Qt::NoModifier, + NKCODE_VOLUME_DOWN, NKCODE_VOLUME_DOWN,Qt::NoModifier); break; case ERemConCoreApiButtonClick: voldowntimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KVolDownButtonPress, Qt::NoModifier, - KVolDownButtonPress, KVolDownButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_DOWN, Qt::NoModifier, + NKCODE_VOLUME_DOWN, NKCODE_VOLUME_DOWN,Qt::NoModifier); default: break; } @@ -199,17 +192,17 @@ void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, switch (aButtonAct) { case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KBackwardButtonPress, Qt::NoModifier, - KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, + NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); break; case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KBackwardButtonPress, Qt::NoModifier, - KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, + NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); break; case ERemConCoreApiButtonClick: backwardtimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KBackwardButtonPress, Qt::NoModifier, - KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, + NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); default: break; } @@ -220,17 +213,17 @@ void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, switch (aButtonAct) { case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KForwardButtonPress, Qt::NoModifier, - KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_NEXT, Qt::NoModifier, + NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); break; case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, KForwardButtonPress, Qt::NoModifier, - KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_NEXT, Qt::NoModifier, + NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); break; case ERemConCoreApiButtonClick: forwardtimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, KForwardButtonPress, Qt::NoModifier, - KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_NEXT, Qt::NoModifier, + NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); default: break; @@ -361,42 +354,42 @@ void SymbianMediaKeys::DoCancel(){ void SymbianMediaKeys::playtimerexpired(){ playtimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KPlayButtonPress, Qt::NoModifier, - KPlayButtonPress, KPlayButtonPress,Qt::NoModifier); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_MEDIA_PLAY_PAUSE, Qt::NoModifier, + NKCODE_MEDIA_PLAY_PAUSE, NKCODE_MEDIA_PLAY_PAUSE,Qt::NoModifier); QCoreApplication::postEvent (receiver, event); } void SymbianMediaKeys::stoptimerexpired(){ stoptimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KStopButtonPress, Qt::NoModifier, - KStopButtonPress, KStopButtonPress,Qt::NoModifier); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_MEDIA_STOP, Qt::NoModifier, + NKCODE_MEDIA_STOP, NKCODE_MEDIA_STOP,Qt::NoModifier); QCoreApplication::postEvent (receiver, event); } void SymbianMediaKeys::forwardtimerexpired(){ forwardtimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KForwardButtonPress, Qt::NoModifier, - KForwardButtonPress, KForwardButtonPress,Qt::NoModifier); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_MEDIA_NEXT, Qt::NoModifier, + NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); QCoreApplication::postEvent (receiver, event); } void SymbianMediaKeys::backwardtimerexpired(){ backwardtimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KBackwardButtonPress, Qt::NoModifier, - KBackwardButtonPress, KBackwardButtonPress,Qt::NoModifier); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, + NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); QCoreApplication::postEvent (receiver, event); } void SymbianMediaKeys::voluptimerexpired(){ voluptimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KVolUpButtonPress, Qt::NoModifier, - KVolUpButtonPress, KVolUpButtonPress,Qt::NoModifier); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_VOLUME_UP, Qt::NoModifier, + NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); QCoreApplication::postEvent (receiver, event); } void SymbianMediaKeys::voldowntimerexpired(){ voldowntimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, KVolDownButtonPress, Qt::NoModifier, - KVolDownButtonPress, KVolDownButtonPress,Qt::NoModifier); + QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_VOLUME_DOWN, Qt::NoModifier, + NKCODE_VOLUME_DOWN, NKCODE_VOLUME_DOWN,Qt::NoModifier); QCoreApplication::postEvent (receiver, event); } From 74e40608b30409f1713c3397f3a217c278022096 Mon Sep 17 00:00:00 2001 From: Summeli Date: Sat, 26 Oct 2013 18:46:38 +0300 Subject: [PATCH 0795/1445] fixed tabs, and using NativeKeys instead of forwarding keyevent though qapplication --- base/QtMain.cpp | 1 - base/SymbianMediaKeys.cpp | 460 +++++++++++++++++--------------------- 2 files changed, 206 insertions(+), 255 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index de05c871a1..346b67e096 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -156,7 +156,6 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) // Start vibration service vibra = CHWRMVibra::NewL(); SymbianMediaKeys* mediakeys = new SymbianMediaKeys(); - mediakeys->subscribeKeyEvent(&w); #endif QThread* thread = new QThread; diff --git a/base/SymbianMediaKeys.cpp b/base/SymbianMediaKeys.cpp index d632b9809a..f17936a96d 100644 --- a/base/SymbianMediaKeys.cpp +++ b/base/SymbianMediaKeys.cpp @@ -9,6 +9,8 @@ #include #include "SymbianMediakeys.h" #include "input/keycodes.h" +#include "base/NativeApp.h" + #define KTimeOut 80 SymbianMediaKeys::SymbianMediaKeys() @@ -51,192 +53,159 @@ void SymbianMediaKeys::subscribeKeyEvent(QObject* aObject ){ void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, TRemConCoreApiButtonAction aButtonAct){ QKeyEvent *event = NULL; - TRequestStatus status; - switch( aOperationId ) - { - case ERemConCoreApiPausePlayFunction: - { - switch (aButtonAct) - { - case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PLAY_PAUSE, Qt::NoModifier, - NKCODE_MEDIA_PLAY_PAUSE, NKCODE_MEDIA_PLAY_PAUSE,Qt::NoModifier); - break; - case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_PLAY_PAUSE, Qt::NoModifier, - NKCODE_MEDIA_PLAY_PAUSE, NKCODE_MEDIA_PLAY_PAUSE,Qt::NoModifier); - // Play/Pause button released - break; - case ERemConCoreApiButtonClick: - // Play/Pause button clicked - playtimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PLAY_PAUSE, Qt::NoModifier, - NKCODE_MEDIA_PLAY_PAUSE, NKCODE_MEDIA_PLAY_PAUSE,Qt::NoModifier); - break; - default: - // Play/Pause unknown action - break; - } + TRequestStatus status; + switch( aOperationId ){ + case ERemConCoreApiPausePlayFunction: + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + playtimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_DOWN)); + break; + default: + // Play/Pause unknown action + break; + } break; } case ERemConCoreApiStop: - { - switch (aButtonAct) - { - case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_STOP, Qt::NoModifier, - NKCODE_MEDIA_STOP, NKCODE_MEDIA_STOP,Qt::NoModifier); - break; - case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_STOP, Qt::NoModifier, - NKCODE_MEDIA_STOP, NKCODE_MEDIA_STOP,Qt::NoModifier); - break; - case ERemConCoreApiButtonClick: - stoptimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_STOP, Qt::NoModifier, - NKCODE_MEDIA_STOP, NKCODE_MEDIA_STOP,Qt::NoModifier); - break; - default: - + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + stoptimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_DOWN)); + break; + default: break; - } - break; - } + } + break; + } case ERemConCoreApiRewind: - { - switch (aButtonAct) - { - case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, - NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); - break; - case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, - NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); - break; - case ERemConCoreApiButtonClick: - backwardtimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, - NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); - default: - break; - } + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + backwardtimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); + default: + break; + } break; - } + } case ERemConCoreApiFastForward: - { - switch (aButtonAct) - { - case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_NEXT, Qt::NoModifier, - NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); - break; - case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_NEXT, Qt::NoModifier, - NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); - break; - case ERemConCoreApiButtonClick: - forwardtimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_NEXT, Qt::NoModifier, - NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); - default: - break; - } - break; - } + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + forwardtimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); + default: + break; + } + break; + } case ERemConCoreApiVolumeUp: - { - switch (aButtonAct) - { - case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_UP, Qt::NoModifier, - NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); - break; - case ERemConCoreApiButtonRelease: + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_UP, Qt::NoModifier, + NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); + break; + case ERemConCoreApiButtonRelease: event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_VOLUME_UP, Qt::NoModifier, - NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); + NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); break; - case ERemConCoreApiButtonClick: - voluptimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_UP, Qt::NoModifier, - NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); - default: + case ERemConCoreApiButtonClick: + voluptimer->start(KTimeOut); + event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_UP, Qt::NoModifier, + NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); + default: break; } break; - } - case ERemConCoreApiVolumeDown: - { - switch (aButtonAct) - { - case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_DOWN, Qt::NoModifier, - NKCODE_VOLUME_DOWN, NKCODE_VOLUME_DOWN,Qt::NoModifier); - break; - case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_VOLUME_DOWN, Qt::NoModifier, - NKCODE_VOLUME_DOWN, NKCODE_VOLUME_DOWN,Qt::NoModifier); - break; - case ERemConCoreApiButtonClick: - voldowntimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_DOWN, Qt::NoModifier, - NKCODE_VOLUME_DOWN, NKCODE_VOLUME_DOWN,Qt::NoModifier); - default: - break; + } + case ERemConCoreApiVolumeDown: + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + voldowntimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_DOWN)); + default: + break; } break; - } - case ERemConCoreApiBackward: - { - switch (aButtonAct) - { - case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, - NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); - break; - case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, - NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); - break; - case ERemConCoreApiButtonClick: - backwardtimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, - NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); - default: - break; + } + case ERemConCoreApiBackward: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + backwardtimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); + default: + break; } + break; + } + case ERemConCoreApiForward: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + forwardtimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); + default: + break; + } break; - } - case ERemConCoreApiForward: - { - switch (aButtonAct) - { - case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_NEXT, Qt::NoModifier, - NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); - break; - case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_MEDIA_NEXT, Qt::NoModifier, - NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); - break; - case ERemConCoreApiButtonClick: - forwardtimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_MEDIA_NEXT, Qt::NoModifier, - NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); - - default: - break; - } - break; - } + } - default: - break; - } - //complete key event - QCoreApplication::postEvent (receiver, event); - CompleteMediaKeyEvent( aOperationId ); + default: + break; + } + //complete key event + CompleteMediaKeyEvent( aOperationId ); } void SymbianMediaKeys::MrccatoPlay(TRemConCoreApiPlaybackSpeed aSpeed, @@ -267,81 +236,76 @@ void SymbianMediaKeys::MrccatoSelectAudioInputFunction(TUint8 aAudioInputSignalN } void SymbianMediaKeys::CompleteMediaKeyEvent( TRemConCoreApiOperationId aOperationId ){ - if ( !IsActive() ) - { - switch ( aOperationId ) - { - case ERemConCoreApiVolumeUp: - { - iRemConCore->VolumeUpResponse( iStatus, KErrNone ); - SetActive(); - } - break; - - case ERemConCoreApiVolumeDown: - { - iRemConCore->VolumeDownResponse( iStatus, KErrNone ); - SetActive(); - } - break; - case ERemConCoreApiPlay: - { - iRemConCore-> PlayResponse(iStatus, KErrNone); - SetActive(); - } - break; - case ERemConCoreApiStop: - { - iRemConCore->StopResponse(iStatus, KErrNone); - SetActive(); - } - break; - - case ERemConCoreApiPause: - { - iRemConCore->PauseResponse(iStatus, KErrNone); - SetActive(); - } - break; - case ERemConCoreApiRewind: - { - iRemConCore->RewindResponse(iStatus, KErrNone); - SetActive(); - } - break; - case ERemConCoreApiFastForward: - { - iRemConCore->FastForwardResponse(iStatus, KErrNone); - SetActive(); - } - break; - case ERemConCoreApiForward: - { - iRemConCore->ForwardResponse( iStatus, KErrNone ); - SetActive(); - } - break; - case ERemConCoreApiBackward: - { - iRemConCore->BackwardResponse(iStatus, KErrNone ); - SetActive(); - } - break; - default: - { - } - break; - } - } - else + if ( !IsActive() ){ + switch ( aOperationId ) { + case ERemConCoreApiVolumeUp: + { + iRemConCore->VolumeUpResponse( iStatus, KErrNone ); + SetActive(); + break; + } + + case ERemConCoreApiVolumeDown: + { + iRemConCore->VolumeDownResponse( iStatus, KErrNone ); + SetActive(); + break; + } + case ERemConCoreApiPlay: + { + iRemConCore-> PlayResponse(iStatus, KErrNone); + SetActive(); + break; + } + case ERemConCoreApiStop: + { + iRemConCore->StopResponse(iStatus, KErrNone); + SetActive(); + break; + } + case ERemConCoreApiPause: + { + iRemConCore->PauseResponse(iStatus, KErrNone); + SetActive(); + break; + } + case ERemConCoreApiRewind: + { + iRemConCore->RewindResponse(iStatus, KErrNone); + SetActive(); + break; + } + case ERemConCoreApiFastForward: + { + iRemConCore->FastForwardResponse(iStatus, KErrNone); + SetActive(); + break; + } + case ERemConCoreApiForward: + { + iRemConCore->ForwardResponse( iStatus, KErrNone ); + SetActive(); + break; + } + case ERemConCoreApiBackward: + { + iRemConCore->BackwardResponse(iStatus, KErrNone ); + SetActive(); + break; + } + default: + break; + } + } + else{ //active, append to queue iResponseQ.Append( aOperationId ); - } + } } void SymbianMediaKeys::RunL(){ - if ( iResponseQ.Count() ){ + if ( iResponseQ.Count() ){ CompleteMediaKeyEvent( iResponseQ[0] ); //remove old response from que iResponseQ.Remove(0); @@ -354,42 +318,30 @@ void SymbianMediaKeys::DoCancel(){ void SymbianMediaKeys::playtimerexpired(){ playtimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_MEDIA_PLAY_PAUSE, Qt::NoModifier, - NKCODE_MEDIA_PLAY_PAUSE, NKCODE_MEDIA_PLAY_PAUSE,Qt::NoModifier); - QCoreApplication::postEvent (receiver, event); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_UP)); } void SymbianMediaKeys::stoptimerexpired(){ stoptimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_MEDIA_STOP, Qt::NoModifier, - NKCODE_MEDIA_STOP, NKCODE_MEDIA_STOP,Qt::NoModifier); - QCoreApplication::postEvent (receiver, event); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_UP)); } void SymbianMediaKeys::forwardtimerexpired(){ forwardtimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_MEDIA_NEXT, Qt::NoModifier, - NKCODE_MEDIA_NEXT, NKCODE_MEDIA_NEXT,Qt::NoModifier); - QCoreApplication::postEvent (receiver, event); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); } void SymbianMediaKeys::backwardtimerexpired(){ backwardtimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_MEDIA_PREVIOUS, Qt::NoModifier, - NKCODE_MEDIA_PREVIOUS, NKCODE_MEDIA_PREVIOUS,Qt::NoModifier); - QCoreApplication::postEvent (receiver, event); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); } void SymbianMediaKeys::voluptimerexpired(){ voluptimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_VOLUME_UP, Qt::NoModifier, - NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); - QCoreApplication::postEvent (receiver, event); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_UP, KEY_UP)); } void SymbianMediaKeys::voldowntimerexpired(){ voldowntimer->stop(); - QKeyEvent* event = QKeyEvent::createExtendedKeyEvent(QEvent::KeyRelease, NKCODE_VOLUME_DOWN, Qt::NoModifier, - NKCODE_VOLUME_DOWN, NKCODE_VOLUME_DOWN,Qt::NoModifier); - QCoreApplication::postEvent (receiver, event); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_UP)); } From 0feb3b05e6f1bef57e411526092fb9cf4ba58b3e Mon Sep 17 00:00:00 2001 From: Summeli Date: Sat, 26 Oct 2013 20:34:46 +0300 Subject: [PATCH 0796/1445] Fix indents and use native keys. --- base/SymbianMediaKeys.cpp | 380 ++++++++++++++++++-------------------- base/SymbianMediaKeys.h | 66 +++---- 2 files changed, 212 insertions(+), 234 deletions(-) diff --git a/base/SymbianMediaKeys.cpp b/base/SymbianMediaKeys.cpp index f17936a96d..3c1107e3d9 100644 --- a/base/SymbianMediaKeys.cpp +++ b/base/SymbianMediaKeys.cpp @@ -4,43 +4,41 @@ */ //Adds mediakey support for Symbian (volume up/down) - -#include #include #include "SymbianMediakeys.h" #include "input/keycodes.h" +#include "input/input_state.h" #include "base/NativeApp.h" #define KTimeOut 80 SymbianMediaKeys::SymbianMediaKeys() : CActive ( EPriorityNormal ){ - CActiveScheduler::Add( this ); - iInterfaceSelector = CRemConInterfaceSelector::NewL(); - iRemConCore = CRemConCoreApiTarget::NewL(*iInterfaceSelector, *this); - iInterfaceSelector->OpenTargetL(); - - playtimer = new QTimer(this); - connect(playtimer, SIGNAL(timeout()), this, SLOT(playtimerexpired())); - stoptimer = new QTimer(this); - connect(stoptimer, SIGNAL(timeout()), this, SLOT(stoptimerexpired())); - forwardtimer = new QTimer(this); - connect(forwardtimer, SIGNAL(timeout()), this, SLOT(forwardtimerexpired())); - backwardtimer = new QTimer(this); - connect(backwardtimer, SIGNAL(timeout()), this, SLOT(backwardtimerexpired())); - voluptimer = new QTimer(this); - connect(voluptimer, SIGNAL(timeout()), this, SLOT(voluptimerexpired())); - voldowntimer = new QTimer(this); - connect(voldowntimer, SIGNAL(timeout()), this, SLOT(voldowntimerexpired())); + CActiveScheduler::Add( this ); + iInterfaceSelector = CRemConInterfaceSelector::NewL(); + iRemConCore = CRemConCoreApiTarget::NewL(*iInterfaceSelector, *this); + iInterfaceSelector->OpenTargetL(); + + playtimer = new QTimer(this); + connect(playtimer, SIGNAL(timeout()), this, SLOT(playtimerexpired())); + stoptimer = new QTimer(this); + connect(stoptimer, SIGNAL(timeout()), this, SLOT(stoptimerexpired())); + forwardtimer = new QTimer(this); + connect(forwardtimer, SIGNAL(timeout()), this, SLOT(forwardtimerexpired())); + backwardtimer = new QTimer(this); + connect(backwardtimer, SIGNAL(timeout()), this, SLOT(backwardtimerexpired())); + voluptimer = new QTimer(this); + connect(voluptimer, SIGNAL(timeout()), this, SLOT(voluptimerexpired())); + voldowntimer = new QTimer(this); + connect(voldowntimer, SIGNAL(timeout()), this, SLOT(voldowntimerexpired())); } SymbianMediaKeys::~SymbianMediaKeys(){ - // TODO Auto-generated destructor stub - delete iInterfaceSelector; - iRemConCore = NULL; //owned by interfaceselector - Cancel(); - iResponseQ.Reset(); - iResponseQ.Close(); + delete iInterfaceSelector; + iRemConCore = NULL; //owned by interfaceselector + Cancel(); + iResponseQ.Reset(); + iResponseQ.Close(); } void SymbianMediaKeys::subscribeKeyEvent(QObject* aObject ){ @@ -50,193 +48,181 @@ void SymbianMediaKeys::subscribeKeyEvent(QObject* aObject ){ /* * it seems that it takes about 600ms to get an update after buttonpress * */ -void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId, - TRemConCoreApiButtonAction aButtonAct){ - QKeyEvent *event = NULL; - TRequestStatus status; - switch( aOperationId ){ - case ERemConCoreApiPausePlayFunction: - { - switch (aButtonAct){ - case ERemConCoreApiButtonPress: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_DOWN)); - break; - case ERemConCoreApiButtonRelease: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_UP)); - break; - case ERemConCoreApiButtonClick: - playtimer->start(KTimeOut); - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_DOWN)); - break; - default: - // Play/Pause unknown action - break; - } - break; - } - - case ERemConCoreApiStop: - { - switch (aButtonAct){ - case ERemConCoreApiButtonPress: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_DOWN)); - break; - case ERemConCoreApiButtonRelease: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_UP)); - break; - case ERemConCoreApiButtonClick: - stoptimer->start(KTimeOut); - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_DOWN)); - break; - default: - break; - } +void SymbianMediaKeys::MrccatoCommand(TRemConCoreApiOperationId aOperationId,TRemConCoreApiButtonAction aButtonAct){ + TRequestStatus status; + switch( aOperationId ){ + case ERemConCoreApiPausePlayFunction: + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_DOWN)); break; - } - case ERemConCoreApiRewind: - { - switch (aButtonAct){ - case ERemConCoreApiButtonPress: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); - break; - case ERemConCoreApiButtonRelease: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); - break; - case ERemConCoreApiButtonClick: - backwardtimer->start(KTimeOut); - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); - default: - break; - } - break; - } - case ERemConCoreApiFastForward: - { - switch (aButtonAct){ - case ERemConCoreApiButtonPress: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); - break; - case ERemConCoreApiButtonRelease: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); - break; - case ERemConCoreApiButtonClick: - forwardtimer->start(KTimeOut); - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); - default: - break; - } + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_UP)); break; - } - case ERemConCoreApiVolumeUp: - { - switch (aButtonAct){ - case ERemConCoreApiButtonPress: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_UP, Qt::NoModifier, - NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); - break; - case ERemConCoreApiButtonRelease: - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyRelease, NKCODE_VOLUME_UP, Qt::NoModifier, - NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); - break; - case ERemConCoreApiButtonClick: - voluptimer->start(KTimeOut); - event = QKeyEvent::createExtendedKeyEvent( QEvent::KeyPress, NKCODE_VOLUME_UP, Qt::NoModifier, - NKCODE_VOLUME_UP, NKCODE_VOLUME_UP,Qt::NoModifier); - default: - break; - } - break; - } - case ERemConCoreApiVolumeDown: - { - switch (aButtonAct){ - case ERemConCoreApiButtonPress: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_DOWN)); - break; - case ERemConCoreApiButtonRelease: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_UP)); - break; - case ERemConCoreApiButtonClick: - voldowntimer->start(KTimeOut); - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_DOWN)); - default: - break; - } - break; - } - case ERemConCoreApiBackward: - { - switch (aButtonAct) - { - case ERemConCoreApiButtonPress: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); - break; - case ERemConCoreApiButtonRelease: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); - break; - case ERemConCoreApiButtonClick: - backwardtimer->start(KTimeOut); - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); - default: - break; - } + case ERemConCoreApiButtonClick: + playtimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PLAY_PAUSE, KEY_DOWN)); + break; + default: + // Play/Pause unknown action break; - } - case ERemConCoreApiForward: - { - switch (aButtonAct) - { - case ERemConCoreApiButtonPress: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); - break; - case ERemConCoreApiButtonRelease: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); - break; - case ERemConCoreApiButtonClick: - forwardtimer->start(KTimeOut); - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); - default: - break; - } - break; } - + break; + } + + case ERemConCoreApiStop: + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + stoptimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_DOWN)); + break; default: break; - } - //complete key event - CompleteMediaKeyEvent( aOperationId ); + } + break; + } + case ERemConCoreApiRewind: + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + backwardtimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); + default: + break; + } + break; + } + case ERemConCoreApiFastForward: + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + forwardtimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); + default: + break; + } + break; + } + case ERemConCoreApiVolumeUp: + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_UP, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_UP, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + voluptimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_UP, KEY_DOWN)); + default: + break; + } + break; + } + case ERemConCoreApiVolumeDown: + { + switch (aButtonAct){ + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + voldowntimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_DOWN, KEY_DOWN)); + default: + break; + } + break; + } + case ERemConCoreApiBackward: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + backwardtimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_DOWN)); + default: + break; + } + break; + } + case ERemConCoreApiForward: + { + switch (aButtonAct) + { + case ERemConCoreApiButtonPress: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); + break; + case ERemConCoreApiButtonRelease: + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); + break; + case ERemConCoreApiButtonClick: + forwardtimer->start(KTimeOut); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_DOWN)); + default: + break; + } + break; + } + + default: + break; + } + //complete key event + CompleteMediaKeyEvent( aOperationId ); } -void SymbianMediaKeys::MrccatoPlay(TRemConCoreApiPlaybackSpeed aSpeed, - TRemConCoreApiButtonAction aButtonAct){ - +void SymbianMediaKeys::MrccatoPlay(TRemConCoreApiPlaybackSpeed aSpeed,TRemConCoreApiButtonAction aButtonAct){ + } -void SymbianMediaKeys::MrccatoTuneFunction(TBool aTwoPart, - TUint aMajorChannel, - TUint aMinorChannel, - TRemConCoreApiButtonAction aButtonAct){ - +void SymbianMediaKeys::MrccatoTuneFunction(TBool aTwoPart, TUint aMajorChannel,TUint aMinorChannel,TRemConCoreApiButtonAction aButtonAct){ + } -void SymbianMediaKeys::MrccatoSelectDiskFunction(TUint aDisk, - TRemConCoreApiButtonAction aButtonAct){ - +void SymbianMediaKeys::MrccatoSelectDiskFunction(TUint aDisk, TRemConCoreApiButtonAction aButtonAct){ + } -void SymbianMediaKeys::MrccatoSelectAvInputFunction(TUint8 aAvInputSignalNumber, - TRemConCoreApiButtonAction aButtonAct){ - +void SymbianMediaKeys::MrccatoSelectAvInputFunction(TUint8 aAvInputSignalNumber,TRemConCoreApiButtonAction aButtonAct){ + } -void SymbianMediaKeys::MrccatoSelectAudioInputFunction(TUint8 aAudioInputSignalNumber, - TRemConCoreApiButtonAction aButtonAct){ - +void SymbianMediaKeys::MrccatoSelectAudioInputFunction(TUint8 aAudioInputSignalNumber,TRemConCoreApiButtonAction aButtonAct){ + } void SymbianMediaKeys::CompleteMediaKeyEvent( TRemConCoreApiOperationId aOperationId ){ - if ( !IsActive() ){ + if( !IsActive() ){ switch ( aOperationId ) { case ERemConCoreApiVolumeUp: @@ -310,7 +296,7 @@ void SymbianMediaKeys::RunL(){ //remove old response from que iResponseQ.Remove(0); iResponseQ.Compress(); - } + } } void SymbianMediaKeys::DoCancel(){ @@ -325,17 +311,17 @@ void SymbianMediaKeys::stoptimerexpired(){ stoptimer->stop(); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_STOP, KEY_UP)); } - + void SymbianMediaKeys::forwardtimerexpired(){ forwardtimer->stop(); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_NEXT, KEY_UP)); } - + void SymbianMediaKeys::backwardtimerexpired(){ backwardtimer->stop(); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_MEDIA_PREVIOUS, KEY_UP)); } - + void SymbianMediaKeys::voluptimerexpired(){ voluptimer->stop(); NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_VOLUME_UP, KEY_UP)); diff --git a/base/SymbianMediaKeys.h b/base/SymbianMediaKeys.h index bc4c4226bd..415d00ac8c 100644 --- a/base/SymbianMediaKeys.h +++ b/base/SymbianMediaKeys.h @@ -16,41 +16,33 @@ #include // RemConInterfaceBase.lib class SymbianMediaKeys: public QObject, public CActive, public MRemConCoreApiTargetObserver - { +{ Q_OBJECT public: SymbianMediaKeys(); virtual ~SymbianMediaKeys(); - + public: void subscribeKeyEvent(QObject* aObject ); - + public: //From MRemConCoreApiTargetObserver - void MrccatoCommand(TRemConCoreApiOperationId aOperationId, - TRemConCoreApiButtonAction aButtonAct); + void MrccatoCommand(TRemConCoreApiOperationId aOperationId,TRemConCoreApiButtonAction aButtonAct); + + void MrccatoPlay(TRemConCoreApiPlaybackSpeed aSpeed,TRemConCoreApiButtonAction aButtonAct); + + void MrccatoTuneFunction(TBool aTwoPart,TUint aMajorChannel,TUint aMinorChannel,TRemConCoreApiButtonAction aButtonAct); + + void MrccatoSelectDiskFunction(TUint aDisk,TRemConCoreApiButtonAction aButtonAct); + + void MrccatoSelectAvInputFunction(TUint8 aAvInputSignalNumber,TRemConCoreApiButtonAction aButtonAct); + + void MrccatoSelectAudioInputFunction(TUint8 aAudioInputSignalNumber,TRemConCoreApiButtonAction aButtonAct); - void MrccatoPlay(TRemConCoreApiPlaybackSpeed aSpeed, - TRemConCoreApiButtonAction aButtonAct); - - void MrccatoTuneFunction(TBool aTwoPart, - TUint aMajorChannel, - TUint aMinorChannel, - TRemConCoreApiButtonAction aButtonAct); - - void MrccatoSelectDiskFunction(TUint aDisk, - TRemConCoreApiButtonAction aButtonAct); - - void MrccatoSelectAvInputFunction(TUint8 aAvInputSignalNumber, - TRemConCoreApiButtonAction aButtonAct); - - void MrccatoSelectAudioInputFunction(TUint8 aAudioInputSignalNumber, - TRemConCoreApiButtonAction aButtonAct); - private: - void CompleteMediaKeyEvent( TRemConCoreApiOperationId aOperationId ); - void RunL(); - void DoCancel(); - + void CompleteMediaKeyEvent( TRemConCoreApiOperationId aOperationId ); + void RunL(); + void DoCancel(); + public slots: void playtimerexpired(); void stoptimerexpired(); @@ -63,16 +55,16 @@ private: RArray iResponseQ; //response queue CRemConCoreApiTarget* iRemConCore; //the controller - CRemConInterfaceSelector* iInterfaceSelector; - - QObject* receiver; - - QTimer* playtimer; - QTimer* stoptimer; - QTimer* forwardtimer; - QTimer* backwardtimer; - QTimer* voluptimer; - QTimer* voldowntimer; - }; + CRemConInterfaceSelector* iInterfaceSelector; + + QObject* receiver; + + QTimer* playtimer; + QTimer* stoptimer; + QTimer* forwardtimer; + QTimer* backwardtimer; + QTimer* voluptimer; + QTimer* voldowntimer; +}; #endif /* SYMBIANMEDIAKEYS_H_ */ From 7d8beb94490c61c295866dd0324941be34d59357 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 27 Oct 2013 05:32:31 +1000 Subject: [PATCH 0797/1445] Use a Qt vibrator instead of a Symbian C++ one. Potentially cross-platform? Also, this should select a better default vibrator (eg. touch instead of phone call) which should allow vibration to work during charging. --- base/QtMain.cpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 346b67e096..c48b050efa 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -16,7 +16,7 @@ #ifdef __SYMBIAN32__ #include #include -#include +#include #include "SymbianMediaKeys.h" #endif #include "QtMain.h" @@ -46,28 +46,17 @@ std::string System_GetProperty(SystemProperty prop) { } } -#ifdef __SYMBIAN32__ -CHWRMVibra* vibra; -#endif - void Vibrate(int length_ms) { if (length_ms == -1 || length_ms == -3) length_ms = 50; else if (length_ms == -2) length_ms = 25; - // Qt 4.8 does not have any cross-platform Vibrate. Symbian-only for now. -#ifdef __SYMBIAN32__ - CHWRMVibra::TVibraModeState iState = vibra->VibraSettings(); - CHWRMVibra::TVibraStatus iStatus = vibra->VibraStatus(); - // User has not enabled vibration in settings. - if(iState != CHWRMVibra::EVibraModeON) - return; - if(iStatus != CHWRMVibra::EVibraStatusStopped) - vibra->StopVibraL(); -#endif - -#ifdef __SYMBIAN32__ - vibra->StartVibraL(length_ms, 20); + // Symbian only for now +#if defined(__SYMBIAN32__) + QFeedbackHapticsEffect effect; + effect.setIntensity(0.2); + effect.setDuration(length_ms); + effect.start(); #endif } @@ -153,8 +142,6 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) // Disable screensaver QSystemScreenSaver *ssObject = new QSystemScreenSaver(&w); ssObject->setScreenSaverInhibit(); - // Start vibration service - vibra = CHWRMVibra::NewL(); SymbianMediaKeys* mediakeys = new SymbianMediaKeys(); #endif @@ -167,9 +154,6 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) int ret = a.exec(); delete audio; -#ifdef __SYMBIAN32__ - delete vibra; -#endif thread->quit(); NativeShutdown(); net::Shutdown(); From 55810809b0a0d4153bdeafd41c737ca48f2f6926 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 27 Oct 2013 11:00:36 +1000 Subject: [PATCH 0798/1445] Support left analog stick for game controllers on Blackberry. --- base/BlackberryMain.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 01a74362cc..fad8e86871 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -158,6 +158,7 @@ void BlackberryMain::handleInput(screen_event_t screen_event) case SCREEN_EVENT_GAMEPAD: case SCREEN_EVENT_JOYSTICK: char device_id[16]; + int analog0[3]; screen_device_t device; screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DEVICE, (void**)&device); screen_get_device_property_cv(device, SCREEN_PROPERTY_ID_STRING, sizeof(device_id), device_id); @@ -167,6 +168,20 @@ void BlackberryMain::handleInput(screen_event_t screen_event) if ((old_buttons & mask) != (buttons & mask)) NativeKey(KeyInput(DEVICE_ID_PAD_0, KeyMapPadBlackberrytoNative.find(mask)->second, (buttons & mask) ? KEY_DOWN : KEY_UP)); } + if (!screen_get_device_property_iv(device, SCREEN_PROPERTY_ANALOG0, analog0)) { + for (int i = 0; i < 3; i++) { + AxisInput axis; + axis.axisId = (i == 0) ? JOYSTICK_AXIS_X : ( + (i == 1) ? JOYSTICK_AXIS_Y : JOYSTICK_AXIS_Z); + // 1.2 to try to approximate the PSP's clamped rectangular range. + axis.value = 1.2 * analog0[i] / 128.0f; + if (axis.value > 1.0f) axis.value = 1.0f; + if (axis.value < -1.0f) axis.value = -1.0f; + axis.deviceId = DEVICE_ID_PAD_0; + axis.flags = 0; + NativeAxis(axis); + } + } old_buttons = buttons; break; case SCREEN_EVENT_DISPLAY: From 4ebb62aa98af492ac4bf25b8ba13a3cbbcf60210 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Sun, 27 Oct 2013 10:58:16 +0530 Subject: [PATCH 0799/1445] allow checkboxes to be force-toggled --- ui/view.cpp | 6 +++++- ui/view.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 4341846563..307f51b2cc 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -383,9 +383,13 @@ void PopupHeader::Draw(UIContext &dc) { dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->popupTitle.fgColor); } -EventReturn CheckBox::OnClicked(EventParams &e) { +void CheckBox::Toggle(){ if (toggle_) *toggle_ = !(*toggle_); +}; + +EventReturn CheckBox::OnClicked(EventParams &e) { + Toggle(); return EVENT_CONTINUE; // It's safe to keep processing events. } diff --git a/ui/view.h b/ui/view.h index 6b9413731b..c439038ac0 100644 --- a/ui/view.h +++ b/ui/view.h @@ -600,7 +600,8 @@ public: virtual void Draw(UIContext &dc); EventReturn OnClicked(EventParams &e); - + //allow external agents to toggle the checkbox + void Toggle(); private: bool *toggle_; std::string text_; From 01b8cda080490bb4024e90bdc403c7484874225e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 27 Oct 2013 10:11:22 +0100 Subject: [PATCH 0800/1445] Make the EGL config chooser actually prefer modes with no alpha. Should finally take care of #4272. --- .../libnative/NativeEGLConfigChooser.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java index 1c8cf36d4c..7ada1daf79 100644 --- a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java +++ b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java @@ -105,7 +105,7 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { // First, find our ideal configuration for (int i = 0; i < configs.length; i++) { ConfigAttribs c = configs[i]; - if (c.red == 8 && c.green == 8 && c.blue == 8 && /* c.alpha == 0 &&*/ c.stencil >= 8 && c.depth == 16) { + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth == 16) { chosen = c; break; } @@ -115,7 +115,7 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { // Second, accept one with bigger depth. for (int i = 0; i < configs.length; i++) { ConfigAttribs c = configs[i]; - if (c.red == 8 && c.green == 8 && c.blue == 8 && /* c.alpha == 8 && */ c.stencil >= 8 && c.depth > 16) { + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth > 16) { chosen = c; break; } @@ -126,7 +126,7 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { // Third, accept one with no stencil. for (int i = 0; i < configs.length; i++) { ConfigAttribs c = configs[i]; - if (c.red == 8 && c.green == 8 && c.blue == 8 && /* c.alpha == 8 && */ c.depth >= 16) { + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.depth >= 16) { chosen = c; break; } @@ -134,10 +134,10 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { } if (chosen == null) { - // Third, accept one with no alpha but with stencil. + // Third, accept one with alpha but with stencil. for (int i = 0; i < configs.length; i++) { ConfigAttribs c = configs[i]; - if (c.red == 8 && c.green == 8 && c.blue == 8 && c.stencil >= 8 && c.depth >= 16) { + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth >= 16) { chosen = c; break; } From 3285f6f41ef447adeecac73b1b3e8e74bbbd9a9b Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 28 Oct 2013 03:07:01 +1000 Subject: [PATCH 0801/1445] Improve swap code to include more platforms. --- base/basictypes.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/base/basictypes.h b/base/basictypes.h index e54af02ad6..72c446c719 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -81,8 +81,21 @@ inline uint64 swap64(uint64 _data) {return _byteswap_uint64(_data);} inline uint16 swap16(uint16 _data) {return bswap_16(_data);} inline uint32 swap32(uint32 _data) {return bswap_32(_data);} inline uint64 swap64(uint64 _data) {return bswap_64(_data);} +#elif defined(__SYMBIAN32__) || defined(__FreeBSD__) +#include +inline uint16 swap16(uint16 _data) {return bswap16(_data);} +inline uint32 swap32(uint32 _data) {return bswap32(_data);} +inline uint64 swap64(uint64 _data) {return bswap64(_data);} +#elif defined(ARM) +inline uint16 swap16 (uint16 _data) { uint32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (uint16)data;} +inline uint32 swap32 (uint32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;} +inline uint64 swap64(uint64 _data) {return ((uint64)swap32(_data) << 32) | swap32(_data >> 32);} +#elif defined(__GNUC__) +inline uint16 swap16(uint16 _data) {return (_data >> 8) | (_data << 8);} +inline uint32 swap32(uint32 _data) {return __builtin_bswap32(_data);} +inline uint64 swap64(uint64 _data) {return __builtin_bswap64(_data);} #else -// Slow generic implementation. +// Slow generic implementation. Hopefully this never hits inline uint16 swap16(uint16 data) {return (data >> 8) | (data << 8);} inline uint32 swap32(uint32 data) {return (swap16(data) << 16) | swap16(data >> 16);} inline uint64 swap64(uint64 data) {return ((uint64)swap32(data) << 32) | swap32(data >> 32);} From 63d427ff9b7d521d000441be4a88cc255d3d6ed8 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 28 Oct 2013 03:54:35 +1000 Subject: [PATCH 0802/1445] Endian Swap: Fall back to ARM implementation for Symbian. --- base/basictypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/basictypes.h b/base/basictypes.h index 72c446c719..771e66b2d9 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -81,7 +81,7 @@ inline uint64 swap64(uint64 _data) {return _byteswap_uint64(_data);} inline uint16 swap16(uint16 _data) {return bswap_16(_data);} inline uint32 swap32(uint32 _data) {return bswap_32(_data);} inline uint64 swap64(uint64 _data) {return bswap_64(_data);} -#elif defined(__SYMBIAN32__) || defined(__FreeBSD__) +#elif defined(__FreeBSD__) #include inline uint16 swap16(uint16 _data) {return bswap16(_data);} inline uint32 swap32(uint32 _data) {return bswap32(_data);} From f0819f14a4e69f154703ef0093375c387e0b1e95 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 28 Oct 2013 12:26:00 +1000 Subject: [PATCH 0803/1445] Blackberry: Instead of polling controller on event, use the event duh. Don't check controller string id -- this is expensive. Use locale function because it's what we want. --- base/BlackberryMain.cpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index fad8e86871..6aa562347f 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -8,7 +8,7 @@ #include #include -#include // Get region and language +#include // Get locale #include "BlackberryMain.h" #include "base/NKCodeFromBlackberry.h" @@ -21,10 +21,9 @@ std::string System_GetProperty(SystemProperty prop) { return name + ((pixel_xres != pixel_yres) ? "Touch" : "QWERTY"); } case SYSPROP_LANGREGION: { - char *lang = 0; - char *region = 0; - region_get(&lang, ®ion); - return std::string(lang) + "_" + std::string(region); + char *locale = 0; + locale_get_locale(&locale); + return std::string(locale); } default: return ""; @@ -157,22 +156,17 @@ void BlackberryMain::handleInput(screen_event_t screen_event) // Gamepad case SCREEN_EVENT_GAMEPAD: case SCREEN_EVENT_JOYSTICK: - char device_id[16]; int analog0[3]; - screen_device_t device; - screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DEVICE, (void**)&device); - screen_get_device_property_cv(device, SCREEN_PROPERTY_ID_STRING, sizeof(device_id), device_id); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); for (int i = 0; i < 32; i++) { int mask = 1 << i; if ((old_buttons & mask) != (buttons & mask)) NativeKey(KeyInput(DEVICE_ID_PAD_0, KeyMapPadBlackberrytoNative.find(mask)->second, (buttons & mask) ? KEY_DOWN : KEY_UP)); } - if (!screen_get_device_property_iv(device, SCREEN_PROPERTY_ANALOG0, analog0)) { - for (int i = 0; i < 3; i++) { + if (!screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ANALOG0, analog0)) { + for (int i = 0; i < 2; i++) { AxisInput axis; - axis.axisId = (i == 0) ? JOYSTICK_AXIS_X : ( - (i == 1) ? JOYSTICK_AXIS_Y : JOYSTICK_AXIS_Z); + axis.axisId = JOYSTICK_AXIS_X + i; // 1.2 to try to approximate the PSP's clamped rectangular range. axis.value = 1.2 * analog0[i] / 128.0f; if (axis.value > 1.0f) axis.value = 1.0f; From 11e62f7f3aac0bbbcd7e8ebb6d7e8bdb1d9e721f Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 28 Oct 2013 14:17:53 +1000 Subject: [PATCH 0804/1445] Add option to display Blackberry debug statistics. Even if you are not running a debug firmware. --- base/BlackberryMain.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 6aa562347f..058df134e6 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -10,6 +10,7 @@ #include // Get locale #include "BlackberryMain.h" +#include "Core/Config.h" #include "base/NKCodeFromBlackberry.h" // Simple implementations of System functions @@ -272,6 +273,10 @@ void BlackberryMain::runMain() { { emulating = true; switchDisplay(screen_emu); + if (g_Config.iShowFPSCounter == 4) { + int options = SCREEN_DEBUG_STATISTICS; + screen_set_window_property_iv(screen_win[0], SCREEN_PROPERTY_DEBUG, &options); + } } else if (globalUIState != UISTATE_INGAME && emulating) { emulating = false; switchDisplay(screen_ui); From 3ddda26eefd601a4ae3a85a29e8689ad9cd08c0f Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 28 Oct 2013 15:33:02 +1000 Subject: [PATCH 0805/1445] Increase audio buffer size by a factor of 5. Helps with audio in some games. --- base/BlackberryAudio.h | 8 ++++---- base/QtMain.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/base/BlackberryAudio.h b/base/BlackberryAudio.h index 7bbba1609c..6938955245 100644 --- a/base/BlackberryAudio.h +++ b/base/BlackberryAudio.h @@ -56,7 +56,7 @@ private: size_t frames_ready; alGetSourcei(source, AL_SOURCE_STATE, &state); if (state != AL_PLAYING) { - frames_ready = NativeMix((short*)stream, SAMPLE_SIZE); + frames_ready = NativeMix((short*)stream, 5*SAMPLE_SIZE); } else frames_ready = 0; @@ -68,10 +68,10 @@ private: alSourcei(source, AL_BUFFER, buffer); alSourcePlay(source); // TODO: Maybe this could get behind? - usleep((1000000 * frames_ready) / AUDIO_FREQ); + usleep((1000000 * SAMPLE_SIZE) / AUDIO_FREQ); } else - usleep(100000); + usleep(10000); } } ALCdevice *alcDevice; @@ -79,7 +79,7 @@ private: ALenum state; ALuint buffer; ALuint source; - char stream[4*SAMPLE_SIZE]; + char stream[20*SAMPLE_SIZE]; pthread_t thread_handle; }; #endif diff --git a/base/QtMain.h b/base/QtMain.h index d4f9a09e4e..cb41a33ed6 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -208,7 +208,7 @@ public slots: fmt.setSampleSize(AUDIO_SAMPLESIZE); fmt.setByteOrder(QAudioFormat::LittleEndian); fmt.setSampleType(QAudioFormat::SignedInt); - mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; + mixlen = 5*2*AUDIO_CHANNELS*AUDIO_SAMPLES; mixbuf = (char*)malloc(mixlen); output = new QAudioOutput(fmt); output->setBufferSize(mixlen); @@ -220,7 +220,7 @@ public slots: protected: void timerEvent(QTimerEvent *) { memset(mixbuf, 0, mixlen); - size_t frames = NativeMix((short *)mixbuf, AUDIO_SAMPLES); + size_t frames = NativeMix((short *)mixbuf, 5*AUDIO_SAMPLES); if (frames > 0) feed->write(mixbuf, sizeof(short) * 2 * frames); } From 214de3a993115dd3a322ca8b95d45c00e2453ae2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 28 Oct 2013 11:24:03 +0100 Subject: [PATCH 0806/1445] Fix back button behaviour on Android Honeycomb and later. --- .../libnative/NativeActivity.java | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 73348e71a0..094e7d693e 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -386,11 +386,7 @@ public class NativeActivity extends Activity { darkenOnScreenButtons(); } } - - public boolean overrideKeys() { - return true; - } - + // Prevent destroying and recreating the main activity when the device rotates etc, // since this would stop the sound. @Override @@ -437,16 +433,30 @@ public class NativeActivity extends Activity { if (state == null) { return super.dispatchKeyEvent(event); } - + + // Let's let volume and back through to dispatchKeyEvent. + boolean passThrough = false; + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_BACK: + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_MUTE: + case KeyEvent.KEYCODE_MENU: + passThrough = true; + break; + default: + break; + } + switch (event.getAction()) { case KeyEvent.ACTION_DOWN: - if (state.onKeyDown(event)) { + if (state.onKeyDown(event) && !passThrough) { return true; } break; case KeyEvent.ACTION_UP: - if (state.onKeyUp(event)) { + if (state.onKeyUp(event) && !passThrough) { return true; } break; From 416cff372c45a418a2513674575cf442dcdb2049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 28 Oct 2013 16:05:21 +0100 Subject: [PATCH 0807/1445] UI fixes --- ui/ui_screen.cpp | 9 +++++++-- ui/ui_screen.h | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index a3d63a7f96..0e60df7875 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -55,7 +55,12 @@ void UIScreen::key(const KeyInput &key) { void UIDialogScreen::key(const KeyInput &key) { if ((key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) { - screenManager()->finishDialog(this, DR_BACK); + if (finished_) { + ELOG("Screen already finished"); + } else { + finished_ = true; + screenManager()->finishDialog(this, DR_BACK); + } } else { UIScreen::key(key); } @@ -124,7 +129,7 @@ void PopupScreen::CreateViews() { root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); - box_ = new LinearLayout(ORIENT_VERTICAL, + box_ = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(550, FillVertical() ? dp_yres - 30 : WRAP_CONTENT, dp_xres / 2, dp_yres / 2, NONE, NONE, true)); root_->Add(box_); diff --git a/ui/ui_screen.h b/ui/ui_screen.h index fee4d99f96..56f63edbae 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -36,7 +36,11 @@ private: class UIDialogScreen : public UIScreen { public: + UIDialogScreen() : UIScreen(), finished_(false) {} virtual void key(const KeyInput &key); + +private: + bool finished_; }; @@ -203,4 +207,4 @@ private: ScreenManager *screenManager_; }; -} // namespace UI \ No newline at end of file +} // namespace UI From 2b63ad24ca99e5c6ec483ccaa25ce6c19e8d5af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 28 Oct 2013 16:42:50 +0100 Subject: [PATCH 0808/1445] Add the armv6 flag to armeabi builds --- Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index 2dbd07a8ef..0800a9c8ab 100644 --- a/Android.mk +++ b/Android.mk @@ -91,7 +91,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI_V7A -DARMV7 else ifeq ($(TARGET_ARCH_ABI),armeabi) -LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI +LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI -march=armv6 else ifeq ($(TARGET_ARCH_ABI),x86) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -D_M_IX86 endif From 60f1d1e3cb92ac37b0269dc906a44b7467a9f2f0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 29 Oct 2013 11:23:42 +1000 Subject: [PATCH 0809/1445] Clean up of unused or redundant code and comments. --- android/app-android.cpp | 2 - base/BlackberryAudio.h | 1 - base/PCMain.cpp | 78 +-------------------------------- base/QtMain.cpp | 27 +++--------- base/QtMain.h | 1 - base/basictypes.h | 8 ++-- thread/prioritizedworkqueue.cpp | 8 +--- 7 files changed, 12 insertions(+), 113 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index ef858beed9..7c4008ec42 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -403,7 +403,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jcl keyInput.keyCode = key; keyInput.flags = KEY_DOWN; NativeKey(keyInput); - g_buttonTracker.Process(keyInput); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint deviceId, jint key) { @@ -412,7 +411,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclas keyInput.keyCode = key; keyInput.flags = KEY_UP; NativeKey(keyInput); - g_buttonTracker.Process(keyInput); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_beginJoystickEvent( diff --git a/base/BlackberryAudio.h b/base/BlackberryAudio.h index 6938955245..6e39099f06 100644 --- a/base/BlackberryAudio.h +++ b/base/BlackberryAudio.h @@ -9,7 +9,6 @@ #include #include -#include "math/math_util.h" #include "base/NativeApp.h" #define AUDIO_FREQ 44100 diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 32d0dcf87b..46cbf7eda9 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -264,52 +264,14 @@ std::string System_GetProperty(SystemProperty prop) { InputState input_state; - -const int buttonMappings[14] = { -#ifdef PANDORA - SDLK_PAGEDOWN, //X => cross - SDLK_END, //B => circle - SDLK_HOME, //A => box - SDLK_PAGEUP, //Y => triangle - SDLK_RSHIFT, //LBUMPER - SDLK_RCTRL, //RBUMPER - SDLK_LALT, //START - SDLK_LCTRL, //SELECT -#else - SDLK_z, //A - SDLK_x, //B - SDLK_a, //X - SDLK_s, //Y - SDLK_q, //LBUMPER - SDLK_w, //RBUMPER - SDLK_SPACE, //START - SDLK_v, //SELECT -#endif - SDLK_UP, //UP - SDLK_DOWN, //DOWN - SDLK_LEFT, //LEFT - SDLK_RIGHT, //RIGHT -#ifdef PANDORA - SDLK_SPACE, //MENU -#else - SDLK_m, //MENU -#endif - SDLK_BACKSPACE, //BACK -}; - void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_buttons = 0; input->pad_lstick_x = 0; input->pad_lstick_y = 0; input->pad_rstick_x = 0; input->pad_rstick_y = 0; - /* - for (int b = 0; b < 14; b++) { - if (keys[buttonMappings[b]]) - input->pad_buttons |= (1<pad_rstick_y = max(min(SDL_JoystickGetAxis(rjoy, 1) / 32000.0f, 1.0f), -1.0f); } } -#else - if (keys[SDLK_i]) - input->pad_lstick_y=1; - else if (keys[SDLK_k]) - input->pad_lstick_y=-1; - if (keys[SDLK_j]) - input->pad_lstick_x=-1; - else if (keys[SDLK_l]) - input->pad_lstick_x=1; - if (keys[SDLK_KP8]) - input->pad_rstick_y=1; - else if (keys[SDLK_KP2]) - input->pad_rstick_y=-1; - if (keys[SDLK_KP4]) - input->pad_rstick_x=-1; - else if (keys[SDLK_KP6]) - input->pad_rstick_x=1; #endif } @@ -358,7 +303,6 @@ int main(int argc, char *argv[]) { bool aspect43 = false; const char *zoomenv = getenv("ZOOM"); const char *tabletenv = getenv("TABLET"); - const char *ipad = getenv("IPAD"); if (zoomenv) { zoom = atof(zoomenv); @@ -366,26 +310,19 @@ int main(int argc, char *argv[]) { if (tabletenv) { tablet = atoi(tabletenv) ? true : false; } - if (ipad) { - aspect43 = true; - } bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); // Change these to temporarily test other resolutions. - aspect43 = false; tablet = false; float density = 1.0f; - //zoom = 1.5f; + // TODO: Just grab the dimensions from EGL if (landscape) { if (tablet) { pixel_xres = 1280 * zoom; pixel_yres = 800 * zoom; - } else if (aspect43) { - pixel_xres = 1024 * zoom; - pixel_yres = 768 * zoom; } else { #ifdef MAEMO pixel_xres = 800 * zoom; @@ -402,9 +339,6 @@ int main(int argc, char *argv[]) { if (tablet) { pixel_xres = 800 * zoom; pixel_yres = 1280 * zoom; - } else if (aspect43) { - pixel_xres = 768 * zoom; - pixel_yres = 1024 * zoom; } else { #ifdef MAEMO pixel_xres = 480 * zoom; @@ -635,7 +569,6 @@ int main(int argc, char *argv[]) { key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); - g_buttonTracker.Process(key); break; } case SDL_KEYUP: @@ -646,7 +579,6 @@ int main(int argc, char *argv[]) { key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); - g_buttonTracker.Process(key); break; } case SDL_MOUSEBUTTONDOWN: @@ -779,12 +711,6 @@ int main(int argc, char *argv[]) { lastT = t; } #endif - - // Simple frame rate limiting -// while (time_now() < t + 1.0f/60.0f) { -// sleep_ms(0); -// time_update(); -// } time_update(); t = time_now(); framecount++; diff --git a/base/QtMain.cpp b/base/QtMain.cpp index c48b050efa..ec23baf062 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -2,7 +2,7 @@ * Copyright (c) 2012 Sacha Refshauge * */ -// Qt 4.7 implementation of the framework. +// Qt 4.7+ / 5.0+ implementation of the framework. // Currently supports: Symbian, Blackberry, Meego, Linux, Windows #include @@ -65,29 +65,15 @@ void LaunchBrowser(const char *url) QDesktopServices::openUrl(QUrl(url)); } -void SimulateGamepad(InputState *input) { - input->pad_lstick_x = 0; - input->pad_lstick_y = 0; - input->pad_rstick_x = 0; - input->pad_rstick_y = 0; - - if (input->pad_buttons & PAD_BUTTON_JOY_UP) - input->pad_lstick_y=1; - else if (input->pad_buttons & PAD_BUTTON_JOY_DOWN) - input->pad_lstick_y=-1; - if (input->pad_buttons & PAD_BUTTON_JOY_LEFT) - input->pad_lstick_x=-1; - else if (input->pad_buttons & PAD_BUTTON_JOY_RIGHT) - input->pad_lstick_x=1; -} - float CalculateDPIScale() { // Sane default rather than check DPI #ifdef __SYMBIAN32__ return 1.4f; -#else +#elif defined(ARM) return 1.2f; +#else + return 1.0f; #endif } @@ -102,11 +88,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); -#ifdef ARM g_dpi_scale = CalculateDPIScale(); -#else - g_dpi_scale = 1.0f; -#endif dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); #ifdef __SYMBIAN32__ @@ -159,3 +141,4 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) net::Shutdown(); return ret; } + diff --git a/base/QtMain.h b/base/QtMain.h index cb41a33ed6..c64fe131e2 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -146,7 +146,6 @@ protected: void paintGL() { - SimulateGamepad(&input_state); updateAccelerometer(); UpdateInputState(&input_state); NativeUpdate(input_state); diff --git a/base/basictypes.h b/base/basictypes.h index 771e66b2d9..29bdce050d 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -73,6 +73,10 @@ inline uint8 swap8(uint8 _data) {return _data;} inline uint16 swap16(uint16 _data) {return _byteswap_ushort(_data);} inline uint32 swap32(uint32 _data) {return _byteswap_ulong (_data);} inline uint64 swap64(uint64 _data) {return _byteswap_uint64(_data);} +#elif defined(ARM) +inline uint16 swap16 (uint16 _data) { uint32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (uint16)data;} +inline uint32 swap32 (uint32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;} +inline uint64 swap64(uint64 _data) {return ((uint64)swap32(_data) << 32) | swap32(_data >> 32);} #elif __linux__ #include #undef swap16 @@ -86,10 +90,6 @@ inline uint64 swap64(uint64 _data) {return bswap_64(_data);} inline uint16 swap16(uint16 _data) {return bswap16(_data);} inline uint32 swap32(uint32 _data) {return bswap32(_data);} inline uint64 swap64(uint64 _data) {return bswap64(_data);} -#elif defined(ARM) -inline uint16 swap16 (uint16 _data) { uint32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (uint16)data;} -inline uint32 swap32 (uint32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;} -inline uint64 swap64(uint64 _data) {return ((uint64)swap32(_data) << 32) | swap32(_data >> 32);} #elif defined(__GNUC__) inline uint16 swap16(uint16 _data) {return (_data >> 8) | (_data << 8);} inline uint32 swap32(uint32 _data) {return __builtin_bswap32(_data);} diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index 0d10d9a0b2..7f193fc407 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -84,13 +84,7 @@ static void threadfunc(PrioritizedWorkQueue *wq) { } void ProcessWorkQueueOnThreadWhile(PrioritizedWorkQueue *wq) { - workThread = new std::thread( -#if defined(__SYMBIAN32__) || defined(BLACKBERRY) - [wq](){threadfunc(wq);} -#else - std::bind(&threadfunc, wq) -#endif - ); + workThread = new std::thread(std::bind(&threadfunc, wq)); } void StopProcessingWorkQueue(PrioritizedWorkQueue *wq) { From b2bc4ffa8e099452de2b7477398267ce931cfb7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 29 Oct 2013 10:11:41 +0100 Subject: [PATCH 0810/1445] Add "auto-enabled" to ui views (set a pointer to a bool that decides whether the view is enabled or not) --- ui/view.cpp | 8 ++++---- ui/view.h | 15 +++++++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 307f51b2cc..7308d1a228 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -170,7 +170,7 @@ void Clickable::FocusChanged(int focusFlags) { } void Clickable::Touch(const TouchInput &input) { - if (!enabled_) { + if (!IsEnabled()) { dragging_ = false; down_ = false; return; @@ -235,7 +235,7 @@ void Clickable::Key(const KeyInput &key) { void StickyChoice::Touch(const TouchInput &input) { dragging_ = false; - if (!enabled_) { + if (!IsEnabled()) { down_ = false; return; } @@ -418,8 +418,8 @@ void Button::Draw(UIContext &dc) { if (HasFocus()) style = dc.theme->buttonFocusedStyle; if (down_) style = dc.theme->buttonDownStyle; - if (!enabled_) style = dc.theme->buttonDisabledStyle; - + if (!IsEnabled()) style = dc.theme->buttonDisabledStyle; + // dc.Draw()->DrawImage4Grid(style.image, bounds_.x, bounds_.y, bounds_.x2(), bounds_.y2(), style.bgColor); dc.FillRect(style.background, bounds_); float tw, th; diff --git a/ui/view.h b/ui/view.h index c439038ac0..5c45a3f4c2 100644 --- a/ui/view.h +++ b/ui/view.h @@ -291,11 +291,10 @@ View *GetFocusedView(); class View { public: - View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), enabled_(true), visibility_(V_VISIBLE), measuredWidth_(0), measuredHeight_(0) { + View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), visibility_(V_VISIBLE), measuredWidth_(0), measuredHeight_(0), enabled_(true), enabledPtr_(0) { if (!layoutParams) layoutParams_.reset(new LayoutParams()); } - virtual ~View(); // Please note that Touch is called ENTIRELY asynchronously from drawing! @@ -344,7 +343,13 @@ public: } void SetEnabled(bool enabled) { enabled_ = enabled; } - bool IsEnabled() const { return enabled_; } + bool IsEnabled() const { + if (enabledPtr_) + return *enabledPtr_; + else + return enabled_; + } + void SetEnabledPtr(bool *enabled) { enabledPtr_ = enabled; } void SetVisibility(Visibility visibility) { visibility_ = visibility; } Visibility GetVisibility() const { return visibility_; } @@ -362,7 +367,6 @@ protected: scoped_ptr layoutParams_; std::string tag_; - bool enabled_; Visibility visibility_; // Results of measure pass. Set these in Measure. @@ -375,6 +379,9 @@ protected: scoped_ptr transform_; private: + bool *enabledPtr_; + bool enabled_; + DISALLOW_COPY_AND_ASSIGN(View); }; From c485d9b25a3a739785b24f43f15de70aa8f3c83d Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 29 Oct 2013 20:18:30 +1000 Subject: [PATCH 0811/1445] Increase vibration on Symbian. --- base/QtMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index ec23baf062..cd1e7fc0d2 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -54,7 +54,7 @@ void Vibrate(int length_ms) { // Symbian only for now #if defined(__SYMBIAN32__) QFeedbackHapticsEffect effect; - effect.setIntensity(0.2); + effect.setIntensity(0.4); effect.setDuration(length_ms); effect.start(); #endif From bc39c0a8e281323568ff1f8f384fe44f2f939313 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 29 Oct 2013 20:21:14 +1000 Subject: [PATCH 0812/1445] Buildfix for Android. --- base/basictypes.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/base/basictypes.h b/base/basictypes.h index 29bdce050d..8887def999 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -69,6 +69,11 @@ typedef intptr_t ssize_t; inline uint8 swap8(uint8 _data) {return _data;} +// Just in case this has been defined by platform +#undef swap16 +#undef swap32 +#undef swap64 + #ifdef _WIN32 inline uint16 swap16(uint16 _data) {return _byteswap_ushort(_data);} inline uint32 swap32(uint32 _data) {return _byteswap_ulong (_data);} @@ -79,9 +84,6 @@ inline uint32 swap32 (uint32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l inline uint64 swap64(uint64 _data) {return ((uint64)swap32(_data) << 32) | swap32(_data >> 32);} #elif __linux__ #include -#undef swap16 -#undef swap32 -#undef swap64 inline uint16 swap16(uint16 _data) {return bswap_16(_data);} inline uint32 swap32(uint32 _data) {return bswap_32(_data);} inline uint64 swap64(uint64 _data) {return bswap_64(_data);} From 68bb097c2f170b7bbb27ab59f8c629983b6f4bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 29 Oct 2013 12:43:03 +0100 Subject: [PATCH 0813/1445] Android quick buildfix --- base/basictypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/basictypes.h b/base/basictypes.h index 8887def999..19a9657e26 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -82,7 +82,7 @@ inline uint64 swap64(uint64 _data) {return _byteswap_uint64(_data);} inline uint16 swap16 (uint16 _data) { uint32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (uint16)data;} inline uint32 swap32 (uint32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;} inline uint64 swap64(uint64 _data) {return ((uint64)swap32(_data) << 32) | swap32(_data >> 32);} -#elif __linux__ +#elif __linux__ && !defined(ANDROID) #include inline uint16 swap16(uint16 _data) {return bswap_16(_data);} inline uint32 swap32(uint32 _data) {return bswap_32(_data);} From 6640b7b7ad00925a89f8127ad9299be851e76740 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 30 Oct 2013 13:05:17 +1000 Subject: [PATCH 0814/1445] SDL: Detect resolution automatically. Use --fullscreen switch to enable fullscreen. --- base/PCMain.cpp | 73 ++++++++++--------------------------------------- 1 file changed, 15 insertions(+), 58 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 46cbf7eda9..83ac74584c 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -297,65 +297,14 @@ extern void mixaudio(void *userdata, Uint8 *stream, int len) { int main(int argc, char *argv[]) { std::string app_name; std::string app_name_nice; - - float zoom = 1.0f; - bool tablet = false; - bool aspect43 = false; - const char *zoomenv = getenv("ZOOM"); - const char *tabletenv = getenv("TABLET"); - - if (zoomenv) { - zoom = atof(zoomenv); - } - if (tabletenv) { - tablet = atoi(tabletenv) ? true : false; - } - bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); - // Change these to temporarily test other resolutions. - tablet = false; - float density = 1.0f; - - // TODO: Just grab the dimensions from EGL - if (landscape) { - if (tablet) { - pixel_xres = 1280 * zoom; - pixel_yres = 800 * zoom; - } else { -#ifdef MAEMO - pixel_xres = 800 * zoom; - pixel_yres = 480 * zoom; -#else - pixel_xres = 960 * zoom; - pixel_yres = 544 * zoom; -#endif - } - } else { - // PC development hack for more space - //pixel_xres = 1580 * zoom; - //pixel_yres = 1000 * zoom; - if (tablet) { - pixel_xres = 800 * zoom; - pixel_yres = 1280 * zoom; - } else { -#ifdef MAEMO - pixel_xres = 480 * zoom; - pixel_yres = 800 * zoom; -#else - pixel_xres = 544 * zoom; - pixel_yres = 960 * zoom; -#endif - } - } - - net::Init(); #ifdef __APPLE__ // Make sure to request a somewhat modern GL context at least - the // latest supported by MacOSX (really, really sad...) - // Requires SDL 2.0 (which is even more sad, as that hasn't been released yet) + // Requires SDL 2.0 //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); #endif @@ -378,13 +327,16 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); - if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, + int mode; #ifdef USING_GLES2 - SDL_SWSURFACE | SDL_FULLSCREEN + mode = SDL_SWSURFACE | SDL_FULLSCREEN; #else - SDL_OPENGL + mode = SDL_OPENGL; + for (int i = 1; i < argc; i++) + if (!strcmp(argv[i],"--fullscreen")) + mode |= SDL_FULLSCREEN; #endif - ) == NULL) { + if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return(2); @@ -413,6 +365,11 @@ int main(int argc, char *argv[]) { } #endif + // Maybe resize screen first if on a desktop + const SDL_VideoInfo* info = SDL_GetVideoInfo(); + pixel_xres = info->current_w; + pixel_yres = info->current_h; + #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); TCHAR path[MAX_PATH]; @@ -438,8 +395,8 @@ int main(int argc, char *argv[]) { NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); #endif - dp_xres = (float)pixel_xres * density / zoom; - dp_yres = (float)pixel_yres * density / zoom; + dp_xres = (float)pixel_xres; + dp_yres = (float)pixel_yres; pixel_in_dps = (float)pixel_xres / dp_xres; NativeInitGraphics(); From 398137422ccc026802ebd4c15c576e5e13bd4bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 30 Oct 2013 12:22:22 +0100 Subject: [PATCH 0815/1445] SDL: Choose a reasonable default window size for windowed mode (2x PSP) --- base/PCMain.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 83ac74584c..de8be6db13 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -305,6 +305,7 @@ int main(int argc, char *argv[]) { // Make sure to request a somewhat modern GL context at least - the // latest supported by MacOSX (really, really sad...) // Requires SDL 2.0 + // We really should upgrade to SDL 2.0 soon. //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); #endif @@ -336,6 +337,12 @@ int main(int argc, char *argv[]) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; #endif + if ((mode & SDL_FULLSCREEN) == 0) { + // set a sensible default resolution (2x) + pixel_xres = 480 * 2; + pixel_yres = 272 * 2; + } + if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); From a8fbcb6165fad4305e82bcda566e0118fa843275 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Wed, 30 Oct 2013 19:48:12 -0200 Subject: [PATCH 0816/1445] Add Launch{Browser,Market,Email} support on Linux Modern Linux desktop should implement a xdg-open program, that should open an URL on the default desktop program. The documentation of xdg-open says that we should supply xdg-open script on our installation script for fallback purposes, but I don't think this is really necessary: anyone using a reasonable recently DE on Linux should have xdg-utils installed. --- base/PCMain.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index de8be6db13..338316a57b 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -11,6 +11,7 @@ #else #include #include +#include #endif #include @@ -228,6 +229,9 @@ void LaunchBrowser(const char *url) { #ifdef _WIN32 ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); +#elif __linux__ + std::string command = std::string("xdg-open ") + url; + system(command.c_str()); #else ILOG("Would have gone to %s but LaunchBrowser is not implemented on this platform", url); #endif @@ -237,6 +241,9 @@ void LaunchMarket(const char *url) { #ifdef _WIN32 ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); +#elif __linux__ + std::string command = std::string("xdg-open ") + url; + system(command.c_str()); #else ILOG("Would have gone to %s but LaunchMarket is not implemented on this platform", url); #endif @@ -246,6 +253,9 @@ void LaunchEmail(const char *email_address) { #ifdef _WIN32 ShellExecute(NULL, "open", (std::string("mailto:") + email_address).c_str(), NULL, NULL, SW_SHOWNORMAL); +#elif __linux__ + std::string command = std::string("xdg-open mailto:") + email_address; + system(command.c_str()); #else ILOG("Would have opened your email client for %s but LaunchEmail is not implemented on this platform", email_address); #endif From c374c6abda8658ab3c273fe4c25003807d3b993c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 31 Oct 2013 01:27:47 +0100 Subject: [PATCH 0817/1445] Prefer modes with 24-bit or 20-bit depth to 16-bit. --- .../libnative/NativeEGLConfigChooser.java | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java index 7ada1daf79..0b0a62986e 100644 --- a/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java +++ b/android/src/com/henrikrydgard/libnative/NativeEGLConfigChooser.java @@ -102,20 +102,31 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { // We now ignore destination alpha as a workaround for the Mali issue // where we get badly composited if we use it. - // First, find our ideal configuration + // First, find our ideal configuration. Prefer depth. for (int i = 0; i < configs.length; i++) { ConfigAttribs c = configs[i]; - if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth == 16) { + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 24) { chosen = c; break; } } if (chosen == null) { - // Second, accept one with bigger depth. + // Then, prefer one with 20-bit depth (Tegra 3) for (int i = 0; i < configs.length; i++) { ConfigAttribs c = configs[i]; - if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth > 16) { + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 20) { + chosen = c; + break; + } + } + } + + if (chosen == null) { + // Second, accept one with 16-bit depth. + for (int i = 0; i < configs.length; i++) { + ConfigAttribs c = configs[i]; + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 0 && c.stencil >= 8 && c.depth >= 16) { chosen = c; break; } @@ -133,6 +144,17 @@ public class NativeEGLConfigChooser implements EGLConfigChooser { } } + if (chosen == null) { + // Third, accept one with alpha but with stencil. + for (int i = 0; i < configs.length; i++) { + ConfigAttribs c = configs[i]; + if (c.red == 8 && c.green == 8 && c.blue == 8 && c.alpha == 8 && c.stencil >= 8 && c.depth >= 24) { + chosen = c; + break; + } + } + } + if (chosen == null) { // Third, accept one with alpha but with stencil. for (int i = 0; i < configs.length; i++) { From 1b46a9ce6bc57aa4aa83d3670fc3c8d46964a0eb Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 31 Oct 2013 01:44:20 +0100 Subject: [PATCH 0818/1445] Fix nasty bug in one FBO setup. Must be a common mistake that some drivers work around? --- gfx_es2/fbo.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 4e767d120b..a2f64aac34 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -172,8 +172,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F // Bind it all together glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); } else { ILOG("Creating %i x %i FBO using separate stencil", width, height); // TEGRA From c3247cfdc7241a473dbfa6f015a045456070acb9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 31 Oct 2013 02:08:46 +0100 Subject: [PATCH 0819/1445] Revert "Fix nasty bug in one FBO setup. Must be a common mistake that some drivers work around?" Doesn't seem to have been a bug. But at least we got a test build out of it :P This reverts commit 1b46a9ce6bc57aa4aa83d3670fc3c8d46964a0eb. --- gfx_es2/fbo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index a2f64aac34..4e767d120b 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -172,7 +172,8 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F // Bind it all together glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); } else { ILOG("Creating %i x %i FBO using separate stencil", width, height); // TEGRA From 2f4099fac4618d563e04422632e36ee591263c62 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 31 Oct 2013 02:27:42 +0100 Subject: [PATCH 0820/1445] Detect EXT_unpack_subimage --- gfx_es2/gl_state.cpp | 8 +++++++- gfx_es2/gpu_features.h | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 78d120c317..7816b56e78 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -218,6 +218,7 @@ void CheckGLExtensions() { gl_extensions.EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0); gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; + gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; #if defined(ANDROID) || defined(BLACKBERRY) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. // https://twitter.com/ID_AA_Carmack/status/387383037794603008 @@ -249,9 +250,14 @@ void CheckGLExtensions() { gl_extensions.EXT_discard_framebuffer = false; #endif #else - // Desktops support minmax + // Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc) gl_extensions.EXT_blend_minmax = true; + gl_extensions.EXT_unpack_subimage = true; #endif + // GLES 3 subsumes many ES2 extensions. + if (gl_extensions.GLES3) { + gl_extensions.EXT_unpack_subimage = true; + } #if defined(ANDROID) || defined(BLACKBERRY) if (gl_extensions.OES_mapbuffer) { diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 7a452cb0ae..75f0871428 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -46,7 +46,7 @@ struct GLExtensions { bool ATIClampBug; bool NV_draw_texture; bool NV_copy_image; - + bool EXT_unpack_subimage; // always supported on desktop and ES3 // EGL extensions bool EGL_NV_system_time; From cff2711a7c087edea398ae98dd245ae094bc17c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 31 Oct 2013 11:03:44 +0100 Subject: [PATCH 0821/1445] Add a few weird axes seen on Ouya --- input/keycodes.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/input/keycodes.h b/input/keycodes.h index 97ce3453b9..b1a396a822 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -282,8 +282,14 @@ enum AndroidJoystickAxis { JOYSTICK_AXIS_MOUSE_REL_X = 26, JOYSTICK_AXIS_MOUSE_REL_Y = 27, + // Getting these on Ouya, no clue what they are. + JOYSTICK_AXIS_OUYA_UNKNOWN1 = 32, + JOYSTICK_AXIS_OUYA_UNKNOWN2 = 33, + JOYSTICK_AXIS_OUYA_UNKNOWN3 = 34, + JOYSTICK_AXIS_OUYA_UNKNOWN4 = 35, + // Mobile device accelerometer/gyro - JOYSTICK_AXIS_ACCELEROMETER_X, - JOYSTICK_AXIS_ACCELEROMETER_Y, - JOYSTICK_AXIS_ACCELEROMETER_Z, + JOYSTICK_AXIS_ACCELEROMETER_X = 64, + JOYSTICK_AXIS_ACCELEROMETER_Y = 65, + JOYSTICK_AXIS_ACCELEROMETER_Z = 66, }; From c4807fbfb89e7988cb43a54c939eca936da81704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 31 Oct 2013 13:33:53 +0100 Subject: [PATCH 0822/1445] Add basic support for showing an icon within choices --- ui/view.cpp | 3 +++ ui/view.h | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 7308d1a228..f6310d5d8e 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -347,6 +347,9 @@ void Choice::Draw(UIContext &dc) { if (centered_) { dc.DrawText(text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); } else { + if (iconImage_ != -1) { + dc.Draw()->DrawImage(iconImage_, bounds_.x2() - 32 - paddingX, bounds_.centerY(), 0.5f, style.fgColor, ALIGN_CENTER); + } dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), style.fgColor, ALIGN_VCENTER); } } diff --git a/ui/view.h b/ui/view.h index 5c45a3f4c2..3210187b21 100644 --- a/ui/view.h +++ b/ui/view.h @@ -517,11 +517,11 @@ public: class Choice : public ClickableItem { public: Choice(const std::string &text, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), centered_(false), highlighted_(false), selected_(false) {} + : ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), iconImage_(-1), centered_(false), highlighted_(false), selected_(false) {} Choice(const std::string &text, const std::string &smallText, bool selected = false, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), centered_(false), highlighted_(false), selected_(selected) {} + : ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), iconImage_(-1), centered_(false), highlighted_(false), selected_(selected) {} Choice(ImageID image, LayoutParams *layoutParams = 0) - : ClickableItem(layoutParams), atlasImage_(image), centered_(false), highlighted_(false), selected_(false) {} + : ClickableItem(layoutParams), atlasImage_(image), iconImage_(-1), centered_(false), highlighted_(false), selected_(false) {} virtual void HighlightChanged(bool highlighted); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; @@ -529,6 +529,9 @@ public: virtual void SetCentered(bool c) { centered_ = c; } + virtual void SetIcon(ImageID iconImage) { + iconImage_ = iconImage; + } protected: // hackery @@ -537,6 +540,7 @@ protected: std::string text_; std::string smallText_; ImageID atlasImage_; + ImageID iconImage_; // Only applies for text, non-centered bool centered_; bool highlighted_; From 0fbcdfaeeee1456c1cf5998c721467f21989c482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 31 Oct 2013 15:46:07 +0100 Subject: [PATCH 0823/1445] Try to fix keyboard numpad mappings in SDL --- base/NKCodeFromSDL.h | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/base/NKCodeFromSDL.h b/base/NKCodeFromSDL.h index f0f158dd8d..c7ed7dc08b 100644 --- a/base/NKCodeFromSDL.h +++ b/base/NKCodeFromSDL.h @@ -62,19 +62,16 @@ static const std::map KeyMapRawSDLtoNative = InitConstMap (SDLK_HOME, NKCODE_MOVE_HOME) (SDLK_END, NKCODE_MOVE_END) (SDLK_INSERT, NKCODE_INSERT) - /* Somehow these are undefined - * on my comp? - (SDLK_KP_0, NKCODE_NUMPAD_0) - (SDLK_KP_1, NKCODE_NUMPAD_1) - (SDLK_KP_2, NKCODE_NUMPAD_2) - (SDLK_KP_3, NKCODE_NUMPAD_3) - (SDLK_KP_4, NKCODE_NUMPAD_4) - (SDLK_KP_5, NKCODE_NUMPAD_5) - (SDLK_KP_6, NKCODE_NUMPAD_6) - (SDLK_KP_7, NKCODE_NUMPAD_7) - (SDLK_KP_8, NKCODE_NUMPAD_8) - (SDLK_KP_9, NKCODE_NUMPAD_9) - */ + (SDLK_KP0, NKCODE_NUMPAD_0) + (SDLK_KP1, NKCODE_NUMPAD_1) + (SDLK_KP2, NKCODE_NUMPAD_2) + (SDLK_KP3, NKCODE_NUMPAD_3) + (SDLK_KP4, NKCODE_NUMPAD_4) + (SDLK_KP5, NKCODE_NUMPAD_5) + (SDLK_KP6, NKCODE_NUMPAD_6) + (SDLK_KP7, NKCODE_NUMPAD_7) + (SDLK_KP8, NKCODE_NUMPAD_8) + (SDLK_KP9, NKCODE_NUMPAD_9) (SDLK_KP_DIVIDE, NKCODE_NUMPAD_DIVIDE) (SDLK_KP_MULTIPLY, NKCODE_NUMPAD_MULTIPLY) (SDLK_KP_MINUS, NKCODE_NUMPAD_SUBTRACT) From 55b8a95a29c469a4ea3edc67a297bc31ed93589d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 31 Oct 2013 15:58:41 +0100 Subject: [PATCH 0824/1445] Add F1-F12 SDL key codes --- base/NKCodeFromSDL.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/base/NKCodeFromSDL.h b/base/NKCodeFromSDL.h index c7ed7dc08b..672e617ac0 100644 --- a/base/NKCodeFromSDL.h +++ b/base/NKCodeFromSDL.h @@ -89,6 +89,18 @@ static const std::map KeyMapRawSDLtoNative = InitConstMap (SDLK_8, NKCODE_8) (SDLK_9, NKCODE_9) (SDLK_0, NKCODE_0) + (SDLK_F1, NKCODE_F1) + (SDLK_F2, NKCODE_F2) + (SDLK_F3, NKCODE_F3) + (SDLK_F4, NKCODE_F4) + (SDLK_F5, NKCODE_F5) + (SDLK_F6, NKCODE_F6) + (SDLK_F7, NKCODE_F7) + (SDLK_F8, NKCODE_F8) + (SDLK_F9, NKCODE_F9) + (SDLK_F10, NKCODE_F10) + (SDLK_F11, NKCODE_F11) + (SDLK_F12, NKCODE_F12) (SDLK_LEFT, NKCODE_DPAD_LEFT) (SDLK_UP, NKCODE_DPAD_UP) (SDLK_RIGHT, NKCODE_DPAD_RIGHT) From 4c8922d9e70cbebc54c2d5a36d52e79339feeff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 31 Oct 2013 17:46:59 +0100 Subject: [PATCH 0825/1445] Add support for launching URLs on MacOSX --- base/PCMain.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 338316a57b..6d68ce32a8 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -232,6 +232,10 @@ void LaunchBrowser(const char *url) #elif __linux__ std::string command = std::string("xdg-open ") + url; system(command.c_str()); +#elif __APPLE__ + char temp[1024]; + sprintf(temp, "open %s", url); + system(temp); #else ILOG("Would have gone to %s but LaunchBrowser is not implemented on this platform", url); #endif From 64e9c2088f8f77f0ee6af067202c053a0107aed8 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Fri, 1 Nov 2013 15:09:36 -0200 Subject: [PATCH 0826/1445] Change string manipulation to C++ string class std::string seems to be the preferred method since you don't need to alloc more memory then you need (the Class automagically allocates the necessary RAM) and there is no chance of buffer overflow. But since I don't have Mac OSX, I didn't test it (it should work, since this is standard C++). Add Mac OSX support to Launcher{Market,Email} too and changed Linux to use "xdg-email " instead "xdg-open mailto:" since this seems the preferred method. --- base/PCMain.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 6d68ce32a8..b7d8b40dbd 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -233,9 +233,8 @@ void LaunchBrowser(const char *url) std::string command = std::string("xdg-open ") + url; system(command.c_str()); #elif __APPLE__ - char temp[1024]; - sprintf(temp, "open %s", url); - system(temp); + std::string command = std::string("open ") + url; + system(command.c_str()); #else ILOG("Would have gone to %s but LaunchBrowser is not implemented on this platform", url); #endif @@ -248,6 +247,9 @@ void LaunchMarket(const char *url) #elif __linux__ std::string command = std::string("xdg-open ") + url; system(command.c_str()); +#elif __APPLE__ + std::string command = std::string("open ") + url; + system(command.c_str()); #else ILOG("Would have gone to %s but LaunchMarket is not implemented on this platform", url); #endif @@ -258,7 +260,10 @@ void LaunchEmail(const char *email_address) #ifdef _WIN32 ShellExecute(NULL, "open", (std::string("mailto:") + email_address).c_str(), NULL, NULL, SW_SHOWNORMAL); #elif __linux__ - std::string command = std::string("xdg-open mailto:") + email_address; + std::string command = std::string("xdg-email ") + email_address; + system(command.c_str()); +#elif __APPLE__ + std::string command = std::string("open mailto:") + email_address; system(command.c_str()); #else ILOG("Would have opened your email client for %s but LaunchEmail is not implemented on this platform", email_address); From f5121df3be55ea9049164607e64a7c7d7bd2a7dd Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 2 Nov 2013 04:28:17 +1000 Subject: [PATCH 0827/1445] Rearrange when NativeInit starts so that BPS events are available for it. --- base/BlackberryMain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 058df134e6..183b700c44 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -214,12 +214,12 @@ void BlackberryMain::startMain(int argc, char *argv[]) { net::Init(); startDisplays(); - NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "app/native/assets/", "BADCOFFEE"); - NativeInitGraphics(); screen_request_events(screen_cxt); navigator_request_events(0); dialog_request_events(0); vibration_request_events(0); + NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "app/native/assets/", "BADCOFFEE"); + NativeInitGraphics(); audio = new BlackberryAudio(); runMain(); } From 045c24d0648da396a3feb3d7dd65293edda976af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 1 Nov 2013 22:14:41 +0100 Subject: [PATCH 0828/1445] SDL: Add support for hat motion events. Y axis may be inverted, not sure. --- base/PCMain.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index b7d8b40dbd..7c975c5791 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -544,6 +544,25 @@ int main(int argc, char *argv[]) { break; } + case SDL_JOYHATMOTION: + { + AxisInput axisX; + AxisInput axisY; + axisX.axisId = JOYSTICK_AXIS_HAT_X; + axisY.axisId = JOYSTICK_AXIS_HAT_Y; + axisX.deviceId = DEVICE_ID_PAD_0; + axisY.deviceId = DEVICE_ID_PAD_0; + axisX.value = 0.0f; + axisY.value = 0.0f; + if (event.jhat.value & SDL_HAT_LEFT) axisX.value = -1.0f; + if (event.jhat.value & SDL_HAT_RIGHT) axisX.value = 1.0f; + if (event.jhat.value & SDL_HAT_DOWN) axisY.value = -1.0f; + if (event.jhat.value & SDL_HAT_UP) axisY.value = 1.0f; + NativeAxis(axisX); + NativeAxis(axisY); + } + break; + case SDL_KEYDOWN: { int k = event.key.keysym.sym; From a02668cf8a0167104513ea4fddcf3fe0a8b5572c Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 3 Nov 2013 13:16:21 +1000 Subject: [PATCH 0829/1445] Check for Blackberry invocation in native instead of in NativeApp. Much cleaner. --- base/BlackberryMain.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 183b700c44..dbb092e5cf 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -8,11 +8,14 @@ #include #include -#include // Get locale +#include // Get locale +#include // Receive invocation messages #include "BlackberryMain.h" #include "Core/Config.h" #include "base/NKCodeFromBlackberry.h" +#include "UI/MiscScreens.h" + // Simple implementations of System functions std::string System_GetProperty(SystemProperty prop) { @@ -241,6 +244,14 @@ void BlackberryMain::runMain() { } else if (domain == navigator_get_domain()) { switch(bps_event_get_code(event)) { + case NAVIGATOR_INVOKE_TARGET: + { + const navigator_invoke_invocation_t *invoke = navigator_invoke_event_get_invocation(event); + if(invoke) { + boot_filename = navigator_invoke_invocation_get_uri(invoke)+7; // Remove file:// + } + } + break; case NAVIGATOR_BACK: case NAVIGATOR_SWIPE_DOWN: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE, KEY_DOWN)); From 64614c954f4862a28efafe31d4e538351dc1e3ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 4 Nov 2013 12:27:15 +0100 Subject: [PATCH 0830/1445] Update some CMakeLists used by projects other than PPSSPP --- ext/stb_image/CMakeLists.txt | 3 --- gfx_es2/CMakeLists.txt | 2 ++ input/CMakeLists.txt | 13 +++++++++++++ ui/CMakeLists.txt | 2 ++ 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 input/CMakeLists.txt diff --git a/ext/stb_image/CMakeLists.txt b/ext/stb_image/CMakeLists.txt index d69d96b6b9..3f4c2fae09 100644 --- a/ext/stb_image/CMakeLists.txt +++ b/ext/stb_image/CMakeLists.txt @@ -2,9 +2,6 @@ cmake_minimum_required(VERSION 2.6) #if(UNIX) add_definitions(-fPIC) -add_definitions(-g) -add_definitions(-O2) -add_definitions(-Wall) #endif(UNIX) add_library(stb_image stb_image.c) diff --git a/gfx_es2/CMakeLists.txt b/gfx_es2/CMakeLists.txt index e3a45b0a7f..9d2471f50e 100644 --- a/gfx_es2/CMakeLists.txt +++ b/gfx_es2/CMakeLists.txt @@ -1,7 +1,9 @@ set(SRCS draw_buffer.cpp + draw_text.cpp fbo.cpp glsl_program.cpp + gpu_features.cpp gl_state.cpp vertex_format.cpp) diff --git a/input/CMakeLists.txt b/input/CMakeLists.txt new file mode 100644 index 0000000000..266cff4ba7 --- /dev/null +++ b/input/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SRCS + input_state.cpp + gesture_detector.cpp) + +set(SRCS ${SRCS}) + +add_library(input STATIC ${SRCS}) +target_link_libraries(input general gfx) +target_link_libraries(input general file) + +if(UNIX) + add_definitions(-fPIC) +endif(UNIX) diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index ffefa49d6b..37c0ab1194 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -1,6 +1,8 @@ set(SRCS ui.cpp ui_context.cpp + view.cpp + viewgroup.cpp screen.cpp virtual_input.cpp ) From c00a47c8923a061ff970c0ba2b7ba9d73cb17a74 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 4 Nov 2013 23:49:30 +1000 Subject: [PATCH 0831/1445] Code cleanup. Rearrange code in logical order. Increase Symbian vibration. Pandora runfast was redundant (exists in math_util). Also it is VFPv3 not VFPv2. --- base/PCMain.cpp | 39 ++++++++++----------------------------- base/QtMain.cpp | 2 +- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 7c975c5791..b079fe6923 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -39,6 +39,7 @@ #include "base/NativeApp.h" #include "net/resolve.h" #include "util/const_map.h" +#include "math/math_util.h" #if defined(MAEMO) || defined(PANDORA) #define EGL @@ -48,23 +49,6 @@ #include "SDL_syswm.h" #include "math.h" -#ifdef PANDORA -void enable_runfast() -{ - static const unsigned int x = 0x04086060; - static const unsigned int y = 0x03000000; - int r; - asm volatile ( - "fmrx %0, fpscr \n\t" //r0 = FPSCR - "and %0, %0, %1 \n\t" //r0 = r0 & 0x04086060 - "orr %0, %0, %2 \n\t" //r0 = r0 | 0x03000000 - "fmxr fpscr, %0 \n\t" //FPSCR = r0 - : "=r"(r) - : "r"(x), "r"(y) - ); -} -#endif - EGLDisplay g_eglDisplay = NULL; EGLContext g_eglContext = NULL; EGLSurface g_eglSurface = NULL; @@ -356,11 +340,17 @@ int main(int argc, char *argv[]) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; #endif - if ((mode & SDL_FULLSCREEN) == 0) { + if (mode & SDL_FULLSCREEN) { + const SDL_VideoInfo* info = SDL_GetVideoInfo(); + pixel_xres = info->current_w; + pixel_yres = info->current_h; + } else { // set a sensible default resolution (2x) pixel_xres = 480 * 2; pixel_yres = 272 * 2; } + dp_xres = (float)pixel_xres; + dp_yres = (float)pixel_yres; if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); @@ -391,11 +381,6 @@ int main(int argc, char *argv[]) { } #endif - // Maybe resize screen first if on a desktop - const SDL_VideoInfo* info = SDL_GetVideoInfo(); - pixel_xres = info->current_w; - pixel_yres = info->current_h; - #ifdef _MSC_VER // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); TCHAR path[MAX_PATH]; @@ -421,13 +406,8 @@ int main(int argc, char *argv[]) { NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); #endif - dp_xres = (float)pixel_xres; - dp_yres = (float)pixel_yres; pixel_in_dps = (float)pixel_xres / dp_xres; - NativeInitGraphics(); - glstate.viewport.set(0, 0, pixel_xres, pixel_yres); - float dp_xscale = (float)dp_xres / pixel_xres; float dp_yscale = (float)dp_yres / pixel_yres; @@ -435,6 +415,7 @@ int main(int argc, char *argv[]) { printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); + NativeInitGraphics(); SDL_AudioSpec fmt; fmt.freq = 44100; @@ -457,13 +438,13 @@ int main(int argc, char *argv[]) { if (numjoys > 1) rjoy = SDL_JoystickOpen(1); } - enable_runfast(); // VFPv2 RunFast #else SDL_JoystickEventState(SDL_ENABLE); if (numjoys > 0) { joy = SDL_JoystickOpen(0); } #endif + EnableFZ(); // This is just a standard mapping that matches the X360 controller on MacOSX. Names will probably be all wrong // on other controllers. diff --git a/base/QtMain.cpp b/base/QtMain.cpp index cd1e7fc0d2..dbc2fcb681 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -54,7 +54,7 @@ void Vibrate(int length_ms) { // Symbian only for now #if defined(__SYMBIAN32__) QFeedbackHapticsEffect effect; - effect.setIntensity(0.4); + effect.setIntensity(0.8); effect.setDuration(length_ms); effect.start(); #endif From f9b19d7789548afb458e4e6d32f02df612b9d0ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 4 Nov 2013 13:34:15 +0100 Subject: [PATCH 0832/1445] Warning fix --- ui/view.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/view.h b/ui/view.h index 3210187b21..663d0f302e 100644 --- a/ui/view.h +++ b/ui/view.h @@ -291,7 +291,7 @@ View *GetFocusedView(); class View { public: - View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), visibility_(V_VISIBLE), measuredWidth_(0), measuredHeight_(0), enabled_(true), enabledPtr_(0) { + View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), visibility_(V_VISIBLE), measuredWidth_(0), measuredHeight_(0), enabledPtr_(0), enabled_(true) { if (!layoutParams) layoutParams_.reset(new LayoutParams()); } @@ -310,7 +310,7 @@ public: void Move(Bounds bounds) { bounds_ = bounds; } - + // Views don't do anything here in Layout, only containers implement this. virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); virtual void Layout() {} From 4e997a2e15d5e930601ada2d931d67eb36e0f95f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 4 Nov 2013 15:31:33 +0100 Subject: [PATCH 0833/1445] Make sure MAX_POINTERS is only defined once. --- input/input_state.h | 2 -- ui/ui.h | 10 +++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/input/input_state.h b/input/input_state.h index 8a86e6d575..561ea60096 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -60,9 +60,7 @@ enum { PAD_BUTTON_UNTHROTTLE = 1 << 20, // Click Tab to unthrottle }; -#ifndef MAX_POINTERS #define MAX_POINTERS 10 -#endif #ifndef MAX_KEYQUEUESIZE #define MAX_KEYQUEUESIZE 20 diff --git a/ui/ui.h b/ui/ui.h index 9c8770ffd1..f00dd5f58b 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -23,11 +23,12 @@ #define GEN_ID_LOOP(i) ((__LINE__) + ((int)i) * 13612) #endif -#include "gfx_es2/draw_buffer.h" - #include #include +#include "gfx_es2/draw_buffer.h" +#include "input/input_state.h" + class Texture; class UIContext; @@ -127,11 +128,6 @@ private: float ySpacing_; }; - -#ifndef MAX_POINTERS -#define MAX_POINTERS 8 -#endif - // "Mouse" out of habit, applies just as well to touch events. // TODO: Change to "pointer" // This struct is zeroed on init, so should be valid at that state. From 56bf9f1d100234f59e1f028341f2667b408fadd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 4 Nov 2013 16:18:32 +0100 Subject: [PATCH 0834/1445] Another cmakelist update --- math/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/math/CMakeLists.txt b/math/CMakeLists.txt index a204c3e6c2..c582f3ad9c 100644 --- a/math/CMakeLists.txt +++ b/math/CMakeLists.txt @@ -4,6 +4,7 @@ set(SRCS lin/quat.cpp lin/aabb.cpp curves.cpp + math_util.cpp ) set(SRCS ${SRCS}) From 1e801767240d5334a5f7103f0b5562360415c60a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 4 Nov 2013 17:13:45 +0100 Subject: [PATCH 0835/1445] Buildfix --- tools/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 0a54bfd97f..ce97e07957 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -8,7 +8,7 @@ add_definitions(-Wall) add_definitions(-DSDL) add_definitions(-Wno-multichar) add_definitions(-fno-strict-aliasing) -add_definitions(-fopenmp) +#add_definitions(-fopenmp) if(IOS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") @@ -52,7 +52,7 @@ add_subdirectory(../ext/stb_image stb_image) add_executable(atlastool atlastool.cpp) -target_link_libraries(atlastool ${PNG_LIBRARY} freetype util image z stb_image rg_etc1 file zip gomp) +target_link_libraries(atlastool ${PNG_LIBRARY} freetype util image z stb_image rg_etc1 file zip) add_executable(zimtool zimtool.cpp) -target_link_libraries(zimtool ${PNG_LIBRARY} freetype image z stb_image rg_etc1 file zip gomp) +target_link_libraries(zimtool ${PNG_LIBRARY} freetype image z stb_image rg_etc1 file zip) From c2b558e8817d1e736686a6d70db997a060a5488e Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 5 Nov 2013 12:58:30 +1000 Subject: [PATCH 0836/1445] SDL: Hide cursor when fullscreen during game without touch controls. Also remove redundant headers. --- base/PCMain.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index b079fe6923..8e71fc7ddc 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -8,39 +8,32 @@ #include #include #include -#else -#include -#include -#include -#endif - -#include -#include -#ifdef _WIN32 #include "SDL/SDL.h" #include "SDL/SDL_timer.h" #include "SDL/SDL_audio.h" #include "SDL/SDL_video.h" #else +#include #include "SDL.h" #include "SDL_timer.h" #include "SDL_audio.h" #include "SDL_video.h" #endif +#include "Core/Core.h" +#include "Core/Config.h" #include "base/display.h" #include "base/logging.h" #include "base/timeutil.h" #include "gfx_es2/gl_state.h" -#include "gfx_es2/glsl_program.h" -#include "file/zip_read.h" #include "input/input_state.h" #include "input/keycodes.h" -#include "base/NKCodeFromSDL.h" -#include "base/NativeApp.h" #include "net/resolve.h" +#include "base/NKCodeFromSDL.h" #include "util/const_map.h" #include "math/math_util.h" +GlobalUIState lastUIState = UISTATE_MENU; + #if defined(MAEMO) || defined(PANDORA) #define EGL #include "EGL/egl.h" @@ -344,10 +337,12 @@ int main(int argc, char *argv[]) { const SDL_VideoInfo* info = SDL_GetVideoInfo(); pixel_xres = info->current_w; pixel_yres = info->current_h; + g_Config.bFullScreen = true; } else { // set a sensible default resolution (2x) pixel_xres = 480 * 2; pixel_yres = 272 * 2; + g_Config.bFullScreen = false; } dp_xres = (float)pixel_xres; dp_yres = (float)pixel_yres; @@ -678,6 +673,15 @@ int main(int argc, char *argv[]) { UpdateInputState(&input_state); NativeUpdate(input_state); NativeRender(); +#ifndef MAEMO + if (lastUIState != globalUIState) { + lastUIState = globalUIState; + if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) + SDL_ShowCursor(SDL_DISABLE); + if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen) + SDL_ShowCursor(SDL_ENABLE); + } +#endif EndInputState(&input_state); From f0e47c2cede7313a057df66a6e01ba173df1e001 Mon Sep 17 00:00:00 2001 From: Peter Tissen Date: Tue, 5 Nov 2013 01:51:49 +0100 Subject: [PATCH 0837/1445] disable non-menu Main Window for all non ARM Qt platforms including Linux, Windows and OSX. --- base/QtMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index dbc2fcb681..f36163b29b 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -109,7 +109,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) #endif NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); -#if !defined(Q_OS_LINUX) || defined(ARM) +#if defined(ARM) MainUI w; w.resize(pixel_xres, pixel_yres); #ifdef ARM From 85722511984a96dfe9c3931543fc6566a419ce9d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 5 Nov 2013 20:49:59 +0100 Subject: [PATCH 0838/1445] Reverse the Moga Pro version check to check for not non-pro instead. May help dpad not working on some Pro's, if they have some new version numbers. --- android/src/com/henrikrydgard/libnative/NativeGLView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 644077cee6..bc891a41e7 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -54,7 +54,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, if (mController.init()) { Log.i(TAG, "MOGA initialized"); mController.setListener(this, new Handler()); - if (mController.getState(Controller.STATE_CURRENT_PRODUCT_VERSION) == Controller.ACTION_VERSION_MOGAPRO) { + if (mController.getState(Controller.STATE_CURRENT_PRODUCT_VERSION) != Controller.ACTION_VERSION_MOGA) { Log.i(TAG, "MOGA pro detected"); isMogaPro = true; } From 46bba78feb15eed9c2a304bf7a04e816d283f6e8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 6 Nov 2013 07:47:05 -0800 Subject: [PATCH 0839/1445] Avoid a mutex lock on a small parallel loop. --- thread/threadpool.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp index d79f2cd6c9..4524082e58 100644 --- a/thread/threadpool.cpp +++ b/thread/threadpool.cpp @@ -57,25 +57,26 @@ void ThreadPool::StartWorkers() { } void ThreadPool::ParallelLoop(std::function loop, int lower, int upper) { - mutex.lock(); - StartWorkers(); - int range = upper-lower; - if(range >= numThreads*2) { // don't parallelize tiny loops (this could be better, maybe add optional parameter that estimates work per iteration) + int range = upper - lower; + if (range >= numThreads * 2) { // don't parallelize tiny loops (this could be better, maybe add optional parameter that estimates work per iteration) + lock_guard guard(mutex); + StartWorkers(); + // could do slightly better load balancing for the generic case, // but doesn't matter since all our loops are power of 2 - int chunk = range/numThreads; + int chunk = range / numThreads; int s = lower; - for(int i=0; iProcess(std::bind(loop, s, s+chunk)); s+=chunk; } + // This is the final chunk. loop(s, upper); - for(int i=0; iWaitForCompletion(); } } else { loop(lower, upper); } - mutex.unlock(); } From 21b63f56ff7838b42ab6bc79ea5e515f0c312e70 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 11 Nov 2013 04:51:23 +1000 Subject: [PATCH 0840/1445] Fix overflow on nanoseconds which was causing issues on some platforms. --- base/mutex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index 89e40a7185..79072ad7cf 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -215,7 +215,7 @@ public: clock_gettime(CLOCK_REALTIME, &timeout); #endif timeout.tv_sec += milliseconds / 1000; - timeout.tv_nsec += milliseconds * 1000000; + timeout.tv_nsec += (milliseconds % 1000) * 1000000; pthread_mutex_lock(&mtx.native_handle()); pthread_cond_timedwait(&event_, &mtx.native_handle(), &timeout); pthread_mutex_unlock(&mtx.native_handle()); @@ -321,7 +321,7 @@ public: clock_gettime(CLOCK_REALTIME, &timeout); #endif timeout.tv_sec += milliseconds / 1000; - timeout.tv_nsec += milliseconds * 1000000; + timeout.tv_nsec += (milliseconds % 1000) * 1000000; pthread_cond_timedwait(&event_, &mtx.native_handle(), &timeout); #endif } From 726471f6657ae0ea2a94c57fc29fbdcf984aec13 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 12 Nov 2013 13:38:14 +0100 Subject: [PATCH 0841/1445] Add my_isnanorinf. --- android/project.properties | 2 +- math/math_util.h | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/android/project.properties b/android/project.properties index 137f19ac6a..f06f217ce4 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt # Project target. -target=android-17 +target=android-19 android.library=true diff --git a/math/math_util.h b/math/math_util.h index 516ab716f1..2c60aa2d8a 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -105,6 +105,16 @@ inline bool my_isnan(float f) { return ((f2u.u & 0x7F800000) == 0x7F800000) && (f2u.u & 0x7FFFFF); } +inline bool my_isnanorinf(float f) { + union { + float f; + uint32_t u; + } f2u; + f2u.f = f; + // NaNs have non-zero mantissa, infs have zero mantissa. That is, we just ignore the mantissa here. + return ((f2u.u & 0x7F800000) == 0x7F800000); +} + inline int is_even(float d) { float int_part; modff(d / 2.0f, &int_part); From 483e42f64e666ee47390b47e3405ad731d011f93 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 13 Nov 2013 00:25:41 +1000 Subject: [PATCH 0842/1445] Atomics: These do not need platform-specific ifdef's as the gcc inbuilts should work fine. --- base/mutex.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/base/mutex.h b/base/mutex.h index 79072ad7cf..14a8c576ec 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -24,12 +24,6 @@ #include #include #include - -#ifdef BLACKBERRY -#include -#elif defined(__SYMBIAN32__) -#include -#endif #endif #include "base/basictypes.h" @@ -54,10 +48,6 @@ public: #if defined(_WIN32) _WriteBarrier(); value = 0; -#elif defined(BLACKBERRY) - atomic_clr(&value, 1); -#elif defined(__SYMBIAN32__) - g_atomic_int_set(&value, 0); #else __sync_lock_release(&value); #endif @@ -67,10 +57,6 @@ public: bool test_and_set() { #if defined(_WIN32) return InterlockedExchange(&value, 1) != 0; -#elif defined(BLACKBERRY) - return atomic_set_value(&value, 1) != 0; -#elif defined(__SYMBIAN32__) - return !g_atomic_int_compare_and_exchange((volatile int*)&value, 0, 1); #else return __sync_lock_test_and_set(&value, 1) != 0; #endif From a3526b513ada09288993a542cb87cf33bd5ffaae Mon Sep 17 00:00:00 2001 From: Aapo Rantalainen Date: Wed, 13 Nov 2013 15:32:24 +0200 Subject: [PATCH 0843/1445] Maemo5: also maemo needs PFNGLDRAWTEXTURENVPROC --- gfx_es2/gl_state.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 781599bb63..96fb49d4d7 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -38,7 +38,7 @@ extern PFNGLMAPBUFFERPROC glMapBuffer; #endif -#if !defined(IOS) +#if !defined(IOS) && !defined(MAEMO) typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV; typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum From cf895f95d7ae75d4535cf252687fd4f9c4f1663b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 13 Nov 2013 17:09:35 +0100 Subject: [PATCH 0844/1445] Didn't mean to upgrade the project yet. --- android/project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/project.properties b/android/project.properties index f06f217ce4..137f19ac6a 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt # Project target. -target=android-19 +target=android-17 android.library=true From 60eb1a1de846b0a14b321f307668090f977e6efb Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 14 Nov 2013 13:49:12 +1000 Subject: [PATCH 0845/1445] Removal of glAlphaFuncQCOM as it did not serve a purpose. --- gfx_es2/gl_state.cpp | 18 ------------------ gfx_es2/gl_state.h | 15 --------------- gfx_es2/gpu_features.h | 1 - 3 files changed, 34 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 7816b56e78..ff0697aadf 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -10,7 +10,6 @@ #if defined(USING_GLES2) #if defined(ANDROID) || defined(BLACKBERRY) -PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; PFNGLDRAWTEXTURENVPROC glDrawTextureNV; @@ -48,17 +47,6 @@ void OpenGLState::Restore() { blendFuncSeparate.restore(); count++; blendColor.restore(); count++; -#if defined(ANDROID) || defined(BLACKBERRY) - if (gl_extensions.QCOM_alpha_test) { - alphaTestQCOM.restore(); - } - count++; - if (gl_extensions.QCOM_alpha_test) { - alphaFuncQCOM.restore(); - } - count++; -#endif - scissorTest.restore(); count++; scissorRect.restore(); count++; @@ -264,12 +252,6 @@ void CheckGLExtensions() { glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" ); } - gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0; - // Load extensions that are not auto-loaded by Android. - if (gl_extensions.QCOM_alpha_test) { - glAlphaFuncQCOM = (PFNGLALPHAFUNCQCOMPROC)eglGetProcAddress("glAlphaFuncQCOM"); - } - // Look for EGL extensions EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 96fb49d4d7..b47f4f6f8f 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -19,14 +19,6 @@ #if defined(ANDROID) || defined(BLACKBERRY) // Additional extensions not included in GLES2/gl2ext.h from the NDK -/* GL_QCOM_alpha_test */ -#define GL_ALPHA_TEST_QCOM 0x0BC0 -#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 -#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 - -typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); -extern PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM; - typedef uint64_t EGLuint64NV; typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); @@ -288,13 +280,6 @@ public: STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp; STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; -#if defined(ANDROID) || defined(BLACKBERRY) - // QCOM Alpha Test. Old school alpha test but ported to GLES2. Does not seem to benefit - // speed very much so probably not worth the trouble. - BoolState alphaTestQCOM; - STATE2(glAlphaFuncQCOM, GLenum, GLclampf, GL_ALWAYS, 0.0f) alphaFuncQCOM; -#endif - // Only works on Win32, all other platforms are "force-vsync" void SetVSyncInterval(int interval); // one of the above VSYNC, or a higher number for multi-frame waits (could be useful for 30hz games) }; diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 75f0871428..282432734f 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -38,7 +38,6 @@ struct GLExtensions { bool FBO_EXT; bool PBO_ARB; bool EXT_swap_control_tear; - bool QCOM_alpha_test; bool OES_mapbuffer; bool OES_vertex_array_object; bool EXT_shader_framebuffer_fetch; From 1e262d169986fd8193d03a089ce6feacc53e6a63 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 15 Nov 2013 08:21:00 -0800 Subject: [PATCH 0846/1445] Fix a redeclaration warning. --- gfx_es2/fbo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 4e767d120b..2d9f8b2116 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -7,9 +7,13 @@ #include "gfx_es2/gl_state.h" #if defined(USING_GLES2) && !defined(BLACKBERRY) +#ifndef GL_READ_FRAMEBUFFER #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER +#endif +#ifndef GL_RGBA8 #define GL_RGBA8 GL_RGBA +#endif #ifndef GL_DEPTH_COMPONENT24 #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #endif From 35b84eecacf2ba49db8e34de29d0dabb1b095ee9 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 17 Nov 2013 15:19:13 +1000 Subject: [PATCH 0847/1445] Update to v1.4 of rg_etc1 to fix 64-bit compile bug with gcc. --- ext/rg_etc1/rg_etc1.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ext/rg_etc1/rg_etc1.cpp b/ext/rg_etc1/rg_etc1.cpp index b03377ec36..25e9d8d7f3 100644 --- a/ext/rg_etc1/rg_etc1.cpp +++ b/ext/rg_etc1/rg_etc1.cpp @@ -4,6 +4,10 @@ // For more information Ericsson Texture Compression (ETC/ETC1), see: // http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt // +// v1.04 - 5/15/14 - Fix signed vs. unsigned subtraction problem (noticed when compiled with gcc) in pack_etc1_block_init(). +// This issue would cause an assert when this func. was called in debug. (Note this module was developed/testing with MSVC, +// I still need to test it throughly when compiled with gcc.) +// // v1.03 - 5/12/13 - Initial public release #include "rg_etc1.h" @@ -1905,7 +1909,7 @@ done: for (uint packed_c = 0; packed_c < limit; packed_c++) { int v = etc1_decode_value(diff, inten, selector, packed_c); - uint err = labs(v - color); + uint err = labs(v - static_cast(color)); if (err < best_error) { best_error = err; From d6304959b0066866bb9802cf51f8ff5f623032eb Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 17 Nov 2013 15:34:51 +1000 Subject: [PATCH 0848/1445] Support ETC1 compression in atlastool. --- tools/atlastool.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index cab032bd33..707c626bd9 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -45,6 +45,7 @@ using namespace std; static int global_id; +static bool etc1 = false; static bool highcolor = false; @@ -768,11 +769,16 @@ int main(int argc, char **argv) { // /usr/share/fonts/truetype/msttcorefonts/Arial_Black.ttf // /usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-R.ttf - CHECK(argc >= 3); + CHECK(argc >= 3); if (argc > 3) { - highcolor = true; - printf("RGBA8888 enabled!\n"); + if (!strcmp(argv[3], "etc1")) { + printf("ETC1 enabled!\n"); + etc1 = true; + } else if (!strcmp(argv[3], "8888")) { + highcolor = true; + printf("RGBA8888 enabled!\n"); + } } printf("Reading script %s\n", argv[1]); const char *atlas_name = argv[2]; @@ -864,7 +870,10 @@ int main(int argc, char **argv) { printf("Resolving...\n"); vector results = bucket.Resolve(image_width, dest); - if (highcolor) { + if (etc1) { + printf("Writing .ZIM %ix%i ETC1...\n", dest.width(), dest.height()); + dest.SaveZIM(image_name.c_str(), ZIM_ETC1 | ZIM_ZLIB_COMPRESSED); + } else if (highcolor) { printf("Writing .ZIM %ix%i RGBA8888...\n", dest.width(), dest.height()); dest.SaveZIM(image_name.c_str(), ZIM_RGBA8888 | ZIM_ZLIB_COMPRESSED); } else { From c53dbbf341ae44fa1a380afbf7d655187a00da4c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Nov 2013 01:33:24 -0800 Subject: [PATCH 0849/1445] Add really basic float support to expr parser. Requires update to consumers, though (even just a stub returning 0.) --- math/expression_parser.cpp | 90 ++++++++++++++++++++++++++++++++------ math/expression_parser.h | 7 +++ 2 files changed, 83 insertions(+), 14 deletions(-) diff --git a/math/expression_parser.cpp b/math/expression_parser.cpp index c80981c0c0..946898c586 100644 --- a/math/expression_parser.cpp +++ b/math/expression_parser.cpp @@ -11,7 +11,7 @@ typedef enum { EXOP_LOGOR, EXOP_TERTIF, EXOP_TERTELSE, EXOP_NUMBER, EXOP_MEM, EXOP_NONE, EXOP_COUNT } ExpressionOpcodeType; -typedef enum { EXCOMM_CONST, EXCOMM_REF, EXCOMM_OP } ExpressionCommand; +typedef enum { EXCOMM_CONST, EXCOMM_CONST_FLOAT, EXCOMM_REF, EXCOMM_OP } ExpressionCommand; static char expressionError[256]; @@ -147,6 +147,28 @@ bool parseNumber(char* str, int defaultrad, int len, uint32& result) return true; } +// Parse only a float, and return as float bits. +static bool parseFloat(const char *str, int len, uint32 &result) +{ + bool foundDecimal = false; + for (int i = 0; i < len; ++i) + { + if (str[i] == '.') + { + if (foundDecimal) + return false; + foundDecimal = true; + continue; + } + if (str[i] < '0' || str[i] > '9') + return false; + } + + float f = (float)atof(str); + memcpy(&result, &f, sizeof(result)); + return foundDecimal; +} + ExpressionOpcodeType getExpressionOpcode(const char* str, int& ReturnLen, ExpressionOpcodeType LastOpcode) { int longestlen = 0; @@ -177,7 +199,7 @@ bool isAlphaNum(char c) if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || - c == '@' || c == '_' || c == '$') + c == '@' || c == '_' || c == '$' || c == '.') { return true; } else { @@ -216,13 +238,16 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf subStr[subPos] = 0; uint32 value; - if (parseNumber(subStr,16,subPos,value) == false) + bool isFloat = false; + if (parseFloat(subStr,subPos,value) == true) + isFloat = true; + else if (parseNumber(subStr,16,subPos,value) == false) { sprintf(expressionError,"Invalid number \"%s\"",subStr); return false; } - dest.push_back(ExpressionPair(EXCOMM_CONST,value)); + dest.push_back(ExpressionPair(isFloat?EXCOMM_CONST_FLOAT:EXCOMM_CONST,value)); lastOpcode = EXOP_NUMBER; } else if ((first >= 'a' && first <= 'z') || first == '@') { @@ -350,6 +375,7 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf switch (dest[i].first) { case EXCOMM_CONST: + case EXCOMM_CONST_FLOAT: testPos += sprintf(&test[testPos],"0x%04X ",dest[i].second); break; case EXCOMM_REF: @@ -371,6 +397,8 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, uint32 opcode; std::vector valueStack; unsigned int arg[5]; + float fArg[5]; + bool useFloat = false; while (num < exp.size()) { @@ -379,7 +407,12 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXCOMM_CONST: // konstante zahl valueStack.push_back(exp[num++].second); break; + case EXCOMM_CONST_FLOAT: + useFloat = true; + valueStack.push_back(exp[num++].second); + break; case EXCOMM_REF: + useFloat = useFloat || funcs->getReferenceType(exp[num].second) == EXPR_TYPE_FLOAT; opcode = funcs->getReferenceValue(exp[num++].second); valueStack.push_back(opcode); break; @@ -395,6 +428,8 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, arg[l] = valueStack[valueStack.size()-1]; valueStack.pop_back(); } + // In case of float representation. + memcpy(fArg, arg, sizeof(fArg)); switch (opcode) { @@ -425,7 +460,10 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXOP_SIGNPLUS: // keine aktion nötig break; case EXOP_SIGNMINUS: // -0 - valueStack.push_back(0-arg[0]); + if (useFloat) + valueStack.push_back(0.0-fArg[0]); + else + valueStack.push_back(0-arg[0]); break; case EXOP_BITNOT: // ~b valueStack.push_back(~arg[0]); @@ -434,7 +472,10 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, valueStack.push_back(!arg[0]); break; case EXOP_MUL: // a*b - valueStack.push_back(arg[1]*arg[0]); + if (useFloat) + valueStack.push_back(fArg[1]*fArg[0]); + else + valueStack.push_back(arg[1]*arg[0]); break; case EXOP_DIV: // a/b if (arg[0] == 0) @@ -442,7 +483,10 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, sprintf(expressionError,"Division by zero"); return false; } - valueStack.push_back(arg[1]/arg[0]); + if (useFloat) + valueStack.push_back(fArg[1]/fArg[0]); + else + valueStack.push_back(arg[1]/arg[0]); break; case EXOP_MOD: // a%b if (arg[0] == 0) @@ -453,10 +497,16 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, valueStack.push_back(arg[1]%arg[0]); break; case EXOP_ADD: // a+b - valueStack.push_back(arg[1]+arg[0]); + if (useFloat) + valueStack.push_back(fArg[1]+fArg[0]); + else + valueStack.push_back(arg[1]+arg[0]); break; case EXOP_SUB: // a-b - valueStack.push_back(arg[1]-arg[0]); + if (useFloat) + valueStack.push_back(fArg[1]-fArg[0]); + else + valueStack.push_back(arg[1]-arg[0]); break; case EXOP_SHL: // a<>arg[0]); break; case EXOP_GREATEREQUAL: // a >= b - valueStack.push_back(arg[1]>=arg[0]); + if (useFloat) + valueStack.push_back(fArg[1]>=fArg[0]); + else + valueStack.push_back(arg[1]>=arg[0]); break; case EXOP_GREATER: // a > b - valueStack.push_back(arg[1]>arg[0]); + if (useFloat) + valueStack.push_back(fArg[1]>fArg[0]); + else + valueStack.push_back(arg[1]>arg[0]); break; case EXOP_LOWEREQUAL: // a <= b - valueStack.push_back(arg[1]<=arg[0]); + if (useFloat) + valueStack.push_back(fArg[1]<=fArg[0]); + else + valueStack.push_back(arg[1]<=arg[0]); break; case EXOP_LOWER: // a < b - valueStack.push_back(arg[1] ExpressionPair; typedef std::vector PostfixExpression; +enum ExpressionType +{ + EXPR_TYPE_UINT = 0, + EXPR_TYPE_FLOAT = 2, +}; + class IExpressionFunctions { public: virtual bool parseReference(char* str, uint32& referenceIndex) = 0; virtual bool parseSymbol(char* str, uint32& symbolValue) = 0; virtual uint32 getReferenceValue(uint32 referenceIndex) = 0; + virtual ExpressionType getReferenceType(uint32 referenceIndex) = 0; virtual bool getMemoryValue(uint32 address, int size, uint32& dest, char* error) = 0; }; From 2583c67c3294f080d7edf7391860ab5c4421b196 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 18 Nov 2013 01:57:06 +1000 Subject: [PATCH 0850/1445] Qt: Use native TTF draw instead of font atlas. --- gfx_es2/draw_text.cpp | 119 +++++++++++++++++++++++++++++++++++------- gfx_es2/draw_text.h | 14 ++++- ui/ui_context.cpp | 2 +- 3 files changed, 115 insertions(+), 20 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 83d39459a0..76f561d8c4 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -193,21 +193,6 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float target.Flush(true); } -void TextDrawer::OncePerFrame() { - frameCount_++; - // Use a prime number to reduce clashing with other rhythms - if (frameCount_ % 23 == 0) { - for (auto iter = cache_.begin(); iter != cache_.end();) { - if (frameCount_ - iter->second->lastUsedFrame > 100) { - delete iter->second; - cache_.erase(iter++); - } else { - iter++; - } - } - } -} - #else TextDrawer::TextDrawer() { @@ -216,12 +201,34 @@ TextDrawer::TextDrawer() { } TextDrawer::~TextDrawer() { - + for (auto iter = cache_.begin(); iter != cache_.end(); ++iter) { + glDeleteTextures(1, &iter->second->textureHandle); + delete iter->second; + } + cache_.clear(); } uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) { +#ifdef USING_QT_UI + uint32_t fontHash = hash::Fletcher((const uint8_t *)fontName, strlen(fontName)); + fontHash ^= size; + fontHash ^= flags << 10; + + auto iter = fontMap_.find(fontHash); + if (iter != fontMap_.end()) { + fontHash_ = fontHash; + return fontHash; + } + + fontSize_ = size; + +// fontMap_[fontHash] = font; + fontHash_ = fontHash; + return fontHash; +#else ELOG("System fonts not supported on this platform"); return 0; +#endif } void TextDrawer::SetFont(uint32_t fontHandle) { @@ -229,16 +236,77 @@ void TextDrawer::SetFont(uint32_t fontHandle) { } void TextDrawer::MeasureString(const char *str, float *w, float *h) { +#ifdef USING_QT_UI + QFontMetrics fm(QFont("default", fontSize_)); + QSize size = fm.size(0, str); + *w = (float)size.width() * fontScaleX_; + *h = (float)size.height() * fontScaleY_; +#else *w = 0; *h = 0; +#endif } void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align) { +#ifdef USING_QT_UI + uint32_t stringHash = hash::Fletcher((const uint8_t *)str, strlen(str)); + uint32_t entryHash = stringHash ^ fontHash_; + + target.Flush(true); -} + TextStringEntry *entry; -void TextDrawer::OncePerFrame() { + auto iter = cache_.find(entryHash); + if (iter != cache_.end()) { + entry = iter->second; + entry->lastUsedFrame = frameCount_; + glBindTexture(GL_TEXTURE_2D, entry->textureHandle); + } else { + QFontMetrics fm(QFont("default", fontSize_)); + QSize size = fm.size(0, str); + QImage image((size.width() + 3) & ~ 3, (size.height() + 3) & ~ 3, QImage::Format_ARGB32_Premultiplied); + if (image.isNull()) { + return; + } + image.fill(0); + QPainter painter; + painter.begin(&image); + painter.setFont(QFont("default", fontSize_)); + painter.setPen(Qt::white); + painter.drawText(0, fontSize_, QString::fromLocal8Bit(str)); + painter.end(); + + entry = new TextStringEntry(); + glGenTextures(1, &entry->textureHandle); + glBindTexture(GL_TEXTURE_2D, entry->textureHandle); + entry->bmWidth = entry->width = image.width(); + entry->bmHeight = entry->height = image.height(); + entry->lastUsedFrame = frameCount_; + + uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight]; + for (int x = 0; x < entry->bmWidth; x++) { + for (int y = 0; y < entry->bmHeight; y++) { + bitmapData[entry->bmWidth * y + x] = 0xfff0 | image.pixel(x, y) >> 28; + } + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, entry->bmWidth, entry->bmHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, bitmapData); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + delete [] bitmapData; + + cache_[entryHash] = entry; + } + float w = entry->bmWidth * fontScaleX_; + float h = entry->bmHeight * fontScaleY_; + DrawBuffer::DoAlign(align, &x, &y, &w, &h); + target.DrawTexRect(x, y, x + w, y + h, 0.0f, 0.0f, 1.0f, 1.0f, color); + target.Flush(true); +#endif } #endif @@ -264,3 +332,18 @@ void TextDrawer::DrawStringRect(DrawBuffer &target, const char *str, const Bound DrawString(target, str, x, y, color, align); } + +void TextDrawer::OncePerFrame() { + frameCount_++; + // Use a prime number to reduce clashing with other rhythms + if (frameCount_ % 23 == 0) { + for (auto iter = cache_.begin(); iter != cache_.end();) { + if (frameCount_ - iter->second->lastUsedFrame > 100) { + delete iter->second; + cache_.erase(iter++); + } else { + iter++; + } + } + } +} diff --git a/gfx_es2/draw_text.h b/gfx_es2/draw_text.h index 301e16b088..eeae559624 100644 --- a/gfx_es2/draw_text.h +++ b/gfx_es2/draw_text.h @@ -13,6 +13,14 @@ #include "base/basictypes.h" #include "gfx_es2/draw_buffer.h" +#ifdef USING_QT_UI +#include +#include +#include +#include +#include +#endif + struct TextStringEntry { uint32_t textureHandle; int width; @@ -58,4 +66,8 @@ private: uint32_t fontHash_; // The key is the CityHash of the string xor the fontHash_. std::map cache_; -}; \ No newline at end of file + +#ifdef USING_QT_UI + int fontSize_; +#endif +}; diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 77d6df6aba..5e6717fb4c 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -25,7 +25,7 @@ void UIContext::Init(const GLSLProgram *uishader, const GLSLProgram *uishadernot uitexture_ = uitexture; uidrawbuffer_ = uidrawbuffer; uidrawbufferTop_ = uidrawbufferTop; -#ifdef _WIN32 +#if defined(_WIN32) || defined(USING_QT_UI) textDrawer_ = new TextDrawer(); #else textDrawer_ = 0; From 957defc419031059eafe0993b0bc319f58d7eb13 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 18 Nov 2013 02:36:49 +1000 Subject: [PATCH 0851/1445] Buildfix for Linux. --- gfx_es2/draw_text.cpp | 7 +++++++ gfx_es2/draw_text.h | 8 -------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 76f561d8c4..2ecf20de7f 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -5,6 +5,13 @@ #include "util/hash/hash.h" #include "util/text/utf8.h" +#ifdef USING_QT_UI +#include +#include +#include +#include +#endif + #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN diff --git a/gfx_es2/draw_text.h b/gfx_es2/draw_text.h index eeae559624..5fc60d9c8b 100644 --- a/gfx_es2/draw_text.h +++ b/gfx_es2/draw_text.h @@ -13,14 +13,6 @@ #include "base/basictypes.h" #include "gfx_es2/draw_buffer.h" -#ifdef USING_QT_UI -#include -#include -#include -#include -#include -#endif - struct TextStringEntry { uint32_t textureHandle; int width; From 35de964293322abab016c076be85ecd8561390ad Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 18 Nov 2013 02:53:38 +1000 Subject: [PATCH 0852/1445] Qt: Use pixel size instead of point size. Set color. --- gfx_es2/draw_text.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 2ecf20de7f..7fb4ce15a0 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -244,7 +244,9 @@ void TextDrawer::SetFont(uint32_t fontHandle) { void TextDrawer::MeasureString(const char *str, float *w, float *h) { #ifdef USING_QT_UI - QFontMetrics fm(QFont("default", fontSize_)); + QFont font("default"); + font.setPixelSize(fontSize_); + QFontMetrics fm(font); QSize size = fm.size(0, str); *w = (float)size.width() * fontScaleX_; *h = (float)size.height() * fontScaleY_; @@ -269,7 +271,9 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float entry->lastUsedFrame = frameCount_; glBindTexture(GL_TEXTURE_2D, entry->textureHandle); } else { - QFontMetrics fm(QFont("default", fontSize_)); + QFont font("default"); + font.setPixelSize(fontSize_); + QFontMetrics fm(font); QSize size = fm.size(0, str); QImage image((size.width() + 3) & ~ 3, (size.height() + 3) & ~ 3, QImage::Format_ARGB32_Premultiplied); if (image.isNull()) { @@ -279,8 +283,8 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float QPainter painter; painter.begin(&image); - painter.setFont(QFont("default", fontSize_)); - painter.setPen(Qt::white); + painter.setFont(font); + painter.setPen(color); painter.drawText(0, fontSize_, QString::fromLocal8Bit(str)); painter.end(); From ecc62f65b68fe1818cb3b69dbeff99b8117f5630 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 17 Nov 2013 23:20:13 +0100 Subject: [PATCH 0853/1445] Revert "Fix a redeclaration warning." This reverts commit 1e262d169986fd8193d03a089ce6feacc53e6a63. --- gfx_es2/fbo.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 2d9f8b2116..4e767d120b 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -7,13 +7,9 @@ #include "gfx_es2/gl_state.h" #if defined(USING_GLES2) && !defined(BLACKBERRY) -#ifndef GL_READ_FRAMEBUFFER #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER -#endif -#ifndef GL_RGBA8 #define GL_RGBA8 GL_RGBA -#endif #ifndef GL_DEPTH_COMPONENT24 #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #endif From d48c3570feb572cf9e33ac20e8207f0238060662 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 17 Nov 2013 23:41:58 +0100 Subject: [PATCH 0854/1445] Fix the warnings in fbo.cpp without breaking things, hopefully. Now only using GL_READ_FRAMEBUFFER and GL_DRAW_FR... when there's support. --- gfx_es2/fbo.cpp | 72 ++++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 4e767d120b..99b52420a1 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -7,9 +7,15 @@ #include "gfx_es2/gl_state.h" #if defined(USING_GLES2) && !defined(BLACKBERRY) + +#ifndef GL_READ_FRAMEBUFFER +// Careful - our ES3 header defines these. Means that we must make sure +// to only use them if ES3 support is detected to be available and otherwise +// use GL_FRAMEBUFFER only. #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER -#define GL_RGBA8 GL_RGBA +#endif + #ifndef GL_DEPTH_COMPONENT24 #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #endif @@ -170,10 +176,10 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); // Bind it all together - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); } else { ILOG("Creating %i x %i FBO using separate stencil", width, height); // TEGRA @@ -189,10 +195,10 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); // Bind it all together - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); } #else fbo->stencil_buffer = 0; @@ -203,10 +209,10 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); // Bind it all together - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); #endif GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -233,9 +239,9 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F void fbo_unbind() { CheckGLExtensions(); - if(gl_extensions.FBO_ARB){ - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - }else{ + if (gl_extensions.FBO_ARB) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } else { #ifndef USING_GLES2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); #endif @@ -246,8 +252,14 @@ void fbo_unbind() { } void fbo_bind_as_render_target(FBO *fbo) { - if(gl_extensions.FBO_ARB){ - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + if (gl_extensions.FBO_ARB) { + if (gl_extensions.GLES3) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + } else { + // This will collide with bind_for_read - but there's nothing in ES 2.0 + // that actually separate them anyway of course, so doesn't matter. + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + } }else{ #ifndef USING_GLES2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); @@ -256,9 +268,15 @@ void fbo_bind_as_render_target(FBO *fbo) { } void fbo_bind_for_read(FBO *fbo) { - if(gl_extensions.FBO_ARB){ - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); - }else{ + if (gl_extensions.FBO_ARB) { + if (gl_extensions.GLES3) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); + } else { + // This will collide with bind_as_render_target - but there's nothing in ES 2.0 + // that actually separate them anyway of course, so doesn't matter. + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + } + } else { #ifndef USING_GLES2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); #endif @@ -272,14 +290,14 @@ void fbo_bind_color_as_texture(FBO *fbo, int color) { } void fbo_destroy(FBO *fbo) { - if(gl_extensions.FBO_ARB){ - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + if (gl_extensions.FBO_ARB) { + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fbo->handle); glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); - }else{ + } else { #ifndef USING_GLES2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); From 1a98d8345d827b93d43de99c65b661e4dc5c1ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 18 Nov 2013 14:02:56 +0100 Subject: [PATCH 0855/1445] Move out PathBrowser from ppsspp --- file/path.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++ file/path.h | 40 ++++++++++++++++++++++++++ native.vcxproj | 2 ++ native.vcxproj.filters | 6 ++++ 4 files changed, 112 insertions(+) create mode 100644 file/path.cpp create mode 100644 file/path.h diff --git a/file/path.cpp b/file/path.cpp new file mode 100644 index 0000000000..d456817282 --- /dev/null +++ b/file/path.cpp @@ -0,0 +1,64 @@ +#include "file/path.h" + +// Normalize slashes. +void PathBrowser::SetPath(const std::string &path) { + if (path[0] == '!') { + path_ = path; + return; + } + path_ = path; + for (size_t i = 0; i < path_.size(); i++) { + if (path_[i] == '\\') path_[i] = '/'; + } + if (!path_.size() || (path_[path_.size() - 1] != '/')) + path_ += "/"; +} + +void PathBrowser::GetListing(std::vector &fileInfo, const char *filter) { +#ifdef _WIN32 + if (path_ == "/") { + // Special path that means root of file system. + std::vector drives = getWindowsDrives(); + for (auto drive = drives.begin(); drive != drives.end(); ++drive) { + FileInfo fake; + fake.fullName = *drive; + fake.name = *drive; + fake.isDirectory = true; + fake.exists = true; + fake.size = 0; + fake.isWritable = false; + fileInfo.push_back(fake); + } + } +#endif + + getFilesInDir(path_.c_str(), &fileInfo, filter); +} + +// TODO: Support paths like "../../hello" +void PathBrowser::Navigate(const std::string &path) { + if (path[0] == '!') + return; + + if (path == ".") + return; + if (path == "..") { + // Upwards. + // Check for windows drives. + if (path_.size() == 3 && path_[1] == ':') { + path_ = "/"; + } else { + size_t slash = path_.rfind('/', path_.size() - 2); + if (slash != std::string::npos) + path_ = path_.substr(0, slash + 1); + } + } + else { + if (path[1] == ':' && path_ == "/") + path_ = path; + else + path_ = path_ + path; + if (path_[path_.size() - 1] != '/') + path_ += "/"; + } +} diff --git a/file/path.h b/file/path.h new file mode 100644 index 0000000000..1543262990 --- /dev/null +++ b/file/path.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +#include "file/file_util.h" + +// Abstraction above path that lets you navigate easily. +// "/" is a special path that means the root of the file system. On Windows, +// listing this will yield drives. +class PathBrowser { +public: + PathBrowser() {} + PathBrowser(std::string path) { SetPath(path); } + + void SetPath(const std::string &path); + void GetListing(std::vector &fileInfo, const char *filter = 0); + void Navigate(const std::string &path); + + std::string GetPath() { + if (path_ != "/") + return path_; + else + return ""; + } + std::string GetFriendlyPath() { + std::string str = GetPath(); + /* +#ifdef ANDROID + if (!memcmp(str.c_str(), g_Config.memCardDirectory.c_str(), g_Config.memCardDirectory.size())) + { + str = str.substr(g_Config.memCardDirectory.size()); + } +#endif*/ + return str; + } + + std::string path_; +}; + diff --git a/native.vcxproj b/native.vcxproj index 0f64ac0767..0bdf5674f1 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -217,6 +217,7 @@ + @@ -353,6 +354,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 1ddb87dee8..c3e2b2e4ea 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -132,6 +132,9 @@ file + + file + gfx @@ -375,6 +378,9 @@ file + + file + gfx From c60ea2f96c8a17fde20c2b580111d159fa0cfa5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 18 Nov 2013 14:05:00 +0100 Subject: [PATCH 0856/1445] Don't forget Android.mk --- Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/Android.mk b/Android.mk index 0800a9c8ab..c2fc541a2a 100644 --- a/Android.mk +++ b/Android.mk @@ -32,6 +32,7 @@ LOCAL_SRC_FILES :=\ file/easy_file.cpp \ file/chunk_file.cpp \ file/file_util.cpp \ + file/path.cpp \ file/ini_file.cpp \ file/zip_read.cpp \ json/json_writer.cpp \ From adaa0ef3cc2f9ac61a745f2480573ad046a1e884 Mon Sep 17 00:00:00 2001 From: Peter Tissen Date: Mon, 18 Nov 2013 14:47:19 +0100 Subject: [PATCH 0857/1445] basic documentation for the atlastool --- tools/README.txt | 64 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/tools/README.txt b/tools/README.txt index f22674b841..26618711e3 100644 --- a/tools/README.txt +++ b/tools/README.txt @@ -1,3 +1,65 @@ These are simple tools to create the ZIM texture format and texture atlases based on it. -Documentation is TODO but they are easy to use. \ No newline at end of file +atlastool + + path to the configuration file for the atlas to be generated + description of the format is below + + the prefix of the output files, the output files will be: + _atlas.zim + _atlas.cpp + _atlas.h + + texture format of the atlas, can be: + 8888 - RGBA8 + etc1 - ETC1 compressed + - uses RGBA4444 + +Basic configuration file format look like this: + + + font [] + image + +All the blocks enclosed with "<" ">" need to be replaced with the respective options, for +example one line in one of out configuration files is: + + font UBUNTU24 C:/Windows/Fonts/KozGoPro-Medium.otf UWkhcsGR 24 + + size is the horizontal size of the atlas, should be a power of 2, the vertical size is + automatically adjusted to be smallest power of 2 that can fit the whole atlas. + + the name of the font in the generated *.h and *.cpp files + + path to the font, can use *.otf and *.ttf fonts + + defines which glyphs should be copied into the atlas, can use any combination + of the following: + U - US ASCII + W - Latin-1 extras 1 + E - Latin-1 Extended A (needed for Hungarian etc) + e - Latin-1 Extended B (for some African and latinized asian languages?) + k - Katakana + h - Hiragana + s - ShiftJIS symbols + H - Hebrew + G - Greek + R - Russian + c - All Kanji, filtered though! + T - Thai + K - Korean (hangul) + + height in pixels of the glyphs in the font atlas + + ??? no idea + + name of this symbol in the generated *.h and *.cpp files + + path to the image file that is going to be used + + can be any of: + copy - copies the image as-is + r2a - red2alpha, red channel to alpha, color is a solid while + r2i - red to intensity, full alpha + pre - premultiply alpha + p2a - pink (255,0,255) to alpha From daffc235b8d3afe2a4f8d6c1298aafc6d700afb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 18 Nov 2013 16:27:39 +0100 Subject: [PATCH 0858/1445] Minor stuff in http_client --- net/http_client.cpp | 33 ++++++++++++++++++++------------- net/http_client.h | 3 ++- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 6671e5070c..202f8b128b 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -22,8 +22,6 @@ #include "net/resolve.h" #include "net/url.h" -// #include "strings/strutil.h" - namespace net { Connection::Connection() @@ -54,7 +52,7 @@ bool Connection::Resolve(const char *host, int port) { char port_str[10]; snprintf(port_str, sizeof(port_str), "%d", port); - + std::string err; if (!net::DNSResolve(host, port_str, &resolved_, err)) { ELOG("Failed to resolve host %s: %s", host, err.c_str()); @@ -144,7 +142,11 @@ void DeChunk(Buffer *inbuffer, Buffer *outbuffer) { } } -int Client::GET(const char *resource, Buffer *output) { +int Client::GET(const char *resource, Buffer *output, float *progress) { + if (progress) { + *progress = 0; + } + Buffer buffer; const char *tpl = "GET %s HTTP/1.1\r\n" @@ -213,29 +215,35 @@ int Client::GET(const char *resource, Buffer *output) { } } + if (!contentLength && progress) { + // Content length is unknown. + // Set progress to 1% so it looks like something is happening... + *progress = 0.01f; + } + // output now contains the rest of the reply. Dechunk it. if (chunked) { + // TODO: Turn this into a loop and update progress DeChunk(&readbuf, output); } else { + // TODO: Turn this into a loop and update progress output->Append(readbuf); } // If it's gzipped, we decompress it and put it back in the buffer. if (gzip) { - std::string compressed; + std::string compressed, decompressed; output->TakeAll(&compressed); - // What is this garbage? - //if (compressed[0] == 0x8e) -// compressed = compressed.substr(4); - std::string decompressed; bool result = decompress_string(compressed, &decompressed); if (!result) { ELOG("Error decompressing using zlib"); + *progress = 0.0f; return -1; } output->Append(decompressed); } + *progress = 1.0f; return code; } @@ -293,8 +301,7 @@ Download::~Download() { } -void Download::Start(std::shared_ptr self) -{ +void Download::Start(std::shared_ptr self) { std::thread th(std::bind(&Download::Do, this, self)); th.detach(); } @@ -344,9 +351,9 @@ void Download::Do(std::shared_ptr self) { } // TODO: Allow cancelling during a GET somehow... - int resultCode = client.GET(fileUrl.Resource().c_str(), &buffer_); + int resultCode = client.GET(fileUrl.Resource().c_str(), &buffer_, &progress_); if (resultCode == 200) { - ILOG("Completed downloading %s to %s", url_.c_str(), outfile_.c_str()); + ILOG("Completed downloading %s to %s", url_.c_str(), outfile_.empty() ? "memory" : outfile_.c_str()); if (!outfile_.empty() && !buffer_.FlushToFile(outfile_.c_str())) { ELOG("Failed writing download to %s", outfile_.c_str()); } diff --git a/net/http_client.h b/net/http_client.h index c9b18acfe6..dd19aac405 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -58,7 +58,7 @@ public: ~Client(); // Return value is the HTTP return code. 200 means OK. < 0 means some local error. - int GET(const char *resource, Buffer *output); + int GET(const char *resource, Buffer *output, float *progress = 0); // Return value is the HTTP return code. int POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output); @@ -114,6 +114,7 @@ public: ~Downloader() { CancelAll(); } + std::shared_ptr StartDownload(const std::string &url, const std::string &outfile); // Drops finished downloads from the list. From cfeb9180333e3c16b05bf1f0d553894eda46c2d6 Mon Sep 17 00:00:00 2001 From: shenweip Date: Mon, 18 Nov 2013 23:45:44 +0800 Subject: [PATCH 0859/1445] Add strcmpIgnore func. --- base/stringutil.cpp | 6 ++++++ base/stringutil.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/base/stringutil.cpp b/base/stringutil.cpp index 414fe117c9..c1d5ed35e6 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -233,4 +233,10 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st pos += dest.size(); } return result; +} + +int strcmpIgnore(std::string str1, std::string str2, std::string ignorestr1, std::string ignorestr2) { + str1 = ReplaceAll(str1, ignorestr1, ignorestr2); + str2 = ReplaceAll(str2, ignorestr1, ignorestr2); + return strcmp(str1.c_str(),str2.c_str()); } \ No newline at end of file diff --git a/base/stringutil.h b/base/stringutil.h index 97fc6051ae..c94638c640 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -133,6 +133,8 @@ void SplitString(const std::string& str, const char delim, std::vector static std::string ValueToString(const N value) { From 9bf31c9ad5d82b4818fff71d7695fefef154b920 Mon Sep 17 00:00:00 2001 From: shenweip Date: Tue, 19 Nov 2013 00:33:18 +0800 Subject: [PATCH 0860/1445] Add a comment. --- base/stringutil.h | 1 + 1 file changed, 1 insertion(+) diff --git a/base/stringutil.h b/base/stringutil.h index c94638c640..3cd9a9f3d4 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -133,6 +133,7 @@ void SplitString(const std::string& str, const char delim, std::vector From a54d58f8e350bdf3b1fb30f7c70da204dc51eb4f Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 19 Nov 2013 23:52:25 +1000 Subject: [PATCH 0861/1445] Improve Qt fonts. --- gfx_es2/draw_text.cpp | 23 +++++++++++------------ gfx_es2/draw_text.h | 12 ++++++++---- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 7fb4ce15a0..7161a526db 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -217,7 +217,8 @@ TextDrawer::~TextDrawer() { uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) { #ifdef USING_QT_UI - uint32_t fontHash = hash::Fletcher((const uint8_t *)fontName, strlen(fontName)); + // We will only use the default font + uint32_t fontHash = 0; //hash::Fletcher((const uint8_t *)fontName, strlen(fontName)); fontHash ^= size; fontHash ^= flags << 10; @@ -227,9 +228,9 @@ uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) { return fontHash; } - fontSize_ = size; - -// fontMap_[fontHash] = font; + QFont* font = new QFont(); + font->setPixelSize(size + 4); + fontMap_[fontHash] = font; fontHash_ = fontHash; return fontHash; #else @@ -244,9 +245,8 @@ void TextDrawer::SetFont(uint32_t fontHandle) { void TextDrawer::MeasureString(const char *str, float *w, float *h) { #ifdef USING_QT_UI - QFont font("default"); - font.setPixelSize(fontSize_); - QFontMetrics fm(font); + QFont* font = fontMap_.find(fontHash_)->second; + QFontMetrics fm(*font); QSize size = fm.size(0, str); *w = (float)size.width() * fontScaleX_; *h = (float)size.height() * fontScaleY_; @@ -271,9 +271,8 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float entry->lastUsedFrame = frameCount_; glBindTexture(GL_TEXTURE_2D, entry->textureHandle); } else { - QFont font("default"); - font.setPixelSize(fontSize_); - QFontMetrics fm(font); + QFont *font = fontMap_.find(fontHash_)->second; + QFontMetrics fm(*font); QSize size = fm.size(0, str); QImage image((size.width() + 3) & ~ 3, (size.height() + 3) & ~ 3, QImage::Format_ARGB32_Premultiplied); if (image.isNull()) { @@ -283,9 +282,9 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float QPainter painter; painter.begin(&image); - painter.setFont(font); + painter.setFont(*font); painter.setPen(color); - painter.drawText(0, fontSize_, QString::fromLocal8Bit(str)); + painter.drawText(0, font->pixelSize() - 4, QString::fromLocal8Bit(str)); painter.end(); entry = new TextStringEntry(); diff --git a/gfx_es2/draw_text.h b/gfx_es2/draw_text.h index 5fc60d9c8b..4280180ec8 100644 --- a/gfx_es2/draw_text.h +++ b/gfx_es2/draw_text.h @@ -13,6 +13,10 @@ #include "base/basictypes.h" #include "gfx_es2/draw_buffer.h" +#ifdef USING_QT_UI +#include +#endif + struct TextStringEntry { uint32_t textureHandle; int width; @@ -53,13 +57,13 @@ private: float fontScaleY_; TextDrawerContext *ctx_; +#ifdef USING_QT_UI + std::map fontMap_; +#else std::map fontMap_; +#endif uint32_t fontHash_; // The key is the CityHash of the string xor the fontHash_. std::map cache_; - -#ifdef USING_QT_UI - int fontSize_; -#endif }; From b04f2d4c45264e448fe7b506756d65f67e6170d0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 20 Nov 2013 01:23:15 +1000 Subject: [PATCH 0862/1445] Hide account path in friendly path. There is limited space to print out a full path. --- file/path.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/file/path.h b/file/path.h index 1543262990..8d98f44439 100644 --- a/file/path.h +++ b/file/path.h @@ -1,7 +1,9 @@ #pragma once #include +#include #include +#include #include "file/file_util.h" @@ -25,6 +27,19 @@ public: } std::string GetFriendlyPath() { std::string str = GetPath(); +#if defined(BLACKBERRY) + char* home = getenv("PERIMETER_HOME"); + if (!strncmp(str.c_str(), home, strlen(home))) { + str = str.substr(strlen(home)); + str.insert(0, 1, '~'); + } +#elif defined(__linux) + char* home = getenv("HOME"); + if (!strncmp(str.c_str(), home, strlen(home))) { + str = str.substr(strlen(home)); + str.insert(0, 1, '~'); + } +#endif /* #ifdef ANDROID if (!memcmp(str.c_str(), g_Config.memCardDirectory.c_str(), g_Config.memCardDirectory.size())) From 6248aefc9601ba4a35f688e3a0aba73abbc8cf49 Mon Sep 17 00:00:00 2001 From: Peter Tissen Date: Tue, 19 Nov 2013 23:33:41 +0100 Subject: [PATCH 0863/1445] Windows Qt fix --- gfx_es2/draw_text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 7161a526db..4593048498 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -12,7 +12,7 @@ #include #endif -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USING_QT_UI) #define WIN32_LEAN_AND_MEAN #include From 7ac7851b339767cf0d8880a63e58850bfdfe890f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 19 Nov 2013 23:43:19 +0100 Subject: [PATCH 0864/1445] Android crashfix --- file/path.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/file/path.h b/file/path.h index 8d98f44439..a3e9bc4322 100644 --- a/file/path.h +++ b/file/path.h @@ -33,6 +33,8 @@ public: str = str.substr(strlen(home)); str.insert(0, 1, '~'); } +#elif defined(ANDROID) + // Do nothing #elif defined(__linux) char* home = getenv("HOME"); if (!strncmp(str.c_str(), home, strlen(home))) { From 8a74896f8d2b199ddcc9108a16c46040fcfa07fa Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 20 Nov 2013 00:05:31 +0100 Subject: [PATCH 0865/1445] Add Vietnamese extra character range to atlastool --- tools/atlastool.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 707c626bd9..0c6433a904 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -757,6 +757,9 @@ void GetLocales(const char *locales, std::vector &ranges) case 'K': // Korean (hangul) ranges.push_back(range(0xAC00, 0xD7A3, hangul3)); break; + case 'V': // Vietnamese (need 'e' too) + ranges.push_back(range(0x1EA0, 0x1EF9)); + break; } } From f3fc923414d92f194861302b176c6407b5af23df Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 20 Nov 2013 15:15:26 +1000 Subject: [PATCH 0866/1445] Qt: Fix font display on non-UTF systems. --- gfx_es2/draw_text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 4593048498..568bd9bcff 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -284,7 +284,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float painter.begin(&image); painter.setFont(*font); painter.setPen(color); - painter.drawText(0, font->pixelSize() - 4, QString::fromLocal8Bit(str)); + painter.drawText(0, font->pixelSize() - 4, QString::fromUtf8(str)); painter.end(); entry = new TextStringEntry(); From e4979428279d17491cdde7c20b0c43a522242fdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 20 Nov 2013 14:41:26 +0100 Subject: [PATCH 0867/1445] Minor json stuff --- ext/vjson/json.cpp | 9 ++++++--- ext/vjson/json.h | 15 +++++++-------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ext/vjson/json.cpp b/ext/vjson/json.cpp index 8e375af951..2a77849470 100644 --- a/ext/vjson/json.cpp +++ b/ext/vjson/json.cpp @@ -14,7 +14,7 @@ int json_value::numChildren() const { const json_value *c = first_child; while (c) { count++; - c = c->next_sibling; + c = c->next_sibling; } return count; } @@ -25,12 +25,15 @@ int json_value::numSiblings() const { int count = 1; while (s) { count++; - s = s->next_sibling; + s = s->next_sibling; } return count; } const json_value *json_value::get(const char *child_name) const { + if (!this) { + FLOG("Cannot get from null node"); + } const json_value *c = first_child; while (c) { if (!strcmp(c->name, child_name)) { @@ -54,7 +57,7 @@ const char *json_value::getString(const char *child_name) const { if (val) return val->string_value; else - FLOG("String %s missing from node %s", child_name, this->name); + FLOG("String '%s' missing from node '%s'", child_name, this->name); return 0; } diff --git a/ext/vjson/json.h b/ext/vjson/json.h index 99b6558476..997f46b9aa 100644 --- a/ext/vjson/json.h +++ b/ext/vjson/json.h @@ -56,10 +56,10 @@ struct json_value int getInt(const char *child_name, int default_value) const; bool getBool(const char *child_name) const; bool getBool(const char *child_name, bool default_value) const; - - bool hasChild(const char *child_name, json_type child_type) const { - return get(child_name, child_type) != 0; - } + + bool hasChild(const char *child_name, json_type child_type) const { + return get(child_name, child_type) != 0; + } private: DISALLOW_COPY_AND_ASSIGN(json_value); @@ -80,13 +80,12 @@ public: buffer_[size] = 0; parse(); } - + ~JsonReader() { if (buffer_) free(buffer_); } - - + bool ok() const { return root_ != 0; } json_value *root() { return root_; } @@ -121,4 +120,4 @@ private: class JsonCursor { public: -}; \ No newline at end of file +}; From feb521fd4196b0e7e6546023835a2f2e376d8956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 20 Nov 2013 14:41:39 +0100 Subject: [PATCH 0868/1445] Add hacky Wait method to prioritizedworkqueue --- thread/prioritizedworkqueue.cpp | 15 +++++++++++++++ thread/prioritizedworkqueue.h | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index 7f193fc407..ea54d35dac 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -1,5 +1,6 @@ #include "base/functional.h" #include "base/logging.h" +#include "base/timeutil.h" #include "thread/thread.h" #include "thread/prioritizedworkqueue.h" @@ -66,6 +67,20 @@ PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { } } +void PrioritizedWorkQueue::Wait(PrioritizedWorkQueueItem *item) { + while (true) { + bool stillThere = false; + lock_guard guard(mutex_); + for (int i = 0; i < queue_.empty(); i++) { + if (queue_[i] == item) + stillThere = true; + } + if (!stillThere) + break; + sleep_ms(100); + } +} + // TODO: This feels ugly. Revisit later. static std::thread *workThread; diff --git a/thread/prioritizedworkqueue.h b/thread/prioritizedworkqueue.h index c2198a3d5b..506e3146b0 100644 --- a/thread/prioritizedworkqueue.h +++ b/thread/prioritizedworkqueue.h @@ -35,6 +35,9 @@ public: bool Done() { return done_; } void Stop(); + // Try not to use this. It's a hack. + void Wait(PrioritizedWorkQueueItem *item); + private: bool done_; recursive_mutex mutex_; @@ -49,4 +52,4 @@ private: // Starts up a thread that keeps trying to run this workqueue. // TODO: This feels ugly. Revisit later. void ProcessWorkQueueOnThreadWhile(PrioritizedWorkQueue *wq); -void StopProcessingWorkQueue(PrioritizedWorkQueue *wq); \ No newline at end of file +void StopProcessingWorkQueue(PrioritizedWorkQueue *wq); From 397da81a2ec6ffa221ce15d400d2eafeab61116e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 20 Nov 2013 14:52:09 +0100 Subject: [PATCH 0869/1445] Crash bug fix for empty scrollviews --- ui/viewgroup.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 2f130d2a7d..c1471c740c 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -646,6 +646,7 @@ void ScrollView::Draw(UIContext &dc) { ViewGroup::Draw(dc); return; } + dc.PushScissor(bounds_); views_[0]->Draw(dc); dc.PopScissor(); @@ -707,8 +708,10 @@ void ScrollView::ScrollRelative(float distance) { } void ScrollView::ClampScrollPos(float &pos) { - if (!views_.size()) + if (!views_.size()) { pos = 0.0f; + return; + } // Clamp scrollTarget. float childHeight = views_[0]->GetBounds().h; float scrollMax = std::max(0.0f, childHeight - bounds_.h); From 59ea9c5e62e8e3c530b383516aa3606303833cf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 20 Nov 2013 17:09:41 +0100 Subject: [PATCH 0870/1445] Add tag for simple data transfer between screens. --- ui/screen.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/screen.h b/ui/screen.h index db0d8532a3..e0f6a53176 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -59,8 +59,12 @@ public: ScreenManager *screenManager() { return screenManager_; } void setScreenManager(ScreenManager *sm) { screenManager_ = sm; } + // This one is icky to use because you can't know what's in it until you know + // what screen it is. virtual void *dialogData() { return 0; } + virtual std::string tag() { return std::string(""); } + virtual bool isTransparent() const { return false; } virtual bool isTopLevel() const { return false; } From d86b4c63d88f8a5c0bef53d7df5e51872eff2eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 20 Nov 2013 17:11:40 +0100 Subject: [PATCH 0871/1445] Constify tag --- ui/screen.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/screen.h b/ui/screen.h index e0f6a53176..4a4e13778e 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -63,7 +63,7 @@ public: // what screen it is. virtual void *dialogData() { return 0; } - virtual std::string tag() { return std::string(""); } + virtual std::string tag() const { return std::string(""); } virtual bool isTransparent() const { return false; } virtual bool isTopLevel() const { return false; } From 857fa4426bcdd0236016de462956b4716682ccab Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 20 Nov 2013 18:57:18 +0100 Subject: [PATCH 0872/1445] Hack libzip into building on win32 --- ext/libzip/config.h | 6 +- ext/libzip/mkstemp.c | 17 ++- ext/libzip/zip.h | 12 +- ext/libzip/zip_close.c | 9 +- ext/libzip/zipint.h | 12 +- native.vcxproj | 328 ++++++++++++++++++++++++++++++++++++++++- native.vcxproj.filters | 173 +++++++++++++++++++++- 7 files changed, 544 insertions(+), 13 deletions(-) diff --git a/ext/libzip/config.h b/ext/libzip/config.h index 5503d4e4b5..e202a3d91f 100644 --- a/ext/libzip/config.h +++ b/ext/libzip/config.h @@ -22,7 +22,9 @@ #define HAVE_MEMORY_H 0 /* Define to 1 if you have the `mkstemp' function. */ -#define HAVE_MKSTEMP 0 +#ifndef _WIN32 +#define HAVE_MKSTEMP 1 +#endif /* Define to 1 if you have the `MoveFileExA' function. */ /* #undef HAVE_MOVEFILEEXA */ @@ -40,7 +42,7 @@ #define HAVE_STRING_H 1 /* Define to 1 if `tm_zone' is a member of `struct tm'. */ -#define HAVE_STRUCT_TM_TM_ZONE 1 +// #define HAVE_STRUCT_TM_TM_ZONE 0 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 diff --git a/ext/libzip/mkstemp.c b/ext/libzip/mkstemp.c index 738a065a09..e8a749fceb 100644 --- a/ext/libzip/mkstemp.c +++ b/ext/libzip/mkstemp.c @@ -43,6 +43,11 @@ #include #include +#ifdef _WIN32 +typedef int pid_t; +#define getpid rand +#endif + #ifndef O_BINARY #define O_BINARY 0 #endif @@ -60,7 +65,8 @@ _zip_mkstemp(char *path) /* To guarantee multiple calls generate unique names even if the file is not created. 676 different possibilities with 7 or more X's, 26 with 6 or less. */ - static char xtra[2] = "aa"; + // Urgh, not threadsafe at all. + static char xtra[3] = "aa"; int xcnt = 0; pid = getpid(); @@ -106,15 +112,22 @@ _zip_mkstemp(char *path) *trv = '\0'; if (stat(path, &sbuf)) return (0); +#ifndef _WIN32 if (!S_ISDIR(sbuf.st_mode)) { errno = ENOTDIR; return (0); } +#endif *trv = '/'; break; } } + +#ifdef _WIN32 + return 0; +#else + for (;;) { if ((fd=open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0) return (fd); @@ -136,5 +149,7 @@ _zip_mkstemp(char *path) } } } +#endif + /*NOTREACHED*/ } diff --git a/ext/libzip/zip.h b/ext/libzip/zip.h index 48431a35c9..1798051de0 100644 --- a/ext/libzip/zip.h +++ b/ext/libzip/zip.h @@ -36,13 +36,19 @@ -#ifndef ZIP_EXTERN #ifdef _MSC_VER -#define ZIP_EXTERN __declspec(dllexport) +#ifndef ZIP_EXTERN +#define ZIP_EXTERN +// __declspec(dllexport) +#endif +#ifdef _M_X64 +typedef __int64 ssize_t; +#else +typedef __int32 ssize_t; +#endif #else #define ZIP_EXTERN #endif -#endif #ifdef __cplusplus extern "C" { diff --git a/ext/libzip/zip_close.c b/ext/libzip/zip_close.c index c6885d96a9..60614c6133 100644 --- a/ext/libzip/zip_close.c +++ b/ext/libzip/zip_close.c @@ -115,7 +115,7 @@ zip_close(struct zip *za) /* archive comment is special for torrentzip */ if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) { - cd->comment = _zip_memdup(TORRENT_SIG "XXXXXXXX", + cd->comment = (char *)_zip_memdup(TORRENT_SIG "XXXXXXXX", TORRENT_SIG_LEN + TORRENT_CRC_LEN, &za->error); if (cd->comment == NULL) { @@ -591,14 +591,14 @@ static int _zip_cdir_set_comment(struct zip_cdir *dest, struct zip *src) { if (src->ch_comment_len != -1) { - dest->comment = _zip_memdup(src->ch_comment, + dest->comment = (char *)_zip_memdup(src->ch_comment, src->ch_comment_len, &src->error); if (dest->comment == NULL) return -1; dest->comment_len = src->ch_comment_len; } else { if (src->cdir && src->cdir->comment) { - dest->comment = _zip_memdup(src->cdir->comment, + dest->comment = (char *)_zip_memdup(src->cdir->comment, src->cdir->comment_len, &src->error); if (dest->comment == NULL) return -1; @@ -636,7 +636,6 @@ _zip_changed(struct zip *za, int *survivorsp) } - static char * _zip_create_temp_output(struct zip *za, FILE **outp) { @@ -659,7 +658,9 @@ _zip_create_temp_output(struct zip *za, FILE **outp) if ((tfp=fdopen(tfd, "r+b")) == NULL) { _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); +#ifndef _WIN32 close(tfd); +#endif remove(temp); free(temp); return NULL; diff --git a/ext/libzip/zipint.h b/ext/libzip/zipint.h index f5a81b1934..287fd15550 100644 --- a/ext/libzip/zipint.h +++ b/ext/libzip/zipint.h @@ -37,7 +37,17 @@ #include #ifdef _MSC_VER -#define ZIP_EXTERN __declspec(dllimport) +#define ZIP_EXTERN +#define fseeko fseek +#define ftello ftell +#define snprintf _snprintf +#ifndef strcasecmp +#define strcasecmp _stricmp +#endif +#define umask(x) 0; +#define chmod(...) ; +typedef int mode_t; +// __declspec(dllimport) #endif #include "zip.h" diff --git a/native.vcxproj b/native.vcxproj index 0bdf5674f1..8b11cac105 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -206,6 +206,8 @@ + + @@ -342,6 +344,330 @@ + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + @@ -410,4 +736,4 @@ - + \ No newline at end of file diff --git a/native.vcxproj.filters b/native.vcxproj.filters index c3e2b2e4ea..fe60f02013 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -289,6 +289,12 @@ gfx + + ext\libzip + + + ext\libzip + @@ -522,6 +528,168 @@ util + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + + + ext\libzip + @@ -587,5 +755,8 @@ {02e8ef95-82c7-4420-b029-a189a5e0fcbd} + + {aa8b9b49-2ff8-4961-b6cc-9c33ea674130} + - + \ No newline at end of file From ae7c0827f288918815ba447205c0196e171768dd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 20 Nov 2013 19:38:23 +0100 Subject: [PATCH 0873/1445] Hack unicode support into libzip --- ext/libzip/config.h | 4 ++- ext/libzip/mkstemp.c | 20 ++++++++++-- ext/libzip/zip.h | 4 +++ ext/libzip/zip_close.c | 71 +++++++++++++++++++++++++++++++++++------- ext/libzip/zip_open.c | 49 +++++++++++++++++++++++------ ext/libzip/zipint.h | 12 +++++-- native.vcxproj | 2 ++ native.vcxproj.filters | 6 ++++ 8 files changed, 143 insertions(+), 25 deletions(-) diff --git a/ext/libzip/config.h b/ext/libzip/config.h index e202a3d91f..5cdc6c194a 100644 --- a/ext/libzip/config.h +++ b/ext/libzip/config.h @@ -27,7 +27,9 @@ #endif /* Define to 1 if you have the `MoveFileExA' function. */ -/* #undef HAVE_MOVEFILEEXA */ +#ifdef _WIN32 +#define HAVE_MOVEFILEEXA 1 +#endif /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 diff --git a/ext/libzip/mkstemp.c b/ext/libzip/mkstemp.c index e8a749fceb..54dc759b63 100644 --- a/ext/libzip/mkstemp.c +++ b/ext/libzip/mkstemp.c @@ -52,21 +52,33 @@ typedef int pid_t; #define O_BINARY 0 #endif - - int +#ifdef UNICODE +_zip_mkstemp(wchar_t *path) +#else _zip_mkstemp(char *path) +#endif { int fd; +#ifdef UNICODE + wchar_t *start, *trv; + struct _stat sbuf; +#else char *start, *trv; struct stat sbuf; +#endif + pid_t pid; /* To guarantee multiple calls generate unique names even if the file is not created. 676 different possibilities with 7 or more X's, 26 with 6 or less. */ // Urgh, not threadsafe at all. +#ifdef UNICODE + static wchar_t xtra[3] = L"aa"; +#else static char xtra[3] = "aa"; +#endif int xcnt = 0; pid = getpid(); @@ -110,7 +122,11 @@ _zip_mkstemp(char *path) break; if (*trv == '/') { *trv = '\0'; +#ifdef UNICODE + if (_wstat(path, &sbuf)) +#else if (stat(path, &sbuf)) +#endif return (0); #ifndef _WIN32 if (!S_ISDIR(sbuf.st_mode)) { diff --git a/ext/libzip/zip.h b/ext/libzip/zip.h index 1798051de0..6a10e990ae 100644 --- a/ext/libzip/zip.h +++ b/ext/libzip/zip.h @@ -204,7 +204,11 @@ ZIP_EXTERN const char *zip_get_file_comment(struct zip *, int, int *, int); ZIP_EXTERN const char *zip_get_name(struct zip *, int, int); ZIP_EXTERN int zip_get_num_files(struct zip *); ZIP_EXTERN int zip_name_locate(struct zip *, const char *, int); +#ifdef UNICODE +ZIP_EXTERN struct zip *zip_open(const wchar_t *, int, int *); +#else ZIP_EXTERN struct zip *zip_open(const char *, int, int *); +#endif ZIP_EXTERN int zip_rename(struct zip *, int, const char *); ZIP_EXTERN int zip_replace(struct zip *, int, struct zip_source *); ZIP_EXTERN int zip_set_archive_comment(struct zip *, const char *, int); diff --git a/ext/libzip/zip_close.c b/ext/libzip/zip_close.c index 60614c6133..0feb32e94c 100644 --- a/ext/libzip/zip_close.c +++ b/ext/libzip/zip_close.c @@ -53,7 +53,12 @@ static int copy_data(FILE *, off_t, FILE *, struct zip_error *); static int write_cdir(struct zip *, struct zip_cdir *, FILE *); static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *); static int _zip_changed(struct zip *, int *); -static char *_zip_create_temp_output(struct zip *, FILE **); +#ifdef UNICODE +static wchar_t * +#else +static char * +#endif + _zip_create_temp_output(struct zip *, FILE **); static int _zip_torrentzip_cmp(const void *, const void *); @@ -70,7 +75,11 @@ zip_close(struct zip *za) { int survivors; int i, j, error; - char *temp; +#ifdef UNICODE + wchar_t *temp; +#else + char *temp; +#endif FILE *out; mode_t mask; struct zip_cdir *cd; @@ -92,9 +101,13 @@ zip_close(struct zip *za) /* don't create zip files with no entries */ if (survivors == 0) { if (za->zn && za->zp) { - if (remove(za->zn) != 0) { - _zip_error_set(&za->error, ZIP_ER_REMOVE, errno); - return -1; +#ifdef UNICODE + if (_wremove(za->zn) != 0) { +#else + if (remove(za->zn) != 0) { +#endif + _zip_error_set(&za->error, ZIP_ER_REMOVE, errno); + return -1; } } _zip_free(za); @@ -133,7 +146,7 @@ zip_close(struct zip *za) } } - if ((temp=_zip_create_temp_output(za, &out)) == NULL) { + if ((temp = _zip_create_temp_output(za, &out)) == NULL) { _zip_cdir_free(cd); free(filelist); return -1; @@ -280,14 +293,22 @@ zip_close(struct zip *za) if (error) { _zip_dirent_finalize(&de); fclose(out); +#ifdef UNICODE + _wremove(temp); +#else remove(temp); +#endif free(temp); return -1; } if (fclose(out) != 0) { _zip_error_set(&za->error, ZIP_ER_CLOSE, errno); +#ifdef UNICODE + _wremove(temp); +#else remove(temp); +#endif free(temp); return -1; } @@ -297,13 +318,21 @@ zip_close(struct zip *za) za->zp = NULL; reopen_on_error = 1; } - if (_zip_rename(temp, za->zn) != 0) { + if (_zip_rename(temp, za->zn) != 0) { _zip_error_set(&za->error, ZIP_ER_RENAME, errno); +#ifdef UNICODE + _wremove(temp); +#else remove(temp); +#endif free(temp); if (reopen_on_error) { /* ignore errors, since we're already in an error case */ - za->zp = fopen(za->zn, "rb"); +#ifdef UNICODE + za->zp = _wfopen(za->zn, L"rb"); +#else + za->zp = fopen(za->zn, "rb"); +#endif } return -1; } @@ -636,19 +665,35 @@ _zip_changed(struct zip *za, int *survivorsp) } +#ifdef UNICODE +static wchar_t * +#else static char * +#endif _zip_create_temp_output(struct zip *za, FILE **outp) { - char *temp; +#ifdef UNICODE + wchar_t *temp; +#else + char *temp; +#endif int tfd; FILE *tfp; - if ((temp=(char *)malloc(strlen(za->zn)+8)) == NULL) { +#ifdef UNICODE + if ((temp=(wchar_t *)malloc((wcslen(za->zn)+8)*2)) == NULL) { +#else + if ((temp=(char *)malloc(strlen(za->zn)+8)) == NULL) { +#endif _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } - sprintf(temp, "%s.XXXXXX", za->zn); +#ifdef UNICODE + swprintf(temp, L"%s.XXXXXX", za->zn); +#else + sprintf(temp, "%s.XXXXXX", za->zn); +#endif if ((tfd=mkstemp(temp)) == -1) { _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); @@ -661,7 +706,11 @@ _zip_create_temp_output(struct zip *za, FILE **outp) #ifndef _WIN32 close(tfd); #endif +#ifdef UNICODE + _wremove(temp); +#else remove(temp); +#endif free(temp); return NULL; } diff --git a/ext/libzip/zip_open.c b/ext/libzip/zip_open.c index a65974df95..19227cfc20 100644 --- a/ext/libzip/zip_open.c +++ b/ext/libzip/zip_open.c @@ -43,11 +43,16 @@ #include "zipint.h" static void set_error(int *, struct zip_error *, int); -static struct zip *_zip_allocate_new(const char *, int *); static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *); static void _zip_check_torrentzip(struct zip *); static struct zip_cdir *_zip_find_central_dir(FILE *, int, int *, off_t); +#ifdef UNICODE +static struct zip *_zip_allocate_new(const wchar_t *, int *); +static int _zip_file_exists(const wchar_t *, int, int *); +#else +static struct zip *_zip_allocate_new(const char *, int *); static int _zip_file_exists(const char *, int, int *); +#endif static int _zip_headercomp(struct zip_dirent *, int, struct zip_dirent *, int); static unsigned char *_zip_memmem(const unsigned char *, int, @@ -56,9 +61,12 @@ static struct zip_cdir *_zip_readcdir(FILE *, unsigned char *, unsigned char *, int, int, struct zip_error *); - ZIP_EXTERN struct zip * +#ifdef UNICODE +zip_open(const wchar_t *fn, int flags, int *zep) +#else zip_open(const char *fn, int flags, int *zep) +#endif { FILE *fp; struct zip *za; @@ -75,8 +83,12 @@ zip_open(const char *fn, int flags, int *zep) break; } - if ((fp=fopen(fn, "rb")) == NULL) { - set_error(zep, NULL, ZIP_ER_OPEN); +#ifdef UNICODE + if ((fp=_wfopen(fn, L"rb")) == NULL) { +#else + if ((fp=fopen(fn, "rb")) == NULL) { +#endif + set_error(zep, NULL, ZIP_ER_OPEN); return NULL; } @@ -417,7 +429,11 @@ _zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2, static struct zip * +#ifdef _UNICODE +_zip_allocate_new(const wchar_t *fn, int *zep) +#else _zip_allocate_new(const char *fn, int *zep) +#endif { struct zip *za; struct zip_error error; @@ -426,8 +442,12 @@ _zip_allocate_new(const char *fn, int *zep) set_error(zep, &error, 0); return NULL; } - - za->zn = strdup(fn); + +#ifdef UNICODE + za->zn = _wcsdup(fn); +#else + za->zn = strdup(fn); +#endif if (!za->zn) { _zip_free(za); set_error(zep, NULL, ZIP_ER_MEMORY); @@ -439,16 +459,27 @@ _zip_allocate_new(const char *fn, int *zep) static int +#ifdef UNICODE +_zip_file_exists(const wchar_t *fn, int flags, int *zep) +#else _zip_file_exists(const char *fn, int flags, int *zep) +#endif { - struct stat st; - +#ifdef UNICODE + struct _stat st; +#else + struct stat st; +#endif if (fn == NULL) { set_error(zep, NULL, ZIP_ER_INVAL); return -1; } - if (stat(fn, &st) != 0) { +#ifdef UNICODE + if (_wstat(fn, &st) != 0) { +#else + if (stat(fn, &st) != 0) { +#endif if (flags & ZIP_CREATE) return 0; else { diff --git a/ext/libzip/zipint.h b/ext/libzip/zipint.h index 287fd15550..f7e3c34b8b 100644 --- a/ext/libzip/zipint.h +++ b/ext/libzip/zipint.h @@ -54,14 +54,18 @@ typedef int mode_t; #include "config.h" #ifndef HAVE_MKSTEMP +#ifdef UNICODE +int _zip_mkstemp(wchar_t *); +#else int _zip_mkstemp(char *); +#endif #define mkstemp _zip_mkstemp #endif #ifdef HAVE_MOVEFILEEXA #include #define _zip_rename(s, t) \ - (!MoveFileExA((s), (t), \ + (!MoveFileEx((s), (t), \ MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING)) #else #define _zip_rename rename @@ -121,7 +125,11 @@ struct zip_error { /* zip archive, part of API */ struct zip { - char *zn; /* file name */ +#ifdef UNICODE + wchar_t *zn; /* file name */ +#else + char *zn; /* file name */ +#endif FILE *zp; /* file */ struct zip_error error; /* error information */ diff --git a/native.vcxproj b/native.vcxproj index 8b11cac105..da336fa7e0 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -171,6 +171,7 @@ + @@ -206,6 +207,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index fe60f02013..2c87de725f 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -19,6 +19,9 @@ ui + + ext\libzip + @@ -295,6 +298,9 @@ ext\libzip + + ext\libzip + From 2b47807497f0281d788a5442e2a13888d735c471 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 21 Nov 2013 11:40:48 +1000 Subject: [PATCH 0874/1445] Qt: Fix font layout metrics. --- gfx_es2/draw_text.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 568bd9bcff..59f5cd223a 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -247,7 +247,7 @@ void TextDrawer::MeasureString(const char *str, float *w, float *h) { #ifdef USING_QT_UI QFont* font = fontMap_.find(fontHash_)->second; QFontMetrics fm(*font); - QSize size = fm.size(0, str); + QSize size = fm.size(0, QString::fromUtf8(str)); *w = (float)size.width() * fontScaleX_; *h = (float)size.height() * fontScaleY_; #else @@ -273,7 +273,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float } else { QFont *font = fontMap_.find(fontHash_)->second; QFontMetrics fm(*font); - QSize size = fm.size(0, str); + QSize size = fm.size(0, QString::fromUtf8(str)); QImage image((size.width() + 3) & ~ 3, (size.height() + 3) & ~ 3, QImage::Format_ARGB32_Premultiplied); if (image.isNull()) { return; From b34c1238e1670e2130e9d83f54020162cb7f0320 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 21 Nov 2013 17:45:54 +1000 Subject: [PATCH 0875/1445] Qt: Load from assets if file is not in VFS. --- file/ini_file.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index e9e50b69f1..c92d338566 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -25,6 +25,10 @@ #define strcasecmp _stricmp #endif +#ifdef USING_QT_UI +#include +#endif + // Ugh, this is ugly. static bool ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) { @@ -428,8 +432,17 @@ bool IniFile::Load(const char* filename) bool IniFile::LoadFromVFS(const std::string &filename) { size_t size; uint8_t *data = VFSReadFile(filename.c_str(), &size); - if (!data) + if (!data) { +#ifdef USING_QT_UI + QFile asset(QString(":/assets/%1").arg(filename.c_str())); + if (asset.open(QIODevice::ReadOnly)) { + std::string str = QString(asset.readAll().data()).toStdString(); + std::stringstream sstream(str); + return Load(sstream); + } else +#endif return false; + } std::string str((const char*)data, size); delete [] data; From 4177cf49db2310a76a116f5d7ae5853b7a0354d6 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 21 Nov 2013 19:31:55 +1000 Subject: [PATCH 0876/1445] Qt: Create a AssetsAssetReader for reading via :/assets on Qt. --- file/ini_file.cpp | 15 +------------- file/zip_read.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++ file/zip_read.h | 15 ++++++++++++++ image/zim_load.cpp | 8 -------- 4 files changed, 67 insertions(+), 22 deletions(-) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index c92d338566..e9e50b69f1 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -25,10 +25,6 @@ #define strcasecmp _stricmp #endif -#ifdef USING_QT_UI -#include -#endif - // Ugh, this is ugly. static bool ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) { @@ -432,17 +428,8 @@ bool IniFile::Load(const char* filename) bool IniFile::LoadFromVFS(const std::string &filename) { size_t size; uint8_t *data = VFSReadFile(filename.c_str(), &size); - if (!data) { -#ifdef USING_QT_UI - QFile asset(QString(":/assets/%1").arg(filename.c_str())); - if (asset.open(QIODevice::ReadOnly)) { - std::string str = QString(asset.readAll().data()).toStdString(); - std::stringstream sstream(str); - return Load(sstream); - } else -#endif + if (!data) return false; - } std::string str((const char*)data, size); delete [] data; diff --git a/file/zip_read.cpp b/file/zip_read.cpp index bf3bfadbac..b5dd6858eb 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -2,6 +2,11 @@ #include #include +#ifdef USING_QT_UI +#include +#include +#endif + #ifdef ANDROID #include #endif @@ -51,6 +56,52 @@ uint8_t *ReadLocalFile(const char *filename, size_t *size) { return contents; } +#ifdef USING_QT_UI +uint8_t *AssetsAssetReader::ReadAsset(const char *path, size_t *size) { + QFile asset(QString(":/assets/") + path); + if (!asset.open(QIODevice::ReadOnly)) + return 0; + uint8_t *contents = new uint8_t[asset.size()]; + memcpy(contents, (uint8_t*)asset.readAll().data(), asset.size()); + *size = asset.size(); + asset.close(); + return contents; +} + +bool AssetsAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) +{ + QDir assetDir(QString(":/assets/") + path); + QFileInfoList infoList = assetDir.entryInfoList(QString(filter).split(':'), QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name); + foreach(QFileInfo qinfo, infoList) { + FileInfo info; + info.name = qinfo.fileName().toStdString(); + info.fullName = path + qinfo.fileName().toStdString(); + info.exists = true; + info.isWritable = false; + info.isDirectory = qinfo.isDir(); + listing->push_back(info); + } + return true; +} + +bool AssetsAssetReader::GetFileInfo(const char *path, FileInfo *info) { + QFileInfo qinfo(QString(":/assets/") + path); + if (qinfo.exists()) { + info->exists = false; + info->size = 0; + return false; + } + + info->fullName = path; + info->exists = true; + info->isWritable = false; + info->isDirectory = qinfo.isDir(); + info->size = qinfo.size(); + return true; +} + +#endif + #ifdef ANDROID ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { diff --git a/file/zip_read.h b/file/zip_read.h index 0857bfc86c..68fde6d224 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -25,6 +25,21 @@ public: virtual std::string toString() const = 0; }; +#ifdef USING_QT_UI +class AssetsAssetReader : public AssetReader { +public: + AssetsAssetReader() {} + ~AssetsAssetReader() {} + // use delete[] + virtual uint8_t *ReadAsset(const char *path, size_t *size); + virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter); + virtual bool GetFileInfo(const char *path, FileInfo *info); + virtual std::string toString() const { + return ":assets/"; + } +}; +#endif + #ifdef ANDROID uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size); class ZipAssetReader : public AssetReader { diff --git a/image/zim_load.cpp b/image/zim_load.cpp index 5f78345ed5..70d564628e 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -135,13 +135,6 @@ int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, } int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t **image) { -#ifdef USING_QT_UI - QFile asset(QString(":/assets/") + filename); - if (!asset.open(QIODevice::ReadOnly)) - return 0; - int retval = LoadZIMPtr((uint8_t*)asset.readAll().data(), asset.size(), width, height, format, image); - asset.close(); -#else size_t size; uint8_t *buffer = VFSReadFile(filename, &size); if (!buffer) { @@ -152,6 +145,5 @@ int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t ELOG("Not a valid ZIM file: %s", filename); } delete [] buffer; -#endif return retval; } From 3b076b41a908bcf54ff0a05eb6c15238b9f19f6c Mon Sep 17 00:00:00 2001 From: Peter Tissen Date: Fri, 22 Nov 2013 01:59:18 +0100 Subject: [PATCH 0877/1445] refactored SDL joystick into seperate file --- base/PCMain.cpp | 102 ++++++------------------------------------------ base/QtMain.cpp | 14 ++++++- file/zip_read.h | 1 + 3 files changed, 27 insertions(+), 90 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 8e71fc7ddc..ee48d56b74 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -31,6 +31,8 @@ #include "base/NKCodeFromSDL.h" #include "util/const_map.h" #include "math/math_util.h" +#include "../SDL/SDLJoystick.h" + GlobalUIState lastUIState = UISTATE_MENU; @@ -171,7 +173,7 @@ void EGL_Close() { SDL_Joystick *ljoy = NULL; SDL_Joystick *rjoy = NULL; #else -SDL_Joystick *joy = NULL; +SDLJoystick *joystick; #endif // Simple implementations of System functions @@ -266,7 +268,6 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_lstick_y = 0; input->pad_rstick_x = 0; input->pad_rstick_y = 0; - // TODO: Use NativeAxis for joy instead. #ifdef PANDORA if ((ljoy)||(rjoy)) { @@ -424,8 +425,6 @@ int main(int argc, char *argv[]) { ELOG("Failed to open audio: %s", SDL_GetError()); // Audio must be unpaused _after_ NativeInit() - SDL_PauseAudio(0); - int numjoys = SDL_NumJoysticks(); #ifdef PANDORA // Joysticks init, we the nubs if setup as Joystick if (numjoys > 0) { @@ -434,40 +433,12 @@ int main(int argc, char *argv[]) { rjoy = SDL_JoystickOpen(1); } #else - SDL_JoystickEventState(SDL_ENABLE); - if (numjoys > 0) { - joy = SDL_JoystickOpen(0); - } + joystick = new SDLJoystick(); #endif + SDL_PauseAudio(0); + EnableFZ(); - // This is just a standard mapping that matches the X360 controller on MacOSX. Names will probably be all wrong - // on other controllers. - std::map SDLJoyButtonMap; - SDLJoyButtonMap[0] = NKCODE_DPAD_UP; - SDLJoyButtonMap[1] = NKCODE_DPAD_DOWN; - SDLJoyButtonMap[2] = NKCODE_DPAD_LEFT; - SDLJoyButtonMap[3] = NKCODE_DPAD_RIGHT; - SDLJoyButtonMap[4] = NKCODE_BUTTON_10; - SDLJoyButtonMap[5] = NKCODE_BUTTON_9; - SDLJoyButtonMap[6] = NKCODE_BUTTON_5; - SDLJoyButtonMap[7] = NKCODE_BUTTON_6; - SDLJoyButtonMap[8] = NKCODE_BUTTON_7; - SDLJoyButtonMap[9] = NKCODE_BUTTON_8; - SDLJoyButtonMap[10] = NKCODE_BUTTON_SELECT; - SDLJoyButtonMap[11] = NKCODE_BUTTON_2; - SDLJoyButtonMap[12] = NKCODE_BUTTON_3; - SDLJoyButtonMap[13] = NKCODE_BUTTON_4; - SDLJoyButtonMap[14] = NKCODE_BUTTON_1; - - std::map SDLJoyAxisMap; - SDLJoyAxisMap[0] = JOYSTICK_AXIS_X; - SDLJoyAxisMap[1] = JOYSTICK_AXIS_Y; - SDLJoyAxisMap[2] = JOYSTICK_AXIS_Z; - SDLJoyAxisMap[3] = JOYSTICK_AXIS_RZ; - SDLJoyAxisMap[4] = JOYSTICK_AXIS_LTRIGGER; - SDLJoyAxisMap[5] = JOYSTICK_AXIS_RTRIGGER; - int framecount = 0; float t = 0; float lastT = 0; @@ -485,60 +456,6 @@ int main(int argc, char *argv[]) { case SDL_QUIT: quitRequested = 1; break; - - case SDL_JOYAXISMOTION: - { - AxisInput axis; - axis.axisId = SDLJoyAxisMap[event.jaxis.axis]; - // 1.2 to try to approximate the PSP's clamped rectangular range. - axis.value = 1.2 * event.jaxis.value / 32767.0f; - if (axis.value > 1.0f) axis.value = 1.0f; - if (axis.value < -1.0f) axis.value = -1.0f; - axis.deviceId = DEVICE_ID_PAD_0; - axis.flags = 0; - NativeAxis(axis); - break; - } - - case SDL_JOYBUTTONDOWN: - { - KeyInput key; - key.flags = KEY_DOWN; - key.keyCode = SDLJoyButtonMap[event.jbutton.button]; - key.deviceId = DEVICE_ID_PAD_0; - NativeKey(key); - break; - } - - case SDL_JOYBUTTONUP: - { - KeyInput key; - key.flags = KEY_UP; - key.keyCode = SDLJoyButtonMap[event.jbutton.button]; - key.deviceId = DEVICE_ID_PAD_0; - NativeKey(key); - break; - } - - case SDL_JOYHATMOTION: - { - AxisInput axisX; - AxisInput axisY; - axisX.axisId = JOYSTICK_AXIS_HAT_X; - axisY.axisId = JOYSTICK_AXIS_HAT_Y; - axisX.deviceId = DEVICE_ID_PAD_0; - axisY.deviceId = DEVICE_ID_PAD_0; - axisX.value = 0.0f; - axisY.value = 0.0f; - if (event.jhat.value & SDL_HAT_LEFT) axisX.value = -1.0f; - if (event.jhat.value & SDL_HAT_RIGHT) axisX.value = 1.0f; - if (event.jhat.value & SDL_HAT_DOWN) axisY.value = -1.0f; - if (event.jhat.value & SDL_HAT_UP) axisY.value = 1.0f; - NativeAxis(axisX); - NativeAxis(axisY); - } - break; - case SDL_KEYDOWN: { int k = event.key.keysym.sym; @@ -662,6 +579,8 @@ int main(int argc, char *argv[]) { break; } break; + default: + joystick->processInput(ev) } } @@ -685,6 +604,11 @@ int main(int argc, char *argv[]) { EndInputState(&input_state); +#ifndef PANDORA + delete joystick; + joystick = 0; +#endif + if (framecount % 60 == 0) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } diff --git a/base/QtMain.cpp b/base/QtMain.cpp index f36163b29b..937a8a24ef 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -19,8 +19,13 @@ #include #include "SymbianMediaKeys.h" #endif +#ifdef QT_HAS_SDL +#include "SDL/SDLJoystick.h" +#endif #include "QtMain.h" + + InputState* input_state; std::string System_GetProperty(SystemProperty prop) { @@ -77,7 +82,10 @@ float CalculateDPIScale() #endif } -Q_DECL_EXPORT int main(int argc, char *argv[]) +#ifndef QT_HAS_SDL +Q_DECL_EXPORT +#endif +int main(int argc, char *argv[]) { #ifdef Q_OS_LINUX QApplication::setAttribute(Qt::AA_X11InitThreads, true); @@ -134,6 +142,10 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); +#ifdef QT_HAS_SDL + SDLJoystick joy(true); + joy.startEventLoop(); +#endif int ret = a.exec(); delete audio; thread->quit(); diff --git a/file/zip_read.h b/file/zip_read.h index 68fde6d224..6fb743c4d9 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -1,4 +1,5 @@ // TODO: Move much of this code to vfs.cpp +#pragma once #ifdef ANDROID #include From 58035235dacdf50715ea23d25886475c635671bd Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 22 Nov 2013 15:25:45 +1000 Subject: [PATCH 0878/1445] Qt: Fix directory listing for VFS. --- file/zip_read.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index b5dd6858eb..188134bd97 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -61,6 +61,7 @@ uint8_t *AssetsAssetReader::ReadAsset(const char *path, size_t *size) { QFile asset(QString(":/assets/") + path); if (!asset.open(QIODevice::ReadOnly)) return 0; + uint8_t *contents = new uint8_t[asset.size()]; memcpy(contents, (uint8_t*)asset.readAll().data(), asset.size()); *size = asset.size(); @@ -71,11 +72,15 @@ uint8_t *AssetsAssetReader::ReadAsset(const char *path, size_t *size) { bool AssetsAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) { QDir assetDir(QString(":/assets/") + path); - QFileInfoList infoList = assetDir.entryInfoList(QString(filter).split(':'), QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name); + QStringList filters = QString(filter).split(':', QString::SkipEmptyParts); + for (int i = 0; i < filters.count(); i++) + filters[i].prepend("*."); + + QFileInfoList infoList = assetDir.entryInfoList(filters, QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name); foreach(QFileInfo qinfo, infoList) { FileInfo info; info.name = qinfo.fileName().toStdString(); - info.fullName = path + qinfo.fileName().toStdString(); + info.fullName = qinfo.absoluteFilePath().remove(":/assets/").toStdString(); info.exists = true; info.isWritable = false; info.isDirectory = qinfo.isDir(); From 127d4b2d200dae3174dc4739e7375292ad85c4ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 22 Nov 2013 13:19:32 +0100 Subject: [PATCH 0879/1445] SDL buildfixing --- base/NKCodeFromSDL.h | 2 ++ base/PCMain.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/base/NKCodeFromSDL.h b/base/NKCodeFromSDL.h index 672e617ac0..d3b2b6a434 100644 --- a/base/NKCodeFromSDL.h +++ b/base/NKCodeFromSDL.h @@ -1,3 +1,5 @@ +#pragma once + #include "util/const_map.h" #include diff --git a/base/PCMain.cpp b/base/PCMain.cpp index ee48d56b74..be053b32b8 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -580,7 +580,8 @@ int main(int argc, char *argv[]) { } break; default: - joystick->processInput(ev) + joystick->ProcessInput(event); + break; } } From 06f5d0b76a53bd9bdda18ca496e65a3fcbf8a76a Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 23 Nov 2013 00:23:01 +1000 Subject: [PATCH 0880/1445] Fix small bug that was preventing some shaders from loading. --- file/zip_read.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 188134bd97..5005af96e1 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -62,8 +62,9 @@ uint8_t *AssetsAssetReader::ReadAsset(const char *path, size_t *size) { if (!asset.open(QIODevice::ReadOnly)) return 0; - uint8_t *contents = new uint8_t[asset.size()]; + uint8_t *contents = new uint8_t[asset.size()+1]; memcpy(contents, (uint8_t*)asset.readAll().data(), asset.size()); + contents[asset.size()] = 0; *size = asset.size(); asset.close(); return contents; From a1719eafa10d4f439ee536c6a08f1a55c80b4362 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 23 Nov 2013 14:21:54 +1000 Subject: [PATCH 0881/1445] Qt: Improve font size, alignment and workaround for '&&' issue. --- gfx_es2/draw_text.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 59f5cd223a..734a9abcf5 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -229,7 +229,7 @@ uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) { } QFont* font = new QFont(); - font->setPixelSize(size + 4); + font->setPixelSize(size + 6); fontMap_[fontHash] = font; fontHash_ = fontHash; return fontHash; @@ -284,7 +284,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float painter.begin(&image); painter.setFont(*font); painter.setPen(color); - painter.drawText(0, font->pixelSize() - 4, QString::fromUtf8(str)); + painter.drawText(image.rect(), Qt::AlignTop | Qt::AlignLeft | Qt::TextShowMnemonic /* Workaround for '&&'*/, QString::fromUtf8(str)); painter.end(); entry = new TextStringEntry(); From ddb9934dcec8ab05177879729c79eacfbf2ffab6 Mon Sep 17 00:00:00 2001 From: Bigpet Date: Sun, 24 Nov 2013 06:13:24 +0100 Subject: [PATCH 0882/1445] actually not deleting the joystick in the runloop anymore --- base/PCMain.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index be053b32b8..36b970b28f 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -173,7 +173,7 @@ void EGL_Close() { SDL_Joystick *ljoy = NULL; SDL_Joystick *rjoy = NULL; #else -SDLJoystick *joystick; +SDLJoystick *joystick = NULL; #endif // Simple implementations of System functions @@ -425,7 +425,9 @@ int main(int argc, char *argv[]) { ELOG("Failed to open audio: %s", SDL_GetError()); // Audio must be unpaused _after_ NativeInit() + SDL_PauseAudio(0); #ifdef PANDORA + int numjoys = SDL_NumJoysticks(); // Joysticks init, we the nubs if setup as Joystick if (numjoys > 0) { ljoy = SDL_JoystickOpen(0); @@ -435,8 +437,6 @@ int main(int argc, char *argv[]) { #else joystick = new SDLJoystick(); #endif - SDL_PauseAudio(0); - EnableFZ(); int framecount = 0; @@ -605,11 +605,6 @@ int main(int argc, char *argv[]) { EndInputState(&input_state); -#ifndef PANDORA - delete joystick; - joystick = 0; -#endif - if (framecount % 60 == 0) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } @@ -627,6 +622,10 @@ int main(int argc, char *argv[]) { t = time_now(); framecount++; } +#ifndef PANDORA + delete joystick; + joystick = NULL; +#endif // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though #ifdef _WIN32 From d7e3173f55994d6f6cb2d3a52e91c2eaad801c32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 25 Nov 2013 14:38:12 +0100 Subject: [PATCH 0883/1445] Kitkat Immersive Mode. Need to upgrade the buildbot before we can merge this. --- android/AndroidManifest.xml | 2 +- android/native-audio-so.cpp | 4 +++- android/project.properties | 2 +- .../com/henrikrydgard/libnative/NativeActivity.java | 12 ++++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index f31e07181c..1b9911acf6 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="1" android:versionName="1.0" > - + diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 4448b8173e..53fa40273c 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -153,7 +153,9 @@ extern "C" void OpenSLWrap_Shutdown() { SLresult result; ILOG("OpenSLWrap_Shutdown - stopping playback"); result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); - assert(SL_RESULT_SUCCESS == result); + if (SL_RESULT_SUCCESS != result) { + ELOG("SetPlayState failed"); + } ILOG("OpenSLWrap_Shutdown - deleting player object"); diff --git a/android/project.properties b/android/project.properties index 137f19ac6a..f06f217ce4 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt # Project target. -target=android-17 +target=android-19 android.library=true diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 094e7d693e..db4302bace 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -313,6 +313,9 @@ public class NativeActivity extends Activity { if (Build.VERSION.SDK_INT >= 14) { darkenOnScreenButtons(); } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + setImmersiveMode(); + } } @Override @@ -339,6 +342,12 @@ public class NativeActivity extends Activity { public void darkenOnScreenButtons() { mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); } + + @TargetApi(Build.VERSION_CODES.KITKAT) + public void setImmersiveMode() { + this.setImmersive(true); // This is an entirely different kind of immersive mode - hides some notification + mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); + } private boolean detectOpenGLES20() { ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); @@ -385,6 +394,9 @@ public class NativeActivity extends Activity { if (Build.VERSION.SDK_INT >= 14) { darkenOnScreenButtons(); } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + setImmersiveMode(); + } } // Prevent destroying and recreating the main activity when the device rotates etc, From 0a607422d27907aa22e49da8466b4957e00d9c92 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 26 Nov 2013 03:04:36 +1000 Subject: [PATCH 0884/1445] Blackberry: Update accelerometer API. --- base/BlackberryMain.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index dbb092e5cf..071672ab86 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -252,6 +252,9 @@ void BlackberryMain::runMain() { } } break; + case NAVIGATOR_ORIENTATION: + sensor_remap_coordinates(navigator_event_get_orientation_angle(event)); + break; case NAVIGATOR_BACK: case NAVIGATOR_SWIPE_DOWN: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE, KEY_DOWN)); @@ -261,17 +264,7 @@ void BlackberryMain::runMain() { } } else if (domain == sensor_get_domain()) { if (SENSOR_ACCELEROMETER_READING == bps_event_get_code(event)) { - float x, y, z; - sensor_event_get_xyz(event, &x, &y, &z); - if (pixel_xres == 1024 || pixel_xres == 720) // Q10 has this negative and reversed - { - input_state.acc.x = -y; - input_state.acc.y = -x; - } else { - input_state.acc.x = x; - input_state.acc.y = y; - } - input_state.acc.z = z; + sensor_event_get_xyz(event, &(input_state.acc.y), &(input_state.acc.x), &(input_state.acc.z)); } } } From 16b69fb583c5435fedd0addd4400e834021ed6b4 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 26 Nov 2013 12:11:52 +1000 Subject: [PATCH 0885/1445] Blackberry: Add simulator support. --- base/BlackberryDisplay.cpp | 6 +++++- base/BlackberryMain.cpp | 32 ++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/base/BlackberryDisplay.cpp b/base/BlackberryDisplay.cpp index 89001b200f..b06fde0033 100644 --- a/base/BlackberryDisplay.cpp +++ b/base/BlackberryDisplay.cpp @@ -75,17 +75,21 @@ void BlackberryMain::startDisplays() { if (displays[i].attached) realiseDisplay(i); } +#ifdef ARM screen_get_display_property_iv(screen_dpy[0], SCREEN_PROPERTY_DPI, &dpi); // Only internal display has DPI +#else + dpi = 340.0f; +#endif g_dpi_scale = ((pixel_xres == pixel_yres) ? 300.0f : 213.6f) / dpi; switchDisplay(screen_ui); } void BlackberryMain::realiseDisplay(int idx) { const EGLint egl_surfaceAttr[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE }; - int size[2] = { atoi(getenv("WIDTH")), atoi(getenv("HEIGHT")) }; if (idx != 0) screen_get_display_property_iv(screen_dpy[idx], SCREEN_PROPERTY_SIZE, size); + displays[idx].width = size[0]; displays[idx].height = size[1]; screen_set_window_property_iv(screen_win[idx], SCREEN_PROPERTY_BUFFER_SIZE, size); diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 071672ab86..e5d413f6a0 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -21,8 +21,12 @@ std::string System_GetProperty(SystemProperty prop) { switch (prop) { case SYSPROP_NAME: { - std::string name = "Blackberry10:"; + std::string name = "Blackberry:"; +#ifdef ARM return name + ((pixel_xres != pixel_yres) ? "Touch" : "QWERTY"); +#else + return name + "Simulator"; +#endif } case SYSPROP_LANGREGION: { char *locale = 0; @@ -96,7 +100,6 @@ void BlackberryMain::handleInput(screen_event_t screen_event) int pair[2]; screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &val); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pair); - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId); input_state.mouse_valid = true; switch(val) @@ -104,6 +107,7 @@ void BlackberryMain::handleInput(screen_event_t screen_event) // Touchscreen case SCREEN_EVENT_MTOUCH_TOUCH: case SCREEN_EVENT_MTOUCH_RELEASE: // Up, down + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId); input_state.pointer_down[pointerId] = (val == SCREEN_EVENT_MTOUCH_TOUCH); input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale; input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale; @@ -115,6 +119,7 @@ void BlackberryMain::handleInput(screen_event_t screen_event) NativeTouch(input); break; case SCREEN_EVENT_MTOUCH_MOVE: + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId); input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale; input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale; @@ -126,27 +131,26 @@ void BlackberryMain::handleInput(screen_event_t screen_event) break; // Mouse, Simulator case SCREEN_EVENT_POINTER: - screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, - &buttons); - if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down - input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale; - input_state.pointer_down[pointerId] = true; + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); + if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down + input_state.pointer_x[0] = pair[0] * g_dpi_scale; + input_state.pointer_y[0] = pair[1] * g_dpi_scale; + input_state.pointer_down[0] = true; input.x = pair[0] * g_dpi_scale; input.y = pair[1] * g_dpi_scale; input.flags = TOUCH_DOWN; - input.id = pointerId; + input.id = 0; NativeTouch(input); - } else if (input_state.pointer_down[pointerId]) { // Up - input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale; - input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale; - input_state.pointer_down[pointerId] = false; + } else if (input_state.pointer_down[0]) { // Up + input_state.pointer_x[0] = pair[0] * g_dpi_scale; + input_state.pointer_y[0] = pair[1] * g_dpi_scale; + input_state.pointer_down[0] = false; input.x = pair[0] * g_dpi_scale; input.y = pair[1] * g_dpi_scale; input.flags = TOUCH_UP; - input.id = pointerId; + input.id = 0; NativeTouch(input); } break; From 3bb995319bc6142e93a066edb0d864033b51e0cc Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 26 Nov 2013 16:38:00 +1000 Subject: [PATCH 0886/1445] SDL/Qt: Cleanup. --- base/PCMain.cpp | 11 +++++++++-- base/QtMain.cpp | 6 +----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 36b970b28f..84de4952ae 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -252,7 +252,15 @@ void LaunchEmail(const char *email_address) std::string System_GetProperty(SystemProperty prop) { switch (prop) { case SYSPROP_NAME: +#ifdef _WIN32 + return "SDL:Windows"; +#elif __linux__ + return "SDL:Linux"; +#elif __APPLE__ + return "SDL:OSX"; +#else return "SDL:"; +#endif case SYSPROP_LANGREGION: return "en_US"; default: @@ -320,7 +328,6 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); @@ -357,7 +364,7 @@ int main(int argc, char *argv[]) { EGL_Init(); #endif - SDL_WM_SetCaption(app_name_nice.c_str(), NULL); + SDL_WM_SetCaption((app_name_nice + " " + PPSSPP_GIT_VERSION).c_str(), NULL); #ifdef MAEMO SDL_ShowCursor(SDL_DISABLE); #endif diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 937a8a24ef..66fcbcc36e 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -34,7 +34,7 @@ std::string System_GetProperty(SystemProperty prop) { #ifdef __SYMBIAN32__ return "Qt:Symbian"; #elif defined(BLACKBERRY) - return "Qt:Blackberry10"; + return "Qt:Blackberry"; #elif defined(MEEGO_EDITION_HARMATTAN) return "Qt:Meego"; #elif defined(Q_OS_LINUX) @@ -120,11 +120,7 @@ int main(int argc, char *argv[]) #if defined(ARM) MainUI w; w.resize(pixel_xres, pixel_yres); -#ifdef ARM w.showFullScreen(); -#else - w.show(); -#endif #endif #ifdef __SYMBIAN32__ // Set RunFast hardware mode for VFPv2. From 0b24b5ce2628839a02b78a189e12be6803622ec4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 26 Nov 2013 13:56:22 +0100 Subject: [PATCH 0887/1445] Add simple version string parser --- Android.mk | 1 + native.vcxproj | 2 ++ native.vcxproj.filters | 6 +++++ util/text/parsers.cpp | 18 +++++++++++++++ util/text/parsers.h | 50 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 77 insertions(+) create mode 100644 util/text/parsers.cpp create mode 100644 util/text/parsers.h diff --git a/Android.mk b/Android.mk index c2fc541a2a..be4a3926de 100644 --- a/Android.mk +++ b/Android.mk @@ -80,6 +80,7 @@ LOCAL_SRC_FILES :=\ ui/virtual_input.cpp \ util/random/perlin.cpp \ util/text/utf8.cpp \ + util/text/parsers.cpp \ util/hash/hash.cpp LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -Wall -Wno-multichar -D__STDC_CONSTANT_MACROS diff --git a/native.vcxproj b/native.vcxproj index da336fa7e0..7e8740eaa8 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -273,6 +273,7 @@ + @@ -733,6 +734,7 @@ AssemblyAndSourceCode AssemblyAndSourceCode + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 2c87de725f..8604a2e67e 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -301,6 +301,9 @@ ext\libzip + + util + @@ -696,6 +699,9 @@ ext\libzip + + util + diff --git a/util/text/parsers.cpp b/util/text/parsers.cpp new file mode 100644 index 0000000000..f2947593b4 --- /dev/null +++ b/util/text/parsers.cpp @@ -0,0 +1,18 @@ +#include +#include + +#include "util/text/parsers.h" + +bool Version::ParseVersionString(std::string str) { + if (str.empty()) + return false; + if (str[0] == 'v') + str = str.substr(1); + return 3 == sscanf(str.c_str(), "%i.%i.%i", &major, &minor, &sub); +} + +std::string Version::ToString() const { + char temp[128]; + sprintf(temp, "%i.%i.%i", major, minor, sub); + return std::string(temp); +} diff --git a/util/text/parsers.h b/util/text/parsers.h new file mode 100644 index 0000000000..6a20058f69 --- /dev/null +++ b/util/text/parsers.h @@ -0,0 +1,50 @@ +#pragma once + +#include + +struct Version; + +// Parses version strings of the format "Major.Minor.Sub" and lets you interact with them conveniently. +struct Version { + Version() : major(0), minor(0), sub(0) {} + Version(std::string str) { + if (!ParseVersionString(str)) { + major = -1; + minor = -1; + sub = -1; + } + } + + int major; + int minor; + int sub; + + bool IsValid() const { + return sub >= 0 && minor >= 0 && major >= 0; + } + + bool operator == (const Version &other) const { + return major == other.major && minor == other.minor && sub == other.sub; + } + bool operator != (const Version &other) const { + return !(*this == other); + } + + bool operator <(const Version &other) const { + if (major < other.major) return true; + if (major > other.major) return false; + if (minor < other.minor) return true; + if (minor > other.minor) return false; + if (sub < other.sub) return true; + if (sub > other.sub) return false; + return false; + } + + bool operator >=(const Version &other) const { + return !(*this < other); + } + + std::string ToString() const; +private: + bool ParseVersionString(std::string str); +}; From d6fa5b83997c227377fe2493581ae008f90d1e94 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 26 Nov 2013 13:56:37 +0100 Subject: [PATCH 0888/1445] http: Add callback to Download/Downloader --- net/http_client.cpp | 11 +++++++++++ net/http_client.h | 18 ++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 202f8b128b..e76196302f 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -372,10 +372,21 @@ std::shared_ptr Downloader::StartDownload(const std::string &url, cons return dl; } +void Downloader::StartDownloadWithCallback( + const std::string &url, + const std::string &outfile, + std::function callback) { + std::shared_ptr dl(new Download(url, outfile)); + dl->SetCallback(callback); + downloads_.push_back(dl); + dl->Start(dl); +} + void Downloader::Update() { restart: for (size_t i = 0; i < downloads_.size(); i++) { if (downloads_[i]->Progress() == 1.0f || downloads_[i]->Failed()) { + downloads_[i]->RunCallback(); downloads_.erase(downloads_.begin() + i); goto restart; } diff --git a/net/http_client.h b/net/http_client.h index dd19aac405..94b8e67b88 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -90,11 +90,21 @@ public: // If not downloading to a file, access this to get the result. Buffer &buffer() { return buffer_; } + const Buffer &buffer() const { return buffer_; } void Cancel() { cancelled_ = true; } + // NOTE: Callbacks are NOT executed until RunCallback is called. This is so that + // the call will end up on the thread that calls g_DownloadManager.Update(). + void SetCallback(std::function callback) { + callback_ = callback; + } + void RunCallback() { + callback_(*this); + } + private: void Do(std::shared_ptr self); // Actually does the download. Runs on thread. void SetFailed(int code); @@ -105,6 +115,7 @@ private: int resultCode_; bool failed_; volatile bool cancelled_; + std::function callback_; }; using std::shared_ptr; @@ -117,10 +128,13 @@ public: std::shared_ptr StartDownload(const std::string &url, const std::string &outfile); + void StartDownloadWithCallback( + const std::string &url, + const std::string &outfile, + std::function callback); + // Drops finished downloads from the list. void Update(); - - void CancelAll(); private: From d2e70ce06fd54e0c884afe8d8b876ae28ce16df0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 26 Nov 2013 13:56:56 +0100 Subject: [PATCH 0889/1445] Minor UI tweaks --- ui/ui_context.cpp | 4 ++++ ui/ui_screen.cpp | 4 ++++ ui/ui_screen.h | 2 +- ui/view.cpp | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 5e6717fb4c..1731cd230b 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -175,6 +175,10 @@ void UIContext::DrawTextRect(const char *str, const Bounds &bounds, uint32_t col } void UIContext::FillRect(const UI::Drawable &drawable, const Bounds &bounds) { + // Only draw if alpha is non-zero. + if ((drawable.color & 0xFF000000) == 0) + return; + switch (drawable.type) { case UI::DRAW_SOLID_COLOR: uidrawbuffer_->DrawImageStretch(theme->whiteImage, bounds.x, bounds.y, bounds.x2(), bounds.y2(), drawable.color); diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 0e60df7875..d4e7ac5c0c 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -10,6 +10,10 @@ UIScreen::UIScreen() : Screen(), root_(0), recreateViews_(true), hatDown_(0) { } +UIScreen::~UIScreen() { + delete root_; +} + void UIScreen::DoRecreateViews() { if (recreateViews_) { delete root_; diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 56f63edbae..9f4dc828ec 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -8,7 +8,7 @@ class I18NCategory; class UIScreen : public Screen { public: UIScreen(); - ~UIScreen() { delete root_; } + ~UIScreen(); virtual void update(InputState &input); virtual void render(); diff --git a/ui/view.cpp b/ui/view.cpp index f6310d5d8e..f8bbc2b8b7 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -414,6 +414,9 @@ void CheckBox::Draw(UIContext &dc) { void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const { dc.MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); + // Add some internal padding to not look totally ugly + w += 16; + h += 8; } void Button::Draw(UIContext &dc) { From 1d28b00536a7366e00ce900547e01a9d4b2914ee Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 26 Nov 2013 14:36:22 +0100 Subject: [PATCH 0890/1445] UIContext; Add accessor for font style --- ui/ui_context.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/ui_context.h b/ui/ui_context.h index 59bbe1fcac..82dc714697 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -52,6 +52,7 @@ public: TextDrawer *Text() const { return textDrawer_; } void SetFontStyle(const UI::FontStyle &style); + const UI::FontStyle &GetFontStyle() { return *fontStyle_; } void SetFontScale(float scaleX, float scaleY); void MeasureText(const UI::FontStyle &style, const char *str, float *x, float *y, int align = 0) const; void DrawText(const char *str, float x, float y, uint32_t color, int align = 0); From 17ddae23cceda928777cf253101dc78a6da502d4 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 27 Nov 2013 01:30:10 +1000 Subject: [PATCH 0891/1445] Qt: Prepare for desktop UI to use embedded mobile UI. --- base/BlackberryMain.cpp | 3 ++- base/PCMain.cpp | 5 +++-- base/QtMain.h | 36 +++++++++++++++++++++++++++++++----- file/chunk_file.cpp | 4 ---- gfx_es2/draw_text.cpp | 2 +- 5 files changed, 37 insertions(+), 13 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index e5d413f6a0..3314745f04 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -11,9 +11,10 @@ #include // Get locale #include // Receive invocation messages #include "BlackberryMain.h" -#include "Core/Config.h" #include "base/NKCodeFromBlackberry.h" +// Bad: PPSSPP includes from native +#include "Core/Config.h" #include "UI/MiscScreens.h" // Simple implementations of System functions diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 84de4952ae..a1b75d637a 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -19,8 +19,6 @@ #include "SDL_audio.h" #include "SDL_video.h" #endif -#include "Core/Core.h" -#include "Core/Config.h" #include "base/display.h" #include "base/logging.h" #include "base/timeutil.h" @@ -32,6 +30,9 @@ #include "util/const_map.h" #include "math/math_util.h" #include "../SDL/SDLJoystick.h" +// Bad: PPSSPP includes from native +#include "Core/Core.h" +#include "Core/Config.h" GlobalUIState lastUIState = UISTATE_MENU; diff --git a/base/QtMain.h b/base/QtMain.h index c64fe131e2..b4ade8a40e 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -17,6 +17,7 @@ QTM_USE_NAMESPACE #include "base/logging.h" #include "base/timeutil.h" #include "file/zip_read.h" +#include "gfx_es2/gl_state.h" #include "input/input_state.h" #include "input/keycodes.h" #include "base/NativeApp.h" @@ -24,6 +25,10 @@ QTM_USE_NAMESPACE #include "display.h" #include "base/NKCodeFromQt.h" +// Bad: PPSSPP includes from native +#include "Core/Core.h" +#include "Core/Config.h" + // Input void SimulateGamepad(InputState *input); @@ -43,6 +48,9 @@ public: acc = new QAccelerometer(this); acc->start(); #endif + setFocus(); + setFocusPolicy(Qt::StrongFocus); + startTimer(16); } ~MainUI() { #ifdef USING_GLES2 @@ -51,6 +59,10 @@ public: NativeShutdownGraphics(); } +signals: + void doubleClick(); + void newFrame(); + protected: void resizeEvent(QResizeEvent * e) { @@ -58,8 +70,16 @@ protected: pixel_yres = e->size().height(); dp_xres = pixel_xres * g_dpi_scale; dp_yres = pixel_yres * g_dpi_scale; + PSP_CoreParameter().pixelWidth = pixel_xres; + PSP_CoreParameter().pixelHeight = pixel_yres; + PSP_CoreParameter().outputWidth = dp_xres; + PSP_CoreParameter().outputHeight = dp_yres; } + void timerEvent(QTimerEvent *) { + updateGL(); + emit newFrame(); + } bool event(QEvent *e) { TouchInput input; @@ -100,7 +120,11 @@ protected: break; } } - break; + break; + case QEvent::MouseButtonDblClick: + if (!g_Config.bShowTouchControls || globalUIState != UISTATE_INGAME) + emit doubleClick(); + break; case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: input_state.pointer_down[0] = (e->type() == QEvent::MouseButtonPress); @@ -122,13 +146,16 @@ protected: input.flags = TOUCH_MOVE; input.id = 0; NativeTouch(input); - break; + break; + case QEvent::Wheel: + NativeKey(KeyInput(DEVICE_ID_MOUSE, ((QWheelEvent*)e)->delta()<0 ? NKCODE_EXT_MOUSEWHEEL_DOWN : NKCODE_EXT_MOUSEWHEEL_UP, KEY_DOWN)); + break; case QEvent::KeyPress: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(((QKeyEvent*)e)->key())->second, KEY_DOWN)); - break; + break; case QEvent::KeyRelease: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(((QKeyEvent*)e)->key())->second, KEY_UP)); - break; + break; default: return QWidget::event(e); } @@ -152,7 +179,6 @@ protected: NativeRender(); EndInputState(&input_state); time_update(); - update(); } void updateAccelerometer() diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index fde65fe970..8c5abaa8c0 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -2,10 +2,6 @@ #include "file/chunk_file.h" #include "file/zip_read.h" -#ifdef __SYMBIAN32__ -#undef UNICODE -#endif - //#define CHUNKDEBUG ChunkFile::ChunkFile(const char *filename, bool _read) { diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 734a9abcf5..8c9acc9f51 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -284,7 +284,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float painter.begin(&image); painter.setFont(*font); painter.setPen(color); - painter.drawText(image.rect(), Qt::AlignTop | Qt::AlignLeft | Qt::TextShowMnemonic /* Workaround for '&&'*/, QString::fromUtf8(str)); + painter.drawText(image.rect(), Qt::AlignTop | Qt::AlignLeft, QString::fromUtf8(str)); painter.end(); entry = new TextStringEntry(); From 7744fdc5db03ff80be97d32c34a4a61f0191e829 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 27 Nov 2013 03:01:56 +1000 Subject: [PATCH 0892/1445] Buildfix for gcc (GNU). --- util/text/parsers.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/util/text/parsers.h b/util/text/parsers.h index 6a20058f69..58e5b9ba19 100644 --- a/util/text/parsers.h +++ b/util/text/parsers.h @@ -2,12 +2,13 @@ #include -struct Version; +#undef major +#undef minor // Parses version strings of the format "Major.Minor.Sub" and lets you interact with them conveniently. struct Version { Version() : major(0), minor(0), sub(0) {} - Version(std::string str) { + Version(const std::string &str) { if (!ParseVersionString(str)) { major = -1; minor = -1; From bd6a94c6ecb8ea66917209cf48417aed3cbbe784 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 28 Nov 2013 15:44:01 +1000 Subject: [PATCH 0893/1445] Use better DPI on Android. --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index db4302bace..124734bf17 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -218,6 +218,8 @@ public class NativeActivity extends Activity { DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); int dpi = metrics.densityDpi; + // We only use dpi to calculate the width. Smaller aspect ratios have giant text despite high DPI. + dpi = dpi * (srcWidth/srcHeight) / (16/9); // Adjust to 16:9 String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); From 8186bebce074fe95ca1f7355f8a33c43631bb45f Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 28 Nov 2013 16:04:37 +1000 Subject: [PATCH 0894/1445] Oops, cast to float. --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 124734bf17..e0d6967073 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -219,7 +219,7 @@ public class NativeActivity extends Activity { getWindowManager().getDefaultDisplay().getMetrics(metrics); int dpi = metrics.densityDpi; // We only use dpi to calculate the width. Smaller aspect ratios have giant text despite high DPI. - dpi = dpi * (srcWidth/srcHeight) / (16/9); // Adjust to 16:9 + dpi = dpi * ((float)srcWidth/(float)srcHeight) / (16.0/9.0); // Adjust to 16:9 String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); From 26821c5f9f30d4afd381e4a78a013b611707e740 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 27 Nov 2013 22:34:52 -0800 Subject: [PATCH 0895/1445] Typo, buildfix, warning fix. --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index e0d6967073..d515207b27 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -219,7 +219,7 @@ public class NativeActivity extends Activity { getWindowManager().getDefaultDisplay().getMetrics(metrics); int dpi = metrics.densityDpi; // We only use dpi to calculate the width. Smaller aspect ratios have giant text despite high DPI. - dpi = dpi * ((float)srcWidth/(float)srcHeight) / (16.0/9.0); // Adjust to 16:9 + dpi = (int)((float)dpi * ((float)scrWidth/(float)scrHeight) / (16.0/9.0)); // Adjust to 16:9 String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); From 26eaba2157a44338e6c085065ca0471b2b4dea7d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 28 Nov 2013 12:35:58 +0100 Subject: [PATCH 0896/1445] Add mac address parser --- util/text/parsers.cpp | 11 +++++++++++ util/text/parsers.h | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/util/text/parsers.cpp b/util/text/parsers.cpp index f2947593b4..42af1da916 100644 --- a/util/text/parsers.cpp +++ b/util/text/parsers.cpp @@ -16,3 +16,14 @@ std::string Version::ToString() const { sprintf(temp, "%i.%i.%i", major, minor, sub); return std::string(temp); } + +bool ParseMacAddress(std::string str, uint8_t macAddr[6]) { + int mac[6]; + if (6 != sscanf(str.c_str(), "%02x:%02x:%02x:%02x:%02x:%02x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5])) { + return false; + } + for (int i = 0; i < 6; i++) { + macAddr[i] = mac[i]; + } + return true; +} \ No newline at end of file diff --git a/util/text/parsers.h b/util/text/parsers.h index 58e5b9ba19..7f763cf9b8 100644 --- a/util/text/parsers.h +++ b/util/text/parsers.h @@ -2,6 +2,8 @@ #include +#include "base/basictypes.h" + #undef major #undef minor @@ -49,3 +51,5 @@ struct Version { private: bool ParseVersionString(std::string str); }; + +bool ParseMacAddress(std::string str, uint8_t macAddr[6]); \ No newline at end of file From 7eacb18ddde0bbf0285a9854a480e606bc08922a Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 29 Nov 2013 04:12:10 +1000 Subject: [PATCH 0897/1445] Blackberry: Match up with Android's DPI settings. --- base/BlackberryDisplay.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/BlackberryDisplay.cpp b/base/BlackberryDisplay.cpp index b06fde0033..3670f75acc 100644 --- a/base/BlackberryDisplay.cpp +++ b/base/BlackberryDisplay.cpp @@ -77,10 +77,12 @@ void BlackberryMain::startDisplays() { } #ifdef ARM screen_get_display_property_iv(screen_dpy[0], SCREEN_PROPERTY_DPI, &dpi); // Only internal display has DPI + // We only use dpi to calculate the width. Smaller aspect ratios have giant text despite high DPI. + dpi = dpi * (((float)displays[0].width/(float)displays[0].height) / (16.0/9.0)); // Adjust to 16:9 #else dpi = 340.0f; #endif - g_dpi_scale = ((pixel_xres == pixel_yres) ? 300.0f : 213.6f) / dpi; + g_dpi_scale = 210.0f / dpi; switchDisplay(screen_ui); } From 0e34574bd7de9fb21b4d403c28a515964909e4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 29 Nov 2013 11:33:51 +0100 Subject: [PATCH 0898/1445] Get rid of empty button from popup lists. Some deactivated logging in lang. --- i18n/i18n.cpp | 15 ++++++++++----- i18n/i18n.h | 7 +++++-- ui/ui_screen.cpp | 8 +++++--- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp index 30587c35dc..6b93848b7a 100644 --- a/i18n/i18n.cpp +++ b/i18n/i18n.cpp @@ -26,12 +26,14 @@ const char *I18NCategory::T(const char *key, const char *def) { auto iter = map_.find(modifiedKey); if (iter != map_.end()) { +// ILOG("translation key found in %s: %s", name_.c_str(), key); return iter->second.text.c_str(); } else { if (def) missedKeyLog_[key] = def; else missedKeyLog_[key] = modifiedKey.c_str(); +// ILOG("Missed translation key in %s: %s", name_.c_str(), key); return def ? def : key; } } @@ -41,6 +43,7 @@ void I18NCategory::SetMap(const std::map &m) { if (map_.find(iter->first) == map_.end()) { std::string text = ReplaceAll(iter->second, "\\n", "\n"); map_[iter->first] = I18NEntry(text); +// ILOG("Language entry: %s -> %s", iter->first.c_str(), text.c_str()); } } } @@ -50,7 +53,7 @@ I18NCategory *I18NRepo::GetCategory(const char *category) { if (iter != cats_.end()) { return iter->second; } else { - I18NCategory *c = new I18NCategory(this); + I18NCategory *c = new I18NCategory(this, category); cats_[category] = c; return c; } @@ -71,6 +74,8 @@ bool I18NRepo::IniExists(const std::string &languageID) const { bool I18NRepo::LoadIni(const std::string &languageID) { IniFile ini; + std::string iniPath = GetIniPath(languageID); +// ILOG("Loading lang ini %s", iniPath.c_str()); if (!ini.LoadFromVFS(GetIniPath(languageID))) { return false; } @@ -81,14 +86,14 @@ bool I18NRepo::LoadIni(const std::string &languageID) { for (auto iter = sections.begin(); iter != sections.end(); ++iter) { if (iter->name() != "") { - cats_[iter->name()] = LoadSection(&(*iter)); + cats_[iter->name()] = LoadSection(&(*iter), iter->name().c_str()); } } return true; } -I18NCategory *I18NRepo::LoadSection(const IniFile::Section *section) { - I18NCategory *cat = new I18NCategory(this); +I18NCategory *I18NRepo::LoadSection(const IniFile::Section *section, const char *name) { + I18NCategory *cat = new I18NCategory(this, name); std::map sectionMap = section->ToMap(); cat->SetMap(sectionMap); return cat; @@ -109,7 +114,7 @@ void I18NRepo::SaveIni(const std::string &languageID) { void I18NRepo::SaveSection(IniFile &ini, IniFile::Section *section, I18NCategory *cat) { const std::map &missed = cat->Missed(); - + for (auto iter = missed.begin(); iter != missed.end(); ++iter) { if (!section->Exists(iter->first.c_str())) { std::string text = ReplaceAll(iter->second, "\n", "\\n"); diff --git a/i18n/i18n.h b/i18n/i18n.h index 052f6221c4..b889a9c2d6 100644 --- a/i18n/i18n.h +++ b/i18n/i18n.h @@ -35,6 +35,7 @@ struct I18NCandidate { class I18NCategory { public: + I18NCategory(const char *name) : name_(name) {} const char *T(const char *key, const char *def = 0); const std::map &Missed() const { @@ -46,7 +47,9 @@ public: void ClearMissed() { missedKeyLog_.clear(); } private: - I18NCategory(I18NRepo *repo) {} + I18NCategory(I18NRepo *repo, const char *name) : name_(name) {} + + std::string name_; std::map map_; std::map missedKeyLog_; @@ -72,7 +75,7 @@ public: private: std::string GetIniPath(const std::string &languageID) const; void Clear(); - I18NCategory *LoadSection(const IniFile::Section *section); + I18NCategory *LoadSection(const IniFile::Section *section, const char *name); void SaveSection(IniFile &ini, IniFile::Section *section, I18NCategory *cat); std::map cats_; diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index d4e7ac5c0c..c49611dffc 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -112,8 +112,10 @@ UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2) : box_(0), title_(title) { I18NCategory *d = GetI18NCategory("Dialog"); - button1_ = d->T(button1.c_str()); - button2_ = d->T(button2.c_str()); + if (!button1.empty()) + button1_ = d->T(button1.c_str()); + if (!button2.empty()) + button2_ = d->T(button2.c_str()); } void PopupScreen::touch(const TouchInput &touch) { @@ -145,7 +147,7 @@ void PopupScreen::CreateViews() { CreatePopupContents(box_); - if (ShowButtons()) { + if (ShowButtons() && !button1_.empty()) { // And the two buttons at the bottom. LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT)); buttonRow->SetSpacing(0); From ca6b5b67d532459d3d679a92b225cd3944c8be88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 29 Nov 2013 12:21:02 +0100 Subject: [PATCH 0899/1445] Don't call a non-set callback. --- net/http_client.cpp | 2 +- net/http_client.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index e76196302f..3c11e02cf6 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -314,7 +314,7 @@ void Download::SetFailed(int code) { void Download::Do(std::shared_ptr self) { // as long as this is in scope, we won't get destructed. // yeah this is ugly, I need to think about how life time should be managed for these... - std::shared_ptr self_ = self; + std::shared_ptr self_ = self; resultCode_ = 0; Url fileUrl(url_); diff --git a/net/http_client.h b/net/http_client.h index 94b8e67b88..bfd4ed0731 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -102,7 +102,9 @@ public: callback_ = callback; } void RunCallback() { - callback_(*this); + if (callback_) { + callback_(*this); + } } private: From 197d010189ccf1509766f76f7f49e2f4fec43e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 29 Nov 2013 16:31:19 +0100 Subject: [PATCH 0900/1445] Compute progress % during downloads --- base/buffer.cpp | 27 +++++++++++++++++++++++++-- base/buffer.h | 6 +++++- net/http_client.cpp | 36 ++++++++++++++++++++++++++++++------ net/http_client.h | 2 ++ 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index 38900e0017..82a93d2ef1 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -175,11 +175,34 @@ bool Buffer::ReadAll(int fd) { return true; } -size_t Buffer::Read(int fd, size_t sz) { +bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress) { + char buf[1024]; + int total = 0; + while (true) { + int retval = recv(fd, buf, sizeof(buf), 0); + if (retval == 0) { + return true; + } else if (retval < 0) { + ELOG("Error reading from buffer: %i", retval); + return false; + } + char *p = Append((size_t)retval); + memcpy(p, buf, retval); + total += retval; + *progress = (float)total / (float)knownSize; + ILOG("Progress: %f", *progress); + } + return true; +} + +int Buffer::Read(int fd, size_t sz) { char buf[1024]; int retval; size_t received = 0; while ((retval = recv(fd, buf, std::min(sz, sizeof(buf)), 0)) > 0) { + if (retval < 0) { + return retval; + } char *p = Append((size_t)retval); memcpy(p, buf, retval); sz -= retval; @@ -193,4 +216,4 @@ size_t Buffer::Read(int fd, size_t sz) { void Buffer::PeekAll(std::string *dest) { dest->resize(data_.size()); memcpy(&(*dest)[0], &data_[0], data_.size()); -} \ No newline at end of file +} diff --git a/base/buffer.h b/base/buffer.h index 0ebf7e3f2b..73fbe898fb 100644 --- a/base/buffer.h +++ b/base/buffer.h @@ -66,7 +66,11 @@ class Buffer { bool FlushSocket(uintptr_t sock); // Windows portability bool ReadAll(int fd); - size_t Read(int fd, size_t sz); + bool ReadAllWithProgress(int fd, int knownSize, float *progress); + + // < 0: error + // >= 0: number of bytes read + int Read(int fd, size_t sz); // Utilities. Try to avoid checking for size. size_t size() const { return data_.size(); } diff --git a/net/http_client.cpp b/net/http_client.cpp index 3c11e02cf6..31b3378ecf 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -121,7 +121,8 @@ Client::~Client() { #define USERAGENT "NATIVEAPP 1.0" -void DeChunk(Buffer *inbuffer, Buffer *outbuffer) { +void DeChunk(Buffer *inbuffer, Buffer *outbuffer, int contentLength, float *progress) { + int dechunkedBytes = 0; while (true) { std::string line; inbuffer->TakeLineCRLF(&line); @@ -138,13 +139,17 @@ void DeChunk(Buffer *inbuffer, Buffer *outbuffer) { inbuffer->clear(); return; } + dechunkedBytes += chunkSize; + if (progress && contentLength) { + *progress = (float)dechunkedBytes / contentLength; + } inbuffer->Skip(2); } } int Client::GET(const char *resource, Buffer *output, float *progress) { if (progress) { - *progress = 0; + *progress = 0.01f; } Buffer buffer; @@ -166,8 +171,10 @@ int Client::GET(const char *resource, Buffer *output, float *progress) { Buffer readbuf; // Snarf all the data we can into RAM. A little unsafe but hey. - if (!readbuf.ReadAll(sock())) + if (readbuf.Read(sock(), 4096) < 0) { + ELOG("Failed to read HTTP headers :("); return -1; + } // Grab the first header line that contains the http code. @@ -218,13 +225,23 @@ int Client::GET(const char *resource, Buffer *output, float *progress) { if (!contentLength && progress) { // Content length is unknown. // Set progress to 1% so it looks like something is happening... - *progress = 0.01f; + *progress = 0.1f; + } + + if (!contentLength) { + // No way to know how far along we are. Let's just not update the progress counter. + if (!readbuf.ReadAll(sock())) + return -1; + } else { + // Let's read in chunks, updating progress between each. + if (!readbuf.ReadAllWithProgress(sock(), contentLength, progress)) + return -1; } // output now contains the rest of the reply. Dechunk it. if (chunked) { // TODO: Turn this into a loop and update progress - DeChunk(&readbuf, output); + DeChunk(&readbuf, output, contentLength, progress); } else { // TODO: Turn this into a loop and update progress output->Append(readbuf); @@ -393,11 +410,18 @@ void Downloader::Update() { } } +std::vector Downloader::GetCurrentProgress() { + std::vector progress; + for (size_t i = 0; i < downloads_.size(); i++) { + progress.push_back(downloads_[i]->Progress()); + } + return progress; +} + void Downloader::CancelAll() { for (size_t i = 0; i < downloads_.size(); i++) { downloads_[i]->Cancel(); } } - } // http diff --git a/net/http_client.h b/net/http_client.h index bfd4ed0731..1074a9efdd 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -139,6 +139,8 @@ public: void Update(); void CancelAll(); + std::vector GetCurrentProgress(); + private: std::vector> downloads_; }; From e9c25e560714a163937b1741bb5f165510266d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 29 Nov 2013 17:10:13 +0100 Subject: [PATCH 0901/1445] Remove progress logging from buffer --- base/buffer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index 82a93d2ef1..49e86b09e0 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -190,7 +190,6 @@ bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress) { memcpy(p, buf, retval); total += retval; *progress = (float)total / (float)knownSize; - ILOG("Progress: %f", *progress); } return true; } From 8c54171c5f6f357a07ce02c423f2201c29b021ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 29 Nov 2013 17:33:56 +0100 Subject: [PATCH 0902/1445] Fix a race condition in http client --- net/http_client.cpp | 9 ++++++--- net/http_client.h | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 31b3378ecf..6acbf5c4b7 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -188,6 +188,7 @@ int Client::GET(const char *resource, Buffer *output, float *progress) { if (code_pos != line.npos) { code_pos = line.find_first_not_of(' ', code_pos); } + if (code_pos != line.npos) { code = atoi(&line[code_pos]); } else { @@ -240,10 +241,8 @@ int Client::GET(const char *resource, Buffer *output, float *progress) { // output now contains the rest of the reply. Dechunk it. if (chunked) { - // TODO: Turn this into a loop and update progress DeChunk(&readbuf, output, contentLength, progress); } else { - // TODO: Turn this into a loop and update progress output->Append(readbuf); } @@ -311,7 +310,7 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) } Download::Download(const std::string &url, const std::string &outfile) - : progress_(0.0f), url_(url), outfile_(outfile), resultCode_(0), failed_(false), cancelled_(false) { + : progress_(0.0f), url_(url), outfile_(outfile), resultCode_(0), completed_(false), failed_(false), cancelled_(false) { } Download::~Download() { @@ -380,6 +379,10 @@ void Download::Do(std::shared_ptr self) { resultCode_ = resultCode; progress_ = 1.0f; + + // Set this last to ensure no race conditions when checking Done. Users must always check + // Done before looking at the result code. + completed_ = true; } std::shared_ptr Downloader::StartDownload(const std::string &url, const std::string &outfile) { diff --git a/net/http_client.h b/net/http_client.h index 1074a9efdd..dd1e070764 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -79,10 +79,11 @@ public: // Returns 1.0 when done. That one value can be compared exactly - or just use Done(). float Progress() const { return progress_; } - bool Done() const { return progress_ == 1.0f; } + bool Done() const { return completed_; } bool Failed() const { return failed_; } + // NOTE! The value of ResultCode is INVALID until Done() returns true. int ResultCode() const { return resultCode_; } std::string url() const { return url_; } @@ -115,6 +116,7 @@ private: std::string url_; std::string outfile_; int resultCode_; + bool completed_; bool failed_; volatile bool cancelled_; std::function callback_; From 8391f2ac810b35e86349efd94709287e919ed18a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 1 Dec 2013 15:36:18 +0100 Subject: [PATCH 0903/1445] Fix minor scrolling issue where the next item wouldn't be prioritized over the top bar. --- ui/viewgroup.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index c1471c740c..aebc78c186 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -191,6 +191,7 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio float dirY = dy / distance; bool wrongDirection = false; + bool vertical = false; float horizOverlap = HorizontalOverlap(origin->GetBounds(), destination->GetBounds()); float vertOverlap = VerticalOverlap(origin->GetBounds(), destination->GetBounds()); if (horizOverlap == 1.0f && vertOverlap == 1.0f) { @@ -209,6 +210,7 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio if (dirY > 0.0f) { wrongDirection = true; } + vertical = true; break; case FOCUS_RIGHT: overlap = vertOverlap; @@ -221,6 +223,7 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio if (dirY < 0.0f) { wrongDirection = true; } + vertical = true; break; case FOCUS_PREV: case FOCUS_NEXT: @@ -228,10 +231,25 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio break; } + // Add a small bonus if the views are the same size. This prioritizes moving to the next item + // upwards in a scroll view instead of moving up to the top bar. + float bonus = 0.0f; + if (vertical) { + float widthDifference = origin->GetBounds().w - destination->GetBounds().w; + if (widthDifference == 0) { + bonus = 1; + } + } else { + float heightDifference = origin->GetBounds().h - destination->GetBounds().h; + if (heightDifference == 0) { + bonus = 1; + } + } + if (wrongDirection) return 0.0f; else - return 1.0f/distance + overlap*10; + return 1.0f / distance + overlap*10 + bonus; } From 81249616761d6b80535e6121b2087cbe8065b780 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 2 Dec 2013 15:39:28 +1000 Subject: [PATCH 0904/1445] Fix Typo so Symbian can build on Linux. --- base/SymbianMediaKeys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/SymbianMediaKeys.cpp b/base/SymbianMediaKeys.cpp index 3c1107e3d9..8cb132c49f 100644 --- a/base/SymbianMediaKeys.cpp +++ b/base/SymbianMediaKeys.cpp @@ -5,7 +5,7 @@ //Adds mediakey support for Symbian (volume up/down) #include -#include "SymbianMediakeys.h" +#include "SymbianMediaKeys.h" #include "input/keycodes.h" #include "input/input_state.h" #include "base/NativeApp.h" From cbd4a6d75881542f74557f28cff41c821a0e6bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 2 Dec 2013 16:50:03 +0100 Subject: [PATCH 0905/1445] Add support for loading JPEG files into textures automatically. --- gfx/texture.cpp | 87 ++++++++++++++++++++++++++++++++++++------------ gfx/texture.h | 5 +-- ui/ui_screen.cpp | 41 ++++++++++++++++++++--- ui/ui_screen.h | 21 +++++++----- ui/view.cpp | 34 +++++++++++++++++++ ui/view.h | 16 +++++++++ 6 files changed, 167 insertions(+), 37 deletions(-) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 7009d85d9d..7e6320c387 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -3,6 +3,7 @@ #include #include "ext/rg_etc1/rg_etc1.h" +#include "ext/jpge/jpgd.h" #include "image/png_load.h" #include "image/zim_load.h" #include "base/logging.h" @@ -59,7 +60,7 @@ bool Texture::Load(const char *filename) { int bpp, w, h; bool clamp; uint8_t *data = generateTexture(filename, bpp, w, h, clamp); - if (!data) + if (!data) return false; glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); @@ -107,15 +108,14 @@ bool Texture::Load(const char *filename) { const char *name = fn; if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); len = strlen(name); - if (!strcmp("png", &name[len-3]) || - !strcmp("PNG", &name[len-3])) { - if (!LoadPNG(fn)) { - WLOG("WARNING: Failed to load .png %s, falling back to ugly gray XOR pattern!", fn); - LoadXOR(); - return false; - } else { - return true; - } + if (!strcmp("png", &name[len-3]) || !strcmp("PNG", &name[len-3])) { + if (!LoadPNG(fn)) { + WLOG("WARNING: Failed to load .png %s, falling back to ugly gray XOR pattern!", fn); + LoadXOR(); + return false; + } else { + return true; + } } else if (!strcmp("zim", &name[len-3])) { if (LoadZIM(name)) { return true; @@ -124,12 +124,23 @@ bool Texture::Load(const char *filename) { LoadXOR(); return false; } + } else if (!strcmp("jpg", &name[len-3]) || !strcmp("JPG", &name[len-3]) || + !strcmp("jpeg", &name[len-4]) || !strcmp("JPEG", &name[len-4])) { + if (!LoadJPEG(fn)) { + WLOG("WARNING: Failed to load jpeg %s, falling back to ugly gray XOR pattern!", fn); + LoadXOR(); + return false; + } else { + return true; + } + } else { + ELOG("Failed to identify image file %s by extension", name); } LoadXOR(); return false; } -bool Texture::LoadPNG(const char *filename) { +bool Texture::LoadPNG(const char *filename, bool genMips) { unsigned char *image_data; if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { return false; @@ -137,15 +148,48 @@ bool Texture::LoadPNG(const char *filename) { GL_CHECK(); glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); - SetTextureParameters(ZIM_GEN_MIPS); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, + SetTextureParameters(genMips ? ZIM_GEN_MIPS : ZIM_CLAMP); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); - if(gl_extensions.FBO_ARB){ - glGenerateMipmap(GL_TEXTURE_2D); - }else{ + if (genMips) { + if (gl_extensions.FBO_ARB) { + glGenerateMipmap(GL_TEXTURE_2D); + } else { #ifndef USING_GLES2 - glGenerateMipmapEXT(GL_TEXTURE_2D); + glGenerateMipmapEXT(GL_TEXTURE_2D); #endif + } + } + GL_CHECK(); + free(image_data); + return true; +} + +bool Texture::LoadJPEG(const char *filename, bool genMips) { + ILOG("Loading jpeg %s", filename); + unsigned char *image_data; + int actual_comps; + image_data = jpgd::decompress_jpeg_image_from_file(filename, &width_, &height_, &actual_comps, 4); + if (!image_data) { + ELOG("jpeg: image data returned was 0"); + return false; + } + ILOG("Jpeg decoder failed to get RGB, got: %i x %i x %i", actual_comps, width_, height_); + ILOG("First four bytes: %i %i %i %i", image_data[0], image_data[1], image_data[2], image_data[3]); + + GL_CHECK(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_2D, id_); + SetTextureParameters(genMips ? ZIM_GEN_MIPS : ZIM_CLAMP); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); + if (genMips) { + if (gl_extensions.FBO_ARB) { + glGenerateMipmap(GL_TEXTURE_2D); + } else { +#ifndef USING_GLES2 + glGenerateMipmapEXT(GL_TEXTURE_2D); +#endif + } } GL_CHECK(); free(image_data); @@ -162,12 +206,11 @@ bool Texture::LoadPNG(const uint8_t *data, size_t size, bool genMips) { glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); SetTextureParameters(genMips ? ZIM_GEN_MIPS : ZIM_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image_data); - if (genMips) { - if(gl_extensions.FBO_ARB) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); + if (genMips) { + if (gl_extensions.FBO_ARB) { glGenerateMipmap(GL_TEXTURE_2D); - }else{ + } else { #ifndef USING_GLES2 glGenerateMipmapEXT(GL_TEXTURE_2D); #endif diff --git a/gfx/texture.h b/gfx/texture.h index 7861c52c30..a712ce2dc4 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -25,7 +25,8 @@ public: // PNG from memory buffer bool LoadPNG(const uint8_t *data, size_t size, bool genMips = true); bool LoadZIM(const char *filename); - bool LoadPNG(const char *filename); + bool LoadPNG(const char *filename, bool genMips = true); + bool LoadJPEG(const char *filename, bool genMips = true); unsigned int Handle() const { return id_; @@ -48,4 +49,4 @@ private: #endif unsigned int id_; int width_, height_; -}; \ No newline at end of file +}; diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index c49611dffc..f7f8e521c1 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -243,13 +243,28 @@ void PopupMultiChoice::Draw(UIContext &dc) { dc.DrawText(valueText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); } +PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams) + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) { + OnClick.Handle(this, &PopupSliderChoice::HandleClick); +} + +PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams) + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) { + OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); +} EventReturn PopupSliderChoice::HandleClick(EventParams &e) { - Screen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_); + SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_); + popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange); screenManager_->push(popupScreen); return EVENT_DONE; } +EventReturn PopupSliderChoice::HandleChange(EventParams &e) { + e.v = this; + OnChange.Trigger(e); + return EVENT_DONE; +} void PopupSliderChoice::Draw(UIContext &dc) { Choice::Draw(dc); @@ -260,11 +275,18 @@ void PopupSliderChoice::Draw(UIContext &dc) { } EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) { - Screen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_); + SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_); + popupScreen->OnChange.Handle(this, &PopupSliderChoiceFloat::HandleChange); screenManager_->push(popupScreen); return EVENT_DONE; } +EventReturn PopupSliderChoiceFloat::HandleChange(EventParams &e) { + e.v = this; + OnChange.Trigger(e); + return EVENT_DONE; +} + void PopupSliderChoiceFloat::Draw(UIContext &dc) { Choice::Draw(dc); char temp[32]; @@ -288,13 +310,24 @@ void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { } void SliderPopupScreen::OnCompleted(DialogResult result) { - if (result == DR_OK) + if (result == DR_OK) { *value_ = sliderValue_; + EventParams e; + e.v = 0; + e.a = *value_; + OnChange.Trigger(e); + } } void SliderFloatPopupScreen::OnCompleted(DialogResult result) { - if (result == DR_OK) + if (result == DR_OK) { *value_ = sliderValue_; + EventParams e; + e.v = 0; + e.a = (int)*value_; + e.f = *value_; + OnChange.Trigger(e); + } } } // namespace UI diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 9f4dc828ec..8bf3f30216 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -115,6 +115,8 @@ public: SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title) : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue) {} void CreatePopupContents(ViewGroup *parent); + Event OnChange; + private: virtual void OnCompleted(DialogResult result); Slider *slider_; @@ -129,6 +131,8 @@ public: SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title) : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue) {} void CreatePopupContents(UI::ViewGroup *parent); + Event OnChange; + private: virtual void OnCompleted(DialogResult result); UI::SliderFloat *slider_; @@ -173,15 +177,15 @@ private: class PopupSliderChoice : public Choice { public: - PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0) - : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) { - OnClick.Handle(this, &PopupSliderChoice::HandleClick); - } + PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0); void Draw(UIContext &dc); + Event OnChange; + private: EventReturn HandleClick(EventParams &e); + EventReturn HandleChange(EventParams &e); int *value_; int minValue_; @@ -191,16 +195,15 @@ private: class PopupSliderChoiceFloat : public Choice { public: - PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0) - : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) { - OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); - } + PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0); void Draw(UIContext &dc); + Event OnChange; + private: EventReturn HandleClick(EventParams &e); - + EventReturn HandleChange(EventParams &e); float *value_; float minValue_; float maxValue_; diff --git a/ui/view.cpp b/ui/view.cpp index f8bbc2b8b7..230eca512c 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -476,6 +476,40 @@ void TextureView::Draw(UIContext &dc) { } } +ImageFileView::ImageFileView(std::string filename, ImageSizeMode sizeMode, LayoutParams *layoutParams) + : InertView(layoutParams), color_(0xFFFFFFFF), sizeMode_(sizeMode) { + texture_ = new Texture(); + if (!texture_->Load(filename.c_str())) { + ELOG("Failed to load texture %s", filename.c_str()); + } +} + +ImageFileView::~ImageFileView() { + delete texture_; +} + +void ImageFileView::Draw(UIContext &dc) { + // TODO: involve sizemode + if (texture_) { + dc.Flush(); + texture_->Bind(0); + dc.Draw()->Rect(bounds_.x, bounds_.y, bounds_.w, bounds_.h, color_); + dc.Flush(); + dc.RebindTexture(); + } +} + +void ImageFileView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + // TODO: involve sizemode + if (texture_) { + w = (float)texture_->Width(); + h = (float)texture_->Height(); + } else { + w = 16; + h = 16; + } +} + void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { dc.MeasureText(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont, text_.c_str(), &w, &h); } diff --git a/ui/view.h b/ui/view.h index 663d0f302e..723e00d1cd 100644 --- a/ui/view.h +++ b/ui/view.h @@ -217,6 +217,7 @@ class View; struct EventParams { View *v; uint32_t a, b, x, y; + float f; std::string s; }; @@ -670,6 +671,8 @@ private: ImageSizeMode sizeMode_; }; +// TextureView takes a texture that is assumed to be alive during the lifetime +// of the view. class TextureView : public InertView { public: TextureView(Texture *texture, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0) @@ -687,6 +690,19 @@ private: ImageSizeMode sizeMode_; }; +// ImageFileView takes a filename and keeps track of the texture by itself. +class ImageFileView : public InertView { +public: + ImageFileView(std::string filename, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0); + ~ImageFileView(); + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + virtual void Draw(UIContext &dc); + +private: + Texture *texture_; + uint32_t color_; + ImageSizeMode sizeMode_; +}; class ProgressBar : public InertView { public: From 1b793049d3e389b1f4f2bac32a2ba0d59eb43842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 3 Dec 2013 16:47:15 +0100 Subject: [PATCH 0906/1445] Key repeat simulation for UI navigation --- ui/viewgroup.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index aebc78c186..0ed37c8a12 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1,3 +1,5 @@ +#include + #include "base/display.h" #include "base/functional.h" #include "base/logging.h" @@ -1058,17 +1060,75 @@ void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { root->Layout(); } +// TODO: Figure out where this should really live. +// Simple simulation of key repeat on platforms and for gamepads where we don't +// automatically get it. + +static int frameCount; + +struct HeldKey { + int key; + int deviceId; + int startFrame; + + bool operator <(const HeldKey &other) const { + if (deviceId < other.deviceId) return true; + if (deviceId > other.deviceId) return false; + if (key < other.key) return true; + return false; + } + bool operator ==(const HeldKey &other) const { return key == other.key && deviceId == other.deviceId; } +}; + +static std::set heldKeys; + +static const int repeatDelay = 15; // 250ms +static const int repeatInterval = 5; // 66ms + void KeyEvent(const KeyInput &key, ViewGroup *root) { if (key.flags & KEY_DOWN) { // We ignore the device ID here. Anything with a DPAD is OK. if (key.keyCode >= NKCODE_DPAD_UP && key.keyCode <= NKCODE_DPAD_RIGHT) { lock_guard lock(focusLock); focusMoves.push_back(key.keyCode); + + // Let's only repeat DPAD initially. + HeldKey hk; + hk.key = key.keyCode; + hk.deviceId = key.deviceId; + hk.startFrame = frameCount; + heldKeys.insert(hk); + } + } + if (key.flags & KEY_UP) { + // We ignore the device ID here. Anything with a DPAD is OK. + if (key.keyCode >= NKCODE_DPAD_UP && key.keyCode <= NKCODE_DPAD_RIGHT) { + HeldKey hk; + hk.key = key.keyCode; + hk.deviceId = key.deviceId; + hk.startFrame = 0; // irrelevant + heldKeys.erase(hk); } } root->Key(key); } +static void ProcessHeldKeys(ViewGroup *root) { + for (auto iter = heldKeys.begin(); iter != heldKeys.end(); ++iter) { + if (iter->startFrame < frameCount - repeatDelay) { + int frame = frameCount - (iter->startFrame + repeatDelay); + if ((frame % repeatInterval) == 0) { + printf("Repeat!\n"); + KeyInput key; + key.keyCode = iter->key; + key.deviceId = iter->deviceId; + key.flags = KEY_DOWN; + KeyEvent(key, root); + } + } + } +} + void TouchEvent(const TouchInput &touch, ViewGroup *root) { EnableFocusMovement(false); @@ -1080,6 +1140,9 @@ void AxisEvent(const AxisInput &axis, ViewGroup *root) { } void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { + ProcessHeldKeys(root); + frameCount++; + if (!root) { ELOG("Tried to update a view hierarchy from a zero pointer root"); return; From 5a5911eac4cce9c6302b7b74195504eba811b2f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 3 Dec 2013 17:49:58 +0100 Subject: [PATCH 0907/1445] Remove unnecessary logging --- ui/viewgroup.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 0ed37c8a12..50184e8a7b 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1118,7 +1118,6 @@ static void ProcessHeldKeys(ViewGroup *root) { if (iter->startFrame < frameCount - repeatDelay) { int frame = frameCount - (iter->startFrame + repeatDelay); if ((frame % repeatInterval) == 0) { - printf("Repeat!\n"); KeyInput key; key.keyCode = iter->key; key.deviceId = iter->deviceId; From 6aa4919c5ef1dd944bf7b970e7df58263fe14633 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 3 Dec 2013 20:05:32 +0100 Subject: [PATCH 0908/1445] Check for ARB_blend_func_extended GL extension. Also check for NV_draw_texture on desktop. --- gfx_es2/gl_state.cpp | 4 +++- gfx_es2/gpu_features.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index ff0697aadf..e24c395d6e 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -197,6 +197,9 @@ void CheckGLExtensions() { // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; #endif + gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; + gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; + #ifdef USING_GLES2 gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0; gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; @@ -204,7 +207,6 @@ void CheckGLExtensions() { gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0; gl_extensions.EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0); - gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; #if defined(ANDROID) || defined(BLACKBERRY) diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 282432734f..10b98e3dc5 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -46,6 +46,8 @@ struct GLExtensions { bool NV_draw_texture; bool NV_copy_image; bool EXT_unpack_subimage; // always supported on desktop and ES3 + bool ARB_blend_func_extended; // dual source blending + // EGL extensions bool EGL_NV_system_time; From 9140f10e2f0a7e99e2a690c9fb5323cf2c5a067c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 4 Dec 2013 12:41:22 +0100 Subject: [PATCH 0909/1445] Take out nonsensical DPI adjustment (android). It had bad effects when combined with kitkat immersive mode. --- .../com/henrikrydgard/libnative/NativeActivity.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index d515207b27..6d5bffc6fb 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -88,6 +88,9 @@ public class NativeActivity extends Activity { // Adjust these as necessary private static String TAG = "NativeActivity"; + // Easy way to flip it on and off from code. + private static final boolean useKitkatImmersiveMode = true; + // Allows us to skip a lot of initialization on secondary calls to onCreate. private static boolean initialized = false; @@ -218,8 +221,10 @@ public class NativeActivity extends Activity { DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); int dpi = metrics.densityDpi; + // We only use dpi to calculate the width. Smaller aspect ratios have giant text despite high DPI. - dpi = (int)((float)dpi * ((float)scrWidth/(float)scrHeight) / (16.0/9.0)); // Adjust to 16:9 + // Uh, I mean, this makes no sense. What was I thinking when I wrote this? Let's just use the DPI as it is. + // dpi = (int)((float)dpi * ((float)scrWidth/(float)scrHeight) / (16.0/9.0)); // Adjust to 16:9 String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); @@ -347,8 +352,10 @@ public class NativeActivity extends Activity { @TargetApi(Build.VERSION_CODES.KITKAT) public void setImmersiveMode() { - this.setImmersive(true); // This is an entirely different kind of immersive mode - hides some notification - mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); + // this.setImmersive(true); // This is an entirely different kind of immersive mode - hides some notification + if (useKitkatImmersiveMode) { + mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); + } } private boolean detectOpenGLES20() { From 563e0051019f22c0a87315c291da0d0c323ac6ff Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 4 Dec 2013 17:38:37 +0100 Subject: [PATCH 0910/1445] Android: Allow sending generic string messages out to Java. Implement stubs for other platforms. --- android/app-android.cpp | 5 +++++ .../henrikrydgard/libnative/NativeActivity.java | 14 +++++++++++--- base/BlackberryMain.cpp | 2 ++ base/NativeApp.h | 1 + base/PCMain.cpp | 17 +++++++---------- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 7c4008ec42..e570406719 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -89,6 +89,11 @@ void System_InputBox(const char *title, const char *defaultValue) { frameCommandParam = title; } +void System_SendMessage(const char *command, const char *parameter) { + frameCommand = command; + frameCommandParam = parameter; +} + std::string System_GetProperty(SystemProperty prop) { switch (prop) { case SYSPROP_NAME: diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 6d5bffc6fb..067ac5d5ab 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -158,6 +158,7 @@ public class NativeActivity extends Activity { w.getDefaultDisplay().getSize(size); } + @SuppressWarnings("deprecation") void GetScreenSize(Point size) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { GetScreenSizeHC(size); @@ -648,10 +649,11 @@ public class NativeActivity extends Activity { return input.getText().toString(); } - public void processCommand(String command, String params) { + public boolean processCommand(String command, String params) { if (command.equals("launchBrowser")) { Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); startActivity(i); + return true; } else if (command.equals("launchEmail")) { Intent send = new Intent(Intent.ACTION_SENDTO); String uriText; @@ -662,22 +664,28 @@ public class NativeActivity extends Activity { Uri uri = Uri.parse(uriText); send.setData(uri); startActivity(Intent.createChooser(send, "E-mail the app author!")); + return true; } else if (command.equals("launchMarket")) { // Don't need this, can just use launchBrowser with a market: // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app // http://developer.android.com/guide/publishing/publishing.html#marketintent + return false; } else if (command.equals("toast")) { Toast toast = Toast.makeText(this, params, Toast.LENGTH_SHORT); toast.show(); + return true; } else if (command.equals("showKeyboard")) { InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); // No idea what the point of the ApplicationWindowToken is or if it matters where we get it from... inputMethodManager.toggleSoftInputFromWindow(mGLSurfaceView.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0); + return true; } else if (command.equals("hideKeyboard")) { InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.toggleSoftInputFromWindow(mGLSurfaceView.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0); + return true; } else if (command.equals("inputBox")) { inputBox(params, "", "OK"); + return true; } else if (command.equals("vibrate")) { if (vibrator != null) { int milliseconds = -1; @@ -707,8 +715,8 @@ public class NativeActivity extends Activity { break; } } - } else { - Log.e(TAG, "Unsupported command " + command + " , param: " + params); + return true; } + return false; } } diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 3314745f04..8ca760cc8b 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -39,6 +39,8 @@ std::string System_GetProperty(SystemProperty prop) { } } +void System_SendMessage(const char *command, const char *parameter) {} + void SystemToast(const char *text) { dialog_instance_t dialog = 0; dialog_create_toast(&dialog); diff --git a/base/NativeApp.h b/base/NativeApp.h index a8de5d723a..03035b6e29 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -108,6 +108,7 @@ void LaunchBrowser(const char *url); void LaunchMarket(const char *url); void LaunchEmail(const char *email_address); void System_InputBox(const char *title, const char *defaultValue); +void System_SendMessage(const char *command, const char *parameter); enum SystemProperty { SYSPROP_NAME, diff --git a/base/PCMain.cpp b/base/PCMain.cpp index a1b75d637a..4f76254ff2 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -188,10 +188,6 @@ void SystemToast(const char *text) { #endif } -void ShowAd(int x, int y, bool center_x) { - // Ignore ads on PC -} - void ShowKeyboard() { // Irrelevant on PC } @@ -200,13 +196,16 @@ void Vibrate(int length_ms) { // Ignore on PC } +void System_SendMessage(const char *command, const char *parameter) { + // Log? +} + void System_InputBox(const char *title, const char *defaultValue) { // Stub NativeMessageReceived((std::string("INPUTBOX:") + title).c_str(), "TestFile"); } -void LaunchBrowser(const char *url) -{ +void LaunchBrowser(const char *url) { #ifdef _WIN32 ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); #elif __linux__ @@ -220,8 +219,7 @@ void LaunchBrowser(const char *url) #endif } -void LaunchMarket(const char *url) -{ +void LaunchMarket(const char *url) { #ifdef _WIN32 ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); #elif __linux__ @@ -235,8 +233,7 @@ void LaunchMarket(const char *url) #endif } -void LaunchEmail(const char *email_address) -{ +void LaunchEmail(const char *email_address) { #ifdef _WIN32 ShellExecute(NULL, "open", (std::string("mailto:") + email_address).c_str(), NULL, NULL, SW_SHOWNORMAL); #elif __linux__ From 3c8374d304bd4fa23a9a581bf70f5685dbf276a3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 4 Dec 2013 17:59:16 +0100 Subject: [PATCH 0911/1445] Add command to invoke android's "Share picture" functionality --- .../henrikrydgard/libnative/NativeActivity.java | 7 ++++++- .../com/henrikrydgard/libnative/NativeGLView.java | 3 +-- .../henrikrydgard/libnative/NativeRenderer.java | 15 +++++++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 067ac5d5ab..7f057b7ff3 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -97,7 +97,7 @@ public class NativeActivity extends Activity { // Graphics and audio interfaces private NativeGLView mGLSurfaceView; private NativeAudioPlayer audioPlayer; - private NativeRenderer nativeRenderer; + protected NativeRenderer nativeRenderer; boolean useOpenSL = false; @@ -665,6 +665,11 @@ public class NativeActivity extends Activity { send.setData(uri); startActivity(Intent.createChooser(send, "E-mail the app author!")); return true; + } else if (command.equals("sharejpeg")) { + Intent share = new Intent(Intent.ACTION_SEND); + share.setType("image/jpeg"); + share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + params)); + startActivity(Intent.createChooser(share, "Share Picture")); } else if (command.equals("launchMarket")) { // Don't need this, can just use launchBrowser with a market: // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index bc891a41e7..61fec4b2f2 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -23,7 +23,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, // Moga controller private Controller mController = null; - boolean isMogaPro = false; + private boolean isMogaPro = false; public NativeGLView(NativeActivity activity) { super(activity); @@ -207,6 +207,5 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, default: break; } - } } diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index 55c1743c1a..e046b3d157 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -3,6 +3,7 @@ package com.henrikrydgard.libnative; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; +import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.util.Log; @@ -10,13 +11,23 @@ import android.util.Log; public class NativeRenderer implements GLSurfaceView.Renderer { private static String TAG = "NativeRenderer"; NativeActivity mActivity; - + private boolean isDark = false; + NativeRenderer(NativeActivity act) { mActivity = act; } + + public void setDark(boolean d) { + isDark = d; + } public void onDrawFrame(GL10 unused /*use GLES20*/) { - displayRender(); + if (isDark) { + GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT); + } else { + displayRender(); + } } public void onSurfaceCreated(GL10 unused, EGLConfig config) { From deb3ccc2614321dfa34d9145a195d78cc8899f2c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 4 Dec 2013 18:12:57 +0100 Subject: [PATCH 0912/1445] Symbian buildfix --- base/QtMain.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 66fcbcc36e..806af47c8d 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -51,6 +51,10 @@ std::string System_GetProperty(SystemProperty prop) { } } +void System_SendMessage(const char *command, const char *parameter) { + // Log? +} + void Vibrate(int length_ms) { if (length_ms == -1 || length_ms == -3) length_ms = 50; From 1e03cd84c31e30e26ea9c82c89184938734cf863 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 5 Dec 2013 22:51:51 +1000 Subject: [PATCH 0913/1445] Linux buildfix. --- ext/libzip/zip_close.c | 3 +++ ext/libzip/zip_name_locate.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/ext/libzip/zip_close.c b/ext/libzip/zip_close.c index 0feb32e94c..5fca55a404 100644 --- a/ext/libzip/zip_close.c +++ b/ext/libzip/zip_close.c @@ -36,6 +36,9 @@ #include #include #include +#ifdef HAVE_STRINGS_H +#include +#endif #include #include #include diff --git a/ext/libzip/zip_name_locate.c b/ext/libzip/zip_name_locate.c index baa6141f67..d91d801c69 100644 --- a/ext/libzip/zip_name_locate.c +++ b/ext/libzip/zip_name_locate.c @@ -34,6 +34,9 @@ #include +#ifdef HAVE_STRINGS_H +#include +#endif #include "zipint.h" From 4caec3871c71df3d8d2440cc772171523fbea182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 5 Dec 2013 14:15:18 +0100 Subject: [PATCH 0914/1445] Add OnOK, OnCancel helpers to UIScreen --- ui/ui_screen.cpp | 10 ++++++++++ ui/ui_screen.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index f7f8e521c1..f035057dd7 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -109,6 +109,16 @@ UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn UIScreen::OnOK(UI::EventParams &e) { + screenManager()->finishDialog(this, DR_OK); + return UI::EVENT_DONE; +} + +UI::EventReturn UIScreen::OnCancel(UI::EventParams &e) { + screenManager()->finishDialog(this, DR_CANCEL); + return UI::EVENT_DONE; +} + PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2) : box_(0), title_(title) { I18NCategory *d = GetI18NCategory("Dialog"); diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 8bf3f30216..fa645ec734 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -17,6 +17,8 @@ public: virtual void axis(const AxisInput &touch); // Some useful default event handlers + UI::EventReturn OnOK(UI::EventParams &e); + UI::EventReturn OnCancel(UI::EventParams &e); UI::EventReturn OnBack(UI::EventParams &e); protected: From e6baad31ed1230e8966eb07f99e92da27dffd57d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 5 Dec 2013 15:08:01 +0100 Subject: [PATCH 0915/1445] Linux buildfix 2 --- ext/libzip/zip_name_locate.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/libzip/zip_name_locate.c b/ext/libzip/zip_name_locate.c index d91d801c69..926abc1b90 100644 --- a/ext/libzip/zip_name_locate.c +++ b/ext/libzip/zip_name_locate.c @@ -33,13 +33,12 @@ +#include "zipint.h" + #include #ifdef HAVE_STRINGS_H #include #endif - -#include "zipint.h" - ZIP_EXTERN int From 48debd78f8532cc11a27dc3e439d3f50914256db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 5 Dec 2013 15:52:39 +0100 Subject: [PATCH 0916/1445] Map backspace correctly in SDL. Minor cosmetic slider fixes --- base/NKCodeFromSDL.h | 1 + ui/view.cpp | 40 +++++++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/base/NKCodeFromSDL.h b/base/NKCodeFromSDL.h index d3b2b6a434..6c5f599832 100644 --- a/base/NKCodeFromSDL.h +++ b/base/NKCodeFromSDL.h @@ -56,6 +56,7 @@ static const std::map KeyMapRawSDLtoNative = InitConstMap (SDLK_BACKSPACE, NKCODE_ESCAPE) #else (SDLK_ESCAPE, NKCODE_ESCAPE) + (SDLK_BACKSPACE, NKCODE_DEL) #endif (SDLK_DELETE, NKCODE_FORWARD_DEL) (SDLK_LCTRL, NKCODE_CTRL_LEFT) diff --git a/ui/view.cpp b/ui/view.cpp index 230eca512c..c0bd179fbd 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -579,12 +579,25 @@ void Slider::Key(const KeyInput &input) { case NKCODE_NUMPAD_ADD: *value_ += 1; break; + case NKCODE_PAGE_UP: + *value_ -= 10; + break; + case NKCODE_PAGE_DOWN: + *value_ += 10; + break; + case NKCODE_MOVE_HOME: + *value_ = minValue_; + break; + case NKCODE_MOVE_END: + *value_ = maxValue_; + break; } Clamp(); } } void Slider::Touch(const TouchInput &input) { + Clickable::Touch(input); if (dragging_ || bounds_.Contains(input.x, input.y)) { float relativeX = (input.x - (bounds_.x + paddingLeft_)) / (bounds_.w - paddingLeft_ - paddingRight_); *value_ = floorf(relativeX * (maxValue_ - minValue_) + minValue_ + 0.5f); @@ -599,10 +612,12 @@ void Slider::Clamp() { void Slider::Draw(UIContext &dc) { bool focus = HasFocus(); + uint32_t linecolor = dc.theme->popupTitle.fgColor; + uint32_t knobcolor = (down_ || focus) ? dc.theme->popupTitle.fgColor : 0xFFFFFFFF; float knobX = ((float)(*value_) - minValue_) / (maxValue_ - minValue_) * (bounds_.w - paddingLeft_ - paddingRight_) + (bounds_.x + paddingLeft_); - dc.FillRect(Drawable(focus ? dc.theme->popupTitle.fgColor : 0xFFFFFFFF), Bounds(bounds_.x + paddingLeft_, bounds_.centerY() - 2, knobX - (bounds_.x + paddingLeft_), 4)); + dc.FillRect(Drawable(linecolor), Bounds(bounds_.x + paddingLeft_, bounds_.centerY() - 2, knobX - (bounds_.x + paddingLeft_), 4)); dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, (bounds_.x + bounds_.w - paddingRight_ - knobX), 4)); - dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, knobcolor, ALIGN_CENTER); char temp[64]; if (showPercent_) sprintf(temp, "%i%%", *value_); @@ -629,7 +644,19 @@ void SliderFloat::Key(const KeyInput &input) { case NKCODE_DPAD_RIGHT: case NKCODE_PLUS: case NKCODE_NUMPAD_ADD: - *value_ += (maxValue_ - minValue_) / 20.0f; + *value_ += (maxValue_ - minValue_) / 30.0f; + break; + case NKCODE_PAGE_UP: + *value_ -= (maxValue_ - minValue_) / 5.0f; + break; + case NKCODE_PAGE_DOWN: + *value_ += (maxValue_ - minValue_) / 5.0f; + break; + case NKCODE_MOVE_HOME: + *value_ = minValue_; + break; + case NKCODE_MOVE_END: + *value_ = maxValue_; break; } Clamp(); @@ -651,10 +678,13 @@ void SliderFloat::Clamp() { void SliderFloat::Draw(UIContext &dc) { bool focus = HasFocus(); + uint32_t linecolor = dc.theme->popupTitle.fgColor; + uint32_t knobcolor = (down_ || focus) ? dc.theme->popupTitle.fgColor : 0xFFFFFFFF; + float knobX = (*value_ - minValue_) / (maxValue_ - minValue_) * (bounds_.w - paddingLeft_ - paddingRight_) + (bounds_.x + paddingLeft_); - dc.FillRect(Drawable(focus ? dc.theme->popupTitle.fgColor : 0xFFFFFFFF), Bounds(bounds_.x + paddingLeft_, bounds_.centerY() - 2, knobX - (bounds_.x + paddingLeft_), 4)); + dc.FillRect(Drawable(linecolor), Bounds(bounds_.x + paddingLeft_, bounds_.centerY() - 2, knobX - (bounds_.x + paddingLeft_), 4)); dc.FillRect(Drawable(0xFF808080), Bounds(knobX, bounds_.centerY() - 2, (bounds_.x + bounds_.w - paddingRight_ - knobX), 4)); - dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + dc.Draw()->DrawImage(dc.theme->sliderKnob, knobX, bounds_.centerY(), 1.0f, knobcolor, ALIGN_CENTER); char temp[64]; sprintf(temp, "%0.2f", *value_); dc.SetFontStyle(dc.theme->uiFont); From 3c862d7bd56b138165dacab6c4f833ed979684e7 Mon Sep 17 00:00:00 2001 From: The Dax Date: Thu, 5 Dec 2013 12:00:40 -0500 Subject: [PATCH 0917/1445] Win32 doesn't have strings.h. --- ext/libzip/config.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/libzip/config.h b/ext/libzip/config.h index 5cdc6c194a..456884aff4 100644 --- a/ext/libzip/config.h +++ b/ext/libzip/config.h @@ -38,7 +38,9 @@ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the header file. */ +#ifndef _WIN32 #define HAVE_STRINGS_H 1 +#endif /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 From b83fea1b6ba4d5012f7085338ab40f03d314e2ee Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 6 Dec 2013 05:03:30 +1000 Subject: [PATCH 0918/1445] Symbian: libzip buildfix. --- ext/libzip/mkstemp.c | 3 +++ ext/libzip/zip.h | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/ext/libzip/mkstemp.c b/ext/libzip/mkstemp.c index 54dc759b63..ba270cf49f 100644 --- a/ext/libzip/mkstemp.c +++ b/ext/libzip/mkstemp.c @@ -33,6 +33,7 @@ * SUCH DAMAGE. */ +#ifndef HAVE_MKSTEMP #include #include @@ -169,3 +170,5 @@ _zip_mkstemp(char *path) /*NOTREACHED*/ } +#endif + diff --git a/ext/libzip/zip.h b/ext/libzip/zip.h index 6a10e990ae..f73e3e5228 100644 --- a/ext/libzip/zip.h +++ b/ext/libzip/zip.h @@ -55,9 +55,18 @@ extern "C" { #endif #include +#include #include #include +#ifdef __SYMBIAN32__ +#define _stat stat +#define _wcsdup wcsdup +#define _wfopen wfopen +#define _wremove wremove +#define _wstat wstat +#endif + /* flags for zip_open */ #define ZIP_CREATE 1 From 26dfe75882873fc8d375253acd0cc0e6e64ecaef Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 6 Dec 2013 13:06:04 +1000 Subject: [PATCH 0919/1445] Some improvements to Qt Audio. --- base/QtMain.h | 6 +++--- ext/libzip/mkstemp.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index b4ade8a40e..a6f7badc97 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -233,10 +233,10 @@ public slots: fmt.setSampleSize(AUDIO_SAMPLESIZE); fmt.setByteOrder(QAudioFormat::LittleEndian); fmt.setSampleType(QAudioFormat::SignedInt); - mixlen = 5*2*AUDIO_CHANNELS*AUDIO_SAMPLES; + mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; mixbuf = (char*)malloc(mixlen); output = new QAudioOutput(fmt); - output->setBufferSize(mixlen); + output->setBufferSize(mixlen*10); feed = output->start(); if (feed != NULL) timer = startTimer(1000*AUDIO_SAMPLES / AUDIO_FREQ); @@ -245,7 +245,7 @@ public slots: protected: void timerEvent(QTimerEvent *) { memset(mixbuf, 0, mixlen); - size_t frames = NativeMix((short *)mixbuf, 5*AUDIO_SAMPLES); + size_t frames = NativeMix((short *)mixbuf, AUDIO_SAMPLES); if (frames > 0) feed->write(mixbuf, sizeof(short) * 2 * frames); } diff --git a/ext/libzip/mkstemp.c b/ext/libzip/mkstemp.c index ba270cf49f..62641f0af3 100644 --- a/ext/libzip/mkstemp.c +++ b/ext/libzip/mkstemp.c @@ -33,6 +33,7 @@ * SUCH DAMAGE. */ +#include "config.h" #ifndef HAVE_MKSTEMP #include #include From 59202a0dfc256dbdfd027b1f6a5eb6ea2636d739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 6 Dec 2013 15:01:34 +0100 Subject: [PATCH 0920/1445] Add +/- buttons to integer sliders for fine adjustment --- ui/ui_screen.cpp | 19 ++++++++++++++++++- ui/ui_screen.h | 2 ++ ui/view.h | 7 +++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index f035057dd7..b6cef8d6af 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -305,10 +305,27 @@ void PopupSliderChoiceFloat::Draw(UIContext &dc) { dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); } +EventReturn SliderPopupScreen::OnDecrease(EventParams ¶ms) { + sliderValue_--; + slider_->Clamp(); + return EVENT_DONE; +} + +EventReturn SliderPopupScreen::OnIncrease(EventParams ¶ms) { + sliderValue_++; + slider_->Clamp(); + return EVENT_DONE; +} + void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; sliderValue_ = *value_; - slider_ = parent->Add(new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5)))); + LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 5)))); + slider_ = new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(1.0f)); + lin->Add(slider_); + lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderPopupScreen::OnDecrease); + lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderPopupScreen::OnIncrease); + UI::SetFocusedView(slider_); } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index fa645ec734..c5626e6a30 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -120,6 +120,8 @@ public: Event OnChange; private: + EventReturn OnDecrease(EventParams ¶ms); + EventReturn OnIncrease(EventParams ¶ms); virtual void OnCompleted(DialogResult result); Slider *slider_; int *value_; diff --git a/ui/view.h b/ui/view.h index 723e00d1cd..be36fcb297 100644 --- a/ui/view.h +++ b/ui/view.h @@ -446,8 +446,10 @@ public: virtual void Touch(const TouchInput &input); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; void SetShowPercent(bool s) { showPercent_ = s; } -private: + + // OK to call this from the outside after having modified *value_ void Clamp(); +private: int *value_; bool showPercent_; int minValue_; @@ -465,8 +467,9 @@ public: virtual void Touch(const TouchInput &input); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; -private: + // OK to call this from the outside after having modified *value_ void Clamp(); +private: float *value_; float minValue_; float maxValue_; From 6730d2d2447b3235b952f483c41a48414140c45f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 6 Dec 2013 15:01:52 +0100 Subject: [PATCH 0921/1445] Android: set immersive mode on "configChanges" --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 7f057b7ff3..82f0b80983 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -415,6 +415,9 @@ public class NativeActivity extends Activity { public void onConfigurationChanged(Configuration newConfig) { // Ignore orientation change super.onConfigurationChanged(newConfig); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + setImmersiveMode(); + } } // We simply grab the first input device to produce an event and ignore all others that are connected. From af08e8f1de16bc80314fe96f45605067e0592183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 6 Dec 2013 15:28:52 +0100 Subject: [PATCH 0922/1445] Limit progress bars to [0-1]. --- ui/view.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ui/view.h b/ui/view.h index be36fcb297..c06753a96a 100644 --- a/ui/view.h +++ b/ui/view.h @@ -715,7 +715,15 @@ public: virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; virtual void Draw(UIContext &dc); - void SetProgress(float progress) { progress_ = progress; } + void SetProgress(float progress) { + if (progress > 1.0f) { + progress_ = 1.0f; + } else if (progress < 0.0f) { + progress_ = 0.0f; + } else { + progress_ = progress; + } + } float GetProgress() const { return progress_; } private: From d7c90499c4ad4dd94c72e46004c696182e42b4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 6 Dec 2013 16:44:39 +0100 Subject: [PATCH 0923/1445] Item views should not override height when a different layout is specified. Fix some fallout from that change. --- ui/view.cpp | 17 +++++++++++------ ui/view.h | 6 +++--- ui/viewgroup.cpp | 34 ++++++++++++++++++++-------------- ui/viewgroup.h | 9 ++++----- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index c0bd179fbd..666eee6369 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -269,8 +269,10 @@ void StickyChoice::FocusChanged(int focusFlags) { } Item::Item(LayoutParams *layoutParams) : InertView(layoutParams) { - layoutParams_->width = FILL_PARENT; - layoutParams_->height = ITEM_HEIGHT; + if (!layoutParams) { + layoutParams_->width = FILL_PARENT; + layoutParams_->height = ITEM_HEIGHT; + } } void Item::GetContentDimensions(const UIContext &dc, float &w, float &h) const { @@ -284,9 +286,11 @@ void ClickableItem::GetContentDimensions(const UIContext &dc, float &w, float &h } ClickableItem::ClickableItem(LayoutParams *layoutParams) : Clickable(layoutParams) { - if (layoutParams_->width == WRAP_CONTENT) - layoutParams_->width = FILL_PARENT; - layoutParams_->height = ITEM_HEIGHT; + if (!layoutParams) { + if (layoutParams_->width == WRAP_CONTENT) + layoutParams_->width = FILL_PARENT; + layoutParams_->height = ITEM_HEIGHT; + } } void ClickableItem::Draw(UIContext &dc) { @@ -336,8 +340,9 @@ void Choice::Draw(UIContext &dc) { } Style style = dc.theme->itemStyle; - if (!IsEnabled()) + if (!IsEnabled()) { style = dc.theme->itemDisabledStyle; + } if (atlasImage_ != -1) { dc.Draw()->DrawImage(atlasImage_, bounds_.centerX(), bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER); diff --git a/ui/view.h b/ui/view.h index c06753a96a..9cce88f1a3 100644 --- a/ui/view.h +++ b/ui/view.h @@ -237,7 +237,7 @@ public: EventReturn Dispatch(EventParams &e); // This is suggested for use in most cases. Autobinds, allowing for neat syntax. - template + template T *Handle(T *thiz, EventReturn (T::* theCallback)(EventParams &e)) { Add(std::bind(theCallback, thiz, placeholder::_1)); return thiz; @@ -248,7 +248,6 @@ public: private: std::vector handlers_; - DISALLOW_COPY_AND_ASSIGN(Event); }; @@ -541,6 +540,7 @@ protected: // hackery virtual bool IsSticky() const { return false; } + int height_; std::string text_; std::string smallText_; ImageID atlasImage_; @@ -563,7 +563,7 @@ public: virtual void Key(const KeyInput &key); virtual void Touch(const TouchInput &touch); virtual void FocusChanged(int focusFlags); - + void Press() { down_ = true; dragging_ = false; } void Release() { down_ = false; dragging_ = false; } bool IsDown() { return down_; } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 50184e8a7b..bad074a861 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -93,9 +93,9 @@ void ViewGroup::Draw(UIContext &dc) { // Darken things behind. dc.FillRect(UI::Drawable(0x60000000), Bounds(0,0,dp_xres, dp_yres)); float dropsize = 30; - dc.Draw()->DrawImage4Grid(dc.theme->dropShadow4Grid, bounds_.x - dropsize, bounds_.y, bounds_.x2() + dropsize, bounds_.y2()+dropsize*1.5, 0xDF000000, 3.0f); - - // dc.Draw()->DrawImage4Grid(dc.theme->dropShadow, ) + dc.Draw()->DrawImage4Grid(dc.theme->dropShadow4Grid, + bounds_.x - dropsize, bounds_.y, + bounds_.x2() + dropsize, bounds_.y2()+dropsize*1.5, 0xDF000000, 3.0f); } if (clip_) { @@ -254,7 +254,6 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio return 1.0f / distance + overlap*10 + bonus; } - NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, NeighborResult result) { if (!IsEnabled()) return result; @@ -457,7 +456,7 @@ void LinearLayout::Layout() { Bounds itemBounds; float pos; - + if (orientation_ == ORIENT_HORIZONTAL) { pos = bounds.x; itemBounds.y = bounds.y; @@ -476,7 +475,7 @@ void LinearLayout::Layout() { const LinearLayoutParams *linLayoutParams = static_cast(layoutParams); if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; - Gravity gravity = G_TOPLEFT; + Gravity gravity = G_TOPLEFT; Margins margins = defaultMargins_; if (linLayoutParams) { if (linLayoutParams->HasMargins()) @@ -508,7 +507,7 @@ void FrameLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ve if (views_.empty()) { MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); - return; + return; } for (size_t i = 0; i < views_.size(); i++) { @@ -910,8 +909,16 @@ EventReturn TabHolder::OnTabClick(EventParams &e) { return EVENT_DONE; } +ChoiceStrip::ChoiceStrip(Orientation orientation, LayoutParams *layoutParams) + : LinearLayout(orientation, layoutParams), selected_(0), topTabs_(false) { + SetSpacing(0.0f); +} + void ChoiceStrip::AddChoice(const std::string &title) { - StickyChoice *c = new StickyChoice(title, "", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + StickyChoice *c = new StickyChoice(title, "", + orientation_ == ORIENT_HORIZONTAL ? + 0 : + new LinearLayoutParams(FILL_PARENT, ITEM_HEIGHT)); c->OnClick.Handle(this, &ChoiceStrip::OnChoiceClick); Add(c); if (selected_ == (int)views_.size() - 1) @@ -919,7 +926,10 @@ void ChoiceStrip::AddChoice(const std::string &title) { } void ChoiceStrip::AddChoice(ImageID buttonImage) { - StickyChoice *c = new StickyChoice(buttonImage, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + StickyChoice *c = new StickyChoice(buttonImage, + orientation_ == ORIENT_HORIZONTAL ? + 0 : + new LinearLayoutParams(FILL_PARENT, ITEM_HEIGHT)); c->OnClick.Handle(this, &ChoiceStrip::OnChoiceClick); Add(c); if (selected_ == (int)views_.size() - 1) @@ -951,19 +961,16 @@ void ChoiceStrip::SetSelection(int sel) { if (selected_ < (int)views_.size()) static_cast(views_[selected_])->Press(); if (topTabs_ && prevSelected != selected_) { - EventParams e; + EventParams e; e.v = views_[selected_]; static_cast(views_[selected_])->OnClick.Trigger(e); } } - - void ChoiceStrip::HighlightChoice(unsigned int choice){ if (choice < (unsigned int)views_.size()){ static_cast(views_[choice])->HighlightChanged(true); } - }; void ChoiceStrip::Key(const KeyInput &input) { @@ -987,7 +994,6 @@ void ChoiceStrip::Draw(UIContext &dc) { } } - ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a) { linLayout_ = new LinearLayout(ORIENT_VERTICAL); diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 04b1291d6c..d657eab18b 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -46,7 +46,7 @@ public: // Assumes that layout has taken place. NeighborResult FindNeighbor(View *view, FocusDirection direction, NeighborResult best); - + virtual bool CanBeFocused() const { return false; } virtual bool IsViewGroup() const { return true; } @@ -78,7 +78,6 @@ public: void Layout(); }; - enum { NONE = -1, }; @@ -159,7 +158,8 @@ private: // Initially, only horizontal layout is supported. struct GridLayoutSettings { GridLayoutSettings() : orientation(ORIENT_HORIZONTAL), columnWidth(100), rowHeight(50), spacing(5), fillCells(false) {} - GridLayoutSettings(int colW, int colH, int spac = 5) : orientation(ORIENT_HORIZONTAL), columnWidth(colW), rowHeight(colH), spacing(spac), fillCells(false) {} + GridLayoutSettings(int colW, int colH, int spac = 5) + : orientation(ORIENT_HORIZONTAL), columnWidth(colW), rowHeight(colH), spacing(spac), fillCells(false) {} Orientation orientation; int columnWidth; @@ -237,8 +237,7 @@ public: class ChoiceStrip : public LinearLayout { public: - ChoiceStrip(Orientation orientation, LayoutParams *layoutParams = 0) - : LinearLayout(orientation, layoutParams), selected_(0), topTabs_(false) { SetSpacing(0.0f); } + ChoiceStrip(Orientation orientation, LayoutParams *layoutParams = 0); void AddChoice(const std::string &title); void AddChoice(ImageID buttonImage); From 567998672ea770f969fed24ddc277de5446fd467 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 7 Dec 2013 19:41:07 +1000 Subject: [PATCH 0924/1445] Update libpng usage to libpng1.6 and enable for Blackberry. --- image/png_load.cpp | 138 +++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 86 deletions(-) diff --git a/image/png_load.cpp b/image/png_load.cpp index 1b23fd99de..8554137be6 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -2,12 +2,13 @@ #include #include "png_load.h" #include "base/logging.h" -#include "ext/stb_image/stb_image.h" +#ifdef BLACKBERRY +#define PNG_AVAILABLE 1 +#endif -// #define PNG_AVAILABLE #ifndef PNG_AVAILABLE - +#include "ext/stb_image/stb_image.h" // *image_data_ptr should be deleted with free() // return value of 1 == success. int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, @@ -65,97 +66,62 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in #else #include -#include #include // *image_data_ptr should be deleted with free() // return value of 1 == success. -int pngLoad(const char *file, int *pwidth, - int *pheight, unsigned char **image_data_ptr, - bool flip) { - FILE *infile = fopen(file, "rb"); - if (!infile) { - printf("No such file: %s\n", file); - return 0; - } - /* Check for the 8-byte signature */ - char sig[8]; /* PNG signature array */ - int len = fread(sig, 1, 8, infile); - if (len != 8 || !png_check_sig((unsigned char *) sig, 8)) { - fclose(infile); - return 0; - } - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) { - fclose(infile); - return 4; /* out of memory */ - } - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); - fclose(infile); - return 4; /* out of memory */ - } - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(infile); - return 0; - } +int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip) { + if (flip) + ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); + png_image png; + memset(&png, 0, sizeof(png)); + png.version = PNG_IMAGE_VERSION; - png_init_io(png_ptr, infile); - png_set_sig_bytes(png_ptr, 8); // we already checked the sig bytes - png_read_info(png_ptr, info_ptr); - int bit_depth=0; - int color_type=0; - png_uint_32 width=0, height=0; - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); - *pwidth = (int)width; - *pheight = (int)height; - // Set up some transforms. Always load RGBA. - if (color_type & PNG_COLOR_MASK_ALPHA) { - // png_set_strip_alpha(png_ptr); - } - if (bit_depth > 8) { - png_set_strip_16(png_ptr); - } - if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - png_set_gray_to_rgb(png_ptr); - } - if (color_type == PNG_COLOR_TYPE_PALETTE) { - png_set_palette_to_rgb(png_ptr); - } - if (color_type == PNG_COLOR_TYPE_RGB) { - png_set_filler(png_ptr, 255, PNG_FILLER_AFTER); - } + png_image_begin_read_from_file(&png, file); - // Update the png info struct. - png_read_update_info(png_ptr, info_ptr); - unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr); - unsigned char *image_data = NULL; /* raw png image data */ - if ((image_data = (unsigned char *) malloc(rowbytes * height))==NULL) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return 4; + if (PNG_IMAGE_FAILED(png)) + { + ELOG("pngLoad: %s", png.message); + return 0; } - png_bytepp row_pointers = NULL; - if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - free(image_data); - image_data = NULL; - return 4; - } - if (flip) { - for (unsigned long i = 0; i < height; ++i) - row_pointers[height - 1 - i] = (png_byte *)(image_data + i*rowbytes); - } else { - for (unsigned long i = 0; i < height; ++i) - row_pointers[i] = (png_byte *)(image_data + i*rowbytes); - } - png_read_image(png_ptr, row_pointers); - free(row_pointers); - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(infile); - *image_data_ptr = image_data; + *pwidth = png.width; + *pheight = png.height; + + int stride = PNG_IMAGE_ROW_STRIDE(png); + *image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_BUFFER_SIZE(png, stride)); + + png_image_finish_read(&png, NULL, image_data_ptr, stride, NULL); + png_image_free(&png); + return 1; } +int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr, + bool flip) { + if (flip) + ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); + png_image png; + memset(&png, 0, sizeof(png)); + png.version = PNG_IMAGE_VERSION; + + png_image_begin_read_from_memory(&png, input_ptr, input_len); + + if (PNG_IMAGE_FAILED(png)) + { + ELOG("pngLoad: %s", png.message); + return 0; + } + *pwidth = png.width; + *pheight = png.height; + + int stride = PNG_IMAGE_ROW_STRIDE(png); + *image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_BUFFER_SIZE(png, stride)); + + png_image_finish_read(&png, NULL, image_data_ptr, stride, NULL); + png_image_free(&png); + + return 1; +} + + #endif From bc1ad342e728c20e67919129c12f4e17d3584934 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 7 Dec 2013 12:23:41 +0100 Subject: [PATCH 0925/1445] Add easy way to check gl version >= something --- gfx_es2/gpu_features.cpp | 12 ++++++++++++ gfx_es2/gpu_features.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/gfx_es2/gpu_features.cpp b/gfx_es2/gpu_features.cpp index 85ef622a3d..cf9be36606 100644 --- a/gfx_es2/gpu_features.cpp +++ b/gfx_es2/gpu_features.cpp @@ -1,5 +1,17 @@ #include "gfx_es2/gpu_features.h" +bool GLExtensions::VersionGEThan(int major, int minor, int sub) { + if (gl_extensions.ver[0] > major) + return true; + if (gl_extensions.ver[0] < major) + return false; + if (gl_extensions.ver[1] > minor) + return true; + if (gl_extensions.ver[1] < minor) + return false; + return gl_extensions.ver[2] >= sub; +} + void ProcessGPUFeatures() { gl_extensions.bugs = 0; // Should be table driven instead, this is a quick hack for Galaxy Y diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 10b98e3dc5..506cfad639 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -29,6 +29,7 @@ enum { struct GLExtensions { int ver[3]; int gpuVendor; + bool GLES3; // true if the full OpenGL ES 3.0 is supported bool OES_depth24; bool OES_packed_depth_stencil; @@ -55,6 +56,9 @@ struct GLExtensions { // Bugs int bugs; + + // greater-or-equal than + bool VersionGEThan(int major, int minor, int sub = 0); }; extern GLExtensions gl_extensions; From 4e2212de407cafb175091fce0e236dfaaa9d4226 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 7 Dec 2013 15:20:11 +0100 Subject: [PATCH 0926/1445] Skip the EGLConfigChooser. Seems to choose a suboptimal mode on several phones. We just have to live with no stencil in non-buffered. Play buffered. --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 82f0b80983..20378840ac 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -311,9 +311,9 @@ public class NativeActivity extends Activity { // if we specify that we want destination alpha in the config chooser, which we do. // http://grokbase.com/t/gg/android-developers/11bj40jm4w/fall-back - mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBX_8888); + // mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBX_8888); - mGLSurfaceView.setEGLConfigChooser(new NativeEGLConfigChooser()); + // mGLSurfaceView.setEGLConfigChooser(new NativeEGLConfigChooser()); nativeRenderer = new NativeRenderer(this); mGLSurfaceView.setRenderer(nativeRenderer); From 64b5146718c768818c6819057d00712acf31631e Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 8 Dec 2013 01:36:37 +1000 Subject: [PATCH 0927/1445] Add libpng16 to project. --- Android.mk | 18 +- ext/libpng16/png.c | 4299 +++++++++++++++++++++++++++++++ ext/libpng16/png.h | 3319 ++++++++++++++++++++++++ ext/libpng16/pngconf.h | 617 +++++ ext/libpng16/pngdebug.h | 157 ++ ext/libpng16/pngerror.c | 932 +++++++ ext/libpng16/pngget.c | 1177 +++++++++ ext/libpng16/pnginfo.h | 260 ++ ext/libpng16/pnglibconf.h | 454 ++++ ext/libpng16/pngmem.c | 277 ++ ext/libpng16/pngpread.c | 1291 ++++++++++ ext/libpng16/pngpriv.h | 2043 +++++++++++++++ ext/libpng16/pngread.c | 4000 +++++++++++++++++++++++++++++ ext/libpng16/pngrio.c | 118 + ext/libpng16/pngrtran.c | 5110 +++++++++++++++++++++++++++++++++++++ ext/libpng16/pngrutil.c | 4475 ++++++++++++++++++++++++++++++++ ext/libpng16/pngset.c | 1597 ++++++++++++ ext/libpng16/pngstruct.h | 489 ++++ ext/libpng16/pngtest.c | 1973 ++++++++++++++ ext/libpng16/pngtrans.c | 841 ++++++ ext/libpng16/pngwio.c | 164 ++ ext/libpng16/pngwrite.c | 2330 +++++++++++++++++ ext/libpng16/pngwtran.c | 637 +++++ ext/libpng16/pngwutil.c | 3023 ++++++++++++++++++++++ image/png_load.cpp | 20 +- native.vcxproj | 25 +- native.vcxproj.filters | 26 +- 27 files changed, 39656 insertions(+), 16 deletions(-) create mode 100644 ext/libpng16/png.c create mode 100644 ext/libpng16/png.h create mode 100644 ext/libpng16/pngconf.h create mode 100644 ext/libpng16/pngdebug.h create mode 100644 ext/libpng16/pngerror.c create mode 100644 ext/libpng16/pngget.c create mode 100644 ext/libpng16/pnginfo.h create mode 100644 ext/libpng16/pnglibconf.h create mode 100644 ext/libpng16/pngmem.c create mode 100644 ext/libpng16/pngpread.c create mode 100644 ext/libpng16/pngpriv.h create mode 100644 ext/libpng16/pngread.c create mode 100644 ext/libpng16/pngrio.c create mode 100644 ext/libpng16/pngrtran.c create mode 100644 ext/libpng16/pngrutil.c create mode 100644 ext/libpng16/pngset.c create mode 100644 ext/libpng16/pngstruct.h create mode 100644 ext/libpng16/pngtest.c create mode 100644 ext/libpng16/pngtrans.c create mode 100644 ext/libpng16/pngwio.c create mode 100644 ext/libpng16/pngwrite.c create mode 100644 ext/libpng16/pngwtran.c create mode 100644 ext/libpng16/pngwutil.c diff --git a/Android.mk b/Android.mk index be4a3926de..92da5f33f8 100644 --- a/Android.mk +++ b/Android.mk @@ -19,6 +19,22 @@ LOCAL_SRC_FILES :=\ data/compression.cpp \ ext/rg_etc1/rg_etc1.cpp \ ext/cityhash/city.cpp \ + ext/libpng16/png.c \ + ext/libpng16/pngerror.c \ + ext/libpng16/pngget.c \ + ext/libpng16/pngmem.c \ + ext/libpng16/pngpread.c \ + ext/libpng16/pngread.c \ + ext/libpng16/pngrio.c \ + ext/libpng16/pngrtran.c \ + ext/libpng16/pngrutil.c \ + ext/libpng16/pngset.c \ + ext/libpng16/pngtest.c \ + ext/libpng16/pngtrans.c \ + ext/libpng16/pngwio.c \ + ext/libpng16/pngwrite.c \ + ext/libpng16/pngwtran.c \ + ext/libpng16/pngwutil.c \ ext/jpge/jpgd.cpp \ ext/jpge/jpge.cpp \ ext/sha1/sha1.cpp \ @@ -80,7 +96,7 @@ LOCAL_SRC_FILES :=\ ui/virtual_input.cpp \ util/random/perlin.cpp \ util/text/utf8.cpp \ - util/text/parsers.cpp \ + util/text/parsers.cpp \ util/hash/hash.cpp LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -Wall -Wno-multichar -D__STDC_CONSTANT_MACROS diff --git a/ext/libpng16/png.c b/ext/libpng16/png.c new file mode 100644 index 0000000000..9a81e81648 --- /dev/null +++ b/ext/libpng16/png.c @@ -0,0 +1,4299 @@ + +/* png.c - location for general purpose libpng functions + * + * Last changed in libpng 1.6.2 [April 25, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef png_libpng_version_1_6_7 Your_png_h_is_not_version_1_6_7; + +/* Tells libpng that we have already handled the first "num_bytes" bytes + * of the PNG file signature. If the PNG data is embedded into another + * stream we can set num_bytes = 8 so that libpng will not attempt to read + * or write any of the magic bytes before it starts on the IHDR. + */ + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_set_sig_bytes(png_structrp png_ptr, int num_bytes) +{ + png_debug(1, "in png_set_sig_bytes"); + + if (png_ptr == NULL) + return; + + if (num_bytes > 8) + png_error(png_ptr, "Too many bytes for PNG signature"); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behavior as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + + if (num_to_check > 8) + num_to_check = 8; + + else if (num_to_check < 1) + return (-1); + + if (start > 7) + return (-1); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Function to allocate memory for zlib */ +PNG_FUNCTION(voidpf /* PRIVATE */, +png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) +{ + png_alloc_size_t num_bytes = size; + + if (png_ptr == NULL) + return NULL; + + if (items >= (~(png_alloc_size_t)0)/size) + { + png_warning (png_voidcast(png_structrp, png_ptr), + "Potential overflow in png_zalloc()"); + return NULL; + } + + num_bytes *= items; + return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes); +} + +/* Function to free memory for zlib */ +void /* PRIVATE */ +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free(png_voidcast(png_const_structrp,png_ptr), ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structrp png_ptr) +{ + /* The cast is safe because the crc is a 32 bit value. */ + png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)) + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + /* 'uLong' is defined in zlib.h as unsigned long; this means that on some + * systems it is a 64 bit value. crc32, however, returns 32 bits so the + * following cast is safe. 'uInt' may be no more than 16 bits, so it is + * necessary to perform a loop here. + */ + if (need_crc && length > 0) + { + uLong crc = png_ptr->crc; /* Should never issue a warning */ + + do + { + uInt safe_length = (uInt)length; + if (safe_length == 0) + safe_length = (uInt)-1; /* evil, but safe */ + + crc = crc32(crc, ptr, safe_length); + + /* The following should never issue compiler warnings; if they do the + * target system has characteristics that will probably violate other + * assumptions within the libpng code. + */ + ptr += safe_length; + length -= safe_length; + } + while (length > 0); + + /* And the following is always safe because the crc is only 32 bits. */ + png_ptr->crc = (png_uint_32)crc; + } +} + +/* Check a user supplied version number, called from both read and write + * functions that create a png_struct. + */ +int +png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) +{ + if (user_png_ver) + { + int i = 0; + + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + + else + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first and third digits (note that when we reach version + * 1.10 we will need to check the fourth symbol, namely user_png_ver[3]). + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && (user_png_ver[2] != png_libpng_ver[2] || + user_png_ver[3] != png_libpng_ver[3])) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#ifdef PNG_WARNINGS_SUPPORTED + size_t pos = 0; + char m[128]; + + pos = png_safecat(m, (sizeof m), pos, + "Application built with libpng-"); + pos = png_safecat(m, (sizeof m), pos, user_png_ver); + pos = png_safecat(m, (sizeof m), pos, " but running with "); + pos = png_safecat(m, (sizeof m), pos, png_libpng_ver); + + png_warning(png_ptr, m); +#endif + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + + return 0; + } + } + + /* Success return. */ + return 1; +} + +/* Generic function to create a png_struct for either read or write - this + * contains the common initialization. + */ +PNG_FUNCTION(png_structp /* PRIVATE */, +png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +{ + png_struct create_struct; +# ifdef PNG_SETJMP_SUPPORTED + jmp_buf create_jmp_buf; +# endif + + /* This temporary stack-allocated structure is used to provide a place to + * build enough context to allow the user provided memory allocator (if any) + * to be called. + */ + memset(&create_struct, 0, (sizeof create_struct)); + + /* Added at libpng-1.2.6 */ +# ifdef PNG_USER_LIMITS_SUPPORTED + create_struct.user_width_max = PNG_USER_WIDTH_MAX; + create_struct.user_height_max = PNG_USER_HEIGHT_MAX; + +# ifdef PNG_USER_CHUNK_CACHE_MAX + /* Added at libpng-1.2.43 and 1.4.0 */ + create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; +# endif + +# ifdef PNG_USER_CHUNK_MALLOC_MAX + /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists + * in png_struct regardless. + */ + create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; +# endif +# endif + + /* The following two API calls simply set fields in png_struct, so it is safe + * to do them now even though error handling is not yet set up. + */ +# ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn); +# endif + + /* (*error_fn) can return control to the caller after the error_ptr is set, + * this will result in a memory leak unless the error_fn does something + * extremely sophisticated. The design lacks merit but is implicit in the + * API. + */ + png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn); + +# ifdef PNG_SETJMP_SUPPORTED + if (!setjmp(create_jmp_buf)) + { + /* Temporarily fake out the longjmp information until we have + * successfully completed this function. This only works if we have + * setjmp() support compiled in, but it is safe - this stuff should + * never happen. + */ + create_struct.jmp_buf_ptr = &create_jmp_buf; + create_struct.jmp_buf_size = 0; /*stack allocation*/ + create_struct.longjmp_fn = longjmp; +# else + { +# endif + /* Call the general version checker (shared with read and write code): + */ + if (png_user_version_check(&create_struct, user_png_ver)) + { + png_structrp png_ptr = png_voidcast(png_structrp, + png_malloc_warn(&create_struct, (sizeof *png_ptr))); + + if (png_ptr != NULL) + { + /* png_ptr->zstream holds a back-pointer to the png_struct, so + * this can only be done now: + */ + create_struct.zstream.zalloc = png_zalloc; + create_struct.zstream.zfree = png_zfree; + create_struct.zstream.opaque = png_ptr; + +# ifdef PNG_SETJMP_SUPPORTED + /* Eliminate the local error handling: */ + create_struct.jmp_buf_ptr = NULL; + create_struct.jmp_buf_size = 0; + create_struct.longjmp_fn = 0; +# endif + + *png_ptr = create_struct; + + /* This is the successful return point */ + return png_ptr; + } + } + } + + /* A longjmp because of a bug in the application storage allocator or a + * simple failure to allocate the png_struct. + */ + return NULL; +} + +/* Allocate the memory for an info_struct for the application. */ +PNG_FUNCTION(png_infop,PNGAPI +png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED) +{ + png_inforp info_ptr; + + png_debug(1, "in png_create_info_struct"); + + if (png_ptr == NULL) + return NULL; + + /* Use the internal API that does not (or at least should not) error out, so + * that this call always returns ok. The application typically sets up the + * error handling *after* creating the info_struct because this is the way it + * has always been done in 'example.c'. + */ + info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr, + (sizeof *info_ptr))); + + if (info_ptr != NULL) + memset(info_ptr, 0, (sizeof *info_ptr)); + + return info_ptr; +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. From libpng 1.6.0 this function is also used + * internally to implement the png_info release part of the 'struct' destroy + * APIs. This ensures that all possible approaches free the same data (all of + * it). + */ +void PNGAPI +png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr) +{ + png_inforp info_ptr = NULL; + + png_debug(1, "in png_destroy_info_struct"); + + if (png_ptr == NULL) + return; + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + /* Do this first in case of an error below; if the app implements its own + * memory management this can lead to png_free calling png_error, which + * will abort this routine and return control to the app error handler. + * An infinite loop may result if it then tries to free the same info + * ptr. + */ + *info_ptr_ptr = NULL; + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + memset(info_ptr, 0, (sizeof *info_ptr)); + png_free(png_ptr, info_ptr); + } +} + +/* Initialize the info structure. This is now an internal function (0.89) + * and applications using it are urged to use png_create_info_struct() + * instead. Use deprecated in 1.6.0, internal use removed (used internally it + * is just a memset). + * + * NOTE: it is almost inconceivable that this API is used because it bypasses + * the user-memory mechanism and the user error handling/warning mechanisms in + * those cases where it does anything other than a memset. + */ +PNG_FUNCTION(void,PNGAPI +png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), + PNG_DEPRECATED) +{ + png_inforp info_ptr = *ptr_ptr; + + png_debug(1, "in png_info_init_3"); + + if (info_ptr == NULL) + return; + + if ((sizeof (png_info)) > png_info_struct_size) + { + *ptr_ptr = NULL; + /* The following line is why this API should not be used: */ + free(info_ptr); + info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL, + (sizeof *info_ptr))); + *ptr_ptr = info_ptr; + } + + /* Set everything to 0 */ + memset(info_ptr, 0, (sizeof *info_ptr)); +} + +/* The following API is not called internally */ +void PNGAPI +png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr, + int freer, png_uint_32 mask) +{ + png_debug(1, "in png_data_freer"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (freer == PNG_DESTROY_WILL_FREE_DATA) + info_ptr->free_me |= mask; + + else if (freer == PNG_USER_WILL_FREE_DATA) + info_ptr->free_me &= ~mask; + + else + png_error(png_ptr, "Unknown freer parameter in png_data_freer"); +} + +void PNGAPI +png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +#ifdef PNG_TEXT_SUPPORTED + /* Free text item num or (if num == -1) all text items */ + if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } + } +#endif + +#ifdef PNG_tRNS_SUPPORTED + /* Free any tRNS entry */ + if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->trans_alpha); + info_ptr->trans_alpha = NULL; + info_ptr->valid &= ~PNG_INFO_tRNS; + } +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* Free any sCAL entry */ + if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; + info_ptr->valid &= ~PNG_INFO_sCAL; + } +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* Free any pCAL entry */ + if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + unsigned int i; + for (i = 0; i < info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i] = NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; + } +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* Free any profile entry */ + if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; + } +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ + if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + + else + { + if (info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, (int)i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } + } +#endif + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED + if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + + else + { + int i; + + if (info_ptr->unknown_chunks_num) + { + for (i = 0; i < info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, (int)i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } + } +#endif + +#ifdef PNG_hIST_SUPPORTED + /* Free any hIST entry */ + if ((mask & PNG_FREE_HIST) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; + } +#endif + + /* Free any PLTE entry that was internally allocated */ + if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; + info_ptr->num_palette = 0; + } + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Free any image bits attached to the info structure */ + if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) + { + if (info_ptr->row_pointers) + { + png_uint_32 row; + for (row = 0; row < info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row] = NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers = NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; + } +#endif + + if (num != -1) + mask &= ~PNG_FREE_MUL; + + info_ptr->free_me &= ~mask; +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return (png_ptr->io_ptr); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_STDIO_SUPPORTED +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a + * function of your own because "FILE *" isn't necessarily available. + */ +void PNGAPI +png_init_io(png_structrp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io"); + + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = (png_voidp)fp; +} +# endif + +#ifdef PNG_SAVE_INT_32_SUPPORTED +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. Note that, + * the following works correctly even if png_int_32 has more than 32 bits + * (compare the more complex code required on read for sign extension.) + */ +void PNGAPI +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} +#endif + +# ifdef PNG_TIME_RFC1123_SUPPORTED +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +int PNGAPI +png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if (out == NULL) + return 0; + + if (ptime->year > 9999 /* RFC1123 limitation */ || + ptime->month == 0 || ptime->month > 12 || + ptime->day == 0 || ptime->day > 31 || + ptime->hour > 23 || ptime->minute > 59 || + ptime->second > 60) + return 0; + + { + size_t pos = 0; + char number_buf[5]; /* enough for a four-digit year */ + +# define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string)) +# define APPEND_NUMBER(format, value)\ + APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value))) +# define APPEND(ch) if (pos < 28) out[pos++] = (ch) + + APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day); + APPEND(' '); + APPEND_STRING(short_months[(ptime->month - 1)]); + APPEND(' '); + APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year); + APPEND(' '); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour); + APPEND(':'); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute); + APPEND(':'); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second); + APPEND_STRING(" +0000"); /* This reliably terminates the buffer */ + +# undef APPEND +# undef APPEND_NUMBER +# undef APPEND_STRING + } + + return 1; +} + +# if PNG_LIBPNG_VER < 10700 +/* To do: remove the following from libpng-1.7 */ +/* Original API that uses a private buffer in png_struct. + * Deprecated because it causes png_struct to carry a spurious temporary + * buffer (png_struct::time_buffer), better to have the caller pass this in. + */ +png_const_charp PNGAPI +png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime) +{ + if (png_ptr != NULL) + { + /* The only failure above if png_ptr != NULL is from an invalid ptime */ + if (!png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime)) + png_warning(png_ptr, "Ignoring invalid time value"); + + else + return png_ptr->time_buffer; + } + + return NULL; +} +# endif +# endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +png_const_charp PNGAPI +png_get_copyright(png_const_structrp png_ptr) +{ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef PNG_STRING_COPYRIGHT + return PNG_STRING_COPYRIGHT +#else +# ifdef __STDC__ + return PNG_STRING_NEWLINE \ + "libpng version 1.6.7 - November 14, 2013" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2013 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ + "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ + "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ + PNG_STRING_NEWLINE; +# else + return "libpng version 1.6.7 - November 14, 2013\ + Copyright (c) 1998-2013 Glenn Randers-Pehrson\ + Copyright (c) 1996-1997 Andreas Dilger\ + Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; +# endif +#endif +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files + * used with your application, print out PNG_LIBPNG_VER_STRING, which + * is defined in png.h. + * Note: now there is no difference between png_get_libpng_ver() and + * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, + * it is guaranteed that png.c uses the correct version of png.h. + */ +png_const_charp PNGAPI +png_get_libpng_ver(png_const_structrp png_ptr) +{ + /* Version of *.c files used when building libpng */ + return png_get_header_ver(png_ptr); +} + +png_const_charp PNGAPI +png_get_header_ver(png_const_structrp png_ptr) +{ + /* Version of *.h files used when building libpng */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ + return PNG_LIBPNG_VER_STRING; +} + +png_const_charp PNGAPI +png_get_header_version(png_const_structrp png_ptr) +{ + /* Returns longer string containing both version and date */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef __STDC__ + return PNG_HEADER_VERSION_STRING +# ifndef PNG_READ_SUPPORTED + " (NO READ SUPPORT)" +# endif + PNG_STRING_NEWLINE; +#else + return PNG_HEADER_VERSION_STRING; +#endif +} + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name) +{ + /* Check chunk_name and return "keep" value if it's on the list, else 0 */ + png_const_bytep p, p_end; + + if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0) + return PNG_HANDLE_CHUNK_AS_DEFAULT; + + p_end = png_ptr->chunk_list; + p = p_end + png_ptr->num_chunk_list*5; /* beyond end */ + + /* The code is the fifth byte after each four byte string. Historically this + * code was always searched from the end of the list, this is no longer + * necessary because the 'set' routine handles duplicate entries correcty. + */ + do /* num_chunk_list > 0, so at least one */ + { + p -= 5; + + if (!memcmp(chunk_name, p, 4)) + return p[4]; + } + while (p > p_end); + + /* This means that known chunks should be processed and unknown chunks should + * be handled according to the value of png_ptr->unknown_default; this can be + * confusing because, as a result, there are two levels of defaulting for + * unknown chunks. + */ + return PNG_HANDLE_CHUNK_AS_DEFAULT; +} + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) +int /* PRIVATE */ +png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name) +{ + png_byte chunk_string[5]; + + PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name); + return png_handle_as_unknown(png_ptr, chunk_string); +} +#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */ +#endif /* SET_UNKNOWN_CHUNKS */ + +#ifdef PNG_READ_SUPPORTED +/* This function, added to libpng-1.0.6g, is untested. */ +int PNGAPI +png_reset_zstream(png_structrp png_ptr) +{ + if (png_ptr == NULL) + return Z_STREAM_ERROR; + + /* WARNING: this resets the window bits to the maximum! */ + return (inflateReset(&png_ptr->zstream)); +} +#endif /* PNG_READ_SUPPORTED */ + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32)PNG_LIBPNG_VER); +} + + + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Ensure that png_ptr->zstream.msg holds some appropriate error message string. + * If it doesn't 'ret' is used to set it to something appropriate, even in cases + * like Z_OK or Z_STREAM_END where the error code is apparently a success code. + */ +void /* PRIVATE */ +png_zstream_error(png_structrp png_ptr, int ret) +{ + /* Translate 'ret' into an appropriate error string, priority is given to the + * one in zstream if set. This always returns a string, even in cases like + * Z_OK or Z_STREAM_END where the error code is a success code. + */ + if (png_ptr->zstream.msg == NULL) switch (ret) + { + default: + case Z_OK: + png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code"); + break; + + case Z_STREAM_END: + /* Normal exit */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream"); + break; + + case Z_NEED_DICT: + /* This means the deflate stream did not have a dictionary; this + * indicates a bogus PNG. + */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary"); + break; + + case Z_ERRNO: + /* gz APIs only: should not happen */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error"); + break; + + case Z_STREAM_ERROR: + /* internal libpng error */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib"); + break; + + case Z_DATA_ERROR: + png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream"); + break; + + case Z_MEM_ERROR: + png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory"); + break; + + case Z_BUF_ERROR: + /* End of input or output; not a problem if the caller is doing + * incremental read or write. + */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated"); + break; + + case Z_VERSION_ERROR: + png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version"); + break; + + case PNG_UNEXPECTED_ZLIB_RETURN: + /* Compile errors here mean that zlib now uses the value co-opted in + * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above + * and change pngpriv.h. Note that this message is "... return", + * whereas the default/Z_OK one is "... return code". + */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return"); + break; + } +} + +/* png_convert_size: a PNGAPI but no longer in png.h, so deleted + * at libpng 1.5.5! + */ + +/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ +#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */ +static int +png_colorspace_check_gamma(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_fixed_point gAMA, int from) + /* This is called to check a new gamma value against an existing one. The + * routine returns false if the new gamma value should not be written. + * + * 'from' says where the new gamma value comes from: + * + * 0: the new gamma value is the libpng estimate for an ICC profile + * 1: the new gamma value comes from a gAMA chunk + * 2: the new gamma value comes from an sRGB chunk + */ +{ + png_fixed_point gtest; + + if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && + (!png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) || + png_gamma_significant(gtest))) + { + /* Either this is an sRGB image, in which case the calculated gamma + * approximation should match, or this is an image with a profile and the + * value libpng calculates for the gamma of the profile does not match the + * value recorded in the file. The former, sRGB, case is an error, the + * latter is just a warning. + */ + if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2) + { + png_chunk_report(png_ptr, "gamma value does not match sRGB", + PNG_CHUNK_ERROR); + /* Do not overwrite an sRGB value */ + return from == 2; + } + + else /* sRGB tag not involved */ + { + png_chunk_report(png_ptr, "gamma value does not match libpng estimate", + PNG_CHUNK_WARNING); + return from == 1; + } + } + + return 1; +} + +void /* PRIVATE */ +png_colorspace_set_gamma(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_fixed_point gAMA) +{ + /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't + * occur. Since the fixed point representation is assymetrical it is + * possible for 1/gamma to overflow the limit of 21474 and this means the + * gamma value must be at least 5/100000 and hence at most 20000.0. For + * safety the limits here are a little narrower. The values are 0.00016 to + * 6250.0, which are truly ridiculous gamma values (and will produce + * displays that are all black or all white.) + * + * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk + * handling code, which only required the value to be >0. + */ + png_const_charp errmsg; + + if (gAMA < 16 || gAMA > 625000000) + errmsg = "gamma value out of range"; + +# ifdef PNG_READ_gAMA_SUPPORTED + /* Allow the application to set the gamma value more than once */ + else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0) + errmsg = "duplicate"; +# endif + + /* Do nothing if the colorspace is already invalid */ + else if (colorspace->flags & PNG_COLORSPACE_INVALID) + return; + + else + { + if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA, 1/*from gAMA*/)) + { + /* Store this gamma value. */ + colorspace->gamma = gAMA; + colorspace->flags |= + (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA); + } + + /* At present if the check_gamma test fails the gamma of the colorspace is + * not updated however the colorspace is not invalidated. This + * corresponds to the case where the existing gamma comes from an sRGB + * chunk or profile. An error message has already been output. + */ + return; + } + + /* Error exit - errmsg has been set. */ + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR); +} + +void /* PRIVATE */ +png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr) +{ + if (info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) + { + /* Everything is invalid */ + info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB| + PNG_INFO_iCCP); + +# ifdef PNG_COLORSPACE_SUPPORTED + /* Clean up the iCCP profile now if it won't be used. */ + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/); +# else + PNG_UNUSED(png_ptr) +# endif + } + + else + { +# ifdef PNG_COLORSPACE_SUPPORTED + /* Leave the INFO_iCCP flag set if the pngset.c code has already set + * it; this allows a PNG to contain a profile which matches sRGB and + * yet still have that profile retrievable by the application. + */ + if (info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) + info_ptr->valid |= PNG_INFO_sRGB; + + else + info_ptr->valid &= ~PNG_INFO_sRGB; + + if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) + info_ptr->valid |= PNG_INFO_cHRM; + + else + info_ptr->valid &= ~PNG_INFO_cHRM; +# endif + + if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) + info_ptr->valid |= PNG_INFO_gAMA; + + else + info_ptr->valid &= ~PNG_INFO_gAMA; + } +} + +#ifdef PNG_READ_SUPPORTED +void /* PRIVATE */ +png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr) +{ + if (info_ptr == NULL) /* reduce code size; check here not in the caller */ + return; + + info_ptr->colorspace = png_ptr->colorspace; + png_colorspace_sync_info(png_ptr, info_ptr); +} +#endif +#endif + +#ifdef PNG_COLORSPACE_SUPPORTED +/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for + * cHRM, as opposed to using chromaticities. These internal APIs return + * non-zero on a parameter error. The X, Y and Z values are required to be + * positive and less than 1.0. + */ +static int +png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ) +{ + png_int_32 d, dwhite, whiteX, whiteY; + + d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z; + if (!png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d)) return 1; + if (!png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d)) return 1; + dwhite = d; + whiteX = XYZ->red_X; + whiteY = XYZ->red_Y; + + d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z; + if (!png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d)) return 1; + if (!png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d)) return 1; + dwhite += d; + whiteX += XYZ->green_X; + whiteY += XYZ->green_Y; + + d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z; + if (!png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d)) return 1; + if (!png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d)) return 1; + dwhite += d; + whiteX += XYZ->blue_X; + whiteY += XYZ->blue_Y; + + /* The reference white is simply the sum of the end-point (X,Y,Z) vectors, + * thus: + */ + if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1; + if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1; + + return 0; +} + +static int +png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) +{ + png_fixed_point red_inverse, green_inverse, blue_scale; + png_fixed_point left, right, denominator; + + /* Check xy and, implicitly, z. Note that wide gamut color spaces typically + * have end points with 0 tristimulus values (these are impossible end + * points, but they are used to cover the possible colors.) + */ + if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1; + if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1; + if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1; + if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1; + if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1; + if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1; + if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1; + if (xy->whitey < 0 || xy->whitey > PNG_FP_1-xy->whitex) return 1; + + /* The reverse calculation is more difficult because the original tristimulus + * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 + * derived values were recorded in the cHRM chunk; + * (red,green,blue,white)x(x,y). This loses one degree of freedom and + * therefore an arbitrary ninth value has to be introduced to undo the + * original transformations. + * + * Think of the original end-points as points in (X,Y,Z) space. The + * chromaticity values (c) have the property: + * + * C + * c = --------- + * X + Y + Z + * + * For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the + * three chromaticity values (x,y,z) for each end-point obey the + * relationship: + * + * x + y + z = 1 + * + * This describes the plane in (X,Y,Z) space that intersects each axis at the + * value 1.0; call this the chromaticity plane. Thus the chromaticity + * calculation has scaled each end-point so that it is on the x+y+z=1 plane + * and chromaticity is the intersection of the vector from the origin to the + * (X,Y,Z) value with the chromaticity plane. + * + * To fully invert the chromaticity calculation we would need the three + * end-point scale factors, (red-scale, green-scale, blue-scale), but these + * were not recorded. Instead we calculated the reference white (X,Y,Z) and + * recorded the chromaticity of this. The reference white (X,Y,Z) would have + * given all three of the scale factors since: + * + * color-C = color-c * color-scale + * white-C = red-C + green-C + blue-C + * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale + * + * But cHRM records only white-x and white-y, so we have lost the white scale + * factor: + * + * white-C = white-c*white-scale + * + * To handle this the inverse transformation makes an arbitrary assumption + * about white-scale: + * + * Assume: white-Y = 1.0 + * Hence: white-scale = 1/white-y + * Or: red-Y + green-Y + blue-Y = 1.0 + * + * Notice the last statement of the assumption gives an equation in three of + * the nine values we want to calculate. 8 more equations come from the + * above routine as summarised at the top above (the chromaticity + * calculation): + * + * Given: color-x = color-X / (color-X + color-Y + color-Z) + * Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0 + * + * This is 9 simultaneous equations in the 9 variables "color-C" and can be + * solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix + * determinants, however this is not as bad as it seems because only 28 of + * the total of 90 terms in the various matrices are non-zero. Nevertheless + * Cramer's rule is notoriously numerically unstable because the determinant + * calculation involves the difference of large, but similar, numbers. It is + * difficult to be sure that the calculation is stable for real world values + * and it is certain that it becomes unstable where the end points are close + * together. + * + * So this code uses the perhaps slightly less optimal but more + * understandable and totally obvious approach of calculating color-scale. + * + * This algorithm depends on the precision in white-scale and that is + * (1/white-y), so we can immediately see that as white-y approaches 0 the + * accuracy inherent in the cHRM chunk drops off substantially. + * + * libpng arithmetic: a simple invertion of the above equations + * ------------------------------------------------------------ + * + * white_scale = 1/white-y + * white-X = white-x * white-scale + * white-Y = 1.0 + * white-Z = (1 - white-x - white-y) * white_scale + * + * white-C = red-C + green-C + blue-C + * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale + * + * This gives us three equations in (red-scale,green-scale,blue-scale) where + * all the coefficients are now known: + * + * red-x*red-scale + green-x*green-scale + blue-x*blue-scale + * = white-x/white-y + * red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1 + * red-z*red-scale + green-z*green-scale + blue-z*blue-scale + * = (1 - white-x - white-y)/white-y + * + * In the last equation color-z is (1 - color-x - color-y) so we can add all + * three equations together to get an alternative third: + * + * red-scale + green-scale + blue-scale = 1/white-y = white-scale + * + * So now we have a Cramer's rule solution where the determinants are just + * 3x3 - far more tractible. Unfortunately 3x3 determinants still involve + * multiplication of three coefficients so we can't guarantee to avoid + * overflow in the libpng fixed point representation. Using Cramer's rule in + * floating point is probably a good choice here, but it's not an option for + * fixed point. Instead proceed to simplify the first two equations by + * eliminating what is likely to be the largest value, blue-scale: + * + * blue-scale = white-scale - red-scale - green-scale + * + * Hence: + * + * (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale = + * (white-x - blue-x)*white-scale + * + * (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale = + * 1 - blue-y*white-scale + * + * And now we can trivially solve for (red-scale,green-scale): + * + * green-scale = + * (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale + * ----------------------------------------------------------- + * green-x - blue-x + * + * red-scale = + * 1 - blue-y*white-scale - (green-y - blue-y) * green-scale + * --------------------------------------------------------- + * red-y - blue-y + * + * Hence: + * + * red-scale = + * ( (green-x - blue-x) * (white-y - blue-y) - + * (green-y - blue-y) * (white-x - blue-x) ) / white-y + * ------------------------------------------------------------------------- + * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) + * + * green-scale = + * ( (red-y - blue-y) * (white-x - blue-x) - + * (red-x - blue-x) * (white-y - blue-y) ) / white-y + * ------------------------------------------------------------------------- + * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) + * + * Accuracy: + * The input values have 5 decimal digits of accuracy. The values are all in + * the range 0 < value < 1, so simple products are in the same range but may + * need up to 10 decimal digits to preserve the original precision and avoid + * underflow. Because we are using a 32-bit signed representation we cannot + * match this; the best is a little over 9 decimal digits, less than 10. + * + * The approach used here is to preserve the maximum precision within the + * signed representation. Because the red-scale calculation above uses the + * difference between two products of values that must be in the range -1..+1 + * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The + * factor is irrelevant in the calculation because it is applied to both + * numerator and denominator. + * + * Note that the values of the differences of the products of the + * chromaticities in the above equations tend to be small, for example for + * the sRGB chromaticities they are: + * + * red numerator: -0.04751 + * green numerator: -0.08788 + * denominator: -0.2241 (without white-y multiplication) + * + * The resultant Y coefficients from the chromaticities of some widely used + * color space definitions are (to 15 decimal places): + * + * sRGB + * 0.212639005871510 0.715168678767756 0.072192315360734 + * Kodak ProPhoto + * 0.288071128229293 0.711843217810102 0.000085653960605 + * Adobe RGB + * 0.297344975250536 0.627363566255466 0.075291458493998 + * Adobe Wide Gamut RGB + * 0.258728243040113 0.724682314948566 0.016589442011321 + */ + /* By the argument, above overflow should be impossible here. The return + * value of 2 indicates an internal error to the caller. + */ + if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7)) + return 2; + if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7)) + return 2; + denominator = left - right; + + /* Now find the red numerator. */ + if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7)) + return 2; + if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7)) + return 2; + + /* Overflow is possible here and it indicates an extreme set of PNG cHRM + * chunk values. This calculation actually returns the reciprocal of the + * scale value because this allows us to delay the multiplication of white-y + * into the denominator, which tends to produce a small number. + */ + if (!png_muldiv(&red_inverse, xy->whitey, denominator, left-right) || + red_inverse <= xy->whitey /* r+g+b scales = white scale */) + return 1; + + /* Similarly for green_inverse: */ + if (!png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7)) + return 2; + if (!png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7)) + return 2; + if (!png_muldiv(&green_inverse, xy->whitey, denominator, left-right) || + green_inverse <= xy->whitey) + return 1; + + /* And the blue scale, the checks above guarantee this can't overflow but it + * can still produce 0 for extreme cHRM values. + */ + blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) - + png_reciprocal(green_inverse); + if (blue_scale <= 0) return 1; + + + /* And fill in the png_XYZ: */ + if (!png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse)) return 1; + if (!png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse)) return 1; + if (!png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1, + red_inverse)) + return 1; + + if (!png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse)) + return 1; + if (!png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse)) + return 1; + if (!png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1, + green_inverse)) + return 1; + + if (!png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1)) return 1; + if (!png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1)) return 1; + if (!png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale, + PNG_FP_1)) + return 1; + + return 0; /*success*/ +} + +static int +png_XYZ_normalize(png_XYZ *XYZ) +{ + png_int_32 Y; + + if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 || + XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 || + XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0) + return 1; + + /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. + * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore + * relying on addition of two positive values producing a negative one is not + * safe. + */ + Y = XYZ->red_Y; + if (0x7fffffff - Y < XYZ->green_X) return 1; + Y += XYZ->green_Y; + if (0x7fffffff - Y < XYZ->blue_X) return 1; + Y += XYZ->blue_Y; + + if (Y != PNG_FP_1) + { + if (!png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y)) return 1; + + if (!png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y)) return 1; + + if (!png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y)) return 1; + } + + return 0; +} + +static int +png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta) +{ + /* Allow an error of +/-0.01 (absolute value) on each chromaticity */ + return !(PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) || + PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) || + PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) || + PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) || + PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) || + PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) || + PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) || + PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta)); +} + +/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM + * chunk chromaticities. Earlier checks used to simply look for the overflow + * condition (where the determinant of the matrix to solve for XYZ ends up zero + * because the chromaticity values are not all distinct.) Despite this it is + * theoretically possible to produce chromaticities that are apparently valid + * but that rapidly degrade to invalid, potentially crashing, sets because of + * arithmetic inaccuracies when calculations are performed on them. The new + * check is to round-trip xy -> XYZ -> xy and then check that the result is + * within a small percentage of the original. + */ +static int +png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy) +{ + int result; + png_xy xy_test; + + /* As a side-effect this routine also returns the XYZ endpoints. */ + result = png_XYZ_from_xy(XYZ, xy); + if (result) return result; + + result = png_xy_from_XYZ(&xy_test, XYZ); + if (result) return result; + + if (png_colorspace_endpoints_match(xy, &xy_test, + 5/*actually, the math is pretty accurate*/)) + return 0; + + /* Too much slip */ + return 1; +} + +/* This is the check going the other way. The XYZ is modified to normalize it + * (another side-effect) and the xy chromaticities are returned. + */ +static int +png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ) +{ + int result; + png_XYZ XYZtemp; + + result = png_XYZ_normalize(XYZ); + if (result) return result; + + result = png_xy_from_XYZ(xy, XYZ); + if (result) return result; + + XYZtemp = *XYZ; + return png_colorspace_check_xy(&XYZtemp, xy); +} + +/* Used to check for an endpoint match against sRGB */ +static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */ +{ + /* color x y */ + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000, + /* white */ 31270, 32900 +}; + +static int +png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr, + png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ, + int preferred) +{ + if (colorspace->flags & PNG_COLORSPACE_INVALID) + return 0; + + /* The consistency check is performed on the chromaticities; this factors out + * variations because of the normalization (or not) of the end point Y + * values. + */ + if (preferred < 2 && (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) + { + /* The end points must be reasonably close to any we already have. The + * following allows an error of up to +/-.001 + */ + if (!png_colorspace_endpoints_match(xy, &colorspace->end_points_xy, 100)) + { + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_benign_error(png_ptr, "inconsistent chromaticities"); + return 0; /* failed */ + } + + /* Only overwrite with preferred values */ + if (!preferred) + return 1; /* ok, but no change */ + } + + colorspace->end_points_xy = *xy; + colorspace->end_points_XYZ = *XYZ; + colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS; + + /* The end points are normally quoted to two decimal digits, so allow +/-0.01 + * on this test. + */ + if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000)) + colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB; + + else + colorspace->flags &= PNG_COLORSPACE_CANCEL( + PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); + + return 2; /* ok and changed */ +} + +int /* PRIVATE */ +png_colorspace_set_chromaticities(png_const_structrp png_ptr, + png_colorspacerp colorspace, const png_xy *xy, int preferred) +{ + /* We must check the end points to ensure they are reasonable - in the past + * color management systems have crashed as a result of getting bogus + * colorant values, while this isn't the fault of libpng it is the + * responsibility of libpng because PNG carries the bomb and libpng is in a + * position to protect against it. + */ + png_XYZ XYZ; + + switch (png_colorspace_check_xy(&XYZ, xy)) + { + case 0: /* success */ + return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ, + preferred); + + case 1: + /* We can't invert the chromaticities so we can't produce value XYZ + * values. Likely as not a color management system will fail too. + */ + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_benign_error(png_ptr, "invalid chromaticities"); + break; + + default: + /* libpng is broken; this should be a warning but if it happens we + * want error reports so for the moment it is an error. + */ + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_error(png_ptr, "internal error checking chromaticities"); + break; + } + + return 0; /* failed */ +} + +int /* PRIVATE */ +png_colorspace_set_endpoints(png_const_structrp png_ptr, + png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred) +{ + png_XYZ XYZ = *XYZ_in; + png_xy xy; + + switch (png_colorspace_check_XYZ(&xy, &XYZ)) + { + case 0: + return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ, + preferred); + + case 1: + /* End points are invalid. */ + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_benign_error(png_ptr, "invalid end points"); + break; + + default: + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_error(png_ptr, "internal error checking chromaticities"); + break; + } + + return 0; /* failed */ +} + +#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED) +/* Error message generation */ +static char +png_icc_tag_char(png_uint_32 byte) +{ + byte &= 0xff; + if (byte >= 32 && byte <= 126) + return (char)byte; + else + return '?'; +} + +static void +png_icc_tag_name(char *name, png_uint_32 tag) +{ + name[0] = '\''; + name[1] = png_icc_tag_char(tag >> 24); + name[2] = png_icc_tag_char(tag >> 16); + name[3] = png_icc_tag_char(tag >> 8); + name[4] = png_icc_tag_char(tag ); + name[5] = '\''; +} + +static int +is_ICC_signature_char(png_alloc_size_t it) +{ + return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) || + (it >= 97 && it <= 122); +} + +static int is_ICC_signature(png_alloc_size_t it) +{ + return is_ICC_signature_char(it >> 24) /* checks all the top bits */ && + is_ICC_signature_char((it >> 16) & 0xff) && + is_ICC_signature_char((it >> 8) & 0xff) && + is_ICC_signature_char(it & 0xff); +} + +static int +png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_alloc_size_t value, png_const_charp reason) +{ + size_t pos; + char message[196]; /* see below for calculation */ + + if (colorspace != NULL) + colorspace->flags |= PNG_COLORSPACE_INVALID; + + pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */ + pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */ + pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */ + if (is_ICC_signature(value)) + { + /* So 'value' is at most 4 bytes and the following cast is safe */ + png_icc_tag_name(message+pos, (png_uint_32)value); + pos += 6; /* total +8; less than the else clause */ + message[pos++] = ':'; + message[pos++] = ' '; + } +# ifdef PNG_WARNINGS_SUPPORTED + else + { + char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/ + + pos = png_safecat(message, (sizeof message), pos, + png_format_number(number, number+(sizeof number), + PNG_NUMBER_FORMAT_x, value)); + pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/ + } +# endif + /* The 'reason' is an arbitrary message, allow +79 maximum 195 */ + pos = png_safecat(message, (sizeof message), pos, reason); + + /* This is recoverable, but make it unconditionally an app_error on write to + * avoid writing invalid ICC profiles into PNG files. (I.e. we handle them + * on read, with a warning, but on write unless the app turns off + * application errors the PNG won't be written.) + */ + png_chunk_report(png_ptr, message, + (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR); + + return 0; +} +#endif /* sRGB || iCCP */ + +#ifdef PNG_sRGB_SUPPORTED +int /* PRIVATE */ +png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, + int intent) +{ + /* sRGB sets known gamma, end points and (from the chunk) intent. */ + /* IMPORTANT: these are not necessarily the values found in an ICC profile + * because ICC profiles store values adapted to a D50 environment; it is + * expected that the ICC profile mediaWhitePointTag will be D50, see the + * checks and code elsewhere to understand this better. + * + * These XYZ values, which are accurate to 5dp, produce rgb to gray + * coefficients of (6968,23435,2366), which are reduced (because they add up + * to 32769 not 32768) to (6968,23434,2366). These are the values that + * libpng has traditionally used (and are the best values given the 15bit + * algorithm used by the rgb to gray code.) + */ + static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */ + { + /* color X Y Z */ + /* red */ 41239, 21264, 1933, + /* green */ 35758, 71517, 11919, + /* blue */ 18048, 7219, 95053 + }; + + /* Do nothing if the colorspace is already invalidated. */ + if (colorspace->flags & PNG_COLORSPACE_INVALID) + return 0; + + /* Check the intent, then check for existing settings. It is valid for the + * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must + * be consistent with the correct values. If, however, this function is + * called below because an iCCP chunk matches sRGB then it is quite + * conceivable that an older app recorded incorrect gAMA and cHRM because of + * an incorrect calculation based on the values in the profile - this does + * *not* invalidate the profile (though it still produces an error, which can + * be ignored.) + */ + if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) + return png_icc_profile_error(png_ptr, colorspace, "sRGB", + (unsigned)intent, "invalid sRGB rendering intent"); + + if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && + colorspace->rendering_intent != intent) + return png_icc_profile_error(png_ptr, colorspace, "sRGB", + (unsigned)intent, "inconsistent rendering intents"); + + if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) + { + png_benign_error(png_ptr, "duplicate sRGB information ignored"); + return 0; + } + + /* If the standard sRGB cHRM chunk does not match the one from the PNG file + * warn but overwrite the value with the correct one. + */ + if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 && + !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy, + 100)) + png_chunk_report(png_ptr, "cHRM chunk does not match sRGB", + PNG_CHUNK_ERROR); + + /* This check is just done for the error reporting - the routine always + * returns true when the 'from' argument corresponds to sRGB (2). + */ + (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE, + 2/*from sRGB*/); + + /* intent: bugs in GCC force 'int' to be used as the parameter type. */ + colorspace->rendering_intent = (png_uint_16)intent; + colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT; + + /* endpoints */ + colorspace->end_points_xy = sRGB_xy; + colorspace->end_points_XYZ = sRGB_XYZ; + colorspace->flags |= + (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); + + /* gamma */ + colorspace->gamma = PNG_GAMMA_sRGB_INVERSE; + colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA; + + /* Finally record that we have an sRGB profile */ + colorspace->flags |= + (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB); + + return 1; /* set */ +} +#endif /* sRGB */ + +#ifdef PNG_iCCP_SUPPORTED +/* Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value + * is XYZ(0.9642,1.0,0.8249), which scales to: + * + * (63189.8112, 65536, 54060.6464) + */ +static const png_byte D50_nCIEXYZ[12] = + { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; + +int /* PRIVATE */ +png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length) +{ + if (profile_length < 132) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "too short"); + + if (profile_length & 3) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "invalid length"); + + return 1; +} + +int /* PRIVATE */ +png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length, + png_const_bytep profile/* first 132 bytes only */, int color_type) +{ + png_uint_32 temp; + + /* Length check; this cannot be ignored in this code because profile_length + * is used later to check the tag table, so even if the profile seems over + * long profile_length from the caller must be correct. The caller can fix + * this up on read or write by just passing in the profile header length. + */ + temp = png_get_uint_32(profile); + if (temp != profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "length does not match profile"); + + temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */ + if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */ + profile_length < 132+12*temp) /* truncated tag table */ + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "tag count too large"); + + /* The 'intent' must be valid or we can't store it, ICC limits the intent to + * 16 bits. + */ + temp = png_get_uint_32(profile+64); + if (temp >= 0xffff) /* The ICC limit */ + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "invalid rendering intent"); + + /* This is just a warning because the profile may be valid in future + * versions. + */ + if (temp >= PNG_sRGB_INTENT_LAST) + (void)png_icc_profile_error(png_ptr, NULL, name, temp, + "intent outside defined range"); + + /* At this point the tag table can't be checked because it hasn't necessarily + * been loaded; however, various header fields can be checked. These checks + * are for values permitted by the PNG spec in an ICC profile; the PNG spec + * restricts the profiles that can be passed in an iCCP chunk (they must be + * appropriate to processing PNG data!) + */ + + /* Data checks (could be skipped). These checks must be independent of the + * version number; however, the version number doesn't accomodate changes in + * the header fields (just the known tags and the interpretation of the + * data.) + */ + temp = png_get_uint_32(profile+36); /* signature 'ascp' */ + if (temp != 0x61637370) + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "invalid signature"); + + /* Currently the PCS illuminant/adopted white point (the computational + * white point) are required to be D50, + * however the profile contains a record of the illuminant so perhaps ICC + * expects to be able to change this in the future (despite the rationale in + * the introduction for using a fixed PCS adopted white.) Consequently the + * following is just a warning. + */ + if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0) + (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/, + "PCS illuminant is not D50"); + + /* The PNG spec requires this: + * "If the iCCP chunk is present, the image samples conform to the colour + * space represented by the embedded ICC profile as defined by the + * International Color Consortium [ICC]. The colour space of the ICC profile + * shall be an RGB colour space for colour images (PNG colour types 2, 3, and + * 6), or a greyscale colour space for greyscale images (PNG colour types 0 + * and 4)." + * + * This checking code ensures the embedded profile (on either read or write) + * conforms to the specification requirements. Notice that an ICC 'gray' + * color-space profile contains the information to transform the monochrome + * data to XYZ or L*a*b (according to which PCS the profile uses) and this + * should be used in preference to the standard libpng K channel replication + * into R, G and B channels. + * + * Previously it was suggested that an RGB profile on grayscale data could be + * handled. However it it is clear that using an RGB profile in this context + * must be an error - there is no specification of what it means. Thus it is + * almost certainly more correct to ignore the profile. + */ + temp = png_get_uint_32(profile+16); /* data colour space field */ + switch (temp) + { + case 0x52474220: /* 'RGB ' */ + if (!(color_type & PNG_COLOR_MASK_COLOR)) + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "RGB color space not permitted on grayscale PNG"); + break; + + case 0x47524159: /* 'GRAY' */ + if (color_type & PNG_COLOR_MASK_COLOR) + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "Gray color space not permitted on RGB PNG"); + break; + + default: + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "invalid ICC profile color space"); + } + + /* It is up to the application to check that the profile class matches the + * application requirements; the spec provides no guidance, but it's pretty + * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer + * ('prtr') or 'spac' (for generic color spaces). Issue a warning in these + * cases. Issue an error for device link or abstract profiles - these don't + * contain the records necessary to transform the color-space to anything + * other than the target device (and not even that for an abstract profile). + * Profiles of these classes may not be embedded in images. + */ + temp = png_get_uint_32(profile+12); /* profile/device class */ + switch (temp) + { + case 0x73636E72: /* 'scnr' */ + case 0x6D6E7472: /* 'mntr' */ + case 0x70727472: /* 'prtr' */ + case 0x73706163: /* 'spac' */ + /* All supported */ + break; + + case 0x61627374: /* 'abst' */ + /* May not be embedded in an image */ + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "invalid embedded Abstract ICC profile"); + + case 0x6C696E6B: /* 'link' */ + /* DeviceLink profiles cannnot be interpreted in a non-device specific + * fashion, if an app uses the AToB0Tag in the profile the results are + * undefined unless the result is sent to the intended device, + * therefore a DeviceLink profile should not be found embedded in a + * PNG. + */ + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "unexpected DeviceLink ICC profile class"); + + case 0x6E6D636C: /* 'nmcl' */ + /* A NamedColor profile is also device specific, however it doesn't + * contain an AToB0 tag that is open to misintrepretation. Almost + * certainly it will fail the tests below. + */ + (void)png_icc_profile_error(png_ptr, NULL, name, temp, + "unexpected NamedColor ICC profile class"); + break; + + default: + /* To allow for future enhancements to the profile accept unrecognized + * profile classes with a warning, these then hit the test below on the + * tag content to ensure they are backward compatible with one of the + * understood profiles. + */ + (void)png_icc_profile_error(png_ptr, NULL, name, temp, + "unrecognized ICC profile class"); + break; + } + + /* For any profile other than a device link one the PCS must be encoded + * either in XYZ or Lab. + */ + temp = png_get_uint_32(profile+20); + switch (temp) + { + case 0x58595A20: /* 'XYZ ' */ + case 0x4C616220: /* 'Lab ' */ + break; + + default: + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "unexpected ICC PCS encoding"); + } + + return 1; +} + +int /* PRIVATE */ +png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length, + png_const_bytep profile /* header plus whole tag table */) +{ + png_uint_32 tag_count = png_get_uint_32(profile+128); + png_uint_32 itag; + png_const_bytep tag = profile+132; /* The first tag */ + + /* First scan all the tags in the table and add bits to the icc_info value + * (temporarily in 'tags'). + */ + for (itag=0; itag < tag_count; ++itag, tag += 12) + { + png_uint_32 tag_id = png_get_uint_32(tag+0); + png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */ + png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */ + + /* The ICC specification does not exclude zero length tags, therefore the + * start might actually be anywhere if there is no data, but this would be + * a clear abuse of the intent of the standard so the start is checked for + * being in range. All defined tag types have an 8 byte header - a 4 byte + * type signature then 0. + */ + if ((tag_start & 3) != 0) + { + /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is + * only a warning here because libpng does not care about the + * alignment. + */ + (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, + "ICC profile tag start not a multiple of 4"); + } + + /* This is a hard error; potentially it can cause read outside the + * profile. + */ + if (tag_start > profile_length || tag_length > profile_length - tag_start) + return png_icc_profile_error(png_ptr, colorspace, name, tag_id, + "ICC profile tag outside profile"); + } + + return 1; /* success, maybe with warnings */ +} + +#ifdef PNG_sRGB_SUPPORTED +/* Information about the known ICC sRGB profiles */ +static const struct +{ + png_uint_32 adler, crc, length; + png_uint_32 md5[4]; + png_byte have_md5; + png_byte is_broken; + png_uint_16 intent; + +# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0) +# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\ + { adler, crc, length, md5, broke, intent }, + +} png_sRGB_checks[] = +{ + /* This data comes from contrib/tools/checksum-icc run on downloads of + * all four ICC sRGB profiles from www.color.org. + */ + /* adler32, crc32, MD5[4], intent, date, length, file-name */ + PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9, + PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0, + "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") + + /* ICC sRGB v2 perceptual no black-compensation: */ + PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21, + PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0, + "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") + + PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae, + PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0, + "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") + + /* ICC sRGB v4 perceptual */ + PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812, + PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0, + "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") + + /* The following profiles have no known MD5 checksum. If there is a match + * on the (empty) MD5 the other fields are used to attempt a match and + * a warning is produced. The first two of these profiles have a 'cprt' tag + * which suggests that they were also made by Hewlett Packard. + */ + PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce, + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0, + "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") + + /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not + * match the D50 PCS illuminant in the header (it is in fact the D65 values, + * so the white point is recorded as the un-adapted value.) The profiles + * below only differ in one byte - the intent - and are basically the same as + * the previous profile except for the mediaWhitePointTag error and a missing + * chromaticAdaptationTag. + */ + PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552, + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, + "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") + + PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d, + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, + "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") +}; + +static int +png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, + png_const_bytep profile, uLong adler) +{ + /* The quick check is to verify just the MD5 signature and trust the + * rest of the data. Because the profile has already been verified for + * correctness this is safe. png_colorspace_set_sRGB will check the 'intent' + * field too, so if the profile has been edited with an intent not defined + * by sRGB (but maybe defined by a later ICC specification) the read of + * the profile will fail at that point. + */ + png_uint_32 length = 0; + png_uint_32 intent = 0x10000; /* invalid */ +#if PNG_sRGB_PROFILE_CHECKS > 1 + uLong crc = 0; /* the value for 0 length data */ +#endif + unsigned int i; + + for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i) + { + if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] && + png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] && + png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] && + png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3]) + { + /* This may be one of the old HP profiles without an MD5, in that + * case we can only use the length and Adler32 (note that these + * are not used by default if there is an MD5!) + */ +# if PNG_sRGB_PROFILE_CHECKS == 0 + if (png_sRGB_checks[i].have_md5) + return 1+png_sRGB_checks[i].is_broken; +# endif + + /* Profile is unsigned or more checks have been configured in. */ + if (length == 0) + { + length = png_get_uint_32(profile); + intent = png_get_uint_32(profile+64); + } + + /* Length *and* intent must match */ + if (length == png_sRGB_checks[i].length && + intent == png_sRGB_checks[i].intent) + { + /* Now calculate the adler32 if not done already. */ + if (adler == 0) + { + adler = adler32(0, NULL, 0); + adler = adler32(adler, profile, length); + } + + if (adler == png_sRGB_checks[i].adler) + { + /* These basic checks suggest that the data has not been + * modified, but if the check level is more than 1 perform + * our own crc32 checksum on the data. + */ +# if PNG_sRGB_PROFILE_CHECKS > 1 + if (crc == 0) + { + crc = crc32(0, NULL, 0); + crc = crc32(crc, profile, length); + } + + /* So this check must pass for the 'return' below to happen. + */ + if (crc == png_sRGB_checks[i].crc) +# endif + { + if (png_sRGB_checks[i].is_broken) + { + /* These profiles are known to have bad data that may cause + * problems if they are used, therefore attempt to + * discourage their use, skip the 'have_md5' warning below, + * which is made irrelevant by this error. + */ + png_chunk_report(png_ptr, "known incorrect sRGB profile", + PNG_CHUNK_ERROR); + } + + /* Warn that this being done; this isn't even an error since + * the profile is perfectly valid, but it would be nice if + * people used the up-to-date ones. + */ + else if (!png_sRGB_checks[i].have_md5) + { + png_chunk_report(png_ptr, + "out-of-date sRGB profile with no signature", + PNG_CHUNK_WARNING); + } + + return 1+png_sRGB_checks[i].is_broken; + } + } + } + +# if PNG_sRGB_PROFILE_CHECKS > 0 + /* The signature matched, but the profile had been changed in some + * way. This is an apparent violation of the ICC terms of use and, + * anyway, probably indicates a data error or uninformed hacking. + */ + if (png_sRGB_checks[i].have_md5) + png_benign_error(png_ptr, + "copyright violation: edited ICC profile ignored"); +# endif + } + } + + return 0; /* no match */ +} +#endif + +#ifdef PNG_sRGB_SUPPORTED +void /* PRIVATE */ +png_icc_set_sRGB(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_bytep profile, uLong adler) +{ + /* Is this profile one of the known ICC sRGB profiles? If it is, just set + * the sRGB information. + */ + if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler)) + (void)png_colorspace_set_sRGB(png_ptr, colorspace, + (int)/*already checked*/png_get_uint_32(profile+64)); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +int /* PRIVATE */ +png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length, png_const_bytep profile, + int color_type) +{ + if (colorspace->flags & PNG_COLORSPACE_INVALID) + return 0; + + if (png_icc_check_length(png_ptr, colorspace, name, profile_length) && + png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, + color_type) && + png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, + profile)) + { +# ifdef PNG_sRGB_SUPPORTED + /* If no sRGB support, don't try storing sRGB information */ + png_icc_set_sRGB(png_ptr, colorspace, profile, 0); +# endif + return 1; + } + + /* Failure case */ + return 0; +} +#endif /* iCCP */ + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +void /* PRIVATE */ +png_colorspace_set_rgb_coefficients(png_structrp png_ptr) +{ + /* Set the rgb_to_gray coefficients from the colorspace. */ + if (!png_ptr->rgb_to_gray_coefficients_set && + (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) + { + /* png_set_background has not been called, get the coefficients from the Y + * values of the colorspace colorants. + */ + png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y; + png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y; + png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y; + png_fixed_point total = r+g+b; + + if (total > 0 && + r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 && + g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 && + b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 && + r+g+b <= 32769) + { + /* We allow 0 coefficients here. r+g+b may be 32769 if two or + * all of the coefficients were rounded up. Handle this by + * reducing the *largest* coefficient by 1; this matches the + * approach used for the default coefficients in pngrtran.c + */ + int add = 0; + + if (r+g+b > 32768) + add = -1; + else if (r+g+b < 32768) + add = 1; + + if (add != 0) + { + if (g >= r && g >= b) + g += add; + else if (r >= g && r >= b) + r += add; + else + b += add; + } + + /* Check for an internal error. */ + if (r+g+b != 32768) + png_error(png_ptr, + "internal error handling cHRM coefficients"); + + else + { + png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r; + png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g; + } + } + + /* This is a png_error at present even though it could be ignored - + * it should never happen, but it is important that if it does, the + * bug is fixed. + */ + else + png_error(png_ptr, "internal error handling cHRM->XYZ"); + } +} +#endif + +#endif /* COLORSPACE */ + +void /* PRIVATE */ +png_check_IHDR(png_const_structrp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + int error = 0; + + /* Check for width and height valid values */ + if (width == 0) + { + png_warning(png_ptr, "Image width is zero in IHDR"); + error = 1; + } + + if (height == 0) + { + png_warning(png_ptr, "Image height is zero in IHDR"); + error = 1; + } + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max) + +# else + if (width > PNG_USER_WIDTH_MAX) +# endif + { + png_warning(png_ptr, "Image width exceeds user limit in IHDR"); + error = 1; + } + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (height > png_ptr->user_height_max) +# else + if (height > PNG_USER_HEIGHT_MAX) +# endif + { + png_warning(png_ptr, "Image height exceeds user limit in IHDR"); + error = 1; + } + + if (width > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image width in IHDR"); + error = 1; + } + + if (height > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image height in IHDR"); + error = 1; + } + + if (width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 48 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + png_warning(png_ptr, "Width is too large for libpng to process pixels"); + + /* Check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + { + png_warning(png_ptr, "Invalid bit depth in IHDR"); + error = 1; + } + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + { + png_warning(png_ptr, "Invalid color type in IHDR"); + error = 1; + } + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + { + png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR"); + error = 1; + } + + if (interlace_type >= PNG_INTERLACE_LAST) + { + png_warning(png_ptr, "Unknown interlace method in IHDR"); + error = 1; + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Unknown compression method in IHDR"); + error = 1; + } + +# ifdef PNG_MNG_FEATURES_SUPPORTED + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) && + png_ptr->mng_features_permitted) + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + + if (filter_type != PNG_FILTER_TYPE_BASE) + { + if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } + + if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) + { + png_warning(png_ptr, "Invalid filter method in IHDR"); + error = 1; + } + } + +# else + if (filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } +# endif + + if (error == 1) + png_error(png_ptr, "Invalid IHDR data"); +} + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* ASCII to fp functions */ +/* Check an ASCII formated floating point value, see the more detailed + * comments in pngpriv.h + */ +/* The following is used internally to preserve the sticky flags */ +#define png_fp_add(state, flags) ((state) |= (flags)) +#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) + +int /* PRIVATE */ +png_check_fp_number(png_const_charp string, png_size_t size, int *statep, + png_size_tp whereami) +{ + int state = *statep; + png_size_t i = *whereami; + + while (i < size) + { + int type; + /* First find the type of the next character */ + switch (string[i]) + { + case 43: type = PNG_FP_SAW_SIGN; break; + case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break; + case 46: type = PNG_FP_SAW_DOT; break; + case 48: type = PNG_FP_SAW_DIGIT; break; + case 49: case 50: case 51: case 52: + case 53: case 54: case 55: case 56: + case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break; + case 69: + case 101: type = PNG_FP_SAW_E; break; + default: goto PNG_FP_End; + } + + /* Now deal with this type according to the current + * state, the type is arranged to not overlap the + * bits of the PNG_FP_STATE. + */ + switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY)) + { + case PNG_FP_INTEGER + PNG_FP_SAW_SIGN: + if (state & PNG_FP_SAW_ANY) + goto PNG_FP_End; /* not a part of the number */ + + png_fp_add(state, type); + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_DOT: + /* Ok as trailer, ok as lead of fraction. */ + if (state & PNG_FP_SAW_DOT) /* two dots */ + goto PNG_FP_End; + + else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */ + png_fp_add(state, type); + + else + png_fp_set(state, PNG_FP_FRACTION | type); + + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT: + if (state & PNG_FP_SAW_DOT) /* delayed fraction */ + png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); + + png_fp_add(state, type | PNG_FP_WAS_VALID); + + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_E: + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: + goto PNG_FP_End; ** no sign in fraction */ + + /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: + goto PNG_FP_End; ** Because SAW_DOT is always set */ + + case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT: + png_fp_add(state, type | PNG_FP_WAS_VALID); + break; + + case PNG_FP_FRACTION + PNG_FP_SAW_E: + /* This is correct because the trailing '.' on an + * integer is handled above - so we can only get here + * with the sequence ".E" (with no preceding digits). + */ + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN: + if (state & PNG_FP_SAW_ANY) + goto PNG_FP_End; /* not a part of the number */ + + png_fp_add(state, PNG_FP_SAW_SIGN); + + break; + + /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: + goto PNG_FP_End; */ + + case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT: + png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID); + + break; + + /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: + goto PNG_FP_End; */ + + default: goto PNG_FP_End; /* I.e. break 2 */ + } + + /* The character seems ok, continue. */ + ++i; + } + +PNG_FP_End: + /* Here at the end, update the state and return the correct + * return code. + */ + *statep = state; + *whereami = i; + + return (state & PNG_FP_SAW_DIGIT) != 0; +} + + +/* The same but for a complete string. */ +int +png_check_fp_string(png_const_charp string, png_size_t size) +{ + int state=0; + png_size_t char_index=0; + + if (png_check_fp_number(string, size, &state, &char_index) && + (char_index == size || string[char_index] == 0)) + return state /* must be non-zero - see above */; + + return 0; /* i.e. fail */ +} +#endif /* pCAL or sCAL */ + +#ifdef PNG_sCAL_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +/* Utility used below - a simple accurate power of ten from an integral + * exponent. + */ +static double +png_pow10(int power) +{ + int recip = 0; + double d = 1; + + /* Handle negative exponent with a reciprocal at the end because + * 10 is exact whereas .1 is inexact in base 2 + */ + if (power < 0) + { + if (power < DBL_MIN_10_EXP) return 0; + recip = 1, power = -power; + } + + if (power > 0) + { + /* Decompose power bitwise. */ + double mult = 10; + do + { + if (power & 1) d *= mult; + mult *= mult; + power >>= 1; + } + while (power > 0); + + if (recip) d = 1/d; + } + /* else power is 0 and d is 1 */ + + return d; +} + +/* Function to format a floating point value in ASCII with a given + * precision. + */ +void /* PRIVATE */ +png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, + double fp, unsigned int precision) +{ + /* We use standard functions from math.h, but not printf because + * that would require stdio. The caller must supply a buffer of + * sufficient size or we will png_error. The tests on size and + * the space in ascii[] consumed are indicated below. + */ + if (precision < 1) + precision = DBL_DIG; + + /* Enforce the limit of the implementation precision too. */ + if (precision > DBL_DIG+1) + precision = DBL_DIG+1; + + /* Basic sanity checks */ + if (size >= precision+5) /* See the requirements below. */ + { + if (fp < 0) + { + fp = -fp; + *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */ + --size; + } + + if (fp >= DBL_MIN && fp <= DBL_MAX) + { + int exp_b10; /* A base 10 exponent */ + double base; /* 10^exp_b10 */ + + /* First extract a base 10 exponent of the number, + * the calculation below rounds down when converting + * from base 2 to base 10 (multiply by log10(2) - + * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to + * be increased. Note that the arithmetic shift + * performs a floor() unlike C arithmetic - using a + * C multiply would break the following for negative + * exponents. + */ + (void)frexp(fp, &exp_b10); /* exponent to base 2 */ + + exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */ + + /* Avoid underflow here. */ + base = png_pow10(exp_b10); /* May underflow */ + + while (base < DBL_MIN || base < fp) + { + /* And this may overflow. */ + double test = png_pow10(exp_b10+1); + + if (test <= DBL_MAX) + ++exp_b10, base = test; + + else + break; + } + + /* Normalize fp and correct exp_b10, after this fp is in the + * range [.1,1) and exp_b10 is both the exponent and the digit + * *before* which the decimal point should be inserted + * (starting with 0 for the first digit). Note that this + * works even if 10^exp_b10 is out of range because of the + * test on DBL_MAX above. + */ + fp /= base; + while (fp >= 1) fp /= 10, ++exp_b10; + + /* Because of the code above fp may, at this point, be + * less than .1, this is ok because the code below can + * handle the leading zeros this generates, so no attempt + * is made to correct that here. + */ + + { + int czero, clead, cdigits; + char exponent[10]; + + /* Allow up to two leading zeros - this will not lengthen + * the number compared to using E-n. + */ + if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ + { + czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ + exp_b10 = 0; /* Dot added below before first output. */ + } + else + czero = 0; /* No zeros to add */ + + /* Generate the digit list, stripping trailing zeros and + * inserting a '.' before a digit if the exponent is 0. + */ + clead = czero; /* Count of leading zeros */ + cdigits = 0; /* Count of digits in list. */ + + do + { + double d; + + fp *= 10; + /* Use modf here, not floor and subtract, so that + * the separation is done in one step. At the end + * of the loop don't break the number into parts so + * that the final digit is rounded. + */ + if (cdigits+czero-clead+1 < (int)precision) + fp = modf(fp, &d); + + else + { + d = floor(fp + .5); + + if (d > 9) + { + /* Rounding up to 10, handle that here. */ + if (czero > 0) + { + --czero, d = 1; + if (cdigits == 0) --clead; + } + else + { + while (cdigits > 0 && d > 9) + { + int ch = *--ascii; + + if (exp_b10 != (-1)) + ++exp_b10; + + else if (ch == 46) + { + ch = *--ascii, ++size; + /* Advance exp_b10 to '1', so that the + * decimal point happens after the + * previous digit. + */ + exp_b10 = 1; + } + + --cdigits; + d = ch - 47; /* I.e. 1+(ch-48) */ + } + + /* Did we reach the beginning? If so adjust the + * exponent but take into account the leading + * decimal point. + */ + if (d > 9) /* cdigits == 0 */ + { + if (exp_b10 == (-1)) + { + /* Leading decimal point (plus zeros?), if + * we lose the decimal point here it must + * be reentered below. + */ + int ch = *--ascii; + + if (ch == 46) + ++size, exp_b10 = 1; + + /* Else lost a leading zero, so 'exp_b10' is + * still ok at (-1) + */ + } + else + ++exp_b10; + + /* In all cases we output a '1' */ + d = 1; + } + } + } + fp = 0; /* Guarantees termination below. */ + } + + if (d == 0) + { + ++czero; + if (cdigits == 0) ++clead; + } + else + { + /* Included embedded zeros in the digit count. */ + cdigits += czero - clead; + clead = 0; + + while (czero > 0) + { + /* exp_b10 == (-1) means we just output the decimal + * place - after the DP don't adjust 'exp_b10' any + * more! + */ + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; + /* PLUS 1: TOTAL 4 */ + --exp_b10; + } + *ascii++ = 48, --czero; + } + + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; /* counted + above */ + --exp_b10; + } + *ascii++ = (char)(48 + (int)d), ++cdigits; + } + } + while (cdigits+czero-clead < (int)precision && fp > DBL_MIN); + + /* The total output count (max) is now 4+precision */ + + /* Check for an exponent, if we don't need one we are + * done and just need to terminate the string. At + * this point exp_b10==(-1) is effectively if flag - it got + * to '-1' because of the decrement after outputing + * the decimal point above (the exponent required is + * *not* -1!) + */ + if (exp_b10 >= (-1) && exp_b10 <= 2) + { + /* The following only happens if we didn't output the + * leading zeros above for negative exponent, so this + * doest add to the digit requirement. Note that the + * two zeros here can only be output if the two leading + * zeros were *not* output, so this doesn't increase + * the output count. + */ + while (--exp_b10 >= 0) *ascii++ = 48; + + *ascii = 0; + + /* Total buffer requirement (including the '\0') is + * 5+precision - see check at the start. + */ + return; + } + + /* Here if an exponent is required, adjust size for + * the digits we output but did not count. The total + * digit output here so far is at most 1+precision - no + * decimal point and no leading or trailing zeros have + * been output. + */ + size -= cdigits; + + *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ + + /* The following use of an unsigned temporary avoids ambiguities in + * the signed arithmetic on exp_b10 and permits GCC at least to do + * better optimization. + */ + { + unsigned int uexp_b10; + + if (exp_b10 < 0) + { + *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ + uexp_b10 = -exp_b10; + } + + else + uexp_b10 = exp_b10; + + cdigits = 0; + + while (uexp_b10 > 0) + { + exponent[cdigits++] = (char)(48 + uexp_b10 % 10); + uexp_b10 /= 10; + } + } + + /* Need another size check here for the exponent digits, so + * this need not be considered above. + */ + if ((int)size > cdigits) + { + while (cdigits > 0) *ascii++ = exponent[--cdigits]; + + *ascii = 0; + + return; + } + } + } + else if (!(fp >= DBL_MIN)) + { + *ascii++ = 48; /* '0' */ + *ascii = 0; + return; + } + else + { + *ascii++ = 105; /* 'i' */ + *ascii++ = 110; /* 'n' */ + *ascii++ = 102; /* 'f' */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} + +# endif /* FLOATING_POINT */ + +# ifdef PNG_FIXED_POINT_SUPPORTED +/* Function to format a fixed point value in ASCII. + */ +void /* PRIVATE */ +png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, + png_size_t size, png_fixed_point fp) +{ + /* Require space for 10 decimal digits, a decimal point, a minus sign and a + * trailing \0, 13 characters: + */ + if (size > 12) + { + png_uint_32 num; + + /* Avoid overflow here on the minimum integer. */ + if (fp < 0) + *ascii++ = 45, --size, num = -fp; + else + num = fp; + + if (num <= 0x80000000) /* else overflowed */ + { + unsigned int ndigits = 0, first = 16 /* flag value */; + char digits[10]; + + while (num) + { + /* Split the low digit off num: */ + unsigned int tmp = num/10; + num -= tmp*10; + digits[ndigits++] = (char)(48 + num); + /* Record the first non-zero digit, note that this is a number + * starting at 1, it's not actually the array index. + */ + if (first == 16 && num > 0) + first = ndigits; + num = tmp; + } + + if (ndigits > 0) + { + while (ndigits > 5) *ascii++ = digits[--ndigits]; + /* The remaining digits are fractional digits, ndigits is '5' or + * smaller at this point. It is certainly not zero. Check for a + * non-zero fractional digit: + */ + if (first <= 5) + { + unsigned int i; + *ascii++ = 46; /* decimal point */ + /* ndigits may be <5 for small numbers, output leading zeros + * then ndigits digits to first: + */ + i = 5; + while (ndigits < i) *ascii++ = 48, --i; + while (ndigits >= first) *ascii++ = digits[--ndigits]; + /* Don't output the trailing zeros! */ + } + } + else + *ascii++ = 48; + + /* And null terminate the string: */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} +# endif /* FIXED_POINT */ +#endif /* READ_SCAL */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \ + (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \ + defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \ + (defined(PNG_sCAL_SUPPORTED) && \ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)) +png_fixed_point +png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text) +{ + double r = floor(100000 * fp + .5); + + if (r > 2147483647. || r < -2147483648.) + png_fixed_error(png_ptr, text); + + return (png_fixed_point)r; +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || \ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) +/* muldiv functions */ +/* This API takes signed arguments and rounds the result to the nearest + * integer (or, for a fixed point number - the standard argument - to + * the nearest .00001). Overflow and divide by zero are signalled in + * the result, a boolean - true on success, false on overflow. + */ +int +png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + /* Return a * times / divisor, rounded. */ + if (divisor != 0) + { + if (a == 0 || times == 0) + { + *res = 0; + return 1; + } + else + { +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a; + r *= times; + r /= divisor; + r = floor(r+.5); + + /* A png_fixed_point is a 32-bit integer. */ + if (r <= 2147483647. && r >= -2147483648.) + { + *res = (png_fixed_point)r; + return 1; + } +#else + int negative = 0; + png_uint_32 A, T, D; + png_uint_32 s16, s32, s00; + + if (a < 0) + negative = 1, A = -a; + else + A = a; + + if (times < 0) + negative = !negative, T = -times; + else + T = times; + + if (divisor < 0) + negative = !negative, D = -divisor; + else + D = divisor; + + /* Following can't overflow because the arguments only + * have 31 bits each, however the result may be 32 bits. + */ + s16 = (A >> 16) * (T & 0xffff) + + (A & 0xffff) * (T >> 16); + /* Can't overflow because the a*times bit is only 30 + * bits at most. + */ + s32 = (A >> 16) * (T >> 16) + (s16 >> 16); + s00 = (A & 0xffff) * (T & 0xffff); + + s16 = (s16 & 0xffff) << 16; + s00 += s16; + + if (s00 < s16) + ++s32; /* carry */ + + if (s32 < D) /* else overflow */ + { + /* s32.s00 is now the 64-bit product, do a standard + * division, we know that s32 < D, so the maximum + * required shift is 31. + */ + int bitshift = 32; + png_fixed_point result = 0; /* NOTE: signed */ + + while (--bitshift >= 0) + { + png_uint_32 d32, d00; + + if (bitshift > 0) + d32 = D >> (32-bitshift), d00 = D << bitshift; + + else + d32 = 0, d00 = D; + + if (s32 > d32) + { + if (s00 < d00) --s32; /* carry */ + s32 -= d32, s00 -= d00, result += 1<= d00) + s32 = 0, s00 -= d00, result += 1<= (D >> 1)) + ++result; + + if (negative) + result = -result; + + /* Check for overflow. */ + if ((negative && result <= 0) || (!negative && result >= 0)) + { + *res = result; + return 1; + } + } +#endif + } + } + + return 0; +} +#endif /* READ_GAMMA || INCH_CONVERSIONS */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* The following is for when the caller doesn't much care about the + * result. + */ +png_fixed_point +png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + png_fixed_point result; + + if (png_muldiv(&result, a, times, divisor)) + return result; + + png_warning(png_ptr, "fixed point overflow ignored"); + return 0; +} +#endif + +#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */ +/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ +png_fixed_point +png_reciprocal(png_fixed_point a) +{ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(1E10/a+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, 100000, 100000, a)) + return res; +#endif + + return 0; /* error/overflow */ +} + +/* This is the shared test on whether a gamma value is 'significant' - whether + * it is worth doing gamma correction. + */ +int /* PRIVATE */ +png_gamma_significant(png_fixed_point gamma_val) +{ + return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED || + gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; +} +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* A local convenience routine. */ +static png_fixed_point +png_product2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a * 1E-5; + r *= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, a, b, 100000)) + return res; +#endif + + return 0; /* overflow */ +} + +/* The inverse of the above. */ +png_fixed_point +png_reciprocal2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = 1E15/a; + r /= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + /* This may overflow because the range of png_fixed_point isn't symmetric, + * but this API is only used for the product of file and screen gamma so it + * doesn't matter that the smallest number it can produce is 1/21474, not + * 1/100000 + */ + png_fixed_point res = png_product2(a, b); + + if (res != 0) + return png_reciprocal(res); +#endif + + return 0; /* overflow */ +} +#endif /* READ_GAMMA */ + +#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */ +#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* Fixed point gamma. + * + * The code to calculate the tables used below can be found in the shell script + * contrib/tools/intgamma.sh + * + * To calculate gamma this code implements fast log() and exp() calls using only + * fixed point arithmetic. This code has sufficient precision for either 8-bit + * or 16-bit sample values. + * + * The tables used here were calculated using simple 'bc' programs, but C double + * precision floating point arithmetic would work fine. + * + * 8-bit log table + * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to + * 255, so it's the base 2 logarithm of a normalized 8-bit floating point + * mantissa. The numbers are 32-bit fractions. + */ +static const png_uint_32 +png_8bit_l2[128] = +{ + 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U, + 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U, + 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U, + 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U, + 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U, + 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U, + 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U, + 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U, + 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U, + 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U, + 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U, + 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U, + 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U, + 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U, + 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U, + 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U, + 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U, + 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U, + 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U, + 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U, + 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U, + 24347096U, 0U + +#if 0 + /* The following are the values for 16-bit tables - these work fine for the + * 8-bit conversions but produce very slightly larger errors in the 16-bit + * log (about 1.2 as opposed to 0.7 absolute error in the final value). To + * use these all the shifts below must be adjusted appropriately. + */ + 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054, + 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803, + 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068, + 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782, + 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887, + 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339, + 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098, + 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132, + 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415, + 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523, + 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495, + 1119, 744, 372 +#endif +}; + +static png_int_32 +png_log8bit(unsigned int x) +{ + unsigned int lg2 = 0; + /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log, + * because the log is actually negate that means adding 1. The final + * returned value thus has the range 0 (for 255 input) to 7.994 (for 1 + * input), return -1 for the overflow (log 0) case, - so the result is + * always at most 19 bits. + */ + if ((x &= 0xff) == 0) + return -1; + + if ((x & 0xf0) == 0) + lg2 = 4, x <<= 4; + + if ((x & 0xc0) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x80) == 0) + lg2 += 1, x <<= 1; + + /* result is at most 19 bits, so this cast is safe: */ + return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16)); +} + +/* The above gives exact (to 16 binary places) log2 values for 8-bit images, + * for 16-bit images we use the most significant 8 bits of the 16-bit value to + * get an approximation then multiply the approximation by a correction factor + * determined by the remaining up to 8 bits. This requires an additional step + * in the 16-bit case. + * + * We want log2(value/65535), we have log2(v'/255), where: + * + * value = v' * 256 + v'' + * = v' * f + * + * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128 + * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less + * than 258. The final factor also needs to correct for the fact that our 8-bit + * value is scaled by 255, whereas the 16-bit values must be scaled by 65535. + * + * This gives a final formula using a calculated value 'x' which is value/v' and + * scaling by 65536 to match the above table: + * + * log2(x/257) * 65536 + * + * Since these numbers are so close to '1' we can use simple linear + * interpolation between the two end values 256/257 (result -368.61) and 258/257 + * (result 367.179). The values used below are scaled by a further 64 to give + * 16-bit precision in the interpolation: + * + * Start (256): -23591 + * Zero (257): 0 + * End (258): 23499 + */ +static png_int_32 +png_log16bit(png_uint_32 x) +{ + unsigned int lg2 = 0; + + /* As above, but now the input has 16 bits. */ + if ((x &= 0xffff) == 0) + return -1; + + if ((x & 0xff00) == 0) + lg2 = 8, x <<= 8; + + if ((x & 0xf000) == 0) + lg2 += 4, x <<= 4; + + if ((x & 0xc000) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x8000) == 0) + lg2 += 1, x <<= 1; + + /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional + * value. + */ + lg2 <<= 28; + lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4; + + /* Now we need to interpolate the factor, this requires a division by the top + * 8 bits. Do this with maximum precision. + */ + x = ((x << 16) + (x >> 9)) / (x >> 8); + + /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24, + * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly + * 16 bits to interpolate to get the low bits of the result. Round the + * answer. Note that the end point values are scaled by 64 to retain overall + * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust + * the overall scaling by 6-12. Round at every step. + */ + x -= 1U << 24; + + if (x <= 65536U) /* <= '257' */ + lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12); + + else + lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12); + + /* Safe, because the result can't have more than 20 bits: */ + return (png_int_32)((lg2 + 2048) >> 12); +} + +/* The 'exp()' case must invert the above, taking a 20-bit fixed point + * logarithmic value and returning a 16 or 8-bit number as appropriate. In + * each case only the low 16 bits are relevant - the fraction - since the + * integer bits (the top 4) simply determine a shift. + * + * The worst case is the 16-bit distinction between 65535 and 65534, this + * requires perhaps spurious accuracty in the decoding of the logarithm to + * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance + * of getting this accuracy in practice. + * + * To deal with this the following exp() function works out the exponent of the + * frational part of the logarithm by using an accurate 32-bit value from the + * top four fractional bits then multiplying in the remaining bits. + */ +static const png_uint_32 +png_32bit_exp[16] = +{ + /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */ + 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U, + 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U, + 2553802834U, 2445529972U, 2341847524U, 2242560872U +}; + +/* Adjustment table; provided to explain the numbers in the code below. */ +#if 0 +for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"} + 11 44937.64284865548751208448 + 10 45180.98734845585101160448 + 9 45303.31936980687359311872 + 8 45364.65110595323018870784 + 7 45395.35850361789624614912 + 6 45410.72259715102037508096 + 5 45418.40724413220722311168 + 4 45422.25021786898173001728 + 3 45424.17186732298419044352 + 2 45425.13273269940811464704 + 1 45425.61317555035558641664 + 0 45425.85339951654943850496 +#endif + +static png_uint_32 +png_exp(png_fixed_point x) +{ + if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */ + { + /* Obtain a 4-bit approximation */ + png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf]; + + /* Incorporate the low 12 bits - these decrease the returned value by + * multiplying by a number less than 1 if the bit is set. The multiplier + * is determined by the above table and the shift. Notice that the values + * converge on 45426 and this is used to allow linear interpolation of the + * low bits. + */ + if (x & 0x800) + e -= (((e >> 16) * 44938U) + 16U) >> 5; + + if (x & 0x400) + e -= (((e >> 16) * 45181U) + 32U) >> 6; + + if (x & 0x200) + e -= (((e >> 16) * 45303U) + 64U) >> 7; + + if (x & 0x100) + e -= (((e >> 16) * 45365U) + 128U) >> 8; + + if (x & 0x080) + e -= (((e >> 16) * 45395U) + 256U) >> 9; + + if (x & 0x040) + e -= (((e >> 16) * 45410U) + 512U) >> 10; + + /* And handle the low 6 bits in a single block. */ + e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9; + + /* Handle the upper bits of x. */ + e >>= x >> 16; + return e; + } + + /* Check for overflow */ + if (x <= 0) + return png_32bit_exp[0]; + + /* Else underflow */ + return 0; +} + +static png_byte +png_exp8bit(png_fixed_point lg2) +{ + /* Get a 32-bit value: */ + png_uint_32 x = png_exp(lg2); + + /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the + * second, rounding, step can't overflow because of the first, subtraction, + * step. + */ + x -= x >> 8; + return (png_byte)((x + 0x7fffffU) >> 24); +} + +static png_uint_16 +png_exp16bit(png_fixed_point lg2) +{ + /* Get a 32-bit value: */ + png_uint_32 x = png_exp(lg2); + + /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */ + x -= x >> 16; + return (png_uint_16)((x + 32767U) >> 16); +} +#endif /* FLOATING_ARITHMETIC */ + +png_byte +png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 255) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(255*pow(value/255.,gamma_val*.00001)+.5); + return (png_byte)r; +# else + png_int_32 lg2 = png_log8bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp8bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_byte)value; +} + +png_uint_16 +png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 65535) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5); + return (png_uint_16)r; +# else + png_int_32 lg2 = png_log16bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp16bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_uint_16)value; +} + +/* This does the right thing based on the bit_depth field of the + * png_struct, interpreting values as 8-bit or 16-bit. While the result + * is nominally a 16-bit value if bit depth is 8 then the result is + * 8-bit (as are the arguments.) + */ +png_uint_16 /* PRIVATE */ +png_gamma_correct(png_structrp png_ptr, unsigned int value, + png_fixed_point gamma_val) +{ + if (png_ptr->bit_depth == 8) + return png_gamma_8bit_correct(value, gamma_val); + + else + return png_gamma_16bit_correct(value, gamma_val); +} + +/* Internal function to build a single 16-bit table - the table consists of + * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount + * to shift the input values right (or 16-number_of_signifiant_bits). + * + * The caller is responsible for ensuring that the table gets cleaned up on + * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument + * should be somewhere that will be cleaned. + */ +static void +png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +{ + /* Various values derived from 'shift': */ + PNG_CONST unsigned int num = 1U << (8U - shift); + PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); + unsigned int i; + + png_uint_16pp table = *ptable = + (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p))); + + for (i = 0; i < num; i++) + { + png_uint_16p sub_table = table[i] = + (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16))); + + /* The 'threshold' test is repeated here because it can arise for one of + * the 16-bit tables even if the others don't hit it. + */ + if (png_gamma_significant(gamma_val)) + { + /* The old code would overflow at the end and this would cause the + * 'pow' function to return a result >1, resulting in an + * arithmetic error. This code follows the spec exactly; ig is + * the recovered input sample, it always has 8-16 bits. + * + * We want input * 65535/max, rounded, the arithmetic fits in 32 + * bits (unsigned) so long as max <= 32767. + */ + unsigned int j; + for (j = 0; j < 256; j++) + { + png_uint_32 ig = (j << (8-shift)) + i; +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + /* Inline the 'max' scaling operation: */ + double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5); + sub_table[j] = (png_uint_16)d; +# else + if (shift) + ig = (ig * 65535U + max_by_2)/max; + + sub_table[j] = png_gamma_16bit_correct(ig, gamma_val); +# endif + } + } + else + { + /* We must still build a table, but do it the fast way. */ + unsigned int j; + + for (j = 0; j < 256; j++) + { + png_uint_32 ig = (j << (8-shift)) + i; + + if (shift) + ig = (ig * 65535U + max_by_2)/max; + + sub_table[j] = (png_uint_16)ig; + } + } + } +} + +/* NOTE: this function expects the *inverse* of the overall gamma transformation + * required. + */ +static void +png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +{ + PNG_CONST unsigned int num = 1U << (8U - shift); + PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + unsigned int i; + png_uint_32 last; + + png_uint_16pp table = *ptable = + (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p))); + + /* 'num' is the number of tables and also the number of low bits of low + * bits of the input 16-bit value used to select a table. Each table is + * itself index by the high 8 bits of the value. + */ + for (i = 0; i < num; i++) + table[i] = (png_uint_16p)png_malloc(png_ptr, + 256 * (sizeof (png_uint_16))); + + /* 'gamma_val' is set to the reciprocal of the value calculated above, so + * pow(out,g) is an *input* value. 'last' is the last input value set. + * + * In the loop 'i' is used to find output values. Since the output is + * 8-bit there are only 256 possible values. The tables are set up to + * select the closest possible output value for each input by finding + * the input value at the boundary between each pair of output values + * and filling the table up to that boundary with the lower output + * value. + * + * The boundary values are 0.5,1.5..253.5,254.5. Since these are 9-bit + * values the code below uses a 16-bit value in i; the values start at + * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last + * entries are filled with 255). Start i at 128 and fill all 'last' + * table entries <= 'max' + */ + last = 0; + for (i = 0; i < 255; ++i) /* 8-bit output value */ + { + /* Find the corresponding maximum input value */ + png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */ + + /* Find the boundary value in 16 bits: */ + png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val); + + /* Adjust (round) to (16-shift) bits: */ + bound = (bound * max + 32768U)/65535U + 1U; + + while (last < bound) + { + table[last & (0xffU >> shift)][last >> (8U - shift)] = out; + last++; + } + } + + /* And fill in the final entries. */ + while (last < (num << 8)) + { + table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U; + last++; + } +} + +/* Build a single 8-bit table: same as the 16-bit case but much simpler (and + * typically much faster). Note that libpng currently does no sBIT processing + * (apparently contrary to the spec) so a 256 entry table is always generated. + */ +static void +png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable, + PNG_CONST png_fixed_point gamma_val) +{ + unsigned int i; + png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); + + if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++) + table[i] = png_gamma_8bit_correct(i, gamma_val); + + else for (i=0; i<256; ++i) + table[i] = (png_byte)i; +} + +/* Used from png_read_destroy and below to release the memory used by the gamma + * tables. + */ +void /* PRIVATE */ +png_destroy_gamma_table(png_structrp png_ptr) +{ + png_free(png_ptr, png_ptr->gamma_table); + png_ptr->gamma_table = NULL; + + if (png_ptr->gamma_16_table != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } + png_free(png_ptr, png_ptr->gamma_16_table); + png_ptr->gamma_16_table = NULL; + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_from_1); + png_ptr->gamma_from_1 = NULL; + png_free(png_ptr, png_ptr->gamma_to_1); + png_ptr->gamma_to_1 = NULL; + + if (png_ptr->gamma_16_from_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_from_1); + png_ptr->gamma_16_from_1 = NULL; + } + if (png_ptr->gamma_16_to_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_to_1); + png_ptr->gamma_16_to_1 = NULL; + } +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ +} + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + */ +void /* PRIVATE */ +png_build_gamma_table(png_structrp png_ptr, int bit_depth) +{ + png_debug(1, "in png_build_gamma_table"); + + /* Remove any existing table; this copes with multiple calls to + * png_read_update_info. The warning is because building the gamma tables + * multiple times is a performance hit - it's harmless but the ability to call + * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible + * to warn if the app introduces such a hit. + */ + if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) + { + png_warning(png_ptr, "gamma table being rebuilt"); + png_destroy_gamma_table(png_ptr); + } + + if (bit_depth <= 8) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_table, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma) : PNG_FP_1); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, + png_reciprocal(png_ptr->colorspace.gamma)); + + png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, + png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : + png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); + } +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ + } + else + { + png_byte shift, sig_bit; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = png_ptr->sig_bit.red; + + if (png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + + if (png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + sig_bit = png_ptr->sig_bit.gray; + + /* 16-bit gamma code uses this equation: + * + * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] + * + * Where 'iv' is the input color value and 'ov' is the output value - + * pow(iv, gamma). + * + * Thus the gamma table consists of up to 256 256 entry tables. The table + * is selected by the (8-gamma_shift) most significant of the low 8 bits of + * the color value then indexed by the upper 8 bits: + * + * table[low bits][high 8 bits] + * + * So the table 'n' corresponds to all those 'iv' of: + * + * ..<(n+1 << gamma_shift)-1> + * + */ + if (sig_bit > 0 && sig_bit < 16U) + shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */ + + else + shift = 0; /* keep all 16 bits */ + + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) + { + /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively + * the significant bits in the *input* when the output will + * eventually be 8 bits. By default it is 11. + */ + if (shift < (16U - PNG_MAX_GAMMA_8)) + shift = (16U - PNG_MAX_GAMMA_8); + } + + if (shift > 8U) + shift = 8U; /* Guarantees at least one table! */ + + png_ptr->gamma_shift = shift; + +#ifdef PNG_16BIT_SUPPORTED + /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now + * PNG_COMPOSE). This effectively smashed the background calculation for + * 16-bit output because the 8-bit table assumes the result will be reduced + * to 8 bits. + */ + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) +#endif + png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma) : PNG_FP_1); + +#ifdef PNG_16BIT_SUPPORTED + else + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma) : PNG_FP_1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) + { + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, + png_reciprocal(png_ptr->colorspace.gamma)); + + /* Notice that the '16 from 1' table should be full precision, however + * the lookup on this table still uses gamma_shift, so it can't be. + * TODO: fix this. + */ + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : + png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); + } +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ + } +} +#endif /* READ_GAMMA */ + +/* HARDWARE OPTION SUPPORT */ +#ifdef PNG_SET_OPTION_SUPPORTED +int PNGAPI +png_set_option(png_structrp png_ptr, int option, int onoff) +{ + if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT && + (option & 1) == 0) + { + int mask = 3 << option; + int setting = (2 + (onoff != 0)) << option; + int current = png_ptr->options; + + png_ptr->options = (png_byte)((current & ~mask) | setting); + + return (current & mask) >> option; + } + + return PNG_OPTION_INVALID; +} +#endif + +/* sRGB support */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) +/* sRGB conversion tables; these are machine generated with the code in + * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the + * specification (see the article at http://en.wikipedia.org/wiki/SRGB) + * is used, not the gamma=1/2.2 approximation use elsewhere in libpng. + * The sRGB to linear table is exact (to the nearest 16 bit linear fraction). + * The inverse (linear to sRGB) table has accuracies as follows: + * + * For all possible (255*65535+1) input values: + * + * error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact + * + * For the input values corresponding to the 65536 16-bit values: + * + * error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact + * + * In all cases the inexact readings are off by one. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* The convert-to-sRGB table is only currently required for read. */ +const png_uint_16 png_sRGB_table[256] = +{ + 0,20,40,60,80,99,119,139, + 159,179,199,219,241,264,288,313, + 340,367,396,427,458,491,526,562, + 599,637,677,718,761,805,851,898, + 947,997,1048,1101,1156,1212,1270,1330, + 1391,1453,1517,1583,1651,1720,1790,1863, + 1937,2013,2090,2170,2250,2333,2418,2504, + 2592,2681,2773,2866,2961,3058,3157,3258, + 3360,3464,3570,3678,3788,3900,4014,4129, + 4247,4366,4488,4611,4736,4864,4993,5124, + 5257,5392,5530,5669,5810,5953,6099,6246, + 6395,6547,6700,6856,7014,7174,7335,7500, + 7666,7834,8004,8177,8352,8528,8708,8889, + 9072,9258,9445,9635,9828,10022,10219,10417, + 10619,10822,11028,11235,11446,11658,11873,12090, + 12309,12530,12754,12980,13209,13440,13673,13909, + 14146,14387,14629,14874,15122,15371,15623,15878, + 16135,16394,16656,16920,17187,17456,17727,18001, + 18277,18556,18837,19121,19407,19696,19987,20281, + 20577,20876,21177,21481,21787,22096,22407,22721, + 23038,23357,23678,24002,24329,24658,24990,25325, + 25662,26001,26344,26688,27036,27386,27739,28094, + 28452,28813,29176,29542,29911,30282,30656,31033, + 31412,31794,32179,32567,32957,33350,33745,34143, + 34544,34948,35355,35764,36176,36591,37008,37429, + 37852,38278,38706,39138,39572,40009,40449,40891, + 41337,41785,42236,42690,43147,43606,44069,44534, + 45002,45473,45947,46423,46903,47385,47871,48359, + 48850,49344,49841,50341,50844,51349,51858,52369, + 52884,53401,53921,54445,54971,55500,56032,56567, + 57105,57646,58190,58737,59287,59840,60396,60955, + 61517,62082,62650,63221,63795,64372,64952,65535 +}; + +#endif /* simplified read only */ + +/* The base/delta tables are required for both read and write (but currently + * only the simplified versions.) + */ +const png_uint_16 png_sRGB_base[512] = +{ + 128,1782,3383,4644,5675,6564,7357,8074, + 8732,9346,9921,10463,10977,11466,11935,12384, + 12816,13233,13634,14024,14402,14769,15125,15473, + 15812,16142,16466,16781,17090,17393,17690,17981, + 18266,18546,18822,19093,19359,19621,19879,20133, + 20383,20630,20873,21113,21349,21583,21813,22041, + 22265,22487,22707,22923,23138,23350,23559,23767, + 23972,24175,24376,24575,24772,24967,25160,25352, + 25542,25730,25916,26101,26284,26465,26645,26823, + 27000,27176,27350,27523,27695,27865,28034,28201, + 28368,28533,28697,28860,29021,29182,29341,29500, + 29657,29813,29969,30123,30276,30429,30580,30730, + 30880,31028,31176,31323,31469,31614,31758,31902, + 32045,32186,32327,32468,32607,32746,32884,33021, + 33158,33294,33429,33564,33697,33831,33963,34095, + 34226,34357,34486,34616,34744,34873,35000,35127, + 35253,35379,35504,35629,35753,35876,35999,36122, + 36244,36365,36486,36606,36726,36845,36964,37083, + 37201,37318,37435,37551,37668,37783,37898,38013, + 38127,38241,38354,38467,38580,38692,38803,38915, + 39026,39136,39246,39356,39465,39574,39682,39790, + 39898,40005,40112,40219,40325,40431,40537,40642, + 40747,40851,40955,41059,41163,41266,41369,41471, + 41573,41675,41777,41878,41979,42079,42179,42279, + 42379,42478,42577,42676,42775,42873,42971,43068, + 43165,43262,43359,43456,43552,43648,43743,43839, + 43934,44028,44123,44217,44311,44405,44499,44592, + 44685,44778,44870,44962,45054,45146,45238,45329, + 45420,45511,45601,45692,45782,45872,45961,46051, + 46140,46229,46318,46406,46494,46583,46670,46758, + 46846,46933,47020,47107,47193,47280,47366,47452, + 47538,47623,47709,47794,47879,47964,48048,48133, + 48217,48301,48385,48468,48552,48635,48718,48801, + 48884,48966,49048,49131,49213,49294,49376,49458, + 49539,49620,49701,49782,49862,49943,50023,50103, + 50183,50263,50342,50422,50501,50580,50659,50738, + 50816,50895,50973,51051,51129,51207,51285,51362, + 51439,51517,51594,51671,51747,51824,51900,51977, + 52053,52129,52205,52280,52356,52432,52507,52582, + 52657,52732,52807,52881,52956,53030,53104,53178, + 53252,53326,53400,53473,53546,53620,53693,53766, + 53839,53911,53984,54056,54129,54201,54273,54345, + 54417,54489,54560,54632,54703,54774,54845,54916, + 54987,55058,55129,55199,55269,55340,55410,55480, + 55550,55620,55689,55759,55828,55898,55967,56036, + 56105,56174,56243,56311,56380,56448,56517,56585, + 56653,56721,56789,56857,56924,56992,57059,57127, + 57194,57261,57328,57395,57462,57529,57595,57662, + 57728,57795,57861,57927,57993,58059,58125,58191, + 58256,58322,58387,58453,58518,58583,58648,58713, + 58778,58843,58908,58972,59037,59101,59165,59230, + 59294,59358,59422,59486,59549,59613,59677,59740, + 59804,59867,59930,59993,60056,60119,60182,60245, + 60308,60370,60433,60495,60558,60620,60682,60744, + 60806,60868,60930,60992,61054,61115,61177,61238, + 61300,61361,61422,61483,61544,61605,61666,61727, + 61788,61848,61909,61969,62030,62090,62150,62211, + 62271,62331,62391,62450,62510,62570,62630,62689, + 62749,62808,62867,62927,62986,63045,63104,63163, + 63222,63281,63340,63398,63457,63515,63574,63632, + 63691,63749,63807,63865,63923,63981,64039,64097, + 64155,64212,64270,64328,64385,64443,64500,64557, + 64614,64672,64729,64786,64843,64900,64956,65013, + 65070,65126,65183,65239,65296,65352,65409,65465 +}; + +const png_byte png_sRGB_delta[512] = +{ + 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54, + 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36, + 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28, + 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24, + 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21, + 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19, + 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17, + 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; +#endif /* SIMPLIFIED READ/WRITE sRGB support */ + +/* SIMPLIFIED READ/WRITE SUPPORT */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) +static int +png_image_free_function(png_voidp argument) +{ + png_imagep image = png_voidcast(png_imagep, argument); + png_controlp cp = image->opaque; + png_control c; + + /* Double check that we have a png_ptr - it should be impossible to get here + * without one. + */ + if (cp->png_ptr == NULL) + return 0; + + /* First free any data held in the control structure. */ +# ifdef PNG_STDIO_SUPPORTED + if (cp->owned_file) + { + FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr); + cp->owned_file = 0; + + /* Ignore errors here. */ + if (fp != NULL) + { + cp->png_ptr->io_ptr = NULL; + (void)fclose(fp); + } + } +# endif + + /* Copy the control structure so that the original, allocated, version can be + * safely freed. Notice that a png_error here stops the remainder of the + * cleanup, but this is probably fine because that would indicate bad memory + * problems anyway. + */ + c = *cp; + image->opaque = &c; + png_free(c.png_ptr, cp); + + /* Then the structures, calling the correct API. */ + if (c.for_write) + { +# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED + png_destroy_write_struct(&c.png_ptr, &c.info_ptr); +# else + png_error(c.png_ptr, "simplified write not supported"); +# endif + } + else + { +# ifdef PNG_SIMPLIFIED_READ_SUPPORTED + png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL); +# else + png_error(c.png_ptr, "simplified read not supported"); +# endif + } + + /* Success. */ + return 1; +} + +void PNGAPI +png_image_free(png_imagep image) +{ + /* Safely call the real function, but only if doing so is safe at this point + * (if not inside an error handling context). Otherwise assume + * png_safe_execute will call this API after the return. + */ + if (image != NULL && image->opaque != NULL && + image->opaque->error_buf == NULL) + { + /* Ignore errors here: */ + (void)png_safe_execute(image, png_image_free_function, image); + image->opaque = NULL; + } +} + +int /* PRIVATE */ +png_image_error(png_imagep image, png_const_charp error_message) +{ + /* Utility to log an error. */ + png_safecat(image->message, (sizeof image->message), 0, error_message); + image->warning_or_error |= PNG_IMAGE_ERROR; + png_image_free(image); + return 0; +} + +#endif /* SIMPLIFIED READ/WRITE */ +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/ext/libpng16/png.h b/ext/libpng16/png.h new file mode 100644 index 0000000000..36ab027128 --- /dev/null +++ b/ext/libpng16/png.h @@ -0,0 +1,3319 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.6.7 - November 14, 2013 + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license (See LICENSE, below) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.6.7 - November 14, 2013: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 12.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 12.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-7 13 10210 12.so.0.10[.0] + * 1.2.10rc1-2 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.4.0beta1-5 14 10400 14.so.0.0[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.4.0beta7-8 14 10400 14.so.0.0[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.4.0beta9-14 14 10400 14.so.0.0[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.4.0beta15-36 14 10400 14.so.0.0[.0] + * 1.4.0beta37-87 14 10400 14.so.14.0[.0] + * 1.4.0rc01 14 10400 14.so.14.0[.0] + * 1.4.0beta88-109 14 10400 14.so.14.0[.0] + * 1.4.0rc02-08 14 10400 14.so.14.0[.0] + * 1.4.0 14 10400 14.so.14.0[.0] + * 1.4.1beta01-03 14 10401 14.so.14.1[.0] + * 1.4.1rc01 14 10401 14.so.14.1[.0] + * 1.4.1beta04-12 14 10401 14.so.14.1[.0] + * 1.4.1 14 10401 14.so.14.1[.0] + * 1.4.2 14 10402 14.so.14.2[.0] + * 1.4.3 14 10403 14.so.14.3[.0] + * 1.4.4 14 10404 14.so.14.4[.0] + * 1.5.0beta01-58 15 10500 15.so.15.0[.0] + * 1.5.0rc01-07 15 10500 15.so.15.0[.0] + * 1.5.0 15 10500 15.so.15.0[.0] + * 1.5.1beta01-11 15 10501 15.so.15.1[.0] + * 1.5.1rc01-02 15 10501 15.so.15.1[.0] + * 1.5.1 15 10501 15.so.15.1[.0] + * 1.5.2beta01-03 15 10502 15.so.15.2[.0] + * 1.5.2rc01-03 15 10502 15.so.15.2[.0] + * 1.5.2 15 10502 15.so.15.2[.0] + * 1.5.3beta01-10 15 10503 15.so.15.3[.0] + * 1.5.3rc01-02 15 10503 15.so.15.3[.0] + * 1.5.3beta11 15 10503 15.so.15.3[.0] + * 1.5.3 [omitted] + * 1.5.4beta01-08 15 10504 15.so.15.4[.0] + * 1.5.4rc01 15 10504 15.so.15.4[.0] + * 1.5.4 15 10504 15.so.15.4[.0] + * 1.5.5beta01-08 15 10505 15.so.15.5[.0] + * 1.5.5rc01 15 10505 15.so.15.5[.0] + * 1.5.5 15 10505 15.so.15.5[.0] + * 1.5.6beta01-07 15 10506 15.so.15.6[.0] + * 1.5.6rc01-03 15 10506 15.so.15.6[.0] + * 1.5.6 15 10506 15.so.15.6[.0] + * 1.5.7beta01-05 15 10507 15.so.15.7[.0] + * 1.5.7rc01-03 15 10507 15.so.15.7[.0] + * 1.5.7 15 10507 15.so.15.7[.0] + * 1.6.0beta01-40 16 10600 16.so.16.0[.0] + * 1.6.0rc01-08 16 10600 16.so.16.0[.0] + * 1.6.0 16 10600 16.so.16.0[.0] + * 1.6.1beta01-09 16 10601 16.so.16.1[.0] + * 1.6.1rc01 16 10601 16.so.16.1[.0] + * 1.6.1 16 10601 16.so.16.1[.0] + * 1.6.2beta01 16 10602 16.so.16.2[.0] + * 1.6.2rc01-06 16 10602 16.so.16.2[.0] + * 1.6.2 16 10602 16.so.16.2[.0] + * 1.6.3beta01-11 16 10603 16.so.16.3[.0] + * 1.6.3rc01 16 10603 16.so.16.3[.0] + * 1.6.3 16 10603 16.so.16.3[.0] + * 1.6.4beta01-02 16 10604 16.so.16.4[.0] + * 1.6.4rc01 16 10604 16.so.16.4[.0] + * 1.6.4 16 10604 16.so.16.4[.0] + * 1.6.5 16 10605 16.so.16.5[.0] + * 1.6.6 16 10606 16.so.16.6[.0] + * 1.6.7beta01-04 16 10607 16.so.16.7[.0] + * 1.6.7rc01-02 16 10607 16.so.16.7[.0] + * 1.6.7 16 10607 16.so.16.7[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng-manual.txt or libpng.3 for more information. The PNG + * specification is available as a W3C Recommendation and as an ISO + * Specification, defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info * png_row_infop; +typedef png_row_info * * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +/* not used anywhere */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +/* Section 3: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, + (png_const_structrp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, + png_size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, + png_const_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), + PNG_ALLOCATED); + +/* DEPRECATED: this function allowed init structures to be created using the + * default allocation method (typically malloc). Use is deprecated in 1.6.0 and + * the API will be removed in the future. + */ +PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, + png_size_t png_info_struct_size), PNG_DEPRECATED); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structrp png_ptr, png_const_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* Convert to a US string format: there is no localization support in this + * routine. The original implementation used a 29 character buffer in + * png_struct, this will be removed in future versions. + */ +#if PNG_LIBPNG_VER < 10700 +/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ +PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED); +#endif +PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + const struct tm * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +#endif /* PNG_CONVERT_tIME_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, + int error_action, double red, double green)) +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)) + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels of + * a PNG file are returned when an alpha channel, or tRNS chunk in a palette + * file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel. The gamma encoded color channels must be + * scaled according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and reencode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. The + * advantage is that the color channels can be resampled (the image can be + * scaled) in this form. The disadvantage is that normal practice is to store + * linear, not (gamma) encoded, values and this requires 16-bit channels for + * still images rather than the 8-bit channels that are just about sufficient if + * gamma encoding is used. In addition all non-transparent pixel values, + * including completely opaque ones, must be gamma encoded to produce the final + * image. This is the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' mode (the + * latter being the two common names for associated alpha color channels.) + * + * Since it is not necessary to perform arithmetic on opaque color values so + * long as they are not to be resampled and are in the final color space it is + * possible to optimize the handling of alpha by storing the opaque pixels in + * the PNG format (adjusted for the output color space) while storing partially + * opaque pixels in the standard, linear, format. The accuracy required for + * standard alpha composition is relatively low, because the pixels are + * isolated, therefore typically the accuracy loss in storing 8-bit linear + * values is acceptable. (This is not true if the alpha channel is used to + * simulate transparency over large areas - use 16 bits or the PNG mode in + * this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is + * treated as opaque only if the alpha value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, + double output_gamma)) +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, + int mode, png_fixed_point output_gamma)) +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. The values used + * correspond to the normal numbers used to describe the overall gamma of a + * computer display system; for example 2.2 for an sRGB conformant system. The + * values are scaled by 100000 in the _fixed version of the API (so 220000 for + * sRGB.) + * + * The inverse of the value is always used to provide a default for the PNG file + * encoding if it has no gAMA chunk and if png_set_gamma() has not been called + * to override the PNG gamma information. + * + * When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode + * opaque pixels however pixels with lower alpha values are not encoded, + * regardless of the output gamma setting. + * + * When the standard Porter Duff handling is requested with mode 1 the output + * encoding is set to be linear and the output_gamma value is only relevant + * as a default for input data that has no gamma information. The linear output + * encoding will be overridden if png_set_gamma() is called - the results may be + * highly unexpected! + * + * The following numbers are derived from the sRGB standard and the research + * behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of + * 0.45455 (1/2.2) for PNG. The value implicitly includes any viewing + * correction required to take account of any differences in the color + * environment of the original scene and the intended display environment; the + * value expresses how to *decode* the image for display, not how the original + * data was *encoded*. + * + * sRGB provides a peg for the PNG standard by defining a viewing environment. + * sRGB itself, and earlier TV standards, actually use a more complex transform + * (a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is + * limited to simple power laws.) By saying that an image for direct display on + * an sRGB conformant system should be stored with a gAMA chunk value of 45455 + * (11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification + * makes it possible to derive values for other display systems and + * environments. + * + * The Mac value is deduced from the sRGB based on an assumption that the actual + * extra viewing correction used in early Mac display systems was implemented as + * a power 1.45 lookup table. + * + * Any system where a programmable lookup table is used or where the behavior of + * the final display device characteristics can be changed requires system + * specific code to obtain the current characteristic. However this can be + * difficult and most PNG gamma correction only requires an approximate value. + * + * By default, if png_set_alpha_mode() is not called, libpng assumes that all + * values are unencoded, linear, values and that the output device also has a + * linear characteristic. This is only very rarely correct - it is invariably + * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the + * default if you don't know what the right answer is! + * + * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS + * 10.6) which used a correction table to implement a somewhat lower gamma on an + * otherwise sRGB system. + * + * Both these values are reserved (not simple gamma values) in order to allow + * more precise correction internally in the future. + * + * NOTE: the following values can be passed to either the fixed or floating + * point APIs, but the floating point API will also accept floating point + * values. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceeded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the ouput gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, + png_uint_32 filler, int flags)); +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)) +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)) +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_const_uint_16p histogram, int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, + double screen_gamma, double override_file_gamma)) +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, + png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, + int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, + int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)) +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structrp png_ptr, int heuristic_method, int num_weights, + png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs)) +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +#ifdef PNG_WRITE_SUPPORTED +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, + int method)); +#endif + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, + (png_structrp png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, + int method)); +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* This callback is called only for *unknown* chunks. If + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known + * chunks to be treated as unknown, however in this case the callback must do + * any processing required by the chunk (e.g. by calling the appropriate + * png_set_ APIs.) + * + * There is no write support - on write, by default, all the chunks in the + * 'unknown' list are written in the specified position. + * + * The integer return from the callback function is interpreted thus: + * + * negative: An error occured, png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be saved. A critical + * chunk will cause an error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + * + * See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about + * how this behavior will change in libpng 1.7 + */ +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, + (png_const_structrp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, + png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application; this works on the png_info structure passed + * in, it does not change the state for other png_info structures. + * + * It is unlikely that this function works correctly as of 1.6.0 and using it + * may result either in memory leaks or double free of allocated data. + */ +PNG_EXPORTA(99, void, png_data_freer, (png_const_structrp png_ptr, + png_inforp info_ptr, int freer, png_uint_32 mask), PNG_DEPRECATED); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_FREE_UNKN 0x0200 +#endif +/* PNG_FREE_LIST 0x0400 removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); +PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, + png_voidp ptr), PNG_DEPRECATED); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Same, chunk name is prepended to message (only during read) */ +PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structrp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +#ifdef PNG_READ_SUPPORTED +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)) +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)) +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)) +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, + png_inforp info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *file_gamma)) +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_file_gamma)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, + png_inforp info_ptr, double file_gamma)) +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_file_gamma)) +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, + png_int_32 *X1, int *type, int *nparams, png_charp *units, + png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, + png_inforp info_ptr, png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, + png_inforp info_ptr, png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, + png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *unit, double *width, double *height)) +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, double width, double height)) +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, png_fixed_point width, + png_fixed_point height)) +PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, + png_const_charp swidth, png_const_charp sheight)); +#endif /* PNG_sCAL_SUPPORTED */ + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +/* Provide the default handling for all unknown chunks or, optionally, for + * specific unknown chunks. + * + * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was + * ignored and the default was used, the per-chunk setting only had an effect on + * write. If you wish to have chunk-specific handling on read in code that must + * work on earlier versions you must use a user chunk callback to specify the + * desired handling (keep or discard.) + * + * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The + * parameter is interpreted as follows: + * + * READ: + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Known chunks: do normal libpng processing, do not keep the chunk (but + * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + * Unknown chunks: for a specific chunk use the global default, when used + * as the default discard the chunk data. + * PNG_HANDLE_CHUNK_NEVER: + * Discard the chunk data. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Keep the chunk data if the chunk is not critical else raise a chunk + * error. + * PNG_HANDLE_CHUNK_ALWAYS: + * Keep the chunk data. + * + * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, + * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent + * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks + * it simply resets the behavior to the libpng default. + * + * INTERACTION WTIH USER CHUNK CALLBACKS: + * The per-chunk handling is always used when there is a png_user_chunk_ptr + * callback and the callback returns 0; the chunk is then always stored *unless* + * it is critical and the per-chunk setting is other than ALWAYS. Notice that + * the global default is *not* used in this case. (In effect the per-chunk + * value is incremented to at least IF_SAFE.) + * + * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and + * per-chunk defaults will be honored. If you want to preserve the current + * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE + * as the default - if you don't do this libpng 1.6 will issue a warning. + * + * If you want unhandled unknown chunks to be discarded in libpng 1.6 and + * earlier simply return '1' (handled). + * + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: + * If this is *not* set known chunks will always be handled by libpng and + * will never be stored in the unknown chunk list. Known chunks listed to + * png_set_keep_unknown_chunks will have no effect. If it is set then known + * chunks listed with a keep other than AS_DEFAULT will *never* be processed + * by libpng, in addition critical chunks must either be processed by the + * callback or saved. + * + * The IHDR and IEND chunks must not be listed. Because this turns off the + * default handling for chunks that would otherwise be recognized the + * behavior of libpng transformations may well become incorrect! + * + * WRITE: + * When writing chunks the options only apply to the chunks specified by + * png_set_unknown_chunks (below), libpng will *always* write known chunks + * required by png_set_ calls and will always write the core critical chunks + * (as required for PLTE). + * + * Each chunk in the png_set_unknown_chunks list is looked up in the + * png_set_keep_unknown_chunks list to find the keep setting, this is then + * interpreted as follows: + * + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Write safe-to-copy chunks and write other chunks if the global + * default is set to _ALWAYS, otherwise don't write this chunk. + * PNG_HANDLE_CHUNK_NEVER: + * Do not write the chunk. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Write the chunk if it is safe-to-copy, otherwise do not write it. + * PNG_HANDLE_CHUNK_ALWAYS: + * Write the chunk. + * + * Note that the default behavior is effectively the opposite of the read case - + * in read unknown chunks are not stored by default, in write they are written + * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different + * - on write the safe-to-copy bit is checked, on read the critical bit is + * checked and on read if the chunk is critical an error will be raised. + * + * num_chunks: + * =========== + * If num_chunks is positive, then the "keep" parameter specifies the manner + * for handling only those chunks appearing in the chunk_list array, + * otherwise the chunk list array is ignored. + * + * If num_chunks is 0 the "keep" parameter specifies the default behavior for + * unknown chunks, as described above. + * + * If num_chunks is negative, then the "keep" parameter specifies the manner + * for handling all unknown chunks plus all chunks recognized by libpng + * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to + * be processed by libpng. + */ +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, + int keep, png_const_bytep chunk_list, int num_chunks)); + +/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; + * the result is therefore true (non-zero) if special handling is required, + * false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, + png_const_bytep chunk_name)); +#endif + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); + /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added + * unknowns to the location currently stored in the png_struct. This is + * invariably the wrong value on write. To fix this call the following API + * for each chunk in the list with the correct location. If you know your + * code won't be compiled on earlier versions you can rely on + * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing + * the correct thing. + */ + +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); + +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, + png_inforp info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structrp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structrp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structrp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structrp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_LAST 4 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structrp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structrp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, + png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); + +/* Removed from libpng 1.6; use png_get_io_chunk_type. */ +PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), + PNG_DEPRECATED) + +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structrp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ + (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535) +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define PNG_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define PNG_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define PNG_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ + : (png_int_32)png_get_uint_32(buf))) + + /* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ +# ifndef PNG_PREFIX +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) +# endif +#else +# ifdef PNG_PREFIX + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) +# endif +#endif + +/******************************************************************************* + * SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt (TODO: write said + * documentation) if you don't understand what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accomodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancillary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack and set the + * version field to PNG_IMAGE_VERSION. + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required sample format. + * 4) Allocate a buffer for the image and, if required, the color-map. + * 5) Call png_image_finish_read to read the image and, if required, the + * color-map into your buffers. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. The only caveat is that if you + * request a color-mapped image from a PNG that is full-color or makes + * complex use of an alpha channel the transformation is extremely lossy and the + * result may look terrible. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image samples. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image and, if necessary, the color-map to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or defines the in-memory format of an image that you + * need to write: + */ +#define PNG_IMAGE_VERSION 1 + +typedef struct png_control *png_controlp; +typedef struct +{ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_uint_32 colormap_entries; + /* Number of entries in the color-map */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * The upper 30 bits of this value are reserved, the low two bits contain + * a value as follows: + */ +# define PNG_IMAGE_WARNING 1 +# define PNG_IMAGE_ERROR 2 + /* + * The result is a two bit code such that a value more than 1 indicates + * a failure in the API just called: + * + * 0 - no warning or error + * 1 - warning + * 2 - error + * 3 - error preceded by warning + */ +# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) + + png_uint_32 warning_or_error; + + char message[64]; +} png_image, *png_imagep; + +/* The samples of the image have one to four channels whose components have + * original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The components are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a single byte. For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a 2-byte integer. All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When the simplified API needs to convert between sRGB and linear colorspaces, + * the actual sRGB transfer curve defined in the sRGB specification (see the + * article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 + * approximation used elsewhere in libpng. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + * + * The samples are either contained directly in the image data, between 1 and 8 + * bytes per pixel according to the encoding, or are held in a color-map indexed + * by bytes in the image data. In the case of a color-map the color-map entries + * are individual samples, encoded as above, and the image data has one byte per + * pixel to select the relevant sample from the color-map. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of sample data and, if present, alpha values. There are + * separate defines for each of the two component encodings. + * + * A format is built up using single bit flag values. All combinations are + * valid. Formats can be built up from the flag values or you can use one of + * the predefined values below. When testing formats always use the FORMAT_FLAG + * macros to test for individual features - future versions of the library may + * add new flags. + * + * When reading or writing color-mapped images the format should be set to the + * format of the entries in the color-map then png_image_{read,write}_colormap + * called to read or write the color-map and set the format correctly for the + * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + * + * NOTE: libpng can be built with particular features disabled, if you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of the appropriate + * "_SUPPORTED" macro, one of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2 byte channels else 1 byte */ +#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ +#endif + +/* Commonly used formats have predefined macros. + * + * First the single byte (sRGB) formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear 2-byte formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* With color-mapped formats the image data is one byte for each pixel, the byte + * is an index into the color-map which is formatted as above. To obtain a + * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP + * to one of the above definitions, or you can use one of the definitions below. + */ +#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image + * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the + * actual image sample values - either the entries in the color-map or the + * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values + * for the pixels and will always return 1 for color-mapped formats. The + * remaining macros return information about the rows in the image and the + * complete image. + * + * NOTE: All the macros that take a png_image::format parameter are compile time + * constants if the format parameter is, itself, a constant. Therefore these + * macros can be used in array declarations and case labels where required. + * Similarly the macros are also pre-processor constants (sizeof is not used) so + * they can be used in #if tests. + * + * First the information about the samples. + */ +#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ + (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ + ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) + /* Return the size in bytes of a single component of a pixel or color-map + * entry (as appropriate) in the image: 1 or 2. + */ + +#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) + /* This is the size of the sample data for one sample. If the image is + * color-mapped it is the size of one color-map entry (and image pixels are + * one byte in size), otherwise it is the size of one image pixel. + */ + +#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) + /* The maximum size of the color-map required by the format expressed in a + * count of components. This can be used to compile-time allocate a + * color-map: + * + * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + * + * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + * + * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + * information from one of the png_image_begin_read_ APIs and dynamically + * allocate the required memory. + */ + +/* Corresponding information about the pixels */ +#define PNG_IMAGE_PIXEL_(test,fmt)\ + (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) + +#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) + /* The number of separate channels (components) in a pixel; 1 for a + * color-mapped image. + */ + +#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) + /* The size, in bytes, of each component in a pixel; 1 for a color-mapped + * image. + */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) + /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ + +/* Information about the whole row, or whole image */ +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. For a color-mapped image this is the minimum number of bytes in a + * row. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) + /* Return the size, in bytes, of an image buffer given a png_image and a row + * stride - the number of components to leave space for in each row. + */ + +#define PNG_IMAGE_SIZE(image)\ + PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) + /* Return the size, in bytes, of the image in memory given just a png_image; + * the row stride is the minimum stride required for the image. + */ + +#define PNG_IMAGE_COLORMAP_SIZE(image)\ + (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) + /* Return the size, in bytes, of the color-map of this image. If the image + * format is not a color-map format this will return a size sufficient for + * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + * you don't want to allocate a color-map in this case. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 + /* This indicates the the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#define PNG_IMAGE_FLAG_FAST 0x02 + /* On write emphasise speed over compression; the resultant PNG file will be + * larger but will be produced significantly faster, particular for large + * images. Do not use this option for images which will be distributed, only + * used it when producing intermediate files that will be read back in + * repeatedly. For a typical 24-bit image the option will double the read + * speed at the cost of increasing the image size by 25%, however for many + * more compressible images the PNG file can be 10 times larger with only a + * slight speed gain. + */ + +#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 + /* On read if the image is a 16-bit per component image and there is no gAMA + * or sRGB chunk assume that the components are sRGB encoded. Notice that + * images output by the simplified API always have gamma information; setting + * this flag only affects the interpretation of 16-bit images from an + * external source. It is recommended that the application expose this flag + * to the user; the user can normally easily recognize the difference between + * linear and sRGB encoding. This flag has no effect on write - the data + * passed to the write APIs must have the correct encoding (as defined + * above.) + * + * If the flag is not set (the default) input 16-bit per component data is + * assumed to be linear. + * + * NOTE: the flag can only be set after the png_image_begin_read_ call, + * because that call initializes the 'flags' field. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* PNG_STDIO_SUPPORTED */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, png_size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_const_colorp background, void *buffer, png_int_32 row_stride, + void *colormap)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in byte or 2-byte units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * background must be supplied when an alpha channel must be removed from a + * single byte color-mapped output format, in other words if: + * + * 1) The original format from png_image_begin_read_from_* had + * PNG_FORMAT_FLAG_ALPHA set. + * 2) The format set by the application does not. + * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and + * PNG_FORMAT_FLAG_LINEAR *not* set. + * + * For linear output removing the alpha channel is always done by compositing + * on black and background is ignored. + * + * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must + * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. + * image->colormap_entries will be updated to the actual number of entries + * written to the colormap; this may be less than the original value. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +#ifdef PNG_STDIO_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written. To do this use memset to set the whole structure to 0 then + * initialize fields describing your image. + * + * version: must be set to PNG_IMAGE_VERSION + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data (image and color-map) you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + * colormap_entries: set to the number of entries in the color-map (0 to 256) + */ +PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride, + const void *colormap)); + /* Write the image to the given (FILE*). */ + +/* With both write APIs if image is in one of the linear formats with 16-bit + * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG + * gamma encoded according to the sRGB specification, otherwise a 16-bit linear + * encoded PNG file is written. + * + * With color-mapped data formats the colormap parameter point to a color-map + * with at least image->colormap_entries encoded in the specified format. If + * the format is linear the written PNG color-map will be converted to sRGB + * regardless of the convert_to_8_bit flag. + * + * With all APIs row_stride is handled as in the read APIs - it is the spacing + * from one row to the next in component sized units (1 or 2 bytes) and if + * negative indicates a bottom-up row layout in the buffer. + * + * Note that the write API does not support interlacing or sub-8-bit pixels. + */ +#endif /* PNG_STDIO_SUPPORTED */ +#endif /* PNG_SIMPLIFIED_WRITE_SUPPORTED */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, + png_const_infop info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + +/******************************************************************************* + * IMPLEMENTATION OPTIONS + ******************************************************************************* + * + * Support for arbitrary implementation-specific optimizations. The API allows + * particular options to be turned on or off. 'Option' is the number of the + * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given + * by the PNG_OPTION_ defines below. + * + * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions, + * are detected at run time, however sometimes it may be impossible + * to do this in user mode, in which case it is necessary to discover + * the capabilities in an OS specific way. Such capabilities are + * listed here when libpng has support for them and must be turned + * ON by the application if present. + * + * SOFTWARE: sometimes software optimizations actually result in performance + * decrease on some architectures or systems, or with some sets of + * PNG images. 'Software' options allow such optimizations to be + * selected at run time. + */ +#ifdef PNG_SET_OPTION_SUPPORTED +#ifdef PNG_ARM_NEON_API_SUPPORTED +# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ +#endif +#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ +#define PNG_OPTION_NEXT 4 /* Next option - numbers must be even */ + +/* Return values: NOTE: there are four values and 'off' is *not* zero */ +#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ +#define PNG_OPTION_INVALID 1 /* Option number out of range */ +#define PNG_OPTION_OFF 2 +#define PNG_OPTION_ON 3 + +PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, + int onoff)); +#endif + +/******************************************************************************* + * END OF HARDWARE OPTIONS + ******************************************************************************/ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs, scripts/pnglibconf.h, and scripts/pnglibconf.h.prebuilt + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) Maintainer, remember to add an entry to + * scripts/symbols.def as well. + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(244); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/ext/libpng16/pngconf.h b/ext/libpng16/pngconf.h new file mode 100644 index 0000000000..e9a3f3b654 --- /dev/null +++ b/ext/libpng16/pngconf.h @@ -0,0 +1,617 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.6.7 - November 14, 2013 + * + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +/* To do: Do all of this in scripts/pnglibconf.dfa */ +#ifdef PNG_SAFE_LIMITS_SUPPORTED +# ifdef PNG_USER_WIDTH_MAX +# undef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000L +# endif +# ifdef PNG_USER_HEIGHT_MAX +# undef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000L +# endif +# ifdef PNG_USER_CHUNK_MALLOC_MAX +# undef PNG_USER_CHUNK_MALLOC_MAX +# define PNG_USER_CHUNK_MALLOC_MAX 4000000L +# endif +# ifdef PNG_USER_CHUNK_CACHE_MAX +# undef PNG_USER_CHUNK_CACHE_MAX +# define PNG_USER_CHUNK_CACHE_MAX 128 +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ + +/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C + * compiler for correct compilation. The following header files are required by + * the standard. If your compiler doesn't provide these header files, or they + * do not match the standard, you will need to provide/improve them. + */ +#include +#include + +/* Library header files. These header files are all defined by ISOC90; libpng + * expects conformant implementations, however, an ISOC90 conformant system need + * not provide these header files if the functionality cannot be implemented. + * In this case it will be necessary to disable the relevant parts of libpng in + * the build of pnglibconf.h. + * + * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not + * include this unnecessary header file. + */ + +#ifdef PNG_STDIO_SUPPORTED + /* Required for the definition of FILE: */ +# include +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Required for the definition of jmp_buf and the declaration of longjmp: */ +# include +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* Required for struct tm: */ +# include +#endif + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using + * PNG_NO_CONST; this is no longer supported except for data declarations which + * apparently still cause problems in 2011 on some compilers. + */ +#define PNG_CONST const /* backward compatibility only */ + +/* This controls optimization of the reading of 16 and 32 bit values + * from PNG files. It can be set on a per-app-file basis - it + * just changes whether a macro is used when the function is called. + * The library builder sets the default; if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect + * against legacy (pre ISOC90) compilers that did not understand function + * prototypes. It is not required for modern C compilers. + */ +#ifndef PNGARG +# define PNGARG(arglist) arglist +#endif + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows sytems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ + defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) + /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or + * MinGW on any architecture currently supported by Windows. Also includes + * Watcom builds but these need special treatment because they are not + * compatible with GCC or Visual C because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) +# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ +#ifndef PNG_EXPORTA + +# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ + PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ + extern attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args)\ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available, incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. Disabling these removes the warnings but may also produce + * less efficient code. + */ +# if defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if __GNUC__ >= 3 +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# if ((__GNUC__ != 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* __GNUC__ == 3.0 */ +# endif /* __GNUC__ >= 3 */ + +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# ifndef PNG_RESTRICT +# if (_MSC_VER >= 1400) +# define PNG_RESTRICT __restrict +# endif +# endif + +# elif defined(__WATCOMC__) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* _MSC_VER */ +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_RESTRICT +# define PNG_RESTRICT /* The C99 "restrict" feature */ +#endif +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* Some typedefs to get us started. These should be safe on most of the common + * platforms. + * + * png_uint_32 and png_int_32 may, currently, be larger than required to hold a + * 32-bit value however this is not normally advisable. + * + * png_uint_16 and png_int_16 should always be two bytes in size - this is + * verified at library build time. + * + * png_byte must always be one byte in size. + * + * The checks below use constants from limits.h, as defined by the ISOC90 + * standard. + */ +#if CHAR_BIT == 8 && UCHAR_MAX == 255 + typedef unsigned char png_byte; +#else +# error "libpng requires 8 bit bytes" +#endif + +#if INT_MIN == -32768 && INT_MAX == 32767 + typedef int png_int_16; +#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 + typedef short png_int_16; +#else +# error "libpng requires a signed 16 bit type" +#endif + +#if UINT_MAX == 65535 + typedef unsigned int png_uint_16; +#elif USHRT_MAX == 65535 + typedef unsigned short png_uint_16; +#else +# error "libpng requires an unsigned 16 bit type" +#endif + +#if INT_MIN < -2147483646 && INT_MAX > 2147483646 + typedef int png_int_32; +#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 + typedef long int png_int_32; +#else +# error "libpng requires a signed 32 bit (or more) type" +#endif + +#if UINT_MAX > 4294967294 + typedef unsigned int png_uint_32; +#elif ULONG_MAX > 4294967294 + typedef unsigned long int png_uint_32; +#else +# error "libpng requires an unsigned 32 bit (or more) type" +#endif + +/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, + * requires an ISOC90 compiler and relies on consistent behavior of sizeof. + */ +typedef size_t png_size_t; +typedef ptrdiff_t png_ptrdiff_t; + +/* libpng needs to know the maximum value of 'size_t' and this controls the + * definition of png_alloc_size_t, below. This maximum value of size_t limits + * but does not control the maximum allocations the library makes - there is + * direct application control of this through png_set_user_limits(). + */ +#ifndef PNG_SMALL_SIZE_T + /* Compiler specific tests for systems where size_t is known to be less than + * 32 bits (some of these systems may no longer work because of the lack of + * 'far' support; see above.) + */ +# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ + (defined(_MSC_VER) && defined(MAXSEG_64K)) +# define PNG_SMALL_SIZE_T +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no + * smaller than png_uint_32. Casts from png_size_t or png_uint_32 to + * png_alloc_size_t are not necessary; in fact, it is recommended not to use + * them at all so that the compiler can complain when something turns out to be + * problematic. + * + * Casts in the other direction (from png_alloc_size_t to png_size_t or + * png_uint_32) should be explicitly applied; however, we do not expect to + * encounter practical situations that require such conversions. + * + * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than + * 4294967295 - i.e. less than the maximum value of png_uint_32. + */ +#ifdef PNG_SMALL_SIZE_T + typedef png_uint_32 png_alloc_size_t; +#else + typedef png_size_t png_alloc_size_t; +#endif + +/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler + * implementations of Intel CPU specific support of user-mode segmented address + * spaces, where 16-bit pointers address more than 65536 bytes of memory using + * separate 'segment' registers. The implementation requires two different + * types of pointer (only one of which includes the segment value.) + * + * If required this support is available in version 1.2 of libpng and may be + * available in versions through 1.5, although the correctness of the code has + * not been verified recently. + */ + +/* Typedef for floating-point numbers that are converted to fixed-point with a + * multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void * png_voidp; +typedef const void * png_const_voidp; +typedef png_byte * png_bytep; +typedef const png_byte * png_const_bytep; +typedef png_uint_32 * png_uint_32p; +typedef const png_uint_32 * png_const_uint_32p; +typedef png_int_32 * png_int_32p; +typedef const png_int_32 * png_const_int_32p; +typedef png_uint_16 * png_uint_16p; +typedef const png_uint_16 * png_const_uint_16p; +typedef png_int_16 * png_int_16p; +typedef const png_int_16 * png_const_int_16p; +typedef char * png_charp; +typedef const char * png_const_charp; +typedef png_fixed_point * png_fixed_point_p; +typedef const png_fixed_point * png_const_fixed_point_p; +typedef png_size_t * png_size_tp; +typedef const png_size_t * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * png_doublep; +typedef const double * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte * * png_bytepp; +typedef png_uint_32 * * png_uint_32pp; +typedef png_int_32 * * png_int_32pp; +typedef png_uint_16 * * png_uint_16pp; +typedef png_int_16 * * png_int_16pp; +typedef const char * * png_const_charpp; +typedef char * * png_charpp; +typedef png_fixed_point * * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char * * * png_charppp; + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +#endif /* PNGCONF_H */ diff --git a/ext/libpng16/pngdebug.h b/ext/libpng16/pngdebug.h new file mode 100644 index 0000000000..96c1ea42b3 --- /dev/null +++ b/ext/libpng16/pngdebug.h @@ -0,0 +1,157 @@ + +/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c + * + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + * + * png_debug[1-2]?(level, message ,arg{0-2}) + * Expands to a statement (either a simple expression or a compound + * do..while(0) statement) that outputs a message with parameter + * substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG + * is undefined, 0 or 1 every png_debug expands to a simple expression + * (actually ((void)0)). + * + * level: level of detail of message, starting at 0. A level 'n' + * message is preceded by 'n' tab characters (not implemented + * on Microsoft compilers unless PNG_DEBUG_FILE is also + * defined, to allow debug DLL compilation with no standard IO). + * message: a printf(3) style text string. A trailing '\n' is added + * to the message. + * arg: 0 to 2 arguments for printf(3) style substitution in message. + */ +#ifndef PNGDEBUG_H +#define PNGDEBUG_H +/* These settings control the formatting of messages in png.c and pngerror.c */ +/* Moved to pngdebug.h at 1.5.0 */ +# ifndef PNG_LITERAL_SHARP +# define PNG_LITERAL_SHARP 0x23 +# endif +# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET +# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b +# endif +# ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET +# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d +# endif +# ifndef PNG_STRING_NEWLINE +# define PNG_STRING_NEWLINE "\n" +# endif + +#ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +# include +# if (PNG_DEBUG > 1) +# ifndef _DEBUG +# define _DEBUG +# endif +# ifndef png_debug +# define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) +# endif +# endif +# else /* PNG_DEBUG_FILE || !_MSC_VER */ +# ifndef PNG_STDIO_SUPPORTED +# include /* not included yet */ +# endif +# ifndef PNG_DEBUG_FILE +# define PNG_DEBUG_FILE stderr +# endif /* PNG_DEBUG_FILE */ + +# if (PNG_DEBUG > 1) +/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on + * non-ISO compilers + */ +# ifdef __STDC__ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ + } while (0) +# endif +# else /* __STDC __ */ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1,p2); \ + } while (0) +# endif +# endif /* __STDC __ */ +# endif /* (PNG_DEBUG > 1) */ + +# endif /* _MSC_VER */ +# endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +# define png_debug(l, m) ((void)0) +#endif +#ifndef png_debug1 +# define png_debug1(l, m, p1) ((void)0) +#endif +#ifndef png_debug2 +# define png_debug2(l, m, p1, p2) ((void)0) +#endif +#endif /* PNGDEBUG_H */ diff --git a/ext/libpng16/pngerror.c b/ext/libpng16/pngerror.c new file mode 100644 index 0000000000..c71e2ab559 --- /dev/null +++ b/ext/libpng16/pngerror.c @@ -0,0 +1,932 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * Last changed in libpng 1.6.1 [March 28, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr, + png_const_charp error_message)),PNG_NORETURN); + +#ifdef PNG_WARNINGS_SUPPORTED +static void /* PRIVATE */ +png_default_warning PNGARG((png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +#ifdef PNG_ERROR_TEXT_SUPPORTED +PNG_FUNCTION(void,PNGAPI +png_error,(png_const_structrp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr != NULL) + { + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + for (offset = 1; offset<15; offset++) + if (error_message[offset] == ' ') + break; + + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i = 0; i < offset - 1; i++) + msg[i] = error_message[i + 1]; + msg[i - 1] = '\0'; + error_message = msg; + } + + else + error_message += offset; + } + + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0] = '0'; + msg[1] = '\0'; + error_message = msg; + } + } + } + } +#endif + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), + error_message); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, error_message); +} +#else +PNG_FUNCTION(void,PNGAPI +png_err,(png_const_structrp png_ptr),PNG_NORETURN) +{ + /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed + * erroneously as '\0', instead of the empty string "". This was + * apparently an error, introduced in libpng-1.2.20, and png_default_error + * will crash in this case. + */ + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), ""); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, ""); +} +#endif /* PNG_ERROR_TEXT_SUPPORTED */ + +/* Utility to safely appends strings to a buffer. This never errors out so + * error checking is not required in the caller. + */ +size_t +png_safecat(png_charp buffer, size_t bufsize, size_t pos, + png_const_charp string) +{ + if (buffer != NULL && pos < bufsize) + { + if (string != NULL) + while (*string != '\0' && pos < bufsize-1) + buffer[pos++] = *string++; + + buffer[pos] = '\0'; + } + + return pos; +} + +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) +/* Utility to dump an unsigned value into a buffer, given a start pointer and + * and end pointer (which should point just *beyond* the end of the buffer!) + * Returns the pointer to the start of the formatted string. + */ +png_charp +png_format_number(png_const_charp start, png_charp end, int format, + png_alloc_size_t number) +{ + int count = 0; /* number of digits output */ + int mincount = 1; /* minimum number required */ + int output = 0; /* digit output (for the fixed point format) */ + + *--end = '\0'; + + /* This is written so that the loop always runs at least once, even with + * number zero. + */ + while (end > start && (number != 0 || count < mincount)) + { + + static const char digits[] = "0123456789ABCDEF"; + + switch (format) + { + case PNG_NUMBER_FORMAT_fixed: + /* Needs five digits (the fraction) */ + mincount = 5; + if (output || number % 10 != 0) + { + *--end = digits[number % 10]; + output = 1; + } + number /= 10; + break; + + case PNG_NUMBER_FORMAT_02u: + /* Expects at least 2 digits. */ + mincount = 2; + /* FALL THROUGH */ + + case PNG_NUMBER_FORMAT_u: + *--end = digits[number % 10]; + number /= 10; + break; + + case PNG_NUMBER_FORMAT_02x: + /* This format expects at least two digits */ + mincount = 2; + /* FALL THROUGH */ + + case PNG_NUMBER_FORMAT_x: + *--end = digits[number & 0xf]; + number >>= 4; + break; + + default: /* an error */ + number = 0; + break; + } + + /* Keep track of the number of digits added */ + ++count; + + /* Float a fixed number here: */ + if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start) + { + /* End of the fraction, but maybe nothing was output? In that case + * drop the decimal point. If the number is a true zero handle that + * here. + */ + if (output) + *--end = '.'; + else if (number == 0) /* and !output */ + *--end = '0'; + } + } + + return end; +} +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called whenever there is a non-fatal error. This function + * should not be changed. If there is a need to handle warnings differently, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_const_structrp png_ptr, png_const_charp warning_message) +{ + int offset = 0; + if (png_ptr != NULL) + { +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*warning_message == PNG_LITERAL_SHARP) + { + for (offset = 1; offset < 15; offset++) + if (warning_message[offset] == ' ') + break; + } + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr), + warning_message + offset); + else + png_default_warning(png_ptr, warning_message + offset); +} + +/* These functions support 'formatted' warning messages with up to + * PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter + * is introduced by @, where 'number' starts at 1. This follows the + * standard established by X/Open for internationalizable error messages. + */ +void +png_warning_parameter(png_warning_parameters p, int number, + png_const_charp string) +{ + if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) + (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); +} + +void +png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, + png_alloc_size_t value) +{ + char buffer[PNG_NUMBER_BUFFER_SIZE]; + png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); +} + +void +png_warning_parameter_signed(png_warning_parameters p, int number, int format, + png_int_32 value) +{ + png_alloc_size_t u; + png_charp str; + char buffer[PNG_NUMBER_BUFFER_SIZE]; + + /* Avoid overflow by doing the negate in a png_alloc_size_t: */ + u = (png_alloc_size_t)value; + if (value < 0) + u = ~u + 1; + + str = PNG_FORMAT_NUMBER(buffer, format, u); + + if (value < 0 && str > buffer) + *--str = '-'; + + png_warning_parameter(p, number, str); +} + +void +png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, + png_const_charp message) +{ + /* The internal buffer is just 192 bytes - enough for all our messages, + * overflow doesn't happen because this code checks! If someone figures + * out how to send us a message longer than 192 bytes, all that will + * happen is that the message will be truncated appropriately. + */ + size_t i = 0; /* Index in the msg[] buffer: */ + char msg[192]; + + /* Each iteration through the following loop writes at most one character + * to msg[i++] then returns here to validate that there is still space for + * the trailing '\0'. It may (in the case of a parameter) read more than + * one character from message[]; it must check for '\0' and continue to the + * test if it finds the end of string. + */ + while (i<(sizeof msg)-1 && *message != '\0') + { + /* '@' at end of string is now just printed (previously it was skipped); + * it is an error in the calling code to terminate the string with @. + */ + if (p != NULL && *message == '@' && message[1] != '\0') + { + int parameter_char = *++message; /* Consume the '@' */ + static const char valid_parameters[] = "123456789"; + int parameter = 0; + + /* Search for the parameter digit, the index in the string is the + * parameter to use. + */ + while (valid_parameters[parameter] != parameter_char && + valid_parameters[parameter] != '\0') + ++parameter; + + /* If the parameter digit is out of range it will just get printed. */ + if (parameter < PNG_WARNING_PARAMETER_COUNT) + { + /* Append this parameter */ + png_const_charp parm = p[parameter]; + png_const_charp pend = p[parameter] + (sizeof p[parameter]); + + /* No need to copy the trailing '\0' here, but there is no guarantee + * that parm[] has been initialized, so there is no guarantee of a + * trailing '\0': + */ + while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend) + msg[i++] = *parm++; + + /* Consume the parameter digit too: */ + ++message; + continue; + } + + /* else not a parameter and there is a character after the @ sign; just + * copy that. This is known not to be '\0' because of the test above. + */ + } + + /* At this point *message can't be '\0', even in the bad parameter case + * above where there is a lone '@' at the end of the message string. + */ + msg[i++] = *message++; + } + + /* i is always less than (sizeof msg), so: */ + msg[i] = '\0'; + + /* And this is the formatted message. It may be larger than + * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these + * are not (currently) formatted. + */ + png_warning(png_ptr, msg); +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_benign_error(png_const_structrp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + { +# ifdef PNG_READ_SUPPORTED + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + png_ptr->chunk_name != 0) + png_chunk_warning(png_ptr, error_message); + else +# endif + png_warning(png_ptr, error_message); + } + + else + { +# ifdef PNG_READ_SUPPORTED + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + png_ptr->chunk_name != 0) + png_chunk_error(png_ptr, error_message); + else +# endif + png_error(png_ptr, error_message); + } +} + +void /* PRIVATE */ +png_app_warning(png_const_structrp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); +} + +void /* PRIVATE */ +png_app_error(png_const_structrp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); +} +#endif /* BENIGN_ERRORS */ + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; + +#define PNG_MAX_ERROR_TEXT 196 /* Currently limited be profile_error in png.c */ +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) +static void /* PRIVATE */ +png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp + error_message) +{ + png_uint_32 chunk_name = png_ptr->chunk_name; + int iout = 0, ishift = 24; + + while (ishift >= 0) + { + int c = (int)(chunk_name >> ishift) & 0xff; + + ishift -= 8; + if (isnonalpha(c)) + { + buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; + } + + else + { + buffer[iout++] = (char)c; + } + } + + if (error_message == NULL) + buffer[iout] = '\0'; + + else + { + int iin = 0; + + buffer[iout++] = ':'; + buffer[iout++] = ' '; + + while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0') + buffer[iout++] = error_message[iin++]; + + /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */ + buffer[iout] = '\0'; + } +} +#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_FUNCTION(void,PNGAPI +png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_error(png_ptr, error_message); + + else + { + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); + } +} +#endif /* PNG_READ_SUPPORTED && PNG_ERROR_TEXT_SUPPORTED */ + +#ifdef PNG_WARNINGS_SUPPORTED +void PNGAPI +png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_warning(png_ptr, warning_message); + + else + { + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); + } +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_READ_SUPPORTED +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp + error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_chunk_warning(png_ptr, error_message); + + else + png_chunk_error(png_ptr, error_message); +} +#endif +#endif /* PNG_READ_SUPPORTED */ + +void /* PRIVATE */ +png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error) +{ + /* This is always supported, but for just read or just write it + * unconditionally does the right thing. + */ +# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) + if (png_ptr->mode & PNG_IS_READ_STRUCT) +# endif + +# ifdef PNG_READ_SUPPORTED + { + if (error < PNG_CHUNK_ERROR) + png_chunk_warning(png_ptr, message); + + else + png_chunk_benign_error(png_ptr, message); + } +# endif + +# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) + else if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) +# endif + +# ifdef PNG_WRITE_SUPPORTED + { + if (error < PNG_CHUNK_WRITE_ERROR) + png_app_warning(png_ptr, message); + + else + png_app_error(png_ptr, message); + } +# endif +} + +#ifdef PNG_ERROR_TEXT_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_FUNCTION(void, +png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN) +{ +# define fixed_message "fixed point overflow in " +# define fixed_message_ln ((sizeof fixed_message)-1) + int iin; + char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; + memcpy(msg, fixed_message, fixed_message_ln); + iin = 0; + if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) + { + msg[fixed_message_ln + iin] = name[iin]; + ++iin; + } + msg[fixed_message_ln + iin] = 0; + png_error(png_ptr, msg); +} +#endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This API only exists if ANSI-C style error handling is used, + * otherwise it is necessary for png_default_error to be overridden. + */ +jmp_buf* PNGAPI +png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn, + size_t jmp_buf_size) +{ + /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value + * and it must not change after that. Libpng doesn't care how big the + * buffer is, just that it doesn't change. + * + * If the buffer size is no *larger* than the size of jmp_buf when libpng is + * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0 + * semantics that this call will not fail. If the size is larger, however, + * the buffer is allocated and this may fail, causing the function to return + * NULL. + */ + if (png_ptr == NULL) + return NULL; + + if (png_ptr->jmp_buf_ptr == NULL) + { + png_ptr->jmp_buf_size = 0; /* not allocated */ + + if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local)) + png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; + + else + { + png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *, + png_malloc_warn(png_ptr, jmp_buf_size)); + + if (png_ptr->jmp_buf_ptr == NULL) + return NULL; /* new NULL return on OOM */ + + png_ptr->jmp_buf_size = jmp_buf_size; + } + } + + else /* Already allocated: check the size */ + { + size_t size = png_ptr->jmp_buf_size; + + if (size == 0) + { + size = (sizeof png_ptr->jmp_buf_local); + if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local) + { + /* This is an internal error in libpng: somehow we have been left + * with a stack allocated jmp_buf when the application regained + * control. It's always possible to fix this up, but for the moment + * this is a png_error because that makes it easy to detect. + */ + png_error(png_ptr, "Libpng jmp_buf still allocated"); + /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */ + } + } + + if (size != jmp_buf_size) + { + png_warning(png_ptr, "Application jmp_buf size changed"); + return NULL; /* caller will probably crash: no choice here */ + } + } + + /* Finally fill in the function, now we have a satisfactory buffer. It is + * valid to change the function on every call. + */ + png_ptr->longjmp_fn = longjmp_fn; + return png_ptr->jmp_buf_ptr; +} + +void /* PRIVATE */ +png_free_jmpbuf(png_structrp png_ptr) +{ + if (png_ptr != NULL) + { + jmp_buf *jb = png_ptr->jmp_buf_ptr; + + /* A size of 0 is used to indicate a local, stack, allocation of the + * pointer; used here and in png.c + */ + if (jb != NULL && png_ptr->jmp_buf_size > 0) + { + + /* This stuff is so that a failure to free the error control structure + * does not leave libpng in a state with no valid error handling: the + * free always succeeds, if there is an error it gets ignored. + */ + if (jb != &png_ptr->jmp_buf_local) + { + /* Make an internal, libpng, jmp_buf to return here */ + jmp_buf free_jmp_buf; + + if (!setjmp(free_jmp_buf)) + { + png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */ + png_ptr->jmp_buf_size = 0; /* stack allocation */ + png_ptr->longjmp_fn = longjmp; + png_free(png_ptr, jb); /* Return to setjmp on error */ + } + } + } + + /* *Always* cancel everything out: */ + png_ptr->jmp_buf_size = 0; + png_ptr->jmp_buf_ptr = NULL; + png_ptr->longjmp_fn = 0; + } +} +#endif + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static PNG_FUNCTION(void /* PRIVATE */, +png_default_error,(png_const_structrp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + /* Check on NULL only added in 1.5.4 */ + if (error_message != NULL && *error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + char error_number[16]; + for (offset = 0; offset<15; offset++) + { + error_number[offset] = error_message[offset + 1]; + if (error_message[offset] == ' ') + break; + } + + if ((offset > 1) && (offset < 15)) + { + error_number[offset - 1] = '\0'; + fprintf(stderr, "libpng error no. %s: %s", + error_number, error_message + offset + 1); + fprintf(stderr, PNG_STRING_NEWLINE); + } + + else + { + fprintf(stderr, "libpng error: %s, offset=%d", + error_message, offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +#endif + { + fprintf(stderr, "libpng error: %s", error_message ? error_message : + "undefined"); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + PNG_UNUSED(error_message) /* Make compiler happy */ +#endif + png_longjmp(png_ptr, 1); +} + +PNG_FUNCTION(void,PNGAPI +png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) +{ +#ifdef PNG_SETJMP_SUPPORTED + if (png_ptr && png_ptr->longjmp_fn && png_ptr->jmp_buf_ptr) + png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val); +#endif + + /* Here if not setjmp support or if png_ptr is null. */ + PNG_ABORT(); +} + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*warning_message == PNG_LITERAL_SHARP) + { + int offset; + char warning_number[16]; + for (offset = 0; offset < 15; offset++) + { + warning_number[offset] = warning_message[offset + 1]; + if (warning_message[offset] == ' ') + break; + } + + if ((offset > 1) && (offset < 15)) + { + warning_number[offset + 1] = '\0'; + fprintf(stderr, "libpng warning no. %s: %s", + warning_number, warning_message + offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + + else + { + fprintf(stderr, "libpng warning: %s", + warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +# endif + + { + fprintf(stderr, "libpng warning: %s", warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + PNG_UNUSED(warning_message) /* Make compiler happy */ +#endif + PNG_UNUSED(png_ptr) /* Make compiler happy */ +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called when the application wants to use another method + * of handling errors and warnings. Note that the error function MUST NOT + * return to the calling routine or serious problems will occur. The return + * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1) + */ +void PNGAPI +png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + png_ptr->warning_fn = warning_fn; +#else + PNG_UNUSED(warning_fn) +#endif +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void PNGAPI +png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode) +{ + if (png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS | + PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif + +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + /* Currently the above both depend on SETJMP_SUPPORTED, however it would be + * possible to implement without setjmp support just so long as there is some + * way to handle the error return here: + */ +PNG_FUNCTION(void /* PRIVATE */, +png_safe_error,(png_structp png_nonconst_ptr, png_const_charp error_message), + PNG_NORETURN) +{ + const png_const_structrp png_ptr = png_nonconst_ptr; + png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); + + /* An error is always logged here, overwriting anything (typically a warning) + * that is already there: + */ + if (image != NULL) + { + png_safecat(image->message, (sizeof image->message), 0, error_message); + image->warning_or_error |= PNG_IMAGE_ERROR; + + /* Retrieve the jmp_buf from within the png_control, making this work for + * C++ compilation too is pretty tricky: C++ wants a pointer to the first + * element of a jmp_buf, but C doesn't tell us the type of that. + */ + if (image->opaque != NULL && image->opaque->error_buf != NULL) + longjmp(png_control_jmp_buf(image->opaque), 1); + + /* Missing longjmp buffer, the following is to help debugging: */ + { + size_t pos = png_safecat(image->message, (sizeof image->message), 0, + "bad longjmp: "); + png_safecat(image->message, (sizeof image->message), pos, + error_message); + } + } + + /* Here on an internal programming error. */ + abort(); +} + +#ifdef PNG_WARNINGS_SUPPORTED +void /* PRIVATE */ +png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message) +{ + const png_const_structrp png_ptr = png_nonconst_ptr; + png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); + + /* A warning is only logged if there is no prior warning or error. */ + if (image->warning_or_error == 0) + { + png_safecat(image->message, (sizeof image->message), 0, warning_message); + image->warning_or_error |= PNG_IMAGE_WARNING; + } +} +#endif + +int /* PRIVATE */ +png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg) +{ + volatile png_imagep image = image_in; + volatile int result; + volatile png_voidp saved_error_buf; + jmp_buf safe_jmpbuf; + + /* Safely execute function(arg) with png_error returning to this function. */ + saved_error_buf = image->opaque->error_buf; + result = setjmp(safe_jmpbuf) == 0; + + if (result) + { + + image->opaque->error_buf = safe_jmpbuf; + result = function(arg); + } + + image->opaque->error_buf = saved_error_buf; + + /* And do the cleanup prior to any failure return. */ + if (!result) + png_image_free(image); + + return result; +} +#endif /* SIMPLIFIED READ/WRITE */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngget.c b/ext/libpng16/pngget.c new file mode 100644 index 0000000000..80ab055dca --- /dev/null +++ b/ext/libpng16/pngget.c @@ -0,0 +1,1177 @@ + +/* pngget.c - retrieval of values from info struct + * + * Last changed in libpng 1.6.1 [March 28, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +png_uint_32 PNGAPI +png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + + return(0); +} + +png_size_t PNGAPI +png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + + return(0); +} + +#ifdef PNG_INFO_IMAGE_SUPPORTED +png_bytepp PNGAPI +png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->width; + + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->height; + + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->bit_depth; + + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->color_type; + + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->filter_type; + + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->interlace_type; + + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->compression_type; + + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp + info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", + "png_get_x_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return (info_ptr->x_pixels_per_unit); + } +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp + info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", + "png_get_y_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return (info_ptr->y_pixels_per_unit); + } +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER && + info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit) + return (info_ptr->x_pixels_per_unit); + } +#endif + + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp + info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); + + if (info_ptr->x_pixels_per_unit != 0) + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return ((float)0.0); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr, + png_const_inforp info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) + && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 + && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX + && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX) + { + png_fixed_point res; + + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed"); + + /* The following casts work because a PNG 4 byte integer only has a valid + * range of 0..2^31-1; otherwise the cast might overflow. + */ + if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1, + (png_int_32)info_ptr->x_pixels_per_unit)) + return res; + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return 0; +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) + return (info_ptr->x_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) + return (info_ptr->y_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->x_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->y_offset); + } +#endif + + return (0); +} + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED +static png_uint_32 +ppi_from_ppm(png_uint_32 ppm) +{ +#if 0 + /* The conversion is *(2.54/100), in binary (32 digits): + * .00000110100000001001110101001001 + */ + png_uint_32 t1001, t1101; + ppm >>= 1; /* .1 */ + t1001 = ppm + (ppm >> 3); /* .1001 */ + t1101 = t1001 + (ppm >> 1); /* .1101 */ + ppm >>= 20; /* .000000000000000000001 */ + t1101 += t1101 >> 15; /* .1101000000000001101 */ + t1001 >>= 11; /* .000000000001001 */ + t1001 += t1001 >> 12; /* .000000000001001000000001001 */ + ppm += t1001; /* .000000000001001000001001001 */ + ppm += t1101; /* .110100000001001110101001001 */ + return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */ +#else + /* The argument is a PNG unsigned integer, so it is not permitted + * to be bigger than 2^31. + */ + png_fixed_point result; + if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, + 5000)) + return result; + + /* Overflow. */ + return 0; +#endif +} + +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr)); +} + +#ifdef PNG_FIXED_POINT_SUPPORTED +static png_fixed_point +png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns) +{ + /* Convert from metres * 1,000,000 to inches * 100,000, meters to + * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. + * Notice that this can overflow - a warning is output and 0 is + * returned. + */ + return png_muldiv_warn(png_ptr, microns, 500, 127); +} + +png_fixed_point PNGAPI +png_get_x_offset_inches_fixed(png_const_structrp png_ptr, + png_const_inforp info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_x_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_y_offset_inches_fixed(png_const_structrp png_ptr, + png_const_inforp info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_y_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_x_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_y_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + + if (*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + + +png_byte PNGAPI +png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + + return (0); +} + +#ifdef PNG_READ_SUPPORTED +png_const_bytep PNGAPI +png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + + return (NULL); +} +#endif + +#ifdef PNG_bKGD_SUPPORTED +png_uint_32 PNGAPI +png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function", "bKGD"); + + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + + return (0); +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +/* The XYZ APIs were added in 1.5.5 to take advantage of the code added at the + * same time to correct the rgb grayscale coefficient defaults obtained from the + * cHRM chunk in 1.5.4 + */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y) +{ + /* Quiet API change: this code used to only return the end points if a cHRM + * chunk was present, but the end points can also come from iCCP or sRGB + * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and + * the png_set_ APIs merely check that set end points are mutually + * consistent. + */ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) + { + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (white_x != NULL) + *white_x = png_float(png_ptr, + info_ptr->colorspace.end_points_xy.whitex, "cHRM white X"); + if (white_y != NULL) + *white_y = png_float(png_ptr, + info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y"); + if (red_x != NULL) + *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx, + "cHRM red X"); + if (red_y != NULL) + *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy, + "cHRM red Y"); + if (green_x != NULL) + *green_x = png_float(png_ptr, + info_ptr->colorspace.end_points_xy.greenx, "cHRM green X"); + if (green_y != NULL) + *green_y = png_float(png_ptr, + info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y"); + if (blue_x != NULL) + *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex, + "cHRM blue X"); + if (blue_y != NULL) + *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey, + "cHRM blue Y"); + return (PNG_INFO_cHRM); + } + + return (0); +} + +png_uint_32 PNGAPI +png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr, + double *red_X, double *red_Y, double *red_Z, double *green_X, + double *green_Y, double *green_Z, double *blue_X, double *blue_Y, + double *blue_Z) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) + { + png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)"); + + if (red_X != NULL) + *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X, + "cHRM red X"); + if (red_Y != NULL) + *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y, + "cHRM red Y"); + if (red_Z != NULL) + *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z, + "cHRM red Z"); + if (green_X != NULL) + *green_X = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X"); + if (green_Y != NULL) + *green_Y = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y"); + if (green_Z != NULL) + *green_Z = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z"); + if (blue_X != NULL) + *blue_X = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X"); + if (blue_Y != NULL) + *blue_Y = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y"); + if (blue_Z != NULL) + *blue_Z = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z"); + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) + { + png_debug1(1, "in %s retrieval function", "cHRM_XYZ"); + + if (int_red_X != NULL) + *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X; + if (int_red_Y != NULL) + *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y; + if (int_red_Z != NULL) + *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z; + if (int_green_X != NULL) + *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X; + if (int_green_Y != NULL) + *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y; + if (int_green_Z != NULL) + *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z; + if (int_blue_X != NULL) + *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X; + if (int_blue_Y != NULL) + *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y; + if (int_blue_Z != NULL) + *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z; + return (PNG_INFO_cHRM); + } + + return (0); +} + +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) + { + if (white_x != NULL) + *white_x = info_ptr->colorspace.end_points_xy.whitex; + if (white_y != NULL) + *white_y = info_ptr->colorspace.end_points_xy.whitey; + if (red_x != NULL) + *red_x = info_ptr->colorspace.end_points_xy.redx; + if (red_y != NULL) + *red_y = info_ptr->colorspace.end_points_xy.redy; + if (green_x != NULL) + *green_x = info_ptr->colorspace.end_points_xy.greenx; + if (green_y != NULL) + *green_y = info_ptr->colorspace.end_points_xy.greeny; + if (blue_x != NULL) + *blue_x = info_ptr->colorspace.end_points_xy.bluex; + if (blue_y != NULL) + *blue_y = info_ptr->colorspace.end_points_xy.bluey; + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) && + file_gamma != NULL) + { + *file_gamma = info_ptr->colorspace.gamma; + return (PNG_INFO_gAMA); + } + + return (0); +} +# endif + +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr, + double *file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA(float)"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) && + file_gamma != NULL) + { + *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma, + "png_get_gAMA"); + return (PNG_INFO_gAMA); + } + + return (0); +} +# endif +#endif + +#ifdef PNG_sRGB_SUPPORTED +png_uint_32 PNGAPI +png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr, + int *file_srgb_intent) +{ + png_debug1(1, "in %s retrieval function", "sRGB"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + *file_srgb_intent = info_ptr->colorspace.rendering_intent; + return (PNG_INFO_sRGB); + } + + return (0); +} +#endif + +#ifdef PNG_iCCP_SUPPORTED +png_uint_32 PNGAPI +png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, + png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen) +{ + png_debug1(1, "in %s retrieval function", "iCCP"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && compression_type != NULL && profile != NULL && + proflen != NULL) + { + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + *proflen = png_get_uint_32(info_ptr->iccp_profile); + /* This is somewhat irrelevant since the profile data returned has + * actually been uncompressed. + */ + *compression_type = PNG_COMPRESSION_TYPE_BASE; + return (PNG_INFO_iCCP); + } + + return (0); +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +int PNGAPI +png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + { + *spalettes = info_ptr->splt_palettes; + return info_ptr->splt_palettes_num; + } + + return (0); +} +#endif + +#ifdef PNG_hIST_SUPPORTED +png_uint_32 PNGAPI +png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr, + png_uint_16p *hist) +{ + png_debug1(1, "in %s retrieval function", "hIST"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + + return (0); +} +#endif + +png_uint_32 PNGAPI +png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, + int *color_type, int *interlace_type, int *compression_type, + int *filter_type) +{ + png_debug1(1, "in %s retrieval function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL || width == NULL || + height == NULL || bit_depth == NULL || color_type == NULL) + return (0); + + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + *color_type = info_ptr->color_type; + + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* This is redundant if we can be sure that the info_ptr values were all + * assigned in png_set_IHDR(). We do the check anyhow in case an + * application has ignored our advice not to mess with the members + * of info_ptr directly. + */ + png_check_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + return (1); +} + +#ifdef PNG_oFFs_SUPPORTED +png_uint_32 PNGAPI +png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + png_debug1(1, "in %s retrieval function", "oFFs"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + + return (0); +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +png_uint_32 PNGAPI +png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + png_charp *units, png_charpp *params) +{ + png_debug1(1, "in %s retrieval function", "pCAL"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + + return (0); +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED +# if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ + defined(PNG_FLOATING_POINT_SUPPORTED) +png_uint_32 PNGAPI +png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, + int *unit, png_fixed_point *width, png_fixed_point *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + /*TODO: make this work without FP support; the API is currently eliminated + * if neither floating point APIs nor internal floating point arithmetic + * are enabled. + */ + *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); + *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), + "sCAL height"); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING_ARITHMETIC */ +# endif /* FIXED_POINT */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = atof(info_ptr->scal_s_width); + *height = atof(info_ptr->scal_s_height); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING POINT */ +png_uint_32 PNGAPI +png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + + return(0); +} +#endif /* sCAL */ + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + + return (retval); +} +#endif /* pHYs */ + +png_uint_32 PNGAPI +png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr, + png_colorp *palette, int *num_palette) +{ + png_debug1(1, "in %s retrieval function", "PLTE"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d", *num_palette); + return (PNG_INFO_PLTE); + } + + return (0); +} + +#ifdef PNG_sBIT_SUPPORTED +png_uint_32 PNGAPI +png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, + png_color_8p *sig_bit) +{ + png_debug1(1, "in %s retrieval function", "sBIT"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + + return (0); +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +int PNGAPI +png_get_text(png_const_structrp png_ptr, png_inforp info_ptr, + png_textp *text_ptr, int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in 0x%lx retrieval function", + (unsigned long)png_ptr->chunk_name); + + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + + if (num_text != NULL) + *num_text = info_ptr->num_text; + + return info_ptr->num_text; + } + + if (num_text != NULL) + *num_text = 0; + + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +png_uint_32 PNGAPI +png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr, + png_timep *mod_time) +{ + png_debug1(1, "in %s retrieval function", "tIME"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + + return (0); +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +png_uint_32 PNGAPI +png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function", "tRNS"); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans_alpha != NULL) + { + *trans_alpha = info_ptr->trans_alpha; + retval |= PNG_INFO_tRNS; + } + + if (trans_color != NULL) + *trans_color = &(info_ptr->trans_color); + } + + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_color != NULL) + { + *trans_color = &(info_ptr->trans_color); + retval |= PNG_INFO_tRNS; + } + + if (trans_alpha != NULL) + *trans_alpha = NULL; + } + + if (num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + + return (retval); +} +#endif + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +int PNGAPI +png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + { + *unknowns = info_ptr->unknown_chunks; + return info_ptr->unknown_chunks_num; + } + + return (0); +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +png_byte PNGAPI +png_get_rgb_to_gray_status (png_const_structrp png_ptr) +{ + return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +png_voidp PNGAPI +png_get_user_chunk_ptr(png_const_structrp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_ptr : NULL); +} +#endif + +png_size_t PNGAPI +png_get_compression_buffer_size(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return 0; + +# ifdef PNG_WRITE_SUPPORTED + if (png_ptr->mode & PNG_IS_READ_STRUCT) +# endif + { +# ifdef PNG_SEQUENTIAL_READ_SUPPORTED + return png_ptr->IDAT_read_size; +# else + return PNG_IDAT_READ_SIZE; +# endif + } + +# ifdef PNG_WRITE_SUPPORTED + else + return png_ptr->zbuffer_size; +# endif +} + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* These functions were added to libpng 1.2.6 and were enabled + * by default in libpng-1.4.0 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_const_structrp png_ptr) +{ + return (png_ptr ? png_ptr->user_width_max : 0); +} + +png_uint_32 PNGAPI +png_get_user_height_max (png_const_structrp png_ptr) +{ + return (png_ptr ? png_ptr->user_height_max : 0); +} + +/* This function was added to libpng 1.4.0 */ +png_uint_32 PNGAPI +png_get_chunk_cache_max (png_const_structrp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_cache_max : 0); +} + +/* This function was added to libpng 1.4.1 */ +png_alloc_size_t PNGAPI +png_get_chunk_malloc_max (png_const_structrp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_malloc_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +/* These functions were added to libpng 1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +png_uint_32 PNGAPI +png_get_io_state (png_const_structrp png_ptr) +{ + return png_ptr->io_state; +} + +png_uint_32 PNGAPI +png_get_io_chunk_type (png_const_structrp png_ptr) +{ + return png_ptr->chunk_name; +} +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +int PNGAPI +png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return png_ptr->num_palette_max; + + return (-1); +} +# endif +#endif + +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pnginfo.h b/ext/libpng16/pnginfo.h new file mode 100644 index 0000000000..683b7ea177 --- /dev/null +++ b/ext/libpng16/pnginfo.h @@ -0,0 +1,260 @@ + +/* pnginfo.h - header file for PNG reference library + * + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.6.1 [March 28, 2013] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + + /* png_info is a structure that holds the information in a PNG file so + * that the application can find out the characteristics of the image. + * If you are reading the file, this structure will tell you what is + * in the PNG file. If you are writing the file, fill in the information + * you want to put into the PNG file, using png_set_*() functions, then + * call png_write_info(). + * + * The names chosen should be very close to the PNG specification, so + * consult that document for information about the meaning of each field. + * + * With libpng < 0.95, it was only possible to directly set and read the + * the values in the png_info_struct, which meant that the contents and + * order of the values had to remain fixed. With libpng 0.95 and later, + * however, there are now functions that abstract the contents of + * png_info_struct from the application, so this makes it easier to use + * libpng with dynamic libraries, and even makes it possible to use + * libraries that don't have all of the libpng ancillary chunk-handing + * functionality. In libpng-1.5.0 this was moved into a separate private + * file that is not visible to applications. + * + * The following members may have allocated storage attached that should be + * cleaned up before the structure is discarded: palette, trans, text, + * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, + * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these + * are automatically freed when the info structure is deallocated, if they were + * allocated internally by libpng. This behavior can be changed by means + * of the png_data_freer() function. + * + * More allocation details: all the chunk-reading functions that + * change these members go through the corresponding png_set_* + * functions. A function to clear these members is available: see + * png_free_data(). The png_set_* functions do not depend on being + * able to point info structure members to any of the storage they are + * passed (they make their own copies), EXCEPT that the png_set_text + * functions use the same storage passed to them in the text_ptr or + * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns + * functions do not make their own copies. + */ +#ifndef PNGINFO_H +#define PNGINFO_H + +struct png_info_def +{ + /* The following are necessary for every PNG file */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + png_size_t rowbytes; /* bytes needed to hold an untransformed row */ + png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ + png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ + png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ + /* The following three should have been named *_method not *_type */ + png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ + png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + + /* The following are set by png_set_IHDR, called from the application on + * write, but the are never actually used by the write code. + */ + png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte spare_byte; /* to align the data, and for future use */ + +#ifdef PNG_READ_SUPPORTED + /* This is never set during write */ + png_byte signature[8]; /* magic bytes read by libpng from start of file */ +#endif + + /* The rest of the data is optional. If you are reading, check the + * valid field to see if the information in these are valid. If you + * are writing, set the valid field to those chunks you want written, + * and initialize the appropriate fields below. + */ + +#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) + /* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are + * defined. When COLORSPACE is switched on all the colorspace-defining + * chunks should be enabled, when GAMMA is switched on all the gamma-defining + * chunks should be enabled. If this is not done it becomes possible to read + * inconsistent PNG files and assign a probably incorrect interpretation to + * the information. (In other words, by carefully choosing which chunks to + * recognize the system configuration can select an interpretation for PNG + * files containing ambiguous data and this will result in inconsistent + * behavior between different libpng builds!) + */ + png_colorspace colorspace; +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* iCCP chunk data. */ + png_charp iccp_name; /* profile name */ + png_bytep iccp_profile; /* International Color Consortium profile data */ + png_uint_32 iccp_proflen; /* ICC profile data length */ +#endif + +#ifdef PNG_TEXT_SUPPORTED + /* The tEXt, and zTXt chunks contain human-readable textual data in + * uncompressed, compressed, and optionally compressed forms, respectively. + * The data in "text" is an array of pointers to uncompressed, + * null-terminated C strings. Each chunk has a keyword that describes the + * textual data contained in that chunk. Keywords are not required to be + * unique, and the text string may be empty. Any number of text chunks may + * be in an image. + */ + int num_text; /* number of comments read or comments to write */ + int max_text; /* current size of text array */ + png_textp text; /* array of comments read or comments to write */ +#endif /* PNG_TEXT_SUPPORTED */ + +#ifdef PNG_tIME_SUPPORTED + /* The tIME chunk holds the last time the displayed image data was + * modified. See the png_time struct for the contents of this struct. + */ + png_time mod_time; +#endif + +#ifdef PNG_sBIT_SUPPORTED + /* The sBIT chunk specifies the number of significant high-order bits + * in the pixel data. Values are in the range [1, bit_depth], and are + * only specified for the channels in the pixel data. The contents of + * the low-order bits is not specified. Data is valid if + * (valid & PNG_INFO_sBIT) is non-zero. + */ + png_color_8 sig_bit; /* significant bits in color channels */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ +defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The tRNS chunk supplies transparency data for paletted images and + * other image types that don't need a full alpha channel. There are + * "num_trans" transparency values for a paletted image, stored in the + * same order as the palette colors, starting from index 0. Values + * for the data are in the range [0, 255], ranging from fully transparent + * to fully opaque, respectively. For non-paletted images, there is a + * single color specified that should be treated as fully transparent. + * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. + */ + png_bytep trans_alpha; /* alpha values for paletted image */ + png_color_16 trans_color; /* transparent color for non-palette image */ +#endif + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The bKGD chunk gives the suggested image background color if the + * display program does not have its own background color and the image + * is needs to composited onto a background before display. The colors + * in "background" are normally in the same color space/depth as the + * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. + */ + png_color_16 background; +#endif + +#ifdef PNG_oFFs_SUPPORTED + /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards + * and downwards from the top-left corner of the display, page, or other + * application-specific co-ordinate space. See the PNG_OFFSET_ defines + * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. + */ + png_int_32 x_offset; /* x offset on page */ + png_int_32 y_offset; /* y offset on page */ + png_byte offset_unit_type; /* offset units type */ +#endif + +#ifdef PNG_pHYs_SUPPORTED + /* The pHYs chunk gives the physical pixel density of the image for + * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ + * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. + */ + png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ + png_uint_32 y_pixels_per_unit; /* vertical pixel density */ + png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ +#endif + +#ifdef PNG_hIST_SUPPORTED + /* The hIST chunk contains the relative frequency or importance of the + * various palette entries, so that a viewer can intelligently select a + * reduced-color palette, if required. Data is an array of "num_palette" + * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) + * is non-zero. + */ + png_uint_16p hist; +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* The pCAL chunk describes a transformation between the stored pixel + * values and original physical data values used to create the image. + * The integer range [0, 2^bit_depth - 1] maps to the floating-point + * range given by [pcal_X0, pcal_X1], and are further transformed by a + * (possibly non-linear) transformation function given by "pcal_type" + * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ + * defines below, and the PNG-Group's PNG extensions document for a + * complete description of the transformations and how they should be + * implemented, and for a description of the ASCII parameter strings. + * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. + */ + png_charp pcal_purpose; /* pCAL chunk description string */ + png_int_32 pcal_X0; /* minimum value */ + png_int_32 pcal_X1; /* maximum value */ + png_charp pcal_units; /* Latin-1 string giving physical units */ + png_charpp pcal_params; /* ASCII strings containing parameter values */ + png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_nparams; /* number of parameters given in pcal_params */ +#endif + +/* New members added in libpng-1.0.6 */ + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED + /* Storage for unknown chunks that the library doesn't recognize. */ + png_unknown_chunkp unknown_chunks; + + /* The type of this field is limited by the type of + * png_struct::user_chunk_cache_max, else overflow can occur. + */ + int unknown_chunks_num; +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Data on sPLT chunks (there may be more than one). */ + png_sPLT_tp splt_palettes; + int splt_palettes_num; /* Match type returned by png_get API */ +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* The sCAL chunk describes the actual physical dimensions of the + * subject matter of the graphic. The chunk contains a unit specification + * a byte value, and two ASCII strings representing floating-point + * values. The values are width and height corresponsing to one pixel + * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is + * non-zero. + */ + png_byte scal_unit; /* unit of physical scale */ + png_charp scal_s_width; /* string containing height */ + png_charp scal_s_height; /* string containing width */ +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) + non-zero */ + /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ + png_bytepp row_pointers; /* the image bits */ +#endif + +}; +#endif /* PNGINFO_H */ diff --git a/ext/libpng16/pnglibconf.h b/ext/libpng16/pnglibconf.h new file mode 100644 index 0000000000..2eac458e1a --- /dev/null +++ b/ext/libpng16/pnglibconf.h @@ -0,0 +1,454 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.6.2 - April 25, 2013 */ + +/* Copyright (c) 1998-2012 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +// TODO: Enable the NEON API on supported hardware +#undef PNG_ARM_NEON_API_SUPPORTED +#undef PNG_ARM_NEON_CHECK_SUPPORTED +#undef PNG_ARM_NEON_SUPPORTED +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +/*#undef PNG_SAFE_LIMITS_SUPPORTED*/ +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +/*#undef PNG_SET_OPTION_SUPPORTED*/ +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_CALLOC_SUPPORTED +#define PNG_COST_SHIFT 3 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_MAX_GAMMA_8 11 +#define PNG_PREFIX png16_ +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_WEIGHT_SHIFT 8 +#define PNG_ZBUF_SIZE 8192 +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#define png_access_version_number png16_png_access_version_number +#define png_benign_error png16_png_benign_error +#define png_build_grayscale_palette png16_png_build_grayscale_palette +#define png_calloc png16_png_calloc +#define png_chunk_benign_error png16_png_chunk_benign_error +#define png_chunk_error png16_png_chunk_error +#define png_chunk_warning png16_png_chunk_warning +#define png_convert_from_struct_tm png16_png_convert_from_struct_tm +#define png_convert_from_time_t png16_png_convert_from_time_t +#define png_convert_to_rfc1123 png16_png_convert_to_rfc1123 +#define png_convert_to_rfc1123_buffer png16_png_convert_to_rfc1123_buffer +#define png_create_info_struct png16_png_create_info_struct +#define png_create_read_struct png16_png_create_read_struct +#define png_create_read_struct_2 png16_png_create_read_struct_2 +#define png_create_write_struct png16_png_create_write_struct +#define png_create_write_struct_2 png16_png_create_write_struct_2 +#define png_data_freer png16_png_data_freer +#define png_destroy_info_struct png16_png_destroy_info_struct +#define png_destroy_read_struct png16_png_destroy_read_struct +#define png_destroy_write_struct png16_png_destroy_write_struct +#define png_error png16_png_error +#define png_free png16_png_free +#define png_free_data png16_png_free_data +#define png_free_default png16_png_free_default +#define png_get_IHDR png16_png_get_IHDR +#define png_get_PLTE png16_png_get_PLTE +#define png_get_bKGD png16_png_get_bKGD +#define png_get_bit_depth png16_png_get_bit_depth +#define png_get_cHRM png16_png_get_cHRM +#define png_get_cHRM_XYZ png16_png_get_cHRM_XYZ +#define png_get_cHRM_XYZ_fixed png16_png_get_cHRM_XYZ_fixed +#define png_get_cHRM_fixed png16_png_get_cHRM_fixed +#define png_get_channels png16_png_get_channels +#define png_get_chunk_cache_max png16_png_get_chunk_cache_max +#define png_get_chunk_malloc_max png16_png_get_chunk_malloc_max +#define png_get_color_type png16_png_get_color_type +#define png_get_compression_buffer_size png16_png_get_compression_buffer_size +#define png_get_compression_type png16_png_get_compression_type +#define png_get_copyright png16_png_get_copyright +#define png_get_current_pass_number png16_png_get_current_pass_number +#define png_get_current_row_number png16_png_get_current_row_number +#define png_get_error_ptr png16_png_get_error_ptr +#define png_get_filter_type png16_png_get_filter_type +#define png_get_gAMA png16_png_get_gAMA +#define png_get_gAMA_fixed png16_png_get_gAMA_fixed +#define png_get_hIST png16_png_get_hIST +#define png_get_header_ver png16_png_get_header_ver +#define png_get_header_version png16_png_get_header_version +#define png_get_iCCP png16_png_get_iCCP +#define png_get_image_height png16_png_get_image_height +#define png_get_image_width png16_png_get_image_width +#define png_get_int_32 png16_png_get_int_32 +#define png_get_interlace_type png16_png_get_interlace_type +#define png_get_io_chunk_type png16_png_get_io_chunk_type +#define png_get_io_ptr png16_png_get_io_ptr +#define png_get_io_state png16_png_get_io_state +#define png_get_libpng_ver png16_png_get_libpng_ver +#define png_get_mem_ptr png16_png_get_mem_ptr +#define png_get_oFFs png16_png_get_oFFs +#define png_get_pCAL png16_png_get_pCAL +#define png_get_pHYs png16_png_get_pHYs +#define png_get_pHYs_dpi png16_png_get_pHYs_dpi +#define png_get_palette_max png16_png_get_palette_max +#define png_get_pixel_aspect_ratio png16_png_get_pixel_aspect_ratio +#define png_get_pixel_aspect_ratio_fixed png16_png_get_pixel_aspect_ratio_fixed +#define png_get_pixels_per_inch png16_png_get_pixels_per_inch +#define png_get_pixels_per_meter png16_png_get_pixels_per_meter +#define png_get_progressive_ptr png16_png_get_progressive_ptr +#define png_get_rgb_to_gray_status png16_png_get_rgb_to_gray_status +#define png_get_rowbytes png16_png_get_rowbytes +#define png_get_rows png16_png_get_rows +#define png_get_sBIT png16_png_get_sBIT +#define png_get_sCAL png16_png_get_sCAL +#define png_get_sCAL_fixed png16_png_get_sCAL_fixed +#define png_get_sCAL_s png16_png_get_sCAL_s +#define png_get_sPLT png16_png_get_sPLT +#define png_get_sRGB png16_png_get_sRGB +#define png_get_signature png16_png_get_signature +#define png_get_tIME png16_png_get_tIME +#define png_get_tRNS png16_png_get_tRNS +#define png_get_text png16_png_get_text +#define png_get_uint_16 png16_png_get_uint_16 +#define png_get_uint_31 png16_png_get_uint_31 +#define png_get_uint_32 png16_png_get_uint_32 +#define png_get_unknown_chunks png16_png_get_unknown_chunks +#define png_get_user_chunk_ptr png16_png_get_user_chunk_ptr +#define png_get_user_height_max png16_png_get_user_height_max +#define png_get_user_transform_ptr png16_png_get_user_transform_ptr +#define png_get_user_width_max png16_png_get_user_width_max +#define png_get_valid png16_png_get_valid +#define png_get_x_offset_inches png16_png_get_x_offset_inches +#define png_get_x_offset_inches_fixed png16_png_get_x_offset_inches_fixed +#define png_get_x_offset_microns png16_png_get_x_offset_microns +#define png_get_x_offset_pixels png16_png_get_x_offset_pixels +#define png_get_x_pixels_per_inch png16_png_get_x_pixels_per_inch +#define png_get_x_pixels_per_meter png16_png_get_x_pixels_per_meter +#define png_get_y_offset_inches png16_png_get_y_offset_inches +#define png_get_y_offset_inches_fixed png16_png_get_y_offset_inches_fixed +#define png_get_y_offset_microns png16_png_get_y_offset_microns +#define png_get_y_offset_pixels png16_png_get_y_offset_pixels +#define png_get_y_pixels_per_inch png16_png_get_y_pixels_per_inch +#define png_get_y_pixels_per_meter png16_png_get_y_pixels_per_meter +#define png_handle_as_unknown png16_png_handle_as_unknown +#define png_image_begin_read_from_file png16_png_image_begin_read_from_file +#define png_image_begin_read_from_memory png16_png_image_begin_read_from_memory +#define png_image_begin_read_from_stdio png16_png_image_begin_read_from_stdio +#define png_image_finish_read png16_png_image_finish_read +#define png_image_free png16_png_image_free +#define png_image_write_to_file png16_png_image_write_to_file +#define png_image_write_to_stdio png16_png_image_write_to_stdio +#define png_info_init_3 png16_png_info_init_3 +#define png_init_io png16_png_init_io +#define png_longjmp png16_png_longjmp +#define png_malloc png16_png_malloc +#define png_malloc_default png16_png_malloc_default +#define png_malloc_warn png16_png_malloc_warn +#define png_permit_mng_features png16_png_permit_mng_features +#define png_process_data png16_png_process_data +#define png_process_data_pause png16_png_process_data_pause +#define png_process_data_skip png16_png_process_data_skip +#define png_progressive_combine_row png16_png_progressive_combine_row +#define png_read_end png16_png_read_end +#define png_read_image png16_png_read_image +#define png_read_info png16_png_read_info +#define png_read_png png16_png_read_png +#define png_read_row png16_png_read_row +#define png_read_rows png16_png_read_rows +#define png_read_update_info png16_png_read_update_info +#define png_reset_zstream png16_png_reset_zstream +#define png_save_int_32 png16_png_save_int_32 +#define png_save_uint_16 png16_png_save_uint_16 +#define png_save_uint_32 png16_png_save_uint_32 +#define png_set_IHDR png16_png_set_IHDR +#define png_set_PLTE png16_png_set_PLTE +#define png_set_add_alpha png16_png_set_add_alpha +#define png_set_alpha_mode png16_png_set_alpha_mode +#define png_set_alpha_mode_fixed png16_png_set_alpha_mode_fixed +#define png_set_bKGD png16_png_set_bKGD +#define png_set_background png16_png_set_background +#define png_set_background_fixed png16_png_set_background_fixed +#define png_set_benign_errors png16_png_set_benign_errors +#define png_set_bgr png16_png_set_bgr +#define png_set_cHRM png16_png_set_cHRM +#define png_set_cHRM_XYZ png16_png_set_cHRM_XYZ +#define png_set_cHRM_XYZ_fixed png16_png_set_cHRM_XYZ_fixed +#define png_set_cHRM_fixed png16_png_set_cHRM_fixed +#define png_set_check_for_invalid_index png16_png_set_check_for_invalid_index +#define png_set_chunk_cache_max png16_png_set_chunk_cache_max +#define png_set_chunk_malloc_max png16_png_set_chunk_malloc_max +#define png_set_compression_buffer_size png16_png_set_compression_buffer_size +#define png_set_compression_level png16_png_set_compression_level +#define png_set_compression_mem_level png16_png_set_compression_mem_level +#define png_set_compression_method png16_png_set_compression_method +#define png_set_compression_strategy png16_png_set_compression_strategy +#define png_set_compression_window_bits png16_png_set_compression_window_bits +#define png_set_crc_action png16_png_set_crc_action +#define png_set_error_fn png16_png_set_error_fn +#define png_set_expand png16_png_set_expand +#define png_set_expand_16 png16_png_set_expand_16 +#define png_set_expand_gray_1_2_4_to_8 png16_png_set_expand_gray_1_2_4_to_8 +#define png_set_filler png16_png_set_filler +#define png_set_filter png16_png_set_filter +#define png_set_filter_heuristics png16_png_set_filter_heuristics +#define png_set_filter_heuristics_fixed png16_png_set_filter_heuristics_fixed +#define png_set_flush png16_png_set_flush +#define png_set_gAMA png16_png_set_gAMA +#define png_set_gAMA_fixed png16_png_set_gAMA_fixed +#define png_set_gamma png16_png_set_gamma +#define png_set_gamma_fixed png16_png_set_gamma_fixed +#define png_set_gray_to_rgb png16_png_set_gray_to_rgb +#define png_set_hIST png16_png_set_hIST +#define png_set_iCCP png16_png_set_iCCP +#define png_set_interlace_handling png16_png_set_interlace_handling +#define png_set_invalid png16_png_set_invalid +#define png_set_invert_alpha png16_png_set_invert_alpha +#define png_set_invert_mono png16_png_set_invert_mono +#define png_set_keep_unknown_chunks png16_png_set_keep_unknown_chunks +#define png_set_longjmp_fn png16_png_set_longjmp_fn +#define png_set_mem_fn png16_png_set_mem_fn +#define png_set_oFFs png16_png_set_oFFs +#define png_set_pCAL png16_png_set_pCAL +#define png_set_pHYs png16_png_set_pHYs +#define png_set_packing png16_png_set_packing +#define png_set_packswap png16_png_set_packswap +#define png_set_palette_to_rgb png16_png_set_palette_to_rgb +#define png_set_progressive_read_fn png16_png_set_progressive_read_fn +#define png_set_quantize png16_png_set_quantize +#define png_set_read_fn png16_png_set_read_fn +#define png_set_read_status_fn png16_png_set_read_status_fn +#define png_set_read_user_chunk_fn png16_png_set_read_user_chunk_fn +#define png_set_read_user_transform_fn png16_png_set_read_user_transform_fn +#define png_set_rgb_to_gray png16_png_set_rgb_to_gray +#define png_set_rgb_to_gray_fixed png16_png_set_rgb_to_gray_fixed +#define png_set_rows png16_png_set_rows +#define png_set_sBIT png16_png_set_sBIT +#define png_set_sCAL png16_png_set_sCAL +#define png_set_sCAL_fixed png16_png_set_sCAL_fixed +#define png_set_sCAL_s png16_png_set_sCAL_s +#define png_set_sPLT png16_png_set_sPLT +#define png_set_sRGB png16_png_set_sRGB +#define png_set_sRGB_gAMA_and_cHRM png16_png_set_sRGB_gAMA_and_cHRM +#define png_set_scale_16 png16_png_set_scale_16 +#define png_set_shift png16_png_set_shift +#define png_set_sig_bytes png16_png_set_sig_bytes +#define png_set_strip_16 png16_png_set_strip_16 +#define png_set_strip_alpha png16_png_set_strip_alpha +#define png_set_swap png16_png_set_swap +#define png_set_swap_alpha png16_png_set_swap_alpha +#define png_set_tIME png16_png_set_tIME +#define png_set_tRNS png16_png_set_tRNS +#define png_set_tRNS_to_alpha png16_png_set_tRNS_to_alpha +#define png_set_text png16_png_set_text +#define png_set_text_compression_level png16_png_set_text_compression_level +#define png_set_text_compression_mem_level png16_png_set_text_compression_mem_level +#define png_set_text_compression_method png16_png_set_text_compression_method +#define png_set_text_compression_strategy png16_png_set_text_compression_strategy +#define png_set_text_compression_window_bits png16_png_set_text_compression_window_bits +#define png_set_unknown_chunk_location png16_png_set_unknown_chunk_location +#define png_set_unknown_chunks png16_png_set_unknown_chunks +#define png_set_user_limits png16_png_set_user_limits +#define png_set_user_transform_info png16_png_set_user_transform_info +#define png_set_write_fn png16_png_set_write_fn +#define png_set_write_status_fn png16_png_set_write_status_fn +#define png_set_write_user_transform_fn png16_png_set_write_user_transform_fn +#define png_sig_cmp png16_png_sig_cmp +#define png_start_read_image png16_png_start_read_image +#define png_warning png16_png_warning +#define png_write_chunk png16_png_write_chunk +#define png_write_chunk_data png16_png_write_chunk_data +#define png_write_chunk_end png16_png_write_chunk_end +#define png_write_chunk_start png16_png_write_chunk_start +#define png_write_end png16_png_write_end +#define png_write_flush png16_png_write_flush +#define png_write_image png16_png_write_image +#define png_write_info png16_png_write_info +#define png_write_info_before_PLTE png16_png_write_info_before_PLTE +#define png_write_png png16_png_write_png +#define png_write_row png16_png_write_row +#define png_write_rows png16_png_write_rows +#define png_write_sig png16_png_write_sig +#define png16_png_get_uint_32(buf) PNG_get_uint_32(buf) +#define png16_png_get_uint_16(buf) PNG_get_uint_16(buf) +#define png16_png_get_int_32(buf) PNG_get_int_32(buf) +#endif /* PNGLCONF_H */ diff --git a/ext/libpng16/pngmem.c b/ext/libpng16/pngmem.c new file mode 100644 index 0000000000..adae736699 --- /dev/null +++ b/ext/libpng16/pngmem.c @@ -0,0 +1,277 @@ + +/* pngmem.c - stub functions for memory allocation + * + * Last changed in libpng 1.6.0 [February 14, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Free a png_struct */ +void /* PRIVATE */ +png_destroy_png_struct(png_structrp png_ptr) +{ + if (png_ptr != NULL) + { + /* png_free might call png_error and may certainly call + * png_get_mem_ptr, so fake a temporary png_struct to support this. + */ + png_struct dummy_struct = *png_ptr; + memset(png_ptr, 0, (sizeof *png_ptr)); + png_free(&dummy_struct, png_ptr); + +# ifdef PNG_SETJMP_SUPPORTED + /* We may have a jmp_buf left to deallocate. */ + png_free_jmpbuf(&dummy_struct); +# endif + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + ret = png_malloc(png_ptr, size); + + if (ret != NULL) + memset(ret, 0, size); + + return ret; +} + +/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of + * allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED. + * Checking and error handling must happen outside this routine; it returns NULL + * if the allocation cannot be done (for any reason.) + */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED) +{ + /* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS + * allocators have also been removed in 1.6.0, so any 16-bit system now has + * to implement a user memory handler. This checks to be sure it isn't + * called with big numbers. + */ +#ifdef PNG_USER_MEM_SUPPORTED + PNG_UNUSED(png_ptr) +#endif + if (size > 0 && size <= PNG_SIZE_MAX +# ifdef PNG_MAX_MALLOC_64K + && size <= 65536U +# endif + ) + { +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr != NULL && png_ptr->malloc_fn != NULL) + return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size); + + else +#endif + return malloc((size_t)size); /* checked for truncation above */ + } + + else + return NULL; +} + +/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7 + * that arises because of the checks in png_realloc_array that are repeated in + * png_malloc_array. + */ +static png_voidp +png_malloc_array_checked(png_const_structrp png_ptr, int nelements, + size_t element_size) +{ + png_alloc_size_t req = nelements; /* known to be > 0 */ + + if (req <= PNG_SIZE_MAX/element_size) + return png_malloc_base(png_ptr, req * element_size); + + /* The failure case when the request is too large */ + return NULL; +} + +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_malloc_array,(png_const_structrp png_ptr, int nelements, + size_t element_size),PNG_ALLOCATED) +{ + if (nelements <= 0 || element_size == 0) + png_error(png_ptr, "internal error: array alloc"); + + return png_malloc_array_checked(png_ptr, nelements, element_size); +} + +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, + int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED) +{ + /* These are internal errors: */ + if (add_elements <= 0 || element_size == 0 || old_elements < 0 || + (old_array == NULL && old_elements > 0)) + png_error(png_ptr, "internal error: array realloc"); + + /* Check for overflow on the elements count (so the caller does not have to + * check.) + */ + if (add_elements <= INT_MAX - old_elements) + { + png_voidp new_array = png_malloc_array_checked(png_ptr, + old_elements+add_elements, element_size); + + if (new_array != NULL) + { + /* Because png_malloc_array worked the size calculations below cannot + * overflow. + */ + if (old_elements > 0) + memcpy(new_array, old_array, element_size*(unsigned)old_elements); + + memset((char*)new_array + element_size*(unsigned)old_elements, 0, + element_size*(unsigned)add_elements); + + return new_array; + } + } + + return NULL; /* error */ +} + +/* Various functions that have different error handling are derived from this. + * png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate + * function png_malloc_default is also provided. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + if (png_ptr == NULL) + return NULL; + + ret = png_malloc_base(png_ptr, size); + + if (ret == NULL) + png_error(png_ptr, "Out of memory"); /* 'm' means png_malloc */ + + return ret; +} + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED PNG_DEPRECATED) +{ + png_voidp ret; + + if (png_ptr == NULL) + return NULL; + + /* Passing 'NULL' here bypasses the application provided memory handler. */ + ret = png_malloc_base(NULL/*use malloc*/, size); + + if (ret == NULL) + png_error(png_ptr, "Out of Memory"); /* 'M' means png_malloc_default */ + + return ret; +} +#endif /* PNG_USER_MEM_SUPPORTED */ + +/* This function was added at libpng version 1.2.3. The png_malloc_warn() + * function will issue a png_warning and return NULL instead of issuing a + * png_error, if it fails to allocate the requested memory. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED) +{ + if (png_ptr != NULL) + { + png_voidp ret = png_malloc_base(png_ptr, size); + + if (ret != NULL) + return ret; + + png_warning(png_ptr, "Out of memory"); + } + + return NULL; +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + * without taking any action. + */ +void PNGAPI +png_free(png_const_structrp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr); + + else + png_free_default(png_ptr, ptr); +} + +PNG_FUNCTION(void,PNGAPI +png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED) +{ + if (png_ptr == NULL || ptr == NULL) + return; +#endif /* PNG_USER_MEM_SUPPORTED */ + + free(ptr); +} + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + if (png_ptr != NULL) + { + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; + } +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + + return png_ptr->mem_ptr; +} +#endif /* PNG_USER_MEM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngpread.c b/ext/libpng16/pngpread.c new file mode 100644 index 0000000000..f97ac3aee3 --- /dev/null +++ b/ext/libpng16/pngpread.c @@ -0,0 +1,1291 @@ + +/* pngpread.c - read a png file in push mode + * + * Last changed in libpng 1.6.0 [February 14, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + +/* Push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structrp png_ptr, png_inforp info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +png_size_t PNGAPI +png_process_data_pause(png_structrp png_ptr, int save) +{ + if (png_ptr != NULL) + { + /* It's easiest for the caller if we do the save, then the caller doesn't + * have to supply the same data again: + */ + if (save) + png_push_save_buffer(png_ptr); + else + { + /* This includes any pending saved bytes: */ + png_size_t remaining = png_ptr->buffer_size; + png_ptr->buffer_size = 0; + + /* So subtract the saved buffer size, unless all the data + * is actually 'saved', in which case we just return 0 + */ + if (png_ptr->save_buffer_size < remaining) + return remaining - png_ptr->save_buffer_size; + } + } + + return 0; +} + +png_uint_32 PNGAPI +png_process_data_skip(png_structrp png_ptr) +{ + png_uint_32 remaining = 0; + + if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE && + png_ptr->skip_length > 0) + { + /* At the end of png_process_data the buffer size must be 0 (see the loop + * above) so we can detect a broken call here: + */ + if (png_ptr->buffer_size != 0) + png_error(png_ptr, + "png_process_data_skip called inside png_process_data"); + + /* If is impossible for there to be a saved buffer at this point - + * otherwise we could not be in SKIP mode. This will also happen if + * png_process_skip is called inside png_process_data (but only very + * rarely.) + */ + if (png_ptr->save_buffer_size != 0) + png_error(png_ptr, "png_process_data_skip called with saved data"); + + remaining = png_ptr->skip_length; + png_ptr->skip_length = 0; + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + + return remaining; +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) +{ + if (png_ptr == NULL) + return; + + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } + + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) +{ + png_uint_32 chunk_name; +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int keep; /* unknown handling method */ +#endif + + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + png_byte chunk_tag[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, chunk_tag, 4); + png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + chunk_name = png_ptr->chunk_name; + + if (chunk_name == png_IDAT) + { + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + png_ptr->mode |= PNG_HAVE_IDAT; + + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_benign_error(png_ptr, "Too many IDATs found"); + } + + if (chunk_name == png_IHDR) + { + if (png_ptr->push_length != 13) + png_error(png_ptr, "Invalid IHDR length"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (chunk_name == png_IEND) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep); + + if (chunk_name == png_PLTE) + png_ptr->mode |= PNG_HAVE_PLTE; + } + +#endif + else if (chunk_name == png_PLTE) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (chunk_name == png_IDAT) + { + png_ptr->idat_size = png_ptr->push_length; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (png_ptr->chunk_name == png_gAMA) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (png_ptr->chunk_name == png_sBIT) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (png_ptr->chunk_name == png_cHRM) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (chunk_name == png_sRGB) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (png_ptr->chunk_name == png_iCCP) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (chunk_name == png_sPLT) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (chunk_name == png_tRNS) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_bKGD_SUPPORTED + else if (chunk_name == png_bKGD) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (chunk_name == png_hIST) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (chunk_name == png_pHYs) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (chunk_name == png_oFFs) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (chunk_name == png_pCAL) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (chunk_name == png_sCAL) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (chunk_name == png_tIME) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (chunk_name == png_tEXt) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (chunk_name == png_zTXt) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (chunk_name == png_iTXt) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, + PNG_HANDLE_CHUNK_AS_DEFAULT); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structrp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structrp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size = png_ptr->save_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'save_buffer_size', but + * they are of different types and we don't know which variable has the + * fewest bits. Carefully select the smaller and cast it to the type of + * the larger - this cannot overflow. Do not cast in the following test + * - it will break on either 16 or 64 bit platforms. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size = png_ptr->current_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'current_buffer_size', here, + * the same problem exists as above and the same solution. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void PNGCBAPI +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + if (png_ptr == NULL) + return; + + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + + else + save_size = png_ptr->save_buffer_size; + + memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + + else + save_size = png_ptr->current_buffer_size; + + memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structrp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i, istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, + (png_size_t)new_max); + + if (png_ptr->save_buffer == NULL) + { + png_free(png_ptr, old_buffer); + png_error(png_ptr, "Insufficient memory for save_buffer"); + } + + memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structrp png_ptr) +{ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + png_byte chunk_tag[4]; + + /* TODO: this code can be commoned up with the same code in push_read */ + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, chunk_tag, 4); + png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_ptr->chunk_name != png_IDAT) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + + if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + png_error(png_ptr, "Not enough compressed data"); + + return; + } + + png_ptr->idat_size = png_ptr->push_length; + } + + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size = png_ptr->save_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. Do not cast in the following test - it + * will break on either 16 or 64 bit platforms. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->idat_size -= idat_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size = png_ptr->current_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= idat_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->zowner = 0; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + /* The caller checks for a non-zero buffer length. */ + if (!(buffer_length > 0) || buffer == NULL) + png_error(png_ptr, "No IDAT data (internal error)"); + + /* This routine must process all the data it has been given + * before returning, calling the row callback as required to + * handle the uncompressed results. + */ + png_ptr->zstream.next_in = buffer; + /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */ + png_ptr->zstream.avail_in = (uInt)buffer_length; + + /* Keep going until the decompressed data is all processed + * or the stream marked as finished. + */ + while (png_ptr->zstream.avail_in > 0 && + !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + { + int ret; + + /* We have data for zlib, but we must check that zlib + * has someplace to put the results. It doesn't matter + * if we don't expect any results -- it may be the input + * data is just the LZ end code. + */ + if (!(png_ptr->zstream.avail_out > 0)) + { + /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */ + png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1); + + png_ptr->zstream.next_out = png_ptr->row_buf; + } + + /* Using Z_SYNC_FLUSH here means that an unterminated + * LZ stream (a stream with a missing end code) can still + * be handled, otherwise (Z_NO_FLUSH) a future zlib + * implementation might defer output and therefore + * change the current behavior (see comments in inflate.c + * for why this doesn't happen at present with zlib 1.2.5). + */ + ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); + + /* Check for any failure before proceeding. */ + if (ret != Z_OK && ret != Z_STREAM_END) + { + /* Terminate the decompression. */ + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; + png_ptr->zowner = 0; + + /* This may be a truncated stream (missing or + * damaged end code). Treat that as a warning. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + png_warning(png_ptr, "Truncated compressed data in IDAT"); + + else + png_error(png_ptr, "Decompression error in IDAT"); + + /* Skip the check on unprocessed input */ + return; + } + + /* Did inflate output any data? */ + if (png_ptr->zstream.next_out != png_ptr->row_buf) + { + /* Is this unexpected data after the last row? + * If it is, artificially terminate the LZ output + * here. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + { + /* Extra data. */ + png_warning(png_ptr, "Extra compressed data in IDAT"); + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; + png_ptr->zowner = 0; + + /* Do no more processing; skip the unprocessed + * input check below. + */ + return; + } + + /* Do we have a complete row? */ + if (png_ptr->zstream.avail_out == 0) + png_push_process_row(png_ptr); + } + + /* And check for the end of the stream. */ + if (ret == Z_STREAM_END) + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; + } + + /* All the data should have been processed, if anything + * is left at this point we have bytes of IDAT data + * after the zlib end code. + */ + if (png_ptr->zstream.avail_in > 0) + png_warning(png_ptr, "Extra compression data in IDAT"); +} + +void /* PRIVATE */ +png_push_process_row(png_structrp png_ptr) +{ + /* 1.5.6: row_info moved out of png_struct to a local here. */ + png_row_info row_info; + + row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ + row_info.color_type = png_ptr->color_type; + row_info.bit_depth = png_ptr->bit_depth; + row_info.channels = png_ptr->channels; + row_info.pixel_depth = png_ptr->pixel_depth; + row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); + + if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) + { + if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) + png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, + png_ptr->prev_row + 1, png_ptr->row_buf[0]); + else + png_error(png_ptr, "bad adaptive filter value"); + } + + /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before + * 1.5.6, while the buffer really is this big in current versions of libpng + * it may not be in the future, so this was changed just to copy the + * interlaced row count: + */ + memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + if (png_ptr->transformations) + png_do_read_transformations(png_ptr, &row_info); +#endif + + /* The transformed pixel depth should match the depth now in row_info. */ + if (png_ptr->transformed_pixel_depth == 0) + { + png_ptr->transformed_pixel_depth = row_info.pixel_depth; + if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) + png_error(png_ptr, "progressive row overflow"); + } + + else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) + png_error(png_ptr, "internal progressive row size calculation error"); + + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) + png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, + png_ptr->transformations); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ + } + + if (png_ptr->pass == 2) /* Pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 2) /* Skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 2: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 3: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 4: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Pass 5 might be empty */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 5: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Skip top generated row */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + default: + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + + if (png_ptr->pass != 6) + break; + + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structrp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ +#endif + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass > 7) + png_ptr->pass--; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +} + +void /* PRIVATE */ +png_push_have_info(png_structrp png_ptr, png_inforp info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structrp png_ptr, png_inforp info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structrp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +void PNGAPI +png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row, + png_const_bytep new_row) +{ + if (png_ptr == NULL) + return; + + /* new_row is a flag here - if it is NULL then the app callback was called + * from an empty row (see the calls to png_struct::row_fn below), otherwise + * it must be png_ptr->row_buf+1 + */ + if (new_row != NULL) + png_combine_row(png_ptr, old_row, 1/*display*/); +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +void PNGAPI +png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +png_voidp PNGAPI +png_get_progressive_ptr(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/ext/libpng16/pngpriv.h b/ext/libpng16/pngpriv.h new file mode 100644 index 0000000000..d014095d3a --- /dev/null +++ b/ext/libpng16/pngpriv.h @@ -0,0 +1,2043 @@ + +/* pngpriv.h - private declarations for use inside libpng + * + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.6.7 [November 14, 2013] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The symbols declared in this file (including the functions declared + * as extern) are PRIVATE. They are not part of the libpng public + * interface, and are not recommended for use by regular applications. + * Some of them may become public in the future; others may stay private, + * change in an incompatible way, or even disappear. + * Although the libpng users are not forbidden to include this header, + * they should be well aware of the issues that may arise from doing so. + */ + +#ifndef PNGPRIV_H +#define PNGPRIV_H + +/* Feature Test Macros. The following are defined here to ensure that correctly + * implemented libraries reveal the APIs libpng needs to build and hide those + * that are not needed and potentially damaging to the compilation. + * + * Feature Test Macros must be defined before any system header is included (see + * POSIX 1003.1 2.8.2 "POSIX Symbols." + * + * These macros only have an effect if the operating system supports either + * POSIX 1003.1 or C99, or both. On other operating systems (particularly + * Windows/Visual Studio) there is no effect; the OS specific tests below are + * still required (as of 2011-05-02.) + */ +#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ + +#ifndef PNG_VERSION_INFO_ONLY +/* Standard library headers not required by png.h: */ +# include +# include +#endif + +#define PNGLIB_BUILD /*libpng is being built, not used*/ + +/* If HAVE_CONFIG_H is defined during the build then the build system must + * provide an appropriate "config.h" file on the include path. The header file + * must provide definitions as required below (search for "HAVE_CONFIG_H"); + * see configure.ac for more details of the requirements. The macro + * "PNG_NO_CONFIG_H" is provided for maintainers to test for dependencies on + * 'configure'; define this macro to prevent the configure build including the + * configure generated config.h. Libpng is expected to compile without *any* + * special build system support on a reasonably ANSI-C compliant system. + */ +#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) +# include + + /* Pick up the definition of 'restrict' from config.h if it was read: */ +# define PNG_RESTRICT restrict +#endif + +/* To support symbol prefixing it is necessary to know *before* including png.h + * whether the fixed point (and maybe other) APIs are exported, because if they + * are not internal definitions may be required. This is handled below just + * before png.h is included, but load the configuration now if it is available. + */ +#ifndef PNGLCONF_H +# include "pnglibconf.h" +#endif + + +#ifdef PNG_USER_CONFIG +# include "pngusr.h" + /* These should have been defined in pngusr.h */ +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD "Custom libpng build" +# endif +# ifndef PNG_USER_DLLFNAME_POSTFIX +# define PNG_USER_DLLFNAME_POSTFIX "Cb" +# endif +#endif + +/* Compile time options. + * ===================== + * In a multi-arch build the compiler may compile the code several times for the + * same object module, producing different binaries for different architectures. + * When this happens configure-time setting of the target host options cannot be + * done and this interferes with the handling of the ARM NEON optimizations, and + * possibly other similar optimizations. Put additional tests here; in general + * this is needed when the same option can be changed at both compile time and + * run time depending on the target OS (i.e. iOS vs Android.) + * + * NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because + * this is not possible with certain compilers (Oracle SUN OS CC), as a result + * it is necessary to ensure that all extern functions that *might* be used + * regardless of $(CFLAGS) get declared in this file. The test on __ARM_NEON__ + * below is one example of this behavior because it is controlled by the + * presence or not of -mfpu=neon on the GCC command line, it is possible to do + * this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely + * do this. + */ +#ifndef PNG_ARM_NEON_OPT + /* ARM NEON optimizations are being controlled by the compiler settings, + * typically the target FPU. If the FPU has been set to NEON (-mfpu=neon + * with GCC) then the compiler will define __ARM_NEON__ and we can rely + * unconditionally on NEON instructions not crashing, otherwise we must + * disable use of NEON instructions: + */ +# ifdef __ARM_NEON__ +# define PNG_ARM_NEON_OPT 2 +# else +# define PNG_ARM_NEON_OPT 0 +# endif +#endif + +#if PNG_ARM_NEON_OPT > 0 + /* NEON optimizations are to be at least considered by libpng, so enable the + * callbacks to do this. + */ +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon + + /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used + * if possible - if __ARM_NEON__ is set and the compiler version is not known + * to be broken. This is control by PNG_ARM_NEON_IMPLEMENTATION which can + * be: + * + * 1 The intrinsics code (the default with __ARM_NEON__) + * 2 The hand coded assembler (the default without __ARM_NEON__) + * + * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however + * this is *NOT* supported and may cease to work even after a minor revision + * to libpng. It *is* valid to do this for testing purposes, e.g. speed + * testing or a new compiler, but the results should be communicated to the + * libpng implementation list for incorporation in the next minor release. + */ +# ifndef PNG_ARM_NEON_IMPLEMENTATION +# ifdef __ARM_NEON__ +# if defined(__clang__) + /* At present it is unknown by the libpng developers which versions + * of clang support the intrinsics, however some or perhaps all + * versions do not work with the assembler so this may be + * irrelevant, so just use the default (do nothing here.) + */ +# elif defined(__GNUC__) + /* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to + * work, so if this *is* GCC, or G++, look for a version >4.5 + */ +# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) +# define PNG_ARM_NEON_IMPLEMENTATION 2 +# endif /* no GNUC support */ +# endif /* __GNUC__ */ +# else /* !defined __ARM_NEON__ */ + /* The 'intrinsics' code simply won't compile without this -mfpu=neon: + */ +# define PNG_ARM_NEON_IMPLEMENTATION 2 +# endif /* __ARM_NEON__ */ +# endif /* !defined PNG_ARM_NEON_IMPLEMENTATION */ + +# ifndef PNG_ARM_NEON_IMPLEMENTATION + /* Use the intrinsics code by default. */ +# define PNG_ARM_NEON_IMPLEMENTATION 1 +# endif +#endif /* PNG_ARM_NEON_OPT > 0 */ + +/* Is this a build of a DLL where compilation of the object modules requires + * different preprocessor settings to those required for a simple library? If + * so PNG_BUILD_DLL must be set. + * + * If libpng is used inside a DLL but that DLL does not export the libpng APIs + * PNG_BUILD_DLL must not be set. To avoid the code below kicking in build a + * static library of libpng then link the DLL against that. + */ +#ifndef PNG_BUILD_DLL +# ifdef DLL_EXPORT + /* This is set by libtool when files are compiled for a DLL; libtool + * always compiles twice, even on systems where it isn't necessary. Set + * PNG_BUILD_DLL in case it is necessary: + */ +# define PNG_BUILD_DLL +# else +# ifdef _WINDLL + /* This is set by the Microsoft Visual Studio IDE in projects that + * build a DLL. It can't easily be removed from those projects (it + * isn't visible in the Visual Studio UI) so it is a fairly reliable + * indication that PNG_IMPEXP needs to be set to the DLL export + * attributes. + */ +# define PNG_BUILD_DLL +# else +# ifdef __DLL__ + /* This is set by the Borland C system when compiling for a DLL + * (as above.) + */ +# define PNG_BUILD_DLL +# else + /* Add additional compiler cases here. */ +# endif +# endif +# endif +#endif /* Setting PNG_BUILD_DLL if required */ + +/* See pngconf.h for more details: the builder of the library may set this on + * the command line to the right thing for the specific compilation system or it + * may be automagically set above (at present we know of no system where it does + * need to be set on the command line.) + * + * PNG_IMPEXP must be set here when building the library to prevent pngconf.h + * setting it to the "import" setting for a DLL build. + */ +#ifndef PNG_IMPEXP +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP PNG_DLL_EXPORT +# else + /* Not building a DLL, or the DLL doesn't require specific export + * definitions. + */ +# define PNG_IMPEXP +# endif +#endif + +/* No warnings for private or deprecated functions in the build: */ +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE +#endif + +/* Symbol preprocessing support. + * + * To enable listing global, but internal, symbols the following macros should + * always be used to declare an extern data or function object in this file. + */ +#ifndef PNG_INTERNAL_DATA +# define PNG_INTERNAL_DATA(type, name, array) extern type name array +#endif + +#ifndef PNG_INTERNAL_FUNCTION +# define PNG_INTERNAL_FUNCTION(type, name, args, attributes)\ + extern PNG_FUNCTION(type, name, args, PNG_EMPTY attributes) +#endif + +/* If floating or fixed point APIs are disabled they may still be compiled + * internally. To handle this make sure they are declared as the appropriate + * internal extern function (otherwise the symbol prefixing stuff won't work and + * the functions will be used without definitions.) + * + * NOTE: although all the API functions are declared here they are not all + * actually built! Because the declarations are still made it is necessary to + * fake out types that they depend on. + */ +#ifndef PNG_FP_EXPORT +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY); +# ifndef PNG_VERSION_INFO_ONLY + typedef struct png_incomplete png_double; + typedef png_double* png_doublep; + typedef const png_double* png_const_doublep; + typedef png_double** png_doublepp; +# endif +# endif +#endif +#ifndef PNG_FIXED_EXPORT +# ifndef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY); +# endif +#endif + +#include "png.h" + +/* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */ +#ifndef PNG_DLL_EXPORT +# define PNG_DLL_EXPORT +#endif + +/* SECURITY and SAFETY: + * + * By default libpng is built without any internal limits on image size, + * individual heap (png_malloc) allocations or the total amount of memory used. + * If PNG_SAFE_LIMITS_SUPPORTED is defined, however, the limits below are used + * (unless individually overridden). These limits are believed to be fairly + * safe, but builders of secure systems should verify the values against the + * real system capabilities. + */ +#ifdef PNG_SAFE_LIMITS_SUPPORTED + /* 'safe' limits */ +# ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000 +# endif +# ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000 +# endif +# ifndef PNG_USER_CHUNK_CACHE_MAX +# define PNG_USER_CHUNK_CACHE_MAX 128 +# endif +# ifndef PNG_USER_CHUNK_MALLOC_MAX +# define PNG_USER_CHUNK_MALLOC_MAX 8000000 +# endif +#else + /* values for no limits */ +# ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 0x7fffffff +# endif +# ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 0x7fffffff +# endif +# ifndef PNG_USER_CHUNK_CACHE_MAX +# define PNG_USER_CHUNK_CACHE_MAX 0 +# endif +# ifndef PNG_USER_CHUNK_MALLOC_MAX +# define PNG_USER_CHUNK_MALLOC_MAX 0 +# endif +#endif + +/* Moved to pngpriv.h at libpng-1.5.0 */ +/* NOTE: some of these may have been used in external applications as + * these definitions were exposed in pngconf.h prior to 1.5. + */ + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. + * + * zlib provides 'MAXSEG_64K' which, if defined, indicates the + * same limit and pngconf.h (already included) sets the limit + * if certain operating systems are detected. + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +#ifndef PNG_UNUSED +/* Unused formal parameter warnings are silenced using the following macro + * which is expected to have no bad effects on performance (optimizing + * compilers will probably remove it entirely). Note that if you replace + * it with something other than whitespace, you must include the terminating + * semicolon. + */ +# define PNG_UNUSED(param) (void)param; +#endif + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + +/* If warnings or errors are turned off the code is disabled or redirected here. + * From 1.5.4 functions have been added to allow very limited formatting of + * error and warning messages - this code will also be disabled here. + */ +#ifdef PNG_WARNINGS_SUPPORTED +# define PNG_WARNING_PARAMETERS(p) png_warning_parameters p; +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +# define png_warning_parameter(p,number,string) ((void)0) +# define png_warning_parameter_unsigned(p,number,format,value) ((void)0) +# define png_warning_parameter_signed(p,number,format,value) ((void)0) +# define png_formatted_warning(pp,p,message) ((void)(pp)) +# define PNG_WARNING_PARAMETERS(p) +#endif +#ifndef PNG_ERROR_TEXT_SUPPORTED +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +# define png_fixed_error(s1,s2) png_err(s1) +#endif + +/* C allows up-casts from (void*) to any pointer and (const void*) to any + * pointer to a const object. C++ regards this as a type error and requires an + * explicit, static, cast and provides the static_cast<> rune to ensure that + * const is not cast away. + */ +#ifdef __cplusplus +# define png_voidcast(type, value) static_cast(value) +# define png_constcast(type, value) const_cast(value) +# define png_aligncast(type, value) \ + static_cast(static_cast(value)) +# define png_aligncastconst(type, value) \ + static_cast(static_cast(value)) +#else +# define png_voidcast(type, value) (value) +# define png_constcast(type, value) ((type)(value)) +# define png_aligncast(type, value) ((void*)(value)) +# define png_aligncastconst(type, value) ((const void*)(value)) +#endif /* __cplusplus */ + +/* Some fixed point APIs are still required even if not exported because + * they get used by the corresponding floating point APIs. This magic + * deals with this: + */ +#ifdef PNG_FIXED_POINT_SUPPORTED +# define PNGFAPI PNGAPI +#else +# define PNGFAPI /* PRIVATE */ +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) + /* png.c requires the following ANSI-C constants if the conversion of + * floating point to ASCII is implemented therein: + * + * DBL_DIG Maximum number of decimal digits (can be set to any constant) + * DBL_MIN Smallest normalized fp number (can be set to an arbitrary value) + * DBL_MAX Maximum floating point number (can be set to an arbitrary value) + */ +# include + +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif +# else +# include +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include +# endif +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include +# include +#endif + +#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ + defined(_WIN32) || defined(__WIN32__) +# include /* defines _WINDOWS_ macro */ +#endif +#endif /* PNG_VERSION_INFO_ONLY */ + +/* Moved here around 1.5.0beta36 from pngconf.h */ +/* Users may want to use these so they are not private. Any library + * functions that are passed far data must be model-independent. + */ + +/* Memory model/platform independent fns */ +#ifndef PNG_ABORT +# ifdef _WINDOWS_ +# define PNG_ABORT() ExitProcess(0) +# else +# define PNG_ABORT() abort() +# endif +#endif + +/* These macros may need to be architecture dependent. */ +#define PNG_ALIGN_NONE 0 /* do not use data alignment */ +#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */ +#ifdef offsetof +# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */ +#else +# define PNG_ALIGN_OFFSET -1 /* prevent the use of this */ +#endif +#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */ + +#ifndef PNG_ALIGN_TYPE + /* Default to using aligned access optimizations and requiring alignment to a + * multiple of the data type size. Override in a compiler specific fashion + * if necessary by inserting tests here: + */ +# define PNG_ALIGN_TYPE PNG_ALIGN_SIZE +#endif + +#if PNG_ALIGN_TYPE == PNG_ALIGN_SIZE + /* This is used because in some compiler implementations non-aligned + * structure members are supported, so the offsetof approach below fails. + * Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access + * is good for performance. Do not do this unless you have tested the result + * and understand it. + */ +# define png_alignof(type) (sizeof (type)) +#else +# if PNG_ALIGN_TYPE == PNG_ALIGN_OFFSET +# define png_alignof(type) offsetof(struct{char c; type t;}, t) +# else +# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS +# define png_alignof(type) (1) +# endif + /* Else leave png_alignof undefined to prevent use thereof */ +# endif +#endif + +/* This implicitly assumes alignment is always to a power of 2. */ +#ifdef png_alignof +# define png_isaligned(ptr, type)\ + ((((const char*)ptr-(const char*)0) & (png_alignof(type)-1)) == 0) +#else +# define png_isaligned(ptr, type) 0 +#endif + +/* End of memory model/platform independent support */ +/* End of 1.5.0beta36 move from pngconf.h */ + +/* CONSTANTS and UTILITY MACROS + * These are used internally by libpng and not exposed in the API + */ + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. Three of these + * are defined in png.h because they need to be visible to applications + * that call png_set_unknown_chunk(). + */ +/* #define PNG_HAVE_IHDR 0x01 (defined in png.h) */ +/* #define PNG_HAVE_PLTE 0x02 (defined in png.h) */ +#define PNG_HAVE_IDAT 0x04 +/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */ +#define PNG_HAVE_IEND 0x10 + /* 0x20 (unused) */ + /* 0x40 (unused) */ + /* 0x80 (unused) */ +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + /* 0x4000 (unused) */ +#define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */ + +/* Flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_QUANTIZE 0x0040 +#define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ +#define PNG_BACKGROUND_EXPAND 0x0100 +#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ +#define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000 +#define PNG_PACKSWAP 0x10000 +#define PNG_SWAP_ALPHA 0x20000 +#define PNG_STRIP_ALPHA 0x40000 +#define PNG_INVERT_ALPHA 0x80000 +#define PNG_USER_TRANSFORM 0x100000 +#define PNG_RGB_TO_GRAY_ERR 0x200000 +#define PNG_RGB_TO_GRAY_WARN 0x400000 +#define PNG_RGB_TO_GRAY 0x600000 /* two bits, RGB_TO_GRAY_ERR|WARN */ +#define PNG_ENCODE_ALPHA 0x800000 /* Added to libpng-1.5.4 */ +#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */ +#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */ + /* 0x8000000 unused */ + /* 0x10000000 unused */ + /* 0x20000000 unused */ + /* 0x40000000 unused */ +/* Flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* Flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */ + /* 0x0004 unused */ +#define PNG_FLAG_ZSTREAM_ENDED 0x0008 /* Added to libpng-1.6.0 */ + /* 0x0010 unused */ + /* 0x0020 unused */ +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 +#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ +/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 */ +/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 */ +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000 +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000 +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000 +#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000 /* Added to libpng-1.4.0 */ +#define PNG_FLAG_APP_WARNINGS_WARN 0x200000 /* Added to libpng-1.6.0 */ +#define PNG_FLAG_APP_ERRORS_WARN 0x400000 /* Added to libpng-1.6.0 */ + /* 0x800000 unused */ + /* 0x1000000 unused */ + /* 0x2000000 unused */ + /* 0x4000000 unused */ + /* 0x8000000 unused */ + /* 0x10000000 unused */ + /* 0x20000000 unused */ + /* 0x40000000 unused */ + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* Save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.6.0: scale a 16-bit value in the range 0..65535 to 0..255 + * by dividing by 257 *with rounding*. This macro is exact for the given range. + * See the discourse in pngrtran.c png_do_scale_16_to_8. The values in the + * macro were established by experiment (modifying the added value). The macro + * has a second variant that takes a value already scaled by 255 and divides by + * 65535 - this has a maximum error of .502. Over the range 0..65535*65535 it + * only gives off-by-one errors and only for 0.5% (1 in 200) of the values. + */ +#define PNG_DIV65535(v24) (((v24) + 32895) >> 16) +#define PNG_DIV257(v16) PNG_DIV65535((png_uint_32)(v16) * 255) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ + (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + * ideal-delta..ideal+delta. Each argument is evaluated twice. + * "ideal" and "delta" should be constants, normally simple + * integers, "value" a variable. Added to libpng-1.2.6 JB + */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* Conversions between fixed and floating point, only defined if + * required (to make sure the code doesn't accidentally use float + * when it is supposedly disabled.) + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* The floating point conversion can't overflow, though it can and + * does lose accuracy relative to the original fixed point value. + * In practice this doesn't matter because png_fixed_point only + * stores numbers with very low precision. The png_ptr and s + * arguments are unused by default but are there in case error + * checking becomes a requirement. + */ +#define png_float(png_ptr, fixed, s) (.00001 * (fixed)) + +/* The fixed point conversion performs range checking and evaluates + * its argument multiple times, so must be used with care. The + * range checking uses the PNG specification values for a signed + * 32 bit fixed point value except that the values are deliberately + * rounded-to-zero to an integral value - 21474 (21474.83 is roughly + * (2^31-1) * 100000). 's' is a string that describes the value being + * converted. + * + * NOTE: this macro will raise a png_error if the range check fails, + * therefore it is normally only appropriate to use this on values + * that come from API calls or other sources where an out of range + * error indicates a programming error, not a data error! + * + * NOTE: by default this is off - the macro is not used - because the + * function call saves a lot of code. + */ +#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED +#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\ + ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0)) +#endif +/* else the corresponding function is defined below, inside the scope of the + * cplusplus test. + */ +#endif + +/* Constants for known chunk types. If you need to add a chunk, define the name + * here. For historical reasons these constants have the form png_; i.e. + * the prefix is lower case. Please use decimal values as the parameters to + * match the ISO PNG specification and to avoid relying on the C locale + * interpretation of character values. + * + * Prior to 1.5.6 these constants were strings, as of 1.5.6 png_uint_32 values + * are computed and a new macro (PNG_STRING_FROM_CHUNK) added to allow a string + * to be generated if required. + * + * PNG_32b correctly produces a value shifted by up to 24 bits, even on + * architectures where (int) is only 16 bits. + */ +#define PNG_32b(b,s) ((png_uint_32)(b) << (s)) +#define PNG_U32(b1,b2,b3,b4) \ + (PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0)) + +/* Constants for known chunk types. + * + * MAINTAINERS: If you need to add a chunk, define the name here. + * For historical reasons these constants have the form png_; i.e. + * the prefix is lower case. Please use decimal values as the parameters to + * match the ISO PNG specification and to avoid relying on the C locale + * interpretation of character values. Please keep the list sorted. + * + * Notice that PNG_U32 is used to define a 32-bit value for the 4 byte chunk + * type. In fact the specification does not express chunk types this way, + * however using a 32-bit value means that the chunk type can be read from the + * stream using exactly the same code as used for a 32-bit unsigned value and + * can be examined far more efficiently (using one arithmetic compare). + * + * Prior to 1.5.6 the chunk type constants were expressed as C strings. The + * libpng API still uses strings for 'unknown' chunks and a macro, + * PNG_STRING_FROM_CHUNK, allows a string to be generated if required. Notice + * that for portable code numeric values must still be used; the string "IHDR" + * is not portable and neither is PNG_U32('I', 'H', 'D', 'R'). + * + * In 1.7.0 the definitions will be made public in png.h to avoid having to + * duplicate the same definitions in application code. + */ +#define png_IDAT PNG_U32( 73, 68, 65, 84) +#define png_IEND PNG_U32( 73, 69, 78, 68) +#define png_IHDR PNG_U32( 73, 72, 68, 82) +#define png_PLTE PNG_U32( 80, 76, 84, 69) +#define png_bKGD PNG_U32( 98, 75, 71, 68) +#define png_cHRM PNG_U32( 99, 72, 82, 77) +#define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */ +#define png_gAMA PNG_U32(103, 65, 77, 65) +#define png_gIFg PNG_U32(103, 73, 70, 103) +#define png_gIFt PNG_U32(103, 73, 70, 116) /* deprecated */ +#define png_gIFx PNG_U32(103, 73, 70, 120) +#define png_hIST PNG_U32(104, 73, 83, 84) +#define png_iCCP PNG_U32(105, 67, 67, 80) +#define png_iTXt PNG_U32(105, 84, 88, 116) +#define png_oFFs PNG_U32(111, 70, 70, 115) +#define png_pCAL PNG_U32(112, 67, 65, 76) +#define png_pHYs PNG_U32(112, 72, 89, 115) +#define png_sBIT PNG_U32(115, 66, 73, 84) +#define png_sCAL PNG_U32(115, 67, 65, 76) +#define png_sPLT PNG_U32(115, 80, 76, 84) +#define png_sRGB PNG_U32(115, 82, 71, 66) +#define png_sTER PNG_U32(115, 84, 69, 82) +#define png_tEXt PNG_U32(116, 69, 88, 116) +#define png_tIME PNG_U32(116, 73, 77, 69) +#define png_tRNS PNG_U32(116, 82, 78, 83) +#define png_zTXt PNG_U32(122, 84, 88, 116) + +/* The following will work on (signed char*) strings, whereas the get_uint_32 + * macro will fail on top-bit-set values because of the sign extension. + */ +#define PNG_CHUNK_FROM_STRING(s)\ + PNG_U32(0xff&(s)[0], 0xff&(s)[1], 0xff&(s)[2], 0xff&(s)[3]) + +/* This uses (char), not (png_byte) to avoid warnings on systems where (char) is + * signed and the argument is a (char[]) This macro will fail miserably on + * systems where (char) is more than 8 bits. + */ +#define PNG_STRING_FROM_CHUNK(s,c)\ + (void)(((char*)(s))[0]=(char)((c)>>24), ((char*)(s))[1]=(char)((c)>>16),\ + ((char*)(s))[2]=(char)((c)>>8), ((char*)(s))[3]=(char)((c))) + +/* Do the same but terminate with a null character. */ +#define PNG_CSTRING_FROM_CHUNK(s,c)\ + (void)(PNG_STRING_FROM_CHUNK(s,c), ((char*)(s))[4] = 0) + +/* Test on flag values as defined in the spec (section 5.4): */ +#define PNG_CHUNK_ANCILLARY(c) (1 & ((c) >> 29)) +#define PNG_CHUNK_CRITICAL(c) (!PNG_CHUNK_ANCILLARY(c)) +#define PNG_CHUNK_PRIVATE(c) (1 & ((c) >> 21)) +#define PNG_CHUNK_RESERVED(c) (1 & ((c) >> 13)) +#define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >> 5)) + +/* Gamma values (new at libpng-1.5.4): */ +#define PNG_GAMMA_MAC_OLD 151724 /* Assume '1.8' is really 2.2/1.45! */ +#define PNG_GAMMA_MAC_INVERSE 65909 +#define PNG_GAMMA_sRGB_INVERSE 45455 + +/* Almost everything below is C specific; the #defines above can be used in + * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot. + */ +#ifndef PNG_VERSION_INFO_ONLY + +#include "pngstruct.h" +#include "pnginfo.h" + +/* Validate the include paths - the include path used to generate pnglibconf.h + * must match that used in the build, or we must be using pnglibconf.h.prebuilt: + */ +#if PNG_ZLIB_VERNUM != 0 && PNG_ZLIB_VERNUM != ZLIB_VERNUM +# error ZLIB_VERNUM != PNG_ZLIB_VERNUM \ + "-I (include path) error: see the notes in pngpriv.h" + /* This means that when pnglibconf.h was built the copy of zlib.h that it + * used is not the same as the one being used here. Because the build of + * libpng makes decisions to use inflateInit2 and inflateReset2 based on the + * zlib version number and because this affects handling of certain broken + * PNG files the -I directives must match. + * + * The most likely explanation is that you passed a -I in CFLAGS, this will + * not work; all the preprocessor directories and in particular all the -I + * directives must be in CPPFLAGS. + */ +#endif + +/* This is used for 16 bit gamma tables -- only the top level pointers are + * const; this could be changed: + */ +typedef const png_uint_16p * png_const_uint_16pp; + +/* Added to libpng-1.5.7: sRGB conversion tables */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_table, [256]); + /* Convert from an sRGB encoded value 0..255 to a 16-bit linear value, + * 0..65535. This table gives the closest 16-bit answers (no errors). + */ +#endif + +PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_base, [512]); +PNG_INTERNAL_DATA(const png_byte, png_sRGB_delta, [512]); + +#define PNG_sRGB_FROM_LINEAR(linear) ((png_byte)((png_sRGB_base[(linear)>>15] +\ + ((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8)) + /* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB + * encoded value with maximum error 0.646365. Note that the input is not a + * 16-bit value; it has been multiplied by 255! */ +#endif /* PNG_SIMPLIFIED_READ/WRITE */ + + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Internal functions; these are not exported from a DLL however because they + * are used within several of the C source files they have to be C extern. + * + * All of these functions must be declared with PNG_INTERNAL_FUNCTION. + */ + +/* Zlib support */ +#define PNG_UNEXPECTED_ZLIB_RETURN (-7) +PNG_INTERNAL_FUNCTION(void, png_zstream_error,(png_structrp png_ptr, int ret), + PNG_EMPTY); + /* Used by the zlib handling functions to ensure that z_stream::msg is always + * set before they return. + */ + +#ifdef PNG_WRITE_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr, + png_compression_bufferp *list),PNG_EMPTY); + /* Free the buffer list used by the compressed write code. */ +#endif + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \ + (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \ + defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \ + (defined(PNG_sCAL_SUPPORTED) && \ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)) +PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr, + double fp, png_const_charp text),PNG_EMPTY); +#endif + +/* Check the user version string for compatibility, returns false if the version + * numbers aren't compatible. + */ +PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr, + png_const_charp user_png_ver),PNG_EMPTY); + +/* Internal base allocator - no messages, NULL on failure to allocate. This + * does, however, call the application provided allocator and that could call + * png_error (although that would be a bug in the application implementation.) + */ +PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_base,(png_const_structrp png_ptr, + png_alloc_size_t size),PNG_ALLOCATED); + +#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\ + defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) +/* Internal array allocator, outputs no error or warning messages on failure, + * just returns NULL. + */ +PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_array,(png_const_structrp png_ptr, + int nelements, size_t element_size),PNG_ALLOCATED); + +/* The same but an existing array is extended by add_elements. This function + * also memsets the new elements to 0 and copies the old elements. The old + * array is not freed or altered. + */ +PNG_INTERNAL_FUNCTION(png_voidp,png_realloc_array,(png_const_structrp png_ptr, + png_const_voidp array, int old_elements, int add_elements, + size_t element_size),PNG_ALLOCATED); +#endif /* text, sPLT or unknown chunks */ + +/* Magic to create a struct when there is no struct to call the user supplied + * memory allocators. Because error handling has not been set up the memory + * handlers can't safely call png_error, but this is an obscure and undocumented + * restriction so libpng has to assume that the 'free' handler, at least, might + * call png_error. + */ +PNG_INTERNAL_FUNCTION(png_structp,png_create_png_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn, + png_free_ptr free_fn),PNG_ALLOCATED); + +/* Free memory from internal libpng struct */ +PNG_INTERNAL_FUNCTION(void,png_destroy_png_struct,(png_structrp png_ptr), + PNG_EMPTY); + +/* Free an allocated jmp_buf (always succeeds) */ +PNG_INTERNAL_FUNCTION(void,png_free_jmpbuf,(png_structrp png_ptr),PNG_EMPTY); + +/* Function to allocate memory for zlib. PNGAPI is disallowed. */ +PNG_INTERNAL_FUNCTION(voidpf,png_zalloc,(voidpf png_ptr, uInt items, uInt size), + PNG_ALLOCATED); + +/* Function to free memory for zlib. PNGAPI is disallowed. */ +PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY); + +/* Next four functions are used internally as callbacks. PNGCBAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to + * PNGCBAPI at 1.5.0 + */ + +PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr, + png_bytep data, png_size_t length),PNG_EMPTY); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr, + png_bytep buffer, png_size_t length),PNG_EMPTY); +#endif + +PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr, + png_bytep data, png_size_t length),PNG_EMPTY); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED +PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_flush,(png_structp png_ptr), + PNG_EMPTY); +# endif +#endif + +/* Reset the CRC variable */ +PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY); + +/* Write the "data" buffer to whatever output you are using */ +PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr, + png_const_bytep data, png_size_t length),PNG_EMPTY); + +/* Read and check the PNG file signature */ +PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); + +/* Read the chunk header (length + type name) */ +PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr), + PNG_EMPTY); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data, + png_size_t length),PNG_EMPTY); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf, + png_uint_32 length),PNG_EMPTY); + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr, + png_uint_32 skip),PNG_EMPTY); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr, + png_const_bytep ptr, png_size_t length),PNG_EMPTY); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); +#endif + +/* Write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_INTERNAL_FUNCTION(void,png_write_IHDR,(png_structrp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, + int compression_method, int filter_method, int interlace_method),PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_write_PLTE,(png_structrp png_ptr, + png_const_colorp palette, png_uint_32 num_pal),PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_compress_IDAT,(png_structrp png_ptr, + png_const_bytep row_data, png_alloc_size_t row_data_length, int flush), + PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_write_IEND,(png_structrp png_ptr),PNG_EMPTY); + +#ifdef PNG_WRITE_gAMA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_gAMA_fixed,(png_structrp png_ptr, + png_fixed_point file_gamma),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_sBIT,(png_structrp png_ptr, + png_const_color_8p sbit, int color_type),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr, + const png_xy *xy), PNG_EMPTY); + /* The xy value must have been previously validated */ +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr, + int intent),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr, + png_const_charp name, png_const_bytep profile), PNG_EMPTY); + /* The profile must have been previously validated for correctness, the + * length comes from the first four bytes. Only the base, deflate, + * compression is supported. + */ +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_sPLT,(png_structrp png_ptr, + png_const_sPLT_tp palette),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_tRNS,(png_structrp png_ptr, + png_const_bytep trans, png_const_color_16p values, int number, + int color_type),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_bKGD,(png_structrp png_ptr, + png_const_color_16p values, int color_type),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr, + png_const_uint_16p hist, int num_hist),PNG_EMPTY); +#endif + +/* Chunks that have keywords */ +#ifdef PNG_WRITE_tEXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr, + png_const_charp key, png_const_charp text, png_size_t text_len),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_zTXt,(png_structrp png_ptr, png_const_charp + key, png_const_charp text, png_size_t text_len, int compression),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_iTXt,(png_structrp png_ptr, + int compression, png_const_charp key, png_const_charp lang, + png_const_charp lang_key, png_const_charp text),PNG_EMPTY); +#endif + +#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ +PNG_INTERNAL_FUNCTION(int,png_set_text_2,(png_const_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_oFFs,(png_structrp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_pCAL,(png_structrp png_ptr, + png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, + png_const_charp units, png_charpp params),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_pHYs,(png_structrp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_tIME,(png_structrp png_ptr, + png_const_timep mod_time),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_sCAL_s,(png_structrp png_ptr, + int unit, png_const_charp width, png_const_charp height),PNG_EMPTY); +#endif + +/* Called when finished processing a row of data */ +PNG_INTERNAL_FUNCTION(void,png_write_finish_row,(png_structrp png_ptr), + PNG_EMPTY); + +/* Internal use only. Called before first row of data */ +PNG_INTERNAL_FUNCTION(void,png_write_start_row,(png_structrp png_ptr), + PNG_EMPTY); + +/* Combine a row of data, dealing with alpha, etc. if requested. 'row' is an + * array of png_ptr->width pixels. If the image is not interlaced or this + * is the final pass this just does a memcpy, otherwise the "display" flag + * is used to determine whether to copy pixels that are not in the current pass. + * + * Because 'png_do_read_interlace' (below) replicates pixels this allows this + * function to achieve the documented 'blocky' appearance during interlaced read + * if display is 1 and the 'sparkle' appearance, where existing pixels in 'row' + * are not changed if they are not in the current pass, when display is 0. + * + * 'display' must be 0 or 1, otherwise the memcpy will be done regardless. + * + * The API always reads from the png_struct row buffer and always assumes that + * it is full width (png_do_read_interlace has already been called.) + * + * This function is only ever used to write to row buffers provided by the + * caller of the relevant libpng API and the row must have already been + * transformed by the read transformations. + * + * The PNG_USE_COMPILE_TIME_MASKS option causes generation of pre-computed + * bitmasks for use within the code, otherwise runtime generated masks are used. + * The default is compile time masks. + */ +#ifndef PNG_USE_COMPILE_TIME_MASKS +# define PNG_USE_COMPILE_TIME_MASKS 1 +#endif +PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr, + png_bytep row, int display),PNG_EMPTY); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Expand an interlaced row: the 'row_info' describes the pass data that has + * been read in and must correspond to the pixels in 'row', the pixels are + * expanded (moved apart) in 'row' to match the final layout, when doing this + * the pixels are *replicated* to the intervening space. This is essential for + * the correct operation of png_combine_row, above. + */ +PNG_INTERNAL_FUNCTION(void,png_do_read_interlace,(png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations),PNG_EMPTY); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Grab pixels out of a row for an interlaced pass */ +PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info, + png_bytep row, int pass),PNG_EMPTY); +#endif + +/* Unfilter a row: check the filter value before calling this, there is no point + * calling it for PNG_FILTER_VALUE_NONE. + */ +PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop + row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); + +/* Choose the best filter to use and filter the row data */ +PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, + png_row_infop row_info),PNG_EMPTY); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr, + png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY); + /* Read 'avail_out' bytes of data from the IDAT stream. If the output buffer + * is NULL the function checks, instead, for the end of the stream. In this + * case a benign error will be issued if the stream end is not found or if + * extra data has to be consumed. + */ +PNG_INTERNAL_FUNCTION(void,png_read_finish_IDAT,(png_structrp png_ptr), + PNG_EMPTY); + /* This cleans up when the IDAT LZ stream does not end when the last image + * byte is read; there is still some pending input. + */ + +PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr), + PNG_EMPTY); + /* Finish a row while reading, dealing with interlacing passes, etc. */ +#endif + +/* Initialize the row buffers, etc. */ +PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +/* Optional call to update the users info structure */ +PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +#endif + +/* These are the functions that do the transformations */ +#ifdef PNG_READ_FILLER_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_read_filler,(png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags),PNG_EMPTY); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_read_swap_alpha,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_write_swap_alpha,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_read_invert_alpha,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_write_invert_alpha,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_strip_channel,(png_row_infop row_info, + png_bytep row, int at_start),PNG_EMPTY); +#endif + +#ifdef PNG_16BIT_SUPPORTED +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_swap,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_packswap,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +PNG_INTERNAL_FUNCTION(int,png_do_rgb_to_gray,(png_structrp png_ptr, + png_row_infop row_info, png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_gray_to_rgb,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_unpack,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_unshift,(png_row_infop row_info, + png_bytep row, png_const_color_8p sig_bits),PNG_EMPTY); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_invert,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_scale_16_to_8,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_chop,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_quantize,(png_row_infop row_info, + png_bytep row, png_const_bytep palette_lookup, + png_const_bytep quantize_lookup),PNG_EMPTY); + +# ifdef PNG_CORRECT_PALETTE_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_correct_palette,(png_structrp png_ptr, + png_colorp palette, int num_palette),PNG_EMPTY); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_pack,(png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_shift,(png_row_infop row_info, + png_bytep row, png_const_color_8p bit_depth),PNG_EMPTY); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_compose,(png_row_infop row_info, + png_bytep row, png_structrp png_ptr),PNG_EMPTY); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_gamma,(png_row_infop row_info, + png_bytep row, png_structrp png_ptr),PNG_EMPTY); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_encode_alpha,(png_row_infop row_info, + png_bytep row, png_structrp png_ptr),PNG_EMPTY); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_expand_palette,(png_row_infop row_info, + png_bytep row, png_const_colorp palette, png_const_bytep trans, + int num_trans),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_do_expand,(png_row_infop row_info, + png_bytep row, png_const_color_16p trans_color),PNG_EMPTY); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_expand_16,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* Decode the IHDR chunk */ +PNG_INTERNAL_FUNCTION(void,png_handle_IHDR,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_handle_PLTE,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_handle_IEND,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); + +#ifdef PNG_READ_bKGD_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_bKGD,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_hIST,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_iCCP,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_iTXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_oFFs,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_pCAL,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_pHYs,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_sBIT,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_sCAL,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_sPLT,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_sRGB_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_sRGB,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_tEXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_tIME,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_tRNS,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr, + png_uint_32 chunk_name),PNG_EMPTY); + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY); + /* This is the function that gets called for unknown chunks. The 'keep' + * argument is either non-zero for a known chunk that has been set to be + * handled as unknown or zero for an unknown chunk. By default the function + * just skips the chunk or errors out if it is critical. + */ + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) +PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling, + (png_const_structrp png_ptr, png_uint_32 chunk_name),PNG_EMPTY); + /* Exactly as the API png_handle_as_unknown() except that the argument is a + * 32-bit chunk name, not a string. + */ +#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */ +#endif /* PNG_SET_UNKNOWN_CHUNKS_SUPPORTED */ + +/* Handle the transformations for reading and writing */ +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_read_transformations,(png_structrp png_ptr, + png_row_infop row_info),PNG_EMPTY); +#endif +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_write_transformations,(png_structrp png_ptr, + png_row_infop row_info),PNG_EMPTY); +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_init_read_transformations,(png_structrp png_ptr), + PNG_EMPTY); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_push_read_chunk,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_sig,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_crc_skip,(png_structrp png_ptr, + png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_crc_finish,(png_structrp png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr, + png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr, + png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_have_row,(png_structrp png_ptr, + png_bytep row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_end,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_push_finish_row,(png_structrp png_ptr), + PNG_EMPTY); +# ifdef PNG_READ_tEXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_push_handle_tEXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_tEXt,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +# endif +# ifdef PNG_READ_zTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_push_handle_zTXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_zTXt,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +# endif +# ifdef PNG_READ_iTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_push_handle_iTXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_iTXt,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +# endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_read_intrapixel,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_do_write_intrapixel,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +/* Added at libpng version 1.6.0 */ +#ifdef PNG_GAMMA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_fixed_point gAMA), PNG_EMPTY); + /* Set the colorspace gamma with a value provided by the application or by + * the gAMA chunk on read. The value will override anything set by an ICC + * profile. + */ + +PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr, + png_inforp info_ptr), PNG_EMPTY); + /* Synchronize the info 'valid' flags with the colorspace */ + +PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr, + png_inforp info_ptr), PNG_EMPTY); + /* Copy the png_struct colorspace to the info_struct and call the above to + * synchronize the flags. Checks for NULL info_ptr and does nothing. + */ +#endif + +/* Added at libpng version 1.4.0 */ +#ifdef PNG_COLORSPACE_SUPPORTED +/* These internal functions are for maintaining the colorspace structure within + * a png_info or png_struct (or, indeed, both). + */ +PNG_INTERNAL_FUNCTION(int,png_colorspace_set_chromaticities, + (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_xy *xy, + int preferred), PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(int,png_colorspace_set_endpoints, + (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_XYZ *XYZ, + int preferred), PNG_EMPTY); + +#ifdef PNG_sRGB_SUPPORTED +PNG_INTERNAL_FUNCTION(int,png_colorspace_set_sRGB,(png_const_structrp png_ptr, + png_colorspacerp colorspace, int intent), PNG_EMPTY); + /* This does set the colorspace gAMA and cHRM values too, but doesn't set the + * flags to write them, if it returns false there was a problem and an error + * message has already been output (but the colorspace may still need to be + * synced to record the invalid flag). + */ +#endif /* sRGB */ + +#ifdef PNG_iCCP_SUPPORTED +PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length, png_const_bytep profile, int color_type), + PNG_EMPTY); + /* The 'name' is used for information only */ + +/* Routines for checking parts of an ICC profile. */ +PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length), PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length, + png_const_bytep profile /* first 132 bytes only */, int color_type), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length, + png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY); +#ifdef PNG_sRGB_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_icc_set_sRGB,( + png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_bytep profile, uLong adler), PNG_EMPTY); + /* 'adler' is the Adler32 checksum of the uncompressed profile data. It may + * be zero to indicate that it is not available. It is used, if provided, + * as a fast check on the profile when checking to see if it is sRGB. + */ +#endif +#endif /* iCCP */ + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_colorspace_set_rgb_coefficients, + (png_structrp png_ptr), PNG_EMPTY); + /* Set the rgb_to_gray coefficients from the colorspace Y values */ +#endif /* READ_RGB_TO_GRAY */ +#endif /* COLORSPACE */ + +/* Added at libpng version 1.4.0 */ +PNG_INTERNAL_FUNCTION(void,png_check_IHDR,(png_const_structrp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type),PNG_EMPTY); + +/* Added at libpng version 1.5.10 */ +#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \ + defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_check_palette_indexes, + (png_structrp png_ptr, png_row_infop row_info),PNG_EMPTY); +#endif + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_fixed_error,(png_const_structrp png_ptr, + png_const_charp name),PNG_NORETURN); +#endif + +/* Puts 'string' into 'buffer' at buffer[pos], taking care never to overwrite + * the end. Always leaves the buffer nul terminated. Never errors out (and + * there is no error code.) + */ +PNG_INTERNAL_FUNCTION(size_t,png_safecat,(png_charp buffer, size_t bufsize, + size_t pos, png_const_charp string),PNG_EMPTY); + +/* Various internal functions to handle formatted warning messages, currently + * only implemented for warnings. + */ +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) +/* Utility to dump an unsigned value into a buffer, given a start pointer and + * and end pointer (which should point just *beyond* the end of the buffer!) + * Returns the pointer to the start of the formatted string. This utility only + * does unsigned values. + */ +PNG_INTERNAL_FUNCTION(png_charp,png_format_number,(png_const_charp start, + png_charp end, int format, png_alloc_size_t number),PNG_EMPTY); + +/* Convenience macro that takes an array: */ +#define PNG_FORMAT_NUMBER(buffer,format,number) \ + png_format_number(buffer, buffer + (sizeof buffer), format, number) + +/* Suggested size for a number buffer (enough for 64 bits and a sign!) */ +#define PNG_NUMBER_BUFFER_SIZE 24 + +/* These are the integer formats currently supported, the name is formed from + * the standard printf(3) format string. + */ +#define PNG_NUMBER_FORMAT_u 1 /* chose unsigned API! */ +#define PNG_NUMBER_FORMAT_02u 2 +#define PNG_NUMBER_FORMAT_d 1 /* chose signed API! */ +#define PNG_NUMBER_FORMAT_02d 2 +#define PNG_NUMBER_FORMAT_x 3 +#define PNG_NUMBER_FORMAT_02x 4 +#define PNG_NUMBER_FORMAT_fixed 5 /* choose the signed API */ +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* New defines and members adding in libpng-1.5.4 */ +# define PNG_WARNING_PARAMETER_SIZE 32 +# define PNG_WARNING_PARAMETER_COUNT 8 /* Maximum 9; see pngerror.c */ + +/* An l-value of this type has to be passed to the APIs below to cache the + * values of the parameters to a formatted warning message. + */ +typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][ + PNG_WARNING_PARAMETER_SIZE]; + +PNG_INTERNAL_FUNCTION(void,png_warning_parameter,(png_warning_parameters p, + int number, png_const_charp string),PNG_EMPTY); + /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters, + * including the trailing '\0'. + */ +PNG_INTERNAL_FUNCTION(void,png_warning_parameter_unsigned, + (png_warning_parameters p, int number, int format, png_alloc_size_t value), + PNG_EMPTY); + /* Use png_alloc_size_t because it is an unsigned type as big as any we + * need to output. Use the following for a signed value. + */ +PNG_INTERNAL_FUNCTION(void,png_warning_parameter_signed, + (png_warning_parameters p, int number, int format, png_int_32 value), + PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_formatted_warning,(png_const_structrp png_ptr, + png_warning_parameters p, png_const_charp message),PNG_EMPTY); + /* 'message' follows the X/Open approach of using @1, @2 to insert + * parameters previously supplied using the above functions. Errors in + * specifying the parameters will simply result in garbage substitutions. + */ +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Application errors (new in 1.6); use these functions (declared below) for + * errors in the parameters or order of API function calls on read. The + * 'warning' should be used for an error that can be handled completely; the + * 'error' for one which can be handled safely but which may lose application + * information or settings. + * + * By default these both result in a png_error call prior to release, while in a + * released version the 'warning' is just a warning. However if the application + * explicitly disables benign errors (explicitly permitting the code to lose + * information) they both turn into warnings. + * + * If benign errors aren't supported they end up as the corresponding base call + * (png_warning or png_error.) + */ +PNG_INTERNAL_FUNCTION(void,png_app_warning,(png_const_structrp png_ptr, + png_const_charp message),PNG_EMPTY); + /* The application provided invalid parameters to an API function or called + * an API function at the wrong time, libpng can completely recover. + */ + +PNG_INTERNAL_FUNCTION(void,png_app_error,(png_const_structrp png_ptr, + png_const_charp message),PNG_EMPTY); + /* As above but libpng will ignore the call, or attempt some other partial + * recovery from the error. + */ +#else +# define png_app_warning(pp,s) png_warning(pp,s) +# define png_app_error(pp,s) png_error(pp,s) +#endif + +PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr, + png_const_charp message, int error),PNG_EMPTY); + /* Report a recoverable issue in chunk data. On read this is used to report + * a problem found while reading a particular chunk and the + * png_chunk_benign_error or png_chunk_warning function is used as + * appropriate. On write this is used to report an error that comes from + * data set via an application call to a png_set_ API and png_app_error or + * png_app_warning is used as appropriate. + * + * The 'error' parameter must have one of the following values: + */ +#define PNG_CHUNK_WARNING 0 /* never an error */ +#define PNG_CHUNK_WRITE_ERROR 1 /* an error only on write */ +#define PNG_CHUNK_ERROR 2 /* always an error */ + +/* ASCII to FP interfaces, currently only implemented if sCAL + * support is required. + */ +#if defined(PNG_sCAL_SUPPORTED) +/* MAX_DIGITS is actually the maximum number of characters in an sCAL + * width or height, derived from the precision (number of significant + * digits - a build time settable option) and assumptions about the + * maximum ridiculous exponent. + */ +#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/) + +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr, + png_charp ascii, png_size_t size, double fp, unsigned int precision), + PNG_EMPTY); +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, + png_charp ascii, png_size_t size, png_fixed_point fp),PNG_EMPTY); +#endif /* FIXED_POINT */ +#endif /* sCAL */ + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* An internal API to validate the format of a floating point number. + * The result is the index of the next character. If the number is + * not valid it will be the index of a character in the supposed number. + * + * The format of a number is defined in the PNG extensions specification + * and this API is strictly conformant to that spec, not anyone elses! + * + * The format as a regular expression is: + * + * [+-]?[0-9]+.?([Ee][+-]?[0-9]+)? + * + * or: + * + * [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)? + * + * The complexity is that either integer or fraction must be present and the + * fraction is permitted to have no digits only if the integer is present. + * + * NOTE: The dangling E problem. + * There is a PNG valid floating point number in the following: + * + * PNG floating point numbers are not greedy. + * + * Working this out requires *TWO* character lookahead (because of the + * sign), the parser does not do this - it will fail at the 'r' - this + * doesn't matter for PNG sCAL chunk values, but it requires more care + * if the value were ever to be embedded in something more complex. Use + * ANSI-C strtod if you need the lookahead. + */ +/* State table for the parser. */ +#define PNG_FP_INTEGER 0 /* before or in integer */ +#define PNG_FP_FRACTION 1 /* before or in fraction */ +#define PNG_FP_EXPONENT 2 /* before or in exponent */ +#define PNG_FP_STATE 3 /* mask for the above */ +#define PNG_FP_SAW_SIGN 4 /* Saw +/- in current state */ +#define PNG_FP_SAW_DIGIT 8 /* Saw a digit in current state */ +#define PNG_FP_SAW_DOT 16 /* Saw a dot in current state */ +#define PNG_FP_SAW_E 32 /* Saw an E (or e) in current state */ +#define PNG_FP_SAW_ANY 60 /* Saw any of the above 4 */ + +/* These three values don't affect the parser. They are set but not used. + */ +#define PNG_FP_WAS_VALID 64 /* Preceding substring is a valid fp number */ +#define PNG_FP_NEGATIVE 128 /* A negative number, including "-0" */ +#define PNG_FP_NONZERO 256 /* A non-zero value */ +#define PNG_FP_STICKY 448 /* The above three flags */ + +/* This is available for the caller to store in 'state' if required. Do not + * call the parser after setting it (the parser sometimes clears it.) + */ +#define PNG_FP_INVALID 512 /* Available for callers as a distinct value */ + +/* Result codes for the parser (boolean - true meants ok, false means + * not ok yet.) + */ +#define PNG_FP_MAYBE 0 /* The number may be valid in the future */ +#define PNG_FP_OK 1 /* The number is valid */ + +/* Tests on the sticky non-zero and negative flags. To pass these checks + * the state must also indicate that the whole number is valid - this is + * achieved by testing PNG_FP_SAW_DIGIT (see the implementation for why this + * is equivalent to PNG_FP_OK above.) + */ +#define PNG_FP_NZ_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NEGATIVE | PNG_FP_NONZERO) + /* NZ_MASK: the string is valid and a non-zero negative value */ +#define PNG_FP_Z_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NONZERO) + /* Z MASK: the string is valid and a non-zero value. */ + /* PNG_FP_SAW_DIGIT: the string is valid. */ +#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT) +#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK) +#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK) + +/* The actual parser. This can be called repeatedly. It updates + * the index into the string and the state variable (which must + * be initialized to 0). It returns a result code, as above. There + * is no point calling the parser any more if it fails to advance to + * the end of the string - it is stuck on an invalid character (or + * terminated by '\0'). + * + * Note that the pointer will consume an E or even an E+ and then leave + * a 'maybe' state even though a preceding integer.fraction is valid. + * The PNG_FP_WAS_VALID flag indicates that a preceding substring was + * a valid number. It's possible to recover from this by calling + * the parser again (from the start, with state 0) but with a string + * that omits the last character (i.e. set the size to the index of + * the problem character.) This has not been tested within libpng. + */ +PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, + png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); + +/* This is the same but it checks a complete string and returns true + * only if it just contains a floating point number. As of 1.5.4 this + * function also returns the state at the end of parsing the number if + * it was valid (otherwise it returns 0.) This can be used for testing + * for negative or zero values using the sticky flag. + */ +PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string, + png_size_t size),PNG_EMPTY); +#endif /* pCAL || sCAL */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) ||\ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) +/* Added at libpng version 1.5.0 */ +/* This is a utility to provide a*times/div (rounded) and indicate + * if there is an overflow. The result is a boolean - false (0) + * for overflow, true (1) if no overflow, in which case *res + * holds the result. + */ +PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a, + png_int_32 multiplied_by, png_int_32 divided_by),PNG_EMPTY); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* Same deal, but issue a warning on overflow and return 0. */ +PNG_INTERNAL_FUNCTION(png_fixed_point,png_muldiv_warn, + (png_const_structrp png_ptr, png_fixed_point a, png_int_32 multiplied_by, + png_int_32 divided_by),PNG_EMPTY); +#endif + +#ifdef PNG_GAMMA_SUPPORTED +/* Calculate a reciprocal - used for gamma values. This returns + * 0 if the argument is 0 in order to maintain an undefined value; + * there are no warnings. + */ +PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a), + PNG_EMPTY); + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The same but gives a reciprocal of the product of two fixed point + * values. Accuracy is suitable for gamma calculations but this is + * not exact - use png_muldiv for that. Only required at present on read. + */ +PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a, + png_fixed_point b),PNG_EMPTY); +#endif + +/* Return true if the gamma value is significantly different from 1.0 */ +PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value), + PNG_EMPTY); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Internal fixed point gamma correction. These APIs are called as + * required to convert single values - they don't need to be fast, + * they are not used when processing image pixel values. + * + * While the input is an 'unsigned' value it must actually be the + * correct bit value - 0..255 or 0..65535 as required. + */ +PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_correct,(png_structrp png_ptr, + unsigned int value, png_fixed_point gamma_value),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_16bit_correct,(unsigned int value, + png_fixed_point gamma_value),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(png_byte,png_gamma_8bit_correct,(unsigned int value, + png_fixed_point gamma_value),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr, + int bit_depth),PNG_EMPTY); +#endif + +/* SIMPLIFIED READ/WRITE SUPPORT */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) +/* The internal structure that png_image::opaque points to. */ +typedef struct png_control +{ + png_structp png_ptr; + png_infop info_ptr; + png_voidp error_buf; /* Always a jmp_buf at present. */ + + png_const_bytep memory; /* Memory buffer. */ + png_size_t size; /* Size of the memory buffer. */ + + unsigned int for_write :1; /* Otherwise it is a read structure */ + unsigned int owned_file :1; /* We own the file in io_ptr */ +} png_control; + +/* Return the pointer to the jmp_buf from a png_control: necessary because C + * does not reveal the type of the elements of jmp_buf. + */ +#ifdef __cplusplus +# define png_control_jmp_buf(pc) (((jmp_buf*)((pc)->error_buf))[0]) +#else +# define png_control_jmp_buf(pc) ((pc)->error_buf) +#endif + +/* Utility to safely execute a piece of libpng code catching and logging any + * errors that might occur. Returns true on success, false on failure (either + * of the function or as a result of a png_error.) + */ +PNG_INTERNAL_FUNCTION(void,png_safe_error,(png_structp png_ptr, + png_const_charp error_message),PNG_NORETURN); + +#ifdef PNG_WARNINGS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_safe_warning,(png_structp png_ptr, + png_const_charp warning_message),PNG_EMPTY); +#else +# define png_safe_warning 0/*dummy argument*/ +#endif + +PNG_INTERNAL_FUNCTION(int,png_safe_execute,(png_imagep image, + int (*function)(png_voidp), png_voidp arg),PNG_EMPTY); + +/* Utility to log an error; this also cleans up the png_image; the function + * always returns 0 (false). + */ +PNG_INTERNAL_FUNCTION(int,png_image_error,(png_imagep image, + png_const_charp error_message),PNG_EMPTY); + +#ifndef PNG_SIMPLIFIED_READ_SUPPORTED +/* png_image_free is used by the write code but not exported */ +PNG_INTERNAL_FUNCTION(void, png_image_free, (png_imagep image), PNG_EMPTY); +#endif /* !SIMPLIFIED_READ */ + +#endif /* SIMPLIFIED READ/WRITE */ + +/* These are initialization functions for hardware specific PNG filter + * optimizations; list these here then select the appropriate one at compile + * time using the macro PNG_FILTER_OPTIMIZATIONS. If the macro is not defined + * the generic code is used. + */ +#ifdef PNG_FILTER_OPTIMIZATIONS +PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr, + unsigned int bpp), PNG_EMPTY); + /* Just declare the optimization that will be used */ +#else + /* List *all* the possible optimizations here - this branch is required if + * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in + * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing. + */ +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +#endif + +/* Maintainer: Put new private prototypes here ^ */ + +#include "pngdebug.h" + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +#endif /* PNGPRIV_H */ diff --git a/ext/libpng16/pngread.c b/ext/libpng16/pngread.c new file mode 100644 index 0000000000..8709ca75ba --- /dev/null +++ b/ext/libpng16/pngread.c @@ -0,0 +1,4000 @@ + +/* pngread.c - read a PNG file + * + * Last changed in libpng 1.6.1 [March 28, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#include "pngpriv.h" +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) +# include +#endif + +#ifdef PNG_READ_SUPPORTED + +/* Create a PNG structure for reading, and allocate any memory needed. */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) +{ +#ifndef PNG_USER_MEM_SUPPORTED + png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + error_fn, warn_fn, NULL, NULL, NULL); +#else + return png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL); +} + +/* Alternate create PNG structure for reading, and allocate any memory + * needed. + */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +{ + png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr != NULL) + { + png_ptr->mode = PNG_IS_READ_STRUCT; + + /* Added in libpng-1.6.0; this can be used to detect a read structure if + * required (it will be zero in a write structure.) + */ +# ifdef PNG_SEQUENTIAL_READ_SUPPORTED + png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE; +# endif + +# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + + /* In stable builds only warn if an application error can be completely + * handled. + */ +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC + png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; +# endif +# endif + + /* TODO: delay this, it can be done in png_init_io (if the app doesn't + * do it itself) avoiding setting the default function if it is not + * required. + */ + png_set_read_fn(png_ptr, NULL, NULL); + } + + return png_ptr; +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structrp png_ptr, png_inforp info_ptr) +{ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int keep; +#endif + + png_debug(1, "in png_read_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Read and check the PNG file signature. */ + png_read_sig(png_ptr, info_ptr); + + for (;;) + { + png_uint_32 length = png_read_chunk_header(png_ptr); + png_uint_32 chunk_name = png_ptr->chunk_name; + + /* IDAT logic needs to happen here to simplify getting the two flags + * right. + */ + if (chunk_name == png_IDAT) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_chunk_error(png_ptr, "Missing PLTE before IDAT"); + + else if (png_ptr->mode & PNG_AFTER_IDAT) + png_chunk_benign_error(png_ptr, "Too many IDATs found"); + + png_ptr->mode |= PNG_HAVE_IDAT; + } + + else if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (chunk_name == png_IHDR) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (chunk_name == png_IEND) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) + { + png_handle_unknown(png_ptr, info_ptr, length, keep); + + if (chunk_name == png_PLTE) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (chunk_name == png_IDAT) + { + png_ptr->idat_size = 0; /* It has been consumed */ + break; + } + } +#endif + else if (chunk_name == png_PLTE) + png_handle_PLTE(png_ptr, info_ptr, length); + + else if (chunk_name == png_IDAT) + { + png_ptr->idat_size = length; + break; + } + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (chunk_name == png_bKGD) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (chunk_name == png_cHRM) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (chunk_name == png_gAMA) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (chunk_name == png_hIST) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (chunk_name == png_oFFs) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (chunk_name == png_pCAL) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (chunk_name == png_sCAL) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (chunk_name == png_pHYs) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (chunk_name == png_sBIT) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (chunk_name == png_sRGB) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (chunk_name == png_iCCP) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (chunk_name == png_sPLT) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (chunk_name == png_tEXt) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (chunk_name == png_tIME) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (chunk_name == png_tRNS) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (chunk_name == png_zTXt) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (chunk_name == png_iTXt) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + + else + png_handle_unknown(png_ptr, info_ptr, length, + PNG_HANDLE_CHUNK_AS_DEFAULT); + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) +{ + png_debug(1, "in png_read_update_info"); + + if (png_ptr != NULL) + { + if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) + { + png_read_start_row(png_ptr); + +# ifdef PNG_READ_TRANSFORMS_SUPPORTED + png_read_transform_info(png_ptr, info_ptr); +# else + PNG_UNUSED(info_ptr) +# endif + } + + /* New in 1.6.0 this avoids the bug of doing the initializations twice */ + else + png_app_error(png_ptr, + "png_read_update_info/png_start_read_image: duplicate call"); + } +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structrp png_ptr) +{ + png_debug(1, "in png_start_read_image"); + + if (png_ptr != NULL) + { + if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) + png_read_start_row(png_ptr); + + /* New in 1.6.0 this avoids the bug of doing the initializations twice */ + else + png_app_error(png_ptr, + "png_start_read_image/png_read_update_info: duplicate call"); + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void PNGAPI +png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) +{ + png_row_info row_info; + + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_read_row (row %lu, pass %d)", + (unsigned long)png_ptr->row_number, png_ptr->pass); + + /* png_read_start_row sets the information (in particular iwidth) for this + * interlace pass. + */ + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + + /* 1.5.6: row_info moved out of png_struct to a local here. */ + row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ + row_info.color_type = png_ptr->color_type; + row_info.bit_depth = png_ptr->bit_depth; + row_info.channels = png_ptr->channels; + row_info.pixel_depth = png_ptr->pixel_depth; + row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); + + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); +#endif + } + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* If interlaced and we do not need a new row, combine row and return. + * Notice that the pixels we have from previous rows have been transformed + * already; we can only combine like with like (transformed or + * untransformed) and, because of the libpng API for interlaced images, this + * means we must transform before de-interlacing. + */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + png_read_finish_row(png_ptr); + return; + } + break; + + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + default: + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + /* Fill the row with IDAT data: */ + png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1); + + if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) + { + if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) + png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, + png_ptr->prev_row + 1, png_ptr->row_buf[0]); + else + png_error(png_ptr, "bad adaptive filter value"); + } + + /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before + * 1.5.6, while the buffer really is this big in current versions of libpng + * it may not be in the future, so this was changed just to copy the + * interlaced count: + */ + memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1); + } +#endif + + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + if (png_ptr->transformations) + png_do_read_transformations(png_ptr, &row_info); +#endif + + /* The transformed pixel depth should match the depth now in row_info. */ + if (png_ptr->transformed_pixel_depth == 0) + { + png_ptr->transformed_pixel_depth = row_info.pixel_depth; + if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) + png_error(png_ptr, "sequential row overflow"); + } + + else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) + png_error(png_ptr, "internal sequential row size calculation error"); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) + png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, + png_ptr->transformations); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + if (row != NULL) + png_combine_row(png_ptr, row, 0/*row*/); + } + + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, -1/*ignored*/); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, -1/*ignored*/); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); + +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ + +void PNGAPI +png_read_rows(png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows"); + + if (png_ptr == NULL) + return; + + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + + else if (rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, NULL); + rp++; + } + + else if (dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, NULL, dptr); + dp++; + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ +void PNGAPI +png_read_image(png_structrp png_ptr, png_bytepp image) +{ + png_uint_32 i, image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + pass = png_set_interlace_handling(png_ptr); + /* And make sure transforms are initialized. */ + png_start_read_image(png_ptr); + } + else + { + if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) + { + /* Caller called png_start_read_image or png_read_update_info without + * first turning on the PNG_INTERLACE transform. We can fix this here, + * but the caller should do it! + */ + png_warning(png_ptr, "Interlace handling should be turned on when " + "using png_read_image"); + /* Make sure this is set correctly */ + png_ptr->num_rows = png_ptr->height; + } + + /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in + * the above error case. + */ + pass = png_set_interlace_handling(png_ptr); + } +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled"); + + pass = 1; +#endif + + image_height=png_ptr->height; + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, NULL); + rp++; + } + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structrp png_ptr, png_inforp info_ptr) +{ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int keep; +#endif + + png_debug(1, "in png_read_end"); + + if (png_ptr == NULL) + return; + + /* If png_read_end is called in the middle of reading the rows there may + * still be pending IDAT data and an owned zstream. Deal with this here. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (!png_chunk_unknown_handling(png_ptr, png_IDAT)) +#endif + png_read_finish_IDAT(png_ptr); + +#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED + /* Report invalid palette index; added at libng-1.5.10 */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + png_ptr->num_palette_max > png_ptr->num_palette) + png_benign_error(png_ptr, "Read palette index exceeding num_palette"); +#endif + + do + { + png_uint_32 length = png_read_chunk_header(png_ptr); + png_uint_32 chunk_name = png_ptr->chunk_name; + + if (chunk_name == png_IHDR) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (chunk_name == png_IEND) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) + { + if (chunk_name == png_IDAT) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + } + png_handle_unknown(png_ptr, info_ptr, length, keep); + if (chunk_name == png_PLTE) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + + else if (chunk_name == png_IDAT) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + + png_crc_finish(png_ptr, length); + } + else if (chunk_name == png_PLTE) + png_handle_PLTE(png_ptr, info_ptr, length); + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (chunk_name == png_bKGD) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (chunk_name == png_cHRM) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (chunk_name == png_gAMA) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (chunk_name == png_hIST) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (chunk_name == png_oFFs) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (chunk_name == png_pCAL) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (chunk_name == png_sCAL) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (chunk_name == png_pHYs) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (chunk_name == png_sBIT) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (chunk_name == png_sRGB) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (chunk_name == png_iCCP) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (chunk_name == png_sPLT) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (chunk_name == png_tEXt) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (chunk_name == png_tIME) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (chunk_name == png_tRNS) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (chunk_name == png_zTXt) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (chunk_name == png_iTXt) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + + else + png_handle_unknown(png_ptr, info_ptr, length, + PNG_HANDLE_CHUNK_AS_DEFAULT); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Free all memory used in the read struct */ +static void +png_read_destroy(png_structrp png_ptr) +{ + png_debug(1, "in png_read_destroy"); + +#ifdef PNG_READ_GAMMA_SUPPORTED + png_destroy_gamma_table(png_ptr); +#endif + + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->big_prev_row); + png_free(png_ptr, png_ptr->read_buffer); + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->quantize_index); +#endif + + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; + +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#endif + + inflateEnd(&png_ptr->zstream); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) &&\ + defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + png_free(png_ptr, png_ptr->unknown_chunk.data); +#endif + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + png_free(png_ptr, png_ptr->chunk_list); +#endif + + /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error + * callbacks are still set at this point. They are required to complete the + * destruction of the png_struct itself. + */ +} + +/* Free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structrp png_ptr = NULL; + + png_debug(1, "in png_destroy_read_struct"); + + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + + if (png_ptr == NULL) + return; + + /* libpng 1.6.0: use the API to destroy info structs to ensure consistent + * behavior. Prior to 1.6.0 libpng did extra 'info' destruction in this API. + * The extra was, apparently, unnecessary yet this hides memory leak bugs. + */ + png_destroy_info_struct(png_ptr, end_info_ptr_ptr); + png_destroy_info_struct(png_ptr, info_ptr_ptr); + + *png_ptr_ptr = NULL; + png_read_destroy(png_ptr); + png_destroy_png_struct(png_ptr); +} + +void PNGAPI +png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->read_row_fn = read_row_fn; +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_read_png(png_structrp png_ptr, png_inforp info_ptr, + int transforms, + voidp params) +{ + int row; + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep))) + png_error(png_ptr, "Image is too high to process with png_read_png()"); + + /* -------------- image transformations start here ------------------- */ + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + /* Tell libpng to strip 16-bit/color files down to 8 bits per color. + */ + if (transforms & PNG_TRANSFORM_SCALE_16) + { + /* Added at libpng-1.5.4. "strip_16" produces the same result that it + * did in earlier versions, while "scale_16" is now more accurate. + */ + png_set_scale_16(png_ptr); + } +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* If both SCALE and STRIP are required pngrtran will effectively cancel the + * latter by doing SCALE first. This is ok and allows apps not to check for + * which is supported to get the right answer. + */ + if (transforms & PNG_TRANSFORM_STRIP_16) + png_set_strip_16(png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + /* Strip alpha bytes from the input data without combining with + * the background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) + png_set_strip_alpha(png_ptr); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) + /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); +#endif + + /* We don't handle background color or gamma transformation or quantizing. + */ + +#ifdef PNG_READ_INVERT_SUPPORTED + /* Invert monochrome files to have 0 as white and 1 as black + */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); + } +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_SUPPORTED + /* Swap bytes of 16-bit files to least significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* Expand grayscale image to RGB */ + if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) + png_set_gray_to_rgb(png_ptr); +#endif + +/* Added at libpng-1.5.4 */ +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (transforms & PNG_TRANSFORM_EXPAND_16) + png_set_expand_16(png_ptr); +#endif + + /* We don't handle adding filler bytes */ + + /* We use png_read_image and rely on that for interlace handling, but we also + * call png_read_update_info therefore must turn on interlace handling now: + */ + (void)png_set_interlace_handling(png_ptr); + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + if (info_ptr->row_pointers == NULL) + { + png_uint_32 iptr; + + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * (sizeof (png_bytep))); + for (iptr=0; iptrheight; iptr++) + info_ptr->row_pointers[iptr] = NULL; + + info_ptr->free_me |= PNG_FREE_ROWS; + + for (row = 0; row < (int)info_ptr->height; row++) + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + PNG_UNUSED(transforms) /* Quiet compiler warnings */ + PNG_UNUSED(params) + +} +#endif /* PNG_INFO_IMAGE_SUPPORTED */ +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* SIMPLIFIED READ + * + * This code currently relies on the sequential reader, though it could easily + * be made to work with the progressive one. + */ +/* Arguments to png_image_finish_read: */ + +/* Encoding of PNG data (used by the color-map code) */ +/* TODO: change these, dang, ANSI-C reserves the 'E' namespace. */ +# define E_NOTSET 0 /* File encoding not yet known */ +# define E_sRGB 1 /* 8-bit encoded to sRGB gamma */ +# define E_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */ +# define E_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */ +# define E_LINEAR8 4 /* 8-bit linear: only from a file value */ + +/* Color-map processing: after libpng has run on the PNG image further + * processing may be needed to conver the data to color-map indicies. + */ +#define PNG_CMAP_NONE 0 +#define PNG_CMAP_GA 1 /* Process GA data to a color-map with alpha */ +#define PNG_CMAP_TRANS 2 /* Process GA data to a background index */ +#define PNG_CMAP_RGB 3 /* Process RGB data */ +#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */ + +/* The following document where the background is for each processing case. */ +#define PNG_CMAP_NONE_BACKGROUND 256 +#define PNG_CMAP_GA_BACKGROUND 231 +#define PNG_CMAP_TRANS_BACKGROUND 254 +#define PNG_CMAP_RGB_BACKGROUND 256 +#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216 + +typedef struct +{ + /* Arguments: */ + png_imagep image; + png_voidp buffer; + png_int_32 row_stride; + png_voidp colormap; + png_const_colorp background; + /* Local variables: */ + png_voidp local_row; + png_voidp first_row; + ptrdiff_t row_bytes; /* step between rows */ + int file_encoding; /* E_ values above */ + png_fixed_point gamma_to_linear; /* For E_FILE, reciprocal of gamma */ + int colormap_processing; /* PNG_CMAP_ values above */ +} png_image_read_control; + +/* Do all the *safe* initialization - 'safe' means that png_error won't be + * called, so setting up the jmp_buf is not required. This means that anything + * called from here must *not* call png_malloc - it has to call png_malloc_warn + * instead so that control is returned safely back to this routine. + */ +static int +png_image_read_init(png_imagep image) +{ + if (image->opaque == NULL) + { + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image, + png_safe_error, png_safe_warning); + + /* And set the rest of the structure to NULL to ensure that the various + * fields are consistent. + */ + memset(image, 0, (sizeof *image)); + image->version = PNG_IMAGE_VERSION; + + if (png_ptr != NULL) + { + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (info_ptr != NULL) + { + png_controlp control = png_voidcast(png_controlp, + png_malloc_warn(png_ptr, (sizeof *control))); + + if (control != NULL) + { + memset(control, 0, (sizeof *control)); + + control->png_ptr = png_ptr; + control->info_ptr = info_ptr; + control->for_write = 0; + + image->opaque = control; + return 1; + } + + /* Error clean up */ + png_destroy_info_struct(png_ptr, &info_ptr); + } + + png_destroy_read_struct(&png_ptr, NULL, NULL); + } + + return png_image_error(image, "png_image_read: out of memory"); + } + + return png_image_error(image, "png_image_read: opaque pointer not NULL"); +} + +/* Utility to find the base format of a PNG file from a png_struct. */ +static png_uint_32 +png_image_format(png_structrp png_ptr) +{ + png_uint_32 format = 0; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + format |= PNG_FORMAT_FLAG_COLOR; + + if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) + format |= PNG_FORMAT_FLAG_ALPHA; + + /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS + * sets the png_struct fields; that's all we are interested in here. The + * precise interaction with an app call to png_set_tRNS and PNG file reading + * is unclear. + */ + else if (png_ptr->num_trans > 0) + format |= PNG_FORMAT_FLAG_ALPHA; + + if (png_ptr->bit_depth == 16) + format |= PNG_FORMAT_FLAG_LINEAR; + + if (png_ptr->color_type & PNG_COLOR_MASK_PALETTE) + format |= PNG_FORMAT_FLAG_COLORMAP; + + return format; +} + +/* Is the given gamma significantly different from sRGB? The test is the same + * one used in pngrtran.c when deciding whether to do gamma correction. The + * arithmetic optimizes the division by using the fact that the inverse of the + * file sRGB gamma is 2.2 + */ +static int +png_gamma_not_sRGB(png_fixed_point g) +{ + if (g < PNG_FP_1) + { + /* An uninitialized gamma is assumed to be sRGB for the simplified API. */ + if (g == 0) + return 0; + + return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */); + } + + return 1; +} + +/* Do the main body of a 'png_image_begin_read' function; read the PNG file + * header and fill in all the information. This is executed in a safe context, + * unlike the init routine above. + */ +static int +png_image_read_header(png_voidp argument) +{ + png_imagep image = png_voidcast(png_imagep, argument); + png_structrp png_ptr = image->opaque->png_ptr; + png_inforp info_ptr = image->opaque->info_ptr; + + png_set_benign_errors(png_ptr, 1/*warn*/); + png_read_info(png_ptr, info_ptr); + + /* Do this the fast way; just read directly out of png_struct. */ + image->width = png_ptr->width; + image->height = png_ptr->height; + + { + png_uint_32 format = png_image_format(png_ptr); + + image->format = format; + +#ifdef PNG_COLORSPACE_SUPPORTED + /* Does the colorspace match sRGB? If there is no color endpoint + * (colorant) information assume yes, otherwise require the + * 'ENDPOINTS_MATCHE_sRGB' colorspace flag to have been set. If the + * colorspace has been determined to be invalid ignore it. + */ + if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags + & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB| + PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS)) + image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB; +#endif + } + + /* We need the maximum number of entries regardless of the format the + * application sets here. + */ + { + png_uint_32 cmap_entries; + + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_GRAY: + cmap_entries = 1U << png_ptr->bit_depth; + break; + + case PNG_COLOR_TYPE_PALETTE: + cmap_entries = png_ptr->num_palette; + break; + + default: + cmap_entries = 256; + break; + } + + if (cmap_entries > 256) + cmap_entries = 256; + + image->colormap_entries = cmap_entries; + } + + return 1; +} + +#ifdef PNG_STDIO_SUPPORTED +int PNGAPI +png_image_begin_read_from_stdio(png_imagep image, FILE* file) +{ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (file != NULL) + { + if (png_image_read_init(image)) + { + /* This is slightly evil, but png_init_io doesn't do anything other + * than this and we haven't changed the standard IO functions so + * this saves a 'safe' function. + */ + image->opaque->png_ptr->io_ptr = file; + return png_safe_execute(image, png_image_read_header, image); + } + } + + else + return png_image_error(image, + "png_image_begin_read_from_stdio: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION"); + + return 0; +} + +int PNGAPI +png_image_begin_read_from_file(png_imagep image, const char *file_name) +{ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (file_name != NULL) + { + FILE *fp = fopen(file_name, "rb"); + + if (fp != NULL) + { + if (png_image_read_init(image)) + { + image->opaque->png_ptr->io_ptr = fp; + image->opaque->owned_file = 1; + return png_safe_execute(image, png_image_read_header, image); + } + + /* Clean up: just the opened file. */ + (void)fclose(fp); + } + + else + return png_image_error(image, strerror(errno)); + } + + else + return png_image_error(image, + "png_image_begin_read_from_file: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION"); + + return 0; +} +#endif /* PNG_STDIO_SUPPORTED */ + +static void PNGCBAPI +png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) +{ + if (png_ptr != NULL) + { + png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr); + if (image != NULL) + { + png_controlp cp = image->opaque; + if (cp != NULL) + { + png_const_bytep memory = cp->memory; + png_size_t size = cp->size; + + if (memory != NULL && size >= need) + { + memcpy(out, memory, need); + cp->memory = memory + need; + cp->size = size - need; + return; + } + + png_error(png_ptr, "read beyond end of data"); + } + } + + png_error(png_ptr, "invalid memory read"); + } +} + +int PNGAPI png_image_begin_read_from_memory(png_imagep image, + png_const_voidp memory, png_size_t size) +{ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (memory != NULL && size > 0) + { + if (png_image_read_init(image)) + { + /* Now set the IO functions to read from the memory buffer and + * store it into io_ptr. Again do this in-place to avoid calling a + * libpng function that requires error handling. + */ + image->opaque->memory = png_voidcast(png_const_bytep, memory); + image->opaque->size = size; + image->opaque->png_ptr->io_ptr = image; + image->opaque->png_ptr->read_data_fn = png_image_memory_read; + + return png_safe_execute(image, png_image_read_header, image); + } + } + + else + return png_image_error(image, + "png_image_begin_read_from_memory: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION"); + + return 0; +} + +/* Utility function to skip chunks that are not used by the simplified image + * read functions and an appropriate macro to call it. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +static void +png_image_skip_unused_chunks(png_structrp png_ptr) +{ + /* Prepare the reader to ignore all recognized chunks whose data will not + * be used, i.e., all chunks recognized by libpng except for those + * involved in basic image reading: + * + * IHDR, PLTE, IDAT, IEND + * + * Or image data handling: + * + * tRNS, bKGD, gAMA, cHRM, sRGB, iCCP and sBIT. + * + * This provides a small performance improvement and eliminates any + * potential vulnerability to security problems in the unused chunks. + */ + { + static PNG_CONST png_byte chunks_to_process[] = { + 98, 75, 71, 68, '\0', /* bKGD */ + 99, 72, 82, 77, '\0', /* cHRM */ + 103, 65, 77, 65, '\0', /* gAMA */ + 105, 67, 67, 80, '\0', /* iCCP */ + 115, 66, 73, 84, '\0', /* sBIT */ + 115, 82, 71, 66, '\0', /* sRGB */ + }; + + /* Ignore unknown chunks and all other chunks except for the + * IHDR, PLTE, tRNS, IDAT, and IEND chunks. + */ + png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER, + NULL, -1); + + /* But do not ignore image data handling chunks */ + png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT, + chunks_to_process, (sizeof chunks_to_process)/5); + } +} + +# define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p) +#else +# define PNG_SKIP_CHUNKS(p) ((void)0) +#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ + +/* The following macro gives the exact rounded answer for all values in the + * range 0..255 (it actually divides by 51.2, but the rounding still generates + * the correct numbers 0..5 + */ +#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8) + +/* Utility functions to make particular color-maps */ +static void +set_file_encoding(png_image_read_control *display) +{ + png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma; + if (png_gamma_significant(g)) + { + if (png_gamma_not_sRGB(g)) + { + display->file_encoding = E_FILE; + display->gamma_to_linear = png_reciprocal(g); + } + + else + display->file_encoding = E_sRGB; + } + + else + display->file_encoding = E_LINEAR8; +} + +static unsigned int +decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) +{ + if (encoding == E_FILE) /* double check */ + encoding = display->file_encoding; + + if (encoding == E_NOTSET) /* must be the file encoding */ + { + set_file_encoding(display); + encoding = display->file_encoding; + } + + switch (encoding) + { + case E_FILE: + value = png_gamma_16bit_correct(value*257, display->gamma_to_linear); + break; + + case E_sRGB: + value = png_sRGB_table[value]; + break; + + case E_LINEAR: + break; + + case E_LINEAR8: + value *= 257; + break; + + default: + png_error(display->image->opaque->png_ptr, + "unexpected encoding (internal error)"); + break; + } + + return value; +} + +static png_uint_32 +png_colormap_compose(png_image_read_control *display, + png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, + png_uint_32 background, int encoding) +{ + /* The file value is composed on the background, the background has the given + * encoding and so does the result, the file is encoded with E_FILE and the + * file and alpha are 8-bit values. The (output) encoding will always be + * E_LINEAR or E_sRGB. + */ + png_uint_32 f = decode_gamma(display, foreground, foreground_encoding); + png_uint_32 b = decode_gamma(display, background, encoding); + + /* The alpha is always an 8-bit value (it comes from the palette), the value + * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires. + */ + f = f * alpha + b * (255-alpha); + + if (encoding == E_LINEAR) + { + /* Scale to 65535; divide by 255, approximately (in fact this is extremely + * accurate, it divides by 255.00000005937181414556, with no overflow.) + */ + f *= 257; /* Now scaled by 65535 */ + f += f >> 16; + f = (f+32768) >> 16; + } + + else /* E_sRGB */ + f = PNG_sRGB_FROM_LINEAR(f); + + return f; +} + +/* NOTE: E_LINEAR values to this routine must be 16-bit, but E_FILE values must + * be 8-bit. + */ +static void +png_create_colormap_entry(png_image_read_control *display, + png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, + png_uint_32 alpha, int encoding) +{ + png_imagep image = display->image; + const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) ? + E_LINEAR : E_sRGB; + const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && + (red != green || green != blue); + + if (ip > 255) + png_error(image->opaque->png_ptr, "color-map index out of range"); + + /* Update the cache with whether the file gamma is significantly different + * from sRGB. + */ + if (encoding == E_FILE) + { + if (display->file_encoding == E_NOTSET) + set_file_encoding(display); + + /* Note that the cached value may be E_FILE too, but if it is then the + * gamma_to_linear member has been set. + */ + encoding = display->file_encoding; + } + + if (encoding == E_FILE) + { + png_fixed_point g = display->gamma_to_linear; + + red = png_gamma_16bit_correct(red*257, g); + green = png_gamma_16bit_correct(green*257, g); + blue = png_gamma_16bit_correct(blue*257, g); + + if (convert_to_Y || output_encoding == E_LINEAR) + { + alpha *= 257; + encoding = E_LINEAR; + } + + else + { + red = PNG_sRGB_FROM_LINEAR(red * 255); + green = PNG_sRGB_FROM_LINEAR(green * 255); + blue = PNG_sRGB_FROM_LINEAR(blue * 255); + encoding = E_sRGB; + } + } + + else if (encoding == E_LINEAR8) + { + /* This encoding occurs quite frequently in test cases because PngSuite + * includes a gAMA 1.0 chunk with most images. + */ + red *= 257; + green *= 257; + blue *= 257; + alpha *= 257; + encoding = E_LINEAR; + } + + else if (encoding == E_sRGB && (convert_to_Y || output_encoding == E_LINEAR)) + { + /* The values are 8-bit sRGB values, but must be converted to 16-bit + * linear. + */ + red = png_sRGB_table[red]; + green = png_sRGB_table[green]; + blue = png_sRGB_table[blue]; + alpha *= 257; + encoding = E_LINEAR; + } + + /* This is set if the color isn't gray but the output is. */ + if (encoding == E_LINEAR) + { + if (convert_to_Y) + { + /* NOTE: these values are copied from png_do_rgb_to_gray */ + png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green + + (png_uint_32)2366 * blue; + + if (output_encoding == E_LINEAR) + y = (y + 16384) >> 15; + + else + { + /* y is scaled by 32768, we need it scaled by 255: */ + y = (y + 128) >> 8; + y *= 255; + y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7); + encoding = E_sRGB; + } + + blue = red = green = y; + } + + else if (output_encoding == E_sRGB) + { + red = PNG_sRGB_FROM_LINEAR(red * 255); + green = PNG_sRGB_FROM_LINEAR(green * 255); + blue = PNG_sRGB_FROM_LINEAR(blue * 255); + alpha = PNG_DIV257(alpha); + encoding = E_sRGB; + } + } + + if (encoding != output_encoding) + png_error(image->opaque->png_ptr, "bad encoding (internal error)"); + + /* Store the value. */ + { +# ifdef PNG_FORMAT_BGR_SUPPORTED + const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && + (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; +# else +# define afirst 0 +# endif +# ifdef PNG_FORMAT_BGR_SUPPORTED + const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) ? 2 : 0; +# else +# define bgr 0 +# endif + + if (output_encoding == E_LINEAR) + { + png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap); + + entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); + + /* The linear 16-bit values must be pre-multiplied by the alpha channel + * value, if less than 65535 (this is, effectively, composite on black + * if the alpha channel is removed.) + */ + switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) + { + case 4: + entry[afirst ? 0 : 3] = (png_uint_16)alpha; + /* FALL THROUGH */ + + case 3: + if (alpha < 65535) + { + if (alpha > 0) + { + blue = (blue * alpha + 32767U)/65535U; + green = (green * alpha + 32767U)/65535U; + red = (red * alpha + 32767U)/65535U; + } + + else + red = green = blue = 0; + } + entry[afirst + (2 ^ bgr)] = (png_uint_16)blue; + entry[afirst + 1] = (png_uint_16)green; + entry[afirst + bgr] = (png_uint_16)red; + break; + + case 2: + entry[1 ^ afirst] = (png_uint_16)alpha; + /* FALL THROUGH */ + + case 1: + if (alpha < 65535) + { + if (alpha > 0) + green = (green * alpha + 32767U)/65535U; + + else + green = 0; + } + entry[afirst] = (png_uint_16)green; + break; + + default: + break; + } + } + + else /* output encoding is E_sRGB */ + { + png_bytep entry = png_voidcast(png_bytep, display->colormap); + + entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); + + switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) + { + case 4: + entry[afirst ? 0 : 3] = (png_byte)alpha; + case 3: + entry[afirst + (2 ^ bgr)] = (png_byte)blue; + entry[afirst + 1] = (png_byte)green; + entry[afirst + bgr] = (png_byte)red; + break; + + case 2: + entry[1 ^ afirst] = (png_byte)alpha; + case 1: + entry[afirst] = (png_byte)green; + break; + + default: + break; + } + } + +# ifdef afirst +# undef afirst +# endif +# ifdef bgr +# undef bgr +# endif + } +} + +static int +make_gray_file_colormap(png_image_read_control *display) +{ + unsigned int i; + + for (i=0; i<256; ++i) + png_create_colormap_entry(display, i, i, i, i, 255, E_FILE); + + return i; +} + +static int +make_gray_colormap(png_image_read_control *display) +{ + unsigned int i; + + for (i=0; i<256; ++i) + png_create_colormap_entry(display, i, i, i, i, 255, E_sRGB); + + return i; +} +#define PNG_GRAY_COLORMAP_ENTRIES 256 + +static int +make_ga_colormap(png_image_read_control *display) +{ + unsigned int i, a; + + /* Alpha is retained, the output will be a color-map with entries + * selected by six levels of alpha. One transparent entry, 6 gray + * levels for all the intermediate alpha values, leaving 230 entries + * for the opaque grays. The color-map entries are the six values + * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the + * relevant entry. + * + * if (alpha > 229) // opaque + * { + * // The 231 entries are selected to make the math below work: + * base = 0; + * entry = (231 * gray + 128) >> 8; + * } + * else if (alpha < 26) // transparent + * { + * base = 231; + * entry = 0; + * } + * else // partially opaque + * { + * base = 226 + 6 * PNG_DIV51(alpha); + * entry = PNG_DIV51(gray); + * } + */ + i = 0; + while (i < 231) + { + unsigned int gray = (i * 256 + 115) / 231; + png_create_colormap_entry(display, i++, gray, gray, gray, 255, E_sRGB); + } + + /* 255 is used here for the component values for consistency with the code + * that undoes premultiplication in pngwrite.c. + */ + png_create_colormap_entry(display, i++, 255, 255, 255, 0, E_sRGB); + + for (a=1; a<5; ++a) + { + unsigned int g; + + for (g=0; g<6; ++g) + png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51, + E_sRGB); + } + + return i; +} + +#define PNG_GA_COLORMAP_ENTRIES 256 + +static int +make_rgb_colormap(png_image_read_control *display) +{ + unsigned int i, r; + + /* Build a 6x6x6 opaque RGB cube */ + for (i=r=0; r<6; ++r) + { + unsigned int g; + + for (g=0; g<6; ++g) + { + unsigned int b; + + for (b=0; b<6; ++b) + png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255, + E_sRGB); + } + } + + return i; +} + +#define PNG_RGB_COLORMAP_ENTRIES 216 + +/* Return a palette index to the above palette given three 8-bit sRGB values. */ +#define PNG_RGB_INDEX(r,g,b) \ + ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b))) + +static int +png_image_read_colormap(png_voidp argument) +{ + png_image_read_control *display = + png_voidcast(png_image_read_control*, argument); + const png_imagep image = display->image; + + const png_structrp png_ptr = image->opaque->png_ptr; + const png_uint_32 output_format = image->format; + const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) ? + E_LINEAR : E_sRGB; + + unsigned int cmap_entries; + unsigned int output_processing; /* Output processing option */ + unsigned int data_encoding = E_NOTSET; /* Encoding libpng must produce */ + + /* Background information; the background color and the index of this color + * in the color-map if it exists (else 256). + */ + unsigned int background_index = 256; + png_uint_32 back_r, back_g, back_b; + + /* Flags to accumulate things that need to be done to the input. */ + int expand_tRNS = 0; + + /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is + * very difficult to do, the results look awful, and it is difficult to see + * what possible use it is because the application can't control the + * color-map. + */ + if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 || + png_ptr->num_trans > 0) /* alpha in input */ && + ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */) + { + if (output_encoding == E_LINEAR) /* compose on black */ + back_b = back_g = back_r = 0; + + else if (display->background == NULL /* no way to remove it */) + png_error(png_ptr, + "a background color must be supplied to remove alpha/transparency"); + + /* Get a copy of the background color (this avoids repeating the checks + * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the + * output format. + */ + else + { + back_g = display->background->green; + if (output_format & PNG_FORMAT_FLAG_COLOR) + { + back_r = display->background->red; + back_b = display->background->blue; + } + else + back_b = back_r = back_g; + } + } + + else if (output_encoding == E_LINEAR) + back_b = back_r = back_g = 65535; + + else + back_b = back_r = back_g = 255; + + /* Default the input file gamma if required - this is necessary because + * libpng assumes that if no gamma information is present the data is in the + * output format, but the simplified API deduces the gamma from the input + * format. + */ + if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0) + { + /* Do this directly, not using the png_colorspace functions, to ensure + * that it happens even if the colorspace is invalid (though probably if + * it is the setting will be ignored) Note that the same thing can be + * achieved at the application interface with png_set_gAMA. + */ + if (png_ptr->bit_depth == 16 && + (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) + png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR; + + else + png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE; + + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; + } + + /* Decide what to do based on the PNG color type of the input data. The + * utility function png_create_colormap_entry deals with most aspects of the + * output transformations; this code works out how to produce bytes of + * color-map entries from the original format. + */ + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_GRAY: + if (png_ptr->bit_depth <= 8) + { + /* There at most 256 colors in the output, regardless of + * transparency. + */ + unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0; + + cmap_entries = 1U << png_ptr->bit_depth; + if (cmap_entries > image->colormap_entries) + png_error(png_ptr, "gray[8] color-map: too few entries"); + + step = 255 / (cmap_entries - 1); + output_processing = PNG_CMAP_NONE; + + /* If there is a tRNS chunk then this either selects a transparent + * value or, if the output has no alpha, the background color. + */ + if (png_ptr->num_trans > 0) + { + trans = png_ptr->trans_color.gray; + + if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) + back_alpha = output_encoding == E_LINEAR ? 65535 : 255; + } + + /* png_create_colormap_entry just takes an RGBA and writes the + * corresponding color-map entry using the format from 'image', + * including the required conversion to sRGB or linear as + * appropriate. The input values are always either sRGB (if the + * gamma correction flag is 0) or 0..255 scaled file encoded values + * (if the function must gamma correct them). + */ + for (i=val=0; ibit_depth < 8) + png_set_packing(png_ptr); + } + + else /* bit depth is 16 */ + { + /* The 16-bit input values can be converted directly to 8-bit gamma + * encoded values; however, if a tRNS chunk is present 257 color-map + * entries are required. This means that the extra entry requires + * special processing; add an alpha channel, sacrifice gray level + * 254 and convert transparent (alpha==0) entries to that. + * + * Use libpng to chop the data to 8 bits. Convert it to sRGB at the + * same time to minimize quality loss. If a tRNS chunk is present + * this means libpng must handle it too; otherwise it is impossible + * to do the exact match on the 16-bit value. + * + * If the output has no alpha channel *and* the background color is + * gray then it is possible to let libpng handle the substitution by + * ensuring that the corresponding gray level matches the background + * color exactly. + */ + data_encoding = E_sRGB; + + if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "gray[16] color-map: too few entries"); + + cmap_entries = make_gray_colormap(display); + + if (png_ptr->num_trans > 0) + { + unsigned int back_alpha; + + if (output_format & PNG_FORMAT_FLAG_ALPHA) + back_alpha = 0; + + else + { + if (back_r == back_g && back_g == back_b) + { + /* Background is gray; no special processing will be + * required. + */ + png_color_16 c; + png_uint_32 gray = back_g; + + if (output_encoding == E_LINEAR) + { + gray = PNG_sRGB_FROM_LINEAR(gray * 255); + + /* And make sure the corresponding palette entry + * matches. + */ + png_create_colormap_entry(display, gray, back_g, back_g, + back_g, 65535, E_LINEAR); + } + + /* The background passed to libpng, however, must be the + * sRGB value. + */ + c.index = 0; /*unused*/ + c.gray = c.red = c.green = c.blue = (png_uint_16)gray; + + /* NOTE: does this work without expanding tRNS to alpha? + * It should be the color->gray case below apparently + * doesn't. + */ + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + + output_processing = PNG_CMAP_NONE; + break; + } + + back_alpha = output_encoding == E_LINEAR ? 65535 : 255; + } + + /* output_processing means that the libpng-processed row will be + * 8-bit GA and it has to be processing to single byte color-map + * values. Entry 254 is replaced by either a completely + * transparent entry or by the background color at full + * precision (and the background color is not a simple gray leve + * in this case.) + */ + expand_tRNS = 1; + output_processing = PNG_CMAP_TRANS; + background_index = 254; + + /* And set (overwrite) color-map entry 254 to the actual + * background color at full precision. + */ + png_create_colormap_entry(display, 254, back_r, back_g, back_b, + back_alpha, output_encoding); + } + + else + output_processing = PNG_CMAP_NONE; + } + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + /* 8-bit or 16-bit PNG with two channels - gray and alpha. A minimum + * of 65536 combinations. If, however, the alpha channel is to be + * removed there are only 256 possibilities if the background is gray. + * (Otherwise there is a subset of the 65536 possibilities defined by + * the triangle between black, white and the background color.) + * + * Reduce 16-bit files to 8-bit and sRGB encode the result. No need to + * worry about tRNS matching - tRNS is ignored if there is an alpha + * channel. + */ + data_encoding = E_sRGB; + + if (output_format & PNG_FORMAT_FLAG_ALPHA) + { + if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "gray+alpha color-map: too few entries"); + + cmap_entries = make_ga_colormap(display); + + background_index = PNG_CMAP_GA_BACKGROUND; + output_processing = PNG_CMAP_GA; + } + + else /* alpha is removed */ + { + /* Alpha must be removed as the PNG data is processed when the + * background is a color because the G and A channels are + * independent and the vector addition (non-parallel vectors) is a + * 2-D problem. + * + * This can be reduced to the same algorithm as above by making a + * colormap containing gray levels (for the opaque grays), a + * background entry (for a transparent pixel) and a set of four six + * level color values, one set for each intermediate alpha value. + * See the comments in make_ga_colormap for how this works in the + * per-pixel processing. + * + * If the background is gray, however, we only need a 256 entry gray + * level color map. It is sufficient to make the entry generated + * for the background color be exactly the color specified. + */ + if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 || + (back_r == back_g && back_g == back_b)) + { + /* Background is gray; no special processing will be required. */ + png_color_16 c; + png_uint_32 gray = back_g; + + if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "gray-alpha color-map: too few entries"); + + cmap_entries = make_gray_colormap(display); + + if (output_encoding == E_LINEAR) + { + gray = PNG_sRGB_FROM_LINEAR(gray * 255); + + /* And make sure the corresponding palette entry matches. */ + png_create_colormap_entry(display, gray, back_g, back_g, + back_g, 65535, E_LINEAR); + } + + /* The background passed to libpng, however, must be the sRGB + * value. + */ + c.index = 0; /*unused*/ + c.gray = c.red = c.green = c.blue = (png_uint_16)gray; + + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + + output_processing = PNG_CMAP_NONE; + } + + else + { + png_uint_32 i, a; + + /* This is the same as png_make_ga_colormap, above, except that + * the entries are all opaque. + */ + if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "ga-alpha color-map: too few entries"); + + i = 0; + while (i < 231) + { + png_uint_32 gray = (i * 256 + 115) / 231; + png_create_colormap_entry(display, i++, gray, gray, gray, + 255, E_sRGB); + } + + /* NOTE: this preserves the full precision of the application + * background color. + */ + background_index = i; + png_create_colormap_entry(display, i++, back_r, back_g, back_b, + output_encoding == E_LINEAR ? 65535U : 255U, output_encoding); + + /* For non-opaque input composite on the sRGB background - this + * requires inverting the encoding for each component. The input + * is still converted to the sRGB encoding because this is a + * reasonable approximate to the logarithmic curve of human + * visual sensitivity, at least over the narrow range which PNG + * represents. Consequently 'G' is always sRGB encoded, while + * 'A' is linear. We need the linear background colors. + */ + if (output_encoding == E_sRGB) /* else already linear */ + { + /* This may produce a value not exactly matching the + * background, but that's ok because these numbers are only + * used when alpha != 0 + */ + back_r = png_sRGB_table[back_r]; + back_g = png_sRGB_table[back_g]; + back_b = png_sRGB_table[back_b]; + } + + for (a=1; a<5; ++a) + { + unsigned int g; + + /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled + * by an 8-bit alpha value (0..255). + */ + png_uint_32 alpha = 51 * a; + png_uint_32 back_rx = (255-alpha) * back_r; + png_uint_32 back_gx = (255-alpha) * back_g; + png_uint_32 back_bx = (255-alpha) * back_b; + + for (g=0; g<6; ++g) + { + png_uint_32 gray = png_sRGB_table[g*51] * alpha; + + png_create_colormap_entry(display, i++, + PNG_sRGB_FROM_LINEAR(gray + back_rx), + PNG_sRGB_FROM_LINEAR(gray + back_gx), + PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, E_sRGB); + } + } + + cmap_entries = i; + output_processing = PNG_CMAP_GA; + } + } + break; + + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + /* Exclude the case where the output is gray; we can always handle this + * with the cases above. + */ + if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0) + { + /* The color-map will be grayscale, so we may as well convert the + * input RGB values to a simple grayscale and use the grayscale + * code above. + * + * NOTE: calling this apparently damages the recognition of the + * transparent color in background color handling; call + * png_set_tRNS_to_alpha before png_set_background_fixed. + */ + png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1, + -1); + data_encoding = E_sRGB; + + /* The output will now be one or two 8-bit gray or gray+alpha + * channels. The more complex case arises when the input has alpha. + */ + if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->num_trans > 0) && + (output_format & PNG_FORMAT_FLAG_ALPHA) != 0) + { + /* Both input and output have an alpha channel, so no background + * processing is required; just map the GA bytes to the right + * color-map entry. + */ + expand_tRNS = 1; + + if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "rgb[ga] color-map: too few entries"); + + cmap_entries = make_ga_colormap(display); + background_index = PNG_CMAP_GA_BACKGROUND; + output_processing = PNG_CMAP_GA; + } + + else + { + /* Either the input or the output has no alpha channel, so there + * will be no non-opaque pixels in the color-map; it will just be + * grayscale. + */ + if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "rgb[gray] color-map: too few entries"); + + /* Ideally this code would use libpng to do the gamma correction, + * but if an input alpha channel is to be removed we will hit the + * libpng bug in gamma+compose+rgb-to-gray (the double gamma + * correction bug). Fix this by dropping the gamma correction in + * this case and doing it in the palette; this will result in + * duplicate palette entries, but that's better than the + * alternative of double gamma correction. + */ + if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->num_trans > 0) && + png_gamma_not_sRGB(png_ptr->colorspace.gamma)) + { + cmap_entries = make_gray_file_colormap(display); + data_encoding = E_FILE; + } + + else + cmap_entries = make_gray_colormap(display); + + /* But if the input has alpha or transparency it must be removed + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->num_trans > 0) + { + png_color_16 c; + png_uint_32 gray = back_g; + + /* We need to ensure that the application background exists in + * the colormap and that completely transparent pixels map to + * it. Achieve this simply by ensuring that the entry + * selected for the background really is the background color. + */ + if (data_encoding == E_FILE) /* from the fixup above */ + { + /* The app supplied a gray which is in output_encoding, we + * need to convert it to a value of the input (E_FILE) + * encoding then set this palette entry to the required + * output encoding. + */ + if (output_encoding == E_sRGB) + gray = png_sRGB_table[gray]; /* now E_LINEAR */ + + gray = PNG_DIV257(png_gamma_16bit_correct(gray, + png_ptr->colorspace.gamma)); /* now E_FILE */ + + /* And make sure the corresponding palette entry contains + * exactly the required sRGB value. + */ + png_create_colormap_entry(display, gray, back_g, back_g, + back_g, 0/*unused*/, output_encoding); + } + + else if (output_encoding == E_LINEAR) + { + gray = PNG_sRGB_FROM_LINEAR(gray * 255); + + /* And make sure the corresponding palette entry matches. + */ + png_create_colormap_entry(display, gray, back_g, back_g, + back_g, 0/*unused*/, E_LINEAR); + } + + /* The background passed to libpng, however, must be the + * output (normally sRGB) value. + */ + c.index = 0; /*unused*/ + c.gray = c.red = c.green = c.blue = (png_uint_16)gray; + + /* NOTE: the following is apparently a bug in libpng. Without + * it the transparent color recognition in + * png_set_background_fixed seems to go wrong. + */ + expand_tRNS = 1; + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + } + + output_processing = PNG_CMAP_NONE; + } + } + + else /* output is color */ + { + /* We could use png_quantize here so long as there is no transparent + * color or alpha; png_quantize ignores alpha. Easier overall just + * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube. + * Consequently we always want libpng to produce sRGB data. + */ + data_encoding = E_sRGB; + + /* Is there any transparency or alpha? */ + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->num_trans > 0) + { + /* Is there alpha in the output too? If so all four channels are + * processed into a special RGB cube with alpha support. + */ + if (output_format & PNG_FORMAT_FLAG_ALPHA) + { + png_uint_32 r; + + if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) + png_error(png_ptr, "rgb+alpha color-map: too few entries"); + + cmap_entries = make_rgb_colormap(display); + + /* Add a transparent entry. */ + png_create_colormap_entry(display, cmap_entries, 255, 255, + 255, 0, E_sRGB); + + /* This is stored as the background index for the processing + * algorithm. + */ + background_index = cmap_entries++; + + /* Add 27 r,g,b entries each with alpha 0.5. */ + for (r=0; r<256; r = (r << 1) | 0x7f) + { + png_uint_32 g; + + for (g=0; g<256; g = (g << 1) | 0x7f) + { + png_uint_32 b; + + /* This generates components with the values 0, 127 and + * 255 + */ + for (b=0; b<256; b = (b << 1) | 0x7f) + png_create_colormap_entry(display, cmap_entries++, + r, g, b, 128, E_sRGB); + } + } + + expand_tRNS = 1; + output_processing = PNG_CMAP_RGB_ALPHA; + } + + else + { + /* Alpha/transparency must be removed. The background must + * exist in the color map (achieved by setting adding it after + * the 666 color-map). If the standard processing code will + * pick up this entry automatically that's all that is + * required; libpng can be called to do the background + * processing. + */ + unsigned int sample_size = + PNG_IMAGE_SAMPLE_SIZE(output_format); + png_uint_32 r, g, b; /* sRGB background */ + + if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) + png_error(png_ptr, "rgb-alpha color-map: too few entries"); + + cmap_entries = make_rgb_colormap(display); + + png_create_colormap_entry(display, cmap_entries, back_r, + back_g, back_b, 0/*unused*/, output_encoding); + + if (output_encoding == E_LINEAR) + { + r = PNG_sRGB_FROM_LINEAR(back_r * 255); + g = PNG_sRGB_FROM_LINEAR(back_g * 255); + b = PNG_sRGB_FROM_LINEAR(back_b * 255); + } + + else + { + r = back_r; + g = back_g; + b = back_g; + } + + /* Compare the newly-created color-map entry with the one the + * PNG_CMAP_RGB algorithm will use. If the two entries don't + * match, add the new one and set this as the background + * index. + */ + if (memcmp((png_const_bytep)display->colormap + + sample_size * cmap_entries, + (png_const_bytep)display->colormap + + sample_size * PNG_RGB_INDEX(r,g,b), + sample_size) != 0) + { + /* The background color must be added. */ + background_index = cmap_entries++; + + /* Add 27 r,g,b entries each with created by composing with + * the background at alpha 0.5. + */ + for (r=0; r<256; r = (r << 1) | 0x7f) + { + for (g=0; g<256; g = (g << 1) | 0x7f) + { + /* This generates components with the values 0, 127 + * and 255 + */ + for (b=0; b<256; b = (b << 1) | 0x7f) + png_create_colormap_entry(display, cmap_entries++, + png_colormap_compose(display, r, E_sRGB, 128, + back_r, output_encoding), + png_colormap_compose(display, g, E_sRGB, 128, + back_g, output_encoding), + png_colormap_compose(display, b, E_sRGB, 128, + back_b, output_encoding), + 0/*unused*/, output_encoding); + } + } + + expand_tRNS = 1; + output_processing = PNG_CMAP_RGB_ALPHA; + } + + else /* background color is in the standard color-map */ + { + png_color_16 c; + + c.index = 0; /*unused*/ + c.red = (png_uint_16)back_r; + c.gray = c.green = (png_uint_16)back_g; + c.blue = (png_uint_16)back_b; + + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + + output_processing = PNG_CMAP_RGB; + } + } + } + + else /* no alpha or transparency in the input */ + { + /* Alpha in the output is irrelevant, simply map the opaque input + * pixels to the 6x6x6 color-map. + */ + if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "rgb color-map: too few entries"); + + cmap_entries = make_rgb_colormap(display); + output_processing = PNG_CMAP_RGB; + } + } + break; + + case PNG_COLOR_TYPE_PALETTE: + /* It's already got a color-map. It may be necessary to eliminate the + * tRNS entries though. + */ + { + unsigned int num_trans = png_ptr->num_trans; + png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; + png_const_colorp colormap = png_ptr->palette; + const int do_background = trans != NULL && + (output_format & PNG_FORMAT_FLAG_ALPHA) == 0; + unsigned int i; + + /* Just in case: */ + if (trans == NULL) + num_trans = 0; + + output_processing = PNG_CMAP_NONE; + data_encoding = E_FILE; /* Don't change from color-map indicies */ + cmap_entries = png_ptr->num_palette; + if (cmap_entries > 256) + cmap_entries = 256; + + if (cmap_entries > image->colormap_entries) + png_error(png_ptr, "palette color-map: too few entries"); + + for (i=0; i < cmap_entries; ++i) + { + if (do_background && i < num_trans && trans[i] < 255) + { + if (trans[i] == 0) + png_create_colormap_entry(display, i, back_r, back_g, + back_b, 0, output_encoding); + + else + { + /* Must compose the PNG file color in the color-map entry + * on the sRGB color in 'back'. + */ + png_create_colormap_entry(display, i, + png_colormap_compose(display, colormap[i].red, E_FILE, + trans[i], back_r, output_encoding), + png_colormap_compose(display, colormap[i].green, E_FILE, + trans[i], back_g, output_encoding), + png_colormap_compose(display, colormap[i].blue, E_FILE, + trans[i], back_b, output_encoding), + output_encoding == E_LINEAR ? trans[i] * 257U : + trans[i], + output_encoding); + } + } + + else + png_create_colormap_entry(display, i, colormap[i].red, + colormap[i].green, colormap[i].blue, + i < num_trans ? trans[i] : 255U, E_FILE/*8-bit*/); + } + + /* The PNG data may have indicies packed in fewer than 8 bits, it + * must be expanded if so. + */ + if (png_ptr->bit_depth < 8) + png_set_packing(png_ptr); + } + break; + + default: + png_error(png_ptr, "invalid PNG color type"); + /*NOT REACHED*/ + break; + } + + /* Now deal with the output processing */ + if (expand_tRNS && png_ptr->num_trans > 0 && + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0) + png_set_tRNS_to_alpha(png_ptr); + + switch (data_encoding) + { + default: + png_error(png_ptr, "bad data option (internal error)"); + break; + + case E_sRGB: + /* Change to 8-bit sRGB */ + png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); + /* FALL THROUGH */ + + case E_FILE: + if (png_ptr->bit_depth > 8) + png_set_scale_16(png_ptr); + break; + } + + if (cmap_entries > 256 || cmap_entries > image->colormap_entries) + png_error(png_ptr, "color map overflow (BAD internal error)"); + + image->colormap_entries = cmap_entries; + + /* Double check using the recorded background index */ + switch (output_processing) + { + case PNG_CMAP_NONE: + if (background_index != PNG_CMAP_NONE_BACKGROUND) + goto bad_background; + break; + + case PNG_CMAP_GA: + if (background_index != PNG_CMAP_GA_BACKGROUND) + goto bad_background; + break; + + case PNG_CMAP_TRANS: + if (background_index >= cmap_entries || + background_index != PNG_CMAP_TRANS_BACKGROUND) + goto bad_background; + break; + + case PNG_CMAP_RGB: + if (background_index != PNG_CMAP_RGB_BACKGROUND) + goto bad_background; + break; + + case PNG_CMAP_RGB_ALPHA: + if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND) + goto bad_background; + break; + + default: + png_error(png_ptr, "bad processing option (internal error)"); + + bad_background: + png_error(png_ptr, "bad background index (internal error)"); + } + + display->colormap_processing = output_processing; + + return 1/*ok*/; +} + +/* The final part of the color-map read called from png_image_finish_read. */ +static int +png_image_read_and_map(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + int passes; + + /* Called when the libpng data must be transformed into the color-mapped + * form. There is a local row buffer in display->local and this routine must + * do the interlace handling. + */ + switch (png_ptr->interlaced) + { + case PNG_INTERLACE_NONE: + passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + passes = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + passes = 0; + png_error(png_ptr, "unknown interlace type"); + } + + { + png_uint_32 height = image->height; + png_uint_32 width = image->width; + int proc = display->colormap_processing; + png_bytep first_row = png_voidcast(png_bytep, display->first_row); + ptrdiff_t step_row = display->row_bytes; + int pass; + + for (pass = 0; pass < passes; ++pass) + { + unsigned int startx, stepx, stepy; + png_uint_32 y; + + if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass); + stepx = PNG_PASS_COL_OFFSET(pass); + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = stepy = 1; + } + + for (; ylocal_row); + png_bytep outrow = first_row + y * step_row; + png_const_bytep end_row = outrow + width; + + /* Read read the libpng data into the temporary buffer. */ + png_read_row(png_ptr, inrow, NULL); + + /* Now process the row according to the processing option, note + * that the caller verifies that the format of the libpng output + * data is as required. + */ + outrow += startx; + switch (proc) + { + case PNG_CMAP_GA: + for (; outrow < end_row; outrow += stepx) + { + /* The data is always in the PNG order */ + unsigned int gray = *inrow++; + unsigned int alpha = *inrow++; + unsigned int entry; + + /* NOTE: this code is copied as a comment in + * make_ga_colormap above. Please update the + * comment if you change this code! + */ + if (alpha > 229) /* opaque */ + { + entry = (231 * gray + 128) >> 8; + } + else if (alpha < 26) /* transparent */ + { + entry = 231; + } + else /* partially opaque */ + { + entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray); + } + + *outrow = (png_byte)entry; + } + break; + + case PNG_CMAP_TRANS: + for (; outrow < end_row; outrow += stepx) + { + png_byte gray = *inrow++; + png_byte alpha = *inrow++; + + if (alpha == 0) + *outrow = PNG_CMAP_TRANS_BACKGROUND; + + else if (gray != PNG_CMAP_TRANS_BACKGROUND) + *outrow = gray; + + else + *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1); + } + break; + + case PNG_CMAP_RGB: + for (; outrow < end_row; outrow += stepx) + { + *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]); + inrow += 3; + } + break; + + case PNG_CMAP_RGB_ALPHA: + for (; outrow < end_row; outrow += stepx) + { + unsigned int alpha = inrow[3]; + + /* Because the alpha entries only hold alpha==0.5 values + * split the processing at alpha==0.25 (64) and 0.75 + * (196). + */ + + if (alpha >= 196) + *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], + inrow[2]); + + else if (alpha < 64) + *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND; + + else + { + /* Likewise there are three entries for each of r, g + * and b. We could select the entry by popcount on + * the top two bits on those architectures that + * support it, this is what the code below does, + * crudely. + */ + unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1; + + /* Here are how the values map: + * + * 0x00 .. 0x3f -> 0 + * 0x40 .. 0xbf -> 1 + * 0xc0 .. 0xff -> 2 + * + * So, as above with the explicit alpha checks, the + * breakpoints are at 64 and 196. + */ + if (inrow[0] & 0x80) back_i += 9; /* red */ + if (inrow[0] & 0x40) back_i += 9; + if (inrow[0] & 0x80) back_i += 3; /* green */ + if (inrow[0] & 0x40) back_i += 3; + if (inrow[0] & 0x80) back_i += 1; /* blue */ + if (inrow[0] & 0x40) back_i += 1; + + *outrow = (png_byte)back_i; + } + + inrow += 4; + } + break; + + default: + break; + } + } + } + } + + return 1; +} + +static int +png_image_read_colormapped(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_controlp control = image->opaque; + png_structrp png_ptr = control->png_ptr; + png_inforp info_ptr = control->info_ptr; + + int passes = 0; /* As a flag */ + + PNG_SKIP_CHUNKS(png_ptr); + + /* Update the 'info' structure and make sure the result is as required; first + * make sure to turn on the interlace handling if it will be required + * (because it can't be turned on *after* the call to png_read_update_info!) + */ + if (display->colormap_processing == PNG_CMAP_NONE) + passes = png_set_interlace_handling(png_ptr); + + png_read_update_info(png_ptr, info_ptr); + + /* The expected output can be deduced from the colormap_processing option. */ + switch (display->colormap_processing) + { + case PNG_CMAP_NONE: + /* Output must be one channel and one byte per pixel, the output + * encoding can be anything. + */ + if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + info_ptr->color_type == PNG_COLOR_TYPE_GRAY) && + info_ptr->bit_depth == 8) + break; + + goto bad_output; + + case PNG_CMAP_TRANS: + case PNG_CMAP_GA: + /* Output must be two channels and the 'G' one must be sRGB, the latter + * can be checked with an exact number because it should have been set + * to this number above! + */ + if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + info_ptr->bit_depth == 8 && + png_ptr->screen_gamma == PNG_GAMMA_sRGB && + image->colormap_entries == 256) + break; + + goto bad_output; + + case PNG_CMAP_RGB: + /* Output must be 8-bit sRGB encoded RGB */ + if (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + info_ptr->bit_depth == 8 && + png_ptr->screen_gamma == PNG_GAMMA_sRGB && + image->colormap_entries == 216) + break; + + goto bad_output; + + case PNG_CMAP_RGB_ALPHA: + /* Output must be 8-bit sRGB encoded RGBA */ + if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + info_ptr->bit_depth == 8 && + png_ptr->screen_gamma == PNG_GAMMA_sRGB && + image->colormap_entries == 244 /* 216 + 1 + 27 */) + break; + + /* goto bad_output; */ + /* FALL THROUGH */ + + default: + bad_output: + png_error(png_ptr, "bad color-map processing (internal error)"); + } + + /* Now read the rows. Do this here if it is possible to read directly into + * the output buffer, otherwise allocate a local row buffer of the maximum + * size libpng requires and call the relevant processing routine safely. + */ + { + png_voidp first_row = display->buffer; + ptrdiff_t row_bytes = display->row_stride; + + /* The following expression is designed to work correctly whether it gives + * a signed or an unsigned result. + */ + if (row_bytes < 0) + { + char *ptr = png_voidcast(char*, first_row); + ptr += (image->height-1) * (-row_bytes); + first_row = png_voidcast(png_voidp, ptr); + } + + display->first_row = first_row; + display->row_bytes = row_bytes; + } + + if (passes == 0) + { + int result; + png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + + display->local_row = row; + result = png_safe_execute(image, png_image_read_and_map, display); + display->local_row = NULL; + png_free(png_ptr, row); + + return result; + } + + else + { + png_alloc_size_t row_bytes = display->row_bytes; + + while (--passes >= 0) + { + png_uint_32 y = image->height; + png_bytep row = png_voidcast(png_bytep, display->first_row); + + while (y-- > 0) + { + png_read_row(png_ptr, row, NULL); + row += row_bytes; + } + } + + return 1; + } +} + +/* Just the row reading part of png_image_read. */ +static int +png_image_read_composite(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + int passes; + + switch (png_ptr->interlaced) + { + case PNG_INTERLACE_NONE: + passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + passes = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + passes = 0; + png_error(png_ptr, "unknown interlace type"); + } + + { + png_uint_32 height = image->height; + png_uint_32 width = image->width; + ptrdiff_t step_row = display->row_bytes; + unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; + int pass; + + for (pass = 0; pass < passes; ++pass) + { + unsigned int startx, stepx, stepy; + png_uint_32 y; + + if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass) * channels; + stepx = PNG_PASS_COL_OFFSET(pass) * channels; + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = channels; + stepy = 1; + } + + for (; ylocal_row); + png_bytep outrow; + png_const_bytep end_row; + + /* Read the row, which is packed: */ + png_read_row(png_ptr, inrow, NULL); + + outrow = png_voidcast(png_bytep, display->first_row); + outrow += y * step_row; + end_row = outrow + width * channels; + + /* Now do the composition on each pixel in this row. */ + outrow += startx; + for (; outrow < end_row; outrow += stepx) + { + png_byte alpha = inrow[channels]; + + if (alpha > 0) /* else no change to the output */ + { + unsigned int c; + + for (c=0; cimage; + png_structrp png_ptr = image->opaque->png_ptr; + png_inforp info_ptr = image->opaque->info_ptr; + png_uint_32 height = image->height; + png_uint_32 width = image->width; + int pass, passes; + + /* Double check the convoluted logic below. We expect to get here with + * libpng doing rgb to gray and gamma correction but background processing + * left to the png_image_read_background function. The rows libpng produce + * might be 8 or 16-bit but should always have two channels; gray plus alpha. + */ + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) + png_error(png_ptr, "lost rgb to gray"); + + if ((png_ptr->transformations & PNG_COMPOSE) != 0) + png_error(png_ptr, "unexpected compose"); + + if (png_get_channels(png_ptr, info_ptr) != 2) + png_error(png_ptr, "lost/gained channels"); + + /* Expect the 8-bit case to always remove the alpha channel */ + if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 && + (image->format & PNG_FORMAT_FLAG_ALPHA) != 0) + png_error(png_ptr, "unexpected 8-bit transformation"); + + switch (png_ptr->interlaced) + { + case PNG_INTERLACE_NONE: + passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + passes = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + passes = 0; + png_error(png_ptr, "unknown interlace type"); + } + + switch (png_get_bit_depth(png_ptr, info_ptr)) + { + default: + png_error(png_ptr, "unexpected bit depth"); + break; + + case 8: + /* 8-bit sRGB gray values with an alpha channel; the alpha channel is + * to be removed by composing on a background: either the row if + * display->background is NULL or display->background->green if not. + * Unlike the code above ALPHA_OPTIMIZED has *not* been done. + */ + { + png_bytep first_row = png_voidcast(png_bytep, display->first_row); + ptrdiff_t step_row = display->row_bytes; + + for (pass = 0; pass < passes; ++pass) + { + png_bytep row = png_voidcast(png_bytep, + display->first_row); + unsigned int startx, stepx, stepy; + png_uint_32 y; + + if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass); + stepx = PNG_PASS_COL_OFFSET(pass); + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = stepy = 1; + } + + if (display->background == NULL) + { + for (; ylocal_row); + png_bytep outrow = first_row + y * step_row; + png_const_bytep end_row = outrow + width; + + /* Read the row, which is packed: */ + png_read_row(png_ptr, inrow, NULL); + + /* Now do the composition on each pixel in this row. */ + outrow += startx; + for (; outrow < end_row; outrow += stepx) + { + png_byte alpha = inrow[1]; + + if (alpha > 0) /* else no change to the output */ + { + png_uint_32 component = inrow[0]; + + if (alpha < 255) /* else just use component */ + { + /* Since PNG_OPTIMIZED_ALPHA was not set it is + * necessary to invert the sRGB transfer + * function and multiply the alpha out. + */ + component = png_sRGB_table[component] * alpha; + component += png_sRGB_table[outrow[0]] * + (255-alpha); + component = PNG_sRGB_FROM_LINEAR(component); + } + + outrow[0] = (png_byte)component; + } + + inrow += 2; /* gray and alpha channel */ + } + } + } + + else /* constant background value */ + { + png_byte background8 = display->background->green; + png_uint_16 background = png_sRGB_table[background8]; + + for (; ylocal_row); + png_bytep outrow = first_row + y * step_row; + png_const_bytep end_row = outrow + width; + + /* Read the row, which is packed: */ + png_read_row(png_ptr, inrow, NULL); + + /* Now do the composition on each pixel in this row. */ + outrow += startx; + for (; outrow < end_row; outrow += stepx) + { + png_byte alpha = inrow[1]; + + if (alpha > 0) /* else use background */ + { + png_uint_32 component = inrow[0]; + + if (alpha < 255) /* else just use component */ + { + component = png_sRGB_table[component] * alpha; + component += background * (255-alpha); + component = PNG_sRGB_FROM_LINEAR(component); + } + + outrow[0] = (png_byte)component; + } + + else + outrow[0] = background8; + + inrow += 2; /* gray and alpha channel */ + } + + row += display->row_bytes; + } + } + } + } + break; + + case 16: + /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must + * still be done and, maybe, the alpha channel removed. This code also + * handles the alpha-first option. + */ + { + png_uint_16p first_row = png_voidcast(png_uint_16p, + display->first_row); + /* The division by two is safe because the caller passed in a + * stride which was multiplied by 2 (below) to get row_bytes. + */ + ptrdiff_t step_row = display->row_bytes / 2; + int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; + unsigned int outchannels = 1+preserve_alpha; + int swap_alpha = 0; + + if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST)) + swap_alpha = 1; + + for (pass = 0; pass < passes; ++pass) + { + unsigned int startx, stepx, stepy; + png_uint_32 y; + + /* The 'x' start and step are adjusted to output components here. + */ + if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass) * outchannels; + stepx = PNG_PASS_COL_OFFSET(pass) * outchannels; + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = outchannels; + stepy = 1; + } + + for (; ylocal_row), NULL); + inrow = png_voidcast(png_const_uint_16p, display->local_row); + + /* Now do the pre-multiplication on each pixel in this row. + */ + outrow += startx; + for (; outrow < end_row; outrow += stepx) + { + png_uint_32 component = inrow[0]; + png_uint_16 alpha = inrow[1]; + + if (alpha > 0) /* else 0 */ + { + if (alpha < 65535) /* else just use component */ + { + component *= alpha; + component += 32767; + component /= 65535; + } + } + + else + component = 0; + + outrow[swap_alpha] = (png_uint_16)component; + if (preserve_alpha) + outrow[1 ^ swap_alpha] = alpha; + + inrow += 2; /* components and alpha channel */ + } + } + } + } + break; + } + + return 1; +} + +/* The guts of png_image_finish_read as a png_safe_execute callback. */ +static int +png_image_read_direct(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + png_inforp info_ptr = image->opaque->info_ptr; + + png_uint_32 format = image->format; + int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; + int do_local_compose = 0; + int do_local_background = 0; /* to avoid double gamma correction bug */ + int passes = 0; + + /* Add transforms to ensure the correct output format is produced then check + * that the required implementation support is there. Always expand; always + * need 8 bits minimum, no palette and expanded tRNS. + */ + png_set_expand(png_ptr); + + /* Now check the format to see if it was modified. */ + { + png_uint_32 base_format = png_image_format(png_ptr) & + ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */; + png_uint_32 change = format ^ base_format; + png_fixed_point output_gamma; + int mode; /* alpha mode */ + + /* Do this first so that we have a record if rgb to gray is happening. */ + if (change & PNG_FORMAT_FLAG_COLOR) + { + /* gray<->color transformation required. */ + if (format & PNG_FORMAT_FLAG_COLOR) + png_set_gray_to_rgb(png_ptr); + + else + { + /* libpng can't do both rgb to gray and + * background/pre-multiplication if there is also significant gamma + * correction, because both operations require linear colors and + * the code only supports one transform doing the gamma correction. + * Handle this by doing the pre-multiplication or background + * operation in this code, if necessary. + * + * TODO: fix this by rewriting pngrtran.c (!) + * + * For the moment (given that fixing this in pngrtran.c is an + * enormous change) 'do_local_background' is used to indicate that + * the problem exists. + */ + if (base_format & PNG_FORMAT_FLAG_ALPHA) + do_local_background = 1/*maybe*/; + + png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, + PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); + } + + change &= ~PNG_FORMAT_FLAG_COLOR; + } + + /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise. + */ + { + png_fixed_point input_gamma_default; + + if ((base_format & PNG_FORMAT_FLAG_LINEAR) && + (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) + input_gamma_default = PNG_GAMMA_LINEAR; + else + input_gamma_default = PNG_DEFAULT_sRGB; + + /* Call png_set_alpha_mode to set the default for the input gamma; the + * output gamma is set by a second call below. + */ + png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default); + } + + if (linear) + { + /* If there *is* an alpha channel in the input it must be multiplied + * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG. + */ + if (base_format & PNG_FORMAT_FLAG_ALPHA) + mode = PNG_ALPHA_STANDARD; /* associated alpha */ + + else + mode = PNG_ALPHA_PNG; + + output_gamma = PNG_GAMMA_LINEAR; + } + + else + { + mode = PNG_ALPHA_PNG; + output_gamma = PNG_DEFAULT_sRGB; + } + + /* If 'do_local_background' is set check for the presence of gamma + * correction; this is part of the work-round for the libpng bug + * described above. + * + * TODO: fix libpng and remove this. + */ + if (do_local_background) + { + png_fixed_point gtest; + + /* This is 'png_gamma_threshold' from pngrtran.c; the test used for + * gamma correction, the screen gamma hasn't been set on png_struct + * yet; it's set below. png_struct::gamma, however, is set to the + * final value. + */ + if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma, + PNG_FP_1) && !png_gamma_significant(gtest)) + do_local_background = 0; + + else if (mode == PNG_ALPHA_STANDARD) + { + do_local_background = 2/*required*/; + mode = PNG_ALPHA_PNG; /* prevent libpng doing it */ + } + + /* else leave as 1 for the checks below */ + } + + /* If the bit-depth changes then handle that here. */ + if (change & PNG_FORMAT_FLAG_LINEAR) + { + if (linear /*16-bit output*/) + png_set_expand_16(png_ptr); + + else /* 8-bit output */ + png_set_scale_16(png_ptr); + + change &= ~PNG_FORMAT_FLAG_LINEAR; + } + + /* Now the background/alpha channel changes. */ + if (change & PNG_FORMAT_FLAG_ALPHA) + { + /* Removing an alpha channel requires composition for the 8-bit + * formats; for the 16-bit it is already done, above, by the + * pre-multiplication and the channel just needs to be stripped. + */ + if (base_format & PNG_FORMAT_FLAG_ALPHA) + { + /* If RGB->gray is happening the alpha channel must be left and the + * operation completed locally. + * + * TODO: fix libpng and remove this. + */ + if (do_local_background) + do_local_background = 2/*required*/; + + /* 16-bit output: just remove the channel */ + else if (linear) /* compose on black (well, pre-multiply) */ + png_set_strip_alpha(png_ptr); + + /* 8-bit output: do an appropriate compose */ + else if (display->background != NULL) + { + png_color_16 c; + + c.index = 0; /*unused*/ + c.red = display->background->red; + c.green = display->background->green; + c.blue = display->background->blue; + c.gray = display->background->green; + + /* This is always an 8-bit sRGB value, using the 'green' channel + * for gray is much better than calculating the luminance here; + * we can get off-by-one errors in that calculation relative to + * the app expectations and that will show up in transparent + * pixels. + */ + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + } + + else /* compose on row: implemented below. */ + { + do_local_compose = 1; + /* This leaves the alpha channel in the output, so it has to be + * removed by the code below. Set the encoding to the 'OPTIMIZE' + * one so the code only has to hack on the pixels that require + * composition. + */ + mode = PNG_ALPHA_OPTIMIZED; + } + } + + else /* output needs an alpha channel */ + { + /* This is tricky because it happens before the swap operation has + * been accomplished; however, the swap does *not* swap the added + * alpha channel (weird API), so it must be added in the correct + * place. + */ + png_uint_32 filler; /* opaque filler */ + int where; + + if (linear) + filler = 65535; + + else + filler = 255; + +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + { + where = PNG_FILLER_BEFORE; + change &= ~PNG_FORMAT_FLAG_AFIRST; + } + + else +# endif + where = PNG_FILLER_AFTER; + + png_set_add_alpha(png_ptr, filler, where); + } + + /* This stops the (irrelevant) call to swap_alpha below. */ + change &= ~PNG_FORMAT_FLAG_ALPHA; + } + + /* Now set the alpha mode correctly; this is always done, even if there is + * no alpha channel in either the input or the output because it correctly + * sets the output gamma. + */ + png_set_alpha_mode_fixed(png_ptr, mode, output_gamma); + +# ifdef PNG_FORMAT_BGR_SUPPORTED + if (change & PNG_FORMAT_FLAG_BGR) + { + /* Check only the output format; PNG is never BGR; don't do this if + * the output is gray, but fix up the 'format' value in that case. + */ + if (format & PNG_FORMAT_FLAG_COLOR) + png_set_bgr(png_ptr); + + else + format &= ~PNG_FORMAT_FLAG_BGR; + + change &= ~PNG_FORMAT_FLAG_BGR; + } +# endif + +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (change & PNG_FORMAT_FLAG_AFIRST) + { + /* Only relevant if there is an alpha channel - it's particularly + * important to handle this correctly because do_local_compose may + * be set above and then libpng will keep the alpha channel for this + * code to remove. + */ + if (format & PNG_FORMAT_FLAG_ALPHA) + { + /* Disable this if doing a local background, + * TODO: remove this when local background is no longer required. + */ + if (do_local_background != 2) + png_set_swap_alpha(png_ptr); + } + + else + format &= ~PNG_FORMAT_FLAG_AFIRST; + + change &= ~PNG_FORMAT_FLAG_AFIRST; + } +# endif + + /* If the *output* is 16-bit then we need to check for a byte-swap on this + * architecture. + */ + if (linear) + { + PNG_CONST png_uint_16 le = 0x0001; + + if (*(png_const_bytep)&le) + png_set_swap(png_ptr); + } + + /* If change is not now 0 some transformation is missing - error out. */ + if (change) + png_error(png_ptr, "png_read_image: unsupported transformation"); + } + + PNG_SKIP_CHUNKS(png_ptr); + + /* Update the 'info' structure and make sure the result is as required; first + * make sure to turn on the interlace handling if it will be required + * (because it can't be turned on *after* the call to png_read_update_info!) + * + * TODO: remove the do_local_background fixup below. + */ + if (!do_local_compose && do_local_background != 2) + passes = png_set_interlace_handling(png_ptr); + + png_read_update_info(png_ptr, info_ptr); + + { + png_uint_32 info_format = 0; + + if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_format |= PNG_FORMAT_FLAG_COLOR; + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + { + /* do_local_compose removes this channel below. */ + if (!do_local_compose) + { + /* do_local_background does the same if required. */ + if (do_local_background != 2 || + (format & PNG_FORMAT_FLAG_ALPHA) != 0) + info_format |= PNG_FORMAT_FLAG_ALPHA; + } + } + + else if (do_local_compose) /* internal error */ + png_error(png_ptr, "png_image_read: alpha channel lost"); + + if (info_ptr->bit_depth == 16) + info_format |= PNG_FORMAT_FLAG_LINEAR; + +# ifdef PNG_FORMAT_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + info_format |= PNG_FORMAT_FLAG_BGR; +# endif + +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (do_local_background == 2) + { + if (format & PNG_FORMAT_FLAG_AFIRST) + info_format |= PNG_FORMAT_FLAG_AFIRST; + } + + if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 || + ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 && + (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0)) + { + if (do_local_background == 2) + png_error(png_ptr, "unexpected alpha swap transformation"); + + info_format |= PNG_FORMAT_FLAG_AFIRST; + } +# endif + + /* This is actually an internal error. */ + if (info_format != format) + png_error(png_ptr, "png_read_image: invalid transformations"); + } + + /* Now read the rows. If do_local_compose is set then it is necessary to use + * a local row buffer. The output will be GA, RGBA or BGRA and must be + * converted to G, RGB or BGR as appropriate. The 'local_row' member of the + * display acts as a flag. + */ + { + png_voidp first_row = display->buffer; + ptrdiff_t row_bytes = display->row_stride; + + if (linear) + row_bytes *= 2; + + /* The following expression is designed to work correctly whether it gives + * a signed or an unsigned result. + */ + if (row_bytes < 0) + { + char *ptr = png_voidcast(char*, first_row); + ptr += (image->height-1) * (-row_bytes); + first_row = png_voidcast(png_voidp, ptr); + } + + display->first_row = first_row; + display->row_bytes = row_bytes; + } + + if (do_local_compose) + { + int result; + png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + + display->local_row = row; + result = png_safe_execute(image, png_image_read_composite, display); + display->local_row = NULL; + png_free(png_ptr, row); + + return result; + } + + else if (do_local_background == 2) + { + int result; + png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + + display->local_row = row; + result = png_safe_execute(image, png_image_read_background, display); + display->local_row = NULL; + png_free(png_ptr, row); + + return result; + } + + else + { + png_alloc_size_t row_bytes = display->row_bytes; + + while (--passes >= 0) + { + png_uint_32 y = image->height; + png_bytep row = png_voidcast(png_bytep, display->first_row); + + while (y-- > 0) + { + png_read_row(png_ptr, row, NULL); + row += row_bytes; + } + } + + return 1; + } +} + +int PNGAPI +png_image_finish_read(png_imagep image, png_const_colorp background, + void *buffer, png_int_32 row_stride, void *colormap) +{ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + png_uint_32 check; + + if (row_stride == 0) + row_stride = PNG_IMAGE_ROW_STRIDE(*image); + + if (row_stride < 0) + check = -row_stride; + + else + check = row_stride; + + if (image->opaque != NULL && buffer != NULL && + check >= PNG_IMAGE_ROW_STRIDE(*image)) + { + if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || + (image->colormap_entries > 0 && colormap != NULL)) + { + int result; + png_image_read_control display; + + memset(&display, 0, (sizeof display)); + display.image = image; + display.buffer = buffer; + display.row_stride = row_stride; + display.colormap = colormap; + display.background = background; + display.local_row = NULL; + + /* Choose the correct 'end' routine; for the color-map case all the + * setup has already been done. + */ + if (image->format & PNG_FORMAT_FLAG_COLORMAP) + result = + png_safe_execute(image, png_image_read_colormap, &display) && + png_safe_execute(image, png_image_read_colormapped, &display); + + else + result = + png_safe_execute(image, png_image_read_direct, &display); + + png_image_free(image); + return result; + } + + else + return png_image_error(image, + "png_image_finish_read[color-map]: no color-map"); + } + + else + return png_image_error(image, + "png_image_finish_read: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_finish_read: damaged PNG_IMAGE_VERSION"); + + return 0; +} + +#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/ext/libpng16/pngrio.c b/ext/libpng16/pngrio.c new file mode 100644 index 0000000000..2b9c103202 --- /dev/null +++ b/ext/libpng16/pngrio.c @@ -0,0 +1,118 @@ + +/* pngrio.c - functions for data input + * + * Last changed in libpng 1.6.0 [February 14, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Read the data from whatever input you are using. The default routine + * reads from a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered reads. This should never be asked + * to read more then 64K on a 16 bit machine. + */ +void /* PRIVATE */ +png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4, "reading %d bytes", (int)length); + + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + + else + png_error(png_ptr, "Call to NULL read function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ +void PNGCBAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); + + if (check != length) + png_error(png_ptr, "Read Error"); +} +#endif + +/* This function allows the application to supply a new input function + * for libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * + * png_ptr - pointer to a png input data structure + * + * io_ptr - pointer to user supplied structure containing info about + * the input functions. May be NULL. + * + * read_data_fn - pointer to a new input function that takes as its + * arguments a pointer to a png_struct, a pointer to + * a location where input data can be stored, and a 32-bit + * unsigned int that is the number of bytes to be read. + * To exit and output any fatal error messages the new write + * function should call png_error(png_ptr, "Error msg"). + * May be NULL, in which case libpng's default function will + * be used. + */ +void PNGAPI +png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->output_flush_fn = NULL; +#endif +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/ext/libpng16/pngrtran.c b/ext/libpng16/pngrtran.c new file mode 100644 index 0000000000..549fed7fe4 --- /dev/null +++ b/ext/libpng16/pngrtran.c @@ -0,0 +1,5110 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * Last changed in libpng 1.6.4 [August 21, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action"); + + if (png_ptr == NULL) + return; + + /* Tell libpng how we react to CRC errors in critical chunks */ + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + + case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ + png_warning(png_ptr, + "Can't discard critical data on CRC error"); + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + /* Tell libpng how we react to CRC errors in ancillary chunks */ + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +/* Is it OK to set a transformation now? Only if png_start_read_image or + * png_read_update_info have not been called. It is not necessary for the IHDR + * to have been read in all cases, the parameter allows for this check too. + */ +static int +png_rtran_ok(png_structrp png_ptr, int need_IHDR) +{ + if (png_ptr != NULL) + { + if (png_ptr->flags & PNG_FLAG_ROW_INIT) + png_app_error(png_ptr, + "invalid after png_start_read_image or png_read_update_info"); + + else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0) + png_app_error(png_ptr, "invalid before the PNG header has been read"); + + else + { + /* Turn on failure to initialize correctly for all transforms. */ + png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; + + return 1; /* Ok */ + } + } + + return 0; /* no png_error possible! */ +} +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS via a background color */ +void PNGFAPI +png_set_background_fixed(png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma) +{ + png_debug(1, "in png_set_background_fixed"); + + if (!png_rtran_ok(png_ptr, 0) || background_color == NULL) + return; + + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + { + png_warning(png_ptr, "Application must supply a known background gamma"); + return; + } + + png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + png_ptr->background = *background_color; + png_ptr->background_gamma = background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + if (need_expand) + png_ptr->transformations |= PNG_BACKGROUND_EXPAND; + else + png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_background(png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_set_background_fixed(png_ptr, background_color, background_gamma_code, + need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); +} +# endif /* FLOATING_POINT */ +#endif /* READ_BACKGROUND */ + +/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the + * one that pngrtran does first (scale) happens. This is necessary to allow the + * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. + */ +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +void PNGAPI +png_set_scale_16(png_structrp png_ptr) +{ + png_debug(1, "in png_set_scale_16"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= PNG_SCALE_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +/* Chop 16-bit depth files to 8-bit depth */ +void PNGAPI +png_set_strip_16(png_structrp png_ptr) +{ + png_debug(1, "in png_set_strip_16"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= PNG_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +void PNGAPI +png_set_strip_alpha(png_structrp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= PNG_STRIP_ALPHA; +} +#endif + +#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) +static png_fixed_point +translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma, + int is_screen) +{ + /* Check for flag values. The main reason for having the old Mac value as a + * flag is that it is pretty near impossible to work out what the correct + * value is from Apple documentation - a working Mac system is needed to + * discover the value! + */ + if (output_gamma == PNG_DEFAULT_sRGB || + output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) + { + /* If there is no sRGB support this just sets the gamma to the standard + * sRGB value. (This is a side effect of using this function!) + */ +# ifdef PNG_READ_sRGB_SUPPORTED + png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; +# else + PNG_UNUSED(png_ptr) +# endif + if (is_screen) + output_gamma = PNG_GAMMA_sRGB; + else + output_gamma = PNG_GAMMA_sRGB_INVERSE; + } + + else if (output_gamma == PNG_GAMMA_MAC_18 || + output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) + { + if (is_screen) + output_gamma = PNG_GAMMA_MAC_OLD; + else + output_gamma = PNG_GAMMA_MAC_INVERSE; + } + + return output_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +static png_fixed_point +convert_gamma_value(png_structrp png_ptr, double output_gamma) +{ + /* The following silently ignores cases where fixed point (times 100,000) + * gamma values are passed to the floating point API. This is safe and it + * means the fixed point constants work just fine with the floating point + * API. The alternative would just lead to undetected errors and spurious + * bug reports. Negative values fail inside the _fixed API unless they + * correspond to the flag values. + */ + if (output_gamma > 0 && output_gamma < 128) + output_gamma *= PNG_FP_1; + + /* This preserves -1 and -2 exactly: */ + output_gamma = floor(output_gamma + .5); + + if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN) + png_fixed_error(png_ptr, "gamma value"); + + return (png_fixed_point)output_gamma; +} +# endif +#endif /* READ_ALPHA_MODE || READ_GAMMA */ + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +void PNGFAPI +png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, + png_fixed_point output_gamma) +{ + int compose = 0; + png_fixed_point file_gamma; + + png_debug(1, "in png_set_alpha_mode"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); + + /* Validate the value to ensure it is in a reasonable range. The value + * is expected to be 1 or greater, but this range test allows for some + * viewing correction values. The intent is to weed out users of this API + * who use the inverse of the gamma value accidentally! Since some of these + * values are reasonable this may have to be changed. + */ + if (output_gamma < 70000 || output_gamma > 300000) + png_error(png_ptr, "output gamma out of expected range"); + + /* The default file gamma is the inverse of the output gamma; the output + * gamma may be changed below so get the file value first: + */ + file_gamma = png_reciprocal(output_gamma); + + /* There are really 8 possibilities here, composed of any combination + * of: + * + * premultiply the color channels + * do not encode non-opaque pixels + * encode the alpha as well as the color channels + * + * The differences disappear if the input/output ('screen') gamma is 1.0, + * because then the encoding is a no-op and there is only the choice of + * premultiplying the color channels or not. + * + * png_set_alpha_mode and png_set_background interact because both use + * png_compose to do the work. Calling both is only useful when + * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along + * with a default gamma value. Otherwise PNG_COMPOSE must not be set. + */ + switch (mode) + { + case PNG_ALPHA_PNG: /* default: png standard */ + /* No compose, but it may be set by png_set_background! */ + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + break; + + case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */ + compose = 1; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + /* The output is linear: */ + output_gamma = PNG_FP_1; + break; + + case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */ + compose = 1; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; + /* output_gamma records the encoding of opaque pixels! */ + break; + + case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */ + compose = 1; + png_ptr->transformations |= PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + break; + + default: + png_error(png_ptr, "invalid alpha mode"); + } + + /* Only set the default gamma if the file gamma has not been set (this has + * the side effect that the gamma in a second call to png_set_alpha_mode will + * be ignored.) + */ + if (png_ptr->colorspace.gamma == 0) + { + png_ptr->colorspace.gamma = file_gamma; + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; + } + + /* But always set the output gamma: */ + png_ptr->screen_gamma = output_gamma; + + /* Finally, if pre-multiplying, set the background fields to achieve the + * desired result. + */ + if (compose) + { + /* And obtain alpha pre-multiplication by composing on black: */ + memset(&png_ptr->background, 0, (sizeof png_ptr->background)); + png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */ + png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; + png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; + + if (png_ptr->transformations & PNG_COMPOSE) + png_error(png_ptr, + "conflicting calls to set alpha mode and background"); + + png_ptr->transformations |= PNG_COMPOSE; + } +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma) +{ + png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, + output_gamma)); +} +# endif +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Dither file to 8-bit. Supply a palette, the current number + * of elements in the palette, the maximum number of elements + * allowed, and a histogram if possible. If the current number + * of colors is greater then the maximum number, the palette will be + * modified to fit in the maximum number. "full_quantize" indicates + * whether we need a quantizing cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort * png_dsortp; +typedef png_dsort * * png_dsortpp; + +void PNGAPI +png_set_quantize(png_structrp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize) +{ + png_debug(1, "in png_set_quantize"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= PNG_QUANTIZE; + + if (!full_quantize) + { + int i; + + png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * (sizeof (png_byte)))); + for (i = 0; i < num_palette; i++) + png_ptr->quantize_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + * Perhaps not the best solution, but good enough. + */ + + int i; + + /* Initialize an array to sort colors */ + png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * (sizeof (png_byte)))); + + /* Initialize the quantize_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->quantize_sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + * bubble sort, and running it until we have sorted + * out enough colors. Note that we don't care about + * sorting all the colors, just finding which are + * least used. + */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* To stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->quantize_sort[j]] + < histogram[png_ptr->quantize_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->quantize_sort[j]; + png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; + png_ptr->quantize_sort[j + 1] = t; + done = 0; + } + } + + if (done) + break; + } + + /* Swap the palette around, and set up a table, if necessary */ + if (full_quantize) + { + int j = num_palette; + + /* Put all the useful colors within the max, but don't + * move the others. + */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* Move all the used colors inside the max limit, and + * develop a translation table. + */ + for (i = 0; i < maximum_colors; i++) + { + /* Only move the colors we need to */ + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* Indicate where the color went */ + png_ptr->quantize_index[j] = (png_byte)i; + png_ptr->quantize_index[i] = (png_byte)j; + } + } + + /* Find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->quantize_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* Find the closest color to one we threw out */ + d_index = png_ptr->quantize_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* Point to closest color */ + png_ptr->quantize_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->quantize_sort); + png_ptr->quantize_sort = NULL; + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + * we need to go through a median cut routine, but those + * don't always behave themselves with only a few colors + * as input. So we will just find the closest two colors, + * and throw out one of them (chosen somewhat randomly). + * [We don't understand this at all, so if someone wants to + * work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; + + t = NULL; + + /* Initialize palette index arrays */ + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * (sizeof (png_byte)))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * (sizeof (png_byte)))); + + /* Initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + (sizeof (png_dsortp)))); + + num_new_palette = num_palette; + + /* Initial wild guess at how far apart the farthest pixel + * pair we will be eliminating will be. Larger + * numbers mean more areas will be allocated, Smaller + * numbers run the risk of not saving enough data, and + * having to do this all over again. + * + * I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(sizeof (png_dsort))); + + if (t == NULL) + break; + + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } + + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (!full_quantize) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->quantize_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[next_j]; + + if ((int)png_ptr->quantize_index[k] == + num_new_palette) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[j]; + } + } + + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; + + png_ptr->index_to_palette[j] = + (png_byte)num_new_palette; + + png_ptr->palette_to_index[num_new_palette] = + (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index = NULL; + png_ptr->index_to_palette = NULL; + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_quantize) + { + int i; + png_bytep distance; + int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + + PNG_QUANTIZE_BLUE_BITS; + int num_red = (1 << PNG_QUANTIZE_RED_BITS); + int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); + int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + + png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, + (png_uint_32)(num_entries * (sizeof (png_byte)))); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + (sizeof (png_byte)))); + + memset(distance, 0xff, num_entries * (sizeof (png_byte))); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + /* int dr = abs(ir - r); */ + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS + + PNG_QUANTIZE_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + /* int dg = abs(ig - g); */ + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + /* int db = abs(ib - b); */ + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +void PNGFAPI +png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma, + png_fixed_point file_gamma) +{ + png_debug(1, "in png_set_gamma_fixed"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + /* New in libpng-1.5.4 - reserve particular negative values as flags. */ + scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); + file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); + + /* Checking the gamma values for being >0 was added in 1.5.4 along with the + * premultiplied alpha support; this actually hides an undocumented feature + * of the previous implementation which allowed gamma processing to be + * disabled in background handling. There is no evidence (so far) that this + * was being used; however, png_set_background itself accepted and must still + * accept '0' for the gamma value it takes, because it isn't always used. + * + * Since this is an API change (albeit a very minor one that removes an + * undocumented API feature) the following checks were only enabled in + * libpng-1.6.0. + */ + if (file_gamma <= 0) + png_error(png_ptr, "invalid file gamma in png_set_gamma"); + + if (scrn_gamma <= 0) + png_error(png_ptr, "invalid screen gamma in png_set_gamma"); + + /* Set the gamma values unconditionally - this overrides the value in the PNG + * file if a gAMA chunk was present. png_set_alpha_mode provides a + * different, easier, way to default the file gamma. + */ + png_ptr->colorspace.gamma = file_gamma; + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; + png_ptr->screen_gamma = scrn_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma) +{ + png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), + convert_gamma_value(png_ptr, file_gamma)); +} +# endif /* FLOATING_POINT_SUPPORTED */ +#endif /* READ_GAMMA */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structrp png_ptr) +{ + png_debug(1, "in png_set_expand"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + * + * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified + * to expand only the sample depth but not to expand the tRNS to alpha + * and its name was changed to png_set_expand_gray_1_2_4_to_8(). + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structrp png_ptr) +{ + png_debug(1, "in png_set_palette_to_rgb"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +} + +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr) +{ + png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= PNG_EXPAND; +} + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structrp png_ptr) +{ + png_debug(1, "in png_set_tRNS_to_alpha"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +} +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise + * it may not work correctly.) + */ +void PNGAPI +png_set_expand_16(png_structrp png_ptr) +{ + png_debug(1, "in png_set_expand_16"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +void PNGAPI +png_set_gray_to_rgb(png_structrp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + /* Because rgb must be 8 bits or more: */ + png_set_expand_gray_1_2_4_to_8(png_ptr); + png_ptr->transformations |= PNG_GRAY_TO_RGB; +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +void PNGFAPI +png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray"); + + /* Need the IHDR here because of the check on color_type below. */ + /* TODO: fix this */ + if (!png_rtran_ok(png_ptr, 1)) + return; + + switch(error_action) + { + case PNG_ERROR_ACTION_NONE: + png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + + case PNG_ERROR_ACTION_WARN: + png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + + case PNG_ERROR_ACTION_ERROR: + png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + break; + + default: + png_error(png_ptr, "invalid error action to rgb_to_gray"); + break; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#ifdef PNG_READ_EXPAND_SUPPORTED + png_ptr->transformations |= PNG_EXPAND; +#else + { + /* Make this an error in 1.6 because otherwise the application may assume + * that it just worked and get a memory overwrite. + */ + png_error(png_ptr, + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); + + /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */ + } +#endif + { + if (red >= 0 && green >= 0 && red + green <= PNG_FP_1) + { + png_uint_16 red_int, green_int; + + /* NOTE: this calculation does not round, but this behavior is retained + * for consistency, the inaccuracy is very small. The code here always + * overwrites the coefficients, regardless of whether they have been + * defaulted or set already. + */ + red_int = (png_uint_16)(((png_uint_32)red*32768)/100000); + green_int = (png_uint_16)(((png_uint_32)green*32768)/100000); + + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_coefficients_set = 1; + } + + else + { + if (red >= 0 && green >= 0) + png_app_warning(png_ptr, + "ignoring out of range rgb_to_gray coefficients"); + + /* Use the defaults, from the cHRM chunk if set, else the historical + * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See + * png_do_rgb_to_gray for more discussion of the values. In this case + * the coefficients are not marked as 'set' and are not overwritten if + * something has already provided a default. + */ + if (png_ptr->rgb_to_gray_red_coeff == 0 && + png_ptr->rgb_to_gray_green_coeff == 0) + { + png_ptr->rgb_to_gray_red_coeff = 6968; + png_ptr->rgb_to_gray_green_coeff = 23434; + /* png_ptr->rgb_to_gray_blue_coeff = 2366; */ + } + } + } +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red, + double green) +{ + png_set_rgb_to_gray_fixed(png_ptr, error_action, + png_fixed(png_ptr, red, "rgb to gray red coefficient"), + png_fixed(png_ptr, green, "rgb to gray green coefficient")); +} +#endif /* FLOATING POINT */ + +#endif /* RGB_TO_GRAY */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn"); + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +} +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +#ifdef PNG_READ_GAMMA_SUPPORTED +/* In the case of gamma transformations only do transformations on images where + * the [file] gamma and screen_gamma are not close reciprocals, otherwise it + * slows things down slightly, and also needlessly introduces small errors. + */ +static int /* PRIVATE */ +png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) +{ + /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma + * correction as a difference of the overall transform from 1.0 + * + * We want to compare the threshold with s*f - 1, if we get + * overflow here it is because of wacky gamma values so we + * turn on processing anyway. + */ + png_fixed_point gtest; + return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) || + png_gamma_significant(gtest); +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ + +/*For the moment 'png_init_palette_transformations' and + * 'png_init_rgb_transformations' only do some flag canceling optimizations. + * The intent is that these two routines should have palette or rgb operations + * extracted from 'png_init_read_transformations'. + */ +static void /* PRIVATE */ +png_init_palette_transformations(png_structrp png_ptr) +{ + /* Called to handle the (input) palette case. In png_do_read_transformations + * the first step is to expand the palette if requested, so this code must + * take care to only make changes that are invariant with respect to the + * palette expansion, or only do them if there is no expansion. + * + * STRIP_ALPHA has already been handled in the caller (by setting num_trans + * to 0.) + */ + int input_has_alpha = 0; + int input_has_transparency = 0; + + if (png_ptr->num_trans > 0) + { + int i; + + /* Ignore if all the entries are opaque (unlikely!) */ + for (i=0; inum_trans; ++i) + { + if (png_ptr->trans_alpha[i] == 255) + continue; + else if (png_ptr->trans_alpha[i] == 0) + input_has_transparency = 1; + else + { + input_has_transparency = 1; + input_has_alpha = 1; + break; + } + } + } + + /* If no alpha we can optimize. */ + if (!input_has_alpha) + { + /* Any alpha means background and associative alpha processing is + * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA + * and ENCODE_ALPHA are irrelevant. + */ + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + if (!input_has_transparency) + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); + } + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + /* png_set_background handling - deals with the complexity of whether the + * background color is in the file format or the screen format in the case + * where an 'expand' will happen. + */ + + /* The following code cannot be entered in the alpha pre-multiplication case + * because PNG_BACKGROUND_EXPAND is cancelled below. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + /* Invert the alpha channel (in tRNS) unless the pixels are + * going to be expanded, in which case leave it for later + */ + int i, istop = png_ptr->num_trans; + + for (i=0; itrans_alpha[i] = (png_byte)(255 - + png_ptr->trans_alpha[i]); + } + } +#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ + } + } /* background expand and (therefore) no alpha association. */ +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ +} + +static void /* PRIVATE */ +png_init_rgb_transformations(png_structrp png_ptr) +{ + /* Added to libpng-1.5.4: check the color type to determine whether there + * is any alpha or transparency in the image and simply cancel the + * background and alpha mode stuff if there isn't. + */ + int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; + int input_has_transparency = png_ptr->num_trans > 0; + + /* If no alpha we can optimize. */ + if (!input_has_alpha) + { + /* Any alpha means background and associative alpha processing is + * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA + * and ENCODE_ALPHA are irrelevant. + */ +# ifdef PNG_READ_ALPHA_MODE_SUPPORTED + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; +# endif + + if (!input_has_transparency) + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); + } + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + /* png_set_background handling - deals with the complexity of whether the + * background color is in the file format or the screen format in the case + * where an 'expand' will happen. + */ + + /* The following code cannot be entered in the alpha pre-multiplication case + * because PNG_BACKGROUND_EXPAND is cancelled below. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND) && + !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) + /* i.e., GRAY or GRAY_ALPHA */ + { + { + /* Expand background and tRNS chunks */ + int gray = png_ptr->background.gray; + int trans_gray = png_ptr->trans_color.gray; + + switch (png_ptr->bit_depth) + { + case 1: + gray *= 0xff; + trans_gray *= 0xff; + break; + + case 2: + gray *= 0x55; + trans_gray *= 0x55; + break; + + case 4: + gray *= 0x11; + trans_gray *= 0x11; + break; + + default: + + case 8: + /* FALL THROUGH (Already 8 bits) */ + + case 16: + /* Already a full 16 bits */ + break; + } + + png_ptr->background.red = png_ptr->background.green = + png_ptr->background.blue = (png_uint_16)gray; + + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.red = png_ptr->trans_color.green = + png_ptr->trans_color.blue = (png_uint_16)trans_gray; + } + } + } /* background expand and (therefore) no alpha association. */ +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ +} + +void /* PRIVATE */ +png_init_read_transformations(png_structrp png_ptr) +{ + png_debug(1, "in png_init_read_transformations"); + + /* This internal function is called from png_read_start_row in pngrutil.c + * and it is called before the 'rowbytes' calculation is done, so the code + * in here can change or update the transformations flags. + * + * First do updates that do not depend on the details of the PNG image data + * being processed. + */ + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds + * png_set_alpha_mode and this is another source for a default file gamma so + * the test needs to be performed later - here. In addition prior to 1.5.4 + * the tests were repeated for the PALETTE color type here - this is no + * longer necessary (and doesn't seem to have been necessary before.) + */ + { + /* The following temporary indicates if overall gamma correction is + * required. + */ + int gamma_correction = 0; + + if (png_ptr->colorspace.gamma != 0) /* has been set */ + { + if (png_ptr->screen_gamma != 0) /* screen set too */ + gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma, + png_ptr->screen_gamma); + + else + /* Assume the output matches the input; a long time default behavior + * of libpng, although the standard has nothing to say about this. + */ + png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma); + } + + else if (png_ptr->screen_gamma != 0) + /* The converse - assume the file matches the screen, note that this + * perhaps undesireable default can (from 1.5.4) be changed by calling + * png_set_alpha_mode (even if the alpha handling mode isn't required + * or isn't changed from the default.) + */ + png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma); + + else /* neither are set */ + /* Just in case the following prevents any processing - file and screen + * are both assumed to be linear and there is no way to introduce a + * third gamma value other than png_set_background with 'UNIQUE', and, + * prior to 1.5.4 + */ + png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1; + + /* We have a gamma value now. */ + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; + + /* Now turn the gamma transformation on or off as appropriate. Notice + * that PNG_GAMMA just refers to the file->screen correction. Alpha + * composition may independently cause gamma correction because it needs + * linear data (e.g. if the file has a gAMA chunk but the screen gamma + * hasn't been specified.) In any case this flag may get turned off in + * the code immediately below if the transform can be handled outside the + * row loop. + */ + if (gamma_correction) + png_ptr->transformations |= PNG_GAMMA; + + else + png_ptr->transformations &= ~PNG_GAMMA; + } +#endif + + /* Certain transformations have the effect of preventing other + * transformations that happen afterward in png_do_read_transformations, + * resolve the interdependencies here. From the code of + * png_do_read_transformations the order is: + * + * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) + * 2) PNG_STRIP_ALPHA (if no compose) + * 3) PNG_RGB_TO_GRAY + * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY + * 5) PNG_COMPOSE + * 6) PNG_GAMMA + * 7) PNG_STRIP_ALPHA (if compose) + * 8) PNG_ENCODE_ALPHA + * 9) PNG_SCALE_16_TO_8 + * 10) PNG_16_TO_8 + * 11) PNG_QUANTIZE (converts to palette) + * 12) PNG_EXPAND_16 + * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY + * 14) PNG_INVERT_MONO + * 15) PNG_SHIFT + * 16) PNG_PACK + * 17) PNG_BGR + * 18) PNG_PACKSWAP + * 19) PNG_FILLER (includes PNG_ADD_ALPHA) + * 20) PNG_INVERT_ALPHA + * 21) PNG_SWAP_ALPHA + * 22) PNG_SWAP_BYTES + * 23) PNG_USER_TRANSFORM [must be last] + */ +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + !(png_ptr->transformations & PNG_COMPOSE)) + { + /* Stripping the alpha channel happens immediately after the 'expand' + * transformations, before all other transformation, so it cancels out + * the alpha handling. It has the side effect negating the effect of + * PNG_EXPAND_tRNS too: + */ + png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA | + PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen + * so transparency information would remain just so long as it wasn't + * expanded. This produces unexpected API changes if the set of things + * that do PNG_EXPAND_tRNS changes (perfectly possible given the + * documentation - which says ask for what you want, accept what you + * get.) This makes the behavior consistent from 1.5.4: + */ + png_ptr->num_trans = 0; + } +#endif /* STRIP_ALPHA supported, no COMPOSE */ + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA + * settings will have no effect. + */ + if (!png_gamma_significant(png_ptr->screen_gamma)) + { + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + } +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* Make sure the coefficients for the rgb to gray conversion are set + * appropriately. + */ + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + png_colorspace_set_rgb_coefficients(png_ptr); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + /* Detect gray background and attempt to enable optimization for + * gray --> RGB case. + * + * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or + * RGB_ALPHA (in which case need_expand is superfluous anyway), the + * background color might actually be gray yet not be flagged as such. + * This is not a problem for the current code, which uses + * PNG_BACKGROUND_IS_GRAY only to decide when to do the + * png_do_gray_to_rgb() transformation. + * + * TODO: this code needs to be revised to avoid the complexity and + * interdependencies. The color type of the background should be recorded in + * png_set_background, along with the bit depth, then the code has a record + * of exactly what color space the background is currently in. + */ + if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) + { + /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if + * the file was grayscale the background value is gray. + */ + if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + } + + else if (png_ptr->transformations & PNG_COMPOSE) + { + /* PNG_COMPOSE: png_set_background was called with need_expand false, + * so the color is in the color space of the output or png_set_alpha_mode + * was called and the color is black. Ignore RGB_TO_GRAY because that + * happens before GRAY_TO_RGB. + */ + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if (png_ptr->background.red == png_ptr->background.green && + png_ptr->background.red == png_ptr->background.blue) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + } + } + } +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ +#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */ + + /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations + * can be performed directly on the palette, and some (such as rgb to gray) + * can be optimized inside the palette. This is particularly true of the + * composite (background and alpha) stuff, which can be pretty much all done + * in the palette even if the result is expanded to RGB or gray afterward. + * + * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and + * earlier and the palette stuff is actually handled on the first row. This + * leads to the reported bug that the palette returned by png_get_PLTE is not + * updated. + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_init_palette_transformations(png_ptr); + + else + png_init_rgb_transformations(png_ptr); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_EXPAND_16_SUPPORTED) + if ((png_ptr->transformations & PNG_EXPAND_16) && + (png_ptr->transformations & PNG_COMPOSE) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + png_ptr->bit_depth != 16) + { + /* TODO: fix this. Because the expand_16 operation is after the compose + * handling the background color must be 8, not 16, bits deep, but the + * application will supply a 16-bit value so reduce it here. + * + * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at + * present, so that case is ok (until do_expand_16 is moved.) + * + * NOTE: this discards the low 16 bits of the user supplied background + * color, but until expand_16 works properly there is no choice! + */ +# define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x)) + CHOP(png_ptr->background.red); + CHOP(png_ptr->background.green); + CHOP(png_ptr->background.blue); + CHOP(png_ptr->background.gray); +# undef CHOP + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */ + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \ + defined(PNG_READ_STRIP_16_TO_8_SUPPORTED)) + if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) && + (png_ptr->transformations & PNG_COMPOSE) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + png_ptr->bit_depth == 16) + { + /* On the other hand, if a 16-bit file is to be reduced to 8-bits per + * component this will also happen after PNG_COMPOSE and so the background + * color must be pre-expanded here. + * + * TODO: fix this too. + */ + png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257); + png_ptr->background.green = + (png_uint_16)(png_ptr->background.green * 257); + png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257); + png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257); + } +#endif + + /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the + * background support (see the comments in scripts/pnglibconf.dfa), this + * allows pre-multiplication of the alpha channel to be implemented as + * compositing on black. This is probably sub-optimal and has been done in + * 1.5.4 betas simply to enable external critique and testing (i.e. to + * implement the new API quickly, without lots of internal changes.) + */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +# ifdef PNG_READ_BACKGROUND_SUPPORTED + /* Includes ALPHA_MODE */ + png_ptr->background_1 = png_ptr->background; +# endif + + /* This needs to change - in the palette image case a whole set of tables are + * built when it would be quicker to just calculate the correct value for + * each palette entry directly. Also, the test is too tricky - why check + * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that + * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the + * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction + * the gamma tables will not be built even if composition is required on a + * gamma encoded value. + * + * In 1.5.4 this is addressed below by an additional check on the individual + * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the + * tables. + */ + if ((png_ptr->transformations & PNG_GAMMA) + || ((png_ptr->transformations & PNG_RGB_TO_GRAY) + && (png_gamma_significant(png_ptr->colorspace.gamma) || + png_gamma_significant(png_ptr->screen_gamma))) + || ((png_ptr->transformations & PNG_COMPOSE) + && (png_gamma_significant(png_ptr->colorspace.gamma) + || png_gamma_significant(png_ptr->screen_gamma) +# ifdef PNG_READ_BACKGROUND_SUPPORTED + || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE + && png_gamma_significant(png_ptr->background_gamma)) +# endif + )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) + && png_gamma_significant(png_ptr->screen_gamma)) + ) + { + png_build_gamma_table(png_ptr, png_ptr->bit_depth); + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_COMPOSE) + { + /* Issue a warning about this combination: because RGB_TO_GRAY is + * optimized to do the gamma transform if present yet do_background has + * to do the same thing if both options are set a + * double-gamma-correction happens. This is true in all versions of + * libpng to date. + */ + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + png_warning(png_ptr, + "libpng does not support gamma+background+rgb_to_gray"); + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + /* We don't get to here unless there is a tRNS chunk with non-opaque + * entries - see the checking code at the start of this function. + */ + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + png_fixed_point g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = PNG_FP_1; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = png_reciprocal(png_ptr->colorspace.gamma); + gs = png_reciprocal2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = png_reciprocal(png_ptr->background_gamma); + gs = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + default: + g = PNG_FP_1; /* back_1 */ + gs = PNG_FP_1; /* back */ + break; + } + + if (png_gamma_significant(gs)) + { + back.red = png_gamma_8bit_correct(png_ptr->background.red, + gs); + back.green = png_gamma_8bit_correct(png_ptr->background.green, + gs); + back.blue = png_gamma_8bit_correct(png_ptr->background.blue, + gs); + } + + else + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + + if (png_gamma_significant(g)) + { + back_1.red = png_gamma_8bit_correct(png_ptr->background.red, + g); + back_1.green = png_gamma_8bit_correct( + png_ptr->background.green, g); + back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, + g); + } + + else + { + back_1.red = (png_byte)png_ptr->background.red; + back_1.green = (png_byte)png_ptr->background.green; + back_1.blue = (png_byte)png_ptr->background.blue; + } + } + + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && + png_ptr->trans_alpha[i] != 0xff) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans_alpha[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + + /* Prevent the transformations being done again. + * + * NOTE: this is highly dubious; it removes the transformations in + * place. This seems inconsistent with the general treatment of the + * transformations elsewhere. + */ + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); + } /* color_type == PNG_COLOR_TYPE_PALETTE */ + + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ + else /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + int gs_sig, g_sig; + png_fixed_point g = PNG_FP_1; /* Correction to linear */ + png_fixed_point gs = PNG_FP_1; /* Correction to screen */ + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = png_ptr->screen_gamma; + /* gs = PNG_FP_1; */ + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = png_reciprocal(png_ptr->colorspace.gamma); + gs = png_reciprocal2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = png_reciprocal(png_ptr->background_gamma); + gs = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + + default: + png_error(png_ptr, "invalid background gamma type"); + } + + g_sig = png_gamma_significant(g); + gs_sig = png_gamma_significant(gs); + + if (g_sig) + png_ptr->background_1.gray = png_gamma_correct(png_ptr, + png_ptr->background.gray, g); + + if (gs_sig) + png_ptr->background.gray = png_gamma_correct(png_ptr, + png_ptr->background.gray, gs); + + if ((png_ptr->background.red != png_ptr->background.green) || + (png_ptr->background.red != png_ptr->background.blue) || + (png_ptr->background.red != png_ptr->background.gray)) + { + /* RGB or RGBA with color background */ + if (g_sig) + { + png_ptr->background_1.red = png_gamma_correct(png_ptr, + png_ptr->background.red, g); + + png_ptr->background_1.green = png_gamma_correct(png_ptr, + png_ptr->background.green, g); + + png_ptr->background_1.blue = png_gamma_correct(png_ptr, + png_ptr->background.blue, g); + } + + if (gs_sig) + { + png_ptr->background.red = png_gamma_correct(png_ptr, + png_ptr->background.red, gs); + + png_ptr->background.green = png_gamma_correct(png_ptr, + png_ptr->background.green, gs); + + png_ptr->background.blue = png_gamma_correct(png_ptr, + png_ptr->background.blue, gs); + } + } + + else + { + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ + png_ptr->background_1.red = png_ptr->background_1.green + = png_ptr->background_1.blue = png_ptr->background_1.gray; + + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + } + + /* The background is now in screen gamma: */ + png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN; + } /* color_type != PNG_COLOR_TYPE_PALETTE */ + }/* png_ptr->transformations & PNG_BACKGROUND */ + + else + /* Transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* RGB_TO_GRAY needs to have non-gamma-corrected values! */ + && ((png_ptr->transformations & PNG_EXPAND) == 0 || + (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) +#endif + ) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + /* NOTE: there are other transformations that should probably be in + * here too. + */ + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + + /* Done the gamma correction. */ + png_ptr->transformations &= ~PNG_GAMMA; + } /* color_type == PALETTE && !PNG_BACKGROUND transformation */ + } +#ifdef PNG_READ_BACKGROUND_SUPPORTED + else +#endif +#endif /* PNG_READ_GAMMA_SUPPORTED */ + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + /* No GAMMA transformation (see the hanging else 4 lines above) */ + if ((png_ptr->transformations & PNG_COMPOSE) && + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + + else if (png_ptr->trans_alpha[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans_alpha[i], back.red); + + png_composite(palette[i].green, palette[i].green, + png_ptr->trans_alpha[i], back.green); + + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans_alpha[i], back.blue); + } + } + + png_ptr->transformations &= ~PNG_COMPOSE; + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#ifdef PNG_READ_SHIFT_SUPPORTED + if ((png_ptr->transformations & PNG_SHIFT) && + !(png_ptr->transformations & PNG_EXPAND) && + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = png_ptr->num_palette; + int shift = 8 - png_ptr->sig_bit.red; + + png_ptr->transformations &= ~PNG_SHIFT; + + /* significant bits can be in the range 1 to 7 for a meaninful result, if + * the number of significant bits is 0 then no shift is done (this is an + * error condition which is silently ignored.) + */ + if (shift > 0 && shift < 8) + for (i=0; ipalette[i].red; + + component >>= shift; + png_ptr->palette[i].red = (png_byte)component; + } + + shift = 8 - png_ptr->sig_bit.green; + if (shift > 0 && shift < 8) + for (i=0; ipalette[i].green; + + component >>= shift; + png_ptr->palette[i].green = (png_byte)component; + } + + shift = 8 - png_ptr->sig_bit.blue; + if (shift > 0 && shift < 8) + for (i=0; ipalette[i].blue; + + component >>= shift; + png_ptr->palette[i].blue = (png_byte)component; + } + } +#endif /* PNG_READ_SHIFT_SUPPORTED */ +} + +/* Modify the info structure to reflect the transformations. The + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr) +{ + png_debug(1, "in png_read_transform_info"); + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + /* This check must match what actually happens in + * png_do_expand_palette; if it ever checks the tRNS chunk to see if + * it is all opaque we must do the same (at present it does not.) + */ + if (png_ptr->num_trans > 0) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + { + if (png_ptr->transformations & PNG_EXPAND_tRNS) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + + info_ptr->num_trans = 0; + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + /* The following is almost certainly wrong unless the background value is in + * the screen space! + */ + if (png_ptr->transformations & PNG_COMPOSE) + info_ptr->background = png_ptr->background; +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), + * however it seems that the code in png_init_read_transformations, which has + * been called before this from png_read_update_info->png_read_start_row + * sometimes does the gamma transform and cancels the flag. + * + * TODO: this looks wrong; the info_ptr should end up with a gamma equal to + * the screen_gamma value. The following probably results in weirdness if + * the info_ptr is used by the app after the rows have been read. + */ + info_ptr->colorspace.gamma = png_ptr->colorspace.gamma; +#endif + + if (info_ptr->bit_depth == 16) + { +# ifdef PNG_READ_16BIT_SUPPORTED +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_SCALE_16_TO_8) + info_ptr->bit_depth = 8; +# endif + +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_16_TO_8) + info_ptr->bit_depth = 8; +# endif + +# else + /* No 16 bit support: force chopping 16-bit input down to 8, in this case + * the app program can chose if both APIs are available by setting the + * correct scaling to use. + */ +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* For compatibility with previous versions use the strip method by + * default. This code works because if PNG_SCALE_16_TO_8 is already + * set the code below will do that in preference to the chop. + */ + png_ptr->transformations |= PNG_16_TO_8; + info_ptr->bit_depth = 8; +# else + +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + png_ptr->transformations |= PNG_SCALE_16_TO_8; + info_ptr->bit_depth = 8; +# else + + CONFIGURATION ERROR: you must enable at least one 16 to 8 method +# endif +# endif +#endif /* !READ_16BIT_SUPPORTED */ + } + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type = (png_byte)(info_ptr->color_type | + PNG_COLOR_MASK_COLOR); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type = (png_byte)(info_ptr->color_type & + ~PNG_COLOR_MASK_COLOR); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 && + info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + info_ptr->bit_depth = 16; + } +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + + else + info_ptr->channels = 1; + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_STRIP_ALPHA) + { + info_ptr->color_type = (png_byte)(info_ptr->color_type & + ~PNG_COLOR_MASK_ALPHA); + info_ptr->num_trans = 0; + } +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#ifdef PNG_READ_FILLER_SUPPORTED + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; + /* If adding a true alpha channel not just filler */ + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + + if (info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); + + /* Adding in 1.5.4: cache the above value in png_struct so that we can later + * check in png_rowbytes that the user buffer won't get overwritten. Note + * that the field is not always set - if png_read_update_info isn't called + * the application has to either not do any transforms or get the calculation + * right itself. + */ + png_ptr->info_rowbytes = info_ptr->rowbytes; + +#ifndef PNG_READ_EXPAND_SUPPORTED + if (png_ptr) + return; +#endif +} + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) +{ + png_debug(1, "in png_do_read_transformations"); + + if (png_ptr->row_buf == NULL) + { + /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this + * error is incredibly rare and incredibly easy to debug without this + * information. + */ + png_error(png_ptr, "NULL row buffer"); + } + + /* The following is debugging; prior to 1.5.4 the code was never compiled in; + * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro + * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for + * all transformations, however in practice the ROW_INIT always gets done on + * demand, if necessary. + */ + if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 && + !(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + /* Application has failed to call either png_read_start_image() or + * png_read_update_info() after setting transforms that expand pixels. + * This check added to libpng-1.2.19 (but not enabled until 1.5.4). + */ + png_error(png_ptr, "Uninitialized row"); + } + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(row_info, png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); + } + + else + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + png_do_expand(row_info, png_ptr->row_buf + 1, + &(png_ptr->trans_color)); + + else + png_do_expand(row_info, png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + !(png_ptr->transformations & PNG_COMPOSE) && + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_do_strip_channel(row_info, png_ptr->row_buf + 1, + 0 /* at_start == false, because SWAP_ALPHA happens later */); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, row_info, + png_ptr->row_buf + 1); + + if (rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* From Andreas Dilger e-mail to png-implement, 26 March 1998: + * + * In most cases, the "simple transparency" should be done prior to doing + * gray-to-RGB, or you will have to test 3x as many bytes to check if a + * pixel is transparent. You would also need to make sure that the + * transparency information is upgraded to RGB. + * + * To summarize, the current flow is: + * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + * with background "in place" if transparent, + * convert to RGB if necessary + * - Gray + alpha -> composite with gray background and remove alpha bytes, + * convert to RGB if necessary + * + * To support RGB backgrounds for gray images we need: + * - Gray + simple transparency -> convert to RGB + simple transparency, + * compare 3 or 6 bytes and composite with + * background "in place" if transparent + * (3x compare/pixel compared to doing + * composite with gray bkgrnd) + * - Gray + alpha -> convert to RGB + alpha, composite with background and + * remove alpha bytes (3x float + * operations/pixel compared with composite + * on gray background) + * + * Greg's change will do this. The reason it wasn't done before is for + * performance, as this increases the per-pixel operations. If we would check + * in advance if the background was gray or RGB, and position the gray-to-RGB + * transform appropriately, then it would save a lot of work/time. + */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* If gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons + */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + if (png_ptr->transformations & PNG_COMPOSE) + png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if ((png_ptr->transformations & PNG_GAMMA) && +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* Because RGB_TO_GRAY does the gamma transform. */ + !(png_ptr->transformations & PNG_RGB_TO_GRAY) && +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + /* Because PNG_COMPOSE does the gamma transform if there is something to + * do (if there is an alpha channel or transparency.) + */ + !((png_ptr->transformations & PNG_COMPOSE) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + /* Because png_init_read_transformations transforms the palette, unless + * RGB_TO_GRAY will do the transform. + */ + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + (png_ptr->transformations & PNG_COMPOSE) && + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_do_strip_channel(row_info, png_ptr->row_buf + 1, + 0 /* at_start == false, because SWAP_ALPHA happens later */); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + if ((png_ptr->transformations & PNG_ENCODE_ALPHA) && + (row_info->color_type & PNG_COLOR_MASK_ALPHA)) + png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_SCALE_16_TO_8) + png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* There is no harm in doing both of these because only one has any effect, + * by putting the 'scale' option first if the app asks for scale (either by + * calling the API or in a TRANSFORM flag) this is what happens. + */ + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + png_do_quantize(row_info, png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->quantize_index); + + if (row_info->rowbytes == 0) + png_error(png_ptr, "png_do_quantize returned rowbytes=0"); + } +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_16_SUPPORTED + /* Do the expansion now, after all the arithmetic has been done. Notice + * that previous transformations can handle the PNG_EXPAND_16 flag if this + * is efficient (particularly true in the case of gamma correction, where + * better accuracy results faster!) + */ + if (png_ptr->transformations & PNG_EXPAND_16) + png_do_expand_16(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* NOTE: moved here in 1.5.4 (from much later in this list.) */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(row_info, png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED + /* Added at libpng-1.5.10 */ + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + png_ptr->num_palette_max >= 0) + png_do_check_palette_indexes(png_ptr, row_info); +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(row_info, png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_16BIT_SUPPORTED +#ifdef PNG_READ_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(row_info, png_ptr->row_buf + 1); +#endif +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* User read transform function */ + (png_ptr, /* png_ptr */ + row_info, /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + if (png_ptr->user_transform_depth) + row_info->bit_depth = png_ptr->user_transform_depth; + + if (png_ptr->user_transform_channels) + row_info->channels = png_ptr->user_transform_channels; +#endif + row_info->pixel_depth = (png_byte)(row_info->bit_depth * + row_info->channels); + + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width); + } +#endif +} + +#ifdef PNG_READ_PACK_SUPPORTED +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +void /* PRIVATE */ +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack"); + + if (row_info->bit_depth < 8) + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +void /* PRIVATE */ +png_do_unshift(png_row_infop row_info, png_bytep row, + png_const_color_8p sig_bits) +{ + int color_type; + + png_debug(1, "in png_do_unshift"); + + /* The palette case has already been handled in the _init routine. */ + color_type = row_info->color_type; + + if (color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int bit_depth = row_info->bit_depth; + + if (color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = bit_depth - sig_bits->red; + shift[channels++] = bit_depth - sig_bits->green; + shift[channels++] = bit_depth - sig_bits->blue; + } + + else + { + shift[channels++] = bit_depth - sig_bits->gray; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = bit_depth - sig_bits->alpha; + } + + { + int c, have_shift; + + for (c = have_shift = 0; c < channels; ++c) + { + /* A shift of more than the bit depth is an error condition but it + * gets ignored here. + */ + if (shift[c] <= 0 || shift[c] >= bit_depth) + shift[c] = 0; + + else + have_shift = 1; + } + + if (!have_shift) + return; + } + + switch (bit_depth) + { + default: + /* Must be 1bpp gray: should not be here! */ + /* NOTREACHED */ + break; + + case 2: + /* Must be 2bpp gray */ + /* assert(channels == 1 && shift[0] == 1) */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + + while (bp < bp_end) + { + int b = (*bp >> 1) & 0x55; + *bp++ = (png_byte)b; + } + break; + } + + case 4: + /* Must be 4bpp gray */ + /* assert(channels == 1) */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + int gray_shift = shift[0]; + int mask = 0xf >> gray_shift; + + mask |= mask << 4; + + while (bp < bp_end) + { + int b = (*bp >> gray_shift) & mask; + *bp++ = (png_byte)b; + } + break; + } + + case 8: + /* Single byte components, G, GA, RGB, RGBA */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + int channel = 0; + + while (bp < bp_end) + { + int b = *bp >> shift[channel]; + if (++channel >= channels) + channel = 0; + *bp++ = (png_byte)b; + } + break; + } + +#ifdef PNG_READ_16BIT_SUPPORTED + case 16: + /* Double byte components, G, GA, RGB, RGBA */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + int channel = 0; + + while (bp < bp_end) + { + int value = (bp[0] << 8) + bp[1]; + + value >>= shift[channel]; + if (++channel >= channels) + channel = 0; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale rows of bit depth 16 down to 8 accurately */ +void /* PRIVATE */ +png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_scale_16_to_8"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; /* source */ + png_bytep dp = row; /* destination */ + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + + while (sp < ep) + { + /* The input is an array of 16 bit components, these must be scaled to + * 8 bits each. For a 16 bit value V the required value (from the PNG + * specification) is: + * + * (V * 255) / 65535 + * + * This reduces to round(V / 257), or floor((V + 128.5)/257) + * + * Represent V as the two byte value vhi.vlo. Make a guess that the + * result is the top byte of V, vhi, then the correction to this value + * is: + * + * error = floor(((V-vhi.vhi) + 128.5) / 257) + * = floor(((vlo-vhi) + 128.5) / 257) + * + * This can be approximated using integer arithmetic (and a signed + * shift): + * + * error = (vlo-vhi+128) >> 8; + * + * The approximate differs from the exact answer only when (vlo-vhi) is + * 128; it then gives a correction of +1 when the exact correction is + * 0. This gives 128 errors. The exact answer (correct for all 16 bit + * input values) is: + * + * error = (vlo-vhi+128)*65535 >> 24; + * + * An alternative arithmetic calculation which also gives no errors is: + * + * (V * 255 + 32895) >> 16 + */ + + png_int_32 tmp = *sp++; /* must be signed! */ + tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24; + *dp++ = (png_byte)tmp; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +void /* PRIVATE */ +/* Simply discard the low byte. This was the default behavior prior + * to libpng-1.5.4. + */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; /* source */ + png_bytep dp = row; /* destination */ + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + + while (sp < ep) + { + *dp++ = *sp; + sp += 2; /* skip low byte */ + } + + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha"); + + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } +#endif + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_uint_32 row_width; + png_debug(1, "in png_do_read_invert_alpha"); + + row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } +#endif + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } +#endif + } +} +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED +/* Add filler channel if we have RGB color */ +void /* PRIVATE */ +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + +#ifdef PNG_READ_16BIT_SUPPORTED + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); +#endif + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler"); + + if ( + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from G to GX */ + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + + else + { + /* This changes the data from G to XG */ + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from GG to GGXX */ + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + + else + { + /* This changes the data from GG to XXGG */ + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } +#endif + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RGB to RGBX */ + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + + else + { + /* This changes the data from RGB to XRGB */ + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + + else + { + /* This changes the data from RRGGBB to XXRRGGBB */ + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } +#endif + } /* COLOR_TYPE == RGB */ +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand grayscale files to RGB, with or without alpha */ +void /* PRIVATE */ +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb"); + + if (row_info->bit_depth >= 8 && + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + /* This changes G to RGB */ + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + + else + { + /* This changes GG to RRGGBB */ + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This changes GA to RGBA */ + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + + else + { + /* This changes GGAA to RRGGBBAA */ + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels = (png_byte)(row_info->channels + 2); + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ of 1998-01-04 at + * (THIS LINK IS DEAD June 2008 but + * versions dated 1998 through November 2002 have been archived at + * http://web.archive.org/web/20000816232553/http://www.inforamp.net/ + * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) + * Charles Poynton poynton at poynton.com + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * Poynton's current link (as of January 2003 through July 2011): + * + * has changed the numbers slightly: + * + * Y = 0.2126*R + 0.7152*G + 0.0722*B + * + * which can be expressed with integers as + * + * Y = (6966 * R + 23436 * G + 2366 * B)/32768 + * + * Historically, however, libpng uses numbers derived from the ITU-R Rec 709 + * end point chromaticities and the D65 white point. Depending on the + * precision used for the D65 white point this produces a variety of different + * numbers, however if the four decimal place value used in ITU-R Rec 709 is + * used (0.3127,0.3290) the Y calculation would be: + * + * Y = (6968 * R + 23435 * G + 2366 * B)/32768 + * + * While this is correct the rounding results in an overflow for white, because + * the sum of the rounded coefficients is 32769, not 32768. Consequently + * libpng uses, instead, the closest non-overflowing approximation: + * + * Y = (6968 * R + 23434 * G + 2366 * B)/32768 + * + * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk + * (including an sRGB chunk) then the chromaticities are used to calculate the + * coefficients. See the chunk handling in pngrutil.c for more information. + * + * In all cases the calculation is to be done in a linear colorspace. If no + * gamma information is available to correct the encoding of the original RGB + * values this results in an implicit assumption that the original PNG RGB + * values were linear. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). Because + * the API takes just red and green coefficients the blue coefficient is + * calculated to make the sum 32768. This will result in different rounding + * to that used above. + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) + +{ + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray"); + + if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) && + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + PNG_CONST png_uint_32 bc = 32768 - rc - gc; + PNG_CONST png_uint_32 row_width = row_info->width; + PNG_CONST int have_alpha = + (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; + + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + /* Notice that gamma to/from 1 are not necessarily inverses (if + * there is an overall gamma correction). Prior to 1.5.5 this code + * checked the linearized values for equality; this doesn't match + * the documentation, the original values must be checked. + */ + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + + if (red != green || red != blue) + { + red = png_ptr->gamma_to_1[red]; + green = png_ptr->gamma_to_1[green]; + blue = png_ptr->gamma_to_1[blue]; + + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red + gc*green + bc*blue + 16384)>>15]; + } + + else + { + /* If there is no overall correction the table will not be + * set. + */ + if (png_ptr->gamma_table != NULL) + red = png_ptr->gamma_table[red]; + + *(dp++) = red; + } + + if (have_alpha) + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + + if (red != green || red != blue) + { + rgb_error |= 1; + /* NOTE: this is the historical approach which simply + * truncates the results. + */ + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + } + + else + *(dp++) = red; + + if (have_alpha) + *(dp++) = *(sp++); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red == green && red == blue) + { + if (png_ptr->gamma_16_table != NULL) + w = png_ptr->gamma_16_table[(red&0xff) + >> png_ptr->gamma_shift][red>>8]; + + else + w = red; + } + + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) + >> png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) + >> png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1 + 16384)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + + if (have_alpha) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + } + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red != green || red != blue) + rgb_error |= 1; + + /* From 1.5.5 in the 16 bit case do the accurate conversion even + * in the 'fast' case - this is because this is where the code + * ends up when handling linear 16 bit data. + */ + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> + 15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + + if (have_alpha) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + } + } + } + } + + row_info->channels = (png_byte)(row_info->channels - 2); + row_info->color_type = (png_byte)(row_info->color_type & + ~PNG_COLOR_MASK_COLOR); + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + return rgb_error; +} +#endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth + * large of png_color. This lets grayscale images be treated as + * paletted. Most useful for gamma correction and simplification + * of code. This API is not used internally. + */ +void PNGAPI +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette"); + + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + + case 2: + num_palette = 4; + color_inc = 0x55; + break; + + case 4: + num_palette = 16; + color_inc = 0x11; + break; + + case 8: + num_palette = 256; + color_inc = 1; + break; + + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} +#endif + + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* Replace any alpha or transparency with the supplied background color. + * "background" is already in the screen gamma, while "background_1" is + * at a gamma of 1.0. Paletted files have already been taken care of. + */ +void /* PRIVATE */ +png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) +{ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; + png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; + png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; + png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; + png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; + int gamma_shift = png_ptr->gamma_shift; + int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; +#endif + + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + int shift; + + png_debug(1, "in png_do_compose"); + + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); + tmp |= png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (!shift) + { + shift = 7; + sp++; + } + + else + shift--; + } + break; + } + + case 2: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + else + { + unsigned int p = (*sp >> shift) & 0x03; + unsigned int g = (gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03; + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= g << shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (!shift) + { + shift = 6; + sp++; + } + + else + shift -= 2; + } + } + + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (!shift) + { + shift = 6; + sp++; + } + + else + shift -= 2; + } + } + break; + } + + case 4: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0xf0f >> (4 - shift)); + tmp |= png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + else + { + unsigned int p = (*sp >> shift) & 0x0f; + unsigned int g = (gamma_table[p | (p << 4)] >> 4) & + 0x0f; + unsigned int tmp = *sp & (0xf0f >> (4 - shift)); + tmp |= g << shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (!shift) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0xf0f >> (4 - shift)); + tmp |= png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (!shift) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + break; + } + + case 8: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; + + else + *sp = gamma_table[*sp]; + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; + } + } + break; + } + + case 16: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == png_ptr->trans_color.gray) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); + } + + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == png_ptr->trans_color.gray) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); + } + } + } + break; + } + + default: + break; + } + break; + } + + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *sp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.gray; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.gray); + if (!optimize) + w = gamma_from_1[w]; + *sp = w; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_byte a = *(sp + 1); + + if (a == 0) + *sp = (png_byte)png_ptr->background.gray; + + else if (a < 0xff) + png_composite(*sp, *sp, a, png_ptr->background.gray); + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, png_ptr->background_1.gray); + if (optimize) + w = v; + else + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, png_ptr->background.gray); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.red); + if (!optimize) w = gamma_from_1[w]; + *sp = w; + + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, png_ptr->background_1.green); + if (!optimize) w = gamma_from_1[w]; + *(sp + 1) = w; + + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, png_ptr->background_1.blue); + if (!optimize) w = gamma_from_1[w]; + *(sp + 2) = w; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else if (a < 0xff) + { + png_composite(*sp, *sp, a, png_ptr->background.red); + + png_composite(*(sp + 1), *(sp + 1), a, + png_ptr->background.green); + + png_composite(*(sp + 2), *(sp + 2), a, + png_ptr->background.blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v, w; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, png_ptr->background_1.red); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> + 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, png_ptr->background_1.green); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 2) = (png_byte)((w >> 8) & 0xff); + *(sp + 3) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, png_ptr->background_1.blue); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 4) = (png_byte)((w >> 8) & 0xff); + *(sp + 5) = (png_byte)(w & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, png_ptr->background.red); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + png_composite_16(v, g, a, png_ptr->background.green); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + png_composite_16(v, b, a, png_ptr->background.blue); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + + default: + break; + } + } +} +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * build_gamma_table(). + */ +void /* PRIVATE */ +png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr) +{ + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; + int gamma_shift = png_ptr->gamma_shift; + + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma"); + + if (((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + + *sp = gamma_table[*sp]; + sp++; + + *sp = gamma_table[*sp]; + sp++; + + sp++; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; + + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; + + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + default: + break; + } + } +} +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* Encode the alpha channel to the output gamma (the input channel is always + * linear.) Called only with color types that have an alpha channel. Needs the + * from_1 tables. + */ +void /* PRIVATE */ +png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) +{ + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_encode_alpha"); + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + if (row_info->bit_depth == 8) + { + PNG_CONST png_bytep table = png_ptr->gamma_from_1; + + if (table != NULL) + { + PNG_CONST int step = + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; + + /* The alpha channel is the last component: */ + row += step - 1; + + for (; row_width > 0; --row_width, row += step) + *row = table[*row]; + + return; + } + } + + else if (row_info->bit_depth == 16) + { + PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; + PNG_CONST int gamma_shift = png_ptr->gamma_shift; + + if (table != NULL) + { + PNG_CONST int step = + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; + + /* The alpha channel is the last component: */ + row += step - 2; + + for (; row_width > 0; --row_width, row += step) + { + png_uint_16 v; + + v = table[*(row + 1) >> gamma_shift][*row]; + *row = (png_byte)((v >> 8) & 0xff); + *(row + 1) = (png_byte)(v & 0xff); + } + + return; + } + } + } + + /* Only get to here if called with a weird row_info; no harm has been done, + * so just issue a warning. + */ + png_warning(png_ptr, "png_do_encode_alpha: unexpected call"); +} +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expands a palette row to an RGB or RGBA row depending + * upon whether you supply trans and num_trans. + */ +void /* PRIVATE */ +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette"); + + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + + else + *dp = 0; + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift += 4; + + dp--; + } + break; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (row_info->bit_depth == 8) + { + { + if (num_trans > 0) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + + else + *dp-- = trans_alpha[*sp]; + + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the already + * expanded transparency value is supplied, an alpha channel is built. + */ +void /* PRIVATE */ +png_do_expand(png_row_infop row_info, png_bytep row, + png_const_color_16p trans_color) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + unsigned int gray = trans_color ? trans_color->gray : 0; + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (gray & 0x01) * 0xff; + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + + else + *dp = 0; + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + gray = (gray & 0x03) * 0x55; + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + gray = (gray & 0x0f) * 0x11; + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_color != NULL) + { + if (row_info->bit_depth == 8) + { + gray = gray & 0xff; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + } + } + + else if (row_info->bit_depth == 16) + { + unsigned int gray_high = (gray >> 8) & 0xff; + unsigned int gray_low = gray & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 1) == gray_high && *(sp) == gray_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + } + } + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color) + { + if (row_info->bit_depth == 8) + { + png_byte red = (png_byte)(trans_color->red & 0xff); + png_byte green = (png_byte)(trans_color->green & 0xff); + png_byte blue = (png_byte)(trans_color->blue & 0xff); + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_color->red & 0xff); + png_byte green_low = (png_byte)(trans_color->green & 0xff); + png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* If the bit depth is 8 and the color type is not a palette type expand the + * whole row to 16 bits. Has no effect otherwise. + */ +void /* PRIVATE */ +png_do_expand_16(png_row_infop row_info, png_bytep row) +{ + if (row_info->bit_depth == 8 && + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + /* The row have a sequence of bytes containing [0..255] and we need + * to turn it into another row containing [0..65535], to do this we + * calculate: + * + * (input / 255) * 65535 + * + * Which happens to be exactly input * 257 and this can be achieved + * simply by byte replication in place (copying backwards). + */ + png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ + png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ + while (dp > sp) + dp[-2] = dp[-1] = *--sp, dp -= 2; + + row_info->rowbytes *= 2; + row_info->bit_depth = 16; + row_info->pixel_depth = (png_byte)(row_info->channels * 16); + } +} +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +void /* PRIVATE */ +png_do_quantize(png_row_infop row_info, png_bytep row, + png_const_bytep palette_lookup, png_const_bytep quantize_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_quantize"); + + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* This looks real messy, but the compiler will reduce + * it down to a reasonable formula. For example, with + * 5 bits per color, we get: + * p = (((r >> 3) & 0x1f) << 10) | + * (((g >> 3) & 0x1f) << 5) | + * ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + quantize_lookup) + { + sp = row; + + for (i = 0; i < row_width; i++, sp++) + { + *sp = quantize_lookup[*sp]; + } + } + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel"); + + if ( + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff); + *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (s0 + s1 + 65536) & 0xffff; + png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/ext/libpng16/pngrutil.c b/ext/libpng16/pngrutil.c new file mode 100644 index 0000000000..fd65c21879 --- /dev/null +++ b/ext/libpng16/pngrutil.c @@ -0,0 +1,4475 @@ + +/* pngrutil.c - utilities to read a PNG file + * + * Last changed in libpng 1.6.7 [November 14, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +png_uint_32 PNGAPI +png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range"); + + return (uval); +} + +#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) +/* The following is a variation on the above for use with the fixed + * point values used for gAMA and cHRM. Instead of png_error it + * issues a warning and returns (-1) - an invalid value because both + * gAMA and cHRM use *unsigned* integers for fixed point values. + */ +#define PNG_FIXED_ERROR (-1) + +static png_fixed_point /* PRIVATE */ +png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval <= PNG_UINT_31_MAX) + return (png_fixed_point)uval; /* known to be in range */ + + /* The caller can turn off the warning by passing NULL. */ + if (png_ptr != NULL) + png_warning(png_ptr, "PNG fixed point integer out of range"); + + return PNG_FIXED_ERROR; +} +#endif + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +/* NOTE: the read macros will obscure these definitions, so that if + * PNG_USE_READ_MACROS is set the library will not use them internally, + * but the APIs will still be available externally. + * + * The parentheses around "PNGAPI function_name" in the following three + * functions are necessary because they allow the macros to co-exist with + * these (unused but exported) functions. + */ + +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 (PNGAPI +png_get_uint_32)(png_const_bytep buf) +{ + png_uint_32 uval = + ((png_uint_32)(*(buf )) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + ((png_uint_32)(*(buf + 3)) ) ; + + return uval; +} + +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format and there + * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore + * the following code does a two's complement to native conversion. + */ +png_int_32 (PNGAPI +png_get_int_32)(png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + if ((uval & 0x80000000) == 0) /* non-negative */ + return uval; + + uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */ + return -(png_int_32)uval; +} + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 (PNGAPI +png_get_uint_16)(png_const_bytep buf) +{ + /* ANSI-C requires an int value to accomodate at least 16 bits so this + * works and allows the compiler not to worry about possible narrowing + * on 32 bit systems. (Pre-ANSI systems did not make integers smaller + * than 16 bits either.) + */ + unsigned int val = + ((unsigned int)(*buf) << 8) + + ((unsigned int)(*(buf + 1))); + + return (png_uint_16)val; +} + +#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */ + +/* Read and check the PNG file signature */ +void /* PRIVATE */ +png_read_sig(png_structrp png_ptr, png_inforp info_ptr) +{ + png_size_t num_checked, num_to_check; + + /* Exit if the user application does not expect a signature. */ + if (png_ptr->sig_bytes >= 8) + return; + + num_checked = png_ptr->sig_bytes; + num_to_check = 8 - num_checked; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; +#endif + + /* The signature must be serialized in a single I/O call. */ + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Read the chunk header (length + type name). + * Put the type name into png_ptr->chunk_name, and return the length. + */ +png_uint_32 /* PRIVATE */ +png_read_chunk_header(png_structrp png_ptr) +{ + png_byte buf[8]; + png_uint_32 length; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; +#endif + + /* Read the length and the chunk name. + * This must be performed in a single I/O call. + */ + png_read_data(png_ptr, buf, 8); + length = png_get_uint_31(png_ptr, buf); + + /* Put the chunk name into png_ptr->chunk_name. */ + png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4); + + png_debug2(0, "Reading %lx chunk, length = %lu", + (unsigned long)png_ptr->chunk_name, (unsigned long)length); + + /* Reset the crc and run it over the chunk name. */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, buf + 4, 4); + + /* Check to see if chunk name is valid. */ + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; +#endif + + return length; +} + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length) +{ + if (png_ptr == NULL) + return; + + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + * are reading an ancillary or critical chunk, and how the program has set + * things up, we may calculate the CRC on the data and print a message. + * Returns '1' if there was a CRC error, '0' otherwise. + */ +int /* PRIVATE */ +png_crc_finish(png_structrp png_ptr, png_uint_32 skip) +{ + /* The size of the local buffer for inflate is a good guess as to a + * reasonable size to use for buffering reads from the application. + */ + while (skip > 0) + { + png_uint_32 len; + png_byte tmpbuf[PNG_INFLATE_BUF_SIZE]; + + len = (sizeof tmpbuf); + if (len > skip) + len = skip; + skip -= len; + + png_crc_read(png_ptr, tmpbuf, len); + } + + if (png_crc_error(png_ptr)) + { + if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) ? + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) : + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + + else + { + png_chunk_benign_error(png_ptr, "CRC error"); + return (0); + } + + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + * the data it has read thus far. + */ +int /* PRIVATE */ +png_crc_error(png_structrp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)) + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; +#endif + + /* The chunk CRC must be serialized in a single I/O call. */ + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + + else + return (0); +} + +/* Manage the read buffer; this simply reallocates the buffer if it is not small + * enough (or if it is not allocated). The routine returns a pointer to the + * buffer; if an error occurs and 'warn' is set the routine returns NULL, else + * it will call png_error (via png_malloc) on failure. (warn == 2 means + * 'silent'). + */ +static png_bytep +png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) +{ + png_bytep buffer = png_ptr->read_buffer; + + if (buffer != NULL && new_size > png_ptr->read_buffer_size) + { + png_ptr->read_buffer = NULL; + png_ptr->read_buffer = NULL; + png_ptr->read_buffer_size = 0; + png_free(png_ptr, buffer); + buffer = NULL; + } + + if (buffer == NULL) + { + buffer = png_voidcast(png_bytep, png_malloc_base(png_ptr, new_size)); + + if (buffer != NULL) + { + png_ptr->read_buffer = buffer; + png_ptr->read_buffer_size = new_size; + } + + else if (warn < 2) /* else silent */ + { +#ifdef PNG_WARNINGS_SUPPORTED + if (warn) + png_chunk_warning(png_ptr, "insufficient memory to read chunk"); + else +#endif + { +#ifdef PNG_ERROR_TEXT_SUPPORTED + png_chunk_error(png_ptr, "insufficient memory to read chunk"); +#endif + } + } + } + + return buffer; +} + +/* png_inflate_claim: claim the zstream for some nefarious purpose that involves + * decompression. Returns Z_OK on success, else a zlib error code. It checks + * the owner but, in final release builds, just issues a warning if some other + * chunk apparently owns the stream. Prior to release it does a png_error. + */ +static int +png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) +{ + if (png_ptr->zowner != 0) + { + char msg[64]; + + PNG_STRING_FROM_CHUNK(msg, png_ptr->zowner); + /* So the message that results is " using zstream"; this is an + * internal error, but is very useful for debugging. i18n requirements + * are minimal. + */ + (void)png_safecat(msg, (sizeof msg), 4, " using zstream"); +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC + png_chunk_warning(png_ptr, msg); + png_ptr->zowner = 0; +# else + png_chunk_error(png_ptr, msg); +# endif + } + + /* Implementation note: unlike 'png_deflate_claim' this internal function + * does not take the size of the data as an argument. Some efficiency could + * be gained by using this when it is known *if* the zlib stream itself does + * not record the number; however, this is an illusion: the original writer + * of the PNG may have selected a lower window size, and we really must + * follow that because, for systems with with limited capabilities, we + * would otherwise reject the application's attempts to use a smaller window + * size (zlib doesn't have an interface to say "this or lower"!). + * + * inflateReset2 was added to zlib 1.2.4; before this the window could not be + * reset, therefore it is necessary to always allocate the maximum window + * size with earlier zlibs just in case later compressed chunks need it. + */ + { + int ret; /* zlib return code */ +# if PNG_ZLIB_VERNUM >= 0x1240 + +# if defined(PNG_SET_OPTION_SUPPORTED) && \ + defined(PNG_MAXIMUM_INFLATE_WINDOW) + int window_bits; + + if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) == + PNG_OPTION_ON) + window_bits = 15; + + else + window_bits = 0; +# else +# define window_bits 0 +# endif +# endif + + /* Set this for safety, just in case the previous owner left pointers to + * memory allocations. + */ + png_ptr->zstream.next_in = NULL; + png_ptr->zstream.avail_in = 0; + png_ptr->zstream.next_out = NULL; + png_ptr->zstream.avail_out = 0; + + if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) + { +# if PNG_ZLIB_VERNUM < 0x1240 + ret = inflateReset(&png_ptr->zstream); +# else + ret = inflateReset2(&png_ptr->zstream, window_bits); +# endif + } + + else + { +# if PNG_ZLIB_VERNUM < 0x1240 + ret = inflateInit(&png_ptr->zstream); +# else + ret = inflateInit2(&png_ptr->zstream, window_bits); +# endif + + if (ret == Z_OK) + png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; + } + + if (ret == Z_OK) + png_ptr->zowner = owner; + + else + png_zstream_error(png_ptr, ret); + + return ret; + } + +# ifdef window_bits +# undef window_bits +# endif +} + +#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED +/* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to + * allow the caller to do multiple calls if required. If the 'finish' flag is + * set Z_FINISH will be passed to the final inflate() call and Z_STREAM_END must + * be returned or there has been a problem, otherwise Z_SYNC_FLUSH is used and + * Z_OK or Z_STREAM_END will be returned on success. + * + * The input and output sizes are updated to the actual amounts of data consumed + * or written, not the amount available (as in a z_stream). The data pointers + * are not changed, so the next input is (data+input_size) and the next + * available output is (output+output_size). + */ +static int +png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, + /* INPUT: */ png_const_bytep input, png_uint_32p input_size_ptr, + /* OUTPUT: */ png_bytep output, png_alloc_size_t *output_size_ptr) +{ + if (png_ptr->zowner == owner) /* Else not claimed */ + { + int ret; + png_alloc_size_t avail_out = *output_size_ptr; + png_uint_32 avail_in = *input_size_ptr; + + /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it + * can't even necessarily handle 65536 bytes) because the type uInt is + * "16 bits or more". Consequently it is necessary to chunk the input to + * zlib. This code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the + * maximum value that can be stored in a uInt.) It is possible to set + * ZLIB_IO_MAX to a lower value in pngpriv.h and this may sometimes have + * a performance advantage, because it reduces the amount of data accessed + * at each step and that may give the OS more time to page it in. + */ + png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); + /* avail_in and avail_out are set below from 'size' */ + png_ptr->zstream.avail_in = 0; + png_ptr->zstream.avail_out = 0; + + /* Read directly into the output if it is available (this is set to + * a local buffer below if output is NULL). + */ + if (output != NULL) + png_ptr->zstream.next_out = output; + + do + { + uInt avail; + Byte local_buffer[PNG_INFLATE_BUF_SIZE]; + + /* zlib INPUT BUFFER */ + /* The setting of 'avail_in' used to be outside the loop; by setting it + * inside it is possible to chunk the input to zlib and simply rely on + * zlib to advance the 'next_in' pointer. This allows arbitrary + * amounts of data to be passed through zlib at the unavoidable cost of + * requiring a window save (memcpy of up to 32768 output bytes) + * every ZLIB_IO_MAX input bytes. + */ + avail_in += png_ptr->zstream.avail_in; /* not consumed last time */ + + avail = ZLIB_IO_MAX; + + if (avail_in < avail) + avail = (uInt)avail_in; /* safe: < than ZLIB_IO_MAX */ + + avail_in -= avail; + png_ptr->zstream.avail_in = avail; + + /* zlib OUTPUT BUFFER */ + avail_out += png_ptr->zstream.avail_out; /* not written last time */ + + avail = ZLIB_IO_MAX; /* maximum zlib can process */ + + if (output == NULL) + { + /* Reset the output buffer each time round if output is NULL and + * make available the full buffer, up to 'remaining_space' + */ + png_ptr->zstream.next_out = local_buffer; + if ((sizeof local_buffer) < avail) + avail = (sizeof local_buffer); + } + + if (avail_out < avail) + avail = (uInt)avail_out; /* safe: < ZLIB_IO_MAX */ + + png_ptr->zstream.avail_out = avail; + avail_out -= avail; + + /* zlib inflate call */ + /* In fact 'avail_out' may be 0 at this point, that happens at the end + * of the read when the final LZ end code was not passed at the end of + * the previous chunk of input data. Tell zlib if we have reached the + * end of the output buffer. + */ + ret = inflate(&png_ptr->zstream, avail_out > 0 ? Z_NO_FLUSH : + (finish ? Z_FINISH : Z_SYNC_FLUSH)); + } while (ret == Z_OK); + + /* For safety kill the local buffer pointer now */ + if (output == NULL) + png_ptr->zstream.next_out = NULL; + + /* Claw back the 'size' and 'remaining_space' byte counts. */ + avail_in += png_ptr->zstream.avail_in; + avail_out += png_ptr->zstream.avail_out; + + /* Update the input and output sizes; the updated values are the amount + * consumed or written, effectively the inverse of what zlib uses. + */ + if (avail_out > 0) + *output_size_ptr -= avail_out; + + if (avail_in > 0) + *input_size_ptr -= avail_in; + + /* Ensure png_ptr->zstream.msg is set (even in the success case!) */ + png_zstream_error(png_ptr, ret); + return ret; + } + + else + { + /* This is a bad internal error. The recovery assigns to the zstream msg + * pointer, which is not owned by the caller, but this is safe; it's only + * used on errors! + */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed"); + return Z_STREAM_ERROR; + } +} + +/* + * Decompress trailing data in a chunk. The assumption is that read_buffer + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +static int +png_decompress_chunk(png_structrp png_ptr, + png_uint_32 chunklength, png_uint_32 prefix_size, + png_alloc_size_t *newlength /* must be initialized to the maximum! */, + int terminate /*add a '\0' to the end of the uncompressed data*/) +{ + /* TODO: implement different limits for different types of chunk. + * + * The caller supplies *newlength set to the maximum length of the + * uncompressed data, but this routine allocates space for the prefix and + * maybe a '\0' terminator too. We have to assume that 'prefix_size' is + * limited only by the maximum chunk size. + */ + png_alloc_size_t limit = PNG_SIZE_MAX; + +# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < limit) + limit = png_ptr->user_chunk_malloc_max; +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + if (PNG_USER_CHUNK_MALLOC_MAX < limit) + limit = PNG_USER_CHUNK_MALLOC_MAX; +# endif + + if (limit >= prefix_size + (terminate != 0)) + { + int ret; + + limit -= prefix_size + (terminate != 0); + + if (limit < *newlength) + *newlength = limit; + + /* Now try to claim the stream. */ + ret = png_inflate_claim(png_ptr, png_ptr->chunk_name); + + if (ret == Z_OK) + { + png_uint_32 lzsize = chunklength - prefix_size; + + ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, + /* input: */ png_ptr->read_buffer + prefix_size, &lzsize, + /* output: */ NULL, newlength); + + if (ret == Z_STREAM_END) + { + /* Use 'inflateReset' here, not 'inflateReset2' because this + * preserves the previously decided window size (otherwise it would + * be necessary to store the previous window size.) In practice + * this doesn't matter anyway, because png_inflate will call inflate + * with Z_FINISH in almost all cases, so the window will not be + * maintained. + */ + if (inflateReset(&png_ptr->zstream) == Z_OK) + { + /* Because of the limit checks above we know that the new, + * expanded, size will fit in a size_t (let alone an + * png_alloc_size_t). Use png_malloc_base here to avoid an + * extra OOM message. + */ + png_alloc_size_t new_size = *newlength; + png_alloc_size_t buffer_size = prefix_size + new_size + + (terminate != 0); + png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr, + buffer_size)); + + if (text != NULL) + { + ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, + png_ptr->read_buffer + prefix_size, &lzsize, + text + prefix_size, newlength); + + if (ret == Z_STREAM_END) + { + if (new_size == *newlength) + { + if (terminate) + text[prefix_size + *newlength] = 0; + + if (prefix_size > 0) + memcpy(text, png_ptr->read_buffer, prefix_size); + + { + png_bytep old_ptr = png_ptr->read_buffer; + + png_ptr->read_buffer = text; + png_ptr->read_buffer_size = buffer_size; + text = old_ptr; /* freed below */ + } + } + + else + { + /* The size changed on the second read, there can be no + * guarantee that anything is correct at this point. + * The 'msg' pointer has been set to "unexpected end of + * LZ stream", which is fine, but return an error code + * that the caller won't accept. + */ + ret = PNG_UNEXPECTED_ZLIB_RETURN; + } + } + + else if (ret == Z_OK) + ret = PNG_UNEXPECTED_ZLIB_RETURN; /* for safety */ + + /* Free the text pointer (this is the old read_buffer on + * success) + */ + png_free(png_ptr, text); + + /* This really is very benign, but it's still an error because + * the extra space may otherwise be used as a Trojan Horse. + */ + if (ret == Z_STREAM_END && + chunklength - prefix_size != lzsize) + png_chunk_benign_error(png_ptr, "extra compressed data"); + } + + else + { + /* Out of memory allocating the buffer */ + ret = Z_MEM_ERROR; + png_zstream_error(png_ptr, Z_MEM_ERROR); + } + } + + else + { + /* inflateReset failed, store the error message */ + png_zstream_error(png_ptr, ret); + + if (ret == Z_STREAM_END) + ret = PNG_UNEXPECTED_ZLIB_RETURN; + } + } + + else if (ret == Z_OK) + ret = PNG_UNEXPECTED_ZLIB_RETURN; + + /* Release the claimed stream */ + png_ptr->zowner = 0; + } + + else /* the claim failed */ if (ret == Z_STREAM_END) /* impossible! */ + ret = PNG_UNEXPECTED_ZLIB_RETURN; + + return ret; + } + + else + { + /* Application/configuration limits exceeded */ + png_zstream_error(png_ptr, Z_MEM_ERROR); + return Z_MEM_ERROR; + } +} +#endif /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */ + +#ifdef PNG_READ_iCCP_SUPPORTED +/* Perform a partial read and decompress, producing 'avail_out' bytes and + * reading from the current chunk as required. + */ +static int +png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, + png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size, + int finish) +{ + if (png_ptr->zowner == png_ptr->chunk_name) + { + int ret; + + /* next_in and avail_in must have been initialized by the caller. */ + png_ptr->zstream.next_out = next_out; + png_ptr->zstream.avail_out = 0; /* set in the loop */ + + do + { + if (png_ptr->zstream.avail_in == 0) + { + if (read_size > *chunk_bytes) + read_size = (uInt)*chunk_bytes; + *chunk_bytes -= read_size; + + if (read_size > 0) + png_crc_read(png_ptr, read_buffer, read_size); + + png_ptr->zstream.next_in = read_buffer; + png_ptr->zstream.avail_in = read_size; + } + + if (png_ptr->zstream.avail_out == 0) + { + uInt avail = ZLIB_IO_MAX; + if (avail > *out_size) + avail = (uInt)*out_size; + *out_size -= avail; + + png_ptr->zstream.avail_out = avail; + } + + /* Use Z_SYNC_FLUSH when there is no more chunk data to ensure that all + * the available output is produced; this allows reading of truncated + * streams. + */ + ret = inflate(&png_ptr->zstream, + *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); + } + while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0)); + + *out_size += png_ptr->zstream.avail_out; + png_ptr->zstream.avail_out = 0; /* Should not be required, but is safe */ + + /* Ensure the error message pointer is always set: */ + png_zstream_error(png_ptr, ret); + return ret; + } + + else + { + png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed"); + return Z_STREAM_ERROR; + } +} +#endif + +/* Read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_chunk_error(png_ptr, "out of place"); + + /* Check the length */ + if (length != 13) + png_chunk_error(png_ptr, "invalid"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, buf); + height = png_get_uint_31(png_ptr, buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + + /* Set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + + /* Find number of channels */ + switch (png_ptr->color_type) + { + default: /* invalid, png_set_IHDR calls png_error */ + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* Set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); + png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); + png_debug1(3, "channels = %d", png_ptr->channels); + png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* Read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifdef PNG_POINTER_INDEXING_SUPPORTED + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + /* Moved to before the 'after IDAT' check below because otherwise duplicate + * PLTE chunks are potentially ignored (the spec says there shall not be more + * than one PLTE, the error is not treated as benign, so this check trumps + * the requirement that PLTE appears before IDAT.) + */ + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_chunk_error(png_ptr, "duplicate"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + /* This is benign because the non-benign error happened before, when an + * IDAT was encountered in a color-mapped image with no PLTE. + */ + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "ignored in grayscale PNG"); + return; + } + +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + png_crc_finish(png_ptr, length); + + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + png_chunk_benign_error(png_ptr, "invalid"); + + else + png_chunk_error(png_ptr, "invalid"); + + return; + } + + /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */ + num = (int)length / 3; + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* Don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually need the PLTE chunk (ie for a paletted image), we do + * whatever the normal CRC configuration tells us. However, if we + * have an RGB image, the PLTE can be considered ancillary, so + * we will act as though it is. + */ +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } + +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + * we have two options: an error abort, or a warning and we + * ignore the data in this chunk (which should be OK, since + * it's considered ancillary for a RGB or RGBA image). + * + * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the + * chunk type to determine whether to check the ancillary or the critical + * flags. + */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_benign_error(png_ptr, "CRC error"); + } + + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its + * own copy of the palette. This has the side effect that when png_start_row + * is called (this happens after any call to png_read_update_info) the + * info_ptr palette gets changed. This is extremely unexpected and + * confusing. + * + * Fix this by not sharing the palette in this way. + */ + png_set_PLTE(png_ptr, info_ptr, palette, num); + + /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before + * IDAT. Prior to 1.6.0 this was not checked; instead the code merely + * checked the apparent validity of a tRNS chunk inserted before PLTE on a + * palette PNG. 1.6.0 attempts to rigorously follow the standard and + * therefore does a benign error if the erroneous condition is detected *and* + * cancels the tRNS if the benign error returns. The alternative is to + * amend the standard since it would be rather hypocritical of the standards + * maintainers to ignore it. + */ +#ifdef PNG_READ_tRNS_SUPPORTED + if (png_ptr->num_trans > 0 || + (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0)) + { + /* Cancel this because otherwise it would be used if the transforms + * require it. Don't cancel the 'valid' flag because this would prevent + * detection of duplicate chunks. + */ + png_ptr->num_trans = 0; + + if (info_ptr != NULL) + info_ptr->num_trans = 0; + + png_chunk_benign_error(png_ptr, "tRNS must be after"); + } +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0) + png_chunk_benign_error(png_ptr, "hIST must be after"); +#endif + +#ifdef PNG_READ_bKGD_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0) + png_chunk_benign_error(png_ptr, "bKGD must be after"); +#endif +} + +void /* PRIVATE */ +png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + png_chunk_error(png_ptr, "out of place"); + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + png_crc_finish(png_ptr, length); + + if (length != 0) + png_chunk_benign_error(png_ptr, "invalid"); + + PNG_UNUSED(info_ptr) +} + +#ifdef PNG_READ_gAMA_SUPPORTED +void /* PRIVATE */ +png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + if (length != 4) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 4); + + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = png_get_fixed_point(NULL, buf); + + png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma); + png_colorspace_sync(png_ptr, info_ptr); +} +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +void /* PRIVATE */ +png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + unsigned int truelen; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT"); + + buf[0] = buf[1] = buf[2] = buf[3] = 0; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 3; + + else + truelen = png_ptr->channels; + + if (length != truelen || length > 4) + { + png_chunk_benign_error(png_ptr, "invalid"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + + if (png_crc_finish(png_ptr, 0)) + return; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +void /* PRIVATE */ +png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[32]; + png_xy xy; + + png_debug(1, "in png_handle_cHRM"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + if (length != 32) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 32); + + if (png_crc_finish(png_ptr, 0)) + return; + + xy.whitex = png_get_fixed_point(NULL, buf); + xy.whitey = png_get_fixed_point(NULL, buf + 4); + xy.redx = png_get_fixed_point(NULL, buf + 8); + xy.redy = png_get_fixed_point(NULL, buf + 12); + xy.greenx = png_get_fixed_point(NULL, buf + 16); + xy.greeny = png_get_fixed_point(NULL, buf + 20); + xy.bluex = png_get_fixed_point(NULL, buf + 24); + xy.bluey = png_get_fixed_point(NULL, buf + 28); + + if (xy.whitex == PNG_FIXED_ERROR || + xy.whitey == PNG_FIXED_ERROR || + xy.redx == PNG_FIXED_ERROR || + xy.redy == PNG_FIXED_ERROR || + xy.greenx == PNG_FIXED_ERROR || + xy.greeny == PNG_FIXED_ERROR || + xy.bluex == PNG_FIXED_ERROR || + xy.bluey == PNG_FIXED_ERROR) + { + png_chunk_benign_error(png_ptr, "invalid values"); + return; + } + + /* If a colorspace error has already been output skip this chunk */ + if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) + return; + + if (png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) + { + png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; + png_colorspace_sync(png_ptr, info_ptr); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; + (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy, + 1/*prefer cHRM values*/); + png_colorspace_sync(png_ptr, info_ptr); +} +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED +void /* PRIVATE */ +png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte intent; + + png_debug(1, "in png_handle_sRGB"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + if (length != 1) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, &intent, 1); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* If a colorspace error has already been output skip this chunk */ + if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) + return; + + /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect + * this. + */ + if (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) + { + png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; + png_colorspace_sync(png_ptr, info_ptr); + png_chunk_benign_error(png_ptr, "too many profiles"); + return; + } + + (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent); + png_colorspace_sync(png_ptr, info_ptr); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_READ_iCCP_SUPPORTED +void /* PRIVATE */ +png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +/* Note: this does not properly handle profiles that are > 64K under DOS */ +{ + png_const_charp errmsg = NULL; /* error message output, or no error */ + int finished = 0; /* crc checked */ + + png_debug(1, "in png_handle_iCCP"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + /* Consistent with all the above colorspace handling an obviously *invalid* + * chunk is just ignored, so does not invalidate the color space. An + * alternative is to set the 'invalid' flags at the start of this routine + * and only clear them in they were not set before and all the tests pass. + * The minimum 'deflate' stream is assumed to be just the 2 byte header and 4 + * byte checksum. The keyword must be one character and there is a + * terminator (0) byte and the compression method. + */ + if (length < 9) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too short"); + return; + } + + /* If a colorspace error has already been output skip this chunk */ + if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) + { + png_crc_finish(png_ptr, length); + return; + } + + /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect + * this. + */ + if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0) + { + uInt read_length, keyword_length; + char keyword[81]; + + /* Find the keyword; the keyword plus separator and compression method + * bytes can be at most 81 characters long. + */ + read_length = 81; /* maximum */ + if (read_length > length) + read_length = (uInt)length; + + png_crc_read(png_ptr, (png_bytep)keyword, read_length); + length -= read_length; + + keyword_length = 0; + while (keyword_length < 80 && keyword_length < read_length && + keyword[keyword_length] != 0) + ++keyword_length; + + /* TODO: make the keyword checking common */ + if (keyword_length >= 1 && keyword_length <= 79) + { + /* We only understand '0' compression - deflate - so if we get a + * different value we can't safely decode the chunk. + */ + if (keyword_length+1 < read_length && + keyword[keyword_length+1] == PNG_COMPRESSION_TYPE_BASE) + { + read_length -= keyword_length+2; + + if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK) + { + Byte profile_header[132]; + Byte local_buffer[PNG_INFLATE_BUF_SIZE]; + png_alloc_size_t size = (sizeof profile_header); + + png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2); + png_ptr->zstream.avail_in = read_length; + (void)png_inflate_read(png_ptr, local_buffer, + (sizeof local_buffer), &length, profile_header, &size, + 0/*finish: don't, because the output is too small*/); + + if (size == 0) + { + /* We have the ICC profile header; do the basic header checks. + */ + const png_uint_32 profile_length = + png_get_uint_32(profile_header); + + if (png_icc_check_length(png_ptr, &png_ptr->colorspace, + keyword, profile_length)) + { + /* The length is apparently ok, so we can check the 132 + * byte header. + */ + if (png_icc_check_header(png_ptr, &png_ptr->colorspace, + keyword, profile_length, profile_header, + png_ptr->color_type)) + { + /* Now read the tag table; a variable size buffer is + * needed at this point, allocate one for the whole + * profile. The header check has already validated + * that none of these stuff will overflow. + */ + const png_uint_32 tag_count = png_get_uint_32( + profile_header+128); + png_bytep profile = png_read_buffer(png_ptr, + profile_length, 2/*silent*/); + + if (profile != NULL) + { + memcpy(profile, profile_header, + (sizeof profile_header)); + + size = 12 * tag_count; + + (void)png_inflate_read(png_ptr, local_buffer, + (sizeof local_buffer), &length, + profile + (sizeof profile_header), &size, 0); + + /* Still expect a a buffer error because we expect + * there to be some tag data! + */ + if (size == 0) + { + if (png_icc_check_tag_table(png_ptr, + &png_ptr->colorspace, keyword, profile_length, + profile)) + { + /* The profile has been validated for basic + * security issues, so read the whole thing in. + */ + size = profile_length - (sizeof profile_header) + - 12 * tag_count; + + (void)png_inflate_read(png_ptr, local_buffer, + (sizeof local_buffer), &length, + profile + (sizeof profile_header) + + 12 * tag_count, &size, 1/*finish*/); + + if (length > 0 && !(png_ptr->flags & + PNG_FLAG_BENIGN_ERRORS_WARN)) + errmsg = "extra compressed data"; + + /* But otherwise allow extra data: */ + else if (size == 0) + { + if (length > 0) + { + /* This can be handled completely, so + * keep going. + */ + png_chunk_warning(png_ptr, + "extra compressed data"); + } + + png_crc_finish(png_ptr, length); + finished = 1; + +# ifdef PNG_sRGB_SUPPORTED + /* Check for a match against sRGB */ + png_icc_set_sRGB(png_ptr, + &png_ptr->colorspace, profile, + png_ptr->zstream.adler); +# endif + + /* Steal the profile for info_ptr. */ + if (info_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, + PNG_FREE_ICCP, 0); + + info_ptr->iccp_name = png_voidcast(char*, + png_malloc_base(png_ptr, + keyword_length+1)); + if (info_ptr->iccp_name != NULL) + { + memcpy(info_ptr->iccp_name, keyword, + keyword_length+1); + info_ptr->iccp_proflen = + profile_length; + info_ptr->iccp_profile = profile; + png_ptr->read_buffer = NULL; /*steal*/ + info_ptr->free_me |= PNG_FREE_ICCP; + info_ptr->valid |= PNG_INFO_iCCP; + } + + else + { + png_ptr->colorspace.flags |= + PNG_COLORSPACE_INVALID; + errmsg = "out of memory"; + } + } + + /* else the profile remains in the read + * buffer which gets reused for subsequent + * chunks. + */ + + if (info_ptr != NULL) + png_colorspace_sync(png_ptr, info_ptr); + + if (errmsg == NULL) + { + png_ptr->zowner = 0; + return; + } + } + + else if (size > 0) + errmsg = "truncated"; + + else + errmsg = png_ptr->zstream.msg; + } + + /* else png_icc_check_tag_table output an error */ + } + + else /* profile truncated */ + errmsg = png_ptr->zstream.msg; + } + + else + errmsg = "out of memory"; + } + + /* else png_icc_check_header output an error */ + } + + /* else png_icc_check_length output an error */ + } + + else /* profile truncated */ + errmsg = png_ptr->zstream.msg; + + /* Release the stream */ + png_ptr->zowner = 0; + } + + else /* png_inflate_claim failed */ + errmsg = png_ptr->zstream.msg; + } + + else + errmsg = "bad compression method"; /* or missing */ + } + + else + errmsg = "bad keyword"; + } + + else + errmsg = "too many profiles"; + + /* Failure: the reason is in 'errmsg' */ + if (!finished) + png_crc_finish(png_ptr, length); + + png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; + png_colorspace_sync(png_ptr, info_ptr); + if (errmsg != NULL) /* else already output */ + png_chunk_benign_error(png_ptr, errmsg); +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_sPLT_SUPPORTED +void /* PRIVATE */ +png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep entry_start, buffer; + png_sPLT_t new_palette; + png_sPLT_entryp pp; + png_uint_32 data_length; + int entry_size, i; + png_uint_32 skip = 0; + png_uint_32 dl; + png_size_t max_dl; + + png_debug(1, "in png_handle_sPLT"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for sPLT"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > 65535U) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too large to fit in memory"); + return; + } +#endif + + buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); + if (buffer == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + + /* WARNING: this may break if size_t is less than 32 bits; it is assumed + * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a + * potential breakage point if the types in pngconf.h aren't exactly right. + */ + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, skip)) + return; + + buffer[length] = 0; + + for (entry_start = buffer; *entry_start; entry_start++) + /* Empty loop to find end of name */ ; + + ++entry_start; + + /* A sample depth should follow the separator, and we should be on it */ + if (entry_start > buffer + length - 2) + { + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + /* This must fit in a png_uint_32 because it is derived from the original + * chunk data length. + */ + data_length = length - (png_uint_32)(entry_start - buffer); + + /* Integrity-check the data length */ + if (data_length % entry_size) + { + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + dl = (png_int_32)(data_length / entry_size); + max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry)); + + if (dl > max_dl) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + + new_palette.nentries = (png_int_32)(data_length / entry_size); + + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( + png_ptr, new_palette.nentries * (sizeof (png_sPLT_entry))); + + if (new_palette.entries == NULL) + { + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; + } + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0; i < new_palette.nentries; i++) + { + pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + + pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* Discard all chunk data except the name and stash that */ + new_palette.name = (png_charp)buffer; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_tRNS_SUPPORTED +void /* PRIVATE */ +png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_tRNS"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[2]; + + if (length != 2) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_color.gray = png_get_uint_16(buf); + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, length); + png_ptr->num_trans = 1; + png_ptr->trans_color.red = png_get_uint_16(buf); + png_ptr->trans_color.green = png_get_uint_16(buf + 2); + png_ptr->trans_color.blue = png_get_uint_16(buf + 4); + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* TODO: is this actually an error in the ISO spec? */ + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + if (length > png_ptr->num_palette || length > PNG_MAX_PALETTE_LENGTH || + length == 0) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, readbuf, length); + png_ptr->num_trans = (png_uint_16)length; + } + + else + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid with alpha channel"); + return; + } + + if (png_crc_finish(png_ptr, 0)) + { + png_ptr->num_trans = 0; + return; + } + + /* TODO: this is a horrible side effect in the palette case because the + * png_struct ends up with a pointer to the tRNS buffer owned by the + * png_info. Fix this. + */ + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_color)); +} +#endif + +#ifdef PNG_READ_bKGD_SUPPORTED +void /* PRIVATE */ +png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + unsigned int truelen; + png_byte buf[6]; + png_color_16 background; + + png_debug(1, "in png_handle_bKGD"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if ((png_ptr->mode & PNG_HAVE_IDAT) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE))) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + + else + truelen = 2; + + if (length != truelen) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, truelen); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + background.index = buf[0]; + + if (info_ptr && info_ptr->num_palette) + { + if (buf[0] >= info_ptr->num_palette) + { + png_chunk_benign_error(png_ptr, "invalid index"); + return; + } + + background.red = (png_uint_16)png_ptr->palette[buf[0]].red; + background.green = (png_uint_16)png_ptr->palette[buf[0]].green; + background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue; + } + + else + background.red = background.green = background.blue = 0; + + background.gray = 0; + } + + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + background.index = 0; + background.red = + background.green = + background.blue = + background.gray = png_get_uint_16(buf); + } + + else + { + background.index = 0; + background.red = png_get_uint_16(buf); + background.green = png_get_uint_16(buf + 2); + background.blue = png_get_uint_16(buf + 4); + background.gray = 0; + } + + png_set_bKGD(png_ptr, info_ptr, &background); +} +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +void /* PRIVATE */ +png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if ((png_ptr->mode & PNG_HAVE_IDAT) || !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + num = length / 2 ; + + if (num != png_ptr->num_palette || num > PNG_MAX_PALETTE_LENGTH) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +void /* PRIVATE */ +png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (length != 9) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 9); + + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +void /* PRIVATE */ +png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (length != 9) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 9); + + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +/* Read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_int_32 X0, X1; + png_byte type, nparams; + png_bytep buffer, buf, units, endptr; + png_charpp params; + int i; + + png_debug(1, "in png_handle_pCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)", + length + 1); + + buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); + + if (buffer == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, 0)) + return; + + buffer[length] = 0; /* Null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string"); + for (buf = buffer; *buf; buf++) + /* Empty loop */ ; + + endptr = buffer + length; + + /* We need to have at least 12 bytes after the purpose string + * in order to get the parameter information. + */ + if (endptr <= buf + 12) + { + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters"); + /* Check that we have the right number of parameters for known + * equation types. + */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_chunk_benign_error(png_ptr, "invalid parameter count"); + return; + } + + else if (type >= PNG_EQUATION_LAST) + { + png_chunk_benign_error(png_ptr, "unrecognized equation type"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array"); + + params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, + nparams * (sizeof (png_charp)))); + + if (params == NULL) + { + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d", i); + + for (params[i] = (png_charp)buf; buf <= endptr && *buf != 0; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_free(png_ptr, params); + png_chunk_benign_error(png_ptr, "invalid data"); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams, + (png_charp)units, params); + + png_free(png_ptr, params); +} +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +/* Read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_bytep buffer; + png_size_t i; + int state; + + png_debug(1, "in png_handle_sCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + /* Need unit type, width, \0, height: minimum 4 bytes */ + else if (length < 4) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", + length + 1); + + buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); + + if (buffer == NULL) + { + png_chunk_benign_error(png_ptr, "out of memory"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buffer, length); + buffer[length] = 0; /* Null terminate the last string */ + + if (png_crc_finish(png_ptr, 0)) + return; + + /* Validate the unit. */ + if (buffer[0] != 1 && buffer[0] != 2) + { + png_chunk_benign_error(png_ptr, "invalid unit"); + return; + } + + /* Validate the ASCII numbers, need two ASCII numbers separated by + * a '\0' and they need to fit exactly in the chunk data. + */ + i = 1; + state = 0; + + if (!png_check_fp_number((png_const_charp)buffer, length, &state, &i) || + i >= length || buffer[i++] != 0) + png_chunk_benign_error(png_ptr, "bad width format"); + + else if (!PNG_FP_IS_POSITIVE(state)) + png_chunk_benign_error(png_ptr, "non-positive width"); + + else + { + png_size_t heighti = i; + + state = 0; + if (!png_check_fp_number((png_const_charp)buffer, length, &state, &i) || + i != length) + png_chunk_benign_error(png_ptr, "bad height format"); + + else if (!PNG_FP_IS_POSITIVE(state)) + png_chunk_benign_error(png_ptr, "non-positive height"); + + else + /* This is the (only) success case. */ + png_set_sCAL_s(png_ptr, info_ptr, buffer[0], + (png_charp)buffer+1, (png_charp)buffer+heighti); + } +} +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +void /* PRIVATE */ +png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 7); + + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_text text_info; + png_bytep buffer; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_tEXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "no space in chunk cache"); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > 65535U) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too large to fit in memory"); + return; + } +#endif + + buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/); + + if (buffer == NULL) + { + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, skip)) + return; + + key = (png_charp)buffer; + key[length] = 0; + + for (text = key; *text; text++) + /* Empty loop to find end of key */ ; + + if (text != key + length) + text++; + + text_info.compression = PNG_TEXT_COMPRESSION_NONE; + text_info.key = key; + text_info.lang = NULL; + text_info.lang_key = NULL; + text_info.itxt_length = 0; + text_info.text = text; + text_info.text_length = strlen(text); + + if (png_set_text_2(png_ptr, info_ptr, &text_info, 1)) + png_warning(png_ptr, "Insufficient memory to process text chunk"); +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_const_charp errmsg = NULL; + png_bytep buffer; + png_uint_32 keyword_length; + + png_debug(1, "in png_handle_zTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "no space in chunk cache"); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + buffer = png_read_buffer(png_ptr, length, 2/*silent*/); + + if (buffer == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* TODO: also check that the keyword contents match the spec! */ + for (keyword_length = 0; + keyword_length < length && buffer[keyword_length] != 0; + ++keyword_length) + /* Empty loop to find end of name */ ; + + if (keyword_length > 79 || keyword_length < 1) + errmsg = "bad keyword"; + + /* zTXt must have some LZ data after the keyword, although it may expand to + * zero bytes; we need a '\0' at the end of the keyword, the compression type + * then the LZ data: + */ + else if (keyword_length + 3 > length) + errmsg = "truncated"; + + else if (buffer[keyword_length+1] != PNG_COMPRESSION_TYPE_BASE) + errmsg = "unknown compression type"; + + else + { + png_alloc_size_t uncompressed_length = PNG_SIZE_MAX; + + /* TODO: at present png_decompress_chunk imposes a single application + * level memory limit, this should be split to different values for iCCP + * and text chunks. + */ + if (png_decompress_chunk(png_ptr, length, keyword_length+2, + &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) + { + png_text text; + + /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except + * for the extra compression type byte and the fact that it isn't + * necessarily '\0' terminated. + */ + buffer = png_ptr->read_buffer; + buffer[uncompressed_length+(keyword_length+2)] = 0; + + text.compression = PNG_TEXT_COMPRESSION_zTXt; + text.key = (png_charp)buffer; + text.text = (png_charp)(buffer + keyword_length+2); + text.text_length = uncompressed_length; + text.itxt_length = 0; + text.lang = NULL; + text.lang_key = NULL; + + if (png_set_text_2(png_ptr, info_ptr, &text, 1)) + errmsg = "insufficient memory"; + } + + else + errmsg = png_ptr->zstream.msg; + } + + if (errmsg != NULL) + png_chunk_benign_error(png_ptr, errmsg); +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_const_charp errmsg = NULL; + png_bytep buffer; + png_uint_32 prefix_length; + + png_debug(1, "in png_handle_iTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "no space in chunk cache"); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/); + + if (buffer == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* First the keyword. */ + for (prefix_length=0; + prefix_length < length && buffer[prefix_length] != 0; + ++prefix_length) + /* Empty loop */ ; + + /* Perform a basic check on the keyword length here. */ + if (prefix_length > 79 || prefix_length < 1) + errmsg = "bad keyword"; + + /* Expect keyword, compression flag, compression type, language, translated + * keyword (both may be empty but are 0 terminated) then the text, which may + * be empty. + */ + else if (prefix_length + 5 > length) + errmsg = "truncated"; + + else if (buffer[prefix_length+1] == 0 || + (buffer[prefix_length+1] == 1 && + buffer[prefix_length+2] == PNG_COMPRESSION_TYPE_BASE)) + { + int compressed = buffer[prefix_length+1] != 0; + png_uint_32 language_offset, translated_keyword_offset; + png_alloc_size_t uncompressed_length = 0; + + /* Now the language tag */ + prefix_length += 3; + language_offset = prefix_length; + + for (; prefix_length < length && buffer[prefix_length] != 0; + ++prefix_length) + /* Empty loop */ ; + + /* WARNING: the length may be invalid here, this is checked below. */ + translated_keyword_offset = ++prefix_length; + + for (; prefix_length < length && buffer[prefix_length] != 0; + ++prefix_length) + /* Empty loop */ ; + + /* prefix_length should now be at the trailing '\0' of the translated + * keyword, but it may already be over the end. None of this arithmetic + * can overflow because chunks are at most 2^31 bytes long, but on 16-bit + * systems the available allocaton may overflow. + */ + ++prefix_length; + + if (!compressed && prefix_length <= length) + uncompressed_length = length - prefix_length; + + else if (compressed && prefix_length < length) + { + uncompressed_length = PNG_SIZE_MAX; + + /* TODO: at present png_decompress_chunk imposes a single application + * level memory limit, this should be split to different values for + * iCCP and text chunks. + */ + if (png_decompress_chunk(png_ptr, length, prefix_length, + &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) + buffer = png_ptr->read_buffer; + + else + errmsg = png_ptr->zstream.msg; + } + + else + errmsg = "truncated"; + + if (errmsg == NULL) + { + png_text text; + + buffer[uncompressed_length+prefix_length] = 0; + + if (compressed) + text.compression = PNG_ITXT_COMPRESSION_NONE; + + else + text.compression = PNG_ITXT_COMPRESSION_zTXt; + + text.key = (png_charp)buffer; + text.lang = (png_charp)buffer + language_offset; + text.lang_key = (png_charp)buffer + translated_keyword_offset; + text.text = (png_charp)buffer + prefix_length; + text.text_length = 0; + text.itxt_length = uncompressed_length; + + if (png_set_text_2(png_ptr, info_ptr, &text, 1)) + errmsg = "insufficient memory"; + } + } + + else + errmsg = "bad compression info"; + + if (errmsg != NULL) + png_chunk_benign_error(png_ptr, errmsg); +} +#endif + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */ +static int +png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) +{ + png_alloc_size_t limit = PNG_SIZE_MAX; + + if (png_ptr->unknown_chunk.data != NULL) + { + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + +# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < limit) + limit = png_ptr->user_chunk_malloc_max; + +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + if (PNG_USER_CHUNK_MALLOC_MAX < limit) + limit = PNG_USER_CHUNK_MALLOC_MAX; +# endif + + if (length <= limit) + { + PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); + /* The following is safe because of the PNG_SIZE_MAX init above */ + png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/; + /* 'mode' is a flag array, only the bottom four bits matter here */ + png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + /* Do a 'warn' here - it is handled below. */ + png_ptr->unknown_chunk.data = png_voidcast(png_bytep, + png_malloc_warn(png_ptr, length)); + } + } + + if (png_ptr->unknown_chunk.data == NULL && length > 0) + { + /* This is benign because we clean up correctly */ + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "unknown chunk exceeds memory limits"); + return 0; + } + + else + { + if (length > 0) + png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length); + png_crc_finish(png_ptr, 0); + return 1; + } +} +#endif /* PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */ + +/* Handle an unknown, or known but disabled, chunk */ +void /* PRIVATE */ +png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, + png_uint_32 length, int keep) +{ + int handled = 0; /* the chunk was handled */ + + png_debug(1, "in png_handle_unknown"); + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + /* NOTE: this code is based on the code in libpng-1.4.12 except for fixing + * the bug which meant that setting a non-default behavior for a specific + * chunk would be ignored (the default was always used unless a user + * callback was installed). + * + * 'keep' is the value from the png_chunk_unknown_handling, the setting for + * this specific chunk_name, if PNG_HANDLE_AS_UNKNOWN_SUPPORTED, if not it + * will always be PNG_HANDLE_CHUNK_AS_DEFAULT and it needs to be set here. + * This is just an optimization to avoid multiple calls to the lookup + * function. + */ +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name); +# endif +# endif + + /* One of the following methods will read the chunk or skip it (at least one + * of these is always defined because this is the only way to switch on + * PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + */ +# ifdef PNG_READ_USER_CHUNKS_SUPPORTED + /* The user callback takes precedence over the chunk keep value, but the + * keep value is still required to validate a save of a critical chunk. + */ + if (png_ptr->read_user_chunk_fn != NULL) + { + if (png_cache_unknown_chunk(png_ptr, length)) + { + /* Callback to user unknown chunk handler */ + int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr, + &png_ptr->unknown_chunk); + + /* ret is: + * negative: An error occured, png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be discarded + * unless png_set_keep_unknown_chunks has been used to set + * a 'keep' behavior for this particular chunk, in which + * case that will be used. A critical chunk will cause an + * error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + */ + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + else if (ret == 0) + { + /* If the keep value is 'default' or 'never' override it, but + * still error out on critical chunks unless the keep value is + * 'always' While this is weird it is the behavior in 1.4.12. + * A possible improvement would be to obey the value set for the + * chunk, but this would be an API change that would probably + * damage some applications. + * + * The png_app_warning below catches the case that matters, where + * the application has not set specific save or ignore for this + * chunk or global save or ignore. + */ + if (keep < PNG_HANDLE_CHUNK_IF_SAFE) + { +# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE) + { + png_chunk_warning(png_ptr, "Saving unknown chunk:"); + png_app_warning(png_ptr, + "forcing save of an unhandled chunk;" + " please call png_set_keep_unknown_chunks"); + /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */ + } +# endif + keep = PNG_HANDLE_CHUNK_IF_SAFE; + } + } + + else /* chunk was handled */ + { + handled = 1; + /* Critical chunks can be safely discarded at this point. */ + keep = PNG_HANDLE_CHUNK_NEVER; + } + } + + else + keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */ + } + + else + /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */ +# endif /* PNG_READ_USER_CHUNKS_SUPPORTED */ + +# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED + { + /* keep is currently just the per-chunk setting, if there was no + * setting change it to the global default now (not that this may + * still be AS_DEFAULT) then obtain the cache of the chunk if required, + * if not simply skip the chunk. + */ + if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT) + keep = png_ptr->unknown_default; + + if (keep == PNG_HANDLE_CHUNK_ALWAYS || + (keep == PNG_HANDLE_CHUNK_IF_SAFE && + PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))) + { + if (!png_cache_unknown_chunk(png_ptr, length)) + keep = PNG_HANDLE_CHUNK_NEVER; + } + + else + png_crc_finish(png_ptr, length); + } +# else +# ifndef PNG_READ_USER_CHUNKS_SUPPORTED +# error no method to support READ_UNKNOWN_CHUNKS +# endif + + { + /* If here there is no read callback pointer set and no support is + * compiled in to just save the unknown chunks, so simply skip this + * chunk. If 'keep' is something other than AS_DEFAULT or NEVER then + * the app has erroneously asked for unknown chunk saving when there + * is no support. + */ + if (keep > PNG_HANDLE_CHUNK_NEVER) + png_app_error(png_ptr, "no unknown chunk support available"); + + png_crc_finish(png_ptr, length); + } +# endif + +# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED + /* Now store the chunk in the chunk list if appropriate, and if the limits + * permit it. + */ + if (keep == PNG_HANDLE_CHUNK_ALWAYS || + (keep == PNG_HANDLE_CHUNK_IF_SAFE && + PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))) + { +# ifdef PNG_USER_LIMITS_SUPPORTED + switch (png_ptr->user_chunk_cache_max) + { + case 2: + png_ptr->user_chunk_cache_max = 1; + png_chunk_benign_error(png_ptr, "no space in chunk cache"); + /* FALL THROUGH */ + case 1: + /* NOTE: prior to 1.6.0 this case resulted in an unknown critical + * chunk being skipped, now there will be a hard error below. + */ + break; + + default: /* not at limit */ + --(png_ptr->user_chunk_cache_max); + /* FALL THROUGH */ + case 0: /* no limit */ +# endif /* PNG_USER_LIMITS_SUPPORTED */ + /* Here when the limit isn't reached or when limits are compiled + * out; store the chunk. + */ + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + handled = 1; +# ifdef PNG_USER_LIMITS_SUPPORTED + break; + } +# endif + } +# else /* no store support: the chunk must be handled by the user callback */ + PNG_UNUSED(info_ptr) +# endif + + /* Regardless of the error handling below the cached data (if any) can be + * freed now. Notice that the data is not freed if there is a png_error, but + * it will be freed by destroy_read_struct. + */ + if (png_ptr->unknown_chunk.data != NULL) + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + +#else /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */ + /* There is no support to read an unknown chunk, so just skip it. */ + png_crc_finish(png_ptr, length); + PNG_UNUSED(info_ptr) + PNG_UNUSED(keep) +#endif /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */ + + /* Check for unhandled critical chunks */ + if (!handled && PNG_CHUNK_CRITICAL(png_ptr->chunk_name)) + png_chunk_error(png_ptr, "unhandled critical chunk"); +} + +/* This function is called to verify that a chunk name is valid. + * This function can't have the "critical chunk check" incorporated + * into it, since in the future we will need to be able to call user + * functions to handle unknown critical chunks after we check that + * the chunk name itself is valid. + */ + +/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is: + * + * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + */ + +void /* PRIVATE */ +png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name) +{ + int i; + + png_debug(1, "in png_check_chunk_name"); + + for (i=1; i<=4; ++i) + { + int c = chunk_name & 0xff; + + if (c < 65 || c > 122 || (c > 90 && c < 97)) + png_chunk_error(png_ptr, "invalid chunk type"); + + chunk_name >>= 8; + } +} + +/* Combines the row recently read in with the existing pixels in the row. This + * routine takes care of alpha and transparency if requested. This routine also + * handles the two methods of progressive display of interlaced images, + * depending on the 'display' value; if 'display' is true then the whole row + * (dp) is filled from the start by replicating the available pixels. If + * 'display' is false only those pixels present in the pass are filled in. + */ +void /* PRIVATE */ +png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) +{ + unsigned int pixel_depth = png_ptr->transformed_pixel_depth; + png_const_bytep sp = png_ptr->row_buf + 1; + png_uint_32 row_width = png_ptr->width; + unsigned int pass = png_ptr->pass; + png_bytep end_ptr = 0; + png_byte end_byte = 0; + unsigned int end_mask; + + png_debug(1, "in png_combine_row"); + + /* Added in 1.5.6: it should not be possible to enter this routine until at + * least one row has been read from the PNG data and transformed. + */ + if (pixel_depth == 0) + png_error(png_ptr, "internal row logic error"); + + /* Added in 1.5.4: the pixel depth should match the information returned by + * any call to png_read_update_info at this point. Do not continue if we got + * this wrong. + */ + if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes != + PNG_ROWBYTES(pixel_depth, row_width)) + png_error(png_ptr, "internal row size calculation error"); + + /* Don't expect this to ever happen: */ + if (row_width == 0) + png_error(png_ptr, "internal row width error"); + + /* Preserve the last byte in cases where only part of it will be overwritten, + * the multiply below may overflow, we don't care because ANSI-C guarantees + * we get the low bits. + */ + end_mask = (pixel_depth * row_width) & 7; + if (end_mask != 0) + { + /* end_ptr == NULL is a flag to say do nothing */ + end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1; + end_byte = *end_ptr; +# ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) /* little-endian byte */ + end_mask = 0xff << end_mask; + + else /* big-endian byte */ +# endif + end_mask = 0xff >> end_mask; + /* end_mask is now the bits to *keep* from the destination row */ + } + + /* For non-interlaced images this reduces to a memcpy(). A memcpy() + * will also happen if interlacing isn't supported or if the application + * does not call png_set_interlace_handling(). In the latter cases the + * caller just gets a sequence of the unexpanded rows from each interlace + * pass. + */ +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) && + pass < 6 && (display == 0 || + /* The following copies everything for 'display' on passes 0, 2 and 4. */ + (display == 1 && (pass & 1) != 0))) + { + /* Narrow images may have no bits in a pass; the caller should handle + * this, but this test is cheap: + */ + if (row_width <= PNG_PASS_START_COL(pass)) + return; + + if (pixel_depth < 8) + { + /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit + * into 32 bits, then a single loop over the bytes using the four byte + * values in the 32-bit mask can be used. For the 'display' option the + * expanded mask may also not require any masking within a byte. To + * make this work the PACKSWAP option must be taken into account - it + * simply requires the pixels to be reversed in each byte. + * + * The 'regular' case requires a mask for each of the first 6 passes, + * the 'display' case does a copy for the even passes in the range + * 0..6. This has already been handled in the test above. + * + * The masks are arranged as four bytes with the first byte to use in + * the lowest bits (little-endian) regardless of the order (PACKSWAP or + * not) of the pixels in each byte. + * + * NOTE: the whole of this logic depends on the caller of this function + * only calling it on rows appropriate to the pass. This function only + * understands the 'x' logic; the 'y' logic is handled by the caller. + * + * The following defines allow generation of compile time constant bit + * masks for each pixel depth and each possibility of swapped or not + * swapped bytes. Pass 'p' is in the range 0..6; 'x', a pixel index, + * is in the range 0..7; and the result is 1 if the pixel is to be + * copied in the pass, 0 if not. 'S' is for the sparkle method, 'B' + * for the block method. + * + * With some compilers a compile time expression of the general form: + * + * (shift >= 32) ? (a >> (shift-32)) : (b >> shift) + * + * Produces warnings with values of 'shift' in the range 33 to 63 + * because the right hand side of the ?: expression is evaluated by + * the compiler even though it isn't used. Microsoft Visual C (various + * versions) and the Intel C compiler are known to do this. To avoid + * this the following macros are used in 1.5.6. This is a temporary + * solution to avoid destabilizing the code during the release process. + */ +# if PNG_USE_COMPILE_TIME_MASKS +# define PNG_LSR(x,s) ((x)>>((s) & 0x1f)) +# define PNG_LSL(x,s) ((x)<<((s) & 0x1f)) +# else +# define PNG_LSR(x,s) ((x)>>(s)) +# define PNG_LSL(x,s) ((x)<<(s)) +# endif +# define S_COPY(p,x) (((p)<4 ? PNG_LSR(0x80088822,(3-(p))*8+(7-(x))) :\ + PNG_LSR(0xaa55ff00,(7-(p))*8+(7-(x)))) & 1) +# define B_COPY(p,x) (((p)<4 ? PNG_LSR(0xff0fff33,(3-(p))*8+(7-(x))) :\ + PNG_LSR(0xff55ff00,(7-(p))*8+(7-(x)))) & 1) + + /* Return a mask for pass 'p' pixel 'x' at depth 'd'. The mask is + * little endian - the first pixel is at bit 0 - however the extra + * parameter 's' can be set to cause the mask position to be swapped + * within each byte, to match the PNG format. This is done by XOR of + * the shift with 7, 6 or 4 for bit depths 1, 2 and 4. + */ +# define PIXEL_MASK(p,x,d,s) \ + (PNG_LSL(((PNG_LSL(1U,(d)))-1),(((x)*(d))^((s)?8-(d):0)))) + + /* Hence generate the appropriate 'block' or 'sparkle' pixel copy mask. + */ +# define S_MASKx(p,x,d,s) (S_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) +# define B_MASKx(p,x,d,s) (B_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) + + /* Combine 8 of these to get the full mask. For the 1-bpp and 2-bpp + * cases the result needs replicating, for the 4-bpp case the above + * generates a full 32 bits. + */ +# define MASK_EXPAND(m,d) ((m)*((d)==1?0x01010101:((d)==2?0x00010001:1))) + +# define S_MASK(p,d,s) MASK_EXPAND(S_MASKx(p,0,d,s) + S_MASKx(p,1,d,s) +\ + S_MASKx(p,2,d,s) + S_MASKx(p,3,d,s) + S_MASKx(p,4,d,s) +\ + S_MASKx(p,5,d,s) + S_MASKx(p,6,d,s) + S_MASKx(p,7,d,s), d) + +# define B_MASK(p,d,s) MASK_EXPAND(B_MASKx(p,0,d,s) + B_MASKx(p,1,d,s) +\ + B_MASKx(p,2,d,s) + B_MASKx(p,3,d,s) + B_MASKx(p,4,d,s) +\ + B_MASKx(p,5,d,s) + B_MASKx(p,6,d,s) + B_MASKx(p,7,d,s), d) + +#if PNG_USE_COMPILE_TIME_MASKS + /* Utility macros to construct all the masks for a depth/swap + * combination. The 's' parameter says whether the format is PNG + * (big endian bytes) or not. Only the three odd-numbered passes are + * required for the display/block algorithm. + */ +# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\ + S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) } + +# define B_MASKS(d,s) { B_MASK(1,d,s), S_MASK(3,d,s), S_MASK(5,d,s) } + +# define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2)) + + /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and + * then pass: + */ + static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = + { + /* Little-endian byte masks for PACKSWAP */ + { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) }, + /* Normal (big-endian byte) masks - PNG format */ + { S_MASKS(1,1), S_MASKS(2,1), S_MASKS(4,1) } + }; + + /* display_mask has only three entries for the odd passes, so index by + * pass>>1. + */ + static PNG_CONST png_uint_32 display_mask[2][3][3] = + { + /* Little-endian byte masks for PACKSWAP */ + { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) }, + /* Normal (big-endian byte) masks - PNG format */ + { B_MASKS(1,1), B_MASKS(2,1), B_MASKS(4,1) } + }; + +# define MASK(pass,depth,display,png)\ + ((display)?display_mask[png][DEPTH_INDEX(depth)][pass>>1]:\ + row_mask[png][DEPTH_INDEX(depth)][pass]) + +#else /* !PNG_USE_COMPILE_TIME_MASKS */ + /* This is the runtime alternative: it seems unlikely that this will + * ever be either smaller or faster than the compile time approach. + */ +# define MASK(pass,depth,display,png)\ + ((display)?B_MASK(pass,depth,png):S_MASK(pass,depth,png)) +#endif /* !PNG_USE_COMPILE_TIME_MASKS */ + + /* Use the appropriate mask to copy the required bits. In some cases + * the byte mask will be 0 or 0xff, optimize these cases. row_width is + * the number of pixels, but the code copies bytes, so it is necessary + * to special case the end. + */ + png_uint_32 pixels_per_byte = 8 / pixel_depth; + png_uint_32 mask; + +# ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + mask = MASK(pass, pixel_depth, display, 0); + + else +# endif + mask = MASK(pass, pixel_depth, display, 1); + + for (;;) + { + png_uint_32 m; + + /* It doesn't matter in the following if png_uint_32 has more than + * 32 bits because the high bits always match those in m<<24; it is, + * however, essential to use OR here, not +, because of this. + */ + m = mask; + mask = (m >> 8) | (m << 24); /* rotate right to good compilers */ + m &= 0xff; + + if (m != 0) /* something to copy */ + { + if (m != 0xff) + *dp = (png_byte)((*dp & ~m) | (*sp & m)); + else + *dp = *sp; + } + + /* NOTE: this may overwrite the last byte with garbage if the image + * is not an exact number of bytes wide; libpng has always done + * this. + */ + if (row_width <= pixels_per_byte) + break; /* May need to restore part of the last byte */ + + row_width -= pixels_per_byte; + ++dp; + ++sp; + } + } + + else /* pixel_depth >= 8 */ + { + unsigned int bytes_to_copy, bytes_to_jump; + + /* Validate the depth - it must be a multiple of 8 */ + if (pixel_depth & 7) + png_error(png_ptr, "invalid user transform pixel depth"); + + pixel_depth >>= 3; /* now in bytes */ + row_width *= pixel_depth; + + /* Regardless of pass number the Adam 7 interlace always results in a + * fixed number of pixels to copy then to skip. There may be a + * different number of pixels to skip at the start though. + */ + { + unsigned int offset = PNG_PASS_START_COL(pass) * pixel_depth; + + row_width -= offset; + dp += offset; + sp += offset; + } + + /* Work out the bytes to copy. */ + if (display) + { + /* When doing the 'block' algorithm the pixel in the pass gets + * replicated to adjacent pixels. This is why the even (0,2,4,6) + * passes are skipped above - the entire expanded row is copied. + */ + bytes_to_copy = (1<<((6-pass)>>1)) * pixel_depth; + + /* But don't allow this number to exceed the actual row width. */ + if (bytes_to_copy > row_width) + bytes_to_copy = row_width; + } + + else /* normal row; Adam7 only ever gives us one pixel to copy. */ + bytes_to_copy = pixel_depth; + + /* In Adam7 there is a constant offset between where the pixels go. */ + bytes_to_jump = PNG_PASS_COL_OFFSET(pass) * pixel_depth; + + /* And simply copy these bytes. Some optimization is possible here, + * depending on the value of 'bytes_to_copy'. Special case the low + * byte counts, which we know to be frequent. + * + * Notice that these cases all 'return' rather than 'break' - this + * avoids an unnecessary test on whether to restore the last byte + * below. + */ + switch (bytes_to_copy) + { + case 1: + for (;;) + { + *dp = *sp; + + if (row_width <= bytes_to_jump) + return; + + dp += bytes_to_jump; + sp += bytes_to_jump; + row_width -= bytes_to_jump; + } + + case 2: + /* There is a possibility of a partial copy at the end here; this + * slows the code down somewhat. + */ + do + { + dp[0] = sp[0], dp[1] = sp[1]; + + if (row_width <= bytes_to_jump) + return; + + sp += bytes_to_jump; + dp += bytes_to_jump; + row_width -= bytes_to_jump; + } + while (row_width > 1); + + /* And there can only be one byte left at this point: */ + *dp = *sp; + return; + + case 3: + /* This can only be the RGB case, so each copy is exactly one + * pixel and it is not necessary to check for a partial copy. + */ + for(;;) + { + dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2]; + + if (row_width <= bytes_to_jump) + return; + + sp += bytes_to_jump; + dp += bytes_to_jump; + row_width -= bytes_to_jump; + } + + default: +#if PNG_ALIGN_TYPE != PNG_ALIGN_NONE + /* Check for double byte alignment and, if possible, use a + * 16-bit copy. Don't attempt this for narrow images - ones that + * are less than an interlace panel wide. Don't attempt it for + * wide bytes_to_copy either - use the memcpy there. + */ + if (bytes_to_copy < 16 /*else use memcpy*/ && + png_isaligned(dp, png_uint_16) && + png_isaligned(sp, png_uint_16) && + bytes_to_copy % (sizeof (png_uint_16)) == 0 && + bytes_to_jump % (sizeof (png_uint_16)) == 0) + { + /* Everything is aligned for png_uint_16 copies, but try for + * png_uint_32 first. + */ + if (png_isaligned(dp, png_uint_32) && + png_isaligned(sp, png_uint_32) && + bytes_to_copy % (sizeof (png_uint_32)) == 0 && + bytes_to_jump % (sizeof (png_uint_32)) == 0) + { + png_uint_32p dp32 = png_aligncast(png_uint_32p,dp); + png_const_uint_32p sp32 = png_aligncastconst( + png_const_uint_32p, sp); + size_t skip = (bytes_to_jump-bytes_to_copy) / + (sizeof (png_uint_32)); + + do + { + size_t c = bytes_to_copy; + do + { + *dp32++ = *sp32++; + c -= (sizeof (png_uint_32)); + } + while (c > 0); + + if (row_width <= bytes_to_jump) + return; + + dp32 += skip; + sp32 += skip; + row_width -= bytes_to_jump; + } + while (bytes_to_copy <= row_width); + + /* Get to here when the row_width truncates the final copy. + * There will be 1-3 bytes left to copy, so don't try the + * 16-bit loop below. + */ + dp = (png_bytep)dp32; + sp = (png_const_bytep)sp32; + do + *dp++ = *sp++; + while (--row_width > 0); + return; + } + + /* Else do it in 16-bit quantities, but only if the size is + * not too large. + */ + else + { + png_uint_16p dp16 = png_aligncast(png_uint_16p, dp); + png_const_uint_16p sp16 = png_aligncastconst( + png_const_uint_16p, sp); + size_t skip = (bytes_to_jump-bytes_to_copy) / + (sizeof (png_uint_16)); + + do + { + size_t c = bytes_to_copy; + do + { + *dp16++ = *sp16++; + c -= (sizeof (png_uint_16)); + } + while (c > 0); + + if (row_width <= bytes_to_jump) + return; + + dp16 += skip; + sp16 += skip; + row_width -= bytes_to_jump; + } + while (bytes_to_copy <= row_width); + + /* End of row - 1 byte left, bytes_to_copy > row_width: */ + dp = (png_bytep)dp16; + sp = (png_const_bytep)sp16; + do + *dp++ = *sp++; + while (--row_width > 0); + return; + } + } +#endif /* PNG_ALIGN_ code */ + + /* The true default - use a memcpy: */ + for (;;) + { + memcpy(dp, sp, bytes_to_copy); + + if (row_width <= bytes_to_jump) + return; + + sp += bytes_to_jump; + dp += bytes_to_jump; + row_width -= bytes_to_jump; + if (bytes_to_copy > row_width) + bytes_to_copy = row_width; + } + } + + /* NOT REACHED*/ + } /* pixel_depth >= 8 */ + + /* Here if pixel_depth < 8 to check 'end_ptr' below. */ + } + else +#endif + + /* If here then the switch above wasn't used so just memcpy the whole row + * from the temporary row buffer (notice that this overwrites the end of the + * destination row if it is a partial byte.) + */ + memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width)); + + /* Restore the overwritten bits from the last byte if necessary. */ + if (end_ptr != NULL) + *end_ptr = (png_byte)((end_byte & end_mask) | (*end_ptr & ~end_mask)); +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +void /* PRIVATE */ +png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, + png_uint_32 transformations /* Because these may affect the byte layout */) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* Offset to next interlace block */ + static PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_read_interlace"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + unsigned int tmp = *dp & (0x7f7f >> (7 - dshift)); + tmp |= v << dshift; + *dp = (png_byte)(tmp & 0xff); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + unsigned int tmp = *dp & (0x3f3f >> (6 - dshift)); + tmp |= v << dshift; + *dp = (png_byte)(tmp & 0xff); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0x0f); + int j; + + for (j = 0; j < jstop; j++) + { + unsigned int tmp = *dp & (0xf0f >> (4 - dshift)); + tmp |= v << dshift; + *dp = (png_byte)(tmp & 0xff); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + + png_bytep sp = row + (png_size_t)(row_info->width - 1) + * pixel_bytes; + + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; /* SAFE; pixel_depth does not exceed 64 */ + int j; + + memcpy(v, sp, pixel_bytes); + + for (j = 0; j < jstop; j++) + { + memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + + sp -= pixel_bytes; + } + break; + } + } + + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); + } +#ifndef PNG_READ_PACKSWAP_SUPPORTED + PNG_UNUSED(transformations) /* Silence compiler warning */ +#endif +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +static void +png_read_filter_row_sub(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_size_t istop = row_info->rowbytes; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + + PNG_UNUSED(prev_row) + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); + rp++; + } +} + +static void +png_read_filter_row_up(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_size_t istop = row_info->rowbytes; + png_bytep rp = row; + png_const_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } +} + +static void +png_read_filter_row_avg(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_bytep rp = row; + png_const_bytep pp = prev_row; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_size_t istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); + + rp++; + } +} + +static void +png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp_end = row + row_info->rowbytes; + int a, c; + + /* First pixel/byte */ + c = *prev_row++; + a = *row + c; + *row++ = (png_byte)a; + + /* Remainder */ + while (row < rp_end) + { + int b, pa, pb, pc, p; + + a &= 0xff; /* From previous iteration or start */ + b = *prev_row++; + + p = b - c; + pc = a - c; + +# ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +# else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +# endif + + /* Find the best predictor, the least of pa, pb, pc favoring the earlier + * ones in the case of a tie. + */ + if (pb < pa) pa = pb, a = b; + if (pc < pa) a = c; + + /* Calculate the current pixel in a, and move the previous row pixel to c + * for the next time round the loop + */ + c = b; + a += *row; + *row++ = (png_byte)a; + } +} + +static void +png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp_end = row + bpp; + + /* Process the first pixel in the row completely (this is the same as 'up' + * because there is only one candidate predictor for the first row). + */ + while (row < rp_end) + { + int a = *row + *prev_row++; + *row++ = (png_byte)a; + } + + /* Remainder */ + rp_end += row_info->rowbytes - bpp; + + while (row < rp_end) + { + int a, b, c, pa, pb, pc, p; + + c = *(prev_row - bpp); + a = *(row - bpp); + b = *prev_row++; + + p = b - c; + pc = a - c; + +# ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +# else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +# endif + + if (pb < pa) pa = pb, a = b; + if (pc < pa) a = c; + + c = b; + a += *row; + *row++ = (png_byte)a; + } +} + +static void +png_init_filter_functions(png_structrp pp) + /* This function is called once for every PNG image (except for PNG images + * that only use PNG_FILTER_VALUE_NONE for all rows) to set the + * implementations required to reverse the filtering of PNG rows. Reversing + * the filter is the first transformation performed on the row data. It is + * performed in place, therefore an implementation can be selected based on + * the image pixel format. If the implementation depends on image width then + * take care to ensure that it works correctly if the image is interlaced - + * interlacing causes the actual row width to vary. + */ +{ + unsigned int bpp = (pp->pixel_depth + 7) >> 3; + + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub; + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg; + if (bpp == 1) + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth_1byte_pixel; + else + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth_multibyte_pixel; + +#ifdef PNG_FILTER_OPTIMIZATIONS + /* To use this define PNG_FILTER_OPTIMIZATIONS as the name of a function to + * call to install hardware optimizations for the above functions; simply + * replace whatever elements of the pp->read_filter[] array with a hardware + * specific (or, for that matter, generic) optimization. + * + * To see an example of this examine what configure.ac does when + * --enable-arm-neon is specified on the command line. + */ + PNG_FILTER_OPTIMIZATIONS(pp, bpp); +#endif +} + +void /* PRIVATE */ +png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row, + png_const_bytep prev_row, int filter) +{ + /* OPTIMIZATION: DO NOT MODIFY THIS FUNCTION, instead #define + * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic + * implementations. See png_init_filter_functions above. + */ + if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST) + { + if (pp->read_filter[0] == NULL) + png_init_filter_functions(pp); + + pp->read_filter[filter-1](row_info, row, prev_row); + } +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void /* PRIVATE */ +png_read_IDAT_data(png_structrp png_ptr, png_bytep output, + png_alloc_size_t avail_out) +{ + /* Loop reading IDATs and decompressing the result into output[avail_out] */ + png_ptr->zstream.next_out = output; + png_ptr->zstream.avail_out = 0; /* safety: set below */ + + if (output == NULL) + avail_out = 0; + + do + { + int ret; + png_byte tmpbuf[PNG_INFLATE_BUF_SIZE]; + + if (png_ptr->zstream.avail_in == 0) + { + uInt avail_in; + png_bytep buffer; + + while (png_ptr->idat_size == 0) + { + png_crc_finish(png_ptr, 0); + + png_ptr->idat_size = png_read_chunk_header(png_ptr); + /* This is an error even in the 'check' case because the code just + * consumed a non-IDAT header. + */ + if (png_ptr->chunk_name != png_IDAT) + png_error(png_ptr, "Not enough image data"); + } + + avail_in = png_ptr->IDAT_read_size; + + if (avail_in > png_ptr->idat_size) + avail_in = (uInt)png_ptr->idat_size; + + /* A PNG with a gradually increasing IDAT size will defeat this attempt + * to minimize memory usage by causing lots of re-allocs, but + * realistically doing IDAT_read_size re-allocs is not likely to be a + * big problem. + */ + buffer = png_read_buffer(png_ptr, avail_in, 0/*error*/); + + png_crc_read(png_ptr, buffer, avail_in); + png_ptr->idat_size -= avail_in; + + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = avail_in; + } + + /* And set up the output side. */ + if (output != NULL) /* standard read */ + { + uInt out = ZLIB_IO_MAX; + + if (out > avail_out) + out = (uInt)avail_out; + + avail_out -= out; + png_ptr->zstream.avail_out = out; + } + + else /* after last row, checking for end */ + { + png_ptr->zstream.next_out = tmpbuf; + png_ptr->zstream.avail_out = (sizeof tmpbuf); + } + + /* Use NO_FLUSH; this gives zlib the maximum opportunity to optimize the + * process. If the LZ stream is truncated the sequential reader will + * terminally damage the stream, above, by reading the chunk header of the + * following chunk (it then exits with png_error). + * + * TODO: deal more elegantly with truncated IDAT lists. + */ + ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); + + /* Take the unconsumed output back. */ + if (output != NULL) + avail_out += png_ptr->zstream.avail_out; + + else /* avail_out counts the extra bytes */ + avail_out += (sizeof tmpbuf) - png_ptr->zstream.avail_out; + + png_ptr->zstream.avail_out = 0; + + if (ret == Z_STREAM_END) + { + /* Do this for safety; we won't read any more into this row. */ + png_ptr->zstream.next_out = NULL; + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; + + if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0) + png_chunk_benign_error(png_ptr, "Extra compressed data"); + break; + } + + if (ret != Z_OK) + { + png_zstream_error(png_ptr, ret); + + if (output != NULL) + png_chunk_error(png_ptr, png_ptr->zstream.msg); + + else /* checking */ + { + png_chunk_benign_error(png_ptr, png_ptr->zstream.msg); + return; + } + } + } while (avail_out > 0); + + if (avail_out > 0) + { + /* The stream ended before the image; this is the same as too few IDATs so + * should be handled the same way. + */ + if (output != NULL) + png_error(png_ptr, "Not enough image data"); + + else /* the deflate stream contained extra data */ + png_chunk_benign_error(png_ptr, "Too much image data"); + } +} + +void /* PRIVATE */ +png_read_finish_IDAT(png_structrp png_ptr) +{ + /* We don't need any more data and the stream should have ended, however the + * LZ end code may actually not have been processed. In this case we must + * read it otherwise stray unread IDAT data or, more likely, an IDAT chunk + * may still remain to be consumed. + */ + if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + { + /* The NULL causes png_read_IDAT_data to swallow any remaining bytes in + * the compressed stream, but the stream may be damaged too, so even after + * this call we may need to terminate the zstream ownership. + */ + png_read_IDAT_data(png_ptr, NULL, 0); + png_ptr->zstream.next_out = NULL; /* safety */ + + /* Now clear everything out for safety; the following may not have been + * done. + */ + if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + { + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; + } + } + + /* If the zstream has not been released do it now *and* terminate the reading + * of the final IDAT chunk. + */ + if (png_ptr->zowner == png_IDAT) + { + /* Always do this; the pointers otherwise point into the read buffer. */ + png_ptr->zstream.next_in = NULL; + png_ptr->zstream.avail_in = 0; + + /* Now we no longer own the zstream. */ + png_ptr->zowner = 0; + + /* The slightly weird semantics of the sequential IDAT reading is that we + * are always in or at the end of an IDAT chunk, so we always need to do a + * crc_finish here. If idat_size is non-zero we also need to read the + * spurious bytes at the end of the chunk now. + */ + (void)png_crc_finish(png_ptr, png_ptr->idat_size); + } +} + +void /* PRIVATE */ +png_read_finish_row(png_structrp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + png_debug(1, "in png_read_finish_row"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + + /* TO DO: don't do this if prev_row isn't needed (requires + * read-ahead of the next row's filter byte. + */ + memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + do + { + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + } + + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; /* libpng deinterlacing sees every row */ + + } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + /* Here after at the end of the last row of the last pass. */ + png_read_finish_IDAT(png_ptr); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +void /* PRIVATE */ +png_read_start_row(png_structrp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int max_pixel_depth; + png_size_t row_bytes; + + png_debug(1, "in png_read_start_row"); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + png_init_read_transformations(png_ptr); +#endif +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + } + + else +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + } + + max_pixel_depth = png_ptr->pixel_depth; + + /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of + * calculations to calculate the final pixel depth, then + * png_do_read_transforms actually does the transforms. This means that the + * code which effectively calculates this value is actually repeated in three + * separate places. They must all match. Innocent changes to the order of + * transformations can and will break libpng in a way that causes memory + * overwrites. + * + * TODO: fix this. + */ +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + + else + max_pixel_depth = 24; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND_16) + { +# ifdef PNG_READ_EXPAND_SUPPORTED + /* In fact it is an error if it isn't supported, but checking is + * the safe way. + */ + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->bit_depth < 16) + max_pixel_depth *= 2; + } + else +# endif + png_ptr->transformations &= ~PNG_EXPAND_16; + } +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & (PNG_FILLER)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + + else + max_pixel_depth = 32; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB || + png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + + else + max_pixel_depth = 64; + } + } +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#ifdef PNG_READ_EXPAND_SUPPORTED + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#ifdef PNG_READ_FILLER_SUPPORTED + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + + else + max_pixel_depth = 64; + } + + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + + else + max_pixel_depth = 24; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth = png_ptr->user_transform_depth * + png_ptr->user_transform_channels; + + if (user_pixel_depth > max_pixel_depth) + max_pixel_depth = user_pixel_depth; + } +#endif + + /* This value is stored in png_struct and double checked in the row read + * code. + */ + png_ptr->maximum_pixel_depth = (png_byte)max_pixel_depth; + png_ptr->transformed_pixel_depth = 0; /* calculated on demand */ + + /* Align the width on the next larger 8 pixels. Mainly used + * for interlacing + */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* Calculate the maximum bytes needed, adding a byte and a pixel + * for safety's sake + */ + row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + + 1 + ((max_pixel_depth + 7) >> 3); + +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + + if (row_bytes + 48 > png_ptr->old_big_row_buf_size) + { + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->big_prev_row); + + if (png_ptr->interlaced) + png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + row_bytes + 48); + + else + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + + png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + +#ifdef PNG_ALIGNED_MEMORY_SUPPORTED + /* Use 16-byte aligned memory for row_buf with at least 16 bytes + * of padding before and after row_buf; treat prev_row similarly. + * NOTE: the alignment is to the start of the pixels, one beyond the start + * of the buffer, because of the filter byte. Prior to libpng 1.5.6 this + * was incorrect; the filter byte was aligned, which had the exact + * opposite effect of that intended. + */ + { + png_bytep temp = png_ptr->big_row_buf + 32; + int extra = (int)((temp - (png_bytep)0) & 0x0f); + png_ptr->row_buf = temp - extra - 1/*filter byte*/; + + temp = png_ptr->big_prev_row + 32; + extra = (int)((temp - (png_bytep)0) & 0x0f); + png_ptr->prev_row = temp - extra - 1/*filter byte*/; + } + +#else + /* Use 31 bytes of padding before and 17 bytes after row_buf. */ + png_ptr->row_buf = png_ptr->big_row_buf + 31; + png_ptr->prev_row = png_ptr->big_prev_row + 31; +#endif + png_ptr->old_big_row_buf_size = row_bytes + 48; + } + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->rowbytes > 65535) + png_error(png_ptr, "This image requires a row greater than 64KB"); + +#endif + if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1)) + png_error(png_ptr, "Row has too many bytes to allocate in memory"); + + memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + png_debug1(3, "width = %u,", png_ptr->width); + png_debug1(3, "height = %u,", png_ptr->height); + png_debug1(3, "iwidth = %u,", png_ptr->iwidth); + png_debug1(3, "num_rows = %u,", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu", + (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); + + /* The sequential reader needs a buffer for IDAT, but the progressive reader + * does not, so free the read buffer now regardless; the sequential reader + * reallocates it on demand. + */ + if (png_ptr->read_buffer) + { + png_bytep buffer = png_ptr->read_buffer; + + png_ptr->read_buffer_size = 0; + png_ptr->read_buffer = NULL; + png_free(png_ptr, buffer); + } + + /* Finally claim the zstream for the inflate of the IDAT data, use the bits + * value from the stream (note that this will result in a fatal error if the + * IDAT stream has a bogus deflate header window_bits value, but this should + * not be happening any longer!) + */ + if (png_inflate_claim(png_ptr, png_IDAT) != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/ext/libpng16/pngset.c b/ext/libpng16/pngset.c new file mode 100644 index 0000000000..1f60cdcbc0 --- /dev/null +++ b/ext/libpng16/pngset.c @@ -0,0 +1,1597 @@ + +/* pngset.c - storage of image information into info struct + * + * Last changed in libpng 1.6.3 [July 18, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#ifdef PNG_bKGD_SUPPORTED +void PNGAPI +png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_color_16p background) +{ + png_debug1(1, "in %s storage function", "bKGD"); + + if (png_ptr == NULL || info_ptr == NULL || background == NULL) + return; + + info_ptr->background = *background; + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +void PNGFAPI +png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_xy xy; + + png_debug1(1, "in %s storage function", "cHRM fixed"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + xy.redx = red_x; + xy.redy = red_y; + xy.greenx = green_x; + xy.greeny = green_y; + xy.bluex = blue_x; + xy.bluey = blue_y; + xy.whitex = white_x; + xy.whitey = white_y; + + if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy, + 2/* override with app values*/)) + info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; + + png_colorspace_sync_info(png_ptr, info_ptr); +} + +void PNGFAPI +png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr, + png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z) +{ + png_XYZ XYZ; + + png_debug1(1, "in %s storage function", "cHRM XYZ fixed"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + XYZ.red_X = int_red_X; + XYZ.red_Y = int_red_Y; + XYZ.red_Z = int_red_Z; + XYZ.green_X = int_green_X; + XYZ.green_Y = int_green_Y; + XYZ.green_Z = int_green_Z; + XYZ.blue_X = int_blue_X; + XYZ.blue_Y = int_blue_Y; + XYZ.blue_Z = int_blue_Z; + + if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace, &XYZ, 2)) + info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; + + png_colorspace_sync_info(png_ptr, info_ptr); +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, + double green_x, double green_y, double blue_x, double blue_y) +{ + png_set_cHRM_fixed(png_ptr, info_ptr, + png_fixed(png_ptr, white_x, "cHRM White X"), + png_fixed(png_ptr, white_y, "cHRM White Y"), + png_fixed(png_ptr, red_x, "cHRM Red X"), + png_fixed(png_ptr, red_y, "cHRM Red Y"), + png_fixed(png_ptr, green_x, "cHRM Green X"), + png_fixed(png_ptr, green_y, "cHRM Green Y"), + png_fixed(png_ptr, blue_x, "cHRM Blue X"), + png_fixed(png_ptr, blue_y, "cHRM Blue Y")); +} + +void PNGAPI +png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, + double red_Y, double red_Z, double green_X, double green_Y, double green_Z, + double blue_X, double blue_Y, double blue_Z) +{ + png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, + png_fixed(png_ptr, red_X, "cHRM Red X"), + png_fixed(png_ptr, red_Y, "cHRM Red Y"), + png_fixed(png_ptr, red_Z, "cHRM Red Z"), + png_fixed(png_ptr, green_X, "cHRM Red X"), + png_fixed(png_ptr, green_Y, "cHRM Red Y"), + png_fixed(png_ptr, green_Z, "cHRM Red Z"), + png_fixed(png_ptr, blue_X, "cHRM Red X"), + png_fixed(png_ptr, blue_Y, "cHRM Red Y"), + png_fixed(png_ptr, blue_Z, "cHRM Red Z")); +} +# endif /* PNG_FLOATING_POINT_SUPPORTED */ + +#endif /* PNG_cHRM_SUPPORTED */ + +#ifdef PNG_gAMA_SUPPORTED +void PNGFAPI +png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr, + png_fixed_point file_gamma) +{ + png_debug1(1, "in %s storage function", "gAMA"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma); + png_colorspace_sync_info(png_ptr, info_ptr); +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma) +{ + png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma, + "png_set_gAMA")); +} +# endif +#endif + +#ifdef PNG_hIST_SUPPORTED +void PNGAPI +png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function", "hIST"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->num_palette == 0 || info_ptr->num_palette + > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, + "Invalid palette size, hIST allocation skipped"); + + return; + } + + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); + + /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in + * version 1.2.1 + */ + info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr, + PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16)))); + + if (info_ptr->hist == NULL) + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data"); + return; + } + + info_ptr->free_me |= PNG_FREE_HIST; + + for (i = 0; i < info_ptr->num_palette; i++) + info_ptr->hist[i] = hist[i]; + + info_ptr->valid |= PNG_INFO_hIST; +} +#endif + +void PNGAPI +png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + png_debug1(1, "in %s storage function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type = (png_byte)color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + + else + info_ptr->channels = 1; + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); +} + +#ifdef PNG_oFFs_SUPPORTED +void PNGAPI +png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "oFFs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +void PNGAPI +png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, png_const_charp units, png_charpp params) +{ + png_size_t length; + int i; + + png_debug1(1, "in %s storage function", "pCAL"); + + if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL + || (nparams > 0 && params == NULL)) + return; + + length = strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)", + (unsigned long)length); + + /* TODO: validate format of calibration name and unit name */ + + /* Check that the type matches the specification. */ + if (type < 0 || type > 3) + png_error(png_ptr, "Invalid pCAL equation type"); + + if (nparams < 0 || nparams > 255) + png_error(png_ptr, "Invalid pCAL parameter count"); + + /* Validate params[nparams] */ + for (i=0; ipcal_purpose = png_voidcast(png_charp, + png_malloc_warn(png_ptr, length)); + + if (info_ptr->pcal_purpose == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose"); + return; + } + + memcpy(info_ptr->pcal_purpose, purpose, length); + + png_debug(3, "storing X0, X1, type, and nparams in info"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)", + (unsigned long)length); + + info_ptr->pcal_units = png_voidcast(png_charp, + png_malloc_warn(png_ptr, length)); + + if (info_ptr->pcal_units == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL units"); + return; + } + + memcpy(info_ptr->pcal_units, units, length); + + info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, + (png_size_t)((nparams + 1) * (sizeof (png_charp))))); + + if (info_ptr->pcal_params == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL params"); + return; + } + + memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp))); + + for (i = 0; i < nparams; i++) + { + length = strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, + (unsigned long)length); + + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter"); + return; + } + + memcpy(info_ptr->pcal_params[i], params[i], length); + } + + info_ptr->valid |= PNG_INFO_pCAL; + info_ptr->free_me |= PNG_FREE_PCAL; +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight) +{ + png_size_t lengthw = 0, lengthh = 0; + + png_debug1(1, "in %s storage function", "sCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Double check the unit (should never get here with an invalid + * unit unless this is an API call.) + */ + if (unit != 1 && unit != 2) + png_error(png_ptr, "Invalid sCAL unit"); + + if (swidth == NULL || (lengthw = strlen(swidth)) == 0 || + swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw)) + png_error(png_ptr, "Invalid sCAL width"); + + if (sheight == NULL || (lengthh = strlen(sheight)) == 0 || + sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh)) + png_error(png_ptr, "Invalid sCAL height"); + + info_ptr->scal_unit = (png_byte)unit; + + ++lengthw; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); + + info_ptr->scal_s_width = png_voidcast(png_charp, + png_malloc_warn(png_ptr, lengthw)); + + if (info_ptr->scal_s_width == NULL) + { + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; + } + + memcpy(info_ptr->scal_s_width, swidth, lengthw); + + ++lengthh; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); + + info_ptr->scal_s_height = png_voidcast(png_charp, + png_malloc_warn(png_ptr, lengthh)); + + if (info_ptr->scal_s_height == NULL) + { + png_free (png_ptr, info_ptr->scal_s_width); + info_ptr->scal_s_width = NULL; + + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; + } + + memcpy(info_ptr->scal_s_height, sheight, lengthh); + + info_ptr->valid |= PNG_INFO_sCAL; + info_ptr->free_me |= PNG_FREE_SCAL; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit, + double width, double height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width, + PNG_sCAL_PRECISION); + png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height, + PNG_sCAL_PRECISION); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit, + png_fixed_point width, png_fixed_point height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width); + png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif +#endif + +#ifdef PNG_pHYs_SUPPORTED +void PNGAPI +png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "pHYs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, + png_const_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function", "PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Invalid palette length"); + + else + { + png_warning(png_ptr, "Invalid palette length"); + return; + } + } + + if ((num_palette > 0 && palette == NULL) || + (num_palette == 0 +# ifdef PNG_MNG_FEATURES_SUPPORTED + && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 +# endif + )) + { + png_chunk_report(png_ptr, "Invalid palette", PNG_CHUNK_ERROR); + return; + } + + /* It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + * + * 1.6.0: the above statement appears to be incorrect; something has to set + * the palette inside png_struct on read. + */ + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); + + /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead + * of num_palette entries, in case of an invalid PNG file that has + * too-large sample values. + */ + png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); + + if (num_palette > 0) + memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color))); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + + info_ptr->free_me |= PNG_FREE_PLTE; + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#ifdef PNG_sBIT_SUPPORTED +void PNGAPI +png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function", "sBIT"); + + if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL) + return; + + info_ptr->sig_bit = *sig_bit; + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#ifdef PNG_sRGB_SUPPORTED +void PNGAPI +png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent); + png_colorspace_sync_info(png_ptr, info_ptr); +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, + int srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent)) + { + /* This causes the gAMA and cHRM to be written too */ + info_ptr->colorspace.flags |= + PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM; + } + + png_colorspace_sync_info(png_ptr, info_ptr); +} +#endif /* sRGB */ + + +#ifdef PNG_iCCP_SUPPORTED +void PNGAPI +png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_bytep new_iccp_profile; + png_size_t length; + + png_debug1(1, "in %s storage function", "iCCP"); + + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_app_error(png_ptr, "Invalid iCCP compression method"); + + /* Set the colorspace first because this validates the profile; do not + * override previously set app cHRM or gAMA here (because likely as not the + * application knows better than libpng what the correct values are.) Pass + * the info_ptr color_type field to png_colorspace_set_ICC because in the + * write case it has not yet been stored in png_ptr. + */ + { + int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name, + proflen, profile, info_ptr->color_type); + + png_colorspace_sync_info(png_ptr, info_ptr); + + /* Don't do any of the copying if the profile was bad, or inconsistent. */ + if (!result) + return; + + /* But do write the gAMA and cHRM chunks from the profile. */ + info_ptr->colorspace.flags |= + PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM; + } + + length = strlen(name)+1; + new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length)); + + if (new_iccp_name == NULL) + { + png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk"); + return; + } + + memcpy(new_iccp_name, name, length); + new_iccp_profile = png_voidcast(png_bytep, + png_malloc_warn(png_ptr, proflen)); + + if (new_iccp_profile == NULL) + { + png_free(png_ptr, new_iccp_name); + png_benign_error(png_ptr, + "Insufficient memory to process iCCP profile"); + return; + } + + memcpy(new_iccp_profile, profile, proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + info_ptr->free_me |= PNG_FREE_ICCP; + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +void PNGAPI +png_set_text(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_textp text_ptr, int num_text) +{ + int ret; + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + + if (ret) + png_error(png_ptr, "Insufficient memory to store text"); +} + +int /* PRIVATE */ +png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_textp text_ptr, int num_text) +{ + int i; + + png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" : + (unsigned long)png_ptr->chunk_name); + + if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL) + return(0); + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. This compare can't overflow + * because max_text >= num_text (anyway, subtract of two positive integers + * can't overflow in any case.) + */ + if (num_text > info_ptr->max_text - info_ptr->num_text) + { + int old_num_text = info_ptr->num_text; + int max_text; + png_textp new_text = NULL; + + /* Calculate an appropriate max_text, checking for overflow. */ + max_text = old_num_text; + if (num_text <= INT_MAX - max_text) + { + max_text += num_text; + + /* Round up to a multiple of 8 */ + if (max_text < INT_MAX-8) + max_text = (max_text + 8) & ~0x7; + + else + max_text = INT_MAX; + + /* Now allocate a new array and copy the old members in, this does all + * the overflow checks. + */ + new_text = png_voidcast(png_textp,png_realloc_array(png_ptr, + info_ptr->text, old_num_text, max_text-old_num_text, + sizeof *new_text)); + } + + if (new_text == NULL) + { + png_chunk_report(png_ptr, "too many text chunks", + PNG_CHUNK_WRITE_ERROR); + return 1; + } + + png_free(png_ptr, info_ptr->text); + + info_ptr->text = new_text; + info_ptr->free_me |= PNG_FREE_TEXT; + info_ptr->max_text = max_text; + /* num_text is adjusted below as the entries are copied in */ + + png_debug1(3, "allocated %d entries for info_ptr->text", max_text); + } + + for (i = 0; i < num_text; i++) + { + size_t text_length, key_len; + size_t lang_len, lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE || + text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) + { + png_chunk_report(png_ptr, "text compression mode is out of range", + PNG_CHUNK_WRITE_ERROR); + continue; + } + + key_len = strlen(text_ptr[i].key); + + if (text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + + else +# ifdef PNG_iTXt_SUPPORTED + { + /* Set iTXt data */ + + if (text_ptr[i].lang != NULL) + lang_len = strlen(text_ptr[i].lang); + + else + lang_len = 0; + + if (text_ptr[i].lang_key != NULL) + lang_key_len = strlen(text_ptr[i].lang_key); + + else + lang_key_len = 0; + } +# else /* PNG_iTXt_SUPPORTED */ + { + png_chunk_report(png_ptr, "iTXt chunk not supported", + PNG_CHUNK_WRITE_ERROR); + continue; + } +# endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +# ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + + else +# endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + + else + { + text_length = strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr, + key_len + text_length + lang_len + lang_key_len + 4)); + + if (textp->key == NULL) + { + png_chunk_report(png_ptr, "text chunk: out of memory", + PNG_CHUNK_WRITE_ERROR); + return 1; + } + + png_debug2(2, "Allocated %lu bytes at %p in png_set_text", + (unsigned long)(png_uint_32) + (key_len + lang_len + lang_key_len + text_length + 4), + textp->key); + + memcpy(textp->key, text_ptr[i].key, key_len); + *(textp->key + key_len) = '\0'; + + if (text_ptr[i].compression > 0) + { + textp->lang = textp->key + key_len + 1; + memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang + lang_len) = '\0'; + textp->lang_key = textp->lang + lang_len + 1; + memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key + lang_key_len) = '\0'; + textp->text = textp->lang_key + lang_key_len + 1; + } + + else + { + textp->lang=NULL; + textp->lang_key=NULL; + textp->text = textp->key + key_len + 1; + } + + if (text_length) + memcpy(textp->text, text_ptr[i].text, text_length); + + *(textp->text + text_length) = '\0'; + +# ifdef PNG_iTXt_SUPPORTED + if (textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + + else +# endif + { + textp->text_length = text_length; + textp->itxt_length = 0; + } + + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d", info_ptr->num_text); + } + + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +void PNGAPI +png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_timep mod_time) +{ + png_debug1(1, "in %s storage function", "tIME"); + + if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + if (mod_time->month == 0 || mod_time->month > 12 || + mod_time->day == 0 || mod_time->day > 31 || + mod_time->hour > 23 || mod_time->minute > 59 || + mod_time->second > 60) + { + png_warning(png_ptr, "Ignoring invalid time value"); + return; + } + + info_ptr->mod_time = *mod_time; + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +void PNGAPI +png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, + png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color) +{ + png_debug1(1, "in %s storage function", "tRNS"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans_alpha != NULL) + { + /* It may not actually be necessary to set png_ptr->trans_alpha here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + * + * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively + * relies on png_set_tRNS storing the information in png_struct + * (otherwise it won't be there for the code in pngrtran.c). + */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); + + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ + png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep, + png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); + + if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) + memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + } + + if (trans_color != NULL) + { + int sample_max = (1 << info_ptr->bit_depth); + + if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && + trans_color->gray > sample_max) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + (trans_color->red > sample_max || + trans_color->green > sample_max || + trans_color->blue > sample_max))) + png_warning(png_ptr, + "tRNS chunk has out-of-range samples for bit_depth"); + + info_ptr->trans_color = *trans_color; + + if (num_trans == 0) + num_trans = 1; + } + + info_ptr->num_trans = (png_uint_16)num_trans; + + if (num_trans != 0) + { + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->free_me |= PNG_FREE_TRNS; + } +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +void PNGAPI +png_set_sPLT(png_const_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries) +/* + * entries - array of png_sPLT_t structures + * to be added to the list of palettes + * in the info structure. + * + * nentries - number of palette structures to be + * added. + */ +{ + png_sPLT_tp np; + + if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL) + return; + + /* Use the internal realloc function, which checks for all the possible + * overflows. Notice that the parameters are (int) and (size_t) + */ + np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr, + info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries, + sizeof *np)); + + if (np == NULL) + { + /* Out of memory or too many chunks */ + png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR); + return; + } + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = np; + info_ptr->free_me |= PNG_FREE_SPLT; + + np += info_ptr->splt_palettes_num; + + do + { + png_size_t length; + + /* Skip invalid input entries */ + if (entries->name == NULL || entries->entries == NULL) + { + /* png_handle_sPLT doesn't do this, so this is an app error */ + png_app_error(png_ptr, "png_set_sPLT: invalid sPLT"); + /* Just skip the invalid entry */ + continue; + } + + np->depth = entries->depth; + + /* In the even of out-of-memory just return - there's no point keeping on + * trying to add sPLT chunks. + */ + length = strlen(entries->name) + 1; + np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length)); + + if (np->name == NULL) + break; + + memcpy(np->name, entries->name, length); + + /* IMPORTANT: we have memory now that won't get freed if something else + * goes wrong, this code must free it. png_malloc_array produces no + * warnings, use a png_chunk_report (below) if there is an error. + */ + np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr, + entries->nentries, sizeof (png_sPLT_entry))); + + if (np->entries == NULL) + { + png_free(png_ptr, np->name); + break; + } + + np->nentries = entries->nentries; + /* This multiply can't overflow because png_malloc_array has already + * checked it when doing the allocation. + */ + memcpy(np->entries, entries->entries, + entries->nentries * sizeof (png_sPLT_entry)); + + /* Note that 'continue' skips the advance of the out pointer and out + * count, so an invalid entry is not added. + */ + info_ptr->valid |= PNG_INFO_sPLT; + ++(info_ptr->splt_palettes_num); + ++np; + } + while (++entries, --nentries); + + if (nentries > 0) + png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR); +} +#endif /* PNG_sPLT_SUPPORTED */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +static png_byte +check_location(png_const_structrp png_ptr, int location) +{ + location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT); + + /* New in 1.6.0; copy the location and check it. This is an API + * change, previously the app had to use the + * png_set_unknown_chunk_location API below for each chunk. + */ + if (location == 0 && !(png_ptr->mode & PNG_IS_READ_STRUCT)) + { + /* Write struct, so unknown chunks come from the app */ + png_app_warning(png_ptr, + "png_set_unknown_chunks now expects a valid location"); + /* Use the old behavior */ + location = (png_byte)(png_ptr->mode & + (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)); + } + + /* This need not be an internal error - if the app calls + * png_set_unknown_chunks on a read pointer it must get the location right. + */ + if (location == 0) + png_error(png_ptr, "invalid location in png_set_unknown_chunks"); + + /* Now reduce the location to the top-most set bit by removing each least + * significant bit in turn. + */ + while (location != (location & -location)) + location &= ~(location & -location); + + /* The cast is safe because 'location' is a bit mask and only the low four + * bits are significant. + */ + return (png_byte)location; +} + +void PNGAPI +png_set_unknown_chunks(png_const_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 || + unknowns == NULL) + return; + + /* Check for the failure cases where support has been disabled at compile + * time. This code is hardly ever compiled - it's here because + * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this + * code) but may be meaningless if the read or write handling of unknown + * chunks is not compiled in. + */ +# if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \ + defined(PNG_READ_SUPPORTED) + if (png_ptr->mode & PNG_IS_READ_STRUCT) + { + png_app_error(png_ptr, "no unknown chunk support on read"); + return; + } +# endif +# if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \ + defined(PNG_WRITE_SUPPORTED) + if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) + { + png_app_error(png_ptr, "no unknown chunk support on write"); + return; + } +# endif + + /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that + * unknown critical chunks could be lost with just a warning resulting in + * undefined behavior. Now png_chunk_report is used to provide behavior + * appropriate to read or write. + */ + np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr, + info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns, + sizeof *np)); + + if (np == NULL) + { + png_chunk_report(png_ptr, "too many unknown chunks", + PNG_CHUNK_WRITE_ERROR); + return; + } + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = np; /* safe because it is initialized */ + info_ptr->free_me |= PNG_FREE_UNKN; + + np += info_ptr->unknown_chunks_num; + + /* Increment unknown_chunks_num each time round the loop to protect the + * just-allocated chunk data. + */ + for (; num_unknowns > 0; --num_unknowns, ++unknowns) + { + memcpy(np->name, unknowns->name, (sizeof np->name)); + np->name[(sizeof np->name)-1] = '\0'; + np->location = check_location(png_ptr, unknowns->location); + + if (unknowns->size == 0) + { + np->data = NULL; + np->size = 0; + } + + else + { + np->data = png_voidcast(png_bytep, + png_malloc_base(png_ptr, unknowns->size)); + + if (np->data == NULL) + { + png_chunk_report(png_ptr, "unknown chunk: out of memory", + PNG_CHUNK_WRITE_ERROR); + /* But just skip storing the unknown chunk */ + continue; + } + + memcpy(np->data, unknowns->data, unknowns->size); + np->size = unknowns->size; + } + + /* These increments are skipped on out-of-memory for the data - the + * unknown chunk entry gets overwritten if the png_chunk_report returns. + * This is correct in the read case (the chunk is just dropped.) + */ + ++np; + ++(info_ptr->unknown_chunks_num); + } +} + +void PNGAPI +png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr, + int chunk, int location) +{ + /* This API is pretty pointless in 1.6.0 because the location can be set + * before the call to png_set_unknown_chunks. + * + * TODO: add a png_app_warning in 1.7 + */ + if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && + chunk < info_ptr->unknown_chunks_num) + { + if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0) + { + png_app_error(png_ptr, "invalid unknown chunk location"); + /* Fake out the pre 1.6.0 behavior: */ + if ((location & PNG_HAVE_IDAT)) /* undocumented! */ + location = PNG_AFTER_IDAT; + + else + location = PNG_HAVE_IHDR; /* also undocumented */ + } + + info_ptr->unknown_chunks[chunk].location = + check_location(png_ptr, location); + } +} +#endif + + +#ifdef PNG_MNG_FEATURES_SUPPORTED +png_uint_32 PNGAPI +png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features"); + + if (png_ptr == NULL) + return 0; + + png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES; + + return png_ptr->mng_features_permitted; +} +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +static unsigned int +add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep) +{ + unsigned int i; + + /* Utility function: update the 'keep' state of a chunk if it is already in + * the list, otherwise add it to the list. + */ + for (i=0; i= PNG_HANDLE_CHUNK_LAST) + { + png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep"); + return; + } + + if (num_chunks_in <= 0) + { + png_ptr->unknown_default = keep; + + /* '0' means just set the flags, so stop here */ + if (num_chunks_in == 0) + return; + } + + if (num_chunks_in < 0) + { + /* Ignore all unknown chunks and all chunks recognized by + * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND + */ + static PNG_CONST png_byte chunks_to_ignore[] = { + 98, 75, 71, 68, '\0', /* bKGD */ + 99, 72, 82, 77, '\0', /* cHRM */ + 103, 65, 77, 65, '\0', /* gAMA */ + 104, 73, 83, 84, '\0', /* hIST */ + 105, 67, 67, 80, '\0', /* iCCP */ + 105, 84, 88, 116, '\0', /* iTXt */ + 111, 70, 70, 115, '\0', /* oFFs */ + 112, 67, 65, 76, '\0', /* pCAL */ + 112, 72, 89, 115, '\0', /* pHYs */ + 115, 66, 73, 84, '\0', /* sBIT */ + 115, 67, 65, 76, '\0', /* sCAL */ + 115, 80, 76, 84, '\0', /* sPLT */ + 115, 84, 69, 82, '\0', /* sTER */ + 115, 82, 71, 66, '\0', /* sRGB */ + 116, 69, 88, 116, '\0', /* tEXt */ + 116, 73, 77, 69, '\0', /* tIME */ + 122, 84, 88, 116, '\0' /* zTXt */ + }; + + chunk_list = chunks_to_ignore; + num_chunks = (sizeof chunks_to_ignore)/5; + } + + else /* num_chunks_in > 0 */ + { + if (chunk_list == NULL) + { + /* Prior to 1.6.0 this was silently ignored, now it is an app_error + * which can be switched off. + */ + png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list"); + return; + } + + num_chunks = num_chunks_in; + } + + old_num_chunks = png_ptr->num_chunk_list; + if (png_ptr->chunk_list == NULL) + old_num_chunks = 0; + + /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow. + */ + if (num_chunks + old_num_chunks > UINT_MAX/5) + { + png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks"); + return; + } + + /* If these chunks are being reset to the default then no more memory is + * required because add_one_chunk above doesn't extend the list if the 'keep' + * parameter is the default. + */ + if (keep) + { + new_list = png_voidcast(png_bytep, png_malloc(png_ptr, + 5 * (num_chunks + old_num_chunks))); + + if (old_num_chunks > 0) + memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks); + } + + else if (old_num_chunks > 0) + new_list = png_ptr->chunk_list; + + else + new_list = NULL; + + /* Add the new chunks together with each one's handling code. If the chunk + * already exists the code is updated, otherwise the chunk is added to the + * end. (In libpng 1.6.0 order no longer matters because this code enforces + * the earlier convention that the last setting is the one that is used.) + */ + if (new_list != NULL) + { + png_const_bytep inlist; + png_bytep outlist; + unsigned int i; + + for (i=0; ichunk_list != new_list) + png_free(png_ptr, new_list); + + new_list = NULL; + } + } + + else + num_chunks = 0; + + png_ptr->num_chunk_list = num_chunks; + + if (png_ptr->chunk_list != new_list) + { + if (png_ptr->chunk_list != NULL) + png_free(png_ptr, png_ptr->chunk_list); + + png_ptr->chunk_list = new_list; + } +} +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +void PNGAPI +png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr, + png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + + info_ptr->row_pointers = row_pointers; + + if (row_pointers) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +void PNGAPI +png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size) +{ + if (png_ptr == NULL) + return; + + if (size == 0 || size > PNG_UINT_31_MAX) + png_error(png_ptr, "invalid compression buffer size"); + +# ifdef PNG_SEQUENTIAL_READ_SUPPORTED + if (png_ptr->mode & PNG_IS_READ_STRUCT) + { + png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */ + return; + } +# endif + +# ifdef PNG_WRITE_SUPPORTED + if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) + { + if (png_ptr->zowner != 0) + { + png_warning(png_ptr, + "Compression buffer size cannot be changed because it is in use"); + return; + } + + if (size > ZLIB_IO_MAX) + { + png_warning(png_ptr, + "Compression buffer size limited to system maximum"); + size = ZLIB_IO_MAX; /* must fit */ + } + + else if (size < 6) + { + /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH + * if this is permitted. + */ + png_warning(png_ptr, + "Compression buffer size cannot be reduced below 6"); + return; + } + + if (png_ptr->zbuffer_size != size) + { + png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); + png_ptr->zbuffer_size = (uInt)size; + } + } +# endif +} + +void PNGAPI +png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~mask; +} + + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* This function was added to libpng 1.2.6 */ +void PNGAPI +png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, + png_uint_32 user_height_max) +{ + /* Images with dimensions larger than these limits will be + * rejected by png_set_IHDR(). To accept any PNG datastream + * regardless of dimensions, set both limits to 0x7ffffffL. + */ + if (png_ptr == NULL) + return; + + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; +} + +/* This function was added to libpng 1.4.0 */ +void PNGAPI +png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max) +{ + if (png_ptr) + png_ptr->user_chunk_cache_max = user_chunk_cache_max; +} + +/* This function was added to libpng 1.4.1 */ +void PNGAPI +png_set_chunk_malloc_max (png_structrp png_ptr, + png_alloc_size_t user_chunk_malloc_max) +{ + if (png_ptr) + png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_set_benign_errors(png_structrp png_ptr, int allowed) +{ + png_debug(1, "in png_set_benign_errors"); + + /* If allowed is 1, png_benign_error() is treated as a warning. + * + * If allowed is 0, png_benign_error() is treated as an error (which + * is the default behavior if png_set_benign_errors() is not called). + */ + + if (allowed) + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN | + PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN; + + else + png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN | + PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN); +} +#endif /* PNG_BENIGN_ERRORS_SUPPORTED */ + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED + /* Whether to report invalid palette index; added at libng-1.5.10. + * It is possible for an indexed (color-type==3) PNG file to contain + * pixels with invalid (out-of-range) indexes if the PLTE chunk has + * fewer entries than the image's bit-depth would allow. We recover + * from this gracefully by filling any incomplete palette with zeroes + * (opaque black). By default, when this occurs libpng will issue + * a benign error. This API can be used to override that behavior. + */ +void PNGAPI +png_set_check_for_invalid_index(png_structrp png_ptr, int allowed) +{ + png_debug(1, "in png_set_check_for_invalid_index"); + + if (allowed > 0) + png_ptr->num_palette_max = 0; + + else + png_ptr->num_palette_max = -1; +} +#endif +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngstruct.h b/ext/libpng16/pngstruct.h new file mode 100644 index 0000000000..b6935534c5 --- /dev/null +++ b/ext/libpng16/pngstruct.h @@ -0,0 +1,489 @@ + +/* pngstruct.h - header file for PNG reference library + * + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.6.1 [March 28, 2013] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application. + */ + +#ifndef PNGSTRUCT_H +#define PNGSTRUCT_H +/* zlib.h defines the structure z_stream, an instance of which is included + * in this structure and is required for decompressing the LZ compressed + * data in PNG files. + */ +#ifndef ZLIB_CONST + /* We must ensure that zlib uses 'const' in declarations. */ +# define ZLIB_CONST +#endif +#include "zlib.h" +#ifdef const + /* zlib.h sometimes #defines const to nothing, undo this. */ +# undef const +#endif + +/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility + * with older builds. + */ +#if ZLIB_VERNUM < 0x1260 +# define PNGZ_MSG_CAST(s) png_constcast(char*,s) +# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b) +#else +# define PNGZ_MSG_CAST(s) (s) +# define PNGZ_INPUT_CAST(b) (b) +#endif + +/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib + * can handle at once. This type need be no larger than 16 bits (so maximum of + * 65535), this define allows us to discover how big it is, but limited by the + * maximuum for png_size_t. The value can be overriden in a library build + * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably + * lower value (e.g. 255 works). A lower value may help memory usage (slightly) + * and may even improve performance on some systems (and degrade it on others.) + */ +#ifndef ZLIB_IO_MAX +# define ZLIB_IO_MAX ((uInt)-1) +#endif + +#ifdef PNG_WRITE_SUPPORTED +/* The type of a compression buffer list used by the write code. */ +typedef struct png_compression_buffer +{ + struct png_compression_buffer *next; + png_byte output[1]; /* actually zbuf_size */ +} png_compression_buffer, *png_compression_bufferp; + +#define PNG_COMPRESSION_BUFFER_SIZE(pp)\ + (offsetof(png_compression_buffer, output) + (pp)->zbuffer_size) +#endif + +/* Colorspace support; structures used in png_struct, png_info and in internal + * functions to hold and communicate information about the color space. + * + * PNG_COLORSPACE_SUPPORTED is only required if the application will perform + * colorspace corrections, otherwise all the colorspace information can be + * skipped and the size of libpng can be reduced (significantly) by compiling + * out the colorspace support. + */ +#ifdef PNG_COLORSPACE_SUPPORTED +/* The chromaticities of the red, green and blue colorants and the chromaticity + * of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)). + */ +typedef struct png_xy +{ + png_fixed_point redx, redy; + png_fixed_point greenx, greeny; + png_fixed_point bluex, bluey; + png_fixed_point whitex, whitey; +} png_xy; + +/* The same data as above but encoded as CIE XYZ values. When this data comes + * from chromaticities the sum of the Y values is assumed to be 1.0 + */ +typedef struct png_XYZ +{ + png_fixed_point red_X, red_Y, red_Z; + png_fixed_point green_X, green_Y, green_Z; + png_fixed_point blue_X, blue_Y, blue_Z; +} png_XYZ; +#endif /* COLORSPACE */ + +#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) +/* A colorspace is all the above plus, potentially, profile information, + * however at present libpng does not use the profile internally so it is only + * stored in the png_info struct (if iCCP is supported.) The rendering intent + * is retained here and is checked. + * + * The file gamma encoding information is also stored here and gamma correction + * is done by libpng, whereas color correction must currently be done by the + * application. + */ +typedef struct png_colorspace +{ +#ifdef PNG_GAMMA_SUPPORTED + png_fixed_point gamma; /* File gamma */ +#endif + +#ifdef PNG_COLORSPACE_SUPPORTED + png_xy end_points_xy; /* End points as chromaticities */ + png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */ + png_uint_16 rendering_intent; /* Rendering intent of a profile */ +#endif + + /* Flags are always defined to simplify the code. */ + png_uint_16 flags; /* As defined below */ +} png_colorspace, * PNG_RESTRICT png_colorspacerp; + +typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp; + +/* General flags for the 'flags' field */ +#define PNG_COLORSPACE_HAVE_GAMMA 0x0001 +#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002 +#define PNG_COLORSPACE_HAVE_INTENT 0x0004 +#define PNG_COLORSPACE_FROM_gAMA 0x0008 +#define PNG_COLORSPACE_FROM_cHRM 0x0010 +#define PNG_COLORSPACE_FROM_sRGB 0x0020 +#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040 +#define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */ +#define PNG_COLORSPACE_INVALID 0x8000 +#define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags)) +#endif /* COLORSPACE || GAMMA */ + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf jmp_buf_local; /* New name in 1.6.0 for jmp_buf in png_struct */ + png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */ + jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */ + size_t jmp_buf_size; /* size of the above, if allocated */ +#endif + png_error_ptr error_fn; /* function for printing errors and aborting */ +#ifdef PNG_WARNINGS_SUPPORTED + png_error_ptr warning_fn; /* function for printing warnings */ +#endif + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */ + z_stream zstream; /* decompression structure */ + +#ifdef PNG_WRITE_SUPPORTED + png_compression_bufferp zbuffer_list; /* Created on demand during write */ + uInt zbuffer_size; /* size of the actual buffer */ + + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ +#endif +/* Added at libpng 1.5.4 */ +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + int zlib_text_level; /* holds zlib compression level */ + int zlib_text_method; /* holds zlib compression method */ + int zlib_text_window_bits; /* holds zlib compression window bits */ + int zlib_text_mem_level; /* holds zlib compression memory level */ + int zlib_text_strategy; /* holds zlib compression strategy */ +#endif +/* End of material added at libpng 1.5.4 */ +/* Added at libpng 1.6.0 */ +#ifdef PNG_WRITE_SUPPORTED + int zlib_set_level; /* Actual values set into the zstream on write */ + int zlib_set_method; + int zlib_set_window_bits; + int zlib_set_mem_level; + int zlib_set_strategy; +#endif + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_size_t rowbytes; /* size of row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row. + * This is a pointer into big_prev_row + */ + png_bytep row_buf; /* buffer to save current (unfiltered) row. + * This is a pointer into big_row_buf + */ +#ifdef PNG_WRITE_SUPPORTED + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ +#endif + png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + +/* Added at libpng-1.5.10 */ +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED + int num_palette_max; /* maximum palette index found in IDAT */ +#endif + + png_uint_16 num_trans; /* number of transparency values */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row: write only */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ +#ifdef PNG_WRITE_SUPPORTED + png_byte usr_channels; /* channels at start of write: write only */ +#endif + png_byte sig_bytes; /* magic bytes read/written from start of file */ + png_byte maximum_pixel_depth; + /* pixel depth used for the row buffers */ + png_byte transformed_pixel_depth; + /* pixel depth after read/write transforms */ +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + png_byte background_gamma_type; + png_fixed_point background_gamma; + png_color_16 background; /* background color in screen gamma space */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn; /* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ + png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ + + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* shift for significant bit tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans_alpha; /* alpha values for paletted files */ + png_color_16 trans_color; /* transparent color for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* For the Borland special 64K segment handler */ + png_bytepp offset_table_ptr; + png_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_bytep palette_lookup; /* lookup table for quantizing */ + png_bytep quantize_index; /* index translation for palette files */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + + /* Options */ +#ifdef PNG_SET_OPTION_SUPPORTED + png_byte options; /* On/off state (up to 4 options) */ +#endif + +#if PNG_LIBPNG_VER < 10700 +/* To do: remove this from libpng-1.7 */ +#ifdef PNG_TIME_RFC1123_SUPPORTED + char time_buffer[29]; /* String to hold RFC 1123 time text */ +#endif +#endif + +/* New members added in libpng-1.0.6 */ + + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#ifdef PNG_USER_CHUNKS_SUPPORTED + png_voidp user_chunk_ptr; +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif +#endif + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + int unknown_default; /* As PNG_HANDLE_* */ + unsigned int num_chunk_list; /* Number of entries in the list */ + png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name + * followed by a PNG_HANDLE_* byte */ +#endif + +/* New members added in libpng-1.0.3 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status; + /* Added in libpng 1.5.5 to record setting of coefficients: */ + png_byte rgb_to_gray_coefficients_set; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + /* deleted in 1.5.5: rgb_to_gray_blue_coeff; */ +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) +/* Changed from png_byte to png_uint_32 at version 1.2.0 */ + png_uint_32 mng_features_permitted; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_byte filter_type; +#endif + +/* New members added in libpng-1.2.0 */ + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep quantize_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is + in the palette */ + png_bytep palette_to_index; /* which original index points to this + palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type; + +#ifdef PNG_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; + png_uint_32 user_height_max; + + /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown + * chunks that can be stored (0 means unlimited). + */ + png_uint_32 user_chunk_cache_max; + + /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. + */ + png_alloc_size_t user_chunk_malloc_max; +#endif + +/* New member added in libpng-1.0.25 and 1.2.17 */ +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + /* Temporary storage for unknown chunk that the library doesn't recognize, + * used while reading the chunk. + */ + png_unknown_chunk unknown_chunk; +#endif + +/* New member added in libpng-1.2.26 */ + png_size_t old_big_row_buf_size; + +#ifdef PNG_READ_SUPPORTED +/* New member added in libpng-1.2.30 */ + png_bytep read_buffer; /* buffer for reading chunk data */ + png_alloc_size_t read_buffer_size; /* current size of the buffer */ +#endif +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED + uInt IDAT_read_size; /* limit on read buffer size for IDAT */ +#endif + +#ifdef PNG_IO_STATE_SUPPORTED +/* New member added in libpng-1.4.0 */ + png_uint_32 io_state; +#endif + +/* New member added in libpng-1.5.6 */ + png_bytep big_prev_row; + +/* New member added in libpng-1.5.7 */ + void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row); + +#ifdef PNG_READ_SUPPORTED +#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) + png_colorspace colorspace; +#endif +#endif +}; +#endif /* PNGSTRUCT_H */ diff --git a/ext/libpng16/pngtest.c b/ext/libpng16/pngtest.c new file mode 100644 index 0000000000..f97907ee59 --- /dev/null +++ b/ext/libpng16/pngtest.c @@ -0,0 +1,1973 @@ + +/* pngtest.c - a simple test program to test libpng + * + * Last changed in libpng 1.6.2 [April 25, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This program reads in a PNG image, writes it out again, and then + * compares the two files. If the files are identical, this shows that + * the basic chunk handling, filtering, and (de)compression code is working + * properly. It does not currently test all of the transforms, although + * it probably should. + * + * The program will report "FAIL" in certain legitimate cases: + * 1) when the compression level or filter selection method is changed. + * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. + * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks + * exist in the input file. + * 4) others not listed here... + * In these cases, it is best to check with another tool such as "pngcheck" + * to see what the differences between the two files are. + * + * If a filename is given on the command-line, then this file is used + * for the input, rather than the default "pngtest.png". This allows + * testing a wide variety of files easily. You can also test a number + * of files at once by typing "pngtest -m file1.png file2.png ..." + */ + +#define _POSIX_SOURCE 1 + +#include +#include +#include + +/* Defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* For DOS */ + +#include "png.h" + +/* Known chunks that exist in pngtest.png must be supported or pngtest will fail + * simply as a result of re-ordering them. This may be fixed in 1.7 + */ +#if defined PNG_READ_SUPPORTED && /* else nothing can be done */\ + defined PNG_READ_bKGD_SUPPORTED &&\ + defined PNG_READ_cHRM_SUPPORTED &&\ + defined PNG_READ_gAMA_SUPPORTED &&\ + defined PNG_READ_oFFs_SUPPORTED &&\ + defined PNG_READ_pCAL_SUPPORTED &&\ + defined PNG_READ_pHYs_SUPPORTED &&\ + defined PNG_READ_sBIT_SUPPORTED &&\ + defined PNG_READ_sCAL_SUPPORTED &&\ + defined PNG_READ_sRGB_SUPPORTED &&\ + defined PNG_READ_tEXt_SUPPORTED &&\ + defined PNG_READ_tIME_SUPPORTED &&\ + defined PNG_READ_zTXt_SUPPORTED + +#include "zlib.h" +/* Copied from pngpriv.h but only used in error messages below. */ +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif +#define FCLOSE(file) fclose(file) + +#ifndef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +/* Makes pngtest verbose so we can find problems. */ +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if PNG_DEBUG > 1 +# define pngtest_debug(m) ((void)fprintf(stderr, m "\n")) +# define pngtest_debug1(m,p1) ((void)fprintf(stderr, m "\n", p1)) +# define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2)) +#else +# define pngtest_debug(m) ((void)0) +# define pngtest_debug1(m,p1) ((void)0) +# define pngtest_debug2(m,p1,p2) ((void)0) +#endif + +#if !PNG_DEBUG +# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ +#endif + +/* Turn on CPU timing +#define PNGTEST_TIMING +*/ + +#ifndef PNG_FLOATING_POINT_SUPPORTED +#undef PNGTEST_TIMING +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#include +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +#define PNG_tIME_STRING_LENGTH 29 +static int tIME_chunk_present = 0; +static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; +#endif + +static int verbose = 0; +static int strict = 0; +static int relaxed = 0; +static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */ +static int error_count = 0; /* count calls to png_error */ +static int warning_count = 0; /* count calls to png_warning */ + +#ifdef __TURBOC__ +#include +#endif + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) png_ptr->jmpbuf +#endif + +/* Defines for unknown chunk handling if required. */ +#ifndef PNG_HANDLE_CHUNK_ALWAYS +# define PNG_HANDLE_CHUNK_ALWAYS 3 +#endif +#ifndef PNG_HANDLE_CHUNK_IF_SAFE +# define PNG_HANDLE_CHUNK_IF_SAFE 2 +#endif + +/* Utility to save typing/errors, the argument must be a name */ +#define MEMZERO(var) ((void)memset(&var, 0, sizeof var)) + +/* Example of using row callbacks to make a simple progress meter */ +static int status_pass = 1; +static int status_dots_requested = 0; +static int status_dots = 1; + +static void PNGCBAPI +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) + return; + + if (status_pass != pass) + { + fprintf(stdout, "\n Pass %d: ", pass); + status_pass = pass; + status_dots = 31; + } + + status_dots--; + + if (status_dots == 0) + { + fprintf(stdout, "\n "); + status_dots=30; + } + + fprintf(stdout, "r"); +} + +#ifdef PNG_WRITE_SUPPORTED +static void PNGCBAPI +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) + return; + + fprintf(stdout, "w"); +} +#endif + + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely examine the row filters. We set this to 256 rather than + * 5 in case illegal filter values are present.) + */ +static png_uint_32 filters_used[256]; +static void PNGCBAPI +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + if (png_ptr != NULL && row_info != NULL) + ++filters_used[*(data - 1)]; +} +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely count the zero samples) + */ + +static png_uint_32 zero_samples; + +static void PNGCBAPI +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + png_bytep dp = data; + if (png_ptr == NULL) + return; + + /* Contents of row_info: + * png_uint_32 width width of row + * png_uint_32 rowbytes number of bytes in row + * png_byte color_type color type of pixels + * png_byte bit_depth bit depth of samples + * png_byte channels number of channels (1-4) + * png_byte pixel_depth bits per pixel (depth*channels) + */ + + /* Counts the number of zero samples (or zero pixels if color_type is 3 */ + + if (row_info->color_type == 0 || row_info->color_type == 3) + { + int pos = 0; + png_uint_32 n, nstop; + + for (n = 0, nstop=row_info->width; nbit_depth == 1) + { + if (((*dp << pos++ ) & 0x80) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 2) + { + if (((*dp << (pos+=2)) & 0xc0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 4) + { + if (((*dp << (pos+=4)) & 0xf0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp+=2; + } + } + } + else /* Other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if (row_info->color_type > 3)color_channels--; + + for (n = 0, nstop=row_info->width; nbit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + + dp+=2; + } + } + if (row_info->color_type > 3) + { + dp++; + if (row_info->bit_depth == 16) + dp++; + } + } + } +} +#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ + +#ifndef PNG_STDIO_SUPPORTED +/* START of code to validate stdio-free compilation */ +/* These copies of the default read/write functions come from pngrio.c and + * pngwio.c. They allow "don't include stdio" testing of the library. + * This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ + +#ifdef PNG_IO_STATE_SUPPORTED +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op); +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op) +{ + png_uint_32 io_state = png_get_io_state(png_ptr); + int err = 0; + + /* Check if the current operation (reading / writing) is as expected. */ + if ((io_state & PNG_IO_MASK_OP) != io_op) + png_error(png_ptr, "Incorrect operation in I/O state"); + + /* Check if the buffer size specific to the current location + * (file signature / header / data / crc) is as expected. + */ + switch (io_state & PNG_IO_MASK_LOC) + { + case PNG_IO_SIGNATURE: + if (data_length > 8) + err = 1; + break; + case PNG_IO_CHUNK_HDR: + if (data_length != 8) + err = 1; + break; + case PNG_IO_CHUNK_DATA: + break; /* no restrictions here */ + case PNG_IO_CHUNK_CRC: + if (data_length != 4) + err = 1; + break; + default: + err = 1; /* uninitialized */ + } + if (err) + png_error(png_ptr, "Bad I/O state or buffer size"); +} +#endif + +static void PNGCBAPI +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check = 0; + png_voidp io_ptr; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + io_ptr = png_get_io_ptr(png_ptr); + if (io_ptr != NULL) + { + check = fread(data, 1, length, (png_FILE_p)io_ptr); + } + + if (check != length) + { + png_error(png_ptr, "Read Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +static void PNGCBAPI +pngtest_flush(png_structp png_ptr) +{ + /* Do nothing; fflush() is said to be just a waste of energy. */ + PNG_UNUSED(png_ptr) /* Stifle compiler warning */ +} +#endif + +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +static void PNGCBAPI +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); + + if (check != length) + { + png_error(png_ptr, "Write Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#endif /* !PNG_STDIO_SUPPORTED */ + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +typedef struct +{ + PNG_CONST char *file_name; +} pngtest_error_parameters; + +static void PNGCBAPI +pngtest_warning(png_structp png_ptr, png_const_charp message) +{ + PNG_CONST char *name = "UNKNOWN (ERROR!)"; + pngtest_error_parameters *test = + (pngtest_error_parameters*)png_get_error_ptr(png_ptr); + + ++warning_count; + + if (test != NULL && test->file_name != NULL) + name = test->file_name; + + fprintf(STDERR, "%s: libpng warning: %s\n", name, message); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void PNGCBAPI +pngtest_error(png_structp png_ptr, png_const_charp message) +{ + ++error_count; + + pngtest_warning(png_ptr, message); + /* We can return because png_error calls the default handler, which is + * actually OK in this case. + */ +} + +/* END of code to validate stdio-free compilation */ + +/* START of code to validate memory allocation and deallocation */ +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * This piece of code can be compiled to validate max 64K allocations + * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. + */ +typedef struct memory_information +{ + png_alloc_size_t size; + png_voidp pointer; + struct memory_information *next; +} memory_information; +typedef memory_information *memory_infop; + +static memory_infop pinformation = NULL; +static int current_allocation = 0; +static int maximum_allocation = 0; +static int total_allocation = 0; +static int num_allocations = 0; + +png_voidp PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr, + png_alloc_size_t size)); +void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); + +png_voidp +PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) +{ + + /* png_malloc has already tested for NULL; png_create_struct calls + * png_debug_malloc directly, with png_ptr == NULL which is OK + */ + + if (size == 0) + return (NULL); + + /* This calls the library allocator twice, once to get the requested + buffer and once to get a new free list entry. */ + { + /* Disable malloc_fn and free_fn */ + memory_infop pinfo; + png_set_mem_fn(png_ptr, NULL, NULL, NULL); + pinfo = (memory_infop)png_malloc(png_ptr, + (sizeof *pinfo)); + pinfo->size = size; + current_allocation += size; + total_allocation += size; + num_allocations ++; + + if (current_allocation > maximum_allocation) + maximum_allocation = current_allocation; + + pinfo->pointer = png_malloc(png_ptr, size); + /* Restore malloc_fn and free_fn */ + + png_set_mem_fn(png_ptr, + NULL, png_debug_malloc, png_debug_free); + + if (size != 0 && pinfo->pointer == NULL) + { + current_allocation -= size; + total_allocation -= size; + png_error(png_ptr, + "out of memory in pngtest->png_debug_malloc"); + } + + pinfo->next = pinformation; + pinformation = pinfo; + /* Make sure the caller isn't assuming zeroed memory. */ + memset(pinfo->pointer, 0xdd, pinfo->size); + + if (verbose) + printf("png_malloc %lu bytes at %p\n", (unsigned long)size, + pinfo->pointer); + + return (png_voidp)(pinfo->pointer); + } +} + +/* Free a pointer. It is removed from the list at the same time. */ +void PNGCBAPI +png_debug_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL) + fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + + if (ptr == 0) + { +#if 0 /* This happens all the time. */ + fprintf(STDERR, "WARNING: freeing NULL pointer\n"); +#endif + return; + } + + /* Unlink the element from the list. */ + { + memory_infop *ppinfo = &pinformation; + + for (;;) + { + memory_infop pinfo = *ppinfo; + + if (pinfo->pointer == ptr) + { + *ppinfo = pinfo->next; + current_allocation -= pinfo->size; + if (current_allocation < 0) + fprintf(STDERR, "Duplicate free of memory\n"); + /* We must free the list element too, but first kill + the memory that is to be freed. */ + memset(ptr, 0x55, pinfo->size); + png_free_default(png_ptr, pinfo); + pinfo = NULL; + break; + } + + if (pinfo->next == NULL) + { + fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); + break; + } + + ppinfo = &pinfo->next; + } + } + + /* Finally free the data. */ + if (verbose) + printf("Freeing %p\n", ptr); + + png_free_default(png_ptr, ptr); + ptr = NULL; +} +#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ +/* END of code to test memory allocation/deallocation */ + + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* Demonstration of user chunk support of the sTER and vpAg chunks */ + +/* (sTER is a public chunk not yet known by libpng. vpAg is a private +chunk used in ImageMagick to store "virtual page" size). */ + +static struct user_chunk_data +{ + png_const_infop info_ptr; + png_uint_32 vpAg_width, vpAg_height; + png_byte vpAg_units; + png_byte sTER_mode; + int location[2]; +} +user_chunk_data; + +/* Used for location and order; zero means nothing. */ +#define have_sTER 0x01 +#define have_vpAg 0x02 +#define before_PLTE 0x10 +#define before_IDAT 0x20 +#define after_IDAT 0x40 + +static void +init_callback_info(png_const_infop info_ptr) +{ + MEMZERO(user_chunk_data); + user_chunk_data.info_ptr = info_ptr; +} + +static int +set_location(png_structp png_ptr, struct user_chunk_data *data, int what) +{ + int location; + + if ((data->location[0] & what) || (data->location[1] & what)) + return 0; /* already have one of these */ + + /* Find where we are (the code below zeros info_ptr to indicate that the + * chunks before the first IDAT have been read.) + */ + if (data->info_ptr == NULL) /* after IDAT */ + location = what | after_IDAT; + + else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE)) + location = what | before_IDAT; + + else + location = what | before_PLTE; + + if (data->location[0] == 0) + data->location[0] = location; + + else + data->location[1] = location; + + return 1; /* handled */ +} + +static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr, + png_unknown_chunkp chunk) +{ + struct user_chunk_data *my_user_chunk_data = + (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr); + + if (my_user_chunk_data == NULL) + png_error(png_ptr, "lost user chunk pointer"); + + /* Return one of the following: + * return (-n); chunk had an error + * return (0); did not recognize + * return (n); success + * + * The unknown chunk structure contains the chunk data: + * png_byte name[5]; + * png_byte *data; + * png_size_t size; + * + * Note that libpng has already taken care of the CRC handling. + */ + + if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ + chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ + { + /* Found sTER chunk */ + if (chunk->size != 1) + return (-1); /* Error return */ + + if (chunk->data[0] != 0 && chunk->data[0] != 1) + return (-1); /* Invalid mode */ + + if (set_location(png_ptr, my_user_chunk_data, have_sTER)) + { + my_user_chunk_data->sTER_mode=chunk->data[0]; + return (1); + } + + else + return (0); /* duplicate sTER - give it to libpng */ + } + + if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ + chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ + return (0); /* Did not recognize */ + + /* Found ImageMagick vpAg chunk */ + + if (chunk->size != 9) + return (-1); /* Error return */ + + if (!set_location(png_ptr, my_user_chunk_data, have_vpAg)) + return (0); /* duplicate vpAg */ + + my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data); + my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4); + my_user_chunk_data->vpAg_units = chunk->data[8]; + + return (1); +} + +#ifdef PNG_WRITE_SUPPORTED +static void +write_sTER_chunk(png_structp write_ptr) +{ + png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}; + + if (verbose) + fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode); + + png_write_chunk(write_ptr, png_sTER, &user_chunk_data.sTER_mode, 1); +} + +static void +write_vpAg_chunk(png_structp write_ptr) +{ + png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; + + png_byte vpag_chunk_data[9]; + + if (verbose) + fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n", + (unsigned long)user_chunk_data.vpAg_width, + (unsigned long)user_chunk_data.vpAg_height, + user_chunk_data.vpAg_units); + + png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width); + png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height); + vpag_chunk_data[8] = user_chunk_data.vpAg_units; + png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9); +} + +static void +write_chunks(png_structp write_ptr, int location) +{ + int i; + + /* Notice that this preserves the original chunk order, however chunks + * intercepted by the callback will be written *after* chunks passed to + * libpng. This will actually reverse a pair of sTER chunks or a pair of + * vpAg chunks, resulting in an error later. This is not worth worrying + * about - the chunks should not be duplicated! + */ + for (i=0; i<2; ++i) + { + if (user_chunk_data.location[i] == (location | have_sTER)) + write_sTER_chunk(write_ptr); + + else if (user_chunk_data.location[i] == (location | have_vpAg)) + write_vpAg_chunk(write_ptr); + } +} +#endif /* PNG_WRITE_SUPPORTED */ +#else /* !PNG_READ_USER_CHUNKS_SUPPORTED */ +# define write_chunks(pp,loc) ((void)0) +#endif +/* END of code to demonstrate user chunk support */ + +/* START of code to check that libpng has the required text support; this only + * checks for the write support because if read support is missing the chunk + * will simply not be reported back to pngtest. + */ +#ifdef PNG_TEXT_SUPPORTED +static void +pngtest_check_text_support(png_const_structp png_ptr, png_textp text_ptr, + int num_text) +{ + while (num_text > 0) + { + switch (text_ptr[--num_text].compression) + { + case PNG_TEXT_COMPRESSION_NONE: + break; + + case PNG_TEXT_COMPRESSION_zTXt: +# ifndef PNG_WRITE_zTXt_SUPPORTED + ++unsupported_chunks; +# endif + break; + + case PNG_ITXT_COMPRESSION_NONE: + case PNG_ITXT_COMPRESSION_zTXt: +# ifndef PNG_WRITE_iTXt_SUPPORTED + ++unsupported_chunks; +# endif + break; + + default: + /* This is an error */ + png_error(png_ptr, "invalid text chunk compression field"); + break; + } + } +} +#endif +/* END of code to check that libpng has the required text support */ + +/* Test one file */ +static int +test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) +{ + static png_FILE_p fpin; + static png_FILE_p fpout; /* "static" prevents setjmp corruption */ + pngtest_error_parameters error_parameters; + png_structp read_ptr; + png_infop read_info_ptr, end_info_ptr; +#ifdef PNG_WRITE_SUPPORTED + png_structp write_ptr; + png_infop write_info_ptr; + png_infop write_end_info_ptr; +#else + png_structp write_ptr = NULL; + png_infop write_info_ptr = NULL; + png_infop write_end_info_ptr = NULL; +#endif + png_bytep row_buf; + png_uint_32 y; + png_uint_32 width, height; + int num_pass, pass; + int bit_depth, color_type; + + row_buf = NULL; + error_parameters.file_name = inname; + + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "wb")) == NULL) + { + fprintf(STDERR, "Could not open output file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + pngtest_debug("Allocating read and write structures"); +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + read_ptr = + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + read_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif + png_set_error_fn(read_ptr, &error_parameters, pngtest_error, + pngtest_warning); + +#ifdef PNG_WRITE_SUPPORTED +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + write_ptr = + png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + write_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif + png_set_error_fn(write_ptr, &error_parameters, pngtest_error, + pngtest_warning); +#endif + pngtest_debug("Allocating read_info, write_info and end_info structures"); + read_info_ptr = png_create_info_struct(read_ptr); + end_info_ptr = png_create_info_struct(read_ptr); +#ifdef PNG_WRITE_SUPPORTED + write_info_ptr = png_create_info_struct(write_ptr); + write_end_info_ptr = png_create_info_struct(write_ptr); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + init_callback_info(read_info_ptr); + png_set_read_user_chunk_fn(read_ptr, &user_chunk_data, + read_user_chunk_callback); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + pngtest_debug("Setting jmpbuf for read struct"); + if (setjmp(png_jmpbuf(read_ptr))) + { + fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); + png_free(read_ptr, row_buf); + row_buf = NULL; + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Setting jmpbuf for write struct"); + + if (setjmp(png_jmpbuf(write_ptr))) + { + fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#endif +#endif + + if (strict) + { + /* Treat png_benign_error() as errors on read */ + png_set_benign_errors(read_ptr, 0); + +#ifdef PNG_WRITE_SUPPORTED + /* Treat them as errors on write */ + png_set_benign_errors(write_ptr, 0); +#endif + + /* if strict is not set, then app warnings and errors are treated as + * warnings in release builds, but not in unstable builds; this can be + * changed with '--relaxed'. + */ + } + + else if (relaxed) + { + /* Allow application (pngtest) errors and warnings to pass */ + png_set_benign_errors(read_ptr, 1); + +#ifdef PNG_WRITE_SUPPORTED + png_set_benign_errors(write_ptr, 1); +#endif + } + + pngtest_debug("Initializing input and output streams"); +#ifdef PNG_STDIO_SUPPORTED + png_init_io(read_ptr, fpin); +# ifdef PNG_WRITE_SUPPORTED + png_init_io(write_ptr, fpout); +# endif +#else + png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); +# ifdef PNG_WRITE_SUPPORTED + png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, +# ifdef PNG_WRITE_FLUSH_SUPPORTED + pngtest_flush); +# else + NULL); +# endif +# endif +#endif + + if (status_dots_requested == 1) + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, write_row_callback); +#endif + png_set_read_status_fn(read_ptr, read_row_callback); + } + + else + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, NULL); +#endif + png_set_read_status_fn(read_ptr, NULL); + } + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + { + int i; + + for (i = 0; i<256; i++) + filters_used[i] = 0; + + png_set_read_user_transform_fn(read_ptr, count_filters); + } +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + zero_samples = 0; + png_set_write_user_transform_fn(write_ptr, count_zero_samples); +#endif + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + /* Preserve all the unknown chunks, if possible. If this is disabled then, + * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use + * libpng to *save* the unknown chunks on read (because we can't switch the + * save option on!) + * + * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all + * unknown chunks and write will write them all. + */ +#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED + png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, + NULL, 0); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS, + NULL, 0); +#endif +#endif + + pngtest_debug("Reading info struct"); + png_read_info(read_ptr, read_info_ptr); + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + /* This is a bit of a hack; there is no obvious way in the callback function + * to determine that the chunks before the first IDAT have been read, so + * remove the info_ptr (which is only used to determine position relative to + * PLTE) here to indicate that we are after the IDAT. + */ + user_chunk_data.info_ptr = NULL; +#endif + + pngtest_debug("Transferring info struct"); + { + int interlace_type, compression_type, filter_type; + + if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, &compression_type, &filter_type)) + { + png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + color_type, interlace_type, compression_type, filter_type); +#else + color_type, PNG_INTERLACE_NONE, compression_type, filter_type); +#endif + } + } +#ifdef PNG_FIXED_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + png_fixed_point gamma; + + if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); + } +#endif +#else /* Use floating point versions */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + double gamma; + + if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA(write_ptr, write_info_ptr, gamma); + } +#endif +#endif /* Floating point */ +#endif /* Fixed point */ +#ifdef PNG_iCCP_SUPPORTED + { + png_charp name; + png_bytep profile; + png_uint_32 proflen; + int compression_type; + + if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, + &profile, &proflen)) + { + png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, + profile, proflen); + } + } +#endif +#ifdef PNG_sRGB_SUPPORTED + { + int intent; + + if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) + png_set_sRGB(write_ptr, write_info_ptr, intent); + } +#endif + { + png_colorp palette; + int num_palette; + + if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) + png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); + } +#ifdef PNG_bKGD_SUPPORTED + { + png_color_16p background; + + if (png_get_bKGD(read_ptr, read_info_ptr, &background)) + { + png_set_bKGD(write_ptr, write_info_ptr, background); + } + } +#endif +#ifdef PNG_hIST_SUPPORTED + { + png_uint_16p hist; + + if (png_get_hIST(read_ptr, read_info_ptr, &hist)) + png_set_hIST(write_ptr, write_info_ptr, hist); + } +#endif +#ifdef PNG_oFFs_SUPPORTED + { + png_int_32 offset_x, offset_y; + int unit_type; + + if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, + &unit_type)) + { + png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); + } + } +#endif +#ifdef PNG_pCAL_SUPPORTED + { + png_charp purpose, units; + png_charpp params; + png_int_32 X0, X1; + int type, nparams; + + if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, + &nparams, &units, ¶ms)) + { + png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, + nparams, units, params); + } + } +#endif +#ifdef PNG_pHYs_SUPPORTED + { + png_uint_32 res_x, res_y; + int unit_type; + + if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) + png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); + } +#endif +#ifdef PNG_sBIT_SUPPORTED + { + png_color_8p sig_bit; + + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) + png_set_sBIT(write_ptr, write_info_ptr, sig_bit); + } +#endif +#ifdef PNG_sCAL_SUPPORTED +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) + { + int unit; + double scal_width, scal_height; + + if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + { + int unit; + png_charp scal_width, scal_height; + + if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, + scal_height); + } + } +#endif +#endif +#endif +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + + pngtest_check_text_support(read_ptr, text_ptr, num_text); + + if (verbose) + { + int i; + + printf("\n"); + for (i=0; igray > sample_max) || + (color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max)))) + png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans, + trans_color); + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + + if (num_unknowns) + { + png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, + num_unknowns); +#if PNG_LIBPNG_VER < 10600 + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_end_info_ptr are wrong prior to 1.6.0 + * because they are reset from the write pointer (removed in 1.6.0). + */ + { + int i; + for (i = 0; i < num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, + unknowns[i].location); + } +#endif + } + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Writing info struct"); + + /* Write the info in two steps so that if we write the 'unknown' chunks here + * they go to the correct place. + */ + png_write_info_before_PLTE(write_ptr, write_info_ptr); + + write_chunks(write_ptr, before_PLTE); /* before PLTE */ + + png_write_info(write_ptr, write_info_ptr); + + write_chunks(write_ptr, before_IDAT); /* after PLTE */ +#endif + +#ifdef SINGLE_ROWBUF_ALLOC + pngtest_debug("Allocating row buffer..."); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug1("\t0x%08lx", (unsigned long)row_buf); +#endif /* SINGLE_ROWBUF_ALLOC */ + pngtest_debug("Writing row data"); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) + num_pass = png_set_interlace_handling(read_ptr); +# ifdef PNG_WRITE_SUPPORTED + png_set_interlace_handling(write_ptr); +# endif +#else + num_pass = 1; +#endif + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; +#endif + for (pass = 0; pass < num_pass; pass++) + { + pngtest_debug1("Writing row data for pass %d", pass); + for (y = 0; y < height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug2("\t0x%08lx (%u bytes)", (unsigned long)row_buf, + png_get_rowbytes(read_ptr, read_info_ptr)); + +#endif /* !SINGLE_ROWBUF_ALLOC */ + png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* !SINGLE_ROWBUF_ALLOC */ + } + } + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); +# endif +# ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); +# endif +#endif + + pngtest_debug("Reading and writing end_info data"); + + png_read_end(read_ptr, end_info_ptr); +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + + pngtest_check_text_support(read_ptr, text_ptr, num_text); + + if (verbose) + { + int i; + + printf("\n"); + for (i=0; i 0) + { + /* We don't really expect to get here because of the setjmp handling + * above, but this is safe. + */ + fprintf(STDERR, "\n %s: %d libpng errors found (%d warnings)", + inname, error_count, warning_count); + + if (strict != 0) + return (1); + } + +# ifdef PNG_WRITE_SUPPORTED + /* If there we no write support nothing was written! */ + else if (unsupported_chunks > 0) + { + fprintf(STDERR, "\n %s: unsupported chunks (%d)%s", + inname, unsupported_chunks, strict ? ": IGNORED --strict!" : ""); + } +# endif + + else if (warning_count > 0) + { + fprintf(STDERR, "\n %s: %d libpng warnings found", + inname, warning_count); + + if (strict != 0) + return (1); + } + + pngtest_debug("Opening files for comparison"); + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", outname); + FCLOSE(fpin); + return (1); + } + +#ifdef PNG_WRITE_SUPPORTED /* else nothing was written */ + { + int wrote_question = 0; + + for (;;) + { + png_size_t num_in, num_out; + char inbuf[256], outbuf[256]; + + + num_in = fread(inbuf, 1, sizeof inbuf, fpin); + num_out = fread(outbuf, 1, sizeof outbuf, fpout); + + if (num_in != num_out) + { + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); + + if (wrote_question == 0 && unsupported_chunks == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + + if (strict != 0 && unsupported_chunks == 0) + return (1); + + else + return (0); + } + + if (!num_in) + break; + + if (memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, + outname); + + if (wrote_question == 0 && unsupported_chunks == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + + /* NOTE: the unsupported_chunks escape is permitted here because + * unsupported text chunk compression will result in the compression + * mode being changed (to NONE) yet, in the test case, the result + * can be exactly the same size! + */ + if (strict != 0 && unsupported_chunks == 0) + return (1); + + else + return (0); + } + } + } +#endif /* PNG_WRITE_SUPPORTED */ + + FCLOSE(fpin); + FCLOSE(fpout); + + return (0); +} + +/* Input and output filenames */ +#ifdef RISCOS +static PNG_CONST char *inname = "pngtest/png"; +static PNG_CONST char *outname = "pngout/png"; +#else +static PNG_CONST char *inname = "pngtest.png"; +static PNG_CONST char *outname = "pngout.png"; +#endif + +int +main(int argc, char *argv[]) +{ + int multiple = 0; + int ierror = 0; + + fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); + fprintf(STDERR, "%s", png_get_copyright(NULL)); + /* Show the version of libpng used in building the library */ + fprintf(STDERR, " library (%lu):%s", + (unsigned long)png_access_version_number(), + png_get_header_version(NULL)); + + /* Show the version of libpng used in building the application */ + fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, + PNG_HEADER_VERSION_STRING); + + /* Do some consistency checking on the memory allocation settings, I'm + * not sure this matters, but it is nice to know, the first of these + * tests should be impossible because of the way the macros are set + * in pngconf.h + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); +#endif + /* I think the following can happen. */ +#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); +#endif + + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) + { + fprintf(STDERR, + "Warning: versions are different between png.h and png.c\n"); + fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); + ++ierror; + } + + if (argc > 1) + { + if (strcmp(argv[1], "-m") == 0) + { + multiple = 1; + status_dots_requested = 0; + } + + else if (strcmp(argv[1], "-mv") == 0 || + strcmp(argv[1], "-vm") == 0 ) + { + multiple = 1; + verbose = 1; + status_dots_requested = 1; + } + + else if (strcmp(argv[1], "-v") == 0) + { + verbose = 1; + status_dots_requested = 1; + inname = argv[2]; + } + + else if (strcmp(argv[1], "--strict") == 0) + { + status_dots_requested = 0; + verbose = 1; + inname = argv[2]; + strict++; + relaxed = 0; + } + + else if (strcmp(argv[1], "--relaxed") == 0) + { + status_dots_requested = 0; + verbose = 1; + inname = argv[2]; + strict = 0; + relaxed++; + } + + else + { + inname = argv[1]; + status_dots_requested = 0; + } + } + + if (!multiple && argc == 3 + verbose) + outname = argv[2 + verbose]; + + if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2)) + { + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); + } + + if (multiple) + { + int i; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + for (i=2; isize, + (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + + else + { + int i; + for (i = 0; i<3; ++i) + { + int kerror; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + if (i == 1) + status_dots_requested = 1; + + else if (verbose == 0) + status_dots_requested = 0; + + if (i == 0 || verbose == 1 || ierror != 0) + fprintf(STDERR, "\n Testing %s:", inname); + + kerror = test_one_file(inname, outname); + + if (kerror == 0) + { + if (verbose == 1 || i == 2) + { +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + int k; +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + for (k = 0; k<256; k++) + if (filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k, (unsigned long)filters_used[k]); +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n", tIME_string); +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } + + else + { + if (verbose == 0 && i != 2) + fprintf(STDERR, "\n Testing %s:", inname); + + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation - allocation_now); + + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + + while (pinfo != NULL) + { + fprintf(STDERR, " %lu bytes at %x\n", + (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; + fprintf(STDERR, " CPU time used = %.3f seconds", + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " (decoding %.3f,\n", + t_decode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " encoding %.3f ,", + t_encode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " other %.3f seconds)\n\n", + t_misc/(float)CLOCKS_PER_SEC); +#endif + + if (ierror == 0) + fprintf(STDERR, " libpng passes test\n"); + + else + fprintf(STDERR, " libpng FAILS test\n"); + + return (int)(ierror != 0); +} +#else +int +main(void) +{ + fprintf(STDERR, + " test ignored because libpng was not built with read support\n"); + /* And skip this test */ + return 77; +} +#endif + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef png_libpng_version_1_6_7 Your_png_h_is_not_version_1_6_7; diff --git a/ext/libpng16/pngtrans.c b/ext/libpng16/pngtrans.c new file mode 100644 index 0000000000..99c6ea9d3b --- /dev/null +++ b/ext/libpng16/pngtrans.c @@ -0,0 +1,841 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * Last changed in libpng 1.6.2 [April 25, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structrp png_ptr) +{ + png_debug(1, "in png_set_bgr"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structrp png_ptr) +{ + png_debug(1, "in png_set_swap"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Turn on pixel packing */ +void PNGAPI +png_set_packing(png_structrp png_ptr) +{ + png_debug(1, "in png_set_packing"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structrp png_ptr) +{ + png_debug(1, "in png_set_packswap"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits) +{ + png_debug(1, "in png_set_shift"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structrp png_ptr) +{ + png_debug(1, "in png_set_interlace handling"); + + if (png_ptr && png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler"); + + if (png_ptr == NULL) + return; + + /* In libpng 1.6 it is possible to determine whether this is a read or write + * operation and therefore to do more checking here for a valid call. + */ + if (png_ptr->mode & PNG_IS_READ_STRUCT) + { +# ifdef PNG_READ_FILLER_SUPPORTED + /* On read png_set_filler is always valid, regardless of the base PNG + * format, because other transformations can give a format where the + * filler code can execute (basically an 8 or 16-bit component RGB or G + * format.) + * + * NOTE: usr_channels is not used by the read code! (This has led to + * confusion in the past.) The filler is only used in the read code. + */ + png_ptr->filler = (png_uint_16)filler; +# else + png_app_error(png_ptr, "png_set_filler not supported on read"); + PNG_UNUSED(filler) /* not used in the write case */ + return; +# endif + } + + else /* write */ + { +# ifdef PNG_WRITE_FILLER_SUPPORTED + /* On write the usr_channels parameter must be set correctly at the + * start to record the number of channels in the app-supplied data. + */ + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_RGB: + png_ptr->usr_channels = 4; + break; + + case PNG_COLOR_TYPE_GRAY: + if (png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + break; + } + + else + { + /* There simply isn't any code in libpng to strip out bits + * from bytes when the components are less than a byte in + * size! + */ + png_app_error(png_ptr, + "png_set_filler is invalid for low bit depth gray output"); + return; + } + + default: + png_app_error(png_ptr, + "png_set_filler: inappropriate color type"); + return; + } +# else + png_app_error(png_ptr, "png_set_filler not supported on write"); + return; +# endif + } + + /* Here on success - libpng supports the operation, set the transformation + * and the flag to say where the filler channel is. + */ + png_ptr->transformations |= PNG_FILLER; + + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; +} + +/* Added to libpng-1.2.7 */ +void PNGAPI +png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_add_alpha"); + + if (png_ptr == NULL) + return; + + png_set_filler(png_ptr, filler, filler_loc); + /* The above may fail to do anything. */ + if (png_ptr->transformations & PNG_FILLER) + png_ptr->transformations |= PNG_ADD_ALPHA; +} + +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structrp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structrp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structrp png_ptr) +{ + png_debug(1, "in png_set_invert_mono"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* Invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert"); + + /* This test removed from libpng version 1.0.13 and 1.2.0: + * if (row_info->bit_depth == 1 && + */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 8) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 2) + { + *rp = (png_byte)(~(*rp)); + rp += 2; + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 4) + { + *rp = (png_byte)(~(*rp)); + *(rp + 1) = (png_byte)(~(*(rp + 1))); + rp += 4; + } + } +#endif +} +#endif + +#ifdef PNG_16BIT_SUPPORTED +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap"); + + if (row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static PNG_CONST png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static PNG_CONST png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static PNG_CONST png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* Swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap"); + + if (row_info->bit_depth < 8) + { + png_bytep rp; + png_const_bytep end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = onebppswaptable; + + else if (row_info->bit_depth == 2) + table = twobppswaptable; + + else if (row_info->bit_depth == 4) + table = fourbppswaptable; + + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* Remove a channel - this used to be 'png_do_strip_filler' but it used a + * somewhat weird combination of flags to determine what to do. All the calls + * to png_do_strip_filler are changed in 1.5.2 to call this instead with the + * correct arguments. + * + * The routine isn't general - the channel must be the channel at the start or + * end (not in the middle) of each pixel. + */ +void /* PRIVATE */ +png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) +{ + png_bytep sp = row; /* source pointer */ + png_bytep dp = row; /* destination pointer */ + png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */ + + /* At the start sp will point to the first byte to copy and dp to where + * it is copied to. ep always points just beyond the end of the row, so + * the loop simply copies (channels-1) channels until sp reaches ep. + * + * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc. + * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc. + */ + + /* GA, GX, XG cases */ + if (row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + if (at_start) /* Skip initial filler */ + ++sp; + else /* Skip initial channel and, for sp, the filler */ + sp += 2, ++dp; + + /* For a 1 pixel wide image there is nothing to do */ + while (sp < ep) + *dp++ = *sp, sp += 2; + + row_info->pixel_depth = 8; + } + + else if (row_info->bit_depth == 16) + { + if (at_start) /* Skip initial filler */ + sp += 2; + else /* Skip initial channel and, for sp, the filler */ + sp += 4, dp += 2; + + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp, sp += 3; + + row_info->pixel_depth = 16; + } + + else + return; /* bad bit depth */ + + row_info->channels = 1; + + /* Finally fix the color type if it records an alpha channel */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + row_info->color_type = PNG_COLOR_TYPE_GRAY; + } + + /* RGBA, RGBX, XRGB cases */ + else if (row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + if (at_start) /* Skip initial filler */ + ++sp; + else /* Skip initial channels and, for sp, the filler */ + sp += 4, dp += 3; + + /* Note that the loop adds 3 to dp and 4 to sp each time. */ + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; + + row_info->pixel_depth = 24; + } + + else if (row_info->bit_depth == 16) + { + if (at_start) /* Skip initial filler */ + sp += 2; + else /* Skip initial channels and, for sp, the filler */ + sp += 8, dp += 6; + + while (sp < ep) + { + /* Copy 6 bytes, skip 2 */ + *dp++ = *sp++, *dp++ = *sp++; + *dp++ = *sp++, *dp++ = *sp++; + *dp++ = *sp++, *dp++ = *sp, sp += 3; + } + + row_info->pixel_depth = 48; + } + + else + return; /* bad bit depth */ + + row_info->channels = 3; + + /* Finally fix the color type if it records an alpha channel */ + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + row_info->color_type = PNG_COLOR_TYPE_RGB; + } + + else + return; /* The filler channel has gone already */ + + /* Fix the rowbytes value. */ + row_info->rowbytes = dp-row; +} +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr"); + + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } +#endif + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \ + defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED) +/* Added at libpng-1.5.10 */ +void /* PRIVATE */ +png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) +{ + if (png_ptr->num_palette < (1 << row_info->bit_depth) && + png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */ + { + /* Calculations moved outside switch in an attempt to stop different + * compiler warnings. 'padding' is in *bits* within the last byte, it is + * an 'int' because pixel_depth becomes an 'int' in the expression below, + * and this calculation is used because it avoids warnings that other + * forms produced on either GCC or MSVC. + */ + int padding = (-row_info->pixel_depth * row_info->width) & 7; + png_bytep rp = png_ptr->row_buf + row_info->rowbytes; + + switch (row_info->bit_depth) + { + case 1: + { + /* in this case, all bytes must be 0 so we don't need + * to unpack the pixels except for the rightmost one. + */ + for (; rp > png_ptr->row_buf; rp--) + { + if (*rp >> padding != 0) + png_ptr->num_palette_max = 1; + padding = 0; + } + + break; + } + + case 2: + { + for (; rp > png_ptr->row_buf; rp--) + { + int i = ((*rp >> padding) & 0x03); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + i = (((*rp >> padding) >> 2) & 0x03); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + i = (((*rp >> padding) >> 4) & 0x03); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + i = (((*rp >> padding) >> 6) & 0x03); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + padding = 0; + } + + break; + } + + case 4: + { + for (; rp > png_ptr->row_buf; rp--) + { + int i = ((*rp >> padding) & 0x0f); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + i = (((*rp >> padding) >> 4) & 0x0f); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + padding = 0; + } + + break; + } + + case 8: + { + for (; rp > png_ptr->row_buf; rp--) + { + if (*rp > png_ptr->num_palette_max) + png_ptr->num_palette_max = (int) *rp; + } + + break; + } + + default: + break; + } + } +} +#endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +void PNGAPI +png_set_user_transform_info(png_structrp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0) + { + png_app_error(png_ptr, + "info change after png_start_read_image or png_read_update_info"); + return; + } +#endif + + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +} +#endif + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +png_voidp PNGAPI +png_get_user_transform_ptr(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->user_transform_ptr; +} +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +png_uint_32 PNGAPI +png_get_current_row_number(png_const_structrp png_ptr) +{ + /* See the comments in png.h - this is the sub-image row when reading and + * interlaced image. + */ + if (png_ptr != NULL) + return png_ptr->row_number; + + return PNG_UINT_32_MAX; /* help the app not to fail silently */ +} + +png_byte PNGAPI +png_get_current_pass_number(png_const_structrp png_ptr) +{ + if (png_ptr != NULL) + return png_ptr->pass; + return 8; /* invalid */ +} +#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */ +#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED || + PNG_WRITE_USER_TRANSFORM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngwio.c b/ext/libpng16/pngwio.c new file mode 100644 index 0000000000..c5fca989c8 --- /dev/null +++ b/ext/libpng16/pngwio.c @@ -0,0 +1,164 @@ + +/* pngwio.c - functions for data output + * + * Last changed in libpng 1.6.0 [February 14, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +/* Write the data to whatever output you are using. The default routine + * writes to a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered writes. This should never be asked + * to write more than 64K on a 16 bit machine. + */ + +void /* PRIVATE */ +png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) +{ + /* NOTE: write_data_fn must not change the buffer! */ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data), + length); + + else + png_error(png_ptr, "Call to NULL write function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +void PNGCBAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); + + if (check != length) + png_error(png_ptr, "Write Error"); +} +#endif + +/* This function is called to output any data pending writing (normally + * to disk). After png_flush is called, there should be no data pending + * writing in any buffers. + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +void /* PRIVATE */ +png_flush(png_structrp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +# ifdef PNG_STDIO_SUPPORTED +void PNGCBAPI +png_default_flush(png_structp png_ptr) +{ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr)); + fflush(io_ptr); +} +# endif +#endif + +/* This function allows the application to supply new output functions for + * libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png output data structure + * io_ptr - pointer to user supplied structure containing info about + * the output functions. May be NULL. + * write_data_fn - pointer to a new output function that takes as its + * arguments a pointer to a png_struct, a pointer to + * data to be written, and a 32-bit unsigned int that is + * the number of bytes to be written. The new write + * function should call png_error(png_ptr, "Error msg") + * to exit and output any fatal error messages. May be + * NULL, in which case libpng's default function will + * be used. + * flush_data_fn - pointer to a new flush function that takes as its + * arguments a pointer to a png_struct. After a call to + * the flush function, there should be no data in any buffers + * or pending transmission. If the output method doesn't do + * any buffering of output, a function prototype must still be + * supplied although it doesn't have to do anything. If + * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + * time, output_flush_fn will be ignored, although it must be + * supplied for compatibility. May be NULL, in which case + * libpng's default function will be used, if + * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not + * a good idea if io_ptr does not point to a standard + * *FILE structure. + */ +void PNGAPI +png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED + + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + + else + png_ptr->output_flush_fn = png_default_flush; + +# else + png_ptr->output_flush_fn = output_flush_fn; +# endif +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + + png_warning(png_ptr, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngwrite.c b/ext/libpng16/pngwrite.c new file mode 100644 index 0000000000..4fe7301d3f --- /dev/null +++ b/ext/libpng16/pngwrite.c @@ -0,0 +1,2330 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * Last changed in libpng 1.6.2 [April 25, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" +#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) +# include +#endif + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +/* Write out all the unknown chunks for the current given location */ +static void +write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, + unsigned int where) +{ + if (info_ptr->unknown_chunks_num) + { + png_const_unknown_chunkp up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + ++up) + if (up->location & where) + { + /* If per-chunk unknown chunk handling is enabled use it, otherwise + * just write the chunks the application has set. + */ +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + int keep = png_handle_as_unknown(png_ptr, up->name); + + /* NOTE: this code is radically different from the read side in the + * matter of handling an ancillary unknown chunk. In the read side + * the default behavior is to discard it, in the code below the default + * behavior is to write it. Critical chunks are, however, only + * written if explicitly listed or if the default is set to write all + * unknown chunks. + * + * The default handling is also slightly weird - it is not possible to + * stop the writing of all unsafe-to-copy chunks! + * + * TODO: REVIEW: this would seem to be a bug. + */ + if (keep != PNG_HANDLE_CHUNK_NEVER && + ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ || + keep == PNG_HANDLE_CHUNK_ALWAYS || + (keep == PNG_HANDLE_CHUNK_AS_DEFAULT && + png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS))) +#endif + { + /* TODO: review, what is wrong with a zero length unknown chunk? */ + if (up->size == 0) + png_warning(png_ptr, "Writing zero-length unknown chunk"); + + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +} +#endif /* PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */ + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + /* Write PNG signature */ + png_write_sig(png_ptr); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \ + (png_ptr->mng_features_permitted)) + { + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted = 0; + } +#endif + + /* Write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + info_ptr->interlace_type +#else + 0 +#endif + ); + + /* The rest of these check to see if the valid field has the appropriate + * flag set, and if it does, writes the chunk. + * + * 1.6.0: COLORSPACE support controls the writing of these chunks too, and + * the chunks will be written if the WRITE routine is there and information + * is available in the COLORSPACE. (See png_colorspace_sync_info in png.c + * for where the valid flags get set.) + * + * Under certain circumstances the colorspace can be invalidated without + * syncing the info_struct 'valid' flags; this happens if libpng detects and + * error and calls png_error while the color space is being set, yet the + * application continues writing the PNG. So check the 'invalid' flag here + * too. + */ +#ifdef PNG_GAMMA_SUPPORTED +# ifdef PNG_WRITE_gAMA_SUPPORTED + if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && + (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) && + (info_ptr->valid & PNG_INFO_gAMA)) + png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma); +# endif +#endif + +#ifdef PNG_COLORSPACE_SUPPORTED + /* Write only one of sRGB or an ICC profile. If a profile was supplied + * and it matches one of the known sRGB ones issue a warning. + */ +# ifdef PNG_WRITE_iCCP_SUPPORTED + if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && + (info_ptr->valid & PNG_INFO_iCCP)) + { +# ifdef PNG_WRITE_sRGB_SUPPORTED + if (info_ptr->valid & PNG_INFO_sRGB) + png_app_warning(png_ptr, + "profile matches sRGB but writing iCCP instead"); +# endif + + png_write_iCCP(png_ptr, info_ptr->iccp_name, + info_ptr->iccp_profile); + } +# ifdef PNG_WRITE_sRGB_SUPPORTED + else +# endif +# endif + +# ifdef PNG_WRITE_sRGB_SUPPORTED + if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && + (info_ptr->valid & PNG_INFO_sRGB)) + png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); +# endif /* WRITE_sRGB */ +#endif /* COLORSPACE */ + +#ifdef PNG_WRITE_sBIT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif + +#ifdef PNG_COLORSPACE_SUPPORTED +# ifdef PNG_WRITE_cHRM_SUPPORTED + if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && + (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) && + (info_ptr->valid & PNG_INFO_cHRM)) + png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy); +# endif +#endif + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); +#endif + + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images"); + +#ifdef PNG_WRITE_tRNS_SUPPORTED + if (info_ptr->valid & PNG_INFO_tRNS) + { +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j = 0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans_alpha[j] = + (png_byte)(255 - info_ptr->trans_alpha[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#ifdef PNG_WRITE_bKGD_SUPPORTED + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_sCAL) + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#endif /* sCAL */ + +#ifdef PNG_WRITE_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif /* pHYs */ + +#ifdef PNG_WRITE_tIME_SUPPORTED + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif /* tIME */ + +#ifdef PNG_WRITE_sPLT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif /* sPLT */ + +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; +#else + /* Can't get here */ + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + } + } +#endif /* tEXt */ + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE); +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structrp png_ptr, png_inforp info_ptr) +{ + png_debug(1, "in png_write_end"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); + +#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED + if (png_ptr->num_palette_max > png_ptr->num_palette) + png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); +#endif + + /* See if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#ifdef PNG_WRITE_TEXT_SUPPORTED + int i; /* local index variable */ +#endif +#ifdef PNG_WRITE_tIME_SUPPORTED + /* Check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + +#endif +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT); +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* Write end of PNG file */ + png_write_IEND(png_ptr); + /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, + * and restored again in libpng-1.2.30, may cause some applications that + * do not set png_ptr->output_flush_fn to crash. If your application + * experiences a problem, please try building libpng with + * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to + * png-mng-implement at lists.sf.net . + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED + png_flush(png_ptr); +# endif +#endif +} + +#ifdef PNG_CONVERT_tIME_SUPPORTED +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm"); + + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t"); + + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) +{ +#ifndef PNG_USER_MEM_SUPPORTED + png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + error_fn, warn_fn, NULL, NULL, NULL); +#else + return png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +{ + png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + if (png_ptr != NULL) + { + /* Set the zlib control values to defaults; they can be overridden by the + * application after the struct has been created. + */ + png_ptr->zbuffer_size = PNG_ZBUF_SIZE; + + /* The 'zlib_strategy' setting is irrelevant because png_default_claim in + * pngwutil.c defaults it according to whether or not filters will be + * used, and ignores this setting. + */ + png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY; + png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION; + png_ptr->zlib_mem_level = 8; + png_ptr->zlib_window_bits = 15; + png_ptr->zlib_method = 8; + +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED + png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY; + png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION; + png_ptr->zlib_text_mem_level = 8; + png_ptr->zlib_text_window_bits = 15; + png_ptr->zlib_text_method = 8; +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ + + /* This is a highly dubious configuration option; by default it is off, + * but it may be appropriate for private builds that are testing + * extensions not conformant to the current specification, or of + * applications that must not fail to write at all costs! + */ +#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + /* In stable builds only warn if an application error can be completely + * handled. + */ +#endif + + /* App warnings are warnings in release (or release candidate) builds but + * are errors during development. + */ +#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC + png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; +#endif + + /* TODO: delay this, it can be done in png_init_io() (if the app doesn't + * do it itself) avoiding setting the default function if it is not + * required. + */ + png_set_write_fn(png_ptr, NULL, NULL, NULL); + } + + return png_ptr; +} + + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* row counter */ + png_bytepp rp; /* row pointer */ + + png_debug(1, "in png_write_rows"); + + if (png_ptr == NULL) + return; + + /* Loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structrp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* row index */ + int pass, num_pass; /* pass variables */ + png_bytepp rp; /* points to current row */ + + if (png_ptr == NULL) + return; + + png_debug(1, "in png_write_image"); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Initialize interlace handling. If image is not interlaced, + * this will set pass to 1 + */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* Loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* Loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +/* Called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structrp png_ptr, png_const_bytep row) +{ + /* 1.5.6: moved from png_struct to be a local structure: */ + png_row_info row_info; + + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_write_row (row %u, pass %d)", + png_ptr->row_number, png_ptr->pass); + + /* Initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row"); + + /* Check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, + "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); +#endif + + png_write_start_row(png_ptr); + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + + default: /* error: ignore it */ + break; + } + } +#endif + + /* Set up row info for transformations */ + row_info.color_type = png_ptr->color_type; + row_info.width = png_ptr->usr_width; + row_info.channels = png_ptr->usr_channels; + row_info.bit_depth = png_ptr->usr_bit_depth; + row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels); + row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); + + png_debug1(3, "row_info->color_type = %d", row_info.color_type); + png_debug1(3, "row_info->width = %u", row_info.width); + png_debug1(3, "row_info->channels = %d", row_info.channels); + png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass); + /* This should always get caught above, but still ... */ + if (!(row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED + /* Handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr, &row_info); +#endif + + /* At this point the row_info pixel depth must match the 'transformed' depth, + * which is also the output depth. + */ + if (row_info.pixel_depth != png_ptr->pixel_depth || + row_info.pixel_depth != png_ptr->transformed_pixel_depth) + png_error(png_ptr, "internal write transform logic error"); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1); + } +#endif + +/* Added at libpng-1.5.10 */ +#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED + /* Check for out-of-range palette index */ + if (row_info.color_type == PNG_COLOR_TYPE_PALETTE && + png_ptr->num_palette_max >= 0) + png_do_check_palette_indexes(png_ptr, &row_info); +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &row_info); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structrp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush"); + + if (png_ptr == NULL) + return; + + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* Flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structrp png_ptr) +{ + png_debug(1, "in png_write_flush"); + + if (png_ptr == NULL) + return; + + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH); + png_ptr->flush_rows = 0; + png_flush(png_ptr); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +static void png_reset_filter_heuristics(png_structrp png_ptr);/* forward decl */ +#endif + +/* Free any memory used in png_ptr struct without freeing the struct itself. */ +static void +png_write_destroy(png_structrp png_ptr) +{ + png_debug(1, "in png_write_destroy"); + + /* Free any memory zlib uses */ + if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) + deflateEnd(&png_ptr->zstream); + + /* Free our memory. png_free checks NULL for us. */ + png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); + png_free(png_ptr, png_ptr->row_buf); +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + png_free(png_ptr, png_ptr->paeth_row); +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Use this to save a little code space, it doesn't free the filter_costs */ + png_reset_filter_heuristics(png_ptr); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + png_free(png_ptr, png_ptr->chunk_list); +#endif + + /* The error handling and memory handling information is left intact at this + * point: the jmp_buf may still have to be freed. See png_destroy_png_struct + * for how this happens. + */ +} + +/* Free all memory used by the write. + * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for + * *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free + * the passed in info_structs but it would quietly fail to free any of the data + * inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it + * has no png_ptr.) + */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_debug(1, "in png_destroy_write_struct"); + + if (png_ptr_ptr != NULL) + { + png_structrp png_ptr = *png_ptr_ptr; + + if (png_ptr != NULL) /* added in libpng 1.6.0 */ + { + png_destroy_info_struct(png_ptr, info_ptr_ptr); + + *png_ptr_ptr = NULL; + png_write_destroy(png_ptr); + png_destroy_png_struct(png_ptr); + } + } +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structrp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; + +#endif + if (method == PNG_FILTER_TYPE_BASE) + { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + case 5: + case 6: + case 7: png_app_error(png_ptr, "Unknown row filter for method 0"); + /* FALL THROUGH */ +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + case PNG_FILTER_VALUE_NONE: + png_ptr->do_filter = PNG_FILTER_NONE; break; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + case PNG_FILTER_VALUE_SUB: + png_ptr->do_filter = PNG_FILTER_SUB; break; + + case PNG_FILTER_VALUE_UP: + png_ptr->do_filter = PNG_FILTER_UP; break; + + case PNG_FILTER_VALUE_AVG: + png_ptr->do_filter = PNG_FILTER_AVG; break; + + case PNG_FILTER_VALUE_PAETH: + png_ptr->do_filter = PNG_FILTER_PAETH; break; + + default: + png_ptr->do_filter = (png_byte)filters; break; +#else + default: + png_app_error(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + } + + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + */ + if (png_ptr->row_buf != NULL) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter = (png_byte)(png_ptr->do_filter & + ~PNG_FILTER_UP); + } + + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter = (png_byte)(png_ptr->do_filter & + ~PNG_FILTER_AVG); + } + + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + + if (png_ptr->do_filter == PNG_NO_FILTERS) +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + png_ptr->do_filter = PNG_FILTER_NONE; + } + } + else + png_error(png_ptr, "Unknown custom filter method"); +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ +/* Convenience reset API. */ +static void +png_reset_filter_heuristics(png_structrp png_ptr) +{ + /* Clear out any old values in the 'weights' - this must be done because if + * the app calls set_filter_heuristics multiple times with different + * 'num_weights' values we would otherwise potentially have wrong sized + * arrays. + */ + png_ptr->num_prev_filters = 0; + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + if (png_ptr->prev_filters != NULL) + { + png_bytep old = png_ptr->prev_filters; + png_ptr->prev_filters = NULL; + png_free(png_ptr, old); + } + if (png_ptr->filter_weights != NULL) + { + png_uint_16p old = png_ptr->filter_weights; + png_ptr->filter_weights = NULL; + png_free(png_ptr, old); + } + + if (png_ptr->inv_filter_weights != NULL) + { + png_uint_16p old = png_ptr->inv_filter_weights; + png_ptr->inv_filter_weights = NULL; + png_free(png_ptr, old); + } + + /* Leave the filter_costs - this array is fixed size. */ +} + +static int +png_init_filter_heuristics(png_structrp png_ptr, int heuristic_method, + int num_weights) +{ + if (png_ptr == NULL) + return 0; + + /* Clear out the arrays */ + png_reset_filter_heuristics(png_ptr); + + /* Check arguments; the 'reset' function makes the correct settings for the + * unweighted case, but we must handle the weight case by initializing the + * arrays for the caller. + */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + + if (num_weights > 0) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)((sizeof (png_byte)) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)((sizeof (png_uint_16)) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)((sizeof (png_uint_16)) * num_weights)); + + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + /* Safe to set this now */ + png_ptr->num_prev_filters = (png_byte)num_weights; + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST)); + } + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + + /* All the arrays are inited, safe to set this: */ + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED; + + /* Return the 'ok' code. */ + return 1; + } + else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + return 1; + } + else + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return 0; + } +} + +/* Provide floating and fixed point APIs */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method, + int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5); + + png_ptr->filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5); + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5); + + png_ptr->filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5); + } + } +} +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method, + int num_weights, png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics_fixed"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + else + { + png_ptr->inv_filter_weights[i] = (png_uint_16) + ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1); + + png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR* + PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]); + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + if (filter_costs[i] >= PNG_FP_1) + { + png_uint_32 tmp; + + /* Use a 32 bit unsigned temporary here because otherwise the + * intermediate value will be a 32 bit *signed* integer (ANSI rules) + * and this will get the wrong answer on division. + */ + tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2); + tmp /= filter_costs[i]; + + png_ptr->inv_filter_costs[i] = (png_uint_16)tmp; + + tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF; + tmp /= PNG_FP_1; + + png_ptr->filter_costs[i] = (png_uint_16)tmp; + } + } +} +#endif /* FIXED_POINT */ +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structrp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structrp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structrp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy"); + + if (png_ptr == NULL) + return; + + /* The flag setting here prevents the libpng dynamic selection of strategy. + */ + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +void PNGAPI +png_set_compression_window_bits(png_structrp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + + /* Prior to 1.6.0 this would warn but then set the window_bits value, this + * meant that negative window bits values could be selected which would cause + * libpng to write a non-standard PNG file with raw deflate or gzip + * compressed IDAT or ancillary chunks. Such files can be read and there is + * no warning on read, so this seems like a very bad idea. + */ + if (window_bits > 15) + { + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + window_bits = 15; + } + + else if (window_bits < 8) + { + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); + window_bits = 8; + } + + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structrp png_ptr, int method) +{ + png_debug(1, "in png_set_compression_method"); + + if (png_ptr == NULL) + return; + + /* This would produce an invalid PNG file if it worked, but it doesn't and + * deflate will fault it, so it is harmless to just warn here. + */ + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + + png_ptr->zlib_method = method; +} + +/* The following were added to libpng-1.5.4 */ +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +void PNGAPI +png_set_text_compression_level(png_structrp png_ptr, int level) +{ + png_debug(1, "in png_set_text_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->zlib_text_level = level; +} + +void PNGAPI +png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_text_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->zlib_text_mem_level = mem_level; +} + +void PNGAPI +png_set_text_compression_strategy(png_structrp png_ptr, int strategy) +{ + png_debug(1, "in png_set_text_compression_strategy"); + + if (png_ptr == NULL) + return; + + png_ptr->zlib_text_strategy = strategy; +} + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +void PNGAPI +png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + + if (window_bits > 15) + { + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + window_bits = 15; + } + + else if (window_bits < 8) + { + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); + window_bits = 8; + } + + png_ptr->zlib_text_window_bits = window_bits; +} + +void PNGAPI +png_set_text_compression_method(png_structrp png_ptr, int method) +{ + png_debug(1, "in png_set_text_compression_method"); + + if (png_ptr == NULL) + return; + + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + + png_ptr->zlib_text_method = method; +} +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ +/* end of API added to libpng-1.5.4 */ + +void PNGAPI +png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->write_row_fn = write_row_fn; +} + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +void PNGAPI +png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_write_png(png_structrp png_ptr, png_inforp info_ptr, + int transforms, voidp params) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + +#ifdef PNG_WRITE_INVERT_SUPPORTED + /* Invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + /* Pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + /* Swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + /* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */ + if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + + else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + /* Flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + /* Swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* Write the bits */ + if (info_ptr->valid & PNG_INFO_IDAT) + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + PNG_UNUSED(transforms) /* Quiet compiler warnings */ + PNG_UNUSED(params) +} +#endif + + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +#ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */ +/* Initialize the write structure - general purpose utility. */ +static int +png_image_write_init(png_imagep image) +{ + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image, + png_safe_error, png_safe_warning); + + if (png_ptr != NULL) + { + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (info_ptr != NULL) + { + png_controlp control = png_voidcast(png_controlp, + png_malloc_warn(png_ptr, (sizeof *control))); + + if (control != NULL) + { + memset(control, 0, (sizeof *control)); + + control->png_ptr = png_ptr; + control->info_ptr = info_ptr; + control->for_write = 1; + + image->opaque = control; + return 1; + } + + /* Error clean up */ + png_destroy_info_struct(png_ptr, &info_ptr); + } + + png_destroy_write_struct(&png_ptr, NULL); + } + + return png_image_error(image, "png_image_write_: out of memory"); +} + +/* Arguments to png_image_write_main: */ +typedef struct +{ + /* Arguments: */ + png_imagep image; + png_const_voidp buffer; + png_int_32 row_stride; + png_const_voidp colormap; + int convert_to_8bit; + /* Local variables: */ + png_const_voidp first_row; + ptrdiff_t row_bytes; + png_voidp local_row; +} png_image_write_control; + +/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to + * do any necessary byte swapping. The component order is defined by the + * png_image format value. + */ +static int +png_write_image_16bit(png_voidp argument) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + + png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, + display->first_row); + png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); + png_uint_16p row_end; + const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; + int aindex = 0; + png_uint_32 y = image->height; + + if (image->format & PNG_FORMAT_FLAG_ALPHA) + { + if (image->format & PNG_FORMAT_FLAG_AFIRST) + { + aindex = -1; + ++input_row; /* To point to the first component */ + ++output_row; + } + + else + aindex = channels; + } + + else + png_error(png_ptr, "png_write_image: internal call error"); + + /* Work out the output row end and count over this, note that the increment + * above to 'row' means that row_end can actually be beyond the end of the + * row; this is correct. + */ + row_end = output_row + image->width * (channels+1); + + while (y-- > 0) + { + png_const_uint_16p in_ptr = input_row; + png_uint_16p out_ptr = output_row; + + while (out_ptr < row_end) + { + const png_uint_16 alpha = in_ptr[aindex]; + png_uint_32 reciprocal = 0; + int c; + + out_ptr[aindex] = alpha; + + /* Calculate a reciprocal. The correct calculation is simply + * component/alpha*65535 << 15. (I.e. 15 bits of precision); this + * allows correct rounding by adding .5 before the shift. 'reciprocal' + * is only initialized when required. + */ + if (alpha > 0 && alpha < 65535) + reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; + + c = channels; + do /* always at least one channel */ + { + png_uint_16 component = *in_ptr++; + + /* The following gives 65535 for an alpha of 0, which is fine, + * otherwise if 0/0 is represented as some other value there is more + * likely to be a discontinuity which will probably damage + * compression when moving from a fully transparent area to a + * nearly transparent one. (The assumption here is that opaque + * areas tend not to be 0 intensity.) + */ + if (component >= alpha) + component = 65535; + + /* component 0 && alpha < 65535) + { + png_uint_32 calc = component * reciprocal; + calc += 16384; /* round to nearest */ + component = (png_uint_16)(calc >> 15); + } + + *out_ptr++ = component; + } + while (--c > 0); + + /* Skip to next component (skip the intervening alpha channel) */ + ++in_ptr; + ++out_ptr; + } + + png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); + input_row += display->row_bytes/(sizeof (png_uint_16)); + } + + return 1; +} + +/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel + * is present it must be removed from the components, the components are then + * written in sRGB encoding. No components are added or removed. + * + * Calculate an alpha reciprocal to reverse pre-multiplication. As above the + * calculation can be done to 15 bits of accuracy; however, the output needs to + * be scaled in the range 0..255*65535, so include that scaling here. + */ +#define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) + +static png_byte +png_unpremultiply(png_uint_32 component, png_uint_32 alpha, + png_uint_32 reciprocal/*from the above macro*/) +{ + /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0 + * is represented as some other value there is more likely to be a + * discontinuity which will probably damage compression when moving from a + * fully transparent area to a nearly transparent one. (The assumption here + * is that opaque areas tend not to be 0 intensity.) + * + * There is a rounding problem here; if alpha is less than 128 it will end up + * as 0 when scaled to 8 bits. To avoid introducing spurious colors into the + * output change for this too. + */ + if (component >= alpha || alpha < 128) + return 255; + + /* component 0) + { + /* The test is that alpha/257 (rounded) is less than 255, the first value + * that becomes 255 is 65407. + * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore, + * be exact!) [Could also test reciprocal != 0] + */ + if (alpha < 65407) + { + component *= reciprocal; + component += 64; /* round to nearest */ + component >>= 7; + } + + else + component *= 255; + + /* Convert the component to sRGB. */ + return (png_byte)PNG_sRGB_FROM_LINEAR(component); + } + + else + return 0; +} + +static int +png_write_image_8bit(png_voidp argument) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + + png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, + display->first_row); + png_bytep output_row = png_voidcast(png_bytep, display->local_row); + png_uint_32 y = image->height; + const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; + + if (image->format & PNG_FORMAT_FLAG_ALPHA) + { + png_bytep row_end; + int aindex; + + if (image->format & PNG_FORMAT_FLAG_AFIRST) + { + aindex = -1; + ++input_row; /* To point to the first component */ + ++output_row; + } + + else + aindex = channels; + + /* Use row_end in place of a loop counter: */ + row_end = output_row + image->width * (channels+1); + + while (y-- > 0) + { + png_const_uint_16p in_ptr = input_row; + png_bytep out_ptr = output_row; + + while (out_ptr < row_end) + { + png_uint_16 alpha = in_ptr[aindex]; + png_byte alphabyte = (png_byte)PNG_DIV257(alpha); + png_uint_32 reciprocal = 0; + int c; + + /* Scale and write the alpha channel. */ + out_ptr[aindex] = alphabyte; + + if (alphabyte > 0 && alphabyte < 255) + reciprocal = UNP_RECIPROCAL(alpha); + + c = channels; + do /* always at least one channel */ + *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); + while (--c > 0); + + /* Skip to next component (skip the intervening alpha channel) */ + ++in_ptr; + ++out_ptr; + } /* while out_ptr < row_end */ + + png_write_row(png_ptr, png_voidcast(png_const_bytep, + display->local_row)); + input_row += display->row_bytes/(sizeof (png_uint_16)); + } /* while y */ + } + + else + { + /* No alpha channel, so the row_end really is the end of the row and it + * is sufficient to loop over the components one by one. + */ + png_bytep row_end = output_row + image->width * channels; + + while (y-- > 0) + { + png_const_uint_16p in_ptr = input_row; + png_bytep out_ptr = output_row; + + while (out_ptr < row_end) + { + png_uint_32 component = *in_ptr++; + + component *= 255; + *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component); + } + + png_write_row(png_ptr, output_row); + input_row += display->row_bytes/(sizeof (png_uint_16)); + } + } + + return 1; +} + +static void +png_image_set_PLTE(png_image_write_control *display) +{ + const png_imagep image = display->image; + const void *cmap = display->colormap; + const int entries = image->colormap_entries > 256 ? 256 : + (int)image->colormap_entries; + + /* NOTE: the caller must check for cmap != NULL and entries != 0 */ + const png_uint_32 format = image->format; + const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); + +# ifdef PNG_FORMAT_BGR_SUPPORTED + const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && + (format & PNG_FORMAT_FLAG_ALPHA) != 0; +# else +# define afirst 0 +# endif + +# ifdef PNG_FORMAT_BGR_SUPPORTED + const int bgr = (format & PNG_FORMAT_FLAG_BGR) ? 2 : 0; +# else +# define bgr 0 +# endif + + int i, num_trans; + png_color palette[256]; + png_byte tRNS[256]; + + memset(tRNS, 255, (sizeof tRNS)); + memset(palette, 0, (sizeof palette)); + + for (i=num_trans=0; i= 3) /* RGB */ + { + palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 * + entry[(2 ^ bgr)]); + palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 * + entry[1]); + palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 * + entry[bgr]); + } + + else /* Gray */ + palette[i].blue = palette[i].red = palette[i].green = + (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry); + } + + else /* alpha */ + { + png_uint_16 alpha = entry[afirst ? 0 : channels-1]; + png_byte alphabyte = (png_byte)PNG_DIV257(alpha); + png_uint_32 reciprocal = 0; + + /* Calculate a reciprocal, as in the png_write_image_8bit code above + * this is designed to produce a value scaled to 255*65535 when + * divided by 128 (i.e. asr 7). + */ + if (alphabyte > 0 && alphabyte < 255) + reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha; + + tRNS[i] = alphabyte; + if (alphabyte < 255) + num_trans = i+1; + + if (channels >= 3) /* RGB */ + { + palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)], + alpha, reciprocal); + palette[i].green = png_unpremultiply(entry[afirst + 1], alpha, + reciprocal); + palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha, + reciprocal); + } + + else /* gray */ + palette[i].blue = palette[i].red = palette[i].green = + png_unpremultiply(entry[afirst], alpha, reciprocal); + } + } + + else /* Color-map has sRGB values */ + { + png_const_bytep entry = png_voidcast(png_const_bytep, cmap); + + entry += i * channels; + + switch (channels) + { + case 4: + tRNS[i] = entry[afirst ? 0 : 3]; + if (tRNS[i] < 255) + num_trans = i+1; + /* FALL THROUGH */ + case 3: + palette[i].blue = entry[afirst + (2 ^ bgr)]; + palette[i].green = entry[afirst + 1]; + palette[i].red = entry[afirst + bgr]; + break; + + case 2: + tRNS[i] = entry[1 ^ afirst]; + if (tRNS[i] < 255) + num_trans = i+1; + /* FALL THROUGH */ + case 1: + palette[i].blue = palette[i].red = palette[i].green = + entry[afirst]; + break; + + default: + break; + } + } + } + +# ifdef afirst +# undef afirst +# endif +# ifdef bgr +# undef bgr +# endif + + png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette, + entries); + + if (num_trans > 0) + png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS, + num_trans, NULL); + + image->colormap_entries = entries; +} + +static int +png_image_write_main(png_voidp argument) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + png_inforp info_ptr = image->opaque->info_ptr; + png_uint_32 format = image->format; + + int colormap = (format & PNG_FORMAT_FLAG_COLORMAP) != 0; + int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */ + int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0; + int write_16bit = linear && !colormap && !display->convert_to_8bit; + +# ifdef PNG_BENIGN_ERRORS_SUPPORTED + /* Make sure we error out on any bad situation */ + png_set_benign_errors(png_ptr, 0/*error*/); +# endif + + /* Default the 'row_stride' parameter if required. */ + if (display->row_stride == 0) + display->row_stride = PNG_IMAGE_ROW_STRIDE(*image); + + /* Set the required transforms then write the rows in the correct order. */ + if (format & PNG_FORMAT_FLAG_COLORMAP) + { + if (display->colormap != NULL && image->colormap_entries > 0) + { + png_uint_32 entries = image->colormap_entries; + + png_set_IHDR(png_ptr, info_ptr, image->width, image->height, + entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)), + PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_image_set_PLTE(display); + } + + else + png_error(image->opaque->png_ptr, + "no color-map for color-mapped image"); + } + + else + png_set_IHDR(png_ptr, info_ptr, image->width, image->height, + write_16bit ? 16 : 8, + ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + + ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* Counter-intuitively the data transformations must be called *after* + * png_write_info, not before as in the read code, but the 'set' functions + * must still be called before. Just set the color space information, never + * write an interlaced image. + */ + + if (write_16bit) + { + /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */ + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR); + + if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB)) + png_set_cHRM_fixed(png_ptr, info_ptr, + /* color x y */ + /* white */ 31270, 32900, + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000 + ); + } + + else if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB)) + png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL); + + /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit + * space must still be gamma encoded. + */ + else + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); + + /* Write the file header. */ + png_write_info(png_ptr, info_ptr); + + /* Now set up the data transformations (*after* the header is written), + * remove the handled transformations from the 'format' flags for checking. + * + * First check for a little endian system if writing 16 bit files. + */ + if (write_16bit) + { + PNG_CONST png_uint_16 le = 0x0001; + + if (*(png_const_bytep)&le) + png_set_swap(png_ptr); + } + +# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED + if (format & PNG_FORMAT_FLAG_BGR) + { + if (!colormap && (format & PNG_FORMAT_FLAG_COLOR) != 0) + png_set_bgr(png_ptr); + format &= ~PNG_FORMAT_FLAG_BGR; + } +# endif + +# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + { + if (!colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0) + png_set_swap_alpha(png_ptr); + format &= ~PNG_FORMAT_FLAG_AFIRST; + } +# endif + + /* If there are 16 or fewer color-map entries we wrote a lower bit depth + * above, but the application data is still byte packed. + */ + if (colormap && image->colormap_entries <= 16) + png_set_packing(png_ptr); + + /* That should have handled all (both) the transforms. */ + if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR | + PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0) + png_error(png_ptr, "png_write_image: unsupported transformation"); + + { + png_const_bytep row = png_voidcast(png_const_bytep, display->buffer); + ptrdiff_t row_bytes = display->row_stride; + + if (linear) + row_bytes *= (sizeof (png_uint_16)); + + if (row_bytes < 0) + row += (image->height-1) * (-row_bytes); + + display->first_row = row; + display->row_bytes = row_bytes; + } + + /* Apply 'fast' options if the flag is set. */ + if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0) + { + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS); + /* NOTE: determined by experiment using pngstest, this reflects some + * balance between the time to write the image once and the time to read + * it about 50 times. The speed-up in pngstest was about 10-20% of the + * total (user) time on a heavily loaded system. + */ + png_set_compression_level(png_ptr, 3); + } + + /* Check for the cases that currently require a pre-transform on the row + * before it is written. This only applies when the input is 16-bit and + * either there is an alpha channel or it is converted to 8-bit. + */ + if ((linear && alpha) || (!colormap && display->convert_to_8bit)) + { + png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr))); + int result; + + display->local_row = row; + if (write_16bit) + result = png_safe_execute(image, png_write_image_16bit, display); + else + result = png_safe_execute(image, png_write_image_8bit, display); + display->local_row = NULL; + + png_free(png_ptr, row); + + /* Skip the 'write_end' on error: */ + if (!result) + return 0; + } + + /* Otherwise this is the case where the input is in a format currently + * supported by the rest of the libpng write code; call it directly. + */ + else + { + png_const_bytep row = png_voidcast(png_const_bytep, display->first_row); + ptrdiff_t row_bytes = display->row_bytes; + png_uint_32 y = image->height; + + while (y-- > 0) + { + png_write_row(png_ptr, row); + row += row_bytes; + } + } + + png_write_end(png_ptr, info_ptr); + return 1; +} + +int PNGAPI +png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, + const void *buffer, png_int_32 row_stride, const void *colormap) +{ + /* Write the image to the given (FILE*). */ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (file != NULL) + { + if (png_image_write_init(image)) + { + png_image_write_control display; + int result; + + /* This is slightly evil, but png_init_io doesn't do anything other + * than this and we haven't changed the standard IO functions so + * this saves a 'safe' function. + */ + image->opaque->png_ptr->io_ptr = file; + + memset(&display, 0, (sizeof display)); + display.image = image; + display.buffer = buffer; + display.row_stride = row_stride; + display.colormap = colormap; + display.convert_to_8bit = convert_to_8bit; + + result = png_safe_execute(image, png_image_write_main, &display); + png_image_free(image); + return result; + } + + else + return 0; + } + + else + return png_image_error(image, + "png_image_write_to_stdio: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); + + else + return 0; +} + +int PNGAPI +png_image_write_to_file(png_imagep image, const char *file_name, + int convert_to_8bit, const void *buffer, png_int_32 row_stride, + const void *colormap) +{ + /* Write the image to the named file. */ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (file_name != NULL) + { + FILE *fp = fopen(file_name, "wb"); + + if (fp != NULL) + { + if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, + row_stride, colormap)) + { + int error; /* from fflush/fclose */ + + /* Make sure the file is flushed correctly. */ + if (fflush(fp) == 0 && ferror(fp) == 0) + { + if (fclose(fp) == 0) + return 1; + + error = errno; /* from fclose */ + } + + else + { + error = errno; /* from fflush or ferror */ + (void)fclose(fp); + } + + (void)remove(file_name); + /* The image has already been cleaned up; this is just used to + * set the error (because the original write succeeded). + */ + return png_image_error(image, strerror(error)); + } + + else + { + /* Clean up: just the opened file. */ + (void)fclose(fp); + (void)remove(file_name); + return 0; + } + } + + else + return png_image_error(image, strerror(errno)); + } + + else + return png_image_error(image, + "png_image_write_to_file: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); + + else + return 0; +} +#endif /* PNG_STDIO_SUPPORTED */ +#endif /* SIMPLIFIED_WRITE */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngwtran.c b/ext/libpng16/pngwtran.c new file mode 100644 index 0000000000..2cdd7c95c2 --- /dev/null +++ b/ext/libpng16/pngwtran.c @@ -0,0 +1,637 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * Last changed in libpng 1.6.0 [February 14, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) +{ + png_debug(1, "in png_do_write_transformations"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if (png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* User write transform + function */ + (png_ptr, /* png_ptr */ + row_info, /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_channel(row_info, png_ptr->row_buf + 1, + !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_pack(row_info, png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(row_info, png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(row_info, png_ptr->row_buf + 1); +#endif +} + +#ifdef PNG_WRITE_PACK_SUPPORTED +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +void /* PRIVATE */ +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack"); + + if (row_info->bit_depth == 8 && + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + + sp++; + + if (mask > 1) + mask >>= 1; + + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + + if (mask != 0x80) + *dp = (png_byte)v; + + break; + } + + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + + else + shift -= 2; + + sp++; + } + + if (shift != 6) + *dp = (png_byte)v; + + break; + } + + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + + else + shift -= 4; + + sp++; + } + + if (shift != 4) + *dp = (png_byte)v; + + break; + } + + default: + break; + } + + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +void /* PRIVATE */ +png_do_shift(png_row_infop row_info, png_bytep row, + png_const_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift"); + + if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* With low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_size_t i; + unsigned int mask; + png_size_t row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + int j; + unsigned int v, out; + + v = *bp; + out = 0; + + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + out |= v << j; + + else + out |= (v >> (-j)) & mask; + } + + *bp = (png_byte)(out & 0xff); + } + } + + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + const unsigned int c = i%channels; + int j; + unsigned int v, out; + + v = *bp; + out = 0; + + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + out |= v << j; + + else + out |= v >> (-j); + } + + *bp = (png_byte)(out & 0xff); + } + } + + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + const unsigned int c = i%channels; + int j; + unsigned int value, v; + + v = png_get_uint_16(bp); + value = 0; + + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= v << j; + + else + value |= v >> (-j); + } + *bp++ = (png_byte)((value >> 8) & 0xff); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from ARGB to RGBA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AARRGGBB to RRGGBBAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from AG to GA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AAGG to GGAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=3; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in RRGGBBAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=6; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=2; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel"); + + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp + 1)) & 0xff); + *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngwutil.c b/ext/libpng16/pngwutil.c new file mode 100644 index 0000000000..88dd0c9d4b --- /dev/null +++ b/ext/libpng16/pngwutil.c @@ -0,0 +1,3023 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * Last changed in libpng 1.6.2 [April 25, 2013] + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void PNGAPI +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void PNGAPI +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} +#endif + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void PNGAPI +png_write_sig(png_structrp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the signature is being written */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; +#endif + + /* Write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)(8 - png_ptr->sig_bytes)); + + if (png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +static void +png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name, + png_uint_32 length) +{ + png_byte buf[8]; + +#if defined(PNG_DEBUG) && (PNG_DEBUG > 0) + PNG_CSTRING_FROM_CHUNK(buf, chunk_name); + png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length); +#endif + + if (png_ptr == NULL) + return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk header is being written. + * PNG_IO_CHUNK_HDR requires a single I/O call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; +#endif + + /* Write the length and the chunk name */ + png_save_uint_32(buf, length); + png_save_uint_32(buf + 4, chunk_name); + png_write_data(png_ptr, buf, 8); + + /* Put the chunk name into png_ptr->chunk_name */ + png_ptr->chunk_name = chunk_name; + + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + + png_calculate_crc(png_ptr, buf + 4, 4); + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that chunk data will (possibly) be written. + * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; +#endif +} + +void PNGAPI +png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, + png_uint_32 length) +{ + png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length); +} + +/* Write the data of a PNG chunk started with png_write_chunk_header(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_header(). + */ +void PNGAPI +png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, + png_size_t length) +{ + /* Write the data, and run the CRC over it */ + if (png_ptr == NULL) + return; + + if (data != NULL && length > 0) + { + png_write_data(png_ptr, data, length); + + /* Update the CRC after writing the data, + * in case that the user I/O routine alters it. + */ + png_calculate_crc(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_header(). */ +void PNGAPI +png_write_chunk_end(png_structrp png_ptr) +{ + png_byte buf[4]; + + if (png_ptr == NULL) return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk CRC is being written. + * PNG_IO_CHUNK_CRC requires a single I/O function call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; +#endif + + /* Write the crc in a single operation */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +static void +png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, + png_const_bytep data, png_size_t length) +{ + if (png_ptr == NULL) + return; + + /* On 64 bit architectures 'length' may not fit in a png_uint_32. */ + if (length > PNG_UINT_31_MAX) + png_error(png_ptr, "length exceeds PNG maxima"); + + png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, length); + png_write_chunk_end(png_ptr); +} + +/* This is the API that calls the internal function above. */ +void PNGAPI +png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, + png_const_bytep data, png_size_t length) +{ + png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, + length); +} + +/* This is used below to find the size of an image to pass to png_deflate_claim, + * so it only needs to be accurate if the size is less than 16384 bytes (the + * point at which a lower LZ window size can be used.) + */ +static png_alloc_size_t +png_image_size(png_structrp png_ptr) +{ + /* Only return sizes up to the maximum of a png_uint_32, do this by limiting + * the width and height used to 15 bits. + */ + png_uint_32 h = png_ptr->height; + + if (png_ptr->rowbytes < 32768 && h < 32768) + { + if (png_ptr->interlaced) + { + /* Interlacing makes the image larger because of the replication of + * both the filter byte and the padding to a byte boundary. + */ + png_uint_32 w = png_ptr->width; + unsigned int pd = png_ptr->pixel_depth; + png_alloc_size_t cb_base; + int pass; + + for (cb_base=0, pass=0; pass<=6; ++pass) + { + png_uint_32 pw = PNG_PASS_COLS(w, pass); + + if (pw > 0) + cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass); + } + + return cb_base; + } + + else + return (png_ptr->rowbytes+1) * h; + } + + else + return 0xffffffffU; +} + +#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + /* This is the code to hack the first two bytes of the deflate stream (the + * deflate header) to correct the windowBits value to match the actual data + * size. Note that the second argument is the *uncompressed* size but the + * first argument is the *compressed* data (and it must be deflate + * compressed.) + */ +static void +optimize_cmf(png_bytep data, png_alloc_size_t data_size) +{ + /* Optimize the CMF field in the zlib stream. The resultant zlib stream is + * still compliant to the stream specification. + */ + if (data_size <= 16384) /* else windowBits must be 15 */ + { + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + unsigned int z_cinfo; + unsigned int half_z_window_size; + + z_cinfo = z_cmf >> 4; + half_z_window_size = 1U << (z_cinfo + 7); + + if (data_size <= half_z_window_size) /* else no change */ + { + unsigned int tmp; + + do + { + half_z_window_size >>= 1; + --z_cinfo; + } + while (z_cinfo > 0 && data_size <= half_z_window_size); + + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + + data[0] = (png_byte)z_cmf; + tmp = data[1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + data[1] = (png_byte)tmp; + } + } + } +} +#else +# define optimize_cmf(dp,dl) ((void)0) +#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ + +/* Initialize the compressor for the appropriate type of compression. */ +static int +png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, + png_alloc_size_t data_size) +{ + if (png_ptr->zowner != 0) + { + char msg[64]; + + PNG_STRING_FROM_CHUNK(msg, owner); + msg[4] = ':'; + msg[5] = ' '; + PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner); + /* So the message that results is " using zstream"; this is an + * internal error, but is very useful for debugging. i18n requirements + * are minimal. + */ + (void)png_safecat(msg, (sizeof msg), 10, " using zstream"); +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC + png_warning(png_ptr, msg); + + /* Attempt sane error recovery */ + if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */ + { + png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT"); + return Z_STREAM_ERROR; + } + + png_ptr->zowner = 0; +# else + png_error(png_ptr, msg); +# endif + } + + { + int level = png_ptr->zlib_level; + int method = png_ptr->zlib_method; + int windowBits = png_ptr->zlib_window_bits; + int memLevel = png_ptr->zlib_mem_level; + int strategy; /* set below */ + int ret; /* zlib return code */ + + if (owner == png_IDAT) + { + if (png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) + strategy = png_ptr->zlib_strategy; + + else if (png_ptr->do_filter != PNG_FILTER_NONE) + strategy = PNG_Z_DEFAULT_STRATEGY; + + else + strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY; + } + + else + { +# ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + level = png_ptr->zlib_text_level; + method = png_ptr->zlib_text_method; + windowBits = png_ptr->zlib_text_window_bits; + memLevel = png_ptr->zlib_text_mem_level; + strategy = png_ptr->zlib_text_strategy; +# else + /* If customization is not supported the values all come from the + * IDAT values except for the strategy, which is fixed to the + * default. (This is the pre-1.6.0 behavior too, although it was + * implemented in a very different way.) + */ + strategy = Z_DEFAULT_STRATEGY; +# endif + } + + /* Adjust 'windowBits' down if larger than 'data_size'; to stop this + * happening just pass 32768 as the data_size parameter. Notice that zlib + * requires an extra 262 bytes in the window in addition to the data to be + * able to see the whole of the data, so if data_size+262 takes us to the + * next windowBits size we need to fix up the value later. (Because even + * though deflate needs the extra window, inflate does not!) + */ + if (data_size <= 16384) + { + /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to + * work round a Microsoft Visual C misbehavior which, contrary to C-90, + * widens the result of the following shift to 64-bits if (and, + * apparently, only if) it is used in a test. + */ + unsigned int half_window_size = 1U << (windowBits-1); + + while (data_size + 262 <= half_window_size) + { + half_window_size >>= 1; + --windowBits; + } + } + + /* Check against the previous initialized values, if any. */ + if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) && + (png_ptr->zlib_set_level != level || + png_ptr->zlib_set_method != method || + png_ptr->zlib_set_window_bits != windowBits || + png_ptr->zlib_set_mem_level != memLevel || + png_ptr->zlib_set_strategy != strategy)) + { + if (deflateEnd(&png_ptr->zstream) != Z_OK) + png_warning(png_ptr, "deflateEnd failed (ignored)"); + + png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED; + } + + /* For safety clear out the input and output pointers (currently zlib + * doesn't use them on Init, but it might in the future). + */ + png_ptr->zstream.next_in = NULL; + png_ptr->zstream.avail_in = 0; + png_ptr->zstream.next_out = NULL; + png_ptr->zstream.avail_out = 0; + + /* Now initialize if required, setting the new parameters, otherwise just + * to a simple reset to the previous parameters. + */ + if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) + ret = deflateReset(&png_ptr->zstream); + + else + { + ret = deflateInit2(&png_ptr->zstream, level, method, windowBits, + memLevel, strategy); + + if (ret == Z_OK) + png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; + } + + /* The return code is from either deflateReset or deflateInit2; they have + * pretty much the same set of error codes. + */ + if (ret == Z_OK) + png_ptr->zowner = owner; + + else + png_zstream_error(png_ptr, ret); + + return ret; + } +} + +/* Clean up (or trim) a linked list of compression buffers. */ +void /* PRIVATE */ +png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp) +{ + png_compression_bufferp list = *listp; + + if (list != NULL) + { + *listp = NULL; + + do + { + png_compression_bufferp next = list->next; + + png_free(png_ptr, list); + list = next; + } + while (list != NULL); + } +} + +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +/* This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller to allow access to the relevant local variables. + * + * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size + * temporary buffers. From 1.6.0 it is retained in png_struct so that it will + * be correctly freed in the event of a write error (previous implementations + * just leaked memory.) + */ +typedef struct +{ + png_const_bytep input; /* The uncompressed input data */ + png_alloc_size_t input_len; /* Its length */ + png_uint_32 output_len; /* Final compressed length */ + png_byte output[1024]; /* First block of output */ +} compression_state; + +static void +png_text_compress_init(compression_state *comp, png_const_bytep input, + png_alloc_size_t input_len) +{ + comp->input = input; + comp->input_len = input_len; + comp->output_len = 0; +} + +/* Compress the data in the compression state input */ +static int +png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, + compression_state *comp, png_uint_32 prefix_len) +{ + int ret; + + /* To find the length of the output it is necessary to first compress the + * input, the result is buffered rather than using the two-pass algorithm + * that is used on the inflate side; deflate is assumed to be slower and a + * PNG writer is assumed to have more memory available than a PNG reader. + * + * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an + * upper limit on the output size, but it is always bigger than the input + * size so it is likely to be more efficient to use this linked-list + * approach. + */ + ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len); + + if (ret != Z_OK) + return ret; + + /* Set up the compression buffers, we need a loop here to avoid overflowing a + * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited + * by the output buffer size, so there is no need to check that. Since this + * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits + * in size. + */ + { + png_compression_bufferp *end = &png_ptr->zbuffer_list; + png_alloc_size_t input_len = comp->input_len; /* may be zero! */ + png_uint_32 output_len; + + /* zlib updates these for us: */ + png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input); + png_ptr->zstream.avail_in = 0; /* Set below */ + png_ptr->zstream.next_out = comp->output; + png_ptr->zstream.avail_out = (sizeof comp->output); + + output_len = png_ptr->zstream.avail_out; + + do + { + uInt avail_in = ZLIB_IO_MAX; + + if (avail_in > input_len) + avail_in = (uInt)input_len; + + input_len -= avail_in; + + png_ptr->zstream.avail_in = avail_in; + + if (png_ptr->zstream.avail_out == 0) + { + png_compression_buffer *next; + + /* Chunk data is limited to 2^31 bytes in length, so the prefix + * length must be counted here. + */ + if (output_len + prefix_len > PNG_UINT_31_MAX) + { + ret = Z_MEM_ERROR; + break; + } + + /* Need a new (malloc'ed) buffer, but there may be one present + * already. + */ + next = *end; + if (next == NULL) + { + next = png_voidcast(png_compression_bufferp, png_malloc_base + (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); + + if (next == NULL) + { + ret = Z_MEM_ERROR; + break; + } + + /* Link in this buffer (so that it will be freed later) */ + next->next = NULL; + *end = next; + } + + png_ptr->zstream.next_out = next->output; + png_ptr->zstream.avail_out = png_ptr->zbuffer_size; + output_len += png_ptr->zstream.avail_out; + + /* Move 'end' to the next buffer pointer. */ + end = &next->next; + } + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, + input_len > 0 ? Z_NO_FLUSH : Z_FINISH); + + /* Claw back input data that was not consumed (because avail_in is + * reset above every time round the loop). + */ + input_len += png_ptr->zstream.avail_in; + png_ptr->zstream.avail_in = 0; /* safety */ + } + while (ret == Z_OK); + + /* There may be some space left in the last output buffer, this needs to + * be subtracted from output_len. + */ + output_len -= png_ptr->zstream.avail_out; + png_ptr->zstream.avail_out = 0; /* safety */ + comp->output_len = output_len; + + /* Now double check the output length, put in a custom message if it is + * too long. Otherwise ensure the z_stream::msg pointer is set to + * something. + */ + if (output_len + prefix_len >= PNG_UINT_31_MAX) + { + png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long"); + ret = Z_MEM_ERROR; + } + + else + png_zstream_error(png_ptr, ret); + + /* Reset zlib for another zTXt/iTXt or image data */ + png_ptr->zowner = 0; + + /* The only success case is Z_STREAM_END, input_len must be 0, if not this + * is an internal error. + */ + if (ret == Z_STREAM_END && input_len == 0) + { + /* Fix up the deflate header, if required */ + optimize_cmf(comp->output, comp->input_len); + + /* But Z_OK is returned, not Z_STREAM_END; this allows the claim + * function above to return Z_STREAM_END on an error (though it never + * does in the current versions of zlib.) + */ + return Z_OK; + } + + else + return ret; + } +} + +/* Ship the compressed text out via chunk writes */ +static void +png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp) +{ + png_uint_32 output_len = comp->output_len; + png_const_bytep output = comp->output; + png_uint_32 avail = (sizeof comp->output); + png_compression_buffer *next = png_ptr->zbuffer_list; + + for (;;) + { + if (avail > output_len) + avail = output_len; + + png_write_chunk_data(png_ptr, output, avail); + + output_len -= avail; + + if (output_len == 0 || next == NULL) + break; + + avail = png_ptr->zbuffer_size; + output = next->output; + next = next->next; + } + + /* This is an internal error; 'next' must have been NULL! */ + if (output_len > 0) + png_error(png_ptr, "error writing ancillary chunked compressed data"); +} +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The 'new_key' buffer must be 80 characters in size (for the keyword plus a + * trailing '\0'). If this routine returns 0 then there was no keyword, or a + * valid one could not be generated, and the caller must png_error. + */ +static png_uint_32 +png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) +{ + png_const_charp orig_key = key; + png_uint_32 key_len = 0; + int bad_character = 0; + int space = 1; + + png_debug(1, "in png_check_keyword"); + + if (key == NULL) + { + *new_key = 0; + return 0; + } + + while (*key && key_len < 79) + { + png_byte ch = (png_byte)(0xff & *key++); + + if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) + *new_key++ = ch, ++key_len, space = 0; + + else if (!space) + { + /* A space or an invalid character when one wasn't seen immediately + * before; output just a space. + */ + *new_key++ = 32, ++key_len, space = 1; + + /* If the character was not a space then it is invalid. */ + if (ch != 32) + bad_character = ch; + } + + else if (!bad_character) + bad_character = ch; /* just skip it, record the first error */ + } + + if (key_len > 0 && space) /* trailing space */ + { + --key_len, --new_key; + if (!bad_character) + bad_character = 32; + } + + /* Terminate the keyword */ + *new_key = 0; + + if (key_len == 0) + return 0; + + /* Try to only output one warning per keyword: */ + if (*key) /* keyword too long */ + png_warning(png_ptr, "keyword truncated"); + + else if (bad_character) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter(p, 1, orig_key); + png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character); + + png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'"); + } + + return key_len; +} +#endif + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ + png_byte buf[13]; /* Buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR"); + + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: +#ifdef PNG_WRITE_16BIT_SUPPORTED + case 16: +#endif + png_ptr->channels = 1; break; + + default: + png_error(png_ptr, + "Invalid bit depth for grayscale image"); + } + break; + + case PNG_COLOR_TYPE_RGB: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + png_error(png_ptr, "Invalid bit depth for RGB image"); + + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + png_ptr->channels = 1; + break; + + default: + png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + png_error(png_ptr, "Invalid bit depth for RGBA image"); + + png_ptr->channels = 4; + break; + + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* Save the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + /* Set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* Pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* Write the chunk */ + png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); + + if (!(png_ptr->do_filter)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + + png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ +} + +/* Write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, + png_uint_32 num_pal) +{ + png_uint_32 i; + png_const_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE"); + + if (( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d", png_ptr->num_palette); + + png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); +#ifdef PNG_POINTER_INDEXING_SUPPORTED + + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } + +#else + /* This is a little slower but some buggy compilers need to do this + * instead + */ + pal_ptr=palette; + + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } + +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* This is similar to png_text_compress, above, except that it does not require + * all of the data at once and, instead of buffering the compressed result, + * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out + * because it calls the write interface. As a result it does its own error + * reporting and does not return an error code. In the event of error it will + * just call png_error. The input data length may exceed 32-bits. The 'flush' + * parameter is exactly the same as that to deflate, with the following + * meanings: + * + * Z_NO_FLUSH: normal incremental output of compressed data + * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush + * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up + * + * The routine manages the acquire and release of the png_ptr->zstream by + * checking and (at the end) clearing png_ptr->zowner, it does some sanity + * checks on the 'mode' flags while doing this. + */ +void /* PRIVATE */ +png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, + png_alloc_size_t input_len, int flush) +{ + if (png_ptr->zowner != png_IDAT) + { + /* First time. Ensure we have a temporary buffer for compression and + * trim the buffer list if it has more than one entry to free memory. + * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been + * created at this point, but the check here is quick and safe. + */ + if (png_ptr->zbuffer_list == NULL) + { + png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp, + png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); + png_ptr->zbuffer_list->next = NULL; + } + + else + png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next); + + /* It is a terminal error if we can't claim the zstream. */ + if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg); + + /* The output state is maintained in png_ptr->zstream, so it must be + * initialized here after the claim. + */ + png_ptr->zstream.next_out = png_ptr->zbuffer_list->output; + png_ptr->zstream.avail_out = png_ptr->zbuffer_size; + } + + /* Now loop reading and writing until all the input is consumed or an error + * terminates the operation. The _out values are maintained across calls to + * this function, but the input must be reset each time. + */ + png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); + png_ptr->zstream.avail_in = 0; /* set below */ + for (;;) + { + int ret; + + /* INPUT: from the row data */ + uInt avail = ZLIB_IO_MAX; + + if (avail > input_len) + avail = (uInt)input_len; /* safe because of the check */ + + png_ptr->zstream.avail_in = avail; + input_len -= avail; + + ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush); + + /* Include as-yet unconsumed input */ + input_len += png_ptr->zstream.avail_in; + png_ptr->zstream.avail_in = 0; + + /* OUTPUT: write complete IDAT chunks when avail_out drops to zero, note + * that these two zstream fields are preserved across the calls, therefore + * there is no need to set these up on entry to the loop. + */ + if (png_ptr->zstream.avail_out == 0) + { + png_bytep data = png_ptr->zbuffer_list->output; + uInt size = png_ptr->zbuffer_size; + + /* Write an IDAT containing the data then reset the buffer. The + * first IDAT may need deflate header optimization. + */ +# ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + optimize_cmf(data, png_image_size(png_ptr)); +# endif + + png_write_complete_chunk(png_ptr, png_IDAT, data, size); + png_ptr->mode |= PNG_HAVE_IDAT; + + png_ptr->zstream.next_out = data; + png_ptr->zstream.avail_out = size; + + /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with + * the same flush parameter until it has finished output, for NO_FLUSH + * it doesn't matter. + */ + if (ret == Z_OK && flush != Z_NO_FLUSH) + continue; + } + + /* The order of these checks doesn't matter much; it just effect which + * possible error might be detected if multiple things go wrong at once. + */ + if (ret == Z_OK) /* most likely return code! */ + { + /* If all the input has been consumed then just return. If Z_FINISH + * was used as the flush parameter something has gone wrong if we get + * here. + */ + if (input_len == 0) + { + if (flush == Z_FINISH) + png_error(png_ptr, "Z_OK on Z_FINISH with output space"); + + return; + } + } + + else if (ret == Z_STREAM_END && flush == Z_FINISH) + { + /* This is the end of the IDAT data; any pending output must be + * flushed. For small PNG files we may still be at the beginning. + */ + png_bytep data = png_ptr->zbuffer_list->output; + uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out; + +# ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + optimize_cmf(data, png_image_size(png_ptr)); +# endif + + png_write_complete_chunk(png_ptr, png_IDAT, data, size); + png_ptr->zstream.avail_out = 0; + png_ptr->zstream.next_out = NULL; + png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; + + png_ptr->zowner = 0; /* Release the stream */ + return; + } + + else + { + /* This is an error condition. */ + png_zstream_error(png_ptr, ret); + png_error(png_ptr, png_ptr->zstream.msg); + } + } +} + +/* Write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structrp png_ptr) +{ + png_debug(1, "in png_write_IEND"); + + png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#ifdef PNG_WRITE_gAMA_SUPPORTED +/* Write a gAMA chunk */ +void /* PRIVATE */ +png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) +{ + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, (png_uint_32)file_gamma); + png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); +} +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +/* Write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structrp png_ptr, int srgb_intent) +{ + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB"); + + if (srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + + buf[0]=(png_byte)srgb_intent; + png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); +} +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +/* Write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structrp png_ptr, png_const_charp name, + png_const_bytep profile) +{ + png_uint_32 name_len; + png_uint_32 profile_len; + png_byte new_name[81]; /* 1 byte for the compression byte */ + compression_state comp; + + png_debug(1, "in png_write_iCCP"); + + /* These are all internal problems: the profile should have been checked + * before when it was stored. + */ + if (profile == NULL) + png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */ + + profile_len = png_get_uint_32(profile); + + if (profile_len < 132) + png_error(png_ptr, "ICC profile too short"); + + if (profile_len & 0x03) + png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)"); + + { + png_uint_32 embedded_profile_len = png_get_uint_32(profile); + + if (profile_len != embedded_profile_len) + png_error(png_ptr, "Profile length does not match profile"); + } + + name_len = png_check_keyword(png_ptr, name, new_name); + + if (name_len == 0) + png_error(png_ptr, "iCCP: invalid keyword"); + + new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE; + + /* Make sure we include the NULL after the name and the compression type */ + ++name_len; + + png_text_compress_init(&comp, profile, profile_len); + + /* Allow for keyword terminator and compression byte */ + if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg); + + png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len); + + png_write_chunk_data(png_ptr, new_name, name_len); + + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +/* Write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) +{ + png_uint_32 name_len; + png_byte new_name[80]; + png_byte entrybuf[10]; + png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); + png_size_t palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifndef PNG_POINTER_INDEXING_SUPPORTED + int i; +#endif + + png_debug(1, "in png_write_sPLT"); + + name_len = png_check_keyword(png_ptr, spalette->name, new_name); + + if (name_len == 0) + png_error(png_ptr, "sPLT: invalid keyword"); + + /* Make sure we include the NULL after the name */ + png_write_chunk_header(png_ptr, png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 1)); + + png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); + + /* Loop through each palette entry, writing appropriately */ +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (ep = spalette->entries; epentries + spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + + png_write_chunk_data(png_ptr, entrybuf, entry_size); + } +#else + ep=spalette->entries; + for (i = 0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + + png_write_chunk_data(png_ptr, entrybuf, entry_size); + } +#endif + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +/* Write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) +{ + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT"); + + /* Make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[size++] = sbit->alpha; + } + + png_write_complete_chunk(png_ptr, png_sBIT, buf, size); +} +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +/* Write the cHRM chunk */ +void /* PRIVATE */ +png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy) +{ + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM"); + + /* Each value is saved in 1/100,000ths */ + png_save_int_32(buf, xy->whitex); + png_save_int_32(buf + 4, xy->whitey); + + png_save_int_32(buf + 8, xy->redx); + png_save_int_32(buf + 12, xy->redy); + + png_save_int_32(buf + 16, xy->greenx); + png_save_int_32(buf + 20, xy->greeny); + + png_save_int_32(buf + 24, xy->bluex); + png_save_int_32(buf + 28, xy->bluey); + + png_write_complete_chunk(png_ptr, png_cHRM, buf, 32); +} +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +/* Write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, + png_const_color_16p tran, int num_trans, int color_type) +{ + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_app_warning(png_ptr, + "Invalid number of transparent colors specified"); + return; + } + + /* Write the chunk out as it is */ + png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, + (png_size_t)num_trans); + } + + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* One 16 bit value */ + if (tran->gray >= (1 << png_ptr->bit_depth)) + { + png_app_warning(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + + return; + } + + png_save_uint_16(buf, tran->gray); + png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); + } + + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* Three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_app_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + + png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); + } + + else + { + png_app_warning(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +/* Write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) +{ + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index >= png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + + buf[0] = back->index; + png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); + } + + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + + return; + } + + png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); + } + + else + { + if (back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + + return; + } + + png_save_uint_16(buf, back->gray); + png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +/* Write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) +{ + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST"); + + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, + png_ptr->num_palette); + + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); + + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +/* Write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, + png_size_t text_len) +{ + png_uint_32 key_len; + png_byte new_key[80]; + + png_debug(1, "in png_write_tEXt"); + + key_len = png_check_keyword(png_ptr, key, new_key); + + if (key_len == 0) + png_error(png_ptr, "tEXt: invalid keyword"); + + if (text == NULL || *text == '\0') + text_len = 0; + + else + text_len = strlen(text); + + if (text_len > PNG_UINT_31_MAX - (key_len+1)) + png_error(png_ptr, "tEXt: text too long"); + + /* Make sure we include the 0 after the key */ + png_write_chunk_header(png_ptr, png_tEXt, + (png_uint_32)/*checked above*/(key_len + text_len + 1)); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, new_key, key_len + 1); + + if (text_len) + png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len); + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +/* Write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, + png_size_t text_len, int compression) +{ + png_uint_32 key_len; + png_byte new_key[81]; + compression_state comp; + + png_debug(1, "in png_write_zTXt"); + PNG_UNUSED(text_len) /* Always use strlen */ + + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, key, text, 0); + return; + } + + if (compression != PNG_TEXT_COMPRESSION_zTXt) + png_error(png_ptr, "zTXt: invalid compression type"); + + key_len = png_check_keyword(png_ptr, key, new_key); + + if (key_len == 0) + png_error(png_ptr, "zTXt: invalid keyword"); + + /* Add the compression method and 1 for the keyword separator. */ + new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; + ++key_len; + + /* Compute the compressed data; do it now for the length */ + png_text_compress_init(&comp, (png_const_bytep)text, + text == NULL ? 0 : strlen(text)); + + if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg); + + /* Write start of chunk */ + png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len); + + /* Write key */ + png_write_chunk_data(png_ptr, new_key, key_len); + + /* Write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); + + /* Close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +/* Write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, + png_const_charp lang, png_const_charp lang_key, png_const_charp text) +{ + png_uint_32 key_len, prefix_len; + png_size_t lang_len, lang_key_len; + png_byte new_key[82]; + compression_state comp; + + png_debug(1, "in png_write_iTXt"); + + key_len = png_check_keyword(png_ptr, key, new_key); + + if (key_len == 0) + png_error(png_ptr, "iTXt: invalid keyword"); + + /* Set the compression flag */ + switch (compression) + { + case PNG_ITXT_COMPRESSION_NONE: + case PNG_TEXT_COMPRESSION_NONE: + compression = new_key[++key_len] = 0; /* no compression */ + break; + + case PNG_TEXT_COMPRESSION_zTXt: + case PNG_ITXT_COMPRESSION_zTXt: + compression = new_key[++key_len] = 1; /* compressed */ + break; + + default: + png_error(png_ptr, "iTXt: invalid compression"); + } + + new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; + ++key_len; /* for the keywod separator */ + + /* We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG, however, + * specifies that the text is UTF-8 and this really doesn't require any + * checking. + * + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + * + * TODO: validate the language tag correctly (see the spec.) + */ + if (lang == NULL) lang = ""; /* empty language is valid */ + lang_len = strlen(lang)+1; + if (lang_key == NULL) lang_key = ""; /* may be empty */ + lang_key_len = strlen(lang_key)+1; + if (text == NULL) text = ""; /* may be empty */ + + prefix_len = key_len; + if (lang_len > PNG_UINT_31_MAX-prefix_len) + prefix_len = PNG_UINT_31_MAX; + else + prefix_len = (png_uint_32)(prefix_len + lang_len); + + if (lang_key_len > PNG_UINT_31_MAX-prefix_len) + prefix_len = PNG_UINT_31_MAX; + else + prefix_len = (png_uint_32)(prefix_len + lang_key_len); + + png_text_compress_init(&comp, (png_const_bytep)text, strlen(text)); + + if (compression) + { + if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg); + } + + else + { + if (comp.input_len > PNG_UINT_31_MAX-prefix_len) + png_error(png_ptr, "iTXt: uncompressed text too long"); + + /* So the string will fit in a chunk: */ + comp.output_len = (png_uint_32)/*SAFE*/comp.input_len; + } + + png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len); + + png_write_chunk_data(png_ptr, new_key, key_len); + + png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len); + + png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len); + + if (compression) + png_write_compressed_data_out(png_ptr, &comp); + + else + png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.input_len); + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +/* Write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset, + int unit_type) +{ + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs"); + + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_int_32(buf, x_offset); + png_save_int_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); +} +#endif +#ifdef PNG_WRITE_pCAL_SUPPORTED +/* Write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_const_charp units, + png_charpp params) +{ + png_uint_32 purpose_len; + png_size_t units_len, total_len; + png_size_tp params_len; + png_byte buf[10]; + png_byte new_purpose[80]; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); + + if (type >= PNG_EQUATION_LAST) + png_error(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, new_purpose); + + if (purpose_len == 0) + png_error(png_ptr, "pCAL: invalid keyword"); + + ++purpose_len; /* terminator */ + + png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); + units_len = strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_size_tp)png_malloc(png_ptr, + (png_alloc_size_t)(nparams * (sizeof (png_size_t)))); + + /* Find the length of each parameter, making sure we don't count the + * null terminator for the last parameter. + */ + for (i = 0; i < nparams; i++) + { + params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu", i, + (unsigned long)params_len[i]); + total_len += params_len[i]; + } + + png_debug1(3, "pCAL total length = %d", (int)total_len); + png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, new_purpose, purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +/* Write the sCAL chunk */ +void /* PRIVATE */ +png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, + png_const_charp height) +{ + png_byte buf[64]; + png_size_t wlen, hlen, total_len; + + png_debug(1, "in png_write_sCAL_s"); + + wlen = strlen(width); + hlen = strlen(height); + total_len = wlen + hlen + 2; + + if (total_len > 64) + { + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); + return; + } + + buf[0] = (png_byte)unit; + memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ + memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len); +} +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +/* Write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs"); + + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); +} +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) +{ + png_byte buf[7]; + + png_debug(1, "in png_write_tIME"); + + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); +} +#endif + +/* Initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structrp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_alloc_size_t buf_size; + int usr_pixel_depth; + + png_debug(1, "in png_write_start_row"); + + usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; + buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1; + + /* 1.5.6: added to allow checking in the row write code. */ + png_ptr->transformed_pixel_depth = png_ptr->pixel_depth; + png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; + + /* Set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size); + + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + /* Set up filtering buffer, if using this filter */ + if (png_ptr->do_filter & PNG_FILTER_SUB) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); + + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + /* We only need to keep the previous row if we are using one of these. */ + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + { + /* Set up previous row buffer */ + png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structrp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_debug(1, "in png_write_finish_row"); + + /* Next row */ + png_ptr->row_number++; + + /* See if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + + else + { + /* Loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* Reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth, png_ptr->width)) + 1); + + return; + } + } +#endif + + /* If we get here, we've just written the last row, so we need + to flush the compressor */ + png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH); +} + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_write_interlace"); + + /* We don't have to do anything on the last pass (6) */ + if (pass < 6) + { + /* Each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + + break; + } + + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + + break; + } + + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + + break; + } + + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* Start at the beginning */ + dp = row; + + /* Find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + + /* Loop through the row, only looking at the pixels that matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* Find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + + /* Move the pixel */ + if (dp != sp) + memcpy(dp, sp, pixel_bytes); + + /* Next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* Set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, + png_size_t row_bytes); + +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) +{ + png_bytep best_row; +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_bytep prev_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_size_t row_bytes = row_info->rowbytes; +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + int num_p_filters = png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter"); + +#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) + { + /* These will never be selected so we need not test them. */ + filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); + } +#endif + + /* Find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) >> 3; + + prev_row = png_ptr->prev_row; +#endif + best_row = png_ptr->row_buf; +#ifdef PNG_WRITE_FILTER_SUPPORTED + row_buf = best_row; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_size_t i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* Sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* It's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* Up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* Avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + + if (pa <= pb && pa <= pc) + p = a; + + else if (pb <= pc) + p = b; + + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + + /* Do the actual writing of the filtered row data from the chosen filter. */ + png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1); + +#ifdef PNG_WRITE_FILTER_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +#endif /* PNG_WRITE_FILTER_SUPPORTED */ +} + + +/* Do the actual writing of a previously filtered row. */ +static void +png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, + png_size_t full_row_length/*includes filter byte*/) +{ + png_debug(1, "in png_write_filtered_row"); + + png_debug1(2, "filter = %d", filtered_row[0]); + + png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH); + + /* Swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } + + /* Finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/image/png_load.cpp b/image/png_load.cpp index 8554137be6..43494bf620 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -3,11 +3,8 @@ #include "png_load.h" #include "base/logging.h" -#ifdef BLACKBERRY -#define PNG_AVAILABLE 1 -#endif -#ifndef PNG_AVAILABLE +#if 0 #include "ext/stb_image/stb_image.h" // *image_data_ptr should be deleted with free() // return value of 1 == success. @@ -86,12 +83,11 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d } *pwidth = png.width; *pheight = png.height; + png.format = PNG_FORMAT_RGBA; int stride = PNG_IMAGE_ROW_STRIDE(png); - *image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_BUFFER_SIZE(png, stride)); - - png_image_finish_read(&png, NULL, image_data_ptr, stride, NULL); - png_image_free(&png); + *image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_SIZE(png)); + png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL); return 1; } @@ -113,15 +109,13 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in } *pwidth = png.width; *pheight = png.height; + png.format = PNG_FORMAT_RGBA; int stride = PNG_IMAGE_ROW_STRIDE(png); - *image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_BUFFER_SIZE(png, stride)); - - png_image_finish_read(&png, NULL, image_data_ptr, stride, NULL); - png_image_free(&png); + *image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_SIZE(png)); + png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL); return 1; } - #endif diff --git a/native.vcxproj b/native.vcxproj index 7e8740eaa8..9131c29b2d 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -207,6 +207,13 @@ + + + + + + + @@ -347,6 +354,22 @@ + + + + + + + + + + + + + + + + CompileAsCpp CompileAsCpp @@ -740,4 +763,4 @@ - \ No newline at end of file + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 8604a2e67e..5bba84ad4d 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -292,6 +292,13 @@ gfx + + + + + + + ext\libzip @@ -537,6 +544,23 @@ util + + + + + + + + + + + + + + + + + ext\libzip @@ -771,4 +795,4 @@ {aa8b9b49-2ff8-4961-b6cc-9c33ea674130} - \ No newline at end of file + From d0023bbdd978cf34a9ff5d812b1c09c9e62d5e99 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 8 Dec 2013 02:35:53 +1000 Subject: [PATCH 0928/1445] Remove stb_image usage (no longer used for anything). --- Android.mk | 4 +-- image/png_load.cpp | 66 ++---------------------------------------- native.vcxproj | 5 +--- native.vcxproj.filters | 7 ----- 4 files changed, 4 insertions(+), 78 deletions(-) diff --git a/Android.mk b/Android.mk index 92da5f33f8..ac86d7721f 100644 --- a/Android.mk +++ b/Android.mk @@ -38,8 +38,6 @@ LOCAL_SRC_FILES :=\ ext/jpge/jpgd.cpp \ ext/jpge/jpge.cpp \ ext/sha1/sha1.cpp \ - ext/stb_image/stb_image.c \ - ext/stb_image_write/stb_image_write.c \ ext/stb_vorbis/stb_vorbis.c.arm \ ext/vjson/json.cpp \ ext/vjson/block_allocator.cpp \ @@ -102,7 +100,7 @@ LOCAL_SRC_FILES :=\ LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -Wall -Wno-multichar -D__STDC_CONSTANT_MACROS LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -fno-rtti -Wno-reorder -Wno-literal-suffix LOCAL_LDLIBS := -lz -LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip $(LOCAL_PATH)/ext/libpng16 #Portable native and separate code on android in future is easy you needs add files #by ($(target_arch_ABI),arquitecture (armeabi-v7a , armeabi , x86 , MIPS) diff --git a/image/png_load.cpp b/image/png_load.cpp index 43494bf620..19ef0adee1 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -1,70 +1,10 @@ +#include #include #include +#include #include "png_load.h" #include "base/logging.h" - -#if 0 -#include "ext/stb_image/stb_image.h" -// *image_data_ptr should be deleted with free() -// return value of 1 == success. -int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, - bool flip) { - if (flip) - { - ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); - } - - int x,y,n; - unsigned char *data = stbi_load(file, &x, &y, &n, 4); // 4 = force RGBA - if (!data) - return 0; - - *pwidth = x; - *pheight = y; - // ... process data if not NULL ... - // ... x = width, y = height, n = # 8-bit components per pixel ... - // ... replace '0' with '1'..'4' to force that many components per pixel - // ... but 'n' will always be the number that it would have been if you said 0 - - // TODO: Get rid of this silly copy which is only to make the buffer free-able with free() - *image_data_ptr = (unsigned char *)malloc(x * y * 4); - memcpy(*image_data_ptr, data, x * y * 4); - stbi_image_free(data); - return 1; -} - -int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr, - bool flip) { - if (flip) - { - ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); - } - - int x,y,n; - unsigned char *data = stbi_load_from_memory(input_ptr,(int)input_len, &x, &y, &n, 4); // 4 = force RGBA - if (!data) - return 0; - - *pwidth = x; - *pheight = y; - // ... process data if not NULL ... - // ... x = width, y = height, n = # 8-bit components per pixel ... - // ... replace '0' with '1'..'4' to force that many components per pixel - // ... but 'n' will always be the number that it would have been if you said 0 - - // TODO: Get rid of this silly copy which is only to make the buffer free-able with free() - *image_data_ptr = (unsigned char *)malloc(x * y * 4); - memcpy(*image_data_ptr, data, x * y * 4); - stbi_image_free(data); - return 1; -} - -#else - -#include -#include - // *image_data_ptr should be deleted with free() // return value of 1 == success. int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip) { @@ -117,5 +57,3 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in return 1; } - -#endif diff --git a/native.vcxproj b/native.vcxproj index 9131c29b2d..f61654f99a 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -99,7 +99,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext\libpng16;%(AdditionalIncludeDirectories); true false false @@ -219,7 +219,6 @@ - @@ -696,8 +695,6 @@ - - diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 5bba84ad4d..db4a618fca 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -210,9 +210,6 @@ util - - ext - ui @@ -463,9 +460,6 @@ util - - ext - ui @@ -536,7 +530,6 @@ input - gfx From 8aa73bfc8da1016d20316b5da7dc522a937161a0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 8 Dec 2013 02:49:26 +1000 Subject: [PATCH 0929/1445] iOS buildfix. --- ext/libpng16/pnglibconf.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/libpng16/pnglibconf.h b/ext/libpng16/pnglibconf.h index 2eac458e1a..fe85ac58fb 100644 --- a/ext/libpng16/pnglibconf.h +++ b/ext/libpng16/pnglibconf.h @@ -16,10 +16,9 @@ /* options */ #define PNG_16BIT_SUPPORTED #define PNG_ALIGNED_MEMORY_SUPPORTED -// TODO: Enable the NEON API on supported hardware -#undef PNG_ARM_NEON_API_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED #undef PNG_ARM_NEON_CHECK_SUPPORTED -#undef PNG_ARM_NEON_SUPPORTED +#undef PNG_ARM_NEON_SUPPORTED*/ #define PNG_BENIGN_ERRORS_SUPPORTED #define PNG_BENIGN_READ_ERRORS_SUPPORTED /*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ From e6b4348bf60051f103337dea42af71e99c6c60b8 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 8 Dec 2013 03:05:21 +1000 Subject: [PATCH 0930/1445] Use libpng16 filter for Windows proj files. --- native.vcxproj | 14 +++---- native.vcxproj.filters | 92 +++++++++++++++++++++++++++++++----------- 2 files changed, 76 insertions(+), 30 deletions(-) diff --git a/native.vcxproj b/native.vcxproj index f61654f99a..af57bee526 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -207,13 +207,13 @@ - - - - - - - + + + + + + + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index db4a618fca..20d2819938 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -289,13 +289,27 @@ gfx - - - - - - - + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + ext\libzip @@ -537,22 +551,54 @@ util - - - - - - - - - - - - - - - - + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + + + ext\libpng16 + ext\libzip From 69806cdd3befb9ad3a61430a260c90940dff99ff Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 8 Dec 2013 03:21:09 +1000 Subject: [PATCH 0931/1445] Windows buildfix. --- native.vcxproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/native.vcxproj b/native.vcxproj index af57bee526..4d2ac2cd0b 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -78,7 +78,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext\libpng16;%(AdditionalIncludeDirectories); ProgramDatabase true false @@ -121,7 +121,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext\libpng16;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast true @@ -146,7 +146,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\libpng;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext\libpng16;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast true From 5d64434c997343c578f49dcdb6d2b41cf01ed5fb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 7 Dec 2013 20:34:09 -0800 Subject: [PATCH 0932/1445] Clean up filters in the vcxproj. --- native.vcxproj.filters | 50 ++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 20d2819938..07388744d7 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -105,12 +105,6 @@ base - - ext - - - ext - gfx @@ -280,11 +274,9 @@ data - math - gfx @@ -322,6 +314,18 @@ util + + ext\jpge + + + ext\jpge + + + ext\vjson + + + ext\vjson + @@ -384,12 +388,6 @@ base - - ext - - - ext - gfx @@ -536,14 +534,12 @@ data - math input - gfx @@ -599,7 +595,6 @@ ext\libpng16 - ext\libzip @@ -765,6 +760,18 @@ util + + ext\jpge + + + ext\jpge + + + ext\vjson + + + ext\vjson + @@ -833,5 +840,14 @@ {aa8b9b49-2ff8-4961-b6cc-9c33ea674130} + + {6c47ee5b-0375-40f0-ab2a-402d001cc9c7} + + + {3721adbc-1a4a-4017-bc1d-893c7e86bc22} + + + {c6910d82-73d3-4d97-ac9c-bcc03265b1bc} + From 9e5df6028ad08d796a4656a30fa532058aa9466d Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 8 Dec 2013 20:14:49 +1000 Subject: [PATCH 0933/1445] Add InputBox as a platform-specific system function instead of a host function. Enable it on all Qt platforms. --- android/app-android.cpp | 5 ----- base/NativeApp.h | 3 ++- base/PCMain.cpp | 5 ----- base/QtMain.cpp | 37 +++++++++++++++++++++++++++---------- base/QtMain.h | 12 ++++++++++++ 5 files changed, 41 insertions(+), 21 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index e570406719..16651f7c7b 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -84,11 +84,6 @@ void LaunchEmail(const char *email_address) { frameCommandParam = email_address; } -void System_InputBox(const char *title, const char *defaultValue) { - frameCommand = "inputBox"; - frameCommandParam = title; -} - void System_SendMessage(const char *command, const char *parameter) { frameCommand = command; frameCommandParam = parameter; diff --git a/base/NativeApp.h b/base/NativeApp.h index 03035b6e29..c81ffe8303 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -107,7 +107,8 @@ void Vibrate(int length_ms); void LaunchBrowser(const char *url); void LaunchMarket(const char *url); void LaunchEmail(const char *email_address); -void System_InputBox(const char *title, const char *defaultValue); +bool System_InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outlength); +bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultValue, std::wstring &outValue); void System_SendMessage(const char *command, const char *parameter); enum SystemProperty { diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 4f76254ff2..3b4668eaa9 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -200,11 +200,6 @@ void System_SendMessage(const char *command, const char *parameter) { // Log? } -void System_InputBox(const char *title, const char *defaultValue) { - // Stub - NativeMessageReceived((std::string("INPUTBOX:") + title).c_str(), "TestFile"); -} - void LaunchBrowser(const char *url) { #ifdef _WIN32 ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 806af47c8d..1025b46755 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -3,7 +3,7 @@ * */ // Qt 4.7+ / 5.0+ implementation of the framework. -// Currently supports: Symbian, Blackberry, Meego, Linux, Windows +// Currently supports: Symbian, Blackberry, Meego, Linux, Windows, Mac OSX #include #include @@ -24,8 +24,6 @@ #endif #include "QtMain.h" - - InputState* input_state; std::string System_GetProperty(SystemProperty prop) { @@ -41,6 +39,8 @@ std::string System_GetProperty(SystemProperty prop) { return "Qt:Linux"; #elif defined(_WIN32) return "Qt:Windows"; +#elif defined(Q_OS_MAC) + return "Qt:Mac"; #else return "Qt"; #endif @@ -55,6 +55,24 @@ void System_SendMessage(const char *command, const char *parameter) { // Log? } +bool System_InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outLength) +{ + QString text = emugl->InputBoxGetQString(QString(title), QString(defaultValue)); + if (text.isEmpty()) + return false; + strcpy(outValue, text.toStdString().c_str()); + return true; +} + +bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultValue, std::wstring &outValue) +{ + QString text = emugl->InputBoxGetQString(QString::fromStdWString(title), QString::fromStdWString(defaultValue)); + if (text.isEmpty()) + return false; + outValue = text.toStdWString(); + return true; +} + void Vibrate(int length_ms) { if (length_ms == -1 || length_ms == -3) length_ms = 50; @@ -79,7 +97,7 @@ float CalculateDPIScale() // Sane default rather than check DPI #ifdef __SYMBIAN32__ return 1.4f; -#elif defined(ARM) +#elif defined(USING_GLES2) return 1.2f; #else return 1.0f; @@ -120,17 +138,16 @@ int main(int argc, char *argv[]) const char *assets_dir = "./"; #endif NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); - -#if defined(ARM) - MainUI w; - w.resize(pixel_xres, pixel_yres); - w.showFullScreen(); +#ifdef USING_GLES2 + emugl = new MainUI(this); + emugl->resize(pixel_xres, pixel_yres); + emugl->showFullScreen(); #endif #ifdef __SYMBIAN32__ // Set RunFast hardware mode for VFPv2. User::SetFloatingPointMode(EFpModeRunFast); // Disable screensaver - QSystemScreenSaver *ssObject = new QSystemScreenSaver(&w); + QSystemScreenSaver *ssObject = new QSystemScreenSaver(emugl); ssObject->setScreenSaverInhibit(); SymbianMediaKeys* mediakeys = new SymbianMediaKeys(); #endif diff --git a/base/QtMain.h b/base/QtMain.h index a6f7badc97..067460e8c8 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -3,6 +3,7 @@ #include #include +#include #include "gfx_es2/glsl_program.h" #include @@ -59,6 +60,15 @@ public: NativeShutdownGraphics(); } +public slots: + QString InputBoxGetQString(QString title, QString defaultValue) { + bool ok; + QString text = QInputDialog::getText(this, title, title, QLineEdit::Normal, defaultValue, &ok); + if (!ok) + text = QString(); + return text; + } + signals: void doubleClick(); void newFrame(); @@ -201,6 +211,8 @@ private: #endif }; +static MainUI* emugl = NULL; + // Audio #define AUDIO_FREQ 44100 #define AUDIO_CHANNELS 2 From 1fbab7d728b1a83398ef7a41131a0541d3f9f6a0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 8 Dec 2013 21:09:24 +1000 Subject: [PATCH 0934/1445] Qt: Update miscellaneous --- base/QtMain.cpp | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 1025b46755..68aee05a08 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -64,15 +64,6 @@ bool System_InputBoxGetString(char *title, const char *defaultValue, char *outVa return true; } -bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultValue, std::wstring &outValue) -{ - QString text = emugl->InputBoxGetQString(QString::fromStdWString(title), QString::fromStdWString(defaultValue)); - if (text.isEmpty()) - return false; - outValue = text.toStdWString(); - return true; -} - void Vibrate(int length_ms) { if (length_ms == -1 || length_ms == -3) length_ms = 50; @@ -129,9 +120,6 @@ int main(int argc, char *argv[]) const char *assets_dir = "app/native/assets/"; #elif defined(MEEGO_EDITION_HARMATTAN) const char *savegame_dir = "/home/user/MyDocs/PPSSPP/"; - QDir myDocs("/home/user/MyDocs/"); - if (!myDocs.exists("PPSSPP")) - myDocs.mkdir("PPSSPP"); const char *assets_dir = "/opt/PPSSPP/"; #else const char *savegame_dir = "./"; @@ -139,7 +127,7 @@ int main(int argc, char *argv[]) #endif NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); #ifdef USING_GLES2 - emugl = new MainUI(this); + emugl = new MainUI(); emugl->resize(pixel_xres, pixel_yres); emugl->showFullScreen(); #endif @@ -147,16 +135,15 @@ int main(int argc, char *argv[]) // Set RunFast hardware mode for VFPv2. User::SetFloatingPointMode(EFpModeRunFast); // Disable screensaver - QSystemScreenSaver *ssObject = new QSystemScreenSaver(emugl); + QScopedPointer ssObject(new QSystemScreenSaver(emugl)); ssObject->setScreenSaverInhibit(); - SymbianMediaKeys* mediakeys = new SymbianMediaKeys(); + QScopedPointer mediakeys(new SymbianMediaKeys()); #endif - QThread* thread = new QThread; - MainAudio *audio = new MainAudio(); - audio->moveToThread(thread); - QObject::connect(thread, SIGNAL(started()), audio, SLOT(run())); - QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + QScopedPointer thread(new QThread); + QScopedPointer audio(new MainAudio()); + audio->moveToThread(thread.data()); + QObject::connect(thread.data(), SIGNAL(started()), audio.data(), SLOT(run())); thread->start(); #ifdef QT_HAS_SDL @@ -164,7 +151,6 @@ int main(int argc, char *argv[]) joy.startEventLoop(); #endif int ret = a.exec(); - delete audio; thread->quit(); NativeShutdown(); net::Shutdown(); From 9f82f521890e4434ce0377a2b14a750b888b2eda Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 8 Dec 2013 13:38:31 -0800 Subject: [PATCH 0935/1445] Small safety tweaks to PathBrowser. --- file/path.cpp | 3 +-- file/path.h | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/file/path.cpp b/file/path.cpp index d456817282..b7097fa585 100644 --- a/file/path.cpp +++ b/file/path.cpp @@ -52,8 +52,7 @@ void PathBrowser::Navigate(const std::string &path) { if (slash != std::string::npos) path_ = path_.substr(0, slash + 1); } - } - else { + } else { if (path[1] == ':' && path_ == "/") path_ = path; else diff --git a/file/path.h b/file/path.h index a3e9bc4322..0acd20c69d 100644 --- a/file/path.h +++ b/file/path.h @@ -19,7 +19,7 @@ public: void GetListing(std::vector &fileInfo, const char *filter = 0); void Navigate(const std::string &path); - std::string GetPath() { + std::string GetPath() const { if (path_ != "/") return path_; else @@ -28,16 +28,16 @@ public: std::string GetFriendlyPath() { std::string str = GetPath(); #if defined(BLACKBERRY) - char* home = getenv("PERIMETER_HOME"); - if (!strncmp(str.c_str(), home, strlen(home))) { + char *home = getenv("PERIMETER_HOME"); + if (home != NULL && !strncmp(str.c_str(), home, strlen(home))) { str = str.substr(strlen(home)); str.insert(0, 1, '~'); } #elif defined(ANDROID) // Do nothing #elif defined(__linux) - char* home = getenv("HOME"); - if (!strncmp(str.c_str(), home, strlen(home))) { + char *home = getenv("HOME"); + if (home != NULL && !strncmp(str.c_str(), home, strlen(home))) { str = str.substr(strlen(home)); str.insert(0, 1, '~'); } From 9b6dc643874a756188822aeebbd9d5cf586d9ca9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 8 Dec 2013 13:39:05 -0800 Subject: [PATCH 0936/1445] Cut down on overhead from std::bind copies. --- thread/threadpool.cpp | 39 ++++++++++++++++++++++++++++++++++----- thread/threadpool.h | 29 +++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp index 4524082e58..2b14500df8 100644 --- a/thread/threadpool.cpp +++ b/thread/threadpool.cpp @@ -31,9 +31,9 @@ void WorkerThread::WaitForCompletion() { void WorkerThread::WorkFunc() { mutex.lock(); started = true; - while(active) { + while (active) { signal.wait(mutex); - if(active) { + if (active) { work_(); doneMutex.lock(); done.notify_one(); @@ -42,6 +42,35 @@ void WorkerThread::WorkFunc() { } } +LoopWorkerThread::LoopWorkerThread() : WorkerThread(true) { + thread = new std::thread(std::bind(&LoopWorkerThread::WorkFunc, this)); + doneMutex.lock(); + while(!started) { }; +} + +void LoopWorkerThread::Process(const std::function &work, int start, int end) { + mutex.lock(); + work_ = work; + start_ = start; + end_ = end; + signal.notify_one(); + mutex.unlock(); +} + +void LoopWorkerThread::WorkFunc() { + mutex.lock(); + started = true; + while (active) { + signal.wait(mutex); + if (active) { + work_(start_, end_); + doneMutex.lock(); + done.notify_one(); + doneMutex.unlock(); + } + } +} + ///////////////////////////// ThreadPool ThreadPool::ThreadPool(int numThreads) : numThreads(numThreads), workersStarted(false) { @@ -50,13 +79,13 @@ ThreadPool::ThreadPool(int numThreads) : numThreads(numThreads), workersStarted( void ThreadPool::StartWorkers() { if(!workersStarted) { for(int i=0; i()); + workers.push_back(std::make_shared()); } workersStarted = true; } } -void ThreadPool::ParallelLoop(std::function loop, int lower, int upper) { +void ThreadPool::ParallelLoop(const std::function &loop, int lower, int upper) { int range = upper - lower; if (range >= numThreads * 2) { // don't parallelize tiny loops (this could be better, maybe add optional parameter that estimates work per iteration) lock_guard guard(mutex); @@ -67,7 +96,7 @@ void ThreadPool::ParallelLoop(std::function loop, int lower, int int chunk = range / numThreads; int s = lower; for (int i = 0; i < numThreads - 1; ++i) { - workers[i]->Process(std::bind(loop, s, s+chunk)); + workers[i]->Process(loop, s, s+chunk); s+=chunk; } // This is the final chunk. diff --git a/thread/threadpool.h b/thread/threadpool.h index e5b26df623..c24c30caa7 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -17,20 +17,37 @@ public: // wait for a submitted work item to be completed void WaitForCompletion(); -private: +protected: + WorkerThread(bool ignored) : active(true), started(false) {} + virtual void WorkFunc(); + std::thread *thread; // the worker thread ::condition_variable signal; // used to signal new work ::condition_variable done; // used to signal work completion ::recursive_mutex mutex, doneMutex; // associated with each respective condition variable volatile bool active, started; - std::function work_; // the work to be done by this thread - void WorkFunc(); +private: + std::function work_; // the work to be done by this thread WorkerThread(const WorkerThread& other); // prevent copies void operator =(const WorkerThread &other); }; +class LoopWorkerThread : public WorkerThread { +public: + LoopWorkerThread(); + void Process(const std::function &work, int start, int end); + +protected: + virtual void WorkFunc(); + +private: + int start_; + int end_; + std::function work_; // the work to be done by this thread +}; + // A thread pool manages a set of worker threads, and allows the execution of parallel loops on them // individual parallel loops are fully sequentialized to simplify synchronization, which should not // be a problem as they should each use the entire system @@ -40,17 +57,17 @@ public: // don't need a destructor, "workers" is cleared on delete, // leading to the stopping and joining of all worker threads (RAII and all that) - void ParallelLoop(std::function loop, int lower, int upper); + void ParallelLoop(const std::function &loop, int lower, int upper); private: const int numThreads; - std::vector> workers; + std::vector> workers; ::recursive_mutex mutex; // used to sequentialize loop execution bool workersStarted; void StartWorkers(); ThreadPool(const ThreadPool& other); // prevent copies - void operator =(const WorkerThread &other); + void operator =(const ThreadPool &other); }; From 9d5cd81729f1d8d78174de0530b4f2d6a59e6a0c Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 9 Dec 2013 15:33:59 +1000 Subject: [PATCH 0937/1445] iOS: Disable neon in libpng16. --- ext/libpng16/pngpriv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/libpng16/pngpriv.h b/ext/libpng16/pngpriv.h index d014095d3a..34cfe058d9 100644 --- a/ext/libpng16/pngpriv.h +++ b/ext/libpng16/pngpriv.h @@ -110,7 +110,7 @@ * unconditionally on NEON instructions not crashing, otherwise we must * disable use of NEON instructions: */ -# ifdef __ARM_NEON__ +# if defined(__ARM_NEON__) && !defined(IOS) # define PNG_ARM_NEON_OPT 2 # else # define PNG_ARM_NEON_OPT 0 From 39ed5ddf4685d616dd945a3bfe6ca88479f3f4a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 9 Dec 2013 11:19:23 +0100 Subject: [PATCH 0938/1445] Apple libpng16 workaround. @xsacha, what's the right way? --- image/png_load.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/image/png_load.cpp b/image/png_load.cpp index 19ef0adee1..a710e3ae6f 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -1,7 +1,13 @@ #include #include #include + +#ifdef __APPLE__ +#include "ext/libpng16/png.h" +#else #include +#endif + #include "png_load.h" #include "base/logging.h" From dc1594ad3d4a3e4147b25afc7c0edd3778e0a92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 9 Dec 2013 13:12:22 +0100 Subject: [PATCH 0939/1445] Turn off kitkat immersive mode. Can't get it to work consistently. --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 20378840ac..2e99e9dfdf 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -89,7 +89,7 @@ public class NativeActivity extends Activity { private static String TAG = "NativeActivity"; // Easy way to flip it on and off from code. - private static final boolean useKitkatImmersiveMode = true; + private static final boolean useKitkatImmersiveMode = false; // Allows us to skip a lot of initialization on secondary calls to onCreate. private static boolean initialized = false; @@ -355,7 +355,7 @@ public class NativeActivity extends Activity { public void setImmersiveMode() { // this.setImmersive(true); // This is an entirely different kind of immersive mode - hides some notification if (useKitkatImmersiveMode) { - mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); + mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); } } From bd442415583c57fe8d011139344ca000f0815a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 9 Dec 2013 13:15:42 +0100 Subject: [PATCH 0940/1445] Add "DLOG" to native logging library (only active if _DEBUG is set) --- base/logging.h | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/base/logging.h b/base/logging.h index 9503313571..6c3a7b6690 100644 --- a/base/logging.h +++ b/base/logging.h @@ -29,13 +29,13 @@ inline void Crash() { __asm { int 3 }; } #if defined(ARM) || defined(MIPS) inline void Crash() { - char *p = (char *)1337; - *p = 1; + char *p = (char *)1337; + *p = 1; } #else // TODO: 64-bit version inline void Crash() { - asm("int $0x3"); + asm("int $0x3"); } #endif @@ -50,6 +50,12 @@ inline void Crash() { #define APP_NAME "NativeApp" #endif +#ifdef _DEBUG +#define DLOG(...) __android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__); +#else +#define DLOG(...) +#endif + #define ILOG(...) __android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__); #define WLOG(...) __android_log_print(ANDROID_LOG_WARN, APP_NAME, __VA_ARGS__); #define ELOG(...) __android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__); @@ -59,6 +65,11 @@ inline void Crash() { #elif defined(__SYMBIAN32__) #include +#ifdef _DEBUG +#define DLOG(...) { qDebug(__VA_ARGS__);} +#else +#define DLOG(...) +#endif #define ILOG(...) { qDebug(__VA_ARGS__);} #define WLOG(...) { qDebug(__VA_ARGS__);} #define ELOG(...) { qDebug(__VA_ARGS__);} @@ -70,6 +81,12 @@ inline void Crash() { void OutputDebugStringUTF8(const char *p); +#ifdef _DEBUG +#define DLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "D: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "D: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#else +#define DLOG(...) +#endif + #define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "I: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} #define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "W: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} #define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "E: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} @@ -80,6 +97,11 @@ void OutputDebugStringUTF8(const char *p); #include +#ifdef _DEBUG +#define DLOG(...) {printf("D: %s:%i: ", __FILE__, __LINE__); printf("D: " __VA_ARGS__); printf("\n");} +#else +#define DLOG(...) +#endif #define ILOG(...) {printf("I: %s:%i: ", __FILE__, __LINE__); printf("I: " __VA_ARGS__); printf("\n");} #define WLOG(...) {printf("W: %s:%i: ", __FILE__, __LINE__); printf("W: " __VA_ARGS__); printf("\n");} #define ELOG(...) {printf("E: %s:%i: ", __FILE__, __LINE__); printf("E: " __VA_ARGS__); printf("\n");} From d0d5be2c5daf5084c8141c9e82fa511350cbc2f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 9 Dec 2013 13:44:47 +0100 Subject: [PATCH 0941/1445] Logspam reductions --- android/app-android.cpp | 32 +++++++------------ .../libnative/NativeActivity.java | 2 -- .../henrikrydgard/libnative/NativeGLView.java | 1 - file/zip_read.cpp | 12 +++---- gfx/texture.cpp | 24 ++++++++------ gfx_es2/gl_state.cpp | 10 +++--- 6 files changed, 38 insertions(+), 43 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 16651f7c7b..11a51bfe89 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -146,7 +146,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioConfig extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init (JNIEnv *env, jclass, jint dpi, jstring jdevicetype, jstring jlangRegion, jstring japkpath, - jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { + jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; ILOG("NativeApp.init() -- begin"); @@ -165,7 +165,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init hat_joystick_y_async = 0; std::string apkPath = GetJavaString(env, japkpath); - ILOG("NativeApp::Init: APK path: %s", apkPath.c_str()); VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); systemName = GetJavaString(env, jdevicetype); @@ -197,14 +196,14 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioInit(JNIEnv *, jclass) { - ILOG("NativeApp.audioInit() -- begin"); if (use_opensl_audio) { // TODO: PPSSPP doesn't support 48khz yet so let's not use that yet. - ILOG("Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: 44100", optimalFramesPerBuffer, optimalSampleRate); + ILOG("NativeApp.audioInit() -- Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: 44100", optimalFramesPerBuffer, optimalSampleRate); optimalSampleRate = 44100; AndroidAudio_Init(&NativeMix, library_path, optimalFramesPerBuffer, optimalSampleRate); + } else { + ILOG("NativeApp.audioInit() -- Using Java audio :("); } - ILOG("NativeApp.audioInit() -- end"); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioShutdown(JNIEnv *, jclass) { @@ -233,7 +232,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclas extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { ILOG("NativeApp.shutdown() -- begin"); NativeShutdown(); - ILOG("VFSShutdown."); VFSShutdown(); net::Shutdown(); ILOG("NativeApp.shutdown() -- end"); @@ -250,22 +248,19 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIE dp_xres = pixel_xres * g_dpi_scale; dp_yres = pixel_yres * g_dpi_scale; - ILOG("Calling NativeInitGraphics(): dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); NativeInitGraphics(); - ILOG("NativeInitGraphics() completed"); + ILOG("NativeInitGraphics() completed: dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); dp_xscale = (float)dp_xres / pixel_xres; dp_yscale = (float)dp_yres / pixel_yres; renderer_inited = true; } else { - ILOG("Calling NativeDeviceLost();"); NativeDeviceLost(); - ILOG("NativeDeviceLost completed.;"); + ILOG("NativeDeviceLost completed."); } - ILOG("(Re)-fetching method ID to postCommand..."); + DLOG("(Re)-fetching method ID to postCommand..."); jclass cls = env->GetObjectClass(obj); postCommand = env->GetMethodID(cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); - ILOG("MethodID: %i", (int)postCommand); } extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { @@ -311,14 +306,14 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN glClearColor(1.0, 0.0, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } - + if (!frameCommand.empty()) { - ILOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str()); + DLOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str()); jstring cmd = env->NewStringUTF(frameCommand.c_str()); jstring param = env->NewStringUTF(frameCommandParam.c_str()); env->CallVoidMethod(obj, postCommand, cmd, param); - + frameCommand = ""; frameCommandParam = ""; } @@ -326,9 +321,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayShutdown(JNIEnv *env, jobject obj) { if (renderer_inited) { - ILOG("Calling NativeDeviceLost();"); NativeDeviceLost(); - ILOG("NativeDeviceLost completed.;"); + ILOG("NativeDeviceLost completed."); NativeShutdownGraphics(); renderer_inited = false; NativeMessageReceived("recreateviews", ""); @@ -441,8 +435,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickAxis( break; } - // Hat is just stupid. Force translate it to dpad events. TODO - AxisInput axis; axis.axisId = axisId; axis.deviceId = deviceId; @@ -473,7 +465,7 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer AxisInput axis; axis.deviceId = DEVICE_ID_ACCELEROMETER; axis.flags = 0; - + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_X; axis.value = x; NativeAxis(axis); diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 2e99e9dfdf..50b78aea81 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -218,7 +218,6 @@ public class NativeActivity extends Activity { String externalStorageDir = sdcard.getAbsolutePath(); String dataDir = this.getFilesDir().getAbsolutePath(); String apkFilePath = appInfo.sourceDir; - NativeApp.sendMessage("Message from Java", "Hot Coffee"); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); int dpi = metrics.densityDpi; @@ -230,7 +229,6 @@ public class NativeActivity extends Activity { String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); - // INIT! NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); NativeApp.init(dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); Log.i(TAG, "Device: " + deviceType); diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 61fec4b2f2..b9455fb6fa 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -49,7 +49,6 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, mSensorManager = (SensorManager)activity.getSystemService(Activity.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - Log.i(TAG, "Initializing MOGA"); mController = Controller.getInstance(activity); if (mController.init()) { Log.i(TAG, "MOGA initialized"); diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 5005af96e1..a9203285d5 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -121,9 +121,9 @@ ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { GetFileListing("assets", &info, 0); for (int i = 0; i < info.size(); i++) { if (info[i].isDirectory) { - ILOG("Directory: %s", info[i].name.c_str()); + DLOG("Directory: %s", info[i].name.c_str()); } else { - ILOG("File: %s", info[i].name.c_str()); + DLOG("File: %s", info[i].name.c_str()); } } } @@ -141,9 +141,9 @@ uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { bool ZipAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) { - ILOG("Zip path: %s", path); + DLOG("Zip path: %s", path); std::set filters; - std::string tmp; + std::string tmp; if (filter) { while (*filter) { if (*filter == ':') { @@ -212,7 +212,7 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis } listing->push_back(info); } - + std::sort(listing->begin(), listing->end()); return true; } @@ -301,7 +301,7 @@ static int num_entries = 0; void VFSRegister(const char *prefix, AssetReader *reader) { entries[num_entries].prefix = prefix; entries[num_entries].reader = reader; - ILOG("Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); + DLOG("Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); num_entries++; } diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 7e6320c387..e6b33380af 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -19,6 +19,11 @@ Texture::Texture() : id_(0) { register_gl_resource_holder(this); } +Texture::~Texture() { + unregister_gl_resource_holder(this); + Destroy(); +} + void Texture::Destroy() { if (id_) { glDeleteTextures(1, &id_); @@ -27,14 +32,13 @@ void Texture::Destroy() { } void Texture::GLLost() { - ILOG("Reloading lost texture %s", filename_.c_str()); - Load(filename_.c_str()); - ILOG("Reloaded lost texture %s", filename_.c_str()); -} - -Texture::~Texture() { - unregister_gl_resource_holder(this); - Destroy(); + if (!filename_.empty()) { + Load(filename_.c_str()); + ILOG("Reloaded lost texture %s", filename_.c_str()); + } else { + WLOG("Texture cannot be restored - has no filename"); + Destroy(); + } } static void SetTextureParameters(int zim_flags) { @@ -133,8 +137,10 @@ bool Texture::Load(const char *filename) { } else { return true; } - } else { + } else if (!name || !strlen(name)) { ELOG("Failed to identify image file %s by extension", name); + } else { + ELOG("Cannot load a texture with an empty filename"); } LoadXOR(); return false; diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index e24c395d6e..eec6e0791c 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -124,13 +124,11 @@ void CheckGLExtensions() { gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; } - ILOG("GPU Vendor : %s", cvendor); + ILOG("GPU Vendor : %s ; GL version str: %s", cvendor, versionStr ? versionStr : "N/A"); #ifndef USING_GLES2 - char buffer[64] = {0}; if (versionStr) { - ILOG("GL version str: %s", versionStr); strncpy(buffer, versionStr, 63); } const char *lastNumStart = buffer; @@ -212,9 +210,12 @@ void CheckGLExtensions() { #if defined(ANDROID) || defined(BLACKBERRY) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. // https://twitter.com/ID_AA_Carmack/status/387383037794603008 +#ifdef _DEBUG void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1"); void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2"); - ILOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2); + DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2); +#endif + if (gl_extensions.NV_draw_texture) { glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)eglGetProcAddress("glDrawTextureNV"); } @@ -271,7 +272,6 @@ void CheckGLExtensions() { } else { g_all_egl_extensions = ""; } - #endif #ifdef USING_GLES2 From 7e2b9d7e98629ea6ef23c7a4e49832e3cd4a6303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 9 Dec 2013 15:27:52 +0100 Subject: [PATCH 0942/1445] Slight logging improvement --- gfx/texture.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index e6b33380af..d848459d5a 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -36,14 +36,15 @@ void Texture::GLLost() { Load(filename_.c_str()); ILOG("Reloaded lost texture %s", filename_.c_str()); } else { - WLOG("Texture cannot be restored - has no filename"); + WLOG("Texture %p cannot be restored - has no filename", this); Destroy(); } } static void SetTextureParameters(int zim_flags) { GLenum wrap = GL_REPEAT; - if (zim_flags & ZIM_CLAMP) wrap = GL_CLAMP_TO_EDGE; + if (zim_flags & ZIM_CLAMP) + wrap = GL_CLAMP_TO_EDGE; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); GL_CHECK(); @@ -59,8 +60,6 @@ static void SetTextureParameters(int zim_flags) { bool Texture::Load(const char *filename) { // hook for generated textures if (!memcmp(filename, "gen:", 4)) { - // TODO - // return false; int bpp, w, h; bool clamp; uint8_t *data = generateTexture(filename, bpp, w, h, clamp); From 9a66b6e803f66db69864ad439b776e3f6c68aa98 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 10 Dec 2013 02:12:58 +1000 Subject: [PATCH 0943/1445] Proper fix for libpng16 includes. --- Android.mk | 2 +- image/png_load.cpp | 6 +----- native.vcxproj | 8 ++++---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Android.mk b/Android.mk index ac86d7721f..b8ccad29a3 100644 --- a/Android.mk +++ b/Android.mk @@ -100,7 +100,7 @@ LOCAL_SRC_FILES :=\ LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -Wall -Wno-multichar -D__STDC_CONSTANT_MACROS LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -fno-rtti -Wno-reorder -Wno-literal-suffix LOCAL_LDLIBS := -lz -LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip $(LOCAL_PATH)/ext/libpng16 +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext $(LOCAL_PATH)/ext/libzip #Portable native and separate code on android in future is easy you needs add files #by ($(target_arch_ABI),arquitecture (armeabi-v7a , armeabi , x86 , MIPS) diff --git a/image/png_load.cpp b/image/png_load.cpp index a710e3ae6f..eeab7f5e63 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -2,11 +2,7 @@ #include #include -#ifdef __APPLE__ -#include "ext/libpng16/png.h" -#else -#include -#endif +#include #include "png_load.h" #include "base/logging.h" diff --git a/native.vcxproj b/native.vcxproj index 4d2ac2cd0b..bbb6640182 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -78,7 +78,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext\libpng16;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); ProgramDatabase true false @@ -99,7 +99,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext\libpng16;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); true false false @@ -121,7 +121,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext\libpng16;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast true @@ -146,7 +146,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext\libpng16;%(AdditionalIncludeDirectories); + ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast true From ecb83130ba112c39a1b7f2582c812e0984a798b0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 10 Dec 2013 11:48:31 +0100 Subject: [PATCH 0944/1445] Make it possible to hide background http downloads from progress bars --- net/http_client.cpp | 8 +++++--- net/http_client.h | 8 +++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 6acbf5c4b7..f75a86d0a8 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -310,7 +310,7 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) } Download::Download(const std::string &url, const std::string &outfile) - : progress_(0.0f), url_(url), outfile_(outfile), resultCode_(0), completed_(false), failed_(false), cancelled_(false) { + : progress_(0.0f), url_(url), outfile_(outfile), resultCode_(0), completed_(false), failed_(false), cancelled_(false), hidden_(false) { } Download::~Download() { @@ -392,7 +392,7 @@ std::shared_ptr Downloader::StartDownload(const std::string &url, cons return dl; } -void Downloader::StartDownloadWithCallback( +std::shared_ptr Downloader::StartDownloadWithCallback( const std::string &url, const std::string &outfile, std::function callback) { @@ -400,6 +400,7 @@ void Downloader::StartDownloadWithCallback( dl->SetCallback(callback); downloads_.push_back(dl); dl->Start(dl); + return dl; } void Downloader::Update() { @@ -416,7 +417,8 @@ void Downloader::Update() { std::vector Downloader::GetCurrentProgress() { std::vector progress; for (size_t i = 0; i < downloads_.size(); i++) { - progress.push_back(downloads_[i]->Progress()); + if (!downloads_[i]->IsHidden()) + progress.push_back(downloads_[i]->Progress()); } return progress; } diff --git a/net/http_client.h b/net/http_client.h index dd1e070764..0a88082d58 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -108,6 +108,11 @@ public: } } + // Just metadata. Convenient for download managers, for example, if set, + // Downloader::GetCurrentProgress won't return it in the results. + bool IsHidden() const { return hidden_; } + void SetHidden(bool hidden) { hidden_ = hidden; } + private: void Do(std::shared_ptr self); // Actually does the download. Runs on thread. void SetFailed(int code); @@ -119,6 +124,7 @@ private: bool completed_; bool failed_; volatile bool cancelled_; + bool hidden_; std::function callback_; }; @@ -132,7 +138,7 @@ public: std::shared_ptr StartDownload(const std::string &url, const std::string &outfile); - void StartDownloadWithCallback( + std::shared_ptr StartDownloadWithCallback( const std::string &url, const std::string &outfile, std::function callback); From 73b46f433c5f649c27836e2342338565a39347b0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 10 Dec 2013 15:29:58 +0100 Subject: [PATCH 0945/1445] Paths starting with '/' are not VFS paths. --- file/ini_file.cpp | 1 + file/zip_read.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index e9e50b69f1..cb186b242d 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -15,6 +15,7 @@ #include #include +#include "base/logging.h" #include "base/stringutil.h" #include "file/ini_file.h" #include "file/vfs.h" diff --git a/file/zip_read.cpp b/file/zip_read.cpp index a9203285d5..6264e67dce 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -313,6 +313,12 @@ void VFSShutdown() { } uint8_t *VFSReadFile(const char *filename, size_t *size) { + if (filename[0] == '/') { + // This is an absolute path, not a VFS file. Return 0. + ILOG("Not a VFS path: %s", filename); + return 0; + } + int fn_len = (int)strlen(filename); for (int i = 0; i < num_entries; i++) { int prefix_len = (int)strlen(entries[i].prefix); @@ -327,7 +333,6 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { // Else try the other registered file systems. } } - ELOG("Missing filesystem for %s", filename); return 0; } From ca6355d8598b788bdb0ef585b542d4a08c00f31d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 10 Dec 2013 23:43:43 +0100 Subject: [PATCH 0946/1445] Turn EGLConfig back on on Ouya --- .../src/com/henrikrydgard/libnative/NativeActivity.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 50b78aea81..2916b46b59 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -309,9 +309,12 @@ public class NativeActivity extends Activity { // if we specify that we want destination alpha in the config chooser, which we do. // http://grokbase.com/t/gg/android-developers/11bj40jm4w/fall-back - // mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBX_8888); - // mGLSurfaceView.setEGLConfigChooser(new NativeEGLConfigChooser()); + // Needed to avoid banding on Ouya? + if (Build.MANUFACTURER == "OUYA") { + mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBX_8888); + mGLSurfaceView.setEGLConfigChooser(new NativeEGLConfigChooser()); + } nativeRenderer = new NativeRenderer(this); mGLSurfaceView.setRenderer(nativeRenderer); From d680a346dc0d243a1e46018e83846de83d533fb0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 11 Dec 2013 09:32:14 +0100 Subject: [PATCH 0947/1445] UI tweaks (image support on buttons, listview height max) Should probably merge Choice and Button... --- ui/ui_screen.cpp | 3 ++- ui/ui_screen.h | 2 +- ui/view.cpp | 22 ++++++++++++++++++---- ui/view.h | 7 ++++++- ui/viewgroup.cpp | 10 +++++++++- ui/viewgroup.h | 4 +++- 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index b6cef8d6af..13f9de807f 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -197,7 +197,8 @@ UI::EventReturn PopupScreen::OnCancel(UI::EventParams &e) { void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; - listView_ = parent->Add(new ListView(&adaptor_, new LinearLayoutParams(1.0))); + listView_ = parent->Add(new ListView(&adaptor_)); //, new LinearLayoutParams(1.0))); + listView_->SetMaxHeight(dp_yres - 140); listView_->OnChoice.Handle(this, &ListPopupScreen::OnListChoice); } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index c5626e6a30..ecd2378ece 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -80,7 +80,7 @@ public: UI::Event OnChoice; protected: - virtual bool FillVertical() const { return true; } + virtual bool FillVertical() const { return false; } virtual bool ShowButtons() const { return showButtons_; } void CreatePopupContents(UI::ViewGroup *parent); UI::StringVectorListAdaptor adaptor_; diff --git a/ui/view.cpp b/ui/view.cpp index 666eee6369..1b4e23f036 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -418,7 +418,13 @@ void CheckBox::Draw(UIContext &dc) { } void Button::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - dc.MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); + if (imageID_ != -1) { + const AtlasImage *img = &dc.Draw()->GetAtlas()->images[imageID_]; + w = img->w; + h = img->h; + } else { + dc.MeasureText(dc.theme->uiFont, text_.c_str(), &w, &h); + } // Add some internal padding to not look totally ugly w += 16; h += 8; @@ -435,12 +441,20 @@ void Button::Draw(UIContext &dc) { dc.FillRect(style.background, bounds_); float tw, th; dc.MeasureText(dc.theme->uiFont, text_.c_str(), &tw, &th); - if (tw > bounds_.w) { + if (tw > bounds_.w || imageID_ != -1) { dc.PushScissor(bounds_); } dc.SetFontStyle(dc.theme->uiFont); - dc.DrawText(text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); - if (tw > bounds_.w) { + if (imageID_ != -1 && text_.empty()) { + dc.Draw()->DrawImage(imageID_, bounds_.centerX(), bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + } else if (!text_.empty()) { + dc.DrawText(text_.c_str(), bounds_.centerX(), bounds_.centerY(), style.fgColor, ALIGN_CENTER); + if (imageID_ != -1) { + const AtlasImage &img = dc.Draw()->GetAtlas()->images[imageID_]; + dc.Draw()->DrawImage(imageID_, bounds_.centerX() - tw / 2 - 5 - img.w/2, bounds_.centerY(), 1.0f, 0xFFFFFFFF, ALIGN_CENTER); + } + } + if (tw > bounds_.w || imageID_ != -1) { dc.PopScissor(); } } diff --git a/ui/view.h b/ui/view.h index 9cce88f1a3..890b63a92e 100644 --- a/ui/view.h +++ b/ui/view.h @@ -425,7 +425,11 @@ protected: class Button : public Clickable { public: Button(const std::string &text, LayoutParams *layoutParams = 0) - : Clickable(layoutParams), text_(text) {} + : Clickable(layoutParams), text_(text), imageID_(-1) {} + Button(ImageID imageID, LayoutParams *layoutParams = 0) + : Clickable(layoutParams), imageID_(imageID) {} + Button(const std::string &text, ImageID imageID, LayoutParams *layoutParams = 0) + : Clickable(layoutParams), text_(text), imageID_(imageID) {} virtual void Draw(UIContext &dc); virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; @@ -434,6 +438,7 @@ public: private: Style style_; std::string text_; + ImageID imageID_; }; class Slider : public Clickable { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index bad074a861..d6b7f12a3e 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -995,7 +995,8 @@ void ChoiceStrip::Draw(UIContext &dc) { } ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) - : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a) { + : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a), maxHeight_(0) { + linLayout_ = new LinearLayout(ORIENT_VERTICAL); linLayout_->SetSpacing(0.0f); Add(linLayout_); @@ -1011,6 +1012,13 @@ void ListView::CreateAllItems() { } } +void ListView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { + ScrollView::Measure(dc, horiz, vert); + if (maxHeight_ > 0 && measuredHeight_ > maxHeight_) { + measuredHeight_ = maxHeight_; + } +} + EventReturn ListView::OnItemCallback(int num, EventParams &e) { EventParams ev; ev.v = 0; diff --git a/ui/viewgroup.h b/ui/viewgroup.h index d657eab18b..d7a2f30588 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -355,7 +355,8 @@ public: ListView(ListAdaptor *a, LayoutParams *layoutParams = 0); int GetSelected() { return adaptor_->GetSelected(); } - + virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); + virtual void SetMaxHeight(float mh) { maxHeight_ = mh; } Event OnChoice; private: @@ -363,6 +364,7 @@ private: EventReturn OnItemCallback(int num, EventParams &e); ListAdaptor *adaptor_; LinearLayout *linLayout_; + float maxHeight_; }; void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root); From d20700d5bb1dfa30c735f16cc2c04d7be6a5ab4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 11 Dec 2013 18:04:23 +0100 Subject: [PATCH 0948/1445] Android: Add "sharetext" action --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 2916b46b59..b808dda013 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -674,6 +674,12 @@ public class NativeActivity extends Activity { share.setType("image/jpeg"); share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + params)); startActivity(Intent.createChooser(share, "Share Picture")); + } else if (command.equals("sharetext")) { + Intent sendIntent = new Intent(); + sendIntent.setType("text/plain"); + sendIntent.putExtra(Intent.EXTRA_TEXT, params); + sendIntent.setAction(Intent.ACTION_SEND); + startActivity(sendIntent); } else if (command.equals("launchMarket")) { // Don't need this, can just use launchBrowser with a market: // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app From b0ab77d4c24b887b3b40ea0512f2e590f4fe36f0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 11 Dec 2013 20:01:00 +0100 Subject: [PATCH 0949/1445] Fix the disabled look of some views --- ui/ui_screen.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 13f9de807f..a933d8cfd8 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -248,10 +248,14 @@ void PopupMultiChoice::ChoiceCallback(int num) { } void PopupMultiChoice::Draw(UIContext &dc) { + Style style = dc.theme->itemStyle; + if (!IsEnabled()) { + style = dc.theme->itemDisabledStyle; + } Choice::Draw(dc); int paddingX = 12; dc.SetFontStyle(dc.theme->uiFont); - dc.DrawText(valueText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); + dc.DrawText(valueText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); } PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams) @@ -278,11 +282,15 @@ EventReturn PopupSliderChoice::HandleChange(EventParams &e) { } void PopupSliderChoice::Draw(UIContext &dc) { + Style style = dc.theme->itemStyle; + if (!IsEnabled()) { + style = dc.theme->itemDisabledStyle; + } Choice::Draw(dc); char temp[32]; sprintf(temp, "%i", *value_); dc.SetFontStyle(dc.theme->uiFont); - dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); + dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); } EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) { @@ -299,11 +307,15 @@ EventReturn PopupSliderChoiceFloat::HandleChange(EventParams &e) { } void PopupSliderChoiceFloat::Draw(UIContext &dc) { + Style style = dc.theme->itemStyle; + if (!IsEnabled()) { + style = dc.theme->itemDisabledStyle; + } Choice::Draw(dc); char temp[32]; sprintf(temp, "%2.2f", *value_); dc.SetFontStyle(dc.theme->uiFont); - dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_VCENTER); + dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); } EventReturn SliderPopupScreen::OnDecrease(EventParams ¶ms) { From c25cf61f54c02f439a934d0318849b16cfca8bde Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Dec 2013 12:07:09 +0100 Subject: [PATCH 0950/1445] Warning fix, delete broken Wait function in prio work queue --- file/chunk_file.cpp | 6 +++--- file/easy_file.cpp | 4 ++-- file/fd_util.cpp | 2 +- thread/prioritizedworkqueue.cpp | 14 -------------- thread/prioritizedworkqueue.h | 3 --- 5 files changed, 6 insertions(+), 23 deletions(-) diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index 8c5abaa8c0..072e36b387 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -24,7 +24,7 @@ ChunkFile::ChunkFile(const char *filename, bool _read) { didFail = true; return; } - eof = size; + eof = (int)size; return; } @@ -213,7 +213,7 @@ void ChunkFile::writeWString(String str) { // Takes utf-8 void ChunkFile::writeWString(const std::string &str) { unsigned short *text; - size_t len = str.length(); + int len = (int)str.length(); text = new unsigned short[len+1]; for (size_t i=0; i 0) { ssize_t nwritten; - if ((nwritten = write(fd, buffer, nleft)) <= 0) { + if ((nwritten = (ssize_t)write(fd, buffer, nleft)) <= 0) { if (errno == EINTR) nwritten = 0; else diff --git a/thread/prioritizedworkqueue.cpp b/thread/prioritizedworkqueue.cpp index ea54d35dac..c747a36ba8 100644 --- a/thread/prioritizedworkqueue.cpp +++ b/thread/prioritizedworkqueue.cpp @@ -67,20 +67,6 @@ PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() { } } -void PrioritizedWorkQueue::Wait(PrioritizedWorkQueueItem *item) { - while (true) { - bool stillThere = false; - lock_guard guard(mutex_); - for (int i = 0; i < queue_.empty(); i++) { - if (queue_[i] == item) - stillThere = true; - } - if (!stillThere) - break; - sleep_ms(100); - } -} - // TODO: This feels ugly. Revisit later. static std::thread *workThread; diff --git a/thread/prioritizedworkqueue.h b/thread/prioritizedworkqueue.h index 506e3146b0..9f5241c0e8 100644 --- a/thread/prioritizedworkqueue.h +++ b/thread/prioritizedworkqueue.h @@ -35,9 +35,6 @@ public: bool Done() { return done_; } void Stop(); - // Try not to use this. It's a hack. - void Wait(PrioritizedWorkQueueItem *item); - private: bool done_; recursive_mutex mutex_; From b99b826f5218c633f1f79d75e8e3e0b0e795443a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Dec 2013 20:45:51 +0100 Subject: [PATCH 0951/1445] Fix bug with missing files in APK --- file/zip_read.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 6264e67dce..1ec60e1c97 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -19,16 +19,14 @@ uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. struct zip_stat zstat; - zip_stat(archive, filename, ZIP_FL_NOCASE, &zstat); - - uint8_t *contents = new uint8_t[zstat.size + 1]; - zip_file *file = zip_fopen(archive, filename, 0); if (!file) { ELOG("Error opening %s from ZIP", filename); - delete [] contents; return 0; } + zip_stat(archive, filename, ZIP_FL_NOCASE, &zstat); + + uint8_t *contents = new uint8_t[zstat.size + 1]; zip_fread(file, contents, zstat.size); zip_fclose(file); contents[zstat.size] = 0; From 1be485c2a983806c820bf0aee2239fafab8662ee Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 12 Dec 2013 22:29:25 +0100 Subject: [PATCH 0952/1445] Be far less aggressive about retrying socket connections --- net/http_client.cpp | 4 ++-- net/http_client.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index f75a86d0a8..5a1f3d9c2e 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -64,7 +64,7 @@ bool Connection::Resolve(const char *host, int port) { return true; } -bool Connection::Connect() { +bool Connection::Connect(int maxTries) { if (port_ <= 0) { ELOG("Bad port"); return false; @@ -75,7 +75,7 @@ bool Connection::Connect() { return false; } - for (int tries = 100; tries > 0; --tries) { + for (int tries = maxTries; tries > 0; --tries) { for (addrinfo *possible = resolved_; possible != NULL; possible = possible->ai_next) { // TODO: Could support ipv6 without huge difficulty... if (possible->ai_family != AF_INET) diff --git a/net/http_client.h b/net/http_client.h index 0a88082d58..dbea901f6d 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -29,7 +29,7 @@ public: // Inits the sockaddr_in. bool Resolve(const char *host, int port); - bool Connect(); + bool Connect(int maxTries = 2); void Disconnect(); // Only to be used for bring-up and debugging. From e015a7caad5a8b2532a17e352e2dafbab45837bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 13 Dec 2013 11:03:40 +0100 Subject: [PATCH 0953/1445] PCMain.cpp: #ifdef away PPSSPP-isms (yeah, this is ugly and needs cleanup) --- base/PCMain.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 3b4668eaa9..61173dcd1e 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -13,6 +13,7 @@ #include "SDL/SDL_audio.h" #include "SDL/SDL_video.h" #else +#include #include #include "SDL.h" #include "SDL_timer.h" @@ -29,13 +30,15 @@ #include "base/NKCodeFromSDL.h" #include "util/const_map.h" #include "math/math_util.h" -#include "../SDL/SDLJoystick.h" +#include "SDL/SDLJoystick.h" + +#ifdef PPSSPP // Bad: PPSSPP includes from native #include "Core/Core.h" #include "Core/Config.h" - GlobalUIState lastUIState = UISTATE_MENU; +#endif #if defined(MAEMO) || defined(PANDORA) #define EGL @@ -338,12 +341,16 @@ int main(int argc, char *argv[]) { const SDL_VideoInfo* info = SDL_GetVideoInfo(); pixel_xres = info->current_w; pixel_yres = info->current_h; +#ifdef PPSSPP g_Config.bFullScreen = true; +#endif } else { // set a sensible default resolution (2x) pixel_xres = 480 * 2; pixel_yres = 272 * 2; +#ifdef PPSSPP g_Config.bFullScreen = false; +#endif } dp_xres = (float)pixel_xres; dp_yres = (float)pixel_yres; @@ -357,7 +364,10 @@ int main(int argc, char *argv[]) { EGL_Init(); #endif +#ifdef PPSSPP SDL_WM_SetCaption((app_name_nice + " " + PPSSPP_GIT_VERSION).c_str(), NULL); +#endif + #ifdef MAEMO SDL_ShowCursor(SDL_DISABLE); #endif @@ -593,7 +603,7 @@ int main(int argc, char *argv[]) { UpdateInputState(&input_state); NativeUpdate(input_state); NativeRender(); -#ifndef MAEMO +#if defined(PPSSPP) && !defined(MAEMO) if (lastUIState != globalUIState) { lastUIState = globalUIState; if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) From a83ac3514135e1ae30caa0ecf0498a85ea4b68f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 13 Dec 2013 12:17:46 +0100 Subject: [PATCH 0954/1445] Restore functionality of "legacy key maps" in SDL. For non-PPSSPP prototyping purposes. --- base/PCMain.cpp | 37 +++++++++++++++++++++++++++++++++++-- input/input_state.cpp | 2 +- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 61173dcd1e..7fe4550b20 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -266,13 +266,35 @@ std::string System_GetProperty(SystemProperty prop) { InputState input_state; +static const int legacyKeyMap[] { + NKCODE_X, //A + NKCODE_S, //B + NKCODE_Z, //X + NKCODE_A, //Y + NKCODE_W, //LBUMPER + NKCODE_Q, //RBUMPER + NKCODE_1, //START + NKCODE_2, //SELECT + NKCODE_DPAD_UP, //UP + NKCODE_DPAD_DOWN, //DOWN + NKCODE_DPAD_LEFT, //LEFT + NKCODE_DPAD_RIGHT, //RIGHT + 0, //MENU (SwipeDown) + NKCODE_ESCAPE, //BACK + NKCODE_I, //JOY UP + NKCODE_K, //JOY DOWN + NKCODE_J, //JOY LEFT + NKCODE_L, //JOY RIGHT +}; + void SimulateGamepad(const uint8 *keys, InputState *input) { + // Legacy key mapping. input->pad_buttons = 0; input->pad_lstick_x = 0; input->pad_lstick_y = 0; input->pad_rstick_x = 0; input->pad_rstick_y = 0; -// TODO: Use NativeAxis for joy instead. + #ifdef PANDORA if ((ljoy)||(rjoy)) { SDL_JoystickUpdate(); @@ -452,6 +474,7 @@ int main(int argc, char *argv[]) { int framecount = 0; float t = 0; float lastT = 0; + uint32_t pad_buttons = 0; // legacy pad buttons while (true) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; @@ -474,6 +497,11 @@ int main(int argc, char *argv[]) { key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); + + for (int i = 0; i < ARRAY_SIZE(legacyKeyMap); i++) { + if (legacyKeyMap[i] == key.keyCode) + pad_buttons |= 1 << i; + } break; } case SDL_KEYUP: @@ -484,6 +512,10 @@ int main(int argc, char *argv[]) { key.keyCode = KeyMapRawSDLtoNative.find(k)->second; key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); + for (int i = 0; i < ARRAY_SIZE(legacyKeyMap); i++) { + if (legacyKeyMap[i] == key.keyCode) + pad_buttons &= ~(1 << i); + } break; } case SDL_MOUSEBUTTONDOWN: @@ -600,7 +632,8 @@ int main(int argc, char *argv[]) { const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); SimulateGamepad(keys, &input_state); - UpdateInputState(&input_state); + input_state.pad_buttons = pad_buttons; + UpdateInputState(&input_state, true); NativeUpdate(input_state); NativeRender(); #if defined(PPSSPP) && !defined(MAEMO) diff --git a/input/input_state.cpp b/input/input_state.cpp index af6cc6ae63..dd4332ceeb 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -28,7 +28,7 @@ int MapPadButtonFixed(int keycode) { return PAD_BUTTON_A; case NKCODE_ESCAPE: - case NKCODE_BUTTON_2: + case NKCODE_BUTTON_2: case NKCODE_BUTTON_B: // same as NKCODE_OUYA_BUTTON_A and NKCODE_BUTTON_CIRCLE_PS3: return PAD_BUTTON_B; From 8166e7a094ff3d2bd8245b1ce529ad8d8967ac31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 13 Dec 2013 12:49:38 +0100 Subject: [PATCH 0955/1445] Let apps specify that they want portrait on startup again --- base/PCMain.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 7fe4550b20..f060c8ec9b 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -20,6 +20,9 @@ #include "SDL_audio.h" #include "SDL_video.h" #endif + +#include + #include "base/display.h" #include "base/logging.h" #include "base/timeutil.h" @@ -374,6 +377,11 @@ int main(int argc, char *argv[]) { g_Config.bFullScreen = false; #endif } + + if (!landscape) { + std::swap(pixel_xres, pixel_yres); + } + dp_xres = (float)pixel_xres; dp_yres = (float)pixel_yres; From da2b26299d211eb52622fbc0af85ece9e1c2cc35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 13 Dec 2013 16:09:09 +0100 Subject: [PATCH 0956/1445] Allow calling getFilesInDir with null files --- file/file_util.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index 7cbe7a3c06..250413bebf 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -316,7 +316,8 @@ size_t getFilesInDir(const char *directory, std::vector *files, const } } - files->push_back(info); + if (files) + files->push_back(info); #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); @@ -324,7 +325,8 @@ size_t getFilesInDir(const char *directory, std::vector *files, const } closedir(dirp); #endif - std::sort(files->begin(), files->end()); + if (files) + std::sort(files->begin(), files->end()); return foundEntries; } From 0909dcbbf5c5d085f306dd7bef19e986e3230cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 13 Dec 2013 16:13:18 +0100 Subject: [PATCH 0957/1445] getFilesInDir: Actually count the number of files. --- file/file_util.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/file/file_util.cpp b/file/file_util.cpp index 250413bebf..705884d800 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -318,6 +318,7 @@ size_t getFilesInDir(const char *directory, std::vector *files, const if (files) files->push_back(info); + foundEntries++; #ifdef _WIN32 } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); From 123cd269b5f5143cb47f799381161ad943ae6489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 13 Dec 2013 16:23:13 +0100 Subject: [PATCH 0958/1445] VFS: Always treat paths beginning with "/" as local file paths and bypass VFS. --- file/zip_read.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 1ec60e1c97..07df10fc65 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -312,9 +312,9 @@ void VFSShutdown() { uint8_t *VFSReadFile(const char *filename, size_t *size) { if (filename[0] == '/') { - // This is an absolute path, not a VFS file. Return 0. - ILOG("Not a VFS path: %s", filename); - return 0; + // Local path, not VFS. + ILOG("Not a VFS path: %s . Reading local file.", filename); + return ReadLocalFile(filename, size); } int fn_len = (int)strlen(filename); @@ -336,6 +336,12 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter) { + if (path[0] == '/') { + // Local path, not VFS. + ILOG("Not a VFS path: %s . Reading local directory.", path); + return getFilesInDir(path, listing, filter); + } + int fn_len = (int)strlen(path); for (int i = 0; i < num_entries; i++) { int prefix_len = (int)strlen(entries[i].prefix); @@ -353,6 +359,12 @@ bool VFSGetFileListing(const char *path, std::vector *listing, const c bool VFSGetFileInfo(const char *path, FileInfo *info) { + if (path[0] == '/') { + // Local path, not VFS. + ILOG("Not a VFS path: %s . Getting local file info.", path); + return getFileInfo(path, info); + } + int fn_len = (int)strlen(path); for (int i = 0; i < num_entries; i++) { int prefix_len = (int)strlen(entries[i].prefix); From 50bd9d74d128fc677a211a874d32a4323267d53d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 15 Dec 2013 18:20:15 -0800 Subject: [PATCH 0959/1445] Fix ATIClampBug being true on NVIDIA/etc. cards. I assume the logic was inversed by accident. --- gfx_es2/gl_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index eec6e0791c..a226fe9357 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -285,7 +285,7 @@ void CheckGLExtensions() { gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; - gl_extensions.ATIClampBug = ((strncmp (renderer, "ATI RADEON X", 12) != 0) || (strncmp (renderer, "ATI MOBILITY RADEON X",21) != 0)); + gl_extensions.ATIClampBug = ((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0)); } #endif From 92015879617429d8c2ad71b4d2d08b2fdf480f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 16 Dec 2013 14:05:51 +0100 Subject: [PATCH 0960/1445] PCMain.cpp: Allow forcing pixel resolution on the command line. Small optimization in gfx_es2 --- base/PCMain.cpp | 49 ++++++++++++++++++++++++++++++++--------- gfx_es2/draw_buffer.cpp | 18 +++++---------- 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index f060c8ec9b..517138269f 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -317,6 +317,18 @@ extern void mixaudio(void *userdata, Uint8 *stream, int len) { NativeMix((short *)stream, len / 4); } +// returns -1 on failure +int parseInt(const char *str) { + int val; + int retval = sscanf(str, "%d", &val); + printf("%i = sscanf %s\n", retval, str); + if (retval != 1) { + return -1; + } else { + return val; + } +} + #ifdef _WIN32 #undef main #endif @@ -358,9 +370,21 @@ int main(int argc, char *argv[]) { mode = SDL_SWSURFACE | SDL_FULLSCREEN; #else mode = SDL_OPENGL; - for (int i = 1; i < argc; i++) + int set_xres = -1; + int set_yres = -1; + for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; + if (set_xres == -2) { + set_xres = parseInt(argv[i]); + } else if (set_yres == -2) { + set_yres = parseInt(argv[i]); + } + if (!strcmp(argv[i],"--xres")) + set_xres = -2; + if (!strcmp(argv[i],"--yres")) + set_yres = -2; + } #endif if (mode & SDL_FULLSCREEN) { const SDL_VideoInfo* info = SDL_GetVideoInfo(); @@ -382,13 +406,20 @@ int main(int argc, char *argv[]) { std::swap(pixel_xres, pixel_yres); } + if (set_xres > 0) { + pixel_xres = set_xres; + } + if (set_yres > 0) { + pixel_yres = set_yres; + } + dp_xres = (float)pixel_xres; dp_yres = (float)pixel_yres; if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode) == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); - return(2); + return 2; } #ifdef EGL EGL_Init(); @@ -443,10 +474,6 @@ int main(int argc, char *argv[]) { #endif pixel_in_dps = (float)pixel_xres / dp_xres; - - float dp_xscale = (float)dp_xres / pixel_xres; - float dp_yscale = (float)dp_yres / pixel_yres; - g_dpi_scale = dp_xres / (float)pixel_xres; printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); @@ -461,8 +488,9 @@ int main(int argc, char *argv[]) { fmt.callback = &mixaudio; fmt.userdata = (void *)0; - if (SDL_OpenAudio(&fmt, NULL) < 0) + if (SDL_OpenAudio(&fmt, NULL) < 0) { ELOG("Failed to open audio: %s", SDL_GetError()); + } // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); @@ -482,7 +510,7 @@ int main(int argc, char *argv[]) { int framecount = 0; float t = 0; float lastT = 0; - uint32_t pad_buttons = 0; // legacy pad buttons + uint32_t pad_buttons = 0; // legacy pad buttons while (true) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; @@ -490,8 +518,8 @@ int main(int argc, char *argv[]) { SDL_Event event; while (SDL_PollEvent(&event)) { - float mx = event.motion.x * dp_xscale; - float my = event.motion.y * dp_yscale; + float mx = event.motion.x * g_dpi_scale; + float my = event.motion.y * g_dpi_scale; switch (event.type) { case SDL_QUIT: @@ -532,7 +560,6 @@ int main(int argc, char *argv[]) { { input_state.pointer_x[0] = mx; input_state.pointer_y[0] = my; - //input_state.mouse_buttons_down = 1; input_state.pointer_down[0] = true; input_state.mouse_valid = true; TouchInput input; diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index d27bf439f1..fe861c08ad 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -203,19 +203,14 @@ void DrawBuffer::DrawImageStretch(ImageID atlas_image, float x1, float y1, float } inline void rot(float *v, float angle, float xc, float yc) { - v[0]-=xc; - v[1]-=yc; - - float ca=cosf(angle),sa=sinf(angle); - - float t0 = v[0] * ca + v[1] * -sa; - float t1 = v[0] * sa + v[1] * ca; - - v[0] = t0 + xc; - v[1] = t1 + yc; + const float x = v[0] - xc; + const float y = v[1] - yc; + const float sa = sinf(angle); + const float ca = cosf(angle); + v[0] = x * ca + y * -sa + xc; + v[1] = x * sa + y * ca + yc; } - void DrawBuffer::DrawImageRotated(ImageID atlas_image, float x, float y, float scale, float angle, Color color, bool mirror_h) { const AtlasImage &image = atlas->images[atlas_image]; float w = (float)image.w * scale; @@ -253,7 +248,6 @@ void DrawBuffer::DrawImageRotated(ImageID atlas_image, float x, float y, float s } } - // TODO: add arc support void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul) { float angleDelta = PI * 2 / segments; From 1ef531ec9cb74e9490dcff8ba7c427588eff0b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 16 Dec 2013 16:19:40 +0100 Subject: [PATCH 0961/1445] Add some infrastructure to handle screen resizes that don't lose the device --- android/app-android.cpp | 50 +++++++++++++++++------------------------ base/NativeApp.h | 10 ++++++--- ui/screen.cpp | 7 ++++++ ui/screen.h | 2 ++ 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 11a51bfe89..975ac96b7e 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -52,11 +52,6 @@ void SystemToast(const char *text) { frameCommandParam = text; } -// TODO: need a Hide or bool show; -void ShowAd(int x, int y, bool center_x) { - ELOG("TODO! ShowAd!"); -} - void ShowKeyboard() { frameCommand = "showKeyboard"; frameCommandParam = ""; @@ -103,8 +98,8 @@ std::string System_GetProperty(SystemProperty prop) { // Remember that all of these need initialization on init! The process // may be reused when restarting the game. Globals are DANGEROUS. -float dp_xscale = 1; -float dp_yscale = 1; +float dp_xscale = 1.0f; +float dp_yscale = 1.0f; InputState input_state; @@ -113,16 +108,14 @@ static bool first_lost = true; static bool use_opensl_audio = false; static std::string library_path; -std::string GetJavaString(JNIEnv *env, jstring jstr) -{ +std::string GetJavaString(JNIEnv *env, jstring jstr) { const char *str = env->GetStringUTFChars(jstr, 0); std::string cpp_string = std::string(str); env->ReleaseStringUTFChars(jstr, str); return cpp_string; } -extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) -{ +extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) { std::string app_name, app_nice_name; bool landscape; NativeGetAppInfo(&app_name, &app_nice_name, &landscape); @@ -240,7 +233,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jc static jmethodID postCommand; extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { - ILOG("NativeApp.displayInit()"); + ILOG("NativeApp.displayInit(pixel_xres = %i, pixel_yres = %i)", pixel_xres, pixel_yres); if (!renderer_inited) { // We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S). // Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo @@ -265,6 +258,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIE extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { ILOG("NativeApp.displayResize(%i, %i)", w, h); + // TODO: Move some of the logic from displayInit here? pixel_xres = w; pixel_yres = h; @@ -272,6 +266,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JN dp_yres = pixel_yres * g_dpi_scale; dp_xscale = (float)dp_xres / pixel_xres; dp_yscale = (float)dp_yres / pixel_yres; + + NativeResized(); } extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { @@ -332,9 +328,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayShutdown( // This path is not used if OpenSL ES is available. extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { - // Too spammy - // ILOG("NativeApp.audioRender"); - // The audio thread can pretty safely enable Flush-to-Zero mode on the FPU. EnableFZ(); @@ -356,8 +349,6 @@ extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* e extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch (JNIEnv *, jclass, float x, float y, int code, int pointerId) { - // ELOG("Touch Enter %i", pointerId); - float scaledX = (int)(x * dp_xscale); // why the (int) cast? float scaledY = (int)(y * dp_yscale); @@ -376,21 +367,18 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch } NativeTouch(touch); - - lock_guard guard(input_state.lock); - - if (pointerId >= MAX_POINTERS) { - ELOG("Too many pointers: %i", pointerId); - return; // We ignore 8+ pointers entirely. + { + lock_guard guard(input_state.lock); + if (pointerId >= MAX_POINTERS) { + ELOG("Too many pointers: %i", pointerId); + return; // We ignore 8+ pointers entirely. + } + input_state.pointer_x[pointerId] = scaledX; + input_state.pointer_y[pointerId] = scaledY; + input_state.mouse_valid = true; } - input_state.pointer_x[pointerId] = scaledX; - input_state.pointer_y[pointerId] = scaledY; - input_state.mouse_valid = true; - - // ELOG("Touch Exit %i", pointerId); } - extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint deviceId, jint key) { KeyInput keyInput; keyInput.deviceId = deviceId; @@ -414,6 +402,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_beginJoystickEvent( extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickAxis( JNIEnv *env, jclass, jint deviceId, jint axisId, jfloat value) { + if (!renderer_inited) + return; switch (axisId) { case JOYSTICK_AXIS_X: left_joystick_x_async = value; @@ -454,6 +444,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_mouseWheelEvent( } extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) { + if (!renderer_inited) + return; // Theoretically this needs locking but I doubt it matters. Worst case, the X // from one "sensor frame" will be used together with Y from the next. // Should look into quantization though, for compressed movement storage. diff --git a/base/NativeApp.h b/base/NativeApp.h index c81ffe8303..0b1ba00f0a 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -35,11 +35,15 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co // Runs after NativeInit() at some point. May (and probably should) call OpenGL. void NativeInitGraphics(); -// Signals that you need to recreate all buffered OpenGL resources, -// like textures, vbo etc. Also, if you have modified dp_xres and dp_yres, you have to -// do it again here. Main thread. +// Signals that you need to destroy and recreate all buffered OpenGL resources, +// like textures, vbo etc. void NativeDeviceLost(); +// If you want to change DPI stuff (such as modifying dp_xres and dp_yres), this is the +// place to do it. You should only read g_dpi_scale and pixel_xres and pixel_yres in this, +// and only write dp_xres and dp_yres. +void NativeResized(); + // Called ~sixty times a second, delivers the current input state. // Main thread. void NativeUpdate(InputState &input); diff --git a/ui/screen.cpp b/ui/screen.cpp index 27a0c6ffe0..7219f2a7ad 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -79,6 +79,13 @@ void ScreenManager::axis(const AxisInput &axis) { stack_.back().screen->axis(axis); } +void ScreenManager::resized() { + // Have to notify the whole stack, otherwise there will be problems when going back + // to non-top screens. + for (auto iter = stack_.begin(); iter != stack_.end(); ++iter) { + iter->screen->resized(); + } +} void ScreenManager::render() { if (!stack_.empty()) { diff --git a/ui/screen.h b/ui/screen.h index 4a4e13778e..4df96d1c86 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -48,6 +48,7 @@ public: virtual void update(InputState &input) {} virtual void render() {} virtual void deviceLost() {} + virtual void resized() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} virtual void touch(const TouchInput &touch) {} virtual void key(const KeyInput &key) {} @@ -95,6 +96,7 @@ public: UIContext *getUIContext() { return uiContext_; } void render(); + void resized(); void deviceLost(); void shutdown(); From c21fa64c19b69e1bb90967141eed52d8c97490ff Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 17 Dec 2013 09:09:39 +0100 Subject: [PATCH 0962/1445] Force ARB_blend_func_extended off on OpenGL < 3.0. --- gfx_es2/gl_state.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index a226fe9357..f72e790960 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -166,9 +166,9 @@ void CheckGLExtensions() { #endif #else // If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable - // modern paths. + // all the same modern paths. // Most of it could be enabled on lower GPUs as well, but let's start this way. - if ((gl_extensions.ver[0] == 4 && gl_extensions.ver[1] >= 3) || gl_extensions.ver[0] > 4) { + if (gl_extensions.VersionGEThan(4, 3, 0)) { gl_extensions.GLES3 = true; } #endif @@ -197,6 +197,10 @@ void CheckGLExtensions() { gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; + if (!gl_extensions.VersionGEThan(3, 0, 0)) { + // Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable + gl_extensions.ARB_blend_func_extended = false; + } #ifdef USING_GLES2 gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0; From 828db2b23369545633c9e8293b8a89e68e7ac37b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 17 Dec 2013 12:25:19 +0100 Subject: [PATCH 0963/1445] Blacklist ARB_blend_func_extended on Intel. See ppsspp issue #4867 --- gfx_es2/gl_state.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index f72e790960..3b34f10339 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -197,8 +197,9 @@ void CheckGLExtensions() { gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; - if (!gl_extensions.VersionGEThan(3, 0, 0)) { + if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) { // Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable + // Also on Intel, see https://github.com/hrydgard/ppsspp/issues/4867 gl_extensions.ARB_blend_func_extended = false; } From ce20273f5f5150568da178f5514b8f5228b56ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 19 Dec 2013 14:27:16 +0100 Subject: [PATCH 0964/1445] Add showTwitter command (Android-only). --- .../src/com/henrikrydgard/libnative/NativeActivity.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index b808dda013..fa1f599e47 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -679,7 +679,14 @@ public class NativeActivity extends Activity { sendIntent.setType("text/plain"); sendIntent.putExtra(Intent.EXTRA_TEXT, params); sendIntent.setAction(Intent.ACTION_SEND); - startActivity(sendIntent); + startActivity(sendIntent); + } else if (command.equals("showTwitter")) { + String twitter_user_name = params; + try { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("twitter://user?screen_name=" + twitter_user_name))); + } catch (Exception e) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/#!/" + twitter_user_name))); + } } else if (command.equals("launchMarket")) { // Don't need this, can just use launchBrowser with a market: // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app From ecd364d85484303a61a45d8b7e2aef5f170714f1 Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 20 Dec 2013 00:41:42 +1000 Subject: [PATCH 0965/1445] Fix a typo that was causing VFS to fail for Qt. --- file/zip_read.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 07df10fc65..e4bc70aac4 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -90,7 +90,7 @@ bool AssetsAssetReader::GetFileListing(const char *path, std::vector * bool AssetsAssetReader::GetFileInfo(const char *path, FileInfo *info) { QFileInfo qinfo(QString(":/assets/") + path); - if (qinfo.exists()) { + if (!qinfo.exists()) { info->exists = false; info->size = 0; return false; From 6670d0003a1960244993145703cd26c732b1c435 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 21 Dec 2013 13:45:11 +0100 Subject: [PATCH 0966/1445] Set ATIClampBug on Tegra as it appears to apply. --- Android.mk | 2 +- gfx_es2/gl_state.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index b8ccad29a3..f9575cdb36 100644 --- a/Android.mk +++ b/Android.mk @@ -98,7 +98,7 @@ LOCAL_SRC_FILES :=\ util/hash/hash.cpp LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -Wall -Wno-multichar -D__STDC_CONSTANT_MACROS -LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -fno-rtti -Wno-reorder -Wno-literal-suffix +LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -fno-rtti -Wno-reorder LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext $(LOCAL_PATH)/ext/libzip diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 3b34f10339..a64a593bcb 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -282,6 +282,7 @@ void CheckGLExtensions() { #ifdef USING_GLES2 gl_extensions.FBO_ARB = true; gl_extensions.FBO_EXT = false; + gl_extensions.ATIClampBug = gl_extensions.gpuVendor == GPU_VENDOR_NVIDIA; // Tegras - TODO: more specific check #else gl_extensions.FBO_ARB = false; gl_extensions.FBO_EXT = false; From eb2d8ac7c9a1d3c13e21bfb4f6ee9c47bef73992 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 23 Dec 2013 20:04:07 +1000 Subject: [PATCH 0967/1445] Qt: Update sound according to #4761. --- base/QtMain.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index 067460e8c8..1d9140617b 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -245,10 +245,10 @@ public slots: fmt.setSampleSize(AUDIO_SAMPLESIZE); fmt.setByteOrder(QAudioFormat::LittleEndian); fmt.setSampleType(QAudioFormat::SignedInt); - mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; + mixlen = 5*2*AUDIO_CHANNELS*AUDIO_SAMPLES; mixbuf = (char*)malloc(mixlen); output = new QAudioOutput(fmt); - output->setBufferSize(mixlen*10); + output->setBufferSize(mixlen); feed = output->start(); if (feed != NULL) timer = startTimer(1000*AUDIO_SAMPLES / AUDIO_FREQ); @@ -257,7 +257,7 @@ public slots: protected: void timerEvent(QTimerEvent *) { memset(mixbuf, 0, mixlen); - size_t frames = NativeMix((short *)mixbuf, AUDIO_SAMPLES); + size_t frames = NativeMix((short *)mixbuf, 5*AUDIO_SAMPLES); if (frames > 0) feed->write(mixbuf, sizeof(short) * 2 * frames); } From 3cd4fcb03d1737554d35eeeff9bbb81000ab4646 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 27 Dec 2013 22:41:58 +0800 Subject: [PATCH 0968/1445] Add fbo_get_depth_buffer & fbo_get_stencil_buffer --- gfx_es2/fbo.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 99b52420a1..467689c15b 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -320,3 +320,11 @@ void fbo_get_dimensions(FBO *fbo, int *w, int *h) { int fbo_get_color_texture(FBO *fbo) { return fbo->color_texture; } + +int fbo_get_depth_buffer(FBO *fbo) { + return fbo->z_buffer; +} + +int fbo_get_stencil_buffer(FBO *fbo) { + return fbo->stencil_buffer; +} From 1f64a8a23258e3283b39721fe36b0148a58893e2 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 27 Dec 2013 22:43:19 +0800 Subject: [PATCH 0969/1445] Update fbo.h --- gfx_es2/fbo.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index fdcb76a15c..e424451aa0 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -33,4 +33,6 @@ void fbo_unbind(); void fbo_destroy(FBO *fbo); void fbo_get_dimensions(FBO *fbo, int *w, int *h); -int fbo_get_color_texture(FBO *fbo); \ No newline at end of file +int fbo_get_color_texture(FBO *fbo); +int fbo_get_depth_buffer(FBO *fbo); +int fbo_get_stencil_buffer(FBO *fbo); From 20e1d2c6c5fa23311ff045192c34886a5a21b4df Mon Sep 17 00:00:00 2001 From: raven02 Date: Sat, 28 Dec 2013 02:15:36 +0800 Subject: [PATCH 0970/1445] Add gl_extensions.ARB_shader_image_load_store --- gfx_es2/gl_state.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index a64a593bcb..7f92d1dceb 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -197,6 +197,7 @@ void CheckGLExtensions() { gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; + gl_extensions.ARB_shader_image_load_store = strstr(extString, "GL_ARB_shader_image_load_store") != 0; if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) { // Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable // Also on Intel, see https://github.com/hrydgard/ppsspp/issues/4867 From 41fb2c113885abad79e89d96c3dace47f71095ad Mon Sep 17 00:00:00 2001 From: raven02 Date: Sat, 28 Dec 2013 02:16:38 +0800 Subject: [PATCH 0971/1445] bool ARB_shader_image_load_store --- gfx_es2/gpu_features.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 506cfad639..37cec29d7e 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -48,7 +48,7 @@ struct GLExtensions { bool NV_copy_image; bool EXT_unpack_subimage; // always supported on desktop and ES3 bool ARB_blend_func_extended; // dual source blending - + bool ARB_shader_image_load_store; // EGL extensions bool EGL_NV_system_time; From 63716cc0855d043a23452331b896e7c6713c8261 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sat, 28 Dec 2013 02:40:06 +0800 Subject: [PATCH 0972/1445] Supports GL_EXT_shader_image_load_store as well --- gfx_es2/gl_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 7f92d1dceb..7afa28698f 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -197,7 +197,7 @@ void CheckGLExtensions() { gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; - gl_extensions.ARB_shader_image_load_store = strstr(extString, "GL_ARB_shader_image_load_store") != 0; + gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) { // Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable // Also on Intel, see https://github.com/hrydgard/ppsspp/issues/4867 From 4cb8c4062a77981567013d05fee6fb6402131e45 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 2 Jan 2014 00:08:22 +0100 Subject: [PATCH 0973/1445] Get rid of "ATIClampBug" because it's not a bug. --- gfx_es2/gl_state.cpp | 6 ++++-- gfx_es2/gpu_features.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 7afa28698f..952524082f 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -195,6 +195,9 @@ void CheckGLExtensions() { // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; #endif + // Check the desktop extension instead of the OES one. They are very similar. + gl_extensions.OES_texture_npot = strstr(extString, "GL_ARB_texture_non_power_of_two") != 0; + gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); @@ -205,6 +208,7 @@ void CheckGLExtensions() { } #ifdef USING_GLES2 + gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0; gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0; gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; @@ -283,7 +287,6 @@ void CheckGLExtensions() { #ifdef USING_GLES2 gl_extensions.FBO_ARB = true; gl_extensions.FBO_EXT = false; - gl_extensions.ATIClampBug = gl_extensions.gpuVendor == GPU_VENDOR_NVIDIA; // Tegras - TODO: more specific check #else gl_extensions.FBO_ARB = false; gl_extensions.FBO_EXT = false; @@ -292,7 +295,6 @@ void CheckGLExtensions() { gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; - gl_extensions.ATIClampBug = ((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0)); } #endif diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 37cec29d7e..0e0de4ac6c 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -34,6 +34,7 @@ struct GLExtensions { bool OES_depth24; bool OES_packed_depth_stencil; bool OES_depth_texture; + bool OES_texture_npot; // If this is set, can wrap non-pow-2 textures. Set on desktop. bool EXT_discard_framebuffer; bool FBO_ARB; bool FBO_EXT; @@ -43,7 +44,6 @@ struct GLExtensions { bool OES_vertex_array_object; bool EXT_shader_framebuffer_fetch; bool EXT_blend_minmax; - bool ATIClampBug; bool NV_draw_texture; bool NV_copy_image; bool EXT_unpack_subimage; // always supported on desktop and ES3 From 69fd1d6594096d7407945b81843354bf8f6ee648 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 2 Jan 2014 00:29:34 +0100 Subject: [PATCH 0974/1445] Fix USING_GLES2 + SDL builds, if we ever have any --- base/PCMain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 517138269f..a5dd918387 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -368,6 +368,8 @@ int main(int argc, char *argv[]) { int mode; #ifdef USING_GLES2 mode = SDL_SWSURFACE | SDL_FULLSCREEN; + int set_xres = -1; + int set_yres = -1; #else mode = SDL_OPENGL; int set_xres = -1; From ee34dcbfa6059f54d076522ecc398ca0b10d0509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Jan 2014 14:21:24 +0100 Subject: [PATCH 0975/1445] Fix bug in key repeat handling, and ignore the host key repeat system. May fix navigation issues on Ouya. --- ui/viewgroup.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index d6b7f12a3e..91c76c27f1 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1085,6 +1085,7 @@ struct HeldKey { int deviceId; int startFrame; + // Ignores startFrame bool operator <(const HeldKey &other) const { if (deviceId < other.deviceId) return true; if (deviceId > other.deviceId) return false; @@ -1103,15 +1104,21 @@ void KeyEvent(const KeyInput &key, ViewGroup *root) { if (key.flags & KEY_DOWN) { // We ignore the device ID here. Anything with a DPAD is OK. if (key.keyCode >= NKCODE_DPAD_UP && key.keyCode <= NKCODE_DPAD_RIGHT) { - lock_guard lock(focusLock); - focusMoves.push_back(key.keyCode); - // Let's only repeat DPAD initially. HeldKey hk; hk.key = key.keyCode; hk.deviceId = key.deviceId; hk.startFrame = frameCount; + + // Check if the key is already held. If it is, ignore it. This is to avoid + // multiple key repeat mechanisms colliding. + if (heldKeys.find(hk) != heldKeys.end()) { + return; + } + heldKeys.insert(hk); + lock_guard lock(focusLock); + focusMoves.push_back(key.keyCode); } } if (key.flags & KEY_UP) { @@ -1137,6 +1144,9 @@ static void ProcessHeldKeys(ViewGroup *root) { key.deviceId = iter->deviceId; key.flags = KEY_DOWN; KeyEvent(key, root); + + lock_guard lock(focusLock); + focusMoves.push_back(key.keyCode); } } } From 73f612aaa8e84d6576f5d85d7a605e6528547a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Jan 2014 15:15:35 +0100 Subject: [PATCH 0976/1445] SDL: Add preliminary fullscreen toggle support. Does not seem to work very well on Mac. --- base/PCMain.cpp | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index a5dd918387..4edddaab92 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -43,6 +43,9 @@ GlobalUIState lastUIState = UISTATE_MENU; #endif +static SDL_Surface* g_Screen = NULL; +bool g_ToggleFullScreenNextFrame = false; + #if defined(MAEMO) || defined(PANDORA) #define EGL #include "EGL/egl.h" @@ -51,11 +54,11 @@ GlobalUIState lastUIState = UISTATE_MENU; #include "SDL_syswm.h" #include "math.h" -EGLDisplay g_eglDisplay = NULL; -EGLContext g_eglContext = NULL; -EGLSurface g_eglSurface = NULL; -Display* g_Display = NULL; -NativeWindowType g_Window = (NativeWindowType)NULL; +static EGLDisplay g_eglDisplay = NULL; +static EGLContext g_eglContext = NULL; +static EGLSurface g_eglSurface = NULL; +static Display* g_Display = NULL; +static NativeWindowType g_Window = (NativeWindowType)NULL; int8_t CheckEGLErrors(const std::string& file, uint16_t line) { EGLenum error; @@ -203,7 +206,9 @@ void Vibrate(int length_ms) { } void System_SendMessage(const char *command, const char *parameter) { - // Log? + if (!strcmp(command, "toggle_fullscreen")) { + g_ToggleFullScreenNextFrame = true; + } } void LaunchBrowser(const char *url) { @@ -299,7 +304,7 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_rstick_y = 0; #ifdef PANDORA - if ((ljoy)||(rjoy)) { + if (ljoy || rjoy) { SDL_JoystickUpdate(); if (ljoy) { input->pad_lstick_x = max(min(SDL_JoystickGetAxis(ljoy, 0) / 32000.0f, 1.0f), -1.0f); @@ -329,6 +334,23 @@ int parseInt(const char *str) { } } +void ToggleFullScreenIfFlagSet() { + if (g_ToggleFullScreenNextFrame) { + g_ToggleFullScreenNextFrame = false; + +#if 1 + int flags = g_Screen->flags; // Save the current flags in case toggling fails + g_Screen = SDL_SetVideoMode(0, 0, 0, g_Screen->flags ^ SDL_FULLSCREEN); // Toggles FullScreen Mode + if (g_Screen == NULL) { + g_Screen = SDL_SetVideoMode(0, 0, 0, flags); // If toggle FullScreen failed, then switch back + } + if (g_Screen == NULL) { + exit(1); // If you can't switch back for some reason, then epic fail + } +#endif + } +} + #ifdef _WIN32 #undef main #endif @@ -418,11 +440,13 @@ int main(int argc, char *argv[]) { dp_xres = (float)pixel_xres; dp_yres = (float)pixel_yres; - if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode) == NULL) { + g_Screen = SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode); + if (g_Screen == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return 2; } + #ifdef EGL EGL_Init(); #endif @@ -698,6 +722,8 @@ int main(int argc, char *argv[]) { lastT = t; } #endif + + ToggleFullScreenIfFlagSet(); time_update(); t = time_now(); framecount++; From ed8df1005d995abbc2f96ce52e0213f1cc46327d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 4 Jan 2014 11:13:44 -0800 Subject: [PATCH 0977/1445] Use GL_READ/DRAW_FRAMEBUFFER on desktop GL. Even for < OpenGL 4.3 (GLES3 = false.) --- gfx_es2/fbo.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 467689c15b..a38408404c 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -253,7 +253,11 @@ void fbo_unbind() { void fbo_bind_as_render_target(FBO *fbo) { if (gl_extensions.FBO_ARB) { +#ifndef USING_GLES2 + if (true) { +#else if (gl_extensions.GLES3) { +#endif glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); } else { // This will collide with bind_for_read - but there's nothing in ES 2.0 @@ -269,7 +273,11 @@ void fbo_bind_as_render_target(FBO *fbo) { void fbo_bind_for_read(FBO *fbo) { if (gl_extensions.FBO_ARB) { +#ifndef USING_GLES2 + if (true) { +#else if (gl_extensions.GLES3) { +#endif glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); } else { // This will collide with bind_as_render_target - but there's nothing in ES 2.0 From a2dfb0f5ea2a0c27cd34659a546ebcc2b03533f3 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 5 Jan 2014 10:53:47 +1000 Subject: [PATCH 0978/1445] Fix Qt for Maemo --- base/QtMain.cpp | 6 ++++-- base/QtMain.h | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 68aee05a08..24aa1496eb 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -35,6 +35,8 @@ std::string System_GetProperty(SystemProperty prop) { return "Qt:Blackberry"; #elif defined(MEEGO_EDITION_HARMATTAN) return "Qt:Meego"; +#elif defined(MAEMO) + return "Qt:Maemo"; #elif defined(Q_OS_LINUX) return "Qt:Linux"; #elif defined(_WIN32) @@ -100,7 +102,7 @@ Q_DECL_EXPORT #endif int main(int argc, char *argv[]) { -#ifdef Q_OS_LINUX +#if defined(Q_OS_LINUX) && !defined(MAEMO) QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); @@ -118,7 +120,7 @@ int main(int argc, char *argv[]) #elif defined(BLACKBERRY) const char *savegame_dir = "/accounts/1000/shared/misc/"; const char *assets_dir = "app/native/assets/"; -#elif defined(MEEGO_EDITION_HARMATTAN) +#elif defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) const char *savegame_dir = "/home/user/MyDocs/PPSSPP/"; const char *assets_dir = "/opt/PPSSPP/"; #else diff --git a/base/QtMain.h b/base/QtMain.h index 1d9140617b..08dfab062b 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -9,7 +9,7 @@ #include #include -#ifdef USING_GLES2 +#if defined(USING_GLES2) && !defined(MAEMO) #include QTM_USE_NAMESPACE #endif @@ -193,7 +193,7 @@ protected: void updateAccelerometer() { -#ifdef USING_GLES2 +#if defined(USING_GLES2) && !defined(MAEMO) // TODO: Toggle it depending on whether it is enabled QAccelerometerReading *reading = acc->reading(); if (reading) { @@ -206,7 +206,7 @@ protected: private: InputState input_state; -#ifdef USING_GLES2 +#if defined(USING_GLES2) && !defined(MAEMO) QAccelerometer* acc; #endif }; From 432fa7e6e6fd3307d3b14253f8cdf5f44e9544b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Jan 2014 12:49:40 +0100 Subject: [PATCH 0979/1445] Workaround for broken key repeat on Ouya - it sends repeats with a different device ID --- .../src/com/henrikrydgard/libnative/InputDeviceState.java | 3 +++ ui/viewgroup.cpp | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/InputDeviceState.java b/android/src/com/henrikrydgard/libnative/InputDeviceState.java index 5f0adf7e2a..dcfd8d47a6 100644 --- a/android/src/com/henrikrydgard/libnative/InputDeviceState.java +++ b/android/src/com/henrikrydgard/libnative/InputDeviceState.java @@ -2,6 +2,7 @@ package com.henrikrydgard.libnative; import android.annotation.TargetApi; import android.os.Build; +import android.util.Log; import android.view.InputDevice; import android.view.InputDevice.MotionRange; import android.view.KeyEvent; @@ -9,6 +10,8 @@ import android.view.MotionEvent; @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) public class InputDeviceState { + private static final String TAG = "InputDeviceState"; + // DEVICE_ID_PAD_0 from the cpp code. TODO: allocate these sequentially if we get more controllers. private static int deviceId = 10; diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 91c76c27f1..d867d26fd7 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1080,6 +1080,9 @@ void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { static int frameCount; +// Ignore deviceId when checking for matches. Turns out that Ouya for example sends +// completely broken input where the original keypresses have deviceId = 10 and the repeats +// have deviceId = 0. struct HeldKey { int key; int deviceId; @@ -1087,12 +1090,10 @@ struct HeldKey { // Ignores startFrame bool operator <(const HeldKey &other) const { - if (deviceId < other.deviceId) return true; - if (deviceId > other.deviceId) return false; if (key < other.key) return true; return false; } - bool operator ==(const HeldKey &other) const { return key == other.key && deviceId == other.deviceId; } + bool operator ==(const HeldKey &other) const { return key == other.key; } }; static std::set heldKeys; From e3a1ecf8a47c7ab3fe909fcb2c312a6abad9b03b Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 5 Jan 2014 23:35:58 +1000 Subject: [PATCH 0980/1445] Qt: Last fix for Maemo. Confirmed compiling. Thanks @AapoRantalainen --- base/QtMain.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index 08dfab062b..22f6ae8f74 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -45,7 +45,7 @@ public: #if QT_VERSION < 0x50000 setAttribute(Qt::WA_LockLandscapeOrientation); #endif -#ifdef USING_GLES2 +#if defined(USING_GLES2) || defined(MAEMO) acc = new QAccelerometer(this); acc->start(); #endif @@ -54,7 +54,7 @@ public: startTimer(16); } ~MainUI() { -#ifdef USING_GLES2 +#if defined(USING_GLES2) || defined(MAEMO) delete acc; #endif NativeShutdownGraphics(); From 469088b16221efb8d858d721589b878f3377b6d1 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 6 Jan 2014 10:41:53 +1000 Subject: [PATCH 0981/1445] Oops. Maemo fix. --- base/QtMain.cpp | 2 +- base/QtMain.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 24aa1496eb..a4a20327ab 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -3,7 +3,7 @@ * */ // Qt 4.7+ / 5.0+ implementation of the framework. -// Currently supports: Symbian, Blackberry, Meego, Linux, Windows, Mac OSX +// Currently supports: Symbian, Blackberry, Maemo/Meego, Linux, Windows, Mac OSX #include #include diff --git a/base/QtMain.h b/base/QtMain.h index 22f6ae8f74..13ea21b22b 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -45,7 +45,7 @@ public: #if QT_VERSION < 0x50000 setAttribute(Qt::WA_LockLandscapeOrientation); #endif -#if defined(USING_GLES2) || defined(MAEMO) +#if defined(USING_GLES2) && !defined(MAEMO) acc = new QAccelerometer(this); acc->start(); #endif @@ -54,7 +54,7 @@ public: startTimer(16); } ~MainUI() { -#if defined(USING_GLES2) || defined(MAEMO) +#if defined(USING_GLES2) && !defined(MAEMO) delete acc; #endif NativeShutdownGraphics(); From 87533085fa939e85ed190b5ed4b4190d722737b7 Mon Sep 17 00:00:00 2001 From: valef Date: Sun, 5 Jan 2014 23:11:59 +0700 Subject: [PATCH 0982/1445] Added 'shortcutParam' argument to init() method declaration. public static native void init(int dpi, String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, boolean useOpenSL); --- android/src/com/henrikrydgard/libnative/NativeApp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 9d97f339fe..a34c2f9cab 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -6,7 +6,7 @@ public class NativeApp { public final static int DEVICE_ID_MOUSE = 2; public final static int DEVICE_ID_PAD_0 = 10; - public static native void init(int dpi, String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String installID, boolean useOpenSL); + public static native void init(int dpi, String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, boolean useOpenSL); public static native void audioInit(); public static native void audioShutdown(); From 234344983a5268504d54cc865c0e5657415b14ac Mon Sep 17 00:00:00 2001 From: valef Date: Sun, 5 Jan 2014 23:14:26 +0700 Subject: [PATCH 0983/1445] - Added key to get shortcut parameter. public static final String SHORTCUT_EXTRA_KEY = "org.ppsspp.ppsspp.Shortcuts"; - Added code to get shortcut parameter from intent. String shortcutParam = getIntent().getStringExtra(SHORTCUT_EXTRA_KEY); - Call NativeApp.init() with shortcutParam argument. NativeApp.init(dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL); --- .../henrikrydgard/libnative/NativeActivity.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index fa1f599e47..a03cc8439a 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -87,6 +87,9 @@ public class NativeActivity extends Activity { // Adjust these as necessary private static String TAG = "NativeActivity"; + + // Key used by shortcut creation. + public static final String SHORTCUT_EXTRA_KEY = "org.ppsspp.ppsspp.Shortcuts"; // Easy way to flip it on and off from code. private static final boolean useKitkatImmersiveMode = false; @@ -203,6 +206,15 @@ public class NativeActivity extends Activity { e.printStackTrace(); throw new RuntimeException("Unable to locate assets, aborting..."); } + + // Get shortcut parameter, in case app was launched from homescreen shortcut. + // We obtain shortcut parameter from Intent extra string. + // Intent extra will be null if we launch from normal app drawer. + String shortcutParam = getIntent().getStringExtra(SHORTCUT_EXTRA_KEY); + if(shortcutParam == null) { + shortcutParam = new String(""); + } + String libraryDir = getApplicationLibraryDir(appInfo); File sdcard = Environment.getExternalStorageDirectory(); Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); @@ -230,7 +242,7 @@ public class NativeActivity extends Activity { String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, installID, useOpenSL); + NativeApp.init(dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL); Log.i(TAG, "Device: " + deviceType); Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat + " dpi: " + dpi); From b2c3ee8d57d1af22e0bc1cd7b1b056233dfc8ef7 Mon Sep 17 00:00:00 2001 From: valef Date: Sun, 5 Jan 2014 23:37:21 +0700 Subject: [PATCH 0984/1445] - Added jshortcutParam parameter to libnative_NativeApp_init. - If shortcut_param is not empty, pass it as additional varargs argument to NativeInit() method. const char *argv[3] = {app_name.c_str(), shortcut_param.c_str(), 0}; NativeInit(2, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); - NativeInit() is expected to treat extra argument as boot_filename, which in turn will start game immediately. --- android/app-android.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 975ac96b7e..b049b6f594 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -139,7 +139,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioConfig extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init (JNIEnv *env, jclass, jint dpi, jstring jdevicetype, jstring jlangRegion, jstring japkpath, - jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jinstallID, jboolean juseNativeAudio) { + jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jshortcutParam, + jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; ILOG("NativeApp.init() -- begin"); @@ -166,9 +167,11 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init std::string externalDir = GetJavaString(env, jexternalDir); std::string user_data_path = GetJavaString(env, jdataDir) + "/"; library_path = GetJavaString(env, jlibraryDir) + "/"; + std::string shortcut_param = GetJavaString(env, jshortcutParam); std::string installID = GetJavaString(env, jinstallID); ILOG("NativeApp.init(): External storage path: %s", externalDir.c_str()); + ILOG("NativeApp.init(): Launch shortcut parameter: %s", shortcut_param.c_str()); std::string app_name; std::string app_nice_name; @@ -181,8 +184,19 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init NativeGetAppInfo(&app_name, &app_nice_name, &landscape); - const char *argv[2] = {app_name.c_str(), 0}; - NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); + + // If shortcut_param is not empty, pass it as additional varargs argument to NativeInit() method. + // NativeInit() is expected to treat extra argument as boot_filename, which in turn will start game immediately. + // NOTE: Will only work if ppsspp started from Activity.onCreate(). Won't work if ppsspp app start from onResume(). + + if(shortcut_param.empty()) { + const char *argv[2] = {app_name.c_str(), 0}; + NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); + } + else { + const char *argv[3] = {app_name.c_str(), shortcut_param.c_str(), 0}; + NativeInit(2, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); + } use_opensl_audio = juseNativeAudio; ILOG("NativeApp.init() -- end"); From 43691090f34b6d94f402217adf2a6a4a48775b19 Mon Sep 17 00:00:00 2001 From: valef Date: Mon, 6 Jan 2014 18:00:24 +0700 Subject: [PATCH 0985/1445] - Removed SHORTCUT_EXTRA_KEY and shortcut query out of NativeActivity class. - Added String shortcutParam member & setShortcutParam() method. This will be set from other class. --- .../henrikrydgard/libnative/NativeActivity.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index a03cc8439a..79adc60c8e 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -88,9 +88,6 @@ public class NativeActivity extends Activity { // Adjust these as necessary private static String TAG = "NativeActivity"; - // Key used by shortcut creation. - public static final String SHORTCUT_EXTRA_KEY = "org.ppsspp.ppsspp.Shortcuts"; - // Easy way to flip it on and off from code. private static final boolean useKitkatImmersiveMode = false; @@ -104,6 +101,8 @@ public class NativeActivity extends Activity { boolean useOpenSL = false; + private String shortcutParam = ""; + public static String runCommand; public static String commandParameter; public static String installID; @@ -173,6 +172,10 @@ public class NativeActivity extends Activity { } } + public void setShortcutParam(String shortcutParam) { + this.shortcutParam = ((shortcutParam == null) ? "" : shortcutParam); + } + public void Initialize() { //initialise audio classes. Do this here since detectOptimalAudioSettings() @@ -207,14 +210,6 @@ public class NativeActivity extends Activity { throw new RuntimeException("Unable to locate assets, aborting..."); } - // Get shortcut parameter, in case app was launched from homescreen shortcut. - // We obtain shortcut parameter from Intent extra string. - // Intent extra will be null if we launch from normal app drawer. - String shortcutParam = getIntent().getStringExtra(SHORTCUT_EXTRA_KEY); - if(shortcutParam == null) { - shortcutParam = new String(""); - } - String libraryDir = getApplicationLibraryDir(appInfo); File sdcard = Environment.getExternalStorageDirectory(); Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); From 4dbff7b2d04bc2353f57b58b9fec097e5948d545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Jan 2014 13:29:56 +0100 Subject: [PATCH 0986/1445] Remove unnecessary logging in chunk_file.cpp --- file/chunk_file.cpp | 1 - file/chunk_file.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index 072e36b387..e7199a1359 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -17,7 +17,6 @@ ChunkFile::ChunkFile(const char *filename, bool _read) { if (fastMode) { size_t size; - ILOG("VFSReadFile %s", filename); data = (uint8_t *)VFSReadFile(filename, &size); if (!data) { ELOG("Chunkfile fail: %s", filename); diff --git a/file/chunk_file.h b/file/chunk_file.h index c7c74c3138..7eb62a972a 100644 --- a/file/chunk_file.h +++ b/file/chunk_file.h @@ -1,6 +1,8 @@ #pragma once // RIFF file format reader/writer. Very old code, basically a total mess but it still works. +// Has nothing to do with the ChunkFile.h used in Dolphin or PPSSPP. +// LAMEFile should be removed. // TO REMEMBER WHEN USING: From 024846cb7b64e3cb63b8ae017f5665667ce95121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Jan 2014 13:42:48 +0100 Subject: [PATCH 0987/1445] Make Android "FrameCommands" quite a bit more robust. --- android/app-android.cpp | 63 +++++++++++-------- .../libnative/InputDeviceState.java | 2 + 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index b049b6f594..ff6cb32d79 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -10,9 +10,11 @@ #include #include #include +#include #include "base/basictypes.h" #include "base/display.h" +#include "base/mutex.h" #include "base/NativeApp.h" #include "base/logging.h" #include "base/timeutil.h" @@ -28,8 +30,16 @@ static JNIEnv *jniEnvUI; -std::string frameCommand; -std::string frameCommandParam; +struct FrameCommand { + FrameCommand() {} + FrameCommand(std::string cmd, std::string prm) : command(cmd), params(prm) {} + + std::string command; + std::string params; +}; + +recursive_mutex frameCommandLock; +std::queue frameCommands; std::string systemName; std::string langRegion; @@ -48,40 +58,40 @@ int optimalSampleRate = 0; // Android implementation of callbacks to the Java part of the app void SystemToast(const char *text) { - frameCommand = "toast"; - frameCommandParam = text; + lock_guard guard(frameCommandLock); + frameCommands.push(FrameCommand("toast", text)); } void ShowKeyboard() { - frameCommand = "showKeyboard"; - frameCommandParam = ""; + lock_guard guard(frameCommandLock); + frameCommands.push(FrameCommand("showKeyboard", "")); } void Vibrate(int length_ms) { - frameCommand = "vibrate"; + lock_guard guard(frameCommandLock); char temp[32]; sprintf(temp, "%i", length_ms); - frameCommandParam = temp; + frameCommands.push(FrameCommand("vibrate", temp)); } void LaunchBrowser(const char *url) { - frameCommand = "launchBrowser"; - frameCommandParam = url; + lock_guard guard(frameCommandLock); + frameCommands.push(FrameCommand("launchBrowser", url)); } void LaunchMarket(const char *url) { - frameCommand = "launchMarket"; - frameCommandParam = url; + lock_guard guard(frameCommandLock); + frameCommands.push(FrameCommand("launchMarket", url)); } void LaunchEmail(const char *email_address) { - frameCommand = "launchEmail"; - frameCommandParam = email_address; + lock_guard guard(frameCommandLock); + frameCommands.push(FrameCommand("launchEmail", email_address)); } void System_SendMessage(const char *command, const char *parameter) { - frameCommand = command; - frameCommandParam = parameter; + lock_guard guard(frameCommandLock); + frameCommands.push(FrameCommand(command, parameter)); } std::string System_GetProperty(SystemProperty prop) { @@ -285,8 +295,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JN } extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { - // Too spammy - // ILOG("NativeApp.displayRender()"); if (renderer_inited) { // TODO: Look into if these locks are a perf loss { @@ -317,15 +325,19 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } - if (!frameCommand.empty()) { - DLOG("frameCommand %s %s", frameCommand.c_str(), frameCommandParam.c_str()); + while (!frameCommands.empty()) { + FrameCommand frameCmd; + { + lock_guard guard(frameCommandLock); + frameCmd = frameCommands.front(); + frameCommands.pop(); + } - jstring cmd = env->NewStringUTF(frameCommand.c_str()); - jstring param = env->NewStringUTF(frameCommandParam.c_str()); + DLOG("frameCommand %s %s", cmd.command.c_str(), frameCmd.params.c_str()); + + jstring cmd = env->NewStringUTF(frameCmd.command.c_str()); + jstring param = env->NewStringUTF(frameCmd.params.c_str()); env->CallVoidMethod(obj, postCommand, cmd, param); - - frameCommand = ""; - frameCommandParam = ""; } } @@ -486,7 +498,6 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) { - jboolean isCopy; std::string msg = GetJavaString(env, message); std::string prm = GetJavaString(env, param); ILOG("Message received: %s %s", msg.c_str(), prm.c_str()); diff --git a/android/src/com/henrikrydgard/libnative/InputDeviceState.java b/android/src/com/henrikrydgard/libnative/InputDeviceState.java index dcfd8d47a6..6b0a7db1cb 100644 --- a/android/src/com/henrikrydgard/libnative/InputDeviceState.java +++ b/android/src/com/henrikrydgard/libnative/InputDeviceState.java @@ -37,6 +37,8 @@ public class InputDeviceState { mAxes[i++] = range.getAxis(); } } + + Log.i(TAG, "Registering input device with " + numAxes + " axes: " + device.getName()); } public static float ProcessAxis(InputDevice.MotionRange range, float axisvalue) { From b1f177830c8d63bc6e39f8561470d4aaf07e1320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Jan 2014 14:16:04 +0100 Subject: [PATCH 0988/1445] Minor logging improvement --- gfx/gl_lost_manager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gfx/gl_lost_manager.cpp b/gfx/gl_lost_manager.cpp index dd8d2f4a17..c36805b841 100644 --- a/gfx/gl_lost_manager.cpp +++ b/gfx/gl_lost_manager.cpp @@ -19,6 +19,7 @@ void register_gl_resource_holder(GfxResourceHolder *holder) { WLOG("GL resource holder not initialized, cannot register resource"); } } + void unregister_gl_resource_holder(GfxResourceHolder *holder) { if (inLost) { FLOG("BAD: Should not call unregister_gl_resource_holder from lost path"); @@ -44,9 +45,11 @@ void gl_lost() { inLost = false; return; } + + // TODO: We should really do this when we get the context back, not during gl_lost... ILOG("gl_lost() restoring %i items:", (int)holders->size()); for (size_t i = 0; i < holders->size(); i++) { - ILOG("GLLost(%i / %i, %p)", (int) i, (int) holders->size(), (*holders)[i]); + ILOG("GLLost(%i / %i, %p)", (int)(i + 1), (int) holders->size(), (*holders)[i]); (*holders)[i]->GLLost(); } ILOG("gl_lost() completed restoring %i items:", (int)holders->size()); From f01e1bbab0257afa8a8c8bf17f999564a158706e Mon Sep 17 00:00:00 2001 From: ufdada Date: Mon, 13 Jan 2014 15:48:07 +0100 Subject: [PATCH 0989/1445] Adding some more keycodes --- input/keycodes.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/input/keycodes.h b/input/keycodes.h index b1a396a822..6b0f1cd3a2 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -211,6 +211,22 @@ typedef enum _keycode_t { NKCODE_BUTTON_14 = 201, NKCODE_BUTTON_15 = 202, NKCODE_BUTTON_16 = 203, + NKCODE_LANGUAGE_SWITCH = 204, + NKCODE_MANNER_MODE = 205, + NKCODE_3D_MODE = 206, + NKCODE_CONTACTS = 207, + NKCODE_CALENDAR = 208, + NKCODE_MUSIC = 209, + NKCODE_CALCULATOR = 210, + NKCODE_ZENKAKU_HANKAKU = 211, + NKCODE_EISU = 212, + NKCODE_MUHENKAN = 213, + NKCODE_HENKAN = 214, + NKCODE_KATAKANA_HIRAGANA = 215, + NKCODE_YEN = 216, + NKCODE_RO = 217, + NKCODE_KANA = 218, + NKCODE_ASSIST = 219, // Ouya buttons. Just here for reference, they map straight to regular android buttons // and will be mapped the same way. From 93155b8a1eb2f047438108e111b4aaea64e027c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Jan 2014 11:01:45 +0100 Subject: [PATCH 0990/1445] Warning fixes --- ui/view.cpp | 2 -- ui/virtual_input.cpp | 7 +------ 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 1b4e23f036..06e7b36e1a 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -111,7 +111,6 @@ void Event::Trigger(EventParams &e) { // Call this from UI thread EventReturn Event::Dispatch(EventParams &e) { - bool eventHandled = false; for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { if ((iter->func)(e) == UI::EVENT_DONE) { // Event is handled, stop looping immediately. This event might even have gotten deleted. @@ -404,7 +403,6 @@ EventReturn CheckBox::OnClicked(EventParams &e) { void CheckBox::Draw(UIContext &dc) { ClickableItem::Draw(dc); int paddingX = 12; - int paddingY = 8; int image = *toggle_ ? dc.theme->checkOn : dc.theme->checkOff; diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index cf1ff447b9..f27a81993e 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -57,7 +57,6 @@ void TouchCrossPad::update(InputState &input_state) float stick_size_ = radius_ * 2; float inv_stick_size = 1.0f / (stick_size_ * scale_); const float deadzone = 0.17f; - bool all_up = true; for (int i = 0; i < MAX_POINTERS; i++) { if (input_state.pointer_down[i]) { @@ -67,13 +66,11 @@ void TouchCrossPad::update(InputState &input_state) if (rad < deadzone || rad > 1.0f) continue; - all_up = false; - if (dx == 0 && dy == 0) continue; int direction = (int)(floorf((atan2f(dy, dx) / (2 * M_PI) * 8) + 0.5f)) & 7; - + input_state.pad_buttons &= ~(PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN); switch (direction) { case 0: input_state.pad_buttons |= PAD_BUTTON_RIGHT; break; @@ -117,10 +114,8 @@ TouchStick::TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex void TouchStick::update(InputState &input_state) { float inv_stick_size = 1.0f / (stick_size_ * scale_); - bool all_up = true; for (int i = 0; i < MAX_POINTERS; i++) { if (input_state.pointer_down[i]) { - all_up = false; float dx = (input_state.pointer_x[i] - stick_x_) * inv_stick_size; float dy = (input_state.pointer_y[i] - stick_y_) * inv_stick_size; // Ignore outside box From 725ada516a4023785c163202fe96350e83a427f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Jan 2014 11:11:29 +0100 Subject: [PATCH 0991/1445] Don't log native-app messages, let the app handle it in NativeMessageReceived if it wants to --- android/app-android.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index ff6cb32d79..0f059ac21b 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -500,6 +500,5 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) { std::string msg = GetJavaString(env, message); std::string prm = GetJavaString(env, param); - ILOG("Message received: %s %s", msg.c_str(), prm.c_str()); NativeMessageReceived(msg.c_str(), prm.c_str()); } From dfcfe5d00faf66fef9a1422a512cb508a2f1d35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Jan 2014 17:32:06 +0100 Subject: [PATCH 0992/1445] Android: Allow apps to override the use of low profile. Minor logging improvement in vjson --- .../libnative/NativeActivity.java | 18 +++++++++++++++--- .../com/henrikrydgard/libnative/NativeApp.java | 1 - ext/vjson/json.cpp | 4 ++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 79adc60c8e..092a663134 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -125,7 +125,13 @@ public class NativeActivity extends Activity { InputDeviceState inputPlayerB; String inputPlayerADesc; - + + // Functions for the app activity to override to change behaviour. + + public boolean useLowProfileButtons() { + return true; + } + @TargetApi(17) private void detectOptimalAudioSettings() { try { @@ -356,14 +362,20 @@ public class NativeActivity extends Activity { @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public void darkenOnScreenButtons() { - mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); + if (useLowProfileButtons()) { + mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); + } } @TargetApi(Build.VERSION_CODES.KITKAT) public void setImmersiveMode() { // this.setImmersive(true); // This is an entirely different kind of immersive mode - hides some notification if (useKitkatImmersiveMode) { - mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); + int flags = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + if (useLowProfileButtons()) { + flags |= View.SYSTEM_UI_FLAG_LOW_PROFILE; + } + mGLSurfaceView.setSystemUiVisibility(flags); } } diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index a34c2f9cab..73ee0ca654 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -13,7 +13,6 @@ public class NativeApp { public static native void audioConfig(int optimalFramesPerBuffer, int optimalSampleRate); public static native boolean isLandscape(); - public static native boolean isAtTopLevel(); // These have Android semantics: Resume is always called on bootup, after init diff --git a/ext/vjson/json.cpp b/ext/vjson/json.cpp index 2a77849470..6015b7c76e 100644 --- a/ext/vjson/json.cpp +++ b/ext/vjson/json.cpp @@ -362,7 +362,7 @@ json_value *json_parse(char *source, char **error_pos, char **error_desc, int *e case ':': if (!top || top->type != JSON_OBJECT) { - ERROR(it, "Unexpected character"); + ERROR(it, "Unexpected character (no top level)"); } ++it; break; @@ -570,7 +570,7 @@ json_value *json_parse(char *source, char **error_pos, char **error_desc, int *e break; default: - ERROR(it, "Unexpected character"); + ERROR(it, "Unexpected character (unknown)"); } // skip white space From f8bb0c4ccc865a892d27280c72d73c1e7c25d6d0 Mon Sep 17 00:00:00 2001 From: danyalzia Date: Wed, 15 Jan 2014 15:11:46 +0500 Subject: [PATCH 0993/1445] Fix ATI bug --- gfx_es2/gl_state.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 952524082f..1e1d571621 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -196,7 +196,9 @@ void CheckGLExtensions() { #endif // Check the desktop extension instead of the OES one. They are very similar. - gl_extensions.OES_texture_npot = strstr(extString, "GL_ARB_texture_non_power_of_two") != 0; + // Also explicitly check those ATI devices that claims to support npot + gl_extensions.OES_texture_npot = strstr(extString, "GL_ARB_texture_non_power_of_two") != 0 + && !(((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0))); gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; From ef2cb9cf35b71582d8ee9cdc8c6deb73ecdb2af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Jan 2014 15:30:31 +0100 Subject: [PATCH 0994/1445] Log "onDestroy" as info instead of error. --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 092a663134..7f814c43c3 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -349,7 +349,7 @@ public class NativeActivity extends Activity { @Override protected void onDestroy() { super.onDestroy(); - Log.e(TAG, "onDestroy"); + Log.i(TAG, "onDestroy"); mGLSurfaceView.onDestroy(); nativeRenderer.onDestroyed(); NativeApp.audioShutdown(); From 1dd3915a4c8f31a8f40b7f353a52719cda520634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Jan 2014 16:38:09 +0100 Subject: [PATCH 0995/1445] Prevent writing pointers as bools in iniFile::section::Set --- file/ini_file.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/file/ini_file.h b/file/ini_file.h index 83626e1552..e64238b62d 100644 --- a/file/ini_file.h +++ b/file/ini_file.h @@ -70,6 +70,12 @@ public: Set(key,temp); } + // Declare without a body to make it fail to compile. This is to prevent accidentally + // setting a pointer as a bool. The failure is in the linker unfortunately, but that's better + // than accidentally succeeding in a bad way. + template + void Set(const char *key, T *ptr); + bool Get(const char* key, int* value, int defaultValue = 0); bool Get(const char* key, uint32_t* value, uint32_t defaultValue = 0); bool Get(const char* key, bool* value, bool defaultValue = false); From 42fb362a91b8f61e350381b8d5e85e04bd66e3a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 17 Jan 2014 14:32:56 +0100 Subject: [PATCH 0996/1445] Tabify --- gfx/texture_atlas.h | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/gfx/texture_atlas.h b/gfx/texture_atlas.h index bbaa16de59..54949e1253 100644 --- a/gfx/texture_atlas.h +++ b/gfx/texture_atlas.h @@ -3,14 +3,14 @@ typedef int ImageID; struct AtlasChar { - // texcoords - float sx, sy, ex, ey; - // offset from the origin - float ox, oy; - // distance to move the origin forward - float wx; - // size in pixels - unsigned short pw, ph; + // texcoords + float sx, sy, ex, ey; + // offset from the origin + float ox, oy; + // distance to move the origin forward + float wx; + // size in pixels + unsigned short pw, ph; }; struct AtlasCharRange { @@ -20,11 +20,11 @@ struct AtlasCharRange { }; struct AtlasFont { - float padding; - float height; - float ascend; - float distslope; - const AtlasChar *charData; + float padding; + float height; + float ascend; + float distslope; + const AtlasChar *charData; const AtlasCharRange *ranges; int numRanges; const char *name; @@ -34,19 +34,19 @@ struct AtlasFont { }; struct AtlasImage { - float u1, v1, u2, v2; - int w, h; + float u1, v1, u2, v2; + int w, h; const char *name; }; struct Atlas { - const char *filename; - const AtlasFont **fonts; - int num_fonts; - const AtlasImage *images; - int num_images; + const char *filename; + const AtlasFont **fonts; + int num_fonts; + const AtlasImage *images; + int num_images; // These are inefficient linear searches, try not to call every frame. const AtlasFont *getFontByName(const char *name) const; const AtlasImage *getImageByName(const char *name) const; -}; \ No newline at end of file +}; From 80a424fd187d645bdcef6855f1d803fc8fff00f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Jan 2014 14:14:45 +0100 Subject: [PATCH 0997/1445] Fix "in_zip_path_" functionality in GetFilesInDir for zip files --- file/zip_read.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index e4bc70aac4..0e47801812 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -117,7 +117,7 @@ ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { std::vector info; GetFileListing("assets", &info, 0); - for (int i = 0; i < info.size(); i++) { + for (size_t i = 0; i < info.size(); i++) { if (info[i].isDirectory) { DLOG("Directory: %s", info[i].name.c_str()); } else { @@ -137,9 +137,11 @@ uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { return ReadFromZip(zip_file_, temp_path, size); } -bool ZipAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) -{ - DLOG("Zip path: %s", path); +bool ZipAssetReader::GetFileListing(const char *orig_path, std::vector *listing, const char *filter = 0) { + char path[1024]; + strcpy(path, in_zip_path_); + strcat(path, orig_path); + std::set filters; std::string tmp; if (filter) { @@ -186,6 +188,9 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis info.fullName = std::string(path); if (info.fullName[info.fullName.size() - 1] == '/') info.fullName = info.fullName.substr(0, info.fullName.size() - 1); + + // Remove the "inzip" part of the fullname. + info.fullName = info.fullName.substr(strlen(in_zip_path_)); info.fullName += "/" + *diter; info.exists = true; info.isWritable = false; @@ -199,6 +204,7 @@ bool ZipAssetReader::GetFileListing(const char *path, std::vector *lis info.fullName = std::string(path); if (info.fullName[info.fullName.size() - 1] == '/') info.fullName = info.fullName.substr(0, info.fullName.size() - 1); + info.fullName = info.fullName.substr(strlen(in_zip_path_)); info.fullName += "/" + *fiter; info.exists = true; info.isWritable = false; @@ -334,8 +340,7 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { return 0; } -bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter) -{ +bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter) { if (path[0] == '/') { // Local path, not VFS. ILOG("Not a VFS path: %s . Reading local directory.", path); @@ -347,8 +352,7 @@ bool VFSGetFileListing(const char *path, std::vector *listing, const c int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(path, entries[i].prefix, prefix_len)) { - if (entries[i].reader->GetFileListing(path + prefix_len, listing, filter)) - { + if (entries[i].reader->GetFileListing(path + prefix_len, listing, filter)) { return true; } } @@ -357,8 +361,7 @@ bool VFSGetFileListing(const char *path, std::vector *listing, const c return false; } -bool VFSGetFileInfo(const char *path, FileInfo *info) -{ +bool VFSGetFileInfo(const char *path, FileInfo *info) { if (path[0] == '/') { // Local path, not VFS. ILOG("Not a VFS path: %s . Getting local file info.", path); From ca90b79bf87e9879aee0ba76cb951def933b057f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Jan 2014 15:57:15 +0100 Subject: [PATCH 0998/1445] Fix Android input box function. Add dpi to command line options in PCMain. --- .../libnative/NativeActivity.java | 158 ++++++++++-------- base/PCMain.cpp | 33 +++- 2 files changed, 115 insertions(+), 76 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 7f814c43c3..60747d6c74 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -30,6 +30,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Vibrator; +import android.text.InputType; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; @@ -116,8 +117,6 @@ public class NativeActivity extends Activity { private AudioManager audioManager; private Vibrator vibrator; - - public static boolean inputBoxCancelled; // Allow for two connected gamepads but just consider them the same for now. // Actually this is not entirely true, see the code. @@ -636,17 +635,18 @@ public class NativeActivity extends Activity { return true; } } - - public String inputBox(String title, String defaultText, String defaultAction) { + + // The return value is sent elsewhere. TODO in java, in SendMessage in C++. + public void inputBox(String title, String defaultText, String defaultAction) { final FrameLayout fl = new FrameLayout(this); final EditText input = new EditText(this); input.setGravity(Gravity.CENTER); - inputBoxCancelled = false; - FrameLayout.LayoutParams editBoxLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); + FrameLayout.LayoutParams editBoxLayout = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); editBoxLayout.setMargins(2, 20, 2, 20); fl.addView(input, editBoxLayout); + input.setInputType(InputType.TYPE_CLASS_TEXT); input.setText(defaultText); input.selectAll(); @@ -655,79 +655,93 @@ public class NativeActivity extends Activity { .setTitle(title) .setPositiveButton(defaultAction, new DialogInterface.OnClickListener(){ public void onClick(DialogInterface d, int which) { + NativeApp.sendMessage("inputbox_completed", input.getText().toString()); d.dismiss(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener(){ public void onClick(DialogInterface d, int which) { + NativeApp.sendMessage("inputbox_failed", ""); d.cancel(); - NativeActivity.inputBoxCancelled = false; } }).create(); - dlg.setCancelable(false); + + dlg.setCancelable(true); dlg.show(); - if (inputBoxCancelled) - return null; - NativeApp.sendMessage("INPUTBOX:" + title, input.getText().toString()); - return input.getText().toString(); } public boolean processCommand(String command, String params) { - if (command.equals("launchBrowser")) { - Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); - startActivity(i); - return true; - } else if (command.equals("launchEmail")) { - Intent send = new Intent(Intent.ACTION_SENDTO); - String uriText; - uriText = "mailto:email@gmail.com" + - "?subject=Your app is..." + - "&body=great! Or?"; - uriText = uriText.replace(" ", "%20"); - Uri uri = Uri.parse(uriText); - send.setData(uri); - startActivity(Intent.createChooser(send, "E-mail the app author!")); - return true; - } else if (command.equals("sharejpeg")) { - Intent share = new Intent(Intent.ACTION_SEND); - share.setType("image/jpeg"); - share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + params)); - startActivity(Intent.createChooser(share, "Share Picture")); - } else if (command.equals("sharetext")) { - Intent sendIntent = new Intent(); - sendIntent.setType("text/plain"); - sendIntent.putExtra(Intent.EXTRA_TEXT, params); - sendIntent.setAction(Intent.ACTION_SEND); - startActivity(sendIntent); - } else if (command.equals("showTwitter")) { - String twitter_user_name = params; - try { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("twitter://user?screen_name=" + twitter_user_name))); - } catch (Exception e) { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/#!/" + twitter_user_name))); - } - } else if (command.equals("launchMarket")) { - // Don't need this, can just use launchBrowser with a market: - // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app - // http://developer.android.com/guide/publishing/publishing.html#marketintent - return false; - } else if (command.equals("toast")) { - Toast toast = Toast.makeText(this, params, Toast.LENGTH_SHORT); - toast.show(); - return true; - } else if (command.equals("showKeyboard")) { - InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); - // No idea what the point of the ApplicationWindowToken is or if it matters where we get it from... - inputMethodManager.toggleSoftInputFromWindow(mGLSurfaceView.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0); - return true; - } else if (command.equals("hideKeyboard")) { - InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); - inputMethodManager.toggleSoftInputFromWindow(mGLSurfaceView.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0); - return true; - } else if (command.equals("inputBox")) { - inputBox(params, "", "OK"); - return true; - } else if (command.equals("vibrate")) { + if (command.equals("launchBrowser")) { + Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); + startActivity(i); + return true; + } else if (command.equals("launchEmail")) { + Intent send = new Intent(Intent.ACTION_SENDTO); + String uriText; + uriText = "mailto:email@gmail.com" + "?subject=Your app is..." + + "&body=great! Or?"; + uriText = uriText.replace(" ", "%20"); + Uri uri = Uri.parse(uriText); + send.setData(uri); + startActivity(Intent.createChooser(send, "E-mail the app author!")); + return true; + } else if (command.equals("sharejpeg")) { + Intent share = new Intent(Intent.ACTION_SEND); + share.setType("image/jpeg"); + share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + params)); + startActivity(Intent.createChooser(share, "Share Picture")); + } else if (command.equals("sharetext")) { + Intent sendIntent = new Intent(); + sendIntent.setType("text/plain"); + sendIntent.putExtra(Intent.EXTRA_TEXT, params); + sendIntent.setAction(Intent.ACTION_SEND); + startActivity(sendIntent); + } else if (command.equals("showTwitter")) { + String twitter_user_name = params; + try { + startActivity(new Intent(Intent.ACTION_VIEW, + Uri.parse("twitter://user?screen_name=" + + twitter_user_name))); + } catch (Exception e) { + startActivity(new Intent( + Intent.ACTION_VIEW, + Uri.parse("https://twitter.com/#!/" + twitter_user_name))); + } + } else if (command.equals("launchMarket")) { + // Don't need this, can just use launchBrowser with a market: + // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app + // http://developer.android.com/guide/publishing/publishing.html#marketintent + return false; + } else if (command.equals("toast")) { + Toast toast = Toast.makeText(this, params, Toast.LENGTH_SHORT); + toast.show(); + return true; + } else if (command.equals("showKeyboard")) { + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + // No idea what the point of the ApplicationWindowToken is or if it + // matters where we get it from... + inputMethodManager.toggleSoftInputFromWindow( + mGLSurfaceView.getApplicationWindowToken(), + InputMethodManager.SHOW_FORCED, 0); + return true; + } else if (command.equals("hideKeyboard")) { + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + inputMethodManager.toggleSoftInputFromWindow( + mGLSurfaceView.getApplicationWindowToken(), + InputMethodManager.SHOW_FORCED, 0); + return true; + } else if (command.equals("inputbox")) { + String title = "Input"; + String defString = ""; + String[] param = params.split(":"); + if (param[0].length() > 0) + title = param[0]; + if (param.length > 1) + defString = param[1]; + Log.i(TAG, "Launching inputbox: " + title + " " + defString); + inputBox(title, defString, "OK"); + return true; + } else if (command.equals("vibrate")) { if (vibrator != null) { int milliseconds = -1; if (params != "") { @@ -736,11 +750,13 @@ public class NativeActivity extends Activity { } catch (NumberFormatException e) { } } - // Special parameters to perform standard haptic feedback operations + // Special parameters to perform standard haptic feedback + // operations // -1 = Standard keyboard press feedback // -2 = Virtual key press // -3 = Long press feedback - // Note that these three do not require the VIBRATE Android permission. + // Note that these three do not require the VIBRATE Android + // permission. switch (milliseconds) { case -1: mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); @@ -756,8 +772,8 @@ public class NativeActivity extends Activity { break; } } - return true; - } + return true; + } return false; } } diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 4edddaab92..cdc82135eb 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -148,7 +148,8 @@ int8_t EGL_Init() { g_Window = (NativeWindowType)sysInfo.info.x11.window; #endif g_eglSurface = eglCreateWindowSurface(g_eglDisplay, g_eglConfig, g_Window, 0); - if (g_eglSurface == EGL_NO_SURFACE) EGL_ERROR("Unable to create EGL surface!", true); + if (g_eglSurface == EGL_NO_SURFACE) + EGL_ERROR("Unable to create EGL surface!", true); if (eglMakeCurrent(g_eglDisplay, g_eglSurface, g_eglSurface, g_eglContext) != EGL_TRUE) EGL_ERROR("Unable to make GLES context current.", true); @@ -323,10 +324,10 @@ extern void mixaudio(void *userdata, Uint8 *stream, int len) { } // returns -1 on failure -int parseInt(const char *str) { +static int parseInt(const char *str) { int val; int retval = sscanf(str, "%d", &val); - printf("%i = sscanf %s\n", retval, str); + printf("%i = scanf %s\n", retval, str); if (retval != 1) { return -1; } else { @@ -334,6 +335,17 @@ int parseInt(const char *str) { } } +static float parseFloat(const char *str) { + float val; + int retval = sscanf(str, "%f", &val); + printf("%i = sscanf %s\n", retval, str); + if (retval != 1) { + return -1.0f; + } else { + return val; + } +} + void ToggleFullScreenIfFlagSet() { if (g_ToggleFullScreenNextFrame) { g_ToggleFullScreenNextFrame = false; @@ -396,6 +408,8 @@ int main(int argc, char *argv[]) { mode = SDL_OPENGL; int set_xres = -1; int set_yres = -1; + + float set_dpi = 1.0f; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; @@ -404,10 +418,15 @@ int main(int argc, char *argv[]) { } else if (set_yres == -2) { set_yres = parseInt(argv[i]); } + if (set_dpi == -2) + set_dpi = parseFloat(argv[i]); + if (!strcmp(argv[i],"--xres")) set_xres = -2; if (!strcmp(argv[i],"--yres")) set_yres = -2; + if (!strcmp(argv[i],"--dpi")) + set_dpi = -2; } #endif if (mode & SDL_FULLSCREEN) { @@ -436,9 +455,13 @@ int main(int argc, char *argv[]) { if (set_yres > 0) { pixel_yres = set_yres; } + float dpi_scale = 1.0f; + if (set_dpi > 0) { + dpi_scale = set_dpi; + } - dp_xres = (float)pixel_xres; - dp_yres = (float)pixel_yres; + dp_xres = (float)pixel_xres * dpi_scale; + dp_yres = (float)pixel_yres * dpi_scale; g_Screen = SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode); if (g_Screen == NULL) { From e41706f74e3f92faf4b79d8d41e2888b6aea5e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Jan 2014 16:55:57 +0100 Subject: [PATCH 0999/1445] Add finish command to NativeActivity --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 ++ android/src/com/henrikrydgard/libnative/NativeRenderer.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 60747d6c74..cfbac45666 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -773,6 +773,8 @@ public class NativeActivity extends Activity { } } return true; + } else if (command.equals("finish")) { + finish(); } return false; } diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index e046b3d157..767c4f9b32 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -65,4 +65,4 @@ public class NativeRenderer implements GLSurfaceView.Renderer { } }); } -} \ No newline at end of file +} \ No newline at end of file From 6d007749d44145fe42cc100a5d5ed9b54e73fa29 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 21 Jan 2014 08:03:57 -0800 Subject: [PATCH 1000/1445] Fix dumb typo in surrogate pair check. --- util/text/utf16.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/text/utf16.h b/util/text/utf16.h index 75f8b3ee02..002886259d 100644 --- a/util/text/utf16.h +++ b/util/text/utf16.h @@ -25,7 +25,7 @@ public: const uint32_t u = UTF16_Swap(c_[index_++]); // Surrogate pair. UTF-16 is so simple. We assume it's valid. - if ((u & 0xD800) == 0xD800) { + if ((u & 0xF800) == 0xD800) { return 0x10000 + (((u & 0x3FF) << 10) | (UTF16_Swap(c_[index_++]) & 0x3FF)); } return u; From fc3bad8059fadf83c97c09475995540bf85dcc04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Jan 2014 16:29:59 +0100 Subject: [PATCH 1001/1445] viewgroup.h: Include fix --- ui/viewgroup.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/viewgroup.h b/ui/viewgroup.h index d7a2f30588..69263ba10c 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -1,9 +1,12 @@ #pragma once +#include + #include "base/logging.h" -#include "ui/view.h" +#include "base/mutex.h" #include "math/geom2d.h" #include "input/gesture_detector.h" +#include "ui/view.h" namespace UI { From 52fac5d294ef243a53c71c4c92c9fd6599ca6de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Jan 2014 17:32:15 +0100 Subject: [PATCH 1002/1445] Remove unused code --- ui/view.h | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/ui/view.h b/ui/view.h index 890b63a92e..acb65ea29c 100644 --- a/ui/view.h +++ b/ui/view.h @@ -735,33 +735,6 @@ private: float progress_; }; - - -// This tab strip is a little special. -/* -class TabStrip : public View { -public: - TabStrip(); - - virtual void Touch(const TouchInput &input); - virtual void Draw(DrawContext &dc); - - void AddTab(const std::string &title, uint32_t color) { - Tab tab; - tab.title = title; - tab.color = color; - tabs_.push_back(tab); - } - -private: - int selected_; - struct Tab { - std::string title; - uint32_t color; - }; - std::vector tabs_; -};*/ - void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured); void EventTriggered(Event *e, EventParams params); From 25bbd8fbd1b397aa0a953fc3dcbee159f860b3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 23 Jan 2014 14:31:56 +0100 Subject: [PATCH 1003/1445] Link backtrace.cpp on Android too for consistency. Use it in FLOG. --- Android.mk | 1 + base/PCMain.cpp | 13 ++++++++++--- base/backtrace.cpp | 13 ++++++++++--- base/logging.h | 4 ++++ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Android.mk b/Android.mk index f9575cdb36..f036619c9e 100644 --- a/Android.mk +++ b/Android.mk @@ -10,6 +10,7 @@ LOCAL_SRC_FILES :=\ android/native_audio.cpp \ audio/wav_read.cpp \ audio/mixer.cpp.arm \ + base/backtrace.cpp \ base/buffer.cpp \ base/display.cpp \ base/timeutil.cpp \ diff --git a/base/PCMain.cpp b/base/PCMain.cpp index cdc82135eb..732879c650 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -400,6 +400,8 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); int mode; + float set_dpi = 1.0f; + float set_scale = 1.0f; #ifdef USING_GLES2 mode = SDL_SWSURFACE | SDL_FULLSCREEN; int set_xres = -1; @@ -409,7 +411,6 @@ int main(int argc, char *argv[]) { int set_xres = -1; int set_yres = -1; - float set_dpi = 1.0f; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; @@ -420,6 +421,8 @@ int main(int argc, char *argv[]) { } if (set_dpi == -2) set_dpi = parseFloat(argv[i]); + if (set_scale == -2) + set_scale = parseFloat(argv[i]); if (!strcmp(argv[i],"--xres")) set_xres = -2; @@ -427,6 +430,8 @@ int main(int argc, char *argv[]) { set_yres = -2; if (!strcmp(argv[i],"--dpi")) set_dpi = -2; + if (!strcmp(argv[i],"--scale")) + set_scale = -2; } #endif if (mode & SDL_FULLSCREEN) { @@ -438,13 +443,15 @@ int main(int argc, char *argv[]) { #endif } else { // set a sensible default resolution (2x) - pixel_xres = 480 * 2; - pixel_yres = 272 * 2; + pixel_xres = 480 * 2 * set_scale; + pixel_yres = 272 * 2 * set_scale; #ifdef PPSSPP g_Config.bFullScreen = false; #endif } + set_dpi = 1.0f / set_dpi; + if (!landscape) { std::swap(pixel_xres, pixel_yres); } diff --git a/base/backtrace.cpp b/base/backtrace.cpp index 92e3e2739f..08cfc4ddd6 100644 --- a/base/backtrace.cpp +++ b/base/backtrace.cpp @@ -1,8 +1,7 @@ #include "base/backtrace.h" -#ifdef __linux__ - -// LINUX ONLY +// The mac check doesn't seem to work right. +#if (!defined(ANDROID) && defined(__linux__)) || (defined(__APPLE__) && (defined(_M_IX86) || defined(_M_X64))) #include #include @@ -14,4 +13,12 @@ void PrintBacktraceToStderr() { backtrace_symbols_fd(backtrace_buffer, num_addrs, STDERR_FILENO); } +#else + +#include + +void PrintBacktraceToStderr() { + fprintf(stderr, "No backtrace available to print on this platform\n"); +} + #endif diff --git a/base/logging.h b/base/logging.h index 6c3a7b6690..fd876f5d7b 100644 --- a/base/logging.h +++ b/base/logging.h @@ -1,5 +1,7 @@ #pragma once +#include "backtrace.h" + // Simple wrapper around Android's logging interface that also allows other // implementations, and also some misc utilities. @@ -29,12 +31,14 @@ inline void Crash() { __asm { int 3 }; } #if defined(ARM) || defined(MIPS) inline void Crash() { + PrintBacktraceToStderr(); char *p = (char *)1337; *p = 1; } #else // TODO: 64-bit version inline void Crash() { + PrintBacktraceToStderr(); asm("int $0x3"); } #endif From 1c87fb74850cfe406e37bf796aba96e0186c2d90 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 25 Jan 2014 11:58:49 -0800 Subject: [PATCH 1004/1445] Allow customizing the tab left/right keys. --- input/input_state.cpp | 9 ++++++++- input/input_state.h | 5 ++++- ui/view.cpp | 28 ++++++++++++++++++++++++++-- ui/view.h | 2 ++ ui/viewgroup.cpp | 4 ++-- 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/input/input_state.cpp b/input/input_state.cpp index dd4332ceeb..2da6321b61 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -44,12 +44,19 @@ int MapPadButtonFixed(int keycode) { std::vector confirmKeys; std::vector cancelKeys; +std::vector tabLeftKeys; +std::vector tabRightKeys; -void SetConfirmCancelKeys(std::vector confirm, std::vector cancel) { +void SetConfirmCancelKeys(const std::vector &confirm, const std::vector &cancel) { confirmKeys = confirm; cancelKeys = cancel; } +void SetTabLeftRightKeys(const std::vector &tabLeft, const std::vector &tabRight) { + tabLeftKeys = tabLeft; + tabRightKeys = tabRight; +} + uint32_t ButtonTracker::Update() { pad_buttons_ |= pad_buttons_async_set; pad_buttons_ &= ~pad_buttons_async_clear; diff --git a/input/input_state.h b/input/input_state.h index 561ea60096..378a4ba98b 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -180,4 +180,7 @@ extern ButtonTracker g_buttonTracker; // Is there a nicer place for this stuff? It's here to avoid dozens of linking errors in UnitTest.. extern std::vector confirmKeys; extern std::vector cancelKeys; -void SetConfirmCancelKeys(std::vector confirm, std::vector cancel); +extern std::vector tabLeftKeys; +extern std::vector tabRightKeys; +void SetConfirmCancelKeys(const std::vector &confirm, const std::vector &cancel); +void SetTabLeftRightKeys(const std::vector &tabLeft, const std::vector &tabRight); diff --git a/ui/view.cpp b/ui/view.cpp index 06e7b36e1a..8e7f60b289 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -202,11 +202,35 @@ void Clickable::Touch(const TouchInput &input) { // TODO: O/X confirm preference for xperia play? bool IsAcceptKeyCode(int keyCode) { - return std::find(confirmKeys.begin(), confirmKeys.end(), (keycode_t)keyCode) != confirmKeys.end(); + if (confirmKeys.empty()) { + return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_Z || keyCode == NKCODE_BUTTON_A || keyCode == NKCODE_BUTTON_CROSS || keyCode == NKCODE_BUTTON_1; + } else { + return std::find(confirmKeys.begin(), confirmKeys.end(), (keycode_t)keyCode) != confirmKeys.end(); + } } bool IsEscapeKeyCode(int keyCode) { - return std::find(cancelKeys.begin(), cancelKeys.end(), (keycode_t)keyCode) != cancelKeys.end(); + if (cancelKeys.empty()) { + return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B || keyCode == NKCODE_BUTTON_2; + } else { + return std::find(cancelKeys.begin(), cancelKeys.end(), (keycode_t)keyCode) != cancelKeys.end(); + } +} + +bool IsTabLeftKeyCode(int keyCode) { + if (tabLeftKeys.empty()) { + return keyCode == NKCODE_BUTTON_L1; + } else { + return std::find(tabLeftKeys.begin(), tabLeftKeys.end(), (keycode_t)keyCode) != tabLeftKeys.end(); + } +} + +bool IsTabRightKeyCode(int keyCode) { + if (tabRightKeys.empty()) { + return keyCode == NKCODE_BUTTON_R1; + } else { + return std::find(tabRightKeys.begin(), tabRightKeys.end(), (keycode_t)keyCode) != tabRightKeys.end(); + } } void Clickable::Key(const KeyInput &key) { diff --git a/ui/view.h b/ui/view.h index 890b63a92e..5d57d046ec 100644 --- a/ui/view.h +++ b/ui/view.h @@ -768,5 +768,7 @@ void EventTriggered(Event *e, EventParams params); void DispatchEvents(); bool IsAcceptKeyCode(int keyCode); bool IsEscapeKeyCode(int keyCode); +bool IsTabLeftKeyCode(int keyCode); +bool IsTabRightKeyCode(int keyCode); } // namespace diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index d867d26fd7..d35394ac31 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -975,9 +975,9 @@ void ChoiceStrip::HighlightChoice(unsigned int choice){ void ChoiceStrip::Key(const KeyInput &input) { if (input.flags & KEY_DOWN) { - if (input.keyCode == NKCODE_BUTTON_L1 && selected_ > 0) { + if (IsTabLeftKeyCode(input.keyCode) && selected_ > 0) { SetSelection(selected_ - 1); - } else if (input.keyCode == NKCODE_BUTTON_R1 && selected_ < (int)views_.size() - 1) { + } else if (IsTabRightKeyCode(input.keyCode) && selected_ < (int)views_.size() - 1) { SetSelection(selected_ + 1); } } From a3133218932f9bc96a228de0d40951c5656e2b16 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Thu, 30 Jan 2014 14:23:04 -0200 Subject: [PATCH 1005/1445] Add fallback in case of xdg-utils is not installed Some distributions may not install xdg-utils by default, so inform the user in case of xdg-utils is not installed when the user tries to use any of the xdg-utils commands. --- base/PCMain.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 732879c650..9f9e8cb86f 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -217,7 +217,10 @@ void LaunchBrowser(const char *url) { ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); #elif __linux__ std::string command = std::string("xdg-open ") + url; - system(command.c_str()); + errno = system(command.c_str()); + if (errno) { + ILOG("Would have gone to %s but xdg-utils seems not to be installed", url) + } #elif __APPLE__ std::string command = std::string("open ") + url; system(command.c_str()); @@ -232,6 +235,9 @@ void LaunchMarket(const char *url) { #elif __linux__ std::string command = std::string("xdg-open ") + url; system(command.c_str()); + if (errno) { + ILOG("Would have gone to %s but xdg-utils seems not to be installed", url) + } #elif __APPLE__ std::string command = std::string("open ") + url; system(command.c_str()); @@ -246,6 +252,9 @@ void LaunchEmail(const char *email_address) { #elif __linux__ std::string command = std::string("xdg-email ") + email_address; system(command.c_str()); + if (errno) { + ILOG("Would have gone to %s but xdg-utils seems not to be installed", email_address) + } #elif __APPLE__ std::string command = std::string("open mailto:") + email_address; system(command.c_str()); From 14e32915b2f171e785d379e6cdff9c0ac7198f11 Mon Sep 17 00:00:00 2001 From: Thiago Kenji Okada Date: Thu, 30 Jan 2014 14:33:48 -0200 Subject: [PATCH 1006/1445] I forget how C works after using Python... --- base/PCMain.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 9f9e8cb86f..8db1dcc20a 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -217,8 +217,8 @@ void LaunchBrowser(const char *url) { ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); #elif __linux__ std::string command = std::string("xdg-open ") + url; - errno = system(command.c_str()); - if (errno) { + int err = system(command.c_str()); + if (err) { ILOG("Would have gone to %s but xdg-utils seems not to be installed", url) } #elif __APPLE__ @@ -234,8 +234,8 @@ void LaunchMarket(const char *url) { ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); #elif __linux__ std::string command = std::string("xdg-open ") + url; - system(command.c_str()); - if (errno) { + int err = system(command.c_str()); + if (err) { ILOG("Would have gone to %s but xdg-utils seems not to be installed", url) } #elif __APPLE__ @@ -251,8 +251,8 @@ void LaunchEmail(const char *email_address) { ShellExecute(NULL, "open", (std::string("mailto:") + email_address).c_str(), NULL, NULL, SW_SHOWNORMAL); #elif __linux__ std::string command = std::string("xdg-email ") + email_address; - system(command.c_str()); - if (errno) { + int err = system(command.c_str()); + if (err) { ILOG("Would have gone to %s but xdg-utils seems not to be installed", email_address) } #elif __APPLE__ From ed96a29988b048c9b55ae6fc591d07bc526204b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 24 Jan 2014 12:34:55 +0100 Subject: [PATCH 1007/1445] Log detected DPI. --- android/app-android.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 0f059ac21b..f6effdbc17 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -149,7 +149,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioConfig extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init (JNIEnv *env, jclass, jint dpi, jstring jdevicetype, jstring jlangRegion, jstring japkpath, - jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jshortcutParam, + jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jshortcutParam, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; @@ -191,6 +191,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init g_dpi = dpi; g_dpi_scale = 240.0f / (float)g_dpi; + ILOG("DPI detected: %i %f", dpi, g_dpi_scale); NativeGetAppInfo(&app_name, &app_nice_name, &landscape); @@ -199,7 +200,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init // NativeInit() is expected to treat extra argument as boot_filename, which in turn will start game immediately. // NOTE: Will only work if ppsspp started from Activity.onCreate(). Won't work if ppsspp app start from onResume(). - if(shortcut_param.empty()) { + if (shortcut_param.empty()) { const char *argv[2] = {app_name.c_str(), 0}; NativeInit(1, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); } From 4818a85042a706457872ddf46eec7bf016c2553a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 31 Jan 2014 14:31:19 +0100 Subject: [PATCH 1008/1445] Add drag capturing (useful to resolve conflicts between scrollviews and draggable controls within) Some misc cleanup --- base/display.cpp | 6 +++--- json/json_writer.h | 4 ---- math/math_util.h | 5 +---- ui/viewgroup.cpp | 18 ++++++++++++++++-- ui/viewgroup.h | 4 ++++ 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/base/display.cpp b/base/display.cpp index 3ceebf334c..cc84259620 100644 --- a/base/display.cpp +++ b/base/display.cpp @@ -6,6 +6,6 @@ int dp_yres; int pixel_xres; int pixel_yres; -int g_dpi; -float g_dpi_scale; -float pixel_in_dps; \ No newline at end of file +int g_dpi = 1.0f; +float g_dpi_scale = 1.0f; +float pixel_in_dps = 1.0f; diff --git a/json/json_writer.h b/json/json_writer.h index faf9e4d937..b58ca37f6d 100644 --- a/json/json_writer.h +++ b/json/json_writer.h @@ -14,8 +14,6 @@ #include #include -#include "base/basictypes.h" - class JsonWriter { public: JsonWriter(); @@ -55,6 +53,4 @@ private: }; std::vector stack_; std::ostringstream str_; - - DISALLOW_COPY_AND_ASSIGN(JsonWriter); }; diff --git a/math/math_util.h b/math/math_util.h index 2c60aa2d8a..4704a51d23 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -1,5 +1,4 @@ -#ifndef _MATHUTILS_H -#define _MATHUTILS_H +#pragma once #include #include @@ -203,5 +202,3 @@ inline uint16_t ShrinkToHalf(float full) { // FPU control. void EnableFZ(); - -#endif diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index d35394ac31..7c72f51f39 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -19,6 +19,20 @@ const float ITEM_HEIGHT = 64.f; static recursive_mutex focusLock; static std::vector focusMoves; +bool dragCaptured[MAX_POINTERS]; + +void CaptureDrag(int id) { + dragCaptured[id] = true; +} + +void ReleaseDrag(int id) { + dragCaptured[id] = false; +} + +bool IsDragCaptured(int id) { + return dragCaptured[id]; +} + void ApplyGravity(const Bounds outer, const Margins &margins, float w, float h, int gravity, Bounds &inner) { inner.w = w - (margins.left + margins.right); inner.h = h - (margins.right + margins.left); @@ -636,12 +650,12 @@ void ScrollView::Touch(const TouchInput &input) { } if (input.flags & TOUCH_UP) { float info[4]; - if (gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info)) + if (!IsDragCaptured(input.id) && gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info)) inertia_ = info[1]; } TouchInput input2; - if (CanScroll()) { + if (CanScroll() && !IsDragCaptured(input.id)) { input2 = gesture_.Update(input, bounds_); float info[4]; if (gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info)) { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 69263ba10c..63e53cadd6 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -377,4 +377,8 @@ void KeyEvent(const KeyInput &key, ViewGroup *root); void TouchEvent(const TouchInput &touch, ViewGroup *root); void AxisEvent(const AxisInput &axis, ViewGroup *root); +void CaptureDrag(int id); +void ReleaseDrag(int id); +bool IsDragCaptured(int id); + } // namespace UI From c960fdb0b2907fdf0f27f6dc02526486b1776dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 4 Feb 2014 12:07:17 +0100 Subject: [PATCH 1009/1445] Add a new "queryConfig" native android function, so that the Java code can check config options like rotation lock (config is implemented on the C++ side). --- android/app-android.cpp | 8 ++++++++ .../src/com/henrikrydgard/libnative/NativeActivity.java | 2 +- android/src/com/henrikrydgard/libnative/NativeApp.java | 2 ++ base/NativeApp.h | 5 +++++ base/display.cpp | 2 +- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index f6effdbc17..4e45c72d5f 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -147,6 +147,14 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioConfig optimalSampleRate = optimalSR; } +extern "C" jstring Java_com_henrikrydgard_libnative_NativeApp_queryConfig + (JNIEnv *env, jclass, jstring jquery) { + std::string query = GetJavaString(env, jquery); + std::string result = NativeQueryConfig(query); + jstring jresult = env->NewStringUTF(result.c_str()); + return jresult; +} + extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init (JNIEnv *env, jclass, jint dpi, jstring jdevicetype, jstring jlangRegion, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jshortcutParam, diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index cfbac45666..bb2c227911 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -669,7 +669,7 @@ public class NativeActivity extends Activity { dlg.setCancelable(true); dlg.show(); } - + public boolean processCommand(String command, String params) { if (command.equals("launchBrowser")) { Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 73ee0ca654..070d74ee3d 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -40,5 +40,7 @@ public class NativeApp { public static native void accelerometer(float x, float y, float z); public static native void sendMessage(String msg, String arg); + + public static native String queryConfig(String queryName); } \ No newline at end of file diff --git a/base/NativeApp.h b/base/NativeApp.h index 0b1ba00f0a..d99b9e20ad 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -23,6 +23,11 @@ void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, boo // Generic host->C++ messaging, used for functionality like system-native popup input boxes. void NativeMessageReceived(const char *message, const char *value); +// Easy way for the Java side to ask the C++ side for configuration options, such as +// the rotation lock which must be controlled from Java on Android. +// It is currently not called on non-Android platforms. +std::string NativeQueryConfig(std::string query); + // For the back button to work right, this should return true on your main or title screen. // Otherwise, just return false. bool NativeIsAtTopLevel(); diff --git a/base/display.cpp b/base/display.cpp index cc84259620..89a78fef05 100644 --- a/base/display.cpp +++ b/base/display.cpp @@ -6,6 +6,6 @@ int dp_yres; int pixel_xres; int pixel_yres; -int g_dpi = 1.0f; +int g_dpi = 1; // will be overwritten float g_dpi_scale = 1.0f; float pixel_in_dps = 1.0f; From 5fa72b4d2227f1d31c0f729284be482011d9e923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 4 Feb 2014 12:57:32 +0100 Subject: [PATCH 1010/1445] Add support for querying the desired rotation setting from Java. --- .../libnative/NativeActivity.java | 63 +++++++++++++++---- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index bb2c227911..f8599aab3d 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -17,6 +17,7 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; import android.content.pm.PackageManager; @@ -124,7 +125,6 @@ public class NativeActivity extends Activity { InputDeviceState inputPlayerB; String inputPlayerADesc; - // Functions for the app activity to override to change behaviour. public boolean useLowProfileButtons() { @@ -182,9 +182,8 @@ public class NativeActivity extends Activity { } public void Initialize() { - - //initialise audio classes. Do this here since detectOptimalAudioSettings() - //needs audioManager + // Initialize audio classes. Do this here since detectOptimalAudioSettings() + // needs audioManager this.audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); this.audioFocusChangeListener = new AudioFocusChangeListener(); @@ -197,12 +196,6 @@ public class NativeActivity extends Activity { detectOptimalAudioSettings(); } - /* - if (NativeApp.isLandscape()) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - } else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - }*/ Log.i(TAG, "onCreate"); // Get system information ApplicationInfo appInfo = null; @@ -243,7 +236,20 @@ public class NativeActivity extends Activity { NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); NativeApp.init(dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL); - Log.i(TAG, "Device: " + deviceType); + + // OK, config should be initialized, we can query for screen rotation. + if (Build.VERSION.SDK_INT >= 9) { + updateScreenRotation(); + } + + /* + if (NativeApp.isLandscape()) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + }*/ + + Log.i(TAG, "Device: " + deviceType); Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat + " dpi: " + dpi); // Detect OpenGL support. @@ -272,6 +278,37 @@ public class NativeActivity extends Activity { // inputBox("Please ener a s", "", "Save"); } + @TargetApi(9) + private void updateScreenRotation() { + // Query the native application on the desired rotation. + int rot = 0; + String rotString = NativeApp.queryConfig("screenRotation"); + try { + rot = Integer.parseInt(rotString); + } catch (NumberFormatException e) { + Log.e(TAG, "Invalid rotation: " + rotString); + return; + } + Log.i(TAG, "Rotation requested: " + rot); + switch (rot) { + case 0: + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + break; + case 1: + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + break; + case 2: + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + break; + case 3: + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); + break; + case 4: + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); + break; + } + } + // Need API 11 to check for existence of a vibrator? Zany. @TargetApi(11) public void checkForVibrator() { @@ -775,6 +812,10 @@ public class NativeActivity extends Activity { return true; } else if (command.equals("finish")) { finish(); + } else if (command.equals("rotate")) { + if (Build.VERSION.SDK_INT >= 9) { + updateScreenRotation(); + } } return false; } From d030b495fc8299a47d8b7c0504b429085e9450db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 4 Feb 2014 15:58:03 +0100 Subject: [PATCH 1011/1445] draw_buffer text rendering: Handle non-breaking spaces (instead of printing a '?'). --- gfx_es2/draw_buffer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index fe861c08ad..03e43e8a4c 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -333,6 +333,10 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { if (utf.end()) break; cval = utf.next(); + // Translate non-breaking space to space. + if (cval == 0xA0) { + cval = ' '; + } if (cval == '\n') { maxX = std::max(maxX, wacc); wacc = 0; @@ -407,6 +411,10 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co if (utf.end()) break; cval = utf.next(); + // Translate non-breaking space to space. + if (cval == 0xA0) { + cval = ' '; + } if (cval == '\n') { y += atlasfont.height * fontscaley; x = sx; From 455411edcb99c1aa9a97f4940003aad64c1b303e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 4 Feb 2014 16:17:41 +0100 Subject: [PATCH 1012/1445] Theme fix for text input alert dialogs --- .../henrikrydgard/libnative/NativeActivity.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index f8599aab3d..041979be29 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -673,6 +673,12 @@ public class NativeActivity extends Activity { } } + + @TargetApi(11) + private AlertDialog.Builder createDialogBuilderWithTheme() { + return new AlertDialog.Builder(this, AlertDialog.THEME_HOLO_DARK); + } + // The return value is sent elsewhere. TODO in java, in SendMessage in C++. public void inputBox(String title, String defaultText, String defaultAction) { final FrameLayout fl = new FrameLayout(this); @@ -687,7 +693,13 @@ public class NativeActivity extends Activity { input.setText(defaultText); input.selectAll(); - AlertDialog dlg = new AlertDialog.Builder(this) + AlertDialog.Builder bld = null; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) + bld = new AlertDialog.Builder(this); + else + bld = createDialogBuilderWithTheme(); + + AlertDialog dlg = bld .setView(fl) .setTitle(title) .setPositiveButton(defaultAction, new DialogInterface.OnClickListener(){ From 63f7bae9c9bb9e063e81ad68f3075133fb15064d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 5 Feb 2014 10:47:19 +0100 Subject: [PATCH 1013/1445] Filter out A:/ and B:/ drives from PathBrowsers. --- file/path.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/file/path.cpp b/file/path.cpp index b7097fa585..a6208d3ce8 100644 --- a/file/path.cpp +++ b/file/path.cpp @@ -20,6 +20,8 @@ void PathBrowser::GetListing(std::vector &fileInfo, const char *filter // Special path that means root of file system. std::vector drives = getWindowsDrives(); for (auto drive = drives.begin(); drive != drives.end(); ++drive) { + if (*drive == "A:/" || *drive == "B:/") + continue; FileInfo fake; fake.fullName = *drive; fake.name = *drive; From 841f04d369dbfdadac8900edab5b524c1c897aa9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 5 Feb 2014 14:46:21 +0100 Subject: [PATCH 1014/1445] For some reason, need to disable the SDL joystick code to build PCMain on windows --- base/PCMain.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 8db1dcc20a..424f3ab608 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -8,10 +8,10 @@ #include #include #include -#include "SDL/SDL.h" -#include "SDL/SDL_timer.h" -#include "SDL/SDL_audio.h" -#include "SDL/SDL_video.h" +#include "SDL.h" +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "SDL_video.h" #else #include #include @@ -33,7 +33,10 @@ #include "base/NKCodeFromSDL.h" #include "util/const_map.h" #include "math/math_util.h" + +#ifndef _WIN32 #include "SDL/SDLJoystick.h" +#endif #ifdef PPSSPP // Bad: PPSSPP includes from native @@ -184,8 +187,10 @@ void EGL_Close() { SDL_Joystick *ljoy = NULL; SDL_Joystick *rjoy = NULL; #else +#ifndef _WIN32 SDLJoystick *joystick = NULL; #endif +#endif // Simple implementations of System functions @@ -568,7 +573,9 @@ int main(int argc, char *argv[]) { rjoy = SDL_JoystickOpen(1); } #else +#ifndef _WIN32 joystick = new SDLJoystick(); +#endif #endif EnableFZ(); @@ -722,7 +729,9 @@ int main(int argc, char *argv[]) { } break; default: +#ifndef _WIN32 joystick->ProcessInput(event); +#endif break; } } @@ -768,8 +777,10 @@ int main(int argc, char *argv[]) { framecount++; } #ifndef PANDORA +#ifndef _WIN32 delete joystick; joystick = NULL; +#endif #endif // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though From b913c3c36f306c7e6620990f7ecf495065b8c025 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 5 Feb 2014 16:18:03 +0100 Subject: [PATCH 1015/1445] Use wstring conversion in file/dialog.cpp --- file/dialog.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/file/dialog.cpp b/file/dialog.cpp index 0cffd2f834..7a8ab45111 100644 --- a/file/dialog.cpp +++ b/file/dialog.cpp @@ -5,11 +5,16 @@ #include +#include "util/text/utf8.h" + // For desktop operating systems only. Stubbed out on Android. // Simplified as this will only be used in utilities / temp code. // An false returned means cancel; -bool OpenFileDialog(const wchar_t *title, const wchar_t *extension, std::wstring *filename) +bool OpenFileDialog(const char *title, const char *extension, std::string *filename) { + std::wstring wtitle = ConvertUTF8ToWString(std::string(title)); + std::wstring wext = ConvertUTF8ToWString(std::string(extension)); + OPENFILENAME of; memset(&of, 0, sizeof(of)); wchar_t buffer[512] = {0}; @@ -20,22 +25,24 @@ bool OpenFileDialog(const wchar_t *title, const wchar_t *extension, std::wstring // These weird strings with zeroes in them can't be dealt with using normal string // functions, so here we go - evil hackery. wchar_t filter[256] = L"XXX files\0*.XXX\0\0"; - memcpy(filter, extension, 3); - memcpy(filter + 12, extension, 3); + memcpy(filter, wext.c_str(), 3 * sizeof(wchar_t)); + memcpy(filter + 12, wext.c_str(), 3 * sizeof(wchar_t)); of.lpstrFilter = filter; - of.lpstrDefExt = extension; + of.lpstrDefExt = wext.c_str(); of.lpstrFile = buffer; of.nMaxFile = 511; of.Flags = OFN_FILEMUSTEXIST; if (!GetOpenFileName(&of)) return false; - *filename = of.lpstrFile; + *filename = ConvertWStringToUTF8(of.lpstrFile); return true; } -bool SaveFileDialog(const wchar_t *title, const wchar_t *extension, std::wstring *filename) -{ +bool SaveFileDialog(const char *title, const char *extension, std::string *filename) { + std::wstring wtitle = ConvertUTF8ToWString(std::string(title)); + std::wstring wext = ConvertUTF8ToWString(std::string(extension)); + OPENFILENAME of; memset(&of, 0, sizeof(of)); wchar_t buffer[512] = {0}; @@ -46,18 +53,18 @@ bool SaveFileDialog(const wchar_t *title, const wchar_t *extension, std::wstring // These weird strings with zeroes in them can't be dealt with using normal string // functions, so here we go - evil hackery. wchar_t filter[256] = L"XXX files\0*.XXX\0\0"; - memcpy(filter, extension, 3); - memcpy(filter + 12, extension, 3); + memcpy(filter, wext.c_str(), 3 * sizeof(wchar_t)); + memcpy(filter + 12, wext.c_str(), 3 * sizeof(wchar_t)); of.lpstrFilter = filter; - of.lpstrDefExt = extension; + of.lpstrDefExt = wext.c_str(); of.lpstrFile = buffer; of.nMaxFile = 511; of.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; if (!GetSaveFileName(&of)) return false; - *filename = of.lpstrFile; + *filename = ConvertWStringToUTF8(of.lpstrFile); return true; } From 790c70f3fb9362828e91fb3d81b95f43f88ef11e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 5 Feb 2014 19:44:43 +0100 Subject: [PATCH 1016/1445] Center SDL window when possible --- base/PCMain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 424f3ab608..efad738fbd 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -381,6 +381,8 @@ void ToggleFullScreenIfFlagSet() { #undef main #endif int main(int argc, char *argv[]) { + putenv("SDL_VIDEO_CENTERED=1"); + std::string app_name; std::string app_name_nice; bool landscape; From 710d63aac16daa3fca8d960d54b8f84475b4714b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 5 Feb 2014 20:01:33 +0100 Subject: [PATCH 1017/1445] Android: Send data about the device used in touch events. --- android/app-android.cpp | 15 ++++------ .../henrikrydgard/libnative/NativeGLView.java | 24 +++++++++++---- input/input_state.h | 29 ++++++++++++------- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 4e45c72d5f..dc487e003b 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -384,24 +384,21 @@ extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* e extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch (JNIEnv *, jclass, float x, float y, int code, int pointerId) { - float scaledX = (int)(x * dp_xscale); // why the (int) cast? - float scaledY = (int)(y * dp_yscale); + float scaledX = x * dp_xscale; + float scaledY = y * dp_yscale; TouchInput touch; touch.id = pointerId; touch.x = scaledX; touch.y = scaledY; - if (code == 1) { + touch.flags = code; + if (code & 2) { input_state.pointer_down[pointerId] = true; - touch.flags = TOUCH_DOWN; - } else if (code == 2) { + } else if (code & 4) { input_state.pointer_down[pointerId] = false; - touch.flags = TOUCH_UP; - } else { - touch.flags = TOUCH_MOVE; } - NativeTouch(touch); + NativeTouch(touch); { lock_guard guard(input_state.lock); if (pointerId >= MAX_POINTERS) { diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index b9455fb6fa..6fd0fc9391 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -3,12 +3,14 @@ package com.henrikrydgard.libnative; // Touch- and sensor-enabled GLSurfaceView. // Supports simple multitouch and pressure. +import android.annotation.TargetApi; import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.opengl.GLSurfaceView; +import android.os.Build; import android.os.Handler; // import android.os.Build; // import android.util.Log; @@ -62,34 +64,44 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, } } + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + private int getToolType(final MotionEvent ev, int pointer) { + return ev.getToolType(pointer); + } + public boolean onTouchEvent(final MotionEvent ev) { + boolean canReadToolType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH; for (int i = 0; i < ev.getPointerCount(); i++) { int pid = ev.getPointerId(i); int code = 0; final int action = ev.getActionMasked(); + // These code bits are now the same as the constants in input_state.h. switch (action) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: if (ev.getActionIndex() == i) - code = 1; + code = 2; break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: if (ev.getActionIndex() == i) - code = 2; + code = 4; break; case MotionEvent.ACTION_MOVE: - code = 3; + code = 1; break; default: break; } + if (code != 0) { - float x = ev.getX(i); - float y = ev.getY(i); - NativeApp.touch(x, y, code, pid); + if (canReadToolType) { + int tool = getToolType(ev, i); + code |= tool << 10; // We use the Android tool type codes + } + NativeApp.touch(ev.getX(i), ev.getY(i), code, pid); } } return true; diff --git a/input/input_state.h b/input/input_state.h index 378a4ba98b..eb16a81bfa 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -8,12 +8,13 @@ // For more detailed and configurable input, implement NativeTouch, NativeKey and NativeAxis and do your // own mapping. Might later move the mapping system from PPSSPP to native. +#include +#include + #include "math/lin/vec3.h" #include "base/mutex.h" #include "base/basictypes.h" #include "input/keycodes.h" -#include -#include // Default device IDs @@ -113,11 +114,19 @@ void UpdateInputState(InputState *input, bool merge = false); void EndInputState(InputState *input); enum { - TOUCH_MOVE = 1, - TOUCH_DOWN = 2, - TOUCH_UP = 4, - TOUCH_CANCEL = 8, // Sent by scrollviews to their children when they detect a scroll - TOUCH_WHEEL = 16, // Scrollwheel event. Usually only affects Y. + TOUCH_MOVE = 1 << 0, + TOUCH_DOWN = 1 << 1, + TOUCH_UP = 1 << 2, + TOUCH_CANCEL = 1 << 3, // Sent by scrollviews to their children when they detect a scroll + TOUCH_WHEEL = 1 << 4, // Scrollwheel event. Usually only affects Y. + + // These are the Android getToolType() codes, shifted by 10. + TOUCH_TOOL_MASK = 7 << 10, + TOUCH_TOOL_UNKNOWN = 0 << 10, + TOUCH_TOOL_FINGER = 1 << 10, + TOUCH_TOOL_STYLUS = 2 << 10, + TOUCH_TOOL_MOUSE = 3 << 10, + TOUCH_TOOL_ERASER = 4 << 10, }; // Used for asynchronous touch input. @@ -135,9 +144,9 @@ struct TouchInput { #undef KEY_UP enum { - KEY_DOWN = 1, - KEY_UP = 2, - KEY_HASWHEELDELTA = 4, + KEY_DOWN = 1 << 0, + KEY_UP = 1 << 1, + KEY_HASWHEELDELTA = 1 << 2, }; struct KeyInput { From b23b44e43bda1777943bf50c77dd0d6ea770ce0f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 5 Feb 2014 20:03:28 +0100 Subject: [PATCH 1018/1445] Update the tools vcprojs --- tools/atlastool.cpp | 7 +++++-- tools/atlastool/atlastool.vcxproj | 19 ++++++++++--------- tools/zimtool/zimtool.vcxproj | 10 ++++------ 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 0c6433a904..314d4f5fb8 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -14,7 +14,7 @@ #include #include #include FT_FREETYPE_H -#include +#include #include #include #include @@ -363,7 +363,10 @@ void RasterizeFonts(const FontReferenceList fontRefs, vector &ranges, for (size_t i = 0, n = fontRefs.size(); i < n; ++i) { FT_Face &font = fonts[i]; - CHECK(FT_New_Face(freetype, fontRefs[i].file_.c_str(), 0, &font) == 0); + if (FT_New_Face(freetype, fontRefs[i].file_.c_str(), 0, &font) != 0) { + printf("Failed to load file %s\n", fontRefs[i].file_.c_str()); + CHECK(false); + } printf("TTF info: %d glyphs, %08x flags, %d units, %d strikes\n", (int)font->num_glyphs, (int)font->face_flags, (int)font->units_per_EM, (int)font->num_fixed_sizes); CHECK(FT_Set_Pixel_Sizes(font, 0, fontRefs[i].size_ * supersample) == 0); diff --git a/tools/atlastool/atlastool.vcxproj b/tools/atlastool/atlastool.vcxproj index a9d29da7f2..6d8e03ba15 100644 --- a/tools/atlastool/atlastool.vcxproj +++ b/tools/atlastool/atlastool.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -20,13 +20,14 @@ Application true MultiByte + v120 Application false false MultiByte - v100 + v120 @@ -43,7 +44,7 @@ false - $(ProjectDir)\..\build + $(ProjectDir)\..\build\ @@ -52,12 +53,12 @@ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..;..\..\SDL\include;..\..\..\libpng;%(AdditionalIncludeDirectories); + ..\..\ext\libpng16;..\..\..\ext\freetype\devel;..\..\..\ext\freetype\include;..\..;..\..\ext\SDL1.2\include;..\..\..\libpng;%(AdditionalIncludeDirectories); Console true - freetype.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies) @@ -71,22 +72,22 @@ true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..;..\..\SDL\include;..\..\..\libpng;%(AdditionalIncludeDirectories); + ..\..\ext\libpng16;..\..\..\ext\freetype\devel;..\..\..\ext\freetype\include;..\..;..\..\ext\SDL1.2\include;..\..\..\libpng;%(AdditionalIncludeDirectories); Console true true true - freetype.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;%(AdditionalDependencies) + kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies) - - {2dbe9ec0-0b03-4b8f-8b8a-75aca6253807} + + {78b079bd-9fc7-4b9e-b4a6-96da0f00248b} {f761046e-6c38-4428-a5f1-38391a37bb34} diff --git a/tools/zimtool/zimtool.vcxproj b/tools/zimtool/zimtool.vcxproj index d43b7f8414..bd3087f108 100644 --- a/tools/zimtool/zimtool.vcxproj +++ b/tools/zimtool/zimtool.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -20,13 +20,14 @@ Application true MultiByte + v120 Application false false MultiByte - v100 + v120 @@ -43,7 +44,7 @@ false - $(ProjectDir)\..\build + $(ProjectDir)\..\build\ @@ -83,9 +84,6 @@ - - {2dbe9ec0-0b03-4b8f-8b8a-75aca6253807} - {f761046e-6c38-4428-a5f1-38391a37bb34} From cf52650724549167de32b7bcd8c85064afa8ec3d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 6 Feb 2014 00:02:45 +0100 Subject: [PATCH 1019/1445] VFS: Detect non-local paths on Windows too. --- file/zip_read.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 0e47801812..ba914197b4 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -341,10 +341,15 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { } bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter) { +#ifdef _WIN32 + if (path[1] == ':') { +#else if (path[0] == '/') { +#endif // Local path, not VFS. ILOG("Not a VFS path: %s . Reading local directory.", path); - return getFilesInDir(path, listing, filter); + getFilesInDir(path, listing, filter); + return true; } int fn_len = (int)strlen(path); @@ -362,7 +367,11 @@ bool VFSGetFileListing(const char *path, std::vector *listing, const c } bool VFSGetFileInfo(const char *path, FileInfo *info) { +#ifdef _WIN32 + if (path[1] == ':') { +#else if (path[0] == '/') { +#endif // Local path, not VFS. ILOG("Not a VFS path: %s . Getting local file info.", path); return getFileInfo(path, info); From 4a743ca627c46a259f8b3ec099912b5b20671114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 7 Feb 2014 11:33:31 +0100 Subject: [PATCH 1020/1445] SDL: Add way to exit cleanly through a message. Warning fix. --- base/PCMain.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index efad738fbd..44556a36ad 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -47,7 +47,8 @@ GlobalUIState lastUIState = UISTATE_MENU; #endif static SDL_Surface* g_Screen = NULL; -bool g_ToggleFullScreenNextFrame = false; +static bool g_ToggleFullScreenNextFrame = false; +static int g_QuitRequested = 0; #if defined(MAEMO) || defined(PANDORA) #define EGL @@ -214,6 +215,9 @@ void Vibrate(int length_ms) { void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "toggle_fullscreen")) { g_ToggleFullScreenNextFrame = true; + } else if (!strcmp(command, "finish")) { + // Do a clean exit + g_QuitRequested = true; } } @@ -381,7 +385,10 @@ void ToggleFullScreenIfFlagSet() { #undef main #endif int main(int argc, char *argv[]) { - putenv("SDL_VIDEO_CENTERED=1"); + // Avoid warning about conversion from const char * to char * + char envTemp[256]; + strcpy(envTemp, "SDL_VIDEO_CENTERED=1"); + putenv(envTemp); std::string app_name; std::string app_name_nice; @@ -588,7 +595,6 @@ int main(int argc, char *argv[]) { while (true) { input_state.accelerometer_valid = false; input_state.mouse_valid = true; - int quitRequested = 0; SDL_Event event; while (SDL_PollEvent(&event)) { @@ -597,7 +603,7 @@ int main(int argc, char *argv[]) { switch (event.type) { case SDL_QUIT: - quitRequested = 1; + g_QuitRequested = 1; break; case SDL_KEYDOWN: { @@ -738,7 +744,7 @@ int main(int argc, char *argv[]) { } } - if (quitRequested) + if (g_QuitRequested) break; const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); From 48b4745e7368a49ed89828d898f0958758f43ef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 7 Feb 2014 14:18:45 +0100 Subject: [PATCH 1021/1445] Some cleanup, make really sure we don't use AudioTrack on Gingerbread+. --- android/app-android.cpp | 2 + .../libnative/NativeActivity.java | 53 ++++++------------- .../libnative/NativeAudioPlayer.java | 3 +- .../libnative/NativeRenderer.java | 2 +- base/PCMain.cpp | 8 ++- 5 files changed, 24 insertions(+), 44 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index dc487e003b..f7ab269793 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -125,6 +125,8 @@ std::string GetJavaString(JNIEnv *env, jstring jstr) { return cpp_string; } +// This is now only used as a trigger for GetAppInfo as a function to all before Init. +// On Android we don't use any of the values it returns. extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) { std::string app_name, app_nice_name; bool landscape; diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 041979be29..dcd31717f2 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -101,8 +101,6 @@ public class NativeActivity extends Activity { private NativeAudioPlayer audioPlayer; protected NativeRenderer nativeRenderer; - boolean useOpenSL = false; - private String shortcutParam = ""; public static String runCommand; @@ -181,22 +179,26 @@ public class NativeActivity extends Activity { this.shortcutParam = ((shortcutParam == null) ? "" : shortcutParam); } + private boolean useOpenSL() { + // Native OpenSL became available on Gingerbread. Let's use it! + return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD); + } + public void Initialize() { - // Initialize audio classes. Do this here since detectOptimalAudioSettings() + // Initialize audio classes. Do this here since detectOptimalAudioSettings() // needs audioManager this.audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); this.audioFocusChangeListener = new AudioFocusChangeListener(); - if (Build.VERSION.SDK_INT >= 9) { - // Native OpenSL is available. Let's use it! - useOpenSL = true; - } if (Build.VERSION.SDK_INT >= 17) { // Get the optimal buffer sz detectOptimalAudioSettings(); } - Log.i(TAG, "onCreate"); + // isLandscape is used to trigger GetAppInfo currently, we + boolean landscape = NativeApp.isLandscape(); + Log.d(TAG, "Landscape: " + landscape); + // Get system information ApplicationInfo appInfo = null; PackageManager packMgmr = getPackageManager(); @@ -212,45 +214,29 @@ public class NativeActivity extends Activity { File sdcard = Environment.getExternalStorageDirectory(); Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); @SuppressWarnings("deprecation") - int scrPixelFormat = display.getPixelFormat(); - Point size = new Point(); - GetScreenSize(size); - int scrWidth = size.x; - int scrHeight = size.y; - - float scrRefreshRate = display.getRefreshRate(); + float scrRefreshRate = display.getRefreshRate(); String externalStorageDir = sdcard.getAbsolutePath(); String dataDir = this.getFilesDir().getAbsolutePath(); String apkFilePath = appInfo.sourceDir; DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); - int dpi = metrics.densityDpi; - // We only use dpi to calculate the width. Smaller aspect ratios have giant text despite high DPI. - // Uh, I mean, this makes no sense. What was I thinking when I wrote this? Let's just use the DPI as it is. - // dpi = (int)((float)dpi * ((float)scrWidth/(float)scrHeight) / (16.0/9.0)); // Adjust to 16:9 + int dpi = metrics.densityDpi; String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL); + NativeApp.init(dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL()); // OK, config should be initialized, we can query for screen rotation. if (Build.VERSION.SDK_INT >= 9) { updateScreenRotation(); } - /* - if (NativeApp.isLandscape()) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - } else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - }*/ - Log.i(TAG, "Device: " + deviceType); - Log.i(TAG, "W : " + scrWidth + " H: " + scrHeight + " rate: " + scrRefreshRate + " fmt: " + scrPixelFormat + " dpi: " + dpi); + Log.i(TAG, " rate: " + scrRefreshRate + " dpi: " + dpi); // Detect OpenGL support. // We don't currently use this detection for anything but good to have in the log. @@ -269,13 +255,6 @@ public class NativeActivity extends Activity { if (Build.VERSION.SDK_INT >= 11) { checkForVibrator(); } - /* - editText = new EditText(this); - editText.setText("Hello world"); - - addContentView(editText, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - */ - // inputBox("Please ener a s", "", "Save"); } @TargetApi(9) @@ -334,9 +313,11 @@ public class NativeActivity extends Activity { setVolumeControlStream(AudioManager.STREAM_MUSIC); // Initialize audio and tell PPSSPP to gain audio focus - if (!useOpenSL) { + if (!useOpenSL()) { + Log.w(TAG, "Falling back to AudioTrack"); audioPlayer = new NativeAudioPlayer(); } + NativeAudioPlayer.gainAudioFocus(this.audioManager, this.audioFocusChangeListener); NativeApp.audioInit(); diff --git a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java index 41ee69307e..763aae59d7 100644 --- a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java +++ b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java @@ -16,7 +16,6 @@ public class NativeAudioPlayer { public synchronized void stop() { if (thread != null) { waitUntilDone(); - } else { Log.e(TAG, "Was already stopped"); } @@ -48,8 +47,8 @@ public class NativeAudioPlayer { } } - private void playStreaming() { + playing_ = true; thread = new Thread(new Runnable() { public void run() { diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index 767c4f9b32..95911a7275 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -31,7 +31,7 @@ public class NativeRenderer implements GLSurfaceView.Renderer { } public void onSurfaceCreated(GL10 unused, EGLConfig config) { - Log.i(TAG, "onSurfaceCreated - EGL context is new or was lost"); + // Log.i(TAG, "onSurfaceCreated - EGL context is new or was lost"); // Actually, it seems that it is here we should recreate lost GL objects. displayInit(); } diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 44556a36ad..39d2897284 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -111,7 +111,7 @@ int8_t EGL_Open() { } int8_t EGL_Init() { - EGLConfig g_eglConfig; //[1] = {NULL}; + EGLConfig g_eglConfig; EGLint g_numConfigs = 0; EGLint attrib_list[]= { #ifdef PANDORA @@ -140,8 +140,7 @@ int8_t EGL_Init() { // Get the SDL window handle SDL_SysWMinfo sysInfo; //Will hold our Window information SDL_VERSION(&sysInfo.version); //Set SDL version - if(SDL_GetWMInfo(&sysInfo) <= 0) - { + if(SDL_GetWMInfo(&sysInfo) <= 0) { printf("EGL ERROR: Unable to get SDL window handle: %s\n", SDL_GetError()); return 1; } @@ -162,8 +161,7 @@ int8_t EGL_Init() { } void EGL_Close() { - if (g_eglDisplay != NULL) - { + if (g_eglDisplay != NULL) { eglMakeCurrent(g_eglDisplay, NULL, NULL, EGL_NO_CONTEXT); if (g_eglContext != NULL) { eglDestroyContext(g_eglDisplay, g_eglContext); From 527c2cf861b0fff3049d795d48a245e6c3866f49 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Feb 2014 13:40:16 -0800 Subject: [PATCH 1022/1445] Update project to MSVC 2013 tools. Retaining XP support, using SDK 7.1a (v120_xp.) Disables SSE2 flag on x64 since it's implied and causes compile warnings. --- native.vcxproj | 9 ++++++--- native.vcxproj.filters | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/native.vcxproj b/native.vcxproj index bbb6640182..8b8276ab32 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -28,24 +28,27 @@ StaticLibrary true Unicode + v120_xp StaticLibrary true Unicode + v120 StaticLibrary false false Unicode - v100 + v120_xp StaticLibrary false false Unicode + v120_xp @@ -147,7 +150,7 @@ true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); - StreamingSIMDExtensions2 + NotSet Fast true false diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 07388744d7..4456492c57 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -1,5 +1,5 @@  - + file From 4ae715832edace32e80cbc340b9d37d83ef5aa73 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 9 Feb 2014 23:15:22 +0100 Subject: [PATCH 1023/1445] Allow control of Kitkat Immersive Mode from native code --- .../libnative/NativeActivity.java | 76 +++++++++---------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index dcd31717f2..20655a2084 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -90,9 +90,6 @@ public class NativeActivity extends Activity { // Adjust these as necessary private static String TAG = "NativeActivity"; - // Easy way to flip it on and off from code. - private static final boolean useKitkatImmersiveMode = false; - // Allows us to skip a lot of initialization on secondary calls to onCreate. private static boolean initialized = false; @@ -288,6 +285,28 @@ public class NativeActivity extends Activity { } } + @SuppressLint("InlinedApi") + @TargetApi(14) + private void updateSystemUiVisibility() { + String immersive = NativeApp.queryConfig("immersiveMode"); + Log.i(TAG, "Immersive: " + immersive); + boolean useImmersive = immersive.equals("1") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + int flags = 0; + if (useLowProfileButtons()) { + flags |= View.SYSTEM_UI_FLAG_LOW_PROFILE; + } + if (useImmersive) { + flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + Log.i(TAG, "Setting immersive mode"); + } + if (mGLSurfaceView != null) { + mGLSurfaceView.setSystemUiVisibility(flags); + } else { + Log.e(TAG, "updateSystemUiVisibility: GLSurfaceView not yet created, ignoring"); + } + } + // Need API 11 to check for existence of a vibrator? Zany. @TargetApi(11) public void checkForVibrator() { @@ -349,12 +368,10 @@ public class NativeActivity extends Activity { nativeRenderer = new NativeRenderer(this); mGLSurfaceView.setRenderer(nativeRenderer); setContentView(mGLSurfaceView); - if (Build.VERSION.SDK_INT >= 14) { - darkenOnScreenButtons(); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - setImmersiveMode(); - } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + updateSystemUiVisibility(); + } } @Override @@ -377,25 +394,6 @@ public class NativeActivity extends Activity { audioManager = null; } - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) - public void darkenOnScreenButtons() { - if (useLowProfileButtons()) { - mGLSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); - } - } - - @TargetApi(Build.VERSION_CODES.KITKAT) - public void setImmersiveMode() { - // this.setImmersive(true); // This is an entirely different kind of immersive mode - hides some notification - if (useKitkatImmersiveMode) { - int flags = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - if (useLowProfileButtons()) { - flags |= View.SYSTEM_UI_FLAG_LOW_PROFILE; - } - mGLSurfaceView.setSystemUiVisibility(flags); - } - } - private boolean detectOpenGLES20() { ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); ConfigurationInfo info = am.getDeviceConfigurationInfo(); @@ -438,23 +436,17 @@ public class NativeActivity extends Activity { audioPlayer.play(); } NativeApp.resume(); - if (Build.VERSION.SDK_INT >= 14) { - darkenOnScreenButtons(); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - setImmersiveMode(); - } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + updateSystemUiVisibility(); + } } - // Prevent destroying and recreating the main activity when the device rotates etc, - // since this would stop the sound. @Override public void onConfigurationChanged(Configuration newConfig) { - // Ignore orientation change super.onConfigurationChanged(newConfig); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - setImmersiveMode(); - } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + updateSystemUiVisibility(); + } } // We simply grab the first input device to produce an event and ignore all others that are connected. @@ -809,6 +801,10 @@ public class NativeActivity extends Activity { if (Build.VERSION.SDK_INT >= 9) { updateScreenRotation(); } + } else if (command.equals("immersive")) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + updateSystemUiVisibility(); + } } return false; } From 93d39b34ff172610ee7230433707e889c37a30cc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 9 Feb 2014 23:31:31 +0100 Subject: [PATCH 1024/1445] Add the few extra lines required to init gl on Raspberry Pi. Still needs work in the build system to set this define. --- base/PCMain.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 39d2897284..44c5a963e5 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -21,6 +21,10 @@ #include "SDL_video.h" #endif +#ifdef RPI +#include +#endif + #include #include "base/display.h" @@ -383,6 +387,10 @@ void ToggleFullScreenIfFlagSet() { #undef main #endif int main(int argc, char *argv[]) { +#ifdef RPI + bcm_host_init(); +#endif + // Avoid warning about conversion from const char * to char * char envTemp[256]; strcpy(envTemp, "SDL_VIDEO_CENTERED=1"); @@ -802,6 +810,10 @@ int main(int argc, char *argv[]) { #endif SDL_Quit(); net::Shutdown(); +#ifdef RPI + bcm_host_deinit(); +#endif + exit(0); return 0; } From e189ba42b0cd68e8806250aa33322f58e867dd41 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 9 Feb 2014 21:42:52 -0800 Subject: [PATCH 1025/1445] Add a simple alternative to UrlEncoder for mulipart. That is, when you want files in your postdata. --- net/url.cpp | 2 ++ net/url.h | 85 +++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 72 insertions(+), 15 deletions(-) diff --git a/net/url.cpp b/net/url.cpp index 4b1c068f57..990bf6ce17 100644 --- a/net/url.cpp +++ b/net/url.cpp @@ -4,6 +4,8 @@ const char *UrlEncoder::unreservedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~"; const char *UrlEncoder::hexChars = "0123456789ABCDEF"; +int MultipartFormDataEncoder::seq = 0; + void Url::Split() { size_t colonSlashSlash = url_.find("://"); if (colonSlashSlash == std::string::npos) { diff --git a/net/url.h b/net/url.h index 734ef0ccd2..52f6cd95e4 100644 --- a/net/url.h +++ b/net/url.h @@ -19,7 +19,7 @@ struct UrlEncoder data.reserve(256); } - void Add(const std::string &key, const std::string &value) + virtual void Add(const std::string &key, const std::string &value) { if (++paramCount > 1) data += '&'; @@ -33,15 +33,6 @@ struct UrlEncoder Add(key, std::string(value)); } - template - void AddT(const std::string &key, const char *fmt, const T value) - { - char temp[64]; - snprintf(temp, sizeof(temp), fmt, value); - temp[sizeof(temp) - 1] = '\0'; - Add(key, temp); - } - void Add(const std::string &key, const int value) { AddT(key, "%d", value); @@ -67,6 +58,21 @@ struct UrlEncoder Add(key, value ? "true" : "false"); } + const std::string &ToString() const + { + return data; + } + +protected: + template + void AddT(const std::string &key, const char *fmt, const T value) + { + char temp[64]; + snprintf(temp, sizeof(temp), fmt, value); + temp[sizeof(temp) - 1] = '\0'; + Add(key, temp); + } + // Percent encoding, aka application/x-www-form-urlencoded. void AppendEscaped(const std::string &value) { @@ -92,11 +98,6 @@ struct UrlEncoder } } - std::string &ToString() - { - return data; - } - std::string data; int paramCount; static const char *unreservedChars; @@ -104,6 +105,60 @@ struct UrlEncoder }; +// Stores everything in memory, not super efficient. +// Easy to swap out for a UrlEncoder. +struct MultipartFormDataEncoder : UrlEncoder +{ + MultipartFormDataEncoder() : UrlEncoder() + { + data.reserve(8192); + int r1 = rand(); + int r2 = rand(); + char temp[256]; + snprintf(temp, sizeof(temp), "NATIVE-DATA-BOUNDARY-%08x%08x-%d", r1, r2, seq++); + boundary = temp; + } + + virtual void Add(const std::string &key, const std::string &value) + { + Add(key, value, "", ""); + } + + void Add(const std::string &key, const std::string &value, const std::string &filename, const std::string &mimeType) + { + data += "--" + boundary + "\r\n"; + data += "Content-Disposition: form-data; name=\"" + key + "\""; + if (!filename.empty()) + data += "; filename=\"" + filename + "\""; + data += "\r\n"; + if (!mimeType.empty()) + data += "Content-Type: " + mimeType + "\r\n"; + char temp[64]; + snprintf(temp, sizeof(temp), "Content-Length: %d\r\n", (int)value.size()); + data += temp; + data += "\r\n"; + + data += value; + data += "\r\n"; + } + + void Finish() + { + data += "--" + boundary + "--"; + } + + std::string GetMimeType() const + { + return "multipart/form-data; boundary=\"" + boundary + "\""; + } + +protected: + std::string boundary; + + static int seq; +}; + + class Url { public: Url(const std::string url) : valid_(false), url_(url) { From e569903f9c68c5c4c11d707f1853c59629300379 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 9 Feb 2014 21:56:34 -0800 Subject: [PATCH 1026/1445] Make it just a bit more drop-in compatible. --- net/url.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/net/url.h b/net/url.h index 52f6cd95e4..c796ae46b3 100644 --- a/net/url.h +++ b/net/url.h @@ -58,11 +58,20 @@ struct UrlEncoder Add(key, value ? "true" : "false"); } + virtual void Finish() + { + } + const std::string &ToString() const { return data; } + virtual std::string GetMimeType() const + { + return "application/x-www-form-urlencoded"; + } + protected: template void AddT(const std::string &key, const char *fmt, const T value) @@ -142,12 +151,12 @@ struct MultipartFormDataEncoder : UrlEncoder data += "\r\n"; } - void Finish() + virtual void Finish() { data += "--" + boundary + "--"; } - std::string GetMimeType() const + virtual std::string GetMimeType() const { return "multipart/form-data; boundary=\"" + boundary + "\""; } From f73890f0b2f74b852e86a5b8f33056fe1790ec5d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 10 Feb 2014 12:35:36 +0100 Subject: [PATCH 1027/1445] UIContext now keeps track of dimensions, allowing us to reduce use of display.h --- gfx_es2/draw_buffer.cpp | 20 ++++++++++++++++++++ gfx_es2/draw_buffer.h | 15 ++++----------- ui/screen.h | 1 - ui/ui_context.cpp | 6 ++++-- ui/ui_context.h | 6 ++++++ ui/ui_screen.cpp | 8 ++++++-- ui/view.cpp | 2 +- ui/viewgroup.cpp | 9 ++------- 8 files changed, 43 insertions(+), 24 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 03e43e8a4c..400cea35e2 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -147,6 +147,18 @@ void DrawBuffer::Rect(float x, float y, float w, float h, uint32 color, int alig RectVGradient(x, y, w, h, color, color); } +void DrawBuffer::hLine(float x1, float y, float x2, uint32 color) { + Rect(x1, y, x2 - x1, pixel_in_dps, color); +} + +void DrawBuffer::vLine(float x, float y1, float y2, uint32 color) { + Rect(x, y1, pixel_in_dps, y2 - y1, color); +} + +void DrawBuffer::vLineAlpha50(float x, float y1, float y2, uint32 color) { + Rect(x, y1, pixel_in_dps, y2 - y1, (color | 0xFF000000) & 0x7F000000); +} + void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom) { V(x, y, 0, colorTop, 0, 0); V(x + w, y, 0, colorTop, 1, 0); @@ -156,6 +168,14 @@ void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32 colorT V(x, y + h, 0, colorBottom, 0, 1); } +void DrawBuffer::RectOutline(float x, float y, float w, float h, uint32 color, int align) { + hLine(x, y, x + w + pixel_in_dps, color); + hLine(x, y + h, x + w + pixel_in_dps, color); + + vLine(x, y, y + h + pixel_in_dps, color); + vLine(x + w, y, y + h + pixel_in_dps, color); +} + void DrawBuffer::MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops) { for (int i = 0; i < numStops - 1; i++) { float t0 = stops[i].t, t1 = stops[i+1].t; diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 88a62770e7..9d3cd90911 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -4,7 +4,6 @@ #include "base/basictypes.h" #include "base/color.h" -#include "base/display.h" #include "gfx/gl_lost_manager.h" #include "gfx/texture_atlas.h" #include "math/geom2d.h" @@ -73,17 +72,11 @@ public: void Flush(bool set_blend_state=true); void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); - void hLine(float x1, float y, float x2, uint32 color) { Rect(x1, y, x2 - x1, pixel_in_dps, color); } - void vLine(float x, float y1, float y2, uint32 color) { Rect(x, y1, pixel_in_dps, y2 - y1, color); } - void vLineAlpha50(float x, float y1, float y2, uint32 color) { Rect(x, y1, pixel_in_dps, y2 - y1, (color | 0xFF000000) & 0x7F000000); } + void hLine(float x1, float y, float x2, uint32 color); + void vLine(float x, float y1, float y2, uint32 color); + void vLineAlpha50(float x, float y1, float y2, uint32 color); - void RectOutline(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT) { - hLine(x, y, x + w + pixel_in_dps, color); - hLine(x, y + h, x + w + pixel_in_dps, color); - - vLine(x, y, y + h + pixel_in_dps, color); - vLine(x + w, y, y + h + pixel_in_dps, color); - } + void RectOutline(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom); void RectVDarkFaded(float x, float y, float w, float h, uint32 colorTop) { diff --git a/ui/screen.h b/ui/screen.h index 4df96d1c86..9a76ab119e 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -17,7 +17,6 @@ #include "base/basictypes.h" #include "base/logging.h" -#include "base/display.h" #include "base/NativeApp.h" namespace UI { diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 1731cd230b..ea4c2a8266 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -1,3 +1,4 @@ +#include "base/display.h" #include "ui/ui.h" #include "ui/view.h" #include "ui/ui_context.h" @@ -12,6 +13,7 @@ UIContext::UIContext() fontScaleX_ = 1.0f; fontScaleY_ = 1.0f; fontStyle_ = new UI::FontStyle(); + bounds_ = Bounds(0, 0, dp_xres, dp_yres); } UIContext::~UIContext() { @@ -107,7 +109,7 @@ Bounds UIContext::GetScissorBounds() { if (!scissorStack_.empty()) return scissorStack_.back(); else - return Bounds(0, 0, dp_xres, dp_yres); + return bounds_; } void UIContext::ActivateTopScissor() { @@ -119,7 +121,7 @@ void UIContext::ActivateTopScissor() { int w = scale * bounds.w; int h = scale * bounds.h; - glstate.scissorRect.set(x,y,w,h); + glstate.scissorRect.set(x, y, w, h); glstate.scissorTest.enable(); } else { glstate.scissorTest.disable(); diff --git a/ui/ui_context.h b/ui/ui_context.h index 82dc714697..ea87aab7f5 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -59,7 +59,13 @@ public: void DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align = 0); void FillRect(const UI::Drawable &drawable, const Bounds &bounds); + // in dps, like dp_xres and dp_yres + void SetBounds(const Bounds &b) { bounds_ = b; } + const Bounds &GetBounds() const { return bounds_; } + private: + Bounds bounds_; + float fontScaleX_; float fontScaleY_; UI::FontStyle *fontStyle_; diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index a933d8cfd8..8a41ff7c65 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -143,10 +143,14 @@ void PopupScreen::touch(const TouchInput &touch) { void PopupScreen::CreateViews() { using namespace UI; + UIContext &dc = *screenManager()->getUIContext(); + root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); + float yres = screenManager()->getUIContext()->GetBounds().h; + box_ = new LinearLayout(ORIENT_VERTICAL, - new AnchorLayoutParams(550, FillVertical() ? dp_yres - 30 : WRAP_CONTENT, dp_xres / 2, dp_yres / 2, NONE, NONE, true)); + new AnchorLayoutParams(550, FillVertical() ? yres - 30 : WRAP_CONTENT, dc.GetBounds().centerX(), dc.GetBounds().centerY(), NONE, NONE, true)); root_->Add(box_); box_->SetBG(UI::Drawable(0xFF303030)); @@ -198,7 +202,7 @@ void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; listView_ = parent->Add(new ListView(&adaptor_)); //, new LinearLayoutParams(1.0))); - listView_->SetMaxHeight(dp_yres - 140); + listView_->SetMaxHeight(screenManager()->getUIContext()->GetBounds().h - 140); listView_->OnChoice.Handle(this, &ListPopupScreen::OnListChoice); } diff --git a/ui/view.cpp b/ui/view.cpp index 8e7f60b289..b9f500909a 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -1,6 +1,6 @@ #include #include -#include "base/display.h" + #include "base/mutex.h" #include "input/input_state.h" #include "input/keycodes.h" diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 7c72f51f39..43cbaeeb27 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1,6 +1,5 @@ #include -#include "base/display.h" #include "base/functional.h" #include "base/logging.h" #include "base/mutex.h" @@ -105,7 +104,7 @@ void ViewGroup::Axis(const AxisInput &input) { void ViewGroup::Draw(UIContext &dc) { if (hasDropShadow_) { // Darken things behind. - dc.FillRect(UI::Drawable(0x60000000), Bounds(0,0,dp_xres, dp_yres)); + dc.FillRect(UI::Drawable(0x60000000), dc.GetBounds()); float dropsize = 30; dc.Draw()->DrawImage4Grid(dc.theme->dropShadow4Grid, bounds_.x - dropsize, bounds_.y, @@ -1072,11 +1071,7 @@ void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root) { ELOG("Tried to layout a view hierarchy from a zero pointer root"); return; } - Bounds rootBounds; - rootBounds.x = 0; - rootBounds.y = 0; - rootBounds.w = dp_xres; - rootBounds.h = dp_yres; + const Bounds &rootBounds = dc.GetBounds(); MeasureSpec horiz(EXACTLY, rootBounds.w); MeasureSpec vert(EXACTLY, rootBounds.h); From 52a7af1ed33af7f1244d4c09de8e3da6a7b47dc5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 10 Feb 2014 15:12:55 +0100 Subject: [PATCH 1028/1445] Fix some build errors due to a removed variable --- base/BlackberryDisplay.cpp | 2 -- base/PCMain.cpp | 2 ++ base/QtMain.h | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/base/BlackberryDisplay.cpp b/base/BlackberryDisplay.cpp index 3670f75acc..91045614d7 100644 --- a/base/BlackberryDisplay.cpp +++ b/base/BlackberryDisplay.cpp @@ -135,8 +135,6 @@ void BlackberryMain::switchDisplay(int idx) { if (emulating) { PSP_CoreParameter().pixelWidth = pixel_xres; PSP_CoreParameter().pixelHeight = pixel_yres; - PSP_CoreParameter().outputWidth = dp_xres; - PSP_CoreParameter().outputHeight = dp_yres; } } diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 44c5a963e5..89b78d75c1 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -563,7 +563,9 @@ int main(int argc, char *argv[]) { printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); + NativeInitGraphics(); + NativeResized(); SDL_AudioSpec fmt; fmt.freq = 44100; diff --git a/base/QtMain.h b/base/QtMain.h index 13ea21b22b..bf9b46c4a1 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -82,8 +82,6 @@ protected: dp_yres = pixel_yres * g_dpi_scale; PSP_CoreParameter().pixelWidth = pixel_xres; PSP_CoreParameter().pixelHeight = pixel_yres; - PSP_CoreParameter().outputWidth = dp_xres; - PSP_CoreParameter().outputHeight = dp_yres; } void timerEvent(QTimerEvent *) { From 35e00807d3c762cc9f799121636790e97b2a757b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 10 Feb 2014 16:07:42 +0100 Subject: [PATCH 1029/1445] Add a helper to easily fill a "Bounds" with a texture. --- gfx_es2/draw_buffer.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 9d3cd90911..65d09870ce 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -112,6 +112,9 @@ public: } void DrawImageRotated(ImageID atlas_image, float x, float y, float scale, float angle, Color color = COLOR(0xFFFFFF), bool mirror_h = false); // Always centers void DrawTexRect(float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2, Color color); + void DrawTexRect(const Bounds &bounds, float u1, float v1, float u2, float v2, Color color) { + DrawTexRect(bounds.x, bounds.y, bounds.x2(), bounds.y2(), u1, v1, u2, v2, color); + } // Results in 18 triangles. Kind of expensive for a button. void DrawImage4Grid(ImageID atlas_image, float x1, float y1, float x2, float y2, Color color = COLOR(0xFFFFFF), float corner_scale = 1.0); // This is only 6 triangles, much cheaper. From 5ca590b746c16eb79beeae805847ec5b0201c011 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 12 Feb 2014 10:21:28 +0100 Subject: [PATCH 1030/1445] Add a way to override the framebuffer bound with "unbind". Allows capturing the output properly if needed to redisplay in strange ways, such as duplicating the screen for VR headsets and similar. This code will be committed later. For true stereo, will need a lot more changes. --- gfx_es2/fbo.cpp | 11 ++++++++++- gfx_es2/fbo.h | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index a38408404c..1a1ccafc59 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -40,6 +40,7 @@ struct FBO { FBOColorDepth colorDepth; }; +static FBO *g_overriddenBackbuffer; // On PC, we always use GL_DEPTH24_STENCIL8. // On Android, we try to use what's available. @@ -237,8 +238,12 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F } void fbo_unbind() { - CheckGLExtensions(); + if (g_overriddenBackbuffer) { + fbo_bind_as_render_target(g_overriddenBackbuffer); + return; + } + CheckGLExtensions(); if (gl_extensions.FBO_ARB) { glBindFramebuffer(GL_FRAMEBUFFER, 0); } else { @@ -251,6 +256,10 @@ void fbo_unbind() { #endif } +void fbo_override_backbuffer(FBO *fbo) { + g_overriddenBackbuffer = fbo; +} + void fbo_bind_as_render_target(FBO *fbo) { if (gl_extensions.FBO_ARB) { #ifndef USING_GLES2 diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index e424451aa0..e0651fd343 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -36,3 +36,5 @@ void fbo_get_dimensions(FBO *fbo, int *w, int *h); int fbo_get_color_texture(FBO *fbo); int fbo_get_depth_buffer(FBO *fbo); int fbo_get_stencil_buffer(FBO *fbo); + +void fbo_override_backbuffer(FBO *fbo); // Makes unbind bind this instead of the real backbuffer. From 52237f3980f65b4c8c9fcdf599afd485ff7845d1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 12 Feb 2014 11:03:31 +0100 Subject: [PATCH 1031/1445] Fix bug where files with the same prefix as a directory would look like they were in that directory, but with their name chopped. --- file/zip_read.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index ba914197b4..f832469bde 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -176,9 +176,10 @@ bool ZipAssetReader::GetFileListing(const char *orig_path, std::vector // A directory. std::string dirName = std::string(name + pathlen + 1, slashPos - (name + pathlen + 1)); directories.insert(dirName); - } else { - files.insert(std::string(name + pathlen + 1)); - } + } else if (name[pathlen] == '/') { + const char *fn = name + pathlen + 1; + files.insert(std::string(fn)); + } // else, it was a file with the same prefix as the path. like langregion.ini next to lang/. } } @@ -351,7 +352,7 @@ bool VFSGetFileListing(const char *path, std::vector *listing, const c getFilesInDir(path, listing, filter); return true; } - + int fn_len = (int)strlen(path); for (int i = 0; i < num_entries; i++) { int prefix_len = (int)strlen(entries[i].prefix); From ae94967bec25ed96a63cbb85d6b5d53953240584 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 12 Feb 2014 11:51:59 +0100 Subject: [PATCH 1032/1445] Add proper shutdown to Blackberry (untested) @xsacha --- base/BlackberryMain.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 8ca760cc8b..311b22230d 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -17,6 +17,8 @@ #include "Core/Config.h" #include "UI/MiscScreens.h" +static bool g_quitRequested = false; + // Simple implementations of System functions std::string System_GetProperty(SystemProperty prop) { @@ -39,7 +41,11 @@ std::string System_GetProperty(SystemProperty prop) { } } -void System_SendMessage(const char *command, const char *parameter) {} +void System_SendMessage(const char *command, const char *parameter) { + if (!strcmp(command, "finish")) { + g_quitRequested = true; + } +} void SystemToast(const char *text) { dialog_instance_t dialog = 0; @@ -214,6 +220,7 @@ void BlackberryMain::handleInput(screen_event_t screen_event) } void BlackberryMain::startMain(int argc, char *argv[]) { + g_quitRequested = false; // Receive events from window manager screen_create_context(&screen_cxt, 0); // Initialise Blackberry Platform Services @@ -236,7 +243,7 @@ void BlackberryMain::startMain(int argc, char *argv[]) { void BlackberryMain::runMain() { bool running = true; - while (running) { + while (running && !g_quitRequested) { input_state.mouse_valid = false; input_state.accelerometer_valid = false; while (true) { From 5557c6801b1f1ddf9c172b5614dd1853d3ce9d4c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 12 Feb 2014 11:54:53 +0100 Subject: [PATCH 1033/1445] Also add basic support for "clean exit" to Symbian (although hacky) --- base/BlackberryMain.cpp | 1 + base/QtMain.cpp | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 311b22230d..e3e75b5c49 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include // Get locale #include // Receive invocation messages diff --git a/base/QtMain.cpp b/base/QtMain.cpp index a4a20327ab..1b6da8ad8d 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -24,6 +24,8 @@ #endif #include "QtMain.h" +#include + InputState* input_state; std::string System_GetProperty(SystemProperty prop) { @@ -54,7 +56,12 @@ std::string System_GetProperty(SystemProperty prop) { } void System_SendMessage(const char *command, const char *parameter) { - // Log? + // TODO: Cleaner exit + if (!strcmp(command, "finish")) { + NativeShutdown(); + net::Shutdown(); + exit(0); + } } bool System_InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outLength) From 6f6c81ce190b04d97708eafad6bbdceecf2c33ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 12 Feb 2014 12:45:26 +0100 Subject: [PATCH 1034/1445] Need to check the quit flag here too --- base/PCMain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 89b78d75c1..0e0958e798 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -751,15 +751,15 @@ int main(int argc, char *argv[]) { break; } } - if (g_QuitRequested) break; - const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); SimulateGamepad(keys, &input_state); input_state.pad_buttons = pad_buttons; UpdateInputState(&input_state, true); NativeUpdate(input_state); + if (g_QuitRequested) + break; NativeRender(); #if defined(PPSSPP) && !defined(MAEMO) if (lastUIState != globalUIState) { From 25586949ccdf144efd83df32e1ece96c04dc7d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 12 Feb 2014 12:46:43 +0100 Subject: [PATCH 1035/1445] Tab fix --- base/BlackberryMain.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index e3e75b5c49..37a1bc34f7 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -43,9 +43,9 @@ std::string System_GetProperty(SystemProperty prop) { } void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "finish")) { - g_quitRequested = true; - } + if (!strcmp(command, "finish")) { + g_quitRequested = true; + } } void SystemToast(const char *text) { @@ -140,7 +140,7 @@ void BlackberryMain::handleInput(screen_event_t screen_event) NativeTouch(input); break; // Mouse, Simulator - case SCREEN_EVENT_POINTER: + case SCREEN_EVENT_POINTER: screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons); if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down input_state.pointer_x[0] = pair[0] * g_dpi_scale; @@ -221,7 +221,7 @@ void BlackberryMain::handleInput(screen_event_t screen_event) } void BlackberryMain::startMain(int argc, char *argv[]) { - g_quitRequested = false; + g_quitRequested = false; // Receive events from window manager screen_create_context(&screen_cxt, 0); // Initialise Blackberry Platform Services From d644f708c7c09b5dcddea44279519f3595a57801 Mon Sep 17 00:00:00 2001 From: The Dax Date: Wed, 12 Feb 2014 18:43:53 -0500 Subject: [PATCH 1036/1445] Allow the i18n ini path to be overridden with a custom path. --- i18n/i18n.cpp | 16 +++++++++++----- i18n/i18n.h | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp index 6b93848b7a..702ed8f44f 100644 --- a/i18n/i18n.cpp +++ b/i18n/i18n.cpp @@ -72,14 +72,20 @@ bool I18NRepo::IniExists(const std::string &languageID) const { return true; } -bool I18NRepo::LoadIni(const std::string &languageID) { +bool I18NRepo::LoadIni(const std::string &languageID, const std::string &overridePath) { IniFile ini; - std::string iniPath = GetIniPath(languageID); -// ILOG("Loading lang ini %s", iniPath.c_str()); - if (!ini.LoadFromVFS(GetIniPath(languageID))) { - return false; + std::string iniPath; + + // ILOG("Loading lang ini %s", iniPath.c_str()); + if (!overridePath.empty()) { + iniPath = overridePath + languageID + ".ini"; + } else { + iniPath = GetIniPath(languageID); } + if (!ini.LoadFromVFS(iniPath)) + return false; + Clear(); const std::vector §ions = ini.Sections(); diff --git a/i18n/i18n.h b/i18n/i18n.h index b889a9c2d6..2a52b21043 100644 --- a/i18n/i18n.h +++ b/i18n/i18n.h @@ -66,7 +66,7 @@ public: ~I18NRepo(); bool IniExists(const std::string &languageID) const; - bool LoadIni(const std::string &languageID); // NOT the filename! + bool LoadIni(const std::string &languageID, const std::string &overridePath = ""); // NOT the filename! void SaveIni(const std::string &languageID); I18NCategory *GetCategory(const char *categoryName); From 128e95c079d91776d9daf573824c8539383114ac Mon Sep 17 00:00:00 2001 From: The Dax Date: Wed, 12 Feb 2014 18:48:09 -0500 Subject: [PATCH 1037/1445] Fix bad tab. --- i18n/i18n.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/i18n.cpp b/i18n/i18n.cpp index 702ed8f44f..84e7e79822 100644 --- a/i18n/i18n.cpp +++ b/i18n/i18n.cpp @@ -76,7 +76,7 @@ bool I18NRepo::LoadIni(const std::string &languageID, const std::string &overrid IniFile ini; std::string iniPath; - // ILOG("Loading lang ini %s", iniPath.c_str()); +// ILOG("Loading lang ini %s", iniPath.c_str()); if (!overridePath.empty()) { iniPath = overridePath + languageID + ".ini"; } else { From 9cb2292308cbc9373eec2d76b1d4790441f3d172 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 15 Feb 2014 09:59:49 +0100 Subject: [PATCH 1038/1445] Reset rotation lock on resume --- .../com/henrikrydgard/libnative/NativeActivity.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 20655a2084..b13eeaddc9 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -424,6 +424,14 @@ public class NativeActivity extends Activity { @Override protected void onResume() { super.onResume(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + updateSystemUiVisibility(); + } + // OK, config should be initialized, we can query for screen rotation. + if (Build.VERSION.SDK_INT >= 9) { + updateScreenRotation(); + } + Log.i(TAG, "onResume"); if (mGLSurfaceView != null) { mGLSurfaceView.onResume(); @@ -436,9 +444,6 @@ public class NativeActivity extends Activity { audioPlayer.play(); } NativeApp.resume(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - updateSystemUiVisibility(); - } } @Override From 263e2207be4a281c7991419bff2c69224d8a4288 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 15 Feb 2014 10:15:07 +0100 Subject: [PATCH 1039/1445] FrameCommand cleanup, logic fix in "vibrate" handling --- android/app-android.cpp | 10 ++-- .../libnative/NativeActivity.java | 52 +++++++++---------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index f7ab269793..10e18c9d17 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -336,15 +336,13 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + lock_guard guard(frameCommandLock); while (!frameCommands.empty()) { FrameCommand frameCmd; - { - lock_guard guard(frameCommandLock); - frameCmd = frameCommands.front(); - frameCommands.pop(); - } + frameCmd = frameCommands.front(); + frameCommands.pop(); - DLOG("frameCommand %s %s", cmd.command.c_str(), frameCmd.params.c_str()); + DLOG("frameCommand %s %s", frameCmd.command.c_str(), frameCmd.params.c_str()); jstring cmd = env->NewStringUTF(frameCmd.command.c_str()); jstring param = env->NewStringUTF(frameCmd.params.c_str()); diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index b13eeaddc9..95cedd0170 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -769,35 +769,35 @@ public class NativeActivity extends Activity { inputBox(title, defString, "OK"); return true; } else if (command.equals("vibrate")) { - if (vibrator != null) { - int milliseconds = -1; - if (params != "") { - try { - milliseconds = Integer.parseInt(params); - } catch (NumberFormatException e) { - } + int milliseconds = -1; + if (params != "") { + try { + milliseconds = Integer.parseInt(params); + } catch (NumberFormatException e) { } - // Special parameters to perform standard haptic feedback - // operations - // -1 = Standard keyboard press feedback - // -2 = Virtual key press - // -3 = Long press feedback - // Note that these three do not require the VIBRATE Android - // permission. - switch (milliseconds) { - case -1: - mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); - break; - case -2: - mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); - break; - case -3: - mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - break; - default: + } + // Special parameters to perform standard haptic feedback + // operations + // -1 = Standard keyboard press feedback + // -2 = Virtual key press + // -3 = Long press feedback + // Note that these three do not require the VIBRATE Android + // permission. + switch (milliseconds) { + case -1: + mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + break; + case -2: + mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + break; + case -3: + mGLSurfaceView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + break; + default: + if (vibrator != null) { vibrator.vibrate(milliseconds); - break; } + break; } return true; } else if (command.equals("finish")) { From c69e7c3bea0ebf0f8d15a7354b07289b60ee96e9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 15 Feb 2014 01:42:48 -0800 Subject: [PATCH 1040/1445] Fix crash on shutdown in Qt. Scoped pointers need to destruct first, or else we'll try to access emulator internals within their destructors. --- base/QtMain.cpp | 68 +++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 1b6da8ad8d..b3cf433d64 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -56,12 +56,12 @@ std::string System_GetProperty(SystemProperty prop) { } void System_SendMessage(const char *command, const char *parameter) { - // TODO: Cleaner exit - if (!strcmp(command, "finish")) { - NativeShutdown(); - net::Shutdown(); - exit(0); - } + // TODO: Cleaner exit + if (!strcmp(command, "finish")) { + NativeShutdown(); + net::Shutdown(); + exit(0); + } } bool System_InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outLength) @@ -104,6 +104,37 @@ float CalculateDPIScale() #endif } +static int mainInternal(QApplication &a) +{ +#ifdef USING_GLES2 + emugl = new MainUI(); + emugl->resize(pixel_xres, pixel_yres); + emugl->showFullScreen(); +#endif +#ifdef __SYMBIAN32__ + // Set RunFast hardware mode for VFPv2. + User::SetFloatingPointMode(EFpModeRunFast); + // Disable screensaver + QScopedPointer ssObject(new QSystemScreenSaver(emugl)); + ssObject->setScreenSaverInhibit(); + QScopedPointer mediakeys(new SymbianMediaKeys()); +#endif + + QScopedPointer thread(new QThread); + QScopedPointer audio(new MainAudio()); + audio->moveToThread(thread.data()); + QObject::connect(thread.data(), SIGNAL(started()), audio.data(), SLOT(run())); + thread->start(); + +#ifdef QT_HAS_SDL + SDLJoystick joy(true); + joy.startEventLoop(); +#endif + int ret = a.exec(); + thread->quit(); + return ret; +} + #ifndef QT_HAS_SDL Q_DECL_EXPORT #endif @@ -135,32 +166,9 @@ int main(int argc, char *argv[]) const char *assets_dir = "./"; #endif NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); -#ifdef USING_GLES2 - emugl = new MainUI(); - emugl->resize(pixel_xres, pixel_yres); - emugl->showFullScreen(); -#endif -#ifdef __SYMBIAN32__ - // Set RunFast hardware mode for VFPv2. - User::SetFloatingPointMode(EFpModeRunFast); - // Disable screensaver - QScopedPointer ssObject(new QSystemScreenSaver(emugl)); - ssObject->setScreenSaverInhibit(); - QScopedPointer mediakeys(new SymbianMediaKeys()); -#endif - QScopedPointer thread(new QThread); - QScopedPointer audio(new MainAudio()); - audio->moveToThread(thread.data()); - QObject::connect(thread.data(), SIGNAL(started()), audio.data(), SLOT(run())); - thread->start(); + int ret = mainInternal(a); -#ifdef QT_HAS_SDL - SDLJoystick joy(true); - joy.startEventLoop(); -#endif - int ret = a.exec(); - thread->quit(); NativeShutdown(); net::Shutdown(); return ret; From 36a9bafcaf90b962480c1ce12155f313ba101cc9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 15 Feb 2014 01:46:47 -0800 Subject: [PATCH 1041/1445] Avoid a char * for constant strings. --- base/NativeApp.h | 2 +- base/QtMain.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/NativeApp.h b/base/NativeApp.h index d99b9e20ad..571364f42b 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -116,7 +116,7 @@ void Vibrate(int length_ms); void LaunchBrowser(const char *url); void LaunchMarket(const char *url); void LaunchEmail(const char *email_address); -bool System_InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outlength); +bool System_InputBoxGetString(const char *title, const char *defaultValue, char *outValue, size_t outlength); bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultValue, std::wstring &outValue); void System_SendMessage(const char *command, const char *parameter); diff --git a/base/QtMain.cpp b/base/QtMain.cpp index b3cf433d64..c2048d21da 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -64,7 +64,7 @@ void System_SendMessage(const char *command, const char *parameter) { } } -bool System_InputBoxGetString(char *title, const char *defaultValue, char *outValue, size_t outLength) +bool System_InputBoxGetString(const char *title, const char *defaultValue, char *outValue, size_t outLength) { QString text = emugl->InputBoxGetQString(QString(title), QString(defaultValue)); if (text.isEmpty()) From c803a1511108c43558334e5bd4f02de87642d132 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 16 Feb 2014 22:11:53 -0800 Subject: [PATCH 1042/1445] Update the screen scale on window resize in Qt. Not sure if the right place, but already has PPSSPP specific code anyway. --- base/QtMain.h | 1 + 1 file changed, 1 insertion(+) diff --git a/base/QtMain.h b/base/QtMain.h index bf9b46c4a1..4fab7543ce 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -82,6 +82,7 @@ protected: dp_yres = pixel_yres * g_dpi_scale; PSP_CoreParameter().pixelWidth = pixel_xres; PSP_CoreParameter().pixelHeight = pixel_yres; + UpdateScreenScale(pixel_xres, pixel_yres); } void timerEvent(QTimerEvent *) { From 7b88bd791844b25cbec7bc9a4e54690de5a37e97 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 17 Feb 2014 18:49:57 +0100 Subject: [PATCH 1043/1445] Use case insensitivity when reading from zip files --- file/zip_read.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index f832469bde..bcd3bc0a27 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -19,12 +19,12 @@ uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. struct zip_stat zstat; - zip_file *file = zip_fopen(archive, filename, 0); + zip_file *file = zip_fopen(archive, filename, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED); if (!file) { ELOG("Error opening %s from ZIP", filename); return 0; } - zip_stat(archive, filename, ZIP_FL_NOCASE, &zstat); + zip_stat(archive, filename, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED, &zstat); uint8_t *contents = new uint8_t[zstat.size + 1]; zip_fread(file, contents, zstat.size); @@ -227,7 +227,7 @@ bool ZipAssetReader::GetFileInfo(const char *path, FileInfo *info) { char temp_path[1024]; strcpy(temp_path, in_zip_path_); strcat(temp_path, path); - if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE, &zstat)) { + if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED, &zstat)) { // ZIP files do not have real directories, so we'll end up here if we // try to stat one. For now that's fine. info->exists = false; @@ -329,7 +329,7 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { - // ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); + ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); if (data) return data; From ade958043cb4d376a5b376da79ff05f70e187195 Mon Sep 17 00:00:00 2001 From: chinhodado Date: Mon, 17 Feb 2014 20:46:51 -0500 Subject: [PATCH 1044/1445] minor condition change there's no guarantee that the function will return 1 on success, at least not in the documentation --- base/mutex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/mutex.h b/base/mutex.h index 14a8c576ec..fb0affa384 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -96,7 +96,7 @@ public: bool trylock() { #ifdef _WIN32 - return TryEnterCriticalSection(&mut_) == TRUE; + return TryEnterCriticalSection(&mut_) != FALSE; #else return pthread_mutex_trylock(&mut_) != EBUSY; #endif From 4dd55657c5677677dfcb03ddcd6ff73649c762b1 Mon Sep 17 00:00:00 2001 From: TwistedUmbrella Date: Wed, 19 Feb 2014 22:56:29 -0500 Subject: [PATCH 1045/1445] Ignore the preemptive key processing for ICS Xperia Play --- .../com/henrikrydgard/libnative/NativeActivity.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 95cedd0170..3c7ec7cf72 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -113,6 +113,8 @@ public class NativeActivity extends Activity { private AudioManager audioManager; private Vibrator vibrator; + + private boolean isXperiaPlay; // Allow for two connected gamepads but just consider them the same for now. // Actually this is not entirely true, see the code. @@ -206,6 +208,8 @@ public class NativeActivity extends Activity { e.printStackTrace(); throw new RuntimeException("Unable to locate assets, aborting..."); } + + isXperiaPlay = IsXperiaPlay(); String libraryDir = getApplicationLibraryDir(appInfo); File sdcard = Environment.getExternalStorageDirectory(); @@ -483,11 +487,15 @@ public class NativeActivity extends Activity { return inputPlayerA; } + public boolean IsXperiaPlay() { + return android.os.Build.MODEL.equals("R800a") || android.os.Build.MODEL.equals("R800i") || android.os.Build.MODEL.equals("R800x") || android.os.Build.MODEL.equals("R800at") || android.os.Build.MODEL.equals("SO-01D") || android.os.Build.MODEL.equals("zeus"); + } + // We grab the keys before onKeyDown/... even see them. This is also better because it lets us // distinguish devices. @Override public boolean dispatchKeyEvent(KeyEvent event) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 && !isXperiaPlay) { InputDeviceState state = getInputDeviceState(event); if (state == null) { return super.dispatchKeyEvent(event); From 989a4cbf3cb83822879dfe35048cd4d195d87a70 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Feb 2014 17:03:24 -0800 Subject: [PATCH 1046/1445] Avoid leaking depth/stencil renderbuffers. Only matters on devices without packed depth/stencil support, not sure how many such devices exist? --- gfx_es2/fbo.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 1a1ccafc59..909b5aab12 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -314,6 +314,8 @@ void fbo_destroy(FBO *fbo) { glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fbo->handle); glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); + glDeleteRenderbuffers(1, &fbo->z_buffer); + glDeleteRenderbuffers(1, &fbo->stencil_buffer); } else { #ifndef USING_GLES2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); From ae951a46faf9acd97da09e334bb038b5123520db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 3 Mar 2014 11:38:48 +0100 Subject: [PATCH 1047/1445] Add clamp_value function to math_util --- math/math_util.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/math/math_util.h b/math/math_util.h index 4704a51d23..e4a08058ba 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -71,6 +71,15 @@ inline double atan_fast(double x) { return (x / (1.0 + 0.28 * (x * x))); } +template +inline T clamp_value(T val, T floor, T cap) { + if (val > cap) + return cap; + else if (val < floor) + return floor; + else + return val; +} // linear -> dB conversion inline float lin2dB(float lin) { From 27bb0b01d39d733c25da390b6d756734c6d80c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 3 Mar 2014 11:39:06 +0100 Subject: [PATCH 1048/1445] Fix some focus issues, allow to set a DefaultFocusView on ViewGroups. --- ui/ui_screen.cpp | 3 +++ ui/view.cpp | 50 ++++-------------------------------------------- ui/viewgroup.cpp | 11 ++++++++++- ui/viewgroup.h | 6 +++++- 4 files changed, 22 insertions(+), 48 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 8a41ff7c65..7397c17af3 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -19,6 +19,9 @@ void UIScreen::DoRecreateViews() { delete root_; root_ = 0; CreateViews(); + if (root_ && root_->GetDefaultFocusView()) { + root_->GetDefaultFocusView()->SetFocus(); + } recreateViews_ = false; } } diff --git a/ui/view.cpp b/ui/view.cpp index b9f500909a..ab50b3bcc3 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -713,8 +713,10 @@ void SliderFloat::Touch(const TouchInput &input) { } void SliderFloat::Clamp() { - if (*value_ < minValue_) *value_ = minValue_; - else if (*value_ > maxValue_) *value_ = maxValue_; + if (*value_ < minValue_) + *value_ = minValue_; + else if (*value_ > maxValue_) + *value_ = maxValue_; } void SliderFloat::Draw(UIContext &dc) { @@ -738,48 +740,4 @@ void SliderFloat::GetContentDimensions(const UIContext &dc, float &w, float &h) h = 50; } - -/* -TabStrip::TabStrip() - : selected_(0) { -} - -void TabStrip::Touch(const TouchInput &touch) { - int tabw = bounds_.w / tabs_.size(); - int h = 20; - if (touch.flags & TOUCH_DOWN) { - for (int i = 0; i < MAX_POINTERS; i++) { - if (UIRegionHit(i, bounds_.x, bounds_.y, bounds_.w, h, 8)) { - selected_ = (touch.x - bounds_.x) / tabw; - } - } - if (selected_ < 0) selected_ = 0; - if (selected_ >= (int)tabs_.size()) selected_ = (int)tabs_.size() - 1; - } -} - -void TabStrip::Draw(DrawContext &dc) { - int tabw = bounds_.w / tabs_.size(); - int h = 20; - for (int i = 0; i < numTabs; i++) { - dc.draw->DrawImageStretch(WHITE, x + 1, y + 2, x + tabw - 1, y + h, 0xFF202020); - dc.draw->DrawText(font, tabs_[i].title.c_str(), x + tabw/2, y + h/2, 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_HCENTER); - if (selected_ == i) { - float tw, th; - ui_draw2d.MeasureText(font, names[i], &tw, &th); - // TODO: better image - ui_draw2d.DrawImageStretch(WHITE, x + 1, y + h - 6, x + tabw - 1, y + h, tabColors ? tabColors[i] : 0xFFFFFFFF); - } else { - ui_draw2d.DrawImageStretch(WHITE, x + 1, y + h - 1, x + tabw - 1, y + h, tabColors ? tabColors[i] : 0xFFFFFFFF); - } - x += tabw; - } -}*/ - -void Fill(UIContext &dc, const Bounds &bounds, const Drawable &drawable) { - if (drawable.type == DRAW_SOLID_COLOR) { - - } -} - } // namespace diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 43cbaeeb27..ce40347eca 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -213,15 +213,18 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio ILOG("Contain overlap"); return 0.0; } + float originSize = 0.0f; switch (direction) { case FOCUS_LEFT: overlap = vertOverlap; + originSize = origin->GetBounds().w; if (dirX > 0.0f) { wrongDirection = true; } break; case FOCUS_UP: overlap = horizOverlap; + originSize = origin->GetBounds().h; if (dirY > 0.0f) { wrongDirection = true; } @@ -229,12 +232,14 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio break; case FOCUS_RIGHT: overlap = vertOverlap; + originSize = origin->GetBounds().w; if (dirX < 0.0f) { wrongDirection = true; } break; case FOCUS_DOWN: overlap = horizOverlap; + originSize = origin->GetBounds().h; if (dirY < 0.0f) { wrongDirection = true; } @@ -261,10 +266,14 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio } } + // At large distances, ignore overlap. + if (distance > 2 * originSize) + overlap = 0; + if (wrongDirection) return 0.0f; else - return 1.0f / distance + overlap*10 + bonus; + return 1.0f / distance + overlap * 10 + bonus; } NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, NeighborResult result) { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 63e53cadd6..e5d98141f1 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -20,7 +20,7 @@ struct NeighborResult { class ViewGroup : public View { public: - ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams), hasDropShadow_(false), clip_(false) {} + ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams), defaultFocusView_(0), hasDropShadow_(false), clip_(false) {} virtual ~ViewGroup(); // Pass through external events to children. @@ -47,6 +47,9 @@ public: virtual bool SubviewFocused(View *view); virtual void RemoveSubview(View *view); + void SetDefaultFocusView(View *view) { defaultFocusView_ = view; } + View *GetDefaultFocusView() { return defaultFocusView_; } + // Assumes that layout has taken place. NeighborResult FindNeighbor(View *view, FocusDirection direction, NeighborResult best); @@ -68,6 +71,7 @@ public: protected: recursive_mutex modifyLock_; // Hold this when changing the subviews. std::vector views_; + View *defaultFocusView_; Drawable bg_; bool hasDropShadow_; bool clip_; From af35f06390b0c5203aeacc3d54a656198125899b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 3 Mar 2014 12:33:57 +0100 Subject: [PATCH 1049/1445] More focus behaviour tweaking. --- ui/view.cpp | 9 +++++++++ ui/view.h | 8 +------- ui/viewgroup.cpp | 8 ++++++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index ab50b3bcc3..a7c06afcdf 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -154,6 +154,15 @@ Point View::GetFocusPosition(FocusDirection dir) { } } +bool View::SetFocus() { + if (IsFocusMovementEnabled()) { + if (CanBeFocused()) { + SetFocusedView(this); + return true; + } + return false; + } +} void Clickable::Click() { UI::EventParams e; diff --git a/ui/view.h b/ui/view.h index 5859e37899..38ef9db698 100644 --- a/ui/view.h +++ b/ui/view.h @@ -328,13 +328,7 @@ public: virtual void ReplaceLayoutParams(LayoutParams *newLayoutParams) { layoutParams_.reset(newLayoutParams); } const Bounds &GetBounds() const { return bounds_; } - virtual bool SetFocus() { - if (CanBeFocused()) { - SetFocusedView(this); - return true; - } - return false; - } + virtual bool SetFocus(); virtual bool CanBeFocused() const { return true; } virtual bool SubviewFocused(View *view) { return false; } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index ce40347eca..e818f84b0b 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -431,7 +431,7 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v } weightZeroSum += spacing_ * (numVisible - 1); - + // Awright, got the sum. Let's take the remaining space after the fixed-size views, // and distribute among the weighted ones. if (orientation_ == ORIENT_HORIZONTAL) { @@ -1194,7 +1194,11 @@ void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { lock_guard lock(focusLock); EnableFocusMovement(true); if (!GetFocusedView()) { - root->SetFocus(); + if (root->GetDefaultFocusView()) { + root->GetDefaultFocusView()->SetFocus(); + } else { + root->SetFocus(); + } root->SubviewFocused(GetFocusedView()); } else { for (size_t i = 0; i < focusMoves.size(); i++) { From 3d906a1471b97a49fc8c61450d469a539d1d835a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 3 Mar 2014 12:55:29 +0100 Subject: [PATCH 1050/1445] Focus the contents of popup screens --- ui/ui_screen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 7397c17af3..64ce3d140a 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -163,6 +163,7 @@ void PopupScreen::CreateViews() { box_->Add(title); CreatePopupContents(box_); + root_->SetDefaultFocusView(box_); if (ShowButtons() && !button1_.empty()) { // And the two buttons at the bottom. From c65734c33a747d2573d90e3992bb5b20133d187d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 3 Mar 2014 16:10:14 +0100 Subject: [PATCH 1051/1445] Move a return statement to the correct position. --- ui/view.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index a7c06afcdf..73e30beaf2 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -106,7 +106,7 @@ void Event::Add(std::function func) { // Call this from input thread or whatever, it doesn't matter void Event::Trigger(EventParams &e) { - EventTriggered(this, e); + EventTriggered(this, e); } // Call this from UI thread @@ -160,8 +160,8 @@ bool View::SetFocus() { SetFocusedView(this); return true; } - return false; } + return false; } void Clickable::Click() { From 7274b8b01e749157cb4737a8fc3f02e3bbc63b25 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 8 Mar 2014 19:08:39 +0100 Subject: [PATCH 1052/1445] For extra safety, check the GLSL version when detecting ES 3.0. --- gfx_es2/gl_state.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 1e1d571621..648bf373e1 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -90,6 +90,7 @@ void CheckGLExtensions() { const char *renderer = (const char *)glGetString(GL_RENDERER); const char *versionStr = (const char *)glGetString(GL_VERSION); + const char *glslVersionStr = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); // Check vendor string to try and guess GPU const char *cvendor = (char *)glGetString(GL_VENDOR); @@ -153,8 +154,9 @@ void CheckGLExtensions() { #if defined(MAY_HAVE_GLES3) // Try to load GLES 3.0 only if "3.0" found in version // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited - // number of times. - if (strstr(versionStr, "3.0") && GL_TRUE == gl3stubInit()) { + // number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584. + // Really, we should do something much better. + if (strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0") && gl3stubInit()) { gl_extensions.ver[0] = 3; gl_extensions.GLES3 = true; ILOG("Full OpenGL ES 3.0 support detected!\n"); From 377a104e68b56a2cc6adf2ae6f3f7360a3ef0761 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 9 Mar 2014 15:42:23 +0100 Subject: [PATCH 1053/1445] JSON: Rename single-parameter getString to getStringOrDie to emphasize the danger. --- ext/vjson/json.cpp | 7 ++++++- ext/vjson/json.h | 16 +++------------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/ext/vjson/json.cpp b/ext/vjson/json.cpp index 6015b7c76e..bdd7bb1db4 100644 --- a/ext/vjson/json.cpp +++ b/ext/vjson/json.cpp @@ -33,6 +33,11 @@ int json_value::numSiblings() const { const json_value *json_value::get(const char *child_name) const { if (!this) { FLOG("Cannot get from null node"); + return 0; + } + if (!child_name) { + FLOG("JSON: Cannot get from null child name"); + return 0; } const json_value *c = first_child; while (c) { @@ -52,7 +57,7 @@ const json_value *json_value::get(const char *child_name, json_type type) const return 0; } -const char *json_value::getString(const char *child_name) const { +const char *json_value::getStringOrDie(const char *child_name) const { const json_value *val = get(child_name, JSON_STRING); if (val) return val->string_value; diff --git a/ext/vjson/json.h b/ext/vjson/json.h index 997f46b9aa..792ab1cba4 100644 --- a/ext/vjson/json.h +++ b/ext/vjson/json.h @@ -7,8 +7,7 @@ #include "block_allocator.h" #include "file/vfs.h" -enum json_type -{ +enum json_type { JSON_NULL, JSON_OBJECT, JSON_ARRAY, @@ -18,8 +17,7 @@ enum json_type JSON_BOOL, }; -struct json_value -{ +struct json_value { json_value() {} json_value *parent; @@ -47,7 +45,7 @@ struct json_value const json_value *getDict(const char *child_name) const { return get(child_name, JSON_OBJECT); } - const char *getString(const char *child_name) const; + const char *getStringOrDie(const char *child_name) const; const char *getString(const char *child_name, const char *default_value) const; bool getStringVector(std::vector *vec) const; float getFloat(const char *child_name) const; @@ -69,7 +67,6 @@ private: json_value *json_parse(char *source, char **error_pos, char **error_desc, int *error_line, block_allocator *allocator); void json_print(json_value *value, int ident = 0); - // Easy-wrapper class JsonReader { public: @@ -114,10 +111,3 @@ private: DISALLOW_COPY_AND_ASSIGN(JsonReader); }; - -// TODO: Make this a push/pop interface similar to JsonWriter. Maybe -// we can get to the point where reading and writing is near identical or the same code. -class JsonCursor { -public: - -}; From 5152308c79094f93d43d321b7744949ed12c699c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 27 Feb 2014 01:22:47 +0700 Subject: [PATCH 1054/1445] Add basic thick-line drawing code --- gfx_es2/draw_buffer.cpp | 25 +++++++++++++++++++++++++ gfx_es2/draw_buffer.h | 4 +++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 400cea35e2..bb296760fa 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -195,6 +195,31 @@ void DrawBuffer::Rect(float x, float y, float w, float h, V(x, y + h, 0, color, u, v + uh); } +void DrawBuffer::Line(int atlas_image, float x1, float y1, float x2, float y2, float thickness, uint32 color) { + const AtlasImage &image = atlas->images[atlas_image]; + + // No caps yet! + // Pre-rotated - we are making a thick line here + float dx = -(y2 - y1); + float dy = x2 - x1; + float len = sqrtf(dx * dx + dy * dy) / thickness; + if (len <= 0.0f) + len = 1.0f; + + dx /= len; + dy /= len; + + float x[4] = { x1 - dx, x2 - dx, x1 + dx, x2 + dx }; + float y[4] = { y1 - dy, y2 - dy, y1 + dy, y2 + dy }; + + V(x[0], y[0], color, image.u1, image.v1); + V(x[1], y[1], color, image.u2, image.v1); + V(x[2], y[2], color, image.u1, image.v2); + V(x[2], y[2], color, image.u1, image.v2); + V(x[1], y[1], color, image.u2, image.v1); + V(x[3], y[3], color, image.u2, image.v2); +} + void DrawBuffer::MeasureImage(ImageID atlas_image, float *w, float *h) { const AtlasImage &image = atlas->images[atlas_image]; *w = (float)image.w; diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 65d09870ce..409b18c83d 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -76,8 +76,10 @@ public: void vLine(float x, float y1, float y2, uint32 color); void vLineAlpha50(float x, float y1, float y2, uint32 color); + void Line(int atlas_image, float x1, float y1, float x2, float y2, float thickness, uint32 color); + void RectOutline(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); - + void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom); void RectVDarkFaded(float x, float y, float w, float h, uint32 colorTop) { RectVGradient(x, y, w, h, colorTop, darkenColor(colorTop)); From d2029ed29a6f5e362e27b3b61f303c0481420034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 10 Mar 2014 23:13:26 +0100 Subject: [PATCH 1055/1445] Minor tweak to drag behaviour of scrollviews --- ui/viewgroup.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index e818f84b0b..104ecc2a8e 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -658,15 +658,16 @@ void ScrollView::Touch(const TouchInput &input) { } if (input.flags & TOUCH_UP) { float info[4]; - if (!IsDragCaptured(input.id) && gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info)) + if (!IsDragCaptured(input.id) && gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info)) { inertia_ = info[1]; + } } TouchInput input2; if (CanScroll() && !IsDragCaptured(input.id)) { input2 = gesture_.Update(input, bounds_); float info[4]; - if (gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info)) { + if (gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info) && !(input.flags & TOUCH_DOWN)) { float pos = scrollStart_ - info[0]; ClampScrollPos(pos); scrollPos_ = pos; @@ -675,6 +676,8 @@ void ScrollView::Touch(const TouchInput &input) { } } else { input2 = input; + scrollTarget_ = scrollPos_; + scrollToTarget_ = false; } if (!(input.flags & TOUCH_DOWN) || bounds_.Contains(input.x, input.y)) { @@ -753,7 +756,7 @@ void ScrollView::ClampScrollPos(float &pos) { pos = 0.0f; return; } - // Clamp scrollTarget. + float childHeight = views_[0]->GetBounds().h; float scrollMax = std::max(0.0f, childHeight - bounds_.h); From 2ad2bd8491361bbfa024a0885f7c5322979ced1f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 12 Mar 2014 19:49:03 +0100 Subject: [PATCH 1056/1445] Add flag to enable getFilesInDir to get hidden files (dotfiles). --- file/file_util.cpp | 4 ++-- file/file_util.h | 6 +++++- native.vcxproj | 9 ++++++++- native.vcxproj.filters | 8 +++++++- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index 705884d800..d0d8a212e3 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -234,7 +234,7 @@ bool FileInfo::operator <(const FileInfo &other) const { return false; } -size_t getFilesInDir(const char *directory, std::vector *files, const char *filter) { +size_t getFilesInDir(const char *directory, std::vector *files, const char *filter, int flags) { size_t foundEntries = 0; std::set filters; std::string tmp; @@ -292,7 +292,7 @@ size_t getFilesInDir(const char *directory, std::vector *files, const continue; // Remove dotfiles (should be made optional?) - if (virtualName[0] == '.') + if (!(flags & GETFILES_GETHIDDEN) && virtualName[0] == '.') continue; FileInfo info; diff --git a/file/file_util.h b/file/file_util.h index 34ee8e61ba..ff3290e5c5 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -27,7 +27,11 @@ std::string getFileExtension(const std::string &fn); std::string getDir(const std::string &path); std::string getFilename(std::string path); bool getFileInfo(const char *path, FileInfo *fileInfo); -size_t getFilesInDir(const char *directory, std::vector *files, const char *filter = 0); + +enum { + GETFILES_GETHIDDEN = 1 +}; +size_t getFilesInDir(const char *directory, std::vector *files, const char *filter = 0, int flags = 0); void deleteFile(const char *file); void deleteDir(const char *file); bool exists(const std::string &filename); diff --git a/native.vcxproj b/native.vcxproj index 8b8276ab32..5b8cb28793 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -242,6 +242,7 @@ + @@ -717,6 +718,12 @@ + + true + true + true + true + @@ -763,4 +770,4 @@ - + \ No newline at end of file diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 4456492c57..eef91701ff 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -326,6 +326,9 @@ ext\vjson + + gfx + @@ -772,6 +775,9 @@ ext\vjson + + gfx + @@ -850,4 +856,4 @@ {c6910d82-73d3-4d97-ac9c-bcc03265b1bc} - + \ No newline at end of file From 7c2ff2557d9d741c6d1049245089b72c9a4ea097 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Mar 2014 16:15:33 +0100 Subject: [PATCH 1057/1445] UI: Improve scoring function for directional keyboard nav --- ui/viewgroup.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 104ecc2a8e..efcb94c4f3 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -253,16 +253,16 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio // Add a small bonus if the views are the same size. This prioritizes moving to the next item // upwards in a scroll view instead of moving up to the top bar. - float bonus = 0.0f; + float distanceBonus = 0.0f; if (vertical) { float widthDifference = origin->GetBounds().w - destination->GetBounds().w; if (widthDifference == 0) { - bonus = 1; + distanceBonus = 40; } } else { float heightDifference = origin->GetBounds().h - destination->GetBounds().h; if (heightDifference == 0) { - bonus = 1; + distanceBonus = 40; } } @@ -273,7 +273,7 @@ float GetDirectionScore(View *origin, View *destination, FocusDirection directio if (wrongDirection) return 0.0f; else - return 1.0f / distance + overlap * 10 + bonus; + return 10.0f / std::max(1.0f, distance - distanceBonus) + overlap; } NeighborResult ViewGroup::FindNeighbor(View *view, FocusDirection direction, NeighborResult result) { From 6b8a8a6c8d5277b295d5f0d53e5b218cb987a296 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 19 Mar 2014 18:03:33 +0100 Subject: [PATCH 1058/1445] Restore immersive mode after volume change (android bug workaround) --- .../libnative/NativeActivity.java | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 3c7ec7cf72..eee41a517a 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -30,6 +30,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.os.Handler; import android.os.Vibrator; import android.text.InputType; import android.util.DisplayMetrics; @@ -42,6 +43,7 @@ import android.view.KeyEvent; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; +import android.view.View.OnSystemUiVisibilityChangeListener; import android.view.Window; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; @@ -304,10 +306,10 @@ public class NativeActivity extends Activity { flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; Log.i(TAG, "Setting immersive mode"); } - if (mGLSurfaceView != null) { - mGLSurfaceView.setSystemUiVisibility(flags); + if (getWindow().getDecorView() != null) { + getWindow().getDecorView().setSystemUiVisibility(flags); } else { - Log.e(TAG, "updateSystemUiVisibility: GLSurfaceView not yet created, ignoring"); + Log.e(TAG, "updateSystemUiVisibility: decor view not yet created, ignoring"); } } @@ -371,13 +373,28 @@ public class NativeActivity extends Activity { nativeRenderer = new NativeRenderer(this); mGLSurfaceView.setRenderer(nativeRenderer); - setContentView(mGLSurfaceView); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - updateSystemUiVisibility(); - } + setContentView(mGLSurfaceView); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + updateSystemUiVisibility(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + setupSystemUiCallback(); + } + } } + @TargetApi(19) + void setupSystemUiCallback() { + getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int visibility) { + if (visibility == 0) { + updateSystemUiVisibility(); + } + } + }); + } + @Override protected void onStop() { super.onStop(); From 9a49f564cecb83bd96c004bda452061e6e34189f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 22 Mar 2014 00:31:10 +0100 Subject: [PATCH 1059/1445] fast_math: SIMD function library that can select to use NEON at runtime. Only contains one function so far: fast_matrix_mul_4x4. C, SSE, and NEON impls. --- Android.mk | 5 ++++ math/fast/fast_math.c | 10 ++++++++ math/fast/fast_math.h | 21 ++++++++++++++++ math/fast/fast_matrix.c | 45 +++++++++++++++++++++++++++++++++ math/fast/fast_matrix.h | 25 +++++++++++++++++++ math/fast/fast_matrix_neon.S | 48 ++++++++++++++++++++++++++++++++++++ math/fast/fast_matrix_sse.c | 18 ++++++++++++++ math/lin/matrix4x4.cpp | 25 ++----------------- math/lin/matrix4x4.h | 13 +++++++--- native.vcxproj | 8 +++++- native.vcxproj.filters | 21 ++++++++++++++++ 11 files changed, 211 insertions(+), 28 deletions(-) create mode 100644 math/fast/fast_math.c create mode 100644 math/fast/fast_math.h create mode 100644 math/fast/fast_matrix.c create mode 100644 math/fast/fast_matrix.h create mode 100644 math/fast/fast_matrix_neon.S create mode 100644 math/fast/fast_matrix_sse.c diff --git a/Android.mk b/Android.mk index f036619c9e..2e74a01a2f 100644 --- a/Android.mk +++ b/Android.mk @@ -54,6 +54,8 @@ LOCAL_SRC_FILES :=\ i18n/i18n.cpp \ input/gesture_detector.cpp \ input/input_state.cpp \ + math/fast/fast_math.c \ + math/fast/fast_matrix.c \ math/math_util.cpp \ math/curves.cpp \ math/expression_parser.cpp \ @@ -107,6 +109,9 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext $(LOCAL_PATH)/ext/libzip #by ($(target_arch_ABI),arquitecture (armeabi-v7a , armeabi , x86 , MIPS) ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI_V7A -DARMV7 +LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ + math/fast/fast_matrix_neon.S.neon + else ifeq ($(TARGET_ARCH_ABI),armeabi) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI -march=armv6 else ifeq ($(TARGET_ARCH_ABI),x86) diff --git a/math/fast/fast_math.c b/math/fast/fast_math.c new file mode 100644 index 0000000000..d9ff9eae88 --- /dev/null +++ b/math/fast/fast_math.c @@ -0,0 +1,10 @@ +#include "fast_math.h" +#include "fast_matrix.h" + +void InitFastMath(int enableNEON) { +#if !defined(_M_IX86) && !defined(_M_X64) + if (enableNEON) { + fast_matrix_mul_4x4 = &fast_matrix_mul_4x4_neon; + } +#endif +} \ No newline at end of file diff --git a/math/fast/fast_math.h b/math/fast/fast_math.h new file mode 100644 index 0000000000..905c7e84f7 --- /dev/null +++ b/math/fast/fast_math.h @@ -0,0 +1,21 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +// Fast Math +// A mini library of math kernels. These should be large enough to be worth calling +// as functions, and generic enough to fit in the "native" library (not PSP specific stuff). + +// NEON versions are dynamically selected at runtime, when you call InitFastMath. + +// SSE versions are hard linked at compile time. + +// See fast_matrix.h for the first set of functions. + +void InitFastMath(int enableNEON); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/math/fast/fast_matrix.c b/math/fast/fast_matrix.c new file mode 100644 index 0000000000..b62404d75a --- /dev/null +++ b/math/fast/fast_matrix.c @@ -0,0 +1,45 @@ +#include "fast_math.h" +#include "fast_matrix.h" + +#define xx 0 +#define xy 1 +#define xz 2 +#define xw 3 +#define yx 4 +#define yy 5 +#define yz 6 +#define yw 7 +#define zx 8 +#define zy 9 +#define zz 10 +#define zw 11 +#define wx 12 +#define wy 13 +#define wz 14 +#define ww 15 + +void fast_matrix_mul_4x4_c(float *dest, const float *a, const float *b) { + dest[xx] = b[xx] * a[xx] + b[xy] * a[yx] + b[xz] * a[zx] + b[xw] * a[wx]; + dest[xy] = b[xx] * a[xy] + b[xy] * a[yy] + b[xz] * a[zy] + b[xw] * a[wy]; + dest[xz] = b[xx] * a[xz] + b[xy] * a[yz] + b[xz] * a[zz] + b[xw] * a[wz]; + dest[xw] = b[xx] * a[xw] + b[xy] * a[yw] + b[xz] * a[zw] + b[xw] * a[ww]; + + dest[yx] = b[yx] * a[xx] + b[yy] * a[yx] + b[yz] * a[zx] + b[yw] * a[wx]; + dest[yy] = b[yx] * a[xy] + b[yy] * a[yy] + b[yz] * a[zy] + b[yw] * a[wy]; + dest[yz] = b[yx] * a[xz] + b[yy] * a[yz] + b[yz] * a[zz] + b[yw] * a[wz]; + dest[yw] = b[yx] * a[xw] + b[yy] * a[yw] + b[yz] * a[zw] + b[yw] * a[ww]; + + dest[zx] = b[zx] * a[xx] + b[zy] * a[yx] + b[zz] * a[zx] + b[zw] * a[wx]; + dest[zy] = b[zx] * a[xy] + b[zy] * a[yy] + b[zz] * a[zy] + b[zw] * a[wy]; + dest[zz] = b[zx] * a[xz] + b[zy] * a[yz] + b[zz] * a[zz] + b[zw] * a[wz]; + dest[zw] = b[zx] * a[xw] + b[zy] * a[yw] + b[zz] * a[zw] + b[zw] * a[ww]; + + dest[wx] = b[wx] * a[xx] + b[wy] * a[yx] + b[wz] * a[zx] + b[ww] * a[wx]; + dest[wy] = b[wx] * a[xy] + b[wy] * a[yy] + b[wz] * a[zy] + b[ww] * a[wy]; + dest[wz] = b[wx] * a[xz] + b[wy] * a[yz] + b[wz] * a[zz] + b[ww] * a[wz]; + dest[ww] = b[wx] * a[xw] + b[wy] * a[yw] + b[wz] * a[zw] + b[ww] * a[ww]; +} + +#ifndef fast_matrix_mul_4x4 +fptr_fast_matrix_mul_4x4 fast_matrix_mul_4x4 = &fast_matrix_mul_4x4_c; +#endif \ No newline at end of file diff --git a/math/fast/fast_matrix.h b/math/fast/fast_matrix.h new file mode 100644 index 0000000000..52913f2747 --- /dev/null +++ b/math/fast/fast_matrix.h @@ -0,0 +1,25 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +// A mini library of matrix math kernels. + +// TODO: Really need to wrap this block in a macro or something, will get repetitive. + +typedef void(*fptr_fast_matrix_mul_4x4)(float *dest, const float *a, const float *b); +extern void fast_matrix_mul_4x4_c(float *dest, const float *a, const float *b); +extern void fast_matrix_mul_4x4_neon(float *dest, const float *a, const float *b); +extern void fast_matrix_mul_4x4_sse(float *dest, const float *a, const float *b); + +#if defined(_M_IX86) || defined(_M_X64) // Hard link to SSE implementations on x86 +#define fast_matrix_mul_4x4 fast_matrix_mul_4x4_sse +#else +extern fptr_fast_matrix_mul_4x4 fast_matrix_mul_4x4; +#endif + + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/math/fast/fast_matrix_neon.S b/math/fast/fast_matrix_neon.S new file mode 100644 index 0000000000..fbf9199315 --- /dev/null +++ b/math/fast/fast_matrix_neon.S @@ -0,0 +1,48 @@ + .syntax unified // Allow both ARM and Thumb-2 instructions + .text + .align 2 // Align the function code to a 4-byte (2^n) word boundary. + .arm // Use ARM instructions instead of Thumb. + +@ From ARM samples +@ +@ matrix_mul_float: +@ Calculate 4x4 (matrix 0) * (matrix 1) and store to result 4x4 matrix. +@ matrix 0, matrix 1 and result pointers can be the same, +@ ie. my_matrix = my_matrix * my_matrix is possible. +@ +@ r0 = pointer to 4x4 result matrix, single precision floats, column major order +@ r1 = pointer to 4x4 matrix 0, single precision floats, column major order +@ r2 = pointer to 4x4 matrix 1, single precision floats, column major order +@ + + .globl fast_matrix_mul_4x4_neon +fast_matrix_mul_4x4_neon: + vld1.32 {d16-d19}, [r1]! @ load first eight elements of matrix 0 + vld1.32 {d20-d23}, [r1]! @ load second eight elements of matrix 0 + vld1.32 {d0-d3}, [r2]! @ load first eight elements of matrix 1 + vld1.32 {d4-d7}, [r2]! @ load second eight elements of matrix 1 + + vmul.f32 q12, q8, d0[0] @ rslt col0 = (mat0 col0) * (mat1 col0 elt0) + vmul.f32 q13, q8, d2[0] @ rslt col1 = (mat0 col0) * (mat1 col1 elt0) + vmul.f32 q14, q8, d4[0] @ rslt col2 = (mat0 col0) * (mat1 col2 elt0) + vmul.f32 q15, q8, d6[0] @ rslt col3 = (mat0 col0) * (mat1 col3 elt0) + + vmla.f32 q12, q9, d0[1] @ rslt col0 += (mat0 col1) * (mat1 col0 elt1) + vmla.f32 q13, q9, d2[1] @ rslt col1 += (mat0 col1) * (mat1 col1 elt1) + vmla.f32 q14, q9, d4[1] @ rslt col2 += (mat0 col1) * (mat1 col2 elt1) + vmla.f32 q15, q9, d6[1] @ rslt col3 += (mat0 col1) * (mat1 col3 elt1) + + vmla.f32 q12, q10, d1[0] @ rslt col0 += (mat0 col2) * (mat1 col0 elt2) + vmla.f32 q13, q10, d3[0] @ rslt col1 += (mat0 col2) * (mat1 col1 elt2) + vmla.f32 q14, q10, d5[0] @ rslt col2 += (mat0 col2) * (mat1 col2 elt2) + vmla.f32 q15, q10, d7[0] @ rslt col3 += (mat0 col2) * (mat1 col2 elt2) + + vmla.f32 q12, q11, d1[1] @ rslt col0 += (mat0 col3) * (mat1 col0 elt3) + vmla.f32 q13, q11, d3[1] @ rslt col1 += (mat0 col3) * (mat1 col1 elt3) + vmla.f32 q14, q11, d5[1] @ rslt col2 += (mat0 col3) * (mat1 col2 elt3) + vmla.f32 q15, q11, d7[1] @ rslt col3 += (mat0 col3) * (mat1 col3 elt3) + + vst1.32 {d24-d27}, [r0]! @ store first eight elements of result + vst1.32 {d28-d31}, [r0]! @ store second eight elements of result + bx lr + diff --git a/math/fast/fast_matrix_sse.c b/math/fast/fast_matrix_sse.c new file mode 100644 index 0000000000..75593feecb --- /dev/null +++ b/math/fast/fast_matrix_sse.c @@ -0,0 +1,18 @@ +#include + +#include "fast_matrix.h" + +void fast_matrix_mul_4x4_sse(float *dest, const float *a, const float *b) { + for (int i = 0; i < 16; i += 4) { + __m128 a_col_1 = _mm_load_ps(a); + __m128 a_col_2 = _mm_load_ps(&a[4]); + __m128 a_col_3 = _mm_load_ps(&a[8]); + __m128 a_col_4 = _mm_load_ps(&a[12]); + + __m128 r_col = _mm_mul_ps(a_col_1, _mm_set1_ps(b[i])); + r_col = _mm_add_ps(r_col, _mm_mul_ps(a_col_2, _mm_set1_ps(b[i + 1]))); + r_col = _mm_add_ps(r_col, _mm_mul_ps(a_col_3, _mm_set1_ps(b[i + 2]))); + r_col = _mm_add_ps(r_col, _mm_mul_ps(a_col_4, _mm_set1_ps(b[i + 3]))); + _mm_store_ps(&dest[i], r_col); + } +} diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp index 1dcab71f90..7234c4fb93 100644 --- a/math/lin/matrix4x4.cpp +++ b/math/lin/matrix4x4.cpp @@ -4,6 +4,7 @@ #include "math/lin/vec3.h" #include "math/lin/quat.h" +#include "math/fast/fast_matrix.h" #ifdef _WIN32 #undef far @@ -13,28 +14,6 @@ // See http://code.google.com/p/oolongengine/source/browse/trunk/Oolong+Engine2/Math/neonmath/neon_matrix_impl.cpp?spec=svn143&r=143 when we need speed // no wait. http://code.google.com/p/math-neon/ -void matrix_mul_4x4(Matrix4x4 &res, const Matrix4x4 &inA, const Matrix4x4 &inB) { - res.xx = inA.xx*inB.xx + inA.xy*inB.yx + inA.xz*inB.zx + inA.xw*inB.wx; - res.xy = inA.xx*inB.xy + inA.xy*inB.yy + inA.xz*inB.zy + inA.xw*inB.wy; - res.xz = inA.xx*inB.xz + inA.xy*inB.yz + inA.xz*inB.zz + inA.xw*inB.wz; - res.xw = inA.xx*inB.xw + inA.xy*inB.yw + inA.xz*inB.zw + inA.xw*inB.ww; - - res.yx = inA.yx*inB.xx + inA.yy*inB.yx + inA.yz*inB.zx + inA.yw*inB.wx; - res.yy = inA.yx*inB.xy + inA.yy*inB.yy + inA.yz*inB.zy + inA.yw*inB.wy; - res.yz = inA.yx*inB.xz + inA.yy*inB.yz + inA.yz*inB.zz + inA.yw*inB.wz; - res.yw = inA.yx*inB.xw + inA.yy*inB.yw + inA.yz*inB.zw + inA.yw*inB.ww; - - res.zx = inA.zx*inB.xx + inA.zy*inB.yx + inA.zz*inB.zx + inA.zw*inB.wx; - res.zy = inA.zx*inB.xy + inA.zy*inB.yy + inA.zz*inB.zy + inA.zw*inB.wy; - res.zz = inA.zx*inB.xz + inA.zy*inB.yz + inA.zz*inB.zz + inA.zw*inB.wz; - res.zw = inA.zx*inB.xw + inA.zy*inB.yw + inA.zz*inB.zw + inA.zw*inB.ww; - - res.wx = inA.wx*inB.xx + inA.wy*inB.yx + inA.wz*inB.zx + inA.ww*inB.wx; - res.wy = inA.wx*inB.xy + inA.wy*inB.yy + inA.wz*inB.zy + inA.ww*inB.wy; - res.wz = inA.wx*inB.xz + inA.wy*inB.yz + inA.wz*inB.zz + inA.ww*inB.wz; - res.ww = inA.wx*inB.xw + inA.wy*inB.yw + inA.wz*inB.zw + inA.ww*inB.ww; -} - Matrix4x4 Matrix4x4::simpleInverse() const { Matrix4x4 out; out.xx = xx; @@ -73,7 +52,7 @@ Matrix4x4 Matrix4x4::transpose() const Matrix4x4 Matrix4x4::operator * (const Matrix4x4 &other) const { Matrix4x4 temp; - matrix_mul_4x4(temp, *this, other); + fast_matrix_mul_4x4(temp.m, this->m, other.m); return temp; } diff --git a/math/lin/matrix4x4.h b/math/lin/matrix4x4.h index 32c69db1ca..ca1345015a 100644 --- a/math/lin/matrix4x4.h +++ b/math/lin/matrix4x4.h @@ -7,10 +7,15 @@ class Quaternion; class Matrix4x4 { public: - float xx, xy, xz, xw; - float yx, yy, yz, yw; - float zx, zy, zz, zw; - float wx, wy, wz, ww; + union { + struct { + float xx, xy, xz, xw; + float yx, yy, yz, yw; + float zx, zy, zz, zw; + float wx, wy, wz, ww; + }; + float m[16]; + }; const Vec3 right() const {return Vec3(xx, xy, xz);} const Vec3 up() const {return Vec3(yx, yy, yz);} diff --git a/native.vcxproj b/native.vcxproj index 5b8cb28793..cdc424ad84 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -180,6 +180,7 @@ + @@ -264,6 +265,8 @@ + + @@ -743,6 +746,9 @@ + + + @@ -770,4 +776,4 @@ - \ No newline at end of file + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index eef91701ff..e9e15c5b0b 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -22,6 +22,9 @@ ext\libzip + + math\fast + @@ -329,6 +332,12 @@ gfx + + math\fast + + + math\fast + @@ -778,6 +787,15 @@ gfx + + math\fast + + + math\fast + + + math\fast + @@ -855,5 +873,8 @@ {c6910d82-73d3-4d97-ac9c-bcc03265b1bc} + + {5ce64c0e-98e4-4411-86cc-aacaf2f60b21} + \ No newline at end of file From 811bc13beb44a9caf143a5db1737123e83d1f28d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 22 Mar 2014 09:41:25 +0100 Subject: [PATCH 1060/1445] Have fast_matrix_mul_4x4_sse accept unaligned matrices --- math/fast/fast_matrix_sse.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/math/fast/fast_matrix_sse.c b/math/fast/fast_matrix_sse.c index 75593feecb..a525ba8dce 100644 --- a/math/fast/fast_matrix_sse.c +++ b/math/fast/fast_matrix_sse.c @@ -4,15 +4,15 @@ void fast_matrix_mul_4x4_sse(float *dest, const float *a, const float *b) { for (int i = 0; i < 16; i += 4) { - __m128 a_col_1 = _mm_load_ps(a); - __m128 a_col_2 = _mm_load_ps(&a[4]); - __m128 a_col_3 = _mm_load_ps(&a[8]); - __m128 a_col_4 = _mm_load_ps(&a[12]); + __m128 a_col_1 = _mm_loadu_ps(a); + __m128 a_col_2 = _mm_loadu_ps(&a[4]); + __m128 a_col_3 = _mm_loadu_ps(&a[8]); + __m128 a_col_4 = _mm_loadu_ps(&a[12]); __m128 r_col = _mm_mul_ps(a_col_1, _mm_set1_ps(b[i])); r_col = _mm_add_ps(r_col, _mm_mul_ps(a_col_2, _mm_set1_ps(b[i + 1]))); r_col = _mm_add_ps(r_col, _mm_mul_ps(a_col_3, _mm_set1_ps(b[i + 2]))); r_col = _mm_add_ps(r_col, _mm_mul_ps(a_col_4, _mm_set1_ps(b[i + 3]))); - _mm_store_ps(&dest[i], r_col); + _mm_storeu_ps(&dest[i], r_col); } } From 8c33c6aa099aa90fffe72932983701f71fa4f74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 22 Mar 2014 15:17:14 +0100 Subject: [PATCH 1061/1445] Fix build for x86 android etc. --- Android.mk | 2 ++ math/fast/fast_math.c | 4 ++-- math/fast/fast_matrix_sse.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Android.mk b/Android.mk index 2e74a01a2f..67334859ee 100644 --- a/Android.mk +++ b/Android.mk @@ -116,6 +116,8 @@ else ifeq ($(TARGET_ARCH_ABI),armeabi) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI -march=armv6 else ifeq ($(TARGET_ARCH_ABI),x86) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -D_M_IX86 +LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ + math/fast/fast_matrix_sse.c endif include $(BUILD_STATIC_LIBRARY) diff --git a/math/fast/fast_math.c b/math/fast/fast_math.c index d9ff9eae88..018c67436a 100644 --- a/math/fast/fast_math.c +++ b/math/fast/fast_math.c @@ -2,9 +2,9 @@ #include "fast_matrix.h" void InitFastMath(int enableNEON) { -#if !defined(_M_IX86) && !defined(_M_X64) +#if !defined(_M_IX86) && !defined(_M_X64) && defined(ARMEABI_V7A) if (enableNEON) { fast_matrix_mul_4x4 = &fast_matrix_mul_4x4_neon; } #endif -} \ No newline at end of file +} diff --git a/math/fast/fast_matrix_sse.c b/math/fast/fast_matrix_sse.c index a525ba8dce..2bc945e4a9 100644 --- a/math/fast/fast_matrix_sse.c +++ b/math/fast/fast_matrix_sse.c @@ -3,7 +3,8 @@ #include "fast_matrix.h" void fast_matrix_mul_4x4_sse(float *dest, const float *a, const float *b) { - for (int i = 0; i < 16; i += 4) { + int i; + for (i = 0; i < 16; i += 4) { __m128 a_col_1 = _mm_loadu_ps(a); __m128 a_col_2 = _mm_loadu_ps(&a[4]); __m128 a_col_3 = _mm_loadu_ps(&a[8]); From 30b5e2879eb6c1fe9623c9275a995f3daa24b263 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 23 Mar 2014 10:04:25 +0100 Subject: [PATCH 1062/1445] Add function to set both FZ and DefaultNaN on ARM. --- math/math_util.cpp | 22 ++++++++++++++++++---- math/math_util.h | 41 ++++++++++++++++++++--------------------- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/math/math_util.cpp b/math/math_util.cpp index 29f7fea983..1ae1cbfc13 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -3,8 +3,7 @@ #if defined(__ARM_ARCH_7A__) && !defined(BLACKBERRY) -void EnableFZ() -{ +void EnableFZ() { int x; asm( "fmrx %[result],FPSCR \r\n" @@ -14,9 +13,24 @@ void EnableFZ() ); //printf("ARM FPSCR: %08x\n",x); } + +void FPU_SetFastMode() { + int x; + asm( + "fmrx %[result],FPSCR \r\n" + "orr %[result],%[result],#50331648 \r\n" // 3 << 24 + "fmxr FPSCR,%[result]" + :[result] "=r" (x) : : + ); + //printf("ARM FPSCR: %08x\n",x); +} + #else -void EnableFZ() -{ + +void EnableFZ() { // TODO } + +void FPU_SetFastMode() {} + #endif diff --git a/math/math_util.h b/math/math_util.h index e4a08058ba..c0ddd86088 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -93,31 +93,31 @@ inline float dB2lin(float dB) { return expf(dB * DB_2_LOG); } +union FP32 { + uint32_t u; + float f; +}; + +struct FP16 { + uint16_t u; +}; + inline bool my_isinf(float f) { - union { - float f; - uint32_t u; - } f2u; + FP32 f2u; f2u.f = f; return f2u.u == 0x7f800000 || f2u.u == 0xff800000; } inline bool my_isnan(float f) { - union { - float f; - uint32_t u; - } f2u; + FP32 f2u; f2u.f = f; // NaNs have non-zero mantissa return ((f2u.u & 0x7F800000) == 0x7F800000) && (f2u.u & 0x7FFFFF); } inline bool my_isnanorinf(float f) { - union { - float f; - uint32_t u; - } f2u; + FP32 f2u; f2u.f = f; // NaNs have non-zero mantissa, infs have zero mantissa. That is, we just ignore the mantissa here. return ((f2u.u & 0x7F800000) == 0x7F800000); @@ -142,15 +142,6 @@ inline double round_ieee_754(double d) { return i + 1.0f; } -union FP32 { - uint32_t u; - float f; -}; - -struct FP16 { - uint16_t u; -}; - // magic code from ryg: http://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/ // See also SSE2 version: https://gist.github.com/rygorous/2144712 inline FP32 half_to_float_fast5(FP16 h) @@ -211,3 +202,11 @@ inline uint16_t ShrinkToHalf(float full) { // FPU control. void EnableFZ(); + +// Enable both FZ and Default-NaN. Is documented to flip some ARM implementation into a "run-fast" mode +// where they can schedule VFP instructions on the NEON unit (these implementations have +// very slow VFP units). +// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0274h/Babffifj.html +void FPU_SetFastMode(); + + From 3139ac497f434f9daebb3db8b4cb062d6a739296 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 24 Mar 2014 16:47:21 +0100 Subject: [PATCH 1063/1445] Improve ARM fastmode setting, probably correct now. --- math/math_util.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/math/math_util.cpp b/math/math_util.cpp index 1ae1cbfc13..4c3e0f0f02 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -14,15 +14,22 @@ void EnableFZ() { //printf("ARM FPSCR: %08x\n",x); } +// New fastmode code from: http://pandorawiki.org/Floating_Point_Optimization +// These settings turbocharge the slow VFP unit on Cortex-A8 based chips by setting +// restrictions that permit running VFP instructions on the NEON unit. +// Denormal flush-to-zero, for example. void FPU_SetFastMode() { - int x; - asm( - "fmrx %[result],FPSCR \r\n" - "orr %[result],%[result],#50331648 \r\n" // 3 << 24 - "fmxr FPSCR,%[result]" - :[result] "=r" (x) : : + static const unsigned int x = 0x04086060; + static const unsigned int y = 0x03000000; + int r; + asm volatile ( + "fmrx %0, fpscr \n\t" //r0 = FPSCR + "and %0, %0, %1 \n\t" //r0 = r0 & 0x04086060 + "orr %0, %0, %2 \n\t" //r0 = r0 | 0x03000000 + "fmxr fpscr, %0 \n\t" //FPSCR = r0 + : "=r"(r) + : "r"(x), "r"(y) ); - //printf("ARM FPSCR: %08x\n",x); } #else From 060e479b934e701aca0cdbe73d5ead83c30c995f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 6 Apr 2014 13:51:19 +0200 Subject: [PATCH 1064/1445] Safer use of defines in logging.h --- base/logging.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/base/logging.h b/base/logging.h index fd876f5d7b..0e0e2e8129 100644 --- a/base/logging.h +++ b/base/logging.h @@ -29,18 +29,17 @@ inline void Crash() { __asm { int 3 }; } #else -#if defined(ARM) || defined(MIPS) +#if defined(_M_IX86) || defined(_M_X64) +inline void Crash() { + PrintBacktraceToStderr(); + asm("int $0x3"); +} +#else inline void Crash() { PrintBacktraceToStderr(); char *p = (char *)1337; *p = 1; } -#else -// TODO: 64-bit version -inline void Crash() { - PrintBacktraceToStderr(); - asm("int $0x3"); -} #endif #endif From 2499288b4cf33b005d3c02b832b251bc9943880c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 6 Apr 2014 13:52:41 +0200 Subject: [PATCH 1065/1445] iOS compat in gfx/texture.cpp --- gfx/texture.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index d848459d5a..a29acf89d3 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -256,7 +256,7 @@ bool Texture::LoadXOR() { } -#if !defined(USING_GLES2) +#if !defined(USING_GLES2) || defined(IOS) // Allocates using new[], doesn't free. uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { @@ -322,12 +322,14 @@ bool Texture::LoadZIM(const char *filename) { int data_h = height[l]; if (data_w < 4) data_w = 4; if (data_h < 4) data_h = 4; -#if defined(USING_GLES2) +#if defined(USING_GLES2) && !defined(IOS) int compressed_image_bytes = data_w * data_h / 2; glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); GL_CHECK(); #else // TODO: OpenGL 4.3+ accepts ETC1 so we should not have to do this anymore on those cards. + // Also, iOS does not have support for ETC1 compressed textures so we just decompress. + // TODO: Use PVR texture compression on iOS. image_data[l] = ETC1ToRGBA(image_data[l], data_w, data_h); glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, width[l], height[l], 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data[l]); From a98abb9c1355764bd91e13e4887ee65172b894c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 6 Apr 2014 14:28:42 +0200 Subject: [PATCH 1066/1445] Minor fixes --- image/png_load.cpp | 2 +- math/curves.h | 2 +- util/bits/bits.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/image/png_load.cpp b/image/png_load.cpp index eeab7f5e63..fadcf64441 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include "libpng16/png.h" #include "png_load.h" #include "base/logging.h" diff --git a/math/curves.h b/math/curves.h index be5133326a..3ed6683c38 100644 --- a/math/curves.h +++ b/math/curves.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "base/basictypes.h" // Easy curve computation for fades etc. diff --git a/util/bits/bits.h b/util/bits/bits.h index d5c3d7eac6..6c1edd22b4 100644 --- a/util/bits/bits.h +++ b/util/bits/bits.h @@ -1,5 +1,5 @@ #ifndef _UTIL_BITS_BITS -#define _UTil_BITS_BITS +#define _UTIL_BITS_BITS #include "base/basictypes.h" From 56f3a9733d916ee8ba2c27149f394e8417c9ccd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 6 Apr 2014 15:04:37 +0200 Subject: [PATCH 1067/1445] Add guards to fast_matrix_sse.c --- math/fast/fast_matrix_sse.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/math/fast/fast_matrix_sse.c b/math/fast/fast_matrix_sse.c index 2bc945e4a9..9472194488 100644 --- a/math/fast/fast_matrix_sse.c +++ b/math/fast/fast_matrix_sse.c @@ -1,3 +1,5 @@ +#if defined(_M_IX86) || defined(_M_X64) + #include #include "fast_matrix.h" @@ -17,3 +19,5 @@ void fast_matrix_mul_4x4_sse(float *dest, const float *a, const float *b) { _mm_storeu_ps(&dest[i], r_col); } } + +#endif \ No newline at end of file From 9ab7a8cb902a0ff15bcc8127a31fd790185bc735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 6 Apr 2014 16:31:32 +0200 Subject: [PATCH 1068/1445] Warning fixes --- gfx_es2/gl_state.cpp | 2 +- util/text/utf8.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 648bf373e1..4535237a19 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -125,7 +125,7 @@ void CheckGLExtensions() { gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; } - ILOG("GPU Vendor : %s ; GL version str: %s", cvendor, versionStr ? versionStr : "N/A"); + ILOG("GPU Vendor : %s ; GL version str: %s ; GLSL version str: %s", cvendor, versionStr ? versionStr : "N/A", glslVersionStr ? glslVersionStr : "N/A"); #ifndef USING_GLES2 char buffer[64] = {0}; diff --git a/util/text/utf8.cpp b/util/text/utf8.cpp index c236125b04..8f9dca5210 100644 --- a/util/text/utf8.cpp +++ b/util/text/utf8.cpp @@ -261,7 +261,7 @@ int hex_digit(char c) returns number of input characters processed */ int u8_read_escape_sequence(const char *str, uint32_t *dest) { - uint32_t ch; + long ch; char digs[9]="\0\0\0\0\0\0\0\0"; int dno=0, i=1; From 06ec64fa620ae4afa2322be2f1cf8e0094ce6089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 8 Apr 2014 15:26:37 +0200 Subject: [PATCH 1069/1445] Warning fixes --- ext/jpge/jpgd.cpp | 2 +- ext/rg_etc1/rg_etc1.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/jpge/jpgd.cpp b/ext/jpge/jpgd.cpp index fad9a37a9a..34e2224e7d 100644 --- a/ext/jpge/jpgd.cpp +++ b/ext/jpge/jpgd.cpp @@ -564,7 +564,7 @@ inline int jpeg_decoder::huff_decode(huff_tables *pH, int& extra_bits) // Tables and macro used to fully decode the DPCM differences. static const int s_extend_test[16] = { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; static const int s_extend_offset[16] = { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; -static const int s_extend_mask[] = { 0, (1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7), (1<<8), (1<<9), (1<<10), (1<<11), (1<<12), (1<<13), (1<<14), (1<<15), (1<<16) }; +//static const int s_extend_mask[] = { 0, (1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7), (1<<8), (1<<9), (1<<10), (1<<11), (1<<12), (1<<13), (1<<14), (1<<15), (1<<16) }; // The logical AND's in this macro are to shut up static code analysis (aren't really necessary - couldn't find another way to do this) #define JPGD_HUFF_EXTEND(x, s) (((x) < s_extend_test[s & 15]) ? ((x) + s_extend_offset[s & 15]) : (x)) diff --git a/ext/rg_etc1/rg_etc1.cpp b/ext/rg_etc1/rg_etc1.cpp index 25e9d8d7f3..6c174b4e71 100644 --- a/ext/rg_etc1/rg_etc1.cpp +++ b/ext/rg_etc1/rg_etc1.cpp @@ -1878,8 +1878,8 @@ done: static uint etc1_decode_value(uint diff, uint inten, uint selector, uint packed_c) { - const uint limit = diff ? 32 : 16; limit; - RG_ETC1_ASSERT((diff < 2) && (inten < 8) && (selector < 4) && (packed_c < limit)); + //const uint limit = diff ? 32 : 16; limit; + //RG_ETC1_ASSERT((diff < 2) && (inten < 8) && (selector < 4) && (packed_c < limit)); int c; if (diff) c = (packed_c >> 2) | (packed_c << 3); @@ -1940,7 +1940,7 @@ done: // For random 888 inputs, MSE results are better than Erricson's ETC1 packer in "slow" mode ~9.5% of the time, is slightly worse only ~.01% of the time, and is equal the rest of the time. static uint64 pack_etc1_block_solid_color(etc1_block& block, const uint8* pColor, etc1_pack_params& pack_params) { - pack_params; + // pack_params; RG_ETC1_ASSERT(g_etc1_inverse_lookup[0][255]); static uint s_next_comp[4] = { 1, 2, 0, 1 }; @@ -2032,7 +2032,7 @@ found_perfect_match: { RG_ETC1_ASSERT(g_etc1_inverse_lookup[0][255]); - pack_params; + //pack_params; static uint s_next_comp[4] = { 1, 2, 0, 1 }; uint best_error = cUINT32_MAX, best_i = 0; From ea404141d76ac58db4f0d77080d994b8eee79c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 8 Apr 2014 15:26:47 +0200 Subject: [PATCH 1070/1445] More warning fixes --- file/file_util.cpp | 4 ++-- file/file_util.h | 4 +++- image/zim_load.cpp | 2 -- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index d0d8a212e3..130d8c8ada 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -86,11 +86,11 @@ bool writeDataToFile(bool text_file, const void* data, const unsigned int size, uint64_t GetSize(FILE *f) { // can't use off_t here because it can be 32-bit - uint64_t pos = ftell(f); + size_t pos = ftell(f); if (fseek(f, 0, SEEK_END) != 0) { return 0; } - uint64_t size = ftell(f); + size_t size = ftell(f); // Reset the seek position to where it was when we started. if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) { // Should error here diff --git a/file/file_util.h b/file/file_util.h index ff3290e5c5..6b659bea9b 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -3,6 +3,8 @@ #include #include +#include + // Whole-file reading/writing bool writeStringToFile(bool text_file, const std::string &str, const char *filename); bool readFileToString(bool text_file, const char *filename, std::string &str); @@ -18,7 +20,7 @@ struct FileInfo { bool exists; bool isDirectory; bool isWritable; - size_t size; + uint64_t size; bool operator <(const FileInfo &other) const; }; diff --git a/image/zim_load.cpp b/image/zim_load.cpp index 70d564628e..ec6266a4b2 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -50,8 +50,6 @@ int ezuncompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSr return nExtraChunks ? Z_BUF_ERROR : Z_OK; } -static const char magic[5] = "ZIMG"; - static unsigned int log2i(unsigned int val) { unsigned int ret = -1; while (val != 0) { From b914c1a1fdddfaf9821a26bb50de104e3b342c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 8 Apr 2014 15:27:14 +0200 Subject: [PATCH 1071/1445] Easy way to mimic an ipad by windows size --- base/PCMain.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 0e0958e798..1a397bf703 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -440,6 +440,7 @@ int main(int argc, char *argv[]) { int set_xres = -1; int set_yres = -1; + int set_ipad = 0; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; @@ -461,6 +462,9 @@ int main(int argc, char *argv[]) { set_dpi = -2; if (!strcmp(argv[i],"--scale")) set_scale = -2; + + if (!strcmp(argv[i],"--ipad")) + set_ipad = 1; } #endif if (mode & SDL_FULLSCREEN) { @@ -481,6 +485,10 @@ int main(int argc, char *argv[]) { set_dpi = 1.0f / set_dpi; + if (set_ipad) { + pixel_xres = 1024; + pixel_yres = 768; + } if (!landscape) { std::swap(pixel_xres, pixel_yres); } From 1167f20d14ba58bc045e3a248aeb71884c99a488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 8 Apr 2014 16:08:38 +0200 Subject: [PATCH 1072/1445] Warning fixes, etc. --- ext/jpge/jpgd.cpp | 2 +- ext/rg_etc1/rg_etc1.cpp | 6 +++--- gfx_es2/glsl_program.cpp | 5 ++++- util/text/utf8.cpp | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ext/jpge/jpgd.cpp b/ext/jpge/jpgd.cpp index 34e2224e7d..cc47bd721c 100644 --- a/ext/jpge/jpgd.cpp +++ b/ext/jpge/jpgd.cpp @@ -874,7 +874,7 @@ void *jpeg_decoder::alloc(size_t nSize, bool zero) } if (!rv) { - int capacity = JPGD_MAX(32768 - 256, (nSize + 2047) & ~2047); + int capacity = (int)JPGD_MAX(32768 - 256, (nSize + 2047) & ~2047); mem_block *b = (mem_block*)jpgd_malloc(sizeof(mem_block) + capacity); if (!b) { stop_decoding(JPGD_NOTENOUGHMEM); } b->m_pNext = m_pMem_blocks; m_pMem_blocks = b; diff --git a/ext/rg_etc1/rg_etc1.cpp b/ext/rg_etc1/rg_etc1.cpp index 6c174b4e71..7a5fce713e 100644 --- a/ext/rg_etc1/rg_etc1.cpp +++ b/ext/rg_etc1/rg_etc1.cpp @@ -1803,7 +1803,7 @@ namespace rg_etc1 { if (block_inten[0] > m_pSorted_luma[n - 1]) { - const uint min_error = labs(block_inten[0] - m_pSorted_luma[n - 1]); + const uint min_error = (uint)(labs(block_inten[0] - m_pSorted_luma[n - 1])); if (min_error >= trial_solution.m_error) continue; } @@ -1817,7 +1817,7 @@ namespace rg_etc1 { if (m_pSorted_luma[0] > block_inten[3]) { - const uint min_error = labs(m_pSorted_luma[0] - block_inten[3]); + const uint min_error = (uint)(labs(m_pSorted_luma[0] - block_inten[3])); if (min_error >= trial_solution.m_error) continue; } @@ -1909,7 +1909,7 @@ done: for (uint packed_c = 0; packed_c < limit; packed_c++) { int v = etc1_decode_value(diff, inten, selector, packed_c); - uint err = labs(v - static_cast(color)); + uint err = (uint)labs(v - static_cast(color)); if (err < best_error) { best_error = err; diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 3ae758d695..fdf88ea807 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -264,7 +264,10 @@ void glsl_destroy(GLSLProgram *program) { } void glsl_bind(const GLSLProgram *program) { - glUseProgram(program->program_); + if (program) + glUseProgram(program->program_); + else + glUseProgram(0); } void glsl_unbind() { diff --git a/util/text/utf8.cpp b/util/text/utf8.cpp index 8f9dca5210..5d5292e689 100644 --- a/util/text/utf8.cpp +++ b/util/text/utf8.cpp @@ -308,7 +308,7 @@ int u8_read_escape_sequence(const char *str, uint32_t *dest) if (dno > 0) ch = strtol(digs, NULL, 16); } - *dest = ch; + *dest = (uint32_t)ch; return i; } From dc1e691ea8e70778d6559366d3e6372b31fe0bf5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 11 Apr 2014 21:21:52 +0200 Subject: [PATCH 1073/1445] Remove unnecessary check for '!' in path browser --- file/path.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/file/path.cpp b/file/path.cpp index a6208d3ce8..d50a64f237 100644 --- a/file/path.cpp +++ b/file/path.cpp @@ -39,9 +39,6 @@ void PathBrowser::GetListing(std::vector &fileInfo, const char *filter // TODO: Support paths like "../../hello" void PathBrowser::Navigate(const std::string &path) { - if (path[0] == '!') - return; - if (path == ".") return; if (path == "..") { From 3c13a9009999bf883c4c608d8b4f30a7d0c75560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 13 Apr 2014 17:08:36 +0200 Subject: [PATCH 1074/1445] SDL: Add flag for portrait mode --- base/PCMain.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 1a397bf703..b134ffe252 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -441,6 +441,7 @@ int main(int argc, char *argv[]) { int set_yres = -1; int set_ipad = 0; + bool portrait = false; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; @@ -465,6 +466,8 @@ int main(int argc, char *argv[]) { if (!strcmp(argv[i],"--ipad")) set_ipad = 1; + if (!strcmp(argv[i],"--portrait")) + portrait = true; } #endif if (mode & SDL_FULLSCREEN) { @@ -478,6 +481,9 @@ int main(int argc, char *argv[]) { // set a sensible default resolution (2x) pixel_xres = 480 * 2 * set_scale; pixel_yres = 272 * 2 * set_scale; + if (portrait) { + std::swap(pixel_xres, pixel_yres); + } #ifdef PPSSPP g_Config.bFullScreen = false; #endif From 980e6eaca6e51e07c0ea5b38bce71499f10acc21 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Apr 2014 18:31:25 -0700 Subject: [PATCH 1075/1445] Check for the GL_EXT_bgra extension. --- gfx_es2/gl_state.cpp | 1 + gfx_es2/gpu_features.h | 1 + 2 files changed, 2 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 4535237a19..63c642f85e 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -205,6 +205,7 @@ void CheckGLExtensions() { gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); + gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0; if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) { // Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable // Also on Intel, see https://github.com/hrydgard/ppsspp/issues/4867 diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 0e0de4ac6c..ab17ec2f17 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -49,6 +49,7 @@ struct GLExtensions { bool EXT_unpack_subimage; // always supported on desktop and ES3 bool ARB_blend_func_extended; // dual source blending bool ARB_shader_image_load_store; + bool EXT_bgra; // EGL extensions bool EGL_NV_system_time; From daf2595eb0d2664d1d5f284e569e41e3b7dc78c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 17 Apr 2014 00:05:34 +0200 Subject: [PATCH 1076/1445] Introduce arch.h, which provides the MSVC compatible arch defines on other platforms. --- base/arch.h | 17 +++++++++++++++++ base/logging.h | 3 ++- math/fast/fast_math.c | 1 + math/fast/fast_matrix_sse.c | 4 +++- 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 base/arch.h diff --git a/base/arch.h b/base/arch.h new file mode 100644 index 0000000000..3bdce74e55 --- /dev/null +++ b/base/arch.h @@ -0,0 +1,17 @@ +#pragma once + +// This provides MSVC's arch-detection defines on other platforms as well. + +#ifndef _WIN32 + +#if defined(__x86_64__) && !defined(_M_X64) +#define _M_X64 1 +#endif + +#if defined(__x86__) && !defined(_M_IX86) +#define _M_IX86 1 +#endif + +// TODO: ARM, ARM64 + +#endif diff --git a/base/logging.h b/base/logging.h index 0e0e2e8129..a70160fe68 100644 --- a/base/logging.h +++ b/base/logging.h @@ -1,6 +1,7 @@ #pragma once -#include "backtrace.h" +#include "base/arch.h" +#include "base/backtrace.h" // Simple wrapper around Android's logging interface that also allows other // implementations, and also some misc utilities. diff --git a/math/fast/fast_math.c b/math/fast/fast_math.c index 018c67436a..1fa6acd8df 100644 --- a/math/fast/fast_math.c +++ b/math/fast/fast_math.c @@ -1,3 +1,4 @@ +#include "base/arch.h" #include "fast_math.h" #include "fast_matrix.h" diff --git a/math/fast/fast_matrix_sse.c b/math/fast/fast_matrix_sse.c index 9472194488..166f71abce 100644 --- a/math/fast/fast_matrix_sse.c +++ b/math/fast/fast_matrix_sse.c @@ -1,3 +1,5 @@ +#include "base/arch.h" + #if defined(_M_IX86) || defined(_M_X64) #include @@ -20,4 +22,4 @@ void fast_matrix_mul_4x4_sse(float *dest, const float *a, const float *b) { } } -#endif \ No newline at end of file +#endif From 551564b2ea752e314253266b01282cb0537a45bd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 18 Apr 2014 19:21:28 +0200 Subject: [PATCH 1077/1445] Detect NV_shader_framebuffer_fetch and the EXT extension separately. --- gfx_es2/gl_state.cpp | 3 ++- gfx_es2/gpu_features.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 63c642f85e..e311f52edd 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -219,7 +219,8 @@ void CheckGLExtensions() { gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0; - gl_extensions.EXT_shader_framebuffer_fetch = (strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0) || (strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0); + gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; + gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; #if defined(ANDROID) || defined(BLACKBERRY) diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index ab17ec2f17..07127567c9 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -42,6 +42,7 @@ struct GLExtensions { bool EXT_swap_control_tear; bool OES_mapbuffer; bool OES_vertex_array_object; + bool NV_shader_framebuffer_fetch; bool EXT_shader_framebuffer_fetch; bool EXT_blend_minmax; bool NV_draw_texture; From 29193f0f2ab7289d7474e916b4e2fce05a70698d Mon Sep 17 00:00:00 2001 From: raven02 Date: Wed, 23 Apr 2014 22:38:56 +0800 Subject: [PATCH 1078/1445] Restore viewport natively in fbo_bind_as_render_target() --- gfx_es2/fbo.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 909b5aab12..9f650d6ce5 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -278,6 +278,9 @@ void fbo_bind_as_render_target(FBO *fbo) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); #endif } + if (gl_extensions.gpuVendor != GPU_VENDOR_POWERVR) { + glstate.viewport.restore(); + } } void fbo_bind_for_read(FBO *fbo) { From 803c5a1ba67e5299c717a4849fd4032fe0fd3c08 Mon Sep 17 00:00:00 2001 From: raven02 Date: Wed, 23 Apr 2014 22:45:38 +0800 Subject: [PATCH 1079/1445] Add comment and specify to use ARM/ADERNO --- gfx_es2/fbo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 9f650d6ce5..50814220dc 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -278,7 +278,8 @@ void fbo_bind_as_render_target(FBO *fbo) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); #endif } - if (gl_extensions.gpuVendor != GPU_VENDOR_POWERVR) { + // Adreno & Mali needs us to reset the viewport after switching render targets. + if ((gl_extensions.gpuVendor == GPU_VENDOR_ARM) || (gl_extensions.gpuVendor == GPU_VENDOR_ADRENO)) { glstate.viewport.restore(); } } From 9ce30b33c31f201ffb6659442862cc190ac33ded Mon Sep 17 00:00:00 2001 From: raven02 Date: Wed, 23 Apr 2014 23:07:09 +0800 Subject: [PATCH 1080/1445] Always restore viewport after render target binding --- gfx_es2/fbo.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 50814220dc..a4ff4dcefd 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -278,10 +278,8 @@ void fbo_bind_as_render_target(FBO *fbo) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); #endif } - // Adreno & Mali needs us to reset the viewport after switching render targets. - if ((gl_extensions.gpuVendor == GPU_VENDOR_ARM) || (gl_extensions.gpuVendor == GPU_VENDOR_ADRENO)) { - glstate.viewport.restore(); - } + // Always restore viewport after render target binding + glstate.viewport.restore(); } void fbo_bind_for_read(FBO *fbo) { From 86b77979851490b6b5f6924a1a44f27efc7997b4 Mon Sep 17 00:00:00 2001 From: sum2012 Date: Thu, 24 Apr 2014 06:03:52 +0800 Subject: [PATCH 1081/1445] Fix French UI crash Reported in https://github.com/hrydgard/ppsspp/issues/5843 by @vnctdj --- file/ini_file.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index cb186b242d..78d6cb24aa 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -45,6 +45,7 @@ static bool ParseLine(const std::string& line, std::string* keyOut, std::string* while (line[FirstCommentChar - 1] == ' ' || line[FirstCommentChar - 1] == 9) // 9 == tab { FirstCommentChar--; + if (FirstCommentChar <= 0) break; } } From db29bc50cf88e712a13ab515b31de54cdb8b10bb Mon Sep 17 00:00:00 2001 From: sum2012 Date: Thu, 24 Apr 2014 06:36:34 +0800 Subject: [PATCH 1082/1445] Use @unknownbrackets fix --- file/ini_file.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index 78d6cb24aa..615df16a12 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -40,13 +40,9 @@ static bool ParseLine(const std::string& line, std::string* keyOut, std::string* FirstCommentChar = 0; // Allow preservation of spacing before comment - if (FirstCommentChar > 0) + while (FirstCommentChar > 0 && line[FirstCommentChar - 1] <= ' ') { - while (line[FirstCommentChar - 1] == ' ' || line[FirstCommentChar - 1] == 9) // 9 == tab - { - FirstCommentChar--; - if (FirstCommentChar <= 0) break; - } + FirstCommentChar--; } if ((FirstEquals >= 0) && ((FirstCommentChar < 0) || (FirstEquals < FirstCommentChar))) From 7c3180c7c705795684dd54b3fa98c647c7599732 Mon Sep 17 00:00:00 2001 From: raven02 Date: Wed, 30 Apr 2014 11:34:15 +0800 Subject: [PATCH 1083/1445] Add ES 3.0 support for iPhone --- gfx/gl_common.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index f209aa26f4..a4d81444a8 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -3,7 +3,8 @@ #if defined(USING_GLES2) #ifdef IOS -// I guess we can soon add ES 3.0 here too +#include +#include #include #include #else From 42754b2662fde9341e3ab2deedfc6ff7e4477e4c Mon Sep 17 00:00:00 2001 From: raven02 Date: Thu, 1 May 2014 10:17:28 +0800 Subject: [PATCH 1084/1445] define MAY_HAVE_GLES3 --- gfx/gl_common.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index a4d81444a8..ea1358e107 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -3,10 +3,13 @@ #if defined(USING_GLES2) #ifdef IOS +#ifdef MAY_HAVE_GLES3 #include #include +#else #include #include +#endif // MAY_HAVE_GLES3 #else #include #include From e70c33aa73e067525e2b3d0085d6b55b3428da94 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 2 May 2014 15:58:19 +0800 Subject: [PATCH 1085/1445] Add support for GL_NV_framebuffer_blit --- gfx_es2/gl_state.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index e311f52edd..397390b790 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -206,6 +206,7 @@ void CheckGLExtensions() { gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0; + gl_extensions.NV_framebuffer_blit = strstr(extString, "GL_NV_framebuffer_blit") != 0; if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) { // Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable // Also on Intel, see https://github.com/hrydgard/ppsspp/issues/4867 From 1502110e25ca95534ce5e3d5abf3ea8f035338f6 Mon Sep 17 00:00:00 2001 From: raven02 Date: Fri, 2 May 2014 18:25:56 +0800 Subject: [PATCH 1086/1445] Add NV_framebuffer_blit --- gfx_es2/gpu_features.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 07127567c9..4dcdc23c57 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -51,6 +51,7 @@ struct GLExtensions { bool ARB_blend_func_extended; // dual source blending bool ARB_shader_image_load_store; bool EXT_bgra; + bool NV_framebuffer_blit; // EGL extensions bool EGL_NV_system_time; From 8ada7de18ad6f7226c03b99a917f3d3e07f00a4c Mon Sep 17 00:00:00 2001 From: The Dax Date: Fri, 2 May 2014 17:46:24 -0400 Subject: [PATCH 1087/1445] Fix fullscreen resizing. It wasn't working properly. --- base/PCMain.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index b134ffe252..2df5e7041d 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -54,6 +54,9 @@ static SDL_Surface* g_Screen = NULL; static bool g_ToggleFullScreenNextFrame = false; static int g_QuitRequested = 0; +static int g_DesktopWidth = 0; +static int g_DesktopHeight = 0; + #if defined(MAEMO) || defined(PANDORA) #define EGL #include "EGL/egl.h" @@ -371,14 +374,21 @@ void ToggleFullScreenIfFlagSet() { g_ToggleFullScreenNextFrame = false; #if 1 + pixel_xres = g_DesktopWidth; + pixel_yres = g_DesktopHeight; + dp_xres = (float)pixel_xres; + dp_yres = (float)pixel_yres; + int flags = g_Screen->flags; // Save the current flags in case toggling fails - g_Screen = SDL_SetVideoMode(0, 0, 0, g_Screen->flags ^ SDL_FULLSCREEN); // Toggles FullScreen Mode + g_Screen = SDL_SetVideoMode(g_DesktopWidth, g_DesktopHeight, 0, g_Screen->flags ^ SDL_FULLSCREEN); // Toggles FullScreen Mode if (g_Screen == NULL) { g_Screen = SDL_SetVideoMode(0, 0, 0, flags); // If toggle FullScreen failed, then switch back } if (g_Screen == NULL) { exit(1); // If you can't switch back for some reason, then epic fail } + + NativeResized(); #endif } } @@ -420,6 +430,11 @@ int main(int argc, char *argv[]) { return 1; #endif + // Get the video info before doing anything else, so we don't get skewed resolution results. + const SDL_VideoInfo* desktopVideoInfo = SDL_GetVideoInfo(); + g_DesktopWidth = desktopVideoInfo->current_w; + g_DesktopHeight = desktopVideoInfo->current_h; + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); From 83f80c427bbd9d8a81f9184daeab9e5fb02ac137 Mon Sep 17 00:00:00 2001 From: The Dax Date: Sat, 26 Apr 2014 00:08:20 -0400 Subject: [PATCH 1088/1445] SDL: Let the window be resizable on platforms it makes sense on. --- base/PCMain.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index b134ffe252..67a9afac40 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -436,7 +436,7 @@ int main(int argc, char *argv[]) { int set_xres = -1; int set_yres = -1; #else - mode = SDL_OPENGL; + mode = SDL_OPENGL | SDL_RESIZABLE; int set_xres = -1; int set_yres = -1; @@ -627,6 +627,23 @@ int main(int argc, char *argv[]) { case SDL_QUIT: g_QuitRequested = 1; break; +#if !defined(MOBILE_DEVICE) + case SDL_VIDEORESIZE: + { + g_Screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_OPENGL | SDL_RESIZABLE); + if (g_Screen == NULL) { + fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); + SDL_Quit(); + return 2; + } + pixel_xres = event.resize.w; + pixel_yres = event.resize.h; + dp_xres = (float)pixel_xres * dpi_scale; + dp_yres = (float)pixel_yres * dpi_scale; + NativeResized(); + break; + } +#endif case SDL_KEYDOWN: { int k = event.key.keysym.sym; From 2fdd86040215cbe33587bdf39d3214e5aa20f00e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 May 2014 13:13:23 -0700 Subject: [PATCH 1089/1445] Add encodeUnits() to utf8/utf16/sjis. So that we know how many units (e.g. u16s) are needed to encode. --- native.vcxproj | 4 +++- native.vcxproj.filters | 6 ++++++ util/text/shiftjis.h | 7 +++++++ util/text/utf16.h | 10 +++++++++- util/text/utf8.h | 12 ++++++++++++ 5 files changed, 37 insertions(+), 2 deletions(-) diff --git a/native.vcxproj b/native.vcxproj index cdc424ad84..2de8185ade 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -287,6 +287,8 @@ + + @@ -776,4 +778,4 @@ - + \ No newline at end of file diff --git a/native.vcxproj.filters b/native.vcxproj.filters index e9e15c5b0b..8406a16f12 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -338,6 +338,12 @@ math\fast + + util + + + util + diff --git a/util/text/shiftjis.h b/util/text/shiftjis.h index 72f9438c48..e92df04db6 100644 --- a/util/text/shiftjis.h +++ b/util/text/shiftjis.h @@ -127,6 +127,13 @@ struct ShiftJIS { return 2; } + static int encodeUnits(uint32_t j) { + if ((j & ~0xFF) == 0) { + return 1; + } + return 2; + } + private: const char *c_; int index_; diff --git a/util/text/utf16.h b/util/text/utf16.h index 002886259d..2475b7292a 100644 --- a/util/text/utf16.h +++ b/util/text/utf16.h @@ -42,7 +42,7 @@ public: return len; } - int byteIndex() const { + int shortIndex() const { return index_; } @@ -58,6 +58,14 @@ public: } } + static int encodeUnits(uint32_t u) { + if (u >= 0x10000) { + return 2; + } else { + return 1; + } + } + private: const uint16_t *c_; int index_; diff --git a/util/text/utf8.h b/util/text/utf8.h index 32312ee35a..8a11eb6a28 100644 --- a/util/text/utf8.h +++ b/util/text/utf8.h @@ -44,6 +44,18 @@ public: static int encode(char *dest, uint32_t ch) { return u8_wc_toutf8(dest, ch); } + static int encodeUnits(uint32_t ch) { + if (ch < 0x80) { + return 1; + } else if (ch < 0x800) { + return 2; + } else if (ch < 0x10000) { + return 3; + } else if (ch < 0x110000) { + return 4; + } + return 0; + } private: const char *c_; From 3866998e10b223ad05264c9fdfa0bde8645eb144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 4 May 2014 12:33:28 +0200 Subject: [PATCH 1090/1445] Apply patch from gschwind that lets us accept more audio formats (although I'm not sure which ones would apply...) --- base/PCMain.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 250c767df5..de634fc2e9 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -147,7 +147,7 @@ int8_t EGL_Init() { // Get the SDL window handle SDL_SysWMinfo sysInfo; //Will hold our Window information SDL_VERSION(&sysInfo.version); //Set SDL version - if(SDL_GetWMInfo(&sysInfo) <= 0) { + if (SDL_GetWMInfo(&sysInfo) <= 0) { printf("EGL ERROR: Unable to get SDL window handle: %s\n", SDL_GetError()); return 1; } @@ -596,7 +596,8 @@ int main(int argc, char *argv[]) { NativeInitGraphics(); NativeResized(); - SDL_AudioSpec fmt; + SDL_AudioSpec fmt, ret_fmt; + memset(&fmt, 0, sizeof(fmt)); fmt.freq = 44100; fmt.format = AUDIO_S16; fmt.channels = 2; @@ -604,8 +605,23 @@ int main(int argc, char *argv[]) { fmt.callback = &mixaudio; fmt.userdata = (void *)0; - if (SDL_OpenAudio(&fmt, NULL) < 0) { + if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) { ELOG("Failed to open audio: %s", SDL_GetError()); + } else { + if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2 || fmt.samples != 2048) { + ELOG("Sound buffer format does not match requested format."); + ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, 44100); + ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, AUDIO_S16); + ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, 2); + ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, 2048); + } + + if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2) { + ELOG("Provided output format does not match requirement, turning audio off"); + SDL_CloseAudio(); + } else { + ELOG("Provided output audio format is usable, thus using it"); + } } // Audio must be unpaused _after_ NativeInit() From fbdf659723a95ef05a55bd0463d93a949bb9d0f7 Mon Sep 17 00:00:00 2001 From: The Dax Date: Mon, 5 May 2014 23:39:57 -0400 Subject: [PATCH 1091/1445] Add the ability for Sliders and their corresponding Screens to have the ability to move in steps greater than 1. No float support, only the integer screens are affected. --- ui/ui_screen.cpp | 13 +++++++++---- ui/ui_screen.h | 9 +++++++-- ui/view.cpp | 11 +++++++---- ui/view.h | 3 +++ 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 64ce3d140a..bbb2fe21bb 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -271,13 +271,18 @@ PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, con OnClick.Handle(this, &PopupSliderChoice::HandleClick); } +PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, int step, ScreenManager *screenManager, LayoutParams *layoutParams) +: Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step), screenManager_(screenManager) { + OnClick.Handle(this, &PopupSliderChoice::HandleClick); +} + PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams) : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) { OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); } EventReturn PopupSliderChoice::HandleClick(EventParams &e) { - SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_); + SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_, step_); popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange); screenManager_->push(popupScreen); return EVENT_DONE; @@ -327,13 +332,13 @@ void PopupSliderChoiceFloat::Draw(UIContext &dc) { } EventReturn SliderPopupScreen::OnDecrease(EventParams ¶ms) { - sliderValue_--; + sliderValue_ -= step_; slider_->Clamp(); return EVENT_DONE; } EventReturn SliderPopupScreen::OnIncrease(EventParams ¶ms) { - sliderValue_++; + sliderValue_ += step_; slider_->Clamp(); return EVENT_DONE; } @@ -342,7 +347,7 @@ void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; sliderValue_ = *value_; LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 5)))); - slider_ = new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(1.0f)); + slider_ = new Slider(&sliderValue_, minValue_, maxValue_, step_, new LinearLayoutParams(1.0f)); lin->Add(slider_); lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderPopupScreen::OnDecrease); lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderPopupScreen::OnIncrease); diff --git a/ui/ui_screen.h b/ui/ui_screen.h index ecd2378ece..888ac0c3f8 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -114,7 +114,8 @@ namespace UI { class SliderPopupScreen : public PopupScreen { public: - SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title) : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue) {} + SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title, int step = 1) + : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step) {} void CreatePopupContents(ViewGroup *parent); Event OnChange; @@ -128,11 +129,13 @@ private: int sliderValue_; int minValue_; int maxValue_; + float step_; }; class SliderFloatPopupScreen : public PopupScreen { public: - SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title) : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue) {} + SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title) + : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue) {} void CreatePopupContents(UI::ViewGroup *parent); Event OnChange; @@ -182,6 +185,7 @@ private: class PopupSliderChoice : public Choice { public: PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0); + PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, int step, ScreenManager *screenManager, LayoutParams *layoutParams = 0); void Draw(UIContext &dc); @@ -194,6 +198,7 @@ private: int *value_; int minValue_; int maxValue_; + float step_; ScreenManager *screenManager_; }; diff --git a/ui/view.cpp b/ui/view.cpp index 73e30beaf2..0b45e499f7 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -622,18 +622,18 @@ void Slider::Key(const KeyInput &input) { case NKCODE_DPAD_LEFT: case NKCODE_MINUS: case NKCODE_NUMPAD_SUBTRACT: - *value_ -= 1; + *value_ -= step_; break; case NKCODE_DPAD_RIGHT: case NKCODE_PLUS: case NKCODE_NUMPAD_ADD: - *value_ += 1; + *value_ += step_; break; case NKCODE_PAGE_UP: - *value_ -= 10; + *value_ -= step_ * 10; break; case NKCODE_PAGE_DOWN: - *value_ += 10; + *value_ += step_ * 10; break; case NKCODE_MOVE_HOME: *value_ = minValue_; @@ -658,6 +658,9 @@ void Slider::Touch(const TouchInput &input) { void Slider::Clamp() { if (*value_ < minValue_) *value_ = minValue_; else if (*value_ > maxValue_) *value_ = maxValue_; + + // Clamp the value to be a multiple of the nearest step (e.g. if step == 5, value == 293, it'll round down to 290). + *value_ = *value_ - fmodf(*value_, step_); } void Slider::Draw(UIContext &dc) { diff --git a/ui/view.h b/ui/view.h index 38ef9db698..490b12ff4d 100644 --- a/ui/view.h +++ b/ui/view.h @@ -439,6 +439,8 @@ class Slider : public Clickable { public: Slider(int *value, int minValue, int maxValue, LayoutParams *layoutParams = 0) : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) {} + Slider(int *value, int minValue, int maxValue, int step = 1, LayoutParams *layoutParams = 0) + : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70), step_(step) {} virtual void Draw(UIContext &dc); virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); @@ -454,6 +456,7 @@ private: int maxValue_; float paddingLeft_; float paddingRight_; + float step_; }; class SliderFloat : public Clickable { From 45f475675dad04802d764dada742b9a0aac6ccb9 Mon Sep 17 00:00:00 2001 From: The Dax Date: Mon, 5 May 2014 23:52:10 -0400 Subject: [PATCH 1092/1445] Make sure the Slider can't step in increments of less than 1. --- ui/view.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/view.h b/ui/view.h index 490b12ff4d..a60ece6179 100644 --- a/ui/view.h +++ b/ui/view.h @@ -439,8 +439,12 @@ class Slider : public Clickable { public: Slider(int *value, int minValue, int maxValue, LayoutParams *layoutParams = 0) : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) {} + Slider(int *value, int minValue, int maxValue, int step = 1, LayoutParams *layoutParams = 0) - : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70), step_(step) {} + : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70), step_(step) { + if (step <= 0) + step_ = 1.0f; + } virtual void Draw(UIContext &dc); virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); From b1261c5b55480250eb75695386c45d6cc2fc4656 Mon Sep 17 00:00:00 2001 From: The Dax Date: Tue, 6 May 2014 00:55:37 -0400 Subject: [PATCH 1093/1445] Use integers instead. --- ui/ui_screen.h | 4 ++-- ui/view.h | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 888ac0c3f8..d586bc8915 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -129,7 +129,7 @@ private: int sliderValue_; int minValue_; int maxValue_; - float step_; + int step_; }; class SliderFloatPopupScreen : public PopupScreen { @@ -198,7 +198,7 @@ private: int *value_; int minValue_; int maxValue_; - float step_; + int step_; ScreenManager *screenManager_; }; diff --git a/ui/view.h b/ui/view.h index a60ece6179..2a6258e779 100644 --- a/ui/view.h +++ b/ui/view.h @@ -441,9 +441,8 @@ public: : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) {} Slider(int *value, int minValue, int maxValue, int step = 1, LayoutParams *layoutParams = 0) - : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70), step_(step) { - if (step <= 0) - step_ = 1.0f; + : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) { + step_ = step <= 0 ? 1 : step; } virtual void Draw(UIContext &dc); virtual void Key(const KeyInput &input); @@ -460,7 +459,7 @@ private: int maxValue_; float paddingLeft_; float paddingRight_; - float step_; + int step_; }; class SliderFloat : public Clickable { From f1694e7d4b1c4c80dbd194f3e532f5bfc605a400 Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 6 May 2014 15:13:33 +0800 Subject: [PATCH 1094/1445] Add GL_NV_pixel_buffer_object that seen on Tegra platform --- gfx_es2/gpu_features.h | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 4dcdc23c57..b328208c5b 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -31,29 +31,39 @@ struct GLExtensions { int gpuVendor; bool GLES3; // true if the full OpenGL ES 3.0 is supported + + // OES bool OES_depth24; bool OES_packed_depth_stencil; bool OES_depth_texture; bool OES_texture_npot; // If this is set, can wrap non-pow-2 textures. Set on desktop. - bool EXT_discard_framebuffer; - bool FBO_ARB; - bool FBO_EXT; - bool PBO_ARB; - bool EXT_swap_control_tear; bool OES_mapbuffer; bool OES_vertex_array_object; - bool NV_shader_framebuffer_fetch; - bool EXT_shader_framebuffer_fetch; - bool EXT_blend_minmax; - bool NV_draw_texture; - bool NV_copy_image; - bool EXT_unpack_subimage; // always supported on desktop and ES3 + + // ARB + bool FBO_ARB; + bool PBO_ARB; bool ARB_blend_func_extended; // dual source blending bool ARB_shader_image_load_store; - bool EXT_bgra; - bool NV_framebuffer_blit; - // EGL extensions + // EXT + bool EXT_swap_control_tear; + bool EXT_discard_framebuffer; + bool EXT_unpack_subimage; // always supported on desktop and ES3 + bool EXT_bgra; + bool EXT_shader_framebuffer_fetch; + bool EXT_blend_minmax; + bool FBO_EXT; + bool PBO_EXT; + + // NV + bool NV_shader_framebuffer_fetch; + bool NV_draw_texture; + bool NV_copy_image; + bool NV_framebuffer_blit; + bool PBO_NV; // GL_NV_pixel_buffer_object + + // EGL bool EGL_NV_system_time; bool EGL_NV_coverage_sample; From ba4f5984dad0a1c8d079f509a256d2dc3baf1fed Mon Sep 17 00:00:00 2001 From: raven02 Date: Tue, 6 May 2014 15:14:50 +0800 Subject: [PATCH 1095/1445] gl_extensions.PBO_NV = strstr(extString, "GL_NV_pixel_buffer_object") != 0; --- gfx_es2/gl_state.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 397390b790..cb18360a2b 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -220,10 +220,10 @@ void CheckGLExtensions() { gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0; + gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; - gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; #if defined(ANDROID) || defined(BLACKBERRY) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. // https://twitter.com/ID_AA_Carmack/status/387383037794603008 @@ -298,10 +298,12 @@ void CheckGLExtensions() { gl_extensions.FBO_ARB = false; gl_extensions.FBO_EXT = false; gl_extensions.PBO_ARB = true; + gl_extensions.PBO_NV = true; if (extString) { gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; + gl_extensions.PBO_NV = strstr(extString, "GL_NV_pixel_buffer_object") != 0; } #endif From e2e352622a0f16b76f473ec215129dec50061a31 Mon Sep 17 00:00:00 2001 From: The Dax Date: Tue, 6 May 2014 14:54:19 -0400 Subject: [PATCH 1096/1445] Oops, make sure step_ is initialised, even with the constructor that doesn't specify a step. --- ui/ui_screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index bbb2fe21bb..745ac549fd 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -267,7 +267,7 @@ void PopupMultiChoice::Draw(UIContext &dc) { } PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams) - : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) { + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager), step_(1) { OnClick.Handle(this, &PopupSliderChoice::HandleClick); } From 104486d31453915e4b79bf50c90427792a602f1c Mon Sep 17 00:00:00 2001 From: The Dax Date: Tue, 6 May 2014 15:05:47 -0400 Subject: [PATCH 1097/1445] Just to be safe, initialise the Slider's step_ too. --- ui/view.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/view.h b/ui/view.h index 2a6258e779..e6ee7ca895 100644 --- a/ui/view.h +++ b/ui/view.h @@ -438,7 +438,7 @@ private: class Slider : public Clickable { public: Slider(int *value, int minValue, int maxValue, LayoutParams *layoutParams = 0) - : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) {} + : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70), step_(1) {} Slider(int *value, int minValue, int maxValue, int step = 1, LayoutParams *layoutParams = 0) : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) { From 996808254b76a2614c0d2506f4b707c0c880f1e9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 8 May 2014 10:39:45 +0200 Subject: [PATCH 1098/1445] Load glBlitFramebufferNV extension correctly --- gfx_es2/gl_state.cpp | 10 +++++++++- gfx_es2/gl_state.h | 7 ++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index cb18360a2b..885bbe45a0 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -13,7 +13,8 @@ PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; PFNGLDRAWTEXTURENVPROC glDrawTextureNV; -PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV ; +PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV; +PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV; PFNGLMAPBUFFERPROC glMapBuffer; PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; @@ -224,6 +225,7 @@ void CheckGLExtensions() { gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; + #if defined(ANDROID) || defined(BLACKBERRY) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. // https://twitter.com/ID_AA_Carmack/status/387383037794603008 @@ -241,6 +243,10 @@ void CheckGLExtensions() { glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV"); } + if (gl_extensions.NV_framebuffer_blit) { + glBlitFramebufferNV = (PFNGLBLITFRAMEBUFFERNVPROC)eglGetProcAddress("glBlitFramebufferNV"); + } + gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0; if (gl_extensions.OES_vertex_array_object) { glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" ); @@ -249,6 +255,7 @@ void CheckGLExtensions() { glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" ); } + // Hm, this should be available on iOS too. gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; if (gl_extensions.EXT_discard_framebuffer) { glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); @@ -257,6 +264,7 @@ void CheckGLExtensions() { gl_extensions.OES_vertex_array_object = false; gl_extensions.EXT_discard_framebuffer = false; #endif + #else // Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc) gl_extensions.EXT_blend_minmax = true; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index b47f4f6f8f..b8419e95c2 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -30,7 +30,7 @@ extern PFNGLMAPBUFFERPROC glMapBuffer; #endif -#if !defined(IOS) && !defined(MAEMO) +#if !defined(IOS) && !defined(MAEMO) && !defined(__SYMBIAN__) typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV; typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum @@ -38,6 +38,11 @@ typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); extern PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV; +typedef void (EGLAPIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) ( + GLint srcX0, GLint srcY0, GLint srcX1, GLuint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLuint dstY1, + GLint mask, GLenum filter); +extern PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV; #endif #if defined(ANDROID) || defined(BLACKBERRY) From 9be913768dc6dc161c5dbb9e5a8e4d3842584eec Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 15 May 2014 15:58:52 +1000 Subject: [PATCH 1099/1445] Symbian: Use new accelerometer events. --- base/QtMain.h | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index 4fab7543ce..f630c7ace9 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -9,7 +9,7 @@ #include #include -#if defined(USING_GLES2) && !defined(MAEMO) +#if defined(MOBILE_DEVICE) && !defined(MAEMO) #include QTM_USE_NAMESPACE #endif @@ -45,7 +45,7 @@ public: #if QT_VERSION < 0x50000 setAttribute(Qt::WA_LockLandscapeOrientation); #endif -#if defined(USING_GLES2) && !defined(MAEMO) +#if defined(MOBILE_DEVICE) && !defined(MAEMO) acc = new QAccelerometer(this); acc->start(); #endif @@ -54,7 +54,7 @@ public: startTimer(16); } ~MainUI() { -#if defined(USING_GLES2) && !defined(MAEMO) +#if defined(MOBILE_DEVICE) && !defined(MAEMO) delete acc; #endif NativeShutdownGraphics(); @@ -192,20 +192,35 @@ protected: void updateAccelerometer() { -#if defined(USING_GLES2) && !defined(MAEMO) +#if defined(MOBILE_DEVICE) && !defined(MAEMO) // TODO: Toggle it depending on whether it is enabled QAccelerometerReading *reading = acc->reading(); if (reading) { input_state.acc.x = reading->x(); input_state.acc.y = reading->y(); input_state.acc.z = reading->z(); + AxisInput axis; + axis.deviceId = DEVICE_ID_ACCELEROMETER; + axis.flags = 0; + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_X; + axis.value = input_state.acc.x; + NativeAxis(axis); + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Y; + axis.value = input_state.acc.y; + NativeAxis(axis); + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Z; + axis.value = input_state.acc.z; + NativeAxis(axis); } #endif } private: InputState input_state; -#if defined(USING_GLES2) && !defined(MAEMO) +#if defined(MOBILE_DEVICE) && !defined(MAEMO) QAccelerometer* acc; #endif }; From edaea34df1b1b7b37eac23abf39a27e3f4b3b78e Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 15 May 2014 15:58:59 +1000 Subject: [PATCH 1100/1445] Blackberry: Use new accelerometer events. --- base/BlackberryMain.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 37a1bc34f7..5f7de616cd 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -280,6 +280,21 @@ void BlackberryMain::runMain() { } else if (domain == sensor_get_domain()) { if (SENSOR_ACCELEROMETER_READING == bps_event_get_code(event)) { sensor_event_get_xyz(event, &(input_state.acc.y), &(input_state.acc.x), &(input_state.acc.z)); + AxisInput axis; + axis.deviceId = DEVICE_ID_ACCELEROMETER; + axis.flags = 0; + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_X; + axis.value = input_state.acc.x; + NativeAxis(axis); + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Y; + axis.value = input_state.acc.y; + NativeAxis(axis); + + axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Z; + axis.value = input_state.acc.z; + NativeAxis(axis); } } } From 94cdd4d609b1f33f17205a305bd7ab334b6db8a8 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 15 May 2014 17:47:33 +1000 Subject: [PATCH 1101/1445] Qt: Use Qt's exit routine which returns exec() and allows clean exit. --- base/QtMain.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index c2048d21da..265a5ed2a9 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -56,11 +56,8 @@ std::string System_GetProperty(SystemProperty prop) { } void System_SendMessage(const char *command, const char *parameter) { - // TODO: Cleaner exit if (!strcmp(command, "finish")) { - NativeShutdown(); - net::Shutdown(); - exit(0); + qApp->exit(0); } } From e7001eb701a953c9508f5a85d40147e5f0a88f3a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 19 May 2014 23:28:11 +0200 Subject: [PATCH 1102/1445] Some input tweaks and UI utility functions --- .../henrikrydgard/libnative/InputDeviceState.java | 10 +++++++++- .../com/henrikrydgard/libnative/NativeActivity.java | 10 ++++++++++ ui/ui_screen.h | 10 ++++++++++ ui/viewgroup.h | 12 ++++++------ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/InputDeviceState.java b/android/src/com/henrikrydgard/libnative/InputDeviceState.java index 6b0a7db1cb..b798261c3f 100644 --- a/android/src/com/henrikrydgard/libnative/InputDeviceState.java +++ b/android/src/com/henrikrydgard/libnative/InputDeviceState.java @@ -20,6 +20,11 @@ public class InputDeviceState { InputDevice getDevice() { return mDevice; } + @TargetApi(19) + void logAdvanced(InputDevice device) { + Log.i(TAG, "Vendor ID:" + device.getVendorId() + " productId: " + device.getProductId()); + } + public InputDeviceState(InputDevice device) { mDevice = device; int numAxes = 0; @@ -39,6 +44,10 @@ public class InputDeviceState { } Log.i(TAG, "Registering input device with " + numAxes + " axes: " + device.getName()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + logAdvanced(device); + } + NativeApp.sendMessage("inputDeviceConnected", device.getName()); } public static float ProcessAxis(InputDevice.MotionRange range, float axisvalue) { @@ -84,7 +93,6 @@ public class InputDeviceState { NativeApp.joystickAxis(deviceId, axisId, value); } NativeApp.endJoystickEvent(); - return true; } } diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index eee41a517a..c60ebb8f6f 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -122,6 +122,7 @@ public class NativeActivity extends Activity { // Actually this is not entirely true, see the code. InputDeviceState inputPlayerA; InputDeviceState inputPlayerB; + InputDeviceState inputPlayerC; String inputPlayerADesc; // Functions for the app activity to override to change behaviour. @@ -501,6 +502,15 @@ public class NativeActivity extends Activity { return inputPlayerB; } + if (inputPlayerC == null) { + Log.i(TAG, "Input player C registered"); + inputPlayerC = new InputDeviceState(device); + } + + if (inputPlayerC.getDevice() == device) { + return inputPlayerC; + } + return inputPlayerA; } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index d586bc8915..a8547798fe 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -76,8 +76,18 @@ public: ListPopupScreen(std::string title, const std::vector &items, int selected, std::function callback, bool showButtons = false) : PopupScreen(title, "OK", "Cancel"), adaptor_(items, selected), callback_(callback), showButtons_(showButtons) { } + ListPopupScreen(std::string title, const std::vector &items, int selected, bool showButtons = false) + : PopupScreen(title, "OK", "Cancel"), adaptor_(items, selected), showButtons_(showButtons) { + } + int GetChoice() const { + return listView_->GetSelected(); + } + std::string GetChoiceString() const { + return adaptor_.GetTitle(listView_->GetSelected()); + } UI::Event OnChoice; + virtual std::string tag() const override { return std::string("listpopup"); } protected: virtual bool FillVertical() const { return false; } diff --git a/ui/viewgroup.h b/ui/viewgroup.h index e5d98141f1..309114dc92 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -320,7 +320,7 @@ public: virtual View *CreateItemView(int index) = 0; virtual int GetNumItems() = 0; virtual bool AddEventCallback(View *view, std::function callback) { return false; } - virtual std::string GetTitle(int index) { return ""; } + virtual std::string GetTitle(int index) const { return ""; } virtual void SetSelected(int sel) { } virtual int GetSelected() { return -1; } }; @@ -343,12 +343,12 @@ class StringVectorListAdaptor : public ListAdaptor { public: StringVectorListAdaptor() : selected_(-1) {} StringVectorListAdaptor(const std::vector &items, int selected = -1) : items_(items), selected_(selected) {} - virtual View *CreateItemView(int index); - virtual int GetNumItems() { return (int)items_.size(); } - virtual bool AddEventCallback(View *view, std::function callback); + virtual View *CreateItemView(int index) override; + virtual int GetNumItems() override { return (int)items_.size(); } + virtual bool AddEventCallback(View *view, std::function callback) override; void SetSelected(int sel) { selected_ = sel; } - virtual std::string GetTitle(int index) { return items_[index]; } - virtual int GetSelected() { return selected_; } + virtual std::string GetTitle(int index) const override { return items_[index]; } + virtual int GetSelected() override { return selected_; } private: std::vector items_; From 4a5519689377f3468ed58d909de22ecb4a6e108c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 20 May 2014 10:22:21 +0200 Subject: [PATCH 1103/1445] "Support" override on Symbian (kill it with a #define) --- base/basictypes.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/base/basictypes.h b/base/basictypes.h index 19a9657e26..60209e517e 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -118,3 +118,8 @@ inline uint64 swap64(const uint8* _pData) {return swap64(*(const uint64*)_pData) #ifndef _TCHAR_DEFINED typedef char TCHAR; #endif + +// Workaround for Symbian's old GCC +#ifdef __SYMBIAN32__ +#define override +#endif // __SYMBIAN32__ From 60fbaad601a45172e2479b7a66bd12a904d4bd0a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 21 May 2014 07:44:32 -0700 Subject: [PATCH 1104/1445] Avoid using override in GCC < 4.7. Travis has some non-Symbian builds using 4.6.3 and they are failing. --- base/basictypes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/basictypes.h b/base/basictypes.h index 60209e517e..c9180108ae 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -120,6 +120,6 @@ typedef char TCHAR; #endif // Workaround for Symbian's old GCC -#ifdef __SYMBIAN32__ +#if defined(__GNUC__) && (__cplusplus < 201103 || (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) < 40700) #define override -#endif // __SYMBIAN32__ +#endif // defined(__GNUC__) && (__cplusplus < 201103 || (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) < 40700) From 3beac9c9b987f01ad87bdba5c8525bef5dff2fd4 Mon Sep 17 00:00:00 2001 From: Andrey Konoplyankin Date: Sun, 25 May 2014 13:50:39 +0700 Subject: [PATCH 1105/1445] iOS: add GLES 3.0 support --- gfx/gl_common.h | 7 ++----- gfx_es2/gl3stub.c | 7 ++++++- gfx_es2/gl3stub.h | 4 ++++ gfx_es2/gl_state.cpp | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index ea1358e107..6a188d2f79 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -3,13 +3,10 @@ #if defined(USING_GLES2) #ifdef IOS -#ifdef MAY_HAVE_GLES3 +#define MAY_HAVE_GLES3 1 #include #include -#else -#include -#include -#endif // MAY_HAVE_GLES3 +#include "../gfx_es2/gl3stub.h" #else #include #include diff --git a/gfx_es2/gl3stub.c b/gfx_es2/gl3stub.c index dd47a49e75..3188c0aa03 100644 --- a/gfx_es2/gl3stub.c +++ b/gfx_es2/gl3stub.c @@ -14,13 +14,14 @@ * limitations under the License. */ -#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) +#if !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) #include "../gfx/gl_common.h" #if defined(USING_GLES2) GLboolean gl3stubInit() { +#if !defined(IOS) #define FIND_PROC(s) s = (void*)eglGetProcAddress(#s) FIND_PROC(glReadBuffer); FIND_PROC(glDrawRangeElements); @@ -128,6 +129,7 @@ GLboolean gl3stubInit() { FIND_PROC(glGetInternalformativ); #undef FIND_PROC +#endif // IOS if (!glReadBuffer || !glDrawRangeElements || !glTexImage3D || @@ -239,6 +241,8 @@ GLboolean gl3stubInit() { return GL_TRUE; } +#if !defined(IOS) + /* Function pointer definitions */ GL_APICALL void (* GL_APIENTRY glReadBuffer) (GLenum mode); GL_APICALL void (* GL_APIENTRY glDrawRangeElements) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices); @@ -345,5 +349,6 @@ GL_APICALL void (* GL_APIENTRY glTexStorage2D) (GLenum target, GLsizei GL_APICALL void (* GL_APIENTRY glTexStorage3D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); +#endif // IOS #endif #endif diff --git a/gfx_es2/gl3stub.h b/gfx_es2/gl3stub.h index 2cfb91a7da..cc68270fa3 100644 --- a/gfx_es2/gl3stub.h +++ b/gfx_es2/gl3stub.h @@ -46,6 +46,8 @@ extern "C" { * otherwise. */ GLboolean gl3stubInit(); +#if !defined(IOS) + /*------------------------------------------------------------------------- * Data type definitions *-----------------------------------------------------------------------*/ @@ -482,6 +484,8 @@ extern GL_APICALL void (* GL_APIENTRY glInvalidateSubFramebuffer) (GLe extern GL_APICALL void (* GL_APIENTRY glTexStorage2D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); extern GL_APICALL void (* GL_APIENTRY glTexStorage3D) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); extern GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); + +#endif // IOS #ifdef __cplusplus } diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 885bbe45a0..ddfa3daaf8 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -216,7 +216,7 @@ void CheckGLExtensions() { #ifdef USING_GLES2 gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0; - gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0; + gl_extensions.OES_packed_depth_stencil = (strstr(extString, "GL_OES_packed_depth_stencil") != 0) || gl_extensions.GLES3; gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; From 522e1c1c841e0e54793df9585d1efb67a3206881 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 29 May 2014 12:12:50 +1000 Subject: [PATCH 1106/1445] Fix GLES2 SDL builds. --- base/PCMain.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index de634fc2e9..245b8f8a2b 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -443,20 +443,19 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); +#ifdef USING_GLES2 + mode = SDL_SWSURFACE | SDL_FULLSCREEN; +#else + mode = SDL_OPENGL | SDL_RESIZABLE; +#endif + int set_xres = -1; + int set_yres = -1; + bool portrait = false; + bool set_ipad = false; int mode; float set_dpi = 1.0f; float set_scale = 1.0f; -#ifdef USING_GLES2 - mode = SDL_SWSURFACE | SDL_FULLSCREEN; - int set_xres = -1; - int set_yres = -1; -#else - mode = SDL_OPENGL | SDL_RESIZABLE; - int set_xres = -1; - int set_yres = -1; - int set_ipad = 0; - bool portrait = false; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) mode |= SDL_FULLSCREEN; @@ -480,11 +479,11 @@ int main(int argc, char *argv[]) { set_scale = -2; if (!strcmp(argv[i],"--ipad")) - set_ipad = 1; + set_ipad = true; if (!strcmp(argv[i],"--portrait")) portrait = true; } -#endif + if (mode & SDL_FULLSCREEN) { const SDL_VideoInfo* info = SDL_GetVideoInfo(); pixel_xres = info->current_w; From 6ac56d8f7636e005a3771c576f64d95d907b1ad4 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 29 May 2014 12:37:04 +1000 Subject: [PATCH 1107/1445] Support all 'other' GLES platforms. Keep ifdefs consistent between gl_common and gl3 stub. --- gfx/gl_common.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 6a188d2f79..ad2c1a662a 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -3,10 +3,8 @@ #if defined(USING_GLES2) #ifdef IOS -#define MAY_HAVE_GLES3 1 #include #include -#include "../gfx_es2/gl3stub.h" #else #include #include @@ -14,12 +12,12 @@ #include #endif // !MAEMO #endif // IOS -#if defined(ANDROID) || defined(BLACKBERRY) +#if !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) // Support OpenGL ES 3.0 // This uses the "DYNAMIC" approach from the gles3jni NDK sample. -// Should work on non-Android mobile platforms too. -#include "../gfx_es2/gl3stub.h" +// Should work on desktop and non-Android mobile platforms too. #define MAY_HAVE_GLES3 1 +#include "../gfx_es2/gl3stub.h" #endif #else // OpenGL // Now that glew is upgraded beyond 4.3, we can define MAY_HAVE_GLES3 on GL platforms From 935165ca69eb399e66ef3da4e94344f475e281eb Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 31 May 2014 01:21:43 +1000 Subject: [PATCH 1108/1445] SDL: Make the code more platform-agnostic and cleaner. --- base/PCMain.cpp | 102 ++++++++++++++++------------------------ gfx/gl_common.h | 4 +- gfx_es2/draw_buffer.cpp | 2 - 3 files changed, 42 insertions(+), 66 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 245b8f8a2b..c043b1406c 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -1,6 +1,7 @@ // SDL/EGL implementation of the framework. // This is quite messy due to platform-specific implementations and #ifdef's. -// It is suggested to use the Qt implementation instead. +// Note: SDL1.2 implementation is deprecated and will soon be replaced by SDL2.0. +// If your platform is not supported, it is suggested to use Qt instead. #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -8,17 +9,19 @@ #include #include #include -#include "SDL.h" -#include "SDL_timer.h" -#include "SDL_audio.h" -#include "SDL_video.h" #else #include #include +#endif + #include "SDL.h" #include "SDL_timer.h" #include "SDL_audio.h" #include "SDL_video.h" +#ifndef _WIN32 +#include "SDL/SDLJoystick.h" +//SDL_Joystick *ljoy = NULL; +//SDL_Joystick *rjoy = NULL; #endif #ifdef RPI @@ -38,10 +41,6 @@ #include "util/const_map.h" #include "math/math_util.h" -#ifndef _WIN32 -#include "SDL/SDLJoystick.h" -#endif - #ifdef PPSSPP // Bad: PPSSPP includes from native #include "Core/Core.h" @@ -50,15 +49,14 @@ GlobalUIState lastUIState = UISTATE_MENU; #endif -static SDL_Surface* g_Screen = NULL; +static SDL_Surface* g_Screen = NULL; static bool g_ToggleFullScreenNextFrame = false; static int g_QuitRequested = 0; static int g_DesktopWidth = 0; static int g_DesktopHeight = 0; -#if defined(MAEMO) || defined(PANDORA) -#define EGL +#if defined(USING_EGL) #include "EGL/egl.h" #include #include @@ -104,8 +102,8 @@ int8_t CheckEGLErrors(const std::string& file, uint16_t line) { } int8_t EGL_Open() { -#ifdef PANDORA - g_Display = EGL_DEFAULT_DISPLAY; +#ifdef USING_FBDEV + g_Display = ((EGLNativeDisplayType)0); #else if ((g_Display = XOpenDisplay(NULL)) == NULL) EGL_ERROR("Unable to get display!", false); @@ -121,7 +119,8 @@ int8_t EGL_Init() { EGLConfig g_eglConfig; EGLint g_numConfigs = 0; EGLint attrib_list[]= { -#ifdef PANDORA + // TODO: Should cycle through fallbacks, like on Android +#ifdef USING_FBDEV EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, @@ -152,7 +151,7 @@ int8_t EGL_Init() { return 1; } -#ifdef PANDORA +#ifdef USING_FBDEV g_Window = (NativeWindowType)NULL; #else g_Window = (NativeWindowType)sysInfo.info.x11.window; @@ -186,16 +185,6 @@ void EGL_Close() { g_eglSurface = NULL; g_eglContext = NULL; } -#else -#endif - -#ifdef PANDORA -SDL_Joystick *ljoy = NULL; -SDL_Joystick *rjoy = NULL; -#else -#ifndef _WIN32 -SDLJoystick *joystick = NULL; -#endif #endif // Simple implementations of System functions @@ -327,19 +316,19 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_rstick_x = 0; input->pad_rstick_y = 0; -#ifdef PANDORA +/*#ifndef _WIN32 if (ljoy || rjoy) { SDL_JoystickUpdate(); if (ljoy) { - input->pad_lstick_x = max(min(SDL_JoystickGetAxis(ljoy, 0) / 32000.0f, 1.0f), -1.0f); - input->pad_lstick_y = max(min(-SDL_JoystickGetAxis(ljoy, 1) / 32000.0f, 1.0f), -1.0f); + input->pad_lstick_x = std::max(std::min(SDL_JoystickGetAxis(ljoy, 0) / 32000.0f, 1.0f), -1.0f); + input->pad_lstick_y = std::max(std::min(-SDL_JoystickGetAxis(ljoy, 1) / 32000.0f, 1.0f), -1.0f); } if (rjoy) { - input->pad_rstick_x = max(min(SDL_JoystickGetAxis(rjoy, 0) / 32000.0f, 1.0f), -1.0f); - input->pad_rstick_y = max(min(SDL_JoystickGetAxis(rjoy, 1) / 32000.0f, 1.0f), -1.0f); + input->pad_rstick_x = std::max(std::min(SDL_JoystickGetAxis(rjoy, 0) / 32000.0f, 1.0f), -1.0f); + input->pad_rstick_y = std::max(std::min(SDL_JoystickGetAxis(rjoy, 1) / 32000.0f, 1.0f), -1.0f); } } -#endif +#endif*/ } extern void mixaudio(void *userdata, Uint8 *stream, int len) { @@ -400,11 +389,7 @@ int main(int argc, char *argv[]) { #ifdef RPI bcm_host_init(); #endif - - // Avoid warning about conversion from const char * to char * - char envTemp[256]; - strcpy(envTemp, "SDL_VIDEO_CENTERED=1"); - putenv(envTemp); + putenv((char*)"SDL_VIDEO_CENTERED=1"); std::string app_name; std::string app_name_nice; @@ -425,7 +410,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } -#ifdef EGL +#ifdef USING_EGL if (EGL_Open()) return 1; #endif @@ -443,6 +428,7 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); + int mode; #ifdef USING_GLES2 mode = SDL_SWSURFACE | SDL_FULLSCREEN; #else @@ -452,7 +438,6 @@ int main(int argc, char *argv[]) { int set_yres = -1; bool portrait = false; bool set_ipad = false; - int mode; float set_dpi = 1.0f; float set_scale = 1.0f; @@ -534,7 +519,7 @@ int main(int argc, char *argv[]) { return 2; } -#ifdef EGL +#ifdef USING_EGL EGL_Init(); #endif @@ -542,7 +527,7 @@ int main(int argc, char *argv[]) { SDL_WM_SetCaption((app_name_nice + " " + PPSSPP_GIT_VERSION).c_str(), NULL); #endif -#ifdef MAEMO +#ifdef MOBILE_DEVICE SDL_ShowCursor(SDL_DISABLE); #endif @@ -625,18 +610,14 @@ int main(int argc, char *argv[]) { // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); -#ifdef PANDORA - int numjoys = SDL_NumJoysticks(); - // Joysticks init, we the nubs if setup as Joystick +#ifndef _WIN32 +/* int numjoys = SDL_NumJoysticks(); + // Joysticks init if (numjoys > 0) { ljoy = SDL_JoystickOpen(0); if (numjoys > 1) rjoy = SDL_JoystickOpen(1); - } -#else -#ifndef _WIN32 - joystick = new SDLJoystick(); -#endif + }*/ #endif EnableFZ(); @@ -806,9 +787,6 @@ int main(int argc, char *argv[]) { } break; default: -#ifndef _WIN32 - joystick->ProcessInput(event); -#endif break; } } @@ -822,7 +800,7 @@ int main(int argc, char *argv[]) { if (g_QuitRequested) break; NativeRender(); -#if defined(PPSSPP) && !defined(MAEMO) +#if defined(PPSSPP) && !defined(MOBILE_DEVICE) if (lastUIState != globalUIState) { lastUIState = globalUIState; if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) @@ -838,7 +816,7 @@ int main(int argc, char *argv[]) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } -#ifdef EGL +#ifdef USING_EGL eglSwapBuffers(g_eglDisplay, g_eglSurface); #else if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) @@ -853,22 +831,22 @@ int main(int argc, char *argv[]) { t = time_now(); framecount++; } -#ifndef PANDORA -#ifndef _WIN32 - delete joystick; - joystick = NULL; -#endif -#endif +/*#ifndef _WIN32 + if (ljoy) + delete ljoy; + if (rjoy) + delete rjoy; +#endif*/ // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though -#ifdef _WIN32 +#ifndef MOBILE_DEVICE exit(0); #endif NativeShutdownGraphics(); SDL_PauseAudio(1); SDL_CloseAudio(); NativeShutdown(); -#ifdef EGL +#ifdef USING_EGL EGL_Close(); #endif SDL_Quit(); diff --git a/gfx/gl_common.h b/gfx/gl_common.h index ad2c1a662a..2ee89033fa 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -8,9 +8,9 @@ #else #include #include -#ifndef MAEMO +#ifndef USING_EGL #include -#endif // !MAEMO +#endif // !USING_EGL #endif // IOS #if !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) // Support OpenGL ES 3.0 diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index bb296760fa..a71f8751bc 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -1,8 +1,6 @@ #include #include -#ifdef PANDORA #include -#endif #include "base/display.h" #include "base/logging.h" From ad57c494296c8a2d1cbbe4b169a9ee71e1691e0a Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 31 May 2014 01:29:00 +1000 Subject: [PATCH 1109/1445] SDL: Enable up to 2 joysticks for everyone. --- base/PCMain.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index c043b1406c..63dec38a87 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -20,8 +20,8 @@ #include "SDL_video.h" #ifndef _WIN32 #include "SDL/SDLJoystick.h" -//SDL_Joystick *ljoy = NULL; -//SDL_Joystick *rjoy = NULL; +SDL_Joystick *ljoy = NULL; +SDL_Joystick *rjoy = NULL; #endif #ifdef RPI @@ -316,7 +316,7 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_rstick_x = 0; input->pad_rstick_y = 0; -/*#ifndef _WIN32 +#ifndef _WIN32 if (ljoy || rjoy) { SDL_JoystickUpdate(); if (ljoy) { @@ -328,7 +328,7 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_rstick_y = std::max(std::min(SDL_JoystickGetAxis(rjoy, 1) / 32000.0f, 1.0f), -1.0f); } } -#endif*/ +#endif } extern void mixaudio(void *userdata, Uint8 *stream, int len) { @@ -611,13 +611,13 @@ int main(int argc, char *argv[]) { // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); #ifndef _WIN32 -/* int numjoys = SDL_NumJoysticks(); + int numjoys = SDL_NumJoysticks(); // Joysticks init if (numjoys > 0) { ljoy = SDL_JoystickOpen(0); if (numjoys > 1) rjoy = SDL_JoystickOpen(1); - }*/ + } #endif EnableFZ(); @@ -831,12 +831,12 @@ int main(int argc, char *argv[]) { t = time_now(); framecount++; } -/*#ifndef _WIN32 +#ifndef _WIN32 if (ljoy) delete ljoy; if (rjoy) delete rjoy; -#endif*/ +#endif // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though #ifndef MOBILE_DEVICE From e6afd98d84aac1a1b7e29cc86e6b433dd95388b4 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 31 May 2014 04:04:06 +1000 Subject: [PATCH 1110/1445] More cleanup for GL --- gfx/gl_common.h | 39 +++++++++++++++++++-------------------- gfx_es2/gl3stub.c | 5 +++-- gfx_es2/gl3stub.h | 4 +--- gfx_es2/gl_state.h | 2 +- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 2ee89033fa..f98f03e3ae 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -1,27 +1,18 @@ -#ifndef _GL_COMMON_H -#define _GL_COMMON_H +#pragma once -#if defined(USING_GLES2) #ifdef IOS #include #include -#else +#elif defined(USING_GLES2) #include #include -#ifndef USING_EGL -#include -#endif // !USING_EGL -#endif // IOS -#if !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) -// Support OpenGL ES 3.0 -// This uses the "DYNAMIC" approach from the gles3jni NDK sample. -// Should work on desktop and non-Android mobile platforms too. -#define MAY_HAVE_GLES3 1 -#include "../gfx_es2/gl3stub.h" -#endif +#include // TODO: Does Maemo like this? +#include +// At least Nokia platforms (Symbian/Maemo/Meego) need the three below? +#include +typedef char GLchar; +#define GL_BGRA_EXT 0x80E1 #else // OpenGL -// Now that glew is upgraded beyond 4.3, we can define MAY_HAVE_GLES3 on GL platforms -#define MAY_HAVE_GLES3 1 #include #if defined(__APPLE__) #include @@ -30,8 +21,16 @@ #endif #endif -#if !defined(GLchar) && !defined(__APPLE__) -typedef char GLchar; +// Gets 'undefined reference' if enabled +#if !defined(__SYMBIAN32__) && !defined(MAEMO) && !defined(MEEGO_EDITION_HARMATTAN) + +#ifdef USING_GLES2 +// Support OpenGL ES 3.0 +// This uses the "DYNAMIC" approach from the gles3jni NDK sample. +#include "../gfx_es2/gl3stub.h" #endif -#endif //_GL_COMMON_H +// Now that glew is upgraded beyond 4.3, we can define MAY_HAVE_GLES3 on GL platforms +#define MAY_HAVE_GLES3 1 + +#endif diff --git a/gfx_es2/gl3stub.c b/gfx_es2/gl3stub.c index 3188c0aa03..c1cd9ecdfc 100644 --- a/gfx_es2/gl3stub.c +++ b/gfx_es2/gl3stub.c @@ -19,7 +19,6 @@ #include "../gfx/gl_common.h" #if defined(USING_GLES2) - GLboolean gl3stubInit() { #if !defined(IOS) #define FIND_PROC(s) s = (void*)eglGetProcAddress(#s) @@ -241,6 +240,8 @@ GLboolean gl3stubInit() { return GL_TRUE; } +#endif + #if !defined(IOS) /* Function pointer definitions */ @@ -350,5 +351,5 @@ GL_APICALL void (* GL_APIENTRY glTexStorage3D) (GLenum target, GLsizei GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); #endif // IOS -#endif + #endif diff --git a/gfx_es2/gl3stub.h b/gfx_es2/gl3stub.h index cc68270fa3..8082484bdf 100644 --- a/gfx_es2/gl3stub.h +++ b/gfx_es2/gl3stub.h @@ -1,5 +1,4 @@ -#ifndef __gl3_h_ -#define __gl3_h_ +#pragma once /* * stub gl3.h for dynamic loading, based on: @@ -493,4 +492,3 @@ extern GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum t #endif // USING_GLES2 -#endif diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index b8419e95c2..cfb28c013d 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -30,7 +30,7 @@ extern PFNGLMAPBUFFERPROC glMapBuffer; #endif -#if !defined(IOS) && !defined(MAEMO) && !defined(__SYMBIAN__) +#if !defined(IOS) typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV; typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum From 39d48a7e67db693ec7c34a1c0121546c521bfebe Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 31 May 2014 04:37:31 +1000 Subject: [PATCH 1111/1445] Switch to libpng17 to resolve NEON issue on iOS + other bug fixes. --- ext/libpng16/pnglibconf.h | 453 - ext/libpng16/pngstruct.h | 489 - ext/libpng17/arm/arm_init.c | 133 + ext/libpng17/arm/filter_neon.S | 246 + ext/libpng17/arm/filter_neon_intrinsics.c | 372 + ext/{libpng16 => libpng17}/png.c | 8708 +++++++++--------- ext/{libpng16 => libpng17}/png.h | 6670 +++++++------- ext/{libpng16 => libpng17}/pngconf.h | 1269 +-- ext/{libpng16 => libpng17}/pngdebug.h | 311 +- ext/{libpng16 => libpng17}/pngerror.c | 1903 ++-- ext/{libpng16 => libpng17}/pngget.c | 2376 ++--- ext/{libpng16 => libpng17}/pnginfo.h | 520 +- ext/libpng17/pnglibconf.h | 210 + ext/{libpng16 => libpng17}/pngmem.c | 538 +- ext/{libpng16 => libpng17}/pngpread.c | 2583 +++--- ext/{libpng16 => libpng17}/pngpriv.h | 3895 ++++---- ext/{libpng16 => libpng17}/pngread.c | 8098 ++++++++--------- ext/{libpng16 => libpng17}/pngrio.c | 238 +- ext/{libpng16 => libpng17}/pngrtran.c | 9995 ++++++++++----------- ext/{libpng16 => libpng17}/pngrutil.c | 8925 +++++++++--------- ext/{libpng16 => libpng17}/pngset.c | 3238 +++---- ext/libpng17/pngstruct.h | 560 ++ ext/{libpng16 => libpng17}/pngtest.c | 3967 ++++---- ext/{libpng16 => libpng17}/pngtrans.c | 1684 ++-- ext/{libpng16 => libpng17}/pngwio.c | 332 +- ext/{libpng16 => libpng17}/pngwrite.c | 4752 +++++----- ext/{libpng16 => libpng17}/pngwtran.c | 1209 ++- ext/{libpng16 => libpng17}/pngwutil.c | 6085 ++++++------- gfx_es2/gl3stub.c | 3 +- image/png_load.cpp | 2 +- 30 files changed, 40179 insertions(+), 39585 deletions(-) delete mode 100644 ext/libpng16/pnglibconf.h delete mode 100644 ext/libpng16/pngstruct.h create mode 100644 ext/libpng17/arm/arm_init.c create mode 100644 ext/libpng17/arm/filter_neon.S create mode 100644 ext/libpng17/arm/filter_neon_intrinsics.c rename ext/{libpng16 => libpng17}/png.c (88%) rename ext/{libpng16 => libpng17}/png.h (90%) rename ext/{libpng16 => libpng17}/pngconf.h (91%) rename ext/{libpng16 => libpng17}/pngdebug.h (84%) rename ext/{libpng16 => libpng17}/pngerror.c (94%) rename ext/{libpng16 => libpng17}/pngget.c (95%) rename ext/{libpng16 => libpng17}/pnginfo.h (97%) create mode 100644 ext/libpng17/pnglibconf.h rename ext/{libpng16 => libpng17}/pngmem.c (84%) rename ext/{libpng16 => libpng17}/pngpread.c (95%) rename ext/{libpng16 => libpng17}/pngpriv.h (84%) rename ext/{libpng16 => libpng17}/pngread.c (92%) rename ext/{libpng16 => libpng17}/pngrio.c (94%) rename ext/{libpng16 => libpng17}/pngrtran.c (80%) rename ext/{libpng16 => libpng17}/pngrutil.c (94%) rename ext/{libpng16 => libpng17}/pngset.c (91%) create mode 100644 ext/libpng17/pngstruct.h rename ext/{libpng16 => libpng17}/pngtest.c (94%) rename ext/{libpng16 => libpng17}/pngtrans.c (95%) rename ext/{libpng16 => libpng17}/pngwio.c (95%) rename ext/{libpng16 => libpng17}/pngwrite.c (89%) rename ext/{libpng16 => libpng17}/pngwtran.c (84%) rename ext/{libpng16 => libpng17}/pngwutil.c (94%) diff --git a/ext/libpng16/pnglibconf.h b/ext/libpng16/pnglibconf.h deleted file mode 100644 index fe85ac58fb..0000000000 --- a/ext/libpng16/pnglibconf.h +++ /dev/null @@ -1,453 +0,0 @@ -/* pnglibconf.h - library build configuration */ - -/* libpng version 1.6.2 - April 25, 2013 */ - -/* Copyright (c) 1998-2012 Glenn Randers-Pehrson */ - -/* This code is released under the libpng license. */ -/* For conditions of distribution and use, see the disclaimer */ -/* and license in png.h */ - -/* pnglibconf.h */ -/* Machine generated file: DO NOT EDIT */ -/* Derived from: scripts/pnglibconf.dfa */ -#ifndef PNGLCONF_H -#define PNGLCONF_H -/* options */ -#define PNG_16BIT_SUPPORTED -#define PNG_ALIGNED_MEMORY_SUPPORTED -/*#undef PNG_ARM_NEON_API_SUPPORTED -#undef PNG_ARM_NEON_CHECK_SUPPORTED -#undef PNG_ARM_NEON_SUPPORTED*/ -#define PNG_BENIGN_ERRORS_SUPPORTED -#define PNG_BENIGN_READ_ERRORS_SUPPORTED -/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ -#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED -#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED -#define PNG_COLORSPACE_SUPPORTED -#define PNG_CONSOLE_IO_SUPPORTED -#define PNG_CONVERT_tIME_SUPPORTED -#define PNG_EASY_ACCESS_SUPPORTED -/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ -#define PNG_ERROR_TEXT_SUPPORTED -#define PNG_FIXED_POINT_SUPPORTED -#define PNG_FLOATING_ARITHMETIC_SUPPORTED -#define PNG_FLOATING_POINT_SUPPORTED -#define PNG_FORMAT_AFIRST_SUPPORTED -#define PNG_FORMAT_BGR_SUPPORTED -#define PNG_GAMMA_SUPPORTED -#define PNG_GET_PALETTE_MAX_SUPPORTED -#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -#define PNG_INCH_CONVERSIONS_SUPPORTED -#define PNG_INFO_IMAGE_SUPPORTED -#define PNG_IO_STATE_SUPPORTED -#define PNG_MNG_FEATURES_SUPPORTED -#define PNG_POINTER_INDEXING_SUPPORTED -#define PNG_PROGRESSIVE_READ_SUPPORTED -#define PNG_READ_16BIT_SUPPORTED -#define PNG_READ_ALPHA_MODE_SUPPORTED -#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_READ_BACKGROUND_SUPPORTED -#define PNG_READ_BGR_SUPPORTED -#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED -#define PNG_READ_COMPOSITE_NODIV_SUPPORTED -#define PNG_READ_COMPRESSED_TEXT_SUPPORTED -#define PNG_READ_EXPAND_16_SUPPORTED -#define PNG_READ_EXPAND_SUPPORTED -#define PNG_READ_FILLER_SUPPORTED -#define PNG_READ_GAMMA_SUPPORTED -#define PNG_READ_GET_PALETTE_MAX_SUPPORTED -#define PNG_READ_GRAY_TO_RGB_SUPPORTED -#define PNG_READ_INTERLACING_SUPPORTED -#define PNG_READ_INT_FUNCTIONS_SUPPORTED -#define PNG_READ_INVERT_ALPHA_SUPPORTED -#define PNG_READ_INVERT_SUPPORTED -#define PNG_READ_OPT_PLTE_SUPPORTED -#define PNG_READ_PACKSWAP_SUPPORTED -#define PNG_READ_PACK_SUPPORTED -#define PNG_READ_QUANTIZE_SUPPORTED -#define PNG_READ_RGB_TO_GRAY_SUPPORTED -#define PNG_READ_SCALE_16_TO_8_SUPPORTED -#define PNG_READ_SHIFT_SUPPORTED -#define PNG_READ_STRIP_16_TO_8_SUPPORTED -#define PNG_READ_STRIP_ALPHA_SUPPORTED -#define PNG_READ_SUPPORTED -#define PNG_READ_SWAP_ALPHA_SUPPORTED -#define PNG_READ_SWAP_SUPPORTED -#define PNG_READ_TEXT_SUPPORTED -#define PNG_READ_TRANSFORMS_SUPPORTED -#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_READ_USER_CHUNKS_SUPPORTED -#define PNG_READ_USER_TRANSFORM_SUPPORTED -#define PNG_READ_bKGD_SUPPORTED -#define PNG_READ_cHRM_SUPPORTED -#define PNG_READ_gAMA_SUPPORTED -#define PNG_READ_hIST_SUPPORTED -#define PNG_READ_iCCP_SUPPORTED -#define PNG_READ_iTXt_SUPPORTED -#define PNG_READ_oFFs_SUPPORTED -#define PNG_READ_pCAL_SUPPORTED -#define PNG_READ_pHYs_SUPPORTED -#define PNG_READ_sBIT_SUPPORTED -#define PNG_READ_sCAL_SUPPORTED -#define PNG_READ_sPLT_SUPPORTED -#define PNG_READ_sRGB_SUPPORTED -#define PNG_READ_tEXt_SUPPORTED -#define PNG_READ_tIME_SUPPORTED -#define PNG_READ_tRNS_SUPPORTED -#define PNG_READ_zTXt_SUPPORTED -/*#undef PNG_SAFE_LIMITS_SUPPORTED*/ -#define PNG_SAVE_INT_32_SUPPORTED -#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_SEQUENTIAL_READ_SUPPORTED -#define PNG_SETJMP_SUPPORTED -#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -/*#undef PNG_SET_OPTION_SUPPORTED*/ -#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_SET_USER_LIMITS_SUPPORTED -#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED -#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED -#define PNG_SIMPLIFIED_READ_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_SUPPORTED -#define PNG_STDIO_SUPPORTED -#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_TEXT_SUPPORTED -#define PNG_TIME_RFC1123_SUPPORTED -#define PNG_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_USER_CHUNKS_SUPPORTED -#define PNG_USER_LIMITS_SUPPORTED -#define PNG_USER_MEM_SUPPORTED -#define PNG_USER_TRANSFORM_INFO_SUPPORTED -#define PNG_USER_TRANSFORM_PTR_SUPPORTED -#define PNG_WARNINGS_SUPPORTED -#define PNG_WRITE_16BIT_SUPPORTED -#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_WRITE_BGR_SUPPORTED -#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED -#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED -#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED -#define PNG_WRITE_FILLER_SUPPORTED -#define PNG_WRITE_FILTER_SUPPORTED -#define PNG_WRITE_FLUSH_SUPPORTED -#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED -#define PNG_WRITE_INTERLACING_SUPPORTED -#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED -#define PNG_WRITE_INVERT_ALPHA_SUPPORTED -#define PNG_WRITE_INVERT_SUPPORTED -#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED -#define PNG_WRITE_PACKSWAP_SUPPORTED -#define PNG_WRITE_PACK_SUPPORTED -#define PNG_WRITE_SHIFT_SUPPORTED -#define PNG_WRITE_SUPPORTED -#define PNG_WRITE_SWAP_ALPHA_SUPPORTED -#define PNG_WRITE_SWAP_SUPPORTED -#define PNG_WRITE_TEXT_SUPPORTED -#define PNG_WRITE_TRANSFORMS_SUPPORTED -#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_WRITE_USER_TRANSFORM_SUPPORTED -#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#define PNG_WRITE_bKGD_SUPPORTED -#define PNG_WRITE_cHRM_SUPPORTED -#define PNG_WRITE_gAMA_SUPPORTED -#define PNG_WRITE_hIST_SUPPORTED -#define PNG_WRITE_iCCP_SUPPORTED -#define PNG_WRITE_iTXt_SUPPORTED -#define PNG_WRITE_oFFs_SUPPORTED -#define PNG_WRITE_pCAL_SUPPORTED -#define PNG_WRITE_pHYs_SUPPORTED -#define PNG_WRITE_sBIT_SUPPORTED -#define PNG_WRITE_sCAL_SUPPORTED -#define PNG_WRITE_sPLT_SUPPORTED -#define PNG_WRITE_sRGB_SUPPORTED -#define PNG_WRITE_tEXt_SUPPORTED -#define PNG_WRITE_tIME_SUPPORTED -#define PNG_WRITE_tRNS_SUPPORTED -#define PNG_WRITE_zTXt_SUPPORTED -#define PNG_bKGD_SUPPORTED -#define PNG_cHRM_SUPPORTED -#define PNG_gAMA_SUPPORTED -#define PNG_hIST_SUPPORTED -#define PNG_iCCP_SUPPORTED -#define PNG_iTXt_SUPPORTED -#define PNG_oFFs_SUPPORTED -#define PNG_pCAL_SUPPORTED -#define PNG_pHYs_SUPPORTED -#define PNG_sBIT_SUPPORTED -#define PNG_sCAL_SUPPORTED -#define PNG_sPLT_SUPPORTED -#define PNG_sRGB_SUPPORTED -#define PNG_tEXt_SUPPORTED -#define PNG_tIME_SUPPORTED -#define PNG_tRNS_SUPPORTED -#define PNG_zTXt_SUPPORTED -/* end of options */ -/* settings */ -#define PNG_API_RULE 0 -#define PNG_CALLOC_SUPPORTED -#define PNG_COST_SHIFT 3 -#define PNG_DEFAULT_READ_MACROS 1 -#define PNG_GAMMA_THRESHOLD_FIXED 5000 -#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE -#define PNG_INFLATE_BUF_SIZE 1024 -#define PNG_MAX_GAMMA_8 11 -#define PNG_PREFIX png16_ -#define PNG_QUANTIZE_BLUE_BITS 5 -#define PNG_QUANTIZE_GREEN_BITS 5 -#define PNG_QUANTIZE_RED_BITS 5 -#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) -#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 -#define PNG_WEIGHT_SHIFT 8 -#define PNG_ZBUF_SIZE 8192 -#define PNG_Z_DEFAULT_COMPRESSION (-1) -#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 -#define PNG_Z_DEFAULT_STRATEGY 1 -#define PNG_sCAL_PRECISION 5 -#define PNG_sRGB_PROFILE_CHECKS 2 -/* end of settings */ -#define png_access_version_number png16_png_access_version_number -#define png_benign_error png16_png_benign_error -#define png_build_grayscale_palette png16_png_build_grayscale_palette -#define png_calloc png16_png_calloc -#define png_chunk_benign_error png16_png_chunk_benign_error -#define png_chunk_error png16_png_chunk_error -#define png_chunk_warning png16_png_chunk_warning -#define png_convert_from_struct_tm png16_png_convert_from_struct_tm -#define png_convert_from_time_t png16_png_convert_from_time_t -#define png_convert_to_rfc1123 png16_png_convert_to_rfc1123 -#define png_convert_to_rfc1123_buffer png16_png_convert_to_rfc1123_buffer -#define png_create_info_struct png16_png_create_info_struct -#define png_create_read_struct png16_png_create_read_struct -#define png_create_read_struct_2 png16_png_create_read_struct_2 -#define png_create_write_struct png16_png_create_write_struct -#define png_create_write_struct_2 png16_png_create_write_struct_2 -#define png_data_freer png16_png_data_freer -#define png_destroy_info_struct png16_png_destroy_info_struct -#define png_destroy_read_struct png16_png_destroy_read_struct -#define png_destroy_write_struct png16_png_destroy_write_struct -#define png_error png16_png_error -#define png_free png16_png_free -#define png_free_data png16_png_free_data -#define png_free_default png16_png_free_default -#define png_get_IHDR png16_png_get_IHDR -#define png_get_PLTE png16_png_get_PLTE -#define png_get_bKGD png16_png_get_bKGD -#define png_get_bit_depth png16_png_get_bit_depth -#define png_get_cHRM png16_png_get_cHRM -#define png_get_cHRM_XYZ png16_png_get_cHRM_XYZ -#define png_get_cHRM_XYZ_fixed png16_png_get_cHRM_XYZ_fixed -#define png_get_cHRM_fixed png16_png_get_cHRM_fixed -#define png_get_channels png16_png_get_channels -#define png_get_chunk_cache_max png16_png_get_chunk_cache_max -#define png_get_chunk_malloc_max png16_png_get_chunk_malloc_max -#define png_get_color_type png16_png_get_color_type -#define png_get_compression_buffer_size png16_png_get_compression_buffer_size -#define png_get_compression_type png16_png_get_compression_type -#define png_get_copyright png16_png_get_copyright -#define png_get_current_pass_number png16_png_get_current_pass_number -#define png_get_current_row_number png16_png_get_current_row_number -#define png_get_error_ptr png16_png_get_error_ptr -#define png_get_filter_type png16_png_get_filter_type -#define png_get_gAMA png16_png_get_gAMA -#define png_get_gAMA_fixed png16_png_get_gAMA_fixed -#define png_get_hIST png16_png_get_hIST -#define png_get_header_ver png16_png_get_header_ver -#define png_get_header_version png16_png_get_header_version -#define png_get_iCCP png16_png_get_iCCP -#define png_get_image_height png16_png_get_image_height -#define png_get_image_width png16_png_get_image_width -#define png_get_int_32 png16_png_get_int_32 -#define png_get_interlace_type png16_png_get_interlace_type -#define png_get_io_chunk_type png16_png_get_io_chunk_type -#define png_get_io_ptr png16_png_get_io_ptr -#define png_get_io_state png16_png_get_io_state -#define png_get_libpng_ver png16_png_get_libpng_ver -#define png_get_mem_ptr png16_png_get_mem_ptr -#define png_get_oFFs png16_png_get_oFFs -#define png_get_pCAL png16_png_get_pCAL -#define png_get_pHYs png16_png_get_pHYs -#define png_get_pHYs_dpi png16_png_get_pHYs_dpi -#define png_get_palette_max png16_png_get_palette_max -#define png_get_pixel_aspect_ratio png16_png_get_pixel_aspect_ratio -#define png_get_pixel_aspect_ratio_fixed png16_png_get_pixel_aspect_ratio_fixed -#define png_get_pixels_per_inch png16_png_get_pixels_per_inch -#define png_get_pixels_per_meter png16_png_get_pixels_per_meter -#define png_get_progressive_ptr png16_png_get_progressive_ptr -#define png_get_rgb_to_gray_status png16_png_get_rgb_to_gray_status -#define png_get_rowbytes png16_png_get_rowbytes -#define png_get_rows png16_png_get_rows -#define png_get_sBIT png16_png_get_sBIT -#define png_get_sCAL png16_png_get_sCAL -#define png_get_sCAL_fixed png16_png_get_sCAL_fixed -#define png_get_sCAL_s png16_png_get_sCAL_s -#define png_get_sPLT png16_png_get_sPLT -#define png_get_sRGB png16_png_get_sRGB -#define png_get_signature png16_png_get_signature -#define png_get_tIME png16_png_get_tIME -#define png_get_tRNS png16_png_get_tRNS -#define png_get_text png16_png_get_text -#define png_get_uint_16 png16_png_get_uint_16 -#define png_get_uint_31 png16_png_get_uint_31 -#define png_get_uint_32 png16_png_get_uint_32 -#define png_get_unknown_chunks png16_png_get_unknown_chunks -#define png_get_user_chunk_ptr png16_png_get_user_chunk_ptr -#define png_get_user_height_max png16_png_get_user_height_max -#define png_get_user_transform_ptr png16_png_get_user_transform_ptr -#define png_get_user_width_max png16_png_get_user_width_max -#define png_get_valid png16_png_get_valid -#define png_get_x_offset_inches png16_png_get_x_offset_inches -#define png_get_x_offset_inches_fixed png16_png_get_x_offset_inches_fixed -#define png_get_x_offset_microns png16_png_get_x_offset_microns -#define png_get_x_offset_pixels png16_png_get_x_offset_pixels -#define png_get_x_pixels_per_inch png16_png_get_x_pixels_per_inch -#define png_get_x_pixels_per_meter png16_png_get_x_pixels_per_meter -#define png_get_y_offset_inches png16_png_get_y_offset_inches -#define png_get_y_offset_inches_fixed png16_png_get_y_offset_inches_fixed -#define png_get_y_offset_microns png16_png_get_y_offset_microns -#define png_get_y_offset_pixels png16_png_get_y_offset_pixels -#define png_get_y_pixels_per_inch png16_png_get_y_pixels_per_inch -#define png_get_y_pixels_per_meter png16_png_get_y_pixels_per_meter -#define png_handle_as_unknown png16_png_handle_as_unknown -#define png_image_begin_read_from_file png16_png_image_begin_read_from_file -#define png_image_begin_read_from_memory png16_png_image_begin_read_from_memory -#define png_image_begin_read_from_stdio png16_png_image_begin_read_from_stdio -#define png_image_finish_read png16_png_image_finish_read -#define png_image_free png16_png_image_free -#define png_image_write_to_file png16_png_image_write_to_file -#define png_image_write_to_stdio png16_png_image_write_to_stdio -#define png_info_init_3 png16_png_info_init_3 -#define png_init_io png16_png_init_io -#define png_longjmp png16_png_longjmp -#define png_malloc png16_png_malloc -#define png_malloc_default png16_png_malloc_default -#define png_malloc_warn png16_png_malloc_warn -#define png_permit_mng_features png16_png_permit_mng_features -#define png_process_data png16_png_process_data -#define png_process_data_pause png16_png_process_data_pause -#define png_process_data_skip png16_png_process_data_skip -#define png_progressive_combine_row png16_png_progressive_combine_row -#define png_read_end png16_png_read_end -#define png_read_image png16_png_read_image -#define png_read_info png16_png_read_info -#define png_read_png png16_png_read_png -#define png_read_row png16_png_read_row -#define png_read_rows png16_png_read_rows -#define png_read_update_info png16_png_read_update_info -#define png_reset_zstream png16_png_reset_zstream -#define png_save_int_32 png16_png_save_int_32 -#define png_save_uint_16 png16_png_save_uint_16 -#define png_save_uint_32 png16_png_save_uint_32 -#define png_set_IHDR png16_png_set_IHDR -#define png_set_PLTE png16_png_set_PLTE -#define png_set_add_alpha png16_png_set_add_alpha -#define png_set_alpha_mode png16_png_set_alpha_mode -#define png_set_alpha_mode_fixed png16_png_set_alpha_mode_fixed -#define png_set_bKGD png16_png_set_bKGD -#define png_set_background png16_png_set_background -#define png_set_background_fixed png16_png_set_background_fixed -#define png_set_benign_errors png16_png_set_benign_errors -#define png_set_bgr png16_png_set_bgr -#define png_set_cHRM png16_png_set_cHRM -#define png_set_cHRM_XYZ png16_png_set_cHRM_XYZ -#define png_set_cHRM_XYZ_fixed png16_png_set_cHRM_XYZ_fixed -#define png_set_cHRM_fixed png16_png_set_cHRM_fixed -#define png_set_check_for_invalid_index png16_png_set_check_for_invalid_index -#define png_set_chunk_cache_max png16_png_set_chunk_cache_max -#define png_set_chunk_malloc_max png16_png_set_chunk_malloc_max -#define png_set_compression_buffer_size png16_png_set_compression_buffer_size -#define png_set_compression_level png16_png_set_compression_level -#define png_set_compression_mem_level png16_png_set_compression_mem_level -#define png_set_compression_method png16_png_set_compression_method -#define png_set_compression_strategy png16_png_set_compression_strategy -#define png_set_compression_window_bits png16_png_set_compression_window_bits -#define png_set_crc_action png16_png_set_crc_action -#define png_set_error_fn png16_png_set_error_fn -#define png_set_expand png16_png_set_expand -#define png_set_expand_16 png16_png_set_expand_16 -#define png_set_expand_gray_1_2_4_to_8 png16_png_set_expand_gray_1_2_4_to_8 -#define png_set_filler png16_png_set_filler -#define png_set_filter png16_png_set_filter -#define png_set_filter_heuristics png16_png_set_filter_heuristics -#define png_set_filter_heuristics_fixed png16_png_set_filter_heuristics_fixed -#define png_set_flush png16_png_set_flush -#define png_set_gAMA png16_png_set_gAMA -#define png_set_gAMA_fixed png16_png_set_gAMA_fixed -#define png_set_gamma png16_png_set_gamma -#define png_set_gamma_fixed png16_png_set_gamma_fixed -#define png_set_gray_to_rgb png16_png_set_gray_to_rgb -#define png_set_hIST png16_png_set_hIST -#define png_set_iCCP png16_png_set_iCCP -#define png_set_interlace_handling png16_png_set_interlace_handling -#define png_set_invalid png16_png_set_invalid -#define png_set_invert_alpha png16_png_set_invert_alpha -#define png_set_invert_mono png16_png_set_invert_mono -#define png_set_keep_unknown_chunks png16_png_set_keep_unknown_chunks -#define png_set_longjmp_fn png16_png_set_longjmp_fn -#define png_set_mem_fn png16_png_set_mem_fn -#define png_set_oFFs png16_png_set_oFFs -#define png_set_pCAL png16_png_set_pCAL -#define png_set_pHYs png16_png_set_pHYs -#define png_set_packing png16_png_set_packing -#define png_set_packswap png16_png_set_packswap -#define png_set_palette_to_rgb png16_png_set_palette_to_rgb -#define png_set_progressive_read_fn png16_png_set_progressive_read_fn -#define png_set_quantize png16_png_set_quantize -#define png_set_read_fn png16_png_set_read_fn -#define png_set_read_status_fn png16_png_set_read_status_fn -#define png_set_read_user_chunk_fn png16_png_set_read_user_chunk_fn -#define png_set_read_user_transform_fn png16_png_set_read_user_transform_fn -#define png_set_rgb_to_gray png16_png_set_rgb_to_gray -#define png_set_rgb_to_gray_fixed png16_png_set_rgb_to_gray_fixed -#define png_set_rows png16_png_set_rows -#define png_set_sBIT png16_png_set_sBIT -#define png_set_sCAL png16_png_set_sCAL -#define png_set_sCAL_fixed png16_png_set_sCAL_fixed -#define png_set_sCAL_s png16_png_set_sCAL_s -#define png_set_sPLT png16_png_set_sPLT -#define png_set_sRGB png16_png_set_sRGB -#define png_set_sRGB_gAMA_and_cHRM png16_png_set_sRGB_gAMA_and_cHRM -#define png_set_scale_16 png16_png_set_scale_16 -#define png_set_shift png16_png_set_shift -#define png_set_sig_bytes png16_png_set_sig_bytes -#define png_set_strip_16 png16_png_set_strip_16 -#define png_set_strip_alpha png16_png_set_strip_alpha -#define png_set_swap png16_png_set_swap -#define png_set_swap_alpha png16_png_set_swap_alpha -#define png_set_tIME png16_png_set_tIME -#define png_set_tRNS png16_png_set_tRNS -#define png_set_tRNS_to_alpha png16_png_set_tRNS_to_alpha -#define png_set_text png16_png_set_text -#define png_set_text_compression_level png16_png_set_text_compression_level -#define png_set_text_compression_mem_level png16_png_set_text_compression_mem_level -#define png_set_text_compression_method png16_png_set_text_compression_method -#define png_set_text_compression_strategy png16_png_set_text_compression_strategy -#define png_set_text_compression_window_bits png16_png_set_text_compression_window_bits -#define png_set_unknown_chunk_location png16_png_set_unknown_chunk_location -#define png_set_unknown_chunks png16_png_set_unknown_chunks -#define png_set_user_limits png16_png_set_user_limits -#define png_set_user_transform_info png16_png_set_user_transform_info -#define png_set_write_fn png16_png_set_write_fn -#define png_set_write_status_fn png16_png_set_write_status_fn -#define png_set_write_user_transform_fn png16_png_set_write_user_transform_fn -#define png_sig_cmp png16_png_sig_cmp -#define png_start_read_image png16_png_start_read_image -#define png_warning png16_png_warning -#define png_write_chunk png16_png_write_chunk -#define png_write_chunk_data png16_png_write_chunk_data -#define png_write_chunk_end png16_png_write_chunk_end -#define png_write_chunk_start png16_png_write_chunk_start -#define png_write_end png16_png_write_end -#define png_write_flush png16_png_write_flush -#define png_write_image png16_png_write_image -#define png_write_info png16_png_write_info -#define png_write_info_before_PLTE png16_png_write_info_before_PLTE -#define png_write_png png16_png_write_png -#define png_write_row png16_png_write_row -#define png_write_rows png16_png_write_rows -#define png_write_sig png16_png_write_sig -#define png16_png_get_uint_32(buf) PNG_get_uint_32(buf) -#define png16_png_get_uint_16(buf) PNG_get_uint_16(buf) -#define png16_png_get_int_32(buf) PNG_get_int_32(buf) -#endif /* PNGLCONF_H */ diff --git a/ext/libpng16/pngstruct.h b/ext/libpng16/pngstruct.h deleted file mode 100644 index b6935534c5..0000000000 --- a/ext/libpng16/pngstruct.h +++ /dev/null @@ -1,489 +0,0 @@ - -/* pngstruct.h - header file for PNG reference library - * - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * Last changed in libpng 1.6.1 [March 28, 2013] - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -/* The structure that holds the information to read and write PNG files. - * The only people who need to care about what is inside of this are the - * people who will be modifying the library for their own special needs. - * It should NOT be accessed directly by an application. - */ - -#ifndef PNGSTRUCT_H -#define PNGSTRUCT_H -/* zlib.h defines the structure z_stream, an instance of which is included - * in this structure and is required for decompressing the LZ compressed - * data in PNG files. - */ -#ifndef ZLIB_CONST - /* We must ensure that zlib uses 'const' in declarations. */ -# define ZLIB_CONST -#endif -#include "zlib.h" -#ifdef const - /* zlib.h sometimes #defines const to nothing, undo this. */ -# undef const -#endif - -/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility - * with older builds. - */ -#if ZLIB_VERNUM < 0x1260 -# define PNGZ_MSG_CAST(s) png_constcast(char*,s) -# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b) -#else -# define PNGZ_MSG_CAST(s) (s) -# define PNGZ_INPUT_CAST(b) (b) -#endif - -/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib - * can handle at once. This type need be no larger than 16 bits (so maximum of - * 65535), this define allows us to discover how big it is, but limited by the - * maximuum for png_size_t. The value can be overriden in a library build - * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably - * lower value (e.g. 255 works). A lower value may help memory usage (slightly) - * and may even improve performance on some systems (and degrade it on others.) - */ -#ifndef ZLIB_IO_MAX -# define ZLIB_IO_MAX ((uInt)-1) -#endif - -#ifdef PNG_WRITE_SUPPORTED -/* The type of a compression buffer list used by the write code. */ -typedef struct png_compression_buffer -{ - struct png_compression_buffer *next; - png_byte output[1]; /* actually zbuf_size */ -} png_compression_buffer, *png_compression_bufferp; - -#define PNG_COMPRESSION_BUFFER_SIZE(pp)\ - (offsetof(png_compression_buffer, output) + (pp)->zbuffer_size) -#endif - -/* Colorspace support; structures used in png_struct, png_info and in internal - * functions to hold and communicate information about the color space. - * - * PNG_COLORSPACE_SUPPORTED is only required if the application will perform - * colorspace corrections, otherwise all the colorspace information can be - * skipped and the size of libpng can be reduced (significantly) by compiling - * out the colorspace support. - */ -#ifdef PNG_COLORSPACE_SUPPORTED -/* The chromaticities of the red, green and blue colorants and the chromaticity - * of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)). - */ -typedef struct png_xy -{ - png_fixed_point redx, redy; - png_fixed_point greenx, greeny; - png_fixed_point bluex, bluey; - png_fixed_point whitex, whitey; -} png_xy; - -/* The same data as above but encoded as CIE XYZ values. When this data comes - * from chromaticities the sum of the Y values is assumed to be 1.0 - */ -typedef struct png_XYZ -{ - png_fixed_point red_X, red_Y, red_Z; - png_fixed_point green_X, green_Y, green_Z; - png_fixed_point blue_X, blue_Y, blue_Z; -} png_XYZ; -#endif /* COLORSPACE */ - -#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) -/* A colorspace is all the above plus, potentially, profile information, - * however at present libpng does not use the profile internally so it is only - * stored in the png_info struct (if iCCP is supported.) The rendering intent - * is retained here and is checked. - * - * The file gamma encoding information is also stored here and gamma correction - * is done by libpng, whereas color correction must currently be done by the - * application. - */ -typedef struct png_colorspace -{ -#ifdef PNG_GAMMA_SUPPORTED - png_fixed_point gamma; /* File gamma */ -#endif - -#ifdef PNG_COLORSPACE_SUPPORTED - png_xy end_points_xy; /* End points as chromaticities */ - png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */ - png_uint_16 rendering_intent; /* Rendering intent of a profile */ -#endif - - /* Flags are always defined to simplify the code. */ - png_uint_16 flags; /* As defined below */ -} png_colorspace, * PNG_RESTRICT png_colorspacerp; - -typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp; - -/* General flags for the 'flags' field */ -#define PNG_COLORSPACE_HAVE_GAMMA 0x0001 -#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002 -#define PNG_COLORSPACE_HAVE_INTENT 0x0004 -#define PNG_COLORSPACE_FROM_gAMA 0x0008 -#define PNG_COLORSPACE_FROM_cHRM 0x0010 -#define PNG_COLORSPACE_FROM_sRGB 0x0020 -#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040 -#define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */ -#define PNG_COLORSPACE_INVALID 0x8000 -#define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags)) -#endif /* COLORSPACE || GAMMA */ - -struct png_struct_def -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf jmp_buf_local; /* New name in 1.6.0 for jmp_buf in png_struct */ - png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */ - jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */ - size_t jmp_buf_size; /* size of the above, if allocated */ -#endif - png_error_ptr error_fn; /* function for printing errors and aborting */ -#ifdef PNG_WARNINGS_SUPPORTED - png_error_ptr warning_fn; /* function for printing warnings */ -#endif - png_voidp error_ptr; /* user supplied struct for error functions */ - png_rw_ptr write_data_fn; /* function for writing output data */ - png_rw_ptr read_data_fn; /* function for reading input data */ - png_voidp io_ptr; /* ptr to application struct for I/O functions */ - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr read_user_transform_fn; /* user read transform */ -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr write_user_transform_fn; /* user write transform */ -#endif - -/* These were added in libpng-1.0.2 */ -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_voidp user_transform_ptr; /* user supplied struct for user transform */ - png_byte user_transform_depth; /* bit depth of user transformed pixels */ - png_byte user_transform_channels; /* channels in user transformed pixels */ -#endif -#endif - - png_uint_32 mode; /* tells us where we are in the PNG file */ - png_uint_32 flags; /* flags indicating various things to libpng */ - png_uint_32 transformations; /* which transformations to perform */ - - png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */ - z_stream zstream; /* decompression structure */ - -#ifdef PNG_WRITE_SUPPORTED - png_compression_bufferp zbuffer_list; /* Created on demand during write */ - uInt zbuffer_size; /* size of the actual buffer */ - - int zlib_level; /* holds zlib compression level */ - int zlib_method; /* holds zlib compression method */ - int zlib_window_bits; /* holds zlib compression window bits */ - int zlib_mem_level; /* holds zlib compression memory level */ - int zlib_strategy; /* holds zlib compression strategy */ -#endif -/* Added at libpng 1.5.4 */ -#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED - int zlib_text_level; /* holds zlib compression level */ - int zlib_text_method; /* holds zlib compression method */ - int zlib_text_window_bits; /* holds zlib compression window bits */ - int zlib_text_mem_level; /* holds zlib compression memory level */ - int zlib_text_strategy; /* holds zlib compression strategy */ -#endif -/* End of material added at libpng 1.5.4 */ -/* Added at libpng 1.6.0 */ -#ifdef PNG_WRITE_SUPPORTED - int zlib_set_level; /* Actual values set into the zstream on write */ - int zlib_set_method; - int zlib_set_window_bits; - int zlib_set_mem_level; - int zlib_set_strategy; -#endif - - png_uint_32 width; /* width of image in pixels */ - png_uint_32 height; /* height of image in pixels */ - png_uint_32 num_rows; /* number of rows in current pass */ - png_uint_32 usr_width; /* width of row at start of write */ - png_size_t rowbytes; /* size of row in bytes */ - png_uint_32 iwidth; /* width of current interlaced row in pixels */ - png_uint_32 row_number; /* current row in interlace pass */ - png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ - png_bytep prev_row; /* buffer to save previous (unfiltered) row. - * This is a pointer into big_prev_row - */ - png_bytep row_buf; /* buffer to save current (unfiltered) row. - * This is a pointer into big_row_buf - */ -#ifdef PNG_WRITE_SUPPORTED - png_bytep sub_row; /* buffer to save "sub" row when filtering */ - png_bytep up_row; /* buffer to save "up" row when filtering */ - png_bytep avg_row; /* buffer to save "avg" row when filtering */ - png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ -#endif - png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ - - png_uint_32 idat_size; /* current IDAT size for read */ - png_uint_32 crc; /* current chunk CRC value */ - png_colorp palette; /* palette from the input file */ - png_uint_16 num_palette; /* number of color entries in palette */ - -/* Added at libpng-1.5.10 */ -#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED - int num_palette_max; /* maximum palette index found in IDAT */ -#endif - - png_uint_16 num_trans; /* number of transparency values */ - png_byte compression; /* file compression type (always 0) */ - png_byte filter; /* file filter type (always 0) */ - png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - png_byte pass; /* current interlace pass (0 - 6) */ - png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ - png_byte color_type; /* color type of file */ - png_byte bit_depth; /* bit depth of file */ - png_byte usr_bit_depth; /* bit depth of users row: write only */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte channels; /* number of channels in file */ -#ifdef PNG_WRITE_SUPPORTED - png_byte usr_channels; /* channels at start of write: write only */ -#endif - png_byte sig_bytes; /* magic bytes read/written from start of file */ - png_byte maximum_pixel_depth; - /* pixel depth used for the row buffers */ - png_byte transformed_pixel_depth; - /* pixel depth after read/write transforms */ -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) - png_uint_16 filler; /* filler bytes for pixel expansion */ -#endif - -#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) - png_byte background_gamma_type; - png_fixed_point background_gamma; - png_color_16 background; /* background color in screen gamma space */ -#ifdef PNG_READ_GAMMA_SUPPORTED - png_color_16 background_1; /* background normalized to gamma 1.0 */ -#endif -#endif /* PNG_bKGD_SUPPORTED */ - -#ifdef PNG_WRITE_FLUSH_SUPPORTED - png_flush_ptr output_flush_fn; /* Function for flushing output */ - png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ - png_uint_32 flush_rows; /* number of rows written since last flush */ -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED - int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ - png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ - - png_bytep gamma_table; /* gamma table for 8-bit depth files */ - png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - png_bytep gamma_from_1; /* converts from 1.0 to screen */ - png_bytep gamma_to_1; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ - png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit; /* significant bits in each available channel */ -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ -#endif - -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ - || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans_alpha; /* alpha values for paletted files */ - png_color_16 trans_color; /* transparent color for non-paletted files */ -#endif - - png_read_status_ptr read_row_fn; /* called after each row is decoded */ - png_write_status_ptr write_row_fn; /* called after each row is encoded */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_progressive_info_ptr info_fn; /* called after header data fully read */ - png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */ - png_progressive_end_ptr end_fn; /* called after image is complete */ - png_bytep save_buffer_ptr; /* current location in save_buffer */ - png_bytep save_buffer; /* buffer for previously read data */ - png_bytep current_buffer_ptr; /* current location in current_buffer */ - png_bytep current_buffer; /* buffer for recently used data */ - png_uint_32 push_length; /* size of current input chunk */ - png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ - png_size_t current_buffer_size; /* amount of data now in current_buffer */ - int process_mode; /* what push library is currently doing */ - int cur_palette; /* current push library palette index */ - -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* For the Borland special 64K segment handler */ - png_bytepp offset_table_ptr; - png_bytep offset_table; - png_uint_16 offset_table_number; - png_uint_16 offset_table_count; - png_uint_16 offset_table_count_free; -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED - png_bytep palette_lookup; /* lookup table for quantizing */ - png_bytep quantize_index; /* index translation for palette files */ -#endif - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - png_byte heuristic_method; /* heuristic for row filter selection */ - png_byte num_prev_filters; /* number of weights for previous rows */ - png_bytep prev_filters; /* filter type(s) of previous row(s) */ - png_uint_16p filter_weights; /* weight(s) for previous line(s) */ - png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ - png_uint_16p filter_costs; /* relative filter calculation cost */ - png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ -#endif - - /* Options */ -#ifdef PNG_SET_OPTION_SUPPORTED - png_byte options; /* On/off state (up to 4 options) */ -#endif - -#if PNG_LIBPNG_VER < 10700 -/* To do: remove this from libpng-1.7 */ -#ifdef PNG_TIME_RFC1123_SUPPORTED - char time_buffer[29]; /* String to hold RFC 1123 time text */ -#endif -#endif - -/* New members added in libpng-1.0.6 */ - - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ - -#ifdef PNG_USER_CHUNKS_SUPPORTED - png_voidp user_chunk_ptr; -#ifdef PNG_READ_USER_CHUNKS_SUPPORTED - png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ -#endif -#endif - -#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - int unknown_default; /* As PNG_HANDLE_* */ - unsigned int num_chunk_list; /* Number of entries in the list */ - png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name - * followed by a PNG_HANDLE_* byte */ -#endif - -/* New members added in libpng-1.0.3 */ -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - png_byte rgb_to_gray_status; - /* Added in libpng 1.5.5 to record setting of coefficients: */ - png_byte rgb_to_gray_coefficients_set; - /* These were changed from png_byte in libpng-1.0.6 */ - png_uint_16 rgb_to_gray_red_coeff; - png_uint_16 rgb_to_gray_green_coeff; - /* deleted in 1.5.5: rgb_to_gray_blue_coeff; */ -#endif - -/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) -/* Changed from png_byte to png_uint_32 at version 1.2.0 */ - png_uint_32 mng_features_permitted; -#endif - -/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ -#ifdef PNG_MNG_FEATURES_SUPPORTED - png_byte filter_type; -#endif - -/* New members added in libpng-1.2.0 */ - -/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ -#ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr; /* user supplied struct for mem functions */ - png_malloc_ptr malloc_fn; /* function for allocating memory */ - png_free_ptr free_fn; /* function for freeing memory */ -#endif - -/* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep quantize_sort; /* working sort array */ - png_bytep index_to_palette; /* where the original index currently is - in the palette */ - png_bytep palette_to_index; /* which original index points to this - palette color */ -#endif - -/* New members added in libpng-1.0.16 and 1.2.6 */ - png_byte compression_type; - -#ifdef PNG_USER_LIMITS_SUPPORTED - png_uint_32 user_width_max; - png_uint_32 user_height_max; - - /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown - * chunks that can be stored (0 means unlimited). - */ - png_uint_32 user_chunk_cache_max; - - /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk - * can occupy when decompressed. 0 means unlimited. - */ - png_alloc_size_t user_chunk_malloc_max; -#endif - -/* New member added in libpng-1.0.25 and 1.2.17 */ -#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED - /* Temporary storage for unknown chunk that the library doesn't recognize, - * used while reading the chunk. - */ - png_unknown_chunk unknown_chunk; -#endif - -/* New member added in libpng-1.2.26 */ - png_size_t old_big_row_buf_size; - -#ifdef PNG_READ_SUPPORTED -/* New member added in libpng-1.2.30 */ - png_bytep read_buffer; /* buffer for reading chunk data */ - png_alloc_size_t read_buffer_size; /* current size of the buffer */ -#endif -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED - uInt IDAT_read_size; /* limit on read buffer size for IDAT */ -#endif - -#ifdef PNG_IO_STATE_SUPPORTED -/* New member added in libpng-1.4.0 */ - png_uint_32 io_state; -#endif - -/* New member added in libpng-1.5.6 */ - png_bytep big_prev_row; - -/* New member added in libpng-1.5.7 */ - void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, - png_bytep row, png_const_bytep prev_row); - -#ifdef PNG_READ_SUPPORTED -#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) - png_colorspace colorspace; -#endif -#endif -}; -#endif /* PNGSTRUCT_H */ diff --git a/ext/libpng17/arm/arm_init.c b/ext/libpng17/arm/arm_init.c new file mode 100644 index 0000000000..a672eaebb5 --- /dev/null +++ b/ext/libpng17/arm/arm_init.c @@ -0,0 +1,133 @@ + +/* arm_init.c - NEON optimised filter functions + * + * Copyright (c) 2014 Glenn Randers-Pehrson + * Written by Mans Rullgard, 2011. + * Last changed in libpng 1.6.10 [(PENDING RELEASE)] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ +/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are + * called. + */ +#define _POSIX_SOURCE 1 + +#include "../pngpriv.h" + +#ifdef PNG_READ_SUPPORTED +#if PNG_ARM_NEON_OPT > 0 +#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */ +/* WARNING: it is strongly recommended that you do not build libpng with + * run-time checks for CPU features if at all possible. In the case of the ARM + * NEON instructions there is no processor-specific way of detecting the + * presence of the required support, therefore run-time detection is extremely + * OS specific. + * + * You may set the macro PNG_ARM_NEON_FILE to the file name of file containing + * a fragment of C source code which defines the png_have_neon function. There + * are a number of implementations in contrib/arm-neon, but the only one that + * has partial support is contrib/arm-neon/linux.c - a generic Linux + * implementation which reads /proc/cpufino. + */ +#ifndef PNG_ARM_NEON_FILE +# ifdef __linux__ +# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c" +# endif +#endif + +#ifdef PNG_ARM_NEON_FILE + +#include /* for sig_atomic_t */ +static int png_have_neon(png_structp png_ptr); +#include PNG_ARM_NEON_FILE + +#else /* PNG_ARM_NEON_FILE */ +# error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks" +#endif /* PNG_ARM_NEON_FILE */ +#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */ + +#ifndef PNG_ALIGNED_MEMORY_SUPPORTED +# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED" +#endif + +void +png_init_filter_functions_neon(png_structp pp, unsigned int bpp) +{ + /* The switch statement is compiled in for ARM_NEON_API, the call to + * png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined + * the check is only performed if the API has not set the NEON option on + * or off explicitly. In this case the check controls what happens. + * + * If the CHECK is not compiled in and the option is UNSET the behavior prior + * to 1.6.7 was to use the NEON code - this was a bug caused by having the + * wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF, + * as documented in png.h + */ +#ifdef PNG_ARM_NEON_API_SUPPORTED + switch ((pp->options >> PNG_ARM_NEON) & 3) + { + case PNG_OPTION_UNSET: + /* Allow the run-time check to execute if it has been enabled - + * thus both API and CHECK can be turned on. If it isn't supported + * this case will fall through to the 'default' below, which just + * returns. + */ +#endif /* PNG_ARM_NEON_API_SUPPORTED */ +#ifdef PNG_ARM_NEON_CHECK_SUPPORTED + { + static volatile sig_atomic_t no_neon = -1; /* not checked */ + + if (no_neon < 0) + no_neon = !png_have_neon(pp); + + if (no_neon) + return; + } +#ifdef PNG_ARM_NEON_API_SUPPORTED + break; +#endif +#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */ + +#ifdef PNG_ARM_NEON_API_SUPPORTED + default: /* OFF or INVALID */ + return; + + case PNG_OPTION_ON: + /* Option turned on */ + break; + } +#endif + + /* IMPORTANT: any new external functions used here must be declared using + * PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the + * 'prefix' option to configure works: + * + * ./configure --with-libpng-prefix=foobar_ + * + * Verify you have got this right by running the above command, doing a build + * and examining pngprefix.h; it must contain a #define for every external + * function you add. (Notice that this happens automatically for the + * initialization function.) + */ + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon; + + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth3_neon; + } + + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth4_neon; + } +} +#endif /* PNG_ARM_NEON_OPT > 0 */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/ext/libpng17/arm/filter_neon.S b/ext/libpng17/arm/filter_neon.S new file mode 100644 index 0000000000..40d97775d6 --- /dev/null +++ b/ext/libpng17/arm/filter_neon.S @@ -0,0 +1,246 @@ + +/* filter_neon.S - NEON optimised filter functions + * + * Copyright (c) 2013 Glenn Randers-Pehrson + * Written by Mans Rullgard, 2011. + * Last changed in libpng 1.6.8 [December 19, 2013] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* This is required to get the symbol renames, which are #defines, and also + * includes the definition (or not) of PNG_ARM_NEON_OPT and + * PNG_ARM_NEON_IMPLEMENTATION. + */ +#define PNG_VERSION_INFO_ONLY +#include "../pngpriv.h" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */ +#endif + +/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for + * ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it + * only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h + * for the logic which sets PNG_USE_ARM_NEON_ASM: + */ +#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */ + +#ifdef PNG_READ_SUPPORTED +#if PNG_ARM_NEON_OPT > 0 + +#ifdef __ELF__ +# define ELF +#else +# define ELF @ +#endif + + .arch armv7-a + .fpu neon + +.macro func name, export=0 + .macro endfunc +ELF .size \name, . - \name + .endfunc + .purgem endfunc + .endm + .text + .if \export + .global \name + .endif +ELF .type \name, STT_FUNC + .func \name +\name: +.endm + +func png_read_filter_row_sub4_neon, export=1 + ldr r3, [r0, #4] @ rowbytes + vmov.i8 d3, #0 +1: + vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] + vadd.u8 d0, d3, d4 + vadd.u8 d1, d0, d5 + vadd.u8 d2, d1, d6 + vadd.u8 d3, d2, d7 + vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! + subs r3, r3, #16 + bgt 1b + + bx lr +endfunc + +func png_read_filter_row_sub3_neon, export=1 + ldr r3, [r0, #4] @ rowbytes + vmov.i8 d3, #0 + mov r0, r1 + mov r2, #3 + mov r12, #12 + vld1.8 {q11}, [r0], r12 +1: + vext.8 d5, d22, d23, #3 + vadd.u8 d0, d3, d22 + vext.8 d6, d22, d23, #6 + vadd.u8 d1, d0, d5 + vext.8 d7, d23, d23, #1 + vld1.8 {q11}, [r0], r12 + vst1.32 {d0[0]}, [r1,:32], r2 + vadd.u8 d2, d1, d6 + vst1.32 {d1[0]}, [r1], r2 + vadd.u8 d3, d2, d7 + vst1.32 {d2[0]}, [r1], r2 + vst1.32 {d3[0]}, [r1], r2 + subs r3, r3, #12 + bgt 1b + + bx lr +endfunc + +func png_read_filter_row_up_neon, export=1 + ldr r3, [r0, #4] @ rowbytes +1: + vld1.8 {q0}, [r1,:128] + vld1.8 {q1}, [r2,:128]! + vadd.u8 q0, q0, q1 + vst1.8 {q0}, [r1,:128]! + subs r3, r3, #16 + bgt 1b + + bx lr +endfunc + +func png_read_filter_row_avg4_neon, export=1 + ldr r12, [r0, #4] @ rowbytes + vmov.i8 d3, #0 +1: + vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] + vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]! + vhadd.u8 d0, d3, d16 + vadd.u8 d0, d0, d4 + vhadd.u8 d1, d0, d17 + vadd.u8 d1, d1, d5 + vhadd.u8 d2, d1, d18 + vadd.u8 d2, d2, d6 + vhadd.u8 d3, d2, d19 + vadd.u8 d3, d3, d7 + vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! + subs r12, r12, #16 + bgt 1b + + bx lr +endfunc + +func png_read_filter_row_avg3_neon, export=1 + push {r4,lr} + ldr r12, [r0, #4] @ rowbytes + vmov.i8 d3, #0 + mov r0, r1 + mov r4, #3 + mov lr, #12 + vld1.8 {q11}, [r0], lr +1: + vld1.8 {q10}, [r2], lr + vext.8 d5, d22, d23, #3 + vhadd.u8 d0, d3, d20 + vext.8 d17, d20, d21, #3 + vadd.u8 d0, d0, d22 + vext.8 d6, d22, d23, #6 + vhadd.u8 d1, d0, d17 + vext.8 d18, d20, d21, #6 + vadd.u8 d1, d1, d5 + vext.8 d7, d23, d23, #1 + vld1.8 {q11}, [r0], lr + vst1.32 {d0[0]}, [r1,:32], r4 + vhadd.u8 d2, d1, d18 + vst1.32 {d1[0]}, [r1], r4 + vext.8 d19, d21, d21, #1 + vadd.u8 d2, d2, d6 + vhadd.u8 d3, d2, d19 + vst1.32 {d2[0]}, [r1], r4 + vadd.u8 d3, d3, d7 + vst1.32 {d3[0]}, [r1], r4 + subs r12, r12, #12 + bgt 1b + + pop {r4,pc} +endfunc + +.macro paeth rx, ra, rb, rc + vaddl.u8 q12, \ra, \rb @ a + b + vaddl.u8 q15, \rc, \rc @ 2*c + vabdl.u8 q13, \rb, \rc @ pa + vabdl.u8 q14, \ra, \rc @ pb + vabd.u16 q15, q12, q15 @ pc + vcle.u16 q12, q13, q14 @ pa <= pb + vcle.u16 q13, q13, q15 @ pa <= pc + vcle.u16 q14, q14, q15 @ pb <= pc + vand q12, q12, q13 @ pa <= pb && pa <= pc + vmovn.u16 d28, q14 + vmovn.u16 \rx, q12 + vbsl d28, \rb, \rc + vbsl \rx, \ra, d28 +.endm + +func png_read_filter_row_paeth4_neon, export=1 + ldr r12, [r0, #4] @ rowbytes + vmov.i8 d3, #0 + vmov.i8 d20, #0 +1: + vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] + vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]! + paeth d0, d3, d16, d20 + vadd.u8 d0, d0, d4 + paeth d1, d0, d17, d16 + vadd.u8 d1, d1, d5 + paeth d2, d1, d18, d17 + vadd.u8 d2, d2, d6 + paeth d3, d2, d19, d18 + vmov d20, d19 + vadd.u8 d3, d3, d7 + vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! + subs r12, r12, #16 + bgt 1b + + bx lr +endfunc + +func png_read_filter_row_paeth3_neon, export=1 + push {r4,lr} + ldr r12, [r0, #4] @ rowbytes + vmov.i8 d3, #0 + vmov.i8 d4, #0 + mov r0, r1 + mov r4, #3 + mov lr, #12 + vld1.8 {q11}, [r0], lr +1: + vld1.8 {q10}, [r2], lr + paeth d0, d3, d20, d4 + vext.8 d5, d22, d23, #3 + vadd.u8 d0, d0, d22 + vext.8 d17, d20, d21, #3 + paeth d1, d0, d17, d20 + vst1.32 {d0[0]}, [r1,:32], r4 + vext.8 d6, d22, d23, #6 + vadd.u8 d1, d1, d5 + vext.8 d18, d20, d21, #6 + paeth d2, d1, d18, d17 + vext.8 d7, d23, d23, #1 + vld1.8 {q11}, [r0], lr + vst1.32 {d1[0]}, [r1], r4 + vadd.u8 d2, d2, d6 + vext.8 d19, d21, d21, #1 + paeth d3, d2, d19, d18 + vst1.32 {d2[0]}, [r1], r4 + vmov d4, d19 + vadd.u8 d3, d3, d7 + vst1.32 {d3[0]}, [r1], r4 + subs r12, r12, #12 + bgt 1b + + pop {r4,pc} +endfunc +#endif /* PNG_ARM_NEON_OPT > 0 */ +#endif /* PNG_READ_SUPPORTED */ +#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */ diff --git a/ext/libpng17/arm/filter_neon_intrinsics.c b/ext/libpng17/arm/filter_neon_intrinsics.c new file mode 100644 index 0000000000..e7a09f4364 --- /dev/null +++ b/ext/libpng17/arm/filter_neon_intrinsics.c @@ -0,0 +1,372 @@ + +/* filter_neon_intrinsics.c - NEON optimised filter functions + * + * Copyright (c) 2013 Glenn Randers-Pehrson + * Written by James Yu , October 2013. + * Based on filter_neon.S, written by Mans Rullgard, 2011. + * + * Last changed in libpng 1.6.8 [December 19, 2013] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "../pngpriv.h" + +/* This code requires -mfpu=neon on the command line: */ +#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */ + +#include + +/* libpng row pointers are not necessarily aligned to any particular boundary, + * however this code will only work with appropriate alignment. arm/arm_init.c + * checks for this (and will not compile unless it is done). This code uses + * variants of png_aligncast to avoid compiler warnings. + */ +#define png_ptr(type,pointer) png_aligncast(type *,pointer) +#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer) + +/* The following relies on a variable 'temp_pointer' being declared with type + * 'type'. This is written this way just to hide the GCC strict aliasing + * warning; note that the code is safe because there never is an alias between + * the input and output pointers. + */ +#define png_ldr(type,pointer)\ + (temp_pointer = png_ptr(type,pointer), *temp_pointer) + +#ifdef PNG_READ_SUPPORTED +#if PNG_ARM_NEON_OPT > 0 + +void +png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_bytep rp_stop = row + row_info->rowbytes; + png_const_bytep pp = prev_row; + + for (; rp < rp_stop; rp += 16, pp += 16) + { + uint8x16_t qrp, qpp; + + qrp = vld1q_u8(rp); + qpp = vld1q_u8(pp); + qrp = vaddq_u8(qrp, qpp); + vst1q_u8(rp, qrp); + } +} + +void +png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_bytep rp_stop = row + row_info->rowbytes; + + uint8x16_t vtmp = vld1q_u8(rp); + uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp); + uint8x8x2_t vrp = *vrpt; + + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + for (; rp < rp_stop;) + { + uint8x8_t vtmp1, vtmp2; + uint32x2_t *temp_pointer; + + vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3); + vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]); + vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6); + vdest.val[1] = vadd_u8(vdest.val[0], vtmp1); + + vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1); + vdest.val[2] = vadd_u8(vdest.val[1], vtmp2); + vdest.val[3] = vadd_u8(vdest.val[2], vtmp1); + + vtmp = vld1q_u8(rp + 12); + vrpt = png_ptr(uint8x8x2_t, &vtmp); + vrp = *vrpt; + + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0); + rp += 3; + } + + PNG_UNUSED(prev_row) +} + +void +png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_bytep rp_stop = row + row_info->rowbytes; + + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + for (; rp < rp_stop; rp += 16) + { + uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp)); + uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp); + uint8x8x4_t vrp = *vrpt; + uint32x2x4_t *temp_pointer; + + vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]); + vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]); + vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]); + vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]); + vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + } + + PNG_UNUSED(prev_row) +} + +void +png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_const_bytep pp = prev_row; + png_bytep rp_stop = row + row_info->rowbytes; + + uint8x16_t vtmp; + uint8x8x2_t *vrpt; + uint8x8x2_t vrp; + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + vtmp = vld1q_u8(rp); + vrpt = png_ptr(uint8x8x2_t,&vtmp); + vrp = *vrpt; + + for (; rp < rp_stop; pp += 12) + { + uint8x8_t vtmp1, vtmp2, vtmp3; + + uint8x8x2_t *vppt; + uint8x8x2_t vpp; + + uint32x2_t *temp_pointer; + + vtmp = vld1q_u8(pp); + vppt = png_ptr(uint8x8x2_t,&vtmp); + vpp = *vppt; + + vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3); + vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]); + vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]); + + vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3); + vtmp3 = vext_u8(vrp.val[0], vrp.val[1], 6); + vdest.val[1] = vhadd_u8(vdest.val[0], vtmp2); + vdest.val[1] = vadd_u8(vdest.val[1], vtmp1); + + vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 6); + vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1); + + vtmp = vld1q_u8(rp + 12); + vrpt = png_ptr(uint8x8x2_t,&vtmp); + vrp = *vrpt; + + vdest.val[2] = vhadd_u8(vdest.val[1], vtmp2); + vdest.val[2] = vadd_u8(vdest.val[2], vtmp3); + + vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1); + + vdest.val[3] = vhadd_u8(vdest.val[2], vtmp2); + vdest.val[3] = vadd_u8(vdest.val[3], vtmp1); + + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0); + rp += 3; + } +} + +void +png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_bytep rp_stop = row + row_info->rowbytes; + png_const_bytep pp = prev_row; + + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + for (; rp < rp_stop; rp += 16, pp += 16) + { + uint32x2x4_t vtmp; + uint8x8x4_t *vrpt, *vppt; + uint8x8x4_t vrp, vpp; + uint32x2x4_t *temp_pointer; + + vtmp = vld4_u32(png_ptr(uint32_t,rp)); + vrpt = png_ptr(uint8x8x4_t,&vtmp); + vrp = *vrpt; + vtmp = vld4_u32(png_ptrc(uint32_t,pp)); + vppt = png_ptr(uint8x8x4_t,&vtmp); + vpp = *vppt; + + vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]); + vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]); + vdest.val[1] = vhadd_u8(vdest.val[0], vpp.val[1]); + vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]); + vdest.val[2] = vhadd_u8(vdest.val[1], vpp.val[2]); + vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]); + vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]); + vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]); + + vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + } +} + +static uint8x8_t +paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c) +{ + uint8x8_t d, e; + uint16x8_t p1, pa, pb, pc; + + p1 = vaddl_u8(a, b); /* a + b */ + pc = vaddl_u8(c, c); /* c * 2 */ + pa = vabdl_u8(b, c); /* pa */ + pb = vabdl_u8(a, c); /* pb */ + pc = vabdq_u16(p1, pc); /* pc */ + + p1 = vcleq_u16(pa, pb); /* pa <= pb */ + pa = vcleq_u16(pa, pc); /* pa <= pc */ + pb = vcleq_u16(pb, pc); /* pb <= pc */ + + p1 = vandq_u16(p1, pa); /* pa <= pb && pa <= pc */ + + d = vmovn_u16(pb); + e = vmovn_u16(p1); + + d = vbsl_u8(d, b, c); + e = vbsl_u8(e, a, d); + + return e; +} + +void +png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_const_bytep pp = prev_row; + png_bytep rp_stop = row + row_info->rowbytes; + + uint8x16_t vtmp; + uint8x8x2_t *vrpt; + uint8x8x2_t vrp; + uint8x8_t vlast = vdup_n_u8(0); + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + vtmp = vld1q_u8(rp); + vrpt = png_ptr(uint8x8x2_t,&vtmp); + vrp = *vrpt; + + for (; rp < rp_stop; pp += 12) + { + uint8x8x2_t *vppt; + uint8x8x2_t vpp; + uint8x8_t vtmp1, vtmp2, vtmp3; + uint32x2_t *temp_pointer; + + vtmp = vld1q_u8(pp); + vppt = png_ptr(uint8x8x2_t,&vtmp); + vpp = *vppt; + + vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast); + vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]); + + vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3); + vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3); + vdest.val[1] = paeth(vdest.val[0], vtmp2, vpp.val[0]); + vdest.val[1] = vadd_u8(vdest.val[1], vtmp1); + + vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 6); + vtmp3 = vext_u8(vpp.val[0], vpp.val[1], 6); + vdest.val[2] = paeth(vdest.val[1], vtmp3, vtmp2); + vdest.val[2] = vadd_u8(vdest.val[2], vtmp1); + + vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1); + vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1); + + vtmp = vld1q_u8(rp + 12); + vrpt = png_ptr(uint8x8x2_t,&vtmp); + vrp = *vrpt; + + vdest.val[3] = paeth(vdest.val[2], vtmp2, vtmp3); + vdest.val[3] = vadd_u8(vdest.val[3], vtmp1); + + vlast = vtmp2; + + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0); + rp += 3; + } +} + +void +png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_bytep rp_stop = row + row_info->rowbytes; + png_const_bytep pp = prev_row; + + uint8x8_t vlast = vdup_n_u8(0); + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + for (; rp < rp_stop; rp += 16, pp += 16) + { + uint32x2x4_t vtmp; + uint8x8x4_t *vrpt, *vppt; + uint8x8x4_t vrp, vpp; + uint32x2x4_t *temp_pointer; + + vtmp = vld4_u32(png_ptr(uint32_t,rp)); + vrpt = png_ptr(uint8x8x4_t,&vtmp); + vrp = *vrpt; + vtmp = vld4_u32(png_ptrc(uint32_t,pp)); + vppt = png_ptr(uint8x8x4_t,&vtmp); + vpp = *vppt; + + vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast); + vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]); + vdest.val[1] = paeth(vdest.val[0], vpp.val[1], vpp.val[0]); + vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]); + vdest.val[2] = paeth(vdest.val[1], vpp.val[2], vpp.val[1]); + vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]); + vdest.val[3] = paeth(vdest.val[2], vpp.val[3], vpp.val[2]); + vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]); + + vlast = vpp.val[3]; + + vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + } +} + +#endif /* PNG_ARM_NEON_OPT > 0 */ +#endif /* PNG_READ_SUPPORTED */ +#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */ diff --git a/ext/libpng16/png.c b/ext/libpng17/png.c similarity index 88% rename from ext/libpng16/png.c rename to ext/libpng17/png.c index 9a81e81648..5ce74f8417 100644 --- a/ext/libpng16/png.c +++ b/ext/libpng17/png.c @@ -1,4299 +1,4409 @@ - -/* png.c - location for general purpose libpng functions - * - * Last changed in libpng 1.6.2 [April 25, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -#include "pngpriv.h" - -/* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_7 Your_png_h_is_not_version_1_6_7; - -/* Tells libpng that we have already handled the first "num_bytes" bytes - * of the PNG file signature. If the PNG data is embedded into another - * stream we can set num_bytes = 8 so that libpng will not attempt to read - * or write any of the magic bytes before it starts on the IHDR. - */ - -#ifdef PNG_READ_SUPPORTED -void PNGAPI -png_set_sig_bytes(png_structrp png_ptr, int num_bytes) -{ - png_debug(1, "in png_set_sig_bytes"); - - if (png_ptr == NULL) - return; - - if (num_bytes > 8) - png_error(png_ptr, "Too many bytes for PNG signature"); - - png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); -} - -/* Checks whether the supplied bytes match the PNG signature. We allow - * checking less than the full 8-byte signature so that those apps that - * already read the first few bytes of a file to determine the file type - * can simply check the remaining bytes for extra assurance. Returns - * an integer less than, equal to, or greater than zero if sig is found, - * respectively, to be less than, to match, or be greater than the correct - * PNG signature (this is the same behavior as strcmp, memcmp, etc). - */ -int PNGAPI -png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) -{ - png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; - - if (num_to_check > 8) - num_to_check = 8; - - else if (num_to_check < 1) - return (-1); - - if (start > 7) - return (-1); - - if (start + num_to_check > 8) - num_to_check = 8 - start; - - return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check))); -} - -#endif /* PNG_READ_SUPPORTED */ - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -/* Function to allocate memory for zlib */ -PNG_FUNCTION(voidpf /* PRIVATE */, -png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) -{ - png_alloc_size_t num_bytes = size; - - if (png_ptr == NULL) - return NULL; - - if (items >= (~(png_alloc_size_t)0)/size) - { - png_warning (png_voidcast(png_structrp, png_ptr), - "Potential overflow in png_zalloc()"); - return NULL; - } - - num_bytes *= items; - return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes); -} - -/* Function to free memory for zlib */ -void /* PRIVATE */ -png_zfree(voidpf png_ptr, voidpf ptr) -{ - png_free(png_voidcast(png_const_structrp,png_ptr), ptr); -} - -/* Reset the CRC variable to 32 bits of 1's. Care must be taken - * in case CRC is > 32 bits to leave the top bits 0. - */ -void /* PRIVATE */ -png_reset_crc(png_structrp png_ptr) -{ - /* The cast is safe because the crc is a 32 bit value. */ - png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0); -} - -/* Calculate the CRC over a section of data. We can only pass as - * much data to this routine as the largest single buffer size. We - * also check that this data will actually be used before going to the - * trouble of calculating it. - */ -void /* PRIVATE */ -png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) -{ - int need_crc = 1; - - if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)) - { - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == - (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) - need_crc = 0; - } - - else /* critical */ - { - if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) - need_crc = 0; - } - - /* 'uLong' is defined in zlib.h as unsigned long; this means that on some - * systems it is a 64 bit value. crc32, however, returns 32 bits so the - * following cast is safe. 'uInt' may be no more than 16 bits, so it is - * necessary to perform a loop here. - */ - if (need_crc && length > 0) - { - uLong crc = png_ptr->crc; /* Should never issue a warning */ - - do - { - uInt safe_length = (uInt)length; - if (safe_length == 0) - safe_length = (uInt)-1; /* evil, but safe */ - - crc = crc32(crc, ptr, safe_length); - - /* The following should never issue compiler warnings; if they do the - * target system has characteristics that will probably violate other - * assumptions within the libpng code. - */ - ptr += safe_length; - length -= safe_length; - } - while (length > 0); - - /* And the following is always safe because the crc is only 32 bits. */ - png_ptr->crc = (png_uint_32)crc; - } -} - -/* Check a user supplied version number, called from both read and write - * functions that create a png_struct. - */ -int -png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) -{ - if (user_png_ver) - { - int i = 0; - - do - { - if (user_png_ver[i] != png_libpng_ver[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - } while (png_libpng_ver[i++]); - } - - else - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - - if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) - { - /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so - * we must recompile any applications that use any older library version. - * For versions after libpng 1.0, we will be compatible, so we need - * only check the first and third digits (note that when we reach version - * 1.10 we will need to check the fourth symbol, namely user_png_ver[3]). - */ - if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || - (user_png_ver[0] == '1' && (user_png_ver[2] != png_libpng_ver[2] || - user_png_ver[3] != png_libpng_ver[3])) || - (user_png_ver[0] == '0' && user_png_ver[2] < '9')) - { -#ifdef PNG_WARNINGS_SUPPORTED - size_t pos = 0; - char m[128]; - - pos = png_safecat(m, (sizeof m), pos, - "Application built with libpng-"); - pos = png_safecat(m, (sizeof m), pos, user_png_ver); - pos = png_safecat(m, (sizeof m), pos, " but running with "); - pos = png_safecat(m, (sizeof m), pos, png_libpng_ver); - - png_warning(png_ptr, m); -#endif - -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags = 0; -#endif - - return 0; - } - } - - /* Success return. */ - return 1; -} - -/* Generic function to create a png_struct for either read or write - this - * contains the common initialization. - */ -PNG_FUNCTION(png_structp /* PRIVATE */, -png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) -{ - png_struct create_struct; -# ifdef PNG_SETJMP_SUPPORTED - jmp_buf create_jmp_buf; -# endif - - /* This temporary stack-allocated structure is used to provide a place to - * build enough context to allow the user provided memory allocator (if any) - * to be called. - */ - memset(&create_struct, 0, (sizeof create_struct)); - - /* Added at libpng-1.2.6 */ -# ifdef PNG_USER_LIMITS_SUPPORTED - create_struct.user_width_max = PNG_USER_WIDTH_MAX; - create_struct.user_height_max = PNG_USER_HEIGHT_MAX; - -# ifdef PNG_USER_CHUNK_CACHE_MAX - /* Added at libpng-1.2.43 and 1.4.0 */ - create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; -# endif - -# ifdef PNG_USER_CHUNK_MALLOC_MAX - /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists - * in png_struct regardless. - */ - create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; -# endif -# endif - - /* The following two API calls simply set fields in png_struct, so it is safe - * to do them now even though error handling is not yet set up. - */ -# ifdef PNG_USER_MEM_SUPPORTED - png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn); -# endif - - /* (*error_fn) can return control to the caller after the error_ptr is set, - * this will result in a memory leak unless the error_fn does something - * extremely sophisticated. The design lacks merit but is implicit in the - * API. - */ - png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn); - -# ifdef PNG_SETJMP_SUPPORTED - if (!setjmp(create_jmp_buf)) - { - /* Temporarily fake out the longjmp information until we have - * successfully completed this function. This only works if we have - * setjmp() support compiled in, but it is safe - this stuff should - * never happen. - */ - create_struct.jmp_buf_ptr = &create_jmp_buf; - create_struct.jmp_buf_size = 0; /*stack allocation*/ - create_struct.longjmp_fn = longjmp; -# else - { -# endif - /* Call the general version checker (shared with read and write code): - */ - if (png_user_version_check(&create_struct, user_png_ver)) - { - png_structrp png_ptr = png_voidcast(png_structrp, - png_malloc_warn(&create_struct, (sizeof *png_ptr))); - - if (png_ptr != NULL) - { - /* png_ptr->zstream holds a back-pointer to the png_struct, so - * this can only be done now: - */ - create_struct.zstream.zalloc = png_zalloc; - create_struct.zstream.zfree = png_zfree; - create_struct.zstream.opaque = png_ptr; - -# ifdef PNG_SETJMP_SUPPORTED - /* Eliminate the local error handling: */ - create_struct.jmp_buf_ptr = NULL; - create_struct.jmp_buf_size = 0; - create_struct.longjmp_fn = 0; -# endif - - *png_ptr = create_struct; - - /* This is the successful return point */ - return png_ptr; - } - } - } - - /* A longjmp because of a bug in the application storage allocator or a - * simple failure to allocate the png_struct. - */ - return NULL; -} - -/* Allocate the memory for an info_struct for the application. */ -PNG_FUNCTION(png_infop,PNGAPI -png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED) -{ - png_inforp info_ptr; - - png_debug(1, "in png_create_info_struct"); - - if (png_ptr == NULL) - return NULL; - - /* Use the internal API that does not (or at least should not) error out, so - * that this call always returns ok. The application typically sets up the - * error handling *after* creating the info_struct because this is the way it - * has always been done in 'example.c'. - */ - info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr, - (sizeof *info_ptr))); - - if (info_ptr != NULL) - memset(info_ptr, 0, (sizeof *info_ptr)); - - return info_ptr; -} - -/* This function frees the memory associated with a single info struct. - * Normally, one would use either png_destroy_read_struct() or - * png_destroy_write_struct() to free an info struct, but this may be - * useful for some applications. From libpng 1.6.0 this function is also used - * internally to implement the png_info release part of the 'struct' destroy - * APIs. This ensures that all possible approaches free the same data (all of - * it). - */ -void PNGAPI -png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr) -{ - png_inforp info_ptr = NULL; - - png_debug(1, "in png_destroy_info_struct"); - - if (png_ptr == NULL) - return; - - if (info_ptr_ptr != NULL) - info_ptr = *info_ptr_ptr; - - if (info_ptr != NULL) - { - /* Do this first in case of an error below; if the app implements its own - * memory management this can lead to png_free calling png_error, which - * will abort this routine and return control to the app error handler. - * An infinite loop may result if it then tries to free the same info - * ptr. - */ - *info_ptr_ptr = NULL; - - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - memset(info_ptr, 0, (sizeof *info_ptr)); - png_free(png_ptr, info_ptr); - } -} - -/* Initialize the info structure. This is now an internal function (0.89) - * and applications using it are urged to use png_create_info_struct() - * instead. Use deprecated in 1.6.0, internal use removed (used internally it - * is just a memset). - * - * NOTE: it is almost inconceivable that this API is used because it bypasses - * the user-memory mechanism and the user error handling/warning mechanisms in - * those cases where it does anything other than a memset. - */ -PNG_FUNCTION(void,PNGAPI -png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), - PNG_DEPRECATED) -{ - png_inforp info_ptr = *ptr_ptr; - - png_debug(1, "in png_info_init_3"); - - if (info_ptr == NULL) - return; - - if ((sizeof (png_info)) > png_info_struct_size) - { - *ptr_ptr = NULL; - /* The following line is why this API should not be used: */ - free(info_ptr); - info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL, - (sizeof *info_ptr))); - *ptr_ptr = info_ptr; - } - - /* Set everything to 0 */ - memset(info_ptr, 0, (sizeof *info_ptr)); -} - -/* The following API is not called internally */ -void PNGAPI -png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr, - int freer, png_uint_32 mask) -{ - png_debug(1, "in png_data_freer"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (freer == PNG_DESTROY_WILL_FREE_DATA) - info_ptr->free_me |= mask; - - else if (freer == PNG_USER_WILL_FREE_DATA) - info_ptr->free_me &= ~mask; - - else - png_error(png_ptr, "Unknown freer parameter in png_data_freer"); -} - -void PNGAPI -png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, - int num) -{ - png_debug(1, "in png_free_data"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - -#ifdef PNG_TEXT_SUPPORTED - /* Free text item num or (if num == -1) all text items */ - if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) - { - if (num != -1) - { - if (info_ptr->text && info_ptr->text[num].key) - { - png_free(png_ptr, info_ptr->text[num].key); - info_ptr->text[num].key = NULL; - } - } - - else - { - int i; - for (i = 0; i < info_ptr->num_text; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); - png_free(png_ptr, info_ptr->text); - info_ptr->text = NULL; - info_ptr->num_text=0; - } - } -#endif - -#ifdef PNG_tRNS_SUPPORTED - /* Free any tRNS entry */ - if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) - { - png_free(png_ptr, info_ptr->trans_alpha); - info_ptr->trans_alpha = NULL; - info_ptr->valid &= ~PNG_INFO_tRNS; - } -#endif - -#ifdef PNG_sCAL_SUPPORTED - /* Free any sCAL entry */ - if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) - { - png_free(png_ptr, info_ptr->scal_s_width); - png_free(png_ptr, info_ptr->scal_s_height); - info_ptr->scal_s_width = NULL; - info_ptr->scal_s_height = NULL; - info_ptr->valid &= ~PNG_INFO_sCAL; - } -#endif - -#ifdef PNG_pCAL_SUPPORTED - /* Free any pCAL entry */ - if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) - { - png_free(png_ptr, info_ptr->pcal_purpose); - png_free(png_ptr, info_ptr->pcal_units); - info_ptr->pcal_purpose = NULL; - info_ptr->pcal_units = NULL; - if (info_ptr->pcal_params != NULL) - { - unsigned int i; - for (i = 0; i < info_ptr->pcal_nparams; i++) - { - png_free(png_ptr, info_ptr->pcal_params[i]); - info_ptr->pcal_params[i] = NULL; - } - png_free(png_ptr, info_ptr->pcal_params); - info_ptr->pcal_params = NULL; - } - info_ptr->valid &= ~PNG_INFO_pCAL; - } -#endif - -#ifdef PNG_iCCP_SUPPORTED - /* Free any profile entry */ - if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) - { - png_free(png_ptr, info_ptr->iccp_name); - png_free(png_ptr, info_ptr->iccp_profile); - info_ptr->iccp_name = NULL; - info_ptr->iccp_profile = NULL; - info_ptr->valid &= ~PNG_INFO_iCCP; - } -#endif - -#ifdef PNG_sPLT_SUPPORTED - /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ - if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) - { - if (num != -1) - { - if (info_ptr->splt_palettes) - { - png_free(png_ptr, info_ptr->splt_palettes[num].name); - png_free(png_ptr, info_ptr->splt_palettes[num].entries); - info_ptr->splt_palettes[num].name = NULL; - info_ptr->splt_palettes[num].entries = NULL; - } - } - - else - { - if (info_ptr->splt_palettes_num) - { - int i; - for (i = 0; i < info_ptr->splt_palettes_num; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, (int)i); - - png_free(png_ptr, info_ptr->splt_palettes); - info_ptr->splt_palettes = NULL; - info_ptr->splt_palettes_num = 0; - } - info_ptr->valid &= ~PNG_INFO_sPLT; - } - } -#endif - -#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED - if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) - { - if (num != -1) - { - if (info_ptr->unknown_chunks) - { - png_free(png_ptr, info_ptr->unknown_chunks[num].data); - info_ptr->unknown_chunks[num].data = NULL; - } - } - - else - { - int i; - - if (info_ptr->unknown_chunks_num) - { - for (i = 0; i < info_ptr->unknown_chunks_num; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, (int)i); - - png_free(png_ptr, info_ptr->unknown_chunks); - info_ptr->unknown_chunks = NULL; - info_ptr->unknown_chunks_num = 0; - } - } - } -#endif - -#ifdef PNG_hIST_SUPPORTED - /* Free any hIST entry */ - if ((mask & PNG_FREE_HIST) & info_ptr->free_me) - { - png_free(png_ptr, info_ptr->hist); - info_ptr->hist = NULL; - info_ptr->valid &= ~PNG_INFO_hIST; - } -#endif - - /* Free any PLTE entry that was internally allocated */ - if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) - { - png_free(png_ptr, info_ptr->palette); - info_ptr->palette = NULL; - info_ptr->valid &= ~PNG_INFO_PLTE; - info_ptr->num_palette = 0; - } - -#ifdef PNG_INFO_IMAGE_SUPPORTED - /* Free any image bits attached to the info structure */ - if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) - { - if (info_ptr->row_pointers) - { - png_uint_32 row; - for (row = 0; row < info_ptr->height; row++) - { - png_free(png_ptr, info_ptr->row_pointers[row]); - info_ptr->row_pointers[row] = NULL; - } - png_free(png_ptr, info_ptr->row_pointers); - info_ptr->row_pointers = NULL; - } - info_ptr->valid &= ~PNG_INFO_IDAT; - } -#endif - - if (num != -1) - mask &= ~PNG_FREE_MUL; - - info_ptr->free_me &= ~mask; -} -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ - -/* This function returns a pointer to the io_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy() or png_read_destroy() are called. - */ -png_voidp PNGAPI -png_get_io_ptr(png_const_structrp png_ptr) -{ - if (png_ptr == NULL) - return (NULL); - - return (png_ptr->io_ptr); -} - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -# ifdef PNG_STDIO_SUPPORTED -/* Initialize the default input/output functions for the PNG file. If you - * use your own read or write routines, you can call either png_set_read_fn() - * or png_set_write_fn() instead of png_init_io(). If you have defined - * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a - * function of your own because "FILE *" isn't necessarily available. - */ -void PNGAPI -png_init_io(png_structrp png_ptr, png_FILE_p fp) -{ - png_debug(1, "in png_init_io"); - - if (png_ptr == NULL) - return; - - png_ptr->io_ptr = (png_voidp)fp; -} -# endif - -#ifdef PNG_SAVE_INT_32_SUPPORTED -/* The png_save_int_32 function assumes integers are stored in two's - * complement format. If this isn't the case, then this routine needs to - * be modified to write data in two's complement format. Note that, - * the following works correctly even if png_int_32 has more than 32 bits - * (compare the more complex code required on read for sign extension.) - */ -void PNGAPI -png_save_int_32(png_bytep buf, png_int_32 i) -{ - buf[0] = (png_byte)((i >> 24) & 0xff); - buf[1] = (png_byte)((i >> 16) & 0xff); - buf[2] = (png_byte)((i >> 8) & 0xff); - buf[3] = (png_byte)(i & 0xff); -} -#endif - -# ifdef PNG_TIME_RFC1123_SUPPORTED -/* Convert the supplied time into an RFC 1123 string suitable for use in - * a "Creation Time" or other text-based time string. - */ -int PNGAPI -png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) -{ - static PNG_CONST char short_months[12][4] = - {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - - if (out == NULL) - return 0; - - if (ptime->year > 9999 /* RFC1123 limitation */ || - ptime->month == 0 || ptime->month > 12 || - ptime->day == 0 || ptime->day > 31 || - ptime->hour > 23 || ptime->minute > 59 || - ptime->second > 60) - return 0; - - { - size_t pos = 0; - char number_buf[5]; /* enough for a four-digit year */ - -# define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string)) -# define APPEND_NUMBER(format, value)\ - APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value))) -# define APPEND(ch) if (pos < 28) out[pos++] = (ch) - - APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day); - APPEND(' '); - APPEND_STRING(short_months[(ptime->month - 1)]); - APPEND(' '); - APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year); - APPEND(' '); - APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour); - APPEND(':'); - APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute); - APPEND(':'); - APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second); - APPEND_STRING(" +0000"); /* This reliably terminates the buffer */ - -# undef APPEND -# undef APPEND_NUMBER -# undef APPEND_STRING - } - - return 1; -} - -# if PNG_LIBPNG_VER < 10700 -/* To do: remove the following from libpng-1.7 */ -/* Original API that uses a private buffer in png_struct. - * Deprecated because it causes png_struct to carry a spurious temporary - * buffer (png_struct::time_buffer), better to have the caller pass this in. - */ -png_const_charp PNGAPI -png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime) -{ - if (png_ptr != NULL) - { - /* The only failure above if png_ptr != NULL is from an invalid ptime */ - if (!png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime)) - png_warning(png_ptr, "Ignoring invalid time value"); - - else - return png_ptr->time_buffer; - } - - return NULL; -} -# endif -# endif /* PNG_TIME_RFC1123_SUPPORTED */ - -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ - -png_const_charp PNGAPI -png_get_copyright(png_const_structrp png_ptr) -{ - PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ -#ifdef PNG_STRING_COPYRIGHT - return PNG_STRING_COPYRIGHT -#else -# ifdef __STDC__ - return PNG_STRING_NEWLINE \ - "libpng version 1.6.7 - November 14, 2013" PNG_STRING_NEWLINE \ - "Copyright (c) 1998-2013 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ - "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ - "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ - PNG_STRING_NEWLINE; -# else - return "libpng version 1.6.7 - November 14, 2013\ - Copyright (c) 1998-2013 Glenn Randers-Pehrson\ - Copyright (c) 1996-1997 Andreas Dilger\ - Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; -# endif -#endif -} - -/* The following return the library version as a short string in the - * format 1.0.0 through 99.99.99zz. To get the version of *.h files - * used with your application, print out PNG_LIBPNG_VER_STRING, which - * is defined in png.h. - * Note: now there is no difference between png_get_libpng_ver() and - * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, - * it is guaranteed that png.c uses the correct version of png.h. - */ -png_const_charp PNGAPI -png_get_libpng_ver(png_const_structrp png_ptr) -{ - /* Version of *.c files used when building libpng */ - return png_get_header_ver(png_ptr); -} - -png_const_charp PNGAPI -png_get_header_ver(png_const_structrp png_ptr) -{ - /* Version of *.h files used when building libpng */ - PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ - return PNG_LIBPNG_VER_STRING; -} - -png_const_charp PNGAPI -png_get_header_version(png_const_structrp png_ptr) -{ - /* Returns longer string containing both version and date */ - PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ -#ifdef __STDC__ - return PNG_HEADER_VERSION_STRING -# ifndef PNG_READ_SUPPORTED - " (NO READ SUPPORT)" -# endif - PNG_STRING_NEWLINE; -#else - return PNG_HEADER_VERSION_STRING; -#endif -} - -#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED -int PNGAPI -png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name) -{ - /* Check chunk_name and return "keep" value if it's on the list, else 0 */ - png_const_bytep p, p_end; - - if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0) - return PNG_HANDLE_CHUNK_AS_DEFAULT; - - p_end = png_ptr->chunk_list; - p = p_end + png_ptr->num_chunk_list*5; /* beyond end */ - - /* The code is the fifth byte after each four byte string. Historically this - * code was always searched from the end of the list, this is no longer - * necessary because the 'set' routine handles duplicate entries correcty. - */ - do /* num_chunk_list > 0, so at least one */ - { - p -= 5; - - if (!memcmp(chunk_name, p, 4)) - return p[4]; - } - while (p > p_end); - - /* This means that known chunks should be processed and unknown chunks should - * be handled according to the value of png_ptr->unknown_default; this can be - * confusing because, as a result, there are two levels of defaulting for - * unknown chunks. - */ - return PNG_HANDLE_CHUNK_AS_DEFAULT; -} - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\ - defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) -int /* PRIVATE */ -png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name) -{ - png_byte chunk_string[5]; - - PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name); - return png_handle_as_unknown(png_ptr, chunk_string); -} -#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */ -#endif /* SET_UNKNOWN_CHUNKS */ - -#ifdef PNG_READ_SUPPORTED -/* This function, added to libpng-1.0.6g, is untested. */ -int PNGAPI -png_reset_zstream(png_structrp png_ptr) -{ - if (png_ptr == NULL) - return Z_STREAM_ERROR; - - /* WARNING: this resets the window bits to the maximum! */ - return (inflateReset(&png_ptr->zstream)); -} -#endif /* PNG_READ_SUPPORTED */ - -/* This function was added to libpng-1.0.7 */ -png_uint_32 PNGAPI -png_access_version_number(void) -{ - /* Version of *.c files used when building libpng */ - return((png_uint_32)PNG_LIBPNG_VER); -} - - - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -/* Ensure that png_ptr->zstream.msg holds some appropriate error message string. - * If it doesn't 'ret' is used to set it to something appropriate, even in cases - * like Z_OK or Z_STREAM_END where the error code is apparently a success code. - */ -void /* PRIVATE */ -png_zstream_error(png_structrp png_ptr, int ret) -{ - /* Translate 'ret' into an appropriate error string, priority is given to the - * one in zstream if set. This always returns a string, even in cases like - * Z_OK or Z_STREAM_END where the error code is a success code. - */ - if (png_ptr->zstream.msg == NULL) switch (ret) - { - default: - case Z_OK: - png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code"); - break; - - case Z_STREAM_END: - /* Normal exit */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream"); - break; - - case Z_NEED_DICT: - /* This means the deflate stream did not have a dictionary; this - * indicates a bogus PNG. - */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary"); - break; - - case Z_ERRNO: - /* gz APIs only: should not happen */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error"); - break; - - case Z_STREAM_ERROR: - /* internal libpng error */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib"); - break; - - case Z_DATA_ERROR: - png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream"); - break; - - case Z_MEM_ERROR: - png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory"); - break; - - case Z_BUF_ERROR: - /* End of input or output; not a problem if the caller is doing - * incremental read or write. - */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated"); - break; - - case Z_VERSION_ERROR: - png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version"); - break; - - case PNG_UNEXPECTED_ZLIB_RETURN: - /* Compile errors here mean that zlib now uses the value co-opted in - * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above - * and change pngpriv.h. Note that this message is "... return", - * whereas the default/Z_OK one is "... return code". - */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return"); - break; - } -} - -/* png_convert_size: a PNGAPI but no longer in png.h, so deleted - * at libpng 1.5.5! - */ - -/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ -#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */ -static int -png_colorspace_check_gamma(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_fixed_point gAMA, int from) - /* This is called to check a new gamma value against an existing one. The - * routine returns false if the new gamma value should not be written. - * - * 'from' says where the new gamma value comes from: - * - * 0: the new gamma value is the libpng estimate for an ICC profile - * 1: the new gamma value comes from a gAMA chunk - * 2: the new gamma value comes from an sRGB chunk - */ -{ - png_fixed_point gtest; - - if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && - (!png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) || - png_gamma_significant(gtest))) - { - /* Either this is an sRGB image, in which case the calculated gamma - * approximation should match, or this is an image with a profile and the - * value libpng calculates for the gamma of the profile does not match the - * value recorded in the file. The former, sRGB, case is an error, the - * latter is just a warning. - */ - if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2) - { - png_chunk_report(png_ptr, "gamma value does not match sRGB", - PNG_CHUNK_ERROR); - /* Do not overwrite an sRGB value */ - return from == 2; - } - - else /* sRGB tag not involved */ - { - png_chunk_report(png_ptr, "gamma value does not match libpng estimate", - PNG_CHUNK_WARNING); - return from == 1; - } - } - - return 1; -} - -void /* PRIVATE */ -png_colorspace_set_gamma(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_fixed_point gAMA) -{ - /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't - * occur. Since the fixed point representation is assymetrical it is - * possible for 1/gamma to overflow the limit of 21474 and this means the - * gamma value must be at least 5/100000 and hence at most 20000.0. For - * safety the limits here are a little narrower. The values are 0.00016 to - * 6250.0, which are truly ridiculous gamma values (and will produce - * displays that are all black or all white.) - * - * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk - * handling code, which only required the value to be >0. - */ - png_const_charp errmsg; - - if (gAMA < 16 || gAMA > 625000000) - errmsg = "gamma value out of range"; - -# ifdef PNG_READ_gAMA_SUPPORTED - /* Allow the application to set the gamma value more than once */ - else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && - (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0) - errmsg = "duplicate"; -# endif - - /* Do nothing if the colorspace is already invalid */ - else if (colorspace->flags & PNG_COLORSPACE_INVALID) - return; - - else - { - if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA, 1/*from gAMA*/)) - { - /* Store this gamma value. */ - colorspace->gamma = gAMA; - colorspace->flags |= - (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA); - } - - /* At present if the check_gamma test fails the gamma of the colorspace is - * not updated however the colorspace is not invalidated. This - * corresponds to the case where the existing gamma comes from an sRGB - * chunk or profile. An error message has already been output. - */ - return; - } - - /* Error exit - errmsg has been set. */ - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR); -} - -void /* PRIVATE */ -png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr) -{ - if (info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) - { - /* Everything is invalid */ - info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB| - PNG_INFO_iCCP); - -# ifdef PNG_COLORSPACE_SUPPORTED - /* Clean up the iCCP profile now if it won't be used. */ - png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/); -# else - PNG_UNUSED(png_ptr) -# endif - } - - else - { -# ifdef PNG_COLORSPACE_SUPPORTED - /* Leave the INFO_iCCP flag set if the pngset.c code has already set - * it; this allows a PNG to contain a profile which matches sRGB and - * yet still have that profile retrievable by the application. - */ - if (info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) - info_ptr->valid |= PNG_INFO_sRGB; - - else - info_ptr->valid &= ~PNG_INFO_sRGB; - - if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) - info_ptr->valid |= PNG_INFO_cHRM; - - else - info_ptr->valid &= ~PNG_INFO_cHRM; -# endif - - if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) - info_ptr->valid |= PNG_INFO_gAMA; - - else - info_ptr->valid &= ~PNG_INFO_gAMA; - } -} - -#ifdef PNG_READ_SUPPORTED -void /* PRIVATE */ -png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr) -{ - if (info_ptr == NULL) /* reduce code size; check here not in the caller */ - return; - - info_ptr->colorspace = png_ptr->colorspace; - png_colorspace_sync_info(png_ptr, info_ptr); -} -#endif -#endif - -#ifdef PNG_COLORSPACE_SUPPORTED -/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for - * cHRM, as opposed to using chromaticities. These internal APIs return - * non-zero on a parameter error. The X, Y and Z values are required to be - * positive and less than 1.0. - */ -static int -png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ) -{ - png_int_32 d, dwhite, whiteX, whiteY; - - d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z; - if (!png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d)) return 1; - if (!png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d)) return 1; - dwhite = d; - whiteX = XYZ->red_X; - whiteY = XYZ->red_Y; - - d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z; - if (!png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d)) return 1; - if (!png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d)) return 1; - dwhite += d; - whiteX += XYZ->green_X; - whiteY += XYZ->green_Y; - - d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z; - if (!png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d)) return 1; - if (!png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d)) return 1; - dwhite += d; - whiteX += XYZ->blue_X; - whiteY += XYZ->blue_Y; - - /* The reference white is simply the sum of the end-point (X,Y,Z) vectors, - * thus: - */ - if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1; - if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1; - - return 0; -} - -static int -png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) -{ - png_fixed_point red_inverse, green_inverse, blue_scale; - png_fixed_point left, right, denominator; - - /* Check xy and, implicitly, z. Note that wide gamut color spaces typically - * have end points with 0 tristimulus values (these are impossible end - * points, but they are used to cover the possible colors.) - */ - if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1; - if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1; - if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1; - if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1; - if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1; - if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1; - if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1; - if (xy->whitey < 0 || xy->whitey > PNG_FP_1-xy->whitex) return 1; - - /* The reverse calculation is more difficult because the original tristimulus - * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 - * derived values were recorded in the cHRM chunk; - * (red,green,blue,white)x(x,y). This loses one degree of freedom and - * therefore an arbitrary ninth value has to be introduced to undo the - * original transformations. - * - * Think of the original end-points as points in (X,Y,Z) space. The - * chromaticity values (c) have the property: - * - * C - * c = --------- - * X + Y + Z - * - * For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the - * three chromaticity values (x,y,z) for each end-point obey the - * relationship: - * - * x + y + z = 1 - * - * This describes the plane in (X,Y,Z) space that intersects each axis at the - * value 1.0; call this the chromaticity plane. Thus the chromaticity - * calculation has scaled each end-point so that it is on the x+y+z=1 plane - * and chromaticity is the intersection of the vector from the origin to the - * (X,Y,Z) value with the chromaticity plane. - * - * To fully invert the chromaticity calculation we would need the three - * end-point scale factors, (red-scale, green-scale, blue-scale), but these - * were not recorded. Instead we calculated the reference white (X,Y,Z) and - * recorded the chromaticity of this. The reference white (X,Y,Z) would have - * given all three of the scale factors since: - * - * color-C = color-c * color-scale - * white-C = red-C + green-C + blue-C - * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale - * - * But cHRM records only white-x and white-y, so we have lost the white scale - * factor: - * - * white-C = white-c*white-scale - * - * To handle this the inverse transformation makes an arbitrary assumption - * about white-scale: - * - * Assume: white-Y = 1.0 - * Hence: white-scale = 1/white-y - * Or: red-Y + green-Y + blue-Y = 1.0 - * - * Notice the last statement of the assumption gives an equation in three of - * the nine values we want to calculate. 8 more equations come from the - * above routine as summarised at the top above (the chromaticity - * calculation): - * - * Given: color-x = color-X / (color-X + color-Y + color-Z) - * Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0 - * - * This is 9 simultaneous equations in the 9 variables "color-C" and can be - * solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix - * determinants, however this is not as bad as it seems because only 28 of - * the total of 90 terms in the various matrices are non-zero. Nevertheless - * Cramer's rule is notoriously numerically unstable because the determinant - * calculation involves the difference of large, but similar, numbers. It is - * difficult to be sure that the calculation is stable for real world values - * and it is certain that it becomes unstable where the end points are close - * together. - * - * So this code uses the perhaps slightly less optimal but more - * understandable and totally obvious approach of calculating color-scale. - * - * This algorithm depends on the precision in white-scale and that is - * (1/white-y), so we can immediately see that as white-y approaches 0 the - * accuracy inherent in the cHRM chunk drops off substantially. - * - * libpng arithmetic: a simple invertion of the above equations - * ------------------------------------------------------------ - * - * white_scale = 1/white-y - * white-X = white-x * white-scale - * white-Y = 1.0 - * white-Z = (1 - white-x - white-y) * white_scale - * - * white-C = red-C + green-C + blue-C - * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale - * - * This gives us three equations in (red-scale,green-scale,blue-scale) where - * all the coefficients are now known: - * - * red-x*red-scale + green-x*green-scale + blue-x*blue-scale - * = white-x/white-y - * red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1 - * red-z*red-scale + green-z*green-scale + blue-z*blue-scale - * = (1 - white-x - white-y)/white-y - * - * In the last equation color-z is (1 - color-x - color-y) so we can add all - * three equations together to get an alternative third: - * - * red-scale + green-scale + blue-scale = 1/white-y = white-scale - * - * So now we have a Cramer's rule solution where the determinants are just - * 3x3 - far more tractible. Unfortunately 3x3 determinants still involve - * multiplication of three coefficients so we can't guarantee to avoid - * overflow in the libpng fixed point representation. Using Cramer's rule in - * floating point is probably a good choice here, but it's not an option for - * fixed point. Instead proceed to simplify the first two equations by - * eliminating what is likely to be the largest value, blue-scale: - * - * blue-scale = white-scale - red-scale - green-scale - * - * Hence: - * - * (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale = - * (white-x - blue-x)*white-scale - * - * (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale = - * 1 - blue-y*white-scale - * - * And now we can trivially solve for (red-scale,green-scale): - * - * green-scale = - * (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale - * ----------------------------------------------------------- - * green-x - blue-x - * - * red-scale = - * 1 - blue-y*white-scale - (green-y - blue-y) * green-scale - * --------------------------------------------------------- - * red-y - blue-y - * - * Hence: - * - * red-scale = - * ( (green-x - blue-x) * (white-y - blue-y) - - * (green-y - blue-y) * (white-x - blue-x) ) / white-y - * ------------------------------------------------------------------------- - * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) - * - * green-scale = - * ( (red-y - blue-y) * (white-x - blue-x) - - * (red-x - blue-x) * (white-y - blue-y) ) / white-y - * ------------------------------------------------------------------------- - * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) - * - * Accuracy: - * The input values have 5 decimal digits of accuracy. The values are all in - * the range 0 < value < 1, so simple products are in the same range but may - * need up to 10 decimal digits to preserve the original precision and avoid - * underflow. Because we are using a 32-bit signed representation we cannot - * match this; the best is a little over 9 decimal digits, less than 10. - * - * The approach used here is to preserve the maximum precision within the - * signed representation. Because the red-scale calculation above uses the - * difference between two products of values that must be in the range -1..+1 - * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The - * factor is irrelevant in the calculation because it is applied to both - * numerator and denominator. - * - * Note that the values of the differences of the products of the - * chromaticities in the above equations tend to be small, for example for - * the sRGB chromaticities they are: - * - * red numerator: -0.04751 - * green numerator: -0.08788 - * denominator: -0.2241 (without white-y multiplication) - * - * The resultant Y coefficients from the chromaticities of some widely used - * color space definitions are (to 15 decimal places): - * - * sRGB - * 0.212639005871510 0.715168678767756 0.072192315360734 - * Kodak ProPhoto - * 0.288071128229293 0.711843217810102 0.000085653960605 - * Adobe RGB - * 0.297344975250536 0.627363566255466 0.075291458493998 - * Adobe Wide Gamut RGB - * 0.258728243040113 0.724682314948566 0.016589442011321 - */ - /* By the argument, above overflow should be impossible here. The return - * value of 2 indicates an internal error to the caller. - */ - if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7)) - return 2; - if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7)) - return 2; - denominator = left - right; - - /* Now find the red numerator. */ - if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7)) - return 2; - if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7)) - return 2; - - /* Overflow is possible here and it indicates an extreme set of PNG cHRM - * chunk values. This calculation actually returns the reciprocal of the - * scale value because this allows us to delay the multiplication of white-y - * into the denominator, which tends to produce a small number. - */ - if (!png_muldiv(&red_inverse, xy->whitey, denominator, left-right) || - red_inverse <= xy->whitey /* r+g+b scales = white scale */) - return 1; - - /* Similarly for green_inverse: */ - if (!png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7)) - return 2; - if (!png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7)) - return 2; - if (!png_muldiv(&green_inverse, xy->whitey, denominator, left-right) || - green_inverse <= xy->whitey) - return 1; - - /* And the blue scale, the checks above guarantee this can't overflow but it - * can still produce 0 for extreme cHRM values. - */ - blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) - - png_reciprocal(green_inverse); - if (blue_scale <= 0) return 1; - - - /* And fill in the png_XYZ: */ - if (!png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse)) return 1; - if (!png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse)) return 1; - if (!png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1, - red_inverse)) - return 1; - - if (!png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse)) - return 1; - if (!png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse)) - return 1; - if (!png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1, - green_inverse)) - return 1; - - if (!png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1)) return 1; - if (!png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1)) return 1; - if (!png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale, - PNG_FP_1)) - return 1; - - return 0; /*success*/ -} - -static int -png_XYZ_normalize(png_XYZ *XYZ) -{ - png_int_32 Y; - - if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 || - XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 || - XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0) - return 1; - - /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. - * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore - * relying on addition of two positive values producing a negative one is not - * safe. - */ - Y = XYZ->red_Y; - if (0x7fffffff - Y < XYZ->green_X) return 1; - Y += XYZ->green_Y; - if (0x7fffffff - Y < XYZ->blue_X) return 1; - Y += XYZ->blue_Y; - - if (Y != PNG_FP_1) - { - if (!png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y)) return 1; - if (!png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y)) return 1; - if (!png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y)) return 1; - - if (!png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y)) return 1; - if (!png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y)) return 1; - if (!png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y)) return 1; - - if (!png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y)) return 1; - if (!png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y)) return 1; - if (!png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y)) return 1; - } - - return 0; -} - -static int -png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta) -{ - /* Allow an error of +/-0.01 (absolute value) on each chromaticity */ - return !(PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) || - PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) || - PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) || - PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) || - PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) || - PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) || - PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) || - PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta)); -} - -/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM - * chunk chromaticities. Earlier checks used to simply look for the overflow - * condition (where the determinant of the matrix to solve for XYZ ends up zero - * because the chromaticity values are not all distinct.) Despite this it is - * theoretically possible to produce chromaticities that are apparently valid - * but that rapidly degrade to invalid, potentially crashing, sets because of - * arithmetic inaccuracies when calculations are performed on them. The new - * check is to round-trip xy -> XYZ -> xy and then check that the result is - * within a small percentage of the original. - */ -static int -png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy) -{ - int result; - png_xy xy_test; - - /* As a side-effect this routine also returns the XYZ endpoints. */ - result = png_XYZ_from_xy(XYZ, xy); - if (result) return result; - - result = png_xy_from_XYZ(&xy_test, XYZ); - if (result) return result; - - if (png_colorspace_endpoints_match(xy, &xy_test, - 5/*actually, the math is pretty accurate*/)) - return 0; - - /* Too much slip */ - return 1; -} - -/* This is the check going the other way. The XYZ is modified to normalize it - * (another side-effect) and the xy chromaticities are returned. - */ -static int -png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ) -{ - int result; - png_XYZ XYZtemp; - - result = png_XYZ_normalize(XYZ); - if (result) return result; - - result = png_xy_from_XYZ(xy, XYZ); - if (result) return result; - - XYZtemp = *XYZ; - return png_colorspace_check_xy(&XYZtemp, xy); -} - -/* Used to check for an endpoint match against sRGB */ -static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */ -{ - /* color x y */ - /* red */ 64000, 33000, - /* green */ 30000, 60000, - /* blue */ 15000, 6000, - /* white */ 31270, 32900 -}; - -static int -png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ, - int preferred) -{ - if (colorspace->flags & PNG_COLORSPACE_INVALID) - return 0; - - /* The consistency check is performed on the chromaticities; this factors out - * variations because of the normalization (or not) of the end point Y - * values. - */ - if (preferred < 2 && (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) - { - /* The end points must be reasonably close to any we already have. The - * following allows an error of up to +/-.001 - */ - if (!png_colorspace_endpoints_match(xy, &colorspace->end_points_xy, 100)) - { - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_benign_error(png_ptr, "inconsistent chromaticities"); - return 0; /* failed */ - } - - /* Only overwrite with preferred values */ - if (!preferred) - return 1; /* ok, but no change */ - } - - colorspace->end_points_xy = *xy; - colorspace->end_points_XYZ = *XYZ; - colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS; - - /* The end points are normally quoted to two decimal digits, so allow +/-0.01 - * on this test. - */ - if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000)) - colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB; - - else - colorspace->flags &= PNG_COLORSPACE_CANCEL( - PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); - - return 2; /* ok and changed */ -} - -int /* PRIVATE */ -png_colorspace_set_chromaticities(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_xy *xy, int preferred) -{ - /* We must check the end points to ensure they are reasonable - in the past - * color management systems have crashed as a result of getting bogus - * colorant values, while this isn't the fault of libpng it is the - * responsibility of libpng because PNG carries the bomb and libpng is in a - * position to protect against it. - */ - png_XYZ XYZ; - - switch (png_colorspace_check_xy(&XYZ, xy)) - { - case 0: /* success */ - return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ, - preferred); - - case 1: - /* We can't invert the chromaticities so we can't produce value XYZ - * values. Likely as not a color management system will fail too. - */ - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_benign_error(png_ptr, "invalid chromaticities"); - break; - - default: - /* libpng is broken; this should be a warning but if it happens we - * want error reports so for the moment it is an error. - */ - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_error(png_ptr, "internal error checking chromaticities"); - break; - } - - return 0; /* failed */ -} - -int /* PRIVATE */ -png_colorspace_set_endpoints(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred) -{ - png_XYZ XYZ = *XYZ_in; - png_xy xy; - - switch (png_colorspace_check_XYZ(&xy, &XYZ)) - { - case 0: - return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ, - preferred); - - case 1: - /* End points are invalid. */ - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_benign_error(png_ptr, "invalid end points"); - break; - - default: - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_error(png_ptr, "internal error checking chromaticities"); - break; - } - - return 0; /* failed */ -} - -#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED) -/* Error message generation */ -static char -png_icc_tag_char(png_uint_32 byte) -{ - byte &= 0xff; - if (byte >= 32 && byte <= 126) - return (char)byte; - else - return '?'; -} - -static void -png_icc_tag_name(char *name, png_uint_32 tag) -{ - name[0] = '\''; - name[1] = png_icc_tag_char(tag >> 24); - name[2] = png_icc_tag_char(tag >> 16); - name[3] = png_icc_tag_char(tag >> 8); - name[4] = png_icc_tag_char(tag ); - name[5] = '\''; -} - -static int -is_ICC_signature_char(png_alloc_size_t it) -{ - return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) || - (it >= 97 && it <= 122); -} - -static int is_ICC_signature(png_alloc_size_t it) -{ - return is_ICC_signature_char(it >> 24) /* checks all the top bits */ && - is_ICC_signature_char((it >> 16) & 0xff) && - is_ICC_signature_char((it >> 8) & 0xff) && - is_ICC_signature_char(it & 0xff); -} - -static int -png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_alloc_size_t value, png_const_charp reason) -{ - size_t pos; - char message[196]; /* see below for calculation */ - - if (colorspace != NULL) - colorspace->flags |= PNG_COLORSPACE_INVALID; - - pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */ - pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */ - pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */ - if (is_ICC_signature(value)) - { - /* So 'value' is at most 4 bytes and the following cast is safe */ - png_icc_tag_name(message+pos, (png_uint_32)value); - pos += 6; /* total +8; less than the else clause */ - message[pos++] = ':'; - message[pos++] = ' '; - } -# ifdef PNG_WARNINGS_SUPPORTED - else - { - char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/ - - pos = png_safecat(message, (sizeof message), pos, - png_format_number(number, number+(sizeof number), - PNG_NUMBER_FORMAT_x, value)); - pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/ - } -# endif - /* The 'reason' is an arbitrary message, allow +79 maximum 195 */ - pos = png_safecat(message, (sizeof message), pos, reason); - - /* This is recoverable, but make it unconditionally an app_error on write to - * avoid writing invalid ICC profiles into PNG files. (I.e. we handle them - * on read, with a warning, but on write unless the app turns off - * application errors the PNG won't be written.) - */ - png_chunk_report(png_ptr, message, - (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR); - - return 0; -} -#endif /* sRGB || iCCP */ - -#ifdef PNG_sRGB_SUPPORTED -int /* PRIVATE */ -png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, - int intent) -{ - /* sRGB sets known gamma, end points and (from the chunk) intent. */ - /* IMPORTANT: these are not necessarily the values found in an ICC profile - * because ICC profiles store values adapted to a D50 environment; it is - * expected that the ICC profile mediaWhitePointTag will be D50, see the - * checks and code elsewhere to understand this better. - * - * These XYZ values, which are accurate to 5dp, produce rgb to gray - * coefficients of (6968,23435,2366), which are reduced (because they add up - * to 32769 not 32768) to (6968,23434,2366). These are the values that - * libpng has traditionally used (and are the best values given the 15bit - * algorithm used by the rgb to gray code.) - */ - static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */ - { - /* color X Y Z */ - /* red */ 41239, 21264, 1933, - /* green */ 35758, 71517, 11919, - /* blue */ 18048, 7219, 95053 - }; - - /* Do nothing if the colorspace is already invalidated. */ - if (colorspace->flags & PNG_COLORSPACE_INVALID) - return 0; - - /* Check the intent, then check for existing settings. It is valid for the - * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must - * be consistent with the correct values. If, however, this function is - * called below because an iCCP chunk matches sRGB then it is quite - * conceivable that an older app recorded incorrect gAMA and cHRM because of - * an incorrect calculation based on the values in the profile - this does - * *not* invalidate the profile (though it still produces an error, which can - * be ignored.) - */ - if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) - return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "invalid sRGB rendering intent"); - - if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && - colorspace->rendering_intent != intent) - return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "inconsistent rendering intents"); - - if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) - { - png_benign_error(png_ptr, "duplicate sRGB information ignored"); - return 0; - } - - /* If the standard sRGB cHRM chunk does not match the one from the PNG file - * warn but overwrite the value with the correct one. - */ - if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 && - !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy, - 100)) - png_chunk_report(png_ptr, "cHRM chunk does not match sRGB", - PNG_CHUNK_ERROR); - - /* This check is just done for the error reporting - the routine always - * returns true when the 'from' argument corresponds to sRGB (2). - */ - (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE, - 2/*from sRGB*/); - - /* intent: bugs in GCC force 'int' to be used as the parameter type. */ - colorspace->rendering_intent = (png_uint_16)intent; - colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT; - - /* endpoints */ - colorspace->end_points_xy = sRGB_xy; - colorspace->end_points_XYZ = sRGB_XYZ; - colorspace->flags |= - (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); - - /* gamma */ - colorspace->gamma = PNG_GAMMA_sRGB_INVERSE; - colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA; - - /* Finally record that we have an sRGB profile */ - colorspace->flags |= - (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB); - - return 1; /* set */ -} -#endif /* sRGB */ - -#ifdef PNG_iCCP_SUPPORTED -/* Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value - * is XYZ(0.9642,1.0,0.8249), which scales to: - * - * (63189.8112, 65536, 54060.6464) - */ -static const png_byte D50_nCIEXYZ[12] = - { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; - -int /* PRIVATE */ -png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length) -{ - if (profile_length < 132) - return png_icc_profile_error(png_ptr, colorspace, name, profile_length, - "too short"); - - if (profile_length & 3) - return png_icc_profile_error(png_ptr, colorspace, name, profile_length, - "invalid length"); - - return 1; -} - -int /* PRIVATE */ -png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, - png_const_bytep profile/* first 132 bytes only */, int color_type) -{ - png_uint_32 temp; - - /* Length check; this cannot be ignored in this code because profile_length - * is used later to check the tag table, so even if the profile seems over - * long profile_length from the caller must be correct. The caller can fix - * this up on read or write by just passing in the profile header length. - */ - temp = png_get_uint_32(profile); - if (temp != profile_length) - return png_icc_profile_error(png_ptr, colorspace, name, temp, - "length does not match profile"); - - temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */ - if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */ - profile_length < 132+12*temp) /* truncated tag table */ - return png_icc_profile_error(png_ptr, colorspace, name, temp, - "tag count too large"); - - /* The 'intent' must be valid or we can't store it, ICC limits the intent to - * 16 bits. - */ - temp = png_get_uint_32(profile+64); - if (temp >= 0xffff) /* The ICC limit */ - return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid rendering intent"); - - /* This is just a warning because the profile may be valid in future - * versions. - */ - if (temp >= PNG_sRGB_INTENT_LAST) - (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "intent outside defined range"); - - /* At this point the tag table can't be checked because it hasn't necessarily - * been loaded; however, various header fields can be checked. These checks - * are for values permitted by the PNG spec in an ICC profile; the PNG spec - * restricts the profiles that can be passed in an iCCP chunk (they must be - * appropriate to processing PNG data!) - */ - - /* Data checks (could be skipped). These checks must be independent of the - * version number; however, the version number doesn't accomodate changes in - * the header fields (just the known tags and the interpretation of the - * data.) - */ - temp = png_get_uint_32(profile+36); /* signature 'ascp' */ - if (temp != 0x61637370) - return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid signature"); - - /* Currently the PCS illuminant/adopted white point (the computational - * white point) are required to be D50, - * however the profile contains a record of the illuminant so perhaps ICC - * expects to be able to change this in the future (despite the rationale in - * the introduction for using a fixed PCS adopted white.) Consequently the - * following is just a warning. - */ - if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0) - (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/, - "PCS illuminant is not D50"); - - /* The PNG spec requires this: - * "If the iCCP chunk is present, the image samples conform to the colour - * space represented by the embedded ICC profile as defined by the - * International Color Consortium [ICC]. The colour space of the ICC profile - * shall be an RGB colour space for colour images (PNG colour types 2, 3, and - * 6), or a greyscale colour space for greyscale images (PNG colour types 0 - * and 4)." - * - * This checking code ensures the embedded profile (on either read or write) - * conforms to the specification requirements. Notice that an ICC 'gray' - * color-space profile contains the information to transform the monochrome - * data to XYZ or L*a*b (according to which PCS the profile uses) and this - * should be used in preference to the standard libpng K channel replication - * into R, G and B channels. - * - * Previously it was suggested that an RGB profile on grayscale data could be - * handled. However it it is clear that using an RGB profile in this context - * must be an error - there is no specification of what it means. Thus it is - * almost certainly more correct to ignore the profile. - */ - temp = png_get_uint_32(profile+16); /* data colour space field */ - switch (temp) - { - case 0x52474220: /* 'RGB ' */ - if (!(color_type & PNG_COLOR_MASK_COLOR)) - return png_icc_profile_error(png_ptr, colorspace, name, temp, - "RGB color space not permitted on grayscale PNG"); - break; - - case 0x47524159: /* 'GRAY' */ - if (color_type & PNG_COLOR_MASK_COLOR) - return png_icc_profile_error(png_ptr, colorspace, name, temp, - "Gray color space not permitted on RGB PNG"); - break; - - default: - return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid ICC profile color space"); - } - - /* It is up to the application to check that the profile class matches the - * application requirements; the spec provides no guidance, but it's pretty - * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer - * ('prtr') or 'spac' (for generic color spaces). Issue a warning in these - * cases. Issue an error for device link or abstract profiles - these don't - * contain the records necessary to transform the color-space to anything - * other than the target device (and not even that for an abstract profile). - * Profiles of these classes may not be embedded in images. - */ - temp = png_get_uint_32(profile+12); /* profile/device class */ - switch (temp) - { - case 0x73636E72: /* 'scnr' */ - case 0x6D6E7472: /* 'mntr' */ - case 0x70727472: /* 'prtr' */ - case 0x73706163: /* 'spac' */ - /* All supported */ - break; - - case 0x61627374: /* 'abst' */ - /* May not be embedded in an image */ - return png_icc_profile_error(png_ptr, colorspace, name, temp, - "invalid embedded Abstract ICC profile"); - - case 0x6C696E6B: /* 'link' */ - /* DeviceLink profiles cannnot be interpreted in a non-device specific - * fashion, if an app uses the AToB0Tag in the profile the results are - * undefined unless the result is sent to the intended device, - * therefore a DeviceLink profile should not be found embedded in a - * PNG. - */ - return png_icc_profile_error(png_ptr, colorspace, name, temp, - "unexpected DeviceLink ICC profile class"); - - case 0x6E6D636C: /* 'nmcl' */ - /* A NamedColor profile is also device specific, however it doesn't - * contain an AToB0 tag that is open to misintrepretation. Almost - * certainly it will fail the tests below. - */ - (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "unexpected NamedColor ICC profile class"); - break; - - default: - /* To allow for future enhancements to the profile accept unrecognized - * profile classes with a warning, these then hit the test below on the - * tag content to ensure they are backward compatible with one of the - * understood profiles. - */ - (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "unrecognized ICC profile class"); - break; - } - - /* For any profile other than a device link one the PCS must be encoded - * either in XYZ or Lab. - */ - temp = png_get_uint_32(profile+20); - switch (temp) - { - case 0x58595A20: /* 'XYZ ' */ - case 0x4C616220: /* 'Lab ' */ - break; - - default: - return png_icc_profile_error(png_ptr, colorspace, name, temp, - "unexpected ICC PCS encoding"); - } - - return 1; -} - -int /* PRIVATE */ -png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, - png_const_bytep profile /* header plus whole tag table */) -{ - png_uint_32 tag_count = png_get_uint_32(profile+128); - png_uint_32 itag; - png_const_bytep tag = profile+132; /* The first tag */ - - /* First scan all the tags in the table and add bits to the icc_info value - * (temporarily in 'tags'). - */ - for (itag=0; itag < tag_count; ++itag, tag += 12) - { - png_uint_32 tag_id = png_get_uint_32(tag+0); - png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */ - png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */ - - /* The ICC specification does not exclude zero length tags, therefore the - * start might actually be anywhere if there is no data, but this would be - * a clear abuse of the intent of the standard so the start is checked for - * being in range. All defined tag types have an 8 byte header - a 4 byte - * type signature then 0. - */ - if ((tag_start & 3) != 0) - { - /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is - * only a warning here because libpng does not care about the - * alignment. - */ - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "ICC profile tag start not a multiple of 4"); - } - - /* This is a hard error; potentially it can cause read outside the - * profile. - */ - if (tag_start > profile_length || tag_length > profile_length - tag_start) - return png_icc_profile_error(png_ptr, colorspace, name, tag_id, - "ICC profile tag outside profile"); - } - - return 1; /* success, maybe with warnings */ -} - -#ifdef PNG_sRGB_SUPPORTED -/* Information about the known ICC sRGB profiles */ -static const struct -{ - png_uint_32 adler, crc, length; - png_uint_32 md5[4]; - png_byte have_md5; - png_byte is_broken; - png_uint_16 intent; - -# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0) -# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\ - { adler, crc, length, md5, broke, intent }, - -} png_sRGB_checks[] = -{ - /* This data comes from contrib/tools/checksum-icc run on downloads of - * all four ICC sRGB profiles from www.color.org. - */ - /* adler32, crc32, MD5[4], intent, date, length, file-name */ - PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9, - PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0, - "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") - - /* ICC sRGB v2 perceptual no black-compensation: */ - PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21, - PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0, - "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") - - PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae, - PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0, - "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") - - /* ICC sRGB v4 perceptual */ - PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812, - PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0, - "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") - - /* The following profiles have no known MD5 checksum. If there is a match - * on the (empty) MD5 the other fields are used to attempt a match and - * a warning is produced. The first two of these profiles have a 'cprt' tag - * which suggests that they were also made by Hewlett Packard. - */ - PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0, - "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") - - /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not - * match the D50 PCS illuminant in the header (it is in fact the D65 values, - * so the white point is recorded as the un-adapted value.) The profiles - * below only differ in one byte - the intent - and are basically the same as - * the previous profile except for the mediaWhitePointTag error and a missing - * chromaticAdaptationTag. - */ - PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, - "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") - - PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, - "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") -}; - -static int -png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, - png_const_bytep profile, uLong adler) -{ - /* The quick check is to verify just the MD5 signature and trust the - * rest of the data. Because the profile has already been verified for - * correctness this is safe. png_colorspace_set_sRGB will check the 'intent' - * field too, so if the profile has been edited with an intent not defined - * by sRGB (but maybe defined by a later ICC specification) the read of - * the profile will fail at that point. - */ - png_uint_32 length = 0; - png_uint_32 intent = 0x10000; /* invalid */ -#if PNG_sRGB_PROFILE_CHECKS > 1 - uLong crc = 0; /* the value for 0 length data */ -#endif - unsigned int i; - - for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i) - { - if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] && - png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] && - png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] && - png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3]) - { - /* This may be one of the old HP profiles without an MD5, in that - * case we can only use the length and Adler32 (note that these - * are not used by default if there is an MD5!) - */ -# if PNG_sRGB_PROFILE_CHECKS == 0 - if (png_sRGB_checks[i].have_md5) - return 1+png_sRGB_checks[i].is_broken; -# endif - - /* Profile is unsigned or more checks have been configured in. */ - if (length == 0) - { - length = png_get_uint_32(profile); - intent = png_get_uint_32(profile+64); - } - - /* Length *and* intent must match */ - if (length == png_sRGB_checks[i].length && - intent == png_sRGB_checks[i].intent) - { - /* Now calculate the adler32 if not done already. */ - if (adler == 0) - { - adler = adler32(0, NULL, 0); - adler = adler32(adler, profile, length); - } - - if (adler == png_sRGB_checks[i].adler) - { - /* These basic checks suggest that the data has not been - * modified, but if the check level is more than 1 perform - * our own crc32 checksum on the data. - */ -# if PNG_sRGB_PROFILE_CHECKS > 1 - if (crc == 0) - { - crc = crc32(0, NULL, 0); - crc = crc32(crc, profile, length); - } - - /* So this check must pass for the 'return' below to happen. - */ - if (crc == png_sRGB_checks[i].crc) -# endif - { - if (png_sRGB_checks[i].is_broken) - { - /* These profiles are known to have bad data that may cause - * problems if they are used, therefore attempt to - * discourage their use, skip the 'have_md5' warning below, - * which is made irrelevant by this error. - */ - png_chunk_report(png_ptr, "known incorrect sRGB profile", - PNG_CHUNK_ERROR); - } - - /* Warn that this being done; this isn't even an error since - * the profile is perfectly valid, but it would be nice if - * people used the up-to-date ones. - */ - else if (!png_sRGB_checks[i].have_md5) - { - png_chunk_report(png_ptr, - "out-of-date sRGB profile with no signature", - PNG_CHUNK_WARNING); - } - - return 1+png_sRGB_checks[i].is_broken; - } - } - } - -# if PNG_sRGB_PROFILE_CHECKS > 0 - /* The signature matched, but the profile had been changed in some - * way. This is an apparent violation of the ICC terms of use and, - * anyway, probably indicates a data error or uninformed hacking. - */ - if (png_sRGB_checks[i].have_md5) - png_benign_error(png_ptr, - "copyright violation: edited ICC profile ignored"); -# endif - } - } - - return 0; /* no match */ -} -#endif - -#ifdef PNG_sRGB_SUPPORTED -void /* PRIVATE */ -png_icc_set_sRGB(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_bytep profile, uLong adler) -{ - /* Is this profile one of the known ICC sRGB profiles? If it is, just set - * the sRGB information. - */ - if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler)) - (void)png_colorspace_set_sRGB(png_ptr, colorspace, - (int)/*already checked*/png_get_uint_32(profile+64)); -} -#endif /* PNG_READ_sRGB_SUPPORTED */ - -int /* PRIVATE */ -png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, png_const_bytep profile, - int color_type) -{ - if (colorspace->flags & PNG_COLORSPACE_INVALID) - return 0; - - if (png_icc_check_length(png_ptr, colorspace, name, profile_length) && - png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, - color_type) && - png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, - profile)) - { -# ifdef PNG_sRGB_SUPPORTED - /* If no sRGB support, don't try storing sRGB information */ - png_icc_set_sRGB(png_ptr, colorspace, profile, 0); -# endif - return 1; - } - - /* Failure case */ - return 0; -} -#endif /* iCCP */ - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -void /* PRIVATE */ -png_colorspace_set_rgb_coefficients(png_structrp png_ptr) -{ - /* Set the rgb_to_gray coefficients from the colorspace. */ - if (!png_ptr->rgb_to_gray_coefficients_set && - (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) - { - /* png_set_background has not been called, get the coefficients from the Y - * values of the colorspace colorants. - */ - png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y; - png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y; - png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y; - png_fixed_point total = r+g+b; - - if (total > 0 && - r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 && - g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 && - b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 && - r+g+b <= 32769) - { - /* We allow 0 coefficients here. r+g+b may be 32769 if two or - * all of the coefficients were rounded up. Handle this by - * reducing the *largest* coefficient by 1; this matches the - * approach used for the default coefficients in pngrtran.c - */ - int add = 0; - - if (r+g+b > 32768) - add = -1; - else if (r+g+b < 32768) - add = 1; - - if (add != 0) - { - if (g >= r && g >= b) - g += add; - else if (r >= g && r >= b) - r += add; - else - b += add; - } - - /* Check for an internal error. */ - if (r+g+b != 32768) - png_error(png_ptr, - "internal error handling cHRM coefficients"); - - else - { - png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r; - png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g; - } - } - - /* This is a png_error at present even though it could be ignored - - * it should never happen, but it is important that if it does, the - * bug is fixed. - */ - else - png_error(png_ptr, "internal error handling cHRM->XYZ"); - } -} -#endif - -#endif /* COLORSPACE */ - -void /* PRIVATE */ -png_check_IHDR(png_const_structrp png_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_type, int compression_type, - int filter_type) -{ - int error = 0; - - /* Check for width and height valid values */ - if (width == 0) - { - png_warning(png_ptr, "Image width is zero in IHDR"); - error = 1; - } - - if (height == 0) - { - png_warning(png_ptr, "Image height is zero in IHDR"); - error = 1; - } - -# ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (width > png_ptr->user_width_max) - -# else - if (width > PNG_USER_WIDTH_MAX) -# endif - { - png_warning(png_ptr, "Image width exceeds user limit in IHDR"); - error = 1; - } - -# ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (height > png_ptr->user_height_max) -# else - if (height > PNG_USER_HEIGHT_MAX) -# endif - { - png_warning(png_ptr, "Image height exceeds user limit in IHDR"); - error = 1; - } - - if (width > PNG_UINT_31_MAX) - { - png_warning(png_ptr, "Invalid image width in IHDR"); - error = 1; - } - - if (height > PNG_UINT_31_MAX) - { - png_warning(png_ptr, "Invalid image height in IHDR"); - error = 1; - } - - if (width > (PNG_UINT_32_MAX - >> 3) /* 8-byte RGBA pixels */ - - 48 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - png_warning(png_ptr, "Width is too large for libpng to process pixels"); - - /* Check other values */ - if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && - bit_depth != 8 && bit_depth != 16) - { - png_warning(png_ptr, "Invalid bit depth in IHDR"); - error = 1; - } - - if (color_type < 0 || color_type == 1 || - color_type == 5 || color_type > 6) - { - png_warning(png_ptr, "Invalid color type in IHDR"); - error = 1; - } - - if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || - ((color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) - { - png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR"); - error = 1; - } - - if (interlace_type >= PNG_INTERLACE_LAST) - { - png_warning(png_ptr, "Unknown interlace method in IHDR"); - error = 1; - } - - if (compression_type != PNG_COMPRESSION_TYPE_BASE) - { - png_warning(png_ptr, "Unknown compression method in IHDR"); - error = 1; - } - -# ifdef PNG_MNG_FEATURES_SUPPORTED - /* Accept filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not read a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ - if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) && - png_ptr->mng_features_permitted) - png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); - - if (filter_type != PNG_FILTER_TYPE_BASE) - { - if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && - ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && - (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA))) - { - png_warning(png_ptr, "Unknown filter method in IHDR"); - error = 1; - } - - if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) - { - png_warning(png_ptr, "Invalid filter method in IHDR"); - error = 1; - } - } - -# else - if (filter_type != PNG_FILTER_TYPE_BASE) - { - png_warning(png_ptr, "Unknown filter method in IHDR"); - error = 1; - } -# endif - - if (error == 1) - png_error(png_ptr, "Invalid IHDR data"); -} - -#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) -/* ASCII to fp functions */ -/* Check an ASCII formated floating point value, see the more detailed - * comments in pngpriv.h - */ -/* The following is used internally to preserve the sticky flags */ -#define png_fp_add(state, flags) ((state) |= (flags)) -#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) - -int /* PRIVATE */ -png_check_fp_number(png_const_charp string, png_size_t size, int *statep, - png_size_tp whereami) -{ - int state = *statep; - png_size_t i = *whereami; - - while (i < size) - { - int type; - /* First find the type of the next character */ - switch (string[i]) - { - case 43: type = PNG_FP_SAW_SIGN; break; - case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break; - case 46: type = PNG_FP_SAW_DOT; break; - case 48: type = PNG_FP_SAW_DIGIT; break; - case 49: case 50: case 51: case 52: - case 53: case 54: case 55: case 56: - case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break; - case 69: - case 101: type = PNG_FP_SAW_E; break; - default: goto PNG_FP_End; - } - - /* Now deal with this type according to the current - * state, the type is arranged to not overlap the - * bits of the PNG_FP_STATE. - */ - switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY)) - { - case PNG_FP_INTEGER + PNG_FP_SAW_SIGN: - if (state & PNG_FP_SAW_ANY) - goto PNG_FP_End; /* not a part of the number */ - - png_fp_add(state, type); - break; - - case PNG_FP_INTEGER + PNG_FP_SAW_DOT: - /* Ok as trailer, ok as lead of fraction. */ - if (state & PNG_FP_SAW_DOT) /* two dots */ - goto PNG_FP_End; - - else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */ - png_fp_add(state, type); - - else - png_fp_set(state, PNG_FP_FRACTION | type); - - break; - - case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT: - if (state & PNG_FP_SAW_DOT) /* delayed fraction */ - png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); - - png_fp_add(state, type | PNG_FP_WAS_VALID); - - break; - - case PNG_FP_INTEGER + PNG_FP_SAW_E: - if ((state & PNG_FP_SAW_DIGIT) == 0) - goto PNG_FP_End; - - png_fp_set(state, PNG_FP_EXPONENT); - - break; - - /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: - goto PNG_FP_End; ** no sign in fraction */ - - /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: - goto PNG_FP_End; ** Because SAW_DOT is always set */ - - case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT: - png_fp_add(state, type | PNG_FP_WAS_VALID); - break; - - case PNG_FP_FRACTION + PNG_FP_SAW_E: - /* This is correct because the trailing '.' on an - * integer is handled above - so we can only get here - * with the sequence ".E" (with no preceding digits). - */ - if ((state & PNG_FP_SAW_DIGIT) == 0) - goto PNG_FP_End; - - png_fp_set(state, PNG_FP_EXPONENT); - - break; - - case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN: - if (state & PNG_FP_SAW_ANY) - goto PNG_FP_End; /* not a part of the number */ - - png_fp_add(state, PNG_FP_SAW_SIGN); - - break; - - /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: - goto PNG_FP_End; */ - - case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT: - png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID); - - break; - - /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: - goto PNG_FP_End; */ - - default: goto PNG_FP_End; /* I.e. break 2 */ - } - - /* The character seems ok, continue. */ - ++i; - } - -PNG_FP_End: - /* Here at the end, update the state and return the correct - * return code. - */ - *statep = state; - *whereami = i; - - return (state & PNG_FP_SAW_DIGIT) != 0; -} - - -/* The same but for a complete string. */ -int -png_check_fp_string(png_const_charp string, png_size_t size) -{ - int state=0; - png_size_t char_index=0; - - if (png_check_fp_number(string, size, &state, &char_index) && - (char_index == size || string[char_index] == 0)) - return state /* must be non-zero - see above */; - - return 0; /* i.e. fail */ -} -#endif /* pCAL or sCAL */ - -#ifdef PNG_sCAL_SUPPORTED -# ifdef PNG_FLOATING_POINT_SUPPORTED -/* Utility used below - a simple accurate power of ten from an integral - * exponent. - */ -static double -png_pow10(int power) -{ - int recip = 0; - double d = 1; - - /* Handle negative exponent with a reciprocal at the end because - * 10 is exact whereas .1 is inexact in base 2 - */ - if (power < 0) - { - if (power < DBL_MIN_10_EXP) return 0; - recip = 1, power = -power; - } - - if (power > 0) - { - /* Decompose power bitwise. */ - double mult = 10; - do - { - if (power & 1) d *= mult; - mult *= mult; - power >>= 1; - } - while (power > 0); - - if (recip) d = 1/d; - } - /* else power is 0 and d is 1 */ - - return d; -} - -/* Function to format a floating point value in ASCII with a given - * precision. - */ -void /* PRIVATE */ -png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, - double fp, unsigned int precision) -{ - /* We use standard functions from math.h, but not printf because - * that would require stdio. The caller must supply a buffer of - * sufficient size or we will png_error. The tests on size and - * the space in ascii[] consumed are indicated below. - */ - if (precision < 1) - precision = DBL_DIG; - - /* Enforce the limit of the implementation precision too. */ - if (precision > DBL_DIG+1) - precision = DBL_DIG+1; - - /* Basic sanity checks */ - if (size >= precision+5) /* See the requirements below. */ - { - if (fp < 0) - { - fp = -fp; - *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */ - --size; - } - - if (fp >= DBL_MIN && fp <= DBL_MAX) - { - int exp_b10; /* A base 10 exponent */ - double base; /* 10^exp_b10 */ - - /* First extract a base 10 exponent of the number, - * the calculation below rounds down when converting - * from base 2 to base 10 (multiply by log10(2) - - * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to - * be increased. Note that the arithmetic shift - * performs a floor() unlike C arithmetic - using a - * C multiply would break the following for negative - * exponents. - */ - (void)frexp(fp, &exp_b10); /* exponent to base 2 */ - - exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */ - - /* Avoid underflow here. */ - base = png_pow10(exp_b10); /* May underflow */ - - while (base < DBL_MIN || base < fp) - { - /* And this may overflow. */ - double test = png_pow10(exp_b10+1); - - if (test <= DBL_MAX) - ++exp_b10, base = test; - - else - break; - } - - /* Normalize fp and correct exp_b10, after this fp is in the - * range [.1,1) and exp_b10 is both the exponent and the digit - * *before* which the decimal point should be inserted - * (starting with 0 for the first digit). Note that this - * works even if 10^exp_b10 is out of range because of the - * test on DBL_MAX above. - */ - fp /= base; - while (fp >= 1) fp /= 10, ++exp_b10; - - /* Because of the code above fp may, at this point, be - * less than .1, this is ok because the code below can - * handle the leading zeros this generates, so no attempt - * is made to correct that here. - */ - - { - int czero, clead, cdigits; - char exponent[10]; - - /* Allow up to two leading zeros - this will not lengthen - * the number compared to using E-n. - */ - if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ - { - czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ - exp_b10 = 0; /* Dot added below before first output. */ - } - else - czero = 0; /* No zeros to add */ - - /* Generate the digit list, stripping trailing zeros and - * inserting a '.' before a digit if the exponent is 0. - */ - clead = czero; /* Count of leading zeros */ - cdigits = 0; /* Count of digits in list. */ - - do - { - double d; - - fp *= 10; - /* Use modf here, not floor and subtract, so that - * the separation is done in one step. At the end - * of the loop don't break the number into parts so - * that the final digit is rounded. - */ - if (cdigits+czero-clead+1 < (int)precision) - fp = modf(fp, &d); - - else - { - d = floor(fp + .5); - - if (d > 9) - { - /* Rounding up to 10, handle that here. */ - if (czero > 0) - { - --czero, d = 1; - if (cdigits == 0) --clead; - } - else - { - while (cdigits > 0 && d > 9) - { - int ch = *--ascii; - - if (exp_b10 != (-1)) - ++exp_b10; - - else if (ch == 46) - { - ch = *--ascii, ++size; - /* Advance exp_b10 to '1', so that the - * decimal point happens after the - * previous digit. - */ - exp_b10 = 1; - } - - --cdigits; - d = ch - 47; /* I.e. 1+(ch-48) */ - } - - /* Did we reach the beginning? If so adjust the - * exponent but take into account the leading - * decimal point. - */ - if (d > 9) /* cdigits == 0 */ - { - if (exp_b10 == (-1)) - { - /* Leading decimal point (plus zeros?), if - * we lose the decimal point here it must - * be reentered below. - */ - int ch = *--ascii; - - if (ch == 46) - ++size, exp_b10 = 1; - - /* Else lost a leading zero, so 'exp_b10' is - * still ok at (-1) - */ - } - else - ++exp_b10; - - /* In all cases we output a '1' */ - d = 1; - } - } - } - fp = 0; /* Guarantees termination below. */ - } - - if (d == 0) - { - ++czero; - if (cdigits == 0) ++clead; - } - else - { - /* Included embedded zeros in the digit count. */ - cdigits += czero - clead; - clead = 0; - - while (czero > 0) - { - /* exp_b10 == (-1) means we just output the decimal - * place - after the DP don't adjust 'exp_b10' any - * more! - */ - if (exp_b10 != (-1)) - { - if (exp_b10 == 0) *ascii++ = 46, --size; - /* PLUS 1: TOTAL 4 */ - --exp_b10; - } - *ascii++ = 48, --czero; - } - - if (exp_b10 != (-1)) - { - if (exp_b10 == 0) *ascii++ = 46, --size; /* counted - above */ - --exp_b10; - } - *ascii++ = (char)(48 + (int)d), ++cdigits; - } - } - while (cdigits+czero-clead < (int)precision && fp > DBL_MIN); - - /* The total output count (max) is now 4+precision */ - - /* Check for an exponent, if we don't need one we are - * done and just need to terminate the string. At - * this point exp_b10==(-1) is effectively if flag - it got - * to '-1' because of the decrement after outputing - * the decimal point above (the exponent required is - * *not* -1!) - */ - if (exp_b10 >= (-1) && exp_b10 <= 2) - { - /* The following only happens if we didn't output the - * leading zeros above for negative exponent, so this - * doest add to the digit requirement. Note that the - * two zeros here can only be output if the two leading - * zeros were *not* output, so this doesn't increase - * the output count. - */ - while (--exp_b10 >= 0) *ascii++ = 48; - - *ascii = 0; - - /* Total buffer requirement (including the '\0') is - * 5+precision - see check at the start. - */ - return; - } - - /* Here if an exponent is required, adjust size for - * the digits we output but did not count. The total - * digit output here so far is at most 1+precision - no - * decimal point and no leading or trailing zeros have - * been output. - */ - size -= cdigits; - - *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ - - /* The following use of an unsigned temporary avoids ambiguities in - * the signed arithmetic on exp_b10 and permits GCC at least to do - * better optimization. - */ - { - unsigned int uexp_b10; - - if (exp_b10 < 0) - { - *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ - uexp_b10 = -exp_b10; - } - - else - uexp_b10 = exp_b10; - - cdigits = 0; - - while (uexp_b10 > 0) - { - exponent[cdigits++] = (char)(48 + uexp_b10 % 10); - uexp_b10 /= 10; - } - } - - /* Need another size check here for the exponent digits, so - * this need not be considered above. - */ - if ((int)size > cdigits) - { - while (cdigits > 0) *ascii++ = exponent[--cdigits]; - - *ascii = 0; - - return; - } - } - } - else if (!(fp >= DBL_MIN)) - { - *ascii++ = 48; /* '0' */ - *ascii = 0; - return; - } - else - { - *ascii++ = 105; /* 'i' */ - *ascii++ = 110; /* 'n' */ - *ascii++ = 102; /* 'f' */ - *ascii = 0; - return; - } - } - - /* Here on buffer too small. */ - png_error(png_ptr, "ASCII conversion buffer too small"); -} - -# endif /* FLOATING_POINT */ - -# ifdef PNG_FIXED_POINT_SUPPORTED -/* Function to format a fixed point value in ASCII. - */ -void /* PRIVATE */ -png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, - png_size_t size, png_fixed_point fp) -{ - /* Require space for 10 decimal digits, a decimal point, a minus sign and a - * trailing \0, 13 characters: - */ - if (size > 12) - { - png_uint_32 num; - - /* Avoid overflow here on the minimum integer. */ - if (fp < 0) - *ascii++ = 45, --size, num = -fp; - else - num = fp; - - if (num <= 0x80000000) /* else overflowed */ - { - unsigned int ndigits = 0, first = 16 /* flag value */; - char digits[10]; - - while (num) - { - /* Split the low digit off num: */ - unsigned int tmp = num/10; - num -= tmp*10; - digits[ndigits++] = (char)(48 + num); - /* Record the first non-zero digit, note that this is a number - * starting at 1, it's not actually the array index. - */ - if (first == 16 && num > 0) - first = ndigits; - num = tmp; - } - - if (ndigits > 0) - { - while (ndigits > 5) *ascii++ = digits[--ndigits]; - /* The remaining digits are fractional digits, ndigits is '5' or - * smaller at this point. It is certainly not zero. Check for a - * non-zero fractional digit: - */ - if (first <= 5) - { - unsigned int i; - *ascii++ = 46; /* decimal point */ - /* ndigits may be <5 for small numbers, output leading zeros - * then ndigits digits to first: - */ - i = 5; - while (ndigits < i) *ascii++ = 48, --i; - while (ndigits >= first) *ascii++ = digits[--ndigits]; - /* Don't output the trailing zeros! */ - } - } - else - *ascii++ = 48; - - /* And null terminate the string: */ - *ascii = 0; - return; - } - } - - /* Here on buffer too small. */ - png_error(png_ptr, "ASCII conversion buffer too small"); -} -# endif /* FIXED_POINT */ -#endif /* READ_SCAL */ - -#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ - !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \ - (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \ - defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \ - (defined(PNG_sCAL_SUPPORTED) && \ - defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)) -png_fixed_point -png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text) -{ - double r = floor(100000 * fp + .5); - - if (r > 2147483647. || r < -2147483648.) - png_fixed_error(png_ptr, text); - - return (png_fixed_point)r; -} -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || \ - defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) -/* muldiv functions */ -/* This API takes signed arguments and rounds the result to the nearest - * integer (or, for a fixed point number - the standard argument - to - * the nearest .00001). Overflow and divide by zero are signalled in - * the result, a boolean - true on success, false on overflow. - */ -int -png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, - png_int_32 divisor) -{ - /* Return a * times / divisor, rounded. */ - if (divisor != 0) - { - if (a == 0 || times == 0) - { - *res = 0; - return 1; - } - else - { -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = a; - r *= times; - r /= divisor; - r = floor(r+.5); - - /* A png_fixed_point is a 32-bit integer. */ - if (r <= 2147483647. && r >= -2147483648.) - { - *res = (png_fixed_point)r; - return 1; - } -#else - int negative = 0; - png_uint_32 A, T, D; - png_uint_32 s16, s32, s00; - - if (a < 0) - negative = 1, A = -a; - else - A = a; - - if (times < 0) - negative = !negative, T = -times; - else - T = times; - - if (divisor < 0) - negative = !negative, D = -divisor; - else - D = divisor; - - /* Following can't overflow because the arguments only - * have 31 bits each, however the result may be 32 bits. - */ - s16 = (A >> 16) * (T & 0xffff) + - (A & 0xffff) * (T >> 16); - /* Can't overflow because the a*times bit is only 30 - * bits at most. - */ - s32 = (A >> 16) * (T >> 16) + (s16 >> 16); - s00 = (A & 0xffff) * (T & 0xffff); - - s16 = (s16 & 0xffff) << 16; - s00 += s16; - - if (s00 < s16) - ++s32; /* carry */ - - if (s32 < D) /* else overflow */ - { - /* s32.s00 is now the 64-bit product, do a standard - * division, we know that s32 < D, so the maximum - * required shift is 31. - */ - int bitshift = 32; - png_fixed_point result = 0; /* NOTE: signed */ - - while (--bitshift >= 0) - { - png_uint_32 d32, d00; - - if (bitshift > 0) - d32 = D >> (32-bitshift), d00 = D << bitshift; - - else - d32 = 0, d00 = D; - - if (s32 > d32) - { - if (s00 < d00) --s32; /* carry */ - s32 -= d32, s00 -= d00, result += 1<= d00) - s32 = 0, s00 -= d00, result += 1<= (D >> 1)) - ++result; - - if (negative) - result = -result; - - /* Check for overflow. */ - if ((negative && result <= 0) || (!negative && result >= 0)) - { - *res = result; - return 1; - } - } -#endif - } - } - - return 0; -} -#endif /* READ_GAMMA || INCH_CONVERSIONS */ - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) -/* The following is for when the caller doesn't much care about the - * result. - */ -png_fixed_point -png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times, - png_int_32 divisor) -{ - png_fixed_point result; - - if (png_muldiv(&result, a, times, divisor)) - return result; - - png_warning(png_ptr, "fixed point overflow ignored"); - return 0; -} -#endif - -#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */ -/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ -png_fixed_point -png_reciprocal(png_fixed_point a) -{ -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = floor(1E10/a+.5); - - if (r <= 2147483647. && r >= -2147483648.) - return (png_fixed_point)r; -#else - png_fixed_point res; - - if (png_muldiv(&res, 100000, 100000, a)) - return res; -#endif - - return 0; /* error/overflow */ -} - -/* This is the shared test on whether a gamma value is 'significant' - whether - * it is worth doing gamma correction. - */ -int /* PRIVATE */ -png_gamma_significant(png_fixed_point gamma_val) -{ - return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED || - gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; -} -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* A local convenience routine. */ -static png_fixed_point -png_product2(png_fixed_point a, png_fixed_point b) -{ - /* The required result is 1/a * 1/b; the following preserves accuracy. */ -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = a * 1E-5; - r *= b; - r = floor(r+.5); - - if (r <= 2147483647. && r >= -2147483648.) - return (png_fixed_point)r; -#else - png_fixed_point res; - - if (png_muldiv(&res, a, b, 100000)) - return res; -#endif - - return 0; /* overflow */ -} - -/* The inverse of the above. */ -png_fixed_point -png_reciprocal2(png_fixed_point a, png_fixed_point b) -{ - /* The required result is 1/a * 1/b; the following preserves accuracy. */ -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = 1E15/a; - r /= b; - r = floor(r+.5); - - if (r <= 2147483647. && r >= -2147483648.) - return (png_fixed_point)r; -#else - /* This may overflow because the range of png_fixed_point isn't symmetric, - * but this API is only used for the product of file and screen gamma so it - * doesn't matter that the smallest number it can produce is 1/21474, not - * 1/100000 - */ - png_fixed_point res = png_product2(a, b); - - if (res != 0) - return png_reciprocal(res); -#endif - - return 0; /* overflow */ -} -#endif /* READ_GAMMA */ - -#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */ -#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED -/* Fixed point gamma. - * - * The code to calculate the tables used below can be found in the shell script - * contrib/tools/intgamma.sh - * - * To calculate gamma this code implements fast log() and exp() calls using only - * fixed point arithmetic. This code has sufficient precision for either 8-bit - * or 16-bit sample values. - * - * The tables used here were calculated using simple 'bc' programs, but C double - * precision floating point arithmetic would work fine. - * - * 8-bit log table - * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to - * 255, so it's the base 2 logarithm of a normalized 8-bit floating point - * mantissa. The numbers are 32-bit fractions. - */ -static const png_uint_32 -png_8bit_l2[128] = -{ - 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U, - 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U, - 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U, - 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U, - 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U, - 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U, - 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U, - 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U, - 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U, - 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U, - 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U, - 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U, - 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U, - 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U, - 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U, - 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U, - 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U, - 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U, - 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U, - 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U, - 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U, - 24347096U, 0U - -#if 0 - /* The following are the values for 16-bit tables - these work fine for the - * 8-bit conversions but produce very slightly larger errors in the 16-bit - * log (about 1.2 as opposed to 0.7 absolute error in the final value). To - * use these all the shifts below must be adjusted appropriately. - */ - 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054, - 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803, - 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068, - 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782, - 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887, - 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339, - 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098, - 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132, - 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415, - 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523, - 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495, - 1119, 744, 372 -#endif -}; - -static png_int_32 -png_log8bit(unsigned int x) -{ - unsigned int lg2 = 0; - /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log, - * because the log is actually negate that means adding 1. The final - * returned value thus has the range 0 (for 255 input) to 7.994 (for 1 - * input), return -1 for the overflow (log 0) case, - so the result is - * always at most 19 bits. - */ - if ((x &= 0xff) == 0) - return -1; - - if ((x & 0xf0) == 0) - lg2 = 4, x <<= 4; - - if ((x & 0xc0) == 0) - lg2 += 2, x <<= 2; - - if ((x & 0x80) == 0) - lg2 += 1, x <<= 1; - - /* result is at most 19 bits, so this cast is safe: */ - return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16)); -} - -/* The above gives exact (to 16 binary places) log2 values for 8-bit images, - * for 16-bit images we use the most significant 8 bits of the 16-bit value to - * get an approximation then multiply the approximation by a correction factor - * determined by the remaining up to 8 bits. This requires an additional step - * in the 16-bit case. - * - * We want log2(value/65535), we have log2(v'/255), where: - * - * value = v' * 256 + v'' - * = v' * f - * - * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128 - * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less - * than 258. The final factor also needs to correct for the fact that our 8-bit - * value is scaled by 255, whereas the 16-bit values must be scaled by 65535. - * - * This gives a final formula using a calculated value 'x' which is value/v' and - * scaling by 65536 to match the above table: - * - * log2(x/257) * 65536 - * - * Since these numbers are so close to '1' we can use simple linear - * interpolation between the two end values 256/257 (result -368.61) and 258/257 - * (result 367.179). The values used below are scaled by a further 64 to give - * 16-bit precision in the interpolation: - * - * Start (256): -23591 - * Zero (257): 0 - * End (258): 23499 - */ -static png_int_32 -png_log16bit(png_uint_32 x) -{ - unsigned int lg2 = 0; - - /* As above, but now the input has 16 bits. */ - if ((x &= 0xffff) == 0) - return -1; - - if ((x & 0xff00) == 0) - lg2 = 8, x <<= 8; - - if ((x & 0xf000) == 0) - lg2 += 4, x <<= 4; - - if ((x & 0xc000) == 0) - lg2 += 2, x <<= 2; - - if ((x & 0x8000) == 0) - lg2 += 1, x <<= 1; - - /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional - * value. - */ - lg2 <<= 28; - lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4; - - /* Now we need to interpolate the factor, this requires a division by the top - * 8 bits. Do this with maximum precision. - */ - x = ((x << 16) + (x >> 9)) / (x >> 8); - - /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24, - * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly - * 16 bits to interpolate to get the low bits of the result. Round the - * answer. Note that the end point values are scaled by 64 to retain overall - * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust - * the overall scaling by 6-12. Round at every step. - */ - x -= 1U << 24; - - if (x <= 65536U) /* <= '257' */ - lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12); - - else - lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12); - - /* Safe, because the result can't have more than 20 bits: */ - return (png_int_32)((lg2 + 2048) >> 12); -} - -/* The 'exp()' case must invert the above, taking a 20-bit fixed point - * logarithmic value and returning a 16 or 8-bit number as appropriate. In - * each case only the low 16 bits are relevant - the fraction - since the - * integer bits (the top 4) simply determine a shift. - * - * The worst case is the 16-bit distinction between 65535 and 65534, this - * requires perhaps spurious accuracty in the decoding of the logarithm to - * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance - * of getting this accuracy in practice. - * - * To deal with this the following exp() function works out the exponent of the - * frational part of the logarithm by using an accurate 32-bit value from the - * top four fractional bits then multiplying in the remaining bits. - */ -static const png_uint_32 -png_32bit_exp[16] = -{ - /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */ - 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U, - 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U, - 2553802834U, 2445529972U, 2341847524U, 2242560872U -}; - -/* Adjustment table; provided to explain the numbers in the code below. */ -#if 0 -for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"} - 11 44937.64284865548751208448 - 10 45180.98734845585101160448 - 9 45303.31936980687359311872 - 8 45364.65110595323018870784 - 7 45395.35850361789624614912 - 6 45410.72259715102037508096 - 5 45418.40724413220722311168 - 4 45422.25021786898173001728 - 3 45424.17186732298419044352 - 2 45425.13273269940811464704 - 1 45425.61317555035558641664 - 0 45425.85339951654943850496 -#endif - -static png_uint_32 -png_exp(png_fixed_point x) -{ - if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */ - { - /* Obtain a 4-bit approximation */ - png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf]; - - /* Incorporate the low 12 bits - these decrease the returned value by - * multiplying by a number less than 1 if the bit is set. The multiplier - * is determined by the above table and the shift. Notice that the values - * converge on 45426 and this is used to allow linear interpolation of the - * low bits. - */ - if (x & 0x800) - e -= (((e >> 16) * 44938U) + 16U) >> 5; - - if (x & 0x400) - e -= (((e >> 16) * 45181U) + 32U) >> 6; - - if (x & 0x200) - e -= (((e >> 16) * 45303U) + 64U) >> 7; - - if (x & 0x100) - e -= (((e >> 16) * 45365U) + 128U) >> 8; - - if (x & 0x080) - e -= (((e >> 16) * 45395U) + 256U) >> 9; - - if (x & 0x040) - e -= (((e >> 16) * 45410U) + 512U) >> 10; - - /* And handle the low 6 bits in a single block. */ - e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9; - - /* Handle the upper bits of x. */ - e >>= x >> 16; - return e; - } - - /* Check for overflow */ - if (x <= 0) - return png_32bit_exp[0]; - - /* Else underflow */ - return 0; -} - -static png_byte -png_exp8bit(png_fixed_point lg2) -{ - /* Get a 32-bit value: */ - png_uint_32 x = png_exp(lg2); - - /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the - * second, rounding, step can't overflow because of the first, subtraction, - * step. - */ - x -= x >> 8; - return (png_byte)((x + 0x7fffffU) >> 24); -} - -static png_uint_16 -png_exp16bit(png_fixed_point lg2) -{ - /* Get a 32-bit value: */ - png_uint_32 x = png_exp(lg2); - - /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */ - x -= x >> 16; - return (png_uint_16)((x + 32767U) >> 16); -} -#endif /* FLOATING_ARITHMETIC */ - -png_byte -png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) -{ - if (value > 0 && value < 255) - { -# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = floor(255*pow(value/255.,gamma_val*.00001)+.5); - return (png_byte)r; -# else - png_int_32 lg2 = png_log8bit(value); - png_fixed_point res; - - if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) - return png_exp8bit(res); - - /* Overflow. */ - value = 0; -# endif - } - - return (png_byte)value; -} - -png_uint_16 -png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) -{ - if (value > 0 && value < 65535) - { -# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5); - return (png_uint_16)r; -# else - png_int_32 lg2 = png_log16bit(value); - png_fixed_point res; - - if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) - return png_exp16bit(res); - - /* Overflow. */ - value = 0; -# endif - } - - return (png_uint_16)value; -} - -/* This does the right thing based on the bit_depth field of the - * png_struct, interpreting values as 8-bit or 16-bit. While the result - * is nominally a 16-bit value if bit depth is 8 then the result is - * 8-bit (as are the arguments.) - */ -png_uint_16 /* PRIVATE */ -png_gamma_correct(png_structrp png_ptr, unsigned int value, - png_fixed_point gamma_val) -{ - if (png_ptr->bit_depth == 8) - return png_gamma_8bit_correct(value, gamma_val); - - else - return png_gamma_16bit_correct(value, gamma_val); -} - -/* Internal function to build a single 16-bit table - the table consists of - * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount - * to shift the input values right (or 16-number_of_signifiant_bits). - * - * The caller is responsible for ensuring that the table gets cleaned up on - * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument - * should be somewhere that will be cleaned. - */ -static void -png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) -{ - /* Various values derived from 'shift': */ - PNG_CONST unsigned int num = 1U << (8U - shift); - PNG_CONST unsigned int max = (1U << (16U - shift))-1U; - PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); - unsigned int i; - - png_uint_16pp table = *ptable = - (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p))); - - for (i = 0; i < num; i++) - { - png_uint_16p sub_table = table[i] = - (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16))); - - /* The 'threshold' test is repeated here because it can arise for one of - * the 16-bit tables even if the others don't hit it. - */ - if (png_gamma_significant(gamma_val)) - { - /* The old code would overflow at the end and this would cause the - * 'pow' function to return a result >1, resulting in an - * arithmetic error. This code follows the spec exactly; ig is - * the recovered input sample, it always has 8-16 bits. - * - * We want input * 65535/max, rounded, the arithmetic fits in 32 - * bits (unsigned) so long as max <= 32767. - */ - unsigned int j; - for (j = 0; j < 256; j++) - { - png_uint_32 ig = (j << (8-shift)) + i; -# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - /* Inline the 'max' scaling operation: */ - double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5); - sub_table[j] = (png_uint_16)d; -# else - if (shift) - ig = (ig * 65535U + max_by_2)/max; - - sub_table[j] = png_gamma_16bit_correct(ig, gamma_val); -# endif - } - } - else - { - /* We must still build a table, but do it the fast way. */ - unsigned int j; - - for (j = 0; j < 256; j++) - { - png_uint_32 ig = (j << (8-shift)) + i; - - if (shift) - ig = (ig * 65535U + max_by_2)/max; - - sub_table[j] = (png_uint_16)ig; - } - } - } -} - -/* NOTE: this function expects the *inverse* of the overall gamma transformation - * required. - */ -static void -png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) -{ - PNG_CONST unsigned int num = 1U << (8U - shift); - PNG_CONST unsigned int max = (1U << (16U - shift))-1U; - unsigned int i; - png_uint_32 last; - - png_uint_16pp table = *ptable = - (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p))); - - /* 'num' is the number of tables and also the number of low bits of low - * bits of the input 16-bit value used to select a table. Each table is - * itself index by the high 8 bits of the value. - */ - for (i = 0; i < num; i++) - table[i] = (png_uint_16p)png_malloc(png_ptr, - 256 * (sizeof (png_uint_16))); - - /* 'gamma_val' is set to the reciprocal of the value calculated above, so - * pow(out,g) is an *input* value. 'last' is the last input value set. - * - * In the loop 'i' is used to find output values. Since the output is - * 8-bit there are only 256 possible values. The tables are set up to - * select the closest possible output value for each input by finding - * the input value at the boundary between each pair of output values - * and filling the table up to that boundary with the lower output - * value. - * - * The boundary values are 0.5,1.5..253.5,254.5. Since these are 9-bit - * values the code below uses a 16-bit value in i; the values start at - * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last - * entries are filled with 255). Start i at 128 and fill all 'last' - * table entries <= 'max' - */ - last = 0; - for (i = 0; i < 255; ++i) /* 8-bit output value */ - { - /* Find the corresponding maximum input value */ - png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */ - - /* Find the boundary value in 16 bits: */ - png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val); - - /* Adjust (round) to (16-shift) bits: */ - bound = (bound * max + 32768U)/65535U + 1U; - - while (last < bound) - { - table[last & (0xffU >> shift)][last >> (8U - shift)] = out; - last++; - } - } - - /* And fill in the final entries. */ - while (last < (num << 8)) - { - table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U; - last++; - } -} - -/* Build a single 8-bit table: same as the 16-bit case but much simpler (and - * typically much faster). Note that libpng currently does no sBIT processing - * (apparently contrary to the spec) so a 256 entry table is always generated. - */ -static void -png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable, - PNG_CONST png_fixed_point gamma_val) -{ - unsigned int i; - png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); - - if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++) - table[i] = png_gamma_8bit_correct(i, gamma_val); - - else for (i=0; i<256; ++i) - table[i] = (png_byte)i; -} - -/* Used from png_read_destroy and below to release the memory used by the gamma - * tables. - */ -void /* PRIVATE */ -png_destroy_gamma_table(png_structrp png_ptr) -{ - png_free(png_ptr, png_ptr->gamma_table); - png_ptr->gamma_table = NULL; - - if (png_ptr->gamma_16_table != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_table[i]); - } - png_free(png_ptr, png_ptr->gamma_16_table); - png_ptr->gamma_16_table = NULL; - } - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - png_free(png_ptr, png_ptr->gamma_from_1); - png_ptr->gamma_from_1 = NULL; - png_free(png_ptr, png_ptr->gamma_to_1); - png_ptr->gamma_to_1 = NULL; - - if (png_ptr->gamma_16_from_1 != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_from_1[i]); - } - png_free(png_ptr, png_ptr->gamma_16_from_1); - png_ptr->gamma_16_from_1 = NULL; - } - if (png_ptr->gamma_16_to_1 != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_to_1[i]); - } - png_free(png_ptr, png_ptr->gamma_16_to_1); - png_ptr->gamma_16_to_1 = NULL; - } -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ -} - -/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit - * tables, we don't make a full table if we are reducing to 8-bit in - * the future. Note also how the gamma_16 tables are segmented so that - * we don't need to allocate > 64K chunks for a full 16-bit table. - */ -void /* PRIVATE */ -png_build_gamma_table(png_structrp png_ptr, int bit_depth) -{ - png_debug(1, "in png_build_gamma_table"); - - /* Remove any existing table; this copes with multiple calls to - * png_read_update_info. The warning is because building the gamma tables - * multiple times is a performance hit - it's harmless but the ability to call - * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible - * to warn if the app introduces such a hit. - */ - if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) - { - png_warning(png_ptr, "gamma table being rebuilt"); - png_destroy_gamma_table(png_ptr); - } - - if (bit_depth <= 8) - { - png_build_8bit_table(png_ptr, &png_ptr->gamma_table, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) - { - png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, - png_reciprocal(png_ptr->colorspace.gamma)); - - png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); - } -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ - } - else - { - png_byte shift, sig_bit; - - if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - { - sig_bit = png_ptr->sig_bit.red; - - if (png_ptr->sig_bit.green > sig_bit) - sig_bit = png_ptr->sig_bit.green; - - if (png_ptr->sig_bit.blue > sig_bit) - sig_bit = png_ptr->sig_bit.blue; - } - else - sig_bit = png_ptr->sig_bit.gray; - - /* 16-bit gamma code uses this equation: - * - * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] - * - * Where 'iv' is the input color value and 'ov' is the output value - - * pow(iv, gamma). - * - * Thus the gamma table consists of up to 256 256 entry tables. The table - * is selected by the (8-gamma_shift) most significant of the low 8 bits of - * the color value then indexed by the upper 8 bits: - * - * table[low bits][high 8 bits] - * - * So the table 'n' corresponds to all those 'iv' of: - * - * ..<(n+1 << gamma_shift)-1> - * - */ - if (sig_bit > 0 && sig_bit < 16U) - shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */ - - else - shift = 0; /* keep all 16 bits */ - - if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) - { - /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively - * the significant bits in the *input* when the output will - * eventually be 8 bits. By default it is 11. - */ - if (shift < (16U - PNG_MAX_GAMMA_8)) - shift = (16U - PNG_MAX_GAMMA_8); - } - - if (shift > 8U) - shift = 8U; /* Guarantees at least one table! */ - - png_ptr->gamma_shift = shift; - -#ifdef PNG_16BIT_SUPPORTED - /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now - * PNG_COMPOSE). This effectively smashed the background calculation for - * 16-bit output because the 8-bit table assumes the result will be reduced - * to 8 bits. - */ - if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) -#endif - png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); - -#ifdef PNG_16BIT_SUPPORTED - else - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) - { - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, - png_reciprocal(png_ptr->colorspace.gamma)); - - /* Notice that the '16 from 1' table should be full precision, however - * the lookup on this table still uses gamma_shift, so it can't be. - * TODO: fix this. - */ - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); - } -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ - } -} -#endif /* READ_GAMMA */ - -/* HARDWARE OPTION SUPPORT */ -#ifdef PNG_SET_OPTION_SUPPORTED -int PNGAPI -png_set_option(png_structrp png_ptr, int option, int onoff) -{ - if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT && - (option & 1) == 0) - { - int mask = 3 << option; - int setting = (2 + (onoff != 0)) << option; - int current = png_ptr->options; - - png_ptr->options = (png_byte)((current & ~mask) | setting); - - return (current & mask) >> option; - } - - return PNG_OPTION_INVALID; -} -#endif - -/* sRGB support */ -#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ - defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) -/* sRGB conversion tables; these are machine generated with the code in - * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the - * specification (see the article at http://en.wikipedia.org/wiki/SRGB) - * is used, not the gamma=1/2.2 approximation use elsewhere in libpng. - * The sRGB to linear table is exact (to the nearest 16 bit linear fraction). - * The inverse (linear to sRGB) table has accuracies as follows: - * - * For all possible (255*65535+1) input values: - * - * error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact - * - * For the input values corresponding to the 65536 16-bit values: - * - * error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact - * - * In all cases the inexact readings are off by one. - */ - -#ifdef PNG_SIMPLIFIED_READ_SUPPORTED -/* The convert-to-sRGB table is only currently required for read. */ -const png_uint_16 png_sRGB_table[256] = -{ - 0,20,40,60,80,99,119,139, - 159,179,199,219,241,264,288,313, - 340,367,396,427,458,491,526,562, - 599,637,677,718,761,805,851,898, - 947,997,1048,1101,1156,1212,1270,1330, - 1391,1453,1517,1583,1651,1720,1790,1863, - 1937,2013,2090,2170,2250,2333,2418,2504, - 2592,2681,2773,2866,2961,3058,3157,3258, - 3360,3464,3570,3678,3788,3900,4014,4129, - 4247,4366,4488,4611,4736,4864,4993,5124, - 5257,5392,5530,5669,5810,5953,6099,6246, - 6395,6547,6700,6856,7014,7174,7335,7500, - 7666,7834,8004,8177,8352,8528,8708,8889, - 9072,9258,9445,9635,9828,10022,10219,10417, - 10619,10822,11028,11235,11446,11658,11873,12090, - 12309,12530,12754,12980,13209,13440,13673,13909, - 14146,14387,14629,14874,15122,15371,15623,15878, - 16135,16394,16656,16920,17187,17456,17727,18001, - 18277,18556,18837,19121,19407,19696,19987,20281, - 20577,20876,21177,21481,21787,22096,22407,22721, - 23038,23357,23678,24002,24329,24658,24990,25325, - 25662,26001,26344,26688,27036,27386,27739,28094, - 28452,28813,29176,29542,29911,30282,30656,31033, - 31412,31794,32179,32567,32957,33350,33745,34143, - 34544,34948,35355,35764,36176,36591,37008,37429, - 37852,38278,38706,39138,39572,40009,40449,40891, - 41337,41785,42236,42690,43147,43606,44069,44534, - 45002,45473,45947,46423,46903,47385,47871,48359, - 48850,49344,49841,50341,50844,51349,51858,52369, - 52884,53401,53921,54445,54971,55500,56032,56567, - 57105,57646,58190,58737,59287,59840,60396,60955, - 61517,62082,62650,63221,63795,64372,64952,65535 -}; - -#endif /* simplified read only */ - -/* The base/delta tables are required for both read and write (but currently - * only the simplified versions.) - */ -const png_uint_16 png_sRGB_base[512] = -{ - 128,1782,3383,4644,5675,6564,7357,8074, - 8732,9346,9921,10463,10977,11466,11935,12384, - 12816,13233,13634,14024,14402,14769,15125,15473, - 15812,16142,16466,16781,17090,17393,17690,17981, - 18266,18546,18822,19093,19359,19621,19879,20133, - 20383,20630,20873,21113,21349,21583,21813,22041, - 22265,22487,22707,22923,23138,23350,23559,23767, - 23972,24175,24376,24575,24772,24967,25160,25352, - 25542,25730,25916,26101,26284,26465,26645,26823, - 27000,27176,27350,27523,27695,27865,28034,28201, - 28368,28533,28697,28860,29021,29182,29341,29500, - 29657,29813,29969,30123,30276,30429,30580,30730, - 30880,31028,31176,31323,31469,31614,31758,31902, - 32045,32186,32327,32468,32607,32746,32884,33021, - 33158,33294,33429,33564,33697,33831,33963,34095, - 34226,34357,34486,34616,34744,34873,35000,35127, - 35253,35379,35504,35629,35753,35876,35999,36122, - 36244,36365,36486,36606,36726,36845,36964,37083, - 37201,37318,37435,37551,37668,37783,37898,38013, - 38127,38241,38354,38467,38580,38692,38803,38915, - 39026,39136,39246,39356,39465,39574,39682,39790, - 39898,40005,40112,40219,40325,40431,40537,40642, - 40747,40851,40955,41059,41163,41266,41369,41471, - 41573,41675,41777,41878,41979,42079,42179,42279, - 42379,42478,42577,42676,42775,42873,42971,43068, - 43165,43262,43359,43456,43552,43648,43743,43839, - 43934,44028,44123,44217,44311,44405,44499,44592, - 44685,44778,44870,44962,45054,45146,45238,45329, - 45420,45511,45601,45692,45782,45872,45961,46051, - 46140,46229,46318,46406,46494,46583,46670,46758, - 46846,46933,47020,47107,47193,47280,47366,47452, - 47538,47623,47709,47794,47879,47964,48048,48133, - 48217,48301,48385,48468,48552,48635,48718,48801, - 48884,48966,49048,49131,49213,49294,49376,49458, - 49539,49620,49701,49782,49862,49943,50023,50103, - 50183,50263,50342,50422,50501,50580,50659,50738, - 50816,50895,50973,51051,51129,51207,51285,51362, - 51439,51517,51594,51671,51747,51824,51900,51977, - 52053,52129,52205,52280,52356,52432,52507,52582, - 52657,52732,52807,52881,52956,53030,53104,53178, - 53252,53326,53400,53473,53546,53620,53693,53766, - 53839,53911,53984,54056,54129,54201,54273,54345, - 54417,54489,54560,54632,54703,54774,54845,54916, - 54987,55058,55129,55199,55269,55340,55410,55480, - 55550,55620,55689,55759,55828,55898,55967,56036, - 56105,56174,56243,56311,56380,56448,56517,56585, - 56653,56721,56789,56857,56924,56992,57059,57127, - 57194,57261,57328,57395,57462,57529,57595,57662, - 57728,57795,57861,57927,57993,58059,58125,58191, - 58256,58322,58387,58453,58518,58583,58648,58713, - 58778,58843,58908,58972,59037,59101,59165,59230, - 59294,59358,59422,59486,59549,59613,59677,59740, - 59804,59867,59930,59993,60056,60119,60182,60245, - 60308,60370,60433,60495,60558,60620,60682,60744, - 60806,60868,60930,60992,61054,61115,61177,61238, - 61300,61361,61422,61483,61544,61605,61666,61727, - 61788,61848,61909,61969,62030,62090,62150,62211, - 62271,62331,62391,62450,62510,62570,62630,62689, - 62749,62808,62867,62927,62986,63045,63104,63163, - 63222,63281,63340,63398,63457,63515,63574,63632, - 63691,63749,63807,63865,63923,63981,64039,64097, - 64155,64212,64270,64328,64385,64443,64500,64557, - 64614,64672,64729,64786,64843,64900,64956,65013, - 65070,65126,65183,65239,65296,65352,65409,65465 -}; - -const png_byte png_sRGB_delta[512] = -{ - 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54, - 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36, - 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28, - 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24, - 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21, - 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19, - 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17, - 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16, - 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14, - 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13, - 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12, - 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, - 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11, - 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, - 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, - 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, - 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, - 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 -}; -#endif /* SIMPLIFIED READ/WRITE sRGB support */ - -/* SIMPLIFIED READ/WRITE SUPPORT */ -#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ - defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) -static int -png_image_free_function(png_voidp argument) -{ - png_imagep image = png_voidcast(png_imagep, argument); - png_controlp cp = image->opaque; - png_control c; - - /* Double check that we have a png_ptr - it should be impossible to get here - * without one. - */ - if (cp->png_ptr == NULL) - return 0; - - /* First free any data held in the control structure. */ -# ifdef PNG_STDIO_SUPPORTED - if (cp->owned_file) - { - FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr); - cp->owned_file = 0; - - /* Ignore errors here. */ - if (fp != NULL) - { - cp->png_ptr->io_ptr = NULL; - (void)fclose(fp); - } - } -# endif - - /* Copy the control structure so that the original, allocated, version can be - * safely freed. Notice that a png_error here stops the remainder of the - * cleanup, but this is probably fine because that would indicate bad memory - * problems anyway. - */ - c = *cp; - image->opaque = &c; - png_free(c.png_ptr, cp); - - /* Then the structures, calling the correct API. */ - if (c.for_write) - { -# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED - png_destroy_write_struct(&c.png_ptr, &c.info_ptr); -# else - png_error(c.png_ptr, "simplified write not supported"); -# endif - } - else - { -# ifdef PNG_SIMPLIFIED_READ_SUPPORTED - png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL); -# else - png_error(c.png_ptr, "simplified read not supported"); -# endif - } - - /* Success. */ - return 1; -} - -void PNGAPI -png_image_free(png_imagep image) -{ - /* Safely call the real function, but only if doing so is safe at this point - * (if not inside an error handling context). Otherwise assume - * png_safe_execute will call this API after the return. - */ - if (image != NULL && image->opaque != NULL && - image->opaque->error_buf == NULL) - { - /* Ignore errors here: */ - (void)png_safe_execute(image, png_image_free_function, image); - image->opaque = NULL; - } -} - -int /* PRIVATE */ -png_image_error(png_imagep image, png_const_charp error_message) -{ - /* Utility to log an error. */ - png_safecat(image->message, (sizeof image->message), 0, error_message); - image->warning_or_error |= PNG_IMAGE_ERROR; - png_image_free(image); - return 0; -} - -#endif /* SIMPLIFIED READ/WRITE */ -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* png.c - location for general purpose libpng functions + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef png_libpng_version_1_7_0beta35 Your_png_h_is_not_version_1_7_0beta35; + +/* Tells libpng that we have already handled the first "num_bytes" bytes + * of the PNG file signature. If the PNG data is embedded into another + * stream we can set num_bytes = 8 so that libpng will not attempt to read + * or write any of the magic bytes before it starts on the IHDR. + */ + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_set_sig_bytes(png_structrp png_ptr, int num_bytes) +{ + png_debug(1, "in png_set_sig_bytes"); + + if (png_ptr == NULL) + return; + + if (num_bytes > 8) + png_error(png_ptr, "Too many bytes for PNG signature"); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behavior as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + + if (num_to_check > 8) + num_to_check = 8; + + else if (num_to_check < 1) + return (-1); + + if (start > 7) + return (-1); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Function to allocate memory for zlib */ +PNG_FUNCTION(voidpf /* PRIVATE */, +png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) +{ + png_alloc_size_t num_bytes = size; + + if (png_ptr == NULL) + return NULL; + + if (items >= (~(png_alloc_size_t)0)/size) + { + png_warning (png_voidcast(png_structrp, png_ptr), + "Potential overflow in png_zalloc()"); + return NULL; + } + + num_bytes *= items; + return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes); +} + +/* Function to free memory for zlib */ +void /* PRIVATE */ +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free(png_voidcast(png_const_structrp,png_ptr), ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structrp png_ptr) +{ + /* The cast is safe because the crc is a 32 bit value. */ + png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)) + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + /* 'uLong' is defined in zlib.h as unsigned long; this means that on some + * systems it is a 64 bit value. crc32, however, returns 32 bits so the + * following cast is safe. 'uInt' may be no more than 16 bits, so it is + * necessary to perform a loop here. + */ + if (need_crc && length > 0) + { + uLong crc = png_ptr->crc; /* Should never issue a warning */ + + do + { + uInt safe_length = (uInt)length; + if (safe_length == 0) + safe_length = (uInt)-1; /* evil, but safe */ + + crc = crc32(crc, ptr, safe_length); + + /* The following should never issue compiler warnings; if they do the + * target system has characteristics that will probably violate other + * assumptions within the libpng code. + */ + ptr += safe_length; + length -= safe_length; + } + while (length > 0); + + /* And the following is always safe because the crc is only 32 bits. */ + png_ptr->crc = (png_uint_32)crc; + } +} + +/* Check a user supplied version number, called from both read and write + * functions that create a png_struct. + */ +int +png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) +{ + if (user_png_ver != NULL) + { + int i = 0; + + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + + else + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first and third digits (note that when we reach version + * 1.10 we will need to check the fourth symbol, namely user_png_ver[3]). + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && (user_png_ver[2] != png_libpng_ver[2] || + user_png_ver[3] != png_libpng_ver[3])) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#ifdef PNG_WARNINGS_SUPPORTED + size_t pos = 0; + char m[128]; + + pos = png_safecat(m, (sizeof m), pos, + "Application built with libpng-"); + pos = png_safecat(m, (sizeof m), pos, user_png_ver); + pos = png_safecat(m, (sizeof m), pos, " but running with "); + pos = png_safecat(m, (sizeof m), pos, png_libpng_ver); + PNG_UNUSED(pos) + + png_warning(png_ptr, m); +#endif + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + + return 0; + } + } + + /* Success return. */ + return 1; +} + +/* Generic function to create a png_struct for either read or write - this + * contains the common initialization. + */ +PNG_FUNCTION(png_structp /* PRIVATE */, +png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +{ + png_struct create_struct; +# ifdef PNG_SETJMP_SUPPORTED + jmp_buf create_jmp_buf; +# endif + + /* This temporary stack-allocated structure is used to provide a place to + * build enough context to allow the user provided memory allocator (if any) + * to be called. + */ + memset(&create_struct, 0, (sizeof create_struct)); + + /* These limits are only used on read at present, and if READ is not turned + * on neither will USER_LIMITS be. The width/height and chunk malloc limits + * are constants, so if they cannot be set they don't get defined in + * png_struct, the user_chunk_cache limits is a down-counter, when it reaches + * 1 no more chunks will be handled. 0 means unlimited, consequently the + * limit is 1 more than the number of chunks that will be handled. + */ +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + create_struct.user_width_max = PNG_USER_WIDTH_MAX; + create_struct.user_height_max = PNG_USER_HEIGHT_MAX; + create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; +# endif +# ifdef PNG_USER_LIMITS_SUPPORTED + /* Must exist even if the initial value is constant */ + create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; +# endif + + /* The following two API calls simply set fields in png_struct, so it is safe + * to do them now even though error handling is not yet set up. + */ +# ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn); +# else + PNG_UNUSED(mem_ptr) + PNG_UNUSED(malloc_fn) + PNG_UNUSED(free_fn) +# endif + + /* (*error_fn) can return control to the caller after the error_ptr is set, + * this will result in a memory leak unless the error_fn does something + * extremely sophisticated. The design lacks merit but is implicit in the + * API. + */ + png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn); + +# ifdef PNG_SETJMP_SUPPORTED + if (!setjmp(create_jmp_buf)) + { + /* Temporarily fake out the longjmp information until we have + * successfully completed this function. This only works if we have + * setjmp() support compiled in, but it is safe - this stuff should + * never happen. + */ + create_struct.jmp_buf_ptr = &create_jmp_buf; + create_struct.jmp_buf_size = 0; /*stack allocation*/ + create_struct.longjmp_fn = longjmp; +# else + { +# endif + /* Call the general version checker (shared with read and write code): + */ + if (png_user_version_check(&create_struct, user_png_ver)) + { + png_structrp png_ptr = png_voidcast(png_structrp, + png_malloc_warn(&create_struct, (sizeof *png_ptr))); + + if (png_ptr != NULL) + { + /* png_ptr->zstream holds a back-pointer to the png_struct, so + * this can only be done now: + */ + create_struct.zstream.zalloc = png_zalloc; + create_struct.zstream.zfree = png_zfree; + create_struct.zstream.opaque = png_ptr; + +# ifdef PNG_SETJMP_SUPPORTED + /* Eliminate the local error handling: */ + create_struct.jmp_buf_ptr = NULL; + create_struct.jmp_buf_size = 0; + create_struct.longjmp_fn = 0; +# endif + + *png_ptr = create_struct; + + /* This is the successful return point */ + return png_ptr; + } + } + } + + /* A longjmp because of a bug in the application storage allocator or a + * simple failure to allocate the png_struct. + */ + return NULL; +} + +/* Allocate the memory for an info_struct for the application. */ +PNG_FUNCTION(png_infop,PNGAPI +png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED) +{ + png_inforp info_ptr; + + png_debug(1, "in png_create_info_struct"); + + if (png_ptr == NULL) + return NULL; + + /* Use the internal API that does not (or at least should not) error out, so + * that this call always returns ok. The application typically sets up the + * error handling *after* creating the info_struct because this is the way it + * has always been done in 'example.c'. + */ + info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr, + (sizeof *info_ptr))); + + if (info_ptr != NULL) + memset(info_ptr, 0, (sizeof *info_ptr)); + + return info_ptr; +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. From libpng 1.6.0 this function is also used + * internally to implement the png_info release part of the 'struct' destroy + * APIs. This ensures that all possible approaches free the same data (all of + * it). + */ +void PNGAPI +png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr) +{ + png_inforp info_ptr = NULL; + + png_debug(1, "in png_destroy_info_struct"); + + if (png_ptr == NULL) + return; + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + /* Do this first in case of an error below; if the app implements its own + * memory management this can lead to png_free calling png_error, which + * will abort this routine and return control to the app error handler. + * An infinite loop may result if it then tries to free the same info + * ptr. + */ + *info_ptr_ptr = NULL; + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + memset(info_ptr, 0, (sizeof *info_ptr)); + png_free(png_ptr, info_ptr); + } +} + +void PNGAPI +png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +#ifdef PNG_TEXT_SUPPORTED + /* Free text item num or (if num == -1) all text items */ + if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } + } +#endif + +#ifdef PNG_tRNS_SUPPORTED + /* Free any tRNS entry */ + if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) + { + info_ptr->valid &= ~PNG_INFO_tRNS; + png_free(png_ptr, info_ptr->trans_alpha); + info_ptr->trans_alpha = NULL; + info_ptr->num_trans = 0; + } +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* Free any sCAL entry */ + if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; + info_ptr->valid &= ~PNG_INFO_sCAL; + } +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* Free any pCAL entry */ + if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + unsigned int i; + for (i = 0; i < info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i] = NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; + } +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* Free any profile entry */ + if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; + } +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ + if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + + else + { + if (info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, (int)i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } + } +#endif + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED + if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + + else + { + int i; + + if (info_ptr->unknown_chunks_num) + { + for (i = 0; i < info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, (int)i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } + } +#endif + +#ifdef PNG_hIST_SUPPORTED + /* Free any hIST entry */ + if ((mask & PNG_FREE_HIST) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; + } +#endif + + /* Free any PLTE entry that was internally allocated */ + if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; + info_ptr->num_palette = 0; + } + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Free any image bits attached to the info structure */ + if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) + { + if (info_ptr->row_pointers) + { + png_uint_32 row; + for (row = 0; row < info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row] = NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers = NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; + } +#endif + + if (num != -1) + mask &= ~PNG_FREE_MUL; + + info_ptr->free_me &= ~mask; +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return (png_ptr->io_ptr); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_STDIO_SUPPORTED +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a + * function of your own because "FILE *" isn't necessarily available. + */ +void PNGAPI +png_init_io(png_structrp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io"); + + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = (png_voidp)fp; +} +# endif + +#ifdef PNG_SAVE_INT_32_SUPPORTED +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. Note that, + * the following works correctly even if png_int_32 has more than 32 bits + * (compare the more complex code required on read for sign extension.) + */ +void PNGAPI +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} +#endif + +# ifdef PNG_TIME_RFC1123_SUPPORTED +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +int PNGAPI +png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if (out == NULL) + return 0; + + if (ptime->year > 9999 /* RFC1123 limitation */ || + ptime->month == 0 || ptime->month > 12 || + ptime->day == 0 || ptime->day > 31 || + ptime->hour > 23 || ptime->minute > 59 || + ptime->second > 60) + return 0; + + { + size_t pos = 0; + char number_buf[5]; /* enough for a four-digit year */ + +# define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string)) +# define APPEND_NUMBER(format, value)\ + APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value))) +# define APPEND(ch) if (pos < 28) out[pos++] = (ch) + + APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day); + APPEND(' '); + APPEND_STRING(short_months[(ptime->month - 1)]); + APPEND(' '); + APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year); + APPEND(' '); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour); + APPEND(':'); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute); + APPEND(':'); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second); + APPEND_STRING(" +0000"); /* This reliably terminates the buffer */ + +# undef APPEND +# undef APPEND_NUMBER +# undef APPEND_STRING + } + + return 1; +} +# endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +png_const_charp PNGAPI +png_get_copyright(png_const_structrp png_ptr) +{ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef PNG_STRING_COPYRIGHT + return PNG_STRING_COPYRIGHT +#else +# ifdef __STDC__ + return PNG_STRING_NEWLINE \ + "libpng version 1.7.0beta35 - March 22, 2014" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2014 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ + "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ + "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ + PNG_STRING_NEWLINE; +# else + return "libpng version 1.7.0beta35 - March 22, 2014\ + Copyright (c) 1998-2014 Glenn Randers-Pehrson\ + Copyright (c) 1996-1997 Andreas Dilger\ + Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; +# endif +#endif +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files + * used with your application, print out PNG_LIBPNG_VER_STRING, which + * is defined in png.h. + * Note: now there is no difference between png_get_libpng_ver() and + * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, + * it is guaranteed that png.c uses the correct version of png.h. + */ +png_const_charp PNGAPI +png_get_libpng_ver(png_const_structrp png_ptr) +{ + /* Version of *.c files used when building libpng */ + return png_get_header_ver(png_ptr); +} + +png_const_charp PNGAPI +png_get_header_ver(png_const_structrp png_ptr) +{ + /* Version of *.h files used when building libpng */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ + return PNG_LIBPNG_VER_STRING; +} + +png_const_charp PNGAPI +png_get_header_version(png_const_structrp png_ptr) +{ + /* Returns longer string containing both version and date */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef __STDC__ + return PNG_HEADER_VERSION_STRING +# ifndef PNG_READ_SUPPORTED + " (NO READ SUPPORT)" +# endif + PNG_STRING_NEWLINE; +#else + return PNG_HEADER_VERSION_STRING; +#endif +} + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +/* NOTE: this routine is not used internally! */ +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth + * large of png_color. This lets grayscale images be treated as + * paletted. Most useful for gamma correction and simplification + * of code. This API is not used internally. + */ +void PNGAPI +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette"); + + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + + case 2: + num_palette = 4; + color_inc = 0x55; + break; + + case 4: + num_palette = 16; + color_inc = 0x11; + break; + + case 8: + num_palette = 256; + color_inc = 1; + break; + + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} +#endif + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name) +{ + /* Check chunk_name and return "keep" value if it's on the list, else 0 */ + png_const_bytep p, p_end; + + if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0) + return PNG_HANDLE_CHUNK_AS_DEFAULT; + + p_end = png_ptr->chunk_list; + p = p_end + png_ptr->num_chunk_list*5; /* beyond end */ + + /* The code is the fifth byte after each four byte string. Historically this + * code was always searched from the end of the list, this is no longer + * necessary because the 'set' routine handles duplicate entries correcty. + */ + do /* num_chunk_list > 0, so at least one */ + { + p -= 5; + + if (!memcmp(chunk_name, p, 4)) + return p[4]; + } + while (p > p_end); + + /* This means that known chunks should be processed and unknown chunks should + * be handled according to the value of png_ptr->unknown_default; this can be + * confusing because, as a result, there are two levels of defaulting for + * unknown chunks. + */ + return PNG_HANDLE_CHUNK_AS_DEFAULT; +} + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) +int /* PRIVATE */ +png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name) +{ + png_byte chunk_string[5]; + + PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name); + return png_handle_as_unknown(png_ptr, chunk_string); +} +#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */ +#endif /* SET_UNKNOWN_CHUNKS */ + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32)PNG_LIBPNG_VER); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Ensure that png_ptr->zstream.msg holds some appropriate error message string. + * If it doesn't 'ret' is used to set it to something appropriate, even in cases + * like Z_OK or Z_STREAM_END where the error code is apparently a success code. + */ +void /* PRIVATE */ +png_zstream_error(png_structrp png_ptr, int ret) +{ + /* Translate 'ret' into an appropriate error string, priority is given to the + * one in zstream if set. This always returns a string, even in cases like + * Z_OK or Z_STREAM_END where the error code is a success code. + */ + if (png_ptr->zstream.msg == NULL) switch (ret) + { + default: + case Z_OK: + png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code"); + break; + + case Z_STREAM_END: + /* Normal exit */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream"); + break; + + case Z_NEED_DICT: + /* This means the deflate stream did not have a dictionary; this + * indicates a bogus PNG. + */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary"); + break; + + case Z_ERRNO: + /* gz APIs only: should not happen */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error"); + break; + + case Z_STREAM_ERROR: + /* internal libpng error */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib"); + break; + + case Z_DATA_ERROR: + png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream"); + break; + + case Z_MEM_ERROR: + png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory"); + break; + + case Z_BUF_ERROR: + /* End of input or output; not a problem if the caller is doing + * incremental read or write. + */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated"); + break; + + case Z_VERSION_ERROR: + png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version"); + break; + + case PNG_UNEXPECTED_ZLIB_RETURN: + /* Compile errors here mean that zlib now uses the value co-opted in + * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above + * and change pngpriv.h. Note that this message is "... return", + * whereas the default/Z_OK one is "... return code". + */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return"); + break; + } +} + +/* png_convert_size: a PNGAPI but no longer in png.h, so deleted + * at libpng 1.5.5! + */ + +/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ +#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */ +static int +png_colorspace_check_gamma(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_fixed_point gAMA, int from) + /* This is called to check a new gamma value against an existing one. The + * routine returns false if the new gamma value should not be written. + * + * 'from' says where the new gamma value comes from: + * + * 0: the new gamma value is the libpng estimate for an ICC profile + * 1: the new gamma value comes from a gAMA chunk + * 2: the new gamma value comes from an sRGB chunk + */ +{ + png_fixed_point gtest; + + if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && + (!png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) || + png_gamma_significant(gtest))) + { + /* Either this is an sRGB image, in which case the calculated gamma + * approximation should match, or this is an image with a profile and the + * value libpng calculates for the gamma of the profile does not match the + * value recorded in the file. The former, sRGB, case is an error, the + * latter is just a warning. + */ + if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2) + { + png_chunk_report(png_ptr, "gamma value does not match sRGB", + PNG_CHUNK_ERROR); + /* Do not overwrite an sRGB value */ + return from == 2; + } + + else /* sRGB tag not involved */ + { + png_chunk_report(png_ptr, "gamma value does not match libpng estimate", + PNG_CHUNK_WARNING); + return from == 1; + } + } + + return 1; +} + +void /* PRIVATE */ +png_colorspace_set_gamma(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_fixed_point gAMA) +{ + /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't + * occur. Since the fixed point representation is assymetrical it is + * possible for 1/gamma to overflow the limit of 21474 and this means the + * gamma value must be at least 5/100000 and hence at most 20000.0. For + * safety the limits here are a little narrower. The values are 0.00016 to + * 6250.0, which are truly ridiculous gamma values (and will produce + * displays that are all black or all white.) + * + * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk + * handling code, which only required the value to be >0. + */ + png_const_charp errmsg; + + if (gAMA < 16 || gAMA > 625000000) + errmsg = "gamma value out of range"; + +# ifdef PNG_READ_gAMA_SUPPORTED + /* Allow the application to set the gamma value more than once */ + else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0) + errmsg = "duplicate"; +# endif + + /* Do nothing if the colorspace is already invalid */ + else if (colorspace->flags & PNG_COLORSPACE_INVALID) + return; + + else + { + if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA, 1/*from gAMA*/)) + { + /* Store this gamma value. */ + colorspace->gamma = gAMA; + colorspace->flags |= + (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA); + } + + /* At present if the check_gamma test fails the gamma of the colorspace is + * not updated however the colorspace is not invalidated. This + * corresponds to the case where the existing gamma comes from an sRGB + * chunk or profile. An error message has already been output. + */ + return; + } + + /* Error exit - errmsg has been set. */ + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR); +} + +void /* PRIVATE */ +png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr) +{ + if (info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) + { + /* Everything is invalid */ + info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB| + PNG_INFO_iCCP); + +# ifdef PNG_COLORSPACE_SUPPORTED + /* Clean up the iCCP profile now if it won't be used. */ + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/); +# else + PNG_UNUSED(png_ptr) +# endif + } + + else + { +# ifdef PNG_COLORSPACE_SUPPORTED + /* Leave the INFO_iCCP flag set if the pngset.c code has already set + * it; this allows a PNG to contain a profile which matches sRGB and + * yet still have that profile retrievable by the application. + */ + if (info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) + info_ptr->valid |= PNG_INFO_sRGB; + + else + info_ptr->valid &= ~PNG_INFO_sRGB; + + if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) + info_ptr->valid |= PNG_INFO_cHRM; + + else + info_ptr->valid &= ~PNG_INFO_cHRM; +# endif + + if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) + info_ptr->valid |= PNG_INFO_gAMA; + + else + info_ptr->valid &= ~PNG_INFO_gAMA; + } +} + +#ifdef PNG_READ_SUPPORTED +void /* PRIVATE */ +png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr) +{ + if (info_ptr == NULL) /* reduce code size; check here not in the caller */ + return; + + info_ptr->colorspace = png_ptr->colorspace; + png_colorspace_sync_info(png_ptr, info_ptr); +} +#endif +#endif + +#ifdef PNG_COLORSPACE_SUPPORTED +/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for + * cHRM, as opposed to using chromaticities. These internal APIs return + * non-zero on a parameter error. The X, Y and Z values are required to be + * positive and less than 1.0. + */ +static int +png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ) +{ + png_int_32 d, dwhite, whiteX, whiteY; + + d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z; + if (!png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d)) return 1; + if (!png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d)) return 1; + dwhite = d; + whiteX = XYZ->red_X; + whiteY = XYZ->red_Y; + + d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z; + if (!png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d)) return 1; + if (!png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d)) return 1; + dwhite += d; + whiteX += XYZ->green_X; + whiteY += XYZ->green_Y; + + d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z; + if (!png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d)) return 1; + if (!png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d)) return 1; + dwhite += d; + whiteX += XYZ->blue_X; + whiteY += XYZ->blue_Y; + + /* The reference white is simply the sum of the end-point (X,Y,Z) vectors, + * thus: + */ + if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1; + if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1; + + return 0; +} + +static int +png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) +{ + png_fixed_point red_inverse, green_inverse, blue_scale; + png_fixed_point left, right, denominator; + + /* Check xy and, implicitly, z. Note that wide gamut color spaces typically + * have end points with 0 tristimulus values (these are impossible end + * points, but they are used to cover the possible colors.) + */ + if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1; + if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1; + if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1; + if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1; + if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1; + if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1; + if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1; + if (xy->whitey < 0 || xy->whitey > PNG_FP_1-xy->whitex) return 1; + + /* The reverse calculation is more difficult because the original tristimulus + * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 + * derived values were recorded in the cHRM chunk; + * (red,green,blue,white)x(x,y). This loses one degree of freedom and + * therefore an arbitrary ninth value has to be introduced to undo the + * original transformations. + * + * Think of the original end-points as points in (X,Y,Z) space. The + * chromaticity values (c) have the property: + * + * C + * c = --------- + * X + Y + Z + * + * For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the + * three chromaticity values (x,y,z) for each end-point obey the + * relationship: + * + * x + y + z = 1 + * + * This describes the plane in (X,Y,Z) space that intersects each axis at the + * value 1.0; call this the chromaticity plane. Thus the chromaticity + * calculation has scaled each end-point so that it is on the x+y+z=1 plane + * and chromaticity is the intersection of the vector from the origin to the + * (X,Y,Z) value with the chromaticity plane. + * + * To fully invert the chromaticity calculation we would need the three + * end-point scale factors, (red-scale, green-scale, blue-scale), but these + * were not recorded. Instead we calculated the reference white (X,Y,Z) and + * recorded the chromaticity of this. The reference white (X,Y,Z) would have + * given all three of the scale factors since: + * + * color-C = color-c * color-scale + * white-C = red-C + green-C + blue-C + * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale + * + * But cHRM records only white-x and white-y, so we have lost the white scale + * factor: + * + * white-C = white-c*white-scale + * + * To handle this the inverse transformation makes an arbitrary assumption + * about white-scale: + * + * Assume: white-Y = 1.0 + * Hence: white-scale = 1/white-y + * Or: red-Y + green-Y + blue-Y = 1.0 + * + * Notice the last statement of the assumption gives an equation in three of + * the nine values we want to calculate. 8 more equations come from the + * above routine as summarised at the top above (the chromaticity + * calculation): + * + * Given: color-x = color-X / (color-X + color-Y + color-Z) + * Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0 + * + * This is 9 simultaneous equations in the 9 variables "color-C" and can be + * solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix + * determinants, however this is not as bad as it seems because only 28 of + * the total of 90 terms in the various matrices are non-zero. Nevertheless + * Cramer's rule is notoriously numerically unstable because the determinant + * calculation involves the difference of large, but similar, numbers. It is + * difficult to be sure that the calculation is stable for real world values + * and it is certain that it becomes unstable where the end points are close + * together. + * + * So this code uses the perhaps slightly less optimal but more + * understandable and totally obvious approach of calculating color-scale. + * + * This algorithm depends on the precision in white-scale and that is + * (1/white-y), so we can immediately see that as white-y approaches 0 the + * accuracy inherent in the cHRM chunk drops off substantially. + * + * libpng arithmetic: a simple invertion of the above equations + * ------------------------------------------------------------ + * + * white_scale = 1/white-y + * white-X = white-x * white-scale + * white-Y = 1.0 + * white-Z = (1 - white-x - white-y) * white_scale + * + * white-C = red-C + green-C + blue-C + * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale + * + * This gives us three equations in (red-scale,green-scale,blue-scale) where + * all the coefficients are now known: + * + * red-x*red-scale + green-x*green-scale + blue-x*blue-scale + * = white-x/white-y + * red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1 + * red-z*red-scale + green-z*green-scale + blue-z*blue-scale + * = (1 - white-x - white-y)/white-y + * + * In the last equation color-z is (1 - color-x - color-y) so we can add all + * three equations together to get an alternative third: + * + * red-scale + green-scale + blue-scale = 1/white-y = white-scale + * + * So now we have a Cramer's rule solution where the determinants are just + * 3x3 - far more tractible. Unfortunately 3x3 determinants still involve + * multiplication of three coefficients so we can't guarantee to avoid + * overflow in the libpng fixed point representation. Using Cramer's rule in + * floating point is probably a good choice here, but it's not an option for + * fixed point. Instead proceed to simplify the first two equations by + * eliminating what is likely to be the largest value, blue-scale: + * + * blue-scale = white-scale - red-scale - green-scale + * + * Hence: + * + * (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale = + * (white-x - blue-x)*white-scale + * + * (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale = + * 1 - blue-y*white-scale + * + * And now we can trivially solve for (red-scale,green-scale): + * + * green-scale = + * (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale + * ----------------------------------------------------------- + * green-x - blue-x + * + * red-scale = + * 1 - blue-y*white-scale - (green-y - blue-y) * green-scale + * --------------------------------------------------------- + * red-y - blue-y + * + * Hence: + * + * red-scale = + * ( (green-x - blue-x) * (white-y - blue-y) - + * (green-y - blue-y) * (white-x - blue-x) ) / white-y + * ------------------------------------------------------------------------- + * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) + * + * green-scale = + * ( (red-y - blue-y) * (white-x - blue-x) - + * (red-x - blue-x) * (white-y - blue-y) ) / white-y + * ------------------------------------------------------------------------- + * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) + * + * Accuracy: + * The input values have 5 decimal digits of accuracy. The values are all in + * the range 0 < value < 1, so simple products are in the same range but may + * need up to 10 decimal digits to preserve the original precision and avoid + * underflow. Because we are using a 32-bit signed representation we cannot + * match this; the best is a little over 9 decimal digits, less than 10. + * + * The approach used here is to preserve the maximum precision within the + * signed representation. Because the red-scale calculation above uses the + * difference between two products of values that must be in the range -1..+1 + * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The + * factor is irrelevant in the calculation because it is applied to both + * numerator and denominator. + * + * Note that the values of the differences of the products of the + * chromaticities in the above equations tend to be small, for example for + * the sRGB chromaticities they are: + * + * red numerator: -0.04751 + * green numerator: -0.08788 + * denominator: -0.2241 (without white-y multiplication) + * + * The resultant Y coefficients from the chromaticities of some widely used + * color space definitions are (to 15 decimal places): + * + * sRGB + * 0.212639005871510 0.715168678767756 0.072192315360734 + * Kodak ProPhoto + * 0.288071128229293 0.711843217810102 0.000085653960605 + * Adobe RGB + * 0.297344975250536 0.627363566255466 0.075291458493998 + * Adobe Wide Gamut RGB + * 0.258728243040113 0.724682314948566 0.016589442011321 + */ + /* By the argument, above overflow should be impossible here. The return + * value of 2 indicates an internal error to the caller. + */ + if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7)) + return 2; + if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7)) + return 2; + denominator = left - right; + + /* Now find the red numerator. */ + if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7)) + return 2; + if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7)) + return 2; + + /* Overflow is possible here and it indicates an extreme set of PNG cHRM + * chunk values. This calculation actually returns the reciprocal of the + * scale value because this allows us to delay the multiplication of white-y + * into the denominator, which tends to produce a small number. + */ + if (!png_muldiv(&red_inverse, xy->whitey, denominator, left-right) || + red_inverse <= xy->whitey /* r+g+b scales = white scale */) + return 1; + + /* Similarly for green_inverse: */ + if (!png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7)) + return 2; + if (!png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7)) + return 2; + if (!png_muldiv(&green_inverse, xy->whitey, denominator, left-right) || + green_inverse <= xy->whitey) + return 1; + + /* And the blue scale, the checks above guarantee this can't overflow but it + * can still produce 0 for extreme cHRM values. + */ + blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) - + png_reciprocal(green_inverse); + if (blue_scale <= 0) return 1; + + + /* And fill in the png_XYZ: */ + if (!png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse)) return 1; + if (!png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse)) return 1; + if (!png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1, + red_inverse)) + return 1; + + if (!png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse)) + return 1; + if (!png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse)) + return 1; + if (!png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1, + green_inverse)) + return 1; + + if (!png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1)) return 1; + if (!png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1)) return 1; + if (!png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale, + PNG_FP_1)) + return 1; + + return 0; /*success*/ +} + +static int +png_XYZ_normalize(png_XYZ *XYZ) +{ + png_int_32 Y; + + if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 || + XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 || + XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0) + return 1; + + /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. + * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore + * relying on addition of two positive values producing a negative one is not + * safe. + */ + Y = XYZ->red_Y; + if (0x7fffffff - Y < XYZ->green_X) return 1; + Y += XYZ->green_Y; + if (0x7fffffff - Y < XYZ->blue_X) return 1; + Y += XYZ->blue_Y; + + if (Y != PNG_FP_1) + { + if (!png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y)) return 1; + + if (!png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y)) return 1; + + if (!png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y)) return 1; + if (!png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y)) return 1; + } + + return 0; +} + +static int +png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta) +{ + /* Allow an error of +/-0.01 (absolute value) on each chromaticity */ + return !(PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) || + PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) || + PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) || + PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) || + PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) || + PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) || + PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) || + PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta)); +} + +/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM + * chunk chromaticities. Earlier checks used to simply look for the overflow + * condition (where the determinant of the matrix to solve for XYZ ends up zero + * because the chromaticity values are not all distinct.) Despite this it is + * theoretically possible to produce chromaticities that are apparently valid + * but that rapidly degrade to invalid, potentially crashing, sets because of + * arithmetic inaccuracies when calculations are performed on them. The new + * check is to round-trip xy -> XYZ -> xy and then check that the result is + * within a small percentage of the original. + */ +static int +png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy) +{ + int result; + png_xy xy_test; + + /* As a side-effect this routine also returns the XYZ endpoints. */ + result = png_XYZ_from_xy(XYZ, xy); + if (result != 0) return result; + + result = png_xy_from_XYZ(&xy_test, XYZ); + if (result != 0) return result; + + if (png_colorspace_endpoints_match(xy, &xy_test, + 5/*actually, the math is pretty accurate*/)) + return 0; + + /* Too much slip */ + return 1; +} + +/* This is the check going the other way. The XYZ is modified to normalize it + * (another side-effect) and the xy chromaticities are returned. + */ +static int +png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ) +{ + int result; + png_XYZ XYZtemp; + + result = png_XYZ_normalize(XYZ); + if (result != 0) return result; + + result = png_xy_from_XYZ(xy, XYZ); + if (result != 0) return result; + + XYZtemp = *XYZ; + return png_colorspace_check_xy(&XYZtemp, xy); +} + +/* Used to check for an endpoint match against sRGB */ +static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */ +{ + /* color x y */ + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000, + /* white */ 31270, 32900 +}; + +static int +png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr, + png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ, + int preferred) +{ + if (colorspace->flags & PNG_COLORSPACE_INVALID) + return 0; + + /* The consistency check is performed on the chromaticities; this factors out + * variations because of the normalization (or not) of the end point Y + * values. + */ + if (preferred < 2 && (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) + { + /* The end points must be reasonably close to any we already have. The + * following allows an error of up to +/-.001 + */ + if (!png_colorspace_endpoints_match(xy, &colorspace->end_points_xy, 100)) + { + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_benign_error(png_ptr, "inconsistent chromaticities"); + return 0; /* failed */ + } + + /* Only overwrite with preferred values */ + if (preferred == 0) + return 1; /* ok, but no change */ + } + + colorspace->end_points_xy = *xy; + colorspace->end_points_XYZ = *XYZ; + colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS; + + /* The end points are normally quoted to two decimal digits, so allow +/-0.01 + * on this test. + */ + if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000)) + colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB; + + else + colorspace->flags &= PNG_COLORSPACE_CANCEL( + PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); + + return 2; /* ok and changed */ +} + +int /* PRIVATE */ +png_colorspace_set_chromaticities(png_const_structrp png_ptr, + png_colorspacerp colorspace, const png_xy *xy, int preferred) +{ + /* We must check the end points to ensure they are reasonable - in the past + * color management systems have crashed as a result of getting bogus + * colorant values, while this isn't the fault of libpng it is the + * responsibility of libpng because PNG carries the bomb and libpng is in a + * position to protect against it. + */ + png_XYZ XYZ; + + switch (png_colorspace_check_xy(&XYZ, xy)) + { + case 0: /* success */ + return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ, + preferred); + + case 1: + /* We can't invert the chromaticities so we can't produce value XYZ + * values. Likely as not a color management system will fail too. + */ + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_benign_error(png_ptr, "invalid chromaticities"); + break; + + default: + /* libpng is broken; this should be a warning but if it happens we + * want error reports so for the moment it is an error. + */ + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_error(png_ptr, "internal error checking chromaticities"); + break; + } + + return 0; /* failed */ +} + +int /* PRIVATE */ +png_colorspace_set_endpoints(png_const_structrp png_ptr, + png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred) +{ + png_XYZ XYZ = *XYZ_in; + png_xy xy; + + switch (png_colorspace_check_XYZ(&xy, &XYZ)) + { + case 0: + return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ, + preferred); + + case 1: + /* End points are invalid. */ + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_benign_error(png_ptr, "invalid end points"); + break; + + default: + colorspace->flags |= PNG_COLORSPACE_INVALID; + png_error(png_ptr, "internal error checking chromaticities"); + break; + } + + return 0; /* failed */ +} + +#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED) +/* Error message generation */ +static char +png_icc_tag_char(png_uint_32 byte) +{ + byte &= 0xff; + if (byte >= 32 && byte <= 126) + return (char)byte; + else + return '?'; +} + +static void +png_icc_tag_name(char *name, png_uint_32 tag) +{ + name[0] = '\''; + name[1] = png_icc_tag_char(tag >> 24); + name[2] = png_icc_tag_char(tag >> 16); + name[3] = png_icc_tag_char(tag >> 8); + name[4] = png_icc_tag_char(tag ); + name[5] = '\''; +} + +static int +is_ICC_signature_char(png_alloc_size_t it) +{ + return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) || + (it >= 97 && it <= 122); +} + +static int is_ICC_signature(png_alloc_size_t it) +{ + return is_ICC_signature_char(it >> 24) /* checks all the top bits */ && + is_ICC_signature_char((it >> 16) & 0xff) && + is_ICC_signature_char((it >> 8) & 0xff) && + is_ICC_signature_char(it & 0xff); +} + +static int +png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_alloc_size_t value, png_const_charp reason) +{ + size_t pos; + char message[196]; /* see below for calculation */ + + if (colorspace != NULL) + colorspace->flags |= PNG_COLORSPACE_INVALID; + + pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */ + pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */ + pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */ + if (is_ICC_signature(value)) + { + /* So 'value' is at most 4 bytes and the following cast is safe */ + png_icc_tag_name(message+pos, (png_uint_32)value); + pos += 6; /* total +8; less than the else clause */ + message[pos++] = ':'; + message[pos++] = ' '; + } +# ifdef PNG_WARNINGS_SUPPORTED + else + { + char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/ + + pos = png_safecat(message, (sizeof message), pos, + png_format_number(number, number+(sizeof number), + PNG_NUMBER_FORMAT_x, value)); + pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/ + } +# endif + /* The 'reason' is an arbitrary message, allow +79 maximum 195 */ + pos = png_safecat(message, (sizeof message), pos, reason); + PNG_UNUSED(pos) + + /* This is recoverable, but make it unconditionally an app_error on write to + * avoid writing invalid ICC profiles into PNG files. (I.e. we handle them + * on read, with a warning, but on write unless the app turns off + * application errors the PNG won't be written.) + */ + png_chunk_report(png_ptr, message, + (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR); + + return 0; +} +#endif /* sRGB || iCCP */ + +#ifdef PNG_sRGB_SUPPORTED +int /* PRIVATE */ +png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, + int intent) +{ + /* sRGB sets known gamma, end points and (from the chunk) intent. */ + /* IMPORTANT: these are not necessarily the values found in an ICC profile + * because ICC profiles store values adapted to a D50 environment; it is + * expected that the ICC profile mediaWhitePointTag will be D50, see the + * checks and code elsewhere to understand this better. + * + * These XYZ values, which are accurate to 5dp, produce rgb to gray + * coefficients of (6968,23435,2366), which are reduced (because they add up + * to 32769 not 32768) to (6968,23434,2366). These are the values that + * libpng has traditionally used (and are the best values given the 15bit + * algorithm used by the rgb to gray code.) + */ + static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */ + { + /* color X Y Z */ + /* red */ 41239, 21264, 1933, + /* green */ 35758, 71517, 11919, + /* blue */ 18048, 7219, 95053 + }; + + /* Do nothing if the colorspace is already invalidated. */ + if (colorspace->flags & PNG_COLORSPACE_INVALID) + return 0; + + /* Check the intent, then check for existing settings. It is valid for the + * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must + * be consistent with the correct values. If, however, this function is + * called below because an iCCP chunk matches sRGB then it is quite + * conceivable that an older app recorded incorrect gAMA and cHRM because of + * an incorrect calculation based on the values in the profile - this does + * *not* invalidate the profile (though it still produces an error, which can + * be ignored.) + */ + if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) + return png_icc_profile_error(png_ptr, colorspace, "sRGB", + (unsigned)intent, "invalid sRGB rendering intent"); + + if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && + colorspace->rendering_intent != intent) + return png_icc_profile_error(png_ptr, colorspace, "sRGB", + (unsigned)intent, "inconsistent rendering intents"); + + if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) + { + png_benign_error(png_ptr, "duplicate sRGB information ignored"); + return 0; + } + + /* If the standard sRGB cHRM chunk does not match the one from the PNG file + * warn but overwrite the value with the correct one. + */ + if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 && + !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy, + 100)) + png_chunk_report(png_ptr, "cHRM chunk does not match sRGB", + PNG_CHUNK_ERROR); + + /* This check is just done for the error reporting - the routine always + * returns true when the 'from' argument corresponds to sRGB (2). + */ + (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE, + 2/*from sRGB*/); + + /* intent: bugs in GCC force 'int' to be used as the parameter type. */ + colorspace->rendering_intent = (png_uint_16)intent; + colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT; + + /* endpoints */ + colorspace->end_points_xy = sRGB_xy; + colorspace->end_points_XYZ = sRGB_XYZ; + colorspace->flags |= + (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); + + /* gamma */ + colorspace->gamma = PNG_GAMMA_sRGB_INVERSE; + colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA; + + /* Finally record that we have an sRGB profile */ + colorspace->flags |= + (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB); + + return 1; /* set */ +} +#endif /* sRGB */ + +#ifdef PNG_iCCP_SUPPORTED +/* Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value + * is XYZ(0.9642,1.0,0.8249), which scales to: + * + * (63189.8112, 65536, 54060.6464) + */ +static const png_byte D50_nCIEXYZ[12] = + { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; + +int /* PRIVATE */ +png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length) +{ + if (profile_length < 132) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "too short"); + + if (profile_length & 3) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "invalid length"); + + return 1; +} + +int /* PRIVATE */ +png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length, + png_const_bytep profile/* first 132 bytes only */, int color_type) +{ + png_uint_32 temp; + + /* Length check; this cannot be ignored in this code because profile_length + * is used later to check the tag table, so even if the profile seems over + * long profile_length from the caller must be correct. The caller can fix + * this up on read or write by just passing in the profile header length. + */ + temp = png_get_uint_32(profile); + if (temp != profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "length does not match profile"); + + temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */ + if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */ + profile_length < 132+12*temp) /* truncated tag table */ + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "tag count too large"); + + /* The 'intent' must be valid or we can't store it, ICC limits the intent to + * 16 bits. + */ + temp = png_get_uint_32(profile+64); + if (temp >= 0xffff) /* The ICC limit */ + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "invalid rendering intent"); + + /* This is just a warning because the profile may be valid in future + * versions. + */ + if (temp >= PNG_sRGB_INTENT_LAST) + (void)png_icc_profile_error(png_ptr, NULL, name, temp, + "intent outside defined range"); + + /* At this point the tag table can't be checked because it hasn't necessarily + * been loaded; however, various header fields can be checked. These checks + * are for values permitted by the PNG spec in an ICC profile; the PNG spec + * restricts the profiles that can be passed in an iCCP chunk (they must be + * appropriate to processing PNG data!) + */ + + /* Data checks (could be skipped). These checks must be independent of the + * version number; however, the version number doesn't accomodate changes in + * the header fields (just the known tags and the interpretation of the + * data.) + */ + temp = png_get_uint_32(profile+36); /* signature 'ascp' */ + if (temp != 0x61637370) + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "invalid signature"); + + /* Currently the PCS illuminant/adopted white point (the computational + * white point) are required to be D50, + * however the profile contains a record of the illuminant so perhaps ICC + * expects to be able to change this in the future (despite the rationale in + * the introduction for using a fixed PCS adopted white.) Consequently the + * following is just a warning. + */ + if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0) + (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/, + "PCS illuminant is not D50"); + + /* The PNG spec requires this: + * "If the iCCP chunk is present, the image samples conform to the colour + * space represented by the embedded ICC profile as defined by the + * International Color Consortium [ICC]. The colour space of the ICC profile + * shall be an RGB colour space for colour images (PNG colour types 2, 3, and + * 6), or a greyscale colour space for greyscale images (PNG colour types 0 + * and 4)." + * + * This checking code ensures the embedded profile (on either read or write) + * conforms to the specification requirements. Notice that an ICC 'gray' + * color-space profile contains the information to transform the monochrome + * data to XYZ or L*a*b (according to which PCS the profile uses) and this + * should be used in preference to the standard libpng K channel replication + * into R, G and B channels. + * + * Previously it was suggested that an RGB profile on grayscale data could be + * handled. However it it is clear that using an RGB profile in this context + * must be an error - there is no specification of what it means. Thus it is + * almost certainly more correct to ignore the profile. + */ + temp = png_get_uint_32(profile+16); /* data colour space field */ + switch (temp) + { + case 0x52474220: /* 'RGB ' */ + if (!(color_type & PNG_COLOR_MASK_COLOR)) + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "RGB color space not permitted on grayscale PNG"); + break; + + case 0x47524159: /* 'GRAY' */ + if (color_type & PNG_COLOR_MASK_COLOR) + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "Gray color space not permitted on RGB PNG"); + break; + + default: + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "invalid ICC profile color space"); + } + + /* It is up to the application to check that the profile class matches the + * application requirements; the spec provides no guidance, but it's pretty + * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer + * ('prtr') or 'spac' (for generic color spaces). Issue a warning in these + * cases. Issue an error for device link or abstract profiles - these don't + * contain the records necessary to transform the color-space to anything + * other than the target device (and not even that for an abstract profile). + * Profiles of these classes may not be embedded in images. + */ + temp = png_get_uint_32(profile+12); /* profile/device class */ + switch (temp) + { + case 0x73636E72: /* 'scnr' */ + case 0x6D6E7472: /* 'mntr' */ + case 0x70727472: /* 'prtr' */ + case 0x73706163: /* 'spac' */ + /* All supported */ + break; + + case 0x61627374: /* 'abst' */ + /* May not be embedded in an image */ + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "invalid embedded Abstract ICC profile"); + + case 0x6C696E6B: /* 'link' */ + /* DeviceLink profiles cannnot be interpreted in a non-device specific + * fashion, if an app uses the AToB0Tag in the profile the results are + * undefined unless the result is sent to the intended device, + * therefore a DeviceLink profile should not be found embedded in a + * PNG. + */ + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "unexpected DeviceLink ICC profile class"); + + case 0x6E6D636C: /* 'nmcl' */ + /* A NamedColor profile is also device specific, however it doesn't + * contain an AToB0 tag that is open to misintrepretation. Almost + * certainly it will fail the tests below. + */ + (void)png_icc_profile_error(png_ptr, NULL, name, temp, + "unexpected NamedColor ICC profile class"); + break; + + default: + /* To allow for future enhancements to the profile accept unrecognized + * profile classes with a warning, these then hit the test below on the + * tag content to ensure they are backward compatible with one of the + * understood profiles. + */ + (void)png_icc_profile_error(png_ptr, NULL, name, temp, + "unrecognized ICC profile class"); + break; + } + + /* For any profile other than a device link one the PCS must be encoded + * either in XYZ or Lab. + */ + temp = png_get_uint_32(profile+20); + switch (temp) + { + case 0x58595A20: /* 'XYZ ' */ + case 0x4C616220: /* 'Lab ' */ + break; + + default: + return png_icc_profile_error(png_ptr, colorspace, name, temp, + "unexpected ICC PCS encoding"); + } + + return 1; +} + +int /* PRIVATE */ +png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length, + png_const_bytep profile /* header plus whole tag table */) +{ + png_uint_32 tag_count = png_get_uint_32(profile+128); + png_uint_32 itag; + png_const_bytep tag = profile+132; /* The first tag */ + + /* First scan all the tags in the table and add bits to the icc_info value + * (temporarily in 'tags'). + */ + for (itag=0; itag < tag_count; ++itag, tag += 12) + { + png_uint_32 tag_id = png_get_uint_32(tag+0); + png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */ + png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */ + + /* The ICC specification does not exclude zero length tags, therefore the + * start might actually be anywhere if there is no data, but this would be + * a clear abuse of the intent of the standard so the start is checked for + * being in range. All defined tag types have an 8 byte header - a 4 byte + * type signature then 0. + */ + if ((tag_start & 3) != 0) + { + /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is + * only a warning here because libpng does not care about the + * alignment. + */ + (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, + "ICC profile tag start not a multiple of 4"); + } + + /* This is a hard error; potentially it can cause read outside the + * profile. + */ + if (tag_start > profile_length || tag_length > profile_length - tag_start) + return png_icc_profile_error(png_ptr, colorspace, name, tag_id, + "ICC profile tag outside profile"); + } + + return 1; /* success, maybe with warnings */ +} + +#ifdef PNG_sRGB_SUPPORTED +/* Information about the known ICC sRGB profiles */ +static const struct +{ + png_uint_32 adler, crc, length; + png_uint_32 md5[4]; + png_byte have_md5; + png_byte is_broken; + png_uint_16 intent; + +# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0) +# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\ + { adler, crc, length, md5, broke, intent }, + +} png_sRGB_checks[] = +{ + /* This data comes from contrib/tools/checksum-icc run on downloads of + * all four ICC sRGB profiles from www.color.org. + */ + /* adler32, crc32, MD5[4], intent, date, length, file-name */ + PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9, + PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0, + "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") + + /* ICC sRGB v2 perceptual no black-compensation: */ + PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21, + PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0, + "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") + + PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae, + PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0, + "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") + + /* ICC sRGB v4 perceptual */ + PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812, + PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0, + "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") + + /* The following profiles have no known MD5 checksum. If there is a match + * on the (empty) MD5 the other fields are used to attempt a match and + * a warning is produced. The first two of these profiles have a 'cprt' tag + * which suggests that they were also made by Hewlett Packard. + */ + PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce, + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0, + "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") + + /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not + * match the D50 PCS illuminant in the header (it is in fact the D65 values, + * so the white point is recorded as the un-adapted value.) The profiles + * below only differ in one byte - the intent - and are basically the same as + * the previous profile except for the mediaWhitePointTag error and a missing + * chromaticAdaptationTag. + */ + PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552, + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, + "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") + + PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d, + PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, + "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") +}; + +static int +png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, + png_const_bytep profile, uLong adler) +{ + /* The quick check is to verify just the MD5 signature and trust the + * rest of the data. Because the profile has already been verified for + * correctness this is safe. png_colorspace_set_sRGB will check the 'intent' + * field too, so if the profile has been edited with an intent not defined + * by sRGB (but maybe defined by a later ICC specification) the read of + * the profile will fail at that point. + */ + png_uint_32 length = 0; + png_uint_32 intent = 0x10000; /* invalid */ +#if PNG_sRGB_PROFILE_CHECKS > 1 + uLong crc = 0; /* the value for 0 length data */ +#endif + unsigned int i; + + for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i) + { + if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] && + png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] && + png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] && + png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3]) + { + /* This may be one of the old HP profiles without an MD5, in that + * case we can only use the length and Adler32 (note that these + * are not used by default if there is an MD5!) + */ +# if PNG_sRGB_PROFILE_CHECKS == 0 + if (png_sRGB_checks[i].have_md5) + return 1+png_sRGB_checks[i].is_broken; +# endif + + /* Profile is unsigned or more checks have been configured in. */ + if (length == 0) + { + length = png_get_uint_32(profile); + intent = png_get_uint_32(profile+64); + } + + /* Length *and* intent must match */ + if (length == png_sRGB_checks[i].length && + intent == png_sRGB_checks[i].intent) + { + /* Now calculate the adler32 if not done already. */ + if (adler == 0) + { + adler = adler32(0, NULL, 0); + adler = adler32(adler, profile, length); + } + + if (adler == png_sRGB_checks[i].adler) + { + /* These basic checks suggest that the data has not been + * modified, but if the check level is more than 1 perform + * our own crc32 checksum on the data. + */ +# if PNG_sRGB_PROFILE_CHECKS > 1 + if (crc == 0) + { + crc = crc32(0, NULL, 0); + crc = crc32(crc, profile, length); + } + + /* So this check must pass for the 'return' below to happen. + */ + if (crc == png_sRGB_checks[i].crc) +# endif + { + if (png_sRGB_checks[i].is_broken) + { + /* These profiles are known to have bad data that may cause + * problems if they are used, therefore attempt to + * discourage their use, skip the 'have_md5' warning below, + * which is made irrelevant by this error. + */ + png_chunk_report(png_ptr, "known incorrect sRGB profile", + PNG_CHUNK_ERROR); + } + + /* Warn that this being done; this isn't even an error since + * the profile is perfectly valid, but it would be nice if + * people used the up-to-date ones. + */ + else if (!png_sRGB_checks[i].have_md5) + { + png_chunk_report(png_ptr, + "out-of-date sRGB profile with no signature", + PNG_CHUNK_WARNING); + } + + return 1+png_sRGB_checks[i].is_broken; + } + } + } + +# if PNG_sRGB_PROFILE_CHECKS > 0 + /* The signature matched, but the profile had been changed in some + * way. This probably indicates a data error or uninformed hacking. + * Fall through to "no match". + */ + png_chunk_report(png_ptr, + "Not recognizing known sRGB profile that has been edited", + PNG_CHUNK_WARNING); +# endif + } + } + + return 0; /* no match */ +} +#endif + +#ifdef PNG_sRGB_SUPPORTED +void /* PRIVATE */ +png_icc_set_sRGB(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_bytep profile, uLong adler) +{ + /* Is this profile one of the known ICC sRGB profiles? If it is, just set + * the sRGB information. + */ + if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler)) + (void)png_colorspace_set_sRGB(png_ptr, colorspace, + (int)/*already checked*/png_get_uint_32(profile+64)); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +int /* PRIVATE */ +png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length, png_const_bytep profile, + int color_type) +{ + if (colorspace->flags & PNG_COLORSPACE_INVALID) + return 0; + + if (png_icc_check_length(png_ptr, colorspace, name, profile_length) && + png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, + color_type) && + png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, + profile)) + { +# ifdef PNG_sRGB_SUPPORTED + /* If no sRGB support, don't try storing sRGB information */ + png_icc_set_sRGB(png_ptr, colorspace, profile, 0); +# endif + return 1; + } + + /* Failure case */ + return 0; +} +#endif /* iCCP */ + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +void /* PRIVATE */ +png_colorspace_set_rgb_coefficients(png_structrp png_ptr) +{ + /* Set the rgb_to_gray coefficients from the colorspace. */ + if ((png_ptr->colorspace.flags & PNG_COLORSPACE_RGB_TO_GRAY_SET) == 0 && + (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) + { + /* png_set_background has not been called, get the coefficients from the Y + * values of the colorspace colorants. + */ + png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y; + png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y; + png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y; + png_fixed_point total = r+g+b; + + if (total > 0 && + r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 && + g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 && + b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 && + r+g+b <= 32769) + { + /* We allow 0 coefficients here. r+g+b may be 32769 if two or + * all of the coefficients were rounded up. Handle this by + * reducing the *largest* coefficient by 1; this matches the + * approach used for the default coefficients in pngrtran.c + */ + int add = 0; + + if (r+g+b > 32768) + add = -1; + else if (r+g+b < 32768) + add = 1; + + if (add != 0) + { + if (g >= r && g >= b) + g += add; + else if (r >= g && r >= b) + r += add; + else + b += add; + } + + /* Check for an internal error. */ + if (r+g+b != 32768) + png_error(png_ptr, + "internal error handling cHRM coefficients"); + + else + { + png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r; + png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g; + } + } + + /* This is a png_error at present even though it could be ignored - + * it should never happen, but it is important that if it does, the + * bug is fixed. + */ + else + png_error(png_ptr, "internal error handling cHRM->XYZ"); + } +} +#endif + +#endif /* COLORSPACE */ + +void /* PRIVATE */ +png_check_IHDR(png_const_structrp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + int error = 0; + + /* Check for width and height valid values */ + if (width == 0) + { + png_warning(png_ptr, "Image width is zero in IHDR"); + error = 1; + } + else if (width > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image width in IHDR"); + error = 1; + } + else + { +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max) +# else + if (width > PNG_USER_WIDTH_MAX) +# endif + { + png_warning(png_ptr, "Image width exceeds user limit in IHDR"); + error = 1; + } + } + + if (height == 0) + { + png_warning(png_ptr, "Image height is zero in IHDR"); + error = 1; + } + else if (height > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image height in IHDR"); + error = 1; + } + else + { +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (height > png_ptr->user_height_max) +# else + if (height > PNG_USER_HEIGHT_MAX) +# endif + { + png_warning(png_ptr, "Image height exceeds user limit in IHDR"); + error = 1; + } + } + + /* Check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + { + png_warning(png_ptr, "Invalid bit depth in IHDR"); + error = 1; + } + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + { + png_warning(png_ptr, "Invalid color type in IHDR"); + error = 1; + } + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + { + png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR"); + error = 1; + } + + if (interlace_type >= PNG_INTERLACE_LAST) + { + png_warning(png_ptr, "Unknown interlace method in IHDR"); + error = 1; + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Unknown compression method in IHDR"); + error = 1; + } + +# ifdef PNG_MNG_FEATURES_SUPPORTED + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) && + png_ptr->mng_features_permitted) + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + + if (filter_type != PNG_FILTER_TYPE_BASE) + { + if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } + + if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) + { + png_warning(png_ptr, "Invalid filter method in IHDR"); + error = 1; + } + } + +# else + if (filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } +# endif + + if (error == 1) + png_error(png_ptr, "Invalid IHDR data"); +} + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* ASCII to fp functions */ +/* Check an ASCII formated floating point value, see the more detailed + * comments in pngpriv.h + */ +/* The following is used internally to preserve the sticky flags */ +#define png_fp_add(state, flags) ((state) |= (flags)) +#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) + +int /* PRIVATE */ +png_check_fp_number(png_const_charp string, png_size_t size, int *statep, + png_size_tp whereami) +{ + int state = *statep; + png_size_t i = *whereami; + + while (i < size) + { + int type; + /* First find the type of the next character */ + switch (string[i]) + { + case 43: type = PNG_FP_SAW_SIGN; break; + case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break; + case 46: type = PNG_FP_SAW_DOT; break; + case 48: type = PNG_FP_SAW_DIGIT; break; + case 49: case 50: case 51: case 52: + case 53: case 54: case 55: case 56: + case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break; + case 69: + case 101: type = PNG_FP_SAW_E; break; + default: goto PNG_FP_End; + } + + /* Now deal with this type according to the current + * state, the type is arranged to not overlap the + * bits of the PNG_FP_STATE. + */ + switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY)) + { + case PNG_FP_INTEGER + PNG_FP_SAW_SIGN: + if (state & PNG_FP_SAW_ANY) + goto PNG_FP_End; /* not a part of the number */ + + png_fp_add(state, type); + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_DOT: + /* Ok as trailer, ok as lead of fraction. */ + if (state & PNG_FP_SAW_DOT) /* two dots */ + goto PNG_FP_End; + + else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */ + png_fp_add(state, type); + + else + png_fp_set(state, PNG_FP_FRACTION | type); + + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT: + if (state & PNG_FP_SAW_DOT) /* delayed fraction */ + png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); + + png_fp_add(state, type | PNG_FP_WAS_VALID); + + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_E: + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: + goto PNG_FP_End; ** no sign in fraction */ + + /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: + goto PNG_FP_End; ** Because SAW_DOT is always set */ + + case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT: + png_fp_add(state, type | PNG_FP_WAS_VALID); + break; + + case PNG_FP_FRACTION + PNG_FP_SAW_E: + /* This is correct because the trailing '.' on an + * integer is handled above - so we can only get here + * with the sequence ".E" (with no preceding digits). + */ + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN: + if (state & PNG_FP_SAW_ANY) + goto PNG_FP_End; /* not a part of the number */ + + png_fp_add(state, PNG_FP_SAW_SIGN); + + break; + + /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: + goto PNG_FP_End; */ + + case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT: + png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID); + + break; + + /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: + goto PNG_FP_End; */ + + default: goto PNG_FP_End; /* I.e. break 2 */ + } + + /* The character seems ok, continue. */ + ++i; + } + +PNG_FP_End: + /* Here at the end, update the state and return the correct + * return code. + */ + *statep = state; + *whereami = i; + + return (state & PNG_FP_SAW_DIGIT) != 0; +} + + +/* The same but for a complete string. */ +int +png_check_fp_string(png_const_charp string, png_size_t size) +{ + int state=0; + png_size_t char_index=0; + + if (png_check_fp_number(string, size, &state, &char_index) && + (char_index == size || string[char_index] == 0)) + return state /* must be non-zero - see above */; + + return 0; /* i.e. fail */ +} +#endif /* pCAL or sCAL */ + +#ifdef PNG_sCAL_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +/* Utility used below - a simple accurate power of ten from an integral + * exponent. + */ +static double +png_pow10(int power) +{ + int recip = 0; + double d = 1; + + /* Handle negative exponent with a reciprocal at the end because + * 10 is exact whereas .1 is inexact in base 2 + */ + if (power < 0) + { + if (power < DBL_MIN_10_EXP) return 0; + recip = 1, power = -power; + } + + if (power > 0) + { + /* Decompose power bitwise. */ + double mult = 10; + do + { + if (power & 1) d *= mult; + mult *= mult; + power >>= 1; + } + while (power > 0); + + if (recip != 0) d = 1/d; + } + /* else power is 0 and d is 1 */ + + return d; +} + +/* Function to format a floating point value in ASCII with a given + * precision. + */ +void /* PRIVATE */ +png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, + double fp, unsigned int precision) +{ + /* We use standard functions from math.h, but not printf because + * that would require stdio. The caller must supply a buffer of + * sufficient size or we will png_error. The tests on size and + * the space in ascii[] consumed are indicated below. + */ + if (precision < 1) + precision = DBL_DIG; + + /* Enforce the limit of the implementation precision too. */ + if (precision > DBL_DIG+1) + precision = DBL_DIG+1; + + /* Basic sanity checks */ + if (size >= precision+5) /* See the requirements below. */ + { + if (fp < 0) + { + fp = -fp; + *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */ + --size; + } + + if (fp >= DBL_MIN && fp <= DBL_MAX) + { + int exp_b10; /* A base 10 exponent */ + double base; /* 10^exp_b10 */ + + /* First extract a base 10 exponent of the number, + * the calculation below rounds down when converting + * from base 2 to base 10 (multiply by log10(2) - + * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to + * be increased. Note that the arithmetic shift + * performs a floor() unlike C arithmetic - using a + * C multiply would break the following for negative + * exponents. + */ + (void)frexp(fp, &exp_b10); /* exponent to base 2 */ + + exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */ + + /* Avoid underflow here. */ + base = png_pow10(exp_b10); /* May underflow */ + + while (base < DBL_MIN || base < fp) + { + /* And this may overflow. */ + double test = png_pow10(exp_b10+1); + + if (test <= DBL_MAX) + ++exp_b10, base = test; + + else + break; + } + + /* Normalize fp and correct exp_b10, after this fp is in the + * range [.1,1) and exp_b10 is both the exponent and the digit + * *before* which the decimal point should be inserted + * (starting with 0 for the first digit). Note that this + * works even if 10^exp_b10 is out of range because of the + * test on DBL_MAX above. + */ + fp /= base; + while (fp >= 1) fp /= 10, ++exp_b10; + + /* Because of the code above fp may, at this point, be + * less than .1, this is ok because the code below can + * handle the leading zeros this generates, so no attempt + * is made to correct that here. + */ + + { + int czero, clead, cdigits; + char exponent[10]; + + /* Allow up to two leading zeros - this will not lengthen + * the number compared to using E-n. + */ + if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ + { + czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ + exp_b10 = 0; /* Dot added below before first output. */ + } + else + czero = 0; /* No zeros to add */ + + /* Generate the digit list, stripping trailing zeros and + * inserting a '.' before a digit if the exponent is 0. + */ + clead = czero; /* Count of leading zeros */ + cdigits = 0; /* Count of digits in list. */ + + do + { + double d; + + fp *= 10; + /* Use modf here, not floor and subtract, so that + * the separation is done in one step. At the end + * of the loop don't break the number into parts so + * that the final digit is rounded. + */ + if (cdigits+czero-clead+1 < (int)precision) + fp = modf(fp, &d); + + else + { + d = floor(fp + .5); + + if (d > 9) + { + /* Rounding up to 10, handle that here. */ + if (czero > 0) + { + --czero, d = 1; + if (cdigits == 0) --clead; + } + else + { + while (cdigits > 0 && d > 9) + { + int ch = *--ascii; + + if (exp_b10 != (-1)) + ++exp_b10; + + else if (ch == 46) + { + ch = *--ascii, ++size; + /* Advance exp_b10 to '1', so that the + * decimal point happens after the + * previous digit. + */ + exp_b10 = 1; + } + + --cdigits; + d = ch - 47; /* I.e. 1+(ch-48) */ + } + + /* Did we reach the beginning? If so adjust the + * exponent but take into account the leading + * decimal point. + */ + if (d > 9) /* cdigits == 0 */ + { + if (exp_b10 == (-1)) + { + /* Leading decimal point (plus zeros?), if + * we lose the decimal point here it must + * be reentered below. + */ + int ch = *--ascii; + + if (ch == 46) + ++size, exp_b10 = 1; + + /* Else lost a leading zero, so 'exp_b10' is + * still ok at (-1) + */ + } + else + ++exp_b10; + + /* In all cases we output a '1' */ + d = 1; + } + } + } + fp = 0; /* Guarantees termination below. */ + } + + if (d == 0) + { + ++czero; + if (cdigits == 0) ++clead; + } + else + { + /* Included embedded zeros in the digit count. */ + cdigits += czero - clead; + clead = 0; + + while (czero > 0) + { + /* exp_b10 == (-1) means we just output the decimal + * place - after the DP don't adjust 'exp_b10' any + * more! + */ + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; + /* PLUS 1: TOTAL 4 */ + --exp_b10; + } + *ascii++ = 48, --czero; + } + + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; /* counted + above */ + --exp_b10; + } + *ascii++ = (char)(48 + (int)d), ++cdigits; + } + } + while (cdigits+czero-clead < (int)precision && fp > DBL_MIN); + + /* The total output count (max) is now 4+precision */ + + /* Check for an exponent, if we don't need one we are + * done and just need to terminate the string. At + * this point exp_b10==(-1) is effectively if flag - it got + * to '-1' because of the decrement after outputing + * the decimal point above (the exponent required is + * *not* -1!) + */ + if (exp_b10 >= (-1) && exp_b10 <= 2) + { + /* The following only happens if we didn't output the + * leading zeros above for negative exponent, so this + * doest add to the digit requirement. Note that the + * two zeros here can only be output if the two leading + * zeros were *not* output, so this doesn't increase + * the output count. + */ + while (--exp_b10 >= 0) *ascii++ = 48; + + *ascii = 0; + + /* Total buffer requirement (including the '\0') is + * 5+precision - see check at the start. + */ + return; + } + + /* Here if an exponent is required, adjust size for + * the digits we output but did not count. The total + * digit output here so far is at most 1+precision - no + * decimal point and no leading or trailing zeros have + * been output. + */ + size -= cdigits; + + *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ + + /* The following use of an unsigned temporary avoids ambiguities in + * the signed arithmetic on exp_b10 and permits GCC at least to do + * better optimization. + */ + { + unsigned int uexp_b10; + + if (exp_b10 < 0) + { + *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ + uexp_b10 = -exp_b10; + } + + else + uexp_b10 = exp_b10; + + cdigits = 0; + + while (uexp_b10 > 0) + { + exponent[cdigits++] = (char)(48 + uexp_b10 % 10); + uexp_b10 /= 10; + } + } + + /* Need another size check here for the exponent digits, so + * this need not be considered above. + */ + if ((int)size > cdigits) + { + while (cdigits > 0) *ascii++ = exponent[--cdigits]; + + *ascii = 0; + + return; + } + } + } + else if (!(fp >= DBL_MIN)) + { + *ascii++ = 48; /* '0' */ + *ascii = 0; + return; + } + else + { + *ascii++ = 105; /* 'i' */ + *ascii++ = 110; /* 'n' */ + *ascii++ = 102; /* 'f' */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} + +# endif /* FLOATING_POINT */ + +# ifdef PNG_FIXED_POINT_SUPPORTED +/* Function to format a fixed point value in ASCII. + */ +void /* PRIVATE */ +png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, + png_size_t size, png_fixed_point fp) +{ + /* Require space for 10 decimal digits, a decimal point, a minus sign and a + * trailing \0, 13 characters: + */ + if (size > 12) + { + png_uint_32 num; + + /* Avoid overflow here on the minimum integer. */ + if (fp < 0) + *ascii++ = 45, --size, num = -fp; + else + num = fp; + + if (num <= 0x80000000) /* else overflowed */ + { + unsigned int ndigits = 0, first = 16 /* flag value */; + char digits[10]; + + while (num) + { + /* Split the low digit off num: */ + unsigned int tmp = num/10; + num -= tmp*10; + digits[ndigits++] = (char)(48 + num); + /* Record the first non-zero digit, note that this is a number + * starting at 1, it's not actually the array index. + */ + if (first == 16 && num > 0) + first = ndigits; + num = tmp; + } + + if (ndigits > 0) + { + while (ndigits > 5) *ascii++ = digits[--ndigits]; + /* The remaining digits are fractional digits, ndigits is '5' or + * smaller at this point. It is certainly not zero. Check for a + * non-zero fractional digit: + */ + if (first <= 5) + { + unsigned int i; + *ascii++ = 46; /* decimal point */ + /* ndigits may be <5 for small numbers, output leading zeros + * then ndigits digits to first: + */ + i = 5; + while (ndigits < i) *ascii++ = 48, --i; + while (ndigits >= first) *ascii++ = digits[--ndigits]; + /* Don't output the trailing zeros! */ + } + } + else + *ascii++ = 48; + + /* And null terminate the string: */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} +# endif /* FIXED_POINT */ +#endif /* SCAL */ + +#if !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && (\ + defined(PNG_FLOATING_POINT_SUPPORTED) && \ + (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \ + defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \ + (defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) &&\ + defined(PNG_sCAL_SUPPORTED))) +png_fixed_point +png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text) +{ + if (fp < 0) + { + if (fp > -21474.836485) + return (png_fixed_point)(100000*fp - .5); + } + + else + { + if (fp < 21474.836475) + return (png_fixed_point)(100000*fp + .5); + } + + /* Overflow */ + png_fixed_error(png_ptr, text); + +# ifndef PNG_ERROR_TEXT_SUPPORTED + PNG_UNUSED(text) +# endif +} +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) +/* muldiv functions */ +/* This API takes signed arguments and rounds the result to the nearest + * integer (or, for a fixed point number - the standard argument - to + * the nearest .00001). Overflow and divide by zero are signalled in + * the result, a boolean - true on success, false on overflow. + */ +int +png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + /* Return a * times / divisor, rounded. */ + if (divisor != 0) + { + if (a == 0 || times == 0) + { + *res = 0; + return 1; + } + else + { +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a; + r *= times; + r /= divisor; + r = floor(r+.5); + + /* A png_fixed_point is a 32-bit integer. */ + if (r <= 2147483647. && r >= -2147483648.) + { + *res = (png_fixed_point)r; + return 1; + } +#else + int negative = 0; + png_uint_32 A, T, D; + png_uint_32 s16, s32, s00; + + if (a < 0) + negative = 1, A = -a; + else + A = a; + + if (times < 0) + negative = !negative, T = -times; + else + T = times; + + if (divisor < 0) + negative = !negative, D = -divisor; + else + D = divisor; + + /* Following can't overflow because the arguments only + * have 31 bits each, however the result may be 32 bits. + */ + s16 = (A >> 16) * (T & 0xffff) + + (A & 0xffff) * (T >> 16); + /* Can't overflow because the a*times bit is only 30 + * bits at most. + */ + s32 = (A >> 16) * (T >> 16) + (s16 >> 16); + s00 = (A & 0xffff) * (T & 0xffff); + + s16 = (s16 & 0xffff) << 16; + s00 += s16; + + if (s00 < s16) + ++s32; /* carry */ + + if (s32 < D) /* else overflow */ + { + /* s32.s00 is now the 64-bit product, do a standard + * division, we know that s32 < D, so the maximum + * required shift is 31. + */ + int bitshift = 32; + png_fixed_point result = 0; /* NOTE: signed */ + + while (--bitshift >= 0) + { + png_uint_32 d32, d00; + + if (bitshift > 0) + d32 = D >> (32-bitshift), d00 = D << bitshift; + + else + d32 = 0, d00 = D; + + if (s32 > d32) + { + if (s00 < d00) --s32; /* carry */ + s32 -= d32, s00 -= d00, result += 1<= d00) + s32 = 0, s00 -= d00, result += 1<= (D >> 1)) + ++result; + + if (negative != 0) + result = -result; + + /* Check for overflow. */ + if ((negative && result <= 0) || (!negative && result >= 0)) + { + *res = result; + return 1; + } + } +#endif + } + } + + return 0; +} +#endif /* READ_GAMMA || INCH_CONVERSIONS */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* The following is for when the caller doesn't much care about the + * result. + */ +png_fixed_point +png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + png_fixed_point result; + + if (png_muldiv(&result, a, times, divisor)) + return result; + + png_warning(png_ptr, "fixed point overflow ignored"); + return 0; +} +#endif + +#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */ +/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ +png_fixed_point +png_reciprocal(png_fixed_point a) +{ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(1E10/a+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, 100000, 100000, a)) + return res; +#endif + + return 0; /* error/overflow */ +} + +/* This is the shared test on whether a gamma value is 'significant' - whether + * it is worth doing gamma correction. + */ +int /* PRIVATE */ +png_gamma_significant(png_fixed_point gamma_val) +{ + return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED || + gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; +} +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* A local convenience routine. */ +#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED +static png_fixed_point +png_product2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a * 1E-5; + r *= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, a, b, 100000)) + return res; +#endif + + return 0; /* overflow */ +} +#endif + +/* The inverse of the above. */ +png_fixed_point +png_reciprocal2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = 1E15/a; + r /= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + /* This may overflow because the range of png_fixed_point isn't symmetric, + * but this API is only used for the product of file and screen gamma so it + * doesn't matter that the smallest number it can produce is 1/21474, not + * 1/100000 + */ + png_fixed_point res = png_product2(a, b); + + if (res != 0) + return png_reciprocal(res); +#endif + + return 0; /* overflow */ +} +#endif /* READ_GAMMA */ + +#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */ +#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* Fixed point gamma. + * + * The code to calculate the tables used below can be found in the shell script + * contrib/tools/intgamma.sh + * + * To calculate gamma this code implements fast log() and exp() calls using only + * fixed point arithmetic. This code has sufficient precision for either 8-bit + * or 16-bit sample values. + * + * The tables used here were calculated using simple 'bc' programs, but C double + * precision floating point arithmetic would work fine. + * + * 8-bit log table + * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to + * 255, so it's the base 2 logarithm of a normalized 8-bit floating point + * mantissa. The numbers are 32-bit fractions. + */ +static const png_uint_32 +png_8bit_l2[128] = +{ + 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U, + 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U, + 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U, + 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U, + 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U, + 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U, + 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U, + 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U, + 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U, + 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U, + 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U, + 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U, + 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U, + 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U, + 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U, + 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U, + 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U, + 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U, + 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U, + 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U, + 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U, + 24347096U, 0U + +#if 0 + /* The following are the values for 16-bit tables - these work fine for the + * 8-bit conversions but produce very slightly larger errors in the 16-bit + * log (about 1.2 as opposed to 0.7 absolute error in the final value). To + * use these all the shifts below must be adjusted appropriately. + */ + 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054, + 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803, + 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068, + 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782, + 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887, + 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339, + 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098, + 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132, + 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415, + 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523, + 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495, + 1119, 744, 372 +#endif +}; + +static png_int_32 +png_log8bit(unsigned int x) +{ + unsigned int lg2 = 0; + /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log, + * because the log is actually negate that means adding 1. The final + * returned value thus has the range 0 (for 255 input) to 7.994 (for 1 + * input), return -1 for the overflow (log 0) case, - so the result is + * always at most 19 bits. + */ + if ((x &= 0xff) == 0) + return -1; + + if ((x & 0xf0) == 0) + lg2 = 4, x <<= 4; + + if ((x & 0xc0) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x80) == 0) + lg2 += 1, x <<= 1; + + /* result is at most 19 bits, so this cast is safe: */ + return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16)); +} + +/* The above gives exact (to 16 binary places) log2 values for 8-bit images, + * for 16-bit images we use the most significant 8 bits of the 16-bit value to + * get an approximation then multiply the approximation by a correction factor + * determined by the remaining up to 8 bits. This requires an additional step + * in the 16-bit case. + * + * We want log2(value/65535), we have log2(v'/255), where: + * + * value = v' * 256 + v'' + * = v' * f + * + * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128 + * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less + * than 258. The final factor also needs to correct for the fact that our 8-bit + * value is scaled by 255, whereas the 16-bit values must be scaled by 65535. + * + * This gives a final formula using a calculated value 'x' which is value/v' and + * scaling by 65536 to match the above table: + * + * log2(x/257) * 65536 + * + * Since these numbers are so close to '1' we can use simple linear + * interpolation between the two end values 256/257 (result -368.61) and 258/257 + * (result 367.179). The values used below are scaled by a further 64 to give + * 16-bit precision in the interpolation: + * + * Start (256): -23591 + * Zero (257): 0 + * End (258): 23499 + */ +static png_int_32 +png_log16bit(png_uint_32 x) +{ + unsigned int lg2 = 0; + + /* As above, but now the input has 16 bits. */ + if ((x &= 0xffff) == 0) + return -1; + + if ((x & 0xff00) == 0) + lg2 = 8, x <<= 8; + + if ((x & 0xf000) == 0) + lg2 += 4, x <<= 4; + + if ((x & 0xc000) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x8000) == 0) + lg2 += 1, x <<= 1; + + /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional + * value. + */ + lg2 <<= 28; + lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4; + + /* Now we need to interpolate the factor, this requires a division by the top + * 8 bits. Do this with maximum precision. + */ + x = ((x << 16) + (x >> 9)) / (x >> 8); + + /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24, + * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly + * 16 bits to interpolate to get the low bits of the result. Round the + * answer. Note that the end point values are scaled by 64 to retain overall + * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust + * the overall scaling by 6-12. Round at every step. + */ + x -= 1U << 24; + + if (x <= 65536U) /* <= '257' */ + lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12); + + else + lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12); + + /* Safe, because the result can't have more than 20 bits: */ + return (png_int_32)((lg2 + 2048) >> 12); +} + +/* The 'exp()' case must invert the above, taking a 20-bit fixed point + * logarithmic value and returning a 16 or 8-bit number as appropriate. In + * each case only the low 16 bits are relevant - the fraction - since the + * integer bits (the top 4) simply determine a shift. + * + * The worst case is the 16-bit distinction between 65535 and 65534, this + * requires perhaps spurious accuracty in the decoding of the logarithm to + * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance + * of getting this accuracy in practice. + * + * To deal with this the following exp() function works out the exponent of the + * frational part of the logarithm by using an accurate 32-bit value from the + * top four fractional bits then multiplying in the remaining bits. + */ +static const png_uint_32 +png_32bit_exp[16] = +{ + /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */ + 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U, + 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U, + 2553802834U, 2445529972U, 2341847524U, 2242560872U +}; + +/* Adjustment table; provided to explain the numbers in the code below. */ +#if 0 +for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"} + 11 44937.64284865548751208448 + 10 45180.98734845585101160448 + 9 45303.31936980687359311872 + 8 45364.65110595323018870784 + 7 45395.35850361789624614912 + 6 45410.72259715102037508096 + 5 45418.40724413220722311168 + 4 45422.25021786898173001728 + 3 45424.17186732298419044352 + 2 45425.13273269940811464704 + 1 45425.61317555035558641664 + 0 45425.85339951654943850496 +#endif + +static png_uint_32 +png_exp(png_fixed_point x) +{ + if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */ + { + /* Obtain a 4-bit approximation */ + png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf]; + + /* Incorporate the low 12 bits - these decrease the returned value by + * multiplying by a number less than 1 if the bit is set. The multiplier + * is determined by the above table and the shift. Notice that the values + * converge on 45426 and this is used to allow linear interpolation of the + * low bits. + */ + if (x & 0x800) + e -= (((e >> 16) * 44938U) + 16U) >> 5; + + if (x & 0x400) + e -= (((e >> 16) * 45181U) + 32U) >> 6; + + if (x & 0x200) + e -= (((e >> 16) * 45303U) + 64U) >> 7; + + if (x & 0x100) + e -= (((e >> 16) * 45365U) + 128U) >> 8; + + if (x & 0x080) + e -= (((e >> 16) * 45395U) + 256U) >> 9; + + if (x & 0x040) + e -= (((e >> 16) * 45410U) + 512U) >> 10; + + /* And handle the low 6 bits in a single block. */ + e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9; + + /* Handle the upper bits of x. */ + e >>= x >> 16; + return e; + } + + /* Check for overflow */ + if (x <= 0) + return png_32bit_exp[0]; + + /* Else underflow */ + return 0; +} + +static png_byte +png_exp8bit(png_fixed_point lg2) +{ + /* Get a 32-bit value: */ + png_uint_32 x = png_exp(lg2); + + /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the + * second, rounding, step can't overflow because of the first, subtraction, + * step. + */ + x -= x >> 8; + return (png_byte)((x + 0x7fffffU) >> 24); +} + +static png_uint_16 +png_exp16bit(png_fixed_point lg2) +{ + /* Get a 32-bit value: */ + png_uint_32 x = png_exp(lg2); + + /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */ + x -= x >> 16; + return (png_uint_16)((x + 32767U) >> 16); +} +#endif /* FLOATING_ARITHMETIC */ + +png_byte +png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 255) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(255*pow(value/255.,gamma_val*.00001)+.5); + return (png_byte)r; +# else + png_int_32 lg2 = png_log8bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp8bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_byte)value; +} + +png_uint_16 +png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 65535) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5); + return (png_uint_16)r; +# else + png_int_32 lg2 = png_log16bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp16bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_uint_16)value; +} + +/* This does the right thing based on the bit_depth field of the + * png_struct, interpreting values as 8-bit or 16-bit. While the result + * is nominally a 16-bit value if bit depth is 8 then the result is + * 8-bit (as are the arguments.) + */ +png_uint_16 /* PRIVATE */ +png_gamma_correct(png_structrp png_ptr, unsigned int value, + png_fixed_point gamma_val) +{ + if (png_ptr->bit_depth == 8) + return png_gamma_8bit_correct(value, gamma_val); + + else + return png_gamma_16bit_correct(value, gamma_val); +} + +#define PNG_GAMMA_TABLE_8 0 /* 8-bit entries in png_byte */ +#define PNG_GAMMA_TABLE_8_IN_16 1 /* 8-bit entries * 257 in png_uint_16 */ +#define PNG_GAMMA_TABLE_16 2 /* 16-bit entries in png_uint_16 */ + +typedef struct +{ + png_fixed_point gamma; + png_uint_32 mult; + unsigned int add; + unsigned int shift; /* input value is (i * mult + add) >> shift */ + int output; /* One of the above values */ + int adjust; /* Divide or multiple output by 257 */ + png_voidp table; /* Lookup table */ +} gamma_table_data; + +static unsigned int +write_gamma_table_entry(const gamma_table_data *data, png_uint_32 i) + /* Calculate and write a single entry into table[i], the value of the entry + * written is returned. + */ +{ + png_uint_32 in = (i * data->mult + data->add) >> data->shift; + unsigned int out; + + /* If the output is TABLE_8 with no adjust, or the output is not with an + * adjust, use 8-bit correction. + */ + if ((data->output == PNG_GAMMA_TABLE_8) != (data->adjust != 0)) + { + out = png_gamma_8bit_correct((unsigned int)in, data->gamma); + + if (data->adjust != 0) + out *= 257U; + } + + else /* 16-bit correction */ + { + out = png_gamma_16bit_correct((unsigned int)in, data->gamma); + + if (data->adjust != 0) + out = PNG_DIV257(out); + } + + if (data->output == PNG_GAMMA_TABLE_8) + ((png_bytep)data->table)[i] = (png_byte)out; + + else + ((png_uint_16p)data->table)[i] = (png_uint_16)out; + + return out; +} + +static void +write_gamma_table(const gamma_table_data *data, png_uint_32 lo, + unsigned int loval, png_uint_32 hi, unsigned int hival) + /* Fill in gamma table entries between lo and hi, exclusive. The entries at + * table[lo] and table[hi] have already been written, the intervening entries + * are written. + */ +{ + if (hi > lo+1) /* Else nothing to fill in */ + { + if (hival == loval) + { + /* All intervening entries must be the same. */ + if (data->output == PNG_GAMMA_TABLE_8) + { + png_bytep table8 = ((png_bytep)data->table); + + while (++lo < hi) + table8[lo] = (png_byte)loval; + } + + else + { + png_uint_16p table16 = ((png_uint_16p)data->table); + + while (++lo < hi) + table16[lo] = (png_uint_16)loval; + } + } + + else + { + png_uint_32 mid = (lo+hi) >> 1; + unsigned int midval = write_gamma_table_entry(data, mid); + + /* The algorithm used is to divide the entries to be written in half + * and fill in the middle. For all practical tables with significant + * gamma this will result in a performance gain because the expensive + * gamma correction arithmetic is avoided for some entries. + */ + write_gamma_table(data, lo, loval, mid, midval); + write_gamma_table(data, mid, midval, hi, hival); + } + } +} + +static void * +png_build_gamma_table(png_structrp png_ptr, png_fixed_point gamma_val, + int output/*as above*/, int input_depth, int use_shift) + /* Build a gamma lookup table to encode input_depth bit input values. + * The table will have 2^input_depth entries plus an extra one if use_shift + * is specified. With shift the table is accessed: + * + * table[(original-value + rounding) >> shift] + * + * And an extra entry exists to accomodate overflow of original-value on + * rounding. If use_shift is not specified the table is accessed with an + * input_depth bit value and the original values must have been correctly + * scaled to this range (not using a shift!) + * + * Each table entry contains input-value^gamma_val rounded to the output + * precision. This is 8 bit precision unless output is specified as + * PNG_GAMMA_TABLE_16, in which case it is 16-bit precision. For + * PNG_GAMMA_TABLE_8_IN_16 the 8-bit value is scaled to 16-bits by + * multiplying by 257. + */ +{ + png_uint_32 size; + unsigned int hival; + gamma_table_data data; + + /* If use_shift is true or if the input or output is not 8-bit the gamma + * correction will use the 16-bit correction code. This requires a value in + * the range 0..65535. For use_shift the value is simply: + * + * input << shift + * + * For the scaling case the value is: + * + * round(input * 65535 / ((1<> shift; + * + * With 'mult' and 'add' chosen to minimize the error for all input values + * in the range 0..((1< PNG_GAMMA_TABLE_8; + + if (use_shift != 0) + { + /* The multiplier does the shift: */ + data.mult = 1U << (8-input_depth); + data.add = 0; + data.shift = 0; + if (input_depth < 8) ++size; + } + + else + { + data.mult = multadd255[input_depth-1].mult; + data.add = multadd255[input_depth-1].add; + data.shift = multadd255[input_depth-1].shift; + } + } + + else + { + /* 16-bit correction is used for cases where input or output require more + * than 8 bits. + */ + data.adjust = output == PNG_GAMMA_TABLE_8; + + if (use_shift != 0) + { + data.mult = 1U << (16-input_depth); + data.add = 0; + data.shift = 0; + if (input_depth < 16) ++size; + } + + else + { + data.mult = multadd65535[input_depth-1].mult; + data.add = multadd65535[input_depth-1].add; + data.shift = multadd65535[input_depth-1].shift; + } + } + + if (output == PNG_GAMMA_TABLE_8) + { + data.table = png_malloc(png_ptr, size * sizeof (png_byte)); + ((png_bytep)data.table)[0] = 0; + hival = ((png_bytep)data.table)[size-1] = 255; + } + + else + { + /* Output is 16 bits, although it may only have 8 bits of precision */ + data.table = png_malloc(png_ptr, size * sizeof (png_uint_16)); + ((png_uint_16p)data.table)[0] = 0; + hival = ((png_uint_16p)data.table)[size-1] = 65535; + } + + if (png_gamma_significant(gamma_val)) + write_gamma_table(&data, 0, 0, size-1, hival); + + else /* gamma_val not significant */ + { + if (output == PNG_GAMMA_TABLE_8) + { + png_uint_32 i; + png_bytep table8 = ((png_bytep)data.table); + + if (data.adjust) + for (i=1; i> + data.shift); + + else + for (i=1; i> data.shift); + } + + else + { + png_uint_32 i; + png_uint_16p table16 = ((png_uint_16p)data.table); + + if (data.adjust) + for (i=1; i> + data.shift) * 257U); + + else + for (i=1; i> + data.shift); + } + } + + return data.table; +} + +/* Used from png_read_destroy and below to release the memory used by the gamma + * tables. + */ +void /* PRIVATE */ +png_destroy_gamma_table(png_structrp png_ptr) +{ + png_free(png_ptr, png_ptr->gamma_table); + png_ptr->gamma_table = NULL; + + png_free(png_ptr, png_ptr->gamma_16_table); + png_ptr->gamma_16_table = NULL; + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_from_1); + png_ptr->gamma_from_1 = NULL; + png_free(png_ptr, png_ptr->gamma_to_1); + png_ptr->gamma_to_1 = NULL; + + png_free(png_ptr, png_ptr->gamma_16_from_1); + png_ptr->gamma_16_from_1 = NULL; + png_free(png_ptr, png_ptr->gamma_16_to_1); + png_ptr->gamma_16_to_1 = NULL; +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ +} + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + */ +void /* PRIVATE */ +png_build_gamma_tables(png_structrp png_ptr, int bit_depth) +{ + png_debug(1, "in png_build_gamma_table"); + + /* Remove any existing table; this copes with multiple calls to + * png_read_update_info. The warning is because building the gamma tables + * multiple times is a performance hit - it's harmless but the ability to call + * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible + * to warn if the app introduces such a hit. + */ + if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) + { + png_warning(png_ptr, "gamma table being rebuilt"); + png_destroy_gamma_table(png_ptr); + } + + if (bit_depth <= 8) + { + png_ptr->gamma_table = png_voidcast(png_bytep, png_build_gamma_table( + png_ptr, png_ptr->screen_gamma > 0 ? + png_reciprocal2(png_ptr->colorspace.gamma, png_ptr->screen_gamma) : + PNG_FP_1, PNG_GAMMA_TABLE_8, 8/*input depth*/, 0/*scale*/)); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) + { + /* This sets the accuracy of 8-bit composition and the 8-bit RGB to gray + * conversion - PNG_MAX_GAMMA_8 (the number of bits in the sixteen bit + * value that are considered significant.) + */ + png_ptr->gamma_to_1 = png_voidcast(png_uint_16p, png_build_gamma_table( + png_ptr, png_reciprocal(png_ptr->colorspace.gamma), + PNG_GAMMA_TABLE_16, 8/*input depth*/, 0/*scale*/)); + + png_ptr->gamma_from_1 = png_voidcast(png_bytep, png_build_gamma_table( + png_ptr, png_ptr->screen_gamma > 0 ? + png_reciprocal(png_ptr->screen_gamma) : + png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */, + PNG_GAMMA_TABLE_8, PNG_MAX_GAMMA_8/*input depth*/, 1/*shift*/)); + + png_ptr->gamma_shift = 16-PNG_MAX_GAMMA_8; + } +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ + } + else + { + png_byte shift, sig_bit; + int table_type; + +# ifdef PNG_16BIT_SUPPORTED + table_type = PNG_GAMMA_TABLE_16; +# else + table_type = PNG_GAMMA_TABLE_8_IN_16; +# endif + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = png_ptr->sig_bit.red; + + if (png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + + if (png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + sig_bit = png_ptr->sig_bit.gray; + + if (sig_bit > 0 && sig_bit < 16U) + shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */ + + else + shift = 0; /* keep all 16 bits */ + + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) + { + /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively + * the significant bits in the *input* when the output will + * eventually be 8 bits. + */ + if (shift < (16U - PNG_MAX_GAMMA_8)) + shift = (16U - PNG_MAX_GAMMA_8); + + table_type = PNG_GAMMA_TABLE_8_IN_16; + } + + png_ptr->gamma_shift = shift; + + png_ptr->gamma_16_table = png_voidcast(png_uint_16p, png_build_gamma_table( + png_ptr, png_ptr->screen_gamma > 0 ? png_reciprocal2( + png_ptr->colorspace.gamma, png_ptr->screen_gamma) : PNG_FP_1, + table_type, (16-shift)/*input depth*/, 1/*shift*/)); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) + { + png_ptr->gamma_16_to_1 = png_voidcast(png_uint_16p, + png_build_gamma_table(png_ptr, + png_reciprocal(png_ptr->colorspace.gamma), PNG_GAMMA_TABLE_16, + (16-shift)/*input depth*/, 1/*shift*/)); + + /* Notice that the '16 from 1' table should be full precision, however + * the lookup on this table still uses gamma_shift, so it can't be. + * TODO: fix this. + */ + png_ptr->gamma_16_from_1 = png_voidcast(png_uint_16p, + png_build_gamma_table(png_ptr, png_ptr->screen_gamma > 0 ? + png_reciprocal(png_ptr->screen_gamma) : + png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */, + PNG_GAMMA_TABLE_16, (16-shift)/*input depth*/, 1/*shift*/)); + } +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ + } +} +#endif /* READ_GAMMA */ + +/* HARDWARE OPTION SUPPORT */ +#ifdef PNG_SET_OPTION_SUPPORTED +int PNGAPI +png_set_option(png_structrp png_ptr, int option, int onoff) +{ + if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT && + (option & 1) == 0) + { + int mask = 3 << option; + int setting = (2 + (onoff != 0)) << option; + int current = png_ptr->options; + + png_ptr->options = (png_byte)((current & ~mask) | setting); + + return (current & mask) >> option; + } + + return PNG_OPTION_INVALID; +} +#endif + +/* sRGB support */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) +/* sRGB conversion tables; these are machine generated with the code in + * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the + * specification (see the article at http://en.wikipedia.org/wiki/SRGB) + * is used, not the gamma=1/2.2 approximation use elsewhere in libpng. + * The sRGB to linear table is exact (to the nearest 16 bit linear fraction). + * The inverse (linear to sRGB) table has accuracies as follows: + * + * For all possible (255*65535+1) input values: + * + * error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact + * + * For the input values corresponding to the 65536 16-bit values: + * + * error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact + * + * In all cases the inexact readings are off by one. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* The convert-to-sRGB table is only currently required for read. */ +const png_uint_16 png_sRGB_table[256] = +{ + 0,20,40,60,80,99,119,139, + 159,179,199,219,241,264,288,313, + 340,367,396,427,458,491,526,562, + 599,637,677,718,761,805,851,898, + 947,997,1048,1101,1156,1212,1270,1330, + 1391,1453,1517,1583,1651,1720,1790,1863, + 1937,2013,2090,2170,2250,2333,2418,2504, + 2592,2681,2773,2866,2961,3058,3157,3258, + 3360,3464,3570,3678,3788,3900,4014,4129, + 4247,4366,4488,4611,4736,4864,4993,5124, + 5257,5392,5530,5669,5810,5953,6099,6246, + 6395,6547,6700,6856,7014,7174,7335,7500, + 7666,7834,8004,8177,8352,8528,8708,8889, + 9072,9258,9445,9635,9828,10022,10219,10417, + 10619,10822,11028,11235,11446,11658,11873,12090, + 12309,12530,12754,12980,13209,13440,13673,13909, + 14146,14387,14629,14874,15122,15371,15623,15878, + 16135,16394,16656,16920,17187,17456,17727,18001, + 18277,18556,18837,19121,19407,19696,19987,20281, + 20577,20876,21177,21481,21787,22096,22407,22721, + 23038,23357,23678,24002,24329,24658,24990,25325, + 25662,26001,26344,26688,27036,27386,27739,28094, + 28452,28813,29176,29542,29911,30282,30656,31033, + 31412,31794,32179,32567,32957,33350,33745,34143, + 34544,34948,35355,35764,36176,36591,37008,37429, + 37852,38278,38706,39138,39572,40009,40449,40891, + 41337,41785,42236,42690,43147,43606,44069,44534, + 45002,45473,45947,46423,46903,47385,47871,48359, + 48850,49344,49841,50341,50844,51349,51858,52369, + 52884,53401,53921,54445,54971,55500,56032,56567, + 57105,57646,58190,58737,59287,59840,60396,60955, + 61517,62082,62650,63221,63795,64372,64952,65535 +}; + +#endif /* simplified read only */ + +/* The base/delta tables are required for both read and write (but currently + * only the simplified versions.) + */ +const png_uint_16 png_sRGB_base[512] = +{ + 128,1782,3383,4644,5675,6564,7357,8074, + 8732,9346,9921,10463,10977,11466,11935,12384, + 12816,13233,13634,14024,14402,14769,15125,15473, + 15812,16142,16466,16781,17090,17393,17690,17981, + 18266,18546,18822,19093,19359,19621,19879,20133, + 20383,20630,20873,21113,21349,21583,21813,22041, + 22265,22487,22707,22923,23138,23350,23559,23767, + 23972,24175,24376,24575,24772,24967,25160,25352, + 25542,25730,25916,26101,26284,26465,26645,26823, + 27000,27176,27350,27523,27695,27865,28034,28201, + 28368,28533,28697,28860,29021,29182,29341,29500, + 29657,29813,29969,30123,30276,30429,30580,30730, + 30880,31028,31176,31323,31469,31614,31758,31902, + 32045,32186,32327,32468,32607,32746,32884,33021, + 33158,33294,33429,33564,33697,33831,33963,34095, + 34226,34357,34486,34616,34744,34873,35000,35127, + 35253,35379,35504,35629,35753,35876,35999,36122, + 36244,36365,36486,36606,36726,36845,36964,37083, + 37201,37318,37435,37551,37668,37783,37898,38013, + 38127,38241,38354,38467,38580,38692,38803,38915, + 39026,39136,39246,39356,39465,39574,39682,39790, + 39898,40005,40112,40219,40325,40431,40537,40642, + 40747,40851,40955,41059,41163,41266,41369,41471, + 41573,41675,41777,41878,41979,42079,42179,42279, + 42379,42478,42577,42676,42775,42873,42971,43068, + 43165,43262,43359,43456,43552,43648,43743,43839, + 43934,44028,44123,44217,44311,44405,44499,44592, + 44685,44778,44870,44962,45054,45146,45238,45329, + 45420,45511,45601,45692,45782,45872,45961,46051, + 46140,46229,46318,46406,46494,46583,46670,46758, + 46846,46933,47020,47107,47193,47280,47366,47452, + 47538,47623,47709,47794,47879,47964,48048,48133, + 48217,48301,48385,48468,48552,48635,48718,48801, + 48884,48966,49048,49131,49213,49294,49376,49458, + 49539,49620,49701,49782,49862,49943,50023,50103, + 50183,50263,50342,50422,50501,50580,50659,50738, + 50816,50895,50973,51051,51129,51207,51285,51362, + 51439,51517,51594,51671,51747,51824,51900,51977, + 52053,52129,52205,52280,52356,52432,52507,52582, + 52657,52732,52807,52881,52956,53030,53104,53178, + 53252,53326,53400,53473,53546,53620,53693,53766, + 53839,53911,53984,54056,54129,54201,54273,54345, + 54417,54489,54560,54632,54703,54774,54845,54916, + 54987,55058,55129,55199,55269,55340,55410,55480, + 55550,55620,55689,55759,55828,55898,55967,56036, + 56105,56174,56243,56311,56380,56448,56517,56585, + 56653,56721,56789,56857,56924,56992,57059,57127, + 57194,57261,57328,57395,57462,57529,57595,57662, + 57728,57795,57861,57927,57993,58059,58125,58191, + 58256,58322,58387,58453,58518,58583,58648,58713, + 58778,58843,58908,58972,59037,59101,59165,59230, + 59294,59358,59422,59486,59549,59613,59677,59740, + 59804,59867,59930,59993,60056,60119,60182,60245, + 60308,60370,60433,60495,60558,60620,60682,60744, + 60806,60868,60930,60992,61054,61115,61177,61238, + 61300,61361,61422,61483,61544,61605,61666,61727, + 61788,61848,61909,61969,62030,62090,62150,62211, + 62271,62331,62391,62450,62510,62570,62630,62689, + 62749,62808,62867,62927,62986,63045,63104,63163, + 63222,63281,63340,63398,63457,63515,63574,63632, + 63691,63749,63807,63865,63923,63981,64039,64097, + 64155,64212,64270,64328,64385,64443,64500,64557, + 64614,64672,64729,64786,64843,64900,64956,65013, + 65070,65126,65183,65239,65296,65352,65409,65465 +}; + +const png_byte png_sRGB_delta[512] = +{ + 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54, + 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36, + 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28, + 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24, + 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21, + 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19, + 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17, + 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; +#endif /* SIMPLIFIED READ/WRITE sRGB support */ + +/* SIMPLIFIED READ/WRITE SUPPORT */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) +static int +png_image_free_function(png_voidp argument) +{ + png_imagep image = png_voidcast(png_imagep, argument); + png_controlp cp = image->opaque; + png_control c; + + /* Double check that we have a png_ptr - it should be impossible to get here + * without one. + */ + if (cp->png_ptr == NULL) + return 0; + + /* First free any data held in the control structure. */ +# ifdef PNG_STDIO_SUPPORTED + if (cp->owned_file) + { + FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr); + cp->owned_file = 0; + + /* Ignore errors here. */ + if (fp != NULL) + { + cp->png_ptr->io_ptr = NULL; + (void)fclose(fp); + } + } +# endif + + /* Copy the control structure so that the original, allocated, version can be + * safely freed. Notice that a png_error here stops the remainder of the + * cleanup, but this is probably fine because that would indicate bad memory + * problems anyway. + */ + c = *cp; + image->opaque = &c; + png_free(c.png_ptr, cp); + + /* Then the structures, calling the correct API. */ + if (c.for_write) + { +# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED + png_destroy_write_struct(&c.png_ptr, &c.info_ptr); +# else + png_error(c.png_ptr, "simplified write not supported"); +# endif + } + else + { +# ifdef PNG_SIMPLIFIED_READ_SUPPORTED + png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL); +# else + png_error(c.png_ptr, "simplified read not supported"); +# endif + } + + /* Success. */ + return 1; +} + +void PNGAPI +png_image_free(png_imagep image) +{ + /* Safely call the real function, but only if doing so is safe at this point + * (if not inside an error handling context). Otherwise assume + * png_safe_execute will call this API after the return. + */ + if (image != NULL && image->opaque != NULL && + image->opaque->error_buf == NULL) + { + /* Ignore errors here: */ + (void)png_safe_execute(image, png_image_free_function, image); + image->opaque = NULL; + } +} + +int /* PRIVATE */ +png_image_error(png_imagep image, png_const_charp error_message) +{ + /* Utility to log an error. */ + png_safecat(image->message, (sizeof image->message), 0, error_message); + image->warning_or_error |= PNG_IMAGE_ERROR; + png_image_free(image); + return 0; +} + +#endif /* SIMPLIFIED READ/WRITE */ +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/ext/libpng16/png.h b/ext/libpng17/png.h similarity index 90% rename from ext/libpng16/png.h rename to ext/libpng17/png.h index 36ab027128..775fe83a62 100644 --- a/ext/libpng16/png.h +++ b/ext/libpng17/png.h @@ -1,3319 +1,3351 @@ - -/* png.h - header file for PNG reference library - * - * libpng version 1.6.7 - November 14, 2013 - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license (See LICENSE, below) - * - * Authors and maintainers: - * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat - * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.7 - November 14, 2013: Glenn - * See also "Contributing Authors", below. - * - * Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - * 1.0.8rc1 1 10008 2.1.0.8rc1 - * 1.0.8 1 10008 2.1.0.8 - * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - * 1.0.9rc1 1 10009 2.1.0.9rc1 - * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - * 1.0.9rc2 1 10009 2.1.0.9rc2 - * 1.0.9 1 10009 2.1.0.9 - * 1.0.10beta1 1 10010 2.1.0.10beta1 - * 1.0.10rc1 1 10010 2.1.0.10rc1 - * 1.0.10 1 10010 2.1.0.10 - * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - * 1.0.11rc1 1 10011 2.1.0.11rc1 - * 1.0.11 1 10011 2.1.0.11 - * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - * 1.0.12rc1 2 10012 2.1.0.12rc1 - * 1.0.12 2 10012 2.1.0.12 - * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) - * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - * 1.2.0rc1 3 10200 3.1.2.0rc1 - * 1.2.0 3 10200 3.1.2.0 - * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 - * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - * 1.2.1 3 10201 3.1.2.1 - * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - * 1.0.13 10 10013 10.so.0.1.0.13 - * 1.2.2 12 10202 12.so.0.1.2.2 - * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - * 1.2.3 12 10203 12.so.0.1.2.3 - * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 - * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - * 1.0.14 10 10014 10.so.0.1.0.14 - * 1.2.4 13 10204 12.so.0.1.2.4 - * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 - * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 - * 1.0.15 10 10015 10.so.0.1.0.15 - * 1.2.5 13 10205 12.so.0.1.2.5 - * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - * 1.0.16 10 10016 10.so.0.1.0.16 - * 1.2.6 13 10206 12.so.0.1.2.6 - * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 12.so.0.1.0.17 - * 1.2.7 13 10207 12.so.0.1.2.7 - * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 - * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 - * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - * 1.0.18 10 10018 12.so.0.1.0.18 - * 1.2.8 13 10208 12.so.0.1.2.8 - * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 - * 1.2.9beta4-11 13 10209 12.so.0.9[.0] - * 1.2.9rc1 13 10209 12.so.0.9[.0] - * 1.2.9 13 10209 12.so.0.9[.0] - * 1.2.10beta1-7 13 10210 12.so.0.10[.0] - * 1.2.10rc1-2 13 10210 12.so.0.10[.0] - * 1.2.10 13 10210 12.so.0.10[.0] - * 1.4.0beta1-5 14 10400 14.so.0.0[.0] - * 1.2.11beta1-4 13 10211 12.so.0.11[.0] - * 1.4.0beta7-8 14 10400 14.so.0.0[.0] - * 1.2.11 13 10211 12.so.0.11[.0] - * 1.2.12 13 10212 12.so.0.12[.0] - * 1.4.0beta9-14 14 10400 14.so.0.0[.0] - * 1.2.13 13 10213 12.so.0.13[.0] - * 1.4.0beta15-36 14 10400 14.so.0.0[.0] - * 1.4.0beta37-87 14 10400 14.so.14.0[.0] - * 1.4.0rc01 14 10400 14.so.14.0[.0] - * 1.4.0beta88-109 14 10400 14.so.14.0[.0] - * 1.4.0rc02-08 14 10400 14.so.14.0[.0] - * 1.4.0 14 10400 14.so.14.0[.0] - * 1.4.1beta01-03 14 10401 14.so.14.1[.0] - * 1.4.1rc01 14 10401 14.so.14.1[.0] - * 1.4.1beta04-12 14 10401 14.so.14.1[.0] - * 1.4.1 14 10401 14.so.14.1[.0] - * 1.4.2 14 10402 14.so.14.2[.0] - * 1.4.3 14 10403 14.so.14.3[.0] - * 1.4.4 14 10404 14.so.14.4[.0] - * 1.5.0beta01-58 15 10500 15.so.15.0[.0] - * 1.5.0rc01-07 15 10500 15.so.15.0[.0] - * 1.5.0 15 10500 15.so.15.0[.0] - * 1.5.1beta01-11 15 10501 15.so.15.1[.0] - * 1.5.1rc01-02 15 10501 15.so.15.1[.0] - * 1.5.1 15 10501 15.so.15.1[.0] - * 1.5.2beta01-03 15 10502 15.so.15.2[.0] - * 1.5.2rc01-03 15 10502 15.so.15.2[.0] - * 1.5.2 15 10502 15.so.15.2[.0] - * 1.5.3beta01-10 15 10503 15.so.15.3[.0] - * 1.5.3rc01-02 15 10503 15.so.15.3[.0] - * 1.5.3beta11 15 10503 15.so.15.3[.0] - * 1.5.3 [omitted] - * 1.5.4beta01-08 15 10504 15.so.15.4[.0] - * 1.5.4rc01 15 10504 15.so.15.4[.0] - * 1.5.4 15 10504 15.so.15.4[.0] - * 1.5.5beta01-08 15 10505 15.so.15.5[.0] - * 1.5.5rc01 15 10505 15.so.15.5[.0] - * 1.5.5 15 10505 15.so.15.5[.0] - * 1.5.6beta01-07 15 10506 15.so.15.6[.0] - * 1.5.6rc01-03 15 10506 15.so.15.6[.0] - * 1.5.6 15 10506 15.so.15.6[.0] - * 1.5.7beta01-05 15 10507 15.so.15.7[.0] - * 1.5.7rc01-03 15 10507 15.so.15.7[.0] - * 1.5.7 15 10507 15.so.15.7[.0] - * 1.6.0beta01-40 16 10600 16.so.16.0[.0] - * 1.6.0rc01-08 16 10600 16.so.16.0[.0] - * 1.6.0 16 10600 16.so.16.0[.0] - * 1.6.1beta01-09 16 10601 16.so.16.1[.0] - * 1.6.1rc01 16 10601 16.so.16.1[.0] - * 1.6.1 16 10601 16.so.16.1[.0] - * 1.6.2beta01 16 10602 16.so.16.2[.0] - * 1.6.2rc01-06 16 10602 16.so.16.2[.0] - * 1.6.2 16 10602 16.so.16.2[.0] - * 1.6.3beta01-11 16 10603 16.so.16.3[.0] - * 1.6.3rc01 16 10603 16.so.16.3[.0] - * 1.6.3 16 10603 16.so.16.3[.0] - * 1.6.4beta01-02 16 10604 16.so.16.4[.0] - * 1.6.4rc01 16 10604 16.so.16.4[.0] - * 1.6.4 16 10604 16.so.16.4[.0] - * 1.6.5 16 10605 16.so.16.5[.0] - * 1.6.6 16 10606 16.so.16.6[.0] - * 1.6.7beta01-04 16 10607 16.so.16.7[.0] - * 1.6.7rc01-02 16 10607 16.so.16.7[.0] - * 1.6.7 16 10607 16.so.16.7[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcNN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng-manual.txt or libpng.3 for more information. The PNG - * specification is available as a W3C Recommendation and as an ISO - * Specification, defines should NOT be changed. - */ -#define PNG_INFO_gAMA 0x0001 -#define PNG_INFO_sBIT 0x0002 -#define PNG_INFO_cHRM 0x0004 -#define PNG_INFO_PLTE 0x0008 -#define PNG_INFO_tRNS 0x0010 -#define PNG_INFO_bKGD 0x0020 -#define PNG_INFO_hIST 0x0040 -#define PNG_INFO_pHYs 0x0080 -#define PNG_INFO_oFFs 0x0100 -#define PNG_INFO_tIME 0x0200 -#define PNG_INFO_pCAL 0x0400 -#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */ - -/* This is used for the transformation routines, as some of them - * change these values for the row. It also should enable using - * the routines for other purposes. - */ -typedef struct png_row_info_struct -{ - png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ - png_byte pixel_depth; /* bits per pixel (depth * channels) */ -} png_row_info; - -typedef png_row_info * png_row_infop; -typedef png_row_info * * png_row_infopp; - -/* These are the function types for the I/O functions and for the functions - * that allow the user to override the default I/O functions with his or her - * own. The png_error_ptr type should match that of user-supplied warning - * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. Note that the 'write' function must not - * modify the buffer it is passed. The 'read' function, on the other hand, is - * expected to return the read data in the buffer. - */ -typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); -typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); -typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); -typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, - int)); -typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, - int)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); -typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); - -/* The following callback receives png_uint_32 row_number, int pass for the - * png_bytep data of the row. When transforming an interlaced image the - * row number is the row number within the sub-image of the interlace pass, so - * the value will increase to the height of the sub-image (not the full image) - * then reset to 0 for the next pass. - * - * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to - * find the output pixel (x,y) given an interlaced sub-image pixel - * (row,col,pass). (See below for these macros.) - */ -typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, - png_uint_32, int)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, - png_bytep)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, - png_unknown_chunkp)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -/* not used anywhere */ -/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This must match the function definition in , and the application - * must include this before png.h to obtain the definition of jmp_buf. The - * function is required to be PNG_NORETURN, but this is not checked. If the - * function does return the application will crash via an abort() or similar - * system level call. - * - * If you get a warning here while building the library you may need to make - * changes to ensure that pnglibconf.h records the calling convention used by - * your compiler. This may be very difficult - try using a different compiler - * to build the library! - */ -PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); -#endif - -/* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ -/* Added to libpng-1.2.34 */ -#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER -#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ -/* Added to libpng-1.4.0 */ -#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ -/* Added to libpng-1.5.4 */ -#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ -#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ - -/* Flags for MNG supported features */ -#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 -#define PNG_FLAG_MNG_FILTER_64 0x04 -#define PNG_ALL_MNG_FEATURES 0x05 - -/* NOTE: prior to 1.5 these functions had no 'API' style declaration, - * this allowed the zlib default functions to be used on Windows - * platforms. In 1.5 the zlib default malloc (which just calls malloc and - * ignores the first argument) should be completely compatible with the - * following. - */ -typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, - png_alloc_size_t)); -typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); - -/* Section 3: exported functions - * Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng-manual.txt for the - * full explanation, see example.c for the summary. This just provides - * a simple one line description of the use of each function. - * - * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in - * pngconf.h and in the *.dfn files in the scripts directory. - * - * PNG_EXPORT(ordinal, type, name, (args)); - * - * ordinal: ordinal that is used while building - * *.def files. The ordinal value is only - * relevant when preprocessing png.h with - * the *.dfn files for building symbol table - * entries, and are removed by pngconf.h. - * type: return type of the function - * name: function name - * args: function arguments, with types - * - * When we wish to append attributes to a function prototype we use - * the PNG_EXPORTA() macro instead. - * - * PNG_EXPORTA(ordinal, type, name, (args), attributes); - * - * ordinal, type, name, and args: same as in PNG_EXPORT(). - * attributes: function attributes - */ - -/* Returns the version number of the library */ -PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); - -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ -PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); - -/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a - * PNG file. Returns zero if the supplied bytes match the 8-byte PNG - * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). - */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, - png_size_t num_to_check)); - -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ -#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) - -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ -PNG_EXPORTA(4, png_structp, png_create_read_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn), - PNG_ALLOCATED); - -/* Allocate and initialize png_ptr struct for writing, and any other memory */ -PNG_EXPORTA(5, png_structp, png_create_write_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn), - PNG_ALLOCATED); - -PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, - (png_const_structrp png_ptr)); - -PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, - png_size_t size)); - -/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp - * match up. - */ -#ifdef PNG_SETJMP_SUPPORTED -/* This function returns the jmp_buf built in to *png_ptr. It must be - * supplied with an appropriate 'longjmp' function to use on that jmp_buf - * unless the default error function is overridden in which case NULL is - * acceptable. The size of the jmp_buf is checked against the actual size - * allocated by the library - the call will return NULL on a mismatch - * indicating an ABI mismatch. - */ -PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, - png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); -# define png_jmpbuf(png_ptr) \ - (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) -#else -# define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) -#endif -/* This function should be used by libpng applications in place of - * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it - * will use it; otherwise it will call PNG_ABORT(). This function was - * added in libpng-1.5.0. - */ -PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), - PNG_NORETURN); - -#ifdef PNG_READ_SUPPORTED -/* Reset the compression stream */ -PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); -#endif - -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(11, png_structp, png_create_read_struct_2, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), - PNG_ALLOCATED); -PNG_EXPORTA(12, png_structp, png_create_write_struct_2, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), - PNG_ALLOCATED); -#endif - -/* Write the PNG file signature. */ -PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); - -/* Write a PNG chunk - size, type, (optional) data, CRC. */ -PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep - chunk_name, png_const_bytep data, png_size_t length)); - -/* Write the start of a PNG chunk - length and chunk name. */ -PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, - png_const_bytep chunk_name, png_uint_32 length)); - -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ -PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, - png_const_bytep data, png_size_t length)); - -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); - -/* Allocate and initialize the info structure */ -PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), - PNG_ALLOCATED); - -/* DEPRECATED: this function allowed init structures to be created using the - * default allocation method (typically malloc). Use is deprecated in 1.6.0 and - * the API will be removed in the future. - */ -PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, - png_size_t png_info_struct_size), PNG_DEPRECATED); - -/* Writes all the PNG information before the image. */ -PNG_EXPORT(20, void, png_write_info_before_PLTE, - (png_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(21, void, png_write_info, - (png_structrp png_ptr, png_const_inforp info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. */ -PNG_EXPORT(22, void, png_read_info, - (png_structrp png_ptr, png_inforp info_ptr)); -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED - /* Convert to a US string format: there is no localization support in this - * routine. The original implementation used a 29 character buffer in - * png_struct, this will be removed in future versions. - */ -#if PNG_LIBPNG_VER < 10700 -/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ -PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, - png_const_timep ptime),PNG_DEPRECATED); -#endif -PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], - png_const_timep ptime)); -#endif - -#ifdef PNG_CONVERT_tIME_SUPPORTED -/* Convert from a struct tm to png_time */ -PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, - const struct tm * ttime)); - -/* Convert from time_t to png_time. Uses gmtime() */ -PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); -#endif /* PNG_CONVERT_tIME_SUPPORTED */ - -#ifdef PNG_READ_EXPAND_SUPPORTED -/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); -PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); -PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); -PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_EXPAND_16_SUPPORTED -/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion - * of a tRNS chunk if present. - */ -PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ -PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -/* Expand the grayscale to 24-bit RGB if necessary. */ -PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -/* Reduce RGB to grayscale. */ -#define PNG_ERROR_ACTION_NONE 1 -#define PNG_ERROR_ACTION_WARN 2 -#define PNG_ERROR_ACTION_ERROR 3 -#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ - -PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, - int error_action, double red, double green)) -PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green)) - -PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp - png_ptr)); -#endif - -#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED -PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, - png_colorp palette)); -#endif - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED -/* How the alpha channel is interpreted - this affects how the color channels of - * a PNG file are returned when an alpha channel, or tRNS chunk in a palette - * file, is present. - * - * This has no effect on the way pixels are written into a PNG output - * datastream. The color samples in a PNG datastream are never premultiplied - * with the alpha samples. - * - * The default is to return data according to the PNG specification: the alpha - * channel is a linear measure of the contribution of the pixel to the - * corresponding composited pixel. The gamma encoded color channels must be - * scaled according to the contribution and to do this it is necessary to undo - * the encoding, scale the color values, perform the composition and reencode - * the values. This is the 'PNG' mode. - * - * The alternative is to 'associate' the alpha with the color information by - * storing color channel values that have been scaled by the alpha. The - * advantage is that the color channels can be resampled (the image can be - * scaled) in this form. The disadvantage is that normal practice is to store - * linear, not (gamma) encoded, values and this requires 16-bit channels for - * still images rather than the 8-bit channels that are just about sufficient if - * gamma encoding is used. In addition all non-transparent pixel values, - * including completely opaque ones, must be gamma encoded to produce the final - * image. This is the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' mode (the - * latter being the two common names for associated alpha color channels.) - * - * Since it is not necessary to perform arithmetic on opaque color values so - * long as they are not to be resampled and are in the final color space it is - * possible to optimize the handling of alpha by storing the opaque pixels in - * the PNG format (adjusted for the output color space) while storing partially - * opaque pixels in the standard, linear, format. The accuracy required for - * standard alpha composition is relatively low, because the pixels are - * isolated, therefore typically the accuracy loss in storing 8-bit linear - * values is acceptable. (This is not true if the alpha channel is used to - * simulate transparency over large areas - use 16 bits or the PNG mode in - * this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is - * treated as opaque only if the alpha value is equal to the maximum value. - * - * The final choice is to gamma encode the alpha channel as well. This is - * broken because, in practice, no implementation that uses this choice - * correctly undoes the encoding before handling alpha composition. Use this - * choice only if other serious errors in the software or hardware you use - * mandate it; the typical serious error is for dark halos to appear around - * opaque areas of the composited PNG image because of arithmetic overflow. - * - * The API function png_set_alpha_mode specifies which of these choices to use - * with an enumerated 'mode' value and the gamma of the required output: - */ -#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ -#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ -#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ -#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ -#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ -#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ - -PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, - double output_gamma)) -PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, - int mode, png_fixed_point output_gamma)) -#endif - -#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) -/* The output_gamma value is a screen gamma in libpng terminology: it expresses - * how to decode the output values, not how they are encoded. The values used - * correspond to the normal numbers used to describe the overall gamma of a - * computer display system; for example 2.2 for an sRGB conformant system. The - * values are scaled by 100000 in the _fixed version of the API (so 220000 for - * sRGB.) - * - * The inverse of the value is always used to provide a default for the PNG file - * encoding if it has no gAMA chunk and if png_set_gamma() has not been called - * to override the PNG gamma information. - * - * When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode - * opaque pixels however pixels with lower alpha values are not encoded, - * regardless of the output gamma setting. - * - * When the standard Porter Duff handling is requested with mode 1 the output - * encoding is set to be linear and the output_gamma value is only relevant - * as a default for input data that has no gamma information. The linear output - * encoding will be overridden if png_set_gamma() is called - the results may be - * highly unexpected! - * - * The following numbers are derived from the sRGB standard and the research - * behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of - * 0.45455 (1/2.2) for PNG. The value implicitly includes any viewing - * correction required to take account of any differences in the color - * environment of the original scene and the intended display environment; the - * value expresses how to *decode* the image for display, not how the original - * data was *encoded*. - * - * sRGB provides a peg for the PNG standard by defining a viewing environment. - * sRGB itself, and earlier TV standards, actually use a more complex transform - * (a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is - * limited to simple power laws.) By saying that an image for direct display on - * an sRGB conformant system should be stored with a gAMA chunk value of 45455 - * (11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification - * makes it possible to derive values for other display systems and - * environments. - * - * The Mac value is deduced from the sRGB based on an assumption that the actual - * extra viewing correction used in early Mac display systems was implemented as - * a power 1.45 lookup table. - * - * Any system where a programmable lookup table is used or where the behavior of - * the final display device characteristics can be changed requires system - * specific code to obtain the current characteristic. However this can be - * difficult and most PNG gamma correction only requires an approximate value. - * - * By default, if png_set_alpha_mode() is not called, libpng assumes that all - * values are unencoded, linear, values and that the output device also has a - * linear characteristic. This is only very rarely correct - it is invariably - * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the - * default if you don't know what the right answer is! - * - * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS - * 10.6) which used a correction table to implement a somewhat lower gamma on an - * otherwise sRGB system. - * - * Both these values are reserved (not simple gamma values) in order to allow - * more precise correction internally in the future. - * - * NOTE: the following values can be passed to either the fixed or floating - * point APIs, but the floating point API will also accept floating point - * values. - */ -#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ -#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ -#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ -#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ -#endif - -/* The following are examples of calls to png_set_alpha_mode to achieve the - * required overall gamma correction and, where necessary, alpha - * premultiplication. - * - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); - * This is the default libpng handling of the alpha channel - it is not - * pre-multiplied into the color components. In addition the call states - * that the output is for a sRGB system and causes all PNG files without gAMA - * chunks to be assumed to be encoded using sRGB. - * - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); - * In this case the output is assumed to be something like an sRGB conformant - * display preceeded by a power-law lookup table of power 1.45. This is how - * early Mac systems behaved. - * - * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); - * This is the classic Jim Blinn approach and will work in academic - * environments where everything is done by the book. It has the shortcoming - * of assuming that input PNG data with no gamma information is linear - this - * is unlikely to be correct unless the PNG files where generated locally. - * Most of the time the output precision will be so low as to show - * significant banding in dark areas of the image. - * - * png_set_expand_16(pp); - * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); - * This is a somewhat more realistic Jim Blinn inspired approach. PNG files - * are assumed to have the sRGB encoding if not marked with a gamma value and - * the output is always 16 bits per component. This permits accurate scaling - * and processing of the data. If you know that your input PNG files were - * generated locally you might need to replace PNG_DEFAULT_sRGB with the - * correct value for your system. - * - * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); - * If you just need to composite the PNG image onto an existing background - * and if you control the code that does this you can use the optimization - * setting. In this case you just copy completely opaque pixels to the - * output. For pixels that are not completely transparent (you just skip - * those) you do the composition math using png_composite or png_composite_16 - * below then encode the resultant 8-bit or 16-bit values to match the output - * encoding. - * - * Other cases - * If neither the PNG nor the standard linear encoding work for you because - * of the software or hardware you use then you have a big problem. The PNG - * case will probably result in halos around the image. The linear encoding - * will probably result in a washed out, too bright, image (it's actually too - * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably - * substantially reduce the halos. Alternatively try: - * - * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); - * This option will also reduce the halos, but there will be slight dark - * halos round the opaque parts of the image where the background is light. - * In the OPTIMIZED mode the halos will be light halos where the background - * is dark. Take your pick - the halos are unavoidable unless you can get - * your hardware/software fixed! (The OPTIMIZED approach is slightly - * faster.) - * - * When the default gamma of PNG files doesn't match the output gamma. - * If you have PNG files with no gamma information png_set_alpha_mode allows - * you to provide a default gamma, but it also sets the ouput gamma to the - * matching value. If you know your PNG files have a gamma that doesn't - * match the output you can take advantage of the fact that - * png_set_alpha_mode always sets the output gamma but only sets the PNG - * default if it is not already set: - * - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); - * The first call sets both the default and the output gamma values, the - * second call overrides the output gamma without changing the default. This - * is easier than achieving the same effect with png_set_gamma. You must use - * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will - * fire if more than one call to png_set_alpha_mode and png_set_background is - * made in the same read operation, however multiple calls with PNG_ALPHA_PNG - * are ignored. - */ - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ -PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, - int flags)); -/* The values of the PNG_FILLER_ defines should NOT be changed */ -# define PNG_FILLER_BEFORE 0 -# define PNG_FILLER_AFTER 1 -/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ -PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, - png_uint_32 filler, int flags)); -#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swap bytes in 16-bit depth files. */ -PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ - defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ -PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ -PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p - true_bits)); -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. - * MUST be called before png_read_update_info or png_start_read_image, - * otherwise it will not have the desired effect. Note that it is still - * necessary to call png_read_row or png_read_rows png_get_image_height - * times for each pass. -*/ -PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ -PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_BACKGROUND_SUPPORTED -/* Handle alpha and tRNS by replacing with a background color. Prior to - * libpng-1.5.4 this API must not be called before the PNG file header has been - * read. Doing so will result in unexpected behavior and possible warnings or - * errors if the PNG file contains a bKGD chunk. - */ -PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)) -PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, png_fixed_point background_gamma)) -#endif -#ifdef PNG_READ_BACKGROUND_SUPPORTED -# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 -# define PNG_BACKGROUND_GAMMA_SCREEN 1 -# define PNG_BACKGROUND_GAMMA_FILE 2 -# define PNG_BACKGROUND_GAMMA_UNIQUE 3 -#endif - -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED -/* Scale a 16-bit depth file down to 8-bit, accurately. */ -PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED -#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */ -/* Strip the second byte of information from a 16-bit depth file. */ -PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* Turn on quantizing, and reduce the palette to the number of colors - * available. - */ -PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, - png_colorp palette, int num_palette, int maximum_colors, - png_const_uint_16p histogram, int full_quantize)); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* The threshold on gamma processing is configurable but hard-wired into the - * library. The following is the floating point variant. - */ -#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) - -/* Handle gamma correction. Screen_gamma=(display_exponent). - * NOTE: this API simply sets the screen and file gamma values. It will - * therefore override the value for gamma in a PNG file if it is called after - * the file header has been read - use with care - call before reading the PNG - * file for best results! - * - * These routines accept the same gamma values as png_set_alpha_mode (described - * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either - * API (floating point or fixed.) Notice, however, that the 'file_gamma' value - * is the inverse of a 'screen gamma' value. - */ -PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, - double screen_gamma, double override_file_gamma)) -PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, - png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) -#endif - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -/* Set how many lines between output flushes - 0 for no flushing */ -PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ -PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); -#endif - -/* Optional update palette with requested transformations */ -PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); - -/* Optional call to update the users info structure */ -PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, - png_inforp info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. */ -PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, - png_bytepp display_row, png_uint_32 num_rows)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read a row of data. */ -PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, - png_bytep display_row)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the whole image into memory at once. */ -PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); -#endif - -/* Write a row of image data */ -PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, - png_const_bytep row)); - -/* Write a few rows of image data: (*row) is not written; however, the type - * is declared as writeable to maintain compatibility with previous versions - * of libpng and to allow the 'display_row' array from read_rows to be passed - * unchanged to write_rows. - */ -PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, - png_uint_32 num_rows)); - -/* Write the image data */ -PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); - -/* Write the end of the PNG file. */ -PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, - png_inforp info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. */ -PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); -#endif - -/* Free any memory associated with the png_info_struct */ -PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, - png_infopp info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr)); - -/* Set the libpng method of handling chunk CRC errors */ -PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, - int ancil_action)); - -/* Values for png_set_crc_action() say how to handle CRC errors in - * ancillary and critical chunks, and whether to use the data contained - * therein. Note that it is impossible to "discard" data in a critical - * chunk. For versions prior to 0.90, the action was always error/quit, - * whereas in version 0.90 and later, the action for CRC errors in ancillary - * chunks is warn/discard. These values should NOT be changed. - * - * value action:critical action:ancillary - */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ - -/* These functions give the user control over the scan-line filtering in - * libpng and the compression methods used by zlib. These functions are - * mainly useful for testing, as the defaults should work with most users. - * Those users who are tight on memory or want faster performance at the - * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. - */ - -/* Set the filtering method(s) used by libpng. Currently, the only valid - * value for "method" is 0. - */ -PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, - int filters)); - -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 -#define PNG_FILTER_PAETH 0x80 -#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) - -/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. - */ -#define PNG_FILTER_VALUE_NONE 0 -#define PNG_FILTER_VALUE_SUB 1 -#define PNG_FILTER_VALUE_UP 2 -#define PNG_FILTER_VALUE_AVG 3 -#define PNG_FILTER_VALUE_PAETH 4 -#define PNG_FILTER_VALUE_LAST 5 - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ -/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ - * defines, either the default (minimum-sum-of-absolute-differences), or - * the experimental method (weighted-minimum-sum-of-absolute-differences). - * - * Weights are factors >= 1.0, indicating how important it is to keep the - * filter type consistent between rows. Larger numbers mean the current - * filter is that many times as likely to be the same as the "num_weights" - * previous filters. This is cumulative for each previous row with a weight. - * There needs to be "num_weights" values in "filter_weights", or it can be - * NULL if the weights aren't being specified. Weights have no influence on - * the selection of the first row filter. Well chosen weights can (in theory) - * improve the compression for a given image. - * - * Costs are factors >= 1.0 indicating the relative decoding costs of a - * filter type. Higher costs indicate more decoding expense, and are - * therefore less likely to be selected over a filter with lower computational - * costs. There needs to be a value in "filter_costs" for each valid filter - * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't - * setting the costs. Costs try to improve the speed of decompression without - * unduly increasing the compressed image size. - * - * A negative weight or cost indicates the default value is to be used, and - * values in the range [0.0, 1.0) indicate the value is to remain unchanged. - * The default values for both weights and costs are currently 1.0, but may - * change if good general weighting/cost heuristics can be found. If both - * the weights and costs are set to 1.0, this degenerates the WEIGHTED method - * to the UNWEIGHTED method, but with added encoding time/computation. - */ -PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, - int heuristic_method, int num_weights, png_const_doublep filter_weights, - png_const_doublep filter_costs)) -PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, - (png_structrp png_ptr, int heuristic_method, int num_weights, - png_const_fixed_point_p filter_weights, - png_const_fixed_point_p filter_costs)) -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -/* Heuristic used for row filter selection. These defines should NOT be - * changed. - */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ - -#ifdef PNG_WRITE_SUPPORTED -/* Set the library compression level. Currently, valid values range from - * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 - * (0 - no compression, 9 - "maximal" compression). Note that tests have - * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, - * these values may not correspond directly to the zlib compression levels. - */ -PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, - int level)); - -PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, - int mem_level)); - -PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, - int strategy)); - -/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a - * smaller value of window_bits if it can do so safely. - */ -PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, - int window_bits)); - -PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, - int method)); -#endif - -#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED -/* Also set zlib parameters for compressing non-IDAT chunks */ -PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, - int level)); - -PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, - int mem_level)); - -PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, - int strategy)); - -/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a - * smaller value of window_bits if it can do so safely. - */ -PNG_EXPORT(225, void, png_set_text_compression_window_bits, - (png_structrp png_ptr, int window_bits)); - -PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, - int method)); -#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ - -/* These next functions are called for input/output, memory, and error - * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, - * and call standard C I/O routines such as fread(), fwrite(), and - * fprintf(). These functions can be made to use other I/O routines - * at run time for those applications that need to handle I/O in a - * different manner by calling png_set_???_fn(). See libpng-manual.txt for - * more information. - */ - -#ifdef PNG_STDIO_SUPPORTED -/* Initialize the input/output for the PNG file to the default functions. */ -PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); -#endif - -/* Replace the (error and abort), and warning functions with user - * supplied functions. If no messages are to be printed you must still - * write and use replacement functions. The replacement error_fn should - * still do a longjmp to the last setjmp location if you are using this - * method of error handling. If error_fn or warning_fn is NULL, the - * default function will be used. - */ - -PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); - -/* Return the user pointer associated with the error functions */ -PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); - -/* Replace the default data output functions with a user supplied one(s). - * If buffered output is not used, then output_flush_fn can be set to NULL. - * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time - * output_flush_fn will be ignored (and thus can be NULL). - * It is probably a mistake to use NULL for output_flush_fn if - * write_data_fn is not also NULL unless you have built libpng with - * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's - * default flush function, which uses the standard *FILE structure, will - * be used. - */ -PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, - png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); - -/* Replace the default data input function with a user supplied one. */ -PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn)); - -/* Return the user pointer associated with the I/O functions */ -PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); - -PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, - png_read_status_ptr read_row_fn)); - -PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, - png_write_status_ptr write_row_fn)); - -#ifdef PNG_USER_MEM_SUPPORTED -/* Replace the default memory allocation functions with user supplied one(s). */ -PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -/* Return the user pointer associated with the memory functions */ -PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); -#endif - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, - png_user_transform_ptr read_user_transform_fn)); -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, - png_user_transform_ptr write_user_transform_fn)); -#endif - -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, - png_voidp user_transform_ptr, int user_transform_depth, - int user_transform_channels)); -/* Return the user pointer associated with the user transform functions */ -PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, - (png_const_structrp png_ptr)); -#endif - -#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED -/* Return information about the row currently being processed. Note that these - * APIs do not fail but will return unexpected results if called outside a user - * transform callback. Also note that when transforming an interlaced image the - * row number is the row number within the sub-image of the interlace pass, so - * the value will increase to the height of the sub-image (not the full image) - * then reset to 0 for the next pass. - * - * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to - * find the output pixel (x,y) given an interlaced sub-image pixel - * (row,col,pass). (See below for these macros.) - */ -PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); -PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); -#endif - -#ifdef PNG_READ_USER_CHUNKS_SUPPORTED -/* This callback is called only for *unknown* chunks. If - * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known - * chunks to be treated as unknown, however in this case the callback must do - * any processing required by the chunk (e.g. by calling the appropriate - * png_set_ APIs.) - * - * There is no write support - on write, by default, all the chunks in the - * 'unknown' list are written in the specified position. - * - * The integer return from the callback function is interpreted thus: - * - * negative: An error occured, png_chunk_error will be called. - * zero: The chunk was not handled, the chunk will be saved. A critical - * chunk will cause an error at this point unless it is to be saved. - * positive: The chunk was handled, libpng will ignore/discard it. - * - * See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about - * how this behavior will change in libpng 1.7 - */ -PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* Sets the function callbacks for the push reader, and a pointer to a - * user-defined structure available to the callback functions. - */ -PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, - png_voidp progressive_ptr, png_progressive_info_ptr info_fn, - png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); - -/* Returns the user pointer associated with the push read functions */ -PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, - (png_const_structrp png_ptr)); - -/* Function to be called when data becomes available */ -PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, - png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size)); - -/* A function which may be called *only* within png_process_data to stop the - * processing of any more data. The function returns the number of bytes - * remaining, excluding any that libpng has cached internally. A subsequent - * call to png_process_data must supply these bytes again. If the argument - * 'save' is set to true the routine will first save all the pending data and - * will always return 0. - */ -PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save)); - -/* A function which may be called *only* outside (after) a call to - * png_process_data. It returns the number of bytes of data to skip in the - * input. Normally it will return 0, but if it returns a non-zero value the - * application must skip than number of bytes of input data and pass the - * following data to the next call to png_process_data. - */ -PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); - -#ifdef PNG_READ_INTERLACING_SUPPORTED -/* Function that combines rows. 'new_row' is a flag that should come from - * the callback and be non-NULL if anything needs to be done; the library - * stores its own version of the new data internally and ignores the passed - * in value. - */ -PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, - png_bytep old_row, png_const_bytep new_row)); -#endif /* PNG_READ_INTERLACING_SUPPORTED */ -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); -/* Added at libpng version 1.4.0 */ -PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); - -/* Added at libpng version 1.2.4 */ -PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); - -/* Frees a pointer allocated by png_malloc() */ -PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); - -/* Free data that was allocated internally */ -PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_32 free_me, int num)); - -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application; this works on the png_info structure passed - * in, it does not change the state for other png_info structures. - * - * It is unlikely that this function works correctly as of 1.6.0 and using it - * may result either in memory leaks or double free of allocated data. - */ -PNG_EXPORTA(99, void, png_data_freer, (png_const_structrp png_ptr, - png_inforp info_ptr, int freer, png_uint_32 mask), PNG_DEPRECATED); - -/* Assignments for png_data_freer */ -#define PNG_DESTROY_WILL_FREE_DATA 1 -#define PNG_SET_WILL_FREE_DATA 1 -#define PNG_USER_WILL_FREE_DATA 2 -/* Flags for png_ptr->free_me and info_ptr->free_me */ -#define PNG_FREE_HIST 0x0008 -#define PNG_FREE_ICCP 0x0010 -#define PNG_FREE_SPLT 0x0020 -#define PNG_FREE_ROWS 0x0040 -#define PNG_FREE_PCAL 0x0080 -#define PNG_FREE_SCAL 0x0100 -#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_FREE_UNKN 0x0200 -#endif -/* PNG_FREE_LIST 0x0400 removed in 1.6.0 because it is ignored */ -#define PNG_FREE_PLTE 0x1000 -#define PNG_FREE_TRNS 0x2000 -#define PNG_FREE_TEXT 0x4000 -#define PNG_FREE_ALL 0x7fff -#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ - -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); -PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, - png_voidp ptr), PNG_DEPRECATED); -#endif - -#ifdef PNG_ERROR_TEXT_SUPPORTED -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, - png_const_charp error_message), PNG_NORETURN); - -/* The same, but the chunk name is prepended to the error string. */ -PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, - png_const_charp error_message), PNG_NORETURN); - -#else -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); -#endif - -#ifdef PNG_WARNINGS_SUPPORTED -/* Non-fatal error in libpng. Can continue, but may have a problem. */ -PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, - png_const_charp warning_message)); - -/* Non-fatal error in libpng, chunk name is prepended to message. */ -PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, - png_const_charp warning_message)); -#endif - -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -/* Benign error in libpng. Can continue, but may have a problem. - * User can choose whether to handle as a fatal error or as a warning. */ -PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, - png_const_charp warning_message)); - -#ifdef PNG_READ_SUPPORTED -/* Same, chunk name is prepended to message (only during read) */ -PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, - png_const_charp warning_message)); -#endif - -PNG_EXPORT(109, void, png_set_benign_errors, - (png_structrp png_ptr, int allowed)); -#else -# ifdef PNG_ALLOW_BENIGN_ERRORS -# define png_benign_error png_warning -# define png_chunk_benign_error png_chunk_warning -# else -# define png_benign_error png_error -# define png_chunk_benign_error png_chunk_error -# endif -#endif - -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ calls are used to read values from the - * png_info_struct, either storing the parameters in the passed variables, or - * setting pointers into the png_info_struct where the data is stored. The - * png_get_ functions return a non-zero value if the data was available - * in info_ptr, or return zero and do not change any of the parameters if the - * data was not available. - * - * These functions should be used instead of directly accessing png_info - * to avoid problems with future changes in the size and internal layout of - * png_info_struct. - */ -/* Returns "flag" if chunk data is valid in info_ptr. */ -PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 flag)); - -/* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* Returns row_pointers, which is an array of pointers to scanlines that was - * returned from png_read_png(). - */ -PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Set row_pointers, which is an array of pointers to scanlines for use - * by png_write_png(). - */ -PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, - png_inforp info_ptr, png_bytepp row_pointers)); -#endif - -/* Returns number of color channels in image. */ -PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ -PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image height in pixels. */ -PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image bit_depth. */ -PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image color_type. */ -PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image filter_type. */ -PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image interlace_type. */ -PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image compression_type. */ -PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ -PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); - -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ -PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) -PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) - -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -#ifdef PNG_READ_SUPPORTED -/* Returns pointer to signature string read from PNG header */ -PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); -#endif - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, - png_inforp info_ptr, png_color_16p *background)); -#endif - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_color_16p background)); -#endif - -#ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, - png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, - double *red_y, double *green_x, double *green_y, double *blue_x, - double *blue_y)) -PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, - png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, - double *green_X, double *green_Y, double *green_Z, double *blue_X, - double *blue_Y, double *blue_Z)) -PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *int_white_x, png_fixed_point *int_white_y, - png_fixed_point *int_red_x, png_fixed_point *int_red_y, - png_fixed_point *int_green_x, png_fixed_point *int_green_y, - png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) -PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *int_red_X, png_fixed_point *int_red_Y, - png_fixed_point *int_red_Z, png_fixed_point *int_green_X, - png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, - png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, - png_fixed_point *int_blue_Z)) -#endif - -#ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, - png_inforp info_ptr, - double white_x, double white_y, double red_x, double red_y, double green_x, - double green_y, double blue_x, double blue_y)) -PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, - png_inforp info_ptr, double red_X, double red_Y, double red_Z, - double green_X, double green_Y, double green_Z, double blue_X, - double blue_Y, double blue_Z)) -PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, png_fixed_point int_white_x, - png_fixed_point int_white_y, png_fixed_point int_red_x, - png_fixed_point int_red_y, png_fixed_point int_green_x, - png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)) -PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, - png_fixed_point int_red_Z, png_fixed_point int_green_X, - png_fixed_point int_green_Y, png_fixed_point int_green_Z, - png_fixed_point int_blue_X, png_fixed_point int_blue_Y, - png_fixed_point int_blue_Z)) -#endif - -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, - png_const_inforp info_ptr, double *file_gamma)) -PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *int_file_gamma)) -#endif - -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, - png_inforp info_ptr, double file_gamma)) -PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, png_fixed_point int_file_gamma)) -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_16p *hist)); -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_uint_16p hist)); -#endif - -PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, - int *bit_depth, int *color_type, int *interlace_method, - int *compression_method, int *filter_method)); - -PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_method, int compression_method, - int filter_method)); - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, - int *unit_type)); -#endif - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, - png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, - int unit_type)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, - png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, - png_int_32 *X1, int *type, int *nparams, png_charp *units, - png_charpp *params)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, - int type, int nparams, png_const_charp units, png_charpp params)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, - int *unit_type)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); -#endif - -PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, - png_inforp info_ptr, png_colorp *palette, int *num_palette)); - -PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, - png_inforp info_ptr, png_const_colorp palette, int num_palette)); - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_color_8p *sig_bit)); -#endif - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_color_8p sig_bit)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, - png_const_inforp info_ptr, int *file_srgb_intent)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, - png_inforp info_ptr, int srgb_intent)); -PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, - png_inforp info_ptr, int srgb_intent)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, - png_inforp info_ptr, png_charpp name, int *compression_type, - png_bytepp profile, png_uint_32 *proflen)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_charp name, int compression_type, - png_const_bytep profile, png_uint_32 proflen)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_sPLT_tpp entries)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); -#endif - -#ifdef PNG_TEXT_SUPPORTED -/* png_get_text also returns the number of text chunks in *num_text */ -PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, - png_inforp info_ptr, png_textp *text_ptr, int *num_text)); -#endif - -/* Note while png_set_text() will accept a structure whose text, - * language, and translated keywords are NULL pointers, the structure - * returned by png_get_text will always contain regular - * zero-terminated C strings. They might be empty strings but - * they will never be NULL pointers. - */ - -#ifdef PNG_TEXT_SUPPORTED -PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_textp text_ptr, int num_text)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, - png_inforp info_ptr, png_timep *mod_time)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_timep mod_time)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, - png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, - png_color_16p *trans_color)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, - png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, - png_const_color_16p trans_color)); -#endif - -#ifdef PNG_sCAL_SUPPORTED -PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, - png_const_inforp info_ptr, int *unit, double *width, double *height)) -#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ - defined(PNG_FLOATING_POINT_SUPPORTED) -/* NOTE: this API is currently implemented using floating point arithmetic, - * consequently it can only be used on systems with floating point support. - * In any case the range of values supported by png_fixed_point is small and it - * is highly recommended that png_get_sCAL_s be used instead. - */ -PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, - png_fixed_point *width, png_fixed_point *height)) -#endif -PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, - (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, - png_charpp swidth, png_charpp sheight)); - -PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, - png_inforp info_ptr, int unit, double width, double height)) -PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, int unit, png_fixed_point width, - png_fixed_point height)) -PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, - png_inforp info_ptr, int unit, - png_const_charp swidth, png_const_charp sheight)); -#endif /* PNG_sCAL_SUPPORTED */ - -#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED -/* Provide the default handling for all unknown chunks or, optionally, for - * specific unknown chunks. - * - * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was - * ignored and the default was used, the per-chunk setting only had an effect on - * write. If you wish to have chunk-specific handling on read in code that must - * work on earlier versions you must use a user chunk callback to specify the - * desired handling (keep or discard.) - * - * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The - * parameter is interpreted as follows: - * - * READ: - * PNG_HANDLE_CHUNK_AS_DEFAULT: - * Known chunks: do normal libpng processing, do not keep the chunk (but - * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) - * Unknown chunks: for a specific chunk use the global default, when used - * as the default discard the chunk data. - * PNG_HANDLE_CHUNK_NEVER: - * Discard the chunk data. - * PNG_HANDLE_CHUNK_IF_SAFE: - * Keep the chunk data if the chunk is not critical else raise a chunk - * error. - * PNG_HANDLE_CHUNK_ALWAYS: - * Keep the chunk data. - * - * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, - * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent - * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks - * it simply resets the behavior to the libpng default. - * - * INTERACTION WTIH USER CHUNK CALLBACKS: - * The per-chunk handling is always used when there is a png_user_chunk_ptr - * callback and the callback returns 0; the chunk is then always stored *unless* - * it is critical and the per-chunk setting is other than ALWAYS. Notice that - * the global default is *not* used in this case. (In effect the per-chunk - * value is incremented to at least IF_SAFE.) - * - * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and - * per-chunk defaults will be honored. If you want to preserve the current - * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE - * as the default - if you don't do this libpng 1.6 will issue a warning. - * - * If you want unhandled unknown chunks to be discarded in libpng 1.6 and - * earlier simply return '1' (handled). - * - * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: - * If this is *not* set known chunks will always be handled by libpng and - * will never be stored in the unknown chunk list. Known chunks listed to - * png_set_keep_unknown_chunks will have no effect. If it is set then known - * chunks listed with a keep other than AS_DEFAULT will *never* be processed - * by libpng, in addition critical chunks must either be processed by the - * callback or saved. - * - * The IHDR and IEND chunks must not be listed. Because this turns off the - * default handling for chunks that would otherwise be recognized the - * behavior of libpng transformations may well become incorrect! - * - * WRITE: - * When writing chunks the options only apply to the chunks specified by - * png_set_unknown_chunks (below), libpng will *always* write known chunks - * required by png_set_ calls and will always write the core critical chunks - * (as required for PLTE). - * - * Each chunk in the png_set_unknown_chunks list is looked up in the - * png_set_keep_unknown_chunks list to find the keep setting, this is then - * interpreted as follows: - * - * PNG_HANDLE_CHUNK_AS_DEFAULT: - * Write safe-to-copy chunks and write other chunks if the global - * default is set to _ALWAYS, otherwise don't write this chunk. - * PNG_HANDLE_CHUNK_NEVER: - * Do not write the chunk. - * PNG_HANDLE_CHUNK_IF_SAFE: - * Write the chunk if it is safe-to-copy, otherwise do not write it. - * PNG_HANDLE_CHUNK_ALWAYS: - * Write the chunk. - * - * Note that the default behavior is effectively the opposite of the read case - - * in read unknown chunks are not stored by default, in write they are written - * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different - * - on write the safe-to-copy bit is checked, on read the critical bit is - * checked and on read if the chunk is critical an error will be raised. - * - * num_chunks: - * =========== - * If num_chunks is positive, then the "keep" parameter specifies the manner - * for handling only those chunks appearing in the chunk_list array, - * otherwise the chunk list array is ignored. - * - * If num_chunks is 0 the "keep" parameter specifies the default behavior for - * unknown chunks, as described above. - * - * If num_chunks is negative, then the "keep" parameter specifies the manner - * for handling all unknown chunks plus all chunks recognized by libpng - * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to - * be processed by libpng. - */ -PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, - int keep, png_const_bytep chunk_list, int num_chunks)); - -/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; - * the result is therefore true (non-zero) if special handling is required, - * false for the default handling. - */ -PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, - png_const_bytep chunk_name)); -#endif - -#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_unknown_chunkp unknowns, - int num_unknowns)); - /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added - * unknowns to the location currently stored in the png_struct. This is - * invariably the wrong value on write. To fix this call the following API - * for each chunk in the list with the correct location. If you know your - * code won't be compiled on earlier versions you can rely on - * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing - * the correct thing. - */ - -PNG_EXPORT(175, void, png_set_unknown_chunk_location, - (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); - -PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, - png_inforp info_ptr, png_unknown_chunkpp entries)); -#endif - -/* Png_free_data() will turn off the "valid" flag for anything it frees. - * If you need to turn it off for a chunk that your application has freed, - * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); - */ -PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, - png_inforp info_ptr, int mask)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* The "params" pointer is currently not used and is for future expansion. */ -PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, - int transforms, png_voidp params)); -PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, - int transforms, png_voidp params)); -#endif - -PNG_EXPORT(180, png_const_charp, png_get_copyright, - (png_const_structrp png_ptr)); -PNG_EXPORT(181, png_const_charp, png_get_header_ver, - (png_const_structrp png_ptr)); -PNG_EXPORT(182, png_const_charp, png_get_header_version, - (png_const_structrp png_ptr)); -PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, - (png_const_structrp png_ptr)); - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, - png_uint_32 mng_features_permitted)); -#endif - -/* For use in png_set_keep_unknown, added to version 1.2.6 */ -#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 -#define PNG_HANDLE_CHUNK_NEVER 1 -#define PNG_HANDLE_CHUNK_IF_SAFE 2 -#define PNG_HANDLE_CHUNK_ALWAYS 3 -#define PNG_HANDLE_CHUNK_LAST 4 - -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. - */ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, - png_uint_32 strip_mode)); -#endif - -/* Added in libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, - png_uint_32 user_width_max, png_uint_32 user_height_max)); -PNG_EXPORT(187, png_uint_32, png_get_user_width_max, - (png_const_structrp png_ptr)); -PNG_EXPORT(188, png_uint_32, png_get_user_height_max, - (png_const_structrp png_ptr)); -/* Added in libpng-1.4.0 */ -PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, - png_uint_32 user_chunk_cache_max)); -PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, - (png_const_structrp png_ptr)); -/* Added in libpng-1.4.1 */ -PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, - png_alloc_size_t user_chunk_cache_max)); -PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, - (png_const_structrp png_ptr)); -#endif - -#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) -PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); - -PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); - -PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); - -PNG_FP_EXPORT(196, float, png_get_x_offset_inches, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) -#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) -#endif - -PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, - png_const_inforp info_ptr)) -#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) -#endif - -# ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, - int *unit_type)); -# endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ - -/* Added in libpng-1.4.0 */ -#ifdef PNG_IO_STATE_SUPPORTED -PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); - -/* Removed from libpng 1.6; use png_get_io_chunk_type. */ -PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), - PNG_DEPRECATED) - -PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, - (png_const_structrp png_ptr)); - -/* The flags returned by png_get_io_state() are the following: */ -# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ -# define PNG_IO_READING 0x0001 /* currently reading */ -# define PNG_IO_WRITING 0x0002 /* currently writing */ -# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ -# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ -# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ -# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ -# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ -# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ -#endif /* ?PNG_IO_STATE_SUPPORTED */ - -/* Interlace support. The following macros are always defined so that if - * libpng interlace handling is turned off the macros may be used to handle - * interlaced images within the application. - */ -#define PNG_INTERLACE_ADAM7_PASSES 7 - -/* Two macros to return the first row and first column of the original, - * full, image which appears in a given pass. 'pass' is in the range 0 - * to 6 and the result is in the range 0 to 7. - */ -#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) -#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) - -/* A macro to return the offset between pixels in the output row for a pair of - * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that - * follows. Note that ROW_OFFSET is the offset from one row to the next whereas - * COL_OFFSET is from one column to the next, within a row. - */ -#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) -#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) - -/* Two macros to help evaluate the number of rows or columns in each - * pass. This is expressed as a shift - effectively log2 of the number or - * rows or columns in each 8x8 tile of the original image. - */ -#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) -#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) - -/* Hence two macros to determine the number of rows or columns in a given - * pass of an image given its height or width. In fact these macros may - * return non-zero even though the sub-image is empty, because the other - * dimension may be empty for a small image. - */ -#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) -#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) - -/* For the reader row callbacks (both progressive and sequential) it is - * necessary to find the row in the output image given a row in an interlaced - * image, so two more macros: - */ -#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ - (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ - ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) - -#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ - ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) -#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ - ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) - -#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines we avoid an integer divide, which will be slower on - * most machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on a few RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ - -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ - * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 \ - - (png_uint_16)(alpha)) + 128); \ - (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } - -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ - * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(65535 \ - - (png_uint_32)(alpha)) + 32768); \ - (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } - -#else /* Standard method using integer division */ - -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - 127) / 255) - -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ - 32767) / 65535) -#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ - -#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); -PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); -PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); -#endif - -PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, - png_const_bytep buf)); -/* No png_get_int_16 -- may be added if there's a real need for it. */ - -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); -#endif -#ifdef PNG_SAVE_INT_32_SUPPORTED -PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); -#endif - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ -#endif - -#ifdef PNG_USE_READ_MACROS -/* Inline macros to do direct reads of bytes from the input buffer. - * The png_get_int_32() routine assumes we are using two's complement - * format for negative values, which is almost certainly true. - */ -# define PNG_get_uint_32(buf) \ - (((png_uint_32)(*(buf)) << 24) + \ - ((png_uint_32)(*((buf) + 1)) << 16) + \ - ((png_uint_32)(*((buf) + 2)) << 8) + \ - ((png_uint_32)(*((buf) + 3)))) - - /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the - * function) incorrectly returned a value of type png_uint_32. - */ -# define PNG_get_uint_16(buf) \ - ((png_uint_16) \ - (((unsigned int)(*(buf)) << 8) + \ - ((unsigned int)(*((buf) + 1))))) - -# define PNG_get_int_32(buf) \ - ((png_int_32)((*(buf) & 0x80) \ - ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ - : (png_int_32)png_get_uint_32(buf))) - - /* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, - * but defining a macro name prefixed with PNG_PREFIX. - */ -# ifndef PNG_PREFIX -# define png_get_uint_32(buf) PNG_get_uint_32(buf) -# define png_get_uint_16(buf) PNG_get_uint_16(buf) -# define png_get_int_32(buf) PNG_get_int_32(buf) -# endif -#else -# ifdef PNG_PREFIX - /* No macros; revert to the (redefined) function */ -# define PNG_get_uint_32 (png_get_uint_32) -# define PNG_get_uint_16 (png_get_uint_16) -# define PNG_get_int_32 (png_get_int_32) -# endif -#endif - -/******************************************************************************* - * SIMPLIFIED API - ******************************************************************************* - * - * Please read the documentation in libpng-manual.txt (TODO: write said - * documentation) if you don't understand what follows. - * - * The simplified API hides the details of both libpng and the PNG file format - * itself. It allows PNG files to be read into a very limited number of - * in-memory bitmap formats or to be written from the same formats. If these - * formats do not accomodate your needs then you can, and should, use the more - * sophisticated APIs above - these support a wide variety of in-memory formats - * and a wide variety of sophisticated transformations to those formats as well - * as a wide variety of APIs to manipulate ancillary information. - * - * To read a PNG file using the simplified API: - * - * 1) Declare a 'png_image' structure (see below) on the stack and set the - * version field to PNG_IMAGE_VERSION. - * 2) Call the appropriate png_image_begin_read... function. - * 3) Set the png_image 'format' member to the required sample format. - * 4) Allocate a buffer for the image and, if required, the color-map. - * 5) Call png_image_finish_read to read the image and, if required, the - * color-map into your buffers. - * - * There are no restrictions on the format of the PNG input itself; all valid - * color types, bit depths, and interlace methods are acceptable, and the - * input image is transformed as necessary to the requested in-memory format - * during the png_image_finish_read() step. The only caveat is that if you - * request a color-mapped image from a PNG that is full-color or makes - * complex use of an alpha channel the transformation is extremely lossy and the - * result may look terrible. - * - * To write a PNG file using the simplified API: - * - * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. - * 2) Initialize the members of the structure that describe the image, setting - * the 'format' member to the format of the image samples. - * 3) Call the appropriate png_image_write... function with a pointer to the - * image and, if necessary, the color-map to write the PNG data. - * - * png_image is a structure that describes the in-memory format of an image - * when it is being read or defines the in-memory format of an image that you - * need to write: - */ -#define PNG_IMAGE_VERSION 1 - -typedef struct png_control *png_controlp; -typedef struct -{ - png_controlp opaque; /* Initialize to NULL, free with png_image_free */ - png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ - png_uint_32 width; /* Image width in pixels (columns) */ - png_uint_32 height; /* Image height in pixels (rows) */ - png_uint_32 format; /* Image format as defined below */ - png_uint_32 flags; /* A bit mask containing informational flags */ - png_uint_32 colormap_entries; - /* Number of entries in the color-map */ - - /* In the event of an error or warning the following field will be set to a - * non-zero value and the 'message' field will contain a '\0' terminated - * string with the libpng error or warning message. If both warnings and - * an error were encountered, only the error is recorded. If there - * are multiple warnings, only the first one is recorded. - * - * The upper 30 bits of this value are reserved, the low two bits contain - * a value as follows: - */ -# define PNG_IMAGE_WARNING 1 -# define PNG_IMAGE_ERROR 2 - /* - * The result is a two bit code such that a value more than 1 indicates - * a failure in the API just called: - * - * 0 - no warning or error - * 1 - warning - * 2 - error - * 3 - error preceded by warning - */ -# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) - - png_uint_32 warning_or_error; - - char message[64]; -} png_image, *png_imagep; - -/* The samples of the image have one to four channels whose components have - * original values in the range 0 to 1.0: - * - * 1: A single gray or luminance channel (G). - * 2: A gray/luminance channel and an alpha channel (GA). - * 3: Three red, green, blue color channels (RGB). - * 4: Three color channels and an alpha channel (RGBA). - * - * The components are encoded in one of two ways: - * - * a) As a small integer, value 0..255, contained in a single byte. For the - * alpha channel the original value is simply value/255. For the color or - * luminance channels the value is encoded according to the sRGB specification - * and matches the 8-bit format expected by typical display devices. - * - * The color/gray channels are not scaled (pre-multiplied) by the alpha - * channel and are suitable for passing to color management software. - * - * b) As a value in the range 0..65535, contained in a 2-byte integer. All - * channels can be converted to the original value by dividing by 65535; all - * channels are linear. Color channels use the RGB encoding (RGB end-points) of - * the sRGB specification. This encoding is identified by the - * PNG_FORMAT_FLAG_LINEAR flag below. - * - * When the simplified API needs to convert between sRGB and linear colorspaces, - * the actual sRGB transfer curve defined in the sRGB specification (see the - * article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 - * approximation used elsewhere in libpng. - * - * When an alpha channel is present it is expected to denote pixel coverage - * of the color or luminance channels and is returned as an associated alpha - * channel: the color/gray channels are scaled (pre-multiplied) by the alpha - * value. - * - * The samples are either contained directly in the image data, between 1 and 8 - * bytes per pixel according to the encoding, or are held in a color-map indexed - * by bytes in the image data. In the case of a color-map the color-map entries - * are individual samples, encoded as above, and the image data has one byte per - * pixel to select the relevant sample from the color-map. - */ - -/* PNG_FORMAT_* - * - * #defines to be used in png_image::format. Each #define identifies a - * particular layout of sample data and, if present, alpha values. There are - * separate defines for each of the two component encodings. - * - * A format is built up using single bit flag values. All combinations are - * valid. Formats can be built up from the flag values or you can use one of - * the predefined values below. When testing formats always use the FORMAT_FLAG - * macros to test for individual features - future versions of the library may - * add new flags. - * - * When reading or writing color-mapped images the format should be set to the - * format of the entries in the color-map then png_image_{read,write}_colormap - * called to read or write the color-map and set the format correctly for the - * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! - * - * NOTE: libpng can be built with particular features disabled, if you see - * compiler errors because the definition of one of the following flags has been - * compiled out it is because libpng does not have the required support. It is - * possible, however, for the libpng configuration to enable the format on just - * read or just write; in that case you may see an error at run time. You can - * guard against this by checking for the definition of the appropriate - * "_SUPPORTED" macro, one of: - * - * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED - */ -#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ -#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ -#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2 byte channels else 1 byte */ -#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ - -#ifdef PNG_FORMAT_BGR_SUPPORTED -# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ -#endif - -#ifdef PNG_FORMAT_AFIRST_SUPPORTED -# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ -#endif - -/* Commonly used formats have predefined macros. - * - * First the single byte (sRGB) formats: - */ -#define PNG_FORMAT_GRAY 0 -#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA -#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) -#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR -#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) -#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) -#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) -#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) -#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) - -/* Then the linear 2-byte formats. When naming these "Y" is used to - * indicate a luminance (gray) channel. - */ -#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR -#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) -#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) -#define PNG_FORMAT_LINEAR_RGB_ALPHA \ - (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) - -/* With color-mapped formats the image data is one byte for each pixel, the byte - * is an index into the color-map which is formatted as above. To obtain a - * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP - * to one of the above definitions, or you can use one of the definitions below. - */ -#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) -#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) -#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) -#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) -#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) -#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) - -/* PNG_IMAGE macros - * - * These are convenience macros to derive information from a png_image - * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the - * actual image sample values - either the entries in the color-map or the - * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values - * for the pixels and will always return 1 for color-mapped formats. The - * remaining macros return information about the rows in the image and the - * complete image. - * - * NOTE: All the macros that take a png_image::format parameter are compile time - * constants if the format parameter is, itself, a constant. Therefore these - * macros can be used in array declarations and case labels where required. - * Similarly the macros are also pre-processor constants (sizeof is not used) so - * they can be used in #if tests. - * - * First the information about the samples. - */ -#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ - (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) - /* Return the total number of channels in a given format: 1..4 */ - -#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ - ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) - /* Return the size in bytes of a single component of a pixel or color-map - * entry (as appropriate) in the image: 1 or 2. - */ - -#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ - (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) - /* This is the size of the sample data for one sample. If the image is - * color-mapped it is the size of one color-map entry (and image pixels are - * one byte in size), otherwise it is the size of one image pixel. - */ - -#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ - (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) - /* The maximum size of the color-map required by the format expressed in a - * count of components. This can be used to compile-time allocate a - * color-map: - * - * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; - * - * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; - * - * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the - * information from one of the png_image_begin_read_ APIs and dynamically - * allocate the required memory. - */ - -/* Corresponding information about the pixels */ -#define PNG_IMAGE_PIXEL_(test,fmt)\ - (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) - -#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ - PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) - /* The number of separate channels (components) in a pixel; 1 for a - * color-mapped image. - */ - -#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ - PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) - /* The size, in bytes, of each component in a pixel; 1 for a color-mapped - * image. - */ - -#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) - /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ - -/* Information about the whole row, or whole image */ -#define PNG_IMAGE_ROW_STRIDE(image)\ - (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) - /* Return the total number of components in a single row of the image; this - * is the minimum 'row stride', the minimum count of components between each - * row. For a color-mapped image this is the minimum number of bytes in a - * row. - */ - -#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ - (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) - /* Return the size, in bytes, of an image buffer given a png_image and a row - * stride - the number of components to leave space for in each row. - */ - -#define PNG_IMAGE_SIZE(image)\ - PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) - /* Return the size, in bytes, of the image in memory given just a png_image; - * the row stride is the minimum stride required for the image. - */ - -#define PNG_IMAGE_COLORMAP_SIZE(image)\ - (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) - /* Return the size, in bytes, of the color-map of this image. If the image - * format is not a color-map format this will return a size sufficient for - * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if - * you don't want to allocate a color-map in this case. - */ - -/* PNG_IMAGE_FLAG_* - * - * Flags containing additional information about the image are held in the - * 'flags' field of png_image. - */ -#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 - /* This indicates the the RGB values of the in-memory bitmap do not - * correspond to the red, green and blue end-points defined by sRGB. - */ - -#define PNG_IMAGE_FLAG_FAST 0x02 - /* On write emphasise speed over compression; the resultant PNG file will be - * larger but will be produced significantly faster, particular for large - * images. Do not use this option for images which will be distributed, only - * used it when producing intermediate files that will be read back in - * repeatedly. For a typical 24-bit image the option will double the read - * speed at the cost of increasing the image size by 25%, however for many - * more compressible images the PNG file can be 10 times larger with only a - * slight speed gain. - */ - -#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 - /* On read if the image is a 16-bit per component image and there is no gAMA - * or sRGB chunk assume that the components are sRGB encoded. Notice that - * images output by the simplified API always have gamma information; setting - * this flag only affects the interpretation of 16-bit images from an - * external source. It is recommended that the application expose this flag - * to the user; the user can normally easily recognize the difference between - * linear and sRGB encoding. This flag has no effect on write - the data - * passed to the write APIs must have the correct encoding (as defined - * above.) - * - * If the flag is not set (the default) input 16-bit per component data is - * assumed to be linear. - * - * NOTE: the flag can only be set after the png_image_begin_read_ call, - * because that call initializes the 'flags' field. - */ - -#ifdef PNG_SIMPLIFIED_READ_SUPPORTED -/* READ APIs - * --------- - * - * The png_image passed to the read APIs must have been initialized by setting - * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) - */ -#ifdef PNG_STDIO_SUPPORTED -PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, - const char *file_name)); - /* The named file is opened for read and the image header is filled in - * from the PNG header in the file. - */ - -PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, - FILE* file)); - /* The PNG header is read from the stdio FILE object. */ -#endif /* PNG_STDIO_SUPPORTED */ - -PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, - png_const_voidp memory, png_size_t size)); - /* The PNG header is read from the given memory buffer. */ - -PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, - png_const_colorp background, void *buffer, png_int_32 row_stride, - void *colormap)); - /* Finish reading the image into the supplied buffer and clean up the - * png_image structure. - * - * row_stride is the step, in byte or 2-byte units as appropriate, - * between adjacent rows. A positive stride indicates that the top-most row - * is first in the buffer - the normal top-down arrangement. A negative - * stride indicates that the bottom-most row is first in the buffer. - * - * background need only be supplied if an alpha channel must be removed from - * a png_byte format and the removal is to be done by compositing on a solid - * color; otherwise it may be NULL and any composition will be done directly - * onto the buffer. The value is an sRGB color to use for the background, - * for grayscale output the green channel is used. - * - * background must be supplied when an alpha channel must be removed from a - * single byte color-mapped output format, in other words if: - * - * 1) The original format from png_image_begin_read_from_* had - * PNG_FORMAT_FLAG_ALPHA set. - * 2) The format set by the application does not. - * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and - * PNG_FORMAT_FLAG_LINEAR *not* set. - * - * For linear output removing the alpha channel is always done by compositing - * on black and background is ignored. - * - * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must - * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. - * image->colormap_entries will be updated to the actual number of entries - * written to the colormap; this may be less than the original value. - */ - -PNG_EXPORT(238, void, png_image_free, (png_imagep image)); - /* Free any data allocated by libpng in image->opaque, setting the pointer to - * NULL. May be called at any time after the structure is initialized. - */ -#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ - -#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED -#ifdef PNG_STDIO_SUPPORTED -/* WRITE APIS - * ---------- - * For write you must initialize a png_image structure to describe the image to - * be written. To do this use memset to set the whole structure to 0 then - * initialize fields describing your image. - * - * version: must be set to PNG_IMAGE_VERSION - * opaque: must be initialized to NULL - * width: image width in pixels - * height: image height in rows - * format: the format of the data (image and color-map) you wish to write - * flags: set to 0 unless one of the defined flags applies; set - * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB - * values do not correspond to the colors in sRGB. - * colormap_entries: set to the number of entries in the color-map (0 to 256) - */ -PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, - const char *file, int convert_to_8bit, const void *buffer, - png_int_32 row_stride, const void *colormap)); - /* Write the image to the named file. */ - -PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, - int convert_to_8_bit, const void *buffer, png_int_32 row_stride, - const void *colormap)); - /* Write the image to the given (FILE*). */ - -/* With both write APIs if image is in one of the linear formats with 16-bit - * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG - * gamma encoded according to the sRGB specification, otherwise a 16-bit linear - * encoded PNG file is written. - * - * With color-mapped data formats the colormap parameter point to a color-map - * with at least image->colormap_entries encoded in the specified format. If - * the format is linear the written PNG color-map will be converted to sRGB - * regardless of the convert_to_8_bit flag. - * - * With all APIs row_stride is handled as in the read APIs - it is the spacing - * from one row to the next in component sized units (1 or 2 bytes) and if - * negative indicates a bottom-up row layout in the buffer. - * - * Note that the write API does not support interlacing or sub-8-bit pixels. - */ -#endif /* PNG_STDIO_SUPPORTED */ -#endif /* PNG_SIMPLIFIED_WRITE_SUPPORTED */ -/******************************************************************************* - * END OF SIMPLIFIED API - ******************************************************************************/ - -#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED -PNG_EXPORT(242, void, png_set_check_for_invalid_index, - (png_structrp png_ptr, int allowed)); -# ifdef PNG_GET_PALETTE_MAX_SUPPORTED -PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, - png_const_infop info_ptr)); -# endif -#endif /* CHECK_FOR_INVALID_INDEX */ - -/******************************************************************************* - * IMPLEMENTATION OPTIONS - ******************************************************************************* - * - * Support for arbitrary implementation-specific optimizations. The API allows - * particular options to be turned on or off. 'Option' is the number of the - * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given - * by the PNG_OPTION_ defines below. - * - * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions, - * are detected at run time, however sometimes it may be impossible - * to do this in user mode, in which case it is necessary to discover - * the capabilities in an OS specific way. Such capabilities are - * listed here when libpng has support for them and must be turned - * ON by the application if present. - * - * SOFTWARE: sometimes software optimizations actually result in performance - * decrease on some architectures or systems, or with some sets of - * PNG images. 'Software' options allow such optimizations to be - * selected at run time. - */ -#ifdef PNG_SET_OPTION_SUPPORTED -#ifdef PNG_ARM_NEON_API_SUPPORTED -# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ -#endif -#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ -#define PNG_OPTION_NEXT 4 /* Next option - numbers must be even */ - -/* Return values: NOTE: there are four values and 'off' is *not* zero */ -#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ -#define PNG_OPTION_INVALID 1 /* Option number out of range */ -#define PNG_OPTION_OFF 2 -#define PNG_OPTION_ON 3 - -PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, - int onoff)); -#endif - -/******************************************************************************* - * END OF HARDWARE OPTIONS - ******************************************************************************/ - -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project - * defs, scripts/pnglibconf.h, and scripts/pnglibconf.h.prebuilt - */ - -/* The last ordinal number (this is the *last* one already used; the next - * one to use is one more than this.) Maintainer, remember to add an entry to - * scripts/symbols.def as well. - */ -#ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(244); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -/* Do not put anything past this line */ -#endif /* PNG_H */ + +/* png.h - header file for PNG reference library + * + * libpng version 1.7.0beta35 - March 17, 2014 + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license (See LICENSE, below) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.7.0beta35 - March 17, 2014: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 12.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 12.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-7 13 10210 12.so.0.10[.0] + * 1.2.10rc1-2 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.4.0beta1-5 14 10400 14.so.0.0[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.4.0beta7-8 14 10400 14.so.0.0[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.4.0beta9-14 14 10400 14.so.0.0[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.4.0beta15-36 14 10400 14.so.0.0[.0] + * 1.4.0beta37-87 14 10400 14.so.14.0[.0] + * 1.4.0rc01 14 10400 14.so.14.0[.0] + * 1.4.0beta88-109 14 10400 14.so.14.0[.0] + * 1.4.0rc02-08 14 10400 14.so.14.0[.0] + * 1.4.0 14 10400 14.so.14.0[.0] + * 1.4.1beta01-03 14 10401 14.so.14.1[.0] + * 1.4.1rc01 14 10401 14.so.14.1[.0] + * 1.4.1beta04-12 14 10401 14.so.14.1[.0] + * 1.4.1 14 10401 14.so.14.1[.0] + * 1.4.2 14 10402 14.so.14.2[.0] + * 1.4.3 14 10403 14.so.14.3[.0] + * 1.4.4 14 10404 14.so.14.4[.0] + * 1.5.0beta01-58 15 10500 15.so.15.0[.0] + * 1.5.0rc01-07 15 10500 15.so.15.0[.0] + * 1.5.0 15 10500 15.so.15.0[.0] + * 1.5.1beta01-11 15 10501 15.so.15.1[.0] + * 1.5.1rc01-02 15 10501 15.so.15.1[.0] + * 1.5.1 15 10501 15.so.15.1[.0] + * 1.5.2beta01-03 15 10502 15.so.15.2[.0] + * 1.5.2rc01-03 15 10502 15.so.15.2[.0] + * 1.5.2 15 10502 15.so.15.2[.0] + * 1.5.3beta01-10 15 10503 15.so.15.3[.0] + * 1.5.3rc01-02 15 10503 15.so.15.3[.0] + * 1.5.3beta11 15 10503 15.so.15.3[.0] + * 1.5.3 [omitted] + * 1.5.4beta01-08 15 10504 15.so.15.4[.0] + * 1.5.4rc01 15 10504 15.so.15.4[.0] + * 1.5.4 15 10504 15.so.15.4[.0] + * 1.5.5beta01-08 15 10505 15.so.15.5[.0] + * 1.5.5rc01 15 10505 15.so.15.5[.0] + * 1.5.5 15 10505 15.so.15.5[.0] + * 1.5.6beta01-07 15 10506 15.so.15.6[.0] + * 1.5.6rc01-03 15 10506 15.so.15.6[.0] + * 1.5.6 15 10506 15.so.15.6[.0] + * 1.5.7beta01-05 15 10507 15.so.15.7[.0] + * 1.5.7rc01-03 15 10507 15.so.15.7[.0] + * 1.5.7 15 10507 15.so.15.7[.0] + * 1.6.0beta01-37 16 10600 16.so.16.0[.0] + * 1.7.0alpha01-10 17 10700 17.so.17.0[.0] + * 1.7.0beta01-35 17 10700 17.so.17.0[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcNN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng-manual.txt or libpng.3 for more information. The PNG + * specification is available as a W3C Recommendation and as an ISO + * Specification, ; i.e. + * the prefix is lower case. Please use decimal values as the parameters to + * match the ISO PNG specification and to avoid relying on the C locale + * interpretation of character values. Please keep the list sorted. + * + * Notice that PNG_U32 is used to define a 32-bit value for the 4 byte chunk + * type. In fact the specification does not express chunk types this way, + * however using a 32-bit value means that the chunk type can be read from the + * stream using exactly the same code as used for a 32-bit unsigned value and + * can be examined far more efficiently (using one arithmetic compare). + * + * Prior to 1.5.6 the chunk type constants were expressed as C strings. The + * libpng API still uses strings for 'unknown' chunks and a macro, + * PNG_STRING_FROM_CHUNK, allows a string to be generated if required. Notice + * that for portable code numeric values must still be used; the string "IHDR" + * is not portable and neither is PNG_U32('I', 'H', 'D', 'R'). + * + * In 1.7.0 the definitions were made public in png.h to avoid having to + * duplicate the same definitions in application code. + * + * SOURCE: http://www.libpng.org/pub/png/spec/register/ + * "Register of PNG Public Chunks and Keywords, version 1.4.6" + * "Extensions to the PNG Specification, version 1.4.0" + */ +#define png_IDAT PNG_U32( 73, 68, 65, 84) +#define png_IEND PNG_U32( 73, 69, 78, 68) +#define png_IHDR PNG_U32( 73, 72, 68, 82) +#define png_PLTE PNG_U32( 80, 76, 84, 69) +#define png_bKGD PNG_U32( 98, 75, 71, 68) +#define png_cHRM PNG_U32( 99, 72, 82, 77) +#define png_dSIG PNG_U32(100, 83, 73, 71) /* separate spec */ +#define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */ +#define png_gAMA PNG_U32(103, 65, 77, 65) +#define png_gIFg PNG_U32(103, 73, 70, 103) +#define png_gIFt PNG_U32(103, 73, 70, 116) /* deprecated */ +#define png_gIFx PNG_U32(103, 73, 70, 120) +#define png_hIST PNG_U32(104, 73, 83, 84) +#define png_iCCP PNG_U32(105, 67, 67, 80) +#define png_iTXt PNG_U32(105, 84, 88, 116) +#define png_oFFs PNG_U32(111, 70, 70, 115) +#define png_pCAL PNG_U32(112, 67, 65, 76) +#define png_pHYs PNG_U32(112, 72, 89, 115) +#define png_sBIT PNG_U32(115, 66, 73, 84) +#define png_sCAL PNG_U32(115, 67, 65, 76) +#define png_sPLT PNG_U32(115, 80, 76, 84) +#define png_sRGB PNG_U32(115, 82, 71, 66) +#define png_sTER PNG_U32(115, 84, 69, 82) +#define png_tEXt PNG_U32(116, 69, 88, 116) +#define png_tIME PNG_U32(116, 73, 77, 69) +#define png_tRNS PNG_U32(116, 82, 78, 83) +#define png_zTXt PNG_U32(122, 84, 88, 116) + +/* The following will work on (signed char*) strings, whereas the PNG_U32 macro + * used directory would fail on top-bit-set values because of the sign + * extension. + */ +#define PNG_CHUNK_FROM_STRING(s)\ + PNG_U32(0xff&(s)[0], 0xff&(s)[1], 0xff&(s)[2], 0xff&(s)[3]) + +/* This uses (char), not (png_byte) to avoid warnings on systems where (char) is + * signed and the argument is a (char[]) This macro will fail miserably on + * systems where (char) is more than 8 bits. + */ +#define PNG_STRING_FROM_CHUNK(s,c)\ + (void)(((char*)(s))[0]=(char)((c)>>24), ((char*)(s))[1]=(char)((c)>>16),\ + ((char*)(s))[2]=(char)((c)>>8), ((char*)(s))[3]=(char)((c))) + +/* Do the same but terminate with a null character. */ +#define PNG_CSTRING_FROM_CHUNK(s,c)\ + (void)(PNG_STRING_FROM_CHUNK(s,c), ((char*)(s))[4] = 0) + +/* Test on flag values as defined in the spec (section 5.4): */ +#define PNG_CHUNK_ANCILLARY(c) (1 & ((c) >> 29)) +#define PNG_CHUNK_CRITICAL(c) (!PNG_CHUNK_ANCILLARY(c)) +#define PNG_CHUNK_PRIVATE(c) (1 & ((c) >> 21)) +#define PNG_CHUNK_RESERVED(c) (1 & ((c) >> 13)) +#define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >> 5)) + +/* Section 2: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Section 3: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_7_0beta35; + +/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. + * + * png_struct is the cache of information used while reading or writing a single + * PNG file. One of these is always required, although the simplified API + * (below) hides the creation and destruction of it. + */ +typedef struct png_struct_def png_struct; +typedef const png_struct * png_const_structp; +typedef png_struct * png_structp; +typedef png_struct * * png_structpp; + +/* png_info contains information read from or to be written to a PNG file. One + * or more of these must exist while reading or creating a PNG file. The + * information is not used by libpng during read but is used to control what + * gets written when a PNG file is created. "png_get_" function calls read + * information during read and "png_set_" functions calls write information + * when creating a PNG. + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info * png_infop; +typedef const png_info * png_const_infop; +typedef png_info * * png_infopp; + +/* Types with names ending 'p' are pointer types. The corresponding types with + * names ending 'rp' are identical pointer types except that the pointer is + * marked 'restrict', which means that it is the only pointer to the object + * passed to the function. Applications should not use the 'restrict' types; + * it is always valid to pass 'p' to a pointer with a function argument of the + * corresponding 'rp' type. Different compilers have different rules with + * regard to type matching in the presence of 'restrict'. For backward + * compatibility libpng callbacks never have 'restrict' in their parameters and, + * consequentially, writing portable application code is extremely difficult if + * an attempt is made to use 'restrict'. + */ +typedef png_struct * PNG_RESTRICT png_structrp; +typedef const png_struct * PNG_RESTRICT png_const_structrp; +typedef png_info * PNG_RESTRICT png_inforp; +typedef const png_info * PNG_RESTRICT png_const_inforp; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color * png_colorp; +typedef const png_color * png_const_colorp; +typedef png_color * * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 * png_color_16p; +typedef const png_color_16 * png_const_color_16p; +typedef png_color_16 * * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 * png_color_8p; +typedef const png_color_8 * png_const_color_8p; +typedef png_color_8 * * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry * png_sPLT_entryp; +typedef const png_sPLT_entry * png_const_sPLT_entryp; +typedef png_sPLT_entry * * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t * png_sPLT_tp; +typedef const png_sPLT_t * png_const_sPLT_tp; +typedef png_sPLT_t * * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text * png_textp; +typedef const png_text * png_const_textp; +typedef png_text * * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time * png_timep; +typedef const png_time * png_const_timep; +typedef png_time * * png_timepp; + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_USER_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + * + * The data in the structure is set by libpng on read and used on write. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; /* Textual chunk name with '\0' terminator */ + png_byte *data; /* Data, should not be modified on read! */ + size_t size; + + /* On write 'location' must be set using the flag values listed below. + * Notice that on read it is set by libpng however the values stored have + * more bits set than are listed below. Always treat the value as a + * bitmask. On write set only one bit - setting multiple bits may cause the + * chunk to be written in multiple places. + */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; + +typedef png_unknown_chunk * png_unknown_chunkp; +typedef const png_unknown_chunk * png_const_unknown_chunkp; +typedef png_unknown_chunk * * png_unknown_chunkpp; +#endif + +/* Flag values for the unknown chunk location byte. */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info * png_row_infop; +typedef png_row_info * * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +/* not used anywhere */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +/* Section 4: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, + (png_const_structrp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, + size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream -- Removed from libpng-1.7.0 */ +PNG_REMOVED(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED) +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, + png_const_bytep data, size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), + PNG_ALLOCATED); + +/* Removed from libpng-1.7.0 */ +PNG_REMOVED(19, void, png_info_init_3, (png_infopp info_ptr, + size_t png_info_struct_size), PNG_DEPRECATED) + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structrp png_ptr, png_const_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* Convert to a US string format: there is no localization support in this + * routine. The original implementation used a 29 character buffer in + * png_struct, this has been removed (in libpng 1.7.0). + */ +PNG_REMOVED(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED) +PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + const struct tm * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +#endif /* PNG_CONVERT_tIME_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, + int error_action, double red, double green)) +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)) + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels + * of a PNG file are returned to the calling application when an alpha channel, + * or a tRNS chunk in a palette file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel, and the color channels are unassociated + * (not premultiplied). The gamma encoded color channels must be scaled + * according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and reencode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. + * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes + * (the latter being the two common names for associated alpha color channels). + * + * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha + * value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, + double output_gamma)) +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, + int mode, png_fixed_point output_gamma)) +#endif + +#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceeded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the ouput gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, + png_uint_32 filler, int flags)); +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)) +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)) +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_const_uint_16p histogram, int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, + double screen_gamma, double override_file_gamma)) +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, + png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, + png_inforp info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, + int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, + int filters)); + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines match the values in the PNG specification. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +/* The above values are valid arguments to png_set_filter() if only a single + * filter is to be used. If multiple filters are to be allowed (the default is + * to allow any of them) then a combination of the following masks must be used + * and the low three bits of the argument to png_set_filter must be 0. + * + * The resultant argument fits in a single byte. + */ +#define PNG_FILTER_NONE (0x08 << PNG_FILTER_VALUE_NONE) +#define PNG_FILTER_SUB (0x08 << PNG_FILTER_VALUE_SUB) +#define PNG_FILTER_UP (0x08 << PNG_FILTER_VALUE_UP) +#define PNG_FILTER_AVG (0x08 << PNG_FILTER_VALUE_AVG) +#define PNG_FILTER_PAETH (0x08 << PNG_FILTER_VALUE_PAETH) + +/* Then two convenience values. PNG_NO_FILTERS is the same as + * PNG_FILTER_VALUE_NONE, but this is harmless because they mean the same thing. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)) +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structrp png_ptr, int heuristic_method, int num_weights, + png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs)) +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +#ifdef PNG_WRITE_SUPPORTED +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, + int method)); +#endif + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, + int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, + (png_structrp png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, + int method)); +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* This callback is called only for *unknown* chunks. If + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known + * chunks to be treated as unknown, however in this case the callback must do + * any processing required by the chunk (e.g. by calling the appropriate + * png_set_ APIs.) + * + * There is no write support - on write, by default, all the chunks in the + * 'unknown' list are written in the specified position. + * + * The integer return from the callback function is interpreted thus: + * + * negative: An error occured, png_chunk_error will be called. + * zero: The chunk was not handled, the default unknown handling is used + * (even if this was a chunk that would otherwise be known.) + * NOTE: prior to libpng 1.7 handling values of + * PNG_HANDLE_CHUNK_AS_DEFAULT and PNG_HANDLE_CHUNK_NEVER were + * converted to PNG_HANDLE_CHUNK_IF_SAFE (libpng 1.6.0 warns if this + * happens) so it was not possible to discard unknown chunk data if a + * user callback was installed. + * positive: The chunk was handled, libpng will ignore/discard it. + */ +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, + (png_const_structrp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application; this works on the png_info structure passed + * in, it does not change the state for other png_info structures. + * + * It is unlikely that this function works correctly as of 1.6.0 and using it + * may result either in memory leaks or double free of allocated data. It was + * removed in libpng 1.7.0. + */ +PNG_REMOVED(99, void, png_data_freer, (png_const_structrp png_ptr, + png_inforp info_ptr, int freer, png_uint_32 mask), PNG_DEPRECATED) + +/* Flags for png_free_data */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_FREE_UNKN 0x0200 +#endif +/* PNG_FREE_LIST 0x0400 removed in 1.6.0 because it is ignored */ +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED + /* These were deprecated in libpng 1.6.0 and have been removed from libpng + * 1.7.0; the functionality should be accessed by calling malloc or free + * directly or, if png_error handling is required, calling png_malloc. + */ +PNG_REMOVED(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED) +PNG_REMOVED(101, void, png_free_default, (png_const_structrp png_ptr, + png_voidp ptr), PNG_DEPRECATED) +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_READ_SUPPORTED +/* Same, chunk name is prepended to message (only during read) */ +PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structrp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +#ifdef PNG_READ_SUPPORTED +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)) +PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)) +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)) +PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, + png_inforp info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, + png_const_inforp info_ptr, double *file_gamma)) +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_file_gamma)) +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, + png_inforp info_ptr, double file_gamma)) +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, png_fixed_point int_file_gamma)) +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, + png_int_32 *X1, int *type, int *nparams, png_charp *units, + png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, + png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, + png_inforp info_ptr, png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, + png_inforp info_ptr, png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, + png_inforp info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, + png_inforp info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, (png_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, + png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, (png_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, + png_inforp info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, + png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, + png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* NOTE: these API are currently implemented using floating point arithmetic, + * consequently they can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, + png_const_inforp info_ptr, int *unit, double *width, double *height)) +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, + png_charpp swidth, png_charpp sheight)); + +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* This also requires internal floating point arithmetic support - i.e. it + * requires a full math library, not just floating point handling. + */ +PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, double width, double height)) +#endif +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, png_fixed_point width, + png_fixed_point height)) +PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, + png_inforp info_ptr, int unit, + png_const_charp swidth, png_const_charp sheight)); +#endif /* PNG_sCAL_SUPPORTED */ + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +/* Provide the default handling for all unknown chunks or, optionally, for + * specific unknown chunks. + * + * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was + * ignored and the default was used, the per-chunk setting only had an effect on + * write. If you wish to have chunk-specific handling on read in code that must + * work on earlier versions you must use a user chunk callback to implement the + * desired handling (keep or discard.) + * + * NOTE: prior to 1.7.0 when a user callback returned '0', indicating that the + * chunk had not been handled, libpng would preserve it regardless of the + * default or per-chunk settings. For compatibility with earlier versions + * simply return '1' (handled) from the callback to discard the chunk. + * + * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The + * parameter is interpreted as follows: + * + * READ: + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Known chunks: do normal libpng processing, do not keep the chunk (but + * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + * Unknown chunks: for a specific chunk use the global default, when used + * as the default discard the chunk data. + * PNG_HANDLE_CHUNK_NEVER: + * Discard the chunk data. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Keep the chunk data if the chunk is not critical else raise a chunk + * error. + * PNG_HANDLE_CHUNK_ALWAYS: + * Keep the chunk data. + * + * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, + * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent + * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks + * it simply resets the behavior to the libpng default. + * + * The per-chunk handling is always used when there is a png_user_chunk_ptr + * callback and the callback returns 0; the chunk is then always stored *unless* + * it is critical and the per-chunk setting is other than ALWAYS. Notice that + * the global default is *not* used in this case. (In effect the per-chunk + * value is incremented to at least IF_SAFE.) + * + * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: + * If this is *not* set known chunks will always be handled by libpng and + * will never be stored in the unknown chunk list. Known chunks listed to + * png_set_keep_unknown_chunks will have no effect. If it is set then known + * chunks listed with a keep other than AS_DEFAULT will *never* be processed + * by libpng, in addition critical chunks must either be processed by the + * callback or saved. + * + * The IHDR and IEND chunks must not be listed. Because this turns off the + * default handling for chunks that would otherwise be recognized the + * behavior of libpng transformations may well become incorrect! + * + * WRITE: + * When writing chunks the options only apply to the chunks specified by + * png_set_unknown_chunks (below), libpng will *always* write known chunks + * required by png_set_ calls and will always write the core critical chunks + * (as required for PLTE). + * + * Each chunk in the png_set_unknown_chunks list is looked up in the + * png_set_keep_unknown_chunks list to find the keep setting, this is then + * interpreted as follows: + * + * PNG_HANDLE_CHUNK_AS_DEFAULT: + * Write safe-to-copy chunks and write other chunks if the global + * default is set to _ALWAYS, otherwise don't write this chunk. + * PNG_HANDLE_CHUNK_NEVER: + * Do not write the chunk. + * PNG_HANDLE_CHUNK_IF_SAFE: + * Write the chunk if it is safe-to-copy, otherwise do not write it. + * PNG_HANDLE_CHUNK_ALWAYS: + * Write the chunk. + * + * Note that the default behavior is effectively the opposite of the read case - + * in read unknown chunks are not stored by default, in write they are written + * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different + * - on write the safe-to-copy bit is checked, on read the critical bit is + * checked and on read if the chunk is critical an error will be raised. + * + * num_chunks: + * =========== + * If num_chunks is positive, then the "keep" parameter specifies the manner + * for handling only those chunks appearing in the chunk_list array, + * otherwise the chunk list array is ignored. + * + * If num_chunks is 0 the "keep" parameter specifies the default behavior for + * unknown chunks, as described above. + * + * If num_chunks is negative, then the "keep" parameter specifies the manner + * for handling all unknown chunks plus all chunks recognized by libpng + * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to + * be processed by libpng. + */ +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, + int keep, png_const_bytep chunk_list, int num_chunks)); + +/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; + * the result is therefore true (non-zero) if special handling is required, + * false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, + png_const_bytep chunk_name)); +#endif + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); + /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added + * unknowns to the location currently stored in the png_struct. This is + * invariably the wrong value on write. To fix this call the following API + * for each chunk in the list with the correct location. If you know your + * code won't be compiled on earlier versions you can rely on + * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing + * the correct thing. + */ + +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); + +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, + png_inforp info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, + png_inforp info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#ifdef PNG_WRITE_SUPPORTED +PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, + int transforms, png_voidp params)); +#endif +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structrp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structrp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structrp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structrp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_LAST 4 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structrp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structrp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structrp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structrp png_ptr, png_const_inforp info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, + png_const_inforp info_ptr)) +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_const_structrp png_ptr, png_const_inforp info_ptr)) +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, + png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); + +/* Removed from libpng 1.6; use png_get_io_chunk_type. */ +PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), + PNG_DEPRECATED) + +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structrp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ + (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + 128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + 127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535) +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + */ +# define PNG_B(ptr, offset) (((png_const_bytep)(ptr))[offset]) +# define PNG_get_uint_32(buf) \ + PNG_U32(PNG_B(buf,0), PNG_B(buf,1), PNG_B(buf,2), PNG_B(buf,3)) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define PNG_get_uint_16(buf) PNG_U16(PNG_B(buf,0), PNG_B(buf,1)) + +# define PNG_get_int_32(buf) \ + PNG_S32(PNG_B(buf,0), PNG_B(buf,1), PNG_B(buf,2), PNG_B(buf,3)) + + /* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, + * but defining a macro name prefixed with PNG_PREFIX. + */ +# ifndef PNG_PREFIX +# define png_get_uint_32(buf) PNG_get_uint_32(buf) +# define png_get_uint_16(buf) PNG_get_uint_16(buf) +# define png_get_int_32(buf) PNG_get_int_32(buf) +# endif +#else +# ifdef PNG_PREFIX + /* No macros; revert to the (redefined) function */ +# define PNG_get_uint_32 (png_get_uint_32) +# define PNG_get_uint_16 (png_get_uint_16) +# define PNG_get_int_32 (png_get_int_32) +# endif +#endif + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structrp png_ptr, + png_const_inforp info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + +/******************************************************************************* + * IMPLEMENTATION OPTIONS + ******************************************************************************* + * + * Support for arbitrary implementation-specific optimizations. The API allows + * particular options to be turned on or off. 'Option' is the number of the + * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given + * by the PNG_OPTION_ defines below. + * + * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions, + * are detected at run time, however sometimes it may be impossible + * to do this in user mode, in which case it is necessary to discover + * the capabilities in an OS specific way. Such capabilities are + * listed here when libpng has support for them and must be turned + * ON by the application if present. + * + * SOFTWARE: sometimes software optimizations actually result in performance + * decrease on some architectures or systems, or with some sets of + * PNG images. 'Software' options allow such optimizations to be + * selected at run time. + */ +#ifdef PNG_SET_OPTION_SUPPORTED +#ifdef PNG_ARM_NEON_API_SUPPORTED +# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ +#endif +#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ +#define PNG_OPTION_NEXT 4 /* Next option - numbers must be even */ + +/* Return values: NOTE: there are four values and 'off' is *not* zero */ +#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ +#define PNG_OPTION_INVALID 1 /* Option number out of range */ +#define PNG_OPTION_OFF 2 +#define PNG_OPTION_ON 3 + +PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, + int onoff)); +#endif + +/******************************************************************************* + * END OF HARDWARE OPTIONS + ******************************************************************************/ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs + */ + +/******************************************************************************* + * Section 5: SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt (TODO: write said + * documentation) if you don't understand what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accomodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancillary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack and set the + * version field to PNG_IMAGE_VERSION. + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required sample format. + * 4) Allocate a buffer for the image and, if required, the color-map. + * 5) Call png_image_finish_read to read the image and, if required, the + * color-map into your buffers. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. The only caveat is that if you + * request a color-mapped image from a PNG that is full-color or makes + * complex use of an alpha channel the transformation is extremely lossy and the + * result may look terrible. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image samples. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image and, if necessary, the color-map to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or defines the in-memory format of an image that you + * need to write: + */ +#define PNG_IMAGE_VERSION 1 + +typedef struct png_control *png_controlp; +typedef struct +{ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_uint_32 colormap_entries; + /* Number of entries in the color-map */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * The upper 30 bits of this value are reserved, the low two bits contain + * a value as follows: + */ +# define PNG_IMAGE_WARNING 1 +# define PNG_IMAGE_ERROR 2 + /* + * The result is a two bit code such that a value more than 1 indicates + * a failure in the API just called: + * + * 0 - no warning or error + * 1 - warning + * 2 - error + * 3 - error preceded by warning + */ +# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) + + png_uint_32 warning_or_error; + + char message[64]; +} png_image, *png_imagep; + +/* The samples of the image have one to four channels whose components have + * original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The components are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a single byte. For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a 2-byte integer. All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When the simplified API needs to convert between sRGB and linear colorspaces, + * the actual sRGB transfer curve defined in the sRGB specification (see the + * article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 + * approximation used elsewhere in libpng. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + * + * The samples are either contained directly in the image data, between 1 and 8 + * bytes per pixel according to the encoding, or are held in a color-map indexed + * by bytes in the image data. In the case of a color-map the color-map entries + * are individual samples, encoded as above, and the image data has one byte per + * pixel to select the relevant sample from the color-map. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of sample data and, if present, alpha values. There are + * separate defines for each of the two component encodings. + * + * A format is built up using single bit flag values. All combinations are + * valid. Formats can be built up from the flag values or you can use one of + * the predefined values below. When testing formats always use the FORMAT_FLAG + * macros to test for individual features - future versions of the library may + * add new flags. + * + * When reading or writing color-mapped images the format should be set to the + * format of the entries in the color-map then png_image_{read,write}_colormap + * called to read or write the color-map and set the format correctly for the + * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! + * + * NOTE: libpng can be built with particular features disabled, if you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of the appropriate + * "_SUPPORTED" macro, one of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2 byte channels else 1 byte */ +#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ +#endif + +/* Commonly used formats have predefined macros. + * + * First the single byte (sRGB) formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear 2-byte formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* With color-mapped formats the image data is one byte for each pixel, the byte + * is an index into the color-map which is formatted as above. To obtain a + * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP + * to one of the above definitions, or you can use one of the definitions below. + */ +#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) +#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image + * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the + * actual image sample values - either the entries in the color-map or the + * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values + * for the pixels and will always return 1 for color-mapped formats. The + * remaining macros return information about the rows in the image and the + * complete image. + * + * NOTE: All the macros that take a png_image::format parameter are compile time + * constants if the format parameter is, itself, a constant. Therefore these + * macros can be used in array declarations and case labels where required. + * Similarly the macros are also pre-processor constants (sizeof is not used) so + * they can be used in #if tests. + * + * First the information about the samples. + */ +#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ + (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ + ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) + /* Return the size in bytes of a single component of a pixel or color-map + * entry (as appropriate) in the image: 1 or 2. + */ + +#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) + /* This is the size of the sample data for one sample. If the image is + * color-mapped it is the size of one color-map entry (and image pixels are + * one byte in size), otherwise it is the size of one image pixel. + */ + +#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ + (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) + /* The maximum size of the color-map required by the format expressed in a + * count of components. This can be used to compile-time allocate a + * color-map: + * + * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + * + * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + * + * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + * information from one of the png_image_begin_read_ APIs and dynamically + * allocate the required memory. + */ + +/* Corresponding information about the pixels */ +#define PNG_IMAGE_PIXEL_(test,fmt)\ + (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) + +#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) + /* The number of separate channels (components) in a pixel; 1 for a + * color-mapped image. + */ + +#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ + PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) + /* The size, in bytes, of each component in a pixel; 1 for a color-mapped + * image. + */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) + /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ + +/* Information about the whole row, or whole image */ +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. For a color-mapped image this is the minimum number of bytes in a + * row. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) + /* Return the size, in bytes, of an image buffer given a png_image and a row + * stride - the number of components to leave space for in each row. + */ + +#define PNG_IMAGE_SIZE(image)\ + PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) + /* Return the size, in bytes, of the image in memory given just a png_image; + * the row stride is the minimum stride required for the image. + */ + +#define PNG_IMAGE_COLORMAP_SIZE(image)\ + (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) + /* Return the size, in bytes, of the color-map of this image. If the image + * format is not a color-map format this will return a size sufficient for + * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + * you don't want to allocate a color-map in this case. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 + /* This indicates the the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#define PNG_IMAGE_FLAG_FAST 0x02 + /* On write emphasise speed over compression; the resultant PNG file will be + * larger but will be produced significantly faster, particular for large + * images. Do not use this option for images which will be distributed, only + * used it when producing intermediate files that will be read back in + * repeatedly. For a typical 24-bit image the option will double the read + * speed at the cost of increasing the image size by 25%, however for many + * more compressible images the PNG file can be 10 times larger with only a + * slight speed gain. + */ + +#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 + /* On read if the image is a 16-bit per component image and there is no gAMA + * or sRGB chunk assume that the components are sRGB encoded. Notice that + * images output by the simplified API always have gamma information; setting + * this flag only affects the interpretation of 16-bit images from an + * external source. It is recommended that the application expose this flag + * to the user; the user can normally easily recognize the difference between + * linear and sRGB encoding. This flag has no effect on write - the data + * passed to the write APIs must have the correct encoding (as defined + * above.) + * + * If the flag is not set (the default) input 16-bit per component data is + * assumed to be linear. + * + * NOTE: the flag can only be set after the png_image_begin_read_ call, + * because that call initializes the 'flags' field. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* PNG_STDIO_SUPPORTED */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_const_colorp background, void *buffer, png_int_32 row_stride, + void *colormap)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in byte or 2-byte units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * background must be supplied when an alpha channel must be removed from a + * single byte color-mapped output format, in other words if: + * + * 1) The original format from png_image_begin_read_from_* had + * PNG_FORMAT_FLAG_ALPHA set. + * 2) The format set by the application does not. + * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and + * PNG_FORMAT_FLAG_LINEAR *not* set. + * + * For linear output removing the alpha channel is always done by compositing + * on black and background is ignored. + * + * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must + * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. + * image->colormap_entries will be updated to the actual number of entries + * written to the colormap; this may be less than the original value. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +#ifdef PNG_STDIO_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written. To do this use memset to set the whole structure to 0 then + * initialize fields describing your image. + * + * version: must be set to PNG_IMAGE_VERSION + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data (image and color-map) you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + * colormap_entries: set to the number of entries in the color-map (0 to 256) + */ +PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride, + const void *colormap)); + /* Write the image to the given (FILE*). */ + +/* With both write APIs if image is in one of the linear formats with 16-bit + * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG + * gamma encoded according to the sRGB specification, otherwise a 16-bit linear + * encoded PNG file is written. + * + * With color-mapped data formats the colormap parameter point to a color-map + * with at least image->colormap_entries encoded in the specified format. If + * the format is linear the written PNG color-map will be converted to sRGB + * regardless of the convert_to_8_bit flag. + * + * With all APIs row_stride is handled as in the read APIs - it is the spacing + * from one row to the next in component sized units (1 or 2 bytes) and if + * negative indicates a bottom-up row layout in the buffer. + * + * Note that the write API does not support interlacing or sub-8-bit pixels. + */ +#endif /* PNG_STDIO_SUPPORTED */ +#endif /* PNG_SIMPLIFIED_WRITE_SUPPORTED */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) Maintainer, remember to add an entry to + * scripts/symbols.def as well. + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(244); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/ext/libpng16/pngconf.h b/ext/libpng17/pngconf.h similarity index 91% rename from ext/libpng16/pngconf.h rename to ext/libpng17/pngconf.h index e9a3f3b654..de3ce894f6 100644 --- a/ext/libpng16/pngconf.h +++ b/ext/libpng17/pngconf.h @@ -1,617 +1,652 @@ - -/* pngconf.h - machine configurable file for libpng - * - * libpng version 1.6.7 - November 14, 2013 - * - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - */ - -/* Any machine specific code is near the front of this file, so if you - * are configuring libpng for a machine, you may want to read the section - * starting here down to where it starts to typedef png_color, png_text, - * and png_info. - */ - -#ifndef PNGCONF_H -#define PNGCONF_H - -/* To do: Do all of this in scripts/pnglibconf.dfa */ -#ifdef PNG_SAFE_LIMITS_SUPPORTED -# ifdef PNG_USER_WIDTH_MAX -# undef PNG_USER_WIDTH_MAX -# define PNG_USER_WIDTH_MAX 1000000L -# endif -# ifdef PNG_USER_HEIGHT_MAX -# undef PNG_USER_HEIGHT_MAX -# define PNG_USER_HEIGHT_MAX 1000000L -# endif -# ifdef PNG_USER_CHUNK_MALLOC_MAX -# undef PNG_USER_CHUNK_MALLOC_MAX -# define PNG_USER_CHUNK_MALLOC_MAX 4000000L -# endif -# ifdef PNG_USER_CHUNK_CACHE_MAX -# undef PNG_USER_CHUNK_CACHE_MAX -# define PNG_USER_CHUNK_CACHE_MAX 128 -# endif -#endif - -#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ - -/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C - * compiler for correct compilation. The following header files are required by - * the standard. If your compiler doesn't provide these header files, or they - * do not match the standard, you will need to provide/improve them. - */ -#include -#include - -/* Library header files. These header files are all defined by ISOC90; libpng - * expects conformant implementations, however, an ISOC90 conformant system need - * not provide these header files if the functionality cannot be implemented. - * In this case it will be necessary to disable the relevant parts of libpng in - * the build of pnglibconf.h. - * - * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not - * include this unnecessary header file. - */ - -#ifdef PNG_STDIO_SUPPORTED - /* Required for the definition of FILE: */ -# include -#endif - -#ifdef PNG_SETJMP_SUPPORTED - /* Required for the definition of jmp_buf and the declaration of longjmp: */ -# include -#endif - -#ifdef PNG_CONVERT_tIME_SUPPORTED - /* Required for struct tm: */ -# include -#endif - -#endif /* PNG_BUILDING_SYMBOL_TABLE */ - -/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using - * PNG_NO_CONST; this is no longer supported except for data declarations which - * apparently still cause problems in 2011 on some compilers. - */ -#define PNG_CONST const /* backward compatibility only */ - -/* This controls optimization of the reading of 16 and 32 bit values - * from PNG files. It can be set on a per-app-file basis - it - * just changes whether a macro is used when the function is called. - * The library builder sets the default; if read functions are not - * built into the library the macro implementation is forced on. - */ -#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED -# define PNG_USE_READ_MACROS -#endif -#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) -# if PNG_DEFAULT_READ_MACROS -# define PNG_USE_READ_MACROS -# endif -#endif - -/* COMPILER SPECIFIC OPTIONS. - * - * These options are provided so that a variety of difficult compilers - * can be used. Some are fixed at build time (e.g. PNG_API_RULE - * below) but still have compiler specific implementations, others - * may be changed on a per-file basis when compiling against libpng. - */ - -/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect - * against legacy (pre ISOC90) compilers that did not understand function - * prototypes. It is not required for modern C compilers. - */ -#ifndef PNGARG -# define PNGARG(arglist) arglist -#endif - -/* Function calling conventions. - * ============================= - * Normally it is not necessary to specify to the compiler how to call - * a function - it just does it - however on x86 systems derived from - * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems - * and some others) there are multiple ways to call a function and the - * default can be changed on the compiler command line. For this reason - * libpng specifies the calling convention of every exported function and - * every function called via a user supplied function pointer. This is - * done in this file by defining the following macros: - * - * PNGAPI Calling convention for exported functions. - * PNGCBAPI Calling convention for user provided (callback) functions. - * PNGCAPI Calling convention used by the ANSI-C library (required - * for longjmp callbacks and sometimes used internally to - * specify the calling convention for zlib). - * - * These macros should never be overridden. If it is necessary to - * change calling convention in a private build this can be done - * by setting PNG_API_RULE (which defaults to 0) to one of the values - * below to select the correct 'API' variants. - * - * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. - * This is correct in every known environment. - * PNG_API_RULE=1 Use the operating system convention for PNGAPI and - * the 'C' calling convention (from PNGCAPI) for - * callbacks (PNGCBAPI). This is no longer required - * in any known environment - if it has to be used - * please post an explanation of the problem to the - * libpng mailing list. - * - * These cases only differ if the operating system does not use the C - * calling convention, at present this just means the above cases - * (x86 DOS/Windows sytems) and, even then, this does not apply to - * Cygwin running on those systems. - * - * Note that the value must be defined in pnglibconf.h so that what - * the application uses to call the library matches the conventions - * set when building the library. - */ - -/* Symbol export - * ============= - * When building a shared library it is almost always necessary to tell - * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' - * is used to mark the symbols. On some systems these symbols can be - * extracted at link time and need no special processing by the compiler, - * on other systems the symbols are flagged by the compiler and just - * the declaration requires a special tag applied (unfortunately) in a - * compiler dependent way. Some systems can do either. - * - * A small number of older systems also require a symbol from a DLL to - * be flagged to the program that calls it. This is a problem because - * we do not know in the header file included by application code that - * the symbol will come from a shared library, as opposed to a statically - * linked one. For this reason the application must tell us by setting - * the magic flag PNG_USE_DLL to turn on the special processing before - * it includes png.h. - * - * Four additional macros are used to make this happen: - * - * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from - * the build or imported if PNG_USE_DLL is set - compiler - * and system specific. - * - * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to - * 'type', compiler specific. - * - * PNG_DLL_EXPORT Set to the magic to use during a libpng build to - * make a symbol exported from the DLL. Not used in the - * public header files; see pngpriv.h for how it is used - * in the libpng build. - * - * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come - * from a DLL - used to define PNG_IMPEXP when - * PNG_USE_DLL is set. - */ - -/* System specific discovery. - * ========================== - * This code is used at build time to find PNG_IMPEXP, the API settings - * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL - * import processing is possible. On Windows systems it also sets - * compiler-specific macros to the values required to change the calling - * conventions of the various functions. - */ -#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ - defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) - /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or - * MinGW on any architecture currently supported by Windows. Also includes - * Watcom builds but these need special treatment because they are not - * compatible with GCC or Visual C because of different calling conventions. - */ -# if PNG_API_RULE == 2 - /* If this line results in an error, either because __watcall is not - * understood or because of a redefine just below you cannot use *this* - * build of the library with the compiler you are using. *This* build was - * build using Watcom and applications must also be built using Watcom! - */ -# define PNGCAPI __watcall -# endif - -# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) -# define PNGCAPI __cdecl -# if PNG_API_RULE == 1 - /* If this line results in an error __stdcall is not understood and - * PNG_API_RULE should not have been set to '1'. - */ -# define PNGAPI __stdcall -# endif -# else - /* An older compiler, or one not detected (erroneously) above, - * if necessary override on the command line to get the correct - * variants for the compiler. - */ -# ifndef PNGCAPI -# define PNGCAPI _cdecl -# endif -# if PNG_API_RULE == 1 && !defined(PNGAPI) -# define PNGAPI _stdcall -# endif -# endif /* compiler/api */ - - /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ - -# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) -# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" -# endif - -# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ - (defined(__BORLANDC__) && __BORLANDC__ < 0x500) - /* older Borland and MSC - * compilers used '__export' and required this to be after - * the type. - */ -# ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP -# endif -# define PNG_DLL_EXPORT __export -# else /* newer compiler */ -# define PNG_DLL_EXPORT __declspec(dllexport) -# ifndef PNG_DLL_IMPORT -# define PNG_DLL_IMPORT __declspec(dllimport) -# endif -# endif /* compiler */ - -#else /* !Windows */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# define PNGAPI _System -# else /* !Windows/x86 && !OS/2 */ - /* Use the defaults, or define PNG*API on the command line (but - * this will have to be done for every compile!) - */ -# endif /* other system, !OS/2 */ -#endif /* !Windows/x86 */ - -/* Now do all the defaulting . */ -#ifndef PNGCAPI -# define PNGCAPI -#endif -#ifndef PNGCBAPI -# define PNGCBAPI PNGCAPI -#endif -#ifndef PNGAPI -# define PNGAPI PNGCAPI -#endif - -/* PNG_IMPEXP may be set on the compilation system command line or (if not set) - * then in an internal header file when building the library, otherwise (when - * using the library) it is set here. - */ -#ifndef PNG_IMPEXP -# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) - /* This forces use of a DLL, disallowing static linking */ -# define PNG_IMPEXP PNG_DLL_IMPORT -# endif - -# ifndef PNG_IMPEXP -# define PNG_IMPEXP -# endif -#endif - -/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat - * 'attributes' as a storage class - the attributes go at the start of the - * function definition, and attributes are always appended regardless of the - * compiler. This considerably simplifies these macros but may cause problems - * if any compilers both need function attributes and fail to handle them as - * a storage class (this is unlikely.) - */ -#ifndef PNG_FUNCTION -# define PNG_FUNCTION(type, name, args, attributes) attributes type name args -#endif - -#ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type -#endif - - /* The ordinal value is only relevant when preprocessing png.h for symbol - * table entries, so we discard it here. See the .dfn files in the - * scripts directory. - */ -#ifndef PNG_EXPORTA - -# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ - PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ - extern attributes) -#endif - -/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, - * so make something non-empty to satisfy the requirement: - */ -#define PNG_EMPTY /*empty list*/ - -#define PNG_EXPORT(ordinal, type, name, args)\ - PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) - -/* Use PNG_REMOVED to comment out a removed interface. */ -#ifndef PNG_REMOVED -# define PNG_REMOVED(ordinal, type, name, args, attributes) -#endif - -#ifndef PNG_CALLBACK -# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) -#endif - -/* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. - * - * Added at libpng-1.2.41. - */ - -#ifndef PNG_NO_PEDANTIC_WARNINGS -# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED -# define PNG_PEDANTIC_WARNINGS_SUPPORTED -# endif -#endif - -#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED - /* Support for compiler specific function attributes. These are used - * so that where compiler support is available, incorrect use of API - * functions in png.h will generate compiler warnings. Added at libpng - * version 1.2.41. Disabling these removes the warnings but may also produce - * less efficient code. - */ -# if defined(__GNUC__) -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __attribute__((__noreturn__)) -# endif -# if __GNUC__ >= 3 -# ifndef PNG_ALLOCATED -# define PNG_ALLOCATED __attribute__((__malloc__)) -# endif -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __attribute__((__deprecated__)) -# endif -# ifndef PNG_PRIVATE -# if 0 /* Doesn't work so we use deprecated instead*/ -# define PNG_PRIVATE \ - __attribute__((warning("This function is not exported by libpng."))) -# else -# define PNG_PRIVATE \ - __attribute__((__deprecated__)) -# endif -# endif -# if ((__GNUC__ != 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) -# ifndef PNG_RESTRICT -# define PNG_RESTRICT __restrict -# endif -# endif /* __GNUC__ == 3.0 */ -# endif /* __GNUC__ >= 3 */ - -# elif defined(_MSC_VER) && (_MSC_VER >= 1300) -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* not supported */ -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __declspec(noreturn) -# endif -# ifndef PNG_ALLOCATED -# if (_MSC_VER >= 1400) -# define PNG_ALLOCATED __declspec(restrict) -# endif -# endif -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __declspec(deprecated) -# endif -# ifndef PNG_PRIVATE -# define PNG_PRIVATE __declspec(deprecated) -# endif -# ifndef PNG_RESTRICT -# if (_MSC_VER >= 1400) -# define PNG_RESTRICT __restrict -# endif -# endif - -# elif defined(__WATCOMC__) -# ifndef PNG_RESTRICT -# define PNG_RESTRICT __restrict -# endif -# endif /* _MSC_VER */ -#endif /* PNG_PEDANTIC_WARNINGS */ - -#ifndef PNG_DEPRECATED -# define PNG_DEPRECATED /* Use of this function is deprecated */ -#endif -#ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* The result of this function must be checked */ -#endif -#ifndef PNG_NORETURN -# define PNG_NORETURN /* This function does not return */ -#endif -#ifndef PNG_ALLOCATED -# define PNG_ALLOCATED /* The result of the function is new memory */ -#endif -#ifndef PNG_PRIVATE -# define PNG_PRIVATE /* This is a private libpng function */ -#endif -#ifndef PNG_RESTRICT -# define PNG_RESTRICT /* The C99 "restrict" feature */ -#endif -#ifndef PNG_FP_EXPORT /* A floating point API. */ -# ifdef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FP_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args); -# else /* No floating point APIs */ -# define PNG_FP_EXPORT(ordinal, type, name, args) -# endif -#endif -#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ -# ifdef PNG_FIXED_POINT_SUPPORTED -# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args); -# else /* No fixed point APIs */ -# define PNG_FIXED_EXPORT(ordinal, type, name, args) -# endif -#endif - -#ifndef PNG_BUILDING_SYMBOL_TABLE -/* Some typedefs to get us started. These should be safe on most of the common - * platforms. - * - * png_uint_32 and png_int_32 may, currently, be larger than required to hold a - * 32-bit value however this is not normally advisable. - * - * png_uint_16 and png_int_16 should always be two bytes in size - this is - * verified at library build time. - * - * png_byte must always be one byte in size. - * - * The checks below use constants from limits.h, as defined by the ISOC90 - * standard. - */ -#if CHAR_BIT == 8 && UCHAR_MAX == 255 - typedef unsigned char png_byte; -#else -# error "libpng requires 8 bit bytes" -#endif - -#if INT_MIN == -32768 && INT_MAX == 32767 - typedef int png_int_16; -#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 - typedef short png_int_16; -#else -# error "libpng requires a signed 16 bit type" -#endif - -#if UINT_MAX == 65535 - typedef unsigned int png_uint_16; -#elif USHRT_MAX == 65535 - typedef unsigned short png_uint_16; -#else -# error "libpng requires an unsigned 16 bit type" -#endif - -#if INT_MIN < -2147483646 && INT_MAX > 2147483646 - typedef int png_int_32; -#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 - typedef long int png_int_32; -#else -# error "libpng requires a signed 32 bit (or more) type" -#endif - -#if UINT_MAX > 4294967294 - typedef unsigned int png_uint_32; -#elif ULONG_MAX > 4294967294 - typedef unsigned long int png_uint_32; -#else -# error "libpng requires an unsigned 32 bit (or more) type" -#endif - -/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, - * requires an ISOC90 compiler and relies on consistent behavior of sizeof. - */ -typedef size_t png_size_t; -typedef ptrdiff_t png_ptrdiff_t; - -/* libpng needs to know the maximum value of 'size_t' and this controls the - * definition of png_alloc_size_t, below. This maximum value of size_t limits - * but does not control the maximum allocations the library makes - there is - * direct application control of this through png_set_user_limits(). - */ -#ifndef PNG_SMALL_SIZE_T - /* Compiler specific tests for systems where size_t is known to be less than - * 32 bits (some of these systems may no longer work because of the lack of - * 'far' support; see above.) - */ -# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ - (defined(_MSC_VER) && defined(MAXSEG_64K)) -# define PNG_SMALL_SIZE_T -# endif -#endif - -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no - * smaller than png_uint_32. Casts from png_size_t or png_uint_32 to - * png_alloc_size_t are not necessary; in fact, it is recommended not to use - * them at all so that the compiler can complain when something turns out to be - * problematic. - * - * Casts in the other direction (from png_alloc_size_t to png_size_t or - * png_uint_32) should be explicitly applied; however, we do not expect to - * encounter practical situations that require such conversions. - * - * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than - * 4294967295 - i.e. less than the maximum value of png_uint_32. - */ -#ifdef PNG_SMALL_SIZE_T - typedef png_uint_32 png_alloc_size_t; -#else - typedef png_size_t png_alloc_size_t; -#endif - -/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler - * implementations of Intel CPU specific support of user-mode segmented address - * spaces, where 16-bit pointers address more than 65536 bytes of memory using - * separate 'segment' registers. The implementation requires two different - * types of pointer (only one of which includes the segment value.) - * - * If required this support is available in version 1.2 of libpng and may be - * available in versions through 1.5, although the correctness of the code has - * not been verified recently. - */ - -/* Typedef for floating-point numbers that are converted to fixed-point with a - * multiple of 100,000, e.g., gamma - */ -typedef png_int_32 png_fixed_point; - -/* Add typedefs for pointers */ -typedef void * png_voidp; -typedef const void * png_const_voidp; -typedef png_byte * png_bytep; -typedef const png_byte * png_const_bytep; -typedef png_uint_32 * png_uint_32p; -typedef const png_uint_32 * png_const_uint_32p; -typedef png_int_32 * png_int_32p; -typedef const png_int_32 * png_const_int_32p; -typedef png_uint_16 * png_uint_16p; -typedef const png_uint_16 * png_const_uint_16p; -typedef png_int_16 * png_int_16p; -typedef const png_int_16 * png_const_int_16p; -typedef char * png_charp; -typedef const char * png_const_charp; -typedef png_fixed_point * png_fixed_point_p; -typedef const png_fixed_point * png_const_fixed_point_p; -typedef png_size_t * png_size_tp; -typedef const png_size_t * png_const_size_tp; - -#ifdef PNG_STDIO_SUPPORTED -typedef FILE * png_FILE_p; -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double * png_doublep; -typedef const double * png_const_doublep; -#endif - -/* Pointers to pointers; i.e. arrays */ -typedef png_byte * * png_bytepp; -typedef png_uint_32 * * png_uint_32pp; -typedef png_int_32 * * png_int_32pp; -typedef png_uint_16 * * png_uint_16pp; -typedef png_int_16 * * png_int_16pp; -typedef const char * * png_const_charpp; -typedef char * * png_charpp; -typedef png_fixed_point * * png_fixed_point_pp; -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double * * png_doublepp; -#endif - -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char * * * png_charppp; - -#endif /* PNG_BUILDING_SYMBOL_TABLE */ - -#endif /* PNGCONF_H */ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.7.0beta35 - March 17, 2014 + * + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +/* To do: Do all of this in scripts/pnglibconf.dfa */ +#ifdef PNG_SAFE_LIMITS_SUPPORTED +# ifdef PNG_USER_WIDTH_MAX +# undef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000L +# endif +# ifdef PNG_USER_HEIGHT_MAX +# undef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000L +# endif +# ifdef PNG_USER_CHUNK_MALLOC_MAX +# undef PNG_USER_CHUNK_MALLOC_MAX +# define PNG_USER_CHUNK_MALLOC_MAX 4000000L +# endif +# ifdef PNG_USER_CHUNK_CACHE_MAX +# undef PNG_USER_CHUNK_CACHE_MAX +# define PNG_USER_CHUNK_CACHE_MAX 128 +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ + +/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C + * compiler for correct compilation. The following header files are required by + * the standard. If your compiler doesn't provide these header files, or they + * do not match the standard, you will need to provide/improve them. + */ +#include +#include + +/* Library header files. These header files are all defined by ISOC90; libpng + * expects conformant implementations, however, an ISOC90 conformant system need + * not provide these header files if the functionality cannot be implemented. + * In this case it will be necessary to disable the relevant parts of libpng in + * the build of pnglibconf.h. + * + * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not + * include this unnecessary header file. + */ + +#ifdef PNG_STDIO_SUPPORTED + /* Required for the definition of FILE: */ +# include +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Required for the definition of jmp_buf and the declaration of longjmp: */ +# include +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* Required for struct tm: */ +# include +#endif + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using + * PNG_NO_CONST; this is no longer supported except for data declarations which + * apparently still cause problems in 2011 on some compilers. + */ +#define PNG_CONST const /* backward compatibility only */ + +/* This controls optimization of the reading of 16 and 32 bit values + * from PNG files. It can be set on a per-app-file basis - it + * just changes whether a macro is used when the function is called. + * The library builder sets the default; if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect + * against legacy (pre ISOC90) compilers that did not understand function + * prototypes. It is not required for modern C compilers. + */ +#ifndef PNGARG +# define PNGARG(arglist) arglist +#endif + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows sytems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ + defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) + /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or + * MinGW on any architecture currently supported by Windows. Also includes + * Watcom builds but these need special treatment because they are not + * compatible with GCC or Visual C because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 + /* If this line results in an error __stdcall is not understood and + * PNG_API_RULE should not have been set to '1'. + */ +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) +# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ +#ifndef PNG_EXPORTA + +# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ + PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ + extern attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args)\ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available, incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. Disabling these removes the warnings but may also produce + * less efficient code. + */ +# if defined(__clang__) + /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ +# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# if !defined(PNG_PRIVATE) +# ifdef __has_extension +# if __has_extension(attribute_unavailable_with_message) +# define PNG_PRIVATE __attribute__((__unavailable__(\ + "This function is not exported by libpng."))) +# endif +# endif +# endif +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# elif defined(__GNUC__) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# if __GNUC__ >= 3 +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif +# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ +# endif /* __GNUC__ >= 3 */ + +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# ifndef PNG_RESTRICT +# if (_MSC_VER >= 1400) +# define PNG_RESTRICT __restrict +# endif +# endif + +# elif defined(__WATCOMC__) +# ifndef PNG_RESTRICT +# define PNG_RESTRICT __restrict +# endif +# endif +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_RESTRICT +# define PNG_RESTRICT /* The C99 "restrict" feature */ +#endif + +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args); +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* Some typedefs to get us started. These should be safe on most of the common + * platforms. + * + * png_uint_32 and png_int_32 may, currently, be larger than required to hold a + * 32-bit value however this is not normally advisable. + * + * png_uint_16 and png_int_16 should always be two bytes in size - this is + * verified at library build time. + * + * png_byte must always be one byte in size. + * + * The checks below use constants from limits.h, as defined by the ISOC90 + * standard. + */ +#if CHAR_BIT == 8 && UCHAR_MAX == 255 + typedef unsigned char png_byte; +#else +# error "libpng requires 8 bit bytes" +#endif + +#if INT_MIN == -32768 && INT_MAX == 32767 + typedef int png_int_16; +#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 + typedef short png_int_16; +#else +# error "libpng requires a signed 16 bit type" +#endif + +#if UINT_MAX == 65535 + typedef unsigned int png_uint_16; +#elif USHRT_MAX == 65535 + typedef unsigned short png_uint_16; +#else +# error "libpng requires an unsigned 16 bit type" +#endif + +#if INT_MIN < -2147483646 && INT_MAX > 2147483646 + typedef int png_int_32; +#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 + typedef long int png_int_32; +#else +# error "libpng requires a signed 32 bit (or more) type" +#endif + +#if UINT_MAX > 4294967294 + typedef unsigned int png_uint_32; +#elif ULONG_MAX > 4294967294 + typedef unsigned long int png_uint_32; +#else +# error "libpng requires an unsigned 32 bit (or more) type" +#endif + +/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, + * requires an ISOC90 compiler and relies on consistent behavior of sizeof. + * + * DEPRECATED: don't use these types, instead use size_t and ptrdiff_t. + */ +typedef size_t png_size_t; +typedef ptrdiff_t png_ptrdiff_t; + +/* libpng needs to know the maximum value of 'size_t' and this controls the + * definition of png_alloc_size_t, below. This maximum value of size_t limits + * but does not control the maximum allocations the library makes - there is + * direct application control of this through png_set_user_limits(). + */ +#ifndef PNG_SMALL_SIZE_T + /* Compiler specific tests for systems where size_t is known to be less than + * 32 bits (some of these systems may no longer work because of the lack of + * 'far' support; see above.) + */ +# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ + (defined(_MSC_VER) && defined(MAXSEG_64K)) +# define PNG_SMALL_SIZE_T +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no + * smaller than png_uint_32. Casts from size_t or png_uint_32 to + * png_alloc_size_t are not necessary; in fact, it is recommended not to use + * them at all so that the compiler can complain when something turns out to be + * problematic. + * + * Casts in the other direction (from png_alloc_size_t to size_t or + * png_uint_32) should be explicitly applied; however, we do not expect to + * encounter practical situations that require such conversions. + * + * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than + * 4294967295 - i.e. less than the maximum value of png_uint_32. + */ +#ifdef PNG_SMALL_SIZE_T + typedef png_uint_32 png_alloc_size_t; +#else + typedef size_t png_alloc_size_t; +#endif + +/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler + * implementations of Intel CPU specific support of user-mode segmented address + * spaces, where 16-bit pointers address more than 65536 bytes of memory using + * separate 'segment' registers. The implementation requires two different + * types of pointer (only one of which includes the segment value.) + * + * If required this support is available in version 1.2 of libpng and may be + * available in versions through 1.5, although the correctness of the code has + * not been verified recently. + */ + +/* Typedef for floating-point numbers that are converted to fixed-point with a + * multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void * png_voidp; +typedef const void * png_const_voidp; +typedef png_byte * png_bytep; +typedef const png_byte * png_const_bytep; +typedef png_uint_32 * png_uint_32p; +typedef const png_uint_32 * png_const_uint_32p; +typedef png_int_32 * png_int_32p; +typedef const png_int_32 * png_const_int_32p; +typedef png_uint_16 * png_uint_16p; +typedef const png_uint_16 * png_const_uint_16p; +typedef png_int_16 * png_int_16p; +typedef const png_int_16 * png_const_int_16p; +typedef char * png_charp; +typedef const char * png_const_charp; +typedef png_fixed_point * png_fixed_point_p; +typedef const png_fixed_point * png_const_fixed_point_p; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * png_doublep; +typedef const double * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte * * png_bytepp; +typedef png_uint_32 * * png_uint_32pp; +typedef png_int_32 * * png_int_32pp; +typedef png_uint_16 * * png_uint_16pp; +typedef png_int_16 * * png_int_16pp; +typedef const char * * png_const_charpp; +typedef char * * png_charpp; +typedef png_fixed_point * * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double * * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char * * * png_charppp; + +#endif /* PNG_BUILDING_SYMBOL_TABLE */ + +#endif /* PNGCONF_H */ diff --git a/ext/libpng16/pngdebug.h b/ext/libpng17/pngdebug.h similarity index 84% rename from ext/libpng16/pngdebug.h rename to ext/libpng17/pngdebug.h index 96c1ea42b3..b43c59cde5 100644 --- a/ext/libpng16/pngdebug.h +++ b/ext/libpng17/pngdebug.h @@ -1,157 +1,154 @@ - -/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c - * - * Copyright (c) 1998-2011 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * Last changed in libpng 1.5.0 [January 6, 2011] - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -/* Define PNG_DEBUG at compile time for debugging information. Higher - * numbers for PNG_DEBUG mean more debugging information. This has - * only been added since version 0.95 so it is not implemented throughout - * libpng yet, but more support will be added as needed. - * - * png_debug[1-2]?(level, message ,arg{0-2}) - * Expands to a statement (either a simple expression or a compound - * do..while(0) statement) that outputs a message with parameter - * substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG - * is undefined, 0 or 1 every png_debug expands to a simple expression - * (actually ((void)0)). - * - * level: level of detail of message, starting at 0. A level 'n' - * message is preceded by 'n' tab characters (not implemented - * on Microsoft compilers unless PNG_DEBUG_FILE is also - * defined, to allow debug DLL compilation with no standard IO). - * message: a printf(3) style text string. A trailing '\n' is added - * to the message. - * arg: 0 to 2 arguments for printf(3) style substitution in message. - */ -#ifndef PNGDEBUG_H -#define PNGDEBUG_H -/* These settings control the formatting of messages in png.c and pngerror.c */ -/* Moved to pngdebug.h at 1.5.0 */ -# ifndef PNG_LITERAL_SHARP -# define PNG_LITERAL_SHARP 0x23 -# endif -# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET -# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b -# endif -# ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET -# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d -# endif -# ifndef PNG_STRING_NEWLINE -# define PNG_STRING_NEWLINE "\n" -# endif - -#ifdef PNG_DEBUG -# if (PNG_DEBUG > 0) -# if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) -# include -# if (PNG_DEBUG > 1) -# ifndef _DEBUG -# define _DEBUG -# endif -# ifndef png_debug -# define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) -# endif -# ifndef png_debug1 -# define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) -# endif -# ifndef png_debug2 -# define png_debug2(l,m,p1,p2) \ - _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) -# endif -# endif -# else /* PNG_DEBUG_FILE || !_MSC_VER */ -# ifndef PNG_STDIO_SUPPORTED -# include /* not included yet */ -# endif -# ifndef PNG_DEBUG_FILE -# define PNG_DEBUG_FILE stderr -# endif /* PNG_DEBUG_FILE */ - -# if (PNG_DEBUG > 1) -/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on - * non-ISO compilers - */ -# ifdef __STDC__ -# ifndef png_debug -# define png_debug(l,m) \ - do { \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ - } while (0) -# endif -# ifndef png_debug1 -# define png_debug1(l,m,p1) \ - do { \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ - } while (0) -# endif -# ifndef png_debug2 -# define png_debug2(l,m,p1,p2) \ - do { \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ - } while (0) -# endif -# else /* __STDC __ */ -# ifndef png_debug -# define png_debug(l,m) \ - do { \ - int num_tabs=l; \ - char format[256]; \ - snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ - m,PNG_STRING_NEWLINE); \ - fprintf(PNG_DEBUG_FILE,format); \ - } while (0) -# endif -# ifndef png_debug1 -# define png_debug1(l,m,p1) \ - do { \ - int num_tabs=l; \ - char format[256]; \ - snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ - m,PNG_STRING_NEWLINE); \ - fprintf(PNG_DEBUG_FILE,format,p1); \ - } while (0) -# endif -# ifndef png_debug2 -# define png_debug2(l,m,p1,p2) \ - do { \ - int num_tabs=l; \ - char format[256]; \ - snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ - m,PNG_STRING_NEWLINE); \ - fprintf(PNG_DEBUG_FILE,format,p1,p2); \ - } while (0) -# endif -# endif /* __STDC __ */ -# endif /* (PNG_DEBUG > 1) */ - -# endif /* _MSC_VER */ -# endif /* (PNG_DEBUG > 0) */ -#endif /* PNG_DEBUG */ -#ifndef png_debug -# define png_debug(l, m) ((void)0) -#endif -#ifndef png_debug1 -# define png_debug1(l, m, p1) ((void)0) -#endif -#ifndef png_debug2 -# define png_debug2(l, m, p1, p2) ((void)0) -#endif -#endif /* PNGDEBUG_H */ + +/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c + * + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.6.8 [December 19, 2013] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + * + * png_debug[1-2]?(level, message ,arg{0-2}) + * Expands to a statement (either a simple expression or a compound + * do..while(0) statement) that outputs a message with parameter + * substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG + * is undefined, 0 or 1 every png_debug expands to a simple expression + * (actually ((void)0)). + * + * level: level of detail of message, starting at 0. A level 'n' + * message is preceded by 'n' 3-space indentations (not implemented + * on Microsoft compilers unless PNG_DEBUG_FILE is also + * defined, to allow debug DLL compilation with no standard IO). + * message: a printf(3) style text string. A trailing '\n' is added + * to the message. + * arg: 0 to 2 arguments for printf(3) style substitution in message. + */ +#ifndef PNGDEBUG_H +#define PNGDEBUG_H +/* These settings control the formatting of messages in png.c and pngerror.c */ +/* Moved to pngdebug.h at 1.5.0 */ +# ifndef PNG_LITERAL_SHARP +# define PNG_LITERAL_SHARP 0x23 +# endif +# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET +# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b +# endif +# ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET +# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d +# endif +# ifndef PNG_STRING_NEWLINE +# define PNG_STRING_NEWLINE "\n" +# endif + +#ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +# include +# if (PNG_DEBUG > 1) +# ifndef _DEBUG +# define _DEBUG +# endif +# ifndef png_debug +# define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) +# endif +# endif +# else /* PNG_DEBUG_FILE || !_MSC_VER */ +# ifndef PNG_STDIO_SUPPORTED +# include /* not included yet */ +# endif +# ifndef PNG_DEBUG_FILE +# define PNG_DEBUG_FILE stderr +# endif /* PNG_DEBUG_FILE */ + +# if (PNG_DEBUG > 1) +# ifdef __STDC__ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \ + (num_tabs==2 ? " " : (num_tabs>2 ? " " : "")))); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \ + (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \ + (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1,p2);\ + } while (0) +# endif +# else /* __STDC __ */ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1,p2); \ + } while (0) +# endif +# endif /* __STDC __ */ +# endif /* (PNG_DEBUG > 1) */ + +# endif /* _MSC_VER */ +# endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +# define png_debug(l, m) ((void)0) +#endif +#ifndef png_debug1 +# define png_debug1(l, m, p1) ((void)0) +#endif +#ifndef png_debug2 +# define png_debug2(l, m, p1, p2) ((void)0) +#endif +#endif /* PNGDEBUG_H */ diff --git a/ext/libpng16/pngerror.c b/ext/libpng17/pngerror.c similarity index 94% rename from ext/libpng16/pngerror.c rename to ext/libpng17/pngerror.c index c71e2ab559..828cac4b3d 100644 --- a/ext/libpng16/pngerror.c +++ b/ext/libpng17/pngerror.c @@ -1,932 +1,971 @@ - -/* pngerror.c - stub functions for i/o and memory allocation - * - * Last changed in libpng 1.6.1 [March 28, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - * This file provides a location for all error handling. Users who - * need special error handling are expected to write replacement functions - * and use png_set_error_fn() to use those functions. See the instructions - * at each function. - */ - -#include "pngpriv.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr, - png_const_charp error_message)),PNG_NORETURN); - -#ifdef PNG_WARNINGS_SUPPORTED -static void /* PRIVATE */ -png_default_warning PNGARG((png_const_structrp png_ptr, - png_const_charp warning_message)); -#endif /* PNG_WARNINGS_SUPPORTED */ - -/* This function is called whenever there is a fatal error. This function - * should not be changed. If there is a need to handle errors differently, - * you should supply a replacement error function and use png_set_error_fn() - * to replace the error function at run-time. - */ -#ifdef PNG_ERROR_TEXT_SUPPORTED -PNG_FUNCTION(void,PNGAPI -png_error,(png_const_structrp png_ptr, png_const_charp error_message), - PNG_NORETURN) -{ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - char msg[16]; - if (png_ptr != NULL) - { - if (png_ptr->flags& - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) - { - if (*error_message == PNG_LITERAL_SHARP) - { - /* Strip "#nnnn " from beginning of error message. */ - int offset; - for (offset = 1; offset<15; offset++) - if (error_message[offset] == ' ') - break; - - if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) - { - int i; - for (i = 0; i < offset - 1; i++) - msg[i] = error_message[i + 1]; - msg[i - 1] = '\0'; - error_message = msg; - } - - else - error_message += offset; - } - - else - { - if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) - { - msg[0] = '0'; - msg[1] = '\0'; - error_message = msg; - } - } - } - } -#endif - if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), - error_message); - - /* If the custom handler doesn't exist, or if it returns, - use the default handler, which will not return. */ - png_default_error(png_ptr, error_message); -} -#else -PNG_FUNCTION(void,PNGAPI -png_err,(png_const_structrp png_ptr),PNG_NORETURN) -{ - /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed - * erroneously as '\0', instead of the empty string "". This was - * apparently an error, introduced in libpng-1.2.20, and png_default_error - * will crash in this case. - */ - if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), ""); - - /* If the custom handler doesn't exist, or if it returns, - use the default handler, which will not return. */ - png_default_error(png_ptr, ""); -} -#endif /* PNG_ERROR_TEXT_SUPPORTED */ - -/* Utility to safely appends strings to a buffer. This never errors out so - * error checking is not required in the caller. - */ -size_t -png_safecat(png_charp buffer, size_t bufsize, size_t pos, - png_const_charp string) -{ - if (buffer != NULL && pos < bufsize) - { - if (string != NULL) - while (*string != '\0' && pos < bufsize-1) - buffer[pos++] = *string++; - - buffer[pos] = '\0'; - } - - return pos; -} - -#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) -/* Utility to dump an unsigned value into a buffer, given a start pointer and - * and end pointer (which should point just *beyond* the end of the buffer!) - * Returns the pointer to the start of the formatted string. - */ -png_charp -png_format_number(png_const_charp start, png_charp end, int format, - png_alloc_size_t number) -{ - int count = 0; /* number of digits output */ - int mincount = 1; /* minimum number required */ - int output = 0; /* digit output (for the fixed point format) */ - - *--end = '\0'; - - /* This is written so that the loop always runs at least once, even with - * number zero. - */ - while (end > start && (number != 0 || count < mincount)) - { - - static const char digits[] = "0123456789ABCDEF"; - - switch (format) - { - case PNG_NUMBER_FORMAT_fixed: - /* Needs five digits (the fraction) */ - mincount = 5; - if (output || number % 10 != 0) - { - *--end = digits[number % 10]; - output = 1; - } - number /= 10; - break; - - case PNG_NUMBER_FORMAT_02u: - /* Expects at least 2 digits. */ - mincount = 2; - /* FALL THROUGH */ - - case PNG_NUMBER_FORMAT_u: - *--end = digits[number % 10]; - number /= 10; - break; - - case PNG_NUMBER_FORMAT_02x: - /* This format expects at least two digits */ - mincount = 2; - /* FALL THROUGH */ - - case PNG_NUMBER_FORMAT_x: - *--end = digits[number & 0xf]; - number >>= 4; - break; - - default: /* an error */ - number = 0; - break; - } - - /* Keep track of the number of digits added */ - ++count; - - /* Float a fixed number here: */ - if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start) - { - /* End of the fraction, but maybe nothing was output? In that case - * drop the decimal point. If the number is a true zero handle that - * here. - */ - if (output) - *--end = '.'; - else if (number == 0) /* and !output */ - *--end = '0'; - } - } - - return end; -} -#endif - -#ifdef PNG_WARNINGS_SUPPORTED -/* This function is called whenever there is a non-fatal error. This function - * should not be changed. If there is a need to handle warnings differently, - * you should supply a replacement warning function and use - * png_set_error_fn() to replace the warning function at run-time. - */ -void PNGAPI -png_warning(png_const_structrp png_ptr, png_const_charp warning_message) -{ - int offset = 0; - if (png_ptr != NULL) - { -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (png_ptr->flags& - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) -#endif - { - if (*warning_message == PNG_LITERAL_SHARP) - { - for (offset = 1; offset < 15; offset++) - if (warning_message[offset] == ' ') - break; - } - } - } - if (png_ptr != NULL && png_ptr->warning_fn != NULL) - (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr), - warning_message + offset); - else - png_default_warning(png_ptr, warning_message + offset); -} - -/* These functions support 'formatted' warning messages with up to - * PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter - * is introduced by @, where 'number' starts at 1. This follows the - * standard established by X/Open for internationalizable error messages. - */ -void -png_warning_parameter(png_warning_parameters p, int number, - png_const_charp string) -{ - if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) - (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); -} - -void -png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, - png_alloc_size_t value) -{ - char buffer[PNG_NUMBER_BUFFER_SIZE]; - png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); -} - -void -png_warning_parameter_signed(png_warning_parameters p, int number, int format, - png_int_32 value) -{ - png_alloc_size_t u; - png_charp str; - char buffer[PNG_NUMBER_BUFFER_SIZE]; - - /* Avoid overflow by doing the negate in a png_alloc_size_t: */ - u = (png_alloc_size_t)value; - if (value < 0) - u = ~u + 1; - - str = PNG_FORMAT_NUMBER(buffer, format, u); - - if (value < 0 && str > buffer) - *--str = '-'; - - png_warning_parameter(p, number, str); -} - -void -png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, - png_const_charp message) -{ - /* The internal buffer is just 192 bytes - enough for all our messages, - * overflow doesn't happen because this code checks! If someone figures - * out how to send us a message longer than 192 bytes, all that will - * happen is that the message will be truncated appropriately. - */ - size_t i = 0; /* Index in the msg[] buffer: */ - char msg[192]; - - /* Each iteration through the following loop writes at most one character - * to msg[i++] then returns here to validate that there is still space for - * the trailing '\0'. It may (in the case of a parameter) read more than - * one character from message[]; it must check for '\0' and continue to the - * test if it finds the end of string. - */ - while (i<(sizeof msg)-1 && *message != '\0') - { - /* '@' at end of string is now just printed (previously it was skipped); - * it is an error in the calling code to terminate the string with @. - */ - if (p != NULL && *message == '@' && message[1] != '\0') - { - int parameter_char = *++message; /* Consume the '@' */ - static const char valid_parameters[] = "123456789"; - int parameter = 0; - - /* Search for the parameter digit, the index in the string is the - * parameter to use. - */ - while (valid_parameters[parameter] != parameter_char && - valid_parameters[parameter] != '\0') - ++parameter; - - /* If the parameter digit is out of range it will just get printed. */ - if (parameter < PNG_WARNING_PARAMETER_COUNT) - { - /* Append this parameter */ - png_const_charp parm = p[parameter]; - png_const_charp pend = p[parameter] + (sizeof p[parameter]); - - /* No need to copy the trailing '\0' here, but there is no guarantee - * that parm[] has been initialized, so there is no guarantee of a - * trailing '\0': - */ - while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend) - msg[i++] = *parm++; - - /* Consume the parameter digit too: */ - ++message; - continue; - } - - /* else not a parameter and there is a character after the @ sign; just - * copy that. This is known not to be '\0' because of the test above. - */ - } - - /* At this point *message can't be '\0', even in the bad parameter case - * above where there is a lone '@' at the end of the message string. - */ - msg[i++] = *message++; - } - - /* i is always less than (sizeof msg), so: */ - msg[i] = '\0'; - - /* And this is the formatted message. It may be larger than - * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these - * are not (currently) formatted. - */ - png_warning(png_ptr, msg); -} -#endif /* PNG_WARNINGS_SUPPORTED */ - -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -void PNGAPI -png_benign_error(png_const_structrp png_ptr, png_const_charp error_message) -{ - if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) - { -# ifdef PNG_READ_SUPPORTED - if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && - png_ptr->chunk_name != 0) - png_chunk_warning(png_ptr, error_message); - else -# endif - png_warning(png_ptr, error_message); - } - - else - { -# ifdef PNG_READ_SUPPORTED - if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && - png_ptr->chunk_name != 0) - png_chunk_error(png_ptr, error_message); - else -# endif - png_error(png_ptr, error_message); - } -} - -void /* PRIVATE */ -png_app_warning(png_const_structrp png_ptr, png_const_charp error_message) -{ - if (png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) - png_warning(png_ptr, error_message); - else - png_error(png_ptr, error_message); -} - -void /* PRIVATE */ -png_app_error(png_const_structrp png_ptr, png_const_charp error_message) -{ - if (png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) - png_warning(png_ptr, error_message); - else - png_error(png_ptr, error_message); -} -#endif /* BENIGN_ERRORS */ - -/* These utilities are used internally to build an error message that relates - * to the current chunk. The chunk name comes from png_ptr->chunk_name, - * this is used to prefix the message. The message is limited in length - * to 63 bytes, the name characters are output as hex digits wrapped in [] - * if the character is invalid. - */ -#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) -static PNG_CONST char png_digit[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F' -}; - -#define PNG_MAX_ERROR_TEXT 196 /* Currently limited be profile_error in png.c */ -#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) -static void /* PRIVATE */ -png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp - error_message) -{ - png_uint_32 chunk_name = png_ptr->chunk_name; - int iout = 0, ishift = 24; - - while (ishift >= 0) - { - int c = (int)(chunk_name >> ishift) & 0xff; - - ishift -= 8; - if (isnonalpha(c)) - { - buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; - buffer[iout++] = png_digit[(c & 0xf0) >> 4]; - buffer[iout++] = png_digit[c & 0x0f]; - buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; - } - - else - { - buffer[iout++] = (char)c; - } - } - - if (error_message == NULL) - buffer[iout] = '\0'; - - else - { - int iin = 0; - - buffer[iout++] = ':'; - buffer[iout++] = ' '; - - while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0') - buffer[iout++] = error_message[iin++]; - - /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */ - buffer[iout] = '\0'; - } -} -#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ - -#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) -PNG_FUNCTION(void,PNGAPI -png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message), - PNG_NORETURN) -{ - char msg[18+PNG_MAX_ERROR_TEXT]; - if (png_ptr == NULL) - png_error(png_ptr, error_message); - - else - { - png_format_buffer(png_ptr, msg, error_message); - png_error(png_ptr, msg); - } -} -#endif /* PNG_READ_SUPPORTED && PNG_ERROR_TEXT_SUPPORTED */ - -#ifdef PNG_WARNINGS_SUPPORTED -void PNGAPI -png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message) -{ - char msg[18+PNG_MAX_ERROR_TEXT]; - if (png_ptr == NULL) - png_warning(png_ptr, warning_message); - - else - { - png_format_buffer(png_ptr, msg, warning_message); - png_warning(png_ptr, msg); - } -} -#endif /* PNG_WARNINGS_SUPPORTED */ - -#ifdef PNG_READ_SUPPORTED -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -void PNGAPI -png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp - error_message) -{ - if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) - png_chunk_warning(png_ptr, error_message); - - else - png_chunk_error(png_ptr, error_message); -} -#endif -#endif /* PNG_READ_SUPPORTED */ - -void /* PRIVATE */ -png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error) -{ - /* This is always supported, but for just read or just write it - * unconditionally does the right thing. - */ -# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) - if (png_ptr->mode & PNG_IS_READ_STRUCT) -# endif - -# ifdef PNG_READ_SUPPORTED - { - if (error < PNG_CHUNK_ERROR) - png_chunk_warning(png_ptr, message); - - else - png_chunk_benign_error(png_ptr, message); - } -# endif - -# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) - else if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) -# endif - -# ifdef PNG_WRITE_SUPPORTED - { - if (error < PNG_CHUNK_WRITE_ERROR) - png_app_warning(png_ptr, message); - - else - png_app_error(png_ptr, message); - } -# endif -} - -#ifdef PNG_ERROR_TEXT_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_FUNCTION(void, -png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN) -{ -# define fixed_message "fixed point overflow in " -# define fixed_message_ln ((sizeof fixed_message)-1) - int iin; - char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; - memcpy(msg, fixed_message, fixed_message_ln); - iin = 0; - if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) - { - msg[fixed_message_ln + iin] = name[iin]; - ++iin; - } - msg[fixed_message_ln + iin] = 0; - png_error(png_ptr, msg); -} -#endif -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This API only exists if ANSI-C style error handling is used, - * otherwise it is necessary for png_default_error to be overridden. - */ -jmp_buf* PNGAPI -png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn, - size_t jmp_buf_size) -{ - /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value - * and it must not change after that. Libpng doesn't care how big the - * buffer is, just that it doesn't change. - * - * If the buffer size is no *larger* than the size of jmp_buf when libpng is - * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0 - * semantics that this call will not fail. If the size is larger, however, - * the buffer is allocated and this may fail, causing the function to return - * NULL. - */ - if (png_ptr == NULL) - return NULL; - - if (png_ptr->jmp_buf_ptr == NULL) - { - png_ptr->jmp_buf_size = 0; /* not allocated */ - - if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local)) - png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; - - else - { - png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *, - png_malloc_warn(png_ptr, jmp_buf_size)); - - if (png_ptr->jmp_buf_ptr == NULL) - return NULL; /* new NULL return on OOM */ - - png_ptr->jmp_buf_size = jmp_buf_size; - } - } - - else /* Already allocated: check the size */ - { - size_t size = png_ptr->jmp_buf_size; - - if (size == 0) - { - size = (sizeof png_ptr->jmp_buf_local); - if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local) - { - /* This is an internal error in libpng: somehow we have been left - * with a stack allocated jmp_buf when the application regained - * control. It's always possible to fix this up, but for the moment - * this is a png_error because that makes it easy to detect. - */ - png_error(png_ptr, "Libpng jmp_buf still allocated"); - /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */ - } - } - - if (size != jmp_buf_size) - { - png_warning(png_ptr, "Application jmp_buf size changed"); - return NULL; /* caller will probably crash: no choice here */ - } - } - - /* Finally fill in the function, now we have a satisfactory buffer. It is - * valid to change the function on every call. - */ - png_ptr->longjmp_fn = longjmp_fn; - return png_ptr->jmp_buf_ptr; -} - -void /* PRIVATE */ -png_free_jmpbuf(png_structrp png_ptr) -{ - if (png_ptr != NULL) - { - jmp_buf *jb = png_ptr->jmp_buf_ptr; - - /* A size of 0 is used to indicate a local, stack, allocation of the - * pointer; used here and in png.c - */ - if (jb != NULL && png_ptr->jmp_buf_size > 0) - { - - /* This stuff is so that a failure to free the error control structure - * does not leave libpng in a state with no valid error handling: the - * free always succeeds, if there is an error it gets ignored. - */ - if (jb != &png_ptr->jmp_buf_local) - { - /* Make an internal, libpng, jmp_buf to return here */ - jmp_buf free_jmp_buf; - - if (!setjmp(free_jmp_buf)) - { - png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */ - png_ptr->jmp_buf_size = 0; /* stack allocation */ - png_ptr->longjmp_fn = longjmp; - png_free(png_ptr, jb); /* Return to setjmp on error */ - } - } - } - - /* *Always* cancel everything out: */ - png_ptr->jmp_buf_size = 0; - png_ptr->jmp_buf_ptr = NULL; - png_ptr->longjmp_fn = 0; - } -} -#endif - -/* This is the default error handling function. Note that replacements for - * this function MUST NOT RETURN, or the program will likely crash. This - * function is used by default, or if the program supplies NULL for the - * error function pointer in png_set_error_fn(). - */ -static PNG_FUNCTION(void /* PRIVATE */, -png_default_error,(png_const_structrp png_ptr, png_const_charp error_message), - PNG_NORETURN) -{ -#ifdef PNG_CONSOLE_IO_SUPPORTED -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - /* Check on NULL only added in 1.5.4 */ - if (error_message != NULL && *error_message == PNG_LITERAL_SHARP) - { - /* Strip "#nnnn " from beginning of error message. */ - int offset; - char error_number[16]; - for (offset = 0; offset<15; offset++) - { - error_number[offset] = error_message[offset + 1]; - if (error_message[offset] == ' ') - break; - } - - if ((offset > 1) && (offset < 15)) - { - error_number[offset - 1] = '\0'; - fprintf(stderr, "libpng error no. %s: %s", - error_number, error_message + offset + 1); - fprintf(stderr, PNG_STRING_NEWLINE); - } - - else - { - fprintf(stderr, "libpng error: %s, offset=%d", - error_message, offset); - fprintf(stderr, PNG_STRING_NEWLINE); - } - } - else -#endif - { - fprintf(stderr, "libpng error: %s", error_message ? error_message : - "undefined"); - fprintf(stderr, PNG_STRING_NEWLINE); - } -#else - PNG_UNUSED(error_message) /* Make compiler happy */ -#endif - png_longjmp(png_ptr, 1); -} - -PNG_FUNCTION(void,PNGAPI -png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) -{ -#ifdef PNG_SETJMP_SUPPORTED - if (png_ptr && png_ptr->longjmp_fn && png_ptr->jmp_buf_ptr) - png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val); -#endif - - /* Here if not setjmp support or if png_ptr is null. */ - PNG_ABORT(); -} - -#ifdef PNG_WARNINGS_SUPPORTED -/* This function is called when there is a warning, but the library thinks - * it can continue anyway. Replacement functions don't have to do anything - * here if you don't want them to. In the default configuration, png_ptr is - * not used, but it is passed in case it may be useful. - */ -static void /* PRIVATE */ -png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message) -{ -#ifdef PNG_CONSOLE_IO_SUPPORTED -# ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (*warning_message == PNG_LITERAL_SHARP) - { - int offset; - char warning_number[16]; - for (offset = 0; offset < 15; offset++) - { - warning_number[offset] = warning_message[offset + 1]; - if (warning_message[offset] == ' ') - break; - } - - if ((offset > 1) && (offset < 15)) - { - warning_number[offset + 1] = '\0'; - fprintf(stderr, "libpng warning no. %s: %s", - warning_number, warning_message + offset); - fprintf(stderr, PNG_STRING_NEWLINE); - } - - else - { - fprintf(stderr, "libpng warning: %s", - warning_message); - fprintf(stderr, PNG_STRING_NEWLINE); - } - } - else -# endif - - { - fprintf(stderr, "libpng warning: %s", warning_message); - fprintf(stderr, PNG_STRING_NEWLINE); - } -#else - PNG_UNUSED(warning_message) /* Make compiler happy */ -#endif - PNG_UNUSED(png_ptr) /* Make compiler happy */ -} -#endif /* PNG_WARNINGS_SUPPORTED */ - -/* This function is called when the application wants to use another method - * of handling errors and warnings. Note that the error function MUST NOT - * return to the calling routine or serious problems will occur. The return - * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1) - */ -void PNGAPI -png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warning_fn) -{ - if (png_ptr == NULL) - return; - - png_ptr->error_ptr = error_ptr; - png_ptr->error_fn = error_fn; -#ifdef PNG_WARNINGS_SUPPORTED - png_ptr->warning_fn = warning_fn; -#else - PNG_UNUSED(warning_fn) -#endif -} - - -/* This function returns a pointer to the error_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy and png_read_destroy are called. - */ -png_voidp PNGAPI -png_get_error_ptr(png_const_structrp png_ptr) -{ - if (png_ptr == NULL) - return NULL; - - return ((png_voidp)png_ptr->error_ptr); -} - - -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -void PNGAPI -png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode) -{ - if (png_ptr != NULL) - { - png_ptr->flags &= - ((~(PNG_FLAG_STRIP_ERROR_NUMBERS | - PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); - } -} -#endif - -#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ - defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) - /* Currently the above both depend on SETJMP_SUPPORTED, however it would be - * possible to implement without setjmp support just so long as there is some - * way to handle the error return here: - */ -PNG_FUNCTION(void /* PRIVATE */, -png_safe_error,(png_structp png_nonconst_ptr, png_const_charp error_message), - PNG_NORETURN) -{ - const png_const_structrp png_ptr = png_nonconst_ptr; - png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); - - /* An error is always logged here, overwriting anything (typically a warning) - * that is already there: - */ - if (image != NULL) - { - png_safecat(image->message, (sizeof image->message), 0, error_message); - image->warning_or_error |= PNG_IMAGE_ERROR; - - /* Retrieve the jmp_buf from within the png_control, making this work for - * C++ compilation too is pretty tricky: C++ wants a pointer to the first - * element of a jmp_buf, but C doesn't tell us the type of that. - */ - if (image->opaque != NULL && image->opaque->error_buf != NULL) - longjmp(png_control_jmp_buf(image->opaque), 1); - - /* Missing longjmp buffer, the following is to help debugging: */ - { - size_t pos = png_safecat(image->message, (sizeof image->message), 0, - "bad longjmp: "); - png_safecat(image->message, (sizeof image->message), pos, - error_message); - } - } - - /* Here on an internal programming error. */ - abort(); -} - -#ifdef PNG_WARNINGS_SUPPORTED -void /* PRIVATE */ -png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message) -{ - const png_const_structrp png_ptr = png_nonconst_ptr; - png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); - - /* A warning is only logged if there is no prior warning or error. */ - if (image->warning_or_error == 0) - { - png_safecat(image->message, (sizeof image->message), 0, warning_message); - image->warning_or_error |= PNG_IMAGE_WARNING; - } -} -#endif - -int /* PRIVATE */ -png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg) -{ - volatile png_imagep image = image_in; - volatile int result; - volatile png_voidp saved_error_buf; - jmp_buf safe_jmpbuf; - - /* Safely execute function(arg) with png_error returning to this function. */ - saved_error_buf = image->opaque->error_buf; - result = setjmp(safe_jmpbuf) == 0; - - if (result) - { - - image->opaque->error_buf = safe_jmpbuf; - result = function(arg); - } - - image->opaque->error_buf = saved_error_buf; - - /* And do the cleanup prior to any failure return. */ - if (!result) - png_image_free(image); - - return result; -} -#endif /* SIMPLIFIED READ/WRITE */ -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr, + png_const_charp error_message)),PNG_NORETURN); + +#ifdef PNG_WARNINGS_SUPPORTED +static void /* PRIVATE */ +png_default_warning PNGARG((png_const_structrp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +#ifdef PNG_ERROR_TEXT_SUPPORTED +PNG_FUNCTION(void,PNGAPI +png_error,(png_const_structrp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr != NULL) + { + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + for (offset = 1; offset<15; offset++) + if (error_message[offset] == ' ') + break; + + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i = 0; i < offset - 1; i++) + msg[i] = error_message[i + 1]; + msg[i - 1] = '\0'; + error_message = msg; + } + + else + error_message += offset; + } + + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0] = '0'; + msg[1] = '\0'; + error_message = msg; + } + } + } + } +#endif + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), + error_message); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, error_message); +} +#else +PNG_FUNCTION(void,PNGAPI +png_err,(png_const_structrp png_ptr),PNG_NORETURN) +{ + /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed + * erroneously as '\0', instead of the empty string "". This was + * apparently an error, introduced in libpng-1.2.20, and png_default_error + * will crash in this case. + */ + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), ""); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, ""); +} +#endif /* PNG_ERROR_TEXT_SUPPORTED */ + +/* Utility to safely appends strings to a buffer. This never errors out so + * error checking is not required in the caller. + */ +size_t +png_safecat(png_charp buffer, size_t bufsize, size_t pos, + png_const_charp string) +{ + if (buffer != NULL && pos < bufsize) + { + if (string != NULL) + while (*string != '\0' && pos < bufsize-1) + buffer[pos++] = *string++; + + buffer[pos] = '\0'; + } + + return pos; +} + +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) +/* Utility to dump an unsigned value into a buffer, given a start pointer and + * and end pointer (which should point just *beyond* the end of the buffer!) + * Returns the pointer to the start of the formatted string. + */ +png_charp +png_format_number(png_const_charp start, png_charp end, int format, + png_alloc_size_t number) +{ + int count = 0; /* number of digits output */ + int mincount = 1; /* minimum number required */ + int output = 0; /* digit output (for the fixed point format) */ + + *--end = '\0'; + + /* This is written so that the loop always runs at least once, even with + * number zero. + */ + while (end > start && (number != 0 || count < mincount)) + { + + static const char digits[] = "0123456789ABCDEF"; + + switch (format) + { + case PNG_NUMBER_FORMAT_fixed: + /* Needs five digits (the fraction) */ + mincount = 5; + if (output || number % 10 != 0) + { + *--end = digits[number % 10]; + output = 1; + } + number /= 10; + break; + + case PNG_NUMBER_FORMAT_02u: + /* Expects at least 2 digits. */ + mincount = 2; + /* FALL THROUGH */ + + case PNG_NUMBER_FORMAT_u: + *--end = digits[number % 10]; + number /= 10; + break; + + case PNG_NUMBER_FORMAT_02x: + /* This format expects at least two digits */ + mincount = 2; + /* FALL THROUGH */ + + case PNG_NUMBER_FORMAT_x: + *--end = digits[number & 0xf]; + number >>= 4; + break; + + default: /* an error */ + number = 0; + break; + } + + /* Keep track of the number of digits added */ + ++count; + + /* Float a fixed number here: */ + if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start) + { + /* End of the fraction, but maybe nothing was output? In that case + * drop the decimal point. If the number is a true zero handle that + * here. + */ + if (output != 0) + *--end = '.'; + else if (number == 0) /* and !output */ + *--end = '0'; + } + } + + return end; +} +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called whenever there is a non-fatal error. This function + * should not be changed. If there is a need to handle warnings differently, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_const_structrp png_ptr, png_const_charp warning_message) +{ + int offset = 0; + if (png_ptr != NULL) + { +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*warning_message == PNG_LITERAL_SHARP) + { + for (offset = 1; offset < 15; offset++) + if (warning_message[offset] == ' ') + break; + } + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr), + warning_message + offset); + else + png_default_warning(png_ptr, warning_message + offset); +} + +/* These functions support 'formatted' warning messages with up to + * PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter + * is introduced by @, where 'number' starts at 1. This follows the + * standard established by X/Open for internationalizable error messages. + */ +void +png_warning_parameter(png_warning_parameters p, int number, + png_const_charp string) +{ + if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) + (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); +} + +void +png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, + png_alloc_size_t value) +{ + char buffer[PNG_NUMBER_BUFFER_SIZE]; + png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); +} + +void +png_warning_parameter_signed(png_warning_parameters p, int number, int format, + png_int_32 value) +{ + png_alloc_size_t u; + png_charp str; + char buffer[PNG_NUMBER_BUFFER_SIZE]; + + /* Avoid overflow by doing the negate in a png_alloc_size_t: */ + u = (png_alloc_size_t)value; + if (value < 0) + u = ~u + 1; + + str = PNG_FORMAT_NUMBER(buffer, format, u); + + if (value < 0 && str > buffer) + *--str = '-'; + + png_warning_parameter(p, number, str); +} + +void +png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, + png_const_charp message) +{ + /* The internal buffer is just 192 bytes - enough for all our messages, + * overflow doesn't happen because this code checks! If someone figures + * out how to send us a message longer than 192 bytes, all that will + * happen is that the message will be truncated appropriately. + */ + size_t i = 0; /* Index in the msg[] buffer: */ + char msg[192]; + + /* Each iteration through the following loop writes at most one character + * to msg[i++] then returns here to validate that there is still space for + * the trailing '\0'. It may (in the case of a parameter) read more than + * one character from message[]; it must check for '\0' and continue to the + * test if it finds the end of string. + */ + while (i<(sizeof msg)-1 && *message != '\0') + { + /* '@' at end of string is now just printed (previously it was skipped); + * it is an error in the calling code to terminate the string with @. + */ + if (p != NULL && *message == '@' && message[1] != '\0') + { + int parameter_char = *++message; /* Consume the '@' */ + static const char valid_parameters[] = "123456789"; + int parameter = 0; + + /* Search for the parameter digit, the index in the string is the + * parameter to use. + */ + while (valid_parameters[parameter] != parameter_char && + valid_parameters[parameter] != '\0') + ++parameter; + + /* If the parameter digit is out of range it will just get printed. */ + if (parameter < PNG_WARNING_PARAMETER_COUNT) + { + /* Append this parameter */ + png_const_charp parm = p[parameter]; + png_const_charp pend = p[parameter] + (sizeof p[parameter]); + + /* No need to copy the trailing '\0' here, but there is no guarantee + * that parm[] has been initialized, so there is no guarantee of a + * trailing '\0': + */ + while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend) + msg[i++] = *parm++; + + /* Consume the parameter digit too: */ + ++message; + continue; + } + + /* else not a parameter and there is a character after the @ sign; just + * copy that. This is known not to be '\0' because of the test above. + */ + } + + /* At this point *message can't be '\0', even in the bad parameter case + * above where there is a lone '@' at the end of the message string. + */ + msg[i++] = *message++; + } + + /* i is always less than (sizeof msg), so: */ + msg[i] = '\0'; + + /* And this is the formatted message. It may be larger than + * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these + * are not (currently) formatted. + */ + png_warning(png_ptr, msg); +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_benign_error(png_const_structrp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + { +# ifdef PNG_READ_SUPPORTED + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + png_ptr->chunk_name != 0) + png_chunk_warning(png_ptr, error_message); + else +# endif + png_warning(png_ptr, error_message); + } + + else + { +# ifdef PNG_READ_SUPPORTED + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + png_ptr->chunk_name != 0) + png_chunk_error(png_ptr, error_message); + else +# endif + png_error(png_ptr, error_message); + } + +# ifndef PNG_ERROR_TEXT_SUPPORTED + PNG_UNUSED(error_message) +# endif +} + +void /* PRIVATE */ +png_app_warning(png_const_structrp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); + +# ifndef PNG_ERROR_TEXT_SUPPORTED + PNG_UNUSED(error_message) +# endif +} + +void /* PRIVATE */ +png_app_error(png_const_structrp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); + +# ifndef PNG_ERROR_TEXT_SUPPORTED + PNG_UNUSED(error_message) +# endif +} +#endif /* BENIGN_ERRORS */ + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; + +#define PNG_MAX_ERROR_TEXT 196 /* Currently limited be profile_error in png.c */ +#if defined(PNG_WARNINGS_SUPPORTED) || \ + (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)) +static void /* PRIVATE */ +png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp + error_message) +{ + png_uint_32 chunk_name = png_ptr->chunk_name; + int iout = 0, ishift = 24; + + while (ishift >= 0) + { + int c = (int)(chunk_name >> ishift) & 0xff; + + ishift -= 8; + if (isnonalpha(c)) + { + buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; + } + + else + { + buffer[iout++] = (char)c; + } + } + + if (error_message == NULL) + buffer[iout] = '\0'; + + else + { + int iin = 0; + + buffer[iout++] = ':'; + buffer[iout++] = ' '; + + while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0') + buffer[iout++] = error_message[iin++]; + + /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */ + buffer[iout] = '\0'; + } +} +#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_FUNCTION(void,PNGAPI +png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_error(png_ptr, error_message); + + else + { + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); + } +} +#endif /* PNG_READ_SUPPORTED && PNG_ERROR_TEXT_SUPPORTED */ + +#ifdef PNG_WARNINGS_SUPPORTED +void PNGAPI +png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_warning(png_ptr, warning_message); + + else + { + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); + } +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_READ_SUPPORTED +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp + error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_chunk_warning(png_ptr, error_message); + + else + png_chunk_error(png_ptr, error_message); + +# ifndef PNG_ERROR_TEXT_SUPPORTED + PNG_UNUSED(error_message) +# endif +} +#endif +#endif /* PNG_READ_SUPPORTED */ + +void /* PRIVATE */ +png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error) +{ +# ifndef PNG_WARNINGS_SUPPORTED + PNG_UNUSED(message) +# endif + + /* This is always supported, but for just read or just write it + * unconditionally does the right thing. + */ +# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) + if (png_ptr->mode & PNG_IS_READ_STRUCT) +# endif + +# ifdef PNG_READ_SUPPORTED + { + if (error < PNG_CHUNK_ERROR) + png_chunk_warning(png_ptr, message); + + else + png_chunk_benign_error(png_ptr, message); + } +# endif + +# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) + else if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) +# endif + +# ifdef PNG_WRITE_SUPPORTED + { + if (error < PNG_CHUNK_WRITE_ERROR) + png_app_warning(png_ptr, message); + + else + png_app_error(png_ptr, message); + } +# endif +} + +#ifdef PNG_ERROR_TEXT_SUPPORTED + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \ + defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \ + (defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) &&\ + defined(PNG_sCAL_SUPPORTED)) +PNG_FUNCTION(void, +png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN) +{ +# define fixed_message "fixed point overflow in " +# define fixed_message_ln ((sizeof fixed_message)-1) + int iin; + char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; + memcpy(msg, fixed_message, fixed_message_ln); + iin = 0; + if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) + { + msg[fixed_message_ln + iin] = name[iin]; + ++iin; + } + msg[fixed_message_ln + iin] = 0; + png_error(png_ptr, msg); +} +#endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This API only exists if ANSI-C style error handling is used, + * otherwise it is necessary for png_default_error to be overridden. + */ +jmp_buf* PNGAPI +png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn, + size_t jmp_buf_size) +{ + /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value + * and it must not change after that. Libpng doesn't care how big the + * buffer is, just that it doesn't change. + * + * If the buffer size is no *larger* than the size of jmp_buf when libpng is + * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0 + * semantics that this call will not fail. If the size is larger, however, + * the buffer is allocated and this may fail, causing the function to return + * NULL. + */ + if (png_ptr == NULL) + return NULL; + + if (png_ptr->jmp_buf_ptr == NULL) + { + png_ptr->jmp_buf_size = 0; /* not allocated */ + + if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local)) + png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; + + else + { + png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *, + png_malloc_warn(png_ptr, jmp_buf_size)); + + if (png_ptr->jmp_buf_ptr == NULL) + return NULL; /* new NULL return on OOM */ + + png_ptr->jmp_buf_size = jmp_buf_size; + } + } + + else /* Already allocated: check the size */ + { + size_t size = png_ptr->jmp_buf_size; + + if (size == 0) + { + size = (sizeof png_ptr->jmp_buf_local); + if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local) + { + /* This is an internal error in libpng: somehow we have been left + * with a stack allocated jmp_buf when the application regained + * control. It's always possible to fix this up, but for the moment + * this is a png_error because that makes it easy to detect. + */ + png_error(png_ptr, "Libpng jmp_buf still allocated"); + /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */ + } + } + + if (size != jmp_buf_size) + { + png_warning(png_ptr, "Application jmp_buf size changed"); + return NULL; /* caller will probably crash: no choice here */ + } + } + + /* Finally fill in the function, now we have a satisfactory buffer. It is + * valid to change the function on every call. + */ + png_ptr->longjmp_fn = longjmp_fn; + return png_ptr->jmp_buf_ptr; +} + +void /* PRIVATE */ +png_free_jmpbuf(png_structrp png_ptr) +{ + if (png_ptr != NULL) + { + jmp_buf *jb = png_ptr->jmp_buf_ptr; + + /* A size of 0 is used to indicate a local, stack, allocation of the + * pointer; used here and in png.c + */ + if (jb != NULL && png_ptr->jmp_buf_size > 0) + { + + /* This stuff is so that a failure to free the error control structure + * does not leave libpng in a state with no valid error handling: the + * free always succeeds, if there is an error it gets ignored. + */ + if (jb != &png_ptr->jmp_buf_local) + { + /* Make an internal, libpng, jmp_buf to return here */ + jmp_buf free_jmp_buf; + + if (!setjmp(free_jmp_buf)) + { + png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */ + png_ptr->jmp_buf_size = 0; /* stack allocation */ + png_ptr->longjmp_fn = longjmp; + png_free(png_ptr, jb); /* Return to setjmp on error */ + } + } + } + + /* *Always* cancel everything out: */ + png_ptr->jmp_buf_size = 0; + png_ptr->jmp_buf_ptr = NULL; + png_ptr->longjmp_fn = 0; + } +} +#endif + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static PNG_FUNCTION(void /* PRIVATE */, +png_default_error,(png_const_structrp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + /* Check on NULL only added in 1.5.4 */ + if (error_message != NULL && *error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + char error_number[16]; + for (offset = 0; offset<15; offset++) + { + error_number[offset] = error_message[offset + 1]; + if (error_message[offset] == ' ') + break; + } + + if ((offset > 1) && (offset < 15)) + { + error_number[offset - 1] = '\0'; + fprintf(stderr, "libpng error no. %s: %s", + error_number, error_message + offset + 1); + fprintf(stderr, PNG_STRING_NEWLINE); + } + + else + { + fprintf(stderr, "libpng error: %s, offset=%d", + error_message, offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +#endif + { + fprintf(stderr, "libpng error: %s", error_message ? error_message : + "undefined"); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + PNG_UNUSED(error_message) /* Make compiler happy */ +#endif + png_longjmp(png_ptr, 1); +} + +PNG_FUNCTION(void,PNGAPI +png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) +{ +#ifdef PNG_SETJMP_SUPPORTED + if (png_ptr && png_ptr->longjmp_fn && png_ptr->jmp_buf_ptr) + png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val); +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(val) +#endif + + /* If control reaches this point, png_longjmp() must not return. The only + * choice is to terminate the whole process (or maybe the thread); to do + * this the ANSI-C abort() function is used unless a different method is + * implemented by overriding the default configuration setting for + * PNG_ABORT (see scripts/pnglibconf.dfa). + * + * API change: prior to 1.7.0 PNG_ABORT was invoked as a function type macro + * with no arguments 'PNG_ABORT();', in 1.7.0 this is changed to a simple + * macro that is defined in the configuration. + */ + PNG_ABORT +} + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*warning_message == PNG_LITERAL_SHARP) + { + int offset; + char warning_number[16]; + for (offset = 0; offset < 15; offset++) + { + warning_number[offset] = warning_message[offset + 1]; + if (warning_message[offset] == ' ') + break; + } + + if ((offset > 1) && (offset < 15)) + { + warning_number[offset + 1] = '\0'; + fprintf(stderr, "libpng warning no. %s: %s", + warning_number, warning_message + offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + + else + { + fprintf(stderr, "libpng warning: %s", + warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +# endif + + { + fprintf(stderr, "libpng warning: %s", warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + PNG_UNUSED(warning_message) /* Make compiler happy */ +#endif + PNG_UNUSED(png_ptr) /* Make compiler happy */ +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called when the application wants to use another method + * of handling errors and warnings. Note that the error function MUST NOT + * return to the calling routine or serious problems will occur. The return + * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1) + */ +void PNGAPI +png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + png_ptr->warning_fn = warning_fn; +#else + PNG_UNUSED(warning_fn) +#endif +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void PNGAPI +png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode) +{ + if (png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS | + PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif + +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + /* Currently the above both depend on SETJMP_SUPPORTED, however it would be + * possible to implement without setjmp support just so long as there is some + * way to handle the error return here: + */ +PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI +png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), + PNG_NORETURN) +{ + const png_const_structrp png_ptr = png_nonconst_ptr; + png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); + + /* An error is always logged here, overwriting anything (typically a warning) + * that is already there: + */ + if (image != NULL) + { + png_safecat(image->message, (sizeof image->message), 0, error_message); + image->warning_or_error |= PNG_IMAGE_ERROR; + + /* Retrieve the jmp_buf from within the png_control, making this work for + * C++ compilation too is pretty tricky: C++ wants a pointer to the first + * element of a jmp_buf, but C doesn't tell us the type of that. + */ + if (image->opaque != NULL && image->opaque->error_buf != NULL) + longjmp(png_control_jmp_buf(image->opaque), 1); + + /* Missing longjmp buffer, the following is to help debugging: */ + { + size_t pos = png_safecat(image->message, (sizeof image->message), 0, + "bad longjmp: "); + png_safecat(image->message, (sizeof image->message), pos, + error_message); + } + } + + /* Here on an internal programming error. */ + abort(); +} + +#ifdef PNG_WARNINGS_SUPPORTED +void /* PRIVATE */ PNGCBAPI +png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message) +{ + const png_const_structrp png_ptr = png_nonconst_ptr; + png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); + + /* A warning is only logged if there is no prior warning or error. */ + if (image->warning_or_error == 0) + { + png_safecat(image->message, (sizeof image->message), 0, warning_message); + image->warning_or_error |= PNG_IMAGE_WARNING; + } +} +#endif + +int /* PRIVATE */ +png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg) +{ + volatile png_imagep image = image_in; + volatile int result; + volatile png_voidp saved_error_buf; + jmp_buf safe_jmpbuf; + + /* Safely execute function(arg) with png_error returning to this function. */ + saved_error_buf = image->opaque->error_buf; + result = setjmp(safe_jmpbuf) == 0; + + if (result != 0) + { + + image->opaque->error_buf = safe_jmpbuf; + result = function(arg); + } + + image->opaque->error_buf = saved_error_buf; + + /* And do the cleanup prior to any failure return. */ + if (result == 0) + png_image_free(image); + + return result; +} +#endif /* SIMPLIFIED READ/WRITE */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngget.c b/ext/libpng17/pngget.c similarity index 95% rename from ext/libpng16/pngget.c rename to ext/libpng17/pngget.c index 80ab055dca..1db8041995 100644 --- a/ext/libpng16/pngget.c +++ b/ext/libpng17/pngget.c @@ -1,1177 +1,1199 @@ - -/* pngget.c - retrieval of values from info struct - * - * Last changed in libpng 1.6.1 [March 28, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - */ - -#include "pngpriv.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -png_uint_32 PNGAPI -png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr, - png_uint_32 flag) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->valid & flag); - - return(0); -} - -png_size_t PNGAPI -png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->rowbytes); - - return(0); -} - -#ifdef PNG_INFO_IMAGE_SUPPORTED -png_bytepp PNGAPI -png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->row_pointers); - - return(0); -} -#endif - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Easy access to info, added in libpng-0.99 */ -png_uint_32 PNGAPI -png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return info_ptr->width; - - return (0); -} - -png_uint_32 PNGAPI -png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return info_ptr->height; - - return (0); -} - -png_byte PNGAPI -png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return info_ptr->bit_depth; - - return (0); -} - -png_byte PNGAPI -png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return info_ptr->color_type; - - return (0); -} - -png_byte PNGAPI -png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return info_ptr->filter_type; - - return (0); -} - -png_byte PNGAPI -png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return info_ptr->interlace_type; - - return (0); -} - -png_byte PNGAPI -png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return info_ptr->compression_type; - - return (0); -} - -png_uint_32 PNGAPI -png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp - info_ptr) -{ -#ifdef PNG_pHYs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) - { - png_debug1(1, "in %s retrieval function", - "png_get_x_pixels_per_meter"); - - if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) - return (info_ptr->x_pixels_per_unit); - } -#endif - - return (0); -} - -png_uint_32 PNGAPI -png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp - info_ptr) -{ -#ifdef PNG_pHYs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) - { - png_debug1(1, "in %s retrieval function", - "png_get_y_pixels_per_meter"); - - if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) - return (info_ptr->y_pixels_per_unit); - } -#endif - - return (0); -} - -png_uint_32 PNGAPI -png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ -#ifdef PNG_pHYs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) - { - png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); - - if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER && - info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit) - return (info_ptr->x_pixels_per_unit); - } -#endif - - return (0); -} - -#ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp - info_ptr) -{ -#ifdef PNG_READ_pHYs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) - { - png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); - - if (info_ptr->x_pixels_per_unit != 0) - return ((float)((float)info_ptr->y_pixels_per_unit - /(float)info_ptr->x_pixels_per_unit)); - } -#else - PNG_UNUSED(png_ptr) - PNG_UNUSED(info_ptr) -#endif - - return ((float)0.0); -} -#endif - -#ifdef PNG_FIXED_POINT_SUPPORTED -png_fixed_point PNGAPI -png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr, - png_const_inforp info_ptr) -{ -#ifdef PNG_READ_pHYs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) - && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 - && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX - && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX) - { - png_fixed_point res; - - png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed"); - - /* The following casts work because a PNG 4 byte integer only has a valid - * range of 0..2^31-1; otherwise the cast might overflow. - */ - if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1, - (png_int_32)info_ptr->x_pixels_per_unit)) - return res; - } -#else - PNG_UNUSED(png_ptr) - PNG_UNUSED(info_ptr) -#endif - - return 0; -} -#endif - -png_int_32 PNGAPI -png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ -#ifdef PNG_oFFs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) - { - png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); - - if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) - return (info_ptr->x_offset); - } -#endif - - return (0); -} - -png_int_32 PNGAPI -png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ -#ifdef PNG_oFFs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) - { - png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); - - if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) - return (info_ptr->y_offset); - } -#endif - - return (0); -} - -png_int_32 PNGAPI -png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ -#ifdef PNG_oFFs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) - { - png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels"); - - if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) - return (info_ptr->x_offset); - } -#endif - - return (0); -} - -png_int_32 PNGAPI -png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ -#ifdef PNG_oFFs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) - { - png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels"); - - if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) - return (info_ptr->y_offset); - } -#endif - - return (0); -} - -#ifdef PNG_INCH_CONVERSIONS_SUPPORTED -static png_uint_32 -ppi_from_ppm(png_uint_32 ppm) -{ -#if 0 - /* The conversion is *(2.54/100), in binary (32 digits): - * .00000110100000001001110101001001 - */ - png_uint_32 t1001, t1101; - ppm >>= 1; /* .1 */ - t1001 = ppm + (ppm >> 3); /* .1001 */ - t1101 = t1001 + (ppm >> 1); /* .1101 */ - ppm >>= 20; /* .000000000000000000001 */ - t1101 += t1101 >> 15; /* .1101000000000001101 */ - t1001 >>= 11; /* .000000000001001 */ - t1001 += t1001 >> 12; /* .000000000001001000000001001 */ - ppm += t1001; /* .000000000001001000001001001 */ - ppm += t1101; /* .110100000001001110101001001 */ - return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */ -#else - /* The argument is a PNG unsigned integer, so it is not permitted - * to be bigger than 2^31. - */ - png_fixed_point result; - if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, - 5000)) - return result; - - /* Overflow. */ - return 0; -#endif -} - -png_uint_32 PNGAPI -png_get_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr)); -} - -png_uint_32 PNGAPI -png_get_x_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr)); -} - -png_uint_32 PNGAPI -png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr)); -} - -#ifdef PNG_FIXED_POINT_SUPPORTED -static png_fixed_point -png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns) -{ - /* Convert from metres * 1,000,000 to inches * 100,000, meters to - * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. - * Notice that this can overflow - a warning is output and 0 is - * returned. - */ - return png_muldiv_warn(png_ptr, microns, 500, 127); -} - -png_fixed_point PNGAPI -png_get_x_offset_inches_fixed(png_const_structrp png_ptr, - png_const_inforp info_ptr) -{ - return png_fixed_inches_from_microns(png_ptr, - png_get_x_offset_microns(png_ptr, info_ptr)); -} -#endif - -#ifdef PNG_FIXED_POINT_SUPPORTED -png_fixed_point PNGAPI -png_get_y_offset_inches_fixed(png_const_structrp png_ptr, - png_const_inforp info_ptr) -{ - return png_fixed_inches_from_microns(png_ptr, - png_get_y_offset_microns(png_ptr, info_ptr)); -} -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_x_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - /* To avoid the overflow do the conversion directly in floating - * point. - */ - return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937); -} -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_y_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - /* To avoid the overflow do the conversion directly in floating - * point. - */ - return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937); -} -#endif - -#ifdef PNG_pHYs_SUPPORTED -png_uint_32 PNGAPI -png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr, - png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) -{ - png_uint_32 retval = 0; - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) - { - png_debug1(1, "in %s retrieval function", "pHYs"); - - if (res_x != NULL) - { - *res_x = info_ptr->x_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - - if (res_y != NULL) - { - *res_y = info_ptr->y_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - - if (unit_type != NULL) - { - *unit_type = (int)info_ptr->phys_unit_type; - retval |= PNG_INFO_pHYs; - - if (*unit_type == 1) - { - if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); - if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); - } - } - } - - return (retval); -} -#endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ - -/* png_get_channels really belongs in here, too, but it's been around longer */ - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - - -png_byte PNGAPI -png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->channels); - - return (0); -} - -#ifdef PNG_READ_SUPPORTED -png_const_bytep PNGAPI -png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->signature); - - return (NULL); -} -#endif - -#ifdef PNG_bKGD_SUPPORTED -png_uint_32 PNGAPI -png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, - png_color_16p *background) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) - && background != NULL) - { - png_debug1(1, "in %s retrieval function", "bKGD"); - - *background = &(info_ptr->background); - return (PNG_INFO_bKGD); - } - - return (0); -} -#endif - -#ifdef PNG_cHRM_SUPPORTED -/* The XYZ APIs were added in 1.5.5 to take advantage of the code added at the - * same time to correct the rgb grayscale coefficient defaults obtained from the - * cHRM chunk in 1.5.4 - */ -# ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, - double *white_x, double *white_y, double *red_x, double *red_y, - double *green_x, double *green_y, double *blue_x, double *blue_y) -{ - /* Quiet API change: this code used to only return the end points if a cHRM - * chunk was present, but the end points can also come from iCCP or sRGB - * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and - * the png_set_ APIs merely check that set end points are mutually - * consistent. - */ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) - { - png_debug1(1, "in %s retrieval function", "cHRM"); - - if (white_x != NULL) - *white_x = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.whitex, "cHRM white X"); - if (white_y != NULL) - *white_y = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y"); - if (red_x != NULL) - *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx, - "cHRM red X"); - if (red_y != NULL) - *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy, - "cHRM red Y"); - if (green_x != NULL) - *green_x = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.greenx, "cHRM green X"); - if (green_y != NULL) - *green_y = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y"); - if (blue_x != NULL) - *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex, - "cHRM blue X"); - if (blue_y != NULL) - *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey, - "cHRM blue Y"); - return (PNG_INFO_cHRM); - } - - return (0); -} - -png_uint_32 PNGAPI -png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr, - double *red_X, double *red_Y, double *red_Z, double *green_X, - double *green_Y, double *green_Z, double *blue_X, double *blue_Y, - double *blue_Z) -{ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) - { - png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)"); - - if (red_X != NULL) - *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X, - "cHRM red X"); - if (red_Y != NULL) - *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y, - "cHRM red Y"); - if (red_Z != NULL) - *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z, - "cHRM red Z"); - if (green_X != NULL) - *green_X = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X"); - if (green_Y != NULL) - *green_Y = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y"); - if (green_Z != NULL) - *green_Z = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z"); - if (blue_X != NULL) - *blue_X = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X"); - if (blue_Y != NULL) - *blue_Y = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y"); - if (blue_Z != NULL) - *blue_Z = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z"); - return (PNG_INFO_cHRM); - } - - return (0); -} -# endif - -# ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *int_red_X, png_fixed_point *int_red_Y, - png_fixed_point *int_red_Z, png_fixed_point *int_green_X, - png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, - png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, - png_fixed_point *int_blue_Z) -{ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) - { - png_debug1(1, "in %s retrieval function", "cHRM_XYZ"); - - if (int_red_X != NULL) - *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X; - if (int_red_Y != NULL) - *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y; - if (int_red_Z != NULL) - *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z; - if (int_green_X != NULL) - *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X; - if (int_green_Y != NULL) - *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y; - if (int_green_Z != NULL) - *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z; - if (int_blue_X != NULL) - *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X; - if (int_blue_Y != NULL) - *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y; - if (int_blue_Z != NULL) - *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z; - return (PNG_INFO_cHRM); - } - - return (0); -} - -png_uint_32 PNGAPI -png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, - png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, - png_fixed_point *blue_x, png_fixed_point *blue_y) -{ - png_debug1(1, "in %s retrieval function", "cHRM"); - - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) - { - if (white_x != NULL) - *white_x = info_ptr->colorspace.end_points_xy.whitex; - if (white_y != NULL) - *white_y = info_ptr->colorspace.end_points_xy.whitey; - if (red_x != NULL) - *red_x = info_ptr->colorspace.end_points_xy.redx; - if (red_y != NULL) - *red_y = info_ptr->colorspace.end_points_xy.redy; - if (green_x != NULL) - *green_x = info_ptr->colorspace.end_points_xy.greenx; - if (green_y != NULL) - *green_y = info_ptr->colorspace.end_points_xy.greeny; - if (blue_x != NULL) - *blue_x = info_ptr->colorspace.end_points_xy.bluex; - if (blue_y != NULL) - *blue_y = info_ptr->colorspace.end_points_xy.bluey; - return (PNG_INFO_cHRM); - } - - return (0); -} -# endif -#endif - -#ifdef PNG_gAMA_SUPPORTED -# ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *file_gamma) -{ - png_debug1(1, "in %s retrieval function", "gAMA"); - - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) && - file_gamma != NULL) - { - *file_gamma = info_ptr->colorspace.gamma; - return (PNG_INFO_gAMA); - } - - return (0); -} -# endif - -# ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr, - double *file_gamma) -{ - png_debug1(1, "in %s retrieval function", "gAMA(float)"); - - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) && - file_gamma != NULL) - { - *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma, - "png_get_gAMA"); - return (PNG_INFO_gAMA); - } - - return (0); -} -# endif -#endif - -#ifdef PNG_sRGB_SUPPORTED -png_uint_32 PNGAPI -png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr, - int *file_srgb_intent) -{ - png_debug1(1, "in %s retrieval function", "sRGB"); - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) - && file_srgb_intent != NULL) - { - *file_srgb_intent = info_ptr->colorspace.rendering_intent; - return (PNG_INFO_sRGB); - } - - return (0); -} -#endif - -#ifdef PNG_iCCP_SUPPORTED -png_uint_32 PNGAPI -png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, - png_charpp name, int *compression_type, - png_bytepp profile, png_uint_32 *proflen) -{ - png_debug1(1, "in %s retrieval function", "iCCP"); - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) - && name != NULL && compression_type != NULL && profile != NULL && - proflen != NULL) - { - *name = info_ptr->iccp_name; - *profile = info_ptr->iccp_profile; - *proflen = png_get_uint_32(info_ptr->iccp_profile); - /* This is somewhat irrelevant since the profile data returned has - * actually been uncompressed. - */ - *compression_type = PNG_COMPRESSION_TYPE_BASE; - return (PNG_INFO_iCCP); - } - - return (0); -} -#endif - -#ifdef PNG_sPLT_SUPPORTED -int PNGAPI -png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr, - png_sPLT_tpp spalettes) -{ - if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) - { - *spalettes = info_ptr->splt_palettes; - return info_ptr->splt_palettes_num; - } - - return (0); -} -#endif - -#ifdef PNG_hIST_SUPPORTED -png_uint_32 PNGAPI -png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr, - png_uint_16p *hist) -{ - png_debug1(1, "in %s retrieval function", "hIST"); - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) - && hist != NULL) - { - *hist = info_ptr->hist; - return (PNG_INFO_hIST); - } - - return (0); -} -#endif - -png_uint_32 PNGAPI -png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr, - png_uint_32 *width, png_uint_32 *height, int *bit_depth, - int *color_type, int *interlace_type, int *compression_type, - int *filter_type) -{ - png_debug1(1, "in %s retrieval function", "IHDR"); - - if (png_ptr == NULL || info_ptr == NULL || width == NULL || - height == NULL || bit_depth == NULL || color_type == NULL) - return (0); - - *width = info_ptr->width; - *height = info_ptr->height; - *bit_depth = info_ptr->bit_depth; - *color_type = info_ptr->color_type; - - if (compression_type != NULL) - *compression_type = info_ptr->compression_type; - - if (filter_type != NULL) - *filter_type = info_ptr->filter_type; - - if (interlace_type != NULL) - *interlace_type = info_ptr->interlace_type; - - /* This is redundant if we can be sure that the info_ptr values were all - * assigned in png_set_IHDR(). We do the check anyhow in case an - * application has ignored our advice not to mess with the members - * of info_ptr directly. - */ - png_check_IHDR(png_ptr, info_ptr->width, info_ptr->height, - info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, - info_ptr->compression_type, info_ptr->filter_type); - - return (1); -} - -#ifdef PNG_oFFs_SUPPORTED -png_uint_32 PNGAPI -png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr, - png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) -{ - png_debug1(1, "in %s retrieval function", "oFFs"); - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) - && offset_x != NULL && offset_y != NULL && unit_type != NULL) - { - *offset_x = info_ptr->x_offset; - *offset_y = info_ptr->y_offset; - *unit_type = (int)info_ptr->offset_unit_type; - return (PNG_INFO_oFFs); - } - - return (0); -} -#endif - -#ifdef PNG_pCAL_SUPPORTED -png_uint_32 PNGAPI -png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, - png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, - png_charp *units, png_charpp *params) -{ - png_debug1(1, "in %s retrieval function", "pCAL"); - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) - && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && - nparams != NULL && units != NULL && params != NULL) - { - *purpose = info_ptr->pcal_purpose; - *X0 = info_ptr->pcal_X0; - *X1 = info_ptr->pcal_X1; - *type = (int)info_ptr->pcal_type; - *nparams = (int)info_ptr->pcal_nparams; - *units = info_ptr->pcal_units; - *params = info_ptr->pcal_params; - return (PNG_INFO_pCAL); - } - - return (0); -} -#endif - -#ifdef PNG_sCAL_SUPPORTED -# ifdef PNG_FIXED_POINT_SUPPORTED -# if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ - defined(PNG_FLOATING_POINT_SUPPORTED) -png_uint_32 PNGAPI -png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, - int *unit, png_fixed_point *width, png_fixed_point *height) -{ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sCAL)) - { - *unit = info_ptr->scal_unit; - /*TODO: make this work without FP support; the API is currently eliminated - * if neither floating point APIs nor internal floating point arithmetic - * are enabled. - */ - *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); - *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), - "sCAL height"); - return (PNG_INFO_sCAL); - } - - return(0); -} -# endif /* FLOATING_ARITHMETIC */ -# endif /* FIXED_POINT */ -# ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr, - int *unit, double *width, double *height) -{ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sCAL)) - { - *unit = info_ptr->scal_unit; - *width = atof(info_ptr->scal_s_width); - *height = atof(info_ptr->scal_s_height); - return (PNG_INFO_sCAL); - } - - return(0); -} -# endif /* FLOATING POINT */ -png_uint_32 PNGAPI -png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr, - int *unit, png_charpp width, png_charpp height) -{ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sCAL)) - { - *unit = info_ptr->scal_unit; - *width = info_ptr->scal_s_width; - *height = info_ptr->scal_s_height; - return (PNG_INFO_sCAL); - } - - return(0); -} -#endif /* sCAL */ - -#ifdef PNG_pHYs_SUPPORTED -png_uint_32 PNGAPI -png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr, - png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) -{ - png_uint_32 retval = 0; - - png_debug1(1, "in %s retrieval function", "pHYs"); - - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_pHYs)) - { - if (res_x != NULL) - { - *res_x = info_ptr->x_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - - if (res_y != NULL) - { - *res_y = info_ptr->y_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - - if (unit_type != NULL) - { - *unit_type = (int)info_ptr->phys_unit_type; - retval |= PNG_INFO_pHYs; - } - } - - return (retval); -} -#endif /* pHYs */ - -png_uint_32 PNGAPI -png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr, - png_colorp *palette, int *num_palette) -{ - png_debug1(1, "in %s retrieval function", "PLTE"); - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) - && palette != NULL) - { - *palette = info_ptr->palette; - *num_palette = info_ptr->num_palette; - png_debug1(3, "num_palette = %d", *num_palette); - return (PNG_INFO_PLTE); - } - - return (0); -} - -#ifdef PNG_sBIT_SUPPORTED -png_uint_32 PNGAPI -png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, - png_color_8p *sig_bit) -{ - png_debug1(1, "in %s retrieval function", "sBIT"); - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) - && sig_bit != NULL) - { - *sig_bit = &(info_ptr->sig_bit); - return (PNG_INFO_sBIT); - } - - return (0); -} -#endif - -#ifdef PNG_TEXT_SUPPORTED -int PNGAPI -png_get_text(png_const_structrp png_ptr, png_inforp info_ptr, - png_textp *text_ptr, int *num_text) -{ - if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) - { - png_debug1(1, "in 0x%lx retrieval function", - (unsigned long)png_ptr->chunk_name); - - if (text_ptr != NULL) - *text_ptr = info_ptr->text; - - if (num_text != NULL) - *num_text = info_ptr->num_text; - - return info_ptr->num_text; - } - - if (num_text != NULL) - *num_text = 0; - - return(0); -} -#endif - -#ifdef PNG_tIME_SUPPORTED -png_uint_32 PNGAPI -png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr, - png_timep *mod_time) -{ - png_debug1(1, "in %s retrieval function", "tIME"); - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) - && mod_time != NULL) - { - *mod_time = &(info_ptr->mod_time); - return (PNG_INFO_tIME); - } - - return (0); -} -#endif - -#ifdef PNG_tRNS_SUPPORTED -png_uint_32 PNGAPI -png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr, - png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) -{ - png_uint_32 retval = 0; - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) - { - png_debug1(1, "in %s retrieval function", "tRNS"); - - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (trans_alpha != NULL) - { - *trans_alpha = info_ptr->trans_alpha; - retval |= PNG_INFO_tRNS; - } - - if (trans_color != NULL) - *trans_color = &(info_ptr->trans_color); - } - - else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ - { - if (trans_color != NULL) - { - *trans_color = &(info_ptr->trans_color); - retval |= PNG_INFO_tRNS; - } - - if (trans_alpha != NULL) - *trans_alpha = NULL; - } - - if (num_trans != NULL) - { - *num_trans = info_ptr->num_trans; - retval |= PNG_INFO_tRNS; - } - } - - return (retval); -} -#endif - -#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -int PNGAPI -png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr, - png_unknown_chunkpp unknowns) -{ - if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) - { - *unknowns = info_ptr->unknown_chunks; - return info_ptr->unknown_chunks_num; - } - - return (0); -} -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -png_byte PNGAPI -png_get_rgb_to_gray_status (png_const_structrp png_ptr) -{ - return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0); -} -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -png_voidp PNGAPI -png_get_user_chunk_ptr(png_const_structrp png_ptr) -{ - return (png_ptr ? png_ptr->user_chunk_ptr : NULL); -} -#endif - -png_size_t PNGAPI -png_get_compression_buffer_size(png_const_structrp png_ptr) -{ - if (png_ptr == NULL) - return 0; - -# ifdef PNG_WRITE_SUPPORTED - if (png_ptr->mode & PNG_IS_READ_STRUCT) -# endif - { -# ifdef PNG_SEQUENTIAL_READ_SUPPORTED - return png_ptr->IDAT_read_size; -# else - return PNG_IDAT_READ_SIZE; -# endif - } - -# ifdef PNG_WRITE_SUPPORTED - else - return png_ptr->zbuffer_size; -# endif -} - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -/* These functions were added to libpng 1.2.6 and were enabled - * by default in libpng-1.4.0 */ -png_uint_32 PNGAPI -png_get_user_width_max (png_const_structrp png_ptr) -{ - return (png_ptr ? png_ptr->user_width_max : 0); -} - -png_uint_32 PNGAPI -png_get_user_height_max (png_const_structrp png_ptr) -{ - return (png_ptr ? png_ptr->user_height_max : 0); -} - -/* This function was added to libpng 1.4.0 */ -png_uint_32 PNGAPI -png_get_chunk_cache_max (png_const_structrp png_ptr) -{ - return (png_ptr ? png_ptr->user_chunk_cache_max : 0); -} - -/* This function was added to libpng 1.4.1 */ -png_alloc_size_t PNGAPI -png_get_chunk_malloc_max (png_const_structrp png_ptr) -{ - return (png_ptr ? png_ptr->user_chunk_malloc_max : 0); -} -#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ - -/* These functions were added to libpng 1.4.0 */ -#ifdef PNG_IO_STATE_SUPPORTED -png_uint_32 PNGAPI -png_get_io_state (png_const_structrp png_ptr) -{ - return png_ptr->io_state; -} - -png_uint_32 PNGAPI -png_get_io_chunk_type (png_const_structrp png_ptr) -{ - return png_ptr->chunk_name; -} -#endif /* ?PNG_IO_STATE_SUPPORTED */ - -#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED -# ifdef PNG_GET_PALETTE_MAX_SUPPORTED -int PNGAPI -png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return png_ptr->num_palette_max; - - return (-1); -} -# endif -#endif - -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ + +/* pngget.c - retrieval of values from info struct + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +png_uint_32 PNGAPI +png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + + return(0); +} + +png_size_t PNGAPI +png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + + return(0); +} + +#ifdef PNG_INFO_IMAGE_SUPPORTED +png_bytepp PNGAPI +png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->width; + + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->height; + + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->bit_depth; + + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->color_type; + + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->filter_type; + + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->interlace_type; + + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->compression_type; + + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp + info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", + "png_get_x_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return (info_ptr->x_pixels_per_unit); + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp + info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", + "png_get_y_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return (info_ptr->y_pixels_per_unit); + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER && + info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit) + return (info_ptr->x_pixels_per_unit); + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp + info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); + + if (info_ptr->x_pixels_per_unit != 0) + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return ((float)0.0); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr, + png_const_inforp info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) + && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 + && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX + && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX) + { + png_fixed_point res; + + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed"); + + /* The following casts work because a PNG 4 byte integer only has a valid + * range of 0..2^31-1; otherwise the cast might overflow. + */ + if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1, + (png_int_32)info_ptr->x_pixels_per_unit)) + return res; + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return 0; +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) + return (info_ptr->x_offset); + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) + return (info_ptr->y_offset); + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->x_offset); + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->y_offset); + } +#else + PNG_UNUSED(png_ptr) + PNG_UNUSED(info_ptr) +#endif + + return (0); +} + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED +static png_uint_32 +ppi_from_ppm(png_uint_32 ppm) +{ +#if 0 + /* The conversion is *(2.54/100), in binary (32 digits): + * .00000110100000001001110101001001 + */ + png_uint_32 t1001, t1101; + ppm >>= 1; /* .1 */ + t1001 = ppm + (ppm >> 3); /* .1001 */ + t1101 = t1001 + (ppm >> 1); /* .1101 */ + ppm >>= 20; /* .000000000000000000001 */ + t1101 += t1101 >> 15; /* .1101000000000001101 */ + t1001 >>= 11; /* .000000000001001 */ + t1001 += t1001 >> 12; /* .000000000001001000000001001 */ + ppm += t1001; /* .000000000001001000001001001 */ + ppm += t1101; /* .110100000001001110101001001 */ + return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */ +#else + /* The argument is a PNG unsigned integer, so it is not permitted + * to be bigger than 2^31. + */ + png_fixed_point result; + if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, + 5000)) + return result; + + /* Overflow. */ + return 0; +#endif +} + +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr)); +} + +#ifdef PNG_FIXED_POINT_SUPPORTED +static png_fixed_point +png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns) +{ + /* Convert from metres * 1,000,000 to inches * 100,000, meters to + * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. + * Notice that this can overflow - a warning is output and 0 is + * returned. + */ + return png_muldiv_warn(png_ptr, microns, 500, 127); +} + +png_fixed_point PNGAPI +png_get_x_offset_inches_fixed(png_const_structrp png_ptr, + png_const_inforp info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_x_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_y_offset_inches_fixed(png_const_structrp png_ptr, + png_const_inforp info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_y_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_x_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_y_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + + if (*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + + +png_byte PNGAPI +png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + + return (0); +} + +#ifdef PNG_READ_SUPPORTED +png_const_bytep PNGAPI +png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + + return (NULL); +} +#endif + +#ifdef PNG_bKGD_SUPPORTED +png_uint_32 PNGAPI +png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function", "bKGD"); + + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + + return (0); +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +/* The XYZ APIs were added in 1.5.5 to take advantage of the code added at the + * same time to correct the rgb grayscale coefficient defaults obtained from the + * cHRM chunk in 1.5.4 + */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y) +{ + /* Quiet API change: this code used to only return the end points if a cHRM + * chunk was present, but the end points can also come from iCCP or sRGB + * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and + * the png_set_ APIs merely check that set end points are mutually + * consistent. + */ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) + { + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (white_x != NULL) + *white_x = png_float(png_ptr, + info_ptr->colorspace.end_points_xy.whitex, "cHRM white X"); + if (white_y != NULL) + *white_y = png_float(png_ptr, + info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y"); + if (red_x != NULL) + *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx, + "cHRM red X"); + if (red_y != NULL) + *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy, + "cHRM red Y"); + if (green_x != NULL) + *green_x = png_float(png_ptr, + info_ptr->colorspace.end_points_xy.greenx, "cHRM green X"); + if (green_y != NULL) + *green_y = png_float(png_ptr, + info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y"); + if (blue_x != NULL) + *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex, + "cHRM blue X"); + if (blue_y != NULL) + *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey, + "cHRM blue Y"); + return (PNG_INFO_cHRM); + } + + return (0); +} + +png_uint_32 PNGAPI +png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr, + double *red_X, double *red_Y, double *red_Z, double *green_X, + double *green_Y, double *green_Z, double *blue_X, double *blue_Y, + double *blue_Z) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) + { + png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)"); + + if (red_X != NULL) + *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X, + "cHRM red X"); + if (red_Y != NULL) + *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y, + "cHRM red Y"); + if (red_Z != NULL) + *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z, + "cHRM red Z"); + if (green_X != NULL) + *green_X = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X"); + if (green_Y != NULL) + *green_Y = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y"); + if (green_Z != NULL) + *green_Z = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z"); + if (blue_X != NULL) + *blue_X = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X"); + if (blue_Y != NULL) + *blue_Y = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y"); + if (blue_Z != NULL) + *blue_Z = png_float(png_ptr, + info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z"); + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) + { + png_debug1(1, "in %s retrieval function", "cHRM_XYZ"); + + if (int_red_X != NULL) + *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X; + if (int_red_Y != NULL) + *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y; + if (int_red_Z != NULL) + *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z; + if (int_green_X != NULL) + *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X; + if (int_green_Y != NULL) + *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y; + if (int_green_Z != NULL) + *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z; + if (int_blue_X != NULL) + *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X; + if (int_blue_Y != NULL) + *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y; + if (int_blue_Z != NULL) + *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z; + return (PNG_INFO_cHRM); + } + + return (0); +} + +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)) + { + if (white_x != NULL) + *white_x = info_ptr->colorspace.end_points_xy.whitex; + if (white_y != NULL) + *white_y = info_ptr->colorspace.end_points_xy.whitey; + if (red_x != NULL) + *red_x = info_ptr->colorspace.end_points_xy.redx; + if (red_y != NULL) + *red_y = info_ptr->colorspace.end_points_xy.redy; + if (green_x != NULL) + *green_x = info_ptr->colorspace.end_points_xy.greenx; + if (green_y != NULL) + *green_y = info_ptr->colorspace.end_points_xy.greeny; + if (blue_x != NULL) + *blue_x = info_ptr->colorspace.end_points_xy.bluex; + if (blue_y != NULL) + *blue_y = info_ptr->colorspace.end_points_xy.bluey; + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_fixed_point *file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) && + file_gamma != NULL) + { + *file_gamma = info_ptr->colorspace.gamma; + return (PNG_INFO_gAMA); + } + + return (0); +} +# endif + +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr, + double *file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA(float)"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) && + file_gamma != NULL) + { + *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma, + "png_get_gAMA"); + return (PNG_INFO_gAMA); + } + + return (0); +} +# endif +#endif + +#ifdef PNG_sRGB_SUPPORTED +png_uint_32 PNGAPI +png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr, + int *file_srgb_intent) +{ + png_debug1(1, "in %s retrieval function", "sRGB"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + *file_srgb_intent = info_ptr->colorspace.rendering_intent; + return (PNG_INFO_sRGB); + } + + return (0); +} +#endif + +#ifdef PNG_iCCP_SUPPORTED +png_uint_32 PNGAPI +png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, + png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen) +{ + png_debug1(1, "in %s retrieval function", "iCCP"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && compression_type != NULL && profile != NULL && + proflen != NULL) + { + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + *proflen = png_get_uint_32(info_ptr->iccp_profile); + /* This is somewhat irrelevant since the profile data returned has + * actually been uncompressed. + */ + *compression_type = PNG_COMPRESSION_TYPE_BASE; + return (PNG_INFO_iCCP); + } + + return (0); +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +int PNGAPI +png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + { + *spalettes = info_ptr->splt_palettes; + return info_ptr->splt_palettes_num; + } + + return (0); +} +#endif + +#ifdef PNG_hIST_SUPPORTED +png_uint_32 PNGAPI +png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr, + png_uint_16p *hist) +{ + png_debug1(1, "in %s retrieval function", "hIST"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + + return (0); +} +#endif + +png_uint_32 PNGAPI +png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, + int *color_type, int *interlace_type, int *compression_type, + int *filter_type) +{ + png_debug1(1, "in %s retrieval function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL || width == NULL || + height == NULL || bit_depth == NULL || color_type == NULL) + return (0); + + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + *color_type = info_ptr->color_type; + + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* This is redundant if we can be sure that the info_ptr values were all + * assigned in png_set_IHDR(). We do the check anyhow in case an + * application has ignored our advice not to mess with the members + * of info_ptr directly. + */ + png_check_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + return (1); +} + +#ifdef PNG_oFFs_SUPPORTED +png_uint_32 PNGAPI +png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + png_debug1(1, "in %s retrieval function", "oFFs"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + + return (0); +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +png_uint_32 PNGAPI +png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + png_charp *units, png_charpp *params) +{ + png_debug1(1, "in %s retrieval function", "pCAL"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + + return (0); +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, + int *unit, png_fixed_point *width, png_fixed_point *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + /*TODO: make this work without FP support; the API is currently eliminated + * if neither floating point APIs nor internal floating point arithmetic + * are enabled. + */ + *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); + *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), + "sCAL height"); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FIXED_POINT */ + +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = atof(info_ptr->scal_s_width); + *height = atof(info_ptr->scal_s_height); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING POINT */ +# endif /* FLOATING_ARITHMETIC */ + +png_uint_32 PNGAPI +png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + + return(0); +} +#endif /* sCAL */ + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + + return (retval); +} +#endif /* pHYs */ + +png_uint_32 PNGAPI +png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr, + png_colorp *palette, int *num_palette) +{ + png_debug1(1, "in %s retrieval function", "PLTE"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d", *num_palette); + return (PNG_INFO_PLTE); + } + + return (0); +} + +#ifdef PNG_sBIT_SUPPORTED +png_uint_32 PNGAPI +png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, + png_color_8p *sig_bit) +{ + png_debug1(1, "in %s retrieval function", "sBIT"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + + return (0); +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +int PNGAPI +png_get_text(png_const_structrp png_ptr, png_inforp info_ptr, + png_textp *text_ptr, int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in 0x%lx retrieval function", + (unsigned long)png_ptr->chunk_name); + + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + + if (num_text != NULL) + *num_text = info_ptr->num_text; + + return info_ptr->num_text; + } + + if (num_text != NULL) + *num_text = 0; + + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +png_uint_32 PNGAPI +png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr, + png_timep *mod_time) +{ + png_debug1(1, "in %s retrieval function", "tIME"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + + return (0); +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +png_uint_32 PNGAPI +png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function", "tRNS"); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans_alpha != NULL) + { + *trans_alpha = info_ptr->trans_alpha; + retval |= PNG_INFO_tRNS; + } + + if (trans_color != NULL) + *trans_color = &(info_ptr->trans_color); + } + + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_color != NULL) + { + *trans_color = &(info_ptr->trans_color); + retval |= PNG_INFO_tRNS; + } + + if (trans_alpha != NULL) + *trans_alpha = NULL; + } + + if (num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + + return (retval); +} +#endif + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +int PNGAPI +png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + { + *unknowns = info_ptr->unknown_chunks; + return info_ptr->unknown_chunks_num; + } + + return (0); +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +png_byte PNGAPI +png_get_rgb_to_gray_status (png_const_structrp png_ptr) +{ + return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +png_voidp PNGAPI +png_get_user_chunk_ptr(png_const_structrp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_ptr : NULL); +} +#endif + +png_size_t PNGAPI +png_get_compression_buffer_size(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return 0; + +# ifdef PNG_WRITE_SUPPORTED + if (png_ptr->mode & PNG_IS_READ_STRUCT) +# endif + { +# ifdef PNG_SEQUENTIAL_READ_SUPPORTED + return png_ptr->IDAT_read_size; +# else + return PNG_IDAT_READ_SIZE; +# endif + } + +# ifdef PNG_WRITE_SUPPORTED + else + return png_ptr->zbuffer_size; +# endif +} + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* These functions were added to libpng 1.2.6 and were enabled + * by default in libpng-1.4.0 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_const_structrp png_ptr) +{ + return (png_ptr ? png_ptr->user_width_max : 0); +} + +png_uint_32 PNGAPI +png_get_user_height_max (png_const_structrp png_ptr) +{ + return (png_ptr ? png_ptr->user_height_max : 0); +} + +/* This function was added to libpng 1.4.0 */ +png_uint_32 PNGAPI +png_get_chunk_cache_max (png_const_structrp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_cache_max : 0); +} + +/* This function was added to libpng 1.4.1 */ +png_alloc_size_t PNGAPI +png_get_chunk_malloc_max (png_const_structrp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_malloc_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +/* These functions were added to libpng 1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +png_uint_32 PNGAPI +png_get_io_state (png_const_structrp png_ptr) +{ + return png_ptr->io_state; +} + +png_uint_32 PNGAPI +png_get_io_chunk_type (png_const_structrp png_ptr) +{ + return png_ptr->chunk_name; +} +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +int PNGAPI +png_get_palette_max(png_const_structrp png_ptr, png_const_inforp info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return png_ptr->num_palette_max; + + return (-1); +} +# endif +#endif + +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pnginfo.h b/ext/libpng17/pnginfo.h similarity index 97% rename from ext/libpng16/pnginfo.h rename to ext/libpng17/pnginfo.h index 683b7ea177..26bf26502c 100644 --- a/ext/libpng16/pnginfo.h +++ b/ext/libpng17/pnginfo.h @@ -1,260 +1,260 @@ - -/* pnginfo.h - header file for PNG reference library - * - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * Last changed in libpng 1.6.1 [March 28, 2013] - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - - /* png_info is a structure that holds the information in a PNG file so - * that the application can find out the characteristics of the image. - * If you are reading the file, this structure will tell you what is - * in the PNG file. If you are writing the file, fill in the information - * you want to put into the PNG file, using png_set_*() functions, then - * call png_write_info(). - * - * The names chosen should be very close to the PNG specification, so - * consult that document for information about the meaning of each field. - * - * With libpng < 0.95, it was only possible to directly set and read the - * the values in the png_info_struct, which meant that the contents and - * order of the values had to remain fixed. With libpng 0.95 and later, - * however, there are now functions that abstract the contents of - * png_info_struct from the application, so this makes it easier to use - * libpng with dynamic libraries, and even makes it possible to use - * libraries that don't have all of the libpng ancillary chunk-handing - * functionality. In libpng-1.5.0 this was moved into a separate private - * file that is not visible to applications. - * - * The following members may have allocated storage attached that should be - * cleaned up before the structure is discarded: palette, trans, text, - * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, - * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these - * are automatically freed when the info structure is deallocated, if they were - * allocated internally by libpng. This behavior can be changed by means - * of the png_data_freer() function. - * - * More allocation details: all the chunk-reading functions that - * change these members go through the corresponding png_set_* - * functions. A function to clear these members is available: see - * png_free_data(). The png_set_* functions do not depend on being - * able to point info structure members to any of the storage they are - * passed (they make their own copies), EXCEPT that the png_set_text - * functions use the same storage passed to them in the text_ptr or - * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns - * functions do not make their own copies. - */ -#ifndef PNGINFO_H -#define PNGINFO_H - -struct png_info_def -{ - /* The following are necessary for every PNG file */ - png_uint_32 width; /* width of image in pixels (from IHDR) */ - png_uint_32 height; /* height of image in pixels (from IHDR) */ - png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ - png_size_t rowbytes; /* bytes needed to hold an untransformed row */ - png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ - png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ - png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ - png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ - png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ - /* The following three should have been named *_method not *_type */ - png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ - png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ - png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - - /* The following are set by png_set_IHDR, called from the application on - * write, but the are never actually used by the write code. - */ - png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte spare_byte; /* to align the data, and for future use */ - -#ifdef PNG_READ_SUPPORTED - /* This is never set during write */ - png_byte signature[8]; /* magic bytes read by libpng from start of file */ -#endif - - /* The rest of the data is optional. If you are reading, check the - * valid field to see if the information in these are valid. If you - * are writing, set the valid field to those chunks you want written, - * and initialize the appropriate fields below. - */ - -#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) - /* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are - * defined. When COLORSPACE is switched on all the colorspace-defining - * chunks should be enabled, when GAMMA is switched on all the gamma-defining - * chunks should be enabled. If this is not done it becomes possible to read - * inconsistent PNG files and assign a probably incorrect interpretation to - * the information. (In other words, by carefully choosing which chunks to - * recognize the system configuration can select an interpretation for PNG - * files containing ambiguous data and this will result in inconsistent - * behavior between different libpng builds!) - */ - png_colorspace colorspace; -#endif - -#ifdef PNG_iCCP_SUPPORTED - /* iCCP chunk data. */ - png_charp iccp_name; /* profile name */ - png_bytep iccp_profile; /* International Color Consortium profile data */ - png_uint_32 iccp_proflen; /* ICC profile data length */ -#endif - -#ifdef PNG_TEXT_SUPPORTED - /* The tEXt, and zTXt chunks contain human-readable textual data in - * uncompressed, compressed, and optionally compressed forms, respectively. - * The data in "text" is an array of pointers to uncompressed, - * null-terminated C strings. Each chunk has a keyword that describes the - * textual data contained in that chunk. Keywords are not required to be - * unique, and the text string may be empty. Any number of text chunks may - * be in an image. - */ - int num_text; /* number of comments read or comments to write */ - int max_text; /* current size of text array */ - png_textp text; /* array of comments read or comments to write */ -#endif /* PNG_TEXT_SUPPORTED */ - -#ifdef PNG_tIME_SUPPORTED - /* The tIME chunk holds the last time the displayed image data was - * modified. See the png_time struct for the contents of this struct. - */ - png_time mod_time; -#endif - -#ifdef PNG_sBIT_SUPPORTED - /* The sBIT chunk specifies the number of significant high-order bits - * in the pixel data. Values are in the range [1, bit_depth], and are - * only specified for the channels in the pixel data. The contents of - * the low-order bits is not specified. Data is valid if - * (valid & PNG_INFO_sBIT) is non-zero. - */ - png_color_8 sig_bit; /* significant bits in color channels */ -#endif - -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ -defined(PNG_READ_BACKGROUND_SUPPORTED) - /* The tRNS chunk supplies transparency data for paletted images and - * other image types that don't need a full alpha channel. There are - * "num_trans" transparency values for a paletted image, stored in the - * same order as the palette colors, starting from index 0. Values - * for the data are in the range [0, 255], ranging from fully transparent - * to fully opaque, respectively. For non-paletted images, there is a - * single color specified that should be treated as fully transparent. - * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. - */ - png_bytep trans_alpha; /* alpha values for paletted image */ - png_color_16 trans_color; /* transparent color for non-palette image */ -#endif - -#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - /* The bKGD chunk gives the suggested image background color if the - * display program does not have its own background color and the image - * is needs to composited onto a background before display. The colors - * in "background" are normally in the same color space/depth as the - * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. - */ - png_color_16 background; -#endif - -#ifdef PNG_oFFs_SUPPORTED - /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards - * and downwards from the top-left corner of the display, page, or other - * application-specific co-ordinate space. See the PNG_OFFSET_ defines - * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. - */ - png_int_32 x_offset; /* x offset on page */ - png_int_32 y_offset; /* y offset on page */ - png_byte offset_unit_type; /* offset units type */ -#endif - -#ifdef PNG_pHYs_SUPPORTED - /* The pHYs chunk gives the physical pixel density of the image for - * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ - * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. - */ - png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ - png_uint_32 y_pixels_per_unit; /* vertical pixel density */ - png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ -#endif - -#ifdef PNG_hIST_SUPPORTED - /* The hIST chunk contains the relative frequency or importance of the - * various palette entries, so that a viewer can intelligently select a - * reduced-color palette, if required. Data is an array of "num_palette" - * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) - * is non-zero. - */ - png_uint_16p hist; -#endif - -#ifdef PNG_pCAL_SUPPORTED - /* The pCAL chunk describes a transformation between the stored pixel - * values and original physical data values used to create the image. - * The integer range [0, 2^bit_depth - 1] maps to the floating-point - * range given by [pcal_X0, pcal_X1], and are further transformed by a - * (possibly non-linear) transformation function given by "pcal_type" - * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ - * defines below, and the PNG-Group's PNG extensions document for a - * complete description of the transformations and how they should be - * implemented, and for a description of the ASCII parameter strings. - * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. - */ - png_charp pcal_purpose; /* pCAL chunk description string */ - png_int_32 pcal_X0; /* minimum value */ - png_int_32 pcal_X1; /* maximum value */ - png_charp pcal_units; /* Latin-1 string giving physical units */ - png_charpp pcal_params; /* ASCII strings containing parameter values */ - png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ - png_byte pcal_nparams; /* number of parameters given in pcal_params */ -#endif - -/* New members added in libpng-1.0.6 */ - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ - -#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED - /* Storage for unknown chunks that the library doesn't recognize. */ - png_unknown_chunkp unknown_chunks; - - /* The type of this field is limited by the type of - * png_struct::user_chunk_cache_max, else overflow can occur. - */ - int unknown_chunks_num; -#endif - -#ifdef PNG_sPLT_SUPPORTED - /* Data on sPLT chunks (there may be more than one). */ - png_sPLT_tp splt_palettes; - int splt_palettes_num; /* Match type returned by png_get API */ -#endif - -#ifdef PNG_sCAL_SUPPORTED - /* The sCAL chunk describes the actual physical dimensions of the - * subject matter of the graphic. The chunk contains a unit specification - * a byte value, and two ASCII strings representing floating-point - * values. The values are width and height corresponsing to one pixel - * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is - * non-zero. - */ - png_byte scal_unit; /* unit of physical scale */ - png_charp scal_s_width; /* string containing height */ - png_charp scal_s_height; /* string containing width */ -#endif - -#ifdef PNG_INFO_IMAGE_SUPPORTED - /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) - non-zero */ - /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ - png_bytepp row_pointers; /* the image bits */ -#endif - -}; -#endif /* PNGINFO_H */ + +/* pnginfo.h - header file for PNG reference library + * + * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.6.1 [March 28, 2013] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + + /* png_info is a structure that holds the information in a PNG file so + * that the application can find out the characteristics of the image. + * If you are reading the file, this structure will tell you what is + * in the PNG file. If you are writing the file, fill in the information + * you want to put into the PNG file, using png_set_*() functions, then + * call png_write_info(). + * + * The names chosen should be very close to the PNG specification, so + * consult that document for information about the meaning of each field. + * + * With libpng < 0.95, it was only possible to directly set and read the + * the values in the png_info_struct, which meant that the contents and + * order of the values had to remain fixed. With libpng 0.95 and later, + * however, there are now functions that abstract the contents of + * png_info_struct from the application, so this makes it easier to use + * libpng with dynamic libraries, and even makes it possible to use + * libraries that don't have all of the libpng ancillary chunk-handing + * functionality. In libpng-1.5.0 this was moved into a separate private + * file that is not visible to applications. + * + * The following members may have allocated storage attached that should be + * cleaned up before the structure is discarded: palette, trans, text, + * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, + * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these + * are automatically freed when the info structure is deallocated, if they were + * allocated internally by libpng. This behavior can be changed by means + * of the png_data_freer() function. + * + * More allocation details: all the chunk-reading functions that + * change these members go through the corresponding png_set_* + * functions. A function to clear these members is available: see + * png_free_data(). The png_set_* functions do not depend on being + * able to point info structure members to any of the storage they are + * passed (they make their own copies), EXCEPT that the png_set_text + * functions use the same storage passed to them in the text_ptr or + * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns + * functions do not make their own copies. + */ +#ifndef PNGINFO_H +#define PNGINFO_H + +struct png_info_def +{ + /* The following are necessary for every PNG file */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + png_size_t rowbytes; /* bytes needed to hold an untransformed row */ + png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ + png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ + png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ + /* The following three should have been named *_method not *_type */ + png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ + png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + + /* The following are set by png_set_IHDR, called from the application on + * write, but the are never actually used by the write code. + */ + png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte spare_byte; /* to align the data, and for future use */ + +#ifdef PNG_READ_SUPPORTED + /* This is never set during write */ + png_byte signature[8]; /* magic bytes read by libpng from start of file */ +#endif + + /* The rest of the data is optional. If you are reading, check the + * valid field to see if the information in these are valid. If you + * are writing, set the valid field to those chunks you want written, + * and initialize the appropriate fields below. + */ + +#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) + /* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are + * defined. When COLORSPACE is switched on all the colorspace-defining + * chunks should be enabled, when GAMMA is switched on all the gamma-defining + * chunks should be enabled. If this is not done it becomes possible to read + * inconsistent PNG files and assign a probably incorrect interpretation to + * the information. (In other words, by carefully choosing which chunks to + * recognize the system configuration can select an interpretation for PNG + * files containing ambiguous data and this will result in inconsistent + * behavior between different libpng builds!) + */ + png_colorspace colorspace; +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* iCCP chunk data. */ + png_charp iccp_name; /* profile name */ + png_bytep iccp_profile; /* International Color Consortium profile data */ + png_uint_32 iccp_proflen; /* ICC profile data length */ +#endif + +#ifdef PNG_TEXT_SUPPORTED + /* The tEXt, and zTXt chunks contain human-readable textual data in + * uncompressed, compressed, and optionally compressed forms, respectively. + * The data in "text" is an array of pointers to uncompressed, + * null-terminated C strings. Each chunk has a keyword that describes the + * textual data contained in that chunk. Keywords are not required to be + * unique, and the text string may be empty. Any number of text chunks may + * be in an image. + */ + int num_text; /* number of comments read or comments to write */ + int max_text; /* current size of text array */ + png_textp text; /* array of comments read or comments to write */ +#endif /* PNG_TEXT_SUPPORTED */ + +#ifdef PNG_tIME_SUPPORTED + /* The tIME chunk holds the last time the displayed image data was + * modified. See the png_time struct for the contents of this struct. + */ + png_time mod_time; +#endif + +#ifdef PNG_sBIT_SUPPORTED + /* The sBIT chunk specifies the number of significant high-order bits + * in the pixel data. Values are in the range [1, bit_depth], and are + * only specified for the channels in the pixel data. The contents of + * the low-order bits is not specified. Data is valid if + * (valid & PNG_INFO_sBIT) is non-zero. + */ + png_color_8 sig_bit; /* significant bits in color channels */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ +defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The tRNS chunk supplies transparency data for paletted images and + * other image types that don't need a full alpha channel. There are + * "num_trans" transparency values for a paletted image, stored in the + * same order as the palette colors, starting from index 0. Values + * for the data are in the range [0, 255], ranging from fully transparent + * to fully opaque, respectively. For non-paletted images, there is a + * single color specified that should be treated as fully transparent. + * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. + */ + png_bytep trans_alpha; /* alpha values for paletted image */ + png_color_16 trans_color; /* transparent color for non-palette image */ +#endif + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The bKGD chunk gives the suggested image background color if the + * display program does not have its own background color and the image + * is needs to composited onto a background before display. The colors + * in "background" are normally in the same color space/depth as the + * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. + */ + png_color_16 background; +#endif + +#ifdef PNG_oFFs_SUPPORTED + /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards + * and downwards from the top-left corner of the display, page, or other + * application-specific co-ordinate space. See the PNG_OFFSET_ defines + * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. + */ + png_int_32 x_offset; /* x offset on page */ + png_int_32 y_offset; /* y offset on page */ + png_byte offset_unit_type; /* offset units type */ +#endif + +#ifdef PNG_pHYs_SUPPORTED + /* The pHYs chunk gives the physical pixel density of the image for + * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ + * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. + */ + png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ + png_uint_32 y_pixels_per_unit; /* vertical pixel density */ + png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ +#endif + +#ifdef PNG_hIST_SUPPORTED + /* The hIST chunk contains the relative frequency or importance of the + * various palette entries, so that a viewer can intelligently select a + * reduced-color palette, if required. Data is an array of "num_palette" + * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) + * is non-zero. + */ + png_uint_16p hist; +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* The pCAL chunk describes a transformation between the stored pixel + * values and original physical data values used to create the image. + * The integer range [0, 2^bit_depth - 1] maps to the floating-point + * range given by [pcal_X0, pcal_X1], and are further transformed by a + * (possibly non-linear) transformation function given by "pcal_type" + * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ + * defines below, and the PNG-Group's PNG extensions document for a + * complete description of the transformations and how they should be + * implemented, and for a description of the ASCII parameter strings. + * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. + */ + png_charp pcal_purpose; /* pCAL chunk description string */ + png_int_32 pcal_X0; /* minimum value */ + png_int_32 pcal_X1; /* maximum value */ + png_charp pcal_units; /* Latin-1 string giving physical units */ + png_charpp pcal_params; /* ASCII strings containing parameter values */ + png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_nparams; /* number of parameters given in pcal_params */ +#endif + +/* New members added in libpng-1.0.6 */ + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED + /* Storage for unknown chunks that the library doesn't recognize. */ + png_unknown_chunkp unknown_chunks; + + /* The type of this field is limited by the type of + * png_struct::user_chunk_cache_max, else overflow can occur. + */ + int unknown_chunks_num; +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Data on sPLT chunks (there may be more than one). */ + png_sPLT_tp splt_palettes; + int splt_palettes_num; /* Match type returned by png_get API */ +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* The sCAL chunk describes the actual physical dimensions of the + * subject matter of the graphic. The chunk contains a unit specification + * a byte value, and two ASCII strings representing floating-point + * values. The values are width and height corresponsing to one pixel + * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is + * non-zero. + */ + png_byte scal_unit; /* unit of physical scale */ + png_charp scal_s_width; /* string containing height */ + png_charp scal_s_height; /* string containing width */ +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) + non-zero */ + /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ + png_bytepp row_pointers; /* the image bits */ +#endif + +}; +#endif /* PNGINFO_H */ diff --git a/ext/libpng17/pnglibconf.h b/ext/libpng17/pnglibconf.h new file mode 100644 index 0000000000..b93120c791 --- /dev/null +++ b/ext/libpng17/pnglibconf.h @@ -0,0 +1,210 @@ +/* libpng 1.7.0beta35 STANDARD API DEFINITION */ + +/* pnglibconf.h - library build configuration */ + +/* Libpng version 1.7.0beta35 - March 22, 2014 */ + +/* Copyright (c) 1998-2013 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +/*#undef PNG_SAFE_LIMITS_SUPPORTED*/ +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_OPTION_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_ABORT { (abort()); } +#define PNG_API_RULE 0 +#define PNG_COST_SHIFT 3 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_WEIGHT_SHIFT 8 +#define PNG_ZLIB_VERNUM 0 /* unknown */ +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_HEADER +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/ext/libpng16/pngmem.c b/ext/libpng17/pngmem.c similarity index 84% rename from ext/libpng16/pngmem.c rename to ext/libpng17/pngmem.c index adae736699..db336c8698 100644 --- a/ext/libpng16/pngmem.c +++ b/ext/libpng17/pngmem.c @@ -1,277 +1,261 @@ - -/* pngmem.c - stub functions for memory allocation - * - * Last changed in libpng 1.6.0 [February 14, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - * This file provides a location for all memory allocation. Users who - * need special memory handling are expected to supply replacement - * functions for png_malloc() and png_free(), and to use - * png_create_read_struct_2() and png_create_write_struct_2() to - * identify the replacement functions. - */ - -#include "pngpriv.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -/* Free a png_struct */ -void /* PRIVATE */ -png_destroy_png_struct(png_structrp png_ptr) -{ - if (png_ptr != NULL) - { - /* png_free might call png_error and may certainly call - * png_get_mem_ptr, so fake a temporary png_struct to support this. - */ - png_struct dummy_struct = *png_ptr; - memset(png_ptr, 0, (sizeof *png_ptr)); - png_free(&dummy_struct, png_ptr); - -# ifdef PNG_SETJMP_SUPPORTED - /* We may have a jmp_buf left to deallocate. */ - png_free_jmpbuf(&dummy_struct); -# endif - } -} - -/* Allocate memory. For reasonable files, size should never exceed - * 64K. However, zlib may allocate more then 64K if you don't tell - * it not to. See zconf.h and png.h for more information. zlib does - * need to allocate exactly 64K, so whatever you call here must - * have the ability to do that. - */ -PNG_FUNCTION(png_voidp,PNGAPI -png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) -{ - png_voidp ret; - - ret = png_malloc(png_ptr, size); - - if (ret != NULL) - memset(ret, 0, size); - - return ret; -} - -/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of - * allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED. - * Checking and error handling must happen outside this routine; it returns NULL - * if the allocation cannot be done (for any reason.) - */ -PNG_FUNCTION(png_voidp /* PRIVATE */, -png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED) -{ - /* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS - * allocators have also been removed in 1.6.0, so any 16-bit system now has - * to implement a user memory handler. This checks to be sure it isn't - * called with big numbers. - */ -#ifdef PNG_USER_MEM_SUPPORTED - PNG_UNUSED(png_ptr) -#endif - if (size > 0 && size <= PNG_SIZE_MAX -# ifdef PNG_MAX_MALLOC_64K - && size <= 65536U -# endif - ) - { -#ifdef PNG_USER_MEM_SUPPORTED - if (png_ptr != NULL && png_ptr->malloc_fn != NULL) - return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size); - - else -#endif - return malloc((size_t)size); /* checked for truncation above */ - } - - else - return NULL; -} - -/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7 - * that arises because of the checks in png_realloc_array that are repeated in - * png_malloc_array. - */ -static png_voidp -png_malloc_array_checked(png_const_structrp png_ptr, int nelements, - size_t element_size) -{ - png_alloc_size_t req = nelements; /* known to be > 0 */ - - if (req <= PNG_SIZE_MAX/element_size) - return png_malloc_base(png_ptr, req * element_size); - - /* The failure case when the request is too large */ - return NULL; -} - -PNG_FUNCTION(png_voidp /* PRIVATE */, -png_malloc_array,(png_const_structrp png_ptr, int nelements, - size_t element_size),PNG_ALLOCATED) -{ - if (nelements <= 0 || element_size == 0) - png_error(png_ptr, "internal error: array alloc"); - - return png_malloc_array_checked(png_ptr, nelements, element_size); -} - -PNG_FUNCTION(png_voidp /* PRIVATE */, -png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, - int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED) -{ - /* These are internal errors: */ - if (add_elements <= 0 || element_size == 0 || old_elements < 0 || - (old_array == NULL && old_elements > 0)) - png_error(png_ptr, "internal error: array realloc"); - - /* Check for overflow on the elements count (so the caller does not have to - * check.) - */ - if (add_elements <= INT_MAX - old_elements) - { - png_voidp new_array = png_malloc_array_checked(png_ptr, - old_elements+add_elements, element_size); - - if (new_array != NULL) - { - /* Because png_malloc_array worked the size calculations below cannot - * overflow. - */ - if (old_elements > 0) - memcpy(new_array, old_array, element_size*(unsigned)old_elements); - - memset((char*)new_array + element_size*(unsigned)old_elements, 0, - element_size*(unsigned)add_elements); - - return new_array; - } - } - - return NULL; /* error */ -} - -/* Various functions that have different error handling are derived from this. - * png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate - * function png_malloc_default is also provided. - */ -PNG_FUNCTION(png_voidp,PNGAPI -png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) -{ - png_voidp ret; - - if (png_ptr == NULL) - return NULL; - - ret = png_malloc_base(png_ptr, size); - - if (ret == NULL) - png_error(png_ptr, "Out of memory"); /* 'm' means png_malloc */ - - return ret; -} - -#ifdef PNG_USER_MEM_SUPPORTED -PNG_FUNCTION(png_voidp,PNGAPI -png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED PNG_DEPRECATED) -{ - png_voidp ret; - - if (png_ptr == NULL) - return NULL; - - /* Passing 'NULL' here bypasses the application provided memory handler. */ - ret = png_malloc_base(NULL/*use malloc*/, size); - - if (ret == NULL) - png_error(png_ptr, "Out of Memory"); /* 'M' means png_malloc_default */ - - return ret; -} -#endif /* PNG_USER_MEM_SUPPORTED */ - -/* This function was added at libpng version 1.2.3. The png_malloc_warn() - * function will issue a png_warning and return NULL instead of issuing a - * png_error, if it fails to allocate the requested memory. - */ -PNG_FUNCTION(png_voidp,PNGAPI -png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED) -{ - if (png_ptr != NULL) - { - png_voidp ret = png_malloc_base(png_ptr, size); - - if (ret != NULL) - return ret; - - png_warning(png_ptr, "Out of memory"); - } - - return NULL; -} - -/* Free a pointer allocated by png_malloc(). If ptr is NULL, return - * without taking any action. - */ -void PNGAPI -png_free(png_const_structrp png_ptr, png_voidp ptr) -{ - if (png_ptr == NULL || ptr == NULL) - return; - -#ifdef PNG_USER_MEM_SUPPORTED - if (png_ptr->free_fn != NULL) - png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr); - - else - png_free_default(png_ptr, ptr); -} - -PNG_FUNCTION(void,PNGAPI -png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED) -{ - if (png_ptr == NULL || ptr == NULL) - return; -#endif /* PNG_USER_MEM_SUPPORTED */ - - free(ptr); -} - -#ifdef PNG_USER_MEM_SUPPORTED -/* This function is called when the application wants to use another method - * of allocating and freeing memory. - */ -void PNGAPI -png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr - malloc_fn, png_free_ptr free_fn) -{ - if (png_ptr != NULL) - { - png_ptr->mem_ptr = mem_ptr; - png_ptr->malloc_fn = malloc_fn; - png_ptr->free_fn = free_fn; - } -} - -/* This function returns a pointer to the mem_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy and png_read_destroy are called. - */ -png_voidp PNGAPI -png_get_mem_ptr(png_const_structrp png_ptr) -{ - if (png_ptr == NULL) - return NULL; - - return png_ptr->mem_ptr; -} -#endif /* PNG_USER_MEM_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ + +/* pngmem.c - stub functions for memory allocation + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Free a png_struct */ +void /* PRIVATE */ +png_destroy_png_struct(png_structrp png_ptr) +{ + if (png_ptr != NULL) + { + /* png_free might call png_error and may certainly call + * png_get_mem_ptr, so fake a temporary png_struct to support this. + */ + png_struct dummy_struct = *png_ptr; + memset(png_ptr, 0, (sizeof *png_ptr)); + png_free(&dummy_struct, png_ptr); + +# ifdef PNG_SETJMP_SUPPORTED + /* We may have a jmp_buf left to deallocate. */ + png_free_jmpbuf(&dummy_struct); +# endif + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + ret = png_malloc(png_ptr, size); + + if (ret != NULL) + memset(ret, 0, size); + + return ret; +} + +/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of + * allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED. + * Checking and error handling must happen outside this routine; it returns NULL + * if the allocation cannot be done (for any reason.) + */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED) +{ + /* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS + * allocators have also been removed in 1.6.0, so any 16-bit system now has + * to implement a user memory handler. This checks to be sure it isn't + * called with big numbers. + */ +#ifndef PNG_USER_MEM_SUPPORTED + PNG_UNUSED(png_ptr) +#endif + + if (size > 0 && size <= PNG_SIZE_MAX +# ifdef PNG_MAX_MALLOC_64K + && size <= 65536U +# endif + ) + { +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr != NULL && png_ptr->malloc_fn != NULL) + return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size); + + else +#endif + return malloc((size_t)size); /* checked for truncation above */ + } + + else + return NULL; +} + +#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\ + defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) +/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7 + * that arises because of the checks in png_realloc_array that are repeated in + * png_malloc_array. + */ +static png_voidp +png_malloc_array_checked(png_const_structrp png_ptr, int nelements, + size_t element_size) +{ + png_alloc_size_t req = nelements; /* known to be > 0 */ + + if (req <= PNG_SIZE_MAX/element_size) + return png_malloc_base(png_ptr, req * element_size); + + /* The failure case when the request is too large */ + return NULL; +} + +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_malloc_array,(png_const_structrp png_ptr, int nelements, + size_t element_size),PNG_ALLOCATED) +{ + if (nelements <= 0 || element_size == 0) + png_error(png_ptr, "internal error: array alloc"); + + return png_malloc_array_checked(png_ptr, nelements, element_size); +} + +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_realloc_array,(png_structrp png_ptr, png_const_voidp old_array, + int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED) +{ + /* These are internal errors: */ + if (add_elements <= 0 || element_size == 0 || old_elements < 0 || + (old_array == NULL && old_elements > 0)) + png_error(png_ptr, "internal error: array realloc"); + + /* Check for overflow on the elements count (so the caller does not have to + * check.) + */ + if (add_elements <= INT_MAX - old_elements) + { + png_voidp new_array = png_malloc_array_checked(png_ptr, + old_elements+add_elements, element_size); + + if (new_array != NULL) + { + /* Because png_malloc_array worked the size calculations below cannot + * overflow. + */ + if (old_elements > 0) + memcpy(new_array, old_array, element_size*(unsigned)old_elements); + + memset((char*)new_array + element_size*(unsigned)old_elements, 0, + element_size*(unsigned)add_elements); + + return new_array; + } + } + +#ifdef PNG_READ_SUPPORTED +# ifdef PNG_USER_LIMITS_SUPPORTED + /* The potential overflow case. Set the cache counter so libpng will + * not make any more attempts + */ + png_ptr->user_chunk_cache_max = 2; +# endif +#endif + + return NULL; /* error */ +} +#endif /* TEXT || sPLT || STORE_UNKNOWN_CHUNKS */ + +/* Various functions that have different error handling are derived from this. + * png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate + * function png_malloc_default is also provided. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + if (png_ptr == NULL) + return NULL; + + ret = png_malloc_base(png_ptr, size); + + if (ret == NULL) + png_error(png_ptr, "Out of memory"); + + return ret; +} + +/* This function was added at libpng version 1.2.3. The png_malloc_warn() + * function will issue a png_warning and return NULL instead of issuing a + * png_error, if it fails to allocate the requested memory. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED) +{ + if (png_ptr != NULL) + { + png_voidp ret = png_malloc_base(png_ptr, size); + + if (ret != NULL) + return ret; + + png_warning(png_ptr, "Out of memory"); + } + + return NULL; +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + * without taking any action. + */ +void PNGAPI +png_free(png_const_structrp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr); + + else +#endif /* PNG_USER_MEM_SUPPORTED */ + free(ptr); +} + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + if (png_ptr != NULL) + { + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; + } +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + + return png_ptr->mem_ptr; +} +#endif /* PNG_USER_MEM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngpread.c b/ext/libpng17/pngpread.c similarity index 95% rename from ext/libpng16/pngpread.c rename to ext/libpng17/pngpread.c index f97ac3aee3..0b251f7363 100644 --- a/ext/libpng16/pngpread.c +++ b/ext/libpng17/pngpread.c @@ -1,1291 +1,1292 @@ - -/* pngpread.c - read a png file in push mode - * - * Last changed in libpng 1.6.0 [February 14, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -#include "pngpriv.h" - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - -/* Push model modes */ -#define PNG_READ_SIG_MODE 0 -#define PNG_READ_CHUNK_MODE 1 -#define PNG_READ_IDAT_MODE 2 -#define PNG_SKIP_MODE 3 -#define PNG_READ_tEXt_MODE 4 -#define PNG_READ_zTXt_MODE 5 -#define PNG_READ_DONE_MODE 6 -#define PNG_READ_iTXt_MODE 7 -#define PNG_ERROR_MODE 8 - -void PNGAPI -png_process_data(png_structrp png_ptr, png_inforp info_ptr, - png_bytep buffer, png_size_t buffer_size) -{ - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_push_restore_buffer(png_ptr, buffer, buffer_size); - - while (png_ptr->buffer_size) - { - png_process_some_data(png_ptr, info_ptr); - } -} - -png_size_t PNGAPI -png_process_data_pause(png_structrp png_ptr, int save) -{ - if (png_ptr != NULL) - { - /* It's easiest for the caller if we do the save, then the caller doesn't - * have to supply the same data again: - */ - if (save) - png_push_save_buffer(png_ptr); - else - { - /* This includes any pending saved bytes: */ - png_size_t remaining = png_ptr->buffer_size; - png_ptr->buffer_size = 0; - - /* So subtract the saved buffer size, unless all the data - * is actually 'saved', in which case we just return 0 - */ - if (png_ptr->save_buffer_size < remaining) - return remaining - png_ptr->save_buffer_size; - } - } - - return 0; -} - -png_uint_32 PNGAPI -png_process_data_skip(png_structrp png_ptr) -{ - png_uint_32 remaining = 0; - - if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE && - png_ptr->skip_length > 0) - { - /* At the end of png_process_data the buffer size must be 0 (see the loop - * above) so we can detect a broken call here: - */ - if (png_ptr->buffer_size != 0) - png_error(png_ptr, - "png_process_data_skip called inside png_process_data"); - - /* If is impossible for there to be a saved buffer at this point - - * otherwise we could not be in SKIP mode. This will also happen if - * png_process_skip is called inside png_process_data (but only very - * rarely.) - */ - if (png_ptr->save_buffer_size != 0) - png_error(png_ptr, "png_process_data_skip called with saved data"); - - remaining = png_ptr->skip_length; - png_ptr->skip_length = 0; - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } - - return remaining; -} - -/* What we do with the incoming data depends on what we were previously - * doing before we ran out of data... - */ -void /* PRIVATE */ -png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) -{ - if (png_ptr == NULL) - return; - - switch (png_ptr->process_mode) - { - case PNG_READ_SIG_MODE: - { - png_push_read_sig(png_ptr, info_ptr); - break; - } - - case PNG_READ_CHUNK_MODE: - { - png_push_read_chunk(png_ptr, info_ptr); - break; - } - - case PNG_READ_IDAT_MODE: - { - png_push_read_IDAT(png_ptr); - break; - } - - case PNG_SKIP_MODE: - { - png_push_crc_finish(png_ptr); - break; - } - - default: - { - png_ptr->buffer_size = 0; - break; - } - } -} - -/* Read any remaining signature bytes from the stream and compare them with - * the correct PNG signature. It is possible that this routine is called - * with bytes already read from the signature, either because they have been - * checked by the calling application, or because of multiple calls to this - * routine. - */ -void /* PRIVATE */ -png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) -{ - png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ - num_to_check = 8 - num_checked; - - if (png_ptr->buffer_size < num_to_check) - { - num_to_check = png_ptr->buffer_size; - } - - png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), - num_to_check); - png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); - - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) - { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); - } - else - { - if (png_ptr->sig_bytes >= 8) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } - } -} - -void /* PRIVATE */ -png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) -{ - png_uint_32 chunk_name; -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - int keep; /* unknown handling method */ -#endif - - /* First we make sure we have enough data for the 4 byte chunk name - * and the 4 byte chunk length before proceeding with decoding the - * chunk data. To fully decode each of these chunks, we also make - * sure we have enough data in the buffer for the 4 byte CRC at the - * end of every chunk (except IDAT, which is handled separately). - */ - if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) - { - png_byte chunk_length[4]; - png_byte chunk_tag[4]; - - if (png_ptr->buffer_size < 8) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, chunk_tag, 4); - png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); - png_check_chunk_name(png_ptr, png_ptr->chunk_name); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - } - - chunk_name = png_ptr->chunk_name; - - if (chunk_name == png_IDAT) - { - if (png_ptr->mode & PNG_AFTER_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; - - /* If we reach an IDAT chunk, this means we have read all of the - * header chunks, and we can start reading the image (or if this - * is called after the image has been read - we have an error). - */ - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - - png_ptr->mode |= PNG_HAVE_IDAT; - - if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - if (png_ptr->push_length == 0) - return; - - if (png_ptr->mode & PNG_AFTER_IDAT) - png_benign_error(png_ptr, "Too many IDATs found"); - } - - if (chunk_name == png_IHDR) - { - if (png_ptr->push_length != 13) - png_error(png_ptr, "Invalid IHDR length"); - - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); - } - - else if (chunk_name == png_IEND) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); - - png_ptr->process_mode = PNG_READ_DONE_MODE; - png_push_have_end(png_ptr, info_ptr); - } - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep); - - if (chunk_name == png_PLTE) - png_ptr->mode |= PNG_HAVE_PLTE; - } - -#endif - else if (chunk_name == png_PLTE) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); - } - - else if (chunk_name == png_IDAT) - { - png_ptr->idat_size = png_ptr->push_length; - png_ptr->process_mode = PNG_READ_IDAT_MODE; - png_push_have_info(png_ptr, info_ptr); - png_ptr->zstream.avail_out = - (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, - png_ptr->iwidth) + 1; - png_ptr->zstream.next_out = png_ptr->row_buf; - return; - } - -#ifdef PNG_READ_gAMA_SUPPORTED - else if (png_ptr->chunk_name == png_gAMA) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_sBIT_SUPPORTED - else if (png_ptr->chunk_name == png_sBIT) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_cHRM_SUPPORTED - else if (png_ptr->chunk_name == png_cHRM) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_sRGB_SUPPORTED - else if (chunk_name == png_sRGB) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_iCCP_SUPPORTED - else if (png_ptr->chunk_name == png_iCCP) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_sPLT_SUPPORTED - else if (chunk_name == png_sPLT) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_tRNS_SUPPORTED - else if (chunk_name == png_tRNS) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_bKGD_SUPPORTED - else if (chunk_name == png_bKGD) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_hIST_SUPPORTED - else if (chunk_name == png_hIST) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_pHYs_SUPPORTED - else if (chunk_name == png_pHYs) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_oFFs_SUPPORTED - else if (chunk_name == png_oFFs) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); - } -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED - else if (chunk_name == png_pCAL) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_sCAL_SUPPORTED - else if (chunk_name == png_sCAL) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_tIME_SUPPORTED - else if (chunk_name == png_tIME) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_tEXt_SUPPORTED - else if (chunk_name == png_tEXt) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_zTXt_SUPPORTED - else if (chunk_name == png_zTXt) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_iTXt_SUPPORTED - else if (chunk_name == png_iTXt) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif - else - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, - PNG_HANDLE_CHUNK_AS_DEFAULT); - } - - png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; -} - -void /* PRIVATE */ -png_push_crc_skip(png_structrp png_ptr, png_uint_32 skip) -{ - png_ptr->process_mode = PNG_SKIP_MODE; - png_ptr->skip_length = skip; -} - -void /* PRIVATE */ -png_push_crc_finish(png_structrp png_ptr) -{ - if (png_ptr->skip_length && png_ptr->save_buffer_size) - { - png_size_t save_size = png_ptr->save_buffer_size; - png_uint_32 skip_length = png_ptr->skip_length; - - /* We want the smaller of 'skip_length' and 'save_buffer_size', but - * they are of different types and we don't know which variable has the - * fewest bits. Carefully select the smaller and cast it to the type of - * the larger - this cannot overflow. Do not cast in the following test - * - it will break on either 16 or 64 bit platforms. - */ - if (skip_length < save_size) - save_size = (png_size_t)skip_length; - - else - skip_length = (png_uint_32)save_size; - - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - - png_ptr->skip_length -= skip_length; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (png_ptr->skip_length && png_ptr->current_buffer_size) - { - png_size_t save_size = png_ptr->current_buffer_size; - png_uint_32 skip_length = png_ptr->skip_length; - - /* We want the smaller of 'skip_length' and 'current_buffer_size', here, - * the same problem exists as above and the same solution. - */ - if (skip_length < save_size) - save_size = (png_size_t)skip_length; - - else - skip_length = (png_uint_32)save_size; - - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_ptr->skip_length -= skip_length; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } - if (!png_ptr->skip_length) - { - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_crc_finish(png_ptr, 0); - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } -} - -void PNGCBAPI -png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) -{ - png_bytep ptr; - - if (png_ptr == NULL) - return; - - ptr = buffer; - if (png_ptr->save_buffer_size) - { - png_size_t save_size; - - if (length < png_ptr->save_buffer_size) - save_size = length; - - else - save_size = png_ptr->save_buffer_size; - - memcpy(ptr, png_ptr->save_buffer_ptr, save_size); - length -= save_size; - ptr += save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (length && png_ptr->current_buffer_size) - { - png_size_t save_size; - - if (length < png_ptr->current_buffer_size) - save_size = length; - - else - save_size = png_ptr->current_buffer_size; - - memcpy(ptr, png_ptr->current_buffer_ptr, save_size); - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } -} - -void /* PRIVATE */ -png_push_save_buffer(png_structrp png_ptr) -{ - if (png_ptr->save_buffer_size) - { - if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) - { - png_size_t i, istop; - png_bytep sp; - png_bytep dp; - - istop = png_ptr->save_buffer_size; - for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; - i < istop; i++, sp++, dp++) - { - *dp = *sp; - } - } - } - if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > - png_ptr->save_buffer_max) - { - png_size_t new_max; - png_bytep old_buffer; - - if (png_ptr->save_buffer_size > PNG_SIZE_MAX - - (png_ptr->current_buffer_size + 256)) - { - png_error(png_ptr, "Potential overflow of save_buffer"); - } - - new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; - old_buffer = png_ptr->save_buffer; - png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, - (png_size_t)new_max); - - if (png_ptr->save_buffer == NULL) - { - png_free(png_ptr, old_buffer); - png_error(png_ptr, "Insufficient memory for save_buffer"); - } - - memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); - png_free(png_ptr, old_buffer); - png_ptr->save_buffer_max = new_max; - } - if (png_ptr->current_buffer_size) - { - memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, - png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); - png_ptr->save_buffer_size += png_ptr->current_buffer_size; - png_ptr->current_buffer_size = 0; - } - png_ptr->save_buffer_ptr = png_ptr->save_buffer; - png_ptr->buffer_size = 0; -} - -void /* PRIVATE */ -png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) -{ - png_ptr->current_buffer = buffer; - png_ptr->current_buffer_size = buffer_length; - png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; - png_ptr->current_buffer_ptr = png_ptr->current_buffer; -} - -void /* PRIVATE */ -png_push_read_IDAT(png_structrp png_ptr) -{ - if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) - { - png_byte chunk_length[4]; - png_byte chunk_tag[4]; - - /* TODO: this code can be commoned up with the same code in push_read */ - if (png_ptr->buffer_size < 8) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, chunk_tag, 4); - png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - - if (png_ptr->chunk_name != png_IDAT) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - - if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) - png_error(png_ptr, "Not enough compressed data"); - - return; - } - - png_ptr->idat_size = png_ptr->push_length; - } - - if (png_ptr->idat_size && png_ptr->save_buffer_size) - { - png_size_t save_size = png_ptr->save_buffer_size; - png_uint_32 idat_size = png_ptr->idat_size; - - /* We want the smaller of 'idat_size' and 'current_buffer_size', but they - * are of different types and we don't know which variable has the fewest - * bits. Carefully select the smaller and cast it to the type of the - * larger - this cannot overflow. Do not cast in the following test - it - * will break on either 16 or 64 bit platforms. - */ - if (idat_size < save_size) - save_size = (png_size_t)idat_size; - - else - idat_size = (png_uint_32)save_size; - - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - - png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); - - png_ptr->idat_size -= idat_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - - if (png_ptr->idat_size && png_ptr->current_buffer_size) - { - png_size_t save_size = png_ptr->current_buffer_size; - png_uint_32 idat_size = png_ptr->idat_size; - - /* We want the smaller of 'idat_size' and 'current_buffer_size', but they - * are of different types and we don't know which variable has the fewest - * bits. Carefully select the smaller and cast it to the type of the - * larger - this cannot overflow. - */ - if (idat_size < save_size) - save_size = (png_size_t)idat_size; - - else - idat_size = (png_uint_32)save_size; - - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_ptr->idat_size -= idat_size; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } - if (!png_ptr->idat_size) - { - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_crc_finish(png_ptr, 0); - png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->zowner = 0; - } -} - -void /* PRIVATE */ -png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) -{ - /* The caller checks for a non-zero buffer length. */ - if (!(buffer_length > 0) || buffer == NULL) - png_error(png_ptr, "No IDAT data (internal error)"); - - /* This routine must process all the data it has been given - * before returning, calling the row callback as required to - * handle the uncompressed results. - */ - png_ptr->zstream.next_in = buffer; - /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */ - png_ptr->zstream.avail_in = (uInt)buffer_length; - - /* Keep going until the decompressed data is all processed - * or the stream marked as finished. - */ - while (png_ptr->zstream.avail_in > 0 && - !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) - { - int ret; - - /* We have data for zlib, but we must check that zlib - * has someplace to put the results. It doesn't matter - * if we don't expect any results -- it may be the input - * data is just the LZ end code. - */ - if (!(png_ptr->zstream.avail_out > 0)) - { - /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */ - png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, - png_ptr->iwidth) + 1); - - png_ptr->zstream.next_out = png_ptr->row_buf; - } - - /* Using Z_SYNC_FLUSH here means that an unterminated - * LZ stream (a stream with a missing end code) can still - * be handled, otherwise (Z_NO_FLUSH) a future zlib - * implementation might defer output and therefore - * change the current behavior (see comments in inflate.c - * for why this doesn't happen at present with zlib 1.2.5). - */ - ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); - - /* Check for any failure before proceeding. */ - if (ret != Z_OK && ret != Z_STREAM_END) - { - /* Terminate the decompression. */ - png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; - png_ptr->zowner = 0; - - /* This may be a truncated stream (missing or - * damaged end code). Treat that as a warning. - */ - if (png_ptr->row_number >= png_ptr->num_rows || - png_ptr->pass > 6) - png_warning(png_ptr, "Truncated compressed data in IDAT"); - - else - png_error(png_ptr, "Decompression error in IDAT"); - - /* Skip the check on unprocessed input */ - return; - } - - /* Did inflate output any data? */ - if (png_ptr->zstream.next_out != png_ptr->row_buf) - { - /* Is this unexpected data after the last row? - * If it is, artificially terminate the LZ output - * here. - */ - if (png_ptr->row_number >= png_ptr->num_rows || - png_ptr->pass > 6) - { - /* Extra data. */ - png_warning(png_ptr, "Extra compressed data in IDAT"); - png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; - png_ptr->zowner = 0; - - /* Do no more processing; skip the unprocessed - * input check below. - */ - return; - } - - /* Do we have a complete row? */ - if (png_ptr->zstream.avail_out == 0) - png_push_process_row(png_ptr); - } - - /* And check for the end of the stream. */ - if (ret == Z_STREAM_END) - png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; - } - - /* All the data should have been processed, if anything - * is left at this point we have bytes of IDAT data - * after the zlib end code. - */ - if (png_ptr->zstream.avail_in > 0) - png_warning(png_ptr, "Extra compression data in IDAT"); -} - -void /* PRIVATE */ -png_push_process_row(png_structrp png_ptr) -{ - /* 1.5.6: row_info moved out of png_struct to a local here. */ - png_row_info row_info; - - row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ - row_info.color_type = png_ptr->color_type; - row_info.bit_depth = png_ptr->bit_depth; - row_info.channels = png_ptr->channels; - row_info.pixel_depth = png_ptr->pixel_depth; - row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); - - if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) - { - if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) - png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, - png_ptr->prev_row + 1, png_ptr->row_buf[0]); - else - png_error(png_ptr, "bad adaptive filter value"); - } - - /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before - * 1.5.6, while the buffer really is this big in current versions of libpng - * it may not be in the future, so this was changed just to copy the - * interlaced row count: - */ - memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED - if (png_ptr->transformations) - png_do_read_transformations(png_ptr, &row_info); -#endif - - /* The transformed pixel depth should match the depth now in row_info. */ - if (png_ptr->transformed_pixel_depth == 0) - { - png_ptr->transformed_pixel_depth = row_info.pixel_depth; - if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) - png_error(png_ptr, "progressive row overflow"); - } - - else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) - png_error(png_ptr, "internal progressive row size calculation error"); - - -#ifdef PNG_READ_INTERLACING_SUPPORTED - /* Blow up interlaced rows to full size */ - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) - { - if (png_ptr->pass < 6) - png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, - png_ptr->transformations); - - switch (png_ptr->pass) - { - case 0: - { - int i; - for (i = 0; i < 8 && png_ptr->pass == 0; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ - } - - if (png_ptr->pass == 2) /* Pass 1 might be empty */ - { - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - } - - if (png_ptr->pass == 4 && png_ptr->height <= 4) - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - } - - if (png_ptr->pass == 6 && png_ptr->height <= 4) - { - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - - break; - } - - case 1: - { - int i; - for (i = 0; i < 8 && png_ptr->pass == 1; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - - if (png_ptr->pass == 2) /* Skip top 4 generated rows */ - { - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - } - - break; - } - - case 2: - { - int i; - - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - - if (png_ptr->pass == 4) /* Pass 3 might be empty */ - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - } - - break; - } - - case 3: - { - int i; - - for (i = 0; i < 4 && png_ptr->pass == 3; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - - if (png_ptr->pass == 4) /* Skip top two generated rows */ - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - } - - break; - } - - case 4: - { - int i; - - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - - if (png_ptr->pass == 6) /* Pass 5 might be empty */ - { - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - - break; - } - - case 5: - { - int i; - - for (i = 0; i < 2 && png_ptr->pass == 5; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - - if (png_ptr->pass == 6) /* Skip top generated row */ - { - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - - break; - } - - default: - case 6: - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - - if (png_ptr->pass != 6) - break; - - png_push_have_row(png_ptr, NULL); - png_read_push_finish_row(png_ptr); - } - } - } - else -#endif - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } -} - -void /* PRIVATE */ -png_read_push_finish_row(png_structrp png_ptr) -{ -#ifdef PNG_READ_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; - - /* Height of interlace block. This is not currently used - if you need - * it, uncomment it here and in png.h - static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; - */ -#endif - - png_ptr->row_number++; - if (png_ptr->row_number < png_ptr->num_rows) - return; - -#ifdef PNG_READ_INTERLACING_SUPPORTED - if (png_ptr->interlaced) - { - png_ptr->row_number = 0; - memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); - - do - { - png_ptr->pass++; - if ((png_ptr->pass == 1 && png_ptr->width < 5) || - (png_ptr->pass == 3 && png_ptr->width < 3) || - (png_ptr->pass == 5 && png_ptr->width < 2)) - png_ptr->pass++; - - if (png_ptr->pass > 7) - png_ptr->pass--; - - if (png_ptr->pass >= 7) - break; - - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - - if (png_ptr->transformations & PNG_INTERLACE) - break; - - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - - } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); - } -#endif /* PNG_READ_INTERLACING_SUPPORTED */ -} - -void /* PRIVATE */ -png_push_have_info(png_structrp png_ptr, png_inforp info_ptr) -{ - if (png_ptr->info_fn != NULL) - (*(png_ptr->info_fn))(png_ptr, info_ptr); -} - -void /* PRIVATE */ -png_push_have_end(png_structrp png_ptr, png_inforp info_ptr) -{ - if (png_ptr->end_fn != NULL) - (*(png_ptr->end_fn))(png_ptr, info_ptr); -} - -void /* PRIVATE */ -png_push_have_row(png_structrp png_ptr, png_bytep row) -{ - if (png_ptr->row_fn != NULL) - (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, - (int)png_ptr->pass); -} - -#ifdef PNG_READ_INTERLACING_SUPPORTED -void PNGAPI -png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row, - png_const_bytep new_row) -{ - if (png_ptr == NULL) - return; - - /* new_row is a flag here - if it is NULL then the app callback was called - * from an empty row (see the calls to png_struct::row_fn below), otherwise - * it must be png_ptr->row_buf+1 - */ - if (new_row != NULL) - png_combine_row(png_ptr, old_row, 1/*display*/); -} -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - -void PNGAPI -png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr, - png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, - png_progressive_end_ptr end_fn) -{ - if (png_ptr == NULL) - return; - - png_ptr->info_fn = info_fn; - png_ptr->row_fn = row_fn; - png_ptr->end_fn = end_fn; - - png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); -} - -png_voidp PNGAPI -png_get_progressive_ptr(png_const_structrp png_ptr) -{ - if (png_ptr == NULL) - return (NULL); - - return png_ptr->io_ptr; -} -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +/* pngpread.c - read a png file in push mode + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + +/* Push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structrp png_ptr, png_inforp info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +png_size_t PNGAPI +png_process_data_pause(png_structrp png_ptr, int save) +{ + if (png_ptr != NULL) + { + /* It's easiest for the caller if we do the save, then the caller doesn't + * have to supply the same data again: + */ + if (save != 0) + png_push_save_buffer(png_ptr); + else + { + /* This includes any pending saved bytes: */ + png_size_t remaining = png_ptr->buffer_size; + png_ptr->buffer_size = 0; + + /* So subtract the saved buffer size, unless all the data + * is actually 'saved', in which case we just return 0 + */ + if (png_ptr->save_buffer_size < remaining) + return remaining - png_ptr->save_buffer_size; + } + } + + return 0; +} + +png_uint_32 PNGAPI +png_process_data_skip(png_structrp png_ptr) +{ + png_uint_32 remaining = 0; + + if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE && + png_ptr->skip_length > 0) + { + /* At the end of png_process_data the buffer size must be 0 (see the loop + * above) so we can detect a broken call here: + */ + if (png_ptr->buffer_size != 0) + png_error(png_ptr, + "png_process_data_skip called inside png_process_data"); + + /* If is impossible for there to be a saved buffer at this point - + * otherwise we could not be in SKIP mode. This will also happen if + * png_process_skip is called inside png_process_data (but only very + * rarely.) + */ + if (png_ptr->save_buffer_size != 0) + png_error(png_ptr, "png_process_data_skip called with saved data"); + + remaining = png_ptr->skip_length; + png_ptr->skip_length = 0; + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + + return remaining; +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) +{ + if (png_ptr == NULL) + return; + + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } + + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) +{ + png_uint_32 chunk_name; +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + int keep; /* unknown handling method */ +#endif + + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + png_byte chunk_tag[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, chunk_tag, 4); + png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + chunk_name = png_ptr->chunk_name; + + if (chunk_name == png_IDAT) + { + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_benign_error(png_ptr, "Too many IDATs found[p]"); + } + + if (chunk_name == png_IHDR) + { + if (png_ptr->push_length != 13) + png_error(png_ptr, "Invalid IHDR length"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (chunk_name == png_IEND) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep); + + if (chunk_name == png_PLTE) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + + else if (chunk_name == png_PLTE) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (chunk_name == png_IDAT) + { + png_ptr->idat_size = png_ptr->push_length; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (png_ptr->chunk_name == png_gAMA) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (png_ptr->chunk_name == png_sBIT) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (png_ptr->chunk_name == png_cHRM) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (chunk_name == png_sRGB) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (png_ptr->chunk_name == png_iCCP) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (chunk_name == png_sPLT) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (chunk_name == png_tRNS) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_bKGD_SUPPORTED + else if (chunk_name == png_bKGD) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (chunk_name == png_hIST) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (chunk_name == png_pHYs) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (chunk_name == png_oFFs) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (chunk_name == png_pCAL) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (chunk_name == png_sCAL) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (chunk_name == png_tIME) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (chunk_name == png_tEXt) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (chunk_name == png_zTXt) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (chunk_name == png_iTXt) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, + PNG_HANDLE_CHUNK_AS_DEFAULT); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structrp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structrp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size = png_ptr->save_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'save_buffer_size', but + * they are of different types and we don't know which variable has the + * fewest bits. Carefully select the smaller and cast it to the type of + * the larger - this cannot overflow. Do not cast in the following test + * - it will break on either 16 or 64 bit platforms. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size = png_ptr->current_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'current_buffer_size', here, + * the same problem exists as above and the same solution. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void PNGCBAPI +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + if (png_ptr == NULL) + return; + + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + + else + save_size = png_ptr->save_buffer_size; + + memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + + else + save_size = png_ptr->current_buffer_size; + + memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structrp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i, istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, + (png_size_t)new_max); + + if (png_ptr->save_buffer == NULL) + { + png_free(png_ptr, old_buffer); + png_error(png_ptr, "Insufficient memory for save_buffer"); + } + + memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structrp png_ptr) +{ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + png_byte chunk_tag[4]; + + /* TODO: this code can be commoned up with the same code in push_read */ + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, chunk_tag, 4); + png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_ptr->chunk_name != png_IDAT) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + + if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + png_error(png_ptr, "Not enough compressed data"); + + return; + } + + png_ptr->idat_size = png_ptr->push_length; + } + + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size = png_ptr->save_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. Do not cast in the following test - it + * will break on either 16 or 64 bit platforms. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->idat_size -= idat_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size = png_ptr->current_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= idat_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->zowner = 0; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + /* The caller checks for a non-zero buffer length. */ + if (!(buffer_length > 0) || buffer == NULL) + png_error(png_ptr, "No IDAT data (internal error)"); + + /* This routine must process all the data it has been given + * before returning, calling the row callback as required to + * handle the uncompressed results. + */ + png_ptr->zstream.next_in = buffer; + /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */ + png_ptr->zstream.avail_in = (uInt)buffer_length; + + /* Keep going until the decompressed data is all processed + * or the stream marked as finished. + */ + while (png_ptr->zstream.avail_in > 0 && + !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + { + int ret; + + /* We have data for zlib, but we must check that zlib + * has someplace to put the results. It doesn't matter + * if we don't expect any results -- it may be the input + * data is just the LZ end code. + */ + if (!(png_ptr->zstream.avail_out > 0)) + { + /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */ + png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1); + + png_ptr->zstream.next_out = png_ptr->row_buf; + } + + /* Using Z_SYNC_FLUSH here means that an unterminated + * LZ stream (a stream with a missing end code) can still + * be handled, otherwise (Z_NO_FLUSH) a future zlib + * implementation might defer output and therefore + * change the current behavior (see comments in inflate.c + * for why this doesn't happen at present with zlib 1.2.5). + */ + ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); + + /* Check for any failure before proceeding. */ + if (ret != Z_OK && ret != Z_STREAM_END) + { + /* Terminate the decompression. */ + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; + png_ptr->zowner = 0; + + /* This may be a truncated stream (missing or + * damaged end code). Treat that as a warning. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + png_warning(png_ptr, "Truncated compressed data in IDAT"); + + else + png_error(png_ptr, "Decompression error in IDAT"); + + /* Skip the check on unprocessed input */ + return; + } + + /* Did inflate output any data? */ + if (png_ptr->zstream.next_out != png_ptr->row_buf) + { + /* Is this unexpected data after the last row? + * If it is, artificially terminate the LZ output + * here. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + { + /* Extra data. */ + png_warning(png_ptr, "Extra compressed data in IDAT"); + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; + png_ptr->zowner = 0; + + /* Do no more processing; skip the unprocessed + * input check below. + */ + return; + } + + /* Do we have a complete row? */ + if (png_ptr->zstream.avail_out == 0) + png_push_process_row(png_ptr); + } + + /* And check for the end of the stream. */ + if (ret == Z_STREAM_END) + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; + } + + /* All the data should have been processed, if anything + * is left at this point we have bytes of IDAT data + * after the zlib end code. + */ + if (png_ptr->zstream.avail_in > 0) + png_warning(png_ptr, "Extra compression data in IDAT"); +} + +void /* PRIVATE */ +png_push_process_row(png_structrp png_ptr) +{ + /* 1.5.6: row_info moved out of png_struct to a local here. */ + png_row_info row_info; + + row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ + row_info.color_type = png_ptr->color_type; + row_info.bit_depth = png_ptr->bit_depth; + row_info.channels = png_ptr->channels; + row_info.pixel_depth = png_ptr->pixel_depth; + row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); + + if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) + { + if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) + png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, + png_ptr->prev_row + 1, png_ptr->row_buf[0]); + else + png_error(png_ptr, "bad adaptive filter value"); + } + + /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before + * 1.5.6, while the buffer really is this big in current versions of libpng + * it may not be in the future, so this was changed just to copy the + * interlaced row count: + */ + memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + if (png_ptr->transformations) + png_do_read_transformations(png_ptr, &row_info); +#endif + + /* The transformed pixel depth should match the depth now in row_info. */ + if (png_ptr->transformed_pixel_depth == 0) + { + png_ptr->transformed_pixel_depth = row_info.pixel_depth; + if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) + png_error(png_ptr, "progressive row overflow"); + } + + else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) + png_error(png_ptr, "internal progressive row size calculation error"); + + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) + png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, + png_ptr->transformations); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ + } + + if (png_ptr->pass == 2) /* Pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 2) /* Skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 2: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 3: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 4: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Pass 5 might be empty */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 5: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Skip top generated row */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + default: + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + + if (png_ptr->pass != 6) + break; + + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structrp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ +#endif + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass > 7) + png_ptr->pass--; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +} + +void /* PRIVATE */ +png_push_have_info(png_structrp png_ptr, png_inforp info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structrp png_ptr, png_inforp info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structrp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +void PNGAPI +png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row, + png_const_bytep new_row) +{ + if (png_ptr == NULL) + return; + + /* new_row is a flag here - if it is NULL then the app callback was called + * from an empty row (see the calls to png_struct::row_fn below), otherwise + * it must be png_ptr->row_buf+1 + */ + if (new_row != NULL) + png_combine_row(png_ptr, old_row, 1/*display*/); +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +void PNGAPI +png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +png_voidp PNGAPI +png_get_progressive_ptr(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/ext/libpng16/pngpriv.h b/ext/libpng17/pngpriv.h similarity index 84% rename from ext/libpng16/pngpriv.h rename to ext/libpng17/pngpriv.h index 34cfe058d9..1156092683 100644 --- a/ext/libpng16/pngpriv.h +++ b/ext/libpng17/pngpriv.h @@ -1,2043 +1,1852 @@ - -/* pngpriv.h - private declarations for use inside libpng - * - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * Last changed in libpng 1.6.7 [November 14, 2013] - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -/* The symbols declared in this file (including the functions declared - * as extern) are PRIVATE. They are not part of the libpng public - * interface, and are not recommended for use by regular applications. - * Some of them may become public in the future; others may stay private, - * change in an incompatible way, or even disappear. - * Although the libpng users are not forbidden to include this header, - * they should be well aware of the issues that may arise from doing so. - */ - -#ifndef PNGPRIV_H -#define PNGPRIV_H - -/* Feature Test Macros. The following are defined here to ensure that correctly - * implemented libraries reveal the APIs libpng needs to build and hide those - * that are not needed and potentially damaging to the compilation. - * - * Feature Test Macros must be defined before any system header is included (see - * POSIX 1003.1 2.8.2 "POSIX Symbols." - * - * These macros only have an effect if the operating system supports either - * POSIX 1003.1 or C99, or both. On other operating systems (particularly - * Windows/Visual Studio) there is no effect; the OS specific tests below are - * still required (as of 2011-05-02.) - */ -#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ - -#ifndef PNG_VERSION_INFO_ONLY -/* Standard library headers not required by png.h: */ -# include -# include -#endif - -#define PNGLIB_BUILD /*libpng is being built, not used*/ - -/* If HAVE_CONFIG_H is defined during the build then the build system must - * provide an appropriate "config.h" file on the include path. The header file - * must provide definitions as required below (search for "HAVE_CONFIG_H"); - * see configure.ac for more details of the requirements. The macro - * "PNG_NO_CONFIG_H" is provided for maintainers to test for dependencies on - * 'configure'; define this macro to prevent the configure build including the - * configure generated config.h. Libpng is expected to compile without *any* - * special build system support on a reasonably ANSI-C compliant system. - */ -#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) -# include - - /* Pick up the definition of 'restrict' from config.h if it was read: */ -# define PNG_RESTRICT restrict -#endif - -/* To support symbol prefixing it is necessary to know *before* including png.h - * whether the fixed point (and maybe other) APIs are exported, because if they - * are not internal definitions may be required. This is handled below just - * before png.h is included, but load the configuration now if it is available. - */ -#ifndef PNGLCONF_H -# include "pnglibconf.h" -#endif - - -#ifdef PNG_USER_CONFIG -# include "pngusr.h" - /* These should have been defined in pngusr.h */ -# ifndef PNG_USER_PRIVATEBUILD -# define PNG_USER_PRIVATEBUILD "Custom libpng build" -# endif -# ifndef PNG_USER_DLLFNAME_POSTFIX -# define PNG_USER_DLLFNAME_POSTFIX "Cb" -# endif -#endif - -/* Compile time options. - * ===================== - * In a multi-arch build the compiler may compile the code several times for the - * same object module, producing different binaries for different architectures. - * When this happens configure-time setting of the target host options cannot be - * done and this interferes with the handling of the ARM NEON optimizations, and - * possibly other similar optimizations. Put additional tests here; in general - * this is needed when the same option can be changed at both compile time and - * run time depending on the target OS (i.e. iOS vs Android.) - * - * NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because - * this is not possible with certain compilers (Oracle SUN OS CC), as a result - * it is necessary to ensure that all extern functions that *might* be used - * regardless of $(CFLAGS) get declared in this file. The test on __ARM_NEON__ - * below is one example of this behavior because it is controlled by the - * presence or not of -mfpu=neon on the GCC command line, it is possible to do - * this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely - * do this. - */ -#ifndef PNG_ARM_NEON_OPT - /* ARM NEON optimizations are being controlled by the compiler settings, - * typically the target FPU. If the FPU has been set to NEON (-mfpu=neon - * with GCC) then the compiler will define __ARM_NEON__ and we can rely - * unconditionally on NEON instructions not crashing, otherwise we must - * disable use of NEON instructions: - */ -# if defined(__ARM_NEON__) && !defined(IOS) -# define PNG_ARM_NEON_OPT 2 -# else -# define PNG_ARM_NEON_OPT 0 -# endif -#endif - -#if PNG_ARM_NEON_OPT > 0 - /* NEON optimizations are to be at least considered by libpng, so enable the - * callbacks to do this. - */ -# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon - - /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used - * if possible - if __ARM_NEON__ is set and the compiler version is not known - * to be broken. This is control by PNG_ARM_NEON_IMPLEMENTATION which can - * be: - * - * 1 The intrinsics code (the default with __ARM_NEON__) - * 2 The hand coded assembler (the default without __ARM_NEON__) - * - * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however - * this is *NOT* supported and may cease to work even after a minor revision - * to libpng. It *is* valid to do this for testing purposes, e.g. speed - * testing or a new compiler, but the results should be communicated to the - * libpng implementation list for incorporation in the next minor release. - */ -# ifndef PNG_ARM_NEON_IMPLEMENTATION -# ifdef __ARM_NEON__ -# if defined(__clang__) - /* At present it is unknown by the libpng developers which versions - * of clang support the intrinsics, however some or perhaps all - * versions do not work with the assembler so this may be - * irrelevant, so just use the default (do nothing here.) - */ -# elif defined(__GNUC__) - /* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to - * work, so if this *is* GCC, or G++, look for a version >4.5 - */ -# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) -# define PNG_ARM_NEON_IMPLEMENTATION 2 -# endif /* no GNUC support */ -# endif /* __GNUC__ */ -# else /* !defined __ARM_NEON__ */ - /* The 'intrinsics' code simply won't compile without this -mfpu=neon: - */ -# define PNG_ARM_NEON_IMPLEMENTATION 2 -# endif /* __ARM_NEON__ */ -# endif /* !defined PNG_ARM_NEON_IMPLEMENTATION */ - -# ifndef PNG_ARM_NEON_IMPLEMENTATION - /* Use the intrinsics code by default. */ -# define PNG_ARM_NEON_IMPLEMENTATION 1 -# endif -#endif /* PNG_ARM_NEON_OPT > 0 */ - -/* Is this a build of a DLL where compilation of the object modules requires - * different preprocessor settings to those required for a simple library? If - * so PNG_BUILD_DLL must be set. - * - * If libpng is used inside a DLL but that DLL does not export the libpng APIs - * PNG_BUILD_DLL must not be set. To avoid the code below kicking in build a - * static library of libpng then link the DLL against that. - */ -#ifndef PNG_BUILD_DLL -# ifdef DLL_EXPORT - /* This is set by libtool when files are compiled for a DLL; libtool - * always compiles twice, even on systems where it isn't necessary. Set - * PNG_BUILD_DLL in case it is necessary: - */ -# define PNG_BUILD_DLL -# else -# ifdef _WINDLL - /* This is set by the Microsoft Visual Studio IDE in projects that - * build a DLL. It can't easily be removed from those projects (it - * isn't visible in the Visual Studio UI) so it is a fairly reliable - * indication that PNG_IMPEXP needs to be set to the DLL export - * attributes. - */ -# define PNG_BUILD_DLL -# else -# ifdef __DLL__ - /* This is set by the Borland C system when compiling for a DLL - * (as above.) - */ -# define PNG_BUILD_DLL -# else - /* Add additional compiler cases here. */ -# endif -# endif -# endif -#endif /* Setting PNG_BUILD_DLL if required */ - -/* See pngconf.h for more details: the builder of the library may set this on - * the command line to the right thing for the specific compilation system or it - * may be automagically set above (at present we know of no system where it does - * need to be set on the command line.) - * - * PNG_IMPEXP must be set here when building the library to prevent pngconf.h - * setting it to the "import" setting for a DLL build. - */ -#ifndef PNG_IMPEXP -# ifdef PNG_BUILD_DLL -# define PNG_IMPEXP PNG_DLL_EXPORT -# else - /* Not building a DLL, or the DLL doesn't require specific export - * definitions. - */ -# define PNG_IMPEXP -# endif -#endif - -/* No warnings for private or deprecated functions in the build: */ -#ifndef PNG_DEPRECATED -# define PNG_DEPRECATED -#endif -#ifndef PNG_PRIVATE -# define PNG_PRIVATE -#endif - -/* Symbol preprocessing support. - * - * To enable listing global, but internal, symbols the following macros should - * always be used to declare an extern data or function object in this file. - */ -#ifndef PNG_INTERNAL_DATA -# define PNG_INTERNAL_DATA(type, name, array) extern type name array -#endif - -#ifndef PNG_INTERNAL_FUNCTION -# define PNG_INTERNAL_FUNCTION(type, name, args, attributes)\ - extern PNG_FUNCTION(type, name, args, PNG_EMPTY attributes) -#endif - -/* If floating or fixed point APIs are disabled they may still be compiled - * internally. To handle this make sure they are declared as the appropriate - * internal extern function (otherwise the symbol prefixing stuff won't work and - * the functions will be used without definitions.) - * - * NOTE: although all the API functions are declared here they are not all - * actually built! Because the declarations are still made it is necessary to - * fake out types that they depend on. - */ -#ifndef PNG_FP_EXPORT -# ifndef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FP_EXPORT(ordinal, type, name, args)\ - PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY); -# ifndef PNG_VERSION_INFO_ONLY - typedef struct png_incomplete png_double; - typedef png_double* png_doublep; - typedef const png_double* png_const_doublep; - typedef png_double** png_doublepp; -# endif -# endif -#endif -#ifndef PNG_FIXED_EXPORT -# ifndef PNG_FIXED_POINT_SUPPORTED -# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ - PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY); -# endif -#endif - -#include "png.h" - -/* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */ -#ifndef PNG_DLL_EXPORT -# define PNG_DLL_EXPORT -#endif - -/* SECURITY and SAFETY: - * - * By default libpng is built without any internal limits on image size, - * individual heap (png_malloc) allocations or the total amount of memory used. - * If PNG_SAFE_LIMITS_SUPPORTED is defined, however, the limits below are used - * (unless individually overridden). These limits are believed to be fairly - * safe, but builders of secure systems should verify the values against the - * real system capabilities. - */ -#ifdef PNG_SAFE_LIMITS_SUPPORTED - /* 'safe' limits */ -# ifndef PNG_USER_WIDTH_MAX -# define PNG_USER_WIDTH_MAX 1000000 -# endif -# ifndef PNG_USER_HEIGHT_MAX -# define PNG_USER_HEIGHT_MAX 1000000 -# endif -# ifndef PNG_USER_CHUNK_CACHE_MAX -# define PNG_USER_CHUNK_CACHE_MAX 128 -# endif -# ifndef PNG_USER_CHUNK_MALLOC_MAX -# define PNG_USER_CHUNK_MALLOC_MAX 8000000 -# endif -#else - /* values for no limits */ -# ifndef PNG_USER_WIDTH_MAX -# define PNG_USER_WIDTH_MAX 0x7fffffff -# endif -# ifndef PNG_USER_HEIGHT_MAX -# define PNG_USER_HEIGHT_MAX 0x7fffffff -# endif -# ifndef PNG_USER_CHUNK_CACHE_MAX -# define PNG_USER_CHUNK_CACHE_MAX 0 -# endif -# ifndef PNG_USER_CHUNK_MALLOC_MAX -# define PNG_USER_CHUNK_MALLOC_MAX 0 -# endif -#endif - -/* Moved to pngpriv.h at libpng-1.5.0 */ -/* NOTE: some of these may have been used in external applications as - * these definitions were exposed in pngconf.h prior to 1.5. - */ - -/* If you are running on a machine where you cannot allocate more - * than 64K of memory at once, uncomment this. While libpng will not - * normally need that much memory in a chunk (unless you load up a very - * large file), zlib needs to know how big of a chunk it can use, and - * libpng thus makes sure to check any memory allocation to verify it - * will fit into memory. - * - * zlib provides 'MAXSEG_64K' which, if defined, indicates the - * same limit and pngconf.h (already included) sets the limit - * if certain operating systems are detected. - */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) -# define PNG_MAX_MALLOC_64K -#endif - -#ifndef PNG_UNUSED -/* Unused formal parameter warnings are silenced using the following macro - * which is expected to have no bad effects on performance (optimizing - * compilers will probably remove it entirely). Note that if you replace - * it with something other than whitespace, you must include the terminating - * semicolon. - */ -# define PNG_UNUSED(param) (void)param; -#endif - -/* Just a little check that someone hasn't tried to define something - * contradictory. - */ -#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) -# undef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 65536L -#endif - -/* If warnings or errors are turned off the code is disabled or redirected here. - * From 1.5.4 functions have been added to allow very limited formatting of - * error and warning messages - this code will also be disabled here. - */ -#ifdef PNG_WARNINGS_SUPPORTED -# define PNG_WARNING_PARAMETERS(p) png_warning_parameters p; -#else -# define png_warning(s1,s2) ((void)(s1)) -# define png_chunk_warning(s1,s2) ((void)(s1)) -# define png_warning_parameter(p,number,string) ((void)0) -# define png_warning_parameter_unsigned(p,number,format,value) ((void)0) -# define png_warning_parameter_signed(p,number,format,value) ((void)0) -# define png_formatted_warning(pp,p,message) ((void)(pp)) -# define PNG_WARNING_PARAMETERS(p) -#endif -#ifndef PNG_ERROR_TEXT_SUPPORTED -# define png_error(s1,s2) png_err(s1) -# define png_chunk_error(s1,s2) png_err(s1) -# define png_fixed_error(s1,s2) png_err(s1) -#endif - -/* C allows up-casts from (void*) to any pointer and (const void*) to any - * pointer to a const object. C++ regards this as a type error and requires an - * explicit, static, cast and provides the static_cast<> rune to ensure that - * const is not cast away. - */ -#ifdef __cplusplus -# define png_voidcast(type, value) static_cast(value) -# define png_constcast(type, value) const_cast(value) -# define png_aligncast(type, value) \ - static_cast(static_cast(value)) -# define png_aligncastconst(type, value) \ - static_cast(static_cast(value)) -#else -# define png_voidcast(type, value) (value) -# define png_constcast(type, value) ((type)(value)) -# define png_aligncast(type, value) ((void*)(value)) -# define png_aligncastconst(type, value) ((const void*)(value)) -#endif /* __cplusplus */ - -/* Some fixed point APIs are still required even if not exported because - * they get used by the corresponding floating point APIs. This magic - * deals with this: - */ -#ifdef PNG_FIXED_POINT_SUPPORTED -# define PNGFAPI PNGAPI -#else -# define PNGFAPI /* PRIVATE */ -#endif - -#ifndef PNG_VERSION_INFO_ONLY -/* Other defines specific to compilers can go here. Try to keep - * them inside an appropriate ifdef/endif pair for portability. - */ -#if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ - defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) - /* png.c requires the following ANSI-C constants if the conversion of - * floating point to ASCII is implemented therein: - * - * DBL_DIG Maximum number of decimal digits (can be set to any constant) - * DBL_MIN Smallest normalized fp number (can be set to an arbitrary value) - * DBL_MAX Maximum floating point number (can be set to an arbitrary value) - */ -# include - -# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ - defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) - /* We need to check that hasn't already been included earlier - * as it seems it doesn't agree with , yet we should really use - * if possible. - */ -# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) -# include -# endif -# else -# include -# endif -# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) - /* Amiga SAS/C: We must include builtin FPU functions when compiling using - * MATH=68881 - */ -# include -# endif -#endif - -/* This provides the non-ANSI (far) memory allocation routines. */ -#if defined(__TURBOC__) && defined(__MSDOS__) -# include -# include -#endif - -#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ - defined(_WIN32) || defined(__WIN32__) -# include /* defines _WINDOWS_ macro */ -#endif -#endif /* PNG_VERSION_INFO_ONLY */ - -/* Moved here around 1.5.0beta36 from pngconf.h */ -/* Users may want to use these so they are not private. Any library - * functions that are passed far data must be model-independent. - */ - -/* Memory model/platform independent fns */ -#ifndef PNG_ABORT -# ifdef _WINDOWS_ -# define PNG_ABORT() ExitProcess(0) -# else -# define PNG_ABORT() abort() -# endif -#endif - -/* These macros may need to be architecture dependent. */ -#define PNG_ALIGN_NONE 0 /* do not use data alignment */ -#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */ -#ifdef offsetof -# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */ -#else -# define PNG_ALIGN_OFFSET -1 /* prevent the use of this */ -#endif -#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */ - -#ifndef PNG_ALIGN_TYPE - /* Default to using aligned access optimizations and requiring alignment to a - * multiple of the data type size. Override in a compiler specific fashion - * if necessary by inserting tests here: - */ -# define PNG_ALIGN_TYPE PNG_ALIGN_SIZE -#endif - -#if PNG_ALIGN_TYPE == PNG_ALIGN_SIZE - /* This is used because in some compiler implementations non-aligned - * structure members are supported, so the offsetof approach below fails. - * Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access - * is good for performance. Do not do this unless you have tested the result - * and understand it. - */ -# define png_alignof(type) (sizeof (type)) -#else -# if PNG_ALIGN_TYPE == PNG_ALIGN_OFFSET -# define png_alignof(type) offsetof(struct{char c; type t;}, t) -# else -# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS -# define png_alignof(type) (1) -# endif - /* Else leave png_alignof undefined to prevent use thereof */ -# endif -#endif - -/* This implicitly assumes alignment is always to a power of 2. */ -#ifdef png_alignof -# define png_isaligned(ptr, type)\ - ((((const char*)ptr-(const char*)0) & (png_alignof(type)-1)) == 0) -#else -# define png_isaligned(ptr, type) 0 -#endif - -/* End of memory model/platform independent support */ -/* End of 1.5.0beta36 move from pngconf.h */ - -/* CONSTANTS and UTILITY MACROS - * These are used internally by libpng and not exposed in the API - */ - -/* Various modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. Three of these - * are defined in png.h because they need to be visible to applications - * that call png_set_unknown_chunk(). - */ -/* #define PNG_HAVE_IHDR 0x01 (defined in png.h) */ -/* #define PNG_HAVE_PLTE 0x02 (defined in png.h) */ -#define PNG_HAVE_IDAT 0x04 -/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */ -#define PNG_HAVE_IEND 0x10 - /* 0x20 (unused) */ - /* 0x40 (unused) */ - /* 0x80 (unused) */ -#define PNG_HAVE_CHUNK_HEADER 0x100 -#define PNG_WROTE_tIME 0x200 -#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 -#define PNG_BACKGROUND_IS_GRAY 0x800 -#define PNG_HAVE_PNG_SIGNATURE 0x1000 -#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ - /* 0x4000 (unused) */ -#define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */ - -/* Flags for the transformations the PNG library does on the image data */ -#define PNG_BGR 0x0001 -#define PNG_INTERLACE 0x0002 -#define PNG_PACK 0x0004 -#define PNG_SHIFT 0x0008 -#define PNG_SWAP_BYTES 0x0010 -#define PNG_INVERT_MONO 0x0020 -#define PNG_QUANTIZE 0x0040 -#define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ -#define PNG_BACKGROUND_EXPAND 0x0100 -#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ -#define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ -#define PNG_RGBA 0x0800 -#define PNG_EXPAND 0x1000 -#define PNG_GAMMA 0x2000 -#define PNG_GRAY_TO_RGB 0x4000 -#define PNG_FILLER 0x8000 -#define PNG_PACKSWAP 0x10000 -#define PNG_SWAP_ALPHA 0x20000 -#define PNG_STRIP_ALPHA 0x40000 -#define PNG_INVERT_ALPHA 0x80000 -#define PNG_USER_TRANSFORM 0x100000 -#define PNG_RGB_TO_GRAY_ERR 0x200000 -#define PNG_RGB_TO_GRAY_WARN 0x400000 -#define PNG_RGB_TO_GRAY 0x600000 /* two bits, RGB_TO_GRAY_ERR|WARN */ -#define PNG_ENCODE_ALPHA 0x800000 /* Added to libpng-1.5.4 */ -#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */ -#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */ -#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */ - /* 0x8000000 unused */ - /* 0x10000000 unused */ - /* 0x20000000 unused */ - /* 0x40000000 unused */ -/* Flags for png_create_struct */ -#define PNG_STRUCT_PNG 0x0001 -#define PNG_STRUCT_INFO 0x0002 - -/* Scaling factor for filter heuristic weighting calculations */ -#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) -#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) - -/* Flags for the png_ptr->flags rather than declaring a byte for each one */ -#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 -#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */ - /* 0x0004 unused */ -#define PNG_FLAG_ZSTREAM_ENDED 0x0008 /* Added to libpng-1.6.0 */ - /* 0x0010 unused */ - /* 0x0020 unused */ -#define PNG_FLAG_ROW_INIT 0x0040 -#define PNG_FLAG_FILLER_AFTER 0x0080 -#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 -#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 -#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 -#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 -#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ -#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ -#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ -/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 */ -/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 */ -#define PNG_FLAG_LIBRARY_MISMATCH 0x20000 -#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000 -#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000 -#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000 /* Added to libpng-1.4.0 */ -#define PNG_FLAG_APP_WARNINGS_WARN 0x200000 /* Added to libpng-1.6.0 */ -#define PNG_FLAG_APP_ERRORS_WARN 0x400000 /* Added to libpng-1.6.0 */ - /* 0x800000 unused */ - /* 0x1000000 unused */ - /* 0x2000000 unused */ - /* 0x4000000 unused */ - /* 0x8000000 unused */ - /* 0x10000000 unused */ - /* 0x20000000 unused */ - /* 0x40000000 unused */ - -#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ - PNG_FLAG_CRC_ANCILLARY_NOWARN) - -#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ - PNG_FLAG_CRC_CRITICAL_IGNORE) - -#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ - PNG_FLAG_CRC_CRITICAL_MASK) - -/* Save typing and make code easier to understand */ - -#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ - abs((int)((c1).green) - (int)((c2).green)) + \ - abs((int)((c1).blue) - (int)((c2).blue))) - -/* Added to libpng-1.6.0: scale a 16-bit value in the range 0..65535 to 0..255 - * by dividing by 257 *with rounding*. This macro is exact for the given range. - * See the discourse in pngrtran.c png_do_scale_16_to_8. The values in the - * macro were established by experiment (modifying the added value). The macro - * has a second variant that takes a value already scaled by 255 and divides by - * 65535 - this has a maximum error of .502. Over the range 0..65535*65535 it - * only gives off-by-one errors and only for 0.5% (1 in 200) of the values. - */ -#define PNG_DIV65535(v24) (((v24) + 32895) >> 16) -#define PNG_DIV257(v16) PNG_DIV65535((png_uint_32)(v16) * 255) - -/* Added to libpng-1.2.6 JB */ -#define PNG_ROWBYTES(pixel_bits, width) \ - ((pixel_bits) >= 8 ? \ - ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ - (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) - -/* PNG_OUT_OF_RANGE returns true if value is outside the range - * ideal-delta..ideal+delta. Each argument is evaluated twice. - * "ideal" and "delta" should be constants, normally simple - * integers, "value" a variable. Added to libpng-1.2.6 JB - */ -#define PNG_OUT_OF_RANGE(value, ideal, delta) \ - ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) - -/* Conversions between fixed and floating point, only defined if - * required (to make sure the code doesn't accidentally use float - * when it is supposedly disabled.) - */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -/* The floating point conversion can't overflow, though it can and - * does lose accuracy relative to the original fixed point value. - * In practice this doesn't matter because png_fixed_point only - * stores numbers with very low precision. The png_ptr and s - * arguments are unused by default but are there in case error - * checking becomes a requirement. - */ -#define png_float(png_ptr, fixed, s) (.00001 * (fixed)) - -/* The fixed point conversion performs range checking and evaluates - * its argument multiple times, so must be used with care. The - * range checking uses the PNG specification values for a signed - * 32 bit fixed point value except that the values are deliberately - * rounded-to-zero to an integral value - 21474 (21474.83 is roughly - * (2^31-1) * 100000). 's' is a string that describes the value being - * converted. - * - * NOTE: this macro will raise a png_error if the range check fails, - * therefore it is normally only appropriate to use this on values - * that come from API calls or other sources where an out of range - * error indicates a programming error, not a data error! - * - * NOTE: by default this is off - the macro is not used - because the - * function call saves a lot of code. - */ -#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED -#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\ - ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0)) -#endif -/* else the corresponding function is defined below, inside the scope of the - * cplusplus test. - */ -#endif - -/* Constants for known chunk types. If you need to add a chunk, define the name - * here. For historical reasons these constants have the form png_; i.e. - * the prefix is lower case. Please use decimal values as the parameters to - * match the ISO PNG specification and to avoid relying on the C locale - * interpretation of character values. - * - * Prior to 1.5.6 these constants were strings, as of 1.5.6 png_uint_32 values - * are computed and a new macro (PNG_STRING_FROM_CHUNK) added to allow a string - * to be generated if required. - * - * PNG_32b correctly produces a value shifted by up to 24 bits, even on - * architectures where (int) is only 16 bits. - */ -#define PNG_32b(b,s) ((png_uint_32)(b) << (s)) -#define PNG_U32(b1,b2,b3,b4) \ - (PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0)) - -/* Constants for known chunk types. - * - * MAINTAINERS: If you need to add a chunk, define the name here. - * For historical reasons these constants have the form png_; i.e. - * the prefix is lower case. Please use decimal values as the parameters to - * match the ISO PNG specification and to avoid relying on the C locale - * interpretation of character values. Please keep the list sorted. - * - * Notice that PNG_U32 is used to define a 32-bit value for the 4 byte chunk - * type. In fact the specification does not express chunk types this way, - * however using a 32-bit value means that the chunk type can be read from the - * stream using exactly the same code as used for a 32-bit unsigned value and - * can be examined far more efficiently (using one arithmetic compare). - * - * Prior to 1.5.6 the chunk type constants were expressed as C strings. The - * libpng API still uses strings for 'unknown' chunks and a macro, - * PNG_STRING_FROM_CHUNK, allows a string to be generated if required. Notice - * that for portable code numeric values must still be used; the string "IHDR" - * is not portable and neither is PNG_U32('I', 'H', 'D', 'R'). - * - * In 1.7.0 the definitions will be made public in png.h to avoid having to - * duplicate the same definitions in application code. - */ -#define png_IDAT PNG_U32( 73, 68, 65, 84) -#define png_IEND PNG_U32( 73, 69, 78, 68) -#define png_IHDR PNG_U32( 73, 72, 68, 82) -#define png_PLTE PNG_U32( 80, 76, 84, 69) -#define png_bKGD PNG_U32( 98, 75, 71, 68) -#define png_cHRM PNG_U32( 99, 72, 82, 77) -#define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */ -#define png_gAMA PNG_U32(103, 65, 77, 65) -#define png_gIFg PNG_U32(103, 73, 70, 103) -#define png_gIFt PNG_U32(103, 73, 70, 116) /* deprecated */ -#define png_gIFx PNG_U32(103, 73, 70, 120) -#define png_hIST PNG_U32(104, 73, 83, 84) -#define png_iCCP PNG_U32(105, 67, 67, 80) -#define png_iTXt PNG_U32(105, 84, 88, 116) -#define png_oFFs PNG_U32(111, 70, 70, 115) -#define png_pCAL PNG_U32(112, 67, 65, 76) -#define png_pHYs PNG_U32(112, 72, 89, 115) -#define png_sBIT PNG_U32(115, 66, 73, 84) -#define png_sCAL PNG_U32(115, 67, 65, 76) -#define png_sPLT PNG_U32(115, 80, 76, 84) -#define png_sRGB PNG_U32(115, 82, 71, 66) -#define png_sTER PNG_U32(115, 84, 69, 82) -#define png_tEXt PNG_U32(116, 69, 88, 116) -#define png_tIME PNG_U32(116, 73, 77, 69) -#define png_tRNS PNG_U32(116, 82, 78, 83) -#define png_zTXt PNG_U32(122, 84, 88, 116) - -/* The following will work on (signed char*) strings, whereas the get_uint_32 - * macro will fail on top-bit-set values because of the sign extension. - */ -#define PNG_CHUNK_FROM_STRING(s)\ - PNG_U32(0xff&(s)[0], 0xff&(s)[1], 0xff&(s)[2], 0xff&(s)[3]) - -/* This uses (char), not (png_byte) to avoid warnings on systems where (char) is - * signed and the argument is a (char[]) This macro will fail miserably on - * systems where (char) is more than 8 bits. - */ -#define PNG_STRING_FROM_CHUNK(s,c)\ - (void)(((char*)(s))[0]=(char)((c)>>24), ((char*)(s))[1]=(char)((c)>>16),\ - ((char*)(s))[2]=(char)((c)>>8), ((char*)(s))[3]=(char)((c))) - -/* Do the same but terminate with a null character. */ -#define PNG_CSTRING_FROM_CHUNK(s,c)\ - (void)(PNG_STRING_FROM_CHUNK(s,c), ((char*)(s))[4] = 0) - -/* Test on flag values as defined in the spec (section 5.4): */ -#define PNG_CHUNK_ANCILLARY(c) (1 & ((c) >> 29)) -#define PNG_CHUNK_CRITICAL(c) (!PNG_CHUNK_ANCILLARY(c)) -#define PNG_CHUNK_PRIVATE(c) (1 & ((c) >> 21)) -#define PNG_CHUNK_RESERVED(c) (1 & ((c) >> 13)) -#define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >> 5)) - -/* Gamma values (new at libpng-1.5.4): */ -#define PNG_GAMMA_MAC_OLD 151724 /* Assume '1.8' is really 2.2/1.45! */ -#define PNG_GAMMA_MAC_INVERSE 65909 -#define PNG_GAMMA_sRGB_INVERSE 45455 - -/* Almost everything below is C specific; the #defines above can be used in - * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot. - */ -#ifndef PNG_VERSION_INFO_ONLY - -#include "pngstruct.h" -#include "pnginfo.h" - -/* Validate the include paths - the include path used to generate pnglibconf.h - * must match that used in the build, or we must be using pnglibconf.h.prebuilt: - */ -#if PNG_ZLIB_VERNUM != 0 && PNG_ZLIB_VERNUM != ZLIB_VERNUM -# error ZLIB_VERNUM != PNG_ZLIB_VERNUM \ - "-I (include path) error: see the notes in pngpriv.h" - /* This means that when pnglibconf.h was built the copy of zlib.h that it - * used is not the same as the one being used here. Because the build of - * libpng makes decisions to use inflateInit2 and inflateReset2 based on the - * zlib version number and because this affects handling of certain broken - * PNG files the -I directives must match. - * - * The most likely explanation is that you passed a -I in CFLAGS, this will - * not work; all the preprocessor directories and in particular all the -I - * directives must be in CPPFLAGS. - */ -#endif - -/* This is used for 16 bit gamma tables -- only the top level pointers are - * const; this could be changed: - */ -typedef const png_uint_16p * png_const_uint_16pp; - -/* Added to libpng-1.5.7: sRGB conversion tables */ -#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ - defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) -#ifdef PNG_SIMPLIFIED_READ_SUPPORTED -PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_table, [256]); - /* Convert from an sRGB encoded value 0..255 to a 16-bit linear value, - * 0..65535. This table gives the closest 16-bit answers (no errors). - */ -#endif - -PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_base, [512]); -PNG_INTERNAL_DATA(const png_byte, png_sRGB_delta, [512]); - -#define PNG_sRGB_FROM_LINEAR(linear) ((png_byte)((png_sRGB_base[(linear)>>15] +\ - ((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8)) - /* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB - * encoded value with maximum error 0.646365. Note that the input is not a - * 16-bit value; it has been multiplied by 255! */ -#endif /* PNG_SIMPLIFIED_READ/WRITE */ - - -/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* Internal functions; these are not exported from a DLL however because they - * are used within several of the C source files they have to be C extern. - * - * All of these functions must be declared with PNG_INTERNAL_FUNCTION. - */ - -/* Zlib support */ -#define PNG_UNEXPECTED_ZLIB_RETURN (-7) -PNG_INTERNAL_FUNCTION(void, png_zstream_error,(png_structrp png_ptr, int ret), - PNG_EMPTY); - /* Used by the zlib handling functions to ensure that z_stream::msg is always - * set before they return. - */ - -#ifdef PNG_WRITE_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr, - png_compression_bufferp *list),PNG_EMPTY); - /* Free the buffer list used by the compressed write code. */ -#endif - -#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ - !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \ - (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \ - defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \ - (defined(PNG_sCAL_SUPPORTED) && \ - defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)) -PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr, - double fp, png_const_charp text),PNG_EMPTY); -#endif - -/* Check the user version string for compatibility, returns false if the version - * numbers aren't compatible. - */ -PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr, - png_const_charp user_png_ver),PNG_EMPTY); - -/* Internal base allocator - no messages, NULL on failure to allocate. This - * does, however, call the application provided allocator and that could call - * png_error (although that would be a bug in the application implementation.) - */ -PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_base,(png_const_structrp png_ptr, - png_alloc_size_t size),PNG_ALLOCATED); - -#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\ - defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) -/* Internal array allocator, outputs no error or warning messages on failure, - * just returns NULL. - */ -PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_array,(png_const_structrp png_ptr, - int nelements, size_t element_size),PNG_ALLOCATED); - -/* The same but an existing array is extended by add_elements. This function - * also memsets the new elements to 0 and copies the old elements. The old - * array is not freed or altered. - */ -PNG_INTERNAL_FUNCTION(png_voidp,png_realloc_array,(png_const_structrp png_ptr, - png_const_voidp array, int old_elements, int add_elements, - size_t element_size),PNG_ALLOCATED); -#endif /* text, sPLT or unknown chunks */ - -/* Magic to create a struct when there is no struct to call the user supplied - * memory allocators. Because error handling has not been set up the memory - * handlers can't safely call png_error, but this is an obscure and undocumented - * restriction so libpng has to assume that the 'free' handler, at least, might - * call png_error. - */ -PNG_INTERNAL_FUNCTION(png_structp,png_create_png_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn, - png_free_ptr free_fn),PNG_ALLOCATED); - -/* Free memory from internal libpng struct */ -PNG_INTERNAL_FUNCTION(void,png_destroy_png_struct,(png_structrp png_ptr), - PNG_EMPTY); - -/* Free an allocated jmp_buf (always succeeds) */ -PNG_INTERNAL_FUNCTION(void,png_free_jmpbuf,(png_structrp png_ptr),PNG_EMPTY); - -/* Function to allocate memory for zlib. PNGAPI is disallowed. */ -PNG_INTERNAL_FUNCTION(voidpf,png_zalloc,(voidpf png_ptr, uInt items, uInt size), - PNG_ALLOCATED); - -/* Function to free memory for zlib. PNGAPI is disallowed. */ -PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY); - -/* Next four functions are used internally as callbacks. PNGCBAPI is required - * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to - * PNGCBAPI at 1.5.0 - */ - -PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr, - png_bytep buffer, png_size_t length),PNG_EMPTY); -#endif - -PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -# ifdef PNG_STDIO_SUPPORTED -PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_flush,(png_structp png_ptr), - PNG_EMPTY); -# endif -#endif - -/* Reset the CRC variable */ -PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY); - -/* Write the "data" buffer to whatever output you are using */ -PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr, - png_const_bytep data, png_size_t length),PNG_EMPTY); - -/* Read and check the PNG file signature */ -PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); - -/* Read the chunk header (length + type name) */ -PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr), - PNG_EMPTY); - -/* Read data from whatever input you are using into the "data" buffer */ -PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data, - png_size_t length),PNG_EMPTY); - -/* Read bytes into buf, and update png_ptr->crc */ -PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf, - png_uint_32 length),PNG_EMPTY); - -/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ -PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr, - png_uint_32 skip),PNG_EMPTY); - -/* Read the CRC from the file and compare it to the libpng calculated CRC */ -PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY); - -/* Calculate the CRC over a section of data. Note that we are only - * passing a maximum of 64K on systems that have this as a memory limit, - * since this is the maximum buffer size we can specify. - */ -PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr, - png_const_bytep ptr, png_size_t length),PNG_EMPTY); - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); -#endif - -/* Write various chunks */ - -/* Write the IHDR chunk, and update the png_struct with the necessary - * information. - */ -PNG_INTERNAL_FUNCTION(void,png_write_IHDR,(png_structrp png_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, - int compression_method, int filter_method, int interlace_method),PNG_EMPTY); - -PNG_INTERNAL_FUNCTION(void,png_write_PLTE,(png_structrp png_ptr, - png_const_colorp palette, png_uint_32 num_pal),PNG_EMPTY); - -PNG_INTERNAL_FUNCTION(void,png_compress_IDAT,(png_structrp png_ptr, - png_const_bytep row_data, png_alloc_size_t row_data_length, int flush), - PNG_EMPTY); - -PNG_INTERNAL_FUNCTION(void,png_write_IEND,(png_structrp png_ptr),PNG_EMPTY); - -#ifdef PNG_WRITE_gAMA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_gAMA_fixed,(png_structrp png_ptr, - png_fixed_point file_gamma),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_sBIT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_sBIT,(png_structrp png_ptr, - png_const_color_8p sbit, int color_type),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_cHRM_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr, - const png_xy *xy), PNG_EMPTY); - /* The xy value must have been previously validated */ -#endif - -#ifdef PNG_WRITE_sRGB_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr, - int intent),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_iCCP_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr, - png_const_charp name, png_const_bytep profile), PNG_EMPTY); - /* The profile must have been previously validated for correctness, the - * length comes from the first four bytes. Only the base, deflate, - * compression is supported. - */ -#endif - -#ifdef PNG_WRITE_sPLT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_sPLT,(png_structrp png_ptr, - png_const_sPLT_tp palette),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_tRNS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_tRNS,(png_structrp png_ptr, - png_const_bytep trans, png_const_color_16p values, int number, - int color_type),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_bKGD_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_bKGD,(png_structrp png_ptr, - png_const_color_16p values, int color_type),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_hIST_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr, - png_const_uint_16p hist, int num_hist),PNG_EMPTY); -#endif - -/* Chunks that have keywords */ -#ifdef PNG_WRITE_tEXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr, - png_const_charp key, png_const_charp text, png_size_t text_len),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_zTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_zTXt,(png_structrp png_ptr, png_const_charp - key, png_const_charp text, png_size_t text_len, int compression),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_iTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_iTXt,(png_structrp png_ptr, - int compression, png_const_charp key, png_const_charp lang, - png_const_charp lang_key, png_const_charp text),PNG_EMPTY); -#endif - -#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ -PNG_INTERNAL_FUNCTION(int,png_set_text_2,(png_const_structrp png_ptr, - png_inforp info_ptr, png_const_textp text_ptr, int num_text),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_oFFs_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_oFFs,(png_structrp png_ptr, - png_int_32 x_offset, png_int_32 y_offset, int unit_type),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_pCAL_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_pCAL,(png_structrp png_ptr, - png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, - png_const_charp units, png_charpp params),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_pHYs_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_pHYs,(png_structrp png_ptr, - png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, - int unit_type),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_tIME_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_tIME,(png_structrp png_ptr, - png_const_timep mod_time),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_sCAL_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_sCAL_s,(png_structrp png_ptr, - int unit, png_const_charp width, png_const_charp height),PNG_EMPTY); -#endif - -/* Called when finished processing a row of data */ -PNG_INTERNAL_FUNCTION(void,png_write_finish_row,(png_structrp png_ptr), - PNG_EMPTY); - -/* Internal use only. Called before first row of data */ -PNG_INTERNAL_FUNCTION(void,png_write_start_row,(png_structrp png_ptr), - PNG_EMPTY); - -/* Combine a row of data, dealing with alpha, etc. if requested. 'row' is an - * array of png_ptr->width pixels. If the image is not interlaced or this - * is the final pass this just does a memcpy, otherwise the "display" flag - * is used to determine whether to copy pixels that are not in the current pass. - * - * Because 'png_do_read_interlace' (below) replicates pixels this allows this - * function to achieve the documented 'blocky' appearance during interlaced read - * if display is 1 and the 'sparkle' appearance, where existing pixels in 'row' - * are not changed if they are not in the current pass, when display is 0. - * - * 'display' must be 0 or 1, otherwise the memcpy will be done regardless. - * - * The API always reads from the png_struct row buffer and always assumes that - * it is full width (png_do_read_interlace has already been called.) - * - * This function is only ever used to write to row buffers provided by the - * caller of the relevant libpng API and the row must have already been - * transformed by the read transformations. - * - * The PNG_USE_COMPILE_TIME_MASKS option causes generation of pre-computed - * bitmasks for use within the code, otherwise runtime generated masks are used. - * The default is compile time masks. - */ -#ifndef PNG_USE_COMPILE_TIME_MASKS -# define PNG_USE_COMPILE_TIME_MASKS 1 -#endif -PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr, - png_bytep row, int display),PNG_EMPTY); - -#ifdef PNG_READ_INTERLACING_SUPPORTED -/* Expand an interlaced row: the 'row_info' describes the pass data that has - * been read in and must correspond to the pixels in 'row', the pixels are - * expanded (moved apart) in 'row' to match the final layout, when doing this - * the pixels are *replicated* to the intervening space. This is essential for - * the correct operation of png_combine_row, above. - */ -PNG_INTERNAL_FUNCTION(void,png_do_read_interlace,(png_row_infop row_info, - png_bytep row, int pass, png_uint_32 transformations),PNG_EMPTY); -#endif - -/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED -/* Grab pixels out of a row for an interlaced pass */ -PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info, - png_bytep row, int pass),PNG_EMPTY); -#endif - -/* Unfilter a row: check the filter value before calling this, there is no point - * calling it for PNG_FILTER_VALUE_NONE. - */ -PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop - row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY); - -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info, - png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); - -/* Choose the best filter to use and filter the row data */ -PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, - png_row_infop row_info),PNG_EMPTY); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr, - png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY); - /* Read 'avail_out' bytes of data from the IDAT stream. If the output buffer - * is NULL the function checks, instead, for the end of the stream. In this - * case a benign error will be issued if the stream end is not found or if - * extra data has to be consumed. - */ -PNG_INTERNAL_FUNCTION(void,png_read_finish_IDAT,(png_structrp png_ptr), - PNG_EMPTY); - /* This cleans up when the IDAT LZ stream does not end when the last image - * byte is read; there is still some pending input. - */ - -PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr), - PNG_EMPTY); - /* Finish a row while reading, dealing with interlacing passes, etc. */ -#endif - -/* Initialize the row buffers, etc. */ -PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY); - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -/* Optional call to update the users info structure */ -PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -#endif - -/* These are the functions that do the transformations */ -#ifdef PNG_READ_FILLER_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_read_filler,(png_row_infop row_info, - png_bytep row, png_uint_32 filler, png_uint_32 flags),PNG_EMPTY); -#endif - -#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_read_swap_alpha,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_write_swap_alpha,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_read_invert_alpha,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_write_invert_alpha,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ - defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_strip_channel,(png_row_infop row_info, - png_bytep row, int at_start),PNG_EMPTY); -#endif - -#ifdef PNG_16BIT_SUPPORTED -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_swap,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ - defined(PNG_WRITE_PACKSWAP_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_packswap,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -PNG_INTERNAL_FUNCTION(int,png_do_rgb_to_gray,(png_structrp png_ptr, - png_row_infop row_info, png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_gray_to_rgb,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_READ_PACK_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_unpack,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_READ_SHIFT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_unshift,(png_row_infop row_info, - png_bytep row, png_const_color_8p sig_bits),PNG_EMPTY); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_invert,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_scale_16_to_8,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_chop,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_quantize,(png_row_infop row_info, - png_bytep row, png_const_bytep palette_lookup, - png_const_bytep quantize_lookup),PNG_EMPTY); - -# ifdef PNG_CORRECT_PALETTE_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_correct_palette,(png_structrp png_ptr, - png_colorp palette, int num_palette),PNG_EMPTY); -# endif -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_PACK_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_pack,(png_row_infop row_info, - png_bytep row, png_uint_32 bit_depth),PNG_EMPTY); -#endif - -#ifdef PNG_WRITE_SHIFT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_shift,(png_row_infop row_info, - png_bytep row, png_const_color_8p bit_depth),PNG_EMPTY); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_compose,(png_row_infop row_info, - png_bytep row, png_structrp png_ptr),PNG_EMPTY); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_gamma,(png_row_infop row_info, - png_bytep row, png_structrp png_ptr),PNG_EMPTY); -#endif - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_encode_alpha,(png_row_infop row_info, - png_bytep row, png_structrp png_ptr),PNG_EMPTY); -#endif - -#ifdef PNG_READ_EXPAND_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_expand_palette,(png_row_infop row_info, - png_bytep row, png_const_colorp palette, png_const_bytep trans, - int num_trans),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_do_expand,(png_row_infop row_info, - png_bytep row, png_const_color_16p trans_color),PNG_EMPTY); -#endif - -#ifdef PNG_READ_EXPAND_16_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_expand_16,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -/* The following decodes the appropriate chunks, and does error correction, - * then calls the appropriate callback for the chunk if it is valid. - */ - -/* Decode the IHDR chunk */ -PNG_INTERNAL_FUNCTION(void,png_handle_IHDR,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_handle_PLTE,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_handle_IEND,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); - -#ifdef PNG_READ_bKGD_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_bKGD,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_cHRM_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_gAMA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_hIST_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_hIST,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_iCCP_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_iCCP,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif /* PNG_READ_iCCP_SUPPORTED */ - -#ifdef PNG_READ_iTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_iTXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_oFFs_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_oFFs,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_pCAL,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_pHYs_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_pHYs,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_sBIT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_sBIT,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_sCAL_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_sCAL,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_sPLT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_sPLT,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif /* PNG_READ_sPLT_SUPPORTED */ - -#ifdef PNG_READ_sRGB_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_sRGB,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_tEXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_tEXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_tIME_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_tIME,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_tRNS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_tRNS,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr, - png_uint_32 chunk_name),PNG_EMPTY); - -#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY); - /* This is the function that gets called for unknown chunks. The 'keep' - * argument is either non-zero for a known chunk that has been set to be - * handled as unknown or zero for an unknown chunk. By default the function - * just skips the chunk or errors out if it is critical. - */ - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\ - defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) -PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling, - (png_const_structrp png_ptr, png_uint_32 chunk_name),PNG_EMPTY); - /* Exactly as the API png_handle_as_unknown() except that the argument is a - * 32-bit chunk name, not a string. - */ -#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */ -#endif /* PNG_SET_UNKNOWN_CHUNKS_SUPPORTED */ - -/* Handle the transformations for reading and writing */ -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_read_transformations,(png_structrp png_ptr, - png_row_infop row_info),PNG_EMPTY); -#endif -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_write_transformations,(png_structrp png_ptr, - png_row_infop row_info),PNG_EMPTY); -#endif - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_init_read_transformations,(png_structrp png_ptr), - PNG_EMPTY); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_push_read_chunk,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_sig,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_crc_skip,(png_structrp png_ptr, - png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_crc_finish,(png_structrp png_ptr), - PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr), - PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr), - PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_have_row,(png_structrp png_ptr, - png_bytep row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_end,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_push_finish_row,(png_structrp png_ptr), - PNG_EMPTY); -# ifdef PNG_READ_tEXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_push_handle_tEXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_tEXt,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -# endif -# ifdef PNG_READ_zTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_push_handle_zTXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_zTXt,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -# endif -# ifdef PNG_READ_iTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_push_handle_iTXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_iTXt,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -# endif - -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_read_intrapixel,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_do_write_intrapixel,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); -#endif - -/* Added at libpng version 1.6.0 */ -#ifdef PNG_GAMMA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_fixed_point gAMA), PNG_EMPTY); - /* Set the colorspace gamma with a value provided by the application or by - * the gAMA chunk on read. The value will override anything set by an ICC - * profile. - */ - -PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr, - png_inforp info_ptr), PNG_EMPTY); - /* Synchronize the info 'valid' flags with the colorspace */ - -PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr, - png_inforp info_ptr), PNG_EMPTY); - /* Copy the png_struct colorspace to the info_struct and call the above to - * synchronize the flags. Checks for NULL info_ptr and does nothing. - */ -#endif - -/* Added at libpng version 1.4.0 */ -#ifdef PNG_COLORSPACE_SUPPORTED -/* These internal functions are for maintaining the colorspace structure within - * a png_info or png_struct (or, indeed, both). - */ -PNG_INTERNAL_FUNCTION(int,png_colorspace_set_chromaticities, - (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_xy *xy, - int preferred), PNG_EMPTY); - -PNG_INTERNAL_FUNCTION(int,png_colorspace_set_endpoints, - (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_XYZ *XYZ, - int preferred), PNG_EMPTY); - -#ifdef PNG_sRGB_SUPPORTED -PNG_INTERNAL_FUNCTION(int,png_colorspace_set_sRGB,(png_const_structrp png_ptr, - png_colorspacerp colorspace, int intent), PNG_EMPTY); - /* This does set the colorspace gAMA and cHRM values too, but doesn't set the - * flags to write them, if it returns false there was a problem and an error - * message has already been output (but the colorspace may still need to be - * synced to record the invalid flag). - */ -#endif /* sRGB */ - -#ifdef PNG_iCCP_SUPPORTED -PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_charp name, - png_uint_32 profile_length, png_const_bytep profile, int color_type), - PNG_EMPTY); - /* The 'name' is used for information only */ - -/* Routines for checking parts of an ICC profile. */ -PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_charp name, - png_uint_32 profile_length), PNG_EMPTY); -PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_charp name, - png_uint_32 profile_length, - png_const_bytep profile /* first 132 bytes only */, int color_type), - PNG_EMPTY); -PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_charp name, - png_uint_32 profile_length, - png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY); -#ifdef PNG_sRGB_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_icc_set_sRGB,( - png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_bytep profile, uLong adler), PNG_EMPTY); - /* 'adler' is the Adler32 checksum of the uncompressed profile data. It may - * be zero to indicate that it is not available. It is used, if provided, - * as a fast check on the profile when checking to see if it is sRGB. - */ -#endif -#endif /* iCCP */ - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_colorspace_set_rgb_coefficients, - (png_structrp png_ptr), PNG_EMPTY); - /* Set the rgb_to_gray coefficients from the colorspace Y values */ -#endif /* READ_RGB_TO_GRAY */ -#endif /* COLORSPACE */ - -/* Added at libpng version 1.4.0 */ -PNG_INTERNAL_FUNCTION(void,png_check_IHDR,(png_const_structrp png_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_type, int compression_type, - int filter_type),PNG_EMPTY); - -/* Added at libpng version 1.5.10 */ -#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \ - defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_check_palette_indexes, - (png_structrp png_ptr, png_row_infop row_info),PNG_EMPTY); -#endif - -#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_fixed_error,(png_const_structrp png_ptr, - png_const_charp name),PNG_NORETURN); -#endif - -/* Puts 'string' into 'buffer' at buffer[pos], taking care never to overwrite - * the end. Always leaves the buffer nul terminated. Never errors out (and - * there is no error code.) - */ -PNG_INTERNAL_FUNCTION(size_t,png_safecat,(png_charp buffer, size_t bufsize, - size_t pos, png_const_charp string),PNG_EMPTY); - -/* Various internal functions to handle formatted warning messages, currently - * only implemented for warnings. - */ -#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) -/* Utility to dump an unsigned value into a buffer, given a start pointer and - * and end pointer (which should point just *beyond* the end of the buffer!) - * Returns the pointer to the start of the formatted string. This utility only - * does unsigned values. - */ -PNG_INTERNAL_FUNCTION(png_charp,png_format_number,(png_const_charp start, - png_charp end, int format, png_alloc_size_t number),PNG_EMPTY); - -/* Convenience macro that takes an array: */ -#define PNG_FORMAT_NUMBER(buffer,format,number) \ - png_format_number(buffer, buffer + (sizeof buffer), format, number) - -/* Suggested size for a number buffer (enough for 64 bits and a sign!) */ -#define PNG_NUMBER_BUFFER_SIZE 24 - -/* These are the integer formats currently supported, the name is formed from - * the standard printf(3) format string. - */ -#define PNG_NUMBER_FORMAT_u 1 /* chose unsigned API! */ -#define PNG_NUMBER_FORMAT_02u 2 -#define PNG_NUMBER_FORMAT_d 1 /* chose signed API! */ -#define PNG_NUMBER_FORMAT_02d 2 -#define PNG_NUMBER_FORMAT_x 3 -#define PNG_NUMBER_FORMAT_02x 4 -#define PNG_NUMBER_FORMAT_fixed 5 /* choose the signed API */ -#endif - -#ifdef PNG_WARNINGS_SUPPORTED -/* New defines and members adding in libpng-1.5.4 */ -# define PNG_WARNING_PARAMETER_SIZE 32 -# define PNG_WARNING_PARAMETER_COUNT 8 /* Maximum 9; see pngerror.c */ - -/* An l-value of this type has to be passed to the APIs below to cache the - * values of the parameters to a formatted warning message. - */ -typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][ - PNG_WARNING_PARAMETER_SIZE]; - -PNG_INTERNAL_FUNCTION(void,png_warning_parameter,(png_warning_parameters p, - int number, png_const_charp string),PNG_EMPTY); - /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters, - * including the trailing '\0'. - */ -PNG_INTERNAL_FUNCTION(void,png_warning_parameter_unsigned, - (png_warning_parameters p, int number, int format, png_alloc_size_t value), - PNG_EMPTY); - /* Use png_alloc_size_t because it is an unsigned type as big as any we - * need to output. Use the following for a signed value. - */ -PNG_INTERNAL_FUNCTION(void,png_warning_parameter_signed, - (png_warning_parameters p, int number, int format, png_int_32 value), - PNG_EMPTY); - -PNG_INTERNAL_FUNCTION(void,png_formatted_warning,(png_const_structrp png_ptr, - png_warning_parameters p, png_const_charp message),PNG_EMPTY); - /* 'message' follows the X/Open approach of using @1, @2 to insert - * parameters previously supplied using the above functions. Errors in - * specifying the parameters will simply result in garbage substitutions. - */ -#endif - -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -/* Application errors (new in 1.6); use these functions (declared below) for - * errors in the parameters or order of API function calls on read. The - * 'warning' should be used for an error that can be handled completely; the - * 'error' for one which can be handled safely but which may lose application - * information or settings. - * - * By default these both result in a png_error call prior to release, while in a - * released version the 'warning' is just a warning. However if the application - * explicitly disables benign errors (explicitly permitting the code to lose - * information) they both turn into warnings. - * - * If benign errors aren't supported they end up as the corresponding base call - * (png_warning or png_error.) - */ -PNG_INTERNAL_FUNCTION(void,png_app_warning,(png_const_structrp png_ptr, - png_const_charp message),PNG_EMPTY); - /* The application provided invalid parameters to an API function or called - * an API function at the wrong time, libpng can completely recover. - */ - -PNG_INTERNAL_FUNCTION(void,png_app_error,(png_const_structrp png_ptr, - png_const_charp message),PNG_EMPTY); - /* As above but libpng will ignore the call, or attempt some other partial - * recovery from the error. - */ -#else -# define png_app_warning(pp,s) png_warning(pp,s) -# define png_app_error(pp,s) png_error(pp,s) -#endif - -PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr, - png_const_charp message, int error),PNG_EMPTY); - /* Report a recoverable issue in chunk data. On read this is used to report - * a problem found while reading a particular chunk and the - * png_chunk_benign_error or png_chunk_warning function is used as - * appropriate. On write this is used to report an error that comes from - * data set via an application call to a png_set_ API and png_app_error or - * png_app_warning is used as appropriate. - * - * The 'error' parameter must have one of the following values: - */ -#define PNG_CHUNK_WARNING 0 /* never an error */ -#define PNG_CHUNK_WRITE_ERROR 1 /* an error only on write */ -#define PNG_CHUNK_ERROR 2 /* always an error */ - -/* ASCII to FP interfaces, currently only implemented if sCAL - * support is required. - */ -#if defined(PNG_sCAL_SUPPORTED) -/* MAX_DIGITS is actually the maximum number of characters in an sCAL - * width or height, derived from the precision (number of significant - * digits - a build time settable option) and assumptions about the - * maximum ridiculous exponent. - */ -#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/) - -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr, - png_charp ascii, png_size_t size, double fp, unsigned int precision), - PNG_EMPTY); -#endif /* FLOATING_POINT */ - -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, - png_charp ascii, png_size_t size, png_fixed_point fp),PNG_EMPTY); -#endif /* FIXED_POINT */ -#endif /* sCAL */ - -#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) -/* An internal API to validate the format of a floating point number. - * The result is the index of the next character. If the number is - * not valid it will be the index of a character in the supposed number. - * - * The format of a number is defined in the PNG extensions specification - * and this API is strictly conformant to that spec, not anyone elses! - * - * The format as a regular expression is: - * - * [+-]?[0-9]+.?([Ee][+-]?[0-9]+)? - * - * or: - * - * [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)? - * - * The complexity is that either integer or fraction must be present and the - * fraction is permitted to have no digits only if the integer is present. - * - * NOTE: The dangling E problem. - * There is a PNG valid floating point number in the following: - * - * PNG floating point numbers are not greedy. - * - * Working this out requires *TWO* character lookahead (because of the - * sign), the parser does not do this - it will fail at the 'r' - this - * doesn't matter for PNG sCAL chunk values, but it requires more care - * if the value were ever to be embedded in something more complex. Use - * ANSI-C strtod if you need the lookahead. - */ -/* State table for the parser. */ -#define PNG_FP_INTEGER 0 /* before or in integer */ -#define PNG_FP_FRACTION 1 /* before or in fraction */ -#define PNG_FP_EXPONENT 2 /* before or in exponent */ -#define PNG_FP_STATE 3 /* mask for the above */ -#define PNG_FP_SAW_SIGN 4 /* Saw +/- in current state */ -#define PNG_FP_SAW_DIGIT 8 /* Saw a digit in current state */ -#define PNG_FP_SAW_DOT 16 /* Saw a dot in current state */ -#define PNG_FP_SAW_E 32 /* Saw an E (or e) in current state */ -#define PNG_FP_SAW_ANY 60 /* Saw any of the above 4 */ - -/* These three values don't affect the parser. They are set but not used. - */ -#define PNG_FP_WAS_VALID 64 /* Preceding substring is a valid fp number */ -#define PNG_FP_NEGATIVE 128 /* A negative number, including "-0" */ -#define PNG_FP_NONZERO 256 /* A non-zero value */ -#define PNG_FP_STICKY 448 /* The above three flags */ - -/* This is available for the caller to store in 'state' if required. Do not - * call the parser after setting it (the parser sometimes clears it.) - */ -#define PNG_FP_INVALID 512 /* Available for callers as a distinct value */ - -/* Result codes for the parser (boolean - true meants ok, false means - * not ok yet.) - */ -#define PNG_FP_MAYBE 0 /* The number may be valid in the future */ -#define PNG_FP_OK 1 /* The number is valid */ - -/* Tests on the sticky non-zero and negative flags. To pass these checks - * the state must also indicate that the whole number is valid - this is - * achieved by testing PNG_FP_SAW_DIGIT (see the implementation for why this - * is equivalent to PNG_FP_OK above.) - */ -#define PNG_FP_NZ_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NEGATIVE | PNG_FP_NONZERO) - /* NZ_MASK: the string is valid and a non-zero negative value */ -#define PNG_FP_Z_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NONZERO) - /* Z MASK: the string is valid and a non-zero value. */ - /* PNG_FP_SAW_DIGIT: the string is valid. */ -#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT) -#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK) -#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK) - -/* The actual parser. This can be called repeatedly. It updates - * the index into the string and the state variable (which must - * be initialized to 0). It returns a result code, as above. There - * is no point calling the parser any more if it fails to advance to - * the end of the string - it is stuck on an invalid character (or - * terminated by '\0'). - * - * Note that the pointer will consume an E or even an E+ and then leave - * a 'maybe' state even though a preceding integer.fraction is valid. - * The PNG_FP_WAS_VALID flag indicates that a preceding substring was - * a valid number. It's possible to recover from this by calling - * the parser again (from the start, with state 0) but with a string - * that omits the last character (i.e. set the size to the index of - * the problem character.) This has not been tested within libpng. - */ -PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, - png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); - -/* This is the same but it checks a complete string and returns true - * only if it just contains a floating point number. As of 1.5.4 this - * function also returns the state at the end of parsing the number if - * it was valid (otherwise it returns 0.) This can be used for testing - * for negative or zero values using the sticky flag. - */ -PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string, - png_size_t size),PNG_EMPTY); -#endif /* pCAL || sCAL */ - -#if defined(PNG_READ_GAMMA_SUPPORTED) ||\ - defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) -/* Added at libpng version 1.5.0 */ -/* This is a utility to provide a*times/div (rounded) and indicate - * if there is an overflow. The result is a boolean - false (0) - * for overflow, true (1) if no overflow, in which case *res - * holds the result. - */ -PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a, - png_int_32 multiplied_by, png_int_32 divided_by),PNG_EMPTY); -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) -/* Same deal, but issue a warning on overflow and return 0. */ -PNG_INTERNAL_FUNCTION(png_fixed_point,png_muldiv_warn, - (png_const_structrp png_ptr, png_fixed_point a, png_int_32 multiplied_by, - png_int_32 divided_by),PNG_EMPTY); -#endif - -#ifdef PNG_GAMMA_SUPPORTED -/* Calculate a reciprocal - used for gamma values. This returns - * 0 if the argument is 0 in order to maintain an undefined value; - * there are no warnings. - */ -PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a), - PNG_EMPTY); - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* The same but gives a reciprocal of the product of two fixed point - * values. Accuracy is suitable for gamma calculations but this is - * not exact - use png_muldiv for that. Only required at present on read. - */ -PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a, - png_fixed_point b),PNG_EMPTY); -#endif - -/* Return true if the gamma value is significantly different from 1.0 */ -PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value), - PNG_EMPTY); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* Internal fixed point gamma correction. These APIs are called as - * required to convert single values - they don't need to be fast, - * they are not used when processing image pixel values. - * - * While the input is an 'unsigned' value it must actually be the - * correct bit value - 0..255 or 0..65535 as required. - */ -PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_correct,(png_structrp png_ptr, - unsigned int value, png_fixed_point gamma_value),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_16bit_correct,(unsigned int value, - png_fixed_point gamma_value),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(png_byte,png_gamma_8bit_correct,(unsigned int value, - png_fixed_point gamma_value),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr), - PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr, - int bit_depth),PNG_EMPTY); -#endif - -/* SIMPLIFIED READ/WRITE SUPPORT */ -#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ - defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) -/* The internal structure that png_image::opaque points to. */ -typedef struct png_control -{ - png_structp png_ptr; - png_infop info_ptr; - png_voidp error_buf; /* Always a jmp_buf at present. */ - - png_const_bytep memory; /* Memory buffer. */ - png_size_t size; /* Size of the memory buffer. */ - - unsigned int for_write :1; /* Otherwise it is a read structure */ - unsigned int owned_file :1; /* We own the file in io_ptr */ -} png_control; - -/* Return the pointer to the jmp_buf from a png_control: necessary because C - * does not reveal the type of the elements of jmp_buf. - */ -#ifdef __cplusplus -# define png_control_jmp_buf(pc) (((jmp_buf*)((pc)->error_buf))[0]) -#else -# define png_control_jmp_buf(pc) ((pc)->error_buf) -#endif - -/* Utility to safely execute a piece of libpng code catching and logging any - * errors that might occur. Returns true on success, false on failure (either - * of the function or as a result of a png_error.) - */ -PNG_INTERNAL_FUNCTION(void,png_safe_error,(png_structp png_ptr, - png_const_charp error_message),PNG_NORETURN); - -#ifdef PNG_WARNINGS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_safe_warning,(png_structp png_ptr, - png_const_charp warning_message),PNG_EMPTY); -#else -# define png_safe_warning 0/*dummy argument*/ -#endif - -PNG_INTERNAL_FUNCTION(int,png_safe_execute,(png_imagep image, - int (*function)(png_voidp), png_voidp arg),PNG_EMPTY); - -/* Utility to log an error; this also cleans up the png_image; the function - * always returns 0 (false). - */ -PNG_INTERNAL_FUNCTION(int,png_image_error,(png_imagep image, - png_const_charp error_message),PNG_EMPTY); - -#ifndef PNG_SIMPLIFIED_READ_SUPPORTED -/* png_image_free is used by the write code but not exported */ -PNG_INTERNAL_FUNCTION(void, png_image_free, (png_imagep image), PNG_EMPTY); -#endif /* !SIMPLIFIED_READ */ - -#endif /* SIMPLIFIED READ/WRITE */ - -/* These are initialization functions for hardware specific PNG filter - * optimizations; list these here then select the appropriate one at compile - * time using the macro PNG_FILTER_OPTIMIZATIONS. If the macro is not defined - * the generic code is used. - */ -#ifdef PNG_FILTER_OPTIMIZATIONS -PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr, - unsigned int bpp), PNG_EMPTY); - /* Just declare the optimization that will be used */ -#else - /* List *all* the possible optimizations here - this branch is required if - * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in - * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing. - */ -PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, - (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); -#endif - -/* Maintainer: Put new private prototypes here ^ */ - -#include "pngdebug.h" - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -#endif /* PNGPRIV_H */ + +/* pngpriv.h - private declarations for use inside libpng + * + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The symbols declared in this file (including the functions declared + * as extern) are PRIVATE. They are not part of the libpng public + * interface, and are not recommended for use by regular applications. + * Some of them may become public in the future; others may stay private, + * change in an incompatible way, or even disappear. + * Although the libpng users are not forbidden to include this header, + * they should be well aware of the issues that may arise from doing so. + */ + +#ifndef PNGPRIV_H +#define PNGPRIV_H + +/* Feature Test Macros. The following are defined here to ensure that correctly + * implemented libraries reveal the APIs libpng needs to build and hide those + * that are not needed and potentially damaging to the compilation. + * + * Feature Test Macros must be defined before any system header is included (see + * POSIX 1003.1 2.8.2 "POSIX Symbols." + * + * These macros only have an effect if the operating system supports either + * POSIX 1003.1 or C99, or both. On other operating systems (particularly + * Windows/Visual Studio) there is no effect; the OS specific tests below are + * still required (as of 2011-05-02.) + */ +#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ + +#ifndef PNG_VERSION_INFO_ONLY +/* Keep standard libraries at the top of this file */ + +/* Standard library headers not required by png.h: */ +# include +# include + +/* For headers only required with some build configurations see the lines after + * pnglibconf.h is included! + */ + +#endif /* VERSION_INFO_ONLY */ + +#define PNGLIB_BUILD /*libpng is being built, not used*/ + +/* If HAVE_CONFIG_H is defined during the build then the build system must + * provide an appropriate "config.h" file on the include path. The header file + * must provide definitions as required below (search for "HAVE_CONFIG_H"); + * see configure.ac for more details of the requirements. The macro + * "PNG_NO_CONFIG_H" is provided for maintainers to test for dependencies on + * 'configure'; define this macro to prevent the configure build including the + * configure generated config.h. Libpng is expected to compile without *any* + * special build system support on a reasonably ANSI-C compliant system. + */ +#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) +# include + + /* Pick up the definition of 'restrict' from config.h if it was read: */ +# define PNG_RESTRICT restrict +#endif + +/* To support symbol prefixing it is necessary to know *before* including png.h + * whether the fixed point (and maybe other) APIs are exported, because if they + * are not internal definitions may be required. This is handled below just + * before png.h is included, but load the configuration now if it is available. + */ +#ifndef PNGLCONF_H +# include "pnglibconf.h" +#endif + +/* Local renames may change non-exported API functions from png.h */ +#if defined(PNG_PREFIX) && !defined(PNGPREFIX_H) +# include "pngprefix.h" +#endif + +#ifdef PNG_USER_CONFIG +# include "pngusr.h" + /* These should have been defined in pngusr.h */ +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD "Custom libpng build" +# endif +# ifndef PNG_USER_DLLFNAME_POSTFIX +# define PNG_USER_DLLFNAME_POSTFIX "Cb" +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY +/* Additional standard libaries required in certain cases, put only standard + * ANSI-C89 headers here. If not available, or non-functional, the problem + * should be fixed by writing a wrapper for the header and the file on your + * include path. + */ +#if defined(PNG_sCAL_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + /* png.c requires the following ANSI-C constants if the conversion of + * floating point to ASCII is implemented therein: + * + * DBL_MIN_10_EXP Minimum negative integer such that 10^integer is a + * normalized (double) value. + * DBL_DIG Maximum number of decimal digits (can be set to any constant) + * DBL_MIN Smallest normalized fp number (can be set to an arbitrary value) + * DBL_MAX Maximum floating point number (can be set to an arbitrary value) + */ +# include +#endif /* sCAL && FLOATING_POINT */ + +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) ||\ + defined(PNG_FLOATING_POINT_SUPPORTED) + /* ANSI-C90 math functions are required. Full compliance with the standard + * is probably not a requirement, but the functions must exist and be + * declared in + */ +# include +#endif /* FLOATING_ARITHMETIC || FLOATING_POINT */ + +#endif /* VERSION_INFO_ONLY */ + +/* Compile time options. + * ===================== + * In a multi-arch build the compiler may compile the code several times for the + * same object module, producing different binaries for different architectures. + * When this happens configure-time setting of the target host options cannot be + * done and this interferes with the handling of the ARM NEON optimizations, and + * possibly other similar optimizations. Put additional tests here; in general + * this is needed when the same option can be changed at both compile time and + * run time depending on the target OS (i.e. iOS vs Android.) + * + * NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because + * this is not possible with certain compilers (Oracle SUN OS CC), as a result + * it is necessary to ensure that all extern functions that *might* be used + * regardless of $(CFLAGS) get declared in this file. The test on __ARM_NEON__ + * below is one example of this behavior because it is controlled by the + * presence or not of -mfpu=neon on the GCC command line, it is possible to do + * this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely + * do this. + */ +#ifndef PNG_ARM_NEON_OPT + /* ARM NEON optimizations are being controlled by the compiler settings, + * typically the target FPU. If the FPU has been set to NEON (-mfpu=neon + * with GCC) then the compiler will define __ARM_NEON__ and we can rely + * unconditionally on NEON instructions not crashing, otherwise we must + * disable use of NEON instructions. + * + * NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they + * can only be turned on automatically if that is supported too. If + * PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail + * to compile with an appropriate #error if ALIGNED_MEMORY has been turned + * off. + */ +# if defined(__ARM_NEON__) && defined(PNG_ALIGNED_MEMORY_SUPPORTED) +# define PNG_ARM_NEON_OPT 2 +# else +# define PNG_ARM_NEON_OPT 0 +# endif +#endif + +#if PNG_ARM_NEON_OPT > 0 + /* NEON optimizations are to be at least considered by libpng, so enable the + * callbacks to do this. + */ +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon + + /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used + * if possible - if __ARM_NEON__ is set and the compiler version is not known + * to be broken. This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can + * be: + * + * 1 The intrinsics code (the default with __ARM_NEON__) + * 2 The hand coded assembler (the default without __ARM_NEON__) + * + * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however + * this is *NOT* supported and may cease to work even after a minor revision + * to libpng. It *is* valid to do this for testing purposes, e.g. speed + * testing or a new compiler, but the results should be communicated to the + * libpng implementation list for incorporation in the next minor release. + */ +# ifndef PNG_ARM_NEON_IMPLEMENTATION +# ifdef __ARM_NEON__ +# if defined(__clang__) + /* At present it is unknown by the libpng developers which versions + * of clang support the intrinsics, however some or perhaps all + * versions do not work with the assembler so this may be + * irrelevant, so just use the default (do nothing here.) + */ +# elif defined(__GNUC__) + /* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to + * work, so if this *is* GCC, or G++, look for a version >4.5 + */ +# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) +# define PNG_ARM_NEON_IMPLEMENTATION 2 +# endif /* no GNUC support */ +# endif /* __GNUC__ */ +# else /* !defined __ARM_NEON__ */ + /* The 'intrinsics' code simply won't compile without this -mfpu=neon: + */ +# define PNG_ARM_NEON_IMPLEMENTATION 2 +# endif /* __ARM_NEON__ */ +# endif /* !defined PNG_ARM_NEON_IMPLEMENTATION */ + +# ifndef PNG_ARM_NEON_IMPLEMENTATION + /* Use the intrinsics code by default. */ +# define PNG_ARM_NEON_IMPLEMENTATION 1 +# endif +#endif /* PNG_ARM_NEON_OPT > 0 */ + +/* Is this a build of a DLL where compilation of the object modules requires + * different preprocessor settings to those required for a simple library? If + * so PNG_BUILD_DLL must be set. + * + * If libpng is used inside a DLL but that DLL does not export the libpng APIs + * PNG_BUILD_DLL must not be set. To avoid the code below kicking in build a + * static library of libpng then link the DLL against that. + */ +#ifndef PNG_BUILD_DLL +# ifdef DLL_EXPORT + /* This is set by libtool when files are compiled for a DLL; libtool + * always compiles twice, even on systems where it isn't necessary. Set + * PNG_BUILD_DLL in case it is necessary: + */ +# define PNG_BUILD_DLL +# else +# ifdef _WINDLL + /* This is set by the Microsoft Visual Studio IDE in projects that + * build a DLL. It can't easily be removed from those projects (it + * isn't visible in the Visual Studio UI) so it is a fairly reliable + * indication that PNG_IMPEXP needs to be set to the DLL export + * attributes. + */ +# define PNG_BUILD_DLL +# else +# ifdef __DLL__ + /* This is set by the Borland C system when compiling for a DLL + * (as above.) + */ +# define PNG_BUILD_DLL +# else + /* Add additional compiler cases here. */ +# endif +# endif +# endif +#endif /* Setting PNG_BUILD_DLL if required */ + +/* See pngconf.h for more details: the builder of the library may set this on + * the command line to the right thing for the specific compilation system or it + * may be automagically set above (at present we know of no system where it does + * need to be set on the command line.) + * + * PNG_IMPEXP must be set here when building the library to prevent pngconf.h + * setting it to the "import" setting for a DLL build. + */ +#ifndef PNG_IMPEXP +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP PNG_DLL_EXPORT +# else + /* Not building a DLL, or the DLL doesn't require specific export + * definitions. + */ +# define PNG_IMPEXP +# endif +#endif + +/* No warnings for private or deprecated functions in the build: */ +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE +#endif + +/* Symbol preprocessing support. + * + * To enable listing global, but internal, symbols the following macros should + * always be used to declare an extern data or function object in this file. + */ +#ifndef PNG_INTERNAL_DATA +# define PNG_INTERNAL_DATA(type, name, array) extern type name array +#endif + +#ifndef PNG_INTERNAL_FUNCTION +# define PNG_INTERNAL_FUNCTION(type, name, args, attributes)\ + extern PNG_FUNCTION(type, name, args, PNG_EMPTY attributes) +#endif + +#ifndef PNG_INTERNAL_CALLBACK +# define PNG_INTERNAL_CALLBACK(type, name, args, attributes)\ + extern PNG_FUNCTION(type, (PNGCBAPI name), args, PNG_EMPTY attributes) +#endif + +/* If floating or fixed point APIs are disabled they may still be compiled + * internally. To handle this make sure they are declared as the appropriate + * internal extern function (otherwise the symbol prefixing stuff won't work and + * the functions will be used without definitions.) + * + * NOTE: although all the API functions are declared here they are not all + * actually built! Because the declarations are still made it is necessary to + * fake out types that they depend on. + */ +#ifndef PNG_FP_EXPORT +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY); +# ifndef PNG_VERSION_INFO_ONLY + typedef struct png_incomplete png_double; + typedef png_double* png_doublep; + typedef const png_double* png_const_doublep; + typedef png_double** png_doublepp; +# endif +# endif +#endif +#ifndef PNG_FIXED_EXPORT +# ifndef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY); +# endif +#endif + +/* Include png.h here to get the version info and other macros, pngstruct.h and + * pnginfo.h are included later under the protection of !PNG_VERSION_INFO_ONLY + */ +#include "png.h" + +/* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */ +#ifndef PNG_DLL_EXPORT +# define PNG_DLL_EXPORT +#endif + +/* asserts are turned off in release code, but are in even in release candidates + * because often system builders only check future libpng releases when a + * release candidate is available. + */ +#if PNG_LIBPNG_BUILD_BASE_TYPE == PNG_LIBPNG_BUILD_STABLE +# define NDEBUG +#endif +#ifndef PNG_VERSION_INFO_ONLY +# include +#endif + +/* SECURITY and SAFETY: + * + * By default libpng is built without any internal limits on image size, + * individual heap (png_malloc) allocations or the total amount of memory used. + * If PNG_SAFE_LIMITS_SUPPORTED is defined, however, the limits below are used + * (unless individually overridden). These limits are believed to be fairly + * safe, but builders of secure systems should verify the values against the + * real system capabilities. + */ +#ifdef PNG_SAFE_LIMITS_SUPPORTED + /* 'safe' limits */ +# ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000 +# endif +# ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000 +# endif +# ifndef PNG_USER_CHUNK_CACHE_MAX +# define PNG_USER_CHUNK_CACHE_MAX 128 +# endif +# ifndef PNG_USER_CHUNK_MALLOC_MAX +# define PNG_USER_CHUNK_MALLOC_MAX 8000000 +# endif +#else + /* values for no limits */ +# ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 0x7fffffff +# endif +# ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 0x7fffffff +# endif +# ifndef PNG_USER_CHUNK_CACHE_MAX +# define PNG_USER_CHUNK_CACHE_MAX 0 +# endif +# ifndef PNG_USER_CHUNK_MALLOC_MAX +# define PNG_USER_CHUNK_MALLOC_MAX 0 +# endif +#endif + +/* Moved to pngpriv.h at libpng-1.5.0 */ +/* NOTE: some of these may have been used in external applications as + * these definitions were exposed in pngconf.h prior to 1.5. + */ + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. + * + * zlib provides 'MAXSEG_64K' which, if defined, indicates the + * same limit and pngconf.h (already included) sets the limit + * if certain operating systems are detected. + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +#ifndef PNG_UNUSED +/* Unused formal parameter warnings are silenced using the following macro + * which is expected to have no bad effects on performance (optimizing + * compilers will probably remove it entirely). Note that if you replace + * it with something other than whitespace, you must include the terminating + * semicolon. + */ +# define PNG_UNUSED(param) (void)param; +#endif + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + +/* If warnings or errors are turned off the code is disabled or redirected here. + * From 1.5.4 functions have been added to allow very limited formatting of + * error and warning messages - this code will also be disabled here. + */ +#ifdef PNG_WARNINGS_SUPPORTED +# define PNG_WARNING_PARAMETERS(p) png_warning_parameters p; +#else +# define png_warning_parameter(p,number,string) ((void)0) +# define png_warning_parameter_unsigned(p,number,format,value) ((void)0) +# define png_warning_parameter_signed(p,number,format,value) ((void)0) +# define png_formatted_warning(pp,p,message) ((void)(pp)) +# define PNG_WARNING_PARAMETERS(p) +#endif +#ifndef PNG_ERROR_TEXT_SUPPORTED +# define png_fixed_error(s1,s2) png_err(s1) +#endif + +/* C allows up-casts from (void*) to any pointer and (const void*) to any + * pointer to a const object. C++ regards this as a type error and requires an + * explicit, static, cast and provides the static_cast<> rune to ensure that + * const is not cast away. + */ +#ifdef __cplusplus +# define png_voidcast(type, value) static_cast(value) +# define png_constcast(type, value) const_cast(value) +# define png_aligncast(type, value) \ + static_cast(static_cast(value)) +# define png_aligncastconst(type, value) \ + static_cast(static_cast(value)) +#else +# define png_voidcast(type, value) (value) +# define png_constcast(type, value) ((type)(value)) +# define png_aligncast(type, value) ((void*)(value)) +# define png_aligncastconst(type, value) ((const void*)(value)) +#endif /* __cplusplus */ + +/* Some fixed point APIs are still required even if not exported because + * they get used by the corresponding floating point APIs. This magic + * deals with this: + */ +#ifdef PNG_FIXED_POINT_SUPPORTED +# define PNGFAPI PNGAPI +#else +# define PNGFAPI /* PRIVATE */ +#endif + +/* These macros may need to be architecture dependent. */ +#define PNG_ALIGN_NONE 0 /* do not use data alignment */ +#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */ +#ifdef offsetof +# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */ +#else +# define PNG_ALIGN_OFFSET -1 /* prevent the use of this */ +#endif +#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */ + +#ifndef PNG_ALIGN_TYPE + /* Default to using aligned access optimizations and requiring alignment to a + * multiple of the data type size. Override in a compiler specific fashion + * if necessary by inserting tests here: + */ +# define PNG_ALIGN_TYPE PNG_ALIGN_SIZE +#endif + +#if PNG_ALIGN_TYPE == PNG_ALIGN_SIZE + /* This is used because in some compiler implementations non-aligned + * structure members are supported, so the offsetof approach below fails. + * Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access + * is good for performance. Do not do this unless you have tested the result + * and understand it. + */ +# define png_alignof(type) (sizeof (type)) +#else +# if PNG_ALIGN_TYPE == PNG_ALIGN_OFFSET +# define png_alignof(type) offsetof(struct{char c; type t;}, t) +# else +# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS +# define png_alignof(type) (1) +# endif + /* Else leave png_alignof undefined to prevent use thereof */ +# endif +#endif + +/* This implicitly assumes alignment is always to a power of 2. */ +#ifdef png_alignof +# define png_isaligned(ptr, type)\ + ((((const char*)ptr-(const char*)0) & (png_alignof(type)-1)) == 0) +#else +# define png_isaligned(ptr, type) 0 +#endif + +/* End of memory model/platform independent support */ +/* End of 1.5.0beta36 move from pngconf.h */ + +/* CONSTANTS and UTILITY MACROS + * These are used internally by libpng and not exposed in the API + */ + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. Three of these + * are defined in png.h because they need to be visible to applications + * that call png_set_unknown_chunk(). + */ +/* #define PNG_HAVE_IHDR 0x01 (defined in png.h) */ +/* #define PNG_HAVE_PLTE 0x02 (defined in png.h) */ +#define PNG_HAVE_IDAT 0x04 +/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */ +#define PNG_HAVE_IEND 0x10 + /* 0x20 (unused) */ + /* 0x40 (unused) */ + /* 0x80 (unused) */ +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 + /* 0x800 (unused) */ +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + /* 0x4000 (unused) */ +#define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */ + +/* Flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_QUANTIZE 0x0040 +#define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ + /* 0x0100 unused */ +#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ +#define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000 +#define PNG_PACKSWAP 0x10000 +#define PNG_SWAP_ALPHA 0x20000 +#define PNG_STRIP_ALPHA 0x40000 +#define PNG_INVERT_ALPHA 0x80000 +#define PNG_USER_TRANSFORM 0x100000 +#define PNG_RGB_TO_GRAY_ERR 0x200000 +#define PNG_RGB_TO_GRAY_WARN 0x400000 +#define PNG_RGB_TO_GRAY 0x600000 /* two bits, RGB_TO_GRAY_ERR|WARN */ +#define PNG_ENCODE_ALPHA 0x800000 /* Added to libpng-1.5.4 */ +#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */ +#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */ + /* 0x8000000 unused */ + /* 0x10000000 unused */ + /* 0x20000000 unused */ + /* 0x40000000 unused */ +/* Flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* Flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */ + /* 0x0004 unused */ +#define PNG_FLAG_ZSTREAM_ENDED 0x0008 /* Added to libpng-1.6.0 */ + /* 0x0010 unused */ + /* 0x0020 unused */ +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 +#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ +/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 */ +/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 */ +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000 +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000 +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000 +#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000 /* Added to libpng-1.4.0 */ +#define PNG_FLAG_APP_WARNINGS_WARN 0x200000 /* Added to libpng-1.6.0 */ +#define PNG_FLAG_APP_ERRORS_WARN 0x400000 /* Added to libpng-1.6.0 */ +#define PNG_FLAG_BACKGROUND_IS_GRAY 0x800000 +#define PNG_FLAG_BACKGROUND_EXPAND 0x1000000 + /* 0x2000000 unused */ + /* 0x4000000 unused */ + /* 0x8000000 unused */ + /* 0x10000000 unused */ + /* 0x20000000 unused */ + /* 0x40000000 unused */ + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* Save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) +/* See below for the definitions of the tables used in these macros */ +#define PNG_sRGB_FROM_LINEAR(linear) ((png_byte)((png_sRGB_base[(linear)>>15] +\ + ((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8)) + /* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB + * encoded value with maximum error 0.646365. Note that the input is not a + * 16-bit value; it has been multiplied by 255! */ +#endif /* PNG_SIMPLIFIED_READ/WRITE */ + +/* Added to libpng-1.6.0: scale a 16-bit value in the range 0..65535 to 0..255 + * by dividing by 257 *with rounding*. This macro is exact for the given range. + * See the discourse in pngrtran.c png_do_scale_16_to_8. The values in the + * macro were established by experiment (modifying the added value). The macro + * has a second variant that takes a value already scaled by 255 and divides by + * 65535 - this has a maximum error of .502. Over the range 0..65535*65535 it + * only gives off-by-one errors and only for 0.5% (1 in 200) of the values. + */ +#define PNG_DIV65535(v24) (((v24) + 32895) >> 16) +#define PNG_DIV257(v16) PNG_DIV65535((png_uint_32)(v16) * 255) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ + (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + * ideal-delta..ideal+delta. Each argument is evaluated twice. + * "ideal" and "delta" should be constants, normally simple + * integers, "value" a variable. Added to libpng-1.2.6 JB + */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* Conversions between fixed and floating point, only defined if + * required (to make sure the code doesn't accidentally use float + * when it is supposedly disabled.) + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* The floating point conversion can't overflow, though it can and + * does lose accuracy relative to the original fixed point value. + * In practice this doesn't matter because png_fixed_point only + * stores numbers with very low precision. The png_ptr and s + * arguments are unused by default but are there in case error + * checking becomes a requirement. + */ +#define png_float(png_ptr, fixed, s) (.00001 * (fixed)) + +/* The fixed point conversion performs range checking and evaluates + * its argument multiple times, so must be used with care. The + * range checking uses the PNG specification values for a signed + * 32 bit fixed point value except that the values are deliberately + * rounded-to-zero to an integral value - 21474 (21474.83 is roughly + * (2^31-1) * 100000). 's' is a string that describes the value being + * converted. + * + * NOTE: this macro will raise a png_error if the range check fails, + * therefore it is normally only appropriate to use this on values + * that come from API calls or other sources where an out of range + * error indicates a programming error, not a data error! + * + * NOTE: by default this is off - the macro is not used - because the + * function call saves a lot of code. + */ +#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED +#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\ + ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0)) +#endif +/* else the corresponding function is defined below, inside the scope of the + * cplusplus test. + */ +#endif + +/* Gamma values (new at libpng-1.5.4): */ +#define PNG_GAMMA_MAC_OLD 151724 /* Assume '1.8' is really 2.2/1.45! */ +#define PNG_GAMMA_MAC_INVERSE 65909 +#define PNG_GAMMA_sRGB_INVERSE 45455 + +/* Almost everything below is C specific; the #defines above can be used in + * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot. + */ +#ifndef PNG_VERSION_INFO_ONLY + +#include "pngstruct.h" +#include "pnginfo.h" + +/* Validate the include paths - the include path used to generate pnglibconf.h + * must match that used in the build, or we must be using pnglibconf.h.prebuilt: + */ +#if PNG_ZLIB_VERNUM != 0 && PNG_ZLIB_VERNUM != ZLIB_VERNUM +# error ZLIB_VERNUM != PNG_ZLIB_VERNUM \ + "-I (include path) error: see the notes in pngpriv.h" + /* This means that when pnglibconf.h was built the copy of zlib.h that it + * used is not the same as the one being used here. Because the build of + * libpng makes decisions to use inflateInit2 and inflateReset2 based on the + * zlib version number and because this affects handling of certain broken + * PNG files the -I directives must match. + * + * The most likely explanation is that you passed a -I in CFLAGS, this will + * not work; all the preprocessor directories and in particular all the -I + * directives must be in CPPFLAGS. + */ +#endif + +/* This is used for 16 bit gamma tables -- only the top level pointers are + * const; this could be changed: + */ +typedef const png_uint_16p * png_const_uint_16pp; + +/* Added to libpng-1.5.7: sRGB conversion tables */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_table, [256]); + /* Convert from an sRGB encoded value 0..255 to a 16-bit linear value, + * 0..65535. This table gives the closest 16-bit answers (no errors). + */ +#endif + +PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_base, [512]); +PNG_INTERNAL_DATA(const png_byte, png_sRGB_delta, [512]); +#endif /* PNG_SIMPLIFIED_READ/WRITE */ + + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Internal functions; these are not exported from a DLL however because they + * are used within several of the C source files they have to be C extern. + * + * All of these functions must be declared with PNG_INTERNAL_FUNCTION. + */ + +/* Zlib support */ +#define PNG_UNEXPECTED_ZLIB_RETURN (-7) +PNG_INTERNAL_FUNCTION(void, png_zstream_error,(png_structrp png_ptr, int ret), + PNG_EMPTY); + /* Used by the zlib handling functions to ensure that z_stream::msg is always + * set before they return. + */ + +#ifdef PNG_WRITE_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr, + png_compression_bufferp *list),PNG_EMPTY); + /* Free the buffer list used by the compressed write code. */ +#endif + +#ifdef PNG_WRITE_FILTER_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_alloc_filter_row_buffers, + (png_structrp png_ptr, int filters),PNG_EMPTY); + /* Allocate pixel row buffers to cache filtered rows while testing candidate + * filters. + * TODO: avoid this, only one spare row buffer (at most) is required, this + * wastes a lot of memory for large images. + */ +#endif + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \ + (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \ + defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \ + (defined(PNG_sCAL_SUPPORTED) && \ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)) +PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr, + double fp, png_const_charp text),PNG_EMPTY); +#endif + +/* Check the user version string for compatibility, returns false if the version + * numbers aren't compatible. + */ +PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr, + png_const_charp user_png_ver),PNG_EMPTY); + +/* Internal base allocator - no messages, NULL on failure to allocate. This + * does, however, call the application provided allocator and that could call + * png_error (although that would be a bug in the application implementation.) + */ +PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_base,(png_const_structrp png_ptr, + png_alloc_size_t size),PNG_ALLOCATED); + +#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\ + defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) +/* Internal array allocator, outputs no error or warning messages on failure, + * just returns NULL. + */ +PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_array,(png_const_structrp png_ptr, + int nelements, size_t element_size),PNG_ALLOCATED); + +/* The same but an existing array is extended by add_elements. This function + * also memsets the new elements to 0 and copies the old elements. The old + * array is not freed or altered. + */ +PNG_INTERNAL_FUNCTION(png_voidp,png_realloc_array,(png_structrp png_ptr, + png_const_voidp array, int old_elements, int add_elements, + size_t element_size),PNG_ALLOCATED); +#endif /* text, sPLT or unknown chunks */ + +/* Magic to create a struct when there is no struct to call the user supplied + * memory allocators. Because error handling has not been set up the memory + * handlers can't safely call png_error, but this is an obscure and undocumented + * restriction so libpng has to assume that the 'free' handler, at least, might + * call png_error. + */ +PNG_INTERNAL_FUNCTION(png_structp,png_create_png_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn, + png_free_ptr free_fn),PNG_ALLOCATED); + +/* Free memory from internal libpng struct */ +PNG_INTERNAL_FUNCTION(void,png_destroy_png_struct,(png_structrp png_ptr), + PNG_EMPTY); + +/* Free an allocated jmp_buf (always succeeds) */ +PNG_INTERNAL_FUNCTION(void,png_free_jmpbuf,(png_structrp png_ptr),PNG_EMPTY); + +/* Function to allocate memory for zlib. PNGAPI is disallowed. */ +PNG_INTERNAL_FUNCTION(voidpf,png_zalloc,(voidpf png_ptr, uInt items, uInt size), + PNG_ALLOCATED); + +/* Function to free memory for zlib. PNGAPI is disallowed. */ +PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY); + +/* Next four functions are used internally as callbacks. PNGCBAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to + * PNGCBAPI at 1.5.0 + */ + +PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr, + png_bytep data, png_size_t length),PNG_EMPTY); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr, + png_bytep buffer, png_size_t length),PNG_EMPTY); +#endif + +PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr, + png_bytep data, png_size_t length),PNG_EMPTY); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED +PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_flush,(png_structp png_ptr), + PNG_EMPTY); +# endif +#endif + +/* Reset the CRC variable */ +PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY); + +/* Write the "data" buffer to whatever output you are using */ +PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr, + png_const_bytep data, png_size_t length),PNG_EMPTY); + +/* Read and check the PNG file signature */ +PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); + +/* Read the chunk header (length + type name) */ +PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr), + PNG_EMPTY); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data, + png_size_t length),PNG_EMPTY); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf, + png_uint_32 length),PNG_EMPTY); + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr, + png_uint_32 skip),PNG_EMPTY); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr, + png_const_bytep ptr, png_size_t length),PNG_EMPTY); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); +#endif + +/* Write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_INTERNAL_FUNCTION(void,png_write_IHDR,(png_structrp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, + int compression_method, int filter_method, int interlace_method),PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_write_PLTE,(png_structrp png_ptr, + png_const_colorp palette, png_uint_32 num_pal),PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_compress_IDAT,(png_structrp png_ptr, + png_const_bytep row_data, png_alloc_size_t row_data_length, int flush), + PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_write_IEND,(png_structrp png_ptr),PNG_EMPTY); + +#ifdef PNG_WRITE_gAMA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_gAMA_fixed,(png_structrp png_ptr, + png_fixed_point file_gamma),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_sBIT,(png_structrp png_ptr, + png_const_color_8p sbit, int color_type),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr, + const png_xy *xy), PNG_EMPTY); + /* The xy value must have been previously validated */ +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr, + int intent),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr, + png_const_charp name, png_const_bytep profile), PNG_EMPTY); + /* The profile must have been previously validated for correctness, the + * length comes from the first four bytes. Only the base, deflate, + * compression is supported. + */ +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_sPLT,(png_structrp png_ptr, + png_const_sPLT_tp palette),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_tRNS,(png_structrp png_ptr, + png_const_bytep trans, png_const_color_16p values, int number, + int color_type),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_bKGD,(png_structrp png_ptr, + png_const_color_16p values, int color_type),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr, + png_const_uint_16p hist, int num_hist),PNG_EMPTY); +#endif + +/* Chunks that have keywords */ +#ifdef PNG_WRITE_tEXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr, + png_const_charp key, png_const_charp text, png_size_t text_len),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_zTXt,(png_structrp png_ptr, png_const_charp + key, png_const_charp text, png_size_t text_len, int compression),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_iTXt,(png_structrp png_ptr, + int compression, png_const_charp key, png_const_charp lang, + png_const_charp lang_key, png_const_charp text),PNG_EMPTY); +#endif + +#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ +PNG_INTERNAL_FUNCTION(int,png_set_text_2,(png_structrp png_ptr, + png_inforp info_ptr, png_const_textp text_ptr, int num_text),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_oFFs,(png_structrp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_pCAL,(png_structrp png_ptr, + png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, + png_const_charp units, png_charpp params),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_pHYs,(png_structrp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_tIME,(png_structrp png_ptr, + png_const_timep mod_time),PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_sCAL_s,(png_structrp png_ptr, + int unit, png_const_charp width, png_const_charp height),PNG_EMPTY); +#endif + +/* Called when finished processing a row of data */ +PNG_INTERNAL_FUNCTION(void,png_write_finish_row,(png_structrp png_ptr), + PNG_EMPTY); + +/* Internal use only. Called before first row of data */ +PNG_INTERNAL_FUNCTION(void,png_write_start_row,(png_structrp png_ptr), + PNG_EMPTY); + +/* Combine a row of data, dealing with alpha, etc. if requested. 'row' is an + * array of png_ptr->width pixels. If the image is not interlaced or this + * is the final pass this just does a memcpy, otherwise the "display" flag + * is used to determine whether to copy pixels that are not in the current pass. + * + * Because 'png_do_read_interlace' (below) replicates pixels this allows this + * function to achieve the documented 'blocky' appearance during interlaced read + * if display is 1 and the 'sparkle' appearance, where existing pixels in 'row' + * are not changed if they are not in the current pass, when display is 0. + * + * 'display' must be 0 or 1, otherwise the memcpy will be done regardless. + * + * The API always reads from the png_struct row buffer and always assumes that + * it is full width (png_do_read_interlace has already been called.) + * + * This function is only ever used to write to row buffers provided by the + * caller of the relevant libpng API and the row must have already been + * transformed by the read transformations. + * + * The PNG_USE_COMPILE_TIME_MASKS option causes generation of pre-computed + * bitmasks for use within the code, otherwise runtime generated masks are used. + * The default is compile time masks. + */ +#ifndef PNG_USE_COMPILE_TIME_MASKS +# define PNG_USE_COMPILE_TIME_MASKS 1 +#endif +PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr, + png_bytep row, int display),PNG_EMPTY); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Expand an interlaced row: the 'row_info' describes the pass data that has + * been read in and must correspond to the pixels in 'row', the pixels are + * expanded (moved apart) in 'row' to match the final layout, when doing this + * the pixels are *replicated* to the intervening space. This is essential for + * the correct operation of png_combine_row, above. + */ +PNG_INTERNAL_FUNCTION(void,png_do_read_interlace,(png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations),PNG_EMPTY); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Grab pixels out of a row for an interlaced pass */ +PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info, + png_bytep row, int pass),PNG_EMPTY); +#endif + +/* Unfilter a row: check the filter value before calling this, there is no point + * calling it for PNG_FILTER_VALUE_NONE. + */ +PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop + row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); + +/* Choose the best filter to use and filter the row data */ +PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, + png_row_infop row_info),PNG_EMPTY); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr, + png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY); + /* Read 'avail_out' bytes of data from the IDAT stream. If the output buffer + * is NULL the function checks, instead, for the end of the stream. In this + * case a benign error will be issued if the stream end is not found or if + * extra data has to be consumed. + */ +PNG_INTERNAL_FUNCTION(void,png_read_finish_IDAT,(png_structrp png_ptr), + PNG_EMPTY); + /* This cleans up when the IDAT LZ stream does not end when the last image + * byte is read; there is still some pending input. + */ + +PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr), + PNG_EMPTY); + /* Finish a row while reading, dealing with interlacing passes, etc. */ +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Initialize the row buffers, etc. */ +PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +/* Optional call to update the users info structure */ +PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +#endif + +/* Shared transform functions, defined in pngtran.c */ +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_strip_channel,(png_row_infop row_info, + png_bytep row, int at_start),PNG_EMPTY); +#endif + +#ifdef PNG_16BIT_SUPPORTED +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_swap,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_packswap,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_invert,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info, + png_bytep row),PNG_EMPTY); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* Decode the IHDR chunk */ +PNG_INTERNAL_FUNCTION(void,png_handle_IHDR,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_handle_PLTE,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_handle_IEND,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); + +#ifdef PNG_READ_bKGD_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_bKGD,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_hIST,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_iCCP,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_iTXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_oFFs,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_pCAL,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_pHYs,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_sBIT,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_sCAL,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_sPLT,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_sRGB_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_sRGB,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_tEXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_tIME,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_tRNS,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + +PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr, + png_uint_32 chunk_name),PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY); + /* This is the function that gets called for unknown chunks. The 'keep' + * argument is either non-zero for a known chunk that has been set to be + * handled as unknown or zero for an unknown chunk. By default the function + * just skips the chunk or errors out if it is critical. + */ + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) +PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling, + (png_const_structrp png_ptr, png_uint_32 chunk_name),PNG_EMPTY); + /* Exactly as the API png_handle_as_unknown() except that the argument is a + * 32-bit chunk name, not a string. + */ +#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */ + +/* Handle the transformations for reading and writing */ +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_read_transformations,(png_structrp png_ptr, + png_row_infop row_info),PNG_EMPTY); +#endif +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_do_write_transformations,(png_structrp png_ptr, + png_row_infop row_info),PNG_EMPTY); +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_init_read_transformations,(png_structrp png_ptr), + PNG_EMPTY); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_push_read_chunk,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_sig,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_crc_skip,(png_structrp png_ptr, + png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_crc_finish,(png_structrp png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr, + png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr, + png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_have_row,(png_structrp png_ptr, + png_bytep row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_end,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_push_finish_row,(png_structrp png_ptr), + PNG_EMPTY); +# ifdef PNG_READ_tEXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_push_handle_tEXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_tEXt,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +# endif +# ifdef PNG_READ_zTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_push_handle_zTXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_zTXt,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +# endif +# ifdef PNG_READ_iTXt_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_push_handle_iTXt,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_push_read_iTXt,(png_structrp png_ptr, + png_inforp info_ptr),PNG_EMPTY); +# endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +/* Added at libpng version 1.6.0 */ +#ifdef PNG_GAMMA_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_fixed_point gAMA), PNG_EMPTY); + /* Set the colorspace gamma with a value provided by the application or by + * the gAMA chunk on read. The value will override anything set by an ICC + * profile. + */ + +PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr, + png_inforp info_ptr), PNG_EMPTY); + /* Synchronize the info 'valid' flags with the colorspace */ + +PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr, + png_inforp info_ptr), PNG_EMPTY); + /* Copy the png_struct colorspace to the info_struct and call the above to + * synchronize the flags. Checks for NULL info_ptr and does nothing. + */ +#endif + +/* Added at libpng version 1.4.0 */ +#ifdef PNG_COLORSPACE_SUPPORTED +/* These internal functions are for maintaining the colorspace structure within + * a png_info or png_struct (or, indeed, both). + */ +PNG_INTERNAL_FUNCTION(int,png_colorspace_set_chromaticities, + (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_xy *xy, + int preferred), PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(int,png_colorspace_set_endpoints, + (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_XYZ *XYZ, + int preferred), PNG_EMPTY); + +#ifdef PNG_sRGB_SUPPORTED +PNG_INTERNAL_FUNCTION(int,png_colorspace_set_sRGB,(png_const_structrp png_ptr, + png_colorspacerp colorspace, int intent), PNG_EMPTY); + /* This does set the colorspace gAMA and cHRM values too, but doesn't set the + * flags to write them, if it returns false there was a problem and an error + * message has already been output (but the colorspace may still need to be + * synced to record the invalid flag). + */ +#endif /* sRGB */ + +#ifdef PNG_iCCP_SUPPORTED +PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length, png_const_bytep profile, int color_type), + PNG_EMPTY); + /* The 'name' is used for information only */ + +/* Routines for checking parts of an ICC profile. */ +PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length), PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length, + png_const_bytep profile /* first 132 bytes only */, int color_type), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_charp name, + png_uint_32 profile_length, + png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY); +#ifdef PNG_sRGB_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_icc_set_sRGB,( + png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_bytep profile, uLong adler), PNG_EMPTY); + /* 'adler' is the Adler32 checksum of the uncompressed profile data. It may + * be zero to indicate that it is not available. It is used, if provided, + * as a fast check on the profile when checking to see if it is sRGB. + */ +#endif +#endif /* iCCP */ + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_colorspace_set_rgb_coefficients, + (png_structrp png_ptr), PNG_EMPTY); + /* Set the rgb_to_gray coefficients from the colorspace Y values */ +#endif /* READ_RGB_TO_GRAY */ +#endif /* COLORSPACE */ + +/* Added at libpng version 1.4.0 */ +PNG_INTERNAL_FUNCTION(void,png_check_IHDR,(png_const_structrp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type),PNG_EMPTY); + +/* Added at libpng version 1.5.10 */ +#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \ + defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_do_check_palette_indexes, + (png_structrp png_ptr, png_row_infop row_info),PNG_EMPTY); +#endif + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_INTERNAL_FUNCTION(void,png_fixed_error,(png_const_structrp png_ptr, + png_const_charp name),PNG_NORETURN); +#endif + +/* Puts 'string' into 'buffer' at buffer[pos], taking care never to overwrite + * the end. Always leaves the buffer nul terminated. Never errors out (and + * there is no error code.) + */ +PNG_INTERNAL_FUNCTION(size_t,png_safecat,(png_charp buffer, size_t bufsize, + size_t pos, png_const_charp string),PNG_EMPTY); + +/* Various internal functions to handle formatted warning messages, currently + * only implemented for warnings. + */ +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) +/* Utility to dump an unsigned value into a buffer, given a start pointer and + * and end pointer (which should point just *beyond* the end of the buffer!) + * Returns the pointer to the start of the formatted string. This utility only + * does unsigned values. + */ +PNG_INTERNAL_FUNCTION(png_charp,png_format_number,(png_const_charp start, + png_charp end, int format, png_alloc_size_t number),PNG_EMPTY); + +/* Convenience macro that takes an array: */ +#define PNG_FORMAT_NUMBER(buffer,format,number) \ + png_format_number(buffer, buffer + (sizeof buffer), format, number) + +/* Suggested size for a number buffer (enough for 64 bits and a sign!) */ +#define PNG_NUMBER_BUFFER_SIZE 24 + +/* These are the integer formats currently supported, the name is formed from + * the standard printf(3) format string. + */ +#define PNG_NUMBER_FORMAT_u 1 /* chose unsigned API! */ +#define PNG_NUMBER_FORMAT_02u 2 +#define PNG_NUMBER_FORMAT_d 1 /* chose signed API! */ +#define PNG_NUMBER_FORMAT_02d 2 +#define PNG_NUMBER_FORMAT_x 3 +#define PNG_NUMBER_FORMAT_02x 4 +#define PNG_NUMBER_FORMAT_fixed 5 /* choose the signed API */ +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* New defines and members adding in libpng-1.5.4 */ +# define PNG_WARNING_PARAMETER_SIZE 32 +# define PNG_WARNING_PARAMETER_COUNT 8 /* Maximum 9; see pngerror.c */ + +/* An l-value of this type has to be passed to the APIs below to cache the + * values of the parameters to a formatted warning message. + */ +typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][ + PNG_WARNING_PARAMETER_SIZE]; + +PNG_INTERNAL_FUNCTION(void,png_warning_parameter,(png_warning_parameters p, + int number, png_const_charp string),PNG_EMPTY); + /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters, + * including the trailing '\0'. + */ +PNG_INTERNAL_FUNCTION(void,png_warning_parameter_unsigned, + (png_warning_parameters p, int number, int format, png_alloc_size_t value), + PNG_EMPTY); + /* Use png_alloc_size_t because it is an unsigned type as big as any we + * need to output. Use the following for a signed value. + */ +PNG_INTERNAL_FUNCTION(void,png_warning_parameter_signed, + (png_warning_parameters p, int number, int format, png_int_32 value), + PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_formatted_warning,(png_const_structrp png_ptr, + png_warning_parameters p, png_const_charp message),PNG_EMPTY); + /* 'message' follows the X/Open approach of using @1, @2 to insert + * parameters previously supplied using the above functions. Errors in + * specifying the parameters will simply result in garbage substitutions. + */ +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Application errors (new in 1.6); use these functions (declared below) for + * errors in the parameters or order of API function calls on read. The + * 'warning' should be used for an error that can be handled completely; the + * 'error' for one which can be handled safely but which may lose application + * information or settings. + * + * By default these both result in a png_error call prior to release, while in a + * released version the 'warning' is just a warning. However if the application + * explicitly disables benign errors (explicitly permitting the code to lose + * information) they both turn into warnings. + * + * If benign errors aren't supported they end up as the corresponding base call + * (png_warning or png_error.) + */ +PNG_INTERNAL_FUNCTION(void,png_app_warning,(png_const_structrp png_ptr, + png_const_charp message),PNG_EMPTY); + /* The application provided invalid parameters to an API function or called + * an API function at the wrong time, libpng can completely recover. + */ + +PNG_INTERNAL_FUNCTION(void,png_app_error,(png_const_structrp png_ptr, + png_const_charp message),PNG_EMPTY); + /* As above but libpng will ignore the call, or attempt some other partial + * recovery from the error. + */ +#else +# define png_app_warning(pp,s) png_warning(pp,s) +# define png_app_error(pp,s) png_error(pp,s) +#endif + +PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr, + png_const_charp message, int error),PNG_EMPTY); + /* Report a recoverable issue in chunk data. On read this is used to report + * a problem found while reading a particular chunk and the + * png_chunk_benign_error or png_chunk_warning function is used as + * appropriate. On write this is used to report an error that comes from + * data set via an application call to a png_set_ API and png_app_error or + * png_app_warning is used as appropriate. + * + * The 'error' parameter must have one of the following values: + */ +#define PNG_CHUNK_WARNING 0 /* never an error */ +#define PNG_CHUNK_WRITE_ERROR 1 /* an error only on write */ +#define PNG_CHUNK_ERROR 2 /* always an error */ + +/* ASCII to FP interfaces, currently only implemented if sCAL + * support is required. + */ +#if defined(PNG_sCAL_SUPPORTED) +/* MAX_DIGITS is actually the maximum number of characters in an sCAL + * width or height, derived from the precision (number of significant + * digits - a build time settable option) and assumptions about the + * maximum ridiculous exponent. + */ +#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/) + +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr, + png_charp ascii, png_size_t size, double fp, unsigned int precision), + PNG_EMPTY); +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, + png_charp ascii, png_size_t size, png_fixed_point fp),PNG_EMPTY); +#endif /* FIXED_POINT */ +#endif /* sCAL */ + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* An internal API to validate the format of a floating point number. + * The result is the index of the next character. If the number is + * not valid it will be the index of a character in the supposed number. + * + * The format of a number is defined in the PNG extensions specification + * and this API is strictly conformant to that spec, not anyone elses! + * + * The format as a regular expression is: + * + * [+-]?[0-9]+.?([Ee][+-]?[0-9]+)? + * + * or: + * + * [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)? + * + * The complexity is that either integer or fraction must be present and the + * fraction is permitted to have no digits only if the integer is present. + * + * NOTE: The dangling E problem. + * There is a PNG valid floating point number in the following: + * + * PNG floating point numbers are not greedy. + * + * Working this out requires *TWO* character lookahead (because of the + * sign), the parser does not do this - it will fail at the 'r' - this + * doesn't matter for PNG sCAL chunk values, but it requires more care + * if the value were ever to be embedded in something more complex. Use + * ANSI-C strtod if you need the lookahead. + */ +/* State table for the parser. */ +#define PNG_FP_INTEGER 0 /* before or in integer */ +#define PNG_FP_FRACTION 1 /* before or in fraction */ +#define PNG_FP_EXPONENT 2 /* before or in exponent */ +#define PNG_FP_STATE 3 /* mask for the above */ +#define PNG_FP_SAW_SIGN 4 /* Saw +/- in current state */ +#define PNG_FP_SAW_DIGIT 8 /* Saw a digit in current state */ +#define PNG_FP_SAW_DOT 16 /* Saw a dot in current state */ +#define PNG_FP_SAW_E 32 /* Saw an E (or e) in current state */ +#define PNG_FP_SAW_ANY 60 /* Saw any of the above 4 */ + +/* These three values don't affect the parser. They are set but not used. + */ +#define PNG_FP_WAS_VALID 64 /* Preceding substring is a valid fp number */ +#define PNG_FP_NEGATIVE 128 /* A negative number, including "-0" */ +#define PNG_FP_NONZERO 256 /* A non-zero value */ +#define PNG_FP_STICKY 448 /* The above three flags */ + +/* This is available for the caller to store in 'state' if required. Do not + * call the parser after setting it (the parser sometimes clears it.) + */ +#define PNG_FP_INVALID 512 /* Available for callers as a distinct value */ + +/* Result codes for the parser (boolean - true meants ok, false means + * not ok yet.) + */ +#define PNG_FP_MAYBE 0 /* The number may be valid in the future */ +#define PNG_FP_OK 1 /* The number is valid */ + +/* Tests on the sticky non-zero and negative flags. To pass these checks + * the state must also indicate that the whole number is valid - this is + * achieved by testing PNG_FP_SAW_DIGIT (see the implementation for why this + * is equivalent to PNG_FP_OK above.) + */ +#define PNG_FP_NZ_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NEGATIVE | PNG_FP_NONZERO) + /* NZ_MASK: the string is valid and a non-zero negative value */ +#define PNG_FP_Z_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NONZERO) + /* Z MASK: the string is valid and a non-zero value. */ + /* PNG_FP_SAW_DIGIT: the string is valid. */ +#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT) +#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK) +#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK) + +/* The actual parser. This can be called repeatedly. It updates + * the index into the string and the state variable (which must + * be initialized to 0). It returns a result code, as above. There + * is no point calling the parser any more if it fails to advance to + * the end of the string - it is stuck on an invalid character (or + * terminated by '\0'). + * + * Note that the pointer will consume an E or even an E+ and then leave + * a 'maybe' state even though a preceding integer.fraction is valid. + * The PNG_FP_WAS_VALID flag indicates that a preceding substring was + * a valid number. It's possible to recover from this by calling + * the parser again (from the start, with state 0) but with a string + * that omits the last character (i.e. set the size to the index of + * the problem character.) This has not been tested within libpng. + */ +PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, + png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); + +/* This is the same but it checks a complete string and returns true + * only if it just contains a floating point number. As of 1.5.4 this + * function also returns the state at the end of parsing the number if + * it was valid (otherwise it returns 0.) This can be used for testing + * for negative or zero values using the sticky flag. + */ +PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string, + png_size_t size),PNG_EMPTY); +#endif /* pCAL || sCAL */ + +#if defined(PNG_GAMMA_SUPPORTED) ||\ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) +/* Added at libpng version 1.5.0 */ +/* This is a utility to provide a*times/div (rounded) and indicate + * if there is an overflow. The result is a boolean - false (0) + * for overflow, true (1) if no overflow, in which case *res + * holds the result. + */ +PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a, + png_int_32 multiplied_by, png_int_32 divided_by),PNG_EMPTY); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* Same deal, but issue a warning on overflow and return 0. */ +PNG_INTERNAL_FUNCTION(png_fixed_point,png_muldiv_warn, + (png_const_structrp png_ptr, png_fixed_point a, png_int_32 multiplied_by, + png_int_32 divided_by),PNG_EMPTY); +#endif + +#ifdef PNG_GAMMA_SUPPORTED +/* Calculate a reciprocal - used for gamma values. This returns + * 0 if the argument is 0 in order to maintain an undefined value; + * there are no warnings. + */ +PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a), + PNG_EMPTY); + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The same but gives a reciprocal of the product of two fixed point + * values. Accuracy is suitable for gamma calculations but this is + * not exact - use png_muldiv for that. Only required at present on read. + */ +PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a, + png_fixed_point b),PNG_EMPTY); +#endif + +/* Return true if the gamma value is significantly different from 1.0 */ +PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value), + PNG_EMPTY); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Internal fixed point gamma correction. These APIs are called as + * required to convert single values - they don't need to be fast, + * they are not used when processing image pixel values. + * + * While the input is an 'unsigned' value it must actually be the + * correct bit value - 0..255 or 0..65535 as required. + */ +PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_correct,(png_structrp png_ptr, + unsigned int value, png_fixed_point gamma_value),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_16bit_correct,(unsigned int value, + png_fixed_point gamma_value),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(png_byte,png_gamma_8bit_correct,(unsigned int value, + png_fixed_point gamma_value),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_build_gamma_tables,(png_structrp png_ptr, + int bit_depth),PNG_EMPTY); +#endif + +/* SIMPLIFIED READ/WRITE SUPPORT */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) +/* The internal structure that png_image::opaque points to. */ +typedef struct png_control +{ + png_structp png_ptr; + png_infop info_ptr; + png_voidp error_buf; /* Always a jmp_buf at present. */ + + png_const_bytep memory; /* Memory buffer. */ + png_size_t size; /* Size of the memory buffer. */ + + unsigned int for_write :1; /* Otherwise it is a read structure */ + unsigned int owned_file :1; /* We own the file in io_ptr */ +} png_control; + +/* Return the pointer to the jmp_buf from a png_control: necessary because C + * does not reveal the type of the elements of jmp_buf. + */ +#ifdef __cplusplus +# define png_control_jmp_buf(pc) (((jmp_buf*)((pc)->error_buf))[0]) +#else +# define png_control_jmp_buf(pc) ((pc)->error_buf) +#endif + +/* Utility to safely execute a piece of libpng code catching and logging any + * errors that might occur. Returns true on success, false on failure (either + * of the function or as a result of a png_error.) + */ +PNG_INTERNAL_CALLBACK(void,png_safe_error,(png_structp png_ptr, + png_const_charp error_message),PNG_NORETURN); + +#ifdef PNG_WARNINGS_SUPPORTED +PNG_INTERNAL_CALLBACK(void,png_safe_warning,(png_structp png_ptr, + png_const_charp warning_message),PNG_EMPTY); +#else +# define png_safe_warning 0/*dummy argument*/ +#endif + +PNG_INTERNAL_FUNCTION(int,png_safe_execute,(png_imagep image, + int (*function)(png_voidp), png_voidp arg),PNG_EMPTY); + +/* Utility to log an error; this also cleans up the png_image; the function + * always returns 0 (false). + */ +PNG_INTERNAL_FUNCTION(int,png_image_error,(png_imagep image, + png_const_charp error_message),PNG_EMPTY); + +#ifndef PNG_SIMPLIFIED_READ_SUPPORTED +/* png_image_free is used by the write code but not exported */ +PNG_INTERNAL_FUNCTION(void, png_image_free, (png_imagep image), PNG_EMPTY); +#endif /* !SIMPLIFIED_READ */ + +#endif /* SIMPLIFIED READ/WRITE */ + +/* These are initialization functions for hardware specific PNG filter + * optimizations; list these here then select the appropriate one at compile + * time using the macro PNG_FILTER_OPTIMIZATIONS. If the macro is not defined + * the generic code is used. + */ +#ifdef PNG_FILTER_OPTIMIZATIONS +PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structrp png_ptr, + unsigned int bpp), PNG_EMPTY); + /* Just declare the optimization that will be used */ +#else + /* List *all* the possible optimizations here - this branch is required if + * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in + * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing. + */ +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +#endif + +/* Maintainer: Put new private prototypes here ^ */ + +#include "pngdebug.h" + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +#endif /* PNGPRIV_H */ diff --git a/ext/libpng16/pngread.c b/ext/libpng17/pngread.c similarity index 92% rename from ext/libpng16/pngread.c rename to ext/libpng17/pngread.c index 8709ca75ba..6a6058f0cf 100644 --- a/ext/libpng16/pngread.c +++ b/ext/libpng17/pngread.c @@ -1,4000 +1,4098 @@ - -/* pngread.c - read a PNG file - * - * Last changed in libpng 1.6.1 [March 28, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - * This file contains routines that an application calls directly to - * read a PNG file or stream. - */ - -#include "pngpriv.h" -#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) -# include -#endif - -#ifdef PNG_READ_SUPPORTED - -/* Create a PNG structure for reading, and allocate any memory needed. */ -PNG_FUNCTION(png_structp,PNGAPI -png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) -{ -#ifndef PNG_USER_MEM_SUPPORTED - png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, - error_fn, warn_fn, NULL, NULL, NULL); -#else - return png_create_read_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, NULL, NULL, NULL); -} - -/* Alternate create PNG structure for reading, and allocate any memory - * needed. - */ -PNG_FUNCTION(png_structp,PNGAPI -png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) -{ - png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, - error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); -#endif /* PNG_USER_MEM_SUPPORTED */ - - if (png_ptr != NULL) - { - png_ptr->mode = PNG_IS_READ_STRUCT; - - /* Added in libpng-1.6.0; this can be used to detect a read structure if - * required (it will be zero in a write structure.) - */ -# ifdef PNG_SEQUENTIAL_READ_SUPPORTED - png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE; -# endif - -# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED - png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; - - /* In stable builds only warn if an application error can be completely - * handled. - */ -# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC - png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; -# endif -# endif - - /* TODO: delay this, it can be done in png_init_io (if the app doesn't - * do it itself) avoiding setting the default function if it is not - * required. - */ - png_set_read_fn(png_ptr, NULL, NULL); - } - - return png_ptr; -} - - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. This has been - * changed in v0.90 to allow reading a file that already has the magic - * bytes read from the stream. You can tell libpng how many bytes have - * been read from the beginning of the stream (up to the maximum of 8) - * via png_set_sig_bytes(), and we will only check the remaining bytes - * here. The application can then have access to the signature bytes we - * read if it is determined that this isn't a valid PNG file. - */ -void PNGAPI -png_read_info(png_structrp png_ptr, png_inforp info_ptr) -{ -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - int keep; -#endif - - png_debug(1, "in png_read_info"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - /* Read and check the PNG file signature. */ - png_read_sig(png_ptr, info_ptr); - - for (;;) - { - png_uint_32 length = png_read_chunk_header(png_ptr); - png_uint_32 chunk_name = png_ptr->chunk_name; - - /* IDAT logic needs to happen here to simplify getting the two flags - * right. - */ - if (chunk_name == png_IDAT) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "Missing IHDR before IDAT"); - - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_chunk_error(png_ptr, "Missing PLTE before IDAT"); - - else if (png_ptr->mode & PNG_AFTER_IDAT) - png_chunk_benign_error(png_ptr, "Too many IDATs found"); - - png_ptr->mode |= PNG_HAVE_IDAT; - } - - else if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - - /* This should be a binary subdivision search or a hash for - * matching the chunk name rather than a linear search. - */ - if (chunk_name == png_IHDR) - png_handle_IHDR(png_ptr, info_ptr, length); - - else if (chunk_name == png_IEND) - png_handle_IEND(png_ptr, info_ptr, length); - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) - { - png_handle_unknown(png_ptr, info_ptr, length, keep); - - if (chunk_name == png_PLTE) - png_ptr->mode |= PNG_HAVE_PLTE; - - else if (chunk_name == png_IDAT) - { - png_ptr->idat_size = 0; /* It has been consumed */ - break; - } - } -#endif - else if (chunk_name == png_PLTE) - png_handle_PLTE(png_ptr, info_ptr, length); - - else if (chunk_name == png_IDAT) - { - png_ptr->idat_size = length; - break; - } - -#ifdef PNG_READ_bKGD_SUPPORTED - else if (chunk_name == png_bKGD) - png_handle_bKGD(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_cHRM_SUPPORTED - else if (chunk_name == png_cHRM) - png_handle_cHRM(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_gAMA_SUPPORTED - else if (chunk_name == png_gAMA) - png_handle_gAMA(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_hIST_SUPPORTED - else if (chunk_name == png_hIST) - png_handle_hIST(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_oFFs_SUPPORTED - else if (chunk_name == png_oFFs) - png_handle_oFFs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED - else if (chunk_name == png_pCAL) - png_handle_pCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sCAL_SUPPORTED - else if (chunk_name == png_sCAL) - png_handle_sCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pHYs_SUPPORTED - else if (chunk_name == png_pHYs) - png_handle_pHYs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sBIT_SUPPORTED - else if (chunk_name == png_sBIT) - png_handle_sBIT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sRGB_SUPPORTED - else if (chunk_name == png_sRGB) - png_handle_sRGB(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iCCP_SUPPORTED - else if (chunk_name == png_iCCP) - png_handle_iCCP(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sPLT_SUPPORTED - else if (chunk_name == png_sPLT) - png_handle_sPLT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tEXt_SUPPORTED - else if (chunk_name == png_tEXt) - png_handle_tEXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tIME_SUPPORTED - else if (chunk_name == png_tIME) - png_handle_tIME(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tRNS_SUPPORTED - else if (chunk_name == png_tRNS) - png_handle_tRNS(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED - else if (chunk_name == png_zTXt) - png_handle_zTXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iTXt_SUPPORTED - else if (chunk_name == png_iTXt) - png_handle_iTXt(png_ptr, info_ptr, length); -#endif - - else - png_handle_unknown(png_ptr, info_ptr, length, - PNG_HANDLE_CHUNK_AS_DEFAULT); - } -} -#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ - -/* Optional call to update the users info_ptr structure */ -void PNGAPI -png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) -{ - png_debug(1, "in png_read_update_info"); - - if (png_ptr != NULL) - { - if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) - { - png_read_start_row(png_ptr); - -# ifdef PNG_READ_TRANSFORMS_SUPPORTED - png_read_transform_info(png_ptr, info_ptr); -# else - PNG_UNUSED(info_ptr) -# endif - } - - /* New in 1.6.0 this avoids the bug of doing the initializations twice */ - else - png_app_error(png_ptr, - "png_read_update_info/png_start_read_image: duplicate call"); - } -} - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Initialize palette, background, etc, after transformations - * are set, but before any reading takes place. This allows - * the user to obtain a gamma-corrected palette, for example. - * If the user doesn't call this, we will do it ourselves. - */ -void PNGAPI -png_start_read_image(png_structrp png_ptr) -{ - png_debug(1, "in png_start_read_image"); - - if (png_ptr != NULL) - { - if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) - png_read_start_row(png_ptr); - - /* New in 1.6.0 this avoids the bug of doing the initializations twice */ - else - png_app_error(png_ptr, - "png_start_read_image/png_read_update_info: duplicate call"); - } -} -#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -void PNGAPI -png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) -{ - png_row_info row_info; - - if (png_ptr == NULL) - return; - - png_debug2(1, "in png_read_row (row %lu, pass %d)", - (unsigned long)png_ptr->row_number, png_ptr->pass); - - /* png_read_start_row sets the information (in particular iwidth) for this - * interlace pass. - */ - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); - - /* 1.5.6: row_info moved out of png_struct to a local here. */ - row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ - row_info.color_type = png_ptr->color_type; - row_info.bit_depth = png_ptr->bit_depth; - row_info.channels = png_ptr->channels; - row_info.pixel_depth = png_ptr->pixel_depth; - row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); - - if (png_ptr->row_number == 0 && png_ptr->pass == 0) - { - /* Check for transforms that have been set but were defined out */ -#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); -#endif - -#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); -#endif - -#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ - !defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); -#endif - -#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); -#endif - -#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); -#endif - -#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); -#endif - -#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); -#endif - } - -#ifdef PNG_READ_INTERLACING_SUPPORTED - /* If interlaced and we do not need a new row, combine row and return. - * Notice that the pixels we have from previous rows have been transformed - * already; we can only combine like with like (transformed or - * untransformed) and, because of the libpng API for interlaced images, this - * means we must transform before de-interlacing. - */ - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) - { - switch (png_ptr->pass) - { - case 0: - if (png_ptr->row_number & 0x07) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, 1/*display*/); - png_read_finish_row(png_ptr); - return; - } - break; - - case 1: - if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, 1/*display*/); - - png_read_finish_row(png_ptr); - return; - } - break; - - case 2: - if ((png_ptr->row_number & 0x07) != 4) - { - if (dsp_row != NULL && (png_ptr->row_number & 4)) - png_combine_row(png_ptr, dsp_row, 1/*display*/); - - png_read_finish_row(png_ptr); - return; - } - break; - - case 3: - if ((png_ptr->row_number & 3) || png_ptr->width < 3) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, 1/*display*/); - - png_read_finish_row(png_ptr); - return; - } - break; - - case 4: - if ((png_ptr->row_number & 3) != 2) - { - if (dsp_row != NULL && (png_ptr->row_number & 2)) - png_combine_row(png_ptr, dsp_row, 1/*display*/); - - png_read_finish_row(png_ptr); - return; - } - break; - - case 5: - if ((png_ptr->row_number & 1) || png_ptr->width < 2) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, 1/*display*/); - - png_read_finish_row(png_ptr); - return; - } - break; - - default: - case 6: - if (!(png_ptr->row_number & 1)) - { - png_read_finish_row(png_ptr); - return; - } - break; - } - } -#endif - - if (!(png_ptr->mode & PNG_HAVE_IDAT)) - png_error(png_ptr, "Invalid attempt to read row data"); - - /* Fill the row with IDAT data: */ - png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1); - - if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) - { - if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) - png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, - png_ptr->prev_row + 1, png_ptr->row_buf[0]); - else - png_error(png_ptr, "bad adaptive filter value"); - } - - /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before - * 1.5.6, while the buffer really is this big in current versions of libpng - * it may not be in the future, so this was changed just to copy the - * interlaced count: - */ - memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); - -#ifdef PNG_MNG_FEATURES_SUPPORTED - if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) - { - /* Intrapixel differencing */ - png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1); - } -#endif - - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED - if (png_ptr->transformations) - png_do_read_transformations(png_ptr, &row_info); -#endif - - /* The transformed pixel depth should match the depth now in row_info. */ - if (png_ptr->transformed_pixel_depth == 0) - { - png_ptr->transformed_pixel_depth = row_info.pixel_depth; - if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) - png_error(png_ptr, "sequential row overflow"); - } - - else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) - png_error(png_ptr, "internal sequential row size calculation error"); - -#ifdef PNG_READ_INTERLACING_SUPPORTED - /* Blow up interlaced rows to full size */ - if (png_ptr->interlaced && - (png_ptr->transformations & PNG_INTERLACE)) - { - if (png_ptr->pass < 6) - png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, - png_ptr->transformations); - - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, 1/*display*/); - - if (row != NULL) - png_combine_row(png_ptr, row, 0/*row*/); - } - - else -#endif - { - if (row != NULL) - png_combine_row(png_ptr, row, -1/*ignored*/); - - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, -1/*ignored*/); - } - png_read_finish_row(png_ptr); - - if (png_ptr->read_row_fn != NULL) - (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); - -} -#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. If the image is interlaced, - * and png_set_interlace_handling() has been called, the rows need to - * contain the contents of the rows from the previous pass. If the - * image has alpha or transparency, and png_handle_alpha()[*] has been - * called, the rows contents must be initialized to the contents of the - * screen. - * - * "row" holds the actual image, and pixels are placed in it - * as they arrive. If the image is displayed after each pass, it will - * appear to "sparkle" in. "display_row" can be used to display a - * "chunky" progressive image, with finer detail added as it becomes - * available. If you do not want this "chunky" display, you may pass - * NULL for display_row. If you do not want the sparkle display, and - * you have not called png_handle_alpha(), you may pass NULL for rows. - * If you have called png_handle_alpha(), and the image has either an - * alpha channel or a transparency chunk, you must provide a buffer for - * rows. In this case, you do not have to provide a display_row buffer - * also, but you may. If the image is not interlaced, or if you have - * not called png_set_interlace_handling(), the display_row buffer will - * be ignored, so pass NULL to it. - * - * [*] png_handle_alpha() does not exist yet, as of this version of libpng - */ - -void PNGAPI -png_read_rows(png_structrp png_ptr, png_bytepp row, - png_bytepp display_row, png_uint_32 num_rows) -{ - png_uint_32 i; - png_bytepp rp; - png_bytepp dp; - - png_debug(1, "in png_read_rows"); - - if (png_ptr == NULL) - return; - - rp = row; - dp = display_row; - if (rp != NULL && dp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep rptr = *rp++; - png_bytep dptr = *dp++; - - png_read_row(png_ptr, rptr, dptr); - } - - else if (rp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep rptr = *rp; - png_read_row(png_ptr, rptr, NULL); - rp++; - } - - else if (dp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep dptr = *dp; - png_read_row(png_ptr, NULL, dptr); - dp++; - } -} -#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the entire image. If the image has an alpha channel or a tRNS - * chunk, and you have called png_handle_alpha()[*], you will need to - * initialize the image to the current image that PNG will be overlaying. - * We set the num_rows again here, in case it was incorrectly set in - * png_read_start_row() by a call to png_read_update_info() or - * png_start_read_image() if png_set_interlace_handling() wasn't called - * prior to either of these functions like it should have been. You can - * only call this function once. If you desire to have an image for - * each pass of a interlaced image, use png_read_rows() instead. - * - * [*] png_handle_alpha() does not exist yet, as of this version of libpng - */ -void PNGAPI -png_read_image(png_structrp png_ptr, png_bytepp image) -{ - png_uint_32 i, image_height; - int pass, j; - png_bytepp rp; - - png_debug(1, "in png_read_image"); - - if (png_ptr == NULL) - return; - -#ifdef PNG_READ_INTERLACING_SUPPORTED - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - { - pass = png_set_interlace_handling(png_ptr); - /* And make sure transforms are initialized. */ - png_start_read_image(png_ptr); - } - else - { - if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) - { - /* Caller called png_start_read_image or png_read_update_info without - * first turning on the PNG_INTERLACE transform. We can fix this here, - * but the caller should do it! - */ - png_warning(png_ptr, "Interlace handling should be turned on when " - "using png_read_image"); - /* Make sure this is set correctly */ - png_ptr->num_rows = png_ptr->height; - } - - /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in - * the above error case. - */ - pass = png_set_interlace_handling(png_ptr); - } -#else - if (png_ptr->interlaced) - png_error(png_ptr, - "Cannot read interlaced image -- interlace handler disabled"); - - pass = 1; -#endif - - image_height=png_ptr->height; - - for (j = 0; j < pass; j++) - { - rp = image; - for (i = 0; i < image_height; i++) - { - png_read_row(png_ptr, *rp, NULL); - rp++; - } - } -} -#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. Will not read past the end of the - * file, will verify the end is accurate, and will read any comments - * or time information at the end of the file, if info is not NULL. - */ -void PNGAPI -png_read_end(png_structrp png_ptr, png_inforp info_ptr) -{ -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - int keep; -#endif - - png_debug(1, "in png_read_end"); - - if (png_ptr == NULL) - return; - - /* If png_read_end is called in the middle of reading the rows there may - * still be pending IDAT data and an owned zstream. Deal with this here. - */ -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - if (!png_chunk_unknown_handling(png_ptr, png_IDAT)) -#endif - png_read_finish_IDAT(png_ptr); - -#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED - /* Report invalid palette index; added at libng-1.5.10 */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - png_ptr->num_palette_max > png_ptr->num_palette) - png_benign_error(png_ptr, "Read palette index exceeding num_palette"); -#endif - - do - { - png_uint_32 length = png_read_chunk_header(png_ptr); - png_uint_32 chunk_name = png_ptr->chunk_name; - - if (chunk_name == png_IHDR) - png_handle_IHDR(png_ptr, info_ptr, length); - - else if (chunk_name == png_IEND) - png_handle_IEND(png_ptr, info_ptr, length); - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) - { - if (chunk_name == png_IDAT) - { - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - png_benign_error(png_ptr, "Too many IDATs found"); - } - png_handle_unknown(png_ptr, info_ptr, length, keep); - if (chunk_name == png_PLTE) - png_ptr->mode |= PNG_HAVE_PLTE; - } -#endif - - else if (chunk_name == png_IDAT) - { - /* Zero length IDATs are legal after the last IDAT has been - * read, but not after other chunks have been read. - */ - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - png_benign_error(png_ptr, "Too many IDATs found"); - - png_crc_finish(png_ptr, length); - } - else if (chunk_name == png_PLTE) - png_handle_PLTE(png_ptr, info_ptr, length); - -#ifdef PNG_READ_bKGD_SUPPORTED - else if (chunk_name == png_bKGD) - png_handle_bKGD(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_cHRM_SUPPORTED - else if (chunk_name == png_cHRM) - png_handle_cHRM(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_gAMA_SUPPORTED - else if (chunk_name == png_gAMA) - png_handle_gAMA(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_hIST_SUPPORTED - else if (chunk_name == png_hIST) - png_handle_hIST(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_oFFs_SUPPORTED - else if (chunk_name == png_oFFs) - png_handle_oFFs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED - else if (chunk_name == png_pCAL) - png_handle_pCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sCAL_SUPPORTED - else if (chunk_name == png_sCAL) - png_handle_sCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pHYs_SUPPORTED - else if (chunk_name == png_pHYs) - png_handle_pHYs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sBIT_SUPPORTED - else if (chunk_name == png_sBIT) - png_handle_sBIT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sRGB_SUPPORTED - else if (chunk_name == png_sRGB) - png_handle_sRGB(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iCCP_SUPPORTED - else if (chunk_name == png_iCCP) - png_handle_iCCP(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sPLT_SUPPORTED - else if (chunk_name == png_sPLT) - png_handle_sPLT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tEXt_SUPPORTED - else if (chunk_name == png_tEXt) - png_handle_tEXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tIME_SUPPORTED - else if (chunk_name == png_tIME) - png_handle_tIME(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tRNS_SUPPORTED - else if (chunk_name == png_tRNS) - png_handle_tRNS(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED - else if (chunk_name == png_zTXt) - png_handle_zTXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iTXt_SUPPORTED - else if (chunk_name == png_iTXt) - png_handle_iTXt(png_ptr, info_ptr, length); -#endif - - else - png_handle_unknown(png_ptr, info_ptr, length, - PNG_HANDLE_CHUNK_AS_DEFAULT); - } while (!(png_ptr->mode & PNG_HAVE_IEND)); -} -#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ - -/* Free all memory used in the read struct */ -static void -png_read_destroy(png_structrp png_ptr) -{ - png_debug(1, "in png_read_destroy"); - -#ifdef PNG_READ_GAMMA_SUPPORTED - png_destroy_gamma_table(png_ptr); -#endif - - png_free(png_ptr, png_ptr->big_row_buf); - png_free(png_ptr, png_ptr->big_prev_row); - png_free(png_ptr, png_ptr->read_buffer); - -#ifdef PNG_READ_QUANTIZE_SUPPORTED - png_free(png_ptr, png_ptr->palette_lookup); - png_free(png_ptr, png_ptr->quantize_index); -#endif - - if (png_ptr->free_me & PNG_FREE_PLTE) - png_zfree(png_ptr, png_ptr->palette); - png_ptr->free_me &= ~PNG_FREE_PLTE; - -#if defined(PNG_tRNS_SUPPORTED) || \ - defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->free_me & PNG_FREE_TRNS) - png_free(png_ptr, png_ptr->trans_alpha); - png_ptr->free_me &= ~PNG_FREE_TRNS; -#endif - - inflateEnd(&png_ptr->zstream); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_free(png_ptr, png_ptr->save_buffer); -#endif - -#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) &&\ - defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - png_free(png_ptr, png_ptr->unknown_chunk.data); -#endif - -#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - png_free(png_ptr, png_ptr->chunk_list); -#endif - - /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error - * callbacks are still set at this point. They are required to complete the - * destruction of the png_struct itself. - */ -} - -/* Free all memory used by the read */ -void PNGAPI -png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, - png_infopp end_info_ptr_ptr) -{ - png_structrp png_ptr = NULL; - - png_debug(1, "in png_destroy_read_struct"); - - if (png_ptr_ptr != NULL) - png_ptr = *png_ptr_ptr; - - if (png_ptr == NULL) - return; - - /* libpng 1.6.0: use the API to destroy info structs to ensure consistent - * behavior. Prior to 1.6.0 libpng did extra 'info' destruction in this API. - * The extra was, apparently, unnecessary yet this hides memory leak bugs. - */ - png_destroy_info_struct(png_ptr, end_info_ptr_ptr); - png_destroy_info_struct(png_ptr, info_ptr_ptr); - - *png_ptr_ptr = NULL; - png_read_destroy(png_ptr); - png_destroy_png_struct(png_ptr); -} - -void PNGAPI -png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn) -{ - if (png_ptr == NULL) - return; - - png_ptr->read_row_fn = read_row_fn; -} - - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -#ifdef PNG_INFO_IMAGE_SUPPORTED -void PNGAPI -png_read_png(png_structrp png_ptr, png_inforp info_ptr, - int transforms, - voidp params) -{ - int row; - - if (png_ptr == NULL || info_ptr == NULL) - return; - - /* png_read_info() gives us all of the information from the - * PNG file before the first IDAT (image data chunk). - */ - png_read_info(png_ptr, info_ptr); - if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep))) - png_error(png_ptr, "Image is too high to process with png_read_png()"); - - /* -------------- image transformations start here ------------------- */ - -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED - /* Tell libpng to strip 16-bit/color files down to 8 bits per color. - */ - if (transforms & PNG_TRANSFORM_SCALE_16) - { - /* Added at libpng-1.5.4. "strip_16" produces the same result that it - * did in earlier versions, while "scale_16" is now more accurate. - */ - png_set_scale_16(png_ptr); - } -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED - /* If both SCALE and STRIP are required pngrtran will effectively cancel the - * latter by doing SCALE first. This is ok and allows apps not to check for - * which is supported to get the right answer. - */ - if (transforms & PNG_TRANSFORM_STRIP_16) - png_set_strip_16(png_ptr); -#endif - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - /* Strip alpha bytes from the input data without combining with - * the background (not recommended). - */ - if (transforms & PNG_TRANSFORM_STRIP_ALPHA) - png_set_strip_alpha(png_ptr); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) - /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single - * byte into separate bytes (useful for paletted and grayscale images). - */ - if (transforms & PNG_TRANSFORM_PACKING) - png_set_packing(png_ptr); -#endif - -#ifdef PNG_READ_PACKSWAP_SUPPORTED - /* Change the order of packed pixels to least significant bit first - * (not useful if you are using png_set_packing). - */ - if (transforms & PNG_TRANSFORM_PACKSWAP) - png_set_packswap(png_ptr); -#endif - -#ifdef PNG_READ_EXPAND_SUPPORTED - /* Expand paletted colors into true RGB triplets - * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel - * Expand paletted or RGB images with transparency to full alpha - * channels so the data will be available as RGBA quartets. - */ - if (transforms & PNG_TRANSFORM_EXPAND) - if ((png_ptr->bit_depth < 8) || - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || - (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) - png_set_expand(png_ptr); -#endif - - /* We don't handle background color or gamma transformation or quantizing. - */ - -#ifdef PNG_READ_INVERT_SUPPORTED - /* Invert monochrome files to have 0 as white and 1 as black - */ - if (transforms & PNG_TRANSFORM_INVERT_MONO) - png_set_invert_mono(png_ptr); -#endif - -#ifdef PNG_READ_SHIFT_SUPPORTED - /* If you want to shift the pixel values from the range [0,255] or - * [0,65535] to the original [0,7] or [0,31], or whatever range the - * colors were originally in: - */ - if ((transforms & PNG_TRANSFORM_SHIFT) - && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) - { - png_color_8p sig_bit; - - png_get_sBIT(png_ptr, info_ptr, &sig_bit); - png_set_shift(png_ptr, sig_bit); - } -#endif - -#ifdef PNG_READ_BGR_SUPPORTED - /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ - if (transforms & PNG_TRANSFORM_BGR) - png_set_bgr(png_ptr); -#endif - -#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED - /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ - if (transforms & PNG_TRANSFORM_SWAP_ALPHA) - png_set_swap_alpha(png_ptr); -#endif - -#ifdef PNG_READ_SWAP_SUPPORTED - /* Swap bytes of 16-bit files to least significant byte first */ - if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) - png_set_swap(png_ptr); -#endif - -/* Added at libpng-1.2.41 */ -#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED - /* Invert the alpha channel from opacity to transparency */ - if (transforms & PNG_TRANSFORM_INVERT_ALPHA) - png_set_invert_alpha(png_ptr); -#endif - -/* Added at libpng-1.2.41 */ -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED - /* Expand grayscale image to RGB */ - if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) - png_set_gray_to_rgb(png_ptr); -#endif - -/* Added at libpng-1.5.4 */ -#ifdef PNG_READ_EXPAND_16_SUPPORTED - if (transforms & PNG_TRANSFORM_EXPAND_16) - png_set_expand_16(png_ptr); -#endif - - /* We don't handle adding filler bytes */ - - /* We use png_read_image and rely on that for interlace handling, but we also - * call png_read_update_info therefore must turn on interlace handling now: - */ - (void)png_set_interlace_handling(png_ptr); - - /* Optional call to gamma correct and add the background to the palette - * and update info structure. REQUIRED if you are expecting libpng to - * update the palette for you (i.e., you selected such a transform above). - */ - png_read_update_info(png_ptr, info_ptr); - - /* -------------- image transformations end here ------------------- */ - - png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); - if (info_ptr->row_pointers == NULL) - { - png_uint_32 iptr; - - info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, - info_ptr->height * (sizeof (png_bytep))); - for (iptr=0; iptrheight; iptr++) - info_ptr->row_pointers[iptr] = NULL; - - info_ptr->free_me |= PNG_FREE_ROWS; - - for (row = 0; row < (int)info_ptr->height; row++) - info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, - png_get_rowbytes(png_ptr, info_ptr)); - } - - png_read_image(png_ptr, info_ptr->row_pointers); - info_ptr->valid |= PNG_INFO_IDAT; - - /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ - png_read_end(png_ptr, info_ptr); - - PNG_UNUSED(transforms) /* Quiet compiler warnings */ - PNG_UNUSED(params) - -} -#endif /* PNG_INFO_IMAGE_SUPPORTED */ -#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ - -#ifdef PNG_SIMPLIFIED_READ_SUPPORTED -/* SIMPLIFIED READ - * - * This code currently relies on the sequential reader, though it could easily - * be made to work with the progressive one. - */ -/* Arguments to png_image_finish_read: */ - -/* Encoding of PNG data (used by the color-map code) */ -/* TODO: change these, dang, ANSI-C reserves the 'E' namespace. */ -# define E_NOTSET 0 /* File encoding not yet known */ -# define E_sRGB 1 /* 8-bit encoded to sRGB gamma */ -# define E_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */ -# define E_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */ -# define E_LINEAR8 4 /* 8-bit linear: only from a file value */ - -/* Color-map processing: after libpng has run on the PNG image further - * processing may be needed to conver the data to color-map indicies. - */ -#define PNG_CMAP_NONE 0 -#define PNG_CMAP_GA 1 /* Process GA data to a color-map with alpha */ -#define PNG_CMAP_TRANS 2 /* Process GA data to a background index */ -#define PNG_CMAP_RGB 3 /* Process RGB data */ -#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */ - -/* The following document where the background is for each processing case. */ -#define PNG_CMAP_NONE_BACKGROUND 256 -#define PNG_CMAP_GA_BACKGROUND 231 -#define PNG_CMAP_TRANS_BACKGROUND 254 -#define PNG_CMAP_RGB_BACKGROUND 256 -#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216 - -typedef struct -{ - /* Arguments: */ - png_imagep image; - png_voidp buffer; - png_int_32 row_stride; - png_voidp colormap; - png_const_colorp background; - /* Local variables: */ - png_voidp local_row; - png_voidp first_row; - ptrdiff_t row_bytes; /* step between rows */ - int file_encoding; /* E_ values above */ - png_fixed_point gamma_to_linear; /* For E_FILE, reciprocal of gamma */ - int colormap_processing; /* PNG_CMAP_ values above */ -} png_image_read_control; - -/* Do all the *safe* initialization - 'safe' means that png_error won't be - * called, so setting up the jmp_buf is not required. This means that anything - * called from here must *not* call png_malloc - it has to call png_malloc_warn - * instead so that control is returned safely back to this routine. - */ -static int -png_image_read_init(png_imagep image) -{ - if (image->opaque == NULL) - { - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image, - png_safe_error, png_safe_warning); - - /* And set the rest of the structure to NULL to ensure that the various - * fields are consistent. - */ - memset(image, 0, (sizeof *image)); - image->version = PNG_IMAGE_VERSION; - - if (png_ptr != NULL) - { - png_infop info_ptr = png_create_info_struct(png_ptr); - - if (info_ptr != NULL) - { - png_controlp control = png_voidcast(png_controlp, - png_malloc_warn(png_ptr, (sizeof *control))); - - if (control != NULL) - { - memset(control, 0, (sizeof *control)); - - control->png_ptr = png_ptr; - control->info_ptr = info_ptr; - control->for_write = 0; - - image->opaque = control; - return 1; - } - - /* Error clean up */ - png_destroy_info_struct(png_ptr, &info_ptr); - } - - png_destroy_read_struct(&png_ptr, NULL, NULL); - } - - return png_image_error(image, "png_image_read: out of memory"); - } - - return png_image_error(image, "png_image_read: opaque pointer not NULL"); -} - -/* Utility to find the base format of a PNG file from a png_struct. */ -static png_uint_32 -png_image_format(png_structrp png_ptr) -{ - png_uint_32 format = 0; - - if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - format |= PNG_FORMAT_FLAG_COLOR; - - if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) - format |= PNG_FORMAT_FLAG_ALPHA; - - /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS - * sets the png_struct fields; that's all we are interested in here. The - * precise interaction with an app call to png_set_tRNS and PNG file reading - * is unclear. - */ - else if (png_ptr->num_trans > 0) - format |= PNG_FORMAT_FLAG_ALPHA; - - if (png_ptr->bit_depth == 16) - format |= PNG_FORMAT_FLAG_LINEAR; - - if (png_ptr->color_type & PNG_COLOR_MASK_PALETTE) - format |= PNG_FORMAT_FLAG_COLORMAP; - - return format; -} - -/* Is the given gamma significantly different from sRGB? The test is the same - * one used in pngrtran.c when deciding whether to do gamma correction. The - * arithmetic optimizes the division by using the fact that the inverse of the - * file sRGB gamma is 2.2 - */ -static int -png_gamma_not_sRGB(png_fixed_point g) -{ - if (g < PNG_FP_1) - { - /* An uninitialized gamma is assumed to be sRGB for the simplified API. */ - if (g == 0) - return 0; - - return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */); - } - - return 1; -} - -/* Do the main body of a 'png_image_begin_read' function; read the PNG file - * header and fill in all the information. This is executed in a safe context, - * unlike the init routine above. - */ -static int -png_image_read_header(png_voidp argument) -{ - png_imagep image = png_voidcast(png_imagep, argument); - png_structrp png_ptr = image->opaque->png_ptr; - png_inforp info_ptr = image->opaque->info_ptr; - - png_set_benign_errors(png_ptr, 1/*warn*/); - png_read_info(png_ptr, info_ptr); - - /* Do this the fast way; just read directly out of png_struct. */ - image->width = png_ptr->width; - image->height = png_ptr->height; - - { - png_uint_32 format = png_image_format(png_ptr); - - image->format = format; - -#ifdef PNG_COLORSPACE_SUPPORTED - /* Does the colorspace match sRGB? If there is no color endpoint - * (colorant) information assume yes, otherwise require the - * 'ENDPOINTS_MATCHE_sRGB' colorspace flag to have been set. If the - * colorspace has been determined to be invalid ignore it. - */ - if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags - & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB| - PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS)) - image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB; -#endif - } - - /* We need the maximum number of entries regardless of the format the - * application sets here. - */ - { - png_uint_32 cmap_entries; - - switch (png_ptr->color_type) - { - case PNG_COLOR_TYPE_GRAY: - cmap_entries = 1U << png_ptr->bit_depth; - break; - - case PNG_COLOR_TYPE_PALETTE: - cmap_entries = png_ptr->num_palette; - break; - - default: - cmap_entries = 256; - break; - } - - if (cmap_entries > 256) - cmap_entries = 256; - - image->colormap_entries = cmap_entries; - } - - return 1; -} - -#ifdef PNG_STDIO_SUPPORTED -int PNGAPI -png_image_begin_read_from_stdio(png_imagep image, FILE* file) -{ - if (image != NULL && image->version == PNG_IMAGE_VERSION) - { - if (file != NULL) - { - if (png_image_read_init(image)) - { - /* This is slightly evil, but png_init_io doesn't do anything other - * than this and we haven't changed the standard IO functions so - * this saves a 'safe' function. - */ - image->opaque->png_ptr->io_ptr = file; - return png_safe_execute(image, png_image_read_header, image); - } - } - - else - return png_image_error(image, - "png_image_begin_read_from_stdio: invalid argument"); - } - - else if (image != NULL) - return png_image_error(image, - "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION"); - - return 0; -} - -int PNGAPI -png_image_begin_read_from_file(png_imagep image, const char *file_name) -{ - if (image != NULL && image->version == PNG_IMAGE_VERSION) - { - if (file_name != NULL) - { - FILE *fp = fopen(file_name, "rb"); - - if (fp != NULL) - { - if (png_image_read_init(image)) - { - image->opaque->png_ptr->io_ptr = fp; - image->opaque->owned_file = 1; - return png_safe_execute(image, png_image_read_header, image); - } - - /* Clean up: just the opened file. */ - (void)fclose(fp); - } - - else - return png_image_error(image, strerror(errno)); - } - - else - return png_image_error(image, - "png_image_begin_read_from_file: invalid argument"); - } - - else if (image != NULL) - return png_image_error(image, - "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION"); - - return 0; -} -#endif /* PNG_STDIO_SUPPORTED */ - -static void PNGCBAPI -png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) -{ - if (png_ptr != NULL) - { - png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr); - if (image != NULL) - { - png_controlp cp = image->opaque; - if (cp != NULL) - { - png_const_bytep memory = cp->memory; - png_size_t size = cp->size; - - if (memory != NULL && size >= need) - { - memcpy(out, memory, need); - cp->memory = memory + need; - cp->size = size - need; - return; - } - - png_error(png_ptr, "read beyond end of data"); - } - } - - png_error(png_ptr, "invalid memory read"); - } -} - -int PNGAPI png_image_begin_read_from_memory(png_imagep image, - png_const_voidp memory, png_size_t size) -{ - if (image != NULL && image->version == PNG_IMAGE_VERSION) - { - if (memory != NULL && size > 0) - { - if (png_image_read_init(image)) - { - /* Now set the IO functions to read from the memory buffer and - * store it into io_ptr. Again do this in-place to avoid calling a - * libpng function that requires error handling. - */ - image->opaque->memory = png_voidcast(png_const_bytep, memory); - image->opaque->size = size; - image->opaque->png_ptr->io_ptr = image; - image->opaque->png_ptr->read_data_fn = png_image_memory_read; - - return png_safe_execute(image, png_image_read_header, image); - } - } - - else - return png_image_error(image, - "png_image_begin_read_from_memory: invalid argument"); - } - - else if (image != NULL) - return png_image_error(image, - "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION"); - - return 0; -} - -/* Utility function to skip chunks that are not used by the simplified image - * read functions and an appropriate macro to call it. - */ -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -static void -png_image_skip_unused_chunks(png_structrp png_ptr) -{ - /* Prepare the reader to ignore all recognized chunks whose data will not - * be used, i.e., all chunks recognized by libpng except for those - * involved in basic image reading: - * - * IHDR, PLTE, IDAT, IEND - * - * Or image data handling: - * - * tRNS, bKGD, gAMA, cHRM, sRGB, iCCP and sBIT. - * - * This provides a small performance improvement and eliminates any - * potential vulnerability to security problems in the unused chunks. - */ - { - static PNG_CONST png_byte chunks_to_process[] = { - 98, 75, 71, 68, '\0', /* bKGD */ - 99, 72, 82, 77, '\0', /* cHRM */ - 103, 65, 77, 65, '\0', /* gAMA */ - 105, 67, 67, 80, '\0', /* iCCP */ - 115, 66, 73, 84, '\0', /* sBIT */ - 115, 82, 71, 66, '\0', /* sRGB */ - }; - - /* Ignore unknown chunks and all other chunks except for the - * IHDR, PLTE, tRNS, IDAT, and IEND chunks. - */ - png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER, - NULL, -1); - - /* But do not ignore image data handling chunks */ - png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT, - chunks_to_process, (sizeof chunks_to_process)/5); - } -} - -# define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p) -#else -# define PNG_SKIP_CHUNKS(p) ((void)0) -#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ - -/* The following macro gives the exact rounded answer for all values in the - * range 0..255 (it actually divides by 51.2, but the rounding still generates - * the correct numbers 0..5 - */ -#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8) - -/* Utility functions to make particular color-maps */ -static void -set_file_encoding(png_image_read_control *display) -{ - png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma; - if (png_gamma_significant(g)) - { - if (png_gamma_not_sRGB(g)) - { - display->file_encoding = E_FILE; - display->gamma_to_linear = png_reciprocal(g); - } - - else - display->file_encoding = E_sRGB; - } - - else - display->file_encoding = E_LINEAR8; -} - -static unsigned int -decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) -{ - if (encoding == E_FILE) /* double check */ - encoding = display->file_encoding; - - if (encoding == E_NOTSET) /* must be the file encoding */ - { - set_file_encoding(display); - encoding = display->file_encoding; - } - - switch (encoding) - { - case E_FILE: - value = png_gamma_16bit_correct(value*257, display->gamma_to_linear); - break; - - case E_sRGB: - value = png_sRGB_table[value]; - break; - - case E_LINEAR: - break; - - case E_LINEAR8: - value *= 257; - break; - - default: - png_error(display->image->opaque->png_ptr, - "unexpected encoding (internal error)"); - break; - } - - return value; -} - -static png_uint_32 -png_colormap_compose(png_image_read_control *display, - png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, - png_uint_32 background, int encoding) -{ - /* The file value is composed on the background, the background has the given - * encoding and so does the result, the file is encoded with E_FILE and the - * file and alpha are 8-bit values. The (output) encoding will always be - * E_LINEAR or E_sRGB. - */ - png_uint_32 f = decode_gamma(display, foreground, foreground_encoding); - png_uint_32 b = decode_gamma(display, background, encoding); - - /* The alpha is always an 8-bit value (it comes from the palette), the value - * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires. - */ - f = f * alpha + b * (255-alpha); - - if (encoding == E_LINEAR) - { - /* Scale to 65535; divide by 255, approximately (in fact this is extremely - * accurate, it divides by 255.00000005937181414556, with no overflow.) - */ - f *= 257; /* Now scaled by 65535 */ - f += f >> 16; - f = (f+32768) >> 16; - } - - else /* E_sRGB */ - f = PNG_sRGB_FROM_LINEAR(f); - - return f; -} - -/* NOTE: E_LINEAR values to this routine must be 16-bit, but E_FILE values must - * be 8-bit. - */ -static void -png_create_colormap_entry(png_image_read_control *display, - png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, - png_uint_32 alpha, int encoding) -{ - png_imagep image = display->image; - const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) ? - E_LINEAR : E_sRGB; - const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && - (red != green || green != blue); - - if (ip > 255) - png_error(image->opaque->png_ptr, "color-map index out of range"); - - /* Update the cache with whether the file gamma is significantly different - * from sRGB. - */ - if (encoding == E_FILE) - { - if (display->file_encoding == E_NOTSET) - set_file_encoding(display); - - /* Note that the cached value may be E_FILE too, but if it is then the - * gamma_to_linear member has been set. - */ - encoding = display->file_encoding; - } - - if (encoding == E_FILE) - { - png_fixed_point g = display->gamma_to_linear; - - red = png_gamma_16bit_correct(red*257, g); - green = png_gamma_16bit_correct(green*257, g); - blue = png_gamma_16bit_correct(blue*257, g); - - if (convert_to_Y || output_encoding == E_LINEAR) - { - alpha *= 257; - encoding = E_LINEAR; - } - - else - { - red = PNG_sRGB_FROM_LINEAR(red * 255); - green = PNG_sRGB_FROM_LINEAR(green * 255); - blue = PNG_sRGB_FROM_LINEAR(blue * 255); - encoding = E_sRGB; - } - } - - else if (encoding == E_LINEAR8) - { - /* This encoding occurs quite frequently in test cases because PngSuite - * includes a gAMA 1.0 chunk with most images. - */ - red *= 257; - green *= 257; - blue *= 257; - alpha *= 257; - encoding = E_LINEAR; - } - - else if (encoding == E_sRGB && (convert_to_Y || output_encoding == E_LINEAR)) - { - /* The values are 8-bit sRGB values, but must be converted to 16-bit - * linear. - */ - red = png_sRGB_table[red]; - green = png_sRGB_table[green]; - blue = png_sRGB_table[blue]; - alpha *= 257; - encoding = E_LINEAR; - } - - /* This is set if the color isn't gray but the output is. */ - if (encoding == E_LINEAR) - { - if (convert_to_Y) - { - /* NOTE: these values are copied from png_do_rgb_to_gray */ - png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green + - (png_uint_32)2366 * blue; - - if (output_encoding == E_LINEAR) - y = (y + 16384) >> 15; - - else - { - /* y is scaled by 32768, we need it scaled by 255: */ - y = (y + 128) >> 8; - y *= 255; - y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7); - encoding = E_sRGB; - } - - blue = red = green = y; - } - - else if (output_encoding == E_sRGB) - { - red = PNG_sRGB_FROM_LINEAR(red * 255); - green = PNG_sRGB_FROM_LINEAR(green * 255); - blue = PNG_sRGB_FROM_LINEAR(blue * 255); - alpha = PNG_DIV257(alpha); - encoding = E_sRGB; - } - } - - if (encoding != output_encoding) - png_error(image->opaque->png_ptr, "bad encoding (internal error)"); - - /* Store the value. */ - { -# ifdef PNG_FORMAT_BGR_SUPPORTED - const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && - (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; -# else -# define afirst 0 -# endif -# ifdef PNG_FORMAT_BGR_SUPPORTED - const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) ? 2 : 0; -# else -# define bgr 0 -# endif - - if (output_encoding == E_LINEAR) - { - png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap); - - entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); - - /* The linear 16-bit values must be pre-multiplied by the alpha channel - * value, if less than 65535 (this is, effectively, composite on black - * if the alpha channel is removed.) - */ - switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) - { - case 4: - entry[afirst ? 0 : 3] = (png_uint_16)alpha; - /* FALL THROUGH */ - - case 3: - if (alpha < 65535) - { - if (alpha > 0) - { - blue = (blue * alpha + 32767U)/65535U; - green = (green * alpha + 32767U)/65535U; - red = (red * alpha + 32767U)/65535U; - } - - else - red = green = blue = 0; - } - entry[afirst + (2 ^ bgr)] = (png_uint_16)blue; - entry[afirst + 1] = (png_uint_16)green; - entry[afirst + bgr] = (png_uint_16)red; - break; - - case 2: - entry[1 ^ afirst] = (png_uint_16)alpha; - /* FALL THROUGH */ - - case 1: - if (alpha < 65535) - { - if (alpha > 0) - green = (green * alpha + 32767U)/65535U; - - else - green = 0; - } - entry[afirst] = (png_uint_16)green; - break; - - default: - break; - } - } - - else /* output encoding is E_sRGB */ - { - png_bytep entry = png_voidcast(png_bytep, display->colormap); - - entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); - - switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) - { - case 4: - entry[afirst ? 0 : 3] = (png_byte)alpha; - case 3: - entry[afirst + (2 ^ bgr)] = (png_byte)blue; - entry[afirst + 1] = (png_byte)green; - entry[afirst + bgr] = (png_byte)red; - break; - - case 2: - entry[1 ^ afirst] = (png_byte)alpha; - case 1: - entry[afirst] = (png_byte)green; - break; - - default: - break; - } - } - -# ifdef afirst -# undef afirst -# endif -# ifdef bgr -# undef bgr -# endif - } -} - -static int -make_gray_file_colormap(png_image_read_control *display) -{ - unsigned int i; - - for (i=0; i<256; ++i) - png_create_colormap_entry(display, i, i, i, i, 255, E_FILE); - - return i; -} - -static int -make_gray_colormap(png_image_read_control *display) -{ - unsigned int i; - - for (i=0; i<256; ++i) - png_create_colormap_entry(display, i, i, i, i, 255, E_sRGB); - - return i; -} -#define PNG_GRAY_COLORMAP_ENTRIES 256 - -static int -make_ga_colormap(png_image_read_control *display) -{ - unsigned int i, a; - - /* Alpha is retained, the output will be a color-map with entries - * selected by six levels of alpha. One transparent entry, 6 gray - * levels for all the intermediate alpha values, leaving 230 entries - * for the opaque grays. The color-map entries are the six values - * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the - * relevant entry. - * - * if (alpha > 229) // opaque - * { - * // The 231 entries are selected to make the math below work: - * base = 0; - * entry = (231 * gray + 128) >> 8; - * } - * else if (alpha < 26) // transparent - * { - * base = 231; - * entry = 0; - * } - * else // partially opaque - * { - * base = 226 + 6 * PNG_DIV51(alpha); - * entry = PNG_DIV51(gray); - * } - */ - i = 0; - while (i < 231) - { - unsigned int gray = (i * 256 + 115) / 231; - png_create_colormap_entry(display, i++, gray, gray, gray, 255, E_sRGB); - } - - /* 255 is used here for the component values for consistency with the code - * that undoes premultiplication in pngwrite.c. - */ - png_create_colormap_entry(display, i++, 255, 255, 255, 0, E_sRGB); - - for (a=1; a<5; ++a) - { - unsigned int g; - - for (g=0; g<6; ++g) - png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51, - E_sRGB); - } - - return i; -} - -#define PNG_GA_COLORMAP_ENTRIES 256 - -static int -make_rgb_colormap(png_image_read_control *display) -{ - unsigned int i, r; - - /* Build a 6x6x6 opaque RGB cube */ - for (i=r=0; r<6; ++r) - { - unsigned int g; - - for (g=0; g<6; ++g) - { - unsigned int b; - - for (b=0; b<6; ++b) - png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255, - E_sRGB); - } - } - - return i; -} - -#define PNG_RGB_COLORMAP_ENTRIES 216 - -/* Return a palette index to the above palette given three 8-bit sRGB values. */ -#define PNG_RGB_INDEX(r,g,b) \ - ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b))) - -static int -png_image_read_colormap(png_voidp argument) -{ - png_image_read_control *display = - png_voidcast(png_image_read_control*, argument); - const png_imagep image = display->image; - - const png_structrp png_ptr = image->opaque->png_ptr; - const png_uint_32 output_format = image->format; - const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) ? - E_LINEAR : E_sRGB; - - unsigned int cmap_entries; - unsigned int output_processing; /* Output processing option */ - unsigned int data_encoding = E_NOTSET; /* Encoding libpng must produce */ - - /* Background information; the background color and the index of this color - * in the color-map if it exists (else 256). - */ - unsigned int background_index = 256; - png_uint_32 back_r, back_g, back_b; - - /* Flags to accumulate things that need to be done to the input. */ - int expand_tRNS = 0; - - /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is - * very difficult to do, the results look awful, and it is difficult to see - * what possible use it is because the application can't control the - * color-map. - */ - if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 || - png_ptr->num_trans > 0) /* alpha in input */ && - ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */) - { - if (output_encoding == E_LINEAR) /* compose on black */ - back_b = back_g = back_r = 0; - - else if (display->background == NULL /* no way to remove it */) - png_error(png_ptr, - "a background color must be supplied to remove alpha/transparency"); - - /* Get a copy of the background color (this avoids repeating the checks - * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the - * output format. - */ - else - { - back_g = display->background->green; - if (output_format & PNG_FORMAT_FLAG_COLOR) - { - back_r = display->background->red; - back_b = display->background->blue; - } - else - back_b = back_r = back_g; - } - } - - else if (output_encoding == E_LINEAR) - back_b = back_r = back_g = 65535; - - else - back_b = back_r = back_g = 255; - - /* Default the input file gamma if required - this is necessary because - * libpng assumes that if no gamma information is present the data is in the - * output format, but the simplified API deduces the gamma from the input - * format. - */ - if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0) - { - /* Do this directly, not using the png_colorspace functions, to ensure - * that it happens even if the colorspace is invalid (though probably if - * it is the setting will be ignored) Note that the same thing can be - * achieved at the application interface with png_set_gAMA. - */ - if (png_ptr->bit_depth == 16 && - (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) - png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR; - - else - png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE; - - png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; - } - - /* Decide what to do based on the PNG color type of the input data. The - * utility function png_create_colormap_entry deals with most aspects of the - * output transformations; this code works out how to produce bytes of - * color-map entries from the original format. - */ - switch (png_ptr->color_type) - { - case PNG_COLOR_TYPE_GRAY: - if (png_ptr->bit_depth <= 8) - { - /* There at most 256 colors in the output, regardless of - * transparency. - */ - unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0; - - cmap_entries = 1U << png_ptr->bit_depth; - if (cmap_entries > image->colormap_entries) - png_error(png_ptr, "gray[8] color-map: too few entries"); - - step = 255 / (cmap_entries - 1); - output_processing = PNG_CMAP_NONE; - - /* If there is a tRNS chunk then this either selects a transparent - * value or, if the output has no alpha, the background color. - */ - if (png_ptr->num_trans > 0) - { - trans = png_ptr->trans_color.gray; - - if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) - back_alpha = output_encoding == E_LINEAR ? 65535 : 255; - } - - /* png_create_colormap_entry just takes an RGBA and writes the - * corresponding color-map entry using the format from 'image', - * including the required conversion to sRGB or linear as - * appropriate. The input values are always either sRGB (if the - * gamma correction flag is 0) or 0..255 scaled file encoded values - * (if the function must gamma correct them). - */ - for (i=val=0; ibit_depth < 8) - png_set_packing(png_ptr); - } - - else /* bit depth is 16 */ - { - /* The 16-bit input values can be converted directly to 8-bit gamma - * encoded values; however, if a tRNS chunk is present 257 color-map - * entries are required. This means that the extra entry requires - * special processing; add an alpha channel, sacrifice gray level - * 254 and convert transparent (alpha==0) entries to that. - * - * Use libpng to chop the data to 8 bits. Convert it to sRGB at the - * same time to minimize quality loss. If a tRNS chunk is present - * this means libpng must handle it too; otherwise it is impossible - * to do the exact match on the 16-bit value. - * - * If the output has no alpha channel *and* the background color is - * gray then it is possible to let libpng handle the substitution by - * ensuring that the corresponding gray level matches the background - * color exactly. - */ - data_encoding = E_sRGB; - - if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) - png_error(png_ptr, "gray[16] color-map: too few entries"); - - cmap_entries = make_gray_colormap(display); - - if (png_ptr->num_trans > 0) - { - unsigned int back_alpha; - - if (output_format & PNG_FORMAT_FLAG_ALPHA) - back_alpha = 0; - - else - { - if (back_r == back_g && back_g == back_b) - { - /* Background is gray; no special processing will be - * required. - */ - png_color_16 c; - png_uint_32 gray = back_g; - - if (output_encoding == E_LINEAR) - { - gray = PNG_sRGB_FROM_LINEAR(gray * 255); - - /* And make sure the corresponding palette entry - * matches. - */ - png_create_colormap_entry(display, gray, back_g, back_g, - back_g, 65535, E_LINEAR); - } - - /* The background passed to libpng, however, must be the - * sRGB value. - */ - c.index = 0; /*unused*/ - c.gray = c.red = c.green = c.blue = (png_uint_16)gray; - - /* NOTE: does this work without expanding tRNS to alpha? - * It should be the color->gray case below apparently - * doesn't. - */ - png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); - - output_processing = PNG_CMAP_NONE; - break; - } - - back_alpha = output_encoding == E_LINEAR ? 65535 : 255; - } - - /* output_processing means that the libpng-processed row will be - * 8-bit GA and it has to be processing to single byte color-map - * values. Entry 254 is replaced by either a completely - * transparent entry or by the background color at full - * precision (and the background color is not a simple gray leve - * in this case.) - */ - expand_tRNS = 1; - output_processing = PNG_CMAP_TRANS; - background_index = 254; - - /* And set (overwrite) color-map entry 254 to the actual - * background color at full precision. - */ - png_create_colormap_entry(display, 254, back_r, back_g, back_b, - back_alpha, output_encoding); - } - - else - output_processing = PNG_CMAP_NONE; - } - break; - - case PNG_COLOR_TYPE_GRAY_ALPHA: - /* 8-bit or 16-bit PNG with two channels - gray and alpha. A minimum - * of 65536 combinations. If, however, the alpha channel is to be - * removed there are only 256 possibilities if the background is gray. - * (Otherwise there is a subset of the 65536 possibilities defined by - * the triangle between black, white and the background color.) - * - * Reduce 16-bit files to 8-bit and sRGB encode the result. No need to - * worry about tRNS matching - tRNS is ignored if there is an alpha - * channel. - */ - data_encoding = E_sRGB; - - if (output_format & PNG_FORMAT_FLAG_ALPHA) - { - if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) - png_error(png_ptr, "gray+alpha color-map: too few entries"); - - cmap_entries = make_ga_colormap(display); - - background_index = PNG_CMAP_GA_BACKGROUND; - output_processing = PNG_CMAP_GA; - } - - else /* alpha is removed */ - { - /* Alpha must be removed as the PNG data is processed when the - * background is a color because the G and A channels are - * independent and the vector addition (non-parallel vectors) is a - * 2-D problem. - * - * This can be reduced to the same algorithm as above by making a - * colormap containing gray levels (for the opaque grays), a - * background entry (for a transparent pixel) and a set of four six - * level color values, one set for each intermediate alpha value. - * See the comments in make_ga_colormap for how this works in the - * per-pixel processing. - * - * If the background is gray, however, we only need a 256 entry gray - * level color map. It is sufficient to make the entry generated - * for the background color be exactly the color specified. - */ - if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 || - (back_r == back_g && back_g == back_b)) - { - /* Background is gray; no special processing will be required. */ - png_color_16 c; - png_uint_32 gray = back_g; - - if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) - png_error(png_ptr, "gray-alpha color-map: too few entries"); - - cmap_entries = make_gray_colormap(display); - - if (output_encoding == E_LINEAR) - { - gray = PNG_sRGB_FROM_LINEAR(gray * 255); - - /* And make sure the corresponding palette entry matches. */ - png_create_colormap_entry(display, gray, back_g, back_g, - back_g, 65535, E_LINEAR); - } - - /* The background passed to libpng, however, must be the sRGB - * value. - */ - c.index = 0; /*unused*/ - c.gray = c.red = c.green = c.blue = (png_uint_16)gray; - - png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); - - output_processing = PNG_CMAP_NONE; - } - - else - { - png_uint_32 i, a; - - /* This is the same as png_make_ga_colormap, above, except that - * the entries are all opaque. - */ - if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) - png_error(png_ptr, "ga-alpha color-map: too few entries"); - - i = 0; - while (i < 231) - { - png_uint_32 gray = (i * 256 + 115) / 231; - png_create_colormap_entry(display, i++, gray, gray, gray, - 255, E_sRGB); - } - - /* NOTE: this preserves the full precision of the application - * background color. - */ - background_index = i; - png_create_colormap_entry(display, i++, back_r, back_g, back_b, - output_encoding == E_LINEAR ? 65535U : 255U, output_encoding); - - /* For non-opaque input composite on the sRGB background - this - * requires inverting the encoding for each component. The input - * is still converted to the sRGB encoding because this is a - * reasonable approximate to the logarithmic curve of human - * visual sensitivity, at least over the narrow range which PNG - * represents. Consequently 'G' is always sRGB encoded, while - * 'A' is linear. We need the linear background colors. - */ - if (output_encoding == E_sRGB) /* else already linear */ - { - /* This may produce a value not exactly matching the - * background, but that's ok because these numbers are only - * used when alpha != 0 - */ - back_r = png_sRGB_table[back_r]; - back_g = png_sRGB_table[back_g]; - back_b = png_sRGB_table[back_b]; - } - - for (a=1; a<5; ++a) - { - unsigned int g; - - /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled - * by an 8-bit alpha value (0..255). - */ - png_uint_32 alpha = 51 * a; - png_uint_32 back_rx = (255-alpha) * back_r; - png_uint_32 back_gx = (255-alpha) * back_g; - png_uint_32 back_bx = (255-alpha) * back_b; - - for (g=0; g<6; ++g) - { - png_uint_32 gray = png_sRGB_table[g*51] * alpha; - - png_create_colormap_entry(display, i++, - PNG_sRGB_FROM_LINEAR(gray + back_rx), - PNG_sRGB_FROM_LINEAR(gray + back_gx), - PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, E_sRGB); - } - } - - cmap_entries = i; - output_processing = PNG_CMAP_GA; - } - } - break; - - case PNG_COLOR_TYPE_RGB: - case PNG_COLOR_TYPE_RGB_ALPHA: - /* Exclude the case where the output is gray; we can always handle this - * with the cases above. - */ - if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0) - { - /* The color-map will be grayscale, so we may as well convert the - * input RGB values to a simple grayscale and use the grayscale - * code above. - * - * NOTE: calling this apparently damages the recognition of the - * transparent color in background color handling; call - * png_set_tRNS_to_alpha before png_set_background_fixed. - */ - png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1, - -1); - data_encoding = E_sRGB; - - /* The output will now be one or two 8-bit gray or gray+alpha - * channels. The more complex case arises when the input has alpha. - */ - if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || - png_ptr->num_trans > 0) && - (output_format & PNG_FORMAT_FLAG_ALPHA) != 0) - { - /* Both input and output have an alpha channel, so no background - * processing is required; just map the GA bytes to the right - * color-map entry. - */ - expand_tRNS = 1; - - if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) - png_error(png_ptr, "rgb[ga] color-map: too few entries"); - - cmap_entries = make_ga_colormap(display); - background_index = PNG_CMAP_GA_BACKGROUND; - output_processing = PNG_CMAP_GA; - } - - else - { - /* Either the input or the output has no alpha channel, so there - * will be no non-opaque pixels in the color-map; it will just be - * grayscale. - */ - if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) - png_error(png_ptr, "rgb[gray] color-map: too few entries"); - - /* Ideally this code would use libpng to do the gamma correction, - * but if an input alpha channel is to be removed we will hit the - * libpng bug in gamma+compose+rgb-to-gray (the double gamma - * correction bug). Fix this by dropping the gamma correction in - * this case and doing it in the palette; this will result in - * duplicate palette entries, but that's better than the - * alternative of double gamma correction. - */ - if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || - png_ptr->num_trans > 0) && - png_gamma_not_sRGB(png_ptr->colorspace.gamma)) - { - cmap_entries = make_gray_file_colormap(display); - data_encoding = E_FILE; - } - - else - cmap_entries = make_gray_colormap(display); - - /* But if the input has alpha or transparency it must be removed - */ - if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || - png_ptr->num_trans > 0) - { - png_color_16 c; - png_uint_32 gray = back_g; - - /* We need to ensure that the application background exists in - * the colormap and that completely transparent pixels map to - * it. Achieve this simply by ensuring that the entry - * selected for the background really is the background color. - */ - if (data_encoding == E_FILE) /* from the fixup above */ - { - /* The app supplied a gray which is in output_encoding, we - * need to convert it to a value of the input (E_FILE) - * encoding then set this palette entry to the required - * output encoding. - */ - if (output_encoding == E_sRGB) - gray = png_sRGB_table[gray]; /* now E_LINEAR */ - - gray = PNG_DIV257(png_gamma_16bit_correct(gray, - png_ptr->colorspace.gamma)); /* now E_FILE */ - - /* And make sure the corresponding palette entry contains - * exactly the required sRGB value. - */ - png_create_colormap_entry(display, gray, back_g, back_g, - back_g, 0/*unused*/, output_encoding); - } - - else if (output_encoding == E_LINEAR) - { - gray = PNG_sRGB_FROM_LINEAR(gray * 255); - - /* And make sure the corresponding palette entry matches. - */ - png_create_colormap_entry(display, gray, back_g, back_g, - back_g, 0/*unused*/, E_LINEAR); - } - - /* The background passed to libpng, however, must be the - * output (normally sRGB) value. - */ - c.index = 0; /*unused*/ - c.gray = c.red = c.green = c.blue = (png_uint_16)gray; - - /* NOTE: the following is apparently a bug in libpng. Without - * it the transparent color recognition in - * png_set_background_fixed seems to go wrong. - */ - expand_tRNS = 1; - png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); - } - - output_processing = PNG_CMAP_NONE; - } - } - - else /* output is color */ - { - /* We could use png_quantize here so long as there is no transparent - * color or alpha; png_quantize ignores alpha. Easier overall just - * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube. - * Consequently we always want libpng to produce sRGB data. - */ - data_encoding = E_sRGB; - - /* Is there any transparency or alpha? */ - if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || - png_ptr->num_trans > 0) - { - /* Is there alpha in the output too? If so all four channels are - * processed into a special RGB cube with alpha support. - */ - if (output_format & PNG_FORMAT_FLAG_ALPHA) - { - png_uint_32 r; - - if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) - png_error(png_ptr, "rgb+alpha color-map: too few entries"); - - cmap_entries = make_rgb_colormap(display); - - /* Add a transparent entry. */ - png_create_colormap_entry(display, cmap_entries, 255, 255, - 255, 0, E_sRGB); - - /* This is stored as the background index for the processing - * algorithm. - */ - background_index = cmap_entries++; - - /* Add 27 r,g,b entries each with alpha 0.5. */ - for (r=0; r<256; r = (r << 1) | 0x7f) - { - png_uint_32 g; - - for (g=0; g<256; g = (g << 1) | 0x7f) - { - png_uint_32 b; - - /* This generates components with the values 0, 127 and - * 255 - */ - for (b=0; b<256; b = (b << 1) | 0x7f) - png_create_colormap_entry(display, cmap_entries++, - r, g, b, 128, E_sRGB); - } - } - - expand_tRNS = 1; - output_processing = PNG_CMAP_RGB_ALPHA; - } - - else - { - /* Alpha/transparency must be removed. The background must - * exist in the color map (achieved by setting adding it after - * the 666 color-map). If the standard processing code will - * pick up this entry automatically that's all that is - * required; libpng can be called to do the background - * processing. - */ - unsigned int sample_size = - PNG_IMAGE_SAMPLE_SIZE(output_format); - png_uint_32 r, g, b; /* sRGB background */ - - if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) - png_error(png_ptr, "rgb-alpha color-map: too few entries"); - - cmap_entries = make_rgb_colormap(display); - - png_create_colormap_entry(display, cmap_entries, back_r, - back_g, back_b, 0/*unused*/, output_encoding); - - if (output_encoding == E_LINEAR) - { - r = PNG_sRGB_FROM_LINEAR(back_r * 255); - g = PNG_sRGB_FROM_LINEAR(back_g * 255); - b = PNG_sRGB_FROM_LINEAR(back_b * 255); - } - - else - { - r = back_r; - g = back_g; - b = back_g; - } - - /* Compare the newly-created color-map entry with the one the - * PNG_CMAP_RGB algorithm will use. If the two entries don't - * match, add the new one and set this as the background - * index. - */ - if (memcmp((png_const_bytep)display->colormap + - sample_size * cmap_entries, - (png_const_bytep)display->colormap + - sample_size * PNG_RGB_INDEX(r,g,b), - sample_size) != 0) - { - /* The background color must be added. */ - background_index = cmap_entries++; - - /* Add 27 r,g,b entries each with created by composing with - * the background at alpha 0.5. - */ - for (r=0; r<256; r = (r << 1) | 0x7f) - { - for (g=0; g<256; g = (g << 1) | 0x7f) - { - /* This generates components with the values 0, 127 - * and 255 - */ - for (b=0; b<256; b = (b << 1) | 0x7f) - png_create_colormap_entry(display, cmap_entries++, - png_colormap_compose(display, r, E_sRGB, 128, - back_r, output_encoding), - png_colormap_compose(display, g, E_sRGB, 128, - back_g, output_encoding), - png_colormap_compose(display, b, E_sRGB, 128, - back_b, output_encoding), - 0/*unused*/, output_encoding); - } - } - - expand_tRNS = 1; - output_processing = PNG_CMAP_RGB_ALPHA; - } - - else /* background color is in the standard color-map */ - { - png_color_16 c; - - c.index = 0; /*unused*/ - c.red = (png_uint_16)back_r; - c.gray = c.green = (png_uint_16)back_g; - c.blue = (png_uint_16)back_b; - - png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); - - output_processing = PNG_CMAP_RGB; - } - } - } - - else /* no alpha or transparency in the input */ - { - /* Alpha in the output is irrelevant, simply map the opaque input - * pixels to the 6x6x6 color-map. - */ - if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries) - png_error(png_ptr, "rgb color-map: too few entries"); - - cmap_entries = make_rgb_colormap(display); - output_processing = PNG_CMAP_RGB; - } - } - break; - - case PNG_COLOR_TYPE_PALETTE: - /* It's already got a color-map. It may be necessary to eliminate the - * tRNS entries though. - */ - { - unsigned int num_trans = png_ptr->num_trans; - png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; - png_const_colorp colormap = png_ptr->palette; - const int do_background = trans != NULL && - (output_format & PNG_FORMAT_FLAG_ALPHA) == 0; - unsigned int i; - - /* Just in case: */ - if (trans == NULL) - num_trans = 0; - - output_processing = PNG_CMAP_NONE; - data_encoding = E_FILE; /* Don't change from color-map indicies */ - cmap_entries = png_ptr->num_palette; - if (cmap_entries > 256) - cmap_entries = 256; - - if (cmap_entries > image->colormap_entries) - png_error(png_ptr, "palette color-map: too few entries"); - - for (i=0; i < cmap_entries; ++i) - { - if (do_background && i < num_trans && trans[i] < 255) - { - if (trans[i] == 0) - png_create_colormap_entry(display, i, back_r, back_g, - back_b, 0, output_encoding); - - else - { - /* Must compose the PNG file color in the color-map entry - * on the sRGB color in 'back'. - */ - png_create_colormap_entry(display, i, - png_colormap_compose(display, colormap[i].red, E_FILE, - trans[i], back_r, output_encoding), - png_colormap_compose(display, colormap[i].green, E_FILE, - trans[i], back_g, output_encoding), - png_colormap_compose(display, colormap[i].blue, E_FILE, - trans[i], back_b, output_encoding), - output_encoding == E_LINEAR ? trans[i] * 257U : - trans[i], - output_encoding); - } - } - - else - png_create_colormap_entry(display, i, colormap[i].red, - colormap[i].green, colormap[i].blue, - i < num_trans ? trans[i] : 255U, E_FILE/*8-bit*/); - } - - /* The PNG data may have indicies packed in fewer than 8 bits, it - * must be expanded if so. - */ - if (png_ptr->bit_depth < 8) - png_set_packing(png_ptr); - } - break; - - default: - png_error(png_ptr, "invalid PNG color type"); - /*NOT REACHED*/ - break; - } - - /* Now deal with the output processing */ - if (expand_tRNS && png_ptr->num_trans > 0 && - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0) - png_set_tRNS_to_alpha(png_ptr); - - switch (data_encoding) - { - default: - png_error(png_ptr, "bad data option (internal error)"); - break; - - case E_sRGB: - /* Change to 8-bit sRGB */ - png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); - /* FALL THROUGH */ - - case E_FILE: - if (png_ptr->bit_depth > 8) - png_set_scale_16(png_ptr); - break; - } - - if (cmap_entries > 256 || cmap_entries > image->colormap_entries) - png_error(png_ptr, "color map overflow (BAD internal error)"); - - image->colormap_entries = cmap_entries; - - /* Double check using the recorded background index */ - switch (output_processing) - { - case PNG_CMAP_NONE: - if (background_index != PNG_CMAP_NONE_BACKGROUND) - goto bad_background; - break; - - case PNG_CMAP_GA: - if (background_index != PNG_CMAP_GA_BACKGROUND) - goto bad_background; - break; - - case PNG_CMAP_TRANS: - if (background_index >= cmap_entries || - background_index != PNG_CMAP_TRANS_BACKGROUND) - goto bad_background; - break; - - case PNG_CMAP_RGB: - if (background_index != PNG_CMAP_RGB_BACKGROUND) - goto bad_background; - break; - - case PNG_CMAP_RGB_ALPHA: - if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND) - goto bad_background; - break; - - default: - png_error(png_ptr, "bad processing option (internal error)"); - - bad_background: - png_error(png_ptr, "bad background index (internal error)"); - } - - display->colormap_processing = output_processing; - - return 1/*ok*/; -} - -/* The final part of the color-map read called from png_image_finish_read. */ -static int -png_image_read_and_map(png_voidp argument) -{ - png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; - int passes; - - /* Called when the libpng data must be transformed into the color-mapped - * form. There is a local row buffer in display->local and this routine must - * do the interlace handling. - */ - switch (png_ptr->interlaced) - { - case PNG_INTERLACE_NONE: - passes = 1; - break; - - case PNG_INTERLACE_ADAM7: - passes = PNG_INTERLACE_ADAM7_PASSES; - break; - - default: - passes = 0; - png_error(png_ptr, "unknown interlace type"); - } - - { - png_uint_32 height = image->height; - png_uint_32 width = image->width; - int proc = display->colormap_processing; - png_bytep first_row = png_voidcast(png_bytep, display->first_row); - ptrdiff_t step_row = display->row_bytes; - int pass; - - for (pass = 0; pass < passes; ++pass) - { - unsigned int startx, stepx, stepy; - png_uint_32 y; - - if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) - { - /* The row may be empty for a short image: */ - if (PNG_PASS_COLS(width, pass) == 0) - continue; - - startx = PNG_PASS_START_COL(pass); - stepx = PNG_PASS_COL_OFFSET(pass); - y = PNG_PASS_START_ROW(pass); - stepy = PNG_PASS_ROW_OFFSET(pass); - } - - else - { - y = 0; - startx = 0; - stepx = stepy = 1; - } - - for (; ylocal_row); - png_bytep outrow = first_row + y * step_row; - png_const_bytep end_row = outrow + width; - - /* Read read the libpng data into the temporary buffer. */ - png_read_row(png_ptr, inrow, NULL); - - /* Now process the row according to the processing option, note - * that the caller verifies that the format of the libpng output - * data is as required. - */ - outrow += startx; - switch (proc) - { - case PNG_CMAP_GA: - for (; outrow < end_row; outrow += stepx) - { - /* The data is always in the PNG order */ - unsigned int gray = *inrow++; - unsigned int alpha = *inrow++; - unsigned int entry; - - /* NOTE: this code is copied as a comment in - * make_ga_colormap above. Please update the - * comment if you change this code! - */ - if (alpha > 229) /* opaque */ - { - entry = (231 * gray + 128) >> 8; - } - else if (alpha < 26) /* transparent */ - { - entry = 231; - } - else /* partially opaque */ - { - entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray); - } - - *outrow = (png_byte)entry; - } - break; - - case PNG_CMAP_TRANS: - for (; outrow < end_row; outrow += stepx) - { - png_byte gray = *inrow++; - png_byte alpha = *inrow++; - - if (alpha == 0) - *outrow = PNG_CMAP_TRANS_BACKGROUND; - - else if (gray != PNG_CMAP_TRANS_BACKGROUND) - *outrow = gray; - - else - *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1); - } - break; - - case PNG_CMAP_RGB: - for (; outrow < end_row; outrow += stepx) - { - *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]); - inrow += 3; - } - break; - - case PNG_CMAP_RGB_ALPHA: - for (; outrow < end_row; outrow += stepx) - { - unsigned int alpha = inrow[3]; - - /* Because the alpha entries only hold alpha==0.5 values - * split the processing at alpha==0.25 (64) and 0.75 - * (196). - */ - - if (alpha >= 196) - *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], - inrow[2]); - - else if (alpha < 64) - *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND; - - else - { - /* Likewise there are three entries for each of r, g - * and b. We could select the entry by popcount on - * the top two bits on those architectures that - * support it, this is what the code below does, - * crudely. - */ - unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1; - - /* Here are how the values map: - * - * 0x00 .. 0x3f -> 0 - * 0x40 .. 0xbf -> 1 - * 0xc0 .. 0xff -> 2 - * - * So, as above with the explicit alpha checks, the - * breakpoints are at 64 and 196. - */ - if (inrow[0] & 0x80) back_i += 9; /* red */ - if (inrow[0] & 0x40) back_i += 9; - if (inrow[0] & 0x80) back_i += 3; /* green */ - if (inrow[0] & 0x40) back_i += 3; - if (inrow[0] & 0x80) back_i += 1; /* blue */ - if (inrow[0] & 0x40) back_i += 1; - - *outrow = (png_byte)back_i; - } - - inrow += 4; - } - break; - - default: - break; - } - } - } - } - - return 1; -} - -static int -png_image_read_colormapped(png_voidp argument) -{ - png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); - png_imagep image = display->image; - png_controlp control = image->opaque; - png_structrp png_ptr = control->png_ptr; - png_inforp info_ptr = control->info_ptr; - - int passes = 0; /* As a flag */ - - PNG_SKIP_CHUNKS(png_ptr); - - /* Update the 'info' structure and make sure the result is as required; first - * make sure to turn on the interlace handling if it will be required - * (because it can't be turned on *after* the call to png_read_update_info!) - */ - if (display->colormap_processing == PNG_CMAP_NONE) - passes = png_set_interlace_handling(png_ptr); - - png_read_update_info(png_ptr, info_ptr); - - /* The expected output can be deduced from the colormap_processing option. */ - switch (display->colormap_processing) - { - case PNG_CMAP_NONE: - /* Output must be one channel and one byte per pixel, the output - * encoding can be anything. - */ - if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE || - info_ptr->color_type == PNG_COLOR_TYPE_GRAY) && - info_ptr->bit_depth == 8) - break; - - goto bad_output; - - case PNG_CMAP_TRANS: - case PNG_CMAP_GA: - /* Output must be two channels and the 'G' one must be sRGB, the latter - * can be checked with an exact number because it should have been set - * to this number above! - */ - if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - info_ptr->bit_depth == 8 && - png_ptr->screen_gamma == PNG_GAMMA_sRGB && - image->colormap_entries == 256) - break; - - goto bad_output; - - case PNG_CMAP_RGB: - /* Output must be 8-bit sRGB encoded RGB */ - if (info_ptr->color_type == PNG_COLOR_TYPE_RGB && - info_ptr->bit_depth == 8 && - png_ptr->screen_gamma == PNG_GAMMA_sRGB && - image->colormap_entries == 216) - break; - - goto bad_output; - - case PNG_CMAP_RGB_ALPHA: - /* Output must be 8-bit sRGB encoded RGBA */ - if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA && - info_ptr->bit_depth == 8 && - png_ptr->screen_gamma == PNG_GAMMA_sRGB && - image->colormap_entries == 244 /* 216 + 1 + 27 */) - break; - - /* goto bad_output; */ - /* FALL THROUGH */ - - default: - bad_output: - png_error(png_ptr, "bad color-map processing (internal error)"); - } - - /* Now read the rows. Do this here if it is possible to read directly into - * the output buffer, otherwise allocate a local row buffer of the maximum - * size libpng requires and call the relevant processing routine safely. - */ - { - png_voidp first_row = display->buffer; - ptrdiff_t row_bytes = display->row_stride; - - /* The following expression is designed to work correctly whether it gives - * a signed or an unsigned result. - */ - if (row_bytes < 0) - { - char *ptr = png_voidcast(char*, first_row); - ptr += (image->height-1) * (-row_bytes); - first_row = png_voidcast(png_voidp, ptr); - } - - display->first_row = first_row; - display->row_bytes = row_bytes; - } - - if (passes == 0) - { - int result; - png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); - - display->local_row = row; - result = png_safe_execute(image, png_image_read_and_map, display); - display->local_row = NULL; - png_free(png_ptr, row); - - return result; - } - - else - { - png_alloc_size_t row_bytes = display->row_bytes; - - while (--passes >= 0) - { - png_uint_32 y = image->height; - png_bytep row = png_voidcast(png_bytep, display->first_row); - - while (y-- > 0) - { - png_read_row(png_ptr, row, NULL); - row += row_bytes; - } - } - - return 1; - } -} - -/* Just the row reading part of png_image_read. */ -static int -png_image_read_composite(png_voidp argument) -{ - png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; - int passes; - - switch (png_ptr->interlaced) - { - case PNG_INTERLACE_NONE: - passes = 1; - break; - - case PNG_INTERLACE_ADAM7: - passes = PNG_INTERLACE_ADAM7_PASSES; - break; - - default: - passes = 0; - png_error(png_ptr, "unknown interlace type"); - } - - { - png_uint_32 height = image->height; - png_uint_32 width = image->width; - ptrdiff_t step_row = display->row_bytes; - unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; - int pass; - - for (pass = 0; pass < passes; ++pass) - { - unsigned int startx, stepx, stepy; - png_uint_32 y; - - if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) - { - /* The row may be empty for a short image: */ - if (PNG_PASS_COLS(width, pass) == 0) - continue; - - startx = PNG_PASS_START_COL(pass) * channels; - stepx = PNG_PASS_COL_OFFSET(pass) * channels; - y = PNG_PASS_START_ROW(pass); - stepy = PNG_PASS_ROW_OFFSET(pass); - } - - else - { - y = 0; - startx = 0; - stepx = channels; - stepy = 1; - } - - for (; ylocal_row); - png_bytep outrow; - png_const_bytep end_row; - - /* Read the row, which is packed: */ - png_read_row(png_ptr, inrow, NULL); - - outrow = png_voidcast(png_bytep, display->first_row); - outrow += y * step_row; - end_row = outrow + width * channels; - - /* Now do the composition on each pixel in this row. */ - outrow += startx; - for (; outrow < end_row; outrow += stepx) - { - png_byte alpha = inrow[channels]; - - if (alpha > 0) /* else no change to the output */ - { - unsigned int c; - - for (c=0; cimage; - png_structrp png_ptr = image->opaque->png_ptr; - png_inforp info_ptr = image->opaque->info_ptr; - png_uint_32 height = image->height; - png_uint_32 width = image->width; - int pass, passes; - - /* Double check the convoluted logic below. We expect to get here with - * libpng doing rgb to gray and gamma correction but background processing - * left to the png_image_read_background function. The rows libpng produce - * might be 8 or 16-bit but should always have two channels; gray plus alpha. - */ - if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) - png_error(png_ptr, "lost rgb to gray"); - - if ((png_ptr->transformations & PNG_COMPOSE) != 0) - png_error(png_ptr, "unexpected compose"); - - if (png_get_channels(png_ptr, info_ptr) != 2) - png_error(png_ptr, "lost/gained channels"); - - /* Expect the 8-bit case to always remove the alpha channel */ - if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 && - (image->format & PNG_FORMAT_FLAG_ALPHA) != 0) - png_error(png_ptr, "unexpected 8-bit transformation"); - - switch (png_ptr->interlaced) - { - case PNG_INTERLACE_NONE: - passes = 1; - break; - - case PNG_INTERLACE_ADAM7: - passes = PNG_INTERLACE_ADAM7_PASSES; - break; - - default: - passes = 0; - png_error(png_ptr, "unknown interlace type"); - } - - switch (png_get_bit_depth(png_ptr, info_ptr)) - { - default: - png_error(png_ptr, "unexpected bit depth"); - break; - - case 8: - /* 8-bit sRGB gray values with an alpha channel; the alpha channel is - * to be removed by composing on a background: either the row if - * display->background is NULL or display->background->green if not. - * Unlike the code above ALPHA_OPTIMIZED has *not* been done. - */ - { - png_bytep first_row = png_voidcast(png_bytep, display->first_row); - ptrdiff_t step_row = display->row_bytes; - - for (pass = 0; pass < passes; ++pass) - { - png_bytep row = png_voidcast(png_bytep, - display->first_row); - unsigned int startx, stepx, stepy; - png_uint_32 y; - - if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) - { - /* The row may be empty for a short image: */ - if (PNG_PASS_COLS(width, pass) == 0) - continue; - - startx = PNG_PASS_START_COL(pass); - stepx = PNG_PASS_COL_OFFSET(pass); - y = PNG_PASS_START_ROW(pass); - stepy = PNG_PASS_ROW_OFFSET(pass); - } - - else - { - y = 0; - startx = 0; - stepx = stepy = 1; - } - - if (display->background == NULL) - { - for (; ylocal_row); - png_bytep outrow = first_row + y * step_row; - png_const_bytep end_row = outrow + width; - - /* Read the row, which is packed: */ - png_read_row(png_ptr, inrow, NULL); - - /* Now do the composition on each pixel in this row. */ - outrow += startx; - for (; outrow < end_row; outrow += stepx) - { - png_byte alpha = inrow[1]; - - if (alpha > 0) /* else no change to the output */ - { - png_uint_32 component = inrow[0]; - - if (alpha < 255) /* else just use component */ - { - /* Since PNG_OPTIMIZED_ALPHA was not set it is - * necessary to invert the sRGB transfer - * function and multiply the alpha out. - */ - component = png_sRGB_table[component] * alpha; - component += png_sRGB_table[outrow[0]] * - (255-alpha); - component = PNG_sRGB_FROM_LINEAR(component); - } - - outrow[0] = (png_byte)component; - } - - inrow += 2; /* gray and alpha channel */ - } - } - } - - else /* constant background value */ - { - png_byte background8 = display->background->green; - png_uint_16 background = png_sRGB_table[background8]; - - for (; ylocal_row); - png_bytep outrow = first_row + y * step_row; - png_const_bytep end_row = outrow + width; - - /* Read the row, which is packed: */ - png_read_row(png_ptr, inrow, NULL); - - /* Now do the composition on each pixel in this row. */ - outrow += startx; - for (; outrow < end_row; outrow += stepx) - { - png_byte alpha = inrow[1]; - - if (alpha > 0) /* else use background */ - { - png_uint_32 component = inrow[0]; - - if (alpha < 255) /* else just use component */ - { - component = png_sRGB_table[component] * alpha; - component += background * (255-alpha); - component = PNG_sRGB_FROM_LINEAR(component); - } - - outrow[0] = (png_byte)component; - } - - else - outrow[0] = background8; - - inrow += 2; /* gray and alpha channel */ - } - - row += display->row_bytes; - } - } - } - } - break; - - case 16: - /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must - * still be done and, maybe, the alpha channel removed. This code also - * handles the alpha-first option. - */ - { - png_uint_16p first_row = png_voidcast(png_uint_16p, - display->first_row); - /* The division by two is safe because the caller passed in a - * stride which was multiplied by 2 (below) to get row_bytes. - */ - ptrdiff_t step_row = display->row_bytes / 2; - int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; - unsigned int outchannels = 1+preserve_alpha; - int swap_alpha = 0; - - if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST)) - swap_alpha = 1; - - for (pass = 0; pass < passes; ++pass) - { - unsigned int startx, stepx, stepy; - png_uint_32 y; - - /* The 'x' start and step are adjusted to output components here. - */ - if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) - { - /* The row may be empty for a short image: */ - if (PNG_PASS_COLS(width, pass) == 0) - continue; - - startx = PNG_PASS_START_COL(pass) * outchannels; - stepx = PNG_PASS_COL_OFFSET(pass) * outchannels; - y = PNG_PASS_START_ROW(pass); - stepy = PNG_PASS_ROW_OFFSET(pass); - } - - else - { - y = 0; - startx = 0; - stepx = outchannels; - stepy = 1; - } - - for (; ylocal_row), NULL); - inrow = png_voidcast(png_const_uint_16p, display->local_row); - - /* Now do the pre-multiplication on each pixel in this row. - */ - outrow += startx; - for (; outrow < end_row; outrow += stepx) - { - png_uint_32 component = inrow[0]; - png_uint_16 alpha = inrow[1]; - - if (alpha > 0) /* else 0 */ - { - if (alpha < 65535) /* else just use component */ - { - component *= alpha; - component += 32767; - component /= 65535; - } - } - - else - component = 0; - - outrow[swap_alpha] = (png_uint_16)component; - if (preserve_alpha) - outrow[1 ^ swap_alpha] = alpha; - - inrow += 2; /* components and alpha channel */ - } - } - } - } - break; - } - - return 1; -} - -/* The guts of png_image_finish_read as a png_safe_execute callback. */ -static int -png_image_read_direct(png_voidp argument) -{ - png_image_read_control *display = png_voidcast(png_image_read_control*, - argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; - png_inforp info_ptr = image->opaque->info_ptr; - - png_uint_32 format = image->format; - int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; - int do_local_compose = 0; - int do_local_background = 0; /* to avoid double gamma correction bug */ - int passes = 0; - - /* Add transforms to ensure the correct output format is produced then check - * that the required implementation support is there. Always expand; always - * need 8 bits minimum, no palette and expanded tRNS. - */ - png_set_expand(png_ptr); - - /* Now check the format to see if it was modified. */ - { - png_uint_32 base_format = png_image_format(png_ptr) & - ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */; - png_uint_32 change = format ^ base_format; - png_fixed_point output_gamma; - int mode; /* alpha mode */ - - /* Do this first so that we have a record if rgb to gray is happening. */ - if (change & PNG_FORMAT_FLAG_COLOR) - { - /* gray<->color transformation required. */ - if (format & PNG_FORMAT_FLAG_COLOR) - png_set_gray_to_rgb(png_ptr); - - else - { - /* libpng can't do both rgb to gray and - * background/pre-multiplication if there is also significant gamma - * correction, because both operations require linear colors and - * the code only supports one transform doing the gamma correction. - * Handle this by doing the pre-multiplication or background - * operation in this code, if necessary. - * - * TODO: fix this by rewriting pngrtran.c (!) - * - * For the moment (given that fixing this in pngrtran.c is an - * enormous change) 'do_local_background' is used to indicate that - * the problem exists. - */ - if (base_format & PNG_FORMAT_FLAG_ALPHA) - do_local_background = 1/*maybe*/; - - png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, - PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); - } - - change &= ~PNG_FORMAT_FLAG_COLOR; - } - - /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise. - */ - { - png_fixed_point input_gamma_default; - - if ((base_format & PNG_FORMAT_FLAG_LINEAR) && - (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) - input_gamma_default = PNG_GAMMA_LINEAR; - else - input_gamma_default = PNG_DEFAULT_sRGB; - - /* Call png_set_alpha_mode to set the default for the input gamma; the - * output gamma is set by a second call below. - */ - png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default); - } - - if (linear) - { - /* If there *is* an alpha channel in the input it must be multiplied - * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG. - */ - if (base_format & PNG_FORMAT_FLAG_ALPHA) - mode = PNG_ALPHA_STANDARD; /* associated alpha */ - - else - mode = PNG_ALPHA_PNG; - - output_gamma = PNG_GAMMA_LINEAR; - } - - else - { - mode = PNG_ALPHA_PNG; - output_gamma = PNG_DEFAULT_sRGB; - } - - /* If 'do_local_background' is set check for the presence of gamma - * correction; this is part of the work-round for the libpng bug - * described above. - * - * TODO: fix libpng and remove this. - */ - if (do_local_background) - { - png_fixed_point gtest; - - /* This is 'png_gamma_threshold' from pngrtran.c; the test used for - * gamma correction, the screen gamma hasn't been set on png_struct - * yet; it's set below. png_struct::gamma, however, is set to the - * final value. - */ - if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma, - PNG_FP_1) && !png_gamma_significant(gtest)) - do_local_background = 0; - - else if (mode == PNG_ALPHA_STANDARD) - { - do_local_background = 2/*required*/; - mode = PNG_ALPHA_PNG; /* prevent libpng doing it */ - } - - /* else leave as 1 for the checks below */ - } - - /* If the bit-depth changes then handle that here. */ - if (change & PNG_FORMAT_FLAG_LINEAR) - { - if (linear /*16-bit output*/) - png_set_expand_16(png_ptr); - - else /* 8-bit output */ - png_set_scale_16(png_ptr); - - change &= ~PNG_FORMAT_FLAG_LINEAR; - } - - /* Now the background/alpha channel changes. */ - if (change & PNG_FORMAT_FLAG_ALPHA) - { - /* Removing an alpha channel requires composition for the 8-bit - * formats; for the 16-bit it is already done, above, by the - * pre-multiplication and the channel just needs to be stripped. - */ - if (base_format & PNG_FORMAT_FLAG_ALPHA) - { - /* If RGB->gray is happening the alpha channel must be left and the - * operation completed locally. - * - * TODO: fix libpng and remove this. - */ - if (do_local_background) - do_local_background = 2/*required*/; - - /* 16-bit output: just remove the channel */ - else if (linear) /* compose on black (well, pre-multiply) */ - png_set_strip_alpha(png_ptr); - - /* 8-bit output: do an appropriate compose */ - else if (display->background != NULL) - { - png_color_16 c; - - c.index = 0; /*unused*/ - c.red = display->background->red; - c.green = display->background->green; - c.blue = display->background->blue; - c.gray = display->background->green; - - /* This is always an 8-bit sRGB value, using the 'green' channel - * for gray is much better than calculating the luminance here; - * we can get off-by-one errors in that calculation relative to - * the app expectations and that will show up in transparent - * pixels. - */ - png_set_background_fixed(png_ptr, &c, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, - 0/*gamma: not used*/); - } - - else /* compose on row: implemented below. */ - { - do_local_compose = 1; - /* This leaves the alpha channel in the output, so it has to be - * removed by the code below. Set the encoding to the 'OPTIMIZE' - * one so the code only has to hack on the pixels that require - * composition. - */ - mode = PNG_ALPHA_OPTIMIZED; - } - } - - else /* output needs an alpha channel */ - { - /* This is tricky because it happens before the swap operation has - * been accomplished; however, the swap does *not* swap the added - * alpha channel (weird API), so it must be added in the correct - * place. - */ - png_uint_32 filler; /* opaque filler */ - int where; - - if (linear) - filler = 65535; - - else - filler = 255; - -# ifdef PNG_FORMAT_AFIRST_SUPPORTED - if (format & PNG_FORMAT_FLAG_AFIRST) - { - where = PNG_FILLER_BEFORE; - change &= ~PNG_FORMAT_FLAG_AFIRST; - } - - else -# endif - where = PNG_FILLER_AFTER; - - png_set_add_alpha(png_ptr, filler, where); - } - - /* This stops the (irrelevant) call to swap_alpha below. */ - change &= ~PNG_FORMAT_FLAG_ALPHA; - } - - /* Now set the alpha mode correctly; this is always done, even if there is - * no alpha channel in either the input or the output because it correctly - * sets the output gamma. - */ - png_set_alpha_mode_fixed(png_ptr, mode, output_gamma); - -# ifdef PNG_FORMAT_BGR_SUPPORTED - if (change & PNG_FORMAT_FLAG_BGR) - { - /* Check only the output format; PNG is never BGR; don't do this if - * the output is gray, but fix up the 'format' value in that case. - */ - if (format & PNG_FORMAT_FLAG_COLOR) - png_set_bgr(png_ptr); - - else - format &= ~PNG_FORMAT_FLAG_BGR; - - change &= ~PNG_FORMAT_FLAG_BGR; - } -# endif - -# ifdef PNG_FORMAT_AFIRST_SUPPORTED - if (change & PNG_FORMAT_FLAG_AFIRST) - { - /* Only relevant if there is an alpha channel - it's particularly - * important to handle this correctly because do_local_compose may - * be set above and then libpng will keep the alpha channel for this - * code to remove. - */ - if (format & PNG_FORMAT_FLAG_ALPHA) - { - /* Disable this if doing a local background, - * TODO: remove this when local background is no longer required. - */ - if (do_local_background != 2) - png_set_swap_alpha(png_ptr); - } - - else - format &= ~PNG_FORMAT_FLAG_AFIRST; - - change &= ~PNG_FORMAT_FLAG_AFIRST; - } -# endif - - /* If the *output* is 16-bit then we need to check for a byte-swap on this - * architecture. - */ - if (linear) - { - PNG_CONST png_uint_16 le = 0x0001; - - if (*(png_const_bytep)&le) - png_set_swap(png_ptr); - } - - /* If change is not now 0 some transformation is missing - error out. */ - if (change) - png_error(png_ptr, "png_read_image: unsupported transformation"); - } - - PNG_SKIP_CHUNKS(png_ptr); - - /* Update the 'info' structure and make sure the result is as required; first - * make sure to turn on the interlace handling if it will be required - * (because it can't be turned on *after* the call to png_read_update_info!) - * - * TODO: remove the do_local_background fixup below. - */ - if (!do_local_compose && do_local_background != 2) - passes = png_set_interlace_handling(png_ptr); - - png_read_update_info(png_ptr, info_ptr); - - { - png_uint_32 info_format = 0; - - if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) - info_format |= PNG_FORMAT_FLAG_COLOR; - - if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - { - /* do_local_compose removes this channel below. */ - if (!do_local_compose) - { - /* do_local_background does the same if required. */ - if (do_local_background != 2 || - (format & PNG_FORMAT_FLAG_ALPHA) != 0) - info_format |= PNG_FORMAT_FLAG_ALPHA; - } - } - - else if (do_local_compose) /* internal error */ - png_error(png_ptr, "png_image_read: alpha channel lost"); - - if (info_ptr->bit_depth == 16) - info_format |= PNG_FORMAT_FLAG_LINEAR; - -# ifdef PNG_FORMAT_BGR_SUPPORTED - if (png_ptr->transformations & PNG_BGR) - info_format |= PNG_FORMAT_FLAG_BGR; -# endif - -# ifdef PNG_FORMAT_AFIRST_SUPPORTED - if (do_local_background == 2) - { - if (format & PNG_FORMAT_FLAG_AFIRST) - info_format |= PNG_FORMAT_FLAG_AFIRST; - } - - if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 || - ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 && - (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0)) - { - if (do_local_background == 2) - png_error(png_ptr, "unexpected alpha swap transformation"); - - info_format |= PNG_FORMAT_FLAG_AFIRST; - } -# endif - - /* This is actually an internal error. */ - if (info_format != format) - png_error(png_ptr, "png_read_image: invalid transformations"); - } - - /* Now read the rows. If do_local_compose is set then it is necessary to use - * a local row buffer. The output will be GA, RGBA or BGRA and must be - * converted to G, RGB or BGR as appropriate. The 'local_row' member of the - * display acts as a flag. - */ - { - png_voidp first_row = display->buffer; - ptrdiff_t row_bytes = display->row_stride; - - if (linear) - row_bytes *= 2; - - /* The following expression is designed to work correctly whether it gives - * a signed or an unsigned result. - */ - if (row_bytes < 0) - { - char *ptr = png_voidcast(char*, first_row); - ptr += (image->height-1) * (-row_bytes); - first_row = png_voidcast(png_voidp, ptr); - } - - display->first_row = first_row; - display->row_bytes = row_bytes; - } - - if (do_local_compose) - { - int result; - png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); - - display->local_row = row; - result = png_safe_execute(image, png_image_read_composite, display); - display->local_row = NULL; - png_free(png_ptr, row); - - return result; - } - - else if (do_local_background == 2) - { - int result; - png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); - - display->local_row = row; - result = png_safe_execute(image, png_image_read_background, display); - display->local_row = NULL; - png_free(png_ptr, row); - - return result; - } - - else - { - png_alloc_size_t row_bytes = display->row_bytes; - - while (--passes >= 0) - { - png_uint_32 y = image->height; - png_bytep row = png_voidcast(png_bytep, display->first_row); - - while (y-- > 0) - { - png_read_row(png_ptr, row, NULL); - row += row_bytes; - } - } - - return 1; - } -} - -int PNGAPI -png_image_finish_read(png_imagep image, png_const_colorp background, - void *buffer, png_int_32 row_stride, void *colormap) -{ - if (image != NULL && image->version == PNG_IMAGE_VERSION) - { - png_uint_32 check; - - if (row_stride == 0) - row_stride = PNG_IMAGE_ROW_STRIDE(*image); - - if (row_stride < 0) - check = -row_stride; - - else - check = row_stride; - - if (image->opaque != NULL && buffer != NULL && - check >= PNG_IMAGE_ROW_STRIDE(*image)) - { - if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || - (image->colormap_entries > 0 && colormap != NULL)) - { - int result; - png_image_read_control display; - - memset(&display, 0, (sizeof display)); - display.image = image; - display.buffer = buffer; - display.row_stride = row_stride; - display.colormap = colormap; - display.background = background; - display.local_row = NULL; - - /* Choose the correct 'end' routine; for the color-map case all the - * setup has already been done. - */ - if (image->format & PNG_FORMAT_FLAG_COLORMAP) - result = - png_safe_execute(image, png_image_read_colormap, &display) && - png_safe_execute(image, png_image_read_colormapped, &display); - - else - result = - png_safe_execute(image, png_image_read_direct, &display); - - png_image_free(image); - return result; - } - - else - return png_image_error(image, - "png_image_finish_read[color-map]: no color-map"); - } - - else - return png_image_error(image, - "png_image_finish_read: invalid argument"); - } - - else if (image != NULL) - return png_image_error(image, - "png_image_finish_read: damaged PNG_IMAGE_VERSION"); - - return 0; -} - -#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED */ + +/* pngread.c - read a PNG file + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#include "pngpriv.h" +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) +# include +#endif + +#ifdef PNG_READ_SUPPORTED + +/* Create a PNG structure for reading, and allocate any memory needed. */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) +{ +#ifndef PNG_USER_MEM_SUPPORTED + png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + error_fn, warn_fn, NULL, NULL, NULL); +#else + return png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL); +} + +/* Alternate create PNG structure for reading, and allocate any memory + * needed. + */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +{ + png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr != NULL) + { + png_ptr->mode = PNG_IS_READ_STRUCT; + + /* Added in libpng-1.6.0; this can be used to detect a read structure if + * required (it will be zero in a write structure.) + */ +# ifdef PNG_SEQUENTIAL_READ_SUPPORTED + png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE; +# endif + +# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + + /* In stable builds only warn if an application error can be completely + * handled. + */ +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC + png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; +# endif +# endif + + /* TODO: delay this, it can be done in png_init_io (if the app doesn't + * do it itself) avoiding setting the default function if it is not + * required. + */ + png_set_read_fn(png_ptr, NULL, NULL); + } + + return png_ptr; +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structrp png_ptr, png_inforp info_ptr) +{ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int keep; +#endif + + png_debug(1, "in png_read_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Read and check the PNG file signature. */ + png_read_sig(png_ptr, info_ptr); + + for (;;) + { + png_uint_32 length = png_read_chunk_header(png_ptr); + png_uint_32 chunk_name = png_ptr->chunk_name; + + /* IDAT logic needs to happen here to simplify getting the two flags + * right. + */ + if (chunk_name == png_IDAT) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_chunk_error(png_ptr, "Missing PLTE before IDAT"); + + else if (png_ptr->mode & PNG_AFTER_IDAT) + png_chunk_benign_error(png_ptr, "Too many IDATs found[s]"); + + png_ptr->mode |= PNG_HAVE_IDAT; + } + + else if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (chunk_name == png_IHDR) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (chunk_name == png_IEND) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) + { + png_handle_unknown(png_ptr, info_ptr, length, keep); + + if (chunk_name == png_PLTE) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (chunk_name == png_IDAT) + { + png_ptr->idat_size = 0; /* It has been consumed */ + break; + } + } +#endif + else if (chunk_name == png_PLTE) + png_handle_PLTE(png_ptr, info_ptr, length); + + else if (chunk_name == png_IDAT) + { + png_ptr->idat_size = length; + break; + } + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (chunk_name == png_bKGD) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (chunk_name == png_cHRM) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (chunk_name == png_gAMA) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (chunk_name == png_hIST) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (chunk_name == png_oFFs) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (chunk_name == png_pCAL) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (chunk_name == png_sCAL) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (chunk_name == png_pHYs) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (chunk_name == png_sBIT) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (chunk_name == png_sRGB) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (chunk_name == png_iCCP) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (chunk_name == png_sPLT) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (chunk_name == png_tEXt) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (chunk_name == png_tIME) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (chunk_name == png_tRNS) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (chunk_name == png_zTXt) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (chunk_name == png_iTXt) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + + else + png_handle_unknown(png_ptr, info_ptr, length, + PNG_HANDLE_CHUNK_AS_DEFAULT); + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) +{ + png_debug(1, "in png_read_update_info"); + + if (png_ptr != NULL) + { + if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) + { + png_read_start_row(png_ptr); + +# ifdef PNG_READ_TRANSFORMS_SUPPORTED + png_read_transform_info(png_ptr, info_ptr); +# else + PNG_UNUSED(info_ptr) +# endif + } + + /* New in 1.6.0 this avoids the bug of doing the initializations twice */ + else + png_app_error(png_ptr, + "png_read_update_info/png_start_read_image: duplicate call"); + } +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structrp png_ptr) +{ + png_debug(1, "in png_start_read_image"); + + if (png_ptr != NULL) + { + if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) + png_read_start_row(png_ptr); + + /* New in 1.6.0 this avoids the bug of doing the initializations twice */ + else + png_app_error(png_ptr, + "png_start_read_image/png_read_update_info: duplicate call"); + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing, + * NOTE: this is apparently only supported in the 'sequential' reader. + */ +static void +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel"); + + if ( + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff); + *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (s0 + s1 + 65536) & 0xffff; + png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ + +void PNGAPI +png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) +{ + png_row_info row_info; + + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_read_row (row %lu, pass %d)", + (unsigned long)png_ptr->row_number, png_ptr->pass); + + /* png_read_start_row sets the information (in particular iwidth) for this + * interlace pass. + */ + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + + /* 1.5.6: row_info moved out of png_struct to a local here. */ + row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ + row_info.color_type = png_ptr->color_type; + row_info.bit_depth = png_ptr->bit_depth; + row_info.channels = png_ptr->channels; + row_info.pixel_depth = png_ptr->pixel_depth; + row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); + + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); +#endif + } + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* If interlaced and we do not need a new row, combine row and return. + * Notice that the pixels we have from previous rows have been transformed + * already; we can only combine like with like (transformed or + * untransformed) and, because of the libpng API for interlaced images, this + * means we must transform before de-interlacing. + */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + png_read_finish_row(png_ptr); + return; + } + break; + + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + default: + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + /* Fill the row with IDAT data: */ + png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1); + + if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) + { + if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) + png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, + png_ptr->prev_row + 1, png_ptr->row_buf[0]); + else + png_error(png_ptr, "bad adaptive filter value"); + } + + /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before + * 1.5.6, while the buffer really is this big in current versions of libpng + * it may not be in the future, so this was changed just to copy the + * interlaced count: + */ + memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1); + } +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + if (png_ptr->transformations) + png_do_read_transformations(png_ptr, &row_info); +#endif + + /* The transformed pixel depth should match the depth now in row_info. */ + if (png_ptr->transformed_pixel_depth == 0) + { + png_ptr->transformed_pixel_depth = row_info.pixel_depth; + if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) + png_error(png_ptr, "sequential row overflow"); + } + + else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) + png_error(png_ptr, "internal sequential row size calculation error"); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) + png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, + png_ptr->transformations); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + if (row != NULL) + png_combine_row(png_ptr, row, 0/*row*/); + } + + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, -1/*ignored*/); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, -1/*ignored*/); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); + +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ + +void PNGAPI +png_read_rows(png_structrp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows"); + + if (png_ptr == NULL) + return; + + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + + else if (rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, NULL); + rp++; + } + + else if (dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, NULL, dptr); + dp++; + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ +void PNGAPI +png_read_image(png_structrp png_ptr, png_bytepp image) +{ + png_uint_32 i, image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + pass = png_set_interlace_handling(png_ptr); + /* And make sure transforms are initialized. */ + png_start_read_image(png_ptr); + } + else + { + if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) + { + /* Caller called png_start_read_image or png_read_update_info without + * first turning on the PNG_INTERLACE transform. We can fix this here, + * but the caller should do it! + */ + png_warning(png_ptr, "Interlace handling should be turned on when " + "using png_read_image"); + /* Make sure this is set correctly */ + png_ptr->num_rows = png_ptr->height; + } + + /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in + * the above error case. + */ + pass = png_set_interlace_handling(png_ptr); + } +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled"); + + pass = 1; +#endif + + image_height=png_ptr->height; + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, NULL); + rp++; + } + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structrp png_ptr, png_inforp info_ptr) +{ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int keep; +#endif + + png_debug(1, "in png_read_end"); + + if (png_ptr == NULL) + return; + + /* If png_read_end is called in the middle of reading the rows there may + * still be pending IDAT data and an owned zstream. Deal with this here. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (!png_chunk_unknown_handling(png_ptr, png_IDAT)) +#endif + png_read_finish_IDAT(png_ptr); + +#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED + /* Report invalid palette index; added at libng-1.5.10 */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + png_ptr->num_palette_max > png_ptr->num_palette) + png_benign_error(png_ptr, "Read palette index exceeding num_palette"); +#endif + + do + { + png_uint_32 length = png_read_chunk_header(png_ptr); + png_uint_32 chunk_name = png_ptr->chunk_name; + + if (chunk_name == png_IEND) + png_handle_IEND(png_ptr, info_ptr, length); + + else if (chunk_name == png_IHDR) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (info_ptr == NULL) + png_crc_finish(png_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) + { + if (chunk_name == png_IDAT) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found(a1)"); + } + png_handle_unknown(png_ptr, info_ptr, length, keep); + if (chunk_name == png_PLTE) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + + else if (chunk_name == png_IDAT) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found(a2)"); + + png_crc_finish(png_ptr, length); + } + else if (chunk_name == png_PLTE) + png_handle_PLTE(png_ptr, info_ptr, length); + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (chunk_name == png_bKGD) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (chunk_name == png_cHRM) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (chunk_name == png_gAMA) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (chunk_name == png_hIST) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (chunk_name == png_oFFs) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (chunk_name == png_pCAL) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (chunk_name == png_sCAL) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (chunk_name == png_pHYs) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (chunk_name == png_sBIT) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (chunk_name == png_sRGB) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (chunk_name == png_iCCP) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (chunk_name == png_sPLT) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (chunk_name == png_tEXt) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (chunk_name == png_tIME) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (chunk_name == png_tRNS) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (chunk_name == png_zTXt) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (chunk_name == png_iTXt) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + + else + png_handle_unknown(png_ptr, info_ptr, length, + PNG_HANDLE_CHUNK_AS_DEFAULT); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Free all memory used in the read struct */ +static void +png_read_destroy(png_structrp png_ptr) +{ + png_debug(1, "in png_read_destroy"); + +#ifdef PNG_READ_GAMMA_SUPPORTED + png_destroy_gamma_table(png_ptr); +#endif + + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->big_prev_row); + png_free(png_ptr, png_ptr->read_buffer); + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->quantize_index); +#endif + + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; + +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#endif + + inflateEnd(&png_ptr->zstream); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) && \ + defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + png_free(png_ptr, png_ptr->unknown_chunk.data); +#endif + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + png_free(png_ptr, png_ptr->chunk_list); +#endif + + /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error + * callbacks are still set at this point. They are required to complete the + * destruction of the png_struct itself. + */ +} + +/* Free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structrp png_ptr = NULL; + + png_debug(1, "in png_destroy_read_struct"); + + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + + if (png_ptr == NULL) + return; + + /* libpng 1.6.0: use the API to destroy info structs to ensure consistent + * behavior. Prior to 1.6.0 libpng did extra 'info' destruction in this API. + * The extra was, apparently, unnecessary yet this hides memory leak bugs. + */ + png_destroy_info_struct(png_ptr, end_info_ptr_ptr); + png_destroy_info_struct(png_ptr, info_ptr_ptr); + + *png_ptr_ptr = NULL; + png_read_destroy(png_ptr); + png_destroy_png_struct(png_ptr); +} + +void PNGAPI +png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->read_row_fn = read_row_fn; +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_read_png(png_structrp png_ptr, png_inforp info_ptr, + int transforms, + voidp params) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep))) + png_error(png_ptr, "Image is too high to process with png_read_png()"); + + /* -------------- image transformations start here ------------------- */ + /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM + * is not implemented. This will only happen in de-configured (non-default) + * libpng builds. The results can be unexpected - png_read_png may return + * short or mal-formed rows because the transform is skipped. + */ + + /* Tell libpng to strip 16-bit/color files down to 8 bits per color. + */ + if (transforms & PNG_TRANSFORM_SCALE_16) + /* Added at libpng-1.5.4. "strip_16" produces the same result that it + * did in earlier versions, while "scale_16" is now more accurate. + */ +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + png_set_scale_16(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported"); +#endif + + /* If both SCALE and STRIP are required pngrtran will effectively cancel the + * latter by doing SCALE first. This is ok and allows apps not to check for + * which is supported to get the right answer. + */ + if (transforms & PNG_TRANSFORM_STRIP_16) +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + png_set_strip_16(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported"); +#endif + + /* Strip alpha bytes from the input data without combining with + * the background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + png_set_strip_alpha(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported"); +#endif + + /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) +#ifdef PNG_READ_PACK_SUPPORTED + png_set_packing(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported"); +#endif + + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + if (transforms & PNG_TRANSFORM_PACKSWAP) +#ifdef PNG_READ_PACKSWAP_SUPPORTED + png_set_packswap(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported"); +#endif + + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) +#ifdef PNG_READ_EXPAND_SUPPORTED + png_set_expand(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported"); +#endif + + /* We don't handle background color or gamma transformation or quantizing. + */ + + /* Invert monochrome files to have 0 as white and 1 as black + */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) +#ifdef PNG_READ_INVERT_SUPPORTED + png_set_invert_mono(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported"); +#endif + + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if (transforms & PNG_TRANSFORM_SHIFT) +#ifdef PNG_READ_SHIFT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sBIT) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported"); +#endif + + /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ + if (transforms & PNG_TRANSFORM_BGR) +#ifdef PNG_READ_BGR_SUPPORTED + png_set_bgr(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported"); +#endif + + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + png_set_swap_alpha(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported"); +#endif + + /* Swap bytes of 16-bit files to least significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) +#ifdef PNG_READ_SWAP_SUPPORTED + png_set_swap(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported"); +#endif + +/* Added at libpng-1.2.41 */ + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + png_set_invert_alpha(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported"); +#endif + +/* Added at libpng-1.2.41 */ + /* Expand grayscale image to RGB */ + if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + png_set_gray_to_rgb(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported"); +#endif + +/* Added at libpng-1.5.4 */ + if (transforms & PNG_TRANSFORM_EXPAND_16) +#ifdef PNG_READ_EXPAND_16_SUPPORTED + png_set_expand_16(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported"); +#endif + + /* We don't handle adding filler bytes */ + + /* We use png_read_image and rely on that for interlace handling, but we also + * call png_read_update_info therefore must turn on interlace handling now: + */ + (void)png_set_interlace_handling(png_ptr); + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + if (info_ptr->row_pointers == NULL) + { + png_uint_32 iptr; + + info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr, + info_ptr->height * (sizeof (png_bytep)))); + + for (iptr=0; iptrheight; iptr++) + info_ptr->row_pointers[iptr] = NULL; + + info_ptr->free_me |= PNG_FREE_ROWS; + + for (iptr = 0; iptr < info_ptr->height; iptr++) + info_ptr->row_pointers[iptr] = png_voidcast(png_bytep, + png_malloc(png_ptr, info_ptr->rowbytes)); + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + PNG_UNUSED(params) +} +#endif /* PNG_INFO_IMAGE_SUPPORTED */ +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* SIMPLIFIED READ + * + * This code currently relies on the sequential reader, though it could easily + * be made to work with the progressive one. + */ +/* Arguments to png_image_finish_read: */ + +/* Encoding of PNG data (used by the color-map code) */ +# define P_NOTSET 0 /* File encoding not yet known */ +# define P_sRGB 1 /* 8-bit encoded to sRGB gamma */ +# define P_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */ +# define P_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */ +# define P_LINEAR8 4 /* 8-bit linear: only from a file value */ + +/* Color-map processing: after libpng has run on the PNG image further + * processing may be needed to conver the data to color-map indicies. + */ +#define PNG_CMAP_NONE 0 +#define PNG_CMAP_GA 1 /* Process GA data to a color-map with alpha */ +#define PNG_CMAP_TRANS 2 /* Process GA data to a background index */ +#define PNG_CMAP_RGB 3 /* Process RGB data */ +#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */ + +/* The following document where the background is for each processing case. */ +#define PNG_CMAP_NONE_BACKGROUND 256 +#define PNG_CMAP_GA_BACKGROUND 231 +#define PNG_CMAP_TRANS_BACKGROUND 254 +#define PNG_CMAP_RGB_BACKGROUND 256 +#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216 + +typedef struct +{ + /* Arguments: */ + png_imagep image; + png_voidp buffer; + png_int_32 row_stride; + png_voidp colormap; + png_const_colorp background; + /* Local variables: */ + png_voidp local_row; + png_voidp first_row; + ptrdiff_t row_bytes; /* step between rows */ + int file_encoding; /* E_ values above */ + png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */ + int colormap_processing; /* PNG_CMAP_ values above */ +} png_image_read_control; + +/* Do all the *safe* initialization - 'safe' means that png_error won't be + * called, so setting up the jmp_buf is not required. This means that anything + * called from here must *not* call png_malloc - it has to call png_malloc_warn + * instead so that control is returned safely back to this routine. + */ +static int +png_image_read_init(png_imagep image) +{ + if (image->opaque == NULL) + { + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image, + png_safe_error, png_safe_warning); + + /* And set the rest of the structure to NULL to ensure that the various + * fields are consistent. + */ + memset(image, 0, (sizeof *image)); + image->version = PNG_IMAGE_VERSION; + + if (png_ptr != NULL) + { + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (info_ptr != NULL) + { + png_controlp control = png_voidcast(png_controlp, + png_malloc_warn(png_ptr, (sizeof *control))); + + if (control != NULL) + { + memset(control, 0, (sizeof *control)); + + control->png_ptr = png_ptr; + control->info_ptr = info_ptr; + control->for_write = 0; + + image->opaque = control; + return 1; + } + + /* Error clean up */ + png_destroy_info_struct(png_ptr, &info_ptr); + } + + png_destroy_read_struct(&png_ptr, NULL, NULL); + } + + return png_image_error(image, "png_image_read: out of memory"); + } + + return png_image_error(image, "png_image_read: opaque pointer not NULL"); +} + +/* Utility to find the base format of a PNG file from a png_struct. */ +static png_uint_32 +png_image_format(png_structrp png_ptr) +{ + png_uint_32 format = 0; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + format |= PNG_FORMAT_FLAG_COLOR; + + if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) + format |= PNG_FORMAT_FLAG_ALPHA; + + /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS + * sets the png_struct fields; that's all we are interested in here. The + * precise interaction with an app call to png_set_tRNS and PNG file reading + * is unclear. + */ + else if (png_ptr->num_trans > 0) + format |= PNG_FORMAT_FLAG_ALPHA; + + if (png_ptr->bit_depth == 16) + format |= PNG_FORMAT_FLAG_LINEAR; + + if (png_ptr->color_type & PNG_COLOR_MASK_PALETTE) + format |= PNG_FORMAT_FLAG_COLORMAP; + + return format; +} + +/* Is the given gamma significantly different from sRGB? The test is the same + * one used in pngrtran.c when deciding whether to do gamma correction. The + * arithmetic optimizes the division by using the fact that the inverse of the + * file sRGB gamma is 2.2 + */ +static int +png_gamma_not_sRGB(png_fixed_point g) +{ + if (g < PNG_FP_1) + { + /* An uninitialized gamma is assumed to be sRGB for the simplified API. */ + if (g == 0) + return 0; + + return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */); + } + + return 1; +} + +/* Do the main body of a 'png_image_begin_read' function; read the PNG file + * header and fill in all the information. This is executed in a safe context, + * unlike the init routine above. + */ +static int +png_image_read_header(png_voidp argument) +{ + png_imagep image = png_voidcast(png_imagep, argument); + png_structrp png_ptr = image->opaque->png_ptr; + png_inforp info_ptr = image->opaque->info_ptr; + + png_set_benign_errors(png_ptr, 1/*warn*/); + png_read_info(png_ptr, info_ptr); + + /* Do this the fast way; just read directly out of png_struct. */ + image->width = png_ptr->width; + image->height = png_ptr->height; + + { + png_uint_32 format = png_image_format(png_ptr); + + image->format = format; + +#ifdef PNG_COLORSPACE_SUPPORTED + /* Does the colorspace match sRGB? If there is no color endpoint + * (colorant) information assume yes, otherwise require the + * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set. If the + * colorspace has been determined to be invalid ignore it. + */ + if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags + & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB| + PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS)) + image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB; +#endif + } + + /* We need the maximum number of entries regardless of the format the + * application sets here. + */ + { + png_uint_32 cmap_entries; + + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_GRAY: + cmap_entries = 1U << png_ptr->bit_depth; + break; + + case PNG_COLOR_TYPE_PALETTE: + cmap_entries = png_ptr->num_palette; + break; + + default: + cmap_entries = 256; + break; + } + + if (cmap_entries > 256) + cmap_entries = 256; + + image->colormap_entries = cmap_entries; + } + + return 1; +} + +#ifdef PNG_STDIO_SUPPORTED +int PNGAPI +png_image_begin_read_from_stdio(png_imagep image, FILE* file) +{ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (file != NULL) + { + if (png_image_read_init(image)) + { + /* This is slightly evil, but png_init_io doesn't do anything other + * than this and we haven't changed the standard IO functions so + * this saves a 'safe' function. + */ + image->opaque->png_ptr->io_ptr = file; + return png_safe_execute(image, png_image_read_header, image); + } + } + + else + return png_image_error(image, + "png_image_begin_read_from_stdio: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION"); + + return 0; +} + +int PNGAPI +png_image_begin_read_from_file(png_imagep image, const char *file_name) +{ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (file_name != NULL) + { + FILE *fp = fopen(file_name, "rb"); + + if (fp != NULL) + { + if (png_image_read_init(image)) + { + image->opaque->png_ptr->io_ptr = fp; + image->opaque->owned_file = 1; + return png_safe_execute(image, png_image_read_header, image); + } + + /* Clean up: just the opened file. */ + (void)fclose(fp); + } + + else + return png_image_error(image, strerror(errno)); + } + + else + return png_image_error(image, + "png_image_begin_read_from_file: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION"); + + return 0; +} +#endif /* PNG_STDIO_SUPPORTED */ + +static void PNGCBAPI +png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) +{ + if (png_ptr != NULL) + { + png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr); + if (image != NULL) + { + png_controlp cp = image->opaque; + if (cp != NULL) + { + png_const_bytep memory = cp->memory; + png_size_t size = cp->size; + + if (memory != NULL && size >= need) + { + memcpy(out, memory, need); + cp->memory = memory + need; + cp->size = size - need; + return; + } + + png_error(png_ptr, "read beyond end of data"); + } + } + + png_error(png_ptr, "invalid memory read"); + } +} + +int PNGAPI png_image_begin_read_from_memory(png_imagep image, + png_const_voidp memory, png_size_t size) +{ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (memory != NULL && size > 0) + { + if (png_image_read_init(image)) + { + /* Now set the IO functions to read from the memory buffer and + * store it into io_ptr. Again do this in-place to avoid calling a + * libpng function that requires error handling. + */ + image->opaque->memory = png_voidcast(png_const_bytep, memory); + image->opaque->size = size; + image->opaque->png_ptr->io_ptr = image; + image->opaque->png_ptr->read_data_fn = png_image_memory_read; + + return png_safe_execute(image, png_image_read_header, image); + } + } + + else + return png_image_error(image, + "png_image_begin_read_from_memory: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION"); + + return 0; +} + +/* Utility function to skip chunks that are not used by the simplified image + * read functions and an appropriate macro to call it. + */ +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +static void +png_image_skip_unused_chunks(png_structrp png_ptr) +{ + /* Prepare the reader to ignore all recognized chunks whose data will not + * be used, i.e., all chunks recognized by libpng except for those + * involved in basic image reading: + * + * IHDR, PLTE, IDAT, IEND + * + * Or image data handling: + * + * tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT. + * + * This provides a small performance improvement and eliminates any + * potential vulnerability to security problems in the unused chunks. + * + * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored + * too. This allows the simplified API to be compiled without iCCP support, + * however if the support is there the chunk is still checked to detect + * errors (which are unfortunately quite common.) + */ + { + static PNG_CONST png_byte chunks_to_process[] = { + 98, 75, 71, 68, '\0', /* bKGD */ + 99, 72, 82, 77, '\0', /* cHRM */ + 103, 65, 77, 65, '\0', /* gAMA */ +# ifdef PNG_READ_iCCP_SUPPORTED + 105, 67, 67, 80, '\0', /* iCCP */ +# endif + 115, 66, 73, 84, '\0', /* sBIT */ + 115, 82, 71, 66, '\0', /* sRGB */ + }; + + /* Ignore unknown chunks and all other chunks except for the + * IHDR, PLTE, tRNS, IDAT, and IEND chunks. + */ + png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER, + NULL, -1); + + /* But do not ignore image data handling chunks */ + png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT, + chunks_to_process, (sizeof chunks_to_process)/5); + } +} + +# define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p) +#else +# define PNG_SKIP_CHUNKS(p) ((void)0) +#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ + +/* The following macro gives the exact rounded answer for all values in the + * range 0..255 (it actually divides by 51.2, but the rounding still generates + * the correct numbers 0..5 + */ +#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8) + +/* Utility functions to make particular color-maps */ +static void +set_file_encoding(png_image_read_control *display) +{ + png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma; + if (png_gamma_significant(g)) + { + if (png_gamma_not_sRGB(g)) + { + display->file_encoding = P_FILE; + display->gamma_to_linear = png_reciprocal(g); + } + + else + display->file_encoding = P_sRGB; + } + + else + display->file_encoding = P_LINEAR8; +} + +static unsigned int +decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) +{ + if (encoding == P_FILE) /* double check */ + encoding = display->file_encoding; + + if (encoding == P_NOTSET) /* must be the file encoding */ + { + set_file_encoding(display); + encoding = display->file_encoding; + } + + switch (encoding) + { + case P_FILE: + value = png_gamma_16bit_correct(value*257, display->gamma_to_linear); + break; + + case P_sRGB: + value = png_sRGB_table[value]; + break; + + case P_LINEAR: + break; + + case P_LINEAR8: + value *= 257; + break; + + default: + png_error(display->image->opaque->png_ptr, + "unexpected encoding (internal error)"); + break; + } + + return value; +} + +static png_uint_32 +png_colormap_compose(png_image_read_control *display, + png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, + png_uint_32 background, int encoding) +{ + /* The file value is composed on the background, the background has the given + * encoding and so does the result, the file is encoded with P_FILE and the + * file and alpha are 8-bit values. The (output) encoding will always be + * P_LINEAR or P_sRGB. + */ + png_uint_32 f = decode_gamma(display, foreground, foreground_encoding); + png_uint_32 b = decode_gamma(display, background, encoding); + + /* The alpha is always an 8-bit value (it comes from the palette), the value + * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires. + */ + f = f * alpha + b * (255-alpha); + + if (encoding == P_LINEAR) + { + /* Scale to 65535; divide by 255, approximately (in fact this is extremely + * accurate, it divides by 255.00000005937181414556, with no overflow.) + */ + f *= 257; /* Now scaled by 65535 */ + f += f >> 16; + f = (f+32768) >> 16; + } + + else /* P_sRGB */ + f = PNG_sRGB_FROM_LINEAR(f); + + return f; +} + +/* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must + * be 8-bit. + */ +static void +png_create_colormap_entry(png_image_read_control *display, + png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, + png_uint_32 alpha, int encoding) +{ + png_imagep image = display->image; + const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) ? + P_LINEAR : P_sRGB; + const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && + (red != green || green != blue); + + if (ip > 255) + png_error(image->opaque->png_ptr, "color-map index out of range"); + + /* Update the cache with whether the file gamma is significantly different + * from sRGB. + */ + if (encoding == P_FILE) + { + if (display->file_encoding == P_NOTSET) + set_file_encoding(display); + + /* Note that the cached value may be P_FILE too, but if it is then the + * gamma_to_linear member has been set. + */ + encoding = display->file_encoding; + } + + if (encoding == P_FILE) + { + png_fixed_point g = display->gamma_to_linear; + + red = png_gamma_16bit_correct(red*257, g); + green = png_gamma_16bit_correct(green*257, g); + blue = png_gamma_16bit_correct(blue*257, g); + + if (convert_to_Y || output_encoding == P_LINEAR) + { + alpha *= 257; + encoding = P_LINEAR; + } + + else + { + red = PNG_sRGB_FROM_LINEAR(red * 255); + green = PNG_sRGB_FROM_LINEAR(green * 255); + blue = PNG_sRGB_FROM_LINEAR(blue * 255); + encoding = P_sRGB; + } + } + + else if (encoding == P_LINEAR8) + { + /* This encoding occurs quite frequently in test cases because PngSuite + * includes a gAMA 1.0 chunk with most images. + */ + red *= 257; + green *= 257; + blue *= 257; + alpha *= 257; + encoding = P_LINEAR; + } + + else if (encoding == P_sRGB && (convert_to_Y || output_encoding == P_LINEAR)) + { + /* The values are 8-bit sRGB values, but must be converted to 16-bit + * linear. + */ + red = png_sRGB_table[red]; + green = png_sRGB_table[green]; + blue = png_sRGB_table[blue]; + alpha *= 257; + encoding = P_LINEAR; + } + + /* This is set if the color isn't gray but the output is. */ + if (encoding == P_LINEAR) + { + if (convert_to_Y != 0) + { + /* NOTE: these values are copied from png_do_rgb_to_gray */ + png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green + + (png_uint_32)2366 * blue; + + if (output_encoding == P_LINEAR) + y = (y + 16384) >> 15; + + else + { + /* y is scaled by 32768, we need it scaled by 255: */ + y = (y + 128) >> 8; + y *= 255; + y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7); + encoding = P_sRGB; + } + + blue = red = green = y; + } + + else if (output_encoding == P_sRGB) + { + red = PNG_sRGB_FROM_LINEAR(red * 255); + green = PNG_sRGB_FROM_LINEAR(green * 255); + blue = PNG_sRGB_FROM_LINEAR(blue * 255); + alpha = PNG_DIV257(alpha); + encoding = P_sRGB; + } + } + + if (encoding != output_encoding) + png_error(image->opaque->png_ptr, "bad encoding (internal error)"); + + /* Store the value. */ + { +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && + (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; +# else +# define afirst 0 +# endif +# ifdef PNG_FORMAT_BGR_SUPPORTED + const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) ? 2 : 0; +# else +# define bgr 0 +# endif + + if (output_encoding == P_LINEAR) + { + png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap); + + entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); + + /* The linear 16-bit values must be pre-multiplied by the alpha channel + * value, if less than 65535 (this is, effectively, composite on black + * if the alpha channel is removed.) + */ + switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) + { + case 4: + entry[afirst ? 0 : 3] = (png_uint_16)alpha; + /* FALL THROUGH */ + + case 3: + if (alpha < 65535) + { + if (alpha > 0) + { + blue = (blue * alpha + 32767U)/65535U; + green = (green * alpha + 32767U)/65535U; + red = (red * alpha + 32767U)/65535U; + } + + else + red = green = blue = 0; + } + entry[afirst + (2 ^ bgr)] = (png_uint_16)blue; + entry[afirst + 1] = (png_uint_16)green; + entry[afirst + bgr] = (png_uint_16)red; + break; + + case 2: + entry[1 ^ afirst] = (png_uint_16)alpha; + /* FALL THROUGH */ + + case 1: + if (alpha < 65535) + { + if (alpha > 0) + green = (green * alpha + 32767U)/65535U; + + else + green = 0; + } + entry[afirst] = (png_uint_16)green; + break; + + default: + break; + } + } + + else /* output encoding is P_sRGB */ + { + png_bytep entry = png_voidcast(png_bytep, display->colormap); + + entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); + + switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) + { + case 4: + entry[afirst ? 0 : 3] = (png_byte)alpha; + case 3: + entry[afirst + (2 ^ bgr)] = (png_byte)blue; + entry[afirst + 1] = (png_byte)green; + entry[afirst + bgr] = (png_byte)red; + break; + + case 2: + entry[1 ^ afirst] = (png_byte)alpha; + case 1: + entry[afirst] = (png_byte)green; + break; + + default: + break; + } + } + +# ifdef afirst +# undef afirst +# endif +# ifdef bgr +# undef bgr +# endif + } +} + +static int +make_gray_file_colormap(png_image_read_control *display) +{ + unsigned int i; + + for (i=0; i<256; ++i) + png_create_colormap_entry(display, i, i, i, i, 255, P_FILE); + + return i; +} + +static int +make_gray_colormap(png_image_read_control *display) +{ + unsigned int i; + + for (i=0; i<256; ++i) + png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB); + + return i; +} +#define PNG_GRAY_COLORMAP_ENTRIES 256 + +static int +make_ga_colormap(png_image_read_control *display) +{ + unsigned int i, a; + + /* Alpha is retained, the output will be a color-map with entries + * selected by six levels of alpha. One transparent entry, 6 gray + * levels for all the intermediate alpha values, leaving 230 entries + * for the opaque grays. The color-map entries are the six values + * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the + * relevant entry. + * + * if (alpha > 229) // opaque + * { + * // The 231 entries are selected to make the math below work: + * base = 0; + * entry = (231 * gray + 128) >> 8; + * } + * else if (alpha < 26) // transparent + * { + * base = 231; + * entry = 0; + * } + * else // partially opaque + * { + * base = 226 + 6 * PNG_DIV51(alpha); + * entry = PNG_DIV51(gray); + * } + */ + i = 0; + while (i < 231) + { + unsigned int gray = (i * 256 + 115) / 231; + png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB); + } + + /* 255 is used here for the component values for consistency with the code + * that undoes premultiplication in pngwrite.c. + */ + png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB); + + for (a=1; a<5; ++a) + { + unsigned int g; + + for (g=0; g<6; ++g) + png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51, + P_sRGB); + } + + return i; +} + +#define PNG_GA_COLORMAP_ENTRIES 256 + +static int +make_rgb_colormap(png_image_read_control *display) +{ + unsigned int i, r; + + /* Build a 6x6x6 opaque RGB cube */ + for (i=r=0; r<6; ++r) + { + unsigned int g; + + for (g=0; g<6; ++g) + { + unsigned int b; + + for (b=0; b<6; ++b) + png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255, + P_sRGB); + } + } + + return i; +} + +#define PNG_RGB_COLORMAP_ENTRIES 216 + +/* Return a palette index to the above palette given three 8-bit sRGB values. */ +#define PNG_RGB_INDEX(r,g,b) \ + ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b))) + +static int +png_image_read_colormap(png_voidp argument) +{ + png_image_read_control *display = + png_voidcast(png_image_read_control*, argument); + const png_imagep image = display->image; + + const png_structrp png_ptr = image->opaque->png_ptr; + const png_uint_32 output_format = image->format; + const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) ? + P_LINEAR : P_sRGB; + + unsigned int cmap_entries; + unsigned int output_processing; /* Output processing option */ + unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */ + + /* Background information; the background color and the index of this color + * in the color-map if it exists (else 256). + */ + unsigned int background_index = 256; + png_uint_32 back_r, back_g, back_b; + + /* Flags to accumulate things that need to be done to the input. */ + int expand_tRNS = 0; + + /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is + * very difficult to do, the results look awful, and it is difficult to see + * what possible use it is because the application can't control the + * color-map. + */ + if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 || + png_ptr->num_trans > 0) /* alpha in input */ && + ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */) + { + if (output_encoding == P_LINEAR) /* compose on black */ + back_b = back_g = back_r = 0; + + else if (display->background == NULL /* no way to remove it */) + png_error(png_ptr, + "a background color must be supplied to remove alpha/transparency"); + + /* Get a copy of the background color (this avoids repeating the checks + * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the + * output format. + */ + else + { + back_g = display->background->green; + if (output_format & PNG_FORMAT_FLAG_COLOR) + { + back_r = display->background->red; + back_b = display->background->blue; + } + else + back_b = back_r = back_g; + } + } + + else if (output_encoding == P_LINEAR) + back_b = back_r = back_g = 65535; + + else + back_b = back_r = back_g = 255; + + /* Default the input file gamma if required - this is necessary because + * libpng assumes that if no gamma information is present the data is in the + * output format, but the simplified API deduces the gamma from the input + * format. + */ + if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0) + { + /* Do this directly, not using the png_colorspace functions, to ensure + * that it happens even if the colorspace is invalid (though probably if + * it is the setting will be ignored) Note that the same thing can be + * achieved at the application interface with png_set_gAMA. + */ + if (png_ptr->bit_depth == 16 && + (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) + png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR; + + else + png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE; + + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; + } + + /* Decide what to do based on the PNG color type of the input data. The + * utility function png_create_colormap_entry deals with most aspects of the + * output transformations; this code works out how to produce bytes of + * color-map entries from the original format. + */ + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_GRAY: + if (png_ptr->bit_depth <= 8) + { + /* There at most 256 colors in the output, regardless of + * transparency. + */ + unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0; + + cmap_entries = 1U << png_ptr->bit_depth; + if (cmap_entries > image->colormap_entries) + png_error(png_ptr, "gray[8] color-map: too few entries"); + + step = 255 / (cmap_entries - 1); + output_processing = PNG_CMAP_NONE; + + /* If there is a tRNS chunk then this either selects a transparent + * value or, if the output has no alpha, the background color. + */ + if (png_ptr->num_trans > 0) + { + trans = png_ptr->trans_color.gray; + + if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) + back_alpha = output_encoding == P_LINEAR ? 65535 : 255; + } + + /* png_create_colormap_entry just takes an RGBA and writes the + * corresponding color-map entry using the format from 'image', + * including the required conversion to sRGB or linear as + * appropriate. The input values are always either sRGB (if the + * gamma correction flag is 0) or 0..255 scaled file encoded values + * (if the function must gamma correct them). + */ + for (i=val=0; ibit_depth < 8) + png_set_packing(png_ptr); + } + + else /* bit depth is 16 */ + { + /* The 16-bit input values can be converted directly to 8-bit gamma + * encoded values; however, if a tRNS chunk is present 257 color-map + * entries are required. This means that the extra entry requires + * special processing; add an alpha channel, sacrifice gray level + * 254 and convert transparent (alpha==0) entries to that. + * + * Use libpng to chop the data to 8 bits. Convert it to sRGB at the + * same time to minimize quality loss. If a tRNS chunk is present + * this means libpng must handle it too; otherwise it is impossible + * to do the exact match on the 16-bit value. + * + * If the output has no alpha channel *and* the background color is + * gray then it is possible to let libpng handle the substitution by + * ensuring that the corresponding gray level matches the background + * color exactly. + */ + data_encoding = P_sRGB; + + if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "gray[16] color-map: too few entries"); + + cmap_entries = make_gray_colormap(display); + + if (png_ptr->num_trans > 0) + { + unsigned int back_alpha; + + if (output_format & PNG_FORMAT_FLAG_ALPHA) + back_alpha = 0; + + else + { + if (back_r == back_g && back_g == back_b) + { + /* Background is gray; no special processing will be + * required. + */ + png_color_16 c; + png_uint_32 gray = back_g; + + if (output_encoding == P_LINEAR) + { + gray = PNG_sRGB_FROM_LINEAR(gray * 255); + + /* And make sure the corresponding palette entry + * matches. + */ + png_create_colormap_entry(display, gray, back_g, back_g, + back_g, 65535, P_LINEAR); + } + + /* The background passed to libpng, however, must be the + * sRGB value. + */ + c.index = 0; /*unused*/ + c.gray = c.red = c.green = c.blue = (png_uint_16)gray; + + /* NOTE: does this work without expanding tRNS to alpha? + * It should be the color->gray case below apparently + * doesn't. + */ + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + + output_processing = PNG_CMAP_NONE; + break; + } + + back_alpha = output_encoding == P_LINEAR ? 65535 : 255; + } + + /* output_processing means that the libpng-processed row will be + * 8-bit GA and it has to be processing to single byte color-map + * values. Entry 254 is replaced by either a completely + * transparent entry or by the background color at full + * precision (and the background color is not a simple gray leve + * in this case.) + */ + expand_tRNS = 1; + output_processing = PNG_CMAP_TRANS; + background_index = 254; + + /* And set (overwrite) color-map entry 254 to the actual + * background color at full precision. + */ + png_create_colormap_entry(display, 254, back_r, back_g, back_b, + back_alpha, output_encoding); + } + + else + output_processing = PNG_CMAP_NONE; + } + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + /* 8-bit or 16-bit PNG with two channels - gray and alpha. A minimum + * of 65536 combinations. If, however, the alpha channel is to be + * removed there are only 256 possibilities if the background is gray. + * (Otherwise there is a subset of the 65536 possibilities defined by + * the triangle between black, white and the background color.) + * + * Reduce 16-bit files to 8-bit and sRGB encode the result. No need to + * worry about tRNS matching - tRNS is ignored if there is an alpha + * channel. + */ + data_encoding = P_sRGB; + + if (output_format & PNG_FORMAT_FLAG_ALPHA) + { + if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "gray+alpha color-map: too few entries"); + + cmap_entries = make_ga_colormap(display); + + background_index = PNG_CMAP_GA_BACKGROUND; + output_processing = PNG_CMAP_GA; + } + + else /* alpha is removed */ + { + /* Alpha must be removed as the PNG data is processed when the + * background is a color because the G and A channels are + * independent and the vector addition (non-parallel vectors) is a + * 2-D problem. + * + * This can be reduced to the same algorithm as above by making a + * colormap containing gray levels (for the opaque grays), a + * background entry (for a transparent pixel) and a set of four six + * level color values, one set for each intermediate alpha value. + * See the comments in make_ga_colormap for how this works in the + * per-pixel processing. + * + * If the background is gray, however, we only need a 256 entry gray + * level color map. It is sufficient to make the entry generated + * for the background color be exactly the color specified. + */ + if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 || + (back_r == back_g && back_g == back_b)) + { + /* Background is gray; no special processing will be required. */ + png_color_16 c; + png_uint_32 gray = back_g; + + if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "gray-alpha color-map: too few entries"); + + cmap_entries = make_gray_colormap(display); + + if (output_encoding == P_LINEAR) + { + gray = PNG_sRGB_FROM_LINEAR(gray * 255); + + /* And make sure the corresponding palette entry matches. */ + png_create_colormap_entry(display, gray, back_g, back_g, + back_g, 65535, P_LINEAR); + } + + /* The background passed to libpng, however, must be the sRGB + * value. + */ + c.index = 0; /*unused*/ + c.gray = c.red = c.green = c.blue = (png_uint_16)gray; + + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + + output_processing = PNG_CMAP_NONE; + } + + else + { + png_uint_32 i, a; + + /* This is the same as png_make_ga_colormap, above, except that + * the entries are all opaque. + */ + if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "ga-alpha color-map: too few entries"); + + i = 0; + while (i < 231) + { + png_uint_32 gray = (i * 256 + 115) / 231; + png_create_colormap_entry(display, i++, gray, gray, gray, + 255, P_sRGB); + } + + /* NOTE: this preserves the full precision of the application + * background color. + */ + background_index = i; + png_create_colormap_entry(display, i++, back_r, back_g, back_b, + output_encoding == P_LINEAR ? 65535U : 255U, output_encoding); + + /* For non-opaque input composite on the sRGB background - this + * requires inverting the encoding for each component. The input + * is still converted to the sRGB encoding because this is a + * reasonable approximate to the logarithmic curve of human + * visual sensitivity, at least over the narrow range which PNG + * represents. Consequently 'G' is always sRGB encoded, while + * 'A' is linear. We need the linear background colors. + */ + if (output_encoding == P_sRGB) /* else already linear */ + { + /* This may produce a value not exactly matching the + * background, but that's ok because these numbers are only + * used when alpha != 0 + */ + back_r = png_sRGB_table[back_r]; + back_g = png_sRGB_table[back_g]; + back_b = png_sRGB_table[back_b]; + } + + for (a=1; a<5; ++a) + { + unsigned int g; + + /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled + * by an 8-bit alpha value (0..255). + */ + png_uint_32 alpha = 51 * a; + png_uint_32 back_rx = (255-alpha) * back_r; + png_uint_32 back_gx = (255-alpha) * back_g; + png_uint_32 back_bx = (255-alpha) * back_b; + + for (g=0; g<6; ++g) + { + png_uint_32 gray = png_sRGB_table[g*51] * alpha; + + png_create_colormap_entry(display, i++, + PNG_sRGB_FROM_LINEAR(gray + back_rx), + PNG_sRGB_FROM_LINEAR(gray + back_gx), + PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB); + } + } + + cmap_entries = i; + output_processing = PNG_CMAP_GA; + } + } + break; + + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + /* Exclude the case where the output is gray; we can always handle this + * with the cases above. + */ + if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0) + { + /* The color-map will be grayscale, so we may as well convert the + * input RGB values to a simple grayscale and use the grayscale + * code above. + * + * NOTE: calling this apparently damages the recognition of the + * transparent color in background color handling; call + * png_set_tRNS_to_alpha before png_set_background_fixed. + */ + png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1, + -1); + data_encoding = P_sRGB; + + /* The output will now be one or two 8-bit gray or gray+alpha + * channels. The more complex case arises when the input has alpha. + */ + if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->num_trans > 0) && + (output_format & PNG_FORMAT_FLAG_ALPHA) != 0) + { + /* Both input and output have an alpha channel, so no background + * processing is required; just map the GA bytes to the right + * color-map entry. + */ + expand_tRNS = 1; + + if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "rgb[ga] color-map: too few entries"); + + cmap_entries = make_ga_colormap(display); + background_index = PNG_CMAP_GA_BACKGROUND; + output_processing = PNG_CMAP_GA; + } + + else + { + /* Either the input or the output has no alpha channel, so there + * will be no non-opaque pixels in the color-map; it will just be + * grayscale. + */ + if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "rgb[gray] color-map: too few entries"); + + /* Ideally this code would use libpng to do the gamma correction, + * but if an input alpha channel is to be removed we will hit the + * libpng bug in gamma+compose+rgb-to-gray (the double gamma + * correction bug). Fix this by dropping the gamma correction in + * this case and doing it in the palette; this will result in + * duplicate palette entries, but that's better than the + * alternative of double gamma correction. + */ + if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->num_trans > 0) && + png_gamma_not_sRGB(png_ptr->colorspace.gamma)) + { + cmap_entries = make_gray_file_colormap(display); + data_encoding = P_FILE; + } + + else + cmap_entries = make_gray_colormap(display); + + /* But if the input has alpha or transparency it must be removed + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->num_trans > 0) + { + png_color_16 c; + png_uint_32 gray = back_g; + + /* We need to ensure that the application background exists in + * the colormap and that completely transparent pixels map to + * it. Achieve this simply by ensuring that the entry + * selected for the background really is the background color. + */ + if (data_encoding == P_FILE) /* from the fixup above */ + { + /* The app supplied a gray which is in output_encoding, we + * need to convert it to a value of the input (P_FILE) + * encoding then set this palette entry to the required + * output encoding. + */ + if (output_encoding == P_sRGB) + gray = png_sRGB_table[gray]; /* now P_LINEAR */ + + gray = PNG_DIV257(png_gamma_16bit_correct(gray, + png_ptr->colorspace.gamma)); /* now P_FILE */ + + /* And make sure the corresponding palette entry contains + * exactly the required sRGB value. + */ + png_create_colormap_entry(display, gray, back_g, back_g, + back_g, 0/*unused*/, output_encoding); + } + + else if (output_encoding == P_LINEAR) + { + gray = PNG_sRGB_FROM_LINEAR(gray * 255); + + /* And make sure the corresponding palette entry matches. + */ + png_create_colormap_entry(display, gray, back_g, back_g, + back_g, 0/*unused*/, P_LINEAR); + } + + /* The background passed to libpng, however, must be the + * output (normally sRGB) value. + */ + c.index = 0; /*unused*/ + c.gray = c.red = c.green = c.blue = (png_uint_16)gray; + + /* NOTE: the following is apparently a bug in libpng. Without + * it the transparent color recognition in + * png_set_background_fixed seems to go wrong. + */ + expand_tRNS = 1; + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + } + + output_processing = PNG_CMAP_NONE; + } + } + + else /* output is color */ + { + /* We could use png_quantize here so long as there is no transparent + * color or alpha; png_quantize ignores alpha. Easier overall just + * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube. + * Consequently we always want libpng to produce sRGB data. + */ + data_encoding = P_sRGB; + + /* Is there any transparency or alpha? */ + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->num_trans > 0) + { + /* Is there alpha in the output too? If so all four channels are + * processed into a special RGB cube with alpha support. + */ + if (output_format & PNG_FORMAT_FLAG_ALPHA) + { + png_uint_32 r; + + if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) + png_error(png_ptr, "rgb+alpha color-map: too few entries"); + + cmap_entries = make_rgb_colormap(display); + + /* Add a transparent entry. */ + png_create_colormap_entry(display, cmap_entries, 255, 255, + 255, 0, P_sRGB); + + /* This is stored as the background index for the processing + * algorithm. + */ + background_index = cmap_entries++; + + /* Add 27 r,g,b entries each with alpha 0.5. */ + for (r=0; r<256; r = (r << 1) | 0x7f) + { + png_uint_32 g; + + for (g=0; g<256; g = (g << 1) | 0x7f) + { + png_uint_32 b; + + /* This generates components with the values 0, 127 and + * 255 + */ + for (b=0; b<256; b = (b << 1) | 0x7f) + png_create_colormap_entry(display, cmap_entries++, + r, g, b, 128, P_sRGB); + } + } + + expand_tRNS = 1; + output_processing = PNG_CMAP_RGB_ALPHA; + } + + else + { + /* Alpha/transparency must be removed. The background must + * exist in the color map (achieved by setting adding it after + * the 666 color-map). If the standard processing code will + * pick up this entry automatically that's all that is + * required; libpng can be called to do the background + * processing. + */ + unsigned int sample_size = + PNG_IMAGE_SAMPLE_SIZE(output_format); + png_uint_32 r, g, b; /* sRGB background */ + + if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) + png_error(png_ptr, "rgb-alpha color-map: too few entries"); + + cmap_entries = make_rgb_colormap(display); + + png_create_colormap_entry(display, cmap_entries, back_r, + back_g, back_b, 0/*unused*/, output_encoding); + + if (output_encoding == P_LINEAR) + { + r = PNG_sRGB_FROM_LINEAR(back_r * 255); + g = PNG_sRGB_FROM_LINEAR(back_g * 255); + b = PNG_sRGB_FROM_LINEAR(back_b * 255); + } + + else + { + r = back_r; + g = back_g; + b = back_g; + } + + /* Compare the newly-created color-map entry with the one the + * PNG_CMAP_RGB algorithm will use. If the two entries don't + * match, add the new one and set this as the background + * index. + */ + if (memcmp((png_const_bytep)display->colormap + + sample_size * cmap_entries, + (png_const_bytep)display->colormap + + sample_size * PNG_RGB_INDEX(r,g,b), + sample_size) != 0) + { + /* The background color must be added. */ + background_index = cmap_entries++; + + /* Add 27 r,g,b entries each with created by composing with + * the background at alpha 0.5. + */ + for (r=0; r<256; r = (r << 1) | 0x7f) + { + for (g=0; g<256; g = (g << 1) | 0x7f) + { + /* This generates components with the values 0, 127 + * and 255 + */ + for (b=0; b<256; b = (b << 1) | 0x7f) + png_create_colormap_entry(display, cmap_entries++, + png_colormap_compose(display, r, P_sRGB, 128, + back_r, output_encoding), + png_colormap_compose(display, g, P_sRGB, 128, + back_g, output_encoding), + png_colormap_compose(display, b, P_sRGB, 128, + back_b, output_encoding), + 0/*unused*/, output_encoding); + } + } + + expand_tRNS = 1; + output_processing = PNG_CMAP_RGB_ALPHA; + } + + else /* background color is in the standard color-map */ + { + png_color_16 c; + + c.index = 0; /*unused*/ + c.red = (png_uint_16)back_r; + c.gray = c.green = (png_uint_16)back_g; + c.blue = (png_uint_16)back_b; + + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + + output_processing = PNG_CMAP_RGB; + } + } + } + + else /* no alpha or transparency in the input */ + { + /* Alpha in the output is irrelevant, simply map the opaque input + * pixels to the 6x6x6 color-map. + */ + if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries) + png_error(png_ptr, "rgb color-map: too few entries"); + + cmap_entries = make_rgb_colormap(display); + output_processing = PNG_CMAP_RGB; + } + } + break; + + case PNG_COLOR_TYPE_PALETTE: + /* It's already got a color-map. It may be necessary to eliminate the + * tRNS entries though. + */ + { + unsigned int num_trans = png_ptr->num_trans; + png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; + png_const_colorp colormap = png_ptr->palette; + const int do_background = trans != NULL && + (output_format & PNG_FORMAT_FLAG_ALPHA) == 0; + unsigned int i; + + /* Just in case: */ + if (trans == NULL) + num_trans = 0; + + output_processing = PNG_CMAP_NONE; + data_encoding = P_FILE; /* Don't change from color-map indicies */ + cmap_entries = png_ptr->num_palette; + if (cmap_entries > 256) + cmap_entries = 256; + + if (cmap_entries > image->colormap_entries) + png_error(png_ptr, "palette color-map: too few entries"); + + for (i=0; i < cmap_entries; ++i) + { + if (do_background && i < num_trans && trans[i] < 255) + { + if (trans[i] == 0) + png_create_colormap_entry(display, i, back_r, back_g, + back_b, 0, output_encoding); + + else + { + /* Must compose the PNG file color in the color-map entry + * on the sRGB color in 'back'. + */ + png_create_colormap_entry(display, i, + png_colormap_compose(display, colormap[i].red, P_FILE, + trans[i], back_r, output_encoding), + png_colormap_compose(display, colormap[i].green, P_FILE, + trans[i], back_g, output_encoding), + png_colormap_compose(display, colormap[i].blue, P_FILE, + trans[i], back_b, output_encoding), + output_encoding == P_LINEAR ? trans[i] * 257U : + trans[i], + output_encoding); + } + } + + else + png_create_colormap_entry(display, i, colormap[i].red, + colormap[i].green, colormap[i].blue, + i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/); + } + + /* The PNG data may have indicies packed in fewer than 8 bits, it + * must be expanded if so. + */ + if (png_ptr->bit_depth < 8) + png_set_packing(png_ptr); + } + break; + + default: + png_error(png_ptr, "invalid PNG color type"); + /*NOT REACHED*/ + break; + } + + /* Now deal with the output processing */ + if (expand_tRNS && png_ptr->num_trans > 0 && + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0) + png_set_tRNS_to_alpha(png_ptr); + + switch (data_encoding) + { + default: + png_error(png_ptr, "bad data option (internal error)"); + break; + + case P_sRGB: + /* Change to 8-bit sRGB */ + png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); + /* FALL THROUGH */ + + case P_FILE: + if (png_ptr->bit_depth > 8) + png_set_scale_16(png_ptr); + break; + } + + if (cmap_entries > 256 || cmap_entries > image->colormap_entries) + png_error(png_ptr, "color map overflow (BAD internal error)"); + + image->colormap_entries = cmap_entries; + + /* Double check using the recorded background index */ + switch (output_processing) + { + case PNG_CMAP_NONE: + if (background_index != PNG_CMAP_NONE_BACKGROUND) + goto bad_background; + break; + + case PNG_CMAP_GA: + if (background_index != PNG_CMAP_GA_BACKGROUND) + goto bad_background; + break; + + case PNG_CMAP_TRANS: + if (background_index >= cmap_entries || + background_index != PNG_CMAP_TRANS_BACKGROUND) + goto bad_background; + break; + + case PNG_CMAP_RGB: + if (background_index != PNG_CMAP_RGB_BACKGROUND) + goto bad_background; + break; + + case PNG_CMAP_RGB_ALPHA: + if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND) + goto bad_background; + break; + + default: + png_error(png_ptr, "bad processing option (internal error)"); + + bad_background: + png_error(png_ptr, "bad background index (internal error)"); + } + + display->colormap_processing = output_processing; + + return 1/*ok*/; +} + +/* The final part of the color-map read called from png_image_finish_read. */ +static int +png_image_read_and_map(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + int passes; + + /* Called when the libpng data must be transformed into the color-mapped + * form. There is a local row buffer in display->local and this routine must + * do the interlace handling. + */ + switch (png_ptr->interlaced) + { + case PNG_INTERLACE_NONE: + passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + passes = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + png_error(png_ptr, "unknown interlace type"); + } + + { + png_uint_32 height = image->height; + png_uint_32 width = image->width; + int proc = display->colormap_processing; + png_bytep first_row = png_voidcast(png_bytep, display->first_row); + ptrdiff_t step_row = display->row_bytes; + int pass; + + for (pass = 0; pass < passes; ++pass) + { + unsigned int startx, stepx, stepy; + png_uint_32 y; + + if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass); + stepx = PNG_PASS_COL_OFFSET(pass); + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = stepy = 1; + } + + for (; ylocal_row); + png_bytep outrow = first_row + y * step_row; + png_const_bytep end_row = outrow + width; + + /* Read read the libpng data into the temporary buffer. */ + png_read_row(png_ptr, inrow, NULL); + + /* Now process the row according to the processing option, note + * that the caller verifies that the format of the libpng output + * data is as required. + */ + outrow += startx; + switch (proc) + { + case PNG_CMAP_GA: + for (; outrow < end_row; outrow += stepx) + { + /* The data is always in the PNG order */ + unsigned int gray = *inrow++; + unsigned int alpha = *inrow++; + unsigned int entry; + + /* NOTE: this code is copied as a comment in + * make_ga_colormap above. Please update the + * comment if you change this code! + */ + if (alpha > 229) /* opaque */ + { + entry = (231 * gray + 128) >> 8; + } + else if (alpha < 26) /* transparent */ + { + entry = 231; + } + else /* partially opaque */ + { + entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray); + } + + *outrow = (png_byte)entry; + } + break; + + case PNG_CMAP_TRANS: + for (; outrow < end_row; outrow += stepx) + { + png_byte gray = *inrow++; + png_byte alpha = *inrow++; + + if (alpha == 0) + *outrow = PNG_CMAP_TRANS_BACKGROUND; + + else if (gray != PNG_CMAP_TRANS_BACKGROUND) + *outrow = gray; + + else + *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1); + } + break; + + case PNG_CMAP_RGB: + for (; outrow < end_row; outrow += stepx) + { + *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]); + inrow += 3; + } + break; + + case PNG_CMAP_RGB_ALPHA: + for (; outrow < end_row; outrow += stepx) + { + unsigned int alpha = inrow[3]; + + /* Because the alpha entries only hold alpha==0.5 values + * split the processing at alpha==0.25 (64) and 0.75 + * (196). + */ + + if (alpha >= 196) + *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], + inrow[2]); + + else if (alpha < 64) + *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND; + + else + { + /* Likewise there are three entries for each of r, g + * and b. We could select the entry by popcount on + * the top two bits on those architectures that + * support it, this is what the code below does, + * crudely. + */ + unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1; + + /* Here are how the values map: + * + * 0x00 .. 0x3f -> 0 + * 0x40 .. 0xbf -> 1 + * 0xc0 .. 0xff -> 2 + * + * So, as above with the explicit alpha checks, the + * breakpoints are at 64 and 196. + */ + if (inrow[0] & 0x80) back_i += 9; /* red */ + if (inrow[0] & 0x40) back_i += 9; + if (inrow[0] & 0x80) back_i += 3; /* green */ + if (inrow[0] & 0x40) back_i += 3; + if (inrow[0] & 0x80) back_i += 1; /* blue */ + if (inrow[0] & 0x40) back_i += 1; + + *outrow = (png_byte)back_i; + } + + inrow += 4; + } + break; + + default: + break; + } + } + } + } + + return 1; +} + +static int +png_image_read_colormapped(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_controlp control = image->opaque; + png_structrp png_ptr = control->png_ptr; + png_inforp info_ptr = control->info_ptr; + + int passes = 0; /* As a flag */ + + PNG_SKIP_CHUNKS(png_ptr); + + /* Update the 'info' structure and make sure the result is as required; first + * make sure to turn on the interlace handling if it will be required + * (because it can't be turned on *after* the call to png_read_update_info!) + */ + if (display->colormap_processing == PNG_CMAP_NONE) + passes = png_set_interlace_handling(png_ptr); + + png_read_update_info(png_ptr, info_ptr); + + /* The expected output can be deduced from the colormap_processing option. */ + switch (display->colormap_processing) + { + case PNG_CMAP_NONE: + /* Output must be one channel and one byte per pixel, the output + * encoding can be anything. + */ + if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + info_ptr->color_type == PNG_COLOR_TYPE_GRAY) && + info_ptr->bit_depth == 8) + break; + + goto bad_output; + + case PNG_CMAP_TRANS: + case PNG_CMAP_GA: + /* Output must be two channels and the 'G' one must be sRGB, the latter + * can be checked with an exact number because it should have been set + * to this number above! + */ + if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + info_ptr->bit_depth == 8 && + png_ptr->screen_gamma == PNG_GAMMA_sRGB && + image->colormap_entries == 256) + break; + + goto bad_output; + + case PNG_CMAP_RGB: + /* Output must be 8-bit sRGB encoded RGB */ + if (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + info_ptr->bit_depth == 8 && + png_ptr->screen_gamma == PNG_GAMMA_sRGB && + image->colormap_entries == 216) + break; + + goto bad_output; + + case PNG_CMAP_RGB_ALPHA: + /* Output must be 8-bit sRGB encoded RGBA */ + if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + info_ptr->bit_depth == 8 && + png_ptr->screen_gamma == PNG_GAMMA_sRGB && + image->colormap_entries == 244 /* 216 + 1 + 27 */) + break; + + /* goto bad_output; */ + /* FALL THROUGH */ + + default: + bad_output: + png_error(png_ptr, "bad color-map processing (internal error)"); + } + + /* Now read the rows. Do this here if it is possible to read directly into + * the output buffer, otherwise allocate a local row buffer of the maximum + * size libpng requires and call the relevant processing routine safely. + */ + { + png_voidp first_row = display->buffer; + ptrdiff_t row_bytes = display->row_stride; + + /* The following expression is designed to work correctly whether it gives + * a signed or an unsigned result. + */ + if (row_bytes < 0) + { + char *ptr = png_voidcast(char*, first_row); + ptr += (image->height-1) * (-row_bytes); + first_row = png_voidcast(png_voidp, ptr); + } + + display->first_row = first_row; + display->row_bytes = row_bytes; + } + + if (passes == 0) + { + int result; + png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + + display->local_row = row; + result = png_safe_execute(image, png_image_read_and_map, display); + display->local_row = NULL; + png_free(png_ptr, row); + + return result; + } + + else + { + png_alloc_size_t row_bytes = display->row_bytes; + + while (--passes >= 0) + { + png_uint_32 y = image->height; + png_bytep row = png_voidcast(png_bytep, display->first_row); + + while (y-- > 0) + { + png_read_row(png_ptr, row, NULL); + row += row_bytes; + } + } + + return 1; + } +} + +/* Just the row reading part of png_image_read. */ +static int +png_image_read_composite(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + int passes; + + switch (png_ptr->interlaced) + { + case PNG_INTERLACE_NONE: + passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + passes = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + png_error(png_ptr, "unknown interlace type"); + } + + { + png_uint_32 height = image->height; + png_uint_32 width = image->width; + ptrdiff_t step_row = display->row_bytes; + unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; + int pass; + + for (pass = 0; pass < passes; ++pass) + { + unsigned int startx, stepx, stepy; + png_uint_32 y; + + if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass) * channels; + stepx = PNG_PASS_COL_OFFSET(pass) * channels; + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = channels; + stepy = 1; + } + + for (; ylocal_row); + png_bytep outrow; + png_const_bytep end_row; + + /* Read the row, which is packed: */ + png_read_row(png_ptr, inrow, NULL); + + outrow = png_voidcast(png_bytep, display->first_row); + outrow += y * step_row; + end_row = outrow + width * channels; + + /* Now do the composition on each pixel in this row. */ + outrow += startx; + for (; outrow < end_row; outrow += stepx) + { + png_byte alpha = inrow[channels]; + + if (alpha > 0) /* else no change to the output */ + { + unsigned int c; + + for (c=0; cimage; + png_structrp png_ptr = image->opaque->png_ptr; + png_inforp info_ptr = image->opaque->info_ptr; + png_uint_32 height = image->height; + png_uint_32 width = image->width; + int pass, passes; + + /* Double check the convoluted logic below. We expect to get here with + * libpng doing rgb to gray and gamma correction but background processing + * left to the png_image_read_background function. The rows libpng produce + * might be 8 or 16-bit but should always have two channels; gray plus alpha. + */ + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) + png_error(png_ptr, "lost rgb to gray"); + + if ((png_ptr->transformations & PNG_COMPOSE) != 0) + png_error(png_ptr, "unexpected compose"); + + if (png_get_channels(png_ptr, info_ptr) != 2) + png_error(png_ptr, "lost/gained channels"); + + /* Expect the 8-bit case to always remove the alpha channel */ + if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 && + (image->format & PNG_FORMAT_FLAG_ALPHA) != 0) + png_error(png_ptr, "unexpected 8-bit transformation"); + + switch (png_ptr->interlaced) + { + case PNG_INTERLACE_NONE: + passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + passes = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + png_error(png_ptr, "unknown interlace type"); + } + + /* Use direct access to info_ptr here because otherwise the simplified API + * would require PNG_EASY_ACCESS_SUPPORTED (just for this.) Note this is + * checking the value after libpng expansions, not the original value in the + * PNG. + */ + switch (info_ptr->bit_depth) + { + default: + png_error(png_ptr, "unexpected bit depth"); + break; + + case 8: + /* 8-bit sRGB gray values with an alpha channel; the alpha channel is + * to be removed by composing on a background: either the row if + * display->background is NULL or display->background->green if not. + * Unlike the code above ALPHA_OPTIMIZED has *not* been done. + */ + { + png_bytep first_row = png_voidcast(png_bytep, display->first_row); + ptrdiff_t step_row = display->row_bytes; + + for (pass = 0; pass < passes; ++pass) + { + png_bytep row = png_voidcast(png_bytep, + display->first_row); + unsigned int startx, stepx, stepy; + png_uint_32 y; + + if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass); + stepx = PNG_PASS_COL_OFFSET(pass); + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = stepy = 1; + } + + if (display->background == NULL) + { + for (; ylocal_row); + png_bytep outrow = first_row + y * step_row; + png_const_bytep end_row = outrow + width; + + /* Read the row, which is packed: */ + png_read_row(png_ptr, inrow, NULL); + + /* Now do the composition on each pixel in this row. */ + outrow += startx; + for (; outrow < end_row; outrow += stepx) + { + png_byte alpha = inrow[1]; + + if (alpha > 0) /* else no change to the output */ + { + png_uint_32 component = inrow[0]; + + if (alpha < 255) /* else just use component */ + { + /* Since PNG_OPTIMIZED_ALPHA was not set it is + * necessary to invert the sRGB transfer + * function and multiply the alpha out. + */ + component = png_sRGB_table[component] * alpha; + component += png_sRGB_table[outrow[0]] * + (255-alpha); + component = PNG_sRGB_FROM_LINEAR(component); + } + + outrow[0] = (png_byte)component; + } + + inrow += 2; /* gray and alpha channel */ + } + } + } + + else /* constant background value */ + { + png_byte background8 = display->background->green; + png_uint_16 background = png_sRGB_table[background8]; + + for (; ylocal_row); + png_bytep outrow = first_row + y * step_row; + png_const_bytep end_row = outrow + width; + + /* Read the row, which is packed: */ + png_read_row(png_ptr, inrow, NULL); + + /* Now do the composition on each pixel in this row. */ + outrow += startx; + for (; outrow < end_row; outrow += stepx) + { + png_byte alpha = inrow[1]; + + if (alpha > 0) /* else use background */ + { + png_uint_32 component = inrow[0]; + + if (alpha < 255) /* else just use component */ + { + component = png_sRGB_table[component] * alpha; + component += background * (255-alpha); + component = PNG_sRGB_FROM_LINEAR(component); + } + + outrow[0] = (png_byte)component; + } + + else + outrow[0] = background8; + + inrow += 2; /* gray and alpha channel */ + } + + row += display->row_bytes; + } + } + } + } + break; + + case 16: + /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must + * still be done and, maybe, the alpha channel removed. This code also + * handles the alpha-first option. + */ + { + png_uint_16p first_row = png_voidcast(png_uint_16p, + display->first_row); + /* The division by two is safe because the caller passed in a + * stride which was multiplied by 2 (below) to get row_bytes. + */ + ptrdiff_t step_row = display->row_bytes / 2; + int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; + unsigned int outchannels = 1+preserve_alpha; + int swap_alpha = 0; + +# ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED + if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST)) + swap_alpha = 1; +# endif + + for (pass = 0; pass < passes; ++pass) + { + unsigned int startx, stepx, stepy; + png_uint_32 y; + + /* The 'x' start and step are adjusted to output components here. + */ + if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass) * outchannels; + stepx = PNG_PASS_COL_OFFSET(pass) * outchannels; + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = outchannels; + stepy = 1; + } + + for (; ylocal_row), NULL); + inrow = png_voidcast(png_const_uint_16p, display->local_row); + + /* Now do the pre-multiplication on each pixel in this row. + */ + outrow += startx; + for (; outrow < end_row; outrow += stepx) + { + png_uint_32 component = inrow[0]; + png_uint_16 alpha = inrow[1]; + + if (alpha > 0) /* else 0 */ + { + if (alpha < 65535) /* else just use component */ + { + component *= alpha; + component += 32767; + component /= 65535; + } + } + + else + component = 0; + + outrow[swap_alpha] = (png_uint_16)component; + if (preserve_alpha != 0) + outrow[1 ^ swap_alpha] = alpha; + + inrow += 2; /* components and alpha channel */ + } + } + } + } + break; + } + + return 1; +} + +/* The guts of png_image_finish_read as a png_safe_execute callback. */ +static int +png_image_read_direct(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + png_inforp info_ptr = image->opaque->info_ptr; + + png_uint_32 format = image->format; + int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; + int do_local_compose = 0; + int do_local_background = 0; /* to avoid double gamma correction bug */ + int passes = 0; + + /* Add transforms to ensure the correct output format is produced then check + * that the required implementation support is there. Always expand; always + * need 8 bits minimum, no palette and expanded tRNS. + */ + png_set_expand(png_ptr); + + /* Now check the format to see if it was modified. */ + { + png_uint_32 base_format = png_image_format(png_ptr) & + ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */; + png_uint_32 change = format ^ base_format; + png_fixed_point output_gamma; + int mode; /* alpha mode */ + + /* Do this first so that we have a record if rgb to gray is happening. */ + if (change & PNG_FORMAT_FLAG_COLOR) + { + /* gray<->color transformation required. */ + if (format & PNG_FORMAT_FLAG_COLOR) + png_set_gray_to_rgb(png_ptr); + + else + { + /* libpng can't do both rgb to gray and + * background/pre-multiplication if there is also significant gamma + * correction, because both operations require linear colors and + * the code only supports one transform doing the gamma correction. + * Handle this by doing the pre-multiplication or background + * operation in this code, if necessary. + * + * TODO: fix this by rewriting pngrtran.c (!) + * + * For the moment (given that fixing this in pngrtran.c is an + * enormous change) 'do_local_background' is used to indicate that + * the problem exists. + */ + if (base_format & PNG_FORMAT_FLAG_ALPHA) + do_local_background = 1/*maybe*/; + + png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, + PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); + } + + change &= ~PNG_FORMAT_FLAG_COLOR; + } + + /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise. + */ + { + png_fixed_point input_gamma_default; + + if ((base_format & PNG_FORMAT_FLAG_LINEAR) && + (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) + input_gamma_default = PNG_GAMMA_LINEAR; + else + input_gamma_default = PNG_DEFAULT_sRGB; + + /* Call png_set_alpha_mode to set the default for the input gamma; the + * output gamma is set by a second call below. + */ + png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default); + } + + if (linear != 0) + { + /* If there *is* an alpha channel in the input it must be multiplied + * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG. + */ + if (base_format & PNG_FORMAT_FLAG_ALPHA) + mode = PNG_ALPHA_STANDARD; /* associated alpha */ + + else + mode = PNG_ALPHA_PNG; + + output_gamma = PNG_GAMMA_LINEAR; + } + + else + { + mode = PNG_ALPHA_PNG; + output_gamma = PNG_DEFAULT_sRGB; + } + + /* If 'do_local_background' is set check for the presence of gamma + * correction; this is part of the work-round for the libpng bug + * described above. + * + * TODO: fix libpng and remove this. + */ + if (do_local_background != 0) + { + png_fixed_point gtest; + + /* This is 'png_gamma_threshold' from pngrtran.c; the test used for + * gamma correction, the screen gamma hasn't been set on png_struct + * yet; it's set below. png_struct::gamma, however, is set to the + * final value. + */ + if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma, + PNG_FP_1) && !png_gamma_significant(gtest)) + do_local_background = 0; + + else if (mode == PNG_ALPHA_STANDARD) + { + do_local_background = 2/*required*/; + mode = PNG_ALPHA_PNG; /* prevent libpng doing it */ + } + + /* else leave as 1 for the checks below */ + } + + /* If the bit-depth changes then handle that here. */ + if (change & PNG_FORMAT_FLAG_LINEAR) + { + if (linear /*16-bit output*/) + png_set_expand_16(png_ptr); + + else /* 8-bit output */ + png_set_scale_16(png_ptr); + + change &= ~PNG_FORMAT_FLAG_LINEAR; + } + + /* Now the background/alpha channel changes. */ + if (change & PNG_FORMAT_FLAG_ALPHA) + { + /* Removing an alpha channel requires composition for the 8-bit + * formats; for the 16-bit it is already done, above, by the + * pre-multiplication and the channel just needs to be stripped. + */ + if (base_format & PNG_FORMAT_FLAG_ALPHA) + { + /* If RGB->gray is happening the alpha channel must be left and the + * operation completed locally. + * + * TODO: fix libpng and remove this. + */ + if (do_local_background != 0) + do_local_background = 2/*required*/; + + /* 16-bit output: just remove the channel */ + else if (linear != 0) /* compose on black (well, pre-multiply) */ + png_set_strip_alpha(png_ptr); + + /* 8-bit output: do an appropriate compose */ + else if (display->background != NULL) + { + png_color_16 c; + + c.index = 0; /*unused*/ + c.red = display->background->red; + c.green = display->background->green; + c.blue = display->background->blue; + c.gray = display->background->green; + + /* This is always an 8-bit sRGB value, using the 'green' channel + * for gray is much better than calculating the luminance here; + * we can get off-by-one errors in that calculation relative to + * the app expectations and that will show up in transparent + * pixels. + */ + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + } + + else /* compose on row: implemented below. */ + { + do_local_compose = 1; + /* This leaves the alpha channel in the output, so it has to be + * removed by the code below. Set the encoding to the 'OPTIMIZE' + * one so the code only has to hack on the pixels that require + * composition. + */ + mode = PNG_ALPHA_OPTIMIZED; + } + } + + else /* output needs an alpha channel */ + { + /* This is tricky because it happens before the swap operation has + * been accomplished; however, the swap does *not* swap the added + * alpha channel (weird API), so it must be added in the correct + * place. + */ + png_uint_32 filler; /* opaque filler */ + int where; + + if (linear != 0) + filler = 65535; + + else + filler = 255; + +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + { + where = PNG_FILLER_BEFORE; + change &= ~PNG_FORMAT_FLAG_AFIRST; + } + + else +# endif + where = PNG_FILLER_AFTER; + + png_set_add_alpha(png_ptr, filler, where); + } + + /* This stops the (irrelevant) call to swap_alpha below. */ + change &= ~PNG_FORMAT_FLAG_ALPHA; + } + + /* Now set the alpha mode correctly; this is always done, even if there is + * no alpha channel in either the input or the output because it correctly + * sets the output gamma. + */ + png_set_alpha_mode_fixed(png_ptr, mode, output_gamma); + +# ifdef PNG_FORMAT_BGR_SUPPORTED + if (change & PNG_FORMAT_FLAG_BGR) + { + /* Check only the output format; PNG is never BGR; don't do this if + * the output is gray, but fix up the 'format' value in that case. + */ + if (format & PNG_FORMAT_FLAG_COLOR) + png_set_bgr(png_ptr); + + else + format &= ~PNG_FORMAT_FLAG_BGR; + + change &= ~PNG_FORMAT_FLAG_BGR; + } +# endif + +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (change & PNG_FORMAT_FLAG_AFIRST) + { + /* Only relevant if there is an alpha channel - it's particularly + * important to handle this correctly because do_local_compose may + * be set above and then libpng will keep the alpha channel for this + * code to remove. + */ + if (format & PNG_FORMAT_FLAG_ALPHA) + { + /* Disable this if doing a local background, + * TODO: remove this when local background is no longer required. + */ + if (do_local_background != 2) + png_set_swap_alpha(png_ptr); + } + + else + format &= ~PNG_FORMAT_FLAG_AFIRST; + + change &= ~PNG_FORMAT_FLAG_AFIRST; + } +# endif + + /* If the *output* is 16-bit then we need to check for a byte-swap on this + * architecture. + */ + if (linear != 0) + { + PNG_CONST png_uint_16 le = 0x0001; + + if (*(png_const_bytep)&le) + png_set_swap(png_ptr); + } + + /* If change is not now 0 some transformation is missing - error out. */ + if (change != 0) + png_error(png_ptr, "png_read_image: unsupported transformation"); + } + + PNG_SKIP_CHUNKS(png_ptr); + + /* Update the 'info' structure and make sure the result is as required; first + * make sure to turn on the interlace handling if it will be required + * (because it can't be turned on *after* the call to png_read_update_info!) + * + * TODO: remove the do_local_background fixup below. + */ + if (do_local_compose == 0 && do_local_background != 2) + passes = png_set_interlace_handling(png_ptr); + + png_read_update_info(png_ptr, info_ptr); + + { + png_uint_32 info_format = 0; + + if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_format |= PNG_FORMAT_FLAG_COLOR; + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + { + /* do_local_compose removes this channel below. */ + if (do_local_compose == 0) + { + /* do_local_background does the same if required. */ + if (do_local_background != 2 || + (format & PNG_FORMAT_FLAG_ALPHA) != 0) + info_format |= PNG_FORMAT_FLAG_ALPHA; + } + } + + else if (do_local_compose != 0) /* internal error */ + png_error(png_ptr, "png_image_read: alpha channel lost"); + + if (info_ptr->bit_depth == 16) + info_format |= PNG_FORMAT_FLAG_LINEAR; + +# ifdef PNG_FORMAT_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + info_format |= PNG_FORMAT_FLAG_BGR; +# endif + +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (do_local_background == 2) + { + if (format & PNG_FORMAT_FLAG_AFIRST) + info_format |= PNG_FORMAT_FLAG_AFIRST; + } + + if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 || + ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 && + (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0)) + { + if (do_local_background == 2) + png_error(png_ptr, "unexpected alpha swap transformation"); + + info_format |= PNG_FORMAT_FLAG_AFIRST; + } +# endif + + /* This is actually an internal error. */ + if (info_format != format) + png_error(png_ptr, "png_read_image: invalid transformations"); + } + + /* Now read the rows. If do_local_compose is set then it is necessary to use + * a local row buffer. The output will be GA, RGBA or BGRA and must be + * converted to G, RGB or BGR as appropriate. The 'local_row' member of the + * display acts as a flag. + */ + { + png_voidp first_row = display->buffer; + ptrdiff_t row_bytes = display->row_stride; + + if (linear != 0) + row_bytes *= 2; + + /* The following expression is designed to work correctly whether it gives + * a signed or an unsigned result. + */ + if (row_bytes < 0) + { + char *ptr = png_voidcast(char*, first_row); + ptr += (image->height-1) * (-row_bytes); + first_row = png_voidcast(png_voidp, ptr); + } + + display->first_row = first_row; + display->row_bytes = row_bytes; + } + + if (do_local_compose != 0) + { + int result; + png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + + display->local_row = row; + result = png_safe_execute(image, png_image_read_composite, display); + display->local_row = NULL; + png_free(png_ptr, row); + + return result; + } + + else if (do_local_background == 2) + { + int result; + png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + + display->local_row = row; + result = png_safe_execute(image, png_image_read_background, display); + display->local_row = NULL; + png_free(png_ptr, row); + + return result; + } + + else + { + png_alloc_size_t row_bytes = display->row_bytes; + + while (--passes >= 0) + { + png_uint_32 y = image->height; + png_bytep row = png_voidcast(png_bytep, display->first_row); + + while (y-- > 0) + { + png_read_row(png_ptr, row, NULL); + row += row_bytes; + } + } + + return 1; + } +} + +int PNGAPI +png_image_finish_read(png_imagep image, png_const_colorp background, + void *buffer, png_int_32 row_stride, void *colormap) +{ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + png_uint_32 check; + + if (row_stride == 0) + row_stride = PNG_IMAGE_ROW_STRIDE(*image); + + if (row_stride < 0) + check = -row_stride; + + else + check = row_stride; + + if (image->opaque != NULL && buffer != NULL && + check >= PNG_IMAGE_ROW_STRIDE(*image)) + { + if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || + (image->colormap_entries > 0 && colormap != NULL)) + { + int result; + png_image_read_control display; + + memset(&display, 0, (sizeof display)); + display.image = image; + display.buffer = buffer; + display.row_stride = row_stride; + display.colormap = colormap; + display.background = background; + display.local_row = NULL; + + /* Choose the correct 'end' routine; for the color-map case all the + * setup has already been done. + */ + if (image->format & PNG_FORMAT_FLAG_COLORMAP) + result = + png_safe_execute(image, png_image_read_colormap, &display) && + png_safe_execute(image, png_image_read_colormapped, &display); + + else + result = + png_safe_execute(image, png_image_read_direct, &display); + + png_image_free(image); + return result; + } + + else + return png_image_error(image, + "png_image_finish_read[color-map]: no color-map"); + } + + else + return png_image_error(image, + "png_image_finish_read: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_finish_read: damaged PNG_IMAGE_VERSION"); + + return 0; +} + +#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/ext/libpng16/pngrio.c b/ext/libpng17/pngrio.c similarity index 94% rename from ext/libpng16/pngrio.c rename to ext/libpng17/pngrio.c index 2b9c103202..d75ac5b4dd 100644 --- a/ext/libpng16/pngrio.c +++ b/ext/libpng17/pngrio.c @@ -1,118 +1,120 @@ - -/* pngrio.c - functions for data input - * - * Last changed in libpng 1.6.0 [February 14, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - * This file provides a location for all input. Users who need - * special handling are expected to write a function that has the same - * arguments as this and performs a similar function, but that possibly - * has a different input method. Note that you shouldn't change this - * function, but rather write a replacement function and then make - * libpng use it at run time with png_set_read_fn(...). - */ - -#include "pngpriv.h" - -#ifdef PNG_READ_SUPPORTED - -/* Read the data from whatever input you are using. The default routine - * reads from a file pointer. Note that this routine sometimes gets called - * with very small lengths, so you should implement some kind of simple - * buffering if you are using unbuffered reads. This should never be asked - * to read more then 64K on a 16 bit machine. - */ -void /* PRIVATE */ -png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) -{ - png_debug1(4, "reading %d bytes", (int)length); - - if (png_ptr->read_data_fn != NULL) - (*(png_ptr->read_data_fn))(png_ptr, data, length); - - else - png_error(png_ptr, "Call to NULL read function"); -} - -#ifdef PNG_STDIO_SUPPORTED -/* This is the function that does the actual reading of data. If you are - * not reading from a standard C stream, you should create a replacement - * read_data function and use it at run time with png_set_read_fn(), rather - * than changing the library. - */ -void PNGCBAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - if (png_ptr == NULL) - return; - - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ - check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); - - if (check != length) - png_error(png_ptr, "Read Error"); -} -#endif - -/* This function allows the application to supply a new input function - * for libpng if standard C streams aren't being used. - * - * This function takes as its arguments: - * - * png_ptr - pointer to a png input data structure - * - * io_ptr - pointer to user supplied structure containing info about - * the input functions. May be NULL. - * - * read_data_fn - pointer to a new input function that takes as its - * arguments a pointer to a png_struct, a pointer to - * a location where input data can be stored, and a 32-bit - * unsigned int that is the number of bytes to be read. - * To exit and output any fatal error messages the new write - * function should call png_error(png_ptr, "Error msg"). - * May be NULL, in which case libpng's default function will - * be used. - */ -void PNGAPI -png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn) -{ - if (png_ptr == NULL) - return; - - png_ptr->io_ptr = io_ptr; - -#ifdef PNG_STDIO_SUPPORTED - if (read_data_fn != NULL) - png_ptr->read_data_fn = read_data_fn; - - else - png_ptr->read_data_fn = png_default_read_data; -#else - png_ptr->read_data_fn = read_data_fn; -#endif - - /* It is an error to write to a read device */ - if (png_ptr->write_data_fn != NULL) - { - png_ptr->write_data_fn = NULL; - png_warning(png_ptr, - "Can't set both read_data_fn and write_data_fn in the" - " same structure"); - } - -#ifdef PNG_WRITE_FLUSH_SUPPORTED - png_ptr->output_flush_fn = NULL; -#endif -} -#endif /* PNG_READ_SUPPORTED */ + +/* pngrio.c - functions for data input + * + * Last changed in libpng 1.6.9 [February 6, 2014] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Read the data from whatever input you are using. The default routine + * reads from a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered reads. This should never be asked + * to read more then 64K on a 16 bit machine. + */ +void /* PRIVATE */ +png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4, "reading %d bytes", (int)length); + + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + + else + png_error(png_ptr, "Call to NULL read function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ +void PNGCBAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); + + if (check != length) + png_error(png_ptr, "Read Error"); +} +#endif + +/* This function allows the application to supply a new input function + * for libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * + * png_ptr - pointer to a png input data structure + * + * io_ptr - pointer to user supplied structure containing info about + * the input functions. May be NULL. + * + * read_data_fn - pointer to a new input function that takes as its + * arguments a pointer to a png_struct, a pointer to + * a location where input data can be stored, and a 32-bit + * unsigned int that is the number of bytes to be read. + * To exit and output any fatal error messages the new write + * function should call png_error(png_ptr, "Error msg"). + * May be NULL, in which case libpng's default function will + * be used. + */ +void PNGAPI +png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + +#ifdef PNG_WRITE_SUPPORTED + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->output_flush_fn = NULL; +#endif +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/ext/libpng16/pngrtran.c b/ext/libpng17/pngrtran.c similarity index 80% rename from ext/libpng16/pngrtran.c rename to ext/libpng17/pngrtran.c index 549fed7fe4..331b59ee62 100644 --- a/ext/libpng16/pngrtran.c +++ b/ext/libpng17/pngrtran.c @@ -1,5110 +1,4885 @@ - -/* pngrtran.c - transforms the data in a row for PNG readers - * - * Last changed in libpng 1.6.4 [August 21, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - * This file contains functions optionally called by an application - * in order to tell libpng how to handle data when reading a PNG. - * Transformations that are used in both reading and writing are - * in pngtrans.c. - */ - -#include "pngpriv.h" - -#ifdef PNG_READ_SUPPORTED - -/* Set the action on getting a CRC error for an ancillary or critical chunk. */ -void PNGAPI -png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action) -{ - png_debug(1, "in png_set_crc_action"); - - if (png_ptr == NULL) - return; - - /* Tell libpng how we react to CRC errors in critical chunks */ - switch (crit_action) - { - case PNG_CRC_NO_CHANGE: /* Leave setting as is */ - break; - - case PNG_CRC_WARN_USE: /* Warn/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; - break; - - case PNG_CRC_QUIET_USE: /* Quiet/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | - PNG_FLAG_CRC_CRITICAL_IGNORE; - break; - - case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ - png_warning(png_ptr, - "Can't discard critical data on CRC error"); - case PNG_CRC_ERROR_QUIT: /* Error/quit */ - - case PNG_CRC_DEFAULT: - default: - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - break; - } - - /* Tell libpng how we react to CRC errors in ancillary chunks */ - switch (ancil_action) - { - case PNG_CRC_NO_CHANGE: /* Leave setting as is */ - break; - - case PNG_CRC_WARN_USE: /* Warn/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; - break; - - case PNG_CRC_QUIET_USE: /* Quiet/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | - PNG_FLAG_CRC_ANCILLARY_NOWARN; - break; - - case PNG_CRC_ERROR_QUIT: /* Error/quit */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; - break; - - case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ - - case PNG_CRC_DEFAULT: - default: - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - break; - } -} - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -/* Is it OK to set a transformation now? Only if png_start_read_image or - * png_read_update_info have not been called. It is not necessary for the IHDR - * to have been read in all cases, the parameter allows for this check too. - */ -static int -png_rtran_ok(png_structrp png_ptr, int need_IHDR) -{ - if (png_ptr != NULL) - { - if (png_ptr->flags & PNG_FLAG_ROW_INIT) - png_app_error(png_ptr, - "invalid after png_start_read_image or png_read_update_info"); - - else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_app_error(png_ptr, "invalid before the PNG header has been read"); - - else - { - /* Turn on failure to initialize correctly for all transforms. */ - png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; - - return 1; /* Ok */ - } - } - - return 0; /* no png_error possible! */ -} -#endif - -#ifdef PNG_READ_BACKGROUND_SUPPORTED -/* Handle alpha and tRNS via a background color */ -void PNGFAPI -png_set_background_fixed(png_structrp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, png_fixed_point background_gamma) -{ - png_debug(1, "in png_set_background_fixed"); - - if (!png_rtran_ok(png_ptr, 0) || background_color == NULL) - return; - - if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) - { - png_warning(png_ptr, "Application must supply a known background gamma"); - return; - } - - png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA; - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - - png_ptr->background = *background_color; - png_ptr->background_gamma = background_gamma; - png_ptr->background_gamma_type = (png_byte)(background_gamma_code); - if (need_expand) - png_ptr->transformations |= PNG_BACKGROUND_EXPAND; - else - png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_background(png_structrp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma) -{ - png_set_background_fixed(png_ptr, background_color, background_gamma_code, - need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); -} -# endif /* FLOATING_POINT */ -#endif /* READ_BACKGROUND */ - -/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the - * one that pngrtran does first (scale) happens. This is necessary to allow the - * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. - */ -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED -void PNGAPI -png_set_scale_16(png_structrp png_ptr) -{ - png_debug(1, "in png_set_scale_16"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - png_ptr->transformations |= PNG_SCALE_16_TO_8; -} -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED -/* Chop 16-bit depth files to 8-bit depth */ -void PNGAPI -png_set_strip_16(png_structrp png_ptr) -{ - png_debug(1, "in png_set_strip_16"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - png_ptr->transformations |= PNG_16_TO_8; -} -#endif - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -void PNGAPI -png_set_strip_alpha(png_structrp png_ptr) -{ - png_debug(1, "in png_set_strip_alpha"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - png_ptr->transformations |= PNG_STRIP_ALPHA; -} -#endif - -#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) -static png_fixed_point -translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma, - int is_screen) -{ - /* Check for flag values. The main reason for having the old Mac value as a - * flag is that it is pretty near impossible to work out what the correct - * value is from Apple documentation - a working Mac system is needed to - * discover the value! - */ - if (output_gamma == PNG_DEFAULT_sRGB || - output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) - { - /* If there is no sRGB support this just sets the gamma to the standard - * sRGB value. (This is a side effect of using this function!) - */ -# ifdef PNG_READ_sRGB_SUPPORTED - png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; -# else - PNG_UNUSED(png_ptr) -# endif - if (is_screen) - output_gamma = PNG_GAMMA_sRGB; - else - output_gamma = PNG_GAMMA_sRGB_INVERSE; - } - - else if (output_gamma == PNG_GAMMA_MAC_18 || - output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) - { - if (is_screen) - output_gamma = PNG_GAMMA_MAC_OLD; - else - output_gamma = PNG_GAMMA_MAC_INVERSE; - } - - return output_gamma; -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -static png_fixed_point -convert_gamma_value(png_structrp png_ptr, double output_gamma) -{ - /* The following silently ignores cases where fixed point (times 100,000) - * gamma values are passed to the floating point API. This is safe and it - * means the fixed point constants work just fine with the floating point - * API. The alternative would just lead to undetected errors and spurious - * bug reports. Negative values fail inside the _fixed API unless they - * correspond to the flag values. - */ - if (output_gamma > 0 && output_gamma < 128) - output_gamma *= PNG_FP_1; - - /* This preserves -1 and -2 exactly: */ - output_gamma = floor(output_gamma + .5); - - if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN) - png_fixed_error(png_ptr, "gamma value"); - - return (png_fixed_point)output_gamma; -} -# endif -#endif /* READ_ALPHA_MODE || READ_GAMMA */ - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED -void PNGFAPI -png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, - png_fixed_point output_gamma) -{ - int compose = 0; - png_fixed_point file_gamma; - - png_debug(1, "in png_set_alpha_mode"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); - - /* Validate the value to ensure it is in a reasonable range. The value - * is expected to be 1 or greater, but this range test allows for some - * viewing correction values. The intent is to weed out users of this API - * who use the inverse of the gamma value accidentally! Since some of these - * values are reasonable this may have to be changed. - */ - if (output_gamma < 70000 || output_gamma > 300000) - png_error(png_ptr, "output gamma out of expected range"); - - /* The default file gamma is the inverse of the output gamma; the output - * gamma may be changed below so get the file value first: - */ - file_gamma = png_reciprocal(output_gamma); - - /* There are really 8 possibilities here, composed of any combination - * of: - * - * premultiply the color channels - * do not encode non-opaque pixels - * encode the alpha as well as the color channels - * - * The differences disappear if the input/output ('screen') gamma is 1.0, - * because then the encoding is a no-op and there is only the choice of - * premultiplying the color channels or not. - * - * png_set_alpha_mode and png_set_background interact because both use - * png_compose to do the work. Calling both is only useful when - * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along - * with a default gamma value. Otherwise PNG_COMPOSE must not be set. - */ - switch (mode) - { - case PNG_ALPHA_PNG: /* default: png standard */ - /* No compose, but it may be set by png_set_background! */ - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - break; - - case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */ - compose = 1; - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - /* The output is linear: */ - output_gamma = PNG_FP_1; - break; - - case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */ - compose = 1; - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; - /* output_gamma records the encoding of opaque pixels! */ - break; - - case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */ - compose = 1; - png_ptr->transformations |= PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - break; - - default: - png_error(png_ptr, "invalid alpha mode"); - } - - /* Only set the default gamma if the file gamma has not been set (this has - * the side effect that the gamma in a second call to png_set_alpha_mode will - * be ignored.) - */ - if (png_ptr->colorspace.gamma == 0) - { - png_ptr->colorspace.gamma = file_gamma; - png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; - } - - /* But always set the output gamma: */ - png_ptr->screen_gamma = output_gamma; - - /* Finally, if pre-multiplying, set the background fields to achieve the - * desired result. - */ - if (compose) - { - /* And obtain alpha pre-multiplication by composing on black: */ - memset(&png_ptr->background, 0, (sizeof png_ptr->background)); - png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */ - png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; - png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; - - if (png_ptr->transformations & PNG_COMPOSE) - png_error(png_ptr, - "conflicting calls to set alpha mode and background"); - - png_ptr->transformations |= PNG_COMPOSE; - } -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma) -{ - png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, - output_gamma)); -} -# endif -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* Dither file to 8-bit. Supply a palette, the current number - * of elements in the palette, the maximum number of elements - * allowed, and a histogram if possible. If the current number - * of colors is greater then the maximum number, the palette will be - * modified to fit in the maximum number. "full_quantize" indicates - * whether we need a quantizing cube set up for RGB images, or if we - * simply are reducing the number of colors in a paletted image. - */ - -typedef struct png_dsort_struct -{ - struct png_dsort_struct * next; - png_byte left; - png_byte right; -} png_dsort; -typedef png_dsort * png_dsortp; -typedef png_dsort * * png_dsortpp; - -void PNGAPI -png_set_quantize(png_structrp png_ptr, png_colorp palette, - int num_palette, int maximum_colors, png_const_uint_16p histogram, - int full_quantize) -{ - png_debug(1, "in png_set_quantize"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - png_ptr->transformations |= PNG_QUANTIZE; - - if (!full_quantize) - { - int i; - - png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); - for (i = 0; i < num_palette; i++) - png_ptr->quantize_index[i] = (png_byte)i; - } - - if (num_palette > maximum_colors) - { - if (histogram != NULL) - { - /* This is easy enough, just throw out the least used colors. - * Perhaps not the best solution, but good enough. - */ - - int i; - - /* Initialize an array to sort colors */ - png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); - - /* Initialize the quantize_sort array */ - for (i = 0; i < num_palette; i++) - png_ptr->quantize_sort[i] = (png_byte)i; - - /* Find the least used palette entries by starting a - * bubble sort, and running it until we have sorted - * out enough colors. Note that we don't care about - * sorting all the colors, just finding which are - * least used. - */ - - for (i = num_palette - 1; i >= maximum_colors; i--) - { - int done; /* To stop early if the list is pre-sorted */ - int j; - - done = 1; - for (j = 0; j < i; j++) - { - if (histogram[png_ptr->quantize_sort[j]] - < histogram[png_ptr->quantize_sort[j + 1]]) - { - png_byte t; - - t = png_ptr->quantize_sort[j]; - png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; - png_ptr->quantize_sort[j + 1] = t; - done = 0; - } - } - - if (done) - break; - } - - /* Swap the palette around, and set up a table, if necessary */ - if (full_quantize) - { - int j = num_palette; - - /* Put all the useful colors within the max, but don't - * move the others. - */ - for (i = 0; i < maximum_colors; i++) - { - if ((int)png_ptr->quantize_sort[i] >= maximum_colors) - { - do - j--; - while ((int)png_ptr->quantize_sort[j] >= maximum_colors); - - palette[i] = palette[j]; - } - } - } - else - { - int j = num_palette; - - /* Move all the used colors inside the max limit, and - * develop a translation table. - */ - for (i = 0; i < maximum_colors; i++) - { - /* Only move the colors we need to */ - if ((int)png_ptr->quantize_sort[i] >= maximum_colors) - { - png_color tmp_color; - - do - j--; - while ((int)png_ptr->quantize_sort[j] >= maximum_colors); - - tmp_color = palette[j]; - palette[j] = palette[i]; - palette[i] = tmp_color; - /* Indicate where the color went */ - png_ptr->quantize_index[j] = (png_byte)i; - png_ptr->quantize_index[i] = (png_byte)j; - } - } - - /* Find closest color for those colors we are not using */ - for (i = 0; i < num_palette; i++) - { - if ((int)png_ptr->quantize_index[i] >= maximum_colors) - { - int min_d, k, min_k, d_index; - - /* Find the closest color to one we threw out */ - d_index = png_ptr->quantize_index[i]; - min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); - for (k = 1, min_k = 0; k < maximum_colors; k++) - { - int d; - - d = PNG_COLOR_DIST(palette[d_index], palette[k]); - - if (d < min_d) - { - min_d = d; - min_k = k; - } - } - /* Point to closest color */ - png_ptr->quantize_index[i] = (png_byte)min_k; - } - } - } - png_free(png_ptr, png_ptr->quantize_sort); - png_ptr->quantize_sort = NULL; - } - else - { - /* This is much harder to do simply (and quickly). Perhaps - * we need to go through a median cut routine, but those - * don't always behave themselves with only a few colors - * as input. So we will just find the closest two colors, - * and throw out one of them (chosen somewhat randomly). - * [We don't understand this at all, so if someone wants to - * work on improving it, be our guest - AED, GRP] - */ - int i; - int max_d; - int num_new_palette; - png_dsortp t; - png_dsortpp hash; - - t = NULL; - - /* Initialize palette index arrays */ - png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); - png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); - - /* Initialize the sort array */ - for (i = 0; i < num_palette; i++) - { - png_ptr->index_to_palette[i] = (png_byte)i; - png_ptr->palette_to_index[i] = (png_byte)i; - } - - hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * - (sizeof (png_dsortp)))); - - num_new_palette = num_palette; - - /* Initial wild guess at how far apart the farthest pixel - * pair we will be eliminating will be. Larger - * numbers mean more areas will be allocated, Smaller - * numbers run the risk of not saving enough data, and - * having to do this all over again. - * - * I have not done extensive checking on this number. - */ - max_d = 96; - - while (num_new_palette > maximum_colors) - { - for (i = 0; i < num_new_palette - 1; i++) - { - int j; - - for (j = i + 1; j < num_new_palette; j++) - { - int d; - - d = PNG_COLOR_DIST(palette[i], palette[j]); - - if (d <= max_d) - { - - t = (png_dsortp)png_malloc_warn(png_ptr, - (png_uint_32)(sizeof (png_dsort))); - - if (t == NULL) - break; - - t->next = hash[d]; - t->left = (png_byte)i; - t->right = (png_byte)j; - hash[d] = t; - } - } - if (t == NULL) - break; - } - - if (t != NULL) - for (i = 0; i <= max_d; i++) - { - if (hash[i] != NULL) - { - png_dsortp p; - - for (p = hash[i]; p; p = p->next) - { - if ((int)png_ptr->index_to_palette[p->left] - < num_new_palette && - (int)png_ptr->index_to_palette[p->right] - < num_new_palette) - { - int j, next_j; - - if (num_new_palette & 0x01) - { - j = p->left; - next_j = p->right; - } - else - { - j = p->right; - next_j = p->left; - } - - num_new_palette--; - palette[png_ptr->index_to_palette[j]] - = palette[num_new_palette]; - if (!full_quantize) - { - int k; - - for (k = 0; k < num_palette; k++) - { - if (png_ptr->quantize_index[k] == - png_ptr->index_to_palette[j]) - png_ptr->quantize_index[k] = - png_ptr->index_to_palette[next_j]; - - if ((int)png_ptr->quantize_index[k] == - num_new_palette) - png_ptr->quantize_index[k] = - png_ptr->index_to_palette[j]; - } - } - - png_ptr->index_to_palette[png_ptr->palette_to_index - [num_new_palette]] = png_ptr->index_to_palette[j]; - - png_ptr->palette_to_index[png_ptr->index_to_palette[j]] - = png_ptr->palette_to_index[num_new_palette]; - - png_ptr->index_to_palette[j] = - (png_byte)num_new_palette; - - png_ptr->palette_to_index[num_new_palette] = - (png_byte)j; - } - if (num_new_palette <= maximum_colors) - break; - } - if (num_new_palette <= maximum_colors) - break; - } - } - - for (i = 0; i < 769; i++) - { - if (hash[i] != NULL) - { - png_dsortp p = hash[i]; - while (p) - { - t = p->next; - png_free(png_ptr, p); - p = t; - } - } - hash[i] = 0; - } - max_d += 96; - } - png_free(png_ptr, hash); - png_free(png_ptr, png_ptr->palette_to_index); - png_free(png_ptr, png_ptr->index_to_palette); - png_ptr->palette_to_index = NULL; - png_ptr->index_to_palette = NULL; - } - num_palette = maximum_colors; - } - if (png_ptr->palette == NULL) - { - png_ptr->palette = palette; - } - png_ptr->num_palette = (png_uint_16)num_palette; - - if (full_quantize) - { - int i; - png_bytep distance; - int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + - PNG_QUANTIZE_BLUE_BITS; - int num_red = (1 << PNG_QUANTIZE_RED_BITS); - int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); - int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); - png_size_t num_entries = ((png_size_t)1 << total_bits); - - png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, - (png_uint_32)(num_entries * (sizeof (png_byte)))); - - distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * - (sizeof (png_byte)))); - - memset(distance, 0xff, num_entries * (sizeof (png_byte))); - - for (i = 0; i < num_palette; i++) - { - int ir, ig, ib; - int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); - int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); - int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS)); - - for (ir = 0; ir < num_red; ir++) - { - /* int dr = abs(ir - r); */ - int dr = ((ir > r) ? ir - r : r - ir); - int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS + - PNG_QUANTIZE_GREEN_BITS)); - - for (ig = 0; ig < num_green; ig++) - { - /* int dg = abs(ig - g); */ - int dg = ((ig > g) ? ig - g : g - ig); - int dt = dr + dg; - int dm = ((dr > dg) ? dr : dg); - int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS); - - for (ib = 0; ib < num_blue; ib++) - { - int d_index = index_g | ib; - /* int db = abs(ib - b); */ - int db = ((ib > b) ? ib - b : b - ib); - int dmax = ((dm > db) ? dm : db); - int d = dmax + dt + db; - - if (d < (int)distance[d_index]) - { - distance[d_index] = (png_byte)d; - png_ptr->palette_lookup[d_index] = (png_byte)i; - } - } - } - } - } - - png_free(png_ptr, distance); - } -} -#endif /* PNG_READ_QUANTIZE_SUPPORTED */ - -#ifdef PNG_READ_GAMMA_SUPPORTED -void PNGFAPI -png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma, - png_fixed_point file_gamma) -{ - png_debug(1, "in png_set_gamma_fixed"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - /* New in libpng-1.5.4 - reserve particular negative values as flags. */ - scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); - file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); - - /* Checking the gamma values for being >0 was added in 1.5.4 along with the - * premultiplied alpha support; this actually hides an undocumented feature - * of the previous implementation which allowed gamma processing to be - * disabled in background handling. There is no evidence (so far) that this - * was being used; however, png_set_background itself accepted and must still - * accept '0' for the gamma value it takes, because it isn't always used. - * - * Since this is an API change (albeit a very minor one that removes an - * undocumented API feature) the following checks were only enabled in - * libpng-1.6.0. - */ - if (file_gamma <= 0) - png_error(png_ptr, "invalid file gamma in png_set_gamma"); - - if (scrn_gamma <= 0) - png_error(png_ptr, "invalid screen gamma in png_set_gamma"); - - /* Set the gamma values unconditionally - this overrides the value in the PNG - * file if a gAMA chunk was present. png_set_alpha_mode provides a - * different, easier, way to default the file gamma. - */ - png_ptr->colorspace.gamma = file_gamma; - png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; - png_ptr->screen_gamma = scrn_gamma; -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma) -{ - png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), - convert_gamma_value(png_ptr, file_gamma)); -} -# endif /* FLOATING_POINT_SUPPORTED */ -#endif /* READ_GAMMA */ - -#ifdef PNG_READ_EXPAND_SUPPORTED -/* Expand paletted images to RGB, expand grayscale images of - * less than 8-bit depth to 8-bit depth, and expand tRNS chunks - * to alpha channels. - */ -void PNGAPI -png_set_expand(png_structrp png_ptr) -{ - png_debug(1, "in png_set_expand"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -} - -/* GRR 19990627: the following three functions currently are identical - * to png_set_expand(). However, it is entirely reasonable that someone - * might wish to expand an indexed image to RGB but *not* expand a single, - * fully transparent palette entry to a full alpha channel--perhaps instead - * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace - * the transparent color with a particular RGB value, or drop tRNS entirely. - * IOW, a future version of the library may make the transformations flag - * a bit more fine-grained, with separate bits for each of these three - * functions. - * - * More to the point, these functions make it obvious what libpng will be - * doing, whereas "expand" can (and does) mean any number of things. - * - * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified - * to expand only the sample depth but not to expand the tRNS to alpha - * and its name was changed to png_set_expand_gray_1_2_4_to_8(). - */ - -/* Expand paletted images to RGB. */ -void PNGAPI -png_set_palette_to_rgb(png_structrp png_ptr) -{ - png_debug(1, "in png_set_palette_to_rgb"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -} - -/* Expand grayscale images of less than 8-bit depth to 8 bits. */ -void PNGAPI -png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr) -{ - png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - png_ptr->transformations |= PNG_EXPAND; -} - -/* Expand tRNS chunks to alpha channels. */ -void PNGAPI -png_set_tRNS_to_alpha(png_structrp png_ptr) -{ - png_debug(1, "in png_set_tRNS_to_alpha"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -} -#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ - -#ifdef PNG_READ_EXPAND_16_SUPPORTED -/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise - * it may not work correctly.) - */ -void PNGAPI -png_set_expand_16(png_structrp png_ptr) -{ - png_debug(1, "in png_set_expand_16"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); -} -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -void PNGAPI -png_set_gray_to_rgb(png_structrp png_ptr) -{ - png_debug(1, "in png_set_gray_to_rgb"); - - if (!png_rtran_ok(png_ptr, 0)) - return; - - /* Because rgb must be 8 bits or more: */ - png_set_expand_gray_1_2_4_to_8(png_ptr); - png_ptr->transformations |= PNG_GRAY_TO_RGB; -} -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -void PNGFAPI -png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, - png_fixed_point red, png_fixed_point green) -{ - png_debug(1, "in png_set_rgb_to_gray"); - - /* Need the IHDR here because of the check on color_type below. */ - /* TODO: fix this */ - if (!png_rtran_ok(png_ptr, 1)) - return; - - switch(error_action) - { - case PNG_ERROR_ACTION_NONE: - png_ptr->transformations |= PNG_RGB_TO_GRAY; - break; - - case PNG_ERROR_ACTION_WARN: - png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; - break; - - case PNG_ERROR_ACTION_ERROR: - png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; - break; - - default: - png_error(png_ptr, "invalid error action to rgb_to_gray"); - break; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) -#ifdef PNG_READ_EXPAND_SUPPORTED - png_ptr->transformations |= PNG_EXPAND; -#else - { - /* Make this an error in 1.6 because otherwise the application may assume - * that it just worked and get a memory overwrite. - */ - png_error(png_ptr, - "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); - - /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */ - } -#endif - { - if (red >= 0 && green >= 0 && red + green <= PNG_FP_1) - { - png_uint_16 red_int, green_int; - - /* NOTE: this calculation does not round, but this behavior is retained - * for consistency, the inaccuracy is very small. The code here always - * overwrites the coefficients, regardless of whether they have been - * defaulted or set already. - */ - red_int = (png_uint_16)(((png_uint_32)red*32768)/100000); - green_int = (png_uint_16)(((png_uint_32)green*32768)/100000); - - png_ptr->rgb_to_gray_red_coeff = red_int; - png_ptr->rgb_to_gray_green_coeff = green_int; - png_ptr->rgb_to_gray_coefficients_set = 1; - } - - else - { - if (red >= 0 && green >= 0) - png_app_warning(png_ptr, - "ignoring out of range rgb_to_gray coefficients"); - - /* Use the defaults, from the cHRM chunk if set, else the historical - * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See - * png_do_rgb_to_gray for more discussion of the values. In this case - * the coefficients are not marked as 'set' and are not overwritten if - * something has already provided a default. - */ - if (png_ptr->rgb_to_gray_red_coeff == 0 && - png_ptr->rgb_to_gray_green_coeff == 0) - { - png_ptr->rgb_to_gray_red_coeff = 6968; - png_ptr->rgb_to_gray_green_coeff = 23434; - /* png_ptr->rgb_to_gray_blue_coeff = 2366; */ - } - } - } -} - -#ifdef PNG_FLOATING_POINT_SUPPORTED -/* Convert a RGB image to a grayscale of the same width. This allows us, - * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. - */ - -void PNGAPI -png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red, - double green) -{ - png_set_rgb_to_gray_fixed(png_ptr, error_action, - png_fixed(png_ptr, red, "rgb to gray red coefficient"), - png_fixed(png_ptr, green, "rgb to gray green coefficient")); -} -#endif /* FLOATING POINT */ - -#endif /* RGB_TO_GRAY */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -void PNGAPI -png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr - read_user_transform_fn) -{ - png_debug(1, "in png_set_read_user_transform_fn"); - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - png_ptr->transformations |= PNG_USER_TRANSFORM; - png_ptr->read_user_transform_fn = read_user_transform_fn; -#endif -} -#endif - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -#ifdef PNG_READ_GAMMA_SUPPORTED -/* In the case of gamma transformations only do transformations on images where - * the [file] gamma and screen_gamma are not close reciprocals, otherwise it - * slows things down slightly, and also needlessly introduces small errors. - */ -static int /* PRIVATE */ -png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) -{ - /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma - * correction as a difference of the overall transform from 1.0 - * - * We want to compare the threshold with s*f - 1, if we get - * overflow here it is because of wacky gamma values so we - * turn on processing anyway. - */ - png_fixed_point gtest; - return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) || - png_gamma_significant(gtest); -} -#endif - -/* Initialize everything needed for the read. This includes modifying - * the palette. - */ - -/*For the moment 'png_init_palette_transformations' and - * 'png_init_rgb_transformations' only do some flag canceling optimizations. - * The intent is that these two routines should have palette or rgb operations - * extracted from 'png_init_read_transformations'. - */ -static void /* PRIVATE */ -png_init_palette_transformations(png_structrp png_ptr) -{ - /* Called to handle the (input) palette case. In png_do_read_transformations - * the first step is to expand the palette if requested, so this code must - * take care to only make changes that are invariant with respect to the - * palette expansion, or only do them if there is no expansion. - * - * STRIP_ALPHA has already been handled in the caller (by setting num_trans - * to 0.) - */ - int input_has_alpha = 0; - int input_has_transparency = 0; - - if (png_ptr->num_trans > 0) - { - int i; - - /* Ignore if all the entries are opaque (unlikely!) */ - for (i=0; inum_trans; ++i) - { - if (png_ptr->trans_alpha[i] == 255) - continue; - else if (png_ptr->trans_alpha[i] == 0) - input_has_transparency = 1; - else - { - input_has_transparency = 1; - input_has_alpha = 1; - break; - } - } - } - - /* If no alpha we can optimize. */ - if (!input_has_alpha) - { - /* Any alpha means background and associative alpha processing is - * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA - * and ENCODE_ALPHA are irrelevant. - */ - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - - if (!input_has_transparency) - png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); - } - -#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) - /* png_set_background handling - deals with the complexity of whether the - * background color is in the file format or the screen format in the case - * where an 'expand' will happen. - */ - - /* The following code cannot be entered in the alpha pre-multiplication case - * because PNG_BACKGROUND_EXPAND is cancelled below. - */ - if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_EXPAND)) - { - { - png_ptr->background.red = - png_ptr->palette[png_ptr->background.index].red; - png_ptr->background.green = - png_ptr->palette[png_ptr->background.index].green; - png_ptr->background.blue = - png_ptr->palette[png_ptr->background.index].blue; - -#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED - if (png_ptr->transformations & PNG_INVERT_ALPHA) - { - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - /* Invert the alpha channel (in tRNS) unless the pixels are - * going to be expanded, in which case leave it for later - */ - int i, istop = png_ptr->num_trans; - - for (i=0; itrans_alpha[i] = (png_byte)(255 - - png_ptr->trans_alpha[i]); - } - } -#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ - } - } /* background expand and (therefore) no alpha association. */ -#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ -} - -static void /* PRIVATE */ -png_init_rgb_transformations(png_structrp png_ptr) -{ - /* Added to libpng-1.5.4: check the color type to determine whether there - * is any alpha or transparency in the image and simply cancel the - * background and alpha mode stuff if there isn't. - */ - int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; - int input_has_transparency = png_ptr->num_trans > 0; - - /* If no alpha we can optimize. */ - if (!input_has_alpha) - { - /* Any alpha means background and associative alpha processing is - * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA - * and ENCODE_ALPHA are irrelevant. - */ -# ifdef PNG_READ_ALPHA_MODE_SUPPORTED - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; -# endif - - if (!input_has_transparency) - png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); - } - -#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) - /* png_set_background handling - deals with the complexity of whether the - * background color is in the file format or the screen format in the case - * where an 'expand' will happen. - */ - - /* The following code cannot be entered in the alpha pre-multiplication case - * because PNG_BACKGROUND_EXPAND is cancelled below. - */ - if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_EXPAND) && - !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) - /* i.e., GRAY or GRAY_ALPHA */ - { - { - /* Expand background and tRNS chunks */ - int gray = png_ptr->background.gray; - int trans_gray = png_ptr->trans_color.gray; - - switch (png_ptr->bit_depth) - { - case 1: - gray *= 0xff; - trans_gray *= 0xff; - break; - - case 2: - gray *= 0x55; - trans_gray *= 0x55; - break; - - case 4: - gray *= 0x11; - trans_gray *= 0x11; - break; - - default: - - case 8: - /* FALL THROUGH (Already 8 bits) */ - - case 16: - /* Already a full 16 bits */ - break; - } - - png_ptr->background.red = png_ptr->background.green = - png_ptr->background.blue = (png_uint_16)gray; - - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_color.red = png_ptr->trans_color.green = - png_ptr->trans_color.blue = (png_uint_16)trans_gray; - } - } - } /* background expand and (therefore) no alpha association. */ -#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ -} - -void /* PRIVATE */ -png_init_read_transformations(png_structrp png_ptr) -{ - png_debug(1, "in png_init_read_transformations"); - - /* This internal function is called from png_read_start_row in pngrutil.c - * and it is called before the 'rowbytes' calculation is done, so the code - * in here can change or update the transformations flags. - * - * First do updates that do not depend on the details of the PNG image data - * being processed. - */ - -#ifdef PNG_READ_GAMMA_SUPPORTED - /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds - * png_set_alpha_mode and this is another source for a default file gamma so - * the test needs to be performed later - here. In addition prior to 1.5.4 - * the tests were repeated for the PALETTE color type here - this is no - * longer necessary (and doesn't seem to have been necessary before.) - */ - { - /* The following temporary indicates if overall gamma correction is - * required. - */ - int gamma_correction = 0; - - if (png_ptr->colorspace.gamma != 0) /* has been set */ - { - if (png_ptr->screen_gamma != 0) /* screen set too */ - gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); - - else - /* Assume the output matches the input; a long time default behavior - * of libpng, although the standard has nothing to say about this. - */ - png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma); - } - - else if (png_ptr->screen_gamma != 0) - /* The converse - assume the file matches the screen, note that this - * perhaps undesireable default can (from 1.5.4) be changed by calling - * png_set_alpha_mode (even if the alpha handling mode isn't required - * or isn't changed from the default.) - */ - png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma); - - else /* neither are set */ - /* Just in case the following prevents any processing - file and screen - * are both assumed to be linear and there is no way to introduce a - * third gamma value other than png_set_background with 'UNIQUE', and, - * prior to 1.5.4 - */ - png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1; - - /* We have a gamma value now. */ - png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; - - /* Now turn the gamma transformation on or off as appropriate. Notice - * that PNG_GAMMA just refers to the file->screen correction. Alpha - * composition may independently cause gamma correction because it needs - * linear data (e.g. if the file has a gAMA chunk but the screen gamma - * hasn't been specified.) In any case this flag may get turned off in - * the code immediately below if the transform can be handled outside the - * row loop. - */ - if (gamma_correction) - png_ptr->transformations |= PNG_GAMMA; - - else - png_ptr->transformations &= ~PNG_GAMMA; - } -#endif - - /* Certain transformations have the effect of preventing other - * transformations that happen afterward in png_do_read_transformations, - * resolve the interdependencies here. From the code of - * png_do_read_transformations the order is: - * - * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) - * 2) PNG_STRIP_ALPHA (if no compose) - * 3) PNG_RGB_TO_GRAY - * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY - * 5) PNG_COMPOSE - * 6) PNG_GAMMA - * 7) PNG_STRIP_ALPHA (if compose) - * 8) PNG_ENCODE_ALPHA - * 9) PNG_SCALE_16_TO_8 - * 10) PNG_16_TO_8 - * 11) PNG_QUANTIZE (converts to palette) - * 12) PNG_EXPAND_16 - * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY - * 14) PNG_INVERT_MONO - * 15) PNG_SHIFT - * 16) PNG_PACK - * 17) PNG_BGR - * 18) PNG_PACKSWAP - * 19) PNG_FILLER (includes PNG_ADD_ALPHA) - * 20) PNG_INVERT_ALPHA - * 21) PNG_SWAP_ALPHA - * 22) PNG_SWAP_BYTES - * 23) PNG_USER_TRANSFORM [must be last] - */ -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - if ((png_ptr->transformations & PNG_STRIP_ALPHA) && - !(png_ptr->transformations & PNG_COMPOSE)) - { - /* Stripping the alpha channel happens immediately after the 'expand' - * transformations, before all other transformation, so it cancels out - * the alpha handling. It has the side effect negating the effect of - * PNG_EXPAND_tRNS too: - */ - png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA | - PNG_EXPAND_tRNS); - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - - /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen - * so transparency information would remain just so long as it wasn't - * expanded. This produces unexpected API changes if the set of things - * that do PNG_EXPAND_tRNS changes (perfectly possible given the - * documentation - which says ask for what you want, accept what you - * get.) This makes the behavior consistent from 1.5.4: - */ - png_ptr->num_trans = 0; - } -#endif /* STRIP_ALPHA supported, no COMPOSE */ - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED - /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA - * settings will have no effect. - */ - if (!png_gamma_significant(png_ptr->screen_gamma)) - { - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - } -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - /* Make sure the coefficients for the rgb to gray conversion are set - * appropriately. - */ - if (png_ptr->transformations & PNG_RGB_TO_GRAY) - png_colorspace_set_rgb_coefficients(png_ptr); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) - /* Detect gray background and attempt to enable optimization for - * gray --> RGB case. - * - * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or - * RGB_ALPHA (in which case need_expand is superfluous anyway), the - * background color might actually be gray yet not be flagged as such. - * This is not a problem for the current code, which uses - * PNG_BACKGROUND_IS_GRAY only to decide when to do the - * png_do_gray_to_rgb() transformation. - * - * TODO: this code needs to be revised to avoid the complexity and - * interdependencies. The color type of the background should be recorded in - * png_set_background, along with the bit depth, then the code has a record - * of exactly what color space the background is currently in. - */ - if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) - { - /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if - * the file was grayscale the background value is gray. - */ - if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - } - - else if (png_ptr->transformations & PNG_COMPOSE) - { - /* PNG_COMPOSE: png_set_background was called with need_expand false, - * so the color is in the color space of the output or png_set_alpha_mode - * was called and the color is black. Ignore RGB_TO_GRAY because that - * happens before GRAY_TO_RGB. - */ - if (png_ptr->transformations & PNG_GRAY_TO_RGB) - { - if (png_ptr->background.red == png_ptr->background.green && - png_ptr->background.red == png_ptr->background.blue) - { - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - png_ptr->background.gray = png_ptr->background.red; - } - } - } -#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ -#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */ - - /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations - * can be performed directly on the palette, and some (such as rgb to gray) - * can be optimized inside the palette. This is particularly true of the - * composite (background and alpha) stuff, which can be pretty much all done - * in the palette even if the result is expanded to RGB or gray afterward. - * - * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and - * earlier and the palette stuff is actually handled on the first row. This - * leads to the reported bug that the palette returned by png_get_PLTE is not - * updated. - */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_init_palette_transformations(png_ptr); - - else - png_init_rgb_transformations(png_ptr); - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - defined(PNG_READ_EXPAND_16_SUPPORTED) - if ((png_ptr->transformations & PNG_EXPAND_16) && - (png_ptr->transformations & PNG_COMPOSE) && - !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - png_ptr->bit_depth != 16) - { - /* TODO: fix this. Because the expand_16 operation is after the compose - * handling the background color must be 8, not 16, bits deep, but the - * application will supply a 16-bit value so reduce it here. - * - * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at - * present, so that case is ok (until do_expand_16 is moved.) - * - * NOTE: this discards the low 16 bits of the user supplied background - * color, but until expand_16 works properly there is no choice! - */ -# define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x)) - CHOP(png_ptr->background.red); - CHOP(png_ptr->background.green); - CHOP(png_ptr->background.blue); - CHOP(png_ptr->background.gray); -# undef CHOP - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */ - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \ - defined(PNG_READ_STRIP_16_TO_8_SUPPORTED)) - if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) && - (png_ptr->transformations & PNG_COMPOSE) && - !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - png_ptr->bit_depth == 16) - { - /* On the other hand, if a 16-bit file is to be reduced to 8-bits per - * component this will also happen after PNG_COMPOSE and so the background - * color must be pre-expanded here. - * - * TODO: fix this too. - */ - png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257); - png_ptr->background.green = - (png_uint_16)(png_ptr->background.green * 257); - png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257); - png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257); - } -#endif - - /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the - * background support (see the comments in scripts/pnglibconf.dfa), this - * allows pre-multiplication of the alpha channel to be implemented as - * compositing on black. This is probably sub-optimal and has been done in - * 1.5.4 betas simply to enable external critique and testing (i.e. to - * implement the new API quickly, without lots of internal changes.) - */ - -#ifdef PNG_READ_GAMMA_SUPPORTED -# ifdef PNG_READ_BACKGROUND_SUPPORTED - /* Includes ALPHA_MODE */ - png_ptr->background_1 = png_ptr->background; -# endif - - /* This needs to change - in the palette image case a whole set of tables are - * built when it would be quicker to just calculate the correct value for - * each palette entry directly. Also, the test is too tricky - why check - * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that - * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the - * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction - * the gamma tables will not be built even if composition is required on a - * gamma encoded value. - * - * In 1.5.4 this is addressed below by an additional check on the individual - * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the - * tables. - */ - if ((png_ptr->transformations & PNG_GAMMA) - || ((png_ptr->transformations & PNG_RGB_TO_GRAY) - && (png_gamma_significant(png_ptr->colorspace.gamma) || - png_gamma_significant(png_ptr->screen_gamma))) - || ((png_ptr->transformations & PNG_COMPOSE) - && (png_gamma_significant(png_ptr->colorspace.gamma) - || png_gamma_significant(png_ptr->screen_gamma) -# ifdef PNG_READ_BACKGROUND_SUPPORTED - || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE - && png_gamma_significant(png_ptr->background_gamma)) -# endif - )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) - && png_gamma_significant(png_ptr->screen_gamma)) - ) - { - png_build_gamma_table(png_ptr, png_ptr->bit_depth); - -#ifdef PNG_READ_BACKGROUND_SUPPORTED - if (png_ptr->transformations & PNG_COMPOSE) - { - /* Issue a warning about this combination: because RGB_TO_GRAY is - * optimized to do the gamma transform if present yet do_background has - * to do the same thing if both options are set a - * double-gamma-correction happens. This is true in all versions of - * libpng to date. - */ - if (png_ptr->transformations & PNG_RGB_TO_GRAY) - png_warning(png_ptr, - "libpng does not support gamma+background+rgb_to_gray"); - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - /* We don't get to here unless there is a tRNS chunk with non-opaque - * entries - see the checking code at the start of this function. - */ - png_color back, back_1; - png_colorp palette = png_ptr->palette; - int num_palette = png_ptr->num_palette; - int i; - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) - { - - back.red = png_ptr->gamma_table[png_ptr->background.red]; - back.green = png_ptr->gamma_table[png_ptr->background.green]; - back.blue = png_ptr->gamma_table[png_ptr->background.blue]; - - back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; - back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; - back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; - } - else - { - png_fixed_point g, gs; - - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = (png_ptr->screen_gamma); - gs = PNG_FP_1; - break; - - case PNG_BACKGROUND_GAMMA_FILE: - g = png_reciprocal(png_ptr->colorspace.gamma); - gs = png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); - break; - - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = png_reciprocal(png_ptr->background_gamma); - gs = png_reciprocal2(png_ptr->background_gamma, - png_ptr->screen_gamma); - break; - default: - g = PNG_FP_1; /* back_1 */ - gs = PNG_FP_1; /* back */ - break; - } - - if (png_gamma_significant(gs)) - { - back.red = png_gamma_8bit_correct(png_ptr->background.red, - gs); - back.green = png_gamma_8bit_correct(png_ptr->background.green, - gs); - back.blue = png_gamma_8bit_correct(png_ptr->background.blue, - gs); - } - - else - { - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; - } - - if (png_gamma_significant(g)) - { - back_1.red = png_gamma_8bit_correct(png_ptr->background.red, - g); - back_1.green = png_gamma_8bit_correct( - png_ptr->background.green, g); - back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, - g); - } - - else - { - back_1.red = (png_byte)png_ptr->background.red; - back_1.green = (png_byte)png_ptr->background.green; - back_1.blue = (png_byte)png_ptr->background.blue; - } - } - - for (i = 0; i < num_palette; i++) - { - if (i < (int)png_ptr->num_trans && - png_ptr->trans_alpha[i] != 0xff) - { - if (png_ptr->trans_alpha[i] == 0) - { - palette[i] = back; - } - else /* if (png_ptr->trans_alpha[i] != 0xff) */ - { - png_byte v, w; - - v = png_ptr->gamma_to_1[palette[i].red]; - png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); - palette[i].red = png_ptr->gamma_from_1[w]; - - v = png_ptr->gamma_to_1[palette[i].green]; - png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); - palette[i].green = png_ptr->gamma_from_1[w]; - - v = png_ptr->gamma_to_1[palette[i].blue]; - png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); - palette[i].blue = png_ptr->gamma_from_1[w]; - } - } - else - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - - /* Prevent the transformations being done again. - * - * NOTE: this is highly dubious; it removes the transformations in - * place. This seems inconsistent with the general treatment of the - * transformations elsewhere. - */ - png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); - } /* color_type == PNG_COLOR_TYPE_PALETTE */ - - /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ - else /* color_type != PNG_COLOR_TYPE_PALETTE */ - { - int gs_sig, g_sig; - png_fixed_point g = PNG_FP_1; /* Correction to linear */ - png_fixed_point gs = PNG_FP_1; /* Correction to screen */ - - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = png_ptr->screen_gamma; - /* gs = PNG_FP_1; */ - break; - - case PNG_BACKGROUND_GAMMA_FILE: - g = png_reciprocal(png_ptr->colorspace.gamma); - gs = png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); - break; - - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = png_reciprocal(png_ptr->background_gamma); - gs = png_reciprocal2(png_ptr->background_gamma, - png_ptr->screen_gamma); - break; - - default: - png_error(png_ptr, "invalid background gamma type"); - } - - g_sig = png_gamma_significant(g); - gs_sig = png_gamma_significant(gs); - - if (g_sig) - png_ptr->background_1.gray = png_gamma_correct(png_ptr, - png_ptr->background.gray, g); - - if (gs_sig) - png_ptr->background.gray = png_gamma_correct(png_ptr, - png_ptr->background.gray, gs); - - if ((png_ptr->background.red != png_ptr->background.green) || - (png_ptr->background.red != png_ptr->background.blue) || - (png_ptr->background.red != png_ptr->background.gray)) - { - /* RGB or RGBA with color background */ - if (g_sig) - { - png_ptr->background_1.red = png_gamma_correct(png_ptr, - png_ptr->background.red, g); - - png_ptr->background_1.green = png_gamma_correct(png_ptr, - png_ptr->background.green, g); - - png_ptr->background_1.blue = png_gamma_correct(png_ptr, - png_ptr->background.blue, g); - } - - if (gs_sig) - { - png_ptr->background.red = png_gamma_correct(png_ptr, - png_ptr->background.red, gs); - - png_ptr->background.green = png_gamma_correct(png_ptr, - png_ptr->background.green, gs); - - png_ptr->background.blue = png_gamma_correct(png_ptr, - png_ptr->background.blue, gs); - } - } - - else - { - /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ - png_ptr->background_1.red = png_ptr->background_1.green - = png_ptr->background_1.blue = png_ptr->background_1.gray; - - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - } - - /* The background is now in screen gamma: */ - png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN; - } /* color_type != PNG_COLOR_TYPE_PALETTE */ - }/* png_ptr->transformations & PNG_BACKGROUND */ - - else - /* Transformation does not include PNG_BACKGROUND */ -#endif /* PNG_READ_BACKGROUND_SUPPORTED */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - /* RGB_TO_GRAY needs to have non-gamma-corrected values! */ - && ((png_ptr->transformations & PNG_EXPAND) == 0 || - (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) -#endif - ) - { - png_colorp palette = png_ptr->palette; - int num_palette = png_ptr->num_palette; - int i; - - /* NOTE: there are other transformations that should probably be in - * here too. - */ - for (i = 0; i < num_palette; i++) - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - - /* Done the gamma correction. */ - png_ptr->transformations &= ~PNG_GAMMA; - } /* color_type == PALETTE && !PNG_BACKGROUND transformation */ - } -#ifdef PNG_READ_BACKGROUND_SUPPORTED - else -#endif -#endif /* PNG_READ_GAMMA_SUPPORTED */ - -#ifdef PNG_READ_BACKGROUND_SUPPORTED - /* No GAMMA transformation (see the hanging else 4 lines above) */ - if ((png_ptr->transformations & PNG_COMPOSE) && - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) - { - int i; - int istop = (int)png_ptr->num_trans; - png_color back; - png_colorp palette = png_ptr->palette; - - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; - - for (i = 0; i < istop; i++) - { - if (png_ptr->trans_alpha[i] == 0) - { - palette[i] = back; - } - - else if (png_ptr->trans_alpha[i] != 0xff) - { - /* The png_composite() macro is defined in png.h */ - png_composite(palette[i].red, palette[i].red, - png_ptr->trans_alpha[i], back.red); - - png_composite(palette[i].green, palette[i].green, - png_ptr->trans_alpha[i], back.green); - - png_composite(palette[i].blue, palette[i].blue, - png_ptr->trans_alpha[i], back.blue); - } - } - - png_ptr->transformations &= ~PNG_COMPOSE; - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED */ - -#ifdef PNG_READ_SHIFT_SUPPORTED - if ((png_ptr->transformations & PNG_SHIFT) && - !(png_ptr->transformations & PNG_EXPAND) && - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) - { - int i; - int istop = png_ptr->num_palette; - int shift = 8 - png_ptr->sig_bit.red; - - png_ptr->transformations &= ~PNG_SHIFT; - - /* significant bits can be in the range 1 to 7 for a meaninful result, if - * the number of significant bits is 0 then no shift is done (this is an - * error condition which is silently ignored.) - */ - if (shift > 0 && shift < 8) - for (i=0; ipalette[i].red; - - component >>= shift; - png_ptr->palette[i].red = (png_byte)component; - } - - shift = 8 - png_ptr->sig_bit.green; - if (shift > 0 && shift < 8) - for (i=0; ipalette[i].green; - - component >>= shift; - png_ptr->palette[i].green = (png_byte)component; - } - - shift = 8 - png_ptr->sig_bit.blue; - if (shift > 0 && shift < 8) - for (i=0; ipalette[i].blue; - - component >>= shift; - png_ptr->palette[i].blue = (png_byte)component; - } - } -#endif /* PNG_READ_SHIFT_SUPPORTED */ -} - -/* Modify the info structure to reflect the transformations. The - * info should be updated so a PNG file could be written with it, - * assuming the transformations result in valid PNG data. - */ -void /* PRIVATE */ -png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr) -{ - png_debug(1, "in png_read_transform_info"); - -#ifdef PNG_READ_EXPAND_SUPPORTED - if (png_ptr->transformations & PNG_EXPAND) - { - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - /* This check must match what actually happens in - * png_do_expand_palette; if it ever checks the tRNS chunk to see if - * it is all opaque we must do the same (at present it does not.) - */ - if (png_ptr->num_trans > 0) - info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - - else - info_ptr->color_type = PNG_COLOR_TYPE_RGB; - - info_ptr->bit_depth = 8; - info_ptr->num_trans = 0; - } - else - { - if (png_ptr->num_trans) - { - if (png_ptr->transformations & PNG_EXPAND_tRNS) - info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; - } - if (info_ptr->bit_depth < 8) - info_ptr->bit_depth = 8; - - info_ptr->num_trans = 0; - } - } -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) - /* The following is almost certainly wrong unless the background value is in - * the screen space! - */ - if (png_ptr->transformations & PNG_COMPOSE) - info_ptr->background = png_ptr->background; -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED - /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), - * however it seems that the code in png_init_read_transformations, which has - * been called before this from png_read_update_info->png_read_start_row - * sometimes does the gamma transform and cancels the flag. - * - * TODO: this looks wrong; the info_ptr should end up with a gamma equal to - * the screen_gamma value. The following probably results in weirdness if - * the info_ptr is used by the app after the rows have been read. - */ - info_ptr->colorspace.gamma = png_ptr->colorspace.gamma; -#endif - - if (info_ptr->bit_depth == 16) - { -# ifdef PNG_READ_16BIT_SUPPORTED -# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED - if (png_ptr->transformations & PNG_SCALE_16_TO_8) - info_ptr->bit_depth = 8; -# endif - -# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED - if (png_ptr->transformations & PNG_16_TO_8) - info_ptr->bit_depth = 8; -# endif - -# else - /* No 16 bit support: force chopping 16-bit input down to 8, in this case - * the app program can chose if both APIs are available by setting the - * correct scaling to use. - */ -# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED - /* For compatibility with previous versions use the strip method by - * default. This code works because if PNG_SCALE_16_TO_8 is already - * set the code below will do that in preference to the chop. - */ - png_ptr->transformations |= PNG_16_TO_8; - info_ptr->bit_depth = 8; -# else - -# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED - png_ptr->transformations |= PNG_SCALE_16_TO_8; - info_ptr->bit_depth = 8; -# else - - CONFIGURATION ERROR: you must enable at least one 16 to 8 method -# endif -# endif -#endif /* !READ_16BIT_SUPPORTED */ - } - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED - if (png_ptr->transformations & PNG_GRAY_TO_RGB) - info_ptr->color_type = (png_byte)(info_ptr->color_type | - PNG_COLOR_MASK_COLOR); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - if (png_ptr->transformations & PNG_RGB_TO_GRAY) - info_ptr->color_type = (png_byte)(info_ptr->color_type & - ~PNG_COLOR_MASK_COLOR); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED - if (png_ptr->transformations & PNG_QUANTIZE) - { - if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || - (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && - png_ptr->palette_lookup && info_ptr->bit_depth == 8) - { - info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; - } - } -#endif - -#ifdef PNG_READ_EXPAND_16_SUPPORTED - if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 && - info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - { - info_ptr->bit_depth = 16; - } -#endif - -#ifdef PNG_READ_PACK_SUPPORTED - if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) - info_ptr->bit_depth = 8; -#endif - - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - info_ptr->channels = 1; - - else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) - info_ptr->channels = 3; - - else - info_ptr->channels = 1; - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - if (png_ptr->transformations & PNG_STRIP_ALPHA) - { - info_ptr->color_type = (png_byte)(info_ptr->color_type & - ~PNG_COLOR_MASK_ALPHA); - info_ptr->num_trans = 0; - } -#endif - - if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - info_ptr->channels++; - -#ifdef PNG_READ_FILLER_SUPPORTED - /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ - if ((png_ptr->transformations & PNG_FILLER) && - ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || - (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) - { - info_ptr->channels++; - /* If adding a true alpha channel not just filler */ - if (png_ptr->transformations & PNG_ADD_ALPHA) - info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; - } -#endif - -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ -defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - if (png_ptr->transformations & PNG_USER_TRANSFORM) - { - if (info_ptr->bit_depth < png_ptr->user_transform_depth) - info_ptr->bit_depth = png_ptr->user_transform_depth; - - if (info_ptr->channels < png_ptr->user_transform_channels) - info_ptr->channels = png_ptr->user_transform_channels; - } -#endif - - info_ptr->pixel_depth = (png_byte)(info_ptr->channels * - info_ptr->bit_depth); - - info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); - - /* Adding in 1.5.4: cache the above value in png_struct so that we can later - * check in png_rowbytes that the user buffer won't get overwritten. Note - * that the field is not always set - if png_read_update_info isn't called - * the application has to either not do any transforms or get the calculation - * right itself. - */ - png_ptr->info_rowbytes = info_ptr->rowbytes; - -#ifndef PNG_READ_EXPAND_SUPPORTED - if (png_ptr) - return; -#endif -} - -/* Transform the row. The order of transformations is significant, - * and is very touchy. If you add a transformation, take care to - * decide how it fits in with the other transformations here. - */ -void /* PRIVATE */ -png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) -{ - png_debug(1, "in png_do_read_transformations"); - - if (png_ptr->row_buf == NULL) - { - /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this - * error is incredibly rare and incredibly easy to debug without this - * information. - */ - png_error(png_ptr, "NULL row buffer"); - } - - /* The following is debugging; prior to 1.5.4 the code was never compiled in; - * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro - * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for - * all transformations, however in practice the ROW_INIT always gets done on - * demand, if necessary. - */ - if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 && - !(png_ptr->flags & PNG_FLAG_ROW_INIT)) - { - /* Application has failed to call either png_read_start_image() or - * png_read_update_info() after setting transforms that expand pixels. - * This check added to libpng-1.2.19 (but not enabled until 1.5.4). - */ - png_error(png_ptr, "Uninitialized row"); - } - -#ifdef PNG_READ_EXPAND_SUPPORTED - if (png_ptr->transformations & PNG_EXPAND) - { - if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_do_expand_palette(row_info, png_ptr->row_buf + 1, - png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); - } - - else - { - if (png_ptr->num_trans && - (png_ptr->transformations & PNG_EXPAND_tRNS)) - png_do_expand(row_info, png_ptr->row_buf + 1, - &(png_ptr->trans_color)); - - else - png_do_expand(row_info, png_ptr->row_buf + 1, - NULL); - } - } -#endif - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - if ((png_ptr->transformations & PNG_STRIP_ALPHA) && - !(png_ptr->transformations & PNG_COMPOSE) && - (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || - row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) - png_do_strip_channel(row_info, png_ptr->row_buf + 1, - 0 /* at_start == false, because SWAP_ALPHA happens later */); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - if (png_ptr->transformations & PNG_RGB_TO_GRAY) - { - int rgb_error = - png_do_rgb_to_gray(png_ptr, row_info, - png_ptr->row_buf + 1); - - if (rgb_error) - { - png_ptr->rgb_to_gray_status=1; - if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == - PNG_RGB_TO_GRAY_WARN) - png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); - - if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == - PNG_RGB_TO_GRAY_ERR) - png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); - } - } -#endif - -/* From Andreas Dilger e-mail to png-implement, 26 March 1998: - * - * In most cases, the "simple transparency" should be done prior to doing - * gray-to-RGB, or you will have to test 3x as many bytes to check if a - * pixel is transparent. You would also need to make sure that the - * transparency information is upgraded to RGB. - * - * To summarize, the current flow is: - * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite - * with background "in place" if transparent, - * convert to RGB if necessary - * - Gray + alpha -> composite with gray background and remove alpha bytes, - * convert to RGB if necessary - * - * To support RGB backgrounds for gray images we need: - * - Gray + simple transparency -> convert to RGB + simple transparency, - * compare 3 or 6 bytes and composite with - * background "in place" if transparent - * (3x compare/pixel compared to doing - * composite with gray bkgrnd) - * - Gray + alpha -> convert to RGB + alpha, composite with background and - * remove alpha bytes (3x float - * operations/pixel compared with composite - * on gray background) - * - * Greg's change will do this. The reason it wasn't done before is for - * performance, as this increases the per-pixel operations. If we would check - * in advance if the background was gray or RGB, and position the gray-to-RGB - * transform appropriately, then it would save a lot of work/time. - */ - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED - /* If gray -> RGB, do so now only if background is non-gray; else do later - * for performance reasons - */ - if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) - png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) - if (png_ptr->transformations & PNG_COMPOSE) - png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED - if ((png_ptr->transformations & PNG_GAMMA) && -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - /* Because RGB_TO_GRAY does the gamma transform. */ - !(png_ptr->transformations & PNG_RGB_TO_GRAY) && -#endif -#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) - /* Because PNG_COMPOSE does the gamma transform if there is something to - * do (if there is an alpha channel or transparency.) - */ - !((png_ptr->transformations & PNG_COMPOSE) && - ((png_ptr->num_trans != 0) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && -#endif - /* Because png_init_read_transformations transforms the palette, unless - * RGB_TO_GRAY will do the transform. - */ - (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) - png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr); -#endif - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - if ((png_ptr->transformations & PNG_STRIP_ALPHA) && - (png_ptr->transformations & PNG_COMPOSE) && - (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || - row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) - png_do_strip_channel(row_info, png_ptr->row_buf + 1, - 0 /* at_start == false, because SWAP_ALPHA happens later */); -#endif - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED - if ((png_ptr->transformations & PNG_ENCODE_ALPHA) && - (row_info->color_type & PNG_COLOR_MASK_ALPHA)) - png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr); -#endif - -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED - if (png_ptr->transformations & PNG_SCALE_16_TO_8) - png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED - /* There is no harm in doing both of these because only one has any effect, - * by putting the 'scale' option first if the app asks for scale (either by - * calling the API or in a TRANSFORM flag) this is what happens. - */ - if (png_ptr->transformations & PNG_16_TO_8) - png_do_chop(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED - if (png_ptr->transformations & PNG_QUANTIZE) - { - png_do_quantize(row_info, png_ptr->row_buf + 1, - png_ptr->palette_lookup, png_ptr->quantize_index); - - if (row_info->rowbytes == 0) - png_error(png_ptr, "png_do_quantize returned rowbytes=0"); - } -#endif /* PNG_READ_QUANTIZE_SUPPORTED */ - -#ifdef PNG_READ_EXPAND_16_SUPPORTED - /* Do the expansion now, after all the arithmetic has been done. Notice - * that previous transformations can handle the PNG_EXPAND_16 flag if this - * is efficient (particularly true in the case of gamma correction, where - * better accuracy results faster!) - */ - if (png_ptr->transformations & PNG_EXPAND_16) - png_do_expand_16(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED - /* NOTE: moved here in 1.5.4 (from much later in this list.) */ - if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) - png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_INVERT_SUPPORTED - if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_SHIFT_SUPPORTED - if (png_ptr->transformations & PNG_SHIFT) - png_do_unshift(row_info, png_ptr->row_buf + 1, - &(png_ptr->shift)); -#endif - -#ifdef PNG_READ_PACK_SUPPORTED - if (png_ptr->transformations & PNG_PACK) - png_do_unpack(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED - /* Added at libpng-1.5.10 */ - if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && - png_ptr->num_palette_max >= 0) - png_do_check_palette_indexes(png_ptr, row_info); -#endif - -#ifdef PNG_READ_BGR_SUPPORTED - if (png_ptr->transformations & PNG_BGR) - png_do_bgr(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_PACKSWAP_SUPPORTED - if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_FILLER_SUPPORTED - if (png_ptr->transformations & PNG_FILLER) - png_do_read_filler(row_info, png_ptr->row_buf + 1, - (png_uint_32)png_ptr->filler, png_ptr->flags); -#endif - -#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED - if (png_ptr->transformations & PNG_INVERT_ALPHA) - png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED - if (png_ptr->transformations & PNG_SWAP_ALPHA) - png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_16BIT_SUPPORTED -#ifdef PNG_READ_SWAP_SUPPORTED - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_do_swap(row_info, png_ptr->row_buf + 1); -#endif -#endif - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - if (png_ptr->transformations & PNG_USER_TRANSFORM) - { - if (png_ptr->read_user_transform_fn != NULL) - (*(png_ptr->read_user_transform_fn)) /* User read transform function */ - (png_ptr, /* png_ptr */ - row_info, /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_size_t rowbytes; number of bytes in row */ - /* png_byte color_type; color type of pixels */ - /* png_byte bit_depth; bit depth of samples */ - /* png_byte channels; number of channels (1-4) */ - /* png_byte pixel_depth; bits per pixel (depth*channels) */ - png_ptr->row_buf + 1); /* start of pixel data for row */ -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED - if (png_ptr->user_transform_depth) - row_info->bit_depth = png_ptr->user_transform_depth; - - if (png_ptr->user_transform_channels) - row_info->channels = png_ptr->user_transform_channels; -#endif - row_info->pixel_depth = (png_byte)(row_info->bit_depth * - row_info->channels); - - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width); - } -#endif -} - -#ifdef PNG_READ_PACK_SUPPORTED -/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, - * without changing the actual values. Thus, if you had a row with - * a bit depth of 1, you would end up with bytes that only contained - * the numbers 0 or 1. If you would rather they contain 0 and 255, use - * png_do_shift() after this. - */ -void /* PRIVATE */ -png_do_unpack(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_unpack"); - - if (row_info->bit_depth < 8) - { - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - switch (row_info->bit_depth) - { - case 1: - { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x01); - - if (shift == 7) - { - shift = 0; - sp--; - } - - else - shift++; - - dp--; - } - break; - } - - case 2: - { - - png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x03); - - if (shift == 6) - { - shift = 0; - sp--; - } - - else - shift += 2; - - dp--; - } - break; - } - - case 4: - { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x0f); - - if (shift == 4) - { - shift = 0; - sp--; - } - - else - shift = 4; - - dp--; - } - break; - } - - default: - break; - } - row_info->bit_depth = 8; - row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_width * row_info->channels; - } -} -#endif - -#ifdef PNG_READ_SHIFT_SUPPORTED -/* Reverse the effects of png_do_shift. This routine merely shifts the - * pixels back to their significant bits values. Thus, if you have - * a row of bit depth 8, but only 5 are significant, this will shift - * the values back to 0 through 31. - */ -void /* PRIVATE */ -png_do_unshift(png_row_infop row_info, png_bytep row, - png_const_color_8p sig_bits) -{ - int color_type; - - png_debug(1, "in png_do_unshift"); - - /* The palette case has already been handled in the _init routine. */ - color_type = row_info->color_type; - - if (color_type != PNG_COLOR_TYPE_PALETTE) - { - int shift[4]; - int channels = 0; - int bit_depth = row_info->bit_depth; - - if (color_type & PNG_COLOR_MASK_COLOR) - { - shift[channels++] = bit_depth - sig_bits->red; - shift[channels++] = bit_depth - sig_bits->green; - shift[channels++] = bit_depth - sig_bits->blue; - } - - else - { - shift[channels++] = bit_depth - sig_bits->gray; - } - - if (color_type & PNG_COLOR_MASK_ALPHA) - { - shift[channels++] = bit_depth - sig_bits->alpha; - } - - { - int c, have_shift; - - for (c = have_shift = 0; c < channels; ++c) - { - /* A shift of more than the bit depth is an error condition but it - * gets ignored here. - */ - if (shift[c] <= 0 || shift[c] >= bit_depth) - shift[c] = 0; - - else - have_shift = 1; - } - - if (!have_shift) - return; - } - - switch (bit_depth) - { - default: - /* Must be 1bpp gray: should not be here! */ - /* NOTREACHED */ - break; - - case 2: - /* Must be 2bpp gray */ - /* assert(channels == 1 && shift[0] == 1) */ - { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; - - while (bp < bp_end) - { - int b = (*bp >> 1) & 0x55; - *bp++ = (png_byte)b; - } - break; - } - - case 4: - /* Must be 4bpp gray */ - /* assert(channels == 1) */ - { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; - int gray_shift = shift[0]; - int mask = 0xf >> gray_shift; - - mask |= mask << 4; - - while (bp < bp_end) - { - int b = (*bp >> gray_shift) & mask; - *bp++ = (png_byte)b; - } - break; - } - - case 8: - /* Single byte components, G, GA, RGB, RGBA */ - { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; - int channel = 0; - - while (bp < bp_end) - { - int b = *bp >> shift[channel]; - if (++channel >= channels) - channel = 0; - *bp++ = (png_byte)b; - } - break; - } - -#ifdef PNG_READ_16BIT_SUPPORTED - case 16: - /* Double byte components, G, GA, RGB, RGBA */ - { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; - int channel = 0; - - while (bp < bp_end) - { - int value = (bp[0] << 8) + bp[1]; - - value >>= shift[channel]; - if (++channel >= channels) - channel = 0; - *bp++ = (png_byte)(value >> 8); - *bp++ = (png_byte)(value & 0xff); - } - break; - } -#endif - } - } -} -#endif - -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED -/* Scale rows of bit depth 16 down to 8 accurately */ -void /* PRIVATE */ -png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_scale_16_to_8"); - - if (row_info->bit_depth == 16) - { - png_bytep sp = row; /* source */ - png_bytep dp = row; /* destination */ - png_bytep ep = sp + row_info->rowbytes; /* end+1 */ - - while (sp < ep) - { - /* The input is an array of 16 bit components, these must be scaled to - * 8 bits each. For a 16 bit value V the required value (from the PNG - * specification) is: - * - * (V * 255) / 65535 - * - * This reduces to round(V / 257), or floor((V + 128.5)/257) - * - * Represent V as the two byte value vhi.vlo. Make a guess that the - * result is the top byte of V, vhi, then the correction to this value - * is: - * - * error = floor(((V-vhi.vhi) + 128.5) / 257) - * = floor(((vlo-vhi) + 128.5) / 257) - * - * This can be approximated using integer arithmetic (and a signed - * shift): - * - * error = (vlo-vhi+128) >> 8; - * - * The approximate differs from the exact answer only when (vlo-vhi) is - * 128; it then gives a correction of +1 when the exact correction is - * 0. This gives 128 errors. The exact answer (correct for all 16 bit - * input values) is: - * - * error = (vlo-vhi+128)*65535 >> 24; - * - * An alternative arithmetic calculation which also gives no errors is: - * - * (V * 255 + 32895) >> 16 - */ - - png_int_32 tmp = *sp++; /* must be signed! */ - tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24; - *dp++ = (png_byte)tmp; - } - - row_info->bit_depth = 8; - row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_info->width * row_info->channels; - } -} -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED -void /* PRIVATE */ -/* Simply discard the low byte. This was the default behavior prior - * to libpng-1.5.4. - */ -png_do_chop(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_chop"); - - if (row_info->bit_depth == 16) - { - png_bytep sp = row; /* source */ - png_bytep dp = row; /* destination */ - png_bytep ep = sp + row_info->rowbytes; /* end+1 */ - - while (sp < ep) - { - *dp++ = *sp; - sp += 2; /* skip low byte */ - } - - row_info->bit_depth = 8; - row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_info->width * row_info->channels; - } -} -#endif - -#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED -void /* PRIVATE */ -png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_read_swap_alpha"); - - { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This converts from RGBA to ARGB */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from RRGGBBAA to AARRGGBB */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } - } -#endif - } - - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This converts from GA to AG */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from GGAA to AAGG */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } - } -#endif - } - } -} -#endif - -#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED -void /* PRIVATE */ -png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) -{ - png_uint_32 row_width; - png_debug(1, "in png_do_read_invert_alpha"); - - row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This inverts the alpha channel in RGBA */ - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - -/* This does nothing: - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - We can replace it with: -*/ - sp-=3; - dp=sp; - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - /* This inverts the alpha channel in RRGGBBAA */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = (png_byte)(255 - *(--sp)); - -/* This does nothing: - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - We can replace it with: -*/ - sp-=6; - dp=sp; - } - } -#endif - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This inverts the alpha channel in GA */ - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = *(--sp); - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - else - { - /* This inverts the alpha channel in GGAA */ - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = (png_byte)(255 - *(--sp)); -/* - *(--dp) = *(--sp); - *(--dp) = *(--sp); -*/ - sp-=2; - dp=sp; - } - } -#endif - } -} -#endif - -#ifdef PNG_READ_FILLER_SUPPORTED -/* Add filler channel if we have RGB color */ -void /* PRIVATE */ -png_do_read_filler(png_row_infop row_info, png_bytep row, - png_uint_32 filler, png_uint_32 flags) -{ - png_uint_32 i; - png_uint_32 row_width = row_info->width; - -#ifdef PNG_READ_16BIT_SUPPORTED - png_byte hi_filler = (png_byte)((filler>>8) & 0xff); -#endif - png_byte lo_filler = (png_byte)(filler & 0xff); - - png_debug(1, "in png_do_read_filler"); - - if ( - row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - if (row_info->bit_depth == 8) - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This changes the data from G to GX */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 1; i < row_width; i++) - { - *(--dp) = lo_filler; - *(--dp) = *(--sp); - } - *(--dp) = lo_filler; - row_info->channels = 2; - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - - else - { - /* This changes the data from G to XG */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = lo_filler; - } - row_info->channels = 2; - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - else if (row_info->bit_depth == 16) - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This changes the data from GG to GGXX */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 1; i < row_width; i++) - { - *(--dp) = hi_filler; - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = hi_filler; - *(--dp) = lo_filler; - row_info->channels = 2; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - - else - { - /* This changes the data from GG to XXGG */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = hi_filler; - *(--dp) = lo_filler; - } - row_info->channels = 2; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - } -#endif - } /* COLOR_TYPE == GRAY */ - else if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - if (row_info->bit_depth == 8) - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This changes the data from RGB to RGBX */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 1; i < row_width; i++) - { - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = lo_filler; - row_info->channels = 4; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - - else - { - /* This changes the data from RGB to XRGB */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = lo_filler; - } - row_info->channels = 4; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - else if (row_info->bit_depth == 16) - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This changes the data from RRGGBB to RRGGBBXX */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 1; i < row_width; i++) - { - *(--dp) = hi_filler; - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = hi_filler; - *(--dp) = lo_filler; - row_info->channels = 4; - row_info->pixel_depth = 64; - row_info->rowbytes = row_width * 8; - } - - else - { - /* This changes the data from RRGGBB to XXRRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = hi_filler; - *(--dp) = lo_filler; - } - - row_info->channels = 4; - row_info->pixel_depth = 64; - row_info->rowbytes = row_width * 8; - } - } -#endif - } /* COLOR_TYPE == RGB */ -} -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -/* Expand grayscale files to RGB, with or without alpha */ -void /* PRIVATE */ -png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) -{ - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - png_debug(1, "in png_do_gray_to_rgb"); - - if (row_info->bit_depth >= 8 && - !(row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - if (row_info->bit_depth == 8) - { - /* This changes G to RGB */ - png_bytep sp = row + (png_size_t)row_width - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(dp--) = *sp; - *(dp--) = *sp; - *(dp--) = *(sp--); - } - } - - else - { - /* This changes GG to RRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; - for (i = 0; i < row_width; i++) - { - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *(sp--); - *(dp--) = *(sp--); - } - } - } - - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This changes GA to RGBA */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(dp--) = *(sp--); - *(dp--) = *sp; - *(dp--) = *sp; - *(dp--) = *(sp--); - } - } - - else - { - /* This changes GGAA to RRGGBBAA */ - png_bytep sp = row + (png_size_t)row_width * 4 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; - for (i = 0; i < row_width; i++) - { - *(dp--) = *(sp--); - *(dp--) = *(sp--); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *(sp--); - *(dp--) = *(sp--); - } - } - } - row_info->channels = (png_byte)(row_info->channels + 2); - row_info->color_type |= PNG_COLOR_MASK_COLOR; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); - } -} -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -/* Reduce RGB files to grayscale, with or without alpha - * using the equation given in Poynton's ColorFAQ of 1998-01-04 at - * (THIS LINK IS DEAD June 2008 but - * versions dated 1998 through November 2002 have been archived at - * http://web.archive.org/web/20000816232553/http://www.inforamp.net/ - * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) - * Charles Poynton poynton at poynton.com - * - * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B - * - * which can be expressed with integers as - * - * Y = (6969 * R + 23434 * G + 2365 * B)/32768 - * - * Poynton's current link (as of January 2003 through July 2011): - * - * has changed the numbers slightly: - * - * Y = 0.2126*R + 0.7152*G + 0.0722*B - * - * which can be expressed with integers as - * - * Y = (6966 * R + 23436 * G + 2366 * B)/32768 - * - * Historically, however, libpng uses numbers derived from the ITU-R Rec 709 - * end point chromaticities and the D65 white point. Depending on the - * precision used for the D65 white point this produces a variety of different - * numbers, however if the four decimal place value used in ITU-R Rec 709 is - * used (0.3127,0.3290) the Y calculation would be: - * - * Y = (6968 * R + 23435 * G + 2366 * B)/32768 - * - * While this is correct the rounding results in an overflow for white, because - * the sum of the rounded coefficients is 32769, not 32768. Consequently - * libpng uses, instead, the closest non-overflowing approximation: - * - * Y = (6968 * R + 23434 * G + 2366 * B)/32768 - * - * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk - * (including an sRGB chunk) then the chromaticities are used to calculate the - * coefficients. See the chunk handling in pngrutil.c for more information. - * - * In all cases the calculation is to be done in a linear colorspace. If no - * gamma information is available to correct the encoding of the original RGB - * values this results in an implicit assumption that the original PNG RGB - * values were linear. - * - * Other integer coefficents can be used via png_set_rgb_to_gray(). Because - * the API takes just red and green coefficients the blue coefficient is - * calculated to make the sum 32768. This will result in different rounding - * to that used above. - */ -int /* PRIVATE */ -png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) - -{ - int rgb_error = 0; - - png_debug(1, "in png_do_rgb_to_gray"); - - if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) && - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; - PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; - PNG_CONST png_uint_32 bc = 32768 - rc - gc; - PNG_CONST png_uint_32 row_width = row_info->width; - PNG_CONST int have_alpha = - (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; - - if (row_info->bit_depth == 8) - { -#ifdef PNG_READ_GAMMA_SUPPORTED - /* Notice that gamma to/from 1 are not necessarily inverses (if - * there is an overall gamma correction). Prior to 1.5.5 this code - * checked the linearized values for equality; this doesn't match - * the documentation, the original values must be checked. - */ - if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - png_byte red = *(sp++); - png_byte green = *(sp++); - png_byte blue = *(sp++); - - if (red != green || red != blue) - { - red = png_ptr->gamma_to_1[red]; - green = png_ptr->gamma_to_1[green]; - blue = png_ptr->gamma_to_1[blue]; - - rgb_error |= 1; - *(dp++) = png_ptr->gamma_from_1[ - (rc*red + gc*green + bc*blue + 16384)>>15]; - } - - else - { - /* If there is no overall correction the table will not be - * set. - */ - if (png_ptr->gamma_table != NULL) - red = png_ptr->gamma_table[red]; - - *(dp++) = red; - } - - if (have_alpha) - *(dp++) = *(sp++); - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - png_byte red = *(sp++); - png_byte green = *(sp++); - png_byte blue = *(sp++); - - if (red != green || red != blue) - { - rgb_error |= 1; - /* NOTE: this is the historical approach which simply - * truncates the results. - */ - *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); - } - - else - *(dp++) = red; - - if (have_alpha) - *(dp++) = *(sp++); - } - } - } - - else /* RGB bit_depth == 16 */ - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, w; - - red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; - green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; - - if (red == green && red == blue) - { - if (png_ptr->gamma_16_table != NULL) - w = png_ptr->gamma_16_table[(red&0xff) - >> png_ptr->gamma_shift][red>>8]; - - else - w = red; - } - - else - { - png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) - >> png_ptr->gamma_shift][red>>8]; - png_uint_16 green_1 = - png_ptr->gamma_16_to_1[(green&0xff) >> - png_ptr->gamma_shift][green>>8]; - png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) - >> png_ptr->gamma_shift][blue>>8]; - png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 - + bc*blue_1 + 16384)>>15); - w = png_ptr->gamma_16_from_1[(gray16&0xff) >> - png_ptr->gamma_shift][gray16 >> 8]; - rgb_error |= 1; - } - - *(dp++) = (png_byte)((w>>8) & 0xff); - *(dp++) = (png_byte)(w & 0xff); - - if (have_alpha) - { - *(dp++) = *(sp++); - *(dp++) = *(sp++); - } - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, gray16; - - red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; - green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; - - if (red != green || red != blue) - rgb_error |= 1; - - /* From 1.5.5 in the 16 bit case do the accurate conversion even - * in the 'fast' case - this is because this is where the code - * ends up when handling linear 16 bit data. - */ - gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> - 15); - *(dp++) = (png_byte)((gray16>>8) & 0xff); - *(dp++) = (png_byte)(gray16 & 0xff); - - if (have_alpha) - { - *(dp++) = *(sp++); - *(dp++) = *(sp++); - } - } - } - } - - row_info->channels = (png_byte)(row_info->channels - 2); - row_info->color_type = (png_byte)(row_info->color_type & - ~PNG_COLOR_MASK_COLOR); - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); - } - return rgb_error; -} -#endif -#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ - -#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED -/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth - * large of png_color. This lets grayscale images be treated as - * paletted. Most useful for gamma correction and simplification - * of code. This API is not used internally. - */ -void PNGAPI -png_build_grayscale_palette(int bit_depth, png_colorp palette) -{ - int num_palette; - int color_inc; - int i; - int v; - - png_debug(1, "in png_do_build_grayscale_palette"); - - if (palette == NULL) - return; - - switch (bit_depth) - { - case 1: - num_palette = 2; - color_inc = 0xff; - break; - - case 2: - num_palette = 4; - color_inc = 0x55; - break; - - case 4: - num_palette = 16; - color_inc = 0x11; - break; - - case 8: - num_palette = 256; - color_inc = 1; - break; - - default: - num_palette = 0; - color_inc = 0; - break; - } - - for (i = 0, v = 0; i < num_palette; i++, v += color_inc) - { - palette[i].red = (png_byte)v; - palette[i].green = (png_byte)v; - palette[i].blue = (png_byte)v; - } -} -#endif - - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) -/* Replace any alpha or transparency with the supplied background color. - * "background" is already in the screen gamma, while "background_1" is - * at a gamma of 1.0. Paletted files have already been taken care of. - */ -void /* PRIVATE */ -png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) -{ -#ifdef PNG_READ_GAMMA_SUPPORTED - png_const_bytep gamma_table = png_ptr->gamma_table; - png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; - png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; - png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; - png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; - png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; - int gamma_shift = png_ptr->gamma_shift; - int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; -#endif - - png_bytep sp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - int shift; - - png_debug(1, "in png_do_compose"); - - { - switch (row_info->color_type) - { - case PNG_COLOR_TYPE_GRAY: - { - switch (row_info->bit_depth) - { - case 1: - { - sp = row; - shift = 7; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x01) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); - tmp |= png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (!shift) - { - shift = 7; - sp++; - } - - else - shift--; - } - break; - } - - case 2: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x03; - unsigned int g = (gamma_table [p | (p << 2) | - (p << 4) | (p << 6)] >> 6) & 0x03; - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= g << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (!shift) - { - shift = 6; - sp++; - } - - else - shift -= 2; - } - } - - else -#endif - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (!shift) - { - shift = 6; - sp++; - } - - else - shift -= 2; - } - } - break; - } - - case 4: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0xf0f >> (4 - shift)); - tmp |= png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x0f; - unsigned int g = (gamma_table[p | (p << 4)] >> 4) & - 0x0f; - unsigned int tmp = *sp & (0xf0f >> (4 - shift)); - tmp |= g << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (!shift) - { - shift = 4; - sp++; - } - - else - shift -= 4; - } - } - - else -#endif - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0xf0f >> (4 - shift)); - tmp |= png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (!shift) - { - shift = 4; - sp++; - } - - else - shift -= 4; - } - } - break; - } - - case 8: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; - - else - *sp = gamma_table[*sp]; - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; - } - } - break; - } - - case 16: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } - - else - { - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } - } - } - break; - } - - default: - break; - } - break; - } - - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 3) - { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - - else - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 3) - { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - } - } - } - else /* if (row_info->bit_depth == 16) */ - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else - { - png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - } - } - - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) - { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - } - } - } - break; - } - - case PNG_COLOR_TYPE_GRAY_ALPHA: - { - if (row_info->bit_depth == 8) - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 a = *(sp + 1); - - if (a == 0xff) - *sp = gamma_table[*sp]; - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.gray; - } - - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.gray); - if (!optimize) - w = gamma_from_1[w]; - *sp = w; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_byte a = *(sp + 1); - - if (a == 0) - *sp = (png_byte)png_ptr->background.gray; - - else if (a < 0xff) - png_composite(*sp, *sp, a, png_ptr->background.gray); - } - } - } - else /* if (png_ptr->bit_depth == 16) */ - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; - - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } - - else - { - png_uint_16 g, v, w; - - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, png_ptr->background_1.gray); - if (optimize) - w = v; - else - w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } - - else if (a < 0xffff) - { - png_uint_16 g, v; - - g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, png_ptr->background.gray); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - } - } - } - break; - } - - case PNG_COLOR_TYPE_RGB_ALPHA: - { - if (row_info->bit_depth == 8) - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); - - if (a == 0xff) - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.red); - if (!optimize) w = gamma_from_1[w]; - *sp = w; - - v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, png_ptr->background_1.green); - if (!optimize) w = gamma_from_1[w]; - *(sp + 1) = w; - - v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, png_ptr->background_1.blue); - if (!optimize) w = gamma_from_1[w]; - *(sp + 2) = w; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); - - if (a == 0) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - - else if (a < 0xff) - { - png_composite(*sp, *sp, a, png_ptr->background.red); - - png_composite(*(sp + 1), *(sp + 1), a, - png_ptr->background.green); - - png_composite(*(sp + 2), *(sp + 2), a, - png_ptr->background.blue); - } - } - } - } - else /* if (row_info->bit_depth == 16) */ - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; - - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else - { - png_uint_16 v, w; - - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, png_ptr->background_1.red); - if (!optimize) - w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> - 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, png_ptr->background_1.green); - if (!optimize) - w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 2) = (png_byte)((w >> 8) & 0xff); - *(sp + 3) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, png_ptr->background_1.blue); - if (!optimize) - w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 4) = (png_byte)((w >> 8) & 0xff); - *(sp + 5) = (png_byte)(w & 0xff); - } - } - } - - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else if (a < 0xffff) - { - png_uint_16 v; - - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - png_composite_16(v, r, a, png_ptr->background.red); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - - png_composite_16(v, g, a, png_ptr->background.green); - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - png_composite_16(v, b, a, png_ptr->background.blue); - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - } - } - } - break; - } - - default: - break; - } - } -} -#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */ - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* Gamma correct the image, avoiding the alpha channel. Make sure - * you do this after you deal with the transparency issue on grayscale - * or RGB images. If your bit depth is 8, use gamma_table, if it - * is 16, use gamma_16_table and gamma_shift. Build these with - * build_gamma_table(). - */ -void /* PRIVATE */ -png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr) -{ - png_const_bytep gamma_table = png_ptr->gamma_table; - png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; - int gamma_shift = png_ptr->gamma_shift; - - png_bytep sp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_gamma"); - - if (((row_info->bit_depth <= 8 && gamma_table != NULL) || - (row_info->bit_depth == 16 && gamma_16_table != NULL))) - { - switch (row_info->color_type) - { - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - } - } - - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v; - - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - } - } - break; - } - - case PNG_COLOR_TYPE_RGB_ALPHA: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - - *sp = gamma_table[*sp]; - sp++; - - *sp = gamma_table[*sp]; - sp++; - - sp++; - } - } - - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 4; - } - } - break; - } - - case PNG_COLOR_TYPE_GRAY_ALPHA: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp += 2; - } - } - - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 4; - } - } - break; - } - - case PNG_COLOR_TYPE_GRAY: - { - if (row_info->bit_depth == 2) - { - sp = row; - for (i = 0; i < row_width; i += 4) - { - int a = *sp & 0xc0; - int b = *sp & 0x30; - int c = *sp & 0x0c; - int d = *sp & 0x03; - - *sp = (png_byte)( - ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| - ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| - ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| - ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); - sp++; - } - } - - if (row_info->bit_depth == 4) - { - sp = row; - for (i = 0; i < row_width; i += 2) - { - int msb = *sp & 0xf0; - int lsb = *sp & 0x0f; - - *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) - | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); - sp++; - } - } - - else if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - } - } - - else if (row_info->bit_depth == 16) - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - } - } - break; - } - - default: - break; - } - } -} -#endif - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED -/* Encode the alpha channel to the output gamma (the input channel is always - * linear.) Called only with color types that have an alpha channel. Needs the - * from_1 tables. - */ -void /* PRIVATE */ -png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) -{ - png_uint_32 row_width = row_info->width; - - png_debug(1, "in png_do_encode_alpha"); - - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - if (row_info->bit_depth == 8) - { - PNG_CONST png_bytep table = png_ptr->gamma_from_1; - - if (table != NULL) - { - PNG_CONST int step = - (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; - - /* The alpha channel is the last component: */ - row += step - 1; - - for (; row_width > 0; --row_width, row += step) - *row = table[*row]; - - return; - } - } - - else if (row_info->bit_depth == 16) - { - PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; - PNG_CONST int gamma_shift = png_ptr->gamma_shift; - - if (table != NULL) - { - PNG_CONST int step = - (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; - - /* The alpha channel is the last component: */ - row += step - 2; - - for (; row_width > 0; --row_width, row += step) - { - png_uint_16 v; - - v = table[*(row + 1) >> gamma_shift][*row]; - *row = (png_byte)((v >> 8) & 0xff); - *(row + 1) = (png_byte)(v & 0xff); - } - - return; - } - } - } - - /* Only get to here if called with a weird row_info; no harm has been done, - * so just issue a warning. - */ - png_warning(png_ptr, "png_do_encode_alpha: unexpected call"); -} -#endif - -#ifdef PNG_READ_EXPAND_SUPPORTED -/* Expands a palette row to an RGB or RGBA row depending - * upon whether you supply trans and num_trans. - */ -void /* PRIVATE */ -png_do_expand_palette(png_row_infop row_info, png_bytep row, - png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) -{ - int shift, value; - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_expand_palette"); - - if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (row_info->bit_depth < 8) - { - switch (row_info->bit_depth) - { - case 1: - { - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 1; - - else - *dp = 0; - - if (shift == 7) - { - shift = 0; - sp--; - } - - else - shift++; - - dp--; - } - break; - } - - case 2: - { - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)value; - if (shift == 6) - { - shift = 0; - sp--; - } - - else - shift += 2; - - dp--; - } - break; - } - - case 4: - { - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((row_width & 0x01) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)value; - if (shift == 4) - { - shift = 0; - sp--; - } - - else - shift += 4; - - dp--; - } - break; - } - - default: - break; - } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (row_info->bit_depth == 8) - { - { - if (num_trans > 0) - { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 2) - 1; - - for (i = 0; i < row_width; i++) - { - if ((int)(*sp) >= num_trans) - *dp-- = 0xff; - - else - *dp-- = trans_alpha[*sp]; - - *dp-- = palette[*sp].blue; - *dp-- = palette[*sp].green; - *dp-- = palette[*sp].red; - sp--; - } - row_info->bit_depth = 8; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - row_info->color_type = 6; - row_info->channels = 4; - } - - else - { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width * 3) - 1; - - for (i = 0; i < row_width; i++) - { - *dp-- = palette[*sp].blue; - *dp-- = palette[*sp].green; - *dp-- = palette[*sp].red; - sp--; - } - - row_info->bit_depth = 8; - row_info->pixel_depth = 24; - row_info->rowbytes = row_width * 3; - row_info->color_type = 2; - row_info->channels = 3; - } - } - } - } -} - -/* If the bit depth < 8, it is expanded to 8. Also, if the already - * expanded transparency value is supplied, an alpha channel is built. - */ -void /* PRIVATE */ -png_do_expand(png_row_infop row_info, png_bytep row, - png_const_color_16p trans_color) -{ - int shift, value; - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_expand"); - - { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - unsigned int gray = trans_color ? trans_color->gray : 0; - - if (row_info->bit_depth < 8) - { - switch (row_info->bit_depth) - { - case 1: - { - gray = (gray & 0x01) * 0xff; - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 0xff; - - else - *dp = 0; - - if (shift == 7) - { - shift = 0; - sp--; - } - - else - shift++; - - dp--; - } - break; - } - - case 2: - { - gray = (gray & 0x03) * 0x55; - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)(value | (value << 2) | (value << 4) | - (value << 6)); - if (shift == 6) - { - shift = 0; - sp--; - } - - else - shift += 2; - - dp--; - } - break; - } - - case 4: - { - gray = (gray & 0x0f) * 0x11; - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)(value | (value << 4)); - if (shift == 4) - { - shift = 0; - sp--; - } - - else - shift = 4; - - dp--; - } - break; - } - - default: - break; - } - - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (trans_color != NULL) - { - if (row_info->bit_depth == 8) - { - gray = gray & 0xff; - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 1) - 1; - - for (i = 0; i < row_width; i++) - { - if (*sp == gray) - *dp-- = 0; - - else - *dp-- = 0xff; - - *dp-- = *sp--; - } - } - - else if (row_info->bit_depth == 16) - { - unsigned int gray_high = (gray >> 8) & 0xff; - unsigned int gray_low = gray & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (row_info->rowbytes << 1) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp - 1) == gray_high && *(sp) == gray_low) - { - *dp-- = 0; - *dp-- = 0; - } - - else - { - *dp-- = 0xff; - *dp-- = 0xff; - } - - *dp-- = *sp--; - *dp-- = *sp--; - } - } - - row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; - row_info->channels = 2; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_width); - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color) - { - if (row_info->bit_depth == 8) - { - png_byte red = (png_byte)(trans_color->red & 0xff); - png_byte green = (png_byte)(trans_color->green & 0xff); - png_byte blue = (png_byte)(trans_color->blue & 0xff); - sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 2) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) - *dp-- = 0; - - else - *dp-- = 0xff; - - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - } - } - else if (row_info->bit_depth == 16) - { - png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); - png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); - png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); - png_byte red_low = (png_byte)(trans_color->red & 0xff); - png_byte green_low = (png_byte)(trans_color->green & 0xff); - png_byte blue_low = (png_byte)(trans_color->blue & 0xff); - sp = row + row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 3) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp - 5) == red_high && - *(sp - 4) == red_low && - *(sp - 3) == green_high && - *(sp - 2) == green_low && - *(sp - 1) == blue_high && - *(sp ) == blue_low) - { - *dp-- = 0; - *dp-- = 0; - } - - else - { - *dp-- = 0xff; - *dp-- = 0xff; - } - - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - } - } - row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - row_info->channels = 4; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); - } - } -} -#endif - -#ifdef PNG_READ_EXPAND_16_SUPPORTED -/* If the bit depth is 8 and the color type is not a palette type expand the - * whole row to 16 bits. Has no effect otherwise. - */ -void /* PRIVATE */ -png_do_expand_16(png_row_infop row_info, png_bytep row) -{ - if (row_info->bit_depth == 8 && - row_info->color_type != PNG_COLOR_TYPE_PALETTE) - { - /* The row have a sequence of bytes containing [0..255] and we need - * to turn it into another row containing [0..65535], to do this we - * calculate: - * - * (input / 255) * 65535 - * - * Which happens to be exactly input * 257 and this can be achieved - * simply by byte replication in place (copying backwards). - */ - png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ - png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ - while (dp > sp) - dp[-2] = dp[-1] = *--sp, dp -= 2; - - row_info->rowbytes *= 2; - row_info->bit_depth = 16; - row_info->pixel_depth = (png_byte)(row_info->channels * 16); - } -} -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -void /* PRIVATE */ -png_do_quantize(png_row_infop row_info, png_bytep row, - png_const_bytep palette_lookup, png_const_bytep quantize_lookup) -{ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_quantize"); - - if (row_info->bit_depth == 8) - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) - { - int r, g, b, p; - sp = row; - dp = row; - for (i = 0; i < row_width; i++) - { - r = *sp++; - g = *sp++; - b = *sp++; - - /* This looks real messy, but the compiler will reduce - * it down to a reasonable formula. For example, with - * 5 bits per color, we get: - * p = (((r >> 3) & 0x1f) << 10) | - * (((g >> 3) & 0x1f) << 5) | - * ((b >> 3) & 0x1f); - */ - p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & - ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << - (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | - (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & - ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << - (PNG_QUANTIZE_BLUE_BITS)) | - ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & - ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); - - *dp++ = palette_lookup[p]; - } - - row_info->color_type = PNG_COLOR_TYPE_PALETTE; - row_info->channels = 1; - row_info->pixel_depth = row_info->bit_depth; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); - } - - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && - palette_lookup != NULL) - { - int r, g, b, p; - sp = row; - dp = row; - for (i = 0; i < row_width; i++) - { - r = *sp++; - g = *sp++; - b = *sp++; - sp++; - - p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & - ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << - (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | - (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & - ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << - (PNG_QUANTIZE_BLUE_BITS)) | - ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & - ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); - - *dp++ = palette_lookup[p]; - } - - row_info->color_type = PNG_COLOR_TYPE_PALETTE; - row_info->channels = 1; - row_info->pixel_depth = row_info->bit_depth; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); - } - - else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && - quantize_lookup) - { - sp = row; - - for (i = 0; i < row_width; i++, sp++) - { - *sp = quantize_lookup[*sp]; - } - } - } -} -#endif /* PNG_READ_QUANTIZE_SUPPORTED */ -#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ - -#ifdef PNG_MNG_FEATURES_SUPPORTED -/* Undoes intrapixel differencing */ -void /* PRIVATE */ -png_do_read_intrapixel(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_read_intrapixel"); - - if ( - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - int bytes_per_pixel; - png_uint_32 row_width = row_info->width; - - if (row_info->bit_depth == 8) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 3; - - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 4; - - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff); - *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff); - } - } - else if (row_info->bit_depth == 16) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 6; - - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 8; - - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); - png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); - png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); - png_uint_32 red = (s0 + s1 + 65536) & 0xffff; - png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; - *(rp ) = (png_byte)((red >> 8) & 0xff); - *(rp + 1) = (png_byte)(red & 0xff); - *(rp + 4) = (png_byte)((blue >> 8) & 0xff); - *(rp + 5) = (png_byte)(blue & 0xff); - } - } - } -} -#endif /* PNG_MNG_FEATURES_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED */ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action"); + + if (png_ptr == NULL) + return; + + /* Tell libpng how we react to CRC errors in critical chunks */ + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + + case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ + png_warning(png_ptr, + "Can't discard critical data on CRC error"); + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + /* Tell libpng how we react to CRC errors in ancillary chunks */ + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +/* Is it OK to set a transformation now? Only if png_start_read_image or + * png_read_update_info have not been called. It is not necessary for the IHDR + * to have been read in all cases, the parameter allows for this check too. + */ +static int +png_rtran_ok(png_structrp png_ptr, int need_IHDR) +{ + if (png_ptr != NULL) + { + if (png_ptr->flags & PNG_FLAG_ROW_INIT) + png_app_error(png_ptr, + "invalid after png_start_read_image or png_read_update_info"); + + else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0) + png_app_error(png_ptr, "invalid before the PNG header has been read"); + + else + { + /* Turn on failure to initialize correctly for all transforms. */ + png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; + + return 1; /* Ok */ + } + } + + return 0; /* no png_error possible! */ +} +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS via a background color */ +void PNGFAPI +png_set_background_fixed(png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma) +{ + png_debug(1, "in png_set_background_fixed"); + + if (!png_rtran_ok(png_ptr, 0) || background_color == NULL) + return; + + if (background_gamma_code != PNG_BACKGROUND_GAMMA_SCREEN && + background_gamma_code != PNG_BACKGROUND_GAMMA_FILE && + background_gamma_code != PNG_BACKGROUND_GAMMA_UNIQUE) + { + png_app_error(png_ptr, "invalid gamma type"); + return; + } + + png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + png_ptr->background = *background_color; + png_ptr->background_gamma = background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + + if (need_expand != 0) + png_ptr->flags |= PNG_FLAG_BACKGROUND_EXPAND; + + else + png_ptr->flags &= ~PNG_FLAG_BACKGROUND_EXPAND; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_background(png_structrp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_set_background_fixed(png_ptr, background_color, background_gamma_code, + need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); +} +# endif /* FLOATING_POINT */ +#endif /* READ_BACKGROUND */ + +/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the + * one that pngrtran does first (scale) happens. This is necessary to allow the + * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. + */ +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +void PNGAPI +png_set_scale_16(png_structrp png_ptr) +{ + png_debug(1, "in png_set_scale_16"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= PNG_SCALE_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +/* Chop 16-bit depth files to 8-bit depth */ +void PNGAPI +png_set_strip_16(png_structrp png_ptr) +{ + png_debug(1, "in png_set_strip_16"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= PNG_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +void PNGAPI +png_set_strip_alpha(png_structrp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= PNG_STRIP_ALPHA; +} +#endif + +#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) +static png_fixed_point +translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma, + int is_screen) +{ + /* Check for flag values. The main reason for having the old Mac value as a + * flag is that it is pretty near impossible to work out what the correct + * value is from Apple documentation - a working Mac system is needed to + * discover the value! + */ + if (output_gamma == PNG_DEFAULT_sRGB || + output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) + { + /* If there is no sRGB support this just sets the gamma to the standard + * sRGB value. (This is a side effect of using this function!) + */ +# ifdef PNG_READ_sRGB_SUPPORTED + png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; +# else + PNG_UNUSED(png_ptr) +# endif + if (is_screen != 0) + output_gamma = PNG_GAMMA_sRGB; + else + output_gamma = PNG_GAMMA_sRGB_INVERSE; + } + + else if (output_gamma == PNG_GAMMA_MAC_18 || + output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) + { + if (is_screen != 0) + output_gamma = PNG_GAMMA_MAC_OLD; + else + output_gamma = PNG_GAMMA_MAC_INVERSE; + } + + return output_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +static png_fixed_point +convert_gamma_value(png_structrp png_ptr, double output_gamma) +{ + /* The following silently ignores cases where fixed point (times 100,000) + * gamma values are passed to the floating point API. This is safe and it + * means the fixed point constants work just fine with the floating point + * API. The alternative would just lead to undetected errors and spurious + * bug reports. Negative values fail inside the _fixed API unless they + * correspond to the flag values. + */ + if (output_gamma < 0 || output_gamma > 128) + output_gamma *= .00001; + + return png_fixed(png_ptr, output_gamma, "gamma value"); +} +# endif +#endif /* READ_ALPHA_MODE || READ_GAMMA */ + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +void PNGFAPI +png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, + png_fixed_point output_gamma) +{ + int compose = 0; + png_fixed_point file_gamma; + + png_debug(1, "in png_set_alpha_mode"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); + + /* Validate the value to ensure it is in a reasonable range. The value + * is expected to be 1 or greater, but this range test allows for some + * viewing correction values. The intent is to weed out users of this API + * who use the inverse of the gamma value accidentally! Since some of these + * values are reasonable this may have to be changed. + */ + if (output_gamma < 70000 || output_gamma > 300000) + png_error(png_ptr, "output gamma out of expected range"); + + /* The default file gamma is the inverse of the output gamma; the output + * gamma may be changed below so get the file value first: + */ + file_gamma = png_reciprocal(output_gamma); + + /* There are really 8 possibilities here, composed of any combination + * of: + * + * premultiply the color channels + * do not encode non-opaque pixels + * encode the alpha as well as the color channels + * + * The differences disappear if the input/output ('screen') gamma is 1.0, + * because then the encoding is a no-op and there is only the choice of + * premultiplying the color channels or not. + * + * png_set_alpha_mode and png_set_background interact because both use + * png_compose to do the work. Calling both is only useful when + * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along + * with a default gamma value. Otherwise PNG_COMPOSE must not be set. + */ + switch (mode) + { + case PNG_ALPHA_PNG: /* default: png standard */ + /* No compose, but it may be set by png_set_background! */ + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + break; + + case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */ + compose = 1; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + /* The output is linear: */ + output_gamma = PNG_FP_1; + break; + + case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */ + compose = 1; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; + /* output_gamma records the encoding of opaque pixels! */ + break; + + case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */ + compose = 1; + png_ptr->transformations |= PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + break; + + default: + png_error(png_ptr, "invalid alpha mode"); + } + + /* Only set the default gamma if the file gamma has not been set (this has + * the side effect that the gamma in a second call to png_set_alpha_mode will + * be ignored.) + */ + if (png_ptr->colorspace.gamma == 0) + { + png_ptr->colorspace.gamma = file_gamma; + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; + } + + /* But always set the output gamma: */ + png_ptr->screen_gamma = output_gamma; + + /* Finally, if pre-multiplying, set the background fields to achieve the + * desired result. + */ + if (compose != 0) + { + /* And obtain alpha pre-multiplication by composing on black: */ + memset(&png_ptr->background, 0, (sizeof png_ptr->background)); + png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */ + png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; + png_ptr->flags &= ~PNG_FLAG_BACKGROUND_EXPAND; + + if (png_ptr->transformations & PNG_COMPOSE) + png_error(png_ptr, + "conflicting calls to set alpha mode and background"); + + png_ptr->transformations |= PNG_COMPOSE; + } +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma) +{ + png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, + output_gamma)); +} +# endif +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Dither file to 8-bit. Supply a palette, the current number + * of elements in the palette, the maximum number of elements + * allowed, and a histogram if possible. If the current number + * of colors is greater then the maximum number, the palette will be + * modified to fit in the maximum number. "full_quantize" indicates + * whether we need a quantizing cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort * png_dsortp; +typedef png_dsort * * png_dsortpp; + +void PNGAPI +png_set_quantize(png_structrp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize) +{ + png_debug(1, "in png_set_quantize"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= PNG_QUANTIZE; + + if (full_quantize == 0) + { + int i; + + png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * (sizeof (png_byte)))); + for (i = 0; i < num_palette; i++) + png_ptr->quantize_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + * Perhaps not the best solution, but good enough. + */ + + int i; + + /* Initialize an array to sort colors */ + png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * (sizeof (png_byte)))); + + /* Initialize the quantize_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->quantize_sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + * bubble sort, and running it until we have sorted + * out enough colors. Note that we don't care about + * sorting all the colors, just finding which are + * least used. + */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* To stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->quantize_sort[j]] + < histogram[png_ptr->quantize_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->quantize_sort[j]; + png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; + png_ptr->quantize_sort[j + 1] = t; + done = 0; + } + } + + if (done != 0) + break; + } + + /* Swap the palette around, and set up a table, if necessary */ + if (full_quantize != 0) + { + int j = num_palette; + + /* Put all the useful colors within the max, but don't + * move the others. + */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* Move all the used colors inside the max limit, and + * develop a translation table. + */ + for (i = 0; i < maximum_colors; i++) + { + /* Only move the colors we need to */ + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* Indicate where the color went */ + png_ptr->quantize_index[j] = (png_byte)i; + png_ptr->quantize_index[i] = (png_byte)j; + } + } + + /* Find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->quantize_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* Find the closest color to one we threw out */ + d_index = png_ptr->quantize_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* Point to closest color */ + png_ptr->quantize_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->quantize_sort); + png_ptr->quantize_sort = NULL; + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + * we need to go through a median cut routine, but those + * don't always behave themselves with only a few colors + * as input. So we will just find the closest two colors, + * and throw out one of them (chosen somewhat randomly). + * [We don't understand this at all, so if someone wants to + * work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; + + t = NULL; + + /* Initialize palette index arrays */ + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * (sizeof (png_byte)))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * (sizeof (png_byte)))); + + /* Initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + (sizeof (png_dsortp)))); + + num_new_palette = num_palette; + + /* Initial wild guess at how far apart the farthest pixel + * pair we will be eliminating will be. Larger + * numbers mean more areas will be allocated, Smaller + * numbers run the risk of not saving enough data, and + * having to do this all over again. + * + * I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(sizeof (png_dsort))); + + if (t == NULL) + break; + + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } + + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (full_quantize == 0) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->quantize_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[next_j]; + + if ((int)png_ptr->quantize_index[k] == + num_new_palette) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[j]; + } + } + + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; + + png_ptr->index_to_palette[j] = + (png_byte)num_new_palette; + + png_ptr->palette_to_index[num_new_palette] = + (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index = NULL; + png_ptr->index_to_palette = NULL; + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_quantize != 0) + { + int i; + png_bytep distance; + int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + + PNG_QUANTIZE_BLUE_BITS; + int num_red = (1 << PNG_QUANTIZE_RED_BITS); + int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); + int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + + png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, + (png_uint_32)(num_entries * (sizeof (png_byte)))); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + (sizeof (png_byte)))); + + memset(distance, 0xff, num_entries * (sizeof (png_byte))); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + /* int dr = abs(ir - r); */ + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS + + PNG_QUANTIZE_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + /* int dg = abs(ig - g); */ + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + /* int db = abs(ib - b); */ + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +void PNGFAPI +png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma, + png_fixed_point file_gamma) +{ + png_debug(1, "in png_set_gamma_fixed"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + /* New in libpng-1.5.4 - reserve particular negative values as flags. */ + scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); + file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); + + /* Checking the gamma values for being >0 was added in 1.5.4 along with the + * premultiplied alpha support; this actually hides an undocumented feature + * of the previous implementation which allowed gamma processing to be + * disabled in background handling. There is no evidence (so far) that this + * was being used; however, png_set_background itself accepted and must still + * accept '0' for the gamma value it takes, because it isn't always used. + * + * Since this is an API change (albeit a very minor one that removes an + * undocumented API feature) the following checks were only enabled in + * libpng-1.6.0. + */ + if (file_gamma <= 0) + png_error(png_ptr, "invalid file gamma in png_set_gamma"); + + if (scrn_gamma <= 0) + png_error(png_ptr, "invalid screen gamma in png_set_gamma"); + + /* Set the gamma values unconditionally - this overrides the value in the PNG + * file if a gAMA chunk was present. png_set_alpha_mode provides a + * different, easier, way to default the file gamma. + */ + png_ptr->colorspace.gamma = file_gamma; + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; + png_ptr->screen_gamma = scrn_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma) +{ + png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), + convert_gamma_value(png_ptr, file_gamma)); +} +# endif /* FLOATING_POINT_SUPPORTED */ +#endif /* READ_GAMMA */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structrp png_ptr) +{ + png_debug(1, "in png_set_expand"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + * + * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified + * to expand only the sample depth but not to expand the tRNS to alpha + * and its name was changed to png_set_expand_gray_1_2_4_to_8(). + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structrp png_ptr) +{ + png_debug(1, "in png_set_palette_to_rgb"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +} + +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr) +{ + png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= PNG_EXPAND; +} + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structrp png_ptr) +{ + png_debug(1, "in png_set_tRNS_to_alpha"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); +} +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise + * it may not work correctly.) + */ +void PNGAPI +png_set_expand_16(png_structrp png_ptr) +{ + png_debug(1, "in png_set_expand_16"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +void PNGAPI +png_set_gray_to_rgb(png_structrp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb"); + + if (!png_rtran_ok(png_ptr, 0)) + return; + + /* Because rgb must be 8 bits or more: */ + png_set_expand_gray_1_2_4_to_8(png_ptr); + png_ptr->transformations |= PNG_GRAY_TO_RGB; +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +void PNGFAPI +png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray"); + + /* Need the IHDR here because of the check on color_type below. */ + /* TODO: fix this */ + if (!png_rtran_ok(png_ptr, 1)) + return; + + switch(error_action) + { + case PNG_ERROR_ACTION_NONE: + png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + + case PNG_ERROR_ACTION_WARN: + png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + + case PNG_ERROR_ACTION_ERROR: + png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + break; + + default: + png_error(png_ptr, "invalid error action to rgb_to_gray"); + break; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#ifdef PNG_READ_EXPAND_SUPPORTED + png_ptr->transformations |= PNG_EXPAND; +#else + { + /* Make this an error in 1.6 because otherwise the application may assume + * that it just worked and get a memory overwrite. + */ + png_error(png_ptr, + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); + + /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */ + } +#endif + { + if (red >= 0 && green >= 0 && red + green <= PNG_FP_1) + { + png_uint_16 red_int, green_int; + + /* NOTE: this calculation does not round, but this behavior is retained + * for consistency, the inaccuracy is very small. The code here always + * overwrites the coefficients, regardless of whether they have been + * defaulted or set already. + */ + red_int = (png_uint_16)(((png_uint_32)red*32768)/100000); + green_int = (png_uint_16)(((png_uint_32)green*32768)/100000); + + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; +# if defined(PNG_COLORS_SPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) + png_ptr->colorspace.flags |= PNG_COLORSPACE_RGB_TO_GRAY_SET; +# endif + } + + else + { + if (red >= 0 && green >= 0) + png_app_warning(png_ptr, + "ignoring out of range rgb_to_gray coefficients"); + + /* Use the defaults, from the cHRM chunk if set, else the historical + * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See + * png_do_rgb_to_gray for more discussion of the values. In this case + * the coefficients are not marked as 'set' and are not overwritten if + * something has already provided a default. + */ + if (png_ptr->rgb_to_gray_red_coeff == 0 && + png_ptr->rgb_to_gray_green_coeff == 0) + { + png_ptr->rgb_to_gray_red_coeff = 6968; + png_ptr->rgb_to_gray_green_coeff = 23434; + /* png_ptr->rgb_to_gray_blue_coeff = 2366; */ + } + } + } +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red, + double green) +{ + png_set_rgb_to_gray_fixed(png_ptr, error_action, + png_fixed(png_ptr, red, "rgb to gray red coefficient"), + png_fixed(png_ptr, green, "rgb to gray green coefficient")); +} +#endif /* FLOATING POINT */ + +#endif /* RGB_TO_GRAY */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn"); + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +} +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +#ifdef PNG_READ_GAMMA_SUPPORTED +/* In the case of gamma transformations only do transformations on images where + * the [file] gamma and screen_gamma are not close reciprocals, otherwise it + * slows things down slightly, and also needlessly introduces small errors. + */ +static int /* PRIVATE */ +png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) +{ + /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma + * correction as a difference of the overall transform from 1.0 + * + * We want to compare the threshold with s*f - 1, if we get + * overflow here it is because of wacky gamma values so we + * turn on processing anyway. + */ + png_fixed_point gtest; + return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) || + png_gamma_significant(gtest); +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) +static void +gamma_correct_background(unsigned int value, unsigned int depth, + png_uint_16p backgroundp, png_uint_16p background_1p, + png_fixed_point gamma_correct, png_fixed_point gamma_to_1) +{ + switch (depth) + { + case 8: + if (gamma_correct != PNG_FP_1) + *backgroundp = png_gamma_8bit_correct(value, gamma_correct); + + else + *backgroundp = (png_uint_16)value; + + if (gamma_to_1 != PNG_FP_1) + *background_1p = png_gamma_16bit_correct(value*257, gamma_to_1); + + else + *background_1p = (png_uint_16)(value*257); + + return; + + case 16: + if (gamma_correct != PNG_FP_1) + *backgroundp = png_gamma_16bit_correct(value, gamma_correct); + + else + *backgroundp = (png_uint_16)value; + + if (gamma_to_1 != PNG_FP_1) + *background_1p = png_gamma_16bit_correct(value, gamma_to_1); + + else + *background_1p = (png_uint_16)value; + + return; + + default: + /* Low bit depth gray levels; do no harm. */ + break; + } + + *backgroundp = (png_uint_16)value; + *background_1p = 0; /* should not be used */ +} + +static void /* PRIVATE */ +png_init_background_transformations(png_structrp png_ptr) + /* Set the png_ptr->background and png_ptr->background_1 members correctly + * for the bit depth and format. + */ +{ + /* png_ptr->background is only assigned by png_set_background and + * png_set_alpha_mode (which just zeros out the fields.) png_set_background + * can set the PNG_FLAG_BACKGROUND_EXPAND flag if the input value is in the + * file format, for example if it comes from a bKGD chunk. + * + * Under some circumstances deficiencies in the current libpng code mean that + * the bit depth of the values must differ from the final bit depth; the bit + * depth has to match that at which the processing of the image pixels + * happens and this is not always the final bit depth. This is fixed up + * here. + * + * First find the required depth. + */ + unsigned int bit_depth, required_bit_depth; + unsigned int color_type = png_ptr->color_type; + const png_uint_32 transform = png_ptr->transformations; + const int expand = (png_ptr->flags & PNG_FLAG_BACKGROUND_EXPAND) != 0; + + if (color_type & PNG_COLOR_MASK_PALETTE) + required_bit_depth = bit_depth = 8; + + else + { + required_bit_depth = bit_depth = png_ptr->bit_depth; + + /* But not PNG_EXPAND_16 at present because it happens after the compose + * operation where the background is used! + */ + if (bit_depth < 8 && (transform & PNG_EXPAND) != 0) + required_bit_depth = 8; + } + + /* bit_depth and color_type now refer to the original file data and + * required_bit_depth is correct for the processing libpng does, however it + * does not necessarily match the output the application gets, fix that and + * the color type here: + */ + if (expand == 0) + { + /* The background bit_depth and color_type need correcting */ + if ((transform & PNG_EXPAND) != 0) + color_type &= ~PNG_COLOR_MASK_PALETTE; + + /* The RGB<->gray transformations do the to gray operation first, then the + * from gray. + */ + if ((transform & PNG_RGB_TO_GRAY) != 0) + color_type &= ~PNG_COLOR_MASK_COLOR; + + if ((transform & PNG_GRAY_TO_RGB) != 0) + color_type |= PNG_COLOR_MASK_COLOR; + + bit_depth = required_bit_depth; + + /* The expansion to 16 bits and the scaling back from 16 bits per + * component to only 8 happens after the background processing (at + * present) so these transforms only affect the screen value, not the + * required value. Note that the 16_TO_8 conversions happen before the 8 + * to 16 one, so in theory both could occur - the order of the tests below + * must be correct! + * + * TODO: Note that the second of these changes cause an input 16-bit + * background value to be temporarily crushed to 8-bits per component, + * losing precision. This is a bug and should be fixed. + */ + if (bit_depth == 16 && + (transform & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0) + bit_depth = 8; + + if (bit_depth == 8 && (color_type & PNG_COLOR_MASK_PALETTE) == 0 && + (transform & PNG_EXPAND_16) != 0) + bit_depth = 16; + } + + /* Now make the background have the correct format. This involves reading the + * correct fields from png_ptr->background, adjusting the bit depth of the + * result and potentially gamma correcting the value then calculating the + * png_ptr->background_1 values too. + */ + { + unsigned int mult = 1; + png_fixed_point gamma_to_1, gamma_correct; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + gamma_to_1 = png_ptr->screen_gamma; + gamma_correct = PNG_FP_1; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + gamma_to_1 = png_reciprocal(png_ptr->colorspace.gamma); + gamma_correct = png_reciprocal2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + gamma_to_1 = png_reciprocal(png_ptr->background_gamma); + gamma_correct = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + + default: + gamma_to_1 = PNG_FP_1; + gamma_correct = PNG_FP_1; + break; + } + +# define CORRECT(v, c)\ + gamma_correct_background((v)*mult, bit_depth,\ + &png_ptr->background.c, &png_ptr->background_1.c,\ + gamma_correct, gamma_to_1);\ + if (bit_depth > required_bit_depth)\ + png_ptr->background.c =\ + (png_uint_16)PNG_DIV257(png_ptr->background.c) + + /* The multiplier 'mult' scales the values to 'required_depth', + * 'bit_depth' is the depth of the resultant values. + */ + while (bit_depth < required_bit_depth) + mult += mult << bit_depth, bit_depth <<= 1; + + /* In the event that this still leaves the background bit depth greater + * than the libpng required depth scale the values back to the 8-bit + * range, the test below verifies that this is correct. + */ + if (bit_depth > required_bit_depth) + { + if (bit_depth != 16 || required_bit_depth != 8) + png_error(png_ptr, "internal error handling background depth"); + } + + if ((color_type & PNG_COLOR_MASK_COLOR) != 0) + { + png_ptr->flags &= ~PNG_FLAG_BACKGROUND_IS_GRAY; /* checked below */ + + /* If need_expand was passed to png_set_background the background value + * was in the file format, therefore if the file is a palette file the + * background will have been an index into the palette. Notice that if + * need_expand was false then the color is RGB even if the output still + * has a palette. + */ + if (expand && (color_type & PNG_COLOR_MASK_PALETTE) != 0) + { + unsigned int background_index = png_ptr->background.index; + + if (background_index < png_ptr->num_palette && + png_ptr->palette != NULL) + { + /* In fact 'mult' is always 1 at present in this case */ + CORRECT(png_ptr->palette[background_index].red, red); + CORRECT(png_ptr->palette[background_index].green, green); + CORRECT(png_ptr->palette[background_index].blue, blue); + } + + else + { + png_app_error(png_ptr, "out of range background index"); + memset(&png_ptr->background, 0, sizeof png_ptr->background); + memset(&png_ptr->background_1, 0, sizeof png_ptr->background_1); + } + } + + else + { + CORRECT(png_ptr->background.red, red); + CORRECT(png_ptr->background.green, green); + CORRECT(png_ptr->background.blue, blue); + } + + if (png_ptr->background.red == png_ptr->background.blue && + png_ptr->background.red == png_ptr->background.green) + { + png_ptr->flags |= PNG_FLAG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + png_ptr->background_1.gray = png_ptr->background_1.red; + } + + else + png_ptr->background.gray = png_ptr->background_1.gray = 0; + } + + else + { + png_ptr->flags |= PNG_FLAG_BACKGROUND_IS_GRAY; + + CORRECT(png_ptr->background.gray, gray); + + png_ptr->background.red = + png_ptr->background.green = + png_ptr->background.blue = png_ptr->background.gray; + + png_ptr->background_1.red = + png_ptr->background_1.green = + png_ptr->background_1.blue = png_ptr->background_1.gray; + } +# undef CORRECT + } +} +#endif /* READ_BACKGROUND || READ_ALPHA_MODE */ + +static void /* PRIVATE */ +png_init_palette_transformations(png_structrp png_ptr) +{ + int input_has_alpha = 0; + int input_has_transparency = 0; + + if (png_ptr->num_trans > 0) + { + int i; + + /* Ignore if all the entries are opaque (unlikely!) */ + for (i=0; inum_trans; ++i) + { + if (png_ptr->trans_alpha[i] == 255) + continue; + else if (png_ptr->trans_alpha[i] == 0) + input_has_transparency = 1; + else + { + input_has_transparency = 1; + input_has_alpha = 1; + break; + } + } + } + + /* If no alpha we can optimize. */ + if (input_has_alpha == 0) + { + /* Any alpha means background and associative alpha processing is + * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA + * and ENCODE_ALPHA are irrelevant. + */ + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + if (input_has_transparency == 0) + png_ptr->transformations &= ~PNG_COMPOSE; + } +} + +static void /* PRIVATE */ +png_init_rgb_transformations(png_structrp png_ptr) +{ + /* Added to libpng-1.5.4: check the color type to determine whether there + * is any alpha or transparency in the image and simply cancel the + * background and alpha mode stuff if there isn't. + */ + int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; + int input_has_transparency = png_ptr->num_trans > 0; + + /* If no alpha we can optimize. */ + if (input_has_alpha == 0) + { + /* Any alpha means background and associative alpha processing is + * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA + * and ENCODE_ALPHA are irrelevant. + */ +# ifdef PNG_READ_ALPHA_MODE_SUPPORTED + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; +# endif + + if (input_has_transparency == 0) + png_ptr->transformations &= ~PNG_COMPOSE; + } +} + +void /* PRIVATE */ +png_init_read_transformations(png_structrp png_ptr) +{ + png_debug(1, "in png_init_read_transformations"); + + /* This internal function is called from png_read_start_row in pngrutil.c + * and it is called before the 'rowbytes' calculation is done, so the code + * in here can change or update the transformations flags. + * + * First do updates that do not depend on the details of the PNG image data + * being processed. + */ + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds + * png_set_alpha_mode and this is another source for a default file gamma so + * the test needs to be performed later - here. In addition prior to 1.5.4 + * the tests were repeated for the PALETTE color type here - this is no + * longer necessary (and doesn't seem to have been necessary before.) + */ + { + /* The following temporary indicates if overall gamma correction is + * required. + */ + int gamma_correction = 0; + + if (png_ptr->colorspace.gamma != 0) /* has been set */ + { + if (png_ptr->screen_gamma != 0) /* screen set too */ + gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma, + png_ptr->screen_gamma); + + else + /* Assume the output matches the input; a long time default behavior + * of libpng, although the standard has nothing to say about this. + */ + png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma); + } + + else if (png_ptr->screen_gamma != 0) + /* The converse - assume the file matches the screen, note that this + * perhaps undesireable default can (from 1.5.4) be changed by calling + * png_set_alpha_mode (even if the alpha handling mode isn't required + * or isn't changed from the default.) + */ + png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma); + + else /* neither are set */ + /* Just in case the following prevents any processing - file and screen + * are both assumed to be linear and there is no way to introduce a + * third gamma value other than png_set_background with 'UNIQUE', and, + * prior to 1.5.4 + */ + png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1; + + /* We have a gamma value now. */ + png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; + + /* Now turn the gamma transformation on or off as appropriate. Notice + * that PNG_GAMMA just refers to the file->screen correction. Alpha + * composition may independently cause gamma correction because it needs + * linear data (e.g. if the file has a gAMA chunk but the screen gamma + * hasn't been specified.) In any case this flag may get turned off in + * the code immediately below if the transform can be handled outside the + * row loop. + */ + if (gamma_correction != 0) + png_ptr->transformations |= PNG_GAMMA; + + else + png_ptr->transformations &= ~PNG_GAMMA; + } +#endif + + /* Certain transformations have the effect of preventing other + * transformations that happen afterward in png_do_read_transformations, + * resolve the interdependencies here. From the code of + * png_do_read_transformations the order is: + * + * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) + * 2) PNG_STRIP_ALPHA (if no compose) + * 3) PNG_RGB_TO_GRAY + * 4) PNG_GRAY_TO_RGB iff !PNG_FLAG_BACKGROUND_IS_GRAY + * 5) PNG_COMPOSE + * 6) PNG_GAMMA + * 7) PNG_STRIP_ALPHA (if compose) + * 8) PNG_ENCODE_ALPHA + * 9) PNG_SCALE_16_TO_8 + * 10) PNG_16_TO_8 + * 11) PNG_QUANTIZE (converts to palette) + * 12) PNG_EXPAND_16 + * 13) PNG_GRAY_TO_RGB iff PNG_FLAG_BACKGROUND_IS_GRAY + * 14) PNG_INVERT_MONO + * 15) PNG_INVERT_ALPHA + * 16) PNG_SHIFT + * 17) PNG_PACK + * 18) PNG_BGR + * 19) PNG_PACKSWAP + * 20) PNG_FILLER (includes PNG_ADD_ALPHA) + * 21) PNG_SWAP_ALPHA + * 22) PNG_SWAP_BYTES + * 23) PNG_USER_TRANSFORM [must be last] + */ +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_STRIP_ALPHA) + { + if (!(png_ptr->transformations & PNG_FILLER)) + png_ptr->transformations &= ~(PNG_INVERT_ALPHA|PNG_SWAP_ALPHA); + + if (!(png_ptr->transformations & PNG_COMPOSE)) + { + /* Stripping the alpha channel happens immediately after the 'expand' + * transformations, before all other transformations, so it cancels out + * the alpha handling. It has the side effect negating the effect of + * PNG_EXPAND_tRNS too: + */ + png_ptr->transformations &= ~(PNG_ENCODE_ALPHA | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen + * so transparency information would remain just so long as it wasn't + * expanded. This produces unexpected API changes if the set of things + * that do PNG_EXPAND_tRNS changes (perfectly possible given the + * documentation - which says ask for what you want, accept what you + * get.) This makes the behavior consistent from 1.5.4: + */ + png_ptr->num_trans = 0; + } + } +#endif /* STRIP_ALPHA supported, no COMPOSE */ + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA + * settings will have no effect. + */ + if (!png_gamma_significant(png_ptr->screen_gamma)) + { + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + } +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* Make sure the coefficients for the rgb to gray conversion are set + * appropriately. + */ + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + png_colorspace_set_rgb_coefficients(png_ptr); +#endif + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_init_palette_transformations(png_ptr); + + else + png_init_rgb_transformations(png_ptr); + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + /* Set up the background information if required. It is only used if + * PNG_COMPOSE is specified. + */ + if (png_ptr->transformations & PNG_COMPOSE) + png_init_background_transformations(png_ptr); +#endif + + /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations + * can be performed directly on the palette, and some (such as rgb to gray) + * can be optimized inside the palette. This is particularly true of the + * composite (background and alpha) stuff, which can be pretty much all done + * in the palette even if the result is expanded to RGB or gray afterward. + * + * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and + * earlier and the palette stuff is actually handled on the first row. This + * leads to the reported bug that the palette returned by png_get_PLTE is not + * updated. + */ +#if 0 /* NYI */ + png_do_palette_transformations(png_ptr); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* This needs to change - in the palette image case a whole set of tables are + * built when it would be quicker to just calculate the correct value for + * each palette entry directly. Also, the test is too tricky - why check + * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that + * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the + * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction + * the gamma tables will not be built even if composition is required on a + * gamma encoded value. + * + * In 1.5.4 this is addressed below by an additional check on the individual + * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the + * tables. + */ + if ((png_ptr->transformations & PNG_GAMMA) + || ((png_ptr->transformations & PNG_RGB_TO_GRAY) + && (png_gamma_significant(png_ptr->colorspace.gamma) || + png_gamma_significant(png_ptr->screen_gamma))) + || ((png_ptr->transformations & PNG_COMPOSE) + && (png_gamma_significant(png_ptr->colorspace.gamma) + || png_gamma_significant(png_ptr->screen_gamma) +# ifdef PNG_READ_BACKGROUND_SUPPORTED + || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE + && png_gamma_significant(png_ptr->background_gamma)) +# endif + )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) + && png_gamma_significant(png_ptr->screen_gamma)) + ) + { + png_build_gamma_tables(png_ptr, png_ptr->bit_depth); + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_COMPOSE) + { + /* Issue a warning about this combination: because RGB_TO_GRAY is + * optimized to do the gamma transform if present yet do_background has + * to do the same thing if both options are set a + * double-gamma-correction happens. This is true in all versions of + * libpng to date. + */ + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + png_warning(png_ptr, + "libpng does not support gamma+background+rgb_to_gray"); + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + unsigned int i, num_palette = png_ptr->num_palette; + png_color back; + png_color_16 back_1 = png_ptr->background_1; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < num_palette; i++) + { + if (i < png_ptr->num_trans && png_ptr->trans_alpha[i] != 0xff) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans_alpha[i] != 0xff) */ + { + png_uint_16 v, w; + unsigned int alpha = png_ptr->trans_alpha[i] * 257U; + unsigned int shift = png_ptr->gamma_shift; + unsigned int add = (shift > 0 ? 1U<<(shift-1) : 0); + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite_16(w, v, alpha, back_1.red); + palette[i].red = png_ptr->gamma_from_1[(w+add)>>shift]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite_16(w, v, alpha, back_1.green); + palette[i].green = png_ptr->gamma_from_1[(w+add)>>shift]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite_16(w, v, alpha, back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[(w+add)>>shift]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + + /* Prevent the transformations being done again. + * + * NOTE: this is highly dubious; it removes the transformations in + * place. This seems inconsistent with the general treatment of the + * transformations elsewhere. + */ + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); + } /* color_type == PNG_COLOR_TYPE_PALETTE */ + }/* png_ptr->transformations & PNG_BACKGROUND */ + + else + /* Transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* RGB_TO_GRAY needs to have non-gamma-corrected values! */ + && ((png_ptr->transformations & PNG_EXPAND) == 0 || + (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) +#endif + ) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + /* NOTE: there are other transformations that should probably be in + * here too. + */ + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + + /* Done the gamma correction. */ + png_ptr->transformations &= ~PNG_GAMMA; + } /* color_type == PALETTE && !PNG_BACKGROUND transformation */ + } +#ifdef PNG_READ_BACKGROUND_SUPPORTED + else +#endif +#endif /* PNG_READ_GAMMA_SUPPORTED */ + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + /* No GAMMA transformation (see the hanging else 4 lines above) */ + if ((png_ptr->transformations & PNG_COMPOSE) && + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + + else if (png_ptr->trans_alpha[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans_alpha[i], back.red); + + png_composite(palette[i].green, palette[i].green, + png_ptr->trans_alpha[i], back.green); + + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans_alpha[i], back.blue); + } + } + + png_ptr->transformations &= ~PNG_COMPOSE; + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#ifdef PNG_READ_SHIFT_SUPPORTED + if ((png_ptr->transformations & PNG_SHIFT) && + !(png_ptr->transformations & PNG_EXPAND) && + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = png_ptr->num_palette; + int shift = 8 - png_ptr->sig_bit.red; + + png_ptr->transformations &= ~PNG_SHIFT; + + /* significant bits can be in the range 1 to 7 for a meaninful result, if + * the number of significant bits is 0 then no shift is done (this is an + * error condition which is silently ignored.) + */ + if (shift > 0 && shift < 8) + for (i=0; ipalette[i].red; + + component >>= shift; + png_ptr->palette[i].red = (png_byte)component; + } + + shift = 8 - png_ptr->sig_bit.green; + if (shift > 0 && shift < 8) + for (i=0; ipalette[i].green; + + component >>= shift; + png_ptr->palette[i].green = (png_byte)component; + } + + shift = 8 - png_ptr->sig_bit.blue; + if (shift > 0 && shift < 8) + for (i=0; ipalette[i].blue; + + component >>= shift; + png_ptr->palette[i].blue = (png_byte)component; + } + } +#endif /* PNG_READ_SHIFT_SUPPORTED */ +} + +/* Modify the info structure to reflect the transformations. The + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr) +{ + png_debug(1, "in png_read_transform_info"); + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + /* This check must match what actually happens in + * png_do_expand_palette; if it ever checks the tRNS chunk to see if + * it is all opaque we must do the same (at present it does not.) + */ + if (png_ptr->num_trans > 0) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + + if (png_ptr->palette == NULL) + png_error (png_ptr, "Palette is NULL in indexed image"); + } + else + { + if (png_ptr->num_trans) + { + if (png_ptr->transformations & PNG_EXPAND_tRNS) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + + info_ptr->num_trans = 0; + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + /* The following is almost certainly wrong unless the background value is in + * the screen space! + */ + if (png_ptr->transformations & PNG_COMPOSE) + info_ptr->background = png_ptr->background; +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), + * however it seems that the code in png_init_read_transformations, which has + * been called before this from png_read_update_info->png_read_start_row + * sometimes does the gamma transform and cancels the flag. + * + * TODO: this looks wrong; the info_ptr should end up with a gamma equal to + * the screen_gamma value. The following probably results in weirdness if + * the info_ptr is used by the app after the rows have been read. + */ + info_ptr->colorspace.gamma = png_ptr->colorspace.gamma; +#endif + + if (info_ptr->bit_depth == 16) + { +# ifdef PNG_READ_16BIT_SUPPORTED +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_SCALE_16_TO_8) + info_ptr->bit_depth = 8; +# endif + +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_16_TO_8) + info_ptr->bit_depth = 8; +# endif + +# else + /* No 16 bit support: force chopping 16-bit input down to 8, in this case + * the app program can chose if both APIs are available by setting the + * correct scaling to use. + */ +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* For compatibility with previous versions use the strip method by + * default. This code works because if PNG_SCALE_16_TO_8 is already + * set the code below will do that in preference to the chop. + */ + png_ptr->transformations |= PNG_16_TO_8; + info_ptr->bit_depth = 8; +# else + +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + png_ptr->transformations |= PNG_SCALE_16_TO_8; + info_ptr->bit_depth = 8; +# else + + CONFIGURATION ERROR: you must enable at least one 16 to 8 method +# endif +# endif +#endif /* !READ_16BIT_SUPPORTED */ + } + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type = (png_byte)(info_ptr->color_type | + PNG_COLOR_MASK_COLOR); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type = (png_byte)(info_ptr->color_type & + ~PNG_COLOR_MASK_COLOR); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 && + info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + info_ptr->bit_depth = 16; + } +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + + else + info_ptr->channels = 1; + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_STRIP_ALPHA) + { + info_ptr->color_type = (png_byte)(info_ptr->color_type & + ~PNG_COLOR_MASK_ALPHA); + info_ptr->num_trans = 0; + } +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#ifdef PNG_READ_FILLER_SUPPORTED + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; + /* If adding a true alpha channel not just filler */ + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + + if (info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); + + /* Adding in 1.5.4: cache the above value in png_struct so that we can later + * check in png_rowbytes that the user buffer won't get overwritten. Note + * that the field is not always set - if png_read_update_info isn't called + * the application has to either not do any transforms or get the calculation + * right itself. + */ + png_ptr->info_rowbytes = info_ptr->rowbytes; + +#ifndef PNG_READ_EXPAND_SUPPORTED + if (png_ptr != NULL) + return; +#endif +} + +#ifdef PNG_READ_PACK_SUPPORTED +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +static void +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack"); + + if (row_info->bit_depth < 8) + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +static void +png_do_unshift(png_row_infop row_info, png_bytep row, + png_const_color_8p sig_bits) +{ + int color_type; + + png_debug(1, "in png_do_unshift"); + + /* The palette case has already been handled in the _init routine. */ + color_type = row_info->color_type; + + if (color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int bit_depth = row_info->bit_depth; + + if (color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = bit_depth - sig_bits->red; + shift[channels++] = bit_depth - sig_bits->green; + shift[channels++] = bit_depth - sig_bits->blue; + } + + else + { + shift[channels++] = bit_depth - sig_bits->gray; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = bit_depth - sig_bits->alpha; + } + + { + int c, have_shift; + + for (c = have_shift = 0; c < channels; ++c) + { + /* A shift of more than the bit depth is an error condition but it + * gets ignored here. + */ + if (shift[c] <= 0 || shift[c] >= bit_depth) + shift[c] = 0; + + else + have_shift = 1; + } + + if (have_shift == 0) + return; + } + + switch (bit_depth) + { + default: + /* Must be 1bpp gray: should not be here! */ + /* NOTREACHED */ + break; + + case 2: + /* Must be 2bpp gray */ + /* assert(channels == 1 && shift[0] == 1) */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + + while (bp < bp_end) + { + int b = (*bp >> 1) & 0x55; + *bp++ = (png_byte)b; + } + break; + } + + case 4: + /* Must be 4bpp gray */ + /* assert(channels == 1) */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + int gray_shift = shift[0]; + int mask = 0xf >> gray_shift; + + mask |= mask << 4; + + while (bp < bp_end) + { + int b = (*bp >> gray_shift) & mask; + *bp++ = (png_byte)b; + } + break; + } + + case 8: + /* Single byte components, G, GA, RGB, RGBA */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + int channel = 0; + + while (bp < bp_end) + { + int b = *bp >> shift[channel]; + if (++channel >= channels) + channel = 0; + *bp++ = (png_byte)b; + } + break; + } + +#ifdef PNG_READ_16BIT_SUPPORTED + case 16: + /* Double byte components, G, GA, RGB, RGBA */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + int channel = 0; + + while (bp < bp_end) + { + int value = (bp[0] << 8) + bp[1]; + + value >>= shift[channel]; + if (++channel >= channels) + channel = 0; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale rows of bit depth 16 down to 8 accurately */ +static void +png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_scale_16_to_8"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; /* source */ + png_bytep dp = row; /* destination */ + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + + while (sp < ep) + { + /* The input is an array of 16 bit components, these must be scaled to + * 8 bits each. For a 16 bit value V the required value (from the PNG + * specification) is: + * + * (V * 255) / 65535 + * + * This reduces to round(V / 257), or floor((V + 128.5)/257) + * + * Represent V as the two byte value vhi.vlo. Make a guess that the + * result is the top byte of V, vhi, then the correction to this value + * is: + * + * error = floor(((V-vhi.vhi) + 128.5) / 257) + * = floor(((vlo-vhi) + 128.5) / 257) + * + * This can be approximated using integer arithmetic (and a signed + * shift): + * + * error = (vlo-vhi+128) >> 8; + * + * The approximate differs from the exact answer only when (vlo-vhi) is + * 128; it then gives a correction of +1 when the exact correction is + * 0. This gives 128 errors. The exact answer (correct for all 16 bit + * input values) is: + * + * error = (vlo-vhi+128)*65535 >> 24; + * + * An alternative arithmetic calculation which also gives no errors is: + * + * (V * 255 + 32895) >> 16 + */ + + png_int_32 tmp = *sp++; /* must be signed! */ + tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24; + *dp++ = (png_byte)tmp; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +static void +/* Simply discard the low byte. This was the default behavior prior + * to libpng-1.5.4. + */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; /* source */ + png_bytep dp = row; /* destination */ + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + + while (sp < ep) + { + *dp++ = *sp; + sp += 2; /* skip low byte */ + } + + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +static void +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha"); + + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } +#endif + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +static void +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_uint_32 row_width; + png_debug(1, "in png_do_read_invert_alpha"); + + row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } +#endif + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } +#endif + } +} +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED +/* Add filler channel if we have RGB color */ +static void +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + +#ifdef PNG_READ_16BIT_SUPPORTED + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); +#endif + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler"); + + if ( + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from G to GX */ + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + + else + { + /* This changes the data from G to XG */ + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from GG to GGXX */ + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + + else + { + /* This changes the data from GG to XXGG */ + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } +#endif + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RGB to RGBX */ + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + + else + { + /* This changes the data from RGB to XRGB */ + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + + else + { + /* This changes the data from RRGGBB to XXRRGGBB */ + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } +#endif + } /* COLOR_TYPE == RGB */ +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand grayscale files to RGB, with or without alpha */ +static void +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb"); + + if (row_info->bit_depth >= 8 && + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + /* This changes G to RGB */ + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + + else + { + /* This changes GG to RRGGBB */ + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This changes GA to RGBA */ + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + + else + { + /* This changes GGAA to RRGGBBAA */ + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels = (png_byte)(row_info->channels + 2); + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ of 1998-01-04 at + * (THIS LINK IS DEAD June 2008 but + * versions dated 1998 through November 2002 have been archived at + * http://web.archive.org/web/20000816232553/http://www.inforamp.net/ + * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) + * Charles Poynton poynton at poynton.com + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * Poynton's current link (as of January 2003 through July 2011): + * + * has changed the numbers slightly: + * + * Y = 0.2126*R + 0.7152*G + 0.0722*B + * + * which can be expressed with integers as + * + * Y = (6966 * R + 23436 * G + 2366 * B)/32768 + * + * Historically, however, libpng uses numbers derived from the ITU-R Rec 709 + * end point chromaticities and the D65 white point. Depending on the + * precision used for the D65 white point this produces a variety of different + * numbers, however if the four decimal place value used in ITU-R Rec 709 is + * used (0.3127,0.3290) the Y calculation would be: + * + * Y = (6968 * R + 23435 * G + 2366 * B)/32768 + * + * While this is correct the rounding results in an overflow for white, because + * the sum of the rounded coefficients is 32769, not 32768. Consequently + * libpng uses, instead, the closest non-overflowing approximation: + * + * Y = (6968 * R + 23434 * G + 2366 * B)/32768 + * + * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk + * (including an sRGB chunk) then the chromaticities are used to calculate the + * coefficients. See the chunk handling in pngrutil.c for more information. + * + * In all cases the calculation is to be done in a linear colorspace. If no + * gamma information is available to correct the encoding of the original RGB + * values this results in an implicit assumption that the original PNG RGB + * values were linear. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). Because + * the API takes just red and green coefficients the blue coefficient is + * calculated to make the sum 32768. This will result in different rounding + * to that used above. + */ +static int +png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) + +{ + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray"); + + if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) && + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + PNG_CONST png_uint_32 bc = 32768 - rc - gc; + PNG_CONST png_uint_32 row_width = row_info->width; + PNG_CONST int have_alpha = + (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; + + if (row_info->bit_depth == 8) + { + /* Notice that gamma to/from 1 are not necessarily inverses (if + * there is an overall gamma correction). Prior to 1.5.5 this code + * checked the linearized values for equality; this doesn't match + * the documentation, the original values must be checked. + */ + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + PNG_CONST unsigned int shift = 15 + png_ptr->gamma_shift; + PNG_CONST png_uint_32 add = 1U << (shift-1); + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + unsigned int red = *(sp++); + unsigned int green = *(sp++); + unsigned int blue = *(sp++); + + if (red != green || red != blue) + { + red = png_ptr->gamma_to_1[red]; + green = png_ptr->gamma_to_1[green]; + blue = png_ptr->gamma_to_1[blue]; + + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red + gc*green + bc*blue + add)>>shift]; + } + + else + { + /* If there is no overall correction the table will not be + * set. + */ + if (png_ptr->gamma_table != NULL) + red = png_ptr->gamma_table[red]; + + *(dp++) = (png_byte)red; + } + + if (have_alpha != 0) + *(dp++) = *(sp++); + } + } + + else + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red+gc*green+bc*blue+16384)>>15); + } + + else + *(dp++) = red; + + if (have_alpha != 0) + *(dp++) = *(sp++); + } + } + } + + else /* RGB bit_depth == 16 */ + { + if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL) + { + unsigned int shift = png_ptr->gamma_shift; + unsigned int add = (shift > 0 ? (1U << (shift-1)) : 0); + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red == green && red == blue) + { + if (png_ptr->gamma_16_table != NULL) + w = png_ptr->gamma_16_table[(red+add) >> shift]; + + else + w = red; + } + + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red+add) + >> shift]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green+add) + >> shift]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue+add) + >> shift]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1 + 16384)>>15); + w = png_ptr->gamma_16_from_1[(gray16+add) >> shift]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + + if (have_alpha != 0) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + } + } + } + + else + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red != green || red != blue) + rgb_error |= 1; + + /* From 1.5.5 in the 16 bit case do the accurate conversion even + * in the 'fast' case - this is because this is where the code + * ends up when handling linear 16 bit data. + */ + gray16 = (png_uint_16)((rc*red+gc*green+bc*blue+16384) >> 15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + + if (have_alpha != 0) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + } + } + } + } + + row_info->channels = (png_byte)(row_info->channels - 2); + row_info->color_type = (png_byte)(row_info->color_type & + ~PNG_COLOR_MASK_COLOR); + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + return rgb_error; +} +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* Replace any alpha or transparency with the supplied background color. + * "background" is already in the screen gamma, while "background_1" is + * at a gamma of 1.0. Paletted files have already been taken care of. + */ +static void +png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) +{ + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; + png_const_uint_16p gamma_to_1 = png_ptr->gamma_to_1; + png_const_uint_16p gamma_16 = png_ptr->gamma_16_table; + png_const_uint_16p gamma_16_from_1 = png_ptr->gamma_16_from_1; + png_const_uint_16p gamma_16_to_1 = png_ptr->gamma_16_to_1; + PNG_CONST unsigned int shift = png_ptr->gamma_shift; + PNG_CONST unsigned int add = (shift > 0 ? 1U<<(shift-1) : 0); + PNG_CONST int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; + + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_compose"); + + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + int bit_shift = 7; + sp = row; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> bit_shift) & 0x01) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x7f7f >> (7 - bit_shift)); + tmp |= png_ptr->background.gray << bit_shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (bit_shift == 0) + { + bit_shift = 7; + sp++; + } + + else + bit_shift--; + } + break; + } + + case 2: + { +#if 0 + if (gamma_table != NULL) + { + int bit_shift = 6; + sp = row; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> bit_shift) & 0x03) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x3f3f >> (6 - bit_shift)); + tmp |= png_ptr->background.gray << bit_shift; + *sp = (png_byte)(tmp & 0xff); + } + + else + { + unsigned int p = (*sp >> bit_shift) & 0x03; + unsigned int g = (gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03; + unsigned int tmp = *sp & (0x3f3f >> (6 - bit_shift)); + tmp |= g << bit_shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (bit_shift == 0) + { + bit_shift = 6; + sp++; + } + + else + bit_shift -= 2; + } + } + + else +#endif + { + int bit_shift = 6; + sp = row; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> bit_shift) & 0x03) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x3f3f >> (6 - bit_shift)); + tmp |= png_ptr->background.gray << bit_shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (bit_shift == 0) + { + bit_shift = 6; + sp++; + } + + else + bit_shift -= 2; + } + } + break; + } + + case 4: + { +#if 0 + if (gamma_table != NULL) + { + int bit_shift = 4; + sp = row; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> bit_shift) & 0x0f) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0xf0f >> (4 - bit_shift)); + tmp |= png_ptr->background.gray << bit_shift; + *sp = (png_byte)(tmp & 0xff); + } + + else + { + unsigned int p = (*sp >> bit_shift) & 0x0f; + unsigned int g = (gamma_table[p | (p << 4)] >> 4) & + 0x0f; + unsigned int tmp = *sp & (0xf0f >> (4 - bit_shift)); + tmp |= g << bit_shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (bit_shift == 0) + { + bit_shift = 4; + sp++; + } + + else + bit_shift -= 4; + } + } + + else +#endif + { + int bit_shift = 4; + sp = row; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> bit_shift) & 0x0f) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0xf0f >> (4 - bit_shift)); + tmp |= png_ptr->background.gray << bit_shift; + *sp = (png_byte)(tmp & 0xff); + } + + if (bit_shift == 0) + { + bit_shift = 4; + sp++; + } + + else + bit_shift -= 4; + } + } + break; + } + + case 8: + { + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; + + else + *sp = gamma_table[*sp]; + } + } + + else + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; + } + } + break; + } + + case 16: + { + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == png_ptr->trans_color.gray) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); + } + + else + { + v = gamma_16[(v+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + + else + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == png_ptr->trans_color.gray) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); + } + } + } + break; + } + + default: + break; + } + break; + } + + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + + else + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v = gamma_16[(r+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[(g+add) >> shift]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[(b+add) >> shift]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + + else + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *sp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.gray; + } + + else + { + unsigned int v, w; + + v = gamma_to_1[*sp]; + png_composite_16(w, v, 257*a, + png_ptr->background_1.gray); + + if (optimize == 0) + w = gamma_from_1[(w+add)>>shift]; + + else /* alpha pixels linear and approximate */ + w = PNG_DIV257(w); + + *sp = (png_byte)w; + } + } + } + + else + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_byte a = *(sp + 1); + + if (a == 0) + *sp = (png_byte)png_ptr->background.gray; + + else if (a < 0xff) + png_composite(*sp, *sp, a, png_ptr->background.gray); + } + } + } + + else /* if (png_ptr->bit_depth == 16) */ + { + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[((sp[0]<<8)+sp[1]+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[((sp[0]<<8)+sp[1]+add) >> shift]; + png_composite_16(v, g, a, png_ptr->background_1.gray); + + if (optimize == 0) + w = gamma_16_from_1[(v+add) >> shift]; + + else + w = v; + + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + } + } + } + + else + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, png_ptr->background.gray); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else + { + unsigned int v, w; + unsigned int alpha = a * 257U; + + v = gamma_to_1[*sp]; + png_composite_16(w, v, alpha, + png_ptr->background_1.red); + + if (optimize == 0) + w = gamma_from_1[(w+add)>>shift]; + + else + w = PNG_DIV257(w); + + *sp = (png_byte)w; + + v = gamma_to_1[*(sp + 1)]; + png_composite_16(w, v, alpha, + png_ptr->background_1.green); + + if (optimize == 0) + w = gamma_from_1[(w+add)>>shift]; + + else + w = PNG_DIV257(w); + + *(sp + 1) = (png_byte)w; + + v = gamma_to_1[*(sp + 2)]; + png_composite_16(w, v, alpha, + png_ptr->background_1.blue); + + if (optimize == 0) + w = gamma_from_1[(w+add)>>shift]; + + else + w = PNG_DIV257(w); + + *(sp + 2) = (png_byte)w; + } + } + } + + else + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else if (a < 0xff) + { + png_composite(*sp, *sp, a, png_ptr->background.red); + + png_composite(*(sp + 1), *(sp + 1), a, + png_ptr->background.green); + + png_composite(*(sp + 2), *(sp + 2), a, + png_ptr->background.blue); + } + } + } + } + + else /* if (row_info->bit_depth == 16) */ + { + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[((sp[0]<<8)+sp[1]+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[((sp[2]<<8)+sp[3]+add) >> shift]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[((sp[4]<<8)+sp[5]+add) >> shift]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v, w; + + v = gamma_16_to_1[((sp[0]<<8)+sp[1]+add) >> shift]; + png_composite_16(w, v, a, png_ptr->background_1.red); + + if (optimize == 0) + w = gamma_16_from_1[(w+add) >> shift]; + + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[((sp[2]<<8)+sp[3]+add) >> shift]; + png_composite_16(w, v, a, png_ptr->background_1.green); + + if (optimize == 0) + w = gamma_16_from_1[(w+add) >> shift]; + + *(sp + 2) = (png_byte)((w >> 8) & 0xff); + *(sp + 3) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[((sp[4]<<8)+sp[5]+add) >> shift]; + png_composite_16(w, v, a, png_ptr->background_1.blue); + + if (optimize == 0) + w = gamma_16_from_1[(w+add) >> shift]; + + *(sp + 4) = (png_byte)((w >> 8) & 0xff); + *(sp + 5) = (png_byte)(w & 0xff); + } + } + } + + else + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, png_ptr->background.red); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + png_composite_16(v, g, a, png_ptr->background.green); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + png_composite_16(v, b, a, png_ptr->background.blue); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + + default: + break; + } + } +} +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * build_gamma_table(). + */ +static void +png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr) +{ + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_uint_16p gamma_16_table = png_ptr->gamma_16_table; + int shift = png_ptr->gamma_shift; + int add = (shift > 0 ? 1U << (shift-1) : 0); + + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma"); + + /* Prior to libpng 1.7.0 this code would attempt to gamma correct 2 and 4 bit + * gray level values, the results are ridiculously inaccurate. In 1.7.0 the + * code is removed and a warning is introduced to catch cases where an + * application might actually try it. + */ + if (((row_info->bit_depth == 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + + *sp = gamma_table[*sp]; + sp++; + + *sp = gamma_table[*sp]; + sp++; + + sp++; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + + else /*row_info->bit_depth == 16 */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + default: + break; + } + } +} +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* Encode the alpha channel to the output gamma (the input channel is always + * linear.) Called only with color types that have an alpha channel. Needs the + * from_1 tables. + */ +static void +png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) +{ + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_encode_alpha"); + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + PNG_CONST unsigned int shift = png_ptr->gamma_shift; + PNG_CONST unsigned int add = (shift > 0 ? 1U<<(shift-1) : 0); + + if (row_info->bit_depth == 8) + { + PNG_CONST png_bytep gamma_from_1 = png_ptr->gamma_from_1; + + if (gamma_from_1 != NULL) + { + PNG_CONST int step = + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; + + /* The alpha channel is the last component: */ + row += step - 1; + + for (; row_width > 0; --row_width, row += step) + *row = gamma_from_1[(257U**row+add)>>shift]; + + return; + } + } + + else if (row_info->bit_depth == 16) + { + PNG_CONST png_uint_16p gamma_16_from_1 = png_ptr->gamma_16_from_1; + + if (gamma_16_from_1 != NULL) + { + PNG_CONST int step = + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; + + /* The alpha channel is the last component: */ + row += step - 2; + + for (; row_width > 0; --row_width, row += step) + { + png_uint_16 v; + + v = gamma_16_from_1[((row[0]<<8)+row[1]+add) >> shift]; + *row = (png_byte)((v >> 8) & 0xff); + *(row + 1) = (png_byte)(v & 0xff); + } + + return; + } + } + } + + /* Only get to here if called with a weird row_info; no harm has been done, + * so just issue a warning. + */ + png_warning(png_ptr, "png_do_encode_alpha: unexpected call"); +} +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expands a palette row to an RGB or RGBA row depending + * upon whether you supply trans and num_trans. + */ +static void +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette"); + + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + + else + *dp = 0; + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift += 4; + + dp--; + } + break; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (row_info->bit_depth == 8) + { + { + if (num_trans > 0) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + + else + *dp-- = trans_alpha[*sp]; + + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the already + * expanded transparency value is supplied, an alpha channel is built. + */ +static void +png_do_expand(png_row_infop row_info, png_bytep row, + png_const_color_16p trans_color) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + unsigned int gray = trans_color ? trans_color->gray : 0; + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (gray & 0x01) * 0xff; + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + + else + *dp = 0; + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + gray = (gray & 0x03) * 0x55; + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + gray = (gray & 0x0f) * 0x11; + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_color != NULL) + { + if (row_info->bit_depth == 8) + { + gray = gray & 0xff; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + } + } + + else if (row_info->bit_depth == 16) + { + unsigned int gray_high = (gray >> 8) & 0xff; + unsigned int gray_low = gray & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 1) == gray_high && *(sp) == gray_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + } + } + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color) + { + if (row_info->bit_depth == 8) + { + png_byte red = (png_byte)(trans_color->red & 0xff); + png_byte green = (png_byte)(trans_color->green & 0xff); + png_byte blue = (png_byte)(trans_color->blue & 0xff); + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_color->red & 0xff); + png_byte green_low = (png_byte)(trans_color->green & 0xff); + png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* If the bit depth is 8 and the color type is not a palette type expand the + * whole row to 16 bits. Has no effect otherwise. + */ +static void +png_do_expand_16(png_row_infop row_info, png_bytep row) +{ + if (row_info->bit_depth == 8 && + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + /* The row have a sequence of bytes containing [0..255] and we need + * to turn it into another row containing [0..65535], to do this we + * calculate: + * + * (input / 255) * 65535 + * + * Which happens to be exactly input * 257 and this can be achieved + * simply by byte replication in place (copying backwards). + */ + png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ + png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ + while (dp > sp) + dp[-2] = dp[-1] = *--sp, dp -= 2; + + row_info->rowbytes *= 2; + row_info->bit_depth = 16; + row_info->pixel_depth = (png_byte)(row_info->channels * 16); + } +} +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +static void +png_do_quantize(png_row_infop row_info, png_bytep row, + png_const_bytep palette_lookup, png_const_bytep quantize_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_quantize"); + + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* This looks real messy, but the compiler will reduce + * it down to a reasonable formula. For example, with + * 5 bits per color, we get: + * p = (((r >> 3) & 0x1f) << 10) | + * (((g >> 3) & 0x1f) << 5) | + * ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + quantize_lookup) + { + sp = row; + + for (i = 0; i < row_width; i++, sp++) + { + *sp = quantize_lookup[*sp]; + } + } + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) +{ + png_debug(1, "in png_do_read_transformations"); + + if (png_ptr->row_buf == NULL) + { + /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this + * error is incredibly rare and incredibly easy to debug without this + * information. + */ + png_error(png_ptr, "NULL row buffer"); + } + + /* The following is debugging; prior to 1.5.4 the code was never compiled in; + * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro + * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for + * all transformations, however in practice the ROW_INIT always gets done on + * demand, if necessary. + */ + if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 && + !(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + /* Application has failed to call either png_read_start_image() or + * png_read_update_info() after setting transforms that expand pixels. + * This check added to libpng-1.2.19 (but not enabled until 1.5.4). + */ + png_error(png_ptr, "Uninitialized row"); + } + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(row_info, png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); + } + + else + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + png_do_expand(row_info, png_ptr->row_buf + 1, + &(png_ptr->trans_color)); + + else + png_do_expand(row_info, png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + !(png_ptr->transformations & PNG_COMPOSE) && + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_do_strip_channel(row_info, png_ptr->row_buf + 1, + 0 /* at_start == false, because SWAP_ALPHA happens later */); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, row_info, + png_ptr->row_buf + 1); + + if (rgb_error != 0) + { + png_ptr->rgb_to_gray_status=1; + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* From Andreas Dilger e-mail to png-implement, 26 March 1998: + * + * In most cases, the "simple transparency" should be done prior to doing + * gray-to-RGB, or you will have to test 3x as many bytes to check if a + * pixel is transparent. You would also need to make sure that the + * transparency information is upgraded to RGB. + * + * To summarize, the current flow is: + * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + * with background "in place" if transparent, + * convert to RGB if necessary + * - Gray + alpha -> composite with gray background and remove alpha bytes, + * convert to RGB if necessary + * + * To support RGB backgrounds for gray images we need: + * - Gray + simple transparency -> convert to RGB + simple transparency, + * compare 3 or 6 bytes and composite with + * background "in place" if transparent + * (3x compare/pixel compared to doing + * composite with gray bkgrnd) + * - Gray + alpha -> convert to RGB + alpha, composite with background and + * remove alpha bytes (3x float + * operations/pixel compared with composite + * on gray background) + * + * Greg's change will do this. The reason it wasn't done before is for + * performance, as this increases the per-pixel operations. If we would check + * in advance if the background was gray or RGB, and position the gray-to-RGB + * transform appropriately, then it would save a lot of work/time. + */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* If gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons + */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + !(png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + if (png_ptr->transformations & PNG_COMPOSE) + png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if ((png_ptr->transformations & PNG_GAMMA) && +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* Because RGB_TO_GRAY does the gamma transform. */ + !(png_ptr->transformations & PNG_RGB_TO_GRAY) && +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + /* Because PNG_COMPOSE does the gamma transform if there is something to + * do (if there is an alpha channel or transparency.) + */ + !((png_ptr->transformations & PNG_COMPOSE) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + /* Because png_init_read_transformations transforms the palette, unless + * RGB_TO_GRAY will do the transform. + */ + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + (png_ptr->transformations & PNG_COMPOSE) && + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_do_strip_channel(row_info, png_ptr->row_buf + 1, + 0 /* at_start == false, because SWAP_ALPHA happens later */); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + if ((png_ptr->transformations & PNG_ENCODE_ALPHA) && + (row_info->color_type & PNG_COLOR_MASK_ALPHA)) + png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_SCALE_16_TO_8) + png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* There is no harm in doing both of these because only one has any effect, + * by putting the 'scale' option first if the app asks for scale (either by + * calling the API or in a TRANSFORM flag) this is what happens. + */ + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + png_do_quantize(row_info, png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->quantize_index); + + if (row_info->rowbytes == 0) + png_error(png_ptr, "png_do_quantize returned rowbytes=0"); + } +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_16_SUPPORTED + /* Do the expansion now, after all the arithmetic has been done. Notice + * that previous transformations can handle the PNG_EXPAND_16 flag if this + * is efficient (particularly true in the case of gamma correction, where + * better accuracy results faster!) + */ + if (png_ptr->transformations & PNG_EXPAND_16) + png_do_expand_16(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* NOTE: moved here in 1.5.4 (from much later in this list.) */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(row_info, png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED + /* Added at libpng-1.5.10 */ + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + png_ptr->num_palette_max >= 0) + png_do_check_palette_indexes(png_ptr, row_info); +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(row_info, png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_16BIT_SUPPORTED +#ifdef PNG_READ_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(row_info, png_ptr->row_buf + 1); +#endif +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* User read transform function */ + (png_ptr, /* png_ptr */ + row_info, /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + if (png_ptr->user_transform_depth) + row_info->bit_depth = png_ptr->user_transform_depth; + + if (png_ptr->user_transform_channels) + row_info->channels = png_ptr->user_transform_channels; +#endif + row_info->pixel_depth = (png_byte)(row_info->bit_depth * + row_info->channels); + + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width); + } +#endif +} +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/ext/libpng16/pngrutil.c b/ext/libpng17/pngrutil.c similarity index 94% rename from ext/libpng16/pngrutil.c rename to ext/libpng17/pngrutil.c index fd65c21879..2a9fc896bf 100644 --- a/ext/libpng16/pngrutil.c +++ b/ext/libpng17/pngrutil.c @@ -1,4475 +1,4450 @@ - -/* pngrutil.c - utilities to read a PNG file - * - * Last changed in libpng 1.6.7 [November 14, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - * This file contains routines that are only called from within - * libpng itself during the course of reading an image. - */ - -#include "pngpriv.h" - -#ifdef PNG_READ_SUPPORTED - -png_uint_32 PNGAPI -png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf) -{ - png_uint_32 uval = png_get_uint_32(buf); - - if (uval > PNG_UINT_31_MAX) - png_error(png_ptr, "PNG unsigned integer out of range"); - - return (uval); -} - -#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) -/* The following is a variation on the above for use with the fixed - * point values used for gAMA and cHRM. Instead of png_error it - * issues a warning and returns (-1) - an invalid value because both - * gAMA and cHRM use *unsigned* integers for fixed point values. - */ -#define PNG_FIXED_ERROR (-1) - -static png_fixed_point /* PRIVATE */ -png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf) -{ - png_uint_32 uval = png_get_uint_32(buf); - - if (uval <= PNG_UINT_31_MAX) - return (png_fixed_point)uval; /* known to be in range */ - - /* The caller can turn off the warning by passing NULL. */ - if (png_ptr != NULL) - png_warning(png_ptr, "PNG fixed point integer out of range"); - - return PNG_FIXED_ERROR; -} -#endif - -#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED -/* NOTE: the read macros will obscure these definitions, so that if - * PNG_USE_READ_MACROS is set the library will not use them internally, - * but the APIs will still be available externally. - * - * The parentheses around "PNGAPI function_name" in the following three - * functions are necessary because they allow the macros to co-exist with - * these (unused but exported) functions. - */ - -/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ -png_uint_32 (PNGAPI -png_get_uint_32)(png_const_bytep buf) -{ - png_uint_32 uval = - ((png_uint_32)(*(buf )) << 24) + - ((png_uint_32)(*(buf + 1)) << 16) + - ((png_uint_32)(*(buf + 2)) << 8) + - ((png_uint_32)(*(buf + 3)) ) ; - - return uval; -} - -/* Grab a signed 32-bit integer from a buffer in big-endian format. The - * data is stored in the PNG file in two's complement format and there - * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore - * the following code does a two's complement to native conversion. - */ -png_int_32 (PNGAPI -png_get_int_32)(png_const_bytep buf) -{ - png_uint_32 uval = png_get_uint_32(buf); - if ((uval & 0x80000000) == 0) /* non-negative */ - return uval; - - uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */ - return -(png_int_32)uval; -} - -/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ -png_uint_16 (PNGAPI -png_get_uint_16)(png_const_bytep buf) -{ - /* ANSI-C requires an int value to accomodate at least 16 bits so this - * works and allows the compiler not to worry about possible narrowing - * on 32 bit systems. (Pre-ANSI systems did not make integers smaller - * than 16 bits either.) - */ - unsigned int val = - ((unsigned int)(*buf) << 8) + - ((unsigned int)(*(buf + 1))); - - return (png_uint_16)val; -} - -#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */ - -/* Read and check the PNG file signature */ -void /* PRIVATE */ -png_read_sig(png_structrp png_ptr, png_inforp info_ptr) -{ - png_size_t num_checked, num_to_check; - - /* Exit if the user application does not expect a signature. */ - if (png_ptr->sig_bytes >= 8) - return; - - num_checked = png_ptr->sig_bytes; - num_to_check = 8 - num_checked; - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; -#endif - - /* The signature must be serialized in a single I/O call. */ - png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); - png_ptr->sig_bytes = 8; - - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) - { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); - } - if (num_checked < 3) - png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; -} - -/* Read the chunk header (length + type name). - * Put the type name into png_ptr->chunk_name, and return the length. - */ -png_uint_32 /* PRIVATE */ -png_read_chunk_header(png_structrp png_ptr) -{ - png_byte buf[8]; - png_uint_32 length; - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; -#endif - - /* Read the length and the chunk name. - * This must be performed in a single I/O call. - */ - png_read_data(png_ptr, buf, 8); - length = png_get_uint_31(png_ptr, buf); - - /* Put the chunk name into png_ptr->chunk_name. */ - png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4); - - png_debug2(0, "Reading %lx chunk, length = %lu", - (unsigned long)png_ptr->chunk_name, (unsigned long)length); - - /* Reset the crc and run it over the chunk name. */ - png_reset_crc(png_ptr); - png_calculate_crc(png_ptr, buf + 4, 4); - - /* Check to see if chunk name is valid. */ - png_check_chunk_name(png_ptr, png_ptr->chunk_name); - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; -#endif - - return length; -} - -/* Read data, and (optionally) run it through the CRC. */ -void /* PRIVATE */ -png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length) -{ - if (png_ptr == NULL) - return; - - png_read_data(png_ptr, buf, length); - png_calculate_crc(png_ptr, buf, length); -} - -/* Optionally skip data and then check the CRC. Depending on whether we - * are reading an ancillary or critical chunk, and how the program has set - * things up, we may calculate the CRC on the data and print a message. - * Returns '1' if there was a CRC error, '0' otherwise. - */ -int /* PRIVATE */ -png_crc_finish(png_structrp png_ptr, png_uint_32 skip) -{ - /* The size of the local buffer for inflate is a good guess as to a - * reasonable size to use for buffering reads from the application. - */ - while (skip > 0) - { - png_uint_32 len; - png_byte tmpbuf[PNG_INFLATE_BUF_SIZE]; - - len = (sizeof tmpbuf); - if (len > skip) - len = skip; - skip -= len; - - png_crc_read(png_ptr, tmpbuf, len); - } - - if (png_crc_error(png_ptr)) - { - if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) ? - !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) : - (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)) - { - png_chunk_warning(png_ptr, "CRC error"); - } - - else - { - png_chunk_benign_error(png_ptr, "CRC error"); - return (0); - } - - return (1); - } - - return (0); -} - -/* Compare the CRC stored in the PNG file with that calculated by libpng from - * the data it has read thus far. - */ -int /* PRIVATE */ -png_crc_error(png_structrp png_ptr) -{ - png_byte crc_bytes[4]; - png_uint_32 crc; - int need_crc = 1; - - if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)) - { - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == - (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) - need_crc = 0; - } - - else /* critical */ - { - if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) - need_crc = 0; - } - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; -#endif - - /* The chunk CRC must be serialized in a single I/O call. */ - png_read_data(png_ptr, crc_bytes, 4); - - if (need_crc) - { - crc = png_get_uint_32(crc_bytes); - return ((int)(crc != png_ptr->crc)); - } - - else - return (0); -} - -/* Manage the read buffer; this simply reallocates the buffer if it is not small - * enough (or if it is not allocated). The routine returns a pointer to the - * buffer; if an error occurs and 'warn' is set the routine returns NULL, else - * it will call png_error (via png_malloc) on failure. (warn == 2 means - * 'silent'). - */ -static png_bytep -png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) -{ - png_bytep buffer = png_ptr->read_buffer; - - if (buffer != NULL && new_size > png_ptr->read_buffer_size) - { - png_ptr->read_buffer = NULL; - png_ptr->read_buffer = NULL; - png_ptr->read_buffer_size = 0; - png_free(png_ptr, buffer); - buffer = NULL; - } - - if (buffer == NULL) - { - buffer = png_voidcast(png_bytep, png_malloc_base(png_ptr, new_size)); - - if (buffer != NULL) - { - png_ptr->read_buffer = buffer; - png_ptr->read_buffer_size = new_size; - } - - else if (warn < 2) /* else silent */ - { -#ifdef PNG_WARNINGS_SUPPORTED - if (warn) - png_chunk_warning(png_ptr, "insufficient memory to read chunk"); - else -#endif - { -#ifdef PNG_ERROR_TEXT_SUPPORTED - png_chunk_error(png_ptr, "insufficient memory to read chunk"); -#endif - } - } - } - - return buffer; -} - -/* png_inflate_claim: claim the zstream for some nefarious purpose that involves - * decompression. Returns Z_OK on success, else a zlib error code. It checks - * the owner but, in final release builds, just issues a warning if some other - * chunk apparently owns the stream. Prior to release it does a png_error. - */ -static int -png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) -{ - if (png_ptr->zowner != 0) - { - char msg[64]; - - PNG_STRING_FROM_CHUNK(msg, png_ptr->zowner); - /* So the message that results is " using zstream"; this is an - * internal error, but is very useful for debugging. i18n requirements - * are minimal. - */ - (void)png_safecat(msg, (sizeof msg), 4, " using zstream"); -# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC - png_chunk_warning(png_ptr, msg); - png_ptr->zowner = 0; -# else - png_chunk_error(png_ptr, msg); -# endif - } - - /* Implementation note: unlike 'png_deflate_claim' this internal function - * does not take the size of the data as an argument. Some efficiency could - * be gained by using this when it is known *if* the zlib stream itself does - * not record the number; however, this is an illusion: the original writer - * of the PNG may have selected a lower window size, and we really must - * follow that because, for systems with with limited capabilities, we - * would otherwise reject the application's attempts to use a smaller window - * size (zlib doesn't have an interface to say "this or lower"!). - * - * inflateReset2 was added to zlib 1.2.4; before this the window could not be - * reset, therefore it is necessary to always allocate the maximum window - * size with earlier zlibs just in case later compressed chunks need it. - */ - { - int ret; /* zlib return code */ -# if PNG_ZLIB_VERNUM >= 0x1240 - -# if defined(PNG_SET_OPTION_SUPPORTED) && \ - defined(PNG_MAXIMUM_INFLATE_WINDOW) - int window_bits; - - if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) == - PNG_OPTION_ON) - window_bits = 15; - - else - window_bits = 0; -# else -# define window_bits 0 -# endif -# endif - - /* Set this for safety, just in case the previous owner left pointers to - * memory allocations. - */ - png_ptr->zstream.next_in = NULL; - png_ptr->zstream.avail_in = 0; - png_ptr->zstream.next_out = NULL; - png_ptr->zstream.avail_out = 0; - - if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) - { -# if PNG_ZLIB_VERNUM < 0x1240 - ret = inflateReset(&png_ptr->zstream); -# else - ret = inflateReset2(&png_ptr->zstream, window_bits); -# endif - } - - else - { -# if PNG_ZLIB_VERNUM < 0x1240 - ret = inflateInit(&png_ptr->zstream); -# else - ret = inflateInit2(&png_ptr->zstream, window_bits); -# endif - - if (ret == Z_OK) - png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; - } - - if (ret == Z_OK) - png_ptr->zowner = owner; - - else - png_zstream_error(png_ptr, ret); - - return ret; - } - -# ifdef window_bits -# undef window_bits -# endif -} - -#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED -/* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to - * allow the caller to do multiple calls if required. If the 'finish' flag is - * set Z_FINISH will be passed to the final inflate() call and Z_STREAM_END must - * be returned or there has been a problem, otherwise Z_SYNC_FLUSH is used and - * Z_OK or Z_STREAM_END will be returned on success. - * - * The input and output sizes are updated to the actual amounts of data consumed - * or written, not the amount available (as in a z_stream). The data pointers - * are not changed, so the next input is (data+input_size) and the next - * available output is (output+output_size). - */ -static int -png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, - /* INPUT: */ png_const_bytep input, png_uint_32p input_size_ptr, - /* OUTPUT: */ png_bytep output, png_alloc_size_t *output_size_ptr) -{ - if (png_ptr->zowner == owner) /* Else not claimed */ - { - int ret; - png_alloc_size_t avail_out = *output_size_ptr; - png_uint_32 avail_in = *input_size_ptr; - - /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it - * can't even necessarily handle 65536 bytes) because the type uInt is - * "16 bits or more". Consequently it is necessary to chunk the input to - * zlib. This code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the - * maximum value that can be stored in a uInt.) It is possible to set - * ZLIB_IO_MAX to a lower value in pngpriv.h and this may sometimes have - * a performance advantage, because it reduces the amount of data accessed - * at each step and that may give the OS more time to page it in. - */ - png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); - /* avail_in and avail_out are set below from 'size' */ - png_ptr->zstream.avail_in = 0; - png_ptr->zstream.avail_out = 0; - - /* Read directly into the output if it is available (this is set to - * a local buffer below if output is NULL). - */ - if (output != NULL) - png_ptr->zstream.next_out = output; - - do - { - uInt avail; - Byte local_buffer[PNG_INFLATE_BUF_SIZE]; - - /* zlib INPUT BUFFER */ - /* The setting of 'avail_in' used to be outside the loop; by setting it - * inside it is possible to chunk the input to zlib and simply rely on - * zlib to advance the 'next_in' pointer. This allows arbitrary - * amounts of data to be passed through zlib at the unavoidable cost of - * requiring a window save (memcpy of up to 32768 output bytes) - * every ZLIB_IO_MAX input bytes. - */ - avail_in += png_ptr->zstream.avail_in; /* not consumed last time */ - - avail = ZLIB_IO_MAX; - - if (avail_in < avail) - avail = (uInt)avail_in; /* safe: < than ZLIB_IO_MAX */ - - avail_in -= avail; - png_ptr->zstream.avail_in = avail; - - /* zlib OUTPUT BUFFER */ - avail_out += png_ptr->zstream.avail_out; /* not written last time */ - - avail = ZLIB_IO_MAX; /* maximum zlib can process */ - - if (output == NULL) - { - /* Reset the output buffer each time round if output is NULL and - * make available the full buffer, up to 'remaining_space' - */ - png_ptr->zstream.next_out = local_buffer; - if ((sizeof local_buffer) < avail) - avail = (sizeof local_buffer); - } - - if (avail_out < avail) - avail = (uInt)avail_out; /* safe: < ZLIB_IO_MAX */ - - png_ptr->zstream.avail_out = avail; - avail_out -= avail; - - /* zlib inflate call */ - /* In fact 'avail_out' may be 0 at this point, that happens at the end - * of the read when the final LZ end code was not passed at the end of - * the previous chunk of input data. Tell zlib if we have reached the - * end of the output buffer. - */ - ret = inflate(&png_ptr->zstream, avail_out > 0 ? Z_NO_FLUSH : - (finish ? Z_FINISH : Z_SYNC_FLUSH)); - } while (ret == Z_OK); - - /* For safety kill the local buffer pointer now */ - if (output == NULL) - png_ptr->zstream.next_out = NULL; - - /* Claw back the 'size' and 'remaining_space' byte counts. */ - avail_in += png_ptr->zstream.avail_in; - avail_out += png_ptr->zstream.avail_out; - - /* Update the input and output sizes; the updated values are the amount - * consumed or written, effectively the inverse of what zlib uses. - */ - if (avail_out > 0) - *output_size_ptr -= avail_out; - - if (avail_in > 0) - *input_size_ptr -= avail_in; - - /* Ensure png_ptr->zstream.msg is set (even in the success case!) */ - png_zstream_error(png_ptr, ret); - return ret; - } - - else - { - /* This is a bad internal error. The recovery assigns to the zstream msg - * pointer, which is not owned by the caller, but this is safe; it's only - * used on errors! - */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed"); - return Z_STREAM_ERROR; - } -} - -/* - * Decompress trailing data in a chunk. The assumption is that read_buffer - * points at an allocated area holding the contents of a chunk with a - * trailing compressed part. What we get back is an allocated area - * holding the original prefix part and an uncompressed version of the - * trailing part (the malloc area passed in is freed). - */ -static int -png_decompress_chunk(png_structrp png_ptr, - png_uint_32 chunklength, png_uint_32 prefix_size, - png_alloc_size_t *newlength /* must be initialized to the maximum! */, - int terminate /*add a '\0' to the end of the uncompressed data*/) -{ - /* TODO: implement different limits for different types of chunk. - * - * The caller supplies *newlength set to the maximum length of the - * uncompressed data, but this routine allocates space for the prefix and - * maybe a '\0' terminator too. We have to assume that 'prefix_size' is - * limited only by the maximum chunk size. - */ - png_alloc_size_t limit = PNG_SIZE_MAX; - -# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED - if (png_ptr->user_chunk_malloc_max > 0 && - png_ptr->user_chunk_malloc_max < limit) - limit = png_ptr->user_chunk_malloc_max; -# elif PNG_USER_CHUNK_MALLOC_MAX > 0 - if (PNG_USER_CHUNK_MALLOC_MAX < limit) - limit = PNG_USER_CHUNK_MALLOC_MAX; -# endif - - if (limit >= prefix_size + (terminate != 0)) - { - int ret; - - limit -= prefix_size + (terminate != 0); - - if (limit < *newlength) - *newlength = limit; - - /* Now try to claim the stream. */ - ret = png_inflate_claim(png_ptr, png_ptr->chunk_name); - - if (ret == Z_OK) - { - png_uint_32 lzsize = chunklength - prefix_size; - - ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, - /* input: */ png_ptr->read_buffer + prefix_size, &lzsize, - /* output: */ NULL, newlength); - - if (ret == Z_STREAM_END) - { - /* Use 'inflateReset' here, not 'inflateReset2' because this - * preserves the previously decided window size (otherwise it would - * be necessary to store the previous window size.) In practice - * this doesn't matter anyway, because png_inflate will call inflate - * with Z_FINISH in almost all cases, so the window will not be - * maintained. - */ - if (inflateReset(&png_ptr->zstream) == Z_OK) - { - /* Because of the limit checks above we know that the new, - * expanded, size will fit in a size_t (let alone an - * png_alloc_size_t). Use png_malloc_base here to avoid an - * extra OOM message. - */ - png_alloc_size_t new_size = *newlength; - png_alloc_size_t buffer_size = prefix_size + new_size + - (terminate != 0); - png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr, - buffer_size)); - - if (text != NULL) - { - ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, - png_ptr->read_buffer + prefix_size, &lzsize, - text + prefix_size, newlength); - - if (ret == Z_STREAM_END) - { - if (new_size == *newlength) - { - if (terminate) - text[prefix_size + *newlength] = 0; - - if (prefix_size > 0) - memcpy(text, png_ptr->read_buffer, prefix_size); - - { - png_bytep old_ptr = png_ptr->read_buffer; - - png_ptr->read_buffer = text; - png_ptr->read_buffer_size = buffer_size; - text = old_ptr; /* freed below */ - } - } - - else - { - /* The size changed on the second read, there can be no - * guarantee that anything is correct at this point. - * The 'msg' pointer has been set to "unexpected end of - * LZ stream", which is fine, but return an error code - * that the caller won't accept. - */ - ret = PNG_UNEXPECTED_ZLIB_RETURN; - } - } - - else if (ret == Z_OK) - ret = PNG_UNEXPECTED_ZLIB_RETURN; /* for safety */ - - /* Free the text pointer (this is the old read_buffer on - * success) - */ - png_free(png_ptr, text); - - /* This really is very benign, but it's still an error because - * the extra space may otherwise be used as a Trojan Horse. - */ - if (ret == Z_STREAM_END && - chunklength - prefix_size != lzsize) - png_chunk_benign_error(png_ptr, "extra compressed data"); - } - - else - { - /* Out of memory allocating the buffer */ - ret = Z_MEM_ERROR; - png_zstream_error(png_ptr, Z_MEM_ERROR); - } - } - - else - { - /* inflateReset failed, store the error message */ - png_zstream_error(png_ptr, ret); - - if (ret == Z_STREAM_END) - ret = PNG_UNEXPECTED_ZLIB_RETURN; - } - } - - else if (ret == Z_OK) - ret = PNG_UNEXPECTED_ZLIB_RETURN; - - /* Release the claimed stream */ - png_ptr->zowner = 0; - } - - else /* the claim failed */ if (ret == Z_STREAM_END) /* impossible! */ - ret = PNG_UNEXPECTED_ZLIB_RETURN; - - return ret; - } - - else - { - /* Application/configuration limits exceeded */ - png_zstream_error(png_ptr, Z_MEM_ERROR); - return Z_MEM_ERROR; - } -} -#endif /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */ - -#ifdef PNG_READ_iCCP_SUPPORTED -/* Perform a partial read and decompress, producing 'avail_out' bytes and - * reading from the current chunk as required. - */ -static int -png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, - png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size, - int finish) -{ - if (png_ptr->zowner == png_ptr->chunk_name) - { - int ret; - - /* next_in and avail_in must have been initialized by the caller. */ - png_ptr->zstream.next_out = next_out; - png_ptr->zstream.avail_out = 0; /* set in the loop */ - - do - { - if (png_ptr->zstream.avail_in == 0) - { - if (read_size > *chunk_bytes) - read_size = (uInt)*chunk_bytes; - *chunk_bytes -= read_size; - - if (read_size > 0) - png_crc_read(png_ptr, read_buffer, read_size); - - png_ptr->zstream.next_in = read_buffer; - png_ptr->zstream.avail_in = read_size; - } - - if (png_ptr->zstream.avail_out == 0) - { - uInt avail = ZLIB_IO_MAX; - if (avail > *out_size) - avail = (uInt)*out_size; - *out_size -= avail; - - png_ptr->zstream.avail_out = avail; - } - - /* Use Z_SYNC_FLUSH when there is no more chunk data to ensure that all - * the available output is produced; this allows reading of truncated - * streams. - */ - ret = inflate(&png_ptr->zstream, - *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); - } - while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0)); - - *out_size += png_ptr->zstream.avail_out; - png_ptr->zstream.avail_out = 0; /* Should not be required, but is safe */ - - /* Ensure the error message pointer is always set: */ - png_zstream_error(png_ptr, ret); - return ret; - } - - else - { - png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed"); - return Z_STREAM_ERROR; - } -} -#endif - -/* Read and check the IDHR chunk */ -void /* PRIVATE */ -png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_byte buf[13]; - png_uint_32 width, height; - int bit_depth, color_type, compression_type, filter_type; - int interlace_type; - - png_debug(1, "in png_handle_IHDR"); - - if (png_ptr->mode & PNG_HAVE_IHDR) - png_chunk_error(png_ptr, "out of place"); - - /* Check the length */ - if (length != 13) - png_chunk_error(png_ptr, "invalid"); - - png_ptr->mode |= PNG_HAVE_IHDR; - - png_crc_read(png_ptr, buf, 13); - png_crc_finish(png_ptr, 0); - - width = png_get_uint_31(png_ptr, buf); - height = png_get_uint_31(png_ptr, buf + 4); - bit_depth = buf[8]; - color_type = buf[9]; - compression_type = buf[10]; - filter_type = buf[11]; - interlace_type = buf[12]; - - /* Set internal variables */ - png_ptr->width = width; - png_ptr->height = height; - png_ptr->bit_depth = (png_byte)bit_depth; - png_ptr->interlaced = (png_byte)interlace_type; - png_ptr->color_type = (png_byte)color_type; -#ifdef PNG_MNG_FEATURES_SUPPORTED - png_ptr->filter_type = (png_byte)filter_type; -#endif - png_ptr->compression_type = (png_byte)compression_type; - - /* Find number of channels */ - switch (png_ptr->color_type) - { - default: /* invalid, png_set_IHDR calls png_error */ - case PNG_COLOR_TYPE_GRAY: - case PNG_COLOR_TYPE_PALETTE: - png_ptr->channels = 1; - break; - - case PNG_COLOR_TYPE_RGB: - png_ptr->channels = 3; - break; - - case PNG_COLOR_TYPE_GRAY_ALPHA: - png_ptr->channels = 2; - break; - - case PNG_COLOR_TYPE_RGB_ALPHA: - png_ptr->channels = 4; - break; - } - - /* Set up other useful info */ - png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * - png_ptr->channels); - png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); - png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); - png_debug1(3, "channels = %d", png_ptr->channels); - png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes); - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, - color_type, interlace_type, compression_type, filter_type); -} - -/* Read and check the palette */ -void /* PRIVATE */ -png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_color palette[PNG_MAX_PALETTE_LENGTH]; - int num, i; -#ifdef PNG_POINTER_INDEXING_SUPPORTED - png_colorp pal_ptr; -#endif - - png_debug(1, "in png_handle_PLTE"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - /* Moved to before the 'after IDAT' check below because otherwise duplicate - * PLTE chunks are potentially ignored (the spec says there shall not be more - * than one PLTE, the error is not treated as benign, so this check trumps - * the requirement that PLTE appears before IDAT.) - */ - else if (png_ptr->mode & PNG_HAVE_PLTE) - png_chunk_error(png_ptr, "duplicate"); - - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - /* This is benign because the non-benign error happened before, when an - * IDAT was encountered in a color-mapped image with no PLTE. - */ - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - png_ptr->mode |= PNG_HAVE_PLTE; - - if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "ignored in grayscale PNG"); - return; - } - -#ifndef PNG_READ_OPT_PLTE_SUPPORTED - if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - { - png_crc_finish(png_ptr, length); - return; - } -#endif - - if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) - { - png_crc_finish(png_ptr, length); - - if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - png_chunk_benign_error(png_ptr, "invalid"); - - else - png_chunk_error(png_ptr, "invalid"); - - return; - } - - /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */ - num = (int)length / 3; - -#ifdef PNG_POINTER_INDEXING_SUPPORTED - for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) - { - png_byte buf[3]; - - png_crc_read(png_ptr, buf, 3); - pal_ptr->red = buf[0]; - pal_ptr->green = buf[1]; - pal_ptr->blue = buf[2]; - } -#else - for (i = 0; i < num; i++) - { - png_byte buf[3]; - - png_crc_read(png_ptr, buf, 3); - /* Don't depend upon png_color being any order */ - palette[i].red = buf[0]; - palette[i].green = buf[1]; - palette[i].blue = buf[2]; - } -#endif - - /* If we actually need the PLTE chunk (ie for a paletted image), we do - * whatever the normal CRC configuration tells us. However, if we - * have an RGB image, the PLTE can be considered ancillary, so - * we will act as though it is. - */ -#ifndef PNG_READ_OPT_PLTE_SUPPORTED - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) -#endif - { - png_crc_finish(png_ptr, 0); - } - -#ifndef PNG_READ_OPT_PLTE_SUPPORTED - else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ - { - /* If we don't want to use the data from an ancillary chunk, - * we have two options: an error abort, or a warning and we - * ignore the data in this chunk (which should be OK, since - * it's considered ancillary for a RGB or RGBA image). - * - * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the - * chunk type to determine whether to check the ancillary or the critical - * flags. - */ - if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) - { - if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) - { - png_chunk_benign_error(png_ptr, "CRC error"); - } - - else - { - png_chunk_warning(png_ptr, "CRC error"); - return; - } - } - - /* Otherwise, we (optionally) emit a warning and use the chunk. */ - else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) - { - png_chunk_warning(png_ptr, "CRC error"); - } - } -#endif - - /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its - * own copy of the palette. This has the side effect that when png_start_row - * is called (this happens after any call to png_read_update_info) the - * info_ptr palette gets changed. This is extremely unexpected and - * confusing. - * - * Fix this by not sharing the palette in this way. - */ - png_set_PLTE(png_ptr, info_ptr, palette, num); - - /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before - * IDAT. Prior to 1.6.0 this was not checked; instead the code merely - * checked the apparent validity of a tRNS chunk inserted before PLTE on a - * palette PNG. 1.6.0 attempts to rigorously follow the standard and - * therefore does a benign error if the erroneous condition is detected *and* - * cancels the tRNS if the benign error returns. The alternative is to - * amend the standard since it would be rather hypocritical of the standards - * maintainers to ignore it. - */ -#ifdef PNG_READ_tRNS_SUPPORTED - if (png_ptr->num_trans > 0 || - (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0)) - { - /* Cancel this because otherwise it would be used if the transforms - * require it. Don't cancel the 'valid' flag because this would prevent - * detection of duplicate chunks. - */ - png_ptr->num_trans = 0; - - if (info_ptr != NULL) - info_ptr->num_trans = 0; - - png_chunk_benign_error(png_ptr, "tRNS must be after"); - } -#endif - -#ifdef PNG_READ_hIST_SUPPORTED - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0) - png_chunk_benign_error(png_ptr, "hIST must be after"); -#endif - -#ifdef PNG_READ_bKGD_SUPPORTED - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0) - png_chunk_benign_error(png_ptr, "bKGD must be after"); -#endif -} - -void /* PRIVATE */ -png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_debug(1, "in png_handle_IEND"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) - png_chunk_error(png_ptr, "out of place"); - - png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); - - png_crc_finish(png_ptr, length); - - if (length != 0) - png_chunk_benign_error(png_ptr, "invalid"); - - PNG_UNUSED(info_ptr) -} - -#ifdef PNG_READ_gAMA_SUPPORTED -void /* PRIVATE */ -png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_fixed_point igamma; - png_byte buf[4]; - - png_debug(1, "in png_handle_gAMA"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - if (length != 4) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_crc_read(png_ptr, buf, 4); - - if (png_crc_finish(png_ptr, 0)) - return; - - igamma = png_get_fixed_point(NULL, buf); - - png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma); - png_colorspace_sync(png_ptr, info_ptr); -} -#endif - -#ifdef PNG_READ_sBIT_SUPPORTED -void /* PRIVATE */ -png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - unsigned int truelen; - png_byte buf[4]; - - png_debug(1, "in png_handle_sBIT"); - - buf[0] = buf[1] = buf[2] = buf[3] = 0; - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - truelen = 3; - - else - truelen = png_ptr->channels; - - if (length != truelen || length > 4) - { - png_chunk_benign_error(png_ptr, "invalid"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, truelen); - - if (png_crc_finish(png_ptr, 0)) - return; - - if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - { - png_ptr->sig_bit.red = buf[0]; - png_ptr->sig_bit.green = buf[1]; - png_ptr->sig_bit.blue = buf[2]; - png_ptr->sig_bit.alpha = buf[3]; - } - - else - { - png_ptr->sig_bit.gray = buf[0]; - png_ptr->sig_bit.red = buf[0]; - png_ptr->sig_bit.green = buf[0]; - png_ptr->sig_bit.blue = buf[0]; - png_ptr->sig_bit.alpha = buf[1]; - } - - png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); -} -#endif - -#ifdef PNG_READ_cHRM_SUPPORTED -void /* PRIVATE */ -png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_byte buf[32]; - png_xy xy; - - png_debug(1, "in png_handle_cHRM"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - if (length != 32) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_crc_read(png_ptr, buf, 32); - - if (png_crc_finish(png_ptr, 0)) - return; - - xy.whitex = png_get_fixed_point(NULL, buf); - xy.whitey = png_get_fixed_point(NULL, buf + 4); - xy.redx = png_get_fixed_point(NULL, buf + 8); - xy.redy = png_get_fixed_point(NULL, buf + 12); - xy.greenx = png_get_fixed_point(NULL, buf + 16); - xy.greeny = png_get_fixed_point(NULL, buf + 20); - xy.bluex = png_get_fixed_point(NULL, buf + 24); - xy.bluey = png_get_fixed_point(NULL, buf + 28); - - if (xy.whitex == PNG_FIXED_ERROR || - xy.whitey == PNG_FIXED_ERROR || - xy.redx == PNG_FIXED_ERROR || - xy.redy == PNG_FIXED_ERROR || - xy.greenx == PNG_FIXED_ERROR || - xy.greeny == PNG_FIXED_ERROR || - xy.bluex == PNG_FIXED_ERROR || - xy.bluey == PNG_FIXED_ERROR) - { - png_chunk_benign_error(png_ptr, "invalid values"); - return; - } - - /* If a colorspace error has already been output skip this chunk */ - if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) - return; - - if (png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) - { - png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; - png_colorspace_sync(png_ptr, info_ptr); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; - (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy, - 1/*prefer cHRM values*/); - png_colorspace_sync(png_ptr, info_ptr); -} -#endif - -#ifdef PNG_READ_sRGB_SUPPORTED -void /* PRIVATE */ -png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_byte intent; - - png_debug(1, "in png_handle_sRGB"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - if (length != 1) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_crc_read(png_ptr, &intent, 1); - - if (png_crc_finish(png_ptr, 0)) - return; - - /* If a colorspace error has already been output skip this chunk */ - if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) - return; - - /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect - * this. - */ - if (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) - { - png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; - png_colorspace_sync(png_ptr, info_ptr); - png_chunk_benign_error(png_ptr, "too many profiles"); - return; - } - - (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent); - png_colorspace_sync(png_ptr, info_ptr); -} -#endif /* PNG_READ_sRGB_SUPPORTED */ - -#ifdef PNG_READ_iCCP_SUPPORTED -void /* PRIVATE */ -png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -/* Note: this does not properly handle profiles that are > 64K under DOS */ -{ - png_const_charp errmsg = NULL; /* error message output, or no error */ - int finished = 0; /* crc checked */ - - png_debug(1, "in png_handle_iCCP"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - /* Consistent with all the above colorspace handling an obviously *invalid* - * chunk is just ignored, so does not invalidate the color space. An - * alternative is to set the 'invalid' flags at the start of this routine - * and only clear them in they were not set before and all the tests pass. - * The minimum 'deflate' stream is assumed to be just the 2 byte header and 4 - * byte checksum. The keyword must be one character and there is a - * terminator (0) byte and the compression method. - */ - if (length < 9) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "too short"); - return; - } - - /* If a colorspace error has already been output skip this chunk */ - if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) - { - png_crc_finish(png_ptr, length); - return; - } - - /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect - * this. - */ - if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0) - { - uInt read_length, keyword_length; - char keyword[81]; - - /* Find the keyword; the keyword plus separator and compression method - * bytes can be at most 81 characters long. - */ - read_length = 81; /* maximum */ - if (read_length > length) - read_length = (uInt)length; - - png_crc_read(png_ptr, (png_bytep)keyword, read_length); - length -= read_length; - - keyword_length = 0; - while (keyword_length < 80 && keyword_length < read_length && - keyword[keyword_length] != 0) - ++keyword_length; - - /* TODO: make the keyword checking common */ - if (keyword_length >= 1 && keyword_length <= 79) - { - /* We only understand '0' compression - deflate - so if we get a - * different value we can't safely decode the chunk. - */ - if (keyword_length+1 < read_length && - keyword[keyword_length+1] == PNG_COMPRESSION_TYPE_BASE) - { - read_length -= keyword_length+2; - - if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK) - { - Byte profile_header[132]; - Byte local_buffer[PNG_INFLATE_BUF_SIZE]; - png_alloc_size_t size = (sizeof profile_header); - - png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2); - png_ptr->zstream.avail_in = read_length; - (void)png_inflate_read(png_ptr, local_buffer, - (sizeof local_buffer), &length, profile_header, &size, - 0/*finish: don't, because the output is too small*/); - - if (size == 0) - { - /* We have the ICC profile header; do the basic header checks. - */ - const png_uint_32 profile_length = - png_get_uint_32(profile_header); - - if (png_icc_check_length(png_ptr, &png_ptr->colorspace, - keyword, profile_length)) - { - /* The length is apparently ok, so we can check the 132 - * byte header. - */ - if (png_icc_check_header(png_ptr, &png_ptr->colorspace, - keyword, profile_length, profile_header, - png_ptr->color_type)) - { - /* Now read the tag table; a variable size buffer is - * needed at this point, allocate one for the whole - * profile. The header check has already validated - * that none of these stuff will overflow. - */ - const png_uint_32 tag_count = png_get_uint_32( - profile_header+128); - png_bytep profile = png_read_buffer(png_ptr, - profile_length, 2/*silent*/); - - if (profile != NULL) - { - memcpy(profile, profile_header, - (sizeof profile_header)); - - size = 12 * tag_count; - - (void)png_inflate_read(png_ptr, local_buffer, - (sizeof local_buffer), &length, - profile + (sizeof profile_header), &size, 0); - - /* Still expect a a buffer error because we expect - * there to be some tag data! - */ - if (size == 0) - { - if (png_icc_check_tag_table(png_ptr, - &png_ptr->colorspace, keyword, profile_length, - profile)) - { - /* The profile has been validated for basic - * security issues, so read the whole thing in. - */ - size = profile_length - (sizeof profile_header) - - 12 * tag_count; - - (void)png_inflate_read(png_ptr, local_buffer, - (sizeof local_buffer), &length, - profile + (sizeof profile_header) + - 12 * tag_count, &size, 1/*finish*/); - - if (length > 0 && !(png_ptr->flags & - PNG_FLAG_BENIGN_ERRORS_WARN)) - errmsg = "extra compressed data"; - - /* But otherwise allow extra data: */ - else if (size == 0) - { - if (length > 0) - { - /* This can be handled completely, so - * keep going. - */ - png_chunk_warning(png_ptr, - "extra compressed data"); - } - - png_crc_finish(png_ptr, length); - finished = 1; - -# ifdef PNG_sRGB_SUPPORTED - /* Check for a match against sRGB */ - png_icc_set_sRGB(png_ptr, - &png_ptr->colorspace, profile, - png_ptr->zstream.adler); -# endif - - /* Steal the profile for info_ptr. */ - if (info_ptr != NULL) - { - png_free_data(png_ptr, info_ptr, - PNG_FREE_ICCP, 0); - - info_ptr->iccp_name = png_voidcast(char*, - png_malloc_base(png_ptr, - keyword_length+1)); - if (info_ptr->iccp_name != NULL) - { - memcpy(info_ptr->iccp_name, keyword, - keyword_length+1); - info_ptr->iccp_proflen = - profile_length; - info_ptr->iccp_profile = profile; - png_ptr->read_buffer = NULL; /*steal*/ - info_ptr->free_me |= PNG_FREE_ICCP; - info_ptr->valid |= PNG_INFO_iCCP; - } - - else - { - png_ptr->colorspace.flags |= - PNG_COLORSPACE_INVALID; - errmsg = "out of memory"; - } - } - - /* else the profile remains in the read - * buffer which gets reused for subsequent - * chunks. - */ - - if (info_ptr != NULL) - png_colorspace_sync(png_ptr, info_ptr); - - if (errmsg == NULL) - { - png_ptr->zowner = 0; - return; - } - } - - else if (size > 0) - errmsg = "truncated"; - - else - errmsg = png_ptr->zstream.msg; - } - - /* else png_icc_check_tag_table output an error */ - } - - else /* profile truncated */ - errmsg = png_ptr->zstream.msg; - } - - else - errmsg = "out of memory"; - } - - /* else png_icc_check_header output an error */ - } - - /* else png_icc_check_length output an error */ - } - - else /* profile truncated */ - errmsg = png_ptr->zstream.msg; - - /* Release the stream */ - png_ptr->zowner = 0; - } - - else /* png_inflate_claim failed */ - errmsg = png_ptr->zstream.msg; - } - - else - errmsg = "bad compression method"; /* or missing */ - } - - else - errmsg = "bad keyword"; - } - - else - errmsg = "too many profiles"; - - /* Failure: the reason is in 'errmsg' */ - if (!finished) - png_crc_finish(png_ptr, length); - - png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; - png_colorspace_sync(png_ptr, info_ptr); - if (errmsg != NULL) /* else already output */ - png_chunk_benign_error(png_ptr, errmsg); -} -#endif /* PNG_READ_iCCP_SUPPORTED */ - -#ifdef PNG_READ_sPLT_SUPPORTED -void /* PRIVATE */ -png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -/* Note: this does not properly handle chunks that are > 64K under DOS */ -{ - png_bytep entry_start, buffer; - png_sPLT_t new_palette; - png_sPLT_entryp pp; - png_uint_32 data_length; - int entry_size, i; - png_uint_32 skip = 0; - png_uint_32 dl; - png_size_t max_dl; - - png_debug(1, "in png_handle_sPLT"); - -#ifdef PNG_USER_LIMITS_SUPPORTED - if (png_ptr->user_chunk_cache_max != 0) - { - if (png_ptr->user_chunk_cache_max == 1) - { - png_crc_finish(png_ptr, length); - return; - } - - if (--png_ptr->user_chunk_cache_max == 1) - { - png_warning(png_ptr, "No space in chunk cache for sPLT"); - png_crc_finish(png_ptr, length); - return; - } - } -#endif - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - -#ifdef PNG_MAX_MALLOC_64K - if (length > 65535U) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "too large to fit in memory"); - return; - } -#endif - - buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); - if (buffer == NULL) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of memory"); - return; - } - - - /* WARNING: this may break if size_t is less than 32 bits; it is assumed - * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a - * potential breakage point if the types in pngconf.h aren't exactly right. - */ - png_crc_read(png_ptr, buffer, length); - - if (png_crc_finish(png_ptr, skip)) - return; - - buffer[length] = 0; - - for (entry_start = buffer; *entry_start; entry_start++) - /* Empty loop to find end of name */ ; - - ++entry_start; - - /* A sample depth should follow the separator, and we should be on it */ - if (entry_start > buffer + length - 2) - { - png_warning(png_ptr, "malformed sPLT chunk"); - return; - } - - new_palette.depth = *entry_start++; - entry_size = (new_palette.depth == 8 ? 6 : 10); - /* This must fit in a png_uint_32 because it is derived from the original - * chunk data length. - */ - data_length = length - (png_uint_32)(entry_start - buffer); - - /* Integrity-check the data length */ - if (data_length % entry_size) - { - png_warning(png_ptr, "sPLT chunk has bad length"); - return; - } - - dl = (png_int_32)(data_length / entry_size); - max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry)); - - if (dl > max_dl) - { - png_warning(png_ptr, "sPLT chunk too long"); - return; - } - - new_palette.nentries = (png_int_32)(data_length / entry_size); - - new_palette.entries = (png_sPLT_entryp)png_malloc_warn( - png_ptr, new_palette.nentries * (sizeof (png_sPLT_entry))); - - if (new_palette.entries == NULL) - { - png_warning(png_ptr, "sPLT chunk requires too much memory"); - return; - } - -#ifdef PNG_POINTER_INDEXING_SUPPORTED - for (i = 0; i < new_palette.nentries; i++) - { - pp = new_palette.entries + i; - - if (new_palette.depth == 8) - { - pp->red = *entry_start++; - pp->green = *entry_start++; - pp->blue = *entry_start++; - pp->alpha = *entry_start++; - } - - else - { - pp->red = png_get_uint_16(entry_start); entry_start += 2; - pp->green = png_get_uint_16(entry_start); entry_start += 2; - pp->blue = png_get_uint_16(entry_start); entry_start += 2; - pp->alpha = png_get_uint_16(entry_start); entry_start += 2; - } - - pp->frequency = png_get_uint_16(entry_start); entry_start += 2; - } -#else - pp = new_palette.entries; - - for (i = 0; i < new_palette.nentries; i++) - { - - if (new_palette.depth == 8) - { - pp[i].red = *entry_start++; - pp[i].green = *entry_start++; - pp[i].blue = *entry_start++; - pp[i].alpha = *entry_start++; - } - - else - { - pp[i].red = png_get_uint_16(entry_start); entry_start += 2; - pp[i].green = png_get_uint_16(entry_start); entry_start += 2; - pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; - pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; - } - - pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2; - } -#endif - - /* Discard all chunk data except the name and stash that */ - new_palette.name = (png_charp)buffer; - - png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); - - png_free(png_ptr, new_palette.entries); -} -#endif /* PNG_READ_sPLT_SUPPORTED */ - -#ifdef PNG_READ_tRNS_SUPPORTED -void /* PRIVATE */ -png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; - - png_debug(1, "in png_handle_tRNS"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - png_byte buf[2]; - - if (length != 2) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_crc_read(png_ptr, buf, 2); - png_ptr->num_trans = 1; - png_ptr->trans_color.gray = png_get_uint_16(buf); - } - - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - png_byte buf[6]; - - if (length != 6) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_crc_read(png_ptr, buf, length); - png_ptr->num_trans = 1; - png_ptr->trans_color.red = png_get_uint_16(buf); - png_ptr->trans_color.green = png_get_uint_16(buf + 2); - png_ptr->trans_color.blue = png_get_uint_16(buf + 4); - } - - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (!(png_ptr->mode & PNG_HAVE_PLTE)) - { - /* TODO: is this actually an error in the ISO spec? */ - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - if (length > png_ptr->num_palette || length > PNG_MAX_PALETTE_LENGTH || - length == 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_crc_read(png_ptr, readbuf, length); - png_ptr->num_trans = (png_uint_16)length; - } - - else - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid with alpha channel"); - return; - } - - if (png_crc_finish(png_ptr, 0)) - { - png_ptr->num_trans = 0; - return; - } - - /* TODO: this is a horrible side effect in the palette case because the - * png_struct ends up with a pointer to the tRNS buffer owned by the - * png_info. Fix this. - */ - png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, - &(png_ptr->trans_color)); -} -#endif - -#ifdef PNG_READ_bKGD_SUPPORTED -void /* PRIVATE */ -png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - unsigned int truelen; - png_byte buf[6]; - png_color_16 background; - - png_debug(1, "in png_handle_bKGD"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & PNG_HAVE_IDAT) || - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE))) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - truelen = 1; - - else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - truelen = 6; - - else - truelen = 2; - - if (length != truelen) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_crc_read(png_ptr, buf, truelen); - - if (png_crc_finish(png_ptr, 0)) - return; - - /* We convert the index value into RGB components so that we can allow - * arbitrary RGB values for background when we have transparency, and - * so it is easy to determine the RGB values of the background color - * from the info_ptr struct. - */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - background.index = buf[0]; - - if (info_ptr && info_ptr->num_palette) - { - if (buf[0] >= info_ptr->num_palette) - { - png_chunk_benign_error(png_ptr, "invalid index"); - return; - } - - background.red = (png_uint_16)png_ptr->palette[buf[0]].red; - background.green = (png_uint_16)png_ptr->palette[buf[0]].green; - background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue; - } - - else - background.red = background.green = background.blue = 0; - - background.gray = 0; - } - - else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ - { - background.index = 0; - background.red = - background.green = - background.blue = - background.gray = png_get_uint_16(buf); - } - - else - { - background.index = 0; - background.red = png_get_uint_16(buf); - background.green = png_get_uint_16(buf + 2); - background.blue = png_get_uint_16(buf + 4); - background.gray = 0; - } - - png_set_bKGD(png_ptr, info_ptr, &background); -} -#endif - -#ifdef PNG_READ_hIST_SUPPORTED -void /* PRIVATE */ -png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - unsigned int num, i; - png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; - - png_debug(1, "in png_handle_hIST"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & PNG_HAVE_IDAT) || !(png_ptr->mode & PNG_HAVE_PLTE)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - num = length / 2 ; - - if (num != png_ptr->num_palette || num > PNG_MAX_PALETTE_LENGTH) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - for (i = 0; i < num; i++) - { - png_byte buf[2]; - - png_crc_read(png_ptr, buf, 2); - readbuf[i] = png_get_uint_16(buf); - } - - if (png_crc_finish(png_ptr, 0)) - return; - - png_set_hIST(png_ptr, info_ptr, readbuf); -} -#endif - -#ifdef PNG_READ_pHYs_SUPPORTED -void /* PRIVATE */ -png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_byte buf[9]; - png_uint_32 res_x, res_y; - int unit_type; - - png_debug(1, "in png_handle_pHYs"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - if (length != 9) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_crc_read(png_ptr, buf, 9); - - if (png_crc_finish(png_ptr, 0)) - return; - - res_x = png_get_uint_32(buf); - res_y = png_get_uint_32(buf + 4); - unit_type = buf[8]; - png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); -} -#endif - -#ifdef PNG_READ_oFFs_SUPPORTED -void /* PRIVATE */ -png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_byte buf[9]; - png_int_32 offset_x, offset_y; - int unit_type; - - png_debug(1, "in png_handle_oFFs"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - if (length != 9) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_crc_read(png_ptr, buf, 9); - - if (png_crc_finish(png_ptr, 0)) - return; - - offset_x = png_get_int_32(buf); - offset_y = png_get_int_32(buf + 4); - unit_type = buf[8]; - png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); -} -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED -/* Read the pCAL chunk (described in the PNG Extensions document) */ -void /* PRIVATE */ -png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_int_32 X0, X1; - png_byte type, nparams; - png_bytep buffer, buf, units, endptr; - png_charpp params; - int i; - - png_debug(1, "in png_handle_pCAL"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)", - length + 1); - - buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); - - if (buffer == NULL) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of memory"); - return; - } - - png_crc_read(png_ptr, buffer, length); - - if (png_crc_finish(png_ptr, 0)) - return; - - buffer[length] = 0; /* Null terminate the last string */ - - png_debug(3, "Finding end of pCAL purpose string"); - for (buf = buffer; *buf; buf++) - /* Empty loop */ ; - - endptr = buffer + length; - - /* We need to have at least 12 bytes after the purpose string - * in order to get the parameter information. - */ - if (endptr <= buf + 12) - { - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); - X0 = png_get_int_32((png_bytep)buf+1); - X1 = png_get_int_32((png_bytep)buf+5); - type = buf[9]; - nparams = buf[10]; - units = buf + 11; - - png_debug(3, "Checking pCAL equation type and number of parameters"); - /* Check that we have the right number of parameters for known - * equation types. - */ - if ((type == PNG_EQUATION_LINEAR && nparams != 2) || - (type == PNG_EQUATION_BASE_E && nparams != 3) || - (type == PNG_EQUATION_ARBITRARY && nparams != 3) || - (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) - { - png_chunk_benign_error(png_ptr, "invalid parameter count"); - return; - } - - else if (type >= PNG_EQUATION_LAST) - { - png_chunk_benign_error(png_ptr, "unrecognized equation type"); - } - - for (buf = units; *buf; buf++) - /* Empty loop to move past the units string. */ ; - - png_debug(3, "Allocating pCAL parameters array"); - - params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, - nparams * (sizeof (png_charp)))); - - if (params == NULL) - { - png_chunk_benign_error(png_ptr, "out of memory"); - return; - } - - /* Get pointers to the start of each parameter string. */ - for (i = 0; i < nparams; i++) - { - buf++; /* Skip the null string terminator from previous parameter. */ - - png_debug1(3, "Reading pCAL parameter %d", i); - - for (params[i] = (png_charp)buf; buf <= endptr && *buf != 0; buf++) - /* Empty loop to move past each parameter string */ ; - - /* Make sure we haven't run out of data yet */ - if (buf > endptr) - { - png_free(png_ptr, params); - png_chunk_benign_error(png_ptr, "invalid data"); - return; - } - } - - png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams, - (png_charp)units, params); - - png_free(png_ptr, params); -} -#endif - -#ifdef PNG_READ_sCAL_SUPPORTED -/* Read the sCAL chunk */ -void /* PRIVATE */ -png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_bytep buffer; - png_size_t i; - int state; - - png_debug(1, "in png_handle_sCAL"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - /* Need unit type, width, \0, height: minimum 4 bytes */ - else if (length < 4) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", - length + 1); - - buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); - - if (buffer == NULL) - { - png_chunk_benign_error(png_ptr, "out of memory"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buffer, length); - buffer[length] = 0; /* Null terminate the last string */ - - if (png_crc_finish(png_ptr, 0)) - return; - - /* Validate the unit. */ - if (buffer[0] != 1 && buffer[0] != 2) - { - png_chunk_benign_error(png_ptr, "invalid unit"); - return; - } - - /* Validate the ASCII numbers, need two ASCII numbers separated by - * a '\0' and they need to fit exactly in the chunk data. - */ - i = 1; - state = 0; - - if (!png_check_fp_number((png_const_charp)buffer, length, &state, &i) || - i >= length || buffer[i++] != 0) - png_chunk_benign_error(png_ptr, "bad width format"); - - else if (!PNG_FP_IS_POSITIVE(state)) - png_chunk_benign_error(png_ptr, "non-positive width"); - - else - { - png_size_t heighti = i; - - state = 0; - if (!png_check_fp_number((png_const_charp)buffer, length, &state, &i) || - i != length) - png_chunk_benign_error(png_ptr, "bad height format"); - - else if (!PNG_FP_IS_POSITIVE(state)) - png_chunk_benign_error(png_ptr, "non-positive height"); - - else - /* This is the (only) success case. */ - png_set_sCAL_s(png_ptr, info_ptr, buffer[0], - (png_charp)buffer+1, (png_charp)buffer+heighti); - } -} -#endif - -#ifdef PNG_READ_tIME_SUPPORTED -void /* PRIVATE */ -png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_byte buf[7]; - png_time mod_time; - - png_debug(1, "in png_handle_tIME"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - - if (length != 7) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - - png_crc_read(png_ptr, buf, 7); - - if (png_crc_finish(png_ptr, 0)) - return; - - mod_time.second = buf[6]; - mod_time.minute = buf[5]; - mod_time.hour = buf[4]; - mod_time.day = buf[3]; - mod_time.month = buf[2]; - mod_time.year = png_get_uint_16(buf); - - png_set_tIME(png_ptr, info_ptr, &mod_time); -} -#endif - -#ifdef PNG_READ_tEXt_SUPPORTED -/* Note: this does not properly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_text text_info; - png_bytep buffer; - png_charp key; - png_charp text; - png_uint_32 skip = 0; - - png_debug(1, "in png_handle_tEXt"); - -#ifdef PNG_USER_LIMITS_SUPPORTED - if (png_ptr->user_chunk_cache_max != 0) - { - if (png_ptr->user_chunk_cache_max == 1) - { - png_crc_finish(png_ptr, length); - return; - } - - if (--png_ptr->user_chunk_cache_max == 1) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "no space in chunk cache"); - return; - } - } -#endif - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - -#ifdef PNG_MAX_MALLOC_64K - if (length > 65535U) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "too large to fit in memory"); - return; - } -#endif - - buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/); - - if (buffer == NULL) - { - png_chunk_benign_error(png_ptr, "out of memory"); - return; - } - - png_crc_read(png_ptr, buffer, length); - - if (png_crc_finish(png_ptr, skip)) - return; - - key = (png_charp)buffer; - key[length] = 0; - - for (text = key; *text; text++) - /* Empty loop to find end of key */ ; - - if (text != key + length) - text++; - - text_info.compression = PNG_TEXT_COMPRESSION_NONE; - text_info.key = key; - text_info.lang = NULL; - text_info.lang_key = NULL; - text_info.itxt_length = 0; - text_info.text = text; - text_info.text_length = strlen(text); - - if (png_set_text_2(png_ptr, info_ptr, &text_info, 1)) - png_warning(png_ptr, "Insufficient memory to process text chunk"); -} -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED -/* Note: this does not correctly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_const_charp errmsg = NULL; - png_bytep buffer; - png_uint_32 keyword_length; - - png_debug(1, "in png_handle_zTXt"); - -#ifdef PNG_USER_LIMITS_SUPPORTED - if (png_ptr->user_chunk_cache_max != 0) - { - if (png_ptr->user_chunk_cache_max == 1) - { - png_crc_finish(png_ptr, length); - return; - } - - if (--png_ptr->user_chunk_cache_max == 1) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "no space in chunk cache"); - return; - } - } -#endif - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - - buffer = png_read_buffer(png_ptr, length, 2/*silent*/); - - if (buffer == NULL) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of memory"); - return; - } - - png_crc_read(png_ptr, buffer, length); - - if (png_crc_finish(png_ptr, 0)) - return; - - /* TODO: also check that the keyword contents match the spec! */ - for (keyword_length = 0; - keyword_length < length && buffer[keyword_length] != 0; - ++keyword_length) - /* Empty loop to find end of name */ ; - - if (keyword_length > 79 || keyword_length < 1) - errmsg = "bad keyword"; - - /* zTXt must have some LZ data after the keyword, although it may expand to - * zero bytes; we need a '\0' at the end of the keyword, the compression type - * then the LZ data: - */ - else if (keyword_length + 3 > length) - errmsg = "truncated"; - - else if (buffer[keyword_length+1] != PNG_COMPRESSION_TYPE_BASE) - errmsg = "unknown compression type"; - - else - { - png_alloc_size_t uncompressed_length = PNG_SIZE_MAX; - - /* TODO: at present png_decompress_chunk imposes a single application - * level memory limit, this should be split to different values for iCCP - * and text chunks. - */ - if (png_decompress_chunk(png_ptr, length, keyword_length+2, - &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) - { - png_text text; - - /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except - * for the extra compression type byte and the fact that it isn't - * necessarily '\0' terminated. - */ - buffer = png_ptr->read_buffer; - buffer[uncompressed_length+(keyword_length+2)] = 0; - - text.compression = PNG_TEXT_COMPRESSION_zTXt; - text.key = (png_charp)buffer; - text.text = (png_charp)(buffer + keyword_length+2); - text.text_length = uncompressed_length; - text.itxt_length = 0; - text.lang = NULL; - text.lang_key = NULL; - - if (png_set_text_2(png_ptr, info_ptr, &text, 1)) - errmsg = "insufficient memory"; - } - - else - errmsg = png_ptr->zstream.msg; - } - - if (errmsg != NULL) - png_chunk_benign_error(png_ptr, errmsg); -} -#endif - -#ifdef PNG_READ_iTXt_SUPPORTED -/* Note: this does not correctly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) -{ - png_const_charp errmsg = NULL; - png_bytep buffer; - png_uint_32 prefix_length; - - png_debug(1, "in png_handle_iTXt"); - -#ifdef PNG_USER_LIMITS_SUPPORTED - if (png_ptr->user_chunk_cache_max != 0) - { - if (png_ptr->user_chunk_cache_max == 1) - { - png_crc_finish(png_ptr, length); - return; - } - - if (--png_ptr->user_chunk_cache_max == 1) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "no space in chunk cache"); - return; - } - } -#endif - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_chunk_error(png_ptr, "missing IHDR"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - - buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/); - - if (buffer == NULL) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of memory"); - return; - } - - png_crc_read(png_ptr, buffer, length); - - if (png_crc_finish(png_ptr, 0)) - return; - - /* First the keyword. */ - for (prefix_length=0; - prefix_length < length && buffer[prefix_length] != 0; - ++prefix_length) - /* Empty loop */ ; - - /* Perform a basic check on the keyword length here. */ - if (prefix_length > 79 || prefix_length < 1) - errmsg = "bad keyword"; - - /* Expect keyword, compression flag, compression type, language, translated - * keyword (both may be empty but are 0 terminated) then the text, which may - * be empty. - */ - else if (prefix_length + 5 > length) - errmsg = "truncated"; - - else if (buffer[prefix_length+1] == 0 || - (buffer[prefix_length+1] == 1 && - buffer[prefix_length+2] == PNG_COMPRESSION_TYPE_BASE)) - { - int compressed = buffer[prefix_length+1] != 0; - png_uint_32 language_offset, translated_keyword_offset; - png_alloc_size_t uncompressed_length = 0; - - /* Now the language tag */ - prefix_length += 3; - language_offset = prefix_length; - - for (; prefix_length < length && buffer[prefix_length] != 0; - ++prefix_length) - /* Empty loop */ ; - - /* WARNING: the length may be invalid here, this is checked below. */ - translated_keyword_offset = ++prefix_length; - - for (; prefix_length < length && buffer[prefix_length] != 0; - ++prefix_length) - /* Empty loop */ ; - - /* prefix_length should now be at the trailing '\0' of the translated - * keyword, but it may already be over the end. None of this arithmetic - * can overflow because chunks are at most 2^31 bytes long, but on 16-bit - * systems the available allocaton may overflow. - */ - ++prefix_length; - - if (!compressed && prefix_length <= length) - uncompressed_length = length - prefix_length; - - else if (compressed && prefix_length < length) - { - uncompressed_length = PNG_SIZE_MAX; - - /* TODO: at present png_decompress_chunk imposes a single application - * level memory limit, this should be split to different values for - * iCCP and text chunks. - */ - if (png_decompress_chunk(png_ptr, length, prefix_length, - &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) - buffer = png_ptr->read_buffer; - - else - errmsg = png_ptr->zstream.msg; - } - - else - errmsg = "truncated"; - - if (errmsg == NULL) - { - png_text text; - - buffer[uncompressed_length+prefix_length] = 0; - - if (compressed) - text.compression = PNG_ITXT_COMPRESSION_NONE; - - else - text.compression = PNG_ITXT_COMPRESSION_zTXt; - - text.key = (png_charp)buffer; - text.lang = (png_charp)buffer + language_offset; - text.lang_key = (png_charp)buffer + translated_keyword_offset; - text.text = (png_charp)buffer + prefix_length; - text.text_length = 0; - text.itxt_length = uncompressed_length; - - if (png_set_text_2(png_ptr, info_ptr, &text, 1)) - errmsg = "insufficient memory"; - } - } - - else - errmsg = "bad compression info"; - - if (errmsg != NULL) - png_chunk_benign_error(png_ptr, errmsg); -} -#endif - -#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */ -static int -png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) -{ - png_alloc_size_t limit = PNG_SIZE_MAX; - - if (png_ptr->unknown_chunk.data != NULL) - { - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; - } - -# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED - if (png_ptr->user_chunk_malloc_max > 0 && - png_ptr->user_chunk_malloc_max < limit) - limit = png_ptr->user_chunk_malloc_max; - -# elif PNG_USER_CHUNK_MALLOC_MAX > 0 - if (PNG_USER_CHUNK_MALLOC_MAX < limit) - limit = PNG_USER_CHUNK_MALLOC_MAX; -# endif - - if (length <= limit) - { - PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); - /* The following is safe because of the PNG_SIZE_MAX init above */ - png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/; - /* 'mode' is a flag array, only the bottom four bits matter here */ - png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/; - - if (length == 0) - png_ptr->unknown_chunk.data = NULL; - - else - { - /* Do a 'warn' here - it is handled below. */ - png_ptr->unknown_chunk.data = png_voidcast(png_bytep, - png_malloc_warn(png_ptr, length)); - } - } - - if (png_ptr->unknown_chunk.data == NULL && length > 0) - { - /* This is benign because we clean up correctly */ - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "unknown chunk exceeds memory limits"); - return 0; - } - - else - { - if (length > 0) - png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length); - png_crc_finish(png_ptr, 0); - return 1; - } -} -#endif /* PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */ - -/* Handle an unknown, or known but disabled, chunk */ -void /* PRIVATE */ -png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, - png_uint_32 length, int keep) -{ - int handled = 0; /* the chunk was handled */ - - png_debug(1, "in png_handle_unknown"); - -#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED - /* NOTE: this code is based on the code in libpng-1.4.12 except for fixing - * the bug which meant that setting a non-default behavior for a specific - * chunk would be ignored (the default was always used unless a user - * callback was installed). - * - * 'keep' is the value from the png_chunk_unknown_handling, the setting for - * this specific chunk_name, if PNG_HANDLE_AS_UNKNOWN_SUPPORTED, if not it - * will always be PNG_HANDLE_CHUNK_AS_DEFAULT and it needs to be set here. - * This is just an optimization to avoid multiple calls to the lookup - * function. - */ -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name); -# endif -# endif - - /* One of the following methods will read the chunk or skip it (at least one - * of these is always defined because this is the only way to switch on - * PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - */ -# ifdef PNG_READ_USER_CHUNKS_SUPPORTED - /* The user callback takes precedence over the chunk keep value, but the - * keep value is still required to validate a save of a critical chunk. - */ - if (png_ptr->read_user_chunk_fn != NULL) - { - if (png_cache_unknown_chunk(png_ptr, length)) - { - /* Callback to user unknown chunk handler */ - int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr, - &png_ptr->unknown_chunk); - - /* ret is: - * negative: An error occured, png_chunk_error will be called. - * zero: The chunk was not handled, the chunk will be discarded - * unless png_set_keep_unknown_chunks has been used to set - * a 'keep' behavior for this particular chunk, in which - * case that will be used. A critical chunk will cause an - * error at this point unless it is to be saved. - * positive: The chunk was handled, libpng will ignore/discard it. - */ - if (ret < 0) - png_chunk_error(png_ptr, "error in user chunk"); - - else if (ret == 0) - { - /* If the keep value is 'default' or 'never' override it, but - * still error out on critical chunks unless the keep value is - * 'always' While this is weird it is the behavior in 1.4.12. - * A possible improvement would be to obey the value set for the - * chunk, but this would be an API change that would probably - * damage some applications. - * - * The png_app_warning below catches the case that matters, where - * the application has not set specific save or ignore for this - * chunk or global save or ignore. - */ - if (keep < PNG_HANDLE_CHUNK_IF_SAFE) - { -# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE) - { - png_chunk_warning(png_ptr, "Saving unknown chunk:"); - png_app_warning(png_ptr, - "forcing save of an unhandled chunk;" - " please call png_set_keep_unknown_chunks"); - /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */ - } -# endif - keep = PNG_HANDLE_CHUNK_IF_SAFE; - } - } - - else /* chunk was handled */ - { - handled = 1; - /* Critical chunks can be safely discarded at this point. */ - keep = PNG_HANDLE_CHUNK_NEVER; - } - } - - else - keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */ - } - - else - /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */ -# endif /* PNG_READ_USER_CHUNKS_SUPPORTED */ - -# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED - { - /* keep is currently just the per-chunk setting, if there was no - * setting change it to the global default now (not that this may - * still be AS_DEFAULT) then obtain the cache of the chunk if required, - * if not simply skip the chunk. - */ - if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT) - keep = png_ptr->unknown_default; - - if (keep == PNG_HANDLE_CHUNK_ALWAYS || - (keep == PNG_HANDLE_CHUNK_IF_SAFE && - PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))) - { - if (!png_cache_unknown_chunk(png_ptr, length)) - keep = PNG_HANDLE_CHUNK_NEVER; - } - - else - png_crc_finish(png_ptr, length); - } -# else -# ifndef PNG_READ_USER_CHUNKS_SUPPORTED -# error no method to support READ_UNKNOWN_CHUNKS -# endif - - { - /* If here there is no read callback pointer set and no support is - * compiled in to just save the unknown chunks, so simply skip this - * chunk. If 'keep' is something other than AS_DEFAULT or NEVER then - * the app has erroneously asked for unknown chunk saving when there - * is no support. - */ - if (keep > PNG_HANDLE_CHUNK_NEVER) - png_app_error(png_ptr, "no unknown chunk support available"); - - png_crc_finish(png_ptr, length); - } -# endif - -# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED - /* Now store the chunk in the chunk list if appropriate, and if the limits - * permit it. - */ - if (keep == PNG_HANDLE_CHUNK_ALWAYS || - (keep == PNG_HANDLE_CHUNK_IF_SAFE && - PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))) - { -# ifdef PNG_USER_LIMITS_SUPPORTED - switch (png_ptr->user_chunk_cache_max) - { - case 2: - png_ptr->user_chunk_cache_max = 1; - png_chunk_benign_error(png_ptr, "no space in chunk cache"); - /* FALL THROUGH */ - case 1: - /* NOTE: prior to 1.6.0 this case resulted in an unknown critical - * chunk being skipped, now there will be a hard error below. - */ - break; - - default: /* not at limit */ - --(png_ptr->user_chunk_cache_max); - /* FALL THROUGH */ - case 0: /* no limit */ -# endif /* PNG_USER_LIMITS_SUPPORTED */ - /* Here when the limit isn't reached or when limits are compiled - * out; store the chunk. - */ - png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); - handled = 1; -# ifdef PNG_USER_LIMITS_SUPPORTED - break; - } -# endif - } -# else /* no store support: the chunk must be handled by the user callback */ - PNG_UNUSED(info_ptr) -# endif - - /* Regardless of the error handling below the cached data (if any) can be - * freed now. Notice that the data is not freed if there is a png_error, but - * it will be freed by destroy_read_struct. - */ - if (png_ptr->unknown_chunk.data != NULL) - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; - -#else /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */ - /* There is no support to read an unknown chunk, so just skip it. */ - png_crc_finish(png_ptr, length); - PNG_UNUSED(info_ptr) - PNG_UNUSED(keep) -#endif /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */ - - /* Check for unhandled critical chunks */ - if (!handled && PNG_CHUNK_CRITICAL(png_ptr->chunk_name)) - png_chunk_error(png_ptr, "unhandled critical chunk"); -} - -/* This function is called to verify that a chunk name is valid. - * This function can't have the "critical chunk check" incorporated - * into it, since in the future we will need to be able to call user - * functions to handle unknown critical chunks after we check that - * the chunk name itself is valid. - */ - -/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is: - * - * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) - */ - -void /* PRIVATE */ -png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name) -{ - int i; - - png_debug(1, "in png_check_chunk_name"); - - for (i=1; i<=4; ++i) - { - int c = chunk_name & 0xff; - - if (c < 65 || c > 122 || (c > 90 && c < 97)) - png_chunk_error(png_ptr, "invalid chunk type"); - - chunk_name >>= 8; - } -} - -/* Combines the row recently read in with the existing pixels in the row. This - * routine takes care of alpha and transparency if requested. This routine also - * handles the two methods of progressive display of interlaced images, - * depending on the 'display' value; if 'display' is true then the whole row - * (dp) is filled from the start by replicating the available pixels. If - * 'display' is false only those pixels present in the pass are filled in. - */ -void /* PRIVATE */ -png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) -{ - unsigned int pixel_depth = png_ptr->transformed_pixel_depth; - png_const_bytep sp = png_ptr->row_buf + 1; - png_uint_32 row_width = png_ptr->width; - unsigned int pass = png_ptr->pass; - png_bytep end_ptr = 0; - png_byte end_byte = 0; - unsigned int end_mask; - - png_debug(1, "in png_combine_row"); - - /* Added in 1.5.6: it should not be possible to enter this routine until at - * least one row has been read from the PNG data and transformed. - */ - if (pixel_depth == 0) - png_error(png_ptr, "internal row logic error"); - - /* Added in 1.5.4: the pixel depth should match the information returned by - * any call to png_read_update_info at this point. Do not continue if we got - * this wrong. - */ - if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes != - PNG_ROWBYTES(pixel_depth, row_width)) - png_error(png_ptr, "internal row size calculation error"); - - /* Don't expect this to ever happen: */ - if (row_width == 0) - png_error(png_ptr, "internal row width error"); - - /* Preserve the last byte in cases where only part of it will be overwritten, - * the multiply below may overflow, we don't care because ANSI-C guarantees - * we get the low bits. - */ - end_mask = (pixel_depth * row_width) & 7; - if (end_mask != 0) - { - /* end_ptr == NULL is a flag to say do nothing */ - end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1; - end_byte = *end_ptr; -# ifdef PNG_READ_PACKSWAP_SUPPORTED - if (png_ptr->transformations & PNG_PACKSWAP) /* little-endian byte */ - end_mask = 0xff << end_mask; - - else /* big-endian byte */ -# endif - end_mask = 0xff >> end_mask; - /* end_mask is now the bits to *keep* from the destination row */ - } - - /* For non-interlaced images this reduces to a memcpy(). A memcpy() - * will also happen if interlacing isn't supported or if the application - * does not call png_set_interlace_handling(). In the latter cases the - * caller just gets a sequence of the unexpanded rows from each interlace - * pass. - */ -#ifdef PNG_READ_INTERLACING_SUPPORTED - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) && - pass < 6 && (display == 0 || - /* The following copies everything for 'display' on passes 0, 2 and 4. */ - (display == 1 && (pass & 1) != 0))) - { - /* Narrow images may have no bits in a pass; the caller should handle - * this, but this test is cheap: - */ - if (row_width <= PNG_PASS_START_COL(pass)) - return; - - if (pixel_depth < 8) - { - /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit - * into 32 bits, then a single loop over the bytes using the four byte - * values in the 32-bit mask can be used. For the 'display' option the - * expanded mask may also not require any masking within a byte. To - * make this work the PACKSWAP option must be taken into account - it - * simply requires the pixels to be reversed in each byte. - * - * The 'regular' case requires a mask for each of the first 6 passes, - * the 'display' case does a copy for the even passes in the range - * 0..6. This has already been handled in the test above. - * - * The masks are arranged as four bytes with the first byte to use in - * the lowest bits (little-endian) regardless of the order (PACKSWAP or - * not) of the pixels in each byte. - * - * NOTE: the whole of this logic depends on the caller of this function - * only calling it on rows appropriate to the pass. This function only - * understands the 'x' logic; the 'y' logic is handled by the caller. - * - * The following defines allow generation of compile time constant bit - * masks for each pixel depth and each possibility of swapped or not - * swapped bytes. Pass 'p' is in the range 0..6; 'x', a pixel index, - * is in the range 0..7; and the result is 1 if the pixel is to be - * copied in the pass, 0 if not. 'S' is for the sparkle method, 'B' - * for the block method. - * - * With some compilers a compile time expression of the general form: - * - * (shift >= 32) ? (a >> (shift-32)) : (b >> shift) - * - * Produces warnings with values of 'shift' in the range 33 to 63 - * because the right hand side of the ?: expression is evaluated by - * the compiler even though it isn't used. Microsoft Visual C (various - * versions) and the Intel C compiler are known to do this. To avoid - * this the following macros are used in 1.5.6. This is a temporary - * solution to avoid destabilizing the code during the release process. - */ -# if PNG_USE_COMPILE_TIME_MASKS -# define PNG_LSR(x,s) ((x)>>((s) & 0x1f)) -# define PNG_LSL(x,s) ((x)<<((s) & 0x1f)) -# else -# define PNG_LSR(x,s) ((x)>>(s)) -# define PNG_LSL(x,s) ((x)<<(s)) -# endif -# define S_COPY(p,x) (((p)<4 ? PNG_LSR(0x80088822,(3-(p))*8+(7-(x))) :\ - PNG_LSR(0xaa55ff00,(7-(p))*8+(7-(x)))) & 1) -# define B_COPY(p,x) (((p)<4 ? PNG_LSR(0xff0fff33,(3-(p))*8+(7-(x))) :\ - PNG_LSR(0xff55ff00,(7-(p))*8+(7-(x)))) & 1) - - /* Return a mask for pass 'p' pixel 'x' at depth 'd'. The mask is - * little endian - the first pixel is at bit 0 - however the extra - * parameter 's' can be set to cause the mask position to be swapped - * within each byte, to match the PNG format. This is done by XOR of - * the shift with 7, 6 or 4 for bit depths 1, 2 and 4. - */ -# define PIXEL_MASK(p,x,d,s) \ - (PNG_LSL(((PNG_LSL(1U,(d)))-1),(((x)*(d))^((s)?8-(d):0)))) - - /* Hence generate the appropriate 'block' or 'sparkle' pixel copy mask. - */ -# define S_MASKx(p,x,d,s) (S_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) -# define B_MASKx(p,x,d,s) (B_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) - - /* Combine 8 of these to get the full mask. For the 1-bpp and 2-bpp - * cases the result needs replicating, for the 4-bpp case the above - * generates a full 32 bits. - */ -# define MASK_EXPAND(m,d) ((m)*((d)==1?0x01010101:((d)==2?0x00010001:1))) - -# define S_MASK(p,d,s) MASK_EXPAND(S_MASKx(p,0,d,s) + S_MASKx(p,1,d,s) +\ - S_MASKx(p,2,d,s) + S_MASKx(p,3,d,s) + S_MASKx(p,4,d,s) +\ - S_MASKx(p,5,d,s) + S_MASKx(p,6,d,s) + S_MASKx(p,7,d,s), d) - -# define B_MASK(p,d,s) MASK_EXPAND(B_MASKx(p,0,d,s) + B_MASKx(p,1,d,s) +\ - B_MASKx(p,2,d,s) + B_MASKx(p,3,d,s) + B_MASKx(p,4,d,s) +\ - B_MASKx(p,5,d,s) + B_MASKx(p,6,d,s) + B_MASKx(p,7,d,s), d) - -#if PNG_USE_COMPILE_TIME_MASKS - /* Utility macros to construct all the masks for a depth/swap - * combination. The 's' parameter says whether the format is PNG - * (big endian bytes) or not. Only the three odd-numbered passes are - * required for the display/block algorithm. - */ -# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\ - S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) } - -# define B_MASKS(d,s) { B_MASK(1,d,s), S_MASK(3,d,s), S_MASK(5,d,s) } - -# define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2)) - - /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and - * then pass: - */ - static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = - { - /* Little-endian byte masks for PACKSWAP */ - { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) }, - /* Normal (big-endian byte) masks - PNG format */ - { S_MASKS(1,1), S_MASKS(2,1), S_MASKS(4,1) } - }; - - /* display_mask has only three entries for the odd passes, so index by - * pass>>1. - */ - static PNG_CONST png_uint_32 display_mask[2][3][3] = - { - /* Little-endian byte masks for PACKSWAP */ - { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) }, - /* Normal (big-endian byte) masks - PNG format */ - { B_MASKS(1,1), B_MASKS(2,1), B_MASKS(4,1) } - }; - -# define MASK(pass,depth,display,png)\ - ((display)?display_mask[png][DEPTH_INDEX(depth)][pass>>1]:\ - row_mask[png][DEPTH_INDEX(depth)][pass]) - -#else /* !PNG_USE_COMPILE_TIME_MASKS */ - /* This is the runtime alternative: it seems unlikely that this will - * ever be either smaller or faster than the compile time approach. - */ -# define MASK(pass,depth,display,png)\ - ((display)?B_MASK(pass,depth,png):S_MASK(pass,depth,png)) -#endif /* !PNG_USE_COMPILE_TIME_MASKS */ - - /* Use the appropriate mask to copy the required bits. In some cases - * the byte mask will be 0 or 0xff, optimize these cases. row_width is - * the number of pixels, but the code copies bytes, so it is necessary - * to special case the end. - */ - png_uint_32 pixels_per_byte = 8 / pixel_depth; - png_uint_32 mask; - -# ifdef PNG_READ_PACKSWAP_SUPPORTED - if (png_ptr->transformations & PNG_PACKSWAP) - mask = MASK(pass, pixel_depth, display, 0); - - else -# endif - mask = MASK(pass, pixel_depth, display, 1); - - for (;;) - { - png_uint_32 m; - - /* It doesn't matter in the following if png_uint_32 has more than - * 32 bits because the high bits always match those in m<<24; it is, - * however, essential to use OR here, not +, because of this. - */ - m = mask; - mask = (m >> 8) | (m << 24); /* rotate right to good compilers */ - m &= 0xff; - - if (m != 0) /* something to copy */ - { - if (m != 0xff) - *dp = (png_byte)((*dp & ~m) | (*sp & m)); - else - *dp = *sp; - } - - /* NOTE: this may overwrite the last byte with garbage if the image - * is not an exact number of bytes wide; libpng has always done - * this. - */ - if (row_width <= pixels_per_byte) - break; /* May need to restore part of the last byte */ - - row_width -= pixels_per_byte; - ++dp; - ++sp; - } - } - - else /* pixel_depth >= 8 */ - { - unsigned int bytes_to_copy, bytes_to_jump; - - /* Validate the depth - it must be a multiple of 8 */ - if (pixel_depth & 7) - png_error(png_ptr, "invalid user transform pixel depth"); - - pixel_depth >>= 3; /* now in bytes */ - row_width *= pixel_depth; - - /* Regardless of pass number the Adam 7 interlace always results in a - * fixed number of pixels to copy then to skip. There may be a - * different number of pixels to skip at the start though. - */ - { - unsigned int offset = PNG_PASS_START_COL(pass) * pixel_depth; - - row_width -= offset; - dp += offset; - sp += offset; - } - - /* Work out the bytes to copy. */ - if (display) - { - /* When doing the 'block' algorithm the pixel in the pass gets - * replicated to adjacent pixels. This is why the even (0,2,4,6) - * passes are skipped above - the entire expanded row is copied. - */ - bytes_to_copy = (1<<((6-pass)>>1)) * pixel_depth; - - /* But don't allow this number to exceed the actual row width. */ - if (bytes_to_copy > row_width) - bytes_to_copy = row_width; - } - - else /* normal row; Adam7 only ever gives us one pixel to copy. */ - bytes_to_copy = pixel_depth; - - /* In Adam7 there is a constant offset between where the pixels go. */ - bytes_to_jump = PNG_PASS_COL_OFFSET(pass) * pixel_depth; - - /* And simply copy these bytes. Some optimization is possible here, - * depending on the value of 'bytes_to_copy'. Special case the low - * byte counts, which we know to be frequent. - * - * Notice that these cases all 'return' rather than 'break' - this - * avoids an unnecessary test on whether to restore the last byte - * below. - */ - switch (bytes_to_copy) - { - case 1: - for (;;) - { - *dp = *sp; - - if (row_width <= bytes_to_jump) - return; - - dp += bytes_to_jump; - sp += bytes_to_jump; - row_width -= bytes_to_jump; - } - - case 2: - /* There is a possibility of a partial copy at the end here; this - * slows the code down somewhat. - */ - do - { - dp[0] = sp[0], dp[1] = sp[1]; - - if (row_width <= bytes_to_jump) - return; - - sp += bytes_to_jump; - dp += bytes_to_jump; - row_width -= bytes_to_jump; - } - while (row_width > 1); - - /* And there can only be one byte left at this point: */ - *dp = *sp; - return; - - case 3: - /* This can only be the RGB case, so each copy is exactly one - * pixel and it is not necessary to check for a partial copy. - */ - for(;;) - { - dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2]; - - if (row_width <= bytes_to_jump) - return; - - sp += bytes_to_jump; - dp += bytes_to_jump; - row_width -= bytes_to_jump; - } - - default: -#if PNG_ALIGN_TYPE != PNG_ALIGN_NONE - /* Check for double byte alignment and, if possible, use a - * 16-bit copy. Don't attempt this for narrow images - ones that - * are less than an interlace panel wide. Don't attempt it for - * wide bytes_to_copy either - use the memcpy there. - */ - if (bytes_to_copy < 16 /*else use memcpy*/ && - png_isaligned(dp, png_uint_16) && - png_isaligned(sp, png_uint_16) && - bytes_to_copy % (sizeof (png_uint_16)) == 0 && - bytes_to_jump % (sizeof (png_uint_16)) == 0) - { - /* Everything is aligned for png_uint_16 copies, but try for - * png_uint_32 first. - */ - if (png_isaligned(dp, png_uint_32) && - png_isaligned(sp, png_uint_32) && - bytes_to_copy % (sizeof (png_uint_32)) == 0 && - bytes_to_jump % (sizeof (png_uint_32)) == 0) - { - png_uint_32p dp32 = png_aligncast(png_uint_32p,dp); - png_const_uint_32p sp32 = png_aligncastconst( - png_const_uint_32p, sp); - size_t skip = (bytes_to_jump-bytes_to_copy) / - (sizeof (png_uint_32)); - - do - { - size_t c = bytes_to_copy; - do - { - *dp32++ = *sp32++; - c -= (sizeof (png_uint_32)); - } - while (c > 0); - - if (row_width <= bytes_to_jump) - return; - - dp32 += skip; - sp32 += skip; - row_width -= bytes_to_jump; - } - while (bytes_to_copy <= row_width); - - /* Get to here when the row_width truncates the final copy. - * There will be 1-3 bytes left to copy, so don't try the - * 16-bit loop below. - */ - dp = (png_bytep)dp32; - sp = (png_const_bytep)sp32; - do - *dp++ = *sp++; - while (--row_width > 0); - return; - } - - /* Else do it in 16-bit quantities, but only if the size is - * not too large. - */ - else - { - png_uint_16p dp16 = png_aligncast(png_uint_16p, dp); - png_const_uint_16p sp16 = png_aligncastconst( - png_const_uint_16p, sp); - size_t skip = (bytes_to_jump-bytes_to_copy) / - (sizeof (png_uint_16)); - - do - { - size_t c = bytes_to_copy; - do - { - *dp16++ = *sp16++; - c -= (sizeof (png_uint_16)); - } - while (c > 0); - - if (row_width <= bytes_to_jump) - return; - - dp16 += skip; - sp16 += skip; - row_width -= bytes_to_jump; - } - while (bytes_to_copy <= row_width); - - /* End of row - 1 byte left, bytes_to_copy > row_width: */ - dp = (png_bytep)dp16; - sp = (png_const_bytep)sp16; - do - *dp++ = *sp++; - while (--row_width > 0); - return; - } - } -#endif /* PNG_ALIGN_ code */ - - /* The true default - use a memcpy: */ - for (;;) - { - memcpy(dp, sp, bytes_to_copy); - - if (row_width <= bytes_to_jump) - return; - - sp += bytes_to_jump; - dp += bytes_to_jump; - row_width -= bytes_to_jump; - if (bytes_to_copy > row_width) - bytes_to_copy = row_width; - } - } - - /* NOT REACHED*/ - } /* pixel_depth >= 8 */ - - /* Here if pixel_depth < 8 to check 'end_ptr' below. */ - } - else -#endif - - /* If here then the switch above wasn't used so just memcpy the whole row - * from the temporary row buffer (notice that this overwrites the end of the - * destination row if it is a partial byte.) - */ - memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width)); - - /* Restore the overwritten bits from the last byte if necessary. */ - if (end_ptr != NULL) - *end_ptr = (png_byte)((end_byte & end_mask) | (*end_ptr & ~end_mask)); -} - -#ifdef PNG_READ_INTERLACING_SUPPORTED -void /* PRIVATE */ -png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, - png_uint_32 transformations /* Because these may affect the byte layout */) -{ - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* Offset to next interlace block */ - static PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - png_debug(1, "in png_do_read_interlace"); - if (row != NULL && row_info != NULL) - { - png_uint_32 final_width; - - final_width = row_info->width * png_pass_inc[pass]; - - switch (row_info->pixel_depth) - { - case 1: - { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; - png_byte v; - png_uint_32 i; - int j; - -#ifdef PNG_READ_PACKSWAP_SUPPORTED - if (transformations & PNG_PACKSWAP) - { - sshift = (int)((row_info->width + 7) & 0x07); - dshift = (int)((final_width + 7) & 0x07); - s_start = 7; - s_end = 0; - s_inc = -1; - } - - else -#endif - { - sshift = 7 - (int)((row_info->width + 7) & 0x07); - dshift = 7 - (int)((final_width + 7) & 0x07); - s_start = 0; - s_end = 7; - s_inc = 1; - } - - for (i = 0; i < row_info->width; i++) - { - v = (png_byte)((*sp >> sshift) & 0x01); - for (j = 0; j < jstop; j++) - { - unsigned int tmp = *dp & (0x7f7f >> (7 - dshift)); - tmp |= v << dshift; - *dp = (png_byte)(tmp & 0xff); - - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - - else - dshift += s_inc; - } - - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - - else - sshift += s_inc; - } - break; - } - - case 2: - { - png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); - png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; - png_uint_32 i; - -#ifdef PNG_READ_PACKSWAP_SUPPORTED - if (transformations & PNG_PACKSWAP) - { - sshift = (int)(((row_info->width + 3) & 0x03) << 1); - dshift = (int)(((final_width + 3) & 0x03) << 1); - s_start = 6; - s_end = 0; - s_inc = -2; - } - - else -#endif - { - sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); - dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); - s_start = 0; - s_end = 6; - s_inc = 2; - } - - for (i = 0; i < row_info->width; i++) - { - png_byte v; - int j; - - v = (png_byte)((*sp >> sshift) & 0x03); - for (j = 0; j < jstop; j++) - { - unsigned int tmp = *dp & (0x3f3f >> (6 - dshift)); - tmp |= v << dshift; - *dp = (png_byte)(tmp & 0xff); - - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - - else - dshift += s_inc; - } - - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - - else - sshift += s_inc; - } - break; - } - - case 4: - { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); - int sshift, dshift; - int s_start, s_end, s_inc; - png_uint_32 i; - int jstop = png_pass_inc[pass]; - -#ifdef PNG_READ_PACKSWAP_SUPPORTED - if (transformations & PNG_PACKSWAP) - { - sshift = (int)(((row_info->width + 1) & 0x01) << 2); - dshift = (int)(((final_width + 1) & 0x01) << 2); - s_start = 4; - s_end = 0; - s_inc = -4; - } - - else -#endif - { - sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); - dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); - s_start = 0; - s_end = 4; - s_inc = 4; - } - - for (i = 0; i < row_info->width; i++) - { - png_byte v = (png_byte)((*sp >> sshift) & 0x0f); - int j; - - for (j = 0; j < jstop; j++) - { - unsigned int tmp = *dp & (0xf0f >> (4 - dshift)); - tmp |= v << dshift; - *dp = (png_byte)(tmp & 0xff); - - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - - else - dshift += s_inc; - } - - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - - else - sshift += s_inc; - } - break; - } - - default: - { - png_size_t pixel_bytes = (row_info->pixel_depth >> 3); - - png_bytep sp = row + (png_size_t)(row_info->width - 1) - * pixel_bytes; - - png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; - - int jstop = png_pass_inc[pass]; - png_uint_32 i; - - for (i = 0; i < row_info->width; i++) - { - png_byte v[8]; /* SAFE; pixel_depth does not exceed 64 */ - int j; - - memcpy(v, sp, pixel_bytes); - - for (j = 0; j < jstop; j++) - { - memcpy(dp, v, pixel_bytes); - dp -= pixel_bytes; - } - - sp -= pixel_bytes; - } - break; - } - } - - row_info->width = final_width; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); - } -#ifndef PNG_READ_PACKSWAP_SUPPORTED - PNG_UNUSED(transformations) /* Silence compiler warning */ -#endif -} -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - -static void -png_read_filter_row_sub(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) -{ - png_size_t i; - png_size_t istop = row_info->rowbytes; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp = row + bpp; - - PNG_UNUSED(prev_row) - - for (i = bpp; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); - rp++; - } -} - -static void -png_read_filter_row_up(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) -{ - png_size_t i; - png_size_t istop = row_info->rowbytes; - png_bytep rp = row; - png_const_bytep pp = prev_row; - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } -} - -static void -png_read_filter_row_avg(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) -{ - png_size_t i; - png_bytep rp = row; - png_const_bytep pp = prev_row; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop = row_info->rowbytes - bpp; - - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + - ((int)(*pp++) / 2 )) & 0xff); - - rp++; - } - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + - (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); - - rp++; - } -} - -static void -png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) -{ - png_bytep rp_end = row + row_info->rowbytes; - int a, c; - - /* First pixel/byte */ - c = *prev_row++; - a = *row + c; - *row++ = (png_byte)a; - - /* Remainder */ - while (row < rp_end) - { - int b, pa, pb, pc, p; - - a &= 0xff; /* From previous iteration or start */ - b = *prev_row++; - - p = b - c; - pc = a - c; - -# ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -# else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -# endif - - /* Find the best predictor, the least of pa, pb, pc favoring the earlier - * ones in the case of a tie. - */ - if (pb < pa) pa = pb, a = b; - if (pc < pa) a = c; - - /* Calculate the current pixel in a, and move the previous row pixel to c - * for the next time round the loop - */ - c = b; - a += *row; - *row++ = (png_byte)a; - } -} - -static void -png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) -{ - int bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp_end = row + bpp; - - /* Process the first pixel in the row completely (this is the same as 'up' - * because there is only one candidate predictor for the first row). - */ - while (row < rp_end) - { - int a = *row + *prev_row++; - *row++ = (png_byte)a; - } - - /* Remainder */ - rp_end += row_info->rowbytes - bpp; - - while (row < rp_end) - { - int a, b, c, pa, pb, pc, p; - - c = *(prev_row - bpp); - a = *(row - bpp); - b = *prev_row++; - - p = b - c; - pc = a - c; - -# ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -# else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -# endif - - if (pb < pa) pa = pb, a = b; - if (pc < pa) a = c; - - c = b; - a += *row; - *row++ = (png_byte)a; - } -} - -static void -png_init_filter_functions(png_structrp pp) - /* This function is called once for every PNG image (except for PNG images - * that only use PNG_FILTER_VALUE_NONE for all rows) to set the - * implementations required to reverse the filtering of PNG rows. Reversing - * the filter is the first transformation performed on the row data. It is - * performed in place, therefore an implementation can be selected based on - * the image pixel format. If the implementation depends on image width then - * take care to ensure that it works correctly if the image is interlaced - - * interlacing causes the actual row width to vary. - */ -{ - unsigned int bpp = (pp->pixel_depth + 7) >> 3; - - pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub; - pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up; - pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg; - if (bpp == 1) - pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = - png_read_filter_row_paeth_1byte_pixel; - else - pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = - png_read_filter_row_paeth_multibyte_pixel; - -#ifdef PNG_FILTER_OPTIMIZATIONS - /* To use this define PNG_FILTER_OPTIMIZATIONS as the name of a function to - * call to install hardware optimizations for the above functions; simply - * replace whatever elements of the pp->read_filter[] array with a hardware - * specific (or, for that matter, generic) optimization. - * - * To see an example of this examine what configure.ac does when - * --enable-arm-neon is specified on the command line. - */ - PNG_FILTER_OPTIMIZATIONS(pp, bpp); -#endif -} - -void /* PRIVATE */ -png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row, - png_const_bytep prev_row, int filter) -{ - /* OPTIMIZATION: DO NOT MODIFY THIS FUNCTION, instead #define - * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic - * implementations. See png_init_filter_functions above. - */ - if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST) - { - if (pp->read_filter[0] == NULL) - png_init_filter_functions(pp); - - pp->read_filter[filter-1](row_info, row, prev_row); - } -} - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -void /* PRIVATE */ -png_read_IDAT_data(png_structrp png_ptr, png_bytep output, - png_alloc_size_t avail_out) -{ - /* Loop reading IDATs and decompressing the result into output[avail_out] */ - png_ptr->zstream.next_out = output; - png_ptr->zstream.avail_out = 0; /* safety: set below */ - - if (output == NULL) - avail_out = 0; - - do - { - int ret; - png_byte tmpbuf[PNG_INFLATE_BUF_SIZE]; - - if (png_ptr->zstream.avail_in == 0) - { - uInt avail_in; - png_bytep buffer; - - while (png_ptr->idat_size == 0) - { - png_crc_finish(png_ptr, 0); - - png_ptr->idat_size = png_read_chunk_header(png_ptr); - /* This is an error even in the 'check' case because the code just - * consumed a non-IDAT header. - */ - if (png_ptr->chunk_name != png_IDAT) - png_error(png_ptr, "Not enough image data"); - } - - avail_in = png_ptr->IDAT_read_size; - - if (avail_in > png_ptr->idat_size) - avail_in = (uInt)png_ptr->idat_size; - - /* A PNG with a gradually increasing IDAT size will defeat this attempt - * to minimize memory usage by causing lots of re-allocs, but - * realistically doing IDAT_read_size re-allocs is not likely to be a - * big problem. - */ - buffer = png_read_buffer(png_ptr, avail_in, 0/*error*/); - - png_crc_read(png_ptr, buffer, avail_in); - png_ptr->idat_size -= avail_in; - - png_ptr->zstream.next_in = buffer; - png_ptr->zstream.avail_in = avail_in; - } - - /* And set up the output side. */ - if (output != NULL) /* standard read */ - { - uInt out = ZLIB_IO_MAX; - - if (out > avail_out) - out = (uInt)avail_out; - - avail_out -= out; - png_ptr->zstream.avail_out = out; - } - - else /* after last row, checking for end */ - { - png_ptr->zstream.next_out = tmpbuf; - png_ptr->zstream.avail_out = (sizeof tmpbuf); - } - - /* Use NO_FLUSH; this gives zlib the maximum opportunity to optimize the - * process. If the LZ stream is truncated the sequential reader will - * terminally damage the stream, above, by reading the chunk header of the - * following chunk (it then exits with png_error). - * - * TODO: deal more elegantly with truncated IDAT lists. - */ - ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); - - /* Take the unconsumed output back. */ - if (output != NULL) - avail_out += png_ptr->zstream.avail_out; - - else /* avail_out counts the extra bytes */ - avail_out += (sizeof tmpbuf) - png_ptr->zstream.avail_out; - - png_ptr->zstream.avail_out = 0; - - if (ret == Z_STREAM_END) - { - /* Do this for safety; we won't read any more into this row. */ - png_ptr->zstream.next_out = NULL; - - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; - - if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0) - png_chunk_benign_error(png_ptr, "Extra compressed data"); - break; - } - - if (ret != Z_OK) - { - png_zstream_error(png_ptr, ret); - - if (output != NULL) - png_chunk_error(png_ptr, png_ptr->zstream.msg); - - else /* checking */ - { - png_chunk_benign_error(png_ptr, png_ptr->zstream.msg); - return; - } - } - } while (avail_out > 0); - - if (avail_out > 0) - { - /* The stream ended before the image; this is the same as too few IDATs so - * should be handled the same way. - */ - if (output != NULL) - png_error(png_ptr, "Not enough image data"); - - else /* the deflate stream contained extra data */ - png_chunk_benign_error(png_ptr, "Too much image data"); - } -} - -void /* PRIVATE */ -png_read_finish_IDAT(png_structrp png_ptr) -{ - /* We don't need any more data and the stream should have ended, however the - * LZ end code may actually not have been processed. In this case we must - * read it otherwise stray unread IDAT data or, more likely, an IDAT chunk - * may still remain to be consumed. - */ - if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) - { - /* The NULL causes png_read_IDAT_data to swallow any remaining bytes in - * the compressed stream, but the stream may be damaged too, so even after - * this call we may need to terminate the zstream ownership. - */ - png_read_IDAT_data(png_ptr, NULL, 0); - png_ptr->zstream.next_out = NULL; /* safety */ - - /* Now clear everything out for safety; the following may not have been - * done. - */ - if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) - { - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; - } - } - - /* If the zstream has not been released do it now *and* terminate the reading - * of the final IDAT chunk. - */ - if (png_ptr->zowner == png_IDAT) - { - /* Always do this; the pointers otherwise point into the read buffer. */ - png_ptr->zstream.next_in = NULL; - png_ptr->zstream.avail_in = 0; - - /* Now we no longer own the zstream. */ - png_ptr->zowner = 0; - - /* The slightly weird semantics of the sequential IDAT reading is that we - * are always in or at the end of an IDAT chunk, so we always need to do a - * crc_finish here. If idat_size is non-zero we also need to read the - * spurious bytes at the end of the chunk now. - */ - (void)png_crc_finish(png_ptr, png_ptr->idat_size); - } -} - -void /* PRIVATE */ -png_read_finish_row(png_structrp png_ptr) -{ -#ifdef PNG_READ_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - - png_debug(1, "in png_read_finish_row"); - png_ptr->row_number++; - if (png_ptr->row_number < png_ptr->num_rows) - return; - -#ifdef PNG_READ_INTERLACING_SUPPORTED - if (png_ptr->interlaced) - { - png_ptr->row_number = 0; - - /* TO DO: don't do this if prev_row isn't needed (requires - * read-ahead of the next row's filter byte. - */ - memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); - - do - { - png_ptr->pass++; - - if (png_ptr->pass >= 7) - break; - - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - - if (!(png_ptr->transformations & PNG_INTERLACE)) - { - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - } - - else /* if (png_ptr->transformations & PNG_INTERLACE) */ - break; /* libpng deinterlacing sees every row */ - - } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0); - - if (png_ptr->pass < 7) - return; - } -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - - /* Here after at the end of the last row of the last pass. */ - png_read_finish_IDAT(png_ptr); -} -#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ - -void /* PRIVATE */ -png_read_start_row(png_structrp png_ptr) -{ -#ifdef PNG_READ_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif - - int max_pixel_depth; - png_size_t row_bytes; - - png_debug(1, "in png_read_start_row"); - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED - png_init_read_transformations(png_ptr); -#endif -#ifdef PNG_READ_INTERLACING_SUPPORTED - if (png_ptr->interlaced) - { - if (!(png_ptr->transformations & PNG_INTERLACE)) - png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - - png_pass_ystart[0]) / png_pass_yinc[0]; - - else - png_ptr->num_rows = png_ptr->height; - - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - } - - else -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - { - png_ptr->num_rows = png_ptr->height; - png_ptr->iwidth = png_ptr->width; - } - - max_pixel_depth = png_ptr->pixel_depth; - - /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of - * calculations to calculate the final pixel depth, then - * png_do_read_transforms actually does the transforms. This means that the - * code which effectively calculates this value is actually repeated in three - * separate places. They must all match. Innocent changes to the order of - * transformations can and will break libpng in a way that causes memory - * overwrites. - * - * TODO: fix this. - */ -#ifdef PNG_READ_PACK_SUPPORTED - if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) - max_pixel_depth = 8; -#endif - -#ifdef PNG_READ_EXPAND_SUPPORTED - if (png_ptr->transformations & PNG_EXPAND) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (png_ptr->num_trans) - max_pixel_depth = 32; - - else - max_pixel_depth = 24; - } - - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - if (max_pixel_depth < 8) - max_pixel_depth = 8; - - if (png_ptr->num_trans) - max_pixel_depth *= 2; - } - - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - if (png_ptr->num_trans) - { - max_pixel_depth *= 4; - max_pixel_depth /= 3; - } - } - } -#endif - -#ifdef PNG_READ_EXPAND_16_SUPPORTED - if (png_ptr->transformations & PNG_EXPAND_16) - { -# ifdef PNG_READ_EXPAND_SUPPORTED - /* In fact it is an error if it isn't supported, but checking is - * the safe way. - */ - if (png_ptr->transformations & PNG_EXPAND) - { - if (png_ptr->bit_depth < 16) - max_pixel_depth *= 2; - } - else -# endif - png_ptr->transformations &= ~PNG_EXPAND_16; - } -#endif - -#ifdef PNG_READ_FILLER_SUPPORTED - if (png_ptr->transformations & (PNG_FILLER)) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - if (max_pixel_depth <= 8) - max_pixel_depth = 16; - - else - max_pixel_depth = 32; - } - - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB || - png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (max_pixel_depth <= 32) - max_pixel_depth = 32; - - else - max_pixel_depth = 64; - } - } -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED - if (png_ptr->transformations & PNG_GRAY_TO_RGB) - { - if ( -#ifdef PNG_READ_EXPAND_SUPPORTED - (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || -#endif -#ifdef PNG_READ_FILLER_SUPPORTED - (png_ptr->transformations & (PNG_FILLER)) || -#endif - png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (max_pixel_depth <= 16) - max_pixel_depth = 32; - - else - max_pixel_depth = 64; - } - - else - { - if (max_pixel_depth <= 8) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - max_pixel_depth = 32; - - else - max_pixel_depth = 24; - } - - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - max_pixel_depth = 64; - - else - max_pixel_depth = 48; - } - } -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ -defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) - if (png_ptr->transformations & PNG_USER_TRANSFORM) - { - int user_pixel_depth = png_ptr->user_transform_depth * - png_ptr->user_transform_channels; - - if (user_pixel_depth > max_pixel_depth) - max_pixel_depth = user_pixel_depth; - } -#endif - - /* This value is stored in png_struct and double checked in the row read - * code. - */ - png_ptr->maximum_pixel_depth = (png_byte)max_pixel_depth; - png_ptr->transformed_pixel_depth = 0; /* calculated on demand */ - - /* Align the width on the next larger 8 pixels. Mainly used - * for interlacing - */ - row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); - /* Calculate the maximum bytes needed, adding a byte and a pixel - * for safety's sake - */ - row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + - 1 + ((max_pixel_depth + 7) >> 3); - -#ifdef PNG_MAX_MALLOC_64K - if (row_bytes > (png_uint_32)65536L) - png_error(png_ptr, "This image requires a row greater than 64KB"); -#endif - - if (row_bytes + 48 > png_ptr->old_big_row_buf_size) - { - png_free(png_ptr, png_ptr->big_row_buf); - png_free(png_ptr, png_ptr->big_prev_row); - - if (png_ptr->interlaced) - png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, - row_bytes + 48); - - else - png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); - - png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48); - -#ifdef PNG_ALIGNED_MEMORY_SUPPORTED - /* Use 16-byte aligned memory for row_buf with at least 16 bytes - * of padding before and after row_buf; treat prev_row similarly. - * NOTE: the alignment is to the start of the pixels, one beyond the start - * of the buffer, because of the filter byte. Prior to libpng 1.5.6 this - * was incorrect; the filter byte was aligned, which had the exact - * opposite effect of that intended. - */ - { - png_bytep temp = png_ptr->big_row_buf + 32; - int extra = (int)((temp - (png_bytep)0) & 0x0f); - png_ptr->row_buf = temp - extra - 1/*filter byte*/; - - temp = png_ptr->big_prev_row + 32; - extra = (int)((temp - (png_bytep)0) & 0x0f); - png_ptr->prev_row = temp - extra - 1/*filter byte*/; - } - -#else - /* Use 31 bytes of padding before and 17 bytes after row_buf. */ - png_ptr->row_buf = png_ptr->big_row_buf + 31; - png_ptr->prev_row = png_ptr->big_prev_row + 31; -#endif - png_ptr->old_big_row_buf_size = row_bytes + 48; - } - -#ifdef PNG_MAX_MALLOC_64K - if (png_ptr->rowbytes > 65535) - png_error(png_ptr, "This image requires a row greater than 64KB"); - -#endif - if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1)) - png_error(png_ptr, "Row has too many bytes to allocate in memory"); - - memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); - - png_debug1(3, "width = %u,", png_ptr->width); - png_debug1(3, "height = %u,", png_ptr->height); - png_debug1(3, "iwidth = %u,", png_ptr->iwidth); - png_debug1(3, "num_rows = %u,", png_ptr->num_rows); - png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes); - png_debug1(3, "irowbytes = %lu", - (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); - - /* The sequential reader needs a buffer for IDAT, but the progressive reader - * does not, so free the read buffer now regardless; the sequential reader - * reallocates it on demand. - */ - if (png_ptr->read_buffer) - { - png_bytep buffer = png_ptr->read_buffer; - - png_ptr->read_buffer_size = 0; - png_ptr->read_buffer = NULL; - png_free(png_ptr, buffer); - } - - /* Finally claim the zstream for the inflate of the IDAT data, use the bits - * value from the stream (note that this will result in a fatal error if the - * IDAT stream has a bogus deflate header window_bits value, but this should - * not be happening any longer!) - */ - if (png_inflate_claim(png_ptr, png_IDAT) != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg); - - png_ptr->flags |= PNG_FLAG_ROW_INIT; -} -#endif /* PNG_READ_SUPPORTED */ + +/* pngrutil.c - utilities to read a PNG file + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) +/* The following is a variation on the above for use with the fixed + * point values used for gAMA and cHRM. Instead of png_error it + * issues a warning and returns (-1) - an invalid value because both + * gAMA and cHRM use *unsigned* integers for fixed point values. + */ +#define PNG_FIXED_ERROR (-1) + +static png_fixed_point /* PRIVATE */ +png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval <= PNG_UINT_31_MAX) + return (png_fixed_point)uval; /* known to be in range */ + + /* The caller can turn off the warning by passing NULL. */ + if (png_ptr != NULL) + png_warning(png_ptr, "PNG fixed point integer out of range"); + + return PNG_FIXED_ERROR; +} +#endif /* READ_gAMA or READ_cHRM */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +/* NOTE: the read macros will obscure these definitions, so that if + * PNG_USE_READ_MACROS is set the library will not use them internally, + * but the APIs will still be available externally. + * + * The parentheses around "PNGAPI function_name" in the following three + * functions are necessary because they allow the macros to co-exist with + * these (unused but exported) functions. + */ + +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 (PNGAPI +png_get_uint_32)(png_const_bytep buf) +{ + return PNG_U32(buf[0], buf[1], buf[2], buf[3]); +} + +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format and there + * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore + * the following code does a two's complement to native conversion. + */ +png_int_32 (PNGAPI +png_get_int_32)(png_const_bytep buf) +{ + return PNG_S32(buf[0], buf[1], buf[2], buf[3]); +} + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 (PNGAPI +png_get_uint_16)(png_const_bytep buf) +{ + return PNG_U16(buf[0], buf[1]); +} +#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */ + +/* This is an exported function however its error handling is too harsh for most + * internal use. For example if it were used for reading the chunk parameters + * it would error out even on ancillary chunks that can be ignored. + */ +png_uint_32 PNGAPI +png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range"); + + return uval; +} + +/* Read and check the PNG file signature */ +void /* PRIVATE */ +png_read_sig(png_structrp png_ptr, png_inforp info_ptr) +{ + png_size_t num_checked, num_to_check; + + /* Exit if the user application does not expect a signature. */ + if (png_ptr->sig_bytes >= 8) + return; + + num_checked = png_ptr->sig_bytes; + num_to_check = 8 - num_checked; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; +#endif + + /* The signature must be serialized in a single I/O call. */ + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Read the chunk header (length + type name). + * Put the type name into png_ptr->chunk_name, and return the length. + */ +png_uint_32 /* PRIVATE */ +png_read_chunk_header(png_structrp png_ptr) +{ + png_byte buf[8]; + png_uint_32 length; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; +#endif + + /* Read the length and the chunk name. + * This must be performed in a single I/O call. + */ + png_read_data(png_ptr, buf, 8); + length = png_get_uint_31(png_ptr, buf); + + /* Put the chunk name into png_ptr->chunk_name. */ + png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4); + + png_debug2(0, "Reading %lx chunk, length = %lu", + (unsigned long)png_ptr->chunk_name, (unsigned long)length); + + /* Reset the crc and run it over the chunk name. */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, buf + 4, 4); + + /* Check to see if chunk name is valid. */ + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; +#endif + + return length; +} + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length) +{ + if (png_ptr == NULL) + return; + + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + * are reading an ancillary or critical chunk, and how the program has set + * things up, we may calculate the CRC on the data and print a message. + * Returns '1' if there was a CRC error, '0' otherwise. + */ +int /* PRIVATE */ +png_crc_finish(png_structrp png_ptr, png_uint_32 skip) +{ + /* The size of the local buffer for inflate is a good guess as to a + * reasonable size to use for buffering reads from the application. + */ + while (skip > 0) + { + png_uint_32 len; + png_byte tmpbuf[PNG_INFLATE_BUF_SIZE]; + + len = (sizeof tmpbuf); + if (len > skip) + len = skip; + skip -= len; + + png_crc_read(png_ptr, tmpbuf, len); + } + + if (png_crc_error(png_ptr)) + { + if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) ? + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) : + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + + else + png_chunk_error(png_ptr, "CRC error"); + + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + * the data it has read thus far. + */ +int /* PRIVATE */ +png_crc_error(png_structrp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)) + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; +#endif + + /* The chunk CRC must be serialized in a single I/O call. */ + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc != 0) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + + else + return (0); +} + +#if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\ + defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_sCAL_SUPPORTED) ||\ + defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) ||\ + defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_SEQUENTIAL_READ_SUPPORTED) +/* Manage the read buffer; this simply reallocates the buffer if it is not small + * enough (or if it is not allocated). The routine returns a pointer to the + * buffer; if an error occurs and 'warn' is set the routine returns NULL, else + * it will call png_error (via png_malloc) on failure. (warn == 2 means + * 'silent'). + */ +static png_bytep +png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) +{ + png_bytep buffer = png_ptr->read_buffer; + + if (buffer != NULL && new_size > png_ptr->read_buffer_size) + { + png_ptr->read_buffer = NULL; + png_ptr->read_buffer = NULL; + png_ptr->read_buffer_size = 0; + png_free(png_ptr, buffer); + buffer = NULL; + } + + if (buffer == NULL) + { + buffer = png_voidcast(png_bytep, png_malloc_base(png_ptr, new_size)); + + if (buffer != NULL) + { + png_ptr->read_buffer = buffer; + png_ptr->read_buffer_size = new_size; + } + + else if (warn < 2) /* else silent */ + { + if (warn != 0) + png_chunk_warning(png_ptr, "insufficient memory to read chunk"); + + else + png_chunk_error(png_ptr, "insufficient memory to read chunk"); + } + } + + return buffer; +} +#endif /* PNG_READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|SEQUENTIAL_READ */ + +/* png_inflate_claim: claim the zstream for some nefarious purpose that involves + * decompression. Returns Z_OK on success, else a zlib error code. It checks + * the owner but, in final release builds, just issues a warning if some other + * chunk apparently owns the stream. Prior to release it does a png_error. + */ +static int +png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) +{ + if (png_ptr->zowner != 0) + { + char msg[64]; + + PNG_STRING_FROM_CHUNK(msg, png_ptr->zowner); + /* So the message that results is " using zstream"; this is an + * internal error, but is very useful for debugging. i18n requirements + * are minimal. + */ + (void)png_safecat(msg, (sizeof msg), 4, " using zstream"); +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC + png_chunk_warning(png_ptr, msg); + png_ptr->zowner = 0; +# else + png_chunk_error(png_ptr, msg); +# endif + } + + /* Implementation note: unlike 'png_deflate_claim' this internal function + * does not take the size of the data as an argument. Some efficiency could + * be gained by using this when it is known *if* the zlib stream itself does + * not record the number; however, this is an illusion: the original writer + * of the PNG may have selected a lower window size, and we really must + * follow that because, for systems with with limited capabilities, we + * would otherwise reject the application's attempts to use a smaller window + * size (zlib doesn't have an interface to say "this or lower"!). + * + * inflateReset2 was added to zlib 1.2.4; before this the window could not be + * reset, therefore it is necessary to always allocate the maximum window + * size with earlier zlibs just in case later compressed chunks need it. + */ + { + int ret; /* zlib return code */ +# if PNG_ZLIB_VERNUM >= 0x1240 + +# if defined(PNG_SET_OPTION_SUPPORTED) && \ + defined(PNG_MAXIMUM_INFLATE_WINDOW) + int window_bits; + + if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) == + PNG_OPTION_ON) + window_bits = 15; + + else + window_bits = 0; +# else +# define window_bits 0 +# endif +# endif + + /* Set this for safety, just in case the previous owner left pointers to + * memory allocations. + */ + png_ptr->zstream.next_in = NULL; + png_ptr->zstream.avail_in = 0; + png_ptr->zstream.next_out = NULL; + png_ptr->zstream.avail_out = 0; + + if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) + { +# if PNG_ZLIB_VERNUM < 0x1240 + ret = inflateReset(&png_ptr->zstream); +# else + ret = inflateReset2(&png_ptr->zstream, window_bits); +# endif + } + + else + { +# if PNG_ZLIB_VERNUM < 0x1240 + ret = inflateInit(&png_ptr->zstream); +# else + ret = inflateInit2(&png_ptr->zstream, window_bits); +# endif + + if (ret == Z_OK) + png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; + } + + if (ret == Z_OK) + png_ptr->zowner = owner; + + else + png_zstream_error(png_ptr, ret); + + return ret; + } + +# ifdef window_bits +# undef window_bits +# endif +} + +#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED +/* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to + * allow the caller to do multiple calls if required. If the 'finish' flag is + * set Z_FINISH will be passed to the final inflate() call and Z_STREAM_END must + * be returned or there has been a problem, otherwise Z_SYNC_FLUSH is used and + * Z_OK or Z_STREAM_END will be returned on success. + * + * The input and output sizes are updated to the actual amounts of data consumed + * or written, not the amount available (as in a z_stream). The data pointers + * are not changed, so the next input is (data+input_size) and the next + * available output is (output+output_size). + */ +static int +png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, + /* INPUT: */ png_const_bytep input, png_uint_32p input_size_ptr, + /* OUTPUT: */ png_bytep output, png_alloc_size_t *output_size_ptr) +{ + if (png_ptr->zowner == owner) /* Else not claimed */ + { + int ret; + png_alloc_size_t avail_out = *output_size_ptr; + png_uint_32 avail_in = *input_size_ptr; + + /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it + * can't even necessarily handle 65536 bytes) because the type uInt is + * "16 bits or more". Consequently it is necessary to chunk the input to + * zlib. This code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the + * maximum value that can be stored in a uInt.) It is possible to set + * ZLIB_IO_MAX to a lower value in pngpriv.h and this may sometimes have + * a performance advantage, because it reduces the amount of data accessed + * at each step and that may give the OS more time to page it in. + */ + png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); + /* avail_in and avail_out are set below from 'size' */ + png_ptr->zstream.avail_in = 0; + png_ptr->zstream.avail_out = 0; + + /* Read directly into the output if it is available (this is set to + * a local buffer below if output is NULL). + */ + if (output != NULL) + png_ptr->zstream.next_out = output; + + do + { + uInt avail; + Byte local_buffer[PNG_INFLATE_BUF_SIZE]; + + /* zlib INPUT BUFFER */ + /* The setting of 'avail_in' used to be outside the loop; by setting it + * inside it is possible to chunk the input to zlib and simply rely on + * zlib to advance the 'next_in' pointer. This allows arbitrary + * amounts of data to be passed through zlib at the unavoidable cost of + * requiring a window save (memcpy of up to 32768 output bytes) + * every ZLIB_IO_MAX input bytes. + */ + avail_in += png_ptr->zstream.avail_in; /* not consumed last time */ + + avail = ZLIB_IO_MAX; + + if (avail_in < avail) + avail = (uInt)avail_in; /* safe: < than ZLIB_IO_MAX */ + + avail_in -= avail; + png_ptr->zstream.avail_in = avail; + + /* zlib OUTPUT BUFFER */ + avail_out += png_ptr->zstream.avail_out; /* not written last time */ + + avail = ZLIB_IO_MAX; /* maximum zlib can process */ + + if (output == NULL) + { + /* Reset the output buffer each time round if output is NULL and + * make available the full buffer, up to 'remaining_space' + */ + png_ptr->zstream.next_out = local_buffer; + if ((sizeof local_buffer) < avail) + avail = (sizeof local_buffer); + } + + if (avail_out < avail) + avail = (uInt)avail_out; /* safe: < ZLIB_IO_MAX */ + + png_ptr->zstream.avail_out = avail; + avail_out -= avail; + + /* zlib inflate call */ + /* In fact 'avail_out' may be 0 at this point, that happens at the end + * of the read when the final LZ end code was not passed at the end of + * the previous chunk of input data. Tell zlib if we have reached the + * end of the output buffer. + */ + ret = inflate(&png_ptr->zstream, avail_out > 0 ? Z_NO_FLUSH : + (finish ? Z_FINISH : Z_SYNC_FLUSH)); + } while (ret == Z_OK); + + /* For safety kill the local buffer pointer now */ + if (output == NULL) + png_ptr->zstream.next_out = NULL; + + /* Claw back the 'size' and 'remaining_space' byte counts. */ + avail_in += png_ptr->zstream.avail_in; + avail_out += png_ptr->zstream.avail_out; + + /* Update the input and output sizes; the updated values are the amount + * consumed or written, effectively the inverse of what zlib uses. + */ + if (avail_out > 0) + *output_size_ptr -= avail_out; + + if (avail_in > 0) + *input_size_ptr -= avail_in; + + /* Ensure png_ptr->zstream.msg is set (even in the success case!) */ + png_zstream_error(png_ptr, ret); + return ret; + } + + else + { + /* This is a bad internal error. The recovery assigns to the zstream msg + * pointer, which is not owned by the caller, but this is safe; it's only + * used on errors! + */ + png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed"); + return Z_STREAM_ERROR; + } +} + +/* + * Decompress trailing data in a chunk. The assumption is that read_buffer + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +static int +png_decompress_chunk(png_structrp png_ptr, + png_uint_32 chunklength, png_uint_32 prefix_size, + png_alloc_size_t *newlength /* must be initialized to the maximum! */, + int terminate /*add a '\0' to the end of the uncompressed data*/) +{ + /* TODO: implement different limits for different types of chunk. + * + * The caller supplies *newlength set to the maximum length of the + * uncompressed data, but this routine allocates space for the prefix and + * maybe a '\0' terminator too. We have to assume that 'prefix_size' is + * limited only by the maximum chunk size. + */ + png_alloc_size_t limit = PNG_SIZE_MAX; + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < limit) + limit = png_ptr->user_chunk_malloc_max; +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + if (PNG_USER_CHUNK_MALLOC_MAX < limit) + limit = PNG_USER_CHUNK_MALLOC_MAX; +# endif + + if (limit >= prefix_size + (terminate != 0)) + { + int ret; + + limit -= prefix_size + (terminate != 0); + + if (limit < *newlength) + *newlength = limit; + + /* Now try to claim the stream. */ + ret = png_inflate_claim(png_ptr, png_ptr->chunk_name); + + if (ret == Z_OK) + { + png_uint_32 lzsize = chunklength - prefix_size; + + ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, + /* input: */ png_ptr->read_buffer + prefix_size, &lzsize, + /* output: */ NULL, newlength); + + if (ret == Z_STREAM_END) + { + /* Use 'inflateReset' here, not 'inflateReset2' because this + * preserves the previously decided window size (otherwise it would + * be necessary to store the previous window size.) In practice + * this doesn't matter anyway, because png_inflate will call inflate + * with Z_FINISH in almost all cases, so the window will not be + * maintained. + */ + if (inflateReset(&png_ptr->zstream) == Z_OK) + { + /* Because of the limit checks above we know that the new, + * expanded, size will fit in a size_t (let alone an + * png_alloc_size_t). Use png_malloc_base here to avoid an + * extra OOM message. + */ + png_alloc_size_t new_size = *newlength; + png_alloc_size_t buffer_size = prefix_size + new_size + + (terminate != 0); + png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr, + buffer_size)); + + if (text != NULL) + { + ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, + png_ptr->read_buffer + prefix_size, &lzsize, + text + prefix_size, newlength); + + if (ret == Z_STREAM_END) + { + if (new_size == *newlength) + { + if (terminate != 0) + text[prefix_size + *newlength] = 0; + + if (prefix_size > 0) + memcpy(text, png_ptr->read_buffer, prefix_size); + + { + png_bytep old_ptr = png_ptr->read_buffer; + + png_ptr->read_buffer = text; + png_ptr->read_buffer_size = buffer_size; + text = old_ptr; /* freed below */ + } + } + + else + { + /* The size changed on the second read, there can be no + * guarantee that anything is correct at this point. + * The 'msg' pointer has been set to "unexpected end of + * LZ stream", which is fine, but return an error code + * that the caller won't accept. + */ + ret = PNG_UNEXPECTED_ZLIB_RETURN; + } + } + + else if (ret == Z_OK) + ret = PNG_UNEXPECTED_ZLIB_RETURN; /* for safety */ + + /* Free the text pointer (this is the old read_buffer on + * success) + */ + png_free(png_ptr, text); + + /* This really is very benign, but it's still an error because + * the extra space may otherwise be used as a Trojan Horse. + */ + if (ret == Z_STREAM_END && + chunklength - prefix_size != lzsize) + png_chunk_benign_error(png_ptr, "extra compressed data"); + } + + else + { + /* Out of memory allocating the buffer */ + ret = Z_MEM_ERROR; + png_zstream_error(png_ptr, Z_MEM_ERROR); + } + } + + else + { + /* inflateReset failed, store the error message */ + png_zstream_error(png_ptr, ret); + + if (ret == Z_STREAM_END) + ret = PNG_UNEXPECTED_ZLIB_RETURN; + } + } + + else if (ret == Z_OK) + ret = PNG_UNEXPECTED_ZLIB_RETURN; + + /* Release the claimed stream */ + png_ptr->zowner = 0; + } + + else /* the claim failed */ if (ret == Z_STREAM_END) /* impossible! */ + ret = PNG_UNEXPECTED_ZLIB_RETURN; + + return ret; + } + + else + { + /* Application/configuration limits exceeded */ + png_zstream_error(png_ptr, Z_MEM_ERROR); + return Z_MEM_ERROR; + } +} +#endif /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */ + +#ifdef PNG_READ_iCCP_SUPPORTED +/* Perform a partial read and decompress, producing 'avail_out' bytes and + * reading from the current chunk as required. + */ +static int +png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, + png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size, + int finish) +{ + if (png_ptr->zowner == png_ptr->chunk_name) + { + int ret; + + /* next_in and avail_in must have been initialized by the caller. */ + png_ptr->zstream.next_out = next_out; + png_ptr->zstream.avail_out = 0; /* set in the loop */ + + do + { + if (png_ptr->zstream.avail_in == 0) + { + if (read_size > *chunk_bytes) + read_size = (uInt)*chunk_bytes; + *chunk_bytes -= read_size; + + if (read_size > 0) + png_crc_read(png_ptr, read_buffer, read_size); + + png_ptr->zstream.next_in = read_buffer; + png_ptr->zstream.avail_in = read_size; + } + + if (png_ptr->zstream.avail_out == 0) + { + uInt avail = ZLIB_IO_MAX; + if (avail > *out_size) + avail = (uInt)*out_size; + *out_size -= avail; + + png_ptr->zstream.avail_out = avail; + } + + /* Use Z_SYNC_FLUSH when there is no more chunk data to ensure that all + * the available output is produced; this allows reading of truncated + * streams. + */ + ret = inflate(&png_ptr->zstream, + *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); + } + while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0)); + + *out_size += png_ptr->zstream.avail_out; + png_ptr->zstream.avail_out = 0; /* Should not be required, but is safe */ + + /* Ensure the error message pointer is always set: */ + png_zstream_error(png_ptr, ret); + return ret; + } + + else + { + png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed"); + return Z_STREAM_ERROR; + } +} +#endif + +/* Read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_chunk_error(png_ptr, "out of place"); + + /* Check the length */ + if (length != 13) + png_chunk_error(png_ptr, "invalid"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, buf); + height = png_get_uint_31(png_ptr, buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + + /* Set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + + /* Find number of channels */ + switch (png_ptr->color_type) + { + default: /* invalid, png_set_IHDR calls png_error */ + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* Set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); + png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); + png_debug1(3, "channels = %d", png_ptr->channels); + png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* Read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifdef PNG_POINTER_INDEXING_SUPPORTED + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + /* Moved to before the 'after IDAT' check below because otherwise duplicate + * PLTE chunks are potentially ignored (the spec says there shall not be more + * than one PLTE, the error is not treated as benign, so this check trumps + * the requirement that PLTE appears before IDAT.) + */ + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_chunk_error(png_ptr, "duplicate"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + /* This is benign because the non-benign error happened before, when an + * IDAT was encountered in a color-mapped image with no PLTE. + */ + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "ignored in grayscale PNG"); + return; + } + +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + png_crc_finish(png_ptr, length); + + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + png_chunk_benign_error(png_ptr, "invalid"); + + else + png_chunk_error(png_ptr, "invalid"); + + return; + } + + /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */ + num = (int)length / 3; + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* Don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually need the PLTE chunk (ie for a paletted image), we do + * whatever the normal CRC configuration tells us. However, if we + * have an RGB image, the PLTE can be considered ancillary, so + * we will act as though it is. + */ +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } + +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + * we have two options: an error abort, or a warning and we + * ignore the data in this chunk (which should be OK, since + * it's considered ancillary for a RGB or RGBA image). + * + * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the + * chunk type to determine whether to check the ancillary or the critical + * flags. + */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + return; + + else + png_chunk_error(png_ptr, "CRC error"); + } + + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its + * own copy of the palette. This has the side effect that when png_start_row + * is called (this happens after any call to png_read_update_info) the + * info_ptr palette gets changed. This is extremely unexpected and + * confusing. + * + * Fix this by not sharing the palette in this way. + */ + png_set_PLTE(png_ptr, info_ptr, palette, num); + + /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before + * IDAT. Prior to 1.6.0 this was not checked; instead the code merely + * checked the apparent validity of a tRNS chunk inserted before PLTE on a + * palette PNG. 1.6.0 attempts to rigorously follow the standard and + * therefore does a benign error if the erroneous condition is detected *and* + * cancels the tRNS if the benign error returns. The alternative is to + * amend the standard since it would be rather hypocritical of the standards + * maintainers to ignore it. + */ +#ifdef PNG_READ_tRNS_SUPPORTED + if (png_ptr->num_trans > 0 || + (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0)) + { + /* Cancel this because otherwise it would be used if the transforms + * require it. Don't cancel the 'valid' flag because this would prevent + * detection of duplicate chunks. + */ + png_ptr->num_trans = 0; + + if (info_ptr != NULL) + info_ptr->num_trans = 0; + + png_chunk_benign_error(png_ptr, "tRNS must be after"); + } +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0) + png_chunk_benign_error(png_ptr, "hIST must be after"); +#endif + +#ifdef PNG_READ_bKGD_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0) + png_chunk_benign_error(png_ptr, "bKGD must be after"); +#endif +} + +void /* PRIVATE */ +png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + png_chunk_error(png_ptr, "out of place"); + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + png_crc_finish(png_ptr, length); + + if (length != 0) + png_chunk_benign_error(png_ptr, "invalid"); + + PNG_UNUSED(info_ptr) +} + +#ifdef PNG_READ_gAMA_SUPPORTED +void /* PRIVATE */ +png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + if (length != 4) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 4); + + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = png_get_fixed_point(NULL, buf); + + png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma); + png_colorspace_sync(png_ptr, info_ptr); +} +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +void /* PRIVATE */ +png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + unsigned int truelen, i; + png_byte sample_depth; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + truelen = 3; + sample_depth = 8; + } + + else + { + truelen = png_ptr->channels; + sample_depth = png_ptr->bit_depth; + } + + if (length != truelen || length > 4) + { + png_chunk_benign_error(png_ptr, "invalid"); + png_crc_finish(png_ptr, length); + return; + } + + buf[0] = buf[1] = buf[2] = buf[3] = sample_depth; + png_crc_read(png_ptr, buf, truelen); + + if (png_crc_finish(png_ptr, 0)) + return; + + for (i=0; i sample_depth) + { + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +void /* PRIVATE */ +png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[32]; + png_xy xy; + + png_debug(1, "in png_handle_cHRM"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + if (length != 32) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 32); + + if (png_crc_finish(png_ptr, 0)) + return; + + xy.whitex = png_get_fixed_point(NULL, buf); + xy.whitey = png_get_fixed_point(NULL, buf + 4); + xy.redx = png_get_fixed_point(NULL, buf + 8); + xy.redy = png_get_fixed_point(NULL, buf + 12); + xy.greenx = png_get_fixed_point(NULL, buf + 16); + xy.greeny = png_get_fixed_point(NULL, buf + 20); + xy.bluex = png_get_fixed_point(NULL, buf + 24); + xy.bluey = png_get_fixed_point(NULL, buf + 28); + + if (xy.whitex == PNG_FIXED_ERROR || + xy.whitey == PNG_FIXED_ERROR || + xy.redx == PNG_FIXED_ERROR || + xy.redy == PNG_FIXED_ERROR || + xy.greenx == PNG_FIXED_ERROR || + xy.greeny == PNG_FIXED_ERROR || + xy.bluex == PNG_FIXED_ERROR || + xy.bluey == PNG_FIXED_ERROR) + { + png_chunk_benign_error(png_ptr, "invalid values"); + return; + } + + /* If a colorspace error has already been output skip this chunk */ + if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) + return; + + if (png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) + { + png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; + png_colorspace_sync(png_ptr, info_ptr); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; + (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy, + 1/*prefer cHRM values*/); + png_colorspace_sync(png_ptr, info_ptr); +} +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED +void /* PRIVATE */ +png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte intent; + + png_debug(1, "in png_handle_sRGB"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + if (length != 1) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, &intent, 1); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* If a colorspace error has already been output skip this chunk */ + if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) + return; + + /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect + * this. + */ + if (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) + { + png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; + png_colorspace_sync(png_ptr, info_ptr); + png_chunk_benign_error(png_ptr, "too many profiles"); + return; + } + + (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent); + png_colorspace_sync(png_ptr, info_ptr); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_READ_iCCP_SUPPORTED +void /* PRIVATE */ +png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +/* Note: this does not properly handle profiles that are > 64K under DOS */ +{ + png_const_charp errmsg = NULL; /* error message output, or no error */ + int finished = 0; /* crc checked */ + + png_debug(1, "in png_handle_iCCP"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + /* Consistent with all the above colorspace handling an obviously *invalid* + * chunk is just ignored, so does not invalidate the color space. An + * alternative is to set the 'invalid' flags at the start of this routine + * and only clear them in they were not set before and all the tests pass. + * The minimum 'deflate' stream is assumed to be just the 2 byte header and 4 + * byte checksum. The keyword must be one character and there is a + * terminator (0) byte and the compression method. + */ + if (length < 9) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too short"); + return; + } + + /* If a colorspace error has already been output skip this chunk */ + if (png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) + { + png_crc_finish(png_ptr, length); + return; + } + + /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect + * this. + */ + if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0) + { + uInt read_length, keyword_length; + char keyword[81]; + + /* Find the keyword; the keyword plus separator and compression method + * bytes can be at most 81 characters long. + */ + read_length = 81; /* maximum */ + if (read_length > length) + read_length = (uInt)length; + + png_crc_read(png_ptr, (png_bytep)keyword, read_length); + length -= read_length; + + keyword_length = 0; + while (keyword_length < 80 && keyword_length < read_length && + keyword[keyword_length] != 0) + ++keyword_length; + + /* TODO: make the keyword checking common */ + if (keyword_length >= 1 && keyword_length <= 79) + { + /* We only understand '0' compression - deflate - so if we get a + * different value we can't safely decode the chunk. + */ + if (keyword_length+1 < read_length && + keyword[keyword_length+1] == PNG_COMPRESSION_TYPE_BASE) + { + read_length -= keyword_length+2; + + if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK) + { + Byte profile_header[132]; + Byte local_buffer[PNG_INFLATE_BUF_SIZE]; + png_alloc_size_t size = (sizeof profile_header); + + png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2); + png_ptr->zstream.avail_in = read_length; + (void)png_inflate_read(png_ptr, local_buffer, + (sizeof local_buffer), &length, profile_header, &size, + 0/*finish: don't, because the output is too small*/); + + if (size == 0) + { + /* We have the ICC profile header; do the basic header checks. + */ + const png_uint_32 profile_length = + png_get_uint_32(profile_header); + + if (png_icc_check_length(png_ptr, &png_ptr->colorspace, + keyword, profile_length)) + { + /* The length is apparently ok, so we can check the 132 + * byte header. + */ + if (png_icc_check_header(png_ptr, &png_ptr->colorspace, + keyword, profile_length, profile_header, + png_ptr->color_type)) + { + /* Now read the tag table; a variable size buffer is + * needed at this point, allocate one for the whole + * profile. The header check has already validated + * that none of these stuff will overflow. + */ + const png_uint_32 tag_count = png_get_uint_32( + profile_header+128); + png_bytep profile = png_read_buffer(png_ptr, + profile_length, 2/*silent*/); + + if (profile != NULL) + { + memcpy(profile, profile_header, + (sizeof profile_header)); + + size = 12 * tag_count; + + (void)png_inflate_read(png_ptr, local_buffer, + (sizeof local_buffer), &length, + profile + (sizeof profile_header), &size, 0); + + /* Still expect a buffer error because we expect + * there to be some tag data! + */ + if (size == 0) + { + if (png_icc_check_tag_table(png_ptr, + &png_ptr->colorspace, keyword, profile_length, + profile)) + { + /* The profile has been validated for basic + * security issues, so read the whole thing in. + */ + size = profile_length - (sizeof profile_header) + - 12 * tag_count; + + (void)png_inflate_read(png_ptr, local_buffer, + (sizeof local_buffer), &length, + profile + (sizeof profile_header) + + 12 * tag_count, &size, 1/*finish*/); + + if (length > 0 && !(png_ptr->flags & + PNG_FLAG_BENIGN_ERRORS_WARN)) + errmsg = "extra compressed data"; + + /* But otherwise allow extra data: */ + else if (size == 0) + { + if (length > 0) + { + /* This can be handled completely, so + * keep going. + */ + png_chunk_warning(png_ptr, + "extra compressed data"); + } + + png_crc_finish(png_ptr, length); + finished = 1; + +# ifdef PNG_sRGB_SUPPORTED + /* Check for a match against sRGB */ + png_icc_set_sRGB(png_ptr, + &png_ptr->colorspace, profile, + png_ptr->zstream.adler); +# endif + + /* Steal the profile for info_ptr. */ + if (info_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, + PNG_FREE_ICCP, 0); + + info_ptr->iccp_name = png_voidcast(char*, + png_malloc_base(png_ptr, + keyword_length+1)); + if (info_ptr->iccp_name != NULL) + { + memcpy(info_ptr->iccp_name, keyword, + keyword_length+1); + info_ptr->iccp_proflen = + profile_length; + info_ptr->iccp_profile = profile; + png_ptr->read_buffer = NULL; /*steal*/ + info_ptr->free_me |= PNG_FREE_ICCP; + info_ptr->valid |= PNG_INFO_iCCP; + } + + else + { + png_ptr->colorspace.flags |= + PNG_COLORSPACE_INVALID; + errmsg = "out of memory"; + } + } + + /* else the profile remains in the read + * buffer which gets reused for subsequent + * chunks. + */ + + if (info_ptr != NULL) + png_colorspace_sync(png_ptr, info_ptr); + + if (errmsg == NULL) + { + png_ptr->zowner = 0; + return; + } + } + + else if (size > 0) + errmsg = "truncated"; + + else + errmsg = png_ptr->zstream.msg; + } + + /* else png_icc_check_tag_table output an error */ + } + + else /* profile truncated */ + errmsg = png_ptr->zstream.msg; + } + + else + errmsg = "out of memory"; + } + + /* else png_icc_check_header output an error */ + } + + /* else png_icc_check_length output an error */ + } + + else /* profile truncated */ + errmsg = png_ptr->zstream.msg; + + /* Release the stream */ + png_ptr->zowner = 0; + } + + else /* png_inflate_claim failed */ + errmsg = png_ptr->zstream.msg; + } + + else + errmsg = "bad compression method"; /* or missing */ + } + + else + errmsg = "bad keyword"; + } + + else + errmsg = "too many profiles"; + + /* Failure: the reason is in 'errmsg' */ + if (finished == 0) + png_crc_finish(png_ptr, length); + + png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; + png_colorspace_sync(png_ptr, info_ptr); + if (errmsg != NULL) /* else already output */ + png_chunk_benign_error(png_ptr, errmsg); +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_sPLT_SUPPORTED +void /* PRIVATE */ +png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep entry_start, buffer; + png_sPLT_t new_palette; + png_sPLT_entryp pp; + png_uint_32 data_length; + int entry_size, i; + png_uint_32 skip = 0; + png_uint_32 dl; + png_size_t max_dl; + + png_debug(1, "in png_handle_sPLT"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + /* Warn the first time */ + png_chunk_benign_error(png_ptr, "chunk cache full"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > 65535U) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too large to fit in memory"); + return; + } +#endif + + buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); + if (buffer == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + + /* WARNING: this may break if size_t is less than 32 bits; it is assumed + * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a + * potential breakage point if the types in pngconf.h aren't exactly right. + */ + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, skip)) + return; + + buffer[length] = 0; + + for (entry_start = buffer; *entry_start; entry_start++) + /* Empty loop to find end of name */ ; + + ++entry_start; + + /* A sample depth should follow the separator, and we should be on it */ + if (entry_start > buffer + length - 2) + { + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + /* This must fit in a png_uint_32 because it is derived from the original + * chunk data length. + */ + data_length = length - (png_uint_32)(entry_start - buffer); + + /* Integrity-check the data length */ + if (data_length % entry_size) + { + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + dl = (png_int_32)(data_length / entry_size); + max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry)); + + if (dl > max_dl) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + + new_palette.nentries = (png_int_32)(data_length / entry_size); + + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( + png_ptr, new_palette.nentries * (sizeof (png_sPLT_entry))); + + if (new_palette.entries == NULL) + { + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; + } + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0; i < new_palette.nentries; i++) + { + pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + + pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* Discard all chunk data except the name and stash that */ + new_palette.name = (png_charp)buffer; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_tRNS_SUPPORTED +void /* PRIVATE */ +png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_tRNS"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[2]; + + if (length != 2) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_color.gray = png_get_uint_16(buf); + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, length); + png_ptr->num_trans = 1; + png_ptr->trans_color.red = png_get_uint_16(buf); + png_ptr->trans_color.green = png_get_uint_16(buf + 2); + png_ptr->trans_color.blue = png_get_uint_16(buf + 4); + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* TODO: is this actually an error in the ISO spec? */ + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + if (length > png_ptr->num_palette || length > PNG_MAX_PALETTE_LENGTH || + length == 0) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, readbuf, length); + png_ptr->num_trans = (png_uint_16)length; + } + + else + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid with alpha channel"); + return; + } + + if (png_crc_finish(png_ptr, 0)) + { + png_ptr->num_trans = 0; + return; + } + + /* TODO: this is a horrible side effect in the palette case because the + * png_struct ends up with a pointer to the tRNS buffer owned by the + * png_info. Fix this. + */ + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_color)); + + png_ptr->trans_alpha = info_ptr->trans_alpha; +} +#endif + +#ifdef PNG_READ_bKGD_SUPPORTED +void /* PRIVATE */ +png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + unsigned int truelen; + png_byte buf[6]; + png_color_16 background; + + png_debug(1, "in png_handle_bKGD"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if ((png_ptr->mode & PNG_HAVE_IDAT) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE))) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + + else + truelen = 2; + + if (length != truelen) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, truelen); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + background.index = buf[0]; + + if (info_ptr && info_ptr->num_palette) + { + if (buf[0] >= info_ptr->num_palette) + { + png_chunk_benign_error(png_ptr, "invalid index"); + return; + } + + background.red = (png_uint_16)png_ptr->palette[buf[0]].red; + background.green = (png_uint_16)png_ptr->palette[buf[0]].green; + background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue; + } + + else + background.red = background.green = background.blue = 0; + + background.gray = 0; + } + + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + background.index = 0; + background.red = + background.green = + background.blue = + background.gray = png_get_uint_16(buf); + } + + else + { + background.index = 0; + background.red = png_get_uint_16(buf); + background.green = png_get_uint_16(buf + 2); + background.blue = png_get_uint_16(buf + 4); + background.gray = 0; + } + + png_set_bKGD(png_ptr, info_ptr, &background); +} +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +void /* PRIVATE */ +png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if ((png_ptr->mode & PNG_HAVE_IDAT) || !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + num = length / 2 ; + + if (num != png_ptr->num_palette || num > PNG_MAX_PALETTE_LENGTH) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +void /* PRIVATE */ +png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (length != 9) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 9); + + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +void /* PRIVATE */ +png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (length != 9) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 9); + + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +/* Read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_int_32 X0, X1; + png_byte type, nparams; + png_bytep buffer, buf, units, endptr; + png_charpp params; + int i; + + png_debug(1, "in png_handle_pCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)", + length + 1); + + buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); + + if (buffer == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, 0)) + return; + + buffer[length] = 0; /* Null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string"); + for (buf = buffer; *buf; buf++) + /* Empty loop */ ; + + endptr = buffer + length; + + /* We need to have at least 12 bytes after the purpose string + * in order to get the parameter information. + */ + if (endptr <= buf + 12) + { + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters"); + /* Check that we have the right number of parameters for known + * equation types. + */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_chunk_benign_error(png_ptr, "invalid parameter count"); + return; + } + + else if (type >= PNG_EQUATION_LAST) + { + png_chunk_benign_error(png_ptr, "unrecognized equation type"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array"); + + params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, + nparams * (sizeof (png_charp)))); + + if (params == NULL) + { + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d", i); + + for (params[i] = (png_charp)buf; buf <= endptr && *buf != 0; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_free(png_ptr, params); + png_chunk_benign_error(png_ptr, "invalid data"); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams, + (png_charp)units, params); + + png_free(png_ptr, params); +} +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +/* Read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_bytep buffer; + png_size_t i; + int state; + + png_debug(1, "in png_handle_sCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + /* Need unit type, width, \0, height: minimum 4 bytes */ + else if (length < 4) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", + length + 1); + + buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); + + if (buffer == NULL) + { + png_chunk_benign_error(png_ptr, "out of memory"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buffer, length); + buffer[length] = 0; /* Null terminate the last string */ + + if (png_crc_finish(png_ptr, 0)) + return; + + /* Validate the unit. */ + if (buffer[0] != 1 && buffer[0] != 2) + { + png_chunk_benign_error(png_ptr, "invalid unit"); + return; + } + + /* Validate the ASCII numbers, need two ASCII numbers separated by + * a '\0' and they need to fit exactly in the chunk data. + */ + i = 1; + state = 0; + + if (!png_check_fp_number((png_const_charp)buffer, length, &state, &i) || + i >= length || buffer[i++] != 0) + png_chunk_benign_error(png_ptr, "bad width format"); + + else if (!PNG_FP_IS_POSITIVE(state)) + png_chunk_benign_error(png_ptr, "non-positive width"); + + else + { + png_size_t heighti = i; + + state = 0; + if (!png_check_fp_number((png_const_charp)buffer, length, &state, &i) || + i != length) + png_chunk_benign_error(png_ptr, "bad height format"); + + else if (!PNG_FP_IS_POSITIVE(state)) + png_chunk_benign_error(png_ptr, "non-positive height"); + + else + /* This is the (only) success case. */ + png_set_sCAL_s(png_ptr, info_ptr, buffer[0], + (png_charp)buffer+1, (png_charp)buffer+heighti); + } +} +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +void /* PRIVATE */ +png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "invalid"); + return; + } + + png_crc_read(png_ptr, buf, 7); + + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_text text_info; + png_bytep buffer; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_tEXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "chunk cache full"); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > 65535U) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too large to fit in memory"); + return; + } +#endif + + buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/); + + if (buffer == NULL) + { + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, skip)) + return; + + key = (png_charp)buffer; + key[length] = 0; + + for (text = key; *text; text++) + /* Empty loop to find end of key */ ; + + if (text != key + length) + text++; + + text_info.compression = PNG_TEXT_COMPRESSION_NONE; + text_info.key = key; + text_info.lang = NULL; + text_info.lang_key = NULL; + text_info.itxt_length = 0; + text_info.text = text; + text_info.text_length = strlen(text); + + if (png_set_text_2(png_ptr, info_ptr, &text_info, 1)) + png_warning(png_ptr, "Insufficient memory to process text chunk"); +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_const_charp errmsg = NULL; + png_bytep buffer; + png_uint_32 keyword_length; + + png_debug(1, "in png_handle_zTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "chunk cache full"); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + buffer = png_read_buffer(png_ptr, length, 2/*silent*/); + + if (buffer == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* TODO: also check that the keyword contents match the spec! */ + for (keyword_length = 0; + keyword_length < length && buffer[keyword_length] != 0; + ++keyword_length) + /* Empty loop to find end of name */ ; + + if (keyword_length > 79 || keyword_length < 1) + errmsg = "bad keyword"; + + /* zTXt must have some LZ data after the keyword, although it may expand to + * zero bytes; we need a '\0' at the end of the keyword, the compression type + * then the LZ data: + */ + else if (keyword_length + 3 > length) + errmsg = "truncated"; + + else if (buffer[keyword_length+1] != PNG_COMPRESSION_TYPE_BASE) + errmsg = "unknown compression type"; + + else + { + png_alloc_size_t uncompressed_length = PNG_SIZE_MAX; + + /* TODO: at present png_decompress_chunk imposes a single application + * level memory limit, this should be split to different values for iCCP + * and text chunks. + */ + if (png_decompress_chunk(png_ptr, length, keyword_length+2, + &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) + { + png_text text; + + /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except + * for the extra compression type byte and the fact that it isn't + * necessarily '\0' terminated. + */ + buffer = png_ptr->read_buffer; + buffer[uncompressed_length+(keyword_length+2)] = 0; + + text.compression = PNG_TEXT_COMPRESSION_zTXt; + text.key = (png_charp)buffer; + text.text = (png_charp)(buffer + keyword_length+2); + text.text_length = uncompressed_length; + text.itxt_length = 0; + text.lang = NULL; + text.lang_key = NULL; + + if (png_set_text_2(png_ptr, info_ptr, &text, 1)) + errmsg = "insufficient memory"; + } + + else + errmsg = png_ptr->zstream.msg; + } + + if (errmsg != NULL) + png_chunk_benign_error(png_ptr, errmsg); +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + png_const_charp errmsg = NULL; + png_bytep buffer; + png_uint_32 prefix_length; + + png_debug(1, "in png_handle_iTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "chunk cache full"); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_chunk_error(png_ptr, "missing IHDR"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/); + + if (buffer == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* First the keyword. */ + for (prefix_length=0; + prefix_length < length && buffer[prefix_length] != 0; + ++prefix_length) + /* Empty loop */ ; + + /* Perform a basic check on the keyword length here. */ + if (prefix_length > 79 || prefix_length < 1) + errmsg = "bad keyword"; + + /* Expect keyword, compression flag, compression type, language, translated + * keyword (both may be empty but are 0 terminated) then the text, which may + * be empty. + */ + else if (prefix_length + 5 > length) + errmsg = "truncated"; + + else if (buffer[prefix_length+1] == 0 || + (buffer[prefix_length+1] == 1 && + buffer[prefix_length+2] == PNG_COMPRESSION_TYPE_BASE)) + { + int compressed = buffer[prefix_length+1] != 0; + png_uint_32 language_offset, translated_keyword_offset; + png_alloc_size_t uncompressed_length = 0; + + /* Now the language tag */ + prefix_length += 3; + language_offset = prefix_length; + + for (; prefix_length < length && buffer[prefix_length] != 0; + ++prefix_length) + /* Empty loop */ ; + + /* WARNING: the length may be invalid here, this is checked below. */ + translated_keyword_offset = ++prefix_length; + + for (; prefix_length < length && buffer[prefix_length] != 0; + ++prefix_length) + /* Empty loop */ ; + + /* prefix_length should now be at the trailing '\0' of the translated + * keyword, but it may already be over the end. None of this arithmetic + * can overflow because chunks are at most 2^31 bytes long, but on 16-bit + * systems the available allocaton may overflow. + */ + ++prefix_length; + + if (!compressed && prefix_length <= length) + uncompressed_length = length - prefix_length; + + else if (compressed && prefix_length < length) + { + uncompressed_length = PNG_SIZE_MAX; + + /* TODO: at present png_decompress_chunk imposes a single application + * level memory limit, this should be split to different values for + * iCCP and text chunks. + */ + if (png_decompress_chunk(png_ptr, length, prefix_length, + &uncompressed_length, 1/*terminate*/) == Z_STREAM_END) + buffer = png_ptr->read_buffer; + + else + errmsg = png_ptr->zstream.msg; + } + + else + errmsg = "truncated"; + + if (errmsg == NULL) + { + png_text text; + + buffer[uncompressed_length+prefix_length] = 0; + + if (compressed != 0) + text.compression = PNG_ITXT_COMPRESSION_NONE; + + else + text.compression = PNG_ITXT_COMPRESSION_zTXt; + + text.key = (png_charp)buffer; + text.lang = (png_charp)buffer + language_offset; + text.lang_key = (png_charp)buffer + translated_keyword_offset; + text.text = (png_charp)buffer + prefix_length; + text.text_length = 0; + text.itxt_length = uncompressed_length; + + if (png_set_text_2(png_ptr, info_ptr, &text, 1)) + errmsg = "insufficient memory"; + } + } + + else + errmsg = "bad compression info"; + + if (errmsg != NULL) + png_chunk_benign_error(png_ptr, errmsg); +} +#endif + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */ +static int +png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) +{ + png_alloc_size_t limit = PNG_SIZE_MAX; + + if (png_ptr->unknown_chunk.data != NULL) + { + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < limit) + limit = png_ptr->user_chunk_malloc_max; + +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + if (PNG_USER_CHUNK_MALLOC_MAX < limit) + limit = PNG_USER_CHUNK_MALLOC_MAX; +# endif + + if (length <= limit) + { + PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); + /* The following is safe because of the PNG_SIZE_MAX init above */ + png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/; + /* 'mode' is a flag array, only the bottom four bits matter here */ + png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + /* Do a 'warn' here - it is handled below. */ + png_ptr->unknown_chunk.data = png_voidcast(png_bytep, + png_malloc_warn(png_ptr, length)); + } + } + + if (png_ptr->unknown_chunk.data == NULL && length > 0) + { + /* This is benign because we clean up correctly */ + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "unknown chunk exceeds memory limits"); + return 0; + } + + else + { + if (length > 0) + png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length); + png_crc_finish(png_ptr, 0); + return 1; + } +} +#endif /* PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */ + +/* Handle an unknown, or known but disabled, chunk */ +void /* PRIVATE */ +png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, + png_uint_32 length, int keep) +{ + int handled = 0; /* the chunk was handled */ + + png_debug(1, "in png_handle_unknown"); + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + /* NOTE: this code is based on the code in libpng-1.4.12 except for fixing + * the bug which meant that setting a non-default behavior for a specific + * chunk would be ignored (the default was always used unless a user + * callback was installed). + * + * 'keep' is the value from the png_chunk_unknown_handling, the setting for + * this specific chunk_name, if PNG_HANDLE_AS_UNKNOWN_SUPPORTED, if not it + * will always be PNG_HANDLE_CHUNK_AS_DEFAULT and it needs to be set here. + * This is just an optimization to avoid multiple calls to the lookup + * function. + */ +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name); +# endif +# endif + + /* One of the following methods will read the chunk or skip it (at least one + * of these is always defined because this is the only way to switch on + * PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + */ +# ifdef PNG_READ_USER_CHUNKS_SUPPORTED + /* The user callback takes precedence over the chunk keep value, but the + * keep value is still required to validate a save of a critical chunk. + */ + if (png_ptr->read_user_chunk_fn != NULL) + { + if (png_cache_unknown_chunk(png_ptr, length)) + { + /* Callback to user unknown chunk handler */ + int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr, + &png_ptr->unknown_chunk); + + /* ret is: + * negative: An error occured, png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be discarded + * unless png_set_keep_unknown_chunks has been used to set + * a 'keep' behavior for this particular chunk, in which + * case that will be used. A critical chunk will cause an + * error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + */ + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + else if (ret == 0) + { + /* Use the default handling, note that if there is per-chunk + * handling specified it has already been set into 'keep'. + * + * NOTE: this is an API change in 1.7.0. Prior to 1.7.0 libpng + * would force keep to PNG_HANDLE_CHUNK_IF_SAFE at this point, + * and 1.6.0 would issue a warning if this caused a default of + * discarding the chunk to be changed. + */ + if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT) + keep = png_ptr->unknown_default; + } + + else /* chunk was handled */ + { + handled = 1; + /* Critical chunks can be safely discarded at this point. */ + keep = PNG_HANDLE_CHUNK_NEVER; + } + } + + else + keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */ + } + + else + /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */ +# endif /* PNG_READ_USER_CHUNKS_SUPPORTED */ + +# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED + { + /* keep is currently just the per-chunk setting, if there was no + * setting change it to the global default now (not that this may + * still be AS_DEFAULT) then obtain the cache of the chunk if required, + * if not simply skip the chunk. + */ + if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT) + keep = png_ptr->unknown_default; + + if (keep == PNG_HANDLE_CHUNK_ALWAYS || + (keep == PNG_HANDLE_CHUNK_IF_SAFE && + PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))) + { + if (!png_cache_unknown_chunk(png_ptr, length)) + keep = PNG_HANDLE_CHUNK_NEVER; + } + + else + png_crc_finish(png_ptr, length); + } +# else +# ifndef PNG_READ_USER_CHUNKS_SUPPORTED +# error no method to support READ_UNKNOWN_CHUNKS +# endif + + { + /* If here there is no read callback pointer set and no support is + * compiled in to just save the unknown chunks, so simply skip this + * chunk. If 'keep' is something other than AS_DEFAULT or NEVER then + * the app has erroneously asked for unknown chunk saving when there + * is no support. + */ + if (keep > PNG_HANDLE_CHUNK_NEVER) + png_app_error(png_ptr, "no unknown chunk support available"); + + png_crc_finish(png_ptr, length); + } +# endif + +# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED + /* Now store the chunk in the chunk list if appropriate, and if the limits + * permit it. + */ + if (keep == PNG_HANDLE_CHUNK_ALWAYS || + (keep == PNG_HANDLE_CHUNK_IF_SAFE && + PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))) + { +# ifdef PNG_USER_LIMITS_SUPPORTED + switch (png_ptr->user_chunk_cache_max) + { + case 2: + png_ptr->user_chunk_cache_max = 1; + png_chunk_benign_error(png_ptr, "chunk cache full"); + /* FALL THROUGH */ + case 1: + /* NOTE: prior to 1.6.0 this case resulted in an unknown critical + * chunk being skipped, now there will be a hard error below. + */ + break; + + default: /* not at limit */ + --(png_ptr->user_chunk_cache_max); + /* FALL THROUGH */ + case 0: /* no limit */ +# endif /* PNG_USER_LIMITS_SUPPORTED */ + /* Here when the limit isn't reached or when limits are compiled + * out; store the chunk. + */ + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + handled = 1; +# ifdef PNG_USER_LIMITS_SUPPORTED + break; + } +# endif + } +# else /* no store support: the chunk must be handled by the user callback */ + PNG_UNUSED(info_ptr) +# endif + + /* Regardless of the error handling below the cached data (if any) can be + * freed now. Notice that the data is not freed if there is a png_error, but + * it will be freed by destroy_read_struct. + */ + if (png_ptr->unknown_chunk.data != NULL) + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + +#else /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */ + /* There is no support to read an unknown chunk, so just skip it. */ + png_crc_finish(png_ptr, length); + PNG_UNUSED(info_ptr) + PNG_UNUSED(keep) +#endif /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */ + + /* Check for unhandled critical chunks */ + if (!handled && PNG_CHUNK_CRITICAL(png_ptr->chunk_name)) + png_chunk_error(png_ptr, "unhandled critical chunk"); +} + +/* This function is called to verify that a chunk name is valid. + * This function can't have the "critical chunk check" incorporated + * into it, since in the future we will need to be able to call user + * functions to handle unknown critical chunks after we check that + * the chunk name itself is valid. + */ + +/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is: + * + * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + */ + +void /* PRIVATE */ +png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name) +{ + int i; + + png_debug(1, "in png_check_chunk_name"); + + for (i=1; i<=4; ++i) + { + int c = chunk_name & 0xff; + + if (c < 65 || c > 122 || (c > 90 && c < 97)) + png_chunk_error(png_ptr, "invalid chunk type"); + + chunk_name >>= 8; + } +} + +/* Combines the row recently read in with the existing pixels in the row. This + * routine takes care of alpha and transparency if requested. This routine also + * handles the two methods of progressive display of interlaced images, + * depending on the 'display' value; if 'display' is true then the whole row + * (dp) is filled from the start by replicating the available pixels. If + * 'display' is false only those pixels present in the pass are filled in. + */ +void /* PRIVATE */ +png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) +{ + unsigned int pixel_depth = png_ptr->transformed_pixel_depth; + png_const_bytep sp = png_ptr->row_buf + 1; + png_uint_32 row_width = png_ptr->width; + unsigned int pass = png_ptr->pass; + png_bytep end_ptr = 0; + png_byte end_byte = 0; + unsigned int end_mask; + + png_debug(1, "in png_combine_row"); + + /* Added in 1.5.6: it should not be possible to enter this routine until at + * least one row has been read from the PNG data and transformed. + */ + if (pixel_depth == 0) + png_error(png_ptr, "internal row logic error"); + + /* Added in 1.5.4: the pixel depth should match the information returned by + * any call to png_read_update_info at this point. Do not continue if we got + * this wrong. + */ + if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes != + PNG_ROWBYTES(pixel_depth, row_width)) + png_error(png_ptr, "internal row size calculation error"); + + /* Don't expect this to ever happen: */ + if (row_width == 0) + png_error(png_ptr, "internal row width error"); + + /* Preserve the last byte in cases where only part of it will be overwritten, + * the multiply below may overflow, we don't care because ANSI-C guarantees + * we get the low bits. + */ + end_mask = (pixel_depth * row_width) & 7; + if (end_mask != 0) + { + /* end_ptr == NULL is a flag to say do nothing */ + end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1; + end_byte = *end_ptr; +# ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) /* little-endian byte */ + end_mask = 0xff << end_mask; + + else /* big-endian byte */ +# endif + end_mask = 0xff >> end_mask; + /* end_mask is now the bits to *keep* from the destination row */ + } + + /* For non-interlaced images this reduces to a memcpy(). A memcpy() + * will also happen if interlacing isn't supported or if the application + * does not call png_set_interlace_handling(). In the latter cases the + * caller just gets a sequence of the unexpanded rows from each interlace + * pass. + */ +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) && + pass < 6 && (display == 0 || + /* The following copies everything for 'display' on passes 0, 2 and 4. */ + (display == 1 && (pass & 1) != 0))) + { + /* Narrow images may have no bits in a pass; the caller should handle + * this, but this test is cheap: + */ + if (row_width <= PNG_PASS_START_COL(pass)) + return; + + if (pixel_depth < 8) + { + /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit + * into 32 bits, then a single loop over the bytes using the four byte + * values in the 32-bit mask can be used. For the 'display' option the + * expanded mask may also not require any masking within a byte. To + * make this work the PACKSWAP option must be taken into account - it + * simply requires the pixels to be reversed in each byte. + * + * The 'regular' case requires a mask for each of the first 6 passes, + * the 'display' case does a copy for the even passes in the range + * 0..6. This has already been handled in the test above. + * + * The masks are arranged as four bytes with the first byte to use in + * the lowest bits (little-endian) regardless of the order (PACKSWAP or + * not) of the pixels in each byte. + * + * NOTE: the whole of this logic depends on the caller of this function + * only calling it on rows appropriate to the pass. This function only + * understands the 'x' logic; the 'y' logic is handled by the caller. + * + * The following defines allow generation of compile time constant bit + * masks for each pixel depth and each possibility of swapped or not + * swapped bytes. Pass 'p' is in the range 0..6; 'x', a pixel index, + * is in the range 0..7; and the result is 1 if the pixel is to be + * copied in the pass, 0 if not. 'S' is for the sparkle method, 'B' + * for the block method. + * + * With some compilers a compile time expression of the general form: + * + * (shift >= 32) ? (a >> (shift-32)) : (b >> shift) + * + * Produces warnings with values of 'shift' in the range 33 to 63 + * because the right hand side of the ?: expression is evaluated by + * the compiler even though it isn't used. Microsoft Visual C (various + * versions) and the Intel C compiler are known to do this. To avoid + * this the following macros are used in 1.5.6. This is a temporary + * solution to avoid destabilizing the code during the release process. + */ +# if PNG_USE_COMPILE_TIME_MASKS +# define PNG_LSR(x,s) ((x)>>((s) & 0x1f)) +# define PNG_LSL(x,s) ((x)<<((s) & 0x1f)) +# else +# define PNG_LSR(x,s) ((x)>>(s)) +# define PNG_LSL(x,s) ((x)<<(s)) +# endif +# define S_COPY(p,x) (((p)<4 ? PNG_LSR(0x80088822,(3-(p))*8+(7-(x))) :\ + PNG_LSR(0xaa55ff00,(7-(p))*8+(7-(x)))) & 1) +# define B_COPY(p,x) (((p)<4 ? PNG_LSR(0xff0fff33,(3-(p))*8+(7-(x))) :\ + PNG_LSR(0xff55ff00,(7-(p))*8+(7-(x)))) & 1) + + /* Return a mask for pass 'p' pixel 'x' at depth 'd'. The mask is + * little endian - the first pixel is at bit 0 - however the extra + * parameter 's' can be set to cause the mask position to be swapped + * within each byte, to match the PNG format. This is done by XOR of + * the shift with 7, 6 or 4 for bit depths 1, 2 and 4. + */ +# define PIXEL_MASK(p,x,d,s) \ + (PNG_LSL(((PNG_LSL(1U,(d)))-1),(((x)*(d))^((s)?8-(d):0)))) + + /* Hence generate the appropriate 'block' or 'sparkle' pixel copy mask. + */ +# define S_MASKx(p,x,d,s) (S_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) +# define B_MASKx(p,x,d,s) (B_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) + + /* Combine 8 of these to get the full mask. For the 1-bpp and 2-bpp + * cases the result needs replicating, for the 4-bpp case the above + * generates a full 32 bits. + */ +# define MASK_EXPAND(m,d) ((m)*((d)==1?0x01010101:((d)==2?0x00010001:1))) + +# define S_MASK(p,d,s) MASK_EXPAND(S_MASKx(p,0,d,s) + S_MASKx(p,1,d,s) +\ + S_MASKx(p,2,d,s) + S_MASKx(p,3,d,s) + S_MASKx(p,4,d,s) +\ + S_MASKx(p,5,d,s) + S_MASKx(p,6,d,s) + S_MASKx(p,7,d,s), d) + +# define B_MASK(p,d,s) MASK_EXPAND(B_MASKx(p,0,d,s) + B_MASKx(p,1,d,s) +\ + B_MASKx(p,2,d,s) + B_MASKx(p,3,d,s) + B_MASKx(p,4,d,s) +\ + B_MASKx(p,5,d,s) + B_MASKx(p,6,d,s) + B_MASKx(p,7,d,s), d) + +#if PNG_USE_COMPILE_TIME_MASKS + /* Utility macros to construct all the masks for a depth/swap + * combination. The 's' parameter says whether the format is PNG + * (big endian bytes) or not. Only the three odd-numbered passes are + * required for the display/block algorithm. + */ +# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\ + S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) } + +# define B_MASKS(d,s) { B_MASK(1,d,s), B_MASK(3,d,s), B_MASK(5,d,s) } + +# define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2)) + + /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and + * then pass: + */ + static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = + { + /* Little-endian byte masks for PACKSWAP */ + { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) }, + /* Normal (big-endian byte) masks - PNG format */ + { S_MASKS(1,1), S_MASKS(2,1), S_MASKS(4,1) } + }; + + /* display_mask has only three entries for the odd passes, so index by + * pass>>1. + */ + static PNG_CONST png_uint_32 display_mask[2][3][3] = + { + /* Little-endian byte masks for PACKSWAP */ + { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) }, + /* Normal (big-endian byte) masks - PNG format */ + { B_MASKS(1,1), B_MASKS(2,1), B_MASKS(4,1) } + }; + +# define MASK(pass,depth,display,png)\ + ((display)?display_mask[png][DEPTH_INDEX(depth)][pass>>1]:\ + row_mask[png][DEPTH_INDEX(depth)][pass]) + +#else /* !PNG_USE_COMPILE_TIME_MASKS */ + /* This is the runtime alternative: it seems unlikely that this will + * ever be either smaller or faster than the compile time approach. + */ +# define MASK(pass,depth,display,png)\ + ((display)?B_MASK(pass,depth,png):S_MASK(pass,depth,png)) +#endif /* !PNG_USE_COMPILE_TIME_MASKS */ + + /* Use the appropriate mask to copy the required bits. In some cases + * the byte mask will be 0 or 0xff, optimize these cases. row_width is + * the number of pixels, but the code copies bytes, so it is necessary + * to special case the end. + */ + png_uint_32 pixels_per_byte = 8 / pixel_depth; + png_uint_32 mask; + +# ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + mask = MASK(pass, pixel_depth, display, 0); + + else +# endif + mask = MASK(pass, pixel_depth, display, 1); + + for (;;) + { + png_uint_32 m; + + /* It doesn't matter in the following if png_uint_32 has more than + * 32 bits because the high bits always match those in m<<24; it is, + * however, essential to use OR here, not +, because of this. + */ + m = mask; + mask = (m >> 8) | (m << 24); /* rotate right to good compilers */ + m &= 0xff; + + if (m != 0) /* something to copy */ + { + if (m != 0xff) + *dp = (png_byte)((*dp & ~m) | (*sp & m)); + else + *dp = *sp; + } + + /* NOTE: this may overwrite the last byte with garbage if the image + * is not an exact number of bytes wide; libpng has always done + * this. + */ + if (row_width <= pixels_per_byte) + break; /* May need to restore part of the last byte */ + + row_width -= pixels_per_byte; + ++dp; + ++sp; + } + } + + else /* pixel_depth >= 8 */ + { + unsigned int bytes_to_copy, bytes_to_jump; + + /* Validate the depth - it must be a multiple of 8 */ + if (pixel_depth & 7) + png_error(png_ptr, "invalid user transform pixel depth"); + + pixel_depth >>= 3; /* now in bytes */ + row_width *= pixel_depth; + + /* Regardless of pass number the Adam 7 interlace always results in a + * fixed number of pixels to copy then to skip. There may be a + * different number of pixels to skip at the start though. + */ + { + unsigned int offset = PNG_PASS_START_COL(pass) * pixel_depth; + + row_width -= offset; + dp += offset; + sp += offset; + } + + /* Work out the bytes to copy. */ + if (display != 0) + { + /* When doing the 'block' algorithm the pixel in the pass gets + * replicated to adjacent pixels. This is why the even (0,2,4,6) + * passes are skipped above - the entire expanded row is copied. + */ + bytes_to_copy = (1<<((6-pass)>>1)) * pixel_depth; + + /* But don't allow this number to exceed the actual row width. */ + if (bytes_to_copy > row_width) + bytes_to_copy = row_width; + } + + else /* normal row; Adam7 only ever gives us one pixel to copy. */ + bytes_to_copy = pixel_depth; + + /* In Adam7 there is a constant offset between where the pixels go. */ + bytes_to_jump = PNG_PASS_COL_OFFSET(pass) * pixel_depth; + + /* And simply copy these bytes. Some optimization is possible here, + * depending on the value of 'bytes_to_copy'. Special case the low + * byte counts, which we know to be frequent. + * + * Notice that these cases all 'return' rather than 'break' - this + * avoids an unnecessary test on whether to restore the last byte + * below. + */ + switch (bytes_to_copy) + { + case 1: + for (;;) + { + *dp = *sp; + + if (row_width <= bytes_to_jump) + return; + + dp += bytes_to_jump; + sp += bytes_to_jump; + row_width -= bytes_to_jump; + } + + case 2: + /* There is a possibility of a partial copy at the end here; this + * slows the code down somewhat. + */ + do + { + dp[0] = sp[0], dp[1] = sp[1]; + + if (row_width <= bytes_to_jump) + return; + + sp += bytes_to_jump; + dp += bytes_to_jump; + row_width -= bytes_to_jump; + } + while (row_width > 1); + + /* And there can only be one byte left at this point: */ + *dp = *sp; + return; + + case 3: + /* This can only be the RGB case, so each copy is exactly one + * pixel and it is not necessary to check for a partial copy. + */ + for(;;) + { + dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2]; + + if (row_width <= bytes_to_jump) + return; + + sp += bytes_to_jump; + dp += bytes_to_jump; + row_width -= bytes_to_jump; + } + + default: +#if PNG_ALIGN_TYPE != PNG_ALIGN_NONE + /* Check for double byte alignment and, if possible, use a + * 16-bit copy. Don't attempt this for narrow images - ones that + * are less than an interlace panel wide. Don't attempt it for + * wide bytes_to_copy either - use the memcpy there. + */ + if (bytes_to_copy < 16 /*else use memcpy*/ && + png_isaligned(dp, png_uint_16) && + png_isaligned(sp, png_uint_16) && + bytes_to_copy % (sizeof (png_uint_16)) == 0 && + bytes_to_jump % (sizeof (png_uint_16)) == 0) + { + /* Everything is aligned for png_uint_16 copies, but try for + * png_uint_32 first. + */ + if (png_isaligned(dp, png_uint_32) && + png_isaligned(sp, png_uint_32) && + bytes_to_copy % (sizeof (png_uint_32)) == 0 && + bytes_to_jump % (sizeof (png_uint_32)) == 0) + { + png_uint_32p dp32 = png_aligncast(png_uint_32p,dp); + png_const_uint_32p sp32 = png_aligncastconst( + png_const_uint_32p, sp); + size_t skip = (bytes_to_jump-bytes_to_copy) / + (sizeof (png_uint_32)); + + do + { + size_t c = bytes_to_copy; + do + { + *dp32++ = *sp32++; + c -= (sizeof (png_uint_32)); + } + while (c > 0); + + if (row_width <= bytes_to_jump) + return; + + dp32 += skip; + sp32 += skip; + row_width -= bytes_to_jump; + } + while (bytes_to_copy <= row_width); + + /* Get to here when the row_width truncates the final copy. + * There will be 1-3 bytes left to copy, so don't try the + * 16-bit loop below. + */ + dp = (png_bytep)dp32; + sp = (png_const_bytep)sp32; + do + *dp++ = *sp++; + while (--row_width > 0); + return; + } + + /* Else do it in 16-bit quantities, but only if the size is + * not too large. + */ + else + { + png_uint_16p dp16 = png_aligncast(png_uint_16p, dp); + png_const_uint_16p sp16 = png_aligncastconst( + png_const_uint_16p, sp); + size_t skip = (bytes_to_jump-bytes_to_copy) / + (sizeof (png_uint_16)); + + do + { + size_t c = bytes_to_copy; + do + { + *dp16++ = *sp16++; + c -= (sizeof (png_uint_16)); + } + while (c > 0); + + if (row_width <= bytes_to_jump) + return; + + dp16 += skip; + sp16 += skip; + row_width -= bytes_to_jump; + } + while (bytes_to_copy <= row_width); + + /* End of row - 1 byte left, bytes_to_copy > row_width: */ + dp = (png_bytep)dp16; + sp = (png_const_bytep)sp16; + do + *dp++ = *sp++; + while (--row_width > 0); + return; + } + } +#endif /* PNG_ALIGN_ code */ + + /* The true default - use a memcpy: */ + for (;;) + { + memcpy(dp, sp, bytes_to_copy); + + if (row_width <= bytes_to_jump) + return; + + sp += bytes_to_jump; + dp += bytes_to_jump; + row_width -= bytes_to_jump; + if (bytes_to_copy > row_width) + bytes_to_copy = row_width; + } + } + + /* NOT REACHED*/ + } /* pixel_depth >= 8 */ + + /* Here if pixel_depth < 8 to check 'end_ptr' below. */ + } + else +#endif + + /* If here then the switch above wasn't used so just memcpy the whole row + * from the temporary row buffer (notice that this overwrites the end of the + * destination row if it is a partial byte.) + */ + memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width)); + + /* Restore the overwritten bits from the last byte if necessary. */ + if (end_ptr != NULL) + *end_ptr = (png_byte)((end_byte & end_mask) | (*end_ptr & ~end_mask)); +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +void /* PRIVATE */ +png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, + png_uint_32 transformations /* Because these may affect the byte layout */) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* Offset to next interlace block */ + static PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_read_interlace"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + unsigned int tmp = *dp & (0x7f7f >> (7 - dshift)); + tmp |= v << dshift; + *dp = (png_byte)(tmp & 0xff); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + unsigned int tmp = *dp & (0x3f3f >> (6 - dshift)); + tmp |= v << dshift; + *dp = (png_byte)(tmp & 0xff); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0x0f); + int j; + + for (j = 0; j < jstop; j++) + { + unsigned int tmp = *dp & (0xf0f >> (4 - dshift)); + tmp |= v << dshift; + *dp = (png_byte)(tmp & 0xff); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + + png_bytep sp = row + (png_size_t)(row_info->width - 1) + * pixel_bytes; + + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; /* SAFE; pixel_depth does not exceed 64 */ + int j; + + memcpy(v, sp, pixel_bytes); + + for (j = 0; j < jstop; j++) + { + memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + + sp -= pixel_bytes; + } + break; + } + } + + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); + } +#ifndef PNG_READ_PACKSWAP_SUPPORTED + PNG_UNUSED(transformations) /* Silence compiler warning */ +#endif +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +static void +png_read_filter_row_sub(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_size_t istop = row_info->rowbytes; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + + PNG_UNUSED(prev_row) + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); + rp++; + } +} + +static void +png_read_filter_row_up(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_size_t istop = row_info->rowbytes; + png_bytep rp = row; + png_const_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } +} + +static void +png_read_filter_row_avg(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_bytep rp = row; + png_const_bytep pp = prev_row; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_size_t istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); + + rp++; + } +} + +static void +png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp_end = row + row_info->rowbytes; + int a, c; + + /* First pixel/byte */ + c = *prev_row++; + a = *row + c; + *row++ = (png_byte)a; + + /* Remainder */ + while (row < rp_end) + { + int b, pa, pb, pc, p; + + a &= 0xff; /* From previous iteration or start */ + b = *prev_row++; + + p = b - c; + pc = a - c; + +# ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +# else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +# endif + + /* Find the best predictor, the least of pa, pb, pc favoring the earlier + * ones in the case of a tie. + */ + if (pb < pa) pa = pb, a = b; + if (pc < pa) a = c; + + /* Calculate the current pixel in a, and move the previous row pixel to c + * for the next time round the loop + */ + c = b; + a += *row; + *row++ = (png_byte)a; + } +} + +static void +png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp_end = row + bpp; + + /* Process the first pixel in the row completely (this is the same as 'up' + * because there is only one candidate predictor for the first row). + */ + while (row < rp_end) + { + int a = *row + *prev_row++; + *row++ = (png_byte)a; + } + + /* Remainder */ + rp_end += row_info->rowbytes - bpp; + + while (row < rp_end) + { + int a, b, c, pa, pb, pc, p; + + c = *(prev_row - bpp); + a = *(row - bpp); + b = *prev_row++; + + p = b - c; + pc = a - c; + +# ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +# else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +# endif + + if (pb < pa) pa = pb, a = b; + if (pc < pa) a = c; + + a += *row; + *row++ = (png_byte)a; + } +} + +static void +png_init_filter_functions(png_structrp pp) + /* This function is called once for every PNG image (except for PNG images + * that only use PNG_FILTER_VALUE_NONE for all rows) to set the + * implementations required to reverse the filtering of PNG rows. Reversing + * the filter is the first transformation performed on the row data. It is + * performed in place, therefore an implementation can be selected based on + * the image pixel format. If the implementation depends on image width then + * take care to ensure that it works correctly if the image is interlaced - + * interlacing causes the actual row width to vary. + */ +{ + unsigned int bpp = (pp->pixel_depth + 7) >> 3; + + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub; + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg; + if (bpp == 1) + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth_1byte_pixel; + else + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth_multibyte_pixel; + +#ifdef PNG_FILTER_OPTIMIZATIONS + /* To use this define PNG_FILTER_OPTIMIZATIONS as the name of a function to + * call to install hardware optimizations for the above functions; simply + * replace whatever elements of the pp->read_filter[] array with a hardware + * specific (or, for that matter, generic) optimization. + * + * To see an example of this examine what configure.ac does when + * --enable-arm-neon is specified on the command line. + */ + PNG_FILTER_OPTIMIZATIONS(pp, bpp); +#endif +} + +void /* PRIVATE */ +png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row, + png_const_bytep prev_row, int filter) +{ + /* OPTIMIZATION: DO NOT MODIFY THIS FUNCTION, instead #define + * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic + * implementations. See png_init_filter_functions above. + */ + if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST) + { + if (pp->read_filter[0] == NULL) + png_init_filter_functions(pp); + + pp->read_filter[filter-1](row_info, row, prev_row); + } +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void /* PRIVATE */ +png_read_IDAT_data(png_structrp png_ptr, png_bytep output, + png_alloc_size_t avail_out) +{ + /* Loop reading IDATs and decompressing the result into output[avail_out] */ + png_ptr->zstream.next_out = output; + png_ptr->zstream.avail_out = 0; /* safety: set below */ + + if (output == NULL) + avail_out = 0; + + do + { + int ret; + png_byte tmpbuf[PNG_INFLATE_BUF_SIZE]; + + if (png_ptr->zstream.avail_in == 0) + { + uInt avail_in; + png_bytep buffer; + + while (png_ptr->idat_size == 0) + { + png_crc_finish(png_ptr, 0); + + png_ptr->idat_size = png_read_chunk_header(png_ptr); + /* This is an error even in the 'check' case because the code just + * consumed a non-IDAT header. + */ + if (png_ptr->chunk_name != png_IDAT) + png_error(png_ptr, "Not enough image data"); + } + + avail_in = png_ptr->IDAT_read_size; + + if (avail_in > png_ptr->idat_size) + avail_in = (uInt)png_ptr->idat_size; + + /* A PNG with a gradually increasing IDAT size will defeat this attempt + * to minimize memory usage by causing lots of re-allocs, but + * realistically doing IDAT_read_size re-allocs is not likely to be a + * big problem. + */ + buffer = png_read_buffer(png_ptr, avail_in, 0/*error*/); + + png_crc_read(png_ptr, buffer, avail_in); + png_ptr->idat_size -= avail_in; + + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = avail_in; + } + + /* And set up the output side. */ + if (output != NULL) /* standard read */ + { + uInt out = ZLIB_IO_MAX; + + if (out > avail_out) + out = (uInt)avail_out; + + avail_out -= out; + png_ptr->zstream.avail_out = out; + } + + else /* after last row, checking for end */ + { + png_ptr->zstream.next_out = tmpbuf; + png_ptr->zstream.avail_out = (sizeof tmpbuf); + } + + /* Use NO_FLUSH; this gives zlib the maximum opportunity to optimize the + * process. If the LZ stream is truncated the sequential reader will + * terminally damage the stream, above, by reading the chunk header of the + * following chunk (it then exits with png_error). + * + * TODO: deal more elegantly with truncated IDAT lists. + */ + ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); + + /* Take the unconsumed output back. */ + if (output != NULL) + avail_out += png_ptr->zstream.avail_out; + + else /* avail_out counts the extra bytes */ + avail_out += (sizeof tmpbuf) - png_ptr->zstream.avail_out; + + png_ptr->zstream.avail_out = 0; + + if (ret == Z_STREAM_END) + { + /* Do this for safety; we won't read any more into this row. */ + png_ptr->zstream.next_out = NULL; + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; + + if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0) + png_chunk_benign_error(png_ptr, "Extra compressed data"); + break; + } + + if (ret != Z_OK) + { + png_zstream_error(png_ptr, ret); + + if (output != NULL) + png_chunk_error(png_ptr, png_ptr->zstream.msg); + + else /* checking */ + { + png_chunk_benign_error(png_ptr, png_ptr->zstream.msg); + return; + } + } + } while (avail_out > 0); + + if (avail_out > 0) + { + /* The stream ended before the image; this is the same as too few IDATs so + * should be handled the same way. + */ + if (output != NULL) + png_error(png_ptr, "Not enough image data"); + + else /* the deflate stream contained extra data */ + png_chunk_benign_error(png_ptr, "Too much image data"); + } +} + +void /* PRIVATE */ +png_read_finish_IDAT(png_structrp png_ptr) +{ + /* We don't need any more data and the stream should have ended, however the + * LZ end code may actually not have been processed. In this case we must + * read it otherwise stray unread IDAT data or, more likely, an IDAT chunk + * may still remain to be consumed. + */ + if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + { + /* The NULL causes png_read_IDAT_data to swallow any remaining bytes in + * the compressed stream, but the stream may be damaged too, so even after + * this call we may need to terminate the zstream ownership. + */ + png_read_IDAT_data(png_ptr, NULL, 0); + png_ptr->zstream.next_out = NULL; /* safety */ + + /* Now clear everything out for safety; the following may not have been + * done. + */ + if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)) + { + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; + } + } + + /* If the zstream has not been released do it now *and* terminate the reading + * of the final IDAT chunk. + */ + if (png_ptr->zowner == png_IDAT) + { + /* Always do this; the pointers otherwise point into the read buffer. */ + png_ptr->zstream.next_in = NULL; + png_ptr->zstream.avail_in = 0; + + /* Now we no longer own the zstream. */ + png_ptr->zowner = 0; + + /* The slightly weird semantics of the sequential IDAT reading is that we + * are always in or at the end of an IDAT chunk, so we always need to do a + * crc_finish here. If idat_size is non-zero we also need to read the + * spurious bytes at the end of the chunk now. + */ + (void)png_crc_finish(png_ptr, png_ptr->idat_size); + } +} + +void /* PRIVATE */ +png_read_finish_row(png_structrp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + png_debug(1, "in png_read_finish_row"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + + /* TO DO: don't do this if prev_row isn't needed (requires + * read-ahead of the next row's filter byte. + */ + memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + do + { + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + } + + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; /* libpng deinterlacing sees every row */ + + } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + /* Here after at the end of the last row of the last pass. */ + png_read_finish_IDAT(png_ptr); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +void /* PRIVATE */ +png_read_start_row(png_structrp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int max_pixel_depth; + png_size_t row_bytes; + + png_debug(1, "in png_read_start_row"); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + png_init_read_transformations(png_ptr); +#endif +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + } + + else +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + } + + max_pixel_depth = png_ptr->pixel_depth; + + /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of + * calculations to calculate the final pixel depth, then + * png_do_read_transforms actually does the transforms. This means that the + * code which effectively calculates this value is actually repeated in three + * separate places. They must all match. Innocent changes to the order of + * transformations can and will break libpng in a way that causes memory + * overwrites. + * + * TODO: fix this. + */ +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + + else + max_pixel_depth = 24; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND_16) + { +# ifdef PNG_READ_EXPAND_SUPPORTED + /* In fact it is an error if it isn't supported, but checking is + * the safe way. + */ + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->bit_depth < 16) + max_pixel_depth *= 2; + } + else +# endif + png_ptr->transformations &= ~PNG_EXPAND_16; + } +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & (PNG_FILLER)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + + else + max_pixel_depth = 32; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB || + png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + + else + max_pixel_depth = 64; + } + } +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#ifdef PNG_READ_EXPAND_SUPPORTED + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#ifdef PNG_READ_FILLER_SUPPORTED + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + + else + max_pixel_depth = 64; + } + + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + + else + max_pixel_depth = 24; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth = png_ptr->user_transform_depth * + png_ptr->user_transform_channels; + + if (user_pixel_depth > max_pixel_depth) + max_pixel_depth = user_pixel_depth; + } +#endif + + /* This value is stored in png_struct and double checked in the row read + * code. + */ + png_ptr->maximum_pixel_depth = (png_byte)max_pixel_depth; + png_ptr->transformed_pixel_depth = 0; /* calculated on demand */ + + /* Align the width on the next larger 8 pixels. Mainly used + * for interlacing + */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* Calculate the maximum bytes needed, adding a byte and a pixel + * for safety's sake + */ + row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + + 1 + ((max_pixel_depth + 7) >> 3); + +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + + if (row_bytes + 48 > png_ptr->big_row_buf_size) + { + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->big_prev_row); + + if (png_ptr->interlaced) + png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + row_bytes + 48); + + else + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + + png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + +#ifdef PNG_ALIGNED_MEMORY_SUPPORTED + /* Use 16-byte aligned memory for row_buf with at least 16 bytes + * of padding before and after row_buf; treat prev_row similarly. + * NOTE: the alignment is to the start of the pixels, one beyond the start + * of the buffer, because of the filter byte. Prior to libpng 1.5.6 this + * was incorrect; the filter byte was aligned, which had the exact + * opposite effect of that intended. + */ + { + png_bytep temp = png_ptr->big_row_buf + 32; + int extra = (int)((temp - (png_bytep)0) & 0x0f); + png_ptr->row_buf = temp - extra - 1/*filter byte*/; + + temp = png_ptr->big_prev_row + 32; + extra = (int)((temp - (png_bytep)0) & 0x0f); + png_ptr->prev_row = temp - extra - 1/*filter byte*/; + } + +#else + /* Use 31 bytes of padding before and 17 bytes after row_buf. */ + png_ptr->row_buf = png_ptr->big_row_buf + 31; + png_ptr->prev_row = png_ptr->big_prev_row + 31; +#endif + png_ptr->big_row_buf_size = row_bytes + 48; + } + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->rowbytes > 65535) + png_error(png_ptr, "This image requires a row greater than 64KB"); + +#endif + if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1)) + png_error(png_ptr, "Row has too many bytes to allocate in memory"); + + memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + png_debug1(3, "width = %u,", png_ptr->width); + png_debug1(3, "height = %u,", png_ptr->height); + png_debug1(3, "iwidth = %u,", png_ptr->iwidth); + png_debug1(3, "num_rows = %u,", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu", + (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); + + /* The sequential reader needs a buffer for IDAT, but the progressive reader + * does not, so free the read buffer now regardless; the sequential reader + * reallocates it on demand. + */ + if (png_ptr->read_buffer) + { + png_bytep buffer = png_ptr->read_buffer; + + png_ptr->read_buffer_size = 0; + png_ptr->read_buffer = NULL; + png_free(png_ptr, buffer); + } + + /* Finally claim the zstream for the inflate of the IDAT data, use the bits + * value from the stream (note that this will result in a fatal error if the + * IDAT stream has a bogus deflate header window_bits value, but this should + * not be happening any longer!) + */ + if (png_inflate_claim(png_ptr, png_IDAT) != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/ext/libpng16/pngset.c b/ext/libpng17/pngset.c similarity index 91% rename from ext/libpng16/pngset.c rename to ext/libpng17/pngset.c index 1f60cdcbc0..f784fbf08b 100644 --- a/ext/libpng16/pngset.c +++ b/ext/libpng17/pngset.c @@ -1,1597 +1,1641 @@ - -/* pngset.c - storage of image information into info struct - * - * Last changed in libpng 1.6.3 [July 18, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - * The functions here are used during reads to store data from the file - * into the info struct, and during writes to store application data - * into the info struct for writing into the file. This abstracts the - * info struct and allows us to change the structure in the future. - */ - -#include "pngpriv.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -#ifdef PNG_bKGD_SUPPORTED -void PNGAPI -png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_color_16p background) -{ - png_debug1(1, "in %s storage function", "bKGD"); - - if (png_ptr == NULL || info_ptr == NULL || background == NULL) - return; - - info_ptr->background = *background; - info_ptr->valid |= PNG_INFO_bKGD; -} -#endif - -#ifdef PNG_cHRM_SUPPORTED -void PNGFAPI -png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr, - png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, - png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, - png_fixed_point blue_x, png_fixed_point blue_y) -{ - png_xy xy; - - png_debug1(1, "in %s storage function", "cHRM fixed"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - xy.redx = red_x; - xy.redy = red_y; - xy.greenx = green_x; - xy.greeny = green_y; - xy.bluex = blue_x; - xy.bluey = blue_y; - xy.whitex = white_x; - xy.whitey = white_y; - - if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy, - 2/* override with app values*/)) - info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; - - png_colorspace_sync_info(png_ptr, info_ptr); -} - -void PNGFAPI -png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr, - png_fixed_point int_red_X, png_fixed_point int_red_Y, - png_fixed_point int_red_Z, png_fixed_point int_green_X, - png_fixed_point int_green_Y, png_fixed_point int_green_Z, - png_fixed_point int_blue_X, png_fixed_point int_blue_Y, - png_fixed_point int_blue_Z) -{ - png_XYZ XYZ; - - png_debug1(1, "in %s storage function", "cHRM XYZ fixed"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - XYZ.red_X = int_red_X; - XYZ.red_Y = int_red_Y; - XYZ.red_Z = int_red_Z; - XYZ.green_X = int_green_X; - XYZ.green_Y = int_green_Y; - XYZ.green_Z = int_green_Z; - XYZ.blue_X = int_blue_X; - XYZ.blue_Y = int_blue_Y; - XYZ.blue_Z = int_blue_Z; - - if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace, &XYZ, 2)) - info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; - - png_colorspace_sync_info(png_ptr, info_ptr); -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, - double white_x, double white_y, double red_x, double red_y, - double green_x, double green_y, double blue_x, double blue_y) -{ - png_set_cHRM_fixed(png_ptr, info_ptr, - png_fixed(png_ptr, white_x, "cHRM White X"), - png_fixed(png_ptr, white_y, "cHRM White Y"), - png_fixed(png_ptr, red_x, "cHRM Red X"), - png_fixed(png_ptr, red_y, "cHRM Red Y"), - png_fixed(png_ptr, green_x, "cHRM Green X"), - png_fixed(png_ptr, green_y, "cHRM Green Y"), - png_fixed(png_ptr, blue_x, "cHRM Blue X"), - png_fixed(png_ptr, blue_y, "cHRM Blue Y")); -} - -void PNGAPI -png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, - double red_Y, double red_Z, double green_X, double green_Y, double green_Z, - double blue_X, double blue_Y, double blue_Z) -{ - png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, - png_fixed(png_ptr, red_X, "cHRM Red X"), - png_fixed(png_ptr, red_Y, "cHRM Red Y"), - png_fixed(png_ptr, red_Z, "cHRM Red Z"), - png_fixed(png_ptr, green_X, "cHRM Red X"), - png_fixed(png_ptr, green_Y, "cHRM Red Y"), - png_fixed(png_ptr, green_Z, "cHRM Red Z"), - png_fixed(png_ptr, blue_X, "cHRM Red X"), - png_fixed(png_ptr, blue_Y, "cHRM Red Y"), - png_fixed(png_ptr, blue_Z, "cHRM Red Z")); -} -# endif /* PNG_FLOATING_POINT_SUPPORTED */ - -#endif /* PNG_cHRM_SUPPORTED */ - -#ifdef PNG_gAMA_SUPPORTED -void PNGFAPI -png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr, - png_fixed_point file_gamma) -{ - png_debug1(1, "in %s storage function", "gAMA"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma); - png_colorspace_sync_info(png_ptr, info_ptr); -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma) -{ - png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma, - "png_set_gAMA")); -} -# endif -#endif - -#ifdef PNG_hIST_SUPPORTED -void PNGAPI -png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_uint_16p hist) -{ - int i; - - png_debug1(1, "in %s storage function", "hIST"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (info_ptr->num_palette == 0 || info_ptr->num_palette - > PNG_MAX_PALETTE_LENGTH) - { - png_warning(png_ptr, - "Invalid palette size, hIST allocation skipped"); - - return; - } - - png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); - - /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in - * version 1.2.1 - */ - info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr, - PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16)))); - - if (info_ptr->hist == NULL) - { - png_warning(png_ptr, "Insufficient memory for hIST chunk data"); - return; - } - - info_ptr->free_me |= PNG_FREE_HIST; - - for (i = 0; i < info_ptr->num_palette; i++) - info_ptr->hist[i] = hist[i]; - - info_ptr->valid |= PNG_INFO_hIST; -} -#endif - -void PNGAPI -png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_type, int compression_type, - int filter_type) -{ - png_debug1(1, "in %s storage function", "IHDR"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->width = width; - info_ptr->height = height; - info_ptr->bit_depth = (png_byte)bit_depth; - info_ptr->color_type = (png_byte)color_type; - info_ptr->compression_type = (png_byte)compression_type; - info_ptr->filter_type = (png_byte)filter_type; - info_ptr->interlace_type = (png_byte)interlace_type; - - png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, - info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, - info_ptr->compression_type, info_ptr->filter_type); - - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - info_ptr->channels = 1; - - else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) - info_ptr->channels = 3; - - else - info_ptr->channels = 1; - - if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - info_ptr->channels++; - - info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); - - info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); -} - -#ifdef PNG_oFFs_SUPPORTED -void PNGAPI -png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr, - png_int_32 offset_x, png_int_32 offset_y, int unit_type) -{ - png_debug1(1, "in %s storage function", "oFFs"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->x_offset = offset_x; - info_ptr->y_offset = offset_y; - info_ptr->offset_unit_type = (png_byte)unit_type; - info_ptr->valid |= PNG_INFO_oFFs; -} -#endif - -#ifdef PNG_pCAL_SUPPORTED -void PNGAPI -png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, - int nparams, png_const_charp units, png_charpp params) -{ - png_size_t length; - int i; - - png_debug1(1, "in %s storage function", "pCAL"); - - if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL - || (nparams > 0 && params == NULL)) - return; - - length = strlen(purpose) + 1; - png_debug1(3, "allocating purpose for info (%lu bytes)", - (unsigned long)length); - - /* TODO: validate format of calibration name and unit name */ - - /* Check that the type matches the specification. */ - if (type < 0 || type > 3) - png_error(png_ptr, "Invalid pCAL equation type"); - - if (nparams < 0 || nparams > 255) - png_error(png_ptr, "Invalid pCAL parameter count"); - - /* Validate params[nparams] */ - for (i=0; ipcal_purpose = png_voidcast(png_charp, - png_malloc_warn(png_ptr, length)); - - if (info_ptr->pcal_purpose == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL purpose"); - return; - } - - memcpy(info_ptr->pcal_purpose, purpose, length); - - png_debug(3, "storing X0, X1, type, and nparams in info"); - info_ptr->pcal_X0 = X0; - info_ptr->pcal_X1 = X1; - info_ptr->pcal_type = (png_byte)type; - info_ptr->pcal_nparams = (png_byte)nparams; - - length = strlen(units) + 1; - png_debug1(3, "allocating units for info (%lu bytes)", - (unsigned long)length); - - info_ptr->pcal_units = png_voidcast(png_charp, - png_malloc_warn(png_ptr, length)); - - if (info_ptr->pcal_units == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL units"); - return; - } - - memcpy(info_ptr->pcal_units, units, length); - - info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, - (png_size_t)((nparams + 1) * (sizeof (png_charp))))); - - if (info_ptr->pcal_params == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL params"); - return; - } - - memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp))); - - for (i = 0; i < nparams; i++) - { - length = strlen(params[i]) + 1; - png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, - (unsigned long)length); - - info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); - - if (info_ptr->pcal_params[i] == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL parameter"); - return; - } - - memcpy(info_ptr->pcal_params[i], params[i], length); - } - - info_ptr->valid |= PNG_INFO_pCAL; - info_ptr->free_me |= PNG_FREE_PCAL; -} -#endif - -#ifdef PNG_sCAL_SUPPORTED -void PNGAPI -png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, - int unit, png_const_charp swidth, png_const_charp sheight) -{ - png_size_t lengthw = 0, lengthh = 0; - - png_debug1(1, "in %s storage function", "sCAL"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - /* Double check the unit (should never get here with an invalid - * unit unless this is an API call.) - */ - if (unit != 1 && unit != 2) - png_error(png_ptr, "Invalid sCAL unit"); - - if (swidth == NULL || (lengthw = strlen(swidth)) == 0 || - swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw)) - png_error(png_ptr, "Invalid sCAL width"); - - if (sheight == NULL || (lengthh = strlen(sheight)) == 0 || - sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh)) - png_error(png_ptr, "Invalid sCAL height"); - - info_ptr->scal_unit = (png_byte)unit; - - ++lengthw; - - png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); - - info_ptr->scal_s_width = png_voidcast(png_charp, - png_malloc_warn(png_ptr, lengthw)); - - if (info_ptr->scal_s_width == NULL) - { - png_warning(png_ptr, "Memory allocation failed while processing sCAL"); - return; - } - - memcpy(info_ptr->scal_s_width, swidth, lengthw); - - ++lengthh; - - png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); - - info_ptr->scal_s_height = png_voidcast(png_charp, - png_malloc_warn(png_ptr, lengthh)); - - if (info_ptr->scal_s_height == NULL) - { - png_free (png_ptr, info_ptr->scal_s_width); - info_ptr->scal_s_width = NULL; - - png_warning(png_ptr, "Memory allocation failed while processing sCAL"); - return; - } - - memcpy(info_ptr->scal_s_height, sheight, lengthh); - - info_ptr->valid |= PNG_INFO_sCAL; - info_ptr->free_me |= PNG_FREE_SCAL; -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit, - double width, double height) -{ - png_debug1(1, "in %s storage function", "sCAL"); - - /* Check the arguments. */ - if (width <= 0) - png_warning(png_ptr, "Invalid sCAL width ignored"); - - else if (height <= 0) - png_warning(png_ptr, "Invalid sCAL height ignored"); - - else - { - /* Convert 'width' and 'height' to ASCII. */ - char swidth[PNG_sCAL_MAX_DIGITS+1]; - char sheight[PNG_sCAL_MAX_DIGITS+1]; - - png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width, - PNG_sCAL_PRECISION); - png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height, - PNG_sCAL_PRECISION); - - png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); - } -} -# endif - -# ifdef PNG_FIXED_POINT_SUPPORTED -void PNGAPI -png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit, - png_fixed_point width, png_fixed_point height) -{ - png_debug1(1, "in %s storage function", "sCAL"); - - /* Check the arguments. */ - if (width <= 0) - png_warning(png_ptr, "Invalid sCAL width ignored"); - - else if (height <= 0) - png_warning(png_ptr, "Invalid sCAL height ignored"); - - else - { - /* Convert 'width' and 'height' to ASCII. */ - char swidth[PNG_sCAL_MAX_DIGITS+1]; - char sheight[PNG_sCAL_MAX_DIGITS+1]; - - png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width); - png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height); - - png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); - } -} -# endif -#endif - -#ifdef PNG_pHYs_SUPPORTED -void PNGAPI -png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr, - png_uint_32 res_x, png_uint_32 res_y, int unit_type) -{ - png_debug1(1, "in %s storage function", "pHYs"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->x_pixels_per_unit = res_x; - info_ptr->y_pixels_per_unit = res_y; - info_ptr->phys_unit_type = (png_byte)unit_type; - info_ptr->valid |= PNG_INFO_pHYs; -} -#endif - -void PNGAPI -png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, - png_const_colorp palette, int num_palette) -{ - - png_debug1(1, "in %s storage function", "PLTE"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) - { - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_error(png_ptr, "Invalid palette length"); - - else - { - png_warning(png_ptr, "Invalid palette length"); - return; - } - } - - if ((num_palette > 0 && palette == NULL) || - (num_palette == 0 -# ifdef PNG_MNG_FEATURES_SUPPORTED - && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 -# endif - )) - { - png_chunk_report(png_ptr, "Invalid palette", PNG_CHUNK_ERROR); - return; - } - - /* It may not actually be necessary to set png_ptr->palette here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - * - * 1.6.0: the above statement appears to be incorrect; something has to set - * the palette inside png_struct on read. - */ - png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); - - /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead - * of num_palette entries, in case of an invalid PNG file that has - * too-large sample values. - */ - png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr, - PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); - - if (num_palette > 0) - memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color))); - info_ptr->palette = png_ptr->palette; - info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; - - info_ptr->free_me |= PNG_FREE_PLTE; - - info_ptr->valid |= PNG_INFO_PLTE; -} - -#ifdef PNG_sBIT_SUPPORTED -void PNGAPI -png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_color_8p sig_bit) -{ - png_debug1(1, "in %s storage function", "sBIT"); - - if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL) - return; - - info_ptr->sig_bit = *sig_bit; - info_ptr->valid |= PNG_INFO_sBIT; -} -#endif - -#ifdef PNG_sRGB_SUPPORTED -void PNGAPI -png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent) -{ - png_debug1(1, "in %s storage function", "sRGB"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent); - png_colorspace_sync_info(png_ptr, info_ptr); -} - -void PNGAPI -png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, - int srgb_intent) -{ - png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent)) - { - /* This causes the gAMA and cHRM to be written too */ - info_ptr->colorspace.flags |= - PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM; - } - - png_colorspace_sync_info(png_ptr, info_ptr); -} -#endif /* sRGB */ - - -#ifdef PNG_iCCP_SUPPORTED -void PNGAPI -png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_charp name, int compression_type, - png_const_bytep profile, png_uint_32 proflen) -{ - png_charp new_iccp_name; - png_bytep new_iccp_profile; - png_size_t length; - - png_debug1(1, "in %s storage function", "iCCP"); - - if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) - return; - - if (compression_type != PNG_COMPRESSION_TYPE_BASE) - png_app_error(png_ptr, "Invalid iCCP compression method"); - - /* Set the colorspace first because this validates the profile; do not - * override previously set app cHRM or gAMA here (because likely as not the - * application knows better than libpng what the correct values are.) Pass - * the info_ptr color_type field to png_colorspace_set_ICC because in the - * write case it has not yet been stored in png_ptr. - */ - { - int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name, - proflen, profile, info_ptr->color_type); - - png_colorspace_sync_info(png_ptr, info_ptr); - - /* Don't do any of the copying if the profile was bad, or inconsistent. */ - if (!result) - return; - - /* But do write the gAMA and cHRM chunks from the profile. */ - info_ptr->colorspace.flags |= - PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM; - } - - length = strlen(name)+1; - new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length)); - - if (new_iccp_name == NULL) - { - png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk"); - return; - } - - memcpy(new_iccp_name, name, length); - new_iccp_profile = png_voidcast(png_bytep, - png_malloc_warn(png_ptr, proflen)); - - if (new_iccp_profile == NULL) - { - png_free(png_ptr, new_iccp_name); - png_benign_error(png_ptr, - "Insufficient memory to process iCCP profile"); - return; - } - - memcpy(new_iccp_profile, profile, proflen); - - png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); - - info_ptr->iccp_proflen = proflen; - info_ptr->iccp_name = new_iccp_name; - info_ptr->iccp_profile = new_iccp_profile; - info_ptr->free_me |= PNG_FREE_ICCP; - info_ptr->valid |= PNG_INFO_iCCP; -} -#endif - -#ifdef PNG_TEXT_SUPPORTED -void PNGAPI -png_set_text(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_textp text_ptr, int num_text) -{ - int ret; - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); - - if (ret) - png_error(png_ptr, "Insufficient memory to store text"); -} - -int /* PRIVATE */ -png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_textp text_ptr, int num_text) -{ - int i; - - png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" : - (unsigned long)png_ptr->chunk_name); - - if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL) - return(0); - - /* Make sure we have enough space in the "text" array in info_struct - * to hold all of the incoming text_ptr objects. This compare can't overflow - * because max_text >= num_text (anyway, subtract of two positive integers - * can't overflow in any case.) - */ - if (num_text > info_ptr->max_text - info_ptr->num_text) - { - int old_num_text = info_ptr->num_text; - int max_text; - png_textp new_text = NULL; - - /* Calculate an appropriate max_text, checking for overflow. */ - max_text = old_num_text; - if (num_text <= INT_MAX - max_text) - { - max_text += num_text; - - /* Round up to a multiple of 8 */ - if (max_text < INT_MAX-8) - max_text = (max_text + 8) & ~0x7; - - else - max_text = INT_MAX; - - /* Now allocate a new array and copy the old members in, this does all - * the overflow checks. - */ - new_text = png_voidcast(png_textp,png_realloc_array(png_ptr, - info_ptr->text, old_num_text, max_text-old_num_text, - sizeof *new_text)); - } - - if (new_text == NULL) - { - png_chunk_report(png_ptr, "too many text chunks", - PNG_CHUNK_WRITE_ERROR); - return 1; - } - - png_free(png_ptr, info_ptr->text); - - info_ptr->text = new_text; - info_ptr->free_me |= PNG_FREE_TEXT; - info_ptr->max_text = max_text; - /* num_text is adjusted below as the entries are copied in */ - - png_debug1(3, "allocated %d entries for info_ptr->text", max_text); - } - - for (i = 0; i < num_text; i++) - { - size_t text_length, key_len; - size_t lang_len, lang_key_len; - png_textp textp = &(info_ptr->text[info_ptr->num_text]); - - if (text_ptr[i].key == NULL) - continue; - - if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE || - text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) - { - png_chunk_report(png_ptr, "text compression mode is out of range", - PNG_CHUNK_WRITE_ERROR); - continue; - } - - key_len = strlen(text_ptr[i].key); - - if (text_ptr[i].compression <= 0) - { - lang_len = 0; - lang_key_len = 0; - } - - else -# ifdef PNG_iTXt_SUPPORTED - { - /* Set iTXt data */ - - if (text_ptr[i].lang != NULL) - lang_len = strlen(text_ptr[i].lang); - - else - lang_len = 0; - - if (text_ptr[i].lang_key != NULL) - lang_key_len = strlen(text_ptr[i].lang_key); - - else - lang_key_len = 0; - } -# else /* PNG_iTXt_SUPPORTED */ - { - png_chunk_report(png_ptr, "iTXt chunk not supported", - PNG_CHUNK_WRITE_ERROR); - continue; - } -# endif - - if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') - { - text_length = 0; -# ifdef PNG_iTXt_SUPPORTED - if (text_ptr[i].compression > 0) - textp->compression = PNG_ITXT_COMPRESSION_NONE; - - else -# endif - textp->compression = PNG_TEXT_COMPRESSION_NONE; - } - - else - { - text_length = strlen(text_ptr[i].text); - textp->compression = text_ptr[i].compression; - } - - textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr, - key_len + text_length + lang_len + lang_key_len + 4)); - - if (textp->key == NULL) - { - png_chunk_report(png_ptr, "text chunk: out of memory", - PNG_CHUNK_WRITE_ERROR); - return 1; - } - - png_debug2(2, "Allocated %lu bytes at %p in png_set_text", - (unsigned long)(png_uint_32) - (key_len + lang_len + lang_key_len + text_length + 4), - textp->key); - - memcpy(textp->key, text_ptr[i].key, key_len); - *(textp->key + key_len) = '\0'; - - if (text_ptr[i].compression > 0) - { - textp->lang = textp->key + key_len + 1; - memcpy(textp->lang, text_ptr[i].lang, lang_len); - *(textp->lang + lang_len) = '\0'; - textp->lang_key = textp->lang + lang_len + 1; - memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); - *(textp->lang_key + lang_key_len) = '\0'; - textp->text = textp->lang_key + lang_key_len + 1; - } - - else - { - textp->lang=NULL; - textp->lang_key=NULL; - textp->text = textp->key + key_len + 1; - } - - if (text_length) - memcpy(textp->text, text_ptr[i].text, text_length); - - *(textp->text + text_length) = '\0'; - -# ifdef PNG_iTXt_SUPPORTED - if (textp->compression > 0) - { - textp->text_length = 0; - textp->itxt_length = text_length; - } - - else -# endif - { - textp->text_length = text_length; - textp->itxt_length = 0; - } - - info_ptr->num_text++; - png_debug1(3, "transferred text chunk %d", info_ptr->num_text); - } - - return(0); -} -#endif - -#ifdef PNG_tIME_SUPPORTED -void PNGAPI -png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_timep mod_time) -{ - png_debug1(1, "in %s storage function", "tIME"); - - if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL || - (png_ptr->mode & PNG_WROTE_tIME)) - return; - - if (mod_time->month == 0 || mod_time->month > 12 || - mod_time->day == 0 || mod_time->day > 31 || - mod_time->hour > 23 || mod_time->minute > 59 || - mod_time->second > 60) - { - png_warning(png_ptr, "Ignoring invalid time value"); - return; - } - - info_ptr->mod_time = *mod_time; - info_ptr->valid |= PNG_INFO_tIME; -} -#endif - -#ifdef PNG_tRNS_SUPPORTED -void PNGAPI -png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, - png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color) -{ - png_debug1(1, "in %s storage function", "tRNS"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (trans_alpha != NULL) - { - /* It may not actually be necessary to set png_ptr->trans_alpha here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - * - * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively - * relies on png_set_tRNS storing the information in png_struct - * (otherwise it won't be there for the code in pngrtran.c). - */ - - png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); - - /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ - png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep, - png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); - - if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) - memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); - } - - if (trans_color != NULL) - { - int sample_max = (1 << info_ptr->bit_depth); - - if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && - trans_color->gray > sample_max) || - (info_ptr->color_type == PNG_COLOR_TYPE_RGB && - (trans_color->red > sample_max || - trans_color->green > sample_max || - trans_color->blue > sample_max))) - png_warning(png_ptr, - "tRNS chunk has out-of-range samples for bit_depth"); - - info_ptr->trans_color = *trans_color; - - if (num_trans == 0) - num_trans = 1; - } - - info_ptr->num_trans = (png_uint_16)num_trans; - - if (num_trans != 0) - { - info_ptr->valid |= PNG_INFO_tRNS; - info_ptr->free_me |= PNG_FREE_TRNS; - } -} -#endif - -#ifdef PNG_sPLT_SUPPORTED -void PNGAPI -png_set_sPLT(png_const_structrp png_ptr, - png_inforp info_ptr, png_const_sPLT_tp entries, int nentries) -/* - * entries - array of png_sPLT_t structures - * to be added to the list of palettes - * in the info structure. - * - * nentries - number of palette structures to be - * added. - */ -{ - png_sPLT_tp np; - - if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL) - return; - - /* Use the internal realloc function, which checks for all the possible - * overflows. Notice that the parameters are (int) and (size_t) - */ - np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr, - info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries, - sizeof *np)); - - if (np == NULL) - { - /* Out of memory or too many chunks */ - png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR); - return; - } - - png_free(png_ptr, info_ptr->splt_palettes); - info_ptr->splt_palettes = np; - info_ptr->free_me |= PNG_FREE_SPLT; - - np += info_ptr->splt_palettes_num; - - do - { - png_size_t length; - - /* Skip invalid input entries */ - if (entries->name == NULL || entries->entries == NULL) - { - /* png_handle_sPLT doesn't do this, so this is an app error */ - png_app_error(png_ptr, "png_set_sPLT: invalid sPLT"); - /* Just skip the invalid entry */ - continue; - } - - np->depth = entries->depth; - - /* In the even of out-of-memory just return - there's no point keeping on - * trying to add sPLT chunks. - */ - length = strlen(entries->name) + 1; - np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length)); - - if (np->name == NULL) - break; - - memcpy(np->name, entries->name, length); - - /* IMPORTANT: we have memory now that won't get freed if something else - * goes wrong, this code must free it. png_malloc_array produces no - * warnings, use a png_chunk_report (below) if there is an error. - */ - np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr, - entries->nentries, sizeof (png_sPLT_entry))); - - if (np->entries == NULL) - { - png_free(png_ptr, np->name); - break; - } - - np->nentries = entries->nentries; - /* This multiply can't overflow because png_malloc_array has already - * checked it when doing the allocation. - */ - memcpy(np->entries, entries->entries, - entries->nentries * sizeof (png_sPLT_entry)); - - /* Note that 'continue' skips the advance of the out pointer and out - * count, so an invalid entry is not added. - */ - info_ptr->valid |= PNG_INFO_sPLT; - ++(info_ptr->splt_palettes_num); - ++np; - } - while (++entries, --nentries); - - if (nentries > 0) - png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR); -} -#endif /* PNG_sPLT_SUPPORTED */ - -#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -static png_byte -check_location(png_const_structrp png_ptr, int location) -{ - location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT); - - /* New in 1.6.0; copy the location and check it. This is an API - * change, previously the app had to use the - * png_set_unknown_chunk_location API below for each chunk. - */ - if (location == 0 && !(png_ptr->mode & PNG_IS_READ_STRUCT)) - { - /* Write struct, so unknown chunks come from the app */ - png_app_warning(png_ptr, - "png_set_unknown_chunks now expects a valid location"); - /* Use the old behavior */ - location = (png_byte)(png_ptr->mode & - (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)); - } - - /* This need not be an internal error - if the app calls - * png_set_unknown_chunks on a read pointer it must get the location right. - */ - if (location == 0) - png_error(png_ptr, "invalid location in png_set_unknown_chunks"); - - /* Now reduce the location to the top-most set bit by removing each least - * significant bit in turn. - */ - while (location != (location & -location)) - location &= ~(location & -location); - - /* The cast is safe because 'location' is a bit mask and only the low four - * bits are significant. - */ - return (png_byte)location; -} - -void PNGAPI -png_set_unknown_chunks(png_const_structrp png_ptr, - png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) -{ - png_unknown_chunkp np; - - if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 || - unknowns == NULL) - return; - - /* Check for the failure cases where support has been disabled at compile - * time. This code is hardly ever compiled - it's here because - * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this - * code) but may be meaningless if the read or write handling of unknown - * chunks is not compiled in. - */ -# if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \ - defined(PNG_READ_SUPPORTED) - if (png_ptr->mode & PNG_IS_READ_STRUCT) - { - png_app_error(png_ptr, "no unknown chunk support on read"); - return; - } -# endif -# if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \ - defined(PNG_WRITE_SUPPORTED) - if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) - { - png_app_error(png_ptr, "no unknown chunk support on write"); - return; - } -# endif - - /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that - * unknown critical chunks could be lost with just a warning resulting in - * undefined behavior. Now png_chunk_report is used to provide behavior - * appropriate to read or write. - */ - np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr, - info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns, - sizeof *np)); - - if (np == NULL) - { - png_chunk_report(png_ptr, "too many unknown chunks", - PNG_CHUNK_WRITE_ERROR); - return; - } - - png_free(png_ptr, info_ptr->unknown_chunks); - info_ptr->unknown_chunks = np; /* safe because it is initialized */ - info_ptr->free_me |= PNG_FREE_UNKN; - - np += info_ptr->unknown_chunks_num; - - /* Increment unknown_chunks_num each time round the loop to protect the - * just-allocated chunk data. - */ - for (; num_unknowns > 0; --num_unknowns, ++unknowns) - { - memcpy(np->name, unknowns->name, (sizeof np->name)); - np->name[(sizeof np->name)-1] = '\0'; - np->location = check_location(png_ptr, unknowns->location); - - if (unknowns->size == 0) - { - np->data = NULL; - np->size = 0; - } - - else - { - np->data = png_voidcast(png_bytep, - png_malloc_base(png_ptr, unknowns->size)); - - if (np->data == NULL) - { - png_chunk_report(png_ptr, "unknown chunk: out of memory", - PNG_CHUNK_WRITE_ERROR); - /* But just skip storing the unknown chunk */ - continue; - } - - memcpy(np->data, unknowns->data, unknowns->size); - np->size = unknowns->size; - } - - /* These increments are skipped on out-of-memory for the data - the - * unknown chunk entry gets overwritten if the png_chunk_report returns. - * This is correct in the read case (the chunk is just dropped.) - */ - ++np; - ++(info_ptr->unknown_chunks_num); - } -} - -void PNGAPI -png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr, - int chunk, int location) -{ - /* This API is pretty pointless in 1.6.0 because the location can be set - * before the call to png_set_unknown_chunks. - * - * TODO: add a png_app_warning in 1.7 - */ - if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && - chunk < info_ptr->unknown_chunks_num) - { - if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0) - { - png_app_error(png_ptr, "invalid unknown chunk location"); - /* Fake out the pre 1.6.0 behavior: */ - if ((location & PNG_HAVE_IDAT)) /* undocumented! */ - location = PNG_AFTER_IDAT; - - else - location = PNG_HAVE_IHDR; /* also undocumented */ - } - - info_ptr->unknown_chunks[chunk].location = - check_location(png_ptr, location); - } -} -#endif - - -#ifdef PNG_MNG_FEATURES_SUPPORTED -png_uint_32 PNGAPI -png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features) -{ - png_debug(1, "in png_permit_mng_features"); - - if (png_ptr == NULL) - return 0; - - png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES; - - return png_ptr->mng_features_permitted; -} -#endif - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -static unsigned int -add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep) -{ - unsigned int i; - - /* Utility function: update the 'keep' state of a chunk if it is already in - * the list, otherwise add it to the list. - */ - for (i=0; i= PNG_HANDLE_CHUNK_LAST) - { - png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep"); - return; - } - - if (num_chunks_in <= 0) - { - png_ptr->unknown_default = keep; - - /* '0' means just set the flags, so stop here */ - if (num_chunks_in == 0) - return; - } - - if (num_chunks_in < 0) - { - /* Ignore all unknown chunks and all chunks recognized by - * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND - */ - static PNG_CONST png_byte chunks_to_ignore[] = { - 98, 75, 71, 68, '\0', /* bKGD */ - 99, 72, 82, 77, '\0', /* cHRM */ - 103, 65, 77, 65, '\0', /* gAMA */ - 104, 73, 83, 84, '\0', /* hIST */ - 105, 67, 67, 80, '\0', /* iCCP */ - 105, 84, 88, 116, '\0', /* iTXt */ - 111, 70, 70, 115, '\0', /* oFFs */ - 112, 67, 65, 76, '\0', /* pCAL */ - 112, 72, 89, 115, '\0', /* pHYs */ - 115, 66, 73, 84, '\0', /* sBIT */ - 115, 67, 65, 76, '\0', /* sCAL */ - 115, 80, 76, 84, '\0', /* sPLT */ - 115, 84, 69, 82, '\0', /* sTER */ - 115, 82, 71, 66, '\0', /* sRGB */ - 116, 69, 88, 116, '\0', /* tEXt */ - 116, 73, 77, 69, '\0', /* tIME */ - 122, 84, 88, 116, '\0' /* zTXt */ - }; - - chunk_list = chunks_to_ignore; - num_chunks = (sizeof chunks_to_ignore)/5; - } - - else /* num_chunks_in > 0 */ - { - if (chunk_list == NULL) - { - /* Prior to 1.6.0 this was silently ignored, now it is an app_error - * which can be switched off. - */ - png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list"); - return; - } - - num_chunks = num_chunks_in; - } - - old_num_chunks = png_ptr->num_chunk_list; - if (png_ptr->chunk_list == NULL) - old_num_chunks = 0; - - /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow. - */ - if (num_chunks + old_num_chunks > UINT_MAX/5) - { - png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks"); - return; - } - - /* If these chunks are being reset to the default then no more memory is - * required because add_one_chunk above doesn't extend the list if the 'keep' - * parameter is the default. - */ - if (keep) - { - new_list = png_voidcast(png_bytep, png_malloc(png_ptr, - 5 * (num_chunks + old_num_chunks))); - - if (old_num_chunks > 0) - memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks); - } - - else if (old_num_chunks > 0) - new_list = png_ptr->chunk_list; - - else - new_list = NULL; - - /* Add the new chunks together with each one's handling code. If the chunk - * already exists the code is updated, otherwise the chunk is added to the - * end. (In libpng 1.6.0 order no longer matters because this code enforces - * the earlier convention that the last setting is the one that is used.) - */ - if (new_list != NULL) - { - png_const_bytep inlist; - png_bytep outlist; - unsigned int i; - - for (i=0; ichunk_list != new_list) - png_free(png_ptr, new_list); - - new_list = NULL; - } - } - - else - num_chunks = 0; - - png_ptr->num_chunk_list = num_chunks; - - if (png_ptr->chunk_list != new_list) - { - if (png_ptr->chunk_list != NULL) - png_free(png_ptr, png_ptr->chunk_list); - - png_ptr->chunk_list = new_list; - } -} -#endif - -#ifdef PNG_READ_USER_CHUNKS_SUPPORTED -void PNGAPI -png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr, - png_user_chunk_ptr read_user_chunk_fn) -{ - png_debug(1, "in png_set_read_user_chunk_fn"); - - if (png_ptr == NULL) - return; - - png_ptr->read_user_chunk_fn = read_user_chunk_fn; - png_ptr->user_chunk_ptr = user_chunk_ptr; -} -#endif - -#ifdef PNG_INFO_IMAGE_SUPPORTED -void PNGAPI -png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr, - png_bytepp row_pointers) -{ - png_debug1(1, "in %s storage function", "rows"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) - png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); - - info_ptr->row_pointers = row_pointers; - - if (row_pointers) - info_ptr->valid |= PNG_INFO_IDAT; -} -#endif - -void PNGAPI -png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size) -{ - if (png_ptr == NULL) - return; - - if (size == 0 || size > PNG_UINT_31_MAX) - png_error(png_ptr, "invalid compression buffer size"); - -# ifdef PNG_SEQUENTIAL_READ_SUPPORTED - if (png_ptr->mode & PNG_IS_READ_STRUCT) - { - png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */ - return; - } -# endif - -# ifdef PNG_WRITE_SUPPORTED - if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) - { - if (png_ptr->zowner != 0) - { - png_warning(png_ptr, - "Compression buffer size cannot be changed because it is in use"); - return; - } - - if (size > ZLIB_IO_MAX) - { - png_warning(png_ptr, - "Compression buffer size limited to system maximum"); - size = ZLIB_IO_MAX; /* must fit */ - } - - else if (size < 6) - { - /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH - * if this is permitted. - */ - png_warning(png_ptr, - "Compression buffer size cannot be reduced below 6"); - return; - } - - if (png_ptr->zbuffer_size != size) - { - png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); - png_ptr->zbuffer_size = (uInt)size; - } - } -# endif -} - -void PNGAPI -png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask) -{ - if (png_ptr && info_ptr) - info_ptr->valid &= ~mask; -} - - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -/* This function was added to libpng 1.2.6 */ -void PNGAPI -png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, - png_uint_32 user_height_max) -{ - /* Images with dimensions larger than these limits will be - * rejected by png_set_IHDR(). To accept any PNG datastream - * regardless of dimensions, set both limits to 0x7ffffffL. - */ - if (png_ptr == NULL) - return; - - png_ptr->user_width_max = user_width_max; - png_ptr->user_height_max = user_height_max; -} - -/* This function was added to libpng 1.4.0 */ -void PNGAPI -png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max) -{ - if (png_ptr) - png_ptr->user_chunk_cache_max = user_chunk_cache_max; -} - -/* This function was added to libpng 1.4.1 */ -void PNGAPI -png_set_chunk_malloc_max (png_structrp png_ptr, - png_alloc_size_t user_chunk_malloc_max) -{ - if (png_ptr) - png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; -} -#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ - - -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -void PNGAPI -png_set_benign_errors(png_structrp png_ptr, int allowed) -{ - png_debug(1, "in png_set_benign_errors"); - - /* If allowed is 1, png_benign_error() is treated as a warning. - * - * If allowed is 0, png_benign_error() is treated as an error (which - * is the default behavior if png_set_benign_errors() is not called). - */ - - if (allowed) - png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN | - PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN; - - else - png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN | - PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN); -} -#endif /* PNG_BENIGN_ERRORS_SUPPORTED */ - -#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED - /* Whether to report invalid palette index; added at libng-1.5.10. - * It is possible for an indexed (color-type==3) PNG file to contain - * pixels with invalid (out-of-range) indexes if the PLTE chunk has - * fewer entries than the image's bit-depth would allow. We recover - * from this gracefully by filling any incomplete palette with zeroes - * (opaque black). By default, when this occurs libpng will issue - * a benign error. This API can be used to override that behavior. - */ -void PNGAPI -png_set_check_for_invalid_index(png_structrp png_ptr, int allowed) -{ - png_debug(1, "in png_set_check_for_invalid_index"); - - if (allowed > 0) - png_ptr->num_palette_max = 0; - - else - png_ptr->num_palette_max = -1; -} -#endif -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ + +/* pngset.c - storage of image information into info struct + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#ifdef PNG_bKGD_SUPPORTED +void PNGAPI +png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_color_16p background) +{ + png_debug1(1, "in %s storage function", "bKGD"); + + if (png_ptr == NULL || info_ptr == NULL || background == NULL) + return; + + info_ptr->background = *background; + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +void PNGFAPI +png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_xy xy; + + png_debug1(1, "in %s storage function", "cHRM fixed"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + xy.redx = red_x; + xy.redy = red_y; + xy.greenx = green_x; + xy.greeny = green_y; + xy.bluex = blue_x; + xy.bluey = blue_y; + xy.whitex = white_x; + xy.whitey = white_y; + + if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy, + 2/* override with app values*/)) + info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; + + png_colorspace_sync_info(png_ptr, info_ptr); +} + +void PNGFAPI +png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr, + png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z) +{ + png_XYZ XYZ; + + png_debug1(1, "in %s storage function", "cHRM XYZ fixed"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + XYZ.red_X = int_red_X; + XYZ.red_Y = int_red_Y; + XYZ.red_Z = int_red_Z; + XYZ.green_X = int_green_X; + XYZ.green_Y = int_green_Y; + XYZ.green_Z = int_green_Z; + XYZ.blue_X = int_blue_X; + XYZ.blue_Y = int_blue_Y; + XYZ.blue_Z = int_blue_Z; + + if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace, &XYZ, 2)) + info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; + + png_colorspace_sync_info(png_ptr, info_ptr); +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, + double white_x, double white_y, double red_x, double red_y, + double green_x, double green_y, double blue_x, double blue_y) +{ + png_set_cHRM_fixed(png_ptr, info_ptr, + png_fixed(png_ptr, white_x, "cHRM White X"), + png_fixed(png_ptr, white_y, "cHRM White Y"), + png_fixed(png_ptr, red_x, "cHRM Red X"), + png_fixed(png_ptr, red_y, "cHRM Red Y"), + png_fixed(png_ptr, green_x, "cHRM Green X"), + png_fixed(png_ptr, green_y, "cHRM Green Y"), + png_fixed(png_ptr, blue_x, "cHRM Blue X"), + png_fixed(png_ptr, blue_y, "cHRM Blue Y")); +} + +void PNGAPI +png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, + double red_Y, double red_Z, double green_X, double green_Y, double green_Z, + double blue_X, double blue_Y, double blue_Z) +{ + png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, + png_fixed(png_ptr, red_X, "cHRM Red X"), + png_fixed(png_ptr, red_Y, "cHRM Red Y"), + png_fixed(png_ptr, red_Z, "cHRM Red Z"), + png_fixed(png_ptr, green_X, "cHRM Red X"), + png_fixed(png_ptr, green_Y, "cHRM Red Y"), + png_fixed(png_ptr, green_Z, "cHRM Red Z"), + png_fixed(png_ptr, blue_X, "cHRM Red X"), + png_fixed(png_ptr, blue_Y, "cHRM Red Y"), + png_fixed(png_ptr, blue_Z, "cHRM Red Z")); +} +# endif /* PNG_FLOATING_POINT_SUPPORTED */ + +#endif /* PNG_cHRM_SUPPORTED */ + +#ifdef PNG_gAMA_SUPPORTED +void PNGFAPI +png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr, + png_fixed_point file_gamma) +{ + png_debug1(1, "in %s storage function", "gAMA"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma); + png_colorspace_sync_info(png_ptr, info_ptr); +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma) +{ + png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma, + "png_set_gAMA")); +} +# endif +#endif + +#ifdef PNG_hIST_SUPPORTED +void PNGAPI +png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function", "hIST"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->num_palette == 0 || info_ptr->num_palette + > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, + "Invalid palette size, hIST allocation skipped"); + + return; + } + + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); + + /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in + * version 1.2.1 + */ + info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr, + PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16)))); + + if (info_ptr->hist == NULL) + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data"); + return; + } + + info_ptr->free_me |= PNG_FREE_HIST; + + for (i = 0; i < info_ptr->num_palette; i++) + info_ptr->hist[i] = hist[i]; + + info_ptr->valid |= PNG_INFO_hIST; +} +#endif + +void PNGAPI +png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + png_debug1(1, "in %s storage function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type = (png_byte)color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + + else + info_ptr->channels = 1; + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); +} + +#ifdef PNG_oFFs_SUPPORTED +void PNGAPI +png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "oFFs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +void PNGAPI +png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, png_const_charp units, png_charpp params) +{ + png_size_t length; + int i; + + png_debug1(1, "in %s storage function", "pCAL"); + + if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL + || (nparams > 0 && params == NULL)) + return; + + length = strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)", + (unsigned long)length); + + /* TODO: validate format of calibration name and unit name */ + + /* Check that the type matches the specification. */ + if (type < 0 || type > 3) + png_error(png_ptr, "Invalid pCAL equation type"); + + if (nparams < 0 || nparams > 255) + png_error(png_ptr, "Invalid pCAL parameter count"); + + /* Validate params[nparams] */ + for (i=0; ipcal_purpose = png_voidcast(png_charp, + png_malloc_warn(png_ptr, length)); + + if (info_ptr->pcal_purpose == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose"); + return; + } + + memcpy(info_ptr->pcal_purpose, purpose, length); + + png_debug(3, "storing X0, X1, type, and nparams in info"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)", + (unsigned long)length); + + info_ptr->pcal_units = png_voidcast(png_charp, + png_malloc_warn(png_ptr, length)); + + if (info_ptr->pcal_units == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL units"); + return; + } + + memcpy(info_ptr->pcal_units, units, length); + + info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, + (png_size_t)((nparams + 1) * (sizeof (png_charp))))); + + if (info_ptr->pcal_params == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL params"); + return; + } + + memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp))); + + for (i = 0; i < nparams; i++) + { + length = strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, + (unsigned long)length); + + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter"); + return; + } + + memcpy(info_ptr->pcal_params[i], params[i], length); + } + + info_ptr->valid |= PNG_INFO_pCAL; + info_ptr->free_me |= PNG_FREE_PCAL; +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight) +{ + png_size_t lengthw = 0, lengthh = 0; + + png_debug1(1, "in %s storage function", "sCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Double check the unit (should never get here with an invalid + * unit unless this is an API call.) + */ + if (unit != 1 && unit != 2) + png_error(png_ptr, "Invalid sCAL unit"); + + if (swidth == NULL || (lengthw = strlen(swidth)) == 0 || + swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw)) + png_error(png_ptr, "Invalid sCAL width"); + + if (sheight == NULL || (lengthh = strlen(sheight)) == 0 || + sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh)) + png_error(png_ptr, "Invalid sCAL height"); + + info_ptr->scal_unit = (png_byte)unit; + + ++lengthw; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); + + info_ptr->scal_s_width = png_voidcast(png_charp, + png_malloc_warn(png_ptr, lengthw)); + + if (info_ptr->scal_s_width == NULL) + { + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; + } + + memcpy(info_ptr->scal_s_width, swidth, lengthw); + + ++lengthh; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); + + info_ptr->scal_s_height = png_voidcast(png_charp, + png_malloc_warn(png_ptr, lengthh)); + + if (info_ptr->scal_s_height == NULL) + { + png_free (png_ptr, info_ptr->scal_s_width); + info_ptr->scal_s_width = NULL; + + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; + } + + memcpy(info_ptr->scal_s_height, sheight, lengthh); + + info_ptr->valid |= PNG_INFO_sCAL; + info_ptr->free_me |= PNG_FREE_SCAL; +} + +# if defined(PNG_FLOATING_POINT_SUPPORTED) &&\ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) +void PNGAPI +png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit, + double width, double height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width, + PNG_sCAL_PRECISION); + png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height, + PNG_sCAL_PRECISION); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit, + png_fixed_point width, png_fixed_point height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width); + png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif +#endif + +#ifdef PNG_pHYs_SUPPORTED +void PNGAPI +png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "pHYs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, + png_const_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function", "PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Invalid palette length"); + + else + { + png_warning(png_ptr, "Invalid palette length"); + return; + } + } + + if ((num_palette > 0 && palette == NULL) || + (num_palette == 0 +# ifdef PNG_MNG_FEATURES_SUPPORTED + && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 +# endif + )) + { + png_error(png_ptr, "Invalid palette"); + return; + } + + /* It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + * + * 1.6.0: the above statement appears to be incorrect; something has to set + * the palette inside png_struct on read. + */ + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); + + /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead + * of num_palette entries, in case of an invalid PNG file that has + * too-large sample values. + */ + png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); + + if (num_palette > 0) + memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color))); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + + info_ptr->free_me |= PNG_FREE_PLTE; + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#ifdef PNG_sBIT_SUPPORTED +void PNGAPI +png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function", "sBIT"); + + if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL) + return; + + info_ptr->sig_bit = *sig_bit; + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#ifdef PNG_sRGB_SUPPORTED +void PNGAPI +png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent); + png_colorspace_sync_info(png_ptr, info_ptr); +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, + int srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent)) + { + /* This causes the gAMA and cHRM to be written too */ + info_ptr->colorspace.flags |= + PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM; + } + + png_colorspace_sync_info(png_ptr, info_ptr); +} +#endif /* sRGB */ + + +#ifdef PNG_iCCP_SUPPORTED +void PNGAPI +png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_bytep new_iccp_profile; + png_size_t length; + + png_debug1(1, "in %s storage function", "iCCP"); + + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_app_error(png_ptr, "Invalid iCCP compression method"); + + /* Set the colorspace first because this validates the profile; do not + * override previously set app cHRM or gAMA here (because likely as not the + * application knows better than libpng what the correct values are.) Pass + * the info_ptr color_type field to png_colorspace_set_ICC because in the + * write case it has not yet been stored in png_ptr. + */ + { + int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name, + proflen, profile, info_ptr->color_type); + + png_colorspace_sync_info(png_ptr, info_ptr); + + /* Don't do any of the copying if the profile was bad, or inconsistent. */ + if (result == 0) + return; + + /* But do write the gAMA and cHRM chunks from the profile. */ + info_ptr->colorspace.flags |= + PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM; + } + + length = strlen(name)+1; + new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length)); + + if (new_iccp_name == NULL) + { + png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk"); + return; + } + + memcpy(new_iccp_name, name, length); + new_iccp_profile = png_voidcast(png_bytep, + png_malloc_warn(png_ptr, proflen)); + + if (new_iccp_profile == NULL) + { + png_free(png_ptr, new_iccp_name); + png_benign_error(png_ptr, + "Insufficient memory to process iCCP profile"); + return; + } + + memcpy(new_iccp_profile, profile, proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + info_ptr->free_me |= PNG_FREE_ICCP; + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +void PNGAPI +png_set_text(png_structrp png_ptr, png_inforp info_ptr, + png_const_textp text_ptr, int num_text) +{ + int ret; + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + + if (ret != 0) + png_error(png_ptr, "Insufficient memory to store text"); +} + +int /* PRIVATE */ +png_set_text_2(png_structrp png_ptr, png_inforp info_ptr, + png_const_textp text_ptr, int num_text) +{ + int i; + + png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" : + (unsigned long)png_ptr->chunk_name); + + if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL) + return(0); + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. This compare can't overflow + * because max_text >= num_text (anyway, subtract of two positive integers + * can't overflow in any case.) + */ + if (num_text > info_ptr->max_text - info_ptr->num_text) + { + int old_num_text = info_ptr->num_text; + int max_text; + png_textp new_text = NULL; + + /* Calculate an appropriate max_text, checking for overflow. */ + max_text = old_num_text; + if (num_text <= INT_MAX - max_text) + { + max_text += num_text; + + /* Round up to a multiple of 8 */ + if (max_text < INT_MAX-8) + max_text = (max_text + 8) & ~0x7; + + else + max_text = INT_MAX; + + /* Now allocate a new array and copy the old members in, this does all + * the overflow checks. + */ + new_text = png_voidcast(png_textp,png_realloc_array(png_ptr, + info_ptr->text, old_num_text, max_text-old_num_text, + sizeof *new_text)); + } + + if (new_text == NULL) + { + png_chunk_report(png_ptr, "too many text chunks", + PNG_CHUNK_WRITE_ERROR); + + return 1; + } + + png_free(png_ptr, info_ptr->text); + + info_ptr->text = new_text; + info_ptr->free_me |= PNG_FREE_TEXT; + info_ptr->max_text = max_text; + /* num_text is adjusted below as the entries are copied in */ + + png_debug1(3, "allocated %d entries for info_ptr->text", max_text); + } + + for (i = 0; i < num_text; i++) + { + size_t text_length, key_len; + size_t lang_len, lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE || + text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) + { + png_chunk_report(png_ptr, "text compression mode is out of range", + PNG_CHUNK_WRITE_ERROR); + continue; + } + + key_len = strlen(text_ptr[i].key); + + if (text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + + else +# ifdef PNG_iTXt_SUPPORTED + { + /* Set iTXt data */ + + if (text_ptr[i].lang != NULL) + lang_len = strlen(text_ptr[i].lang); + + else + lang_len = 0; + + if (text_ptr[i].lang_key != NULL) + lang_key_len = strlen(text_ptr[i].lang_key); + + else + lang_key_len = 0; + } +# else /* PNG_iTXt_SUPPORTED */ + { + png_chunk_report(png_ptr, "iTXt chunk not supported", + PNG_CHUNK_WRITE_ERROR); + continue; + } +# endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +# ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + + else +# endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + + else + { + text_length = strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr, + key_len + text_length + lang_len + lang_key_len + 4)); + + if (textp->key == NULL) + { + png_chunk_report(png_ptr, "text chunk: out of memory", + PNG_CHUNK_WRITE_ERROR); + return 1; + } + + png_debug2(2, "Allocated %lu bytes at %p in png_set_text", + (unsigned long)(png_uint_32) + (key_len + lang_len + lang_key_len + text_length + 4), + textp->key); + + memcpy(textp->key, text_ptr[i].key, key_len); + *(textp->key + key_len) = '\0'; + + if (text_ptr[i].compression > 0) + { + textp->lang = textp->key + key_len + 1; + memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang + lang_len) = '\0'; + textp->lang_key = textp->lang + lang_len + 1; + memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key + lang_key_len) = '\0'; + textp->text = textp->lang_key + lang_key_len + 1; + } + + else + { + textp->lang=NULL; + textp->lang_key=NULL; + textp->text = textp->key + key_len + 1; + } + + if (text_length != 0) + memcpy(textp->text, text_ptr[i].text, text_length); + + *(textp->text + text_length) = '\0'; + +# ifdef PNG_iTXt_SUPPORTED + if (textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + + else +# endif + { + textp->text_length = text_length; + textp->itxt_length = 0; + } + + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d", info_ptr->num_text); + } + + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +void PNGAPI +png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr, + png_const_timep mod_time) +{ + png_debug1(1, "in %s storage function", "tIME"); + + if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + if (mod_time->month == 0 || mod_time->month > 12 || + mod_time->day == 0 || mod_time->day > 31 || + mod_time->hour > 23 || mod_time->minute > 59 || + mod_time->second > 60) + { + png_warning(png_ptr, "Ignoring invalid time value"); + return; + } + + info_ptr->mod_time = *mod_time; + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +void PNGAPI +png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, + png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color) +{ + png_debug1(1, "in %s storage function", "tRNS"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + png_chunk_report(png_ptr, + "png_set_tRNS: invalid on PNG with alpha channel", PNG_CHUNK_ERROR); + + else if (info_ptr->color_type & PNG_COLOR_MASK_PALETTE) + { + int max_num; + + /* Free the old data; num_trans 0 can be used to kill the tRNS */ + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); + + /* Do this just in case the old data was not owned by libpng: */ + info_ptr->valid &= ~PNG_INFO_tRNS; + info_ptr->trans_alpha = NULL; + info_ptr->num_trans = 0; + + /* Expect png_set_PLTE to happen before png_set_tRNS, so num_palette will + * be set, but this is not a requirement of the API. + */ + if (png_ptr->num_palette) + max_num = png_ptr->num_palette; + + else + max_num = 1 << png_ptr->bit_depth; + + if (num_trans > max_num) + { + png_chunk_report(png_ptr, "png_set_tRNS: num_trans too large", + PNG_CHUNK_ERROR); + /* If control returns simply limit it; the behavior prior to 1.7 was to + * issue a warning and skip the palette in png_write_tRNS. + */ + num_trans = max_num; + } + + /* But only attempt a malloc if there is something to do; so the app can + * set a tRNS array then later delete it. + */ + if (num_trans > 0 && trans_alpha != NULL) + { + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1, + * this avoids issues where a palette image contains out of range + * indices. + */ + info_ptr->trans_alpha = png_voidcast(png_bytep, png_malloc(png_ptr, + PNG_MAX_PALETTE_LENGTH)); + info_ptr->free_me |= PNG_FREE_TRNS; + + memcpy(info_ptr->trans_alpha, trans_alpha, + (unsigned)/*SAFE*/num_trans); + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->num_trans = (png_uint_16)num_trans; /* SAFE */ + } + } + + else /* not a PALETTE image */ + { + /* Invalidate any prior transparent color, set num_trans too, it is not + * used internally in this case but png_get_tRNS still returns it. + */ + info_ptr->valid &= ~PNG_INFO_tRNS; + info_ptr->num_trans = 0; /* for png_get_tRNS */ + + if (trans_color != NULL) + { + int sample_max = (1 << info_ptr->bit_depth); + + if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && + trans_color->gray <= sample_max) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + trans_color->red <= sample_max && + trans_color->green <= sample_max && + trans_color->blue <= sample_max)) + { + info_ptr->trans_color = *trans_color; + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->num_trans = 1; /* for png_get_tRNS */ + } + + else + png_chunk_report(png_ptr, + "tRNS chunk has out-of-range samples for bit_depth", + PNG_CHUNK_ERROR); + } + } +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +void PNGAPI +png_set_sPLT(png_structrp png_ptr, + png_inforp info_ptr, png_const_sPLT_tp entries, int nentries) +/* + * entries - array of png_sPLT_t structures + * to be added to the list of palettes + * in the info structure. + * + * nentries - number of palette structures to be + * added. + */ +{ + png_sPLT_tp np; + + if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL) + return; + + /* Use the internal realloc function, which checks for all the possible + * overflows. Notice that the parameters are (int) and (size_t) + */ + np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr, + info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries, + sizeof *np)); + + if (np == NULL) + { + /* Out of memory or too many chunks */ + png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR); + + return; + } + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = np; + info_ptr->free_me |= PNG_FREE_SPLT; + + np += info_ptr->splt_palettes_num; + + do + { + png_size_t length; + + /* Skip invalid input entries */ + if (entries->name == NULL || entries->entries == NULL) + { + /* png_handle_sPLT doesn't do this, so this is an app error */ + png_app_error(png_ptr, "png_set_sPLT: invalid sPLT"); + /* Just skip the invalid entry */ + continue; + } + + np->depth = entries->depth; + + /* In the even of out-of-memory just return - there's no point keeping on + * trying to add sPLT chunks. + */ + length = strlen(entries->name) + 1; + np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length)); + + if (np->name == NULL) + break; + + memcpy(np->name, entries->name, length); + + /* IMPORTANT: we have memory now that won't get freed if something else + * goes wrong, this code must free it. png_malloc_array produces no + * warnings, use a png_chunk_report (below) if there is an error. + */ + np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr, + entries->nentries, sizeof (png_sPLT_entry))); + + if (np->entries == NULL) + { + png_free(png_ptr, np->name); + break; + } + + np->nentries = entries->nentries; + /* This multiply can't overflow because png_malloc_array has already + * checked it when doing the allocation. + */ + memcpy(np->entries, entries->entries, + entries->nentries * sizeof (png_sPLT_entry)); + + /* Note that 'continue' skips the advance of the out pointer and out + * count, so an invalid entry is not added. + */ + info_ptr->valid |= PNG_INFO_sPLT; + ++(info_ptr->splt_palettes_num); + ++np; + } + while (++entries, --nentries); + + if (nentries > 0) + png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR); +} +#endif /* PNG_sPLT_SUPPORTED */ + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +static png_byte +check_location(png_const_structrp png_ptr, int location) +{ + location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT); + + /* New in 1.6.0; copy the location and check it. This is an API + * change, previously the app had to use the + * png_set_unknown_chunk_location API below for each chunk. + */ + if (location == 0 && !(png_ptr->mode & PNG_IS_READ_STRUCT)) + { + /* Write struct, so unknown chunks come from the app */ + png_app_warning(png_ptr, + "png_set_unknown_chunks now expects a valid location"); + /* Use the old behavior */ + location = (png_byte)(png_ptr->mode & + (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)); + } + + /* This need not be an internal error - if the app calls + * png_set_unknown_chunks on a read pointer it must get the location right. + */ + if (location == 0) + png_error(png_ptr, "invalid location in png_set_unknown_chunks"); + + /* Now reduce the location to the top-most set bit by removing each least + * significant bit in turn. + */ + while (location != (location & -location)) + location &= ~(location & -location); + + /* The cast is safe because 'location' is a bit mask and only the low four + * bits are significant. + */ + return (png_byte)location; +} + +void PNGAPI +png_set_unknown_chunks(png_structrp png_ptr, + png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 || + unknowns == NULL) + return; + + /* Check for the failure cases where support has been disabled at compile + * time. This code is hardly ever compiled - it's here because + * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this + * code) but may be meaningless if the read or write handling of unknown + * chunks is not compiled in. + */ +# if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \ + defined(PNG_READ_SUPPORTED) + if (png_ptr->mode & PNG_IS_READ_STRUCT) + { + png_app_error(png_ptr, "no unknown chunk support on read"); + return; + } +# endif +# if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \ + defined(PNG_WRITE_SUPPORTED) + if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) + { + png_app_error(png_ptr, "no unknown chunk support on write"); + return; + } +# endif + + /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that + * unknown critical chunks could be lost with just a warning resulting in + * undefined behavior. Now png_chunk_report is used to provide behavior + * appropriate to read or write. + */ + np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr, + info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns, + sizeof *np)); + + if (np == NULL) + { + png_chunk_report(png_ptr, "too many unknown chunks", + PNG_CHUNK_WRITE_ERROR); + + return; + } + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = np; /* safe because it is initialized */ + info_ptr->free_me |= PNG_FREE_UNKN; + + np += info_ptr->unknown_chunks_num; + + /* Increment unknown_chunks_num each time round the loop to protect the + * just-allocated chunk data. + */ + for (; num_unknowns > 0; --num_unknowns, ++unknowns) + { + memcpy(np->name, unknowns->name, (sizeof np->name)); + np->name[(sizeof np->name)-1] = '\0'; + np->location = check_location(png_ptr, unknowns->location); + + if (unknowns->size == 0) + { + np->data = NULL; + np->size = 0; + } + + else + { + np->data = png_voidcast(png_bytep, + png_malloc_base(png_ptr, unknowns->size)); + + if (np->data == NULL) + { + png_chunk_report(png_ptr, "unknown chunk: out of memory", + PNG_CHUNK_WRITE_ERROR); + /* But just skip storing the unknown chunk */ + continue; + } + + memcpy(np->data, unknowns->data, unknowns->size); + np->size = unknowns->size; + } + + /* These increments are skipped on out-of-memory for the data - the + * unknown chunk entry gets overwritten if the png_chunk_report returns. + * This is correct in the read case (the chunk is just dropped.) + */ + ++np; + ++(info_ptr->unknown_chunks_num); + } +} + +void PNGAPI +png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr, + int chunk, int location) +{ + /* This API is pretty pointless in 1.6.0 because the location can be set + * before the call to png_set_unknown_chunks. + */ + if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && + chunk < info_ptr->unknown_chunks_num) + { + if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0) + { + png_app_error(png_ptr, "invalid unknown chunk location"); + /* Fake out the pre 1.6.0 behavior: */ + if ((location & PNG_HAVE_IDAT)) /* undocumented! */ + location = PNG_AFTER_IDAT; + + else + location = PNG_HAVE_IHDR; /* also undocumented */ + } + + info_ptr->unknown_chunks[chunk].location = + check_location(png_ptr, location); + } + + /* TODO: make this an error in 1.8 (or maybe it will become one in 1.7!) */ + else if (png_ptr != NULL) + png_app_warning(png_ptr, "unknown chunk index out of range"); +} +#endif + + +#ifdef PNG_MNG_FEATURES_SUPPORTED +png_uint_32 PNGAPI +png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features"); + + if (png_ptr == NULL) + return 0; + + png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES; + + return png_ptr->mng_features_permitted; +} +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +static unsigned int +add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep) +{ + unsigned int i; + + /* Utility function: update the 'keep' state of a chunk if it is already in + * the list, otherwise add it to the list. + */ + for (i=0; i= PNG_HANDLE_CHUNK_LAST) + { + png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep"); + return; + } + + if (num_chunks_in <= 0) + { + png_ptr->unknown_default = keep; + + /* '0' means just set the flags, so stop here */ + if (num_chunks_in == 0) + return; + } + + if (num_chunks_in < 0) + { + /* Ignore all unknown chunks and all chunks recognized by + * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND + */ + static PNG_CONST png_byte chunks_to_ignore[] = { + 98, 75, 71, 68, '\0', /* bKGD */ + 99, 72, 82, 77, '\0', /* cHRM */ + 103, 65, 77, 65, '\0', /* gAMA */ + 104, 73, 83, 84, '\0', /* hIST */ + 105, 67, 67, 80, '\0', /* iCCP */ + 105, 84, 88, 116, '\0', /* iTXt */ + 111, 70, 70, 115, '\0', /* oFFs */ + 112, 67, 65, 76, '\0', /* pCAL */ + 112, 72, 89, 115, '\0', /* pHYs */ + 115, 66, 73, 84, '\0', /* sBIT */ + 115, 67, 65, 76, '\0', /* sCAL */ + 115, 80, 76, 84, '\0', /* sPLT */ + 115, 84, 69, 82, '\0', /* sTER */ + 115, 82, 71, 66, '\0', /* sRGB */ + 116, 69, 88, 116, '\0', /* tEXt */ + 116, 73, 77, 69, '\0', /* tIME */ + 122, 84, 88, 116, '\0' /* zTXt */ + }; + + chunk_list = chunks_to_ignore; + num_chunks = (sizeof chunks_to_ignore)/5; + } + + else /* num_chunks_in > 0 */ + { + if (chunk_list == NULL) + { + /* Prior to 1.6.0 this was silently ignored, now it is an app_error + * which can be switched off. + */ + png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list"); + return; + } + + num_chunks = num_chunks_in; + } + + old_num_chunks = png_ptr->num_chunk_list; + if (png_ptr->chunk_list == NULL) + old_num_chunks = 0; + + /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow. + */ + if (num_chunks + old_num_chunks > UINT_MAX/5) + { + png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks"); + return; + } + + /* If these chunks are being reset to the default then no more memory is + * required because add_one_chunk above doesn't extend the list if the 'keep' + * parameter is the default. + */ + if (keep != 0) + { + new_list = png_voidcast(png_bytep, png_malloc(png_ptr, + 5 * (num_chunks + old_num_chunks))); + + if (old_num_chunks > 0) + memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks); + } + + else if (old_num_chunks > 0) + new_list = png_ptr->chunk_list; + + else + new_list = NULL; + + /* Add the new chunks together with each one's handling code. If the chunk + * already exists the code is updated, otherwise the chunk is added to the + * end. (In libpng 1.6.0 order no longer matters because this code enforces + * the earlier convention that the last setting is the one that is used.) + */ + if (new_list != NULL) + { + png_const_bytep inlist; + png_bytep outlist; + unsigned int i; + + for (i=0; ichunk_list != new_list) + png_free(png_ptr, new_list); + + new_list = NULL; + } + } + + else + num_chunks = 0; + + png_ptr->num_chunk_list = num_chunks; + + if (png_ptr->chunk_list != new_list) + { + if (png_ptr->chunk_list != NULL) + png_free(png_ptr, png_ptr->chunk_list); + + png_ptr->chunk_list = new_list; + } +} +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +void PNGAPI +png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr, + png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + + info_ptr->row_pointers = row_pointers; + + if (row_pointers != NULL) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +void PNGAPI +png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size) +{ + if (png_ptr == NULL) + return; + + if (size == 0 || size > PNG_UINT_31_MAX) + png_error(png_ptr, "invalid compression buffer size"); + +# ifdef PNG_SEQUENTIAL_READ_SUPPORTED + if (png_ptr->mode & PNG_IS_READ_STRUCT) + { + png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */ + return; + } +# endif + +# ifdef PNG_WRITE_SUPPORTED + if (!(png_ptr->mode & PNG_IS_READ_STRUCT)) + { + if (png_ptr->zowner != 0) + { + png_warning(png_ptr, + "Compression buffer size cannot be changed because it is in use"); + return; + } + + if (size > ZLIB_IO_MAX) + { + png_warning(png_ptr, + "Compression buffer size limited to system maximum"); + size = ZLIB_IO_MAX; /* must fit */ + } + + else if (size < 6) + { + /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH + * if this is permitted. + */ + png_warning(png_ptr, + "Compression buffer size cannot be reduced below 6"); + return; + } + + if (png_ptr->zbuffer_size != size) + { + png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); + png_ptr->zbuffer_size = (uInt)size; + } + } +# endif +} + +void PNGAPI +png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~mask; +} + + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* This function was added to libpng 1.2.6 */ +void PNGAPI +png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, + png_uint_32 user_height_max) +{ + /* Images with dimensions larger than these limits will be + * rejected by png_set_IHDR(). To accept any PNG datastream + * regardless of dimensions, set both limits to 0x7ffffffL. + */ + if (png_ptr != NULL) + { + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; + } +} + +/* This function was added to libpng 1.4.0 */ +void PNGAPI +png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max) +{ + if (png_ptr != NULL) + png_ptr->user_chunk_cache_max = user_chunk_cache_max; +} + +/* This function was added to libpng 1.4.1 */ +void PNGAPI +png_set_chunk_malloc_max (png_structrp png_ptr, + png_alloc_size_t user_chunk_malloc_max) +{ + if (png_ptr != NULL) + png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_set_benign_errors(png_structrp png_ptr, int allowed) +{ + png_debug(1, "in png_set_benign_errors"); + + /* If allowed is 1, png_benign_error() is treated as a warning. + * + * If allowed is 0, png_benign_error() is treated as an error (which + * is the default behavior if png_set_benign_errors() is not called). + */ + + if (allowed != 0) + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN | + PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN; + + else + png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN | + PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN); +} +#endif /* PNG_BENIGN_ERRORS_SUPPORTED */ + +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED + /* Whether to report invalid palette index; added at libng-1.5.10. + * It is possible for an indexed (color-type==3) PNG file to contain + * pixels with invalid (out-of-range) indexes if the PLTE chunk has + * fewer entries than the image's bit-depth would allow. We recover + * from this gracefully by filling any incomplete palette with zeroes + * (opaque black). By default, when this occurs libpng will issue + * a benign error. This API can be used to override that behavior. + */ +void PNGAPI +png_set_check_for_invalid_index(png_structrp png_ptr, int allowed) +{ + png_debug(1, "in png_set_check_for_invalid_index"); + + if (allowed > 0) + png_ptr->num_palette_max = 0; + + else + png_ptr->num_palette_max = -1; +} +#endif +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng17/pngstruct.h b/ext/libpng17/pngstruct.h new file mode 100644 index 0000000000..e4341eede6 --- /dev/null +++ b/ext/libpng17/pngstruct.h @@ -0,0 +1,560 @@ + +/* pngstruct.h - header file for PNG reference library + * + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application. + */ + +#ifndef PNGSTRUCT_H +#define PNGSTRUCT_H +/* zlib.h defines the structure z_stream, an instance of which is included + * in this structure and is required for decompressing the LZ compressed + * data in PNG files. + */ +#ifndef ZLIB_CONST + /* We must ensure that zlib uses 'const' in declarations. */ +# define ZLIB_CONST +#endif + +#include PNG_ZLIB_HEADER + +#ifdef const + /* zlib.h sometimes #defines const to nothing, undo this. */ +# undef const +#endif + +/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility + * with older builds. + */ +#if ZLIB_VERNUM < 0x1260 +# define PNGZ_MSG_CAST(s) png_constcast(char*,s) +# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b) +#else +# define PNGZ_MSG_CAST(s) (s) +# define PNGZ_INPUT_CAST(b) (b) +#endif + +/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib + * can handle at once. This type need be no larger than 16 bits (so maximum of + * 65535), this define allows us to discover how big it is, but limited by the + * maximum for size_t. The value can be overridden in a library build (pngusr.h, + * or set it in CPPFLAGS) and it works to set it to a considerably lower value + * (e.g. 255 works). A lower value may help memory usage (slightly) and may + * even improve performance on some systems (and degrade it on others.) + */ +#ifndef ZLIB_IO_MAX +# define ZLIB_IO_MAX ((uInt)-1) +#endif + +#ifdef PNG_WRITE_SUPPORTED +/* The type of a compression buffer list used by the write code. */ +typedef struct png_compression_buffer +{ + struct png_compression_buffer *next; + png_byte output[1]; /* actually zbuf_size */ +} png_compression_buffer, *png_compression_bufferp; + +#define PNG_COMPRESSION_BUFFER_SIZE(pp)\ + (offsetof(png_compression_buffer, output) + (pp)->zbuffer_size) +#endif + +/* Colorspace support; structures used in png_struct, png_info and in internal + * functions to hold and communicate information about the color space. + * + * PNG_COLORSPACE_SUPPORTED is only required if the application will perform + * colorspace corrections, otherwise all the colorspace information can be + * skipped and the size of libpng can be reduced (significantly) by compiling + * out the colorspace support. + */ +#ifdef PNG_COLORSPACE_SUPPORTED +/* The chromaticities of the red, green and blue colorants and the chromaticity + * of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)). + */ +typedef struct png_xy +{ + png_fixed_point redx, redy; + png_fixed_point greenx, greeny; + png_fixed_point bluex, bluey; + png_fixed_point whitex, whitey; +} png_xy; + +/* The same data as above but encoded as CIE XYZ values. When this data comes + * from chromaticities the sum of the Y values is assumed to be 1.0 + */ +typedef struct png_XYZ +{ + png_fixed_point red_X, red_Y, red_Z; + png_fixed_point green_X, green_Y, green_Z; + png_fixed_point blue_X, blue_Y, blue_Z; +} png_XYZ; +#endif /* COLORSPACE */ + +#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) +/* A colorspace is all the above plus, potentially, profile information, + * however at present libpng does not use the profile internally so it is only + * stored in the png_info struct (if iCCP is supported.) The rendering intent + * is retained here and is checked. + * + * The file gamma encoding information is also stored here and gamma correction + * is done by libpng, whereas color correction must currently be done by the + * application. + */ +typedef struct png_colorspace +{ +#ifdef PNG_GAMMA_SUPPORTED + png_fixed_point gamma; /* File gamma */ +#endif + +#ifdef PNG_COLORSPACE_SUPPORTED + png_xy end_points_xy; /* End points as chromaticities */ + png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */ + png_uint_16 rendering_intent; /* Rendering intent of a profile */ +#endif + + /* Flags are always defined to simplify the code. */ + png_uint_16 flags; /* As defined below */ +} png_colorspace, * PNG_RESTRICT png_colorspacerp; + +typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp; + +/* General flags for the 'flags' field */ +#define PNG_COLORSPACE_HAVE_GAMMA 0x0001 +#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002 +#define PNG_COLORSPACE_HAVE_INTENT 0x0004 +#define PNG_COLORSPACE_FROM_gAMA 0x0008 +#define PNG_COLORSPACE_FROM_cHRM 0x0010 +#define PNG_COLORSPACE_FROM_sRGB 0x0020 +#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040 +#define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */ +#define PNG_COLORSPACE_RGB_TO_GRAY_SET 0x0100 /* user specified coeffs */ +#define PNG_COLORSPACE_INVALID 0x8000 +#define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags)) +#endif /* COLORSPACE || GAMMA */ + +struct png_struct_def +{ + /* Rearranged in libpng 1.7 to attempt to lessen padding; in general + * (char), (short), (int) and pointer types are kept separate, however + * associated members under the control of the same #define are still + * together. + */ +#ifdef PNG_SETJMP_SUPPORTED + /* jmp_buf can have very high alignment requirements on some systems, so put + * it first (the other setjmp members are later as they are infrequently + * accesed.) + */ + jmp_buf jmp_buf_local; +#endif + + /* Next the frequently accessed fields. Many processors perform arithmetic + * in the address pipeline, but frequently the amount of addition or + * subtraction is limited. By putting these fields at the head of png_struct + * the hope is that such processors will generate code that is both smaller + * and faster. + */ + png_colorp palette; /* palette from the input file */ + size_t rowbytes; /* size of row in bytes */ + size_t info_rowbytes; /* cache of updated row bytes */ + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ + png_uint_32 crc; /* current chunk CRC value */ + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations;/* which transformations to perform */ + png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */ + png_uint_32 free_me; /* items libpng is responsible for freeing */ + + int maximum_pixel_depth; /* pixel depth used for the row buffers */ +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED + int num_palette_max; /* maximum palette index found in IDAT */ +#endif + + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + + /* Single byte values, typically used either to save space or to hold 1-byte + * values from the PNG chunk specifications. + */ + png_byte compression_type; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + png_byte transformed_pixel_depth; + /* pixel depth after read/write transforms */ + + /* ERROR HANDLING */ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */ + png_longjmp_ptr longjmp_fn; /* setjmp non-local goto function. */ + size_t jmp_buf_size; /* size of *jmp_buf_ptr, if allocated */ +#endif + + /* Error/warning callbacks */ + png_error_ptr error_fn; /* print an error message and abort */ +#ifdef PNG_WARNINGS_SUPPORTED + png_error_ptr warning_fn; /* print a warning and continue */ +#endif + png_voidp error_ptr; /* user supplied data for the above */ + + /* MEMORY ALLOCATION */ +#ifdef PNG_USER_MEM_SUPPORTED + png_malloc_ptr malloc_fn; /* allocate memory */ + png_free_ptr free_fn; /* free memory */ + png_voidp mem_ptr; /* user supplied data for the above */ +#endif + + /* IO and BASIC READ/WRITE SUPPORT */ + png_voidp io_ptr; /* user supplied data for IO callbacks */ + +#ifdef PNG_READ_SUPPORTED + png_rw_ptr read_data_fn; /* read some bytes (must succeed) */ + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_bytep read_buffer; /* buffer for reading chunk data */ + + /* During read the following array is set up to point to the appropriate + * un-filter function, this allows per-image and per-processor optimization. + */ + void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row); + +#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) + /* The png_struct colorspace structure is only required on read - on write it + * is in (just) the info_struct. + */ + png_colorspace colorspace; +#endif +#endif /* PNG_READ_SUPPORTED */ + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; /* Maximum width on read */ + png_uint_32 user_height_max; /* Maximum height on read */ + /* Total memory that a single zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. This field is a counter + * - it is decremented as memory is allocated. + */ + png_alloc_size_t user_chunk_malloc_max; +#endif +#ifdef PNG_USER_LIMITS_SUPPORTED + /* limit on total *number* of sPLT, text and unknown chunks that can be + * stored. 0 means unlimited. This field is a counter - it is decremented + * as chunks are encountered. + */ + png_uint_32 user_chunk_cache_max; +#endif + + /* The progressive reader gets passed data and calls application handling + * functions when appropriate. + */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after a row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + + /* Progressive read control data */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + + size_t save_buffer_size; /* amount of data now in save_buffer */ + size_t save_buffer_max; /* total size of save_buffer */ + size_t buffer_size; /* total amount of available input data */ + size_t current_buffer_size; /* amount of data now in current_buffer */ + + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ +#endif + +#ifdef PNG_WRITE_SUPPORTED + png_rw_ptr write_data_fn;/* write some bytes (must succeed) */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn; /* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ +#endif + +#ifdef PNG_WRITE_SUPPORTED + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte usr_channels; /* channels at start of write */ +#endif + +#ifdef PNG_IO_STATE_SUPPORTED + png_uint_32 io_state; /* tells the app read/write progress */ +#endif + + /* ROW BUFFERS + * + * Members that hold pointers to the decompressed image rows. + */ + png_bytep row_buf; /* buffer for the current (unfiltered) row */ +#if defined(PNG_WRITE_FILTER_SUPPORTED) || defined(PNG_READ_SUPPORTED) + png_bytep prev_row; /* buffer to save the previous (unfiltered) row */ +#endif + +#ifdef PNG_READ_SUPPORTED + /* The row_buf and prev_row pointers are misaligned so that the start of the + * row - after the filter byte - is aligned, the 'big_' pointers record the + * original allocated pointer. + */ + png_bytep big_row_buf; + png_bytep big_prev_row; + size_t big_row_buf_size; /* Actual size of both */ +#endif + +#ifdef PNG_WRITE_SUPPORTED + /* This is somewhat excessive, there is no obvious reason on write to + * allocate a buffer for each possible filtered row, only for the one being + * tested and the current best. + * + * TODO: fix this + */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ +#endif + + /* UNKNOWN CHUNK HANDLING */ + /* TODO: this is excessively complicated, there are multiple ways of doing + * the same thing. It should be cleaned up, possibly by finding out which + * APIs applications really use. + */ +#ifdef PNG_USER_CHUNKS_SUPPORTED + /* General purpose pointer for all user/unknown chunk handling; points to + * application supplied data for use in the read_user_chunk_fn callback + * (currently there is no write side support - the write side must use the + * set_unknown_chunks interface.) + */ + png_voidp user_chunk_ptr; +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + /* This is called back from the unknown chunk handling */ + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + /* Temporary storage for unknown chunk that the library doesn't recognize, + * used while reading the chunk. + */ + png_unknown_chunk unknown_chunk; +#endif + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name + * followed by a PNG_HANDLE_* byte */ + int unknown_default; /* As PNG_HANDLE_* */ + unsigned int num_chunk_list; /* Number of entries in the list */ +#endif + + /* USER TRANSFORM SUPPORT */ +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + png_voidp user_transform_ptr; /* user supplied data for the above */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif + + /* READ TRANSFORM SUPPORT + * + * Quite a lot of things can be done to the original image data on read, and + * most of these are configurable. The data required by the configurable + * read transforms should be stored here. The png_color_16 and png_color_8 + * structures have low alignment requirements and odd sizes, so may cause + * misalignment when present. Member alignment is as follows: + * + * png_color_16 png_uint_16 + * png_color_8 png_byte + */ + /* GAMMA/BACKGROUND/ALPHA-MODE/RGB-TO-GRAY/tRNS/sBIT + * + * These things are all interrelated because they need some or all of the + * gamma tables. Some attempt has been made below to order these members by + * size, so that as little padding as possible is required. + */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_uint_16p gamma_16_table; /* gamma table for 16-bit depth files */ + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) ||\ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_uint_16p gamma_to_1; /* converts from file to 1.0 */ + png_uint_16p gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16p gamma_16_to_1; /* converts from file to 1.0 */ +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ +#endif /* PNG_READ_GAMMA_SUPPORTED */ + +#if defined(PNG_READ_tRNS_SUPPORTED) || \ + defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) + png_bytep trans_alpha; /* alpha values for paletted files */ +#endif + + /* Integer values */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + png_fixed_point background_gamma; +#endif +#ifdef PNG_READ_GAMMA_SUPPORTED + png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ + int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ +#endif + + /* png_color_16 */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + png_color_16 background; /* background color in screen gamma space */ + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) || \ + defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) + png_color_16 trans_color; /* transparent color for non-paletted files */ +#endif + + /* png_uint_16 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + /* The blue coefficient is calculated from the above */ +#endif + + /* png_color_8 */ +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + + /* png_byte */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + png_byte background_gamma_type; +#endif +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status; +#endif + + /* SHIFT - both READ_SHIFT and WRITE_SHIFT */ +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* shift for significant bit tranformation */ +#endif + + /* FILLER SUPPORT (pixel expansion or read, contraction on write) */ +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif + + /* QUANTIZE (convert to color-mapped) */ +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_bytep palette_lookup; /* lookup table for quantizing */ + png_bytep quantize_index; /* index translation for palette files */ + png_bytep quantize_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is in the + * palette + */ + png_bytep palette_to_index; /* which original index points to this palette + * color + */ +#endif + + /* MNG SUPPORT */ +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_uint_32 mng_features_permitted; + png_byte filter_type; +#endif + + /* Options */ +#ifdef PNG_SET_OPTION_SUPPORTED + png_byte options; /* On/off state (up to 4 options) */ +#endif + + /* COMPRESSION AND DECOMPRESSION SUPPORT. + * + * zlib expects a 'zstream' as the fundamental control structure, it allows + * all the parameters to be passed as one pointer. + */ + z_stream zstream; /* decompression structure */ + +#ifdef PNG_READ_SUPPORTED + /* These, and IDAT_read_size below, control how much input and output (at + * most) is available to zlib. + */ + png_uint_32 idat_size; /* current IDAT size for read */ + png_alloc_size_t read_buffer_size; /* current size of the buffer */ +#endif + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + int zlib_text_level; /* holds zlib compression level */ + int zlib_text_method; /* holds zlib compression method */ + int zlib_text_window_bits; /* holds zlib compression window bits */ + int zlib_text_mem_level; /* holds zlib compression memory level */ + int zlib_text_strategy; /* holds zlib compression strategy */ +#endif + +#ifdef PNG_WRITE_SUPPORTED + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ + + int zlib_set_level; /* Actual values set into the zstream on write */ + int zlib_set_method; + int zlib_set_window_bits; + int zlib_set_mem_level; + int zlib_set_strategy; + + png_compression_bufferp zbuffer_list; /* Created on demand during write */ + uInt zbuffer_size; /* size of the actual zlib buffer */ +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED + uInt IDAT_read_size; /* limit on read buffer size for IDAT */ +#endif +}; +#endif /* PNGSTRUCT_H */ diff --git a/ext/libpng16/pngtest.c b/ext/libpng17/pngtest.c similarity index 94% rename from ext/libpng16/pngtest.c rename to ext/libpng17/pngtest.c index f97907ee59..75feb8e1b2 100644 --- a/ext/libpng16/pngtest.c +++ b/ext/libpng17/pngtest.c @@ -1,1973 +1,1994 @@ - -/* pngtest.c - a simple test program to test libpng - * - * Last changed in libpng 1.6.2 [April 25, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - * This program reads in a PNG image, writes it out again, and then - * compares the two files. If the files are identical, this shows that - * the basic chunk handling, filtering, and (de)compression code is working - * properly. It does not currently test all of the transforms, although - * it probably should. - * - * The program will report "FAIL" in certain legitimate cases: - * 1) when the compression level or filter selection method is changed. - * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. - * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks - * exist in the input file. - * 4) others not listed here... - * In these cases, it is best to check with another tool such as "pngcheck" - * to see what the differences between the two files are. - * - * If a filename is given on the command-line, then this file is used - * for the input, rather than the default "pngtest.png". This allows - * testing a wide variety of files easily. You can also test a number - * of files at once by typing "pngtest -m file1.png file2.png ..." - */ - -#define _POSIX_SOURCE 1 - -#include -#include -#include - -/* Defined so I can write to a file on gui/windowing platforms */ -/* #define STDERR stderr */ -#define STDERR stdout /* For DOS */ - -#include "png.h" - -/* Known chunks that exist in pngtest.png must be supported or pngtest will fail - * simply as a result of re-ordering them. This may be fixed in 1.7 - */ -#if defined PNG_READ_SUPPORTED && /* else nothing can be done */\ - defined PNG_READ_bKGD_SUPPORTED &&\ - defined PNG_READ_cHRM_SUPPORTED &&\ - defined PNG_READ_gAMA_SUPPORTED &&\ - defined PNG_READ_oFFs_SUPPORTED &&\ - defined PNG_READ_pCAL_SUPPORTED &&\ - defined PNG_READ_pHYs_SUPPORTED &&\ - defined PNG_READ_sBIT_SUPPORTED &&\ - defined PNG_READ_sCAL_SUPPORTED &&\ - defined PNG_READ_sRGB_SUPPORTED &&\ - defined PNG_READ_tEXt_SUPPORTED &&\ - defined PNG_READ_tIME_SUPPORTED &&\ - defined PNG_READ_zTXt_SUPPORTED - -#include "zlib.h" -/* Copied from pngpriv.h but only used in error messages below. */ -#ifndef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 8192 -#endif -#define FCLOSE(file) fclose(file) - -#ifndef PNG_STDIO_SUPPORTED -typedef FILE * png_FILE_p; -#endif - -/* Makes pngtest verbose so we can find problems. */ -#ifndef PNG_DEBUG -# define PNG_DEBUG 0 -#endif - -#if PNG_DEBUG > 1 -# define pngtest_debug(m) ((void)fprintf(stderr, m "\n")) -# define pngtest_debug1(m,p1) ((void)fprintf(stderr, m "\n", p1)) -# define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2)) -#else -# define pngtest_debug(m) ((void)0) -# define pngtest_debug1(m,p1) ((void)0) -# define pngtest_debug2(m,p1,p2) ((void)0) -#endif - -#if !PNG_DEBUG -# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ -#endif - -/* Turn on CPU timing -#define PNGTEST_TIMING -*/ - -#ifndef PNG_FLOATING_POINT_SUPPORTED -#undef PNGTEST_TIMING -#endif - -#ifdef PNGTEST_TIMING -static float t_start, t_stop, t_decode, t_encode, t_misc; -#include -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED -#define PNG_tIME_STRING_LENGTH 29 -static int tIME_chunk_present = 0; -static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; -#endif - -static int verbose = 0; -static int strict = 0; -static int relaxed = 0; -static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */ -static int error_count = 0; /* count calls to png_error */ -static int warning_count = 0; /* count calls to png_warning */ - -#ifdef __TURBOC__ -#include -#endif - -/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ -#ifndef png_jmpbuf -# define png_jmpbuf(png_ptr) png_ptr->jmpbuf -#endif - -/* Defines for unknown chunk handling if required. */ -#ifndef PNG_HANDLE_CHUNK_ALWAYS -# define PNG_HANDLE_CHUNK_ALWAYS 3 -#endif -#ifndef PNG_HANDLE_CHUNK_IF_SAFE -# define PNG_HANDLE_CHUNK_IF_SAFE 2 -#endif - -/* Utility to save typing/errors, the argument must be a name */ -#define MEMZERO(var) ((void)memset(&var, 0, sizeof var)) - -/* Example of using row callbacks to make a simple progress meter */ -static int status_pass = 1; -static int status_dots_requested = 0; -static int status_dots = 1; - -static void PNGCBAPI -read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) -{ - if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) - return; - - if (status_pass != pass) - { - fprintf(stdout, "\n Pass %d: ", pass); - status_pass = pass; - status_dots = 31; - } - - status_dots--; - - if (status_dots == 0) - { - fprintf(stdout, "\n "); - status_dots=30; - } - - fprintf(stdout, "r"); -} - -#ifdef PNG_WRITE_SUPPORTED -static void PNGCBAPI -write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) -{ - if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) - return; - - fprintf(stdout, "w"); -} -#endif - - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -/* Example of using user transform callback (we don't transform anything, - * but merely examine the row filters. We set this to 256 rather than - * 5 in case illegal filter values are present.) - */ -static png_uint_32 filters_used[256]; -static void PNGCBAPI -count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) -{ - if (png_ptr != NULL && row_info != NULL) - ++filters_used[*(data - 1)]; -} -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -/* Example of using user transform callback (we don't transform anything, - * but merely count the zero samples) - */ - -static png_uint_32 zero_samples; - -static void PNGCBAPI -count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) -{ - png_bytep dp = data; - if (png_ptr == NULL) - return; - - /* Contents of row_info: - * png_uint_32 width width of row - * png_uint_32 rowbytes number of bytes in row - * png_byte color_type color type of pixels - * png_byte bit_depth bit depth of samples - * png_byte channels number of channels (1-4) - * png_byte pixel_depth bits per pixel (depth*channels) - */ - - /* Counts the number of zero samples (or zero pixels if color_type is 3 */ - - if (row_info->color_type == 0 || row_info->color_type == 3) - { - int pos = 0; - png_uint_32 n, nstop; - - for (n = 0, nstop=row_info->width; nbit_depth == 1) - { - if (((*dp << pos++ ) & 0x80) == 0) - zero_samples++; - - if (pos == 8) - { - pos = 0; - dp++; - } - } - - if (row_info->bit_depth == 2) - { - if (((*dp << (pos+=2)) & 0xc0) == 0) - zero_samples++; - - if (pos == 8) - { - pos = 0; - dp++; - } - } - - if (row_info->bit_depth == 4) - { - if (((*dp << (pos+=4)) & 0xf0) == 0) - zero_samples++; - - if (pos == 8) - { - pos = 0; - dp++; - } - } - - if (row_info->bit_depth == 8) - if (*dp++ == 0) - zero_samples++; - - if (row_info->bit_depth == 16) - { - if ((*dp | *(dp+1)) == 0) - zero_samples++; - dp+=2; - } - } - } - else /* Other color types */ - { - png_uint_32 n, nstop; - int channel; - int color_channels = row_info->channels; - if (row_info->color_type > 3)color_channels--; - - for (n = 0, nstop=row_info->width; nbit_depth == 8) - if (*dp++ == 0) - zero_samples++; - - if (row_info->bit_depth == 16) - { - if ((*dp | *(dp+1)) == 0) - zero_samples++; - - dp+=2; - } - } - if (row_info->color_type > 3) - { - dp++; - if (row_info->bit_depth == 16) - dp++; - } - } - } -} -#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ - -#ifndef PNG_STDIO_SUPPORTED -/* START of code to validate stdio-free compilation */ -/* These copies of the default read/write functions come from pngrio.c and - * pngwio.c. They allow "don't include stdio" testing of the library. - * This is the function that does the actual reading of data. If you are - * not reading from a standard C stream, you should create a replacement - * read_data function and use it at run time with png_set_read_fn(), rather - * than changing the library. - */ - -#ifdef PNG_IO_STATE_SUPPORTED -void -pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, - png_uint_32 io_op); -void -pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, - png_uint_32 io_op) -{ - png_uint_32 io_state = png_get_io_state(png_ptr); - int err = 0; - - /* Check if the current operation (reading / writing) is as expected. */ - if ((io_state & PNG_IO_MASK_OP) != io_op) - png_error(png_ptr, "Incorrect operation in I/O state"); - - /* Check if the buffer size specific to the current location - * (file signature / header / data / crc) is as expected. - */ - switch (io_state & PNG_IO_MASK_LOC) - { - case PNG_IO_SIGNATURE: - if (data_length > 8) - err = 1; - break; - case PNG_IO_CHUNK_HDR: - if (data_length != 8) - err = 1; - break; - case PNG_IO_CHUNK_DATA: - break; /* no restrictions here */ - case PNG_IO_CHUNK_CRC: - if (data_length != 4) - err = 1; - break; - default: - err = 1; /* uninitialized */ - } - if (err) - png_error(png_ptr, "Bad I/O state or buffer size"); -} -#endif - -static void PNGCBAPI -pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check = 0; - png_voidp io_ptr; - - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ - io_ptr = png_get_io_ptr(png_ptr); - if (io_ptr != NULL) - { - check = fread(data, 1, length, (png_FILE_p)io_ptr); - } - - if (check != length) - { - png_error(png_ptr, "Read Error"); - } - -#ifdef PNG_IO_STATE_SUPPORTED - pngtest_check_io_state(png_ptr, length, PNG_IO_READING); -#endif -} - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -static void PNGCBAPI -pngtest_flush(png_structp png_ptr) -{ - /* Do nothing; fflush() is said to be just a waste of energy. */ - PNG_UNUSED(png_ptr) /* Stifle compiler warning */ -} -#endif - -/* This is the function that does the actual writing of data. If you are - * not writing to a standard C stream, you should create a replacement - * write_data function and use it at run time with png_set_write_fn(), rather - * than changing the library. - */ -static void PNGCBAPI -pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); - - if (check != length) - { - png_error(png_ptr, "Write Error"); - } - -#ifdef PNG_IO_STATE_SUPPORTED - pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); -#endif -} -#endif /* !PNG_STDIO_SUPPORTED */ - -/* This function is called when there is a warning, but the library thinks - * it can continue anyway. Replacement functions don't have to do anything - * here if you don't want to. In the default configuration, png_ptr is - * not used, but it is passed in case it may be useful. - */ -typedef struct -{ - PNG_CONST char *file_name; -} pngtest_error_parameters; - -static void PNGCBAPI -pngtest_warning(png_structp png_ptr, png_const_charp message) -{ - PNG_CONST char *name = "UNKNOWN (ERROR!)"; - pngtest_error_parameters *test = - (pngtest_error_parameters*)png_get_error_ptr(png_ptr); - - ++warning_count; - - if (test != NULL && test->file_name != NULL) - name = test->file_name; - - fprintf(STDERR, "%s: libpng warning: %s\n", name, message); -} - -/* This is the default error handling function. Note that replacements for - * this function MUST NOT RETURN, or the program will likely crash. This - * function is used by default, or if the program supplies NULL for the - * error function pointer in png_set_error_fn(). - */ -static void PNGCBAPI -pngtest_error(png_structp png_ptr, png_const_charp message) -{ - ++error_count; - - pngtest_warning(png_ptr, message); - /* We can return because png_error calls the default handler, which is - * actually OK in this case. - */ -} - -/* END of code to validate stdio-free compilation */ - -/* START of code to validate memory allocation and deallocation */ -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - -/* Allocate memory. For reasonable files, size should never exceed - * 64K. However, zlib may allocate more then 64K if you don't tell - * it not to. See zconf.h and png.h for more information. zlib does - * need to allocate exactly 64K, so whatever you call here must - * have the ability to do that. - * - * This piece of code can be compiled to validate max 64K allocations - * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. - */ -typedef struct memory_information -{ - png_alloc_size_t size; - png_voidp pointer; - struct memory_information *next; -} memory_information; -typedef memory_information *memory_infop; - -static memory_infop pinformation = NULL; -static int current_allocation = 0; -static int maximum_allocation = 0; -static int total_allocation = 0; -static int num_allocations = 0; - -png_voidp PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr, - png_alloc_size_t size)); -void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); - -png_voidp -PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) -{ - - /* png_malloc has already tested for NULL; png_create_struct calls - * png_debug_malloc directly, with png_ptr == NULL which is OK - */ - - if (size == 0) - return (NULL); - - /* This calls the library allocator twice, once to get the requested - buffer and once to get a new free list entry. */ - { - /* Disable malloc_fn and free_fn */ - memory_infop pinfo; - png_set_mem_fn(png_ptr, NULL, NULL, NULL); - pinfo = (memory_infop)png_malloc(png_ptr, - (sizeof *pinfo)); - pinfo->size = size; - current_allocation += size; - total_allocation += size; - num_allocations ++; - - if (current_allocation > maximum_allocation) - maximum_allocation = current_allocation; - - pinfo->pointer = png_malloc(png_ptr, size); - /* Restore malloc_fn and free_fn */ - - png_set_mem_fn(png_ptr, - NULL, png_debug_malloc, png_debug_free); - - if (size != 0 && pinfo->pointer == NULL) - { - current_allocation -= size; - total_allocation -= size; - png_error(png_ptr, - "out of memory in pngtest->png_debug_malloc"); - } - - pinfo->next = pinformation; - pinformation = pinfo; - /* Make sure the caller isn't assuming zeroed memory. */ - memset(pinfo->pointer, 0xdd, pinfo->size); - - if (verbose) - printf("png_malloc %lu bytes at %p\n", (unsigned long)size, - pinfo->pointer); - - return (png_voidp)(pinfo->pointer); - } -} - -/* Free a pointer. It is removed from the list at the same time. */ -void PNGCBAPI -png_debug_free(png_structp png_ptr, png_voidp ptr) -{ - if (png_ptr == NULL) - fprintf(STDERR, "NULL pointer to png_debug_free.\n"); - - if (ptr == 0) - { -#if 0 /* This happens all the time. */ - fprintf(STDERR, "WARNING: freeing NULL pointer\n"); -#endif - return; - } - - /* Unlink the element from the list. */ - { - memory_infop *ppinfo = &pinformation; - - for (;;) - { - memory_infop pinfo = *ppinfo; - - if (pinfo->pointer == ptr) - { - *ppinfo = pinfo->next; - current_allocation -= pinfo->size; - if (current_allocation < 0) - fprintf(STDERR, "Duplicate free of memory\n"); - /* We must free the list element too, but first kill - the memory that is to be freed. */ - memset(ptr, 0x55, pinfo->size); - png_free_default(png_ptr, pinfo); - pinfo = NULL; - break; - } - - if (pinfo->next == NULL) - { - fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); - break; - } - - ppinfo = &pinfo->next; - } - } - - /* Finally free the data. */ - if (verbose) - printf("Freeing %p\n", ptr); - - png_free_default(png_ptr, ptr); - ptr = NULL; -} -#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ -/* END of code to test memory allocation/deallocation */ - - -#ifdef PNG_READ_USER_CHUNKS_SUPPORTED -/* Demonstration of user chunk support of the sTER and vpAg chunks */ - -/* (sTER is a public chunk not yet known by libpng. vpAg is a private -chunk used in ImageMagick to store "virtual page" size). */ - -static struct user_chunk_data -{ - png_const_infop info_ptr; - png_uint_32 vpAg_width, vpAg_height; - png_byte vpAg_units; - png_byte sTER_mode; - int location[2]; -} -user_chunk_data; - -/* Used for location and order; zero means nothing. */ -#define have_sTER 0x01 -#define have_vpAg 0x02 -#define before_PLTE 0x10 -#define before_IDAT 0x20 -#define after_IDAT 0x40 - -static void -init_callback_info(png_const_infop info_ptr) -{ - MEMZERO(user_chunk_data); - user_chunk_data.info_ptr = info_ptr; -} - -static int -set_location(png_structp png_ptr, struct user_chunk_data *data, int what) -{ - int location; - - if ((data->location[0] & what) || (data->location[1] & what)) - return 0; /* already have one of these */ - - /* Find where we are (the code below zeros info_ptr to indicate that the - * chunks before the first IDAT have been read.) - */ - if (data->info_ptr == NULL) /* after IDAT */ - location = what | after_IDAT; - - else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE)) - location = what | before_IDAT; - - else - location = what | before_PLTE; - - if (data->location[0] == 0) - data->location[0] = location; - - else - data->location[1] = location; - - return 1; /* handled */ -} - -static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr, - png_unknown_chunkp chunk) -{ - struct user_chunk_data *my_user_chunk_data = - (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr); - - if (my_user_chunk_data == NULL) - png_error(png_ptr, "lost user chunk pointer"); - - /* Return one of the following: - * return (-n); chunk had an error - * return (0); did not recognize - * return (n); success - * - * The unknown chunk structure contains the chunk data: - * png_byte name[5]; - * png_byte *data; - * png_size_t size; - * - * Note that libpng has already taken care of the CRC handling. - */ - - if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ - chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ - { - /* Found sTER chunk */ - if (chunk->size != 1) - return (-1); /* Error return */ - - if (chunk->data[0] != 0 && chunk->data[0] != 1) - return (-1); /* Invalid mode */ - - if (set_location(png_ptr, my_user_chunk_data, have_sTER)) - { - my_user_chunk_data->sTER_mode=chunk->data[0]; - return (1); - } - - else - return (0); /* duplicate sTER - give it to libpng */ - } - - if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ - chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ - return (0); /* Did not recognize */ - - /* Found ImageMagick vpAg chunk */ - - if (chunk->size != 9) - return (-1); /* Error return */ - - if (!set_location(png_ptr, my_user_chunk_data, have_vpAg)) - return (0); /* duplicate vpAg */ - - my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data); - my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4); - my_user_chunk_data->vpAg_units = chunk->data[8]; - - return (1); -} - -#ifdef PNG_WRITE_SUPPORTED -static void -write_sTER_chunk(png_structp write_ptr) -{ - png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}; - - if (verbose) - fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode); - - png_write_chunk(write_ptr, png_sTER, &user_chunk_data.sTER_mode, 1); -} - -static void -write_vpAg_chunk(png_structp write_ptr) -{ - png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; - - png_byte vpag_chunk_data[9]; - - if (verbose) - fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n", - (unsigned long)user_chunk_data.vpAg_width, - (unsigned long)user_chunk_data.vpAg_height, - user_chunk_data.vpAg_units); - - png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width); - png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height); - vpag_chunk_data[8] = user_chunk_data.vpAg_units; - png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9); -} - -static void -write_chunks(png_structp write_ptr, int location) -{ - int i; - - /* Notice that this preserves the original chunk order, however chunks - * intercepted by the callback will be written *after* chunks passed to - * libpng. This will actually reverse a pair of sTER chunks or a pair of - * vpAg chunks, resulting in an error later. This is not worth worrying - * about - the chunks should not be duplicated! - */ - for (i=0; i<2; ++i) - { - if (user_chunk_data.location[i] == (location | have_sTER)) - write_sTER_chunk(write_ptr); - - else if (user_chunk_data.location[i] == (location | have_vpAg)) - write_vpAg_chunk(write_ptr); - } -} -#endif /* PNG_WRITE_SUPPORTED */ -#else /* !PNG_READ_USER_CHUNKS_SUPPORTED */ -# define write_chunks(pp,loc) ((void)0) -#endif -/* END of code to demonstrate user chunk support */ - -/* START of code to check that libpng has the required text support; this only - * checks for the write support because if read support is missing the chunk - * will simply not be reported back to pngtest. - */ -#ifdef PNG_TEXT_SUPPORTED -static void -pngtest_check_text_support(png_const_structp png_ptr, png_textp text_ptr, - int num_text) -{ - while (num_text > 0) - { - switch (text_ptr[--num_text].compression) - { - case PNG_TEXT_COMPRESSION_NONE: - break; - - case PNG_TEXT_COMPRESSION_zTXt: -# ifndef PNG_WRITE_zTXt_SUPPORTED - ++unsupported_chunks; -# endif - break; - - case PNG_ITXT_COMPRESSION_NONE: - case PNG_ITXT_COMPRESSION_zTXt: -# ifndef PNG_WRITE_iTXt_SUPPORTED - ++unsupported_chunks; -# endif - break; - - default: - /* This is an error */ - png_error(png_ptr, "invalid text chunk compression field"); - break; - } - } -} -#endif -/* END of code to check that libpng has the required text support */ - -/* Test one file */ -static int -test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) -{ - static png_FILE_p fpin; - static png_FILE_p fpout; /* "static" prevents setjmp corruption */ - pngtest_error_parameters error_parameters; - png_structp read_ptr; - png_infop read_info_ptr, end_info_ptr; -#ifdef PNG_WRITE_SUPPORTED - png_structp write_ptr; - png_infop write_info_ptr; - png_infop write_end_info_ptr; -#else - png_structp write_ptr = NULL; - png_infop write_info_ptr = NULL; - png_infop write_end_info_ptr = NULL; -#endif - png_bytep row_buf; - png_uint_32 y; - png_uint_32 width, height; - int num_pass, pass; - int bit_depth, color_type; - - row_buf = NULL; - error_parameters.file_name = inname; - - if ((fpin = fopen(inname, "rb")) == NULL) - { - fprintf(STDERR, "Could not find input file %s\n", inname); - return (1); - } - - if ((fpout = fopen(outname, "wb")) == NULL) - { - fprintf(STDERR, "Could not open output file %s\n", outname); - FCLOSE(fpin); - return (1); - } - - pngtest_debug("Allocating read and write structures"); -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - read_ptr = - png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, - NULL, NULL, NULL, png_debug_malloc, png_debug_free); -#else - read_ptr = - png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); -#endif - png_set_error_fn(read_ptr, &error_parameters, pngtest_error, - pngtest_warning); - -#ifdef PNG_WRITE_SUPPORTED -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - write_ptr = - png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, - NULL, NULL, NULL, png_debug_malloc, png_debug_free); -#else - write_ptr = - png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); -#endif - png_set_error_fn(write_ptr, &error_parameters, pngtest_error, - pngtest_warning); -#endif - pngtest_debug("Allocating read_info, write_info and end_info structures"); - read_info_ptr = png_create_info_struct(read_ptr); - end_info_ptr = png_create_info_struct(read_ptr); -#ifdef PNG_WRITE_SUPPORTED - write_info_ptr = png_create_info_struct(write_ptr); - write_end_info_ptr = png_create_info_struct(write_ptr); -#endif - -#ifdef PNG_READ_USER_CHUNKS_SUPPORTED - init_callback_info(read_info_ptr); - png_set_read_user_chunk_fn(read_ptr, &user_chunk_data, - read_user_chunk_callback); -#endif - -#ifdef PNG_SETJMP_SUPPORTED - pngtest_debug("Setting jmpbuf for read struct"); - if (setjmp(png_jmpbuf(read_ptr))) - { - fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); - png_free(read_ptr, row_buf); - row_buf = NULL; - png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); -#ifdef PNG_WRITE_SUPPORTED - png_destroy_info_struct(write_ptr, &write_end_info_ptr); - png_destroy_write_struct(&write_ptr, &write_info_ptr); -#endif - FCLOSE(fpin); - FCLOSE(fpout); - return (1); - } - -#ifdef PNG_WRITE_SUPPORTED - pngtest_debug("Setting jmpbuf for write struct"); - - if (setjmp(png_jmpbuf(write_ptr))) - { - fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); - png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); - png_destroy_info_struct(write_ptr, &write_end_info_ptr); -#ifdef PNG_WRITE_SUPPORTED - png_destroy_write_struct(&write_ptr, &write_info_ptr); -#endif - FCLOSE(fpin); - FCLOSE(fpout); - return (1); - } -#endif -#endif - - if (strict) - { - /* Treat png_benign_error() as errors on read */ - png_set_benign_errors(read_ptr, 0); - -#ifdef PNG_WRITE_SUPPORTED - /* Treat them as errors on write */ - png_set_benign_errors(write_ptr, 0); -#endif - - /* if strict is not set, then app warnings and errors are treated as - * warnings in release builds, but not in unstable builds; this can be - * changed with '--relaxed'. - */ - } - - else if (relaxed) - { - /* Allow application (pngtest) errors and warnings to pass */ - png_set_benign_errors(read_ptr, 1); - -#ifdef PNG_WRITE_SUPPORTED - png_set_benign_errors(write_ptr, 1); -#endif - } - - pngtest_debug("Initializing input and output streams"); -#ifdef PNG_STDIO_SUPPORTED - png_init_io(read_ptr, fpin); -# ifdef PNG_WRITE_SUPPORTED - png_init_io(write_ptr, fpout); -# endif -#else - png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); -# ifdef PNG_WRITE_SUPPORTED - png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, -# ifdef PNG_WRITE_FLUSH_SUPPORTED - pngtest_flush); -# else - NULL); -# endif -# endif -#endif - - if (status_dots_requested == 1) - { -#ifdef PNG_WRITE_SUPPORTED - png_set_write_status_fn(write_ptr, write_row_callback); -#endif - png_set_read_status_fn(read_ptr, read_row_callback); - } - - else - { -#ifdef PNG_WRITE_SUPPORTED - png_set_write_status_fn(write_ptr, NULL); -#endif - png_set_read_status_fn(read_ptr, NULL); - } - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - { - int i; - - for (i = 0; i<256; i++) - filters_used[i] = 0; - - png_set_read_user_transform_fn(read_ptr, count_filters); - } -#endif -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED - zero_samples = 0; - png_set_write_user_transform_fn(write_ptr, count_zero_samples); -#endif - -#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - /* Preserve all the unknown chunks, if possible. If this is disabled then, - * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use - * libpng to *save* the unknown chunks on read (because we can't switch the - * save option on!) - * - * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all - * unknown chunks and write will write them all. - */ -#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED - png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, - NULL, 0); -#endif -#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED - png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS, - NULL, 0); -#endif -#endif - - pngtest_debug("Reading info struct"); - png_read_info(read_ptr, read_info_ptr); - -#ifdef PNG_READ_USER_CHUNKS_SUPPORTED - /* This is a bit of a hack; there is no obvious way in the callback function - * to determine that the chunks before the first IDAT have been read, so - * remove the info_ptr (which is only used to determine position relative to - * PLTE) here to indicate that we are after the IDAT. - */ - user_chunk_data.info_ptr = NULL; -#endif - - pngtest_debug("Transferring info struct"); - { - int interlace_type, compression_type, filter_type; - - if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, - &color_type, &interlace_type, &compression_type, &filter_type)) - { - png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - color_type, interlace_type, compression_type, filter_type); -#else - color_type, PNG_INTERLACE_NONE, compression_type, filter_type); -#endif - } - } -#ifdef PNG_FIXED_POINT_SUPPORTED -#ifdef PNG_cHRM_SUPPORTED - { - png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, - blue_y; - - if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, - &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) - { - png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, - red_y, green_x, green_y, blue_x, blue_y); - } - } -#endif -#ifdef PNG_gAMA_SUPPORTED - { - png_fixed_point gamma; - - if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) - png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); - } -#endif -#else /* Use floating point versions */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -#ifdef PNG_cHRM_SUPPORTED - { - double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, - blue_y; - - if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, - &red_y, &green_x, &green_y, &blue_x, &blue_y)) - { - png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, - red_y, green_x, green_y, blue_x, blue_y); - } - } -#endif -#ifdef PNG_gAMA_SUPPORTED - { - double gamma; - - if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) - png_set_gAMA(write_ptr, write_info_ptr, gamma); - } -#endif -#endif /* Floating point */ -#endif /* Fixed point */ -#ifdef PNG_iCCP_SUPPORTED - { - png_charp name; - png_bytep profile; - png_uint_32 proflen; - int compression_type; - - if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, - &profile, &proflen)) - { - png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, - profile, proflen); - } - } -#endif -#ifdef PNG_sRGB_SUPPORTED - { - int intent; - - if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) - png_set_sRGB(write_ptr, write_info_ptr, intent); - } -#endif - { - png_colorp palette; - int num_palette; - - if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) - png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); - } -#ifdef PNG_bKGD_SUPPORTED - { - png_color_16p background; - - if (png_get_bKGD(read_ptr, read_info_ptr, &background)) - { - png_set_bKGD(write_ptr, write_info_ptr, background); - } - } -#endif -#ifdef PNG_hIST_SUPPORTED - { - png_uint_16p hist; - - if (png_get_hIST(read_ptr, read_info_ptr, &hist)) - png_set_hIST(write_ptr, write_info_ptr, hist); - } -#endif -#ifdef PNG_oFFs_SUPPORTED - { - png_int_32 offset_x, offset_y; - int unit_type; - - if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, - &unit_type)) - { - png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); - } - } -#endif -#ifdef PNG_pCAL_SUPPORTED - { - png_charp purpose, units; - png_charpp params; - png_int_32 X0, X1; - int type, nparams; - - if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, - &nparams, &units, ¶ms)) - { - png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, - nparams, units, params); - } - } -#endif -#ifdef PNG_pHYs_SUPPORTED - { - png_uint_32 res_x, res_y; - int unit_type; - - if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) - png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); - } -#endif -#ifdef PNG_sBIT_SUPPORTED - { - png_color_8p sig_bit; - - if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) - png_set_sBIT(write_ptr, write_info_ptr, sig_bit); - } -#endif -#ifdef PNG_sCAL_SUPPORTED -#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ - defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) - { - int unit; - double scal_width, scal_height; - - if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, - &scal_height)) - { - png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); - } - } -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - { - int unit; - png_charp scal_width, scal_height; - - if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, - &scal_height)) - { - png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, - scal_height); - } - } -#endif -#endif -#endif -#ifdef PNG_TEXT_SUPPORTED - { - png_textp text_ptr; - int num_text; - - if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) - { - pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); - - pngtest_check_text_support(read_ptr, text_ptr, num_text); - - if (verbose) - { - int i; - - printf("\n"); - for (i=0; igray > sample_max) || - (color_type == PNG_COLOR_TYPE_RGB && - ((int)trans_color->red > sample_max || - (int)trans_color->green > sample_max || - (int)trans_color->blue > sample_max)))) - png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans, - trans_color); - } - } -#endif -#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED - { - png_unknown_chunkp unknowns; - int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr, - &unknowns); - - if (num_unknowns) - { - png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, - num_unknowns); -#if PNG_LIBPNG_VER < 10600 - /* Copy the locations from the read_info_ptr. The automatically - * generated locations in write_end_info_ptr are wrong prior to 1.6.0 - * because they are reset from the write pointer (removed in 1.6.0). - */ - { - int i; - for (i = 0; i < num_unknowns; i++) - png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, - unknowns[i].location); - } -#endif - } - } -#endif - -#ifdef PNG_WRITE_SUPPORTED - pngtest_debug("Writing info struct"); - - /* Write the info in two steps so that if we write the 'unknown' chunks here - * they go to the correct place. - */ - png_write_info_before_PLTE(write_ptr, write_info_ptr); - - write_chunks(write_ptr, before_PLTE); /* before PLTE */ - - png_write_info(write_ptr, write_info_ptr); - - write_chunks(write_ptr, before_IDAT); /* after PLTE */ -#endif - -#ifdef SINGLE_ROWBUF_ALLOC - pngtest_debug("Allocating row buffer..."); - row_buf = (png_bytep)png_malloc(read_ptr, - png_get_rowbytes(read_ptr, read_info_ptr)); - - pngtest_debug1("\t0x%08lx", (unsigned long)row_buf); -#endif /* SINGLE_ROWBUF_ALLOC */ - pngtest_debug("Writing row data"); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) - num_pass = png_set_interlace_handling(read_ptr); -# ifdef PNG_WRITE_SUPPORTED - png_set_interlace_handling(write_ptr); -# endif -#else - num_pass = 1; -#endif - -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_misc += (t_stop - t_start); - t_start = t_stop; -#endif - for (pass = 0; pass < num_pass; pass++) - { - pngtest_debug1("Writing row data for pass %d", pass); - for (y = 0; y < height; y++) - { -#ifndef SINGLE_ROWBUF_ALLOC - pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); - row_buf = (png_bytep)png_malloc(read_ptr, - png_get_rowbytes(read_ptr, read_info_ptr)); - - pngtest_debug2("\t0x%08lx (%u bytes)", (unsigned long)row_buf, - png_get_rowbytes(read_ptr, read_info_ptr)); - -#endif /* !SINGLE_ROWBUF_ALLOC */ - png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1); - -#ifdef PNG_WRITE_SUPPORTED -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_decode += (t_stop - t_start); - t_start = t_stop; -#endif - png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_encode += (t_stop - t_start); - t_start = t_stop; -#endif -#endif /* PNG_WRITE_SUPPORTED */ - -#ifndef SINGLE_ROWBUF_ALLOC - pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y); - png_free(read_ptr, row_buf); - row_buf = NULL; -#endif /* !SINGLE_ROWBUF_ALLOC */ - } - } - -#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -# ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED - png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); -# endif -# ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED - png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); -# endif -#endif - - pngtest_debug("Reading and writing end_info data"); - - png_read_end(read_ptr, end_info_ptr); -#ifdef PNG_TEXT_SUPPORTED - { - png_textp text_ptr; - int num_text; - - if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) - { - pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); - - pngtest_check_text_support(read_ptr, text_ptr, num_text); - - if (verbose) - { - int i; - - printf("\n"); - for (i=0; i 0) - { - /* We don't really expect to get here because of the setjmp handling - * above, but this is safe. - */ - fprintf(STDERR, "\n %s: %d libpng errors found (%d warnings)", - inname, error_count, warning_count); - - if (strict != 0) - return (1); - } - -# ifdef PNG_WRITE_SUPPORTED - /* If there we no write support nothing was written! */ - else if (unsupported_chunks > 0) - { - fprintf(STDERR, "\n %s: unsupported chunks (%d)%s", - inname, unsupported_chunks, strict ? ": IGNORED --strict!" : ""); - } -# endif - - else if (warning_count > 0) - { - fprintf(STDERR, "\n %s: %d libpng warnings found", - inname, warning_count); - - if (strict != 0) - return (1); - } - - pngtest_debug("Opening files for comparison"); - if ((fpin = fopen(inname, "rb")) == NULL) - { - fprintf(STDERR, "Could not find file %s\n", inname); - return (1); - } - - if ((fpout = fopen(outname, "rb")) == NULL) - { - fprintf(STDERR, "Could not find file %s\n", outname); - FCLOSE(fpin); - return (1); - } - -#ifdef PNG_WRITE_SUPPORTED /* else nothing was written */ - { - int wrote_question = 0; - - for (;;) - { - png_size_t num_in, num_out; - char inbuf[256], outbuf[256]; - - - num_in = fread(inbuf, 1, sizeof inbuf, fpin); - num_out = fread(outbuf, 1, sizeof outbuf, fpout); - - if (num_in != num_out) - { - fprintf(STDERR, "\nFiles %s and %s are of a different size\n", - inname, outname); - - if (wrote_question == 0 && unsupported_chunks == 0) - { - fprintf(STDERR, - " Was %s written with the same maximum IDAT chunk size (%d bytes),", - inname, PNG_ZBUF_SIZE); - fprintf(STDERR, - "\n filtering heuristic (libpng default), compression"); - fprintf(STDERR, - " level (zlib default),\n and zlib version (%s)?\n\n", - ZLIB_VERSION); - wrote_question = 1; - } - - FCLOSE(fpin); - FCLOSE(fpout); - - if (strict != 0 && unsupported_chunks == 0) - return (1); - - else - return (0); - } - - if (!num_in) - break; - - if (memcmp(inbuf, outbuf, num_in)) - { - fprintf(STDERR, "\nFiles %s and %s are different\n", inname, - outname); - - if (wrote_question == 0 && unsupported_chunks == 0) - { - fprintf(STDERR, - " Was %s written with the same maximum IDAT chunk size (%d bytes),", - inname, PNG_ZBUF_SIZE); - fprintf(STDERR, - "\n filtering heuristic (libpng default), compression"); - fprintf(STDERR, - " level (zlib default),\n and zlib version (%s)?\n\n", - ZLIB_VERSION); - wrote_question = 1; - } - - FCLOSE(fpin); - FCLOSE(fpout); - - /* NOTE: the unsupported_chunks escape is permitted here because - * unsupported text chunk compression will result in the compression - * mode being changed (to NONE) yet, in the test case, the result - * can be exactly the same size! - */ - if (strict != 0 && unsupported_chunks == 0) - return (1); - - else - return (0); - } - } - } -#endif /* PNG_WRITE_SUPPORTED */ - - FCLOSE(fpin); - FCLOSE(fpout); - - return (0); -} - -/* Input and output filenames */ -#ifdef RISCOS -static PNG_CONST char *inname = "pngtest/png"; -static PNG_CONST char *outname = "pngout/png"; -#else -static PNG_CONST char *inname = "pngtest.png"; -static PNG_CONST char *outname = "pngout.png"; -#endif - -int -main(int argc, char *argv[]) -{ - int multiple = 0; - int ierror = 0; - - fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); - fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); - fprintf(STDERR, "%s", png_get_copyright(NULL)); - /* Show the version of libpng used in building the library */ - fprintf(STDERR, " library (%lu):%s", - (unsigned long)png_access_version_number(), - png_get_header_version(NULL)); - - /* Show the version of libpng used in building the application */ - fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, - PNG_HEADER_VERSION_STRING); - - /* Do some consistency checking on the memory allocation settings, I'm - * not sure this matters, but it is nice to know, the first of these - * tests should be impossible because of the way the macros are set - * in pngconf.h - */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) - fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); -#endif - /* I think the following can happen. */ -#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) - fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); -#endif - - if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) - { - fprintf(STDERR, - "Warning: versions are different between png.h and png.c\n"); - fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); - fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); - ++ierror; - } - - if (argc > 1) - { - if (strcmp(argv[1], "-m") == 0) - { - multiple = 1; - status_dots_requested = 0; - } - - else if (strcmp(argv[1], "-mv") == 0 || - strcmp(argv[1], "-vm") == 0 ) - { - multiple = 1; - verbose = 1; - status_dots_requested = 1; - } - - else if (strcmp(argv[1], "-v") == 0) - { - verbose = 1; - status_dots_requested = 1; - inname = argv[2]; - } - - else if (strcmp(argv[1], "--strict") == 0) - { - status_dots_requested = 0; - verbose = 1; - inname = argv[2]; - strict++; - relaxed = 0; - } - - else if (strcmp(argv[1], "--relaxed") == 0) - { - status_dots_requested = 0; - verbose = 1; - inname = argv[2]; - strict = 0; - relaxed++; - } - - else - { - inname = argv[1]; - status_dots_requested = 0; - } - } - - if (!multiple && argc == 3 + verbose) - outname = argv[2 + verbose]; - - if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2)) - { - fprintf(STDERR, - "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", - argv[0], argv[0]); - fprintf(STDERR, - " reads/writes one PNG file (without -m) or multiple files (-m)\n"); - fprintf(STDERR, - " with -m %s is used as a temporary file\n", outname); - exit(1); - } - - if (multiple) - { - int i; -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - int allocation_now = current_allocation; -#endif - for (i=2; isize, - (unsigned int)pinfo->pointer); - pinfo = pinfo->next; - } - } -#endif - } -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - fprintf(STDERR, " Current memory allocation: %10d bytes\n", - current_allocation); - fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", - maximum_allocation); - fprintf(STDERR, " Total memory allocation: %10d bytes\n", - total_allocation); - fprintf(STDERR, " Number of allocations: %10d\n", - num_allocations); -#endif - } - - else - { - int i; - for (i = 0; i<3; ++i) - { - int kerror; -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - int allocation_now = current_allocation; -#endif - if (i == 1) - status_dots_requested = 1; - - else if (verbose == 0) - status_dots_requested = 0; - - if (i == 0 || verbose == 1 || ierror != 0) - fprintf(STDERR, "\n Testing %s:", inname); - - kerror = test_one_file(inname, outname); - - if (kerror == 0) - { - if (verbose == 1 || i == 2) - { -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - int k; -#endif -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED - fprintf(STDERR, "\n PASS (%lu zero samples)\n", - (unsigned long)zero_samples); -#else - fprintf(STDERR, " PASS\n"); -#endif -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - for (k = 0; k<256; k++) - if (filters_used[k]) - fprintf(STDERR, " Filter %d was used %lu times\n", - k, (unsigned long)filters_used[k]); -#endif -#ifdef PNG_TIME_RFC1123_SUPPORTED - if (tIME_chunk_present != 0) - fprintf(STDERR, " tIME = %s\n", tIME_string); -#endif /* PNG_TIME_RFC1123_SUPPORTED */ - } - } - - else - { - if (verbose == 0 && i != 2) - fprintf(STDERR, "\n Testing %s:", inname); - - fprintf(STDERR, " FAIL\n"); - ierror += kerror; - } -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - if (allocation_now != current_allocation) - fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", - current_allocation - allocation_now); - - if (current_allocation != 0) - { - memory_infop pinfo = pinformation; - - fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", - current_allocation); - - while (pinfo != NULL) - { - fprintf(STDERR, " %lu bytes at %x\n", - (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); - pinfo = pinfo->next; - } - } -#endif - } -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - fprintf(STDERR, " Current memory allocation: %10d bytes\n", - current_allocation); - fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", - maximum_allocation); - fprintf(STDERR, " Total memory allocation: %10d bytes\n", - total_allocation); - fprintf(STDERR, " Number of allocations: %10d\n", - num_allocations); -#endif - } - -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_misc += (t_stop - t_start); - t_start = t_stop; - fprintf(STDERR, " CPU time used = %.3f seconds", - (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); - fprintf(STDERR, " (decoding %.3f,\n", - t_decode/(float)CLOCKS_PER_SEC); - fprintf(STDERR, " encoding %.3f ,", - t_encode/(float)CLOCKS_PER_SEC); - fprintf(STDERR, " other %.3f seconds)\n\n", - t_misc/(float)CLOCKS_PER_SEC); -#endif - - if (ierror == 0) - fprintf(STDERR, " libpng passes test\n"); - - else - fprintf(STDERR, " libpng FAILS test\n"); - - return (int)(ierror != 0); -} -#else -int -main(void) -{ - fprintf(STDERR, - " test ignored because libpng was not built with read support\n"); - /* And skip this test */ - return 77; -} -#endif - -/* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_7 Your_png_h_is_not_version_1_6_7; + +/* pngtest.c - a simple test program to test libpng + * + * Last changed in libpng 1.6.11 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This program reads in a PNG image, writes it out again, and then + * compares the two files. If the files are identical, this shows that + * the basic chunk handling, filtering, and (de)compression code is working + * properly. It does not currently test all of the transforms, although + * it probably should. + * + * The program will report "FAIL" in certain legitimate cases: + * 1) when the compression level or filter selection method is changed. + * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. + * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks + * exist in the input file. + * 4) others not listed here... + * In these cases, it is best to check with another tool such as "pngcheck" + * to see what the differences between the two files are. + * + * If a filename is given on the command-line, then this file is used + * for the input, rather than the default "pngtest.png". This allows + * testing a wide variety of files easily. You can also test a number + * of files at once by typing "pngtest -m file1.png file2.png ..." + */ + +#define _POSIX_SOURCE 1 + +#include +#include +#include + +/* Defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* For DOS */ + +#include "png.h" + +/* Known chunks that exist in pngtest.png must be supported or pngtest will fail + * simply as a result of re-ordering them. This may be fixed in 1.7 + * + * pngtest allocates a single row buffer for each row and overwrites it, + * therefore if the write side doesn't support the writing of interlaced images + * nothing can be done for an interlaced image (and the code below will fail + * horribly trying to write extra data after writing garbage). + */ +#if defined PNG_READ_SUPPORTED && /* else nothing can be done */\ + defined PNG_READ_bKGD_SUPPORTED &&\ + defined PNG_READ_cHRM_SUPPORTED &&\ + defined PNG_READ_gAMA_SUPPORTED &&\ + defined PNG_READ_oFFs_SUPPORTED &&\ + defined PNG_READ_pCAL_SUPPORTED &&\ + defined PNG_READ_pHYs_SUPPORTED &&\ + defined PNG_READ_sBIT_SUPPORTED &&\ + defined PNG_READ_sCAL_SUPPORTED &&\ + defined PNG_READ_sRGB_SUPPORTED &&\ + defined PNG_READ_tEXt_SUPPORTED &&\ + defined PNG_READ_tIME_SUPPORTED &&\ + defined PNG_READ_zTXt_SUPPORTED &&\ + defined PNG_WRITE_INTERLACING_SUPPORTED + +#ifdef PNG_ZLIB_HEADER +# include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */ +#else +# include "zlib.h" +#endif + +/* Copied from pngpriv.h but only used in error messages below. */ +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif +#define FCLOSE(file) fclose(file) + +#ifndef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +/* Makes pngtest verbose so we can find problems. */ +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if PNG_DEBUG > 1 +# define pngtest_debug(m) ((void)fprintf(stderr, m "\n")) +# define pngtest_debug1(m,p1) ((void)fprintf(stderr, m "\n", p1)) +# define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2)) +#else +# define pngtest_debug(m) ((void)0) +# define pngtest_debug1(m,p1) ((void)0) +# define pngtest_debug2(m,p1,p2) ((void)0) +#endif + +#if !PNG_DEBUG +# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ +#endif + +/* Turn on CPU timing +#define PNGTEST_TIMING +*/ + +#ifndef PNG_FLOATING_POINT_SUPPORTED +#undef PNGTEST_TIMING +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#include +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +#define PNG_tIME_STRING_LENGTH 29 +static int tIME_chunk_present = 0; +static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; +#endif + +static int verbose = 0; +static int strict = 0; +static int relaxed = 0; +static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */ +static int error_count = 0; /* count calls to png_error */ +static int warning_count = 0; /* count calls to png_warning */ + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) png_ptr->jmpbuf +#endif + +/* Defines for unknown chunk handling if required. */ +#ifndef PNG_HANDLE_CHUNK_ALWAYS +# define PNG_HANDLE_CHUNK_ALWAYS 3 +#endif +#ifndef PNG_HANDLE_CHUNK_IF_SAFE +# define PNG_HANDLE_CHUNK_IF_SAFE 2 +#endif + +/* Utility to save typing/errors, the argument must be a name */ +#define MEMZERO(var) ((void)memset(&var, 0, sizeof var)) + +/* Example of using row callbacks to make a simple progress meter */ +static int status_pass = 1; +static int status_dots_requested = 0; +static int status_dots = 1; + +static void PNGCBAPI +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) + return; + + if (status_pass != pass) + { + fprintf(stdout, "\n Pass %d: ", pass); + status_pass = pass; + status_dots = 31; + } + + status_dots--; + + if (status_dots == 0) + { + fprintf(stdout, "\n "); + status_dots=30; + } + + fprintf(stdout, "r"); +} + +#ifdef PNG_WRITE_SUPPORTED +static void PNGCBAPI +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) + return; + + fprintf(stdout, "w"); +} +#endif + + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely examine the row filters. We set this to 256 rather than + * 5 in case illegal filter values are present.) + */ +static png_uint_32 filters_used[256]; +static void PNGCBAPI +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + if (png_ptr != NULL && row_info != NULL) + ++filters_used[*(data - 1)]; +} +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely count the zero samples) + */ + +static png_uint_32 zero_samples; + +static void PNGCBAPI +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + png_bytep dp = data; + if (png_ptr == NULL) + return; + + /* Contents of row_info: + * png_uint_32 width width of row + * png_uint_32 rowbytes number of bytes in row + * png_byte color_type color type of pixels + * png_byte bit_depth bit depth of samples + * png_byte channels number of channels (1-4) + * png_byte pixel_depth bits per pixel (depth*channels) + */ + + /* Counts the number of zero samples (or zero pixels if color_type is 3 */ + + if (row_info->color_type == 0 || row_info->color_type == 3) + { + int pos = 0; + png_uint_32 n, nstop; + + for (n = 0, nstop=row_info->width; nbit_depth == 1) + { + if (((*dp << pos++ ) & 0x80) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 2) + { + if (((*dp << (pos+=2)) & 0xc0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 4) + { + if (((*dp << (pos+=4)) & 0xf0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp+=2; + } + } + } + else /* Other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if (row_info->color_type > 3)color_channels--; + + for (n = 0, nstop=row_info->width; nbit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + + dp+=2; + } + } + if (row_info->color_type > 3) + { + dp++; + if (row_info->bit_depth == 16) + dp++; + } + } + } +} +#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ + +#ifndef PNG_STDIO_SUPPORTED +/* START of code to validate stdio-free compilation */ +/* These copies of the default read/write functions come from pngrio.c and + * pngwio.c. They allow "don't include stdio" testing of the library. + * This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ + +#ifdef PNG_IO_STATE_SUPPORTED +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op); +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op) +{ + png_uint_32 io_state = png_get_io_state(png_ptr); + int err = 0; + + /* Check if the current operation (reading / writing) is as expected. */ + if ((io_state & PNG_IO_MASK_OP) != io_op) + png_error(png_ptr, "Incorrect operation in I/O state"); + + /* Check if the buffer size specific to the current location + * (file signature / header / data / crc) is as expected. + */ + switch (io_state & PNG_IO_MASK_LOC) + { + case PNG_IO_SIGNATURE: + if (data_length > 8) + err = 1; + break; + case PNG_IO_CHUNK_HDR: + if (data_length != 8) + err = 1; + break; + case PNG_IO_CHUNK_DATA: + break; /* no restrictions here */ + case PNG_IO_CHUNK_CRC: + if (data_length != 4) + err = 1; + break; + default: + err = 1; /* uninitialized */ + } + if (err != 0) + png_error(png_ptr, "Bad I/O state or buffer size"); +} +#endif + +static void PNGCBAPI +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check = 0; + png_voidp io_ptr; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + io_ptr = png_get_io_ptr(png_ptr); + if (io_ptr != NULL) + { + check = fread(data, 1, length, (png_FILE_p)io_ptr); + } + + if (check != length) + { + png_error(png_ptr, "Read Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +static void PNGCBAPI +pngtest_flush(png_structp png_ptr) +{ + /* Do nothing; fflush() is said to be just a waste of energy. */ + PNG_UNUSED(png_ptr) /* Stifle compiler warning */ +} +#endif + +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +static void PNGCBAPI +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); + + if (check != length) + { + png_error(png_ptr, "Write Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#endif /* !PNG_STDIO_SUPPORTED */ + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +typedef struct +{ + PNG_CONST char *file_name; +} pngtest_error_parameters; + +static void PNGCBAPI +pngtest_warning(png_structp png_ptr, png_const_charp message) +{ + PNG_CONST char *name = "UNKNOWN (ERROR!)"; + pngtest_error_parameters *test = + (pngtest_error_parameters*)png_get_error_ptr(png_ptr); + + ++warning_count; + + if (test != NULL && test->file_name != NULL) + name = test->file_name; + + fprintf(STDERR, "%s: libpng warning: %s\n", name, message); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void PNGCBAPI +pngtest_error(png_structp png_ptr, png_const_charp message) +{ + ++error_count; + + pngtest_warning(png_ptr, message); + /* We can return because png_error calls the default handler, which is + * actually OK in this case. + */ +} + +/* END of code to validate stdio-free compilation */ + +/* START of code to validate memory allocation and deallocation */ +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * This piece of code can be compiled to validate max 64K allocations + * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. + */ +typedef struct memory_information +{ + png_alloc_size_t size; + png_voidp pointer; + struct memory_information *next; +} memory_information; +typedef memory_information *memory_infop; + +static memory_infop pinformation = NULL; +static int current_allocation = 0; +static int maximum_allocation = 0; +static int total_allocation = 0; +static int num_allocations = 0; + +png_voidp PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr, + png_alloc_size_t size)); +void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); + +png_voidp +PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) +{ + + /* png_malloc has already tested for NULL; png_create_struct calls + * png_debug_malloc directly, with png_ptr == NULL which is OK + */ + + if (size == 0) + return (NULL); + + /* This calls the library allocator twice, once to get the requested + buffer and once to get a new free list entry. */ + { + /* Disable malloc_fn and free_fn */ + memory_infop pinfo; + png_set_mem_fn(png_ptr, NULL, NULL, NULL); + pinfo = (memory_infop)png_malloc(png_ptr, + (sizeof *pinfo)); + pinfo->size = size; + current_allocation += size; + total_allocation += size; + num_allocations ++; + + if (current_allocation > maximum_allocation) + maximum_allocation = current_allocation; + + pinfo->pointer = png_malloc(png_ptr, size); + /* Restore malloc_fn and free_fn */ + + png_set_mem_fn(png_ptr, + NULL, png_debug_malloc, png_debug_free); + + if (size != 0 && pinfo->pointer == NULL) + { + current_allocation -= size; + total_allocation -= size; + png_error(png_ptr, + "out of memory in pngtest->png_debug_malloc"); + } + + pinfo->next = pinformation; + pinformation = pinfo; + /* Make sure the caller isn't assuming zeroed memory. */ + memset(pinfo->pointer, 0xdd, pinfo->size); + + if (verbose != 0) + printf("png_malloc %lu bytes at %p\n", (unsigned long)size, + pinfo->pointer); + + return (png_voidp)(pinfo->pointer); + } +} + +/* Free a pointer. It is removed from the list at the same time. */ +void PNGCBAPI +png_debug_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL) + fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + + if (ptr == 0) + { +#if 0 /* This happens all the time. */ + fprintf(STDERR, "WARNING: freeing NULL pointer\n"); +#endif + return; + } + + /* Unlink the element from the list. */ + { + memory_infop *ppinfo = &pinformation; + + for (;;) + { + memory_infop pinfo = *ppinfo; + + if (pinfo->pointer == ptr) + { + *ppinfo = pinfo->next; + current_allocation -= pinfo->size; + if (current_allocation < 0) + fprintf(STDERR, "Duplicate free of memory\n"); + /* We must free the list element too, but first kill + the memory that is to be freed. */ + memset(ptr, 0x55, pinfo->size); + if (pinfo != NULL) + free(pinfo); + pinfo = NULL; + break; + } + + if (pinfo->next == NULL) + { + fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); + break; + } + + ppinfo = &pinfo->next; + } + } + + /* Finally free the data. */ + if (verbose != 0) + printf("Freeing %p\n", ptr); + + if (ptr != NULL) + free(ptr); + ptr = NULL; +} +#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ +/* END of code to test memory allocation/deallocation */ + + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* Demonstration of user chunk support of the sTER and vpAg chunks */ + +/* (sTER is a public chunk not yet known by libpng. vpAg is a private +chunk used in ImageMagick to store "virtual page" size). */ + +static struct user_chunk_data +{ + png_const_infop info_ptr; + png_uint_32 vpAg_width, vpAg_height; + png_byte vpAg_units; + png_byte sTER_mode; + int location[2]; +} +user_chunk_data; + +/* Used for location and order; zero means nothing. */ +#define have_sTER 0x01 +#define have_vpAg 0x02 +#define before_PLTE 0x10 +#define before_IDAT 0x20 +#define after_IDAT 0x40 + +static void +init_callback_info(png_const_infop info_ptr) +{ + MEMZERO(user_chunk_data); + user_chunk_data.info_ptr = info_ptr; +} + +static int +set_location(png_structp png_ptr, struct user_chunk_data *data, int what) +{ + int location; + + if ((data->location[0] & what) || (data->location[1] & what)) + return 0; /* already have one of these */ + + /* Find where we are (the code below zeros info_ptr to indicate that the + * chunks before the first IDAT have been read.) + */ + if (data->info_ptr == NULL) /* after IDAT */ + location = what | after_IDAT; + + else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE)) + location = what | before_IDAT; + + else + location = what | before_PLTE; + + if (data->location[0] == 0) + data->location[0] = location; + + else + data->location[1] = location; + + return 1; /* handled */ +} + +static int PNGCBAPI +read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk) +{ + struct user_chunk_data *my_user_chunk_data = + (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr); + + if (my_user_chunk_data == NULL) + png_error(png_ptr, "lost user chunk pointer"); + + /* Return one of the following: + * return (-n); chunk had an error + * return (0); did not recognize + * return (n); success + * + * The unknown chunk structure contains the chunk data: + * png_byte name[5]; + * png_byte *data; + * png_size_t size; + * + * Note that libpng has already taken care of the CRC handling. + */ + + if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ + chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ + { + /* Found sTER chunk */ + if (chunk->size != 1) + return (-1); /* Error return */ + + if (chunk->data[0] != 0 && chunk->data[0] != 1) + return (-1); /* Invalid mode */ + + if (set_location(png_ptr, my_user_chunk_data, have_sTER)) + { + my_user_chunk_data->sTER_mode=chunk->data[0]; + return (1); + } + + else + return (0); /* duplicate sTER - give it to libpng */ + } + + if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ + chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ + return (0); /* Did not recognize */ + + /* Found ImageMagick vpAg chunk */ + + if (chunk->size != 9) + return (-1); /* Error return */ + + if (!set_location(png_ptr, my_user_chunk_data, have_vpAg)) + return (0); /* duplicate vpAg */ + + my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data); + my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4); + my_user_chunk_data->vpAg_units = chunk->data[8]; + + return (1); +} + +#ifdef PNG_WRITE_SUPPORTED +static void +write_sTER_chunk(png_structp write_ptr) +{ + png_byte sTER[5] = {115, 84, 69, 82, '\0'}; + + if (verbose != 0) + fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode); + + png_write_chunk(write_ptr, sTER, &user_chunk_data.sTER_mode, 1); +} + +static void +write_vpAg_chunk(png_structp write_ptr) +{ + png_byte vpAg[5] = {118, 112, 65, 103, '\0'}; + + png_byte vpag_chunk_data[9]; + + if (verbose != 0) + fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n", + (unsigned long)user_chunk_data.vpAg_width, + (unsigned long)user_chunk_data.vpAg_height, + user_chunk_data.vpAg_units); + + png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width); + png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height); + vpag_chunk_data[8] = user_chunk_data.vpAg_units; + png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9); +} + +static void +write_chunks(png_structp write_ptr, int location) +{ + int i; + + /* Notice that this preserves the original chunk order, however chunks + * intercepted by the callback will be written *after* chunks passed to + * libpng. This will actually reverse a pair of sTER chunks or a pair of + * vpAg chunks, resulting in an error later. This is not worth worrying + * about - the chunks should not be duplicated! + */ + for (i=0; i<2; ++i) + { + if (user_chunk_data.location[i] == (location | have_sTER)) + write_sTER_chunk(write_ptr); + + else if (user_chunk_data.location[i] == (location | have_vpAg)) + write_vpAg_chunk(write_ptr); + } +} +#endif /* PNG_WRITE_SUPPORTED */ +#else /* !PNG_READ_USER_CHUNKS_SUPPORTED */ +# define write_chunks(pp,loc) ((void)0) +#endif +/* END of code to demonstrate user chunk support */ + +/* START of code to check that libpng has the required text support; this only + * checks for the write support because if read support is missing the chunk + * will simply not be reported back to pngtest. + */ +#ifdef PNG_TEXT_SUPPORTED +static void +pngtest_check_text_support(png_const_structp png_ptr, png_textp text_ptr, + int num_text) +{ + while (num_text > 0) + { + switch (text_ptr[--num_text].compression) + { + case PNG_TEXT_COMPRESSION_NONE: + break; + + case PNG_TEXT_COMPRESSION_zTXt: +# ifndef PNG_WRITE_zTXt_SUPPORTED + ++unsupported_chunks; +# endif + break; + + case PNG_ITXT_COMPRESSION_NONE: + case PNG_ITXT_COMPRESSION_zTXt: +# ifndef PNG_WRITE_iTXt_SUPPORTED + ++unsupported_chunks; +# endif + break; + + default: + /* This is an error */ + png_error(png_ptr, "invalid text chunk compression field"); + break; + } + } +} +#endif +/* END of code to check that libpng has the required text support */ + +/* Test one file */ +static int +test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) +{ + static png_FILE_p fpin; + static png_FILE_p fpout; /* "static" prevents setjmp corruption */ + pngtest_error_parameters error_parameters; + png_structp read_ptr; + png_infop read_info_ptr, end_info_ptr; +#ifdef PNG_WRITE_SUPPORTED + png_structp write_ptr; + png_infop write_info_ptr; + png_infop write_end_info_ptr; + int interlace_preserved = 1; +#else + png_structp write_ptr = NULL; + png_infop write_info_ptr = NULL; + png_infop write_end_info_ptr = NULL; +#endif + png_bytep row_buf; + png_uint_32 y; + png_uint_32 width, height; + int num_pass = 1, pass; + int bit_depth, color_type; + + row_buf = NULL; + error_parameters.file_name = inname; + + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "wb")) == NULL) + { + fprintf(STDERR, "Could not open output file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + pngtest_debug("Allocating read and write structures"); +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + read_ptr = + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + read_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif + png_set_error_fn(read_ptr, &error_parameters, pngtest_error, + pngtest_warning); + +#ifdef PNG_WRITE_SUPPORTED +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + write_ptr = + png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + write_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif + png_set_error_fn(write_ptr, &error_parameters, pngtest_error, + pngtest_warning); +#endif + pngtest_debug("Allocating read_info, write_info and end_info structures"); + read_info_ptr = png_create_info_struct(read_ptr); + end_info_ptr = png_create_info_struct(read_ptr); +#ifdef PNG_WRITE_SUPPORTED + write_info_ptr = png_create_info_struct(write_ptr); + write_end_info_ptr = png_create_info_struct(write_ptr); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + init_callback_info(read_info_ptr); + png_set_read_user_chunk_fn(read_ptr, &user_chunk_data, + read_user_chunk_callback); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + pngtest_debug("Setting jmpbuf for read struct"); + if (setjmp(png_jmpbuf(read_ptr))) + { + fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); + png_free(read_ptr, row_buf); + row_buf = NULL; + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Setting jmpbuf for write struct"); + + if (setjmp(png_jmpbuf(write_ptr))) + { + fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#endif +#endif + + if (strict != 0) + { + /* Treat png_benign_error() as errors on read */ + png_set_benign_errors(read_ptr, 0); + +#ifdef PNG_WRITE_SUPPORTED + /* Treat them as errors on write */ + png_set_benign_errors(write_ptr, 0); +#endif + + /* if strict is not set, then app warnings and errors are treated as + * warnings in release builds, but not in unstable builds; this can be + * changed with '--relaxed'. + */ + } + + else if (relaxed != 0) + { + /* Allow application (pngtest) errors and warnings to pass */ + png_set_benign_errors(read_ptr, 1); + +#ifdef PNG_WRITE_SUPPORTED + png_set_benign_errors(write_ptr, 1); +#endif + } + + pngtest_debug("Initializing input and output streams"); +#ifdef PNG_STDIO_SUPPORTED + png_init_io(read_ptr, fpin); +# ifdef PNG_WRITE_SUPPORTED + png_init_io(write_ptr, fpout); +# endif +#else + png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); +# ifdef PNG_WRITE_SUPPORTED + png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, +# ifdef PNG_WRITE_FLUSH_SUPPORTED + pngtest_flush); +# else + NULL); +# endif +# endif +#endif + + if (status_dots_requested == 1) + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, write_row_callback); +#endif + png_set_read_status_fn(read_ptr, read_row_callback); + } + + else + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, NULL); +#endif + png_set_read_status_fn(read_ptr, NULL); + } + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + { + int i; + + for (i = 0; i<256; i++) + filters_used[i] = 0; + + png_set_read_user_transform_fn(read_ptr, count_filters); + } +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + zero_samples = 0; + png_set_write_user_transform_fn(write_ptr, count_zero_samples); +#endif + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + /* Preserve all the unknown chunks, if possible. If this is disabled then, + * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use + * libpng to *save* the unknown chunks on read (because we can't switch the + * save option on!) + * + * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all + * unknown chunks and write will write them all. + */ +#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED + png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, + NULL, 0); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS, + NULL, 0); +#endif +#endif + + pngtest_debug("Reading info struct"); + png_read_info(read_ptr, read_info_ptr); + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + /* This is a bit of a hack; there is no obvious way in the callback function + * to determine that the chunks before the first IDAT have been read, so + * remove the info_ptr (which is only used to determine position relative to + * PLTE) here to indicate that we are after the IDAT. + */ + user_chunk_data.info_ptr = NULL; +#endif + + pngtest_debug("Transferring info struct"); + { + int interlace_type, compression_type, filter_type; + + if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, &compression_type, &filter_type)) + { + png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +#ifndef PNG_READ_INTERLACING_SUPPORTED + /* num_pass will not be set below, set it here if the image is + * interlaced: what happens is that write interlacing is *not* turned + * on an the partial interlaced rows are written directly. + */ + switch (interlace_type) + { + case PNG_INTERLACE_NONE: + num_pass = 1; + break; + + case PNG_INTERLACE_ADAM7: + num_pass = 7; + break; + + default: + png_error(read_ptr, "invalid interlace type"); + /*NOT REACHED*/ + } +#endif + } + } +#ifdef PNG_FIXED_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + png_fixed_point gamma; + + if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); + } +#endif +#else /* Use floating point versions */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + double gamma; + + if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA(write_ptr, write_info_ptr, gamma); + } +#endif +#endif /* Floating point */ +#endif /* Fixed point */ +#ifdef PNG_iCCP_SUPPORTED + { + png_charp name; + png_bytep profile; + png_uint_32 proflen; + int compression_type; + + if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, + &profile, &proflen)) + { + png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, + profile, proflen); + } + } +#endif +#ifdef PNG_sRGB_SUPPORTED + { + int intent; + + if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) + png_set_sRGB(write_ptr, write_info_ptr, intent); + } +#endif + { + png_colorp palette; + int num_palette; + + if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) + png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); + } +#ifdef PNG_bKGD_SUPPORTED + { + png_color_16p background; + + if (png_get_bKGD(read_ptr, read_info_ptr, &background)) + { + png_set_bKGD(write_ptr, write_info_ptr, background); + } + } +#endif +#ifdef PNG_hIST_SUPPORTED + { + png_uint_16p hist; + + if (png_get_hIST(read_ptr, read_info_ptr, &hist)) + png_set_hIST(write_ptr, write_info_ptr, hist); + } +#endif +#ifdef PNG_oFFs_SUPPORTED + { + png_int_32 offset_x, offset_y; + int unit_type; + + if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, + &unit_type)) + { + png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); + } + } +#endif +#ifdef PNG_pCAL_SUPPORTED + { + png_charp purpose, units; + png_charpp params; + png_int_32 X0, X1; + int type, nparams; + + if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, + &nparams, &units, ¶ms)) + { + png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, + nparams, units, params); + } + } +#endif +#ifdef PNG_pHYs_SUPPORTED + { + png_uint_32 res_x, res_y; + int unit_type; + + if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) + png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); + } +#endif +#ifdef PNG_sBIT_SUPPORTED + { + png_color_8p sig_bit; + + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) + png_set_sBIT(write_ptr, write_info_ptr, sig_bit); + } +#endif +#ifdef PNG_sCAL_SUPPORTED +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) + { + int unit; + double scal_width, scal_height; + + if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + { + int unit; + png_charp scal_width, scal_height; + + if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, + scal_height); + } + } +#endif +#endif +#endif +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + + pngtest_check_text_support(read_ptr, text_ptr, num_text); + + if (verbose != 0) + { + int i; + + printf("\n"); + for (i=0; igray > sample_max) || + (color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max)))) + png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans, + trans_color); + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + + if (num_unknowns != 0) + { + png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, + num_unknowns); +#if PNG_LIBPNG_VER < 10600 + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_end_info_ptr are wrong prior to 1.6.0 + * because they are reset from the write pointer (removed in 1.6.0). + */ + { + int i; + for (i = 0; i < num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, + unknowns[i].location); + } +#endif + } + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Writing info struct"); + + /* Write the info in two steps so that if we write the 'unknown' chunks here + * they go to the correct place. + */ + png_write_info_before_PLTE(write_ptr, write_info_ptr); + + write_chunks(write_ptr, before_PLTE); /* before PLTE */ + + png_write_info(write_ptr, write_info_ptr); + + write_chunks(write_ptr, before_IDAT); /* after PLTE */ +#endif + +#ifdef SINGLE_ROWBUF_ALLOC + pngtest_debug("Allocating row buffer..."); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug1("\t0x%08lx", (unsigned long)row_buf); +#endif /* SINGLE_ROWBUF_ALLOC */ + pngtest_debug("Writing row data"); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + num_pass = png_set_interlace_handling(read_ptr); + if (png_set_interlace_handling(write_ptr) != num_pass) + png_error(write_ptr, "png_set_interlace_handling: inconsistent num_pass"); +#endif + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; +#endif + for (pass = 0; pass < num_pass; pass++) + { + pngtest_debug1("Writing row data for pass %d", pass); + for (y = 0; y < height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug2("\t0x%08lx (%u bytes)", (unsigned long)row_buf, + png_get_rowbytes(read_ptr, read_info_ptr)); + +#endif /* !SINGLE_ROWBUF_ALLOC */ + png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* !SINGLE_ROWBUF_ALLOC */ + } + } + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); +# endif +# ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); +# endif +#endif + + pngtest_debug("Reading and writing end_info data"); + + png_read_end(read_ptr, end_info_ptr); +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + + pngtest_check_text_support(read_ptr, text_ptr, num_text); + + if (verbose != 0) + { + int i; + + printf("\n"); + for (i=0; i 0) + { + /* We don't really expect to get here because of the setjmp handling + * above, but this is safe. + */ + fprintf(STDERR, "\n %s: %d libpng errors found (%d warnings)", + inname, error_count, warning_count); + + if (strict != 0) + return (1); + } + +# ifdef PNG_WRITE_SUPPORTED + /* If there we no write support nothing was written! */ + else if (unsupported_chunks > 0) + { + fprintf(STDERR, "\n %s: unsupported chunks (%d)%s", + inname, unsupported_chunks, strict ? ": IGNORED --strict!" : ""); + } +# endif + + else if (warning_count > 0) + { + fprintf(STDERR, "\n %s: %d libpng warnings found", + inname, warning_count); + + if (strict != 0) + return (1); + } + + pngtest_debug("Opening files for comparison"); + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", outname); + FCLOSE(fpin); + return (1); + } + +#ifdef PNG_WRITE_SUPPORTED /* else nothing was written */ + if (interlace_preserved != 0) /* else the files will be changed */ + { + for (;;) + { + static int wrote_question = 0; + png_size_t num_in, num_out; + char inbuf[256], outbuf[256]; + + num_in = fread(inbuf, 1, sizeof inbuf, fpin); + num_out = fread(outbuf, 1, sizeof outbuf, fpout); + + if (num_in != num_out) + { + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); + + if (wrote_question == 0 && unsupported_chunks == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + + if (strict != 0 && unsupported_chunks == 0) + return (1); + + else + return (0); + } + + if (num_in == 0) + break; + + if (memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, + outname); + + if (wrote_question == 0 && unsupported_chunks == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + + /* NOTE: the unsupported_chunks escape is permitted here because + * unsupported text chunk compression will result in the compression + * mode being changed (to NONE) yet, in the test case, the result + * can be exactly the same size! + */ + if (strict != 0 && unsupported_chunks == 0) + return (1); + + else + return (0); + } + } + } +#endif /* PNG_WRITE_SUPPORTED */ + + FCLOSE(fpin); + FCLOSE(fpout); + + return (0); +} + +/* Input and output filenames */ +#ifdef RISCOS +static PNG_CONST char *inname = "pngtest/png"; +static PNG_CONST char *outname = "pngout/png"; +#else +static PNG_CONST char *inname = "pngtest.png"; +static PNG_CONST char *outname = "pngout.png"; +#endif + +int +main(int argc, char *argv[]) +{ + int multiple = 0; + int ierror = 0; + + fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); + fprintf(STDERR, "%s", png_get_copyright(NULL)); + /* Show the version of libpng used in building the library */ + fprintf(STDERR, " library (%lu):%s", + (unsigned long)png_access_version_number(), + png_get_header_version(NULL)); + + /* Show the version of libpng used in building the application */ + fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, + PNG_HEADER_VERSION_STRING); + + /* Do some consistency checking on the memory allocation settings, I'm + * not sure this matters, but it is nice to know, the first of these + * tests should be impossible because of the way the macros are set + * in pngconf.h + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); +#endif + /* I think the following can happen. */ +#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); +#endif + + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) + { + fprintf(STDERR, + "Warning: versions are different between png.h and png.c\n"); + fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); + ++ierror; + } + + if (argc > 1) + { + if (strcmp(argv[1], "-m") == 0) + { + multiple = 1; + status_dots_requested = 0; + } + + else if (strcmp(argv[1], "-mv") == 0 || + strcmp(argv[1], "-vm") == 0 ) + { + multiple = 1; + verbose = 1; + status_dots_requested = 1; + } + + else if (strcmp(argv[1], "-v") == 0) + { + verbose = 1; + status_dots_requested = 1; + inname = argv[2]; + } + + else if (strcmp(argv[1], "--strict") == 0) + { + status_dots_requested = 0; + verbose = 1; + inname = argv[2]; + strict++; + relaxed = 0; + } + + else if (strcmp(argv[1], "--relaxed") == 0) + { + status_dots_requested = 0; + verbose = 1; + inname = argv[2]; + strict = 0; + relaxed++; + } + + else + { + inname = argv[1]; + status_dots_requested = 0; + } + } + + if (!multiple && argc == 3 + verbose) + outname = argv[2 + verbose]; + + if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2)) + { + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); + } + + if (multiple != 0) + { + int i; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + for (i=2; isize, + (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + + else + { + int i; + for (i = 0; i<3; ++i) + { + int kerror; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + if (i == 1) + status_dots_requested = 1; + + else if (verbose == 0) + status_dots_requested = 0; + + if (i == 0 || verbose == 1 || ierror != 0) + fprintf(STDERR, "\n Testing %s:", inname); + + kerror = test_one_file(inname, outname); + + if (kerror == 0) + { + if (verbose == 1 || i == 2) + { +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + int k; +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + for (k = 0; k<256; k++) + if (filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k, (unsigned long)filters_used[k]); +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n", tIME_string); +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } + + else + { + if (verbose == 0 && i != 2) + fprintf(STDERR, "\n Testing %s:", inname); + + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation - allocation_now); + + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + + while (pinfo != NULL) + { + fprintf(STDERR, " %lu bytes at %x\n", + (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; + fprintf(STDERR, " CPU time used = %.3f seconds", + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " (decoding %.3f,\n", + t_decode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " encoding %.3f ,", + t_encode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " other %.3f seconds)\n\n", + t_misc/(float)CLOCKS_PER_SEC); +#endif + + if (ierror == 0) + fprintf(STDERR, " libpng passes test\n"); + + else + fprintf(STDERR, " libpng FAILS test\n"); + + return (int)(ierror != 0); +} +#else +int +main(void) +{ + fprintf(STDERR, + " test ignored because libpng was not built with read support\n"); + /* And skip this test */ + return PNG_LIBPNG_VER < 10600 ? 0 : 77; +} +#endif + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef png_libpng_version_1_7_0beta35 Your_png_h_is_not_version_1_7_0beta35; diff --git a/ext/libpng16/pngtrans.c b/ext/libpng17/pngtrans.c similarity index 95% rename from ext/libpng16/pngtrans.c rename to ext/libpng17/pngtrans.c index 99c6ea9d3b..22499e49c2 100644 --- a/ext/libpng16/pngtrans.c +++ b/ext/libpng17/pngtrans.c @@ -1,841 +1,843 @@ - -/* pngtrans.c - transforms the data in a row (used by both readers and writers) - * - * Last changed in libpng 1.6.2 [April 25, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -#include "pngpriv.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Turn on BGR-to-RGB mapping */ -void PNGAPI -png_set_bgr(png_structrp png_ptr) -{ - png_debug(1, "in png_set_bgr"); - - if (png_ptr == NULL) - return; - - png_ptr->transformations |= PNG_BGR; -} -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Turn on 16 bit byte swapping */ -void PNGAPI -png_set_swap(png_structrp png_ptr) -{ - png_debug(1, "in png_set_swap"); - - if (png_ptr == NULL) - return; - - if (png_ptr->bit_depth == 16) - png_ptr->transformations |= PNG_SWAP_BYTES; -} -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Turn on pixel packing */ -void PNGAPI -png_set_packing(png_structrp png_ptr) -{ - png_debug(1, "in png_set_packing"); - - if (png_ptr == NULL) - return; - - if (png_ptr->bit_depth < 8) - { - png_ptr->transformations |= PNG_PACK; - png_ptr->usr_bit_depth = 8; - } -} -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Turn on packed pixel swapping */ -void PNGAPI -png_set_packswap(png_structrp png_ptr) -{ - png_debug(1, "in png_set_packswap"); - - if (png_ptr == NULL) - return; - - if (png_ptr->bit_depth < 8) - png_ptr->transformations |= PNG_PACKSWAP; -} -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -void PNGAPI -png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits) -{ - png_debug(1, "in png_set_shift"); - - if (png_ptr == NULL) - return; - - png_ptr->transformations |= PNG_SHIFT; - png_ptr->shift = *true_bits; -} -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -int PNGAPI -png_set_interlace_handling(png_structrp png_ptr) -{ - png_debug(1, "in png_set_interlace handling"); - - if (png_ptr && png_ptr->interlaced) - { - png_ptr->transformations |= PNG_INTERLACE; - return (7); - } - - return (1); -} -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte on read, or remove a filler or alpha byte on write. - * The filler type has changed in v0.95 to allow future 2-byte fillers - * for 48-bit input data, as well as to avoid problems with some compilers - * that don't like bytes as parameters. - */ -void PNGAPI -png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc) -{ - png_debug(1, "in png_set_filler"); - - if (png_ptr == NULL) - return; - - /* In libpng 1.6 it is possible to determine whether this is a read or write - * operation and therefore to do more checking here for a valid call. - */ - if (png_ptr->mode & PNG_IS_READ_STRUCT) - { -# ifdef PNG_READ_FILLER_SUPPORTED - /* On read png_set_filler is always valid, regardless of the base PNG - * format, because other transformations can give a format where the - * filler code can execute (basically an 8 or 16-bit component RGB or G - * format.) - * - * NOTE: usr_channels is not used by the read code! (This has led to - * confusion in the past.) The filler is only used in the read code. - */ - png_ptr->filler = (png_uint_16)filler; -# else - png_app_error(png_ptr, "png_set_filler not supported on read"); - PNG_UNUSED(filler) /* not used in the write case */ - return; -# endif - } - - else /* write */ - { -# ifdef PNG_WRITE_FILLER_SUPPORTED - /* On write the usr_channels parameter must be set correctly at the - * start to record the number of channels in the app-supplied data. - */ - switch (png_ptr->color_type) - { - case PNG_COLOR_TYPE_RGB: - png_ptr->usr_channels = 4; - break; - - case PNG_COLOR_TYPE_GRAY: - if (png_ptr->bit_depth >= 8) - { - png_ptr->usr_channels = 2; - break; - } - - else - { - /* There simply isn't any code in libpng to strip out bits - * from bytes when the components are less than a byte in - * size! - */ - png_app_error(png_ptr, - "png_set_filler is invalid for low bit depth gray output"); - return; - } - - default: - png_app_error(png_ptr, - "png_set_filler: inappropriate color type"); - return; - } -# else - png_app_error(png_ptr, "png_set_filler not supported on write"); - return; -# endif - } - - /* Here on success - libpng supports the operation, set the transformation - * and the flag to say where the filler channel is. - */ - png_ptr->transformations |= PNG_FILLER; - - if (filler_loc == PNG_FILLER_AFTER) - png_ptr->flags |= PNG_FLAG_FILLER_AFTER; - - else - png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; -} - -/* Added to libpng-1.2.7 */ -void PNGAPI -png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc) -{ - png_debug(1, "in png_set_add_alpha"); - - if (png_ptr == NULL) - return; - - png_set_filler(png_ptr, filler, filler_loc); - /* The above may fail to do anything. */ - if (png_ptr->transformations & PNG_FILLER) - png_ptr->transformations |= PNG_ADD_ALPHA; -} - -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -void PNGAPI -png_set_swap_alpha(png_structrp png_ptr) -{ - png_debug(1, "in png_set_swap_alpha"); - - if (png_ptr == NULL) - return; - - png_ptr->transformations |= PNG_SWAP_ALPHA; -} -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -void PNGAPI -png_set_invert_alpha(png_structrp png_ptr) -{ - png_debug(1, "in png_set_invert_alpha"); - - if (png_ptr == NULL) - return; - - png_ptr->transformations |= PNG_INVERT_ALPHA; -} -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -void PNGAPI -png_set_invert_mono(png_structrp png_ptr) -{ - png_debug(1, "in png_set_invert_mono"); - - if (png_ptr == NULL) - return; - - png_ptr->transformations |= PNG_INVERT_MONO; -} - -/* Invert monochrome grayscale data */ -void /* PRIVATE */ -png_do_invert(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_invert"); - - /* This test removed from libpng version 1.0.13 and 1.2.0: - * if (row_info->bit_depth == 1 && - */ - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(~(*rp)); - rp++; - } - } - - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - row_info->bit_depth == 8) - { - png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; - - for (i = 0; i < istop; i += 2) - { - *rp = (png_byte)(~(*rp)); - rp += 2; - } - } - -#ifdef PNG_16BIT_SUPPORTED - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - row_info->bit_depth == 16) - { - png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; - - for (i = 0; i < istop; i += 4) - { - *rp = (png_byte)(~(*rp)); - *(rp + 1) = (png_byte)(~(*(rp + 1))); - rp += 4; - } - } -#endif -} -#endif - -#ifdef PNG_16BIT_SUPPORTED -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swaps byte order on 16 bit depth images */ -void /* PRIVATE */ -png_do_swap(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_swap"); - - if (row_info->bit_depth == 16) - { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop= row_info->width * row_info->channels; - - for (i = 0; i < istop; i++, rp += 2) - { - png_byte t = *rp; - *rp = *(rp + 1); - *(rp + 1) = t; - } - } -} -#endif -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) -static PNG_CONST png_byte onebppswaptable[256] = { - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, - 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, - 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, - 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, - 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, - 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, - 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, - 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, - 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, - 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, - 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, - 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, - 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, - 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, - 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, - 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, - 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF -}; - -static PNG_CONST png_byte twobppswaptable[256] = { - 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, - 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, - 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, - 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, - 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, - 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, - 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, - 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, - 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, - 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, - 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, - 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, - 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, - 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, - 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, - 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, - 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, - 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, - 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, - 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, - 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, - 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, - 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, - 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, - 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, - 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, - 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, - 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, - 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, - 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, - 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, - 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF -}; - -static PNG_CONST png_byte fourbppswaptable[256] = { - 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, - 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, - 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, - 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, - 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, - 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, - 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, - 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, - 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, - 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, - 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, - 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, - 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, - 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, - 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, - 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, - 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, - 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, - 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, - 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, - 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, - 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, - 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, - 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, - 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, - 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, - 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, - 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, - 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, - 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, - 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, - 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF -}; - -/* Swaps pixel packing order within bytes */ -void /* PRIVATE */ -png_do_packswap(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_packswap"); - - if (row_info->bit_depth < 8) - { - png_bytep rp; - png_const_bytep end, table; - - end = row + row_info->rowbytes; - - if (row_info->bit_depth == 1) - table = onebppswaptable; - - else if (row_info->bit_depth == 2) - table = twobppswaptable; - - else if (row_info->bit_depth == 4) - table = fourbppswaptable; - - else - return; - - for (rp = row; rp < end; rp++) - *rp = table[*rp]; - } -} -#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ - -#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ - defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -/* Remove a channel - this used to be 'png_do_strip_filler' but it used a - * somewhat weird combination of flags to determine what to do. All the calls - * to png_do_strip_filler are changed in 1.5.2 to call this instead with the - * correct arguments. - * - * The routine isn't general - the channel must be the channel at the start or - * end (not in the middle) of each pixel. - */ -void /* PRIVATE */ -png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) -{ - png_bytep sp = row; /* source pointer */ - png_bytep dp = row; /* destination pointer */ - png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */ - - /* At the start sp will point to the first byte to copy and dp to where - * it is copied to. ep always points just beyond the end of the row, so - * the loop simply copies (channels-1) channels until sp reaches ep. - * - * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc. - * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc. - */ - - /* GA, GX, XG cases */ - if (row_info->channels == 2) - { - if (row_info->bit_depth == 8) - { - if (at_start) /* Skip initial filler */ - ++sp; - else /* Skip initial channel and, for sp, the filler */ - sp += 2, ++dp; - - /* For a 1 pixel wide image there is nothing to do */ - while (sp < ep) - *dp++ = *sp, sp += 2; - - row_info->pixel_depth = 8; - } - - else if (row_info->bit_depth == 16) - { - if (at_start) /* Skip initial filler */ - sp += 2; - else /* Skip initial channel and, for sp, the filler */ - sp += 4, dp += 2; - - while (sp < ep) - *dp++ = *sp++, *dp++ = *sp, sp += 3; - - row_info->pixel_depth = 16; - } - - else - return; /* bad bit depth */ - - row_info->channels = 1; - - /* Finally fix the color type if it records an alpha channel */ - if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - row_info->color_type = PNG_COLOR_TYPE_GRAY; - } - - /* RGBA, RGBX, XRGB cases */ - else if (row_info->channels == 4) - { - if (row_info->bit_depth == 8) - { - if (at_start) /* Skip initial filler */ - ++sp; - else /* Skip initial channels and, for sp, the filler */ - sp += 4, dp += 3; - - /* Note that the loop adds 3 to dp and 4 to sp each time. */ - while (sp < ep) - *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; - - row_info->pixel_depth = 24; - } - - else if (row_info->bit_depth == 16) - { - if (at_start) /* Skip initial filler */ - sp += 2; - else /* Skip initial channels and, for sp, the filler */ - sp += 8, dp += 6; - - while (sp < ep) - { - /* Copy 6 bytes, skip 2 */ - *dp++ = *sp++, *dp++ = *sp++; - *dp++ = *sp++, *dp++ = *sp++; - *dp++ = *sp++, *dp++ = *sp, sp += 3; - } - - row_info->pixel_depth = 48; - } - - else - return; /* bad bit depth */ - - row_info->channels = 3; - - /* Finally fix the color type if it records an alpha channel */ - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - row_info->color_type = PNG_COLOR_TYPE_RGB; - } - - else - return; /* The filler channel has gone already */ - - /* Fix the rowbytes value. */ - row_info->rowbytes = dp-row; -} -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Swaps red and blue bytes within a pixel */ -void /* PRIVATE */ -png_do_bgr(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_bgr"); - - if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 3) - { - png_byte save = *rp; - *rp = *(rp + 2); - *(rp + 2) = save; - } - } - - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 4) - { - png_byte save = *rp; - *rp = *(rp + 2); - *(rp + 2) = save; - } - } - } - -#ifdef PNG_16BIT_SUPPORTED - else if (row_info->bit_depth == 16) - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 6) - { - png_byte save = *rp; - *rp = *(rp + 4); - *(rp + 4) = save; - save = *(rp + 1); - *(rp + 1) = *(rp + 5); - *(rp + 5) = save; - } - } - - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 8) - { - png_byte save = *rp; - *rp = *(rp + 4); - *(rp + 4) = save; - save = *(rp + 1); - *(rp + 1) = *(rp + 5); - *(rp + 5) = save; - } - } - } -#endif - } -} -#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ - -#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \ - defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED) -/* Added at libpng-1.5.10 */ -void /* PRIVATE */ -png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) -{ - if (png_ptr->num_palette < (1 << row_info->bit_depth) && - png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */ - { - /* Calculations moved outside switch in an attempt to stop different - * compiler warnings. 'padding' is in *bits* within the last byte, it is - * an 'int' because pixel_depth becomes an 'int' in the expression below, - * and this calculation is used because it avoids warnings that other - * forms produced on either GCC or MSVC. - */ - int padding = (-row_info->pixel_depth * row_info->width) & 7; - png_bytep rp = png_ptr->row_buf + row_info->rowbytes; - - switch (row_info->bit_depth) - { - case 1: - { - /* in this case, all bytes must be 0 so we don't need - * to unpack the pixels except for the rightmost one. - */ - for (; rp > png_ptr->row_buf; rp--) - { - if (*rp >> padding != 0) - png_ptr->num_palette_max = 1; - padding = 0; - } - - break; - } - - case 2: - { - for (; rp > png_ptr->row_buf; rp--) - { - int i = ((*rp >> padding) & 0x03); - - if (i > png_ptr->num_palette_max) - png_ptr->num_palette_max = i; - - i = (((*rp >> padding) >> 2) & 0x03); - - if (i > png_ptr->num_palette_max) - png_ptr->num_palette_max = i; - - i = (((*rp >> padding) >> 4) & 0x03); - - if (i > png_ptr->num_palette_max) - png_ptr->num_palette_max = i; - - i = (((*rp >> padding) >> 6) & 0x03); - - if (i > png_ptr->num_palette_max) - png_ptr->num_palette_max = i; - - padding = 0; - } - - break; - } - - case 4: - { - for (; rp > png_ptr->row_buf; rp--) - { - int i = ((*rp >> padding) & 0x0f); - - if (i > png_ptr->num_palette_max) - png_ptr->num_palette_max = i; - - i = (((*rp >> padding) >> 4) & 0x0f); - - if (i > png_ptr->num_palette_max) - png_ptr->num_palette_max = i; - - padding = 0; - } - - break; - } - - case 8: - { - for (; rp > png_ptr->row_buf; rp--) - { - if (*rp > png_ptr->num_palette_max) - png_ptr->num_palette_max = (int) *rp; - } - - break; - } - - default: - break; - } - } -} -#endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -void PNGAPI -png_set_user_transform_info(png_structrp png_ptr, png_voidp - user_transform_ptr, int user_transform_depth, int user_transform_channels) -{ - png_debug(1, "in png_set_user_transform_info"); - - if (png_ptr == NULL) - return; - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && - (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0) - { - png_app_error(png_ptr, - "info change after png_start_read_image or png_read_update_info"); - return; - } -#endif - - png_ptr->user_transform_ptr = user_transform_ptr; - png_ptr->user_transform_depth = (png_byte)user_transform_depth; - png_ptr->user_transform_channels = (png_byte)user_transform_channels; -} -#endif - -/* This function returns a pointer to the user_transform_ptr associated with - * the user transform functions. The application should free any memory - * associated with this pointer before png_write_destroy and png_read_destroy - * are called. - */ -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -png_voidp PNGAPI -png_get_user_transform_ptr(png_const_structrp png_ptr) -{ - if (png_ptr == NULL) - return (NULL); - - return png_ptr->user_transform_ptr; -} -#endif - -#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED -png_uint_32 PNGAPI -png_get_current_row_number(png_const_structrp png_ptr) -{ - /* See the comments in png.h - this is the sub-image row when reading and - * interlaced image. - */ - if (png_ptr != NULL) - return png_ptr->row_number; - - return PNG_UINT_32_MAX; /* help the app not to fail silently */ -} - -png_byte PNGAPI -png_get_current_pass_number(png_const_structrp png_ptr) -{ - if (png_ptr != NULL) - return png_ptr->pass; - return 8; /* invalid */ -} -#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */ -#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED || - PNG_WRITE_USER_TRANSFORM_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * Last changed in libpng 1.6.11 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structrp png_ptr) +{ + png_debug(1, "in png_set_bgr"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structrp png_ptr) +{ + png_debug(1, "in png_set_swap"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Turn on pixel packing */ +void PNGAPI +png_set_packing(png_structrp png_ptr) +{ + png_debug(1, "in png_set_packing"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; +# ifdef PNG_WRITE_SUPPORTED + png_ptr->usr_bit_depth = 8; +# endif + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structrp png_ptr) +{ + png_debug(1, "in png_set_packswap"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits) +{ + png_debug(1, "in png_set_shift"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structrp png_ptr) +{ + png_debug(1, "in png_set_interlace handling"); + + if (png_ptr && png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler"); + + if (png_ptr == NULL) + return; + + /* In libpng 1.6 it is possible to determine whether this is a read or write + * operation and therefore to do more checking here for a valid call. + */ + if (png_ptr->mode & PNG_IS_READ_STRUCT) + { +# ifdef PNG_READ_FILLER_SUPPORTED + /* On read png_set_filler is always valid, regardless of the base PNG + * format, because other transformations can give a format where the + * filler code can execute (basically an 8 or 16-bit component RGB or G + * format.) + * + * NOTE: usr_channels is not used by the read code! (This has led to + * confusion in the past.) The filler is only used in the read code. + */ + png_ptr->filler = (png_uint_16)filler; +# else + png_app_error(png_ptr, "png_set_filler not supported on read"); + PNG_UNUSED(filler) /* not used in the write case */ + return; +# endif + } + + else /* write */ + { +# ifdef PNG_WRITE_FILLER_SUPPORTED + /* On write the usr_channels parameter must be set correctly at the + * start to record the number of channels in the app-supplied data. + */ + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_RGB: + png_ptr->usr_channels = 4; + break; + + case PNG_COLOR_TYPE_GRAY: + if (png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + break; + } + + else + { + /* There simply isn't any code in libpng to strip out bits + * from bytes when the components are less than a byte in + * size! + */ + png_app_error(png_ptr, + "png_set_filler is invalid for low bit depth gray output"); + return; + } + + default: + png_app_error(png_ptr, + "png_set_filler: inappropriate color type"); + return; + } +# else + png_app_error(png_ptr, "png_set_filler not supported on write"); + return; +# endif + } + + /* Here on success - libpng supports the operation, set the transformation + * and the flag to say where the filler channel is. + */ + png_ptr->transformations |= PNG_FILLER; + + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; +} + +/* Added to libpng-1.2.7 */ +void PNGAPI +png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_add_alpha"); + + if (png_ptr == NULL) + return; + + png_set_filler(png_ptr, filler, filler_loc); + /* The above may fail to do anything. */ + if (png_ptr->transformations & PNG_FILLER) + png_ptr->transformations |= PNG_ADD_ALPHA; +} + +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structrp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structrp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structrp png_ptr) +{ + png_debug(1, "in png_set_invert_mono"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* Invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert"); + + /* This test removed from libpng version 1.0.13 and 1.2.0: + * if (row_info->bit_depth == 1 && + */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 8) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 2) + { + *rp = (png_byte)(~(*rp)); + rp += 2; + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 4) + { + *rp = (png_byte)(~(*rp)); + *(rp + 1) = (png_byte)(~(*(rp + 1))); + rp += 4; + } + } +#endif +} +#endif + +#ifdef PNG_16BIT_SUPPORTED +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap"); + + if (row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static PNG_CONST png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static PNG_CONST png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static PNG_CONST png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* Swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap"); + + if (row_info->bit_depth < 8) + { + png_bytep rp; + png_const_bytep end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = onebppswaptable; + + else if (row_info->bit_depth == 2) + table = twobppswaptable; + + else if (row_info->bit_depth == 4) + table = fourbppswaptable; + + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* Remove a channel - this used to be 'png_do_strip_filler' but it used a + * somewhat weird combination of flags to determine what to do. All the calls + * to png_do_strip_filler are changed in 1.5.2 to call this instead with the + * correct arguments. + * + * The routine isn't general - the channel must be the channel at the start or + * end (not in the middle) of each pixel. + */ +void /* PRIVATE */ +png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) +{ + png_bytep sp = row; /* source pointer */ + png_bytep dp = row; /* destination pointer */ + png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */ + + /* At the start sp will point to the first byte to copy and dp to where + * it is copied to. ep always points just beyond the end of the row, so + * the loop simply copies (channels-1) channels until sp reaches ep. + * + * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc. + * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc. + */ + + /* GA, GX, XG cases */ + if (row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + if (at_start != 0) /* Skip initial filler */ + ++sp; + else /* Skip initial channel and, for sp, the filler */ + sp += 2, ++dp; + + /* For a 1 pixel wide image there is nothing to do */ + while (sp < ep) + *dp++ = *sp, sp += 2; + + row_info->pixel_depth = 8; + } + + else if (row_info->bit_depth == 16) + { + if (at_start != 0) /* Skip initial filler */ + sp += 2; + else /* Skip initial channel and, for sp, the filler */ + sp += 4, dp += 2; + + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp, sp += 3; + + row_info->pixel_depth = 16; + } + + else + return; /* bad bit depth */ + + row_info->channels = 1; + + /* Finally fix the color type if it records an alpha channel */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + row_info->color_type = PNG_COLOR_TYPE_GRAY; + } + + /* RGBA, RGBX, XRGB cases */ + else if (row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + if (at_start != 0) /* Skip initial filler */ + ++sp; + else /* Skip initial channels and, for sp, the filler */ + sp += 4, dp += 3; + + /* Note that the loop adds 3 to dp and 4 to sp each time. */ + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; + + row_info->pixel_depth = 24; + } + + else if (row_info->bit_depth == 16) + { + if (at_start != 0) /* Skip initial filler */ + sp += 2; + else /* Skip initial channels and, for sp, the filler */ + sp += 8, dp += 6; + + while (sp < ep) + { + /* Copy 6 bytes, skip 2 */ + *dp++ = *sp++, *dp++ = *sp++; + *dp++ = *sp++, *dp++ = *sp++; + *dp++ = *sp++, *dp++ = *sp, sp += 3; + } + + row_info->pixel_depth = 48; + } + + else + return; /* bad bit depth */ + + row_info->channels = 3; + + /* Finally fix the color type if it records an alpha channel */ + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + row_info->color_type = PNG_COLOR_TYPE_RGB; + } + + else + return; /* The filler channel has gone already */ + + /* Fix the rowbytes value. */ + row_info->rowbytes = dp-row; +} +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr"); + + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } +#endif + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \ + defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED) +/* Added at libpng-1.5.10 */ +void /* PRIVATE */ +png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) +{ + if (png_ptr->num_palette < (1 << row_info->bit_depth) && + png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */ + { + /* Calculations moved outside switch in an attempt to stop different + * compiler warnings. 'padding' is in *bits* within the last byte, it is + * an 'int' because pixel_depth becomes an 'int' in the expression below, + * and this calculation is used because it avoids warnings that other + * forms produced on either GCC or MSVC. + */ + int padding = (-row_info->pixel_depth * row_info->width) & 7; + png_bytep rp = png_ptr->row_buf + row_info->rowbytes; + + switch (row_info->bit_depth) + { + case 1: + { + /* in this case, all bytes must be 0 so we don't need + * to unpack the pixels except for the rightmost one. + */ + for (; rp > png_ptr->row_buf; rp--) + { + if (*rp >> padding != 0) + png_ptr->num_palette_max = 1; + padding = 0; + } + + break; + } + + case 2: + { + for (; rp > png_ptr->row_buf; rp--) + { + int i = ((*rp >> padding) & 0x03); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + i = (((*rp >> padding) >> 2) & 0x03); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + i = (((*rp >> padding) >> 4) & 0x03); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + i = (((*rp >> padding) >> 6) & 0x03); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + padding = 0; + } + + break; + } + + case 4: + { + for (; rp > png_ptr->row_buf; rp--) + { + int i = ((*rp >> padding) & 0x0f); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + i = (((*rp >> padding) >> 4) & 0x0f); + + if (i > png_ptr->num_palette_max) + png_ptr->num_palette_max = i; + + padding = 0; + } + + break; + } + + case 8: + { + for (; rp > png_ptr->row_buf; rp--) + { + if (*rp > png_ptr->num_palette_max) + png_ptr->num_palette_max = (int) *rp; + } + + break; + } + + default: + break; + } + } +} +#endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +void PNGAPI +png_set_user_transform_info(png_structrp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0) + { + png_app_error(png_ptr, + "info change after png_start_read_image or png_read_update_info"); + return; + } +#endif + + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +} +#endif + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +png_voidp PNGAPI +png_get_user_transform_ptr(png_const_structrp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->user_transform_ptr; +} +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +png_uint_32 PNGAPI +png_get_current_row_number(png_const_structrp png_ptr) +{ + /* See the comments in png.h - this is the sub-image row when reading and + * interlaced image. + */ + if (png_ptr != NULL) + return png_ptr->row_number; + + return PNG_UINT_32_MAX; /* help the app not to fail silently */ +} + +png_byte PNGAPI +png_get_current_pass_number(png_const_structrp png_ptr) +{ + if (png_ptr != NULL) + return png_ptr->pass; + return 8; /* invalid */ +} +#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */ +#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED || + PNG_WRITE_USER_TRANSFORM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngwio.c b/ext/libpng17/pngwio.c similarity index 95% rename from ext/libpng16/pngwio.c rename to ext/libpng17/pngwio.c index c5fca989c8..1b525f9484 100644 --- a/ext/libpng16/pngwio.c +++ b/ext/libpng17/pngwio.c @@ -1,164 +1,168 @@ - -/* pngwio.c - functions for data output - * - * Last changed in libpng 1.6.0 [February 14, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - * This file provides a location for all output. Users who need - * special handling are expected to write functions that have the same - * arguments as these and perform similar functions, but that possibly - * use different output methods. Note that you shouldn't change these - * functions, but rather write replacement functions and then change - * them at run time with png_set_write_fn(...). - */ - -#include "pngpriv.h" - -#ifdef PNG_WRITE_SUPPORTED - -/* Write the data to whatever output you are using. The default routine - * writes to a file pointer. Note that this routine sometimes gets called - * with very small lengths, so you should implement some kind of simple - * buffering if you are using unbuffered writes. This should never be asked - * to write more than 64K on a 16 bit machine. - */ - -void /* PRIVATE */ -png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) -{ - /* NOTE: write_data_fn must not change the buffer! */ - if (png_ptr->write_data_fn != NULL ) - (*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data), - length); - - else - png_error(png_ptr, "Call to NULL write function"); -} - -#ifdef PNG_STDIO_SUPPORTED -/* This is the function that does the actual writing of data. If you are - * not writing to a standard C stream, you should create a replacement - * write_data function and use it at run time with png_set_write_fn(), rather - * than changing the library. - */ -void PNGCBAPI -png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - if (png_ptr == NULL) - return; - - check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); - - if (check != length) - png_error(png_ptr, "Write Error"); -} -#endif - -/* This function is called to output any data pending writing (normally - * to disk). After png_flush is called, there should be no data pending - * writing in any buffers. - */ -#ifdef PNG_WRITE_FLUSH_SUPPORTED -void /* PRIVATE */ -png_flush(png_structrp png_ptr) -{ - if (png_ptr->output_flush_fn != NULL) - (*(png_ptr->output_flush_fn))(png_ptr); -} - -# ifdef PNG_STDIO_SUPPORTED -void PNGCBAPI -png_default_flush(png_structp png_ptr) -{ - png_FILE_p io_ptr; - - if (png_ptr == NULL) - return; - - io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr)); - fflush(io_ptr); -} -# endif -#endif - -/* This function allows the application to supply new output functions for - * libpng if standard C streams aren't being used. - * - * This function takes as its arguments: - * png_ptr - pointer to a png output data structure - * io_ptr - pointer to user supplied structure containing info about - * the output functions. May be NULL. - * write_data_fn - pointer to a new output function that takes as its - * arguments a pointer to a png_struct, a pointer to - * data to be written, and a 32-bit unsigned int that is - * the number of bytes to be written. The new write - * function should call png_error(png_ptr, "Error msg") - * to exit and output any fatal error messages. May be - * NULL, in which case libpng's default function will - * be used. - * flush_data_fn - pointer to a new flush function that takes as its - * arguments a pointer to a png_struct. After a call to - * the flush function, there should be no data in any buffers - * or pending transmission. If the output method doesn't do - * any buffering of output, a function prototype must still be - * supplied although it doesn't have to do anything. If - * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile - * time, output_flush_fn will be ignored, although it must be - * supplied for compatibility. May be NULL, in which case - * libpng's default function will be used, if - * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not - * a good idea if io_ptr does not point to a standard - * *FILE structure. - */ -void PNGAPI -png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr, - png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) -{ - if (png_ptr == NULL) - return; - - png_ptr->io_ptr = io_ptr; - -#ifdef PNG_STDIO_SUPPORTED - if (write_data_fn != NULL) - png_ptr->write_data_fn = write_data_fn; - - else - png_ptr->write_data_fn = png_default_write_data; -#else - png_ptr->write_data_fn = write_data_fn; -#endif - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -# ifdef PNG_STDIO_SUPPORTED - - if (output_flush_fn != NULL) - png_ptr->output_flush_fn = output_flush_fn; - - else - png_ptr->output_flush_fn = png_default_flush; - -# else - png_ptr->output_flush_fn = output_flush_fn; -# endif -#endif /* PNG_WRITE_FLUSH_SUPPORTED */ - - /* It is an error to read while writing a png file */ - if (png_ptr->read_data_fn != NULL) - { - png_ptr->read_data_fn = NULL; - - png_warning(png_ptr, - "Can't set both read_data_fn and write_data_fn in the" - " same structure"); - } -} -#endif /* PNG_WRITE_SUPPORTED */ + +/* pngwio.c - functions for data output + * + * Last changed in libpng 1.6.9 [February 6, 2014] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +/* Write the data to whatever output you are using. The default routine + * writes to a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered writes. This should never be asked + * to write more than 64K on a 16 bit machine. + */ + +void /* PRIVATE */ +png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) +{ + /* NOTE: write_data_fn must not change the buffer! */ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data), + length); + + else + png_error(png_ptr, "Call to NULL write function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +void PNGCBAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); + + if (check != length) + png_error(png_ptr, "Write Error"); +} +#endif + +/* This function is called to output any data pending writing (normally + * to disk). After png_flush is called, there should be no data pending + * writing in any buffers. + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +void /* PRIVATE */ +png_flush(png_structrp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +# ifdef PNG_STDIO_SUPPORTED +void PNGCBAPI +png_default_flush(png_structp png_ptr) +{ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr)); + fflush(io_ptr); +} +# endif +#endif + +/* This function allows the application to supply new output functions for + * libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png output data structure + * io_ptr - pointer to user supplied structure containing info about + * the output functions. May be NULL. + * write_data_fn - pointer to a new output function that takes as its + * arguments a pointer to a png_struct, a pointer to + * data to be written, and a 32-bit unsigned int that is + * the number of bytes to be written. The new write + * function should call png_error(png_ptr, "Error msg") + * to exit and output any fatal error messages. May be + * NULL, in which case libpng's default function will + * be used. + * flush_data_fn - pointer to a new flush function that takes as its + * arguments a pointer to a png_struct. After a call to + * the flush function, there should be no data in any buffers + * or pending transmission. If the output method doesn't do + * any buffering of output, a function prototype must still be + * supplied although it doesn't have to do anything. If + * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + * time, output_flush_fn will be ignored, although it must be + * supplied for compatibility. May be NULL, in which case + * libpng's default function will be used, if + * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not + * a good idea if io_ptr does not point to a standard + * *FILE structure. + */ +void PNGAPI +png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED + + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + + else + png_ptr->output_flush_fn = png_default_flush; + +# else + png_ptr->output_flush_fn = output_flush_fn; +# endif +#else + PNG_UNUSED(output_flush_fn) +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +#ifdef PNG_READ_SUPPORTED + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + + png_warning(png_ptr, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngwrite.c b/ext/libpng17/pngwrite.c similarity index 89% rename from ext/libpng16/pngwrite.c rename to ext/libpng17/pngwrite.c index 4fe7301d3f..1c91697f37 100644 --- a/ext/libpng16/pngwrite.c +++ b/ext/libpng17/pngwrite.c @@ -1,2330 +1,2422 @@ - -/* pngwrite.c - general routines to write a PNG file - * - * Last changed in libpng 1.6.2 [April 25, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -#include "pngpriv.h" -#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) -# include -#endif - -#ifdef PNG_WRITE_SUPPORTED - -#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -/* Write out all the unknown chunks for the current given location */ -static void -write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, - unsigned int where) -{ - if (info_ptr->unknown_chunks_num) - { - png_const_unknown_chunkp up; - - png_debug(5, "writing extra chunks"); - - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - ++up) - if (up->location & where) - { - /* If per-chunk unknown chunk handling is enabled use it, otherwise - * just write the chunks the application has set. - */ -#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - int keep = png_handle_as_unknown(png_ptr, up->name); - - /* NOTE: this code is radically different from the read side in the - * matter of handling an ancillary unknown chunk. In the read side - * the default behavior is to discard it, in the code below the default - * behavior is to write it. Critical chunks are, however, only - * written if explicitly listed or if the default is set to write all - * unknown chunks. - * - * The default handling is also slightly weird - it is not possible to - * stop the writing of all unsafe-to-copy chunks! - * - * TODO: REVIEW: this would seem to be a bug. - */ - if (keep != PNG_HANDLE_CHUNK_NEVER && - ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ || - keep == PNG_HANDLE_CHUNK_ALWAYS || - (keep == PNG_HANDLE_CHUNK_AS_DEFAULT && - png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS))) -#endif - { - /* TODO: review, what is wrong with a zero length unknown chunk? */ - if (up->size == 0) - png_warning(png_ptr, "Writing zero-length unknown chunk"); - - png_write_chunk(png_ptr, up->name, up->data, up->size); - } - } - } -} -#endif /* PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */ - -/* Writes all the PNG information. This is the suggested way to use the - * library. If you have a new chunk to add, make a function to write it, - * and put it in the correct location here. If you want the chunk written - * after the image data, put it in png_write_end(). I strongly encourage - * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing - * the chunk, as that will keep the code from breaking if you want to just - * write a plain PNG file. If you have long comments, I suggest writing - * them in png_write_end(), and compressing them. - */ -void PNGAPI -png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) -{ - png_debug(1, "in png_write_info_before_PLTE"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) - { - /* Write PNG signature */ - png_write_sig(png_ptr); - -#ifdef PNG_MNG_FEATURES_SUPPORTED - if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \ - (png_ptr->mng_features_permitted)) - { - png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); - png_ptr->mng_features_permitted = 0; - } -#endif - - /* Write IHDR information. */ - png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, - info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, - info_ptr->filter_type, -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - info_ptr->interlace_type -#else - 0 -#endif - ); - - /* The rest of these check to see if the valid field has the appropriate - * flag set, and if it does, writes the chunk. - * - * 1.6.0: COLORSPACE support controls the writing of these chunks too, and - * the chunks will be written if the WRITE routine is there and information - * is available in the COLORSPACE. (See png_colorspace_sync_info in png.c - * for where the valid flags get set.) - * - * Under certain circumstances the colorspace can be invalidated without - * syncing the info_struct 'valid' flags; this happens if libpng detects and - * error and calls png_error while the color space is being set, yet the - * application continues writing the PNG. So check the 'invalid' flag here - * too. - */ -#ifdef PNG_GAMMA_SUPPORTED -# ifdef PNG_WRITE_gAMA_SUPPORTED - if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && - (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) && - (info_ptr->valid & PNG_INFO_gAMA)) - png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma); -# endif -#endif - -#ifdef PNG_COLORSPACE_SUPPORTED - /* Write only one of sRGB or an ICC profile. If a profile was supplied - * and it matches one of the known sRGB ones issue a warning. - */ -# ifdef PNG_WRITE_iCCP_SUPPORTED - if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && - (info_ptr->valid & PNG_INFO_iCCP)) - { -# ifdef PNG_WRITE_sRGB_SUPPORTED - if (info_ptr->valid & PNG_INFO_sRGB) - png_app_warning(png_ptr, - "profile matches sRGB but writing iCCP instead"); -# endif - - png_write_iCCP(png_ptr, info_ptr->iccp_name, - info_ptr->iccp_profile); - } -# ifdef PNG_WRITE_sRGB_SUPPORTED - else -# endif -# endif - -# ifdef PNG_WRITE_sRGB_SUPPORTED - if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && - (info_ptr->valid & PNG_INFO_sRGB)) - png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); -# endif /* WRITE_sRGB */ -#endif /* COLORSPACE */ - -#ifdef PNG_WRITE_sBIT_SUPPORTED - if (info_ptr->valid & PNG_INFO_sBIT) - png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); -#endif - -#ifdef PNG_COLORSPACE_SUPPORTED -# ifdef PNG_WRITE_cHRM_SUPPORTED - if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && - (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) && - (info_ptr->valid & PNG_INFO_cHRM)) - png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy); -# endif -#endif - -#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED - write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); -#endif - - png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; - } -} - -void PNGAPI -png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) -{ -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) - int i; -#endif - - png_debug(1, "in png_write_info"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_write_info_before_PLTE(png_ptr, info_ptr); - - if (info_ptr->valid & PNG_INFO_PLTE) - png_write_PLTE(png_ptr, info_ptr->palette, - (png_uint_32)info_ptr->num_palette); - - else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_error(png_ptr, "Valid palette required for paletted images"); - -#ifdef PNG_WRITE_tRNS_SUPPORTED - if (info_ptr->valid & PNG_INFO_tRNS) - { -#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED - /* Invert the alpha channel (in tRNS) */ - if ((png_ptr->transformations & PNG_INVERT_ALPHA) && - info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - int j; - for (j = 0; j<(int)info_ptr->num_trans; j++) - info_ptr->trans_alpha[j] = - (png_byte)(255 - info_ptr->trans_alpha[j]); - } -#endif - png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), - info_ptr->num_trans, info_ptr->color_type); - } -#endif -#ifdef PNG_WRITE_bKGD_SUPPORTED - if (info_ptr->valid & PNG_INFO_bKGD) - png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); -#endif - -#ifdef PNG_WRITE_hIST_SUPPORTED - if (info_ptr->valid & PNG_INFO_hIST) - png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); -#endif - -#ifdef PNG_WRITE_oFFs_SUPPORTED - if (info_ptr->valid & PNG_INFO_oFFs) - png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, - info_ptr->offset_unit_type); -#endif - -#ifdef PNG_WRITE_pCAL_SUPPORTED - if (info_ptr->valid & PNG_INFO_pCAL) - png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, - info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, - info_ptr->pcal_units, info_ptr->pcal_params); -#endif - -#ifdef PNG_WRITE_sCAL_SUPPORTED - if (info_ptr->valid & PNG_INFO_sCAL) - png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, - info_ptr->scal_s_width, info_ptr->scal_s_height); -#endif /* sCAL */ - -#ifdef PNG_WRITE_pHYs_SUPPORTED - if (info_ptr->valid & PNG_INFO_pHYs) - png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, - info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); -#endif /* pHYs */ - -#ifdef PNG_WRITE_tIME_SUPPORTED - if (info_ptr->valid & PNG_INFO_tIME) - { - png_write_tIME(png_ptr, &(info_ptr->mod_time)); - png_ptr->mode |= PNG_WROTE_tIME; - } -#endif /* tIME */ - -#ifdef PNG_WRITE_sPLT_SUPPORTED - if (info_ptr->valid & PNG_INFO_sPLT) - for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) - png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); -#endif /* sPLT */ - -#ifdef PNG_WRITE_TEXT_SUPPORTED - /* Check to see if we need to write text chunks */ - for (i = 0; i < info_ptr->num_text; i++) - { - png_debug2(2, "Writing header text chunk %d, type %d", i, - info_ptr->text[i].compression); - /* An internationalized chunk? */ - if (info_ptr->text[i].compression > 0) - { -#ifdef PNG_WRITE_iTXt_SUPPORTED - /* Write international chunk */ - png_write_iTXt(png_ptr, - info_ptr->text[i].compression, - info_ptr->text[i].key, - info_ptr->text[i].lang, - info_ptr->text[i].lang_key, - info_ptr->text[i].text); -#else - png_warning(png_ptr, "Unable to write international text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - - /* If we want a compressed text chunk */ - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) - { -#ifdef PNG_WRITE_zTXt_SUPPORTED - /* Write compressed chunk */ - png_write_zTXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0, - info_ptr->text[i].compression); -#else - png_warning(png_ptr, "Unable to write compressed text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; - } - - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) - { -#ifdef PNG_WRITE_tEXt_SUPPORTED - /* Write uncompressed chunk */ - png_write_tEXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, - 0); - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; -#else - /* Can't get here */ - png_warning(png_ptr, "Unable to write uncompressed text"); -#endif - } - } -#endif /* tEXt */ - -#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED - write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE); -#endif -} - -/* Writes the end of the PNG file. If you don't want to write comments or - * time information, you can pass NULL for info. If you already wrote these - * in png_write_info(), do not write them again here. If you have long - * comments, I suggest writing them here, and compressing them. - */ -void PNGAPI -png_write_end(png_structrp png_ptr, png_inforp info_ptr) -{ - png_debug(1, "in png_write_end"); - - if (png_ptr == NULL) - return; - - if (!(png_ptr->mode & PNG_HAVE_IDAT)) - png_error(png_ptr, "No IDATs written into file"); - -#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED - if (png_ptr->num_palette_max > png_ptr->num_palette) - png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); -#endif - - /* See if user wants us to write information chunks */ - if (info_ptr != NULL) - { -#ifdef PNG_WRITE_TEXT_SUPPORTED - int i; /* local index variable */ -#endif -#ifdef PNG_WRITE_tIME_SUPPORTED - /* Check to see if user has supplied a time chunk */ - if ((info_ptr->valid & PNG_INFO_tIME) && - !(png_ptr->mode & PNG_WROTE_tIME)) - png_write_tIME(png_ptr, &(info_ptr->mod_time)); - -#endif -#ifdef PNG_WRITE_TEXT_SUPPORTED - /* Loop through comment chunks */ - for (i = 0; i < info_ptr->num_text; i++) - { - png_debug2(2, "Writing trailer text chunk %d, type %d", i, - info_ptr->text[i].compression); - /* An internationalized chunk? */ - if (info_ptr->text[i].compression > 0) - { -#ifdef PNG_WRITE_iTXt_SUPPORTED - /* Write international chunk */ - png_write_iTXt(png_ptr, - info_ptr->text[i].compression, - info_ptr->text[i].key, - info_ptr->text[i].lang, - info_ptr->text[i].lang_key, - info_ptr->text[i].text); -#else - png_warning(png_ptr, "Unable to write international text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - - else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) - { -#ifdef PNG_WRITE_zTXt_SUPPORTED - /* Write compressed chunk */ - png_write_zTXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0, - info_ptr->text[i].compression); -#else - png_warning(png_ptr, "Unable to write compressed text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; - } - - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) - { -#ifdef PNG_WRITE_tEXt_SUPPORTED - /* Write uncompressed chunk */ - png_write_tEXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0); -#else - png_warning(png_ptr, "Unable to write uncompressed text"); -#endif - - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - } -#endif -#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED - write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT); -#endif - } - - png_ptr->mode |= PNG_AFTER_IDAT; - - /* Write end of PNG file */ - png_write_IEND(png_ptr); - /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, - * and restored again in libpng-1.2.30, may cause some applications that - * do not set png_ptr->output_flush_fn to crash. If your application - * experiences a problem, please try building libpng with - * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to - * png-mng-implement at lists.sf.net . - */ -#ifdef PNG_WRITE_FLUSH_SUPPORTED -# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED - png_flush(png_ptr); -# endif -#endif -} - -#ifdef PNG_CONVERT_tIME_SUPPORTED -void PNGAPI -png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime) -{ - png_debug(1, "in png_convert_from_struct_tm"); - - ptime->year = (png_uint_16)(1900 + ttime->tm_year); - ptime->month = (png_byte)(ttime->tm_mon + 1); - ptime->day = (png_byte)ttime->tm_mday; - ptime->hour = (png_byte)ttime->tm_hour; - ptime->minute = (png_byte)ttime->tm_min; - ptime->second = (png_byte)ttime->tm_sec; -} - -void PNGAPI -png_convert_from_time_t(png_timep ptime, time_t ttime) -{ - struct tm *tbuf; - - png_debug(1, "in png_convert_from_time_t"); - - tbuf = gmtime(&ttime); - png_convert_from_struct_tm(ptime, tbuf); -} -#endif - -/* Initialize png_ptr structure, and allocate any memory needed */ -PNG_FUNCTION(png_structp,PNGAPI -png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) -{ -#ifndef PNG_USER_MEM_SUPPORTED - png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, - error_fn, warn_fn, NULL, NULL, NULL); -#else - return png_create_write_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, NULL, NULL, NULL); -} - -/* Alternate initialize png_ptr structure, and allocate any memory needed */ -PNG_FUNCTION(png_structp,PNGAPI -png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) -{ - png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, - error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); -#endif /* PNG_USER_MEM_SUPPORTED */ - if (png_ptr != NULL) - { - /* Set the zlib control values to defaults; they can be overridden by the - * application after the struct has been created. - */ - png_ptr->zbuffer_size = PNG_ZBUF_SIZE; - - /* The 'zlib_strategy' setting is irrelevant because png_default_claim in - * pngwutil.c defaults it according to whether or not filters will be - * used, and ignores this setting. - */ - png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY; - png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION; - png_ptr->zlib_mem_level = 8; - png_ptr->zlib_window_bits = 15; - png_ptr->zlib_method = 8; - -#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED - png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY; - png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION; - png_ptr->zlib_text_mem_level = 8; - png_ptr->zlib_text_window_bits = 15; - png_ptr->zlib_text_method = 8; -#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ - - /* This is a highly dubious configuration option; by default it is off, - * but it may be appropriate for private builds that are testing - * extensions not conformant to the current specification, or of - * applications that must not fail to write at all costs! - */ -#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED - png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; - /* In stable builds only warn if an application error can be completely - * handled. - */ -#endif - - /* App warnings are warnings in release (or release candidate) builds but - * are errors during development. - */ -#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC - png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; -#endif - - /* TODO: delay this, it can be done in png_init_io() (if the app doesn't - * do it itself) avoiding setting the default function if it is not - * required. - */ - png_set_write_fn(png_ptr, NULL, NULL, NULL); - } - - return png_ptr; -} - - -/* Write a few rows of image data. If the image is interlaced, - * either you will have to write the 7 sub images, or, if you - * have called png_set_interlace_handling(), you will have to - * "write" the image seven times. - */ -void PNGAPI -png_write_rows(png_structrp png_ptr, png_bytepp row, - png_uint_32 num_rows) -{ - png_uint_32 i; /* row counter */ - png_bytepp rp; /* row pointer */ - - png_debug(1, "in png_write_rows"); - - if (png_ptr == NULL) - return; - - /* Loop through the rows */ - for (i = 0, rp = row; i < num_rows; i++, rp++) - { - png_write_row(png_ptr, *rp); - } -} - -/* Write the image. You only need to call this function once, even - * if you are writing an interlaced image. - */ -void PNGAPI -png_write_image(png_structrp png_ptr, png_bytepp image) -{ - png_uint_32 i; /* row index */ - int pass, num_pass; /* pass variables */ - png_bytepp rp; /* points to current row */ - - if (png_ptr == NULL) - return; - - png_debug(1, "in png_write_image"); - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* Initialize interlace handling. If image is not interlaced, - * this will set pass to 1 - */ - num_pass = png_set_interlace_handling(png_ptr); -#else - num_pass = 1; -#endif - /* Loop through passes */ - for (pass = 0; pass < num_pass; pass++) - { - /* Loop through image */ - for (i = 0, rp = image; i < png_ptr->height; i++, rp++) - { - png_write_row(png_ptr, *rp); - } - } -} - -/* Called by user to write a row of image data */ -void PNGAPI -png_write_row(png_structrp png_ptr, png_const_bytep row) -{ - /* 1.5.6: moved from png_struct to be a local structure: */ - png_row_info row_info; - - if (png_ptr == NULL) - return; - - png_debug2(1, "in png_write_row (row %u, pass %d)", - png_ptr->row_number, png_ptr->pass); - - /* Initialize transformations and other stuff if first time */ - if (png_ptr->row_number == 0 && png_ptr->pass == 0) - { - /* Make sure we wrote the header info */ - if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) - png_error(png_ptr, - "png_write_info was never called before png_write_row"); - - /* Check for transforms that have been set but were defined out */ -#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); -#endif - -#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); -#endif -#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ - defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_warning(png_ptr, - "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); -#endif - -#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); -#endif - -#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); -#endif - -#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); -#endif - -#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); -#endif - - png_write_start_row(png_ptr); - } - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* If interlaced and not interested in row, return */ - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) - { - switch (png_ptr->pass) - { - case 0: - if (png_ptr->row_number & 0x07) - { - png_write_finish_row(png_ptr); - return; - } - break; - - case 1: - if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) - { - png_write_finish_row(png_ptr); - return; - } - break; - - case 2: - if ((png_ptr->row_number & 0x07) != 4) - { - png_write_finish_row(png_ptr); - return; - } - break; - - case 3: - if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) - { - png_write_finish_row(png_ptr); - return; - } - break; - - case 4: - if ((png_ptr->row_number & 0x03) != 2) - { - png_write_finish_row(png_ptr); - return; - } - break; - - case 5: - if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) - { - png_write_finish_row(png_ptr); - return; - } - break; - - case 6: - if (!(png_ptr->row_number & 0x01)) - { - png_write_finish_row(png_ptr); - return; - } - break; - - default: /* error: ignore it */ - break; - } - } -#endif - - /* Set up row info for transformations */ - row_info.color_type = png_ptr->color_type; - row_info.width = png_ptr->usr_width; - row_info.channels = png_ptr->usr_channels; - row_info.bit_depth = png_ptr->usr_bit_depth; - row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels); - row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); - - png_debug1(3, "row_info->color_type = %d", row_info.color_type); - png_debug1(3, "row_info->width = %u", row_info.width); - png_debug1(3, "row_info->channels = %d", row_info.channels); - png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth); - png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth); - png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes); - - /* Copy user's row into buffer, leaving room for filter byte. */ - memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes); - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* Handle interlacing */ - if (png_ptr->interlaced && png_ptr->pass < 6 && - (png_ptr->transformations & PNG_INTERLACE)) - { - png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass); - /* This should always get caught above, but still ... */ - if (!(row_info.width)) - { - png_write_finish_row(png_ptr); - return; - } - } -#endif - -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED - /* Handle other transformations */ - if (png_ptr->transformations) - png_do_write_transformations(png_ptr, &row_info); -#endif - - /* At this point the row_info pixel depth must match the 'transformed' depth, - * which is also the output depth. - */ - if (row_info.pixel_depth != png_ptr->pixel_depth || - row_info.pixel_depth != png_ptr->transformed_pixel_depth) - png_error(png_ptr, "internal write transform logic error"); - -#ifdef PNG_MNG_FEATURES_SUPPORTED - /* Write filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not write a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ - if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) - { - /* Intrapixel differencing */ - png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1); - } -#endif - -/* Added at libpng-1.5.10 */ -#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED - /* Check for out-of-range palette index */ - if (row_info.color_type == PNG_COLOR_TYPE_PALETTE && - png_ptr->num_palette_max >= 0) - png_do_check_palette_indexes(png_ptr, &row_info); -#endif - - /* Find a filter if necessary, filter the row and write it out. */ - png_write_find_filter(png_ptr, &row_info); - - if (png_ptr->write_row_fn != NULL) - (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); -} - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -/* Set the automatic flush interval or 0 to turn flushing off */ -void PNGAPI -png_set_flush(png_structrp png_ptr, int nrows) -{ - png_debug(1, "in png_set_flush"); - - if (png_ptr == NULL) - return; - - png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); -} - -/* Flush the current output buffers now */ -void PNGAPI -png_write_flush(png_structrp png_ptr) -{ - png_debug(1, "in png_write_flush"); - - if (png_ptr == NULL) - return; - - /* We have already written out all of the data */ - if (png_ptr->row_number >= png_ptr->num_rows) - return; - - png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH); - png_ptr->flush_rows = 0; - png_flush(png_ptr); -} -#endif /* PNG_WRITE_FLUSH_SUPPORTED */ - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -static void png_reset_filter_heuristics(png_structrp png_ptr);/* forward decl */ -#endif - -/* Free any memory used in png_ptr struct without freeing the struct itself. */ -static void -png_write_destroy(png_structrp png_ptr) -{ - png_debug(1, "in png_write_destroy"); - - /* Free any memory zlib uses */ - if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) - deflateEnd(&png_ptr->zstream); - - /* Free our memory. png_free checks NULL for us. */ - png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); - png_free(png_ptr, png_ptr->row_buf); -#ifdef PNG_WRITE_FILTER_SUPPORTED - png_free(png_ptr, png_ptr->prev_row); - png_free(png_ptr, png_ptr->sub_row); - png_free(png_ptr, png_ptr->up_row); - png_free(png_ptr, png_ptr->avg_row); - png_free(png_ptr, png_ptr->paeth_row); -#endif - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - /* Use this to save a little code space, it doesn't free the filter_costs */ - png_reset_filter_heuristics(png_ptr); - png_free(png_ptr, png_ptr->filter_costs); - png_free(png_ptr, png_ptr->inv_filter_costs); -#endif - -#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - png_free(png_ptr, png_ptr->chunk_list); -#endif - - /* The error handling and memory handling information is left intact at this - * point: the jmp_buf may still have to be freed. See png_destroy_png_struct - * for how this happens. - */ -} - -/* Free all memory used by the write. - * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for - * *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free - * the passed in info_structs but it would quietly fail to free any of the data - * inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it - * has no png_ptr.) - */ -void PNGAPI -png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) -{ - png_debug(1, "in png_destroy_write_struct"); - - if (png_ptr_ptr != NULL) - { - png_structrp png_ptr = *png_ptr_ptr; - - if (png_ptr != NULL) /* added in libpng 1.6.0 */ - { - png_destroy_info_struct(png_ptr, info_ptr_ptr); - - *png_ptr_ptr = NULL; - png_write_destroy(png_ptr); - png_destroy_png_struct(png_ptr); - } - } -} - -/* Allow the application to select one or more row filters to use. */ -void PNGAPI -png_set_filter(png_structrp png_ptr, int method, int filters) -{ - png_debug(1, "in png_set_filter"); - - if (png_ptr == NULL) - return; - -#ifdef PNG_MNG_FEATURES_SUPPORTED - if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (method == PNG_INTRAPIXEL_DIFFERENCING)) - method = PNG_FILTER_TYPE_BASE; - -#endif - if (method == PNG_FILTER_TYPE_BASE) - { - switch (filters & (PNG_ALL_FILTERS | 0x07)) - { -#ifdef PNG_WRITE_FILTER_SUPPORTED - case 5: - case 6: - case 7: png_app_error(png_ptr, "Unknown row filter for method 0"); - /* FALL THROUGH */ -#endif /* PNG_WRITE_FILTER_SUPPORTED */ - case PNG_FILTER_VALUE_NONE: - png_ptr->do_filter = PNG_FILTER_NONE; break; - -#ifdef PNG_WRITE_FILTER_SUPPORTED - case PNG_FILTER_VALUE_SUB: - png_ptr->do_filter = PNG_FILTER_SUB; break; - - case PNG_FILTER_VALUE_UP: - png_ptr->do_filter = PNG_FILTER_UP; break; - - case PNG_FILTER_VALUE_AVG: - png_ptr->do_filter = PNG_FILTER_AVG; break; - - case PNG_FILTER_VALUE_PAETH: - png_ptr->do_filter = PNG_FILTER_PAETH; break; - - default: - png_ptr->do_filter = (png_byte)filters; break; -#else - default: - png_app_error(png_ptr, "Unknown row filter for method 0"); -#endif /* PNG_WRITE_FILTER_SUPPORTED */ - } - - /* If we have allocated the row_buf, this means we have already started - * with the image and we should have allocated all of the filter buffers - * that have been selected. If prev_row isn't already allocated, then - * it is too late to start using the filters that need it, since we - * will be missing the data in the previous row. If an application - * wants to start and stop using particular filters during compression, - * it should start out with all of the filters, and then add and - * remove them after the start of compression. - */ - if (png_ptr->row_buf != NULL) - { -#ifdef PNG_WRITE_FILTER_SUPPORTED - if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } - - if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Up filter after starting"); - png_ptr->do_filter = (png_byte)(png_ptr->do_filter & - ~PNG_FILTER_UP); - } - - else - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } - } - - if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Average filter after starting"); - png_ptr->do_filter = (png_byte)(png_ptr->do_filter & - ~PNG_FILTER_AVG); - } - - else - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } - } - - if ((png_ptr->do_filter & PNG_FILTER_PAETH) && - png_ptr->paeth_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Paeth filter after starting"); - png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); - } - - else - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } - } - - if (png_ptr->do_filter == PNG_NO_FILTERS) -#endif /* PNG_WRITE_FILTER_SUPPORTED */ - png_ptr->do_filter = PNG_FILTER_NONE; - } - } - else - png_error(png_ptr, "Unknown custom filter method"); -} - -/* This allows us to influence the way in which libpng chooses the "best" - * filter for the current scanline. While the "minimum-sum-of-absolute- - * differences metric is relatively fast and effective, there is some - * question as to whether it can be improved upon by trying to keep the - * filtered data going to zlib more consistent, hopefully resulting in - * better compression. - */ -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ -/* Convenience reset API. */ -static void -png_reset_filter_heuristics(png_structrp png_ptr) -{ - /* Clear out any old values in the 'weights' - this must be done because if - * the app calls set_filter_heuristics multiple times with different - * 'num_weights' values we would otherwise potentially have wrong sized - * arrays. - */ - png_ptr->num_prev_filters = 0; - png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; - if (png_ptr->prev_filters != NULL) - { - png_bytep old = png_ptr->prev_filters; - png_ptr->prev_filters = NULL; - png_free(png_ptr, old); - } - if (png_ptr->filter_weights != NULL) - { - png_uint_16p old = png_ptr->filter_weights; - png_ptr->filter_weights = NULL; - png_free(png_ptr, old); - } - - if (png_ptr->inv_filter_weights != NULL) - { - png_uint_16p old = png_ptr->inv_filter_weights; - png_ptr->inv_filter_weights = NULL; - png_free(png_ptr, old); - } - - /* Leave the filter_costs - this array is fixed size. */ -} - -static int -png_init_filter_heuristics(png_structrp png_ptr, int heuristic_method, - int num_weights) -{ - if (png_ptr == NULL) - return 0; - - /* Clear out the arrays */ - png_reset_filter_heuristics(png_ptr); - - /* Check arguments; the 'reset' function makes the correct settings for the - * unweighted case, but we must handle the weight case by initializing the - * arrays for the caller. - */ - if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int i; - - if (num_weights > 0) - { - png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((sizeof (png_byte)) * num_weights)); - - /* To make sure that the weighting starts out fairly */ - for (i = 0; i < num_weights; i++) - { - png_ptr->prev_filters[i] = 255; - } - - png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)((sizeof (png_uint_16)) * num_weights)); - - png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)((sizeof (png_uint_16)) * num_weights)); - - for (i = 0; i < num_weights; i++) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - - /* Safe to set this now */ - png_ptr->num_prev_filters = (png_byte)num_weights; - } - - /* If, in the future, there are other filter methods, this would - * need to be based on png_ptr->filter. - */ - if (png_ptr->filter_costs == NULL) - { - png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST)); - - png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST)); - } - - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) - { - png_ptr->inv_filter_costs[i] = - png_ptr->filter_costs[i] = PNG_COST_FACTOR; - } - - /* All the arrays are inited, safe to set this: */ - png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED; - - /* Return the 'ok' code. */ - return 1; - } - else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT || - heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) - { - return 1; - } - else - { - png_warning(png_ptr, "Unknown filter heuristic method"); - return 0; - } -} - -/* Provide floating and fixed point APIs */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method, - int num_weights, png_const_doublep filter_weights, - png_const_doublep filter_costs) -{ - png_debug(1, "in png_set_filter_heuristics"); - - /* The internal API allocates all the arrays and ensures that the elements of - * those arrays are set to the default value. - */ - if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) - return; - - /* If using the weighted method copy in the weights. */ - if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int i; - for (i = 0; i < num_weights; i++) - { - if (filter_weights[i] <= 0.0) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - - else - { - png_ptr->inv_filter_weights[i] = - (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5); - - png_ptr->filter_weights[i] = - (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5); - } - } - - /* Here is where we set the relative costs of the different filters. We - * should take the desired compression level into account when setting - * the costs, so that Paeth, for instance, has a high relative cost at low - * compression levels, while it has a lower relative cost at higher - * compression settings. The filter types are in order of increasing - * relative cost, so it would be possible to do this with an algorithm. - */ - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0) - { - png_ptr->inv_filter_costs[i] = - (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5); - - png_ptr->filter_costs[i] = - (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5); - } - } -} -#endif /* FLOATING_POINT */ - -#ifdef PNG_FIXED_POINT_SUPPORTED -void PNGAPI -png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method, - int num_weights, png_const_fixed_point_p filter_weights, - png_const_fixed_point_p filter_costs) -{ - png_debug(1, "in png_set_filter_heuristics_fixed"); - - /* The internal API allocates all the arrays and ensures that the elements of - * those arrays are set to the default value. - */ - if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) - return; - - /* If using the weighted method copy in the weights. */ - if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int i; - for (i = 0; i < num_weights; i++) - { - if (filter_weights[i] <= 0) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - - else - { - png_ptr->inv_filter_weights[i] = (png_uint_16) - ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1); - - png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR* - PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]); - } - } - - /* Here is where we set the relative costs of the different filters. We - * should take the desired compression level into account when setting - * the costs, so that Paeth, for instance, has a high relative cost at low - * compression levels, while it has a lower relative cost at higher - * compression settings. The filter types are in order of increasing - * relative cost, so it would be possible to do this with an algorithm. - */ - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) - if (filter_costs[i] >= PNG_FP_1) - { - png_uint_32 tmp; - - /* Use a 32 bit unsigned temporary here because otherwise the - * intermediate value will be a 32 bit *signed* integer (ANSI rules) - * and this will get the wrong answer on division. - */ - tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2); - tmp /= filter_costs[i]; - - png_ptr->inv_filter_costs[i] = (png_uint_16)tmp; - - tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF; - tmp /= PNG_FP_1; - - png_ptr->filter_costs[i] = (png_uint_16)tmp; - } - } -} -#endif /* FIXED_POINT */ -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -void PNGAPI -png_set_compression_level(png_structrp png_ptr, int level) -{ - png_debug(1, "in png_set_compression_level"); - - if (png_ptr == NULL) - return; - - png_ptr->zlib_level = level; -} - -void PNGAPI -png_set_compression_mem_level(png_structrp png_ptr, int mem_level) -{ - png_debug(1, "in png_set_compression_mem_level"); - - if (png_ptr == NULL) - return; - - png_ptr->zlib_mem_level = mem_level; -} - -void PNGAPI -png_set_compression_strategy(png_structrp png_ptr, int strategy) -{ - png_debug(1, "in png_set_compression_strategy"); - - if (png_ptr == NULL) - return; - - /* The flag setting here prevents the libpng dynamic selection of strategy. - */ - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; - png_ptr->zlib_strategy = strategy; -} - -/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a - * smaller value of window_bits if it can do so safely. - */ -void PNGAPI -png_set_compression_window_bits(png_structrp png_ptr, int window_bits) -{ - if (png_ptr == NULL) - return; - - /* Prior to 1.6.0 this would warn but then set the window_bits value, this - * meant that negative window bits values could be selected which would cause - * libpng to write a non-standard PNG file with raw deflate or gzip - * compressed IDAT or ancillary chunks. Such files can be read and there is - * no warning on read, so this seems like a very bad idea. - */ - if (window_bits > 15) - { - png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); - window_bits = 15; - } - - else if (window_bits < 8) - { - png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); - window_bits = 8; - } - - png_ptr->zlib_window_bits = window_bits; -} - -void PNGAPI -png_set_compression_method(png_structrp png_ptr, int method) -{ - png_debug(1, "in png_set_compression_method"); - - if (png_ptr == NULL) - return; - - /* This would produce an invalid PNG file if it worked, but it doesn't and - * deflate will fault it, so it is harmless to just warn here. - */ - if (method != 8) - png_warning(png_ptr, "Only compression method 8 is supported by PNG"); - - png_ptr->zlib_method = method; -} - -/* The following were added to libpng-1.5.4 */ -#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED -void PNGAPI -png_set_text_compression_level(png_structrp png_ptr, int level) -{ - png_debug(1, "in png_set_text_compression_level"); - - if (png_ptr == NULL) - return; - - png_ptr->zlib_text_level = level; -} - -void PNGAPI -png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level) -{ - png_debug(1, "in png_set_text_compression_mem_level"); - - if (png_ptr == NULL) - return; - - png_ptr->zlib_text_mem_level = mem_level; -} - -void PNGAPI -png_set_text_compression_strategy(png_structrp png_ptr, int strategy) -{ - png_debug(1, "in png_set_text_compression_strategy"); - - if (png_ptr == NULL) - return; - - png_ptr->zlib_text_strategy = strategy; -} - -/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a - * smaller value of window_bits if it can do so safely. - */ -void PNGAPI -png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits) -{ - if (png_ptr == NULL) - return; - - if (window_bits > 15) - { - png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); - window_bits = 15; - } - - else if (window_bits < 8) - { - png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); - window_bits = 8; - } - - png_ptr->zlib_text_window_bits = window_bits; -} - -void PNGAPI -png_set_text_compression_method(png_structrp png_ptr, int method) -{ - png_debug(1, "in png_set_text_compression_method"); - - if (png_ptr == NULL) - return; - - if (method != 8) - png_warning(png_ptr, "Only compression method 8 is supported by PNG"); - - png_ptr->zlib_text_method = method; -} -#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ -/* end of API added to libpng-1.5.4 */ - -void PNGAPI -png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn) -{ - if (png_ptr == NULL) - return; - - png_ptr->write_row_fn = write_row_fn; -} - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -void PNGAPI -png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr - write_user_transform_fn) -{ - png_debug(1, "in png_set_write_user_transform_fn"); - - if (png_ptr == NULL) - return; - - png_ptr->transformations |= PNG_USER_TRANSFORM; - png_ptr->write_user_transform_fn = write_user_transform_fn; -} -#endif - - -#ifdef PNG_INFO_IMAGE_SUPPORTED -void PNGAPI -png_write_png(png_structrp png_ptr, png_inforp info_ptr, - int transforms, voidp params) -{ - if (png_ptr == NULL || info_ptr == NULL) - return; - - /* Write the file header information. */ - png_write_info(png_ptr, info_ptr); - - /* ------ these transformations don't touch the info structure ------- */ - -#ifdef PNG_WRITE_INVERT_SUPPORTED - /* Invert monochrome pixels */ - if (transforms & PNG_TRANSFORM_INVERT_MONO) - png_set_invert_mono(png_ptr); -#endif - -#ifdef PNG_WRITE_SHIFT_SUPPORTED - /* Shift the pixels up to a legal bit depth and fill in - * as appropriate to correctly scale the image. - */ - if ((transforms & PNG_TRANSFORM_SHIFT) - && (info_ptr->valid & PNG_INFO_sBIT)) - png_set_shift(png_ptr, &info_ptr->sig_bit); -#endif - -#ifdef PNG_WRITE_PACK_SUPPORTED - /* Pack pixels into bytes */ - if (transforms & PNG_TRANSFORM_PACKING) - png_set_packing(png_ptr); -#endif - -#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED - /* Swap location of alpha bytes from ARGB to RGBA */ - if (transforms & PNG_TRANSFORM_SWAP_ALPHA) - png_set_swap_alpha(png_ptr); -#endif - -#ifdef PNG_WRITE_FILLER_SUPPORTED - /* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */ - if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) - png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); - - else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) - png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); -#endif - -#ifdef PNG_WRITE_BGR_SUPPORTED - /* Flip BGR pixels to RGB */ - if (transforms & PNG_TRANSFORM_BGR) - png_set_bgr(png_ptr); -#endif - -#ifdef PNG_WRITE_SWAP_SUPPORTED - /* Swap bytes of 16-bit files to most significant byte first */ - if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) - png_set_swap(png_ptr); -#endif - -#ifdef PNG_WRITE_PACKSWAP_SUPPORTED - /* Swap bits of 1, 2, 4 bit packed pixel formats */ - if (transforms & PNG_TRANSFORM_PACKSWAP) - png_set_packswap(png_ptr); -#endif - -#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED - /* Invert the alpha channel from opacity to transparency */ - if (transforms & PNG_TRANSFORM_INVERT_ALPHA) - png_set_invert_alpha(png_ptr); -#endif - - /* ----------------------- end of transformations ------------------- */ - - /* Write the bits */ - if (info_ptr->valid & PNG_INFO_IDAT) - png_write_image(png_ptr, info_ptr->row_pointers); - - /* It is REQUIRED to call this to finish writing the rest of the file */ - png_write_end(png_ptr, info_ptr); - - PNG_UNUSED(transforms) /* Quiet compiler warnings */ - PNG_UNUSED(params) -} -#endif - - -#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED -#ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */ -/* Initialize the write structure - general purpose utility. */ -static int -png_image_write_init(png_imagep image) -{ - png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image, - png_safe_error, png_safe_warning); - - if (png_ptr != NULL) - { - png_infop info_ptr = png_create_info_struct(png_ptr); - - if (info_ptr != NULL) - { - png_controlp control = png_voidcast(png_controlp, - png_malloc_warn(png_ptr, (sizeof *control))); - - if (control != NULL) - { - memset(control, 0, (sizeof *control)); - - control->png_ptr = png_ptr; - control->info_ptr = info_ptr; - control->for_write = 1; - - image->opaque = control; - return 1; - } - - /* Error clean up */ - png_destroy_info_struct(png_ptr, &info_ptr); - } - - png_destroy_write_struct(&png_ptr, NULL); - } - - return png_image_error(image, "png_image_write_: out of memory"); -} - -/* Arguments to png_image_write_main: */ -typedef struct -{ - /* Arguments: */ - png_imagep image; - png_const_voidp buffer; - png_int_32 row_stride; - png_const_voidp colormap; - int convert_to_8bit; - /* Local variables: */ - png_const_voidp first_row; - ptrdiff_t row_bytes; - png_voidp local_row; -} png_image_write_control; - -/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to - * do any necessary byte swapping. The component order is defined by the - * png_image format value. - */ -static int -png_write_image_16bit(png_voidp argument) -{ - png_image_write_control *display = png_voidcast(png_image_write_control*, - argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; - - png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, - display->first_row); - png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); - png_uint_16p row_end; - const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; - int aindex = 0; - png_uint_32 y = image->height; - - if (image->format & PNG_FORMAT_FLAG_ALPHA) - { - if (image->format & PNG_FORMAT_FLAG_AFIRST) - { - aindex = -1; - ++input_row; /* To point to the first component */ - ++output_row; - } - - else - aindex = channels; - } - - else - png_error(png_ptr, "png_write_image: internal call error"); - - /* Work out the output row end and count over this, note that the increment - * above to 'row' means that row_end can actually be beyond the end of the - * row; this is correct. - */ - row_end = output_row + image->width * (channels+1); - - while (y-- > 0) - { - png_const_uint_16p in_ptr = input_row; - png_uint_16p out_ptr = output_row; - - while (out_ptr < row_end) - { - const png_uint_16 alpha = in_ptr[aindex]; - png_uint_32 reciprocal = 0; - int c; - - out_ptr[aindex] = alpha; - - /* Calculate a reciprocal. The correct calculation is simply - * component/alpha*65535 << 15. (I.e. 15 bits of precision); this - * allows correct rounding by adding .5 before the shift. 'reciprocal' - * is only initialized when required. - */ - if (alpha > 0 && alpha < 65535) - reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; - - c = channels; - do /* always at least one channel */ - { - png_uint_16 component = *in_ptr++; - - /* The following gives 65535 for an alpha of 0, which is fine, - * otherwise if 0/0 is represented as some other value there is more - * likely to be a discontinuity which will probably damage - * compression when moving from a fully transparent area to a - * nearly transparent one. (The assumption here is that opaque - * areas tend not to be 0 intensity.) - */ - if (component >= alpha) - component = 65535; - - /* component 0 && alpha < 65535) - { - png_uint_32 calc = component * reciprocal; - calc += 16384; /* round to nearest */ - component = (png_uint_16)(calc >> 15); - } - - *out_ptr++ = component; - } - while (--c > 0); - - /* Skip to next component (skip the intervening alpha channel) */ - ++in_ptr; - ++out_ptr; - } - - png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); - input_row += display->row_bytes/(sizeof (png_uint_16)); - } - - return 1; -} - -/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel - * is present it must be removed from the components, the components are then - * written in sRGB encoding. No components are added or removed. - * - * Calculate an alpha reciprocal to reverse pre-multiplication. As above the - * calculation can be done to 15 bits of accuracy; however, the output needs to - * be scaled in the range 0..255*65535, so include that scaling here. - */ -#define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) - -static png_byte -png_unpremultiply(png_uint_32 component, png_uint_32 alpha, - png_uint_32 reciprocal/*from the above macro*/) -{ - /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0 - * is represented as some other value there is more likely to be a - * discontinuity which will probably damage compression when moving from a - * fully transparent area to a nearly transparent one. (The assumption here - * is that opaque areas tend not to be 0 intensity.) - * - * There is a rounding problem here; if alpha is less than 128 it will end up - * as 0 when scaled to 8 bits. To avoid introducing spurious colors into the - * output change for this too. - */ - if (component >= alpha || alpha < 128) - return 255; - - /* component 0) - { - /* The test is that alpha/257 (rounded) is less than 255, the first value - * that becomes 255 is 65407. - * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore, - * be exact!) [Could also test reciprocal != 0] - */ - if (alpha < 65407) - { - component *= reciprocal; - component += 64; /* round to nearest */ - component >>= 7; - } - - else - component *= 255; - - /* Convert the component to sRGB. */ - return (png_byte)PNG_sRGB_FROM_LINEAR(component); - } - - else - return 0; -} - -static int -png_write_image_8bit(png_voidp argument) -{ - png_image_write_control *display = png_voidcast(png_image_write_control*, - argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; - - png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, - display->first_row); - png_bytep output_row = png_voidcast(png_bytep, display->local_row); - png_uint_32 y = image->height; - const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; - - if (image->format & PNG_FORMAT_FLAG_ALPHA) - { - png_bytep row_end; - int aindex; - - if (image->format & PNG_FORMAT_FLAG_AFIRST) - { - aindex = -1; - ++input_row; /* To point to the first component */ - ++output_row; - } - - else - aindex = channels; - - /* Use row_end in place of a loop counter: */ - row_end = output_row + image->width * (channels+1); - - while (y-- > 0) - { - png_const_uint_16p in_ptr = input_row; - png_bytep out_ptr = output_row; - - while (out_ptr < row_end) - { - png_uint_16 alpha = in_ptr[aindex]; - png_byte alphabyte = (png_byte)PNG_DIV257(alpha); - png_uint_32 reciprocal = 0; - int c; - - /* Scale and write the alpha channel. */ - out_ptr[aindex] = alphabyte; - - if (alphabyte > 0 && alphabyte < 255) - reciprocal = UNP_RECIPROCAL(alpha); - - c = channels; - do /* always at least one channel */ - *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); - while (--c > 0); - - /* Skip to next component (skip the intervening alpha channel) */ - ++in_ptr; - ++out_ptr; - } /* while out_ptr < row_end */ - - png_write_row(png_ptr, png_voidcast(png_const_bytep, - display->local_row)); - input_row += display->row_bytes/(sizeof (png_uint_16)); - } /* while y */ - } - - else - { - /* No alpha channel, so the row_end really is the end of the row and it - * is sufficient to loop over the components one by one. - */ - png_bytep row_end = output_row + image->width * channels; - - while (y-- > 0) - { - png_const_uint_16p in_ptr = input_row; - png_bytep out_ptr = output_row; - - while (out_ptr < row_end) - { - png_uint_32 component = *in_ptr++; - - component *= 255; - *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component); - } - - png_write_row(png_ptr, output_row); - input_row += display->row_bytes/(sizeof (png_uint_16)); - } - } - - return 1; -} - -static void -png_image_set_PLTE(png_image_write_control *display) -{ - const png_imagep image = display->image; - const void *cmap = display->colormap; - const int entries = image->colormap_entries > 256 ? 256 : - (int)image->colormap_entries; - - /* NOTE: the caller must check for cmap != NULL and entries != 0 */ - const png_uint_32 format = image->format; - const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); - -# ifdef PNG_FORMAT_BGR_SUPPORTED - const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && - (format & PNG_FORMAT_FLAG_ALPHA) != 0; -# else -# define afirst 0 -# endif - -# ifdef PNG_FORMAT_BGR_SUPPORTED - const int bgr = (format & PNG_FORMAT_FLAG_BGR) ? 2 : 0; -# else -# define bgr 0 -# endif - - int i, num_trans; - png_color palette[256]; - png_byte tRNS[256]; - - memset(tRNS, 255, (sizeof tRNS)); - memset(palette, 0, (sizeof palette)); - - for (i=num_trans=0; i= 3) /* RGB */ - { - palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 * - entry[(2 ^ bgr)]); - palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 * - entry[1]); - palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 * - entry[bgr]); - } - - else /* Gray */ - palette[i].blue = palette[i].red = palette[i].green = - (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry); - } - - else /* alpha */ - { - png_uint_16 alpha = entry[afirst ? 0 : channels-1]; - png_byte alphabyte = (png_byte)PNG_DIV257(alpha); - png_uint_32 reciprocal = 0; - - /* Calculate a reciprocal, as in the png_write_image_8bit code above - * this is designed to produce a value scaled to 255*65535 when - * divided by 128 (i.e. asr 7). - */ - if (alphabyte > 0 && alphabyte < 255) - reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha; - - tRNS[i] = alphabyte; - if (alphabyte < 255) - num_trans = i+1; - - if (channels >= 3) /* RGB */ - { - palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)], - alpha, reciprocal); - palette[i].green = png_unpremultiply(entry[afirst + 1], alpha, - reciprocal); - palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha, - reciprocal); - } - - else /* gray */ - palette[i].blue = palette[i].red = palette[i].green = - png_unpremultiply(entry[afirst], alpha, reciprocal); - } - } - - else /* Color-map has sRGB values */ - { - png_const_bytep entry = png_voidcast(png_const_bytep, cmap); - - entry += i * channels; - - switch (channels) - { - case 4: - tRNS[i] = entry[afirst ? 0 : 3]; - if (tRNS[i] < 255) - num_trans = i+1; - /* FALL THROUGH */ - case 3: - palette[i].blue = entry[afirst + (2 ^ bgr)]; - palette[i].green = entry[afirst + 1]; - palette[i].red = entry[afirst + bgr]; - break; - - case 2: - tRNS[i] = entry[1 ^ afirst]; - if (tRNS[i] < 255) - num_trans = i+1; - /* FALL THROUGH */ - case 1: - palette[i].blue = palette[i].red = palette[i].green = - entry[afirst]; - break; - - default: - break; - } - } - } - -# ifdef afirst -# undef afirst -# endif -# ifdef bgr -# undef bgr -# endif - - png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette, - entries); - - if (num_trans > 0) - png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS, - num_trans, NULL); - - image->colormap_entries = entries; -} - -static int -png_image_write_main(png_voidp argument) -{ - png_image_write_control *display = png_voidcast(png_image_write_control*, - argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; - png_inforp info_ptr = image->opaque->info_ptr; - png_uint_32 format = image->format; - - int colormap = (format & PNG_FORMAT_FLAG_COLORMAP) != 0; - int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */ - int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0; - int write_16bit = linear && !colormap && !display->convert_to_8bit; - -# ifdef PNG_BENIGN_ERRORS_SUPPORTED - /* Make sure we error out on any bad situation */ - png_set_benign_errors(png_ptr, 0/*error*/); -# endif - - /* Default the 'row_stride' parameter if required. */ - if (display->row_stride == 0) - display->row_stride = PNG_IMAGE_ROW_STRIDE(*image); - - /* Set the required transforms then write the rows in the correct order. */ - if (format & PNG_FORMAT_FLAG_COLORMAP) - { - if (display->colormap != NULL && image->colormap_entries > 0) - { - png_uint_32 entries = image->colormap_entries; - - png_set_IHDR(png_ptr, info_ptr, image->width, image->height, - entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)), - PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - png_image_set_PLTE(display); - } - - else - png_error(image->opaque->png_ptr, - "no color-map for color-mapped image"); - } - - else - png_set_IHDR(png_ptr, info_ptr, image->width, image->height, - write_16bit ? 16 : 8, - ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + - ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - /* Counter-intuitively the data transformations must be called *after* - * png_write_info, not before as in the read code, but the 'set' functions - * must still be called before. Just set the color space information, never - * write an interlaced image. - */ - - if (write_16bit) - { - /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */ - png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR); - - if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB)) - png_set_cHRM_fixed(png_ptr, info_ptr, - /* color x y */ - /* white */ 31270, 32900, - /* red */ 64000, 33000, - /* green */ 30000, 60000, - /* blue */ 15000, 6000 - ); - } - - else if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB)) - png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL); - - /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit - * space must still be gamma encoded. - */ - else - png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); - - /* Write the file header. */ - png_write_info(png_ptr, info_ptr); - - /* Now set up the data transformations (*after* the header is written), - * remove the handled transformations from the 'format' flags for checking. - * - * First check for a little endian system if writing 16 bit files. - */ - if (write_16bit) - { - PNG_CONST png_uint_16 le = 0x0001; - - if (*(png_const_bytep)&le) - png_set_swap(png_ptr); - } - -# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED - if (format & PNG_FORMAT_FLAG_BGR) - { - if (!colormap && (format & PNG_FORMAT_FLAG_COLOR) != 0) - png_set_bgr(png_ptr); - format &= ~PNG_FORMAT_FLAG_BGR; - } -# endif - -# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED - if (format & PNG_FORMAT_FLAG_AFIRST) - { - if (!colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0) - png_set_swap_alpha(png_ptr); - format &= ~PNG_FORMAT_FLAG_AFIRST; - } -# endif - - /* If there are 16 or fewer color-map entries we wrote a lower bit depth - * above, but the application data is still byte packed. - */ - if (colormap && image->colormap_entries <= 16) - png_set_packing(png_ptr); - - /* That should have handled all (both) the transforms. */ - if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR | - PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0) - png_error(png_ptr, "png_write_image: unsupported transformation"); - - { - png_const_bytep row = png_voidcast(png_const_bytep, display->buffer); - ptrdiff_t row_bytes = display->row_stride; - - if (linear) - row_bytes *= (sizeof (png_uint_16)); - - if (row_bytes < 0) - row += (image->height-1) * (-row_bytes); - - display->first_row = row; - display->row_bytes = row_bytes; - } - - /* Apply 'fast' options if the flag is set. */ - if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0) - { - png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS); - /* NOTE: determined by experiment using pngstest, this reflects some - * balance between the time to write the image once and the time to read - * it about 50 times. The speed-up in pngstest was about 10-20% of the - * total (user) time on a heavily loaded system. - */ - png_set_compression_level(png_ptr, 3); - } - - /* Check for the cases that currently require a pre-transform on the row - * before it is written. This only applies when the input is 16-bit and - * either there is an alpha channel or it is converted to 8-bit. - */ - if ((linear && alpha) || (!colormap && display->convert_to_8bit)) - { - png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, - png_get_rowbytes(png_ptr, info_ptr))); - int result; - - display->local_row = row; - if (write_16bit) - result = png_safe_execute(image, png_write_image_16bit, display); - else - result = png_safe_execute(image, png_write_image_8bit, display); - display->local_row = NULL; - - png_free(png_ptr, row); - - /* Skip the 'write_end' on error: */ - if (!result) - return 0; - } - - /* Otherwise this is the case where the input is in a format currently - * supported by the rest of the libpng write code; call it directly. - */ - else - { - png_const_bytep row = png_voidcast(png_const_bytep, display->first_row); - ptrdiff_t row_bytes = display->row_bytes; - png_uint_32 y = image->height; - - while (y-- > 0) - { - png_write_row(png_ptr, row); - row += row_bytes; - } - } - - png_write_end(png_ptr, info_ptr); - return 1; -} - -int PNGAPI -png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, - const void *buffer, png_int_32 row_stride, const void *colormap) -{ - /* Write the image to the given (FILE*). */ - if (image != NULL && image->version == PNG_IMAGE_VERSION) - { - if (file != NULL) - { - if (png_image_write_init(image)) - { - png_image_write_control display; - int result; - - /* This is slightly evil, but png_init_io doesn't do anything other - * than this and we haven't changed the standard IO functions so - * this saves a 'safe' function. - */ - image->opaque->png_ptr->io_ptr = file; - - memset(&display, 0, (sizeof display)); - display.image = image; - display.buffer = buffer; - display.row_stride = row_stride; - display.colormap = colormap; - display.convert_to_8bit = convert_to_8bit; - - result = png_safe_execute(image, png_image_write_main, &display); - png_image_free(image); - return result; - } - - else - return 0; - } - - else - return png_image_error(image, - "png_image_write_to_stdio: invalid argument"); - } - - else if (image != NULL) - return png_image_error(image, - "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); - - else - return 0; -} - -int PNGAPI -png_image_write_to_file(png_imagep image, const char *file_name, - int convert_to_8bit, const void *buffer, png_int_32 row_stride, - const void *colormap) -{ - /* Write the image to the named file. */ - if (image != NULL && image->version == PNG_IMAGE_VERSION) - { - if (file_name != NULL) - { - FILE *fp = fopen(file_name, "wb"); - - if (fp != NULL) - { - if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, - row_stride, colormap)) - { - int error; /* from fflush/fclose */ - - /* Make sure the file is flushed correctly. */ - if (fflush(fp) == 0 && ferror(fp) == 0) - { - if (fclose(fp) == 0) - return 1; - - error = errno; /* from fclose */ - } - - else - { - error = errno; /* from fflush or ferror */ - (void)fclose(fp); - } - - (void)remove(file_name); - /* The image has already been cleaned up; this is just used to - * set the error (because the original write succeeded). - */ - return png_image_error(image, strerror(error)); - } - - else - { - /* Clean up: just the opened file. */ - (void)fclose(fp); - (void)remove(file_name); - return 0; - } - } - - else - return png_image_error(image, strerror(errno)); - } - - else - return png_image_error(image, - "png_image_write_to_file: invalid argument"); - } - - else if (image != NULL) - return png_image_error(image, - "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); - - else - return 0; -} -#endif /* PNG_STDIO_SUPPORTED */ -#endif /* SIMPLIFIED_WRITE */ -#endif /* PNG_WRITE_SUPPORTED */ + +/* pngwrite.c - general routines to write a PNG file + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" +#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) +# include +#endif + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +/* Write out all the unknown chunks for the current given location */ +static void +write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, + unsigned int where) +{ + if (info_ptr->unknown_chunks_num) + { + png_const_unknown_chunkp up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + ++up) + if (up->location & where) + { + /* If per-chunk unknown chunk handling is enabled use it, otherwise + * just write the chunks the application has set. + */ +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + int keep = png_handle_as_unknown(png_ptr, up->name); + + /* NOTE: this code is radically different from the read side in the + * matter of handling an ancillary unknown chunk. In the read side + * the default behavior is to discard it, in the code below the default + * behavior is to write it. Critical chunks are, however, only + * written if explicitly listed or if the default is set to write all + * unknown chunks. + * + * The default handling is also slightly weird - it is not possible to + * stop the writing of all unsafe-to-copy chunks! + * + * TODO: REVIEW: this would seem to be a bug. + */ + if (keep != PNG_HANDLE_CHUNK_NEVER && + ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ || + keep == PNG_HANDLE_CHUNK_ALWAYS || + (keep == PNG_HANDLE_CHUNK_AS_DEFAULT && + png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS))) +#endif + { + /* TODO: review, what is wrong with a zero length unknown chunk? */ + if (up->size == 0) + png_warning(png_ptr, "Writing zero-length unknown chunk"); + + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +} +#endif /* PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED */ + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + /* Write PNG signature */ + png_write_sig(png_ptr); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \ + (png_ptr->mng_features_permitted)) + { + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted = 0; + } +#endif + + /* Write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + info_ptr->interlace_type +#else + 0 +#endif + ); + + /* The rest of these check to see if the valid field has the appropriate + * flag set, and if it does, writes the chunk. + * + * 1.6.0: COLORSPACE support controls the writing of these chunks too, and + * the chunks will be written if the WRITE routine is there and information + * is available in the COLORSPACE. (See png_colorspace_sync_info in png.c + * for where the valid flags get set.) + * + * Under certain circumstances the colorspace can be invalidated without + * syncing the info_struct 'valid' flags; this happens if libpng detects and + * error and calls png_error while the color space is being set, yet the + * application continues writing the PNG. So check the 'invalid' flag here + * too. + */ +#ifdef PNG_GAMMA_SUPPORTED +# ifdef PNG_WRITE_gAMA_SUPPORTED + if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && + (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) && + (info_ptr->valid & PNG_INFO_gAMA)) + png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma); +# endif +#endif + +#ifdef PNG_COLORSPACE_SUPPORTED + /* Write only one of sRGB or an ICC profile. If a profile was supplied + * and it matches one of the known sRGB ones issue a warning. + */ +# ifdef PNG_WRITE_iCCP_SUPPORTED + if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && + (info_ptr->valid & PNG_INFO_iCCP)) + { +# ifdef PNG_WRITE_sRGB_SUPPORTED + if (info_ptr->valid & PNG_INFO_sRGB) + png_app_warning(png_ptr, + "profile matches sRGB but writing iCCP instead"); +# endif + + png_write_iCCP(png_ptr, info_ptr->iccp_name, + info_ptr->iccp_profile); + } +# ifdef PNG_WRITE_sRGB_SUPPORTED + else +# endif +# endif + +# ifdef PNG_WRITE_sRGB_SUPPORTED + if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && + (info_ptr->valid & PNG_INFO_sRGB)) + png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); +# endif /* WRITE_sRGB */ +#endif /* COLORSPACE */ + +#ifdef PNG_WRITE_sBIT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif + +#ifdef PNG_COLORSPACE_SUPPORTED +# ifdef PNG_WRITE_cHRM_SUPPORTED + if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) && + (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) && + (info_ptr->valid & PNG_INFO_cHRM)) + png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy); +# endif +#endif + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); +#endif + + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images"); + +#ifdef PNG_WRITE_tRNS_SUPPORTED + if (info_ptr->valid & PNG_INFO_tRNS) + { +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j, jend; + + jend = info_ptr->num_trans; + if (jend > PNG_MAX_PALETTE_LENGTH) + jend = PNG_MAX_PALETTE_LENGTH; + + for (j = 0; jtrans_alpha[j] = + (png_byte)(255 - info_ptr->trans_alpha[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#ifdef PNG_WRITE_bKGD_SUPPORTED + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_sCAL) + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#endif /* sCAL */ + +#ifdef PNG_WRITE_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif /* pHYs */ + +#ifdef PNG_WRITE_tIME_SUPPORTED + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif /* tIME */ + +#ifdef PNG_WRITE_sPLT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif /* sPLT */ + +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; +#else + /* Can't get here */ + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + } + } +#endif /* tEXt */ + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE); +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structrp png_ptr, png_inforp info_ptr) +{ + png_debug(1, "in png_write_end"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); + +#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED + if (png_ptr->num_palette_max > png_ptr->num_palette) + png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); +#endif + + /* See if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#ifdef PNG_WRITE_TEXT_SUPPORTED + int i; /* local index variable */ +#endif +#ifdef PNG_WRITE_tIME_SUPPORTED + /* Check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + +#endif +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT); +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* Write end of PNG file */ + png_write_IEND(png_ptr); + /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, + * and restored again in libpng-1.2.30, may cause some applications that + * do not set png_ptr->output_flush_fn to crash. If your application + * experiences a problem, please try building libpng with + * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to + * png-mng-implement at lists.sf.net . + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED + png_flush(png_ptr); +# endif +#endif +} + +#ifdef PNG_CONVERT_tIME_SUPPORTED +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm"); + + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t"); + + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) +{ +#ifndef PNG_USER_MEM_SUPPORTED + png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + error_fn, warn_fn, NULL, NULL, NULL); +#else + return png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +{ + png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr != NULL) + { + /* Set the zlib control values to defaults; they can be overridden by the + * application after the struct has been created. + */ + png_ptr->zbuffer_size = PNG_ZBUF_SIZE; + + /* The 'zlib_strategy' setting is irrelevant because png_default_claim in + * pngwutil.c defaults it according to whether or not filters will be + * used, and ignores this setting. + */ + png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY; + png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION; + png_ptr->zlib_mem_level = 8; + png_ptr->zlib_window_bits = 15; + png_ptr->zlib_method = 8; + +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED + png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY; + png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION; + png_ptr->zlib_text_mem_level = 8; + png_ptr->zlib_text_window_bits = 15; + png_ptr->zlib_text_method = 8; +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ + + /* This is a highly dubious configuration option; by default it is off, + * but it may be appropriate for private builds that are testing + * extensions not conformant to the current specification, or of + * applications that must not fail to write at all costs! + */ +#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + /* In stable builds only warn if an application error can be completely + * handled. + */ +#endif + + /* App warnings are warnings in release (or release candidate) builds but + * are errors during development. + */ +#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC + png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; +#endif + + /* TODO: delay this, it can be done in png_init_io() (if the app doesn't + * do it itself) avoiding setting the default function if it is not + * required. + */ + png_set_write_fn(png_ptr, NULL, NULL, NULL); + } + + return png_ptr; +} + + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structrp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* row counter */ + png_bytepp rp; /* row pointer */ + + png_debug(1, "in png_write_rows"); + + if (png_ptr == NULL) + return; + + /* Loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structrp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* row index */ + int pass, num_pass; /* pass variables */ + png_bytepp rp; /* points to current row */ + + if (png_ptr == NULL) + return; + + png_debug(1, "in png_write_image"); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Initialize interlace handling. If image is not interlaced, + * this will set pass to 1 + */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* Loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* Loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Performs intrapixel differencing */ +static void +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel"); + + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp + 1)) & 0xff); + *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ + +/* Called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structrp png_ptr, png_const_bytep row) +{ + /* 1.5.6: moved from png_struct to be a local structure: */ + png_row_info row_info; + + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_write_row (row %u, pass %d)", + png_ptr->row_number, png_ptr->pass); + + /* Initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row"); + + /* Check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, + "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); +#endif + + png_write_start_row(png_ptr); + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + + default: /* error: ignore it */ + break; + } + } +#endif + + /* Set up row info for transformations */ + row_info.color_type = png_ptr->color_type; + row_info.width = png_ptr->usr_width; + row_info.channels = png_ptr->usr_channels; + row_info.bit_depth = png_ptr->usr_bit_depth; + row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels); + row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); + + png_debug1(3, "row_info->color_type = %d", row_info.color_type); + png_debug1(3, "row_info->width = %u", row_info.width); + png_debug1(3, "row_info->channels = %d", row_info.channels); + png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass); + /* This should always get caught above, but still ... */ + if (row_info.width == 0) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED + /* Handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr, &row_info); +#endif + + /* At this point the row_info pixel depth must match the 'transformed' depth, + * which is also the output depth. + */ + if (row_info.pixel_depth != png_ptr->pixel_depth || + row_info.pixel_depth != png_ptr->transformed_pixel_depth) + png_error(png_ptr, "internal write transform logic error"); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1); + } +#endif + +/* Added at libpng-1.5.10 */ +#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED + /* Check for out-of-range palette index */ + if (row_info.color_type == PNG_COLOR_TYPE_PALETTE && + png_ptr->num_palette_max >= 0) + png_do_check_palette_indexes(png_ptr, &row_info); +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &row_info); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structrp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush"); + + if (png_ptr == NULL) + return; + + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* Flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structrp png_ptr) +{ + png_debug(1, "in png_write_flush"); + + if (png_ptr == NULL) + return; + + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH); + png_ptr->flush_rows = 0; + png_flush(png_ptr); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +static void png_reset_filter_heuristics(png_structrp png_ptr);/* forward decl */ +#endif + +/* Free any memory used in png_ptr struct without freeing the struct itself. */ +static void +png_write_destroy(png_structrp png_ptr) +{ + png_debug(1, "in png_write_destroy"); + + /* Free any memory zlib uses */ + if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) + deflateEnd(&png_ptr->zstream); + + /* Free our memory. png_free checks NULL for us. */ + png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); + png_free(png_ptr, png_ptr->row_buf); +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + png_free(png_ptr, png_ptr->paeth_row); +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Use this to save a little code space, it doesn't free the filter_costs */ + png_reset_filter_heuristics(png_ptr); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + png_free(png_ptr, png_ptr->chunk_list); +#endif + + /* The error handling and memory handling information is left intact at this + * point: the jmp_buf may still have to be freed. See png_destroy_png_struct + * for how this happens. + */ +} + +/* Free all memory used by the write. + * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for + * *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free + * the passed in info_structs but it would quietly fail to free any of the data + * inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it + * has no png_ptr.) + */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_debug(1, "in png_destroy_write_struct"); + + if (png_ptr_ptr != NULL) + { + png_structrp png_ptr = *png_ptr_ptr; + + if (png_ptr != NULL) /* added in libpng 1.6.0 */ + { + png_destroy_info_struct(png_ptr, info_ptr_ptr); + + *png_ptr_ptr = NULL; + png_write_destroy(png_ptr); + png_destroy_png_struct(png_ptr); + } + } +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structrp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; +#endif + + /* The only supported method, except for the check above, is + * PNG_FILTER_TYPE_BASE. The code below does not use 'method' other than + * for the check, so just keep going if png_app_error returns. + */ + if (method != PNG_FILTER_TYPE_BASE) + png_app_error(png_ptr, "Unknown custom filter method"); + + /* If filter writing is not supported the 'filters' value must be zero, + * otherwise the value must be a single, valid, filter value or a set of the + * mask values. The defines in png.h are such that the filter masks used in + * this API and internally are 1<<(3+value), value is in the range 0..4, so + * this fits in a byte. + */ +# ifdef PNG_WRITE_FILTER_SUPPORTED + /* Notice that PNG_NO_FILTERS is 0 and passes this test; this is OK + * because filters then gets set to PNG_FILTER_NONE, as is required. + */ + if (filters < PNG_FILTER_VALUE_LAST) + filters = 0x08 << filters; + + else if ((filters & ~PNG_ALL_FILTERS) != 0) + { + png_app_error(png_ptr, "png_set_filter: invalid filters mask/value"); + + /* For compatibility with the previous behavior assume a mask value was + * passed and ignore the non-mask bits. + */ + filters &= PNG_ALL_FILTERS; + + /* For a possibly foolish consistency (it shouldn't matter) set + * PNG_FILTER_NONE rather than 0. + */ + if (filters == 0) + filters = PNG_FILTER_NONE; + } +# else + /* PNG_FILTER_VALUE_NONE and PNG_NO_FILTERS are both 0. */ + if (filters != 0 && filters != PNG_FILTER_NONE) + png_app_error(png_ptr, "png_set_filter: no filters supported"); + + filters = PNG_FILTER_NONE; +# endif + +# ifdef PNG_WRITE_FILTER_SUPPORTED + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + * + * NOTE: this is a nasty constraint on the code, because it means that the + * prev_row buffer must be maintained even if there are currently no + * 'prev_row' requiring filters active. + */ + if (png_ptr->row_buf != NULL) + { + /* Repeat the checks in png_write_start_row; 1 pixel high or wide + * images cannot benefit from certain filters. If this isn't done here + * the check below will fire on 1 pixel high images. + */ + if (png_ptr->height == 1) + filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); + + if (png_ptr->width == 1) + filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH); + + if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0 + && png_ptr->prev_row == NULL) + { + /* This is the error case, however it is benign - the previous row + * is not available so the filter can't be used. Just warn here. + */ + png_app_warning(png_ptr, + "png_set_filter: UP/AVG/PAETH cannot be added after start"); + filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); + } + + /* Allocate any required buffers that have not already been allocated. + */ + png_write_alloc_filter_row_buffers(png_ptr, filters); + } +# endif /* PNG_WRITE_FILTER_SUPPORTED */ + + /* Finally store the value. + * TODO: this field could probably be removed if neither READ nor + * WRITE_FILTER are supported. + */ + png_ptr->do_filter = (png_byte)filters; /* SAFE: checked above */ +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ +/* Convenience reset API. */ +static void +png_reset_filter_heuristics(png_structrp png_ptr) +{ + /* Clear out any old values in the 'weights' - this must be done because if + * the app calls set_filter_heuristics multiple times with different + * 'num_weights' values we would otherwise potentially have wrong sized + * arrays. + */ + png_ptr->num_prev_filters = 0; + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + if (png_ptr->prev_filters != NULL) + { + png_bytep old = png_ptr->prev_filters; + png_ptr->prev_filters = NULL; + png_free(png_ptr, old); + } + if (png_ptr->filter_weights != NULL) + { + png_uint_16p old = png_ptr->filter_weights; + png_ptr->filter_weights = NULL; + png_free(png_ptr, old); + } + + if (png_ptr->inv_filter_weights != NULL) + { + png_uint_16p old = png_ptr->inv_filter_weights; + png_ptr->inv_filter_weights = NULL; + png_free(png_ptr, old); + } + + /* Leave the filter_costs - this array is fixed size. */ +} + +static int +png_init_filter_heuristics(png_structrp png_ptr, int heuristic_method, + int num_weights) +{ + if (png_ptr == NULL) + return 0; + + /* Clear out the arrays */ + png_reset_filter_heuristics(png_ptr); + + /* Check arguments; the 'reset' function makes the correct settings for the + * unweighted case, but we must handle the weight case by initializing the + * arrays for the caller. + */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + + if (num_weights > 0) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)((sizeof (png_byte)) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)((sizeof (png_uint_16)) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)((sizeof (png_uint_16)) * num_weights)); + + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + /* Safe to set this now */ + png_ptr->num_prev_filters = (png_byte)num_weights; + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST)); + } + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + + /* All the arrays are inited, safe to set this: */ + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED; + + /* Return the 'ok' code. */ + return 1; + } + else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + return 1; + } + else + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return 0; + } +} + +/* Provide floating and fixed point APIs */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method, + int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5); + + png_ptr->filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5); + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5); + + png_ptr->filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5); + } + } +} +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method, + int num_weights, png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics_fixed"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + else + { + png_ptr->inv_filter_weights[i] = (png_uint_16) + ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1); + + png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR* + PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]); + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + if (filter_costs[i] >= PNG_FP_1) + { + png_uint_32 tmp; + + /* Use a 32 bit unsigned temporary here because otherwise the + * intermediate value will be a 32 bit *signed* integer (ANSI rules) + * and this will get the wrong answer on division. + */ + tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2); + tmp /= filter_costs[i]; + + png_ptr->inv_filter_costs[i] = (png_uint_16)tmp; + + tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF; + tmp /= PNG_FP_1; + + png_ptr->filter_costs[i] = (png_uint_16)tmp; + } + } +} +#endif /* FIXED_POINT */ +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structrp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structrp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structrp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy"); + + if (png_ptr == NULL) + return; + + /* The flag setting here prevents the libpng dynamic selection of strategy. + */ + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +void PNGAPI +png_set_compression_window_bits(png_structrp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + + /* Prior to 1.6.0 this would warn but then set the window_bits value, this + * meant that negative window bits values could be selected which would cause + * libpng to write a non-standard PNG file with raw deflate or gzip + * compressed IDAT or ancillary chunks. Such files can be read and there is + * no warning on read, so this seems like a very bad idea. + */ + if (window_bits > 15) + { + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + window_bits = 15; + } + + else if (window_bits < 8) + { + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); + window_bits = 8; + } + + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structrp png_ptr, int method) +{ + png_debug(1, "in png_set_compression_method"); + + if (png_ptr == NULL) + return; + + /* This would produce an invalid PNG file if it worked, but it doesn't and + * deflate will fault it, so it is harmless to just warn here. + */ + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + + png_ptr->zlib_method = method; +} + +/* The following were added to libpng-1.5.4 */ +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +void PNGAPI +png_set_text_compression_level(png_structrp png_ptr, int level) +{ + png_debug(1, "in png_set_text_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->zlib_text_level = level; +} + +void PNGAPI +png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_text_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->zlib_text_mem_level = mem_level; +} + +void PNGAPI +png_set_text_compression_strategy(png_structrp png_ptr, int strategy) +{ + png_debug(1, "in png_set_text_compression_strategy"); + + if (png_ptr == NULL) + return; + + png_ptr->zlib_text_strategy = strategy; +} + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +void PNGAPI +png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + + if (window_bits > 15) + { + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + window_bits = 15; + } + + else if (window_bits < 8) + { + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); + window_bits = 8; + } + + png_ptr->zlib_text_window_bits = window_bits; +} + +void PNGAPI +png_set_text_compression_method(png_structrp png_ptr, int method) +{ + png_debug(1, "in png_set_text_compression_method"); + + if (png_ptr == NULL) + return; + + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + + png_ptr->zlib_text_method = method; +} +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ +/* end of API added to libpng-1.5.4 */ + +void PNGAPI +png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->write_row_fn = write_row_fn; +} + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +void PNGAPI +png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_write_png(png_structrp png_ptr, png_inforp info_ptr, + int transforms, voidp params) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + if ((info_ptr->valid & PNG_INFO_IDAT) == 0) + { + png_app_error(png_ptr, "no rows for png_write_image to write"); + return; + } + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + + /* Invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) +#ifdef PNG_WRITE_INVERT_SUPPORTED + png_set_invert_mono(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported"); +#endif + + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if (transforms & PNG_TRANSFORM_SHIFT) +#ifdef PNG_WRITE_SHIFT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sBIT) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported"); +#endif + + /* Pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) +#ifdef PNG_WRITE_PACK_SUPPORTED + png_set_packing(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported"); +#endif + + /* Swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + png_set_swap_alpha(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported"); +#endif + + /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into + * RGB, note that the code expects the input color type to be G or RGB; no + * alpha channel. + */ + if (transforms & + (PNG_TRANSFORM_STRIP_FILLER_AFTER|PNG_TRANSFORM_STRIP_FILLER_BEFORE)) + { +#ifdef PNG_WRITE_FILLER_SUPPORTED + if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) + { + if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) + png_app_error(png_ptr, + "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported"); + + /* Continue if ignored - this is the pre-1.6.10 behavior */ + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + } + + else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported"); +#endif + } + + /* Flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) +#ifdef PNG_WRITE_BGR_SUPPORTED + png_set_bgr(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported"); +#endif + + /* Swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) +#ifdef PNG_WRITE_SWAP_SUPPORTED + png_set_swap(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported"); +#endif + + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + png_set_packswap(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported"); +#endif + + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + png_set_invert_alpha(png_ptr); +#else + png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported"); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* Write the bits */ + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + PNG_UNUSED(params) +} +#endif + + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +#ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */ +/* Initialize the write structure - general purpose utility. */ +static int +png_image_write_init(png_imagep image) +{ + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image, + png_safe_error, png_safe_warning); + + if (png_ptr != NULL) + { + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (info_ptr != NULL) + { + png_controlp control = png_voidcast(png_controlp, + png_malloc_warn(png_ptr, (sizeof *control))); + + if (control != NULL) + { + memset(control, 0, (sizeof *control)); + + control->png_ptr = png_ptr; + control->info_ptr = info_ptr; + control->for_write = 1; + + image->opaque = control; + return 1; + } + + /* Error clean up */ + png_destroy_info_struct(png_ptr, &info_ptr); + } + + png_destroy_write_struct(&png_ptr, NULL); + } + + return png_image_error(image, "png_image_write_: out of memory"); +} + +/* Arguments to png_image_write_main: */ +typedef struct +{ + /* Arguments: */ + png_imagep image; + png_const_voidp buffer; + png_int_32 row_stride; + png_const_voidp colormap; + int convert_to_8bit; + /* Local variables: */ + png_const_voidp first_row; + ptrdiff_t row_bytes; + png_voidp local_row; +} png_image_write_control; + +/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to + * do any necessary byte swapping. The component order is defined by the + * png_image format value. + */ +static int +png_write_image_16bit(png_voidp argument) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + + png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, + display->first_row); + png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); + png_uint_16p row_end; + const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; + int aindex = 0; + png_uint_32 y = image->height; + + if (image->format & PNG_FORMAT_FLAG_ALPHA) + { +# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED + if (image->format & PNG_FORMAT_FLAG_AFIRST) + { + aindex = -1; + ++input_row; /* To point to the first component */ + ++output_row; + } + + else +# endif + aindex = channels; + } + + else + png_error(png_ptr, "png_write_image: internal call error"); + + /* Work out the output row end and count over this, note that the increment + * above to 'row' means that row_end can actually be beyond the end of the + * row; this is correct. + */ + row_end = output_row + image->width * (channels+1); + + while (y-- > 0) + { + png_const_uint_16p in_ptr = input_row; + png_uint_16p out_ptr = output_row; + + while (out_ptr < row_end) + { + const png_uint_16 alpha = in_ptr[aindex]; + png_uint_32 reciprocal = 0; + int c; + + out_ptr[aindex] = alpha; + + /* Calculate a reciprocal. The correct calculation is simply + * component/alpha*65535 << 15. (I.e. 15 bits of precision); this + * allows correct rounding by adding .5 before the shift. 'reciprocal' + * is only initialized when required. + */ + if (alpha > 0 && alpha < 65535) + reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; + + c = channels; + do /* always at least one channel */ + { + png_uint_16 component = *in_ptr++; + + /* The following gives 65535 for an alpha of 0, which is fine, + * otherwise if 0/0 is represented as some other value there is more + * likely to be a discontinuity which will probably damage + * compression when moving from a fully transparent area to a + * nearly transparent one. (The assumption here is that opaque + * areas tend not to be 0 intensity.) + */ + if (component >= alpha) + component = 65535; + + /* component 0 && alpha < 65535) + { + png_uint_32 calc = component * reciprocal; + calc += 16384; /* round to nearest */ + component = (png_uint_16)(calc >> 15); + } + + *out_ptr++ = component; + } + while (--c > 0); + + /* Skip to next component (skip the intervening alpha channel) */ + ++in_ptr; + ++out_ptr; + } + + png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); + input_row += display->row_bytes/(sizeof (png_uint_16)); + } + + return 1; +} + +/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel + * is present it must be removed from the components, the components are then + * written in sRGB encoding. No components are added or removed. + * + * Calculate an alpha reciprocal to reverse pre-multiplication. As above the + * calculation can be done to 15 bits of accuracy; however, the output needs to + * be scaled in the range 0..255*65535, so include that scaling here. + */ +#define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) + +static png_byte +png_unpremultiply(png_uint_32 component, png_uint_32 alpha, + png_uint_32 reciprocal/*from the above macro*/) +{ + /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0 + * is represented as some other value there is more likely to be a + * discontinuity which will probably damage compression when moving from a + * fully transparent area to a nearly transparent one. (The assumption here + * is that opaque areas tend not to be 0 intensity.) + * + * There is a rounding problem here; if alpha is less than 128 it will end up + * as 0 when scaled to 8 bits. To avoid introducing spurious colors into the + * output change for this too. + */ + if (component >= alpha || alpha < 128) + return 255; + + /* component 0) + { + /* The test is that alpha/257 (rounded) is less than 255, the first value + * that becomes 255 is 65407. + * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore, + * be exact!) [Could also test reciprocal != 0] + */ + if (alpha < 65407) + { + component *= reciprocal; + component += 64; /* round to nearest */ + component >>= 7; + } + + else + component *= 255; + + /* Convert the component to sRGB. */ + return (png_byte)PNG_sRGB_FROM_LINEAR(component); + } + + else + return 0; +} + +static int +png_write_image_8bit(png_voidp argument) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + + png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, + display->first_row); + png_bytep output_row = png_voidcast(png_bytep, display->local_row); + png_uint_32 y = image->height; + const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; + + if (image->format & PNG_FORMAT_FLAG_ALPHA) + { + png_bytep row_end; + int aindex; + +# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED + if (image->format & PNG_FORMAT_FLAG_AFIRST) + { + aindex = -1; + ++input_row; /* To point to the first component */ + ++output_row; + } + + else +# endif + aindex = channels; + + /* Use row_end in place of a loop counter: */ + row_end = output_row + image->width * (channels+1); + + while (y-- > 0) + { + png_const_uint_16p in_ptr = input_row; + png_bytep out_ptr = output_row; + + while (out_ptr < row_end) + { + png_uint_16 alpha = in_ptr[aindex]; + png_byte alphabyte = (png_byte)PNG_DIV257(alpha); + png_uint_32 reciprocal = 0; + int c; + + /* Scale and write the alpha channel. */ + out_ptr[aindex] = alphabyte; + + if (alphabyte > 0 && alphabyte < 255) + reciprocal = UNP_RECIPROCAL(alpha); + + c = channels; + do /* always at least one channel */ + *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); + while (--c > 0); + + /* Skip to next component (skip the intervening alpha channel) */ + ++in_ptr; + ++out_ptr; + } /* while out_ptr < row_end */ + + png_write_row(png_ptr, png_voidcast(png_const_bytep, + display->local_row)); + input_row += display->row_bytes/(sizeof (png_uint_16)); + } /* while y */ + } + + else + { + /* No alpha channel, so the row_end really is the end of the row and it + * is sufficient to loop over the components one by one. + */ + png_bytep row_end = output_row + image->width * channels; + + while (y-- > 0) + { + png_const_uint_16p in_ptr = input_row; + png_bytep out_ptr = output_row; + + while (out_ptr < row_end) + { + png_uint_32 component = *in_ptr++; + + component *= 255; + *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component); + } + + png_write_row(png_ptr, output_row); + input_row += display->row_bytes/(sizeof (png_uint_16)); + } + } + + return 1; +} + +static void +png_image_set_PLTE(png_image_write_control *display) +{ + const png_imagep image = display->image; + const void *cmap = display->colormap; + const int entries = image->colormap_entries > 256 ? 256 : + (int)image->colormap_entries; + + /* NOTE: the caller must check for cmap != NULL and entries != 0 */ + const png_uint_32 format = image->format; + const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); + +# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\ + defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED) + const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && + (format & PNG_FORMAT_FLAG_ALPHA) != 0; +# else +# define afirst 0 +# endif + +# ifdef PNG_FORMAT_BGR_SUPPORTED + const int bgr = (format & PNG_FORMAT_FLAG_BGR) ? 2 : 0; +# else +# define bgr 0 +# endif + + int i, num_trans; + png_color palette[256]; + png_byte tRNS[256]; + + memset(tRNS, 255, (sizeof tRNS)); + memset(palette, 0, (sizeof palette)); + + for (i=num_trans=0; i= 3) /* RGB */ + { + palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 * + entry[(2 ^ bgr)]); + palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 * + entry[1]); + palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 * + entry[bgr]); + } + + else /* Gray */ + palette[i].blue = palette[i].red = palette[i].green = + (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry); + } + + else /* alpha */ + { + png_uint_16 alpha = entry[afirst ? 0 : channels-1]; + png_byte alphabyte = (png_byte)PNG_DIV257(alpha); + png_uint_32 reciprocal = 0; + + /* Calculate a reciprocal, as in the png_write_image_8bit code above + * this is designed to produce a value scaled to 255*65535 when + * divided by 128 (i.e. asr 7). + */ + if (alphabyte > 0 && alphabyte < 255) + reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha; + + tRNS[i] = alphabyte; + if (alphabyte < 255) + num_trans = i+1; + + if (channels >= 3) /* RGB */ + { + palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)], + alpha, reciprocal); + palette[i].green = png_unpremultiply(entry[afirst + 1], alpha, + reciprocal); + palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha, + reciprocal); + } + + else /* gray */ + palette[i].blue = palette[i].red = palette[i].green = + png_unpremultiply(entry[afirst], alpha, reciprocal); + } + } + + else /* Color-map has sRGB values */ + { + png_const_bytep entry = png_voidcast(png_const_bytep, cmap); + + entry += i * channels; + + switch (channels) + { + case 4: + tRNS[i] = entry[afirst ? 0 : 3]; + if (tRNS[i] < 255) + num_trans = i+1; + /* FALL THROUGH */ + case 3: + palette[i].blue = entry[afirst + (2 ^ bgr)]; + palette[i].green = entry[afirst + 1]; + palette[i].red = entry[afirst + bgr]; + break; + + case 2: + tRNS[i] = entry[1 ^ afirst]; + if (tRNS[i] < 255) + num_trans = i+1; + /* FALL THROUGH */ + case 1: + palette[i].blue = palette[i].red = palette[i].green = + entry[afirst]; + break; + + default: + break; + } + } + } + +# ifdef afirst +# undef afirst +# endif +# ifdef bgr +# undef bgr +# endif + + png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette, + entries); + + if (num_trans > 0) + png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS, + num_trans, NULL); + + image->colormap_entries = entries; +} + +static int +png_image_write_main(png_voidp argument) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); + png_imagep image = display->image; + png_structrp png_ptr = image->opaque->png_ptr; + png_inforp info_ptr = image->opaque->info_ptr; + png_uint_32 format = image->format; + + int colormap = (format & PNG_FORMAT_FLAG_COLORMAP) != 0; + int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */ + int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0; + int write_16bit = linear && !colormap && !display->convert_to_8bit; + +# ifdef PNG_BENIGN_ERRORS_SUPPORTED + /* Make sure we error out on any bad situation */ + png_set_benign_errors(png_ptr, 0/*error*/); +# endif + + /* Default the 'row_stride' parameter if required. */ + if (display->row_stride == 0) + display->row_stride = PNG_IMAGE_ROW_STRIDE(*image); + + /* Set the required transforms then write the rows in the correct order. */ + if (format & PNG_FORMAT_FLAG_COLORMAP) + { + if (display->colormap != NULL && image->colormap_entries > 0) + { + png_uint_32 entries = image->colormap_entries; + + png_set_IHDR(png_ptr, info_ptr, image->width, image->height, + entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)), + PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_image_set_PLTE(display); + } + + else + png_error(image->opaque->png_ptr, + "no color-map for color-mapped image"); + } + + else + png_set_IHDR(png_ptr, info_ptr, image->width, image->height, + write_16bit ? 16 : 8, + ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + + ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* Counter-intuitively the data transformations must be called *after* + * png_write_info, not before as in the read code, but the 'set' functions + * must still be called before. Just set the color space information, never + * write an interlaced image. + */ + + if (write_16bit != 0) + { + /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */ + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR); + + if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB)) + png_set_cHRM_fixed(png_ptr, info_ptr, + /* color x y */ + /* white */ 31270, 32900, + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000 + ); + } + + else if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB)) + png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL); + + /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit + * space must still be gamma encoded. + */ + else + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); + + /* Write the file header. */ + png_write_info(png_ptr, info_ptr); + + /* Now set up the data transformations (*after* the header is written), + * remove the handled transformations from the 'format' flags for checking. + * + * First check for a little endian system if writing 16 bit files. + */ + if (write_16bit != 0) + { + PNG_CONST png_uint_16 le = 0x0001; + + if (*(png_const_bytep)&le) + png_set_swap(png_ptr); + } + +# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED + if (format & PNG_FORMAT_FLAG_BGR) + { + if (!colormap && (format & PNG_FORMAT_FLAG_COLOR) != 0) + png_set_bgr(png_ptr); + format &= ~PNG_FORMAT_FLAG_BGR; + } +# endif + +# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + { + if (!colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0) + png_set_swap_alpha(png_ptr); + format &= ~PNG_FORMAT_FLAG_AFIRST; + } +# endif + + /* If there are 16 or fewer color-map entries we wrote a lower bit depth + * above, but the application data is still byte packed. + */ + if (colormap && image->colormap_entries <= 16) + png_set_packing(png_ptr); + + /* That should have handled all (both) the transforms. */ + if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR | + PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0) + png_error(png_ptr, "png_write_image: unsupported transformation"); + + { + png_const_bytep row = png_voidcast(png_const_bytep, display->buffer); + ptrdiff_t row_bytes = display->row_stride; + + if (linear != 0) + row_bytes *= (sizeof (png_uint_16)); + + if (row_bytes < 0) + row += (image->height-1) * (-row_bytes); + + display->first_row = row; + display->row_bytes = row_bytes; + } + + /* Apply 'fast' options if the flag is set. */ + if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0) + { + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS); + /* NOTE: determined by experiment using pngstest, this reflects some + * balance between the time to write the image once and the time to read + * it about 50 times. The speed-up in pngstest was about 10-20% of the + * total (user) time on a heavily loaded system. + */ + png_set_compression_level(png_ptr, 3); + } + + /* Check for the cases that currently require a pre-transform on the row + * before it is written. This only applies when the input is 16-bit and + * either there is an alpha channel or it is converted to 8-bit. + */ + if ((linear && alpha) || (!colormap && display->convert_to_8bit)) + { + png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr))); + int result; + + display->local_row = row; + if (write_16bit != 0) + result = png_safe_execute(image, png_write_image_16bit, display); + else + result = png_safe_execute(image, png_write_image_8bit, display); + display->local_row = NULL; + + png_free(png_ptr, row); + + /* Skip the 'write_end' on error: */ + if (result == 0) + return 0; + } + + /* Otherwise this is the case where the input is in a format currently + * supported by the rest of the libpng write code; call it directly. + */ + else + { + png_const_bytep row = png_voidcast(png_const_bytep, display->first_row); + ptrdiff_t row_bytes = display->row_bytes; + png_uint_32 y = image->height; + + while (y-- > 0) + { + png_write_row(png_ptr, row); + row += row_bytes; + } + } + + png_write_end(png_ptr, info_ptr); + return 1; +} + +int PNGAPI +png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, + const void *buffer, png_int_32 row_stride, const void *colormap) +{ + /* Write the image to the given (FILE*). */ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (file != NULL) + { + if (png_image_write_init(image)) + { + png_image_write_control display; + int result; + + /* This is slightly evil, but png_init_io doesn't do anything other + * than this and we haven't changed the standard IO functions so + * this saves a 'safe' function. + */ + image->opaque->png_ptr->io_ptr = file; + + memset(&display, 0, (sizeof display)); + display.image = image; + display.buffer = buffer; + display.row_stride = row_stride; + display.colormap = colormap; + display.convert_to_8bit = convert_to_8bit; + + result = png_safe_execute(image, png_image_write_main, &display); + png_image_free(image); + return result; + } + + else + return 0; + } + + else + return png_image_error(image, + "png_image_write_to_stdio: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); + + else + return 0; +} + +int PNGAPI +png_image_write_to_file(png_imagep image, const char *file_name, + int convert_to_8bit, const void *buffer, png_int_32 row_stride, + const void *colormap) +{ + /* Write the image to the named file. */ + if (image != NULL && image->version == PNG_IMAGE_VERSION) + { + if (file_name != NULL) + { + FILE *fp = fopen(file_name, "wb"); + + if (fp != NULL) + { + if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, + row_stride, colormap)) + { + int error; /* from fflush/fclose */ + + /* Make sure the file is flushed correctly. */ + if (fflush(fp) == 0 && ferror(fp) == 0) + { + if (fclose(fp) == 0) + return 1; + + error = errno; /* from fclose */ + } + + else + { + error = errno; /* from fflush or ferror */ + (void)fclose(fp); + } + + (void)remove(file_name); + /* The image has already been cleaned up; this is just used to + * set the error (because the original write succeeded). + */ + return png_image_error(image, strerror(error)); + } + + else + { + /* Clean up: just the opened file. */ + (void)fclose(fp); + (void)remove(file_name); + return 0; + } + } + + else + return png_image_error(image, strerror(errno)); + } + + else + return png_image_error(image, + "png_image_write_to_file: invalid argument"); + } + + else if (image != NULL) + return png_image_error(image, + "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); + + else + return 0; +} +#endif /* PNG_STDIO_SUPPORTED */ +#endif /* SIMPLIFIED_WRITE */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngwtran.c b/ext/libpng17/pngwtran.c similarity index 84% rename from ext/libpng16/pngwtran.c rename to ext/libpng17/pngwtran.c index 2cdd7c95c2..215bd68a9d 100644 --- a/ext/libpng16/pngwtran.c +++ b/ext/libpng17/pngwtran.c @@ -1,637 +1,572 @@ - -/* pngwtran.c - transforms the data in a row for PNG writers - * - * Last changed in libpng 1.6.0 [February 14, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -#include "pngpriv.h" - -#ifdef PNG_WRITE_SUPPORTED - -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED -/* Transform the data according to the user's wishes. The order of - * transformations is significant. - */ -void /* PRIVATE */ -png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) -{ - png_debug(1, "in png_do_write_transformations"); - - if (png_ptr == NULL) - return; - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED - if (png_ptr->transformations & PNG_USER_TRANSFORM) - if (png_ptr->write_user_transform_fn != NULL) - (*(png_ptr->write_user_transform_fn)) /* User write transform - function */ - (png_ptr, /* png_ptr */ - row_info, /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_size_t rowbytes; number of bytes in row */ - /* png_byte color_type; color type of pixels */ - /* png_byte bit_depth; bit depth of samples */ - /* png_byte channels; number of channels (1-4) */ - /* png_byte pixel_depth; bits per pixel (depth*channels) */ - png_ptr->row_buf + 1); /* start of pixel data for row */ -#endif - -#ifdef PNG_WRITE_FILLER_SUPPORTED - if (png_ptr->transformations & PNG_FILLER) - png_do_strip_channel(row_info, png_ptr->row_buf + 1, - !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); -#endif - -#ifdef PNG_WRITE_PACKSWAP_SUPPORTED - if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_WRITE_PACK_SUPPORTED - if (png_ptr->transformations & PNG_PACK) - png_do_pack(row_info, png_ptr->row_buf + 1, - (png_uint_32)png_ptr->bit_depth); -#endif - -#ifdef PNG_WRITE_SWAP_SUPPORTED - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_do_swap(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_WRITE_SHIFT_SUPPORTED - if (png_ptr->transformations & PNG_SHIFT) - png_do_shift(row_info, png_ptr->row_buf + 1, - &(png_ptr->shift)); -#endif - -#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED - if (png_ptr->transformations & PNG_SWAP_ALPHA) - png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED - if (png_ptr->transformations & PNG_INVERT_ALPHA) - png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_WRITE_BGR_SUPPORTED - if (png_ptr->transformations & PNG_BGR) - png_do_bgr(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_WRITE_INVERT_SUPPORTED - if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(row_info, png_ptr->row_buf + 1); -#endif -} - -#ifdef PNG_WRITE_PACK_SUPPORTED -/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The - * row_info bit depth should be 8 (one pixel per byte). The channels - * should be 1 (this only happens on grayscale and paletted images). - */ -void /* PRIVATE */ -png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) -{ - png_debug(1, "in png_do_pack"); - - if (row_info->bit_depth == 8 && - row_info->channels == 1) - { - switch ((int)bit_depth) - { - case 1: - { - png_bytep sp, dp; - int mask, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - sp = row; - dp = row; - mask = 0x80; - v = 0; - - for (i = 0; i < row_width; i++) - { - if (*sp != 0) - v |= mask; - - sp++; - - if (mask > 1) - mask >>= 1; - - else - { - mask = 0x80; - *dp = (png_byte)v; - dp++; - v = 0; - } - } - - if (mask != 0x80) - *dp = (png_byte)v; - - break; - } - - case 2: - { - png_bytep sp, dp; - int shift, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - sp = row; - dp = row; - shift = 6; - v = 0; - - for (i = 0; i < row_width; i++) - { - png_byte value; - - value = (png_byte)(*sp & 0x03); - v |= (value << shift); - - if (shift == 0) - { - shift = 6; - *dp = (png_byte)v; - dp++; - v = 0; - } - - else - shift -= 2; - - sp++; - } - - if (shift != 6) - *dp = (png_byte)v; - - break; - } - - case 4: - { - png_bytep sp, dp; - int shift, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - sp = row; - dp = row; - shift = 4; - v = 0; - - for (i = 0; i < row_width; i++) - { - png_byte value; - - value = (png_byte)(*sp & 0x0f); - v |= (value << shift); - - if (shift == 0) - { - shift = 4; - *dp = (png_byte)v; - dp++; - v = 0; - } - - else - shift -= 4; - - sp++; - } - - if (shift != 4) - *dp = (png_byte)v; - - break; - } - - default: - break; - } - - row_info->bit_depth = (png_byte)bit_depth; - row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_info->width); - } -} -#endif - -#ifdef PNG_WRITE_SHIFT_SUPPORTED -/* Shift pixel values to take advantage of whole range. Pass the - * true number of bits in bit_depth. The row should be packed - * according to row_info->bit_depth. Thus, if you had a row of - * bit depth 4, but the pixels only had values from 0 to 7, you - * would pass 3 as bit_depth, and this routine would translate the - * data to 0 to 15. - */ -void /* PRIVATE */ -png_do_shift(png_row_infop row_info, png_bytep row, - png_const_color_8p bit_depth) -{ - png_debug(1, "in png_do_shift"); - - if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) - { - int shift_start[4], shift_dec[4]; - int channels = 0; - - if (row_info->color_type & PNG_COLOR_MASK_COLOR) - { - shift_start[channels] = row_info->bit_depth - bit_depth->red; - shift_dec[channels] = bit_depth->red; - channels++; - - shift_start[channels] = row_info->bit_depth - bit_depth->green; - shift_dec[channels] = bit_depth->green; - channels++; - - shift_start[channels] = row_info->bit_depth - bit_depth->blue; - shift_dec[channels] = bit_depth->blue; - channels++; - } - - else - { - shift_start[channels] = row_info->bit_depth - bit_depth->gray; - shift_dec[channels] = bit_depth->gray; - channels++; - } - - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - shift_start[channels] = row_info->bit_depth - bit_depth->alpha; - shift_dec[channels] = bit_depth->alpha; - channels++; - } - - /* With low row depths, could only be grayscale, so one channel */ - if (row_info->bit_depth < 8) - { - png_bytep bp = row; - png_size_t i; - unsigned int mask; - png_size_t row_bytes = row_info->rowbytes; - - if (bit_depth->gray == 1 && row_info->bit_depth == 2) - mask = 0x55; - - else if (row_info->bit_depth == 4 && bit_depth->gray == 3) - mask = 0x11; - - else - mask = 0xff; - - for (i = 0; i < row_bytes; i++, bp++) - { - int j; - unsigned int v, out; - - v = *bp; - out = 0; - - for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) - { - if (j > 0) - out |= v << j; - - else - out |= (v >> (-j)) & mask; - } - - *bp = (png_byte)(out & 0xff); - } - } - - else if (row_info->bit_depth == 8) - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = channels * row_info->width; - - for (i = 0; i < istop; i++, bp++) - { - - const unsigned int c = i%channels; - int j; - unsigned int v, out; - - v = *bp; - out = 0; - - for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) - { - if (j > 0) - out |= v << j; - - else - out |= v >> (-j); - } - - *bp = (png_byte)(out & 0xff); - } - } - - else - { - png_bytep bp; - png_uint_32 i; - png_uint_32 istop = channels * row_info->width; - - for (bp = row, i = 0; i < istop; i++) - { - const unsigned int c = i%channels; - int j; - unsigned int value, v; - - v = png_get_uint_16(bp); - value = 0; - - for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) - { - if (j > 0) - value |= v << j; - - else - value |= v >> (-j); - } - *bp++ = (png_byte)((value >> 8) & 0xff); - *bp++ = (png_byte)(value & 0xff); - } - } - } -} -#endif - -#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED -void /* PRIVATE */ -png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_write_swap_alpha"); - - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This converts from ARGB to RGBA */ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save; - } - } - -#ifdef PNG_WRITE_16BIT_SUPPORTED - else - { - /* This converts from AARRGGBB to RRGGBBAA */ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save[2]; - save[0] = *(sp++); - save[1] = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save[0]; - *(dp++) = save[1]; - } - } -#endif /* PNG_WRITE_16BIT_SUPPORTED */ - } - - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This converts from AG to GA */ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save; - } - } - -#ifdef PNG_WRITE_16BIT_SUPPORTED - else - { - /* This converts from AAGG to GGAA */ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save[2]; - save[0] = *(sp++); - save[1] = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save[0]; - *(dp++) = save[1]; - } - } -#endif /* PNG_WRITE_16BIT_SUPPORTED */ - } - } -} -#endif - -#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED -void /* PRIVATE */ -png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_write_invert_alpha"); - - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This inverts the alpha channel in RGBA */ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* Does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=3; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - -#ifdef PNG_WRITE_16BIT_SUPPORTED - else - { - /* This inverts the alpha channel in RRGGBBAA */ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* Does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=6; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } -#endif /* PNG_WRITE_16BIT_SUPPORTED */ - } - - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This inverts the alpha channel in GA */ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - *(dp++) = *(sp++); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - -#ifdef PNG_WRITE_16BIT_SUPPORTED - else - { - /* This inverts the alpha channel in GGAA */ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* Does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=2; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } -#endif /* PNG_WRITE_16BIT_SUPPORTED */ - } - } -} -#endif -#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ - -#ifdef PNG_MNG_FEATURES_SUPPORTED -/* Undoes intrapixel differencing */ -void /* PRIVATE */ -png_do_write_intrapixel(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_write_intrapixel"); - - if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - int bytes_per_pixel; - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 3; - - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 4; - - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - *(rp) = (png_byte)((*rp - *(rp + 1)) & 0xff); - *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff); - } - } - -#ifdef PNG_WRITE_16BIT_SUPPORTED - else if (row_info->bit_depth == 16) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 6; - - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 8; - - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); - png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); - png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); - png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); - png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); - *(rp ) = (png_byte)((red >> 8) & 0xff); - *(rp + 1) = (png_byte)(red & 0xff); - *(rp + 4) = (png_byte)((blue >> 8) & 0xff); - *(rp + 5) = (png_byte)(blue & 0xff); - } - } -#endif /* PNG_WRITE_16BIT_SUPPORTED */ - } -} -#endif /* PNG_MNG_FEATURES_SUPPORTED */ -#endif /* PNG_WRITE_SUPPORTED */ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * Last changed in libpng 1.6.9 [February 6, 2014] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED + +#ifdef PNG_WRITE_PACK_SUPPORTED +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +static void +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack"); + + if (row_info->bit_depth == 8 && + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + + sp++; + + if (mask > 1) + mask >>= 1; + + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + + if (mask != 0x80) + *dp = (png_byte)v; + + break; + } + + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + + else + shift -= 2; + + sp++; + } + + if (shift != 6) + *dp = (png_byte)v; + + break; + } + + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + + else + shift -= 4; + + sp++; + } + + if (shift != 4) + *dp = (png_byte)v; + + break; + } + + default: + break; + } + + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +static void +png_do_shift(png_row_infop row_info, png_bytep row, + png_const_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift"); + + if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* With low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_size_t i; + unsigned int mask; + png_size_t row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + int j; + unsigned int v, out; + + v = *bp; + out = 0; + + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + out |= v << j; + + else + out |= (v >> (-j)) & mask; + } + + *bp = (png_byte)(out & 0xff); + } + } + + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + const unsigned int c = i%channels; + int j; + unsigned int v, out; + + v = *bp; + out = 0; + + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + out |= v << j; + + else + out |= v >> (-j); + } + + *bp = (png_byte)(out & 0xff); + } + } + + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + const unsigned int c = i%channels; + int j; + unsigned int value, v; + + v = png_get_uint_16(bp); + value = 0; + + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= v << j; + + else + value |= v >> (-j); + } + *bp++ = (png_byte)((value >> 8) & 0xff); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +static void +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from ARGB to RGBA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AARRGGBB to RRGGBBAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from AG to GA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AAGG to GGAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +static void +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=3; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in RRGGBBAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=6; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=2; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif + +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) +{ + png_debug(1, "in png_do_write_transformations"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if (png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* User write transform + function */ + (png_ptr, /* png_ptr */ + row_info, /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_channel(row_info, png_ptr->row_buf + 1, + !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_pack(row_info, png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(row_info, png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(row_info, png_ptr->row_buf + 1); +#endif +} +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/ext/libpng16/pngwutil.c b/ext/libpng17/pngwutil.c similarity index 94% rename from ext/libpng16/pngwutil.c rename to ext/libpng17/pngwutil.c index 88dd0c9d4b..df2ffdb9df 100644 --- a/ext/libpng16/pngwutil.c +++ b/ext/libpng17/pngwutil.c @@ -1,3023 +1,3062 @@ - -/* pngwutil.c - utilities to write a PNG file - * - * Last changed in libpng 1.6.2 [April 25, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -#include "pngpriv.h" - -#ifdef PNG_WRITE_SUPPORTED - -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -/* Place a 32-bit number into a buffer in PNG byte order. We work - * with unsigned numbers for convenience, although one supported - * ancillary chunk uses signed (two's complement) numbers. - */ -void PNGAPI -png_save_uint_32(png_bytep buf, png_uint_32 i) -{ - buf[0] = (png_byte)((i >> 24) & 0xff); - buf[1] = (png_byte)((i >> 16) & 0xff); - buf[2] = (png_byte)((i >> 8) & 0xff); - buf[3] = (png_byte)(i & 0xff); -} - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -void PNGAPI -png_save_uint_16(png_bytep buf, unsigned int i) -{ - buf[0] = (png_byte)((i >> 8) & 0xff); - buf[1] = (png_byte)(i & 0xff); -} -#endif - -/* Simple function to write the signature. If we have already written - * the magic bytes of the signature, or more likely, the PNG stream is - * being embedded into another stream and doesn't need its own signature, - * we should call png_set_sig_bytes() to tell libpng how many of the - * bytes have already been written. - */ -void PNGAPI -png_write_sig(png_structrp png_ptr) -{ - png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; - -#ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that the signature is being written */ - png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; -#endif - - /* Write the rest of the 8 byte signature */ - png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], - (png_size_t)(8 - png_ptr->sig_bytes)); - - if (png_ptr->sig_bytes < 3) - png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; -} - -/* Write the start of a PNG chunk. The type is the chunk type. - * The total_length is the sum of the lengths of all the data you will be - * passing in png_write_chunk_data(). - */ -static void -png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name, - png_uint_32 length) -{ - png_byte buf[8]; - -#if defined(PNG_DEBUG) && (PNG_DEBUG > 0) - PNG_CSTRING_FROM_CHUNK(buf, chunk_name); - png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length); -#endif - - if (png_ptr == NULL) - return; - -#ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that the chunk header is being written. - * PNG_IO_CHUNK_HDR requires a single I/O call. - */ - png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; -#endif - - /* Write the length and the chunk name */ - png_save_uint_32(buf, length); - png_save_uint_32(buf + 4, chunk_name); - png_write_data(png_ptr, buf, 8); - - /* Put the chunk name into png_ptr->chunk_name */ - png_ptr->chunk_name = chunk_name; - - /* Reset the crc and run it over the chunk name */ - png_reset_crc(png_ptr); - - png_calculate_crc(png_ptr, buf + 4, 4); - -#ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that chunk data will (possibly) be written. - * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. - */ - png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; -#endif -} - -void PNGAPI -png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, - png_uint_32 length) -{ - png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length); -} - -/* Write the data of a PNG chunk started with png_write_chunk_header(). - * Note that multiple calls to this function are allowed, and that the - * sum of the lengths from these calls *must* add up to the total_length - * given to png_write_chunk_header(). - */ -void PNGAPI -png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, - png_size_t length) -{ - /* Write the data, and run the CRC over it */ - if (png_ptr == NULL) - return; - - if (data != NULL && length > 0) - { - png_write_data(png_ptr, data, length); - - /* Update the CRC after writing the data, - * in case that the user I/O routine alters it. - */ - png_calculate_crc(png_ptr, data, length); - } -} - -/* Finish a chunk started with png_write_chunk_header(). */ -void PNGAPI -png_write_chunk_end(png_structrp png_ptr) -{ - png_byte buf[4]; - - if (png_ptr == NULL) return; - -#ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that the chunk CRC is being written. - * PNG_IO_CHUNK_CRC requires a single I/O function call. - */ - png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; -#endif - - /* Write the crc in a single operation */ - png_save_uint_32(buf, png_ptr->crc); - - png_write_data(png_ptr, buf, (png_size_t)4); -} - -/* Write a PNG chunk all at once. The type is an array of ASCII characters - * representing the chunk name. The array must be at least 4 bytes in - * length, and does not need to be null terminated. To be safe, pass the - * pre-defined chunk names here, and if you need a new one, define it - * where the others are defined. The length is the length of the data. - * All the data must be present. If that is not possible, use the - * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() - * functions instead. - */ -static void -png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, - png_const_bytep data, png_size_t length) -{ - if (png_ptr == NULL) - return; - - /* On 64 bit architectures 'length' may not fit in a png_uint_32. */ - if (length > PNG_UINT_31_MAX) - png_error(png_ptr, "length exceeds PNG maxima"); - - png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length); - png_write_chunk_data(png_ptr, data, length); - png_write_chunk_end(png_ptr); -} - -/* This is the API that calls the internal function above. */ -void PNGAPI -png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, - png_const_bytep data, png_size_t length) -{ - png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, - length); -} - -/* This is used below to find the size of an image to pass to png_deflate_claim, - * so it only needs to be accurate if the size is less than 16384 bytes (the - * point at which a lower LZ window size can be used.) - */ -static png_alloc_size_t -png_image_size(png_structrp png_ptr) -{ - /* Only return sizes up to the maximum of a png_uint_32, do this by limiting - * the width and height used to 15 bits. - */ - png_uint_32 h = png_ptr->height; - - if (png_ptr->rowbytes < 32768 && h < 32768) - { - if (png_ptr->interlaced) - { - /* Interlacing makes the image larger because of the replication of - * both the filter byte and the padding to a byte boundary. - */ - png_uint_32 w = png_ptr->width; - unsigned int pd = png_ptr->pixel_depth; - png_alloc_size_t cb_base; - int pass; - - for (cb_base=0, pass=0; pass<=6; ++pass) - { - png_uint_32 pw = PNG_PASS_COLS(w, pass); - - if (pw > 0) - cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass); - } - - return cb_base; - } - - else - return (png_ptr->rowbytes+1) * h; - } - - else - return 0xffffffffU; -} - -#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED - /* This is the code to hack the first two bytes of the deflate stream (the - * deflate header) to correct the windowBits value to match the actual data - * size. Note that the second argument is the *uncompressed* size but the - * first argument is the *compressed* data (and it must be deflate - * compressed.) - */ -static void -optimize_cmf(png_bytep data, png_alloc_size_t data_size) -{ - /* Optimize the CMF field in the zlib stream. The resultant zlib stream is - * still compliant to the stream specification. - */ - if (data_size <= 16384) /* else windowBits must be 15 */ - { - unsigned int z_cmf = data[0]; /* zlib compression method and flags */ - - if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) - { - unsigned int z_cinfo; - unsigned int half_z_window_size; - - z_cinfo = z_cmf >> 4; - half_z_window_size = 1U << (z_cinfo + 7); - - if (data_size <= half_z_window_size) /* else no change */ - { - unsigned int tmp; - - do - { - half_z_window_size >>= 1; - --z_cinfo; - } - while (z_cinfo > 0 && data_size <= half_z_window_size); - - z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); - - data[0] = (png_byte)z_cmf; - tmp = data[1] & 0xe0; - tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; - data[1] = (png_byte)tmp; - } - } - } -} -#else -# define optimize_cmf(dp,dl) ((void)0) -#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ - -/* Initialize the compressor for the appropriate type of compression. */ -static int -png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, - png_alloc_size_t data_size) -{ - if (png_ptr->zowner != 0) - { - char msg[64]; - - PNG_STRING_FROM_CHUNK(msg, owner); - msg[4] = ':'; - msg[5] = ' '; - PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner); - /* So the message that results is " using zstream"; this is an - * internal error, but is very useful for debugging. i18n requirements - * are minimal. - */ - (void)png_safecat(msg, (sizeof msg), 10, " using zstream"); -# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC - png_warning(png_ptr, msg); - - /* Attempt sane error recovery */ - if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */ - { - png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT"); - return Z_STREAM_ERROR; - } - - png_ptr->zowner = 0; -# else - png_error(png_ptr, msg); -# endif - } - - { - int level = png_ptr->zlib_level; - int method = png_ptr->zlib_method; - int windowBits = png_ptr->zlib_window_bits; - int memLevel = png_ptr->zlib_mem_level; - int strategy; /* set below */ - int ret; /* zlib return code */ - - if (owner == png_IDAT) - { - if (png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) - strategy = png_ptr->zlib_strategy; - - else if (png_ptr->do_filter != PNG_FILTER_NONE) - strategy = PNG_Z_DEFAULT_STRATEGY; - - else - strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY; - } - - else - { -# ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED - level = png_ptr->zlib_text_level; - method = png_ptr->zlib_text_method; - windowBits = png_ptr->zlib_text_window_bits; - memLevel = png_ptr->zlib_text_mem_level; - strategy = png_ptr->zlib_text_strategy; -# else - /* If customization is not supported the values all come from the - * IDAT values except for the strategy, which is fixed to the - * default. (This is the pre-1.6.0 behavior too, although it was - * implemented in a very different way.) - */ - strategy = Z_DEFAULT_STRATEGY; -# endif - } - - /* Adjust 'windowBits' down if larger than 'data_size'; to stop this - * happening just pass 32768 as the data_size parameter. Notice that zlib - * requires an extra 262 bytes in the window in addition to the data to be - * able to see the whole of the data, so if data_size+262 takes us to the - * next windowBits size we need to fix up the value later. (Because even - * though deflate needs the extra window, inflate does not!) - */ - if (data_size <= 16384) - { - /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to - * work round a Microsoft Visual C misbehavior which, contrary to C-90, - * widens the result of the following shift to 64-bits if (and, - * apparently, only if) it is used in a test. - */ - unsigned int half_window_size = 1U << (windowBits-1); - - while (data_size + 262 <= half_window_size) - { - half_window_size >>= 1; - --windowBits; - } - } - - /* Check against the previous initialized values, if any. */ - if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) && - (png_ptr->zlib_set_level != level || - png_ptr->zlib_set_method != method || - png_ptr->zlib_set_window_bits != windowBits || - png_ptr->zlib_set_mem_level != memLevel || - png_ptr->zlib_set_strategy != strategy)) - { - if (deflateEnd(&png_ptr->zstream) != Z_OK) - png_warning(png_ptr, "deflateEnd failed (ignored)"); - - png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED; - } - - /* For safety clear out the input and output pointers (currently zlib - * doesn't use them on Init, but it might in the future). - */ - png_ptr->zstream.next_in = NULL; - png_ptr->zstream.avail_in = 0; - png_ptr->zstream.next_out = NULL; - png_ptr->zstream.avail_out = 0; - - /* Now initialize if required, setting the new parameters, otherwise just - * to a simple reset to the previous parameters. - */ - if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) - ret = deflateReset(&png_ptr->zstream); - - else - { - ret = deflateInit2(&png_ptr->zstream, level, method, windowBits, - memLevel, strategy); - - if (ret == Z_OK) - png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; - } - - /* The return code is from either deflateReset or deflateInit2; they have - * pretty much the same set of error codes. - */ - if (ret == Z_OK) - png_ptr->zowner = owner; - - else - png_zstream_error(png_ptr, ret); - - return ret; - } -} - -/* Clean up (or trim) a linked list of compression buffers. */ -void /* PRIVATE */ -png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp) -{ - png_compression_bufferp list = *listp; - - if (list != NULL) - { - *listp = NULL; - - do - { - png_compression_bufferp next = list->next; - - png_free(png_ptr, list); - list = next; - } - while (list != NULL); - } -} - -#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED -/* This pair of functions encapsulates the operation of (a) compressing a - * text string, and (b) issuing it later as a series of chunk data writes. - * The compression_state structure is shared context for these functions - * set up by the caller to allow access to the relevant local variables. - * - * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size - * temporary buffers. From 1.6.0 it is retained in png_struct so that it will - * be correctly freed in the event of a write error (previous implementations - * just leaked memory.) - */ -typedef struct -{ - png_const_bytep input; /* The uncompressed input data */ - png_alloc_size_t input_len; /* Its length */ - png_uint_32 output_len; /* Final compressed length */ - png_byte output[1024]; /* First block of output */ -} compression_state; - -static void -png_text_compress_init(compression_state *comp, png_const_bytep input, - png_alloc_size_t input_len) -{ - comp->input = input; - comp->input_len = input_len; - comp->output_len = 0; -} - -/* Compress the data in the compression state input */ -static int -png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, - compression_state *comp, png_uint_32 prefix_len) -{ - int ret; - - /* To find the length of the output it is necessary to first compress the - * input, the result is buffered rather than using the two-pass algorithm - * that is used on the inflate side; deflate is assumed to be slower and a - * PNG writer is assumed to have more memory available than a PNG reader. - * - * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an - * upper limit on the output size, but it is always bigger than the input - * size so it is likely to be more efficient to use this linked-list - * approach. - */ - ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len); - - if (ret != Z_OK) - return ret; - - /* Set up the compression buffers, we need a loop here to avoid overflowing a - * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited - * by the output buffer size, so there is no need to check that. Since this - * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits - * in size. - */ - { - png_compression_bufferp *end = &png_ptr->zbuffer_list; - png_alloc_size_t input_len = comp->input_len; /* may be zero! */ - png_uint_32 output_len; - - /* zlib updates these for us: */ - png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input); - png_ptr->zstream.avail_in = 0; /* Set below */ - png_ptr->zstream.next_out = comp->output; - png_ptr->zstream.avail_out = (sizeof comp->output); - - output_len = png_ptr->zstream.avail_out; - - do - { - uInt avail_in = ZLIB_IO_MAX; - - if (avail_in > input_len) - avail_in = (uInt)input_len; - - input_len -= avail_in; - - png_ptr->zstream.avail_in = avail_in; - - if (png_ptr->zstream.avail_out == 0) - { - png_compression_buffer *next; - - /* Chunk data is limited to 2^31 bytes in length, so the prefix - * length must be counted here. - */ - if (output_len + prefix_len > PNG_UINT_31_MAX) - { - ret = Z_MEM_ERROR; - break; - } - - /* Need a new (malloc'ed) buffer, but there may be one present - * already. - */ - next = *end; - if (next == NULL) - { - next = png_voidcast(png_compression_bufferp, png_malloc_base - (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); - - if (next == NULL) - { - ret = Z_MEM_ERROR; - break; - } - - /* Link in this buffer (so that it will be freed later) */ - next->next = NULL; - *end = next; - } - - png_ptr->zstream.next_out = next->output; - png_ptr->zstream.avail_out = png_ptr->zbuffer_size; - output_len += png_ptr->zstream.avail_out; - - /* Move 'end' to the next buffer pointer. */ - end = &next->next; - } - - /* Compress the data */ - ret = deflate(&png_ptr->zstream, - input_len > 0 ? Z_NO_FLUSH : Z_FINISH); - - /* Claw back input data that was not consumed (because avail_in is - * reset above every time round the loop). - */ - input_len += png_ptr->zstream.avail_in; - png_ptr->zstream.avail_in = 0; /* safety */ - } - while (ret == Z_OK); - - /* There may be some space left in the last output buffer, this needs to - * be subtracted from output_len. - */ - output_len -= png_ptr->zstream.avail_out; - png_ptr->zstream.avail_out = 0; /* safety */ - comp->output_len = output_len; - - /* Now double check the output length, put in a custom message if it is - * too long. Otherwise ensure the z_stream::msg pointer is set to - * something. - */ - if (output_len + prefix_len >= PNG_UINT_31_MAX) - { - png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long"); - ret = Z_MEM_ERROR; - } - - else - png_zstream_error(png_ptr, ret); - - /* Reset zlib for another zTXt/iTXt or image data */ - png_ptr->zowner = 0; - - /* The only success case is Z_STREAM_END, input_len must be 0, if not this - * is an internal error. - */ - if (ret == Z_STREAM_END && input_len == 0) - { - /* Fix up the deflate header, if required */ - optimize_cmf(comp->output, comp->input_len); - - /* But Z_OK is returned, not Z_STREAM_END; this allows the claim - * function above to return Z_STREAM_END on an error (though it never - * does in the current versions of zlib.) - */ - return Z_OK; - } - - else - return ret; - } -} - -/* Ship the compressed text out via chunk writes */ -static void -png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp) -{ - png_uint_32 output_len = comp->output_len; - png_const_bytep output = comp->output; - png_uint_32 avail = (sizeof comp->output); - png_compression_buffer *next = png_ptr->zbuffer_list; - - for (;;) - { - if (avail > output_len) - avail = output_len; - - png_write_chunk_data(png_ptr, output, avail); - - output_len -= avail; - - if (output_len == 0 || next == NULL) - break; - - avail = png_ptr->zbuffer_size; - output = next->output; - next = next->next; - } - - /* This is an internal error; 'next' must have been NULL! */ - if (output_len > 0) - png_error(png_ptr, "error writing ancillary chunked compressed data"); -} -#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ - -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ - defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) -/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, - * and if invalid, correct the keyword rather than discarding the entire - * chunk. The PNG 1.0 specification requires keywords 1-79 characters in - * length, forbids leading or trailing whitespace, multiple internal spaces, - * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. - * - * The 'new_key' buffer must be 80 characters in size (for the keyword plus a - * trailing '\0'). If this routine returns 0 then there was no keyword, or a - * valid one could not be generated, and the caller must png_error. - */ -static png_uint_32 -png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) -{ - png_const_charp orig_key = key; - png_uint_32 key_len = 0; - int bad_character = 0; - int space = 1; - - png_debug(1, "in png_check_keyword"); - - if (key == NULL) - { - *new_key = 0; - return 0; - } - - while (*key && key_len < 79) - { - png_byte ch = (png_byte)(0xff & *key++); - - if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) - *new_key++ = ch, ++key_len, space = 0; - - else if (!space) - { - /* A space or an invalid character when one wasn't seen immediately - * before; output just a space. - */ - *new_key++ = 32, ++key_len, space = 1; - - /* If the character was not a space then it is invalid. */ - if (ch != 32) - bad_character = ch; - } - - else if (!bad_character) - bad_character = ch; /* just skip it, record the first error */ - } - - if (key_len > 0 && space) /* trailing space */ - { - --key_len, --new_key; - if (!bad_character) - bad_character = 32; - } - - /* Terminate the keyword */ - *new_key = 0; - - if (key_len == 0) - return 0; - - /* Try to only output one warning per keyword: */ - if (*key) /* keyword too long */ - png_warning(png_ptr, "keyword truncated"); - - else if (bad_character) - { - PNG_WARNING_PARAMETERS(p) - - png_warning_parameter(p, 1, orig_key); - png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character); - - png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'"); - } - - return key_len; -} -#endif - -/* Write the IHDR chunk, and update the png_struct with the necessary - * information. Note that the rest of this code depends upon this - * information being correct. - */ -void /* PRIVATE */ -png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, - int bit_depth, int color_type, int compression_type, int filter_type, - int interlace_type) -{ - png_byte buf[13]; /* Buffer to store the IHDR info */ - - png_debug(1, "in png_write_IHDR"); - - /* Check that we have valid input data from the application info */ - switch (color_type) - { - case PNG_COLOR_TYPE_GRAY: - switch (bit_depth) - { - case 1: - case 2: - case 4: - case 8: -#ifdef PNG_WRITE_16BIT_SUPPORTED - case 16: -#endif - png_ptr->channels = 1; break; - - default: - png_error(png_ptr, - "Invalid bit depth for grayscale image"); - } - break; - - case PNG_COLOR_TYPE_RGB: -#ifdef PNG_WRITE_16BIT_SUPPORTED - if (bit_depth != 8 && bit_depth != 16) -#else - if (bit_depth != 8) -#endif - png_error(png_ptr, "Invalid bit depth for RGB image"); - - png_ptr->channels = 3; - break; - - case PNG_COLOR_TYPE_PALETTE: - switch (bit_depth) - { - case 1: - case 2: - case 4: - case 8: - png_ptr->channels = 1; - break; - - default: - png_error(png_ptr, "Invalid bit depth for paletted image"); - } - break; - - case PNG_COLOR_TYPE_GRAY_ALPHA: - if (bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); - - png_ptr->channels = 2; - break; - - case PNG_COLOR_TYPE_RGB_ALPHA: -#ifdef PNG_WRITE_16BIT_SUPPORTED - if (bit_depth != 8 && bit_depth != 16) -#else - if (bit_depth != 8) -#endif - png_error(png_ptr, "Invalid bit depth for RGBA image"); - - png_ptr->channels = 4; - break; - - default: - png_error(png_ptr, "Invalid image color type specified"); - } - - if (compression_type != PNG_COMPRESSION_TYPE_BASE) - { - png_warning(png_ptr, "Invalid compression type specified"); - compression_type = PNG_COMPRESSION_TYPE_BASE; - } - - /* Write filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not write a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ - if ( -#ifdef PNG_MNG_FEATURES_SUPPORTED - !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && - (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) && - (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && -#endif - filter_type != PNG_FILTER_TYPE_BASE) - { - png_warning(png_ptr, "Invalid filter type specified"); - filter_type = PNG_FILTER_TYPE_BASE; - } - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - if (interlace_type != PNG_INTERLACE_NONE && - interlace_type != PNG_INTERLACE_ADAM7) - { - png_warning(png_ptr, "Invalid interlace type specified"); - interlace_type = PNG_INTERLACE_ADAM7; - } -#else - interlace_type=PNG_INTERLACE_NONE; -#endif - - /* Save the relevent information */ - png_ptr->bit_depth = (png_byte)bit_depth; - png_ptr->color_type = (png_byte)color_type; - png_ptr->interlaced = (png_byte)interlace_type; -#ifdef PNG_MNG_FEATURES_SUPPORTED - png_ptr->filter_type = (png_byte)filter_type; -#endif - png_ptr->compression_type = (png_byte)compression_type; - png_ptr->width = width; - png_ptr->height = height; - - png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); - png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); - /* Set the usr info, so any transformations can modify it */ - png_ptr->usr_width = png_ptr->width; - png_ptr->usr_bit_depth = png_ptr->bit_depth; - png_ptr->usr_channels = png_ptr->channels; - - /* Pack the header information into the buffer */ - png_save_uint_32(buf, width); - png_save_uint_32(buf + 4, height); - buf[8] = (png_byte)bit_depth; - buf[9] = (png_byte)color_type; - buf[10] = (png_byte)compression_type; - buf[11] = (png_byte)filter_type; - buf[12] = (png_byte)interlace_type; - - /* Write the chunk */ - png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); - - if (!(png_ptr->do_filter)) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || - png_ptr->bit_depth < 8) - png_ptr->do_filter = PNG_FILTER_NONE; - - else - png_ptr->do_filter = PNG_ALL_FILTERS; - } - - png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ -} - -/* Write the palette. We are careful not to trust png_color to be in the - * correct order for PNG, so people can redefine it to any convenient - * structure. - */ -void /* PRIVATE */ -png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, - png_uint_32 num_pal) -{ - png_uint_32 i; - png_const_colorp pal_ptr; - png_byte buf[3]; - - png_debug(1, "in png_write_PLTE"); - - if (( -#ifdef PNG_MNG_FEATURES_SUPPORTED - !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && -#endif - num_pal == 0) || num_pal > 256) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_error(png_ptr, "Invalid number of colors in palette"); - } - - else - { - png_warning(png_ptr, "Invalid number of colors in palette"); - return; - } - } - - if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) - { - png_warning(png_ptr, - "Ignoring request to write a PLTE chunk in grayscale PNG"); - - return; - } - - png_ptr->num_palette = (png_uint_16)num_pal; - png_debug1(3, "num_palette = %d", png_ptr->num_palette); - - png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); -#ifdef PNG_POINTER_INDEXING_SUPPORTED - - for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) - { - buf[0] = pal_ptr->red; - buf[1] = pal_ptr->green; - buf[2] = pal_ptr->blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); - } - -#else - /* This is a little slower but some buggy compilers need to do this - * instead - */ - pal_ptr=palette; - - for (i = 0; i < num_pal; i++) - { - buf[0] = pal_ptr[i].red; - buf[1] = pal_ptr[i].green; - buf[2] = pal_ptr[i].blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); - } - -#endif - png_write_chunk_end(png_ptr); - png_ptr->mode |= PNG_HAVE_PLTE; -} - -/* This is similar to png_text_compress, above, except that it does not require - * all of the data at once and, instead of buffering the compressed result, - * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out - * because it calls the write interface. As a result it does its own error - * reporting and does not return an error code. In the event of error it will - * just call png_error. The input data length may exceed 32-bits. The 'flush' - * parameter is exactly the same as that to deflate, with the following - * meanings: - * - * Z_NO_FLUSH: normal incremental output of compressed data - * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush - * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up - * - * The routine manages the acquire and release of the png_ptr->zstream by - * checking and (at the end) clearing png_ptr->zowner, it does some sanity - * checks on the 'mode' flags while doing this. - */ -void /* PRIVATE */ -png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, - png_alloc_size_t input_len, int flush) -{ - if (png_ptr->zowner != png_IDAT) - { - /* First time. Ensure we have a temporary buffer for compression and - * trim the buffer list if it has more than one entry to free memory. - * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been - * created at this point, but the check here is quick and safe. - */ - if (png_ptr->zbuffer_list == NULL) - { - png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp, - png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); - png_ptr->zbuffer_list->next = NULL; - } - - else - png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next); - - /* It is a terminal error if we can't claim the zstream. */ - if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg); - - /* The output state is maintained in png_ptr->zstream, so it must be - * initialized here after the claim. - */ - png_ptr->zstream.next_out = png_ptr->zbuffer_list->output; - png_ptr->zstream.avail_out = png_ptr->zbuffer_size; - } - - /* Now loop reading and writing until all the input is consumed or an error - * terminates the operation. The _out values are maintained across calls to - * this function, but the input must be reset each time. - */ - png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); - png_ptr->zstream.avail_in = 0; /* set below */ - for (;;) - { - int ret; - - /* INPUT: from the row data */ - uInt avail = ZLIB_IO_MAX; - - if (avail > input_len) - avail = (uInt)input_len; /* safe because of the check */ - - png_ptr->zstream.avail_in = avail; - input_len -= avail; - - ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush); - - /* Include as-yet unconsumed input */ - input_len += png_ptr->zstream.avail_in; - png_ptr->zstream.avail_in = 0; - - /* OUTPUT: write complete IDAT chunks when avail_out drops to zero, note - * that these two zstream fields are preserved across the calls, therefore - * there is no need to set these up on entry to the loop. - */ - if (png_ptr->zstream.avail_out == 0) - { - png_bytep data = png_ptr->zbuffer_list->output; - uInt size = png_ptr->zbuffer_size; - - /* Write an IDAT containing the data then reset the buffer. The - * first IDAT may need deflate header optimization. - */ -# ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED - if (!(png_ptr->mode & PNG_HAVE_IDAT) && - png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) - optimize_cmf(data, png_image_size(png_ptr)); -# endif - - png_write_complete_chunk(png_ptr, png_IDAT, data, size); - png_ptr->mode |= PNG_HAVE_IDAT; - - png_ptr->zstream.next_out = data; - png_ptr->zstream.avail_out = size; - - /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with - * the same flush parameter until it has finished output, for NO_FLUSH - * it doesn't matter. - */ - if (ret == Z_OK && flush != Z_NO_FLUSH) - continue; - } - - /* The order of these checks doesn't matter much; it just effect which - * possible error might be detected if multiple things go wrong at once. - */ - if (ret == Z_OK) /* most likely return code! */ - { - /* If all the input has been consumed then just return. If Z_FINISH - * was used as the flush parameter something has gone wrong if we get - * here. - */ - if (input_len == 0) - { - if (flush == Z_FINISH) - png_error(png_ptr, "Z_OK on Z_FINISH with output space"); - - return; - } - } - - else if (ret == Z_STREAM_END && flush == Z_FINISH) - { - /* This is the end of the IDAT data; any pending output must be - * flushed. For small PNG files we may still be at the beginning. - */ - png_bytep data = png_ptr->zbuffer_list->output; - uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out; - -# ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED - if (!(png_ptr->mode & PNG_HAVE_IDAT) && - png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) - optimize_cmf(data, png_image_size(png_ptr)); -# endif - - png_write_complete_chunk(png_ptr, png_IDAT, data, size); - png_ptr->zstream.avail_out = 0; - png_ptr->zstream.next_out = NULL; - png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; - - png_ptr->zowner = 0; /* Release the stream */ - return; - } - - else - { - /* This is an error condition. */ - png_zstream_error(png_ptr, ret); - png_error(png_ptr, png_ptr->zstream.msg); - } - } -} - -/* Write an IEND chunk */ -void /* PRIVATE */ -png_write_IEND(png_structrp png_ptr) -{ - png_debug(1, "in png_write_IEND"); - - png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); - png_ptr->mode |= PNG_HAVE_IEND; -} - -#ifdef PNG_WRITE_gAMA_SUPPORTED -/* Write a gAMA chunk */ -void /* PRIVATE */ -png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) -{ - png_byte buf[4]; - - png_debug(1, "in png_write_gAMA"); - - /* file_gamma is saved in 1/100,000ths */ - png_save_uint_32(buf, (png_uint_32)file_gamma); - png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); -} -#endif - -#ifdef PNG_WRITE_sRGB_SUPPORTED -/* Write a sRGB chunk */ -void /* PRIVATE */ -png_write_sRGB(png_structrp png_ptr, int srgb_intent) -{ - png_byte buf[1]; - - png_debug(1, "in png_write_sRGB"); - - if (srgb_intent >= PNG_sRGB_INTENT_LAST) - png_warning(png_ptr, - "Invalid sRGB rendering intent specified"); - - buf[0]=(png_byte)srgb_intent; - png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); -} -#endif - -#ifdef PNG_WRITE_iCCP_SUPPORTED -/* Write an iCCP chunk */ -void /* PRIVATE */ -png_write_iCCP(png_structrp png_ptr, png_const_charp name, - png_const_bytep profile) -{ - png_uint_32 name_len; - png_uint_32 profile_len; - png_byte new_name[81]; /* 1 byte for the compression byte */ - compression_state comp; - - png_debug(1, "in png_write_iCCP"); - - /* These are all internal problems: the profile should have been checked - * before when it was stored. - */ - if (profile == NULL) - png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */ - - profile_len = png_get_uint_32(profile); - - if (profile_len < 132) - png_error(png_ptr, "ICC profile too short"); - - if (profile_len & 0x03) - png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)"); - - { - png_uint_32 embedded_profile_len = png_get_uint_32(profile); - - if (profile_len != embedded_profile_len) - png_error(png_ptr, "Profile length does not match profile"); - } - - name_len = png_check_keyword(png_ptr, name, new_name); - - if (name_len == 0) - png_error(png_ptr, "iCCP: invalid keyword"); - - new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE; - - /* Make sure we include the NULL after the name and the compression type */ - ++name_len; - - png_text_compress_init(&comp, profile, profile_len); - - /* Allow for keyword terminator and compression byte */ - if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg); - - png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len); - - png_write_chunk_data(png_ptr, new_name, name_len); - - png_write_compressed_data_out(png_ptr, &comp); - - png_write_chunk_end(png_ptr); -} -#endif - -#ifdef PNG_WRITE_sPLT_SUPPORTED -/* Write a sPLT chunk */ -void /* PRIVATE */ -png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) -{ - png_uint_32 name_len; - png_byte new_name[80]; - png_byte entrybuf[10]; - png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); - png_size_t palette_size = entry_size * spalette->nentries; - png_sPLT_entryp ep; -#ifndef PNG_POINTER_INDEXING_SUPPORTED - int i; -#endif - - png_debug(1, "in png_write_sPLT"); - - name_len = png_check_keyword(png_ptr, spalette->name, new_name); - - if (name_len == 0) - png_error(png_ptr, "sPLT: invalid keyword"); - - /* Make sure we include the NULL after the name */ - png_write_chunk_header(png_ptr, png_sPLT, - (png_uint_32)(name_len + 2 + palette_size)); - - png_write_chunk_data(png_ptr, (png_bytep)new_name, - (png_size_t)(name_len + 1)); - - png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); - - /* Loop through each palette entry, writing appropriately */ -#ifdef PNG_POINTER_INDEXING_SUPPORTED - for (ep = spalette->entries; epentries + spalette->nentries; ep++) - { - if (spalette->depth == 8) - { - entrybuf[0] = (png_byte)ep->red; - entrybuf[1] = (png_byte)ep->green; - entrybuf[2] = (png_byte)ep->blue; - entrybuf[3] = (png_byte)ep->alpha; - png_save_uint_16(entrybuf + 4, ep->frequency); - } - - else - { - png_save_uint_16(entrybuf + 0, ep->red); - png_save_uint_16(entrybuf + 2, ep->green); - png_save_uint_16(entrybuf + 4, ep->blue); - png_save_uint_16(entrybuf + 6, ep->alpha); - png_save_uint_16(entrybuf + 8, ep->frequency); - } - - png_write_chunk_data(png_ptr, entrybuf, entry_size); - } -#else - ep=spalette->entries; - for (i = 0; i>spalette->nentries; i++) - { - if (spalette->depth == 8) - { - entrybuf[0] = (png_byte)ep[i].red; - entrybuf[1] = (png_byte)ep[i].green; - entrybuf[2] = (png_byte)ep[i].blue; - entrybuf[3] = (png_byte)ep[i].alpha; - png_save_uint_16(entrybuf + 4, ep[i].frequency); - } - - else - { - png_save_uint_16(entrybuf + 0, ep[i].red); - png_save_uint_16(entrybuf + 2, ep[i].green); - png_save_uint_16(entrybuf + 4, ep[i].blue); - png_save_uint_16(entrybuf + 6, ep[i].alpha); - png_save_uint_16(entrybuf + 8, ep[i].frequency); - } - - png_write_chunk_data(png_ptr, entrybuf, entry_size); - } -#endif - - png_write_chunk_end(png_ptr); -} -#endif - -#ifdef PNG_WRITE_sBIT_SUPPORTED -/* Write the sBIT chunk */ -void /* PRIVATE */ -png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) -{ - png_byte buf[4]; - png_size_t size; - - png_debug(1, "in png_write_sBIT"); - - /* Make sure we don't depend upon the order of PNG_COLOR_8 */ - if (color_type & PNG_COLOR_MASK_COLOR) - { - png_byte maxbits; - - maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : - png_ptr->usr_bit_depth); - - if (sbit->red == 0 || sbit->red > maxbits || - sbit->green == 0 || sbit->green > maxbits || - sbit->blue == 0 || sbit->blue > maxbits) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - - buf[0] = sbit->red; - buf[1] = sbit->green; - buf[2] = sbit->blue; - size = 3; - } - - else - { - if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - - buf[0] = sbit->gray; - size = 1; - } - - if (color_type & PNG_COLOR_MASK_ALPHA) - { - if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - - buf[size++] = sbit->alpha; - } - - png_write_complete_chunk(png_ptr, png_sBIT, buf, size); -} -#endif - -#ifdef PNG_WRITE_cHRM_SUPPORTED -/* Write the cHRM chunk */ -void /* PRIVATE */ -png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy) -{ - png_byte buf[32]; - - png_debug(1, "in png_write_cHRM"); - - /* Each value is saved in 1/100,000ths */ - png_save_int_32(buf, xy->whitex); - png_save_int_32(buf + 4, xy->whitey); - - png_save_int_32(buf + 8, xy->redx); - png_save_int_32(buf + 12, xy->redy); - - png_save_int_32(buf + 16, xy->greenx); - png_save_int_32(buf + 20, xy->greeny); - - png_save_int_32(buf + 24, xy->bluex); - png_save_int_32(buf + 28, xy->bluey); - - png_write_complete_chunk(png_ptr, png_cHRM, buf, 32); -} -#endif - -#ifdef PNG_WRITE_tRNS_SUPPORTED -/* Write the tRNS chunk */ -void /* PRIVATE */ -png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, - png_const_color_16p tran, int num_trans, int color_type) -{ - png_byte buf[6]; - - png_debug(1, "in png_write_tRNS"); - - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) - { - png_app_warning(png_ptr, - "Invalid number of transparent colors specified"); - return; - } - - /* Write the chunk out as it is */ - png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, - (png_size_t)num_trans); - } - - else if (color_type == PNG_COLOR_TYPE_GRAY) - { - /* One 16 bit value */ - if (tran->gray >= (1 << png_ptr->bit_depth)) - { - png_app_warning(png_ptr, - "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); - - return; - } - - png_save_uint_16(buf, tran->gray); - png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); - } - - else if (color_type == PNG_COLOR_TYPE_RGB) - { - /* Three 16 bit values */ - png_save_uint_16(buf, tran->red); - png_save_uint_16(buf + 2, tran->green); - png_save_uint_16(buf + 4, tran->blue); -#ifdef PNG_WRITE_16BIT_SUPPORTED - if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) -#else - if (buf[0] | buf[2] | buf[4]) -#endif - { - png_app_warning(png_ptr, - "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); - return; - } - - png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); - } - - else - { - png_app_warning(png_ptr, "Can't write tRNS with an alpha channel"); - } -} -#endif - -#ifdef PNG_WRITE_bKGD_SUPPORTED -/* Write the background chunk */ -void /* PRIVATE */ -png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) -{ - png_byte buf[6]; - - png_debug(1, "in png_write_bKGD"); - - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - if ( -#ifdef PNG_MNG_FEATURES_SUPPORTED - (png_ptr->num_palette || - (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && -#endif - back->index >= png_ptr->num_palette) - { - png_warning(png_ptr, "Invalid background palette index"); - return; - } - - buf[0] = back->index; - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); - } - - else if (color_type & PNG_COLOR_MASK_COLOR) - { - png_save_uint_16(buf, back->red); - png_save_uint_16(buf + 2, back->green); - png_save_uint_16(buf + 4, back->blue); -#ifdef PNG_WRITE_16BIT_SUPPORTED - if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) -#else - if (buf[0] | buf[2] | buf[4]) -#endif - { - png_warning(png_ptr, - "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); - - return; - } - - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); - } - - else - { - if (back->gray >= (1 << png_ptr->bit_depth)) - { - png_warning(png_ptr, - "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); - - return; - } - - png_save_uint_16(buf, back->gray); - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); - } -} -#endif - -#ifdef PNG_WRITE_hIST_SUPPORTED -/* Write the histogram */ -void /* PRIVATE */ -png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) -{ - int i; - png_byte buf[3]; - - png_debug(1, "in png_write_hIST"); - - if (num_hist > (int)png_ptr->num_palette) - { - png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, - png_ptr->num_palette); - - png_warning(png_ptr, "Invalid number of histogram entries specified"); - return; - } - - png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); - - for (i = 0; i < num_hist; i++) - { - png_save_uint_16(buf, hist[i]); - png_write_chunk_data(png_ptr, buf, (png_size_t)2); - } - - png_write_chunk_end(png_ptr); -} -#endif - -#ifdef PNG_WRITE_tEXt_SUPPORTED -/* Write a tEXt chunk */ -void /* PRIVATE */ -png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, - png_size_t text_len) -{ - png_uint_32 key_len; - png_byte new_key[80]; - - png_debug(1, "in png_write_tEXt"); - - key_len = png_check_keyword(png_ptr, key, new_key); - - if (key_len == 0) - png_error(png_ptr, "tEXt: invalid keyword"); - - if (text == NULL || *text == '\0') - text_len = 0; - - else - text_len = strlen(text); - - if (text_len > PNG_UINT_31_MAX - (key_len+1)) - png_error(png_ptr, "tEXt: text too long"); - - /* Make sure we include the 0 after the key */ - png_write_chunk_header(png_ptr, png_tEXt, - (png_uint_32)/*checked above*/(key_len + text_len + 1)); - /* - * We leave it to the application to meet PNG-1.0 requirements on the - * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of - * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. - * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. - */ - png_write_chunk_data(png_ptr, new_key, key_len + 1); - - if (text_len) - png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len); - - png_write_chunk_end(png_ptr); -} -#endif - -#ifdef PNG_WRITE_zTXt_SUPPORTED -/* Write a compressed text chunk */ -void /* PRIVATE */ -png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, - png_size_t text_len, int compression) -{ - png_uint_32 key_len; - png_byte new_key[81]; - compression_state comp; - - png_debug(1, "in png_write_zTXt"); - PNG_UNUSED(text_len) /* Always use strlen */ - - if (compression == PNG_TEXT_COMPRESSION_NONE) - { - png_write_tEXt(png_ptr, key, text, 0); - return; - } - - if (compression != PNG_TEXT_COMPRESSION_zTXt) - png_error(png_ptr, "zTXt: invalid compression type"); - - key_len = png_check_keyword(png_ptr, key, new_key); - - if (key_len == 0) - png_error(png_ptr, "zTXt: invalid keyword"); - - /* Add the compression method and 1 for the keyword separator. */ - new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; - ++key_len; - - /* Compute the compressed data; do it now for the length */ - png_text_compress_init(&comp, (png_const_bytep)text, - text == NULL ? 0 : strlen(text)); - - if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg); - - /* Write start of chunk */ - png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len); - - /* Write key */ - png_write_chunk_data(png_ptr, new_key, key_len); - - /* Write the compressed data */ - png_write_compressed_data_out(png_ptr, &comp); - - /* Close the chunk */ - png_write_chunk_end(png_ptr); -} -#endif - -#ifdef PNG_WRITE_iTXt_SUPPORTED -/* Write an iTXt chunk */ -void /* PRIVATE */ -png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, - png_const_charp lang, png_const_charp lang_key, png_const_charp text) -{ - png_uint_32 key_len, prefix_len; - png_size_t lang_len, lang_key_len; - png_byte new_key[82]; - compression_state comp; - - png_debug(1, "in png_write_iTXt"); - - key_len = png_check_keyword(png_ptr, key, new_key); - - if (key_len == 0) - png_error(png_ptr, "iTXt: invalid keyword"); - - /* Set the compression flag */ - switch (compression) - { - case PNG_ITXT_COMPRESSION_NONE: - case PNG_TEXT_COMPRESSION_NONE: - compression = new_key[++key_len] = 0; /* no compression */ - break; - - case PNG_TEXT_COMPRESSION_zTXt: - case PNG_ITXT_COMPRESSION_zTXt: - compression = new_key[++key_len] = 1; /* compressed */ - break; - - default: - png_error(png_ptr, "iTXt: invalid compression"); - } - - new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; - ++key_len; /* for the keywod separator */ - - /* We leave it to the application to meet PNG-1.0 requirements on the - * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of - * any non-Latin-1 characters except for NEWLINE. ISO PNG, however, - * specifies that the text is UTF-8 and this really doesn't require any - * checking. - * - * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. - * - * TODO: validate the language tag correctly (see the spec.) - */ - if (lang == NULL) lang = ""; /* empty language is valid */ - lang_len = strlen(lang)+1; - if (lang_key == NULL) lang_key = ""; /* may be empty */ - lang_key_len = strlen(lang_key)+1; - if (text == NULL) text = ""; /* may be empty */ - - prefix_len = key_len; - if (lang_len > PNG_UINT_31_MAX-prefix_len) - prefix_len = PNG_UINT_31_MAX; - else - prefix_len = (png_uint_32)(prefix_len + lang_len); - - if (lang_key_len > PNG_UINT_31_MAX-prefix_len) - prefix_len = PNG_UINT_31_MAX; - else - prefix_len = (png_uint_32)(prefix_len + lang_key_len); - - png_text_compress_init(&comp, (png_const_bytep)text, strlen(text)); - - if (compression) - { - if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg); - } - - else - { - if (comp.input_len > PNG_UINT_31_MAX-prefix_len) - png_error(png_ptr, "iTXt: uncompressed text too long"); - - /* So the string will fit in a chunk: */ - comp.output_len = (png_uint_32)/*SAFE*/comp.input_len; - } - - png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len); - - png_write_chunk_data(png_ptr, new_key, key_len); - - png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len); - - png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len); - - if (compression) - png_write_compressed_data_out(png_ptr, &comp); - - else - png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.input_len); - - png_write_chunk_end(png_ptr); -} -#endif - -#ifdef PNG_WRITE_oFFs_SUPPORTED -/* Write the oFFs chunk */ -void /* PRIVATE */ -png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset, - int unit_type) -{ - png_byte buf[9]; - - png_debug(1, "in png_write_oFFs"); - - if (unit_type >= PNG_OFFSET_LAST) - png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); - - png_save_int_32(buf, x_offset); - png_save_int_32(buf + 4, y_offset); - buf[8] = (png_byte)unit_type; - - png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); -} -#endif -#ifdef PNG_WRITE_pCAL_SUPPORTED -/* Write the pCAL chunk (described in the PNG extensions document) */ -void /* PRIVATE */ -png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, - png_int_32 X1, int type, int nparams, png_const_charp units, - png_charpp params) -{ - png_uint_32 purpose_len; - png_size_t units_len, total_len; - png_size_tp params_len; - png_byte buf[10]; - png_byte new_purpose[80]; - int i; - - png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); - - if (type >= PNG_EQUATION_LAST) - png_error(png_ptr, "Unrecognized equation type for pCAL chunk"); - - purpose_len = png_check_keyword(png_ptr, purpose, new_purpose); - - if (purpose_len == 0) - png_error(png_ptr, "pCAL: invalid keyword"); - - ++purpose_len; /* terminator */ - - png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); - units_len = strlen(units) + (nparams == 0 ? 0 : 1); - png_debug1(3, "pCAL units length = %d", (int)units_len); - total_len = purpose_len + units_len + 10; - - params_len = (png_size_tp)png_malloc(png_ptr, - (png_alloc_size_t)(nparams * (sizeof (png_size_t)))); - - /* Find the length of each parameter, making sure we don't count the - * null terminator for the last parameter. - */ - for (i = 0; i < nparams; i++) - { - params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1); - png_debug2(3, "pCAL parameter %d length = %lu", i, - (unsigned long)params_len[i]); - total_len += params_len[i]; - } - - png_debug1(3, "pCAL total length = %d", (int)total_len); - png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len); - png_write_chunk_data(png_ptr, new_purpose, purpose_len); - png_save_int_32(buf, X0); - png_save_int_32(buf + 4, X1); - buf[8] = (png_byte)type; - buf[9] = (png_byte)nparams; - png_write_chunk_data(png_ptr, buf, (png_size_t)10); - png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); - - for (i = 0; i < nparams; i++) - { - png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]); - } - - png_free(png_ptr, params_len); - png_write_chunk_end(png_ptr); -} -#endif - -#ifdef PNG_WRITE_sCAL_SUPPORTED -/* Write the sCAL chunk */ -void /* PRIVATE */ -png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, - png_const_charp height) -{ - png_byte buf[64]; - png_size_t wlen, hlen, total_len; - - png_debug(1, "in png_write_sCAL_s"); - - wlen = strlen(width); - hlen = strlen(height); - total_len = wlen + hlen + 2; - - if (total_len > 64) - { - png_warning(png_ptr, "Can't write sCAL (buffer too small)"); - return; - } - - buf[0] = (png_byte)unit; - memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ - memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ - - png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); - png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len); -} -#endif - -#ifdef PNG_WRITE_pHYs_SUPPORTED -/* Write the pHYs chunk */ -void /* PRIVATE */ -png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, - png_uint_32 y_pixels_per_unit, - int unit_type) -{ - png_byte buf[9]; - - png_debug(1, "in png_write_pHYs"); - - if (unit_type >= PNG_RESOLUTION_LAST) - png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); - - png_save_uint_32(buf, x_pixels_per_unit); - png_save_uint_32(buf + 4, y_pixels_per_unit); - buf[8] = (png_byte)unit_type; - - png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); -} -#endif - -#ifdef PNG_WRITE_tIME_SUPPORTED -/* Write the tIME chunk. Use either png_convert_from_struct_tm() - * or png_convert_from_time_t(), or fill in the structure yourself. - */ -void /* PRIVATE */ -png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) -{ - png_byte buf[7]; - - png_debug(1, "in png_write_tIME"); - - if (mod_time->month > 12 || mod_time->month < 1 || - mod_time->day > 31 || mod_time->day < 1 || - mod_time->hour > 23 || mod_time->second > 60) - { - png_warning(png_ptr, "Invalid time specified for tIME chunk"); - return; - } - - png_save_uint_16(buf, mod_time->year); - buf[2] = mod_time->month; - buf[3] = mod_time->day; - buf[4] = mod_time->hour; - buf[5] = mod_time->minute; - buf[6] = mod_time->second; - - png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); -} -#endif - -/* Initializes the row writing capability of libpng */ -void /* PRIVATE */ -png_write_start_row(png_structrp png_ptr) -{ -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif - - png_alloc_size_t buf_size; - int usr_pixel_depth; - - png_debug(1, "in png_write_start_row"); - - usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; - buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1; - - /* 1.5.6: added to allow checking in the row write code. */ - png_ptr->transformed_pixel_depth = png_ptr->pixel_depth; - png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; - - /* Set up row buffer */ - png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size); - - png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; - -#ifdef PNG_WRITE_FILTER_SUPPORTED - /* Set up filtering buffer, if using this filter */ - if (png_ptr->do_filter & PNG_FILTER_SUB) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); - - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } - - /* We only need to keep the previous row if we are using one of these. */ - if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) - { - /* Set up previous row buffer */ - png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size); - - if (png_ptr->do_filter & PNG_FILTER_UP) - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - png_ptr->rowbytes + 1); - - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } - - if (png_ptr->do_filter & PNG_FILTER_AVG) - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - png_ptr->rowbytes + 1); - - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } - - if (png_ptr->do_filter & PNG_FILTER_PAETH) - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - png_ptr->rowbytes + 1); - - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } - } -#endif /* PNG_WRITE_FILTER_SUPPORTED */ - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* If interlaced, we need to set up width and height of pass */ - if (png_ptr->interlaced) - { - if (!(png_ptr->transformations & PNG_INTERLACE)) - { - png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - - png_pass_ystart[0]) / png_pass_yinc[0]; - - png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - - png_pass_start[0]) / png_pass_inc[0]; - } - - else - { - png_ptr->num_rows = png_ptr->height; - png_ptr->usr_width = png_ptr->width; - } - } - - else -#endif - { - png_ptr->num_rows = png_ptr->height; - png_ptr->usr_width = png_ptr->width; - } -} - -/* Internal use only. Called when finished processing a row of data. */ -void /* PRIVATE */ -png_write_finish_row(png_structrp png_ptr) -{ -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif - - png_debug(1, "in png_write_finish_row"); - - /* Next row */ - png_ptr->row_number++; - - /* See if we are done */ - if (png_ptr->row_number < png_ptr->num_rows) - return; - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* If interlaced, go to next pass */ - if (png_ptr->interlaced) - { - png_ptr->row_number = 0; - if (png_ptr->transformations & PNG_INTERLACE) - { - png_ptr->pass++; - } - - else - { - /* Loop until we find a non-zero width or height pass */ - do - { - png_ptr->pass++; - - if (png_ptr->pass >= 7) - break; - - png_ptr->usr_width = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - - if (png_ptr->transformations & PNG_INTERLACE) - break; - - } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); - - } - - /* Reset the row above the image for the next pass */ - if (png_ptr->pass < 7) - { - if (png_ptr->prev_row != NULL) - memset(png_ptr->prev_row, 0, - (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* - png_ptr->usr_bit_depth, png_ptr->width)) + 1); - - return; - } - } -#endif - - /* If we get here, we've just written the last row, so we need - to flush the compressor */ - png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH); -} - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED -/* Pick out the correct pixels for the interlace pass. - * The basic idea here is to go through the row with a source - * pointer and a destination pointer (sp and dp), and copy the - * correct pixels for the pass. As the row gets compacted, - * sp will always be >= dp, so we should never overwrite anything. - * See the default: case for the easiest code to understand. - */ -void /* PRIVATE */ -png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) -{ - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - png_debug(1, "in png_do_write_interlace"); - - /* We don't have to do anything on the last pass (6) */ - if (pass < 6) - { - /* Each pixel depth is handled separately */ - switch (row_info->pixel_depth) - { - case 1: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - dp = row; - d = 0; - shift = 7; - - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 3); - value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; - d |= (value << shift); - - if (shift == 0) - { - shift = 7; - *dp++ = (png_byte)d; - d = 0; - } - - else - shift--; - - } - if (shift != 7) - *dp = (png_byte)d; - - break; - } - - case 2: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - dp = row; - shift = 6; - d = 0; - - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 2); - value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; - d |= (value << shift); - - if (shift == 0) - { - shift = 6; - *dp++ = (png_byte)d; - d = 0; - } - - else - shift -= 2; - } - if (shift != 6) - *dp = (png_byte)d; - - break; - } - - case 4: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - dp = row; - shift = 4; - d = 0; - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 1); - value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; - d |= (value << shift); - - if (shift == 0) - { - shift = 4; - *dp++ = (png_byte)d; - d = 0; - } - - else - shift -= 4; - } - if (shift != 4) - *dp = (png_byte)d; - - break; - } - - default: - { - png_bytep sp; - png_bytep dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - png_size_t pixel_bytes; - - /* Start at the beginning */ - dp = row; - - /* Find out how many bytes each pixel takes up */ - pixel_bytes = (row_info->pixel_depth >> 3); - - /* Loop through the row, only looking at the pixels that matter */ - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - /* Find out where the original pixel is */ - sp = row + (png_size_t)i * pixel_bytes; - - /* Move the pixel */ - if (dp != sp) - memcpy(dp, sp, pixel_bytes); - - /* Next pixel */ - dp += pixel_bytes; - } - break; - } - } - /* Set new row width */ - row_info->width = (row_info->width + - png_pass_inc[pass] - 1 - - png_pass_start[pass]) / - png_pass_inc[pass]; - - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_info->width); - } -} -#endif - -/* This filters the row, chooses which filter to use, if it has not already - * been specified by the application, and then writes the row out with the - * chosen filter. - */ -static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t row_bytes); - -#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) -#define PNG_HISHIFT 10 -#define PNG_LOMASK ((png_uint_32)0xffffL) -#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) -void /* PRIVATE */ -png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) -{ - png_bytep best_row; -#ifdef PNG_WRITE_FILTER_SUPPORTED - png_bytep prev_row, row_buf; - png_uint_32 mins, bpp; - png_byte filter_to_do = png_ptr->do_filter; - png_size_t row_bytes = row_info->rowbytes; -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - int num_p_filters = png_ptr->num_prev_filters; -#endif - - png_debug(1, "in png_write_find_filter"); - -#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) - { - /* These will never be selected so we need not test them. */ - filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); - } -#endif - - /* Find out how many bytes offset each pixel is */ - bpp = (row_info->pixel_depth + 7) >> 3; - - prev_row = png_ptr->prev_row; -#endif - best_row = png_ptr->row_buf; -#ifdef PNG_WRITE_FILTER_SUPPORTED - row_buf = best_row; - mins = PNG_MAXSUM; - - /* The prediction method we use is to find which method provides the - * smallest value when summing the absolute values of the distances - * from zero, using anything >= 128 as negative numbers. This is known - * as the "minimum sum of absolute differences" heuristic. Other - * heuristics are the "weighted minimum sum of absolute differences" - * (experimental and can in theory improve compression), and the "zlib - * predictive" method (not implemented yet), which does test compressions - * of lines using different filter methods, and then chooses the - * (series of) filter(s) that give minimum compressed data size (VERY - * computationally expensive). - * - * GRR 980525: consider also - * - * (1) minimum sum of absolute differences from running average (i.e., - * keep running sum of non-absolute differences & count of bytes) - * [track dispersion, too? restart average if dispersion too large?] - * - * (1b) minimum sum of absolute differences from sliding average, probably - * with window size <= deflate window (usually 32K) - * - * (2) minimum sum of squared differences from zero or running average - * (i.e., ~ root-mean-square approach) - */ - - - /* We don't need to test the 'no filter' case if this is the only filter - * that has been chosen, as it doesn't actually do anything to the data. - */ - if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE) - { - png_bytep rp; - png_uint_32 sum = 0; - png_size_t i; - int v; - - for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) - { - v = *rp; - sum += (v < 128) ? v : 256 - v; - } - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - png_uint_32 sumhi, sumlo; - int j; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ - - /* Reduce the sum if we match any of the previous rows */ - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - /* Factor in the cost of this filter (this is here for completeness, - * but it makes no sense to have a "cost" for the NONE filter, as - * it has the minimum possible computational cost - none). - */ - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> - PNG_COST_SHIFT; - - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - mins = sum; - } - - /* Sub filter */ - if (filter_to_do == PNG_FILTER_SUB) - /* It's the only filter so no testing is needed */ - { - png_bytep rp, lp, dp; - png_size_t i; - - for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; - i++, rp++, dp++) - { - *dp = *rp; - } - - for (lp = row_buf + 1; i < row_bytes; - i++, rp++, lp++, dp++) - { - *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); - } - - best_row = png_ptr->sub_row; - } - - else if (filter_to_do & PNG_FILTER_SUB) - { - png_bytep rp, dp, lp; - png_uint_32 sum = 0, lmins = mins; - png_size_t i; - int v; - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - /* We temporarily increase the "minimum sum" by the factor we - * would reduce the sum of this filter, so that we can do the - * early exit comparison without scaling the sum each time. - */ - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; - i++, rp++, dp++) - { - v = *dp = *rp; - - sum += (v < 128) ? v : 256 - v; - } - - for (lp = row_buf + 1; i < row_bytes; - i++, rp++, lp++, dp++) - { - v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) - { - sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - mins = sum; - best_row = png_ptr->sub_row; - } - } - - /* Up filter */ - if (filter_to_do == PNG_FILTER_UP) - { - png_bytep rp, dp, pp; - png_size_t i; - - for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, - pp = prev_row + 1; i < row_bytes; - i++, rp++, pp++, dp++) - { - *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); - } - - best_row = png_ptr->up_row; - } - - else if (filter_to_do & PNG_FILTER_UP) - { - png_bytep rp, dp, pp; - png_uint_32 sum = 0, lmins = mins; - png_size_t i; - int v; - - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, - pp = prev_row + 1; i < row_bytes; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - mins = sum; - best_row = png_ptr->up_row; - } - } - - /* Avg filter */ - if (filter_to_do == PNG_FILTER_AVG) - { - png_bytep rp, dp, pp, lp; - png_uint_32 i; - - for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); - } - - for (lp = row_buf + 1; i < row_bytes; i++) - { - *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) - & 0xff); - } - best_row = png_ptr->avg_row; - } - - else if (filter_to_do & PNG_FILTER_AVG) - { - png_bytep rp, dp, pp, lp; - png_uint_32 sum = 0, lmins = mins; - png_size_t i; - int v; - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); - - sum += (v < 128) ? v : 256 - v; - } - - for (lp = row_buf + 1; i < row_bytes; i++) - { - v = *dp++ = - (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - mins = sum; - best_row = png_ptr->avg_row; - } - } - - /* Paeth filter */ - if (filter_to_do == PNG_FILTER_PAETH) - { - png_bytep rp, dp, pp, cp, lp; - png_size_t i; - - for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - } - - for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) - { - int a, b, c, pa, pb, pc, p; - - b = *pp++; - c = *cp++; - a = *lp++; - - p = b - c; - pc = a - c; - -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; - - *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); - } - best_row = png_ptr->paeth_row; - } - - else if (filter_to_do & PNG_FILTER_PAETH) - { - png_bytep rp, dp, pp, cp, lp; - png_uint_32 sum = 0, lmins = mins; - png_size_t i; - int v; - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - - sum += (v < 128) ? v : 256 - v; - } - - for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) - { - int a, b, c, pa, pb, pc, p; - - b = *pp++; - c = *cp++; - a = *lp++; - -#ifndef PNG_SLOW_PAETH - p = b - c; - pc = a - c; -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; -#else /* PNG_SLOW_PAETH */ - p = a + b - c; - pa = abs(p - a); - pb = abs(p - b); - pc = abs(p - c); - - if (pa <= pb && pa <= pc) - p = a; - - else if (pb <= pc) - p = b; - - else - p = c; -#endif /* PNG_SLOW_PAETH */ - - v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - best_row = png_ptr->paeth_row; - } - } -#endif /* PNG_WRITE_FILTER_SUPPORTED */ - - /* Do the actual writing of the filtered row data from the chosen filter. */ - png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1); - -#ifdef PNG_WRITE_FILTER_SUPPORTED -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - /* Save the type of filter we picked this time for future calculations */ - if (png_ptr->num_prev_filters > 0) - { - int j; - - for (j = 1; j < num_p_filters; j++) - { - png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; - } - - png_ptr->prev_filters[j] = best_row[0]; - } -#endif -#endif /* PNG_WRITE_FILTER_SUPPORTED */ -} - - -/* Do the actual writing of a previously filtered row. */ -static void -png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t full_row_length/*includes filter byte*/) -{ - png_debug(1, "in png_write_filtered_row"); - - png_debug1(2, "filter = %d", filtered_row[0]); - - png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH); - - /* Swap the current and previous rows */ - if (png_ptr->prev_row != NULL) - { - png_bytep tptr; - - tptr = png_ptr->prev_row; - png_ptr->prev_row = png_ptr->row_buf; - png_ptr->row_buf = tptr; - } - - /* Finish row - updates counters and flushes zlib if last row */ - png_write_finish_row(png_ptr); - -#ifdef PNG_WRITE_FLUSH_SUPPORTED - png_ptr->flush_rows++; - - if (png_ptr->flush_dist > 0 && - png_ptr->flush_rows >= png_ptr->flush_dist) - { - png_write_flush(png_ptr); - } -#endif -} -#endif /* PNG_WRITE_SUPPORTED */ + +/* pngwutil.c - utilities to write a PNG file + * + * Last changed in libpng 1.7.0 [(PENDING RELEASE)] + * Copyright (c) 1998-2014 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void PNGAPI +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void PNGAPI +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} +#endif + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void PNGAPI +png_write_sig(png_structrp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the signature is being written */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; +#endif + + /* Write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)(8 - png_ptr->sig_bytes)); + + if (png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +static void +png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name, + png_uint_32 length) +{ + png_byte buf[8]; + +#if defined(PNG_DEBUG) && (PNG_DEBUG > 0) + PNG_CSTRING_FROM_CHUNK(buf, chunk_name); + png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length); +#endif + + if (png_ptr == NULL) + return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk header is being written. + * PNG_IO_CHUNK_HDR requires a single I/O call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; +#endif + + /* Write the length and the chunk name */ + png_save_uint_32(buf, length); + png_save_uint_32(buf + 4, chunk_name); + png_write_data(png_ptr, buf, 8); + + /* Put the chunk name into png_ptr->chunk_name */ + png_ptr->chunk_name = chunk_name; + + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + + png_calculate_crc(png_ptr, buf + 4, 4); + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that chunk data will (possibly) be written. + * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; +#endif +} + +void PNGAPI +png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, + png_uint_32 length) +{ + png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length); +} + +/* Write the data of a PNG chunk started with png_write_chunk_header(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_header(). + */ +void PNGAPI +png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, + png_size_t length) +{ + /* Write the data, and run the CRC over it */ + if (png_ptr == NULL) + return; + + if (data != NULL && length > 0) + { + png_write_data(png_ptr, data, length); + + /* Update the CRC after writing the data, + * in case that the user I/O routine alters it. + */ + png_calculate_crc(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_header(). */ +void PNGAPI +png_write_chunk_end(png_structrp png_ptr) +{ + png_byte buf[4]; + + if (png_ptr == NULL) return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk CRC is being written. + * PNG_IO_CHUNK_CRC requires a single I/O function call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; +#endif + + /* Write the crc in a single operation */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +static void +png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, + png_const_bytep data, png_size_t length) +{ + if (png_ptr == NULL) + return; + + /* On 64 bit architectures 'length' may not fit in a png_uint_32. */ + if (length > PNG_UINT_31_MAX) + png_error(png_ptr, "length exceeds PNG maxima"); + + png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, length); + png_write_chunk_end(png_ptr); +} + +/* This is the API that calls the internal function above. */ +void PNGAPI +png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, + png_const_bytep data, png_size_t length) +{ + png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, + length); +} + +/* This is used below to find the size of an image to pass to png_deflate_claim, + * so it only needs to be accurate if the size is less than 16384 bytes (the + * point at which a lower LZ window size can be used.) + */ +static png_alloc_size_t +png_image_size(png_structrp png_ptr) +{ + /* Only return sizes up to the maximum of a png_uint_32, do this by limiting + * the width and height used to 15 bits. + */ + png_uint_32 h = png_ptr->height; + + if (png_ptr->rowbytes < 32768 && h < 32768) + { + if (png_ptr->interlaced) + { + /* Interlacing makes the image larger because of the replication of + * both the filter byte and the padding to a byte boundary. + */ + png_uint_32 w = png_ptr->width; + unsigned int pd = png_ptr->pixel_depth; + png_alloc_size_t cb_base; + int pass; + + for (cb_base=0, pass=0; pass<=6; ++pass) + { + png_uint_32 pw = PNG_PASS_COLS(w, pass); + + if (pw > 0) + cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass); + } + + return cb_base; + } + + else + return (png_ptr->rowbytes+1) * h; + } + + else + return 0xffffffffU; +} + +#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + /* This is the code to hack the first two bytes of the deflate stream (the + * deflate header) to correct the windowBits value to match the actual data + * size. Note that the second argument is the *uncompressed* size but the + * first argument is the *compressed* data (and it must be deflate + * compressed.) + */ +static void +optimize_cmf(png_bytep data, png_alloc_size_t data_size) +{ + /* Optimize the CMF field in the zlib stream. The resultant zlib stream is + * still compliant to the stream specification. + */ + if (data_size <= 16384) /* else windowBits must be 15 */ + { + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + unsigned int z_cinfo; + unsigned int half_z_window_size; + + z_cinfo = z_cmf >> 4; + half_z_window_size = 1U << (z_cinfo + 7); + + if (data_size <= half_z_window_size) /* else no change */ + { + unsigned int tmp; + + do + { + half_z_window_size >>= 1; + --z_cinfo; + } + while (z_cinfo > 0 && data_size <= half_z_window_size); + + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + + data[0] = (png_byte)z_cmf; + tmp = data[1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + data[1] = (png_byte)tmp; + } + } + } +} +#else +# define optimize_cmf(dp,dl) ((void)0) +#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ + +/* Initialize the compressor for the appropriate type of compression. */ +static int +png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, + png_alloc_size_t data_size) +{ + if (png_ptr->zowner != 0) + { + char msg[64]; + + PNG_STRING_FROM_CHUNK(msg, owner); + msg[4] = ':'; + msg[5] = ' '; + PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner); + /* So the message that results is " using zstream"; this is an + * internal error, but is very useful for debugging. i18n requirements + * are minimal. + */ + (void)png_safecat(msg, (sizeof msg), 10, " using zstream"); +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC + png_warning(png_ptr, msg); + + /* Attempt sane error recovery */ + if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */ + { + png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT"); + return Z_STREAM_ERROR; + } + + png_ptr->zowner = 0; +# else + png_error(png_ptr, msg); +# endif + } + + { + int level = png_ptr->zlib_level; + int method = png_ptr->zlib_method; + int windowBits = png_ptr->zlib_window_bits; + int memLevel = png_ptr->zlib_mem_level; + int strategy; /* set below */ + int ret; /* zlib return code */ + + if (owner == png_IDAT) + { + if (png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) + strategy = png_ptr->zlib_strategy; + + else if (png_ptr->do_filter != PNG_FILTER_NONE) + strategy = PNG_Z_DEFAULT_STRATEGY; + + else + strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY; + } + + else + { +# ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + level = png_ptr->zlib_text_level; + method = png_ptr->zlib_text_method; + windowBits = png_ptr->zlib_text_window_bits; + memLevel = png_ptr->zlib_text_mem_level; + strategy = png_ptr->zlib_text_strategy; +# else + /* If customization is not supported the values all come from the + * IDAT values except for the strategy, which is fixed to the + * default. (This is the pre-1.6.0 behavior too, although it was + * implemented in a very different way.) + */ + strategy = Z_DEFAULT_STRATEGY; +# endif + } + + /* Adjust 'windowBits' down if larger than 'data_size'; to stop this + * happening just pass 32768 as the data_size parameter. Notice that zlib + * requires an extra 262 bytes in the window in addition to the data to be + * able to see the whole of the data, so if data_size+262 takes us to the + * next windowBits size we need to fix up the value later. (Because even + * though deflate needs the extra window, inflate does not!) + */ + if (data_size <= 16384) + { + /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to + * work round a Microsoft Visual C misbehavior which, contrary to C-90, + * widens the result of the following shift to 64-bits if (and, + * apparently, only if) it is used in a test. + */ + unsigned int half_window_size = 1U << (windowBits-1); + + while (data_size + 262 <= half_window_size) + { + half_window_size >>= 1; + --windowBits; + } + } + + /* Check against the previous initialized values, if any. */ + if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) && + (png_ptr->zlib_set_level != level || + png_ptr->zlib_set_method != method || + png_ptr->zlib_set_window_bits != windowBits || + png_ptr->zlib_set_mem_level != memLevel || + png_ptr->zlib_set_strategy != strategy)) + { + if (deflateEnd(&png_ptr->zstream) != Z_OK) + png_warning(png_ptr, "deflateEnd failed (ignored)"); + + png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED; + } + + /* For safety clear out the input and output pointers (currently zlib + * doesn't use them on Init, but it might in the future). + */ + png_ptr->zstream.next_in = NULL; + png_ptr->zstream.avail_in = 0; + png_ptr->zstream.next_out = NULL; + png_ptr->zstream.avail_out = 0; + + /* Now initialize if required, setting the new parameters, otherwise just + * to a simple reset to the previous parameters. + */ + if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) + ret = deflateReset(&png_ptr->zstream); + + else + { + ret = deflateInit2(&png_ptr->zstream, level, method, windowBits, + memLevel, strategy); + + if (ret == Z_OK) + png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; + } + + /* The return code is from either deflateReset or deflateInit2; they have + * pretty much the same set of error codes. + */ + if (ret == Z_OK) + png_ptr->zowner = owner; + + else + png_zstream_error(png_ptr, ret); + + return ret; + } +} + +/* Clean up (or trim) a linked list of compression buffers. */ +void /* PRIVATE */ +png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp) +{ + png_compression_bufferp list = *listp; + + if (list != NULL) + { + *listp = NULL; + + do + { + png_compression_bufferp next = list->next; + + png_free(png_ptr, list); + list = next; + } + while (list != NULL); + } +} + +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +/* This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller to allow access to the relevant local variables. + * + * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size + * temporary buffers. From 1.6.0 it is retained in png_struct so that it will + * be correctly freed in the event of a write error (previous implementations + * just leaked memory.) + */ +typedef struct +{ + png_const_bytep input; /* The uncompressed input data */ + png_alloc_size_t input_len; /* Its length */ + png_uint_32 output_len; /* Final compressed length */ + png_byte output[1024]; /* First block of output */ +} compression_state; + +static void +png_text_compress_init(compression_state *comp, png_const_bytep input, + png_alloc_size_t input_len) +{ + comp->input = input; + comp->input_len = input_len; + comp->output_len = 0; +} + +/* Compress the data in the compression state input */ +static int +png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, + compression_state *comp, png_uint_32 prefix_len) +{ + int ret; + + /* To find the length of the output it is necessary to first compress the + * input, the result is buffered rather than using the two-pass algorithm + * that is used on the inflate side; deflate is assumed to be slower and a + * PNG writer is assumed to have more memory available than a PNG reader. + * + * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an + * upper limit on the output size, but it is always bigger than the input + * size so it is likely to be more efficient to use this linked-list + * approach. + */ + ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len); + + if (ret != Z_OK) + return ret; + + /* Set up the compression buffers, we need a loop here to avoid overflowing a + * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited + * by the output buffer size, so there is no need to check that. Since this + * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits + * in size. + */ + { + png_compression_bufferp *end = &png_ptr->zbuffer_list; + png_alloc_size_t input_len = comp->input_len; /* may be zero! */ + png_uint_32 output_len; + + /* zlib updates these for us: */ + png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input); + png_ptr->zstream.avail_in = 0; /* Set below */ + png_ptr->zstream.next_out = comp->output; + png_ptr->zstream.avail_out = (sizeof comp->output); + + output_len = png_ptr->zstream.avail_out; + + do + { + uInt avail_in = ZLIB_IO_MAX; + + if (avail_in > input_len) + avail_in = (uInt)input_len; + + input_len -= avail_in; + + png_ptr->zstream.avail_in = avail_in; + + if (png_ptr->zstream.avail_out == 0) + { + png_compression_buffer *next; + + /* Chunk data is limited to 2^31 bytes in length, so the prefix + * length must be counted here. + */ + if (output_len + prefix_len > PNG_UINT_31_MAX) + { + ret = Z_MEM_ERROR; + break; + } + + /* Need a new (malloc'ed) buffer, but there may be one present + * already. + */ + next = *end; + if (next == NULL) + { + next = png_voidcast(png_compression_bufferp, png_malloc_base + (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); + + if (next == NULL) + { + ret = Z_MEM_ERROR; + break; + } + + /* Link in this buffer (so that it will be freed later) */ + next->next = NULL; + *end = next; + } + + png_ptr->zstream.next_out = next->output; + png_ptr->zstream.avail_out = png_ptr->zbuffer_size; + output_len += png_ptr->zstream.avail_out; + + /* Move 'end' to the next buffer pointer. */ + end = &next->next; + } + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, + input_len > 0 ? Z_NO_FLUSH : Z_FINISH); + + /* Claw back input data that was not consumed (because avail_in is + * reset above every time round the loop). + */ + input_len += png_ptr->zstream.avail_in; + png_ptr->zstream.avail_in = 0; /* safety */ + } + while (ret == Z_OK); + + /* There may be some space left in the last output buffer, this needs to + * be subtracted from output_len. + */ + output_len -= png_ptr->zstream.avail_out; + png_ptr->zstream.avail_out = 0; /* safety */ + comp->output_len = output_len; + + /* Now double check the output length, put in a custom message if it is + * too long. Otherwise ensure the z_stream::msg pointer is set to + * something. + */ + if (output_len + prefix_len >= PNG_UINT_31_MAX) + { + png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long"); + ret = Z_MEM_ERROR; + } + + else + png_zstream_error(png_ptr, ret); + + /* Reset zlib for another zTXt/iTXt or image data */ + png_ptr->zowner = 0; + + /* The only success case is Z_STREAM_END, input_len must be 0, if not this + * is an internal error. + */ + if (ret == Z_STREAM_END && input_len == 0) + { + /* Fix up the deflate header, if required */ + optimize_cmf(comp->output, comp->input_len); + + /* But Z_OK is returned, not Z_STREAM_END; this allows the claim + * function above to return Z_STREAM_END on an error (though it never + * does in the current versions of zlib.) + */ + return Z_OK; + } + + else + return ret; + } +} + +/* Ship the compressed text out via chunk writes */ +static void +png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp) +{ + png_uint_32 output_len = comp->output_len; + png_const_bytep output = comp->output; + png_uint_32 avail = (sizeof comp->output); + png_compression_buffer *next = png_ptr->zbuffer_list; + + for (;;) + { + if (avail > output_len) + avail = output_len; + + png_write_chunk_data(png_ptr, output, avail); + + output_len -= avail; + + if (output_len == 0 || next == NULL) + break; + + avail = png_ptr->zbuffer_size; + output = next->output; + next = next->next; + } + + /* This is an internal error; 'next' must have been NULL! */ + if (output_len > 0) + png_error(png_ptr, "error writing ancillary chunked compressed data"); +} +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The 'new_key' buffer must be 80 characters in size (for the keyword plus a + * trailing '\0'). If this routine returns 0 then there was no keyword, or a + * valid one could not be generated, and the caller must png_error. + */ +static png_uint_32 +png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) +{ + png_const_charp orig_key = key; + png_uint_32 key_len = 0; + int bad_character = 0; + int space = 1; + + png_debug(1, "in png_check_keyword"); + + if (key == NULL) + { + *new_key = 0; + return 0; + } + + while (*key && key_len < 79) + { + png_byte ch = (png_byte)(0xff & *key++); + + if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) + *new_key++ = ch, ++key_len, space = 0; + + else if (space == 0) + { + /* A space or an invalid character when one wasn't seen immediately + * before; output just a space. + */ + *new_key++ = 32, ++key_len, space = 1; + + /* If the character was not a space then it is invalid. */ + if (ch != 32) + bad_character = ch; + } + + else if (bad_character == 0) + bad_character = ch; /* just skip it, record the first error */ + } + + if (key_len > 0 && space) /* trailing space */ + { + --key_len, --new_key; + if (bad_character == 0) + bad_character = 32; + } + + /* Terminate the keyword */ + *new_key = 0; + + if (key_len == 0) + return 0; + + /* Try to only output one warning per keyword: */ + if (*key) /* keyword too long */ + png_warning(png_ptr, "keyword truncated"); + + else if (bad_character != 0) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter(p, 1, orig_key); + png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character); + + png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'"); + } + + return key_len; +} +#endif + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ + png_byte buf[13]; /* Buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR"); + + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: +#ifdef PNG_WRITE_16BIT_SUPPORTED + case 16: +#endif + png_ptr->channels = 1; break; + + default: + png_error(png_ptr, + "Invalid bit depth for grayscale image"); + } + break; + + case PNG_COLOR_TYPE_RGB: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + png_error(png_ptr, "Invalid bit depth for RGB image"); + + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + png_ptr->channels = 1; + break; + + default: + png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + png_error(png_ptr, "Invalid bit depth for RGBA image"); + + png_ptr->channels = 4; + break; + + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* Save the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + /* Set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* Pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* Write the chunk */ + png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); + + if ((png_ptr->do_filter) == PNG_NO_FILTERS) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + + png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ +} + +/* Write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, + png_uint_32 num_pal) +{ + png_uint_32 i; + png_const_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE"); + + if (( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d", png_ptr->num_palette); + + png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); +#ifdef PNG_POINTER_INDEXING_SUPPORTED + + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } + +#else + /* This is a little slower but some buggy compilers need to do this + * instead + */ + pal_ptr=palette; + + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } + +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* This is similar to png_text_compress, above, except that it does not require + * all of the data at once and, instead of buffering the compressed result, + * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out + * because it calls the write interface. As a result it does its own error + * reporting and does not return an error code. In the event of error it will + * just call png_error. The input data length may exceed 32-bits. The 'flush' + * parameter is exactly the same as that to deflate, with the following + * meanings: + * + * Z_NO_FLUSH: normal incremental output of compressed data + * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush + * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up + * + * The routine manages the acquire and release of the png_ptr->zstream by + * checking and (at the end) clearing png_ptr->zowner, it does some sanity + * checks on the 'mode' flags while doing this. + */ +void /* PRIVATE */ +png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, + png_alloc_size_t input_len, int flush) +{ + if (png_ptr->zowner != png_IDAT) + { + /* First time. Ensure we have a temporary buffer for compression and + * trim the buffer list if it has more than one entry to free memory. + * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been + * created at this point, but the check here is quick and safe. + */ + if (png_ptr->zbuffer_list == NULL) + { + png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp, + png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); + png_ptr->zbuffer_list->next = NULL; + } + + else + png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next); + + /* It is a terminal error if we can't claim the zstream. */ + if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg); + + /* The output state is maintained in png_ptr->zstream, so it must be + * initialized here after the claim. + */ + png_ptr->zstream.next_out = png_ptr->zbuffer_list->output; + png_ptr->zstream.avail_out = png_ptr->zbuffer_size; + } + + /* Now loop reading and writing until all the input is consumed or an error + * terminates the operation. The _out values are maintained across calls to + * this function, but the input must be reset each time. + */ + png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); + png_ptr->zstream.avail_in = 0; /* set below */ + for (;;) + { + int ret; + + /* INPUT: from the row data */ + uInt avail = ZLIB_IO_MAX; + + if (avail > input_len) + avail = (uInt)input_len; /* safe because of the check */ + + png_ptr->zstream.avail_in = avail; + input_len -= avail; + + ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush); + + /* Include as-yet unconsumed input */ + input_len += png_ptr->zstream.avail_in; + png_ptr->zstream.avail_in = 0; + + /* OUTPUT: write complete IDAT chunks when avail_out drops to zero, note + * that these two zstream fields are preserved across the calls, therefore + * there is no need to set these up on entry to the loop. + */ + if (png_ptr->zstream.avail_out == 0) + { + png_bytep data = png_ptr->zbuffer_list->output; + uInt size = png_ptr->zbuffer_size; + + /* Write an IDAT containing the data then reset the buffer. The + * first IDAT may need deflate header optimization. + */ +# ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + optimize_cmf(data, png_image_size(png_ptr)); +# endif + + png_write_complete_chunk(png_ptr, png_IDAT, data, size); + png_ptr->mode |= PNG_HAVE_IDAT; + + png_ptr->zstream.next_out = data; + png_ptr->zstream.avail_out = size; + + /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with + * the same flush parameter until it has finished output, for NO_FLUSH + * it doesn't matter. + */ + if (ret == Z_OK && flush != Z_NO_FLUSH) + continue; + } + + /* The order of these checks doesn't matter much; it just effect which + * possible error might be detected if multiple things go wrong at once. + */ + if (ret == Z_OK) /* most likely return code! */ + { + /* If all the input has been consumed then just return. If Z_FINISH + * was used as the flush parameter something has gone wrong if we get + * here. + */ + if (input_len == 0) + { + if (flush == Z_FINISH) + png_error(png_ptr, "Z_OK on Z_FINISH with output space"); + + return; + } + } + + else if (ret == Z_STREAM_END && flush == Z_FINISH) + { + /* This is the end of the IDAT data; any pending output must be + * flushed. For small PNG files we may still be at the beginning. + */ + png_bytep data = png_ptr->zbuffer_list->output; + uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out; + +# ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + optimize_cmf(data, png_image_size(png_ptr)); +# endif + + png_write_complete_chunk(png_ptr, png_IDAT, data, size); + png_ptr->zstream.avail_out = 0; + png_ptr->zstream.next_out = NULL; + png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; + + png_ptr->zowner = 0; /* Release the stream */ + return; + } + + else + { + /* This is an error condition. */ + png_zstream_error(png_ptr, ret); + png_error(png_ptr, png_ptr->zstream.msg); + } + } +} + +/* Write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structrp png_ptr) +{ + png_debug(1, "in png_write_IEND"); + + png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#ifdef PNG_WRITE_gAMA_SUPPORTED +/* Write a gAMA chunk */ +void /* PRIVATE */ +png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) +{ + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, (png_uint_32)file_gamma); + png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); +} +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +/* Write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structrp png_ptr, int srgb_intent) +{ + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB"); + + if (srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + + buf[0]=(png_byte)srgb_intent; + png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); +} +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +/* Write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structrp png_ptr, png_const_charp name, + png_const_bytep profile) +{ + png_uint_32 name_len; + png_uint_32 profile_len; + png_byte new_name[81]; /* 1 byte for the compression byte */ + compression_state comp; + + png_debug(1, "in png_write_iCCP"); + + /* These are all internal problems: the profile should have been checked + * before when it was stored. + */ + if (profile == NULL) + png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */ + + profile_len = png_get_uint_32(profile); + + if (profile_len < 132) + png_error(png_ptr, "ICC profile too short"); + + if (profile_len & 0x03) + png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)"); + + { + png_uint_32 embedded_profile_len = png_get_uint_32(profile); + + if (profile_len != embedded_profile_len) + png_error(png_ptr, "Profile length does not match profile"); + } + + name_len = png_check_keyword(png_ptr, name, new_name); + + if (name_len == 0) + png_error(png_ptr, "iCCP: invalid keyword"); + + new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE; + + /* Make sure we include the NULL after the name and the compression type */ + ++name_len; + + png_text_compress_init(&comp, profile, profile_len); + + /* Allow for keyword terminator and compression byte */ + if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg); + + png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len); + + png_write_chunk_data(png_ptr, new_name, name_len); + + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +/* Write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) +{ + png_uint_32 name_len; + png_byte new_name[80]; + png_byte entrybuf[10]; + png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); + png_size_t palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifndef PNG_POINTER_INDEXING_SUPPORTED + int i; +#endif + + png_debug(1, "in png_write_sPLT"); + + name_len = png_check_keyword(png_ptr, spalette->name, new_name); + + if (name_len == 0) + png_error(png_ptr, "sPLT: invalid keyword"); + + /* Make sure we include the NULL after the name */ + png_write_chunk_header(png_ptr, png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 1)); + + png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); + + /* Loop through each palette entry, writing appropriately */ +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (ep = spalette->entries; epentries + spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + + png_write_chunk_data(png_ptr, entrybuf, entry_size); + } +#else + ep=spalette->entries; + for (i = 0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + + png_write_chunk_data(png_ptr, entrybuf, entry_size); + } +#endif + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +/* Write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) +{ + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT"); + + /* Make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[size++] = sbit->alpha; + } + + png_write_complete_chunk(png_ptr, png_sBIT, buf, size); +} +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +/* Write the cHRM chunk */ +void /* PRIVATE */ +png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy) +{ + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM"); + + /* Each value is saved in 1/100,000ths */ + png_save_int_32(buf, xy->whitex); + png_save_int_32(buf + 4, xy->whitey); + + png_save_int_32(buf + 8, xy->redx); + png_save_int_32(buf + 12, xy->redy); + + png_save_int_32(buf + 16, xy->greenx); + png_save_int_32(buf + 20, xy->greeny); + + png_save_int_32(buf + 24, xy->bluex); + png_save_int_32(buf + 28, xy->bluey); + + png_write_complete_chunk(png_ptr, png_cHRM, buf, 32); +} +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +/* Write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, + png_const_color_16p tran, int num_trans, int color_type) +{ + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > png_ptr->num_palette) + { + /* This is an error which can only be reliably detected late. */ + png_app_error(png_ptr, + "Invalid number of transparent colors specified"); + return; + } + + /* Write the chunk out as it is */ + png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, + (png_size_t)num_trans); + } + + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* One 16 bit value */ + if (tran->gray >= (1 << png_ptr->bit_depth)) + { + /* This can no longer happen because it is checked in png_set_tRNS */ + png_app_error(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + + return; + } + + png_save_uint_16(buf, tran->gray); + png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); + } + + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* Three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + /* Also checked in png_set_tRNS */ + png_app_error(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + + png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); + } + + else + { + /* Checked in png_set_tRNS */ + png_app_error(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +/* Write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) +{ + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index >= png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + + buf[0] = back->index; + png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); + } + + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + + return; + } + + png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); + } + + else + { + if (back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + + return; + } + + png_save_uint_16(buf, back->gray); + png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +/* Write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) +{ + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST"); + + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, + png_ptr->num_palette); + + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); + + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +/* Write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, + png_size_t text_len) +{ + png_uint_32 key_len; + png_byte new_key[80]; + + png_debug(1, "in png_write_tEXt"); + + key_len = png_check_keyword(png_ptr, key, new_key); + + if (key_len == 0) + png_error(png_ptr, "tEXt: invalid keyword"); + + if (text == NULL || *text == '\0') + text_len = 0; + + else + text_len = strlen(text); + + if (text_len > PNG_UINT_31_MAX - (key_len+1)) + png_error(png_ptr, "tEXt: text too long"); + + /* Make sure we include the 0 after the key */ + png_write_chunk_header(png_ptr, png_tEXt, + (png_uint_32)/*checked above*/(key_len + text_len + 1)); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, new_key, key_len + 1); + + if (text_len != 0) + png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len); + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +/* Write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, + png_size_t text_len, int compression) +{ + png_uint_32 key_len; + png_byte new_key[81]; + compression_state comp; + + png_debug(1, "in png_write_zTXt"); + PNG_UNUSED(text_len) /* Always use strlen */ + + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, key, text, 0); + return; + } + + if (compression != PNG_TEXT_COMPRESSION_zTXt) + png_error(png_ptr, "zTXt: invalid compression type"); + + key_len = png_check_keyword(png_ptr, key, new_key); + + if (key_len == 0) + png_error(png_ptr, "zTXt: invalid keyword"); + + /* Add the compression method and 1 for the keyword separator. */ + new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; + ++key_len; + + /* Compute the compressed data; do it now for the length */ + png_text_compress_init(&comp, (png_const_bytep)text, + text == NULL ? 0 : strlen(text)); + + if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg); + + /* Write start of chunk */ + png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len); + + /* Write key */ + png_write_chunk_data(png_ptr, new_key, key_len); + + /* Write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); + + /* Close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +/* Write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, + png_const_charp lang, png_const_charp lang_key, png_const_charp text) +{ + png_uint_32 key_len, prefix_len; + png_size_t lang_len, lang_key_len; + png_byte new_key[82]; + compression_state comp; + + png_debug(1, "in png_write_iTXt"); + + key_len = png_check_keyword(png_ptr, key, new_key); + + if (key_len == 0) + png_error(png_ptr, "iTXt: invalid keyword"); + + /* Set the compression flag */ + switch (compression) + { + case PNG_ITXT_COMPRESSION_NONE: + case PNG_TEXT_COMPRESSION_NONE: + compression = new_key[++key_len] = 0; /* no compression */ + break; + + case PNG_TEXT_COMPRESSION_zTXt: + case PNG_ITXT_COMPRESSION_zTXt: + compression = new_key[++key_len] = 1; /* compressed */ + break; + + default: + png_error(png_ptr, "iTXt: invalid compression"); + } + + new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; + ++key_len; /* for the keywod separator */ + + /* We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG, however, + * specifies that the text is UTF-8 and this really doesn't require any + * checking. + * + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + * + * TODO: validate the language tag correctly (see the spec.) + */ + if (lang == NULL) lang = ""; /* empty language is valid */ + lang_len = strlen(lang)+1; + if (lang_key == NULL) lang_key = ""; /* may be empty */ + lang_key_len = strlen(lang_key)+1; + if (text == NULL) text = ""; /* may be empty */ + + prefix_len = key_len; + if (lang_len > PNG_UINT_31_MAX-prefix_len) + prefix_len = PNG_UINT_31_MAX; + else + prefix_len = (png_uint_32)(prefix_len + lang_len); + + if (lang_key_len > PNG_UINT_31_MAX-prefix_len) + prefix_len = PNG_UINT_31_MAX; + else + prefix_len = (png_uint_32)(prefix_len + lang_key_len); + + png_text_compress_init(&comp, (png_const_bytep)text, strlen(text)); + + if (compression != 0) + { + if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg); + } + + else + { + if (comp.input_len > PNG_UINT_31_MAX-prefix_len) + png_error(png_ptr, "iTXt: uncompressed text too long"); + + /* So the string will fit in a chunk: */ + comp.output_len = (png_uint_32)/*SAFE*/comp.input_len; + } + + png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len); + + png_write_chunk_data(png_ptr, new_key, key_len); + + png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len); + + png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len); + + if (compression != 0) + png_write_compressed_data_out(png_ptr, &comp); + + else + png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len); + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +/* Write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset, + int unit_type) +{ + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs"); + + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_int_32(buf, x_offset); + png_save_int_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); +} +#endif +#ifdef PNG_WRITE_pCAL_SUPPORTED +/* Write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_const_charp units, + png_charpp params) +{ + png_uint_32 purpose_len; + png_size_t units_len, total_len; + png_size_tp params_len; + png_byte buf[10]; + png_byte new_purpose[80]; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); + + if (type >= PNG_EQUATION_LAST) + png_error(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, new_purpose); + + if (purpose_len == 0) + png_error(png_ptr, "pCAL: invalid keyword"); + + ++purpose_len; /* terminator */ + + png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); + units_len = strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_size_tp)png_malloc(png_ptr, + (png_alloc_size_t)(nparams * (sizeof (png_size_t)))); + + /* Find the length of each parameter, making sure we don't count the + * null terminator for the last parameter. + */ + for (i = 0; i < nparams; i++) + { + params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu", i, + (unsigned long)params_len[i]); + total_len += params_len[i]; + } + + png_debug1(3, "pCAL total length = %d", (int)total_len); + png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, new_purpose, purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +/* Write the sCAL chunk */ +void /* PRIVATE */ +png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, + png_const_charp height) +{ + png_byte buf[64]; + png_size_t wlen, hlen, total_len; + + png_debug(1, "in png_write_sCAL_s"); + + wlen = strlen(width); + hlen = strlen(height); + total_len = wlen + hlen + 2; + + if (total_len > 64) + { + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); + return; + } + + buf[0] = (png_byte)unit; + memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ + memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len); +} +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +/* Write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs"); + + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); +} +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) +{ + png_byte buf[7]; + + png_debug(1, "in png_write_tIME"); + + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); +} +#endif + +#ifdef PNG_WRITE_FILTER_SUPPORTED +void /* PRIVATE */ +png_write_alloc_filter_row_buffers(png_structrp png_ptr, int filters) + /* Allocate row buffers for any filters that need them, this is also called + * from png_set_filter if the filters are changed during write to ensure that + * the required buffers exist. png_set_filter ensures that up/avg/paeth are + * only set if png_ptr->prev_row is allocated. + */ +{ + /* The buffer size is determined just by the output row size, not any + * processing requirements. + */ + png_alloc_size_t buf_size = png_ptr->rowbytes + 1; + + if ((filters & PNG_FILTER_SUB) != 0 && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((filters & PNG_FILTER_UP) != 0 && png_ptr->up_row == NULL) + { + png_ptr->up_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if ((filters & PNG_FILTER_AVG) != 0 && png_ptr->avg_row == NULL) + { + png_ptr->avg_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if ((filters & PNG_FILTER_PAETH) != 0 && png_ptr->paeth_row == NULL) + { + png_ptr->paeth_row = png_voidcast(png_bytep, png_malloc(png_ptr, + buf_size)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } +} +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + +/* Initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structrp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + +#ifdef PNG_WRITE_FILTER_SUPPORTED + int filters; +#endif + + png_alloc_size_t buf_size; + int usr_pixel_depth; + + png_debug(1, "in png_write_start_row"); + + if (png_ptr == NULL) + return; + + usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; + buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1; + + /* 1.5.6: added to allow checking in the row write code. */ + png_ptr->transformed_pixel_depth = png_ptr->pixel_depth; + png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; + + /* Set up row buffer */ + png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); + + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + filters = png_ptr->do_filter; + + if (png_ptr->height == 1) + filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); + + if (png_ptr->width == 1) + filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH); + + if (filters == 0) + filters = PNG_FILTER_NONE; + + /* We only need to keep the previous row if we are using one of the following + * filters. + */ + if (filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + png_ptr->prev_row = png_voidcast(png_bytep, png_calloc(png_ptr, + buf_size)); + + png_write_alloc_filter_row_buffers(png_ptr, filters); + + png_ptr->do_filter = (png_byte)filters; /* in case it was changed above */ +#else + png_ptr->do_filter = PNG_FILTER_NONE; +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structrp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_debug(1, "in png_write_finish_row"); + + /* Next row */ + png_ptr->row_number++; + + /* See if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + + else + { + /* Loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* Reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth, png_ptr->width)) + 1); + + return; + } + } +#endif + + /* If we get here, we've just written the last row, so we need + to flush the compressor */ + png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH); +} + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_write_interlace"); + + /* We don't have to do anything on the last pass (6) */ + if (pass < 6) + { + /* Each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + + break; + } + + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + + break; + } + + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + + break; + } + + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* Start at the beginning */ + dp = row; + + /* Find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + + /* Loop through the row, only looking at the pixels that matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* Find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + + /* Move the pixel */ + if (dp != sp) + memcpy(dp, sp, pixel_bytes); + + /* Next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* Set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, + png_size_t row_bytes); + +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) +{ + png_bytep best_row; +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_bytep prev_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_size_t row_bytes = row_info->rowbytes; +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + int num_p_filters = png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter"); + +#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) + { + /* These will never be selected so we need not test them. */ + filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); + } +#endif + + /* Find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) >> 3; + + prev_row = png_ptr->prev_row; +#endif + best_row = png_ptr->row_buf; +#ifdef PNG_WRITE_FILTER_SUPPORTED + row_buf = best_row; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_size_t i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* Sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* It's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* Up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* Avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + + if (pa <= pb && pa <= pc) + p = a; + + else if (pb <= pc) + p = b; + + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + + /* Do the actual writing of the filtered row data from the chosen filter. */ + png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1); + +#ifdef PNG_WRITE_FILTER_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +#endif /* PNG_WRITE_FILTER_SUPPORTED */ +} + + +/* Do the actual writing of a previously filtered row. */ +static void +png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, + png_size_t full_row_length/*includes filter byte*/) +{ + png_debug(1, "in png_write_filtered_row"); + + png_debug1(2, "filter = %d", filtered_row[0]); + + png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH); + +#ifdef PNG_WRITE_FILTER_SUPPORTED + /* Swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + + /* Finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/gfx_es2/gl3stub.c b/gfx_es2/gl3stub.c index c1cd9ecdfc..3bdd919b63 100644 --- a/gfx_es2/gl3stub.c +++ b/gfx_es2/gl3stub.c @@ -240,8 +240,6 @@ GLboolean gl3stubInit() { return GL_TRUE; } -#endif - #if !defined(IOS) /* Function pointer definitions */ @@ -352,4 +350,5 @@ GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum target, #endif // IOS +#endif // GLES2 #endif diff --git a/image/png_load.cpp b/image/png_load.cpp index fadcf64441..33618ea868 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -2,7 +2,7 @@ #include #include -#include "libpng16/png.h" +#include "libpng17/png.h" #include "png_load.h" #include "base/logging.h" From 7d08267d646f9268105197e8f3370b30ffbf917c Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 31 May 2014 04:47:47 +1000 Subject: [PATCH 1112/1445] Oops. eglext wasn't meant to be there. --- gfx/gl_common.h | 1 - 1 file changed, 1 deletion(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index f98f03e3ae..0bb02d8158 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -7,7 +7,6 @@ #include #include #include // TODO: Does Maemo like this? -#include // At least Nokia platforms (Symbian/Maemo/Meego) need the three below? #include typedef char GLchar; From f4d66f5c5057300f2ca83e46657b17de8dd472d2 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 31 May 2014 05:13:47 +1000 Subject: [PATCH 1113/1445] Update everything to libpng17 (even atlastool). --- Android.mk | 37 ++++++------ native.vcxproj | 48 ++++++++-------- native.vcxproj.filters | 96 +++++++++++++++---------------- tools/atlastool/atlastool.vcxproj | 6 +- 4 files changed, 95 insertions(+), 92 deletions(-) diff --git a/Android.mk b/Android.mk index 67334859ee..c58f18e5c2 100644 --- a/Android.mk +++ b/Android.mk @@ -20,22 +20,22 @@ LOCAL_SRC_FILES :=\ data/compression.cpp \ ext/rg_etc1/rg_etc1.cpp \ ext/cityhash/city.cpp \ - ext/libpng16/png.c \ - ext/libpng16/pngerror.c \ - ext/libpng16/pngget.c \ - ext/libpng16/pngmem.c \ - ext/libpng16/pngpread.c \ - ext/libpng16/pngread.c \ - ext/libpng16/pngrio.c \ - ext/libpng16/pngrtran.c \ - ext/libpng16/pngrutil.c \ - ext/libpng16/pngset.c \ - ext/libpng16/pngtest.c \ - ext/libpng16/pngtrans.c \ - ext/libpng16/pngwio.c \ - ext/libpng16/pngwrite.c \ - ext/libpng16/pngwtran.c \ - ext/libpng16/pngwutil.c \ + ext/libpng17/png.c \ + ext/libpng17/pngerror.c \ + ext/libpng17/pngget.c \ + ext/libpng17/pngmem.c \ + ext/libpng17/pngpread.c \ + ext/libpng17/pngread.c \ + ext/libpng17/pngrio.c \ + ext/libpng17/pngrtran.c \ + ext/libpng17/pngrutil.c \ + ext/libpng17/pngset.c \ + ext/libpng17/pngtest.c \ + ext/libpng17/pngtrans.c \ + ext/libpng17/pngwio.c \ + ext/libpng17/pngwrite.c \ + ext/libpng17/pngwtran.c \ + ext/libpng17/pngwutil.c \ ext/jpge/jpgd.cpp \ ext/jpge/jpge.cpp \ ext/sha1/sha1.cpp \ @@ -110,7 +110,10 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext $(LOCAL_PATH)/ext/libzip ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI_V7A -DARMV7 LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ - math/fast/fast_matrix_neon.S.neon + math/fast/fast_matrix_neon.S.neon \ + ext/libpng17/arm/arm_init.c \ + ext/libpng17/arm/filter_neon_intrinsics.c \ + ext/libpng17/arm/filter_neon.S.neon else ifeq ($(TARGET_ARCH_ABI),armeabi) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI -march=armv6 diff --git a/native.vcxproj b/native.vcxproj index 2de8185ade..831a61317a 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -211,13 +211,13 @@ - - - - - - - + + + + + + + @@ -362,22 +362,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + CompileAsCpp CompileAsCpp @@ -778,4 +778,4 @@ - \ No newline at end of file + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 8406a16f12..8272c3f79d 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -284,26 +284,26 @@ gfx - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 ext\libzip @@ -565,53 +565,53 @@ util - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 - - ext\libpng16 + + ext\libpng17 ext\libzip @@ -870,7 +870,7 @@ {aa8b9b49-2ff8-4961-b6cc-9c33ea674130} - + {6c47ee5b-0375-40f0-ab2a-402d001cc9c7} @@ -883,4 +883,4 @@ {5ce64c0e-98e4-4411-86cc-aacaf2f60b21} - \ No newline at end of file + diff --git a/tools/atlastool/atlastool.vcxproj b/tools/atlastool/atlastool.vcxproj index 6d8e03ba15..da873d853f 100644 --- a/tools/atlastool/atlastool.vcxproj +++ b/tools/atlastool/atlastool.vcxproj @@ -53,7 +53,7 @@ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\ext\libpng16;..\..\..\ext\freetype\devel;..\..\..\ext\freetype\include;..\..;..\..\ext\SDL1.2\include;..\..\..\libpng;%(AdditionalIncludeDirectories); + ..\..\ext\libpng17;..\..\..\ext\freetype\devel;..\..\..\ext\freetype\include;..\..;..\..\ext\SDL1.2\include;..\..\..\libpng;%(AdditionalIncludeDirectories); Console @@ -72,7 +72,7 @@ true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\ext\libpng16;..\..\..\ext\freetype\devel;..\..\..\ext\freetype\include;..\..;..\..\ext\SDL1.2\include;..\..\..\libpng;%(AdditionalIncludeDirectories); + ..\..\ext\libpng17;..\..\..\ext\freetype\devel;..\..\..\ext\freetype\include;..\..;..\..\ext\SDL1.2\include;..\..\..\libpng;%(AdditionalIncludeDirectories); Console @@ -102,4 +102,4 @@ - \ No newline at end of file + From 3c4e046609a245177be74b126d0ee78f22045356 Mon Sep 17 00:00:00 2001 From: Peter Tissen Date: Sun, 1 Jun 2014 11:35:57 +0200 Subject: [PATCH 1114/1445] make enum identifiers for all pad numbers, add a constant for the max number of pads and add string names for each identifier --- input/input_state.cpp | 11 ++++++++++- input/input_state.h | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/input/input_state.cpp b/input/input_state.cpp index 2da6321b61..2761c6564d 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -6,7 +6,16 @@ const char *GetDeviceName(int deviceId) { switch (deviceId) { case DEVICE_ID_DEFAULT: return "built-in"; case DEVICE_ID_KEYBOARD: return "kbd"; - case DEVICE_ID_PAD_0: return "pad"; + case DEVICE_ID_PAD_0: return "pad1"; + case DEVICE_ID_PAD_1: return "pad2"; + case DEVICE_ID_PAD_2: return "pad3"; + case DEVICE_ID_PAD_3: return "pad4"; + case DEVICE_ID_PAD_4: return "pad5"; + case DEVICE_ID_PAD_5: return "pad6"; + case DEVICE_ID_PAD_6: return "pad7"; + case DEVICE_ID_PAD_7: return "pad8"; + case DEVICE_ID_PAD_8: return "pad9"; + case DEVICE_ID_PAD_9: return "pad10"; case DEVICE_ID_X360_0: return "x360"; case DEVICE_ID_ACCELEROMETER: return "accelerometer"; case DEVICE_ID_MOUSE: return "mouse"; diff --git a/input/input_state.h b/input/input_state.h index eb16a81bfa..c9fe43a91c 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -23,10 +23,22 @@ enum { DEVICE_ID_KEYBOARD = 1, // PC keyboard, android keyboards DEVICE_ID_MOUSE = 2, // PC mouse only (not touchscreen!) DEVICE_ID_PAD_0 = 10, // Generic joypads + DEVICE_ID_PAD_1 = 11, // these should stay as contiguous numbers + DEVICE_ID_PAD_2 = 12, + DEVICE_ID_PAD_3 = 13, + DEVICE_ID_PAD_4 = 14, + DEVICE_ID_PAD_5 = 15, + DEVICE_ID_PAD_6 = 16, + DEVICE_ID_PAD_7 = 17, + DEVICE_ID_PAD_8 = 18, + DEVICE_ID_PAD_9 = 19, DEVICE_ID_X360_0 = 20, // XInput joypads DEVICE_ID_ACCELEROMETER = 30, }; +//number of contiguous generic joypad IDs +const int MAX_NUM_PADS = 10; + const char *GetDeviceName(int deviceId); enum { From b0968fb7bb93522a8e2f4fe8c01a08f5ef68b9cf Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 2 Jun 2014 11:32:02 +1000 Subject: [PATCH 1115/1445] Define MAY_HAVE_GLES3 on all platforms. Tell me if there are any errors on Maemo/Meego or other ARM platforms. --- gfx/gl_common.h | 7 +++---- gfx_es2/gl3stub.c | 4 +--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 0bb02d8158..c44678750d 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -3,6 +3,9 @@ #ifdef IOS #include #include +#elif defined(BLACKBERRY) +#include +#include #elif defined(USING_GLES2) #include #include @@ -20,9 +23,6 @@ typedef char GLchar; #endif #endif -// Gets 'undefined reference' if enabled -#if !defined(__SYMBIAN32__) && !defined(MAEMO) && !defined(MEEGO_EDITION_HARMATTAN) - #ifdef USING_GLES2 // Support OpenGL ES 3.0 // This uses the "DYNAMIC" approach from the gles3jni NDK sample. @@ -32,4 +32,3 @@ typedef char GLchar; // Now that glew is upgraded beyond 4.3, we can define MAY_HAVE_GLES3 on GL platforms #define MAY_HAVE_GLES3 1 -#endif diff --git a/gfx_es2/gl3stub.c b/gfx_es2/gl3stub.c index 3bdd919b63..8637761d07 100644 --- a/gfx_es2/gl3stub.c +++ b/gfx_es2/gl3stub.c @@ -14,8 +14,6 @@ * limitations under the License. */ -#if !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO) - #include "../gfx/gl_common.h" #if defined(USING_GLES2) @@ -351,4 +349,4 @@ GL_APICALL void (* GL_APIENTRY glGetInternalformativ) (GLenum target, #endif // IOS #endif // GLES2 -#endif + From 79880f85673d5db4077a14c6d26ca377ff54fad9 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 2 Jun 2014 12:01:16 +1000 Subject: [PATCH 1116/1445] Fix all warnings/errors on Blackberry. Revert GLES3 headers as they didn't include nvidia extensions. --- base/BlackberryDisplay.cpp | 2 +- base/BlackberryMain.h | 2 +- gfx/gl_common.h | 3 --- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/base/BlackberryDisplay.cpp b/base/BlackberryDisplay.cpp index 91045614d7..e4bbdcaf6d 100644 --- a/base/BlackberryDisplay.cpp +++ b/base/BlackberryDisplay.cpp @@ -5,7 +5,7 @@ // Blackberry implementation of the framework. #include "BlackberryMain.h" -char* BlackberryMain::displayTypeString(int type) +const char* BlackberryMain::displayTypeString(int type) { switch (type) { diff --git a/base/BlackberryMain.h b/base/BlackberryMain.h index 78eb164c8f..fe4af41d4c 100644 --- a/base/BlackberryMain.h +++ b/base/BlackberryMain.h @@ -64,7 +64,7 @@ private: void handleInput(screen_event_t screen_event); - char* displayTypeString(int type); + const char* displayTypeString(int type); void startDisplays(); void* startDisplay(int idx); void realiseDisplay(int idx); diff --git a/gfx/gl_common.h b/gfx/gl_common.h index c44678750d..856c4e3248 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -3,9 +3,6 @@ #ifdef IOS #include #include -#elif defined(BLACKBERRY) -#include -#include #elif defined(USING_GLES2) #include #include From 205423637fd4ffc00beef769acc3d904c7fbd202 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 2 Jun 2014 12:08:29 +1000 Subject: [PATCH 1117/1445] Remove MAY_HAVE_GLES3 --- gfx/gl_common.h | 3 --- gfx_es2/gl_state.cpp | 3 --- 2 files changed, 6 deletions(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 856c4e3248..f960ee45ea 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -26,6 +26,3 @@ typedef char GLchar; #include "../gfx_es2/gl3stub.h" #endif -// Now that glew is upgraded beyond 4.3, we can define MAY_HAVE_GLES3 on GL platforms -#define MAY_HAVE_GLES3 1 - diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index ddfa3daaf8..fc976a7369 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -151,8 +151,6 @@ void CheckGLExtensions() { #endif #if defined(USING_GLES2) - // MAY_HAVE_GLES3 defined on all platforms that support it -#if defined(MAY_HAVE_GLES3) // Try to load GLES 3.0 only if "3.0" found in version // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited // number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584. @@ -166,7 +164,6 @@ void CheckGLExtensions() { gl_extensions.GLES3 = false; } } -#endif #else // If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable // all the same modern paths. From dfe866441987d3c2c01e721b0749a373360801be Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 3 Jun 2014 09:03:09 +1000 Subject: [PATCH 1118/1445] Buildfix Qt5 mobile platforms such as Android. --- base/QtMain.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/QtMain.h b/base/QtMain.h index f630c7ace9..8361af7ea2 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -11,8 +11,10 @@ #include #if defined(MOBILE_DEVICE) && !defined(MAEMO) #include +#if QT_VERSION < 0x50000 QTM_USE_NAMESPACE #endif +#endif #include "base/display.h" #include "base/logging.h" @@ -23,7 +25,6 @@ QTM_USE_NAMESPACE #include "input/keycodes.h" #include "base/NativeApp.h" #include "net/resolve.h" -#include "display.h" #include "base/NKCodeFromQt.h" // Bad: PPSSPP includes from native From 4f0ffa2d515269e4aaaae685d3bad2812249e058 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 3 Jun 2014 10:02:24 +1000 Subject: [PATCH 1119/1445] Make Qt a bit more friendly for Android. Report as Qt:Android. Use standard locations. --- base/QtMain.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 265a5ed2a9..0094ab070c 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -13,6 +13,10 @@ #include #include +#ifdef ANDROID +#include +#endif + #ifdef __SYMBIAN32__ #include #include @@ -39,6 +43,8 @@ std::string System_GetProperty(SystemProperty prop) { return "Qt:Meego"; #elif defined(MAEMO) return "Qt:Maemo"; +#elif defined(ANDROID) + return "Qt:Android"; #elif defined(Q_OS_LINUX) return "Qt:Linux"; #elif defined(_WIN32) @@ -158,6 +164,10 @@ int main(int argc, char *argv[]) #elif defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) const char *savegame_dir = "/home/user/MyDocs/PPSSPP/"; const char *assets_dir = "/opt/PPSSPP/"; +#elif defined(ANDROID) + const char *savegame_dir = QStandardPaths::standardLocations(QStandardPaths::HomeLocation).at(0).toStdString().c_str(); + const char *assets_dir = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).at(0).toStdString().c_str(); + setenv("QT_USE_ANDROID_NATIVE_DIALOGS", "1", 1); // Which Qt version does this need? #else const char *savegame_dir = "./"; const char *assets_dir = "./"; From 45244dce8061665f61bc3b0cdeb858eb0dd7d94b Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 3 Jun 2014 10:17:43 +1000 Subject: [PATCH 1120/1445] Qt: Add support for back key --- base/NKCodeFromQt.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/NKCodeFromQt.h b/base/NKCodeFromQt.h index 0c1176f9ac..cb6a79da84 100644 --- a/base/NKCodeFromQt.h +++ b/base/NKCodeFromQt.h @@ -96,5 +96,6 @@ static const std::map KeyMapRawQttoNative = InitConstMap (Qt::Key_Left, NKCODE_DPAD_LEFT) (Qt::Key_Up, NKCODE_DPAD_UP) (Qt::Key_Right, NKCODE_DPAD_RIGHT) - (Qt::Key_Down, NKCODE_DPAD_DOWN); + (Qt::Key_Down, NKCODE_DPAD_DOWN) + (Qt::Key_Back, NKCODE_BACK); From 6f476520c5b968e8113fd4c4f9cba1bb98bd8b65 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 5 Jun 2014 21:28:49 +0200 Subject: [PATCH 1121/1445] Fix fbo_bind_for_read on Tegra --- gfx_es2/fbo.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index a4ff4dcefd..589256acf6 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -267,6 +267,7 @@ void fbo_bind_as_render_target(FBO *fbo) { #else if (gl_extensions.GLES3) { #endif + // GL_DRAW_FRAMEBUFFER is actually the same value as GL_FRAMEBUFFER so this is a bit redundant. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); } else { // This will collide with bind_for_read - but there's nothing in ES 2.0 @@ -282,13 +283,15 @@ void fbo_bind_as_render_target(FBO *fbo) { glstate.viewport.restore(); } +// For GL_EXT_FRAMEBUFFER_BLIT and similar. void fbo_bind_for_read(FBO *fbo) { if (gl_extensions.FBO_ARB) { #ifndef USING_GLES2 if (true) { #else - if (gl_extensions.GLES3) { + if (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit) { #endif + // GL_READ_FRAMEBUFFER is defined to the same value as GL_READ_FRAMEBUFFER_NV. glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); } else { // This will collide with bind_as_render_target - but there's nothing in ES 2.0 From c055b4852be968fb97ae298b3e2a7b50a6a0b85c Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 6 Jun 2014 14:12:21 +1000 Subject: [PATCH 1122/1445] Buildfix Meego Harmattan with gcc4.8.2 --- gfx/gl_common.h | 6 ++++-- gfx_es2/draw_text.cpp | 14 +++++++------- gfx_es2/gl_state.h | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index f960ee45ea..d2a1a09255 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -6,8 +6,10 @@ #elif defined(USING_GLES2) #include #include -#include // TODO: Does Maemo like this? -// At least Nokia platforms (Symbian/Maemo/Meego) need the three below? +#if !defined(MAEMO) && !defined(MEEGO_EDITION_HARMATTAN) +#include // X11 pollutes namespace +#endif +// At least Nokia platforms need the three below #include typedef char GLchar; #define GL_BGRA_EXT 0x80E1 diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 8c9acc9f51..d9cb2e7464 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -1,10 +1,3 @@ -#include "base/logging.h" -#include "base/stringutil.h" -#include "gfx/gl_common.h" -#include "gfx_es2/draw_text.h" -#include "util/hash/hash.h" -#include "util/text/utf8.h" - #ifdef USING_QT_UI #include #include @@ -12,6 +5,13 @@ #include #endif +#include "base/logging.h" +#include "base/stringutil.h" +#include "gfx/gl_common.h" +#include "gfx_es2/draw_text.h" +#include "util/hash/hash.h" +#include "util/text/utf8.h" + #if defined(_WIN32) && !defined(USING_QT_UI) #define WIN32_LEAN_AND_MEAN diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index cfb28c013d..ccee34582e 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -30,7 +30,7 @@ extern PFNGLMAPBUFFERPROC glMapBuffer; #endif -#if !defined(IOS) +#if !defined(IOS) && !defined(MEEGO_EDITION_HARMATTAN) typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV; typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum From efd2cb0f618cc750842a9176487fee27599191cd Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 8 Jun 2014 00:55:51 +1000 Subject: [PATCH 1123/1445] Fix SDL Joystick. --- base/PCMain.cpp | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 63dec38a87..b3e7386a2f 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -20,8 +20,7 @@ #include "SDL_video.h" #ifndef _WIN32 #include "SDL/SDLJoystick.h" -SDL_Joystick *ljoy = NULL; -SDL_Joystick *rjoy = NULL; +SDLJoystick *joystick = NULL; #endif #ifdef RPI @@ -315,20 +314,6 @@ void SimulateGamepad(const uint8 *keys, InputState *input) { input->pad_lstick_y = 0; input->pad_rstick_x = 0; input->pad_rstick_y = 0; - -#ifndef _WIN32 - if (ljoy || rjoy) { - SDL_JoystickUpdate(); - if (ljoy) { - input->pad_lstick_x = std::max(std::min(SDL_JoystickGetAxis(ljoy, 0) / 32000.0f, 1.0f), -1.0f); - input->pad_lstick_y = std::max(std::min(-SDL_JoystickGetAxis(ljoy, 1) / 32000.0f, 1.0f), -1.0f); - } - if (rjoy) { - input->pad_rstick_x = std::max(std::min(SDL_JoystickGetAxis(rjoy, 0) / 32000.0f, 1.0f), -1.0f); - input->pad_rstick_y = std::max(std::min(SDL_JoystickGetAxis(rjoy, 1) / 32000.0f, 1.0f), -1.0f); - } - } -#endif } extern void mixaudio(void *userdata, Uint8 *stream, int len) { @@ -611,13 +596,7 @@ int main(int argc, char *argv[]) { // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); #ifndef _WIN32 - int numjoys = SDL_NumJoysticks(); - // Joysticks init - if (numjoys > 0) { - ljoy = SDL_JoystickOpen(0); - if (numjoys > 1) - rjoy = SDL_JoystickOpen(1); - } + joystick = new SDLJoystick(); #endif EnableFZ(); @@ -787,6 +766,9 @@ int main(int argc, char *argv[]) { } break; default: +#ifndef _WIN32 + joystick->ProcessInput(event); +#endif break; } } @@ -832,10 +814,7 @@ int main(int argc, char *argv[]) { framecount++; } #ifndef _WIN32 - if (ljoy) - delete ljoy; - if (rjoy) - delete rjoy; + delete joystick; #endif // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though From 7ab6385a5e7a0fe18a59363739f1b10b13b6224a Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 8 Jun 2014 05:09:10 +1000 Subject: [PATCH 1124/1445] Qt: Fix gl before glew error. --- gfx_es2/draw_text.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index d9cb2e7464..8c9acc9f51 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -1,10 +1,3 @@ -#ifdef USING_QT_UI -#include -#include -#include -#include -#endif - #include "base/logging.h" #include "base/stringutil.h" #include "gfx/gl_common.h" @@ -12,6 +5,13 @@ #include "util/hash/hash.h" #include "util/text/utf8.h" +#ifdef USING_QT_UI +#include +#include +#include +#include +#endif + #if defined(_WIN32) && !defined(USING_QT_UI) #define WIN32_LEAN_AND_MEAN From d052c403f954a732644a769aec28432aa2065267 Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 9 Jun 2014 21:45:57 +1000 Subject: [PATCH 1125/1445] Symbian: Remove outdated ifdefs --- base/basictypes.h | 4 ---- ext/stb_vorbis/stb_vorbis.h | 3 --- 2 files changed, 7 deletions(-) diff --git a/base/basictypes.h b/base/basictypes.h index c9180108ae..479b6510f2 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -119,7 +119,3 @@ inline uint64 swap64(const uint8* _pData) {return swap64(*(const uint64*)_pData) typedef char TCHAR; #endif -// Workaround for Symbian's old GCC -#if defined(__GNUC__) && (__cplusplus < 201103 || (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) < 40700) -#define override -#endif // defined(__GNUC__) && (__cplusplus < 201103 || (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) < 40700) diff --git a/ext/stb_vorbis/stb_vorbis.h b/ext/stb_vorbis/stb_vorbis.h index 3c39b06405..16ccc10036 100644 --- a/ext/stb_vorbis/stb_vorbis.h +++ b/ext/stb_vorbis/stb_vorbis.h @@ -46,9 +46,6 @@ extern "C" { // If you pass in a non-NULL buffer of the type below, allocation // will occur from it as described above. Otherwise just pass NULL // to use malloc()/alloca() -#ifdef __SYMBIAN32__ -#define alloca(size) __builtin_alloca (size) -#endif typedef struct { From 271ecd0cae6e340bf0d16bc41409b15311712c4f Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 10 Jun 2014 04:15:58 +1000 Subject: [PATCH 1126/1445] Travis buildfix --- base/BlackberryAudio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/base/BlackberryAudio.h b/base/BlackberryAudio.h index 6e39099f06..7c604354dc 100644 --- a/base/BlackberryAudio.h +++ b/base/BlackberryAudio.h @@ -8,6 +8,7 @@ #include #include +#include #include "base/NativeApp.h" From dd03687400d18fb8b2747ba22901bb525cac5ff7 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 10 Jun 2014 15:09:47 +1000 Subject: [PATCH 1127/1445] Fix X11 includes by avoiding confict. Only compile this EGL code on Android / Blackberry. --- gfx/gl_common.h | 3 --- gfx_es2/gl_state.h | 6 +----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index d2a1a09255..b8437bd399 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -6,9 +6,6 @@ #elif defined(USING_GLES2) #include #include -#if !defined(MAEMO) && !defined(MEEGO_EDITION_HARMATTAN) -#include // X11 pollutes namespace -#endif // At least Nokia platforms need the three below #include typedef char GLchar; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index ccee34582e..157afc58c8 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -17,6 +17,7 @@ #endif #if defined(ANDROID) || defined(BLACKBERRY) +#include // Additional extensions not included in GLES2/gl2ext.h from the NDK typedef uint64_t EGLuint64NV; @@ -28,9 +29,6 @@ extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; typedef GLvoid* (GL_APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); extern PFNGLMAPBUFFERPROC glMapBuffer; -#endif - -#if !defined(IOS) && !defined(MEEGO_EDITION_HARMATTAN) typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV; typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum @@ -43,9 +41,7 @@ typedef void (EGLAPIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) ( GLint dstX0, GLint dstY0, GLint dstX1, GLuint dstY1, GLint mask, GLenum filter); extern PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV; -#endif -#if defined(ANDROID) || defined(BLACKBERRY) extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; From f7ffcd41973a1106a6866186a0d65f41e6e97b3c Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 10 Jun 2014 23:05:14 +1000 Subject: [PATCH 1128/1445] Remove a lot of #ifdef's that simply were not needed. For example: Symbian has zip in-built, no need to even compile it let alone use #ifdef's. --- base/functional.h | 6 +++--- ext/jpge/jpge.cpp | 3 --- ext/libzip/zip.h | 8 -------- file/fd_util.cpp | 3 --- file/file_util.cpp | 2 +- net/resolve.cpp | 4 ---- 6 files changed, 4 insertions(+), 22 deletions(-) diff --git a/base/functional.h b/base/functional.h index 4a0ddab9eb..5610819d42 100644 --- a/base/functional.h +++ b/base/functional.h @@ -26,9 +26,9 @@ namespace std { using boost::function; using boost::shared_ptr; #else - using tr1::bind; - using tr1::function; - using tr1::shared_ptr; + using tr1::bind; + using tr1::function; + using tr1::shared_ptr; #endif template diff --git a/ext/jpge/jpge.cpp b/ext/jpge/jpge.cpp index 556985927e..d355b4f414 100644 --- a/ext/jpge/jpge.cpp +++ b/ext/jpge/jpge.cpp @@ -12,9 +12,6 @@ #include #include -#if !defined(__SYMBIAN32__) && !defined(__MAC_10_6) -#include -#endif // Higher level wrappers/examples (optional). #include diff --git a/ext/libzip/zip.h b/ext/libzip/zip.h index f73e3e5228..10a961d478 100644 --- a/ext/libzip/zip.h +++ b/ext/libzip/zip.h @@ -59,14 +59,6 @@ extern "C" { #include #include -#ifdef __SYMBIAN32__ -#define _stat stat -#define _wcsdup wcsdup -#define _wfopen wfopen -#define _wremove wremove -#define _wstat wstat -#endif - /* flags for zip_open */ #define ZIP_CREATE 1 diff --git a/file/fd_util.cpp b/file/fd_util.cpp index 48ff04ba95..babe09f970 100644 --- a/file/fd_util.cpp +++ b/file/fd_util.cpp @@ -5,10 +5,7 @@ #include #ifndef _WIN32 #include -#include -#ifdef __SYMBIAN32__ #include -#endif #else #include #include diff --git a/file/file_util.cpp b/file/file_util.cpp index 130d8c8ada..73cecc9d4b 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -23,7 +23,7 @@ #include "file/file_util.h" #include "util/text/utf8.h" -#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__SYMBIAN32__) +#if defined(__FreeBSD__) || defined(__APPLE__) #define stat64 stat #endif diff --git a/net/resolve.cpp b/net/resolve.cpp index 683484ad40..5f2ef4f67a 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -13,11 +13,7 @@ #undef min #undef max #else -#if defined(__FreeBSD__) || defined(__SYMBIAN32__) #include -#else -#include -#endif #include #include #include From d03acfdbf305eeb4b96679a9da83c29b33d241e0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 10 Jun 2014 23:22:20 +1000 Subject: [PATCH 1129/1445] Revert some of that, sorry. --- ext/libzip/zip.h | 9 +++++++++ net/resolve.cpp | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/ext/libzip/zip.h b/ext/libzip/zip.h index 10a961d478..78b8519918 100644 --- a/ext/libzip/zip.h +++ b/ext/libzip/zip.h @@ -59,6 +59,15 @@ extern "C" { #include #include +#ifdef __SYMBIAN32__ +#define _stat stat +#define _wcsdup wcsdup +#define _wfopen wfopen +#define _wremove wremove +#define _wstat wstat +#endif + + /* flags for zip_open */ #define ZIP_CREATE 1 diff --git a/net/resolve.cpp b/net/resolve.cpp index 5f2ef4f67a..683484ad40 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -13,7 +13,11 @@ #undef min #undef max #else +#if defined(__FreeBSD__) || defined(__SYMBIAN32__) #include +#else +#include +#endif #include #include #include From d7cb2508d70d6049dea4075b30ec8b53df39b06c Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 11 Jun 2014 03:10:11 +1000 Subject: [PATCH 1130/1445] Update Symbian to GCC 4.8.3 --- net/resolve.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/resolve.cpp b/net/resolve.cpp index 683484ad40..9677bec443 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -13,7 +13,7 @@ #undef min #undef max #else -#if defined(__FreeBSD__) || defined(__SYMBIAN32__) +#if defined(__FreeBSD__) #include #else #include From d809cf9e37d114b52b4ab152df1d187cee0ea91b Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 11 Jun 2014 15:14:20 +1000 Subject: [PATCH 1131/1445] Remove some redundant armv7 defines. Also, a stray QFile include. --- Android.mk | 2 +- image/zim_load.cpp | 4 ---- math/fast/fast_math.c | 3 ++- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Android.mk b/Android.mk index c58f18e5c2..db81b0de40 100644 --- a/Android.mk +++ b/Android.mk @@ -108,7 +108,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext $(LOCAL_PATH)/ext/libzip #Portable native and separate code on android in future is easy you needs add files #by ($(target_arch_ABI),arquitecture (armeabi-v7a , armeabi , x86 , MIPS) ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) -LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI_V7A -DARMV7 +LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI_V7A LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ math/fast/fast_matrix_neon.S.neon \ ext/libpng17/arm/arm_init.c \ diff --git a/image/zim_load.cpp b/image/zim_load.cpp index ec6266a4b2..65a29e434d 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -2,10 +2,6 @@ #include #include -#ifdef USING_QT_UI -#include -#endif - #include "base/logging.h" #include "zlib.h" #include "image/zim_load.h" diff --git a/math/fast/fast_math.c b/math/fast/fast_math.c index 1fa6acd8df..ad68673703 100644 --- a/math/fast/fast_math.c +++ b/math/fast/fast_math.c @@ -3,7 +3,8 @@ #include "fast_matrix.h" void InitFastMath(int enableNEON) { -#if !defined(_M_IX86) && !defined(_M_X64) && defined(ARMEABI_V7A) +// Every architecture has its own define. This needs to be added to. +#if defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7S__) if (enableNEON) { fast_matrix_mul_4x4 = &fast_matrix_mul_4x4_neon; } From 23b89ddb32355f0949f5326fa967cc58bd00fbb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 13 Jun 2014 23:33:10 +0200 Subject: [PATCH 1132/1445] Cap threads at 8 to avoid problems with too many threads on CPUs that misreport core number --- thread/threadpool.cpp | 24 +++++++++++++++++------- thread/threadpool.h | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/thread/threadpool.cpp b/thread/threadpool.cpp index 2b14500df8..b89447d084 100644 --- a/thread/threadpool.cpp +++ b/thread/threadpool.cpp @@ -1,3 +1,4 @@ +#include "base/logging.h" #include "threadpool.h" ///////////////////////////// WorkerThread @@ -73,12 +74,21 @@ void LoopWorkerThread::WorkFunc() { ///////////////////////////// ThreadPool -ThreadPool::ThreadPool(int numThreads) : numThreads(numThreads), workersStarted(false) { +ThreadPool::ThreadPool(int numThreads) : workersStarted(false) { + if (numThreads <= 0) { + numThreads_ = 1; + ILOG("ThreadPool: Bad number of threads %i", numThreads); + } else if (numThreads > 8) { + ILOG("ThreadPool: Capping number of threads to 8 (was %i)", numThreads); + numThreads_ = 8; + } else { + numThreads_ = numThreads; + } } void ThreadPool::StartWorkers() { - if(!workersStarted) { - for(int i=0; i()); } workersStarted = true; @@ -87,21 +97,21 @@ void ThreadPool::StartWorkers() { void ThreadPool::ParallelLoop(const std::function &loop, int lower, int upper) { int range = upper - lower; - if (range >= numThreads * 2) { // don't parallelize tiny loops (this could be better, maybe add optional parameter that estimates work per iteration) + if (range >= numThreads_ * 2) { // don't parallelize tiny loops (this could be better, maybe add optional parameter that estimates work per iteration) lock_guard guard(mutex); StartWorkers(); // could do slightly better load balancing for the generic case, // but doesn't matter since all our loops are power of 2 - int chunk = range / numThreads; + int chunk = range / numThreads_; int s = lower; - for (int i = 0; i < numThreads - 1; ++i) { + for (int i = 0; i < numThreads_ - 1; ++i) { workers[i]->Process(loop, s, s+chunk); s+=chunk; } // This is the final chunk. loop(s, upper); - for (int i = 0; i < numThreads - 1; ++i) { + for (int i = 0; i < numThreads_ - 1; ++i) { workers[i]->WaitForCompletion(); } } else { diff --git a/thread/threadpool.h b/thread/threadpool.h index c24c30caa7..7647f64d25 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -60,7 +60,7 @@ public: void ParallelLoop(const std::function &loop, int lower, int upper); private: - const int numThreads; + int numThreads_; std::vector> workers; ::recursive_mutex mutex; // used to sequentialize loop execution From 6739fc565464ec4cb830ad16ca73605519ab3223 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 15 Jun 2014 11:38:14 +0200 Subject: [PATCH 1133/1445] Have the input functions return bool, so we can say if we used the key. Will allow mapping Android volume keys as game inputs without also showing the volume setting. --- android/app-android.cpp | 37 ++++++++++--------- .../henrikrydgard/libnative/NativeApp.java | 10 ++--- base/NativeApp.h | 6 +-- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 10e18c9d17..3c4b080794 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -382,7 +382,7 @@ extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* e return 0; } -extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch +extern "C" jboolean JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch (JNIEnv *, jclass, float x, float y, int code, int pointerId) { float scaledX = x * dp_xscale; float scaledY = y * dp_yscale; @@ -398,33 +398,34 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch input_state.pointer_down[pointerId] = false; } - NativeTouch(touch); + bool retval = NativeTouch(touch); { lock_guard guard(input_state.lock); if (pointerId >= MAX_POINTERS) { ELOG("Too many pointers: %i", pointerId); - return; // We ignore 8+ pointers entirely. + return false; // We ignore 8+ pointers entirely. } input_state.pointer_x[pointerId] = scaledX; input_state.pointer_y[pointerId] = scaledY; input_state.mouse_valid = true; } + return retval; } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint deviceId, jint key) { +extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint deviceId, jint key) { KeyInput keyInput; keyInput.deviceId = deviceId; keyInput.keyCode = key; keyInput.flags = KEY_DOWN; - NativeKey(keyInput); + return NativeKey(keyInput); } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint deviceId, jint key) { +extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_keyUp(JNIEnv *, jclass, jint deviceId, jint key) { KeyInput keyInput; keyInput.deviceId = deviceId; keyInput.keyCode = key; keyInput.flags = KEY_UP; - NativeKey(keyInput); + return NativeKey(keyInput); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_beginJoystickEvent( @@ -432,10 +433,10 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_beginJoystickEvent( // mutex lock? } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickAxis( +extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_joystickAxis( JNIEnv *env, jclass, jint deviceId, jint axisId, jfloat value) { if (!renderer_inited) - return; + return false; switch (axisId) { case JOYSTICK_AXIS_X: left_joystick_x_async = value; @@ -461,7 +462,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_joystickAxis( axis.axisId = axisId; axis.deviceId = deviceId; axis.value = value; - NativeAxis(axis); + return NativeAxis(axis); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_endJoystickEvent( @@ -470,14 +471,15 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_endJoystickEvent( } -extern "C" void Java_com_henrikrydgard_libnative_NativeApp_mouseWheelEvent( +extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_mouseWheelEvent( JNIEnv *env, jclass, jint stick, jfloat x, jfloat y) { - // TODO + // TODO: Support mousewheel for android + return true; } -extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) { +extern "C" jboolean JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) { if (!renderer_inited) - return; + return false; // Theoretically this needs locking but I doubt it matters. Worst case, the X // from one "sensor frame" will be used together with Y from the next. // Should look into quantization though, for compressed movement storage. @@ -492,15 +494,16 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_X; axis.value = x; - NativeAxis(axis); + bool retval = NativeAxis(axis); axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Y; axis.value = y; - NativeAxis(axis); + retval = retval || NativeAxis(axis); axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Z; axis.value = z; - NativeAxis(axis); + retval = retval || NativeAxis(axis); + return retval; } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) { diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 070d74ee3d..03eb8fa96f 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -22,22 +22,22 @@ public class NativeApp { // There's not really any reason to ever call shutdown as we can recover from a killed activity. public static native void shutdown(); - public static native void keyDown(int deviceId, int key); - public static native void keyUp(int deviceId, int key); + public static native boolean keyDown(int deviceId, int key); + public static native boolean keyUp(int deviceId, int key); public static native void beginJoystickEvent(); public static native void joystickAxis(int deviceId, int axis, float value); public static native void endJoystickEvent(); - public static native void mouseWheelEvent(float x, float y); + public static native boolean mouseWheelEvent(float x, float y); // will only be called between init() and shutdown() public static native int audioRender(short[] buffer); // Sensor/input data. These are asynchronous, beware! - public static native void touch(float x, float y, int data, int pointerId); + public static native boolean touch(float x, float y, int data, int pointerId); - public static native void accelerometer(float x, float y, float z); + public static native boolean accelerometer(float x, float y, float z); public static native void sendMessage(String msg, String arg); diff --git a/base/NativeApp.h b/base/NativeApp.h index 571364f42b..cf3815a0bf 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -57,9 +57,9 @@ void NativeUpdate(InputState &input); // Useful for triggering audio events, saving a few ms. // If you don't care about touch latency, just do a no-op implementation of this. // time is not yet implemented. finger can be from 0 to 7, inclusive. -void NativeTouch(const TouchInput &touch); -void NativeKey(const KeyInput &key); -void NativeAxis(const AxisInput &axis); +bool NativeTouch(const TouchInput &touch); +bool NativeKey(const KeyInput &key); +bool NativeAxis(const AxisInput &axis); // Called when it's time to render. If the device can keep up, this // will also be called sixty times per second. Main thread. From a3e23f0ac6266507ecf24a5f4d59087a089ceda3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 15 Jun 2014 13:04:10 +0200 Subject: [PATCH 1134/1445] Propagate input even return values in more places. Handle repeats better. --- android/app-android.cpp | 6 +++- .../libnative/InputDeviceState.java | 18 +++++------- .../libnative/NativeActivity.java | 24 +++++---------- .../henrikrydgard/libnative/NativeApp.java | 2 +- .../henrikrydgard/libnative/NativeGLView.java | 11 ++++--- .../libnative/NativeRenderer.java | 2 +- input/input_state.h | 1 + ui/screen.cpp | 27 +++++++++++------ ui/screen.h | 12 ++++---- ui/ui_screen.cpp | 25 +++++++++------- ui/ui_screen.h | 19 ++++++------ ui/viewgroup.cpp | 29 +++++++++++++++---- ui/viewgroup.h | 6 ++-- 13 files changed, 105 insertions(+), 77 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 3c4b080794..258fa7340d 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -412,11 +412,15 @@ extern "C" jboolean JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch return retval; } -extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint deviceId, jint key) { +extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, jclass, jint deviceId, jint key, jboolean isRepeat) { KeyInput keyInput; keyInput.deviceId = deviceId; keyInput.keyCode = key; keyInput.flags = KEY_DOWN; + if (isRepeat) { + ILOG("Is repeat! %i", key); + keyInput.flags |= KEY_IS_REPEAT; + } return NativeKey(keyInput); } diff --git a/android/src/com/henrikrydgard/libnative/InputDeviceState.java b/android/src/com/henrikrydgard/libnative/InputDeviceState.java index b798261c3f..a17ac0cc60 100644 --- a/android/src/com/henrikrydgard/libnative/InputDeviceState.java +++ b/android/src/com/henrikrydgard/libnative/InputDeviceState.java @@ -14,12 +14,12 @@ public class InputDeviceState { // DEVICE_ID_PAD_0 from the cpp code. TODO: allocate these sequentially if we get more controllers. private static int deviceId = 10; - + private InputDevice mDevice; private int[] mAxes; - + InputDevice getDevice() { return mDevice; } - + @TargetApi(19) void logAdvanced(InputDevice device) { Log.i(TAG, "Vendor ID:" + device.getVendorId() + " productId: " + device.getProductId()); @@ -68,17 +68,13 @@ public class InputDeviceState { public boolean onKeyDown(KeyEvent event) { int keyCode = event.getKeyCode(); - if (event.getRepeatCount() == 0) { - NativeApp.keyDown(deviceId, keyCode); - return true; - } - return false; + boolean repeat = event.getRepeatCount() > 0; + return NativeApp.keyDown(deviceId, keyCode, repeat); } public boolean onKeyUp(KeyEvent event) { - int keyCode = event.getKeyCode(); - NativeApp.keyUp(deviceId, keyCode); - return true; + int keyCode = event.getKeyCode(); + return NativeApp.keyUp(deviceId, keyCode); } public boolean onJoystickMotion(MotionEvent event) { diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index c60ebb8f6f..5503d4c55d 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -532,9 +532,6 @@ public class NativeActivity extends Activity { boolean passThrough = false; switch (event.getKeyCode()) { case KeyEvent.KEYCODE_BACK: - case KeyEvent.KEYCODE_VOLUME_DOWN: - case KeyEvent.KEYCODE_VOLUME_UP: - case KeyEvent.KEYCODE_VOLUME_MUTE: case KeyEvent.KEYCODE_MENU: passThrough = true; break; @@ -608,25 +605,22 @@ public class NativeActivity extends Activity { public boolean onKeyDown(int keyCode, KeyEvent event) { // Eat these keys, to avoid accidental exits / other screwups. // Maybe there's even more we need to eat on tablets? + boolean repeat = event.getRepeatCount() > 0; switch (keyCode) { case KeyEvent.KEYCODE_BACK: if (event.isAltPressed()) { - NativeApp.keyDown(0, 1004); // special custom keycode + NativeApp.keyDown(0, 1004, repeat); // special custom keycode } else if (NativeApp.isAtTopLevel()) { Log.i(TAG, "IsAtTopLevel returned true."); return super.onKeyDown(keyCode, event); } else { - NativeApp.keyDown(0, keyCode); + NativeApp.keyDown(0, keyCode, repeat); } return true; case KeyEvent.KEYCODE_MENU: case KeyEvent.KEYCODE_SEARCH: - NativeApp.keyDown(0, keyCode); + NativeApp.keyDown(0, keyCode, repeat); return true; - case KeyEvent.KEYCODE_VOLUME_DOWN: - case KeyEvent.KEYCODE_VOLUME_UP: - // NativeApp should ignore these. - return super.onKeyDown(keyCode, event); case KeyEvent.KEYCODE_DPAD_UP: case KeyEvent.KEYCODE_DPAD_DOWN: @@ -641,8 +635,7 @@ public class NativeActivity extends Activity { // send the rest of the keys through. // TODO: get rid of the three special cases above by adjusting the native side of the code. // Log.d(TAG, "Key down: " + keyCode + ", KeyEvent: " + event); - NativeApp.keyDown(0, keyCode); - return true; + return NativeApp.keyDown(0, keyCode, repeat); } } @@ -665,9 +658,7 @@ public class NativeActivity extends Activity { // Search probably should also be ignored. We send it to the app. NativeApp.keyUp(0, keyCode); return true; - case KeyEvent.KEYCODE_VOLUME_DOWN: - case KeyEvent.KEYCODE_VOLUME_UP: - return super.onKeyUp(keyCode, event); + case KeyEvent.KEYCODE_DPAD_UP: case KeyEvent.KEYCODE_DPAD_DOWN: case KeyEvent.KEYCODE_DPAD_LEFT: @@ -681,8 +672,7 @@ public class NativeActivity extends Activity { // send the rest of the keys through. // TODO: get rid of the three special cases above by adjusting the native side of the code. // Log.d(TAG, "Key down: " + keyCode + ", KeyEvent: " + event); - NativeApp.keyUp(0, keyCode); - return true; + return NativeApp.keyUp(0, keyCode); } } diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 03eb8fa96f..b435fdbce1 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -22,7 +22,7 @@ public class NativeApp { // There's not really any reason to ever call shutdown as we can recover from a killed activity. public static native void shutdown(); - public static native boolean keyDown(int deviceId, int key); + public static native boolean keyDown(int deviceId, int key, boolean isRepeat); public static native boolean keyUp(int deviceId, int key); public static native void beginJoystickEvent(); diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 6fd0fc9391..2caa1e0604 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -71,6 +71,8 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, public boolean onTouchEvent(final MotionEvent ev) { boolean canReadToolType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH; + + boolean retval = false; for (int i = 0; i < ev.getPointerCount(); i++) { int pid = ev.getPointerId(i); int code = 0; @@ -101,11 +103,11 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, int tool = getToolType(ev, i); code |= tool << 10; // We use the Android tool type codes } - NativeApp.touch(ev.getX(i), ev.getY(i), code, pid); + retval = retval || NativeApp.touch(ev.getX(i), ev.getY(i), code, pid); } } - return true; - } + return retval; + } // Sensor management public void onAccuracyChanged(Sensor sensor, int arg1) { @@ -165,9 +167,10 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, } } + boolean repeat = false; // Moga has no repeats? switch (event.getAction()) { case KeyEvent.ACTION_DOWN: - NativeApp.keyDown(NativeApp.DEVICE_ID_PAD_0, event.getKeyCode()); + NativeApp.keyDown(NativeApp.DEVICE_ID_PAD_0, event.getKeyCode(), repeat); break; case KeyEvent.ACTION_UP: NativeApp.keyUp(NativeApp.DEVICE_ID_PAD_0, event.getKeyCode()); diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index 95911a7275..4856fdd09c 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -65,4 +65,4 @@ public class NativeRenderer implements GLSurfaceView.Renderer { } }); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/input/input_state.h b/input/input_state.h index c9fe43a91c..37f7633b5b 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -159,6 +159,7 @@ enum { KEY_DOWN = 1 << 0, KEY_UP = 1 << 1, KEY_HASWHEELDELTA = 1 << 2, + KEY_IS_REPEAT = 1 << 3, }; struct KeyInput { diff --git a/ui/screen.cpp b/ui/screen.cpp index 7219f2a7ad..341d9a01ec 100644 --- a/ui/screen.cpp +++ b/ui/screen.cpp @@ -64,19 +64,28 @@ void ScreenManager::switchToNext() { UI::SetFocusedView(0); } -void ScreenManager::touch(const TouchInput &touch) { - if (!stack_.empty()) - stack_.back().screen->touch(touch); +bool ScreenManager::touch(const TouchInput &touch) { + if (!stack_.empty()) { + return stack_.back().screen->touch(touch); + } else { + return false; + } } -void ScreenManager::key(const KeyInput &key) { - if (!stack_.empty()) - stack_.back().screen->key(key); +bool ScreenManager::key(const KeyInput &key) { + if (!stack_.empty()) { + return stack_.back().screen->key(key); + } else { + return false; + } } -void ScreenManager::axis(const AxisInput &axis) { - if (!stack_.empty()) - stack_.back().screen->axis(axis); +bool ScreenManager::axis(const AxisInput &axis) { + if (!stack_.empty()) { + return stack_.back().screen->axis(axis); + } else { + return false; + } } void ScreenManager::resized() { diff --git a/ui/screen.h b/ui/screen.h index 9a76ab119e..8992c235a1 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -49,9 +49,9 @@ public: virtual void deviceLost() {} virtual void resized() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} - virtual void touch(const TouchInput &touch) {} - virtual void key(const KeyInput &key) {} - virtual void axis(const AxisInput &touch) {} + virtual bool touch(const TouchInput &touch) { return false; } + virtual bool key(const KeyInput &key) { return false; } + virtual bool axis(const AxisInput &touch) { return false; } virtual void sendMessage(const char *msg, const char *value) {} virtual void RecreateViews() {} @@ -109,9 +109,9 @@ public: void finishDialog(Screen *dialog, DialogResult result = DR_OK); // Instant touch, separate from the update() mechanism. - void touch(const TouchInput &touch); - void key(const KeyInput &key); - void axis(const AxisInput &touch); + bool touch(const TouchInput &touch); + bool key(const KeyInput &key); + bool axis(const AxisInput &touch); // Generic facility for gross hacks :P void sendMessage(const char *msg, const char *value); diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 745ac549fd..535d1e9018 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -48,19 +48,22 @@ void UIScreen::render() { } } -void UIScreen::touch(const TouchInput &touch) { +bool UIScreen::touch(const TouchInput &touch) { if (root_) { UI::TouchEvent(touch, root_); + return true; } + return false; } -void UIScreen::key(const KeyInput &key) { +bool UIScreen::key(const KeyInput &key) { if (root_) { - UI::KeyEvent(key, root_); + return UI::KeyEvent(key, root_); } + return false; } -void UIDialogScreen::key(const KeyInput &key) { +bool UIDialogScreen::key(const KeyInput &key) { if ((key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) { if (finished_) { ELOG("Screen already finished"); @@ -68,12 +71,13 @@ void UIDialogScreen::key(const KeyInput &key) { finished_ = true; screenManager()->finishDialog(this, DR_BACK); } + return true; } else { - UIScreen::key(key); + return UIScreen::key(key); } } -void UIScreen::axis(const AxisInput &axis) { +bool UIScreen::axis(const AxisInput &axis) { // Simple translation of hat to keys for Shield and other modern pads. // TODO: Use some variant of keymap? int flags = 0; @@ -104,7 +108,9 @@ void UIScreen::axis(const AxisInput &axis) { hatDown_ = flags; if (root_) { UI::AxisEvent(axis, root_); + return true; } + return (pressed & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) != 0; } UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { @@ -131,16 +137,15 @@ PopupScreen::PopupScreen(std::string title, std::string button1, std::string but button2_ = d->T(button2.c_str()); } -void PopupScreen::touch(const TouchInput &touch) { +bool PopupScreen::touch(const TouchInput &touch) { if (!box_ || (touch.flags & TOUCH_DOWN) == 0 || touch.id != 0) { - UIDialogScreen::touch(touch); - return; + return UIDialogScreen::touch(touch); } if (!box_->GetBounds().Contains(touch.x, touch.y)) screenManager()->finishDialog(this, DR_BACK); - UIDialogScreen::touch(touch); + return UIDialogScreen::touch(touch); } void PopupScreen::CreateViews() { diff --git a/ui/ui_screen.h b/ui/ui_screen.h index a8547798fe..6ff656c105 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -10,11 +10,12 @@ public: UIScreen(); ~UIScreen(); - virtual void update(InputState &input); - virtual void render(); - virtual void touch(const TouchInput &touch); - virtual void key(const KeyInput &touch); - virtual void axis(const AxisInput &touch); + virtual void update(InputState &input) override; + virtual void render() override; + + virtual bool touch(const TouchInput &touch) override; + virtual bool key(const KeyInput &touch) override; + virtual bool axis(const AxisInput &touch) override; // Some useful default event handlers UI::EventReturn OnOK(UI::EventParams &e); @@ -39,7 +40,7 @@ private: class UIDialogScreen : public UIScreen { public: UIDialogScreen() : UIScreen(), finished_(false) {} - virtual void key(const KeyInput &key); + virtual bool key(const KeyInput &key) override; private: bool finished_; @@ -51,9 +52,9 @@ public: PopupScreen(std::string title, std::string button1 = "", std::string button2 = ""); virtual void CreatePopupContents(UI::ViewGroup *parent) = 0; - virtual void CreateViews(); - virtual bool isTransparent() const { return true; } - virtual void touch(const TouchInput &touch); + virtual void CreateViews() override; + virtual bool isTransparent() const override { return true; } + virtual bool touch(const TouchInput &touch) override; protected: virtual bool FillVertical() const { return false; } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index efcb94c4f3..b19efb82f4 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1122,8 +1122,10 @@ static std::set heldKeys; static const int repeatDelay = 15; // 250ms static const int repeatInterval = 5; // 66ms -void KeyEvent(const KeyInput &key, ViewGroup *root) { - if (key.flags & KEY_DOWN) { +bool KeyEvent(const KeyInput &key, ViewGroup *root) { + bool retval = false; + // Ignore repeats for focus moves. + if ((key.flags & (KEY_DOWN | KEY_IS_REPEAT)) == KEY_DOWN) { // We ignore the device ID here. Anything with a DPAD is OK. if (key.keyCode >= NKCODE_DPAD_UP && key.keyCode <= NKCODE_DPAD_RIGHT) { // Let's only repeat DPAD initially. @@ -1135,12 +1137,13 @@ void KeyEvent(const KeyInput &key, ViewGroup *root) { // Check if the key is already held. If it is, ignore it. This is to avoid // multiple key repeat mechanisms colliding. if (heldKeys.find(hk) != heldKeys.end()) { - return; + return false; } heldKeys.insert(hk); lock_guard lock(focusLock); focusMoves.push_back(key.keyCode); + retval = true; } } if (key.flags & KEY_UP) { @@ -1151,9 +1154,23 @@ void KeyEvent(const KeyInput &key, ViewGroup *root) { hk.deviceId = key.deviceId; hk.startFrame = 0; // irrelevant heldKeys.erase(hk); + retval = true; } } + root->Key(key); + retval = true; + + // Ignore volume keys and stuff here. Not elegant but need to propagate bools through the view hierarchy as well... + switch (key.keyCode) { + case NKCODE_VOLUME_DOWN: + case NKCODE_VOLUME_UP: + case NKCODE_VOLUME_MUTE: + retval = false; + break; + } + + return retval; } static void ProcessHeldKeys(ViewGroup *root) { @@ -1174,14 +1191,16 @@ static void ProcessHeldKeys(ViewGroup *root) { } } -void TouchEvent(const TouchInput &touch, ViewGroup *root) { +bool TouchEvent(const TouchInput &touch, ViewGroup *root) { EnableFocusMovement(false); root->Touch(touch); + return true; } -void AxisEvent(const AxisInput &axis, ViewGroup *root) { +bool AxisEvent(const AxisInput &axis, ViewGroup *root) { root->Axis(axis); + return true; } void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root) { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 309114dc92..e331c63283 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -377,9 +377,9 @@ private: void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root); void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root); // Hooks arrow keys for navigation -void KeyEvent(const KeyInput &key, ViewGroup *root); -void TouchEvent(const TouchInput &touch, ViewGroup *root); -void AxisEvent(const AxisInput &axis, ViewGroup *root); +bool KeyEvent(const KeyInput &key, ViewGroup *root); +bool TouchEvent(const TouchInput &touch, ViewGroup *root); +bool AxisEvent(const AxisInput &axis, ViewGroup *root); void CaptureDrag(int id); void ReleaseDrag(int id); From 1509ddd2ba714da273576690e08449428549c4e9 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 17 Jun 2014 23:45:04 +1000 Subject: [PATCH 1135/1445] Qt: Fix bug that draws two UIs on USING_GLES2 and not MOBILE_DEVICE --- base/QtMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 0094ab070c..ac5abab2a6 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -109,7 +109,7 @@ float CalculateDPIScale() static int mainInternal(QApplication &a) { -#ifdef USING_GLES2 +#ifdef MOBILE_DEVICE emugl = new MainUI(); emugl->resize(pixel_xres, pixel_yres); emugl->showFullScreen(); From 58020174b12d0361a8457bb3e8691402660e4ee5 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 18 Jun 2014 03:41:20 +1000 Subject: [PATCH 1136/1445] Remove Meego define. Use Maemo instead. --- base/QtMain.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index ac5abab2a6..dd43213cc1 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -39,8 +39,6 @@ std::string System_GetProperty(SystemProperty prop) { return "Qt:Symbian"; #elif defined(BLACKBERRY) return "Qt:Blackberry"; -#elif defined(MEEGO_EDITION_HARMATTAN) - return "Qt:Meego"; #elif defined(MAEMO) return "Qt:Maemo"; #elif defined(ANDROID) @@ -161,7 +159,7 @@ int main(int argc, char *argv[]) #elif defined(BLACKBERRY) const char *savegame_dir = "/accounts/1000/shared/misc/"; const char *assets_dir = "app/native/assets/"; -#elif defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) +#elif defined(MAEMO) const char *savegame_dir = "/home/user/MyDocs/PPSSPP/"; const char *assets_dir = "/opt/PPSSPP/"; #elif defined(ANDROID) From 1c93a5822325dadd693fab30857654e0d4fa46c8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 18 Jun 2014 00:54:11 +0200 Subject: [PATCH 1137/1445] Prevent short-circuit evaluation from eating some of our touch event handling --- android/src/com/henrikrydgard/libnative/NativeGLView.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 2caa1e0604..1cb0a35005 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -72,7 +72,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, public boolean onTouchEvent(final MotionEvent ev) { boolean canReadToolType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH; - boolean retval = false; + int numTouchesHandled = 0; for (int i = 0; i < ev.getPointerCount(); i++) { int pid = ev.getPointerId(i); int code = 0; @@ -103,10 +103,11 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, int tool = getToolType(ev, i); code |= tool << 10; // We use the Android tool type codes } - retval = retval || NativeApp.touch(ev.getX(i), ev.getY(i), code, pid); + // Can't use || due to short circuit evaluation + numTouchesHandled += NativeApp.touch(ev.getX(i), ev.getY(i), code, pid) ? 1 : 0; } } - return retval; + return numTouchesHandled > 0; } // Sensor management From dbfb4d9962cf25983c845d5fa32fbf01581c5604 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 18 Jun 2014 16:14:56 +1000 Subject: [PATCH 1138/1445] Qt: Use inbuilt png handler to resolve conflicts. --- image/png_load.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/image/png_load.cpp b/image/png_load.cpp index 33618ea868..3f48c12c84 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -2,7 +2,11 @@ #include #include +#ifdef USING_QT_UI +#include +#else #include "libpng17/png.h" +#endif #include "png_load.h" #include "base/logging.h" @@ -10,6 +14,20 @@ // *image_data_ptr should be deleted with free() // return value of 1 == success. int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip) { +#ifdef USING_QT_UI + QImage image(file, "PNG"); + if (image.isNull()) { + ELOG("pngLoad: Error loading image %s", file); + return 0; + } + if (flip) + image = image.mirrored(); + image.convertToFormat(QImage::Format_RGB32); + *pwidth = image.width(); + *pheight = image.height(); + *image_data_ptr = (unsigned char *)malloc(image.byteCount()); + memcpy(image.bits(), *image_data_ptr, image.byteCount()); +#else if (flip) ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); png_image png; @@ -30,12 +48,27 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d int stride = PNG_IMAGE_ROW_STRIDE(png); *image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_SIZE(png)); png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL); +#endif return 1; } int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr, bool flip) { +#ifdef USING_QT_UI + QImage image; + if (!image.loadFromData(input_ptr, input_len)) { + ELOG("pngLoad: Error loading image"); + return 0; + } + if (flip) + image = image.mirrored(); + image.convertToFormat(QImage::Format_RGB32); + *pwidth = image.width(); + *pheight = image.height(); + *image_data_ptr = (unsigned char *)malloc(image.byteCount()); + memcpy(image.bits(), *image_data_ptr, image.byteCount()); +#else if (flip) ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); png_image png; @@ -56,6 +89,7 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in int stride = PNG_IMAGE_ROW_STRIDE(png); *image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_SIZE(png)); png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL); +#endif return 1; } From 1ec7516a1a813815c78518a38f5984ce61e75c5e Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 20 Jun 2014 23:09:49 +1000 Subject: [PATCH 1139/1445] Qt: Qt4 doesn't support RGBA directly. So lets convert manually. --- image/png_load.cpp | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/image/png_load.cpp b/image/png_load.cpp index 3f48c12c84..32b844f2de 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -3,7 +3,7 @@ #include #ifdef USING_QT_UI -#include +#include #else #include "libpng17/png.h" #endif @@ -20,13 +20,25 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d ELOG("pngLoad: Error loading image %s", file); return 0; } + if (flip) image = image.mirrored(); - image.convertToFormat(QImage::Format_RGB32); *pwidth = image.width(); *pheight = image.height(); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + image.convertToFormat(QImage::Format_ARGB32); *image_data_ptr = (unsigned char *)malloc(image.byteCount()); + uint32_t *src = (uint32_t*) image.bits(); + uint32_t *dest = (uint32_t*) *image_data_ptr; + // Qt4 does not support RGBA + for (size_t sz = 0; sz < image.byteCount(); sz+=4, ++src, ++dest) { + const uint32_t v = *src; + *dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // ARGB -> RGBA + } +#else + image.convertToFormat(QImage::Format_RGBA8888); memcpy(image.bits(), *image_data_ptr, image.byteCount()); +#endif #else if (flip) ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); @@ -57,17 +69,28 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in bool flip) { #ifdef USING_QT_UI QImage image; - if (!image.loadFromData(input_ptr, input_len)) { + if (!image.loadFromData(input_ptr, input_len, "PNG")) { ELOG("pngLoad: Error loading image"); return 0; } + if (flip) image = image.mirrored(); - image.convertToFormat(QImage::Format_RGB32); *pwidth = image.width(); *pheight = image.height(); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) *image_data_ptr = (unsigned char *)malloc(image.byteCount()); + uint32_t *src = (uint32_t*) image.bits(); + uint32_t *dest = (uint32_t*) *image_data_ptr; + // Qt4 does not support RGBA + for (size_t sz = 0; sz < image.byteCount(); sz+=4, ++src, ++dest) { + const uint32_t v = *src; + *dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // convert it! + } +#else + image.convertToFormat(QImage::Format_RGBA8888); memcpy(image.bits(), *image_data_ptr, image.byteCount()); +#endif #else if (flip) ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); From 9a6d1ce7e70b9c616263bedf40381e5c7cc9f6b2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 20 Jun 2014 08:48:44 -0700 Subject: [PATCH 1140/1445] Define fast_matrix_mul_4x4_neon with dual mangling. Some compilers/platforms want or don't want the underscore prefix. Both should work fine. --- math/fast/fast_matrix_neon.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/math/fast/fast_matrix_neon.S b/math/fast/fast_matrix_neon.S index fbf9199315..3b5d930849 100644 --- a/math/fast/fast_matrix_neon.S +++ b/math/fast/fast_matrix_neon.S @@ -15,6 +15,8 @@ @ r2 = pointer to 4x4 matrix 1, single precision floats, column major order @ + .globl _fast_matrix_mul_4x4_neon +_fast_matrix_mul_4x4_neon: .globl fast_matrix_mul_4x4_neon fast_matrix_mul_4x4_neon: vld1.32 {d16-d19}, [r1]! @ load first eight elements of matrix 0 From c3fffa291bc92e290216305d9f2bd66c89902e22 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 22 Jun 2014 10:34:22 +0200 Subject: [PATCH 1141/1445] Update uistate hackery. Need to get rid of this from PCMain.cpp... --- base/PCMain.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index b3e7386a2f..48ca4fc45b 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -45,7 +45,7 @@ SDLJoystick *joystick = NULL; #include "Core/Core.h" #include "Core/Config.h" -GlobalUIState lastUIState = UISTATE_MENU; +GlobalUIState GetUIState(); #endif static SDL_Surface* g_Screen = NULL; @@ -783,8 +783,8 @@ int main(int argc, char *argv[]) { break; NativeRender(); #if defined(PPSSPP) && !defined(MOBILE_DEVICE) - if (lastUIState != globalUIState) { - lastUIState = globalUIState; + if (lastUIState != GetUIState()) { + lastUIState = GetUIState(); if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) SDL_ShowCursor(SDL_DISABLE); if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen) From 820bad2d64a18261925a922074b03daf4b6b1191 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 22 Jun 2014 10:53:06 +0200 Subject: [PATCH 1142/1445] Oops, should not have deleted this. --- base/PCMain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 48ca4fc45b..7b1e6da6a0 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -45,6 +45,7 @@ SDLJoystick *joystick = NULL; #include "Core/Core.h" #include "Core/Config.h" +GlobalUIState lastUIState = UISTATE_MENU; GlobalUIState GetUIState(); #endif From bddebfceebd1b8e4c57ac300c4deddb526cdea08 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 22 Jun 2014 11:17:03 +0200 Subject: [PATCH 1143/1445] Blackberry and mobile Qt buildfixes --- base/BlackberryMain.cpp | 6 +++--- base/PCMain.cpp | 1 + base/QtMain.h | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 5f7de616cd..03d7567f9d 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -15,6 +15,7 @@ #include "base/NKCodeFromBlackberry.h" // Bad: PPSSPP includes from native +#include "Core/System.h" #include "Core/Config.h" #include "UI/MiscScreens.h" @@ -303,15 +304,14 @@ void BlackberryMain::runMain() { // Work in Progress // Currently: Render to HDMI port (eg. 1080p) when in game. Render to device when in menu. // Idea: Render to all displays. Controls go to internal, game goes to external(s). - if (globalUIState == UISTATE_INGAME && !emulating) - { + if (GetUIState() == UISTATE_INGAME && !emulating) { emulating = true; switchDisplay(screen_emu); if (g_Config.iShowFPSCounter == 4) { int options = SCREEN_DEBUG_STATISTICS; screen_set_window_property_iv(screen_win[0], SCREEN_PROPERTY_DEBUG, &options); } - } else if (globalUIState != UISTATE_INGAME && emulating) { + } else if (GetUIState() != UISTATE_INGAME && emulating) { emulating = false; switchDisplay(screen_ui); } diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 7b1e6da6a0..c8e43b126e 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -42,6 +42,7 @@ SDLJoystick *joystick = NULL; #ifdef PPSSPP // Bad: PPSSPP includes from native +#include "Core/System.h" #include "Core/Core.h" #include "Core/Config.h" diff --git a/base/QtMain.h b/base/QtMain.h index 8361af7ea2..a12730b817 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -28,6 +28,7 @@ QTM_USE_NAMESPACE #include "base/NKCodeFromQt.h" // Bad: PPSSPP includes from native +#include "Core/System.h" #include "Core/Core.h" #include "Core/Config.h" @@ -132,7 +133,7 @@ protected: } break; case QEvent::MouseButtonDblClick: - if (!g_Config.bShowTouchControls || globalUIState != UISTATE_INGAME) + if (!g_Config.bShowTouchControls || GetUIState() != UISTATE_INGAME) emit doubleClick(); break; case QEvent::MouseButtonPress: From fe1100a714c760ed8f24df6f48cc90fcb02184f7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 22 Jun 2014 17:41:15 +0200 Subject: [PATCH 1144/1445] Add a pointer constructor to chunk_file --- file/chunk_file.cpp | 11 +++++++++++ file/chunk_file.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index e7199a1359..4dd58dd8f7 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -36,6 +36,17 @@ ChunkFile::ChunkFile(const char *filename, bool _read) { } } +ChunkFile::ChunkFile(const uint8_t *read_data, int data_size) { + data = new uint8_t[data_size]; + memcpy(data, read_data, data_size); + fastMode = true; + numLevels = 0; + read = true; + pos = 0; + didFail = false; + eof = data_size; +} + ChunkFile::~ChunkFile() { if (fastMode && data) delete [] data; diff --git a/file/chunk_file.h b/file/chunk_file.h index 7eb62a972a..520b45b5bb 100644 --- a/file/chunk_file.h +++ b/file/chunk_file.h @@ -22,6 +22,8 @@ inline uint32 flipID(uint32 id) { class ChunkFile { public: ChunkFile(const char *filename, bool _read); + ChunkFile(const uint8_t *read_data, int data_size); + ~ChunkFile(); bool descend(uint32 id); From 8685d02e6d44cbe327ab49f69efbcc1275771d6f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 22 Jun 2014 17:46:38 +0200 Subject: [PATCH 1145/1445] When disabling keyboard focus, send a lost focus message --- ui/view.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/view.cpp b/ui/view.cpp index 0b45e499f7..feb59e55e7 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -73,8 +73,11 @@ void SetFocusedView(View *view) { void EnableFocusMovement(bool enable) { focusMovementEnabled = enable; - if (!enable) + if (!enable) { + if (focusedView) + focusedView->FocusChanged(FF_LOSTFOCUS); focusedView = 0; + } } bool IsFocusMovementEnabled() { From 51c8a57821ecf412a161f7bb134c0a2a0ef0412e Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 25 Jun 2014 13:00:42 +1000 Subject: [PATCH 1146/1445] Qt: Use SDL Audio where available. Should give consistent audio amongst Linux platforms. --- base/QtMain.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index dd43213cc1..72078ef6f7 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -25,6 +25,7 @@ #endif #ifdef QT_HAS_SDL #include "SDL/SDLJoystick.h" +#include "SDL_audio.h" #endif #include "QtMain.h" @@ -32,6 +33,12 @@ InputState* input_state; +#ifdef QT_HAS_SDL +extern void mixaudio(void *userdata, Uint8 *stream, int len) { + NativeMix((short *)stream, len / 4); +} +#endif + std::string System_GetProperty(SystemProperty prop) { switch (prop) { case SYSPROP_NAME: @@ -121,18 +128,51 @@ static int mainInternal(QApplication &a) QScopedPointer mediakeys(new SymbianMediaKeys()); #endif +#ifdef QT_HAS_SDL + SDLJoystick joy(true); + joy.startEventLoop(); + SDL_Init(SDL_INIT_AUDIO); + SDL_AudioSpec fmt, ret_fmt; + memset(&fmt, 0, sizeof(fmt)); + fmt.freq = 44100; + fmt.format = AUDIO_S16; + fmt.channels = 2; + fmt.samples = 2048; + fmt.callback = &mixaudio; + fmt.userdata = (void *)0; + + if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) { + ELOG("Failed to open audio: %s", SDL_GetError()); + } else { + if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2 || fmt.samples != 2048) { + ELOG("Sound buffer format does not match requested format."); + ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, 44100); + ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, AUDIO_S16); + ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, 2); + ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, 2048); + } + + if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2) { + ELOG("Provided output format does not match requirement, turning audio off"); + SDL_CloseAudio(); + } else { + ELOG("Provided output audio format is usable, thus using it"); + } + } + + // Audio must be unpaused _after_ NativeInit() + SDL_PauseAudio(0); +#else QScopedPointer thread(new QThread); QScopedPointer audio(new MainAudio()); audio->moveToThread(thread.data()); QObject::connect(thread.data(), SIGNAL(started()), audio.data(), SLOT(run())); thread->start(); - -#ifdef QT_HAS_SDL - SDLJoystick joy(true); - joy.startEventLoop(); #endif int ret = a.exec(); +#ifndef QT_HAS_SDL thread->quit(); +#endif return ret; } @@ -174,6 +214,12 @@ int main(int argc, char *argv[]) int ret = mainInternal(a); +#ifndef MOBILE_DEVICE + exit(0); +#endif + NativeShutdownGraphics(); + SDL_PauseAudio(1); + SDL_CloseAudio(); NativeShutdown(); net::Shutdown(); return ret; From c50c17d6eba1be98ce6a10726ccf11cd543c1b4c Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 25 Jun 2014 13:22:45 +1000 Subject: [PATCH 1147/1445] Qt5: Fix malloc inside ifdef --- image/png_load.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/image/png_load.cpp b/image/png_load.cpp index 32b844f2de..ec4e6da92a 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -25,9 +25,9 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d image = image.mirrored(); *pwidth = image.width(); *pheight = image.height(); + *image_data_ptr = (unsigned char *)malloc(image.byteCount()); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) image.convertToFormat(QImage::Format_ARGB32); - *image_data_ptr = (unsigned char *)malloc(image.byteCount()); uint32_t *src = (uint32_t*) image.bits(); uint32_t *dest = (uint32_t*) *image_data_ptr; // Qt4 does not support RGBA @@ -78,8 +78,8 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in image = image.mirrored(); *pwidth = image.width(); *pheight = image.height(); -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) *image_data_ptr = (unsigned char *)malloc(image.byteCount()); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) uint32_t *src = (uint32_t*) image.bits(); uint32_t *dest = (uint32_t*) *image_data_ptr; // Qt4 does not support RGBA From eb458da7c7548236b6d9a3f24f2b59a5a89ab82d Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 25 Jun 2014 13:26:43 +1000 Subject: [PATCH 1148/1445] Qt: forgot ifdef --- base/QtMain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 72078ef6f7..1d7d1c5c3b 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -218,8 +218,10 @@ int main(int argc, char *argv[]) exit(0); #endif NativeShutdownGraphics(); +#ifdef QT_HAS_SDL SDL_PauseAudio(1); SDL_CloseAudio(); +#endif NativeShutdown(); net::Shutdown(); return ret; From 9c0d44ceb0b628b5d66f9257e8f59cf97a9ab888 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 25 Jun 2014 15:40:28 +1000 Subject: [PATCH 1149/1445] Qt: Let Qt decide which directories to use for Qt5. Fix an SDL Audio error which was a false positive. --- base/PCMain.cpp | 16 ++++++---------- base/QtMain.cpp | 48 ++++++++++++++++++++++-------------------------- 2 files changed, 28 insertions(+), 36 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index c8e43b126e..d04600df0e 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -579,19 +579,15 @@ int main(int argc, char *argv[]) { if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) { ELOG("Failed to open audio: %s", SDL_GetError()); } else { - if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2 || fmt.samples != 2048) { + if (ret_fmt.samples != fmt.samples) // Notify, but still use it + ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples); + if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) { ELOG("Sound buffer format does not match requested format."); - ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, 44100); - ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, AUDIO_S16); - ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, 2); - ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, 2048); - } - - if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2) { + ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq); + ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format); + ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels); ELOG("Provided output format does not match requirement, turning audio off"); SDL_CloseAudio(); - } else { - ELOG("Provided output audio format is usable, thus using it"); } } diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 1d7d1c5c3b..3c13a22bfb 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -13,7 +13,7 @@ #include #include -#ifdef ANDROID +#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) #include #endif @@ -144,19 +144,15 @@ static int mainInternal(QApplication &a) if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) { ELOG("Failed to open audio: %s", SDL_GetError()); } else { - if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2 || fmt.samples != 2048) { + if (ret_fmt.samples != fmt.samples) // Notify, but still use it + ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples); + if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) { ELOG("Sound buffer format does not match requested format."); - ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, 44100); - ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, AUDIO_S16); - ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, 2); - ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, 2048); - } - - if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2) { + ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq); + ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format); + ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels); ELOG("Provided output format does not match requirement, turning audio off"); SDL_CloseAudio(); - } else { - ELOG("Provided output audio format is usable, thus using it"); } } @@ -193,24 +189,24 @@ int main(int argc, char *argv[]) g_dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); -#ifdef __SYMBIAN32__ - const char *savegame_dir = "E:/PPSSPP/"; - const char *assets_dir = "E:/PPSSPP/"; + std::string savegame_dir = "."; + std::string assets_dir = "."; +#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) + savegame_dir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString(); + assets_dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation).toStdString(); +#elif defined(__SYMBIAN32__) + savegame_dir = "E:/PPSSPP"; + assets_dir = "E:/PPSSPP"; #elif defined(BLACKBERRY) - const char *savegame_dir = "/accounts/1000/shared/misc/"; - const char *assets_dir = "app/native/assets/"; + savegame_dir = "/accounts/1000/shared/misc"; + assets_dir = "app/native/assets"; #elif defined(MAEMO) - const char *savegame_dir = "/home/user/MyDocs/PPSSPP/"; - const char *assets_dir = "/opt/PPSSPP/"; -#elif defined(ANDROID) - const char *savegame_dir = QStandardPaths::standardLocations(QStandardPaths::HomeLocation).at(0).toStdString().c_str(); - const char *assets_dir = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).at(0).toStdString().c_str(); - setenv("QT_USE_ANDROID_NATIVE_DIALOGS", "1", 1); // Which Qt version does this need? -#else - const char *savegame_dir = "./"; - const char *assets_dir = "./"; + savegame_dir = "/home/user/MyDocs/PPSSPP"; + assets_dir = "/opt/PPSSPP"; #endif - NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); + savegame_dir += "/"; + assets_dir += "/"; + NativeInit(argc, (const char **)argv, savegame_dir.c_str(), assets_dir.c_str(), "BADCOFFEE"); int ret = mainInternal(a); From ae341ca45e85b451f56f2aa699f1ab4d1200c8fc Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 26 Jun 2014 17:42:36 +1000 Subject: [PATCH 1150/1445] Qt: RGBA8888 only in Qt5.2+ --- image/png_load.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image/png_load.cpp b/image/png_load.cpp index ec4e6da92a..0f461cdfec 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -26,7 +26,7 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d *pwidth = image.width(); *pheight = image.height(); *image_data_ptr = (unsigned char *)malloc(image.byteCount()); -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) image.convertToFormat(QImage::Format_ARGB32); uint32_t *src = (uint32_t*) image.bits(); uint32_t *dest = (uint32_t*) *image_data_ptr; From 320f5f1952c1c462e67c634af7455105967fc602 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 26 Jun 2014 17:58:05 +1000 Subject: [PATCH 1151/1445] Qt: Some things I missed. --- base/QtMain.cpp | 4 ++-- image/png_load.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 3c13a22bfb..699f84efb4 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -3,7 +3,7 @@ * */ // Qt 4.7+ / 5.0+ implementation of the framework. -// Currently supports: Symbian, Blackberry, Maemo/Meego, Linux, Windows, Mac OSX +// Currently supports: Android, Symbian, Blackberry, Maemo/Meego, Linux, Windows, Mac OSX #include #include @@ -193,7 +193,7 @@ int main(int argc, char *argv[]) std::string assets_dir = "."; #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) savegame_dir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString(); - assets_dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation).toStdString(); + assets_dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation).toStdString(); #elif defined(__SYMBIAN32__) savegame_dir = "E:/PPSSPP"; assets_dir = "E:/PPSSPP"; diff --git a/image/png_load.cpp b/image/png_load.cpp index 0f461cdfec..51c36b7b13 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -79,7 +79,7 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in *pwidth = image.width(); *pheight = image.height(); *image_data_ptr = (unsigned char *)malloc(image.byteCount()); -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) uint32_t *src = (uint32_t*) image.bits(); uint32_t *dest = (uint32_t*) *image_data_ptr; // Qt4 does not support RGBA From 2fd318662460046262fa4d94667a66c75162b17f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 29 Jun 2014 12:20:46 +0200 Subject: [PATCH 1152/1445] Log an error if lost manager exits with objects still registered --- gfx/gl_lost_manager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx/gl_lost_manager.cpp b/gfx/gl_lost_manager.cpp index c36805b841..98cf37c52d 100644 --- a/gfx/gl_lost_manager.cpp +++ b/gfx/gl_lost_manager.cpp @@ -67,7 +67,10 @@ void gl_lost_manager_init() { void gl_lost_manager_shutdown() { if (!holders) { FLOG("Lost manager already shutdown"); + } else if (holders->size() > 0) { + ELOG("Lost manager shutdown with %i objects still registered", (int)holders->size()); } + delete holders; holders = 0; } From e65160102599ddbce3410ec17f39364b93e22424 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 29 Jun 2014 12:44:07 +0200 Subject: [PATCH 1153/1445] Clean up threadutil.cpp/h. Add AssertCurrentThreadName function. --- thread/threadutil.cpp | 34 +++++++++++++++++++------ thread/threadutil.h | 58 +++---------------------------------------- 2 files changed, 31 insertions(+), 61 deletions(-) diff --git a/thread/threadutil.cpp b/thread/threadutil.cpp index 24ff853c1b..6dcaa4369d 100644 --- a/thread/threadutil.cpp +++ b/thread/threadutil.cpp @@ -1,16 +1,24 @@ #ifdef _WIN32 #include +#define TLS_SUPPORTED +#elif defined(ANDROID) +#define TLS_SUPPORTED #endif + +#include "base/basictypes.h" +#include "base/logging.h" #include "thread/threadutil.h" -void setCurrentThreadName(const char* szThreadName) -{ -#ifdef _WIN32 - static const DWORD MS_VC_EXCEPTION = 0x406D1388; +#ifdef TLS_SUPPORTED +static __THREAD const char *curThreadName; +#endif +void setCurrentThreadName(const char* threadName) { +#ifdef _WIN32 + // Set the debugger-visible threadname through an unholy magic hack + static const DWORD MS_VC_EXCEPTION = 0x406D1388; #pragma pack(push,8) - struct THREADNAME_INFO - { + struct THREADNAME_INFO { DWORD dwType; // must be 0x1000 LPCSTR szName; // pointer to name (in user addr space) DWORD dwThreadID; // thread ID (-1=caller thread) @@ -19,7 +27,7 @@ void setCurrentThreadName(const char* szThreadName) #pragma pack(pop) info.dwType = 0x1000; - info.szName = szThreadName; + info.szName = threadName; info.dwThreadID = -1; //dwThreadID; info.dwFlags = 0; @@ -31,5 +39,17 @@ void setCurrentThreadName(const char* szThreadName) {} #else // Do nothing +#endif + // Set the locally known threadname using a thread local variable. +#ifdef TLS_SUPPORTED + curThreadName = threadName; +#endif +} + +void AssertCurrentThreadName(const char *threadName) { +#ifdef TLS_SUPPORTED + if (strcmp(curThreadName, threadName) != 0) { + ELOG("Thread name assert failed: Expected %s, was %s", threadName, curThreadName); + } #endif } diff --git a/thread/threadutil.h b/thread/threadutil.h index 347562a26c..2c80ef7736 100644 --- a/thread/threadutil.h +++ b/thread/threadutil.h @@ -1,56 +1,6 @@ #pragma once -#include - -#ifdef _WIN32 -#define NOMINMAX -#define WIN32_LEAN_AND_MEAN -#include -#include -#else - -#include - -#ifndef _POSIX_THREADS -#error unsupported platform (no pthreads?) -#endif - -#include - -#endif - -void setCurrentThreadName(const char *name); - -/* -class thread { -private: -#ifdef _WIN32 - typedef HANDLE thread_; -#else - typedef pthread_t thread_; -#endif - -public: - //void run(std::function threadFunc) { - // func_ = - //} - - void wait() { - - } -};*/ - - -#ifdef _WIN32 -#define THREAD_HANDLE HANDLE -#else -#define THREAD_HANDLE pthread_t -#endif - - -// TODO: replace this abomination with std::thread - -class thread { -public: - virtual void Run(); -}; \ No newline at end of file +// Note that name must be a global string that lives until the end of the process, +// for assertThreadName to work. +void setCurrentThreadName(const char *threadName); +void AssertCurrentThreadName(const char *threadName); From 69a6ba884c3c5036b4a7558f626c52a79474daf7 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 29 Jun 2014 22:14:22 +1000 Subject: [PATCH 1154/1445] Qt+Blackberry: Notify PPSSPP Core of minimized window. --- base/BlackberryMain.cpp | 4 ++++ base/QtMain.h | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 03d7567f9d..a3888b05ed 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -17,6 +17,7 @@ // Bad: PPSSPP includes from native #include "Core/System.h" #include "Core/Config.h" +#include "Core/Core.h" #include "UI/MiscScreens.h" static bool g_quitRequested = false; @@ -271,6 +272,9 @@ void BlackberryMain::runMain() { case NAVIGATOR_ORIENTATION: sensor_remap_coordinates(navigator_event_get_orientation_angle(event)); break; + case NAVIGATOR_WINDOW_STATE: + Core_NotifyWindowHidden(navigator_event_get_window_state(event) != NAVIGATOR_WINDOW_FULLSCREEN); + break; case NAVIGATOR_BACK: case NAVIGATOR_SWIPE_DOWN: NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE, KEY_DOWN)); diff --git a/base/QtMain.h b/base/QtMain.h index a12730b817..ff7651e99c 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -91,6 +91,12 @@ protected: updateGL(); emit newFrame(); } + void changeEvent(QEvent *e) + { + QGLWidget::changeEvent(e); + if(e->type() == QEvent::WindowStateChange) + Core_NotifyWindowHidden(isMinimized()); + } bool event(QEvent *e) { TouchInput input; From 50d4319832447774c8eabb823e82c0898377419b Mon Sep 17 00:00:00 2001 From: Sacha Date: Mon, 30 Jun 2014 00:15:37 +1000 Subject: [PATCH 1155/1445] Use the UpdateRunLoop from Core as it handles when window is minimized. There is no way outside of Core right now (bad for native?). --- base/BlackberryMain.cpp | 4 +--- base/PCMain.cpp | 5 +---- base/QtMain.h | 8 +++----- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index a3888b05ed..36cf8e3901 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -304,7 +304,6 @@ void BlackberryMain::runMain() { } } UpdateInputState(&input_state); - NativeUpdate(input_state); // Work in Progress // Currently: Render to HDMI port (eg. 1080p) when in game. Render to device when in menu. // Idea: Render to all displays. Controls go to internal, game goes to external(s). @@ -319,9 +318,8 @@ void BlackberryMain::runMain() { emulating = false; switchDisplay(screen_ui); } - NativeRender(); - EndInputState(&input_state); time_update(); + UpdateRunLoop(); // This handles VSync if (emulating) eglSwapBuffers(egl_disp[screen_emu], egl_surf[screen_emu]); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index d04600df0e..12fe958206 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -776,10 +776,9 @@ int main(int argc, char *argv[]) { SimulateGamepad(keys, &input_state); input_state.pad_buttons = pad_buttons; UpdateInputState(&input_state, true); - NativeUpdate(input_state); + UpdateRunLoop(); if (g_QuitRequested) break; - NativeRender(); #if defined(PPSSPP) && !defined(MOBILE_DEVICE) if (lastUIState != GetUIState()) { lastUIState = GetUIState(); @@ -790,8 +789,6 @@ int main(int argc, char *argv[]) { } #endif - EndInputState(&input_state); - if (framecount % 60 == 0) { // glsl_refresh(); // auto-reloads modified GLSL shaders once per second. } diff --git a/base/QtMain.h b/base/QtMain.h index ff7651e99c..cede104ff5 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -11,7 +11,7 @@ #include #if defined(MOBILE_DEVICE) && !defined(MAEMO) #include -#if QT_VERSION < 0x50000 +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) QTM_USE_NAMESPACE #endif #endif @@ -44,7 +44,7 @@ public: QGLWidget(parent) { setAttribute(Qt::WA_AcceptTouchEvents); -#if QT_VERSION < 0x50000 +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) setAttribute(Qt::WA_LockLandscapeOrientation); #endif #if defined(MOBILE_DEVICE) && !defined(MAEMO) @@ -192,10 +192,8 @@ protected: { updateAccelerometer(); UpdateInputState(&input_state); - NativeUpdate(input_state); - NativeRender(); - EndInputState(&input_state); time_update(); + UpdateRunLoop(); } void updateAccelerometer() From b0f23617308216781b8dbf4ad8448746b1e444a8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 29 Jun 2014 23:31:09 +0200 Subject: [PATCH 1156/1445] Add KEY_CHAR --- input/input_state.h | 1 + 1 file changed, 1 insertion(+) diff --git a/input/input_state.h b/input/input_state.h index 37f7633b5b..5538238cfd 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -160,6 +160,7 @@ enum { KEY_UP = 1 << 1, KEY_HASWHEELDELTA = 1 << 2, KEY_IS_REPEAT = 1 << 3, + KEY_CHAR = 1 << 4, // Unicode character input. Cannot detect keyups of these so KEY_DOWN and KEY_UP are zero when this is set. }; struct KeyInput { From 179347a493ed58af9ecaefb8695b2a84a1d8d3a0 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 1 Jul 2014 00:54:44 +1000 Subject: [PATCH 1157/1445] Qt: Fix png bug. --- image/png_load.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/image/png_load.cpp b/image/png_load.cpp index 51c36b7b13..f731f271a4 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -25,9 +25,9 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d image = image.mirrored(); *pwidth = image.width(); *pheight = image.height(); - *image_data_ptr = (unsigned char *)malloc(image.byteCount()); + *image_data_ptr = (unsigned char *)malloc(image.width() * image.height() * 4); #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) - image.convertToFormat(QImage::Format_ARGB32); + image = image.convertToFormat(QImage::Format_ARGB32); uint32_t *src = (uint32_t*) image.bits(); uint32_t *dest = (uint32_t*) *image_data_ptr; // Qt4 does not support RGBA @@ -36,7 +36,7 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d *dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // ARGB -> RGBA } #else - image.convertToFormat(QImage::Format_RGBA8888); + image = image.convertToFormat(QImage::Format_RGBA8888); memcpy(image.bits(), *image_data_ptr, image.byteCount()); #endif #else @@ -73,13 +73,13 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in ELOG("pngLoad: Error loading image"); return 0; } - if (flip) image = image.mirrored(); *pwidth = image.width(); *pheight = image.height(); - *image_data_ptr = (unsigned char *)malloc(image.byteCount()); + *image_data_ptr = (unsigned char *)malloc(image.width() * image.height() * 4); #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) + image = image.convertToFormat(QImage::Format_ARGB32); uint32_t *src = (uint32_t*) image.bits(); uint32_t *dest = (uint32_t*) *image_data_ptr; // Qt4 does not support RGBA @@ -88,7 +88,7 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in *dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // convert it! } #else - image.convertToFormat(QImage::Format_RGBA8888); + image = image.convertToFormat(QImage::Format_RGBA8888); memcpy(image.bits(), *image_data_ptr, image.byteCount()); #endif #else From 1d1d9f76eddd695ca41ad45a6df6062de81bad6b Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 1 Jul 2014 16:30:36 +1000 Subject: [PATCH 1158/1445] Qt: Use Qt4 path for libpng on Qt5 too (faster anyway and most images are ARGB). --- image/png_load.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/image/png_load.cpp b/image/png_load.cpp index f731f271a4..d48691bfc6 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -25,9 +25,8 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d image = image.mirrored(); *pwidth = image.width(); *pheight = image.height(); - *image_data_ptr = (unsigned char *)malloc(image.width() * image.height() * 4); -#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) image = image.convertToFormat(QImage::Format_ARGB32); + *image_data_ptr = (unsigned char *)malloc(image.byteCount()); uint32_t *src = (uint32_t*) image.bits(); uint32_t *dest = (uint32_t*) *image_data_ptr; // Qt4 does not support RGBA @@ -35,10 +34,6 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d const uint32_t v = *src; *dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // ARGB -> RGBA } -#else - image = image.convertToFormat(QImage::Format_RGBA8888); - memcpy(image.bits(), *image_data_ptr, image.byteCount()); -#endif #else if (flip) ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); @@ -77,9 +72,8 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in image = image.mirrored(); *pwidth = image.width(); *pheight = image.height(); - *image_data_ptr = (unsigned char *)malloc(image.width() * image.height() * 4); -#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) image = image.convertToFormat(QImage::Format_ARGB32); + *image_data_ptr = (unsigned char *)malloc(image.byteCount()); uint32_t *src = (uint32_t*) image.bits(); uint32_t *dest = (uint32_t*) *image_data_ptr; // Qt4 does not support RGBA @@ -87,10 +81,6 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in const uint32_t v = *src; *dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // convert it! } -#else - image = image.convertToFormat(QImage::Format_RGBA8888); - memcpy(image.bits(), *image_data_ptr, image.byteCount()); -#endif #else if (flip) ELOG("pngLoad: flip flag not supported, image will be loaded upside down"); From 8538a5bf74e50bffff193b818062f061e8dd9763 Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 1 Jul 2014 17:14:46 +1000 Subject: [PATCH 1159/1445] Qt: Don't build MainAudio if we will use SDL audio anyway. --- base/QtMain.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/base/QtMain.h b/base/QtMain.h index cede104ff5..3ded3ddbc1 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -7,8 +7,10 @@ #include "gfx_es2/glsl_program.h" #include +#ifndef QT_HAS_SDL #include #include +#endif #if defined(MOBILE_DEVICE) && !defined(MAEMO) #include #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) @@ -233,6 +235,8 @@ private: static MainUI* emugl = NULL; +#ifndef QT_HAS_SDL + // Audio #define AUDIO_FREQ 44100 #define AUDIO_CHANNELS 2 @@ -289,5 +293,7 @@ private: int timer; }; +#endif //QT_HAS_SDL + #endif From 10af5e6f2254942b4f094e2ccd355bf5b7d33787 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 4 Jul 2014 13:35:48 -0700 Subject: [PATCH 1160/1445] Define NOMINMAX before win includes. Prevents some pollution when not including other files. --- net/http_client.h | 1 + 1 file changed, 1 insertion(+) diff --git a/net/http_client.h b/net/http_client.h index dbea901f6d..cc6c607520 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -8,6 +8,7 @@ #include "base/functional.h" #ifdef _WIN32 +#define NOMINMAX #include #else #if defined(__FreeBSD__) || defined(__SYMBIAN32__) From ce9337c8d9ea9b1f26a5f77274aebd49c81bba86 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 6 Jul 2014 16:16:38 -0700 Subject: [PATCH 1161/1445] Try to approximate condvars on win xp better. --- base/mutex.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/base/mutex.h b/base/mutex.h index fb0affa384..99b4260657 100644 --- a/base/mutex.h +++ b/base/mutex.h @@ -235,6 +235,7 @@ public: InitializeConditionVariable(&cond_); #else sema_ = CreateSemaphore(NULL, 0, LONG_MAX, NULL); + waiting_ = 0; #endif #else pthread_cond_init(&event_, NULL); @@ -256,7 +257,10 @@ public: #ifdef _M_X64 WakeConditionVariable(&cond_); #else - ReleaseSemaphore(sema_, 1, NULL); + // Should be locked at this time. + if (waiting_ != 0) { + ReleaseSemaphore(sema_, 1, NULL); + } #endif #else pthread_cond_signal(&event_); @@ -275,9 +279,11 @@ public: // Since a semaphore keeps a count, the window between unlock and lock won't cause us to deadlock. // However, we could wake early incorrectly (if the semaphore is signalled already.) // That's better than deadlocking or forgetting to wake. + waiting_++; mtx.unlock(); WaitForSingleObject(sema_, INFINITE); mtx.lock(); + waiting_--; #endif #else pthread_cond_wait(&event_, &mtx.native_handle()); @@ -292,9 +298,11 @@ public: // Since a semaphore keeps a count, the window between unlock and lock won't cause us to deadlock. // However, we could wake early incorrectly (if the semaphore is signalled already.) // That's better than deadlocking or forgetting to wake. + waiting_++; mtx.unlock(); WaitForSingleObject(sema_, milliseconds); mtx.lock(); + waiting_--; #endif #else timespec timeout; @@ -318,6 +326,7 @@ private: CONDITION_VARIABLE cond_; #else HANDLE sema_; + volatile int waiting_; #endif #else pthread_cond_t event_; From 22f41720b322c44d558546996f205bf6c06104d3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 8 Jul 2014 23:37:51 -0700 Subject: [PATCH 1162/1445] Allow using a disabled pointer on a view. Sometimes this is more convenient. Like with PPSSPP's config settings. --- ui/view.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ui/view.h b/ui/view.h index e6ee7ca895..87d1ac83a3 100644 --- a/ui/view.h +++ b/ui/view.h @@ -291,7 +291,7 @@ View *GetFocusedView(); class View { public: - View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), visibility_(V_VISIBLE), measuredWidth_(0), measuredHeight_(0), enabledPtr_(0), enabled_(true) { + View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), visibility_(V_VISIBLE), measuredWidth_(0), measuredHeight_(0), enabledPtr_(0), enabled_(true), enabledMeansDisabled_(false) { if (!layoutParams) layoutParams_.reset(new LayoutParams()); } @@ -336,14 +336,15 @@ public: return GetFocusedView() == this; } - void SetEnabled(bool enabled) { enabled_ = enabled; } + void SetEnabled(bool enabled) { enabled_ = enabled; enabledMeansDisabled_ = false; } bool IsEnabled() const { if (enabledPtr_) - return *enabledPtr_; + return *enabledPtr_ != enabledMeansDisabled_; else - return enabled_; + return enabled_ != enabledMeansDisabled_; } - void SetEnabledPtr(bool *enabled) { enabledPtr_ = enabled; } + void SetEnabledPtr(bool *enabled) { enabledPtr_ = enabled; enabledMeansDisabled_ = false; } + void SetDisabledPtr(bool *disabled) { enabledPtr_ = disabled; enabledMeansDisabled_ = true; } void SetVisibility(Visibility visibility) { visibility_ = visibility; } Visibility GetVisibility() const { return visibility_; } @@ -375,6 +376,7 @@ protected: private: bool *enabledPtr_; bool enabled_; + bool enabledMeansDisabled_; DISALLOW_COPY_AND_ASSIGN(View); }; From 6336435f8118ab9a5d41ce7ea4a9a14459f4c1a7 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 13 Jul 2014 07:58:42 +1000 Subject: [PATCH 1163/1445] Fix a bug where it would sleep for a full second instead of a millisecond on non-Windows. --- base/buffer.cpp | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index 49e86b09e0..6516528e9b 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -14,6 +14,7 @@ #endif #include "base/logging.h" +#include "base/timeutil.h" #include "file/fd_util.h" Buffer::Buffer() { } @@ -137,26 +138,21 @@ bool Buffer::FlushToFile(const char *filename) { } bool Buffer::FlushSocket(uintptr_t sock) { - for (size_t pos = 0, end = data_.size(); pos < end; ) { - int sent = send(sock, &data_[pos], end - pos, 0); - if (sent < 0) { - ELOG("FlushSocket failed"); - return false; - } - pos += sent; + for (size_t pos = 0, end = data_.size(); pos < end; ) { + int sent = send(sock, &data_[pos], end - pos, 0); + if (sent < 0) { + ELOG("FlushSocket failed"); + return false; + } + pos += sent; - // Buffer full, don't spin. - if (sent == 0) { -#ifdef _WIN32 - Sleep(1); -#else - sleep(1); -#endif - } - } - - data_.resize(0); - return true; + // Buffer full, don't spin. + if (sent == 0) { + sleep_ms(1); + } + } + data_.resize(0); + return true; } bool Buffer::ReadAll(int fd) { From 84df417a01c425c64cd7d5dfe44a598a72c94611 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 13 Jul 2014 08:15:14 +1000 Subject: [PATCH 1164/1445] Fix two more sleep bugs. --- net/http_client.cpp | 6 +----- net/resolve.cpp | 7 ++----- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 5a1f3d9c2e..59b6257529 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -85,11 +85,7 @@ bool Connection::Connect(int maxTries) { if (retval >= 0) return true; } -#ifdef _WIN32 - Sleep(1); -#else - sleep(1); -#endif + sleep_ms(1); } // Let's not leak this socket. diff --git a/net/resolve.cpp b/net/resolve.cpp index 9677bec443..329c3d8c2f 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -1,5 +1,6 @@ #include "net/resolve.h" #include "base/logging.h" +#include "base/timeutil.h" #include #include @@ -98,11 +99,7 @@ bool DNSResolve(const std::string &host, const std::string &service, addrinfo ** int result = getaddrinfo(host.c_str(), servicep, &hints, res); if (result == EAI_AGAIN) { // Temporary failure. Since this already blocks, let's just try once more. -#ifdef _WIN32 - Sleep(1); -#else - sleep(1); -#endif + sleep_ms(1); result = getaddrinfo(host.c_str(), servicep, &hints, res); } From 28234ca4d2c77c6238deb0781991bcca3165d0ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 15 Jul 2014 16:52:29 +0200 Subject: [PATCH 1165/1445] Buildfix for non-PPSSPP projects --- base/PCMain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 12fe958206..17006a1910 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -776,7 +776,9 @@ int main(int argc, char *argv[]) { SimulateGamepad(keys, &input_state); input_state.pad_buttons = pad_buttons; UpdateInputState(&input_state, true); +#ifdef PPSSPP UpdateRunLoop(); +#endif if (g_QuitRequested) break; #if defined(PPSSPP) && !defined(MOBILE_DEVICE) From 06d70ee435bd000a1c8cb0c2b3b5b4917b92adfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 15 Jul 2014 17:00:57 +0200 Subject: [PATCH 1166/1445] When did these disappear? :/ --- base/PCMain.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 17006a1910..9aa39a4e43 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -778,6 +778,9 @@ int main(int argc, char *argv[]) { UpdateInputState(&input_state, true); #ifdef PPSSPP UpdateRunLoop(); +#else + NativeUpdate(input_state); + NativeRender(); #endif if (g_QuitRequested) break; From fb9f1c2d6a636ae13843ffeda44ce5c396226900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 15 Jul 2014 17:24:15 +0200 Subject: [PATCH 1167/1445] Fix native tools build on mac etc --- base/CMakeLists.txt | 3 ++- base/logging.h | 2 +- ext/libpng17/CMakeLists.txt | 26 ++++++++++++++++++++++++++ math/fast/fast_matrix.h | 4 ++-- tools/CMakeLists.txt | 10 ++++++---- tools/atlastool.cpp | 10 +++++++--- 6 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 ext/libpng17/CMakeLists.txt diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 62bf4979b2..54b0cd67f8 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -4,7 +4,8 @@ set(SRCS ../thread/threadutil.cpp error_context.cpp display.cpp - buffer.cpp) + buffer.cpp + backtrace.cpp) add_library(base STATIC ${SRCS}) diff --git a/base/logging.h b/base/logging.h index a70160fe68..c129f19d9d 100644 --- a/base/logging.h +++ b/base/logging.h @@ -116,7 +116,7 @@ void OutputDebugStringUTF8(const char *p); #undef CHECK -#define CHECK(a) {if (!(a)) {FLOG("CHECK failed");}} +#define CHECK(a) {if (!(a)) {FLOG("%i: CHECK failed on this line", __LINE__);}} #define CHECK_P(a, ...) {if (!(a)) {FLOG("CHECK failed: " __VA_ARGS__);}} #define CHECK_EQ(a, b) CHECK((a) == (b)); #define CHECK_NE(a, b) CHECK((a) != (b)); diff --git a/ext/libpng17/CMakeLists.txt b/ext/libpng17/CMakeLists.txt new file mode 100644 index 0000000000..d2829cd3fe --- /dev/null +++ b/ext/libpng17/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 2.6) + +add_library(png17 + pngconf.h + pngdebug.h + png.c + png.h + pngerror.c + pngget.c + pnginfo.h + pnglibconf.h + pngmem.c + pngpread.c + pngpriv.h + pngread.c + pngrio.c + pngrtran.c + pngrutil.c + pngset.c + pngstruct.h + pngtest.c + pngtrans.c + pngwio.c + pngwrite.c + pngwtran.c + pngwutil.c) diff --git a/math/fast/fast_matrix.h b/math/fast/fast_matrix.h index 52913f2747..69936c4913 100644 --- a/math/fast/fast_matrix.h +++ b/math/fast/fast_matrix.h @@ -13,7 +13,7 @@ extern void fast_matrix_mul_4x4_c(float *dest, const float *a, const float *b); extern void fast_matrix_mul_4x4_neon(float *dest, const float *a, const float *b); extern void fast_matrix_mul_4x4_sse(float *dest, const float *a, const float *b); -#if defined(_M_IX86) || defined(_M_X64) // Hard link to SSE implementations on x86 +#if 0 // defined(_M_IX86) || defined(_M_X64) // Hard link to SSE implementations on x86 #define fast_matrix_mul_4x4 fast_matrix_mul_4x4_sse #else extern fptr_fast_matrix_mul_4x4 fast_matrix_mul_4x4; @@ -22,4 +22,4 @@ extern fptr_fast_matrix_mul_4x4 fast_matrix_mul_4x4; #ifdef __cplusplus } // extern "C" -#endif \ No newline at end of file +#endif diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index ce97e07957..f828fbe2a0 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required(VERSION 2.6) project (Tools) -find_package(PNG REQUIRED) add_definitions(-O2) add_definitions(-Wall) @@ -25,12 +24,13 @@ endif() # add_definitions(-fstrict-aliasing) include_directories(..) +include_directories(../ext) include_directories(../math/lin) include_directories(../image) include_directories(../ext/libzip) include_directories(../ext/rg_etc1) +include_directories(../ext/glew) include_directories(/usr/local/include) -include_directories(${PNG_INCLUDE_DIR}) link_directories(/usr/X11R6/lib) link_directories(/opt/local/lib) @@ -39,6 +39,7 @@ link_directories(/opt/local/lib) include_directories(/usr/include/freetype2) include_directories(/usr/local/include/freetype2) include_directories(/opt/local/include/freetype2) +include_directories(/opt/local/include) add_subdirectory(../base base) add_subdirectory(../gfx gfx) @@ -49,10 +50,11 @@ add_subdirectory(../util util) add_subdirectory(../ext/libzip libzip) add_subdirectory(../ext/rg_etc1 rg_etc1) add_subdirectory(../ext/stb_image stb_image) +add_subdirectory(../ext/libpng17 png17) add_executable(atlastool atlastool.cpp) -target_link_libraries(atlastool ${PNG_LIBRARY} freetype util image z stb_image rg_etc1 file zip) +target_link_libraries(atlastool png17 freetype util image z stb_image rg_etc1 file zip base) add_executable(zimtool zimtool.cpp) -target_link_libraries(zimtool ${PNG_LIBRARY} freetype image z stb_image rg_etc1 file zip) +target_link_libraries(zimtool png17 freetype image z stb_image rg_etc1 file zip base) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 314d4f5fb8..c877065763 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -11,10 +11,10 @@ // line height // dist-per-pixel -#include +#include #include #include FT_FREETYPE_H -#include +#include #include #include #include @@ -22,6 +22,7 @@ #include #include +#include "base/logging.h" #include "gfx/texture_atlas.h" #include "image/png_load.h" @@ -774,7 +775,10 @@ int main(int argc, char **argv) { // initProgram(&argc, const_cast(&argv)); // /usr/share/fonts/truetype/msttcorefonts/Arial_Black.ttf // /usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-R.ttf - + if (argc < 3) { + FLOG("Not enough arguments"); + return 1; + } CHECK(argc >= 3); if (argc > 3) { From 8dc540d78d8fb383b1d149b20d1331edf03a73ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 15 Jul 2014 17:42:21 +0200 Subject: [PATCH 1168/1445] atlas scripts: allow comment lines (starting with #) --- tools/atlastool.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index c877065763..4102b44f72 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -42,8 +42,6 @@ #include "util/text/utf8.h" -#define CHECK(x) if (!(x)) { printf("%i: CHECK failed on this line\n", __LINE__); exit(1); } - using namespace std; static int global_id; static bool etc1 = false; @@ -812,6 +810,7 @@ int main(int argc, char **argv) { while (!feof(script)) { if (!fgets(line, 511, script)) break; if (!strlen(line)) break; + if (line[0] == '#') continue; char *rest = strchr(line, ' '); if (rest) { *rest = 0; From b532ab8f15be72b091625336ee52674efcc38c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 15 Jul 2014 18:45:26 +0200 Subject: [PATCH 1169/1445] Oops --- math/fast/fast_matrix.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/math/fast/fast_matrix.h b/math/fast/fast_matrix.h index 69936c4913..968739ba0b 100644 --- a/math/fast/fast_matrix.h +++ b/math/fast/fast_matrix.h @@ -13,7 +13,7 @@ extern void fast_matrix_mul_4x4_c(float *dest, const float *a, const float *b); extern void fast_matrix_mul_4x4_neon(float *dest, const float *a, const float *b); extern void fast_matrix_mul_4x4_sse(float *dest, const float *a, const float *b); -#if 0 // defined(_M_IX86) || defined(_M_X64) // Hard link to SSE implementations on x86 +#if defined(_M_IX86) || defined(_M_X64) // Hard link to SSE implementations on x86 #define fast_matrix_mul_4x4 fast_matrix_mul_4x4_sse #else extern fptr_fast_matrix_mul_4x4 fast_matrix_mul_4x4; From 7dfdecca10de1ed27ae3ff716dddc3037f9bc875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 15 Jul 2014 19:45:22 +0200 Subject: [PATCH 1170/1445] Forgot to reverse this when semantics of the 4x4 mul changed. (this wasn't used in PPSSPP) --- math/lin/matrix4x4.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp index 7234c4fb93..318655cdcc 100644 --- a/math/lin/matrix4x4.cpp +++ b/math/lin/matrix4x4.cpp @@ -39,6 +39,7 @@ Matrix4x4 Matrix4x4::simpleInverse() const { return out; } + Matrix4x4 Matrix4x4::transpose() const { Matrix4x4 out; @@ -52,7 +53,7 @@ Matrix4x4 Matrix4x4::transpose() const Matrix4x4 Matrix4x4::operator * (const Matrix4x4 &other) const { Matrix4x4 temp; - fast_matrix_mul_4x4(temp.m, this->m, other.m); + fast_matrix_mul_4x4(temp.m, other.m, this->m); return temp; } From 2481cfed5bf182a478da5b40da40b55f506553dc Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 16 Jul 2014 23:50:49 +1000 Subject: [PATCH 1171/1445] Add Symbian 'RunFast' path to math_util with the rest. Enable FZ for all Qt ARM devices (I think Qt enables it by default but lets do it just in case). Enable FZ for armv6 devices too (they only require VFPv2). Add comments for why we don't use it on Blackberry. --- base/QtMain.cpp | 5 ++--- math/math_util.cpp | 12 ++++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 699f84efb4..239ffad0e9 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -18,7 +18,6 @@ #endif #ifdef __SYMBIAN32__ -#include #include #include #include "SymbianMediaKeys.h" @@ -28,6 +27,7 @@ #include "SDL_audio.h" #endif #include "QtMain.h" +#include "math/math_util.h" #include @@ -119,9 +119,8 @@ static int mainInternal(QApplication &a) emugl->resize(pixel_xres, pixel_yres); emugl->showFullScreen(); #endif + EnableFZ(); #ifdef __SYMBIAN32__ - // Set RunFast hardware mode for VFPv2. - User::SetFloatingPointMode(EFpModeRunFast); // Disable screensaver QScopedPointer ssObject(new QSystemScreenSaver(emugl)); ssObject->setScreenSaverInhibit(); diff --git a/math/math_util.cpp b/math/math_util.cpp index 4c3e0f0f02..b7f541ab39 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -1,8 +1,12 @@ #include "math/math_util.h" #include +#ifdef __SYMBIAN32__ +#include +#endif -#if defined(__ARM_ARCH_7A__) && !defined(BLACKBERRY) - +// QNX can only use RunFast mode and it is already the default. +#if defined(ARM) && !defined(BLACKBERRY) && !defined(__SYMBIAN32__) +// Enables 'RunFast' VFP mode. void EnableFZ() { int x; asm( @@ -35,6 +39,10 @@ void FPU_SetFastMode() { #else void EnableFZ() { +#ifdef __SYMBIAN32__ + // Set RunFast hardware mode for Symbian VFPv2. + User::SetFloatingPointMode(EFpModeRunFast); +#endif // TODO } From d1cccf2c26193740c7ce6836dab3afc7a6a5a118 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 17 Jul 2014 00:48:47 +1000 Subject: [PATCH 1172/1445] Fix some compiler warnings. --- file/chunk_file.cpp | 6 +++--- image/png_load.cpp | 4 ++-- math/fast/fast_math.c | 6 +++--- ui/ui_screen.cpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index 4dd58dd8f7..914864653b 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -225,8 +225,8 @@ void ChunkFile::writeWString(const std::string &str) { unsigned short *text; int len = (int)str.length(); text = new unsigned short[len+1]; - for (size_t i=0; i 255 ? ' ' : src[i]; } return str; diff --git a/image/png_load.cpp b/image/png_load.cpp index d48691bfc6..145d084ce3 100644 --- a/image/png_load.cpp +++ b/image/png_load.cpp @@ -30,7 +30,7 @@ int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_d uint32_t *src = (uint32_t*) image.bits(); uint32_t *dest = (uint32_t*) *image_data_ptr; // Qt4 does not support RGBA - for (size_t sz = 0; sz < image.byteCount(); sz+=4, ++src, ++dest) { + for (size_t sz = 0; sz < (size_t)image.byteCount(); sz+=4, ++src, ++dest) { const uint32_t v = *src; *dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // ARGB -> RGBA } @@ -77,7 +77,7 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in uint32_t *src = (uint32_t*) image.bits(); uint32_t *dest = (uint32_t*) *image_data_ptr; // Qt4 does not support RGBA - for (size_t sz = 0; sz < image.byteCount(); sz+=4, ++src, ++dest) { + for (size_t sz = 0; sz < (size_t)image.byteCount(); sz+=4, ++src, ++dest) { const uint32_t v = *src; *dest = (v & 0xFF00FF00) | ((v & 0xFF) << 16) | (( v >> 16 ) & 0xFF); // convert it! } diff --git a/math/fast/fast_math.c b/math/fast/fast_math.c index ad68673703..67506a1823 100644 --- a/math/fast/fast_math.c +++ b/math/fast/fast_math.c @@ -3,10 +3,10 @@ #include "fast_matrix.h" void InitFastMath(int enableNEON) { -// Every architecture has its own define. This needs to be added to. -#if defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7S__) + // Every architecture has its own define. This needs to be added to. if (enableNEON) { +#if defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7S__) fast_matrix_mul_4x4 = &fast_matrix_mul_4x4_neon; - } #endif + } } diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 535d1e9018..7589e5ecf5 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -272,7 +272,7 @@ void PopupMultiChoice::Draw(UIContext &dc) { } PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams) - : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager), step_(1) { + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(1), screenManager_(screenManager) { OnClick.Handle(this, &PopupSliderChoice::HandleClick); } From 49e8414fec1e371c30d901916a2c014cd5316d1a Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 17 Jul 2014 02:29:49 +1000 Subject: [PATCH 1173/1445] Oops. fmrx is only for armv7. --- math/math_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/math/math_util.cpp b/math/math_util.cpp index b7f541ab39..eb50c58426 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -5,7 +5,7 @@ #endif // QNX can only use RunFast mode and it is already the default. -#if defined(ARM) && !defined(BLACKBERRY) && !defined(__SYMBIAN32__) +#if defined(__ARM_ARCH_7A__) && !defined(BLACKBERRY) && !defined(__SYMBIAN32__) // Enables 'RunFast' VFP mode. void EnableFZ() { int x; From 76cb31cdd5e0ef7b65819943c9f667810600fe6f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 18 Jul 2014 11:03:18 +0200 Subject: [PATCH 1174/1445] nativeui: Add basic TextEdit control, and popupchoice --- ui/ui_screen.cpp | 48 +++++++++++++++++++++++++++ ui/ui_screen.h | 34 ++++++++++++++++++++ ui/view.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ ui/view.h | 21 ++++++++++-- 4 files changed, 185 insertions(+), 2 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 7589e5ecf5..e1c8f2d481 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -388,4 +388,52 @@ void SliderFloatPopupScreen::OnCompleted(DialogResult result) { } } +PopupTextInputChoice::PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, ScreenManager *screenManager, LayoutParams *layoutParams) +: Choice(title, "", false, layoutParams), value_(value), placeHolder_(placeholder), screenManager_(screenManager) { + OnClick.Handle(this, &PopupTextInputChoice::HandleClick); +} + +EventReturn PopupTextInputChoice::HandleClick(EventParams &e) { + TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, text_); + popupScreen->OnChange.Handle(this, &PopupTextInputChoice::HandleChange); + screenManager_->push(popupScreen); + return EVENT_DONE; +} + +void PopupTextInputChoice::Draw(UIContext &dc) { + Style style = dc.theme->itemStyle; + if (!IsEnabled()) { + style = dc.theme->itemDisabledStyle; + } + Choice::Draw(dc); + dc.SetFontStyle(dc.theme->uiFont); + dc.DrawText(value_->c_str(), bounds_.x2() - 12, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); +} + +EventReturn PopupTextInputChoice::HandleChange(EventParams &e) { + e.v = this; + OnChange.Trigger(e); + return EVENT_DONE; +} + +void TextEditPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { + using namespace UI; + + textEditValue_ = *value_; + LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams((UI::Size)300, WRAP_CONTENT))); + edit_ = new TextEdit(textEditValue_, placeholder_, new LinearLayoutParams(1.0f)); + lin->Add(edit_); + + UI::SetFocusedView(edit_); +} + +void TextEditPopupScreen::OnCompleted(DialogResult result) { + if (result == DR_OK) { + *value_ = edit_->GetText(); + EventParams e; + e.v = edit_; + OnChange.Trigger(e); + } +} + } // namespace UI diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 6ff656c105..071c3f2326 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -160,6 +160,23 @@ private: float maxValue_; }; +class TextEditPopupScreen : public PopupScreen { +public: + TextEditPopupScreen(std::string *value, std::string &placeholder, const std::string &title) + : PopupScreen(title, "OK", "Cancel"), value_(value), placeholder_(placeholder) {} + void CreatePopupContents(ViewGroup *parent); + + Event OnChange; + +private: + virtual void OnCompleted(DialogResult result) override; + TextEdit *edit_; + std::string *value_; + std::string textEditValue_; + std::string placeholder_; + int step_; +}; + // Reads and writes value to determine the current selection. class PopupMultiChoice : public UI::Choice { public: @@ -230,4 +247,21 @@ private: ScreenManager *screenManager_; }; +class PopupTextInputChoice: public Choice { +public: + PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, ScreenManager *screenManager, LayoutParams *layoutParams = 0); + + void Draw(UIContext &dc); + + Event OnChange; + +private: + EventReturn HandleClick(EventParams &e); + EventReturn HandleChange(EventParams &e); + ScreenManager *screenManager_; + std::string *value_; + std::string placeHolder_; + std::string defaultText_; +}; + } // namespace UI diff --git a/ui/view.cpp b/ui/view.cpp index feb59e55e7..bad5f5c367 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -7,6 +7,7 @@ #include "gfx_es2/draw_buffer.h" #include "gfx/texture.h" #include "gfx/texture_atlas.h" +#include "util/text/utf8.h" #include "ui/ui.h" #include "ui/view.h" #include "ui/ui_context.h" @@ -572,6 +573,89 @@ void TextView::Draw(UIContext &dc) { dc.DrawTextRect(text_.c_str(), bounds_, 0xFFFFFFFF, textAlign_); } +TextEdit::TextEdit(const std::string &text, const std::string &placeholderText, LayoutParams *layoutParams) + : View(layoutParams), text_(text), placeholderText_(placeholderText) { + caret_ = (int)text_.size(); +} + +void TextEdit::Draw(UIContext &dc) { + dc.SetFontStyle(dc.theme->uiFont); + dc.FillRect(UI::Drawable(0x80000000), bounds_); + if (text_.empty()) { + if (placeholderText_.size()) { + dc.DrawTextRect(placeholderText_.c_str(), bounds_, 0x50FFFFFF, ALIGN_CENTER); + } + } else { + dc.DrawTextRect(text_.c_str(), bounds_, 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_LEFT); + } + // Hack to find the caret position. Might want to find a better way... + + std::string subset = text_.substr(0, caret_); + float w, h; + dc.MeasureText(dc.theme->uiFont, subset.c_str(), &w, &h, ALIGN_VCENTER | ALIGN_LEFT); + float caretX = bounds_.x + w; + dc.FillRect(UI::Drawable(0xFFFFFFFF), Bounds(caretX - 1, bounds_.y + 2, 3, bounds_.h - 4)); +} + +void TextEdit::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + dc.MeasureText(dc.theme->uiFont, text_.size() ? text_.c_str() : "Wj", &w, &h); + w += 2; + h += 2; +} + +void TextEdit::Key(const KeyInput &input) { + // Process navigation keys. These aren't chars. + if (input.flags & KEY_DOWN) { + switch (input.keyCode) { + case NKCODE_DPAD_LEFT: // ASCII left arrow + caret_--; + break; + case NKCODE_DPAD_RIGHT: // ASCII right arrow + caret_++; + break; + case NKCODE_MOVE_HOME: + case NKCODE_PAGE_UP: + caret_ = 0; + break; + case NKCODE_MOVE_END: + case NKCODE_PAGE_DOWN: + caret_ = (int)text_.size(); + break; + case NKCODE_FORWARD_DEL: + if (caret_ < text_.size()) { + text_.erase(text_.begin() + caret_, text_.begin() + caret_ + 1); + } + case NKCODE_DEL: + if (caret_ > 0) { + text_.erase(text_.begin() + caret_ - 1, text_.begin() + caret_); + caret_--; + } + break; + } + + if (caret_ < 0) { + caret_ = 0; + } + if (caret_ > (int)text_.size()) { + caret_ = (int)text_.size(); + } + } + + // Process chars. + if (input.flags & KEY_CHAR) { + int unichar = input.keyCode; + if (unichar >= 0x20) { // Ignore control characters. + // Insert it! (todo: do it with a string insert) + char buf[8]; + buf[u8_wc_toutf8(buf, unichar)] = '\0'; + for (int i = 0; i < strlen(buf); i++) { + text_.insert(text_.begin() + caret_, buf[i]); + caret_++; + } + } + } +} + void ProgressBar::GetContentDimensions(const UIContext &dc, float &w, float &h) const { dc.MeasureText(dc.theme->uiFont, " 100% ", &w, &h); } diff --git a/ui/view.h b/ui/view.h index 87d1ac83a3..9bb8522f9b 100644 --- a/ui/view.h +++ b/ui/view.h @@ -654,8 +654,8 @@ public: TextView(const std::string &text, int textAlign, bool small, LayoutParams *layoutParams = 0) : InertView(layoutParams), text_(text), textAlign_(textAlign), small_(small) {} - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; - virtual void Draw(UIContext &dc); + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + virtual void Draw(UIContext &dc) override; void SetText(const std::string &text) { text_ = text; } void SetSmall(bool small) { small_ = small; } private: @@ -664,6 +664,23 @@ private: bool small_; }; +class TextEdit : public View { +public: + TextEdit(const std::string &text, const std::string &placeholderText, LayoutParams *layoutParams = 0); + void SetText(const std::string &text) { text_ = text; caret_ = (int)text_.size(); } + const std::string &GetText() const { return text_; } + + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + virtual void Draw(UIContext &dc) override; + virtual void Key(const KeyInput &input) override; + +private: + std::string text_; + std::string placeholderText_; + int caret_; + // TODO: Selections +}; + enum ImageSizeMode { IS_DEFAULT, }; From 8cd755942b0b8ab5f69dbc54c97a0aa7eef81d5d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 18 Jul 2014 12:07:08 +0200 Subject: [PATCH 1175/1445] Reduce some logging --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 6 ++---- file/zip_read.cpp | 2 +- gfx/texture.cpp | 3 --- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 5503d4c55d..1489b15a46 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -272,7 +272,6 @@ public class NativeActivity extends Activity { Log.e(TAG, "Invalid rotation: " + rotString); return; } - Log.i(TAG, "Rotation requested: " + rot); switch (rot) { case 0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); @@ -296,7 +295,6 @@ public class NativeActivity extends Activity { @TargetApi(14) private void updateSystemUiVisibility() { String immersive = NativeApp.queryConfig("immersiveMode"); - Log.i(TAG, "Immersive: " + immersive); boolean useImmersive = immersive.equals("1") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; int flags = 0; @@ -599,7 +597,7 @@ public class NativeActivity extends Activity { } return super.onGenericMotionEvent(event); } - + @SuppressLint("NewApi") @Override public boolean onKeyDown(int keyCode, KeyEvent event) { @@ -838,4 +836,4 @@ public class NativeActivity extends Activity { } return false; } -} +} \ No newline at end of file diff --git a/file/zip_read.cpp b/file/zip_read.cpp index bcd3bc0a27..1999bbdde0 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -329,7 +329,7 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { - ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); + // ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); if (data) return data; diff --git a/gfx/texture.cpp b/gfx/texture.cpp index a29acf89d3..f4eab57b7a 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -280,7 +280,6 @@ bool Texture::LoadZIM(const char *filename) { int flags; int num_levels = ::LoadZIM(filename, &width[0], &height[0], &flags, &image_data[0]); - ILOG("ZIM loaded: %i levels", num_levels); if (!num_levels) return false; if (num_levels >= ZIM_MAX_MIP_LEVELS) @@ -310,8 +309,6 @@ bool Texture::LoadZIM(const char *filename) { GL_CHECK(); - - ILOG("Gen-binding texture"); glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); SetTextureParameters(flags); From 31f7ad574a9610457baa015d7f4c37b87fa8e014 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 18 Jul 2014 12:22:33 +0200 Subject: [PATCH 1176/1445] Add focus management to textedit. Close popups (with OnOK) on Enter. --- ui/ui_screen.cpp | 20 +++++++++++++++++--- ui/ui_screen.h | 2 ++ ui/view.cpp | 4 +++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index e1c8f2d481..4730353b5b 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -129,7 +129,7 @@ UI::EventReturn UIScreen::OnCancel(UI::EventParams &e) { } PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2) - : box_(0), title_(title) { + : box_(0), title_(title), defaultButton_(NULL) { I18NCategory *d = GetI18NCategory("Dialog"); if (!button1.empty()) button1_ = d->T(button1.c_str()); @@ -148,6 +148,18 @@ bool PopupScreen::touch(const TouchInput &touch) { return UIDialogScreen::touch(touch); } +bool PopupScreen::key(const KeyInput &key) { + if (key.flags & KEY_DOWN) { + if (key.keyCode == NKCODE_ENTER) { + UI::EventParams e; + defaultButton_->OnClick.Trigger(e); + return true; + } + } + + return UIDialogScreen::key(key); +} + void PopupScreen::CreateViews() { using namespace UI; @@ -178,13 +190,15 @@ void PopupScreen::CreateViews() { // Adjust button order to the platform default. #if defined(_WIN32) - buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle(this, &PopupScreen::OnOK); + defaultButton_ = buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f, buttonMargins))); + defaultButton_->OnClick.Handle(this, &PopupScreen::OnOK); if (!button2_.empty()) buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle(this, &PopupScreen::OnCancel); #else if (!button2_.empty()) buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel); - buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK); + defaultButton_ = buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f))); + defaultButton_->OnClick.Handle(this, &PopupScreen::OnOK); #endif box_->Add(buttonRow); diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 071c3f2326..95af3041d7 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -55,6 +55,7 @@ public: virtual void CreateViews() override; virtual bool isTransparent() const override { return true; } virtual bool touch(const TouchInput &touch) override; + virtual bool key(const KeyInput &key) override; protected: virtual bool FillVertical() const { return false; } @@ -66,6 +67,7 @@ private: UI::EventReturn OnCancel(UI::EventParams &e); UI::ViewGroup *box_; + UI::Button *defaultButton_; std::string title_; std::string button1_; std::string button2_; diff --git a/ui/view.cpp b/ui/view.cpp index bad5f5c367..cfaec627e8 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -580,7 +580,7 @@ TextEdit::TextEdit(const std::string &text, const std::string &placeholderText, void TextEdit::Draw(UIContext &dc) { dc.SetFontStyle(dc.theme->uiFont); - dc.FillRect(UI::Drawable(0x80000000), bounds_); + dc.FillRect(HasFocus() ? UI::Drawable(0x80000000) : UI::Drawable(0x30000000), bounds_); if (text_.empty()) { if (placeholderText_.size()) { dc.DrawTextRect(placeholderText_.c_str(), bounds_, 0x50FFFFFF, ALIGN_CENTER); @@ -604,6 +604,8 @@ void TextEdit::GetContentDimensions(const UIContext &dc, float &w, float &h) con } void TextEdit::Key(const KeyInput &input) { + if (!HasFocus()) + return; // Process navigation keys. These aren't chars. if (input.flags & KEY_DOWN) { switch (input.keyCode) { From 3b45ca1d2fc1f2f97226e60d02b300b5485765a4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 18 Jul 2014 16:07:36 +0200 Subject: [PATCH 1177/1445] Some cleanup --- android/app-android.cpp | 10 +--- android/native-audio-so.cpp | 2 - .../henrikrydgard/libnative/Installation.java | 46 +++++++++++++++++++ .../libnative/NativeActivity.java | 41 ++--------------- .../libnative/NativeRenderer.java | 7 ++- 5 files changed, 59 insertions(+), 47 deletions(-) create mode 100644 android/src/com/henrikrydgard/libnative/Installation.java diff --git a/android/app-android.cpp b/android/app-android.cpp index 258fa7340d..63266f6f95 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -44,8 +44,6 @@ std::queue frameCommands; std::string systemName; std::string langRegion; -const bool extraLog = true; - static float left_joystick_x_async; static float left_joystick_y_async; static float right_joystick_x_async; @@ -134,13 +132,9 @@ extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isLandscape(JNIEn return landscape; } -// For the Back button to work right. +// Allow the app to intercept the back button. extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isAtTopLevel(JNIEnv *env, jclass) { - bool isAtTop = NativeIsAtTopLevel(); - if (extraLog) { - ILOG("isAtTopLevel %i", (int)isAtTop); - } - return isAtTop; + return NativeIsAtTopLevel(); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioConfig diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 53fa40273c..998080d8f1 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -1,8 +1,6 @@ // Minimal audio streaming using OpenSL. // // Loosely based on the Android NDK sample code. -// Hardcoded to 44.1kHz stereo 16-bit audio, because as far as I'm concerned, -// that's the only format that makes any sense. #include #include diff --git a/android/src/com/henrikrydgard/libnative/Installation.java b/android/src/com/henrikrydgard/libnative/Installation.java new file mode 100644 index 0000000000..dffa7cc441 --- /dev/null +++ b/android/src/com/henrikrydgard/libnative/Installation.java @@ -0,0 +1,46 @@ +package com.henrikrydgard.libnative; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.UUID; + +import android.content.Context; + + +public class Installation { + private static String sID = null; + private static final String INSTALLATION = "INSTALLATION"; + + public synchronized static String id(Context context) { + if (sID == null) { + File installation = new File(context.getFilesDir(), INSTALLATION); + try { + if (!installation.exists()) + writeInstallationFile(installation); + sID = readInstallationFile(installation); + } catch (Exception e) { + // We can't even open a file for writing? Then we can't get a unique-ish installation id. + return "BROKENAPPUSERFILESYSTEM"; + } + } + return sID; + } + + private static String readInstallationFile(File installation) throws IOException { + RandomAccessFile f = new RandomAccessFile(installation, "r"); + byte[] bytes = new byte[(int) f.length()]; + f.readFully(bytes); + f.close(); + return new String(bytes); + } + + private static void writeInstallationFile(File installation) throws IOException { + FileOutputStream out = new FileOutputStream(installation); + String id = UUID.randomUUID().toString(); + out.write(id.getBytes()); + out.close(); + } +} + \ No newline at end of file diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 1489b15a46..b08ac3d726 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -51,41 +51,6 @@ import android.widget.EditText; import android.widget.FrameLayout; import android.widget.Toast; -class Installation { - private static String sID = null; - private static final String INSTALLATION = "INSTALLATION"; - - public synchronized static String id(Context context) { - if (sID == null) { - File installation = new File(context.getFilesDir(), INSTALLATION); - try { - if (!installation.exists()) - writeInstallationFile(installation); - sID = readInstallationFile(installation); - } catch (Exception e) { - // We can't even open a file for writing? Then we can't get a unique-ish installation id. - return "BROKENAPPUSERFILESYSTEM"; - } - } - return sID; - } - - private static String readInstallationFile(File installation) throws IOException { - RandomAccessFile f = new RandomAccessFile(installation, "r"); - byte[] bytes = new byte[(int) f.length()]; - f.readFully(bytes); - f.close(); - return new String(bytes); - } - - private static void writeInstallationFile(File installation) throws IOException { - FileOutputStream out = new FileOutputStream(installation); - String id = UUID.randomUUID().toString(); - out.write(id.getBytes()); - out.close(); - } -} - public class NativeActivity extends Activity { // Remember to loadLibrary your JNI .so in a static {} block @@ -135,6 +100,10 @@ public class NativeActivity extends Activity { private void detectOptimalAudioSettings() { try { optimalFramesPerBuffer = Integer.parseInt(this.audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); + } catch (NumberFormatException e) { + // Ignore, if we can't parse it it's bogus and zero is a fine value (means we couldn't detect it). + } + try { optimalSampleRate = Integer.parseInt(this.audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)); } catch (NumberFormatException e) { // Ignore, if we can't parse it it's bogus and zero is a fine value (means we couldn't detect it). @@ -159,7 +128,7 @@ public class NativeActivity extends Activity { return libdir; } - @TargetApi(13) + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) void GetScreenSizeHC(Point size) { WindowManager w = getWindowManager(); w.getDefaultDisplay().getSize(size); diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index 4856fdd09c..85e857f53e 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -21,8 +21,10 @@ public class NativeRenderer implements GLSurfaceView.Renderer { isDark = d; } + @Override public void onDrawFrame(GL10 unused /*use GLES20*/) { if (isDark) { + GLES20.glDisable(GLES20.GL_SCISSOR_TEST); GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT); } else { @@ -30,17 +32,20 @@ public class NativeRenderer implements GLSurfaceView.Renderer { } } + @Override public void onSurfaceCreated(GL10 unused, EGLConfig config) { // Log.i(TAG, "onSurfaceCreated - EGL context is new or was lost"); // Actually, it seems that it is here we should recreate lost GL objects. displayInit(); } + @Override public void onSurfaceChanged(GL10 unused, int width, int height) { Log.i(TAG, "onSurfaceChanged"); displayResize(width, height); } - + + // Not override, it's custom. public void onDestroyed() { displayShutdown(); } From 326504baf8ef2d5e9310904fc6f37b9b0cdccd2e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 18 Jul 2014 17:39:32 +0200 Subject: [PATCH 1178/1445] android: Cleanup of dpi/refresh variables --- android/app-android.cpp | 35 +++++++------------ .../libnative/NativeActivity.java | 14 ++------ .../henrikrydgard/libnative/NativeApp.java | 2 +- .../libnative/NativeRenderer.java | 21 ++++++++--- base/NativeApp.h | 3 +- base/display.cpp | 1 + base/display.h | 3 +- 7 files changed, 36 insertions(+), 43 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 63266f6f95..7837d43b46 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -152,7 +152,7 @@ extern "C" jstring Java_com_henrikrydgard_libnative_NativeApp_queryConfig } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init - (JNIEnv *env, jclass, jint dpi, jstring jdevicetype, jstring jlangRegion, jstring japkpath, + (JNIEnv *env, jclass, jstring jdevicetype, jstring jlangRegion, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jshortcutParam, jstring jinstallID, jboolean juseNativeAudio) { jniEnvUI = env; @@ -193,10 +193,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init net::Init(); - g_dpi = dpi; - g_dpi_scale = 240.0f / (float)g_dpi; - ILOG("DPI detected: %i %f", dpi, g_dpi_scale); - NativeGetAppInfo(&app_name, &app_nice_name, &landscape); @@ -262,39 +258,32 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jc static jmethodID postCommand; extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayInit(JNIEnv * env, jobject obj) { - ILOG("NativeApp.displayInit(pixel_xres = %i, pixel_yres = %i)", pixel_xres, pixel_yres); + ILOG("NativeApp.displayInit()"); if (!renderer_inited) { - // We default to 240 dpi and all UI code is written to assume it. (DENSITY_HIGH, like Nexus S). - // Note that we don't compute dp_xscale and dp_yscale until later! This is so that NativeGetAppInfo - // can change the dp resolution if it feels like it. - dp_xres = pixel_xres * g_dpi_scale; - dp_yres = pixel_yres * g_dpi_scale; - NativeInitGraphics(); - ILOG("NativeInitGraphics() completed: dpi = %i, dp_xres = %i, dp_yres = %i", g_dpi, dp_xres, dp_yres); - - dp_xscale = (float)dp_xres / pixel_xres; - dp_yscale = (float)dp_yres / pixel_yres; renderer_inited = true; } else { - NativeDeviceLost(); - ILOG("NativeDeviceLost completed."); + NativeDeviceLost(); // ??? + ILOG("displayInit: NativeDeviceLost completed."); } + DLOG("(Re)-fetching method ID to postCommand..."); - jclass cls = env->GetObjectClass(obj); - postCommand = env->GetMethodID(cls, "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); + postCommand = env->GetMethodID(env->GetObjectClass(obj), "postCommand", "(Ljava/lang/String;Ljava/lang/String;)V"); } -extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h) { - ILOG("NativeApp.displayResize(%i, %i)", w, h); +extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JNIEnv *, jobject clazz, jint w, jint h, jint dpi, jfloat refreshRate) { + ILOG("NativeApp.displayResize(%i x %i, dpi=%i, refresh=%0.2f)", w, h, dpi, refreshRate); + + g_dpi = dpi; + g_dpi_scale = 240.0f / (float)g_dpi; - // TODO: Move some of the logic from displayInit here? pixel_xres = w; pixel_yres = h; dp_xres = pixel_xres * g_dpi_scale; dp_yres = pixel_yres * g_dpi_scale; dp_xscale = (float)dp_xres / pixel_xres; dp_yscale = (float)dp_yres / pixel_yres; + display_hz = refreshRate; NativeResized(); } diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index b08ac3d726..aded02d330 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -185,32 +185,23 @@ public class NativeActivity extends Activity { String libraryDir = getApplicationLibraryDir(appInfo); File sdcard = Environment.getExternalStorageDirectory(); - Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); @SuppressWarnings("deprecation") - float scrRefreshRate = display.getRefreshRate(); String externalStorageDir = sdcard.getAbsolutePath(); String dataDir = this.getFilesDir().getAbsolutePath(); String apkFilePath = appInfo.sourceDir; - DisplayMetrics metrics = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(metrics); - - int dpi = metrics.densityDpi; String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(dpi, deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL()); + NativeApp.init(deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL()); // OK, config should be initialized, we can query for screen rotation. if (Build.VERSION.SDK_INT >= 9) { updateScreenRotation(); } - Log.i(TAG, "Device: " + deviceType); - Log.i(TAG, " rate: " + scrRefreshRate + " dpi: " + dpi); - // Detect OpenGL support. // We don't currently use this detection for anything but good to have in the log. if (!detectOpenGLES20()) { @@ -272,7 +263,6 @@ public class NativeActivity extends Activity { } if (useImmersive) { flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - Log.i(TAG, "Setting immersive mode"); } if (getWindow().getDecorView() != null) { getWindow().getDecorView().setSystemUiVisibility(flags); @@ -315,6 +305,7 @@ public class NativeActivity extends Activity { NativeApp.audioInit(); mGLSurfaceView = new NativeGLView(this); + nativeRenderer = new NativeRenderer(this); mGLSurfaceView.setEGLContextClientVersion(2); @@ -339,7 +330,6 @@ public class NativeActivity extends Activity { mGLSurfaceView.setEGLConfigChooser(new NativeEGLConfigChooser()); } - nativeRenderer = new NativeRenderer(this); mGLSurfaceView.setRenderer(nativeRenderer); setContentView(mGLSurfaceView); diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index b435fdbce1..97da039e5b 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -6,7 +6,7 @@ public class NativeApp { public final static int DEVICE_ID_MOUSE = 2; public final static int DEVICE_ID_PAD_0 = 10; - public static native void init(int dpi, String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, boolean useOpenSL); + public static native void init(String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, boolean useOpenSL); public static native void audioInit(); public static native void audioShutdown(); diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index 85e857f53e..88d5df2ec7 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -3,18 +3,31 @@ package com.henrikrydgard.libnative; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; +import android.content.Context; import android.opengl.GLES20; import android.opengl.GLSurfaceView; +import android.util.DisplayMetrics; import android.util.Log; - +import android.view.Display; public class NativeRenderer implements GLSurfaceView.Renderer { private static String TAG = "NativeRenderer"; - NativeActivity mActivity; + private NativeActivity mActivity; private boolean isDark = false; + private int dpi; + private float refreshRate; NativeRenderer(NativeActivity act) { mActivity = act; + + DisplayMetrics metrics = new DisplayMetrics(); + Display display = act.getWindowManager().getDefaultDisplay(); + display.getMetrics(metrics); + dpi = metrics.densityDpi; + refreshRate = display.getRefreshRate(); + + // Log.i(TAG, "Display name: " + display.getName()); + Log.i(TAG, " rate: " + refreshRate + " dpi: " + dpi); } public void setDark(boolean d) { @@ -42,7 +55,7 @@ public class NativeRenderer implements GLSurfaceView.Renderer { @Override public void onSurfaceChanged(GL10 unused, int width, int height) { Log.i(TAG, "onSurfaceChanged"); - displayResize(width, height); + displayResize(width, height, dpi, refreshRate); } // Not override, it's custom. @@ -55,7 +68,7 @@ public class NativeRenderer implements GLSurfaceView.Renderer { // Note: This also means "device lost" and you should reload // all buffered objects. public native void displayInit(); - public native void displayResize(int w, int h); + public native void displayResize(int w, int h, int dpi, float refreshRate); public native void displayRender(); public native void displayShutdown(); diff --git a/base/NativeApp.h b/base/NativeApp.h index cf3815a0bf..ec1e6c6233 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -16,8 +16,6 @@ struct AxisInput; // The first function to get called, just write strings to the two pointers. // This might get called multiple times in some implementations, you must be able to handle that. -// The detected DP dimensions of the screen are set as dp_xres and dp_yres and you're free to change -// them if you have a fixed-size app that needs to stretch a little to fit. void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape); // Generic host->C++ messaging, used for functionality like system-native popup input boxes. @@ -38,6 +36,7 @@ bool NativeIsAtTopLevel(); void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *external_directory, const char *installID); // Runs after NativeInit() at some point. May (and probably should) call OpenGL. +// Should not initialize anything screen-size-dependent - do that in NativeResized. void NativeInitGraphics(); // Signals that you need to destroy and recreate all buffered OpenGL resources, diff --git a/base/display.cpp b/base/display.cpp index 89a78fef05..b072e1d547 100644 --- a/base/display.cpp +++ b/base/display.cpp @@ -9,3 +9,4 @@ int pixel_yres; int g_dpi = 1; // will be overwritten float g_dpi_scale = 1.0f; float pixel_in_dps = 1.0f; +float display_hz = 60.0f; \ No newline at end of file diff --git a/base/display.h b/base/display.h index 761af3b55b..930fef955a 100644 --- a/base/display.h +++ b/base/display.h @@ -10,4 +10,5 @@ extern int pixel_yres; extern int g_dpi; extern float g_dpi_scale; -extern float pixel_in_dps; \ No newline at end of file +extern float pixel_in_dps; +extern float display_hz; \ No newline at end of file From 1012f46dee3473376eff2a549c64a7f2356461b0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 18 Jul 2014 20:31:29 +0200 Subject: [PATCH 1179/1445] Add some infrastructure to be able to support Android hardware scaling --- .../libnative/NativeActivity.java | 66 ++++++++++++++----- .../henrikrydgard/libnative/NativeApp.java | 3 + .../henrikrydgard/libnative/NativeGLView.java | 6 +- .../libnative/NativeRenderer.java | 36 ++++++++-- 4 files changed, 89 insertions(+), 22 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index aded02d330..2f02070afa 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -96,6 +96,10 @@ public class NativeActivity extends Activity { return true; } + NativeRenderer getRenderer() { + return nativeRenderer; + } + @TargetApi(17) private void detectOptimalAudioSettings() { try { @@ -128,16 +132,29 @@ public class NativeActivity extends Activity { return libdir; } - @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) - void GetScreenSizeHC(Point size) { + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) + void GetScreenSizeJB(Point size, boolean real) { WindowManager w = getWindowManager(); - w.getDefaultDisplay().getSize(size); + if (real) { + w.getDefaultDisplay().getRealSize(size); + } + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) + void GetScreenSizeHC(Point size, boolean real) { + WindowManager w = getWindowManager(); + if (real && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + GetScreenSizeJB(size, real); + } else { + w.getDefaultDisplay().getSize(size); + } } @SuppressWarnings("deprecation") - void GetScreenSize(Point size) { + public void GetScreenSize(Point size) { + boolean real = useImmersive(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { - GetScreenSizeHC(size); + GetScreenSizeHC(size, real); } else { WindowManager w = getWindowManager(); Display d = w.getDefaultDisplay(); @@ -185,7 +202,6 @@ public class NativeActivity extends Activity { String libraryDir = getApplicationLibraryDir(appInfo); File sdcard = Environment.getExternalStorageDirectory(); - @SuppressWarnings("deprecation") String externalStorageDir = sdcard.getAbsolutePath(); String dataDir = this.getFilesDir().getAbsolutePath(); @@ -251,17 +267,19 @@ public class NativeActivity extends Activity { } } + private boolean useImmersive() { + String immersive = NativeApp.queryConfig("immersiveMode"); + return immersive.equals("1") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + } + @SuppressLint("InlinedApi") @TargetApi(14) private void updateSystemUiVisibility() { - String immersive = NativeApp.queryConfig("immersiveMode"); - boolean useImmersive = immersive.equals("1") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - int flags = 0; if (useLowProfileButtons()) { flags |= View.SYSTEM_UI_FLAG_LOW_PROFILE; } - if (useImmersive) { + if (useImmersive()) { flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; } if (getWindow().getDecorView() != null) { @@ -280,7 +298,16 @@ public class NativeActivity extends Activity { } } } - + + // Override this to scale the backbuffer (use the Android hardware scaler) + private void getDesiredBackbufferSize(Point sz) { + // GetScreenSize(sz, useImmersive()); + // sz.x /= 2; + // sz.y /= 2; + sz.x = 0; + sz.y = 0; + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -307,6 +334,12 @@ public class NativeActivity extends Activity { mGLSurfaceView = new NativeGLView(this); nativeRenderer = new NativeRenderer(this); + Point sz = new Point(); + getDesiredBackbufferSize(sz); + if (sz.x > 0) { + // Auto-calculates new DPI and forwards to the correct call on mGLSurfaceView.getHolder() + nativeRenderer.setFixedSize(sz.x, sz.y, mGLSurfaceView); + } mGLSurfaceView.setEGLContextClientVersion(2); // Setup the GLSurface and ask android for the correct @@ -356,7 +389,7 @@ public class NativeActivity extends Activity { @Override protected void onStop() { super.onStop(); - Log.i(TAG, "onStop - do nothing, just let Android switch away"); + Log.i(TAG, "onStop - do nothing special"); } @Override @@ -393,11 +426,8 @@ public class NativeActivity extends Activity { if (audioPlayer != null) { audioPlayer.stop(); } - Log.i(TAG, "nativeapp pause"); NativeApp.pause(); - Log.i(TAG, "gl pause"); mGLSurfaceView.onPause(); - Log.i(TAG, "onPause returning"); } @Override @@ -431,6 +461,12 @@ public class NativeActivity extends Activity { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { updateSystemUiVisibility(); } + + Point sz = new Point(); + getDesiredBackbufferSize(sz); + if (sz.x > 0) { + mGLSurfaceView.getHolder().setFixedSize(sz.x/2, sz.y/2); + } } // We simply grab the first input device to produce an event and ignore all others that are connected. diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 97da039e5b..39407b1cd2 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -1,5 +1,8 @@ package com.henrikrydgard.libnative; + +// Note that the display* methods are in NativeRenderer.java + public class NativeApp { public final static int DEVICE_ID_DEFAULT = 0; public final static int DEVICE_ID_KEYBOARD = 1; diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 1cb0a35005..ec2cd9dd49 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -22,6 +22,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, private static String TAG = "NativeGLView"; private SensorManager mSensorManager; private Sensor mAccelerometer; + private NativeActivity mActivity; // Moga controller private Controller mController = null; @@ -29,6 +30,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, public NativeGLView(NativeActivity activity) { super(activity); + mActivity = activity; /* if (Build.VERSION.SDK_INT >= 11) { @@ -73,6 +75,8 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, boolean canReadToolType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH; int numTouchesHandled = 0; + float scaleX = (float)mActivity.getRenderer().getDpiScaleX(); + float scaleY = (float)mActivity.getRenderer().getDpiScaleY(); for (int i = 0; i < ev.getPointerCount(); i++) { int pid = ev.getPointerId(i); int code = 0; @@ -104,7 +108,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, code |= tool << 10; // We use the Android tool type codes } // Can't use || due to short circuit evaluation - numTouchesHandled += NativeApp.touch(ev.getX(i), ev.getY(i), code, pid) ? 1 : 0; + numTouchesHandled += NativeApp.touch(scaleX * ev.getX(i), scaleY * ev.getY(i), code, pid) ? 1 : 0; } } return numTouchesHandled > 0; diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index 88d5df2ec7..ea43320fdb 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -4,6 +4,7 @@ import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; +import android.graphics.Point; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.util.DisplayMetrics; @@ -17,23 +18,37 @@ public class NativeRenderer implements GLSurfaceView.Renderer { private int dpi; private float refreshRate; + private double dpi_scale_x; + private double dpi_scale_y; + + int last_width, last_height; + NativeRenderer(NativeActivity act) { mActivity = act; - DisplayMetrics metrics = new DisplayMetrics(); Display display = act.getWindowManager().getDefaultDisplay(); display.getMetrics(metrics); dpi = metrics.densityDpi; - refreshRate = display.getRefreshRate(); - // Log.i(TAG, "Display name: " + display.getName()); - Log.i(TAG, " rate: " + refreshRate + " dpi: " + dpi); + refreshRate = display.getRefreshRate(); + } + + double getDpiScaleX() { + return dpi_scale_x; + } + double getDpiScaleY() { + return dpi_scale_y; } public void setDark(boolean d) { isDark = d; } + public void setFixedSize(int xres, int yres, GLSurfaceView surfaceView) { + Log.i(TAG, "Setting surface to fixed size " + xres + "x" + yres); + surfaceView.getHolder().setFixedSize(xres, yres); + } + @Override public void onDrawFrame(GL10 unused /*use GLES20*/) { if (isDark) { @@ -54,8 +69,17 @@ public class NativeRenderer implements GLSurfaceView.Renderer { @Override public void onSurfaceChanged(GL10 unused, int width, int height) { - Log.i(TAG, "onSurfaceChanged"); - displayResize(width, height, dpi, refreshRate); + Point sz = new Point(); + mActivity.GetScreenSize(sz); + double actualW = sz.x; + double actualH = sz.y; + dpi_scale_x = ((double)width / (double)actualW); + dpi_scale_y = ((double)height / (double)actualH); + Log.i(TAG, "onSurfaceChanged: " + dpi_scale_x + "x" + dpi_scale_y + " (width=" + width + ", actualW=" + actualW); + int scaled_dpi = (int)((double)dpi * dpi_scale_x); + displayResize(width, height, scaled_dpi, refreshRate); + last_width = width; + last_height = height; } // Not override, it's custom. From 82c805d93d2f469a7f0be36db818b87b48de1b5f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 18 Jul 2014 21:25:14 +0200 Subject: [PATCH 1180/1445] gotta be public --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 2f02070afa..73fb6b7dac 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -300,7 +300,7 @@ public class NativeActivity extends Activity { } // Override this to scale the backbuffer (use the Android hardware scaler) - private void getDesiredBackbufferSize(Point sz) { + public void getDesiredBackbufferSize(Point sz) { // GetScreenSize(sz, useImmersive()); // sz.x /= 2; // sz.y /= 2; From ceb5a94c4a525616a5102e15330f525410b1e5f3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 18 Jul 2014 21:49:33 +0200 Subject: [PATCH 1181/1445] android: Add "recreate" command --- .../libnative/NativeActivity.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 73fb6b7dac..c8c29b2e73 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -760,6 +760,7 @@ public class NativeActivity extends Activity { } else if (command.equals("toast")) { Toast toast = Toast.makeText(this, params, Toast.LENGTH_SHORT); toast.show(); + Log.i(TAG, params); return true; } else if (command.equals("showKeyboard")) { InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); @@ -828,7 +829,24 @@ public class NativeActivity extends Activity { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { updateSystemUiVisibility(); } + } else if (command.equals("recreate")) { + recreate(); } return false; } + + @SuppressLint("NewApi") + @Override + public void recreate() + { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) + { + super.recreate(); + } + else + { + startActivity(getIntent()); + finish(); + } + } } \ No newline at end of file From 085faa87ccf760048b8f72fd96a29294b5461b0d Mon Sep 17 00:00:00 2001 From: The Dax Date: Fri, 18 Jul 2014 18:42:41 -0400 Subject: [PATCH 1182/1445] Add a new Choice subclass which lets the UI display a value in addition to the title, similar to other controls. --- ui/ui_screen.cpp | 15 +++++++++++++++ ui/ui_screen.h | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 4730353b5b..d1fdb22f66 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -450,4 +450,19 @@ void TextEditPopupScreen::OnCompleted(DialogResult result) { } } +void ChoiceWithValueDisplay::Draw(UIContext &dc) { + Style style = dc.theme->itemStyle; + std::ostringstream valueText; + Choice::Draw(dc); + dc.SetFontStyle(dc.theme->uiFont); + + if (sValue_ != nullptr) { + valueText << *sValue_; + } else if (iValue_ != nullptr) { + valueText << *iValue_; + } + + dc.DrawText(valueText.str().c_str(), bounds_.x2() - 12, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); +} + } // namespace UI diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 95af3041d7..252a807821 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -266,4 +266,19 @@ private: std::string defaultText_; }; +class ChoiceWithValueDisplay : public UI::Choice { +public: + ChoiceWithValueDisplay(int *value, const std::string &text, LayoutParams *layoutParams = 0) + : Choice(text, layoutParams), iValue_(value) { sValue_ = nullptr; } + + ChoiceWithValueDisplay(std::string *value, const std::string &text, LayoutParams *layoutParams = 0) + : Choice(text, layoutParams), sValue_(value) { iValue_ = nullptr; } + + void Draw(UIContext &dc); + +private: + int *iValue_; + std::string *sValue_; +}; + } // namespace UI From c93e3149a89e48a7b4e4eede3da155eba16142af Mon Sep 17 00:00:00 2001 From: sum2012 Date: Sat, 19 Jul 2014 07:38:07 +0800 Subject: [PATCH 1183/1445] Android build fix for unknown reason #6575 --- ext/cityhash/city.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 54cc2a727c..4e25788eab 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -27,6 +27,9 @@ // possible hash functions, by using SIMD instructions, or by // compromising on hash quality. +#ifndef __WIN32__ +#undef __SSE4_2__ +#endif #include "city.h" #include From b980b73f41bae250a96115fe534cbc1556342965 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 20 Jul 2014 00:23:43 +0200 Subject: [PATCH 1184/1445] Change sum's buildhack to only affect android --- ext/cityhash/city.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 4e25788eab..c38da1e2ce 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -27,7 +27,7 @@ // possible hash functions, by using SIMD instructions, or by // compromising on hash quality. -#ifndef __WIN32__ +#ifdef ANDROID #undef __SSE4_2__ #endif #include "city.h" From ed04a0bf28dbe89f894bb33b0700f72c9ec17b72 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 19 Jul 2014 22:57:09 -0700 Subject: [PATCH 1185/1445] Only trigger a popup's default button if it has one. --- ui/ui_screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index d1fdb22f66..9576f31a47 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -150,7 +150,7 @@ bool PopupScreen::touch(const TouchInput &touch) { bool PopupScreen::key(const KeyInput &key) { if (key.flags & KEY_DOWN) { - if (key.keyCode == NKCODE_ENTER) { + if (key.keyCode == NKCODE_ENTER && defaultButton_) { UI::EventParams e; defaultButton_->OnClick.Trigger(e); return true; From 2ab2016002074e2d5190b38957902a2edea19e2a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 20 Jul 2014 12:04:22 +0200 Subject: [PATCH 1186/1445] Expose the Android system version to the app. Useful to enable/disable android-only features like immersive mode --- android/app-android.cpp | 13 ++++++++++++- .../com/henrikrydgard/libnative/NativeActivity.java | 2 +- .../src/com/henrikrydgard/libnative/NativeApp.java | 2 +- base/BlackberryMain.cpp | 2 ++ base/NativeApp.h | 4 ++++ base/PCMain.cpp | 2 ++ base/QtMain.cpp | 2 ++ 7 files changed, 24 insertions(+), 3 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 7837d43b46..fd497ba645 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -53,6 +53,7 @@ static float hat_joystick_y_async; int optimalFramesPerBuffer = 0; int optimalSampleRate = 0; +static int androidVersion; // Android implementation of callbacks to the Java part of the app void SystemToast(const char *text) { @@ -103,6 +104,15 @@ std::string System_GetProperty(SystemProperty prop) { } } +int System_GetPropertyInt(SystemProperty prop) { + switch (prop) { + case SYSPROP_SYSTEMVERSION: + return androidVersion; + default: + return -1; + } +} + // Remember that all of these need initialization on init! The process // may be reused when restarting the game. Globals are DANGEROUS. @@ -154,7 +164,7 @@ extern "C" jstring Java_com_henrikrydgard_libnative_NativeApp_queryConfig extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init (JNIEnv *env, jclass, jstring jdevicetype, jstring jlangRegion, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jshortcutParam, - jstring jinstallID, jboolean juseNativeAudio) { + jstring jinstallID, jboolean juseNativeAudio, jint jAndroidVersion) { jniEnvUI = env; ILOG("NativeApp.init() -- begin"); @@ -162,6 +172,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init memset(&input_state, 0, sizeof(input_state)); renderer_inited = false; first_lost = true; + androidVersion = jAndroidVersion; g_buttonTracker.Reset(); diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index c8c29b2e73..43b5382b59 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -211,7 +211,7 @@ public class NativeActivity extends Activity { String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL()); + NativeApp.init(deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL(), Build.VERSION.SDK_INT); // OK, config should be initialized, we can query for screen rotation. if (Build.VERSION.SDK_INT >= 9) { diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 39407b1cd2..a45fcdea13 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -9,7 +9,7 @@ public class NativeApp { public final static int DEVICE_ID_MOUSE = 2; public final static int DEVICE_ID_PAD_0 = 10; - public static native void init(String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, boolean useOpenSL); + public static native void init(String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, boolean useOpenSL, int androidVersion); public static native void audioInit(); public static native void audioShutdown(); diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 36cf8e3901..338639baa6 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -44,6 +44,8 @@ std::string System_GetProperty(SystemProperty prop) { } } +int System_GetPropertyInt(SystemProperty prop) {return -1;} + void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { g_quitRequested = true; diff --git a/base/NativeApp.h b/base/NativeApp.h index ec1e6c6233..cb6bf96004 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -123,6 +123,10 @@ enum SystemProperty { SYSPROP_NAME, SYSPROP_LANGREGION, SYSPROP_CPUINFO, + + // Available as Int: + SYSPROP_SYSTEMVERSION, }; std::string System_GetProperty(SystemProperty prop); +int System_GetPropertyInt(SystemProperty prop); \ No newline at end of file diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 9aa39a4e43..6609ba13f5 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -286,6 +286,8 @@ std::string System_GetProperty(SystemProperty prop) { } } +int System_GetPropertyInt(SystemProperty prop) {return -1;} + InputState input_state; static const int legacyKeyMap[] { diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 239ffad0e9..0a6ba0846f 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -66,6 +66,8 @@ std::string System_GetProperty(SystemProperty prop) { } } +int System_GetPropertyInt(SystemProperty prop) {return -1;} + void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { qApp->exit(0); From 1bc2fef02c07e86e9d60855af21001a72d1587e6 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 20 Jul 2014 12:08:19 +0200 Subject: [PATCH 1187/1445] VFS: Don't log irrelevant message when a file is just missing --- file/zip_read.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 1999bbdde0..ae12474798 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -325,10 +325,12 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { } int fn_len = (int)strlen(filename); + bool fileSystemFound = false; for (int i = 0; i < num_entries; i++) { int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { + fileSystemFound = true; // ILOG("Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); if (data) @@ -338,6 +340,9 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { // Else try the other registered file systems. } } + if (!fileSystemFound) { + ELOG("Missing filesystem for %s", filename); + } // Otherwise, the file was just missing. No need to log. return 0; } @@ -354,16 +359,21 @@ bool VFSGetFileListing(const char *path, std::vector *listing, const c } int fn_len = (int)strlen(path); + bool fileSystemFound = false; for (int i = 0; i < num_entries; i++) { int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(path, entries[i].prefix, prefix_len)) { + fileSystemFound = true; if (entries[i].reader->GetFileListing(path + prefix_len, listing, filter)) { return true; } } } - ELOG("Missing filesystem for %s", path); + + if (!fileSystemFound) { + ELOG("Missing filesystem for %s", path); + } // Otherwise, the file was just missing. No need to log. return false; } @@ -378,17 +388,21 @@ bool VFSGetFileInfo(const char *path, FileInfo *info) { return getFileInfo(path, info); } + bool fileSystemFound = false; int fn_len = (int)strlen(path); for (int i = 0; i < num_entries; i++) { int prefix_len = (int)strlen(entries[i].prefix); if (prefix_len >= fn_len) continue; if (0 == memcmp(path, entries[i].prefix, prefix_len)) { + fileSystemFound = true; if (entries[i].reader->GetFileInfo(path + prefix_len, info)) return true; else continue; } } - ELOG("Missing filesystem for %s", path); + if (!fileSystemFound) { + ELOG("Missing filesystem for %s", path); + } // Otherwise, the file was just missing. No need to log. return false; } From 370b6b3eacd68353add01167411d6f73201e32e2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 20 Jul 2014 12:49:58 +0200 Subject: [PATCH 1188/1445] input: Add a convenient constant for max axis. remap a couple to reduce the number. (isn't possible to manually map the accelerometer ones so should be safe for ppsspp) --- input/keycodes.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/input/keycodes.h b/input/keycodes.h index 6b0f1cd3a2..22c9b417a7 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -305,7 +305,9 @@ enum AndroidJoystickAxis { JOYSTICK_AXIS_OUYA_UNKNOWN4 = 35, // Mobile device accelerometer/gyro - JOYSTICK_AXIS_ACCELEROMETER_X = 64, - JOYSTICK_AXIS_ACCELEROMETER_Y = 65, - JOYSTICK_AXIS_ACCELEROMETER_Z = 66, + JOYSTICK_AXIS_ACCELEROMETER_X = 40, + JOYSTICK_AXIS_ACCELEROMETER_Y = 41, + JOYSTICK_AXIS_ACCELEROMETER_Z = 42, + + JOYSTICK_AXIS_MAX = 44 }; From a9ab9bcdca0c938e716d0d5d59a2676c3e2bf530 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 20 Jul 2014 17:13:35 +0200 Subject: [PATCH 1189/1445] android: LDLIBS in a static library just causes warnings: remove --- Android.mk | 1 - ext/libzip/Android.mk | 1 - 2 files changed, 2 deletions(-) diff --git a/Android.mk b/Android.mk index db81b0de40..4098bf4253 100644 --- a/Android.mk +++ b/Android.mk @@ -102,7 +102,6 @@ LOCAL_SRC_FILES :=\ LOCAL_CFLAGS := -O3 -DUSING_GLES2 -fsigned-char -fno-strict-aliasing -Wall -Wno-multichar -D__STDC_CONSTANT_MACROS LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -fno-rtti -Wno-reorder -LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext $(LOCAL_PATH)/ext/libzip #Portable native and separate code on android in future is easy you needs add files diff --git a/ext/libzip/Android.mk b/ext/libzip/Android.mk index 8973e1aaef..e05b292f44 100644 --- a/ext/libzip/Android.mk +++ b/ext/libzip/Android.mk @@ -73,6 +73,5 @@ LOCAL_SRC_FILES :=\ zip_unchange_data.c LOCAL_CFLAGS := -O2 -LOCAL_LDLIBS := -lz include $(BUILD_STATIC_LIBRARY) From a7bb45a30b3b2980ee8e09f74c7a085be85a6e85 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 20 Jul 2014 08:47:37 -0700 Subject: [PATCH 1190/1445] Fix a few minor warnings on Android. Seems st_mtime is not a time_t there, just unsigned long. --- gfx_es2/glsl_program.cpp | 6 +++--- ui/view.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index fdf88ea807..57058ee67e 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -78,9 +78,9 @@ bool glsl_up_to_date(GLSLProgram *program) { struct stat vs, fs; stat(program->vshader_filename, &vs); stat(program->fshader_filename, &fs); - if (vs.st_mtime != program->vshader_mtime || - fs.st_mtime != program->fshader_mtime) { - return false; + if ((time_t)vs.st_mtime != program->vshader_mtime || + (time_t)fs.st_mtime != program->fshader_mtime) { + return false; } else { return true; } diff --git a/ui/view.cpp b/ui/view.cpp index cfaec627e8..adf9d604cb 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -624,7 +624,7 @@ void TextEdit::Key(const KeyInput &input) { caret_ = (int)text_.size(); break; case NKCODE_FORWARD_DEL: - if (caret_ < text_.size()) { + if (caret_ < (int)text_.size()) { text_.erase(text_.begin() + caret_, text_.begin() + caret_ + 1); } case NKCODE_DEL: @@ -650,7 +650,7 @@ void TextEdit::Key(const KeyInput &input) { // Insert it! (todo: do it with a string insert) char buf[8]; buf[u8_wc_toutf8(buf, unichar)] = '\0'; - for (int i = 0; i < strlen(buf); i++) { + for (size_t i = 0; i < strlen(buf); i++) { text_.insert(text_.begin() + caret_, buf[i]); caret_++; } From 692dc810cf4dec5c36bca309c1ad99acbb88f3bc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 20 Jul 2014 08:56:01 -0700 Subject: [PATCH 1191/1445] Update CityHash to v1.1.1/r15. No major changes. --- ext/cityhash/city.cpp | 33 ++++++++++++++++++++++++++++++--- ext/cityhash/city.h | 4 ++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index c38da1e2ce..28e766b010 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -53,13 +53,39 @@ static uint32 UNALIGNED_LOAD32(const char *p) { #ifdef _MSC_VER #define bswap_32(x) _byteswap_ulong(x) #define bswap_64(x) _byteswap_uint64(x) + #elif defined(__GLIBC__) #include + #elif defined(__APPLE__) // Mac OS X / Darwin features #include #define bswap_32(x) OSSwapInt32(x) #define bswap_64(x) OSSwapInt64(x) + +#elif defined(__sun) || defined(sun) +#include +#define bswap_32(x) BSWAP_32(x) +#define bswap_64(x) BSWAP_64(x) + +#elif defined(__FreeBSD__) +#include +#define bswap_32(x) bswap32(x) +#define bswap_64(x) bswap64(x) + +#elif defined(__OpenBSD__) +#include +#define bswap_32(x) swap32(x) +#define bswap_64(x) swap64(x) + +#elif defined(__NetBSD__) +#include +#include +#if defined(__BSWAP_RENAME) && !defined(__bswap_32) +#define bswap_32(x) bswap32(x) +#define bswap_64(x) bswap64(x) +#endif + #else #define bswap_32(x) (0 | ((x & 0x000000ff) << 24) \ | ((x & 0x0000ff00) << 8) \ @@ -105,8 +131,8 @@ static const uint64 k1 = 0xb492b66fbe98f273ULL; static const uint64 k2 = 0x9ae16a3b2f90404fULL; // Magic numbers for 32-bit hashing. Copied from Murmur3. -static const uint32_t c1 = 0xcc9e2d51; -static const uint32_t c2 = 0x1b873593; +static const uint32 c1 = 0xcc9e2d51; +static const uint32 c2 = 0x1b873593; // A 32-bit to 32-bit integer hash copied from Murmur3. static uint32 fmix(uint32 h) @@ -153,7 +179,8 @@ static uint32 Hash32Len0to4(const char *s, size_t len) { uint32 b = 0; uint32 c = 9; for (size_t i = 0; i < len; i++) { - b = b * c1 + s[i]; + signed char v = s[i]; + b = b * c1 + v; c ^= b; } return fmix(Mur(b, Mur(len, c))); diff --git a/ext/cityhash/city.h b/ext/cityhash/city.h index ec52f2b5b2..94499ce419 100644 --- a/ext/cityhash/city.h +++ b/ext/cityhash/city.h @@ -38,6 +38,7 @@ // nearest competitor is Bob Jenkins' Spooky. We don't have great data for // other 64-bit CPUs, but for long strings we know that Spooky is slightly // faster than CityHash on some relatively recent AMD x86-64 CPUs, for example. +// Note that CityHashCrc128 is declared in citycrc.h. // // For 32-bit x86 code, we don't know of anything faster than CityHash32 that // is of comparable quality. We believe our nearest competitor is Murmur3A. @@ -45,6 +46,9 @@ // // Functions in the CityHash family are not suitable for cryptography. // +// Please see CityHash's README file for more details on our performance +// measurements and so on. +// // WARNING: This code has been only lightly tested on big-endian platforms! // It is known to work well on little-endian platforms that have a small penalty // for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs. From 1d77b9435562e67d2814db99c89a752febd6dbe4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 20 Jul 2014 18:29:18 +0200 Subject: [PATCH 1192/1445] Fix another operator shortcutting bug (tilt events) --- android/app-android.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index fd497ba645..bc221ea3eb 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -478,6 +478,7 @@ extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_mouseWheelEvent( extern "C" jboolean JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerometer(JNIEnv *, jclass, float x, float y, float z) { if (!renderer_inited) return false; + // Theoretically this needs locking but I doubt it matters. Worst case, the X // from one "sensor frame" will be used together with Y from the next. // Should look into quantization though, for compressed movement storage. @@ -492,16 +493,17 @@ extern "C" jboolean JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerom axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_X; axis.value = x; - bool retval = NativeAxis(axis); + bool retvalX = NativeAxis(axis); axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Y; axis.value = y; - retval = retval || NativeAxis(axis); + bool retvalY = NativeAxis(axis); axis.axisId = JOYSTICK_AXIS_ACCELEROMETER_Z; axis.value = z; - retval = retval || NativeAxis(axis); - return retval; + bool retvalZ = NativeAxis(axis); + + return retvalX || retvalY || retvalZ; } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) { From dcd27e134d42ba35647430cc33006225af40cc20 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 20 Jul 2014 22:20:09 +0200 Subject: [PATCH 1193/1445] Add flag to identify events from mouses. --- base/PCMain.cpp | 10 +++++----- input/input_state.h | 3 ++- ui/view.cpp | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 6609ba13f5..cda16b7877 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -674,7 +674,7 @@ int main(int argc, char *argv[]) { TouchInput input; input.x = mx; input.y = my; - input.flags = TOUCH_DOWN; + input.flags = TOUCH_DOWN | TOUCH_MOUSE; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN); @@ -715,7 +715,7 @@ int main(int argc, char *argv[]) { TouchInput input; input.x = mx; input.y = my; - input.flags = TOUCH_MOVE; + input.flags = TOUCH_MOVE | TOUCH_MOUSE; input.id = 0; NativeTouch(input); } @@ -732,7 +732,7 @@ int main(int argc, char *argv[]) { TouchInput input; input.x = mx; input.y = my; - input.flags = TOUCH_UP; + input.flags = TOUCH_UP | TOUCH_MOUSE; input.id = 0; NativeTouch(input); KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP); @@ -748,7 +748,7 @@ int main(int argc, char *argv[]) { case SDL_BUTTON_WHEELUP: { KeyInput key; - key.deviceId = DEVICE_ID_DEFAULT; + key.deviceId = DEVICE_ID_MOUSE; key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_UP; NativeKey(key); @@ -757,7 +757,7 @@ int main(int argc, char *argv[]) { case SDL_BUTTON_WHEELDOWN: { KeyInput key; - key.deviceId = DEVICE_ID_DEFAULT; + key.deviceId = DEVICE_ID_MOUSE; key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_UP; NativeKey(key); diff --git a/input/input_state.h b/input/input_state.h index 5538238cfd..9a4df96248 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -130,7 +130,8 @@ enum { TOUCH_DOWN = 1 << 1, TOUCH_UP = 1 << 2, TOUCH_CANCEL = 1 << 3, // Sent by scrollviews to their children when they detect a scroll - TOUCH_WHEEL = 1 << 4, // Scrollwheel event. Usually only affects Y. + TOUCH_WHEEL = 1 << 4, // Scrollwheel event. Usually only affects Y but can potentially affect X. + TOUCH_MOUSE = 1 << 5, // Identifies that this touch event came from a mouse // These are the Android getToolType() codes, shifted by 10. TOUCH_TOOL_MASK = 7 << 10, diff --git a/ui/view.cpp b/ui/view.cpp index adf9d604cb..0610c54f36 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -706,7 +706,7 @@ void TriggerButton::GetContentDimensions(const UIContext &dc, float &w, float &h } void Slider::Key(const KeyInput &input) { - if (HasFocus() && input.flags & KEY_DOWN) { + if (HasFocus() && (input.flags & KEY_DOWN)) { switch (input.keyCode) { case NKCODE_DPAD_LEFT: case NKCODE_MINUS: @@ -776,7 +776,7 @@ void Slider::GetContentDimensions(const UIContext &dc, float &w, float &h) const } void SliderFloat::Key(const KeyInput &input) { - if (HasFocus() && input.flags & KEY_DOWN) { + if (HasFocus() && (input.flags & KEY_DOWN)) { switch (input.keyCode) { case NKCODE_DPAD_LEFT: case NKCODE_MINUS: From a4a17415a7f12d15eb37f57181df97d46e239531 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 21 Jul 2014 00:34:12 +0200 Subject: [PATCH 1194/1445] android: Allow querying the real display resolution as detected on start --- android/app-android.cpp | 12 +++++++++++- .../com/henrikrydgard/libnative/NativeActivity.java | 12 ++++++------ .../src/com/henrikrydgard/libnative/NativeApp.java | 2 +- base/NativeApp.h | 2 ++ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index bc221ea3eb..91b6562a62 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -55,6 +55,10 @@ int optimalFramesPerBuffer = 0; int optimalSampleRate = 0; static int androidVersion; +// Should only be used for display detection during startup (for config defaults etc) +static int display_xres; +static int display_yres; + // Android implementation of callbacks to the Java part of the app void SystemToast(const char *text) { lock_guard guard(frameCommandLock); @@ -108,6 +112,10 @@ int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_SYSTEMVERSION: return androidVersion; + case SYSPROP_DISPLAY_XRES: + return display_xres; + case SYSPROP_DISPLAY_YRES: + return display_yres; default: return -1; } @@ -162,7 +170,7 @@ extern "C" jstring Java_com_henrikrydgard_libnative_NativeApp_queryConfig } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init - (JNIEnv *env, jclass, jstring jdevicetype, jstring jlangRegion, jstring japkpath, + (JNIEnv *env, jclass, jstring jdevicetype, jint jxres, jint jyres, jstring jlangRegion, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jshortcutParam, jstring jinstallID, jboolean juseNativeAudio, jint jAndroidVersion) { jniEnvUI = env; @@ -182,6 +190,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init right_joystick_y_async = 0; hat_joystick_x_async = 0; hat_joystick_y_async = 0; + display_xres = jxres; + display_yres = jyres; std::string apkPath = GetJavaString(env, japkpath); VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 43b5382b59..e853917687 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -206,12 +206,14 @@ public class NativeActivity extends Activity { String externalStorageDir = sdcard.getAbsolutePath(); String dataDir = this.getFilesDir().getAbsolutePath(); String apkFilePath = appInfo.sourceDir; - + String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); - + + Point displaySize = new Point(); + GetScreenSize(displaySize); NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(deviceType, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL(), Build.VERSION.SDK_INT); + NativeApp.init(deviceType, displaySize.x, displaySize.y, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL(), Build.VERSION.SDK_INT); // OK, config should be initialized, we can query for screen rotation. if (Build.VERSION.SDK_INT >= 9) { @@ -301,9 +303,6 @@ public class NativeActivity extends Activity { // Override this to scale the backbuffer (use the Android hardware scaler) public void getDesiredBackbufferSize(Point sz) { - // GetScreenSize(sz, useImmersive()); - // sz.x /= 2; - // sz.y /= 2; sz.x = 0; sz.y = 0; } @@ -337,6 +336,7 @@ public class NativeActivity extends Activity { Point sz = new Point(); getDesiredBackbufferSize(sz); if (sz.x > 0) { + Log.i(TAG, "Requesting fixed size buffer: " + sz.x + "x" + sz.y); // Auto-calculates new DPI and forwards to the correct call on mGLSurfaceView.getHolder() nativeRenderer.setFixedSize(sz.x, sz.y, mGLSurfaceView); } diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index a45fcdea13..5239131da6 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -9,7 +9,7 @@ public class NativeApp { public final static int DEVICE_ID_MOUSE = 2; public final static int DEVICE_ID_PAD_0 = 10; - public static native void init(String deviceType, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, boolean useOpenSL, int androidVersion); + public static native void init(String deviceType, int xres, int yres, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, boolean useOpenSL, int androidVersion); public static native void audioInit(); public static native void audioShutdown(); diff --git a/base/NativeApp.h b/base/NativeApp.h index cb6bf96004..ae83042fb8 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -126,6 +126,8 @@ enum SystemProperty { // Available as Int: SYSPROP_SYSTEMVERSION, + SYSPROP_DISPLAY_XRES, + SYSPROP_DISPLAY_YRES, }; std::string System_GetProperty(SystemProperty prop); From 6f6f6eb1fbe82b0b16dc54628cce231cda26255b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 21 Jul 2014 11:59:05 +0200 Subject: [PATCH 1195/1445] TextEdit: Add utf-8 support, enable paste from clipboard --- base/NativeApp.h | 1 + gfx_es2/draw_buffer.cpp | 8 +++- gfx_es2/draw_buffer.h | 4 +- ui/ui_context.cpp | 9 ++++- ui/ui_context.h | 1 + ui/ui_screen.cpp | 7 ++-- ui/ui_screen.h | 8 ++-- ui/view.cpp | 82 +++++++++++++++++++++++++++++++++++------ ui/view.h | 6 +++ util/text/utf8.h | 9 +++++ 10 files changed, 113 insertions(+), 22 deletions(-) diff --git a/base/NativeApp.h b/base/NativeApp.h index ae83042fb8..a70f3094a1 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -123,6 +123,7 @@ enum SystemProperty { SYSPROP_NAME, SYSPROP_LANGREGION, SYSPROP_CPUINFO, + SYSPROP_CLIPBOARD_TEXT, // Available as Int: SYSPROP_SYSTEMVERSION, diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index a71f8751bc..2ba96081a0 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -364,7 +364,7 @@ void DrawBuffer::DrawImage2GridH(ImageID atlas_image, float x1, float y1, float DrawTexRect(xb, y1, x2, y2, um, v1, u2, v2, color); } -void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { +void DrawBuffer::MeasureTextCount(int font, const char *text, int count, float *w, float *h) { const AtlasFont &atlasfont = *atlas->fonts[font]; unsigned int cval; @@ -375,6 +375,8 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { while (true) { if (utf.end()) break; + if (utf.byteIndex() >= count) + break; cval = utf.next(); // Translate non-breaking space to space. if (cval == 0xA0) { @@ -398,6 +400,10 @@ void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { if (h) *h = atlasfont.height * fontscaley * lines; } +void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { + return MeasureTextCount(font, text, strlen(text), w, h); +} + void DrawBuffer::DrawTextShadow(int font, const char *text, float x, float y, Color color, int flags) { uint32_t alpha = (color >> 1) & 0xFF000000; DrawText(font, text, x + 2, y + 2, alpha, flags); diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 409b18c83d..914f7cc746 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -123,7 +123,9 @@ public: void DrawImage2GridH(ImageID atlas_image, float x1, float y1, float x2, Color color = COLOR(0xFFFFFF), float scale = 1.0); void MeasureText(int font, const char *text, float *w, float *h); - + + // NOTE: Count is in plain chars not utf-8 chars! + void MeasureTextCount(int font, const char *text, int count, float *w, float *h); void DrawTextRect(int font, const char *text, float x, float y, float w, float h, Color color = 0xFFFFFFFF, int align = 0); void DrawText(int font, const char *text, float x, float y, Color color = 0xFFFFFFFF, int align = 0); diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index ea4c2a8266..fbdaacb596 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -142,13 +142,18 @@ void UIContext::SetFontStyle(const UI::FontStyle &fontStyle) { } void UIContext::MeasureText(const UI::FontStyle &style, const char *str, float *x, float *y, int align) const { + MeasureTextCount(style, str, (int)strlen(str), x, y, align); +} + +void UIContext::MeasureTextCount(const UI::FontStyle &style, const char *str, int count, float *x, float *y, int align) const { if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) { float sizeFactor = (float)style.sizePts / 24.0f; Draw()->SetFontScale(fontScaleX_ * sizeFactor, fontScaleY_ * sizeFactor); - Draw()->MeasureText(style.atlasFont, str, x, y); + Draw()->MeasureTextCount(style.atlasFont, str, count, x, y); } else { textDrawer_->SetFontScale(fontScaleX_, fontScaleY_); - textDrawer_->MeasureString(str, x, y); + std::string subset(str, count); + textDrawer_->MeasureString(subset.c_str(), x, y); } } diff --git a/ui/ui_context.h b/ui/ui_context.h index ea87aab7f5..5fff30ec35 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -54,6 +54,7 @@ public: void SetFontStyle(const UI::FontStyle &style); const UI::FontStyle &GetFontStyle() { return *fontStyle_; } void SetFontScale(float scaleX, float scaleY); + void MeasureTextCount(const UI::FontStyle &style, const char *str, int count, float *x, float *y, int align = 0) const; void MeasureText(const UI::FontStyle &style, const char *str, float *x, float *y, int align = 0) const; void DrawText(const char *str, float x, float y, uint32_t color, int align = 0); void DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align = 0); diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 9576f31a47..fb53a3a489 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -402,13 +402,13 @@ void SliderFloatPopupScreen::OnCompleted(DialogResult result) { } } -PopupTextInputChoice::PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, ScreenManager *screenManager, LayoutParams *layoutParams) -: Choice(title, "", false, layoutParams), value_(value), placeHolder_(placeholder), screenManager_(screenManager) { +PopupTextInputChoice::PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams) +: Choice(title, "", false, layoutParams), value_(value), placeHolder_(placeholder), screenManager_(screenManager), maxLen_(maxLen) { OnClick.Handle(this, &PopupTextInputChoice::HandleClick); } EventReturn PopupTextInputChoice::HandleClick(EventParams &e) { - TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, text_); + TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, text_, maxLen_); popupScreen->OnChange.Handle(this, &PopupTextInputChoice::HandleChange); screenManager_->push(popupScreen); return EVENT_DONE; @@ -436,6 +436,7 @@ void TextEditPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { textEditValue_ = *value_; LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams((UI::Size)300, WRAP_CONTENT))); edit_ = new TextEdit(textEditValue_, placeholder_, new LinearLayoutParams(1.0f)); + edit_->SetMaxLen(maxLen_); lin->Add(edit_); UI::SetFocusedView(edit_); diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 252a807821..82b519c701 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -164,8 +164,8 @@ private: class TextEditPopupScreen : public PopupScreen { public: - TextEditPopupScreen(std::string *value, std::string &placeholder, const std::string &title) - : PopupScreen(title, "OK", "Cancel"), value_(value), placeholder_(placeholder) {} + TextEditPopupScreen(std::string *value, std::string &placeholder, const std::string &title, int maxLen) + : PopupScreen(title, "OK", "Cancel"), value_(value), placeholder_(placeholder), maxLen_(maxLen) {} void CreatePopupContents(ViewGroup *parent); Event OnChange; @@ -177,6 +177,7 @@ private: std::string textEditValue_; std::string placeholder_; int step_; + int maxLen_; }; // Reads and writes value to determine the current selection. @@ -251,7 +252,7 @@ private: class PopupTextInputChoice: public Choice { public: - PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, ScreenManager *screenManager, LayoutParams *layoutParams = 0); + PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams = 0); void Draw(UIContext &dc); @@ -264,6 +265,7 @@ private: std::string *value_; std::string placeHolder_; std::string defaultText_; + int maxLen_; }; class ChoiceWithValueDisplay : public UI::Choice { diff --git a/ui/view.cpp b/ui/view.cpp index 0610c54f36..69f7f0f3a5 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -11,6 +11,7 @@ #include "ui/ui.h" #include "ui/view.h" #include "ui/ui_context.h" +#include "base/NativeApp.h" namespace UI { @@ -574,7 +575,7 @@ void TextView::Draw(UIContext &dc) { } TextEdit::TextEdit(const std::string &text, const std::string &placeholderText, LayoutParams *layoutParams) - : View(layoutParams), text_(text), placeholderText_(placeholderText) { + : View(layoutParams), text_(text), placeholderText_(placeholderText), maxLen_(255), ctrlDown_(false) { caret_ = (int)text_.size(); } @@ -590,9 +591,8 @@ void TextEdit::Draw(UIContext &dc) { } // Hack to find the caret position. Might want to find a better way... - std::string subset = text_.substr(0, caret_); float w, h; - dc.MeasureText(dc.theme->uiFont, subset.c_str(), &w, &h, ALIGN_VCENTER | ALIGN_LEFT); + dc.MeasureTextCount(dc.theme->uiFont, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT); float caretX = bounds_.x + w; dc.FillRect(UI::Drawable(0xFFFFFFFF), Bounds(caretX - 1, bounds_.y + 2, 3, bounds_.h - 4)); } @@ -603,17 +603,34 @@ void TextEdit::GetContentDimensions(const UIContext &dc, float &w, float &h) con h += 2; } +// Handles both windows and unix line endings. +std::string FirstLine(const std::string &text) { + size_t pos = text.find("\r\n"); + if (pos != std::string::npos) { + return text.substr(0, pos); + } + pos = text.find('\n'); + if (pos != std::string::npos) { + return text.substr(0, pos); + } + return text; +} + void TextEdit::Key(const KeyInput &input) { if (!HasFocus()) return; // Process navigation keys. These aren't chars. if (input.flags & KEY_DOWN) { switch (input.keyCode) { + case NKCODE_CTRL_LEFT: + case NKCODE_CTRL_RIGHT: + ctrlDown_ = true; + break; case NKCODE_DPAD_LEFT: // ASCII left arrow - caret_--; + u8_dec(text_.c_str(), &caret_); break; case NKCODE_DPAD_RIGHT: // ASCII right arrow - caret_++; + u8_inc(text_.c_str(), &caret_); break; case NKCODE_MOVE_HOME: case NKCODE_PAGE_UP: @@ -625,16 +642,43 @@ void TextEdit::Key(const KeyInput &input) { break; case NKCODE_FORWARD_DEL: if (caret_ < (int)text_.size()) { - text_.erase(text_.begin() + caret_, text_.begin() + caret_ + 1); + int endCaret = caret_; + u8_inc(text_.c_str(), &endCaret); + text_.erase(text_.begin() + caret_, text_.begin() + endCaret); } + break; case NKCODE_DEL: if (caret_ > 0) { - text_.erase(text_.begin() + caret_ - 1, text_.begin() + caret_); + int begCaret = caret_; + u8_dec(text_.c_str(), &begCaret); + text_.erase(text_.begin() + begCaret, text_.begin() + caret_); caret_--; } break; } + if (ctrlDown_) { + switch (input.keyCode) { + case NKCODE_V: + { + std::string clipText = System_GetProperty(SYSPROP_CLIPBOARD_TEXT); + clipText = FirstLine(clipText); + if (clipText.size() > 32) { + int end = 0; + while (end < 32) { + u8_inc(clipText.c_str(), &end); + } + if (end > 0) { + u8_dec(clipText.c_str(), &end); + } + clipText = clipText.substr(0, end); + } + InsertAtCaret(clipText.c_str()); + } + break; + } + } + if (caret_ < 0) { caret_ = 0; } @@ -643,21 +687,35 @@ void TextEdit::Key(const KeyInput &input) { } } + if (input.flags & KEY_UP) { + switch (input.keyCode) { + case NKCODE_CTRL_LEFT: + case NKCODE_CTRL_RIGHT: + ctrlDown_ = false; + break; + } + } + // Process chars. if (input.flags & KEY_CHAR) { int unichar = input.keyCode; - if (unichar >= 0x20) { // Ignore control characters. + if (unichar >= 0x20 && !ctrlDown_) { // Ignore control characters. // Insert it! (todo: do it with a string insert) char buf[8]; buf[u8_wc_toutf8(buf, unichar)] = '\0'; - for (size_t i = 0; i < strlen(buf); i++) { - text_.insert(text_.begin() + caret_, buf[i]); - caret_++; - } + InsertAtCaret(buf); } } } +void TextEdit::InsertAtCaret(const char *text) { + size_t len = strlen(text); + for (size_t i = 0; i < len; i++) { + text_.insert(text_.begin() + caret_, text[i]); + caret_++; + } +} + void ProgressBar::GetContentDimensions(const UIContext &dc, float &w, float &h) const { dc.MeasureText(dc.theme->uiFont, " 100% ", &w, &h); } diff --git a/ui/view.h b/ui/view.h index 9bb8522f9b..d02a18d560 100644 --- a/ui/view.h +++ b/ui/view.h @@ -658,6 +658,7 @@ public: virtual void Draw(UIContext &dc) override; void SetText(const std::string &text) { text_ = text; } void SetSmall(bool small) { small_ = small; } + private: std::string text_; int textAlign_; @@ -669,15 +670,20 @@ public: TextEdit(const std::string &text, const std::string &placeholderText, LayoutParams *layoutParams = 0); void SetText(const std::string &text) { text_ = text; caret_ = (int)text_.size(); } const std::string &GetText() const { return text_; } + void SetMaxLen(int maxLen) { maxLen_ = maxLen; } virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; virtual void Draw(UIContext &dc) override; virtual void Key(const KeyInput &input) override; private: + void InsertAtCaret(const char *text); + std::string text_; std::string placeholderText_; int caret_; + int maxLen_; + bool ctrlDown_; // TODO: Make some global mechanism for this. // TODO: Selections }; diff --git a/util/text/utf8.h b/util/text/utf8.h index 8a11eb6a28..83af37ee58 100644 --- a/util/text/utf8.h +++ b/util/text/utf8.h @@ -22,11 +22,14 @@ uint32_t u8_nextchar(const char *s, int *i); int u8_wc_toutf8(char *dest, uint32_t ch); int u8_strlen(const char *s); +void u8_inc(const char *s, int *i); +void u8_dec(const char *s, int *i); class UTF8 { public: static const uint32_t INVALID = (uint32_t)-1; UTF8(const char *c) : c_(c), index_(0) {} + UTF8(const char *c, int index) : c_(c), index_(index) {} bool end() const { return c_[index_] == 0; } uint32_t next() { return u8_nextchar(c_, &index_); @@ -35,6 +38,12 @@ public: int tempIndex = index_; return u8_nextchar(c_, &tempIndex); } + void fwd() { + u8_inc(c_, &index_); + } + void bwd() { + u8_dec(c_, &index_); + } int length() const { return u8_strlen(c_); } From 9d8d64b321f6d8964066dd6ed83064a32969ec04 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 21 Jul 2014 17:35:51 +0200 Subject: [PATCH 1196/1445] TextEdit: Ctrl-C to copy the contents of the textbox. --- ui/view.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/view.cpp b/ui/view.cpp index 69f7f0f3a5..db3bfc9c5a 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -659,6 +659,10 @@ void TextEdit::Key(const KeyInput &input) { if (ctrlDown_) { switch (input.keyCode) { + case NKCODE_C: + // Just copy the entire text contents, until we get selection support. + System_SendMessage("setclipboardtext", text_.c_str()); + break; case NKCODE_V: { std::string clipText = System_GetProperty(SYSPROP_CLIPBOARD_TEXT); From 4195da289c15dbdecc1c71989efb3baaf0758043 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 21 Jul 2014 18:42:25 +0200 Subject: [PATCH 1197/1445] ChoiceWithValueDisplay: Allow translation of the value --- i18n/i18n.h | 3 +++ ui/ui_screen.cpp | 5 ++++- ui/ui_screen.h | 7 ++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/i18n/i18n.h b/i18n/i18n.h index 2a52b21043..ffa09647aa 100644 --- a/i18n/i18n.h +++ b/i18n/i18n.h @@ -37,6 +37,9 @@ class I18NCategory { public: I18NCategory(const char *name) : name_(name) {} const char *T(const char *key, const char *def = 0); + const char *T(const std::string &key) { + return T(key.c_str(), nullptr); + } const std::map &Missed() const { return missedKeyLog_; diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index fb53a3a489..a6de1bebb5 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -458,7 +458,10 @@ void ChoiceWithValueDisplay::Draw(UIContext &dc) { dc.SetFontStyle(dc.theme->uiFont); if (sValue_ != nullptr) { - valueText << *sValue_; + if (category_) + valueText << category_->T(*sValue_); + else + valueText << *sValue_; } else if (iValue_ != nullptr) { valueText << *iValue_; } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 82b519c701..f536397601 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -271,16 +271,17 @@ private: class ChoiceWithValueDisplay : public UI::Choice { public: ChoiceWithValueDisplay(int *value, const std::string &text, LayoutParams *layoutParams = 0) - : Choice(text, layoutParams), iValue_(value) { sValue_ = nullptr; } + : Choice(text, layoutParams), iValue_(value), category_(nullptr) { sValue_ = nullptr; } - ChoiceWithValueDisplay(std::string *value, const std::string &text, LayoutParams *layoutParams = 0) - : Choice(text, layoutParams), sValue_(value) { iValue_ = nullptr; } + ChoiceWithValueDisplay(std::string *value, const std::string &text, I18NCategory *category, LayoutParams *layoutParams = 0) + : Choice(text, layoutParams), sValue_(value), category_(category) { iValue_ = nullptr; } void Draw(UIContext &dc); private: int *iValue_; std::string *sValue_; + I18NCategory *category_; }; } // namespace UI From db6a57c8fefd62482d0a15c8d5ae9ecf9c8996fd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 22 Jul 2014 01:04:42 +0200 Subject: [PATCH 1198/1445] Try to detect GLES 3.1 as well as 3.0 --- gfx_es2/gl_state.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index fc976a7369..c65b57a725 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -101,15 +101,15 @@ void CheckGLExtensions() { if (vendor == "NVIDIA Corporation" || vendor == "Nouveau" || vendor == "nouveau") { - gl_extensions.gpuVendor = GPU_VENDOR_NVIDIA; + gl_extensions.gpuVendor = GPU_VENDOR_NVIDIA; } else if (vendor == "Advanced Micro Devices, Inc." || vendor == "ATI Technologies Inc.") { - gl_extensions.gpuVendor = GPU_VENDOR_AMD; + gl_extensions.gpuVendor = GPU_VENDOR_AMD; } else if (vendor == "Intel" || vendor == "Intel Inc." || vendor == "Intel Corporation" || vendor == "Tungsten Graphics, Inc") { // We'll assume this last one means Intel - gl_extensions.gpuVendor = GPU_VENDOR_INTEL; + gl_extensions.gpuVendor = GPU_VENDOR_INTEL; } else if (vendor == "ARM") { gl_extensions.gpuVendor = GPU_VENDOR_ARM; } else if (vendor == "Imagination Technologies") { @@ -129,7 +129,7 @@ void CheckGLExtensions() { ILOG("GPU Vendor : %s ; GL version str: %s ; GLSL version str: %s", cvendor, versionStr ? versionStr : "N/A", glslVersionStr ? glslVersionStr : "N/A"); #ifndef USING_GLES2 - char buffer[64] = {0}; + char buffer[64] = { 0 }; if (versionStr) { strncpy(buffer, versionStr, 63); } @@ -154,11 +154,18 @@ void CheckGLExtensions() { // Try to load GLES 3.0 only if "3.0" found in version // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited // number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584. - // Really, we should do something much better. - if (strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0") && gl3stubInit()) { + // TODO: Do something way more robust! + bool gl_3_0_in_string = strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0"); + bool gl_3_1_in_string = strstr(versionStr, "3.1") && strstr(glslVersionStr, "3.1"); // intentionally left out .1 + if ((gl_3_0_in_string || gl_3_1_in_string) && gl3stubInit()) { gl_extensions.ver[0] = 3; + if (gl_3_1_in_string) { + ILOG("OpenGL ES 3.1 support detected!\n"); + gl_extensions.ver[1] = 1; + } else { + ILOG("OpenGL ES 3.0 support detected!\n"); + } gl_extensions.GLES3 = true; - ILOG("Full OpenGL ES 3.0 support detected!\n"); // Though, let's ban Mali from the GLES 3 path for now, see #4078 if (strstr(renderer, "Mali") != 0) { gl_extensions.GLES3 = false; From 8c1a48b90caf69f558ad80a1ee5a56fb6721649e Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 22 Jul 2014 16:03:42 +1000 Subject: [PATCH 1199/1445] Qt: Inhibit screensaver for all platforms using Qt5. --- base/QtMain.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 0a6ba0846f..88da2b6c58 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -15,6 +15,7 @@ #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) #include +#include #endif #ifdef __SYMBIAN32__ @@ -122,11 +123,14 @@ static int mainInternal(QApplication &a) emugl->showFullScreen(); #endif EnableFZ(); -#ifdef __SYMBIAN32__ // Disable screensaver - QScopedPointer ssObject(new QSystemScreenSaver(emugl)); - ssObject->setScreenSaverInhibit(); +#ifdef __SYMBIAN32__ + QSystemScreenSaver ssObject(emugl); + ssObject.setScreenSaverInhibit(); QScopedPointer mediakeys(new SymbianMediaKeys()); +#elif QT_VERSION > QT_VERSION_CHECK(5, 0, 0) + QScreenSaver ssObject(emugl); + ssObject.setScreenSaverEnabled(false); #endif #ifdef QT_HAS_SDL From d826c7f1818157c0621d00fc9678974faa3b587b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 22 Jul 2014 09:54:24 +0200 Subject: [PATCH 1200/1445] Have PopupMultiChoice update their strings every frame --- ui/ui_screen.cpp | 4 ++++ ui/ui_screen.h | 41 +++++++++++++++++++++-------------------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index a6de1bebb5..420ded84a7 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -253,6 +253,10 @@ UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) { return UI::EVENT_DONE; } +void PopupMultiChoice::Update(const InputState &input_state) { + UpdateText(); +} + void PopupMultiChoice::UpdateText() { // Clamp the value to be safe. if (*value_ < minVal_ || *value_ > minVal_ + numChoices_ - 1) { diff --git a/ui/ui_screen.h b/ui/ui_screen.h index f536397601..b07dfd5775 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -93,9 +93,9 @@ public: virtual std::string tag() const override { return std::string("listpopup"); } protected: - virtual bool FillVertical() const { return false; } - virtual bool ShowButtons() const { return showButtons_; } - void CreatePopupContents(UI::ViewGroup *parent); + virtual bool FillVertical() const override { return false; } + virtual bool ShowButtons() const override { return showButtons_; } + virtual void CreatePopupContents(UI::ViewGroup *parent) override; UI::StringVectorListAdaptor adaptor_; UI::ListView *listView_; @@ -112,9 +112,9 @@ public: UI::Event OnChoice; protected: - virtual bool FillVertical() const { return false; } - virtual bool ShowButtons() const { return true; } - void CreatePopupContents(UI::ViewGroup *parent); + virtual bool FillVertical() const override { return false; } + virtual bool ShowButtons() const override { return true; } + virtual void CreatePopupContents(UI::ViewGroup *parent) override; private: std::string message_; @@ -129,14 +129,14 @@ class SliderPopupScreen : public PopupScreen { public: SliderPopupScreen(int *value, int minValue, int maxValue, const std::string &title, int step = 1) : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step) {} - void CreatePopupContents(ViewGroup *parent); + virtual void CreatePopupContents(ViewGroup *parent) override; Event OnChange; private: EventReturn OnDecrease(EventParams ¶ms); EventReturn OnIncrease(EventParams ¶ms); - virtual void OnCompleted(DialogResult result); + virtual void OnCompleted(DialogResult result) override; Slider *slider_; int *value_; int sliderValue_; @@ -149,12 +149,12 @@ class SliderFloatPopupScreen : public PopupScreen { public: SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title) : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue) {} - void CreatePopupContents(UI::ViewGroup *parent); + void CreatePopupContents(UI::ViewGroup *parent) override; Event OnChange; private: - virtual void OnCompleted(DialogResult result); + virtual void OnCompleted(DialogResult result) override; UI::SliderFloat *slider_; float sliderValue_; float *value_; @@ -166,7 +166,7 @@ class TextEditPopupScreen : public PopupScreen { public: TextEditPopupScreen(std::string *value, std::string &placeholder, const std::string &title, int maxLen) : PopupScreen(title, "OK", "Cancel"), value_(value), placeholder_(placeholder), maxLen_(maxLen) {} - void CreatePopupContents(ViewGroup *parent); + virtual void CreatePopupContents(ViewGroup *parent) override; Event OnChange; @@ -187,13 +187,14 @@ public: I18NCategory *category, ScreenManager *screenManager, UI::LayoutParams *layoutParams = 0) : UI::Choice(text, "", false, layoutParams), value_(value), choices_(choices), minVal_(minVal), numChoices_(numChoices), category_(category), screenManager_(screenManager) { - if (*value >= numChoices+minVal) *value = numChoices+minVal-1; - if (*value < minVal) *value = minVal; - OnClick.Handle(this, &PopupMultiChoice::HandleClick); - UpdateText(); + if (*value >= numChoices+minVal) *value = numChoices+minVal-1; + if (*value < minVal) *value = minVal; + OnClick.Handle(this, &PopupMultiChoice::HandleClick); + UpdateText(); } - virtual void Draw(UIContext &dc); + virtual void Draw(UIContext &dc) override; + virtual void Update(const InputState &input_state) override; UI::Event OnChoice; @@ -218,7 +219,7 @@ public: PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0); PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, int step, ScreenManager *screenManager, LayoutParams *layoutParams = 0); - void Draw(UIContext &dc); + virtual void Draw(UIContext &dc) override; Event OnChange; @@ -237,7 +238,7 @@ class PopupSliderChoiceFloat : public Choice { public: PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0); - void Draw(UIContext &dc); + virtual void Draw(UIContext &dc) override; Event OnChange; @@ -254,7 +255,7 @@ class PopupTextInputChoice: public Choice { public: PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams = 0); - void Draw(UIContext &dc); + virtual void Draw(UIContext &dc) override; Event OnChange; @@ -276,7 +277,7 @@ public: ChoiceWithValueDisplay(std::string *value, const std::string &text, I18NCategory *category, LayoutParams *layoutParams = 0) : Choice(text, layoutParams), sValue_(value), category_(category) { iValue_ = nullptr; } - void Draw(UIContext &dc); + virtual void Draw(UIContext &dc) override; private: int *iValue_; From 78941b087161ae684efac774508bd9d24b61dd5e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 22 Jul 2014 10:20:51 +0200 Subject: [PATCH 1201/1445] TextEdit: Clip to rect, scroll if caret outside rect --- ui/view.cpp | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index db3bfc9c5a..485b39c800 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -580,21 +580,36 @@ TextEdit::TextEdit(const std::string &text, const std::string &placeholderText, } void TextEdit::Draw(UIContext &dc) { + dc.PushScissor(bounds_); dc.SetFontStyle(dc.theme->uiFont); dc.FillRect(HasFocus() ? UI::Drawable(0x80000000) : UI::Drawable(0x30000000), bounds_); + + float textX = bounds_.x; + float w, h; + // Hack to find the caret position. Might want to find a better way... + dc.MeasureTextCount(dc.theme->uiFont, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT); + float caretX = w; + + if (caretX > bounds_.w) { + // Scroll text to the left if the caret won't fit. Not ideal but looks better than not scrolling it. + textX -= caretX - bounds_.w; + } + + caretX += textX; + + Bounds textBounds = bounds_; + textBounds.x = textX; + if (text_.empty()) { if (placeholderText_.size()) { dc.DrawTextRect(placeholderText_.c_str(), bounds_, 0x50FFFFFF, ALIGN_CENTER); } } else { - dc.DrawTextRect(text_.c_str(), bounds_, 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_LEFT); + dc.DrawTextRect(text_.c_str(), textBounds, 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_LEFT); } - // Hack to find the caret position. Might want to find a better way... - float w, h; - dc.MeasureTextCount(dc.theme->uiFont, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT); - float caretX = bounds_.x + w; dc.FillRect(UI::Drawable(0xFFFFFFFF), Bounds(caretX - 1, bounds_.y + 2, 3, bounds_.h - 4)); + dc.PopScissor(); } void TextEdit::GetContentDimensions(const UIContext &dc, float &w, float &h) const { @@ -667,9 +682,10 @@ void TextEdit::Key(const KeyInput &input) { { std::string clipText = System_GetProperty(SYSPROP_CLIPBOARD_TEXT); clipText = FirstLine(clipText); - if (clipText.size() > 32) { + size_t maxPaste = maxLen_ - text_.size(); + if (clipText.size() > maxPaste) { int end = 0; - while (end < 32) { + while (end < maxPaste) { u8_inc(clipText.c_str(), &end); } if (end > 0) { @@ -707,7 +723,9 @@ void TextEdit::Key(const KeyInput &input) { // Insert it! (todo: do it with a string insert) char buf[8]; buf[u8_wc_toutf8(buf, unichar)] = '\0'; - InsertAtCaret(buf); + if (strlen(buf) + text_.size() < maxLen_) { + InsertAtCaret(buf); + } } } } From 9f4f49be66d62e6dc064ff95d985b2d39b7ce47a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 22 Jul 2014 22:16:09 +0200 Subject: [PATCH 1202/1445] TextEdit: Add single undo, paste over the contents --- ui/view.cpp | 35 ++++++++++++++++++++++++----------- ui/view.h | 1 + 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 485b39c800..01b6e5ec4f 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -575,7 +575,7 @@ void TextView::Draw(UIContext &dc) { } TextEdit::TextEdit(const std::string &text, const std::string &placeholderText, LayoutParams *layoutParams) - : View(layoutParams), text_(text), placeholderText_(placeholderText), maxLen_(255), ctrlDown_(false) { + : View(layoutParams), text_(text), undo_(text), placeholderText_(placeholderText), maxLen_(255), ctrlDown_(false) { caret_ = (int)text_.size(); } @@ -659,6 +659,7 @@ void TextEdit::Key(const KeyInput &input) { if (caret_ < (int)text_.size()) { int endCaret = caret_; u8_inc(text_.c_str(), &endCaret); + undo_ = text_; text_.erase(text_.begin() + caret_, text_.begin() + endCaret); } break; @@ -666,6 +667,7 @@ void TextEdit::Key(const KeyInput &input) { if (caret_ > 0) { int begCaret = caret_; u8_dec(text_.c_str(), &begCaret); + undo_ = text_; text_.erase(text_.begin() + begCaret, text_.begin() + caret_); caret_--; } @@ -682,20 +684,30 @@ void TextEdit::Key(const KeyInput &input) { { std::string clipText = System_GetProperty(SYSPROP_CLIPBOARD_TEXT); clipText = FirstLine(clipText); - size_t maxPaste = maxLen_ - text_.size(); - if (clipText.size() > maxPaste) { - int end = 0; - while (end < maxPaste) { - u8_inc(clipText.c_str(), &end); + if (clipText.size()) { + // Until we get selection, replace the whole text + undo_ = text_; + text_.clear(); + caret_ = 0; + + size_t maxPaste = maxLen_ - text_.size(); + if (clipText.size() > maxPaste) { + int end = 0; + while (end < maxPaste) { + u8_inc(clipText.c_str(), &end); + } + if (end > 0) { + u8_dec(clipText.c_str(), &end); + } + clipText = clipText.substr(0, end); } - if (end > 0) { - u8_dec(clipText.c_str(), &end); - } - clipText = clipText.substr(0, end); + InsertAtCaret(clipText.c_str()); } - InsertAtCaret(clipText.c_str()); } break; + case NKCODE_Z: + text_ = undo_; + break; } } @@ -724,6 +736,7 @@ void TextEdit::Key(const KeyInput &input) { char buf[8]; buf[u8_wc_toutf8(buf, unichar)] = '\0'; if (strlen(buf) + text_.size() < maxLen_) { + undo_ = text_; InsertAtCaret(buf); } } diff --git a/ui/view.h b/ui/view.h index d02a18d560..4b006673e0 100644 --- a/ui/view.h +++ b/ui/view.h @@ -680,6 +680,7 @@ private: void InsertAtCaret(const char *text); std::string text_; + std::string undo_; std::string placeholderText_; int caret_; int maxLen_; From 79d189b545efd209e4ea221e307d94c21c6c7163 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 23 Jul 2014 12:50:03 +0200 Subject: [PATCH 1203/1445] atlastool buildfix (yeah, it's still a mess to build, I know) --- tools/atlastool.cpp | 10 ++++++++-- tools/atlastool/atlastool.vcxproj | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/atlastool.cpp b/tools/atlastool.cpp index 4102b44f72..874a28b4f5 100644 --- a/tools/atlastool.cpp +++ b/tools/atlastool.cpp @@ -14,7 +14,12 @@ #include #include #include FT_FREETYPE_H +#ifdef _WIN32 +// Hackery for our broken path structure +#include +#else #include +#endif #include #include #include @@ -363,8 +368,9 @@ void RasterizeFonts(const FontReferenceList fontRefs, vector &ranges, for (size_t i = 0, n = fontRefs.size(); i < n; ++i) { FT_Face &font = fonts[i]; if (FT_New_Face(freetype, fontRefs[i].file_.c_str(), 0, &font) != 0) { - printf("Failed to load file %s\n", fontRefs[i].file_.c_str()); - CHECK(false); + printf("Failed to load font file %s\n", fontRefs[i].file_.c_str()); + printf("bailing"); + exit(0); } printf("TTF info: %d glyphs, %08x flags, %d units, %d strikes\n", (int)font->num_glyphs, (int)font->face_flags, (int)font->units_per_EM, (int)font->num_fixed_sizes); diff --git a/tools/atlastool/atlastool.vcxproj b/tools/atlastool/atlastool.vcxproj index da873d853f..24469ad637 100644 --- a/tools/atlastool/atlastool.vcxproj +++ b/tools/atlastool/atlastool.vcxproj @@ -53,7 +53,7 @@ Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\ext\libpng17;..\..\..\ext\freetype\devel;..\..\..\ext\freetype\include;..\..;..\..\ext\SDL1.2\include;..\..\..\libpng;%(AdditionalIncludeDirectories); + ..\..\ext;..\..\..\ext\freetype\devel;..\..\..\ext\freetype\include;..\..;..\..\ext\SDL1.2\include;..\..\..\libpng;%(AdditionalIncludeDirectories); Console @@ -72,7 +72,7 @@ true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\ext\libpng17;..\..\..\ext\freetype\devel;..\..\..\ext\freetype\include;..\..;..\..\ext\SDL1.2\include;..\..\..\libpng;%(AdditionalIncludeDirectories); + ..\..\ext;..\..\..\ext\freetype\devel;..\..\..\ext\freetype\include;..\..;..\..\ext\SDL1.2\include;..\..\..\libpng;%(AdditionalIncludeDirectories); Console From 14141b5a9e44ecc01736ce9fc3e0970be236e79b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 23 Jul 2014 21:39:44 +0200 Subject: [PATCH 1204/1445] Add some hackery to work around the problem of textedit losing focus on click --- ui/view.cpp | 20 ++++++++++++++++---- ui/view.h | 5 +++-- ui/viewgroup.cpp | 8 +++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 01b6e5ec4f..0b63de5651 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -17,7 +17,7 @@ namespace UI { static View *focusedView; static bool focusMovementEnabled; - +bool focusForced; static recursive_mutex mutex_; const float ITEM_HEIGHT = 64.f; @@ -63,21 +63,25 @@ View *GetFocusedView() { return focusedView; } -void SetFocusedView(View *view) { +void SetFocusedView(View *view, bool force) { if (focusedView) { focusedView->FocusChanged(FF_LOSTFOCUS); } focusedView = view; if (focusedView) { focusedView->FocusChanged(FF_GOTFOCUS); + if (force) { + focusForced = true; + } } } void EnableFocusMovement(bool enable) { focusMovementEnabled = enable; if (!enable) { - if (focusedView) + if (focusedView) { focusedView->FocusChanged(FF_LOSTFOCUS); + } focusedView = 0; } } @@ -619,7 +623,7 @@ void TextEdit::GetContentDimensions(const UIContext &dc, float &w, float &h) con } // Handles both windows and unix line endings. -std::string FirstLine(const std::string &text) { +static std::string FirstLine(const std::string &text) { size_t pos = text.find("\r\n"); if (pos != std::string::npos) { return text.substr(0, pos); @@ -631,6 +635,14 @@ std::string FirstLine(const std::string &text) { return text; } +void TextEdit::Touch(const TouchInput &touch) { + if (touch.flags & TOUCH_DOWN) { + if (bounds_.Contains(touch.x, touch.y)) { + SetFocusedView(this, true); + } + } +} + void TextEdit::Key(const KeyInput &input) { if (!HasFocus()) return; diff --git a/ui/view.h b/ui/view.h index 4b006673e0..1010e99eef 100644 --- a/ui/view.h +++ b/ui/view.h @@ -43,7 +43,7 @@ class View; void EnableFocusMovement(bool enable); bool IsFocusMovementEnabled(); View *GetFocusedView(); -void SetFocusedView(View *view); +void SetFocusedView(View *view, bool force = false); enum DrawableType { DRAW_NOTHING, @@ -674,7 +674,8 @@ public: virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; virtual void Draw(UIContext &dc) override; - virtual void Key(const KeyInput &input) override; + virtual void Key(const KeyInput &key) override; + virtual void Touch(const TouchInput &touch) override; private: void InsertAtCaret(const char *text); diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index b19efb82f4..3d3068efa0 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -17,7 +17,7 @@ const float ITEM_HEIGHT = 64.f; static recursive_mutex focusLock; static std::vector focusMoves; - +extern bool focusForced; bool dragCaptured[MAX_POINTERS]; void CaptureDrag(int id) { @@ -1192,9 +1192,11 @@ static void ProcessHeldKeys(ViewGroup *root) { } bool TouchEvent(const TouchInput &touch, ViewGroup *root) { - EnableFocusMovement(false); - + focusForced = false; root->Touch(touch); + if ((touch.flags & TOUCH_DOWN) && !focusForced) { + EnableFocusMovement(false); + } return true; } From f339bda6e278c22d519f9d4e349995d4c2707fc2 Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 25 Jul 2014 14:41:23 +1000 Subject: [PATCH 1205/1445] SystemInfo is never installed by default, so make it optional. --- base/QtMain.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 88da2b6c58..da1b74800c 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -15,8 +15,10 @@ #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) #include +#ifdef QT_HAS_SYSTEMINFO #include #endif +#endif #ifdef __SYMBIAN32__ #include @@ -128,7 +130,7 @@ static int mainInternal(QApplication &a) QSystemScreenSaver ssObject(emugl); ssObject.setScreenSaverInhibit(); QScopedPointer mediakeys(new SymbianMediaKeys()); -#elif QT_VERSION > QT_VERSION_CHECK(5, 0, 0) +#elif defined(QT_HAS_SYSTEMINFO) QScreenSaver ssObject(emugl); ssObject.setScreenSaverEnabled(false); #endif From d3a88d42766391a3de595e3f1a9c5e88843b89ed Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 25 Jul 2014 17:15:59 +1000 Subject: [PATCH 1206/1445] Qt: Fix double ampersands in text. --- gfx_es2/draw_text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 8c9acc9f51..dff9a6a080 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -284,7 +284,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float painter.begin(&image); painter.setFont(*font); painter.setPen(color); - painter.drawText(image.rect(), Qt::AlignTop | Qt::AlignLeft, QString::fromUtf8(str)); + painter.drawText(image.rect(), Qt::AlignTop | Qt::AlignLeft, QString::fromUtf8(str).replace("&&", "&")); painter.end(); entry = new TextStringEntry(); From 8b634fade4200eb942078c9a92c81c0a2835fe04 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sat, 26 Jul 2014 01:35:49 +1000 Subject: [PATCH 1207/1445] Qt: Terminate the thread instead of quitting. Stops an annoying popup on OSX and should speed up exit on systems that didn't like the thread still running. --- base/QtMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index da1b74800c..fc29b26fba 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -174,7 +174,7 @@ static int mainInternal(QApplication &a) #endif int ret = a.exec(); #ifndef QT_HAS_SDL - thread->quit(); + thread->terminate(); #endif return ret; } From 86cd0ccf1abcec498803bd6f933d5d5916b6b5e7 Mon Sep 17 00:00:00 2001 From: The Dax Date: Thu, 31 Jul 2014 01:19:44 -0400 Subject: [PATCH 1208/1445] Add a new SYSPROP enum variable. --- base/NativeApp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/base/NativeApp.h b/base/NativeApp.h index a70f3094a1..19811ca731 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -124,6 +124,7 @@ enum SystemProperty { SYSPROP_LANGREGION, SYSPROP_CPUINFO, SYSPROP_CLIPBOARD_TEXT, + SYSPROP_GPUDRIVER_VERSION, // Available as Int: SYSPROP_SYSTEMVERSION, From 9f239b96852c49278f39d84e48bf0f49ca294a17 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 3 Aug 2014 19:09:45 -0700 Subject: [PATCH 1209/1445] Warning fix. --- gfx_es2/draw_buffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 2ba96081a0..4ce0b69ce9 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -401,7 +401,7 @@ void DrawBuffer::MeasureTextCount(int font, const char *text, int count, float * } void DrawBuffer::MeasureText(int font, const char *text, float *w, float *h) { - return MeasureTextCount(font, text, strlen(text), w, h); + return MeasureTextCount(font, text, (int)strlen(text), w, h); } void DrawBuffer::DrawTextShadow(int font, const char *text, float x, float y, Color color, int flags) { From ddf67c5f72d79a392eea1dbcbd76251352c7c671 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 3 Aug 2014 21:36:25 -0700 Subject: [PATCH 1210/1445] Add glStencilMask to glstate. --- gfx_es2/gl_state.cpp | 1 + gfx_es2/gl_state.h | 1 + 2 files changed, 2 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index c65b57a725..f656343d03 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -66,6 +66,7 @@ void OpenGLState::Restore() { stencilTest.restore(); count++; stencilOp.restore(); count++; stencilFunc.restore(); count++; + stencilMask.restore(); count++; dither.restore(); count++; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 157afc58c8..1217110801 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -280,6 +280,7 @@ public: BoolState stencilTest; STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp; STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; + STATE1(glStencilMask, GLuint, 0xFF) stencilMask; // Only works on Win32, all other platforms are "force-vsync" void SetVSyncInterval(int interval); // one of the above VSYNC, or a higher number for multi-frame waits (could be useful for 30hz games) From 130865577d7dc7167326a060df0c93e4ca46ab0d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 3 Aug 2014 18:18:09 -0700 Subject: [PATCH 1211/1445] Use glBlendEquationSeparate for ADD on alpha. --- gfx_es2/gl_state.cpp | 2 +- gfx_es2/gl_state.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index f656343d03..a240d0302f 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -44,7 +44,7 @@ void OpenGLState::Restore() { int count = 0; blend.restore(); count++; - blendEquation.restore(); count++; + blendEquationSeparate.restore(); count++; blendFuncSeparate.restore(); count++; blendColor.restore(); count++; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 1217110801..26fa639ac6 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -239,7 +239,7 @@ public: STATE4(glBlendFuncSeparate, GLenum, GLenum, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFuncSeparate; // On OpenGL ES, using minmax blend requires glBlendEquationEXT (in theory at least but I don't think it's true in practice) - STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; + STATE2(glBlendEquationSeparate, GLenum, GLenum, GL_FUNC_ADD, GL_FUNC_ADD) blendEquationSeparate; STATEFLOAT4(glBlendColor, 1.0f) blendColor; // Logic Ops. Not available on OpenGL ES at all. From deed84f9976e9afa855f3e4d8938c02e252dca58 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 3 Aug 2014 19:50:04 -0700 Subject: [PATCH 1212/1445] Reassert the add equation in UIContext. Otherwise it might use subtract or some other equation. Fixes another case of hrydgard/ppsspp#6678. --- ui/ui_context.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index fbdaacb596..5bac398568 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -37,6 +37,7 @@ void UIContext::Init(const GLSLProgram *uishader, const GLSLProgram *uishadernot void UIContext::Begin() { glstate.blend.enable(); glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blendEquationSeparate.set(GL_FUNC_ADD, GL_FUNC_ADD); glstate.cullFace.disable(); glstate.depthTest.disable(); glstate.dither.enable(); @@ -54,6 +55,7 @@ void UIContext::Begin() { void UIContext::BeginNoTex() { glstate.blend.enable(); glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blendEquationSeparate.set(GL_FUNC_ADD, GL_FUNC_ADD); glstate.cullFace.disable(); glstate.depthTest.disable(); glstate.dither.enable(); From fbafdb4e35bf75eb6f7434f18c7b799e51f4e0d2 Mon Sep 17 00:00:00 2001 From: Toad King Date: Tue, 5 Aug 2014 17:43:25 -0400 Subject: [PATCH 1213/1445] add ability to create opaque FBO objects from native opengl FBOs --- gfx_es2/fbo.cpp | 26 ++++++++++++++++++++++++++ gfx_es2/fbo.h | 6 ++++++ 2 files changed, 32 insertions(+) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 589256acf6..bd60a14d0b 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -38,6 +38,7 @@ struct FBO { int width; int height; FBOColorDepth colorDepth; + bool native_fbo; }; static FBO *g_overriddenBackbuffer; @@ -48,6 +49,7 @@ static FBO *g_overriddenBackbuffer; #ifndef USING_GLES2 FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { FBO *fbo = new FBO(); + fbo->native_fbo = false; fbo->width = width; fbo->height = height; fbo->colorDepth = colorDepth; @@ -129,6 +131,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F #endif FBO *fbo = new FBO(); + fbo->native_fbo = false; fbo->width = width; fbo->height = height; fbo->colorDepth = colorDepth; @@ -237,6 +240,24 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F return fbo; } +FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo) +{ + if (!fbo) + fbo = new FBO(); + + fbo->native_fbo = true; + fbo->handle = native_fbo; + fbo->color_texture = 0; + fbo->z_stencil_buffer = 0; + fbo->z_buffer = 0; + fbo->stencil_buffer = 0; + fbo->width = 0; + fbo->height = 0; + fbo->colorDepth = FBO_8888; + + return fbo; +} + void fbo_unbind() { if (g_overriddenBackbuffer) { fbo_bind_as_render_target(g_overriddenBackbuffer); @@ -312,6 +333,11 @@ void fbo_bind_color_as_texture(FBO *fbo, int color) { } void fbo_destroy(FBO *fbo) { + if (fbo->native_fbo) { + delete fbo; + return; + } + if (gl_extensions.FBO_ARB) { glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index e0651fd343..70e4e92794 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -4,6 +4,8 @@ // Very C-ish API because that's what I felt like, and it's cool to completely // hide the data from callers... +#include "gfx/gl_common.h" + struct FBO; @@ -24,6 +26,10 @@ enum FBOColorDepth { // On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth = FBO_8888); +// Create an opaque FBO from a native GL FBO, optionally reusing an existing FBO structure. +// Useful for overriding the backbuffer FBO that is generated outside of this wrapper. +FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo = NULL); + // These functions should be self explanatory. void fbo_bind_as_render_target(FBO *fbo); // color must be 0, for now. From 69e66df07e9a4000cedee9faa96e9f1e1c30a4cd Mon Sep 17 00:00:00 2001 From: The Dax Date: Sat, 16 Aug 2014 15:07:06 -0400 Subject: [PATCH 1214/1445] Update PopupSliderChoiceFloat to have increment/decrement buttons, and stepping. --- ui/ui_screen.cpp | 26 ++++++++++++++++++++++++-- ui/ui_screen.h | 9 +++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 420ded84a7..16fdbae3b1 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -304,6 +304,11 @@ PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, flo OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); } +PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, float step, ScreenManager *screenManager, LayoutParams *layoutParams) + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step), screenManager_(screenManager) { + OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); +} + EventReturn PopupSliderChoice::HandleClick(EventParams &e) { SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_, step_); popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange); @@ -330,7 +335,7 @@ void PopupSliderChoice::Draw(UIContext &dc) { } EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) { - SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_); + SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_, step_); popupScreen->OnChange.Handle(this, &PopupSliderChoiceFloat::HandleChange); screenManager_->push(popupScreen); return EVENT_DONE; @@ -381,10 +386,27 @@ void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; sliderValue_ = *value_; - slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5)))); + LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 5)))); + slider_ = new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(1.0f)); + lin->Add(slider_); + lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderFloatPopupScreen::OnDecrease); + lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderFloatPopupScreen::OnIncrease); + // slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5)))); UI::SetFocusedView(slider_); } +EventReturn SliderFloatPopupScreen::OnDecrease(EventParams ¶ms) { + sliderValue_ -= step_; + slider_->Clamp(); + return EVENT_DONE; +} + +EventReturn SliderFloatPopupScreen::OnIncrease(EventParams ¶ms) { + sliderValue_ += step_; + slider_->Clamp(); + return EVENT_DONE; +} + void SliderPopupScreen::OnCompleted(DialogResult result) { if (result == DR_OK) { *value_ = sliderValue_; diff --git a/ui/ui_screen.h b/ui/ui_screen.h index b07dfd5775..868de6580e 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -147,19 +147,22 @@ private: class SliderFloatPopupScreen : public PopupScreen { public: - SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title) - : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue) {} + SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title, float step = 1.0f) + : PopupScreen(title, "OK", "Cancel"), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step) {} void CreatePopupContents(UI::ViewGroup *parent) override; Event OnChange; private: + EventReturn OnIncrease(EventParams ¶ms); + EventReturn OnDecrease(EventParams ¶ms); virtual void OnCompleted(DialogResult result) override; UI::SliderFloat *slider_; float sliderValue_; float *value_; float minValue_; float maxValue_; + float step_; }; class TextEditPopupScreen : public PopupScreen { @@ -237,6 +240,7 @@ private: class PopupSliderChoiceFloat : public Choice { public: PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams = 0); + PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, float step, ScreenManager *screenManager, LayoutParams *layoutParams = 0); virtual void Draw(UIContext &dc) override; @@ -248,6 +252,7 @@ private: float *value_; float minValue_; float maxValue_; + float step_; ScreenManager *screenManager_; }; From cfae07f72b99640e13a01db0699d9587565d5fc5 Mon Sep 17 00:00:00 2001 From: The Dax Date: Sat, 16 Aug 2014 15:14:38 -0400 Subject: [PATCH 1215/1445] Need to initialise step_ here, too. --- ui/ui_screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 16fdbae3b1..66f6eec6bc 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -300,7 +300,7 @@ PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, con } PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams) - : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) { + : Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(1.0f), screenManager_(screenManager) { OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick); } From 14d2fa9a39157691db21eb2d0e8a0f1908666e18 Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 21 Aug 2014 03:46:00 +1000 Subject: [PATCH 1216/1445] Drop the thread from Qt audio loop. Makes exit cleaner. Probably needs to be reworked or replaced with SDL it seems. --- base/QtMain.cpp | 13 ++----------- base/QtMain.h | 6 +++--- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index fc29b26fba..3b475bd1b2 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -162,21 +162,12 @@ static int mainInternal(QApplication &a) SDL_CloseAudio(); } } - - // Audio must be unpaused _after_ NativeInit() SDL_PauseAudio(0); #else - QScopedPointer thread(new QThread); QScopedPointer audio(new MainAudio()); - audio->moveToThread(thread.data()); - QObject::connect(thread.data(), SIGNAL(started()), audio.data(), SLOT(run())); - thread->start(); + audio->run(); #endif - int ret = a.exec(); -#ifndef QT_HAS_SDL - thread->terminate(); -#endif - return ret; + return a.exec(); } #ifndef QT_HAS_SDL diff --git a/base/QtMain.h b/base/QtMain.h index 3ded3ddbc1..85685a4a50 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -269,19 +269,19 @@ public slots: fmt.setSampleSize(AUDIO_SAMPLESIZE); fmt.setByteOrder(QAudioFormat::LittleEndian); fmt.setSampleType(QAudioFormat::SignedInt); - mixlen = 5*2*AUDIO_CHANNELS*AUDIO_SAMPLES; + mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; mixbuf = (char*)malloc(mixlen); output = new QAudioOutput(fmt); output->setBufferSize(mixlen); feed = output->start(); if (feed != NULL) - timer = startTimer(1000*AUDIO_SAMPLES / AUDIO_FREQ); + timer = startTimer((1000*AUDIO_SAMPLES) / AUDIO_FREQ); } protected: void timerEvent(QTimerEvent *) { memset(mixbuf, 0, mixlen); - size_t frames = NativeMix((short *)mixbuf, 5*AUDIO_SAMPLES); + size_t frames = NativeMix((short *)mixbuf, AUDIO_SAMPLES); if (frames > 0) feed->write(mixbuf, sizeof(short) * 2 * frames); } From cea002e39a2c01de18018292c39e686ab3ffafb5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 21 Aug 2014 10:21:37 +0200 Subject: [PATCH 1217/1445] Update GLEW with GL4.4 support --- ext/glew/GL/glew.h | 844 ++++++++++----- ext/glew/GL/glxew.h | 95 +- ext/glew/GL/wglew.h | 17 + ext/glew/glew.c | 2408 ++++++++++++++++++++++++----------------- ext/glew/glewinfo.c | 305 +++++- ext/glew/visualinfo.c | 69 +- 6 files changed, 2456 insertions(+), 1282 deletions(-) diff --git a/ext/glew/GL/glew.h b/ext/glew/GL/glew.h index a4ef6981dd..bee952d37d 100644 --- a/ext/glew/GL/glew.h +++ b/ext/glew/GL/glew.h @@ -1,5 +1,6 @@ /* ** The OpenGL Extension Wrangler Library +** Copyright (C) 2008-2014, Nigel Stewart ** Copyright (C) 2002-2008, Milan Ikits ** Copyright (C) 2002-2008, Marcelo E. Magallon ** Copyright (C) 2002, Lev Povalahev @@ -76,10 +77,6 @@ ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ -#ifndef GLEW_STATIC -#define GLEW_STATIC -#endif - #ifndef __glew_h__ #define __glew_h__ #define __GLEW_H__ @@ -120,13 +117,24 @@ * GL needs GLAPI and GLAPIENTRY, GLU needs APIENTRY, CALLBACK, and wchar_t * defined properly. */ -/* */ -#ifndef APIENTRY +/* and */ +#ifdef APIENTRY +# ifndef GLAPIENTRY +# define GLAPIENTRY APIENTRY +# endif +# ifndef GLEWAPIENTRY +# define GLEWAPIENTRY APIENTRY +# endif +#else #define GLEW_APIENTRY_DEFINED -# if defined(__MINGW32__) || defined(__CYGWIN__) -# define APIENTRY __stdcall -# elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) +# if defined(__MINGW32__) || defined(__CYGWIN__) || (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) # define APIENTRY __stdcall +# ifndef GLAPIENTRY +# define GLAPIENTRY __stdcall +# endif +# ifndef GLEWAPIENTRY +# define GLEWAPIENTRY __stdcall +# endif # else # define APIENTRY # endif @@ -183,14 +191,6 @@ typedef _W64 int ptrdiff_t; # endif #endif -#ifndef GLAPIENTRY -#define GLAPIENTRY APIENTRY -#endif - -#ifndef GLEWAPIENTRY -#define GLEWAPIENTRY APIENTRY -#endif - /* * GLEW_STATIC is defined for static library. * GLEW_BUILD is defined for building the DLL library. @@ -252,6 +252,8 @@ typedef _W64 int ptrdiff_t; #define GLAPI extern #endif +#endif /* _WIN32 */ + #ifndef GLAPIENTRY #define GLAPIENTRY #endif @@ -260,8 +262,6 @@ typedef _W64 int ptrdiff_t; #define GLEWAPIENTRY #endif -#endif /* _WIN32 */ - #ifdef __cplusplus extern "C" { #endif @@ -850,7 +850,7 @@ GLAPI void GLAPIENTRY glBindTexture (GLenum target, GLuint texture); GLAPI void GLAPIENTRY glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); GLAPI void GLAPIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); GLAPI void GLAPIENTRY glCallList (GLuint list); -GLAPI void GLAPIENTRY glCallLists (GLsizei n, GLenum type, const GLvoid *lists); +GLAPI void GLAPIENTRY glCallLists (GLsizei n, GLenum type, const void *lists); GLAPI void GLAPIENTRY glClear (GLbitfield mask); GLAPI void GLAPIENTRY glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); GLAPI void GLAPIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); @@ -892,7 +892,7 @@ GLAPI void GLAPIENTRY glColor4us (GLushort red, GLushort green, GLushort blue, G GLAPI void GLAPIENTRY glColor4usv (const GLushort *v); GLAPI void GLAPIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); GLAPI void GLAPIENTRY glColorMaterial (GLenum face, GLenum mode); -GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer); GLAPI void GLAPIENTRY glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); GLAPI void GLAPIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); GLAPI void GLAPIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); @@ -908,10 +908,10 @@ GLAPI void GLAPIENTRY glDisable (GLenum cap); GLAPI void GLAPIENTRY glDisableClientState (GLenum array); GLAPI void GLAPIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); GLAPI void GLAPIENTRY glDrawBuffer (GLenum mode); -GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -GLAPI void GLAPIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); +GLAPI void GLAPIENTRY glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); GLAPI void GLAPIENTRY glEdgeFlag (GLboolean flag); -GLAPI void GLAPIENTRY glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glEdgeFlagPointer (GLsizei stride, const void *pointer); GLAPI void GLAPIENTRY glEdgeFlagv (const GLboolean *flag); GLAPI void GLAPIENTRY glEnable (GLenum cap); GLAPI void GLAPIENTRY glEnableClientState (GLenum array); @@ -956,7 +956,7 @@ GLAPI void GLAPIENTRY glGetMaterialiv (GLenum face, GLenum pname, GLint *params) GLAPI void GLAPIENTRY glGetPixelMapfv (GLenum map, GLfloat *values); GLAPI void GLAPIENTRY glGetPixelMapuiv (GLenum map, GLuint *values); GLAPI void GLAPIENTRY glGetPixelMapusv (GLenum map, GLushort *values); -GLAPI void GLAPIENTRY glGetPointerv (GLenum pname, GLvoid* *params); +GLAPI void GLAPIENTRY glGetPointerv (GLenum pname, void* *params); GLAPI void GLAPIENTRY glGetPolygonStipple (GLubyte *mask); GLAPI const GLubyte * GLAPIENTRY glGetString (GLenum name); GLAPI void GLAPIENTRY glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params); @@ -964,14 +964,14 @@ GLAPI void GLAPIENTRY glGetTexEnviv (GLenum target, GLenum pname, GLint *params) GLAPI void GLAPIENTRY glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params); GLAPI void GLAPIENTRY glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params); GLAPI void GLAPIENTRY glGetTexGeniv (GLenum coord, GLenum pname, GLint *params); -GLAPI void GLAPIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +GLAPI void GLAPIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, void *pixels); GLAPI void GLAPIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); GLAPI void GLAPIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); GLAPI void GLAPIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); GLAPI void GLAPIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); GLAPI void GLAPIENTRY glHint (GLenum target, GLenum mode); GLAPI void GLAPIENTRY glIndexMask (GLuint mask); -GLAPI void GLAPIENTRY glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glIndexPointer (GLenum type, GLsizei stride, const void *pointer); GLAPI void GLAPIENTRY glIndexd (GLdouble c); GLAPI void GLAPIENTRY glIndexdv (const GLdouble *c); GLAPI void GLAPIENTRY glIndexf (GLfloat c); @@ -983,7 +983,7 @@ GLAPI void GLAPIENTRY glIndexsv (const GLshort *c); GLAPI void GLAPIENTRY glIndexub (GLubyte c); GLAPI void GLAPIENTRY glIndexubv (const GLubyte *c); GLAPI void GLAPIENTRY glInitNames (void); -GLAPI void GLAPIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glInterleavedArrays (GLenum format, GLsizei stride, const void *pointer); GLAPI GLboolean GLAPIENTRY glIsEnabled (GLenum cap); GLAPI GLboolean GLAPIENTRY glIsList (GLuint list); GLAPI GLboolean GLAPIENTRY glIsTexture (GLuint texture); @@ -1029,7 +1029,7 @@ GLAPI void GLAPIENTRY glNormal3i (GLint nx, GLint ny, GLint nz); GLAPI void GLAPIENTRY glNormal3iv (const GLint *v); GLAPI void GLAPIENTRY glNormal3s (GLshort nx, GLshort ny, GLshort nz); GLAPI void GLAPIENTRY glNormal3sv (const GLshort *v); -GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glNormalPointer (GLenum type, GLsizei stride, const void *pointer); GLAPI void GLAPIENTRY glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); GLAPI void GLAPIENTRY glPassThrough (GLfloat token); GLAPI void GLAPIENTRY glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values); @@ -1078,7 +1078,7 @@ GLAPI void GLAPIENTRY glRasterPos4iv (const GLint *v); GLAPI void GLAPIENTRY glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w); GLAPI void GLAPIENTRY glRasterPos4sv (const GLshort *v); GLAPI void GLAPIENTRY glReadBuffer (GLenum mode); -GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +GLAPI void GLAPIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); GLAPI void GLAPIENTRY glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); GLAPI void GLAPIENTRY glRectdv (const GLdouble *v1, const GLdouble *v2); GLAPI void GLAPIENTRY glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); @@ -1130,7 +1130,7 @@ GLAPI void GLAPIENTRY glTexCoord4i (GLint s, GLint t, GLint r, GLint q); GLAPI void GLAPIENTRY glTexCoord4iv (const GLint *v); GLAPI void GLAPIENTRY glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q); GLAPI void GLAPIENTRY glTexCoord4sv (const GLshort *v); -GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const void *pointer); GLAPI void GLAPIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param); GLAPI void GLAPIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params); GLAPI void GLAPIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param); @@ -1141,14 +1141,14 @@ GLAPI void GLAPIENTRY glTexGenf (GLenum coord, GLenum pname, GLfloat param); GLAPI void GLAPIENTRY glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params); GLAPI void GLAPIENTRY glTexGeni (GLenum coord, GLenum pname, GLint param); GLAPI void GLAPIENTRY glTexGeniv (GLenum coord, GLenum pname, const GLint *params); -GLAPI void GLAPIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI void GLAPIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); GLAPI void GLAPIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); GLAPI void GLAPIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); GLAPI void GLAPIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); GLAPI void GLAPIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); -GLAPI void GLAPIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLAPI void GLAPIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +GLAPI void GLAPIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); GLAPI void GLAPIENTRY glTranslated (GLdouble x, GLdouble y, GLdouble z); GLAPI void GLAPIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z); GLAPI void GLAPIENTRY glVertex2d (GLdouble x, GLdouble y); @@ -1175,7 +1175,7 @@ GLAPI void GLAPIENTRY glVertex4i (GLint x, GLint y, GLint z, GLint w); GLAPI void GLAPIENTRY glVertex4iv (const GLint *v); GLAPI void GLAPIENTRY glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w); GLAPI void GLAPIENTRY glVertex4sv (const GLshort *v); -GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GLAPI void GLAPIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const void *pointer); GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); #define GLEW_VERSION_1_1 GLEW_GET_VAR(__GLEW_VERSION_1_1) @@ -1184,6 +1184,15 @@ GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei heigh /* ---------------------------------- GLU ---------------------------------- */ +#ifndef GLEW_NO_GLU +# ifdef __APPLE__ +# include +# if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +# define GLEW_NO_GLU +# endif +# endif +#endif + #ifndef GLEW_NO_GLU /* this is where we can safely include GLU */ # if defined(__APPLE__) && defined(__MACH__) @@ -1240,9 +1249,9 @@ GLAPI void GLAPIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei heigh #define GL_ALIASED_LINE_WIDTH_RANGE 0x846E typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); -typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); #define glCopyTexSubImage3D GLEW_GET_FUN(__glewCopyTexSubImage3D) #define glDrawRangeElements GLEW_GET_FUN(__glewDrawRangeElements) @@ -1366,13 +1375,13 @@ typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture); typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, GLvoid *img); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint lod, void *img); typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); typedef void (GLAPIENTRY * PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat m[16]); typedef void (GLAPIENTRY * PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble m[16]); @@ -1510,13 +1519,13 @@ typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean i typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode); typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const void *pointer); typedef void (GLAPIENTRY * PFNGLFOGCOORDDPROC) (GLdouble coord); typedef void (GLAPIENTRY * PFNGLFOGCOORDDVPROC) (const GLdouble *coord); typedef void (GLAPIENTRY * PFNGLFOGCOORDFPROC) (GLfloat coord); typedef void (GLAPIENTRY * PFNGLFOGCOORDFVPROC) (const GLfloat *coord); typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei drawcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const* indices, GLsizei drawcount); typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); @@ -1537,7 +1546,7 @@ typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer); typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); typedef void (GLAPIENTRY * PFNGLWINDOWPOS2DVPROC) (const GLdouble *p); typedef void (GLAPIENTRY * PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); @@ -1612,18 +1621,18 @@ typedef void (GLAPIENTRY * PFNGLWINDOWPOS3SVPROC) (const GLshort *p); #ifndef GL_VERSION_1_5 #define GL_VERSION_1_5 1 -#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE +#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE #define GL_FOG_COORD GL_FOG_COORDINATE #define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY -#define GL_SRC0_RGB GL_SOURCE0_RGB -#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER -#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE -#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA -#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE -#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE -#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA -#define GL_SRC1_RGB GL_SOURCE1_RGB #define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING +#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER +#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE +#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE +#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE +#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA +#define GL_SRC0_RGB GL_SOURCE0_RGB +#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA +#define GL_SRC1_RGB GL_SOURCE1_RGB #define GL_SRC2_ALPHA GL_SOURCE2_ALPHA #define GL_SRC2_RGB GL_SOURCE2_RGB #define GL_BUFFER_SIZE 0x8764 @@ -1668,22 +1677,22 @@ typedef ptrdiff_t GLsizeiptr; typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); -typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void* data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void* data); typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers); typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* ids); typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target); typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers); typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* ids); typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid** params); -typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void** params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void* data); typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params); typedef void (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint* params); typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer); typedef GLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id); -typedef GLvoid* (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +typedef void* (GLAPIENTRY * PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERPROC) (GLenum target); #define glBeginQuery GLEW_GET_FUN(__glewBeginQuery) @@ -1824,14 +1833,14 @@ typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, G typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name); typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint, GLenum, GLvoid**); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint, GLenum, void**); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVPROC) (GLuint, GLenum, GLdouble*); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint, GLenum, GLfloat*); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint, GLenum, GLint*); typedef GLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program); typedef GLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader); typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program); -typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths); +typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const* string, const GLint* length); typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); typedef void (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum, GLuint); typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); @@ -1892,7 +1901,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshor typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); #define glAttachShader GLEW_GET_FUN(__glewAttachShader) #define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation) @@ -2044,14 +2053,14 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei #ifndef GL_VERSION_3_0 #define GL_VERSION_3_0 1 -#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES -#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5 -#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1 -#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3 -#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB #define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0 -#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4 +#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1 #define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2 +#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3 +#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4 +#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5 +#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB +#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES #define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS #define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 #define GL_MAJOR_VERSION 0x821B @@ -2175,7 +2184,7 @@ typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint, GLenum, GLuint typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDIPROC) (GLenum, GLuint); typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIIVPROC) (GLenum, GLenum, const GLint*); typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIUIVPROC) (GLenum, GLenum, const GLuint*); -typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint, GLsizei, const GLchar **, GLenum); +typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint, GLsizei, const GLchar *const*, GLenum); typedef void (GLAPIENTRY * PFNGLUNIFORM1UIPROC) (GLint, GLuint); typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVPROC) (GLint, GLsizei, const GLuint*); typedef void (GLAPIENTRY * PFNGLUNIFORM2UIPROC) (GLint, GLuint, GLuint); @@ -2204,7 +2213,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVPROC) (GLuint, const GLubyte*); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIPROC) (GLuint, GLuint, GLuint, GLuint, GLuint); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVPROC) (GLuint, const GLuint*); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVPROC) (GLuint, const GLushort*); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint, GLint, GLenum, GLsizei, const GLvoid*); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint, GLint, GLenum, GLsizei, const void*); #define glBeginConditionalRender GLEW_GET_FUN(__glewBeginConditionalRender) #define glBeginTransformFeedback GLEW_GET_FUN(__glewBeginTransformFeedback) @@ -2307,7 +2316,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint, GLint, GLenum #define GL_BUFFER_MAP_OFFSET 0x9121 typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum, GLint, GLsizei, GLsizei); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum, GLsizei, GLenum, const GLvoid*, GLsizei); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum, GLsizei, GLenum, const void*, GLsizei); typedef void (GLAPIENTRY * PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint); typedef void (GLAPIENTRY * PFNGLTEXBUFFERPROC) (GLenum, GLenum, GLuint); @@ -2450,7 +2459,9 @@ typedef void (GLAPIENTRY * PFNGLMINSAMPLESHADINGPROC) (GLclampf value); #ifndef GL_VERSION_4_4 #define GL_VERSION_4_4 1 +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 #define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 +#define GL_TEXTURE_BUFFER_BINDING 0x8C2A #define GLEW_VERSION_4_4 GLEW_GET_VAR(__GLEW_VERSION_4_4) @@ -2536,9 +2547,9 @@ typedef void (GLAPIENTRY * PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); #define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F #define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150 -typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); +typedef void (GLAPIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar* message, void* userParam); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, GLvoid *userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void *userParam); typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar* buf); typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum* categories, GLuint* severities, GLuint* ids, GLsizei* lengths, GLchar* message); @@ -2583,6 +2594,24 @@ typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GL #endif /* GL_AMD_draw_buffers_blend */ +/* --------------------------- GL_AMD_gcn_shader --------------------------- */ + +#ifndef GL_AMD_gcn_shader +#define GL_AMD_gcn_shader 1 + +#define GLEW_AMD_gcn_shader GLEW_GET_VAR(__GLEW_AMD_gcn_shader) + +#endif /* GL_AMD_gcn_shader */ + +/* ------------------------ GL_AMD_gpu_shader_int64 ------------------------ */ + +#ifndef GL_AMD_gpu_shader_int64 +#define GL_AMD_gpu_shader_int64 1 + +#define GLEW_AMD_gpu_shader_int64 GLEW_GET_VAR(__GLEW_AMD_gpu_shader_int64) + +#endif /* GL_AMD_gpu_shader_int64 */ + /* ---------------------- GL_AMD_interleaved_elements ---------------------- */ #ifndef GL_AMD_interleaved_elements @@ -2611,8 +2640,8 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPARAMETERIAMDPROC) (GLuint index, GL #ifndef GL_AMD_multi_draw_indirect #define GL_AMD_multi_draw_indirect 1 -typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const GLvoid *indirect, GLsizei primcount, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLsizei primcount, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const void *indirect, GLsizei primcount, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei primcount, GLsizei stride); #define glMultiDrawArraysIndirectAMD GLEW_GET_FUN(__glewMultiDrawArraysIndirectAMD) #define glMultiDrawElementsIndirectAMD GLEW_GET_FUN(__glewMultiDrawElementsIndirectAMD) @@ -2644,6 +2673,26 @@ typedef GLboolean (GLAPIENTRY * PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint n #endif /* GL_AMD_name_gen_delete */ +/* ---------------------- GL_AMD_occlusion_query_event --------------------- */ + +#ifndef GL_AMD_occlusion_query_event +#define GL_AMD_occlusion_query_event 1 + +#define GL_QUERY_DEPTH_PASS_EVENT_BIT_AMD 0x00000001 +#define GL_QUERY_DEPTH_FAIL_EVENT_BIT_AMD 0x00000002 +#define GL_QUERY_STENCIL_FAIL_EVENT_BIT_AMD 0x00000004 +#define GL_QUERY_DEPTH_BOUNDS_FAIL_EVENT_BIT_AMD 0x00000008 +#define GL_OCCLUSION_QUERY_EVENT_MASK_AMD 0x874F +#define GL_QUERY_ALL_EVENT_BITS_AMD 0xFFFFFFFF + +typedef void (GLAPIENTRY * PFNGLQUERYOBJECTPARAMETERUIAMDPROC) (GLenum target, GLuint id, GLenum pname, GLuint param); + +#define glQueryObjectParameteruiAMD GLEW_GET_FUN(__glewQueryObjectParameteruiAMD) + +#define GLEW_AMD_occlusion_query_event GLEW_GET_VAR(__GLEW_AMD_occlusion_query_event) + +#endif /* GL_AMD_occlusion_query_event */ + /* ----------------------- GL_AMD_performance_monitor ---------------------- */ #ifndef GL_AMD_performance_monitor @@ -2662,7 +2711,7 @@ typedef void (GLAPIENTRY * PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint* m typedef void (GLAPIENTRY * PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); typedef void (GLAPIENTRY * PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint* monitors); typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint* data, GLint *bytesWritten); -typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data); +typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data); typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei* length, GLchar *counterString); typedef void (GLAPIENTRY * PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint* numCounters, GLint *maxActiveCounters, GLsizei countersSize, GLuint *counters); typedef void (GLAPIENTRY * PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei* length, GLchar *groupString); @@ -2735,6 +2784,15 @@ typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint i #endif /* GL_AMD_seamless_cubemap_per_texture */ +/* -------------------- GL_AMD_shader_atomic_counter_ops ------------------- */ + +#ifndef GL_AMD_shader_atomic_counter_ops +#define GL_AMD_shader_atomic_counter_ops 1 + +#define GLEW_AMD_shader_atomic_counter_ops GLEW_GET_VAR(__GLEW_AMD_shader_atomic_counter_ops) + +#endif /* GL_AMD_shader_atomic_counter_ops */ + /* ---------------------- GL_AMD_shader_stencil_export --------------------- */ #ifndef GL_AMD_shader_stencil_export @@ -2744,6 +2802,15 @@ typedef void (GLAPIENTRY * PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint i #endif /* GL_AMD_shader_stencil_export */ +/* ------------------- GL_AMD_shader_stencil_value_export ------------------ */ + +#ifndef GL_AMD_shader_stencil_value_export +#define GL_AMD_shader_stencil_value_export 1 + +#define GLEW_AMD_shader_stencil_value_export GLEW_GET_VAR(__GLEW_AMD_shader_stencil_value_export) + +#endif /* GL_AMD_shader_stencil_value_export */ + /* ---------------------- GL_AMD_shader_trinary_minmax --------------------- */ #ifndef GL_AMD_shader_trinary_minmax @@ -2814,6 +2881,17 @@ typedef void (GLAPIENTRY * PFNGLSTENCILOPVALUEAMDPROC) (GLenum face, GLuint valu #endif /* GL_AMD_transform_feedback3_lines_triangles */ +/* ----------------------- GL_AMD_transform_feedback4 ---------------------- */ + +#ifndef GL_AMD_transform_feedback4 +#define GL_AMD_transform_feedback4 1 + +#define GL_STREAM_RASTERIZATION_AMD 0x91A0 + +#define GLEW_AMD_transform_feedback4 GLEW_GET_VAR(__GLEW_AMD_transform_feedback4) + +#endif /* GL_AMD_transform_feedback4 */ + /* ----------------------- GL_AMD_vertex_shader_layer ---------------------- */ #ifndef GL_AMD_vertex_shader_layer @@ -2907,7 +2985,7 @@ typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum #define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); #define glDrawArraysInstancedANGLE GLEW_GET_FUN(__glewDrawArraysInstancedANGLE) @@ -3082,7 +3160,7 @@ typedef void (GLAPIENTRY * PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shad typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); -typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void *pointer); typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); typedef void (GLAPIENTRY * PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint* first, const GLsizei *count, GLsizei primcount); @@ -3211,6 +3289,7 @@ typedef GLenum (GLAPIENTRY * PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType #define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA #define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB #define GL_RGB_422_APPLE 0x8A1F +#define GL_RGB_RAW_422_APPLE 0x8A51 #define GLEW_APPLE_rgb_422 GLEW_GET_VAR(__GLEW_APPLE_rgb_422) @@ -3251,8 +3330,8 @@ typedef GLenum (GLAPIENTRY * PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType #define GL_STORAGE_CACHED_APPLE 0x85BE #define GL_STORAGE_SHARED_APPLE 0x85BF -typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, GLvoid **params); -typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, void **params); +typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, void *pointer); #define glGetTexParameterPointervAPPLE GLEW_GET_FUN(__glewGetTexParameterPointervAPPLE) #define glTextureRangeAPPLE GLEW_GET_FUN(__glewTextureRangeAPPLE) @@ -3307,9 +3386,9 @@ typedef GLboolean (GLAPIENTRY * PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); #define GL_STORAGE_CACHED_APPLE 0x85BE #define GL_STORAGE_SHARED_APPLE 0x85BF -typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer); #define glFlushVertexArrayRangeAPPLE GLEW_GET_FUN(__glewFlushVertexArrayRangeAPPLE) #define glVertexArrayParameteriAPPLE GLEW_GET_FUN(__glewVertexArrayParameteriAPPLE) @@ -3394,7 +3473,7 @@ typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf d); typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf n, GLclampf f); typedef void (GLAPIENTRY * PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint *precision); typedef void (GLAPIENTRY * PFNGLRELEASESHADERCOMPILERPROC) (void); -typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* shaders, GLenum binaryformat, const GLvoid*binary, GLsizei length); +typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* shaders, GLenum binaryformat, const void*binary, GLsizei length); #define glClearDepthf GLEW_GET_FUN(__glewClearDepthf) #define glDepthRangef GLEW_GET_FUN(__glewDepthRangef) @@ -3445,8 +3524,8 @@ typedef void (GLAPIENTRY * PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint* #define GL_ARB_base_instance 1 typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount, GLuint baseinstance); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLuint baseinstance); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex, GLuint baseinstance); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount, GLuint baseinstance); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount, GLint basevertex, GLuint baseinstance); #define glDrawArraysInstancedBaseInstance GLEW_GET_FUN(__glewDrawArraysInstancedBaseInstance) #define glDrawElementsInstancedBaseInstance GLEW_GET_FUN(__glewDrawElementsInstancedBaseInstance) @@ -3536,8 +3615,8 @@ typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GL #define GL_BUFFER_IMMUTABLE_STORAGE 0x821F #define GL_BUFFER_STORAGE_FLAGS 0x8220 -typedef void (GLAPIENTRY * PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLbitfield flags); -typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSTORAGEEXTPROC) (GLuint buffer, GLsizeiptr size, const GLvoid* data, GLbitfield flags); +typedef void (GLAPIENTRY * PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSTORAGEEXTPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags); #define glBufferStorage GLEW_GET_FUN(__glewBufferStorage) #define glNamedBufferStorageEXT GLEW_GET_FUN(__glewNamedBufferStorageEXT) @@ -3570,10 +3649,10 @@ typedef GLsync (GLAPIENTRY * PFNGLCREATESYNCFROMCLEVENTARBPROC) (cl_context cont #ifndef GL_ARB_clear_buffer_object #define GL_ARB_clear_buffer_object 1 -typedef void (GLAPIENTRY * PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data); -typedef void (GLAPIENTRY * PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data); -typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data); -typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data); +typedef void (GLAPIENTRY * PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); +typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data); +typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); #define glClearBufferData GLEW_GET_FUN(__glewClearBufferData) #define glClearBufferSubData GLEW_GET_FUN(__glewClearBufferSubData) @@ -3591,8 +3670,8 @@ typedef void (GLAPIENTRY * PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, #define GL_CLEAR_TEXTURE 0x9365 -typedef void (GLAPIENTRY * PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const GLvoid* data); -typedef void (GLAPIENTRY * PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* data); +typedef void (GLAPIENTRY * PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data); +typedef void (GLAPIENTRY * PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data); #define glClearTexImage GLEW_GET_FUN(__glewClearTexImage) #define glClearTexSubImage GLEW_GET_FUN(__glewClearTexSubImage) @@ -3765,12 +3844,12 @@ typedef void (GLAPIENTRY * PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum sr #define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 #define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 -typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); +typedef void (GLAPIENTRY *GLDEBUGPROCARB)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const GLvoid *userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const void *userParam); typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf); -typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog); #define glDebugMessageCallbackARB GLEW_GET_FUN(__glewDebugMessageCallbackARB) #define glDebugMessageControlARB GLEW_GET_FUN(__glewDebugMessageControlARB) @@ -3875,10 +3954,10 @@ typedef void (GLAPIENTRY * PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLen #ifndef GL_ARB_draw_elements_base_vertex #define GL_ARB_draw_elements_base_vertex 1 -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount, GLint basevertex); -typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const *indices, GLsizei primcount, const GLint *basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei* count, GLenum type, const void *const *indices, GLsizei primcount, const GLint *basevertex); #define glDrawElementsBaseVertex GLEW_GET_FUN(__glewDrawElementsBaseVertex) #define glDrawElementsInstancedBaseVertex GLEW_GET_FUN(__glewDrawElementsInstancedBaseVertex) @@ -3897,8 +3976,8 @@ typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, c #define GL_DRAW_INDIRECT_BUFFER 0x8F3F #define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 -typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const GLvoid *indirect); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect); +typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect); #define glDrawArraysIndirect GLEW_GET_FUN(__glewDrawArraysIndirect) #define glDrawElementsIndirect GLEW_GET_FUN(__glewDrawElementsIndirect) @@ -4229,8 +4308,8 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenu #define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE #define GL_PROGRAM_BINARY_FORMATS 0x87FF -typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, GLvoid*binary); -typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLenum *binaryFormat, void*binary); +typedef void (GLAPIENTRY * PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); typedef void (GLAPIENTRY * PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); #define glGetProgramBinary GLEW_GET_FUN(__glewGetProgramBinary) @@ -4422,12 +4501,12 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei #define GL_REPLICATE_BORDER 0x8153 #define GL_CONVOLUTION_BORDER_COLOR 0x8154 -typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table); typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); @@ -4436,24 +4515,24 @@ typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei s typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, void *table); typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, void *image); typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GLAPIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum types, void *values); typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span); typedef void (GLAPIENTRY * PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); typedef void (GLAPIENTRY * PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); typedef void (GLAPIENTRY * PFNGLRESETHISTOGRAMPROC) (GLenum target); typedef void (GLAPIENTRY * PFNGLRESETMINMAXPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column); #define glColorSubTable GLEW_GET_FUN(__glewColorSubTable) #define glColorTable GLEW_GET_FUN(__glewColorTable) @@ -4500,8 +4579,8 @@ typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum in #define GL_PARAMETER_BUFFER_ARB 0x80EE #define GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF -typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, const GLvoid *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); #define glMultiDrawArraysIndirectCountARB GLEW_GET_FUN(__glewMultiDrawArraysIndirectCountARB) #define glMultiDrawElementsIndirectCountARB GLEW_GET_FUN(__glewMultiDrawElementsIndirectCountARB) @@ -4704,7 +4783,7 @@ typedef void (GLAPIENTRY * PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLin #define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); -typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void * (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); #define glFlushMappedBufferRange GLEW_GET_FUN(__glewFlushMappedBufferRange) #define glMapBufferRange GLEW_GET_FUN(__glewMapBufferRange) @@ -4730,7 +4809,7 @@ typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr #define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 typedef void (GLAPIENTRY * PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); -typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, void *pointer); typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUBVARBPROC) (GLint size, GLubyte *indices); typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUIVARBPROC) (GLint size, GLuint *indices); typedef void (GLAPIENTRY * PFNGLMATRIXINDEXUSVARBPROC) (GLint size, GLushort *indices); @@ -4773,8 +4852,8 @@ typedef void (GLAPIENTRY * PFNGLBINDVERTEXBUFFERSPROC) (GLuint first, GLsizei co #ifndef GL_ARB_multi_draw_indirect #define GL_ARB_multi_draw_indirect 1 -typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const GLvoid *indirect, GLsizei primcount, GLsizei stride); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLsizei primcount, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei primcount, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei primcount, GLsizei stride); #define glMultiDrawArraysIndirect GLEW_GET_FUN(__glewMultiDrawArraysIndirect) #define glMultiDrawElementsIndirect GLEW_GET_FUN(__glewMultiDrawElementsIndirect) @@ -5149,7 +5228,7 @@ typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufS typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint* values); typedef void (GLAPIENTRY * PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort* values); typedef void (GLAPIENTRY * PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte* pattern); -typedef void (GLAPIENTRY * PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void* row, GLsizei columnBufSize, GLvoid*column, GLvoid*span); +typedef void (GLAPIENTRY * PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void* row, GLsizei columnBufSize, void*column, void*span); typedef void (GLAPIENTRY * PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void* img); typedef void (GLAPIENTRY * PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat* params); @@ -5296,7 +5375,7 @@ typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum typedef void (GLAPIENTRY * PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); typedef void (GLAPIENTRY * PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); -typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar ** strings); +typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar * const * strings); typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint* pipelines); typedef void (GLAPIENTRY * PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint* pipelines); typedef void (GLAPIENTRY * PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar *infoLog); @@ -5898,7 +5977,7 @@ typedef void (GLAPIENTRY * PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, #define GL_NUM_SPARSE_LEVELS_ARB 0x91AA typedef void (GLAPIENTRY * PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); -typedef void (GLAPIENTRY * PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); +typedef void (GLAPIENTRY * PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); #define glTexPageCommitmentARB GLEW_GET_FUN(__glewTexPageCommitmentARB) #define glTexturePageCommitmentEXT GLEW_GET_FUN(__glewTexturePageCommitmentEXT) @@ -6082,13 +6161,13 @@ typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFERRANGEEXTPROC) (GLuint texture, GLen #define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 #define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLvoid *img); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, void *img); #define glCompressedTexImage1DARB GLEW_GET_FUN(__glewCompressedTexImage1DARB) #define glCompressedTexImage2DARB GLEW_GET_FUN(__glewCompressedTexImage2DARB) @@ -6325,8 +6404,8 @@ typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GL typedef void (GLAPIENTRY * PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat* val); typedef void (GLAPIENTRY * PFNGLSAMPLEMASKIPROC) (GLuint index, GLbitfield mask); -typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); -typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); #define glGetMultisamplefv GLEW_GET_FUN(__glewGetMultisamplefv) #define glSampleMaski GLEW_GET_FUN(__glewSampleMaski) @@ -6673,7 +6752,7 @@ typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuin typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint* data); typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar* uniformBlockName); -typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar** uniformNames, GLuint* uniformIndices); +typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar* const * uniformNames, GLuint* uniformIndices); typedef void (GLAPIENTRY * PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); #define glBindBufferBase GLEW_GET_FUN(__glewBindBufferBase) @@ -6766,8 +6845,15 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint s #define GL_VERTEX_BINDING_STRIDE 0x82D8 #define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 #define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA +#define GL_VERTEX_BINDING_BUFFER 0x8F4F typedef void (GLAPIENTRY * PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); @@ -6775,6 +6861,12 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GL typedef void (GLAPIENTRY * PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor); #define glBindVertexBuffer GLEW_GET_FUN(__glewBindVertexBuffer) +#define glVertexArrayBindVertexBufferEXT GLEW_GET_FUN(__glewVertexArrayBindVertexBufferEXT) +#define glVertexArrayVertexAttribBindingEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribBindingEXT) +#define glVertexArrayVertexAttribFormatEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribFormatEXT) +#define glVertexArrayVertexAttribIFormatEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribIFormatEXT) +#define glVertexArrayVertexAttribLFormatEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribLFormatEXT) +#define glVertexArrayVertexBindingDivisorEXT GLEW_GET_FUN(__glewVertexArrayVertexBindingDivisorEXT) #define glVertexAttribBinding GLEW_GET_FUN(__glewVertexAttribBinding) #define glVertexAttribFormat GLEW_GET_FUN(__glewVertexAttribFormat) #define glVertexAttribIFormat GLEW_GET_FUN(__glewVertexAttribIFormat) @@ -6834,7 +6926,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, #define GL_MODELVIEW31_ARB 0x873F typedef void (GLAPIENTRY * PFNGLVERTEXBLENDARBPROC) (GLint count); -typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, void *pointer); typedef void (GLAPIENTRY * PFNGLWEIGHTBVARBPROC) (GLint size, GLbyte *weights); typedef void (GLAPIENTRY * PFNGLWEIGHTDVARBPROC) (GLint size, GLdouble *weights); typedef void (GLAPIENTRY * PFNGLWEIGHTFVARBPROC) (GLint size, GLfloat *weights); @@ -6900,15 +6992,15 @@ typedef ptrdiff_t GLintptrARB; typedef ptrdiff_t GLsizeiptrARB; typedef void (GLAPIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); -typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const void *data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data); typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint* buffers); typedef void (GLAPIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint* buffers); typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid** params); -typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); +typedef void (GLAPIENTRY * PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, void** params); +typedef void (GLAPIENTRY * PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, void *data); typedef GLboolean (GLAPIENTRY * PFNGLISBUFFERARBPROC) (GLuint buffer); -typedef GLvoid * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); +typedef void * (GLAPIENTRY * PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); typedef GLboolean (GLAPIENTRY * PFNGLUNMAPBUFFERARBPROC) (GLenum target); #define glBindBufferARB GLEW_GET_FUN(__glewBindBufferARB) @@ -7021,9 +7113,9 @@ typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, typedef void (GLAPIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string); +typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void *string); typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid** pointer); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, void** pointer); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint* params); @@ -7036,7 +7128,7 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble* params); typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (GLAPIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat* params); -typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string); +typedef void (GLAPIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void *string); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); @@ -7073,7 +7165,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLs typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); #define glBindProgramARB GLEW_GET_FUN(__glewBindProgramARB) #define glDeleteProgramsARB GLEW_GET_FUN(__glewDeleteProgramsARB) @@ -7451,7 +7543,7 @@ typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum* bu typedef void (GLAPIENTRY * PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); -typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void *pointer); #define glDrawElementArrayATI GLEW_GET_FUN(__glewDrawElementArrayATI) #define glDrawRangeElementArrayATI GLEW_GET_FUN(__glewDrawRangeElementArrayATI) @@ -7494,13 +7586,13 @@ typedef void (GLAPIENTRY * PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint #ifndef GL_ATI_fragment_shader #define GL_ATI_fragment_shader 1 -#define GL_RED_BIT_ATI 0x00000001 #define GL_2X_BIT_ATI 0x00000001 +#define GL_RED_BIT_ATI 0x00000001 #define GL_4X_BIT_ATI 0x00000002 -#define GL_GREEN_BIT_ATI 0x00000002 #define GL_COMP_BIT_ATI 0x00000002 -#define GL_BLUE_BIT_ATI 0x00000004 +#define GL_GREEN_BIT_ATI 0x00000002 #define GL_8X_BIT_ATI 0x00000004 +#define GL_BLUE_BIT_ATI 0x00000004 #define GL_NEGATE_BIT_ATI 0x00000004 #define GL_BIAS_BIT_ATI 0x00000008 #define GL_HALF_BIT_ATI 0x00000008 @@ -7588,7 +7680,7 @@ typedef void (GLAPIENTRY * PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, c #ifndef GL_ATI_map_object_buffer #define GL_ATI_map_object_buffer 1 -typedef GLvoid * (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void * (GLAPIENTRY * PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); typedef void (GLAPIENTRY * PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); #define glMapObjectBufferATI GLEW_GET_FUN(__glewMapObjectBufferATI) @@ -7757,8 +7849,8 @@ typedef void (GLAPIENTRY * PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint* params); typedef GLboolean (GLAPIENTRY * PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); -typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage); -typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve); +typedef GLuint (GLAPIENTRY * PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void *pointer, GLenum usage); +typedef void (GLAPIENTRY * PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void *pointer, GLenum preserve); typedef void (GLAPIENTRY * PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); #define glArrayObjectATI GLEW_GET_FUN(__glewArrayObjectATI) @@ -8102,7 +8194,7 @@ typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); #ifndef GL_EXT_color_subtable #define GL_EXT_color_subtable 1 -typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data); typedef void (GLAPIENTRY * PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); #define glColorSubTableEXT GLEW_GET_FUN(__glewColorSubTableEXT) @@ -8156,19 +8248,19 @@ typedef void (GLAPIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); #define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 #define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); -typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image); +typedef void (GLAPIENTRY * PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); typedef void (GLAPIENTRY * PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint* params); typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (GLAPIENTRY * PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void *image); typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); -typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +typedef void (GLAPIENTRY * PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span); +typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column); #define glConvolutionFilter1DEXT GLEW_GET_FUN(__glewConvolutionFilter1DEXT) #define glConvolutionFilter2DEXT GLEW_GET_FUN(__glewConvolutionFilter2DEXT) @@ -8208,8 +8300,8 @@ typedef void (GLAPIENTRY * PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum #define GL_MAP1_BINORMAL_EXT 0x8446 #define GL_MAP2_BINORMAL_EXT 0x8447 -typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLvoid *pointer); -typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, void *pointer); +typedef void (GLAPIENTRY * PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, void *pointer); #define glBinormalPointerEXT GLEW_GET_FUN(__glewBinormalPointerEXT) #define glTangentPointerEXT GLEW_GET_FUN(__glewTangentPointerEXT) @@ -8258,6 +8350,28 @@ typedef void (GLAPIENTRY * PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat* #endif /* GL_EXT_cull_vertex */ +/* --------------------------- GL_EXT_debug_label -------------------------- */ + +#ifndef GL_EXT_debug_label +#define GL_EXT_debug_label 1 + +#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F +#define GL_PROGRAM_OBJECT_EXT 0x8B40 +#define GL_SHADER_OBJECT_EXT 0x8B48 +#define GL_BUFFER_OBJECT_EXT 0x9151 +#define GL_QUERY_OBJECT_EXT 0x9153 +#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 + +typedef void (GLAPIENTRY * PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei* length, GLchar *label); +typedef void (GLAPIENTRY * PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar* label); + +#define glGetObjectLabelEXT GLEW_GET_FUN(__glewGetObjectLabelEXT) +#define glLabelObjectEXT GLEW_GET_FUN(__glewLabelObjectEXT) + +#define GLEW_EXT_debug_label GLEW_GET_VAR(__GLEW_EXT_debug_label) + +#endif /* GL_EXT_debug_label */ + /* -------------------------- GL_EXT_debug_marker -------------------------- */ #ifndef GL_EXT_debug_marker @@ -8303,18 +8417,18 @@ typedef void (GLAPIENTRY * PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zma typedef void (GLAPIENTRY * PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture); typedef GLenum (GLAPIENTRY * PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target); typedef void (GLAPIENTRY * PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); typedef void (GLAPIENTRY * PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); @@ -8339,8 +8453,8 @@ typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuff typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode); typedef void (GLAPIENTRY * PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target); typedef void (GLAPIENTRY * PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLvoid *img); -typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLvoid *img); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, void *img); +typedef void (GLAPIENTRY * PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, void *img); typedef void (GLAPIENTRY * PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat* params); @@ -8351,7 +8465,7 @@ typedef void (GLAPIENTRY * PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void *pixels); typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); @@ -8360,18 +8474,18 @@ typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, typedef void (GLAPIENTRY * PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void** params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid *data); +typedef void (GLAPIENTRY * PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data); typedef void (GLAPIENTRY * PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat* params); -typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, GLvoid *string); +typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void *string); typedef void (GLAPIENTRY * PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLvoid** params); -typedef void (GLAPIENTRY * PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, GLvoid** params); -typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, void** params); +typedef void (GLAPIENTRY * PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void** params); +typedef void (GLAPIENTRY * PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void *pixels); typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); @@ -8380,10 +8494,10 @@ typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, G typedef void (GLAPIENTRY * PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint* param); typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint* param); -typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLvoid** param); -typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, GLvoid** param); -typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); -typedef GLvoid * (GLAPIENTRY * PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void** param); +typedef void (GLAPIENTRY * PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, void** param); +typedef void * (GLAPIENTRY * PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access); +typedef void * (GLAPIENTRY * PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); typedef void (GLAPIENTRY * PFNGLMATRIXFRUSTUMEXTPROC) (GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f); typedef void (GLAPIENTRY * PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum matrixMode); typedef void (GLAPIENTRY * PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum matrixMode, const GLdouble* m); @@ -8404,7 +8518,7 @@ typedef void (GLAPIENTRY * PFNGLMATRIXSCALEFEXTPROC) (GLenum matrixMode, GLfloat typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z); typedef void (GLAPIENTRY * PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z); typedef void (GLAPIENTRY * PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer); typedef void (GLAPIENTRY * PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); typedef void (GLAPIENTRY * PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); @@ -8415,9 +8529,9 @@ typedef void (GLAPIENTRY * PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coo typedef void (GLAPIENTRY * PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param); typedef void (GLAPIENTRY * PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* params); typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint* params); typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param); @@ -8425,11 +8539,11 @@ typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLe typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param); typedef void (GLAPIENTRY * PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint* param); typedef void (GLAPIENTRY * PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const GLvoid *data, GLenum usage); -typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid *data); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage); +typedef void (GLAPIENTRY * PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); typedef void (GLAPIENTRY * PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); typedef void (GLAPIENTRY * PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); @@ -8449,7 +8563,7 @@ typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint* params); typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint* params); -typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const GLvoid *string); +typedef void (GLAPIENTRY * PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void *string); typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); typedef void (GLAPIENTRY * PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); @@ -8488,9 +8602,9 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint progra typedef void (GLAPIENTRY * PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); typedef void (GLAPIENTRY * PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask); typedef void (GLAPIENTRY * PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* params); typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint* params); typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param); @@ -8498,9 +8612,9 @@ typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLen typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param); typedef void (GLAPIENTRY * PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint* param); typedef void (GLAPIENTRY * PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer); -typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); typedef GLboolean (GLAPIENTRY * PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); @@ -8510,6 +8624,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint v typedef void (GLAPIENTRY * PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC) (GLuint vaobj, GLuint index, GLuint divisor); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); @@ -8724,6 +8839,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, G #define glVertexArrayNormalOffsetEXT GLEW_GET_FUN(__glewVertexArrayNormalOffsetEXT) #define glVertexArraySecondaryColorOffsetEXT GLEW_GET_FUN(__glewVertexArraySecondaryColorOffsetEXT) #define glVertexArrayTexCoordOffsetEXT GLEW_GET_FUN(__glewVertexArrayTexCoordOffsetEXT) +#define glVertexArrayVertexAttribDivisorEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribDivisorEXT) #define glVertexArrayVertexAttribIOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribIOffsetEXT) #define glVertexArrayVertexAttribOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribOffsetEXT) #define glVertexArrayVertexOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexOffsetEXT) @@ -8761,7 +8877,7 @@ typedef GLboolean (GLAPIENTRY * PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GL #define GL_EXT_draw_instanced 1 typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); #define glDrawArraysInstancedEXT GLEW_GET_FUN(__glewDrawArraysInstancedEXT) #define glDrawElementsInstancedEXT GLEW_GET_FUN(__glewDrawElementsInstancedEXT) @@ -8778,7 +8894,7 @@ typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsi #define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 #define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 -typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); #define glDrawRangeElementsEXT GLEW_GET_FUN(__glewDrawRangeElementsEXT) @@ -8800,7 +8916,7 @@ typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint s #define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 #define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 -typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer); typedef void (GLAPIENTRY * PFNGLFOGCOORDDEXTPROC) (GLdouble coord); typedef void (GLAPIENTRY * PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); typedef void (GLAPIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord); @@ -9152,7 +9268,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const G typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); #define glBindFragDataLocationEXT GLEW_GET_FUN(__glewBindFragDataLocationEXT) #define glGetFragDataLocationEXT GLEW_GET_FUN(__glewGetFragDataLocationEXT) @@ -9212,10 +9328,10 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLin #define GL_MINMAX_FORMAT_EXT 0x802F #define GL_MINMAX_SINK_EXT 0x8030 -typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (GLAPIENTRY * PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values); typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); @@ -9324,7 +9440,7 @@ typedef void (GLAPIENTRY * PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mod #define GL_EXT_multi_draw_arrays 1 typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint* first, const GLsizei *count, GLsizei primcount); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const GLvoid * const *indices, GLsizei primcount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, GLsizei* count, GLenum type, const void *const *indices, GLsizei primcount); #define glMultiDrawArraysEXT GLEW_GET_FUN(__glewMultiDrawArraysEXT) #define glMultiDrawElementsEXT GLEW_GET_FUN(__glewMultiDrawElementsEXT) @@ -9435,8 +9551,8 @@ typedef void (GLAPIENTRY * PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); #define GL_TEXTURE_CUBE_MAP_ARB 0x8513 #define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B -typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data); +typedef void (GLAPIENTRY * PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void *data); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void *data); typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint* params); @@ -9615,7 +9731,7 @@ typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint gr typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); typedef void (GLAPIENTRY * PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer); #define glSecondaryColor3bEXT GLEW_GET_FUN(__glewSecondaryColor3bEXT) #define glSecondaryColor3bvEXT GLEW_GET_FUN(__glewSecondaryColor3bvEXT) @@ -9671,6 +9787,15 @@ typedef void (GLAPIENTRY * PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint pr #endif /* GL_EXT_separate_specular_color */ +/* ------------------- GL_EXT_shader_image_load_formatted ------------------ */ + +#ifndef GL_EXT_shader_image_load_formatted +#define GL_EXT_shader_image_load_formatted 1 + +#define GLEW_EXT_shader_image_load_formatted GLEW_GET_VAR(__GLEW_EXT_shader_image_load_formatted) + +#endif /* GL_EXT_shader_image_load_formatted */ + /* --------------------- GL_EXT_shader_image_load_store -------------------- */ #ifndef GL_EXT_shader_image_load_store @@ -9742,6 +9867,15 @@ typedef void (GLAPIENTRY * PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers); #endif /* GL_EXT_shader_image_load_store */ +/* ----------------------- GL_EXT_shader_integer_mix ----------------------- */ + +#ifndef GL_EXT_shader_integer_mix +#define GL_EXT_shader_integer_mix 1 + +#define GLEW_EXT_shader_integer_mix GLEW_GET_VAR(__GLEW_EXT_shader_integer_mix) + +#endif /* GL_EXT_shader_integer_mix */ + /* -------------------------- GL_EXT_shadow_funcs -------------------------- */ #ifndef GL_EXT_shadow_funcs @@ -9807,9 +9941,9 @@ typedef void (GLAPIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); #ifndef GL_EXT_subtexture #define GL_EXT_subtexture 1 -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); #define glTexSubImage1DEXT GLEW_GET_FUN(__glewTexSubImage1DEXT) #define glTexSubImage2DEXT GLEW_GET_FUN(__glewTexSubImage2DEXT) @@ -9886,7 +10020,7 @@ typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint leve #define GL_TEXTURE_WRAP_R_EXT 0x8072 #define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 -typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); #define glTexImage3DEXT GLEW_GET_FUN(__glewTexImage3DEXT) @@ -10448,13 +10582,13 @@ typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint progra #define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 typedef void (GLAPIENTRY * PFNGLARRAYELEMENTEXTPROC) (GLint i); -typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer); typedef void (GLAPIENTRY * PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean* pointer); -typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); -typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void *pointer); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void *pointer); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer); #define glArrayElementEXT GLEW_GET_FUN(__glewArrayElementEXT) #define glColorPointerEXT GLEW_GET_FUN(__glewColorPointerEXT) @@ -10508,7 +10642,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); #define glGetVertexAttribLdvEXT GLEW_GET_FUN(__glewGetVertexAttribLdvEXT) #define glVertexArrayVertexAttribLOffsetEXT GLEW_GET_FUN(__glewVertexArrayVertexAttribLOffsetEXT) @@ -10665,16 +10799,16 @@ typedef void (GLAPIENTRY * PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLe typedef void (GLAPIENTRY * PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); typedef void (GLAPIENTRY * PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); typedef void (GLAPIENTRY * PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); -typedef void (GLAPIENTRY * PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid **data); +typedef void (GLAPIENTRY * PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, void **data); typedef void (GLAPIENTRY * PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); typedef GLboolean (GLAPIENTRY * PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); -typedef void (GLAPIENTRY * PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); -typedef void (GLAPIENTRY * PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, void *addr); +typedef void (GLAPIENTRY * PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, void *addr); typedef void (GLAPIENTRY * PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); typedef void (GLAPIENTRY * PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); typedef void (GLAPIENTRY * PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); typedef void (GLAPIENTRY * PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); -typedef void (GLAPIENTRY * PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, GLvoid *addr); +typedef void (GLAPIENTRY * PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, void *addr); typedef void (GLAPIENTRY * PFNGLVARIANTBVEXTPROC) (GLuint id, GLbyte *addr); typedef void (GLAPIENTRY * PFNGLVARIANTDVEXTPROC) (GLuint id, GLdouble *addr); typedef void (GLAPIENTRY * PFNGLVARIANTFVEXTPROC) (GLuint id, GLfloat *addr); @@ -10751,7 +10885,7 @@ typedef void (GLAPIENTRY * PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum #define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F #define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 -typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, void *pointer); typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); typedef void (GLAPIENTRY * PFNGLVERTEXWEIGHTFVEXTPROC) (GLfloat* weight); @@ -10796,7 +10930,7 @@ typedef void (GLAPIENTRY * PFNGLFRAMETERMINATORGREMEDYPROC) (void); #ifndef GL_GREMEDY_string_marker #define GL_GREMEDY_string_marker 1 -typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string); +typedef void (GLAPIENTRY * PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void *string); #define glStringMarkerGREMEDY GLEW_GET_FUN(__glewStringMarkerGREMEDY) @@ -10871,7 +11005,7 @@ typedef void (GLAPIENTRY * PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, #define GL_IBM_multimode_draw_arrays 1 typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum* mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); -typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, GLint modestride); +typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mode, const GLsizei *count, GLenum type, const void *const *indices, GLsizei primcount, GLint modestride); #define glMultiModeDrawArraysIBM GLEW_GET_FUN(__glewMultiModeDrawArraysIBM) #define glMultiModeDrawElementsIBM GLEW_GET_FUN(__glewMultiModeDrawElementsIBM) @@ -10936,14 +11070,14 @@ typedef void (GLAPIENTRY * PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum* mod #define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 #define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 -typedef void (GLAPIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void** pointer, GLint ptrstride); typedef void (GLAPIENTRY * PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); -typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid ** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void** pointer, GLint ptrstride); +typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void** pointer, GLint ptrstride); #define glColorPointerListIBM GLEW_GET_FUN(__glewColorPointerListIBM) #define glEdgeFlagPointerListIBM GLEW_GET_FUN(__glewEdgeFlagPointerListIBM) @@ -10987,6 +11121,15 @@ typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum ty #endif /* GL_INGR_interlace_read */ +/* ------------------- GL_INTEL_fragment_shader_ordering ------------------- */ + +#ifndef GL_INTEL_fragment_shader_ordering +#define GL_INTEL_fragment_shader_ordering 1 + +#define GLEW_INTEL_fragment_shader_ordering GLEW_GET_VAR(__GLEW_INTEL_fragment_shader_ordering) + +#endif /* GL_INTEL_fragment_shader_ordering */ + /* -------------------------- GL_INTEL_map_texture ------------------------- */ #ifndef GL_INTEL_map_texture @@ -10997,7 +11140,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum ty #define GL_LAYOUT_LINEAR_CPU_CACHED_INTEL 2 #define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF -typedef GLvoid * (GLAPIENTRY * PFNGLMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level, GLbitfield access, GLint* stride, GLenum *layout); +typedef void * (GLAPIENTRY * PFNGLMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level, GLbitfield access, GLint* stride, GLenum *layout); typedef void (GLAPIENTRY * PFNGLSYNCTEXTUREINTELPROC) (GLuint texture); typedef void (GLAPIENTRY * PFNGLUNMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level); @@ -11034,6 +11177,58 @@ typedef void (GLAPIENTRY * PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum typ #endif /* GL_INTEL_parallel_arrays */ +/* ----------------------- GL_INTEL_performance_query ---------------------- */ + +#ifndef GL_INTEL_performance_query +#define GL_INTEL_performance_query 1 + +#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x0000 +#define GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x0001 +#define GL_PERFQUERY_DONOT_FLUSH_INTEL 0x83F9 +#define GL_PERFQUERY_FLUSH_INTEL 0x83FA +#define GL_PERFQUERY_WAIT_INTEL 0x83FB +#define GL_PERFQUERY_COUNTER_EVENT_INTEL 0x94F0 +#define GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1 +#define GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2 +#define GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3 +#define GL_PERFQUERY_COUNTER_RAW_INTEL 0x94F4 +#define GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5 +#define GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8 +#define GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9 +#define GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA +#define GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB +#define GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC +#define GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD +#define GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE +#define GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF +#define GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500 + +typedef void (GLAPIENTRY * PFNGLBEGINPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (GLAPIENTRY * PFNGLCREATEPERFQUERYINTELPROC) (GLuint queryId, GLuint* queryHandle); +typedef void (GLAPIENTRY * PFNGLDELETEPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (GLAPIENTRY * PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle); +typedef void (GLAPIENTRY * PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint* queryId); +typedef void (GLAPIENTRY * PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint* nextQueryId); +typedef void (GLAPIENTRY * PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar* counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); +typedef void (GLAPIENTRY * PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, void *data, GLuint *bytesWritten); +typedef void (GLAPIENTRY * PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar* queryName, GLuint *queryId); +typedef void (GLAPIENTRY * PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar* queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); + +#define glBeginPerfQueryINTEL GLEW_GET_FUN(__glewBeginPerfQueryINTEL) +#define glCreatePerfQueryINTEL GLEW_GET_FUN(__glewCreatePerfQueryINTEL) +#define glDeletePerfQueryINTEL GLEW_GET_FUN(__glewDeletePerfQueryINTEL) +#define glEndPerfQueryINTEL GLEW_GET_FUN(__glewEndPerfQueryINTEL) +#define glGetFirstPerfQueryIdINTEL GLEW_GET_FUN(__glewGetFirstPerfQueryIdINTEL) +#define glGetNextPerfQueryIdINTEL GLEW_GET_FUN(__glewGetNextPerfQueryIdINTEL) +#define glGetPerfCounterInfoINTEL GLEW_GET_FUN(__glewGetPerfCounterInfoINTEL) +#define glGetPerfQueryDataINTEL GLEW_GET_FUN(__glewGetPerfQueryDataINTEL) +#define glGetPerfQueryIdByNameINTEL GLEW_GET_FUN(__glewGetPerfQueryIdByNameINTEL) +#define glGetPerfQueryInfoINTEL GLEW_GET_FUN(__glewGetPerfQueryInfoINTEL) + +#define GLEW_INTEL_performance_query GLEW_GET_VAR(__GLEW_INTEL_performance_query) + +#endif /* GL_INTEL_performance_query */ + /* ------------------------ GL_INTEL_texture_scissor ----------------------- */ #ifndef GL_INTEL_texture_scissor @@ -11095,16 +11290,16 @@ typedef void (GLAPIENTRY * PFNGLTEXSCISSORINTELPROC) (GLenum target, GLclampf tl #define GL_DEBUG_SEVERITY_LOW 0x9148 #define GL_DEBUG_OUTPUT 0x92E0 -typedef void (APIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* userParam); +typedef void (GLAPIENTRY *GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam); -typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const GLvoid *userParam); +typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam); typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf); -typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog); +typedef GLuint (GLAPIENTRY * PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog); typedef void (GLAPIENTRY * PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar *label); -typedef void (GLAPIENTRY * PFNGLGETOBJECTPTRLABELPROC) (void* ptr, GLsizei bufSize, GLsizei* length, GLchar *label); +typedef void (GLAPIENTRY * PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei* length, GLchar *label); typedef void (GLAPIENTRY * PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar* label); -typedef void (GLAPIENTRY * PFNGLOBJECTPTRLABELPROC) (void* ptr, GLsizei length, const GLchar* label); +typedef void (GLAPIENTRY * PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar* label); typedef void (GLAPIENTRY * PFNGLPOPDEBUGGROUPPROC) (void); typedef void (GLAPIENTRY * PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar * message); @@ -11123,6 +11318,44 @@ typedef void (GLAPIENTRY * PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, G #endif /* GL_KHR_debug */ +/* ------------------ GL_KHR_texture_compression_astc_hdr ------------------ */ + +#ifndef GL_KHR_texture_compression_astc_hdr +#define GL_KHR_texture_compression_astc_hdr 1 + +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD + +#define GLEW_KHR_texture_compression_astc_hdr GLEW_GET_VAR(__GLEW_KHR_texture_compression_astc_hdr) + +#endif /* GL_KHR_texture_compression_astc_hdr */ + /* ------------------ GL_KHR_texture_compression_astc_ldr ------------------ */ #ifndef GL_KHR_texture_compression_astc_ldr @@ -11334,8 +11567,8 @@ typedef void (GLAPIENTRY * PFNGLENDCONDITIONALRENDERNVXPROC) (void); #ifndef GL_NV_bindless_multi_draw_indirect #define GL_NV_bindless_multi_draw_indirect 1 -typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const GLvoid *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); -typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC) (GLenum mode, GLenum type, const GLvoid *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); +typedef void (GLAPIENTRY * PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); #define glMultiDrawArraysIndirectBindlessNV GLEW_GET_FUN(__glewMultiDrawArraysIndirectBindlessNV) #define glMultiDrawElementsIndirectBindlessNV GLEW_GET_FUN(__glewMultiDrawElementsIndirectBindlessNV) @@ -11386,6 +11619,10 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsiz #ifndef GL_NV_blend_equation_advanced #define GL_NV_blend_equation_advanced 1 +#define GL_XOR_NV 0x1506 +#define GL_RED_NV 0x1903 +#define GL_GREEN_NV 0x1904 +#define GL_BLUE_NV 0x1905 #define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280 #define GL_BLEND_OVERLAP_NV 0x9281 #define GL_UNCORRELATED_NV 0x9282 @@ -11624,10 +11861,10 @@ typedef void (GLAPIENTRY * PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampl typedef void (GLAPIENTRY * PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); +typedef void (GLAPIENTRY * PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void *points); typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); +typedef void (GLAPIENTRY * PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void *points); typedef void (GLAPIENTRY * PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint* params); @@ -12260,8 +12497,8 @@ typedef void (GLAPIENTRY * PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, #define GL_ITALIC_BIT_NV 0x02 #define GL_MOVE_TO_NV 0x02 #define GL_RELATIVE_MOVE_TO_NV 0x03 -#define GL_LINE_TO_NV 0x04 #define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04 +#define GL_LINE_TO_NV 0x04 #define GL_RELATIVE_LINE_TO_NV 0x05 #define GL_HORIZONTAL_LINE_TO_NV 0x06 #define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07 @@ -12407,13 +12644,13 @@ typedef GLboolean (GLAPIENTRY * PFNGLISPATHNVPROC) (GLuint path); typedef GLboolean (GLAPIENTRY * PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y); typedef GLboolean (GLAPIENTRY * PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y); typedef void (GLAPIENTRY * PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat* coeffs); -typedef void (GLAPIENTRY * PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const GLvoid*coords); +typedef void (GLAPIENTRY * PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const void*coords); typedef void (GLAPIENTRY * PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void* coords); typedef void (GLAPIENTRY * PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum zfunc); typedef void (GLAPIENTRY * PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat* dashArray); typedef void (GLAPIENTRY * PFNGLPATHFOGGENNVPROC) (GLenum genMode); typedef void (GLAPIENTRY * PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void* fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); -typedef void (GLAPIENTRY * PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void* fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const GLvoid*charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); +typedef void (GLAPIENTRY * PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void* fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void*charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); typedef void (GLAPIENTRY * PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value); typedef void (GLAPIENTRY * PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat* value); typedef void (GLAPIENTRY * PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value); @@ -12421,7 +12658,7 @@ typedef void (GLAPIENTRY * PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pnam typedef void (GLAPIENTRY * PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units); typedef void (GLAPIENTRY * PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask); typedef void (GLAPIENTRY * PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void* pathString); -typedef void (GLAPIENTRY * PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const GLvoid*coords); +typedef void (GLAPIENTRY * PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte* commands, GLsizei numCoords, GLenum coordType, const void*coords); typedef void (GLAPIENTRY * PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void* coords); typedef void (GLAPIENTRY * PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat* coeffs); typedef GLboolean (GLAPIENTRY * PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat* x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY); @@ -12499,7 +12736,7 @@ typedef void (GLAPIENTRY * PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei n #define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D typedef void (GLAPIENTRY * PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); -typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, void *pointer); #define glFlushPixelDataRangeNV GLEW_GET_FUN(__glewFlushPixelDataRangeNV) #define glPixelDataRangeNV GLEW_GET_FUN(__glewPixelDataRangeNV) @@ -12749,6 +12986,28 @@ typedef void (GLAPIENTRY * PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei cou #endif /* GL_NV_shader_storage_buffer_object */ +/* ----------------------- GL_NV_shader_thread_group ----------------------- */ + +#ifndef GL_NV_shader_thread_group +#define GL_NV_shader_thread_group 1 + +#define GL_WARP_SIZE_NV 0x9339 +#define GL_WARPS_PER_SM_NV 0x933A +#define GL_SM_COUNT_NV 0x933B + +#define GLEW_NV_shader_thread_group GLEW_GET_VAR(__GLEW_NV_shader_thread_group) + +#endif /* GL_NV_shader_thread_group */ + +/* ---------------------- GL_NV_shader_thread_shuffle ---------------------- */ + +#ifndef GL_NV_shader_thread_shuffle +#define GL_NV_shader_thread_shuffle 1 + +#define GLEW_NV_shader_thread_shuffle GLEW_GET_VAR(__GLEW_NV_shader_thread_shuffle) + +#endif /* GL_NV_shader_thread_shuffle */ + /* ---------------------- GL_NV_tessellation_program5 ---------------------- */ #ifndef GL_NV_tessellation_program5 @@ -12897,8 +13156,8 @@ typedef void (GLAPIENTRY * PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture #define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 #define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2 #define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 -#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 #define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 #define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 #define GL_CONST_EYE_NV 0x86E5 #define GL_PASS_THROUGH_NV 0x86E6 @@ -13128,7 +13387,7 @@ typedef GLintptr GLvdpauSurfaceNV; typedef void (GLAPIENTRY * PFNGLVDPAUFININVPROC) (void); typedef void (GLAPIENTRY * PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei* length, GLint *values); -typedef void (GLAPIENTRY * PFNGLVDPAUINITNVPROC) (const void* vdpDevice, const GLvoid*getProcAddress); +typedef void (GLAPIENTRY * PFNGLVDPAUINITNVPROC) (const void* vdpDevice, const void*getProcAddress); typedef void (GLAPIENTRY * PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface); typedef void (GLAPIENTRY * PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV* surfaces); typedef GLvdpauSurfaceNV (GLAPIENTRY * PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void* vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); @@ -13164,7 +13423,7 @@ typedef void (GLAPIENTRY * PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV #define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 typedef void (GLAPIENTRY * PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); -typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, void *pointer); #define glFlushVertexArrayRangeNV GLEW_GET_FUN(__glewFlushVertexArrayRangeNV) #define glVertexArrayRangeNV GLEW_GET_FUN(__glewVertexArrayRangeNV) @@ -13396,7 +13655,7 @@ typedef void (GLAPIENTRY * PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLu typedef void (GLAPIENTRY * PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte* program); typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint* params); typedef void (GLAPIENTRY * PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid** pointer); +typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, void** pointer); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble* params); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint* params); @@ -13436,7 +13695,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte* v); -typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei n, const GLdouble* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei n, const GLfloat* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei n, const GLshort* v); @@ -13894,7 +14153,7 @@ typedef void (GLAPIENTRY * PFNGLGETTEXENVXVPROC) (GLenum env, GLenum pname, GLfi typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERXVPROC) (GLenum target, GLenum pname, GLfixed* params); typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERXPROC) (GLenum pname, GLfixed param); typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERXVPROC) (GLenum pname, const GLfixed* params); -typedef void (GLAPIENTRY * PFNGLPOINTSIZEPOINTEROESPROC) (GLenum type, GLsizei stride, const GLvoid* pointer); +typedef void (GLAPIENTRY * PFNGLPOINTSIZEPOINTEROESPROC) (GLenum type, GLsizei stride, const void *pointer); typedef void (GLAPIENTRY * PFNGLTEXPARAMETERXVPROC) (GLenum target, GLenum pname, const GLfixed* params); #define glClipPlanef GLEW_GET_FUN(__glewClipPlanef) @@ -13978,7 +14237,7 @@ typedef GLboolean (GLAPIENTRY * PFNGLISSUPPORTEDREGALPROC) (const GLchar* ext); #define GL_LOG_STATUS_REGAL 0x9320 #define GL_LOG_HTTP_REGAL 0x9321 -typedef void (APIENTRY *GLLOGPROCREGAL)(GLenum stream, GLsizei length, const GLchar *message, GLvoid *context); +typedef void (APIENTRY *GLLOGPROCREGAL)(GLenum stream, GLsizei length, const GLchar *message, void *context); typedef void (GLAPIENTRY * PFNGLLOGMESSAGECALLBACKREGALPROC) (GLLOGPROCREGAL callback); @@ -13988,6 +14247,19 @@ typedef void (GLAPIENTRY * PFNGLLOGMESSAGECALLBACKREGALPROC) (GLLOGPROCREGAL cal #endif /* GL_REGAL_log */ +/* ------------------------- GL_REGAL_proc_address ------------------------- */ + +#ifndef GL_REGAL_proc_address +#define GL_REGAL_proc_address 1 + +typedef void * (GLAPIENTRY * PFNGLGETPROCADDRESSREGALPROC) (const GLchar *name); + +#define glGetProcAddressREGAL GLEW_GET_FUN(__glewGetProcAddressREGAL) + +#define GLEW_REGAL_proc_address GLEW_GET_VAR(__GLEW_REGAL_proc_address) + +#endif /* GL_REGAL_proc_address */ + /* ----------------------- GL_REND_screen_coordinates ---------------------- */ #ifndef GL_REND_screen_coordinates @@ -14156,8 +14428,8 @@ typedef void (GLAPIENTRY * PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei #ifndef GL_SGIS_texture4D #define GL_SGIS_texture4D 1 -typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (GLAPIENTRY * PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei extent, GLenum format, GLenum type, const void *pixels); #define glTexImage4DSGIS GLEW_GET_FUN(__glewTexImage4DSGIS) #define glTexSubImage4DSGIS GLEW_GET_FUN(__glewTexSubImage4DSGIS) @@ -14354,9 +14626,9 @@ typedef void (GLAPIENTRY * PFNGLFLUSHRASTERSGIXPROC) (void); #ifndef GL_SGIX_fog_texture #define GL_SGIX_fog_texture 1 -#define GL_TEXTURE_FOG_SGIX 0 #define GL_FOG_PATCHY_FACTOR_SGIX 0 #define GL_FRAGMENT_FOG_SGIX 0 +#define GL_TEXTURE_FOG_SGIX 0 typedef void (GLAPIENTRY * PFNGLTEXTUREFOGSGIXPROC) (GLenum pname); @@ -14732,11 +15004,11 @@ typedef void (GLAPIENTRY * PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat* params); typedef void (GLAPIENTRY * PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint* params); -typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (GLAPIENTRY * PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table); typedef void (GLAPIENTRY * PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat* params); typedef void (GLAPIENTRY * PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint* params); -typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (GLAPIENTRY * PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void *table); #define glColorTableParameterfvSGI GLEW_GET_FUN(__glewColorTableParameterfvSGI) #define glColorTableParameterivSGI GLEW_GET_FUN(__glewColorTableParameterivSGI) @@ -14836,7 +15108,7 @@ typedef void (GLAPIENTRY * PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); #ifndef GL_SUN_read_video_pixels #define GL_SUN_read_video_pixels 1 -typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); +typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels); #define glReadVideoPixelsSUN GLEW_GET_FUN(__glewReadVideoPixelsSUN) @@ -14878,7 +15150,7 @@ typedef void (GLAPIENTRY * PFNGLREADVIDEOPIXELSSUNPROC) (GLint x, GLint y, GLsiz #define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA #define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB -typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void *pointer); typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte* code); typedef void (GLAPIENTRY * PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); @@ -15359,6 +15631,8 @@ GLEW_FUN_EXPORT PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD; GLEW_FUN_EXPORT PFNGLGENNAMESAMDPROC __glewGenNamesAMD; GLEW_FUN_EXPORT PFNGLISNAMEAMDPROC __glewIsNameAMD; +GLEW_FUN_EXPORT PFNGLQUERYOBJECTPARAMETERUIAMDPROC __glewQueryObjectParameteruiAMD; + GLEW_FUN_EXPORT PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD; GLEW_FUN_EXPORT PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD; GLEW_FUN_EXPORT PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD; @@ -15962,6 +16236,12 @@ GLEW_FUN_EXPORT PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv; GLEW_FUN_EXPORT PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer; GLEW_FUN_EXPORT PFNGLBINDVERTEXBUFFERPROC __glewBindVertexBuffer; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC __glewVertexArrayBindVertexBufferEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC __glewVertexArrayVertexAttribBindingEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC __glewVertexArrayVertexAttribFormatEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC __glewVertexArrayVertexAttribIFormatEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC __glewVertexArrayVertexAttribLFormatEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC __glewVertexArrayVertexBindingDivisorEXT; GLEW_FUN_EXPORT PFNGLVERTEXATTRIBBINDINGPROC __glewVertexAttribBinding; GLEW_FUN_EXPORT PFNGLVERTEXATTRIBFORMATPROC __glewVertexAttribFormat; GLEW_FUN_EXPORT PFNGLVERTEXATTRIBIFORMATPROC __glewVertexAttribIFormat; @@ -16267,6 +16547,9 @@ GLEW_FUN_EXPORT PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT; GLEW_FUN_EXPORT PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT; GLEW_FUN_EXPORT PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT; +GLEW_FUN_EXPORT PFNGLGETOBJECTLABELEXTPROC __glewGetObjectLabelEXT; +GLEW_FUN_EXPORT PFNGLLABELOBJECTEXTPROC __glewLabelObjectEXT; + GLEW_FUN_EXPORT PFNGLINSERTEVENTMARKEREXTPROC __glewInsertEventMarkerEXT; GLEW_FUN_EXPORT PFNGLPOPGROUPMARKEREXTPROC __glewPopGroupMarkerEXT; GLEW_FUN_EXPORT PFNGLPUSHGROUPMARKEREXTPROC __glewPushGroupMarkerEXT; @@ -16483,6 +16766,7 @@ GLEW_FUN_EXPORT PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC __glewVertexArrayMult GLEW_FUN_EXPORT PFNGLVERTEXARRAYNORMALOFFSETEXTPROC __glewVertexArrayNormalOffsetEXT; GLEW_FUN_EXPORT PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC __glewVertexArraySecondaryColorOffsetEXT; GLEW_FUN_EXPORT PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC __glewVertexArrayTexCoordOffsetEXT; +GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC __glewVertexArrayVertexAttribDivisorEXT; GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC __glewVertexArrayVertexAttribIOffsetEXT; GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC __glewVertexArrayVertexAttribOffsetEXT; GLEW_FUN_EXPORT PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC __glewVertexArrayVertexOffsetEXT; @@ -16801,6 +17085,17 @@ GLEW_FUN_EXPORT PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL; GLEW_FUN_EXPORT PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL; GLEW_FUN_EXPORT PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL; +GLEW_FUN_EXPORT PFNGLBEGINPERFQUERYINTELPROC __glewBeginPerfQueryINTEL; +GLEW_FUN_EXPORT PFNGLCREATEPERFQUERYINTELPROC __glewCreatePerfQueryINTEL; +GLEW_FUN_EXPORT PFNGLDELETEPERFQUERYINTELPROC __glewDeletePerfQueryINTEL; +GLEW_FUN_EXPORT PFNGLENDPERFQUERYINTELPROC __glewEndPerfQueryINTEL; +GLEW_FUN_EXPORT PFNGLGETFIRSTPERFQUERYIDINTELPROC __glewGetFirstPerfQueryIdINTEL; +GLEW_FUN_EXPORT PFNGLGETNEXTPERFQUERYIDINTELPROC __glewGetNextPerfQueryIdINTEL; +GLEW_FUN_EXPORT PFNGLGETPERFCOUNTERINFOINTELPROC __glewGetPerfCounterInfoINTEL; +GLEW_FUN_EXPORT PFNGLGETPERFQUERYDATAINTELPROC __glewGetPerfQueryDataINTEL; +GLEW_FUN_EXPORT PFNGLGETPERFQUERYIDBYNAMEINTELPROC __glewGetPerfQueryIdByNameINTEL; +GLEW_FUN_EXPORT PFNGLGETPERFQUERYINFOINTELPROC __glewGetPerfQueryInfoINTEL; + GLEW_FUN_EXPORT PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL; GLEW_FUN_EXPORT PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL; @@ -17333,6 +17628,8 @@ GLEW_FUN_EXPORT PFNGLISSUPPORTEDREGALPROC __glewIsSupportedREGAL; GLEW_FUN_EXPORT PFNGLLOGMESSAGECALLBACKREGALPROC __glewLogMessageCallbackREGAL; +GLEW_FUN_EXPORT PFNGLGETPROCADDRESSREGALPROC __glewGetProcAddressREGAL; + GLEW_FUN_EXPORT PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS; GLEW_FUN_EXPORT PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS; @@ -17495,20 +17792,26 @@ GLEW_VAR_EXPORT GLboolean __GLEW_AMD_conservative_depth; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_debug_output; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_depth_clamp_separate; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_draw_buffers_blend; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_gcn_shader; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_gpu_shader_int64; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_interleaved_elements; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_multi_draw_indirect; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_name_gen_delete; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_occlusion_query_event; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_performance_monitor; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_pinned_memory; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_query_buffer_object; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sample_positions; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_seamless_cubemap_per_texture; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_atomic_counter_ops; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_stencil_export; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_stencil_value_export; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_shader_trinary_minmax; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_sparse_texture; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_stencil_operation_extended; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_texture_texture4; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_transform_feedback3_lines_triangles; +GLEW_VAR_EXPORT GLboolean __GLEW_AMD_transform_feedback4; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_layer; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_tessellator; GLEW_VAR_EXPORT GLboolean __GLEW_AMD_vertex_shader_viewport_index; @@ -17724,6 +18027,7 @@ GLEW_VAR_EXPORT GLboolean __GLEW_EXT_convolution; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_coordinate_frame; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_copy_texture; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_cull_vertex; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_debug_label; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_debug_marker; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_depth_bounds_test; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_direct_state_access; @@ -17764,7 +18068,9 @@ GLEW_VAR_EXPORT GLboolean __GLEW_EXT_scene_marker; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_secondary_color; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_shader_objects; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_separate_specular_color; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_image_load_formatted; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_image_load_store; +GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shader_integer_mix; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shadow_funcs; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_shared_texture_palette; GLEW_VAR_EXPORT GLboolean __GLEW_EXT_stencil_clear_tag; @@ -17819,10 +18125,13 @@ GLEW_VAR_EXPORT GLboolean __GLEW_IBM_texture_mirrored_repeat; GLEW_VAR_EXPORT GLboolean __GLEW_IBM_vertex_array_lists; GLEW_VAR_EXPORT GLboolean __GLEW_INGR_color_clamp; GLEW_VAR_EXPORT GLboolean __GLEW_INGR_interlace_read; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_fragment_shader_ordering; GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_map_texture; GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_parallel_arrays; +GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_performance_query; GLEW_VAR_EXPORT GLboolean __GLEW_INTEL_texture_scissor; GLEW_VAR_EXPORT GLboolean __GLEW_KHR_debug; +GLEW_VAR_EXPORT GLboolean __GLEW_KHR_texture_compression_astc_hdr; GLEW_VAR_EXPORT GLboolean __GLEW_KHR_texture_compression_astc_ldr; GLEW_VAR_EXPORT GLboolean __GLEW_KTX_buffer_region; GLEW_VAR_EXPORT GLboolean __GLEW_MESAX_texture_stack; @@ -17882,6 +18191,8 @@ GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_atomic_counters; GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_atomic_float; GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_buffer_load; GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_storage_buffer_object; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_thread_group; +GLEW_VAR_EXPORT GLboolean __GLEW_NV_shader_thread_shuffle; GLEW_VAR_EXPORT GLboolean __GLEW_NV_tessellation_program5; GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_emboss; GLEW_VAR_EXPORT GLboolean __GLEW_NV_texgen_reflection; @@ -17923,6 +18234,7 @@ GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_enable; GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_error_string; GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_extension_query; GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_log; +GLEW_VAR_EXPORT GLboolean __GLEW_REGAL_proc_address; GLEW_VAR_EXPORT GLboolean __GLEW_REND_screen_coordinates; GLEW_VAR_EXPORT GLboolean __GLEW_S3_s3tc; GLEW_VAR_EXPORT GLboolean __GLEW_SGIS_color_range; @@ -18046,8 +18358,6 @@ GLEWAPI const GLubyte * GLEWAPIENTRY glewGetString (GLenum name); #ifdef GLEW_APIENTRY_DEFINED #undef GLEW_APIENTRY_DEFINED #undef APIENTRY -#undef GLAPIENTRY -#define GLAPIENTRY #endif #ifdef GLEW_CALLBACK_DEFINED diff --git a/ext/glew/GL/glxew.h b/ext/glew/GL/glxew.h index 76a5f0d82a..f757939e15 100644 --- a/ext/glew/GL/glxew.h +++ b/ext/glew/GL/glxew.h @@ -1,5 +1,6 @@ /* ** The OpenGL Extension Wrangler Library +** Copyright (C) 2008-2014, Nigel Stewart ** Copyright (C) 2002-2008, Milan Ikits ** Copyright (C) 2002-2008, Marcelo E. Magallon ** Copyright (C) 2002, Lev Povalahev @@ -200,18 +201,18 @@ typedef Display* ( * PFNGLXGETCURRENTDISPLAYPROC) (void); #ifndef GLX_VERSION_1_3 #define GLX_VERSION_1_3 1 -#define GLX_RGBA_BIT 0x00000001 #define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_RGBA_BIT 0x00000001 #define GLX_WINDOW_BIT 0x00000001 #define GLX_COLOR_INDEX_BIT 0x00000002 -#define GLX_PIXMAP_BIT 0x00000002 #define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_PIXMAP_BIT 0x00000002 #define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 #define GLX_PBUFFER_BIT 0x00000004 #define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 #define GLX_AUX_BUFFERS_BIT 0x00000010 -#define GLX_CONFIG_CAVEAT 0x20 #define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_CONFIG_CAVEAT 0x20 #define GLX_X_VISUAL_TYPE 0x22 #define GLX_TRANSPARENT_TYPE 0x23 #define GLX_TRANSPARENT_INDEX_VALUE 0x24 @@ -665,6 +666,19 @@ typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display* dpy, GLXContext context #endif /* GLX_EXT_scene_marker */ +/* -------------------------- GLX_EXT_stereo_tree -------------------------- */ + +#ifndef GLX_EXT_stereo_tree +#define GLX_EXT_stereo_tree 1 + +#define GLX_STEREO_NOTIFY_EXT 0x00000000 +#define GLX_STEREO_NOTIFY_MASK_EXT 0x00000001 +#define GLX_STEREO_TREE_EXT 0x20F5 + +#define GLXEW_EXT_stereo_tree GLXEW_GET_VAR(__GLXEW_EXT_stereo_tree) + +#endif /* GLX_EXT_stereo_tree */ + /* -------------------------- GLX_EXT_swap_control ------------------------- */ #ifndef GLX_EXT_swap_control @@ -831,6 +845,38 @@ typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display* dpy, XVisualInfo #endif /* GLX_MESA_pixmap_colormap */ +/* ------------------------ GLX_MESA_query_renderer ------------------------ */ + +#ifndef GLX_MESA_query_renderer +#define GLX_MESA_query_renderer 1 + +#define GLX_RENDERER_VENDOR_ID_MESA 0x8183 +#define GLX_RENDERER_DEVICE_ID_MESA 0x8184 +#define GLX_RENDERER_VERSION_MESA 0x8185 +#define GLX_RENDERER_ACCELERATED_MESA 0x8186 +#define GLX_RENDERER_VIDEO_MEMORY_MESA 0x8187 +#define GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA 0x8188 +#define GLX_RENDERER_PREFERRED_PROFILE_MESA 0x8189 +#define GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA 0x818A +#define GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA 0x818B +#define GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA 0x818C +#define GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA 0x818D +#define GLX_RENDERER_ID_MESA 0x818E + +typedef Bool ( * PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) (int attribute, unsigned int* value); +typedef const char* ( * PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC) (int attribute); +typedef Bool ( * PFNGLXQUERYRENDERERINTEGERMESAPROC) (Display* dpy, int screen, int renderer, int attribute, unsigned int *value); +typedef const char* ( * PFNGLXQUERYRENDERERSTRINGMESAPROC) (Display *dpy, int screen, int renderer, int attribute); + +#define glXQueryCurrentRendererIntegerMESA GLXEW_GET_FUN(__glewXQueryCurrentRendererIntegerMESA) +#define glXQueryCurrentRendererStringMESA GLXEW_GET_FUN(__glewXQueryCurrentRendererStringMESA) +#define glXQueryRendererIntegerMESA GLXEW_GET_FUN(__glewXQueryRendererIntegerMESA) +#define glXQueryRendererStringMESA GLXEW_GET_FUN(__glewXQueryRendererStringMESA) + +#define GLXEW_MESA_query_renderer GLXEW_GET_VAR(__GLXEW_MESA_query_renderer) + +#endif /* GLX_MESA_query_renderer */ + /* ------------------------ GLX_MESA_release_buffers ----------------------- */ #ifndef GLX_MESA_release_buffers @@ -888,6 +934,19 @@ typedef void ( * PFNGLXCOPYIMAGESUBDATANVPROC) (Display *dpy, GLXContext srcCtx, #endif /* GLX_NV_copy_image */ +/* ------------------------ GLX_NV_delay_before_swap ----------------------- */ + +#ifndef GLX_NV_delay_before_swap +#define GLX_NV_delay_before_swap 1 + +typedef Bool ( * PFNGLXDELAYBEFORESWAPNVPROC) (Display* dpy, GLXDrawable drawable, GLfloat seconds); + +#define glXDelayBeforeSwapNV GLXEW_GET_FUN(__glewXDelayBeforeSwapNV) + +#define GLXEW_NV_delay_before_swap GLXEW_GET_VAR(__GLXEW_NV_delay_before_swap) + +#endif /* GLX_NV_delay_before_swap */ + /* -------------------------- GLX_NV_float_buffer -------------------------- */ #ifndef GLX_NV_float_buffer @@ -993,10 +1052,10 @@ typedef void ( * PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC) (Display* dpy, GLXVideoC #endif /* GLX_NV_video_capture */ -/* -------------------------- GLX_NV_video_output -------------------------- */ +/* ---------------------------- GLX_NV_video_out --------------------------- */ -#ifndef GLX_NV_video_output -#define GLX_NV_video_output 1 +#ifndef GLX_NV_video_out +#define GLX_NV_video_out 1 #define GLX_VIDEO_OUT_COLOR_NV 0x20C3 #define GLX_VIDEO_OUT_ALPHA_NV 0x20C4 @@ -1023,9 +1082,9 @@ typedef int ( * PFNGLXSENDPBUFFERTOVIDEONVPROC) (Display* dpy, GLXPbuffer pbuf, #define glXReleaseVideoImageNV GLXEW_GET_FUN(__glewXReleaseVideoImageNV) #define glXSendPbufferToVideoNV GLXEW_GET_FUN(__glewXSendPbufferToVideoNV) -#define GLXEW_NV_video_output GLXEW_GET_VAR(__GLXEW_NV_video_output) +#define GLXEW_NV_video_out GLXEW_GET_VAR(__GLXEW_NV_video_out) -#endif /* GLX_NV_video_output */ +#endif /* GLX_NV_video_out */ /* -------------------------- GLX_OML_swap_method -------------------------- */ @@ -1111,10 +1170,10 @@ typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display* dpy, GLXDrawable drawable, i #ifndef GLX_SGIX_fbconfig #define GLX_SGIX_fbconfig 1 -#define GLX_WINDOW_BIT_SGIX 0x00000001 #define GLX_RGBA_BIT_SGIX 0x00000001 -#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_WINDOW_BIT_SGIX 0x00000001 #define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 #define GLX_SCREEN_EXT 0x800C #define GLX_DRAWABLE_TYPE_SGIX 0x8010 #define GLX_RENDER_TYPE_SGIX 0x8011 @@ -1151,8 +1210,8 @@ typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLX #define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 #define GLX_PIPE_RECT_SGIX 0x00000001 -#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 #define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 +#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 #define GLX_HYPERPIPE_STEREO_SGIX 0x00000003 #define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 #define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 @@ -1218,8 +1277,8 @@ typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Disp #define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 #define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 -#define GLX_PBUFFER_BIT_SGIX 0x00000004 #define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 +#define GLX_PBUFFER_BIT_SGIX 0x00000004 #define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 #define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 #define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 @@ -1473,6 +1532,11 @@ GLXEW_FUN_EXPORT PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA; GLXEW_FUN_EXPORT PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA; +GLXEW_FUN_EXPORT PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC __glewXQueryCurrentRendererIntegerMESA; +GLXEW_FUN_EXPORT PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC __glewXQueryCurrentRendererStringMESA; +GLXEW_FUN_EXPORT PFNGLXQUERYRENDERERINTEGERMESAPROC __glewXQueryRendererIntegerMESA; +GLXEW_FUN_EXPORT PFNGLXQUERYRENDERERSTRINGMESAPROC __glewXQueryRendererStringMESA; + GLXEW_FUN_EXPORT PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA; GLXEW_FUN_EXPORT PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA; @@ -1482,6 +1546,8 @@ GLXEW_FUN_EXPORT PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA; GLXEW_FUN_EXPORT PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV; +GLXEW_FUN_EXPORT PFNGLXDELAYBEFORESWAPNVPROC __glewXDelayBeforeSwapNV; + GLXEW_FUN_EXPORT PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV; GLXEW_FUN_EXPORT PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV; @@ -1593,6 +1659,7 @@ GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_fbconfig_packed_float; GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_framebuffer_sRGB; GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_import_context; GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_scene_marker; +GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_stereo_tree; GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_swap_control; GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_swap_control_tear; GLXEW_VAR_EXPORT GLboolean __GLXEW_EXT_texture_from_pixmap; @@ -1602,17 +1669,19 @@ GLXEW_VAR_EXPORT GLboolean __GLXEW_INTEL_swap_event; GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_agp_offset; GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_copy_sub_buffer; GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_pixmap_colormap; +GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_query_renderer; GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_release_buffers; GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_set_3dfx_mode; GLXEW_VAR_EXPORT GLboolean __GLXEW_MESA_swap_control; GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_copy_image; +GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_delay_before_swap; GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_float_buffer; GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_multisample_coverage; GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_present_video; GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_swap_group; GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_vertex_array_range; GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_video_capture; -GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_video_output; +GLXEW_VAR_EXPORT GLboolean __GLXEW_NV_video_out; GLXEW_VAR_EXPORT GLboolean __GLXEW_OML_swap_method; GLXEW_VAR_EXPORT GLboolean __GLXEW_OML_sync_control; GLXEW_VAR_EXPORT GLboolean __GLXEW_SGIS_blended_overlay; diff --git a/ext/glew/GL/wglew.h b/ext/glew/GL/wglew.h index 8659841d35..da63e40378 100644 --- a/ext/glew/GL/wglew.h +++ b/ext/glew/GL/wglew.h @@ -1,5 +1,6 @@ /* ** The OpenGL Extension Wrangler Library +** Copyright (C) 2008-2014, Nigel Stewart ** Copyright (C) 2002-2008, Milan Ikits ** Copyright (C) 2002-2008, Marcelo E. Magallon ** Copyright (C) 2002, Lev Povalahev @@ -928,6 +929,19 @@ typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcNa #endif /* WGL_NV_copy_image */ +/* ------------------------ WGL_NV_delay_before_swap ----------------------- */ + +#ifndef WGL_NV_delay_before_swap +#define WGL_NV_delay_before_swap 1 + +typedef BOOL (WINAPI * PFNWGLDELAYBEFORESWAPNVPROC) (HDC hDC, GLfloat seconds); + +#define wglDelayBeforeSwapNV WGLEW_GET_FUN(__wglewDelayBeforeSwapNV) + +#define WGLEW_NV_delay_before_swap WGLEW_GET_VAR(__WGLEW_NV_delay_before_swap) + +#endif /* WGL_NV_delay_before_swap */ + /* -------------------------- WGL_NV_float_buffer -------------------------- */ #ifndef WGL_NV_float_buffer @@ -1291,6 +1305,8 @@ WGLEW_FUN_EXPORT PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV; WGLEW_FUN_EXPORT PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV; +WGLEW_FUN_EXPORT PFNWGLDELAYBEFORESWAPNVPROC __wglewDelayBeforeSwapNV; + WGLEW_FUN_EXPORT PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV; WGLEW_FUN_EXPORT PFNWGLDELETEDCNVPROC __wglewDeleteDCNV; WGLEW_FUN_EXPORT PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV; @@ -1371,6 +1387,7 @@ WGLEW_VAR_EXPORT GLboolean __WGLEW_I3D_swap_frame_usage; WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_DX_interop; WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_DX_interop2; WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_copy_image; +WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_delay_before_swap; WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_float_buffer; WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_gpu_affinity; WGLEW_VAR_EXPORT GLboolean __WGLEW_NV_multisample_coverage; diff --git a/ext/glew/glew.c b/ext/glew/glew.c index d075b52488..2239864d68 100644 --- a/ext/glew/glew.c +++ b/ext/glew/glew.c @@ -1,5 +1,6 @@ /* ** The OpenGL Extension Wrangler Library +** Copyright (C) 2008-2014, Nigel Stewart ** Copyright (C) 2002-2008, Milan Ikits ** Copyright (C) 2002-2008, Marcelo E. Magallon ** Copyright (C) 2002, Lev Povalahev @@ -33,10 +34,12 @@ #if defined(_WIN32) # include -#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) +#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) # include #endif +#include /* For size_t */ + /* * Define glewGetContext and related helper macros. */ @@ -66,7 +69,23 @@ # define GLXEW_CONTEXT_ARG_DEF_LIST void #endif /* GLEW_MX */ -#if defined(__sgi) || defined (__sun) || defined(GLEW_APPLE_GLX) +#if defined(GLEW_REGAL) + +/* In GLEW_REGAL mode we call direcly into the linked + libRegal.so glGetProcAddressREGAL for looking up + the GL function pointers. */ + +# undef glGetProcAddressREGAL +# ifdef WIN32 +extern void * __stdcall glGetProcAddressREGAL(const GLchar *name); +static void * (__stdcall * regalGetProcAddress) (const GLchar *) = glGetProcAddressREGAL; +# else +extern void * glGetProcAddressREGAL(const GLchar *name); +static void * (*regalGetProcAddress) (const GLchar *) = glGetProcAddressREGAL; +# endif +# define glGetProcAddressREGAL GLEW_GET_FUN(__glewGetProcAddressREGAL) + +#elif defined(__sgi) || defined (__sun) || defined(__HAIKU__) || defined(GLEW_APPLE_GLX) #include #include #include @@ -104,11 +123,7 @@ void* NSGLGetProcAddress (const GLubyte *name) void* addr; if (NULL == image) { -#ifdef GLEW_REGAL - image = dlopen("libRegal.dylib", RTLD_LAZY); -#else image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); -#endif } if( !image ) return NULL; addr = dlsym(image, (const char*)name); @@ -130,11 +145,7 @@ void* NSGLGetProcAddress (const GLubyte *name) char* symbolName; if (NULL == image) { -#ifdef GLEW_REGAL - image = NSAddImage("libRegal.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR); -#else image = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", NSADDIMAGE_OPTION_RETURN_ON_ERROR); -#endif } /* prepend a '_' for the Unix C symbol mangling convention */ symbolName = malloc(strlen((const char*)name) + 2); @@ -158,11 +169,13 @@ void* NSGLGetProcAddress (const GLubyte *name) /* * Define glewGetProcAddress. */ -#if defined(_WIN32) +#if defined(GLEW_REGAL) +# define glewGetProcAddress(name) regalGetProcAddress((const GLchar *) name) +#elif defined(_WIN32) # define glewGetProcAddress(name) wglGetProcAddress((LPCSTR)name) #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) # define glewGetProcAddress(name) NSGLGetProcAddress(name) -#elif defined(__sgi) || defined(__sun) +#elif defined(__sgi) || defined(__sun) || defined(__HAIKU__) # define glewGetProcAddress(name) dlGetProcAddress(name) #elif defined(__ANDROID__) # define glewGetProcAddress(name) NULL /* TODO */ @@ -173,9 +186,33 @@ void* NSGLGetProcAddress (const GLubyte *name) #endif /* - * Define GLboolean const cast. + * Redefine GLEW_GET_VAR etc without const cast */ -#define CONST_CAST(x) (*(GLboolean*)&x) + +#undef GLEW_GET_VAR +#ifdef GLEW_MX +# define GLEW_GET_VAR(x) (glewGetContext()->x) +#else /* GLEW_MX */ +# define GLEW_GET_VAR(x) (x) +#endif /* GLEW_MX */ + +#ifdef WGLEW_GET_VAR +# undef WGLEW_GET_VAR +# ifdef GLEW_MX +# define WGLEW_GET_VAR(x) (wglewGetContext()->x) +# else /* GLEW_MX */ +# define WGLEW_GET_VAR(x) (x) +# endif /* GLEW_MX */ +#endif /* WGLEW_GET_VAR */ + +#ifdef GLXEW_GET_VAR +# undef GLXEW_GET_VAR +# ifdef GLEW_MX +# define GLXEW_GET_VAR(x) (glxewGetContext()->x) +# else /* GLEW_MX */ +# define GLXEW_GET_VAR(x) (x) +# endif /* GLEW_MX */ +#endif /* GLXEW_GET_VAR */ /* * GLEW, just like OpenGL or GLU, does not rely on the standard C library. @@ -596,6 +633,8 @@ PFNGLDELETENAMESAMDPROC __glewDeleteNamesAMD = NULL; PFNGLGENNAMESAMDPROC __glewGenNamesAMD = NULL; PFNGLISNAMEAMDPROC __glewIsNameAMD = NULL; +PFNGLQUERYOBJECTPARAMETERUIAMDPROC __glewQueryObjectParameteruiAMD = NULL; + PFNGLBEGINPERFMONITORAMDPROC __glewBeginPerfMonitorAMD = NULL; PFNGLDELETEPERFMONITORSAMDPROC __glewDeletePerfMonitorsAMD = NULL; PFNGLENDPERFMONITORAMDPROC __glewEndPerfMonitorAMD = NULL; @@ -1199,6 +1238,12 @@ PFNGLVERTEXATTRIBL4DVPROC __glewVertexAttribL4dv = NULL; PFNGLVERTEXATTRIBLPOINTERPROC __glewVertexAttribLPointer = NULL; PFNGLBINDVERTEXBUFFERPROC __glewBindVertexBuffer = NULL; +PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC __glewVertexArrayBindVertexBufferEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC __glewVertexArrayVertexAttribBindingEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC __glewVertexArrayVertexAttribFormatEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC __glewVertexArrayVertexAttribIFormatEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC __glewVertexArrayVertexAttribLFormatEXT = NULL; +PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC __glewVertexArrayVertexBindingDivisorEXT = NULL; PFNGLVERTEXATTRIBBINDINGPROC __glewVertexAttribBinding = NULL; PFNGLVERTEXATTRIBFORMATPROC __glewVertexAttribFormat = NULL; PFNGLVERTEXATTRIBIFORMATPROC __glewVertexAttribIFormat = NULL; @@ -1504,6 +1549,9 @@ PFNGLCOPYTEXSUBIMAGE3DEXTPROC __glewCopyTexSubImage3DEXT = NULL; PFNGLCULLPARAMETERDVEXTPROC __glewCullParameterdvEXT = NULL; PFNGLCULLPARAMETERFVEXTPROC __glewCullParameterfvEXT = NULL; +PFNGLGETOBJECTLABELEXTPROC __glewGetObjectLabelEXT = NULL; +PFNGLLABELOBJECTEXTPROC __glewLabelObjectEXT = NULL; + PFNGLINSERTEVENTMARKEREXTPROC __glewInsertEventMarkerEXT = NULL; PFNGLPOPGROUPMARKEREXTPROC __glewPopGroupMarkerEXT = NULL; PFNGLPUSHGROUPMARKEREXTPROC __glewPushGroupMarkerEXT = NULL; @@ -1720,6 +1768,7 @@ PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC __glewVertexArrayMultiTexCoordOffsetE PFNGLVERTEXARRAYNORMALOFFSETEXTPROC __glewVertexArrayNormalOffsetEXT = NULL; PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC __glewVertexArraySecondaryColorOffsetEXT = NULL; PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC __glewVertexArrayTexCoordOffsetEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC __glewVertexArrayVertexAttribDivisorEXT = NULL; PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC __glewVertexArrayVertexAttribIOffsetEXT = NULL; PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC __glewVertexArrayVertexAttribOffsetEXT = NULL; PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC __glewVertexArrayVertexOffsetEXT = NULL; @@ -2038,6 +2087,17 @@ PFNGLNORMALPOINTERVINTELPROC __glewNormalPointervINTEL = NULL; PFNGLTEXCOORDPOINTERVINTELPROC __glewTexCoordPointervINTEL = NULL; PFNGLVERTEXPOINTERVINTELPROC __glewVertexPointervINTEL = NULL; +PFNGLBEGINPERFQUERYINTELPROC __glewBeginPerfQueryINTEL = NULL; +PFNGLCREATEPERFQUERYINTELPROC __glewCreatePerfQueryINTEL = NULL; +PFNGLDELETEPERFQUERYINTELPROC __glewDeletePerfQueryINTEL = NULL; +PFNGLENDPERFQUERYINTELPROC __glewEndPerfQueryINTEL = NULL; +PFNGLGETFIRSTPERFQUERYIDINTELPROC __glewGetFirstPerfQueryIdINTEL = NULL; +PFNGLGETNEXTPERFQUERYIDINTELPROC __glewGetNextPerfQueryIdINTEL = NULL; +PFNGLGETPERFCOUNTERINFOINTELPROC __glewGetPerfCounterInfoINTEL = NULL; +PFNGLGETPERFQUERYDATAINTELPROC __glewGetPerfQueryDataINTEL = NULL; +PFNGLGETPERFQUERYIDBYNAMEINTELPROC __glewGetPerfQueryIdByNameINTEL = NULL; +PFNGLGETPERFQUERYINFOINTELPROC __glewGetPerfQueryInfoINTEL = NULL; + PFNGLTEXSCISSORFUNCINTELPROC __glewTexScissorFuncINTEL = NULL; PFNGLTEXSCISSORINTELPROC __glewTexScissorINTEL = NULL; @@ -2570,6 +2630,8 @@ PFNGLISSUPPORTEDREGALPROC __glewIsSupportedREGAL = NULL; PFNGLLOGMESSAGECALLBACKREGALPROC __glewLogMessageCallbackREGAL = NULL; +PFNGLGETPROCADDRESSREGALPROC __glewGetProcAddressREGAL = NULL; + PFNGLDETAILTEXFUNCSGISPROC __glewDetailTexFuncSGIS = NULL; PFNGLGETDETAILTEXFUNCSGISPROC __glewGetDetailTexFuncSGIS = NULL; @@ -2731,20 +2793,26 @@ GLboolean __GLEW_AMD_conservative_depth = GL_FALSE; GLboolean __GLEW_AMD_debug_output = GL_FALSE; GLboolean __GLEW_AMD_depth_clamp_separate = GL_FALSE; GLboolean __GLEW_AMD_draw_buffers_blend = GL_FALSE; +GLboolean __GLEW_AMD_gcn_shader = GL_FALSE; +GLboolean __GLEW_AMD_gpu_shader_int64 = GL_FALSE; GLboolean __GLEW_AMD_interleaved_elements = GL_FALSE; GLboolean __GLEW_AMD_multi_draw_indirect = GL_FALSE; GLboolean __GLEW_AMD_name_gen_delete = GL_FALSE; +GLboolean __GLEW_AMD_occlusion_query_event = GL_FALSE; GLboolean __GLEW_AMD_performance_monitor = GL_FALSE; GLboolean __GLEW_AMD_pinned_memory = GL_FALSE; GLboolean __GLEW_AMD_query_buffer_object = GL_FALSE; GLboolean __GLEW_AMD_sample_positions = GL_FALSE; GLboolean __GLEW_AMD_seamless_cubemap_per_texture = GL_FALSE; +GLboolean __GLEW_AMD_shader_atomic_counter_ops = GL_FALSE; GLboolean __GLEW_AMD_shader_stencil_export = GL_FALSE; +GLboolean __GLEW_AMD_shader_stencil_value_export = GL_FALSE; GLboolean __GLEW_AMD_shader_trinary_minmax = GL_FALSE; GLboolean __GLEW_AMD_sparse_texture = GL_FALSE; GLboolean __GLEW_AMD_stencil_operation_extended = GL_FALSE; GLboolean __GLEW_AMD_texture_texture4 = GL_FALSE; GLboolean __GLEW_AMD_transform_feedback3_lines_triangles = GL_FALSE; +GLboolean __GLEW_AMD_transform_feedback4 = GL_FALSE; GLboolean __GLEW_AMD_vertex_shader_layer = GL_FALSE; GLboolean __GLEW_AMD_vertex_shader_tessellator = GL_FALSE; GLboolean __GLEW_AMD_vertex_shader_viewport_index = GL_FALSE; @@ -2960,6 +3028,7 @@ GLboolean __GLEW_EXT_convolution = GL_FALSE; GLboolean __GLEW_EXT_coordinate_frame = GL_FALSE; GLboolean __GLEW_EXT_copy_texture = GL_FALSE; GLboolean __GLEW_EXT_cull_vertex = GL_FALSE; +GLboolean __GLEW_EXT_debug_label = GL_FALSE; GLboolean __GLEW_EXT_debug_marker = GL_FALSE; GLboolean __GLEW_EXT_depth_bounds_test = GL_FALSE; GLboolean __GLEW_EXT_direct_state_access = GL_FALSE; @@ -3000,7 +3069,9 @@ GLboolean __GLEW_EXT_scene_marker = GL_FALSE; GLboolean __GLEW_EXT_secondary_color = GL_FALSE; GLboolean __GLEW_EXT_separate_shader_objects = GL_FALSE; GLboolean __GLEW_EXT_separate_specular_color = GL_FALSE; +GLboolean __GLEW_EXT_shader_image_load_formatted = GL_FALSE; GLboolean __GLEW_EXT_shader_image_load_store = GL_FALSE; +GLboolean __GLEW_EXT_shader_integer_mix = GL_FALSE; GLboolean __GLEW_EXT_shadow_funcs = GL_FALSE; GLboolean __GLEW_EXT_shared_texture_palette = GL_FALSE; GLboolean __GLEW_EXT_stencil_clear_tag = GL_FALSE; @@ -3055,10 +3126,13 @@ GLboolean __GLEW_IBM_texture_mirrored_repeat = GL_FALSE; GLboolean __GLEW_IBM_vertex_array_lists = GL_FALSE; GLboolean __GLEW_INGR_color_clamp = GL_FALSE; GLboolean __GLEW_INGR_interlace_read = GL_FALSE; +GLboolean __GLEW_INTEL_fragment_shader_ordering = GL_FALSE; GLboolean __GLEW_INTEL_map_texture = GL_FALSE; GLboolean __GLEW_INTEL_parallel_arrays = GL_FALSE; +GLboolean __GLEW_INTEL_performance_query = GL_FALSE; GLboolean __GLEW_INTEL_texture_scissor = GL_FALSE; GLboolean __GLEW_KHR_debug = GL_FALSE; +GLboolean __GLEW_KHR_texture_compression_astc_hdr = GL_FALSE; GLboolean __GLEW_KHR_texture_compression_astc_ldr = GL_FALSE; GLboolean __GLEW_KTX_buffer_region = GL_FALSE; GLboolean __GLEW_MESAX_texture_stack = GL_FALSE; @@ -3118,6 +3192,8 @@ GLboolean __GLEW_NV_shader_atomic_counters = GL_FALSE; GLboolean __GLEW_NV_shader_atomic_float = GL_FALSE; GLboolean __GLEW_NV_shader_buffer_load = GL_FALSE; GLboolean __GLEW_NV_shader_storage_buffer_object = GL_FALSE; +GLboolean __GLEW_NV_shader_thread_group = GL_FALSE; +GLboolean __GLEW_NV_shader_thread_shuffle = GL_FALSE; GLboolean __GLEW_NV_tessellation_program5 = GL_FALSE; GLboolean __GLEW_NV_texgen_emboss = GL_FALSE; GLboolean __GLEW_NV_texgen_reflection = GL_FALSE; @@ -3159,6 +3235,7 @@ GLboolean __GLEW_REGAL_enable = GL_FALSE; GLboolean __GLEW_REGAL_error_string = GL_FALSE; GLboolean __GLEW_REGAL_extension_query = GL_FALSE; GLboolean __GLEW_REGAL_log = GL_FALSE; +GLboolean __GLEW_REGAL_proc_address = GL_FALSE; GLboolean __GLEW_REND_screen_coordinates = GL_FALSE; GLboolean __GLEW_S3_s3tc = GL_FALSE; GLboolean __GLEW_SGIS_color_range = GL_FALSE; @@ -3724,6 +3801,14 @@ static GLboolean _glewInit_GL_AMD_draw_buffers_blend (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_AMD_draw_buffers_blend */ +#ifdef GL_AMD_gcn_shader + +#endif /* GL_AMD_gcn_shader */ + +#ifdef GL_AMD_gpu_shader_int64 + +#endif /* GL_AMD_gpu_shader_int64 */ + #ifdef GL_AMD_interleaved_elements static GLboolean _glewInit_GL_AMD_interleaved_elements (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3766,6 +3851,19 @@ static GLboolean _glewInit_GL_AMD_name_gen_delete (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_AMD_name_gen_delete */ +#ifdef GL_AMD_occlusion_query_event + +static GLboolean _glewInit_GL_AMD_occlusion_query_event (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glQueryObjectParameteruiAMD = (PFNGLQUERYOBJECTPARAMETERUIAMDPROC)glewGetProcAddress((const GLubyte*)"glQueryObjectParameteruiAMD")) == NULL) || r; + + return r; +} + +#endif /* GL_AMD_occlusion_query_event */ + #ifdef GL_AMD_performance_monitor static GLboolean _glewInit_GL_AMD_performance_monitor (GLEW_CONTEXT_ARG_DEF_INIT) @@ -3814,10 +3912,18 @@ static GLboolean _glewInit_GL_AMD_sample_positions (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_AMD_seamless_cubemap_per_texture */ +#ifdef GL_AMD_shader_atomic_counter_ops + +#endif /* GL_AMD_shader_atomic_counter_ops */ + #ifdef GL_AMD_shader_stencil_export #endif /* GL_AMD_shader_stencil_export */ +#ifdef GL_AMD_shader_stencil_value_export + +#endif /* GL_AMD_shader_stencil_value_export */ + #ifdef GL_AMD_shader_trinary_minmax #endif /* GL_AMD_shader_trinary_minmax */ @@ -3857,6 +3963,10 @@ static GLboolean _glewInit_GL_AMD_stencil_operation_extended (GLEW_CONTEXT_ARG_D #endif /* GL_AMD_transform_feedback3_lines_triangles */ +#ifdef GL_AMD_transform_feedback4 + +#endif /* GL_AMD_transform_feedback4 */ + #ifdef GL_AMD_vertex_shader_layer #endif /* GL_AMD_vertex_shader_layer */ @@ -5679,6 +5789,12 @@ static GLboolean _glewInit_GL_ARB_vertex_attrib_binding (GLEW_CONTEXT_ARG_DEF_IN GLboolean r = GL_FALSE; r = ((glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindVertexBuffer")) == NULL) || r; + r = ((glVertexArrayBindVertexBufferEXT = (PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayBindVertexBufferEXT")) == NULL) || r; + r = ((glVertexArrayVertexAttribBindingEXT = (PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribBindingEXT")) == NULL) || r; + r = ((glVertexArrayVertexAttribFormatEXT = (PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribFormatEXT")) == NULL) || r; + r = ((glVertexArrayVertexAttribIFormatEXT = (PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribIFormatEXT")) == NULL) || r; + r = ((glVertexArrayVertexAttribLFormatEXT = (PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribLFormatEXT")) == NULL) || r; + r = ((glVertexArrayVertexBindingDivisorEXT = (PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexBindingDivisorEXT")) == NULL) || r; r = ((glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribBinding")) == NULL) || r; r = ((glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribFormat")) == NULL) || r; r = ((glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribIFormat")) == NULL) || r; @@ -6377,6 +6493,20 @@ static GLboolean _glewInit_GL_EXT_cull_vertex (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_EXT_cull_vertex */ +#ifdef GL_EXT_debug_label + +static GLboolean _glewInit_GL_EXT_debug_label (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetObjectLabelEXT = (PFNGLGETOBJECTLABELEXTPROC)glewGetProcAddress((const GLubyte*)"glGetObjectLabelEXT")) == NULL) || r; + r = ((glLabelObjectEXT = (PFNGLLABELOBJECTEXTPROC)glewGetProcAddress((const GLubyte*)"glLabelObjectEXT")) == NULL) || r; + + return r; +} + +#endif /* GL_EXT_debug_label */ + #ifdef GL_EXT_debug_marker static GLboolean _glewInit_GL_EXT_debug_marker (GLEW_CONTEXT_ARG_DEF_INIT) @@ -6621,6 +6751,7 @@ static GLboolean _glewInit_GL_EXT_direct_state_access (GLEW_CONTEXT_ARG_DEF_INIT r = ((glVertexArrayNormalOffsetEXT = (PFNGLVERTEXARRAYNORMALOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayNormalOffsetEXT")) == NULL) || r; r = ((glVertexArraySecondaryColorOffsetEXT = (PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArraySecondaryColorOffsetEXT")) == NULL) || r; r = ((glVertexArrayTexCoordOffsetEXT = (PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayTexCoordOffsetEXT")) == NULL) || r; + r = ((glVertexArrayVertexAttribDivisorEXT = (PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribDivisorEXT")) == NULL) || r; r = ((glVertexArrayVertexAttribIOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribIOffsetEXT")) == NULL) || r; r = ((glVertexArrayVertexAttribOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexAttribOffsetEXT")) == NULL) || r; r = ((glVertexArrayVertexOffsetEXT = (PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC)glewGetProcAddress((const GLubyte*)"glVertexArrayVertexOffsetEXT")) == NULL) || r; @@ -7123,6 +7254,10 @@ static GLboolean _glewInit_GL_EXT_separate_shader_objects (GLEW_CONTEXT_ARG_DEF_ #endif /* GL_EXT_separate_specular_color */ +#ifdef GL_EXT_shader_image_load_formatted + +#endif /* GL_EXT_shader_image_load_formatted */ + #ifdef GL_EXT_shader_image_load_store static GLboolean _glewInit_GL_EXT_shader_image_load_store (GLEW_CONTEXT_ARG_DEF_INIT) @@ -7137,6 +7272,10 @@ static GLboolean _glewInit_GL_EXT_shader_image_load_store (GLEW_CONTEXT_ARG_DEF_ #endif /* GL_EXT_shader_image_load_store */ +#ifdef GL_EXT_shader_integer_mix + +#endif /* GL_EXT_shader_integer_mix */ + #ifdef GL_EXT_shadow_funcs #endif /* GL_EXT_shadow_funcs */ @@ -7625,6 +7764,10 @@ static GLboolean _glewInit_GL_IBM_vertex_array_lists (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_INGR_interlace_read */ +#ifdef GL_INTEL_fragment_shader_ordering + +#endif /* GL_INTEL_fragment_shader_ordering */ + #ifdef GL_INTEL_map_texture static GLboolean _glewInit_GL_INTEL_map_texture (GLEW_CONTEXT_ARG_DEF_INIT) @@ -7656,6 +7799,28 @@ static GLboolean _glewInit_GL_INTEL_parallel_arrays (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_INTEL_parallel_arrays */ +#ifdef GL_INTEL_performance_query + +static GLboolean _glewInit_GL_INTEL_performance_query (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glBeginPerfQueryINTEL = (PFNGLBEGINPERFQUERYINTELPROC)glewGetProcAddress((const GLubyte*)"glBeginPerfQueryINTEL")) == NULL) || r; + r = ((glCreatePerfQueryINTEL = (PFNGLCREATEPERFQUERYINTELPROC)glewGetProcAddress((const GLubyte*)"glCreatePerfQueryINTEL")) == NULL) || r; + r = ((glDeletePerfQueryINTEL = (PFNGLDELETEPERFQUERYINTELPROC)glewGetProcAddress((const GLubyte*)"glDeletePerfQueryINTEL")) == NULL) || r; + r = ((glEndPerfQueryINTEL = (PFNGLENDPERFQUERYINTELPROC)glewGetProcAddress((const GLubyte*)"glEndPerfQueryINTEL")) == NULL) || r; + r = ((glGetFirstPerfQueryIdINTEL = (PFNGLGETFIRSTPERFQUERYIDINTELPROC)glewGetProcAddress((const GLubyte*)"glGetFirstPerfQueryIdINTEL")) == NULL) || r; + r = ((glGetNextPerfQueryIdINTEL = (PFNGLGETNEXTPERFQUERYIDINTELPROC)glewGetProcAddress((const GLubyte*)"glGetNextPerfQueryIdINTEL")) == NULL) || r; + r = ((glGetPerfCounterInfoINTEL = (PFNGLGETPERFCOUNTERINFOINTELPROC)glewGetProcAddress((const GLubyte*)"glGetPerfCounterInfoINTEL")) == NULL) || r; + r = ((glGetPerfQueryDataINTEL = (PFNGLGETPERFQUERYDATAINTELPROC)glewGetProcAddress((const GLubyte*)"glGetPerfQueryDataINTEL")) == NULL) || r; + r = ((glGetPerfQueryIdByNameINTEL = (PFNGLGETPERFQUERYIDBYNAMEINTELPROC)glewGetProcAddress((const GLubyte*)"glGetPerfQueryIdByNameINTEL")) == NULL) || r; + r = ((glGetPerfQueryInfoINTEL = (PFNGLGETPERFQUERYINFOINTELPROC)glewGetProcAddress((const GLubyte*)"glGetPerfQueryInfoINTEL")) == NULL) || r; + + return r; +} + +#endif /* GL_INTEL_performance_query */ + #ifdef GL_INTEL_texture_scissor static GLboolean _glewInit_GL_INTEL_texture_scissor (GLEW_CONTEXT_ARG_DEF_INIT) @@ -7692,6 +7857,10 @@ static GLboolean _glewInit_GL_KHR_debug (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_KHR_debug */ +#ifdef GL_KHR_texture_compression_astc_hdr + +#endif /* GL_KHR_texture_compression_astc_hdr */ + #ifdef GL_KHR_texture_compression_astc_ldr #endif /* GL_KHR_texture_compression_astc_ldr */ @@ -8442,6 +8611,14 @@ static GLboolean _glewInit_GL_NV_shader_buffer_load (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_NV_shader_storage_buffer_object */ +#ifdef GL_NV_shader_thread_group + +#endif /* GL_NV_shader_thread_group */ + +#ifdef GL_NV_shader_thread_shuffle + +#endif /* GL_NV_shader_thread_shuffle */ + #ifdef GL_NV_tessellation_program5 #endif /* GL_NV_tessellation_program5 */ @@ -8932,6 +9109,19 @@ static GLboolean _glewInit_GL_REGAL_log (GLEW_CONTEXT_ARG_DEF_INIT) #endif /* GL_REGAL_log */ +#ifdef GL_REGAL_proc_address + +static GLboolean _glewInit_GL_REGAL_proc_address (GLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glGetProcAddressREGAL = (PFNGLGETPROCADDRESSREGALPROC)glewGetProcAddress((const GLubyte*)"glGetProcAddressREGAL")) == NULL) || r; + + return r; +} + +#endif /* GL_REGAL_proc_address */ + #ifdef GL_REND_screen_coordinates #endif /* GL_REND_screen_coordinates */ @@ -9512,23 +9702,23 @@ GLenum GLEWAPIENTRY glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) } else { - CONST_CAST(GLEW_VERSION_4_4) = ( major > 4 ) || ( major == 4 && minor >= 4 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_4_3) = GLEW_VERSION_4_4 == GL_TRUE || ( major == 4 && minor >= 3 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_4_2) = GLEW_VERSION_4_3 == GL_TRUE || ( major == 4 && minor >= 2 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_4_1) = GLEW_VERSION_4_2 == GL_TRUE || ( major == 4 && minor >= 1 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_4_0) = GLEW_VERSION_4_1 == GL_TRUE || ( major == 4 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_3_3) = GLEW_VERSION_4_0 == GL_TRUE || ( major == 3 && minor >= 3 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_3_2) = GLEW_VERSION_3_3 == GL_TRUE || ( major == 3 && minor >= 2 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_3_1) = GLEW_VERSION_3_2 == GL_TRUE || ( major == 3 && minor >= 1 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_3_0) = GLEW_VERSION_3_1 == GL_TRUE || ( major == 3 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_2_1) = GLEW_VERSION_3_0 == GL_TRUE || ( major == 2 && minor >= 1 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_2_0) = GLEW_VERSION_2_1 == GL_TRUE || ( major == 2 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_1_5) = GLEW_VERSION_2_0 == GL_TRUE || ( major == 1 && minor >= 5 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_1_4) = GLEW_VERSION_1_5 == GL_TRUE || ( major == 1 && minor >= 4 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_1_3) = GLEW_VERSION_1_4 == GL_TRUE || ( major == 1 && minor >= 3 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_1_2_1) = GLEW_VERSION_1_3 == GL_TRUE ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_1_2) = GLEW_VERSION_1_2_1 == GL_TRUE || ( major == 1 && minor >= 2 ) ? GL_TRUE : GL_FALSE; - CONST_CAST(GLEW_VERSION_1_1) = GLEW_VERSION_1_2 == GL_TRUE || ( major == 1 && minor >= 1 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_4_4 = ( major > 4 ) || ( major == 4 && minor >= 4 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_4_3 = GLEW_VERSION_4_4 == GL_TRUE || ( major == 4 && minor >= 3 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_4_2 = GLEW_VERSION_4_3 == GL_TRUE || ( major == 4 && minor >= 2 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_4_1 = GLEW_VERSION_4_2 == GL_TRUE || ( major == 4 && minor >= 1 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_4_0 = GLEW_VERSION_4_1 == GL_TRUE || ( major == 4 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_3_3 = GLEW_VERSION_4_0 == GL_TRUE || ( major == 3 && minor >= 3 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_3_2 = GLEW_VERSION_3_3 == GL_TRUE || ( major == 3 && minor >= 2 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_3_1 = GLEW_VERSION_3_2 == GL_TRUE || ( major == 3 && minor >= 1 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_3_0 = GLEW_VERSION_3_1 == GL_TRUE || ( major == 3 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_2_1 = GLEW_VERSION_3_0 == GL_TRUE || ( major == 2 && minor >= 1 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_2_0 = GLEW_VERSION_2_1 == GL_TRUE || ( major == 2 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_1_5 = GLEW_VERSION_2_0 == GL_TRUE || ( major == 1 && minor >= 5 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_1_4 = GLEW_VERSION_1_5 == GL_TRUE || ( major == 1 && minor >= 4 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_1_3 = GLEW_VERSION_1_4 == GL_TRUE || ( major == 1 && minor >= 3 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_1_2_1 = GLEW_VERSION_1_3 == GL_TRUE ? GL_TRUE : GL_FALSE; + GLEW_VERSION_1_2 = GLEW_VERSION_1_2_1 == GL_TRUE || ( major == 1 && minor >= 2 ) ? GL_TRUE : GL_FALSE; + GLEW_VERSION_1_1 = GLEW_VERSION_1_2 == GL_TRUE || ( major == 1 && minor >= 1 ) ? GL_TRUE : GL_FALSE; } /* query opengl extensions string */ @@ -9539,39 +9729,39 @@ GLenum GLEWAPIENTRY glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) /* initialize extensions */ #ifdef GL_VERSION_1_2 - if (glewExperimental || GLEW_VERSION_1_2) CONST_CAST(GLEW_VERSION_1_2) = !_glewInit_GL_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_1_2) GLEW_VERSION_1_2 = !_glewInit_GL_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_1_2 */ #ifdef GL_VERSION_1_2_1 #endif /* GL_VERSION_1_2_1 */ #ifdef GL_VERSION_1_3 - if (glewExperimental || GLEW_VERSION_1_3) CONST_CAST(GLEW_VERSION_1_3) = !_glewInit_GL_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_1_3) GLEW_VERSION_1_3 = !_glewInit_GL_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_1_3 */ #ifdef GL_VERSION_1_4 - if (glewExperimental || GLEW_VERSION_1_4) CONST_CAST(GLEW_VERSION_1_4) = !_glewInit_GL_VERSION_1_4(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_1_4) GLEW_VERSION_1_4 = !_glewInit_GL_VERSION_1_4(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_1_4 */ #ifdef GL_VERSION_1_5 - if (glewExperimental || GLEW_VERSION_1_5) CONST_CAST(GLEW_VERSION_1_5) = !_glewInit_GL_VERSION_1_5(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_1_5) GLEW_VERSION_1_5 = !_glewInit_GL_VERSION_1_5(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_1_5 */ #ifdef GL_VERSION_2_0 - if (glewExperimental || GLEW_VERSION_2_0) CONST_CAST(GLEW_VERSION_2_0) = !_glewInit_GL_VERSION_2_0(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_2_0) GLEW_VERSION_2_0 = !_glewInit_GL_VERSION_2_0(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_2_0 */ #ifdef GL_VERSION_2_1 - if (glewExperimental || GLEW_VERSION_2_1) CONST_CAST(GLEW_VERSION_2_1) = !_glewInit_GL_VERSION_2_1(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_2_1) GLEW_VERSION_2_1 = !_glewInit_GL_VERSION_2_1(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_2_1 */ #ifdef GL_VERSION_3_0 - if (glewExperimental || GLEW_VERSION_3_0) CONST_CAST(GLEW_VERSION_3_0) = !_glewInit_GL_VERSION_3_0(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_3_0) GLEW_VERSION_3_0 = !_glewInit_GL_VERSION_3_0(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_3_0 */ #ifdef GL_VERSION_3_1 - if (glewExperimental || GLEW_VERSION_3_1) CONST_CAST(GLEW_VERSION_3_1) = !_glewInit_GL_VERSION_3_1(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_3_1) GLEW_VERSION_3_1 = !_glewInit_GL_VERSION_3_1(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_3_1 */ #ifdef GL_VERSION_3_2 - if (glewExperimental || GLEW_VERSION_3_2) CONST_CAST(GLEW_VERSION_3_2) = !_glewInit_GL_VERSION_3_2(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_3_2) GLEW_VERSION_3_2 = !_glewInit_GL_VERSION_3_2(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_3_2 */ #ifdef GL_VERSION_3_3 - if (glewExperimental || GLEW_VERSION_3_3) CONST_CAST(GLEW_VERSION_3_3) = !_glewInit_GL_VERSION_3_3(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_3_3) GLEW_VERSION_3_3 = !_glewInit_GL_VERSION_3_3(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_3_3 */ #ifdef GL_VERSION_4_0 - if (glewExperimental || GLEW_VERSION_4_0) CONST_CAST(GLEW_VERSION_4_0) = !_glewInit_GL_VERSION_4_0(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLEW_VERSION_4_0) GLEW_VERSION_4_0 = !_glewInit_GL_VERSION_4_0(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_VERSION_4_0 */ #ifdef GL_VERSION_4_1 #endif /* GL_VERSION_4_1 */ @@ -9582,1739 +9772,1788 @@ GLenum GLEWAPIENTRY glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST) #ifdef GL_VERSION_4_4 #endif /* GL_VERSION_4_4 */ #ifdef GL_3DFX_multisample - CONST_CAST(GLEW_3DFX_multisample) = _glewSearchExtension("GL_3DFX_multisample", extStart, extEnd); + GLEW_3DFX_multisample = _glewSearchExtension("GL_3DFX_multisample", extStart, extEnd); #endif /* GL_3DFX_multisample */ #ifdef GL_3DFX_tbuffer - CONST_CAST(GLEW_3DFX_tbuffer) = _glewSearchExtension("GL_3DFX_tbuffer", extStart, extEnd); - if (glewExperimental || GLEW_3DFX_tbuffer) CONST_CAST(GLEW_3DFX_tbuffer) = !_glewInit_GL_3DFX_tbuffer(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_3DFX_tbuffer = _glewSearchExtension("GL_3DFX_tbuffer", extStart, extEnd); + if (glewExperimental || GLEW_3DFX_tbuffer) GLEW_3DFX_tbuffer = !_glewInit_GL_3DFX_tbuffer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_3DFX_tbuffer */ #ifdef GL_3DFX_texture_compression_FXT1 - CONST_CAST(GLEW_3DFX_texture_compression_FXT1) = _glewSearchExtension("GL_3DFX_texture_compression_FXT1", extStart, extEnd); + GLEW_3DFX_texture_compression_FXT1 = _glewSearchExtension("GL_3DFX_texture_compression_FXT1", extStart, extEnd); #endif /* GL_3DFX_texture_compression_FXT1 */ #ifdef GL_AMD_blend_minmax_factor - CONST_CAST(GLEW_AMD_blend_minmax_factor) = _glewSearchExtension("GL_AMD_blend_minmax_factor", extStart, extEnd); + GLEW_AMD_blend_minmax_factor = _glewSearchExtension("GL_AMD_blend_minmax_factor", extStart, extEnd); #endif /* GL_AMD_blend_minmax_factor */ #ifdef GL_AMD_conservative_depth - CONST_CAST(GLEW_AMD_conservative_depth) = _glewSearchExtension("GL_AMD_conservative_depth", extStart, extEnd); + GLEW_AMD_conservative_depth = _glewSearchExtension("GL_AMD_conservative_depth", extStart, extEnd); #endif /* GL_AMD_conservative_depth */ #ifdef GL_AMD_debug_output - CONST_CAST(GLEW_AMD_debug_output) = _glewSearchExtension("GL_AMD_debug_output", extStart, extEnd); - if (glewExperimental || GLEW_AMD_debug_output) CONST_CAST(GLEW_AMD_debug_output) = !_glewInit_GL_AMD_debug_output(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_AMD_debug_output = _glewSearchExtension("GL_AMD_debug_output", extStart, extEnd); + if (glewExperimental || GLEW_AMD_debug_output) GLEW_AMD_debug_output = !_glewInit_GL_AMD_debug_output(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_debug_output */ #ifdef GL_AMD_depth_clamp_separate - CONST_CAST(GLEW_AMD_depth_clamp_separate) = _glewSearchExtension("GL_AMD_depth_clamp_separate", extStart, extEnd); + GLEW_AMD_depth_clamp_separate = _glewSearchExtension("GL_AMD_depth_clamp_separate", extStart, extEnd); #endif /* GL_AMD_depth_clamp_separate */ #ifdef GL_AMD_draw_buffers_blend - CONST_CAST(GLEW_AMD_draw_buffers_blend) = _glewSearchExtension("GL_AMD_draw_buffers_blend", extStart, extEnd); - if (glewExperimental || GLEW_AMD_draw_buffers_blend) CONST_CAST(GLEW_AMD_draw_buffers_blend) = !_glewInit_GL_AMD_draw_buffers_blend(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_AMD_draw_buffers_blend = _glewSearchExtension("GL_AMD_draw_buffers_blend", extStart, extEnd); + if (glewExperimental || GLEW_AMD_draw_buffers_blend) GLEW_AMD_draw_buffers_blend = !_glewInit_GL_AMD_draw_buffers_blend(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_draw_buffers_blend */ +#ifdef GL_AMD_gcn_shader + GLEW_AMD_gcn_shader = _glewSearchExtension("GL_AMD_gcn_shader", extStart, extEnd); +#endif /* GL_AMD_gcn_shader */ +#ifdef GL_AMD_gpu_shader_int64 + GLEW_AMD_gpu_shader_int64 = _glewSearchExtension("GL_AMD_gpu_shader_int64", extStart, extEnd); +#endif /* GL_AMD_gpu_shader_int64 */ #ifdef GL_AMD_interleaved_elements - CONST_CAST(GLEW_AMD_interleaved_elements) = _glewSearchExtension("GL_AMD_interleaved_elements", extStart, extEnd); - if (glewExperimental || GLEW_AMD_interleaved_elements) CONST_CAST(GLEW_AMD_interleaved_elements) = !_glewInit_GL_AMD_interleaved_elements(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_AMD_interleaved_elements = _glewSearchExtension("GL_AMD_interleaved_elements", extStart, extEnd); + if (glewExperimental || GLEW_AMD_interleaved_elements) GLEW_AMD_interleaved_elements = !_glewInit_GL_AMD_interleaved_elements(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_interleaved_elements */ #ifdef GL_AMD_multi_draw_indirect - CONST_CAST(GLEW_AMD_multi_draw_indirect) = _glewSearchExtension("GL_AMD_multi_draw_indirect", extStart, extEnd); - if (glewExperimental || GLEW_AMD_multi_draw_indirect) CONST_CAST(GLEW_AMD_multi_draw_indirect) = !_glewInit_GL_AMD_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_AMD_multi_draw_indirect = _glewSearchExtension("GL_AMD_multi_draw_indirect", extStart, extEnd); + if (glewExperimental || GLEW_AMD_multi_draw_indirect) GLEW_AMD_multi_draw_indirect = !_glewInit_GL_AMD_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_multi_draw_indirect */ #ifdef GL_AMD_name_gen_delete - CONST_CAST(GLEW_AMD_name_gen_delete) = _glewSearchExtension("GL_AMD_name_gen_delete", extStart, extEnd); - if (glewExperimental || GLEW_AMD_name_gen_delete) CONST_CAST(GLEW_AMD_name_gen_delete) = !_glewInit_GL_AMD_name_gen_delete(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_AMD_name_gen_delete = _glewSearchExtension("GL_AMD_name_gen_delete", extStart, extEnd); + if (glewExperimental || GLEW_AMD_name_gen_delete) GLEW_AMD_name_gen_delete = !_glewInit_GL_AMD_name_gen_delete(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_name_gen_delete */ +#ifdef GL_AMD_occlusion_query_event + GLEW_AMD_occlusion_query_event = _glewSearchExtension("GL_AMD_occlusion_query_event", extStart, extEnd); + if (glewExperimental || GLEW_AMD_occlusion_query_event) GLEW_AMD_occlusion_query_event = !_glewInit_GL_AMD_occlusion_query_event(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_AMD_occlusion_query_event */ #ifdef GL_AMD_performance_monitor - CONST_CAST(GLEW_AMD_performance_monitor) = _glewSearchExtension("GL_AMD_performance_monitor", extStart, extEnd); - if (glewExperimental || GLEW_AMD_performance_monitor) CONST_CAST(GLEW_AMD_performance_monitor) = !_glewInit_GL_AMD_performance_monitor(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_AMD_performance_monitor = _glewSearchExtension("GL_AMD_performance_monitor", extStart, extEnd); + if (glewExperimental || GLEW_AMD_performance_monitor) GLEW_AMD_performance_monitor = !_glewInit_GL_AMD_performance_monitor(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_performance_monitor */ #ifdef GL_AMD_pinned_memory - CONST_CAST(GLEW_AMD_pinned_memory) = _glewSearchExtension("GL_AMD_pinned_memory", extStart, extEnd); + GLEW_AMD_pinned_memory = _glewSearchExtension("GL_AMD_pinned_memory", extStart, extEnd); #endif /* GL_AMD_pinned_memory */ #ifdef GL_AMD_query_buffer_object - CONST_CAST(GLEW_AMD_query_buffer_object) = _glewSearchExtension("GL_AMD_query_buffer_object", extStart, extEnd); + GLEW_AMD_query_buffer_object = _glewSearchExtension("GL_AMD_query_buffer_object", extStart, extEnd); #endif /* GL_AMD_query_buffer_object */ #ifdef GL_AMD_sample_positions - CONST_CAST(GLEW_AMD_sample_positions) = _glewSearchExtension("GL_AMD_sample_positions", extStart, extEnd); - if (glewExperimental || GLEW_AMD_sample_positions) CONST_CAST(GLEW_AMD_sample_positions) = !_glewInit_GL_AMD_sample_positions(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_AMD_sample_positions = _glewSearchExtension("GL_AMD_sample_positions", extStart, extEnd); + if (glewExperimental || GLEW_AMD_sample_positions) GLEW_AMD_sample_positions = !_glewInit_GL_AMD_sample_positions(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_sample_positions */ #ifdef GL_AMD_seamless_cubemap_per_texture - CONST_CAST(GLEW_AMD_seamless_cubemap_per_texture) = _glewSearchExtension("GL_AMD_seamless_cubemap_per_texture", extStart, extEnd); + GLEW_AMD_seamless_cubemap_per_texture = _glewSearchExtension("GL_AMD_seamless_cubemap_per_texture", extStart, extEnd); #endif /* GL_AMD_seamless_cubemap_per_texture */ +#ifdef GL_AMD_shader_atomic_counter_ops + GLEW_AMD_shader_atomic_counter_ops = _glewSearchExtension("GL_AMD_shader_atomic_counter_ops", extStart, extEnd); +#endif /* GL_AMD_shader_atomic_counter_ops */ #ifdef GL_AMD_shader_stencil_export - CONST_CAST(GLEW_AMD_shader_stencil_export) = _glewSearchExtension("GL_AMD_shader_stencil_export", extStart, extEnd); + GLEW_AMD_shader_stencil_export = _glewSearchExtension("GL_AMD_shader_stencil_export", extStart, extEnd); #endif /* GL_AMD_shader_stencil_export */ +#ifdef GL_AMD_shader_stencil_value_export + GLEW_AMD_shader_stencil_value_export = _glewSearchExtension("GL_AMD_shader_stencil_value_export", extStart, extEnd); +#endif /* GL_AMD_shader_stencil_value_export */ #ifdef GL_AMD_shader_trinary_minmax - CONST_CAST(GLEW_AMD_shader_trinary_minmax) = _glewSearchExtension("GL_AMD_shader_trinary_minmax", extStart, extEnd); + GLEW_AMD_shader_trinary_minmax = _glewSearchExtension("GL_AMD_shader_trinary_minmax", extStart, extEnd); #endif /* GL_AMD_shader_trinary_minmax */ #ifdef GL_AMD_sparse_texture - CONST_CAST(GLEW_AMD_sparse_texture) = _glewSearchExtension("GL_AMD_sparse_texture", extStart, extEnd); - if (glewExperimental || GLEW_AMD_sparse_texture) CONST_CAST(GLEW_AMD_sparse_texture) = !_glewInit_GL_AMD_sparse_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_AMD_sparse_texture = _glewSearchExtension("GL_AMD_sparse_texture", extStart, extEnd); + if (glewExperimental || GLEW_AMD_sparse_texture) GLEW_AMD_sparse_texture = !_glewInit_GL_AMD_sparse_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_sparse_texture */ #ifdef GL_AMD_stencil_operation_extended - CONST_CAST(GLEW_AMD_stencil_operation_extended) = _glewSearchExtension("GL_AMD_stencil_operation_extended", extStart, extEnd); - if (glewExperimental || GLEW_AMD_stencil_operation_extended) CONST_CAST(GLEW_AMD_stencil_operation_extended) = !_glewInit_GL_AMD_stencil_operation_extended(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_AMD_stencil_operation_extended = _glewSearchExtension("GL_AMD_stencil_operation_extended", extStart, extEnd); + if (glewExperimental || GLEW_AMD_stencil_operation_extended) GLEW_AMD_stencil_operation_extended = !_glewInit_GL_AMD_stencil_operation_extended(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_stencil_operation_extended */ #ifdef GL_AMD_texture_texture4 - CONST_CAST(GLEW_AMD_texture_texture4) = _glewSearchExtension("GL_AMD_texture_texture4", extStart, extEnd); + GLEW_AMD_texture_texture4 = _glewSearchExtension("GL_AMD_texture_texture4", extStart, extEnd); #endif /* GL_AMD_texture_texture4 */ #ifdef GL_AMD_transform_feedback3_lines_triangles - CONST_CAST(GLEW_AMD_transform_feedback3_lines_triangles) = _glewSearchExtension("GL_AMD_transform_feedback3_lines_triangles", extStart, extEnd); + GLEW_AMD_transform_feedback3_lines_triangles = _glewSearchExtension("GL_AMD_transform_feedback3_lines_triangles", extStart, extEnd); #endif /* GL_AMD_transform_feedback3_lines_triangles */ +#ifdef GL_AMD_transform_feedback4 + GLEW_AMD_transform_feedback4 = _glewSearchExtension("GL_AMD_transform_feedback4", extStart, extEnd); +#endif /* GL_AMD_transform_feedback4 */ #ifdef GL_AMD_vertex_shader_layer - CONST_CAST(GLEW_AMD_vertex_shader_layer) = _glewSearchExtension("GL_AMD_vertex_shader_layer", extStart, extEnd); + GLEW_AMD_vertex_shader_layer = _glewSearchExtension("GL_AMD_vertex_shader_layer", extStart, extEnd); #endif /* GL_AMD_vertex_shader_layer */ #ifdef GL_AMD_vertex_shader_tessellator - CONST_CAST(GLEW_AMD_vertex_shader_tessellator) = _glewSearchExtension("GL_AMD_vertex_shader_tessellator", extStart, extEnd); - if (glewExperimental || GLEW_AMD_vertex_shader_tessellator) CONST_CAST(GLEW_AMD_vertex_shader_tessellator) = !_glewInit_GL_AMD_vertex_shader_tessellator(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_AMD_vertex_shader_tessellator = _glewSearchExtension("GL_AMD_vertex_shader_tessellator", extStart, extEnd); + if (glewExperimental || GLEW_AMD_vertex_shader_tessellator) GLEW_AMD_vertex_shader_tessellator = !_glewInit_GL_AMD_vertex_shader_tessellator(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_AMD_vertex_shader_tessellator */ #ifdef GL_AMD_vertex_shader_viewport_index - CONST_CAST(GLEW_AMD_vertex_shader_viewport_index) = _glewSearchExtension("GL_AMD_vertex_shader_viewport_index", extStart, extEnd); + GLEW_AMD_vertex_shader_viewport_index = _glewSearchExtension("GL_AMD_vertex_shader_viewport_index", extStart, extEnd); #endif /* GL_AMD_vertex_shader_viewport_index */ #ifdef GL_ANGLE_depth_texture - CONST_CAST(GLEW_ANGLE_depth_texture) = _glewSearchExtension("GL_ANGLE_depth_texture", extStart, extEnd); + GLEW_ANGLE_depth_texture = _glewSearchExtension("GL_ANGLE_depth_texture", extStart, extEnd); #endif /* GL_ANGLE_depth_texture */ #ifdef GL_ANGLE_framebuffer_blit - CONST_CAST(GLEW_ANGLE_framebuffer_blit) = _glewSearchExtension("GL_ANGLE_framebuffer_blit", extStart, extEnd); - if (glewExperimental || GLEW_ANGLE_framebuffer_blit) CONST_CAST(GLEW_ANGLE_framebuffer_blit) = !_glewInit_GL_ANGLE_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ANGLE_framebuffer_blit = _glewSearchExtension("GL_ANGLE_framebuffer_blit", extStart, extEnd); + if (glewExperimental || GLEW_ANGLE_framebuffer_blit) GLEW_ANGLE_framebuffer_blit = !_glewInit_GL_ANGLE_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ANGLE_framebuffer_blit */ #ifdef GL_ANGLE_framebuffer_multisample - CONST_CAST(GLEW_ANGLE_framebuffer_multisample) = _glewSearchExtension("GL_ANGLE_framebuffer_multisample", extStart, extEnd); - if (glewExperimental || GLEW_ANGLE_framebuffer_multisample) CONST_CAST(GLEW_ANGLE_framebuffer_multisample) = !_glewInit_GL_ANGLE_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ANGLE_framebuffer_multisample = _glewSearchExtension("GL_ANGLE_framebuffer_multisample", extStart, extEnd); + if (glewExperimental || GLEW_ANGLE_framebuffer_multisample) GLEW_ANGLE_framebuffer_multisample = !_glewInit_GL_ANGLE_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ANGLE_framebuffer_multisample */ #ifdef GL_ANGLE_instanced_arrays - CONST_CAST(GLEW_ANGLE_instanced_arrays) = _glewSearchExtension("GL_ANGLE_instanced_arrays", extStart, extEnd); - if (glewExperimental || GLEW_ANGLE_instanced_arrays) CONST_CAST(GLEW_ANGLE_instanced_arrays) = !_glewInit_GL_ANGLE_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ANGLE_instanced_arrays = _glewSearchExtension("GL_ANGLE_instanced_arrays", extStart, extEnd); + if (glewExperimental || GLEW_ANGLE_instanced_arrays) GLEW_ANGLE_instanced_arrays = !_glewInit_GL_ANGLE_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ANGLE_instanced_arrays */ #ifdef GL_ANGLE_pack_reverse_row_order - CONST_CAST(GLEW_ANGLE_pack_reverse_row_order) = _glewSearchExtension("GL_ANGLE_pack_reverse_row_order", extStart, extEnd); + GLEW_ANGLE_pack_reverse_row_order = _glewSearchExtension("GL_ANGLE_pack_reverse_row_order", extStart, extEnd); #endif /* GL_ANGLE_pack_reverse_row_order */ #ifdef GL_ANGLE_program_binary - CONST_CAST(GLEW_ANGLE_program_binary) = _glewSearchExtension("GL_ANGLE_program_binary", extStart, extEnd); + GLEW_ANGLE_program_binary = _glewSearchExtension("GL_ANGLE_program_binary", extStart, extEnd); #endif /* GL_ANGLE_program_binary */ #ifdef GL_ANGLE_texture_compression_dxt1 - CONST_CAST(GLEW_ANGLE_texture_compression_dxt1) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt1", extStart, extEnd); + GLEW_ANGLE_texture_compression_dxt1 = _glewSearchExtension("GL_ANGLE_texture_compression_dxt1", extStart, extEnd); #endif /* GL_ANGLE_texture_compression_dxt1 */ #ifdef GL_ANGLE_texture_compression_dxt3 - CONST_CAST(GLEW_ANGLE_texture_compression_dxt3) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt3", extStart, extEnd); + GLEW_ANGLE_texture_compression_dxt3 = _glewSearchExtension("GL_ANGLE_texture_compression_dxt3", extStart, extEnd); #endif /* GL_ANGLE_texture_compression_dxt3 */ #ifdef GL_ANGLE_texture_compression_dxt5 - CONST_CAST(GLEW_ANGLE_texture_compression_dxt5) = _glewSearchExtension("GL_ANGLE_texture_compression_dxt5", extStart, extEnd); + GLEW_ANGLE_texture_compression_dxt5 = _glewSearchExtension("GL_ANGLE_texture_compression_dxt5", extStart, extEnd); #endif /* GL_ANGLE_texture_compression_dxt5 */ #ifdef GL_ANGLE_texture_usage - CONST_CAST(GLEW_ANGLE_texture_usage) = _glewSearchExtension("GL_ANGLE_texture_usage", extStart, extEnd); + GLEW_ANGLE_texture_usage = _glewSearchExtension("GL_ANGLE_texture_usage", extStart, extEnd); #endif /* GL_ANGLE_texture_usage */ #ifdef GL_ANGLE_timer_query - CONST_CAST(GLEW_ANGLE_timer_query) = _glewSearchExtension("GL_ANGLE_timer_query", extStart, extEnd); - if (glewExperimental || GLEW_ANGLE_timer_query) CONST_CAST(GLEW_ANGLE_timer_query) = !_glewInit_GL_ANGLE_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ANGLE_timer_query = _glewSearchExtension("GL_ANGLE_timer_query", extStart, extEnd); + if (glewExperimental || GLEW_ANGLE_timer_query) GLEW_ANGLE_timer_query = !_glewInit_GL_ANGLE_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ANGLE_timer_query */ #ifdef GL_ANGLE_translated_shader_source - CONST_CAST(GLEW_ANGLE_translated_shader_source) = _glewSearchExtension("GL_ANGLE_translated_shader_source", extStart, extEnd); - if (glewExperimental || GLEW_ANGLE_translated_shader_source) CONST_CAST(GLEW_ANGLE_translated_shader_source) = !_glewInit_GL_ANGLE_translated_shader_source(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ANGLE_translated_shader_source = _glewSearchExtension("GL_ANGLE_translated_shader_source", extStart, extEnd); + if (glewExperimental || GLEW_ANGLE_translated_shader_source) GLEW_ANGLE_translated_shader_source = !_glewInit_GL_ANGLE_translated_shader_source(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ANGLE_translated_shader_source */ #ifdef GL_APPLE_aux_depth_stencil - CONST_CAST(GLEW_APPLE_aux_depth_stencil) = _glewSearchExtension("GL_APPLE_aux_depth_stencil", extStart, extEnd); + GLEW_APPLE_aux_depth_stencil = _glewSearchExtension("GL_APPLE_aux_depth_stencil", extStart, extEnd); #endif /* GL_APPLE_aux_depth_stencil */ #ifdef GL_APPLE_client_storage - CONST_CAST(GLEW_APPLE_client_storage) = _glewSearchExtension("GL_APPLE_client_storage", extStart, extEnd); + GLEW_APPLE_client_storage = _glewSearchExtension("GL_APPLE_client_storage", extStart, extEnd); #endif /* GL_APPLE_client_storage */ #ifdef GL_APPLE_element_array - CONST_CAST(GLEW_APPLE_element_array) = _glewSearchExtension("GL_APPLE_element_array", extStart, extEnd); - if (glewExperimental || GLEW_APPLE_element_array) CONST_CAST(GLEW_APPLE_element_array) = !_glewInit_GL_APPLE_element_array(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_APPLE_element_array = _glewSearchExtension("GL_APPLE_element_array", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_element_array) GLEW_APPLE_element_array = !_glewInit_GL_APPLE_element_array(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_APPLE_element_array */ #ifdef GL_APPLE_fence - CONST_CAST(GLEW_APPLE_fence) = _glewSearchExtension("GL_APPLE_fence", extStart, extEnd); - if (glewExperimental || GLEW_APPLE_fence) CONST_CAST(GLEW_APPLE_fence) = !_glewInit_GL_APPLE_fence(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_APPLE_fence = _glewSearchExtension("GL_APPLE_fence", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_fence) GLEW_APPLE_fence = !_glewInit_GL_APPLE_fence(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_APPLE_fence */ #ifdef GL_APPLE_float_pixels - CONST_CAST(GLEW_APPLE_float_pixels) = _glewSearchExtension("GL_APPLE_float_pixels", extStart, extEnd); + GLEW_APPLE_float_pixels = _glewSearchExtension("GL_APPLE_float_pixels", extStart, extEnd); #endif /* GL_APPLE_float_pixels */ #ifdef GL_APPLE_flush_buffer_range - CONST_CAST(GLEW_APPLE_flush_buffer_range) = _glewSearchExtension("GL_APPLE_flush_buffer_range", extStart, extEnd); - if (glewExperimental || GLEW_APPLE_flush_buffer_range) CONST_CAST(GLEW_APPLE_flush_buffer_range) = !_glewInit_GL_APPLE_flush_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_APPLE_flush_buffer_range = _glewSearchExtension("GL_APPLE_flush_buffer_range", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_flush_buffer_range) GLEW_APPLE_flush_buffer_range = !_glewInit_GL_APPLE_flush_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_APPLE_flush_buffer_range */ #ifdef GL_APPLE_object_purgeable - CONST_CAST(GLEW_APPLE_object_purgeable) = _glewSearchExtension("GL_APPLE_object_purgeable", extStart, extEnd); - if (glewExperimental || GLEW_APPLE_object_purgeable) CONST_CAST(GLEW_APPLE_object_purgeable) = !_glewInit_GL_APPLE_object_purgeable(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_APPLE_object_purgeable = _glewSearchExtension("GL_APPLE_object_purgeable", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_object_purgeable) GLEW_APPLE_object_purgeable = !_glewInit_GL_APPLE_object_purgeable(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_APPLE_object_purgeable */ #ifdef GL_APPLE_pixel_buffer - CONST_CAST(GLEW_APPLE_pixel_buffer) = _glewSearchExtension("GL_APPLE_pixel_buffer", extStart, extEnd); + GLEW_APPLE_pixel_buffer = _glewSearchExtension("GL_APPLE_pixel_buffer", extStart, extEnd); #endif /* GL_APPLE_pixel_buffer */ #ifdef GL_APPLE_rgb_422 - CONST_CAST(GLEW_APPLE_rgb_422) = _glewSearchExtension("GL_APPLE_rgb_422", extStart, extEnd); + GLEW_APPLE_rgb_422 = _glewSearchExtension("GL_APPLE_rgb_422", extStart, extEnd); #endif /* GL_APPLE_rgb_422 */ #ifdef GL_APPLE_row_bytes - CONST_CAST(GLEW_APPLE_row_bytes) = _glewSearchExtension("GL_APPLE_row_bytes", extStart, extEnd); + GLEW_APPLE_row_bytes = _glewSearchExtension("GL_APPLE_row_bytes", extStart, extEnd); #endif /* GL_APPLE_row_bytes */ #ifdef GL_APPLE_specular_vector - CONST_CAST(GLEW_APPLE_specular_vector) = _glewSearchExtension("GL_APPLE_specular_vector", extStart, extEnd); + GLEW_APPLE_specular_vector = _glewSearchExtension("GL_APPLE_specular_vector", extStart, extEnd); #endif /* GL_APPLE_specular_vector */ #ifdef GL_APPLE_texture_range - CONST_CAST(GLEW_APPLE_texture_range) = _glewSearchExtension("GL_APPLE_texture_range", extStart, extEnd); - if (glewExperimental || GLEW_APPLE_texture_range) CONST_CAST(GLEW_APPLE_texture_range) = !_glewInit_GL_APPLE_texture_range(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_APPLE_texture_range = _glewSearchExtension("GL_APPLE_texture_range", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_texture_range) GLEW_APPLE_texture_range = !_glewInit_GL_APPLE_texture_range(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_APPLE_texture_range */ #ifdef GL_APPLE_transform_hint - CONST_CAST(GLEW_APPLE_transform_hint) = _glewSearchExtension("GL_APPLE_transform_hint", extStart, extEnd); + GLEW_APPLE_transform_hint = _glewSearchExtension("GL_APPLE_transform_hint", extStart, extEnd); #endif /* GL_APPLE_transform_hint */ #ifdef GL_APPLE_vertex_array_object - CONST_CAST(GLEW_APPLE_vertex_array_object) = _glewSearchExtension("GL_APPLE_vertex_array_object", extStart, extEnd); - if (glewExperimental || GLEW_APPLE_vertex_array_object) CONST_CAST(GLEW_APPLE_vertex_array_object) = !_glewInit_GL_APPLE_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_APPLE_vertex_array_object = _glewSearchExtension("GL_APPLE_vertex_array_object", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_vertex_array_object) GLEW_APPLE_vertex_array_object = !_glewInit_GL_APPLE_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_APPLE_vertex_array_object */ #ifdef GL_APPLE_vertex_array_range - CONST_CAST(GLEW_APPLE_vertex_array_range) = _glewSearchExtension("GL_APPLE_vertex_array_range", extStart, extEnd); - if (glewExperimental || GLEW_APPLE_vertex_array_range) CONST_CAST(GLEW_APPLE_vertex_array_range) = !_glewInit_GL_APPLE_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_APPLE_vertex_array_range = _glewSearchExtension("GL_APPLE_vertex_array_range", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_vertex_array_range) GLEW_APPLE_vertex_array_range = !_glewInit_GL_APPLE_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_APPLE_vertex_array_range */ #ifdef GL_APPLE_vertex_program_evaluators - CONST_CAST(GLEW_APPLE_vertex_program_evaluators) = _glewSearchExtension("GL_APPLE_vertex_program_evaluators", extStart, extEnd); - if (glewExperimental || GLEW_APPLE_vertex_program_evaluators) CONST_CAST(GLEW_APPLE_vertex_program_evaluators) = !_glewInit_GL_APPLE_vertex_program_evaluators(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_APPLE_vertex_program_evaluators = _glewSearchExtension("GL_APPLE_vertex_program_evaluators", extStart, extEnd); + if (glewExperimental || GLEW_APPLE_vertex_program_evaluators) GLEW_APPLE_vertex_program_evaluators = !_glewInit_GL_APPLE_vertex_program_evaluators(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_APPLE_vertex_program_evaluators */ #ifdef GL_APPLE_ycbcr_422 - CONST_CAST(GLEW_APPLE_ycbcr_422) = _glewSearchExtension("GL_APPLE_ycbcr_422", extStart, extEnd); + GLEW_APPLE_ycbcr_422 = _glewSearchExtension("GL_APPLE_ycbcr_422", extStart, extEnd); #endif /* GL_APPLE_ycbcr_422 */ #ifdef GL_ARB_ES2_compatibility - CONST_CAST(GLEW_ARB_ES2_compatibility) = _glewSearchExtension("GL_ARB_ES2_compatibility", extStart, extEnd); - if (glewExperimental || GLEW_ARB_ES2_compatibility) CONST_CAST(GLEW_ARB_ES2_compatibility) = !_glewInit_GL_ARB_ES2_compatibility(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_ES2_compatibility = _glewSearchExtension("GL_ARB_ES2_compatibility", extStart, extEnd); + if (glewExperimental || GLEW_ARB_ES2_compatibility) GLEW_ARB_ES2_compatibility = !_glewInit_GL_ARB_ES2_compatibility(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_ES2_compatibility */ #ifdef GL_ARB_ES3_compatibility - CONST_CAST(GLEW_ARB_ES3_compatibility) = _glewSearchExtension("GL_ARB_ES3_compatibility", extStart, extEnd); + GLEW_ARB_ES3_compatibility = _glewSearchExtension("GL_ARB_ES3_compatibility", extStart, extEnd); #endif /* GL_ARB_ES3_compatibility */ #ifdef GL_ARB_arrays_of_arrays - CONST_CAST(GLEW_ARB_arrays_of_arrays) = _glewSearchExtension("GL_ARB_arrays_of_arrays", extStart, extEnd); + GLEW_ARB_arrays_of_arrays = _glewSearchExtension("GL_ARB_arrays_of_arrays", extStart, extEnd); #endif /* GL_ARB_arrays_of_arrays */ #ifdef GL_ARB_base_instance - CONST_CAST(GLEW_ARB_base_instance) = _glewSearchExtension("GL_ARB_base_instance", extStart, extEnd); - if (glewExperimental || GLEW_ARB_base_instance) CONST_CAST(GLEW_ARB_base_instance) = !_glewInit_GL_ARB_base_instance(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_base_instance = _glewSearchExtension("GL_ARB_base_instance", extStart, extEnd); + if (glewExperimental || GLEW_ARB_base_instance) GLEW_ARB_base_instance = !_glewInit_GL_ARB_base_instance(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_base_instance */ #ifdef GL_ARB_bindless_texture - CONST_CAST(GLEW_ARB_bindless_texture) = _glewSearchExtension("GL_ARB_bindless_texture", extStart, extEnd); - if (glewExperimental || GLEW_ARB_bindless_texture) CONST_CAST(GLEW_ARB_bindless_texture) = !_glewInit_GL_ARB_bindless_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_bindless_texture = _glewSearchExtension("GL_ARB_bindless_texture", extStart, extEnd); + if (glewExperimental || GLEW_ARB_bindless_texture) GLEW_ARB_bindless_texture = !_glewInit_GL_ARB_bindless_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_bindless_texture */ #ifdef GL_ARB_blend_func_extended - CONST_CAST(GLEW_ARB_blend_func_extended) = _glewSearchExtension("GL_ARB_blend_func_extended", extStart, extEnd); - if (glewExperimental || GLEW_ARB_blend_func_extended) CONST_CAST(GLEW_ARB_blend_func_extended) = !_glewInit_GL_ARB_blend_func_extended(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_blend_func_extended = _glewSearchExtension("GL_ARB_blend_func_extended", extStart, extEnd); + if (glewExperimental || GLEW_ARB_blend_func_extended) GLEW_ARB_blend_func_extended = !_glewInit_GL_ARB_blend_func_extended(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_blend_func_extended */ #ifdef GL_ARB_buffer_storage - CONST_CAST(GLEW_ARB_buffer_storage) = _glewSearchExtension("GL_ARB_buffer_storage", extStart, extEnd); - if (glewExperimental || GLEW_ARB_buffer_storage) CONST_CAST(GLEW_ARB_buffer_storage) = !_glewInit_GL_ARB_buffer_storage(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_buffer_storage = _glewSearchExtension("GL_ARB_buffer_storage", extStart, extEnd); + if (glewExperimental || GLEW_ARB_buffer_storage) GLEW_ARB_buffer_storage = !_glewInit_GL_ARB_buffer_storage(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_buffer_storage */ #ifdef GL_ARB_cl_event - CONST_CAST(GLEW_ARB_cl_event) = _glewSearchExtension("GL_ARB_cl_event", extStart, extEnd); - if (glewExperimental || GLEW_ARB_cl_event) CONST_CAST(GLEW_ARB_cl_event) = !_glewInit_GL_ARB_cl_event(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_cl_event = _glewSearchExtension("GL_ARB_cl_event", extStart, extEnd); + if (glewExperimental || GLEW_ARB_cl_event) GLEW_ARB_cl_event = !_glewInit_GL_ARB_cl_event(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_cl_event */ #ifdef GL_ARB_clear_buffer_object - CONST_CAST(GLEW_ARB_clear_buffer_object) = _glewSearchExtension("GL_ARB_clear_buffer_object", extStart, extEnd); - if (glewExperimental || GLEW_ARB_clear_buffer_object) CONST_CAST(GLEW_ARB_clear_buffer_object) = !_glewInit_GL_ARB_clear_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_clear_buffer_object = _glewSearchExtension("GL_ARB_clear_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_clear_buffer_object) GLEW_ARB_clear_buffer_object = !_glewInit_GL_ARB_clear_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_clear_buffer_object */ #ifdef GL_ARB_clear_texture - CONST_CAST(GLEW_ARB_clear_texture) = _glewSearchExtension("GL_ARB_clear_texture", extStart, extEnd); - if (glewExperimental || GLEW_ARB_clear_texture) CONST_CAST(GLEW_ARB_clear_texture) = !_glewInit_GL_ARB_clear_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_clear_texture = _glewSearchExtension("GL_ARB_clear_texture", extStart, extEnd); + if (glewExperimental || GLEW_ARB_clear_texture) GLEW_ARB_clear_texture = !_glewInit_GL_ARB_clear_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_clear_texture */ #ifdef GL_ARB_color_buffer_float - CONST_CAST(GLEW_ARB_color_buffer_float) = _glewSearchExtension("GL_ARB_color_buffer_float", extStart, extEnd); - if (glewExperimental || GLEW_ARB_color_buffer_float) CONST_CAST(GLEW_ARB_color_buffer_float) = !_glewInit_GL_ARB_color_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_color_buffer_float = _glewSearchExtension("GL_ARB_color_buffer_float", extStart, extEnd); + if (glewExperimental || GLEW_ARB_color_buffer_float) GLEW_ARB_color_buffer_float = !_glewInit_GL_ARB_color_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_color_buffer_float */ #ifdef GL_ARB_compatibility - CONST_CAST(GLEW_ARB_compatibility) = _glewSearchExtension("GL_ARB_compatibility", extStart, extEnd); + GLEW_ARB_compatibility = _glewSearchExtension("GL_ARB_compatibility", extStart, extEnd); #endif /* GL_ARB_compatibility */ #ifdef GL_ARB_compressed_texture_pixel_storage - CONST_CAST(GLEW_ARB_compressed_texture_pixel_storage) = _glewSearchExtension("GL_ARB_compressed_texture_pixel_storage", extStart, extEnd); + GLEW_ARB_compressed_texture_pixel_storage = _glewSearchExtension("GL_ARB_compressed_texture_pixel_storage", extStart, extEnd); #endif /* GL_ARB_compressed_texture_pixel_storage */ #ifdef GL_ARB_compute_shader - CONST_CAST(GLEW_ARB_compute_shader) = _glewSearchExtension("GL_ARB_compute_shader", extStart, extEnd); - if (glewExperimental || GLEW_ARB_compute_shader) CONST_CAST(GLEW_ARB_compute_shader) = !_glewInit_GL_ARB_compute_shader(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_compute_shader = _glewSearchExtension("GL_ARB_compute_shader", extStart, extEnd); + if (glewExperimental || GLEW_ARB_compute_shader) GLEW_ARB_compute_shader = !_glewInit_GL_ARB_compute_shader(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_compute_shader */ #ifdef GL_ARB_compute_variable_group_size - CONST_CAST(GLEW_ARB_compute_variable_group_size) = _glewSearchExtension("GL_ARB_compute_variable_group_size", extStart, extEnd); - if (glewExperimental || GLEW_ARB_compute_variable_group_size) CONST_CAST(GLEW_ARB_compute_variable_group_size) = !_glewInit_GL_ARB_compute_variable_group_size(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_compute_variable_group_size = _glewSearchExtension("GL_ARB_compute_variable_group_size", extStart, extEnd); + if (glewExperimental || GLEW_ARB_compute_variable_group_size) GLEW_ARB_compute_variable_group_size = !_glewInit_GL_ARB_compute_variable_group_size(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_compute_variable_group_size */ #ifdef GL_ARB_conservative_depth - CONST_CAST(GLEW_ARB_conservative_depth) = _glewSearchExtension("GL_ARB_conservative_depth", extStart, extEnd); + GLEW_ARB_conservative_depth = _glewSearchExtension("GL_ARB_conservative_depth", extStart, extEnd); #endif /* GL_ARB_conservative_depth */ #ifdef GL_ARB_copy_buffer - CONST_CAST(GLEW_ARB_copy_buffer) = _glewSearchExtension("GL_ARB_copy_buffer", extStart, extEnd); - if (glewExperimental || GLEW_ARB_copy_buffer) CONST_CAST(GLEW_ARB_copy_buffer) = !_glewInit_GL_ARB_copy_buffer(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_copy_buffer = _glewSearchExtension("GL_ARB_copy_buffer", extStart, extEnd); + if (glewExperimental || GLEW_ARB_copy_buffer) GLEW_ARB_copy_buffer = !_glewInit_GL_ARB_copy_buffer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_copy_buffer */ #ifdef GL_ARB_copy_image - CONST_CAST(GLEW_ARB_copy_image) = _glewSearchExtension("GL_ARB_copy_image", extStart, extEnd); - if (glewExperimental || GLEW_ARB_copy_image) CONST_CAST(GLEW_ARB_copy_image) = !_glewInit_GL_ARB_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_copy_image = _glewSearchExtension("GL_ARB_copy_image", extStart, extEnd); + if (glewExperimental || GLEW_ARB_copy_image) GLEW_ARB_copy_image = !_glewInit_GL_ARB_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_copy_image */ #ifdef GL_ARB_debug_output - CONST_CAST(GLEW_ARB_debug_output) = _glewSearchExtension("GL_ARB_debug_output", extStart, extEnd); - if (glewExperimental || GLEW_ARB_debug_output) CONST_CAST(GLEW_ARB_debug_output) = !_glewInit_GL_ARB_debug_output(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_debug_output = _glewSearchExtension("GL_ARB_debug_output", extStart, extEnd); + if (glewExperimental || GLEW_ARB_debug_output) GLEW_ARB_debug_output = !_glewInit_GL_ARB_debug_output(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_debug_output */ #ifdef GL_ARB_depth_buffer_float - CONST_CAST(GLEW_ARB_depth_buffer_float) = _glewSearchExtension("GL_ARB_depth_buffer_float", extStart, extEnd); + GLEW_ARB_depth_buffer_float = _glewSearchExtension("GL_ARB_depth_buffer_float", extStart, extEnd); #endif /* GL_ARB_depth_buffer_float */ #ifdef GL_ARB_depth_clamp - CONST_CAST(GLEW_ARB_depth_clamp) = _glewSearchExtension("GL_ARB_depth_clamp", extStart, extEnd); + GLEW_ARB_depth_clamp = _glewSearchExtension("GL_ARB_depth_clamp", extStart, extEnd); #endif /* GL_ARB_depth_clamp */ #ifdef GL_ARB_depth_texture - CONST_CAST(GLEW_ARB_depth_texture) = _glewSearchExtension("GL_ARB_depth_texture", extStart, extEnd); + GLEW_ARB_depth_texture = _glewSearchExtension("GL_ARB_depth_texture", extStart, extEnd); #endif /* GL_ARB_depth_texture */ #ifdef GL_ARB_draw_buffers - CONST_CAST(GLEW_ARB_draw_buffers) = _glewSearchExtension("GL_ARB_draw_buffers", extStart, extEnd); - if (glewExperimental || GLEW_ARB_draw_buffers) CONST_CAST(GLEW_ARB_draw_buffers) = !_glewInit_GL_ARB_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_draw_buffers = _glewSearchExtension("GL_ARB_draw_buffers", extStart, extEnd); + if (glewExperimental || GLEW_ARB_draw_buffers) GLEW_ARB_draw_buffers = !_glewInit_GL_ARB_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_draw_buffers */ #ifdef GL_ARB_draw_buffers_blend - CONST_CAST(GLEW_ARB_draw_buffers_blend) = _glewSearchExtension("GL_ARB_draw_buffers_blend", extStart, extEnd); - if (glewExperimental || GLEW_ARB_draw_buffers_blend) CONST_CAST(GLEW_ARB_draw_buffers_blend) = !_glewInit_GL_ARB_draw_buffers_blend(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_draw_buffers_blend = _glewSearchExtension("GL_ARB_draw_buffers_blend", extStart, extEnd); + if (glewExperimental || GLEW_ARB_draw_buffers_blend) GLEW_ARB_draw_buffers_blend = !_glewInit_GL_ARB_draw_buffers_blend(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_draw_buffers_blend */ #ifdef GL_ARB_draw_elements_base_vertex - CONST_CAST(GLEW_ARB_draw_elements_base_vertex) = _glewSearchExtension("GL_ARB_draw_elements_base_vertex", extStart, extEnd); - if (glewExperimental || GLEW_ARB_draw_elements_base_vertex) CONST_CAST(GLEW_ARB_draw_elements_base_vertex) = !_glewInit_GL_ARB_draw_elements_base_vertex(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_draw_elements_base_vertex = _glewSearchExtension("GL_ARB_draw_elements_base_vertex", extStart, extEnd); + if (glewExperimental || GLEW_ARB_draw_elements_base_vertex) GLEW_ARB_draw_elements_base_vertex = !_glewInit_GL_ARB_draw_elements_base_vertex(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_draw_elements_base_vertex */ #ifdef GL_ARB_draw_indirect - CONST_CAST(GLEW_ARB_draw_indirect) = _glewSearchExtension("GL_ARB_draw_indirect", extStart, extEnd); - if (glewExperimental || GLEW_ARB_draw_indirect) CONST_CAST(GLEW_ARB_draw_indirect) = !_glewInit_GL_ARB_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_draw_indirect = _glewSearchExtension("GL_ARB_draw_indirect", extStart, extEnd); + if (glewExperimental || GLEW_ARB_draw_indirect) GLEW_ARB_draw_indirect = !_glewInit_GL_ARB_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_draw_indirect */ #ifdef GL_ARB_draw_instanced - CONST_CAST(GLEW_ARB_draw_instanced) = _glewSearchExtension("GL_ARB_draw_instanced", extStart, extEnd); + GLEW_ARB_draw_instanced = _glewSearchExtension("GL_ARB_draw_instanced", extStart, extEnd); #endif /* GL_ARB_draw_instanced */ #ifdef GL_ARB_enhanced_layouts - CONST_CAST(GLEW_ARB_enhanced_layouts) = _glewSearchExtension("GL_ARB_enhanced_layouts", extStart, extEnd); + GLEW_ARB_enhanced_layouts = _glewSearchExtension("GL_ARB_enhanced_layouts", extStart, extEnd); #endif /* GL_ARB_enhanced_layouts */ #ifdef GL_ARB_explicit_attrib_location - CONST_CAST(GLEW_ARB_explicit_attrib_location) = _glewSearchExtension("GL_ARB_explicit_attrib_location", extStart, extEnd); + GLEW_ARB_explicit_attrib_location = _glewSearchExtension("GL_ARB_explicit_attrib_location", extStart, extEnd); #endif /* GL_ARB_explicit_attrib_location */ #ifdef GL_ARB_explicit_uniform_location - CONST_CAST(GLEW_ARB_explicit_uniform_location) = _glewSearchExtension("GL_ARB_explicit_uniform_location", extStart, extEnd); + GLEW_ARB_explicit_uniform_location = _glewSearchExtension("GL_ARB_explicit_uniform_location", extStart, extEnd); #endif /* GL_ARB_explicit_uniform_location */ #ifdef GL_ARB_fragment_coord_conventions - CONST_CAST(GLEW_ARB_fragment_coord_conventions) = _glewSearchExtension("GL_ARB_fragment_coord_conventions", extStart, extEnd); + GLEW_ARB_fragment_coord_conventions = _glewSearchExtension("GL_ARB_fragment_coord_conventions", extStart, extEnd); #endif /* GL_ARB_fragment_coord_conventions */ #ifdef GL_ARB_fragment_layer_viewport - CONST_CAST(GLEW_ARB_fragment_layer_viewport) = _glewSearchExtension("GL_ARB_fragment_layer_viewport", extStart, extEnd); + GLEW_ARB_fragment_layer_viewport = _glewSearchExtension("GL_ARB_fragment_layer_viewport", extStart, extEnd); #endif /* GL_ARB_fragment_layer_viewport */ #ifdef GL_ARB_fragment_program - CONST_CAST(GLEW_ARB_fragment_program) = _glewSearchExtension("GL_ARB_fragment_program", extStart, extEnd); + GLEW_ARB_fragment_program = _glewSearchExtension("GL_ARB_fragment_program", extStart, extEnd); #endif /* GL_ARB_fragment_program */ #ifdef GL_ARB_fragment_program_shadow - CONST_CAST(GLEW_ARB_fragment_program_shadow) = _glewSearchExtension("GL_ARB_fragment_program_shadow", extStart, extEnd); + GLEW_ARB_fragment_program_shadow = _glewSearchExtension("GL_ARB_fragment_program_shadow", extStart, extEnd); #endif /* GL_ARB_fragment_program_shadow */ #ifdef GL_ARB_fragment_shader - CONST_CAST(GLEW_ARB_fragment_shader) = _glewSearchExtension("GL_ARB_fragment_shader", extStart, extEnd); + GLEW_ARB_fragment_shader = _glewSearchExtension("GL_ARB_fragment_shader", extStart, extEnd); #endif /* GL_ARB_fragment_shader */ #ifdef GL_ARB_framebuffer_no_attachments - CONST_CAST(GLEW_ARB_framebuffer_no_attachments) = _glewSearchExtension("GL_ARB_framebuffer_no_attachments", extStart, extEnd); - if (glewExperimental || GLEW_ARB_framebuffer_no_attachments) CONST_CAST(GLEW_ARB_framebuffer_no_attachments) = !_glewInit_GL_ARB_framebuffer_no_attachments(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_framebuffer_no_attachments = _glewSearchExtension("GL_ARB_framebuffer_no_attachments", extStart, extEnd); + if (glewExperimental || GLEW_ARB_framebuffer_no_attachments) GLEW_ARB_framebuffer_no_attachments = !_glewInit_GL_ARB_framebuffer_no_attachments(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_framebuffer_no_attachments */ #ifdef GL_ARB_framebuffer_object - CONST_CAST(GLEW_ARB_framebuffer_object) = _glewSearchExtension("GL_ARB_framebuffer_object", extStart, extEnd); - if (glewExperimental || GLEW_ARB_framebuffer_object) CONST_CAST(GLEW_ARB_framebuffer_object) = !_glewInit_GL_ARB_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_framebuffer_object = _glewSearchExtension("GL_ARB_framebuffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_framebuffer_object) GLEW_ARB_framebuffer_object = !_glewInit_GL_ARB_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_framebuffer_object */ #ifdef GL_ARB_framebuffer_sRGB - CONST_CAST(GLEW_ARB_framebuffer_sRGB) = _glewSearchExtension("GL_ARB_framebuffer_sRGB", extStart, extEnd); + GLEW_ARB_framebuffer_sRGB = _glewSearchExtension("GL_ARB_framebuffer_sRGB", extStart, extEnd); #endif /* GL_ARB_framebuffer_sRGB */ #ifdef GL_ARB_geometry_shader4 - CONST_CAST(GLEW_ARB_geometry_shader4) = _glewSearchExtension("GL_ARB_geometry_shader4", extStart, extEnd); - if (glewExperimental || GLEW_ARB_geometry_shader4) CONST_CAST(GLEW_ARB_geometry_shader4) = !_glewInit_GL_ARB_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_geometry_shader4 = _glewSearchExtension("GL_ARB_geometry_shader4", extStart, extEnd); + if (glewExperimental || GLEW_ARB_geometry_shader4) GLEW_ARB_geometry_shader4 = !_glewInit_GL_ARB_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_geometry_shader4 */ #ifdef GL_ARB_get_program_binary - CONST_CAST(GLEW_ARB_get_program_binary) = _glewSearchExtension("GL_ARB_get_program_binary", extStart, extEnd); - if (glewExperimental || GLEW_ARB_get_program_binary) CONST_CAST(GLEW_ARB_get_program_binary) = !_glewInit_GL_ARB_get_program_binary(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_get_program_binary = _glewSearchExtension("GL_ARB_get_program_binary", extStart, extEnd); + if (glewExperimental || GLEW_ARB_get_program_binary) GLEW_ARB_get_program_binary = !_glewInit_GL_ARB_get_program_binary(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_get_program_binary */ #ifdef GL_ARB_gpu_shader5 - CONST_CAST(GLEW_ARB_gpu_shader5) = _glewSearchExtension("GL_ARB_gpu_shader5", extStart, extEnd); + GLEW_ARB_gpu_shader5 = _glewSearchExtension("GL_ARB_gpu_shader5", extStart, extEnd); #endif /* GL_ARB_gpu_shader5 */ #ifdef GL_ARB_gpu_shader_fp64 - CONST_CAST(GLEW_ARB_gpu_shader_fp64) = _glewSearchExtension("GL_ARB_gpu_shader_fp64", extStart, extEnd); - if (glewExperimental || GLEW_ARB_gpu_shader_fp64) CONST_CAST(GLEW_ARB_gpu_shader_fp64) = !_glewInit_GL_ARB_gpu_shader_fp64(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_gpu_shader_fp64 = _glewSearchExtension("GL_ARB_gpu_shader_fp64", extStart, extEnd); + if (glewExperimental || GLEW_ARB_gpu_shader_fp64) GLEW_ARB_gpu_shader_fp64 = !_glewInit_GL_ARB_gpu_shader_fp64(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_gpu_shader_fp64 */ #ifdef GL_ARB_half_float_pixel - CONST_CAST(GLEW_ARB_half_float_pixel) = _glewSearchExtension("GL_ARB_half_float_pixel", extStart, extEnd); + GLEW_ARB_half_float_pixel = _glewSearchExtension("GL_ARB_half_float_pixel", extStart, extEnd); #endif /* GL_ARB_half_float_pixel */ #ifdef GL_ARB_half_float_vertex - CONST_CAST(GLEW_ARB_half_float_vertex) = _glewSearchExtension("GL_ARB_half_float_vertex", extStart, extEnd); + GLEW_ARB_half_float_vertex = _glewSearchExtension("GL_ARB_half_float_vertex", extStart, extEnd); #endif /* GL_ARB_half_float_vertex */ #ifdef GL_ARB_imaging - CONST_CAST(GLEW_ARB_imaging) = _glewSearchExtension("GL_ARB_imaging", extStart, extEnd); - if (glewExperimental || GLEW_ARB_imaging) CONST_CAST(GLEW_ARB_imaging) = !_glewInit_GL_ARB_imaging(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_imaging = _glewSearchExtension("GL_ARB_imaging", extStart, extEnd); + if (glewExperimental || GLEW_ARB_imaging) GLEW_ARB_imaging = !_glewInit_GL_ARB_imaging(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_imaging */ #ifdef GL_ARB_indirect_parameters - CONST_CAST(GLEW_ARB_indirect_parameters) = _glewSearchExtension("GL_ARB_indirect_parameters", extStart, extEnd); - if (glewExperimental || GLEW_ARB_indirect_parameters) CONST_CAST(GLEW_ARB_indirect_parameters) = !_glewInit_GL_ARB_indirect_parameters(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_indirect_parameters = _glewSearchExtension("GL_ARB_indirect_parameters", extStart, extEnd); + if (glewExperimental || GLEW_ARB_indirect_parameters) GLEW_ARB_indirect_parameters = !_glewInit_GL_ARB_indirect_parameters(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_indirect_parameters */ #ifdef GL_ARB_instanced_arrays - CONST_CAST(GLEW_ARB_instanced_arrays) = _glewSearchExtension("GL_ARB_instanced_arrays", extStart, extEnd); - if (glewExperimental || GLEW_ARB_instanced_arrays) CONST_CAST(GLEW_ARB_instanced_arrays) = !_glewInit_GL_ARB_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_instanced_arrays = _glewSearchExtension("GL_ARB_instanced_arrays", extStart, extEnd); + if (glewExperimental || GLEW_ARB_instanced_arrays) GLEW_ARB_instanced_arrays = !_glewInit_GL_ARB_instanced_arrays(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_instanced_arrays */ #ifdef GL_ARB_internalformat_query - CONST_CAST(GLEW_ARB_internalformat_query) = _glewSearchExtension("GL_ARB_internalformat_query", extStart, extEnd); - if (glewExperimental || GLEW_ARB_internalformat_query) CONST_CAST(GLEW_ARB_internalformat_query) = !_glewInit_GL_ARB_internalformat_query(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_internalformat_query = _glewSearchExtension("GL_ARB_internalformat_query", extStart, extEnd); + if (glewExperimental || GLEW_ARB_internalformat_query) GLEW_ARB_internalformat_query = !_glewInit_GL_ARB_internalformat_query(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_internalformat_query */ #ifdef GL_ARB_internalformat_query2 - CONST_CAST(GLEW_ARB_internalformat_query2) = _glewSearchExtension("GL_ARB_internalformat_query2", extStart, extEnd); - if (glewExperimental || GLEW_ARB_internalformat_query2) CONST_CAST(GLEW_ARB_internalformat_query2) = !_glewInit_GL_ARB_internalformat_query2(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_internalformat_query2 = _glewSearchExtension("GL_ARB_internalformat_query2", extStart, extEnd); + if (glewExperimental || GLEW_ARB_internalformat_query2) GLEW_ARB_internalformat_query2 = !_glewInit_GL_ARB_internalformat_query2(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_internalformat_query2 */ #ifdef GL_ARB_invalidate_subdata - CONST_CAST(GLEW_ARB_invalidate_subdata) = _glewSearchExtension("GL_ARB_invalidate_subdata", extStart, extEnd); - if (glewExperimental || GLEW_ARB_invalidate_subdata) CONST_CAST(GLEW_ARB_invalidate_subdata) = !_glewInit_GL_ARB_invalidate_subdata(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_invalidate_subdata = _glewSearchExtension("GL_ARB_invalidate_subdata", extStart, extEnd); + if (glewExperimental || GLEW_ARB_invalidate_subdata) GLEW_ARB_invalidate_subdata = !_glewInit_GL_ARB_invalidate_subdata(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_invalidate_subdata */ #ifdef GL_ARB_map_buffer_alignment - CONST_CAST(GLEW_ARB_map_buffer_alignment) = _glewSearchExtension("GL_ARB_map_buffer_alignment", extStart, extEnd); + GLEW_ARB_map_buffer_alignment = _glewSearchExtension("GL_ARB_map_buffer_alignment", extStart, extEnd); #endif /* GL_ARB_map_buffer_alignment */ #ifdef GL_ARB_map_buffer_range - CONST_CAST(GLEW_ARB_map_buffer_range) = _glewSearchExtension("GL_ARB_map_buffer_range", extStart, extEnd); - if (glewExperimental || GLEW_ARB_map_buffer_range) CONST_CAST(GLEW_ARB_map_buffer_range) = !_glewInit_GL_ARB_map_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_map_buffer_range = _glewSearchExtension("GL_ARB_map_buffer_range", extStart, extEnd); + if (glewExperimental || GLEW_ARB_map_buffer_range) GLEW_ARB_map_buffer_range = !_glewInit_GL_ARB_map_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_map_buffer_range */ #ifdef GL_ARB_matrix_palette - CONST_CAST(GLEW_ARB_matrix_palette) = _glewSearchExtension("GL_ARB_matrix_palette", extStart, extEnd); - if (glewExperimental || GLEW_ARB_matrix_palette) CONST_CAST(GLEW_ARB_matrix_palette) = !_glewInit_GL_ARB_matrix_palette(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_matrix_palette = _glewSearchExtension("GL_ARB_matrix_palette", extStart, extEnd); + if (glewExperimental || GLEW_ARB_matrix_palette) GLEW_ARB_matrix_palette = !_glewInit_GL_ARB_matrix_palette(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_matrix_palette */ #ifdef GL_ARB_multi_bind - CONST_CAST(GLEW_ARB_multi_bind) = _glewSearchExtension("GL_ARB_multi_bind", extStart, extEnd); - if (glewExperimental || GLEW_ARB_multi_bind) CONST_CAST(GLEW_ARB_multi_bind) = !_glewInit_GL_ARB_multi_bind(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_multi_bind = _glewSearchExtension("GL_ARB_multi_bind", extStart, extEnd); + if (glewExperimental || GLEW_ARB_multi_bind) GLEW_ARB_multi_bind = !_glewInit_GL_ARB_multi_bind(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_multi_bind */ #ifdef GL_ARB_multi_draw_indirect - CONST_CAST(GLEW_ARB_multi_draw_indirect) = _glewSearchExtension("GL_ARB_multi_draw_indirect", extStart, extEnd); - if (glewExperimental || GLEW_ARB_multi_draw_indirect) CONST_CAST(GLEW_ARB_multi_draw_indirect) = !_glewInit_GL_ARB_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_multi_draw_indirect = _glewSearchExtension("GL_ARB_multi_draw_indirect", extStart, extEnd); + if (glewExperimental || GLEW_ARB_multi_draw_indirect) GLEW_ARB_multi_draw_indirect = !_glewInit_GL_ARB_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_multi_draw_indirect */ #ifdef GL_ARB_multisample - CONST_CAST(GLEW_ARB_multisample) = _glewSearchExtension("GL_ARB_multisample", extStart, extEnd); - if (glewExperimental || GLEW_ARB_multisample) CONST_CAST(GLEW_ARB_multisample) = !_glewInit_GL_ARB_multisample(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_multisample = _glewSearchExtension("GL_ARB_multisample", extStart, extEnd); + if (glewExperimental || GLEW_ARB_multisample) GLEW_ARB_multisample = !_glewInit_GL_ARB_multisample(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_multisample */ #ifdef GL_ARB_multitexture - CONST_CAST(GLEW_ARB_multitexture) = _glewSearchExtension("GL_ARB_multitexture", extStart, extEnd); - if (glewExperimental || GLEW_ARB_multitexture) CONST_CAST(GLEW_ARB_multitexture) = !_glewInit_GL_ARB_multitexture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_multitexture = _glewSearchExtension("GL_ARB_multitexture", extStart, extEnd); + if (glewExperimental || GLEW_ARB_multitexture) GLEW_ARB_multitexture = !_glewInit_GL_ARB_multitexture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_multitexture */ #ifdef GL_ARB_occlusion_query - CONST_CAST(GLEW_ARB_occlusion_query) = _glewSearchExtension("GL_ARB_occlusion_query", extStart, extEnd); - if (glewExperimental || GLEW_ARB_occlusion_query) CONST_CAST(GLEW_ARB_occlusion_query) = !_glewInit_GL_ARB_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_occlusion_query = _glewSearchExtension("GL_ARB_occlusion_query", extStart, extEnd); + if (glewExperimental || GLEW_ARB_occlusion_query) GLEW_ARB_occlusion_query = !_glewInit_GL_ARB_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_occlusion_query */ #ifdef GL_ARB_occlusion_query2 - CONST_CAST(GLEW_ARB_occlusion_query2) = _glewSearchExtension("GL_ARB_occlusion_query2", extStart, extEnd); + GLEW_ARB_occlusion_query2 = _glewSearchExtension("GL_ARB_occlusion_query2", extStart, extEnd); #endif /* GL_ARB_occlusion_query2 */ #ifdef GL_ARB_pixel_buffer_object - CONST_CAST(GLEW_ARB_pixel_buffer_object) = _glewSearchExtension("GL_ARB_pixel_buffer_object", extStart, extEnd); + GLEW_ARB_pixel_buffer_object = _glewSearchExtension("GL_ARB_pixel_buffer_object", extStart, extEnd); #endif /* GL_ARB_pixel_buffer_object */ #ifdef GL_ARB_point_parameters - CONST_CAST(GLEW_ARB_point_parameters) = _glewSearchExtension("GL_ARB_point_parameters", extStart, extEnd); - if (glewExperimental || GLEW_ARB_point_parameters) CONST_CAST(GLEW_ARB_point_parameters) = !_glewInit_GL_ARB_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_point_parameters = _glewSearchExtension("GL_ARB_point_parameters", extStart, extEnd); + if (glewExperimental || GLEW_ARB_point_parameters) GLEW_ARB_point_parameters = !_glewInit_GL_ARB_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_point_parameters */ #ifdef GL_ARB_point_sprite - CONST_CAST(GLEW_ARB_point_sprite) = _glewSearchExtension("GL_ARB_point_sprite", extStart, extEnd); + GLEW_ARB_point_sprite = _glewSearchExtension("GL_ARB_point_sprite", extStart, extEnd); #endif /* GL_ARB_point_sprite */ #ifdef GL_ARB_program_interface_query - CONST_CAST(GLEW_ARB_program_interface_query) = _glewSearchExtension("GL_ARB_program_interface_query", extStart, extEnd); - if (glewExperimental || GLEW_ARB_program_interface_query) CONST_CAST(GLEW_ARB_program_interface_query) = !_glewInit_GL_ARB_program_interface_query(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_program_interface_query = _glewSearchExtension("GL_ARB_program_interface_query", extStart, extEnd); + if (glewExperimental || GLEW_ARB_program_interface_query) GLEW_ARB_program_interface_query = !_glewInit_GL_ARB_program_interface_query(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_program_interface_query */ #ifdef GL_ARB_provoking_vertex - CONST_CAST(GLEW_ARB_provoking_vertex) = _glewSearchExtension("GL_ARB_provoking_vertex", extStart, extEnd); - if (glewExperimental || GLEW_ARB_provoking_vertex) CONST_CAST(GLEW_ARB_provoking_vertex) = !_glewInit_GL_ARB_provoking_vertex(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_provoking_vertex = _glewSearchExtension("GL_ARB_provoking_vertex", extStart, extEnd); + if (glewExperimental || GLEW_ARB_provoking_vertex) GLEW_ARB_provoking_vertex = !_glewInit_GL_ARB_provoking_vertex(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_provoking_vertex */ #ifdef GL_ARB_query_buffer_object - CONST_CAST(GLEW_ARB_query_buffer_object) = _glewSearchExtension("GL_ARB_query_buffer_object", extStart, extEnd); + GLEW_ARB_query_buffer_object = _glewSearchExtension("GL_ARB_query_buffer_object", extStart, extEnd); #endif /* GL_ARB_query_buffer_object */ #ifdef GL_ARB_robust_buffer_access_behavior - CONST_CAST(GLEW_ARB_robust_buffer_access_behavior) = _glewSearchExtension("GL_ARB_robust_buffer_access_behavior", extStart, extEnd); + GLEW_ARB_robust_buffer_access_behavior = _glewSearchExtension("GL_ARB_robust_buffer_access_behavior", extStart, extEnd); #endif /* GL_ARB_robust_buffer_access_behavior */ #ifdef GL_ARB_robustness - CONST_CAST(GLEW_ARB_robustness) = _glewSearchExtension("GL_ARB_robustness", extStart, extEnd); - if (glewExperimental || GLEW_ARB_robustness) CONST_CAST(GLEW_ARB_robustness) = !_glewInit_GL_ARB_robustness(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_robustness = _glewSearchExtension("GL_ARB_robustness", extStart, extEnd); + if (glewExperimental || GLEW_ARB_robustness) GLEW_ARB_robustness = !_glewInit_GL_ARB_robustness(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_robustness */ #ifdef GL_ARB_robustness_application_isolation - CONST_CAST(GLEW_ARB_robustness_application_isolation) = _glewSearchExtension("GL_ARB_robustness_application_isolation", extStart, extEnd); + GLEW_ARB_robustness_application_isolation = _glewSearchExtension("GL_ARB_robustness_application_isolation", extStart, extEnd); #endif /* GL_ARB_robustness_application_isolation */ #ifdef GL_ARB_robustness_share_group_isolation - CONST_CAST(GLEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("GL_ARB_robustness_share_group_isolation", extStart, extEnd); + GLEW_ARB_robustness_share_group_isolation = _glewSearchExtension("GL_ARB_robustness_share_group_isolation", extStart, extEnd); #endif /* GL_ARB_robustness_share_group_isolation */ #ifdef GL_ARB_sample_shading - CONST_CAST(GLEW_ARB_sample_shading) = _glewSearchExtension("GL_ARB_sample_shading", extStart, extEnd); - if (glewExperimental || GLEW_ARB_sample_shading) CONST_CAST(GLEW_ARB_sample_shading) = !_glewInit_GL_ARB_sample_shading(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_sample_shading = _glewSearchExtension("GL_ARB_sample_shading", extStart, extEnd); + if (glewExperimental || GLEW_ARB_sample_shading) GLEW_ARB_sample_shading = !_glewInit_GL_ARB_sample_shading(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_sample_shading */ #ifdef GL_ARB_sampler_objects - CONST_CAST(GLEW_ARB_sampler_objects) = _glewSearchExtension("GL_ARB_sampler_objects", extStart, extEnd); - if (glewExperimental || GLEW_ARB_sampler_objects) CONST_CAST(GLEW_ARB_sampler_objects) = !_glewInit_GL_ARB_sampler_objects(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_sampler_objects = _glewSearchExtension("GL_ARB_sampler_objects", extStart, extEnd); + if (glewExperimental || GLEW_ARB_sampler_objects) GLEW_ARB_sampler_objects = !_glewInit_GL_ARB_sampler_objects(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_sampler_objects */ #ifdef GL_ARB_seamless_cube_map - CONST_CAST(GLEW_ARB_seamless_cube_map) = _glewSearchExtension("GL_ARB_seamless_cube_map", extStart, extEnd); + GLEW_ARB_seamless_cube_map = _glewSearchExtension("GL_ARB_seamless_cube_map", extStart, extEnd); #endif /* GL_ARB_seamless_cube_map */ #ifdef GL_ARB_seamless_cubemap_per_texture - CONST_CAST(GLEW_ARB_seamless_cubemap_per_texture) = _glewSearchExtension("GL_ARB_seamless_cubemap_per_texture", extStart, extEnd); + GLEW_ARB_seamless_cubemap_per_texture = _glewSearchExtension("GL_ARB_seamless_cubemap_per_texture", extStart, extEnd); #endif /* GL_ARB_seamless_cubemap_per_texture */ #ifdef GL_ARB_separate_shader_objects - CONST_CAST(GLEW_ARB_separate_shader_objects) = _glewSearchExtension("GL_ARB_separate_shader_objects", extStart, extEnd); - if (glewExperimental || GLEW_ARB_separate_shader_objects) CONST_CAST(GLEW_ARB_separate_shader_objects) = !_glewInit_GL_ARB_separate_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_separate_shader_objects = _glewSearchExtension("GL_ARB_separate_shader_objects", extStart, extEnd); + if (glewExperimental || GLEW_ARB_separate_shader_objects) GLEW_ARB_separate_shader_objects = !_glewInit_GL_ARB_separate_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_separate_shader_objects */ #ifdef GL_ARB_shader_atomic_counters - CONST_CAST(GLEW_ARB_shader_atomic_counters) = _glewSearchExtension("GL_ARB_shader_atomic_counters", extStart, extEnd); - if (glewExperimental || GLEW_ARB_shader_atomic_counters) CONST_CAST(GLEW_ARB_shader_atomic_counters) = !_glewInit_GL_ARB_shader_atomic_counters(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_shader_atomic_counters = _glewSearchExtension("GL_ARB_shader_atomic_counters", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shader_atomic_counters) GLEW_ARB_shader_atomic_counters = !_glewInit_GL_ARB_shader_atomic_counters(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_shader_atomic_counters */ #ifdef GL_ARB_shader_bit_encoding - CONST_CAST(GLEW_ARB_shader_bit_encoding) = _glewSearchExtension("GL_ARB_shader_bit_encoding", extStart, extEnd); + GLEW_ARB_shader_bit_encoding = _glewSearchExtension("GL_ARB_shader_bit_encoding", extStart, extEnd); #endif /* GL_ARB_shader_bit_encoding */ #ifdef GL_ARB_shader_draw_parameters - CONST_CAST(GLEW_ARB_shader_draw_parameters) = _glewSearchExtension("GL_ARB_shader_draw_parameters", extStart, extEnd); + GLEW_ARB_shader_draw_parameters = _glewSearchExtension("GL_ARB_shader_draw_parameters", extStart, extEnd); #endif /* GL_ARB_shader_draw_parameters */ #ifdef GL_ARB_shader_group_vote - CONST_CAST(GLEW_ARB_shader_group_vote) = _glewSearchExtension("GL_ARB_shader_group_vote", extStart, extEnd); + GLEW_ARB_shader_group_vote = _glewSearchExtension("GL_ARB_shader_group_vote", extStart, extEnd); #endif /* GL_ARB_shader_group_vote */ #ifdef GL_ARB_shader_image_load_store - CONST_CAST(GLEW_ARB_shader_image_load_store) = _glewSearchExtension("GL_ARB_shader_image_load_store", extStart, extEnd); - if (glewExperimental || GLEW_ARB_shader_image_load_store) CONST_CAST(GLEW_ARB_shader_image_load_store) = !_glewInit_GL_ARB_shader_image_load_store(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_shader_image_load_store = _glewSearchExtension("GL_ARB_shader_image_load_store", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shader_image_load_store) GLEW_ARB_shader_image_load_store = !_glewInit_GL_ARB_shader_image_load_store(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_shader_image_load_store */ #ifdef GL_ARB_shader_image_size - CONST_CAST(GLEW_ARB_shader_image_size) = _glewSearchExtension("GL_ARB_shader_image_size", extStart, extEnd); + GLEW_ARB_shader_image_size = _glewSearchExtension("GL_ARB_shader_image_size", extStart, extEnd); #endif /* GL_ARB_shader_image_size */ #ifdef GL_ARB_shader_objects - CONST_CAST(GLEW_ARB_shader_objects) = _glewSearchExtension("GL_ARB_shader_objects", extStart, extEnd); - if (glewExperimental || GLEW_ARB_shader_objects) CONST_CAST(GLEW_ARB_shader_objects) = !_glewInit_GL_ARB_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_shader_objects = _glewSearchExtension("GL_ARB_shader_objects", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shader_objects) GLEW_ARB_shader_objects = !_glewInit_GL_ARB_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_shader_objects */ #ifdef GL_ARB_shader_precision - CONST_CAST(GLEW_ARB_shader_precision) = _glewSearchExtension("GL_ARB_shader_precision", extStart, extEnd); + GLEW_ARB_shader_precision = _glewSearchExtension("GL_ARB_shader_precision", extStart, extEnd); #endif /* GL_ARB_shader_precision */ #ifdef GL_ARB_shader_stencil_export - CONST_CAST(GLEW_ARB_shader_stencil_export) = _glewSearchExtension("GL_ARB_shader_stencil_export", extStart, extEnd); + GLEW_ARB_shader_stencil_export = _glewSearchExtension("GL_ARB_shader_stencil_export", extStart, extEnd); #endif /* GL_ARB_shader_stencil_export */ #ifdef GL_ARB_shader_storage_buffer_object - CONST_CAST(GLEW_ARB_shader_storage_buffer_object) = _glewSearchExtension("GL_ARB_shader_storage_buffer_object", extStart, extEnd); - if (glewExperimental || GLEW_ARB_shader_storage_buffer_object) CONST_CAST(GLEW_ARB_shader_storage_buffer_object) = !_glewInit_GL_ARB_shader_storage_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_shader_storage_buffer_object = _glewSearchExtension("GL_ARB_shader_storage_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shader_storage_buffer_object) GLEW_ARB_shader_storage_buffer_object = !_glewInit_GL_ARB_shader_storage_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_shader_storage_buffer_object */ #ifdef GL_ARB_shader_subroutine - CONST_CAST(GLEW_ARB_shader_subroutine) = _glewSearchExtension("GL_ARB_shader_subroutine", extStart, extEnd); - if (glewExperimental || GLEW_ARB_shader_subroutine) CONST_CAST(GLEW_ARB_shader_subroutine) = !_glewInit_GL_ARB_shader_subroutine(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_shader_subroutine = _glewSearchExtension("GL_ARB_shader_subroutine", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shader_subroutine) GLEW_ARB_shader_subroutine = !_glewInit_GL_ARB_shader_subroutine(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_shader_subroutine */ #ifdef GL_ARB_shader_texture_lod - CONST_CAST(GLEW_ARB_shader_texture_lod) = _glewSearchExtension("GL_ARB_shader_texture_lod", extStart, extEnd); + GLEW_ARB_shader_texture_lod = _glewSearchExtension("GL_ARB_shader_texture_lod", extStart, extEnd); #endif /* GL_ARB_shader_texture_lod */ #ifdef GL_ARB_shading_language_100 - CONST_CAST(GLEW_ARB_shading_language_100) = _glewSearchExtension("GL_ARB_shading_language_100", extStart, extEnd); + GLEW_ARB_shading_language_100 = _glewSearchExtension("GL_ARB_shading_language_100", extStart, extEnd); #endif /* GL_ARB_shading_language_100 */ #ifdef GL_ARB_shading_language_420pack - CONST_CAST(GLEW_ARB_shading_language_420pack) = _glewSearchExtension("GL_ARB_shading_language_420pack", extStart, extEnd); + GLEW_ARB_shading_language_420pack = _glewSearchExtension("GL_ARB_shading_language_420pack", extStart, extEnd); #endif /* GL_ARB_shading_language_420pack */ #ifdef GL_ARB_shading_language_include - CONST_CAST(GLEW_ARB_shading_language_include) = _glewSearchExtension("GL_ARB_shading_language_include", extStart, extEnd); - if (glewExperimental || GLEW_ARB_shading_language_include) CONST_CAST(GLEW_ARB_shading_language_include) = !_glewInit_GL_ARB_shading_language_include(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_shading_language_include = _glewSearchExtension("GL_ARB_shading_language_include", extStart, extEnd); + if (glewExperimental || GLEW_ARB_shading_language_include) GLEW_ARB_shading_language_include = !_glewInit_GL_ARB_shading_language_include(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_shading_language_include */ #ifdef GL_ARB_shading_language_packing - CONST_CAST(GLEW_ARB_shading_language_packing) = _glewSearchExtension("GL_ARB_shading_language_packing", extStart, extEnd); + GLEW_ARB_shading_language_packing = _glewSearchExtension("GL_ARB_shading_language_packing", extStart, extEnd); #endif /* GL_ARB_shading_language_packing */ #ifdef GL_ARB_shadow - CONST_CAST(GLEW_ARB_shadow) = _glewSearchExtension("GL_ARB_shadow", extStart, extEnd); + GLEW_ARB_shadow = _glewSearchExtension("GL_ARB_shadow", extStart, extEnd); #endif /* GL_ARB_shadow */ #ifdef GL_ARB_shadow_ambient - CONST_CAST(GLEW_ARB_shadow_ambient) = _glewSearchExtension("GL_ARB_shadow_ambient", extStart, extEnd); + GLEW_ARB_shadow_ambient = _glewSearchExtension("GL_ARB_shadow_ambient", extStart, extEnd); #endif /* GL_ARB_shadow_ambient */ #ifdef GL_ARB_sparse_texture - CONST_CAST(GLEW_ARB_sparse_texture) = _glewSearchExtension("GL_ARB_sparse_texture", extStart, extEnd); - if (glewExperimental || GLEW_ARB_sparse_texture) CONST_CAST(GLEW_ARB_sparse_texture) = !_glewInit_GL_ARB_sparse_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_sparse_texture = _glewSearchExtension("GL_ARB_sparse_texture", extStart, extEnd); + if (glewExperimental || GLEW_ARB_sparse_texture) GLEW_ARB_sparse_texture = !_glewInit_GL_ARB_sparse_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_sparse_texture */ #ifdef GL_ARB_stencil_texturing - CONST_CAST(GLEW_ARB_stencil_texturing) = _glewSearchExtension("GL_ARB_stencil_texturing", extStart, extEnd); + GLEW_ARB_stencil_texturing = _glewSearchExtension("GL_ARB_stencil_texturing", extStart, extEnd); #endif /* GL_ARB_stencil_texturing */ #ifdef GL_ARB_sync - CONST_CAST(GLEW_ARB_sync) = _glewSearchExtension("GL_ARB_sync", extStart, extEnd); - if (glewExperimental || GLEW_ARB_sync) CONST_CAST(GLEW_ARB_sync) = !_glewInit_GL_ARB_sync(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_sync = _glewSearchExtension("GL_ARB_sync", extStart, extEnd); + if (glewExperimental || GLEW_ARB_sync) GLEW_ARB_sync = !_glewInit_GL_ARB_sync(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_sync */ #ifdef GL_ARB_tessellation_shader - CONST_CAST(GLEW_ARB_tessellation_shader) = _glewSearchExtension("GL_ARB_tessellation_shader", extStart, extEnd); - if (glewExperimental || GLEW_ARB_tessellation_shader) CONST_CAST(GLEW_ARB_tessellation_shader) = !_glewInit_GL_ARB_tessellation_shader(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_tessellation_shader = _glewSearchExtension("GL_ARB_tessellation_shader", extStart, extEnd); + if (glewExperimental || GLEW_ARB_tessellation_shader) GLEW_ARB_tessellation_shader = !_glewInit_GL_ARB_tessellation_shader(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_tessellation_shader */ #ifdef GL_ARB_texture_border_clamp - CONST_CAST(GLEW_ARB_texture_border_clamp) = _glewSearchExtension("GL_ARB_texture_border_clamp", extStart, extEnd); + GLEW_ARB_texture_border_clamp = _glewSearchExtension("GL_ARB_texture_border_clamp", extStart, extEnd); #endif /* GL_ARB_texture_border_clamp */ #ifdef GL_ARB_texture_buffer_object - CONST_CAST(GLEW_ARB_texture_buffer_object) = _glewSearchExtension("GL_ARB_texture_buffer_object", extStart, extEnd); - if (glewExperimental || GLEW_ARB_texture_buffer_object) CONST_CAST(GLEW_ARB_texture_buffer_object) = !_glewInit_GL_ARB_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_texture_buffer_object = _glewSearchExtension("GL_ARB_texture_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_buffer_object) GLEW_ARB_texture_buffer_object = !_glewInit_GL_ARB_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_texture_buffer_object */ #ifdef GL_ARB_texture_buffer_object_rgb32 - CONST_CAST(GLEW_ARB_texture_buffer_object_rgb32) = _glewSearchExtension("GL_ARB_texture_buffer_object_rgb32", extStart, extEnd); + GLEW_ARB_texture_buffer_object_rgb32 = _glewSearchExtension("GL_ARB_texture_buffer_object_rgb32", extStart, extEnd); #endif /* GL_ARB_texture_buffer_object_rgb32 */ #ifdef GL_ARB_texture_buffer_range - CONST_CAST(GLEW_ARB_texture_buffer_range) = _glewSearchExtension("GL_ARB_texture_buffer_range", extStart, extEnd); - if (glewExperimental || GLEW_ARB_texture_buffer_range) CONST_CAST(GLEW_ARB_texture_buffer_range) = !_glewInit_GL_ARB_texture_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_texture_buffer_range = _glewSearchExtension("GL_ARB_texture_buffer_range", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_buffer_range) GLEW_ARB_texture_buffer_range = !_glewInit_GL_ARB_texture_buffer_range(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_texture_buffer_range */ #ifdef GL_ARB_texture_compression - CONST_CAST(GLEW_ARB_texture_compression) = _glewSearchExtension("GL_ARB_texture_compression", extStart, extEnd); - if (glewExperimental || GLEW_ARB_texture_compression) CONST_CAST(GLEW_ARB_texture_compression) = !_glewInit_GL_ARB_texture_compression(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_texture_compression = _glewSearchExtension("GL_ARB_texture_compression", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_compression) GLEW_ARB_texture_compression = !_glewInit_GL_ARB_texture_compression(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_texture_compression */ #ifdef GL_ARB_texture_compression_bptc - CONST_CAST(GLEW_ARB_texture_compression_bptc) = _glewSearchExtension("GL_ARB_texture_compression_bptc", extStart, extEnd); + GLEW_ARB_texture_compression_bptc = _glewSearchExtension("GL_ARB_texture_compression_bptc", extStart, extEnd); #endif /* GL_ARB_texture_compression_bptc */ #ifdef GL_ARB_texture_compression_rgtc - CONST_CAST(GLEW_ARB_texture_compression_rgtc) = _glewSearchExtension("GL_ARB_texture_compression_rgtc", extStart, extEnd); + GLEW_ARB_texture_compression_rgtc = _glewSearchExtension("GL_ARB_texture_compression_rgtc", extStart, extEnd); #endif /* GL_ARB_texture_compression_rgtc */ #ifdef GL_ARB_texture_cube_map - CONST_CAST(GLEW_ARB_texture_cube_map) = _glewSearchExtension("GL_ARB_texture_cube_map", extStart, extEnd); + GLEW_ARB_texture_cube_map = _glewSearchExtension("GL_ARB_texture_cube_map", extStart, extEnd); #endif /* GL_ARB_texture_cube_map */ #ifdef GL_ARB_texture_cube_map_array - CONST_CAST(GLEW_ARB_texture_cube_map_array) = _glewSearchExtension("GL_ARB_texture_cube_map_array", extStart, extEnd); + GLEW_ARB_texture_cube_map_array = _glewSearchExtension("GL_ARB_texture_cube_map_array", extStart, extEnd); #endif /* GL_ARB_texture_cube_map_array */ #ifdef GL_ARB_texture_env_add - CONST_CAST(GLEW_ARB_texture_env_add) = _glewSearchExtension("GL_ARB_texture_env_add", extStart, extEnd); + GLEW_ARB_texture_env_add = _glewSearchExtension("GL_ARB_texture_env_add", extStart, extEnd); #endif /* GL_ARB_texture_env_add */ #ifdef GL_ARB_texture_env_combine - CONST_CAST(GLEW_ARB_texture_env_combine) = _glewSearchExtension("GL_ARB_texture_env_combine", extStart, extEnd); + GLEW_ARB_texture_env_combine = _glewSearchExtension("GL_ARB_texture_env_combine", extStart, extEnd); #endif /* GL_ARB_texture_env_combine */ #ifdef GL_ARB_texture_env_crossbar - CONST_CAST(GLEW_ARB_texture_env_crossbar) = _glewSearchExtension("GL_ARB_texture_env_crossbar", extStart, extEnd); + GLEW_ARB_texture_env_crossbar = _glewSearchExtension("GL_ARB_texture_env_crossbar", extStart, extEnd); #endif /* GL_ARB_texture_env_crossbar */ #ifdef GL_ARB_texture_env_dot3 - CONST_CAST(GLEW_ARB_texture_env_dot3) = _glewSearchExtension("GL_ARB_texture_env_dot3", extStart, extEnd); + GLEW_ARB_texture_env_dot3 = _glewSearchExtension("GL_ARB_texture_env_dot3", extStart, extEnd); #endif /* GL_ARB_texture_env_dot3 */ #ifdef GL_ARB_texture_float - CONST_CAST(GLEW_ARB_texture_float) = _glewSearchExtension("GL_ARB_texture_float", extStart, extEnd); + GLEW_ARB_texture_float = _glewSearchExtension("GL_ARB_texture_float", extStart, extEnd); #endif /* GL_ARB_texture_float */ #ifdef GL_ARB_texture_gather - CONST_CAST(GLEW_ARB_texture_gather) = _glewSearchExtension("GL_ARB_texture_gather", extStart, extEnd); + GLEW_ARB_texture_gather = _glewSearchExtension("GL_ARB_texture_gather", extStart, extEnd); #endif /* GL_ARB_texture_gather */ #ifdef GL_ARB_texture_mirror_clamp_to_edge - CONST_CAST(GLEW_ARB_texture_mirror_clamp_to_edge) = _glewSearchExtension("GL_ARB_texture_mirror_clamp_to_edge", extStart, extEnd); + GLEW_ARB_texture_mirror_clamp_to_edge = _glewSearchExtension("GL_ARB_texture_mirror_clamp_to_edge", extStart, extEnd); #endif /* GL_ARB_texture_mirror_clamp_to_edge */ #ifdef GL_ARB_texture_mirrored_repeat - CONST_CAST(GLEW_ARB_texture_mirrored_repeat) = _glewSearchExtension("GL_ARB_texture_mirrored_repeat", extStart, extEnd); + GLEW_ARB_texture_mirrored_repeat = _glewSearchExtension("GL_ARB_texture_mirrored_repeat", extStart, extEnd); #endif /* GL_ARB_texture_mirrored_repeat */ #ifdef GL_ARB_texture_multisample - CONST_CAST(GLEW_ARB_texture_multisample) = _glewSearchExtension("GL_ARB_texture_multisample", extStart, extEnd); - if (glewExperimental || GLEW_ARB_texture_multisample) CONST_CAST(GLEW_ARB_texture_multisample) = !_glewInit_GL_ARB_texture_multisample(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_texture_multisample = _glewSearchExtension("GL_ARB_texture_multisample", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_multisample) GLEW_ARB_texture_multisample = !_glewInit_GL_ARB_texture_multisample(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_texture_multisample */ #ifdef GL_ARB_texture_non_power_of_two - CONST_CAST(GLEW_ARB_texture_non_power_of_two) = _glewSearchExtension("GL_ARB_texture_non_power_of_two", extStart, extEnd); + GLEW_ARB_texture_non_power_of_two = _glewSearchExtension("GL_ARB_texture_non_power_of_two", extStart, extEnd); #endif /* GL_ARB_texture_non_power_of_two */ #ifdef GL_ARB_texture_query_levels - CONST_CAST(GLEW_ARB_texture_query_levels) = _glewSearchExtension("GL_ARB_texture_query_levels", extStart, extEnd); + GLEW_ARB_texture_query_levels = _glewSearchExtension("GL_ARB_texture_query_levels", extStart, extEnd); #endif /* GL_ARB_texture_query_levels */ #ifdef GL_ARB_texture_query_lod - CONST_CAST(GLEW_ARB_texture_query_lod) = _glewSearchExtension("GL_ARB_texture_query_lod", extStart, extEnd); + GLEW_ARB_texture_query_lod = _glewSearchExtension("GL_ARB_texture_query_lod", extStart, extEnd); #endif /* GL_ARB_texture_query_lod */ #ifdef GL_ARB_texture_rectangle - CONST_CAST(GLEW_ARB_texture_rectangle) = _glewSearchExtension("GL_ARB_texture_rectangle", extStart, extEnd); + GLEW_ARB_texture_rectangle = _glewSearchExtension("GL_ARB_texture_rectangle", extStart, extEnd); #endif /* GL_ARB_texture_rectangle */ #ifdef GL_ARB_texture_rg - CONST_CAST(GLEW_ARB_texture_rg) = _glewSearchExtension("GL_ARB_texture_rg", extStart, extEnd); + GLEW_ARB_texture_rg = _glewSearchExtension("GL_ARB_texture_rg", extStart, extEnd); #endif /* GL_ARB_texture_rg */ #ifdef GL_ARB_texture_rgb10_a2ui - CONST_CAST(GLEW_ARB_texture_rgb10_a2ui) = _glewSearchExtension("GL_ARB_texture_rgb10_a2ui", extStart, extEnd); + GLEW_ARB_texture_rgb10_a2ui = _glewSearchExtension("GL_ARB_texture_rgb10_a2ui", extStart, extEnd); #endif /* GL_ARB_texture_rgb10_a2ui */ #ifdef GL_ARB_texture_stencil8 - CONST_CAST(GLEW_ARB_texture_stencil8) = _glewSearchExtension("GL_ARB_texture_stencil8", extStart, extEnd); + GLEW_ARB_texture_stencil8 = _glewSearchExtension("GL_ARB_texture_stencil8", extStart, extEnd); #endif /* GL_ARB_texture_stencil8 */ #ifdef GL_ARB_texture_storage - CONST_CAST(GLEW_ARB_texture_storage) = _glewSearchExtension("GL_ARB_texture_storage", extStart, extEnd); - if (glewExperimental || GLEW_ARB_texture_storage) CONST_CAST(GLEW_ARB_texture_storage) = !_glewInit_GL_ARB_texture_storage(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_texture_storage = _glewSearchExtension("GL_ARB_texture_storage", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_storage) GLEW_ARB_texture_storage = !_glewInit_GL_ARB_texture_storage(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_texture_storage */ #ifdef GL_ARB_texture_storage_multisample - CONST_CAST(GLEW_ARB_texture_storage_multisample) = _glewSearchExtension("GL_ARB_texture_storage_multisample", extStart, extEnd); - if (glewExperimental || GLEW_ARB_texture_storage_multisample) CONST_CAST(GLEW_ARB_texture_storage_multisample) = !_glewInit_GL_ARB_texture_storage_multisample(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_texture_storage_multisample = _glewSearchExtension("GL_ARB_texture_storage_multisample", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_storage_multisample) GLEW_ARB_texture_storage_multisample = !_glewInit_GL_ARB_texture_storage_multisample(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_texture_storage_multisample */ #ifdef GL_ARB_texture_swizzle - CONST_CAST(GLEW_ARB_texture_swizzle) = _glewSearchExtension("GL_ARB_texture_swizzle", extStart, extEnd); + GLEW_ARB_texture_swizzle = _glewSearchExtension("GL_ARB_texture_swizzle", extStart, extEnd); #endif /* GL_ARB_texture_swizzle */ #ifdef GL_ARB_texture_view - CONST_CAST(GLEW_ARB_texture_view) = _glewSearchExtension("GL_ARB_texture_view", extStart, extEnd); - if (glewExperimental || GLEW_ARB_texture_view) CONST_CAST(GLEW_ARB_texture_view) = !_glewInit_GL_ARB_texture_view(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_texture_view = _glewSearchExtension("GL_ARB_texture_view", extStart, extEnd); + if (glewExperimental || GLEW_ARB_texture_view) GLEW_ARB_texture_view = !_glewInit_GL_ARB_texture_view(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_texture_view */ #ifdef GL_ARB_timer_query - CONST_CAST(GLEW_ARB_timer_query) = _glewSearchExtension("GL_ARB_timer_query", extStart, extEnd); - if (glewExperimental || GLEW_ARB_timer_query) CONST_CAST(GLEW_ARB_timer_query) = !_glewInit_GL_ARB_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_timer_query = _glewSearchExtension("GL_ARB_timer_query", extStart, extEnd); + if (glewExperimental || GLEW_ARB_timer_query) GLEW_ARB_timer_query = !_glewInit_GL_ARB_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_timer_query */ #ifdef GL_ARB_transform_feedback2 - CONST_CAST(GLEW_ARB_transform_feedback2) = _glewSearchExtension("GL_ARB_transform_feedback2", extStart, extEnd); - if (glewExperimental || GLEW_ARB_transform_feedback2) CONST_CAST(GLEW_ARB_transform_feedback2) = !_glewInit_GL_ARB_transform_feedback2(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_transform_feedback2 = _glewSearchExtension("GL_ARB_transform_feedback2", extStart, extEnd); + if (glewExperimental || GLEW_ARB_transform_feedback2) GLEW_ARB_transform_feedback2 = !_glewInit_GL_ARB_transform_feedback2(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_transform_feedback2 */ #ifdef GL_ARB_transform_feedback3 - CONST_CAST(GLEW_ARB_transform_feedback3) = _glewSearchExtension("GL_ARB_transform_feedback3", extStart, extEnd); - if (glewExperimental || GLEW_ARB_transform_feedback3) CONST_CAST(GLEW_ARB_transform_feedback3) = !_glewInit_GL_ARB_transform_feedback3(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_transform_feedback3 = _glewSearchExtension("GL_ARB_transform_feedback3", extStart, extEnd); + if (glewExperimental || GLEW_ARB_transform_feedback3) GLEW_ARB_transform_feedback3 = !_glewInit_GL_ARB_transform_feedback3(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_transform_feedback3 */ #ifdef GL_ARB_transform_feedback_instanced - CONST_CAST(GLEW_ARB_transform_feedback_instanced) = _glewSearchExtension("GL_ARB_transform_feedback_instanced", extStart, extEnd); - if (glewExperimental || GLEW_ARB_transform_feedback_instanced) CONST_CAST(GLEW_ARB_transform_feedback_instanced) = !_glewInit_GL_ARB_transform_feedback_instanced(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_transform_feedback_instanced = _glewSearchExtension("GL_ARB_transform_feedback_instanced", extStart, extEnd); + if (glewExperimental || GLEW_ARB_transform_feedback_instanced) GLEW_ARB_transform_feedback_instanced = !_glewInit_GL_ARB_transform_feedback_instanced(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_transform_feedback_instanced */ #ifdef GL_ARB_transpose_matrix - CONST_CAST(GLEW_ARB_transpose_matrix) = _glewSearchExtension("GL_ARB_transpose_matrix", extStart, extEnd); - if (glewExperimental || GLEW_ARB_transpose_matrix) CONST_CAST(GLEW_ARB_transpose_matrix) = !_glewInit_GL_ARB_transpose_matrix(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_transpose_matrix = _glewSearchExtension("GL_ARB_transpose_matrix", extStart, extEnd); + if (glewExperimental || GLEW_ARB_transpose_matrix) GLEW_ARB_transpose_matrix = !_glewInit_GL_ARB_transpose_matrix(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_transpose_matrix */ #ifdef GL_ARB_uniform_buffer_object - CONST_CAST(GLEW_ARB_uniform_buffer_object) = _glewSearchExtension("GL_ARB_uniform_buffer_object", extStart, extEnd); - if (glewExperimental || GLEW_ARB_uniform_buffer_object) CONST_CAST(GLEW_ARB_uniform_buffer_object) = !_glewInit_GL_ARB_uniform_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_uniform_buffer_object = _glewSearchExtension("GL_ARB_uniform_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_uniform_buffer_object) GLEW_ARB_uniform_buffer_object = !_glewInit_GL_ARB_uniform_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_uniform_buffer_object */ #ifdef GL_ARB_vertex_array_bgra - CONST_CAST(GLEW_ARB_vertex_array_bgra) = _glewSearchExtension("GL_ARB_vertex_array_bgra", extStart, extEnd); + GLEW_ARB_vertex_array_bgra = _glewSearchExtension("GL_ARB_vertex_array_bgra", extStart, extEnd); #endif /* GL_ARB_vertex_array_bgra */ #ifdef GL_ARB_vertex_array_object - CONST_CAST(GLEW_ARB_vertex_array_object) = _glewSearchExtension("GL_ARB_vertex_array_object", extStart, extEnd); - if (glewExperimental || GLEW_ARB_vertex_array_object) CONST_CAST(GLEW_ARB_vertex_array_object) = !_glewInit_GL_ARB_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_vertex_array_object = _glewSearchExtension("GL_ARB_vertex_array_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_array_object) GLEW_ARB_vertex_array_object = !_glewInit_GL_ARB_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_vertex_array_object */ #ifdef GL_ARB_vertex_attrib_64bit - CONST_CAST(GLEW_ARB_vertex_attrib_64bit) = _glewSearchExtension("GL_ARB_vertex_attrib_64bit", extStart, extEnd); - if (glewExperimental || GLEW_ARB_vertex_attrib_64bit) CONST_CAST(GLEW_ARB_vertex_attrib_64bit) = !_glewInit_GL_ARB_vertex_attrib_64bit(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_vertex_attrib_64bit = _glewSearchExtension("GL_ARB_vertex_attrib_64bit", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_attrib_64bit) GLEW_ARB_vertex_attrib_64bit = !_glewInit_GL_ARB_vertex_attrib_64bit(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_vertex_attrib_64bit */ #ifdef GL_ARB_vertex_attrib_binding - CONST_CAST(GLEW_ARB_vertex_attrib_binding) = _glewSearchExtension("GL_ARB_vertex_attrib_binding", extStart, extEnd); - if (glewExperimental || GLEW_ARB_vertex_attrib_binding) CONST_CAST(GLEW_ARB_vertex_attrib_binding) = !_glewInit_GL_ARB_vertex_attrib_binding(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_vertex_attrib_binding = _glewSearchExtension("GL_ARB_vertex_attrib_binding", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_attrib_binding) GLEW_ARB_vertex_attrib_binding = !_glewInit_GL_ARB_vertex_attrib_binding(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_vertex_attrib_binding */ #ifdef GL_ARB_vertex_blend - CONST_CAST(GLEW_ARB_vertex_blend) = _glewSearchExtension("GL_ARB_vertex_blend", extStart, extEnd); - if (glewExperimental || GLEW_ARB_vertex_blend) CONST_CAST(GLEW_ARB_vertex_blend) = !_glewInit_GL_ARB_vertex_blend(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_vertex_blend = _glewSearchExtension("GL_ARB_vertex_blend", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_blend) GLEW_ARB_vertex_blend = !_glewInit_GL_ARB_vertex_blend(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_vertex_blend */ #ifdef GL_ARB_vertex_buffer_object - CONST_CAST(GLEW_ARB_vertex_buffer_object) = _glewSearchExtension("GL_ARB_vertex_buffer_object", extStart, extEnd); - if (glewExperimental || GLEW_ARB_vertex_buffer_object) CONST_CAST(GLEW_ARB_vertex_buffer_object) = !_glewInit_GL_ARB_vertex_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_vertex_buffer_object = _glewSearchExtension("GL_ARB_vertex_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_buffer_object) GLEW_ARB_vertex_buffer_object = !_glewInit_GL_ARB_vertex_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_vertex_buffer_object */ #ifdef GL_ARB_vertex_program - CONST_CAST(GLEW_ARB_vertex_program) = _glewSearchExtension("GL_ARB_vertex_program", extStart, extEnd); - if (glewExperimental || GLEW_ARB_vertex_program) CONST_CAST(GLEW_ARB_vertex_program) = !_glewInit_GL_ARB_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_vertex_program = _glewSearchExtension("GL_ARB_vertex_program", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_program) GLEW_ARB_vertex_program = !_glewInit_GL_ARB_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_vertex_program */ #ifdef GL_ARB_vertex_shader - CONST_CAST(GLEW_ARB_vertex_shader) = _glewSearchExtension("GL_ARB_vertex_shader", extStart, extEnd); - if (glewExperimental || GLEW_ARB_vertex_shader) CONST_CAST(GLEW_ARB_vertex_shader) = !_glewInit_GL_ARB_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_vertex_shader = _glewSearchExtension("GL_ARB_vertex_shader", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_shader) { GLEW_ARB_vertex_shader = !_glewInit_GL_ARB_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); _glewInit_GL_ARB_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); } #endif /* GL_ARB_vertex_shader */ #ifdef GL_ARB_vertex_type_10f_11f_11f_rev - CONST_CAST(GLEW_ARB_vertex_type_10f_11f_11f_rev) = _glewSearchExtension("GL_ARB_vertex_type_10f_11f_11f_rev", extStart, extEnd); + GLEW_ARB_vertex_type_10f_11f_11f_rev = _glewSearchExtension("GL_ARB_vertex_type_10f_11f_11f_rev", extStart, extEnd); #endif /* GL_ARB_vertex_type_10f_11f_11f_rev */ #ifdef GL_ARB_vertex_type_2_10_10_10_rev - CONST_CAST(GLEW_ARB_vertex_type_2_10_10_10_rev) = _glewSearchExtension("GL_ARB_vertex_type_2_10_10_10_rev", extStart, extEnd); - if (glewExperimental || GLEW_ARB_vertex_type_2_10_10_10_rev) CONST_CAST(GLEW_ARB_vertex_type_2_10_10_10_rev) = !_glewInit_GL_ARB_vertex_type_2_10_10_10_rev(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_vertex_type_2_10_10_10_rev = _glewSearchExtension("GL_ARB_vertex_type_2_10_10_10_rev", extStart, extEnd); + if (glewExperimental || GLEW_ARB_vertex_type_2_10_10_10_rev) GLEW_ARB_vertex_type_2_10_10_10_rev = !_glewInit_GL_ARB_vertex_type_2_10_10_10_rev(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_vertex_type_2_10_10_10_rev */ #ifdef GL_ARB_viewport_array - CONST_CAST(GLEW_ARB_viewport_array) = _glewSearchExtension("GL_ARB_viewport_array", extStart, extEnd); - if (glewExperimental || GLEW_ARB_viewport_array) CONST_CAST(GLEW_ARB_viewport_array) = !_glewInit_GL_ARB_viewport_array(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_viewport_array = _glewSearchExtension("GL_ARB_viewport_array", extStart, extEnd); + if (glewExperimental || GLEW_ARB_viewport_array) GLEW_ARB_viewport_array = !_glewInit_GL_ARB_viewport_array(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_viewport_array */ #ifdef GL_ARB_window_pos - CONST_CAST(GLEW_ARB_window_pos) = _glewSearchExtension("GL_ARB_window_pos", extStart, extEnd); - if (glewExperimental || GLEW_ARB_window_pos) CONST_CAST(GLEW_ARB_window_pos) = !_glewInit_GL_ARB_window_pos(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ARB_window_pos = _glewSearchExtension("GL_ARB_window_pos", extStart, extEnd); + if (glewExperimental || GLEW_ARB_window_pos) GLEW_ARB_window_pos = !_glewInit_GL_ARB_window_pos(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ARB_window_pos */ #ifdef GL_ATIX_point_sprites - CONST_CAST(GLEW_ATIX_point_sprites) = _glewSearchExtension("GL_ATIX_point_sprites", extStart, extEnd); + GLEW_ATIX_point_sprites = _glewSearchExtension("GL_ATIX_point_sprites", extStart, extEnd); #endif /* GL_ATIX_point_sprites */ #ifdef GL_ATIX_texture_env_combine3 - CONST_CAST(GLEW_ATIX_texture_env_combine3) = _glewSearchExtension("GL_ATIX_texture_env_combine3", extStart, extEnd); + GLEW_ATIX_texture_env_combine3 = _glewSearchExtension("GL_ATIX_texture_env_combine3", extStart, extEnd); #endif /* GL_ATIX_texture_env_combine3 */ #ifdef GL_ATIX_texture_env_route - CONST_CAST(GLEW_ATIX_texture_env_route) = _glewSearchExtension("GL_ATIX_texture_env_route", extStart, extEnd); + GLEW_ATIX_texture_env_route = _glewSearchExtension("GL_ATIX_texture_env_route", extStart, extEnd); #endif /* GL_ATIX_texture_env_route */ #ifdef GL_ATIX_vertex_shader_output_point_size - CONST_CAST(GLEW_ATIX_vertex_shader_output_point_size) = _glewSearchExtension("GL_ATIX_vertex_shader_output_point_size", extStart, extEnd); + GLEW_ATIX_vertex_shader_output_point_size = _glewSearchExtension("GL_ATIX_vertex_shader_output_point_size", extStart, extEnd); #endif /* GL_ATIX_vertex_shader_output_point_size */ #ifdef GL_ATI_draw_buffers - CONST_CAST(GLEW_ATI_draw_buffers) = _glewSearchExtension("GL_ATI_draw_buffers", extStart, extEnd); - if (glewExperimental || GLEW_ATI_draw_buffers) CONST_CAST(GLEW_ATI_draw_buffers) = !_glewInit_GL_ATI_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ATI_draw_buffers = _glewSearchExtension("GL_ATI_draw_buffers", extStart, extEnd); + if (glewExperimental || GLEW_ATI_draw_buffers) GLEW_ATI_draw_buffers = !_glewInit_GL_ATI_draw_buffers(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ATI_draw_buffers */ #ifdef GL_ATI_element_array - CONST_CAST(GLEW_ATI_element_array) = _glewSearchExtension("GL_ATI_element_array", extStart, extEnd); - if (glewExperimental || GLEW_ATI_element_array) CONST_CAST(GLEW_ATI_element_array) = !_glewInit_GL_ATI_element_array(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ATI_element_array = _glewSearchExtension("GL_ATI_element_array", extStart, extEnd); + if (glewExperimental || GLEW_ATI_element_array) GLEW_ATI_element_array = !_glewInit_GL_ATI_element_array(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ATI_element_array */ #ifdef GL_ATI_envmap_bumpmap - CONST_CAST(GLEW_ATI_envmap_bumpmap) = _glewSearchExtension("GL_ATI_envmap_bumpmap", extStart, extEnd); - if (glewExperimental || GLEW_ATI_envmap_bumpmap) CONST_CAST(GLEW_ATI_envmap_bumpmap) = !_glewInit_GL_ATI_envmap_bumpmap(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ATI_envmap_bumpmap = _glewSearchExtension("GL_ATI_envmap_bumpmap", extStart, extEnd); + if (glewExperimental || GLEW_ATI_envmap_bumpmap) GLEW_ATI_envmap_bumpmap = !_glewInit_GL_ATI_envmap_bumpmap(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ATI_envmap_bumpmap */ #ifdef GL_ATI_fragment_shader - CONST_CAST(GLEW_ATI_fragment_shader) = _glewSearchExtension("GL_ATI_fragment_shader", extStart, extEnd); - if (glewExperimental || GLEW_ATI_fragment_shader) CONST_CAST(GLEW_ATI_fragment_shader) = !_glewInit_GL_ATI_fragment_shader(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ATI_fragment_shader = _glewSearchExtension("GL_ATI_fragment_shader", extStart, extEnd); + if (glewExperimental || GLEW_ATI_fragment_shader) GLEW_ATI_fragment_shader = !_glewInit_GL_ATI_fragment_shader(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ATI_fragment_shader */ #ifdef GL_ATI_map_object_buffer - CONST_CAST(GLEW_ATI_map_object_buffer) = _glewSearchExtension("GL_ATI_map_object_buffer", extStart, extEnd); - if (glewExperimental || GLEW_ATI_map_object_buffer) CONST_CAST(GLEW_ATI_map_object_buffer) = !_glewInit_GL_ATI_map_object_buffer(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ATI_map_object_buffer = _glewSearchExtension("GL_ATI_map_object_buffer", extStart, extEnd); + if (glewExperimental || GLEW_ATI_map_object_buffer) GLEW_ATI_map_object_buffer = !_glewInit_GL_ATI_map_object_buffer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ATI_map_object_buffer */ #ifdef GL_ATI_meminfo - CONST_CAST(GLEW_ATI_meminfo) = _glewSearchExtension("GL_ATI_meminfo", extStart, extEnd); + GLEW_ATI_meminfo = _glewSearchExtension("GL_ATI_meminfo", extStart, extEnd); #endif /* GL_ATI_meminfo */ #ifdef GL_ATI_pn_triangles - CONST_CAST(GLEW_ATI_pn_triangles) = _glewSearchExtension("GL_ATI_pn_triangles", extStart, extEnd); - if (glewExperimental || GLEW_ATI_pn_triangles) CONST_CAST(GLEW_ATI_pn_triangles) = !_glewInit_GL_ATI_pn_triangles(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ATI_pn_triangles = _glewSearchExtension("GL_ATI_pn_triangles", extStart, extEnd); + if (glewExperimental || GLEW_ATI_pn_triangles) GLEW_ATI_pn_triangles = !_glewInit_GL_ATI_pn_triangles(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ATI_pn_triangles */ #ifdef GL_ATI_separate_stencil - CONST_CAST(GLEW_ATI_separate_stencil) = _glewSearchExtension("GL_ATI_separate_stencil", extStart, extEnd); - if (glewExperimental || GLEW_ATI_separate_stencil) CONST_CAST(GLEW_ATI_separate_stencil) = !_glewInit_GL_ATI_separate_stencil(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ATI_separate_stencil = _glewSearchExtension("GL_ATI_separate_stencil", extStart, extEnd); + if (glewExperimental || GLEW_ATI_separate_stencil) GLEW_ATI_separate_stencil = !_glewInit_GL_ATI_separate_stencil(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ATI_separate_stencil */ #ifdef GL_ATI_shader_texture_lod - CONST_CAST(GLEW_ATI_shader_texture_lod) = _glewSearchExtension("GL_ATI_shader_texture_lod", extStart, extEnd); + GLEW_ATI_shader_texture_lod = _glewSearchExtension("GL_ATI_shader_texture_lod", extStart, extEnd); #endif /* GL_ATI_shader_texture_lod */ #ifdef GL_ATI_text_fragment_shader - CONST_CAST(GLEW_ATI_text_fragment_shader) = _glewSearchExtension("GL_ATI_text_fragment_shader", extStart, extEnd); + GLEW_ATI_text_fragment_shader = _glewSearchExtension("GL_ATI_text_fragment_shader", extStart, extEnd); #endif /* GL_ATI_text_fragment_shader */ #ifdef GL_ATI_texture_compression_3dc - CONST_CAST(GLEW_ATI_texture_compression_3dc) = _glewSearchExtension("GL_ATI_texture_compression_3dc", extStart, extEnd); + GLEW_ATI_texture_compression_3dc = _glewSearchExtension("GL_ATI_texture_compression_3dc", extStart, extEnd); #endif /* GL_ATI_texture_compression_3dc */ #ifdef GL_ATI_texture_env_combine3 - CONST_CAST(GLEW_ATI_texture_env_combine3) = _glewSearchExtension("GL_ATI_texture_env_combine3", extStart, extEnd); + GLEW_ATI_texture_env_combine3 = _glewSearchExtension("GL_ATI_texture_env_combine3", extStart, extEnd); #endif /* GL_ATI_texture_env_combine3 */ #ifdef GL_ATI_texture_float - CONST_CAST(GLEW_ATI_texture_float) = _glewSearchExtension("GL_ATI_texture_float", extStart, extEnd); + GLEW_ATI_texture_float = _glewSearchExtension("GL_ATI_texture_float", extStart, extEnd); #endif /* GL_ATI_texture_float */ #ifdef GL_ATI_texture_mirror_once - CONST_CAST(GLEW_ATI_texture_mirror_once) = _glewSearchExtension("GL_ATI_texture_mirror_once", extStart, extEnd); + GLEW_ATI_texture_mirror_once = _glewSearchExtension("GL_ATI_texture_mirror_once", extStart, extEnd); #endif /* GL_ATI_texture_mirror_once */ #ifdef GL_ATI_vertex_array_object - CONST_CAST(GLEW_ATI_vertex_array_object) = _glewSearchExtension("GL_ATI_vertex_array_object", extStart, extEnd); - if (glewExperimental || GLEW_ATI_vertex_array_object) CONST_CAST(GLEW_ATI_vertex_array_object) = !_glewInit_GL_ATI_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ATI_vertex_array_object = _glewSearchExtension("GL_ATI_vertex_array_object", extStart, extEnd); + if (glewExperimental || GLEW_ATI_vertex_array_object) GLEW_ATI_vertex_array_object = !_glewInit_GL_ATI_vertex_array_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ATI_vertex_array_object */ #ifdef GL_ATI_vertex_attrib_array_object - CONST_CAST(GLEW_ATI_vertex_attrib_array_object) = _glewSearchExtension("GL_ATI_vertex_attrib_array_object", extStart, extEnd); - if (glewExperimental || GLEW_ATI_vertex_attrib_array_object) CONST_CAST(GLEW_ATI_vertex_attrib_array_object) = !_glewInit_GL_ATI_vertex_attrib_array_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ATI_vertex_attrib_array_object = _glewSearchExtension("GL_ATI_vertex_attrib_array_object", extStart, extEnd); + if (glewExperimental || GLEW_ATI_vertex_attrib_array_object) GLEW_ATI_vertex_attrib_array_object = !_glewInit_GL_ATI_vertex_attrib_array_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ATI_vertex_attrib_array_object */ #ifdef GL_ATI_vertex_streams - CONST_CAST(GLEW_ATI_vertex_streams) = _glewSearchExtension("GL_ATI_vertex_streams", extStart, extEnd); - if (glewExperimental || GLEW_ATI_vertex_streams) CONST_CAST(GLEW_ATI_vertex_streams) = !_glewInit_GL_ATI_vertex_streams(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_ATI_vertex_streams = _glewSearchExtension("GL_ATI_vertex_streams", extStart, extEnd); + if (glewExperimental || GLEW_ATI_vertex_streams) GLEW_ATI_vertex_streams = !_glewInit_GL_ATI_vertex_streams(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_ATI_vertex_streams */ #ifdef GL_EXT_422_pixels - CONST_CAST(GLEW_EXT_422_pixels) = _glewSearchExtension("GL_EXT_422_pixels", extStart, extEnd); + GLEW_EXT_422_pixels = _glewSearchExtension("GL_EXT_422_pixels", extStart, extEnd); #endif /* GL_EXT_422_pixels */ #ifdef GL_EXT_Cg_shader - CONST_CAST(GLEW_EXT_Cg_shader) = _glewSearchExtension("GL_EXT_Cg_shader", extStart, extEnd); + GLEW_EXT_Cg_shader = _glewSearchExtension("GL_EXT_Cg_shader", extStart, extEnd); #endif /* GL_EXT_Cg_shader */ #ifdef GL_EXT_abgr - CONST_CAST(GLEW_EXT_abgr) = _glewSearchExtension("GL_EXT_abgr", extStart, extEnd); + GLEW_EXT_abgr = _glewSearchExtension("GL_EXT_abgr", extStart, extEnd); #endif /* GL_EXT_abgr */ #ifdef GL_EXT_bgra - CONST_CAST(GLEW_EXT_bgra) = _glewSearchExtension("GL_EXT_bgra", extStart, extEnd); + GLEW_EXT_bgra = _glewSearchExtension("GL_EXT_bgra", extStart, extEnd); #endif /* GL_EXT_bgra */ #ifdef GL_EXT_bindable_uniform - CONST_CAST(GLEW_EXT_bindable_uniform) = _glewSearchExtension("GL_EXT_bindable_uniform", extStart, extEnd); - if (glewExperimental || GLEW_EXT_bindable_uniform) CONST_CAST(GLEW_EXT_bindable_uniform) = !_glewInit_GL_EXT_bindable_uniform(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_bindable_uniform = _glewSearchExtension("GL_EXT_bindable_uniform", extStart, extEnd); + if (glewExperimental || GLEW_EXT_bindable_uniform) GLEW_EXT_bindable_uniform = !_glewInit_GL_EXT_bindable_uniform(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_bindable_uniform */ #ifdef GL_EXT_blend_color - CONST_CAST(GLEW_EXT_blend_color) = _glewSearchExtension("GL_EXT_blend_color", extStart, extEnd); - if (glewExperimental || GLEW_EXT_blend_color) CONST_CAST(GLEW_EXT_blend_color) = !_glewInit_GL_EXT_blend_color(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_blend_color = _glewSearchExtension("GL_EXT_blend_color", extStart, extEnd); + if (glewExperimental || GLEW_EXT_blend_color) GLEW_EXT_blend_color = !_glewInit_GL_EXT_blend_color(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_blend_color */ #ifdef GL_EXT_blend_equation_separate - CONST_CAST(GLEW_EXT_blend_equation_separate) = _glewSearchExtension("GL_EXT_blend_equation_separate", extStart, extEnd); - if (glewExperimental || GLEW_EXT_blend_equation_separate) CONST_CAST(GLEW_EXT_blend_equation_separate) = !_glewInit_GL_EXT_blend_equation_separate(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_blend_equation_separate = _glewSearchExtension("GL_EXT_blend_equation_separate", extStart, extEnd); + if (glewExperimental || GLEW_EXT_blend_equation_separate) GLEW_EXT_blend_equation_separate = !_glewInit_GL_EXT_blend_equation_separate(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_blend_equation_separate */ #ifdef GL_EXT_blend_func_separate - CONST_CAST(GLEW_EXT_blend_func_separate) = _glewSearchExtension("GL_EXT_blend_func_separate", extStart, extEnd); - if (glewExperimental || GLEW_EXT_blend_func_separate) CONST_CAST(GLEW_EXT_blend_func_separate) = !_glewInit_GL_EXT_blend_func_separate(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_blend_func_separate = _glewSearchExtension("GL_EXT_blend_func_separate", extStart, extEnd); + if (glewExperimental || GLEW_EXT_blend_func_separate) GLEW_EXT_blend_func_separate = !_glewInit_GL_EXT_blend_func_separate(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_blend_func_separate */ #ifdef GL_EXT_blend_logic_op - CONST_CAST(GLEW_EXT_blend_logic_op) = _glewSearchExtension("GL_EXT_blend_logic_op", extStart, extEnd); + GLEW_EXT_blend_logic_op = _glewSearchExtension("GL_EXT_blend_logic_op", extStart, extEnd); #endif /* GL_EXT_blend_logic_op */ #ifdef GL_EXT_blend_minmax - CONST_CAST(GLEW_EXT_blend_minmax) = _glewSearchExtension("GL_EXT_blend_minmax", extStart, extEnd); - if (glewExperimental || GLEW_EXT_blend_minmax) CONST_CAST(GLEW_EXT_blend_minmax) = !_glewInit_GL_EXT_blend_minmax(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_blend_minmax = _glewSearchExtension("GL_EXT_blend_minmax", extStart, extEnd); + if (glewExperimental || GLEW_EXT_blend_minmax) GLEW_EXT_blend_minmax = !_glewInit_GL_EXT_blend_minmax(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_blend_minmax */ #ifdef GL_EXT_blend_subtract - CONST_CAST(GLEW_EXT_blend_subtract) = _glewSearchExtension("GL_EXT_blend_subtract", extStart, extEnd); + GLEW_EXT_blend_subtract = _glewSearchExtension("GL_EXT_blend_subtract", extStart, extEnd); #endif /* GL_EXT_blend_subtract */ #ifdef GL_EXT_clip_volume_hint - CONST_CAST(GLEW_EXT_clip_volume_hint) = _glewSearchExtension("GL_EXT_clip_volume_hint", extStart, extEnd); + GLEW_EXT_clip_volume_hint = _glewSearchExtension("GL_EXT_clip_volume_hint", extStart, extEnd); #endif /* GL_EXT_clip_volume_hint */ #ifdef GL_EXT_cmyka - CONST_CAST(GLEW_EXT_cmyka) = _glewSearchExtension("GL_EXT_cmyka", extStart, extEnd); + GLEW_EXT_cmyka = _glewSearchExtension("GL_EXT_cmyka", extStart, extEnd); #endif /* GL_EXT_cmyka */ #ifdef GL_EXT_color_subtable - CONST_CAST(GLEW_EXT_color_subtable) = _glewSearchExtension("GL_EXT_color_subtable", extStart, extEnd); - if (glewExperimental || GLEW_EXT_color_subtable) CONST_CAST(GLEW_EXT_color_subtable) = !_glewInit_GL_EXT_color_subtable(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_color_subtable = _glewSearchExtension("GL_EXT_color_subtable", extStart, extEnd); + if (glewExperimental || GLEW_EXT_color_subtable) GLEW_EXT_color_subtable = !_glewInit_GL_EXT_color_subtable(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_color_subtable */ #ifdef GL_EXT_compiled_vertex_array - CONST_CAST(GLEW_EXT_compiled_vertex_array) = _glewSearchExtension("GL_EXT_compiled_vertex_array", extStart, extEnd); - if (glewExperimental || GLEW_EXT_compiled_vertex_array) CONST_CAST(GLEW_EXT_compiled_vertex_array) = !_glewInit_GL_EXT_compiled_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_compiled_vertex_array = _glewSearchExtension("GL_EXT_compiled_vertex_array", extStart, extEnd); + if (glewExperimental || GLEW_EXT_compiled_vertex_array) GLEW_EXT_compiled_vertex_array = !_glewInit_GL_EXT_compiled_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_compiled_vertex_array */ #ifdef GL_EXT_convolution - CONST_CAST(GLEW_EXT_convolution) = _glewSearchExtension("GL_EXT_convolution", extStart, extEnd); - if (glewExperimental || GLEW_EXT_convolution) CONST_CAST(GLEW_EXT_convolution) = !_glewInit_GL_EXT_convolution(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_convolution = _glewSearchExtension("GL_EXT_convolution", extStart, extEnd); + if (glewExperimental || GLEW_EXT_convolution) GLEW_EXT_convolution = !_glewInit_GL_EXT_convolution(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_convolution */ #ifdef GL_EXT_coordinate_frame - CONST_CAST(GLEW_EXT_coordinate_frame) = _glewSearchExtension("GL_EXT_coordinate_frame", extStart, extEnd); - if (glewExperimental || GLEW_EXT_coordinate_frame) CONST_CAST(GLEW_EXT_coordinate_frame) = !_glewInit_GL_EXT_coordinate_frame(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_coordinate_frame = _glewSearchExtension("GL_EXT_coordinate_frame", extStart, extEnd); + if (glewExperimental || GLEW_EXT_coordinate_frame) GLEW_EXT_coordinate_frame = !_glewInit_GL_EXT_coordinate_frame(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_coordinate_frame */ #ifdef GL_EXT_copy_texture - CONST_CAST(GLEW_EXT_copy_texture) = _glewSearchExtension("GL_EXT_copy_texture", extStart, extEnd); - if (glewExperimental || GLEW_EXT_copy_texture) CONST_CAST(GLEW_EXT_copy_texture) = !_glewInit_GL_EXT_copy_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_copy_texture = _glewSearchExtension("GL_EXT_copy_texture", extStart, extEnd); + if (glewExperimental || GLEW_EXT_copy_texture) GLEW_EXT_copy_texture = !_glewInit_GL_EXT_copy_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_copy_texture */ #ifdef GL_EXT_cull_vertex - CONST_CAST(GLEW_EXT_cull_vertex) = _glewSearchExtension("GL_EXT_cull_vertex", extStart, extEnd); - if (glewExperimental || GLEW_EXT_cull_vertex) CONST_CAST(GLEW_EXT_cull_vertex) = !_glewInit_GL_EXT_cull_vertex(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_cull_vertex = _glewSearchExtension("GL_EXT_cull_vertex", extStart, extEnd); + if (glewExperimental || GLEW_EXT_cull_vertex) GLEW_EXT_cull_vertex = !_glewInit_GL_EXT_cull_vertex(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_cull_vertex */ +#ifdef GL_EXT_debug_label + GLEW_EXT_debug_label = _glewSearchExtension("GL_EXT_debug_label", extStart, extEnd); + if (glewExperimental || GLEW_EXT_debug_label) GLEW_EXT_debug_label = !_glewInit_GL_EXT_debug_label(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_EXT_debug_label */ #ifdef GL_EXT_debug_marker - CONST_CAST(GLEW_EXT_debug_marker) = _glewSearchExtension("GL_EXT_debug_marker", extStart, extEnd); - if (glewExperimental || GLEW_EXT_debug_marker) CONST_CAST(GLEW_EXT_debug_marker) = !_glewInit_GL_EXT_debug_marker(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_debug_marker = _glewSearchExtension("GL_EXT_debug_marker", extStart, extEnd); + if (glewExperimental || GLEW_EXT_debug_marker) GLEW_EXT_debug_marker = !_glewInit_GL_EXT_debug_marker(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_debug_marker */ #ifdef GL_EXT_depth_bounds_test - CONST_CAST(GLEW_EXT_depth_bounds_test) = _glewSearchExtension("GL_EXT_depth_bounds_test", extStart, extEnd); - if (glewExperimental || GLEW_EXT_depth_bounds_test) CONST_CAST(GLEW_EXT_depth_bounds_test) = !_glewInit_GL_EXT_depth_bounds_test(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_depth_bounds_test = _glewSearchExtension("GL_EXT_depth_bounds_test", extStart, extEnd); + if (glewExperimental || GLEW_EXT_depth_bounds_test) GLEW_EXT_depth_bounds_test = !_glewInit_GL_EXT_depth_bounds_test(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_depth_bounds_test */ #ifdef GL_EXT_direct_state_access - CONST_CAST(GLEW_EXT_direct_state_access) = _glewSearchExtension("GL_EXT_direct_state_access", extStart, extEnd); - if (glewExperimental || GLEW_EXT_direct_state_access) CONST_CAST(GLEW_EXT_direct_state_access) = !_glewInit_GL_EXT_direct_state_access(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_direct_state_access = _glewSearchExtension("GL_EXT_direct_state_access", extStart, extEnd); + if (glewExperimental || GLEW_EXT_direct_state_access) GLEW_EXT_direct_state_access = !_glewInit_GL_EXT_direct_state_access(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_direct_state_access */ #ifdef GL_EXT_draw_buffers2 - CONST_CAST(GLEW_EXT_draw_buffers2) = _glewSearchExtension("GL_EXT_draw_buffers2", extStart, extEnd); - if (glewExperimental || GLEW_EXT_draw_buffers2) CONST_CAST(GLEW_EXT_draw_buffers2) = !_glewInit_GL_EXT_draw_buffers2(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_draw_buffers2 = _glewSearchExtension("GL_EXT_draw_buffers2", extStart, extEnd); + if (glewExperimental || GLEW_EXT_draw_buffers2) GLEW_EXT_draw_buffers2 = !_glewInit_GL_EXT_draw_buffers2(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_draw_buffers2 */ #ifdef GL_EXT_draw_instanced - CONST_CAST(GLEW_EXT_draw_instanced) = _glewSearchExtension("GL_EXT_draw_instanced", extStart, extEnd); - if (glewExperimental || GLEW_EXT_draw_instanced) CONST_CAST(GLEW_EXT_draw_instanced) = !_glewInit_GL_EXT_draw_instanced(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_draw_instanced = _glewSearchExtension("GL_EXT_draw_instanced", extStart, extEnd); + if (glewExperimental || GLEW_EXT_draw_instanced) GLEW_EXT_draw_instanced = !_glewInit_GL_EXT_draw_instanced(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_draw_instanced */ #ifdef GL_EXT_draw_range_elements - CONST_CAST(GLEW_EXT_draw_range_elements) = _glewSearchExtension("GL_EXT_draw_range_elements", extStart, extEnd); - if (glewExperimental || GLEW_EXT_draw_range_elements) CONST_CAST(GLEW_EXT_draw_range_elements) = !_glewInit_GL_EXT_draw_range_elements(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_draw_range_elements = _glewSearchExtension("GL_EXT_draw_range_elements", extStart, extEnd); + if (glewExperimental || GLEW_EXT_draw_range_elements) GLEW_EXT_draw_range_elements = !_glewInit_GL_EXT_draw_range_elements(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_draw_range_elements */ #ifdef GL_EXT_fog_coord - CONST_CAST(GLEW_EXT_fog_coord) = _glewSearchExtension("GL_EXT_fog_coord", extStart, extEnd); - if (glewExperimental || GLEW_EXT_fog_coord) CONST_CAST(GLEW_EXT_fog_coord) = !_glewInit_GL_EXT_fog_coord(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_fog_coord = _glewSearchExtension("GL_EXT_fog_coord", extStart, extEnd); + if (glewExperimental || GLEW_EXT_fog_coord) GLEW_EXT_fog_coord = !_glewInit_GL_EXT_fog_coord(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_fog_coord */ #ifdef GL_EXT_fragment_lighting - CONST_CAST(GLEW_EXT_fragment_lighting) = _glewSearchExtension("GL_EXT_fragment_lighting", extStart, extEnd); - if (glewExperimental || GLEW_EXT_fragment_lighting) CONST_CAST(GLEW_EXT_fragment_lighting) = !_glewInit_GL_EXT_fragment_lighting(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_fragment_lighting = _glewSearchExtension("GL_EXT_fragment_lighting", extStart, extEnd); + if (glewExperimental || GLEW_EXT_fragment_lighting) GLEW_EXT_fragment_lighting = !_glewInit_GL_EXT_fragment_lighting(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_fragment_lighting */ #ifdef GL_EXT_framebuffer_blit - CONST_CAST(GLEW_EXT_framebuffer_blit) = _glewSearchExtension("GL_EXT_framebuffer_blit", extStart, extEnd); - if (glewExperimental || GLEW_EXT_framebuffer_blit) CONST_CAST(GLEW_EXT_framebuffer_blit) = !_glewInit_GL_EXT_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_framebuffer_blit = _glewSearchExtension("GL_EXT_framebuffer_blit", extStart, extEnd); + if (glewExperimental || GLEW_EXT_framebuffer_blit) GLEW_EXT_framebuffer_blit = !_glewInit_GL_EXT_framebuffer_blit(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_framebuffer_blit */ #ifdef GL_EXT_framebuffer_multisample - CONST_CAST(GLEW_EXT_framebuffer_multisample) = _glewSearchExtension("GL_EXT_framebuffer_multisample", extStart, extEnd); - if (glewExperimental || GLEW_EXT_framebuffer_multisample) CONST_CAST(GLEW_EXT_framebuffer_multisample) = !_glewInit_GL_EXT_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_framebuffer_multisample = _glewSearchExtension("GL_EXT_framebuffer_multisample", extStart, extEnd); + if (glewExperimental || GLEW_EXT_framebuffer_multisample) GLEW_EXT_framebuffer_multisample = !_glewInit_GL_EXT_framebuffer_multisample(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_framebuffer_multisample */ #ifdef GL_EXT_framebuffer_multisample_blit_scaled - CONST_CAST(GLEW_EXT_framebuffer_multisample_blit_scaled) = _glewSearchExtension("GL_EXT_framebuffer_multisample_blit_scaled", extStart, extEnd); + GLEW_EXT_framebuffer_multisample_blit_scaled = _glewSearchExtension("GL_EXT_framebuffer_multisample_blit_scaled", extStart, extEnd); #endif /* GL_EXT_framebuffer_multisample_blit_scaled */ #ifdef GL_EXT_framebuffer_object - CONST_CAST(GLEW_EXT_framebuffer_object) = _glewSearchExtension("GL_EXT_framebuffer_object", extStart, extEnd); - if (glewExperimental || GLEW_EXT_framebuffer_object) CONST_CAST(GLEW_EXT_framebuffer_object) = !_glewInit_GL_EXT_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_framebuffer_object = _glewSearchExtension("GL_EXT_framebuffer_object", extStart, extEnd); + if (glewExperimental || GLEW_EXT_framebuffer_object) GLEW_EXT_framebuffer_object = !_glewInit_GL_EXT_framebuffer_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_framebuffer_object */ #ifdef GL_EXT_framebuffer_sRGB - CONST_CAST(GLEW_EXT_framebuffer_sRGB) = _glewSearchExtension("GL_EXT_framebuffer_sRGB", extStart, extEnd); + GLEW_EXT_framebuffer_sRGB = _glewSearchExtension("GL_EXT_framebuffer_sRGB", extStart, extEnd); #endif /* GL_EXT_framebuffer_sRGB */ #ifdef GL_EXT_geometry_shader4 - CONST_CAST(GLEW_EXT_geometry_shader4) = _glewSearchExtension("GL_EXT_geometry_shader4", extStart, extEnd); - if (glewExperimental || GLEW_EXT_geometry_shader4) CONST_CAST(GLEW_EXT_geometry_shader4) = !_glewInit_GL_EXT_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_geometry_shader4 = _glewSearchExtension("GL_EXT_geometry_shader4", extStart, extEnd); + if (glewExperimental || GLEW_EXT_geometry_shader4) GLEW_EXT_geometry_shader4 = !_glewInit_GL_EXT_geometry_shader4(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_geometry_shader4 */ #ifdef GL_EXT_gpu_program_parameters - CONST_CAST(GLEW_EXT_gpu_program_parameters) = _glewSearchExtension("GL_EXT_gpu_program_parameters", extStart, extEnd); - if (glewExperimental || GLEW_EXT_gpu_program_parameters) CONST_CAST(GLEW_EXT_gpu_program_parameters) = !_glewInit_GL_EXT_gpu_program_parameters(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_gpu_program_parameters = _glewSearchExtension("GL_EXT_gpu_program_parameters", extStart, extEnd); + if (glewExperimental || GLEW_EXT_gpu_program_parameters) GLEW_EXT_gpu_program_parameters = !_glewInit_GL_EXT_gpu_program_parameters(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_gpu_program_parameters */ #ifdef GL_EXT_gpu_shader4 - CONST_CAST(GLEW_EXT_gpu_shader4) = _glewSearchExtension("GL_EXT_gpu_shader4", extStart, extEnd); - if (glewExperimental || GLEW_EXT_gpu_shader4) CONST_CAST(GLEW_EXT_gpu_shader4) = !_glewInit_GL_EXT_gpu_shader4(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_gpu_shader4 = _glewSearchExtension("GL_EXT_gpu_shader4", extStart, extEnd); + if (glewExperimental || GLEW_EXT_gpu_shader4) GLEW_EXT_gpu_shader4 = !_glewInit_GL_EXT_gpu_shader4(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_gpu_shader4 */ #ifdef GL_EXT_histogram - CONST_CAST(GLEW_EXT_histogram) = _glewSearchExtension("GL_EXT_histogram", extStart, extEnd); - if (glewExperimental || GLEW_EXT_histogram) CONST_CAST(GLEW_EXT_histogram) = !_glewInit_GL_EXT_histogram(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_histogram = _glewSearchExtension("GL_EXT_histogram", extStart, extEnd); + if (glewExperimental || GLEW_EXT_histogram) GLEW_EXT_histogram = !_glewInit_GL_EXT_histogram(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_histogram */ #ifdef GL_EXT_index_array_formats - CONST_CAST(GLEW_EXT_index_array_formats) = _glewSearchExtension("GL_EXT_index_array_formats", extStart, extEnd); + GLEW_EXT_index_array_formats = _glewSearchExtension("GL_EXT_index_array_formats", extStart, extEnd); #endif /* GL_EXT_index_array_formats */ #ifdef GL_EXT_index_func - CONST_CAST(GLEW_EXT_index_func) = _glewSearchExtension("GL_EXT_index_func", extStart, extEnd); - if (glewExperimental || GLEW_EXT_index_func) CONST_CAST(GLEW_EXT_index_func) = !_glewInit_GL_EXT_index_func(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_index_func = _glewSearchExtension("GL_EXT_index_func", extStart, extEnd); + if (glewExperimental || GLEW_EXT_index_func) GLEW_EXT_index_func = !_glewInit_GL_EXT_index_func(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_index_func */ #ifdef GL_EXT_index_material - CONST_CAST(GLEW_EXT_index_material) = _glewSearchExtension("GL_EXT_index_material", extStart, extEnd); - if (glewExperimental || GLEW_EXT_index_material) CONST_CAST(GLEW_EXT_index_material) = !_glewInit_GL_EXT_index_material(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_index_material = _glewSearchExtension("GL_EXT_index_material", extStart, extEnd); + if (glewExperimental || GLEW_EXT_index_material) GLEW_EXT_index_material = !_glewInit_GL_EXT_index_material(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_index_material */ #ifdef GL_EXT_index_texture - CONST_CAST(GLEW_EXT_index_texture) = _glewSearchExtension("GL_EXT_index_texture", extStart, extEnd); + GLEW_EXT_index_texture = _glewSearchExtension("GL_EXT_index_texture", extStart, extEnd); #endif /* GL_EXT_index_texture */ #ifdef GL_EXT_light_texture - CONST_CAST(GLEW_EXT_light_texture) = _glewSearchExtension("GL_EXT_light_texture", extStart, extEnd); - if (glewExperimental || GLEW_EXT_light_texture) CONST_CAST(GLEW_EXT_light_texture) = !_glewInit_GL_EXT_light_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_light_texture = _glewSearchExtension("GL_EXT_light_texture", extStart, extEnd); + if (glewExperimental || GLEW_EXT_light_texture) GLEW_EXT_light_texture = !_glewInit_GL_EXT_light_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_light_texture */ #ifdef GL_EXT_misc_attribute - CONST_CAST(GLEW_EXT_misc_attribute) = _glewSearchExtension("GL_EXT_misc_attribute", extStart, extEnd); + GLEW_EXT_misc_attribute = _glewSearchExtension("GL_EXT_misc_attribute", extStart, extEnd); #endif /* GL_EXT_misc_attribute */ #ifdef GL_EXT_multi_draw_arrays - CONST_CAST(GLEW_EXT_multi_draw_arrays) = _glewSearchExtension("GL_EXT_multi_draw_arrays", extStart, extEnd); - if (glewExperimental || GLEW_EXT_multi_draw_arrays) CONST_CAST(GLEW_EXT_multi_draw_arrays) = !_glewInit_GL_EXT_multi_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_multi_draw_arrays = _glewSearchExtension("GL_EXT_multi_draw_arrays", extStart, extEnd); + if (glewExperimental || GLEW_EXT_multi_draw_arrays) GLEW_EXT_multi_draw_arrays = !_glewInit_GL_EXT_multi_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_multi_draw_arrays */ #ifdef GL_EXT_multisample - CONST_CAST(GLEW_EXT_multisample) = _glewSearchExtension("GL_EXT_multisample", extStart, extEnd); - if (glewExperimental || GLEW_EXT_multisample) CONST_CAST(GLEW_EXT_multisample) = !_glewInit_GL_EXT_multisample(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_multisample = _glewSearchExtension("GL_EXT_multisample", extStart, extEnd); + if (glewExperimental || GLEW_EXT_multisample) GLEW_EXT_multisample = !_glewInit_GL_EXT_multisample(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_multisample */ #ifdef GL_EXT_packed_depth_stencil - CONST_CAST(GLEW_EXT_packed_depth_stencil) = _glewSearchExtension("GL_EXT_packed_depth_stencil", extStart, extEnd); + GLEW_EXT_packed_depth_stencil = _glewSearchExtension("GL_EXT_packed_depth_stencil", extStart, extEnd); #endif /* GL_EXT_packed_depth_stencil */ #ifdef GL_EXT_packed_float - CONST_CAST(GLEW_EXT_packed_float) = _glewSearchExtension("GL_EXT_packed_float", extStart, extEnd); + GLEW_EXT_packed_float = _glewSearchExtension("GL_EXT_packed_float", extStart, extEnd); #endif /* GL_EXT_packed_float */ #ifdef GL_EXT_packed_pixels - CONST_CAST(GLEW_EXT_packed_pixels) = _glewSearchExtension("GL_EXT_packed_pixels", extStart, extEnd); + GLEW_EXT_packed_pixels = _glewSearchExtension("GL_EXT_packed_pixels", extStart, extEnd); #endif /* GL_EXT_packed_pixels */ #ifdef GL_EXT_paletted_texture - CONST_CAST(GLEW_EXT_paletted_texture) = _glewSearchExtension("GL_EXT_paletted_texture", extStart, extEnd); - if (glewExperimental || GLEW_EXT_paletted_texture) CONST_CAST(GLEW_EXT_paletted_texture) = !_glewInit_GL_EXT_paletted_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_paletted_texture = _glewSearchExtension("GL_EXT_paletted_texture", extStart, extEnd); + if (glewExperimental || GLEW_EXT_paletted_texture) GLEW_EXT_paletted_texture = !_glewInit_GL_EXT_paletted_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_paletted_texture */ #ifdef GL_EXT_pixel_buffer_object - CONST_CAST(GLEW_EXT_pixel_buffer_object) = _glewSearchExtension("GL_EXT_pixel_buffer_object", extStart, extEnd); + GLEW_EXT_pixel_buffer_object = _glewSearchExtension("GL_EXT_pixel_buffer_object", extStart, extEnd); #endif /* GL_EXT_pixel_buffer_object */ #ifdef GL_EXT_pixel_transform - CONST_CAST(GLEW_EXT_pixel_transform) = _glewSearchExtension("GL_EXT_pixel_transform", extStart, extEnd); - if (glewExperimental || GLEW_EXT_pixel_transform) CONST_CAST(GLEW_EXT_pixel_transform) = !_glewInit_GL_EXT_pixel_transform(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_pixel_transform = _glewSearchExtension("GL_EXT_pixel_transform", extStart, extEnd); + if (glewExperimental || GLEW_EXT_pixel_transform) GLEW_EXT_pixel_transform = !_glewInit_GL_EXT_pixel_transform(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_pixel_transform */ #ifdef GL_EXT_pixel_transform_color_table - CONST_CAST(GLEW_EXT_pixel_transform_color_table) = _glewSearchExtension("GL_EXT_pixel_transform_color_table", extStart, extEnd); + GLEW_EXT_pixel_transform_color_table = _glewSearchExtension("GL_EXT_pixel_transform_color_table", extStart, extEnd); #endif /* GL_EXT_pixel_transform_color_table */ #ifdef GL_EXT_point_parameters - CONST_CAST(GLEW_EXT_point_parameters) = _glewSearchExtension("GL_EXT_point_parameters", extStart, extEnd); - if (glewExperimental || GLEW_EXT_point_parameters) CONST_CAST(GLEW_EXT_point_parameters) = !_glewInit_GL_EXT_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_point_parameters = _glewSearchExtension("GL_EXT_point_parameters", extStart, extEnd); + if (glewExperimental || GLEW_EXT_point_parameters) GLEW_EXT_point_parameters = !_glewInit_GL_EXT_point_parameters(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_point_parameters */ #ifdef GL_EXT_polygon_offset - CONST_CAST(GLEW_EXT_polygon_offset) = _glewSearchExtension("GL_EXT_polygon_offset", extStart, extEnd); - if (glewExperimental || GLEW_EXT_polygon_offset) CONST_CAST(GLEW_EXT_polygon_offset) = !_glewInit_GL_EXT_polygon_offset(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_polygon_offset = _glewSearchExtension("GL_EXT_polygon_offset", extStart, extEnd); + if (glewExperimental || GLEW_EXT_polygon_offset) GLEW_EXT_polygon_offset = !_glewInit_GL_EXT_polygon_offset(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_polygon_offset */ #ifdef GL_EXT_provoking_vertex - CONST_CAST(GLEW_EXT_provoking_vertex) = _glewSearchExtension("GL_EXT_provoking_vertex", extStart, extEnd); - if (glewExperimental || GLEW_EXT_provoking_vertex) CONST_CAST(GLEW_EXT_provoking_vertex) = !_glewInit_GL_EXT_provoking_vertex(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_provoking_vertex = _glewSearchExtension("GL_EXT_provoking_vertex", extStart, extEnd); + if (glewExperimental || GLEW_EXT_provoking_vertex) GLEW_EXT_provoking_vertex = !_glewInit_GL_EXT_provoking_vertex(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_provoking_vertex */ #ifdef GL_EXT_rescale_normal - CONST_CAST(GLEW_EXT_rescale_normal) = _glewSearchExtension("GL_EXT_rescale_normal", extStart, extEnd); + GLEW_EXT_rescale_normal = _glewSearchExtension("GL_EXT_rescale_normal", extStart, extEnd); #endif /* GL_EXT_rescale_normal */ #ifdef GL_EXT_scene_marker - CONST_CAST(GLEW_EXT_scene_marker) = _glewSearchExtension("GL_EXT_scene_marker", extStart, extEnd); - if (glewExperimental || GLEW_EXT_scene_marker) CONST_CAST(GLEW_EXT_scene_marker) = !_glewInit_GL_EXT_scene_marker(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_scene_marker = _glewSearchExtension("GL_EXT_scene_marker", extStart, extEnd); + if (glewExperimental || GLEW_EXT_scene_marker) GLEW_EXT_scene_marker = !_glewInit_GL_EXT_scene_marker(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_scene_marker */ #ifdef GL_EXT_secondary_color - CONST_CAST(GLEW_EXT_secondary_color) = _glewSearchExtension("GL_EXT_secondary_color", extStart, extEnd); - if (glewExperimental || GLEW_EXT_secondary_color) CONST_CAST(GLEW_EXT_secondary_color) = !_glewInit_GL_EXT_secondary_color(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_secondary_color = _glewSearchExtension("GL_EXT_secondary_color", extStart, extEnd); + if (glewExperimental || GLEW_EXT_secondary_color) GLEW_EXT_secondary_color = !_glewInit_GL_EXT_secondary_color(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_secondary_color */ #ifdef GL_EXT_separate_shader_objects - CONST_CAST(GLEW_EXT_separate_shader_objects) = _glewSearchExtension("GL_EXT_separate_shader_objects", extStart, extEnd); - if (glewExperimental || GLEW_EXT_separate_shader_objects) CONST_CAST(GLEW_EXT_separate_shader_objects) = !_glewInit_GL_EXT_separate_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_separate_shader_objects = _glewSearchExtension("GL_EXT_separate_shader_objects", extStart, extEnd); + if (glewExperimental || GLEW_EXT_separate_shader_objects) GLEW_EXT_separate_shader_objects = !_glewInit_GL_EXT_separate_shader_objects(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_separate_shader_objects */ #ifdef GL_EXT_separate_specular_color - CONST_CAST(GLEW_EXT_separate_specular_color) = _glewSearchExtension("GL_EXT_separate_specular_color", extStart, extEnd); + GLEW_EXT_separate_specular_color = _glewSearchExtension("GL_EXT_separate_specular_color", extStart, extEnd); #endif /* GL_EXT_separate_specular_color */ +#ifdef GL_EXT_shader_image_load_formatted + GLEW_EXT_shader_image_load_formatted = _glewSearchExtension("GL_EXT_shader_image_load_formatted", extStart, extEnd); +#endif /* GL_EXT_shader_image_load_formatted */ #ifdef GL_EXT_shader_image_load_store - CONST_CAST(GLEW_EXT_shader_image_load_store) = _glewSearchExtension("GL_EXT_shader_image_load_store", extStart, extEnd); - if (glewExperimental || GLEW_EXT_shader_image_load_store) CONST_CAST(GLEW_EXT_shader_image_load_store) = !_glewInit_GL_EXT_shader_image_load_store(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_shader_image_load_store = _glewSearchExtension("GL_EXT_shader_image_load_store", extStart, extEnd); + if (glewExperimental || GLEW_EXT_shader_image_load_store) GLEW_EXT_shader_image_load_store = !_glewInit_GL_EXT_shader_image_load_store(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_shader_image_load_store */ +#ifdef GL_EXT_shader_integer_mix + GLEW_EXT_shader_integer_mix = _glewSearchExtension("GL_EXT_shader_integer_mix", extStart, extEnd); +#endif /* GL_EXT_shader_integer_mix */ #ifdef GL_EXT_shadow_funcs - CONST_CAST(GLEW_EXT_shadow_funcs) = _glewSearchExtension("GL_EXT_shadow_funcs", extStart, extEnd); + GLEW_EXT_shadow_funcs = _glewSearchExtension("GL_EXT_shadow_funcs", extStart, extEnd); #endif /* GL_EXT_shadow_funcs */ #ifdef GL_EXT_shared_texture_palette - CONST_CAST(GLEW_EXT_shared_texture_palette) = _glewSearchExtension("GL_EXT_shared_texture_palette", extStart, extEnd); + GLEW_EXT_shared_texture_palette = _glewSearchExtension("GL_EXT_shared_texture_palette", extStart, extEnd); #endif /* GL_EXT_shared_texture_palette */ #ifdef GL_EXT_stencil_clear_tag - CONST_CAST(GLEW_EXT_stencil_clear_tag) = _glewSearchExtension("GL_EXT_stencil_clear_tag", extStart, extEnd); + GLEW_EXT_stencil_clear_tag = _glewSearchExtension("GL_EXT_stencil_clear_tag", extStart, extEnd); #endif /* GL_EXT_stencil_clear_tag */ #ifdef GL_EXT_stencil_two_side - CONST_CAST(GLEW_EXT_stencil_two_side) = _glewSearchExtension("GL_EXT_stencil_two_side", extStart, extEnd); - if (glewExperimental || GLEW_EXT_stencil_two_side) CONST_CAST(GLEW_EXT_stencil_two_side) = !_glewInit_GL_EXT_stencil_two_side(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_stencil_two_side = _glewSearchExtension("GL_EXT_stencil_two_side", extStart, extEnd); + if (glewExperimental || GLEW_EXT_stencil_two_side) GLEW_EXT_stencil_two_side = !_glewInit_GL_EXT_stencil_two_side(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_stencil_two_side */ #ifdef GL_EXT_stencil_wrap - CONST_CAST(GLEW_EXT_stencil_wrap) = _glewSearchExtension("GL_EXT_stencil_wrap", extStart, extEnd); + GLEW_EXT_stencil_wrap = _glewSearchExtension("GL_EXT_stencil_wrap", extStart, extEnd); #endif /* GL_EXT_stencil_wrap */ #ifdef GL_EXT_subtexture - CONST_CAST(GLEW_EXT_subtexture) = _glewSearchExtension("GL_EXT_subtexture", extStart, extEnd); - if (glewExperimental || GLEW_EXT_subtexture) CONST_CAST(GLEW_EXT_subtexture) = !_glewInit_GL_EXT_subtexture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_subtexture = _glewSearchExtension("GL_EXT_subtexture", extStart, extEnd); + if (glewExperimental || GLEW_EXT_subtexture) GLEW_EXT_subtexture = !_glewInit_GL_EXT_subtexture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_subtexture */ #ifdef GL_EXT_texture - CONST_CAST(GLEW_EXT_texture) = _glewSearchExtension("GL_EXT_texture", extStart, extEnd); + GLEW_EXT_texture = _glewSearchExtension("GL_EXT_texture", extStart, extEnd); #endif /* GL_EXT_texture */ #ifdef GL_EXT_texture3D - CONST_CAST(GLEW_EXT_texture3D) = _glewSearchExtension("GL_EXT_texture3D", extStart, extEnd); - if (glewExperimental || GLEW_EXT_texture3D) CONST_CAST(GLEW_EXT_texture3D) = !_glewInit_GL_EXT_texture3D(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_texture3D = _glewSearchExtension("GL_EXT_texture3D", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture3D) GLEW_EXT_texture3D = !_glewInit_GL_EXT_texture3D(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_texture3D */ #ifdef GL_EXT_texture_array - CONST_CAST(GLEW_EXT_texture_array) = _glewSearchExtension("GL_EXT_texture_array", extStart, extEnd); - if (glewExperimental || GLEW_EXT_texture_array) CONST_CAST(GLEW_EXT_texture_array) = !_glewInit_GL_EXT_texture_array(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_texture_array = _glewSearchExtension("GL_EXT_texture_array", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture_array) GLEW_EXT_texture_array = !_glewInit_GL_EXT_texture_array(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_texture_array */ #ifdef GL_EXT_texture_buffer_object - CONST_CAST(GLEW_EXT_texture_buffer_object) = _glewSearchExtension("GL_EXT_texture_buffer_object", extStart, extEnd); - if (glewExperimental || GLEW_EXT_texture_buffer_object) CONST_CAST(GLEW_EXT_texture_buffer_object) = !_glewInit_GL_EXT_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_texture_buffer_object = _glewSearchExtension("GL_EXT_texture_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture_buffer_object) GLEW_EXT_texture_buffer_object = !_glewInit_GL_EXT_texture_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_texture_buffer_object */ #ifdef GL_EXT_texture_compression_dxt1 - CONST_CAST(GLEW_EXT_texture_compression_dxt1) = _glewSearchExtension("GL_EXT_texture_compression_dxt1", extStart, extEnd); + GLEW_EXT_texture_compression_dxt1 = _glewSearchExtension("GL_EXT_texture_compression_dxt1", extStart, extEnd); #endif /* GL_EXT_texture_compression_dxt1 */ #ifdef GL_EXT_texture_compression_latc - CONST_CAST(GLEW_EXT_texture_compression_latc) = _glewSearchExtension("GL_EXT_texture_compression_latc", extStart, extEnd); + GLEW_EXT_texture_compression_latc = _glewSearchExtension("GL_EXT_texture_compression_latc", extStart, extEnd); #endif /* GL_EXT_texture_compression_latc */ #ifdef GL_EXT_texture_compression_rgtc - CONST_CAST(GLEW_EXT_texture_compression_rgtc) = _glewSearchExtension("GL_EXT_texture_compression_rgtc", extStart, extEnd); + GLEW_EXT_texture_compression_rgtc = _glewSearchExtension("GL_EXT_texture_compression_rgtc", extStart, extEnd); #endif /* GL_EXT_texture_compression_rgtc */ #ifdef GL_EXT_texture_compression_s3tc - CONST_CAST(GLEW_EXT_texture_compression_s3tc) = _glewSearchExtension("GL_EXT_texture_compression_s3tc", extStart, extEnd); + GLEW_EXT_texture_compression_s3tc = _glewSearchExtension("GL_EXT_texture_compression_s3tc", extStart, extEnd); #endif /* GL_EXT_texture_compression_s3tc */ #ifdef GL_EXT_texture_cube_map - CONST_CAST(GLEW_EXT_texture_cube_map) = _glewSearchExtension("GL_EXT_texture_cube_map", extStart, extEnd); + GLEW_EXT_texture_cube_map = _glewSearchExtension("GL_EXT_texture_cube_map", extStart, extEnd); #endif /* GL_EXT_texture_cube_map */ #ifdef GL_EXT_texture_edge_clamp - CONST_CAST(GLEW_EXT_texture_edge_clamp) = _glewSearchExtension("GL_EXT_texture_edge_clamp", extStart, extEnd); + GLEW_EXT_texture_edge_clamp = _glewSearchExtension("GL_EXT_texture_edge_clamp", extStart, extEnd); #endif /* GL_EXT_texture_edge_clamp */ #ifdef GL_EXT_texture_env - CONST_CAST(GLEW_EXT_texture_env) = _glewSearchExtension("GL_EXT_texture_env", extStart, extEnd); + GLEW_EXT_texture_env = _glewSearchExtension("GL_EXT_texture_env", extStart, extEnd); #endif /* GL_EXT_texture_env */ #ifdef GL_EXT_texture_env_add - CONST_CAST(GLEW_EXT_texture_env_add) = _glewSearchExtension("GL_EXT_texture_env_add", extStart, extEnd); + GLEW_EXT_texture_env_add = _glewSearchExtension("GL_EXT_texture_env_add", extStart, extEnd); #endif /* GL_EXT_texture_env_add */ #ifdef GL_EXT_texture_env_combine - CONST_CAST(GLEW_EXT_texture_env_combine) = _glewSearchExtension("GL_EXT_texture_env_combine", extStart, extEnd); + GLEW_EXT_texture_env_combine = _glewSearchExtension("GL_EXT_texture_env_combine", extStart, extEnd); #endif /* GL_EXT_texture_env_combine */ #ifdef GL_EXT_texture_env_dot3 - CONST_CAST(GLEW_EXT_texture_env_dot3) = _glewSearchExtension("GL_EXT_texture_env_dot3", extStart, extEnd); + GLEW_EXT_texture_env_dot3 = _glewSearchExtension("GL_EXT_texture_env_dot3", extStart, extEnd); #endif /* GL_EXT_texture_env_dot3 */ #ifdef GL_EXT_texture_filter_anisotropic - CONST_CAST(GLEW_EXT_texture_filter_anisotropic) = _glewSearchExtension("GL_EXT_texture_filter_anisotropic", extStart, extEnd); + GLEW_EXT_texture_filter_anisotropic = _glewSearchExtension("GL_EXT_texture_filter_anisotropic", extStart, extEnd); #endif /* GL_EXT_texture_filter_anisotropic */ #ifdef GL_EXT_texture_integer - CONST_CAST(GLEW_EXT_texture_integer) = _glewSearchExtension("GL_EXT_texture_integer", extStart, extEnd); - if (glewExperimental || GLEW_EXT_texture_integer) CONST_CAST(GLEW_EXT_texture_integer) = !_glewInit_GL_EXT_texture_integer(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_texture_integer = _glewSearchExtension("GL_EXT_texture_integer", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture_integer) GLEW_EXT_texture_integer = !_glewInit_GL_EXT_texture_integer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_texture_integer */ #ifdef GL_EXT_texture_lod_bias - CONST_CAST(GLEW_EXT_texture_lod_bias) = _glewSearchExtension("GL_EXT_texture_lod_bias", extStart, extEnd); + GLEW_EXT_texture_lod_bias = _glewSearchExtension("GL_EXT_texture_lod_bias", extStart, extEnd); #endif /* GL_EXT_texture_lod_bias */ #ifdef GL_EXT_texture_mirror_clamp - CONST_CAST(GLEW_EXT_texture_mirror_clamp) = _glewSearchExtension("GL_EXT_texture_mirror_clamp", extStart, extEnd); + GLEW_EXT_texture_mirror_clamp = _glewSearchExtension("GL_EXT_texture_mirror_clamp", extStart, extEnd); #endif /* GL_EXT_texture_mirror_clamp */ #ifdef GL_EXT_texture_object - CONST_CAST(GLEW_EXT_texture_object) = _glewSearchExtension("GL_EXT_texture_object", extStart, extEnd); - if (glewExperimental || GLEW_EXT_texture_object) CONST_CAST(GLEW_EXT_texture_object) = !_glewInit_GL_EXT_texture_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_texture_object = _glewSearchExtension("GL_EXT_texture_object", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture_object) GLEW_EXT_texture_object = !_glewInit_GL_EXT_texture_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_texture_object */ #ifdef GL_EXT_texture_perturb_normal - CONST_CAST(GLEW_EXT_texture_perturb_normal) = _glewSearchExtension("GL_EXT_texture_perturb_normal", extStart, extEnd); - if (glewExperimental || GLEW_EXT_texture_perturb_normal) CONST_CAST(GLEW_EXT_texture_perturb_normal) = !_glewInit_GL_EXT_texture_perturb_normal(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_texture_perturb_normal = _glewSearchExtension("GL_EXT_texture_perturb_normal", extStart, extEnd); + if (glewExperimental || GLEW_EXT_texture_perturb_normal) GLEW_EXT_texture_perturb_normal = !_glewInit_GL_EXT_texture_perturb_normal(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_texture_perturb_normal */ #ifdef GL_EXT_texture_rectangle - CONST_CAST(GLEW_EXT_texture_rectangle) = _glewSearchExtension("GL_EXT_texture_rectangle", extStart, extEnd); + GLEW_EXT_texture_rectangle = _glewSearchExtension("GL_EXT_texture_rectangle", extStart, extEnd); #endif /* GL_EXT_texture_rectangle */ #ifdef GL_EXT_texture_sRGB - CONST_CAST(GLEW_EXT_texture_sRGB) = _glewSearchExtension("GL_EXT_texture_sRGB", extStart, extEnd); + GLEW_EXT_texture_sRGB = _glewSearchExtension("GL_EXT_texture_sRGB", extStart, extEnd); #endif /* GL_EXT_texture_sRGB */ #ifdef GL_EXT_texture_sRGB_decode - CONST_CAST(GLEW_EXT_texture_sRGB_decode) = _glewSearchExtension("GL_EXT_texture_sRGB_decode", extStart, extEnd); + GLEW_EXT_texture_sRGB_decode = _glewSearchExtension("GL_EXT_texture_sRGB_decode", extStart, extEnd); #endif /* GL_EXT_texture_sRGB_decode */ #ifdef GL_EXT_texture_shared_exponent - CONST_CAST(GLEW_EXT_texture_shared_exponent) = _glewSearchExtension("GL_EXT_texture_shared_exponent", extStart, extEnd); + GLEW_EXT_texture_shared_exponent = _glewSearchExtension("GL_EXT_texture_shared_exponent", extStart, extEnd); #endif /* GL_EXT_texture_shared_exponent */ #ifdef GL_EXT_texture_snorm - CONST_CAST(GLEW_EXT_texture_snorm) = _glewSearchExtension("GL_EXT_texture_snorm", extStart, extEnd); + GLEW_EXT_texture_snorm = _glewSearchExtension("GL_EXT_texture_snorm", extStart, extEnd); #endif /* GL_EXT_texture_snorm */ #ifdef GL_EXT_texture_swizzle - CONST_CAST(GLEW_EXT_texture_swizzle) = _glewSearchExtension("GL_EXT_texture_swizzle", extStart, extEnd); + GLEW_EXT_texture_swizzle = _glewSearchExtension("GL_EXT_texture_swizzle", extStart, extEnd); #endif /* GL_EXT_texture_swizzle */ #ifdef GL_EXT_timer_query - CONST_CAST(GLEW_EXT_timer_query) = _glewSearchExtension("GL_EXT_timer_query", extStart, extEnd); - if (glewExperimental || GLEW_EXT_timer_query) CONST_CAST(GLEW_EXT_timer_query) = !_glewInit_GL_EXT_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_timer_query = _glewSearchExtension("GL_EXT_timer_query", extStart, extEnd); + if (glewExperimental || GLEW_EXT_timer_query) GLEW_EXT_timer_query = !_glewInit_GL_EXT_timer_query(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_timer_query */ #ifdef GL_EXT_transform_feedback - CONST_CAST(GLEW_EXT_transform_feedback) = _glewSearchExtension("GL_EXT_transform_feedback", extStart, extEnd); - if (glewExperimental || GLEW_EXT_transform_feedback) CONST_CAST(GLEW_EXT_transform_feedback) = !_glewInit_GL_EXT_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_transform_feedback = _glewSearchExtension("GL_EXT_transform_feedback", extStart, extEnd); + if (glewExperimental || GLEW_EXT_transform_feedback) GLEW_EXT_transform_feedback = !_glewInit_GL_EXT_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_transform_feedback */ #ifdef GL_EXT_vertex_array - CONST_CAST(GLEW_EXT_vertex_array) = _glewSearchExtension("GL_EXT_vertex_array", extStart, extEnd); - if (glewExperimental || GLEW_EXT_vertex_array) CONST_CAST(GLEW_EXT_vertex_array) = !_glewInit_GL_EXT_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_vertex_array = _glewSearchExtension("GL_EXT_vertex_array", extStart, extEnd); + if (glewExperimental || GLEW_EXT_vertex_array) GLEW_EXT_vertex_array = !_glewInit_GL_EXT_vertex_array(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_vertex_array */ #ifdef GL_EXT_vertex_array_bgra - CONST_CAST(GLEW_EXT_vertex_array_bgra) = _glewSearchExtension("GL_EXT_vertex_array_bgra", extStart, extEnd); + GLEW_EXT_vertex_array_bgra = _glewSearchExtension("GL_EXT_vertex_array_bgra", extStart, extEnd); #endif /* GL_EXT_vertex_array_bgra */ #ifdef GL_EXT_vertex_attrib_64bit - CONST_CAST(GLEW_EXT_vertex_attrib_64bit) = _glewSearchExtension("GL_EXT_vertex_attrib_64bit", extStart, extEnd); - if (glewExperimental || GLEW_EXT_vertex_attrib_64bit) CONST_CAST(GLEW_EXT_vertex_attrib_64bit) = !_glewInit_GL_EXT_vertex_attrib_64bit(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_vertex_attrib_64bit = _glewSearchExtension("GL_EXT_vertex_attrib_64bit", extStart, extEnd); + if (glewExperimental || GLEW_EXT_vertex_attrib_64bit) GLEW_EXT_vertex_attrib_64bit = !_glewInit_GL_EXT_vertex_attrib_64bit(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_vertex_attrib_64bit */ #ifdef GL_EXT_vertex_shader - CONST_CAST(GLEW_EXT_vertex_shader) = _glewSearchExtension("GL_EXT_vertex_shader", extStart, extEnd); - if (glewExperimental || GLEW_EXT_vertex_shader) CONST_CAST(GLEW_EXT_vertex_shader) = !_glewInit_GL_EXT_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_vertex_shader = _glewSearchExtension("GL_EXT_vertex_shader", extStart, extEnd); + if (glewExperimental || GLEW_EXT_vertex_shader) GLEW_EXT_vertex_shader = !_glewInit_GL_EXT_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_vertex_shader */ #ifdef GL_EXT_vertex_weighting - CONST_CAST(GLEW_EXT_vertex_weighting) = _glewSearchExtension("GL_EXT_vertex_weighting", extStart, extEnd); - if (glewExperimental || GLEW_EXT_vertex_weighting) CONST_CAST(GLEW_EXT_vertex_weighting) = !_glewInit_GL_EXT_vertex_weighting(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_vertex_weighting = _glewSearchExtension("GL_EXT_vertex_weighting", extStart, extEnd); + if (glewExperimental || GLEW_EXT_vertex_weighting) GLEW_EXT_vertex_weighting = !_glewInit_GL_EXT_vertex_weighting(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_vertex_weighting */ #ifdef GL_EXT_x11_sync_object - CONST_CAST(GLEW_EXT_x11_sync_object) = _glewSearchExtension("GL_EXT_x11_sync_object", extStart, extEnd); - if (glewExperimental || GLEW_EXT_x11_sync_object) CONST_CAST(GLEW_EXT_x11_sync_object) = !_glewInit_GL_EXT_x11_sync_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_EXT_x11_sync_object = _glewSearchExtension("GL_EXT_x11_sync_object", extStart, extEnd); + if (glewExperimental || GLEW_EXT_x11_sync_object) GLEW_EXT_x11_sync_object = !_glewInit_GL_EXT_x11_sync_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_EXT_x11_sync_object */ #ifdef GL_GREMEDY_frame_terminator - CONST_CAST(GLEW_GREMEDY_frame_terminator) = _glewSearchExtension("GL_GREMEDY_frame_terminator", extStart, extEnd); - if (glewExperimental || GLEW_GREMEDY_frame_terminator) CONST_CAST(GLEW_GREMEDY_frame_terminator) = !_glewInit_GL_GREMEDY_frame_terminator(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_GREMEDY_frame_terminator = _glewSearchExtension("GL_GREMEDY_frame_terminator", extStart, extEnd); + if (glewExperimental || GLEW_GREMEDY_frame_terminator) GLEW_GREMEDY_frame_terminator = !_glewInit_GL_GREMEDY_frame_terminator(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_GREMEDY_frame_terminator */ #ifdef GL_GREMEDY_string_marker - CONST_CAST(GLEW_GREMEDY_string_marker) = _glewSearchExtension("GL_GREMEDY_string_marker", extStart, extEnd); - if (glewExperimental || GLEW_GREMEDY_string_marker) CONST_CAST(GLEW_GREMEDY_string_marker) = !_glewInit_GL_GREMEDY_string_marker(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_GREMEDY_string_marker = _glewSearchExtension("GL_GREMEDY_string_marker", extStart, extEnd); + if (glewExperimental || GLEW_GREMEDY_string_marker) GLEW_GREMEDY_string_marker = !_glewInit_GL_GREMEDY_string_marker(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_GREMEDY_string_marker */ #ifdef GL_HP_convolution_border_modes - CONST_CAST(GLEW_HP_convolution_border_modes) = _glewSearchExtension("GL_HP_convolution_border_modes", extStart, extEnd); + GLEW_HP_convolution_border_modes = _glewSearchExtension("GL_HP_convolution_border_modes", extStart, extEnd); #endif /* GL_HP_convolution_border_modes */ #ifdef GL_HP_image_transform - CONST_CAST(GLEW_HP_image_transform) = _glewSearchExtension("GL_HP_image_transform", extStart, extEnd); - if (glewExperimental || GLEW_HP_image_transform) CONST_CAST(GLEW_HP_image_transform) = !_glewInit_GL_HP_image_transform(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_HP_image_transform = _glewSearchExtension("GL_HP_image_transform", extStart, extEnd); + if (glewExperimental || GLEW_HP_image_transform) GLEW_HP_image_transform = !_glewInit_GL_HP_image_transform(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_HP_image_transform */ #ifdef GL_HP_occlusion_test - CONST_CAST(GLEW_HP_occlusion_test) = _glewSearchExtension("GL_HP_occlusion_test", extStart, extEnd); + GLEW_HP_occlusion_test = _glewSearchExtension("GL_HP_occlusion_test", extStart, extEnd); #endif /* GL_HP_occlusion_test */ #ifdef GL_HP_texture_lighting - CONST_CAST(GLEW_HP_texture_lighting) = _glewSearchExtension("GL_HP_texture_lighting", extStart, extEnd); + GLEW_HP_texture_lighting = _glewSearchExtension("GL_HP_texture_lighting", extStart, extEnd); #endif /* GL_HP_texture_lighting */ #ifdef GL_IBM_cull_vertex - CONST_CAST(GLEW_IBM_cull_vertex) = _glewSearchExtension("GL_IBM_cull_vertex", extStart, extEnd); + GLEW_IBM_cull_vertex = _glewSearchExtension("GL_IBM_cull_vertex", extStart, extEnd); #endif /* GL_IBM_cull_vertex */ #ifdef GL_IBM_multimode_draw_arrays - CONST_CAST(GLEW_IBM_multimode_draw_arrays) = _glewSearchExtension("GL_IBM_multimode_draw_arrays", extStart, extEnd); - if (glewExperimental || GLEW_IBM_multimode_draw_arrays) CONST_CAST(GLEW_IBM_multimode_draw_arrays) = !_glewInit_GL_IBM_multimode_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_IBM_multimode_draw_arrays = _glewSearchExtension("GL_IBM_multimode_draw_arrays", extStart, extEnd); + if (glewExperimental || GLEW_IBM_multimode_draw_arrays) GLEW_IBM_multimode_draw_arrays = !_glewInit_GL_IBM_multimode_draw_arrays(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_IBM_multimode_draw_arrays */ #ifdef GL_IBM_rasterpos_clip - CONST_CAST(GLEW_IBM_rasterpos_clip) = _glewSearchExtension("GL_IBM_rasterpos_clip", extStart, extEnd); + GLEW_IBM_rasterpos_clip = _glewSearchExtension("GL_IBM_rasterpos_clip", extStart, extEnd); #endif /* GL_IBM_rasterpos_clip */ #ifdef GL_IBM_static_data - CONST_CAST(GLEW_IBM_static_data) = _glewSearchExtension("GL_IBM_static_data", extStart, extEnd); + GLEW_IBM_static_data = _glewSearchExtension("GL_IBM_static_data", extStart, extEnd); #endif /* GL_IBM_static_data */ #ifdef GL_IBM_texture_mirrored_repeat - CONST_CAST(GLEW_IBM_texture_mirrored_repeat) = _glewSearchExtension("GL_IBM_texture_mirrored_repeat", extStart, extEnd); + GLEW_IBM_texture_mirrored_repeat = _glewSearchExtension("GL_IBM_texture_mirrored_repeat", extStart, extEnd); #endif /* GL_IBM_texture_mirrored_repeat */ #ifdef GL_IBM_vertex_array_lists - CONST_CAST(GLEW_IBM_vertex_array_lists) = _glewSearchExtension("GL_IBM_vertex_array_lists", extStart, extEnd); - if (glewExperimental || GLEW_IBM_vertex_array_lists) CONST_CAST(GLEW_IBM_vertex_array_lists) = !_glewInit_GL_IBM_vertex_array_lists(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_IBM_vertex_array_lists = _glewSearchExtension("GL_IBM_vertex_array_lists", extStart, extEnd); + if (glewExperimental || GLEW_IBM_vertex_array_lists) GLEW_IBM_vertex_array_lists = !_glewInit_GL_IBM_vertex_array_lists(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_IBM_vertex_array_lists */ #ifdef GL_INGR_color_clamp - CONST_CAST(GLEW_INGR_color_clamp) = _glewSearchExtension("GL_INGR_color_clamp", extStart, extEnd); + GLEW_INGR_color_clamp = _glewSearchExtension("GL_INGR_color_clamp", extStart, extEnd); #endif /* GL_INGR_color_clamp */ #ifdef GL_INGR_interlace_read - CONST_CAST(GLEW_INGR_interlace_read) = _glewSearchExtension("GL_INGR_interlace_read", extStart, extEnd); + GLEW_INGR_interlace_read = _glewSearchExtension("GL_INGR_interlace_read", extStart, extEnd); #endif /* GL_INGR_interlace_read */ +#ifdef GL_INTEL_fragment_shader_ordering + GLEW_INTEL_fragment_shader_ordering = _glewSearchExtension("GL_INTEL_fragment_shader_ordering", extStart, extEnd); +#endif /* GL_INTEL_fragment_shader_ordering */ #ifdef GL_INTEL_map_texture - CONST_CAST(GLEW_INTEL_map_texture) = _glewSearchExtension("GL_INTEL_map_texture", extStart, extEnd); - if (glewExperimental || GLEW_INTEL_map_texture) CONST_CAST(GLEW_INTEL_map_texture) = !_glewInit_GL_INTEL_map_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_INTEL_map_texture = _glewSearchExtension("GL_INTEL_map_texture", extStart, extEnd); + if (glewExperimental || GLEW_INTEL_map_texture) GLEW_INTEL_map_texture = !_glewInit_GL_INTEL_map_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_INTEL_map_texture */ #ifdef GL_INTEL_parallel_arrays - CONST_CAST(GLEW_INTEL_parallel_arrays) = _glewSearchExtension("GL_INTEL_parallel_arrays", extStart, extEnd); - if (glewExperimental || GLEW_INTEL_parallel_arrays) CONST_CAST(GLEW_INTEL_parallel_arrays) = !_glewInit_GL_INTEL_parallel_arrays(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_INTEL_parallel_arrays = _glewSearchExtension("GL_INTEL_parallel_arrays", extStart, extEnd); + if (glewExperimental || GLEW_INTEL_parallel_arrays) GLEW_INTEL_parallel_arrays = !_glewInit_GL_INTEL_parallel_arrays(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_INTEL_parallel_arrays */ +#ifdef GL_INTEL_performance_query + GLEW_INTEL_performance_query = _glewSearchExtension("GL_INTEL_performance_query", extStart, extEnd); + if (glewExperimental || GLEW_INTEL_performance_query) GLEW_INTEL_performance_query = !_glewInit_GL_INTEL_performance_query(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_INTEL_performance_query */ #ifdef GL_INTEL_texture_scissor - CONST_CAST(GLEW_INTEL_texture_scissor) = _glewSearchExtension("GL_INTEL_texture_scissor", extStart, extEnd); - if (glewExperimental || GLEW_INTEL_texture_scissor) CONST_CAST(GLEW_INTEL_texture_scissor) = !_glewInit_GL_INTEL_texture_scissor(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_INTEL_texture_scissor = _glewSearchExtension("GL_INTEL_texture_scissor", extStart, extEnd); + if (glewExperimental || GLEW_INTEL_texture_scissor) GLEW_INTEL_texture_scissor = !_glewInit_GL_INTEL_texture_scissor(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_INTEL_texture_scissor */ #ifdef GL_KHR_debug - CONST_CAST(GLEW_KHR_debug) = _glewSearchExtension("GL_KHR_debug", extStart, extEnd); - if (glewExperimental || GLEW_KHR_debug) CONST_CAST(GLEW_KHR_debug) = !_glewInit_GL_KHR_debug(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_KHR_debug = _glewSearchExtension("GL_KHR_debug", extStart, extEnd); + if (glewExperimental || GLEW_KHR_debug) GLEW_KHR_debug = !_glewInit_GL_KHR_debug(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_KHR_debug */ +#ifdef GL_KHR_texture_compression_astc_hdr + GLEW_KHR_texture_compression_astc_hdr = _glewSearchExtension("GL_KHR_texture_compression_astc_hdr", extStart, extEnd); +#endif /* GL_KHR_texture_compression_astc_hdr */ #ifdef GL_KHR_texture_compression_astc_ldr - CONST_CAST(GLEW_KHR_texture_compression_astc_ldr) = _glewSearchExtension("GL_KHR_texture_compression_astc_ldr", extStart, extEnd); + GLEW_KHR_texture_compression_astc_ldr = _glewSearchExtension("GL_KHR_texture_compression_astc_ldr", extStart, extEnd); #endif /* GL_KHR_texture_compression_astc_ldr */ #ifdef GL_KTX_buffer_region - CONST_CAST(GLEW_KTX_buffer_region) = _glewSearchExtension("GL_KTX_buffer_region", extStart, extEnd); - if (glewExperimental || GLEW_KTX_buffer_region) CONST_CAST(GLEW_KTX_buffer_region) = !_glewInit_GL_KTX_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_KTX_buffer_region = _glewSearchExtension("GL_KTX_buffer_region", extStart, extEnd); + if (glewExperimental || GLEW_KTX_buffer_region) GLEW_KTX_buffer_region = !_glewInit_GL_KTX_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_KTX_buffer_region */ #ifdef GL_MESAX_texture_stack - CONST_CAST(GLEW_MESAX_texture_stack) = _glewSearchExtension("GL_MESAX_texture_stack", extStart, extEnd); + GLEW_MESAX_texture_stack = _glewSearchExtension("GL_MESAX_texture_stack", extStart, extEnd); #endif /* GL_MESAX_texture_stack */ #ifdef GL_MESA_pack_invert - CONST_CAST(GLEW_MESA_pack_invert) = _glewSearchExtension("GL_MESA_pack_invert", extStart, extEnd); + GLEW_MESA_pack_invert = _glewSearchExtension("GL_MESA_pack_invert", extStart, extEnd); #endif /* GL_MESA_pack_invert */ #ifdef GL_MESA_resize_buffers - CONST_CAST(GLEW_MESA_resize_buffers) = _glewSearchExtension("GL_MESA_resize_buffers", extStart, extEnd); - if (glewExperimental || GLEW_MESA_resize_buffers) CONST_CAST(GLEW_MESA_resize_buffers) = !_glewInit_GL_MESA_resize_buffers(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_MESA_resize_buffers = _glewSearchExtension("GL_MESA_resize_buffers", extStart, extEnd); + if (glewExperimental || GLEW_MESA_resize_buffers) GLEW_MESA_resize_buffers = !_glewInit_GL_MESA_resize_buffers(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_MESA_resize_buffers */ #ifdef GL_MESA_window_pos - CONST_CAST(GLEW_MESA_window_pos) = _glewSearchExtension("GL_MESA_window_pos", extStart, extEnd); - if (glewExperimental || GLEW_MESA_window_pos) CONST_CAST(GLEW_MESA_window_pos) = !_glewInit_GL_MESA_window_pos(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_MESA_window_pos = _glewSearchExtension("GL_MESA_window_pos", extStart, extEnd); + if (glewExperimental || GLEW_MESA_window_pos) GLEW_MESA_window_pos = !_glewInit_GL_MESA_window_pos(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_MESA_window_pos */ #ifdef GL_MESA_ycbcr_texture - CONST_CAST(GLEW_MESA_ycbcr_texture) = _glewSearchExtension("GL_MESA_ycbcr_texture", extStart, extEnd); + GLEW_MESA_ycbcr_texture = _glewSearchExtension("GL_MESA_ycbcr_texture", extStart, extEnd); #endif /* GL_MESA_ycbcr_texture */ #ifdef GL_NVX_conditional_render - CONST_CAST(GLEW_NVX_conditional_render) = _glewSearchExtension("GL_NVX_conditional_render", extStart, extEnd); - if (glewExperimental || GLEW_NVX_conditional_render) CONST_CAST(GLEW_NVX_conditional_render) = !_glewInit_GL_NVX_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NVX_conditional_render = _glewSearchExtension("GL_NVX_conditional_render", extStart, extEnd); + if (glewExperimental || GLEW_NVX_conditional_render) GLEW_NVX_conditional_render = !_glewInit_GL_NVX_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NVX_conditional_render */ #ifdef GL_NVX_gpu_memory_info - CONST_CAST(GLEW_NVX_gpu_memory_info) = _glewSearchExtension("GL_NVX_gpu_memory_info", extStart, extEnd); + GLEW_NVX_gpu_memory_info = _glewSearchExtension("GL_NVX_gpu_memory_info", extStart, extEnd); #endif /* GL_NVX_gpu_memory_info */ #ifdef GL_NV_bindless_multi_draw_indirect - CONST_CAST(GLEW_NV_bindless_multi_draw_indirect) = _glewSearchExtension("GL_NV_bindless_multi_draw_indirect", extStart, extEnd); - if (glewExperimental || GLEW_NV_bindless_multi_draw_indirect) CONST_CAST(GLEW_NV_bindless_multi_draw_indirect) = !_glewInit_GL_NV_bindless_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_bindless_multi_draw_indirect = _glewSearchExtension("GL_NV_bindless_multi_draw_indirect", extStart, extEnd); + if (glewExperimental || GLEW_NV_bindless_multi_draw_indirect) GLEW_NV_bindless_multi_draw_indirect = !_glewInit_GL_NV_bindless_multi_draw_indirect(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_bindless_multi_draw_indirect */ #ifdef GL_NV_bindless_texture - CONST_CAST(GLEW_NV_bindless_texture) = _glewSearchExtension("GL_NV_bindless_texture", extStart, extEnd); - if (glewExperimental || GLEW_NV_bindless_texture) CONST_CAST(GLEW_NV_bindless_texture) = !_glewInit_GL_NV_bindless_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_bindless_texture = _glewSearchExtension("GL_NV_bindless_texture", extStart, extEnd); + if (glewExperimental || GLEW_NV_bindless_texture) GLEW_NV_bindless_texture = !_glewInit_GL_NV_bindless_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_bindless_texture */ #ifdef GL_NV_blend_equation_advanced - CONST_CAST(GLEW_NV_blend_equation_advanced) = _glewSearchExtension("GL_NV_blend_equation_advanced", extStart, extEnd); - if (glewExperimental || GLEW_NV_blend_equation_advanced) CONST_CAST(GLEW_NV_blend_equation_advanced) = !_glewInit_GL_NV_blend_equation_advanced(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_blend_equation_advanced = _glewSearchExtension("GL_NV_blend_equation_advanced", extStart, extEnd); + if (glewExperimental || GLEW_NV_blend_equation_advanced) GLEW_NV_blend_equation_advanced = !_glewInit_GL_NV_blend_equation_advanced(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_blend_equation_advanced */ #ifdef GL_NV_blend_equation_advanced_coherent - CONST_CAST(GLEW_NV_blend_equation_advanced_coherent) = _glewSearchExtension("GL_NV_blend_equation_advanced_coherent", extStart, extEnd); + GLEW_NV_blend_equation_advanced_coherent = _glewSearchExtension("GL_NV_blend_equation_advanced_coherent", extStart, extEnd); #endif /* GL_NV_blend_equation_advanced_coherent */ #ifdef GL_NV_blend_square - CONST_CAST(GLEW_NV_blend_square) = _glewSearchExtension("GL_NV_blend_square", extStart, extEnd); + GLEW_NV_blend_square = _glewSearchExtension("GL_NV_blend_square", extStart, extEnd); #endif /* GL_NV_blend_square */ #ifdef GL_NV_compute_program5 - CONST_CAST(GLEW_NV_compute_program5) = _glewSearchExtension("GL_NV_compute_program5", extStart, extEnd); + GLEW_NV_compute_program5 = _glewSearchExtension("GL_NV_compute_program5", extStart, extEnd); #endif /* GL_NV_compute_program5 */ #ifdef GL_NV_conditional_render - CONST_CAST(GLEW_NV_conditional_render) = _glewSearchExtension("GL_NV_conditional_render", extStart, extEnd); - if (glewExperimental || GLEW_NV_conditional_render) CONST_CAST(GLEW_NV_conditional_render) = !_glewInit_GL_NV_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_conditional_render = _glewSearchExtension("GL_NV_conditional_render", extStart, extEnd); + if (glewExperimental || GLEW_NV_conditional_render) GLEW_NV_conditional_render = !_glewInit_GL_NV_conditional_render(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_conditional_render */ #ifdef GL_NV_copy_depth_to_color - CONST_CAST(GLEW_NV_copy_depth_to_color) = _glewSearchExtension("GL_NV_copy_depth_to_color", extStart, extEnd); + GLEW_NV_copy_depth_to_color = _glewSearchExtension("GL_NV_copy_depth_to_color", extStart, extEnd); #endif /* GL_NV_copy_depth_to_color */ #ifdef GL_NV_copy_image - CONST_CAST(GLEW_NV_copy_image) = _glewSearchExtension("GL_NV_copy_image", extStart, extEnd); - if (glewExperimental || GLEW_NV_copy_image) CONST_CAST(GLEW_NV_copy_image) = !_glewInit_GL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_copy_image = _glewSearchExtension("GL_NV_copy_image", extStart, extEnd); + if (glewExperimental || GLEW_NV_copy_image) GLEW_NV_copy_image = !_glewInit_GL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_copy_image */ #ifdef GL_NV_deep_texture3D - CONST_CAST(GLEW_NV_deep_texture3D) = _glewSearchExtension("GL_NV_deep_texture3D", extStart, extEnd); + GLEW_NV_deep_texture3D = _glewSearchExtension("GL_NV_deep_texture3D", extStart, extEnd); #endif /* GL_NV_deep_texture3D */ #ifdef GL_NV_depth_buffer_float - CONST_CAST(GLEW_NV_depth_buffer_float) = _glewSearchExtension("GL_NV_depth_buffer_float", extStart, extEnd); - if (glewExperimental || GLEW_NV_depth_buffer_float) CONST_CAST(GLEW_NV_depth_buffer_float) = !_glewInit_GL_NV_depth_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_depth_buffer_float = _glewSearchExtension("GL_NV_depth_buffer_float", extStart, extEnd); + if (glewExperimental || GLEW_NV_depth_buffer_float) GLEW_NV_depth_buffer_float = !_glewInit_GL_NV_depth_buffer_float(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_depth_buffer_float */ #ifdef GL_NV_depth_clamp - CONST_CAST(GLEW_NV_depth_clamp) = _glewSearchExtension("GL_NV_depth_clamp", extStart, extEnd); + GLEW_NV_depth_clamp = _glewSearchExtension("GL_NV_depth_clamp", extStart, extEnd); #endif /* GL_NV_depth_clamp */ #ifdef GL_NV_depth_range_unclamped - CONST_CAST(GLEW_NV_depth_range_unclamped) = _glewSearchExtension("GL_NV_depth_range_unclamped", extStart, extEnd); + GLEW_NV_depth_range_unclamped = _glewSearchExtension("GL_NV_depth_range_unclamped", extStart, extEnd); #endif /* GL_NV_depth_range_unclamped */ #ifdef GL_NV_draw_texture - CONST_CAST(GLEW_NV_draw_texture) = _glewSearchExtension("GL_NV_draw_texture", extStart, extEnd); - if (glewExperimental || GLEW_NV_draw_texture) CONST_CAST(GLEW_NV_draw_texture) = !_glewInit_GL_NV_draw_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_draw_texture = _glewSearchExtension("GL_NV_draw_texture", extStart, extEnd); + if (glewExperimental || GLEW_NV_draw_texture) GLEW_NV_draw_texture = !_glewInit_GL_NV_draw_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_draw_texture */ #ifdef GL_NV_evaluators - CONST_CAST(GLEW_NV_evaluators) = _glewSearchExtension("GL_NV_evaluators", extStart, extEnd); - if (glewExperimental || GLEW_NV_evaluators) CONST_CAST(GLEW_NV_evaluators) = !_glewInit_GL_NV_evaluators(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_evaluators = _glewSearchExtension("GL_NV_evaluators", extStart, extEnd); + if (glewExperimental || GLEW_NV_evaluators) GLEW_NV_evaluators = !_glewInit_GL_NV_evaluators(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_evaluators */ #ifdef GL_NV_explicit_multisample - CONST_CAST(GLEW_NV_explicit_multisample) = _glewSearchExtension("GL_NV_explicit_multisample", extStart, extEnd); - if (glewExperimental || GLEW_NV_explicit_multisample) CONST_CAST(GLEW_NV_explicit_multisample) = !_glewInit_GL_NV_explicit_multisample(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_explicit_multisample = _glewSearchExtension("GL_NV_explicit_multisample", extStart, extEnd); + if (glewExperimental || GLEW_NV_explicit_multisample) GLEW_NV_explicit_multisample = !_glewInit_GL_NV_explicit_multisample(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_explicit_multisample */ #ifdef GL_NV_fence - CONST_CAST(GLEW_NV_fence) = _glewSearchExtension("GL_NV_fence", extStart, extEnd); - if (glewExperimental || GLEW_NV_fence) CONST_CAST(GLEW_NV_fence) = !_glewInit_GL_NV_fence(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_fence = _glewSearchExtension("GL_NV_fence", extStart, extEnd); + if (glewExperimental || GLEW_NV_fence) GLEW_NV_fence = !_glewInit_GL_NV_fence(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_fence */ #ifdef GL_NV_float_buffer - CONST_CAST(GLEW_NV_float_buffer) = _glewSearchExtension("GL_NV_float_buffer", extStart, extEnd); + GLEW_NV_float_buffer = _glewSearchExtension("GL_NV_float_buffer", extStart, extEnd); #endif /* GL_NV_float_buffer */ #ifdef GL_NV_fog_distance - CONST_CAST(GLEW_NV_fog_distance) = _glewSearchExtension("GL_NV_fog_distance", extStart, extEnd); + GLEW_NV_fog_distance = _glewSearchExtension("GL_NV_fog_distance", extStart, extEnd); #endif /* GL_NV_fog_distance */ #ifdef GL_NV_fragment_program - CONST_CAST(GLEW_NV_fragment_program) = _glewSearchExtension("GL_NV_fragment_program", extStart, extEnd); - if (glewExperimental || GLEW_NV_fragment_program) CONST_CAST(GLEW_NV_fragment_program) = !_glewInit_GL_NV_fragment_program(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_fragment_program = _glewSearchExtension("GL_NV_fragment_program", extStart, extEnd); + if (glewExperimental || GLEW_NV_fragment_program) GLEW_NV_fragment_program = !_glewInit_GL_NV_fragment_program(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_fragment_program */ #ifdef GL_NV_fragment_program2 - CONST_CAST(GLEW_NV_fragment_program2) = _glewSearchExtension("GL_NV_fragment_program2", extStart, extEnd); + GLEW_NV_fragment_program2 = _glewSearchExtension("GL_NV_fragment_program2", extStart, extEnd); #endif /* GL_NV_fragment_program2 */ #ifdef GL_NV_fragment_program4 - CONST_CAST(GLEW_NV_fragment_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); + GLEW_NV_fragment_program4 = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); #endif /* GL_NV_fragment_program4 */ #ifdef GL_NV_fragment_program_option - CONST_CAST(GLEW_NV_fragment_program_option) = _glewSearchExtension("GL_NV_fragment_program_option", extStart, extEnd); + GLEW_NV_fragment_program_option = _glewSearchExtension("GL_NV_fragment_program_option", extStart, extEnd); #endif /* GL_NV_fragment_program_option */ #ifdef GL_NV_framebuffer_multisample_coverage - CONST_CAST(GLEW_NV_framebuffer_multisample_coverage) = _glewSearchExtension("GL_NV_framebuffer_multisample_coverage", extStart, extEnd); - if (glewExperimental || GLEW_NV_framebuffer_multisample_coverage) CONST_CAST(GLEW_NV_framebuffer_multisample_coverage) = !_glewInit_GL_NV_framebuffer_multisample_coverage(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_framebuffer_multisample_coverage = _glewSearchExtension("GL_NV_framebuffer_multisample_coverage", extStart, extEnd); + if (glewExperimental || GLEW_NV_framebuffer_multisample_coverage) GLEW_NV_framebuffer_multisample_coverage = !_glewInit_GL_NV_framebuffer_multisample_coverage(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_framebuffer_multisample_coverage */ #ifdef GL_NV_geometry_program4 - CONST_CAST(GLEW_NV_geometry_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); - if (glewExperimental || GLEW_NV_geometry_program4) CONST_CAST(GLEW_NV_geometry_program4) = !_glewInit_GL_NV_geometry_program4(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_geometry_program4 = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); + if (glewExperimental || GLEW_NV_geometry_program4) GLEW_NV_geometry_program4 = !_glewInit_GL_NV_geometry_program4(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_geometry_program4 */ #ifdef GL_NV_geometry_shader4 - CONST_CAST(GLEW_NV_geometry_shader4) = _glewSearchExtension("GL_NV_geometry_shader4", extStart, extEnd); + GLEW_NV_geometry_shader4 = _glewSearchExtension("GL_NV_geometry_shader4", extStart, extEnd); #endif /* GL_NV_geometry_shader4 */ #ifdef GL_NV_gpu_program4 - CONST_CAST(GLEW_NV_gpu_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); - if (glewExperimental || GLEW_NV_gpu_program4) CONST_CAST(GLEW_NV_gpu_program4) = !_glewInit_GL_NV_gpu_program4(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_gpu_program4 = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); + if (glewExperimental || GLEW_NV_gpu_program4) GLEW_NV_gpu_program4 = !_glewInit_GL_NV_gpu_program4(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_gpu_program4 */ #ifdef GL_NV_gpu_program5 - CONST_CAST(GLEW_NV_gpu_program5) = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd); + GLEW_NV_gpu_program5 = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd); #endif /* GL_NV_gpu_program5 */ #ifdef GL_NV_gpu_program5_mem_extended - CONST_CAST(GLEW_NV_gpu_program5_mem_extended) = _glewSearchExtension("GL_NV_gpu_program5_mem_extended", extStart, extEnd); + GLEW_NV_gpu_program5_mem_extended = _glewSearchExtension("GL_NV_gpu_program5_mem_extended", extStart, extEnd); #endif /* GL_NV_gpu_program5_mem_extended */ #ifdef GL_NV_gpu_program_fp64 - CONST_CAST(GLEW_NV_gpu_program_fp64) = _glewSearchExtension("GL_NV_gpu_program_fp64", extStart, extEnd); + GLEW_NV_gpu_program_fp64 = _glewSearchExtension("GL_NV_gpu_program_fp64", extStart, extEnd); #endif /* GL_NV_gpu_program_fp64 */ #ifdef GL_NV_gpu_shader5 - CONST_CAST(GLEW_NV_gpu_shader5) = _glewSearchExtension("GL_NV_gpu_shader5", extStart, extEnd); - if (glewExperimental || GLEW_NV_gpu_shader5) CONST_CAST(GLEW_NV_gpu_shader5) = !_glewInit_GL_NV_gpu_shader5(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_gpu_shader5 = _glewSearchExtension("GL_NV_gpu_shader5", extStart, extEnd); + if (glewExperimental || GLEW_NV_gpu_shader5) GLEW_NV_gpu_shader5 = !_glewInit_GL_NV_gpu_shader5(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_gpu_shader5 */ #ifdef GL_NV_half_float - CONST_CAST(GLEW_NV_half_float) = _glewSearchExtension("GL_NV_half_float", extStart, extEnd); - if (glewExperimental || GLEW_NV_half_float) CONST_CAST(GLEW_NV_half_float) = !_glewInit_GL_NV_half_float(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_half_float = _glewSearchExtension("GL_NV_half_float", extStart, extEnd); + if (glewExperimental || GLEW_NV_half_float) GLEW_NV_half_float = !_glewInit_GL_NV_half_float(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_half_float */ #ifdef GL_NV_light_max_exponent - CONST_CAST(GLEW_NV_light_max_exponent) = _glewSearchExtension("GL_NV_light_max_exponent", extStart, extEnd); + GLEW_NV_light_max_exponent = _glewSearchExtension("GL_NV_light_max_exponent", extStart, extEnd); #endif /* GL_NV_light_max_exponent */ #ifdef GL_NV_multisample_coverage - CONST_CAST(GLEW_NV_multisample_coverage) = _glewSearchExtension("GL_NV_multisample_coverage", extStart, extEnd); + GLEW_NV_multisample_coverage = _glewSearchExtension("GL_NV_multisample_coverage", extStart, extEnd); #endif /* GL_NV_multisample_coverage */ #ifdef GL_NV_multisample_filter_hint - CONST_CAST(GLEW_NV_multisample_filter_hint) = _glewSearchExtension("GL_NV_multisample_filter_hint", extStart, extEnd); + GLEW_NV_multisample_filter_hint = _glewSearchExtension("GL_NV_multisample_filter_hint", extStart, extEnd); #endif /* GL_NV_multisample_filter_hint */ #ifdef GL_NV_occlusion_query - CONST_CAST(GLEW_NV_occlusion_query) = _glewSearchExtension("GL_NV_occlusion_query", extStart, extEnd); - if (glewExperimental || GLEW_NV_occlusion_query) CONST_CAST(GLEW_NV_occlusion_query) = !_glewInit_GL_NV_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_occlusion_query = _glewSearchExtension("GL_NV_occlusion_query", extStart, extEnd); + if (glewExperimental || GLEW_NV_occlusion_query) GLEW_NV_occlusion_query = !_glewInit_GL_NV_occlusion_query(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_occlusion_query */ #ifdef GL_NV_packed_depth_stencil - CONST_CAST(GLEW_NV_packed_depth_stencil) = _glewSearchExtension("GL_NV_packed_depth_stencil", extStart, extEnd); + GLEW_NV_packed_depth_stencil = _glewSearchExtension("GL_NV_packed_depth_stencil", extStart, extEnd); #endif /* GL_NV_packed_depth_stencil */ #ifdef GL_NV_parameter_buffer_object - CONST_CAST(GLEW_NV_parameter_buffer_object) = _glewSearchExtension("GL_NV_parameter_buffer_object", extStart, extEnd); - if (glewExperimental || GLEW_NV_parameter_buffer_object) CONST_CAST(GLEW_NV_parameter_buffer_object) = !_glewInit_GL_NV_parameter_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_parameter_buffer_object = _glewSearchExtension("GL_NV_parameter_buffer_object", extStart, extEnd); + if (glewExperimental || GLEW_NV_parameter_buffer_object) GLEW_NV_parameter_buffer_object = !_glewInit_GL_NV_parameter_buffer_object(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_parameter_buffer_object */ #ifdef GL_NV_parameter_buffer_object2 - CONST_CAST(GLEW_NV_parameter_buffer_object2) = _glewSearchExtension("GL_NV_parameter_buffer_object2", extStart, extEnd); + GLEW_NV_parameter_buffer_object2 = _glewSearchExtension("GL_NV_parameter_buffer_object2", extStart, extEnd); #endif /* GL_NV_parameter_buffer_object2 */ #ifdef GL_NV_path_rendering - CONST_CAST(GLEW_NV_path_rendering) = _glewSearchExtension("GL_NV_path_rendering", extStart, extEnd); - if (glewExperimental || GLEW_NV_path_rendering) CONST_CAST(GLEW_NV_path_rendering) = !_glewInit_GL_NV_path_rendering(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_path_rendering = _glewSearchExtension("GL_NV_path_rendering", extStart, extEnd); + if (glewExperimental || GLEW_NV_path_rendering) GLEW_NV_path_rendering = !_glewInit_GL_NV_path_rendering(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_path_rendering */ #ifdef GL_NV_pixel_data_range - CONST_CAST(GLEW_NV_pixel_data_range) = _glewSearchExtension("GL_NV_pixel_data_range", extStart, extEnd); - if (glewExperimental || GLEW_NV_pixel_data_range) CONST_CAST(GLEW_NV_pixel_data_range) = !_glewInit_GL_NV_pixel_data_range(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_pixel_data_range = _glewSearchExtension("GL_NV_pixel_data_range", extStart, extEnd); + if (glewExperimental || GLEW_NV_pixel_data_range) GLEW_NV_pixel_data_range = !_glewInit_GL_NV_pixel_data_range(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_pixel_data_range */ #ifdef GL_NV_point_sprite - CONST_CAST(GLEW_NV_point_sprite) = _glewSearchExtension("GL_NV_point_sprite", extStart, extEnd); - if (glewExperimental || GLEW_NV_point_sprite) CONST_CAST(GLEW_NV_point_sprite) = !_glewInit_GL_NV_point_sprite(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_point_sprite = _glewSearchExtension("GL_NV_point_sprite", extStart, extEnd); + if (glewExperimental || GLEW_NV_point_sprite) GLEW_NV_point_sprite = !_glewInit_GL_NV_point_sprite(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_point_sprite */ #ifdef GL_NV_present_video - CONST_CAST(GLEW_NV_present_video) = _glewSearchExtension("GL_NV_present_video", extStart, extEnd); - if (glewExperimental || GLEW_NV_present_video) CONST_CAST(GLEW_NV_present_video) = !_glewInit_GL_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_present_video = _glewSearchExtension("GL_NV_present_video", extStart, extEnd); + if (glewExperimental || GLEW_NV_present_video) GLEW_NV_present_video = !_glewInit_GL_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_present_video */ #ifdef GL_NV_primitive_restart - CONST_CAST(GLEW_NV_primitive_restart) = _glewSearchExtension("GL_NV_primitive_restart", extStart, extEnd); - if (glewExperimental || GLEW_NV_primitive_restart) CONST_CAST(GLEW_NV_primitive_restart) = !_glewInit_GL_NV_primitive_restart(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_primitive_restart = _glewSearchExtension("GL_NV_primitive_restart", extStart, extEnd); + if (glewExperimental || GLEW_NV_primitive_restart) GLEW_NV_primitive_restart = !_glewInit_GL_NV_primitive_restart(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_primitive_restart */ #ifdef GL_NV_register_combiners - CONST_CAST(GLEW_NV_register_combiners) = _glewSearchExtension("GL_NV_register_combiners", extStart, extEnd); - if (glewExperimental || GLEW_NV_register_combiners) CONST_CAST(GLEW_NV_register_combiners) = !_glewInit_GL_NV_register_combiners(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_register_combiners = _glewSearchExtension("GL_NV_register_combiners", extStart, extEnd); + if (glewExperimental || GLEW_NV_register_combiners) GLEW_NV_register_combiners = !_glewInit_GL_NV_register_combiners(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_register_combiners */ #ifdef GL_NV_register_combiners2 - CONST_CAST(GLEW_NV_register_combiners2) = _glewSearchExtension("GL_NV_register_combiners2", extStart, extEnd); - if (glewExperimental || GLEW_NV_register_combiners2) CONST_CAST(GLEW_NV_register_combiners2) = !_glewInit_GL_NV_register_combiners2(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_register_combiners2 = _glewSearchExtension("GL_NV_register_combiners2", extStart, extEnd); + if (glewExperimental || GLEW_NV_register_combiners2) GLEW_NV_register_combiners2 = !_glewInit_GL_NV_register_combiners2(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_register_combiners2 */ #ifdef GL_NV_shader_atomic_counters - CONST_CAST(GLEW_NV_shader_atomic_counters) = _glewSearchExtension("GL_NV_shader_atomic_counters", extStart, extEnd); + GLEW_NV_shader_atomic_counters = _glewSearchExtension("GL_NV_shader_atomic_counters", extStart, extEnd); #endif /* GL_NV_shader_atomic_counters */ #ifdef GL_NV_shader_atomic_float - CONST_CAST(GLEW_NV_shader_atomic_float) = _glewSearchExtension("GL_NV_shader_atomic_float", extStart, extEnd); + GLEW_NV_shader_atomic_float = _glewSearchExtension("GL_NV_shader_atomic_float", extStart, extEnd); #endif /* GL_NV_shader_atomic_float */ #ifdef GL_NV_shader_buffer_load - CONST_CAST(GLEW_NV_shader_buffer_load) = _glewSearchExtension("GL_NV_shader_buffer_load", extStart, extEnd); - if (glewExperimental || GLEW_NV_shader_buffer_load) CONST_CAST(GLEW_NV_shader_buffer_load) = !_glewInit_GL_NV_shader_buffer_load(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_shader_buffer_load = _glewSearchExtension("GL_NV_shader_buffer_load", extStart, extEnd); + if (glewExperimental || GLEW_NV_shader_buffer_load) GLEW_NV_shader_buffer_load = !_glewInit_GL_NV_shader_buffer_load(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_shader_buffer_load */ #ifdef GL_NV_shader_storage_buffer_object - CONST_CAST(GLEW_NV_shader_storage_buffer_object) = _glewSearchExtension("GL_NV_shader_storage_buffer_object", extStart, extEnd); + GLEW_NV_shader_storage_buffer_object = _glewSearchExtension("GL_NV_shader_storage_buffer_object", extStart, extEnd); #endif /* GL_NV_shader_storage_buffer_object */ +#ifdef GL_NV_shader_thread_group + GLEW_NV_shader_thread_group = _glewSearchExtension("GL_NV_shader_thread_group", extStart, extEnd); +#endif /* GL_NV_shader_thread_group */ +#ifdef GL_NV_shader_thread_shuffle + GLEW_NV_shader_thread_shuffle = _glewSearchExtension("GL_NV_shader_thread_shuffle", extStart, extEnd); +#endif /* GL_NV_shader_thread_shuffle */ #ifdef GL_NV_tessellation_program5 - CONST_CAST(GLEW_NV_tessellation_program5) = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd); + GLEW_NV_tessellation_program5 = _glewSearchExtension("GL_NV_gpu_program5", extStart, extEnd); #endif /* GL_NV_tessellation_program5 */ #ifdef GL_NV_texgen_emboss - CONST_CAST(GLEW_NV_texgen_emboss) = _glewSearchExtension("GL_NV_texgen_emboss", extStart, extEnd); + GLEW_NV_texgen_emboss = _glewSearchExtension("GL_NV_texgen_emboss", extStart, extEnd); #endif /* GL_NV_texgen_emboss */ #ifdef GL_NV_texgen_reflection - CONST_CAST(GLEW_NV_texgen_reflection) = _glewSearchExtension("GL_NV_texgen_reflection", extStart, extEnd); + GLEW_NV_texgen_reflection = _glewSearchExtension("GL_NV_texgen_reflection", extStart, extEnd); #endif /* GL_NV_texgen_reflection */ #ifdef GL_NV_texture_barrier - CONST_CAST(GLEW_NV_texture_barrier) = _glewSearchExtension("GL_NV_texture_barrier", extStart, extEnd); - if (glewExperimental || GLEW_NV_texture_barrier) CONST_CAST(GLEW_NV_texture_barrier) = !_glewInit_GL_NV_texture_barrier(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_texture_barrier = _glewSearchExtension("GL_NV_texture_barrier", extStart, extEnd); + if (glewExperimental || GLEW_NV_texture_barrier) GLEW_NV_texture_barrier = !_glewInit_GL_NV_texture_barrier(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_texture_barrier */ #ifdef GL_NV_texture_compression_vtc - CONST_CAST(GLEW_NV_texture_compression_vtc) = _glewSearchExtension("GL_NV_texture_compression_vtc", extStart, extEnd); + GLEW_NV_texture_compression_vtc = _glewSearchExtension("GL_NV_texture_compression_vtc", extStart, extEnd); #endif /* GL_NV_texture_compression_vtc */ #ifdef GL_NV_texture_env_combine4 - CONST_CAST(GLEW_NV_texture_env_combine4) = _glewSearchExtension("GL_NV_texture_env_combine4", extStart, extEnd); + GLEW_NV_texture_env_combine4 = _glewSearchExtension("GL_NV_texture_env_combine4", extStart, extEnd); #endif /* GL_NV_texture_env_combine4 */ #ifdef GL_NV_texture_expand_normal - CONST_CAST(GLEW_NV_texture_expand_normal) = _glewSearchExtension("GL_NV_texture_expand_normal", extStart, extEnd); + GLEW_NV_texture_expand_normal = _glewSearchExtension("GL_NV_texture_expand_normal", extStart, extEnd); #endif /* GL_NV_texture_expand_normal */ #ifdef GL_NV_texture_multisample - CONST_CAST(GLEW_NV_texture_multisample) = _glewSearchExtension("GL_NV_texture_multisample", extStart, extEnd); - if (glewExperimental || GLEW_NV_texture_multisample) CONST_CAST(GLEW_NV_texture_multisample) = !_glewInit_GL_NV_texture_multisample(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_texture_multisample = _glewSearchExtension("GL_NV_texture_multisample", extStart, extEnd); + if (glewExperimental || GLEW_NV_texture_multisample) GLEW_NV_texture_multisample = !_glewInit_GL_NV_texture_multisample(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_texture_multisample */ #ifdef GL_NV_texture_rectangle - CONST_CAST(GLEW_NV_texture_rectangle) = _glewSearchExtension("GL_NV_texture_rectangle", extStart, extEnd); + GLEW_NV_texture_rectangle = _glewSearchExtension("GL_NV_texture_rectangle", extStart, extEnd); #endif /* GL_NV_texture_rectangle */ #ifdef GL_NV_texture_shader - CONST_CAST(GLEW_NV_texture_shader) = _glewSearchExtension("GL_NV_texture_shader", extStart, extEnd); + GLEW_NV_texture_shader = _glewSearchExtension("GL_NV_texture_shader", extStart, extEnd); #endif /* GL_NV_texture_shader */ #ifdef GL_NV_texture_shader2 - CONST_CAST(GLEW_NV_texture_shader2) = _glewSearchExtension("GL_NV_texture_shader2", extStart, extEnd); + GLEW_NV_texture_shader2 = _glewSearchExtension("GL_NV_texture_shader2", extStart, extEnd); #endif /* GL_NV_texture_shader2 */ #ifdef GL_NV_texture_shader3 - CONST_CAST(GLEW_NV_texture_shader3) = _glewSearchExtension("GL_NV_texture_shader3", extStart, extEnd); + GLEW_NV_texture_shader3 = _glewSearchExtension("GL_NV_texture_shader3", extStart, extEnd); #endif /* GL_NV_texture_shader3 */ #ifdef GL_NV_transform_feedback - CONST_CAST(GLEW_NV_transform_feedback) = _glewSearchExtension("GL_NV_transform_feedback", extStart, extEnd); - if (glewExperimental || GLEW_NV_transform_feedback) CONST_CAST(GLEW_NV_transform_feedback) = !_glewInit_GL_NV_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_transform_feedback = _glewSearchExtension("GL_NV_transform_feedback", extStart, extEnd); + if (glewExperimental || GLEW_NV_transform_feedback) GLEW_NV_transform_feedback = !_glewInit_GL_NV_transform_feedback(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_transform_feedback */ #ifdef GL_NV_transform_feedback2 - CONST_CAST(GLEW_NV_transform_feedback2) = _glewSearchExtension("GL_NV_transform_feedback2", extStart, extEnd); - if (glewExperimental || GLEW_NV_transform_feedback2) CONST_CAST(GLEW_NV_transform_feedback2) = !_glewInit_GL_NV_transform_feedback2(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_transform_feedback2 = _glewSearchExtension("GL_NV_transform_feedback2", extStart, extEnd); + if (glewExperimental || GLEW_NV_transform_feedback2) GLEW_NV_transform_feedback2 = !_glewInit_GL_NV_transform_feedback2(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_transform_feedback2 */ #ifdef GL_NV_vdpau_interop - CONST_CAST(GLEW_NV_vdpau_interop) = _glewSearchExtension("GL_NV_vdpau_interop", extStart, extEnd); - if (glewExperimental || GLEW_NV_vdpau_interop) CONST_CAST(GLEW_NV_vdpau_interop) = !_glewInit_GL_NV_vdpau_interop(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_vdpau_interop = _glewSearchExtension("GL_NV_vdpau_interop", extStart, extEnd); + if (glewExperimental || GLEW_NV_vdpau_interop) GLEW_NV_vdpau_interop = !_glewInit_GL_NV_vdpau_interop(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_vdpau_interop */ #ifdef GL_NV_vertex_array_range - CONST_CAST(GLEW_NV_vertex_array_range) = _glewSearchExtension("GL_NV_vertex_array_range", extStart, extEnd); - if (glewExperimental || GLEW_NV_vertex_array_range) CONST_CAST(GLEW_NV_vertex_array_range) = !_glewInit_GL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_vertex_array_range = _glewSearchExtension("GL_NV_vertex_array_range", extStart, extEnd); + if (glewExperimental || GLEW_NV_vertex_array_range) GLEW_NV_vertex_array_range = !_glewInit_GL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_vertex_array_range */ #ifdef GL_NV_vertex_array_range2 - CONST_CAST(GLEW_NV_vertex_array_range2) = _glewSearchExtension("GL_NV_vertex_array_range2", extStart, extEnd); + GLEW_NV_vertex_array_range2 = _glewSearchExtension("GL_NV_vertex_array_range2", extStart, extEnd); #endif /* GL_NV_vertex_array_range2 */ #ifdef GL_NV_vertex_attrib_integer_64bit - CONST_CAST(GLEW_NV_vertex_attrib_integer_64bit) = _glewSearchExtension("GL_NV_vertex_attrib_integer_64bit", extStart, extEnd); - if (glewExperimental || GLEW_NV_vertex_attrib_integer_64bit) CONST_CAST(GLEW_NV_vertex_attrib_integer_64bit) = !_glewInit_GL_NV_vertex_attrib_integer_64bit(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_vertex_attrib_integer_64bit = _glewSearchExtension("GL_NV_vertex_attrib_integer_64bit", extStart, extEnd); + if (glewExperimental || GLEW_NV_vertex_attrib_integer_64bit) GLEW_NV_vertex_attrib_integer_64bit = !_glewInit_GL_NV_vertex_attrib_integer_64bit(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_vertex_attrib_integer_64bit */ #ifdef GL_NV_vertex_buffer_unified_memory - CONST_CAST(GLEW_NV_vertex_buffer_unified_memory) = _glewSearchExtension("GL_NV_vertex_buffer_unified_memory", extStart, extEnd); - if (glewExperimental || GLEW_NV_vertex_buffer_unified_memory) CONST_CAST(GLEW_NV_vertex_buffer_unified_memory) = !_glewInit_GL_NV_vertex_buffer_unified_memory(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_vertex_buffer_unified_memory = _glewSearchExtension("GL_NV_vertex_buffer_unified_memory", extStart, extEnd); + if (glewExperimental || GLEW_NV_vertex_buffer_unified_memory) GLEW_NV_vertex_buffer_unified_memory = !_glewInit_GL_NV_vertex_buffer_unified_memory(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_vertex_buffer_unified_memory */ #ifdef GL_NV_vertex_program - CONST_CAST(GLEW_NV_vertex_program) = _glewSearchExtension("GL_NV_vertex_program", extStart, extEnd); - if (glewExperimental || GLEW_NV_vertex_program) CONST_CAST(GLEW_NV_vertex_program) = !_glewInit_GL_NV_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_vertex_program = _glewSearchExtension("GL_NV_vertex_program", extStart, extEnd); + if (glewExperimental || GLEW_NV_vertex_program) GLEW_NV_vertex_program = !_glewInit_GL_NV_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_vertex_program */ #ifdef GL_NV_vertex_program1_1 - CONST_CAST(GLEW_NV_vertex_program1_1) = _glewSearchExtension("GL_NV_vertex_program1_1", extStart, extEnd); + GLEW_NV_vertex_program1_1 = _glewSearchExtension("GL_NV_vertex_program1_1", extStart, extEnd); #endif /* GL_NV_vertex_program1_1 */ #ifdef GL_NV_vertex_program2 - CONST_CAST(GLEW_NV_vertex_program2) = _glewSearchExtension("GL_NV_vertex_program2", extStart, extEnd); + GLEW_NV_vertex_program2 = _glewSearchExtension("GL_NV_vertex_program2", extStart, extEnd); #endif /* GL_NV_vertex_program2 */ #ifdef GL_NV_vertex_program2_option - CONST_CAST(GLEW_NV_vertex_program2_option) = _glewSearchExtension("GL_NV_vertex_program2_option", extStart, extEnd); + GLEW_NV_vertex_program2_option = _glewSearchExtension("GL_NV_vertex_program2_option", extStart, extEnd); #endif /* GL_NV_vertex_program2_option */ #ifdef GL_NV_vertex_program3 - CONST_CAST(GLEW_NV_vertex_program3) = _glewSearchExtension("GL_NV_vertex_program3", extStart, extEnd); + GLEW_NV_vertex_program3 = _glewSearchExtension("GL_NV_vertex_program3", extStart, extEnd); #endif /* GL_NV_vertex_program3 */ #ifdef GL_NV_vertex_program4 - CONST_CAST(GLEW_NV_vertex_program4) = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); + GLEW_NV_vertex_program4 = _glewSearchExtension("GL_NV_gpu_program4", extStart, extEnd); #endif /* GL_NV_vertex_program4 */ #ifdef GL_NV_video_capture - CONST_CAST(GLEW_NV_video_capture) = _glewSearchExtension("GL_NV_video_capture", extStart, extEnd); - if (glewExperimental || GLEW_NV_video_capture) CONST_CAST(GLEW_NV_video_capture) = !_glewInit_GL_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_NV_video_capture = _glewSearchExtension("GL_NV_video_capture", extStart, extEnd); + if (glewExperimental || GLEW_NV_video_capture) GLEW_NV_video_capture = !_glewInit_GL_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_NV_video_capture */ #ifdef GL_OES_byte_coordinates - CONST_CAST(GLEW_OES_byte_coordinates) = _glewSearchExtension("GL_OES_byte_coordinates", extStart, extEnd); + GLEW_OES_byte_coordinates = _glewSearchExtension("GL_OES_byte_coordinates", extStart, extEnd); #endif /* GL_OES_byte_coordinates */ #ifdef GL_OES_compressed_paletted_texture - CONST_CAST(GLEW_OES_compressed_paletted_texture) = _glewSearchExtension("GL_OES_compressed_paletted_texture", extStart, extEnd); + GLEW_OES_compressed_paletted_texture = _glewSearchExtension("GL_OES_compressed_paletted_texture", extStart, extEnd); #endif /* GL_OES_compressed_paletted_texture */ #ifdef GL_OES_read_format - CONST_CAST(GLEW_OES_read_format) = _glewSearchExtension("GL_OES_read_format", extStart, extEnd); + GLEW_OES_read_format = _glewSearchExtension("GL_OES_read_format", extStart, extEnd); #endif /* GL_OES_read_format */ #ifdef GL_OES_single_precision - CONST_CAST(GLEW_OES_single_precision) = _glewSearchExtension("GL_OES_single_precision", extStart, extEnd); - if (glewExperimental || GLEW_OES_single_precision) CONST_CAST(GLEW_OES_single_precision) = !_glewInit_GL_OES_single_precision(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_OES_single_precision = _glewSearchExtension("GL_OES_single_precision", extStart, extEnd); + if (glewExperimental || GLEW_OES_single_precision) GLEW_OES_single_precision = !_glewInit_GL_OES_single_precision(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_OES_single_precision */ #ifdef GL_OML_interlace - CONST_CAST(GLEW_OML_interlace) = _glewSearchExtension("GL_OML_interlace", extStart, extEnd); + GLEW_OML_interlace = _glewSearchExtension("GL_OML_interlace", extStart, extEnd); #endif /* GL_OML_interlace */ #ifdef GL_OML_resample - CONST_CAST(GLEW_OML_resample) = _glewSearchExtension("GL_OML_resample", extStart, extEnd); + GLEW_OML_resample = _glewSearchExtension("GL_OML_resample", extStart, extEnd); #endif /* GL_OML_resample */ #ifdef GL_OML_subsample - CONST_CAST(GLEW_OML_subsample) = _glewSearchExtension("GL_OML_subsample", extStart, extEnd); + GLEW_OML_subsample = _glewSearchExtension("GL_OML_subsample", extStart, extEnd); #endif /* GL_OML_subsample */ #ifdef GL_PGI_misc_hints - CONST_CAST(GLEW_PGI_misc_hints) = _glewSearchExtension("GL_PGI_misc_hints", extStart, extEnd); + GLEW_PGI_misc_hints = _glewSearchExtension("GL_PGI_misc_hints", extStart, extEnd); #endif /* GL_PGI_misc_hints */ #ifdef GL_PGI_vertex_hints - CONST_CAST(GLEW_PGI_vertex_hints) = _glewSearchExtension("GL_PGI_vertex_hints", extStart, extEnd); + GLEW_PGI_vertex_hints = _glewSearchExtension("GL_PGI_vertex_hints", extStart, extEnd); #endif /* GL_PGI_vertex_hints */ #ifdef GL_REGAL_ES1_0_compatibility - CONST_CAST(GLEW_REGAL_ES1_0_compatibility) = _glewSearchExtension("GL_REGAL_ES1_0_compatibility", extStart, extEnd); - if (glewExperimental || GLEW_REGAL_ES1_0_compatibility) CONST_CAST(GLEW_REGAL_ES1_0_compatibility) = !_glewInit_GL_REGAL_ES1_0_compatibility(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_REGAL_ES1_0_compatibility = _glewSearchExtension("GL_REGAL_ES1_0_compatibility", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_ES1_0_compatibility) GLEW_REGAL_ES1_0_compatibility = !_glewInit_GL_REGAL_ES1_0_compatibility(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_REGAL_ES1_0_compatibility */ #ifdef GL_REGAL_ES1_1_compatibility - CONST_CAST(GLEW_REGAL_ES1_1_compatibility) = _glewSearchExtension("GL_REGAL_ES1_1_compatibility", extStart, extEnd); - if (glewExperimental || GLEW_REGAL_ES1_1_compatibility) CONST_CAST(GLEW_REGAL_ES1_1_compatibility) = !_glewInit_GL_REGAL_ES1_1_compatibility(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_REGAL_ES1_1_compatibility = _glewSearchExtension("GL_REGAL_ES1_1_compatibility", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_ES1_1_compatibility) GLEW_REGAL_ES1_1_compatibility = !_glewInit_GL_REGAL_ES1_1_compatibility(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_REGAL_ES1_1_compatibility */ #ifdef GL_REGAL_enable - CONST_CAST(GLEW_REGAL_enable) = _glewSearchExtension("GL_REGAL_enable", extStart, extEnd); + GLEW_REGAL_enable = _glewSearchExtension("GL_REGAL_enable", extStart, extEnd); #endif /* GL_REGAL_enable */ #ifdef GL_REGAL_error_string - CONST_CAST(GLEW_REGAL_error_string) = _glewSearchExtension("GL_REGAL_error_string", extStart, extEnd); - if (glewExperimental || GLEW_REGAL_error_string) CONST_CAST(GLEW_REGAL_error_string) = !_glewInit_GL_REGAL_error_string(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_REGAL_error_string = _glewSearchExtension("GL_REGAL_error_string", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_error_string) GLEW_REGAL_error_string = !_glewInit_GL_REGAL_error_string(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_REGAL_error_string */ #ifdef GL_REGAL_extension_query - CONST_CAST(GLEW_REGAL_extension_query) = _glewSearchExtension("GL_REGAL_extension_query", extStart, extEnd); - if (glewExperimental || GLEW_REGAL_extension_query) CONST_CAST(GLEW_REGAL_extension_query) = !_glewInit_GL_REGAL_extension_query(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_REGAL_extension_query = _glewSearchExtension("GL_REGAL_extension_query", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_extension_query) GLEW_REGAL_extension_query = !_glewInit_GL_REGAL_extension_query(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_REGAL_extension_query */ #ifdef GL_REGAL_log - CONST_CAST(GLEW_REGAL_log) = _glewSearchExtension("GL_REGAL_log", extStart, extEnd); - if (glewExperimental || GLEW_REGAL_log) CONST_CAST(GLEW_REGAL_log) = !_glewInit_GL_REGAL_log(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_REGAL_log = _glewSearchExtension("GL_REGAL_log", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_log) GLEW_REGAL_log = !_glewInit_GL_REGAL_log(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_REGAL_log */ +#ifdef GL_REGAL_proc_address + GLEW_REGAL_proc_address = _glewSearchExtension("GL_REGAL_proc_address", extStart, extEnd); + if (glewExperimental || GLEW_REGAL_proc_address) GLEW_REGAL_proc_address = !_glewInit_GL_REGAL_proc_address(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GL_REGAL_proc_address */ #ifdef GL_REND_screen_coordinates - CONST_CAST(GLEW_REND_screen_coordinates) = _glewSearchExtension("GL_REND_screen_coordinates", extStart, extEnd); + GLEW_REND_screen_coordinates = _glewSearchExtension("GL_REND_screen_coordinates", extStart, extEnd); #endif /* GL_REND_screen_coordinates */ #ifdef GL_S3_s3tc - CONST_CAST(GLEW_S3_s3tc) = _glewSearchExtension("GL_S3_s3tc", extStart, extEnd); + GLEW_S3_s3tc = _glewSearchExtension("GL_S3_s3tc", extStart, extEnd); #endif /* GL_S3_s3tc */ #ifdef GL_SGIS_color_range - CONST_CAST(GLEW_SGIS_color_range) = _glewSearchExtension("GL_SGIS_color_range", extStart, extEnd); + GLEW_SGIS_color_range = _glewSearchExtension("GL_SGIS_color_range", extStart, extEnd); #endif /* GL_SGIS_color_range */ #ifdef GL_SGIS_detail_texture - CONST_CAST(GLEW_SGIS_detail_texture) = _glewSearchExtension("GL_SGIS_detail_texture", extStart, extEnd); - if (glewExperimental || GLEW_SGIS_detail_texture) CONST_CAST(GLEW_SGIS_detail_texture) = !_glewInit_GL_SGIS_detail_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIS_detail_texture = _glewSearchExtension("GL_SGIS_detail_texture", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_detail_texture) GLEW_SGIS_detail_texture = !_glewInit_GL_SGIS_detail_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIS_detail_texture */ #ifdef GL_SGIS_fog_function - CONST_CAST(GLEW_SGIS_fog_function) = _glewSearchExtension("GL_SGIS_fog_function", extStart, extEnd); - if (glewExperimental || GLEW_SGIS_fog_function) CONST_CAST(GLEW_SGIS_fog_function) = !_glewInit_GL_SGIS_fog_function(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIS_fog_function = _glewSearchExtension("GL_SGIS_fog_function", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_fog_function) GLEW_SGIS_fog_function = !_glewInit_GL_SGIS_fog_function(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIS_fog_function */ #ifdef GL_SGIS_generate_mipmap - CONST_CAST(GLEW_SGIS_generate_mipmap) = _glewSearchExtension("GL_SGIS_generate_mipmap", extStart, extEnd); + GLEW_SGIS_generate_mipmap = _glewSearchExtension("GL_SGIS_generate_mipmap", extStart, extEnd); #endif /* GL_SGIS_generate_mipmap */ #ifdef GL_SGIS_multisample - CONST_CAST(GLEW_SGIS_multisample) = _glewSearchExtension("GL_SGIS_multisample", extStart, extEnd); - if (glewExperimental || GLEW_SGIS_multisample) CONST_CAST(GLEW_SGIS_multisample) = !_glewInit_GL_SGIS_multisample(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIS_multisample = _glewSearchExtension("GL_SGIS_multisample", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_multisample) GLEW_SGIS_multisample = !_glewInit_GL_SGIS_multisample(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIS_multisample */ #ifdef GL_SGIS_pixel_texture - CONST_CAST(GLEW_SGIS_pixel_texture) = _glewSearchExtension("GL_SGIS_pixel_texture", extStart, extEnd); + GLEW_SGIS_pixel_texture = _glewSearchExtension("GL_SGIS_pixel_texture", extStart, extEnd); #endif /* GL_SGIS_pixel_texture */ #ifdef GL_SGIS_point_line_texgen - CONST_CAST(GLEW_SGIS_point_line_texgen) = _glewSearchExtension("GL_SGIS_point_line_texgen", extStart, extEnd); + GLEW_SGIS_point_line_texgen = _glewSearchExtension("GL_SGIS_point_line_texgen", extStart, extEnd); #endif /* GL_SGIS_point_line_texgen */ #ifdef GL_SGIS_sharpen_texture - CONST_CAST(GLEW_SGIS_sharpen_texture) = _glewSearchExtension("GL_SGIS_sharpen_texture", extStart, extEnd); - if (glewExperimental || GLEW_SGIS_sharpen_texture) CONST_CAST(GLEW_SGIS_sharpen_texture) = !_glewInit_GL_SGIS_sharpen_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIS_sharpen_texture = _glewSearchExtension("GL_SGIS_sharpen_texture", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_sharpen_texture) GLEW_SGIS_sharpen_texture = !_glewInit_GL_SGIS_sharpen_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIS_sharpen_texture */ #ifdef GL_SGIS_texture4D - CONST_CAST(GLEW_SGIS_texture4D) = _glewSearchExtension("GL_SGIS_texture4D", extStart, extEnd); - if (glewExperimental || GLEW_SGIS_texture4D) CONST_CAST(GLEW_SGIS_texture4D) = !_glewInit_GL_SGIS_texture4D(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIS_texture4D = _glewSearchExtension("GL_SGIS_texture4D", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_texture4D) GLEW_SGIS_texture4D = !_glewInit_GL_SGIS_texture4D(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIS_texture4D */ #ifdef GL_SGIS_texture_border_clamp - CONST_CAST(GLEW_SGIS_texture_border_clamp) = _glewSearchExtension("GL_SGIS_texture_border_clamp", extStart, extEnd); + GLEW_SGIS_texture_border_clamp = _glewSearchExtension("GL_SGIS_texture_border_clamp", extStart, extEnd); #endif /* GL_SGIS_texture_border_clamp */ #ifdef GL_SGIS_texture_edge_clamp - CONST_CAST(GLEW_SGIS_texture_edge_clamp) = _glewSearchExtension("GL_SGIS_texture_edge_clamp", extStart, extEnd); + GLEW_SGIS_texture_edge_clamp = _glewSearchExtension("GL_SGIS_texture_edge_clamp", extStart, extEnd); #endif /* GL_SGIS_texture_edge_clamp */ #ifdef GL_SGIS_texture_filter4 - CONST_CAST(GLEW_SGIS_texture_filter4) = _glewSearchExtension("GL_SGIS_texture_filter4", extStart, extEnd); - if (glewExperimental || GLEW_SGIS_texture_filter4) CONST_CAST(GLEW_SGIS_texture_filter4) = !_glewInit_GL_SGIS_texture_filter4(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIS_texture_filter4 = _glewSearchExtension("GL_SGIS_texture_filter4", extStart, extEnd); + if (glewExperimental || GLEW_SGIS_texture_filter4) GLEW_SGIS_texture_filter4 = !_glewInit_GL_SGIS_texture_filter4(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIS_texture_filter4 */ #ifdef GL_SGIS_texture_lod - CONST_CAST(GLEW_SGIS_texture_lod) = _glewSearchExtension("GL_SGIS_texture_lod", extStart, extEnd); + GLEW_SGIS_texture_lod = _glewSearchExtension("GL_SGIS_texture_lod", extStart, extEnd); #endif /* GL_SGIS_texture_lod */ #ifdef GL_SGIS_texture_select - CONST_CAST(GLEW_SGIS_texture_select) = _glewSearchExtension("GL_SGIS_texture_select", extStart, extEnd); + GLEW_SGIS_texture_select = _glewSearchExtension("GL_SGIS_texture_select", extStart, extEnd); #endif /* GL_SGIS_texture_select */ #ifdef GL_SGIX_async - CONST_CAST(GLEW_SGIX_async) = _glewSearchExtension("GL_SGIX_async", extStart, extEnd); - if (glewExperimental || GLEW_SGIX_async) CONST_CAST(GLEW_SGIX_async) = !_glewInit_GL_SGIX_async(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIX_async = _glewSearchExtension("GL_SGIX_async", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_async) GLEW_SGIX_async = !_glewInit_GL_SGIX_async(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIX_async */ #ifdef GL_SGIX_async_histogram - CONST_CAST(GLEW_SGIX_async_histogram) = _glewSearchExtension("GL_SGIX_async_histogram", extStart, extEnd); + GLEW_SGIX_async_histogram = _glewSearchExtension("GL_SGIX_async_histogram", extStart, extEnd); #endif /* GL_SGIX_async_histogram */ #ifdef GL_SGIX_async_pixel - CONST_CAST(GLEW_SGIX_async_pixel) = _glewSearchExtension("GL_SGIX_async_pixel", extStart, extEnd); + GLEW_SGIX_async_pixel = _glewSearchExtension("GL_SGIX_async_pixel", extStart, extEnd); #endif /* GL_SGIX_async_pixel */ #ifdef GL_SGIX_blend_alpha_minmax - CONST_CAST(GLEW_SGIX_blend_alpha_minmax) = _glewSearchExtension("GL_SGIX_blend_alpha_minmax", extStart, extEnd); + GLEW_SGIX_blend_alpha_minmax = _glewSearchExtension("GL_SGIX_blend_alpha_minmax", extStart, extEnd); #endif /* GL_SGIX_blend_alpha_minmax */ #ifdef GL_SGIX_clipmap - CONST_CAST(GLEW_SGIX_clipmap) = _glewSearchExtension("GL_SGIX_clipmap", extStart, extEnd); + GLEW_SGIX_clipmap = _glewSearchExtension("GL_SGIX_clipmap", extStart, extEnd); #endif /* GL_SGIX_clipmap */ #ifdef GL_SGIX_convolution_accuracy - CONST_CAST(GLEW_SGIX_convolution_accuracy) = _glewSearchExtension("GL_SGIX_convolution_accuracy", extStart, extEnd); + GLEW_SGIX_convolution_accuracy = _glewSearchExtension("GL_SGIX_convolution_accuracy", extStart, extEnd); #endif /* GL_SGIX_convolution_accuracy */ #ifdef GL_SGIX_depth_texture - CONST_CAST(GLEW_SGIX_depth_texture) = _glewSearchExtension("GL_SGIX_depth_texture", extStart, extEnd); + GLEW_SGIX_depth_texture = _glewSearchExtension("GL_SGIX_depth_texture", extStart, extEnd); #endif /* GL_SGIX_depth_texture */ #ifdef GL_SGIX_flush_raster - CONST_CAST(GLEW_SGIX_flush_raster) = _glewSearchExtension("GL_SGIX_flush_raster", extStart, extEnd); - if (glewExperimental || GLEW_SGIX_flush_raster) CONST_CAST(GLEW_SGIX_flush_raster) = !_glewInit_GL_SGIX_flush_raster(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIX_flush_raster = _glewSearchExtension("GL_SGIX_flush_raster", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_flush_raster) GLEW_SGIX_flush_raster = !_glewInit_GL_SGIX_flush_raster(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIX_flush_raster */ #ifdef GL_SGIX_fog_offset - CONST_CAST(GLEW_SGIX_fog_offset) = _glewSearchExtension("GL_SGIX_fog_offset", extStart, extEnd); + GLEW_SGIX_fog_offset = _glewSearchExtension("GL_SGIX_fog_offset", extStart, extEnd); #endif /* GL_SGIX_fog_offset */ #ifdef GL_SGIX_fog_texture - CONST_CAST(GLEW_SGIX_fog_texture) = _glewSearchExtension("GL_SGIX_fog_texture", extStart, extEnd); - if (glewExperimental || GLEW_SGIX_fog_texture) CONST_CAST(GLEW_SGIX_fog_texture) = !_glewInit_GL_SGIX_fog_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIX_fog_texture = _glewSearchExtension("GL_SGIX_fog_texture", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_fog_texture) GLEW_SGIX_fog_texture = !_glewInit_GL_SGIX_fog_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIX_fog_texture */ #ifdef GL_SGIX_fragment_specular_lighting - CONST_CAST(GLEW_SGIX_fragment_specular_lighting) = _glewSearchExtension("GL_SGIX_fragment_specular_lighting", extStart, extEnd); - if (glewExperimental || GLEW_SGIX_fragment_specular_lighting) CONST_CAST(GLEW_SGIX_fragment_specular_lighting) = !_glewInit_GL_SGIX_fragment_specular_lighting(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIX_fragment_specular_lighting = _glewSearchExtension("GL_SGIX_fragment_specular_lighting", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_fragment_specular_lighting) GLEW_SGIX_fragment_specular_lighting = !_glewInit_GL_SGIX_fragment_specular_lighting(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIX_fragment_specular_lighting */ #ifdef GL_SGIX_framezoom - CONST_CAST(GLEW_SGIX_framezoom) = _glewSearchExtension("GL_SGIX_framezoom", extStart, extEnd); - if (glewExperimental || GLEW_SGIX_framezoom) CONST_CAST(GLEW_SGIX_framezoom) = !_glewInit_GL_SGIX_framezoom(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIX_framezoom = _glewSearchExtension("GL_SGIX_framezoom", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_framezoom) GLEW_SGIX_framezoom = !_glewInit_GL_SGIX_framezoom(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIX_framezoom */ #ifdef GL_SGIX_interlace - CONST_CAST(GLEW_SGIX_interlace) = _glewSearchExtension("GL_SGIX_interlace", extStart, extEnd); + GLEW_SGIX_interlace = _glewSearchExtension("GL_SGIX_interlace", extStart, extEnd); #endif /* GL_SGIX_interlace */ #ifdef GL_SGIX_ir_instrument1 - CONST_CAST(GLEW_SGIX_ir_instrument1) = _glewSearchExtension("GL_SGIX_ir_instrument1", extStart, extEnd); + GLEW_SGIX_ir_instrument1 = _glewSearchExtension("GL_SGIX_ir_instrument1", extStart, extEnd); #endif /* GL_SGIX_ir_instrument1 */ #ifdef GL_SGIX_list_priority - CONST_CAST(GLEW_SGIX_list_priority) = _glewSearchExtension("GL_SGIX_list_priority", extStart, extEnd); + GLEW_SGIX_list_priority = _glewSearchExtension("GL_SGIX_list_priority", extStart, extEnd); #endif /* GL_SGIX_list_priority */ #ifdef GL_SGIX_pixel_texture - CONST_CAST(GLEW_SGIX_pixel_texture) = _glewSearchExtension("GL_SGIX_pixel_texture", extStart, extEnd); - if (glewExperimental || GLEW_SGIX_pixel_texture) CONST_CAST(GLEW_SGIX_pixel_texture) = !_glewInit_GL_SGIX_pixel_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIX_pixel_texture = _glewSearchExtension("GL_SGIX_pixel_texture", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_pixel_texture) GLEW_SGIX_pixel_texture = !_glewInit_GL_SGIX_pixel_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIX_pixel_texture */ #ifdef GL_SGIX_pixel_texture_bits - CONST_CAST(GLEW_SGIX_pixel_texture_bits) = _glewSearchExtension("GL_SGIX_pixel_texture_bits", extStart, extEnd); + GLEW_SGIX_pixel_texture_bits = _glewSearchExtension("GL_SGIX_pixel_texture_bits", extStart, extEnd); #endif /* GL_SGIX_pixel_texture_bits */ #ifdef GL_SGIX_reference_plane - CONST_CAST(GLEW_SGIX_reference_plane) = _glewSearchExtension("GL_SGIX_reference_plane", extStart, extEnd); - if (glewExperimental || GLEW_SGIX_reference_plane) CONST_CAST(GLEW_SGIX_reference_plane) = !_glewInit_GL_SGIX_reference_plane(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIX_reference_plane = _glewSearchExtension("GL_SGIX_reference_plane", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_reference_plane) GLEW_SGIX_reference_plane = !_glewInit_GL_SGIX_reference_plane(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIX_reference_plane */ #ifdef GL_SGIX_resample - CONST_CAST(GLEW_SGIX_resample) = _glewSearchExtension("GL_SGIX_resample", extStart, extEnd); + GLEW_SGIX_resample = _glewSearchExtension("GL_SGIX_resample", extStart, extEnd); #endif /* GL_SGIX_resample */ #ifdef GL_SGIX_shadow - CONST_CAST(GLEW_SGIX_shadow) = _glewSearchExtension("GL_SGIX_shadow", extStart, extEnd); + GLEW_SGIX_shadow = _glewSearchExtension("GL_SGIX_shadow", extStart, extEnd); #endif /* GL_SGIX_shadow */ #ifdef GL_SGIX_shadow_ambient - CONST_CAST(GLEW_SGIX_shadow_ambient) = _glewSearchExtension("GL_SGIX_shadow_ambient", extStart, extEnd); + GLEW_SGIX_shadow_ambient = _glewSearchExtension("GL_SGIX_shadow_ambient", extStart, extEnd); #endif /* GL_SGIX_shadow_ambient */ #ifdef GL_SGIX_sprite - CONST_CAST(GLEW_SGIX_sprite) = _glewSearchExtension("GL_SGIX_sprite", extStart, extEnd); - if (glewExperimental || GLEW_SGIX_sprite) CONST_CAST(GLEW_SGIX_sprite) = !_glewInit_GL_SGIX_sprite(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIX_sprite = _glewSearchExtension("GL_SGIX_sprite", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_sprite) GLEW_SGIX_sprite = !_glewInit_GL_SGIX_sprite(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIX_sprite */ #ifdef GL_SGIX_tag_sample_buffer - CONST_CAST(GLEW_SGIX_tag_sample_buffer) = _glewSearchExtension("GL_SGIX_tag_sample_buffer", extStart, extEnd); - if (glewExperimental || GLEW_SGIX_tag_sample_buffer) CONST_CAST(GLEW_SGIX_tag_sample_buffer) = !_glewInit_GL_SGIX_tag_sample_buffer(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGIX_tag_sample_buffer = _glewSearchExtension("GL_SGIX_tag_sample_buffer", extStart, extEnd); + if (glewExperimental || GLEW_SGIX_tag_sample_buffer) GLEW_SGIX_tag_sample_buffer = !_glewInit_GL_SGIX_tag_sample_buffer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGIX_tag_sample_buffer */ #ifdef GL_SGIX_texture_add_env - CONST_CAST(GLEW_SGIX_texture_add_env) = _glewSearchExtension("GL_SGIX_texture_add_env", extStart, extEnd); + GLEW_SGIX_texture_add_env = _glewSearchExtension("GL_SGIX_texture_add_env", extStart, extEnd); #endif /* GL_SGIX_texture_add_env */ #ifdef GL_SGIX_texture_coordinate_clamp - CONST_CAST(GLEW_SGIX_texture_coordinate_clamp) = _glewSearchExtension("GL_SGIX_texture_coordinate_clamp", extStart, extEnd); + GLEW_SGIX_texture_coordinate_clamp = _glewSearchExtension("GL_SGIX_texture_coordinate_clamp", extStart, extEnd); #endif /* GL_SGIX_texture_coordinate_clamp */ #ifdef GL_SGIX_texture_lod_bias - CONST_CAST(GLEW_SGIX_texture_lod_bias) = _glewSearchExtension("GL_SGIX_texture_lod_bias", extStart, extEnd); + GLEW_SGIX_texture_lod_bias = _glewSearchExtension("GL_SGIX_texture_lod_bias", extStart, extEnd); #endif /* GL_SGIX_texture_lod_bias */ #ifdef GL_SGIX_texture_multi_buffer - CONST_CAST(GLEW_SGIX_texture_multi_buffer) = _glewSearchExtension("GL_SGIX_texture_multi_buffer", extStart, extEnd); + GLEW_SGIX_texture_multi_buffer = _glewSearchExtension("GL_SGIX_texture_multi_buffer", extStart, extEnd); #endif /* GL_SGIX_texture_multi_buffer */ #ifdef GL_SGIX_texture_range - CONST_CAST(GLEW_SGIX_texture_range) = _glewSearchExtension("GL_SGIX_texture_range", extStart, extEnd); + GLEW_SGIX_texture_range = _glewSearchExtension("GL_SGIX_texture_range", extStart, extEnd); #endif /* GL_SGIX_texture_range */ #ifdef GL_SGIX_texture_scale_bias - CONST_CAST(GLEW_SGIX_texture_scale_bias) = _glewSearchExtension("GL_SGIX_texture_scale_bias", extStart, extEnd); + GLEW_SGIX_texture_scale_bias = _glewSearchExtension("GL_SGIX_texture_scale_bias", extStart, extEnd); #endif /* GL_SGIX_texture_scale_bias */ #ifdef GL_SGIX_vertex_preclip - CONST_CAST(GLEW_SGIX_vertex_preclip) = _glewSearchExtension("GL_SGIX_vertex_preclip", extStart, extEnd); + GLEW_SGIX_vertex_preclip = _glewSearchExtension("GL_SGIX_vertex_preclip", extStart, extEnd); #endif /* GL_SGIX_vertex_preclip */ #ifdef GL_SGIX_vertex_preclip_hint - CONST_CAST(GLEW_SGIX_vertex_preclip_hint) = _glewSearchExtension("GL_SGIX_vertex_preclip_hint", extStart, extEnd); + GLEW_SGIX_vertex_preclip_hint = _glewSearchExtension("GL_SGIX_vertex_preclip_hint", extStart, extEnd); #endif /* GL_SGIX_vertex_preclip_hint */ #ifdef GL_SGIX_ycrcb - CONST_CAST(GLEW_SGIX_ycrcb) = _glewSearchExtension("GL_SGIX_ycrcb", extStart, extEnd); + GLEW_SGIX_ycrcb = _glewSearchExtension("GL_SGIX_ycrcb", extStart, extEnd); #endif /* GL_SGIX_ycrcb */ #ifdef GL_SGI_color_matrix - CONST_CAST(GLEW_SGI_color_matrix) = _glewSearchExtension("GL_SGI_color_matrix", extStart, extEnd); + GLEW_SGI_color_matrix = _glewSearchExtension("GL_SGI_color_matrix", extStart, extEnd); #endif /* GL_SGI_color_matrix */ #ifdef GL_SGI_color_table - CONST_CAST(GLEW_SGI_color_table) = _glewSearchExtension("GL_SGI_color_table", extStart, extEnd); - if (glewExperimental || GLEW_SGI_color_table) CONST_CAST(GLEW_SGI_color_table) = !_glewInit_GL_SGI_color_table(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SGI_color_table = _glewSearchExtension("GL_SGI_color_table", extStart, extEnd); + if (glewExperimental || GLEW_SGI_color_table) GLEW_SGI_color_table = !_glewInit_GL_SGI_color_table(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SGI_color_table */ #ifdef GL_SGI_texture_color_table - CONST_CAST(GLEW_SGI_texture_color_table) = _glewSearchExtension("GL_SGI_texture_color_table", extStart, extEnd); + GLEW_SGI_texture_color_table = _glewSearchExtension("GL_SGI_texture_color_table", extStart, extEnd); #endif /* GL_SGI_texture_color_table */ #ifdef GL_SUNX_constant_data - CONST_CAST(GLEW_SUNX_constant_data) = _glewSearchExtension("GL_SUNX_constant_data", extStart, extEnd); - if (glewExperimental || GLEW_SUNX_constant_data) CONST_CAST(GLEW_SUNX_constant_data) = !_glewInit_GL_SUNX_constant_data(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SUNX_constant_data = _glewSearchExtension("GL_SUNX_constant_data", extStart, extEnd); + if (glewExperimental || GLEW_SUNX_constant_data) GLEW_SUNX_constant_data = !_glewInit_GL_SUNX_constant_data(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SUNX_constant_data */ #ifdef GL_SUN_convolution_border_modes - CONST_CAST(GLEW_SUN_convolution_border_modes) = _glewSearchExtension("GL_SUN_convolution_border_modes", extStart, extEnd); + GLEW_SUN_convolution_border_modes = _glewSearchExtension("GL_SUN_convolution_border_modes", extStart, extEnd); #endif /* GL_SUN_convolution_border_modes */ #ifdef GL_SUN_global_alpha - CONST_CAST(GLEW_SUN_global_alpha) = _glewSearchExtension("GL_SUN_global_alpha", extStart, extEnd); - if (glewExperimental || GLEW_SUN_global_alpha) CONST_CAST(GLEW_SUN_global_alpha) = !_glewInit_GL_SUN_global_alpha(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SUN_global_alpha = _glewSearchExtension("GL_SUN_global_alpha", extStart, extEnd); + if (glewExperimental || GLEW_SUN_global_alpha) GLEW_SUN_global_alpha = !_glewInit_GL_SUN_global_alpha(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SUN_global_alpha */ #ifdef GL_SUN_mesh_array - CONST_CAST(GLEW_SUN_mesh_array) = _glewSearchExtension("GL_SUN_mesh_array", extStart, extEnd); + GLEW_SUN_mesh_array = _glewSearchExtension("GL_SUN_mesh_array", extStart, extEnd); #endif /* GL_SUN_mesh_array */ #ifdef GL_SUN_read_video_pixels - CONST_CAST(GLEW_SUN_read_video_pixels) = _glewSearchExtension("GL_SUN_read_video_pixels", extStart, extEnd); - if (glewExperimental || GLEW_SUN_read_video_pixels) CONST_CAST(GLEW_SUN_read_video_pixels) = !_glewInit_GL_SUN_read_video_pixels(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SUN_read_video_pixels = _glewSearchExtension("GL_SUN_read_video_pixels", extStart, extEnd); + if (glewExperimental || GLEW_SUN_read_video_pixels) GLEW_SUN_read_video_pixels = !_glewInit_GL_SUN_read_video_pixels(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SUN_read_video_pixels */ #ifdef GL_SUN_slice_accum - CONST_CAST(GLEW_SUN_slice_accum) = _glewSearchExtension("GL_SUN_slice_accum", extStart, extEnd); + GLEW_SUN_slice_accum = _glewSearchExtension("GL_SUN_slice_accum", extStart, extEnd); #endif /* GL_SUN_slice_accum */ #ifdef GL_SUN_triangle_list - CONST_CAST(GLEW_SUN_triangle_list) = _glewSearchExtension("GL_SUN_triangle_list", extStart, extEnd); - if (glewExperimental || GLEW_SUN_triangle_list) CONST_CAST(GLEW_SUN_triangle_list) = !_glewInit_GL_SUN_triangle_list(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SUN_triangle_list = _glewSearchExtension("GL_SUN_triangle_list", extStart, extEnd); + if (glewExperimental || GLEW_SUN_triangle_list) GLEW_SUN_triangle_list = !_glewInit_GL_SUN_triangle_list(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SUN_triangle_list */ #ifdef GL_SUN_vertex - CONST_CAST(GLEW_SUN_vertex) = _glewSearchExtension("GL_SUN_vertex", extStart, extEnd); - if (glewExperimental || GLEW_SUN_vertex) CONST_CAST(GLEW_SUN_vertex) = !_glewInit_GL_SUN_vertex(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_SUN_vertex = _glewSearchExtension("GL_SUN_vertex", extStart, extEnd); + if (glewExperimental || GLEW_SUN_vertex) GLEW_SUN_vertex = !_glewInit_GL_SUN_vertex(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_SUN_vertex */ #ifdef GL_WIN_phong_shading - CONST_CAST(GLEW_WIN_phong_shading) = _glewSearchExtension("GL_WIN_phong_shading", extStart, extEnd); + GLEW_WIN_phong_shading = _glewSearchExtension("GL_WIN_phong_shading", extStart, extEnd); #endif /* GL_WIN_phong_shading */ #ifdef GL_WIN_specular_fog - CONST_CAST(GLEW_WIN_specular_fog) = _glewSearchExtension("GL_WIN_specular_fog", extStart, extEnd); + GLEW_WIN_specular_fog = _glewSearchExtension("GL_WIN_specular_fog", extStart, extEnd); #endif /* GL_WIN_specular_fog */ #ifdef GL_WIN_swap_hint - CONST_CAST(GLEW_WIN_swap_hint) = _glewSearchExtension("GL_WIN_swap_hint", extStart, extEnd); - if (glewExperimental || GLEW_WIN_swap_hint) CONST_CAST(GLEW_WIN_swap_hint) = !_glewInit_GL_WIN_swap_hint(GLEW_CONTEXT_ARG_VAR_INIT); + GLEW_WIN_swap_hint = _glewSearchExtension("GL_WIN_swap_hint", extStart, extEnd); + if (glewExperimental || GLEW_WIN_swap_hint) GLEW_WIN_swap_hint = !_glewInit_GL_WIN_swap_hint(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GL_WIN_swap_hint */ return GLEW_OK; @@ -11433,6 +11672,8 @@ PFNWGLDXUNREGISTEROBJECTNVPROC __wglewDXUnregisterObjectNV = NULL; PFNWGLCOPYIMAGESUBDATANVPROC __wglewCopyImageSubDataNV = NULL; +PFNWGLDELAYBEFORESWAPNVPROC __wglewDelayBeforeSwapNV = NULL; + PFNWGLCREATEAFFINITYDCNVPROC __wglewCreateAffinityDCNV = NULL; PFNWGLDELETEDCNVPROC __wglewDeleteDCNV = NULL; PFNWGLENUMGPUDEVICESNVPROC __wglewEnumGpuDevicesNV = NULL; @@ -11513,6 +11754,7 @@ GLboolean __WGLEW_I3D_swap_frame_usage = GL_FALSE; GLboolean __WGLEW_NV_DX_interop = GL_FALSE; GLboolean __WGLEW_NV_DX_interop2 = GL_FALSE; GLboolean __WGLEW_NV_copy_image = GL_FALSE; +GLboolean __WGLEW_NV_delay_before_swap = GL_FALSE; GLboolean __WGLEW_NV_float_buffer = GL_FALSE; GLboolean __WGLEW_NV_gpu_affinity = GL_FALSE; GLboolean __WGLEW_NV_multisample_coverage = GL_FALSE; @@ -11960,6 +12202,19 @@ static GLboolean _glewInit_WGL_NV_copy_image (WGLEW_CONTEXT_ARG_DEF_INIT) #endif /* WGL_NV_copy_image */ +#ifdef WGL_NV_delay_before_swap + +static GLboolean _glewInit_WGL_NV_delay_before_swap (WGLEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((wglDelayBeforeSwapNV = (PFNWGLDELAYBEFORESWAPNVPROC)glewGetProcAddress((const GLubyte*)"wglDelayBeforeSwapNV")) == NULL) || r; + + return r; +} + +#endif /* WGL_NV_delay_before_swap */ + #ifdef WGL_NV_float_buffer #endif /* WGL_NV_float_buffer */ @@ -12135,196 +12390,200 @@ GLenum GLEWAPIENTRY wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST) /* initialize extensions */ crippled = _wglewGetExtensionsStringARB == NULL && _wglewGetExtensionsStringEXT == NULL; #ifdef WGL_3DFX_multisample - CONST_CAST(WGLEW_3DFX_multisample) = _glewSearchExtension("WGL_3DFX_multisample", extStart, extEnd); + WGLEW_3DFX_multisample = _glewSearchExtension("WGL_3DFX_multisample", extStart, extEnd); #endif /* WGL_3DFX_multisample */ #ifdef WGL_3DL_stereo_control - CONST_CAST(WGLEW_3DL_stereo_control) = _glewSearchExtension("WGL_3DL_stereo_control", extStart, extEnd); - if (glewExperimental || WGLEW_3DL_stereo_control|| crippled) CONST_CAST(WGLEW_3DL_stereo_control)= !_glewInit_WGL_3DL_stereo_control(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_3DL_stereo_control = _glewSearchExtension("WGL_3DL_stereo_control", extStart, extEnd); + if (glewExperimental || WGLEW_3DL_stereo_control|| crippled) WGLEW_3DL_stereo_control= !_glewInit_WGL_3DL_stereo_control(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_3DL_stereo_control */ #ifdef WGL_AMD_gpu_association - CONST_CAST(WGLEW_AMD_gpu_association) = _glewSearchExtension("WGL_AMD_gpu_association", extStart, extEnd); - if (glewExperimental || WGLEW_AMD_gpu_association|| crippled) CONST_CAST(WGLEW_AMD_gpu_association)= !_glewInit_WGL_AMD_gpu_association(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_AMD_gpu_association = _glewSearchExtension("WGL_AMD_gpu_association", extStart, extEnd); + if (glewExperimental || WGLEW_AMD_gpu_association|| crippled) WGLEW_AMD_gpu_association= !_glewInit_WGL_AMD_gpu_association(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_AMD_gpu_association */ #ifdef WGL_ARB_buffer_region - CONST_CAST(WGLEW_ARB_buffer_region) = _glewSearchExtension("WGL_ARB_buffer_region", extStart, extEnd); - if (glewExperimental || WGLEW_ARB_buffer_region|| crippled) CONST_CAST(WGLEW_ARB_buffer_region)= !_glewInit_WGL_ARB_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_ARB_buffer_region = _glewSearchExtension("WGL_ARB_buffer_region", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_buffer_region|| crippled) WGLEW_ARB_buffer_region= !_glewInit_WGL_ARB_buffer_region(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_ARB_buffer_region */ #ifdef WGL_ARB_create_context - CONST_CAST(WGLEW_ARB_create_context) = _glewSearchExtension("WGL_ARB_create_context", extStart, extEnd); - if (glewExperimental || WGLEW_ARB_create_context|| crippled) CONST_CAST(WGLEW_ARB_create_context)= !_glewInit_WGL_ARB_create_context(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_ARB_create_context = _glewSearchExtension("WGL_ARB_create_context", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_create_context|| crippled) WGLEW_ARB_create_context= !_glewInit_WGL_ARB_create_context(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_ARB_create_context */ #ifdef WGL_ARB_create_context_profile - CONST_CAST(WGLEW_ARB_create_context_profile) = _glewSearchExtension("WGL_ARB_create_context_profile", extStart, extEnd); + WGLEW_ARB_create_context_profile = _glewSearchExtension("WGL_ARB_create_context_profile", extStart, extEnd); #endif /* WGL_ARB_create_context_profile */ #ifdef WGL_ARB_create_context_robustness - CONST_CAST(WGLEW_ARB_create_context_robustness) = _glewSearchExtension("WGL_ARB_create_context_robustness", extStart, extEnd); + WGLEW_ARB_create_context_robustness = _glewSearchExtension("WGL_ARB_create_context_robustness", extStart, extEnd); #endif /* WGL_ARB_create_context_robustness */ #ifdef WGL_ARB_extensions_string - CONST_CAST(WGLEW_ARB_extensions_string) = _glewSearchExtension("WGL_ARB_extensions_string", extStart, extEnd); - if (glewExperimental || WGLEW_ARB_extensions_string|| crippled) CONST_CAST(WGLEW_ARB_extensions_string)= !_glewInit_WGL_ARB_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_ARB_extensions_string = _glewSearchExtension("WGL_ARB_extensions_string", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_extensions_string|| crippled) WGLEW_ARB_extensions_string= !_glewInit_WGL_ARB_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_ARB_extensions_string */ #ifdef WGL_ARB_framebuffer_sRGB - CONST_CAST(WGLEW_ARB_framebuffer_sRGB) = _glewSearchExtension("WGL_ARB_framebuffer_sRGB", extStart, extEnd); + WGLEW_ARB_framebuffer_sRGB = _glewSearchExtension("WGL_ARB_framebuffer_sRGB", extStart, extEnd); #endif /* WGL_ARB_framebuffer_sRGB */ #ifdef WGL_ARB_make_current_read - CONST_CAST(WGLEW_ARB_make_current_read) = _glewSearchExtension("WGL_ARB_make_current_read", extStart, extEnd); - if (glewExperimental || WGLEW_ARB_make_current_read|| crippled) CONST_CAST(WGLEW_ARB_make_current_read)= !_glewInit_WGL_ARB_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_ARB_make_current_read = _glewSearchExtension("WGL_ARB_make_current_read", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_make_current_read|| crippled) WGLEW_ARB_make_current_read= !_glewInit_WGL_ARB_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_ARB_make_current_read */ #ifdef WGL_ARB_multisample - CONST_CAST(WGLEW_ARB_multisample) = _glewSearchExtension("WGL_ARB_multisample", extStart, extEnd); + WGLEW_ARB_multisample = _glewSearchExtension("WGL_ARB_multisample", extStart, extEnd); #endif /* WGL_ARB_multisample */ #ifdef WGL_ARB_pbuffer - CONST_CAST(WGLEW_ARB_pbuffer) = _glewSearchExtension("WGL_ARB_pbuffer", extStart, extEnd); - if (glewExperimental || WGLEW_ARB_pbuffer|| crippled) CONST_CAST(WGLEW_ARB_pbuffer)= !_glewInit_WGL_ARB_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_ARB_pbuffer = _glewSearchExtension("WGL_ARB_pbuffer", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_pbuffer|| crippled) WGLEW_ARB_pbuffer= !_glewInit_WGL_ARB_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_ARB_pbuffer */ #ifdef WGL_ARB_pixel_format - CONST_CAST(WGLEW_ARB_pixel_format) = _glewSearchExtension("WGL_ARB_pixel_format", extStart, extEnd); - if (glewExperimental || WGLEW_ARB_pixel_format|| crippled) CONST_CAST(WGLEW_ARB_pixel_format)= !_glewInit_WGL_ARB_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_ARB_pixel_format = _glewSearchExtension("WGL_ARB_pixel_format", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_pixel_format|| crippled) WGLEW_ARB_pixel_format= !_glewInit_WGL_ARB_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_ARB_pixel_format */ #ifdef WGL_ARB_pixel_format_float - CONST_CAST(WGLEW_ARB_pixel_format_float) = _glewSearchExtension("WGL_ARB_pixel_format_float", extStart, extEnd); + WGLEW_ARB_pixel_format_float = _glewSearchExtension("WGL_ARB_pixel_format_float", extStart, extEnd); #endif /* WGL_ARB_pixel_format_float */ #ifdef WGL_ARB_render_texture - CONST_CAST(WGLEW_ARB_render_texture) = _glewSearchExtension("WGL_ARB_render_texture", extStart, extEnd); - if (glewExperimental || WGLEW_ARB_render_texture|| crippled) CONST_CAST(WGLEW_ARB_render_texture)= !_glewInit_WGL_ARB_render_texture(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_ARB_render_texture = _glewSearchExtension("WGL_ARB_render_texture", extStart, extEnd); + if (glewExperimental || WGLEW_ARB_render_texture|| crippled) WGLEW_ARB_render_texture= !_glewInit_WGL_ARB_render_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_ARB_render_texture */ #ifdef WGL_ARB_robustness_application_isolation - CONST_CAST(WGLEW_ARB_robustness_application_isolation) = _glewSearchExtension("WGL_ARB_robustness_application_isolation", extStart, extEnd); + WGLEW_ARB_robustness_application_isolation = _glewSearchExtension("WGL_ARB_robustness_application_isolation", extStart, extEnd); #endif /* WGL_ARB_robustness_application_isolation */ #ifdef WGL_ARB_robustness_share_group_isolation - CONST_CAST(WGLEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("WGL_ARB_robustness_share_group_isolation", extStart, extEnd); + WGLEW_ARB_robustness_share_group_isolation = _glewSearchExtension("WGL_ARB_robustness_share_group_isolation", extStart, extEnd); #endif /* WGL_ARB_robustness_share_group_isolation */ #ifdef WGL_ATI_pixel_format_float - CONST_CAST(WGLEW_ATI_pixel_format_float) = _glewSearchExtension("WGL_ATI_pixel_format_float", extStart, extEnd); + WGLEW_ATI_pixel_format_float = _glewSearchExtension("WGL_ATI_pixel_format_float", extStart, extEnd); #endif /* WGL_ATI_pixel_format_float */ #ifdef WGL_ATI_render_texture_rectangle - CONST_CAST(WGLEW_ATI_render_texture_rectangle) = _glewSearchExtension("WGL_ATI_render_texture_rectangle", extStart, extEnd); + WGLEW_ATI_render_texture_rectangle = _glewSearchExtension("WGL_ATI_render_texture_rectangle", extStart, extEnd); #endif /* WGL_ATI_render_texture_rectangle */ #ifdef WGL_EXT_create_context_es2_profile - CONST_CAST(WGLEW_EXT_create_context_es2_profile) = _glewSearchExtension("WGL_EXT_create_context_es2_profile", extStart, extEnd); + WGLEW_EXT_create_context_es2_profile = _glewSearchExtension("WGL_EXT_create_context_es2_profile", extStart, extEnd); #endif /* WGL_EXT_create_context_es2_profile */ #ifdef WGL_EXT_create_context_es_profile - CONST_CAST(WGLEW_EXT_create_context_es_profile) = _glewSearchExtension("WGL_EXT_create_context_es_profile", extStart, extEnd); + WGLEW_EXT_create_context_es_profile = _glewSearchExtension("WGL_EXT_create_context_es_profile", extStart, extEnd); #endif /* WGL_EXT_create_context_es_profile */ #ifdef WGL_EXT_depth_float - CONST_CAST(WGLEW_EXT_depth_float) = _glewSearchExtension("WGL_EXT_depth_float", extStart, extEnd); + WGLEW_EXT_depth_float = _glewSearchExtension("WGL_EXT_depth_float", extStart, extEnd); #endif /* WGL_EXT_depth_float */ #ifdef WGL_EXT_display_color_table - CONST_CAST(WGLEW_EXT_display_color_table) = _glewSearchExtension("WGL_EXT_display_color_table", extStart, extEnd); - if (glewExperimental || WGLEW_EXT_display_color_table|| crippled) CONST_CAST(WGLEW_EXT_display_color_table)= !_glewInit_WGL_EXT_display_color_table(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_EXT_display_color_table = _glewSearchExtension("WGL_EXT_display_color_table", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_display_color_table|| crippled) WGLEW_EXT_display_color_table= !_glewInit_WGL_EXT_display_color_table(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_EXT_display_color_table */ #ifdef WGL_EXT_extensions_string - CONST_CAST(WGLEW_EXT_extensions_string) = _glewSearchExtension("WGL_EXT_extensions_string", extStart, extEnd); - if (glewExperimental || WGLEW_EXT_extensions_string|| crippled) CONST_CAST(WGLEW_EXT_extensions_string)= !_glewInit_WGL_EXT_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_EXT_extensions_string = _glewSearchExtension("WGL_EXT_extensions_string", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_extensions_string|| crippled) WGLEW_EXT_extensions_string= !_glewInit_WGL_EXT_extensions_string(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_EXT_extensions_string */ #ifdef WGL_EXT_framebuffer_sRGB - CONST_CAST(WGLEW_EXT_framebuffer_sRGB) = _glewSearchExtension("WGL_EXT_framebuffer_sRGB", extStart, extEnd); + WGLEW_EXT_framebuffer_sRGB = _glewSearchExtension("WGL_EXT_framebuffer_sRGB", extStart, extEnd); #endif /* WGL_EXT_framebuffer_sRGB */ #ifdef WGL_EXT_make_current_read - CONST_CAST(WGLEW_EXT_make_current_read) = _glewSearchExtension("WGL_EXT_make_current_read", extStart, extEnd); - if (glewExperimental || WGLEW_EXT_make_current_read|| crippled) CONST_CAST(WGLEW_EXT_make_current_read)= !_glewInit_WGL_EXT_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_EXT_make_current_read = _glewSearchExtension("WGL_EXT_make_current_read", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_make_current_read|| crippled) WGLEW_EXT_make_current_read= !_glewInit_WGL_EXT_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_EXT_make_current_read */ #ifdef WGL_EXT_multisample - CONST_CAST(WGLEW_EXT_multisample) = _glewSearchExtension("WGL_EXT_multisample", extStart, extEnd); + WGLEW_EXT_multisample = _glewSearchExtension("WGL_EXT_multisample", extStart, extEnd); #endif /* WGL_EXT_multisample */ #ifdef WGL_EXT_pbuffer - CONST_CAST(WGLEW_EXT_pbuffer) = _glewSearchExtension("WGL_EXT_pbuffer", extStart, extEnd); - if (glewExperimental || WGLEW_EXT_pbuffer|| crippled) CONST_CAST(WGLEW_EXT_pbuffer)= !_glewInit_WGL_EXT_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_EXT_pbuffer = _glewSearchExtension("WGL_EXT_pbuffer", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_pbuffer|| crippled) WGLEW_EXT_pbuffer= !_glewInit_WGL_EXT_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_EXT_pbuffer */ #ifdef WGL_EXT_pixel_format - CONST_CAST(WGLEW_EXT_pixel_format) = _glewSearchExtension("WGL_EXT_pixel_format", extStart, extEnd); - if (glewExperimental || WGLEW_EXT_pixel_format|| crippled) CONST_CAST(WGLEW_EXT_pixel_format)= !_glewInit_WGL_EXT_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_EXT_pixel_format = _glewSearchExtension("WGL_EXT_pixel_format", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_pixel_format|| crippled) WGLEW_EXT_pixel_format= !_glewInit_WGL_EXT_pixel_format(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_EXT_pixel_format */ #ifdef WGL_EXT_pixel_format_packed_float - CONST_CAST(WGLEW_EXT_pixel_format_packed_float) = _glewSearchExtension("WGL_EXT_pixel_format_packed_float", extStart, extEnd); + WGLEW_EXT_pixel_format_packed_float = _glewSearchExtension("WGL_EXT_pixel_format_packed_float", extStart, extEnd); #endif /* WGL_EXT_pixel_format_packed_float */ #ifdef WGL_EXT_swap_control - CONST_CAST(WGLEW_EXT_swap_control) = _glewSearchExtension("WGL_EXT_swap_control", extStart, extEnd); - if (glewExperimental || WGLEW_EXT_swap_control|| crippled) CONST_CAST(WGLEW_EXT_swap_control)= !_glewInit_WGL_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_EXT_swap_control = _glewSearchExtension("WGL_EXT_swap_control", extStart, extEnd); + if (glewExperimental || WGLEW_EXT_swap_control|| crippled) WGLEW_EXT_swap_control= !_glewInit_WGL_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_EXT_swap_control */ #ifdef WGL_EXT_swap_control_tear - CONST_CAST(WGLEW_EXT_swap_control_tear) = _glewSearchExtension("WGL_EXT_swap_control_tear", extStart, extEnd); + WGLEW_EXT_swap_control_tear = _glewSearchExtension("WGL_EXT_swap_control_tear", extStart, extEnd); #endif /* WGL_EXT_swap_control_tear */ #ifdef WGL_I3D_digital_video_control - CONST_CAST(WGLEW_I3D_digital_video_control) = _glewSearchExtension("WGL_I3D_digital_video_control", extStart, extEnd); - if (glewExperimental || WGLEW_I3D_digital_video_control|| crippled) CONST_CAST(WGLEW_I3D_digital_video_control)= !_glewInit_WGL_I3D_digital_video_control(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_I3D_digital_video_control = _glewSearchExtension("WGL_I3D_digital_video_control", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_digital_video_control|| crippled) WGLEW_I3D_digital_video_control= !_glewInit_WGL_I3D_digital_video_control(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_I3D_digital_video_control */ #ifdef WGL_I3D_gamma - CONST_CAST(WGLEW_I3D_gamma) = _glewSearchExtension("WGL_I3D_gamma", extStart, extEnd); - if (glewExperimental || WGLEW_I3D_gamma|| crippled) CONST_CAST(WGLEW_I3D_gamma)= !_glewInit_WGL_I3D_gamma(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_I3D_gamma = _glewSearchExtension("WGL_I3D_gamma", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_gamma|| crippled) WGLEW_I3D_gamma= !_glewInit_WGL_I3D_gamma(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_I3D_gamma */ #ifdef WGL_I3D_genlock - CONST_CAST(WGLEW_I3D_genlock) = _glewSearchExtension("WGL_I3D_genlock", extStart, extEnd); - if (glewExperimental || WGLEW_I3D_genlock|| crippled) CONST_CAST(WGLEW_I3D_genlock)= !_glewInit_WGL_I3D_genlock(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_I3D_genlock = _glewSearchExtension("WGL_I3D_genlock", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_genlock|| crippled) WGLEW_I3D_genlock= !_glewInit_WGL_I3D_genlock(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_I3D_genlock */ #ifdef WGL_I3D_image_buffer - CONST_CAST(WGLEW_I3D_image_buffer) = _glewSearchExtension("WGL_I3D_image_buffer", extStart, extEnd); - if (glewExperimental || WGLEW_I3D_image_buffer|| crippled) CONST_CAST(WGLEW_I3D_image_buffer)= !_glewInit_WGL_I3D_image_buffer(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_I3D_image_buffer = _glewSearchExtension("WGL_I3D_image_buffer", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_image_buffer|| crippled) WGLEW_I3D_image_buffer= !_glewInit_WGL_I3D_image_buffer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_I3D_image_buffer */ #ifdef WGL_I3D_swap_frame_lock - CONST_CAST(WGLEW_I3D_swap_frame_lock) = _glewSearchExtension("WGL_I3D_swap_frame_lock", extStart, extEnd); - if (glewExperimental || WGLEW_I3D_swap_frame_lock|| crippled) CONST_CAST(WGLEW_I3D_swap_frame_lock)= !_glewInit_WGL_I3D_swap_frame_lock(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_I3D_swap_frame_lock = _glewSearchExtension("WGL_I3D_swap_frame_lock", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_swap_frame_lock|| crippled) WGLEW_I3D_swap_frame_lock= !_glewInit_WGL_I3D_swap_frame_lock(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_I3D_swap_frame_lock */ #ifdef WGL_I3D_swap_frame_usage - CONST_CAST(WGLEW_I3D_swap_frame_usage) = _glewSearchExtension("WGL_I3D_swap_frame_usage", extStart, extEnd); - if (glewExperimental || WGLEW_I3D_swap_frame_usage|| crippled) CONST_CAST(WGLEW_I3D_swap_frame_usage)= !_glewInit_WGL_I3D_swap_frame_usage(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_I3D_swap_frame_usage = _glewSearchExtension("WGL_I3D_swap_frame_usage", extStart, extEnd); + if (glewExperimental || WGLEW_I3D_swap_frame_usage|| crippled) WGLEW_I3D_swap_frame_usage= !_glewInit_WGL_I3D_swap_frame_usage(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_I3D_swap_frame_usage */ #ifdef WGL_NV_DX_interop - CONST_CAST(WGLEW_NV_DX_interop) = _glewSearchExtension("WGL_NV_DX_interop", extStart, extEnd); - if (glewExperimental || WGLEW_NV_DX_interop|| crippled) CONST_CAST(WGLEW_NV_DX_interop)= !_glewInit_WGL_NV_DX_interop(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_NV_DX_interop = _glewSearchExtension("WGL_NV_DX_interop", extStart, extEnd); + if (glewExperimental || WGLEW_NV_DX_interop|| crippled) WGLEW_NV_DX_interop= !_glewInit_WGL_NV_DX_interop(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_NV_DX_interop */ #ifdef WGL_NV_DX_interop2 - CONST_CAST(WGLEW_NV_DX_interop2) = _glewSearchExtension("WGL_NV_DX_interop2", extStart, extEnd); + WGLEW_NV_DX_interop2 = _glewSearchExtension("WGL_NV_DX_interop2", extStart, extEnd); #endif /* WGL_NV_DX_interop2 */ #ifdef WGL_NV_copy_image - CONST_CAST(WGLEW_NV_copy_image) = _glewSearchExtension("WGL_NV_copy_image", extStart, extEnd); - if (glewExperimental || WGLEW_NV_copy_image|| crippled) CONST_CAST(WGLEW_NV_copy_image)= !_glewInit_WGL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_NV_copy_image = _glewSearchExtension("WGL_NV_copy_image", extStart, extEnd); + if (glewExperimental || WGLEW_NV_copy_image|| crippled) WGLEW_NV_copy_image= !_glewInit_WGL_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_NV_copy_image */ +#ifdef WGL_NV_delay_before_swap + WGLEW_NV_delay_before_swap = _glewSearchExtension("WGL_NV_delay_before_swap", extStart, extEnd); + if (glewExperimental || WGLEW_NV_delay_before_swap|| crippled) WGLEW_NV_delay_before_swap= !_glewInit_WGL_NV_delay_before_swap(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* WGL_NV_delay_before_swap */ #ifdef WGL_NV_float_buffer - CONST_CAST(WGLEW_NV_float_buffer) = _glewSearchExtension("WGL_NV_float_buffer", extStart, extEnd); + WGLEW_NV_float_buffer = _glewSearchExtension("WGL_NV_float_buffer", extStart, extEnd); #endif /* WGL_NV_float_buffer */ #ifdef WGL_NV_gpu_affinity - CONST_CAST(WGLEW_NV_gpu_affinity) = _glewSearchExtension("WGL_NV_gpu_affinity", extStart, extEnd); - if (glewExperimental || WGLEW_NV_gpu_affinity|| crippled) CONST_CAST(WGLEW_NV_gpu_affinity)= !_glewInit_WGL_NV_gpu_affinity(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_NV_gpu_affinity = _glewSearchExtension("WGL_NV_gpu_affinity", extStart, extEnd); + if (glewExperimental || WGLEW_NV_gpu_affinity|| crippled) WGLEW_NV_gpu_affinity= !_glewInit_WGL_NV_gpu_affinity(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_NV_gpu_affinity */ #ifdef WGL_NV_multisample_coverage - CONST_CAST(WGLEW_NV_multisample_coverage) = _glewSearchExtension("WGL_NV_multisample_coverage", extStart, extEnd); + WGLEW_NV_multisample_coverage = _glewSearchExtension("WGL_NV_multisample_coverage", extStart, extEnd); #endif /* WGL_NV_multisample_coverage */ #ifdef WGL_NV_present_video - CONST_CAST(WGLEW_NV_present_video) = _glewSearchExtension("WGL_NV_present_video", extStart, extEnd); - if (glewExperimental || WGLEW_NV_present_video|| crippled) CONST_CAST(WGLEW_NV_present_video)= !_glewInit_WGL_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_NV_present_video = _glewSearchExtension("WGL_NV_present_video", extStart, extEnd); + if (glewExperimental || WGLEW_NV_present_video|| crippled) WGLEW_NV_present_video= !_glewInit_WGL_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_NV_present_video */ #ifdef WGL_NV_render_depth_texture - CONST_CAST(WGLEW_NV_render_depth_texture) = _glewSearchExtension("WGL_NV_render_depth_texture", extStart, extEnd); + WGLEW_NV_render_depth_texture = _glewSearchExtension("WGL_NV_render_depth_texture", extStart, extEnd); #endif /* WGL_NV_render_depth_texture */ #ifdef WGL_NV_render_texture_rectangle - CONST_CAST(WGLEW_NV_render_texture_rectangle) = _glewSearchExtension("WGL_NV_render_texture_rectangle", extStart, extEnd); + WGLEW_NV_render_texture_rectangle = _glewSearchExtension("WGL_NV_render_texture_rectangle", extStart, extEnd); #endif /* WGL_NV_render_texture_rectangle */ #ifdef WGL_NV_swap_group - CONST_CAST(WGLEW_NV_swap_group) = _glewSearchExtension("WGL_NV_swap_group", extStart, extEnd); - if (glewExperimental || WGLEW_NV_swap_group|| crippled) CONST_CAST(WGLEW_NV_swap_group)= !_glewInit_WGL_NV_swap_group(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_NV_swap_group = _glewSearchExtension("WGL_NV_swap_group", extStart, extEnd); + if (glewExperimental || WGLEW_NV_swap_group|| crippled) WGLEW_NV_swap_group= !_glewInit_WGL_NV_swap_group(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_NV_swap_group */ #ifdef WGL_NV_vertex_array_range - CONST_CAST(WGLEW_NV_vertex_array_range) = _glewSearchExtension("WGL_NV_vertex_array_range", extStart, extEnd); - if (glewExperimental || WGLEW_NV_vertex_array_range|| crippled) CONST_CAST(WGLEW_NV_vertex_array_range)= !_glewInit_WGL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_NV_vertex_array_range = _glewSearchExtension("WGL_NV_vertex_array_range", extStart, extEnd); + if (glewExperimental || WGLEW_NV_vertex_array_range|| crippled) WGLEW_NV_vertex_array_range= !_glewInit_WGL_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_NV_vertex_array_range */ #ifdef WGL_NV_video_capture - CONST_CAST(WGLEW_NV_video_capture) = _glewSearchExtension("WGL_NV_video_capture", extStart, extEnd); - if (glewExperimental || WGLEW_NV_video_capture|| crippled) CONST_CAST(WGLEW_NV_video_capture)= !_glewInit_WGL_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_NV_video_capture = _glewSearchExtension("WGL_NV_video_capture", extStart, extEnd); + if (glewExperimental || WGLEW_NV_video_capture|| crippled) WGLEW_NV_video_capture= !_glewInit_WGL_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_NV_video_capture */ #ifdef WGL_NV_video_output - CONST_CAST(WGLEW_NV_video_output) = _glewSearchExtension("WGL_NV_video_output", extStart, extEnd); - if (glewExperimental || WGLEW_NV_video_output|| crippled) CONST_CAST(WGLEW_NV_video_output)= !_glewInit_WGL_NV_video_output(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_NV_video_output = _glewSearchExtension("WGL_NV_video_output", extStart, extEnd); + if (glewExperimental || WGLEW_NV_video_output|| crippled) WGLEW_NV_video_output= !_glewInit_WGL_NV_video_output(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_NV_video_output */ #ifdef WGL_OML_sync_control - CONST_CAST(WGLEW_OML_sync_control) = _glewSearchExtension("WGL_OML_sync_control", extStart, extEnd); - if (glewExperimental || WGLEW_OML_sync_control|| crippled) CONST_CAST(WGLEW_OML_sync_control)= !_glewInit_WGL_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT); + WGLEW_OML_sync_control = _glewSearchExtension("WGL_OML_sync_control", extStart, extEnd); + if (glewExperimental || WGLEW_OML_sync_control|| crippled) WGLEW_OML_sync_control= !_glewInit_WGL_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* WGL_OML_sync_control */ return GLEW_OK; } -#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) +#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) PFNGLXGETCURRENTDISPLAYPROC __glewXGetCurrentDisplay = NULL; @@ -12378,6 +12637,11 @@ PFNGLXCOPYSUBBUFFERMESAPROC __glewXCopySubBufferMESA = NULL; PFNGLXCREATEGLXPIXMAPMESAPROC __glewXCreateGLXPixmapMESA = NULL; +PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC __glewXQueryCurrentRendererIntegerMESA = NULL; +PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC __glewXQueryCurrentRendererStringMESA = NULL; +PFNGLXQUERYRENDERERINTEGERMESAPROC __glewXQueryRendererIntegerMESA = NULL; +PFNGLXQUERYRENDERERSTRINGMESAPROC __glewXQueryRendererStringMESA = NULL; + PFNGLXRELEASEBUFFERSMESAPROC __glewXReleaseBuffersMESA = NULL; PFNGLXSET3DFXMODEMESAPROC __glewXSet3DfxModeMESA = NULL; @@ -12387,6 +12651,8 @@ PFNGLXSWAPINTERVALMESAPROC __glewXSwapIntervalMESA = NULL; PFNGLXCOPYIMAGESUBDATANVPROC __glewXCopyImageSubDataNV = NULL; +PFNGLXDELAYBEFORESWAPNVPROC __glewXDelayBeforeSwapNV = NULL; + PFNGLXBINDVIDEODEVICENVPROC __glewXBindVideoDeviceNV = NULL; PFNGLXENUMERATEVIDEODEVICESNVPROC __glewXEnumerateVideoDevicesNV = NULL; @@ -12495,6 +12761,7 @@ GLboolean __GLXEW_EXT_fbconfig_packed_float = GL_FALSE; GLboolean __GLXEW_EXT_framebuffer_sRGB = GL_FALSE; GLboolean __GLXEW_EXT_import_context = GL_FALSE; GLboolean __GLXEW_EXT_scene_marker = GL_FALSE; +GLboolean __GLXEW_EXT_stereo_tree = GL_FALSE; GLboolean __GLXEW_EXT_swap_control = GL_FALSE; GLboolean __GLXEW_EXT_swap_control_tear = GL_FALSE; GLboolean __GLXEW_EXT_texture_from_pixmap = GL_FALSE; @@ -12504,17 +12771,19 @@ GLboolean __GLXEW_INTEL_swap_event = GL_FALSE; GLboolean __GLXEW_MESA_agp_offset = GL_FALSE; GLboolean __GLXEW_MESA_copy_sub_buffer = GL_FALSE; GLboolean __GLXEW_MESA_pixmap_colormap = GL_FALSE; +GLboolean __GLXEW_MESA_query_renderer = GL_FALSE; GLboolean __GLXEW_MESA_release_buffers = GL_FALSE; GLboolean __GLXEW_MESA_set_3dfx_mode = GL_FALSE; GLboolean __GLXEW_MESA_swap_control = GL_FALSE; GLboolean __GLXEW_NV_copy_image = GL_FALSE; +GLboolean __GLXEW_NV_delay_before_swap = GL_FALSE; GLboolean __GLXEW_NV_float_buffer = GL_FALSE; GLboolean __GLXEW_NV_multisample_coverage = GL_FALSE; GLboolean __GLXEW_NV_present_video = GL_FALSE; GLboolean __GLXEW_NV_swap_group = GL_FALSE; GLboolean __GLXEW_NV_vertex_array_range = GL_FALSE; GLboolean __GLXEW_NV_video_capture = GL_FALSE; -GLboolean __GLXEW_NV_video_output = GL_FALSE; +GLboolean __GLXEW_NV_video_out = GL_FALSE; GLboolean __GLXEW_OML_swap_method = GL_FALSE; GLboolean __GLXEW_OML_sync_control = GL_FALSE; GLboolean __GLXEW_SGIS_blended_overlay = GL_FALSE; @@ -12716,6 +12985,10 @@ static GLboolean _glewInit_GLX_EXT_import_context (GLXEW_CONTEXT_ARG_DEF_INIT) #endif /* GLX_EXT_scene_marker */ +#ifdef GLX_EXT_stereo_tree + +#endif /* GLX_EXT_stereo_tree */ + #ifdef GLX_EXT_swap_control static GLboolean _glewInit_GLX_EXT_swap_control (GLXEW_CONTEXT_ARG_DEF_INIT) @@ -12798,6 +13071,22 @@ static GLboolean _glewInit_GLX_MESA_pixmap_colormap (GLXEW_CONTEXT_ARG_DEF_INIT) #endif /* GLX_MESA_pixmap_colormap */ +#ifdef GLX_MESA_query_renderer + +static GLboolean _glewInit_GLX_MESA_query_renderer (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXQueryCurrentRendererIntegerMESA = (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC)glewGetProcAddress((const GLubyte*)"glXQueryCurrentRendererIntegerMESA")) == NULL) || r; + r = ((glXQueryCurrentRendererStringMESA = (PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC)glewGetProcAddress((const GLubyte*)"glXQueryCurrentRendererStringMESA")) == NULL) || r; + r = ((glXQueryRendererIntegerMESA = (PFNGLXQUERYRENDERERINTEGERMESAPROC)glewGetProcAddress((const GLubyte*)"glXQueryRendererIntegerMESA")) == NULL) || r; + r = ((glXQueryRendererStringMESA = (PFNGLXQUERYRENDERERSTRINGMESAPROC)glewGetProcAddress((const GLubyte*)"glXQueryRendererStringMESA")) == NULL) || r; + + return r; +} + +#endif /* GLX_MESA_query_renderer */ + #ifdef GLX_MESA_release_buffers static GLboolean _glewInit_GLX_MESA_release_buffers (GLXEW_CONTEXT_ARG_DEF_INIT) @@ -12851,6 +13140,19 @@ static GLboolean _glewInit_GLX_NV_copy_image (GLXEW_CONTEXT_ARG_DEF_INIT) #endif /* GLX_NV_copy_image */ +#ifdef GLX_NV_delay_before_swap + +static GLboolean _glewInit_GLX_NV_delay_before_swap (GLXEW_CONTEXT_ARG_DEF_INIT) +{ + GLboolean r = GL_FALSE; + + r = ((glXDelayBeforeSwapNV = (PFNGLXDELAYBEFORESWAPNVPROC)glewGetProcAddress((const GLubyte*)"glXDelayBeforeSwapNV")) == NULL) || r; + + return r; +} + +#endif /* GLX_NV_delay_before_swap */ + #ifdef GLX_NV_float_buffer #endif /* GLX_NV_float_buffer */ @@ -12922,9 +13224,9 @@ static GLboolean _glewInit_GLX_NV_video_capture (GLXEW_CONTEXT_ARG_DEF_INIT) #endif /* GLX_NV_video_capture */ -#ifdef GLX_NV_video_output +#ifdef GLX_NV_video_out -static GLboolean _glewInit_GLX_NV_video_output (GLXEW_CONTEXT_ARG_DEF_INIT) +static GLboolean _glewInit_GLX_NV_video_out (GLXEW_CONTEXT_ARG_DEF_INIT) { GLboolean r = GL_FALSE; @@ -12938,7 +13240,7 @@ static GLboolean _glewInit_GLX_NV_video_output (GLXEW_CONTEXT_ARG_DEF_INIT) return r; } -#endif /* GLX_NV_video_output */ +#endif /* GLX_NV_video_out */ #ifdef GLX_OML_swap_method @@ -13183,11 +13485,11 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) /* initialize core GLX 1.2 */ if (_glewInit_GLX_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT)) return GLEW_ERROR_GLX_VERSION_11_ONLY; /* initialize flags */ - CONST_CAST(GLXEW_VERSION_1_0) = GL_TRUE; - CONST_CAST(GLXEW_VERSION_1_1) = GL_TRUE; - CONST_CAST(GLXEW_VERSION_1_2) = GL_TRUE; - CONST_CAST(GLXEW_VERSION_1_3) = GL_TRUE; - CONST_CAST(GLXEW_VERSION_1_4) = GL_TRUE; + GLXEW_VERSION_1_0 = GL_TRUE; + GLXEW_VERSION_1_1 = GL_TRUE; + GLXEW_VERSION_1_2 = GL_TRUE; + GLXEW_VERSION_1_3 = GL_TRUE; + GLXEW_VERSION_1_4 = GL_TRUE; /* query GLX version */ glXQueryVersion(glXGetCurrentDisplay(), &major, &minor); if (major == 1 && minor <= 3) @@ -13195,11 +13497,11 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) switch (minor) { case 3: - CONST_CAST(GLXEW_VERSION_1_4) = GL_FALSE; + GLXEW_VERSION_1_4 = GL_FALSE; break; case 2: - CONST_CAST(GLXEW_VERSION_1_4) = GL_FALSE; - CONST_CAST(GLXEW_VERSION_1_3) = GL_FALSE; + GLXEW_VERSION_1_4 = GL_FALSE; + GLXEW_VERSION_1_3 = GL_FALSE; break; default: return GLEW_ERROR_GLX_VERSION_11_ONLY; @@ -13215,224 +13517,235 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST) extEnd = extStart + _glewStrLen(extStart); /* initialize extensions */ #ifdef GLX_VERSION_1_3 - if (glewExperimental || GLXEW_VERSION_1_3) CONST_CAST(GLXEW_VERSION_1_3) = !_glewInit_GLX_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT); + if (glewExperimental || GLXEW_VERSION_1_3) GLXEW_VERSION_1_3 = !_glewInit_GLX_VERSION_1_3(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_VERSION_1_3 */ #ifdef GLX_3DFX_multisample - CONST_CAST(GLXEW_3DFX_multisample) = _glewSearchExtension("GLX_3DFX_multisample", extStart, extEnd); + GLXEW_3DFX_multisample = _glewSearchExtension("GLX_3DFX_multisample", extStart, extEnd); #endif /* GLX_3DFX_multisample */ #ifdef GLX_AMD_gpu_association - CONST_CAST(GLXEW_AMD_gpu_association) = _glewSearchExtension("GLX_AMD_gpu_association", extStart, extEnd); - if (glewExperimental || GLXEW_AMD_gpu_association) CONST_CAST(GLXEW_AMD_gpu_association) = !_glewInit_GLX_AMD_gpu_association(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_AMD_gpu_association = _glewSearchExtension("GLX_AMD_gpu_association", extStart, extEnd); + if (glewExperimental || GLXEW_AMD_gpu_association) GLXEW_AMD_gpu_association = !_glewInit_GLX_AMD_gpu_association(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_AMD_gpu_association */ #ifdef GLX_ARB_create_context - CONST_CAST(GLXEW_ARB_create_context) = _glewSearchExtension("GLX_ARB_create_context", extStart, extEnd); - if (glewExperimental || GLXEW_ARB_create_context) CONST_CAST(GLXEW_ARB_create_context) = !_glewInit_GLX_ARB_create_context(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_ARB_create_context = _glewSearchExtension("GLX_ARB_create_context", extStart, extEnd); + if (glewExperimental || GLXEW_ARB_create_context) GLXEW_ARB_create_context = !_glewInit_GLX_ARB_create_context(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_ARB_create_context */ #ifdef GLX_ARB_create_context_profile - CONST_CAST(GLXEW_ARB_create_context_profile) = _glewSearchExtension("GLX_ARB_create_context_profile", extStart, extEnd); + GLXEW_ARB_create_context_profile = _glewSearchExtension("GLX_ARB_create_context_profile", extStart, extEnd); #endif /* GLX_ARB_create_context_profile */ #ifdef GLX_ARB_create_context_robustness - CONST_CAST(GLXEW_ARB_create_context_robustness) = _glewSearchExtension("GLX_ARB_create_context_robustness", extStart, extEnd); + GLXEW_ARB_create_context_robustness = _glewSearchExtension("GLX_ARB_create_context_robustness", extStart, extEnd); #endif /* GLX_ARB_create_context_robustness */ #ifdef GLX_ARB_fbconfig_float - CONST_CAST(GLXEW_ARB_fbconfig_float) = _glewSearchExtension("GLX_ARB_fbconfig_float", extStart, extEnd); + GLXEW_ARB_fbconfig_float = _glewSearchExtension("GLX_ARB_fbconfig_float", extStart, extEnd); #endif /* GLX_ARB_fbconfig_float */ #ifdef GLX_ARB_framebuffer_sRGB - CONST_CAST(GLXEW_ARB_framebuffer_sRGB) = _glewSearchExtension("GLX_ARB_framebuffer_sRGB", extStart, extEnd); + GLXEW_ARB_framebuffer_sRGB = _glewSearchExtension("GLX_ARB_framebuffer_sRGB", extStart, extEnd); #endif /* GLX_ARB_framebuffer_sRGB */ #ifdef GLX_ARB_get_proc_address - CONST_CAST(GLXEW_ARB_get_proc_address) = _glewSearchExtension("GLX_ARB_get_proc_address", extStart, extEnd); + GLXEW_ARB_get_proc_address = _glewSearchExtension("GLX_ARB_get_proc_address", extStart, extEnd); #endif /* GLX_ARB_get_proc_address */ #ifdef GLX_ARB_multisample - CONST_CAST(GLXEW_ARB_multisample) = _glewSearchExtension("GLX_ARB_multisample", extStart, extEnd); + GLXEW_ARB_multisample = _glewSearchExtension("GLX_ARB_multisample", extStart, extEnd); #endif /* GLX_ARB_multisample */ #ifdef GLX_ARB_robustness_application_isolation - CONST_CAST(GLXEW_ARB_robustness_application_isolation) = _glewSearchExtension("GLX_ARB_robustness_application_isolation", extStart, extEnd); + GLXEW_ARB_robustness_application_isolation = _glewSearchExtension("GLX_ARB_robustness_application_isolation", extStart, extEnd); #endif /* GLX_ARB_robustness_application_isolation */ #ifdef GLX_ARB_robustness_share_group_isolation - CONST_CAST(GLXEW_ARB_robustness_share_group_isolation) = _glewSearchExtension("GLX_ARB_robustness_share_group_isolation", extStart, extEnd); + GLXEW_ARB_robustness_share_group_isolation = _glewSearchExtension("GLX_ARB_robustness_share_group_isolation", extStart, extEnd); #endif /* GLX_ARB_robustness_share_group_isolation */ #ifdef GLX_ARB_vertex_buffer_object - CONST_CAST(GLXEW_ARB_vertex_buffer_object) = _glewSearchExtension("GLX_ARB_vertex_buffer_object", extStart, extEnd); + GLXEW_ARB_vertex_buffer_object = _glewSearchExtension("GLX_ARB_vertex_buffer_object", extStart, extEnd); #endif /* GLX_ARB_vertex_buffer_object */ #ifdef GLX_ATI_pixel_format_float - CONST_CAST(GLXEW_ATI_pixel_format_float) = _glewSearchExtension("GLX_ATI_pixel_format_float", extStart, extEnd); + GLXEW_ATI_pixel_format_float = _glewSearchExtension("GLX_ATI_pixel_format_float", extStart, extEnd); #endif /* GLX_ATI_pixel_format_float */ #ifdef GLX_ATI_render_texture - CONST_CAST(GLXEW_ATI_render_texture) = _glewSearchExtension("GLX_ATI_render_texture", extStart, extEnd); - if (glewExperimental || GLXEW_ATI_render_texture) CONST_CAST(GLXEW_ATI_render_texture) = !_glewInit_GLX_ATI_render_texture(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_ATI_render_texture = _glewSearchExtension("GLX_ATI_render_texture", extStart, extEnd); + if (glewExperimental || GLXEW_ATI_render_texture) GLXEW_ATI_render_texture = !_glewInit_GLX_ATI_render_texture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_ATI_render_texture */ #ifdef GLX_EXT_buffer_age - CONST_CAST(GLXEW_EXT_buffer_age) = _glewSearchExtension("GLX_EXT_buffer_age", extStart, extEnd); + GLXEW_EXT_buffer_age = _glewSearchExtension("GLX_EXT_buffer_age", extStart, extEnd); #endif /* GLX_EXT_buffer_age */ #ifdef GLX_EXT_create_context_es2_profile - CONST_CAST(GLXEW_EXT_create_context_es2_profile) = _glewSearchExtension("GLX_EXT_create_context_es2_profile", extStart, extEnd); + GLXEW_EXT_create_context_es2_profile = _glewSearchExtension("GLX_EXT_create_context_es2_profile", extStart, extEnd); #endif /* GLX_EXT_create_context_es2_profile */ #ifdef GLX_EXT_create_context_es_profile - CONST_CAST(GLXEW_EXT_create_context_es_profile) = _glewSearchExtension("GLX_EXT_create_context_es_profile", extStart, extEnd); + GLXEW_EXT_create_context_es_profile = _glewSearchExtension("GLX_EXT_create_context_es_profile", extStart, extEnd); #endif /* GLX_EXT_create_context_es_profile */ #ifdef GLX_EXT_fbconfig_packed_float - CONST_CAST(GLXEW_EXT_fbconfig_packed_float) = _glewSearchExtension("GLX_EXT_fbconfig_packed_float", extStart, extEnd); + GLXEW_EXT_fbconfig_packed_float = _glewSearchExtension("GLX_EXT_fbconfig_packed_float", extStart, extEnd); #endif /* GLX_EXT_fbconfig_packed_float */ #ifdef GLX_EXT_framebuffer_sRGB - CONST_CAST(GLXEW_EXT_framebuffer_sRGB) = _glewSearchExtension("GLX_EXT_framebuffer_sRGB", extStart, extEnd); + GLXEW_EXT_framebuffer_sRGB = _glewSearchExtension("GLX_EXT_framebuffer_sRGB", extStart, extEnd); #endif /* GLX_EXT_framebuffer_sRGB */ #ifdef GLX_EXT_import_context - CONST_CAST(GLXEW_EXT_import_context) = _glewSearchExtension("GLX_EXT_import_context", extStart, extEnd); - if (glewExperimental || GLXEW_EXT_import_context) CONST_CAST(GLXEW_EXT_import_context) = !_glewInit_GLX_EXT_import_context(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_EXT_import_context = _glewSearchExtension("GLX_EXT_import_context", extStart, extEnd); + if (glewExperimental || GLXEW_EXT_import_context) GLXEW_EXT_import_context = !_glewInit_GLX_EXT_import_context(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_EXT_import_context */ #ifdef GLX_EXT_scene_marker - CONST_CAST(GLXEW_EXT_scene_marker) = _glewSearchExtension("GLX_EXT_scene_marker", extStart, extEnd); + GLXEW_EXT_scene_marker = _glewSearchExtension("GLX_EXT_scene_marker", extStart, extEnd); #endif /* GLX_EXT_scene_marker */ +#ifdef GLX_EXT_stereo_tree + GLXEW_EXT_stereo_tree = _glewSearchExtension("GLX_EXT_stereo_tree", extStart, extEnd); +#endif /* GLX_EXT_stereo_tree */ #ifdef GLX_EXT_swap_control - CONST_CAST(GLXEW_EXT_swap_control) = _glewSearchExtension("GLX_EXT_swap_control", extStart, extEnd); - if (glewExperimental || GLXEW_EXT_swap_control) CONST_CAST(GLXEW_EXT_swap_control) = !_glewInit_GLX_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_EXT_swap_control = _glewSearchExtension("GLX_EXT_swap_control", extStart, extEnd); + if (glewExperimental || GLXEW_EXT_swap_control) GLXEW_EXT_swap_control = !_glewInit_GLX_EXT_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_EXT_swap_control */ #ifdef GLX_EXT_swap_control_tear - CONST_CAST(GLXEW_EXT_swap_control_tear) = _glewSearchExtension("GLX_EXT_swap_control_tear", extStart, extEnd); + GLXEW_EXT_swap_control_tear = _glewSearchExtension("GLX_EXT_swap_control_tear", extStart, extEnd); #endif /* GLX_EXT_swap_control_tear */ #ifdef GLX_EXT_texture_from_pixmap - CONST_CAST(GLXEW_EXT_texture_from_pixmap) = _glewSearchExtension("GLX_EXT_texture_from_pixmap", extStart, extEnd); - if (glewExperimental || GLXEW_EXT_texture_from_pixmap) CONST_CAST(GLXEW_EXT_texture_from_pixmap) = !_glewInit_GLX_EXT_texture_from_pixmap(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_EXT_texture_from_pixmap = _glewSearchExtension("GLX_EXT_texture_from_pixmap", extStart, extEnd); + if (glewExperimental || GLXEW_EXT_texture_from_pixmap) GLXEW_EXT_texture_from_pixmap = !_glewInit_GLX_EXT_texture_from_pixmap(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_EXT_texture_from_pixmap */ #ifdef GLX_EXT_visual_info - CONST_CAST(GLXEW_EXT_visual_info) = _glewSearchExtension("GLX_EXT_visual_info", extStart, extEnd); + GLXEW_EXT_visual_info = _glewSearchExtension("GLX_EXT_visual_info", extStart, extEnd); #endif /* GLX_EXT_visual_info */ #ifdef GLX_EXT_visual_rating - CONST_CAST(GLXEW_EXT_visual_rating) = _glewSearchExtension("GLX_EXT_visual_rating", extStart, extEnd); + GLXEW_EXT_visual_rating = _glewSearchExtension("GLX_EXT_visual_rating", extStart, extEnd); #endif /* GLX_EXT_visual_rating */ #ifdef GLX_INTEL_swap_event - CONST_CAST(GLXEW_INTEL_swap_event) = _glewSearchExtension("GLX_INTEL_swap_event", extStart, extEnd); + GLXEW_INTEL_swap_event = _glewSearchExtension("GLX_INTEL_swap_event", extStart, extEnd); #endif /* GLX_INTEL_swap_event */ #ifdef GLX_MESA_agp_offset - CONST_CAST(GLXEW_MESA_agp_offset) = _glewSearchExtension("GLX_MESA_agp_offset", extStart, extEnd); - if (glewExperimental || GLXEW_MESA_agp_offset) CONST_CAST(GLXEW_MESA_agp_offset) = !_glewInit_GLX_MESA_agp_offset(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_MESA_agp_offset = _glewSearchExtension("GLX_MESA_agp_offset", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_agp_offset) GLXEW_MESA_agp_offset = !_glewInit_GLX_MESA_agp_offset(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_MESA_agp_offset */ #ifdef GLX_MESA_copy_sub_buffer - CONST_CAST(GLXEW_MESA_copy_sub_buffer) = _glewSearchExtension("GLX_MESA_copy_sub_buffer", extStart, extEnd); - if (glewExperimental || GLXEW_MESA_copy_sub_buffer) CONST_CAST(GLXEW_MESA_copy_sub_buffer) = !_glewInit_GLX_MESA_copy_sub_buffer(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_MESA_copy_sub_buffer = _glewSearchExtension("GLX_MESA_copy_sub_buffer", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_copy_sub_buffer) GLXEW_MESA_copy_sub_buffer = !_glewInit_GLX_MESA_copy_sub_buffer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_MESA_copy_sub_buffer */ #ifdef GLX_MESA_pixmap_colormap - CONST_CAST(GLXEW_MESA_pixmap_colormap) = _glewSearchExtension("GLX_MESA_pixmap_colormap", extStart, extEnd); - if (glewExperimental || GLXEW_MESA_pixmap_colormap) CONST_CAST(GLXEW_MESA_pixmap_colormap) = !_glewInit_GLX_MESA_pixmap_colormap(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_MESA_pixmap_colormap = _glewSearchExtension("GLX_MESA_pixmap_colormap", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_pixmap_colormap) GLXEW_MESA_pixmap_colormap = !_glewInit_GLX_MESA_pixmap_colormap(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_MESA_pixmap_colormap */ +#ifdef GLX_MESA_query_renderer + GLXEW_MESA_query_renderer = _glewSearchExtension("GLX_MESA_query_renderer", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_query_renderer) GLXEW_MESA_query_renderer = !_glewInit_GLX_MESA_query_renderer(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_MESA_query_renderer */ #ifdef GLX_MESA_release_buffers - CONST_CAST(GLXEW_MESA_release_buffers) = _glewSearchExtension("GLX_MESA_release_buffers", extStart, extEnd); - if (glewExperimental || GLXEW_MESA_release_buffers) CONST_CAST(GLXEW_MESA_release_buffers) = !_glewInit_GLX_MESA_release_buffers(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_MESA_release_buffers = _glewSearchExtension("GLX_MESA_release_buffers", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_release_buffers) GLXEW_MESA_release_buffers = !_glewInit_GLX_MESA_release_buffers(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_MESA_release_buffers */ #ifdef GLX_MESA_set_3dfx_mode - CONST_CAST(GLXEW_MESA_set_3dfx_mode) = _glewSearchExtension("GLX_MESA_set_3dfx_mode", extStart, extEnd); - if (glewExperimental || GLXEW_MESA_set_3dfx_mode) CONST_CAST(GLXEW_MESA_set_3dfx_mode) = !_glewInit_GLX_MESA_set_3dfx_mode(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_MESA_set_3dfx_mode = _glewSearchExtension("GLX_MESA_set_3dfx_mode", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_set_3dfx_mode) GLXEW_MESA_set_3dfx_mode = !_glewInit_GLX_MESA_set_3dfx_mode(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_MESA_set_3dfx_mode */ #ifdef GLX_MESA_swap_control - CONST_CAST(GLXEW_MESA_swap_control) = _glewSearchExtension("GLX_MESA_swap_control", extStart, extEnd); - if (glewExperimental || GLXEW_MESA_swap_control) CONST_CAST(GLXEW_MESA_swap_control) = !_glewInit_GLX_MESA_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_MESA_swap_control = _glewSearchExtension("GLX_MESA_swap_control", extStart, extEnd); + if (glewExperimental || GLXEW_MESA_swap_control) GLXEW_MESA_swap_control = !_glewInit_GLX_MESA_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_MESA_swap_control */ #ifdef GLX_NV_copy_image - CONST_CAST(GLXEW_NV_copy_image) = _glewSearchExtension("GLX_NV_copy_image", extStart, extEnd); - if (glewExperimental || GLXEW_NV_copy_image) CONST_CAST(GLXEW_NV_copy_image) = !_glewInit_GLX_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_NV_copy_image = _glewSearchExtension("GLX_NV_copy_image", extStart, extEnd); + if (glewExperimental || GLXEW_NV_copy_image) GLXEW_NV_copy_image = !_glewInit_GLX_NV_copy_image(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_NV_copy_image */ +#ifdef GLX_NV_delay_before_swap + GLXEW_NV_delay_before_swap = _glewSearchExtension("GLX_NV_delay_before_swap", extStart, extEnd); + if (glewExperimental || GLXEW_NV_delay_before_swap) GLXEW_NV_delay_before_swap = !_glewInit_GLX_NV_delay_before_swap(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_NV_delay_before_swap */ #ifdef GLX_NV_float_buffer - CONST_CAST(GLXEW_NV_float_buffer) = _glewSearchExtension("GLX_NV_float_buffer", extStart, extEnd); + GLXEW_NV_float_buffer = _glewSearchExtension("GLX_NV_float_buffer", extStart, extEnd); #endif /* GLX_NV_float_buffer */ #ifdef GLX_NV_multisample_coverage - CONST_CAST(GLXEW_NV_multisample_coverage) = _glewSearchExtension("GLX_NV_multisample_coverage", extStart, extEnd); + GLXEW_NV_multisample_coverage = _glewSearchExtension("GLX_NV_multisample_coverage", extStart, extEnd); #endif /* GLX_NV_multisample_coverage */ #ifdef GLX_NV_present_video - CONST_CAST(GLXEW_NV_present_video) = _glewSearchExtension("GLX_NV_present_video", extStart, extEnd); - if (glewExperimental || GLXEW_NV_present_video) CONST_CAST(GLXEW_NV_present_video) = !_glewInit_GLX_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_NV_present_video = _glewSearchExtension("GLX_NV_present_video", extStart, extEnd); + if (glewExperimental || GLXEW_NV_present_video) GLXEW_NV_present_video = !_glewInit_GLX_NV_present_video(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_NV_present_video */ #ifdef GLX_NV_swap_group - CONST_CAST(GLXEW_NV_swap_group) = _glewSearchExtension("GLX_NV_swap_group", extStart, extEnd); - if (glewExperimental || GLXEW_NV_swap_group) CONST_CAST(GLXEW_NV_swap_group) = !_glewInit_GLX_NV_swap_group(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_NV_swap_group = _glewSearchExtension("GLX_NV_swap_group", extStart, extEnd); + if (glewExperimental || GLXEW_NV_swap_group) GLXEW_NV_swap_group = !_glewInit_GLX_NV_swap_group(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_NV_swap_group */ #ifdef GLX_NV_vertex_array_range - CONST_CAST(GLXEW_NV_vertex_array_range) = _glewSearchExtension("GLX_NV_vertex_array_range", extStart, extEnd); - if (glewExperimental || GLXEW_NV_vertex_array_range) CONST_CAST(GLXEW_NV_vertex_array_range) = !_glewInit_GLX_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_NV_vertex_array_range = _glewSearchExtension("GLX_NV_vertex_array_range", extStart, extEnd); + if (glewExperimental || GLXEW_NV_vertex_array_range) GLXEW_NV_vertex_array_range = !_glewInit_GLX_NV_vertex_array_range(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_NV_vertex_array_range */ #ifdef GLX_NV_video_capture - CONST_CAST(GLXEW_NV_video_capture) = _glewSearchExtension("GLX_NV_video_capture", extStart, extEnd); - if (glewExperimental || GLXEW_NV_video_capture) CONST_CAST(GLXEW_NV_video_capture) = !_glewInit_GLX_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_NV_video_capture = _glewSearchExtension("GLX_NV_video_capture", extStart, extEnd); + if (glewExperimental || GLXEW_NV_video_capture) GLXEW_NV_video_capture = !_glewInit_GLX_NV_video_capture(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_NV_video_capture */ -#ifdef GLX_NV_video_output - CONST_CAST(GLXEW_NV_video_output) = _glewSearchExtension("GLX_NV_video_output", extStart, extEnd); - if (glewExperimental || GLXEW_NV_video_output) CONST_CAST(GLXEW_NV_video_output) = !_glewInit_GLX_NV_video_output(GLEW_CONTEXT_ARG_VAR_INIT); -#endif /* GLX_NV_video_output */ +#ifdef GLX_NV_video_out + GLXEW_NV_video_out = _glewSearchExtension("GLX_NV_video_out", extStart, extEnd); + if (glewExperimental || GLXEW_NV_video_out) GLXEW_NV_video_out = !_glewInit_GLX_NV_video_out(GLEW_CONTEXT_ARG_VAR_INIT); +#endif /* GLX_NV_video_out */ #ifdef GLX_OML_swap_method - CONST_CAST(GLXEW_OML_swap_method) = _glewSearchExtension("GLX_OML_swap_method", extStart, extEnd); + GLXEW_OML_swap_method = _glewSearchExtension("GLX_OML_swap_method", extStart, extEnd); #endif /* GLX_OML_swap_method */ #ifdef GLX_OML_sync_control - CONST_CAST(GLXEW_OML_sync_control) = _glewSearchExtension("GLX_OML_sync_control", extStart, extEnd); - if (glewExperimental || GLXEW_OML_sync_control) CONST_CAST(GLXEW_OML_sync_control) = !_glewInit_GLX_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_OML_sync_control = _glewSearchExtension("GLX_OML_sync_control", extStart, extEnd); + if (glewExperimental || GLXEW_OML_sync_control) GLXEW_OML_sync_control = !_glewInit_GLX_OML_sync_control(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_OML_sync_control */ #ifdef GLX_SGIS_blended_overlay - CONST_CAST(GLXEW_SGIS_blended_overlay) = _glewSearchExtension("GLX_SGIS_blended_overlay", extStart, extEnd); + GLXEW_SGIS_blended_overlay = _glewSearchExtension("GLX_SGIS_blended_overlay", extStart, extEnd); #endif /* GLX_SGIS_blended_overlay */ #ifdef GLX_SGIS_color_range - CONST_CAST(GLXEW_SGIS_color_range) = _glewSearchExtension("GLX_SGIS_color_range", extStart, extEnd); + GLXEW_SGIS_color_range = _glewSearchExtension("GLX_SGIS_color_range", extStart, extEnd); #endif /* GLX_SGIS_color_range */ #ifdef GLX_SGIS_multisample - CONST_CAST(GLXEW_SGIS_multisample) = _glewSearchExtension("GLX_SGIS_multisample", extStart, extEnd); + GLXEW_SGIS_multisample = _glewSearchExtension("GLX_SGIS_multisample", extStart, extEnd); #endif /* GLX_SGIS_multisample */ #ifdef GLX_SGIS_shared_multisample - CONST_CAST(GLXEW_SGIS_shared_multisample) = _glewSearchExtension("GLX_SGIS_shared_multisample", extStart, extEnd); + GLXEW_SGIS_shared_multisample = _glewSearchExtension("GLX_SGIS_shared_multisample", extStart, extEnd); #endif /* GLX_SGIS_shared_multisample */ #ifdef GLX_SGIX_fbconfig - CONST_CAST(GLXEW_SGIX_fbconfig) = _glewSearchExtension("GLX_SGIX_fbconfig", extStart, extEnd); - if (glewExperimental || GLXEW_SGIX_fbconfig) CONST_CAST(GLXEW_SGIX_fbconfig) = !_glewInit_GLX_SGIX_fbconfig(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SGIX_fbconfig = _glewSearchExtension("GLX_SGIX_fbconfig", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_fbconfig) GLXEW_SGIX_fbconfig = !_glewInit_GLX_SGIX_fbconfig(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SGIX_fbconfig */ #ifdef GLX_SGIX_hyperpipe - CONST_CAST(GLXEW_SGIX_hyperpipe) = _glewSearchExtension("GLX_SGIX_hyperpipe", extStart, extEnd); - if (glewExperimental || GLXEW_SGIX_hyperpipe) CONST_CAST(GLXEW_SGIX_hyperpipe) = !_glewInit_GLX_SGIX_hyperpipe(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SGIX_hyperpipe = _glewSearchExtension("GLX_SGIX_hyperpipe", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_hyperpipe) GLXEW_SGIX_hyperpipe = !_glewInit_GLX_SGIX_hyperpipe(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SGIX_hyperpipe */ #ifdef GLX_SGIX_pbuffer - CONST_CAST(GLXEW_SGIX_pbuffer) = _glewSearchExtension("GLX_SGIX_pbuffer", extStart, extEnd); - if (glewExperimental || GLXEW_SGIX_pbuffer) CONST_CAST(GLXEW_SGIX_pbuffer) = !_glewInit_GLX_SGIX_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SGIX_pbuffer = _glewSearchExtension("GLX_SGIX_pbuffer", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_pbuffer) GLXEW_SGIX_pbuffer = !_glewInit_GLX_SGIX_pbuffer(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SGIX_pbuffer */ #ifdef GLX_SGIX_swap_barrier - CONST_CAST(GLXEW_SGIX_swap_barrier) = _glewSearchExtension("GLX_SGIX_swap_barrier", extStart, extEnd); - if (glewExperimental || GLXEW_SGIX_swap_barrier) CONST_CAST(GLXEW_SGIX_swap_barrier) = !_glewInit_GLX_SGIX_swap_barrier(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SGIX_swap_barrier = _glewSearchExtension("GLX_SGIX_swap_barrier", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_swap_barrier) GLXEW_SGIX_swap_barrier = !_glewInit_GLX_SGIX_swap_barrier(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SGIX_swap_barrier */ #ifdef GLX_SGIX_swap_group - CONST_CAST(GLXEW_SGIX_swap_group) = _glewSearchExtension("GLX_SGIX_swap_group", extStart, extEnd); - if (glewExperimental || GLXEW_SGIX_swap_group) CONST_CAST(GLXEW_SGIX_swap_group) = !_glewInit_GLX_SGIX_swap_group(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SGIX_swap_group = _glewSearchExtension("GLX_SGIX_swap_group", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_swap_group) GLXEW_SGIX_swap_group = !_glewInit_GLX_SGIX_swap_group(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SGIX_swap_group */ #ifdef GLX_SGIX_video_resize - CONST_CAST(GLXEW_SGIX_video_resize) = _glewSearchExtension("GLX_SGIX_video_resize", extStart, extEnd); - if (glewExperimental || GLXEW_SGIX_video_resize) CONST_CAST(GLXEW_SGIX_video_resize) = !_glewInit_GLX_SGIX_video_resize(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SGIX_video_resize = _glewSearchExtension("GLX_SGIX_video_resize", extStart, extEnd); + if (glewExperimental || GLXEW_SGIX_video_resize) GLXEW_SGIX_video_resize = !_glewInit_GLX_SGIX_video_resize(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SGIX_video_resize */ #ifdef GLX_SGIX_visual_select_group - CONST_CAST(GLXEW_SGIX_visual_select_group) = _glewSearchExtension("GLX_SGIX_visual_select_group", extStart, extEnd); + GLXEW_SGIX_visual_select_group = _glewSearchExtension("GLX_SGIX_visual_select_group", extStart, extEnd); #endif /* GLX_SGIX_visual_select_group */ #ifdef GLX_SGI_cushion - CONST_CAST(GLXEW_SGI_cushion) = _glewSearchExtension("GLX_SGI_cushion", extStart, extEnd); - if (glewExperimental || GLXEW_SGI_cushion) CONST_CAST(GLXEW_SGI_cushion) = !_glewInit_GLX_SGI_cushion(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SGI_cushion = _glewSearchExtension("GLX_SGI_cushion", extStart, extEnd); + if (glewExperimental || GLXEW_SGI_cushion) GLXEW_SGI_cushion = !_glewInit_GLX_SGI_cushion(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SGI_cushion */ #ifdef GLX_SGI_make_current_read - CONST_CAST(GLXEW_SGI_make_current_read) = _glewSearchExtension("GLX_SGI_make_current_read", extStart, extEnd); - if (glewExperimental || GLXEW_SGI_make_current_read) CONST_CAST(GLXEW_SGI_make_current_read) = !_glewInit_GLX_SGI_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SGI_make_current_read = _glewSearchExtension("GLX_SGI_make_current_read", extStart, extEnd); + if (glewExperimental || GLXEW_SGI_make_current_read) GLXEW_SGI_make_current_read = !_glewInit_GLX_SGI_make_current_read(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SGI_make_current_read */ #ifdef GLX_SGI_swap_control - CONST_CAST(GLXEW_SGI_swap_control) = _glewSearchExtension("GLX_SGI_swap_control", extStart, extEnd); - if (glewExperimental || GLXEW_SGI_swap_control) CONST_CAST(GLXEW_SGI_swap_control) = !_glewInit_GLX_SGI_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SGI_swap_control = _glewSearchExtension("GLX_SGI_swap_control", extStart, extEnd); + if (glewExperimental || GLXEW_SGI_swap_control) GLXEW_SGI_swap_control = !_glewInit_GLX_SGI_swap_control(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SGI_swap_control */ #ifdef GLX_SGI_video_sync - CONST_CAST(GLXEW_SGI_video_sync) = _glewSearchExtension("GLX_SGI_video_sync", extStart, extEnd); - if (glewExperimental || GLXEW_SGI_video_sync) CONST_CAST(GLXEW_SGI_video_sync) = !_glewInit_GLX_SGI_video_sync(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SGI_video_sync = _glewSearchExtension("GLX_SGI_video_sync", extStart, extEnd); + if (glewExperimental || GLXEW_SGI_video_sync) GLXEW_SGI_video_sync = !_glewInit_GLX_SGI_video_sync(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SGI_video_sync */ #ifdef GLX_SUN_get_transparent_index - CONST_CAST(GLXEW_SUN_get_transparent_index) = _glewSearchExtension("GLX_SUN_get_transparent_index", extStart, extEnd); - if (glewExperimental || GLXEW_SUN_get_transparent_index) CONST_CAST(GLXEW_SUN_get_transparent_index) = !_glewInit_GLX_SUN_get_transparent_index(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SUN_get_transparent_index = _glewSearchExtension("GLX_SUN_get_transparent_index", extStart, extEnd); + if (glewExperimental || GLXEW_SUN_get_transparent_index) GLXEW_SUN_get_transparent_index = !_glewInit_GLX_SUN_get_transparent_index(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SUN_get_transparent_index */ #ifdef GLX_SUN_video_resize - CONST_CAST(GLXEW_SUN_video_resize) = _glewSearchExtension("GLX_SUN_video_resize", extStart, extEnd); - if (glewExperimental || GLXEW_SUN_video_resize) CONST_CAST(GLXEW_SUN_video_resize) = !_glewInit_GLX_SUN_video_resize(GLEW_CONTEXT_ARG_VAR_INIT); + GLXEW_SUN_video_resize = _glewSearchExtension("GLX_SUN_video_resize", extStart, extEnd); + if (glewExperimental || GLXEW_SUN_video_resize) GLXEW_SUN_video_resize = !_glewInit_GLX_SUN_video_resize(GLEW_CONTEXT_ARG_VAR_INIT); #endif /* GLX_SUN_video_resize */ return GLEW_OK; } -#endif /* !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) */ +#endif /* !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) */ /* ------------------------------------------------------------------------ */ @@ -13446,8 +13759,8 @@ const GLubyte * GLEWAPIENTRY glewGetErrorString (GLenum error) (const GLubyte*)"GLX 1.2 and up are not supported", (const GLubyte*)"Unknown error" }; - const int max_error = sizeof(_glewErrorString)/sizeof(*_glewErrorString) - 1; - return _glewErrorString[(int)error > max_error ? max_error : (int)error]; + const size_t max_error = sizeof(_glewErrorString)/sizeof(*_glewErrorString) - 1; + return _glewErrorString[(size_t)error > max_error ? max_error : (size_t)error]; } const GLubyte * GLEWAPIENTRY glewGetString (GLenum name) @@ -13460,8 +13773,8 @@ const GLubyte * GLEWAPIENTRY glewGetString (GLenum name) (const GLubyte*)"10", (const GLubyte*)"0" }; - const int max_string = sizeof(_glewString)/sizeof(*_glewString) - 1; - return _glewString[(int)name > max_string ? 0 : (int)name]; + const size_t max_string = sizeof(_glewString)/sizeof(*_glewString) - 1; + return _glewString[(size_t)name > max_string ? 0 : (size_t)name]; } /* ------------------------------------------------------------------------ */ @@ -13472,7 +13785,7 @@ GLboolean glewExperimental = GL_FALSE; #if defined(_WIN32) extern GLenum GLEWAPIENTRY wglewContextInit (void); -#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) +#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) extern GLenum GLEWAPIENTRY glxewContextInit (void); #endif /* _WIN32 */ @@ -13483,7 +13796,7 @@ GLenum GLEWAPIENTRY glewInit (void) if ( r != 0 ) return r; #if defined(_WIN32) return wglewContextInit(); -#elif !defined(__ANDROID__) && !defined(__native_client__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) /* _UNIX */ +#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) /* _UNIX */ return glxewContextInit(); #else return r; @@ -13680,6 +13993,20 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_AMD_gcn_shader + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gcn_shader", 10)) + { + ret = GLEW_AMD_gcn_shader; + continue; + } +#endif +#ifdef GL_AMD_gpu_shader_int64 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"gpu_shader_int64", 16)) + { + ret = GLEW_AMD_gpu_shader_int64; + continue; + } +#endif #ifdef GL_AMD_interleaved_elements if (_glewStrSame3(&pos, &len, (const GLubyte*)"interleaved_elements", 20)) { @@ -13701,6 +14028,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_AMD_occlusion_query_event + if (_glewStrSame3(&pos, &len, (const GLubyte*)"occlusion_query_event", 21)) + { + ret = GLEW_AMD_occlusion_query_event; + continue; + } +#endif #ifdef GL_AMD_performance_monitor if (_glewStrSame3(&pos, &len, (const GLubyte*)"performance_monitor", 19)) { @@ -13736,6 +14070,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_AMD_shader_atomic_counter_ops + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_atomic_counter_ops", 25)) + { + ret = GLEW_AMD_shader_atomic_counter_ops; + continue; + } +#endif #ifdef GL_AMD_shader_stencil_export if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_stencil_export", 21)) { @@ -13743,6 +14084,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_AMD_shader_stencil_value_export + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_stencil_value_export", 27)) + { + ret = GLEW_AMD_shader_stencil_value_export; + continue; + } +#endif #ifdef GL_AMD_shader_trinary_minmax if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_trinary_minmax", 21)) { @@ -13778,6 +14126,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_AMD_transform_feedback4 + if (_glewStrSame3(&pos, &len, (const GLubyte*)"transform_feedback4", 19)) + { + ret = GLEW_AMD_transform_feedback4; + continue; + } +#endif #ifdef GL_AMD_vertex_shader_layer if (_glewStrSame3(&pos, &len, (const GLubyte*)"vertex_shader_layer", 19)) { @@ -15301,6 +15656,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_EXT_debug_label + if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_label", 11)) + { + ret = GLEW_EXT_debug_label; + continue; + } +#endif #ifdef GL_EXT_debug_marker if (_glewStrSame3(&pos, &len, (const GLubyte*)"debug_marker", 12)) { @@ -15581,6 +15943,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_EXT_shader_image_load_formatted + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_image_load_formatted", 27)) + { + ret = GLEW_EXT_shader_image_load_formatted; + continue; + } +#endif #ifdef GL_EXT_shader_image_load_store if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_image_load_store", 23)) { @@ -15588,6 +15957,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_EXT_shader_integer_mix + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_integer_mix", 18)) + { + ret = GLEW_EXT_shader_integer_mix; + continue; + } +#endif #ifdef GL_EXT_shadow_funcs if (_glewStrSame3(&pos, &len, (const GLubyte*)"shadow_funcs", 12)) { @@ -15981,6 +16357,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) } if (_glewStrSame2(&pos, &len, (const GLubyte*)"INTEL_", 6)) { +#ifdef GL_INTEL_fragment_shader_ordering + if (_glewStrSame3(&pos, &len, (const GLubyte*)"fragment_shader_ordering", 24)) + { + ret = GLEW_INTEL_fragment_shader_ordering; + continue; + } +#endif #ifdef GL_INTEL_map_texture if (_glewStrSame3(&pos, &len, (const GLubyte*)"map_texture", 11)) { @@ -15995,6 +16378,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_INTEL_performance_query + if (_glewStrSame3(&pos, &len, (const GLubyte*)"performance_query", 17)) + { + ret = GLEW_INTEL_performance_query; + continue; + } +#endif #ifdef GL_INTEL_texture_scissor if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_scissor", 15)) { @@ -16012,6 +16402,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_KHR_texture_compression_astc_hdr + if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_astc_hdr", 28)) + { + ret = GLEW_KHR_texture_compression_astc_hdr; + continue; + } +#endif #ifdef GL_KHR_texture_compression_astc_ldr if (_glewStrSame3(&pos, &len, (const GLubyte*)"texture_compression_astc_ldr", 28)) { @@ -16440,6 +16837,20 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) continue; } #endif +#ifdef GL_NV_shader_thread_group + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_thread_group", 19)) + { + ret = GLEW_NV_shader_thread_group; + continue; + } +#endif +#ifdef GL_NV_shader_thread_shuffle + if (_glewStrSame3(&pos, &len, (const GLubyte*)"shader_thread_shuffle", 21)) + { + ret = GLEW_NV_shader_thread_shuffle; + continue; + } +#endif #ifdef GL_NV_tessellation_program5 if (_glewStrSame3(&pos, &len, (const GLubyte*)"tessellation_program5", 21)) { @@ -16738,6 +17149,13 @@ GLboolean GLEWAPIENTRY glewIsSupported (const char* name) ret = GLEW_REGAL_log; continue; } +#endif +#ifdef GL_REGAL_proc_address + if (_glewStrSame3(&pos, &len, (const GLubyte*)"proc_address", 12)) + { + ret = GLEW_REGAL_proc_address; + continue; + } #endif } if (_glewStrSame2(&pos, &len, (const GLubyte*)"REND_", 5)) @@ -17529,6 +17947,13 @@ GLboolean GLEWAPIENTRY wglewIsSupported (const char* name) continue; } #endif +#ifdef WGL_NV_delay_before_swap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"delay_before_swap", 17)) + { + ret = WGLEW_NV_delay_before_swap; + continue; + } +#endif #ifdef WGL_NV_float_buffer if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12)) { @@ -17616,7 +18041,7 @@ GLboolean GLEWAPIENTRY wglewIsSupported (const char* name) return ret; } -#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && !defined(__APPLE__) || defined(GLEW_APPLE_GLX) #if defined(GLEW_MX) GLboolean glxewContextIsSupported (const GLXEWContext* ctx, const char* name) @@ -17816,6 +18241,13 @@ GLboolean glxewIsSupported (const char* name) continue; } #endif +#ifdef GLX_EXT_stereo_tree + if (_glewStrSame3(&pos, &len, (const GLubyte*)"stereo_tree", 11)) + { + ret = GLXEW_EXT_stereo_tree; + continue; + } +#endif #ifdef GLX_EXT_swap_control if (_glewStrSame3(&pos, &len, (const GLubyte*)"swap_control", 12)) { @@ -17885,6 +18317,13 @@ GLboolean glxewIsSupported (const char* name) continue; } #endif +#ifdef GLX_MESA_query_renderer + if (_glewStrSame3(&pos, &len, (const GLubyte*)"query_renderer", 14)) + { + ret = GLXEW_MESA_query_renderer; + continue; + } +#endif #ifdef GLX_MESA_release_buffers if (_glewStrSame3(&pos, &len, (const GLubyte*)"release_buffers", 15)) { @@ -17916,6 +18355,13 @@ GLboolean glxewIsSupported (const char* name) continue; } #endif +#ifdef GLX_NV_delay_before_swap + if (_glewStrSame3(&pos, &len, (const GLubyte*)"delay_before_swap", 17)) + { + ret = GLXEW_NV_delay_before_swap; + continue; + } +#endif #ifdef GLX_NV_float_buffer if (_glewStrSame3(&pos, &len, (const GLubyte*)"float_buffer", 12)) { @@ -17958,10 +18404,10 @@ GLboolean glxewIsSupported (const char* name) continue; } #endif -#ifdef GLX_NV_video_output - if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_output", 12)) +#ifdef GLX_NV_video_out + if (_glewStrSame3(&pos, &len, (const GLubyte*)"video_out", 9)) { - ret = GLXEW_NV_video_output; + ret = GLXEW_NV_video_out; continue; } #endif diff --git a/ext/glew/glewinfo.c b/ext/glew/glewinfo.c index ad44f7256c..86ef352ff6 100644 --- a/ext/glew/glewinfo.c +++ b/ext/glew/glewinfo.c @@ -1,5 +1,6 @@ /* ** The OpenGL Extension Wrangler Library +** Copyright (C) 2008-2014, Nigel Stewart ** Copyright (C) 2002-2008, Milan Ikits ** Copyright (C) 2002-2008, Marcelo E. Magallon ** Copyright (C) 2002, Lev Povalahev @@ -35,7 +36,7 @@ #include #if defined(_WIN32) #include -#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +#elif !defined(__APPLE__) && !defined(__HAIKU__) || defined(GLEW_APPLE_GLX) #include #endif @@ -51,7 +52,7 @@ GLEWContext _glewctx; #ifdef _WIN32 WGLEWContext _wglewctx; #define wglewGetContext() (&_wglewctx) -#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +#elif !defined(__APPLE__) && !defined(__HAIKU__) || defined(GLEW_APPLE_GLX) GLXEWContext _glxewctx; #define glxewGetContext() (&_glxewctx) #endif @@ -59,7 +60,7 @@ GLXEWContext _glxewctx; #if defined(_WIN32) GLboolean glewCreateContext (int* pixelformat); -#elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +#elif !defined(__APPLE__) && !defined(__HAIKU__) || defined(GLEW_APPLE_GLX) GLboolean glewCreateContext (const char* display, int* visual); #else GLboolean glewCreateContext (); @@ -632,6 +633,24 @@ static void _glewInfo_GL_AMD_draw_buffers_blend (void) #endif /* GL_AMD_draw_buffers_blend */ +#ifdef GL_AMD_gcn_shader + +static void _glewInfo_GL_AMD_gcn_shader (void) +{ + glewPrintExt("GL_AMD_gcn_shader", GLEW_AMD_gcn_shader, glewIsSupported("GL_AMD_gcn_shader"), glewGetExtension("GL_AMD_gcn_shader")); +} + +#endif /* GL_AMD_gcn_shader */ + +#ifdef GL_AMD_gpu_shader_int64 + +static void _glewInfo_GL_AMD_gpu_shader_int64 (void) +{ + glewPrintExt("GL_AMD_gpu_shader_int64", GLEW_AMD_gpu_shader_int64, glewIsSupported("GL_AMD_gpu_shader_int64"), glewGetExtension("GL_AMD_gpu_shader_int64")); +} + +#endif /* GL_AMD_gpu_shader_int64 */ + #ifdef GL_AMD_interleaved_elements static void _glewInfo_GL_AMD_interleaved_elements (void) @@ -668,6 +687,17 @@ static void _glewInfo_GL_AMD_name_gen_delete (void) #endif /* GL_AMD_name_gen_delete */ +#ifdef GL_AMD_occlusion_query_event + +static void _glewInfo_GL_AMD_occlusion_query_event (void) +{ + glewPrintExt("GL_AMD_occlusion_query_event", GLEW_AMD_occlusion_query_event, glewIsSupported("GL_AMD_occlusion_query_event"), glewGetExtension("GL_AMD_occlusion_query_event")); + + glewInfoFunc("glQueryObjectParameteruiAMD", glQueryObjectParameteruiAMD == NULL); +} + +#endif /* GL_AMD_occlusion_query_event */ + #ifdef GL_AMD_performance_monitor static void _glewInfo_GL_AMD_performance_monitor (void) @@ -727,6 +757,15 @@ static void _glewInfo_GL_AMD_seamless_cubemap_per_texture (void) #endif /* GL_AMD_seamless_cubemap_per_texture */ +#ifdef GL_AMD_shader_atomic_counter_ops + +static void _glewInfo_GL_AMD_shader_atomic_counter_ops (void) +{ + glewPrintExt("GL_AMD_shader_atomic_counter_ops", GLEW_AMD_shader_atomic_counter_ops, glewIsSupported("GL_AMD_shader_atomic_counter_ops"), glewGetExtension("GL_AMD_shader_atomic_counter_ops")); +} + +#endif /* GL_AMD_shader_atomic_counter_ops */ + #ifdef GL_AMD_shader_stencil_export static void _glewInfo_GL_AMD_shader_stencil_export (void) @@ -736,6 +775,15 @@ static void _glewInfo_GL_AMD_shader_stencil_export (void) #endif /* GL_AMD_shader_stencil_export */ +#ifdef GL_AMD_shader_stencil_value_export + +static void _glewInfo_GL_AMD_shader_stencil_value_export (void) +{ + glewPrintExt("GL_AMD_shader_stencil_value_export", GLEW_AMD_shader_stencil_value_export, glewIsSupported("GL_AMD_shader_stencil_value_export"), glewGetExtension("GL_AMD_shader_stencil_value_export")); +} + +#endif /* GL_AMD_shader_stencil_value_export */ + #ifdef GL_AMD_shader_trinary_minmax static void _glewInfo_GL_AMD_shader_trinary_minmax (void) @@ -786,6 +834,15 @@ static void _glewInfo_GL_AMD_transform_feedback3_lines_triangles (void) #endif /* GL_AMD_transform_feedback3_lines_triangles */ +#ifdef GL_AMD_transform_feedback4 + +static void _glewInfo_GL_AMD_transform_feedback4 (void) +{ + glewPrintExt("GL_AMD_transform_feedback4", GLEW_AMD_transform_feedback4, glewIsSupported("GL_AMD_transform_feedback4"), glewGetExtension("GL_AMD_transform_feedback4")); +} + +#endif /* GL_AMD_transform_feedback4 */ + #ifdef GL_AMD_vertex_shader_layer static void _glewInfo_GL_AMD_vertex_shader_layer (void) @@ -2871,6 +2928,12 @@ static void _glewInfo_GL_ARB_vertex_attrib_binding (void) glewPrintExt("GL_ARB_vertex_attrib_binding", GLEW_ARB_vertex_attrib_binding, glewIsSupported("GL_ARB_vertex_attrib_binding"), glewGetExtension("GL_ARB_vertex_attrib_binding")); glewInfoFunc("glBindVertexBuffer", glBindVertexBuffer == NULL); + glewInfoFunc("glVertexArrayBindVertexBufferEXT", glVertexArrayBindVertexBufferEXT == NULL); + glewInfoFunc("glVertexArrayVertexAttribBindingEXT", glVertexArrayVertexAttribBindingEXT == NULL); + glewInfoFunc("glVertexArrayVertexAttribFormatEXT", glVertexArrayVertexAttribFormatEXT == NULL); + glewInfoFunc("glVertexArrayVertexAttribIFormatEXT", glVertexArrayVertexAttribIFormatEXT == NULL); + glewInfoFunc("glVertexArrayVertexAttribLFormatEXT", glVertexArrayVertexAttribLFormatEXT == NULL); + glewInfoFunc("glVertexArrayVertexBindingDivisorEXT", glVertexArrayVertexBindingDivisorEXT == NULL); glewInfoFunc("glVertexAttribBinding", glVertexAttribBinding == NULL); glewInfoFunc("glVertexAttribFormat", glVertexAttribFormat == NULL); glewInfoFunc("glVertexAttribIFormat", glVertexAttribIFormat == NULL); @@ -3611,6 +3674,18 @@ static void _glewInfo_GL_EXT_cull_vertex (void) #endif /* GL_EXT_cull_vertex */ +#ifdef GL_EXT_debug_label + +static void _glewInfo_GL_EXT_debug_label (void) +{ + glewPrintExt("GL_EXT_debug_label", GLEW_EXT_debug_label, glewIsSupported("GL_EXT_debug_label"), glewGetExtension("GL_EXT_debug_label")); + + glewInfoFunc("glGetObjectLabelEXT", glGetObjectLabelEXT == NULL); + glewInfoFunc("glLabelObjectEXT", glLabelObjectEXT == NULL); +} + +#endif /* GL_EXT_debug_label */ + #ifdef GL_EXT_debug_marker static void _glewInfo_GL_EXT_debug_marker (void) @@ -3851,6 +3926,7 @@ static void _glewInfo_GL_EXT_direct_state_access (void) glewInfoFunc("glVertexArrayNormalOffsetEXT", glVertexArrayNormalOffsetEXT == NULL); glewInfoFunc("glVertexArraySecondaryColorOffsetEXT", glVertexArraySecondaryColorOffsetEXT == NULL); glewInfoFunc("glVertexArrayTexCoordOffsetEXT", glVertexArrayTexCoordOffsetEXT == NULL); + glewInfoFunc("glVertexArrayVertexAttribDivisorEXT", glVertexArrayVertexAttribDivisorEXT == NULL); glewInfoFunc("glVertexArrayVertexAttribIOffsetEXT", glVertexArrayVertexAttribIOffsetEXT == NULL); glewInfoFunc("glVertexArrayVertexAttribOffsetEXT", glVertexArrayVertexAttribOffsetEXT == NULL); glewInfoFunc("glVertexArrayVertexOffsetEXT", glVertexArrayVertexOffsetEXT == NULL); @@ -4361,6 +4437,15 @@ static void _glewInfo_GL_EXT_separate_specular_color (void) #endif /* GL_EXT_separate_specular_color */ +#ifdef GL_EXT_shader_image_load_formatted + +static void _glewInfo_GL_EXT_shader_image_load_formatted (void) +{ + glewPrintExt("GL_EXT_shader_image_load_formatted", GLEW_EXT_shader_image_load_formatted, glewIsSupported("GL_EXT_shader_image_load_formatted"), glewGetExtension("GL_EXT_shader_image_load_formatted")); +} + +#endif /* GL_EXT_shader_image_load_formatted */ + #ifdef GL_EXT_shader_image_load_store static void _glewInfo_GL_EXT_shader_image_load_store (void) @@ -4373,6 +4458,15 @@ static void _glewInfo_GL_EXT_shader_image_load_store (void) #endif /* GL_EXT_shader_image_load_store */ +#ifdef GL_EXT_shader_integer_mix + +static void _glewInfo_GL_EXT_shader_integer_mix (void) +{ + glewPrintExt("GL_EXT_shader_integer_mix", GLEW_EXT_shader_integer_mix, glewIsSupported("GL_EXT_shader_integer_mix"), glewGetExtension("GL_EXT_shader_integer_mix")); +} + +#endif /* GL_EXT_shader_integer_mix */ + #ifdef GL_EXT_shadow_funcs static void _glewInfo_GL_EXT_shadow_funcs (void) @@ -4991,6 +5085,15 @@ static void _glewInfo_GL_INGR_interlace_read (void) #endif /* GL_INGR_interlace_read */ +#ifdef GL_INTEL_fragment_shader_ordering + +static void _glewInfo_GL_INTEL_fragment_shader_ordering (void) +{ + glewPrintExt("GL_INTEL_fragment_shader_ordering", GLEW_INTEL_fragment_shader_ordering, glewIsSupported("GL_INTEL_fragment_shader_ordering"), glewGetExtension("GL_INTEL_fragment_shader_ordering")); +} + +#endif /* GL_INTEL_fragment_shader_ordering */ + #ifdef GL_INTEL_map_texture static void _glewInfo_GL_INTEL_map_texture (void) @@ -5018,6 +5121,26 @@ static void _glewInfo_GL_INTEL_parallel_arrays (void) #endif /* GL_INTEL_parallel_arrays */ +#ifdef GL_INTEL_performance_query + +static void _glewInfo_GL_INTEL_performance_query (void) +{ + glewPrintExt("GL_INTEL_performance_query", GLEW_INTEL_performance_query, glewIsSupported("GL_INTEL_performance_query"), glewGetExtension("GL_INTEL_performance_query")); + + glewInfoFunc("glBeginPerfQueryINTEL", glBeginPerfQueryINTEL == NULL); + glewInfoFunc("glCreatePerfQueryINTEL", glCreatePerfQueryINTEL == NULL); + glewInfoFunc("glDeletePerfQueryINTEL", glDeletePerfQueryINTEL == NULL); + glewInfoFunc("glEndPerfQueryINTEL", glEndPerfQueryINTEL == NULL); + glewInfoFunc("glGetFirstPerfQueryIdINTEL", glGetFirstPerfQueryIdINTEL == NULL); + glewInfoFunc("glGetNextPerfQueryIdINTEL", glGetNextPerfQueryIdINTEL == NULL); + glewInfoFunc("glGetPerfCounterInfoINTEL", glGetPerfCounterInfoINTEL == NULL); + glewInfoFunc("glGetPerfQueryDataINTEL", glGetPerfQueryDataINTEL == NULL); + glewInfoFunc("glGetPerfQueryIdByNameINTEL", glGetPerfQueryIdByNameINTEL == NULL); + glewInfoFunc("glGetPerfQueryInfoINTEL", glGetPerfQueryInfoINTEL == NULL); +} + +#endif /* GL_INTEL_performance_query */ + #ifdef GL_INTEL_texture_scissor static void _glewInfo_GL_INTEL_texture_scissor (void) @@ -5050,6 +5173,15 @@ static void _glewInfo_GL_KHR_debug (void) #endif /* GL_KHR_debug */ +#ifdef GL_KHR_texture_compression_astc_hdr + +static void _glewInfo_GL_KHR_texture_compression_astc_hdr (void) +{ + glewPrintExt("GL_KHR_texture_compression_astc_hdr", GLEW_KHR_texture_compression_astc_hdr, glewIsSupported("GL_KHR_texture_compression_astc_hdr"), glewGetExtension("GL_KHR_texture_compression_astc_hdr")); +} + +#endif /* GL_KHR_texture_compression_astc_hdr */ + #ifdef GL_KHR_texture_compression_astc_ldr static void _glewInfo_GL_KHR_texture_compression_astc_ldr (void) @@ -5885,6 +6017,24 @@ static void _glewInfo_GL_NV_shader_storage_buffer_object (void) #endif /* GL_NV_shader_storage_buffer_object */ +#ifdef GL_NV_shader_thread_group + +static void _glewInfo_GL_NV_shader_thread_group (void) +{ + glewPrintExt("GL_NV_shader_thread_group", GLEW_NV_shader_thread_group, glewIsSupported("GL_NV_shader_thread_group"), glewGetExtension("GL_NV_shader_thread_group")); +} + +#endif /* GL_NV_shader_thread_group */ + +#ifdef GL_NV_shader_thread_shuffle + +static void _glewInfo_GL_NV_shader_thread_shuffle (void) +{ + glewPrintExt("GL_NV_shader_thread_shuffle", GLEW_NV_shader_thread_shuffle, glewIsSupported("GL_NV_shader_thread_shuffle"), glewGetExtension("GL_NV_shader_thread_shuffle")); +} + +#endif /* GL_NV_shader_thread_shuffle */ + #ifdef GL_NV_tessellation_program5 static void _glewInfo_GL_NV_tessellation_program5 (void) @@ -6468,6 +6618,17 @@ static void _glewInfo_GL_REGAL_log (void) #endif /* GL_REGAL_log */ +#ifdef GL_REGAL_proc_address + +static void _glewInfo_GL_REGAL_proc_address (void) +{ + glewPrintExt("GL_REGAL_proc_address", GLEW_REGAL_proc_address, glewIsSupported("GL_REGAL_proc_address"), glewGetExtension("GL_REGAL_proc_address")); + + glewInfoFunc("glGetProcAddressREGAL", glGetProcAddressREGAL == NULL); +} + +#endif /* GL_REGAL_proc_address */ + #ifdef GL_REND_screen_coordinates static void _glewInfo_GL_REND_screen_coordinates (void) @@ -7637,6 +7798,17 @@ static void _glewInfo_WGL_NV_copy_image (void) #endif /* WGL_NV_copy_image */ +#ifdef WGL_NV_delay_before_swap + +static void _glewInfo_WGL_NV_delay_before_swap (void) +{ + glewPrintExt("WGL_NV_delay_before_swap", WGLEW_NV_delay_before_swap, wglewIsSupported("WGL_NV_delay_before_swap"), wglewGetExtension("WGL_NV_delay_before_swap")); + + glewInfoFunc("wglDelayBeforeSwapNV", wglDelayBeforeSwapNV == NULL); +} + +#endif /* WGL_NV_delay_before_swap */ + #ifdef WGL_NV_float_buffer static void _glewInfo_WGL_NV_float_buffer (void) @@ -8035,6 +8207,15 @@ static void _glewInfo_GLX_EXT_scene_marker (void) #endif /* GLX_EXT_scene_marker */ +#ifdef GLX_EXT_stereo_tree + +static void _glewInfo_GLX_EXT_stereo_tree (void) +{ + glewPrintExt("GLX_EXT_stereo_tree", GLXEW_EXT_stereo_tree, glxewIsSupported("GLX_EXT_stereo_tree"), glxewGetExtension("GLX_EXT_stereo_tree")); +} + +#endif /* GLX_EXT_stereo_tree */ + #ifdef GLX_EXT_swap_control static void _glewInfo_GLX_EXT_swap_control (void) @@ -8127,6 +8308,20 @@ static void _glewInfo_GLX_MESA_pixmap_colormap (void) #endif /* GLX_MESA_pixmap_colormap */ +#ifdef GLX_MESA_query_renderer + +static void _glewInfo_GLX_MESA_query_renderer (void) +{ + glewPrintExt("GLX_MESA_query_renderer", GLXEW_MESA_query_renderer, glxewIsSupported("GLX_MESA_query_renderer"), glxewGetExtension("GLX_MESA_query_renderer")); + + glewInfoFunc("glXQueryCurrentRendererIntegerMESA", glXQueryCurrentRendererIntegerMESA == NULL); + glewInfoFunc("glXQueryCurrentRendererStringMESA", glXQueryCurrentRendererStringMESA == NULL); + glewInfoFunc("glXQueryRendererIntegerMESA", glXQueryRendererIntegerMESA == NULL); + glewInfoFunc("glXQueryRendererStringMESA", glXQueryRendererStringMESA == NULL); +} + +#endif /* GLX_MESA_query_renderer */ + #ifdef GLX_MESA_release_buffers static void _glewInfo_GLX_MESA_release_buffers (void) @@ -8172,6 +8367,17 @@ static void _glewInfo_GLX_NV_copy_image (void) #endif /* GLX_NV_copy_image */ +#ifdef GLX_NV_delay_before_swap + +static void _glewInfo_GLX_NV_delay_before_swap (void) +{ + glewPrintExt("GLX_NV_delay_before_swap", GLXEW_NV_delay_before_swap, glxewIsSupported("GLX_NV_delay_before_swap"), glxewGetExtension("GLX_NV_delay_before_swap")); + + glewInfoFunc("glXDelayBeforeSwapNV", glXDelayBeforeSwapNV == NULL); +} + +#endif /* GLX_NV_delay_before_swap */ + #ifdef GLX_NV_float_buffer static void _glewInfo_GLX_NV_float_buffer (void) @@ -8245,11 +8451,11 @@ static void _glewInfo_GLX_NV_video_capture (void) #endif /* GLX_NV_video_capture */ -#ifdef GLX_NV_video_output +#ifdef GLX_NV_video_out -static void _glewInfo_GLX_NV_video_output (void) +static void _glewInfo_GLX_NV_video_out (void) { - glewPrintExt("GLX_NV_video_output", GLXEW_NV_video_output, glxewIsSupported("GLX_NV_video_output"), glxewGetExtension("GLX_NV_video_output")); + glewPrintExt("GLX_NV_video_out", GLXEW_NV_video_out, glxewIsSupported("GLX_NV_video_out"), glxewGetExtension("GLX_NV_video_out")); glewInfoFunc("glXBindVideoImageNV", glXBindVideoImageNV == NULL); glewInfoFunc("glXGetVideoDeviceNV", glXGetVideoDeviceNV == NULL); @@ -8259,7 +8465,7 @@ static void _glewInfo_GLX_NV_video_output (void) glewInfoFunc("glXSendPbufferToVideoNV", glXSendPbufferToVideoNV == NULL); } -#endif /* GLX_NV_video_output */ +#endif /* GLX_NV_video_out */ #ifdef GLX_OML_swap_method @@ -8567,6 +8773,12 @@ static void glewInfo (void) #ifdef GL_AMD_draw_buffers_blend _glewInfo_GL_AMD_draw_buffers_blend(); #endif /* GL_AMD_draw_buffers_blend */ +#ifdef GL_AMD_gcn_shader + _glewInfo_GL_AMD_gcn_shader(); +#endif /* GL_AMD_gcn_shader */ +#ifdef GL_AMD_gpu_shader_int64 + _glewInfo_GL_AMD_gpu_shader_int64(); +#endif /* GL_AMD_gpu_shader_int64 */ #ifdef GL_AMD_interleaved_elements _glewInfo_GL_AMD_interleaved_elements(); #endif /* GL_AMD_interleaved_elements */ @@ -8576,6 +8788,9 @@ static void glewInfo (void) #ifdef GL_AMD_name_gen_delete _glewInfo_GL_AMD_name_gen_delete(); #endif /* GL_AMD_name_gen_delete */ +#ifdef GL_AMD_occlusion_query_event + _glewInfo_GL_AMD_occlusion_query_event(); +#endif /* GL_AMD_occlusion_query_event */ #ifdef GL_AMD_performance_monitor _glewInfo_GL_AMD_performance_monitor(); #endif /* GL_AMD_performance_monitor */ @@ -8591,9 +8806,15 @@ static void glewInfo (void) #ifdef GL_AMD_seamless_cubemap_per_texture _glewInfo_GL_AMD_seamless_cubemap_per_texture(); #endif /* GL_AMD_seamless_cubemap_per_texture */ +#ifdef GL_AMD_shader_atomic_counter_ops + _glewInfo_GL_AMD_shader_atomic_counter_ops(); +#endif /* GL_AMD_shader_atomic_counter_ops */ #ifdef GL_AMD_shader_stencil_export _glewInfo_GL_AMD_shader_stencil_export(); #endif /* GL_AMD_shader_stencil_export */ +#ifdef GL_AMD_shader_stencil_value_export + _glewInfo_GL_AMD_shader_stencil_value_export(); +#endif /* GL_AMD_shader_stencil_value_export */ #ifdef GL_AMD_shader_trinary_minmax _glewInfo_GL_AMD_shader_trinary_minmax(); #endif /* GL_AMD_shader_trinary_minmax */ @@ -8609,6 +8830,9 @@ static void glewInfo (void) #ifdef GL_AMD_transform_feedback3_lines_triangles _glewInfo_GL_AMD_transform_feedback3_lines_triangles(); #endif /* GL_AMD_transform_feedback3_lines_triangles */ +#ifdef GL_AMD_transform_feedback4 + _glewInfo_GL_AMD_transform_feedback4(); +#endif /* GL_AMD_transform_feedback4 */ #ifdef GL_AMD_vertex_shader_layer _glewInfo_GL_AMD_vertex_shader_layer(); #endif /* GL_AMD_vertex_shader_layer */ @@ -9254,6 +9478,9 @@ static void glewInfo (void) #ifdef GL_EXT_cull_vertex _glewInfo_GL_EXT_cull_vertex(); #endif /* GL_EXT_cull_vertex */ +#ifdef GL_EXT_debug_label + _glewInfo_GL_EXT_debug_label(); +#endif /* GL_EXT_debug_label */ #ifdef GL_EXT_debug_marker _glewInfo_GL_EXT_debug_marker(); #endif /* GL_EXT_debug_marker */ @@ -9374,9 +9601,15 @@ static void glewInfo (void) #ifdef GL_EXT_separate_specular_color _glewInfo_GL_EXT_separate_specular_color(); #endif /* GL_EXT_separate_specular_color */ +#ifdef GL_EXT_shader_image_load_formatted + _glewInfo_GL_EXT_shader_image_load_formatted(); +#endif /* GL_EXT_shader_image_load_formatted */ #ifdef GL_EXT_shader_image_load_store _glewInfo_GL_EXT_shader_image_load_store(); #endif /* GL_EXT_shader_image_load_store */ +#ifdef GL_EXT_shader_integer_mix + _glewInfo_GL_EXT_shader_integer_mix(); +#endif /* GL_EXT_shader_integer_mix */ #ifdef GL_EXT_shadow_funcs _glewInfo_GL_EXT_shadow_funcs(); #endif /* GL_EXT_shadow_funcs */ @@ -9539,18 +9772,27 @@ static void glewInfo (void) #ifdef GL_INGR_interlace_read _glewInfo_GL_INGR_interlace_read(); #endif /* GL_INGR_interlace_read */ +#ifdef GL_INTEL_fragment_shader_ordering + _glewInfo_GL_INTEL_fragment_shader_ordering(); +#endif /* GL_INTEL_fragment_shader_ordering */ #ifdef GL_INTEL_map_texture _glewInfo_GL_INTEL_map_texture(); #endif /* GL_INTEL_map_texture */ #ifdef GL_INTEL_parallel_arrays _glewInfo_GL_INTEL_parallel_arrays(); #endif /* GL_INTEL_parallel_arrays */ +#ifdef GL_INTEL_performance_query + _glewInfo_GL_INTEL_performance_query(); +#endif /* GL_INTEL_performance_query */ #ifdef GL_INTEL_texture_scissor _glewInfo_GL_INTEL_texture_scissor(); #endif /* GL_INTEL_texture_scissor */ #ifdef GL_KHR_debug _glewInfo_GL_KHR_debug(); #endif /* GL_KHR_debug */ +#ifdef GL_KHR_texture_compression_astc_hdr + _glewInfo_GL_KHR_texture_compression_astc_hdr(); +#endif /* GL_KHR_texture_compression_astc_hdr */ #ifdef GL_KHR_texture_compression_astc_ldr _glewInfo_GL_KHR_texture_compression_astc_ldr(); #endif /* GL_KHR_texture_compression_astc_ldr */ @@ -9728,6 +9970,12 @@ static void glewInfo (void) #ifdef GL_NV_shader_storage_buffer_object _glewInfo_GL_NV_shader_storage_buffer_object(); #endif /* GL_NV_shader_storage_buffer_object */ +#ifdef GL_NV_shader_thread_group + _glewInfo_GL_NV_shader_thread_group(); +#endif /* GL_NV_shader_thread_group */ +#ifdef GL_NV_shader_thread_shuffle + _glewInfo_GL_NV_shader_thread_shuffle(); +#endif /* GL_NV_shader_thread_shuffle */ #ifdef GL_NV_tessellation_program5 _glewInfo_GL_NV_tessellation_program5(); #endif /* GL_NV_tessellation_program5 */ @@ -9851,6 +10099,9 @@ static void glewInfo (void) #ifdef GL_REGAL_log _glewInfo_GL_REGAL_log(); #endif /* GL_REGAL_log */ +#ifdef GL_REGAL_proc_address + _glewInfo_GL_REGAL_proc_address(); +#endif /* GL_REGAL_proc_address */ #ifdef GL_REND_screen_coordinates _glewInfo_GL_REND_screen_coordinates(); #endif /* GL_REND_screen_coordinates */ @@ -10168,6 +10419,9 @@ static void wglewInfo () #ifdef WGL_NV_copy_image _glewInfo_WGL_NV_copy_image(); #endif /* WGL_NV_copy_image */ +#ifdef WGL_NV_delay_before_swap + _glewInfo_WGL_NV_delay_before_swap(); +#endif /* WGL_NV_delay_before_swap */ #ifdef WGL_NV_float_buffer _glewInfo_WGL_NV_float_buffer(); #endif /* WGL_NV_float_buffer */ @@ -10279,6 +10533,9 @@ static void glxewInfo () #ifdef GLX_EXT_scene_marker _glewInfo_GLX_EXT_scene_marker(); #endif /* GLX_EXT_scene_marker */ +#ifdef GLX_EXT_stereo_tree + _glewInfo_GLX_EXT_stereo_tree(); +#endif /* GLX_EXT_stereo_tree */ #ifdef GLX_EXT_swap_control _glewInfo_GLX_EXT_swap_control(); #endif /* GLX_EXT_swap_control */ @@ -10306,6 +10563,9 @@ static void glxewInfo () #ifdef GLX_MESA_pixmap_colormap _glewInfo_GLX_MESA_pixmap_colormap(); #endif /* GLX_MESA_pixmap_colormap */ +#ifdef GLX_MESA_query_renderer + _glewInfo_GLX_MESA_query_renderer(); +#endif /* GLX_MESA_query_renderer */ #ifdef GLX_MESA_release_buffers _glewInfo_GLX_MESA_release_buffers(); #endif /* GLX_MESA_release_buffers */ @@ -10318,6 +10578,9 @@ static void glxewInfo () #ifdef GLX_NV_copy_image _glewInfo_GLX_NV_copy_image(); #endif /* GLX_NV_copy_image */ +#ifdef GLX_NV_delay_before_swap + _glewInfo_GLX_NV_delay_before_swap(); +#endif /* GLX_NV_delay_before_swap */ #ifdef GLX_NV_float_buffer _glewInfo_GLX_NV_float_buffer(); #endif /* GLX_NV_float_buffer */ @@ -10336,9 +10599,9 @@ static void glxewInfo () #ifdef GLX_NV_video_capture _glewInfo_GLX_NV_video_capture(); #endif /* GLX_NV_video_capture */ -#ifdef GLX_NV_video_output - _glewInfo_GLX_NV_video_output(); -#endif /* GLX_NV_video_output */ +#ifdef GLX_NV_video_out + _glewInfo_GLX_NV_video_out(); +#endif /* GLX_NV_video_out */ #ifdef GLX_OML_swap_method _glewInfo_GLX_OML_swap_method(); #endif /* GLX_OML_swap_method */ @@ -10456,7 +10719,12 @@ int main (void) return 1; } #if defined(_WIN32) +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + if (fopen_s(&f, "glewinfo.txt", "w") != 0) + f = stdout; +#else f = fopen("glewinfo.txt", "w"); +#endif if (f == NULL) f = stdout; #else f = stdout; @@ -10600,7 +10868,7 @@ GLboolean glewCreateContext () if (GL_FALSE == aglSetCurrentContext(ctx)) return GL_TRUE; /* Needed for Regal on the Mac */ #if defined(GLEW_REGAL) && defined(__APPLE__) - RegalMakeCurrent(octx); + RegalMakeCurrent(ctx); #endif return GL_FALSE; } @@ -10613,6 +10881,21 @@ void glewDestroyContext () /* ------------------------------------------------------------------------ */ +#elif defined(__HAIKU__) + +GLboolean glewCreateContext () +{ + /* TODO: Haiku: We need to call C++ code here */ + return GL_FALSE; +} + +void glewDestroyContext () +{ + /* TODO: Haiku: We need to call C++ code here */ +} + +/* ------------------------------------------------------------------------ */ + #else /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */ Display* dpy = NULL; diff --git a/ext/glew/visualinfo.c b/ext/glew/visualinfo.c index b8bb59ef60..23a849996b 100644 --- a/ext/glew/visualinfo.c +++ b/ext/glew/visualinfo.c @@ -4,6 +4,7 @@ ** Copyright (C) Nate Robins, 1997 ** Michael Wimmer, 1999 ** Milan Ikits, 2002-2008 +** Nigel Stewart, 2008-2013 ** ** visualinfo is a small utility that displays all available visuals, ** aka. pixelformats, in an OpenGL system along with renderer version @@ -37,7 +38,7 @@ #include #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) #include -#else +#elif !defined(__HAIKU__) #include #endif @@ -47,7 +48,7 @@ GLEWContext _glewctx; # ifdef _WIN32 WGLEWContext _wglewctx; # define wglewGetContext() (&_wglewctx) -# elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +# elif !defined(__APPLE__) && !defined(__HAIKU__) || defined(GLEW_APPLE_GLX) GLXEWContext _glxewctx; # define glxewGetContext() (&_glxewctx) # endif @@ -61,7 +62,7 @@ typedef struct GLContextStruct HGLRC rc; #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) AGLContext ctx, octx; -#else +#elif !defined(__HAIKU__) Display* dpy; XVisualInfo* vi; GLXContext ctx; @@ -129,7 +130,7 @@ main (int argc, char** argv) err = glewContextInit(glewGetContext()); # ifdef _WIN32 err = err || wglewContextInit(wglewGetContext()); -# elif !defined(__APPLE__) || defined(GLEW_APPLE_GLX) +# elif !defined(__APPLE__) && !defined(__HAIKU__) || defined(GLEW_APPLE_GLX) err = err || glxewContextInit(glxewGetContext()); # endif #else @@ -145,8 +146,15 @@ main (int argc, char** argv) /* ---------------------------------------------------------------------- */ /* open file */ #if defined(_WIN32) - if (!displaystdout) + if (!displaystdout) + { +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + if (fopen_s(&file, "visualinfo.txt", "w") != 0) + file = stdout; +#else file = fopen("visualinfo.txt", "w"); +#endif + } if (file == NULL) file = stdout; #else @@ -160,13 +168,13 @@ main (int argc, char** argv) fprintf(file, "OpenGL renderer string: %s\n", glGetString(GL_RENDERER)); fprintf(file, "OpenGL version string: %s\n", glGetString(GL_VERSION)); fprintf(file, "OpenGL extensions (GL_): \n"); - PrintExtensions((char*)glGetString(GL_EXTENSIONS)); + PrintExtensions((const char*)glGetString(GL_EXTENSIONS)); #ifndef GLEW_NO_GLU /* GLU extensions */ fprintf(file, "GLU version string: %s\n", gluGetString(GLU_VERSION)); fprintf(file, "GLU extensions (GLU_): \n"); - PrintExtensions((char*)gluGetString(GLU_EXTENSIONS)); + PrintExtensions((const char*)gluGetString(GLU_EXTENSIONS)); #endif /* ---------------------------------------------------------------------- */ @@ -177,11 +185,15 @@ main (int argc, char** argv) { fprintf(file, "WGL extensions (WGL_): \n"); PrintExtensions(wglGetExtensionsStringARB ? - (char*)wglGetExtensionsStringARB(ctx.dc) : - (char*)wglGetExtensionsStringEXT()); + (const char*)wglGetExtensionsStringARB(ctx.dc) : + (const char*)wglGetExtensionsStringEXT()); } #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) +#elif defined(__HAIKU__) + + /* TODO */ + #else /* GLX extensions */ fprintf(file, "GLX extensions (GLX_): \n"); @@ -231,7 +243,11 @@ void PrintExtensions (const char* s) fprintf(file, " %s\n", t); p++; i = (int)strlen(p); +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + strcpy_s(t, sizeof(t), p); +#else strcpy(t, p); +#endif } s++; } @@ -582,7 +598,7 @@ VisualInfo (GLContext* ctx) #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) void -VisualInfo (GLContext* ctx) +VisualInfo (GLContext* __attribute__((__unused__)) ctx) { /* int attrib[] = { AGL_RGBA, AGL_NONE }; @@ -598,6 +614,16 @@ VisualInfo (GLContext* ctx) */ } +/* ---------------------------------------------------------------------- */ + +#elif defined(__HAIKU__) + +void +VisualInfo (GLContext* ctx) +{ + /* TODO */ +} + #else /* GLX */ void @@ -1074,6 +1100,29 @@ void DestroyContext (GLContext* ctx) /* ------------------------------------------------------------------------ */ +#elif defined(__HAIKU__) + +void +InitContext (GLContext* ctx) +{ + /* TODO */ +} + +GLboolean +CreateContext (GLContext* ctx) +{ + /* TODO */ + return GL_FALSE; +} + +void +DestroyContext (GLContext* ctx) +{ + /* TODO */ +} + +/* ------------------------------------------------------------------------ */ + #else /* __UNIX || (__APPLE__ && GLEW_APPLE_GLX) */ void InitContext (GLContext* ctx) From c1bc4215f2dfe3dd63bb8f6cf6429cc7390196f7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 17 Aug 2014 12:16:57 +0200 Subject: [PATCH 1218/1445] Thin3D: A thin OpenGL/D3D9 wrapper for basic rendering. Only the OpenGL implementation actually works yet. --- thin3d/d3dx9_loader.cpp | 284 ++++++++++++++++++++ thin3d/d3dx9_loader.h | 21 ++ thin3d/thin3d.cpp | 80 ++++++ thin3d/thin3d.h | 220 ++++++++++++++++ thin3d/thin3d_d3d9.cpp | 331 +++++++++++++++++++++++ thin3d/thin3d_gl.cpp | 562 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 1498 insertions(+) create mode 100644 thin3d/d3dx9_loader.cpp create mode 100644 thin3d/d3dx9_loader.h create mode 100644 thin3d/thin3d.cpp create mode 100644 thin3d/thin3d.h create mode 100644 thin3d/thin3d_d3d9.cpp create mode 100644 thin3d/thin3d_gl.cpp diff --git a/thin3d/d3dx9_loader.cpp b/thin3d/d3dx9_loader.cpp new file mode 100644 index 0000000000..87e5898c70 --- /dev/null +++ b/thin3d/d3dx9_loader.cpp @@ -0,0 +1,284 @@ +#include +#include +#include +#include +#include +#include + +#include "base/logging.h" +#include "thin3d/d3dx9_loader.h" + +typedef BOOL(__stdcall *TFunc_D3DXCheckVersion)(UINT D3DSDKVersion, UINT D3DXSDKVersion); +typedef HRESULT(__stdcall *TFunc_D3DXCompileShader)( + LPCSTR pSrcData, + UINT srcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + LPCSTR pFunctionName, + LPCSTR pProfile, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE * ppConstantTable); + +typedef HRESULT(__stdcall *TFunc_D3DXAssembleShader)( + LPCSTR pSrcData, + UINT SrcDataLen, + CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, + DWORD Flags, + LPD3DXBUFFER* ppShader, + LPD3DXBUFFER * ppErrorMsgs + ); + +static HMODULE hm_d3dx; +static unsigned int d3dx_version; +static TFunc_D3DXCheckVersion m_TFunc_D3DXCheckVersion; +static TFunc_D3DXAssembleShader m_TFunc_D3DXAssembleShader; +static TFunc_D3DXCompileShader m_TFunc_D3DXCompileShader; + +void makeD3DX9dllFilename_by_version(std::string& strOut, unsigned int vers, bool bDebugV = false) { + strOut = ""; + strOut += "d3dx9"; + if (bDebugV) { + strOut += "d"; + } + strOut += "_"; + char buf[32]; + sprintf(buf, "%02i", vers); + strOut += buf; + strOut += ".dll"; + // temp mon + if (vers < 10) { + int _stop = 0; + } +} + +void makeD3DX9dllFilename_by_versionW(std::wstring& strOut, unsigned int vers, bool bDebugV = false) +{ + strOut = L""; + strOut += L"d3dx9"; + + if (bDebugV) { + strOut += L"d"; + } + + strOut += L"_"; + + wchar_t buf[32]; + wsprintf(buf, L"%02i", vers); + strOut += buf; + strOut += L".dll"; + + // temp mon + if (vers < 10) { + int _stop = 0; + } +} + +bool checkDllExistsA(const char* fname, bool bIncludeExeDir) { + return ::GetFileAttributesA(fname) != DWORD(-1); +} + +bool checkDllExistsW(const WCHAR* fname, bool bIncludeExeDir) { + return ::GetFileAttributesW(fname) != DWORD(-1); +} + +bool checkExistsDll(const char* sDllFilename) { + std::string sfullpath; + char bufsysdir[MAX_PATH]; + + if (!::GetSystemDirectoryA(bufsysdir, MAX_PATH)) { + throw (std::runtime_error("system error")); + } + sfullpath = bufsysdir; + sfullpath += '\\'; + sfullpath += sDllFilename; + if (checkDllExistsA(sfullpath.c_str(), true)) { + return true; + } + return false; +} + +bool checkExistsDllW(const WCHAR* sDllFilename) { + std::wstring sfullpath; + WCHAR bufsysdir[MAX_PATH]; + + if (!::GetSystemDirectoryW(bufsysdir, MAX_PATH)) { + throw (std::runtime_error("system error")); + } + + sfullpath = bufsysdir; + sfullpath += L'\\'; + sfullpath += sDllFilename; + + if (checkDllExistsW(sfullpath.c_str(), true)) { + return true; + } + + return false; +} + +bool getInstaledD3DXlastVersion(unsigned int* piOutVers) { + *piOutVers = 0; + std::string fname; + for (unsigned int cvers = 45; cvers > 0; cvers--) { + makeD3DX9dllFilename_by_version(fname, cvers); + if (checkExistsDll(fname.c_str())) { + *piOutVers = cvers; + return true; + } + } + return false; +} + +//==================================================================== +bool getInstaledD3DXallVersion(std::vector& versions) { + bool result = false; + versions.clear(); + + std::string fname; + for (unsigned int cvers = 45; cvers > 0; cvers--) { + makeD3DX9dllFilename_by_version(fname, cvers); + if (checkExistsDll(fname.c_str())) { + versions.push_back(cvers); + result = true; + } + } + return result; +} + +//==================================================================== +HMODULE loadDllLastVersion(unsigned int* piOutVers) { + if (piOutVers) + *piOutVers = 0; + + // old code ansi string +#if 0 + + if (!getInstaledD3DXlastVersion(piOutVers)) { + + return 0; + } + + std::string dllfname; + makeD3DX9dllFilename_by_version(dllfname, *piOutVers); + + HMODULE hm = 0; + hm = ::LoadLibraryA(dllfname.c_str()); + +#else + // unicode + if (!getInstaledD3DXlastVersion(piOutVers)) { + return 0; + } + + bool bdebugvers = false; +#ifdef _DEBUG + bdebugvers = false; // true; +#endif + std::wstring dllfname; + makeD3DX9dllFilename_by_versionW(dllfname, *piOutVers, bdebugvers); + HMODULE hm = 0; + hm = ::LoadLibraryW(dllfname.c_str()); +#endif + return hm; +} + + +#define GB_MAKE_STR(s) # s +#define GB_MAKE_STR2(x) GB_MAKE_STR(x) + +#define __HANDLE_DLL_ENTRY(funcname) m_TFunc_##funcname = \ + ( TFunc_##funcname ) ::GetProcAddress(hm_d3dx, GB_MAKE_STR(funcname) ); \ + \ + if(!m_TFunc_##funcname) {\ + handleNotFoundAddr( GB_MAKE_STR(funcname) ); \ + } + +//============================================================== +void handleNotFoundAddr(const char* sFuncName) { +#ifdef _DEBUG + std::string temp; + temp = " Entry point not found in d3dx dll : \n"; + temp += sFuncName; + // ELOG(temp.c_str()); + + assert(false && temp.c_str()); + + static FILE* st_file = NULL; + if (st_file == NULL) { + st_file = fopen("__getProcAddrlog.txt", "w"); + } + + fputs(sFuncName, st_file); + fputs("\n", st_file); + +#endif +} + +int LoadD3DX9Dynamic() { + if (hm_d3dx) { + // Already loaded + return d3dx_version; + } + + hm_d3dx = loadDllLastVersion(&d3dx_version); + void* ptr = NULL; + const int NERROR = -1; + int _begin = 0; + + __HANDLE_DLL_ENTRY(D3DXCheckVersion); + __HANDLE_DLL_ENTRY(D3DXAssembleShader); + __HANDLE_DLL_ENTRY(D3DXCompileShader); + + return d3dx_version; +} + +int GetD3DXVersion() { + return d3dx_version; +} + +void UnloadD3DXDynamic() { + if (hm_d3dx) { + FreeLibrary(hm_d3dx); + hm_d3dx = NULL; + d3dx_version = 0; + } +} + +// version function + +#define GB_D3D9_D3DXDLL_LOADER_CHECK_ENTRY_NULL_PTR(funcname) assert(false && GB_MAKE_STR2(funcname) ); + + +BOOL D3DXCheckVersion(UINT D3DSDKVersion, UINT D3DXSDKVersion) { + if (!m_TFunc_D3DXCheckVersion) { + GB_D3D9_D3DXDLL_LOADER_CHECK_ENTRY_NULL_PTR(D3DXCheckVersion) + } + + return m_TFunc_D3DXCheckVersion(D3DSDKVersion, D3DXSDKVersion); +} + +HRESULT D3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER * ppErrorMsgs) +{ + if (!m_TFunc_D3DXAssembleShader) { + GB_D3D9_D3DXDLL_LOADER_CHECK_ENTRY_NULL_PTR(D3DXAssembleShader); + } + return m_TFunc_D3DXAssembleShader(pSrcData, SrcDataLen, pDefines, + pInclude, Flags, ppShader, ppErrorMsgs); +} + +HRESULT D3DXCompileShader(LPCSTR pSrcData, UINT srcDataLen, CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, + DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE * ppConstantTable) +{ + if (!m_TFunc_D3DXCompileShader) { + GB_D3D9_D3DXDLL_LOADER_CHECK_ENTRY_NULL_PTR(D3DXCompileShader); + } + return m_TFunc_D3DXCompileShader(pSrcData, srcDataLen, pDefines, + pInclude, pFunctionName, pProfile, + Flags, ppShader, ppErrorMsgs, ppConstantTable); +} \ No newline at end of file diff --git a/thin3d/d3dx9_loader.h b/thin3d/d3dx9_loader.h new file mode 100644 index 0000000000..b4950809f3 --- /dev/null +++ b/thin3d/d3dx9_loader.h @@ -0,0 +1,21 @@ +// Cut-down version of https://code.google.com/p/d3dx9-dynamic-load/ +// by ksacvet777, licensed under the MIT + +#pragma once + +#include +#include + +// Returns the D3DX9 version we got. 0 if none. +int LoadD3DX9Dynamic(); +int GetD3DXVersion(); +void UnloadD3DXDynamic(); + +// Call these instead of the real D3DX9 functions. +BOOL dyn_D3DXCheckVersion(UINT D3DSDKVersion, UINT D3DXSDKVersion); +HRESULT dyn_D3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER * ppErrorMsgs); +HRESULT dyn_D3DXCompileShader(LPCSTR pSrcData, UINT srcDataLen, CONST D3DXMACRO* pDefines, + LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, + DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, + LPD3DXCONSTANTTABLE * ppConstantTable); diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp new file mode 100644 index 0000000000..df652bd33b --- /dev/null +++ b/thin3d/thin3d.cpp @@ -0,0 +1,80 @@ +#include + +static const char * const fsTexCol = +"varying vec4 oColor0;\n" +"varying vec2 oTexCoord0;\n" +"uniform sampler2D Sampler0;\n" +"void main() { gl_FragColor = oColor0 * texture2D(Sampler0, oTexCoord0); }\n"; + +static const char * const hlslFsTexCol = ""; + +static const char * const fsCol = +"varying vec4 oColor0;\n" +"uniform sampler2D Sampler0;\n" +"void main() { gl_FragColor = oColor0; }\n"; + +static const char * const hlslFsCol = ""; + +static const char * const vsCol = +"attribute vec3 Position;\n" +"attribute vec4 Color0;\n" +"varying vec4 oColor0;\n" +"uniform mat4 WorldViewProj;\n" +"void main() {\n" +" gl_Position = WorldViewProj * vec4(Position, 1.0);\n" +" oColor0 = Color0;\n" +"}"; + +static const char * const hlslVsCol = ""; + +static const char * const vsTexCol = +"attribute vec3 Position;\n" +"attribute vec4 Color0;\n" +"attribute vec2 TexCoord0;\n" +"varying vec4 oColor0;\n" +"varying vec2 oTexCoord0;\n" +"uniform mat4 WorldViewProj;\n" +"void main() {\n" +" gl_Position = WorldViewProj * vec4(Position, 1.0);\n" +" oColor0 = Color0;\n" +" oTexCoord0 = TexCoord0; \n" +"}"; + +static const char * const hlslVsTexCol = ""; + +void Thin3DContext::CreatePresets() { + // Build prebuilt objects + T3DBlendStateDesc off = { false }; + T3DBlendStateDesc additive = { true, T3DBlendEquation::ADD, T3DBlendFactor::ONE, T3DBlendFactor::ONE, T3DBlendEquation::ADD, T3DBlendFactor::ONE, T3DBlendFactor::ZERO }; + T3DBlendStateDesc standard_alpha = { true, T3DBlendEquation::ADD, T3DBlendFactor::SRC_ALPHA, T3DBlendFactor::ONE_MINUS_SRC_ALPHA, T3DBlendEquation::ADD, T3DBlendFactor::ONE, T3DBlendFactor::ZERO }; + T3DBlendStateDesc premul_alpha = { true, T3DBlendEquation::ADD, T3DBlendFactor::ONE, T3DBlendFactor::ONE_MINUS_SRC_ALPHA, T3DBlendEquation::ADD, T3DBlendFactor::ONE, T3DBlendFactor::ZERO }; + + bsPresets_[BS_OFF] = CreateBlendState(off); + bsPresets_[BS_ADDITIVE] = CreateBlendState(additive); + bsPresets_[BS_STANDARD_ALPHA] = CreateBlendState(standard_alpha); + bsPresets_[BS_PREMUL_ALPHA] = CreateBlendState(premul_alpha); + + vsPresets_[VS_TEXTURE_COLOR_2D] = CreateVertexShader(vsTexCol, hlslVsTexCol); + vsPresets_[VS_COLOR_2D] = CreateVertexShader(vsCol, hlslVsCol); + + fsPresets_[FS_TEXTURE_COLOR_2D] = CreateFragmentShader(fsTexCol, hlslFsTexCol); + fsPresets_[FS_COLOR_2D] = CreateFragmentShader(fsCol, hlslFsCol); + + ssPresets_[SS_TEXTURE_COLOR_2D] = CreateShaderSet(vsPresets_[VS_TEXTURE_COLOR_2D], fsPresets_[FS_TEXTURE_COLOR_2D]); + ssPresets_[SS_COLOR_2D] = CreateShaderSet(vsPresets_[VS_COLOR_2D], fsPresets_[FS_COLOR_2D]); +} + +Thin3DContext::~Thin3DContext() { + for (int i = 0; i < VS_MAX_PRESET; i++) { + vsPresets_[i]->Release(); + } + for (int i = 0; i < FS_MAX_PRESET; i++) { + fsPresets_[i]->Release(); + } + for (int i = 0; i < BS_MAX_PRESET; i++) { + bsPresets_[i]->Release(); + } + for (int i = 0; i < SS_MAX_PRESET; i++) { + ssPresets_[i]->Release(); + } +} \ No newline at end of file diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h new file mode 100644 index 0000000000..25d3a95b8b --- /dev/null +++ b/thin3d/thin3d.h @@ -0,0 +1,220 @@ +// Very thin API wrapper, suitable for porting UI code (like the native/ui framework) and similar but not real rendering. +// Does not involve context creation etc, that should be handled separately - only does drawing. + +// The goals may change in the future though. +// MIT licensed, by Henrik Rydgård 2014. + +#pragma once + +#include + +class Matrix4x4; + +enum T3DBlendEquation : int { + ADD, + SUBTRACT, + REV_SUBTRACT, + // MIN, MAX, +}; + +enum T3DComparison : int { + NEVER, + LESS, + EQUAL, + LESS_EQUAL, + GREATER, + NOT_EQUAL, + GREATER_EQUAL, + ALWAYS, +}; + +enum T3DBlendFactor : int { + ZERO, + ONE, + SRC_COLOR, + SRC_ALPHA, + ONE_MINUS_SRC_COLOR, + ONE_MINUS_SRC_ALPHA, + DST_COLOR, + DST_ALPHA, + ONE_MINUS_DST_COLOR, + ONE_MINUS_DST_ALPHA, + FIXED_COLOR, +}; + +enum T3DBufferUsage : int { + VERTEXDATA = 1, + INDEXDATA = 2, + GENERIC = 4, + + DYNAMIC = 16, +}; + +enum T3DVertexFormatPreset : int { + FVF_POS_UV_COLOR +}; + +enum T3DSemantic : int { + SEM_POSITION, + SEM_COLOR0, + SEM_TEXCOORD0, + SEM_NORMAL, + SEM_TANGENT, + SEM_BINORMAL, // really BITANGENT + SEM_MAX, +}; + +enum T3DPrimitive : int { + PRIM_POINTS, + PRIM_LINES, + PRIM_TRIANGLES, +}; + +enum T3DVertexShaderPreset : int { + VS_COLOR_2D, + VS_TEXTURE_COLOR_2D, + VS_MAX_PRESET, +}; + +enum T3DFragmentShaderPreset : int { + FS_COLOR_2D, + FS_TEXTURE_COLOR_2D, + FS_MAX_PRESET, +}; + +// Predefined full shader setups. +enum T3DShaderSetPreset : int { + SS_COLOR_2D, + SS_TEXTURE_COLOR_2D, + SS_MAX_PRESET, +}; + +enum T3DBlendStatePreset : int { + BS_OFF, + BS_STANDARD_ALPHA, + BS_PREMUL_ALPHA, + BS_ADDITIVE, + BS_MAX_PRESET, +}; + +enum T3DClear : int { + COLOR, + DEPTH, + STENCIL, +}; + +// Binary compatible with D3D11 viewport. +struct T3DViewport { + float TopLeftX; + float TopLeftY; + float Width; + float Height; + float MinDepth; + float MaxDepth; +}; + +class Thin3DObject { +public: + Thin3DObject() : refcount_(1) {} + virtual ~Thin3DObject() {} + + virtual void AddRef() { refcount_++; } + virtual void Release() { refcount_--; if (!refcount_) delete this; } // TODO: Refcount + +private: + int refcount_; +}; + +class Thin3DBlendState : public Thin3DObject { +public: +}; + +class Thin3DDepthStencilState : public Thin3DObject { +public: +}; + +class Thin3DBuffer : public Thin3DObject { +public: + virtual void SetData(const uint8_t *data, size_t size) = 0; + virtual void SubData(const uint8_t *data, size_t offset, size_t size) = 0; +}; + +class Thin3DTexture : public Thin3DObject { +public: + virtual void SetRectangle(int x, int y, int w, int h, const uint8_t *data, int level = 0, int layer = 0); +}; + +class Thin3DVertexFormat : public Thin3DObject { +public: +}; + +class Thin3DShader : public Thin3DObject { +public: +}; + +class Thin3DShaderSet : public Thin3DObject { +public: + // TODO: Make some faster way of doing these. Support uniform buffers (and fake them on GL 2.0?) + virtual void SetVector(const char *name, float *value, int n) = 0; + virtual void SetMatrix4x4(const char *name, const Matrix4x4 &value) = 0; +}; + +struct T3DBlendStateDesc { + bool enabled; + T3DBlendEquation eqCol; + T3DBlendFactor srcCol; + T3DBlendFactor dstCol; + T3DBlendEquation eqAlpha; + T3DBlendFactor srcAlpha; + T3DBlendFactor dstAlpha; + // int colorMask; +}; + +class Thin3DContext : public Thin3DObject { +public: + virtual ~Thin3DContext(); + virtual Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) = 0; + virtual Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) = 0; + virtual Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0; + virtual Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) = 0; + virtual Thin3DVertexFormat *CreateVertexFormat(T3DVertexFormatPreset preset) = 0; + + // Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them. + Thin3DBlendState *GetBlendStatePreset(T3DBlendStatePreset preset) { return bsPresets_[preset]; } + Thin3DShader *GetVshaderPreset(T3DVertexShaderPreset preset) { return fsPresets_[preset]; } + Thin3DShader *GetFshaderPreset(T3DFragmentShaderPreset preset) { return vsPresets_[preset]; } + Thin3DShaderSet *GetShaderSetPreset(T3DShaderSetPreset preset) { return ssPresets_[preset]; } + + // The implementation makes the choice of which shader code to use. + virtual Thin3DShader *CreateVertexShader(const char *glsl_source, const char *hlsl_source) = 0; + virtual Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source) = 0; + + // Bound state objects. Too cumbersome to add them all as parameters to Draw. + virtual void SetBlendState(Thin3DBlendState *state) = 0; + + // Raster state + virtual void SetScissorEnabled(bool enable) = 0; + virtual void SetScissorRect(int left, int top, int width, int height) = 0; + virtual void SetViewports(int count, T3DViewport *viewports) = 0; + + // TODO: Add more sophisticated draws with buffer offsets, and multidraws. + virtual void Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) = 0; + virtual void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) = 0; + virtual void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) = 0; + +protected: + void CreatePresets(); + + Thin3DShader *vsPresets_[VS_MAX_PRESET]; + Thin3DShader *fsPresets_[FS_MAX_PRESET]; + Thin3DBlendState *bsPresets_[BS_MAX_PRESET]; + Thin3DShaderSet *ssPresets_[SS_MAX_PRESET]; + +private: +}; + +Thin3DContext *T3DCreateGLContext(); + +#ifdef _WIN32 +Thin3DContext *T3DCreateDX9Context(); +#endif diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp new file mode 100644 index 0000000000..03964d0eee --- /dev/null +++ b/thin3d/thin3d_d3d9.cpp @@ -0,0 +1,331 @@ +#include +#include +#include +#include + +#include "base/logging.h" +#include "thin3d/thin3d.h" +#include "thin3d/d3dx9_loader.h" + +// Could be declared as u8 +static const D3DCMPFUNC compareToD3D9[] = { + D3DCMP_NEVER, + D3DCMP_LESS, + D3DCMP_EQUAL, + D3DCMP_LESSEQUAL, + D3DCMP_GREATER, + D3DCMP_NOTEQUAL, + D3DCMP_GREATEREQUAL, + D3DCMP_ALWAYS +}; + +// Could be declared as u8 +static const D3DBLENDOP blendEqToD3D9[] = { + D3DBLENDOP_ADD, + D3DBLENDOP_SUBTRACT, +}; + +// Could be declared as u8 +static const D3DBLEND blendFactorToD3D9[] = { + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_SRCCOLOR, + D3DBLEND_SRCALPHA, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_INVSRCALPHA, + D3DBLEND_DESTCOLOR, + D3DBLEND_DESTALPHA, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_INVDESTALPHA, + D3DBLEND_BLENDFACTOR, +}; + +static const D3DPRIMITIVETYPE primToD3D9[] = { + D3DPT_POINTLIST, + D3DPT_LINELIST, + D3DPT_TRIANGLELIST, +}; + +class Thin3DDX9DepthStencilState : public Thin3DDepthStencilState { +public: + BOOL depthTestEnabled; + BOOL depthWriteEnabled; + D3DCMPFUNC depthCompare; + + void Apply(LPDIRECT3DDEVICE9 device) { + device->SetRenderState(D3DRS_ZENABLE, depthTestEnabled); + device->SetRenderState(D3DRS_ZWRITEENABLE, depthWriteEnabled); + device->SetRenderState(D3DRS_ZFUNC, depthCompare); + } +}; + +class Thin3DDX9BlendState : public Thin3DBlendState { +public: + bool enabled; + D3DBLENDOP eqCol, eqAlpha; + D3DBLEND srcCol, srcAlpha, dstCol, dstAlpha; + uint32_t fixedColor; + + void Apply(LPDIRECT3DDEVICE9 device) { + device->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)enabled); + device->SetRenderState(D3DRS_BLENDOP, eqCol); + device->SetRenderState(D3DRS_BLENDOPALPHA, eqAlpha); + device->SetRenderState(D3DRS_SRCBLEND, srcCol); + device->SetRenderState(D3DRS_DESTBLEND, dstCol); + device->SetRenderState(D3DRS_SRCBLENDALPHA, srcAlpha); + device->SetRenderState(D3DRS_DESTBLENDALPHA, dstAlpha); + // device->SetRenderState(, fixedColor); + } +}; + +class Thin3DDX9Buffer : public Thin3DBuffer { +public: + Thin3DDX9Buffer(LPDIRECT3DDEVICE9 device, size_t size, uint32_t flags) : vbuffer_(nullptr), ibuffer_(nullptr) { + if (flags & T3DBufferUsage::INDEXDATA) { + DWORD usage = 0; + device->CreateIndexBuffer((UINT)size, usage, D3DFMT_INDEX32, D3DPOOL_MANAGED, &ibuffer_, NULL); + } else { + DWORD usage = 0; + device->CreateVertexBuffer((UINT)size, usage, 0, D3DPOOL_MANAGED, &vbuffer_, NULL); + } + } + void SetData(const uint8_t *data, size_t size) override { + if (vbuffer_) { + void *ptr; + vbuffer_->Lock(0, (UINT)size, &ptr, D3DLOCK_DISCARD); + memcpy(ptr, data, size); + vbuffer_->Unlock(); + } else if (ibuffer_) { + void *ptr; + ibuffer_->Lock(0, (UINT)size, &ptr, D3DLOCK_DISCARD); + memcpy(ptr, data, size); + ibuffer_->Unlock(); + } + } + void SubData(const uint8_t *data, size_t offset, size_t size) override { + if (vbuffer_) { + void *ptr; + vbuffer_->Lock((UINT)offset, (UINT)size, &ptr, D3DLOCK_DISCARD); + memcpy(ptr, data, size); + vbuffer_->Unlock(); + } else if (ibuffer_) { + void *ptr; + ibuffer_->Lock((UINT)offset, (UINT)size, &ptr, D3DLOCK_DISCARD); + memcpy(ptr, data, size); + ibuffer_->Unlock(); + } + } + void BindVertex(LPDIRECT3DDEVICE9 device, int vertexSize, int offset = 0) { + if (vbuffer_) + device->SetStreamSource(0, vbuffer_, offset, vertexSize); + } + void BindIndex(LPDIRECT3DDEVICE9 device) { + if (ibuffer_) + device->SetIndices(ibuffer_); + } + +private: + LPDIRECT3DVERTEXBUFFER9 vbuffer_; + LPDIRECT3DINDEXBUFFER9 ibuffer_; +}; + + +class Thin3DDX9VertexFormat : public Thin3DVertexFormat { +public: + int GetVertexSize() { return 0; } + +private: + LPDIRECT3DVERTEXDECLARATION9 decl_; +}; + +class Thin3DDX9Shader : public Thin3DShader { +public: + Thin3DDX9Shader(bool isPixelShader) : isPixelShader_(isPixelShader), vshader(NULL), pshader(NULL) {} + ~Thin3DDX9Shader() { + if (vshader) + vshader->Release(); + if (pshader) + pshader->Release(); + if (constantTable) + constantTable->Release(); + } + bool Compile(LPDIRECT3DDEVICE9 device, const char *source, const char *profile); + void Apply(LPDIRECT3DDEVICE9 device) { + if (isPixelShader_) { + device->SetPixelShader(pshader); + } else { + device->SetVertexShader(vshader); + } + } + +private: + bool isPixelShader_; + LPDIRECT3DVERTEXSHADER9 vshader; + LPDIRECT3DPIXELSHADER9 pshader; + LPD3DXCONSTANTTABLE constantTable; +}; + +class Thin3DDX9Pipeline : public Thin3DShaderSet { +public: + Thin3DDX9Shader *vshader; + Thin3DDX9Shader *pshader; + void Apply(LPDIRECT3DDEVICE9 device); + +private: +}; + +class Thin3DDX9Context : public Thin3DContext { +public: + Thin3DDX9Context(LPDIRECT3DDEVICE9 device); + ~Thin3DDX9Context(); + + Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare); + Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override; + Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override; + Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override; + Thin3DVertexFormat *CreateVertexFormat(T3DVertexFormatPreset preset) override; + + Thin3DShader *CreateVertexShader(const char *glsl_source, const char *hlsl_source); + Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source); + + // Bound state objects. Too cumbersome to add them all as parameters to Draw. + void SetBlendState(Thin3DBlendState *state); + + // Raster state + void SetScissorEnabled(bool enable); + void SetScissorRect(int left, int top, int width, int height); + void SetViewports(int count, T3DViewport *viewports); + + void Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) override; + void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; + void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal); + +private: + // void CompileShader(const char *hlsl_source); + + LPDIRECT3DDEVICE9 device_; +}; + +Thin3DDX9Context::Thin3DDX9Context(LPDIRECT3DDEVICE9 device) : device_(device) { + CreatePresets(); + int d3dx_ver = LoadD3DX9Dynamic(); + if (!d3dx_ver) { + ELOG("Failed to load D3DX9!"); + } +} + +Thin3DDX9Context::~Thin3DDX9Context() { + for (int i = 0; i < BS_MAX_PRESET; i++) { + bsPresets_[i]->Release(); + } + +} + +Thin3DShader *Thin3DDX9Context::CreateVertexShader(const char *glsl_source, const char *hlsl_source) { + Thin3DDX9Shader *shader = new Thin3DDX9Shader(false); + if (shader->Compile(device_, hlsl_source, "ps_3_0")) { + return shader; + } else { + delete shader; + return NULL; + } +} + +Thin3DShader *Thin3DDX9Context::CreateFragmentShader(const char *glsl_source, const char *hlsl_source) { + Thin3DDX9Shader *shader = new Thin3DDX9Shader(false); + if (shader->Compile(device_, hlsl_source, "vs_3_0")) { + return shader; + } else { + delete shader; + return NULL; + } +} + +Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) { + Thin3DDX9DepthStencilState *ds = new Thin3DDX9DepthStencilState(); + ds->depthCompare = compareToD3D9[depthCompare]; + ds->depthTestEnabled = depthTestEnabled; + ds->depthWriteEnabled = depthWriteEnabled; + return ds; +} + +Thin3DBlendState *Thin3DDX9Context::CreateBlendState(const T3DBlendStateDesc &desc) { + Thin3DDX9BlendState *bs = new Thin3DDX9BlendState(); + bs->enabled = desc.enabled; + bs->eqCol = blendEqToD3D9[desc.eqCol]; + bs->srcCol = blendFactorToD3D9[desc.srcCol]; + bs->dstCol = blendFactorToD3D9[desc.dstCol]; + bs->eqAlpha = blendEqToD3D9[desc.eqAlpha]; + bs->srcAlpha = blendFactorToD3D9[desc.srcAlpha]; + bs->dstAlpha = blendFactorToD3D9[desc.dstAlpha]; + return bs; +} + +void Thin3DDX9Context::SetBlendState(Thin3DBlendState *state) { + Thin3DDX9BlendState *bs = static_cast(state); +} + +Thin3DBuffer *Thin3DDX9Context::CreateBuffer(size_t size, uint32_t usageFlags) { + return new Thin3DDX9Buffer(device_, size, usageFlags); +} + +void Thin3DDX9Pipeline::Apply(LPDIRECT3DDEVICE9 device) { + vshader->Apply(device); + pshader->Apply(device); +} + +void Thin3DDX9Context::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) { + Thin3DDX9Buffer *vbuf = static_cast(vdata); + Thin3DDX9VertexFormat *fmt = static_cast(format); + vbuf->BindVertex(device_, fmt->GetVertexSize(), offset); + device_->DrawPrimitive(primToD3D9[prim], offset, vertexCount / 3); +} + +void Thin3DDX9Context::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) { + Thin3DDX9Buffer *vbuf = static_cast(vdata); + Thin3DDX9Buffer *ibuf = static_cast(idata); + Thin3DDX9VertexFormat *fmt = static_cast(format); + vbuf->BindVertex(device_, fmt->GetVertexSize(), offset); + ibuf->BindIndex(device_); + device_->DrawIndexedPrimitive(primToD3D9[prim], 0, 0, vertexCount, 0, vertexCount / 3); +} + +void Thin3DDX9Context::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) { + UINT d3dMask = 0; + if (mask & T3DClear::COLOR) d3dMask |= D3DCLEAR_TARGET; + if (mask & T3DClear::DEPTH) d3dMask |= D3DCLEAR_ZBUFFER; + if (mask & T3DClear::STENCIL) d3dMask |= D3DCLEAR_STENCIL; + device_->Clear(0, NULL, d3dMask, (D3DCOLOR)colorval, depthVal, stencilVal); +} + +Thin3DContext *T3DCreateDX9Context(LPDIRECT3DDEVICE9 device) { + return new Thin3DDX9Context(device); +} + +bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, const char *profile) { + LPD3DXMACRO defines = NULL; + LPD3DXINCLUDE includes = NULL; + DWORD flags = 0; + LPD3DXBUFFER codeBuffer; + LPD3DXBUFFER errorBuffer; + HRESULT hr = dyn_D3DXCompileShader(source, strlen(source), defines, includes, "main", profile, flags, &codeBuffer, &errorBuffer, &constantTable); + if (FAILED(hr)) { + codeBuffer->Release(); + if (constantTable) + constantTable->Release(); + return false; + } + + bool success = false; + if (isPixelShader_) { + HRESULT result = device->CreatePixelShader((DWORD *)codeBuffer->GetBufferPointer(), &pshader); + success = SUCCEEDED(result); + } else { + HRESULT result = device->CreateVertexShader((DWORD *)codeBuffer->GetBufferPointer(), &vshader); + success = SUCCEEDED(result); + } + codeBuffer->Release(); + + // delete[] code; + return true; +} diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp new file mode 100644 index 0000000000..207ce2aa1a --- /dev/null +++ b/thin3d/thin3d_gl.cpp @@ -0,0 +1,562 @@ +#include +#include +#include +#include + +#include "base/logging.h" +#include "math/lin/matrix4x4.h" +#include "thin3d/thin3d.h" +#include "gfx_es2/gl_state.h" + +static const unsigned short compToGL[] = { + GL_NEVER, + GL_LESS, + GL_EQUAL, + GL_LEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_GEQUAL, + GL_ALWAYS +}; + +static const unsigned short blendEqToGL[] = { + GL_FUNC_ADD, + GL_FUNC_SUBTRACT, + GL_FUNC_REVERSE_SUBTRACT, +}; + +static const unsigned short blendFactorToGL[] = { + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_COLOR, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_COLOR, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_COLOR, + GL_ONE_MINUS_DST_ALPHA, + GL_CONSTANT_COLOR, +}; + +static const unsigned short primToGL[] = { + GL_POINTS, + GL_LINES, + GL_TRIANGLES, +}; + +static const char *glsl_fragment_prelude = +"#ifdef GL_ES\n" +"precision mediump float;\n" +"#endif\n"; + +inline void Uint32ToFloat4(uint32_t u, float f[4]) { + f[0] = ((u >> 0) & 0xFF) * (1.0f / 255.0f); + f[1] = ((u >> 8) & 0xFF) * (1.0f / 255.0f); + f[2] = ((u >> 16) & 0xFF) * (1.0f / 255.0f); + f[3] = ((u >> 24) & 0xFF) * (1.0f / 255.0f); +} + +class Thin3DGLBlendState : public Thin3DBlendState { +public: + bool enabled; + GLuint eqCol, eqAlpha; + GLuint srcCol, srcAlpha, dstCol, dstAlpha; + // int maskBits; + uint32_t fixedColor; + + void Apply() { + glstate.blend.set(enabled); + glstate.blendEquationSeparate.set(eqCol, eqAlpha); + glstate.blendFuncSeparate.set(srcCol, dstCol, srcAlpha, dstAlpha); + // glstate.blendColor.set(fixedColor); + +#if !defined(USING_GLES2) + glstate.colorLogicOp.disable(); +#endif + + // glstate.colorMask.set(maskBits & 1, (maskBits >> 1) & 1, (maskBits >> 2) & 1, (maskBits >> 3) & 1); + // glstate.blendColor.set(fixedColor); + } +}; + +class Thin3DGLDepthStencilState : public Thin3DDepthStencilState { +public: + bool depthTestEnabled; + bool depthWriteEnabled; + GLuint depthComp; + // bool stencilTestEnabled; TODO + + void Apply() { + glstate.depthTest.set(depthTestEnabled); + glstate.depthFunc.set(depthComp); + glstate.depthWrite.set(depthWriteEnabled); + glstate.stencilTest.disable(); + } +}; + +class Thin3DGLBuffer : public Thin3DBuffer { +public: + Thin3DGLBuffer(size_t size, uint32_t flags) { + glGenBuffers(1, &buffer_); + target_ = (flags & T3DBufferUsage::INDEXDATA) ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER; + usage_ = 0; + if (flags & T3DBufferUsage::DYNAMIC) + usage_ = GL_STREAM_DRAW; + else + usage_ = GL_STATIC_DRAW; + knownSize_ = 0; + } + ~Thin3DGLBuffer() override { + glDeleteBuffers(1, &buffer_); + } + + void SetData(const uint8_t *data, size_t size) override { + glBindBuffer(target_, buffer_); + glBufferData(target_, size, data, usage_); + knownSize_ = size; + } + + void SubData(const uint8_t *data, size_t offset, size_t size) override { + glBindBuffer(target_, buffer_); + if (size > knownSize_) { + // Allocate the buffer. + glBufferData(target_, size + offset, NULL, usage_); + knownSize_ = size + offset; + } + glBufferSubData(target_, offset, size, data); + } + void Bind() { + glBindBuffer(target_, buffer_); + } + +private: + GLuint buffer_; + GLuint target_; + GLuint usage_; + + size_t knownSize_; +}; + +class Thin3DGLShader : public Thin3DShader { +public: + Thin3DGLShader(bool isFragmentShader) : shader_(0), type_(0) { + type_ = isFragmentShader ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER; + } + + bool Compile(const char *source); + GLuint GetShader() const { return shader_; } + + ~Thin3DGLShader() { + glDeleteShader(shader_); + } + +private: + GLuint shader_; + GLuint type_; + bool ok_; +}; + +bool Thin3DGLShader::Compile(const char *source) { + shader_ = glCreateShader(type_); + glShaderSource(shader_, 1, &source, 0); + glCompileShader(shader_); + GLint success; + glGetShaderiv(shader_, GL_COMPILE_STATUS, &success); + if (!success) { +#define MAX_INFO_LOG_SIZE 2048 + GLchar infoLog[MAX_INFO_LOG_SIZE]; + GLsizei len; + glGetShaderInfoLog(shader_, MAX_INFO_LOG_SIZE, &len, infoLog); + infoLog[len] = '\0'; + glDeleteShader(shader_); + shader_ = 0; + // print? + } + ok_ = success != 0; + return ok_; +} + +enum T3DVertexDataType : uint8_t { + INVALID, + FLOATx2, + FLOATx3, + FLOATx4, + UNORM8x4, +}; + +struct Thin3DVertexComponent { + Thin3DVertexComponent() : name(nullptr), type(T3DVertexDataType::INVALID), semantic(255), offset(255) {} + Thin3DVertexComponent(const char *name, T3DSemantic semantic, T3DVertexDataType dataType, uint8_t offset) { + this->name = name; + this->semantic = semantic; + this->type = dataType; + this->offset = offset; + } + const char *name; + T3DVertexDataType type; + uint8_t semantic; + uint8_t offset; +}; + +class Thin3DGLVertexFormat : public Thin3DVertexFormat { +public: + void Apply(); + void Unapply(); + void Compile(); + + std::vector components_; + int semanticsMask_; // Fast way to check what semantics to enable/disable. + int stride_; +}; + +struct UniformInfo { + int loc_; +}; + +// TODO: Fold BlendState into this? Seems likely to be right for DX12 etc. +// TODO: Add Uniform Buffer support. +class Thin3DGLShaderSet : public Thin3DShaderSet { +public: + Thin3DGLShaderSet() { + program_ = glCreateProgram(); + } + ~Thin3DGLShaderSet() { + vshader->Release(); + fshader->Release(); + glDeleteProgram(program_); + } + bool Link(); + + void Apply(); + void Unapply(); + + int GetUniformLoc(const char *name); + + void SetVector(const char *name, float *value, int n); + void SetMatrix4x4(const char *name, const Matrix4x4 &value) override; + + Thin3DGLShader *vshader; + Thin3DGLShader *fshader; + +private: + GLuint program_; + std::map uniforms_; +}; + +class Thin3DGLContext : public Thin3DContext { +public: + Thin3DGLContext(); + virtual ~Thin3DGLContext(); + + Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) override; + Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override; + Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override; + Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override; + Thin3DVertexFormat *CreateVertexFormat(T3DVertexFormatPreset preset) override; + + // Bound state objects + void SetBlendState(Thin3DBlendState *state) override { + Thin3DGLBlendState *s = static_cast(state); + s->Apply(); + } + + // The implementation makes the choice of which shader code to use. + Thin3DShader *CreateVertexShader(const char *glsl_source, const char *hlsl_source); + Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source); + + void SetScissorEnabled(bool enable) override { + if (enable) { + glstate.scissorTest.enable(); + } else { + glstate.scissorTest.disable(); + } + } + + void SetScissorRect(int left, int top, int width, int height) override { + glstate.scissorRect.set(left, top, width, height); + } + + void SetViewports(int count, T3DViewport *viewports) override { + // TODO: Add support for multiple viewports. + glstate.viewport.set(viewports[0].TopLeftX, viewports[0].TopLeftY, viewports[0].Width, viewports[0].Height); + glstate.depthRange.set(viewports[0].MinDepth, viewports[0].MaxDepth); + } + + // TODO: Add more sophisticated draws. + void Draw(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) override; + void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; + void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override; +}; + +Thin3DGLContext::Thin3DGLContext() { + CreatePresets(); +} + +Thin3DGLContext::~Thin3DGLContext() { +} + +Thin3DVertexFormat *Thin3DGLContext::CreateVertexFormat(T3DVertexFormatPreset preset) { + Thin3DGLVertexFormat *fmt = new Thin3DGLVertexFormat(); + switch (preset) { + case FVF_POS_UV_COLOR: + fmt->components_.push_back(Thin3DVertexComponent("Position", SEM_POSITION, FLOATx3, 0)); + fmt->components_.push_back(Thin3DVertexComponent("TexCoord0", SEM_TEXCOORD0, FLOATx2, 12)); + fmt->components_.push_back(Thin3DVertexComponent("Color0", SEM_COLOR0, UNORM8x4, 20)); + fmt->stride_ = 24; + break; + } + fmt->Compile(); + return fmt; +} + +void Thin3DGLVertexFormat::Compile() { + int sem = 0; + for (int i = 0; i < (int)components_.size(); i++) { + sem |= 1 << components_[i].semantic; + } + semanticsMask_ = sem; + // TODO : Compute stride as well? +} + +Thin3DDepthStencilState *Thin3DGLContext::CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) { + Thin3DGLDepthStencilState *ds = new Thin3DGLDepthStencilState(); + ds->depthTestEnabled = depthTestEnabled; + ds->depthWriteEnabled = depthWriteEnabled; + ds->depthComp = compToGL[depthCompare]; + return ds; +} + +Thin3DBlendState *Thin3DGLContext::CreateBlendState(const T3DBlendStateDesc &desc) { + Thin3DGLBlendState *bs = new Thin3DGLBlendState(); + bs->enabled = desc.enabled; + bs->eqCol = blendEqToGL[desc.eqCol]; + bs->srcCol = blendFactorToGL[desc.srcCol]; + bs->dstCol = blendFactorToGL[desc.dstCol]; + bs->eqAlpha = blendEqToGL[desc.eqAlpha]; + bs->srcAlpha = blendFactorToGL[desc.srcAlpha]; + bs->dstAlpha = blendFactorToGL[desc.dstAlpha]; + return bs; +} + +Thin3DBuffer *Thin3DGLContext::CreateBuffer(size_t size, uint32_t usageFlags) { + return new Thin3DGLBuffer(size, usageFlags); +} + +Thin3DShaderSet *Thin3DGLContext::CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) { + Thin3DGLShaderSet *shaderSet = new Thin3DGLShaderSet(); + if (!vshader || !fshader) { + ELOG("ShaderSet requires both a valid vertex and a fragment shader: %p %p", vshader, fshader); + } + vshader->AddRef(); + fshader->AddRef(); + shaderSet->vshader = static_cast(vshader); + shaderSet->fshader = static_cast(fshader); + if (shaderSet->Link()) { + return shaderSet; + } else { + delete shaderSet; + return NULL; + } +} + +Thin3DShader *Thin3DGLContext::CreateVertexShader(const char *glsl_source, const char *hlsl_source) { + Thin3DGLShader *shader = new Thin3DGLShader(false); + if (shader->Compile(glsl_source)) { + return shader; + } else { + shader->Release(); + return nullptr; + } +} + +Thin3DShader *Thin3DGLContext::CreateFragmentShader(const char *glsl_source, const char *hlsl_source) { + Thin3DGLShader *shader = new Thin3DGLShader(true); + if (shader->Compile(glsl_source)) { + return shader; + } else { + shader->Release(); + return nullptr; + } +} + +bool Thin3DGLShaderSet::Link() { + glAttachShader(program_, vshader->GetShader()); + glAttachShader(program_, fshader->GetShader()); + + // Bind all the common vertex data points. Mismatching ones will be ignored. + glBindAttribLocation(program_, SEM_POSITION, "Position"); + glBindAttribLocation(program_, SEM_COLOR0, "Color0"); + glBindAttribLocation(program_, SEM_TEXCOORD0, "TexCoord0"); + glBindAttribLocation(program_, SEM_NORMAL, "Normal"); + glBindAttribLocation(program_, SEM_TANGENT, "Tangent"); + glBindAttribLocation(program_, SEM_BINORMAL, "Binormal"); + glLinkProgram(program_); + + GLint linkStatus = GL_FALSE; + glGetProgramiv(program_, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) { + GLint bufLength = 0; + glGetProgramiv(program_, GL_INFO_LOG_LENGTH, &bufLength); + if (bufLength) { + char* buf = new char[bufLength]; + glGetProgramInfoLog(program_, bufLength, NULL, buf); + //ERROR_LOG(G3D, "Could not link program:\n %s", buf); + //ERROR_LOG(G3D, "VS:\n%s", vs->source().c_str()); + //ERROR_LOG(G3D, "FS:\n%s", fs->source().c_str()); +#ifdef SHADERLOG + OutputDebugStringUTF8(buf); + OutputDebugStringUTF8(vs->source().c_str()); + OutputDebugStringUTF8(fs->source().c_str()); +#endif + delete[] buf; // we're dead! + } + return false; + } + + // Auto-initialize samplers. + for (int i = 0; i < 4; i++) { + char temp[256]; + sprintf(temp, "Sampler%i", i); + int samplerLoc = GetUniformLoc(temp); + if (samplerLoc != -1) { + glProgramUniform1i(program_, samplerLoc, i); + } + } + // Here we could (using glGetAttribLocation) save a bitmask about which pieces of vertex data are used in the shader + // and then AND it with the vertex format bitmask later... + return true; +} + +int Thin3DGLShaderSet::GetUniformLoc(const char *name) { + auto iter = uniforms_.find(name); + int loc = -1; + if (iter != uniforms_.end()) { + loc = iter->second.loc_; + } else { + loc = glGetUniformLocation(program_, name); + UniformInfo info; + info.loc_ = loc; + uniforms_[name] = info; + } + return loc; +} + +void Thin3DGLShaderSet::SetVector(const char *name, float *value, int n) { + int loc = GetUniformLoc(name); + if (loc != -1) { + switch (n) { + case 1: glProgramUniform1fv(program_, loc, 1, value); break; + case 2: glProgramUniform1fv(program_, loc, 2, value); break; + case 3: glProgramUniform1fv(program_, loc, 3, value); break; + case 4: glProgramUniform1fv(program_, loc, 4, value); break; + } + } +} + +void Thin3DGLShaderSet::SetMatrix4x4(const char *name, const Matrix4x4 &value) { + int loc = GetUniformLoc(name); + if (loc != -1) { + glProgramUniformMatrix4fv(program_, loc, 1, false, value.getReadPtr()); + } +} + +void Thin3DGLShaderSet::Apply() { + glUseProgram(program_); +} + +void Thin3DGLShaderSet::Unapply() { + glUseProgram(0); +} + +void Thin3DGLContext::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) { + Thin3DGLShaderSet *pipe = static_cast(pipeline); + Thin3DGLBuffer *vbuf = static_cast(vdata); + Thin3DGLVertexFormat *fmt = static_cast(format); + + vbuf->Bind(); + fmt->Apply(); + + pipe->Apply(); + + glDrawArrays(primToGL[prim], offset, vertexCount); + + pipe->Unapply(); + fmt->Unapply(); + + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) { + Thin3DGLShaderSet *pipe = static_cast(pipeline); + Thin3DGLBuffer *vbuf = static_cast(vdata); + Thin3DGLBuffer *ibuf = static_cast(idata); + Thin3DGLVertexFormat *fmt = static_cast(format); + + vbuf->Bind(); + fmt->Apply(); + pipe->Apply(); + + glDrawElements(primToGL[prim], offset, GL_INT, 0); + + pipe->Unapply(); + fmt->Unapply(); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +void Thin3DGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) { + float col[4]; + Uint32ToFloat4(colorval, col); + GLuint glMask = 0; + if (mask & T3DClear::COLOR) { + glClearColor(col[0], col[1], col[2], col[3]); + glMask |= GL_COLOR_BUFFER_BIT; + } + if (mask & T3DClear::DEPTH) { + glClearDepth(depthVal); + glMask |= GL_DEPTH_BUFFER_BIT; + } + if (mask & T3DClear::STENCIL) { + glClearStencil(stencilVal); + glMask |= GL_STENCIL_BUFFER_BIT; + } + glClear(glMask); +} + +Thin3DContext *T3DCreateGLContext() { + return new Thin3DGLContext(); +} + +void Thin3DGLVertexFormat::Apply() { + for (int i = 0; i < SEM_MAX; i++) { + if (semanticsMask_ & (1 << i)) { + glEnableVertexAttribArray(i); + } + } + for (int i = 0; i < components_.size(); i++) { + switch (components_[i].type) { + case FLOATx2: + glVertexAttribPointer(components_[i].semantic, 2, GL_FLOAT, GL_FALSE, stride_, (void *)(intptr_t)components_[i].offset); + break; + case FLOATx3: + glVertexAttribPointer(components_[i].semantic, 3, GL_FLOAT, GL_FALSE, stride_, (void *)(intptr_t)components_[i].offset); + break; + case FLOATx4: + glVertexAttribPointer(components_[i].semantic, 4, GL_FLOAT, GL_FALSE, stride_, (void *)(intptr_t)components_[i].offset); + break; + case UNORM8x4: + glVertexAttribPointer(components_[i].semantic, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride_, (void *)(intptr_t)components_[i].offset); + break; + } + } +} + +void Thin3DGLVertexFormat::Unapply() { + for (int i = 0; i < SEM_MAX; i++) { + if (semanticsMask_ & (1 << i)) { + glDisableVertexAttribArray(i); + } + } +} \ No newline at end of file From a9b5fe44bf7b2a87c71f2f614d3c7e17eaa9521e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 17 Aug 2014 12:17:59 +0200 Subject: [PATCH 1219/1445] Slip thin3d underneath DrawBuffer/UI --- ext/cityhash/city.cpp | 2 +- gfx_es2/draw_buffer.cpp | 86 ++++++++++++----------------------------- gfx_es2/draw_buffer.h | 28 +++++++++----- gfx_es2/gl_state.cpp | 4 ++ native.vcxproj | 16 +++++--- native.vcxproj.filters | 23 ++++++++++- ui/screen.h | 5 +++ ui/ui.cpp | 7 ++-- ui/ui.h | 2 +- ui/ui_context.cpp | 23 ++++++----- ui/ui_context.h | 19 ++++++--- ui/ui_screen.h | 2 + ui/viewgroup.h | 6 ++- 13 files changed, 122 insertions(+), 101 deletions(-) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 28e766b010..4e088af1c8 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -170,7 +170,7 @@ static uint32 Hash32Len13to24(const char *s, size_t len) { uint32 d = Fetch32(s + (len >> 1)); uint32 e = Fetch32(s); uint32 f = Fetch32(s + len - 4); - uint32 h = len; + uint32 h = (uint32)len; return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h))))))); } diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 4ce0b69ce9..a89f42099b 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -21,7 +21,7 @@ enum { // #define USE_VBO -DrawBuffer::DrawBuffer() : program_(0), count_(0), atlas(0) { +DrawBuffer::DrawBuffer() : count_(0), atlas(0) { verts_ = new Vertex[MAX_VERTS]; fontscalex = 1.0f; fontscaley = 1.0f; @@ -32,30 +32,36 @@ DrawBuffer::~DrawBuffer() { delete [] verts_; } -void DrawBuffer::Init(bool registerAsHolder) { +void DrawBuffer::Init(Thin3DContext *t3d, bool registerAsHolder) { if (inited_) return; + + t3d_ = t3d; + vbuf_ = t3d_->CreateBuffer(MAX_VERTS * sizeof(Vertex), T3DBufferUsage::DYNAMIC | T3DBufferUsage::VERTEXDATA); inited_ = true; - glGenBuffers(1, (GLuint *)&vbo_); - if (registerAsHolder) + + vformat_ = t3d_->CreateVertexFormat(FVF_POS_UV_COLOR); + + if (registerAsHolder) { register_gl_resource_holder(this); + } } void DrawBuffer::Shutdown() { - glDeleteBuffers(1, (GLuint *)&vbo_); - vbo_ = 0; + vbuf_->Release(); + vformat_->Release(); + inited_ = false; unregister_gl_resource_holder(this); } void DrawBuffer::GLLost() { inited_ = false; - Init(false); + Init(t3d_, false); } -void DrawBuffer::Begin(const GLSLProgram *program, DrawBufferMode dbmode) { - Init(); - program_ = program; +void DrawBuffer::Begin(Thin3DShaderSet *program, DrawBufferPrimitiveMode dbmode) { + shaderSet_ = program; count_ = 0; mode_ = dbmode; } @@ -65,63 +71,19 @@ void DrawBuffer::End() { } void DrawBuffer::Flush(bool set_blend_state) { - if (!program_) { + if (!shaderSet_) { ELOG("No program set!"); return; } - glsl_bind(program_); + + vbuf_->SubData((const uint8_t *)verts_, 0, sizeof(Vertex) * count_); if (count_ == 0) return; -#ifdef USE_VBO - glBindBuffer(GL_ARRAY_BUFFER, vbo_); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * count_, verts_, GL_STREAM_DRAW); - if (set_blend_state) { - glstate.blend.enable(); - glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - glUniform1i(program_->sampler0, 0); - glEnableVertexAttribArray(program_->a_position); - glEnableVertexAttribArray(program_->a_color); - if (program_->a_texcoord0 != -1) - glEnableVertexAttribArray(program_->a_texcoord0); - GL_CHECK(); - glVertexAttribPointer(program_->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, x)); - glVertexAttribPointer(program_->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void *)offsetof(Vertex, rgba)); - if (program_->a_texcoord0 != -1) - glVertexAttribPointer(program_->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, u)); - glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_); - GL_CHECK(); - glDisableVertexAttribArray(program_->a_position); - glDisableVertexAttribArray(program_->a_color); - if (program_->a_texcoord0 != -1) - glDisableVertexAttribArray(program_->a_texcoord0); - GL_CHECK(); - glBindBuffer(GL_ARRAY_BUFFER, 0); -#else - if (set_blend_state) { - glstate.blend.enable(); - glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - glBindBuffer(GL_ARRAY_BUFFER, 0); - glUniform1i(program_->sampler0, 0); - glEnableVertexAttribArray(program_->a_position); - glEnableVertexAttribArray(program_->a_color); - if (program_->a_texcoord0 != -1) - glEnableVertexAttribArray(program_->a_texcoord0); - GL_CHECK(); - glVertexAttribPointer(program_->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)&verts_[0].x); - glVertexAttribPointer(program_->a_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void *)&verts_[0].rgba); - if (program_->a_texcoord0 != -1) - glVertexAttribPointer(program_->a_texcoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)&verts_[0].u); - glDrawArrays(mode_ == DBMODE_LINES ? GL_LINES : GL_TRIANGLES, 0, count_); - GL_CHECK(); - glDisableVertexAttribArray(program_->a_position); - glDisableVertexAttribArray(program_->a_color); - if (program_->a_texcoord0 != -1) - glDisableVertexAttribArray(program_->a_texcoord0); - GL_CHECK(); -#endif + + int offset = 0; + + shaderSet_->SetMatrix4x4("WorldViewProj", drawMatrix_); + t3d_->Draw(mode_ == DBMODE_NORMAL ? PRIM_TRIANGLES : PRIM_LINES, shaderSet_, vformat_, vbuf_, count_, offset); count_ = 0; } diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 914f7cc746..112b2a45b4 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -7,6 +7,8 @@ #include "gfx/gl_lost_manager.h" #include "gfx/texture_atlas.h" #include "math/geom2d.h" +#include "math/lin/matrix4x4.h" +#include "thin3d/thin3d.h" #undef DrawText @@ -39,9 +41,9 @@ enum { FLAG_NO_PREFIX = 4096 // means to not process ampersands }; -struct GLSLProgram; +class Thin3DShaderSet; -enum DrawBufferMode { +enum DrawBufferPrimitiveMode { DBMODE_NORMAL = 0, DBMODE_LINES = 1 }; @@ -58,18 +60,18 @@ public: DrawBuffer(); ~DrawBuffer(); - void Begin(const GLSLProgram *program, DrawBufferMode mode = DBMODE_NORMAL); + void Begin(Thin3DShaderSet *shaders, DrawBufferPrimitiveMode mode = DBMODE_NORMAL); void End(); // TODO: Enforce these. Now Init is autocalled and shutdown not called. - void Init(bool registerAsHolder = true); + void Init(Thin3DContext *t3d, bool registerAsHolder = true); void Shutdown(); virtual void GLLost(); int Count() const { return count_; } - void Flush(bool set_blend_state=true); + void Flush(bool set_blend_state = true); void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); void hLine(float x1, float y, float x2, uint32 color); @@ -148,19 +150,27 @@ public: static void DoAlign(int flags, float *x, float *y, float *w, float *h); + void SetDrawMatrix(const Matrix4x4 &m) { + drawMatrix_ = m; + } + private: struct Vertex { float x, y, z; - uint32_t rgba; float u, v; + uint32_t rgba; }; - const GLSLProgram *program_; + Matrix4x4 drawMatrix_; + + Thin3DContext *t3d_; + Thin3DBuffer *vbuf_; + Thin3DVertexFormat *vformat_; + Thin3DShaderSet *shaderSet_; - int vbo_; Vertex *verts_; int count_; - DrawBufferMode mode_; + DrawBufferPrimitiveMode mode_; const Atlas *atlas; bool inited_; diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index a240d0302f..b8f8c95367 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -321,6 +321,10 @@ void CheckGLExtensions() { #endif ProcessGPUFeatures(); + + int error = glGetError(); + if (error) + ELOG("GL error in init: %i", error); } void OpenGLState::SetVSyncInterval(int interval) { diff --git a/native.vcxproj b/native.vcxproj index 831a61317a..fc39463309 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -81,7 +81,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); + ..\dx9sdk\Include;..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); ProgramDatabase true false @@ -102,7 +102,7 @@ Level3 Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); + ..\dx9sdk\Include;..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); true false false @@ -124,7 +124,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); + ..\dx9sdk\Include;..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); StreamingSIMDExtensions2 Fast true @@ -149,7 +149,7 @@ true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); + ..\dx9sdk\Include;..\zlib;..\ext\zlib;..\native;..\RollerballGL;..\native\ext\glew;..\SDL\include;..\native\ext;%(AdditionalIncludeDirectories); NotSet Fast true @@ -272,6 +272,8 @@ + + @@ -756,6 +758,10 @@ + + + + @@ -778,4 +784,4 @@ - + \ No newline at end of file diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 8272c3f79d..5025807740 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -344,6 +344,12 @@ util + + thin3d + + + thin3d + @@ -802,6 +808,18 @@ math\fast + + thin3d + + + thin3d + + + thin3d + + + thin3d + @@ -882,5 +900,8 @@ {5ce64c0e-98e4-4411-86cc-aacaf2f60b21} + + {06c6305a-a646-485b-85b9-645a24dd6553} + - + \ No newline at end of file diff --git a/ui/screen.h b/ui/screen.h index 8992c235a1..1c8aa7da00 100644 --- a/ui/screen.h +++ b/ui/screen.h @@ -35,6 +35,7 @@ enum DialogResult { class ScreenManager; class UIContext; +class Thin3DContext; class Screen { public: @@ -94,6 +95,9 @@ public: void setUIContext(UIContext *context) { uiContext_ = context; } UIContext *getUIContext() { return uiContext_; } + void setThin3DContext(Thin3DContext *context) { thin3DContext_ = context; } + Thin3DContext *getThin3DContext() { return thin3DContext_; } + void render(); void resized(); void deviceLost(); @@ -125,6 +129,7 @@ private: Screen *nextScreen_; UIContext *uiContext_; + Thin3DContext *thin3DContext_; const Screen *dialogFinished_; DialogResult dialogResult_; diff --git a/ui/ui.cpp b/ui/ui.cpp index 08520698a2..e8c4a568c4 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -77,11 +77,11 @@ bool UIRegionHit(int i, int x, int y, int w, int h, int margin) { } } -void UIBegin(const GLSLProgram *shader) { +void UIBegin(Thin3DShaderSet *shaderSet) { for (int i = 0; i < MAX_POINTERS; i++) uistate.hotitem[i] = 0; - ui_draw2d.Begin(shader); - ui_draw2d_front.Begin(shader); + ui_draw2d.Begin(shaderSet); + ui_draw2d_front.Begin(shaderSet); } void UIFlush() { @@ -89,7 +89,6 @@ void UIFlush() { ui_draw2d_front.Flush(); } - void UIEnd() { for (int i = 0; i < MAX_POINTERS; i++) { if (uistate.mousedown[i] == 0) { diff --git a/ui/ui.h b/ui/ui.h index f00dd5f58b..b9f1d72e2f 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -225,7 +225,7 @@ private: bool UIRegionHit(int pointerId, int x, int y, int w, int h, int margin); // Call at start of frame -void UIBegin(const GLSLProgram *shader); +void UIBegin(Thin3DShaderSet *shaderSet); // Call at end of frame. diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 5bac398568..2378e5d7f9 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -17,11 +17,16 @@ UIContext::UIContext() } UIContext::~UIContext() { + blend_->Release(); delete fontStyle_; delete textDrawer_; } -void UIContext::Init(const GLSLProgram *uishader, const GLSLProgram *uishadernotex, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) { +void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DShaderSet *uishadernotex, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) { + thin3d_ = thin3d; + blend_ = thin3d_->GetBlendStatePreset(T3DBlendStatePreset::BS_STANDARD_ALPHA); + depth_ = thin3d_->CreateDepthStencilState(false, false, T3DComparison::LESS); + uishader_ = uishader; uishadernotex_ = uishadernotex; uitexture_ = uitexture; @@ -35,19 +40,15 @@ void UIContext::Init(const GLSLProgram *uishader, const GLSLProgram *uishadernot } void UIContext::Begin() { - glstate.blend.enable(); - glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glstate.blendEquationSeparate.set(GL_FUNC_ADD, GL_FUNC_ADD); + thin3d_->SetBlendState(blend_); + int error = glGetError(); + glstate.cullFace.disable(); glstate.depthTest.disable(); - glstate.dither.enable(); -#if !defined(USING_GLES2) - glstate.colorLogicOp.disable(); -#endif - if (uishader_) - glsl_bind(uishader_); + if (uitexture_) uitexture_->Bind(0); + error = glGetError(); UIBegin(uishader_); } @@ -62,8 +63,6 @@ void UIContext::BeginNoTex() { #if !defined(USING_GLES2) glstate.colorLogicOp.disable(); #endif - if (uishader_) - glsl_bind(uishader_); if (uitexture_) uitexture_->Bind(0); diff --git a/ui/ui_context.h b/ui/ui_context.h index 5fff30ec35..e0be7df327 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -9,7 +9,10 @@ // Everything you need to draw a UI collected into a single unit that can be passed around. // Everything forward declared so this header is safe everywhere. -struct GLSLProgram; +class Thin3DContext; +class Thin3DShaderSet; +class Thin3DDepthStencilState; +class Thin3DBlendState; class Texture; class DrawBuffer; class TextDrawer; @@ -27,7 +30,7 @@ public: UIContext(); ~UIContext(); - void Init(const GLSLProgram *uishader, const GLSLProgram *uishadernotex, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop); + void Init(Thin3DContext *thin3d, Thin3DShaderSet *uiShaderTex, Thin3DShaderSet *uiShaderNoTex, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop); void Begin(); void BeginNoTex(); @@ -63,17 +66,23 @@ public: // in dps, like dp_xres and dp_yres void SetBounds(const Bounds &b) { bounds_ = b; } const Bounds &GetBounds() const { return bounds_; } + Thin3DContext *GetThin3DContext() { return thin3d_; } private: + Thin3DContext *thin3d_; Bounds bounds_; float fontScaleX_; float fontScaleY_; UI::FontStyle *fontStyle_; TextDrawer *textDrawer_; - // TODO: Collect these into a UIContext - const GLSLProgram *uishader_; - const GLSLProgram *uishadernotex_; + + Thin3DContext *thin3D_; + Thin3DDepthStencilState *depth_; + Thin3DBlendState *blend_; + Thin3DShaderSet *uishader_; + Thin3DShaderSet *uishadernotex_; + Texture *uitexture_; DrawBuffer *uidrawbuffer_; DrawBuffer *uidrawbufferTop_; diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 868de6580e..85cc5f7863 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -4,6 +4,7 @@ #include "ui/viewgroup.h" class I18NCategory; +class Thin3DContext; class UIScreen : public Screen { public: @@ -32,6 +33,7 @@ protected: private: void DoRecreateViews(); + bool recreateViews_; int hatDown_; diff --git a/ui/viewgroup.h b/ui/viewgroup.h index e331c63283..4406313117 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -41,7 +41,11 @@ public: // Takes ownership! DO NOT add a view to multiple parents! template - T *Add(T *view) { views_.push_back(view); return view; } + T *Add(T *view) { + lock_guard guard(modifyLock_); + views_.push_back(view); + return view; + } virtual bool SetFocus(); virtual bool SubviewFocused(View *view); From 40b67e27cf62bd50f8f015f711a4ad517268e764 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 17 Aug 2014 12:21:17 +0200 Subject: [PATCH 1220/1445] Crashfix --- ui/ui_context.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 2378e5d7f9..32d308c653 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -17,7 +17,6 @@ UIContext::UIContext() } UIContext::~UIContext() { - blend_->Release(); delete fontStyle_; delete textDrawer_; } From a0f7f877e2e21d1b3b5f8c40cbf5d1908ad7acdc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 17 Aug 2014 14:08:55 +0200 Subject: [PATCH 1221/1445] Fix vertex declarations. Hook up some more of D3D9 (doesn't work yet) --- gfx_es2/draw_buffer.cpp | 7 ++- thin3d/d3dx9_loader.cpp | 6 +- thin3d/thin3d.cpp | 54 ++++++++++++---- thin3d/thin3d.h | 29 +++++++-- thin3d/thin3d_d3d9.cpp | 134 +++++++++++++++++++++++++++++++++++----- thin3d/thin3d_gl.cpp | 36 ++--------- 6 files changed, 197 insertions(+), 69 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index a89f42099b..0d4a9b60e2 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include "base/display.h" @@ -40,7 +41,11 @@ void DrawBuffer::Init(Thin3DContext *t3d, bool registerAsHolder) { vbuf_ = t3d_->CreateBuffer(MAX_VERTS * sizeof(Vertex), T3DBufferUsage::DYNAMIC | T3DBufferUsage::VERTEXDATA); inited_ = true; - vformat_ = t3d_->CreateVertexFormat(FVF_POS_UV_COLOR); + std::vector components; + components.push_back(Thin3DVertexComponent("Position", SEM_POSITION, FLOATx3, 0)); + components.push_back(Thin3DVertexComponent("TexCoord0", SEM_TEXCOORD0, FLOATx2, 12)); + components.push_back(Thin3DVertexComponent("Color0", SEM_COLOR0, UNORM8x4, 20)); + vformat_ = t3d_->CreateVertexFormat(components, 24); if (registerAsHolder) { register_gl_resource_holder(this); diff --git a/thin3d/d3dx9_loader.cpp b/thin3d/d3dx9_loader.cpp index 87e5898c70..a18453045f 100644 --- a/thin3d/d3dx9_loader.cpp +++ b/thin3d/d3dx9_loader.cpp @@ -252,7 +252,7 @@ void UnloadD3DXDynamic() { #define GB_D3D9_D3DXDLL_LOADER_CHECK_ENTRY_NULL_PTR(funcname) assert(false && GB_MAKE_STR2(funcname) ); -BOOL D3DXCheckVersion(UINT D3DSDKVersion, UINT D3DXSDKVersion) { +BOOL dyn_D3DXCheckVersion(UINT D3DSDKVersion, UINT D3DXSDKVersion) { if (!m_TFunc_D3DXCheckVersion) { GB_D3D9_D3DXDLL_LOADER_CHECK_ENTRY_NULL_PTR(D3DXCheckVersion) } @@ -260,7 +260,7 @@ BOOL D3DXCheckVersion(UINT D3DSDKVersion, UINT D3DXSDKVersion) { return m_TFunc_D3DXCheckVersion(D3DSDKVersion, D3DXSDKVersion); } -HRESULT D3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, +HRESULT dyn_D3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER * ppErrorMsgs) { if (!m_TFunc_D3DXAssembleShader) { @@ -270,7 +270,7 @@ HRESULT D3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pD pInclude, Flags, ppShader, ppErrorMsgs); } -HRESULT D3DXCompileShader(LPCSTR pSrcData, UINT srcDataLen, CONST D3DXMACRO* pDefines, +HRESULT dyn_D3DXCompileShader(LPCSTR pSrcData, UINT srcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE * ppConstantTable) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index df652bd33b..df896d145a 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -1,21 +1,30 @@ #include -static const char * const fsTexCol = +static const char * const glsl_fsTexCol = "varying vec4 oColor0;\n" "varying vec2 oTexCoord0;\n" "uniform sampler2D Sampler0;\n" "void main() { gl_FragColor = oColor0 * texture2D(Sampler0, oTexCoord0); }\n"; -static const char * const hlslFsTexCol = ""; +static const char * const hlslFsTexCol = +"struct PS_INPUT { float4 color : COLOR0; float2 uv : TEXCOORD0; };\n" +"sampler2D tex0;\n" +"float4 main(PS_INPUT input) : COLOR0 {\n" +" return input.color * tex2D(tex0, input.uv);\n" +"}\n"; -static const char * const fsCol = +static const char * const glsl_fsCol = "varying vec4 oColor0;\n" "uniform sampler2D Sampler0;\n" "void main() { gl_FragColor = oColor0; }\n"; -static const char * const hlslFsCol = ""; +static const char * const hlslFsCol = +"struct PS_INPUT { float4 color : COLOR0; };\n" +"float4 main(PS_INPUT input) : COLOR0 {\n" +" return input.color;\n" +"}\n"; -static const char * const vsCol = +static const char * const glsl_vsCol = "attribute vec3 Position;\n" "attribute vec4 Color0;\n" "varying vec4 oColor0;\n" @@ -25,9 +34,18 @@ static const char * const vsCol = " oColor0 = Color0;\n" "}"; -static const char * const hlslVsCol = ""; +static const char * const hlslVsCol = +"struct VS_INPUT { float3 Position : POSITION; float4 Color0 : COLOR0; };\n" +"struct VS_OUTPUT { float4 Position : POSITION; float4 Color0 : COLOR0; };\n" +"float4x4 WorldViewProj : WORLDVIEWPROJ;\n" +"VS_OUTPUT main(VS_INPUT input) {\n" +" VS_OUTPUT output;\n" +" output.Position = mul(float4(input.Position, 1.0), WorldViewProj);\n" +" output.Color0 = input.Color0;\n" +" return output;\n" +"}\n"; -static const char * const vsTexCol = +static const char * const glsl_vsTexCol = "attribute vec3 Position;\n" "attribute vec4 Color0;\n" "attribute vec2 TexCoord0;\n" @@ -38,9 +56,19 @@ static const char * const vsTexCol = " gl_Position = WorldViewProj * vec4(Position, 1.0);\n" " oColor0 = Color0;\n" " oTexCoord0 = TexCoord0; \n" -"}"; +"}\n"; -static const char * const hlslVsTexCol = ""; +static const char * const hlslVsTexCol = +"struct VS_INPUT { float3 Position : POSITION; float2 Texcoord0 : TEXCOORD0; float4 Color0 : COLOR0; };\n" +"struct VS_OUTPUT { float4 Position : POSITION; float2 Texcoord0 : TEXCOORD0; float4 Color0 : COLOR0; };\n" +"float4x4 WorldViewProj : WORLDVIEWPROJ;\n" +"VS_OUTPUT main(VS_INPUT input) {\n" +" VS_OUTPUT output;\n" +" output.Position = mul(float4(input.Position, 1.0), WorldViewProj);\n" +" output.Texcoord0 = input.Texcoord0;\n" +" output.Color0 = input.Color0;\n" +" return output;\n" +"}\n"; void Thin3DContext::CreatePresets() { // Build prebuilt objects @@ -54,11 +82,11 @@ void Thin3DContext::CreatePresets() { bsPresets_[BS_STANDARD_ALPHA] = CreateBlendState(standard_alpha); bsPresets_[BS_PREMUL_ALPHA] = CreateBlendState(premul_alpha); - vsPresets_[VS_TEXTURE_COLOR_2D] = CreateVertexShader(vsTexCol, hlslVsTexCol); - vsPresets_[VS_COLOR_2D] = CreateVertexShader(vsCol, hlslVsCol); + vsPresets_[VS_TEXTURE_COLOR_2D] = CreateVertexShader(glsl_vsTexCol, hlslVsTexCol); + vsPresets_[VS_COLOR_2D] = CreateVertexShader(glsl_vsCol, hlslVsCol); - fsPresets_[FS_TEXTURE_COLOR_2D] = CreateFragmentShader(fsTexCol, hlslFsTexCol); - fsPresets_[FS_COLOR_2D] = CreateFragmentShader(fsCol, hlslFsCol); + fsPresets_[FS_TEXTURE_COLOR_2D] = CreateFragmentShader(glsl_fsTexCol, hlslFsTexCol); + fsPresets_[FS_COLOR_2D] = CreateFragmentShader(glsl_fsCol, hlslFsCol); ssPresets_[SS_TEXTURE_COLOR_2D] = CreateShaderSet(vsPresets_[VS_TEXTURE_COLOR_2D], fsPresets_[FS_TEXTURE_COLOR_2D]); ssPresets_[SS_COLOR_2D] = CreateShaderSet(vsPresets_[VS_COLOR_2D], fsPresets_[FS_COLOR_2D]); diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 25d3a95b8b..2773106de5 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -7,6 +7,7 @@ #pragma once #include +#include class Matrix4x4; @@ -50,14 +51,19 @@ enum T3DBufferUsage : int { DYNAMIC = 16, }; -enum T3DVertexFormatPreset : int { - FVF_POS_UV_COLOR +enum T3DVertexDataType : uint8_t { + INVALID, + FLOATx2, + FLOATx3, + FLOATx4, + UNORM8x4, }; enum T3DSemantic : int { SEM_POSITION, SEM_COLOR0, SEM_TEXCOORD0, + SEM_TEXCOORD1, SEM_NORMAL, SEM_TANGENT, SEM_BINORMAL, // really BITANGENT @@ -144,6 +150,20 @@ public: virtual void SetRectangle(int x, int y, int w, int h, const uint8_t *data, int level = 0, int layer = 0); }; +struct Thin3DVertexComponent { + Thin3DVertexComponent() : name(nullptr), type(T3DVertexDataType::INVALID), semantic(255), offset(255) {} + Thin3DVertexComponent(const char *name, T3DSemantic semantic, T3DVertexDataType dataType, uint8_t offset) { + this->name = name; + this->semantic = semantic; + this->type = dataType; + this->offset = offset; + } + const char *name; + T3DVertexDataType type; + uint8_t semantic; + uint8_t offset; +}; + class Thin3DVertexFormat : public Thin3DObject { public: }; @@ -177,7 +197,7 @@ public: virtual Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) = 0; virtual Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0; virtual Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) = 0; - virtual Thin3DVertexFormat *CreateVertexFormat(T3DVertexFormatPreset preset) = 0; + virtual Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) = 0; // Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them. Thin3DBlendState *GetBlendStatePreset(T3DBlendStatePreset preset) { return bsPresets_[preset]; } @@ -216,5 +236,6 @@ private: Thin3DContext *T3DCreateGLContext(); #ifdef _WIN32 -Thin3DContext *T3DCreateDX9Context(); +struct IDirect3DDevice9; +Thin3DContext *T3DCreateDX9Context(IDirect3DDevice9 *device); #endif diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 03964d0eee..46fa230add 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -132,10 +132,11 @@ private: class Thin3DDX9VertexFormat : public Thin3DVertexFormat { public: - int GetVertexSize() { return 0; } - + Thin3DDX9VertexFormat(const std::vector &components, int stride); + int GetStride() const { return stride_; } private: LPDIRECT3DVERTEXDECLARATION9 decl_; + int stride_; }; class Thin3DDX9Shader : public Thin3DShader { @@ -165,11 +166,13 @@ private: LPD3DXCONSTANTTABLE constantTable; }; -class Thin3DDX9Pipeline : public Thin3DShaderSet { +class Thin3DDX9ShaderSet : public Thin3DShaderSet { public: Thin3DDX9Shader *vshader; Thin3DDX9Shader *pshader; void Apply(LPDIRECT3DDEVICE9 device); + void SetVector(const char *name, float *value, int n); + void SetMatrix4x4(const char *name, const Matrix4x4 &value); private: }; @@ -183,10 +186,10 @@ public: Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override; Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override; - Thin3DVertexFormat *CreateVertexFormat(T3DVertexFormatPreset preset) override; + Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) override; - Thin3DShader *CreateVertexShader(const char *glsl_source, const char *hlsl_source); - Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source); + Thin3DShader *CreateVertexShader(const char *glsl_source, const char *hlsl_source) override; + Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source) override; // Bound state objects. Too cumbersome to add them all as parameters to Draw. void SetBlendState(Thin3DBlendState *state); @@ -207,11 +210,11 @@ private: }; Thin3DDX9Context::Thin3DDX9Context(LPDIRECT3DDEVICE9 device) : device_(device) { - CreatePresets(); int d3dx_ver = LoadD3DX9Dynamic(); if (!d3dx_ver) { ELOG("Failed to load D3DX9!"); } + CreatePresets(); } Thin3DDX9Context::~Thin3DDX9Context() { @@ -223,7 +226,7 @@ Thin3DDX9Context::~Thin3DDX9Context() { Thin3DShader *Thin3DDX9Context::CreateVertexShader(const char *glsl_source, const char *hlsl_source) { Thin3DDX9Shader *shader = new Thin3DDX9Shader(false); - if (shader->Compile(device_, hlsl_source, "ps_3_0")) { + if (shader->Compile(device_, hlsl_source, "vs_3_0")) { return shader; } else { delete shader; @@ -233,7 +236,7 @@ Thin3DShader *Thin3DDX9Context::CreateVertexShader(const char *glsl_source, cons Thin3DShader *Thin3DDX9Context::CreateFragmentShader(const char *glsl_source, const char *hlsl_source) { Thin3DDX9Shader *shader = new Thin3DDX9Shader(false); - if (shader->Compile(device_, hlsl_source, "vs_3_0")) { + if (shader->Compile(device_, hlsl_source, "ps_3_0")) { return shader; } else { delete shader; @@ -241,7 +244,14 @@ Thin3DShader *Thin3DDX9Context::CreateFragmentShader(const char *glsl_source, co } } -Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) { +Thin3DShaderSet *Thin3DDX9Context::CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) { + Thin3DDX9ShaderSet *shaderSet = new Thin3DDX9ShaderSet(); + shaderSet->vshader = static_cast(vshader); + shaderSet->pshader = static_cast(fshader); + return shaderSet; +} + +Thin3DDepthStencilState *Thin3DDX9Context::CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) { Thin3DDX9DepthStencilState *ds = new Thin3DDX9DepthStencilState(); ds->depthCompare = compareToD3D9[depthCompare]; ds->depthTestEnabled = depthTestEnabled; @@ -249,6 +259,11 @@ Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool dep return ds; } +Thin3DVertexFormat *Thin3DDX9Context::CreateVertexFormat(const std::vector &components, int stride) { + Thin3DDX9VertexFormat *fmt = new Thin3DDX9VertexFormat(components, stride); + return fmt; +} + Thin3DBlendState *Thin3DDX9Context::CreateBlendState(const T3DBlendStateDesc &desc) { Thin3DDX9BlendState *bs = new Thin3DDX9BlendState(); bs->enabled = desc.enabled; @@ -261,6 +276,56 @@ Thin3DBlendState *Thin3DDX9Context::CreateBlendState(const T3DBlendStateDesc &de return bs; } +void SemanticToD3D9UsageAndIndex(int semantic, BYTE *usage, BYTE *index) { + *index = 0; + switch (semantic) { + case SEM_POSITION: + *usage = D3DDECLUSAGE_POSITION; + break; + case SEM_NORMAL: + *usage = D3DDECLUSAGE_NORMAL; + break; + case SEM_TANGENT: + *usage = D3DDECLUSAGE_TANGENT; + break; + case SEM_BINORMAL: + *usage = D3DDECLUSAGE_BINORMAL; + break; + case SEM_COLOR0: + *usage = D3DDECLUSAGE_COLOR; + break; + case SEM_TEXCOORD0: + *usage = D3DDECLUSAGE_TEXCOORD; + break; + case SEM_TEXCOORD1: + *usage = D3DDECLUSAGE_TEXCOORD; + *index = 1; + break; + } +} + +static int VertexDataTypeToD3DType(T3DVertexDataType type) { + switch (type) { + case T3DVertexDataType::FLOATx2: return D3DDECLTYPE_FLOAT2; + case T3DVertexDataType::FLOATx3: return D3DDECLTYPE_FLOAT3; + case T3DVertexDataType::FLOATx4: return D3DDECLTYPE_FLOAT4; + case T3DVertexDataType::UNORM8x4: return D3DDECLTYPE_UBYTE4; // D3DCOLOR? + default: return D3DDECLTYPE_UNUSED; + } +} + +Thin3DDX9VertexFormat::Thin3DDX9VertexFormat(const std::vector &components, int stride) { + D3DVERTEXELEMENT9 *elements = new D3DVERTEXELEMENT9[components.size()]; + for (int i = 0; i < components.size(); i++) { + elements[i].Stream = 0; + elements[i].Offset = components[i].offset; + elements[i].Method = D3DDECLMETHOD_DEFAULT; + SemanticToD3D9UsageAndIndex(components[i].semantic, &elements[i].Usage, &elements[i].UsageIndex); + elements[i].Type = VertexDataTypeToD3DType(components[i].type); + } + stride_ = stride; +} + void Thin3DDX9Context::SetBlendState(Thin3DBlendState *state) { Thin3DDX9BlendState *bs = static_cast(state); } @@ -269,7 +334,7 @@ Thin3DBuffer *Thin3DDX9Context::CreateBuffer(size_t size, uint32_t usageFlags) { return new Thin3DDX9Buffer(device_, size, usageFlags); } -void Thin3DDX9Pipeline::Apply(LPDIRECT3DDEVICE9 device) { +void Thin3DDX9ShaderSet::Apply(LPDIRECT3DDEVICE9 device) { vshader->Apply(device); pshader->Apply(device); } @@ -277,7 +342,7 @@ void Thin3DDX9Pipeline::Apply(LPDIRECT3DDEVICE9 device) { void Thin3DDX9Context::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) { Thin3DDX9Buffer *vbuf = static_cast(vdata); Thin3DDX9VertexFormat *fmt = static_cast(format); - vbuf->BindVertex(device_, fmt->GetVertexSize(), offset); + vbuf->BindVertex(device_, fmt->GetStride(), offset); device_->DrawPrimitive(primToD3D9[prim], offset, vertexCount / 3); } @@ -285,7 +350,7 @@ void Thin3DDX9Context::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DDX9Buffer *vbuf = static_cast(vdata); Thin3DDX9Buffer *ibuf = static_cast(idata); Thin3DDX9VertexFormat *fmt = static_cast(format); - vbuf->BindVertex(device_, fmt->GetVertexSize(), offset); + vbuf->BindVertex(device_, fmt->GetStride(), offset); ibuf->BindIndex(device_); device_->DrawIndexedPrimitive(primToD3D9[prim], 0, 0, vertexCount, 0, vertexCount / 3); } @@ -302,6 +367,30 @@ Thin3DContext *T3DCreateDX9Context(LPDIRECT3DDEVICE9 device) { return new Thin3DDX9Context(device); } +void Thin3DDX9Context::SetScissorEnabled(bool enable) { + device_->SetRenderState(D3DRS_SCISSORTESTENABLE, enable); +} + +void Thin3DDX9Context::SetScissorRect(int left, int top, int width, int height) { + RECT rc; + rc.left = left; + rc.top = top; + rc.right = left + width; + rc.bottom = top + height; + device_->SetScissorRect(&rc); +} + +void Thin3DDX9Context::SetViewports(int count, T3DViewport *viewports) { + D3DVIEWPORT9 vp; + vp.X = viewports[0].TopLeftX; + vp.Y = viewports[0].TopLeftY; + vp.Width = viewports[0].Width; + vp.Height = viewports[0].Height; + vp.MinZ = viewports[0].MinDepth; + vp.MaxZ = viewports[0].MaxDepth; + device_->SetViewport(&vp); +} + bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, const char *profile) { LPD3DXMACRO defines = NULL; LPD3DXINCLUDE includes = NULL; @@ -310,7 +399,13 @@ bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, cons LPD3DXBUFFER errorBuffer; HRESULT hr = dyn_D3DXCompileShader(source, strlen(source), defines, includes, "main", profile, flags, &codeBuffer, &errorBuffer, &constantTable); if (FAILED(hr)) { - codeBuffer->Release(); + const char *error = (const char *)errorBuffer->GetBufferPointer(); + OutputDebugStringA(source); + OutputDebugStringA(error); + errorBuffer->Release(); + + if (codeBuffer) + codeBuffer->Release(); if (constantTable) constantTable->Release(); return false; @@ -324,8 +419,15 @@ bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, cons HRESULT result = device->CreateVertexShader((DWORD *)codeBuffer->GetBufferPointer(), &vshader); success = SUCCEEDED(result); } - codeBuffer->Release(); - // delete[] code; + codeBuffer->Release(); return true; } + +void Thin3DDX9ShaderSet::SetVector(const char *name, float *value, int n) { + +} + +void Thin3DDX9ShaderSet::SetMatrix4x4(const char *name, const Matrix4x4 &value) { + +} diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 207ce2aa1a..872a73b229 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -177,28 +177,6 @@ bool Thin3DGLShader::Compile(const char *source) { return ok_; } -enum T3DVertexDataType : uint8_t { - INVALID, - FLOATx2, - FLOATx3, - FLOATx4, - UNORM8x4, -}; - -struct Thin3DVertexComponent { - Thin3DVertexComponent() : name(nullptr), type(T3DVertexDataType::INVALID), semantic(255), offset(255) {} - Thin3DVertexComponent(const char *name, T3DSemantic semantic, T3DVertexDataType dataType, uint8_t offset) { - this->name = name; - this->semantic = semantic; - this->type = dataType; - this->offset = offset; - } - const char *name; - T3DVertexDataType type; - uint8_t semantic; - uint8_t offset; -}; - class Thin3DGLVertexFormat : public Thin3DVertexFormat { public: void Apply(); @@ -253,7 +231,7 @@ public: Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override; Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override; - Thin3DVertexFormat *CreateVertexFormat(T3DVertexFormatPreset preset) override; + Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) override; // Bound state objects void SetBlendState(Thin3DBlendState *state) override { @@ -296,16 +274,10 @@ Thin3DGLContext::Thin3DGLContext() { Thin3DGLContext::~Thin3DGLContext() { } -Thin3DVertexFormat *Thin3DGLContext::CreateVertexFormat(T3DVertexFormatPreset preset) { +Thin3DVertexFormat *Thin3DGLContext::CreateVertexFormat(const std::vector &components, int stride) { Thin3DGLVertexFormat *fmt = new Thin3DGLVertexFormat(); - switch (preset) { - case FVF_POS_UV_COLOR: - fmt->components_.push_back(Thin3DVertexComponent("Position", SEM_POSITION, FLOATx3, 0)); - fmt->components_.push_back(Thin3DVertexComponent("TexCoord0", SEM_TEXCOORD0, FLOATx2, 12)); - fmt->components_.push_back(Thin3DVertexComponent("Color0", SEM_COLOR0, UNORM8x4, 20)); - fmt->stride_ = 24; - break; - } + fmt->components_ = components; + fmt->stride_ = stride; fmt->Compile(); return fmt; } From 1251b6df798c7c658431e9db32e1087dd1474fc0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 17 Aug 2014 15:02:43 +0200 Subject: [PATCH 1222/1445] Thin3d: Add some untested texturing stuff --- thin3d/thin3d.cpp | 17 +++++++- thin3d/thin3d.h | 31 ++++++++++++++- thin3d/thin3d_d3d9.cpp | 89 +++++++++++++++++++++++++++++++++++++++++- thin3d/thin3d_gl.cpp | 76 ++++++++++++++++++++++++++++++++++++ 4 files changed, 210 insertions(+), 3 deletions(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index df896d145a..cd72881942 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -1,5 +1,7 @@ #include +#include "image/zim_load.h" + static const char * const glsl_fsTexCol = "varying vec4 oColor0;\n" "varying vec2 oTexCoord0;\n" @@ -105,4 +107,17 @@ Thin3DContext::~Thin3DContext() { for (int i = 0; i < SS_MAX_PRESET; i++) { ssPresets_[i]->Release(); } -} \ No newline at end of file +} + +Thin3DTexture *Thin3DContext::CreateTextureFromFile(const char *filename) { + int width[16], height[16], flags; + uint8_t *image[16] = { nullptr }; + + int num_levels = LoadZIM(filename, width, height, &flags, image); + Thin3DTexture *tex = CreateTexture(LINEAR2D, RGBA8888, width[0], height[0], 1, num_levels); + for (int i = 0; i < num_levels; i++) { + tex->SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]); + free(image[i]); + } + return tex; +} diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 2773106de5..69575b5788 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -147,7 +147,8 @@ public: class Thin3DTexture : public Thin3DObject { public: - virtual void SetRectangle(int x, int y, int w, int h, const uint8_t *data, int level = 0, int layer = 0); + virtual void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) = 0; + virtual void AutoGenMipmaps() = 0; }; struct Thin3DVertexComponent { @@ -190,14 +191,37 @@ struct T3DBlendStateDesc { // int colorMask; }; +enum T3DTextureType : uint8_t { + LINEAR1D, + LINEAR2D, + LINEAR3D, + CUBE, + ARRAY1D, + ARRAY2D, +}; + +enum T3DImageFormat : uint8_t { + RGBA8888, + DXT1, + ETC1, // Needs simulation on many platforms + D16, + D24S8, + D24X8, +}; + class Thin3DContext : public Thin3DObject { public: virtual ~Thin3DContext(); + virtual Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) = 0; virtual Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) = 0; virtual Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0; virtual Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) = 0; virtual Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) = 0; + virtual Thin3DTexture *CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) = 0; + + // Common Thin3D function, uses CreateTexture + Thin3DTexture *CreateTextureFromFile(const char *filename); // Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them. Thin3DBlendState *GetBlendStatePreset(T3DBlendStatePreset preset) { return bsPresets_[preset]; } @@ -211,6 +235,11 @@ public: // Bound state objects. Too cumbersome to add them all as parameters to Draw. virtual void SetBlendState(Thin3DBlendState *state) = 0; + virtual void SetTextures(int start, int count, Thin3DTexture **textures) = 0; + + void SetTexture(int stage, Thin3DTexture *texture) { + SetTextures(stage, 1, &texture); + } // from sampler 0 and upwards // Raster state virtual void SetScissorEnabled(bool enable) = 0; diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 46fa230add..11da0ae2e5 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -173,10 +173,82 @@ public: void Apply(LPDIRECT3DDEVICE9 device); void SetVector(const char *name, float *value, int n); void SetMatrix4x4(const char *name, const Matrix4x4 &value); - private: }; +class Thin3DDX9Texture : public Thin3DTexture { +public: + Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels); + void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) override; + void AutoGenMipmaps() {} + void SetToSampler(LPDIRECT3DDEVICE9 device, int sampler); + +private: + T3DTextureType type_; + D3DFORMAT fmt_; + LPDIRECT3DTEXTURE9 tex_; + LPDIRECT3DVOLUMETEXTURE9 volTex_; + LPDIRECT3DCUBETEXTURE9 cubeTex_; +}; + +D3DFORMAT FormatToD3D(T3DImageFormat fmt) { + switch (fmt) { + case RGBA8888: return D3DFMT_A8B8G8R8; + case D24S8: return D3DFMT_D24S8; + case D16: return D3DFMT_D16; + default: return D3DFMT_UNKNOWN; + } +} + +Thin3DDX9Texture::Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) + : type_(type) { + fmt_ = FormatToD3D(format); + HRESULT hr; + switch (type_) { + case LINEAR1D: + case LINEAR2D: + hr = device->CreateTexture(width, height, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &tex_, NULL); + break; + case LINEAR3D: + hr = device->CreateVolumeTexture(width, height, depth, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &volTex_, NULL); + break; + case CUBE: + hr = device->CreateCubeTexture(width, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &cubeTex_, NULL); + break; + } +} + +void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) { + switch (type_) { + case LINEAR2D: + // tex_->LockRect() + + break; + + default: + // TODO + break; + } +} + +void Thin3DDX9Texture::SetToSampler(LPDIRECT3DDEVICE9 device, int sampler) { + switch (type_) { + case LINEAR1D: + case LINEAR2D: + device->SetTexture(sampler, tex_); + break; + + case LINEAR3D: + device->SetTexture(sampler, volTex_); + break; + + case CUBE: + device->SetTexture(sampler, cubeTex_); + break; + } +} + + class Thin3DDX9Context : public Thin3DContext { public: Thin3DDX9Context(LPDIRECT3DDEVICE9 device); @@ -187,6 +259,7 @@ public: Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override; Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) override; + Thin3DTexture *CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override; Thin3DShader *CreateVertexShader(const char *glsl_source, const char *hlsl_source) override; Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source) override; @@ -194,6 +267,8 @@ public: // Bound state objects. Too cumbersome to add them all as parameters to Draw. void SetBlendState(Thin3DBlendState *state); + void SetTextures(int start, int count, Thin3DTexture **textures); + // Raster state void SetScissorEnabled(bool enable); void SetScissorRect(int left, int top, int width, int height); @@ -276,6 +351,18 @@ Thin3DBlendState *Thin3DDX9Context::CreateBlendState(const T3DBlendStateDesc &de return bs; } +Thin3DTexture *Thin3DDX9Context::CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) { + Thin3DDX9Texture *tex = new Thin3DDX9Texture(device_, type, format, width, height, depth, mipLevels); + return tex; +} + +void Thin3DDX9Context::SetTextures(int start, int count, Thin3DTexture **textures) { + for (int i = start; i < start + count; i++) { + Thin3DDX9Texture *tex = static_cast(textures[i - start]); + tex->SetToSampler(device_, i); + } +} + void SemanticToD3D9UsageAndIndex(int semantic, BYTE *usage, BYTE *index) { *index = 0; switch (semantic) { diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 872a73b229..32a1cdd5b7 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -232,6 +232,7 @@ public: Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override; Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) override; + Thin3DTexture *CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override; // Bound state objects void SetBlendState(Thin3DBlendState *state) override { @@ -261,6 +262,8 @@ public: glstate.depthRange.set(viewports[0].MinDepth, viewports[0].MaxDepth); } + void SetTextures(int start, int count, Thin3DTexture **textures) override; + // TODO: Add more sophisticated draws. void Draw(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) override; void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; @@ -282,6 +285,69 @@ Thin3DVertexFormat *Thin3DGLContext::CreateVertexFormat(const std::vector(textures[i]); + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, glTex->tex_); + } + glActiveTexture(GL_TEXTURE0); +} + + Thin3DShader *Thin3DGLContext::CreateVertexShader(const char *glsl_source, const char *hlsl_source) { Thin3DGLShader *shader = new Thin3DGLShader(false); if (shader->Compile(glsl_source)) { From bf41d05dfc6829e0a4e1624280c3343d70695990 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 17 Aug 2014 15:29:50 +0200 Subject: [PATCH 1223/1445] Switch to Thin3DTexture. GL still works, d3d still broken. --- thin3d/thin3d.cpp | 17 ++++++++++++++++- thin3d/thin3d.h | 10 ++++++++++ thin3d/thin3d_d3d9.cpp | 41 ++++++++++++++++++----------------------- ui/ui_context.cpp | 16 ++++------------ ui/ui_context.h | 5 +++-- 5 files changed, 51 insertions(+), 38 deletions(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index cd72881942..99028aa34c 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -109,12 +109,27 @@ Thin3DContext::~Thin3DContext() { } } +static T3DImageFormat ZimToT3DFormat(int zim) { + switch (zim) { + case ZIM_ETC1: return T3DImageFormat::ETC1; + case ZIM_RGBA8888: return T3DImageFormat::RGBA8888; + case ZIM_LUMINANCE: return T3DImageFormat::LUMINANCE; + default: return T3DImageFormat::RGBA8888; + } +} + Thin3DTexture *Thin3DContext::CreateTextureFromFile(const char *filename) { int width[16], height[16], flags; uint8_t *image[16] = { nullptr }; int num_levels = LoadZIM(filename, width, height, &flags, image); - Thin3DTexture *tex = CreateTexture(LINEAR2D, RGBA8888, width[0], height[0], 1, num_levels); + if (num_levels == 0) { + return NULL; + } + + T3DImageFormat fmt = ZimToT3DFormat(flags & ZIM_FORMAT_MASK); + + Thin3DTexture *tex = CreateTexture(LINEAR2D, fmt, width[0], height[0], 1, num_levels); for (int i = 0; i < num_levels; i++) { tex->SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]); free(image[i]); diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 69575b5788..59c3af38f9 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -201,6 +201,7 @@ enum T3DTextureType : uint8_t { }; enum T3DImageFormat : uint8_t { + LUMINANCE, RGBA8888, DXT1, ETC1, // Needs simulation on many platforms @@ -251,6 +252,12 @@ public: virtual void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) = 0; virtual void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) = 0; + // Necessary to correctly flip scissor rectangles etc for OpenGL. + void SetTargetSize(int w, int h) { + targetWidth_ = w; + targetHeight_ = h; + } + protected: void CreatePresets(); @@ -259,6 +266,9 @@ protected: Thin3DBlendState *bsPresets_[BS_MAX_PRESET]; Thin3DShaderSet *ssPresets_[SS_MAX_PRESET]; + int targetWidth_; + int targetHeight_; + private: }; diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 11da0ae2e5..a621a5f64f 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -141,29 +141,29 @@ private: class Thin3DDX9Shader : public Thin3DShader { public: - Thin3DDX9Shader(bool isPixelShader) : isPixelShader_(isPixelShader), vshader(NULL), pshader(NULL) {} + Thin3DDX9Shader(bool isPixelShader) : isPixelShader_(isPixelShader), vshader_(NULL), pshader_(NULL) {} ~Thin3DDX9Shader() { - if (vshader) - vshader->Release(); - if (pshader) - pshader->Release(); - if (constantTable) - constantTable->Release(); + if (vshader_) + vshader_->Release(); + if (pshader_) + pshader_->Release(); + if (constantTable_) + constantTable_->Release(); } bool Compile(LPDIRECT3DDEVICE9 device, const char *source, const char *profile); void Apply(LPDIRECT3DDEVICE9 device) { if (isPixelShader_) { - device->SetPixelShader(pshader); + device->SetPixelShader(pshader_); } else { - device->SetVertexShader(vshader); + device->SetVertexShader(vshader_); } } private: bool isPixelShader_; - LPDIRECT3DVERTEXSHADER9 vshader; - LPDIRECT3DPIXELSHADER9 pshader; - LPD3DXCONSTANTTABLE constantTable; + LPDIRECT3DVERTEXSHADER9 vshader_; + LPDIRECT3DPIXELSHADER9 pshader_; + LPD3DXCONSTANTTABLE constantTable_; }; class Thin3DDX9ShaderSet : public Thin3DShaderSet { @@ -222,7 +222,6 @@ void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height, switch (type_) { case LINEAR2D: // tex_->LockRect() - break; default: @@ -293,10 +292,6 @@ Thin3DDX9Context::Thin3DDX9Context(LPDIRECT3DDEVICE9 device) : device_(device) { } Thin3DDX9Context::~Thin3DDX9Context() { - for (int i = 0; i < BS_MAX_PRESET; i++) { - bsPresets_[i]->Release(); - } - } Thin3DShader *Thin3DDX9Context::CreateVertexShader(const char *glsl_source, const char *hlsl_source) { @@ -484,7 +479,7 @@ bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, cons DWORD flags = 0; LPD3DXBUFFER codeBuffer; LPD3DXBUFFER errorBuffer; - HRESULT hr = dyn_D3DXCompileShader(source, strlen(source), defines, includes, "main", profile, flags, &codeBuffer, &errorBuffer, &constantTable); + HRESULT hr = dyn_D3DXCompileShader(source, strlen(source), defines, includes, "main", profile, flags, &codeBuffer, &errorBuffer, &constantTable_); if (FAILED(hr)) { const char *error = (const char *)errorBuffer->GetBufferPointer(); OutputDebugStringA(source); @@ -493,17 +488,17 @@ bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, cons if (codeBuffer) codeBuffer->Release(); - if (constantTable) - constantTable->Release(); + if (constantTable_) + constantTable_->Release(); return false; } bool success = false; if (isPixelShader_) { - HRESULT result = device->CreatePixelShader((DWORD *)codeBuffer->GetBufferPointer(), &pshader); + HRESULT result = device->CreatePixelShader((DWORD *)codeBuffer->GetBufferPointer(), &pshader_); success = SUCCEEDED(result); } else { - HRESULT result = device->CreateVertexShader((DWORD *)codeBuffer->GetBufferPointer(), &vshader); + HRESULT result = device->CreateVertexShader((DWORD *)codeBuffer->GetBufferPointer(), &vshader_); success = SUCCEEDED(result); } @@ -512,7 +507,7 @@ bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, cons } void Thin3DDX9ShaderSet::SetVector(const char *name, float *value, int n) { - + } void Thin3DDX9ShaderSet::SetMatrix4x4(const char *name, const Matrix4x4 &value) { diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 32d308c653..b824afbd87 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -5,7 +5,6 @@ #include "gfx/texture.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/draw_text.h" -#include "gfx_es2/glsl_program.h" #include "gfx_es2/gl_state.h" UIContext::UIContext() @@ -21,7 +20,7 @@ UIContext::~UIContext() { delete textDrawer_; } -void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DShaderSet *uishadernotex, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) { +void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DShaderSet *uishadernotex, Thin3DTexture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) { thin3d_ = thin3d; blend_ = thin3d_->GetBlendStatePreset(T3DBlendStatePreset::BS_STANDARD_ALPHA); depth_ = thin3d_->CreateDepthStencilState(false, false, T3DComparison::LESS); @@ -40,14 +39,9 @@ void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DSha void UIContext::Begin() { thin3d_->SetBlendState(blend_); - int error = glGetError(); - glstate.cullFace.disable(); glstate.depthTest.disable(); - - if (uitexture_) - uitexture_->Bind(0); - error = glGetError(); + thin3d_->SetTexture(0, uitexture_); UIBegin(uishader_); } @@ -62,15 +56,13 @@ void UIContext::BeginNoTex() { #if !defined(USING_GLES2) glstate.colorLogicOp.disable(); #endif - if (uitexture_) - uitexture_->Bind(0); +// thin3d_->SetTexture(0, uitexture_); UIBegin(uishadernotex_); } void UIContext::RebindTexture() const { - if (uitexture_) - uitexture_->Bind(0); + thin3d_->SetTexture(0, uitexture_); } void UIContext::Flush() { diff --git a/ui/ui_context.h b/ui/ui_context.h index e0be7df327..d7960d34b4 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -12,6 +12,7 @@ class Thin3DContext; class Thin3DShaderSet; class Thin3DDepthStencilState; +class Thin3DTexture; class Thin3DBlendState; class Texture; class DrawBuffer; @@ -30,7 +31,7 @@ public: UIContext(); ~UIContext(); - void Init(Thin3DContext *thin3d, Thin3DShaderSet *uiShaderTex, Thin3DShaderSet *uiShaderNoTex, Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop); + void Init(Thin3DContext *thin3d, Thin3DShaderSet *uiShaderTex, Thin3DShaderSet *uiShaderNoTex, Thin3DTexture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop); void Begin(); void BeginNoTex(); @@ -82,8 +83,8 @@ private: Thin3DBlendState *blend_; Thin3DShaderSet *uishader_; Thin3DShaderSet *uishadernotex_; + Thin3DTexture *uitexture_; - Texture *uitexture_; DrawBuffer *uidrawbuffer_; DrawBuffer *uidrawbufferTop_; From 29a60b59527154b87739c2a327cb856faa96735c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 17 Aug 2014 16:04:27 +0200 Subject: [PATCH 1224/1445] Thin3d: Add cull mode, other fixes --- thin3d/thin3d.h | 20 +++++++++++++++++--- thin3d/thin3d_d3d9.cpp | 26 +++++++++++++++++++++----- thin3d/thin3d_gl.cpp | 21 +++++++++++++++++++++ ui/ui_context.cpp | 23 +++++++---------------- 4 files changed, 66 insertions(+), 24 deletions(-) diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 59c3af38f9..11ecb19c04 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -104,9 +104,9 @@ enum T3DBlendStatePreset : int { }; enum T3DClear : int { - COLOR, - DEPTH, - STENCIL, + COLOR = 1, + DEPTH = 2, + STENCIL = 4, }; // Binary compatible with D3D11 viewport. @@ -210,6 +210,16 @@ enum T3DImageFormat : uint8_t { D24X8, }; +enum T3DRenderState : uint8_t { + CULL_MODE, +}; + +enum T3DCullMode : uint8_t { + NO_CULL, + CW, + CCW, +}; + class Thin3DContext : public Thin3DObject { public: virtual ~Thin3DContext(); @@ -236,6 +246,7 @@ public: // Bound state objects. Too cumbersome to add them all as parameters to Draw. virtual void SetBlendState(Thin3DBlendState *state) = 0; + virtual void SetDepthStencilState(Thin3DDepthStencilState *state) = 0; virtual void SetTextures(int start, int count, Thin3DTexture **textures) = 0; void SetTexture(int stage, Thin3DTexture *texture) { @@ -247,6 +258,9 @@ public: virtual void SetScissorRect(int left, int top, int width, int height) = 0; virtual void SetViewports(int count, T3DViewport *viewports) = 0; + // Single render states that aren't worth state blocks. May have to convert some of these state blocks on D3D11 though... + virtual void SetRenderState(T3DRenderState rs, uint32_t value) = 0; + // TODO: Add more sophisticated draws with buffer offsets, and multidraws. virtual void Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) = 0; virtual void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) = 0; diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index a621a5f64f..5b648ba383 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -264,7 +264,14 @@ public: Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source) override; // Bound state objects. Too cumbersome to add them all as parameters to Draw. - void SetBlendState(Thin3DBlendState *state); + void SetBlendState(Thin3DBlendState *state) { + Thin3DDX9BlendState *bs = static_cast(state); + bs->Apply(device_); + } + void SetDepthStencilState(Thin3DDepthStencilState *state) { + Thin3DDX9DepthStencilState *bs = static_cast(state); + bs->Apply(device_); + } void SetTextures(int start, int count, Thin3DTexture **textures); @@ -272,6 +279,7 @@ public: void SetScissorEnabled(bool enable); void SetScissorRect(int left, int top, int width, int height); void SetViewports(int count, T3DViewport *viewports); + void SetRenderState(T3DRenderState rs, uint32_t value) override; void Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) override; void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; @@ -408,10 +416,6 @@ Thin3DDX9VertexFormat::Thin3DDX9VertexFormat(const std::vector(state); -} - Thin3DBuffer *Thin3DDX9Context::CreateBuffer(size_t size, uint32_t usageFlags) { return new Thin3DDX9Buffer(device_, size, usageFlags); } @@ -421,6 +425,18 @@ void Thin3DDX9ShaderSet::Apply(LPDIRECT3DDEVICE9 device) { pshader->Apply(device); } +void Thin3DDX9Context::SetRenderState(T3DRenderState rs, uint32_t value) { + switch (rs) { + case T3DRenderState::CULL_MODE: + switch (value) { + case T3DCullMode::CCW: device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); + case T3DCullMode::CW: device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); + case T3DCullMode::NO_CULL: device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + } + break; + } +} + void Thin3DDX9Context::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) { Thin3DDX9Buffer *vbuf = static_cast(vdata); Thin3DDX9VertexFormat *fmt = static_cast(format); diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 32a1cdd5b7..5f0a0ac44d 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -69,6 +69,7 @@ public: glstate.blend.set(enabled); glstate.blendEquationSeparate.set(eqCol, eqAlpha); glstate.blendFuncSeparate.set(srcCol, dstCol, srcAlpha, dstAlpha); + glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // glstate.blendColor.set(fixedColor); #if !defined(USING_GLES2) @@ -240,6 +241,12 @@ public: s->Apply(); } + // Bound state objects + void SetDepthStencilState(Thin3DDepthStencilState *state) override { + Thin3DGLDepthStencilState *s = static_cast(state); + s->Apply(); + } + // The implementation makes the choice of which shader code to use. Thin3DShader *CreateVertexShader(const char *glsl_source, const char *hlsl_source); Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source); @@ -264,6 +271,8 @@ public: void SetTextures(int start, int count, Thin3DTexture **textures) override; + void SetRenderState(T3DRenderState rs, uint32_t value) override; + // TODO: Add more sophisticated draws. void Draw(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) override; void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; @@ -517,6 +526,18 @@ void Thin3DGLShaderSet::Unapply() { glUseProgram(0); } +void Thin3DGLContext::SetRenderState(T3DRenderState rs, uint32_t value) { + switch (rs) { + case T3DRenderState::CULL_MODE: + switch (value) { + case T3DCullMode::NO_CULL: glstate.cullFace.disable(); break; + case T3DCullMode::CCW: glstate.cullFace.enable(); glstate.cullFaceMode.set(GL_CCW); break; + case T3DCullMode::CW: glstate.cullFace.enable(); glstate.cullFaceMode.set(GL_CW); break; + } + break; + } +} + void Thin3DGLContext::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) { Thin3DGLShaderSet *pipe = static_cast(pipeline); Thin3DGLBuffer *vbuf = static_cast(vdata); diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index b824afbd87..51c5f7a82e 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -5,7 +5,6 @@ #include "gfx/texture.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/draw_text.h" -#include "gfx_es2/gl_state.h" UIContext::UIContext() : uishader_(0), uitexture_(0), uidrawbuffer_(0), uidrawbufferTop_(0) { @@ -39,24 +38,16 @@ void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DSha void UIContext::Begin() { thin3d_->SetBlendState(blend_); - glstate.cullFace.disable(); - glstate.depthTest.disable(); + thin3d_->SetDepthStencilState(depth_); + thin3d_->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL); thin3d_->SetTexture(0, uitexture_); UIBegin(uishader_); } void UIContext::BeginNoTex() { - glstate.blend.enable(); - glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glstate.blendEquationSeparate.set(GL_FUNC_ADD, GL_FUNC_ADD); - glstate.cullFace.disable(); - glstate.depthTest.disable(); - glstate.dither.enable(); -#if !defined(USING_GLES2) - glstate.colorLogicOp.disable(); -#endif -// thin3d_->SetTexture(0, uitexture_); + thin3d_->SetBlendState(blend_); + thin3d_->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL); UIBegin(uishadernotex_); } @@ -113,10 +104,10 @@ void UIContext::ActivateTopScissor() { int w = scale * bounds.w; int h = scale * bounds.h; - glstate.scissorRect.set(x, y, w, h); - glstate.scissorTest.enable(); + thin3d_->SetScissorRect(x, y, w, h); + thin3d_->SetScissorEnabled(true); } else { - glstate.scissorTest.disable(); + thin3d_->SetScissorEnabled(false); } } From 54b298a63ec0bf338c88c0fff4268bf0c2d744ea Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 17 Aug 2014 21:28:34 +0200 Subject: [PATCH 1225/1445] More Thin3D work (textures etc) --- image/zim_load.cpp | 2 +- image/zim_load.h | 2 +- math/lin/matrix4x4.cpp | 11 ++++ math/lin/matrix4x4.h | 1 + thin3d/thin3d.cpp | 43 +++++++++++++-- thin3d/thin3d.h | 17 +++++- thin3d/thin3d_d3d9.cpp | 116 ++++++++++++++++++++++++++++++++--------- thin3d/thin3d_gl.cpp | 40 ++++++++++++-- ui/view.cpp | 23 ++++++++ ui/view.h | 22 ++++++++ 10 files changed, 242 insertions(+), 35 deletions(-) diff --git a/image/zim_load.cpp b/image/zim_load.cpp index 65a29e434d..bcaa25bd5c 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -54,7 +54,7 @@ static unsigned int log2i(unsigned int val) { return ret; } -int LoadZIMPtr(uint8_t *zim, int datasize, int *width, int *height, int *flags, uint8 **image) { +int LoadZIMPtr(const uint8_t *zim, int datasize, int *width, int *height, int *flags, uint8 **image) { if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') { ELOG("Not a ZIM file"); return 0; diff --git a/image/zim_load.h b/image/zim_load.h index cc4d514269..bc98f459c8 100644 --- a/image/zim_load.h +++ b/image/zim_load.h @@ -48,4 +48,4 @@ enum { // Watch out! If the image has mipmaps, multiple values will be written // to width, height, and image, as if they were arrays, up to 12 (max texture size is 4096 which is 2^12). int LoadZIM(const char *filename, int *width, int *height, int *flags, uint8_t **image); -int LoadZIMPtr(char *zim, int datasize, int *width, int *height, int *flags, uint8_t **image); \ No newline at end of file +int LoadZIMPtr(const uint8_t *zim, int datasize, int *width, int *height, int *flags, uint8_t **image); \ No newline at end of file diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp index 318655cdcc..c0b2d2d280 100644 --- a/math/lin/matrix4x4.cpp +++ b/math/lin/matrix4x4.cpp @@ -211,6 +211,17 @@ void Matrix4x4::setOrtho(float left, float right, float bottom, float top, float wz = -(far + near) / (far - near); } +void Matrix4x4::setOrthoD3D(float left, float right, float bottom, float top, float near, float far) { + setIdentity(); + xx = 2.0f / (right - left); + yy = 2.0f / (top - bottom); + zz = 1.0f / (far - near); + wx = -(right + left) / (right - left); + wy = -(top + bottom) / (top - bottom); + //wz = -(far + near) / (far - near); + wz = -near / (far - near); +} + void Matrix4x4::setProjectionInf(const float near_plane, const float fov_horiz, const float aspect) { empty(); float f = fov_horiz*0.5f; diff --git a/math/lin/matrix4x4.h b/math/lin/matrix4x4.h index ca1345015a..00c9074486 100644 --- a/math/lin/matrix4x4.h +++ b/math/lin/matrix4x4.h @@ -112,6 +112,7 @@ public: void setProjectionD3D(float near_plane, float far_plane, float fov_horiz, float aspect = 0.75f); void setProjectionInf(float near_plane, float fov_horiz, float aspect = 0.75f); void setOrtho(float left, float right, float bottom, float top, float near, float far); + void setOrthoD3D(float left, float right, float bottom, float top, float near, float far); void setShadow(float Lx, float Ly, float Lz, float Lw) { float Pa=0; float Pb=1; diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 99028aa34c..8568641e36 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -1,6 +1,7 @@ #include #include "image/zim_load.h" +#include "image/png_load.h" static const char * const glsl_fsTexCol = "varying vec4 oColor0;\n" @@ -39,7 +40,7 @@ static const char * const glsl_vsCol = static const char * const hlslVsCol = "struct VS_INPUT { float3 Position : POSITION; float4 Color0 : COLOR0; };\n" "struct VS_OUTPUT { float4 Position : POSITION; float4 Color0 : COLOR0; };\n" -"float4x4 WorldViewProj : WORLDVIEWPROJ;\n" +"float4x4 WorldViewProj;\n" "VS_OUTPUT main(VS_INPUT input) {\n" " VS_OUTPUT output;\n" " output.Position = mul(float4(input.Position, 1.0), WorldViewProj);\n" @@ -63,7 +64,7 @@ static const char * const glsl_vsTexCol = static const char * const hlslVsTexCol = "struct VS_INPUT { float3 Position : POSITION; float2 Texcoord0 : TEXCOORD0; float4 Color0 : COLOR0; };\n" "struct VS_OUTPUT { float4 Position : POSITION; float2 Texcoord0 : TEXCOORD0; float4 Color0 : COLOR0; };\n" -"float4x4 WorldViewProj : WORLDVIEWPROJ;\n" +"float4x4 WorldViewProj;\n" "VS_OUTPUT main(VS_INPUT input) {\n" " VS_OUTPUT output;\n" " output.Position = mul(float4(input.Position, 1.0), WorldViewProj);\n" @@ -118,7 +119,7 @@ static T3DImageFormat ZimToT3DFormat(int zim) { } } -Thin3DTexture *Thin3DContext::CreateTextureFromFile(const char *filename) { +Thin3DTexture *Thin3DContext::CreateTextureFromFile(const char *filename, T3DFileType type) { int width[16], height[16], flags; uint8_t *image[16] = { nullptr }; @@ -136,3 +137,39 @@ Thin3DTexture *Thin3DContext::CreateTextureFromFile(const char *filename) { } return tex; } + +Thin3DTexture *Thin3DContext::CreateTextureFromFileData(const char *data, int size, T3DFileType type) { + int width[16], height[16], zim_flags = 0; + uint8_t *image[16] = { nullptr }; + + int num_levels = 0; + T3DImageFormat fmt; + + switch (type) { + case ZIM: + num_levels = LoadZIMPtr((const uint8_t *)data, size, width, height, &zim_flags, image); + fmt = ZimToT3DFormat(zim_flags & ZIM_FORMAT_MASK); + break; + + case PNG: + if (1 != pngLoadPtr((const unsigned char *)data, size, &width[0], &height[0], &image[0], false)) { + return false; + } + num_levels = 1; + fmt = RGBA8888; + break; + } + + if (num_levels == 0) { + return NULL; + } + + Thin3DTexture *tex = CreateTexture(LINEAR2D, fmt, width[0], height[0], 1, num_levels); + for (int i = 0; i < num_levels; i++) { + tex->SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]); + free(image[i]); + } + + tex->Finalize(zim_flags); + return tex; +} diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 11ecb19c04..4de0b86ef6 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -149,6 +149,13 @@ class Thin3DTexture : public Thin3DObject { public: virtual void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) = 0; virtual void AutoGenMipmaps() = 0; + virtual void Finalize(int zim_flags) = 0; // TODO: Tidy up + + int Width() { return width_; } + int Height() { return height_; } + int Depth() { return depth_; } +protected: + int width_, height_, depth_; }; struct Thin3DVertexComponent { @@ -220,6 +227,13 @@ enum T3DCullMode : uint8_t { CCW, }; +enum T3DFileType { + PNG, + JPEG, + ZIM, + DETECT, +}; + class Thin3DContext : public Thin3DObject { public: virtual ~Thin3DContext(); @@ -232,7 +246,8 @@ public: virtual Thin3DTexture *CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) = 0; // Common Thin3D function, uses CreateTexture - Thin3DTexture *CreateTextureFromFile(const char *filename); + Thin3DTexture *CreateTextureFromFile(const char *filename, T3DFileType fileType); + Thin3DTexture *CreateTextureFromFileData(const char *data, int size, T3DFileType fileType); // Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them. Thin3DBlendState *GetBlendStatePreset(T3DBlendStatePreset preset) { return bsPresets_[preset]; } diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 5b648ba383..af760cce63 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -4,6 +4,7 @@ #include #include "base/logging.h" +#include "math/lin/matrix4x4.h" #include "thin3d/thin3d.h" #include "thin3d/d3dx9_loader.h" @@ -115,11 +116,11 @@ public: ibuffer_->Unlock(); } } - void BindVertex(LPDIRECT3DDEVICE9 device, int vertexSize, int offset = 0) { + void BindAsVertexBuf(LPDIRECT3DDEVICE9 device, int vertexSize, int offset = 0) { if (vbuffer_) device->SetStreamSource(0, vbuffer_, offset, vertexSize); } - void BindIndex(LPDIRECT3DDEVICE9 device) { + void BindAsIndexBuf(LPDIRECT3DDEVICE9 device) { if (ibuffer_) device->SetIndices(ibuffer_); } @@ -132,8 +133,11 @@ private: class Thin3DDX9VertexFormat : public Thin3DVertexFormat { public: - Thin3DDX9VertexFormat(const std::vector &components, int stride); + Thin3DDX9VertexFormat(LPDIRECT3DDEVICE9 device, const std::vector &components, int stride); int GetStride() const { return stride_; } + void Apply(LPDIRECT3DDEVICE9 device) { + device->SetVertexDeclaration(decl_); + } private: LPDIRECT3DVERTEXDECLARATION9 decl_; int stride_; @@ -158,6 +162,8 @@ public: device->SetVertexShader(vshader_); } } + void SetVector(LPDIRECT3DDEVICE9 device, const char *name, float *value, int n); + void SetMatrix4x4(LPDIRECT3DDEVICE9 device, const char *name, const Matrix4x4 &value); private: bool isPixelShader_; @@ -168,20 +174,23 @@ private: class Thin3DDX9ShaderSet : public Thin3DShaderSet { public: + Thin3DDX9ShaderSet(LPDIRECT3DDEVICE9 device) : device_(device) {} Thin3DDX9Shader *vshader; Thin3DDX9Shader *pshader; void Apply(LPDIRECT3DDEVICE9 device); - void SetVector(const char *name, float *value, int n); - void SetMatrix4x4(const char *name, const Matrix4x4 &value); + void SetVector(const char *name, float *value, int n) { vshader->SetVector(device_, name, value, n); pshader->SetVector(device_, name, value, n); } + void SetMatrix4x4(const char *name, const Matrix4x4 &value) { vshader->SetMatrix4x4(device_, name, value); } // pshaders don't usually have matrices private: + LPDIRECT3DDEVICE9 device_; }; class Thin3DDX9Texture : public Thin3DTexture { public: Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels); void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) override; - void AutoGenMipmaps() {} + void AutoGenMipmaps() override {} void SetToSampler(LPDIRECT3DDEVICE9 device, int sampler); + void Finalize(int zim_flags) override {} private: T3DTextureType type_; @@ -193,7 +202,7 @@ private: D3DFORMAT FormatToD3D(T3DImageFormat fmt) { switch (fmt) { - case RGBA8888: return D3DFMT_A8B8G8R8; + case RGBA8888: return D3DFMT_A8R8G8B8; case D24S8: return D3DFMT_D24S8; case D16: return D3DFMT_D16; default: return D3DFMT_UNKNOWN; @@ -202,6 +211,10 @@ D3DFORMAT FormatToD3D(T3DImageFormat fmt) { Thin3DDX9Texture::Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) : type_(type) { + width_ = width; + height_ = height; + depth_ = depth; + tex_ = NULL; fmt_ = FormatToD3D(format); HRESULT hr; switch (type_) { @@ -219,10 +232,29 @@ Thin3DDX9Texture::Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type } void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) { + if (!tex_) { + return; + } + if (level == 0) { + width_ = width; + height_ = height; + depth_ = depth; + } + switch (type_) { case LINEAR2D: + { + D3DLOCKED_RECT rect; + if (x == 0 && y == 0) { + tex_->LockRect(level, &rect, NULL, D3DLOCK_DISCARD); + for (int i = 0; i < height; i++) { + memcpy((uint8_t *)rect.pBits + rect.Pitch * i, data + stride * i, width * 4); + } + tex_->UnlockRect(level); + } // tex_->LockRect() break; + } default: // TODO @@ -323,7 +355,7 @@ Thin3DShader *Thin3DDX9Context::CreateFragmentShader(const char *glsl_source, co } Thin3DShaderSet *Thin3DDX9Context::CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) { - Thin3DDX9ShaderSet *shaderSet = new Thin3DDX9ShaderSet(); + Thin3DDX9ShaderSet *shaderSet = new Thin3DDX9ShaderSet(device_); shaderSet->vshader = static_cast(vshader); shaderSet->pshader = static_cast(fshader); return shaderSet; @@ -338,7 +370,7 @@ Thin3DDepthStencilState *Thin3DDX9Context::CreateDepthStencilState(bool depthTes } Thin3DVertexFormat *Thin3DDX9Context::CreateVertexFormat(const std::vector &components, int stride) { - Thin3DDX9VertexFormat *fmt = new Thin3DDX9VertexFormat(components, stride); + Thin3DDX9VertexFormat *fmt = new Thin3DDX9VertexFormat(device_, components, stride); return fmt; } @@ -404,15 +436,24 @@ static int VertexDataTypeToD3DType(T3DVertexDataType type) { } } -Thin3DDX9VertexFormat::Thin3DDX9VertexFormat(const std::vector &components, int stride) { - D3DVERTEXELEMENT9 *elements = new D3DVERTEXELEMENT9[components.size()]; - for (int i = 0; i < components.size(); i++) { +Thin3DDX9VertexFormat::Thin3DDX9VertexFormat(LPDIRECT3DDEVICE9 device, const std::vector &components, int stride) { + D3DVERTEXELEMENT9 *elements = new D3DVERTEXELEMENT9[components.size() + 1]; + int i; + for (i = 0; i < components.size(); i++) { elements[i].Stream = 0; elements[i].Offset = components[i].offset; elements[i].Method = D3DDECLMETHOD_DEFAULT; SemanticToD3D9UsageAndIndex(components[i].semantic, &elements[i].Usage, &elements[i].UsageIndex); elements[i].Type = VertexDataTypeToD3DType(components[i].type); } + D3DVERTEXELEMENT9 end = D3DDECL_END(); + // Zero the last one. + memcpy(&elements[i], &end, sizeof(elements[i])); + + HRESULT hr = device->CreateVertexDeclaration(elements, &decl_); + if (FAILED(hr)) { + ELOG("Error creating vertex decl"); + } stride_ = stride; } @@ -429,27 +470,35 @@ void Thin3DDX9Context::SetRenderState(T3DRenderState rs, uint32_t value) { switch (rs) { case T3DRenderState::CULL_MODE: switch (value) { - case T3DCullMode::CCW: device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); - case T3DCullMode::CW: device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); - case T3DCullMode::NO_CULL: device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + case T3DCullMode::CCW: device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); break; + case T3DCullMode::CW: device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); break; + case T3DCullMode::NO_CULL: device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); break; } break; } } -void Thin3DDX9Context::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) { +void Thin3DDX9Context::Draw(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) { Thin3DDX9Buffer *vbuf = static_cast(vdata); Thin3DDX9VertexFormat *fmt = static_cast(format); - vbuf->BindVertex(device_, fmt->GetStride(), offset); + Thin3DDX9ShaderSet *ss = static_cast(shaderSet); + + ss->Apply(device_); + fmt->Apply(device_); + vbuf->BindAsVertexBuf(device_, fmt->GetStride(), offset); device_->DrawPrimitive(primToD3D9[prim], offset, vertexCount / 3); } -void Thin3DDX9Context::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) { +void Thin3DDX9Context::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) { Thin3DDX9Buffer *vbuf = static_cast(vdata); Thin3DDX9Buffer *ibuf = static_cast(idata); Thin3DDX9VertexFormat *fmt = static_cast(format); - vbuf->BindVertex(device_, fmt->GetStride(), offset); - ibuf->BindIndex(device_); + Thin3DDX9ShaderSet *ss = static_cast(shaderSet); + + ss->Apply(device_); + fmt->Apply(device_); + vbuf->BindAsVertexBuf(device_, fmt->GetStride(), offset); + ibuf->BindAsIndexBuf(device_); device_->DrawIndexedPrimitive(primToD3D9[prim], 0, 0, vertexCount, 0, vertexCount / 3); } @@ -518,14 +567,33 @@ bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, cons success = SUCCEEDED(result); } + D3DXCONSTANTTABLE_DESC desc; + constantTable_->GetDesc(&desc); + + //D3DXCONSTANT_DESC *descs = new D3DXCONSTANT_DESC[desc.Constants]; + //constantTable_->GetConstantDesc() + for (int i = 0; i < desc.Constants; i++) { + D3DXHANDLE c = constantTable_->GetConstant(NULL, i); + D3DXCONSTANT_DESC cdesc; + UINT count = 1; + constantTable_->GetConstantDesc(c, &cdesc, &count); + ILOG("%s", cdesc.Name); + } + codeBuffer->Release(); return true; } -void Thin3DDX9ShaderSet::SetVector(const char *name, float *value, int n) { - +void Thin3DDX9Shader::SetVector(LPDIRECT3DDEVICE9 device, const char *name, float *value, int n) { + D3DXHANDLE handle = constantTable_->GetConstantByName(NULL, name); + if (handle) { + constantTable_->SetFloatArray(device, handle, value, n); + } } -void Thin3DDX9ShaderSet::SetMatrix4x4(const char *name, const Matrix4x4 &value) { - +void Thin3DDX9Shader::SetMatrix4x4(LPDIRECT3DDEVICE9 device, const char *name, const Matrix4x4 &value) { + D3DXHANDLE handle = constantTable_->GetConstantByName(NULL, name); + if (handle) { + constantTable_->SetFloatArray(device, handle, value.getReadPtr(), 16); + } } diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 5f0a0ac44d..5d749dce1d 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -4,6 +4,7 @@ #include #include "base/logging.h" +#include "image/zim_load.h" #include "math/lin/matrix4x4.h" #include "thin3d/thin3d.h" #include "gfx_es2/gl_state.h" @@ -317,12 +318,17 @@ public: void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) override; void AutoGenMipmaps() override; - GLuint tex_; + void Bind() { + glBindTexture(target_, tex_); + } + void Finalize(int zim_flags); private: + GLuint tex_; GLuint target_; + T3DImageFormat format_; - int width_, height_, depth_, mipLevels_; + int mipLevels_; }; Thin3DTexture *Thin3DGLContext::CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) { @@ -336,6 +342,12 @@ void Thin3DGLTexture::AutoGenMipmaps() { } void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) { + if (level == 0) { + width_ = width; + height_ = height; + depth_ = depth; + } + int internalFormat; int format; int type; @@ -357,6 +369,25 @@ void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, i } } +bool isPowerOf2(int n) { + return n == 1 || (n & (n - 1)) == 0; +} + +void Thin3DGLTexture::Finalize(int zim_flags) { + GLenum wrap = GL_REPEAT; + if ((zim_flags & ZIM_CLAMP) || !isPowerOf2(width_) || !isPowerOf2(height_)) + wrap = GL_CLAMP_TO_EDGE; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } +} + + void Thin3DGLVertexFormat::Compile() { int sem = 0; for (int i = 0; i < (int)components_.size(); i++) { @@ -408,10 +439,10 @@ Thin3DShaderSet *Thin3DGLContext::CreateShaderSet(Thin3DShader *vshader, Thin3DS } void Thin3DGLContext::SetTextures(int start, int count, Thin3DTexture **textures) { - for (int i = start; i < count; i++) { + for (int i = start; i < start + count; i++) { Thin3DGLTexture *glTex = static_cast(textures[i]); glActiveTexture(GL_TEXTURE0 + i); - glBindTexture(GL_TEXTURE_2D, glTex->tex_); + glTex->Bind(); } glActiveTexture(GL_TEXTURE0); } @@ -545,7 +576,6 @@ void Thin3DGLContext::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DV vbuf->Bind(); fmt->Apply(); - pipe->Apply(); glDrawArrays(primToGL[prim], offset, vertexCount); diff --git a/ui/view.cpp b/ui/view.cpp index 0b63de5651..422d8ac857 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -11,6 +11,7 @@ #include "ui/ui.h" #include "ui/view.h" #include "ui/ui_context.h" +#include "thin3d/thin3d.h" #include "base/NativeApp.h" namespace UI { @@ -535,6 +536,28 @@ void TextureView::Draw(UIContext &dc) { } } +void Thin3DTextureView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { + // TODO: involve sizemode + if (texture_) { + w = (float)texture_->Width(); + h = (float)texture_->Height(); + } else { + w = 16; + h = 16; + } +} + +void Thin3DTextureView::Draw(UIContext &dc) { + // TODO: involve sizemode + if (texture_) { + dc.Flush(); + dc.GetThin3DContext()->SetTexture(0, texture_); + dc.Draw()->Rect(bounds_.x, bounds_.y, bounds_.w, bounds_.h, color_); + dc.Flush(); + dc.RebindTexture(); + } +} + ImageFileView::ImageFileView(std::string filename, ImageSizeMode sizeMode, LayoutParams *layoutParams) : InertView(layoutParams), color_(0xFFFFFFFF), sizeMode_(sizeMode) { texture_ = new Texture(); diff --git a/ui/view.h b/ui/view.h index 1010e99eef..5db4c00b48 100644 --- a/ui/view.h +++ b/ui/view.h @@ -33,6 +33,9 @@ class DrawBuffer; class Texture; class UIContext; +class Thin3DTexture; + + // I don't generally like namespaces but I think we do need one for UI, so many potentially-clashing names. namespace UI { @@ -725,6 +728,25 @@ private: ImageSizeMode sizeMode_; }; +// TextureView takes a texture that is assumed to be alive during the lifetime +// of the view. +class Thin3DTextureView : public InertView { +public: + Thin3DTextureView(Thin3DTexture *texture, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0) + : InertView(layoutParams), texture_(texture), sizeMode_(sizeMode) {} + + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + virtual void Draw(UIContext &dc); + + void SetTexture(Thin3DTexture *texture) { texture_ = texture; } + void SetColor(uint32_t color) { color_ = color; } + +private: + Thin3DTexture *texture_; + uint32_t color_; + ImageSizeMode sizeMode_; +}; + // ImageFileView takes a filename and keeps track of the texture by itself. class ImageFileView : public InertView { public: From 8774fcad94e6a8ee913730af8247ff1da8578490 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 18 Aug 2014 19:35:14 +0200 Subject: [PATCH 1226/1445] Some more thin3d --- thin3d/thin3d.cpp | 2 +- thin3d/thin3d_d3d9.cpp | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 8568641e36..7c74d6b933 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -11,7 +11,7 @@ static const char * const glsl_fsTexCol = static const char * const hlslFsTexCol = "struct PS_INPUT { float4 color : COLOR0; float2 uv : TEXCOORD0; };\n" -"sampler2D tex0;\n" +"sampler2D tex0 : register(s0);\n" "float4 main(PS_INPUT input) : COLOR0 {\n" " return input.color * tex2D(tex0, input.uv);\n" "}\n"; diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index af760cce63..c2b1457128 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -106,14 +106,18 @@ public: void SubData(const uint8_t *data, size_t offset, size_t size) override { if (vbuffer_) { void *ptr; - vbuffer_->Lock((UINT)offset, (UINT)size, &ptr, D3DLOCK_DISCARD); - memcpy(ptr, data, size); - vbuffer_->Unlock(); + HRESULT res = vbuffer_->Lock((UINT)offset, (UINT)size, &ptr, D3DLOCK_DISCARD); + if (!FAILED(res)) { + memcpy(ptr, data, size); + vbuffer_->Unlock(); + } } else if (ibuffer_) { void *ptr; - ibuffer_->Lock((UINT)offset, (UINT)size, &ptr, D3DLOCK_DISCARD); - memcpy(ptr, data, size); - ibuffer_->Unlock(); + HRESULT res = ibuffer_->Lock((UINT)offset, (UINT)size, &ptr, D3DLOCK_DISCARD); + if (!FAILED(res)) { + memcpy(ptr, data, size); + ibuffer_->Unlock(); + } } } void BindAsVertexBuf(LPDIRECT3DDEVICE9 device, int vertexSize, int offset = 0) { @@ -483,9 +487,15 @@ void Thin3DDX9Context::Draw(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3 Thin3DDX9VertexFormat *fmt = static_cast(format); Thin3DDX9ShaderSet *ss = static_cast(shaderSet); + device_->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device_->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + device_->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + device_->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + device_->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + + vbuf->BindAsVertexBuf(device_, fmt->GetStride(), offset); ss->Apply(device_); fmt->Apply(device_); - vbuf->BindAsVertexBuf(device_, fmt->GetStride(), offset); device_->DrawPrimitive(primToD3D9[prim], offset, vertexCount / 3); } From ecb33f005e787bd340422b9872bc1ac86ef3ac9e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 22 Aug 2014 01:24:34 +0200 Subject: [PATCH 1227/1445] Thin3D now actually draws some stuff --- gfx_es2/draw_buffer.cpp | 2 +- thin3d/thin3d_d3d9.cpp | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 0d4a9b60e2..78128035e5 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -81,9 +81,9 @@ void DrawBuffer::Flush(bool set_blend_state) { return; } - vbuf_->SubData((const uint8_t *)verts_, 0, sizeof(Vertex) * count_); if (count_ == 0) return; + vbuf_->SubData((const uint8_t *)verts_, 0, sizeof(Vertex) * count_); int offset = 0; diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index c2b1457128..f312ddad34 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -1,5 +1,10 @@ #include #include + +#ifdef _DEBUG +#define D3D_DEBUG_INFO +#endif + #include #include @@ -81,7 +86,7 @@ public: class Thin3DDX9Buffer : public Thin3DBuffer { public: - Thin3DDX9Buffer(LPDIRECT3DDEVICE9 device, size_t size, uint32_t flags) : vbuffer_(nullptr), ibuffer_(nullptr) { + Thin3DDX9Buffer(LPDIRECT3DDEVICE9 device, size_t size, uint32_t flags) : vbuffer_(nullptr), ibuffer_(nullptr), maxSize_(size) { if (flags & T3DBufferUsage::INDEXDATA) { DWORD usage = 0; device->CreateIndexBuffer((UINT)size, usage, D3DFMT_INDEX32, D3DPOOL_MANAGED, &ibuffer_, NULL); @@ -91,6 +96,12 @@ public: } } void SetData(const uint8_t *data, size_t size) override { + if (!size) + return; + if (size > maxSize_) { + ELOG("Can't SetData with bigger size than buffer was created with on D3D"); + return; + } if (vbuffer_) { void *ptr; vbuffer_->Lock(0, (UINT)size, &ptr, D3DLOCK_DISCARD); @@ -104,6 +115,12 @@ public: } } void SubData(const uint8_t *data, size_t offset, size_t size) override { + if (!size) + return; + if (offset + size > maxSize_) { + ELOG("Can't SubData with bigger size than buffer was created with on D3D"); + return; + } if (vbuffer_) { void *ptr; HRESULT res = vbuffer_->Lock((UINT)offset, (UINT)size, &ptr, D3DLOCK_DISCARD); @@ -132,12 +149,18 @@ public: private: LPDIRECT3DVERTEXBUFFER9 vbuffer_; LPDIRECT3DINDEXBUFFER9 ibuffer_; + int maxSize_; }; class Thin3DDX9VertexFormat : public Thin3DVertexFormat { public: Thin3DDX9VertexFormat(LPDIRECT3DDEVICE9 device, const std::vector &components, int stride); + ~Thin3DDX9VertexFormat() { + if (decl_) { + decl_->Release(); + } + } int GetStride() const { return stride_; } void Apply(LPDIRECT3DDEVICE9 device) { device->SetVertexDeclaration(decl_); @@ -349,7 +372,7 @@ Thin3DShader *Thin3DDX9Context::CreateVertexShader(const char *glsl_source, cons } Thin3DShader *Thin3DDX9Context::CreateFragmentShader(const char *glsl_source, const char *hlsl_source) { - Thin3DDX9Shader *shader = new Thin3DDX9Shader(false); + Thin3DDX9Shader *shader = new Thin3DDX9Shader(true); if (shader->Compile(device_, hlsl_source, "ps_3_0")) { return shader; } else { @@ -435,12 +458,12 @@ static int VertexDataTypeToD3DType(T3DVertexDataType type) { case T3DVertexDataType::FLOATx2: return D3DDECLTYPE_FLOAT2; case T3DVertexDataType::FLOATx3: return D3DDECLTYPE_FLOAT3; case T3DVertexDataType::FLOATx4: return D3DDECLTYPE_FLOAT4; - case T3DVertexDataType::UNORM8x4: return D3DDECLTYPE_UBYTE4; // D3DCOLOR? + case T3DVertexDataType::UNORM8x4: return D3DDECLTYPE_UBYTE4N; // D3DCOLOR? default: return D3DDECLTYPE_UNUSED; } } -Thin3DDX9VertexFormat::Thin3DDX9VertexFormat(LPDIRECT3DDEVICE9 device, const std::vector &components, int stride) { +Thin3DDX9VertexFormat::Thin3DDX9VertexFormat(LPDIRECT3DDEVICE9 device, const std::vector &components, int stride) : decl_(NULL) { D3DVERTEXELEMENT9 *elements = new D3DVERTEXELEMENT9[components.size() + 1]; int i; for (i = 0; i < components.size(); i++) { From a1ff7a44884a9babcf0a5ef52a79f4af2f888165 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 22 Aug 2014 19:55:39 +0200 Subject: [PATCH 1228/1445] Thin3D: Add APIName query. Swizzle texture colors in D3D. (not sure whether it's best done in the shader or in the texture data...) --- thin3d/thin3d.cpp | 2 +- thin3d/thin3d.h | 2 ++ thin3d/thin3d_d3d9.cpp | 2 ++ thin3d/thin3d_gl.cpp | 9 +++++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 7c74d6b933..4ce2a275b3 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -13,7 +13,7 @@ static const char * const hlslFsTexCol = "struct PS_INPUT { float4 color : COLOR0; float2 uv : TEXCOORD0; };\n" "sampler2D tex0 : register(s0);\n" "float4 main(PS_INPUT input) : COLOR0 {\n" -" return input.color * tex2D(tex0, input.uv);\n" +" return input.color * tex2D(tex0, input.uv).bgra;\n" "}\n"; static const char * const glsl_fsCol = diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 4de0b86ef6..e6f9dfa87b 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -287,6 +287,8 @@ public: targetHeight_ = h; } + virtual const char *GetAPIName() const = 0; + protected: void CreatePresets(); diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index f312ddad34..037a184c66 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -344,6 +344,8 @@ public: void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal); + const char *GetAPIName() const override { return "Direct3D9"; } + private: // void CompileShader(const char *hlsl_source); diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 5d749dce1d..257b7a5621 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -278,6 +278,15 @@ public: void Draw(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) override; void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override; + + const char *GetAPIName() const override { +#ifdef USING_GLES2 + return "OpenGL ES"; +#else + return "OpenGL"; +#endif + } + }; Thin3DGLContext::Thin3DGLContext() { From ff5df25135423a06357d5e455be19acfec81663f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 22 Aug 2014 20:47:40 +0200 Subject: [PATCH 1229/1445] Add Thin3d support to draw_text (Qt not touched) --- gfx_es2/draw_text.cpp | 27 +++++++++++------------ gfx_es2/draw_text.h | 16 ++++++++++++-- thin3d/thin3d.cpp | 2 +- thin3d/thin3d.h | 13 +++++++++-- thin3d/thin3d_d3d9.cpp | 49 ++++++++++++++++++++++++++++++++++++++---- thin3d/thin3d_gl.cpp | 46 +++++++++++++++++++++++---------------- ui/ui_context.cpp | 2 +- 7 files changed, 112 insertions(+), 43 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index dff9a6a080..53baf045c9 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -1,9 +1,9 @@ #include "base/logging.h" #include "base/stringutil.h" -#include "gfx/gl_common.h" -#include "gfx_es2/draw_text.h" +#include "thin3d/thin3d.h" #include "util/hash/hash.h" #include "util/text/utf8.h" +#include "gfx_es2/draw_text.h" #ifdef USING_QT_UI #include @@ -32,9 +32,10 @@ struct TextDrawerContext { int *pBitmapBits; }; -TextDrawer::TextDrawer() { +TextDrawer::TextDrawer(Thin3DContext *thin3d) : thin3d_(thin3d), ctx_(NULL) { fontScaleX_ = 1.0f; fontScaleY_ = 1.0f; + ctx_ = new TextDrawerContext(); ctx_->hDC = CreateCompatibleDC(NULL); @@ -55,7 +56,7 @@ TextDrawer::TextDrawer() { TextDrawer::~TextDrawer() { for (auto iter = cache_.begin(); iter != cache_.end(); ++iter) { - glDeleteTextures(1, &iter->second->textureHandle); + iter->second->texture->Release(); delete iter->second; } cache_.clear(); @@ -123,6 +124,9 @@ void TextDrawer::MeasureString(const char *str, float *w, float *h) { } void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align) { + if (!strlen(str)) + return; + uint32_t stringHash = hash::Fletcher((const uint8_t *)str, strlen(str)); uint32_t entryHash = stringHash ^ fontHash_; @@ -134,7 +138,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float if (iter != cache_.end()) { entry = iter->second; entry->lastUsedFrame = frameCount_; - glBindTexture(GL_TEXTURE_2D, entry->textureHandle); + thin3d_->SetTexture(0, entry->texture); } else { // Render the string to our bitmap and save to a GL texture. std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(str, "\n", "\r\n")); @@ -163,30 +167,23 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float DrawTextExW(ctx_->hDC, (LPWSTR)wstr.c_str(), (int)wstr.size(), &rc, DT_HIDEPREFIX|DT_TOP|DT_LEFT, 0); entry = new TextStringEntry(); - glGenTextures(1, &entry->textureHandle); - glBindTexture(GL_TEXTURE_2D, entry->textureHandle); entry->width = size.cx; entry->height = size.cy; entry->bmWidth = (size.cx + 3) & ~3; entry->bmHeight = (size.cy + 3) & ~3; entry->lastUsedFrame = frameCount_; + entry->texture = thin3d_->CreateTexture(LINEAR2D, RGBA4444, entry->bmWidth, entry->bmHeight, 1, 0); // Convert the bitmap to a gl-compatible array of pixels. uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight]; - for (int y = 0; y < entry->bmHeight; y++) { for (int x = 0; x < entry->bmWidth; x++) { BYTE bAlpha = (BYTE)((ctx_->pBitmapBits[MAX_TEXT_WIDTH * y + x] & 0xff) >> 4); bitmapData[entry->bmWidth * y + x] = (bAlpha) | 0xfff0; // ^ rand(); } } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, entry->bmWidth, entry->bmHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, bitmapData); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - + entry->texture->SetImageData(0, 0, 0, entry->bmWidth, entry->bmHeight, 1, 0, entry->bmWidth * 2, (const uint8_t *)bitmapData); + entry->texture->Finalize(0); delete [] bitmapData; cache_[entryHash] = entry; diff --git a/gfx_es2/draw_text.h b/gfx_es2/draw_text.h index 4280180ec8..3d94a0528e 100644 --- a/gfx_es2/draw_text.h +++ b/gfx_es2/draw_text.h @@ -12,13 +12,23 @@ #include "base/basictypes.h" #include "gfx_es2/draw_buffer.h" +#if !(defined(_WIN32) && !defined(USING_QT_UI)) +#include "gfx_es2/gl_state.h" +#endif + +class Thin3DContext; +class Thin3DTexture; #ifdef USING_QT_UI #include #endif struct TextStringEntry { - uint32_t textureHandle; +#if defined(_WIN32) && !defined(USING_QT_UI) + Thin3DTexture *texture; +#else + GLuint textureHandle; +#endif int width; int height; int bmWidth; @@ -38,7 +48,7 @@ struct TextDrawerFontContext; class TextDrawer { public: - TextDrawer(); + TextDrawer(Thin3DContext *thin3d); ~TextDrawer(); uint32_t SetFont(const char *fontName, int size, int flags); @@ -52,6 +62,8 @@ public: void OncePerFrame(); private: + Thin3DContext *thin3d_; + int frameCount_; float fontScaleX_; float fontScaleY_; diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 4ce2a275b3..7c74d6b933 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -13,7 +13,7 @@ static const char * const hlslFsTexCol = "struct PS_INPUT { float4 color : COLOR0; float2 uv : TEXCOORD0; };\n" "sampler2D tex0 : register(s0);\n" "float4 main(PS_INPUT input) : COLOR0 {\n" -" return input.color * tex2D(tex0, input.uv).bgra;\n" +" return input.color * tex2D(tex0, input.uv);\n" "}\n"; static const char * const glsl_fsCol = diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index e6f9dfa87b..45fbf8ac35 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -147,7 +147,7 @@ public: class Thin3DTexture : public Thin3DObject { public: - virtual void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) = 0; + virtual void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) = 0; virtual void AutoGenMipmaps() = 0; virtual void Finalize(int zim_flags) = 0; // TODO: Tidy up @@ -210,6 +210,7 @@ enum T3DTextureType : uint8_t { enum T3DImageFormat : uint8_t { LUMINANCE, RGBA8888, + RGBA4444, DXT1, ETC1, // Needs simulation on many platforms D16, @@ -234,6 +235,14 @@ enum T3DFileType { DETECT, }; +enum T3DInfo { + APINAME, + APIVERSION, + VENDOR, + SHADELANGVERSION, + RENDERER, +}; + class Thin3DContext : public Thin3DObject { public: virtual ~Thin3DContext(); @@ -287,7 +296,7 @@ public: targetHeight_ = h; } - virtual const char *GetAPIName() const = 0; + virtual const char *GetInfoString(T3DInfo info) const = 0; protected: void CreatePresets(); diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 037a184c66..e55b690289 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -214,7 +214,7 @@ private: class Thin3DDX9Texture : public Thin3DTexture { public: Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels); - void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) override; + void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override; void AutoGenMipmaps() override {} void SetToSampler(LPDIRECT3DDEVICE9 device, int sampler); void Finalize(int zim_flags) override {} @@ -230,6 +230,7 @@ private: D3DFORMAT FormatToD3D(T3DImageFormat fmt) { switch (fmt) { case RGBA8888: return D3DFMT_A8R8G8B8; + case RGBA4444: return D3DFMT_A4R4G4B4; case D24S8: return D3DFMT_D24S8; case D16: return D3DFMT_D16; default: return D3DFMT_UNKNOWN; @@ -256,9 +257,22 @@ Thin3DDX9Texture::Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type hr = device->CreateCubeTexture(width, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &cubeTex_, NULL); break; } + if (FAILED(hr)) { + ELOG("Texture creation failed"); + } } -void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) { +inline uint16_t Shuffle4444(uint16_t x) { + return (x << 12) | (x >> 4); +} + +// A rather different transform, for curious reasons.. +inline uint32_t Shuffle8888(uint32_t x) { + return (x & 0xFF00FF00) | ((x >> 16) & 0xFF) | ((x << 16) & 0xFF0000); +} + + +void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) { if (!tex_) { return; } @@ -274,8 +288,25 @@ void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height, D3DLOCKED_RECT rect; if (x == 0 && y == 0) { tex_->LockRect(level, &rect, NULL, D3DLOCK_DISCARD); + for (int i = 0; i < height; i++) { - memcpy((uint8_t *)rect.pBits + rect.Pitch * i, data + stride * i, width * 4); + uint8_t *dest = (uint8_t *)rect.pBits + rect.Pitch * i; + const uint8_t *source = data + stride * i; + int j; + switch (fmt_) { + case D3DFMT_A4R4G4B4: + // This is backwards from OpenGL so we need to shuffle around a bit. + for (j = 0; j < width; j++) { + ((uint16_t *)dest)[j] = Shuffle4444(((uint16_t *)source)[j]); + } + break; + + case D3DFMT_A8R8G8B8: + for (j = 0; j < width; j++) { + ((uint32_t *)dest)[j] = Shuffle8888(((uint32_t *)source)[j]); + } + break; + } } tex_->UnlockRect(level); } @@ -344,7 +375,17 @@ public: void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal); - const char *GetAPIName() const override { return "Direct3D9"; } + const char *GetInfoString(T3DInfo info) const override { + // TODO: Make these actually query the right information + switch (info) { + case APIVERSION: return "DirectX 9.0"; + case VENDOR: return "?"; + case RENDERER: return "?"; + case SHADELANGVERSION: return "3.0"; + case APINAME: return "Direct3D 9"; + default: return "?"; + } + } private: // void CompileShader(const char *hlsl_source); diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 257b7a5621..f179b6135f 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -279,12 +279,21 @@ public: void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override; - const char *GetAPIName() const override { -#ifdef USING_GLES2 - return "OpenGL ES"; -#else - return "OpenGL"; -#endif + const char *GetInfoString(T3DInfo info) const override { + // TODO: Make these actually query the right information + switch (info) { + case APINAME: + #ifdef USING_GLES2 + return "OpenGL ES"; + #else + return "OpenGL"; + #endif + case VENDOR: return (const char *)glGetString(GL_VENDOR); + case RENDERER: return (const char *)glGetString(GL_RENDERER); + case SHADELANGVERSION: return (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); + case APIVERSION: return (const char *)glGetString(GL_VERSION); + default: return "?"; + } } }; @@ -318,13 +327,16 @@ GLuint TypeToTarget(T3DTextureType type) { class Thin3DGLTexture : public Thin3DTexture { public: - Thin3DGLTexture(T3DTextureType type, T3DImageFormat format, int mipLevels) : format_(format), tex_(0), target_(TypeToTarget(type)), mipLevels_(mipLevels) { + Thin3DGLTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) : format_(format), tex_(0), target_(TypeToTarget(type)), mipLevels_(mipLevels) { + width_ = width; + height_ = height; + depth_ = depth; glGenTextures(1, &tex_); } ~Thin3DGLTexture() { glDeleteTextures(1, &tex_); } - void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) override; + void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override; void AutoGenMipmaps() override; void Bind() { @@ -341,8 +353,7 @@ private: }; Thin3DTexture *Thin3DGLContext::CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) { - Thin3DGLTexture *tex = new Thin3DGLTexture(type, format, mipLevels); - return tex; + return new Thin3DGLTexture(type, format, width, height, depth, mipLevels); } void Thin3DGLTexture::AutoGenMipmaps() { @@ -350,13 +361,7 @@ void Thin3DGLTexture::AutoGenMipmaps() { glGenerateMipmap(target_); } -void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, uint8_t *data) { - if (level == 0) { - width_ = width; - height_ = height; - depth_ = depth; - } - +void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) { int internalFormat; int format; int type; @@ -366,6 +371,11 @@ void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, i format = GL_RGBA; type = GL_UNSIGNED_BYTE; break; + case RGBA4444: + internalFormat = GL_RGBA; + format = GL_RGBA; + type = GL_UNSIGNED_SHORT_4_4_4_4; + break; default: return; } @@ -373,7 +383,7 @@ void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, i glBindTexture(target_, tex_); switch (target_) { case GL_TEXTURE_2D: - glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type, data); + glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width_, height_, 0, format, type, data); break; } } diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 51c5f7a82e..2b23035fc4 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -30,7 +30,7 @@ void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DSha uidrawbuffer_ = uidrawbuffer; uidrawbufferTop_ = uidrawbufferTop; #if defined(_WIN32) || defined(USING_QT_UI) - textDrawer_ = new TextDrawer(); + textDrawer_ = new TextDrawer(thin3d); #else textDrawer_ = 0; #endif From 1401de50dca62f9084edbf50ff1b09f6ca06d8d4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 22 Aug 2014 21:26:46 +0200 Subject: [PATCH 1230/1445] Thin3d: Minor shader cleanup --- thin3d/thin3d.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 7c74d6b933..63b8b234aa 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -11,14 +11,13 @@ static const char * const glsl_fsTexCol = static const char * const hlslFsTexCol = "struct PS_INPUT { float4 color : COLOR0; float2 uv : TEXCOORD0; };\n" -"sampler2D tex0 : register(s0);\n" +"sampler2D Sampler0 : register(s0);\n" "float4 main(PS_INPUT input) : COLOR0 {\n" -" return input.color * tex2D(tex0, input.uv);\n" +" return input.color * tex2D(Sampler0, input.uv);\n" "}\n"; static const char * const glsl_fsCol = "varying vec4 oColor0;\n" -"uniform sampler2D Sampler0;\n" "void main() { gl_FragColor = oColor0; }\n"; static const char * const hlslFsCol = @@ -58,7 +57,7 @@ static const char * const glsl_vsTexCol = "void main() {\n" " gl_Position = WorldViewProj * vec4(Position, 1.0);\n" " oColor0 = Color0;\n" -" oTexCoord0 = TexCoord0; \n" +" oTexCoord0 = TexCoord0;\n" "}\n"; static const char * const hlslVsTexCol = From 110f640ca8dbcdf290037512e6c716f93351a659 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 Aug 2014 00:34:55 -0700 Subject: [PATCH 1231/1445] Fix Linux/Android compilation. --- Android.mk | 2 ++ gfx_es2/draw_text.cpp | 20 +++++++++----------- gfx_es2/draw_text.h | 4 ---- thin3d/thin3d_gl.cpp | 23 +++++++++++++++++------ 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Android.mk b/Android.mk index 4098bf4253..8bc0fb1a02 100644 --- a/Android.mk +++ b/Android.mk @@ -88,6 +88,8 @@ LOCAL_SRC_FILES :=\ image/zim_load.cpp \ image/zim_save.cpp \ image/png_load.cpp \ + thin3d/thin3d.cpp \ + thin3d/thin3d_gl.cpp \ ui/view.cpp \ ui/viewgroup.cpp \ ui/ui.cpp \ diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 53baf045c9..c01988dc1c 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -199,14 +199,14 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float #else -TextDrawer::TextDrawer() { +TextDrawer::TextDrawer(Thin3DContext *thin3d) : thin3d_(thin3d), ctx_(NULL) { fontScaleX_ = 1.0f; fontScaleY_ = 1.0f; } TextDrawer::~TextDrawer() { for (auto iter = cache_.begin(); iter != cache_.end(); ++iter) { - glDeleteTextures(1, &iter->second->textureHandle); + iter->second->texture->Release(); delete iter->second; } cache_.clear(); @@ -254,6 +254,9 @@ void TextDrawer::MeasureString(const char *str, float *w, float *h) { } void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align) { + if (!strlen(str)) + return; + #ifdef USING_QT_UI uint32_t stringHash = hash::Fletcher((const uint8_t *)str, strlen(str)); uint32_t entryHash = stringHash ^ fontHash_; @@ -266,7 +269,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float if (iter != cache_.end()) { entry = iter->second; entry->lastUsedFrame = frameCount_; - glBindTexture(GL_TEXTURE_2D, entry->textureHandle); + thin3d_->SetTexture(0, entry->texture); } else { QFont *font = fontMap_.find(fontHash_)->second; QFontMetrics fm(*font); @@ -285,11 +288,10 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float painter.end(); entry = new TextStringEntry(); - glGenTextures(1, &entry->textureHandle); - glBindTexture(GL_TEXTURE_2D, entry->textureHandle); entry->bmWidth = entry->width = image.width(); entry->bmHeight = entry->height = image.height(); entry->lastUsedFrame = frameCount_; + entry->texture = thin3d_->CreateTexture(LINEAR2D, RGBA4444, entry->bmWidth, entry->bmHeight, 1, 0); uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight]; for (int x = 0; x < entry->bmWidth; x++) { @@ -297,12 +299,8 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float bitmapData[entry->bmWidth * y + x] = 0xfff0 | image.pixel(x, y) >> 28; } } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, entry->bmWidth, entry->bmHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, bitmapData); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + entry->texture->SetImageData(0, 0, 0, entry->bmWidth, entry->bmHeight, 1, 0, entry->bmWidth * 2, (const uint8_t *)bitmapData); + entry->texture->Finalize(0); delete [] bitmapData; diff --git a/gfx_es2/draw_text.h b/gfx_es2/draw_text.h index 3d94a0528e..bd1f1d8248 100644 --- a/gfx_es2/draw_text.h +++ b/gfx_es2/draw_text.h @@ -24,11 +24,7 @@ class Thin3DTexture; #endif struct TextStringEntry { -#if defined(_WIN32) && !defined(USING_QT_UI) Thin3DTexture *texture; -#else - GLuint textureHandle; -#endif int width; int height; int bmWidth; diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index f179b6135f..eaa7cd17a1 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -315,11 +315,15 @@ Thin3DVertexFormat *Thin3DGLContext::CreateVertexFormat(const std::vector Date: Sat, 23 Aug 2014 00:14:17 -0700 Subject: [PATCH 1232/1445] Fix some type conversion warnings. --- thin3d/thin3d_d3d9.cpp | 6 +++--- thin3d/thin3d_gl.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index e55b690289..1f500671c1 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -149,7 +149,7 @@ public: private: LPDIRECT3DVERTEXBUFFER9 vbuffer_; LPDIRECT3DINDEXBUFFER9 ibuffer_; - int maxSize_; + size_t maxSize_; }; @@ -620,7 +620,7 @@ bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, cons DWORD flags = 0; LPD3DXBUFFER codeBuffer; LPD3DXBUFFER errorBuffer; - HRESULT hr = dyn_D3DXCompileShader(source, strlen(source), defines, includes, "main", profile, flags, &codeBuffer, &errorBuffer, &constantTable_); + HRESULT hr = dyn_D3DXCompileShader(source, (UINT)strlen(source), defines, includes, "main", profile, flags, &codeBuffer, &errorBuffer, &constantTable_); if (FAILED(hr)) { const char *error = (const char *)errorBuffer->GetBufferPointer(); OutputDebugStringA(source); @@ -648,7 +648,7 @@ bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, cons //D3DXCONSTANT_DESC *descs = new D3DXCONSTANT_DESC[desc.Constants]; //constantTable_->GetConstantDesc() - for (int i = 0; i < desc.Constants; i++) { + for (UINT i = 0; i < desc.Constants; i++) { D3DXHANDLE c = constantTable_->GetConstant(NULL, i); D3DXCONSTANT_DESC cdesc; UINT count = 1; diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index eaa7cd17a1..09c80146f4 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -664,7 +664,7 @@ void Thin3DGLVertexFormat::Apply() { glEnableVertexAttribArray(i); } } - for (int i = 0; i < components_.size(); i++) { + for (size_t i = 0; i < components_.size(); i++) { switch (components_[i].type) { case FLOATx2: glVertexAttribPointer(components_[i].semantic, 2, GL_FLOAT, GL_FALSE, stride_, (void *)(intptr_t)components_[i].offset); From 7708558c2f247dd4e8d874df9a05c414c3739bc8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 23 Aug 2014 09:47:30 +0200 Subject: [PATCH 1233/1445] Remove a comment, add some checks. --- gfx_es2/draw_text.cpp | 5 ++++- math/lin/matrix4x4.cpp | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index c01988dc1c..cf15308b45 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -56,7 +56,8 @@ TextDrawer::TextDrawer(Thin3DContext *thin3d) : thin3d_(thin3d), ctx_(NULL) { TextDrawer::~TextDrawer() { for (auto iter = cache_.begin(); iter != cache_.end(); ++iter) { - iter->second->texture->Release(); + if (iter->second->texture) + iter->second->texture->Release(); delete iter->second; } cache_.clear(); @@ -344,6 +345,8 @@ void TextDrawer::OncePerFrame() { if (frameCount_ % 23 == 0) { for (auto iter = cache_.begin(); iter != cache_.end();) { if (frameCount_ - iter->second->lastUsedFrame > 100) { + if (iter->second->texture) + iter->second->texture->Release(); delete iter->second; cache_.erase(iter++); } else { diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp index c0b2d2d280..f96fd871f4 100644 --- a/math/lin/matrix4x4.cpp +++ b/math/lin/matrix4x4.cpp @@ -218,7 +218,6 @@ void Matrix4x4::setOrthoD3D(float left, float right, float bottom, float top, fl zz = 1.0f / (far - near); wx = -(right + left) / (right - left); wy = -(top + bottom) / (top - bottom); - //wz = -(far + near) / (far - near); wz = -near / (far - near); } From 75b7ccd739a8c49a68c018853b51a2fbc3dba0f2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 23 Aug 2014 10:01:03 +0200 Subject: [PATCH 1234/1445] Clean up D3DX loader a little --- thin3d/d3dx9_loader.cpp | 152 +++++++--------------------------------- thin3d/d3dx9_loader.h | 2 +- thin3d/thin3d_d3d9.cpp | 17 ++--- 3 files changed, 35 insertions(+), 136 deletions(-) diff --git a/thin3d/d3dx9_loader.cpp b/thin3d/d3dx9_loader.cpp index a18453045f..539916fb98 100644 --- a/thin3d/d3dx9_loader.cpp +++ b/thin3d/d3dx9_loader.cpp @@ -33,73 +33,22 @@ typedef HRESULT(__stdcall *TFunc_D3DXAssembleShader)( static HMODULE hm_d3dx; static unsigned int d3dx_version; +static int failedFunctions; + static TFunc_D3DXCheckVersion m_TFunc_D3DXCheckVersion; static TFunc_D3DXAssembleShader m_TFunc_D3DXAssembleShader; static TFunc_D3DXCompileShader m_TFunc_D3DXCompileShader; -void makeD3DX9dllFilename_by_version(std::string& strOut, unsigned int vers, bool bDebugV = false) { - strOut = ""; - strOut += "d3dx9"; - if (bDebugV) { - strOut += "d"; - } - strOut += "_"; - char buf[32]; - sprintf(buf, "%02i", vers); - strOut += buf; - strOut += ".dll"; - // temp mon - if (vers < 10) { - int _stop = 0; - } -} - -void makeD3DX9dllFilename_by_versionW(std::wstring& strOut, unsigned int vers, bool bDebugV = false) -{ - strOut = L""; - strOut += L"d3dx9"; - - if (bDebugV) { - strOut += L"d"; - } - - strOut += L"_"; - - wchar_t buf[32]; - wsprintf(buf, L"%02i", vers); - strOut += buf; - strOut += L".dll"; - - // temp mon - if (vers < 10) { - int _stop = 0; - } -} - -bool checkDllExistsA(const char* fname, bool bIncludeExeDir) { - return ::GetFileAttributesA(fname) != DWORD(-1); +void makeD3DX9dllFilename_by_versionW(std::wstring& strOut, unsigned int versionNumber, bool debugVersion = false) { + wchar_t buf[256]; + wsprintf(buf, L"d3dx9%s_%02i.dll", debugVersion ? L"d" : L"", versionNumber); + strOut = buf; } bool checkDllExistsW(const WCHAR* fname, bool bIncludeExeDir) { return ::GetFileAttributesW(fname) != DWORD(-1); } -bool checkExistsDll(const char* sDllFilename) { - std::string sfullpath; - char bufsysdir[MAX_PATH]; - - if (!::GetSystemDirectoryA(bufsysdir, MAX_PATH)) { - throw (std::runtime_error("system error")); - } - sfullpath = bufsysdir; - sfullpath += '\\'; - sfullpath += sDllFilename; - if (checkDllExistsA(sfullpath.c_str(), true)) { - return true; - } - return false; -} - bool checkExistsDllW(const WCHAR* sDllFilename) { std::wstring sfullpath; WCHAR bufsysdir[MAX_PATH]; @@ -119,12 +68,12 @@ bool checkExistsDllW(const WCHAR* sDllFilename) { return false; } -bool getInstaledD3DXlastVersion(unsigned int* piOutVers) { +bool getLatestInstalledD3DXVersion(unsigned int* piOutVers) { *piOutVers = 0; - std::string fname; + std::wstring fname; for (unsigned int cvers = 45; cvers > 0; cvers--) { - makeD3DX9dllFilename_by_version(fname, cvers); - if (checkExistsDll(fname.c_str())) { + makeD3DX9dllFilename_by_versionW(fname, cvers); + if (checkExistsDllW(fname.c_str())) { *piOutVers = cvers; return true; } @@ -132,60 +81,22 @@ bool getInstaledD3DXlastVersion(unsigned int* piOutVers) { return false; } -//==================================================================== -bool getInstaledD3DXallVersion(std::vector& versions) { - bool result = false; - versions.clear(); +HMODULE loadDllLastVersion(unsigned int* version, bool debugVersion) { + failedFunctions = 0; - std::string fname; - for (unsigned int cvers = 45; cvers > 0; cvers--) { - makeD3DX9dllFilename_by_version(fname, cvers); - if (checkExistsDll(fname.c_str())) { - versions.push_back(cvers); - result = true; - } - } - return result; -} - -//==================================================================== -HMODULE loadDllLastVersion(unsigned int* piOutVers) { - if (piOutVers) - *piOutVers = 0; - - // old code ansi string -#if 0 - - if (!getInstaledD3DXlastVersion(piOutVers)) { + if (version) + *version = 0; + if (!getLatestInstalledD3DXVersion(version)) { return 0; } - std::string dllfname; - makeD3DX9dllFilename_by_version(dllfname, *piOutVers); - - HMODULE hm = 0; - hm = ::LoadLibraryA(dllfname.c_str()); - -#else - // unicode - if (!getInstaledD3DXlastVersion(piOutVers)) { - return 0; - } - - bool bdebugvers = false; -#ifdef _DEBUG - bdebugvers = false; // true; -#endif std::wstring dllfname; - makeD3DX9dllFilename_by_versionW(dllfname, *piOutVers, bdebugvers); - HMODULE hm = 0; - hm = ::LoadLibraryW(dllfname.c_str()); -#endif + makeD3DX9dllFilename_by_versionW(dllfname, *version, debugVersion); + HMODULE hm = ::LoadLibraryW(dllfname.c_str()); return hm; } - #define GB_MAKE_STR(s) # s #define GB_MAKE_STR2(x) GB_MAKE_STR(x) @@ -196,34 +107,18 @@ HMODULE loadDllLastVersion(unsigned int* piOutVers) { handleNotFoundAddr( GB_MAKE_STR(funcname) ); \ } -//============================================================== void handleNotFoundAddr(const char* sFuncName) { -#ifdef _DEBUG - std::string temp; - temp = " Entry point not found in d3dx dll : \n"; - temp += sFuncName; - // ELOG(temp.c_str()); - - assert(false && temp.c_str()); - - static FILE* st_file = NULL; - if (st_file == NULL) { - st_file = fopen("__getProcAddrlog.txt", "w"); - } - - fputs(sFuncName, st_file); - fputs("\n", st_file); - -#endif + ELOG("Failed to find D3DX fucntion %s", sFuncName); + failedFunctions++; } -int LoadD3DX9Dynamic() { +int LoadD3DX9Dynamic(bool debugVersion) { if (hm_d3dx) { // Already loaded return d3dx_version; } - hm_d3dx = loadDllLastVersion(&d3dx_version); + hm_d3dx = loadDllLastVersion(&d3dx_version, debugVersion); void* ptr = NULL; const int NERROR = -1; int _begin = 0; @@ -232,6 +127,10 @@ int LoadD3DX9Dynamic() { __HANDLE_DLL_ENTRY(D3DXAssembleShader); __HANDLE_DLL_ENTRY(D3DXCompileShader); + if (failedFunctions > 0) { + ELOG("Failed to load %i D3DX functions. This will not go well.", failedFunctions); + } + return d3dx_version; } @@ -256,7 +155,6 @@ BOOL dyn_D3DXCheckVersion(UINT D3DSDKVersion, UINT D3DXSDKVersion) { if (!m_TFunc_D3DXCheckVersion) { GB_D3D9_D3DXDLL_LOADER_CHECK_ENTRY_NULL_PTR(D3DXCheckVersion) } - return m_TFunc_D3DXCheckVersion(D3DSDKVersion, D3DXSDKVersion); } diff --git a/thin3d/d3dx9_loader.h b/thin3d/d3dx9_loader.h index b4950809f3..a194077a2e 100644 --- a/thin3d/d3dx9_loader.h +++ b/thin3d/d3dx9_loader.h @@ -7,7 +7,7 @@ #include // Returns the D3DX9 version we got. 0 if none. -int LoadD3DX9Dynamic(); +int LoadD3DX9Dynamic(bool debugVersion = false); // If debugVersion is set, load d3dx9d.dll int GetD3DXVersion(); void UnloadD3DXDynamic(); diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 1f500671c1..93c2d1589c 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -394,10 +394,6 @@ private: }; Thin3DDX9Context::Thin3DDX9Context(LPDIRECT3DDEVICE9 device) : device_(device) { - int d3dx_ver = LoadD3DX9Dynamic(); - if (!d3dx_ver) { - ELOG("Failed to load D3DX9!"); - } CreatePresets(); } @@ -586,10 +582,6 @@ void Thin3DDX9Context::Clear(int mask, uint32_t colorval, float depthVal, int st device_->Clear(0, NULL, d3dMask, (D3DCOLOR)colorval, depthVal, stencilVal); } -Thin3DContext *T3DCreateDX9Context(LPDIRECT3DDEVICE9 device) { - return new Thin3DDX9Context(device); -} - void Thin3DDX9Context::SetScissorEnabled(bool enable) { device_->SetRenderState(D3DRS_SCISSORTESTENABLE, enable); } @@ -673,3 +665,12 @@ void Thin3DDX9Shader::SetMatrix4x4(LPDIRECT3DDEVICE9 device, const char *name, c constantTable_->SetFloatArray(device, handle, value.getReadPtr(), 16); } } + +Thin3DContext *T3DCreateDX9Context(LPDIRECT3DDEVICE9 device) { + int d3dx_ver = LoadD3DX9Dynamic(); + if (!d3dx_ver) { + ELOG("Failed to load D3DX9!"); + return NULL; + } + return new Thin3DDX9Context(device); +} From 6f96004381895365cfe0d748bd8c8805aa472a0a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 23 Aug 2014 10:20:27 +0200 Subject: [PATCH 1235/1445] Thin3d D3D: More system information, other minor fixes --- thin3d/thin3d.h | 3 ++- thin3d/thin3d_d3d9.cpp | 41 +++++++++++++++++++++++++---------------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 45fbf8ac35..1a3442c527 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -316,5 +316,6 @@ Thin3DContext *T3DCreateGLContext(); #ifdef _WIN32 struct IDirect3DDevice9; -Thin3DContext *T3DCreateDX9Context(IDirect3DDevice9 *device); +struct IDirect3D9; +Thin3DContext *T3DCreateDX9Context(IDirect3D9 *d3d, int adapterId, IDirect3DDevice9 *device); #endif diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 93c2d1589c..00252dbd2e 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -1,4 +1,5 @@ #include +#include #include #ifdef _DEBUG @@ -266,7 +267,7 @@ inline uint16_t Shuffle4444(uint16_t x) { return (x << 12) | (x >> 4); } -// A rather different transform, for curious reasons.. +// Just switches R and G. inline uint32_t Shuffle8888(uint32_t x) { return (x & 0xFF00FF00) | ((x >> 16) & 0xFF) | ((x << 16) & 0xFF0000); } @@ -310,12 +311,11 @@ void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height, } tex_->UnlockRect(level); } - // tex_->LockRect() break; } default: - // TODO + ELOG("Non-LINEAR2D textures not yet supported"); break; } } @@ -337,10 +337,9 @@ void Thin3DDX9Texture::SetToSampler(LPDIRECT3DDEVICE9 device, int sampler) { } } - class Thin3DDX9Context : public Thin3DContext { public: - Thin3DDX9Context(LPDIRECT3DDEVICE9 device); + Thin3DDX9Context(LPDIRECT3D9 d3d, int adapterId, LPDIRECT3DDEVICE9 device); ~Thin3DDX9Context(); Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare); @@ -376,25 +375,33 @@ public: void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal); const char *GetInfoString(T3DInfo info) const override { - // TODO: Make these actually query the right information switch (info) { case APIVERSION: return "DirectX 9.0"; - case VENDOR: return "?"; - case RENDERER: return "?"; - case SHADELANGVERSION: return "3.0"; + case VENDOR: return identifier_.Description; + case RENDERER: return identifier_.Driver; // eh, sort of + case SHADELANGVERSION: return shadeLangVersion_; case APINAME: return "Direct3D 9"; default: return "?"; } } private: - // void CompileShader(const char *hlsl_source); - + LPDIRECT3D9 d3d_; LPDIRECT3DDEVICE9 device_; + int adapterId_; + D3DADAPTER_IDENTIFIER9 identifier_; + D3DCAPS9 caps_; + char shadeLangVersion_[64]; }; -Thin3DDX9Context::Thin3DDX9Context(LPDIRECT3DDEVICE9 device) : device_(device) { +Thin3DDX9Context::Thin3DDX9Context(LPDIRECT3D9 d3d, int adapterId, LPDIRECT3DDEVICE9 device) : d3d_(d3d), adapterId_(adapterId), device_(device) { CreatePresets(); + d3d->GetAdapterIdentifier(adapterId, 0, &identifier_); + if (!FAILED(device->GetDeviceCaps(&caps_))) { + sprintf(shadeLangVersion_, "PS: %04x VS: %04x", caps_.PixelShaderVersion & 0xFFFF, caps_.VertexShaderVersion & 0xFFFF); + } else { + strcpy(shadeLangVersion_, "N/A"); + } } Thin3DDX9Context::~Thin3DDX9Context() { @@ -635,11 +642,12 @@ bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, cons success = SUCCEEDED(result); } +#if 0 + // Just for testing. Will later use to pre populate uniform tables. + D3DXCONSTANTTABLE_DESC desc; constantTable_->GetDesc(&desc); - //D3DXCONSTANT_DESC *descs = new D3DXCONSTANT_DESC[desc.Constants]; - //constantTable_->GetConstantDesc() for (UINT i = 0; i < desc.Constants; i++) { D3DXHANDLE c = constantTable_->GetConstant(NULL, i); D3DXCONSTANT_DESC cdesc; @@ -647,6 +655,7 @@ bool Thin3DDX9Shader::Compile(LPDIRECT3DDEVICE9 device, const char *source, cons constantTable_->GetConstantDesc(c, &cdesc, &count); ILOG("%s", cdesc.Name); } +#endif codeBuffer->Release(); return true; @@ -666,11 +675,11 @@ void Thin3DDX9Shader::SetMatrix4x4(LPDIRECT3DDEVICE9 device, const char *name, c } } -Thin3DContext *T3DCreateDX9Context(LPDIRECT3DDEVICE9 device) { +Thin3DContext *T3DCreateDX9Context(LPDIRECT3D9 d3d, int adapterId, LPDIRECT3DDEVICE9 device) { int d3dx_ver = LoadD3DX9Dynamic(); if (!d3dx_ver) { ELOG("Failed to load D3DX9!"); return NULL; } - return new Thin3DDX9Context(device); + return new Thin3DDX9Context(d3d, adapterId, device); } From 49602416cf218a1b52f38e7ebd9b62b3a8a70315 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 23 Aug 2014 10:31:23 +0200 Subject: [PATCH 1236/1445] More thin3d minor fixes --- base/logging.h | 5 +++-- base/stringutil.cpp | 6 ++++++ thin3d/thin3d_gl.cpp | 25 ++++++++++++------------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/base/logging.h b/base/logging.h index c129f19d9d..cda8eaf8d0 100644 --- a/base/logging.h +++ b/base/logging.h @@ -45,6 +45,9 @@ inline void Crash() { #endif +// Just ILOGs on nonWindows. On Windows it outputs to the VS output console. +void OutputDebugStringUTF8(const char *p); + #if defined(ANDROID) #include @@ -83,8 +86,6 @@ inline void Crash() { #ifdef _WIN32 -void OutputDebugStringUTF8(const char *p); - #ifdef _DEBUG #define DLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "D: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "D: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} #else diff --git a/base/stringutil.cpp b/base/stringutil.cpp index c1d5ed35e6..2c8bd1e56a 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -29,6 +29,12 @@ void OutputDebugStringUTF8(const char *p) { OutputDebugString(temp); } +#else + +void OutputDebugStringUTF8(const char *p) { + ILOG("%s", p); +} + #endif unsigned int parseHex(const char *_szValue) diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 09c80146f4..23e9959062 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -64,7 +64,7 @@ public: GLuint eqCol, eqAlpha; GLuint srcCol, srcAlpha, dstCol, dstAlpha; // int maskBits; - uint32_t fixedColor; + // uint32_t fixedColor; void Apply() { glstate.blend.set(enabled); @@ -78,7 +78,6 @@ public: #endif // glstate.colorMask.set(maskBits & 1, (maskBits >> 1) & 1, (maskBits >> 2) & 1, (maskBits >> 3) & 1); - // glstate.blendColor.set(fixedColor); } }; @@ -173,7 +172,7 @@ bool Thin3DGLShader::Compile(const char *source) { infoLog[len] = '\0'; glDeleteShader(shader_); shader_ = 0; - // print? + ILOG("%s Shader compile error:\n%s", type_ == GL_FRAGMENT_SHADER ? "Fragment" : "Vertex", infoLog); } ok_ = success != 0; return ok_; @@ -295,7 +294,6 @@ public: default: return "?"; } } - }; Thin3DGLContext::Thin3DGLContext() { @@ -361,7 +359,7 @@ Thin3DTexture *Thin3DGLContext::CreateTexture(T3DTextureType type, T3DImageForma } void Thin3DGLTexture::AutoGenMipmaps() { - glBindTexture(target_, tex_); + Bind(); glGenerateMipmap(target_); } @@ -384,11 +382,14 @@ void Thin3DGLTexture::SetImageData(int x, int y, int z, int width, int height, i return; } - glBindTexture(target_, tex_); + Bind(); switch (target_) { case GL_TEXTURE_2D: glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width_, height_, 0, format, type, data); break; + default: + ELOG("Thin3D GL: Targets other than GL_TEXTURE_2D not yet supported"); + break; } } @@ -512,15 +513,12 @@ bool Thin3DGLShaderSet::Link() { if (bufLength) { char* buf = new char[bufLength]; glGetProgramInfoLog(program_, bufLength, NULL, buf); - //ERROR_LOG(G3D, "Could not link program:\n %s", buf); - //ERROR_LOG(G3D, "VS:\n%s", vs->source().c_str()); - //ERROR_LOG(G3D, "FS:\n%s", fs->source().c_str()); -#ifdef SHADERLOG + ELOG("Could not link program:\n %s", buf); + // We've thrown out the source at this point. Might want to do something about that. +#ifdef _WIN32 OutputDebugStringUTF8(buf); - OutputDebugStringUTF8(vs->source().c_str()); - OutputDebugStringUTF8(fs->source().c_str()); #endif - delete[] buf; // we're dead! + delete[] buf; } return false; } @@ -535,6 +533,7 @@ bool Thin3DGLShaderSet::Link() { glUniform1i(samplerLoc, i); } } + // Here we could (using glGetAttribLocation) save a bitmask about which pieces of vertex data are used in the shader // and then AND it with the vertex format bitmask later... return true; From 6b5e9f6b7cb45a8e0d8aa75d9409e3c8ea8b57c5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 Aug 2014 02:11:45 -0700 Subject: [PATCH 1237/1445] Linux buildfix. --- thin3d/thin3d.cpp | 2 +- thin3d/thin3d.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 63b8b234aa..f4d81c0b33 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -152,7 +152,7 @@ Thin3DTexture *Thin3DContext::CreateTextureFromFileData(const char *data, int si case PNG: if (1 != pngLoadPtr((const unsigned char *)data, size, &width[0], &height[0], &image[0], false)) { - return false; + return NULL; } num_levels = 1; fmt = RGBA8888; diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 1a3442c527..22c4a125d1 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include class Matrix4x4; From 1ea54accefaa3a302b10447245e7b216597b99ee Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 Aug 2014 09:25:59 -0700 Subject: [PATCH 1238/1445] Add the prelude to fragment shaders. --- thin3d/thin3d_gl.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 23e9959062..1f10135282 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -160,6 +160,14 @@ private: bool Thin3DGLShader::Compile(const char *source) { shader_ = glCreateShader(type_); + + std::string temp; + // Add the prelude on automatically for fragment shaders. + if (type_ == GL_FRAGMENT_SHADER) { + temp = std::string(glsl_fragment_prelude) + source; + source = temp.c_str(); + } + glShaderSource(shader_, 1, &source, 0); glCompileShader(shader_); GLint success; From d726e7f389acccc6faf655551b45611a30c480e3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 Aug 2014 10:36:42 -0700 Subject: [PATCH 1239/1445] Try not to crash on shader compile errors. --- thin3d/thin3d.cpp | 16 ++++++++++++---- thin3d/thin3d_gl.cpp | 3 ++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index f4d81c0b33..73d2d32681 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -96,16 +96,24 @@ void Thin3DContext::CreatePresets() { Thin3DContext::~Thin3DContext() { for (int i = 0; i < VS_MAX_PRESET; i++) { - vsPresets_[i]->Release(); + if (vsPresets_[i]) { + vsPresets_[i]->Release(); + } } for (int i = 0; i < FS_MAX_PRESET; i++) { - fsPresets_[i]->Release(); + if (fsPresets_[i]) { + fsPresets_[i]->Release(); + } } for (int i = 0; i < BS_MAX_PRESET; i++) { - bsPresets_[i]->Release(); + if (bsPresets_[i]) { + bsPresets_[i]->Release(); + } } for (int i = 0; i < SS_MAX_PRESET; i++) { - ssPresets_[i]->Release(); + if (ssPresets_[i]) { + ssPresets_[i]->Release(); + } } } diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 1f10135282..246b4ea077 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -454,10 +454,11 @@ Thin3DBuffer *Thin3DGLContext::CreateBuffer(size_t size, uint32_t usageFlags) { } Thin3DShaderSet *Thin3DGLContext::CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) { - Thin3DGLShaderSet *shaderSet = new Thin3DGLShaderSet(); if (!vshader || !fshader) { ELOG("ShaderSet requires both a valid vertex and a fragment shader: %p %p", vshader, fshader); + return NULL; } + Thin3DGLShaderSet *shaderSet = new Thin3DGLShaderSet(); vshader->AddRef(); fshader->AddRef(); shaderSet->vshader = static_cast(vshader); From 6b223e2cc668362aab974e45838709251b2c039e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 Aug 2014 21:53:00 -0700 Subject: [PATCH 1240/1445] d3d: Fix a crash on a shader compile error. --- thin3d/thin3d.cpp | 10 +++++----- thin3d/thin3d_d3d9.cpp | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 73d2d32681..5dbb9dee68 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -32,8 +32,8 @@ static const char * const glsl_vsCol = "varying vec4 oColor0;\n" "uniform mat4 WorldViewProj;\n" "void main() {\n" -" gl_Position = WorldViewProj * vec4(Position, 1.0);\n" -" oColor0 = Color0;\n" +" gl_Position = WorldViewProj * vec4(Position, 1.0);\n" +" oColor0 = Color0;\n" "}"; static const char * const hlslVsCol = @@ -55,9 +55,9 @@ static const char * const glsl_vsTexCol = "varying vec2 oTexCoord0;\n" "uniform mat4 WorldViewProj;\n" "void main() {\n" -" gl_Position = WorldViewProj * vec4(Position, 1.0);\n" -" oColor0 = Color0;\n" -" oTexCoord0 = TexCoord0;\n" +" gl_Position = WorldViewProj * vec4(Position, 1.0);\n" +" oColor0 = Color0;\n" +" oTexCoord0 = TexCoord0;\n" "}\n"; static const char * const hlslVsTexCol = diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 00252dbd2e..5583b72e7f 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -173,7 +173,7 @@ private: class Thin3DDX9Shader : public Thin3DShader { public: - Thin3DDX9Shader(bool isPixelShader) : isPixelShader_(isPixelShader), vshader_(NULL), pshader_(NULL) {} + Thin3DDX9Shader(bool isPixelShader) : isPixelShader_(isPixelShader), vshader_(NULL), pshader_(NULL), constantTable_(NULL) {} ~Thin3DDX9Shader() { if (vshader_) vshader_->Release(); @@ -428,6 +428,10 @@ Thin3DShader *Thin3DDX9Context::CreateFragmentShader(const char *glsl_source, co } Thin3DShaderSet *Thin3DDX9Context::CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) { + if (!vshader || !fshader) { + ELOG("ShaderSet requires both a valid vertex and a fragment shader: %p %p", vshader, fshader); + return NULL; + } Thin3DDX9ShaderSet *shaderSet = new Thin3DDX9ShaderSet(device_); shaderSet->vshader = static_cast(vshader); shaderSet->pshader = static_cast(fshader); From e141280f8dc86b5b55c9a11a00559444a7dd2240 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 24 Aug 2014 01:22:25 -0700 Subject: [PATCH 1241/1445] Only create 1 miplevel in TextDrawer. Fixes missing text in D3D. --- gfx_es2/draw_text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index cf15308b45..40c6dd5553 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -173,7 +173,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float entry->bmWidth = (size.cx + 3) & ~3; entry->bmHeight = (size.cy + 3) & ~3; entry->lastUsedFrame = frameCount_; - entry->texture = thin3d_->CreateTexture(LINEAR2D, RGBA4444, entry->bmWidth, entry->bmHeight, 1, 0); + entry->texture = thin3d_->CreateTexture(LINEAR2D, RGBA4444, entry->bmWidth, entry->bmHeight, 1, 1); // Convert the bitmap to a gl-compatible array of pixels. uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight]; From c141c368fcafacf4f2e2d208cb519400b3e55dea Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 24 Aug 2014 01:23:08 -0700 Subject: [PATCH 1242/1445] Skip some conversion warnings. --- thin3d/thin3d_d3d9.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 5583b72e7f..5336b4818c 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -608,10 +608,10 @@ void Thin3DDX9Context::SetScissorRect(int left, int top, int width, int height) void Thin3DDX9Context::SetViewports(int count, T3DViewport *viewports) { D3DVIEWPORT9 vp; - vp.X = viewports[0].TopLeftX; - vp.Y = viewports[0].TopLeftY; - vp.Width = viewports[0].Width; - vp.Height = viewports[0].Height; + vp.X = (DWORD)viewports[0].TopLeftX; + vp.Y = (DWORD)viewports[0].TopLeftY; + vp.Width = (DWORD)viewports[0].Width; + vp.Height = (DWORD)viewports[0].Height; vp.MinZ = viewports[0].MinDepth; vp.MaxZ = viewports[0].MaxDepth; device_->SetViewport(&vp); From 731ab24e21cd4dace1aaefe67d5a9328c72572be Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 24 Aug 2014 19:50:36 -0700 Subject: [PATCH 1243/1445] d3d: fix scissoring by using top=actual top. --- thin3d/thin3d_gl.cpp | 2 +- ui/ui_context.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 246b4ea077..83e9460bd1 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -268,7 +268,7 @@ public: } void SetScissorRect(int left, int top, int width, int height) override { - glstate.scissorRect.set(left, top, width, height); + glstate.scissorRect.set(left, targetHeight_ - (top + height), width, height); } void SetViewports(int count, T3DViewport *viewports) override { diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 2b23035fc4..7dbf2e1381 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -100,10 +100,9 @@ void UIContext::ActivateTopScissor() { const Bounds &bounds = scissorStack_.back(); float scale = 1.0f / g_dpi_scale; int x = scale * bounds.x; - int y = scale * (dp_yres - bounds.y2()); + int y = scale * bounds.y; int w = scale * bounds.w; int h = scale * bounds.h; - thin3d_->SetScissorRect(x, y, w, h); thin3d_->SetScissorEnabled(true); } else { From 6f9a83819f7cf9f3c00567af38af75cdbc93b147 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 25 Aug 2014 01:54:06 -0700 Subject: [PATCH 1244/1445] d3d: fix bad texture on first text draw. OpenGL autobinds on create, D3D does not. --- gfx_es2/draw_text.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 40c6dd5553..3c243c5632 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -139,7 +139,6 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float if (iter != cache_.end()) { entry = iter->second; entry->lastUsedFrame = frameCount_; - thin3d_->SetTexture(0, entry->texture); } else { // Render the string to our bitmap and save to a GL texture. std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(str, "\n", "\r\n")); @@ -190,6 +189,8 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float cache_[entryHash] = entry; } + thin3d_->SetTexture(0, entry->texture); + // Okay, the texture is bound, let's draw. float w = entry->bmWidth * fontScaleX_; float h = entry->bmHeight * fontScaleY_; From f1ec201dbc6af46fb1b2f6ac57267c2bdd54a0f8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 27 Aug 2014 22:58:11 -0700 Subject: [PATCH 1245/1445] Cache bound fbos, allow unbinding only read. This maintains the currently bound fbos, similar to glstate. So long as these funcs are used, it can prevent duplicate binds. Binding the same buffer twice comes with a performance penalty. --- gfx_es2/fbo.cpp | 94 ++++++++++++++++++++++++++++++------------------- gfx_es2/fbo.h | 2 ++ 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index bd60a14d0b..232ed85770 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -43,6 +43,9 @@ struct FBO { static FBO *g_overriddenBackbuffer; +static GLuint currentDrawHandle_ = 0; +static GLuint currentReadHandle_ = 0; + // On PC, we always use GL_DEPTH24_STENCIL8. // On Android, we try to use what's available. @@ -118,6 +121,9 @@ FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stenci // Unbind state we don't need glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); glBindTexture(GL_TEXTURE_2D, 0); + + currentDrawHandle_ = fbo->handle; + currentReadHandle_ = fbo->handle; return fbo; } #endif @@ -237,6 +243,9 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F // Unbind state we don't need glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); + + currentDrawHandle_ = fbo->handle; + currentReadHandle_ = fbo->handle; return fbo; } @@ -258,6 +267,37 @@ FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo) return fbo; } +static GLenum fbo_get_fb_target(bool read, GLuint **cached) { + bool supportsBlit = gl_extensions.FBO_ARB; +#ifdef USING_GLES2 + supportsBlit = supportsBlit && (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); +#endif + + // Note: GL_FRAMEBUFFER_EXT and GL_FRAMEBUFFER have the same value, same with _NV. + if (supportsBlit) { + if (read) { + *cached = ¤tReadHandle_; + return GL_READ_FRAMEBUFFER; + } else { + *cached = ¤tDrawHandle_; + return GL_DRAW_FRAMEBUFFER; + } + } else { + *cached = ¤tDrawHandle_; + return GL_FRAMEBUFFER; + } +} + +static void fbo_bind_fb_target(bool read, GLuint name) { + GLuint *cached; + GLenum target = fbo_get_fb_target(read, &cached); + + if (*cached != name) { + glBindFramebuffer(target, name); + *cached = name; + } +} + void fbo_unbind() { if (g_overriddenBackbuffer) { fbo_bind_as_render_target(g_overriddenBackbuffer); @@ -275,6 +315,9 @@ void fbo_unbind() { #ifdef IOS bindDefaultFBO(); #endif + + currentDrawHandle_ = 0; + currentReadHandle_ = 0; } void fbo_override_backbuffer(FBO *fbo) { @@ -282,48 +325,24 @@ void fbo_override_backbuffer(FBO *fbo) { } void fbo_bind_as_render_target(FBO *fbo) { - if (gl_extensions.FBO_ARB) { -#ifndef USING_GLES2 - if (true) { -#else - if (gl_extensions.GLES3) { -#endif - // GL_DRAW_FRAMEBUFFER is actually the same value as GL_FRAMEBUFFER so this is a bit redundant. - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); - } else { - // This will collide with bind_for_read - but there's nothing in ES 2.0 - // that actually separate them anyway of course, so doesn't matter. - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - } - }else{ -#ifndef USING_GLES2 - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); -#endif - } + // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing + // in ES 2.0 that actually separate them anyway of course, so doesn't matter. + fbo_bind_fb_target(false, fbo->handle); // Always restore viewport after render target binding glstate.viewport.restore(); } +void fbo_unbind_render_target() { + fbo_unbind(); +} + // For GL_EXT_FRAMEBUFFER_BLIT and similar. void fbo_bind_for_read(FBO *fbo) { - if (gl_extensions.FBO_ARB) { -#ifndef USING_GLES2 - if (true) { -#else - if (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit) { -#endif - // GL_READ_FRAMEBUFFER is defined to the same value as GL_READ_FRAMEBUFFER_NV. - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle); - } else { - // This will collide with bind_as_render_target - but there's nothing in ES 2.0 - // that actually separate them anyway of course, so doesn't matter. - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - } - } else { -#ifndef USING_GLES2 - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); -#endif - } + fbo_bind_fb_target(true, fbo->handle); +} + +void fbo_unbind_read() { + fbo_bind_fb_target(true, 0); } void fbo_bind_color_as_texture(FBO *fbo, int color) { @@ -358,6 +377,9 @@ void fbo_destroy(FBO *fbo) { #endif } + currentDrawHandle_ = 0; + currentReadHandle_ = 0; + glDeleteTextures(1, &fbo->color_texture); delete fbo; } diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index 70e4e92794..9fd9426171 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -36,6 +36,8 @@ void fbo_bind_as_render_target(FBO *fbo); void fbo_bind_color_as_texture(FBO *fbo, int color); void fbo_bind_for_read(FBO *fbo); void fbo_unbind(); +void fbo_unbind_render_target(); +void fbo_unbind_read(); void fbo_destroy(FBO *fbo); void fbo_get_dimensions(FBO *fbo, int *w, int *h); From ca16eb2857d2b322f023fd2e65e892671a6f76bb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Aug 2014 02:05:21 -0700 Subject: [PATCH 1246/1445] Fix some type conversion warnings. --- thin3d/thin3d_d3d9.cpp | 2 +- ui/view.cpp | 2 +- ui/view.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 5336b4818c..a86009c569 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -515,7 +515,7 @@ static int VertexDataTypeToD3DType(T3DVertexDataType type) { Thin3DDX9VertexFormat::Thin3DDX9VertexFormat(LPDIRECT3DDEVICE9 device, const std::vector &components, int stride) : decl_(NULL) { D3DVERTEXELEMENT9 *elements = new D3DVERTEXELEMENT9[components.size() + 1]; - int i; + size_t i; for (i = 0; i < components.size(); i++) { elements[i].Stream = 0; elements[i].Offset = components[i].offset; diff --git a/ui/view.cpp b/ui/view.cpp index 422d8ac857..58132637ae 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -728,7 +728,7 @@ void TextEdit::Key(const KeyInput &input) { size_t maxPaste = maxLen_ - text_.size(); if (clipText.size() > maxPaste) { int end = 0; - while (end < maxPaste) { + while ((size_t)end < maxPaste) { u8_inc(clipText.c_str(), &end); } if (end > 0) { diff --git a/ui/view.h b/ui/view.h index 5db4c00b48..2289e08d07 100644 --- a/ui/view.h +++ b/ui/view.h @@ -673,7 +673,7 @@ public: TextEdit(const std::string &text, const std::string &placeholderText, LayoutParams *layoutParams = 0); void SetText(const std::string &text) { text_ = text; caret_ = (int)text_.size(); } const std::string &GetText() const { return text_; } - void SetMaxLen(int maxLen) { maxLen_ = maxLen; } + void SetMaxLen(size_t maxLen) { maxLen_ = maxLen; } virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; virtual void Draw(UIContext &dc) override; @@ -687,7 +687,7 @@ private: std::string undo_; std::string placeholderText_; int caret_; - int maxLen_; + size_t maxLen_; bool ctrlDown_; // TODO: Make some global mechanism for this. // TODO: Selections }; From 9a72d5323bfafdaf97aec583eefef9e51e0be594 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 31 Aug 2014 09:10:41 +0200 Subject: [PATCH 1247/1445] Change thin3d to compile model 2_0 shaders by default. We can add a way to choose 3_0 later. --- thin3d/thin3d_d3d9.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index a86009c569..9219d5c2b4 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -409,7 +409,7 @@ Thin3DDX9Context::~Thin3DDX9Context() { Thin3DShader *Thin3DDX9Context::CreateVertexShader(const char *glsl_source, const char *hlsl_source) { Thin3DDX9Shader *shader = new Thin3DDX9Shader(false); - if (shader->Compile(device_, hlsl_source, "vs_3_0")) { + if (shader->Compile(device_, hlsl_source, "vs_2_0")) { return shader; } else { delete shader; @@ -419,7 +419,7 @@ Thin3DShader *Thin3DDX9Context::CreateVertexShader(const char *glsl_source, cons Thin3DShader *Thin3DDX9Context::CreateFragmentShader(const char *glsl_source, const char *hlsl_source) { Thin3DDX9Shader *shader = new Thin3DDX9Shader(true); - if (shader->Compile(device_, hlsl_source, "ps_3_0")) { + if (shader->Compile(device_, hlsl_source, "ps_2_0")) { return shader; } else { delete shader; From d4014f5f7f73f3b3774c498ee5a0145752f9a25b Mon Sep 17 00:00:00 2001 From: Daniel Nagel Date: Mon, 1 Sep 2014 15:46:14 +0200 Subject: [PATCH 1248/1445] Update to SDL2 --- base/NKCodeFromSDL.h | 20 +++--- base/PCMain.cpp | 151 +++++++++++++++++++------------------------ 2 files changed, 76 insertions(+), 95 deletions(-) diff --git a/base/NKCodeFromSDL.h b/base/NKCodeFromSDL.h index 6c5f599832..62cb8cd6dd 100644 --- a/base/NKCodeFromSDL.h +++ b/base/NKCodeFromSDL.h @@ -65,16 +65,16 @@ static const std::map KeyMapRawSDLtoNative = InitConstMap (SDLK_HOME, NKCODE_MOVE_HOME) (SDLK_END, NKCODE_MOVE_END) (SDLK_INSERT, NKCODE_INSERT) - (SDLK_KP0, NKCODE_NUMPAD_0) - (SDLK_KP1, NKCODE_NUMPAD_1) - (SDLK_KP2, NKCODE_NUMPAD_2) - (SDLK_KP3, NKCODE_NUMPAD_3) - (SDLK_KP4, NKCODE_NUMPAD_4) - (SDLK_KP5, NKCODE_NUMPAD_5) - (SDLK_KP6, NKCODE_NUMPAD_6) - (SDLK_KP7, NKCODE_NUMPAD_7) - (SDLK_KP8, NKCODE_NUMPAD_8) - (SDLK_KP9, NKCODE_NUMPAD_9) + (SDLK_KP_0, NKCODE_NUMPAD_0) + (SDLK_KP_1, NKCODE_NUMPAD_1) + (SDLK_KP_2, NKCODE_NUMPAD_2) + (SDLK_KP_3, NKCODE_NUMPAD_3) + (SDLK_KP_4, NKCODE_NUMPAD_4) + (SDLK_KP_5, NKCODE_NUMPAD_5) + (SDLK_KP_6, NKCODE_NUMPAD_6) + (SDLK_KP_7, NKCODE_NUMPAD_7) + (SDLK_KP_8, NKCODE_NUMPAD_8) + (SDLK_KP_9, NKCODE_NUMPAD_9) (SDLK_KP_DIVIDE, NKCODE_NUMPAD_DIVIDE) (SDLK_KP_MULTIPLY, NKCODE_NUMPAD_MULTIPLY) (SDLK_KP_MINUS, NKCODE_NUMPAD_SUBTRACT) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index cda16b7877..051df396b2 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -15,9 +15,6 @@ #endif #include "SDL.h" -#include "SDL_timer.h" -#include "SDL_audio.h" -#include "SDL_video.h" #ifndef _WIN32 #include "SDL/SDLJoystick.h" SDLJoystick *joystick = NULL; @@ -50,7 +47,7 @@ GlobalUIState lastUIState = UISTATE_MENU; GlobalUIState GetUIState(); #endif -static SDL_Surface* g_Screen = NULL; +static SDL_Window* g_Screen = NULL; static bool g_ToggleFullScreenNextFrame = false; static int g_QuitRequested = 0; @@ -357,14 +354,8 @@ void ToggleFullScreenIfFlagSet() { dp_xres = (float)pixel_xres; dp_yres = (float)pixel_yres; - int flags = g_Screen->flags; // Save the current flags in case toggling fails - g_Screen = SDL_SetVideoMode(g_DesktopWidth, g_DesktopHeight, 0, g_Screen->flags ^ SDL_FULLSCREEN); // Toggles FullScreen Mode - if (g_Screen == NULL) { - g_Screen = SDL_SetVideoMode(0, 0, 0, flags); // If toggle FullScreen failed, then switch back - } - if (g_Screen == NULL) { - exit(1); // If you can't switch back for some reason, then epic fail - } + Uint32 window_flags = SDL_GetWindowFlags(g_Screen); + SDL_SetWindowFullscreen(g_Screen, window_flags ^ SDL_WINDOW_FULLSCREEN_DESKTOP); NativeResized(); #endif @@ -386,28 +377,37 @@ int main(int argc, char *argv[]) { NativeGetAppInfo(&app_name, &app_name_nice, &landscape); net::Init(); -#ifdef __APPLE__ - // Make sure to request a somewhat modern GL context at least - the - // latest supported by MacOSX (really, really sad...) - // Requires SDL 2.0 - // We really should upgrade to SDL 2.0 soon. - //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); -#endif if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } + +#ifdef __APPLE__ + // Make sure to request a somewhat modern GL context at least - the + // latest supported by MacOSX (really, really sad...) + // Requires SDL 2.0 + // We really should upgrade to SDL 2.0 soon. + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); +#endif + #ifdef USING_EGL if (EGL_Open()) return 1; #endif // Get the video info before doing anything else, so we don't get skewed resolution results. - const SDL_VideoInfo* desktopVideoInfo = SDL_GetVideoInfo(); - g_DesktopWidth = desktopVideoInfo->current_w; - g_DesktopHeight = desktopVideoInfo->current_h; + // TODO: support multiple displays correctly + SDL_DisplayMode displayMode; + int should_be_zero = SDL_GetCurrentDisplayMode(0, &displayMode); + if (should_be_zero != 0) { + fprintf(stderr, "Could not get display mode: %s\n", SDL_GetError()); + return 1; + } + g_DesktopWidth = displayMode.w; + g_DesktopHeight = displayMode.h; SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); @@ -415,13 +415,13 @@ int main(int argc, char *argv[]) { SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); + SDL_GL_SetSwapInterval(1); - int mode; + Uint32 mode; #ifdef USING_GLES2 mode = SDL_SWSURFACE | SDL_FULLSCREEN; #else - mode = SDL_OPENGL | SDL_RESIZABLE; + mode = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; #endif int set_xres = -1; int set_yres = -1; @@ -432,7 +432,7 @@ int main(int argc, char *argv[]) { for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) - mode |= SDL_FULLSCREEN; + mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; if (set_xres == -2) { set_xres = parseInt(argv[i]); } else if (set_yres == -2) { @@ -458,10 +458,9 @@ int main(int argc, char *argv[]) { portrait = true; } - if (mode & SDL_FULLSCREEN) { - const SDL_VideoInfo* info = SDL_GetVideoInfo(); - pixel_xres = info->current_w; - pixel_yres = info->current_h; + if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) { + pixel_xres = g_DesktopWidth; + pixel_yres = g_DesktopHeight; #ifdef PPSSPP g_Config.bFullScreen = true; #endif @@ -501,19 +500,21 @@ int main(int argc, char *argv[]) { dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; - g_Screen = SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode); + g_Screen = SDL_CreateWindow(app_name_nice.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, pixel_xres, pixel_yres, 0); if (g_Screen == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); return 2; } + SDL_GLContext glContext = SDL_GL_CreateContext(g_Screen); + #ifdef USING_EGL EGL_Init(); #endif #ifdef PPSSPP - SDL_WM_SetCaption((app_name_nice + " " + PPSSPP_GIT_VERSION).c_str(), NULL); + SDL_SetWindowTitle(g_Screen, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str()); #endif #ifdef MOBILE_DEVICE @@ -618,21 +619,19 @@ int main(int argc, char *argv[]) { g_QuitRequested = 1; break; #if !defined(MOBILE_DEVICE) - case SDL_VIDEORESIZE: - { - g_Screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_OPENGL | SDL_RESIZABLE); - if (g_Screen == NULL) { - fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); - SDL_Quit(); - return 2; + case SDL_WINDOWEVENT: + switch (event.window.event) { + case SDL_WINDOWEVENT_RESIZED: + { + pixel_xres = event.window.data1; + pixel_yres = event.window.data2; + dp_xres = (float)pixel_xres * dpi_scale; + dp_yres = (float)pixel_yres * dpi_scale; + NativeResized(); + break; + } + break; } - pixel_xres = event.resize.w; - pixel_yres = event.resize.h; - dp_xres = (float)pixel_xres * dpi_scale; - dp_yres = (float)pixel_yres * dpi_scale; - NativeResized(); - break; - } #endif case SDL_KEYDOWN: { @@ -687,26 +686,25 @@ int main(int argc, char *argv[]) { NativeKey(key); } break; - case SDL_BUTTON_WHEELUP: - { - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; - key.flags = KEY_DOWN; - NativeKey(key); - } - break; - case SDL_BUTTON_WHEELDOWN: - { - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; - key.flags = KEY_DOWN; - NativeKey(key); - } - break; } break; + case SDL_MOUSEWHEEL: + { + KeyInput key; + key.deviceId = DEVICE_ID_MOUSE; + if (event.wheel.y > 0) { + key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; + } else { + key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; + } + key.flags = KEY_DOWN; + NativeKey(key); + + // SDL2 doesn't consider the mousewheel a button anymore + // so let's send the KEY_UP right away + key.flags = KEY_UP; + NativeKey(key); + } case SDL_MOUSEMOTION: if (input_state.pointer_down[0]) { input_state.pointer_x[0] = mx; @@ -745,24 +743,6 @@ int main(int argc, char *argv[]) { NativeKey(key); } break; - case SDL_BUTTON_WHEELUP: - { - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; - key.flags = KEY_UP; - NativeKey(key); - } - break; - case SDL_BUTTON_WHEELDOWN: - { - KeyInput key; - key.deviceId = DEVICE_ID_MOUSE; - key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; - key.flags = KEY_UP; - NativeKey(key); - } - break; } break; default: @@ -774,7 +754,7 @@ int main(int argc, char *argv[]) { } if (g_QuitRequested) break; - const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL); + const uint8 *keys = SDL_GetKeyboardState(NULL); SimulateGamepad(keys, &input_state); input_state.pad_buttons = pad_buttons; UpdateInputState(&input_state, true); @@ -805,7 +785,7 @@ int main(int argc, char *argv[]) { #else if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) { - SDL_GL_SwapBuffers(); + SDL_GL_SwapWindow(g_Screen); lastT = t; } #endif @@ -830,6 +810,7 @@ int main(int argc, char *argv[]) { #ifdef USING_EGL EGL_Close(); #endif + SDL_GL_DeleteContext(glContext); SDL_Quit(); net::Shutdown(); #ifdef RPI From 3ab1f8baa93d5b1d89ef3338c76b0347a9c88e92 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 1 Sep 2014 08:08:51 -0700 Subject: [PATCH 1249/1445] thin3d: Use dynamic index/vertex buffers. --- thin3d/thin3d_d3d9.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 9219d5c2b4..2912a047db 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -89,11 +89,11 @@ class Thin3DDX9Buffer : public Thin3DBuffer { public: Thin3DDX9Buffer(LPDIRECT3DDEVICE9 device, size_t size, uint32_t flags) : vbuffer_(nullptr), ibuffer_(nullptr), maxSize_(size) { if (flags & T3DBufferUsage::INDEXDATA) { - DWORD usage = 0; - device->CreateIndexBuffer((UINT)size, usage, D3DFMT_INDEX32, D3DPOOL_MANAGED, &ibuffer_, NULL); + DWORD usage = D3DUSAGE_DYNAMIC; + device->CreateIndexBuffer((UINT)size, usage, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &ibuffer_, NULL); } else { - DWORD usage = 0; - device->CreateVertexBuffer((UINT)size, usage, 0, D3DPOOL_MANAGED, &vbuffer_, NULL); + DWORD usage = D3DUSAGE_DYNAMIC; + device->CreateVertexBuffer((UINT)size, usage, 0, D3DPOOL_DEFAULT, &vbuffer_, NULL); } } void SetData(const uint8_t *data, size_t size) override { From 2d8f6f8287d6ee157fc971cc9e0836794093cfee Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 1 Sep 2014 08:09:20 -0700 Subject: [PATCH 1250/1445] thin3d: Simplify d3d9 debug dll loading. --- thin3d/d3dx9_loader.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/thin3d/d3dx9_loader.cpp b/thin3d/d3dx9_loader.cpp index 539916fb98..a5cffcfd88 100644 --- a/thin3d/d3dx9_loader.cpp +++ b/thin3d/d3dx9_loader.cpp @@ -68,11 +68,11 @@ bool checkExistsDllW(const WCHAR* sDllFilename) { return false; } -bool getLatestInstalledD3DXVersion(unsigned int* piOutVers) { +bool getLatestInstalledD3DXVersion(unsigned int* piOutVers, bool debugVersion) { *piOutVers = 0; std::wstring fname; for (unsigned int cvers = 45; cvers > 0; cvers--) { - makeD3DX9dllFilename_by_versionW(fname, cvers); + makeD3DX9dllFilename_by_versionW(fname, cvers, debugVersion); if (checkExistsDllW(fname.c_str())) { *piOutVers = cvers; return true; @@ -87,7 +87,7 @@ HMODULE loadDllLastVersion(unsigned int* version, bool debugVersion) { if (version) *version = 0; - if (!getLatestInstalledD3DXVersion(version)) { + if (!getLatestInstalledD3DXVersion(version, debugVersion)) { return 0; } @@ -108,7 +108,7 @@ HMODULE loadDllLastVersion(unsigned int* version, bool debugVersion) { } void handleNotFoundAddr(const char* sFuncName) { - ELOG("Failed to find D3DX fucntion %s", sFuncName); + ELOG("Failed to find D3DX function %s", sFuncName); failedFunctions++; } From 58f8b7aa218961cc65389bb12b38b5bbf6f3f3a7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 1 Sep 2014 08:41:17 -0700 Subject: [PATCH 1251/1445] thin3d: Avoid dynamic texturing locking. Seems like it requires checking caps, and these textures are probably not dynamic anyway. --- thin3d/thin3d_d3d9.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 2912a047db..0e68b10615 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -288,7 +288,7 @@ void Thin3DDX9Texture::SetImageData(int x, int y, int z, int width, int height, { D3DLOCKED_RECT rect; if (x == 0 && y == 0) { - tex_->LockRect(level, &rect, NULL, D3DLOCK_DISCARD); + tex_->LockRect(level, &rect, NULL, 0); for (int i = 0; i < height; i++) { uint8_t *dest = (uint8_t *)rect.pBits + rect.Pitch * i; From 66c19727ce59e77de724ecf68569f8fe9170fa83 Mon Sep 17 00:00:00 2001 From: Daniel Nagel Date: Mon, 1 Sep 2014 20:24:26 +0200 Subject: [PATCH 1252/1445] Add missing mode flag --- base/PCMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 051df396b2..c1f80dd0e9 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -500,7 +500,7 @@ int main(int argc, char *argv[]) { dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; - g_Screen = SDL_CreateWindow(app_name_nice.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, pixel_xres, pixel_yres, 0); + g_Screen = SDL_CreateWindow(app_name_nice.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, pixel_xres, pixel_yres, mode); if (g_Screen == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); From 439ea67cc2f84267bfcb932a0c2efd818ce239ca Mon Sep 17 00:00:00 2001 From: Daniel Nagel Date: Tue, 2 Sep 2014 07:34:08 +0200 Subject: [PATCH 1253/1445] Add error handling for SDL_GL_CreateContext --- base/PCMain.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index c1f80dd0e9..6afa48eb64 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -502,12 +502,17 @@ int main(int argc, char *argv[]) { g_Screen = SDL_CreateWindow(app_name_nice.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, pixel_xres, pixel_yres, mode); if (g_Screen == NULL) { - fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); + fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); SDL_Quit(); return 2; } SDL_GLContext glContext = SDL_GL_CreateContext(g_Screen); + if (glContext == NULL) { + fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError()); + SDL_Quit(); + return 2; + } #ifdef USING_EGL EGL_Init(); From 8e38e177b4a7573bf21c65c00ef8bf684493995b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 4 Sep 2014 00:38:13 -0700 Subject: [PATCH 1254/1445] Check for the EXT_gpu_shader4 extension. --- gfx_es2/gl_state.cpp | 1 + gfx_es2/gpu_features.h | 1 + 2 files changed, 2 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index b8f8c95367..1877c499c3 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -212,6 +212,7 @@ void CheckGLExtensions() { gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0; + gl_extensions.EXT_gpu_shader4 = strstr(extString, "GL_EXT_gpu_shader4") != 0; gl_extensions.NV_framebuffer_blit = strstr(extString, "GL_NV_framebuffer_blit") != 0; if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) { // Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index b328208c5b..0415fb60d2 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -52,6 +52,7 @@ struct GLExtensions { bool EXT_unpack_subimage; // always supported on desktop and ES3 bool EXT_bgra; bool EXT_shader_framebuffer_fetch; + bool EXT_gpu_shader4; bool EXT_blend_minmax; bool FBO_EXT; bool PBO_EXT; From 4a85cbe4040e4a33484e8b895a4d84ed1e66479d Mon Sep 17 00:00:00 2001 From: Daniel Nagel Date: Thu, 4 Sep 2014 10:20:04 +0200 Subject: [PATCH 1255/1445] Make sure fullscreen state is properly reflected in the UI --- base/PCMain.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 6afa48eb64..5285640407 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -348,17 +348,8 @@ void ToggleFullScreenIfFlagSet() { if (g_ToggleFullScreenNextFrame) { g_ToggleFullScreenNextFrame = false; -#if 1 - pixel_xres = g_DesktopWidth; - pixel_yres = g_DesktopHeight; - dp_xres = (float)pixel_xres; - dp_yres = (float)pixel_yres; - Uint32 window_flags = SDL_GetWindowFlags(g_Screen); SDL_SetWindowFullscreen(g_Screen, window_flags ^ SDL_WINDOW_FULLSCREEN_DESKTOP); - - NativeResized(); -#endif } } @@ -628,11 +619,26 @@ int main(int argc, char *argv[]) { switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: { + Uint32 window_flags = SDL_GetWindowFlags(g_Screen); + bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN); + pixel_xres = event.window.data1; pixel_yres = event.window.data2; dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; NativeResized(); + +#if defined(PPSSPP) + // Set variable here in case fullscreen was toggled by hotkey + g_Config.bFullScreen = fullscreen; + + // Hide/Show cursor correctly toggling fullscreen + if (lastUIState == UISTATE_INGAME && fullscreen && !g_Config.bShowTouchControls) { + SDL_ShowCursor(SDL_DISABLE); + } else if (lastUIState != UISTATE_INGAME || !fullscreen) { + SDL_ShowCursor(SDL_ENABLE); + } +#endif break; } break; @@ -706,7 +712,8 @@ int main(int argc, char *argv[]) { NativeKey(key); // SDL2 doesn't consider the mousewheel a button anymore - // so let's send the KEY_UP right away + // so let's send the KEY_UP right away. + // Maybe KEY_UP alone will suffice? key.flags = KEY_UP; NativeKey(key); } From ef3912f63f5bbb4738cc6fa6949e25197626e5c5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 6 Sep 2014 10:27:47 +0200 Subject: [PATCH 1256/1445] Proper msvc implementation of snprintf - _snprintf is different (does not add a null terminator) --- Android.mk | 1 + base/compat.cpp | 28 ++++++++++++++++++++++++++++ base/compat.h | 11 +++++++++++ base/logging.h | 10 +++------- gfx/texture.h | 2 ++ native.vcxproj | 2 ++ native.vcxproj.filters | 2 ++ 7 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 base/compat.cpp create mode 100644 base/compat.h diff --git a/Android.mk b/Android.mk index 8bc0fb1a02..9a2b6b387f 100644 --- a/Android.mk +++ b/Android.mk @@ -12,6 +12,7 @@ LOCAL_SRC_FILES :=\ audio/mixer.cpp.arm \ base/backtrace.cpp \ base/buffer.cpp \ + base/compat.cpp \ base/display.cpp \ base/timeutil.cpp \ base/colorutil.cpp \ diff --git a/base/compat.cpp b/base/compat.cpp new file mode 100644 index 0000000000..0368a39d4a --- /dev/null +++ b/base/compat.cpp @@ -0,0 +1,28 @@ +#include +#include + +#include "base/compat.h" + +#ifdef _MSC_VER + +static int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) { + int count = -1; + if (size != 0) + count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); + if (count == -1) + count = _vscprintf(format, ap); + return count; +} + +int c99_snprintf(char* str, size_t size, const char* format, ...) { + int count; + va_list ap; + + va_start(ap, format); + count = c99_vsnprintf(str, size, format, ap); + va_end(ap); + + return count; +} + +#endif \ No newline at end of file diff --git a/base/compat.h b/base/compat.h new file mode 100644 index 0000000000..cd47806265 --- /dev/null +++ b/base/compat.h @@ -0,0 +1,11 @@ +#pragma once + +// Implement C99 functions and similar that are missing in MSVC. + +#ifdef _MSC_VER + +int c99_snprintf(char* str, size_t size, const char* format, ...); +#define snprintf c99_snprintf +#define vscprintf _vscprintf + +#endif \ No newline at end of file diff --git a/base/logging.h b/base/logging.h index cda8eaf8d0..4b11631f64 100644 --- a/base/logging.h +++ b/base/logging.h @@ -2,18 +2,14 @@ #include "base/arch.h" #include "base/backtrace.h" +#include "base/compat.h" // Simple wrapper around Android's logging interface that also allows other // implementations, and also some misc utilities. - -// Disable annoying warnings in VS #ifdef _MSC_VER -#pragma warning (disable:4996) //strcpy may be dangerous - -#if !defined(snprintf) -#define snprintf _snprintf -#endif +// Disable annoying warnings in VS +#pragma warning (disable:4996) //strcpy may be dangerous, etc. #endif #undef Crash diff --git a/gfx/texture.h b/gfx/texture.h index a712ce2dc4..702cb74189 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -3,6 +3,8 @@ // Load and manage OpenGL textures easily. Supports ETC1 compressed texture with mipmaps // in the custom ZIM format. +// This is deprecated - start using Thin3D instead. + #include #include "base/basictypes.h" diff --git a/native.vcxproj b/native.vcxproj index fc39463309..59eaa83023 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -193,6 +193,7 @@ + @@ -323,6 +324,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 5025807740..3cc3807123 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -350,6 +350,7 @@ thin3d + @@ -820,6 +821,7 @@ thin3d + From e96761e400e03a4ad54d753953f3d71df8bef016 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 6 Sep 2014 13:49:01 +0200 Subject: [PATCH 1257/1445] Hook up Thin3D to GLLost interface. Textures now remember their filename, shaders their source, so they can recreate themselves. --- gfx_es2/draw_buffer.cpp | 12 +---- gfx_es2/draw_buffer.h | 6 +-- image/zim_load.cpp | 6 +-- image/zim_load.h | 2 +- thin3d/thin3d.cpp | 75 ++++++++++++++++++++++++---- thin3d/thin3d.h | 106 ++++++++++++++++++++++------------------ thin3d/thin3d_d3d9.cpp | 29 ++++++++--- thin3d/thin3d_gl.cpp | 81 +++++++++++++++++++++++++++--- 8 files changed, 229 insertions(+), 88 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 78128035e5..60901f358c 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -33,7 +33,7 @@ DrawBuffer::~DrawBuffer() { delete [] verts_; } -void DrawBuffer::Init(Thin3DContext *t3d, bool registerAsHolder) { +void DrawBuffer::Init(Thin3DContext *t3d) { if (inited_) return; @@ -46,10 +46,6 @@ void DrawBuffer::Init(Thin3DContext *t3d, bool registerAsHolder) { components.push_back(Thin3DVertexComponent("TexCoord0", SEM_TEXCOORD0, FLOATx2, 12)); components.push_back(Thin3DVertexComponent("Color0", SEM_COLOR0, UNORM8x4, 20)); vformat_ = t3d_->CreateVertexFormat(components, 24); - - if (registerAsHolder) { - register_gl_resource_holder(this); - } } void DrawBuffer::Shutdown() { @@ -57,12 +53,6 @@ void DrawBuffer::Shutdown() { vformat_->Release(); inited_ = false; - unregister_gl_resource_holder(this); -} - -void DrawBuffer::GLLost() { - inited_ = false; - Init(t3d_, false); } void DrawBuffer::Begin(Thin3DShaderSet *program, DrawBufferPrimitiveMode dbmode) { diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 112b2a45b4..59b384087b 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -55,7 +55,7 @@ struct GradientStop { class TextDrawer; -class DrawBuffer : public GfxResourceHolder { +class DrawBuffer { public: DrawBuffer(); ~DrawBuffer(); @@ -64,11 +64,9 @@ public: void End(); // TODO: Enforce these. Now Init is autocalled and shutdown not called. - void Init(Thin3DContext *t3d, bool registerAsHolder = true); + void Init(Thin3DContext *t3d); void Shutdown(); - virtual void GLLost(); - int Count() const { return count_; } void Flush(bool set_blend_state = true); diff --git a/image/zim_load.cpp b/image/zim_load.cpp index bcaa25bd5c..cfd7b1a7d5 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -54,7 +54,7 @@ static unsigned int log2i(unsigned int val) { return ret; } -int LoadZIMPtr(const uint8_t *zim, int datasize, int *width, int *height, int *flags, uint8 **image) { +int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int *flags, uint8 **image) { if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') { ELOG("Not a ZIM file"); return 0; @@ -110,8 +110,8 @@ int LoadZIMPtr(const uint8_t *zim, int datasize, int *width, int *height, int *f } if (*flags & ZIM_ZLIB_COMPRESSED) { - long outlen = total_data_size; - if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), datasize - 16)) { + long outlen = (long)total_data_size; + if (Z_OK != ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), (long)datasize - 16)) { free(*image); *image = 0; return 0; diff --git a/image/zim_load.h b/image/zim_load.h index bc98f459c8..65bc1f5490 100644 --- a/image/zim_load.h +++ b/image/zim_load.h @@ -48,4 +48,4 @@ enum { // Watch out! If the image has mipmaps, multiple values will be written // to width, height, and image, as if they were arrays, up to 12 (max texture size is 4096 which is 2^12). int LoadZIM(const char *filename, int *width, int *height, int *flags, uint8_t **image); -int LoadZIMPtr(const uint8_t *zim, int datasize, int *width, int *height, int *flags, uint8_t **image); \ No newline at end of file +int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int *flags, uint8_t **image); \ No newline at end of file diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 5dbb9dee68..6011204b73 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -1,7 +1,9 @@ #include +#include "base/logging.h" #include "image/zim_load.h" #include "image/png_load.h" +#include "file/vfs.h" static const char * const glsl_fsTexCol = "varying vec4 oColor0;\n" @@ -126,32 +128,83 @@ static T3DImageFormat ZimToT3DFormat(int zim) { } } -Thin3DTexture *Thin3DContext::CreateTextureFromFile(const char *filename, T3DFileType type) { - int width[16], height[16], flags; +bool Thin3DTexture::LoadFromFileData(const uint8_t *data, size_t dataSize, T3DImageType type) { + int width[16], height[16], zim_flags; uint8_t *image[16] = { nullptr }; - int num_levels = LoadZIM(filename, width, height, &flags, image); + int num_levels = LoadZIMPtr(data, dataSize, width, height, &zim_flags, image); if (num_levels == 0) { - return NULL; + return false; } - T3DImageFormat fmt = ZimToT3DFormat(flags & ZIM_FORMAT_MASK); + T3DImageFormat fmt = ZimToT3DFormat(zim_flags & ZIM_FORMAT_MASK); + + // TODO: Cube map / 3D texture / texture array support + + Create(LINEAR2D, fmt, width[0], height[0], 1, num_levels); - Thin3DTexture *tex = CreateTexture(LINEAR2D, fmt, width[0], height[0], 1, num_levels); for (int i = 0; i < num_levels; i++) { - tex->SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]); + SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]); free(image[i]); } - return tex; + + Finalize(zim_flags); + return true; } -Thin3DTexture *Thin3DContext::CreateTextureFromFileData(const char *data, int size, T3DFileType type) { +bool Thin3DTexture::LoadFromFile(const std::string &filename, T3DImageType type) { + filename_ = ""; + size_t fileSize; + uint8_t *buffer = VFSReadFile(filename.c_str(), &fileSize); + if (!buffer) { + return false; + } + bool retval = LoadFromFileData(buffer, fileSize, type); + if (retval) { + filename_ = filename; + } + delete[] buffer; + return retval; +} + +Thin3DTexture *Thin3DContext::CreateTextureFromFile(const char *filename, T3DImageType type) { + Thin3DTexture *tex = CreateTexture(); + if (!tex->LoadFromFile(filename, type)) { + tex->Release(); + return NULL; + } else { + return tex; + } +} + +T3DImageType DetectImageFileType(const uint8_t *data, size_t size) { + if (!memcmp(data, "ZIMG", 4)) { + return ZIM; + } else if (!memcmp(data, "\x89\x50\x4E\x47", 4)) { + return PNG; + } else if (!memcmp(data, "\xff\xd8\xff\xe0", 4)) { + return JPEG; + } else { + return TYPE_UNKNOWN; + } +} + +// TODO: Remove the code duplication between this and LoadFromFileData +Thin3DTexture *Thin3DContext::CreateTextureFromFileData(const uint8_t *data, int size, T3DImageType type) { int width[16], height[16], zim_flags = 0; uint8_t *image[16] = { nullptr }; int num_levels = 0; T3DImageFormat fmt; + if (type == DETECT) { + type = DetectImageFileType(data, size); + } + if (type == TYPE_UNKNOWN) { + ELOG("File has unknown format"); + return nullptr; + } + switch (type) { case ZIM: num_levels = LoadZIMPtr((const uint8_t *)data, size, width, height, &zim_flags, image); @@ -165,6 +218,10 @@ Thin3DTexture *Thin3DContext::CreateTextureFromFileData(const char *data, int si num_levels = 1; fmt = RGBA8888; break; + + default: + ELOG("Unknown image format"); + return nullptr; } if (num_levels == 0) { diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 22c4a125d1..51890a1e70 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -9,6 +9,7 @@ #include #include #include +#include class Matrix4x4; @@ -110,6 +111,53 @@ enum T3DClear : int { STENCIL = 4, }; +enum T3DTextureType : uint8_t { + UNKNOWN, + LINEAR1D, + LINEAR2D, + LINEAR3D, + CUBE, + ARRAY1D, + ARRAY2D, +}; + +enum T3DImageFormat : uint8_t { + LUMINANCE, + RGBA8888, + RGBA4444, + DXT1, + ETC1, // Needs simulation on many platforms + D16, + D24S8, + D24X8, +}; + +enum T3DRenderState : uint8_t { + CULL_MODE, +}; + +enum T3DCullMode : uint8_t { + NO_CULL, + CW, + CCW, +}; + +enum T3DImageType { + PNG, + JPEG, + ZIM, + DETECT, + TYPE_UNKNOWN, +}; + +enum T3DInfo { + APINAME, + APIVERSION, + VENDOR, + SHADELANGVERSION, + RENDERER, +}; + // Binary compatible with D3D11 viewport. struct T3DViewport { float TopLeftX; @@ -126,7 +174,7 @@ public: virtual ~Thin3DObject() {} virtual void AddRef() { refcount_++; } - virtual void Release() { refcount_--; if (!refcount_) delete this; } // TODO: Refcount + virtual void Release() { refcount_--; if (!refcount_) delete this; } private: int refcount_; @@ -148,6 +196,10 @@ public: class Thin3DTexture : public Thin3DObject { public: + bool LoadFromFile(const std::string &filename, T3DImageType type = T3DImageType::DETECT); + bool LoadFromFileData(const uint8_t *data, size_t dataSize, T3DImageType type = T3DImageType::DETECT); + + virtual bool Create(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) = 0; virtual void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) = 0; virtual void AutoGenMipmaps() = 0; virtual void Finalize(int zim_flags) = 0; // TODO: Tidy up @@ -156,6 +208,7 @@ public: int Height() { return height_; } int Depth() { return depth_; } protected: + std::string filename_; // Textures that are loaded from files can reload themselves automatically. int width_, height_, depth_; }; @@ -199,51 +252,6 @@ struct T3DBlendStateDesc { // int colorMask; }; -enum T3DTextureType : uint8_t { - LINEAR1D, - LINEAR2D, - LINEAR3D, - CUBE, - ARRAY1D, - ARRAY2D, -}; - -enum T3DImageFormat : uint8_t { - LUMINANCE, - RGBA8888, - RGBA4444, - DXT1, - ETC1, // Needs simulation on many platforms - D16, - D24S8, - D24X8, -}; - -enum T3DRenderState : uint8_t { - CULL_MODE, -}; - -enum T3DCullMode : uint8_t { - NO_CULL, - CW, - CCW, -}; - -enum T3DFileType { - PNG, - JPEG, - ZIM, - DETECT, -}; - -enum T3DInfo { - APINAME, - APIVERSION, - VENDOR, - SHADELANGVERSION, - RENDERER, -}; - class Thin3DContext : public Thin3DObject { public: virtual ~Thin3DContext(); @@ -253,11 +261,13 @@ public: virtual Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0; virtual Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) = 0; virtual Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) = 0; + + virtual Thin3DTexture *CreateTexture() = 0; // To be later filled in by ->LoadFromFile or similar. virtual Thin3DTexture *CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) = 0; // Common Thin3D function, uses CreateTexture - Thin3DTexture *CreateTextureFromFile(const char *filename, T3DFileType fileType); - Thin3DTexture *CreateTextureFromFileData(const char *data, int size, T3DFileType fileType); + Thin3DTexture *CreateTextureFromFile(const char *filename, T3DImageType fileType); + Thin3DTexture *CreateTextureFromFileData(const uint8_t *data, int size, T3DImageType fileType); // Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them. Thin3DBlendState *GetBlendStatePreset(T3DBlendStatePreset preset) { return bsPresets_[preset]; } diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 0e68b10615..29a5813c0e 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -214,13 +214,17 @@ private: class Thin3DDX9Texture : public Thin3DTexture { public: + Thin3DDX9Texture(LPDIRECT3DDEVICE9 device) : device_(device), type_(T3DTextureType::UNKNOWN), fmt_(D3DFMT_UNKNOWN), tex_(NULL), volTex_(NULL), cubeTex_(NULL) { + } Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels); + bool Create(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override; void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override; void AutoGenMipmaps() override {} void SetToSampler(LPDIRECT3DDEVICE9 device, int sampler); void Finalize(int zim_flags) override {} private: + LPDIRECT3DDEVICE9 device_; T3DTextureType type_; D3DFORMAT fmt_; LPDIRECT3DTEXTURE9 tex_; @@ -239,28 +243,35 @@ D3DFORMAT FormatToD3D(T3DImageFormat fmt) { } Thin3DDX9Texture::Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) - : type_(type) { + : device_(device), type_(type), tex_(NULL), volTex_(NULL), cubeTex_(NULL) { + Create(type, format, width, height, depth, mipLevels); +} + +bool Thin3DDX9Texture::Create(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) { width_ = width; height_ = height; depth_ = depth; + type_ = type; tex_ = NULL; fmt_ = FormatToD3D(format); - HRESULT hr; - switch (type_) { + HRESULT hr = E_FAIL; + switch (type) { case LINEAR1D: case LINEAR2D: - hr = device->CreateTexture(width, height, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &tex_, NULL); + hr = device_->CreateTexture(width, height, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &tex_, NULL); break; case LINEAR3D: - hr = device->CreateVolumeTexture(width, height, depth, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &volTex_, NULL); + hr = device_->CreateVolumeTexture(width, height, depth, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &volTex_, NULL); break; case CUBE: - hr = device->CreateCubeTexture(width, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &cubeTex_, NULL); + hr = device_->CreateCubeTexture(width, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &cubeTex_, NULL); break; } if (FAILED(hr)) { ELOG("Texture creation failed"); + return false; } + return true; } inline uint16_t Shuffle4444(uint16_t x) { @@ -347,6 +358,7 @@ public: Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override; Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) override; + Thin3DTexture *CreateTexture() override; Thin3DTexture *CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override; Thin3DShader *CreateVertexShader(const char *glsl_source, const char *hlsl_source) override; @@ -463,6 +475,11 @@ Thin3DBlendState *Thin3DDX9Context::CreateBlendState(const T3DBlendStateDesc &de return bs; } +Thin3DTexture *Thin3DDX9Context::CreateTexture() { + Thin3DDX9Texture *tex = new Thin3DDX9Texture(device_); + return tex; +} + Thin3DTexture *Thin3DDX9Context::CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) { Thin3DDX9Texture *tex = new Thin3DDX9Texture(device_, type, format, width, height, depth, mipLevels); return tex; diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 83e9460bd1..644dd448a7 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -8,6 +8,7 @@ #include "math/lin/matrix4x4.h" #include "thin3d/thin3d.h" #include "gfx_es2/gl_state.h" +#include "gfx/gl_lost_manager.h" static const unsigned short compToGL[] = { GL_NEVER, @@ -96,7 +97,7 @@ public: } }; -class Thin3DGLBuffer : public Thin3DBuffer { +class Thin3DGLBuffer : public Thin3DBuffer, GfxResourceHolder { public: Thin3DGLBuffer(size_t size, uint32_t flags) { glGenBuffers(1, &buffer_); @@ -107,8 +108,10 @@ public: else usage_ = GL_STATIC_DRAW; knownSize_ = 0; + register_gl_resource_holder(this); } ~Thin3DGLBuffer() override { + unregister_gl_resource_holder(this); glDeleteBuffers(1, &buffer_); } @@ -131,6 +134,12 @@ public: glBindBuffer(target_, buffer_); } + void GLLost() override { + ILOG("Recreating vertex buffer after glLost"); + knownSize_ = 0; // Will cause a new glBufferData call. Should genBuffers again though? + glGenBuffers(1, &buffer_); + } + private: GLuint buffer_; GLuint target_; @@ -139,6 +148,8 @@ private: size_t knownSize_; }; +// Not registering this as a resource holder, instead ShaderSet is registered. It will +// invoke Compile again to recreate the shader then link them together. class Thin3DGLShader : public Thin3DShader { public: Thin3DGLShader(bool isFragmentShader) : shader_(0), type_(0) { @@ -146,7 +157,10 @@ public: } bool Compile(const char *source); - GLuint GetShader() const { return shader_; } + GLuint GetShader() const { + return shader_; + } + const std::string &GetSource() const { return source_; } ~Thin3DGLShader() { glDeleteShader(shader_); @@ -156,9 +170,11 @@ private: GLuint shader_; GLuint type_; bool ok_; + std::string source_; // So we can recompile in case of context loss. }; bool Thin3DGLShader::Compile(const char *source) { + source_ = source; shader_ = glCreateShader(type_); std::string temp; @@ -203,12 +219,14 @@ struct UniformInfo { // TODO: Fold BlendState into this? Seems likely to be right for DX12 etc. // TODO: Add Uniform Buffer support. -class Thin3DGLShaderSet : public Thin3DShaderSet { +class Thin3DGLShaderSet : public Thin3DShaderSet, GfxResourceHolder { public: Thin3DGLShaderSet() { - program_ = glCreateProgram(); + program_ = 0; + register_gl_resource_holder(this); } ~Thin3DGLShaderSet() { + unregister_gl_resource_holder(this); vshader->Release(); fshader->Release(); glDeleteProgram(program_); @@ -223,6 +241,12 @@ public: void SetVector(const char *name, float *value, int n); void SetMatrix4x4(const char *name, const Matrix4x4 &value) override; + void GLLost() { + vshader->Compile(vshader->GetSource().c_str()); + fshader->Compile(fshader->GetSource().c_str()); + Link(); + } + Thin3DGLShader *vshader; Thin3DGLShader *fshader; @@ -242,6 +266,7 @@ public: Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override; Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) override; Thin3DTexture *CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override; + Thin3DTexture *CreateTexture() override; // Bound state objects void SetBlendState(Thin3DBlendState *state) override { @@ -335,16 +360,42 @@ GLuint TypeToTarget(T3DTextureType type) { } } -class Thin3DGLTexture : public Thin3DTexture { +class Thin3DGLTexture : public Thin3DTexture, GfxResourceHolder { public: + Thin3DGLTexture() : tex_(0), target_(0) { + width_ = 0; + height_ = 0; + depth_ = 0; + glGenTextures(1, &tex_); + register_gl_resource_holder(this); + } Thin3DGLTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) : format_(format), tex_(0), target_(TypeToTarget(type)), mipLevels_(mipLevels) { width_ = width; height_ = height; depth_ = depth; glGenTextures(1, &tex_); + register_gl_resource_holder(this); } ~Thin3DGLTexture() { - glDeleteTextures(1, &tex_); + unregister_gl_resource_holder(this); + Destroy(); + } + + bool Create(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) { + format_ = format; + target_ = TypeToTarget(type); + mipLevels_ = mipLevels; + width_ = width; + height_ = height; + depth_ = depth; + return true; + } + + void Destroy() { + if (tex_) { + glDeleteTextures(1, &tex_); + tex_ = 0; + } } void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override; void AutoGenMipmaps() override; @@ -352,6 +403,19 @@ public: void Bind() { glBindTexture(target_, tex_); } + + void GLLost() { + if (!filename_.empty()) { + if (LoadFromFile(filename_.c_str())) { + ILOG("Reloaded lost texture %s", filename_.c_str()); + } else { + ELOG("Failed to reload lost texture %s", filename_.c_str()); + } + } else { + WLOG("Texture %p cannot be restored - has no filename", this); + tex_ = 0; + } + } void Finalize(int zim_flags); private: @@ -362,6 +426,10 @@ private: int mipLevels_; }; +Thin3DTexture *Thin3DGLContext::CreateTexture() { + return new Thin3DGLTexture(); +} + Thin3DTexture *Thin3DGLContext::CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) { return new Thin3DGLTexture(type, format, width, height, depth, mipLevels); } @@ -502,6 +570,7 @@ Thin3DShader *Thin3DGLContext::CreateFragmentShader(const char *glsl_source, con } bool Thin3DGLShaderSet::Link() { + program_ = glCreateProgram(); glAttachShader(program_, vshader->GetShader()); glAttachShader(program_, fshader->GetShader()); From 69bad8ba74dda4745f4ad5d12fe0cfdbf4230f1a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 6 Sep 2014 08:11:52 -0700 Subject: [PATCH 1258/1445] Linux buildfix. --- thin3d/thin3d.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 6011204b73..304effc907 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -1,3 +1,4 @@ +#include #include #include "base/logging.h" From 588930dd66219ccd644da63a4b723730b1c2f139 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 7 Sep 2014 10:47:21 +0200 Subject: [PATCH 1259/1445] Thin3d: Minor API change in prep for DX11 --- gfx_es2/draw_buffer.cpp | 5 ++++- thin3d/thin3d.h | 6 ++++-- thin3d/thin3d_d3d9.cpp | 8 ++++++-- thin3d/thin3d_gl.cpp | 6 +++--- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 60901f358c..0816ff8592 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -45,7 +45,10 @@ void DrawBuffer::Init(Thin3DContext *t3d) { components.push_back(Thin3DVertexComponent("Position", SEM_POSITION, FLOATx3, 0)); components.push_back(Thin3DVertexComponent("TexCoord0", SEM_TEXCOORD0, FLOATx2, 12)); components.push_back(Thin3DVertexComponent("Color0", SEM_COLOR0, UNORM8x4, 20)); - vformat_ = t3d_->CreateVertexFormat(components, 24); + + Thin3DShader *vshader = t3d_->GetVshaderPreset(VS_TEXTURE_COLOR_2D); + + vformat_ = t3d_->CreateVertexFormat(components, 24, vshader); } void DrawBuffer::Shutdown() { diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 51890a1e70..1025bb9dfe 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -17,7 +17,8 @@ enum T3DBlendEquation : int { ADD, SUBTRACT, REV_SUBTRACT, - // MIN, MAX, + MIN, + MAX, }; enum T3DComparison : int { @@ -122,6 +123,7 @@ enum T3DTextureType : uint8_t { }; enum T3DImageFormat : uint8_t { + IMG_UNKNOWN, LUMINANCE, RGBA8888, RGBA4444, @@ -260,7 +262,7 @@ public: virtual Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) = 0; virtual Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0; virtual Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) = 0; - virtual Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) = 0; + virtual Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride, Thin3DShader *vshader) = 0; virtual Thin3DTexture *CreateTexture() = 0; // To be later filled in by ->LoadFromFile or similar. virtual Thin3DTexture *CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) = 0; diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 29a5813c0e..749d909b4b 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -30,6 +30,9 @@ static const D3DCMPFUNC compareToD3D9[] = { static const D3DBLENDOP blendEqToD3D9[] = { D3DBLENDOP_ADD, D3DBLENDOP_SUBTRACT, + D3DBLENDOP_REVSUBTRACT, + D3DBLENDOP_MIN, + D3DBLENDOP_MAX, }; // Could be declared as u8 @@ -357,7 +360,7 @@ public: Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override; Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override; - Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) override; + Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride, Thin3DShader *vshader) override; Thin3DTexture *CreateTexture() override; Thin3DTexture *CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override; @@ -458,7 +461,7 @@ Thin3DDepthStencilState *Thin3DDX9Context::CreateDepthStencilState(bool depthTes return ds; } -Thin3DVertexFormat *Thin3DDX9Context::CreateVertexFormat(const std::vector &components, int stride) { +Thin3DVertexFormat *Thin3DDX9Context::CreateVertexFormat(const std::vector &components, int stride, Thin3DShader *vshader) { Thin3DDX9VertexFormat *fmt = new Thin3DDX9VertexFormat(device_, components, stride); return fmt; } @@ -548,6 +551,7 @@ Thin3DDX9VertexFormat::Thin3DDX9VertexFormat(LPDIRECT3DDEVICE9 device, const std if (FAILED(hr)) { ELOG("Error creating vertex decl"); } + delete[] elements; stride_ = stride; } diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 644dd448a7..2a1f1acf33 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -52,7 +52,7 @@ static const char *glsl_fragment_prelude = "precision mediump float;\n" "#endif\n"; -inline void Uint32ToFloat4(uint32_t u, float f[4]) { +static inline void Uint32ToFloat4(uint32_t u, float f[4]) { f[0] = ((u >> 0) & 0xFF) * (1.0f / 255.0f); f[1] = ((u >> 8) & 0xFF) * (1.0f / 255.0f); f[2] = ((u >> 16) & 0xFF) * (1.0f / 255.0f); @@ -264,7 +264,7 @@ public: Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override; Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override; Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override; - Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride) override; + Thin3DVertexFormat *CreateVertexFormat(const std::vector &components, int stride, Thin3DShader *vshader) override; Thin3DTexture *CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override; Thin3DTexture *CreateTexture() override; @@ -336,7 +336,7 @@ Thin3DGLContext::Thin3DGLContext() { Thin3DGLContext::~Thin3DGLContext() { } -Thin3DVertexFormat *Thin3DGLContext::CreateVertexFormat(const std::vector &components, int stride) { +Thin3DVertexFormat *Thin3DGLContext::CreateVertexFormat(const std::vector &components, int stride, Thin3DShader *vshader) { Thin3DGLVertexFormat *fmt = new Thin3DGLVertexFormat(); fmt->components_ = components; fmt->stride_ = stride; From d5711f360dc8789d65db9f80b9502a9ed26dbe99 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Sep 2014 13:46:09 -0700 Subject: [PATCH 1260/1445] thin3d: Fix some leaks in d3d9 code. --- thin3d/thin3d_d3d9.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 749d909b4b..30b6dc2e3b 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -99,6 +99,15 @@ public: device->CreateVertexBuffer((UINT)size, usage, 0, D3DPOOL_DEFAULT, &vbuffer_, NULL); } } + virtual ~Thin3DDX9Buffer() override { + if (ibuffer_) { + ibuffer_->Release(); + } + if (vbuffer_) { + vbuffer_->Release(); + } + } + void SetData(const uint8_t *data, size_t size) override { if (!size) return; @@ -220,6 +229,7 @@ public: Thin3DDX9Texture(LPDIRECT3DDEVICE9 device) : device_(device), type_(T3DTextureType::UNKNOWN), fmt_(D3DFMT_UNKNOWN), tex_(NULL), volTex_(NULL), cubeTex_(NULL) { } Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels); + ~Thin3DDX9Texture(); bool Create(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override; void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override; void AutoGenMipmaps() override {} @@ -250,6 +260,18 @@ Thin3DDX9Texture::Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type Create(type, format, width, height, depth, mipLevels); } +Thin3DDX9Texture::~Thin3DDX9Texture() { + if (tex_) { + tex_->Release(); + } + if (volTex_) { + volTex_->Release(); + } + if (cubeTex_) { + cubeTex_->Release(); + } +} + bool Thin3DDX9Texture::Create(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) { width_ = width; height_ = height; From c6060670445ecc2f0f82cf5799c0b7b467599f08 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 8 Sep 2014 14:20:30 -0700 Subject: [PATCH 1261/1445] Bring back glBindFramebufferEXT() in OpenGL. Did not intentionally remove this. Broke Intel and AMD cards which did not yet support the ARB_framebuffer_object extension. --- gfx_es2/fbo.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 232ed85770..a338417bf3 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -293,7 +293,13 @@ static void fbo_bind_fb_target(bool read, GLuint name) { GLenum target = fbo_get_fb_target(read, &cached); if (*cached != name) { - glBindFramebuffer(target, name); + if (gl_extensions.FBO_ARB) { + glBindFramebuffer(target, name); + } else { +#ifndef USING_GLES2 + glBindFramebufferEXT(target, name); +#endif + } *cached = name; } } From 3c0d666e90e528a91d76d0d07b312ae76b4d1c63 Mon Sep 17 00:00:00 2001 From: Sacha Date: Wed, 10 Sep 2014 05:12:17 +1000 Subject: [PATCH 1262/1445] Qt audio sounds a lot better with a larger mixlen. I suppose real buffers would be a proper solution although I can't seem to get it working. --- base/QtMain.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index 85685a4a50..c966315d28 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -242,6 +242,7 @@ static MainUI* emugl = NULL; #define AUDIO_CHANNELS 2 #define AUDIO_SAMPLES 2048 #define AUDIO_SAMPLESIZE 16 +#define AUDIO_BUFFERS 5 class MainAudio: public QObject { Q_OBJECT @@ -269,7 +270,7 @@ public slots: fmt.setSampleSize(AUDIO_SAMPLESIZE); fmt.setByteOrder(QAudioFormat::LittleEndian); fmt.setSampleType(QAudioFormat::SignedInt); - mixlen = 2*AUDIO_CHANNELS*AUDIO_SAMPLES; + mixlen = sizeof(short)*AUDIO_BUFFERS*AUDIO_CHANNELS*AUDIO_SAMPLES; mixbuf = (char*)malloc(mixlen); output = new QAudioOutput(fmt); output->setBufferSize(mixlen); @@ -281,9 +282,9 @@ public slots: protected: void timerEvent(QTimerEvent *) { memset(mixbuf, 0, mixlen); - size_t frames = NativeMix((short *)mixbuf, AUDIO_SAMPLES); + size_t frames = NativeMix((short *)mixbuf, AUDIO_BUFFERS*AUDIO_SAMPLES); if (frames > 0) - feed->write(mixbuf, sizeof(short) * 2 * frames); + feed->write(mixbuf, sizeof(short) * AUDIO_CHANNELS * frames); } private: QIODevice* feed; From 33d496d76f529a6b921c4c8fef70e6c5fd2caef7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 9 Sep 2014 22:26:53 +0200 Subject: [PATCH 1263/1445] Add support for D3D9Ex --- thin3d/thin3d.h | 4 +++- thin3d/thin3d_d3d9.cpp | 36 +++++++++++++++++++++++------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 1025bb9dfe..e6d1397b48 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -330,5 +330,7 @@ Thin3DContext *T3DCreateGLContext(); #ifdef _WIN32 struct IDirect3DDevice9; struct IDirect3D9; -Thin3DContext *T3DCreateDX9Context(IDirect3D9 *d3d, int adapterId, IDirect3DDevice9 *device); +struct IDirect3DDevice9Ex; +struct IDirect3D9Ex; +Thin3DContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx); #endif diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 30b6dc2e3b..b787fd407b 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -226,9 +226,9 @@ private: class Thin3DDX9Texture : public Thin3DTexture { public: - Thin3DDX9Texture(LPDIRECT3DDEVICE9 device) : device_(device), type_(T3DTextureType::UNKNOWN), fmt_(D3DFMT_UNKNOWN), tex_(NULL), volTex_(NULL), cubeTex_(NULL) { + Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, LPDIRECT3DDEVICE9EX deviceEx) : device_(device), deviceEx_(deviceEx), type_(T3DTextureType::UNKNOWN), fmt_(D3DFMT_UNKNOWN), tex_(NULL), volTex_(NULL), cubeTex_(NULL) { } - Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels); + Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, LPDIRECT3DDEVICE9EX deviceEx, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels); ~Thin3DDX9Texture(); bool Create(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override; void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override; @@ -238,6 +238,7 @@ public: private: LPDIRECT3DDEVICE9 device_; + LPDIRECT3DDEVICE9EX deviceEx_; T3DTextureType type_; D3DFORMAT fmt_; LPDIRECT3DTEXTURE9 tex_; @@ -255,8 +256,8 @@ D3DFORMAT FormatToD3D(T3DImageFormat fmt) { } } -Thin3DDX9Texture::Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) - : device_(device), type_(type), tex_(NULL), volTex_(NULL), cubeTex_(NULL) { +Thin3DDX9Texture::Thin3DDX9Texture(LPDIRECT3DDEVICE9 device, LPDIRECT3DDEVICE9EX deviceEx, T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) + : device_(device), deviceEx_(deviceEx), type_(type), tex_(NULL), volTex_(NULL), cubeTex_(NULL) { Create(type, format, width, height, depth, mipLevels); } @@ -280,16 +281,23 @@ bool Thin3DDX9Texture::Create(T3DTextureType type, T3DImageFormat format, int wi tex_ = NULL; fmt_ = FormatToD3D(format); HRESULT hr = E_FAIL; + + D3DPOOL pool = D3DPOOL_MANAGED; + int usage = 0; + if (deviceEx_ != nullptr) { + pool = D3DPOOL_DEFAULT; + usage = D3DUSAGE_DYNAMIC; + } switch (type) { case LINEAR1D: case LINEAR2D: - hr = device_->CreateTexture(width, height, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &tex_, NULL); + hr = device_->CreateTexture(width, height, mipLevels, usage, fmt_, pool, &tex_, NULL); break; case LINEAR3D: - hr = device_->CreateVolumeTexture(width, height, depth, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &volTex_, NULL); + hr = device_->CreateVolumeTexture(width, height, depth, mipLevels, usage, fmt_, pool, &volTex_, NULL); break; case CUBE: - hr = device_->CreateCubeTexture(width, mipLevels, 0, fmt_, D3DPOOL_MANAGED, &cubeTex_, NULL); + hr = device_->CreateCubeTexture(width, mipLevels, usage, fmt_, pool, &cubeTex_, NULL); break; } if (FAILED(hr)) { @@ -375,7 +383,7 @@ void Thin3DDX9Texture::SetToSampler(LPDIRECT3DDEVICE9 device, int sampler) { class Thin3DDX9Context : public Thin3DContext { public: - Thin3DDX9Context(LPDIRECT3D9 d3d, int adapterId, LPDIRECT3DDEVICE9 device); + Thin3DDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx); ~Thin3DDX9Context(); Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare); @@ -424,14 +432,16 @@ public: private: LPDIRECT3D9 d3d_; + LPDIRECT3D9EX d3dEx_; LPDIRECT3DDEVICE9 device_; + LPDIRECT3DDEVICE9EX deviceEx_; int adapterId_; D3DADAPTER_IDENTIFIER9 identifier_; D3DCAPS9 caps_; char shadeLangVersion_[64]; }; -Thin3DDX9Context::Thin3DDX9Context(LPDIRECT3D9 d3d, int adapterId, LPDIRECT3DDEVICE9 device) : d3d_(d3d), adapterId_(adapterId), device_(device) { +Thin3DDX9Context::Thin3DDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx) : d3d_(d3d), d3dEx_(d3dEx), adapterId_(adapterId), device_(device), deviceEx_(deviceEx) { CreatePresets(); d3d->GetAdapterIdentifier(adapterId, 0, &identifier_); if (!FAILED(device->GetDeviceCaps(&caps_))) { @@ -501,12 +511,12 @@ Thin3DBlendState *Thin3DDX9Context::CreateBlendState(const T3DBlendStateDesc &de } Thin3DTexture *Thin3DDX9Context::CreateTexture() { - Thin3DDX9Texture *tex = new Thin3DDX9Texture(device_); + Thin3DDX9Texture *tex = new Thin3DDX9Texture(device_, deviceEx_); return tex; } Thin3DTexture *Thin3DDX9Context::CreateTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) { - Thin3DDX9Texture *tex = new Thin3DDX9Texture(device_, type, format, width, height, depth, mipLevels); + Thin3DDX9Texture *tex = new Thin3DDX9Texture(device_, deviceEx_, type, format, width, height, depth, mipLevels); return tex; } @@ -722,11 +732,11 @@ void Thin3DDX9Shader::SetMatrix4x4(LPDIRECT3DDEVICE9 device, const char *name, c } } -Thin3DContext *T3DCreateDX9Context(LPDIRECT3D9 d3d, int adapterId, LPDIRECT3DDEVICE9 device) { +Thin3DContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx) { int d3dx_ver = LoadD3DX9Dynamic(); if (!d3dx_ver) { ELOG("Failed to load D3DX9!"); return NULL; } - return new Thin3DDX9Context(d3d, adapterId, device); + return new Thin3DDX9Context(d3d, d3dEx, adapterId, device, deviceEx); } From 6ee862b564bca639659a231937e02dfec0774475 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 14 Sep 2014 00:13:24 +0200 Subject: [PATCH 1264/1445] Increase some buffer sizes --- base/PCMain.cpp | 2 +- file/zip_read.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index cda16b7877..13983b8070 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -542,7 +542,7 @@ int main(int argc, char *argv[]) { PathAppend(path, (app_name + "\\").c_str()); #else // Mac / Linux - char path[512]; + char path[2048]; const char *the_path = getenv("HOME"); if (!the_path) { struct passwd* pwd = getpwuid(getuid()); diff --git a/file/zip_read.cpp b/file/zip_read.cpp index ae12474798..228cfa79f2 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -246,7 +246,8 @@ bool ZipAssetReader::GetFileInfo(const char *path, FileInfo *info) { #endif uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { - char new_path[1024] = {0}; + char new_path[2048]; + new_path[0] = '\0'; // Check if it already contains the path if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { } @@ -259,7 +260,8 @@ uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { bool DirectoryAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) { - char new_path[1024] = {0}; + char new_path[2048]; + new_path[0] = '\0'; // Check if it already contains the path if (strlen(path) > strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { } @@ -284,7 +286,8 @@ bool DirectoryAssetReader::GetFileListing(const char *path, std::vector strlen(path_) && 0 == memcmp(path, path_, strlen(path_))) { } From 167f2a8a2c106bc38201c70ed74cf73dba94517f Mon Sep 17 00:00:00 2001 From: The Dax Date: Sun, 14 Sep 2014 19:51:13 -0400 Subject: [PATCH 1265/1445] Add functionality to the MessagePopupScreen class. It can more or less replace PromptScreen in PPSSPP. --- ui/ui_screen.cpp | 15 ++++++++++++++- ui/ui_screen.h | 8 +++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 66f6eec6bc..c13ebf5733 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -206,7 +206,20 @@ void PopupScreen::CreateViews() { } void MessagePopupScreen::CreatePopupContents(UI::ViewGroup *parent) { - parent->Add(new UI::TextView(message_)); + std::vector messageLines; + SplitString(message_, '\n', messageLines); + for (const auto& lineOfText : messageLines) + parent->Add(new UI::TextView(lineOfText, ALIGN_LEFT | ALIGN_VCENTER, false)); +} + +void MessagePopupScreen::OnCompleted(DialogResult result) { + if (result == DR_OK) { + if (callback_) + callback_(true); + } else { + if (callback_) + callback_(false); + } } UI::EventReturn PopupScreen::OnOK(UI::EventParams &e) { diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 85cc5f7863..42362ba08a 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -110,8 +110,9 @@ private: class MessagePopupScreen : public PopupScreen { public: - MessagePopupScreen(std::string title, std::string message, std::string button1, std::string button2, std::function callback) : PopupScreen(title) {} - UI::Event OnChoice; + MessagePopupScreen(std::string title, std::string message, std::string button1, std::string button2, std::function callback) + : PopupScreen(title, button1, button2), message_(message), callback_(callback) {} + UI::Event OnChange; protected: virtual bool FillVertical() const override { return false; } @@ -119,8 +120,9 @@ protected: virtual void CreatePopupContents(UI::ViewGroup *parent) override; private: + void OnCompleted(DialogResult result) override; std::string message_; - std::function callback_; + std::function callback_; }; // TODO: Need a way to translate OK and Cancel From 03ed11fa0fc8d893b10cf370d1d7ac71ca75d3bc Mon Sep 17 00:00:00 2001 From: The Dax Date: Tue, 16 Sep 2014 03:57:39 -0400 Subject: [PATCH 1266/1445] Change OnChange back to OnChoice. Not like it's used anyway, but it doesn't hurt. --- ui/ui_screen.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 42362ba08a..edabf4d262 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -112,7 +112,7 @@ class MessagePopupScreen : public PopupScreen { public: MessagePopupScreen(std::string title, std::string message, std::string button1, std::string button2, std::function callback) : PopupScreen(title, button1, button2), message_(message), callback_(callback) {} - UI::Event OnChange; + UI::Event OnChoice; protected: virtual bool FillVertical() const override { return false; } From 66c585e9317e53dd3cf45672f496b010acd19772 Mon Sep 17 00:00:00 2001 From: beaumanvienna Date: Mon, 22 Sep 2014 20:08:02 +0200 Subject: [PATCH 1267/1445] dual head support (SDL_VIDEO_FULLSCREEN_HEAD) for Qt and SDL2 --- base/PCMain.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ base/QtMain.cpp | 66 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 140 insertions(+), 2 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 13983b8070..4c53df1b20 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -188,6 +188,72 @@ void EGL_Close() { } #endif +//Dual Head Support +bool verifyIsNumber(char * string) +{ + int x = 0; + int len; + + if (string == NULL) + { + return false; + } + + len = strlen(string); + + while(x < len) { + if(!isdigit(*(string+x))) + return false; + ++x; + } + return true; +} + +int getNumVideoDisplays(void) +{ + +#ifdef USESDL2 + #warning "sdl2 code" + return SDL_GetNumVideoDisplays(); +#else + #warning "sdl1.2 code" + return 0; +#endif + +} + +//Dual Head Support +int getDisplayNumber(void) +{ + int displayNumber; + long tempValue = 0; + char * displayNumberStr; + + // setup default display + displayNumber = 0; + + //get environment + displayNumberStr=getenv("SDL_VIDEO_FULLSCREEN_HEAD"); + + // check if a valid number was found + if(verifyIsNumber(displayNumberStr)) + { + // a valid number was found + + //convert to integer + tempValue = atoi(displayNumberStr); + + //check if larger equal zero and less display numbers + if ((tempValue >=0) && (tempValue < getNumVideoDisplays())) + { + // check passed + displayNumber = tempValue; + } + } + + return displayNumber; +} + // Simple implementations of System functions @@ -501,7 +567,17 @@ int main(int argc, char *argv[]) { dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; +#ifdef USESDL2 +#warning "sdl2 code" + //Dual Head Support + g_Screen = SDL_CreateWindow((app_name_nice + " " + version_string).c_str(), \ + SDL_WINDOWPOS_UNDEFINED_DISPLAY(getDisplayNumber()), \ + SDL_WINDOWPOS_UNDEFINED, pixel_xres, pixel_yres, mode); + +#else + #warning "sdl1.2 code" g_Screen = SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode); +#endif if (g_Screen == NULL) { fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError()); SDL_Quit(); diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 3b475bd1b2..a4359ae588 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -32,10 +32,72 @@ #include "QtMain.h" #include "math/math_util.h" -#include +#include InputState* input_state; +//Dual Head Support +bool verifyIsNumber(char * string) +{ + int x = 0; + int len; + + if (string == NULL) + { + return false; + } + + len = strlen(string); + + while(x < len) { + if(!isdigit(*(string+x))) + return false; + ++x; + } + return true; +} + +int getNumVideoDisplays(void) +{ + + QDesktopWidget *desktop = QApplication::desktop(); + return desktop->screenCount(); + +} + +//Dual Head Support +int getDisplayNumber(void) +{ + + int displayNumber; + long tempValue = 0; + char * displayNumberStr; + + // setup default display + displayNumber = 0; + + //get environment + displayNumberStr=getenv("SDL_VIDEO_FULLSCREEN_HEAD"); + + // check if a valid number was found + if(verifyIsNumber(displayNumberStr)) + { + // a valid number was found + + //convert to integer + tempValue = atoi(displayNumberStr); + + //check if larger equal zero and less display numbers + if ((tempValue >=0) && (tempValue < getNumVideoDisplays())) + { + // check passed + displayNumber = tempValue; + } + } + + return displayNumber; +} + #ifdef QT_HAS_SDL extern void mixaudio(void *userdata, Uint8 *stream, int len) { NativeMix((short *)stream, len / 4); @@ -205,7 +267,7 @@ int main(int argc, char *argv[]) savegame_dir += "/"; assets_dir += "/"; NativeInit(argc, (const char **)argv, savegame_dir.c_str(), assets_dir.c_str(), "BADCOFFEE"); - + int ret = mainInternal(a); #ifndef MOBILE_DEVICE From 3a918141ef10a02d40a24e2fd15c87336a6a8c4c Mon Sep 17 00:00:00 2001 From: beaumanvienna Date: Tue, 23 Sep 2014 22:29:02 +0200 Subject: [PATCH 1268/1445] dual head support for Qt reworked / --fullscreen for Qt / fullscreen top most --- base/QtMain.cpp | 70 +++++++------------------------------------------ 1 file changed, 9 insertions(+), 61 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index a4359ae588..ba13725239 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -36,67 +36,8 @@ InputState* input_state; -//Dual Head Support -bool verifyIsNumber(char * string) -{ - int x = 0; - int len; - - if (string == NULL) - { - return false; - } - - len = strlen(string); - - while(x < len) { - if(!isdigit(*(string+x))) - return false; - ++x; - } - return true; -} - -int getNumVideoDisplays(void) -{ - - QDesktopWidget *desktop = QApplication::desktop(); - return desktop->screenCount(); - -} - -//Dual Head Support -int getDisplayNumber(void) -{ - - int displayNumber; - long tempValue = 0; - char * displayNumberStr; - - // setup default display - displayNumber = 0; - - //get environment - displayNumberStr=getenv("SDL_VIDEO_FULLSCREEN_HEAD"); - - // check if a valid number was found - if(verifyIsNumber(displayNumberStr)) - { - // a valid number was found - - //convert to integer - tempValue = atoi(displayNumberStr); - - //check if larger equal zero and less display numbers - if ((tempValue >=0) && (tempValue < getNumVideoDisplays())) - { - // check passed - displayNumber = tempValue; - } - } - - return displayNumber; -} +// "--fullscreen" from command line interface +bool fullscreenCLI; #ifdef QT_HAS_SDL extern void mixaudio(void *userdata, Uint8 *stream, int len) { @@ -266,6 +207,13 @@ int main(int argc, char *argv[]) #endif savegame_dir += "/"; assets_dir += "/"; + + fullscreenCLI=false; + for (int i = 1; i < argc; i++) + { + if (!strcmp(argv[i],"--fullscreen")) + fullscreenCLI=true; + } NativeInit(argc, (const char **)argv, savegame_dir.c_str(), assets_dir.c_str(), "BADCOFFEE"); int ret = mainInternal(a); From e11f403a8ed89f165c05636a0d33c6e9ff352a58 Mon Sep 17 00:00:00 2001 From: beaumanvienna Date: Tue, 23 Sep 2014 22:30:50 +0200 Subject: [PATCH 1269/1445] dual head support for Qt reworked / --fullscreen for Qt / fullscreen top most --- base/QtMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index ba13725239..bf71d5a58a 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -32,7 +32,7 @@ #include "QtMain.h" #include "math/math_util.h" -#include +#include InputState* input_state; From 48856951a778fdfaebc5352366838fc64648459c Mon Sep 17 00:00:00 2001 From: beaumanvienna Date: Wed, 24 Sep 2014 23:23:25 +0200 Subject: [PATCH 1270/1445] amendments for: global variable 'fullscreenCLI'/move on top timer/Qt fullscreen code --- base/NativeApp.h | 2 +- base/QtMain.cpp | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/base/NativeApp.h b/base/NativeApp.h index 19811ca731..4b6c6f6e28 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -33,7 +33,7 @@ bool NativeIsAtTopLevel(); // The very first function to be called after NativeGetAppInfo. Even NativeMix is not called // before this, although it may be called at any point in time afterwards (on any thread!) // This functions must NOT call OpenGL. Main thread. -void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *external_directory, const char *installID); +void NativeInit(int argc, const char *argv[], const char *savegame_directory, const char *external_directory, const char *installID, bool fs); // Runs after NativeInit() at some point. May (and probably should) call OpenGL. // Should not initialize anything screen-size-dependent - do that in NativeResized. diff --git a/base/QtMain.cpp b/base/QtMain.cpp index bf71d5a58a..992e67f1ae 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -36,9 +36,6 @@ InputState* input_state; -// "--fullscreen" from command line interface -bool fullscreenCLI; - #ifdef QT_HAS_SDL extern void mixaudio(void *userdata, Uint8 *stream, int len) { NativeMix((short *)stream, len / 4); @@ -208,13 +205,13 @@ int main(int argc, char *argv[]) savegame_dir += "/"; assets_dir += "/"; - fullscreenCLI=false; + bool fullscreenCLI=false; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) fullscreenCLI=true; } - NativeInit(argc, (const char **)argv, savegame_dir.c_str(), assets_dir.c_str(), "BADCOFFEE"); + NativeInit(argc, (const char **)argv, savegame_dir.c_str(), assets_dir.c_str(), "BADCOFFEE",fullscreenCLI); int ret = mainInternal(a); From d54daa2ea5faea429e6ec2ecc850e5b9b852ea93 Mon Sep 17 00:00:00 2001 From: beaumanvienna Date: Thu, 25 Sep 2014 21:59:45 +0200 Subject: [PATCH 1271/1445] amendement for sdl version after Qt changes --- base/PCMain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 4c53df1b20..86b4c66392 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -631,9 +631,9 @@ int main(int argc, char *argv[]) { #endif #ifdef _WIN32 - NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE",false); #else - NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); + NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE",false); #endif pixel_in_dps = (float)pixel_xres / dp_xres; From c5bb2c7b23e9fbfdb53650768042b90fec689fa8 Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Fri, 26 Sep 2014 18:47:19 -0500 Subject: [PATCH 1272/1445] base: Allow building when not using X11 on a FBDEV based system * Currently building base will fail on non X11 based systems due to inclusion of X11 headers and some calls to X11 functions. * Portions of the code currently attempts to avoid calling X11 functions when fbdev is used. This patch adds additional checks to avoid X11 calls. Signed-off-by: Franklin S Cooper Jr --- base/PCMain.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 13983b8070..81e939cbae 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -59,16 +59,24 @@ static int g_DesktopHeight = 0; #if defined(USING_EGL) #include "EGL/egl.h" + +#if !defined(USING_FBDEV) #include #include +#endif + #include "SDL_syswm.h" #include "math.h" -static EGLDisplay g_eglDisplay = NULL; -static EGLContext g_eglContext = NULL; -static EGLSurface g_eglSurface = NULL; -static Display* g_Display = NULL; -static NativeWindowType g_Window = (NativeWindowType)NULL; +static EGLDisplay g_eglDisplay = NULL; +static EGLContext g_eglContext = NULL; +static EGLSurface g_eglSurface = NULL; +#ifdef USING_FBDEV +static EGLNativeDisplayType g_Display = NULL; +#else +static Display* g_Display = NULL; +#endif +static NativeWindowType g_Window = (NativeWindowType)NULL; int8_t CheckEGLErrors(const std::string& file, uint16_t line) { EGLenum error; @@ -144,13 +152,15 @@ int8_t EGL_Init() { g_eglContext = eglCreateContext(g_eglDisplay, g_eglConfig, NULL, attributes ); if (g_eglContext == EGL_NO_CONTEXT) EGL_ERROR("Unable to create GLES context!", true); - // Get the SDL window handle +#if !defined(USING_FBDEV) + //Get the SDL window handle SDL_SysWMinfo sysInfo; //Will hold our Window information SDL_VERSION(&sysInfo.version); //Set SDL version if (SDL_GetWMInfo(&sysInfo) <= 0) { printf("EGL ERROR: Unable to get SDL window handle: %s\n", SDL_GetError()); return 1; } +#endif #ifdef USING_FBDEV g_Window = (NativeWindowType)NULL; @@ -180,7 +190,9 @@ void EGL_Close() { g_eglDisplay = NULL; } if (g_Display != NULL) { +#if !defined(USING_FBDEV) XCloseDisplay(g_Display); +#endif g_Display = NULL; } g_eglSurface = NULL; From d3743d0f39554d68f1bb585e2b51892e2adbbdba Mon Sep 17 00:00:00 2001 From: Sacha Date: Thu, 9 Oct 2014 04:58:47 +1000 Subject: [PATCH 1273/1445] Fix pause menu on Blackberry. --- base/BlackberryMain.cpp | 2 +- base/NKCodeFromBlackberry.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 338639baa6..0ce861247b 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -279,7 +279,7 @@ void BlackberryMain::runMain() { break; case NAVIGATOR_BACK: case NAVIGATOR_SWIPE_DOWN: - NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE, KEY_DOWN)); + NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_BACK, KEY_DOWN)); break; case NAVIGATOR_EXIT: return; diff --git a/base/NKCodeFromBlackberry.h b/base/NKCodeFromBlackberry.h index 2b73c6a8d4..d32f39bd9e 100644 --- a/base/NKCodeFromBlackberry.h +++ b/base/NKCodeFromBlackberry.h @@ -11,7 +11,7 @@ static const std::map KeyMapPadBlackberrytoNative = InitConstMap Date: Wed, 15 Oct 2014 10:12:16 +0800 Subject: [PATCH 1274/1445] Compatibility ndk r9d armeabi-v7a-hard APP_ABI building. --- Android.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index 9a2b6b387f..d9d0e595e2 100644 --- a/Android.mk +++ b/Android.mk @@ -109,7 +109,8 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext $(LOCAL_PATH)/ext/libzip #Portable native and separate code on android in future is easy you needs add files #by ($(target_arch_ABI),arquitecture (armeabi-v7a , armeabi , x86 , MIPS) -ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) +# ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) +ifeq ($(findstring armeabi-v7a,$(TARGET_ARCH_ABI)),armeabi-v7a) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI_V7A LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ math/fast/fast_matrix_neon.S.neon \ From 428f338f28a2909a444e77888ccfce4e1eb55f47 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 21 Oct 2014 00:07:27 +0200 Subject: [PATCH 1275/1445] Delete commented out code --- file/path.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/file/path.h b/file/path.h index 0acd20c69d..f29492960e 100644 --- a/file/path.h +++ b/file/path.h @@ -42,13 +42,6 @@ public: str.insert(0, 1, '~'); } #endif - /* -#ifdef ANDROID - if (!memcmp(str.c_str(), g_Config.memCardDirectory.c_str(), g_Config.memCardDirectory.size())) - { - str = str.substr(g_Config.memCardDirectory.size()); - } -#endif*/ return str; } From cfc18556207bd28e0caa334a730c7d95dbf8cdf7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 5 Nov 2014 08:07:33 -0800 Subject: [PATCH 1276/1445] Correctly append to a fixed buffer while logging. --- base/logging.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/logging.h b/base/logging.h index 4b11631f64..e3e968af6b 100644 --- a/base/logging.h +++ b/base/logging.h @@ -83,15 +83,15 @@ void OutputDebugStringUTF8(const char *p); #ifdef _WIN32 #ifdef _DEBUG -#define DLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "D: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "D: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define DLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "D: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "D: " __VA_ARGS__); if (p > temp + 450) p = temp + 450; p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} #else #define DLOG(...) #endif -#define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "I: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} -#define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "W: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} -#define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "E: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} -#define FLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "F: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "F: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp); Crash();} +#define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "I: " __VA_ARGS__); if (p > temp + 450) p = temp + 450; p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "W: " __VA_ARGS__); if (p > temp + 450) p = temp + 450; p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "E: " __VA_ARGS__); if (p > temp + 450) p = temp + 450; p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define FLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "F: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "F: " __VA_ARGS__); if (p > temp + 450) p = temp + 450; p += sprintf(p, "\n"); OutputDebugStringUTF8(temp); Crash();} // TODO: Win32 version using OutputDebugString #else From dea2ae0950406358b3029e3c9190a2aeb464ff8d Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 14 Nov 2014 01:38:50 +1000 Subject: [PATCH 1277/1445] SDL: Support low resolution displays by automatically using fullscreen when window is too large. --- base/PCMain.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 51ebea73ec..e7d56e7ea0 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -477,6 +477,11 @@ int main(int argc, char *argv[]) { portrait = true; } + // Is resolution is too low to run windowed + if (g_DesktopWidth < 480 * 2 && g_desktopHeight < 272 * 2) { + mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; + } + if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) { pixel_xres = g_DesktopWidth; pixel_yres = g_DesktopHeight; From 1e847f977d80ff427ec889eb03e0d8c4e56f29ee Mon Sep 17 00:00:00 2001 From: Sacha Date: Fri, 14 Nov 2014 03:13:01 +1000 Subject: [PATCH 1278/1445] Typo fix. --- base/PCMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index e7d56e7ea0..ad8852feae 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -478,7 +478,7 @@ int main(int argc, char *argv[]) { } // Is resolution is too low to run windowed - if (g_DesktopWidth < 480 * 2 && g_desktopHeight < 272 * 2) { + if (g_DesktopWidth < 480 * 2 && g_DesktopHeight < 272 * 2) { mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; } From cedd5b29971199f25af6f76e25819e0efd0186a7 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 16 Nov 2014 16:44:07 +0100 Subject: [PATCH 1279/1445] Add OnTextChanged event to TextEdit, minor other stuff --- ui/view.cpp | 34 +++++++++++++++++++++++----------- ui/view.h | 2 ++ ui/viewgroup.h | 2 +- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 58132637ae..a70985ba83 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -613,16 +613,6 @@ void TextEdit::Draw(UIContext &dc) { float textX = bounds_.x; float w, h; - // Hack to find the caret position. Might want to find a better way... - dc.MeasureTextCount(dc.theme->uiFont, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT); - float caretX = w; - - if (caretX > bounds_.w) { - // Scroll text to the left if the caret won't fit. Not ideal but looks better than not scrolling it. - textX -= caretX - bounds_.w; - } - - caretX += textX; Bounds textBounds = bounds_; textBounds.x = textX; @@ -635,7 +625,18 @@ void TextEdit::Draw(UIContext &dc) { dc.DrawTextRect(text_.c_str(), textBounds, 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_LEFT); } - dc.FillRect(UI::Drawable(0xFFFFFFFF), Bounds(caretX - 1, bounds_.y + 2, 3, bounds_.h - 4)); + if (HasFocus()) { + // Hack to find the caret position. Might want to find a better way... + dc.MeasureTextCount(dc.theme->uiFont, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT); + float caretX = w; + caretX += textX; + + if (caretX > bounds_.w) { + // Scroll text to the left if the caret won't fit. Not ideal but looks better than not scrolling it. + textX -= caretX - bounds_.w; + } + dc.FillRect(UI::Drawable(0xFFFFFFFF), Bounds(caretX - 1, bounds_.y + 2, 3, bounds_.h - 4)); + } dc.PopScissor(); } @@ -669,6 +670,7 @@ void TextEdit::Touch(const TouchInput &touch) { void TextEdit::Key(const KeyInput &input) { if (!HasFocus()) return; + bool textChanged = false; // Process navigation keys. These aren't chars. if (input.flags & KEY_DOWN) { switch (input.keyCode) { @@ -696,6 +698,7 @@ void TextEdit::Key(const KeyInput &input) { u8_inc(text_.c_str(), &endCaret); undo_ = text_; text_.erase(text_.begin() + caret_, text_.begin() + endCaret); + textChanged = true; } break; case NKCODE_DEL: @@ -705,6 +708,7 @@ void TextEdit::Key(const KeyInput &input) { undo_ = text_; text_.erase(text_.begin() + begCaret, text_.begin() + caret_); caret_--; + textChanged = true; } break; } @@ -737,6 +741,7 @@ void TextEdit::Key(const KeyInput &input) { clipText = clipText.substr(0, end); } InsertAtCaret(clipText.c_str()); + textChanged = true; } } break; @@ -773,9 +778,16 @@ void TextEdit::Key(const KeyInput &input) { if (strlen(buf) + text_.size() < maxLen_) { undo_ = text_; InsertAtCaret(buf); + textChanged = true; } } } + + if (textChanged) { + UI::EventParams e; + e.v = this; + OnTextChange.Trigger(e); + } } void TextEdit::InsertAtCaret(const char *text) { diff --git a/ui/view.h b/ui/view.h index 2289e08d07..74949ae1b7 100644 --- a/ui/view.h +++ b/ui/view.h @@ -680,6 +680,8 @@ public: virtual void Key(const KeyInput &key) override; virtual void Touch(const TouchInput &touch) override; + Event OnTextChange; + private: void InsertAtCaret(const char *text); diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 4406313117..3ebcbd03ae 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -64,7 +64,7 @@ public: virtual void Clear(); View *GetViewByIndex(int index) { return views_[index]; } - + int GetNumSubviews() const { return (int)views_.size(); } void SetHasDropShadow(bool has) { hasDropShadow_ = has; } void Lock() { modifyLock_.lock(); } From ffee75fe5da90812b3c0f3ce94913ea4092088ed Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 16 Nov 2014 16:44:32 +0100 Subject: [PATCH 1280/1445] Warning fixes --- base/buffer.cpp | 6 +++--- file/fd_util.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index 6516528e9b..6de2ea48a8 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -139,7 +139,7 @@ bool Buffer::FlushToFile(const char *filename) { bool Buffer::FlushSocket(uintptr_t sock) { for (size_t pos = 0, end = data_.size(); pos < end; ) { - int sent = send(sock, &data_[pos], end - pos, 0); + int sent = send(sock, &data_[pos], (int)(end - pos), 0); if (sent < 0) { ELOG("FlushSocket failed"); return false; @@ -194,7 +194,7 @@ int Buffer::Read(int fd, size_t sz) { char buf[1024]; int retval; size_t received = 0; - while ((retval = recv(fd, buf, std::min(sz, sizeof(buf)), 0)) > 0) { + while ((retval = recv(fd, buf, (int)std::min(sz, sizeof(buf)), 0)) > 0) { if (retval < 0) { return retval; } @@ -205,7 +205,7 @@ int Buffer::Read(int fd, size_t sz) { if (sz == 0) return 0; } - return received; + return (int)received; } void Buffer::PeekAll(std::string *dest) { diff --git a/file/fd_util.cpp b/file/fd_util.cpp index babe09f970..8326fecf94 100644 --- a/file/fd_util.cpp +++ b/file/fd_util.cpp @@ -53,8 +53,8 @@ ssize_t WriteLine(int fd, const char *vptr, size_t n) { size_t nleft = n; while (nleft > 0) { - ssize_t nwritten; - if ((nwritten = (ssize_t)write(fd, buffer, nleft)) <= 0) { + int nwritten; + if ((nwritten = (int)write(fd, buffer, nleft)) <= 0) { if (errno == EINTR) nwritten = 0; else From 62f7b51536719f07c2cac71170b6ebaa2af2f247 Mon Sep 17 00:00:00 2001 From: xsacha Date: Tue, 18 Nov 2014 13:34:49 +1000 Subject: [PATCH 1281/1445] Remove SDL1 code hiding in GLES2 paths. --- base/PCMain.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index ad8852feae..0d459d53ca 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -133,7 +133,11 @@ int8_t EGL_Init() { #endif EGL_DEPTH_SIZE, 16, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, +#ifdef USING_GLES2 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#else + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, +#endif EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, 0, #ifdef MAEMO @@ -153,10 +157,6 @@ int8_t EGL_Init() { //Get the SDL window handle SDL_SysWMinfo sysInfo; //Will hold our Window information SDL_VERSION(&sysInfo.version); //Set SDL version - if (SDL_GetWMInfo(&sysInfo) <= 0) { - printf("EGL ERROR: Unable to get SDL window handle: %s\n", SDL_GetError()); - return 1; - } #endif #ifdef USING_FBDEV @@ -438,7 +438,7 @@ int main(int argc, char *argv[]) { Uint32 mode; #ifdef USING_GLES2 - mode = SDL_SWSURFACE | SDL_FULLSCREEN; + mode = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN; #else mode = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; #endif From b2ff5bc9f3e5d42313d1465fff28f5e21851180f Mon Sep 17 00:00:00 2001 From: Sacha Date: Tue, 18 Nov 2014 16:17:56 +1000 Subject: [PATCH 1282/1445] Fix backtrace ifdef. Failed on Linux systems that used uclibc. It is actually only available for glibc. --- base/backtrace.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/base/backtrace.cpp b/base/backtrace.cpp index 08cfc4ddd6..6c22f209ff 100644 --- a/base/backtrace.cpp +++ b/base/backtrace.cpp @@ -1,8 +1,6 @@ #include "base/backtrace.h" -// The mac check doesn't seem to work right. -#if (!defined(ANDROID) && defined(__linux__)) || (defined(__APPLE__) && (defined(_M_IX86) || defined(_M_X64))) - +#if defined(__GLIBC__) && !defined(__UCLIBC__) #include #include From 92be7b0b1bb73b01b4322d787b9c54d03ed7c270 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Nov 2014 11:01:51 -0800 Subject: [PATCH 1283/1445] Fix shutdown crash. Both glGetShaderiv and glGetShaderInfoLog do not set their outputs on failure, we need to initialize them. On app shutdown (e.g. via the back button), we end up in display shutdown which travels through GLLost which ends up trying to rebuild the shaders. This causes an ANR. --- thin3d/thin3d_gl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 2a1f1acf33..08516fb19e 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -186,12 +186,12 @@ bool Thin3DGLShader::Compile(const char *source) { glShaderSource(shader_, 1, &source, 0); glCompileShader(shader_); - GLint success; + GLint success = 0; glGetShaderiv(shader_, GL_COMPILE_STATUS, &success); if (!success) { #define MAX_INFO_LOG_SIZE 2048 GLchar infoLog[MAX_INFO_LOG_SIZE]; - GLsizei len; + GLsizei len = 0; glGetShaderInfoLog(shader_, MAX_INFO_LOG_SIZE, &len, infoLog); infoLog[len] = '\0'; glDeleteShader(shader_); @@ -765,4 +765,4 @@ void Thin3DGLVertexFormat::Unapply() { glDisableVertexAttribArray(i); } } -} \ No newline at end of file +} From 73d5ad3b5c937afceb95569dd55ce8603da17357 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Nov 2014 16:12:54 -0800 Subject: [PATCH 1284/1445] Make the HTTP client more generic. This way we can send other headers and use HEAD requests. --- base/buffer.cpp | 5 + base/buffer.h | 1 + net/http_client.cpp | 253 +++++++++++++++++++++++++------------------- net/http_client.h | 8 ++ 4 files changed, 158 insertions(+), 109 deletions(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index 6de2ea48a8..0c2cb830d5 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -57,11 +57,16 @@ void Buffer::Take(size_t length, std::string *dest) { } dest->resize(length); if (length > 0) { + Take(length, &(*dest)[0]); memcpy(&(*dest)[0], &data_[0], length); data_.erase(data_.begin(), data_.begin() + length); } } +void Buffer::Take(size_t length, char *dest) { + memcpy(dest, &data_[0], length); +} + int Buffer::TakeLineCRLF(std::string *dest) { int after_next_line = OffsetToAfterNextCRLF(); if (after_next_line < 0) diff --git a/base/buffer.h b/base/buffer.h index 73fbe898fb..6021c76699 100644 --- a/base/buffer.h +++ b/base/buffer.h @@ -38,6 +38,7 @@ class Buffer { // Takers void Take(size_t length, std::string *dest); + void Take(size_t length, char *dest); void TakeAll(std::string *dest) { Take(size(), dest); } // On failure, return value < 0 and *dest is unchanged. // Strips off the actual CRLF from the result. diff --git a/net/http_client.cpp b/net/http_client.cpp index 59b6257529..88f18c5d24 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -105,17 +105,18 @@ void Connection::Disconnect() { namespace http { -Client::Client() { +// TODO: do something sane here +#define USERAGENT "NATIVEAPP 1.0" +Client::Client() { + httpVersion_ = "1.1"; + userAgent_ = USERAGENT; } Client::~Client() { Disconnect(); } -// TODO: do something sane here -#define USERAGENT "NATIVEAPP 1.0" - void DeChunk(Buffer *inbuffer, Buffer *outbuffer, int contentLength, float *progress) { int dechunkedBytes = 0; @@ -144,118 +145,25 @@ void DeChunk(Buffer *inbuffer, Buffer *outbuffer, int contentLength, float *prog } int Client::GET(const char *resource, Buffer *output, float *progress) { - if (progress) { - *progress = 0.01f; - } - - Buffer buffer; - const char *tpl = - "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" - "User-Agent: " USERAGENT "\r\n" + const char *otherHeaders = "Accept: */*\r\n" - "Accept-Encoding: gzip\r\n" - "Connection: close\r\n" - "\r\n"; - - buffer.Printf(tpl, resource, host_.c_str()); - bool flushed = buffer.FlushSocket(sock()); - if (!flushed) { - return -1; // TODO error code. + "Accept-Encoding: gzip\r\n"; + int err = SendRequest("GET", resource, otherHeaders, progress); + if (err < 0) { + return err; } Buffer readbuf; - - // Snarf all the data we can into RAM. A little unsafe but hey. - if (readbuf.Read(sock(), 4096) < 0) { - ELOG("Failed to read HTTP headers :("); - return -1; + std::vector responseHeaders; + int code = ReadResponseHeaders(&readbuf, responseHeaders, progress); + if (code < 0) { + return code; } - // Grab the first header line that contains the http code. - - // Skip the header. TODO: read HTTP code and file size so we can make progress bars. - - std::string line; - readbuf.TakeLineCRLF(&line); - - int code; - size_t code_pos = line.find(' '); - if (code_pos != line.npos) { - code_pos = line.find_first_not_of(' ', code_pos); + err = ReadResponseEntity(&readbuf, responseHeaders, output, progress); + if (err < 0) { + return err; } - - if (code_pos != line.npos) { - code = atoi(&line[code_pos]); - } else { - return -1; - } - - bool gzip = false; - bool chunked = false; - int contentLength = 0; - while (true) { - int sz = readbuf.TakeLineCRLF(&line); - if (!sz) - break; - // TODO: Case folding. - if (startsWith(line, "Content-Length:")) { - size_t size_pos = line.find_first_of(' '); - if (size_pos != line.npos) { - size_pos = line.find_first_not_of(' ', size_pos); - } - if (size_pos != line.npos) { - contentLength = atoi(&line[size_pos]); - chunked = false; - } - } else if (startsWith(line, "Content-Encoding:")) { - if (line.find("gzip") != std::string::npos) { - gzip = true; - } - } else if (startsWith(line, "Transfer-Encoding:")) { - if (line.find("chunked") != std::string::npos) { - chunked = true; - } - } - } - - if (!contentLength && progress) { - // Content length is unknown. - // Set progress to 1% so it looks like something is happening... - *progress = 0.1f; - } - - if (!contentLength) { - // No way to know how far along we are. Let's just not update the progress counter. - if (!readbuf.ReadAll(sock())) - return -1; - } else { - // Let's read in chunks, updating progress between each. - if (!readbuf.ReadAllWithProgress(sock(), contentLength, progress)) - return -1; - } - - // output now contains the rest of the reply. Dechunk it. - if (chunked) { - DeChunk(&readbuf, output, contentLength, progress); - } else { - output->Append(readbuf); - } - - // If it's gzipped, we decompress it and put it back in the buffer. - if (gzip) { - std::string compressed, decompressed; - output->TakeAll(&compressed); - bool result = decompress_string(compressed, &decompressed); - if (!result) { - ELOG("Error decompressing using zlib"); - *progress = 0.0f; - return -1; - } - output->Append(decompressed); - } - - *progress = 1.0f; return code; } @@ -305,6 +213,133 @@ int Client::POST(const char *resource, const std::string &data, Buffer *output) return POST(resource, data, "", output); } +int Client::SendRequest(const char *method, const char *resource, const char *otherHeaders, float *progress) { + if (progress) { + *progress = 0.01f; + } + + Buffer buffer; + const char *tpl = + "%s %s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: " USERAGENT "\r\n" + "Connection: close\r\n" + "%s" + "\r\n"; + + buffer.Printf(tpl, method, resource, host_.c_str(), otherHeaders ? otherHeaders : ""); + bool flushed = buffer.FlushSocket(sock()); + if (!flushed) { + return -1; // TODO error code. + } + return 0; +} + +int Client::ReadResponseHeaders(Buffer *readbuf, std::vector &responseHeaders, float *progress) { + // Snarf all the data we can into RAM. A little unsafe but hey. + if (readbuf->Read(sock(), 4096) < 0) { + ELOG("Failed to read HTTP headers :("); + return -1; + } + + // Grab the first header line that contains the http code. + + // Skip the header. TODO: read HTTP code and file size so we can make progress bars. + + std::string line; + readbuf->TakeLineCRLF(&line); + + int code; + size_t code_pos = line.find(' '); + if (code_pos != line.npos) { + code_pos = line.find_first_not_of(' ', code_pos); + } + + if (code_pos != line.npos) { + code = atoi(&line[code_pos]); + } else { + return -1; + } + + // TODO + while (true) { + int sz = readbuf->TakeLineCRLF(&line); + if (!sz) + break; + responseHeaders.push_back(line); + } + + return code; +} + +int Client::ReadResponseEntity(Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, float *progress) { + bool gzip = false; + bool chunked = false; + int contentLength = 0; + for (std::string line : responseHeaders) { + // TODO: Case folding. + if (startsWith(line, "Content-Length:")) { + size_t size_pos = line.find_first_of(' '); + if (size_pos != line.npos) { + size_pos = line.find_first_not_of(' ', size_pos); + } + if (size_pos != line.npos) { + contentLength = atoi(&line[size_pos]); + chunked = false; + } + } else if (startsWith(line, "Content-Encoding:")) { + if (line.find("gzip") != std::string::npos) { + gzip = true; + } + } else if (startsWith(line, "Transfer-Encoding:")) { + if (line.find("chunked") != std::string::npos) { + chunked = true; + } + } + } + + if (!contentLength && progress) { + // Content length is unknown. + // Set progress to 1% so it looks like something is happening... + *progress = 0.1f; + } + + if (!contentLength || !progress) { + // No way to know how far along we are. Let's just not update the progress counter. + if (!readbuf->ReadAll(sock())) + return -1; + } else { + // Let's read in chunks, updating progress between each. + if (!readbuf->ReadAllWithProgress(sock(), contentLength, progress)) + return -1; + } + + // output now contains the rest of the reply. Dechunk it. + if (chunked) { + DeChunk(readbuf, output, contentLength, progress); + } else { + output->Append(*readbuf); + } + + // If it's gzipped, we decompress it and put it back in the buffer. + if (gzip) { + std::string compressed, decompressed; + output->TakeAll(&compressed); + bool result = decompress_string(compressed, &decompressed); + if (!result) { + ELOG("Error decompressing using zlib"); + *progress = 0.0f; + return -1; + } + output->Append(decompressed); + } + + if (progress) { + *progress = 1.0f; + } + return 0; +} + Download::Download(const std::string &url, const std::string &outfile) : progress_(0.0f), url_(url), outfile_(outfile), resultCode_(0), completed_(false), failed_(false), cancelled_(false), hidden_(false) { } diff --git a/net/http_client.h b/net/http_client.h index cc6c607520..7425115785 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -66,6 +66,14 @@ public: int POST(const char *resource, const std::string &data, Buffer *output); // HEAD, PUT, DELETE aren't implemented yet. + + int SendRequest(const char *method, const char *resource, const char *otherHeaders = nullptr, float *progress = nullptr); + int ReadResponseHeaders(Buffer *readbuf, std::vector &responseHeaders, float *progress = nullptr); + // If your response contains a response, you must read it. + int ReadResponseEntity(Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, float *progress = nullptr); + + const char *userAgent_; + const char *httpVersion_; }; // Not particularly efficient, but hey - it's a background download, that's pretty cool :P From c85fb55502feaea7c8a36004957229df4dc2b334 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 24 Nov 2014 07:47:57 -0800 Subject: [PATCH 1285/1445] Fix Take() methods. --- base/buffer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index 0c2cb830d5..54d062036d 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -58,13 +58,12 @@ void Buffer::Take(size_t length, std::string *dest) { dest->resize(length); if (length > 0) { Take(length, &(*dest)[0]); - memcpy(&(*dest)[0], &data_[0], length); - data_.erase(data_.begin(), data_.begin() + length); } } void Buffer::Take(size_t length, char *dest) { memcpy(dest, &data_[0], length); + data_.erase(data_.begin(), data_.begin() + length); } int Buffer::TakeLineCRLF(std::string *dest) { From 3de556b248f0c83405451e46ce5e56168d0ed0d1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 25 Nov 2014 00:30:13 -0800 Subject: [PATCH 1286/1445] Handle commonly mixed-case headers better. Sometimes you'll see Content-length, etc. --- base/stringutil.h | 15 +++++++++++++++ net/http_client.cpp | 9 +++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/base/stringutil.h b/base/stringutil.h index 3cd9a9f3d4..24b6092096 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -12,6 +12,7 @@ #ifdef _MSC_VER #pragma warning (disable:4996) +#define strncasecmp _strnicmp #endif #ifdef BLACKBERRY @@ -74,6 +75,20 @@ inline bool endsWith(const std::string &str, const std::string &what) { return str.substr(str.size() - what.size()) == what; } +// Only use on strings where you're only concerned about ASCII. +inline bool startsWithNoCase(const std::string &str, const std::string &what) { + if (str.size() < what.size()) + return false; + return strncasecmp(str.c_str(), what.c_str(), what.size()) == 0; +} + +inline bool endsWithNoCase(const std::string &str, const std::string &what) { + if (str.size() < what.size()) + return false; + const size_t offset = str.size() - what.size(); + return strncasecmp(str.c_str() + offset, what.c_str(), what.size()) == 0; +} + void DataToHexString(const uint8 *data, size_t size, std::string *output); inline void StringToHexString(const std::string &data, std::string *output) { DataToHexString((uint8_t *)(&data[0]), data.size(), output); diff --git a/net/http_client.cpp b/net/http_client.cpp index 88f18c5d24..081958b00b 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -277,8 +277,7 @@ int Client::ReadResponseEntity(Buffer *readbuf, const std::vector & bool chunked = false; int contentLength = 0; for (std::string line : responseHeaders) { - // TODO: Case folding. - if (startsWith(line, "Content-Length:")) { + if (startsWithNoCase(line, "Content-Length:")) { size_t size_pos = line.find_first_of(' '); if (size_pos != line.npos) { size_pos = line.find_first_not_of(' ', size_pos); @@ -287,11 +286,13 @@ int Client::ReadResponseEntity(Buffer *readbuf, const std::vector & contentLength = atoi(&line[size_pos]); chunked = false; } - } else if (startsWith(line, "Content-Encoding:")) { + } else if (startsWithNoCase(line, "Content-Encoding:")) { + // TODO: Case folding... if (line.find("gzip") != std::string::npos) { gzip = true; } - } else if (startsWith(line, "Transfer-Encoding:")) { + } else if (startsWithNoCase(line, "Transfer-Encoding:")) { + // TODO: Case folding... if (line.find("chunked") != std::string::npos) { chunked = true; } From b88c792f0ed2239a98cb190298e63ef52af026d1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 25 Nov 2014 08:37:59 -0800 Subject: [PATCH 1287/1445] Actually use httpVersion_ and userAgent_. --- net/http_client.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 081958b00b..84879441d0 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -220,14 +220,14 @@ int Client::SendRequest(const char *method, const char *resource, const char *ot Buffer buffer; const char *tpl = - "%s %s HTTP/1.1\r\n" + "%s %s HTTP/%s\r\n" "Host: %s\r\n" - "User-Agent: " USERAGENT "\r\n" + "User-Agent: %s\r\n" "Connection: close\r\n" "%s" "\r\n"; - buffer.Printf(tpl, method, resource, host_.c_str(), otherHeaders ? otherHeaders : ""); + buffer.Printf(tpl, method, resource, httpVersion_, host_.c_str(), userAgent_, otherHeaders ? otherHeaders : ""); bool flushed = buffer.FlushSocket(sock()); if (!flushed) { return -1; // TODO error code. From 1150598ce463c99fbb08ba4177a7937692fe9bc0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 25 Nov 2014 08:49:05 -0800 Subject: [PATCH 1288/1445] Migrate POST to use HTTP/1.1, etc. --- net/http_client.cpp | 66 +++++++++++++++++++-------------------------- net/http_client.h | 9 ++++--- 2 files changed, 33 insertions(+), 42 deletions(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 84879441d0..2d7dfa0db5 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -167,53 +167,41 @@ int Client::GET(const char *resource, Buffer *output, float *progress) { return code; } -int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output) { - Buffer buffer; - const char *tpl = "POST %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " USERAGENT "\r\nContent-Length: %d\r\n"; - buffer.Printf(tpl, resource, host_.c_str(), (int)data.size()); - if (!mime.empty()) { - buffer.Printf("Content-Type: %s\r\n", mime.c_str()); +int Client::POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output, float *progress) { + char otherHeaders[2048]; + if (mime.empty()) { + snprintf(otherHeaders, sizeof(otherHeaders), "Content-Length: %lld\r\n", (long long)data.size()); + } else { + snprintf(otherHeaders, sizeof(otherHeaders), "Content-Length: %lld\r\nContent-Type: %s\r\n", (long long)data.size(), mime.c_str()); } - buffer.Append("\r\n"); - buffer.Append(data); - if (!buffer.FlushSocket(sock())) { - ELOG("Failed posting"); + int err = SendRequestWithData("POST", resource, data, otherHeaders, progress); + if (err < 0) { + return err; } - // I guess we could add a deadline here. - output->ReadAll(sock()); - - if (output->size() == 0) { - // The connection was closed. - ELOG("POST failed."); - return -1; + Buffer readbuf; + std::vector responseHeaders; + int code = ReadResponseHeaders(&readbuf, responseHeaders, progress); + if (code < 0) { + return code; } - std::string debug_data; - output->PeekAll(&debug_data); - - //VLOG(1) << "Reply size (before stripping headers): " << debug_data.size(); - std::string debug_str; - StringToHexString(debug_data, &debug_str); - // Tear off the http headers, leaving the actual response data. - std::string firstline; - CHECK_GT(output->TakeLineCRLF(&firstline), 0); - int code = atoi(&firstline[9]); - //VLOG(1) << "HTTP result code: " << code; - while (true) { - int skipped = output->SkipLineCRLF(); - if (skipped == 0) - break; + err = ReadResponseEntity(&readbuf, responseHeaders, output, progress); + if (err < 0) { + return err; } - output->PeekAll(&debug_data); return code; } -int Client::POST(const char *resource, const std::string &data, Buffer *output) { - return POST(resource, data, "", output); +int Client::POST(const char *resource, const std::string &data, Buffer *output, float *progress) { + return POST(resource, data, "", output, progress); } int Client::SendRequest(const char *method, const char *resource, const char *otherHeaders, float *progress) { + return SendRequestWithData(method, resource, "", otherHeaders, progress); +} + +int Client::SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders, float *progress) { if (progress) { *progress = 0.01f; } @@ -228,6 +216,7 @@ int Client::SendRequest(const char *method, const char *resource, const char *ot "\r\n"; buffer.Printf(tpl, method, resource, httpVersion_, host_.c_str(), userAgent_, otherHeaders ? otherHeaders : ""); + buffer.Append(data); bool flushed = buffer.FlushSocket(sock()); if (!flushed) { return -1; // TODO error code. @@ -244,8 +233,6 @@ int Client::ReadResponseHeaders(Buffer *readbuf, std::vector &respo // Grab the first header line that contains the http code. - // Skip the header. TODO: read HTTP code and file size so we can make progress bars. - std::string line; readbuf->TakeLineCRLF(&line); @@ -261,7 +248,6 @@ int Client::ReadResponseHeaders(Buffer *readbuf, std::vector &respo return -1; } - // TODO while (true) { int sz = readbuf->TakeLineCRLF(&line); if (!sz) @@ -269,6 +255,10 @@ int Client::ReadResponseHeaders(Buffer *readbuf, std::vector &respo responseHeaders.push_back(line); } + if (responseHeaders.size() == 0) { + return -1; + } + return code; } diff --git a/net/http_client.h b/net/http_client.h index 7425115785..ece8add041 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -59,15 +59,16 @@ public: ~Client(); // Return value is the HTTP return code. 200 means OK. < 0 means some local error. - int GET(const char *resource, Buffer *output, float *progress = 0); + int GET(const char *resource, Buffer *output, float *progress = nullptr); // Return value is the HTTP return code. - int POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output); - int POST(const char *resource, const std::string &data, Buffer *output); + int POST(const char *resource, const std::string &data, const std::string &mime, Buffer *output, float *progress = nullptr); + int POST(const char *resource, const std::string &data, Buffer *output, float *progress = nullptr); - // HEAD, PUT, DELETE aren't implemented yet. + // HEAD, PUT, DELETE aren't implemented yet, but can be done with SendRequest. int SendRequest(const char *method, const char *resource, const char *otherHeaders = nullptr, float *progress = nullptr); + int SendRequestWithData(const char *method, const char *resource, const std::string &data, const char *otherHeaders = nullptr, float *progress = nullptr); int ReadResponseHeaders(Buffer *readbuf, std::vector &responseHeaders, float *progress = nullptr); // If your response contains a response, you must read it. int ReadResponseEntity(Buffer *readbuf, const std::vector &responseHeaders, Buffer *output, float *progress = nullptr); From 524fceea5c0b395858de0df1f067de677dab5b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 21 Nov 2014 19:20:19 +0100 Subject: [PATCH 1289/1445] Fix text input on SDL platforms. Make V_GONE more consistent. --- base/PCMain.cpp | 12 ++++++++++++ ui/viewgroup.cpp | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 0d459d53ca..d97f977354 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -35,6 +35,7 @@ SDLJoystick *joystick = NULL; #include "net/resolve.h" #include "base/NKCodeFromSDL.h" #include "util/const_map.h" +#include "util/text/utf8.h" #include "math/math_util.h" #ifdef PPSSPP @@ -708,6 +709,17 @@ int main(int argc, char *argv[]) { } break; } + case SDL_TEXTINPUT: + { + int pos = 0; + int c = u8_nextchar(event.text.text, &pos); + KeyInput key; + key.flags = KEY_CHAR; + key.keyCode = c; + key.deviceId = DEVICE_ID_KEYBOARD; + NativeKey(key); + break; + } case SDL_MOUSEBUTTONDOWN: switch (event.button.button) { case SDL_BUTTON_LEFT: diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 3d3068efa0..c1c7e6ebaf 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -441,6 +441,8 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v float unit = (measuredWidth_ - weightZeroSum) / weightSum; // Redistribute the stretchy ones! and remeasure the children! for (size_t i = 0; i < views_.size(); i++) { + if (views_[i]->GetVisibility() == V_GONE) + continue; const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); const LinearLayoutParams *linLayoutParams = static_cast(layoutParams); if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; @@ -459,6 +461,8 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v // Redistribute! and remeasure children! for (size_t i = 0; i < views_.size(); i++) { + if (views_[i]->GetVisibility() == V_GONE) + continue; const LayoutParams *layoutParams = views_[i]->GetLayoutParams(); const LinearLayoutParams *linLayoutParams = static_cast(layoutParams); if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; @@ -533,12 +537,16 @@ void FrameLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ve } for (size_t i = 0; i < views_.size(); i++) { + if (views_[i]->GetVisibility() == V_GONE) + continue; views_[i]->Measure(dc, horiz, vert); } } void FrameLayout::Layout() { for (size_t i = 0; i < views_.size(); i++) { + if (views_[i]->GetVisibility() == V_GONE) + continue; float w = views_[i]->GetMeasuredWidth(); float h = views_[i]->GetMeasuredHeight(); From 2b6ed975e28de79d7dc34f225238eae631199afc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 6 Dec 2014 00:28:11 +0100 Subject: [PATCH 1290/1445] Improve fast sse matrix multiply --- math/fast/fast_matrix_sse.c | 10 +++++----- native.vcxproj | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/math/fast/fast_matrix_sse.c b/math/fast/fast_matrix_sse.c index 166f71abce..9de79ce760 100644 --- a/math/fast/fast_matrix_sse.c +++ b/math/fast/fast_matrix_sse.c @@ -8,12 +8,12 @@ void fast_matrix_mul_4x4_sse(float *dest, const float *a, const float *b) { int i; - for (i = 0; i < 16; i += 4) { - __m128 a_col_1 = _mm_loadu_ps(a); - __m128 a_col_2 = _mm_loadu_ps(&a[4]); - __m128 a_col_3 = _mm_loadu_ps(&a[8]); - __m128 a_col_4 = _mm_loadu_ps(&a[12]); + __m128 a_col_1 = _mm_loadu_ps(a); + __m128 a_col_2 = _mm_loadu_ps(&a[4]); + __m128 a_col_3 = _mm_loadu_ps(&a[8]); + __m128 a_col_4 = _mm_loadu_ps(&a[12]); + for (i = 0; i < 16; i += 4) { __m128 r_col = _mm_mul_ps(a_col_1, _mm_set1_ps(b[i])); r_col = _mm_add_ps(r_col, _mm_mul_ps(a_col_2, _mm_set1_ps(b[i + 1]))); r_col = _mm_add_ps(r_col, _mm_mul_ps(a_col_3, _mm_set1_ps(b[i + 2]))); diff --git a/native.vcxproj b/native.vcxproj index 59eaa83023..da563a52cd 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -754,7 +754,9 @@ - + + AssemblyAndSourceCode + From a7a9965617941adf880866cc65b0275e41c1fe3e Mon Sep 17 00:00:00 2001 From: TwistedUmbrella Date: Fri, 5 Dec 2014 19:45:51 -0500 Subject: [PATCH 1291/1445] use libc++ for iOS to avoid additional directives --- base/functional.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/base/functional.h b/base/functional.h index 5610819d42..d85cfc4d26 100644 --- a/base/functional.h +++ b/base/functional.h @@ -15,7 +15,7 @@ #endif #include -#if defined(__SYMBIAN32__) || defined(IOS) || defined(MACGNUSTD) +#if defined(__SYMBIAN32__) || defined(MACGNUSTD) #ifndef __SYMBIAN32__ #include #include @@ -47,8 +47,6 @@ namespace std { #ifdef __SYMBIAN32__ #define placeholder -#elif defined(IOS) -namespace placeholder = std::tr1::placeholders; #else namespace placeholder = std::placeholders; #endif From 82bf2dc136eeeba70b1ebee1e467c6b34240df75 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 6 Dec 2014 13:13:05 +0100 Subject: [PATCH 1292/1445] Remove left-behind log statement --- android/app-android.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 91b6562a62..6cc307ec3c 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -422,7 +422,6 @@ extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_keyDown(JNIEnv *, keyInput.keyCode = key; keyInput.flags = KEY_DOWN; if (isRepeat) { - ILOG("Is repeat! %i", key); keyInput.flags |= KEY_IS_REPEAT; } return NativeKey(keyInput); From c178af7b8b00fa48dc9be25c833823de19fccc03 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Dec 2014 15:22:52 -0800 Subject: [PATCH 1293/1445] Add wchar conversion on non-Windows. --- util/text/utf8.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++++ util/text/utf8.h | 6 ++++-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/util/text/utf8.cpp b/util/text/utf8.cpp index 5d5292e689..33e780d663 100644 --- a/util/text/utf8.cpp +++ b/util/text/utf8.cpp @@ -28,6 +28,7 @@ #include "base/basictypes.h" #include "utf8.h" +#include "utf16.h" // is start of UTF sequence inline bool isutf(char c) { @@ -460,4 +461,51 @@ std::wstring ConvertUTF8ToWString(const std::string &source) { return str; } +#else + +static size_t ConvertUTF8ToWStringInternal(wchar_t *dest, size_t destSize, const std::string &source) { + const wchar_t *const orig = dest; + const wchar_t *const destEnd = dest + destSize; + + UTF8 utf(source.c_str()); + + if (sizeof(wchar_t) == 2) { + uint16_t *destw = (uint16_t *)dest; + const uint16_t *const destwEnd = destw + destSize; + while (uint32_t c = utf.next()) { + if (destw + UTF16LE::encodeUnits(c) >= destwEnd) { + break; + } + destw += UTF16LE::encode(destw, c); + } + } else { + while (uint32_t c = utf.next()) { + if (dest + 1 >= destEnd) { + break; + } + *dest++ = c; + } + } + + // No ++ to not count the terminal in length. + if (dest < destEnd) { + *dest = 0; + } + + return dest - orig; +} + +void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) { + ConvertUTF8ToWStringInternal(dest, destSize, source); +} + +std::wstring ConvertUTF8ToWString(const std::string &source) { + std::wstring dst; + // utf-8 won't be less bytes than there are characters. But need +1 for terminator. + dst.resize(source.size() + 1, 0); + size_t realLen = ConvertUTF8ToWStringInternal(&dst[0], source.size() + 1, source); + dst.resize(realLen); + return dst; +} + #endif diff --git a/util/text/utf8.h b/util/text/utf8.h index 83af37ee58..70dbf80b07 100644 --- a/util/text/utf8.h +++ b/util/text/utf8.h @@ -82,7 +82,9 @@ bool UTF8StringHasNonASCII(const char *utf8string); std::string ConvertWStringToUTF8(const std::wstring &wstr); std::string ConvertWStringToUTF8(const wchar_t *wstr); -void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source); -std::wstring ConvertUTF8ToWString(const std::string &source); #endif + +// Dest size in units, not bytes. +void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source); +std::wstring ConvertUTF8ToWString(const std::string &source); From 60f8132d2eede3a477248883274d2712221b7737 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 8 Dec 2014 14:07:51 -0500 Subject: [PATCH 1294/1445] stringutil: Add early-exit case to ReplaceAll If both 'replaceands' are the same, the result string can just be returned. --- base/stringutil.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/stringutil.cpp b/base/stringutil.cpp index 2c8bd1e56a..134a9b1dfd 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -230,6 +230,10 @@ void SplitString(const std::string& str, const char delim, std::vector Date: Mon, 15 Dec 2014 00:00:16 +0100 Subject: [PATCH 1295/1445] Port my old webserver from the predecessor to native --- Android.mk | 3 + base/stringutil.cpp | 28 +++++++ base/stringutil.h | 4 + native.vcxproj | 6 ++ native.vcxproj.filters | 18 +++++ net/http_headers.cpp | 164 ++++++++++++++++++++++++++++++++++++++++ net/http_headers.h | 43 +++++++++++ net/http_server.cpp | 167 +++++++++++++++++++++++++++++++++++++++++ net/http_server.h | 88 ++++++++++++++++++++++ thin3d/thin3d_gl.cpp | 6 +- thread/executor.cpp | 10 +++ thread/executor.h | 18 +++++ 12 files changed, 550 insertions(+), 5 deletions(-) create mode 100644 net/http_headers.cpp create mode 100644 net/http_headers.h create mode 100644 net/http_server.cpp create mode 100644 net/http_server.h create mode 100644 thread/executor.cpp create mode 100644 thread/executor.h diff --git a/Android.mk b/Android.mk index d9d0e595e2..0bfee1bbb4 100644 --- a/Android.mk +++ b/Android.mk @@ -67,9 +67,12 @@ LOCAL_SRC_FILES :=\ math/lin/matrix4x4.cpp.arm \ midi/midi_input.cpp \ net/http_client.cpp \ + net/http_server.cpp \ + net/http_headers.cpp \ net/resolve.cpp \ net/url.cpp \ profiler/profiler.cpp \ + thread/executor.cpp \ thread/threadutil.cpp \ thread/prioritizedworkqueue.cpp \ thread/threadpool.cpp \ diff --git a/base/stringutil.cpp b/base/stringutil.cpp index 134a9b1dfd..848993349e 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -37,6 +37,34 @@ void OutputDebugStringUTF8(const char *p) { #endif +void StringTrimEndNonAlphaNum(char *str) { + int n = strlen(str); + while (!isalnum(str[n]) && n >= 0) { + str[n--] = '\0'; + } +} + +void SkipSpace(const char **ptr) { + while (**ptr && isspace(**ptr)) { + (*ptr)++; + } +} + +void StringUpper(char *str) { + while (*str) { + *str = toupper(*str); + str++; + } +} + +void StringUpper(char *str, int len) { + while (len--) { + *str = toupper(*str); + str++; + } +} + + unsigned int parseHex(const char *_szValue) { int Value = 0; diff --git a/base/stringutil.h b/base/stringutil.h index 24b6092096..aa6157383c 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -159,3 +159,7 @@ static std::string ValueToString(const N value) return string.str(); } +void StringTrimEndNonAlphaNum(char *str); +void SkipSpace(const char **ptr); +void StringUpper(char *str); +void StringUpper(char *str, int len); diff --git a/native.vcxproj b/native.vcxproj index da563a52cd..3cd20ba3af 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -270,11 +270,14 @@ + + + @@ -759,6 +762,8 @@ + + @@ -766,6 +771,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 3cc3807123..abb54be747 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -351,6 +351,15 @@ thin3d + + net + + + net + + + thread + @@ -822,6 +831,15 @@ thin3d + + net + + + net + + + thread + diff --git a/net/http_headers.cpp b/net/http_headers.cpp new file mode 100644 index 0000000000..2e7103ca51 --- /dev/null +++ b/net/http_headers.cpp @@ -0,0 +1,164 @@ +#include "net/http_headers.h" + +#ifdef _WIN32 + +#include // for timeval + +#endif + +#include +#include + +#include "base/logging.h" +#include "base/stringutil.h" +#include "file/fd_util.h" + +namespace http { + +RequestHeader::RequestHeader() + : status(200), referer(0), user_agent(0), + resource(0), params(0), content_length(-1), first_header_(true) { +} + +RequestHeader::~RequestHeader() { + delete [] referer; + delete [] user_agent; + delete [] resource; + delete [] params; +} + +bool RequestHeader::GetParamValue(const char *param_name, std::string *value) const { + if (!params) + return false; + std::string p(params); + std::vector v; + SplitString(p, '&', v); + for (size_t i = 0; i < v.size(); i++) { + std::vector parts; + SplitString(v[i], '=', parts); + ILOG("Param: %s Value: %s", parts[0].c_str(), parts[1].c_str()); + if (parts[0] == param_name) { + *value = parts[1]; + return true; + } + } + return false; +} + +// Intended to be a mad fast parser. It's not THAT fast currently, there's still +// things to optimize, but meh. +int RequestHeader::ParseHttpHeader(const char *buffer) { + if (first_header_) { + // Step 1: Method + first_header_ = false; + if (!memcmp(buffer, "GET ", 4)) { + method = GET; + buffer += 4; + } else if (!memcmp(buffer, "HEAD ", 5)) { + method = HEAD; + buffer += 5; + } else if (!memcmp(buffer, "POST ", 5)) { + method = POST; + buffer += 5; + } else { + method = UNSUPPORTED; + status = 501; + return -1; + } + SkipSpace(&buffer); + + // Step 2: Resource, params (what's after the ?, if any) + const char *endptr = strchr(buffer, ' '); + const char *q_ptr = strchr(buffer, '?'); + + int resource_name_len; + if (q_ptr) + resource_name_len = q_ptr - buffer; + else + resource_name_len = endptr - buffer; + if (!resource_name_len) { + status = 400; + return -1; + } + resource = new char[resource_name_len + 1]; + memcpy(resource, buffer, resource_name_len); + resource[resource_name_len] = '\0'; + if (q_ptr) { + int param_length = endptr - q_ptr - 1; + params = new char[param_length + 1]; + memcpy(params, q_ptr + 1, param_length); + params[param_length] = '\0'; + } + if (strstr(buffer, "HTTP/")) + type = FULL; + else + type = SIMPLE; + return 0; + } + + // We have a real header to parse. + const char *colon = strchr(buffer, ':'); + if (!colon) { + status = 400; + return -1; + } + + // The header is formatted as key: value. + int key_len = colon - buffer; + char *key = new char[key_len + 1]; + strncpy(key, buffer, key_len); + key[key_len] = 0; + StringUpper(key, key_len); + + // Go to after the colon to get the value. + buffer = colon + 1; + SkipSpace(&buffer); + int value_len = strlen(buffer); + + if (!strcmp(key, "USER-AGENT")) { + user_agent = new char[value_len + 1]; + memcpy(user_agent, buffer, value_len + 1); + ILOG("user-agent: %s", user_agent); + } else if (!strcmp(key, "REFERER")) { + referer = new char[value_len + 1]; + memcpy(referer, buffer, value_len + 1); + } else if (!strcmp(key, "CONTENT-LENGTH")) { + content_length = atoi(buffer); + ILOG("Content-Length: %i", (int)content_length); + } + + delete [] key; +} + +void RequestHeader::ParseHeaders(int fd) { + // Get the request, with a timeout. + struct ::timeval tv; + tv.tv_sec = 5; + tv.tv_usec = 0; + + int line_count = 0; + // Loop through request headers. + while (true) { + if (!fd_util::WaitUntilReady(fd, 5.0)) { // Wait max 5 secs. + // Timed out or error. + ok = false; + return; + } + char buffer[1024]; + fd_util::ReadLine(fd, buffer, 1023); + StringTrimEndNonAlphaNum(buffer); + if (buffer[0] == '\0') + break; + ParseHttpHeader(buffer); + line_count++; + if (type == SIMPLE) { + // Done! + ILOG("Simple: Done parsing http request."); + break; + } + } + ILOG("finished parsing request."); + ok = line_count > 1; +} + +} // namespace http diff --git a/net/http_headers.h b/net/http_headers.h new file mode 100644 index 0000000000..d333e1f91a --- /dev/null +++ b/net/http_headers.h @@ -0,0 +1,43 @@ +#ifndef _NET_HTTP_HTTP_HEADERS +#define _NET_HTTP_HTTP_HEADERS + +#include "base/buffer.h" + +namespace http { + +class RequestHeader { + public: + RequestHeader(); + ~RequestHeader(); + // Public variables since it doesn't make sense + // to bother with accessors for all these. + int status; + char *referer; + char *user_agent; + char *resource; + char *params; + int content_length; + enum RequestType { + SIMPLE, FULL, + }; + RequestType type; + enum Method { + GET, + HEAD, + POST, + UNSUPPORTED, + }; + Method method; + bool ok; + void ParseHeaders(int fd); + bool GetParamValue(const char *param_name, std::string *value) const; + private: + int ParseHttpHeader(const char *buffer); + bool first_header_; + + DISALLOW_COPY_AND_ASSIGN(RequestHeader); +}; + +} // namespace http + +#endif diff --git a/net/http_server.cpp b/net/http_server.cpp new file mode 100644 index 0000000000..a12b9cc5cf --- /dev/null +++ b/net/http_server.cpp @@ -0,0 +1,167 @@ +#include "base/timeutil.h" + +#ifdef _WIN32 + +#include +#include +#include + +#else + +#include /* socket definitions */ +#include /* socket types */ +#include /* for waitpid() */ +#include /* inet (3) funtions */ +#include /* misc. UNIX functions */ + +#endif + +#include +#include + +#include "base/functional.h" +#include "base/logging.h" +#include "base/buffer.h" +#include "file/fd_util.h" +#include "net/http_server.h" + +namespace http { + +Request::Request(int fd) + : fd_(fd) { + in_buffer_ = new Buffer; + out_buffer_ = new Buffer; + header_.ParseHeaders(fd_); + + if (header_.ok) { + // Read the rest, too. + if (header_.content_length >= 0) { + in_buffer_->Read(fd_, header_.content_length); + } + ILOG("The request carried with it %i bytes", (int)in_buffer_->size()); + } else { + Close(); + } +} + +Request::~Request() { + Close(); + + CHECK(in_buffer_->empty()); + delete in_buffer_; + CHECK(out_buffer_->empty()); + delete out_buffer_; +} + +void Request::WriteHttpResponseHeader(int status, int size) const { + Buffer *buffer = out_buffer_; + buffer->Printf("HTTP/1.0 %d OK\r\n", status); + buffer->Append("Server: SuperDuperServer v0.1\r\n"); + buffer->Append("Content-Type: text/html\r\n"); + if (size >= 0) { + buffer->Printf("Content-Length: %i\r\n", size); + } + buffer->Append("\r\n"); +} + +void Request::WritePartial() const { + CHECK(fd_); + out_buffer_->Flush(fd_); +} + +void Request::Write() { + CHECK(fd_); + WritePartial(); + Close(); +} + +void Request::Close() { + if (fd_) { + close(fd_); + fd_ = 0; + } +} + +Server::Server(threading::Executor *executor) + : port_(0), executor_(executor) { + RegisterHandler("/", std::bind(&Server::HandleListing, this, placeholder::_1)); +} + +void Server::RegisterHandler(const char *url_path, UrlHandlerFunc handler) { + handlers_[std::string(url_path)] = handler; +} + +bool Server::Run(int port) { + ILOG("HTTP server started on port %i", port); + port_ = port; + + int listener = socket(AF_INET, SOCK_STREAM, 0); + CHECK_GE(listener, 0); + + struct sockaddr_in server_addr; + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htonl(INADDR_ANY); + server_addr.sin_port = htons(port); + + int opt = 1; + // Enable re-binding to avoid the pain when restarting the server quickly. + setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)); + + if (bind(listener, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + ELOG("Failed to bind to port %i. Bailing.", port); + return false; + } + + // 1024 is the max number of queued requests. + CHECK_GE(listen(listener, 1024), 0); + while (true) { + sockaddr client_addr; + socklen_t client_addr_size = sizeof(client_addr); + int conn_fd = accept(listener, &client_addr, &client_addr_size); + if (conn_fd >= 0) { + executor_->Run(std::bind(&Server::HandleConnection, this, conn_fd)); + } else { + FLOG("socket accept failed: %i", conn_fd); + } + } + + // We'll never get here. Ever. + return true; +} + +void Server::HandleConnection(int conn_fd) { + Request request(conn_fd); + if (!request.IsOK()) { + WLOG("Bad request, ignoring."); + return; + } + HandleRequestDefault(request); + request.WritePartial(); +} + +void Server::HandleRequest(const Request &request) { + HandleRequestDefault(request); +} + +void Server::HandleRequestDefault(const Request &request) { + // First, look through all handlers. If we got one, use it. + for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { + if (iter->first == request.resource()) { + (iter->second)(request); + return; + } + } + ILOG("No handler for '%s', falling back to 404.", request.resource()); + const char *payload = "404 not found\r\n"; + request.WriteHttpResponseHeader(404, strlen(payload)); + request.out_buffer()->Append(payload); +} + +void Server::HandleListing(const Request &request) { + for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { + request.out_buffer()->Printf("%s", iter->first.c_str()); + } +} + +} // namespace http diff --git a/net/http_server.h b/net/http_server.h new file mode 100644 index 0000000000..5d45722671 --- /dev/null +++ b/net/http_server.h @@ -0,0 +1,88 @@ +#ifndef _HTTP_SERVER_H +#define _HTTP_SERVER_H + +#include + +#include "base/functional.h" +#include "base/buffer.h" +#include "net/http_headers.h" +#include "thread/executor.h" + +namespace http { + +class Request { + public: + Request(int fd); + ~Request(); + + const char *resource() const { + return header_.resource; + } + + bool GetParamValue(const char *param_name, std::string *value) const { + return header_.GetParamValue(param_name, value); + } + + Buffer *in_buffer() const { return in_buffer_; } + Buffer *out_buffer() const { return out_buffer_; } + + // TODO: Remove, in favor of PartialWrite and friends. + int fd() const { return fd_; } + + void WritePartial() const; + void Write(); + void Close(); + + bool IsOK() const { return fd_ > 0; } + + // If size is negative, no Content-Length: line is written. + void WriteHttpResponseHeader(int status, int size = -1) const; + + private: + Buffer *in_buffer_; + Buffer *out_buffer_; + RequestHeader header_; + int fd_; +}; + +// Register handlers on this class to serve stuff. +class Server { + public: + Server(threading::Executor *executor); + + typedef std::function UrlHandlerFunc; + typedef std::map UrlHandlerMap; + + // Runs forever, serving request. If you want to do something else than serve pages, + // better put this on a thread. Returns false if failed to start serving, never + // returns if successful. + bool Run(int port); + + void RegisterHandler(const char *url_path, UrlHandlerFunc handler); + + // If you want to customize things at a lower level than just a simple path handler, + // then inherit and override this. Implementations should forward to HandleRequestDefault + // if they don't recognize the url. + virtual void HandleRequest(const Request &request); + + private: + void HandleConnection(int conn_fd); + + void GetRequest(Request *request); + + // Things like default 404, etc. + void HandleRequestDefault(const Request &request); + + // Neat built-in handlers that are tied to the server. + void HandleListing(const Request &request); + + int port_; + + UrlHandlerMap handlers_; + + threading::Executor *executor_; +}; + +} // namespace http + +#endif // _HTTP_SERVER_H diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 08516fb19e..530a3bd9ea 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -285,11 +285,7 @@ public: Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source); void SetScissorEnabled(bool enable) override { - if (enable) { - glstate.scissorTest.enable(); - } else { - glstate.scissorTest.disable(); - } + glstate.scissorTest.set(enable); } void SetScissorRect(int left, int top, int width, int height) override { diff --git a/thread/executor.cpp b/thread/executor.cpp new file mode 100644 index 0000000000..abba1fb809 --- /dev/null +++ b/thread/executor.cpp @@ -0,0 +1,10 @@ +#include "thread/executor.h" +#include "base/functional.h" + +namespace threading { + +void SameThreadExecutor::Run(std::function func) { + func(); +} + +} // namespace threading diff --git a/thread/executor.h b/thread/executor.h new file mode 100644 index 0000000000..dcc7cd8175 --- /dev/null +++ b/thread/executor.h @@ -0,0 +1,18 @@ +#pragma once + +#include "base/functional.h" + +namespace threading { + +// Stuff that can execute other stuff, like threadpools, should inherit from this. +class Executor { + public: + virtual void Run(std::function func) = 0; +}; + +class SameThreadExecutor : public Executor { + public: + virtual void Run(std::function func); +}; + +} // namespace threading From 277788500e88b6971cd2fade29860809cd7e58ef Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Dec 2014 01:12:28 +0100 Subject: [PATCH 1296/1445] Detect the terribleness of PowerVR precision issues depending on GPU revision --- gfx_es2/gl_state.cpp | 7 ++++++- gfx_es2/gpu_features.cpp | 15 +++++++++++++++ gfx_es2/gpu_features.h | 5 ++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 1877c499c3..97626d7242 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -127,7 +127,12 @@ void CheckGLExtensions() { gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; } - ILOG("GPU Vendor : %s ; GL version str: %s ; GLSL version str: %s", cvendor, versionStr ? versionStr : "N/A", glslVersionStr ? glslVersionStr : "N/A"); + ILOG("GPU Vendor : %s ; renderer: %s version str: %s ; GLSL version str: %s", cvendor, renderer ? renderer : "N/A", versionStr ? versionStr : "N/A", glslVersionStr ? glslVersionStr : "N/A"); + + if (renderer) { + strncpy(gl_extensions.model, renderer, sizeof(gl_extensions.model)); + gl_extensions.model[sizeof(gl_extensions.model) - 1] = 0; + } #ifndef USING_GLES2 char buffer[64] = { 0 }; diff --git a/gfx_es2/gpu_features.cpp b/gfx_es2/gpu_features.cpp index cf9be36606..ce1ed8ba96 100644 --- a/gfx_es2/gpu_features.cpp +++ b/gfx_es2/gpu_features.cpp @@ -1,3 +1,4 @@ +#include "base/logging.h" #include "gfx_es2/gpu_features.h" bool GLExtensions::VersionGEThan(int major, int minor, int sub) { @@ -14,8 +15,22 @@ bool GLExtensions::VersionGEThan(int major, int minor, int sub) { void ProcessGPUFeatures() { gl_extensions.bugs = 0; + + ILOG("Checking for GL driver bugs... vendor=%i model='%s'", (int)gl_extensions.gpuVendor, gl_extensions.model); // Should be table driven instead, this is a quick hack for Galaxy Y if (System_GetProperty(SYSPROP_NAME) == "samsung:GT-S5360") { gl_extensions.bugs |= BUG_FBO_UNUSABLE; } + + if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) { + if (!strcmp(gl_extensions.model, "PowerVR SGX 540") || + !strcmp(gl_extensions.model, "PowerVR SGX 530") || + !strcmp(gl_extensions.model, "PowerVR SGX 520") ) { + WLOG("GL DRIVER BUG: PVR with bad and terrible precision"); + gl_extensions.bugs |= BUG_PVR_SHADER_PRECISION_TERRIBLE | BUG_PVR_SHADER_PRECISION_BAD; + } else { + WLOG("GL DRIVER BUG: PVR with bad precision"); + gl_extensions.bugs |= BUG_PVR_SHADER_PRECISION_BAD; + } + } } diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 0415fb60d2..a74b00c8ff 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -18,7 +18,9 @@ enum { }; enum { - BUG_FBO_UNUSABLE=1 + BUG_FBO_UNUSABLE = 1, + BUG_PVR_SHADER_PRECISION_BAD = 2, + BUG_PVR_SHADER_PRECISION_TERRIBLE = 4, }; // Extensions to look at using: @@ -29,6 +31,7 @@ enum { struct GLExtensions { int ver[3]; int gpuVendor; + char model[128]; bool GLES3; // true if the full OpenGL ES 3.0 is supported From 350c5e3ad58684f6dba8d1529a2835376eb5dd9b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Dec 2014 17:24:47 -0800 Subject: [PATCH 1297/1445] Buildfix for a few platforms. --- gfx_es2/gpu_features.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx_es2/gpu_features.cpp b/gfx_es2/gpu_features.cpp index ce1ed8ba96..67d205ec88 100644 --- a/gfx_es2/gpu_features.cpp +++ b/gfx_es2/gpu_features.cpp @@ -1,3 +1,4 @@ +#include #include "base/logging.h" #include "gfx_es2/gpu_features.h" From 8e092998c2ff78d033e36d20710485b43da10bae Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Dec 2014 21:02:16 +0100 Subject: [PATCH 1298/1445] Add SGX 543 to the halls of the damned.. I mean the ones with terrible precision --- gfx_es2/gpu_features.cpp | 3 ++- net/http_headers.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gpu_features.cpp b/gfx_es2/gpu_features.cpp index 67d205ec88..f230b7c96d 100644 --- a/gfx_es2/gpu_features.cpp +++ b/gfx_es2/gpu_features.cpp @@ -24,7 +24,8 @@ void ProcessGPUFeatures() { } if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) { - if (!strcmp(gl_extensions.model, "PowerVR SGX 540") || + if (!strcmp(gl_extensions.model, "PowerVR SGX 543") || + !strcmp(gl_extensions.model, "PowerVR SGX 540") || !strcmp(gl_extensions.model, "PowerVR SGX 530") || !strcmp(gl_extensions.model, "PowerVR SGX 520") ) { WLOG("GL DRIVER BUG: PVR with bad and terrible precision"); diff --git a/net/http_headers.cpp b/net/http_headers.cpp index 2e7103ca51..c0cafd6c62 100644 --- a/net/http_headers.cpp +++ b/net/http_headers.cpp @@ -128,6 +128,7 @@ int RequestHeader::ParseHttpHeader(const char *buffer) { } delete [] key; + return 0; } void RequestHeader::ParseHeaders(int fd) { From 072f918f788093231ac5fb676544785af8a7beba Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Dec 2014 23:00:02 +0100 Subject: [PATCH 1299/1445] Check shader precision when possible --- gfx_es2/gl_state.cpp | 21 +++++++++++++++++++++ gfx_es2/gpu_features.h | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 97626d7242..a1ed3c24fe 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -310,10 +310,31 @@ void CheckGLExtensions() { } #endif +#ifdef USING_GLES2 + if (true) { +#else + if (strstr(extString, "GL_ARB_ES2_compatibility")) { +#endif + const GLint precisions[6] = { + GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT, + GL_LOW_INT, GL_MEDIUM_INT, GL_HIGH_INT + }; + GLint shaderTypes[2] = { + GL_VERTEX_SHADER, GL_FRAGMENT_SHADER + }; + for (int st = 0; st < 2; st++) { + for (int p = 0; p < 6; p++) { + glGetShaderPrecisionFormat(shaderTypes[st], precisions[p], gl_extensions.range[st][p], &gl_extensions.precision[p]); + } + } + } + + #ifdef USING_GLES2 gl_extensions.FBO_ARB = true; gl_extensions.FBO_EXT = false; #else + gl_extensions.FBO_ARB = false; gl_extensions.FBO_EXT = false; gl_extensions.PBO_ARB = true; diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index a74b00c8ff..12f27a4d19 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -74,6 +74,10 @@ struct GLExtensions { // Bugs int bugs; + // Shader precision. Only fetched on ES for now. + int range[2][6][2]; // [vs,fs][lowf,mediumf,highf,lowi,mediumi,highi][min,max] + int precision[6]; + // greater-or-equal than bool VersionGEThan(int major, int minor, int sub = 0); }; From ae9d05f6a2e6a3c5c99dce2d9ce2f608ee34c32f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 15 Dec 2014 23:11:27 +0100 Subject: [PATCH 1300/1445] Oops --- gfx_es2/gl_state.cpp | 2 +- gfx_es2/gpu_features.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index a1ed3c24fe..ab97de2dd5 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -324,7 +324,7 @@ void CheckGLExtensions() { }; for (int st = 0; st < 2; st++) { for (int p = 0; p < 6; p++) { - glGetShaderPrecisionFormat(shaderTypes[st], precisions[p], gl_extensions.range[st][p], &gl_extensions.precision[p]); + glGetShaderPrecisionFormat(shaderTypes[st], precisions[p], gl_extensions.range[st][p], &gl_extensions.precision[st][p]); } } } diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 12f27a4d19..37faea8fde 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -76,7 +76,7 @@ struct GLExtensions { // Shader precision. Only fetched on ES for now. int range[2][6][2]; // [vs,fs][lowf,mediumf,highf,lowi,mediumi,highi][min,max] - int precision[6]; + int precision[2][6]; // [vs,fs][lowf...] // greater-or-equal than bool VersionGEThan(int major, int minor, int sub = 0); From abb96807cb0b4c7d0fa3acdfa06bbf104aace8f8 Mon Sep 17 00:00:00 2001 From: chinhodado Date: Tue, 16 Dec 2014 01:00:32 -0500 Subject: [PATCH 1301/1445] Remove a redundant member variable in a subclass --- ui/viewgroup.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 3ebcbd03ae..66f39ae4e9 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -278,7 +278,7 @@ class TabHolder : public LinearLayout { public: TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0) : LinearLayout(Opposite(orientation), layoutParams), - orientation_(orientation), stripSize_(stripSize), currentTab_(0) { + stripSize_(stripSize), currentTab_(0) { SetSpacing(0.0f); tabStrip_ = new ChoiceStrip(orientation, new LinearLayoutParams(stripSize, WRAP_CONTENT)); tabStrip_->SetTopTabs(true); @@ -311,7 +311,6 @@ private: ChoiceStrip *tabStrip_; - Orientation orientation_; float stripSize_; int currentTab_; std::vector tabs_; From c958ca6b4c05364c1c2a4e3eda5b355328ec8049 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 18 Dec 2014 22:50:17 +0100 Subject: [PATCH 1302/1445] Add version argument to NativeGetAppInfo --- android/app-android.cpp | 7 ++++--- base/NativeApp.h | 2 +- base/PCMain.cpp | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 6cc307ec3c..38f0e5c55d 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -144,9 +144,9 @@ std::string GetJavaString(JNIEnv *env, jstring jstr) { // This is now only used as a trigger for GetAppInfo as a function to all before Init. // On Android we don't use any of the values it returns. extern "C" jboolean Java_com_henrikrydgard_libnative_NativeApp_isLandscape(JNIEnv *env, jclass) { - std::string app_name, app_nice_name; + std::string app_name, app_nice_name, version; bool landscape; - NativeGetAppInfo(&app_name, &app_nice_name, &landscape); + NativeGetAppInfo(&app_name, &app_nice_name, &landscape, &version); return landscape; } @@ -210,11 +210,12 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init std::string app_name; std::string app_nice_name; + std::string version; bool landscape; net::Init(); - NativeGetAppInfo(&app_name, &app_nice_name, &landscape); + NativeGetAppInfo(&app_name, &app_nice_name, &landscape, &version); // If shortcut_param is not empty, pass it as additional varargs argument to NativeInit() method. diff --git a/base/NativeApp.h b/base/NativeApp.h index d86c3561b7..16b69cc93c 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -16,7 +16,7 @@ struct AxisInput; // The first function to get called, just write strings to the two pointers. // This might get called multiple times in some implementations, you must be able to handle that. -void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape); +void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape, std::string *version); // Generic host->C++ messaging, used for functionality like system-native popup input boxes. void NativeMessageReceived(const char *message, const char *value); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index d97f977354..e16691ce0a 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -393,8 +393,9 @@ int main(int argc, char *argv[]) { std::string app_name; std::string app_name_nice; + std::string version; bool landscape; - NativeGetAppInfo(&app_name, &app_name_nice, &landscape); + NativeGetAppInfo(&app_name, &app_name_nice, &landscape, &version); net::Init(); From 9eceb70492d5959b909af2be850a5636ec6e5be1 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Thu, 18 Dec 2014 23:57:59 +0100 Subject: [PATCH 1303/1445] Pass -D SDL when SDL is used --- base/QtMain.cpp | 10 +++++----- base/QtMain.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 992e67f1ae..629ccd061c 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -25,7 +25,7 @@ #include #include "SymbianMediaKeys.h" #endif -#ifdef QT_HAS_SDL +#ifdef SDL #include "SDL/SDLJoystick.h" #include "SDL_audio.h" #endif @@ -36,7 +36,7 @@ InputState* input_state; -#ifdef QT_HAS_SDL +#ifdef SDL extern void mixaudio(void *userdata, Uint8 *stream, int len) { NativeMix((short *)stream, len / 4); } @@ -135,7 +135,7 @@ static int mainInternal(QApplication &a) ssObject.setScreenSaverEnabled(false); #endif -#ifdef QT_HAS_SDL +#ifdef SDL SDLJoystick joy(true); joy.startEventLoop(); SDL_Init(SDL_INIT_AUDIO); @@ -170,7 +170,7 @@ static int mainInternal(QApplication &a) return a.exec(); } -#ifndef QT_HAS_SDL +#ifndef SDL Q_DECL_EXPORT #endif int main(int argc, char *argv[]) @@ -219,7 +219,7 @@ int main(int argc, char *argv[]) exit(0); #endif NativeShutdownGraphics(); -#ifdef QT_HAS_SDL +#ifdef SDL SDL_PauseAudio(1); SDL_CloseAudio(); #endif diff --git a/base/QtMain.h b/base/QtMain.h index c966315d28..a59cf5a2a0 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -7,7 +7,7 @@ #include "gfx_es2/glsl_program.h" #include -#ifndef QT_HAS_SDL +#ifndef SDL #include #include #endif @@ -235,7 +235,7 @@ private: static MainUI* emugl = NULL; -#ifndef QT_HAS_SDL +#ifndef SDL // Audio #define AUDIO_FREQ 44100 @@ -294,7 +294,7 @@ private: int timer; }; -#endif //QT_HAS_SDL +#endif //SDL #endif From c3538f46dc703eef6d6f2bda2b5df04f994a8817 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Dec 2014 01:18:39 -0800 Subject: [PATCH 1304/1445] Add methods to translate and scale in one go. Should be faster than involving a matrix mul at all. Probably could SSE this by extending scale and trans by 1 and 0 in either order. --- math/lin/matrix4x4.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/math/lin/matrix4x4.h b/math/lin/matrix4x4.h index 00c9074486..d56906d1f2 100644 --- a/math/lin/matrix4x4.h +++ b/math/lin/matrix4x4.h @@ -73,6 +73,13 @@ public: wy = trans.y; wz = trans.z; } + void setTranslationAndScaling(const Vec3 &trans, const Vec3 &scale) { + setScaling(scale); + wx = trans.x; + wy = trans.y; + wz = trans.z; + } + Matrix4x4 inverse() const; Matrix4x4 simpleInverse() const; Matrix4x4 transpose() const; @@ -141,6 +148,24 @@ public: void toText(char *buffer, int len) const; void print() const; static Matrix4x4 fromPRS(const Vec3 &position, const Quaternion &normal, const Vec3 &scale); + + void translateAndScale(const Vec3 &trans, const Vec3 &scale) { + xx = xx * scale.x + xw * trans.x; + xy = xy * scale.y + xw * trans.y; + xz = xz * scale.z + xw * trans.z; + + yx = yx * scale.x + yw * trans.x; + yy = yy * scale.y + yw * trans.y; + yz = yz * scale.z + yw * trans.z; + + zx = zx * scale.x + zw * trans.x; + zy = zy * scale.y + zw * trans.y; + zz = zz * scale.z + zw * trans.z; + + wx = wx * scale.x + ww * trans.x; + wy = wy * scale.y + ww * trans.y; + wz = wz * scale.z + ww * trans.z; + } }; #endif // _MATH_LIN_MATRIX4X4_H From b71dcc352e715f82fb9219f024812545308f5511 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Dec 2014 09:14:20 -0800 Subject: [PATCH 1305/1445] Fix some snprintf() usage. --- math/lin/matrix4x4.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/math/lin/matrix4x4.cpp b/math/lin/matrix4x4.cpp index f96fd871f4..d90dc957ab 100644 --- a/math/lin/matrix4x4.cpp +++ b/math/lin/matrix4x4.cpp @@ -2,6 +2,7 @@ #include +#include "base/compat.h" #include "math/lin/vec3.h" #include "math/lin/quat.h" #include "math/fast/fast_matrix.h" @@ -250,9 +251,7 @@ Matrix4x4 Matrix4x4::fromPRS(const Vec3 &positionv, const Quaternion &rotv, cons newM.wz = positionv.z; return newM; } -#if _MSC_VER -#define snprintf _snprintf -#endif + void Matrix4x4::toText(char *buffer, int len) const { snprintf(buffer, len, "%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", xx,xy,xz,xw, From 561de790d84abb33a39d3d9ca60ed51db65e227d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Dec 2014 09:14:33 -0800 Subject: [PATCH 1306/1445] Fix an incorrect unsigned compare. --- ext/stb_vorbis/stb_vorbis.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index f7989b0a2a..1c2f8ff31f 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -1026,7 +1026,7 @@ static int capture_pattern(vorb *f) static int start_page_no_capturepattern(vorb *f) { - uint32 loc0,loc1,n,i; + uint32 loc0,loc1,n; // stream structure version if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version); // header flag @@ -1050,6 +1050,7 @@ static int start_page_no_capturepattern(vorb *f) // assume we _don't_ know any the sample position of any segments f->end_seg_with_known_loc = -2; if (loc0 != ~0 || loc1 != ~0) { + int i; // determine which packet is the last one that will complete for (i=f->segment_count-1; i >= 0; --i) if (f->segments[i] < 255) From 614ae52eb85131c8c1efe96f08d69d7df2653ad6 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Dec 2014 09:37:39 -0800 Subject: [PATCH 1307/1445] Quiet some warnings in externals. We're not very worried about these anyway. Better to not have the spam. --- ext/libpng17/pngread.c | 5 +++++ ext/libpng17/pngtest.c | 5 +++++ ext/libpng17/pngwrite.c | 5 +++++ ext/libzip/zip_add_dir.c | 7 +++++-- ext/libzip/zip_close.c | 24 ++++++++++++++---------- ext/libzip/zip_dirent.c | 5 ++++- ext/libzip/zip_error_strerror.c | 7 +++++-- ext/libzip/zip_error_to_str.c | 5 ++++- ext/libzip/zip_filerange_crc.c | 10 +++++++--- ext/libzip/zip_fopen_index.c | 11 ++++++++--- ext/libzip/zip_fread.c | 14 +++++++++----- ext/libzip/zip_open.c | 7 +++++-- ext/libzip/zip_set_name.c | 5 ++++- ext/libzip/zip_source_buffer.c | 2 +- ext/libzip/zip_source_filep.c | 10 +++++++--- ext/libzip/zip_source_zip.c | 7 +++++-- ext/stb_vorbis/stb_vorbis.c | 2 ++ 17 files changed, 95 insertions(+), 36 deletions(-) diff --git a/ext/libpng17/pngread.c b/ext/libpng17/pngread.c index 6a6058f0cf..cec1144451 100644 --- a/ext/libpng17/pngread.c +++ b/ext/libpng17/pngread.c @@ -14,6 +14,11 @@ * read a PNG file or stream. */ +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif + #include "pngpriv.h" #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) # include diff --git a/ext/libpng17/pngtest.c b/ext/libpng17/pngtest.c index 75feb8e1b2..9add642142 100644 --- a/ext/libpng17/pngtest.c +++ b/ext/libpng17/pngtest.c @@ -31,6 +31,11 @@ * of files at once by typing "pngtest -m file1.png file2.png ..." */ +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif + #define _POSIX_SOURCE 1 #include diff --git a/ext/libpng17/pngwrite.c b/ext/libpng17/pngwrite.c index 1c91697f37..b43a16fc07 100644 --- a/ext/libpng17/pngwrite.c +++ b/ext/libpng17/pngwrite.c @@ -11,6 +11,11 @@ * and license in png.h */ +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif + #include "pngpriv.h" #if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) # include diff --git a/ext/libzip/zip_add_dir.c b/ext/libzip/zip_add_dir.c index 493e28ddab..a058640c1e 100644 --- a/ext/libzip/zip_add_dir.c +++ b/ext/libzip/zip_add_dir.c @@ -31,7 +31,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include #include @@ -53,7 +56,7 @@ zip_add_dir(struct zip *za, const char *name) } s = NULL; - len = strlen(name); + len = (int)strlen(name); if (name[len-1] != '/') { if ((s=(char *)malloc(len+2)) == NULL) { diff --git a/ext/libzip/zip_close.c b/ext/libzip/zip_close.c index 5fca55a404..902303a3f9 100644 --- a/ext/libzip/zip_close.c +++ b/ext/libzip/zip_close.c @@ -31,20 +31,24 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include #include #include -#ifdef HAVE_STRINGS_H -#include -#endif #include #include #include #include "zipint.h" +#ifdef HAVE_STRINGS_H +#include +#endif + static int add_data(struct zip *, struct zip_source *, struct zip_dirent *, FILE *); static int add_data_comp(zip_source_callback, void *, struct zip_stat *, @@ -196,7 +200,7 @@ zip_close(struct zip *za) } else { de.filename = strdup(za->cdir->entry[i].filename); - de.filename_len = strlen(de.filename); + de.filename_len = (unsigned short)strlen(de.filename); cd->entry[j].filename = za->cdir->entry[i].filename; cd->entry[j].filename_len = de.filename_len; } @@ -230,7 +234,7 @@ zip_close(struct zip *za) error = 1; break; } - de.filename_len = strlen(de.filename); + de.filename_len = (unsigned short)strlen(de.filename); cd->entry[j].filename = za->entry[i].ch_filename; cd->entry[j].filename_len = de.filename_len; } @@ -517,7 +521,7 @@ add_data_uncomp(struct zip *za, zip_source_callback cb, void *ud, zstr.next_out = (Bytef *)b2; zstr.avail_out = sizeof(b2); - st->comp_size += n2; + st->comp_size += (off_t)n2; } if (ret == Z_STREAM_END) { @@ -552,7 +556,7 @@ static int copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error) { char buf[BUFSIZE]; - int n, nn; + ssize_t n, nn; if (len == 0) return 0; @@ -568,12 +572,12 @@ copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error) return -1; } - if (fwrite(buf, 1, n, ft) != (size_t)n) { + if (fwrite(buf, 1, n, ft) != n) { _zip_error_set(error, ZIP_ER_WRITE, errno); return -1; } - len -= n; + len -= (off_t)n; } return 0; diff --git a/ext/libzip/zip_dirent.c b/ext/libzip/zip_dirent.c index d15b376bad..d0ae6ad1cb 100644 --- a/ext/libzip/zip_dirent.c +++ b/ext/libzip/zip_dirent.c @@ -31,7 +31,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include #include diff --git a/ext/libzip/zip_error_strerror.c b/ext/libzip/zip_error_strerror.c index 3d0951cfb1..d7f7d0ea9a 100644 --- a/ext/libzip/zip_error_strerror.c +++ b/ext/libzip/zip_error_strerror.c @@ -31,7 +31,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include #include @@ -40,7 +43,7 @@ #include "zipint.h" - + const char * _zip_error_strerror(struct zip_error *err) diff --git a/ext/libzip/zip_error_to_str.c b/ext/libzip/zip_error_to_str.c index bdba41a6cb..4eea045662 100644 --- a/ext/libzip/zip_error_to_str.c +++ b/ext/libzip/zip_error_to_str.c @@ -31,7 +31,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include #include diff --git a/ext/libzip/zip_filerange_crc.c b/ext/libzip/zip_filerange_crc.c index 4d1ad56692..4da727b337 100644 --- a/ext/libzip/zip_filerange_crc.c +++ b/ext/libzip/zip_filerange_crc.c @@ -31,7 +31,11 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include #include @@ -62,9 +66,9 @@ _zip_filerange_crc(FILE *fp, off_t start, off_t len, uLong *crcp, return -1; } - *crcp = crc32(*crcp, buf, n); + *crcp = crc32(*crcp, buf, (uInt)n); - len-= n; + len-= (off_t)n; } return 0; diff --git a/ext/libzip/zip_fopen_index.c b/ext/libzip/zip_fopen_index.c index a330d697d2..ea4a68acf7 100644 --- a/ext/libzip/zip_fopen_index.c +++ b/ext/libzip/zip_fopen_index.c @@ -31,7 +31,11 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif + #include #include @@ -141,7 +145,8 @@ zip_fopen_index(struct zip *za, int fileno, int flags) int _zip_file_fillbuf(void *buf, size_t buflen, struct zip_file *zf) { - int i, j; + ssize_t i; + int j; if (zf->error.zip_err != ZIP_ER_OK) return -1; @@ -158,7 +163,7 @@ _zip_file_fillbuf(void *buf, size_t buflen, struct zip_file *zf) else i = zf->cbytes_left; - j = fread(buf, 1, i, zf->za->zp); + j = (int)fread(buf, 1, i, zf->za->zp); if (j == 0) { _zip_error_set(&zf->error, ZIP_ER_EOF, 0); j = -1; diff --git a/ext/libzip/zip_fread.c b/ext/libzip/zip_fread.c index 2a7fb42c78..036e87c547 100644 --- a/ext/libzip/zip_fread.c +++ b/ext/libzip/zip_fread.c @@ -31,11 +31,15 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include "zipint.h" - + ZIP_EXTERN ssize_t zip_fread(struct zip_file *zf, void *outbuf, size_t toread) @@ -75,7 +79,7 @@ zip_fread(struct zip_file *zf, void *outbuf, size_t toread) } zf->zstr->next_out = (Bytef *)outbuf; - zf->zstr->avail_out = toread; + zf->zstr->avail_out = (uInt)toread; out_before = zf->zstr->total_out; /* endless loop until something has been accomplished */ @@ -99,8 +103,8 @@ zip_fread(struct zip_file *zf, void *outbuf, size_t toread) len = zf->zstr->total_out - out_before; if (len >= zf->bytes_left || len >= toread) { if (zf->flags & ZIP_ZF_CRC) - zf->crc = crc32(zf->crc, (Bytef *)outbuf, len); - zf->bytes_left -= len; + zf->crc = crc32(zf->crc, (Bytef *)outbuf, (uInt)len); + zf->bytes_left -= (unsigned long)len; return len; } break; diff --git a/ext/libzip/zip_open.c b/ext/libzip/zip_open.c index 19227cfc20..fee8a9c61c 100644 --- a/ext/libzip/zip_open.c +++ b/ext/libzip/zip_open.c @@ -31,7 +31,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include #include @@ -521,7 +524,7 @@ _zip_find_central_dir(FILE *fp, int flags, int *zep, off_t len) } clearerr(fp); - buflen = fread(buf, 1, CDBUFSIZE, fp); + buflen = (int)fread(buf, 1, CDBUFSIZE, fp); if (ferror(fp)) { set_error(zep, NULL, ZIP_ER_READ); diff --git a/ext/libzip/zip_set_name.c b/ext/libzip/zip_set_name.c index 5c7da3d7c5..65b60a65cb 100644 --- a/ext/libzip/zip_set_name.c +++ b/ext/libzip/zip_set_name.c @@ -31,7 +31,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include #include diff --git a/ext/libzip/zip_source_buffer.c b/ext/libzip/zip_source_buffer.c index 1e9121c560..1f24a1642e 100644 --- a/ext/libzip/zip_source_buffer.c +++ b/ext/libzip/zip_source_buffer.c @@ -124,7 +124,7 @@ read_data(void *state, void *data, size_t len, enum zip_source_cmd cmd) zip_stat_init(st); st->mtime = z->mtime; - st->size = z->end - z->data; + st->size = (off_t)(z->end - z->data); return sizeof(*st); } diff --git a/ext/libzip/zip_source_filep.c b/ext/libzip/zip_source_filep.c index 5373934102..e81a9df193 100644 --- a/ext/libzip/zip_source_filep.c +++ b/ext/libzip/zip_source_filep.c @@ -31,7 +31,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include #include @@ -115,7 +118,8 @@ read_file(void *state, void *data, size_t len, enum zip_source_cmd cmd) { struct read_file *z; char *buf; - int i, n; + ssize_t i; + size_t n; z = (struct read_file *)state; buf = (char *)data; @@ -151,7 +155,7 @@ read_file(void *state, void *data, size_t len, enum zip_source_cmd cmd) } if (z->remain != -1) - z->remain -= i; + z->remain -= (off_t)i; return i; diff --git a/ext/libzip/zip_source_zip.c b/ext/libzip/zip_source_zip.c index 3eef552a23..e2e128e0f6 100644 --- a/ext/libzip/zip_source_zip.c +++ b/ext/libzip/zip_source_zip.c @@ -31,7 +31,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#ifdef _MSC_VER +#pragma warning (disable:4996) +#pragma warning (disable:4244) +#endif #include #include @@ -120,7 +123,7 @@ read_zip(void *state, void *data, size_t len, enum zip_source_cmd cmd) { struct read_zip *z; char b[8192], *buf; - int i, n; + ssize_t i, n; z = (struct read_zip *)state; buf = (char *)data; diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index 1c2f8ff31f..5e8e397b58 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -15,6 +15,8 @@ #pragma warning (disable:4996) #pragma warning (disable:4244) #include +#else +#include #endif // Todo: From a392902175d2f57adeb2d5d301baf1c73f7b5ba4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Dec 2014 09:39:37 -0800 Subject: [PATCH 1308/1445] thin3d: Bind index buffer in GL. Pretty sure this is right. --- thin3d/thin3d_gl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 530a3bd9ea..bce0f94f55 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -692,6 +692,7 @@ void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DGLVertexFormat *fmt = static_cast(format); vbuf->Bind(); + ibuf->Bind(); fmt->Apply(); pipe->Apply(); From 738c99e77803e7ca5227fbc2af940b213e840876 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Dec 2014 09:40:03 -0800 Subject: [PATCH 1309/1445] thin3d: Log an unexpected case. --- thin3d/thin3d_gl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index bce0f94f55..92e8b3c30a 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -752,6 +752,8 @@ void Thin3DGLVertexFormat::Apply() { case UNORM8x4: glVertexAttribPointer(components_[i].semantic, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride_, (void *)(intptr_t)components_[i].offset); break; + case INVALID: + ELOG("Thin3DGLVertexFormat: Invalid component type applied."); } } } From 07b8637adaf4b4e251bd1146ee861a7babb0716a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Dec 2014 00:01:16 -0800 Subject: [PATCH 1310/1445] Fix a bitwise precedence warning. --- ext/cityhash/city.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 4e088af1c8..640c831fd7 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -87,18 +87,18 @@ static uint32 UNALIGNED_LOAD32(const char *p) { #endif #else -#define bswap_32(x) (0 | ((x & 0x000000ff) << 24) \ - | ((x & 0x0000ff00) << 8) \ - | ((x & 0x00ff0000) >> 8) \ - | ((x & 0xff000000) >> 24)) -#define bswap_64(x) (0 | ((x & UINT64_C(0x00000000000000ff)) << 56) \ - | ((x & UINT64_C(0x000000000000ff00)) << 40) \ - | ((x & UINT64_C(0x0000000000ff0000)) << 24) \ - | ((x & UINT64_C(0x00000000ff000000)) << 8) \ - | ((x & UINT64_C(0x000000ff00000000)) >> 8) \ - | ((x & UINT64_C(0x0000ff0000000000)) >> 24) \ - | ((x & UINT64_C(0x00ff000000000000)) >> 40) \ - | ((x & UINT64_C(0xff00000000000000)) >> 56)) +#define bswap_32(x) (0 | (((x) & 0x000000ff) << 24) \ + | (((x) & 0x0000ff00) << 8) \ + | (((x) & 0x00ff0000) >> 8) \ + | (((x) & 0xff000000) >> 24)) +#define bswap_64(x) (0 | (((x) & UINT64_C(0x00000000000000ff)) << 56) \ + | (((x) & UINT64_C(0x000000000000ff00)) << 40) \ + | (((x) & UINT64_C(0x0000000000ff0000)) << 24) \ + | (((x) & UINT64_C(0x00000000ff000000)) << 8) \ + | (((x) & UINT64_C(0x000000ff00000000)) >> 8) \ + | (((x) & UINT64_C(0x0000ff0000000000)) >> 24) \ + | (((x) & UINT64_C(0x00ff000000000000)) >> 40) \ + | (((x) & UINT64_C(0xff00000000000000)) >> 56)) #endif #ifdef WORDS_BIGENDIAN From f20e05bb4cf58d76fe17545ea15e8eaa6fd8b7db Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Dec 2014 00:02:08 -0800 Subject: [PATCH 1311/1445] Fix an undefined pragma warning on non-msvc. --- ext/rg_etc1/rg_etc1.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/rg_etc1/rg_etc1.cpp b/ext/rg_etc1/rg_etc1.cpp index 7a5fce713e..e003f14863 100644 --- a/ext/rg_etc1/rg_etc1.cpp +++ b/ext/rg_etc1/rg_etc1.cpp @@ -17,7 +17,9 @@ //#include #include +#ifdef _MSC_VER #pragma warning (disable: 4201) // nonstandard extension used : nameless struct/union +#endif #if defined(_DEBUG) || defined(DEBUG) #define RG_ETC1_BUILD_DEBUG From 10fbb0f6ef8a057496607d9eabc981323de75fbe Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Dec 2014 10:21:58 -0800 Subject: [PATCH 1312/1445] Silence some type conversion warnings. --- ext/cityhash/city.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 640c831fd7..329111c9a8 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -183,11 +183,11 @@ static uint32 Hash32Len0to4(const char *s, size_t len) { b = b * c1 + v; c ^= b; } - return fmix(Mur(b, Mur(len, c))); + return fmix(Mur(b, Mur((uint32)len, c))); } static uint32 Hash32Len5to12(const char *s, size_t len) { - uint32 a = len, b = len * 5, c = 9, d = b; + uint32 a = (uint32)len, b = (uint32)len * 5, c = 9, d = b; a += Fetch32(s); b += Fetch32(s + len - 4); c += Fetch32(s + ((len >> 1) & 4)); @@ -202,7 +202,7 @@ uint32 CityHash32(const char *s, size_t len) { } // len > 24 - uint32 h = len, g = c1 * len, f = g; + uint32 h = (uint32)len, g = c1 * (uint32)len, f = g; uint32 a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2; uint32 a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2; uint32 a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2; @@ -307,7 +307,7 @@ static uint64 HashLen0to16(const char *s, size_t len) { uint8 b = s[len >> 1]; uint8 c = s[len - 1]; uint32 y = static_cast(a) + (static_cast(b) << 8); - uint32 z = len + (static_cast(c) << 2); + uint32 z = (uint32)len + (static_cast(c) << 2); return ShiftMix(y * k2 ^ z * k0) * k2; } return k2; @@ -425,7 +425,7 @@ static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { uint64 b = Uint128High64(seed); uint64 c = 0; uint64 d = 0; - signed long l = len - 16; + signed long l = (signed long)len - 16; if (l <= 0) { // len <= 16 a = ShiftMix(a * k1) * k1; c = b * k1 + HashLen0to16(s, len); From 6fc70b1679b4a29e61c53a75841938484e043339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 23 Dec 2014 08:57:23 +0100 Subject: [PATCH 1313/1445] ARM64 buildfix (not sure why needed though) --- gfx_es2/gl_state.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 26fa639ac6..293a28d03b 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -36,10 +36,12 @@ typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); extern PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV; +#ifndef ARM64 typedef void (EGLAPIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) ( GLint srcX0, GLint srcY0, GLint srcX1, GLuint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLuint dstY1, GLint mask, GLenum filter); +#endif extern PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV; extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; From c7a74ef796d127a65b678bd57e9ee8943c161ce8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 25 Dec 2014 19:30:24 -0800 Subject: [PATCH 1314/1445] Make a parent class destructor virtual. --- thread/threadpool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thread/threadpool.h b/thread/threadpool.h index 7647f64d25..0a2a2f9722 100644 --- a/thread/threadpool.h +++ b/thread/threadpool.h @@ -10,7 +10,7 @@ class WorkerThread { public: WorkerThread(); - ~WorkerThread(); + virtual ~WorkerThread(); // submit a new work item void Process(const std::function& work); From edb0203cfba7a7d9acb1a626376922f098864a75 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 25 Dec 2014 19:43:06 -0800 Subject: [PATCH 1315/1445] Symbian doesn't have alloca.h. --- ext/stb_vorbis/stb_vorbis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index 5e8e397b58..e508af2775 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -15,7 +15,7 @@ #pragma warning (disable:4996) #pragma warning (disable:4244) #include -#else +#elif !defined(__SYMBIAN32__) #include #endif From 826b12bb70515dcd0d1c1dca9d388646bc36c407 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 29 Dec 2014 10:06:19 -0800 Subject: [PATCH 1316/1445] Tiny optimization for real_time_now() on win. --- base/timeutil.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/base/timeutil.cpp b/base/timeutil.cpp index c9df4901db..bab362cc41 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -18,18 +18,21 @@ static float curtime_f = 0; #ifdef _WIN32 -__int64 _frequency = 0; -__int64 _starttime = 0; +LARGE_INTEGER frequency; +double frequencyMult; +LARGE_INTEGER startTime; double real_time_now() { - if (_frequency == 0) { - QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); - QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); - curtime=0; + if (frequency.QuadPart == 0) { + QueryPerformanceFrequency(&frequency); + QueryPerformanceCounter(&startTime); + curtime = 0.0; + frequencyMult = 1.0 / static_cast(frequency.QuadPart); } - __int64 time; - QueryPerformanceCounter((LARGE_INTEGER*)&time); - return ((double) (time - _starttime) / (double) _frequency); + LARGE_INTEGER time; + QueryPerformanceCounter(&time); + double elapsed = static_cast(time.QuadPart - startTime.QuadPart); + return elapsed * frequencyMult; } #elif defined(BLACKBERRY) From 6562ae4ebcd16380b937724d4a2086adf4613ac4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 30 Dec 2014 10:06:09 -0800 Subject: [PATCH 1317/1445] Minor warning fixes. --- base/stringutil.cpp | 2 +- ext/libzip/mkstemp.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/base/stringutil.cpp b/base/stringutil.cpp index 848993349e..f5a2675b18 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -38,7 +38,7 @@ void OutputDebugStringUTF8(const char *p) { #endif void StringTrimEndNonAlphaNum(char *str) { - int n = strlen(str); + ssize_t n = strlen(str); while (!isalnum(str[n]) && n >= 0) { str[n--] = '\0'; } diff --git a/ext/libzip/mkstemp.c b/ext/libzip/mkstemp.c index 62641f0af3..0dbaaf0572 100644 --- a/ext/libzip/mkstemp.c +++ b/ext/libzip/mkstemp.c @@ -61,7 +61,9 @@ _zip_mkstemp(wchar_t *path) _zip_mkstemp(char *path) #endif { +#ifndef _WIN32 int fd; +#endif #ifdef UNICODE wchar_t *start, *trv; struct _stat sbuf; From 99c930d6d3883d00d9afa270e7d7c55674a98128 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 30 Dec 2014 10:19:09 -0800 Subject: [PATCH 1318/1445] Try harder to get 64-bit sizes in GetSize(). Fixes a warning too. --- file/file_util.cpp | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index 73cecc9d4b..b58ced1150 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -5,6 +5,8 @@ #ifndef strcasecmp #define strcasecmp _stricmp #endif +#define fseeko _fseeki64 +#define ftello _ftelli64 #else #include #include @@ -85,18 +87,31 @@ bool writeDataToFile(bool text_file, const void* data, const unsigned int size, uint64_t GetSize(FILE *f) { - // can't use off_t here because it can be 32-bit - size_t pos = ftell(f); - if (fseek(f, 0, SEEK_END) != 0) { - return 0; - } - size_t size = ftell(f); - // Reset the seek position to where it was when we started. - if ((size != pos) && (fseek(f, pos, SEEK_SET) != 0)) { - // Should error here + // This will only support 64-bit when large file support is available. + // That won't be the case on some versions of Android, at least. +#if defined(ANDROID) || (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64) + int fd = fileno(f); + + off64_t pos = lseek64(fd, 0, SEEK_CUR); + off64_t size = lseek64(fd, 0, SEEK_END); + if (size != pos && lseek64(fd, pos, SEEK_SET) != pos) { + // Should error here. return 0; } return size; +#else + uint64_t pos = ftello(f); + if (fseek(f, 0, SEEK_END) != 0) { + return 0; + } + uint64_t size = ftello(f); + // Reset the seek position to where it was when we started. + if (size != pos && fseeko(f, pos, SEEK_SET) != 0) { + // Should error here. + return 0; + } + return size; +#endif } bool readFileToString(bool text_file, const char *filename, std::string &str) From 33e00b5c2e24980a18741079e2913b92bed5dd30 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 31 Dec 2014 11:23:10 +0100 Subject: [PATCH 1319/1445] UI: Get rid of "ImageFileView" which uses non-thin3d-compatible textures. --- ui/view.cpp | 34 ---------------------------------- ui/view.h | 14 -------------- 2 files changed, 48 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index a70985ba83..b15133090d 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -558,40 +558,6 @@ void Thin3DTextureView::Draw(UIContext &dc) { } } -ImageFileView::ImageFileView(std::string filename, ImageSizeMode sizeMode, LayoutParams *layoutParams) - : InertView(layoutParams), color_(0xFFFFFFFF), sizeMode_(sizeMode) { - texture_ = new Texture(); - if (!texture_->Load(filename.c_str())) { - ELOG("Failed to load texture %s", filename.c_str()); - } -} - -ImageFileView::~ImageFileView() { - delete texture_; -} - -void ImageFileView::Draw(UIContext &dc) { - // TODO: involve sizemode - if (texture_) { - dc.Flush(); - texture_->Bind(0); - dc.Draw()->Rect(bounds_.x, bounds_.y, bounds_.w, bounds_.h, color_); - dc.Flush(); - dc.RebindTexture(); - } -} - -void ImageFileView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - // TODO: involve sizemode - if (texture_) { - w = (float)texture_->Width(); - h = (float)texture_->Height(); - } else { - w = 16; - h = 16; - } -} - void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { dc.MeasureText(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont, text_.c_str(), &w, &h); } diff --git a/ui/view.h b/ui/view.h index 74949ae1b7..ebf1b01a82 100644 --- a/ui/view.h +++ b/ui/view.h @@ -749,20 +749,6 @@ private: ImageSizeMode sizeMode_; }; -// ImageFileView takes a filename and keeps track of the texture by itself. -class ImageFileView : public InertView { -public: - ImageFileView(std::string filename, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0); - ~ImageFileView(); - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; - virtual void Draw(UIContext &dc); - -private: - Texture *texture_; - uint32_t color_; - ImageSizeMode sizeMode_; -}; - class ProgressBar : public InertView { public: ProgressBar(LayoutParams *layoutParams = 0) From b891268d60418a7a2501cc5cc8b1cf6f7b483cd3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 31 Dec 2014 15:28:14 +0100 Subject: [PATCH 1320/1445] Clean up texture loading in thin3D a bit --- thin3d/thin3d.cpp | 133 +++++++++++++++++++++++++++------------------- ui/view.h | 2 + 2 files changed, 79 insertions(+), 56 deletions(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 304effc907..c7de1ce947 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -5,6 +5,7 @@ #include "image/zim_load.h" #include "image/png_load.h" #include "file/vfs.h" +#include "ext/jpge/jpgd.h" static const char * const glsl_fsTexCol = "varying vec4 oColor0;\n" @@ -129,24 +130,85 @@ static T3DImageFormat ZimToT3DFormat(int zim) { } } -bool Thin3DTexture::LoadFromFileData(const uint8_t *data, size_t dataSize, T3DImageType type) { - int width[16], height[16], zim_flags; - uint8_t *image[16] = { nullptr }; +static T3DImageType DetectImageFileType(const uint8_t *data, size_t size) { + if (!memcmp(data, "ZIMG", 4)) { + return ZIM; + } else if (!memcmp(data, "\x89\x50\x4E\x47", 4)) { + return PNG; + } else if (!memcmp(data, "\xff\xd8\xff\xe0", 4)) { + return JPEG; + } else { + return TYPE_UNKNOWN; + } +} - int num_levels = LoadZIMPtr(data, dataSize, width, height, &zim_flags, image); - if (num_levels == 0) { +bool LoadTextureLevels(const uint8_t *data, int size, T3DImageType type, int width[16], int height[16], int *num_levels, T3DImageFormat *fmt, uint8_t *image[16], int *zim_flags) { + if (type == DETECT) { + type = DetectImageFileType(data, size); + } + if (type == TYPE_UNKNOWN) { + ELOG("File has unknown format"); return false; } - T3DImageFormat fmt = ZimToT3DFormat(zim_flags & ZIM_FORMAT_MASK); + *num_levels = 0; + *zim_flags = 0; - // TODO: Cube map / 3D texture / texture array support + switch (type) { + case ZIM: + { + *num_levels = LoadZIMPtr((const uint8_t *)data, size, width, height, zim_flags, image); + *fmt = ZimToT3DFormat(*zim_flags & ZIM_FORMAT_MASK); + } + break; + + case PNG: + if (1 == pngLoadPtr((const unsigned char *)data, size, &width[0], &height[0], &image[0], false)) { + *num_levels = 1; + *fmt = RGBA8888; + } + break; + + case JPEG: + { + int actual_components = 0; + unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(data, size, &width[0], &height[0], &actual_components, 4); + if (jpegBuf) { + *num_levels = 1; + *fmt = RGBA8888; + image[0] = (uint8_t *)jpegBuf; + } + } + break; + + default: + ELOG("Unknown image format"); + return false; + } + + return *num_levels > 0; +} + +bool Thin3DTexture::LoadFromFileData(const uint8_t *data, size_t dataSize, T3DImageType type) { + int width[16], height[16]; + uint8_t *image[16] = { nullptr }; + + int num_levels; + int zim_flags; + T3DImageFormat fmt; + + if (!LoadTextureLevels(data, dataSize, type, width, height, &num_levels, &fmt, image, &zim_flags)) { + return false; + } Create(LINEAR2D, fmt, width[0], height[0], 1, num_levels); - for (int i = 0; i < num_levels; i++) { - SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]); - free(image[i]); + if (image[i]) { + SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]); + free(image[i]); + } else { + ELOG("Missing image level %i", i); + } } Finalize(zim_flags); @@ -177,57 +239,16 @@ Thin3DTexture *Thin3DContext::CreateTextureFromFile(const char *filename, T3DIma return tex; } } - -T3DImageType DetectImageFileType(const uint8_t *data, size_t size) { - if (!memcmp(data, "ZIMG", 4)) { - return ZIM; - } else if (!memcmp(data, "\x89\x50\x4E\x47", 4)) { - return PNG; - } else if (!memcmp(data, "\xff\xd8\xff\xe0", 4)) { - return JPEG; - } else { - return TYPE_UNKNOWN; - } -} - // TODO: Remove the code duplication between this and LoadFromFileData Thin3DTexture *Thin3DContext::CreateTextureFromFileData(const uint8_t *data, int size, T3DImageType type) { - int width[16], height[16], zim_flags = 0; + int width[16], height[16]; + int num_levels = 0; + int zim_flags = 0; + T3DImageFormat fmt; uint8_t *image[16] = { nullptr }; - int num_levels = 0; - T3DImageFormat fmt; - - if (type == DETECT) { - type = DetectImageFileType(data, size); - } - if (type == TYPE_UNKNOWN) { - ELOG("File has unknown format"); - return nullptr; - } - - switch (type) { - case ZIM: - num_levels = LoadZIMPtr((const uint8_t *)data, size, width, height, &zim_flags, image); - fmt = ZimToT3DFormat(zim_flags & ZIM_FORMAT_MASK); - break; - - case PNG: - if (1 != pngLoadPtr((const unsigned char *)data, size, &width[0], &height[0], &image[0], false)) { - return NULL; - } - num_levels = 1; - fmt = RGBA8888; - break; - - default: - ELOG("Unknown image format"); - return nullptr; - } - - if (num_levels == 0) { + if (!LoadTextureLevels(data, size, type, width, height, &num_levels, &fmt, image, &zim_flags)) return NULL; - } Thin3DTexture *tex = CreateTexture(LINEAR2D, fmt, width[0], height[0], 1, num_levels); for (int i = 0; i < num_levels; i++) { diff --git a/ui/view.h b/ui/view.h index ebf1b01a82..544c4a8051 100644 --- a/ui/view.h +++ b/ui/view.h @@ -153,6 +153,8 @@ enum Gravity { G_BOTTOMLEFT = G_BOTTOM | G_LEFT, G_BOTTOMRIGHT = G_BOTTOM | G_RIGHT, + G_CENTER = G_HCENTER | G_VCENTER, + G_VERTMASK = 3 << 2, }; From 823dd6f72ae3da4376b48e84a2abe229d0773028 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 31 Dec 2014 17:11:31 +0100 Subject: [PATCH 1321/1445] Just some logging --- thin3d/thin3d.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index c7de1ce947..593b9f72c5 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -225,6 +225,8 @@ bool Thin3DTexture::LoadFromFile(const std::string &filename, T3DImageType type) bool retval = LoadFromFileData(buffer, fileSize, type); if (retval) { filename_ = filename; + } else { + ELOG("%s: Failed to load texture %s", __FUNCTION__, filename.c_str()); } delete[] buffer; return retval; @@ -235,10 +237,10 @@ Thin3DTexture *Thin3DContext::CreateTextureFromFile(const char *filename, T3DIma if (!tex->LoadFromFile(filename, type)) { tex->Release(); return NULL; - } else { - return tex; } + return tex; } + // TODO: Remove the code duplication between this and LoadFromFileData Thin3DTexture *Thin3DContext::CreateTextureFromFileData(const uint8_t *data, int size, T3DImageType type) { int width[16], height[16]; @@ -247,8 +249,9 @@ Thin3DTexture *Thin3DContext::CreateTextureFromFileData(const uint8_t *data, int T3DImageFormat fmt; uint8_t *image[16] = { nullptr }; - if (!LoadTextureLevels(data, size, type, width, height, &num_levels, &fmt, image, &zim_flags)) + if (!LoadTextureLevels(data, size, type, width, height, &num_levels, &fmt, image, &zim_flags)) { return NULL; + } Thin3DTexture *tex = CreateTexture(LINEAR2D, fmt, width[0], height[0], 1, num_levels); for (int i = 0; i < num_levels; i++) { From 48cbcc9a5e8b68b42587193051b2641523e0835d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 31 Dec 2014 09:36:00 -0800 Subject: [PATCH 1322/1445] Read from sockets using larger, dynamic buffers. 1024 is too small for downloading things. --- base/buffer.cpp | 36 ++++++++++++++++++++++++++---------- base/buffer.h | 2 +- net/http_client.cpp | 8 ++++++-- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index 54d062036d..0bd5c61aab 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -159,27 +159,43 @@ bool Buffer::FlushSocket(uintptr_t sock) { return true; } -bool Buffer::ReadAll(int fd) { - char buf[1024]; +bool Buffer::ReadAll(int fd, int hintSize) { + std::vector buf; + if (hintSize >= 65536 * 16) { + buf.resize(65536); + } else if (hintSize >= 1024 * 16) { + buf.resize(hintSize / 16); + } else { + buf.resize(1024); + } + while (true) { - int retval = recv(fd, buf, sizeof(buf), 0); - if (retval == 0) - return true; - else if (retval < 0) { + int retval = recv(fd, buf.data(), (int)buf.size(), 0); + if (retval == 0) { + break; + } else if (retval < 0) { ELOG("Error reading from buffer: %i", retval); return false; } char *p = Append((size_t)retval); - memcpy(p, buf, retval); + memcpy(p, buf.data(), retval); } return true; } bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress) { - char buf[1024]; + std::vector buf; + if (knownSize >= 65536 * 16) { + buf.resize(65536); + } else if (knownSize >= 1024 * 16) { + buf.resize(knownSize / 16); + } else { + buf.resize(1024); + } + int total = 0; while (true) { - int retval = recv(fd, buf, sizeof(buf), 0); + int retval = recv(fd, buf.data(), (int)buf.size(), 0); if (retval == 0) { return true; } else if (retval < 0) { @@ -187,7 +203,7 @@ bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress) { return false; } char *p = Append((size_t)retval); - memcpy(p, buf, retval); + memcpy(p, buf.data(), retval); total += retval; *progress = (float)total / (float)knownSize; } diff --git a/base/buffer.h b/base/buffer.h index 6021c76699..d98ca94c9f 100644 --- a/base/buffer.h +++ b/base/buffer.h @@ -66,7 +66,7 @@ class Buffer { bool FlushToFile(const char *filename); bool FlushSocket(uintptr_t sock); // Windows portability - bool ReadAll(int fd); + bool ReadAll(int fd, int hintSize = 0); bool ReadAllWithProgress(int fd, int knownSize, float *progress); // < 0: error diff --git a/net/http_client.cpp b/net/http_client.cpp index 2d7dfa0db5..5e77c75624 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -215,7 +215,11 @@ int Client::SendRequestWithData(const char *method, const char *resource, const "%s" "\r\n"; - buffer.Printf(tpl, method, resource, httpVersion_, host_.c_str(), userAgent_, otherHeaders ? otherHeaders : ""); + buffer.Printf(tpl, + method, resource, httpVersion_, + host_.c_str(), + userAgent_, + otherHeaders ? otherHeaders : ""); buffer.Append(data); bool flushed = buffer.FlushSocket(sock()); if (!flushed) { @@ -297,7 +301,7 @@ int Client::ReadResponseEntity(Buffer *readbuf, const std::vector & if (!contentLength || !progress) { // No way to know how far along we are. Let's just not update the progress counter. - if (!readbuf->ReadAll(sock())) + if (!readbuf->ReadAll(sock(), contentLength)) return -1; } else { // Let's read in chunks, updating progress between each. From 49ea91720959f36734cf7bdc3c9e14442ba3e859 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 31 Dec 2014 09:36:51 -0800 Subject: [PATCH 1323/1445] Support ports in Url. --- net/http_client.cpp | 2 +- net/url.cpp | 8 ++++++++ net/url.h | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/net/http_client.cpp b/net/http_client.cpp index 5e77c75624..a3fba7f37c 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -368,7 +368,7 @@ void Download::Do(std::shared_ptr self) { net::AutoInit netInit; http::Client client; - if (!client.Resolve(fileUrl.Host().c_str(), 80)) { + if (!client.Resolve(fileUrl.Host().c_str(), fileUrl.Port())) { ELOG("Failed resolving %s", url_.c_str()); failed_ = true; progress_ = 1.0f; diff --git a/net/url.cpp b/net/url.cpp index 990bf6ce17..522adc6709 100644 --- a/net/url.cpp +++ b/net/url.cpp @@ -20,6 +20,14 @@ void Url::Split() { host_ = url_.substr(colonSlashSlash + 3, sep - colonSlashSlash - 3); resource_ = url_.substr(sep); // include the slash! + size_t portsep = host_.find(':'); + if (portsep != host_.npos) { + port_ = atoi(host_.substr(portsep + 1).c_str()); + host_ = host_.substr(0, portsep); + } else { + port_ = protocol_ == "https" ? 443 : 80; + } + valid_ = protocol_.size() > 1 && host_.size() > 1; } diff --git a/net/url.h b/net/url.h index c796ae46b3..b6621f3b6d 100644 --- a/net/url.h +++ b/net/url.h @@ -176,7 +176,9 @@ public: bool Valid() const { return valid_; } + // Host = Hostname:Port, or just Hostname. std::string Host() const { return host_; } + int Port() const { return port_; } std::string Protocol() const { return protocol_; } std::string Resource() const { return resource_; } @@ -187,6 +189,7 @@ private: std::string host_; std::string resource_; std::string protocol_; + int port_; }; From 9f490ddb0fc0b40ab4e080613ef170f9c30dbf7b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 31 Dec 2014 10:25:50 -0800 Subject: [PATCH 1324/1445] Symbian buildfix. --- base/buffer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/buffer.cpp b/base/buffer.cpp index 0bd5c61aab..da87602a02 100644 --- a/base/buffer.cpp +++ b/base/buffer.cpp @@ -170,7 +170,7 @@ bool Buffer::ReadAll(int fd, int hintSize) { } while (true) { - int retval = recv(fd, buf.data(), (int)buf.size(), 0); + int retval = recv(fd, &buf[0], (int)buf.size(), 0); if (retval == 0) { break; } else if (retval < 0) { @@ -178,7 +178,7 @@ bool Buffer::ReadAll(int fd, int hintSize) { return false; } char *p = Append((size_t)retval); - memcpy(p, buf.data(), retval); + memcpy(p, &buf[0], retval); } return true; } @@ -195,7 +195,7 @@ bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress) { int total = 0; while (true) { - int retval = recv(fd, buf.data(), (int)buf.size(), 0); + int retval = recv(fd, &buf[0], (int)buf.size(), 0); if (retval == 0) { return true; } else if (retval < 0) { @@ -203,7 +203,7 @@ bool Buffer::ReadAllWithProgress(int fd, int knownSize, float *progress) { return false; } char *p = Append((size_t)retval); - memcpy(p, buf.data(), retval); + memcpy(p, &buf[0], retval); total += retval; *progress = (float)total / (float)knownSize; } From 6ec765dcf4a1dd26c99b39961e487b84eedfcf91 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 1 Jan 2015 11:25:13 +0100 Subject: [PATCH 1325/1445] Make thin3d clear color consistent (R/B was swapped between GL and DX) Thanks unknown. --- thin3d/thin3d_d3d9.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index b787fd407b..753468194d 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -638,12 +638,17 @@ void Thin3DDX9Context::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet device_->DrawIndexedPrimitive(primToD3D9[prim], 0, 0, vertexCount, 0, vertexCount / 3); } +static uint32_t SwapRB(uint32_t c) { + return (c & 0xFF00FF00) | ((c >> 16) & 0xFF) | ((c << 16) & 0xFF0000); +} + void Thin3DDX9Context::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) { UINT d3dMask = 0; if (mask & T3DClear::COLOR) d3dMask |= D3DCLEAR_TARGET; if (mask & T3DClear::DEPTH) d3dMask |= D3DCLEAR_ZBUFFER; if (mask & T3DClear::STENCIL) d3dMask |= D3DCLEAR_STENCIL; - device_->Clear(0, NULL, d3dMask, (D3DCOLOR)colorval, depthVal, stencilVal); + + device_->Clear(0, NULL, d3dMask, (D3DCOLOR)SwapRB(colorval), depthVal, stencilVal); } void Thin3DDX9Context::SetScissorEnabled(bool enable) { From 4dce24d05cbe02e8bc711698aca01193f1a36433 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 1 Jan 2015 13:34:32 +0100 Subject: [PATCH 1326/1445] Improve Moga version detection - do it after the connect event. --- android/app-android.cpp | 7 +++++++ .../henrikrydgard/libnative/NativeGLView.java | 16 ++++++++++------ base/NativeApp.h | 1 + 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 38f0e5c55d..7064a246cf 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -43,6 +43,7 @@ std::queue frameCommands; std::string systemName; std::string langRegion; +std::string mogaVersion; static float left_joystick_x_async; static float left_joystick_y_async; @@ -103,6 +104,8 @@ std::string System_GetProperty(SystemProperty prop) { return systemName; case SYSPROP_LANGREGION: // "en_US" return langRegion; + case SYSPROP_MOGA_VERSION: + return mogaVersion; default: return ""; } @@ -519,5 +522,9 @@ extern "C" jboolean JNICALL Java_com_henrikrydgard_libnative_NativeApp_accelerom extern "C" void Java_com_henrikrydgard_libnative_NativeApp_sendMessage(JNIEnv *env, jclass, jstring message, jstring param) { std::string msg = GetJavaString(env, message); std::string prm = GetJavaString(env, param); + + if (msg == "moga") { + mogaVersion = prm; + } NativeMessageReceived(msg.c_str(), prm.c_str()); } diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index ec2cd9dd49..cca8e0fbab 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -32,7 +32,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, super(activity); mActivity = activity; - /* + /*// TODO: This would be nice. if (Build.VERSION.SDK_INT >= 11) { try { Method method_setPreserveEGLContextOnPause = GLSurfaceView.class.getMethod( @@ -57,12 +57,8 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, if (mController.init()) { Log.i(TAG, "MOGA initialized"); mController.setListener(this, new Handler()); - if (mController.getState(Controller.STATE_CURRENT_PRODUCT_VERSION) != Controller.ACTION_VERSION_MOGA) { - Log.i(TAG, "MOGA pro detected"); - isMogaPro = true; - } } else { - Log.i(TAG, "MOGA failed to initialize"); + Log.i(TAG, "MOGA failed to initialize. No moga detected?"); } } @@ -202,12 +198,20 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, switch (state.getAction()) { case StateEvent.ACTION_CONNECTED: Log.i(TAG, "Moga Connected"); + if (mController.getState(Controller.STATE_CURRENT_PRODUCT_VERSION) == Controller.ACTION_VERSION_MOGA) { + NativeApp.sendMessage("moga", "Moga"); + } else { + Log.i(TAG, "MOGA Pro detected"); + isMogaPro = true; + NativeApp.sendMessage("moga", "MogaPro"); + } break; case StateEvent.ACTION_CONNECTING: Log.i(TAG, "Moga Connecting..."); break; case StateEvent.ACTION_DISCONNECTED: Log.i(TAG, "Moga Disconnected (or simply Not connected)"); + NativeApp.sendMessage("moga", ""); break; } break; diff --git a/base/NativeApp.h b/base/NativeApp.h index 16b69cc93c..7c14c0e562 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -130,6 +130,7 @@ enum SystemProperty { SYSPROP_SYSTEMVERSION, SYSPROP_DISPLAY_XRES, SYSPROP_DISPLAY_YRES, + SYSPROP_MOGA_VERSION }; std::string System_GetProperty(SystemProperty prop); From 7f0387a31e6391bc9ae7a87f4fa19be171478a46 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 2 Jan 2015 16:36:18 +0100 Subject: [PATCH 1327/1445] Improves buffer overflow protection in LOG macros. Replaces #250. Also some warning fixes. --- base/logging.h | 24 +++++++++++++++++++----- file/fd_util.cpp | 2 +- net/http_headers.cpp | 2 +- net/http_server.cpp | 2 +- thin3d/thin3d.cpp | 4 ++-- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/base/logging.h b/base/logging.h index e3e968af6b..56676b5d3d 100644 --- a/base/logging.h +++ b/base/logging.h @@ -82,16 +82,30 @@ void OutputDebugStringUTF8(const char *p); #ifdef _WIN32 +#define XLOG_IMPL(type, ...) do {\ + char temp[512]; \ + char *p = temp; \ + int len = snprintf(p, sizeof(temp), type ": %s:%i: ", __FILE__, __LINE__); \ + if (len < sizeof(temp)) { \ + p += len; \ + p += snprintf(p, sizeof(temp) - len - 3, type ": " __VA_ARGS__); \ + if (p > temp + sizeof(temp) - 3) \ + p = temp + sizeof(temp) - 3; \ + p += sprintf(p, "\n"); \ + OutputDebugStringUTF8(temp); \ + } \ +} while (false) + #ifdef _DEBUG -#define DLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "D: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "D: " __VA_ARGS__); if (p > temp + 450) p = temp + 450; p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} +#define DLOG(...) XLOG_IMPL("D", __VA_ARGS__) #else #define DLOG(...) #endif -#define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "I: " __VA_ARGS__); if (p > temp + 450) p = temp + 450; p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} -#define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "W: " __VA_ARGS__); if (p > temp + 450) p = temp + 450; p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} -#define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "E: " __VA_ARGS__); if (p > temp + 450) p = temp + 450; p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);} -#define FLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "F: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "F: " __VA_ARGS__); if (p > temp + 450) p = temp + 450; p += sprintf(p, "\n"); OutputDebugStringUTF8(temp); Crash();} +#define ILOG(...) XLOG_IMPL("I", __VA_ARGS__) +#define WLOG(...) XLOG_IMPL("W", __VA_ARGS__) +#define ELOG(...) XLOG_IMPL("E", __VA_ARGS__) +#define FLOG(...) do {XLOG_IMPL("F", __VA_ARGS__); Crash();} while (false) // TODO: Win32 version using OutputDebugString #else diff --git a/file/fd_util.cpp b/file/fd_util.cpp index 8326fecf94..f8f9fa7e86 100644 --- a/file/fd_util.cpp +++ b/file/fd_util.cpp @@ -54,7 +54,7 @@ ssize_t WriteLine(int fd, const char *vptr, size_t n) { while (nleft > 0) { int nwritten; - if ((nwritten = (int)write(fd, buffer, nleft)) <= 0) { + if ((nwritten = (int)write(fd, buffer, (unsigned int)nleft)) <= 0) { if (errno == EINTR) nwritten = 0; else diff --git a/net/http_headers.cpp b/net/http_headers.cpp index c0cafd6c62..a5f544c05d 100644 --- a/net/http_headers.cpp +++ b/net/http_headers.cpp @@ -113,7 +113,7 @@ int RequestHeader::ParseHttpHeader(const char *buffer) { // Go to after the colon to get the value. buffer = colon + 1; SkipSpace(&buffer); - int value_len = strlen(buffer); + int value_len = (int)strlen(buffer); if (!strcmp(key, "USER-AGENT")) { user_agent = new char[value_len + 1]; diff --git a/net/http_server.cpp b/net/http_server.cpp index a12b9cc5cf..ae95ca7aca 100644 --- a/net/http_server.cpp +++ b/net/http_server.cpp @@ -154,7 +154,7 @@ void Server::HandleRequestDefault(const Request &request) { } ILOG("No handler for '%s', falling back to 404.", request.resource()); const char *payload = "404 not found\r\n"; - request.WriteHttpResponseHeader(404, strlen(payload)); + request.WriteHttpResponseHeader(404, (int)strlen(payload)); request.out_buffer()->Append(payload); } diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index 593b9f72c5..bd6d0f9f9d 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -142,7 +142,7 @@ static T3DImageType DetectImageFileType(const uint8_t *data, size_t size) { } } -bool LoadTextureLevels(const uint8_t *data, int size, T3DImageType type, int width[16], int height[16], int *num_levels, T3DImageFormat *fmt, uint8_t *image[16], int *zim_flags) { +static bool LoadTextureLevels(const uint8_t *data, size_t size, T3DImageType type, int width[16], int height[16], int *num_levels, T3DImageFormat *fmt, uint8_t *image[16], int *zim_flags) { if (type == DETECT) { type = DetectImageFileType(data, size); } @@ -172,7 +172,7 @@ bool LoadTextureLevels(const uint8_t *data, int size, T3DImageType type, int wid case JPEG: { int actual_components = 0; - unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(data, size, &width[0], &height[0], &actual_components, 4); + unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(data, (int)size, &width[0], &height[0], &actual_components, 4); if (jpegBuf) { *num_levels = 1; *fmt = RGBA8888; From 673491e568f605adcfa36b4754833d026041a865 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 2 Jan 2015 17:25:23 +0100 Subject: [PATCH 1328/1445] Whitespace fix --- base/logging.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/logging.h b/base/logging.h index 56676b5d3d..0c96a12d05 100644 --- a/base/logging.h +++ b/base/logging.h @@ -83,7 +83,7 @@ void OutputDebugStringUTF8(const char *p); #ifdef _WIN32 #define XLOG_IMPL(type, ...) do {\ - char temp[512]; \ + char temp[512]; \ char *p = temp; \ int len = snprintf(p, sizeof(temp), type ": %s:%i: ", __FILE__, __LINE__); \ if (len < sizeof(temp)) { \ From fe94cb614672edbb1f82915088ff62ce600038f1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 3 Jan 2015 22:44:41 +0100 Subject: [PATCH 1329/1445] Try not to pass-through back and menu as Android commands if they come from a gamepad. --- android/AndroidManifest.xml | 2 +- .../libnative/InputDeviceState.java | 3 +- .../libnative/NativeActivity.java | 52 ++++++++++++------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 1b9911acf6..f85c5efadd 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionCode="1" android:versionName="1.0" > - + diff --git a/android/src/com/henrikrydgard/libnative/InputDeviceState.java b/android/src/com/henrikrydgard/libnative/InputDeviceState.java index a17ac0cc60..f572c44dee 100644 --- a/android/src/com/henrikrydgard/libnative/InputDeviceState.java +++ b/android/src/com/henrikrydgard/libnative/InputDeviceState.java @@ -12,8 +12,7 @@ import android.view.MotionEvent; public class InputDeviceState { private static final String TAG = "InputDeviceState"; - // DEVICE_ID_PAD_0 from the cpp code. TODO: allocate these sequentially if we get more controllers. - private static int deviceId = 10; + private static final int deviceId = NativeApp.DEVICE_ID_PAD_0; private InputDevice mDevice; private int[] mAxes; diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index e853917687..bf9553a473 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -83,7 +83,7 @@ public class NativeActivity extends Activity { private boolean isXperiaPlay; - // Allow for two connected gamepads but just consider them the same for now. + // Allow for multiple connected gamepads but just consider them the same for now. // Actually this is not entirely true, see the code. InputDeviceState inputPlayerA; InputDeviceState inputPlayerB; @@ -477,9 +477,9 @@ public class NativeActivity extends Activity { return null; } if (inputPlayerA == null) { - Log.i(TAG, "Input player A registered"); - inputPlayerA = new InputDeviceState(device); inputPlayerADesc = getInputDesc(device); + Log.i(TAG, "Input player A registered: desc = " + inputPlayerADesc); + inputPlayerA = new InputDeviceState(device); } if (inputPlayerA.getDevice() == device) { @@ -487,7 +487,7 @@ public class NativeActivity extends Activity { } if (inputPlayerB == null) { - Log.i(TAG, "Input player B registered"); + Log.i(TAG, "Input player B registered: desc = " + getInputDesc(device)); inputPlayerB = new InputDeviceState(device); } @@ -496,7 +496,7 @@ public class NativeActivity extends Activity { } if (inputPlayerC == null) { - Log.i(TAG, "Input player C registered"); + Log.i(TAG, "Input player C registered"); inputPlayerC = new InputDeviceState(device); } @@ -520,9 +520,10 @@ public class NativeActivity extends Activity { if (state == null) { return super.dispatchKeyEvent(event); } - - // Let's let volume and back through to dispatchKeyEvent. + + // Let's let back and menu through to dispatchKeyEvent. boolean passThrough = false; + switch (event.getKeyCode()) { case KeyEvent.KEYCODE_BACK: case KeyEvent.KEYCODE_MENU: @@ -531,19 +532,31 @@ public class NativeActivity extends Activity { default: break; } - - switch (event.getAction()) { - case KeyEvent.ACTION_DOWN: - if (state.onKeyDown(event) && !passThrough) { - return true; - } + + // Don't passthrough back button if gamepad. + int sources = event.getSource(); + switch (sources) { + case InputDevice.SOURCE_GAMEPAD: + case InputDevice.SOURCE_JOYSTICK: + case InputDevice.SOURCE_DPAD: + passThrough = false; break; - - case KeyEvent.ACTION_UP: - if (state.onKeyUp(event) && !passThrough) { - return true; + } + + if (!passThrough) { + switch (event.getAction()) { + case KeyEvent.ACTION_DOWN: + if (state.onKeyDown(event)) { + return true; + } + break; + + case KeyEvent.ACTION_UP: + if (state.onKeyUp(event)) { + return true; + } + break; } - break; } } @@ -602,9 +615,10 @@ public class NativeActivity extends Activity { switch (keyCode) { case KeyEvent.KEYCODE_BACK: if (event.isAltPressed()) { - NativeApp.keyDown(0, 1004, repeat); // special custom keycode + NativeApp.keyDown(0, 1004, repeat); // special custom keycode for the O button on Xperia Play } else if (NativeApp.isAtTopLevel()) { Log.i(TAG, "IsAtTopLevel returned true."); + // Pass through the back event. return super.onKeyDown(keyCode, event); } else { NativeApp.keyDown(0, keyCode, repeat); From 6ee1c8e9ee7b04464dc609e71aa42a98788be7f2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 4 Jan 2015 17:57:52 +0100 Subject: [PATCH 1330/1445] Make sure to disable stencil in UIContext::Begin. Add logic ops to thin3d for completeness. --- thin3d/thin3d.h | 22 ++++++++++++++++++++++ thin3d/thin3d_d3d9.cpp | 1 + thin3d/thin3d_gl.cpp | 28 +++++++++++++++++++++++++++- ui/ui_context.cpp | 1 + 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index e6d1397b48..16492f710b 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -32,6 +32,26 @@ enum T3DComparison : int { ALWAYS, }; +// Had to prefix with LOGIC, too many clashes +enum T3DLogicOp : int { + LOGIC_CLEAR, + LOGIC_SET, + LOGIC_COPY, + LOGIC_COPY_INVERTED, + LOGIC_NOOP, + LOGIC_INVERT, + LOGIC_AND, + LOGIC_NAND, + LOGIC_OR, + LOGIC_NOR, + LOGIC_XOR, + LOGIC_EQUIV, + LOGIC_AND_REVERSE, + LOGIC_AND_INVERTED, + LOGIC_OR_REVERSE, + LOGIC_OR_INVERTED, +}; + enum T3DBlendFactor : int { ZERO, ONE, @@ -251,6 +271,8 @@ struct T3DBlendStateDesc { T3DBlendEquation eqAlpha; T3DBlendFactor srcAlpha; T3DBlendFactor dstAlpha; + bool logicEnabled; + T3DLogicOp logicOp; // int colorMask; }; diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 753468194d..278fa4b490 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -507,6 +507,7 @@ Thin3DBlendState *Thin3DDX9Context::CreateBlendState(const T3DBlendStateDesc &de bs->eqAlpha = blendEqToD3D9[desc.eqAlpha]; bs->srcAlpha = blendFactorToD3D9[desc.srcAlpha]; bs->dstAlpha = blendFactorToD3D9[desc.dstAlpha]; + // Ignore logic ops, we don't support them in D3D9 return bs; } diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 92e8b3c30a..f04935dec4 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -41,6 +41,25 @@ static const unsigned short blendFactorToGL[] = { GL_CONSTANT_COLOR, }; +static const unsigned short logicOpToGL[] = { + GL_CLEAR, + GL_SET, + GL_COPY, + GL_COPY_INVERTED, + GL_NOOP, + GL_INVERT, + GL_AND, + GL_NAND, + GL_OR, + GL_NOR, + GL_XOR, + GL_EQUIV, + GL_AND_REVERSE, + GL_AND_INVERTED, + GL_OR_REVERSE, + GL_OR_INVERTED, +}; + static const unsigned short primToGL[] = { GL_POINTS, GL_LINES, @@ -64,6 +83,8 @@ public: bool enabled; GLuint eqCol, eqAlpha; GLuint srcCol, srcAlpha, dstCol, dstAlpha; + bool logicEnabled; + GLuint logicOp; // int maskBits; // uint32_t fixedColor; @@ -75,7 +96,10 @@ public: // glstate.blendColor.set(fixedColor); #if !defined(USING_GLES2) - glstate.colorLogicOp.disable(); + glstate.colorLogicOp.set(logicEnabled); + if (logicEnabled) { + glstate.logicOp.set(logicOp); + } #endif // glstate.colorMask.set(maskBits & 1, (maskBits >> 1) & 1, (maskBits >> 2) & 1, (maskBits >> 3) & 1); @@ -510,6 +534,8 @@ Thin3DBlendState *Thin3DGLContext::CreateBlendState(const T3DBlendStateDesc &des bs->eqAlpha = blendEqToGL[desc.eqAlpha]; bs->srcAlpha = blendFactorToGL[desc.srcAlpha]; bs->dstAlpha = blendFactorToGL[desc.dstAlpha]; + bs->logicEnabled = desc.logicEnabled; + bs->logicOp = logicOpToGL[desc.logicOp]; return bs; } diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 7dbf2e1381..5aa410c14c 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -41,6 +41,7 @@ void UIContext::Begin() { thin3d_->SetDepthStencilState(depth_); thin3d_->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL); thin3d_->SetTexture(0, uitexture_); + thin3d_->SetScissorEnabled(false); UIBegin(uishader_); } From 3ebd4675091e3d08e0da3ad8d3d66d1adff1697a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 4 Jan 2015 17:59:58 +0100 Subject: [PATCH 1331/1445] ES buildfix --- thin3d/thin3d_gl.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index f04935dec4..d168243404 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -41,6 +41,7 @@ static const unsigned short blendFactorToGL[] = { GL_CONSTANT_COLOR, }; +#ifndef USING_GLES2 static const unsigned short logicOpToGL[] = { GL_CLEAR, GL_SET, @@ -59,6 +60,7 @@ static const unsigned short logicOpToGL[] = { GL_OR_REVERSE, GL_OR_INVERTED, }; +#endif static const unsigned short primToGL[] = { GL_POINTS, @@ -534,8 +536,10 @@ Thin3DBlendState *Thin3DGLContext::CreateBlendState(const T3DBlendStateDesc &des bs->eqAlpha = blendEqToGL[desc.eqAlpha]; bs->srcAlpha = blendFactorToGL[desc.srcAlpha]; bs->dstAlpha = blendFactorToGL[desc.dstAlpha]; +#ifndef USING_GLES2 bs->logicEnabled = desc.logicEnabled; bs->logicOp = logicOpToGL[desc.logicOp]; +#endif return bs; } From 40848ae4b64907fec31b2562fc977c043133a275 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 5 Jan 2015 01:19:49 +0100 Subject: [PATCH 1332/1445] A few UI framework tweaks --- gfx_es2/draw_buffer.cpp | 5 +++++ ui/view.cpp | 9 ++++++++- ui/view.h | 7 +++++-- ui/viewgroup.cpp | 7 +++++++ ui/viewgroup.h | 1 + 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 0816ff8592..4d40531fc3 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -400,6 +400,11 @@ void DrawBuffer::DrawTextRect(int font, const char *text, float x, float y, floa // ROTATE_* doesn't yet work right. void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color color, int align) { + // rough estimate + if (count_ + strlen(text) * 6 > MAX_VERTS) { + Flush(true); + } + const AtlasFont &atlasfont = *atlas->fonts[font]; unsigned int cval; float w, h; diff --git a/ui/view.cpp b/ui/view.cpp index b15133090d..dd965e5769 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -564,7 +564,7 @@ void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) con void TextView::Draw(UIContext &dc) { dc.SetFontStyle(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont); - dc.DrawTextRect(text_.c_str(), bounds_, 0xFFFFFFFF, textAlign_); + dc.DrawTextRect(text_.c_str(), bounds_, textColor_, textAlign_); } TextEdit::TextEdit(const std::string &text, const std::string &placeholderText, LayoutParams *layoutParams) @@ -677,6 +677,13 @@ void TextEdit::Key(const KeyInput &input) { textChanged = true; } break; + case NKCODE_ENTER: + { + EventParams e; + e.s = text_; + OnEnter.Trigger(e); + break; + } } if (ctrlDown_) { diff --git a/ui/view.h b/ui/view.h index 544c4a8051..85ce4ce457 100644 --- a/ui/view.h +++ b/ui/view.h @@ -654,19 +654,21 @@ private: class TextView : public InertView { public: TextView(const std::string &text, LayoutParams *layoutParams = 0) - : InertView(layoutParams), text_(text), textAlign_(0), small_(false) {} + : InertView(layoutParams), text_(text), textAlign_(0), textColor_(0xFFFFFFFF), small_(false) {} TextView(const std::string &text, int textAlign, bool small, LayoutParams *layoutParams = 0) - : InertView(layoutParams), text_(text), textAlign_(textAlign), small_(small) {} + : InertView(layoutParams), text_(text), textAlign_(textAlign), textColor_(0xFFFFFFFF), small_(small) {} virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; virtual void Draw(UIContext &dc) override; void SetText(const std::string &text) { text_ = text; } void SetSmall(bool small) { small_ = small; } + void SetTextColor(uint32_t color) { textColor_ = color; } private: std::string text_; int textAlign_; + uint32_t textColor_; bool small_; }; @@ -683,6 +685,7 @@ public: virtual void Touch(const TouchInput &touch) override; Event OnTextChange; + Event OnEnter; private: void InsertAtCaret(const char *text); diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index c1c7e6ebaf..343f0d39a0 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -776,6 +776,13 @@ void ScrollView::ClampScrollPos(float &pos) { } } +void ScrollView::ScrollToBottom() { + float childHeight = views_[0]->GetBounds().h; + float scrollMax = std::max(0.0f, childHeight - bounds_.h); + scrollPos_ = scrollMax; + scrollTarget_ = scrollMax; +} + bool ScrollView::CanScroll() const { if (!views_.size()) return false; diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 66f39ae4e9..ec69fb31c0 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -217,6 +217,7 @@ public: void Draw(UIContext &dc); void ScrollTo(float newScrollPos); + void ScrollToBottom(); void ScrollRelative(float distance); bool CanScroll() const; void Update(const InputState &input_state); From 9201103abe872dcdc50e0d8331f96d9044b8f0b4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 11 Jan 2015 11:39:30 +0100 Subject: [PATCH 1333/1445] Get rid of the Java audio path. We now only support Android 2.3+ where it's not needed. Also, expose the optimal sample rate for the platform so we can show it in the UI. --- android/app-android.cpp | 49 ++++---- android/native-audio-so.cpp | 5 +- .../libnative/NativeActivity.java | 41 +++--- .../libnative/NativeAudioPlayer.java | 117 ------------------ base/NativeApp.h | 10 +- 5 files changed, 57 insertions(+), 165 deletions(-) delete mode 100644 android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java diff --git a/android/app-android.cpp b/android/app-android.cpp index 7064a246cf..c3407aa86c 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -52,8 +52,10 @@ static float right_joystick_y_async; static float hat_joystick_x_async; static float hat_joystick_y_async; -int optimalFramesPerBuffer = 0; -int optimalSampleRate = 0; +static int optimalFramesPerBuffer = 0; +static int optimalSampleRate = 0; +static int sampleRate = 0; +static int framesPerBuffer = 0; static int androidVersion; // Should only be used for display detection during startup (for config defaults etc) @@ -119,6 +121,14 @@ int System_GetPropertyInt(SystemProperty prop) { return display_xres; case SYSPROP_DISPLAY_YRES: return display_yres; + case SYSPROP_AUDIO_SAMPLE_RATE: + return sampleRate; + case SYSPROP_AUDIO_FRAMES_PER_BUFFER: + return framesPerBuffer; + case SYSPROP_AUDIO_OPTIMAL_SAMPLE_RATE: + return optimalSampleRate; + case SYSPROP_AUDIO_OPTIMAL_FRAMES_PER_BUFFER: + return optimalFramesPerBuffer; default: return -1; } @@ -134,7 +144,6 @@ InputState input_state; static bool renderer_inited = false; static bool first_lost = true; -static bool use_opensl_audio = false; static std::string library_path; std::string GetJavaString(JNIEnv *env, jstring jstr) { @@ -175,7 +184,7 @@ extern "C" jstring Java_com_henrikrydgard_libnative_NativeApp_queryConfig extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init (JNIEnv *env, jclass, jstring jdevicetype, jint jxres, jint jyres, jstring jlangRegion, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jshortcutParam, - jstring jinstallID, jboolean juseNativeAudio, jint jAndroidVersion) { + jstring jinstallID, jint jAndroidVersion) { jniEnvUI = env; ILOG("NativeApp.init() -- begin"); @@ -220,7 +229,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init NativeGetAppInfo(&app_name, &app_nice_name, &landscape, &version); - // If shortcut_param is not empty, pass it as additional varargs argument to NativeInit() method. // NativeInit() is expected to treat extra argument as boot_filename, which in turn will start game immediately. // NOTE: Will only work if ppsspp started from Activity.onCreate(). Won't work if ppsspp app start from onResume(). @@ -234,42 +242,29 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init NativeInit(2, argv, user_data_path.c_str(), externalDir.c_str(), installID.c_str()); } - use_opensl_audio = juseNativeAudio; ILOG("NativeApp.init() -- end"); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioInit(JNIEnv *, jclass) { - if (use_opensl_audio) { - // TODO: PPSSPP doesn't support 48khz yet so let's not use that yet. - ILOG("NativeApp.audioInit() -- Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: 44100", optimalFramesPerBuffer, optimalSampleRate); - optimalSampleRate = 44100; - AndroidAudio_Init(&NativeMix, library_path, optimalFramesPerBuffer, optimalSampleRate); - } else { - ILOG("NativeApp.audioInit() -- Using Java audio :("); - } + // TODO: PPSSPP doesn't support 48khz yet so let's not use that yet. + ILOG("NativeApp.audioInit() -- Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: 44100", optimalFramesPerBuffer, optimalSampleRate); + sampleRate = 44100; + framesPerBuffer = optimalFramesPerBuffer; + AndroidAudio_Init(&NativeMix, library_path, framesPerBuffer, sampleRate); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioShutdown(JNIEnv *, jclass) { - ILOG("NativeApp.audioShutdown() -- begin"); - if (use_opensl_audio) { - AndroidAudio_Shutdown(); - } - ILOG("NativeApp.audioShutdown() -- end"); + AndroidAudio_Shutdown(); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_resume(JNIEnv *, jclass) { ILOG("NativeApp.resume() - resuming audio"); - if (use_opensl_audio) { - AndroidAudio_Resume(); - } + AndroidAudio_Resume(); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_pause(JNIEnv *, jclass) { - ILOG("NativeApp.pause() - begin"); - if (use_opensl_audio) { - AndroidAudio_Pause(); - } - ILOG("NativeApp.pause() - end"); + ILOG("NativeApp.pause() - pausing audio"); + AndroidAudio_Pause(); } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 998080d8f1..71c6c214bf 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -49,7 +49,10 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { int renderedFrames = audioCallback(buffer[curBuffer], framesPerBuffer); int sizeInBytes = framesPerBuffer * 2 * sizeof(short); - memset(buffer[curBuffer] + renderedFrames * 2, 0, (framesPerBuffer - renderedFrames) * 4); + int byteCount = (framesPerBuffer - renderedFrames) * 4; + if (byteCount > 0) { + memset(buffer[curBuffer] + renderedFrames * 2, 0, byteCount); + } SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeInBytes); // Comment from sample code: diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index bf9553a473..bf12ecfe9b 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -62,7 +62,6 @@ public class NativeActivity extends Activity { // Graphics and audio interfaces private NativeGLView mGLSurfaceView; - private NativeAudioPlayer audioPlayer; protected NativeRenderer nativeRenderer; private String shortcutParam = ""; @@ -103,7 +102,7 @@ public class NativeActivity extends Activity { @TargetApi(17) private void detectOptimalAudioSettings() { try { - optimalFramesPerBuffer = Integer.parseInt(this.audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); + optimalFramesPerBuffer = Integer.parseInt(this.audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); } catch (NumberFormatException e) { // Ignore, if we can't parse it it's bogus and zero is a fine value (means we couldn't detect it). } @@ -321,13 +320,7 @@ public class NativeActivity extends Activity { window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setVolumeControlStream(AudioManager.STREAM_MUSIC); - // Initialize audio and tell PPSSPP to gain audio focus - if (!useOpenSL()) { - Log.w(TAG, "Falling back to AudioTrack"); - audioPlayer = new NativeAudioPlayer(); - } - - NativeAudioPlayer.gainAudioFocus(this.audioManager, this.audioFocusChangeListener); + gainAudioFocus(this.audioManager, this.audioFocusChangeListener); NativeApp.audioInit(); mGLSurfaceView = new NativeGLView(this); @@ -400,7 +393,6 @@ public class NativeActivity extends Activity { nativeRenderer.onDestroyed(); NativeApp.audioShutdown(); // Probably vain attempt to help the garbage collector... - audioPlayer = null; mGLSurfaceView = null; audioFocusChangeListener = null; audioManager = null; @@ -422,10 +414,7 @@ public class NativeActivity extends Activity { protected void onPause() { super.onPause(); Log.i(TAG, "onPause"); - NativeAudioPlayer.loseAudioFocus(this.audioManager, this.audioFocusChangeListener); - if (audioPlayer != null) { - audioPlayer.stop(); - } + loseAudioFocus(this.audioManager, this.audioFocusChangeListener); NativeApp.pause(); mGLSurfaceView.onPause(); } @@ -448,10 +437,7 @@ public class NativeActivity extends Activity { Log.e(TAG, "mGLSurfaceView really shouldn't be null in onResume"); } - NativeAudioPlayer.gainAudioFocus(this.audioManager, this.audioFocusChangeListener); - if (audioPlayer != null) { - audioPlayer.play(); - } + gainAudioFocus(this.audioManager, this.audioFocusChangeListener); NativeApp.resume(); } @@ -468,7 +454,24 @@ public class NativeActivity extends Activity { mGLSurfaceView.getHolder().setFixedSize(sz.x/2, sz.y/2); } } - + + //keep this static so we can call this even if we don't + //instantiate NativeAudioPlayer + public static void gainAudioFocus(AudioManager audioManager, AudioFocusChangeListener focusChangeListener) { + if (audioManager != null) { + audioManager.requestAudioFocus(focusChangeListener, + AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); + } + } + + //keep this static so we can call this even if we don't + //instantiate NativeAudioPlayer + public static void loseAudioFocus(AudioManager audioManager,AudioFocusChangeListener focusChangeListener){ + if (audioManager != null) { + audioManager.abandonAudioFocus(focusChangeListener); + } + } + // We simply grab the first input device to produce an event and ignore all others that are connected. @TargetApi(Build.VERSION_CODES.GINGERBREAD) private InputDeviceState getInputDeviceState(InputEvent event) { diff --git a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java b/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java deleted file mode 100644 index 763aae59d7..0000000000 --- a/android/src/com/henrikrydgard/libnative/NativeAudioPlayer.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.henrikrydgard.libnative; - -import android.media.AudioFormat; -import android.media.AudioManager; -import android.media.AudioTrack; -import android.util.Log; -import com.henrikrydgard.libnative.AudioFocusChangeListener; - -public class NativeAudioPlayer { - private String TAG = "NativeAudioPlayer"; - private Thread thread; - private boolean playing_; - - // Calling stop() is allowed at any time, whether stopped or not. - // If playing, blocks until not. - public synchronized void stop() { - if (thread != null) { - waitUntilDone(); - } else { - Log.e(TAG, "Was already stopped"); - } - } - - // If not playing, make sure we're playing. - public synchronized void play() { - if (thread == null) { - playStreaming(); - } else { - Log.e(TAG, "Was already playing"); - } - } - - //keep this static so we can call this even if we don't - //instantiate NativeAudioPlayer - public static void gainAudioFocus(AudioManager audioManager, AudioFocusChangeListener focusChangeListener) { - if (audioManager != null) { - audioManager.requestAudioFocus(focusChangeListener, - AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); - } - } - - //keep this static so we can call this even if we don't - //instantiate NativeAudioPlayer - public static void loseAudioFocus(AudioManager audioManager,AudioFocusChangeListener focusChangeListener){ - if (audioManager != null) { - audioManager.abandonAudioFocus(focusChangeListener); - } - } - - private void playStreaming() { - - playing_ = true; - thread = new Thread(new Runnable() { - public void run() { - playThread(); - } - }); - thread.setPriority(Thread.MAX_PRIORITY); - thread.start(); - } - - private void waitUntilDone() { - if (!playing_) { - Log.i(TAG, "not playing."); - } - try { - playing_ = false; - Log.e(TAG, "waitUntilDone: Joining audio thread."); - thread.join(); - } catch (InterruptedException e) { - Log.e(TAG, "INterrupted!"); - e.printStackTrace(); - } - thread = null; - Log.i(TAG, "Finished waitUntilDone"); - } - - private void playThread() { - try { - Log.i(TAG, "Thread started."); - // Get the smallest possible buffer size (which is annoyingly huge). - int buffer_size_bytes = AudioTrack.getMinBufferSize( - 44100, - AudioFormat.CHANNEL_OUT_STEREO, - AudioFormat.ENCODING_PCM_16BIT); - - // Round buffer_size_bytes up to an even multiple of 128 for convenience. - buffer_size_bytes = (buffer_size_bytes + 127) & ~127; - - AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, - 44100, - AudioFormat.CHANNEL_OUT_STEREO, - AudioFormat.ENCODING_PCM_16BIT, - buffer_size_bytes, - AudioTrack.MODE_STREAM); - - int buffer_size = buffer_size_bytes / 2; - short [] buffer = new short[buffer_size]; - audioTrack.play(); - Log.i(TAG, "Playing... minBuffersize = " + buffer_size); - while (playing_) { - int validShorts = NativeApp.audioRender(buffer); - if (validShorts != 0) { - audioTrack.write(buffer, 0, validShorts); - } - Thread.yield(); - } - audioTrack.stop(); - audioTrack.release(); - Log.i(TAG, "Stopped playing."); - } catch (Throwable t) { - Log.e(TAG, "Playback Failed"); - t.printStackTrace(); - Log.e(TAG, t.toString()); - } - } -} \ No newline at end of file diff --git a/base/NativeApp.h b/base/NativeApp.h index 7c14c0e562..7dedd32ac0 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -130,7 +130,15 @@ enum SystemProperty { SYSPROP_SYSTEMVERSION, SYSPROP_DISPLAY_XRES, SYSPROP_DISPLAY_YRES, - SYSPROP_MOGA_VERSION + SYSPROP_MOGA_VERSION, + + // Exposed on Android. Choosing the optimal sample rate for audio + // will result in lower latencies. Buffer size is automatically matched + // by the OpenSL audio backend, only exposed here for debugging/info. + SYSPROP_AUDIO_SAMPLE_RATE, + SYSPROP_AUDIO_FRAMES_PER_BUFFER, + SYSPROP_AUDIO_OPTIMAL_SAMPLE_RATE, + SYSPROP_AUDIO_OPTIMAL_FRAMES_PER_BUFFER, }; std::string System_GetProperty(SystemProperty prop); From b6fea8a35568d8932096e300ef2f7d3a714b0f62 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 11 Jan 2015 14:15:26 +0100 Subject: [PATCH 1334/1445] SDL: Implement SYSPROP_AUDIO_SAMPLE_RATE query --- base/PCMain.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index e16691ce0a..ba82636eba 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -312,7 +312,14 @@ std::string System_GetProperty(SystemProperty prop) { } } -int System_GetPropertyInt(SystemProperty prop) {return -1;} +int System_GetPropertyInt(SystemProperty prop) { + switch (prop) { + case SYSPROP_AUDIO_SAMPLE_RATE: + return 44100; + default: + return -1; + } +} InputState input_state; From 1b5bf730caffa702de34a6db9f0ae93fbbd88eed Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 11 Jan 2015 14:17:23 +0100 Subject: [PATCH 1335/1445] Same as the last one for BlackBerry and Qt --- base/BlackberryMain.cpp | 9 ++++++++- base/QtMain.cpp | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 0ce861247b..47aabf651c 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -44,7 +44,14 @@ std::string System_GetProperty(SystemProperty prop) { } } -int System_GetPropertyInt(SystemProperty prop) {return -1;} +int System_GetPropertyInt(SystemProperty prop) { + switch (prop) { + case SYSPROP_AUDIO_SAMPLE_RATE: + return 44100; + default: + return -1; + } +} void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 629ccd061c..c1aba18f66 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -69,7 +69,14 @@ std::string System_GetProperty(SystemProperty prop) { } } -int System_GetPropertyInt(SystemProperty prop) {return -1;} +int System_GetPropertyInt(SystemProperty prop) { + switch (prop) { + case SYSPROP_AUDIO_SAMPLE_RATE: + return 44100; + default: + return -1; + } +} void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { From 84ed01df53cd557eb126c1f6badef7d9201add5f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 11 Jan 2015 17:27:45 +0100 Subject: [PATCH 1336/1445] Android audio: Add ability to not override the sample rate to 44khz --- android/app-android.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index c3407aa86c..b4fc8dd6ed 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -246,10 +246,12 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioInit(JNIEnv *, jclass) { - // TODO: PPSSPP doesn't support 48khz yet so let's not use that yet. - ILOG("NativeApp.audioInit() -- Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: 44100", optimalFramesPerBuffer, optimalSampleRate); - sampleRate = 44100; + sampleRate = optimalSampleRate; + if (NativeQueryConfig("force44khz") != "0") { + sampleRate = 44100; + } framesPerBuffer = optimalFramesPerBuffer; + ILOG("NativeApp.audioInit() -- Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: %i", optimalFramesPerBuffer, optimalSampleRate, sampleRate); AndroidAudio_Init(&NativeMix, library_path, framesPerBuffer, sampleRate); } From 7a5e182fd1383ac3ae63748d38c8405eceb6291e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Jan 2015 16:52:37 -0800 Subject: [PATCH 1337/1445] Cache the bound VBO/index buffer in glstate. Though, the index buffer is actually part of VAO state (unlike VBOs...), so that might change when we implement VAOs. --- gfx_es2/gl_state.cpp | 3 +++ gfx_es2/gl_state.h | 57 ++++++++++++++++++++++++-------------------- thin3d/thin3d_gl.cpp | 16 ++++++++----- 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index ab97de2dd5..6bf5843321 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -75,6 +75,9 @@ void OpenGLState::Restore() { logicOp.restore(); count++; #endif + arrayBuffer.restore(); count++; + elementArrayBuffer.restore(); count++; + if (count != state_count) { FLOG("OpenGLState::Restore is missing some states"); } diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 293a28d03b..fa38e6b822 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -109,7 +109,7 @@ private: public: \ SavedState1_##func() : p1(p1def) { \ OpenGLState::state_count++; \ - }; \ + } \ void set(p1type newp1) { \ if(newp1 != p1) { \ p1 = newp1; \ @@ -128,7 +128,7 @@ private: public: \ SavedState2_##func() : p1(p1def), p2(p2def) { \ OpenGLState::state_count++; \ - }; \ + } \ inline void set(p1type newp1, p2type newp2) { \ if(newp1 != p1 || newp2 != p2) { \ p1 = newp1; \ @@ -141,27 +141,7 @@ private: } \ } -#define STATE2_4(func, p1type, p2type, p1def, p2def, p3def, p4def) \ - class SavedState2_##func { \ - p1type p1; \ - p2type p2; \ - public: \ - SavedState2_##func() : p1(p1def), p2(p2def) { \ - OpenGLState::state_count++; \ - }; \ - inline void set(p1type newp1, p2type newp2) { \ - if(newp1 != p1 || newp2 != p2) { \ - p1 = newp1; \ - p2 = newp2; \ - func(p1, p2, p3def, p4def); \ - } \ - } \ - inline void restore() { \ - func(p1, p2, p3def, p4def); \ - } \ - } - - #define STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \ +#define STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \ class SavedState3_##func { \ p1type p1; \ p2type p2; \ @@ -169,7 +149,7 @@ private: public: \ SavedState3_##func() : p1(p1def), p2(p2def), p3(p3def) { \ OpenGLState::state_count++; \ - }; \ + } \ inline void set(p1type newp1, p2type newp2, p3type newp3) { \ if(newp1 != p1 || newp2 != p2 || newp3 != p3) { \ p1 = newp1; \ @@ -192,7 +172,7 @@ private: public: \ SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) { \ OpenGLState::state_count++; \ - }; \ + } \ inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \ if(newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \ p1 = newp1; \ @@ -214,7 +194,7 @@ private: SavedState4_##func() { \ for (int i = 0; i < 4; i++) {p[i] = def;} \ OpenGLState::state_count++; \ - }; \ + } \ inline void set(const float v[4]) { \ if(memcmp(p,v,sizeof(float)*4)) { \ memcpy(p,v,sizeof(float)*4); \ @@ -226,6 +206,28 @@ private: } \ } +#define STATEBIND(func, target) \ + class SavedBind_##func_##target { \ + GLuint val_; \ + public: \ + SavedBind_##func_##target() { \ + val_ = 0; \ + OpenGLState::state_count++; \ + } \ + inline void bind(GLuint val) { \ + if (val_ != val) { \ + func(target, val); \ + val_ = val; \ + } \ + } \ + inline void unbind() { \ + bind(0); \ + } \ + inline void restore() { \ + func(target, val_); \ + } \ + } + bool initialized; public: @@ -284,6 +286,9 @@ public: STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; STATE1(glStencilMask, GLuint, 0xFF) stencilMask; + STATEBIND(glBindBuffer, GL_ARRAY_BUFFER) arrayBuffer; + STATEBIND(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER) elementArrayBuffer; + // Only works on Win32, all other platforms are "force-vsync" void SetVSyncInterval(int interval); // one of the above VSYNC, or a higher number for multi-frame waits (could be useful for 30hz games) }; diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index d168243404..1280ed7092 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -142,13 +142,13 @@ public: } void SetData(const uint8_t *data, size_t size) override { - glBindBuffer(target_, buffer_); + Bind(); glBufferData(target_, size, data, usage_); knownSize_ = size; } void SubData(const uint8_t *data, size_t offset, size_t size) override { - glBindBuffer(target_, buffer_); + Bind(); if (size > knownSize_) { // Allocate the buffer. glBufferData(target_, size + offset, NULL, usage_); @@ -157,7 +157,11 @@ public: glBufferSubData(target_, offset, size, data); } void Bind() { - glBindBuffer(target_, buffer_); + if (target_ == GL_ARRAY_BUFFER) { + glstate.arrayBuffer.bind(buffer_); + } else { + glstate.elementArrayBuffer.bind(buffer_); + } } void GLLost() override { @@ -712,7 +716,7 @@ void Thin3DGLContext::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DV pipe->Unapply(); fmt->Unapply(); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glstate.arrayBuffer.unbind(); } void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) { @@ -731,8 +735,8 @@ void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, pipe->Unapply(); fmt->Unapply(); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glstate.arrayBuffer.unbind(); + glstate.elementArrayBuffer.unbind(); } void Thin3DGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) { From be15181d29af9c60d8494a38c13fb9b3de4faa3b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Jan 2015 17:03:15 -0800 Subject: [PATCH 1338/1445] Leave arrays bound in case we can reuse them. --- thin3d/thin3d_gl.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index 1280ed7092..e57f2567bf 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -715,8 +715,6 @@ void Thin3DGLContext::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DV pipe->Unapply(); fmt->Unapply(); - - glstate.arrayBuffer.unbind(); } void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) { @@ -734,9 +732,6 @@ void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, pipe->Unapply(); fmt->Unapply(); - - glstate.arrayBuffer.unbind(); - glstate.elementArrayBuffer.unbind(); } void Thin3DGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) { From a506ba2e83913ac4ebf4d1fb092f847f5e7e03e4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 14 Jan 2015 00:27:21 +0100 Subject: [PATCH 1339/1445] Expose/fake native display refresh rate. Only has a real value on Android. --- android/app-android.cpp | 2 ++ base/BlackberryMain.cpp | 2 ++ base/NativeApp.h | 1 + base/PCMain.cpp | 2 ++ base/QtMain.cpp | 2 ++ 5 files changed, 9 insertions(+) diff --git a/android/app-android.cpp b/android/app-android.cpp index b4fc8dd6ed..f4dd3006c9 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -129,6 +129,8 @@ int System_GetPropertyInt(SystemProperty prop) { return optimalSampleRate; case SYSPROP_AUDIO_OPTIMAL_FRAMES_PER_BUFFER: return optimalFramesPerBuffer; + case SYSPROP_DISPLAY_REFRESH_RATE: + return (int)(display_hz * 1000.0); default: return -1; } diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 47aabf651c..75bab2aa6c 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -48,6 +48,8 @@ int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: return 44100; + case SYSPROP_DISPLAY_REFRESH_RATE: + return 60000; default: return -1; } diff --git a/base/NativeApp.h b/base/NativeApp.h index 7dedd32ac0..b24a284782 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -130,6 +130,7 @@ enum SystemProperty { SYSPROP_SYSTEMVERSION, SYSPROP_DISPLAY_XRES, SYSPROP_DISPLAY_YRES, + SYSPROP_DISPLAY_REFRESH_RATE, // returns 1000*the refresh rate in Hz as it can be non-integer SYSPROP_MOGA_VERSION, // Exposed on Android. Choosing the optimal sample rate for audio diff --git a/base/PCMain.cpp b/base/PCMain.cpp index ba82636eba..536d2fd5da 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -316,6 +316,8 @@ int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: return 44100; + case SYSPROP_DISPLAY_REFRESH_RATE: + return 60000; default: return -1; } diff --git a/base/QtMain.cpp b/base/QtMain.cpp index c1aba18f66..0e82b028ff 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -73,6 +73,8 @@ int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: return 44100; + case SYSPROP_DISPLAY_REFRESH_RATE: + return 60000; default: return -1; } From d2f95b91909418d07cb6cdd3f6b8f7cf5ad4dc09 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 14 Jan 2015 00:34:27 +0100 Subject: [PATCH 1340/1445] Set some half reasonable defaults when there's no optimal sample rate available --- android/app-android.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index f4dd3006c9..bf4407692f 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -249,10 +249,14 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioInit(JNIEnv *, jclass) { sampleRate = optimalSampleRate; - if (NativeQueryConfig("force44khz") != "0") { + if (NativeQueryConfig("force44khz") != "0" || optimalSampleRate == 0) { sampleRate = 44100; } - framesPerBuffer = optimalFramesPerBuffer; + if (optimalFramesPerBuffer > 0) { + framesPerBuffer = optimalFramesPerBuffer; + } else { + framesPerBuffer = 512; + } ILOG("NativeApp.audioInit() -- Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: %i", optimalFramesPerBuffer, optimalSampleRate, sampleRate); AndroidAudio_Init(&NativeMix, library_path, framesPerBuffer, sampleRate); } From a90adc8f8db3069c4c552159e7fe1bcf8f3c917a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Jan 2015 11:59:27 -0800 Subject: [PATCH 1341/1445] Fix a memory leak on error condition. --- gfx_es2/glsl_program.cpp | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 57058ee67e..8fac10ede1 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -96,15 +96,38 @@ void glsl_refresh() { } } +// Not wanting to change ReadLocalFile semantics. +// Needs to use delete [], not delete like auto_ptr, and can't use unique_ptr because of Symbian. +struct AutoCharArrayBuf { + AutoCharArrayBuf(char *buf = nullptr) : buf_(buf) { + } + ~AutoCharArrayBuf() { + delete [] buf_; + buf_ = nullptr; + } + void reset(char *buf) { + if (buf_) { + delete[] buf_; + } + buf_ = buf; + } + operator char *() { + return buf_; + } + +private: + char *buf_; +}; + bool glsl_recompile(GLSLProgram *program, std::string *error_message) { struct stat vs, fs; - char *vsh_src = 0, *fsh_src = 0; + AutoCharArrayBuf vsh_src, fsh_src; if (strlen(program->vshader_filename) > 0 && 0 == stat(program->vshader_filename, &vs)) { program->vshader_mtime = vs.st_mtime; if (!program->vshader_source) { size_t sz; - vsh_src = (char *)ReadLocalFile(program->vshader_filename, &sz); + vsh_src.reset((char *)ReadLocalFile(program->vshader_filename, &sz)); } } else { program->vshader_mtime = 0; @@ -114,7 +137,7 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { program->fshader_mtime = fs.st_mtime; if (!program->fshader_source) { size_t sz; - fsh_src = (char *)ReadLocalFile(program->fshader_filename, &sz); + fsh_src.reset((char *)ReadLocalFile(program->fshader_filename, &sz)); } } else { program->fshader_mtime = 0; @@ -122,26 +145,24 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { if (!program->vshader_source && !vsh_src) { size_t sz; - vsh_src = (char *)VFSReadFile(program->vshader_filename, &sz); + vsh_src.reset((char *)VFSReadFile(program->vshader_filename, &sz)); } if (!program->vshader_source && !vsh_src) { ELOG("File missing: %s", program->vshader_filename); if (error_message) { *error_message = std::string("File missing: ") + program->vshader_filename; } - delete [] fsh_src; return false; } if (!program->fshader_source && !fsh_src) { size_t sz; - fsh_src = (char *)VFSReadFile(program->fshader_filename, &sz); + fsh_src.reset((char *)VFSReadFile(program->fshader_filename, &sz)); } if (!program->fshader_source && !fsh_src) { ELOG("File missing: %s", program->fshader_filename); if (error_message) { *error_message = std::string("File missing: ") + program->fshader_filename; } - delete [] vsh_src; return false; } @@ -150,7 +171,6 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { if (!CompileShader(vsh_str, vsh, program->vshader_filename, error_message)) { return false; } - delete [] vsh_src; const GLchar *fsh_str = program->fshader_source ? program->fshader_source : (const GLchar *)(fsh_src); GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER); @@ -158,7 +178,6 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { glDeleteShader(vsh); return false; } - delete [] fsh_src; GLuint prog = glCreateProgram(); glAttachShader(prog, vsh); From 255b39a6f6a1e15227f8727da7eada34e0b79968 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Jan 2015 13:54:52 -0800 Subject: [PATCH 1342/1445] Fix a small memory leak. --- file/chunk_file.cpp | 2 +- gfx_es2/draw_text.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index 914864653b..e65bc6891e 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -48,7 +48,7 @@ ChunkFile::ChunkFile(const uint8_t *read_data, int data_size) { } ChunkFile::~ChunkFile() { - if (fastMode && data) + if (fastMode) delete [] data; else file.close(); diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index 3c243c5632..f99fc68125 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -70,6 +70,8 @@ TextDrawer::~TextDrawer() { DeleteObject(ctx_->hbmBitmap); DeleteDC(ctx_->hDC); + + delete ctx_; } uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) { From b48117d01b17c1782880066b9bc7999ebdf0cdcc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Jan 2015 19:47:54 -0800 Subject: [PATCH 1343/1445] Fix a potential null deref. This is null checked after dereferencing. --- gfx_es2/gl_state.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 6bf5843321..1b864e6e64 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -194,6 +194,7 @@ void CheckGLExtensions() { g_all_gl_extensions = extString; } else { g_all_gl_extensions = ""; + extString = ""; } #ifdef WIN32 @@ -342,7 +343,7 @@ void CheckGLExtensions() { gl_extensions.FBO_EXT = false; gl_extensions.PBO_ARB = true; gl_extensions.PBO_NV = true; - if (extString) { + if (strlen(extString) != 0) { gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; From 45103d19294387e31af45505ada4ef131d67fd20 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Jan 2015 13:15:18 -0800 Subject: [PATCH 1344/1445] Fix an unlikely buffer overflow. --- file/zip_read.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/file/zip_read.h b/file/zip_read.h index 6fb743c4d9..57141f3216 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -64,7 +64,8 @@ private: class DirectoryAssetReader : public AssetReader { public: DirectoryAssetReader(const char *path) { - strcpy(path_, path); + strncpy(path_, path, ARRAY_SIZE(path_)); + path_[ARRAY_SIZE(path_) - 1] = '\0'; } // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size); From 3af3452d7e6f50059655eecc3eeed68b49195a31 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Jan 2015 15:29:14 -0800 Subject: [PATCH 1345/1445] Resize in Qt like in other backends. Should fix switching to fullscren and probably also resizing in general. --- base/QtMain.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/base/QtMain.h b/base/QtMain.h index a59cf5a2a0..176ca7fe35 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -80,13 +80,9 @@ signals: protected: void resizeEvent(QResizeEvent * e) { - pixel_xres = e->size().width(); - pixel_yres = e->size().height(); - dp_xres = pixel_xres * g_dpi_scale; - dp_yres = pixel_yres * g_dpi_scale; + UpdateScreenScale(e->size().width(), e->size().height()); PSP_CoreParameter().pixelWidth = pixel_xres; PSP_CoreParameter().pixelHeight = pixel_yres; - UpdateScreenScale(pixel_xres, pixel_yres); } void timerEvent(QTimerEvent *) { From 471816c24b718fe57796a320148101386ec0c6ce Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Jan 2015 15:53:23 -0800 Subject: [PATCH 1346/1445] Fully remove old useOpenSL param. --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 +- android/src/com/henrikrydgard/libnative/NativeApp.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index bf12ecfe9b..c20861dd55 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -212,7 +212,7 @@ public class NativeActivity extends Activity { Point displaySize = new Point(); GetScreenSize(displaySize); NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(deviceType, displaySize.x, displaySize.y, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, useOpenSL(), Build.VERSION.SDK_INT); + NativeApp.init(deviceType, displaySize.x, displaySize.y, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, Build.VERSION.SDK_INT); // OK, config should be initialized, we can query for screen rotation. if (Build.VERSION.SDK_INT >= 9) { diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index 5239131da6..e03bf17db8 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -9,7 +9,7 @@ public class NativeApp { public final static int DEVICE_ID_MOUSE = 2; public final static int DEVICE_ID_PAD_0 = 10; - public static native void init(String deviceType, int xres, int yres, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, boolean useOpenSL, int androidVersion); + public static native void init(String deviceType, int xres, int yres, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, int androidVersion); public static native void audioInit(); public static native void audioShutdown(); From 7c28b2f7a1707479bf333bcdba8e66adbe826053 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 24 Jan 2015 13:30:18 +0100 Subject: [PATCH 1347/1445] Statically link MSVCRT --- native.vcxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/native.vcxproj b/native.vcxproj index 3cd20ba3af..523c79ecef 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -86,6 +86,7 @@ true false false + MultiThreadedDebug Windows @@ -106,6 +107,7 @@ true false false + MultiThreadedDebug Windows @@ -129,6 +131,7 @@ Fast true false + MultiThreaded Windows @@ -154,6 +157,7 @@ Fast true false + MultiThreaded Windows From c6f1552756ff6ceeb626bc0a7f5e0476545436e4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 24 Jan 2015 20:33:38 -0800 Subject: [PATCH 1348/1445] Fix a typo causing frag shaders to leak. Only utility type shaders, though. --- gfx_es2/glsl_program.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 8fac10ede1..38725ccdb4 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -218,7 +218,7 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { program->program_ = prog; program->vsh_ = vsh; - program->fsh_ = vsh; + program->fsh_ = fsh; program->sampler0 = glGetUniformLocation(program->program_, "sampler0"); program->sampler1 = glGetUniformLocation(program->program_, "sampler1"); From 813c12e40fa241c3097b541de4cb68f16a45af53 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 27 Jan 2015 00:11:23 +0100 Subject: [PATCH 1349/1445] Thin3d preset GLSL shaders: Make them identical to the old GL-only shaders by adding precision qualifiers --- thin3d/thin3d.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/thin3d/thin3d.cpp b/thin3d/thin3d.cpp index bd6d0f9f9d..afc465a0c4 100644 --- a/thin3d/thin3d.cpp +++ b/thin3d/thin3d.cpp @@ -8,10 +8,13 @@ #include "ext/jpge/jpgd.h" static const char * const glsl_fsTexCol = +"#ifdef GL_ES\n" +"precision lowp float;\n" +"#endif\n" "varying vec4 oColor0;\n" "varying vec2 oTexCoord0;\n" "uniform sampler2D Sampler0;\n" -"void main() { gl_FragColor = oColor0 * texture2D(Sampler0, oTexCoord0); }\n"; +"void main() { gl_FragColor = texture2D(Sampler0, oTexCoord0) * oColor0; }\n"; static const char * const hlslFsTexCol = "struct PS_INPUT { float4 color : COLOR0; float2 uv : TEXCOORD0; };\n" @@ -21,6 +24,9 @@ static const char * const hlslFsTexCol = "}\n"; static const char * const glsl_fsCol = +"#ifdef GL_ES\n" +"precision lowp float;\n" +"#endif\n" "varying vec4 oColor0;\n" "void main() { gl_FragColor = oColor0; }\n"; From 1467753c35eaf57be5610d756a3071e4badc1b69 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 29 Jan 2015 10:35:34 +0100 Subject: [PATCH 1350/1445] Don't use a VBO for DrawBuffer drawing. Some crappy ES drivers really don't like dynamic vertex buffers. --- android/app-android.cpp | 6 ++++++ gfx_es2/draw_buffer.cpp | 34 +++++++++++++------------------- gfx_es2/draw_buffer.h | 8 -------- thin3d/thin3d.h | 1 + thin3d/thin3d_d3d9.cpp | 16 +++++++++++++++ thin3d/thin3d_gl.cpp | 43 +++++++++++++++++++++++++++-------------- 6 files changed, 65 insertions(+), 43 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index bf4407692f..4719f5a2b1 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -257,6 +257,12 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioInit(JNIEnv *, j } else { framesPerBuffer = 512; } + + // Some devices have totally bonkers buffer sizes like 8192. They will have terrible latency anyway, so to avoid having to + // create extra smart buffering code, we'll just let their regular mixer deal with it, missing the fast path (as if they had one...) + if (framesPerBuffer > 1024) + framesPerBuffer = 1024; + ILOG("NativeApp.audioInit() -- Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: %i", optimalFramesPerBuffer, optimalSampleRate, sampleRate); AndroidAudio_Init(&NativeMix, library_path, framesPerBuffer, sampleRate); } diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 4d40531fc3..34abaaf536 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -38,7 +38,11 @@ void DrawBuffer::Init(Thin3DContext *t3d) { return; t3d_ = t3d; +#ifdef USE_VBO vbuf_ = t3d_->CreateBuffer(MAX_VERTS * sizeof(Vertex), T3DBufferUsage::DYNAMIC | T3DBufferUsage::VERTEXDATA); +#else + vbuf_ = nullptr; +#endif inited_ = true; std::vector components; @@ -52,7 +56,9 @@ void DrawBuffer::Init(Thin3DContext *t3d) { } void DrawBuffer::Shutdown() { - vbuf_->Release(); + if (vbuf_) { + vbuf_->Release(); + } vformat_->Release(); inited_ = false; @@ -76,12 +82,15 @@ void DrawBuffer::Flush(bool set_blend_state) { if (count_ == 0) return; - vbuf_->SubData((const uint8_t *)verts_, 0, sizeof(Vertex) * count_); - - int offset = 0; shaderSet_->SetMatrix4x4("WorldViewProj", drawMatrix_); +#ifdef USE_VBO + vbuf_->SubData((const uint8_t *)verts_, 0, sizeof(Vertex) * count_); + int offset = 0; t3d_->Draw(mode_ == DBMODE_NORMAL ? PRIM_TRIANGLES : PRIM_LINES, shaderSet_, vformat_, vbuf_, count_, offset); +#else + t3d_->DrawUP(mode_ == DBMODE_NORMAL ? PRIM_TRIANGLES : PRIM_LINES, shaderSet_, vformat_, (const void *)verts_, count_); +#endif count_ = 0; } @@ -467,20 +476,3 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co } } } - -void DrawBuffer::EnableBlend(bool enable) { - glstate.blend.set(enable); - glstate.blendFuncSeparate.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -} - -void DrawBuffer::SetClipRect(float x, float y, float w, float h) -{ - // Sigh, OpenGL is upside down. - glstate.scissorRect.set(x, dp_yres - y, w, h); - glstate.scissorTest.enable(); -} - -void DrawBuffer::NoClip() -{ - glstate.scissorTest.disable(); -} diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index 59b384087b..d83792025a 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -138,14 +138,6 @@ public: fontscaley = ys; } - // Utility to avoid having to include gl.h just for this in UI code. - void EnableBlend(bool enable); - - // Rectangular clipping, implemented using scissoring. - // Must flush before and after. - void SetClipRect(float x1, float y1, float x2, float y2); - void NoClip(); - static void DoAlign(int flags, float *x, float *y, float *w, float *h); void SetDrawMatrix(const Matrix4x4 &m) { diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index 16492f710b..fb71bb1077 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -323,6 +323,7 @@ public: // TODO: Add more sophisticated draws with buffer offsets, and multidraws. virtual void Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) = 0; virtual void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) = 0; + virtual void DrawUP(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, const void *vdata, int vertexCount) = 0; virtual void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) = 0; // Necessary to correctly flip scissor rectangles etc for OpenGL. diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 278fa4b490..81cff9f472 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -417,6 +417,7 @@ public: void Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) override; void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; + void DrawUP(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, const void *vdata, int vertexCount) override; void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal); const char *GetInfoString(T3DInfo info) const override { @@ -639,6 +640,21 @@ void Thin3DDX9Context::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet device_->DrawIndexedPrimitive(primToD3D9[prim], 0, 0, vertexCount, 0, vertexCount / 3); } +void Thin3DDX9Context::DrawUP(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, const void *vdata, int vertexCount) { + Thin3DDX9VertexFormat *fmt = static_cast(format); + Thin3DDX9ShaderSet *ss = static_cast(shaderSet); + + device_->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device_->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + device_->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + device_->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + device_->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + + ss->Apply(device_); + fmt->Apply(device_); + device_->DrawPrimitiveUP(primToD3D9[prim], vertexCount / 3, vdata, fmt->GetStride()); +} + static uint32_t SwapRB(uint32_t c) { return (c & 0xFF00FF00) | ((c >> 16) & 0xFF) | ((c << 16) & 0xFF0000); } diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index e57f2567bf..fa682c935c 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -234,7 +234,7 @@ bool Thin3DGLShader::Compile(const char *source) { class Thin3DGLVertexFormat : public Thin3DVertexFormat { public: - void Apply(); + void Apply(const void *base = nullptr); void Unapply(); void Compile(); @@ -335,6 +335,7 @@ public: // TODO: Add more sophisticated draws. void Draw(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) override; void DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) override; + void DrawUP(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, const void *vdata, int vertexCount) override; void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override; const char *GetInfoString(T3DInfo info) const override { @@ -702,23 +703,23 @@ void Thin3DGLContext::SetRenderState(T3DRenderState rs, uint32_t value) { } } -void Thin3DGLContext::Draw(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) { - Thin3DGLShaderSet *pipe = static_cast(pipeline); +void Thin3DGLContext::Draw(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, int vertexCount, int offset) { + Thin3DGLShaderSet *ss = static_cast(shaderSet); Thin3DGLBuffer *vbuf = static_cast(vdata); Thin3DGLVertexFormat *fmt = static_cast(format); vbuf->Bind(); fmt->Apply(); - pipe->Apply(); + ss->Apply(); glDrawArrays(primToGL[prim], offset, vertexCount); - pipe->Unapply(); + ss->Unapply(); fmt->Unapply(); } -void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) { - Thin3DGLShaderSet *pipe = static_cast(pipeline); +void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, Thin3DBuffer *vdata, Thin3DBuffer *idata, int vertexCount, int offset) { + Thin3DGLShaderSet *ss = static_cast(shaderSet); Thin3DGLBuffer *vbuf = static_cast(vdata); Thin3DGLBuffer *ibuf = static_cast(idata); Thin3DGLVertexFormat *fmt = static_cast(format); @@ -726,11 +727,24 @@ void Thin3DGLContext::DrawIndexed(T3DPrimitive prim, Thin3DShaderSet *pipeline, vbuf->Bind(); ibuf->Bind(); fmt->Apply(); - pipe->Apply(); + ss->Apply(); glDrawElements(primToGL[prim], offset, GL_INT, 0); - pipe->Unapply(); + ss->Unapply(); + fmt->Unapply(); +} + +void Thin3DGLContext::DrawUP(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, const void *vdata, int vertexCount) { + Thin3DGLShaderSet *ss = static_cast(shaderSet); + Thin3DGLVertexFormat *fmt = static_cast(format); + + fmt->Apply(vdata); + ss->Apply(); + + glDrawArrays(primToGL[prim], 0, vertexCount); + + ss->Unapply(); fmt->Unapply(); } @@ -761,25 +775,26 @@ Thin3DContext *T3DCreateGLContext() { return new Thin3DGLContext(); } -void Thin3DGLVertexFormat::Apply() { +void Thin3DGLVertexFormat::Apply(const void *base) { for (int i = 0; i < SEM_MAX; i++) { if (semanticsMask_ & (1 << i)) { glEnableVertexAttribArray(i); } } + intptr_t b = (intptr_t)base; for (size_t i = 0; i < components_.size(); i++) { switch (components_[i].type) { case FLOATx2: - glVertexAttribPointer(components_[i].semantic, 2, GL_FLOAT, GL_FALSE, stride_, (void *)(intptr_t)components_[i].offset); + glVertexAttribPointer(components_[i].semantic, 2, GL_FLOAT, GL_FALSE, stride_, (void *)(b + (intptr_t)components_[i].offset)); break; case FLOATx3: - glVertexAttribPointer(components_[i].semantic, 3, GL_FLOAT, GL_FALSE, stride_, (void *)(intptr_t)components_[i].offset); + glVertexAttribPointer(components_[i].semantic, 3, GL_FLOAT, GL_FALSE, stride_, (void *)(b + (intptr_t)components_[i].offset)); break; case FLOATx4: - glVertexAttribPointer(components_[i].semantic, 4, GL_FLOAT, GL_FALSE, stride_, (void *)(intptr_t)components_[i].offset); + glVertexAttribPointer(components_[i].semantic, 4, GL_FLOAT, GL_FALSE, stride_, (void *)(b + (intptr_t)components_[i].offset)); break; case UNORM8x4: - glVertexAttribPointer(components_[i].semantic, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride_, (void *)(intptr_t)components_[i].offset); + glVertexAttribPointer(components_[i].semantic, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride_, (void *)(b + (intptr_t)components_[i].offset)); break; case INVALID: ELOG("Thin3DGLVertexFormat: Invalid component type applied."); From 044cc8e9505285bb29228b5bc57e10778fb43723 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 31 Jan 2015 11:35:53 +0100 Subject: [PATCH 1351/1445] clock_gettime(MONOTONIC) seems more appropriate than gettimeofday for our purposes. Reluctant to do this before 1.0 though so I'll leave it as a pull request for now. --- base/timeutil.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/base/timeutil.cpp b/base/timeutil.cpp index bab362cc41..d66f24134d 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -60,8 +60,10 @@ double real_time_now() { return (double)diff / (double)_frequency; } -#endif - + struct timespec time; + clock_gettime(CLOCK_MONOTONIC_RAW, &time); + return time.tv_sec + time.tv_nsec / 1.0e9; +#else static time_t start; struct timeval tv; gettimeofday(&tv, NULL); @@ -70,6 +72,7 @@ double real_time_now() { } tv.tv_sec -= start; return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; +#endif } #endif From a72858d15e3678051787738076912b11e33982b9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 31 Jan 2015 11:47:05 +0100 Subject: [PATCH 1352/1445] Turn off the android audio fast path if not actually fast. Might as well use the PSP sample rate then. --- android/app-android.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 4719f5a2b1..37e3626815 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -260,8 +260,10 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_audioInit(JNIEnv *, j // Some devices have totally bonkers buffer sizes like 8192. They will have terrible latency anyway, so to avoid having to // create extra smart buffering code, we'll just let their regular mixer deal with it, missing the fast path (as if they had one...) - if (framesPerBuffer > 1024) - framesPerBuffer = 1024; + if (framesPerBuffer > 512) { + framesPerBuffer = 512; + sampleRate = 44100; + } ILOG("NativeApp.audioInit() -- Using OpenSL audio! frames/buffer: %i optimal sr: %i actual sr: %i", optimalFramesPerBuffer, optimalSampleRate, sampleRate); AndroidAudio_Init(&NativeMix, library_path, framesPerBuffer, sampleRate); From 5becb9a4be8f6e18b102de4eafe902284e9faded Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 1 Feb 2015 18:03:31 +0100 Subject: [PATCH 1353/1445] Add a new image size mode (nothing here uses it though). Also add Bounds.Expand --- math/geom2d.h | 3 +++ ui/view.h | 1 + 2 files changed, 4 insertions(+) diff --git a/math/geom2d.h b/math/geom2d.h index 0a94a42b8c..15f2f99501 100644 --- a/math/geom2d.h +++ b/math/geom2d.h @@ -59,6 +59,9 @@ struct Bounds { Point Center() const { return Point(centerX(), centerY()); } + Bounds Expand(float amount) const { + return Bounds(x - amount, y - amount, w + amount * 2, h + amount * 2); + } float x; float y; diff --git a/ui/view.h b/ui/view.h index 85ce4ce457..5910ea5a1c 100644 --- a/ui/view.h +++ b/ui/view.h @@ -701,6 +701,7 @@ private: enum ImageSizeMode { IS_DEFAULT, + IS_FIXED, }; class ImageView : public InertView { From 04515e403153472a56f5db826c1dfd060e785411 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 2 Feb 2015 09:12:07 +0100 Subject: [PATCH 1354/1445] Fix margins in stretched subviews in LinearLayout --- ui/viewgroup.cpp | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 343f0d39a0..2a2688fe42 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -368,6 +368,7 @@ void MoveFocus(ViewGroup *root, FocusDirection direction) { } } +// TODO: This code needs some cleanup/restructuring... void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) { MeasureBySpec(layoutParams_->width, 0.0f, horiz, &measuredWidth_); MeasureBySpec(layoutParams_->height, 0.0f, vert, &measuredHeight_); @@ -402,11 +403,12 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v if (orientation_ == ORIENT_HORIZONTAL) { MeasureSpec v = vert; - if (v.type == UNSPECIFIED) v = MeasureSpec(AT_MOST, measuredHeight_); - views_[i]->Measure(dc, MeasureSpec(UNSPECIFIED, measuredWidth_), vert - (float)(margins.top + margins.bottom)); + if (v.type == UNSPECIFIED && measuredHeight_ != 0.0) + v = MeasureSpec(AT_MOST, measuredHeight_); + views_[i]->Measure(dc, MeasureSpec(UNSPECIFIED, measuredWidth_), v - (float)(margins.top + margins.bottom)); } else if (orientation_ == ORIENT_VERTICAL) { MeasureSpec h = horiz; - if (h.type == UNSPECIFIED) h = MeasureSpec(AT_MOST, measuredWidth_); + if (h.type == UNSPECIFIED && measuredWidth_ != 0) h = MeasureSpec(AT_MOST, measuredWidth_); views_[i]->Measure(dc, h - (float)(margins.left + margins.right), MeasureSpec(UNSPECIFIED, measuredHeight_)); } @@ -432,7 +434,7 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v weightZeroSum += spacing_ * (numVisible - 1); - // Awright, got the sum. Let's take the remaining space after the fixed-size views, + // Alright, got the sum. Let's take the remaining space after the fixed-size views, // and distribute among the weighted ones. if (orientation_ == ORIENT_HORIZONTAL) { MeasureBySpec(layoutParams_->width, weightZeroSum, horiz, &measuredWidth_); @@ -448,8 +450,14 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; if (linLayoutParams && linLayoutParams->weight > 0.0f) { - int marginSum = linLayoutParams->margins.left + linLayoutParams->margins.right; - views_[i]->Measure(dc, MeasureSpec(EXACTLY, unit * linLayoutParams->weight - marginSum), MeasureSpec(EXACTLY, measuredHeight_)); + Margins margins = defaultMargins_; + if (linLayoutParams->HasMargins()) + margins = linLayoutParams->margins; + int marginSum = margins.left + margins.right; + MeasureSpec v = vert; + if (v.type == UNSPECIFIED && measuredHeight_ != 0.0) + v = MeasureSpec(AT_MOST, measuredHeight_); + views_[i]->Measure(dc, MeasureSpec(EXACTLY, unit * linLayoutParams->weight - marginSum), v - (float)(margins.top + margins.bottom)); } } } else { @@ -459,7 +467,7 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v float unit = (measuredHeight_ - weightZeroSum) / weightSum; - // Redistribute! and remeasure children! + // Redistribute the stretchy ones! and remeasure the children! for (size_t i = 0; i < views_.size(); i++) { if (views_[i]->GetVisibility() == V_GONE) continue; @@ -468,14 +476,19 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; if (linLayoutParams && linLayoutParams->weight > 0.0f) { - int marginSum = linLayoutParams->margins.top + linLayoutParams->margins.bottom; - views_[i]->Measure(dc, MeasureSpec(EXACTLY, measuredWidth_), MeasureSpec(EXACTLY, unit * linLayoutParams->weight - marginSum)); + Margins margins = defaultMargins_; + if (linLayoutParams->HasMargins()) + margins = linLayoutParams->margins; + int marginSum = margins.top + margins.bottom; + MeasureSpec h = horiz; + if (h.type == UNSPECIFIED && measuredWidth_ != 0.0) + h = MeasureSpec(AT_MOST, measuredWidth_); + views_[i]->Measure(dc, h - (float)(margins.left + margins.right), MeasureSpec(EXACTLY, unit * linLayoutParams->weight - marginSum)); } } } } -// TODO: Stretch and squeeze! // weight != 0 = fill remaining space. void LinearLayout::Layout() { const Bounds &bounds = bounds_; @@ -700,6 +713,8 @@ void ScrollView::Draw(UIContext &dc) { } dc.PushScissor(bounds_); + // For debugging layout issues, this can be useful. + // dc.FillRect(Drawable(0x60FF00FF), bounds_); views_[0]->Draw(dc); dc.PopScissor(); From 91ab27110183969167c05055ea6624933b70eeca Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 2 Feb 2015 09:21:19 +0100 Subject: [PATCH 1355/1445] Return a 0 d3dx version if failed to get any of the function pointers --- thin3d/d3dx9_loader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/thin3d/d3dx9_loader.cpp b/thin3d/d3dx9_loader.cpp index a5cffcfd88..bfb5e16d80 100644 --- a/thin3d/d3dx9_loader.cpp +++ b/thin3d/d3dx9_loader.cpp @@ -119,6 +119,10 @@ int LoadD3DX9Dynamic(bool debugVersion) { } hm_d3dx = loadDllLastVersion(&d3dx_version, debugVersion); + if (!hm_d3dx) { + ELOG("Failed to find D3DX dll."); + return 0; + } void* ptr = NULL; const int NERROR = -1; int _begin = 0; @@ -131,7 +135,7 @@ int LoadD3DX9Dynamic(bool debugVersion) { ELOG("Failed to load %i D3DX functions. This will not go well.", failedFunctions); } - return d3dx_version; + return failedFunctions > 0 ? 0 : d3dx_version; } int GetD3DXVersion() { From c12d4242a8f316464cc8015d1b5651f8c5b0c132 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 3 Feb 2015 00:10:38 +0100 Subject: [PATCH 1356/1445] Return a bool if you actually do something with a key event. --- ui/ui_screen.cpp | 6 +-- ui/view.cpp | 36 ++++++++++++++---- ui/view.h | 99 +++++++++++++++++++++++++----------------------- ui/viewgroup.cpp | 20 ++++++---- ui/viewgroup.h | 17 ++++----- 5 files changed, 102 insertions(+), 76 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index c13ebf5733..8384afee8a 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -64,7 +64,8 @@ bool UIScreen::key(const KeyInput &key) { } bool UIDialogScreen::key(const KeyInput &key) { - if ((key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) { + bool retval = UIScreen::key(key); + if (!retval && (key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) { if (finished_) { ELOG("Screen already finished"); } else { @@ -72,9 +73,8 @@ bool UIDialogScreen::key(const KeyInput &key) { screenManager()->finishDialog(this, DR_BACK); } return true; - } else { - return UIScreen::key(key); } + return retval; } bool UIScreen::axis(const AxisInput &axis) { diff --git a/ui/view.cpp b/ui/view.cpp index dd965e5769..63005765ec 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -252,15 +252,17 @@ bool IsTabRightKeyCode(int keyCode) { } } -void Clickable::Key(const KeyInput &key) { +bool Clickable::Key(const KeyInput &key) { if (!HasFocus() && key.deviceId != DEVICE_ID_MOUSE) { down_ = false; - return; + return false; } // TODO: Replace most of Update with this. + bool ret = false; if (key.flags & KEY_DOWN) { if (IsAcceptKeyCode(key.keyCode)) { down_ = true; + ret = true; } } if (key.flags & KEY_UP) { @@ -268,11 +270,13 @@ void Clickable::Key(const KeyInput &key) { if (down_) { Click(); down_ = false; + ret = true; } } else if (IsEscapeKeyCode(key.keyCode)) { down_ = false; } } + return ret; } void StickyChoice::Touch(const TouchInput &input) { @@ -292,9 +296,9 @@ void StickyChoice::Touch(const TouchInput &input) { } } -void StickyChoice::Key(const KeyInput &key) { +bool StickyChoice::Key(const KeyInput &key) { if (!HasFocus()) { - return; + return false; } // TODO: Replace most of Update with this. @@ -302,8 +306,10 @@ void StickyChoice::Key(const KeyInput &key) { if (IsAcceptKeyCode(key.keyCode)) { down_ = true; Click(); + return true; } } + return false; } void StickyChoice::FocusChanged(int focusFlags) { @@ -633,9 +639,9 @@ void TextEdit::Touch(const TouchInput &touch) { } } -void TextEdit::Key(const KeyInput &input) { +bool TextEdit::Key(const KeyInput &input) { if (!HasFocus()) - return; + return false; bool textChanged = false; // Process navigation keys. These aren't chars. if (input.flags & KEY_DOWN) { @@ -684,6 +690,9 @@ void TextEdit::Key(const KeyInput &input) { OnEnter.Trigger(e); break; } + case NKCODE_BACK: + case NKCODE_ESCAPE: + return false; } if (ctrlDown_) { @@ -761,6 +770,7 @@ void TextEdit::Key(const KeyInput &input) { e.v = this; OnTextChange.Trigger(e); } + return true; } void TextEdit::InsertAtCaret(const char *text) { @@ -818,7 +828,7 @@ void TriggerButton::GetContentDimensions(const UIContext &dc, float &w, float &h h = image.h; } -void Slider::Key(const KeyInput &input) { +bool Slider::Key(const KeyInput &input) { if (HasFocus() && (input.flags & KEY_DOWN)) { switch (input.keyCode) { case NKCODE_DPAD_LEFT: @@ -843,8 +853,13 @@ void Slider::Key(const KeyInput &input) { case NKCODE_MOVE_END: *value_ = maxValue_; break; + default: + return false; } Clamp(); + return true; + } else { + return false; } } @@ -888,7 +903,7 @@ void Slider::GetContentDimensions(const UIContext &dc, float &w, float &h) const h = 50; } -void SliderFloat::Key(const KeyInput &input) { +bool SliderFloat::Key(const KeyInput &input) { if (HasFocus() && (input.flags & KEY_DOWN)) { switch (input.keyCode) { case NKCODE_DPAD_LEFT: @@ -913,8 +928,13 @@ void SliderFloat::Key(const KeyInput &input) { case NKCODE_MOVE_END: *value_ = maxValue_; break; + default: + return true; } Clamp(); + return true; + } else { + return false; } } diff --git a/ui/view.h b/ui/view.h index 5910ea5a1c..75294379d6 100644 --- a/ui/view.h +++ b/ui/view.h @@ -305,7 +305,7 @@ public: // Please note that Touch is called ENTIRELY asynchronously from drawing! // Can even be called on a different thread! This is to really minimize latency, and decouple // touch response from the frame rate. Same with Key and Axis. - virtual void Key(const KeyInput &input) {} + virtual bool Key(const KeyInput &input) { return false; } virtual void Touch(const TouchInput &input) {} virtual void Axis(const AxisInput &input) {} virtual void Update(const InputState &input_state) {} @@ -392,10 +392,10 @@ public: InertView(LayoutParams *layoutParams) : View(layoutParams) {} - virtual void Key(const KeyInput &input) {} - virtual void Touch(const TouchInput &input) {} - virtual bool CanBeFocused() const { return false; } - virtual void Update(const InputState &input_state) {} + bool Key(const KeyInput &input) override { return false; } + void Touch(const TouchInput &input) override {} + bool CanBeFocused() const override { return false; } + void Update(const InputState &input_state) override {} }; @@ -405,10 +405,10 @@ public: Clickable(LayoutParams *layoutParams) : View(layoutParams), downCountDown_(0), dragging_(false), down_(false){} - virtual void Key(const KeyInput &input); - virtual void Touch(const TouchInput &input); + bool Key(const KeyInput &input) override; + void Touch(const TouchInput &input) override; - virtual void FocusChanged(int focusFlags); + void FocusChanged(int focusFlags) override; Event OnClick; @@ -432,8 +432,8 @@ public: Button(const std::string &text, ImageID imageID, LayoutParams *layoutParams = 0) : Clickable(layoutParams), text_(text), imageID_(imageID) {} - virtual void Draw(UIContext &dc); - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + void Draw(UIContext &dc) override; + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; const std::string &GetText() const { return text_; } private: @@ -451,14 +451,15 @@ public: : Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) { step_ = step <= 0 ? 1 : step; } - virtual void Draw(UIContext &dc); - virtual void Key(const KeyInput &input); - virtual void Touch(const TouchInput &input); - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + void Draw(UIContext &dc) override; + bool Key(const KeyInput &input) override; + void Touch(const TouchInput &input) override; + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; void SetShowPercent(bool s) { showPercent_ = s; } // OK to call this from the outside after having modified *value_ void Clamp(); + private: int *value_; bool showPercent_; @@ -473,10 +474,10 @@ class SliderFloat : public Clickable { public: SliderFloat(float *value, float minValue, float maxValue, LayoutParams *layoutParams = 0) : Clickable(layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) {} - virtual void Draw(UIContext &dc); - virtual void Key(const KeyInput &input); - virtual void Touch(const TouchInput &input); - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + void Draw(UIContext &dc) override; + bool Key(const KeyInput &input) override; + void Touch(const TouchInput &input) override; + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; // OK to call this from the outside after having modified *value_ void Clamp(); @@ -495,9 +496,9 @@ public: TriggerButton(uint32_t *bitField, uint32_t bit, int imageBackground, int imageForeground, LayoutParams *layoutParams) : View(layoutParams), down_(0.0), bitField_(bitField), bit_(bit), imageBackground_(imageBackground), imageForeground_(imageForeground) {} - virtual void Touch(const TouchInput &input); - virtual void Draw(UIContext &dc); - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + void Touch(const TouchInput &input) override; + void Draw(UIContext &dc) override; + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; private: int down_; // bitfield of pressed fingers, translates into bitField @@ -516,16 +517,16 @@ private: class Item : public InertView { public: Item(LayoutParams *layoutParams); - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; }; class ClickableItem : public Clickable { public: ClickableItem(LayoutParams *layoutParams); - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; // Draws the item background. - virtual void Draw(UIContext &dc); + void Draw(UIContext &dc) override; }; // Use to trigger something or open a submenu screen. @@ -539,8 +540,8 @@ public: : ClickableItem(layoutParams), atlasImage_(image), iconImage_(-1), centered_(false), highlighted_(false), selected_(false) {} virtual void HighlightChanged(bool highlighted); - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; - virtual void Draw(UIContext &dc); + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + void Draw(UIContext &dc) override; virtual void SetCentered(bool c) { centered_ = c; } @@ -572,9 +573,9 @@ public: StickyChoice(ImageID buttonImage, LayoutParams *layoutParams = 0) : Choice(buttonImage, layoutParams) {} - virtual void Key(const KeyInput &key); - virtual void Touch(const TouchInput &touch); - virtual void FocusChanged(int focusFlags); + bool Key(const KeyInput &key) override; + void Touch(const TouchInput &touch) override; + void FocusChanged(int focusFlags) override; void Press() { down_ = true; dragging_ = false; } void Release() { down_ = false; dragging_ = false; } @@ -590,7 +591,7 @@ public: InfoItem(const std::string &text, const std::string &rightText, LayoutParams *layoutParams = 0) : Item(layoutParams), text_(text), rightText_(rightText) {} - virtual void Draw(UIContext &dc); + void Draw(UIContext &dc) override; private: std::string text_; @@ -600,7 +601,8 @@ private: class ItemHeader : public Item { public: ItemHeader(const std::string &text, LayoutParams *layoutParams = 0); - virtual void Draw(UIContext &dc); + void Draw(UIContext &dc) override; + private: std::string text_; }; @@ -612,7 +614,7 @@ public: layoutParams_->width = FILL_PARENT; layoutParams_->height = 64; } - virtual void Draw(UIContext &dc); + void Draw(UIContext &dc) override; private: std::string text_; }; @@ -624,7 +626,7 @@ public: OnClick.Handle(this, &CheckBox::OnClicked); } - virtual void Draw(UIContext &dc); + void Draw(UIContext &dc) override; EventReturn OnClicked(EventParams &e); //allow external agents to toggle the checkbox @@ -646,7 +648,7 @@ public: virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { w = size_; h = size_; } - virtual void Draw(UIContext &dc) {} + void Draw(UIContext &dc) override {} private: float size_; }; @@ -659,8 +661,9 @@ public: TextView(const std::string &text, int textAlign, bool small, LayoutParams *layoutParams = 0) : InertView(layoutParams), text_(text), textAlign_(textAlign), textColor_(0xFFFFFFFF), small_(small) {} - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; - virtual void Draw(UIContext &dc) override; + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + void Draw(UIContext &dc) override; + void SetText(const std::string &text) { text_ = text; } void SetSmall(bool small) { small_ = small; } void SetTextColor(uint32_t color) { textColor_ = color; } @@ -679,10 +682,10 @@ public: const std::string &GetText() const { return text_; } void SetMaxLen(size_t maxLen) { maxLen_ = maxLen; } - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; - virtual void Draw(UIContext &dc) override; - virtual void Key(const KeyInput &key) override; - virtual void Touch(const TouchInput &touch) override; + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + void Draw(UIContext &dc) override; + bool Key(const KeyInput &key) override; + void Touch(const TouchInput &touch) override; Event OnTextChange; Event OnEnter; @@ -709,8 +712,8 @@ public: ImageView(int atlasImage, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0) : InertView(layoutParams), atlasImage_(atlasImage), sizeMode_(sizeMode) {} - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; - virtual void Draw(UIContext &dc); + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + void Draw(UIContext &dc) override; private: int atlasImage_; @@ -724,8 +727,8 @@ public: TextureView(Texture *texture, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0) : InertView(layoutParams), texture_(texture), sizeMode_(sizeMode) {} - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; - virtual void Draw(UIContext &dc); + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + void Draw(UIContext &dc) override; void SetTexture(Texture *texture) { texture_ = texture; } void SetColor(uint32_t color) { color_ = color; } @@ -743,8 +746,8 @@ public: Thin3DTextureView(Thin3DTexture *texture, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0) : InertView(layoutParams), texture_(texture), sizeMode_(sizeMode) {} - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; - virtual void Draw(UIContext &dc); + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + void Draw(UIContext &dc) override; void SetTexture(Thin3DTexture *texture) { texture_ = texture; } void SetColor(uint32_t color) { color_ = color; } @@ -760,8 +763,8 @@ public: ProgressBar(LayoutParams *layoutParams = 0) : InertView(layoutParams), progress_(0.0) {} - virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const; - virtual void Draw(UIContext &dc); + void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; + void Draw(UIContext &dc) override; void SetProgress(float progress) { if (progress > 1.0f) { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 2a2688fe42..98805e12de 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -83,13 +83,15 @@ void ViewGroup::Touch(const TouchInput &input) { } } -void ViewGroup::Key(const KeyInput &input) { +bool ViewGroup::Key(const KeyInput &input) { lock_guard guard(modifyLock_); + bool ret = false; for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. if ((*iter)->GetVisibility() == V_VISIBLE) - (*iter)->Key(input); + ret = ret || (*iter)->Key(input); } + return ret; } void ViewGroup::Axis(const AxisInput &input) { @@ -639,7 +641,7 @@ void ScrollView::Layout() { views_[0]->Layout(); } -void ScrollView::Key(const KeyInput &input) { +bool ScrollView::Key(const KeyInput &input) { if (visibility_ != V_VISIBLE) return ViewGroup::Key(input); @@ -666,7 +668,7 @@ void ScrollView::Key(const KeyInput &input) { break; } } - ViewGroup::Key(input); + return ViewGroup::Key(input); } const float friction = 0.92f; @@ -1028,15 +1030,18 @@ void ChoiceStrip::HighlightChoice(unsigned int choice){ } }; -void ChoiceStrip::Key(const KeyInput &input) { +bool ChoiceStrip::Key(const KeyInput &input) { + bool ret = false; if (input.flags & KEY_DOWN) { if (IsTabLeftKeyCode(input.keyCode) && selected_ > 0) { SetSelection(selected_ - 1); + ret = true; } else if (IsTabRightKeyCode(input.keyCode) && selected_ < (int)views_.size() - 1) { SetSelection(selected_ + 1); + ret = true; } } - ViewGroup::Key(input); + return ret || ViewGroup::Key(input); } void ChoiceStrip::Draw(UIContext &dc) { @@ -1188,8 +1193,7 @@ bool KeyEvent(const KeyInput &key, ViewGroup *root) { } } - root->Key(key); - retval = true; + retval = root->Key(key); // Ignore volume keys and stuff here. Not elegant but need to propagate bools through the view hierarchy as well... switch (key.keyCode) { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index ec69fb31c0..49223316e6 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -24,16 +24,16 @@ public: virtual ~ViewGroup(); // Pass through external events to children. - virtual void Key(const KeyInput &input); - virtual void Touch(const TouchInput &input); - virtual void Axis(const AxisInput &input); + virtual bool Key(const KeyInput &input) override; + virtual void Touch(const TouchInput &input) override; + virtual void Axis(const AxisInput &input) override; // By default, a container will layout to its own bounds. virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) = 0; virtual void Layout() = 0; virtual void Update(const InputState &input_state); - virtual void Draw(UIContext &dc); + virtual void Draw(UIContext &dc) override; // These should be unused. virtual float GetContentWidth() const { return 0.0f; } @@ -47,7 +47,7 @@ public: return view; } - virtual bool SetFocus(); + virtual bool SetFocus() override; virtual bool SubviewFocused(View *view); virtual void RemoveSubview(View *view); @@ -212,7 +212,7 @@ public: void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); - void Key(const KeyInput &input); + bool Key(const KeyInput &input); void Touch(const TouchInput &input); void Draw(UIContext &dc); @@ -259,11 +259,10 @@ public: void HighlightChoice(unsigned int choice); - - virtual void Key(const KeyInput &input); + bool Key(const KeyInput &input) override; void SetTopTabs(bool tabs) { topTabs_ = tabs; } - void Draw(UIContext &dc); + void Draw(UIContext &dc) override; Event OnChoice; From 778934641ef75bf5de967278984b62ab16ab0c0c Mon Sep 17 00:00:00 2001 From: sergiobenrocha2 Date: Tue, 3 Feb 2015 17:35:45 -0200 Subject: [PATCH 1357/1445] You need this if you don't want to install libglew-dev dependence. --- ext/glew/GL/glxew.h | 2 +- ext/glew/glew.c | 4 ++-- ext/glew/glewinfo.c | 4 ++-- ext/glew/visualinfo.c | 4 ++-- gfx/gl_common.h | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/glew/GL/glxew.h b/ext/glew/GL/glxew.h index f757939e15..ab3a7d98da 100644 --- a/ext/glew/GL/glxew.h +++ b/ext/glew/GL/glxew.h @@ -98,7 +98,7 @@ #include #include #include -#include +#include "glew.h" #ifdef __cplusplus extern "C" { diff --git a/ext/glew/glew.c b/ext/glew/glew.c index 2239864d68..9d43a24bdd 100644 --- a/ext/glew/glew.c +++ b/ext/glew/glew.c @@ -30,12 +30,12 @@ ** THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include "GL/glew.h" #if defined(_WIN32) # include #elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) -# include +# include "GL/glxew.h" #endif #include /* For size_t */ diff --git a/ext/glew/glewinfo.c b/ext/glew/glewinfo.c index 86ef352ff6..de6dad5c18 100644 --- a/ext/glew/glewinfo.c +++ b/ext/glew/glewinfo.c @@ -33,11 +33,11 @@ #include #include #include -#include +#include "GL/glew.h" #if defined(_WIN32) #include #elif !defined(__APPLE__) && !defined(__HAIKU__) || defined(GLEW_APPLE_GLX) -#include +#include "GL/glxew.h" #endif #ifdef GLEW_REGAL diff --git a/ext/glew/visualinfo.c b/ext/glew/visualinfo.c index 23a849996b..6a7df43717 100644 --- a/ext/glew/visualinfo.c +++ b/ext/glew/visualinfo.c @@ -33,13 +33,13 @@ #include #include #include -#include +#include "GL/glew.h" #if defined(_WIN32) #include #elif defined(__APPLE__) && !defined(GLEW_APPLE_GLX) #include #elif !defined(__HAIKU__) -#include +#include "GL/glxew.h" #endif #ifdef GLEW_MX diff --git a/gfx/gl_common.h b/gfx/gl_common.h index b8437bd399..ca030a6949 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -11,7 +11,7 @@ typedef char GLchar; #define GL_BGRA_EXT 0x80E1 #else // OpenGL -#include +#include "GL/glew.h" #if defined(__APPLE__) #include #else From 26bc250e9b0c18f442eec64cf7cd3d6342caf5d8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 9 Feb 2015 23:12:30 +0100 Subject: [PATCH 1358/1445] cleanup --- thin3d/d3dx9_loader.cpp | 3 +-- ui/ui_context.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/thin3d/d3dx9_loader.cpp b/thin3d/d3dx9_loader.cpp index bfb5e16d80..51dab2ec53 100644 --- a/thin3d/d3dx9_loader.cpp +++ b/thin3d/d3dx9_loader.cpp @@ -92,7 +92,7 @@ HMODULE loadDllLastVersion(unsigned int* version, bool debugVersion) { } std::wstring dllfname; - makeD3DX9dllFilename_by_versionW(dllfname, *version, debugVersion); + makeD3DX9dllFilename_by_versionW(dllfname, version ? *version : 0, debugVersion); HMODULE hm = ::LoadLibraryW(dllfname.c_str()); return hm; } @@ -123,7 +123,6 @@ int LoadD3DX9Dynamic(bool debugVersion) { ELOG("Failed to find D3DX dll."); return 0; } - void* ptr = NULL; const int NERROR = -1; int _begin = 0; diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index 5aa410c14c..bc7d2d6faa 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -5,6 +5,7 @@ #include "gfx/texture.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/draw_text.h" +#include "gfx_es2/gl_state.h" UIContext::UIContext() : uishader_(0), uitexture_(0), uidrawbuffer_(0), uidrawbufferTop_(0) { @@ -42,7 +43,6 @@ void UIContext::Begin() { thin3d_->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL); thin3d_->SetTexture(0, uitexture_); thin3d_->SetScissorEnabled(false); - UIBegin(uishader_); } From d2acef3a3b15683d553a593d1c4ca3decd3b0c41 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 15 Feb 2015 11:20:19 +0100 Subject: [PATCH 1359/1445] Add a bit of "overscroll" to the scrollview when keyboard-navigating. Add shadow support to TextView --- math/geom2d.h | 3 +++ ui/view.cpp | 4 ++++ ui/view.h | 7 ++++--- ui/viewgroup.cpp | 18 +++++++----------- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/math/geom2d.h b/math/geom2d.h index 15f2f99501..e937acafbc 100644 --- a/math/geom2d.h +++ b/math/geom2d.h @@ -62,6 +62,9 @@ struct Bounds { Bounds Expand(float amount) const { return Bounds(x - amount, y - amount, w + amount * 2, h + amount * 2); } + Bounds Offset(float xAmount, float yAmount) const { + return Bounds(x + xAmount, y + yAmount, w, h); + } float x; float y; diff --git a/ui/view.cpp b/ui/view.cpp index 63005765ec..9c66334e84 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -570,6 +570,10 @@ void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) con void TextView::Draw(UIContext &dc) { dc.SetFontStyle(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont); + if (shadow_) { + uint32_t shadowColor = 0x80000000; + dc.DrawTextRect(text_.c_str(), bounds_.Offset(1, 1), shadowColor, textAlign_); + } dc.DrawTextRect(text_.c_str(), bounds_, textColor_, textAlign_); } diff --git a/ui/view.h b/ui/view.h index 75294379d6..5f6e206aff 100644 --- a/ui/view.h +++ b/ui/view.h @@ -656,10 +656,10 @@ private: class TextView : public InertView { public: TextView(const std::string &text, LayoutParams *layoutParams = 0) - : InertView(layoutParams), text_(text), textAlign_(0), textColor_(0xFFFFFFFF), small_(false) {} + : InertView(layoutParams), text_(text), textAlign_(0), textColor_(0xFFFFFFFF), small_(false), shadow_(false) {} TextView(const std::string &text, int textAlign, bool small, LayoutParams *layoutParams = 0) - : InertView(layoutParams), text_(text), textAlign_(textAlign), textColor_(0xFFFFFFFF), small_(small) {} + : InertView(layoutParams), text_(text), textAlign_(textAlign), textColor_(0xFFFFFFFF), small_(small), shadow_(false) {} void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; void Draw(UIContext &dc) override; @@ -667,12 +667,13 @@ public: void SetText(const std::string &text) { text_ = text; } void SetSmall(bool small) { small_ = small; } void SetTextColor(uint32_t color) { textColor_ = color; } - + void SetShadow(bool shadow) { shadow_ = shadow; } private: std::string text_; int textAlign_; uint32_t textColor_; bool small_; + bool shadow_; }; class TextEdit : public View { diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 98805e12de..693de4aa3f 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -360,13 +360,7 @@ void MoveFocus(ViewGroup *root, FocusDirection direction) { if (neigh.view) { neigh.view->SetFocus(); - root->SubviewFocused(neigh.view); - - //if (neigh.parent != 0) { - // Let scrollviews and similar know that a child has been focused. - //neigh.parent->SubviewFocused(neigh.view); - //} } } @@ -741,22 +735,24 @@ bool ScrollView::SubviewFocused(View *view) { const Bounds &vBounds = view->GetBounds(); - // Scroll so that the focused view is visible. + // Scroll so that the focused view is visible, and a bit more so that headers etc gets visible too, in most cases. + const float overscroll = std::min(view->GetBounds().h / 1.5f, GetBounds().h / 4.0f); + switch (orientation_) { case ORIENT_HORIZONTAL: if (vBounds.x2() > bounds_.x2()) { - ScrollTo(scrollPos_ + vBounds.x2() - bounds_.x2()); + ScrollTo(scrollPos_ + vBounds.x2() - bounds_.x2() + overscroll); } if (vBounds.x < bounds_.x) { - ScrollTo(scrollPos_ + (vBounds.x - bounds_.x)); + ScrollTo(scrollPos_ + (vBounds.x - bounds_.x) - overscroll); } break; case ORIENT_VERTICAL: if (vBounds.y2() > bounds_.y2()) { - ScrollTo(scrollPos_ + vBounds.y2() - bounds_.y2()); + ScrollTo(scrollPos_ + vBounds.y2() - bounds_.y2() + overscroll); } if (vBounds.y < bounds_.y) { - ScrollTo(scrollPos_ + (vBounds.y - bounds_.y)); + ScrollTo(scrollPos_ + (vBounds.y - bounds_.y) - overscroll); } break; } From 7ed0e24b17a18c9cc5233b298dd6f07cffc73a60 Mon Sep 17 00:00:00 2001 From: sum2012 Date: Sun, 22 Feb 2015 16:17:22 +0800 Subject: [PATCH 1360/1445] Remove unused import --- .../com/henrikrydgard/libnative/NativeActivity.java | 11 ----------- .../com/henrikrydgard/libnative/NativeRenderer.java | 1 - 2 files changed, 12 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index c20861dd55..6c3dce6a48 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -1,13 +1,9 @@ package com.henrikrydgard.libnative; import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; import java.lang.reflect.Field; import java.util.List; import java.util.Locale; -import java.util.UUID; import android.annotation.SuppressLint; import android.annotation.TargetApi; @@ -30,10 +26,8 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; -import android.os.Handler; import android.os.Vibrator; import android.text.InputType; -import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.Gravity; @@ -166,11 +160,6 @@ public class NativeActivity extends Activity { this.shortcutParam = ((shortcutParam == null) ? "" : shortcutParam); } - private boolean useOpenSL() { - // Native OpenSL became available on Gingerbread. Let's use it! - return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD); - } - public void Initialize() { // Initialize audio classes. Do this here since detectOptimalAudioSettings() // needs audioManager diff --git a/android/src/com/henrikrydgard/libnative/NativeRenderer.java b/android/src/com/henrikrydgard/libnative/NativeRenderer.java index ea43320fdb..658eacc5e8 100644 --- a/android/src/com/henrikrydgard/libnative/NativeRenderer.java +++ b/android/src/com/henrikrydgard/libnative/NativeRenderer.java @@ -3,7 +3,6 @@ package com.henrikrydgard.libnative; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; -import android.content.Context; import android.graphics.Point; import android.opengl.GLES20; import android.opengl.GLSurfaceView; From 5f863cbbe8e9d90b1b07f7d0b87788ba7cbc2053 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 22 Feb 2015 13:30:35 -0800 Subject: [PATCH 1361/1445] Fix a small warning. --- image/zim_load.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image/zim_load.cpp b/image/zim_load.cpp index cfd7b1a7d5..5b1a3d09c0 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -121,7 +121,7 @@ int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int } } else { memcpy(*image, zim + 16, datasize - 16); - if (datasize - 16 != total_data_size) { + if (datasize - 16 != (size_t)total_data_size) { ELOG("Wrong size data in ZIM: %i vs %i", (int)(datasize-16), (int)total_data_size); } } From 52ce9c11185ddb3ca40950036d8b9926784640c0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 24 Feb 2015 00:22:21 +0100 Subject: [PATCH 1362/1445] Fix horizontal scrolling in ScrollViews and horizontal scroll gesture detection Use this to scroll the tabs in TabHolders, to make more tabs fit on screen. --- input/gesture_detector.cpp | 16 +++++++++++ ui/viewgroup.cpp | 56 ++++++++++++++++++++++++++++++-------- ui/viewgroup.h | 11 ++------ 3 files changed, 63 insertions(+), 20 deletions(-) diff --git a/input/gesture_detector.cpp b/input/gesture_detector.cpp index cd8b79a574..ef1951b474 100644 --- a/input/gesture_detector.cpp +++ b/input/gesture_detector.cpp @@ -59,6 +59,22 @@ TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds active_ = 0; } } + + if (touch.id == 0 && p.distanceX > p.distanceY) { + if (p.down) { + double timeDown = time_now_d() - p.downTime; + if (!active_ && p.distanceX * timeDown > 3) { + active_ |= GESTURE_DRAG_HORIZONTAL; + // Kill the drag + TouchInput inp2 = touch; + inp2.flags = TOUCH_UP | TOUCH_CANCEL; + return inp2; + } + } else { + active_ = 0; + } + } + return touch; } diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 693de4aa3f..142f998035 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -574,7 +574,9 @@ void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver Margins margins; if (views_.size()) { const LinearLayoutParams *linLayoutParams = static_cast(views_[0]->GetLayoutParams()); - if (!linLayoutParams->Is(LP_LINEAR)) linLayoutParams = 0; + if (!linLayoutParams->Is(LP_LINEAR)) { + linLayoutParams = 0; + } if (linLayoutParams) { margins = linLayoutParams->margins; } @@ -586,9 +588,11 @@ void ScrollView::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec ver if (views_.size()) { if (orientation_ == ORIENT_HORIZONTAL) { - views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED), MeasureSpec(AT_MOST, measuredHeight_ - (margins.top + margins.bottom))); + views_[0]->Measure(dc, MeasureSpec(UNSPECIFIED), MeasureSpec(UNSPECIFIED)); + MeasureBySpec(layoutParams_->height, views_[0]->GetMeasuredHeight(), vert, &measuredHeight_); } else { views_[0]->Measure(dc, MeasureSpec(AT_MOST, measuredWidth_ - (margins.left + margins.right)), MeasureSpec(UNSPECIFIED)); + MeasureBySpec(layoutParams_->width, views_[0]->GetMeasuredWidth(), horiz, &measuredWidth_); } if (orientation_ == ORIENT_VERTICAL && vert.type != EXACTLY && measuredHeight_ < views_[0]->GetBounds().h) measuredHeight_ = views_[0]->GetBounds().h; @@ -611,7 +615,6 @@ void ScrollView::Layout() { scrolled.w = views_[0]->GetMeasuredWidth() - (margins.left + margins.right); scrolled.h = views_[0]->GetMeasuredHeight() - (margins.top + margins.bottom); - switch (orientation_) { case ORIENT_HORIZONTAL: if (scrolled.w != lastViewSize_) { @@ -648,17 +651,17 @@ bool ScrollView::Key(const KeyInput &input) { ScrollRelative(250); break; case NKCODE_PAGE_DOWN: - ScrollRelative(bounds_.h - 50); + ScrollRelative((orientation_ == ORIENT_VERTICAL ? bounds_.h : bounds_.w) - 50); break; case NKCODE_PAGE_UP: - ScrollRelative(-bounds_.h + 50); + ScrollRelative(-(orientation_ == ORIENT_VERTICAL ? bounds_.h : bounds_.w) + 50); break; case NKCODE_MOVE_HOME: ScrollTo(0); break; case NKCODE_MOVE_END: if (views_.size()) - ScrollTo(views_[0]->GetBounds().h); + ScrollTo(orientation_ == ORIENT_VERTICAL ? views_[0]->GetBounds().h : views_[0]->GetBounds().w); break; } } @@ -673,9 +676,12 @@ void ScrollView::Touch(const TouchInput &input) { scrollStart_ = scrollPos_; inertia_ = 0.0f; } + + Gesture gesture = orientation_ == ORIENT_VERTICAL ? GESTURE_DRAG_VERTICAL : GESTURE_DRAG_HORIZONTAL; + if (input.flags & TOUCH_UP) { float info[4]; - if (!IsDragCaptured(input.id) && gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info)) { + if (!IsDragCaptured(input.id) && gesture_.GetGestureInfo(gesture, info)) { inertia_ = info[1]; } } @@ -684,7 +690,7 @@ void ScrollView::Touch(const TouchInput &input) { if (CanScroll() && !IsDragCaptured(input.id)) { input2 = gesture_.Update(input, bounds_); float info[4]; - if (gesture_.GetGestureInfo(GESTURE_DRAG_VERTICAL, info) && !(input.flags & TOUCH_DOWN)) { + if (gesture_.GetGestureInfo(gesture, info) && !(input.flags & TOUCH_DOWN)) { float pos = scrollStart_ - info[0]; ClampScrollPos(pos); scrollPos_ = pos; @@ -778,8 +784,8 @@ void ScrollView::ClampScrollPos(float &pos) { return; } - float childHeight = views_[0]->GetBounds().h; - float scrollMax = std::max(0.0f, childHeight - bounds_.h); + float childSize = orientation_ == ORIENT_VERTICAL ? views_[0]->GetBounds().h : views_[0]->GetBounds().w; + float scrollMax = std::max(0.0f, childSize - (orientation_ == ORIENT_VERTICAL ? bounds_.h : bounds_.w)); if (pos < 0.0f) { pos = 0.0f; @@ -799,7 +805,14 @@ void ScrollView::ScrollToBottom() { bool ScrollView::CanScroll() const { if (!views_.size()) return false; - return views_[0]->GetBounds().h > bounds_.h; + switch (orientation_) { + case ORIENT_VERTICAL: + return views_[0]->GetBounds().h > bounds_.h; + case ORIENT_HORIZONTAL: + return views_[0]->GetBounds().w > bounds_.w; + default: + return false; + } } void ScrollView::Update(const InputState &input_state) { @@ -955,6 +968,27 @@ void GridLayout::Layout() { } } +TabHolder::TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams) + : LinearLayout(Opposite(orientation), layoutParams), + tabStrip_(nullptr), tabScroll_(nullptr), + stripSize_(stripSize), + currentTab_(0) { + SetSpacing(0.0f); + if (orientation == ORIENT_HORIZONTAL) { + tabStrip_ = new ChoiceStrip(orientation, new LayoutParams(FILL_PARENT, WRAP_CONTENT)); + tabStrip_->SetTopTabs(true); + tabScroll_ = new ScrollView(orientation, new LayoutParams(FILL_PARENT, FILL_PARENT)); + tabScroll_->Add(tabStrip_); + Add(tabScroll_); + } else { + tabStrip_ = new ChoiceStrip(orientation, new LayoutParams(stripSize, WRAP_CONTENT)); + tabStrip_->SetTopTabs(true); + Add(tabStrip_); + tabScroll_ = nullptr; + } + tabStrip_->OnChoice.Handle(this, &TabHolder::OnTabClick); +} + EventReturn TabHolder::OnTabClick(EventParams &e) { tabs_[currentTab_]->SetVisibility(V_GONE); currentTab_ = e.a; diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 49223316e6..6126dc63d8 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -276,15 +276,7 @@ private: class TabHolder : public LinearLayout { public: - TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0) - : LinearLayout(Opposite(orientation), layoutParams), - stripSize_(stripSize), currentTab_(0) { - SetSpacing(0.0f); - tabStrip_ = new ChoiceStrip(orientation, new LinearLayoutParams(stripSize, WRAP_CONTENT)); - tabStrip_->SetTopTabs(true); - Add(tabStrip_); - tabStrip_->OnChoice.Handle(this, &TabHolder::OnTabClick); - } + TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0); template T *AddTab(const std::string &title, T *tabContents) { @@ -310,6 +302,7 @@ private: EventReturn OnTabClick(EventParams &e); ChoiceStrip *tabStrip_; + ScrollView *tabScroll_; float stripSize_; int currentTab_; From b01f18f3314860c3e6072e74420d76ecd319a10f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 28 Feb 2015 10:26:58 -0800 Subject: [PATCH 1363/1445] Support escaped comment marks like \# in inis. This fixes: * Float values like INF and IND. * Paths with \# in them. * Keys with \# in them (in case of i18n strings.) A small change in behavior: ; at the start of the line is now always a comment. Previously, if the line had a comment already, adding ; to the front of it would not comment it out. --- file/ini_file.cpp | 138 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 115 insertions(+), 23 deletions(-) diff --git a/file/ini_file.cpp b/file/ini_file.cpp index 615df16a12..9070bb8079 100644 --- a/file/ini_file.cpp +++ b/file/ini_file.cpp @@ -26,34 +26,126 @@ #define strcasecmp _stricmp #endif +static bool ParseLineKey(const std::string &line, size_t &pos, std::string *keyOut) { + std::string key = ""; + + while (pos < line.size()) { + size_t next = line.find_first_of("=#", pos); + if (next == line.npos || next == 0) { + // Key never ended or empty, invalid. + return false; + } else if (line[next] == '#') { + if (line[next - 1] != '\\') { + // Value commented out before =, so not valid. + return false; + } + + // Escaped. + key += line.substr(pos, next - pos - 1) + "#"; + pos = next + 1; + } else if (line[next] == '=') { + // Hurray, done. + key += line.substr(pos, next - pos); + pos = next + 1; + break; + } + } + + if (keyOut) { + *keyOut = StripSpaces(key); + } + return true; +} + +static bool ParseLineValue(const std::string &line, size_t &pos, std::string *valueOut) { + std::string value = ""; + + while (pos < line.size()) { + size_t next = line.find('#', pos); + if (next == line.npos) { + value += line.substr(pos); + pos = line.npos; + break; + } else if (line[next - 1] != '\\') { + // It wasn't escaped, so finish before the #. + value += line.substr(pos, next - pos); + // Include the comment's # in pos. + pos = next; + break; + } else { + // Escaped. + value += line.substr(pos, next - pos - 1) + "#"; + pos = next + 1; + } + } + + if (valueOut) { + *valueOut = StripQuotes(StripSpaces(value)); + } + + return true; +} + +static bool ParseLineComment(const std::string& line, size_t &pos, std::string *commentOut) { + // Don't bother with anything if we don't need the comment data. + if (commentOut) { + // Include any whitespace/formatting in the comment. + size_t commentStartPos = pos; + if (commentStartPos != line.npos) { + while (commentStartPos > 0 && line[commentStartPos - 1] <= ' ') { + --commentStartPos; + } + + *commentOut = line.substr(commentStartPos); + } else { + // There was no comment. + commentOut->clear(); + } + } + + pos = line.npos; + return true; +} + // Ugh, this is ugly. static bool ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) { - int FirstEquals = (int)line.find("=", 0); - int FirstCommentChar = -1; + // Rules: + // 1. A line starting with ; is commented out. + // 2. A # in a line (and all the space before it) is the comment. + // 3. A \# in a line is not part of a comment and becomes # in the value. + // 4. Whitespace around values is removed. + // 5. Double quotes around values is removed. - // Comments - if (FirstCommentChar < 0) - FirstCommentChar = - (int)line.find("#", FirstEquals > 0 ? FirstEquals : 0); - if (FirstCommentChar < 0 && line[0] == ';') - FirstCommentChar = 0; + if (line.size() < 2 || line[0] == ';') + return false; - // Allow preservation of spacing before comment - while (FirstCommentChar > 0 && line[FirstCommentChar - 1] <= ' ') - { - FirstCommentChar--; + size_t pos = 0; + if (!ParseLineKey(line, pos, keyOut)) + return false; + if (!ParseLineValue(line, pos, valueOut)) + return false; + if (!ParseLineComment(line, pos, commentOut)) + return false; + + return true; +} + +static std::string EscapeComments(const std::string &value) { + std::string result = ""; + + for (size_t pos = 0; pos < value.size(); ) { + size_t next = value.find('#', pos); + if (next == value.npos) { + result += value.substr(pos); + pos = value.npos; + } else { + result += value.substr(pos, next - pos) + "\\#"; + pos = next + 1; + } } - if ((FirstEquals >= 0) && ((FirstCommentChar < 0) || (FirstEquals < FirstCommentChar))) - { - // Yes, a valid key/value line! - *keyOut = StripSpaces(line.substr(0, FirstEquals)); - if (commentOut) *commentOut = FirstCommentChar > 0 ? line.substr(FirstCommentChar) : std::string(""); - if (valueOut) *valueOut = StripQuotes(StripSpaces(line.substr(FirstEquals + 1, FirstCommentChar - FirstEquals - 1))); - return true; - } - return false; + return result; } void IniFile::Section::Clear() { @@ -80,12 +172,12 @@ void IniFile::Section::Set(const char* key, const char* newValue) if (line) { // Change the value - keep the key and comment - *line = StripSpaces(key) + " = " + newValue + commented; + *line = StripSpaces(key) + " = " + EscapeComments(newValue) + commented; } else { // The key did not already exist in this section - let's add it. - lines.push_back(std::string(key) + " = " + newValue); + lines.push_back(std::string(key) + " = " + EscapeComments(newValue)); } } From 77ff1bc1c2c48d118f8de352500d288642fd9b2f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 28 Feb 2015 12:17:18 -0800 Subject: [PATCH 1364/1445] Detect GLES version more accurately. --- gfx_es2/gl_state.cpp | 57 ++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 1b864e6e64..cdbd357cef 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -160,25 +160,52 @@ void CheckGLExtensions() { #endif #if defined(USING_GLES2) - // Try to load GLES 3.0 only if "3.0" found in version - // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited - // number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584. - // TODO: Do something way more robust! - bool gl_3_0_in_string = strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0"); - bool gl_3_1_in_string = strstr(versionStr, "3.1") && strstr(glslVersionStr, "3.1"); // intentionally left out .1 - if ((gl_3_0_in_string || gl_3_1_in_string) && gl3stubInit()) { - gl_extensions.ver[0] = 3; - if (gl_3_1_in_string) { +#ifdef GL_MAJOR_VERSION + // Before grabbing the values, reset the error. + glGetError(); + glGetIntegerv(GL_MAJOR_VERSION, &gl_extensions.ver[0]); + glGetIntegerv(GL_MINOR_VERSION, &gl_extensions.ver[1]); + if (glGetError() != GL_NO_ERROR) { + gl_extensions.ver[0] = 2; + gl_extensions.ver[1] = 0; + } +#endif + + // If the above didn't give us a version, or gave us a crazy version, fallback. + if (gl_extensions.ver[0] < 3 || gl_extensions.ver[0] > 5) { + // Try to load GLES 3.0 only if "3.0" found in version + // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited + // number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584. + bool gl_3_0_in_string = strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0"); + bool gl_3_1_in_string = strstr(versionStr, "3.1") && strstr(glslVersionStr, "3.1"); // intentionally left out .1 + if ((gl_3_0_in_string || gl_3_1_in_string) && gl3stubInit()) { + gl_extensions.ver[0] = 3; + if (gl_3_1_in_string) { + gl_extensions.ver[1] = 1; + } + gl_extensions.GLES3 = true; + // Though, let's ban Mali from the GLES 3 path for now, see #4078 + if (strstr(renderer, "Mali") != 0) { + gl_extensions.GLES3 = false; + } + } else { + // Just to be safe. + gl_extensions.ver[0] = 2; + gl_extensions.ver[1] = 0; + } + } else { + // Otherwise, let's trust GL_MAJOR_VERSION. Note that Mali is intentionally not banned here. + if (gl_extensions.ver[0] >= 3) { + gl_extensions.GLES3 = gl3stubInit(); + } + } + + if (gl_extensions.GLES3) { + if (gl_extensions.ver[1] >= 1) { ILOG("OpenGL ES 3.1 support detected!\n"); - gl_extensions.ver[1] = 1; } else { ILOG("OpenGL ES 3.0 support detected!\n"); } - gl_extensions.GLES3 = true; - // Though, let's ban Mali from the GLES 3 path for now, see #4078 - if (strstr(renderer, "Mali") != 0) { - gl_extensions.GLES3 = false; - } } #else // If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable From 6f3125ac4d8ff1409d06ad170756498e4c2e8350 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 1 Mar 2015 16:09:52 +0100 Subject: [PATCH 1365/1445] UI framework: Make keyboard repeats time-based instead of frame count based --- ui/viewgroup.cpp | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 142f998035..8168384692 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -3,6 +3,7 @@ #include "base/functional.h" #include "base/logging.h" #include "base/mutex.h" +#include "base/timeutil.h" #include "input/keycodes.h" #include "ui/ui_context.h" #include "ui/view.h" @@ -1172,9 +1173,9 @@ static int frameCount; struct HeldKey { int key; int deviceId; - int startFrame; + double triggerTime; - // Ignores startFrame + // Ignores startTime bool operator <(const HeldKey &other) const { if (key < other.key) return true; return false; @@ -1184,8 +1185,8 @@ struct HeldKey { static std::set heldKeys; -static const int repeatDelay = 15; // 250ms -static const int repeatInterval = 5; // 66ms +const double repeatDelay = 15 * (1.0 / 60.0f); // 15 frames like before. +const double repeatInterval = 5 * (1.0 / 60.0f); // 5 frames like before. bool KeyEvent(const KeyInput &key, ViewGroup *root) { bool retval = false; @@ -1197,7 +1198,7 @@ bool KeyEvent(const KeyInput &key, ViewGroup *root) { HeldKey hk; hk.key = key.keyCode; hk.deviceId = key.deviceId; - hk.startFrame = frameCount; + hk.triggerTime = time_now_d() + repeatDelay; // Check if the key is already held. If it is, ignore it. This is to avoid // multiple key repeat mechanisms colliding. @@ -1217,7 +1218,7 @@ bool KeyEvent(const KeyInput &key, ViewGroup *root) { HeldKey hk; hk.key = key.keyCode; hk.deviceId = key.deviceId; - hk.startFrame = 0; // irrelevant + hk.triggerTime = 0.0; // irrelevant heldKeys.erase(hk); retval = true; } @@ -1238,19 +1239,27 @@ bool KeyEvent(const KeyInput &key, ViewGroup *root) { } static void ProcessHeldKeys(ViewGroup *root) { - for (auto iter = heldKeys.begin(); iter != heldKeys.end(); ++iter) { - if (iter->startFrame < frameCount - repeatDelay) { - int frame = frameCount - (iter->startFrame + repeatDelay); - if ((frame % repeatInterval) == 0) { - KeyInput key; - key.keyCode = iter->key; - key.deviceId = iter->deviceId; - key.flags = KEY_DOWN; - KeyEvent(key, root); + double now = time_now_d(); - lock_guard lock(focusLock); - focusMoves.push_back(key.keyCode); - } +restart: + + for (std::set::iterator iter = heldKeys.begin(); iter != heldKeys.end(); ++iter) { + if (iter->triggerTime < now) { + KeyInput key; + key.keyCode = iter->key; + key.deviceId = iter->deviceId; + key.flags = KEY_DOWN; + KeyEvent(key, root); + + lock_guard lock(focusLock); + focusMoves.push_back(key.keyCode); + + // Cannot modify the current item when looping over a set, so let's do this instead. + HeldKey hk = *iter; + heldKeys.erase(hk); + hk.triggerTime = now + repeatInterval; + heldKeys.insert(hk); + goto restart; } } } From dd1a40653fc3832f3100591bb3def90b33607711 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 1 Mar 2015 21:01:49 +0100 Subject: [PATCH 1366/1445] Experiment: Disable 24-bit Z and interleaved depth/stencil on mali. --- gfx_es2/gl_state.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index cdbd357cef..91b27cd16b 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -312,6 +312,13 @@ void CheckGLExtensions() { gl_extensions.EXT_blend_minmax = true; gl_extensions.EXT_unpack_subimage = true; #endif + + // Disable 24D8S buffers on Mali. See issue #7218 + if (gl_extensions.gpuVendor == GPU_VENDOR_ARM) { + gl_extensions.OES_depth24 = false; + gl_extensions.OES_packed_depth_stencil = false; + } + // GLES 3 subsumes many ES2 extensions. if (gl_extensions.GLES3) { gl_extensions.EXT_unpack_subimage = true; From 30a362f227e2ea6f09fdf7395347e6ae51d906d4 Mon Sep 17 00:00:00 2001 From: Peter Tissen Date: Fri, 6 Mar 2015 00:19:31 -0800 Subject: [PATCH 1367/1445] Make compilable with VS2015 So Microsoft decided to make their C runtime conform to C99 --- base/compat.h | 2 +- ext/libzip/zipint.h | 2 ++ net/url.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/base/compat.h b/base/compat.h index cd47806265..e8e9621cf9 100644 --- a/base/compat.h +++ b/base/compat.h @@ -2,7 +2,7 @@ // Implement C99 functions and similar that are missing in MSVC. -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 1900 int c99_snprintf(char* str, size_t size, const char* format, ...); #define snprintf c99_snprintf diff --git a/ext/libzip/zipint.h b/ext/libzip/zipint.h index f7e3c34b8b..26e9b73280 100644 --- a/ext/libzip/zipint.h +++ b/ext/libzip/zipint.h @@ -40,7 +40,9 @@ #define ZIP_EXTERN #define fseeko fseek #define ftello ftell +#if _MSC_VER < 1900 #define snprintf _snprintf +#endif #ifndef strcasecmp #define strcasecmp _stricmp #endif diff --git a/net/url.h b/net/url.h index b6621f3b6d..dedf44c7db 100644 --- a/net/url.h +++ b/net/url.h @@ -7,7 +7,7 @@ #include "base/basictypes.h" -#if defined(_MSC_VER) +#if defined(_MSC_VER) && _MSC_VER < 1900 #undef snprintf #define snprintf _snprintf #endif From 12010bb4ce09fd80295d4e45a40724a0fc8c470d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 5 Mar 2015 09:49:25 +0100 Subject: [PATCH 1368/1445] Revert "Experiment: Disable 24-bit Z and interleaved depth/stencil on mali." This reverts commit dd1a40653fc3832f3100591bb3def90b33607711. --- gfx_es2/gl_state.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 91b27cd16b..cdbd357cef 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -312,13 +312,6 @@ void CheckGLExtensions() { gl_extensions.EXT_blend_minmax = true; gl_extensions.EXT_unpack_subimage = true; #endif - - // Disable 24D8S buffers on Mali. See issue #7218 - if (gl_extensions.gpuVendor == GPU_VENDOR_ARM) { - gl_extensions.OES_depth24 = false; - gl_extensions.OES_packed_depth_stencil = false; - } - // GLES 3 subsumes many ES2 extensions. if (gl_extensions.GLES3) { gl_extensions.EXT_unpack_subimage = true; From 516dbf37e44114984289a0800a662e4a72dd461e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 7 Mar 2015 01:29:38 +0100 Subject: [PATCH 1369/1445] ARM64 buildfix --- Android.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Android.mk b/Android.mk index 0bfee1bbb4..ed517e5302 100644 --- a/Android.mk +++ b/Android.mk @@ -123,6 +123,8 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ else ifeq ($(TARGET_ARCH_ABI),armeabi) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -DARM -DARMEABI -march=armv6 +else ifeq ($(TARGET_ARCH_ABI),arm64-v8a) +LOCAL_CFLAGS := $(LOCAL_CFLAGS) -D_ARCH_64 -DARM64 else ifeq ($(TARGET_ARCH_ABI),x86) LOCAL_CFLAGS := $(LOCAL_CFLAGS) -D_M_IX86 LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ From 23150858a4d593e2725e6ac8ae00e2bb4ffe18eb Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 7 Mar 2015 13:56:17 +0100 Subject: [PATCH 1370/1445] ARM64: Make sure that eglGetProcAddress is declared, so the return value doesn't get truncated to int. --- gfx/gl_common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index ca030a6949..d716602de3 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -6,6 +6,7 @@ #elif defined(USING_GLES2) #include #include +#include "EGL/egl.h" // At least Nokia platforms need the three below #include typedef char GLchar; From 656fe78656a99b92cfbd144a148e93e95f5dab04 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 7 Mar 2015 16:09:17 -0800 Subject: [PATCH 1371/1445] Check for ARM_shader_framebuffer_fetch. Also, let's combine them too. Unfortunately, the shader needs a require that matches the one they have, so we need the individual flags also. --- gfx_es2/gl_state.cpp | 2 ++ gfx_es2/gpu_features.h | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index cdbd357cef..9379aa9b6c 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -266,6 +266,8 @@ void CheckGLExtensions() { gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; + gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0; + gl_extensions.ANY_shader_framebuffer_fetch = gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.NV_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; #if defined(ANDROID) || defined(BLACKBERRY) diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 37faea8fde..79309b8b19 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -67,10 +67,16 @@ struct GLExtensions { bool NV_framebuffer_blit; bool PBO_NV; // GL_NV_pixel_buffer_object + // ARM + bool ARM_shader_framebuffer_fetch; + // EGL bool EGL_NV_system_time; bool EGL_NV_coverage_sample; + // Convenience (in case we need to know which, but can treat them mostly the same.) + bool ANY_shader_framebuffer_fetch; + // Bugs int bugs; From bf4a5f03522a255723c1c098d97f42fd66f26c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Apr 2015 11:13:38 +0200 Subject: [PATCH 1372/1445] Detect the Android UIMode, use as device type. For better automatic configuration for things like Android TV. --- android/app-android.cpp | 12 ++++++++---- .../libnative/NativeActivity.java | 19 +++++++++++++++++-- .../henrikrydgard/libnative/NativeApp.java | 6 +++++- .../henrikrydgard/libnative/NativeGLView.java | 14 +++++++++----- base/BlackberryMain.cpp | 2 ++ base/NativeApp.h | 11 ++++++++++- base/PCMain.cpp | 12 ++++++++++++ base/QtMain.cpp | 18 ++++++++++++++++++ 8 files changed, 81 insertions(+), 13 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 37e3626815..d27f90d2ea 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -38,8 +38,8 @@ struct FrameCommand { std::string params; }; -recursive_mutex frameCommandLock; -std::queue frameCommands; +static recursive_mutex frameCommandLock; +static std::queue frameCommands; std::string systemName; std::string langRegion; @@ -57,6 +57,7 @@ static int optimalSampleRate = 0; static int sampleRate = 0; static int framesPerBuffer = 0; static int androidVersion; +static int deviceType; // Should only be used for display detection during startup (for config defaults etc) static int display_xres; @@ -117,6 +118,8 @@ int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_SYSTEMVERSION: return androidVersion; + case SYSPROP_DEVICE_TYPE: + return deviceType; case SYSPROP_DISPLAY_XRES: return display_xres; case SYSPROP_DISPLAY_YRES: @@ -184,7 +187,7 @@ extern "C" jstring Java_com_henrikrydgard_libnative_NativeApp_queryConfig } extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init - (JNIEnv *env, jclass, jstring jdevicetype, jint jxres, jint jyres, jstring jlangRegion, jstring japkpath, + (JNIEnv *env, jclass, jstring jmodel, jint jdeviceType, jint jxres, jint jyres, jstring jlangRegion, jstring japkpath, jstring jdataDir, jstring jexternalDir, jstring jlibraryDir, jstring jshortcutParam, jstring jinstallID, jint jAndroidVersion) { jniEnvUI = env; @@ -195,6 +198,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init renderer_inited = false; first_lost = true; androidVersion = jAndroidVersion; + deviceType = jdeviceType; g_buttonTracker.Reset(); @@ -210,7 +214,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init std::string apkPath = GetJavaString(env, japkpath); VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); - systemName = GetJavaString(env, jdevicetype); + systemName = GetJavaString(env, jmodel); langRegion = GetJavaString(env, jlangRegion); std::string externalDir = GetJavaString(env, jexternalDir); diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 6c3dce6a48..1ba6a72c4e 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -10,6 +10,7 @@ import android.annotation.TargetApi; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; +import android.app.UiModeManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -186,6 +187,20 @@ public class NativeActivity extends Activity { throw new RuntimeException("Unable to locate assets, aborting..."); } + int deviceType = NativeApp.DEVICE_TYPE_MOBILE; + UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE); + switch (uiModeManager.getCurrentModeType()) { + case Configuration.UI_MODE_TYPE_TELEVISION: + deviceType = NativeApp.DEVICE_TYPE_TV; + Log.i(TAG, "Running on an Android TV Device"); + break; + case Configuration.UI_MODE_TYPE_DESK: + deviceType = NativeApp.DEVICE_TYPE_DESKTOP; + Log.i(TAG, "Running on an Android desktop computer (!)"); + break; + // All other device types are treated the same. + } + isXperiaPlay = IsXperiaPlay(); String libraryDir = getApplicationLibraryDir(appInfo); @@ -195,13 +210,13 @@ public class NativeActivity extends Activity { String dataDir = this.getFilesDir().getAbsolutePath(); String apkFilePath = appInfo.sourceDir; - String deviceType = Build.MANUFACTURER + ":" + Build.MODEL; + String model = Build.MANUFACTURER + ":" + Build.MODEL; String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry(); Point displaySize = new Point(); GetScreenSize(displaySize); NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(deviceType, displaySize.x, displaySize.y, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, Build.VERSION.SDK_INT); + NativeApp.init(model, deviceType, displaySize.x, displaySize.y, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, Build.VERSION.SDK_INT); // OK, config should be initialized, we can query for screen rotation. if (Build.VERSION.SDK_INT >= 9) { diff --git a/android/src/com/henrikrydgard/libnative/NativeApp.java b/android/src/com/henrikrydgard/libnative/NativeApp.java index e03bf17db8..a392f5b61a 100644 --- a/android/src/com/henrikrydgard/libnative/NativeApp.java +++ b/android/src/com/henrikrydgard/libnative/NativeApp.java @@ -9,7 +9,11 @@ public class NativeApp { public final static int DEVICE_ID_MOUSE = 2; public final static int DEVICE_ID_PAD_0 = 10; - public static native void init(String deviceType, int xres, int yres, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, int androidVersion); + public final static int DEVICE_TYPE_MOBILE = 0; + public final static int DEVICE_TYPE_TV = 1; + public final static int DEVICE_TYPE_DESKTOP = 2; + + public static native void init(String model, int deviceType, int xres, int yres, String languageRegion, String apkPath, String dataDir, String externalDir, String libraryDir, String shortcutParam, String installID, int androidVersion); public static native void audioInit(); public static native void audioShutdown(); diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index cca8e0fbab..2451c87b45 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -54,11 +54,15 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mController = Controller.getInstance(activity); - if (mController.init()) { - Log.i(TAG, "MOGA initialized"); - mController.setListener(this, new Handler()); - } else { - Log.i(TAG, "MOGA failed to initialize. No moga detected?"); + try { + if (mController.init()) { + Log.i(TAG, "MOGA initialized"); + mController.setListener(this, new Handler()); + } else { + Log.i(TAG, "MOGA failed to initialize. No moga detected?"); + } + } catch (java.lang.RuntimeException e) { + Log.i(TAG, "MOGA failed to initialize due to the bug."); } } diff --git a/base/BlackberryMain.cpp b/base/BlackberryMain.cpp index 75bab2aa6c..f6bc2ece11 100644 --- a/base/BlackberryMain.cpp +++ b/base/BlackberryMain.cpp @@ -50,6 +50,8 @@ int System_GetPropertyInt(SystemProperty prop) { return 44100; case SYSPROP_DISPLAY_REFRESH_RATE: return 60000; + case SYSPROP_DEVICE_TYPE: + return DEVICE_TYPE_MOBILE; default: return -1; } diff --git a/base/NativeApp.h b/base/NativeApp.h index b24a284782..7eb3eb43c5 100644 --- a/base/NativeApp.h +++ b/base/NativeApp.h @@ -119,6 +119,13 @@ bool System_InputBoxGetString(const char *title, const char *defaultValue, char bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultValue, std::wstring &outValue); void System_SendMessage(const char *command, const char *parameter); +// This will get muddy with multi-screen support :/ But this will always be the type of the main device. +enum SystemDeviceType { + DEVICE_TYPE_MOBILE = 0, // phones and pads + DEVICE_TYPE_TV = 1, // Android TV and similar + DEVICE_TYPE_DESKTOP = 2, // Desktop computer +}; + enum SystemProperty { SYSPROP_NAME, SYSPROP_LANGREGION, @@ -133,6 +140,8 @@ enum SystemProperty { SYSPROP_DISPLAY_REFRESH_RATE, // returns 1000*the refresh rate in Hz as it can be non-integer SYSPROP_MOGA_VERSION, + SYSPROP_DEVICE_TYPE, + // Exposed on Android. Choosing the optimal sample rate for audio // will result in lower latencies. Buffer size is automatically matched // by the OpenSL audio backend, only exposed here for debugging/info. @@ -143,4 +152,4 @@ enum SystemProperty { }; std::string System_GetProperty(SystemProperty prop); -int System_GetPropertyInt(SystemProperty prop); \ No newline at end of file +int System_GetPropertyInt(SystemProperty prop); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 536d2fd5da..51228d4f89 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -318,6 +318,18 @@ int System_GetPropertyInt(SystemProperty prop) { return 44100; case SYSPROP_DISPLAY_REFRESH_RATE: return 60000; + case SYSPROP_DEVICE_TYPE: +#ifdef _WIN32 + return DEVICE_TYPE_DESKTOP; +#elif defined(MAEMO) + return DEVICE_TYPE_MOBILE; +#elif __linux__ + return DEVICE_TYPE_DESKTOP; +#elif __APPLE__ + return DEVICE_TYPE_DESKTOP; +#else + return DEVICE_TYPE_MOBILE; +#endif default: return -1; } diff --git a/base/QtMain.cpp b/base/QtMain.cpp index 0e82b028ff..bcc23a514e 100644 --- a/base/QtMain.cpp +++ b/base/QtMain.cpp @@ -75,6 +75,24 @@ int System_GetPropertyInt(SystemProperty prop) { return 44100; case SYSPROP_DISPLAY_REFRESH_RATE: return 60000; + case SYSPROP_DEVICE_TYPE: +#ifdef __SYMBIAN32__ + return DEVICE_TYPE_MOBILE; +#elif defined(BLACKBERRY) + return DEVICE_TYPE_MOBILE; +#elif defined(MAEMO) + return DEVICE_TYPE_MOBILE; +#elif defined(ANDROID) + return DEVICE_TYPE_MOBILE; +#elif defined(Q_OS_LINUX) + return DEVICE_TYPE_DESKTOP; +#elif defined(_WIN32) + return DEVICE_TYPE_DESKTOP; +#elif defined(Q_OS_MAC) + return DEVICE_TYPE_DESKTOP; +#else + return DEVICE_TYPE_DESKTOP; +#endif default: return -1; } From 98083c8985ef52cb018fc8bd4ec89d2aaefccdd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Apr 2015 11:14:21 +0200 Subject: [PATCH 1373/1445] UI: Make InfoView focusable, make it possible to make TextView focusable. --- ui/view.cpp | 6 ++++++ ui/view.h | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ui/view.cpp b/ui/view.cpp index 9c66334e84..e0881ce849 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -414,7 +414,13 @@ void Choice::Draw(UIContext &dc) { void InfoItem::Draw(UIContext &dc) { Item::Draw(dc); + if (HasFocus()) { + UI::Style style = dc.theme->itemFocusedStyle; + style.background.color &= 0x7fffffff; + dc.FillRect(style.background, bounds_); + } int paddingX = 12; + dc.SetFontStyle(dc.theme->uiFont); dc.DrawText(text_.c_str(), bounds_.x + paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER); dc.DrawText(rightText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), 0xFFFFFFFF, ALIGN_VCENTER | ALIGN_RIGHT); diff --git a/ui/view.h b/ui/view.h index 5f6e206aff..929c6ba96c 100644 --- a/ui/view.h +++ b/ui/view.h @@ -593,6 +593,9 @@ public: void Draw(UIContext &dc) override; + // These are focusable so that long lists of them can be keybaord scrolled. + bool CanBeFocused() const override { return true; } + private: std::string text_; std::string rightText_; @@ -656,10 +659,10 @@ private: class TextView : public InertView { public: TextView(const std::string &text, LayoutParams *layoutParams = 0) - : InertView(layoutParams), text_(text), textAlign_(0), textColor_(0xFFFFFFFF), small_(false), shadow_(false) {} + : InertView(layoutParams), text_(text), textAlign_(0), textColor_(0xFFFFFFFF), small_(false), shadow_(false), focusable_(false) {} TextView(const std::string &text, int textAlign, bool small, LayoutParams *layoutParams = 0) - : InertView(layoutParams), text_(text), textAlign_(textAlign), textColor_(0xFFFFFFFF), small_(small), shadow_(false) {} + : InertView(layoutParams), text_(text), textAlign_(textAlign), textColor_(0xFFFFFFFF), small_(small), shadow_(false), focusable_(false) {} void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; void Draw(UIContext &dc) override; @@ -668,12 +671,17 @@ public: void SetSmall(bool small) { small_ = small; } void SetTextColor(uint32_t color) { textColor_ = color; } void SetShadow(bool shadow) { shadow_ = shadow; } + void SetFocusable(bool focusable) { focusable_ = focusable; } + + bool CanBeFocused() const override { return focusable_; } + private: std::string text_; int textAlign_; uint32_t textColor_; bool small_; bool shadow_; + bool focusable_; }; class TextEdit : public View { From 2f5b1c6ebe10e1d7ee4c3429ebfc5c7e71b6d52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Apr 2015 11:35:55 +0200 Subject: [PATCH 1374/1445] Add Mupen64's hack around the broken Moga library (that won't work in android 21+) --- .../com/henrikrydgard/libnative/MogaHack.java | 117 ++++++++++++++++++ .../henrikrydgard/libnative/NativeGLView.java | 13 +- 2 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 android/src/com/henrikrydgard/libnative/MogaHack.java diff --git a/android/src/com/henrikrydgard/libnative/MogaHack.java b/android/src/com/henrikrydgard/libnative/MogaHack.java new file mode 100644 index 0000000000..2eb88354a3 --- /dev/null +++ b/android/src/com/henrikrydgard/libnative/MogaHack.java @@ -0,0 +1,117 @@ +/** + * Mupen64PlusAE, an N64 emulator for the Android platform + * + * Copyright (C) 2013 Paul Lamb + * + * This file is part of Mupen64PlusAE. + * + * Mupen64PlusAE 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, either version 3 of the + * License, or (at your option) any later version. + * + * Mupen64PlusAE 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Mupen64PlusAE. If + * not, see . + * + * Authors: Paul Lamb + */ +package com.henrikrydgard.libnative; + +import java.util.List; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.os.Build; +import android.util.Log; + +import com.bda.controller.Controller; +import com.bda.controller.IControllerService; + +/** + * Temporary hack for crash in MOGA library on Lollipop. This hack can be removed once MOGA fixes + * their library. The actual issue is caused by the use of implicit service intents, which are + * illegal in Lollipop, as seen in the logcat message below. + * + *
+ * {@code Service Intent must be explicit: Intent { act=com.bda.controller.IControllerService } }
+ * 
+ * + * @see MOGA developer site + * @see + * Discussion on explicit intents + */ +public class MogaHack +{ + public static void init(Controller controller, Context context ) + { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) + { + boolean mIsBound = false; + java.lang.reflect.Field fIsBound = null; + android.content.ServiceConnection mServiceConnection = null; + java.lang.reflect.Field fServiceConnection = null; + try + { + Class cMogaController = controller.getClass(); + fIsBound = cMogaController.getDeclaredField( "mIsBound" ); + fIsBound.setAccessible( true ); + mIsBound = fIsBound.getBoolean( controller ); + fServiceConnection = cMogaController.getDeclaredField( "mServiceConnection" ); + fServiceConnection.setAccessible( true ); + mServiceConnection = ( android.content.ServiceConnection ) fServiceConnection.get( controller ); + } + catch( NoSuchFieldException e ) + { + Log.e( "MogaHack", "MOGA Lollipop Hack NoSuchFieldException (get)", e ); + } + catch( IllegalAccessException e ) + { + Log.e( "MogaHack", "MOGA Lollipop Hack IllegalAccessException (get)", e ); + } + catch( IllegalArgumentException e ) + { + Log.e( "MogaHack", "MOGA Lollipop Hack IllegalArgumentException (get)", e ); + } + if( ( !mIsBound ) && ( mServiceConnection != null ) ) + { + // Convert implicit intent to explicit intent, see http://stackoverflow.com/a/26318757 + Intent intent = new Intent( IControllerService.class.getName() ); + List resolveInfos = context.getPackageManager().queryIntentServices( intent, 0 ); + if( resolveInfos == null || resolveInfos.size() != 1 ) + { + Log.e( "MogaHack", "Somebody is trying to intercept our intent. Disabling MOGA controller for security." ); + } + ServiceInfo serviceInfo = resolveInfos.get( 0 ).serviceInfo; + String packageName = serviceInfo.packageName; + String className = serviceInfo.name; + intent.setComponent( new ComponentName( packageName, className ) ); + + // Start the service explicitly + context.startService( intent ); + context.bindService( intent, mServiceConnection, 1 ); + try + { + fIsBound.setBoolean( controller, true ); + } + catch( IllegalAccessException e ) + { + Log.e( "MogaHack", "MOGA Lollipop Hack IllegalAccessException (set)", e ); + } + catch( IllegalArgumentException e ) + { + Log.e( "MogaHack", "MOGA Lollipop Hack IllegalArgumentException (set)", e ); + } + } + } + else + { + controller.init(); + } + } +} diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 2451c87b45..65046d08ee 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -55,14 +55,11 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener, mController = Controller.getInstance(activity); try { - if (mController.init()) { - Log.i(TAG, "MOGA initialized"); - mController.setListener(this, new Handler()); - } else { - Log.i(TAG, "MOGA failed to initialize. No moga detected?"); - } - } catch (java.lang.RuntimeException e) { - Log.i(TAG, "MOGA failed to initialize due to the bug."); + MogaHack.init(mController, activity); + Log.i(TAG, "MOGA initialized"); + mController.setListener(this, new Handler()); + } catch (Exception e) { + Log.i(TAG, "Moga failed to initialize"); } } From d91ab195c4c9489fb9579ac1ae375cef1c97f374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 4 Apr 2015 11:27:22 +0200 Subject: [PATCH 1375/1445] Don't use CLOCK_MONOTONIC_RAW on android, it is super choppy on Nexus 9. --- base/timeutil.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/base/timeutil.cpp b/base/timeutil.cpp index d66f24134d..a79dfce891 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -60,6 +60,8 @@ double real_time_now() { return (double)diff / (double)_frequency; } +#if 0 + // This clock is really "choppy" on Nexus 9! struct timespec time; clock_gettime(CLOCK_MONOTONIC_RAW, &time); return time.tv_sec + time.tv_nsec / 1.0e9; @@ -73,6 +75,17 @@ double real_time_now() { tv.tv_sec -= start; return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; #endif + +#else + static time_t start; + struct timeval tv; + gettimeofday(&tv, NULL); + if (start == 0) { + start = tv.tv_sec; + } + tv.tv_sec -= start; + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; +#endif } #endif From b9dfb4dbe2bd748f75749d9ba7773c0a410e0970 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 8 Apr 2015 12:03:54 -0700 Subject: [PATCH 1376/1445] Validate read size in ReadLocalFile(). --- file/zip_read.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 228cfa79f2..8209a006e7 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -41,16 +41,26 @@ uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { uint8_t *ReadLocalFile(const char *filename, size_t *size) { FILE *file = fopen(filename, "rb"); if (!file) { - return 0; + *size = 0; + return nullptr; } fseek(file, 0, SEEK_END); size_t f_size = ftell(file); + if ((long)f_size < 0) { + *size = 0; + return nullptr; + } fseek(file, 0, SEEK_SET); uint8_t *contents = new uint8_t[f_size+1]; - fread(contents, 1, f_size, file); + if (fread(contents, 1, f_size, file) != f_size) { + delete [] contents; + contents = nullptr; + *size = 0; + } else { + contents[f_size] = 0; + *size = f_size; + } fclose(file); - contents[f_size] = 0; - *size = f_size; return contents; } From acc1ae6f2e9544af76e016399eb8c0770f8481e3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 8 Apr 2015 16:57:17 -0700 Subject: [PATCH 1377/1445] Blacklist NV_shader_framebuffer_fetch on Tegra 3. Reported to cause rendering problems: http://forums.ppsspp.org/showthread.php?tid=4481&pid=105487#pid105487 --- gfx_es2/gl_state.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 9379aa9b6c..6157d49b4f 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -270,6 +270,12 @@ void CheckGLExtensions() { gl_extensions.ANY_shader_framebuffer_fetch = gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.NV_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; + // Framebuffer fetch appears to be buggy at least on Tegra 3 devices. So we blacklist it. + // Tales of Destiny 2 has been reported to display green. + if (gl_extensions.ANY_shader_framebuffer_fetch && strstr(renderer, "NVIDIA Tegra 3") != 0) { + gl_extensions.ANY_shader_framebuffer_fetch = false; + } + #if defined(ANDROID) || defined(BLACKBERRY) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. // https://twitter.com/ID_AA_Carmack/status/387383037794603008 From 6c0bc5502b19944b825478a04bfd0a7ab07dc635 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 10 Apr 2015 11:47:59 -0700 Subject: [PATCH 1378/1445] Oops, fix another leak. --- file/zip_read.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 8209a006e7..76966127ad 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -48,6 +48,7 @@ uint8_t *ReadLocalFile(const char *filename, size_t *size) { size_t f_size = ftell(file); if ((long)f_size < 0) { *size = 0; + fclose(file); return nullptr; } fseek(file, 0, SEEK_SET); From bd6d9a97a5cb0504302458c346238c4a245637ae Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 19 Apr 2015 16:07:00 -0700 Subject: [PATCH 1379/1445] Retain NaN bits in fp16/fp32 conversions. This matches PSP behavior better. --- math/math_util.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/math/math_util.h b/math/math_util.h index c0ddd86088..d4a299b0bd 100644 --- a/math/math_util.h +++ b/math/math_util.h @@ -151,8 +151,8 @@ inline FP32 half_to_float_fast5(FP16 h) FP32 o; o.u = (h.u & 0x7fff) << 13; // exponent/mantissa bits o.f *= magic.f; // exponent adjust - if (o.f >= was_infnan.f) // make sure Inf/NaN survive - o.u |= 255 << 23; + if (o.f >= was_infnan.f) // make sure Inf/NaN survive (retain the low bits) + o.u = (255 << 23) | (h.u & 0x03ff); o.u |= (h.u & 0x8000) << 16; // sign bit return o; } @@ -178,7 +178,7 @@ inline FP16 float_to_half_fast3(FP32 f) f.u ^= sign; if (f.u >= f32infty.u) // Inf or NaN (all exponent bits set) - o.u = (f.u > f32infty.u) ? 0x7e00 : 0x7c00; // NaN->qNaN and Inf->Inf + o.u = (f.u > f32infty.u) ? (0x7e00 | (f.u & 0x3ff)) : 0x7c00; // NaN->qNaN and Inf->Inf else // (De)normalized number or zero { f.u &= round_mask; From 7d9ff90bec0435c8268af278e71fa6bff20153a7 Mon Sep 17 00:00:00 2001 From: zhyk Date: Thu, 7 May 2015 10:45:24 +0800 Subject: [PATCH 1380/1445] Add UIContext::DrawTextShadow for drawing text correctly under Qt --- ui/ui_context.cpp | 6 ++++++ ui/ui_context.h | 1 + 2 files changed, 7 insertions(+) diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index bc7d2d6faa..d67ed1e0c0 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -152,6 +152,12 @@ void UIContext::DrawText(const char *str, float x, float y, uint32_t color, int } } +void UIContext::DrawTextShadow(const char *str, float x, float y, uint32_t color, int align) { + uint32_t alpha = (color >> 1) & 0xFF000000; + DrawText(str, x + 2, y + 2, alpha, align); + DrawText(str, x, y, color, align); +} + void UIContext::DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align) { if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) { float sizeFactor = (float)fontStyle_->sizePts / 24.0f; diff --git a/ui/ui_context.h b/ui/ui_context.h index d7960d34b4..628a96cba1 100644 --- a/ui/ui_context.h +++ b/ui/ui_context.h @@ -61,6 +61,7 @@ public: void MeasureTextCount(const UI::FontStyle &style, const char *str, int count, float *x, float *y, int align = 0) const; void MeasureText(const UI::FontStyle &style, const char *str, float *x, float *y, int align = 0) const; void DrawText(const char *str, float x, float y, uint32_t color, int align = 0); + void DrawTextShadow(const char *str, float x, float y, uint32_t color, int align = 0); void DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align = 0); void FillRect(const UI::Drawable &drawable, const Bounds &bounds); From eefcf860271cdcb4658b8db37cb13f6639fa6ba9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 12 May 2015 19:50:56 +0200 Subject: [PATCH 1381/1445] Initial profiler work --- profiler/profiler.cpp | 114 +++++++++++++++++++++--------------------- profiler/profiler.h | 56 ++++++++++++--------- ui/virtual_input.cpp | 2 +- 3 files changed, 91 insertions(+), 81 deletions(-) diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index a8f84befae..9ec8b89149 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -1,4 +1,4 @@ -// UNFINISHED but kinda working +// Ultra-lightweight category profiler with history. #include #include @@ -7,78 +7,78 @@ #include #include "base/logging.h" -#include "gfx_es2/draw_buffer.h" #include "base/timeutil.h" +#include "gfx_es2/draw_buffer.h" +#include "profiler/profiler.h" -using namespace std; +#define MAX_CATEGORIES 16 // Can be any number +#define HISTORY_SIZE 256 // Must be power of 2 +#ifndef _DEBUG +// If the compiler can collapse identical strings, we don't even need the strcmp. +#define UNIFIED_CONST_STR +#endif -struct Section { - const char *name; - int level; - double start; - double end; +struct CategoryFrame { + float time_taken[MAX_CATEGORIES]; }; -static vector
current_frame; -static double frame_start; -#define NUM_LEVELS 16 -static Section cur_section[NUM_LEVELS]; +struct Profiler { + int frameCount; + int historyPos; + double eventStart; + double curFrameStart; +}; -static int level; +static Profiler profiler; +static Category categories[MAX_CATEGORIES]; +static CategoryFrame *history; -void _profiler_init() { - level = 0; +void internal_profiler_init() { + history = new CategoryFrame[HISTORY_SIZE]; + for (int i = 0; i < MAX_CATEGORIES; i++) { + categories[i].color = 0x358236 * i; + } } -void _profiler_enter(const char *section_name) { - cur_section[level].name = section_name; - cur_section[level].start = real_time_now(); - level++; +int internal_profiler_enter(const char *section_name) { + for (int i = 0; i < MAX_CATEGORIES; i++) { + const char *catname = categories[i].name; + if (!catname) + break; +#ifdef UNIFIED_CONST_STR + if (catname == section_name) { +#else + if (!strcmp(catname, section_name)) { +#endif + profiler.eventStart = time_now_d(); + return i; + } + } + return -1; } -void _profiler_leave(const char *section_name) { - --level; - cur_section[level].end = real_time_now(); - if (strcmp(section_name, cur_section[level].name)) { - FLOG("Can't enter %s when %s is active, only one at a time!", - section_name, cur_section[level].name); - } - cur_section[level].level = level; - current_frame.push_back(cur_section[level]); +void internal_profiler_leave(int category) { + if (category < 0) + return; + double diff = time_now_d() - profiler.eventStart; + history[profiler.historyPos].time_taken[category] += (float)diff; } -void _profiler_begin_frame() { - frame_start = real_time_now(); +void internal_profiler_end_frame() { + profiler.curFrameStart = real_time_now(); + profiler.historyPos++; + profiler.historyPos &= ~HISTORY_SIZE; } -void _profiler_end_frame() { - current_frame.clear(); +const char *GetSectionName(int i) { + return i >= 0 ? categories[i].name : "N/A"; } -void _profiler_log() { - const char *spaces = " "; - ILOG("Profiler output ===================="); - for (int i = 0; i < (int)current_frame.size(); i++) { - double start = current_frame[i].start - frame_start; - double elapsed = current_frame[i].end - current_frame[i].start; - double start_ms = (start*1000); - double elapsed_ms = (elapsed*1000); - ILOG("%s%s: %0.3f ms", spaces + 15-current_frame[i].level, current_frame[i].name, elapsed_ms); - } -} - -void _profiler_draw(DrawBuffer *draw2d, int font) { - uint32_t colors[4] = { 0xFFc0a030, 0xFF30a0c0, 0xFF30C050, 0xFFc02080 }; - for (int i = 0; i < (int)current_frame.size(); i++) { - const Section §ion = current_frame[i]; - double start = section.start - frame_start; - double elapsed = section.end - current_frame[i].start; - - uint32_t color = colors[i&3]; - float y1 = i * 32, y2 = (i+1)*32; - float x1 = start / 0.0166666; - float x2 = (start + elapsed) / 0.01666666; - draw2d->Rect(x1, y1, x2, y2, color); - } +int GetNumSections() { + for (int i = 0; i < MAX_CATEGORIES; i++) { + if (!categories[i].name) + return i; + } + return 0; } diff --git a/profiler/profiler.h b/profiler/profiler.h index a1ed0bd2c0..e61ffbe194 100644 --- a/profiler/profiler.h +++ b/profiler/profiler.h @@ -1,38 +1,48 @@ #pragma once -// WIP - very preliminary. -// #define USE_PROFILER +#define USE_PROFILER #ifdef USE_PROFILER class DrawBuffer; -void _profiler_init(); -void _profiler_begin_frame(); -void _profiler_end_frame(); +struct Category { + const char *name; + uint32_t color; +}; -void _profiler_log(); -void _profiler_draw(DrawBuffer *draw2d, int font); +void internal_profiler_init(); +void internal_profiler_end_frame(); -void _profiler_enter(const char *section); -void _profiler_leave(const char *section); +int internal_profiler_enter(const char *section); // Returns the category number. +void internal_profiler_leave(int category); -#define PROFILER_INIT() _profiler_init(); -#define PROFILER_ENTER(section) _profiler_enter(section); -#define PROFILER_LEAVE(section) _profiler_leave(section); -#define PROFILER_LOG() _profiler_log(); -#define PROFILER_DRAW(draw, font) _profiler_draw(draw, font); -#define PROFILER_BEGIN_FRAME() _profiler_begin_frame(); -#define PROFILER_END_FRAME() _profiler_end_frame(); +float internal_profiler_gethistory(const char *section, float *data, int count); +const char *GetSectionName(int i); +int GetNumSections(); + +class ProfileThis { +public: + ProfileThis(const char *category) { + cat_ = internal_profiler_enter(category); + } + ~ProfileThis() { + internal_profiler_leave(cat_); + } +private: + int cat_; +}; + +#define PROFILE_INIT() internal_profiler_init(); +#define PROFILE_THIS_SCOPE(cat) ProfileThis _profile_scoped(cat); +#define PROFILE_END_FRAME() internal_profiler_end_frame(); +#define PROFILE_GET_HISTORY(section, data, count) internal_profiler_gethistory(section, data, count); #else -#define PROFILER_INIT() -#define PROFILER_ENTER(section) -#define PROFILER_LEAVE(section) -#define PROFILER_LOG() -#define PROFILER_DRAW(draw, font) -#define PROFILER_BEGIN_FRAME() -#define PROFILER_END_FRAME() +#define PROFILE_INIT() +#define PROFILE_THIS_SCOPE(cat) ProfileThis _profile_scoped(cat); +#define PROFILE_END_FRAME() +#define PROFILE_GET_HISTORY(section, data, count) internal_profiler_gethistory(section, data, count); #endif diff --git a/ui/virtual_input.cpp b/ui/virtual_input.cpp index f27a81993e..dc12940543 100644 --- a/ui/virtual_input.cpp +++ b/ui/virtual_input.cpp @@ -47,7 +47,7 @@ void TouchButton::draw(DrawBuffer &db, uint32_t color, uint32_t colorOverlay) } TouchCrossPad::TouchCrossPad(const Atlas *atlas, int arrowIndex, int overlayIndex) - : atlas_(atlas), arrowIndex_(arrowIndex), overlayIndex_(overlayIndex) + : atlas_(atlas), arrowIndex_(arrowIndex), overlayIndex_(overlayIndex), down_(0) { } From fa1930773f2178fa6a6f646bae23ba5b4c57d43c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 13 May 2015 22:26:51 +0200 Subject: [PATCH 1382/1445] Rewrite the frame profiler --- profiler/profiler.cpp | 62 ++++++++++++++++++++++++++++++++++++------- profiler/profiler.h | 24 ++++++++--------- 2 files changed, 63 insertions(+), 23 deletions(-) diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index 9ec8b89149..4bb6ab3f8a 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -19,14 +19,22 @@ #define UNIFIED_CONST_STR #endif +struct Category { + const char *name; + uint32_t color; +}; + struct CategoryFrame { + CategoryFrame() { + memset(time_taken, 0, sizeof(time_taken)); + } float time_taken[MAX_CATEGORIES]; }; struct Profiler { int frameCount; int historyPos; - double eventStart; + double eventStart[MAX_CATEGORIES]; double curFrameStart; }; @@ -35,50 +43,84 @@ static Category categories[MAX_CATEGORIES]; static CategoryFrame *history; void internal_profiler_init() { + memset(&profiler, 0, sizeof(profiler)); history = new CategoryFrame[HISTORY_SIZE]; for (int i = 0; i < MAX_CATEGORIES; i++) { - categories[i].color = 0x358236 * i; + categories[i].color = 0xFF000000 | (0x358236 * (i+4)); } } -int internal_profiler_enter(const char *section_name) { - for (int i = 0; i < MAX_CATEGORIES; i++) { +int internal_profiler_enter(const char *category_name) { + int i; + for (i = 0; i < MAX_CATEGORIES; i++) { const char *catname = categories[i].name; if (!catname) break; #ifdef UNIFIED_CONST_STR - if (catname == section_name) { + if (catname == category_name) { #else - if (!strcmp(catname, section_name)) { + if (!strcmp(catname, category_name)) { #endif - profiler.eventStart = time_now_d(); + if (profiler.eventStart[i] == 0.0f) { + profiler.eventStart[i] = real_time_now(); + } return i; } } + + if (i < MAX_CATEGORIES && category_name) { + categories[i].name = category_name; + if (profiler.eventStart[i] == 0.0f) { + profiler.eventStart[i] = real_time_now(); + } + return i; + } + return -1; } void internal_profiler_leave(int category) { if (category < 0) return; - double diff = time_now_d() - profiler.eventStart; + double diff = real_time_now() - profiler.eventStart[category]; history[profiler.historyPos].time_taken[category] += (float)diff; + profiler.eventStart[category] = 0.0; } void internal_profiler_end_frame() { profiler.curFrameStart = real_time_now(); profiler.historyPos++; profiler.historyPos &= ~HISTORY_SIZE; + memset(&history[profiler.historyPos], 0, sizeof(history[profiler.historyPos])); } -const char *GetSectionName(int i) { +const char *Profiler_GetCategoryName(int i) { return i >= 0 ? categories[i].name : "N/A"; } -int GetNumSections() { +uint32_t Profiler_GetCategoryColor(int i) { + return i >= 0 ? categories[i].color : 0xFFFF00FF; +} + +int Profiler_GetHistoryLength() { + return HISTORY_SIZE; +} + +int Profiler_GetNumCategories() { for (int i = 0; i < MAX_CATEGORIES; i++) { if (!categories[i].name) return i; } return 0; } + +void Profiler_GetHistory(int category, float *data, int count) { + for (int i = 0; i < HISTORY_SIZE; i++) { + int x = i - count + profiler.historyPos; + if (x < 0) + x += HISTORY_SIZE; + if (x >= HISTORY_SIZE) + x -= HISTORY_SIZE; + data[i] = history[x].time_taken[category]; + } +} diff --git a/profiler/profiler.h b/profiler/profiler.h index e61ffbe194..86baf7956e 100644 --- a/profiler/profiler.h +++ b/profiler/profiler.h @@ -1,25 +1,25 @@ #pragma once -#define USE_PROFILER +#include + +// #define USE_PROFILER #ifdef USE_PROFILER class DrawBuffer; -struct Category { - const char *name; - uint32_t color; -}; - void internal_profiler_init(); void internal_profiler_end_frame(); -int internal_profiler_enter(const char *section); // Returns the category number. +int internal_profiler_enter(const char *category_name); // Returns the category number. void internal_profiler_leave(int category); -float internal_profiler_gethistory(const char *section, float *data, int count); -const char *GetSectionName(int i); -int GetNumSections(); + +const char *Profiler_GetCategoryName(int i); +uint32_t Profiler_GetCategoryColor(int i); +int Profiler_GetNumCategories(); +int Profiler_GetHistoryLength(); +void Profiler_GetHistory(int i, float *data, int count); class ProfileThis { public: @@ -36,13 +36,11 @@ private: #define PROFILE_INIT() internal_profiler_init(); #define PROFILE_THIS_SCOPE(cat) ProfileThis _profile_scoped(cat); #define PROFILE_END_FRAME() internal_profiler_end_frame(); -#define PROFILE_GET_HISTORY(section, data, count) internal_profiler_gethistory(section, data, count); #else #define PROFILE_INIT() -#define PROFILE_THIS_SCOPE(cat) ProfileThis _profile_scoped(cat); +#define PROFILE_THIS_SCOPE(cat) #define PROFILE_END_FRAME() -#define PROFILE_GET_HISTORY(section, data, count) internal_profiler_gethistory(section, data, count); #endif From b9089e505117e52ec93708235c8f9db2e47e9bb2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 13 May 2015 23:34:41 +0200 Subject: [PATCH 1383/1445] Colors don't belong here, let the visualization handle that --- profiler/profiler.cpp | 8 -------- profiler/profiler.h | 3 +-- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index 4bb6ab3f8a..671a0fa48f 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -21,7 +21,6 @@ struct Category { const char *name; - uint32_t color; }; struct CategoryFrame { @@ -45,9 +44,6 @@ static CategoryFrame *history; void internal_profiler_init() { memset(&profiler, 0, sizeof(profiler)); history = new CategoryFrame[HISTORY_SIZE]; - for (int i = 0; i < MAX_CATEGORIES; i++) { - categories[i].color = 0xFF000000 | (0x358236 * (i+4)); - } } int internal_profiler_enter(const char *category_name) { @@ -98,10 +94,6 @@ const char *Profiler_GetCategoryName(int i) { return i >= 0 ? categories[i].name : "N/A"; } -uint32_t Profiler_GetCategoryColor(int i) { - return i >= 0 ? categories[i].color : 0xFFFF00FF; -} - int Profiler_GetHistoryLength() { return HISTORY_SIZE; } diff --git a/profiler/profiler.h b/profiler/profiler.h index 86baf7956e..9275cb697d 100644 --- a/profiler/profiler.h +++ b/profiler/profiler.h @@ -2,7 +2,7 @@ #include -// #define USE_PROFILER +#define USE_PROFILER #ifdef USE_PROFILER @@ -16,7 +16,6 @@ void internal_profiler_leave(int category); const char *Profiler_GetCategoryName(int i); -uint32_t Profiler_GetCategoryColor(int i); int Profiler_GetNumCategories(); int Profiler_GetHistoryLength(); void Profiler_GetHistory(int i, float *data, int count); From 05d48b053e638109adaa6892c24373f21e6bf6a0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 15 May 2015 18:14:28 +0200 Subject: [PATCH 1384/1445] Profiler fix for Android, count events --- android/app-android.cpp | 2 ++ profiler/profiler.cpp | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index d27f90d2ea..204167c254 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -20,6 +20,7 @@ #include "base/timeutil.h" #include "file/zip_read.h" #include "input/input_state.h" +#include "profiler/profiler.h" #include "audio/mixer.h" #include "math/math_util.h" #include "net/resolve.h" @@ -193,6 +194,7 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init jniEnvUI = env; ILOG("NativeApp.init() -- begin"); + PROFILE_INIT(); memset(&input_state, 0, sizeof(input_state)); renderer_inited = false; diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index 671a0fa48f..37b0a38318 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -28,6 +28,7 @@ struct CategoryFrame { memset(time_taken, 0, sizeof(time_taken)); } float time_taken[MAX_CATEGORIES]; + int count[MAX_CATEGORIES]; }; struct Profiler { @@ -76,10 +77,15 @@ int internal_profiler_enter(const char *category_name) { } void internal_profiler_leave(int category) { - if (category < 0) + if (category == -1 || !history) { return; + } + if (category < 0 || category >= MAX_CATEGORIES) { + ELOG("Bad category index %d", category); + } double diff = real_time_now() - profiler.eventStart[category]; history[profiler.historyPos].time_taken[category] += (float)diff; + history[profiler.historyPos].count[category]++; profiler.eventStart[category] = 0.0; } @@ -108,7 +114,7 @@ int Profiler_GetNumCategories() { void Profiler_GetHistory(int category, float *data, int count) { for (int i = 0; i < HISTORY_SIZE; i++) { - int x = i - count + profiler.historyPos; + int x = i - count + profiler.historyPos + 1; if (x < 0) x += HISTORY_SIZE; if (x >= HISTORY_SIZE) From 157b4e2ac90ab7cdcf8f03d18b466b23e14e11bd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 16 May 2015 01:14:29 +0200 Subject: [PATCH 1385/1445] Didn't mean to leave this on --- profiler/profiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profiler/profiler.h b/profiler/profiler.h index 9275cb697d..9ed1a81e9f 100644 --- a/profiler/profiler.h +++ b/profiler/profiler.h @@ -2,7 +2,7 @@ #include -#define USE_PROFILER +// #define USE_PROFILER #ifdef USE_PROFILER From 6ae73b8919acf504aa61c9100d28b650ce53742d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 21 May 2015 10:45:49 +0200 Subject: [PATCH 1386/1445] Add a new touch input flag for handling loss of window focus where events get lost --- input/input_state.h | 1 + 1 file changed, 1 insertion(+) diff --git a/input/input_state.h b/input/input_state.h index 9a4df96248..5f948c7427 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -132,6 +132,7 @@ enum { TOUCH_CANCEL = 1 << 3, // Sent by scrollviews to their children when they detect a scroll TOUCH_WHEEL = 1 << 4, // Scrollwheel event. Usually only affects Y but can potentially affect X. TOUCH_MOUSE = 1 << 5, // Identifies that this touch event came from a mouse + TOUCH_RELEASE_ALL = 1 << 6, // Useful for app focus switches when events may be lost. // These are the Android getToolType() codes, shifted by 10. TOUCH_TOOL_MASK = 7 << 10, From a24f22d4e77bd2c92fc319e452835531ce76ab2f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 21 May 2015 11:44:35 +0200 Subject: [PATCH 1387/1445] Update Qt to fit new definition of UpdateScreenScale. Does not do the smallwindow check though. --- base/QtMain.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/QtMain.h b/base/QtMain.h index 176ca7fe35..18956d789e 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -80,7 +80,7 @@ signals: protected: void resizeEvent(QResizeEvent * e) { - UpdateScreenScale(e->size().width(), e->size().height()); + UpdateScreenScale(e->size().width(), e->size().height(), false); PSP_CoreParameter().pixelWidth = pixel_xres; PSP_CoreParameter().pixelHeight = pixel_yres; } From 22ab3a4bde42ac34929134a3af641931e97b96fa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 24 May 2015 14:34:52 -0700 Subject: [PATCH 1388/1445] Track frame events with sub-events carved out. Simply by using a fixed-size stack. --- profiler/profiler.cpp | 53 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index 37b0a38318..fcf9342618 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -12,6 +12,7 @@ #include "profiler/profiler.h" #define MAX_CATEGORIES 16 // Can be any number +#define MAX_DEPTH 16 // Can be any number #define HISTORY_SIZE 256 // Must be power of 2 #ifndef _DEBUG @@ -34,6 +35,8 @@ struct CategoryFrame { struct Profiler { int frameCount; int historyPos; + int depth; + int parentCategory[MAX_DEPTH]; double eventStart[MAX_CATEGORIES]; double curFrameStart; }; @@ -47,7 +50,7 @@ void internal_profiler_init() { history = new CategoryFrame[HISTORY_SIZE]; } -int internal_profiler_enter(const char *category_name) { +int internal_profiler_find_cat(const char *category_name) { int i; for (i = 0; i < MAX_CATEGORIES; i++) { const char *catname = categories[i].name; @@ -58,24 +61,49 @@ int internal_profiler_enter(const char *category_name) { #else if (!strcmp(catname, category_name)) { #endif - if (profiler.eventStart[i] == 0.0f) { - profiler.eventStart[i] = real_time_now(); - } return i; } } if (i < MAX_CATEGORIES && category_name) { categories[i].name = category_name; - if (profiler.eventStart[i] == 0.0f) { - profiler.eventStart[i] = real_time_now(); - } return i; } return -1; } +// Suspend, also used to prepare for leaving. +static void internal_profiler_suspend(int category) { + double diff = real_time_now() - profiler.eventStart[category]; + history[profiler.historyPos].time_taken[category] += (float)diff; + profiler.eventStart[category] = 0.0; +} + +// Resume, also used as part of entering. +static void internal_profiler_resume(int category) { + profiler.eventStart[category] = real_time_now(); +} + +int internal_profiler_enter(const char *category_name) { + int category = internal_profiler_find_cat(category_name); + if (category != -1) { + if (profiler.eventStart[category] == 0.0f) { + int parent = profiler.parentCategory[profiler.depth]; + // Temporarily suspend the parent on entering a child. + if (parent != 0) { + internal_profiler_suspend(parent); + } + internal_profiler_resume(category); + + profiler.depth++; + profiler.parentCategory[profiler.depth] = category; + } + } + + return category; +} + void internal_profiler_leave(int category) { if (category == -1 || !history) { return; @@ -83,10 +111,15 @@ void internal_profiler_leave(int category) { if (category < 0 || category >= MAX_CATEGORIES) { ELOG("Bad category index %d", category); } - double diff = real_time_now() - profiler.eventStart[category]; - history[profiler.historyPos].time_taken[category] += (float)diff; + internal_profiler_suspend(category); history[profiler.historyPos].count[category]++; - profiler.eventStart[category] = 0.0; + + profiler.depth--; + int parent = profiler.parentCategory[profiler.depth]; + if (parent != 0) { + // Resume tracking the parent. + internal_profiler_resume(parent); + } } void internal_profiler_end_frame() { From bad9806687a2c132a1225c8ed47e4096e699279f Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 25 May 2015 13:55:29 +0000 Subject: [PATCH 1389/1445] file: extend #ifdef for any recent Unix with large file support by default At least other BSDs still fail with file/file_util.cpp: In function 'bool exists(const string&)': file/file_util.cpp:172:16: error: aggregate 'exists(const string&)::stat64 file_info' has incomplete type and cannot be defined struct stat64 file_info; ^ file/file_util.cpp:177:46: error: invalid use of incomplete type 'struct exists(const string&)::stat64' int result = stat64(copy.c_str(), &file_info); ^ file/file_util.cpp:172:9: note: forward declaration of 'struct exists(const string&)::stat64' struct stat64 file_info; ^ file/file_util.cpp: In function 'bool getFileInfo(const char*, FileInfo*)': file/file_util.cpp:207:16: error: aggregate 'getFileInfo(const char*, FileInfo*)::stat64 file_info' has incomplete type and cannot be defined struct stat64 file_info; ^ file/file_util.cpp:212:46: error: invalid use of incomplete type 'struct getFileInfo(const char*, FileInfo*)::stat64' int result = stat64(copy.c_str(), &file_info); ^ file/file_util.cpp:207:9: note: forward declaration of 'struct getFileInfo(const char*, FileInfo*)::stat64' struct stat64 file_info; ^ --- file/file_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index b58ced1150..ec1216858e 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -25,7 +25,7 @@ #include "file/file_util.h" #include "util/text/utf8.h" -#if defined(__FreeBSD__) || defined(__APPLE__) +#if !defined(__linux__) && !defined(__SYMBIAN32__) #define stat64 stat #endif From 4593b22bbe66f799e31f266166e123eda1abd84e Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 25 May 2015 14:07:35 +0000 Subject: [PATCH 1390/1445] net: remove dead (pre WaitUntilReady?) code accidentally found via native/net/http_headers.cpp: In member function 'void http::RequestHeader::ParseHeaders(int)': native/net/http_headers.cpp:136:12: error: 'timeval' in namespace '::' does not name a type struct ::timeval tv; ^ native/net/http_headers.cpp:137:6: error: request for member 'tv_sec' in 'tv', which is of non-class type 'int' tv.tv_sec = 5; ^ native/net/http_headers.cpp:138:6: error: request for member 'tv_usec' in 'tv', which is of non-class type 'int' tv.tv_usec = 0; ^ --- net/http_headers.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/net/http_headers.cpp b/net/http_headers.cpp index a5f544c05d..0fdf628d3f 100644 --- a/net/http_headers.cpp +++ b/net/http_headers.cpp @@ -1,11 +1,5 @@ #include "net/http_headers.h" -#ifdef _WIN32 - -#include // for timeval - -#endif - #include #include @@ -132,11 +126,6 @@ int RequestHeader::ParseHttpHeader(const char *buffer) { } void RequestHeader::ParseHeaders(int fd) { - // Get the request, with a timeout. - struct ::timeval tv; - tv.tv_sec = 5; - tv.tv_usec = 0; - int line_count = 0; // Loop through request headers. while (true) { From babb5036e62e85e65f4ce15344363429c9e6d932 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 25 May 2015 13:40:26 +0000 Subject: [PATCH 1391/1445] net: don't add #ifdefs for POSIX headers http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/arpa_inet.h.html --- net/http_client.h | 3 --- net/http_server.cpp | 1 + net/resolve.cpp | 3 --- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/net/http_client.h b/net/http_client.h index ece8add041..34c03c2ffa 100644 --- a/net/http_client.h +++ b/net/http_client.h @@ -11,11 +11,8 @@ #define NOMINMAX #include #else -#if defined(__FreeBSD__) || defined(__SYMBIAN32__) #include -#else #include -#endif #include #include #endif diff --git a/net/http_server.cpp b/net/http_server.cpp index ae95ca7aca..a61c625aca 100644 --- a/net/http_server.cpp +++ b/net/http_server.cpp @@ -11,6 +11,7 @@ #include /* socket definitions */ #include /* socket types */ #include /* for waitpid() */ +#include /* struct sockaddr_in */ #include /* inet (3) funtions */ #include /* misc. UNIX functions */ diff --git a/net/resolve.cpp b/net/resolve.cpp index 329c3d8c2f..fd6a774c8c 100644 --- a/net/resolve.cpp +++ b/net/resolve.cpp @@ -14,11 +14,8 @@ #undef min #undef max #else -#if defined(__FreeBSD__) #include -#else #include -#endif #include #include #include From 7af88bf50eb3e5aa3db084b57d3373d31d0bb382 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 25 May 2015 14:05:11 +0000 Subject: [PATCH 1392/1445] ext/stb_vorbis: alloca() is in stdlib.h on BSDs as well ext/stb_vorbis/stb_vorbis.c:19:10: fatal error: 'alloca.h' file not found --- ext/stb_vorbis/stb_vorbis.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/stb_vorbis/stb_vorbis.c b/ext/stb_vorbis/stb_vorbis.c index e508af2775..44c64fde8a 100644 --- a/ext/stb_vorbis/stb_vorbis.c +++ b/ext/stb_vorbis/stb_vorbis.c @@ -15,7 +15,8 @@ #pragma warning (disable:4996) #pragma warning (disable:4244) #include -#elif !defined(__SYMBIAN32__) +#elif !defined(__SYMBIAN32__) && !defined(__Bitrig__) && !defined(__DragonFly__) && \ + !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) #include #endif From b9b02eb4038600cd6b7e619f8654323b8ba22680 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 25 May 2015 13:52:48 +0000 Subject: [PATCH 1393/1445] DragonFly has bswap* like FreeBSD, Bitrig - like OpenBSD --- base/basictypes.h | 2 +- ext/cityhash/city.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/basictypes.h b/base/basictypes.h index 479b6510f2..7f3dfea731 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -87,7 +87,7 @@ inline uint64 swap64(uint64 _data) {return ((uint64)swap32(_data) << 32) | swap3 inline uint16 swap16(uint16 _data) {return bswap_16(_data);} inline uint32 swap32(uint32 _data) {return bswap_32(_data);} inline uint64 swap64(uint64 _data) {return bswap_64(_data);} -#elif defined(__FreeBSD__) +#elif defined(__DragonFly__) || defined(__FreeBSD__) #include inline uint16 swap16(uint16 _data) {return bswap16(_data);} inline uint32 swap32(uint32 _data) {return bswap32(_data);} diff --git a/ext/cityhash/city.cpp b/ext/cityhash/city.cpp index 329111c9a8..06190d529f 100644 --- a/ext/cityhash/city.cpp +++ b/ext/cityhash/city.cpp @@ -68,12 +68,12 @@ static uint32 UNALIGNED_LOAD32(const char *p) { #define bswap_32(x) BSWAP_32(x) #define bswap_64(x) BSWAP_64(x) -#elif defined(__FreeBSD__) +#elif defined(__DragonFly__) || defined(__FreeBSD__) #include #define bswap_32(x) bswap32(x) #define bswap_64(x) bswap64(x) -#elif defined(__OpenBSD__) +#elif defined(__Bitrig__) || defined(__OpenBSD__) #include #define bswap_32(x) swap32(x) #define bswap_64(x) swap64(x) From 5984a4aa1cee5f66370902296346be5c91d3a628 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 25 May 2015 17:11:33 +0000 Subject: [PATCH 1394/1445] file: sync stat64 #ifdef with ppsspp --- file/file_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file/file_util.cpp b/file/file_util.cpp index ec1216858e..a173933eda 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -25,7 +25,7 @@ #include "file/file_util.h" #include "util/text/utf8.h" -#if !defined(__linux__) && !defined(__SYMBIAN32__) +#if !defined(__linux__) && !defined(_WIN32) && !defined(__QNX__) #define stat64 stat #endif From de60aad2abfd9aa3431c9ba557a0042a42bbfb8c Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Tue, 26 May 2015 14:51:53 +0000 Subject: [PATCH 1395/1445] base: fallback to Unix desktop, not mobile --- base/PCMain.cpp | 52 ++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 51228d4f89..1a6a194a1f 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -243,53 +243,53 @@ void System_SendMessage(const char *command, const char *parameter) { } void LaunchBrowser(const char *url) { -#ifdef _WIN32 +#if defined(MOBILE_DEVICE) + ILOG("Would have gone to %s but LaunchBrowser is not implemented on this platform", url); +#elif defined(_WIN32) ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); -#elif __linux__ +#elif defined(__APPLE__) + std::string command = std::string("open ") + url; + system(command.c_str()); +#else std::string command = std::string("xdg-open ") + url; int err = system(command.c_str()); if (err) { ILOG("Would have gone to %s but xdg-utils seems not to be installed", url) } -#elif __APPLE__ - std::string command = std::string("open ") + url; - system(command.c_str()); -#else - ILOG("Would have gone to %s but LaunchBrowser is not implemented on this platform", url); #endif } void LaunchMarket(const char *url) { -#ifdef _WIN32 +#if defined(MOBILE_DEVICE) + ILOG("Would have gone to %s but LaunchMarket is not implemented on this platform", url); +#elif defined(_WIN32) ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); -#elif __linux__ +#elif defined(__APPLE__) + std::string command = std::string("open ") + url; + system(command.c_str()); +#else std::string command = std::string("xdg-open ") + url; int err = system(command.c_str()); if (err) { ILOG("Would have gone to %s but xdg-utils seems not to be installed", url) } -#elif __APPLE__ - std::string command = std::string("open ") + url; - system(command.c_str()); -#else - ILOG("Would have gone to %s but LaunchMarket is not implemented on this platform", url); #endif } void LaunchEmail(const char *email_address) { -#ifdef _WIN32 +#if defined(MOBILE_DEVICE) + ILOG("Would have opened your email client for %s but LaunchEmail is not implemented on this platform", email_address); +#elif defined(_WIN32) ShellExecute(NULL, "open", (std::string("mailto:") + email_address).c_str(), NULL, NULL, SW_SHOWNORMAL); -#elif __linux__ +#elif defined(__APPLE__) + std::string command = std::string("open mailto:") + email_address; + system(command.c_str()); +#else std::string command = std::string("xdg-email ") + email_address; int err = system(command.c_str()); if (err) { ILOG("Would have gone to %s but xdg-utils seems not to be installed", email_address) } -#elif __APPLE__ - std::string command = std::string("open mailto:") + email_address; - system(command.c_str()); -#else - ILOG("Would have opened your email client for %s but LaunchEmail is not implemented on this platform", email_address); #endif } @@ -319,16 +319,10 @@ int System_GetPropertyInt(SystemProperty prop) { case SYSPROP_DISPLAY_REFRESH_RATE: return 60000; case SYSPROP_DEVICE_TYPE: -#ifdef _WIN32 - return DEVICE_TYPE_DESKTOP; -#elif defined(MAEMO) +#if defined(MOBILE_DEVICE) return DEVICE_TYPE_MOBILE; -#elif __linux__ - return DEVICE_TYPE_DESKTOP; -#elif __APPLE__ - return DEVICE_TYPE_DESKTOP; #else - return DEVICE_TYPE_MOBILE; + return DEVICE_TYPE_DESKTOP; #endif default: return -1; From 90c2ef38bd071a832d0057d5025c995489b0bf41 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 May 2015 21:21:30 +0200 Subject: [PATCH 1396/1445] Make Native also target android-22 (oversight) --- android/project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/project.properties b/android/project.properties index f06f217ce4..9f2199fbd5 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt # Project target. -target=android-19 +target=android-22 android.library=true From 93a7d0c67e239c816c408c1d8631727f2790eb4c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 11 Jun 2015 12:15:38 +0200 Subject: [PATCH 1397/1445] Profiler: Handle category 0 correctly when suspending parent categories. Small optimization + sanity checks. --- profiler/profiler.cpp | 47 +++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index fcf9342618..84b1d80de1 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -47,6 +47,9 @@ static CategoryFrame *history; void internal_profiler_init() { memset(&profiler, 0, sizeof(profiler)); + for (int i = 0; i < MAX_DEPTH; i++) { + profiler.parentCategory[i] = -1; + } history = new CategoryFrame[HISTORY_SIZE]; } @@ -74,31 +77,36 @@ int internal_profiler_find_cat(const char *category_name) { } // Suspend, also used to prepare for leaving. -static void internal_profiler_suspend(int category) { - double diff = real_time_now() - profiler.eventStart[category]; +static void internal_profiler_suspend(int category, double now) { + double diff = now - profiler.eventStart[category]; history[profiler.historyPos].time_taken[category] += (float)diff; profiler.eventStart[category] = 0.0; } // Resume, also used as part of entering. -static void internal_profiler_resume(int category) { - profiler.eventStart[category] = real_time_now(); +static void internal_profiler_resume(int category, double now) { + profiler.eventStart[category] = now; } int internal_profiler_enter(const char *category_name) { int category = internal_profiler_find_cat(category_name); - if (category != -1) { - if (profiler.eventStart[category] == 0.0f) { - int parent = profiler.parentCategory[profiler.depth]; - // Temporarily suspend the parent on entering a child. - if (parent != 0) { - internal_profiler_suspend(parent); - } - internal_profiler_resume(category); + if (category == -1 || !history) { + return category; + } - profiler.depth++; - profiler.parentCategory[profiler.depth] = category; + if (profiler.eventStart[category] == 0.0f) { + double now = real_time_now(); + int parent = profiler.parentCategory[profiler.depth]; + // Temporarily suspend the parent on entering a child. + if (parent != -1) { + internal_profiler_suspend(parent, now); } + internal_profiler_resume(category, now); + + profiler.depth++; + profiler.parentCategory[profiler.depth] = category; + } else { + FLOG("profiler: recursive enter"); } return category; @@ -111,18 +119,23 @@ void internal_profiler_leave(int category) { if (category < 0 || category >= MAX_CATEGORIES) { ELOG("Bad category index %d", category); } - internal_profiler_suspend(category); + + double now = real_time_now(); + internal_profiler_suspend(category, now); history[profiler.historyPos].count[category]++; profiler.depth--; int parent = profiler.parentCategory[profiler.depth]; - if (parent != 0) { + if (parent != -1) { // Resume tracking the parent. - internal_profiler_resume(parent); + internal_profiler_resume(parent, now); } } void internal_profiler_end_frame() { + if (profiler.depth != 0) { + FLOG("Can't be inside a profiler scope at end of frame!"); + } profiler.curFrameStart = real_time_now(); profiler.historyPos++; profiler.historyPos &= ~HISTORY_SIZE; From 316d6ab84def4666fe13ff0c14c9bcb1659ab5c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 11 Jun 2015 16:00:12 +0200 Subject: [PATCH 1398/1445] Fix another bug in the profiler, that would happily overwrite memory. --- profiler/profiler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index 84b1d80de1..259a4805e5 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -138,7 +138,7 @@ void internal_profiler_end_frame() { } profiler.curFrameStart = real_time_now(); profiler.historyPos++; - profiler.historyPos &= ~HISTORY_SIZE; + profiler.historyPos &= (HISTORY_SIZE - 1); memset(&history[profiler.historyPos], 0, sizeof(history[profiler.historyPos])); } @@ -161,9 +161,9 @@ int Profiler_GetNumCategories() { void Profiler_GetHistory(int category, float *data, int count) { for (int i = 0; i < HISTORY_SIZE; i++) { int x = i - count + profiler.historyPos + 1; - if (x < 0) + while (x < 0) x += HISTORY_SIZE; - if (x >= HISTORY_SIZE) + while (x >= HISTORY_SIZE) x -= HISTORY_SIZE; data[i] = history[x].time_taken[category]; } From 32a75bea4639bd361ebf1bd532f6969547d6e3ba Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 11 Jun 2015 18:43:59 +0200 Subject: [PATCH 1399/1445] Add an FLOG if profiler depth goes negative. Make Crash()/FLOG actually crash on win64. --- base/logging.h | 2 +- profiler/profiler.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/base/logging.h b/base/logging.h index 0c96a12d05..72837a4c6f 100644 --- a/base/logging.h +++ b/base/logging.h @@ -19,7 +19,7 @@ #ifdef _WIN32 #ifdef _M_X64 -inline void Crash() { /*DebugBreak();*/ } +inline void Crash() { int *x = (int *)1337; *x = 1; } #else inline void Crash() { __asm { int 3 }; } #endif diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index 259a4805e5..b3aff97281 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -125,6 +125,9 @@ void internal_profiler_leave(int category) { history[profiler.historyPos].count[category]++; profiler.depth--; + if (profiler.depth < 0) { + FLOG("Profiler enter/leave mismatch!"); + } int parent = profiler.parentCategory[profiler.depth]; if (parent != -1) { // Resume tracking the parent. From ba829ad4aa7a4acbacbaa7f77233e037862443e4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 12 Jun 2015 12:38:48 +0200 Subject: [PATCH 1400/1445] Fix crash bug in DrawText on Windows, clip TextView text if too large --- gfx_es2/draw_text.cpp | 7 ++++++- ui/view.cpp | 31 +++++++++++++++++++++++++++++-- ui/view.h | 2 +- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/gfx_es2/draw_text.cpp b/gfx_es2/draw_text.cpp index f99fc68125..a4ebb22bfe 100644 --- a/gfx_es2/draw_text.cpp +++ b/gfx_es2/draw_text.cpp @@ -19,7 +19,7 @@ enum { MAX_TEXT_WIDTH = 1024, - MAX_TEXT_HEIGHT = 256 + MAX_TEXT_HEIGHT = 512 }; struct TextDrawerFontContext { @@ -168,6 +168,11 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float //ExtTextOut(ctx_->hDC, 0, 0, ETO_OPAQUE | ETO_CLIPPED, NULL, wstr.c_str(), (int)wstr.size(), NULL); DrawTextExW(ctx_->hDC, (LPWSTR)wstr.c_str(), (int)wstr.size(), &rc, DT_HIDEPREFIX|DT_TOP|DT_LEFT, 0); + if (size.cx > MAX_TEXT_WIDTH) + size.cx = MAX_TEXT_WIDTH; + if (size.cy > MAX_TEXT_HEIGHT) + size.cy = MAX_TEXT_HEIGHT; + entry = new TextStringEntry(); entry->width = size.cx; entry->height = size.cy; diff --git a/ui/view.cpp b/ui/view.cpp index e0881ce849..6014a67004 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -2,6 +2,7 @@ #include #include "base/mutex.h" +#include "base/stringutil.h" #include "input/input_state.h" #include "input/keycodes.h" #include "gfx_es2/draw_buffer.h" @@ -571,16 +572,42 @@ void Thin3DTextureView::Draw(UIContext &dc) { } void TextView::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - dc.MeasureText(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont, text_.c_str(), &w, &h); + // MeasureText doesn't seem to work with line breaks, so do something more sophisticated. + std::vector lines; + SplitString(text_, '\n', lines); + float total_w = 0.f; + float total_h = 0.f; + for (size_t i = 0; i < lines.size(); i++) { + float temp_w, temp_h; + dc.MeasureText(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont, lines[i].c_str(), &temp_w, &temp_h); + if (temp_w > total_w) + total_w = temp_w; + total_h += temp_h; + } + w = total_w; + h = total_h; } void TextView::Draw(UIContext &dc) { + float w, h; + GetContentDimensions(dc, w, h); + bool clip = false; + if (w > bounds_.w || h > bounds_.h) + clip = true; + if (clip) { + Bounds clipRect = bounds_.Expand(10); // TODO: Remove this hackery + dc.Flush(); + dc.PushScissor(clipRect); + } dc.SetFontStyle(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont); if (shadow_) { uint32_t shadowColor = 0x80000000; - dc.DrawTextRect(text_.c_str(), bounds_.Offset(1, 1), shadowColor, textAlign_); + dc.DrawTextRect(text_.c_str(), bounds_, shadowColor, textAlign_); } dc.DrawTextRect(text_.c_str(), bounds_, textColor_, textAlign_); + if (clip) { + dc.PopScissor(); + } } TextEdit::TextEdit(const std::string &text, const std::string &placeholderText, LayoutParams *layoutParams) diff --git a/ui/view.h b/ui/view.h index 929c6ba96c..edc1418e74 100644 --- a/ui/view.h +++ b/ui/view.h @@ -753,7 +753,7 @@ private: class Thin3DTextureView : public InertView { public: Thin3DTextureView(Thin3DTexture *texture, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0) - : InertView(layoutParams), texture_(texture), sizeMode_(sizeMode) {} + : InertView(layoutParams), texture_(texture), color_(0xFFFFFFFF), sizeMode_(sizeMode) {} void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; void Draw(UIContext &dc) override; From aa194f1e78045f4f32afd903a2a78d212af45a16 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 14 Jun 2015 13:01:21 +0200 Subject: [PATCH 1401/1445] Improve some logging in profiler --- profiler/profiler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index b3aff97281..37e2ec876e 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -106,7 +106,7 @@ int internal_profiler_enter(const char *category_name) { profiler.depth++; profiler.parentCategory[profiler.depth] = category; } else { - FLOG("profiler: recursive enter"); + FLOG("profiler: recursive enter (%i - %s)", category, category_name); } return category; @@ -118,6 +118,8 @@ void internal_profiler_leave(int category) { } if (category < 0 || category >= MAX_CATEGORIES) { ELOG("Bad category index %d", category); + profiler.depth--; + return; } double now = real_time_now(); From 6eeecbc5af0ca37e42142f794fd11d4d98f21c3c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Jun 2015 12:11:00 -0700 Subject: [PATCH 1402/1445] Avoid pulling in EGL except where needed. Seems to pull in X11, which pulls in a bunch of defines we don't want. This fixes compilation on such systems. --- gfx/gl_common.h | 1 - gfx_es2/gl_state.cpp | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index d716602de3..ca030a6949 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -6,7 +6,6 @@ #elif defined(USING_GLES2) #include #include -#include "EGL/egl.h" // At least Nokia platforms need the three below #include typedef char GLchar; diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 6157d49b4f..200ec4ffdb 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -23,6 +23,9 @@ PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES; PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; #endif +#ifndef IOS +#include "EGL/egl.h" +#endif #endif OpenGLState glstate; From ad73a39e4eaeffa416f185637c569f1736ddb649 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Jun 2015 12:15:28 -0700 Subject: [PATCH 1403/1445] Allow recursion in the frame profiler. --- profiler/profiler.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index 37e2ec876e..2d7b12725d 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -102,13 +102,13 @@ int internal_profiler_enter(const char *category_name) { internal_profiler_suspend(parent, now); } internal_profiler_resume(category, now); - - profiler.depth++; - profiler.parentCategory[profiler.depth] = category; } else { - FLOG("profiler: recursive enter (%i - %s)", category, category_name); + DLOG("profiler: recursive enter (%i - %s)", category, category_name); } + profiler.depth++; + profiler.parentCategory[profiler.depth] = category; + return category; } @@ -123,17 +123,22 @@ void internal_profiler_leave(int category) { } double now = real_time_now(); - internal_profiler_suspend(category, now); - history[profiler.historyPos].count[category]++; profiler.depth--; if (profiler.depth < 0) { FLOG("Profiler enter/leave mismatch!"); } + int parent = profiler.parentCategory[profiler.depth]; - if (parent != -1) { - // Resume tracking the parent. - internal_profiler_resume(parent, now); + // When there's recursion, we don't suspend or resume. + if (parent != category) { + internal_profiler_suspend(category, now); + history[profiler.historyPos].count[category]++; + + if (parent != -1) { + // Resume tracking the parent. + internal_profiler_resume(parent, now); + } } } From 1e3beadb7b164ef8e3718d75abf6e9a5d18dcbb7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 23 Jun 2015 22:42:48 -0700 Subject: [PATCH 1404/1445] Fix insta-crash on AArch64. Oops, missed an eglGetProcAddress(). --- gfx_es2/gl3stub.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gfx_es2/gl3stub.c b/gfx_es2/gl3stub.c index 8637761d07..83117ea231 100644 --- a/gfx_es2/gl3stub.c +++ b/gfx_es2/gl3stub.c @@ -17,6 +17,10 @@ #include "../gfx/gl_common.h" #if defined(USING_GLES2) +#if !defined(IOS) +#include "EGL/egl.h" +#endif + GLboolean gl3stubInit() { #if !defined(IOS) #define FIND_PROC(s) s = (void*)eglGetProcAddress(#s) From 57f44edaeac2c4aa7864042e00c79ebf2bdd19a0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 27 Jun 2015 09:41:53 -0700 Subject: [PATCH 1405/1445] Retain focus after popup choice selection. --- ui/ui_screen.cpp | 6 ++++++ ui/ui_screen.h | 1 + 2 files changed, 7 insertions(+) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 8384afee8a..984fe78665 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -255,6 +255,8 @@ UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) { namespace UI { UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) { + restoreFocus_ = HasFocus(); + std::vector choices; for (int i = 0; i < numChoices_; i++) { choices.push_back(category_ ? category_->T(choices_[i]) : choices_[i]); @@ -288,6 +290,10 @@ void PopupMultiChoice::ChoiceCallback(int num) { e.v = this; e.a = num; OnChoice.Trigger(e); + + if (restoreFocus_) { + SetFocusedView(this); + } } } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index edabf4d262..11d54caca1 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -218,6 +218,7 @@ private: I18NCategory *category_; ScreenManager *screenManager_; std::string valueText_; + bool restoreFocus_; }; From b72060bc062e420b4ce2320a5057b98f6298fc1b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 27 Jun 2015 09:48:24 -0700 Subject: [PATCH 1406/1445] Retain focus with other choice popups. --- ui/ui_screen.cpp | 18 ++++++++++++++++++ ui/ui_screen.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 984fe78665..f2b4e9cc7b 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -329,6 +329,8 @@ PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, flo } EventReturn PopupSliderChoice::HandleClick(EventParams &e) { + restoreFocus_ = HasFocus(); + SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_, step_); popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange); screenManager_->push(popupScreen); @@ -338,6 +340,10 @@ EventReturn PopupSliderChoice::HandleClick(EventParams &e) { EventReturn PopupSliderChoice::HandleChange(EventParams &e) { e.v = this; OnChange.Trigger(e); + + if (restoreFocus_) { + SetFocusedView(this); + } return EVENT_DONE; } @@ -354,6 +360,8 @@ void PopupSliderChoice::Draw(UIContext &dc) { } EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) { + restoreFocus_ = HasFocus(); + SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_, step_); popupScreen->OnChange.Handle(this, &PopupSliderChoiceFloat::HandleChange); screenManager_->push(popupScreen); @@ -363,6 +371,10 @@ EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) { EventReturn PopupSliderChoiceFloat::HandleChange(EventParams &e) { e.v = this; OnChange.Trigger(e); + + if (restoreFocus_) { + SetFocusedView(this); + } return EVENT_DONE; } @@ -453,6 +465,8 @@ PopupTextInputChoice::PopupTextInputChoice(std::string *value, const std::string } EventReturn PopupTextInputChoice::HandleClick(EventParams &e) { + restoreFocus_ = HasFocus(); + TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, text_, maxLen_); popupScreen->OnChange.Handle(this, &PopupTextInputChoice::HandleChange); screenManager_->push(popupScreen); @@ -472,6 +486,10 @@ void PopupTextInputChoice::Draw(UIContext &dc) { EventReturn PopupTextInputChoice::HandleChange(EventParams &e) { e.v = this; OnChange.Trigger(e); + + if (restoreFocus_) { + SetFocusedView(this); + } return EVENT_DONE; } diff --git a/ui/ui_screen.h b/ui/ui_screen.h index 11d54caca1..1ffb28c289 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -240,6 +240,7 @@ private: int maxValue_; int step_; ScreenManager *screenManager_; + bool restoreFocus_; }; class PopupSliderChoiceFloat : public Choice { @@ -259,6 +260,7 @@ private: float maxValue_; float step_; ScreenManager *screenManager_; + bool restoreFocus_; }; class PopupTextInputChoice: public Choice { @@ -277,6 +279,7 @@ private: std::string placeHolder_; std::string defaultText_; int maxLen_; + bool restoreFocus_; }; class ChoiceWithValueDisplay : public UI::Choice { From bc294098179cc30bb8c758aad696c605a1994eab Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 27 Jun 2015 18:27:54 -0700 Subject: [PATCH 1407/1445] Send the cache dir path to the app. --- android/src/com/henrikrydgard/libnative/NativeActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/src/com/henrikrydgard/libnative/NativeActivity.java b/android/src/com/henrikrydgard/libnative/NativeActivity.java index 1ba6a72c4e..9bc0648411 100644 --- a/android/src/com/henrikrydgard/libnative/NativeActivity.java +++ b/android/src/com/henrikrydgard/libnative/NativeActivity.java @@ -218,6 +218,8 @@ public class NativeActivity extends Activity { NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); NativeApp.init(model, deviceType, displaySize.x, displaySize.y, languageRegion, apkFilePath, dataDir, externalStorageDir, libraryDir, shortcutParam, installID, Build.VERSION.SDK_INT); + NativeApp.sendMessage("cacheDir", getCacheDir().getAbsolutePath()); + // OK, config should be initialized, we can query for screen rotation. if (Build.VERSION.SDK_INT >= 9) { updateScreenRotation(); From 3c093ccf73af6d57ec6995cda56323082208515f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 28 Jun 2015 18:47:52 -0700 Subject: [PATCH 1408/1445] Show popup headers as marquees if they are too long. They were just overflowing before. --- ui/view.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/ui/view.cpp b/ui/view.cpp index 6014a67004..5e27c925b5 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -3,6 +3,7 @@ #include "base/mutex.h" #include "base/stringutil.h" +#include "base/timeutil.h" #include "input/input_state.h" #include "input/keycodes.h" #include "gfx_es2/draw_buffer.h" @@ -441,9 +442,31 @@ void ItemHeader::Draw(UIContext &dc) { } void PopupHeader::Draw(UIContext &dc) { + const float paddingHorizontal = 12; + const float availableWidth = bounds_.w - paddingHorizontal * 2; + + float tw, th; dc.SetFontStyle(dc.theme->uiFont); - dc.DrawText(text_.c_str(), bounds_.x + 12, bounds_.centerY(), dc.theme->popupTitle.fgColor, ALIGN_LEFT | ALIGN_VCENTER); + dc.MeasureText(dc.GetFontStyle(), text_.c_str(), &tw, &th, 0); + + float sineWidth = std::max(0.0f, (tw - availableWidth)) / 2.0f; + + float tx = paddingHorizontal; + if (availableWidth < tw) { + float overageRatio = 1.5f * availableWidth * 1.0f / tw; + tx -= (1.0f + sin(time_now_d() * overageRatio)) * sineWidth; + Bounds tb = bounds_; + tb.x = bounds_.x + paddingHorizontal; + tb.w = bounds_.w - paddingHorizontal * 2; + dc.PushScissor(tb); + } + + dc.DrawText(text_.c_str(), bounds_.x + tx, bounds_.centerY(), dc.theme->popupTitle.fgColor, ALIGN_LEFT | ALIGN_VCENTER); dc.Draw()->DrawImageStretch(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->popupTitle.fgColor); + + if (availableWidth < tw) { + dc.PopScissor(); + } } void CheckBox::Toggle(){ From 0f0115da8abbe6479e52c655dd9e8adbcab1c00e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 28 Jun 2015 18:48:22 -0700 Subject: [PATCH 1409/1445] Show a highlight for focusable text views. --- ui/view.cpp | 6 ++++++ ui/view.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ui/view.cpp b/ui/view.cpp index 5e27c925b5..7a38d9acf1 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -622,6 +622,12 @@ void TextView::Draw(UIContext &dc) { dc.Flush(); dc.PushScissor(clipRect); } + // In case it's been made focusable. + if (HasFocus()) { + UI::Style style = dc.theme->itemFocusedStyle; + style.background.color &= 0x7fffffff; + dc.FillRect(style.background, bounds_); + } dc.SetFontStyle(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont); if (shadow_) { uint32_t shadowColor = 0x80000000; diff --git a/ui/view.h b/ui/view.h index edc1418e74..7f82fdb61d 100644 --- a/ui/view.h +++ b/ui/view.h @@ -593,7 +593,7 @@ public: void Draw(UIContext &dc) override; - // These are focusable so that long lists of them can be keybaord scrolled. + // These are focusable so that long lists of them can be keyboard scrolled. bool CanBeFocused() const override { return true; } private: From 63817040856f6b4580d41a0621e9d3ed9838f109 Mon Sep 17 00:00:00 2001 From: vnctdj Date: Thu, 2 Jul 2015 14:20:04 +0200 Subject: [PATCH 1410/1445] Consistently use *di for the Dialog i18n category Same goal as https://github.com/hrydgard/ppsspp/pull/7836. I didn't know native also uses this kind of pointers :) --- ui/ui_screen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index f2b4e9cc7b..3fef16172e 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -130,11 +130,11 @@ UI::EventReturn UIScreen::OnCancel(UI::EventParams &e) { PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2) : box_(0), title_(title), defaultButton_(NULL) { - I18NCategory *d = GetI18NCategory("Dialog"); + I18NCategory *di = GetI18NCategory("Dialog"); if (!button1.empty()) - button1_ = d->T(button1.c_str()); + button1_ = di->T(button1.c_str()); if (!button2.empty()) - button2_ = d->T(button2.c_str()); + button2_ = di->T(button2.c_str()); } bool PopupScreen::touch(const TouchInput &touch) { From ad5301873f7db44eb4b13bc7592ffe511928325a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 3 Jul 2015 12:11:18 -0700 Subject: [PATCH 1411/1445] Increase max profiler cats. We're near this limit and about to pass it in PPSSPP, 32 isn't a ton worse. --- profiler/profiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profiler/profiler.cpp b/profiler/profiler.cpp index 2d7b12725d..f21200a18b 100644 --- a/profiler/profiler.cpp +++ b/profiler/profiler.cpp @@ -11,7 +11,7 @@ #include "gfx_es2/draw_buffer.h" #include "profiler/profiler.h" -#define MAX_CATEGORIES 16 // Can be any number +#define MAX_CATEGORIES 32 // Can be any number #define MAX_DEPTH 16 // Can be any number #define HISTORY_SIZE 256 // Must be power of 2 From 4588eb8328412265f08bcc61418d0b64454d4776 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 5 Jul 2015 18:45:23 +0200 Subject: [PATCH 1412/1445] Add a couple of accessors to InfoView --- ui/view.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ui/view.h b/ui/view.h index 7f82fdb61d..a4832bb66b 100644 --- a/ui/view.h +++ b/ui/view.h @@ -596,6 +596,13 @@ public: // These are focusable so that long lists of them can be keyboard scrolled. bool CanBeFocused() const override { return true; } + void SetText(const std::string &text) { + text_ = text; + } + void SetRightText(const std::string &text) { + rightText_ = text; + } + private: std::string text_; std::string rightText_; From 758c614f0a3eea6c95a7c2e6f9e03ddca6e5ae6a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Jul 2015 16:21:24 +0200 Subject: [PATCH 1413/1445] Set threadnames on Android --- thread/threadutil.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/thread/threadutil.cpp b/thread/threadutil.cpp index 6dcaa4369d..c0ff13f044 100644 --- a/thread/threadutil.cpp +++ b/thread/threadutil.cpp @@ -9,6 +9,10 @@ #include "base/logging.h" #include "thread/threadutil.h" +#ifdef ANDROID +#include +#endif + #ifdef TLS_SUPPORTED static __THREAD const char *curThreadName; #endif @@ -38,6 +42,13 @@ void setCurrentThreadName(const char* threadName) { __except(EXCEPTION_CONTINUE_EXECUTION) {} #else + +#if defined(ANDROID) + pthread_setname_np(pthread_self(), threadName); +// #else +// pthread_setname_np(thread_name); +#endif + // Do nothing #endif // Set the locally known threadname using a thread local variable. From 7c24761d4db84a5b9140794ad7c03252c1ed36b0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Jul 2015 17:14:48 +0200 Subject: [PATCH 1414/1445] Http download : set completed flag even if failed. Use setThreadName on android in init --- android/app-android.cpp | 25 +++---------------------- net/http_client.cpp | 10 ++++------ 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 204167c254..44a10ded1b 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -18,6 +18,7 @@ #include "base/NativeApp.h" #include "base/logging.h" #include "base/timeutil.h" +#include "thread/threadutil.h" #include "file/zip_read.h" #include "input/input_state.h" #include "profiler/profiler.h" @@ -193,6 +194,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeApp_init jstring jinstallID, jint jAndroidVersion) { jniEnvUI = env; + setCurrentThreadName("androidInit"); + ILOG("NativeApp.init() -- begin"); PROFILE_INIT(); @@ -385,28 +388,6 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayShutdown( } } - -// This path is not used if OpenSL ES is available. -extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* env, jclass clazz, jshortArray array) { - // The audio thread can pretty safely enable Flush-to-Zero mode on the FPU. - EnableFZ(); - - int buf_size = env->GetArrayLength(array); - if (buf_size) { - short *data = env->GetShortArrayElements(array, 0); - int samples = buf_size / 2; - samples = NativeMix(data, samples); - if (samples != 0) { - env->ReleaseShortArrayElements(array, data, 0); - return samples * 2; - } else { - env->ReleaseShortArrayElements(array, data, JNI_ABORT); - return 0; - } - } - return 0; -} - extern "C" jboolean JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch (JNIEnv *, jclass, float x, float y, int code, int pointerId) { float scaledX = x * dp_xscale; diff --git a/net/http_client.cpp b/net/http_client.cpp index a3fba7f37c..aecee2ae1d 100644 --- a/net/http_client.cpp +++ b/net/http_client.cpp @@ -351,6 +351,7 @@ void Download::Start(std::shared_ptr self) { void Download::SetFailed(int code) { failed_ = true; progress_ = 1.0f; + completed_ = true; } void Download::Do(std::shared_ptr self) { @@ -361,8 +362,7 @@ void Download::Do(std::shared_ptr self) { Url fileUrl(url_); if (!fileUrl.Valid()) { - failed_ = true; - progress_ = 1.0f; + SetFailed(-1); return; } net::AutoInit netInit; @@ -370,8 +370,7 @@ void Download::Do(std::shared_ptr self) { http::Client client; if (!client.Resolve(fileUrl.Host().c_str(), fileUrl.Port())) { ELOG("Failed resolving %s", url_.c_str()); - failed_ = true; - progress_ = 1.0f; + SetFailed(-1); return; } @@ -382,8 +381,7 @@ void Download::Do(std::shared_ptr self) { if (!client.Connect()) { ELOG("Failed connecting to server."); - resultCode_ = -1; - progress_ = 1.0f; + SetFailed(-1); return; } From e23e20d8a1a74326027850982c33e501010f39c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Jul 2015 17:27:02 +0200 Subject: [PATCH 1415/1445] Get rid of the separate so file for OpenSL stuff, we haven't supported 2.2 for a long time Code needs some cleanup, but that's for later. --- Android.mk | 1 + android/native-audio-so.cpp | 4 ++-- android/native-audio-so.h | 6 ++---- android/native_audio.cpp | 32 +++++--------------------------- 4 files changed, 10 insertions(+), 33 deletions(-) diff --git a/Android.mk b/Android.mk index ed517e5302..77ff519153 100644 --- a/Android.mk +++ b/Android.mk @@ -8,6 +8,7 @@ LOCAL_MODULE := libnative LOCAL_ARM_MODE := arm LOCAL_SRC_FILES :=\ android/native_audio.cpp \ + android/native-audio-so.cpp \ audio/wav_read.cpp \ audio/mixer.cpp.arm \ base/backtrace.cpp \ diff --git a/android/native-audio-so.cpp b/android/native-audio-so.cpp index 71c6c214bf..901fdeea22 100644 --- a/android/native-audio-so.cpp +++ b/android/native-audio-so.cpp @@ -66,7 +66,7 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { } // create the engine and output mix objects -extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate) { +bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate) { audioCallback = cb; framesPerBuffer = _FramesPerBuffer; if (framesPerBuffer == 0) @@ -150,7 +150,7 @@ extern "C" bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, i } // shut down the native audio system -extern "C" void OpenSLWrap_Shutdown() { +void OpenSLWrap_Shutdown() { SLresult result; ILOG("OpenSLWrap_Shutdown - stopping playback"); result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); diff --git a/android/native-audio-so.h b/android/native-audio-so.h index c48123db41..72d36db6a5 100644 --- a/android/native-audio-so.h +++ b/android/native-audio-so.h @@ -1,8 +1,6 @@ #pragma once -// Header for dynamic loading - typedef int (*AndroidAudioCallback)(short *buffer, int num_samples); -typedef bool (*OpenSLWrap_Init_T)(AndroidAudioCallback cb, int framesPerBuffer, int sampleRate); -typedef void (*OpenSLWrap_Shutdown_T)(); +bool OpenSLWrap_Init(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate); +void OpenSLWrap_Shutdown(); \ No newline at end of file diff --git a/android/native_audio.cpp b/android/native_audio.cpp index 0e0f8d455b..a96dc1bf02 100644 --- a/android/native_audio.cpp +++ b/android/native_audio.cpp @@ -1,15 +1,10 @@ -#include -#include - #include "base/logging.h" #include "android/native_audio.h" #include "android/native-audio-so.h" struct AudioState { void *so; - AndroidAudioCallback s_cb; - OpenSLWrap_Init_T init_func; - OpenSLWrap_Shutdown_T shutdown_func; + AndroidAudioCallback callback; bool playing; int frames_per_buffer; int sample_rate; @@ -17,31 +12,18 @@ struct AudioState { static AudioState *state = 0; -bool AndroidAudio_Init(AndroidAudioCallback cb, std::string libraryDir, int optimalFramesPerBuffer, int optimalSampleRate) { +bool AndroidAudio_Init(AndroidAudioCallback callback, std::string libraryDir, int optimalFramesPerBuffer, int optimalSampleRate) { if (state != 0) { ELOG("Audio state already exists"); return false; } - ILOG("Loading native audio library..."); - std::string so_filename = libraryDir + "/libnative_audio.so"; - void *the_so = dlopen(so_filename.c_str(), RTLD_LAZY); - if (!the_so) { - ELOG("Failed to find native audio library: %i: %s ", errno, dlerror()); - return false; - } - state = new AudioState(); - state->so = the_so; - state->s_cb = cb; + state->callback = callback; state->playing = false; - state->init_func = (OpenSLWrap_Init_T)dlsym(state->so, "OpenSLWrap_Init"); - state->shutdown_func = (OpenSLWrap_Shutdown_T)dlsym(state->so, "OpenSLWrap_Shutdown"); state->frames_per_buffer = optimalFramesPerBuffer ? optimalFramesPerBuffer : 256; state->sample_rate = optimalSampleRate ? optimalSampleRate : 44100; - ILOG("OpenSLWrap init_func: %p shutdown_func: %p", (void *)state->init_func, (void *)state->shutdown_func); - return true; } @@ -52,7 +34,7 @@ bool AndroidAudio_Resume() { } if (!state->playing) { ILOG("Calling OpenSLWrap_Init_T..."); - bool init_retval = state->init_func(state->s_cb, state->frames_per_buffer, state->sample_rate); + bool init_retval = OpenSLWrap_Init(state->callback, state->frames_per_buffer, state->sample_rate); ILOG("Returned from OpenSLWrap_Init_T"); state->playing = true; return init_retval; @@ -67,7 +49,7 @@ bool AndroidAudio_Pause() { } if (state->playing) { ILOG("Calling OpenSLWrap_Shutdown_T..."); - state->shutdown_func(); + OpenSLWrap_Shutdown(); ILOG("Returned from OpenSLWrap_Shutdown_T ..."); state->playing = false; return true; @@ -83,10 +65,6 @@ void AndroidAudio_Shutdown() { if (state->playing) { ELOG("Should not shut down when playing! Something is wrong!"); } - ILOG("dlclose"); - dlclose(state->so); - ILOG("Returned from dlclose"); - state->so = 0; delete state; state = 0; ILOG("OpenSLWrap completely unloaded."); From 166d07df0c37c038a02bda687ba77a5bbfd1d01c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 19 Jul 2015 17:33:03 +0200 Subject: [PATCH 1416/1445] MogaHack: Remove irrelevant log (?) --- android/src/com/henrikrydgard/libnative/MogaHack.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/src/com/henrikrydgard/libnative/MogaHack.java b/android/src/com/henrikrydgard/libnative/MogaHack.java index 2eb88354a3..74bda85f79 100644 --- a/android/src/com/henrikrydgard/libnative/MogaHack.java +++ b/android/src/com/henrikrydgard/libnative/MogaHack.java @@ -85,7 +85,8 @@ public class MogaHack List resolveInfos = context.getPackageManager().queryIntentServices( intent, 0 ); if( resolveInfos == null || resolveInfos.size() != 1 ) { - Log.e( "MogaHack", "Somebody is trying to intercept our intent. Disabling MOGA controller for security." ); + // What? this doesn't do anything. + // Log.e( "MogaHack", "Somebody is trying to intercept our intent. Disabling MOGA controller for security." ); } ServiceInfo serviceInfo = resolveInfos.get( 0 ).serviceInfo; String packageName = serviceInfo.packageName; From a9cefe2f3ad5c9f9af6e19af06e54e082cbbb9d5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 20 Jul 2015 20:28:59 +0200 Subject: [PATCH 1417/1445] Android: Set display thread name, release local refs to frame comman strings properly --- android/app-android.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/android/app-android.cpp b/android/app-android.cpp index 44a10ded1b..581517107f 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -334,6 +334,12 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayResize(JN } extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JNIEnv *env, jobject obj) { + static bool hasSetThreadName = false; + if (!hasSetThreadName) { + hasSetThreadName = true; + setCurrentThreadName("AndroidRender"); + } + if (renderer_inited) { // TODO: Look into if these locks are a perf loss { @@ -375,6 +381,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN jstring cmd = env->NewStringUTF(frameCmd.command.c_str()); jstring param = env->NewStringUTF(frameCmd.params.c_str()); env->CallVoidMethod(obj, postCommand, cmd, param); + env->DeleteLocalRef(cmd); + env->DeleteLocalRef(param); } } From 477568b3485e9921ede59c26b266c762b1fbd066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Jul 2015 20:46:31 +0200 Subject: [PATCH 1418/1445] Try to improve GPU vendor detection. --- gfx_es2/gl_state.cpp | 3 ++- thin3d/thin3d.h | 1 + thin3d/thin3d_d3d9.cpp | 3 ++- thin3d/thin3d_gl.cpp | 16 +++++++++++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 200ec4ffdb..b378e4abcf 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -1,6 +1,7 @@ #include #include "base/logging.h" +#include "base/stringutil.h" #include "base/NativeApp.h" #include "gl_state.h" @@ -104,7 +105,7 @@ void CheckGLExtensions() { const char *cvendor = (char *)glGetString(GL_VENDOR); // TODO: move this stuff to gpu_features.cpp if (cvendor) { - const std::string vendor(cvendor); + const std::string vendor = StripSpaces(std::string(cvendor)); if (vendor == "NVIDIA Corporation" || vendor == "Nouveau" || vendor == "nouveau") { diff --git a/thin3d/thin3d.h b/thin3d/thin3d.h index fb71bb1077..3b7d3a17d0 100644 --- a/thin3d/thin3d.h +++ b/thin3d/thin3d.h @@ -175,6 +175,7 @@ enum T3DImageType { enum T3DInfo { APINAME, APIVERSION, + VENDORSTRING, VENDOR, SHADELANGVERSION, RENDERER, diff --git a/thin3d/thin3d_d3d9.cpp b/thin3d/thin3d_d3d9.cpp index 81cff9f472..ea18919e3f 100644 --- a/thin3d/thin3d_d3d9.cpp +++ b/thin3d/thin3d_d3d9.cpp @@ -423,7 +423,8 @@ public: const char *GetInfoString(T3DInfo info) const override { switch (info) { case APIVERSION: return "DirectX 9.0"; - case VENDOR: return identifier_.Description; + case VENDORSTRING: return identifier_.Description; + case VENDOR: return "-"; case RENDERER: return identifier_.Driver; // eh, sort of case SHADELANGVERSION: return shadeLangVersion_; case APINAME: return "Direct3D 9"; diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index fa682c935c..fe3ac92d32 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -347,7 +347,21 @@ public: #else return "OpenGL"; #endif - case VENDOR: return (const char *)glGetString(GL_VENDOR); + case VENDORSTRING: return (const char *)glGetString(GL_VENDOR); + case VENDOR: + switch (gl_extensions.gpuVendor) { + case GPU_VENDOR_AMD: return "VENDOR_AMD"; + case GPU_VENDOR_POWERVR: return "VENDOR_POWERVR"; + case GPU_VENDOR_NVIDIA: return "VENDOR_NVIDIA"; + case GPU_VENDOR_INTEL: return "VENDOR_INTEL"; + case GPU_VENDOR_ADRENO: return "VENDOR_ADRENO"; + case GPU_VENDOR_ARM: return "VENDOR_ARM"; + case GPU_VENDOR_BROADCOM: return "VENDOR_BROADCOM"; + case GPU_VENDOR_UNKNOWN: + default: + return "VENDOR_UNKNOWN"; + } + break; case RENDERER: return (const char *)glGetString(GL_RENDERER); case SHADELANGVERSION: return (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); case APIVERSION: return (const char *)glGetString(GL_VERSION); From 9baedbcc2a07b3bccc6d8b8d170498111b990adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 6 Aug 2015 17:48:34 +0200 Subject: [PATCH 1419/1445] Shorter file path in ILOG/ELOG/WLOG etc on unix-likes --- base/logging.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/base/logging.h b/base/logging.h index 72837a4c6f..4bdba4aaa4 100644 --- a/base/logging.h +++ b/base/logging.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "base/arch.h" #include "base/backtrace.h" #include "base/compat.h" @@ -112,15 +114,20 @@ void OutputDebugStringUTF8(const char *p); #include +inline const char *removePath(const char *str) { + const char *slash = strrchr(str, '/'); + return slash ? (slash + 1) : str; +} + #ifdef _DEBUG -#define DLOG(...) {printf("D: %s:%i: ", __FILE__, __LINE__); printf("D: " __VA_ARGS__); printf("\n");} +#define DLOG(...) {printf("D: %s:%i: ", removePath(__FILE__), __LINE__); printf("D: " __VA_ARGS__); printf("\n");} #else #define DLOG(...) #endif -#define ILOG(...) {printf("I: %s:%i: ", __FILE__, __LINE__); printf("I: " __VA_ARGS__); printf("\n");} -#define WLOG(...) {printf("W: %s:%i: ", __FILE__, __LINE__); printf("W: " __VA_ARGS__); printf("\n");} -#define ELOG(...) {printf("E: %s:%i: ", __FILE__, __LINE__); printf("E: " __VA_ARGS__); printf("\n");} -#define FLOG(...) {printf("F: %s:%i: ", __FILE__, __LINE__); printf("F: " __VA_ARGS__); printf("\n"); Crash();} +#define ILOG(...) {printf("I: %s:%i: ", removePath(__FILE__), __LINE__); printf("I: " __VA_ARGS__); printf("\n");} +#define WLOG(...) {printf("W: %s:%i: ", removePath(__FILE__), __LINE__); printf("W: " __VA_ARGS__); printf("\n");} +#define ELOG(...) {printf("E: %s:%i: ", removePath(__FILE__), __LINE__); printf("E: " __VA_ARGS__); printf("\n");} +#define FLOG(...) {printf("F: %s:%i: ", removePath(__FILE__), __LINE__); printf("F: " __VA_ARGS__); printf("\n"); Crash();} #endif #endif From 8487e56b4283f2f8bcd9ed394956bf1eb3f8cdfd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 23 Aug 2015 21:34:11 -0700 Subject: [PATCH 1420/1445] Move some GLES checks to runtime. --- gfx/texture.cpp | 10 +- gfx_es2/fbo.cpp | 87 +++++++------ gfx_es2/gl_state.cpp | 288 +++++++++++++++++++++-------------------- gfx_es2/gpu_features.h | 3 +- thin3d/thin3d_gl.cpp | 10 +- 5 files changed, 201 insertions(+), 197 deletions(-) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index f4eab57b7a..6cc617a241 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -68,11 +68,11 @@ bool Texture::Load(const char *filename) { glGenTextures(1, &id_); glBindTexture(GL_TEXTURE_2D, id_); if (bpp == 1) { -#if defined(USING_GLES2) - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); -#else - glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); -#endif + if (gl_extensions.IsGLES) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + } } else { FLOG("unsupported"); } diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index a338417bf3..35cd3c0ee8 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -19,10 +19,11 @@ #ifndef GL_DEPTH_COMPONENT24 #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #endif +#endif + #ifndef GL_DEPTH24_STENCIL8_OES #define GL_DEPTH24_STENCIL8_OES 0x88F0 #endif -#endif #ifdef IOS extern void bindDefaultFBO(); @@ -174,56 +175,56 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -#ifdef USING_GLES2 - if (gl_extensions.OES_packed_depth_stencil) { - ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", width, height); - // Standard method + if (gl_extensions.IsGLES) { + if (gl_extensions.OES_packed_depth_stencil) { + ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", width, height); + // Standard method + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 24-bit Z, 8-bit stencil combined + glGenRenderbuffers(1, &fbo->z_stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); + + // Bind it all together + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + } else { + ILOG("Creating %i x %i FBO using separate stencil", width, height); + // TEGRA + fbo->z_stencil_buffer = 0; + // 16/24-bit Z, separate 8-bit stencil + glGenRenderbuffers(1, &fbo->z_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, width, height); + + // 8-bit stencil buffer + glGenRenderbuffers(1, &fbo->stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); + + // Bind it all together + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); + } + } else { fbo->stencil_buffer = 0; fbo->z_buffer = 0; - // 24-bit Z, 8-bit stencil combined + // 24-bit Z, 8-bit stencil glGenRenderbuffers(1, &fbo->z_stencil_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); // Bind it all together glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - } else { - ILOG("Creating %i x %i FBO using separate stencil", width, height); - // TEGRA - fbo->z_stencil_buffer = 0; - // 16/24-bit Z, separate 8-bit stencil - glGenRenderbuffers(1, &fbo->z_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, width, height); - - // 8-bit stencil buffer - glGenRenderbuffers(1, &fbo->stencil_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); - - // Bind it all together - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); } -#else - fbo->stencil_buffer = 0; - fbo->z_buffer = 0; - // 24-bit Z, 8-bit stencil - glGenRenderbuffers(1, &fbo->z_stencil_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); - - // Bind it all together - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); -#endif GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { @@ -269,9 +270,9 @@ FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo) static GLenum fbo_get_fb_target(bool read, GLuint **cached) { bool supportsBlit = gl_extensions.FBO_ARB; -#ifdef USING_GLES2 - supportsBlit = supportsBlit && (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); -#endif + if (gl_extensions.IsGLES) { + supportsBlit = supportsBlit && (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); + } // Note: GL_FRAMEBUFFER_EXT and GL_FRAMEBUFFER have the same value, same with _NV. if (supportsBlit) { diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index b378e4abcf..90045eafd6 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -97,6 +97,10 @@ void CheckGLExtensions() { done = true; memset(&gl_extensions, 0, sizeof(gl_extensions)); +#ifdef USING_GLES2 + gl_extensions.IsGLES = true; +#endif + const char *renderer = (const char *)glGetString(GL_RENDERER); const char *versionStr = (const char *)glGetString(GL_VERSION); const char *glslVersionStr = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); @@ -141,85 +145,89 @@ void CheckGLExtensions() { gl_extensions.model[sizeof(gl_extensions.model) - 1] = 0; } -#ifndef USING_GLES2 - char buffer[64] = { 0 }; - if (versionStr) { - strncpy(buffer, versionStr, 63); - } - const char *lastNumStart = buffer; - int numVer = 0; - int len = (int)strlen(buffer); - for (int i = 0; i < len && numVer < 3; i++) { - if (buffer[i] == '.') { - buffer[i] = 0; - gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); - i++; - lastNumStart = buffer + i; + if (!gl_extensions.IsGLES) { + // For desktop GL, grab the version and attempt to parse. + char buffer[64] = { 0 }; + if (versionStr) { + strncpy(buffer, versionStr, 63); } - } - if (numVer < 3) - gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); -#else - gl_extensions.ver[0] = 2; -#endif - -#if defined(USING_GLES2) -#ifdef GL_MAJOR_VERSION - // Before grabbing the values, reset the error. - glGetError(); - glGetIntegerv(GL_MAJOR_VERSION, &gl_extensions.ver[0]); - glGetIntegerv(GL_MINOR_VERSION, &gl_extensions.ver[1]); - if (glGetError() != GL_NO_ERROR) { - gl_extensions.ver[0] = 2; - gl_extensions.ver[1] = 0; - } -#endif - - // If the above didn't give us a version, or gave us a crazy version, fallback. - if (gl_extensions.ver[0] < 3 || gl_extensions.ver[0] > 5) { - // Try to load GLES 3.0 only if "3.0" found in version - // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited - // number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584. - bool gl_3_0_in_string = strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0"); - bool gl_3_1_in_string = strstr(versionStr, "3.1") && strstr(glslVersionStr, "3.1"); // intentionally left out .1 - if ((gl_3_0_in_string || gl_3_1_in_string) && gl3stubInit()) { - gl_extensions.ver[0] = 3; - if (gl_3_1_in_string) { - gl_extensions.ver[1] = 1; + const char *lastNumStart = buffer; + int numVer = 0; + int len = (int)strlen(buffer); + for (int i = 0; i < len && numVer < 3; i++) { + if (buffer[i] == '.') { + buffer[i] = 0; + gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); + i++; + lastNumStart = buffer + i; } + } + if (numVer < 3) + gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); + + // If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable + // all the same modern paths. + // Most of it could be enabled on lower GPUs as well, but let's start this way. + if (gl_extensions.VersionGEThan(4, 3, 0)) { gl_extensions.GLES3 = true; - // Though, let's ban Mali from the GLES 3 path for now, see #4078 - if (strstr(renderer, "Mali") != 0) { - gl_extensions.GLES3 = false; - } - } else { - // Just to be safe. + } + } else { + // Start by assuming we're at 2.0. + gl_extensions.ver[0] = 2; + +#ifdef USING_GLES2 +#ifdef GL_MAJOR_VERSION + // Before grabbing the values, reset the error. + glGetError(); + glGetIntegerv(GL_MAJOR_VERSION, &gl_extensions.ver[0]); + glGetIntegerv(GL_MINOR_VERSION, &gl_extensions.ver[1]); + // We check error here to detect if these properties were supported. + if (glGetError() != GL_NO_ERROR) { + // They weren't, reset to GLES 2.0. gl_extensions.ver[0] = 2; gl_extensions.ver[1] = 0; } - } else { - // Otherwise, let's trust GL_MAJOR_VERSION. Note that Mali is intentionally not banned here. - if (gl_extensions.ver[0] >= 3) { - gl_extensions.GLES3 = gl3stubInit(); - } - } - - if (gl_extensions.GLES3) { - if (gl_extensions.ver[1] >= 1) { - ILOG("OpenGL ES 3.1 support detected!\n"); - } else { - ILOG("OpenGL ES 3.0 support detected!\n"); - } - } -#else - // If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable - // all the same modern paths. - // Most of it could be enabled on lower GPUs as well, but let's start this way. - if (gl_extensions.VersionGEThan(4, 3, 0)) { - gl_extensions.GLES3 = true; - } #endif + // If the above didn't give us a version, or gave us a crazy version, fallback. + if (gl_extensions.ver[0] < 3 || gl_extensions.ver[0] > 5) { + // Try to load GLES 3.0 only if "3.0" found in version + // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited + // number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584. + bool gl_3_0_in_string = strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0"); + bool gl_3_1_in_string = strstr(versionStr, "3.1") && strstr(glslVersionStr, "3.1"); // intentionally left out .1 + if ((gl_3_0_in_string || gl_3_1_in_string) && gl3stubInit()) { + gl_extensions.ver[0] = 3; + if (gl_3_1_in_string) { + gl_extensions.ver[1] = 1; + } + gl_extensions.GLES3 = true; + // Though, let's ban Mali from the GLES 3 path for now, see #4078 + if (strstr(renderer, "Mali") != 0) { + gl_extensions.GLES3 = false; + } + } else { + // Just to be safe. + gl_extensions.ver[0] = 2; + gl_extensions.ver[1] = 0; + } + } else { + // Otherwise, let's trust GL_MAJOR_VERSION. Note that Mali is intentionally not banned here. + if (gl_extensions.ver[0] >= 3) { + gl_extensions.GLES3 = gl3stubInit(); + } + } +#endif + + if (gl_extensions.GLES3) { + if (gl_extensions.ver[1] >= 1) { + ILOG("OpenGL ES 3.1 support detected!\n"); + } else { + ILOG("OpenGL ES 3.0 support detected!\n"); + } + } + } + const char *extString = (const char *)glGetString(GL_EXTENSIONS); if (extString) { g_all_gl_extensions = extString; @@ -260,70 +268,70 @@ void CheckGLExtensions() { gl_extensions.ARB_blend_func_extended = false; } -#ifdef USING_GLES2 - gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0; - gl_extensions.OES_packed_depth_stencil = (strstr(extString, "GL_OES_packed_depth_stencil") != 0) || gl_extensions.GLES3; - gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; - gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; - gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; - gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0; - gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; - gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; - gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; - gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0; - gl_extensions.ANY_shader_framebuffer_fetch = gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.NV_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch; - gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; + if (gl_extensions.IsGLES) { + gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0; + gl_extensions.OES_packed_depth_stencil = (strstr(extString, "GL_OES_packed_depth_stencil") != 0) || gl_extensions.GLES3; + gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; + gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; + gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; + gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0; + gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; + gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; + gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; + gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0; + gl_extensions.ANY_shader_framebuffer_fetch = gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.NV_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch; + gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; - // Framebuffer fetch appears to be buggy at least on Tegra 3 devices. So we blacklist it. - // Tales of Destiny 2 has been reported to display green. - if (gl_extensions.ANY_shader_framebuffer_fetch && strstr(renderer, "NVIDIA Tegra 3") != 0) { - gl_extensions.ANY_shader_framebuffer_fetch = false; - } + // Framebuffer fetch appears to be buggy at least on Tegra 3 devices. So we blacklist it. + // Tales of Destiny 2 has been reported to display green. + if (gl_extensions.ANY_shader_framebuffer_fetch && strstr(renderer, "NVIDIA Tegra 3") != 0) { + gl_extensions.ANY_shader_framebuffer_fetch = false; + } #if defined(ANDROID) || defined(BLACKBERRY) - // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. - // https://twitter.com/ID_AA_Carmack/status/387383037794603008 + // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. + // https://twitter.com/ID_AA_Carmack/status/387383037794603008 #ifdef _DEBUG - void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1"); - void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2"); - DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2); + void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1"); + void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2"); + DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2); #endif - if (gl_extensions.NV_draw_texture) { - glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)eglGetProcAddress("glDrawTextureNV"); - } + if (gl_extensions.NV_draw_texture) { + glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)eglGetProcAddress("glDrawTextureNV"); + } - if (gl_extensions.NV_copy_image) { - glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV"); - } + if (gl_extensions.NV_copy_image) { + glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV"); + } - if (gl_extensions.NV_framebuffer_blit) { - glBlitFramebufferNV = (PFNGLBLITFRAMEBUFFERNVPROC)eglGetProcAddress("glBlitFramebufferNV"); - } + if (gl_extensions.NV_framebuffer_blit) { + glBlitFramebufferNV = (PFNGLBLITFRAMEBUFFERNVPROC)eglGetProcAddress("glBlitFramebufferNV"); + } - gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0; - if (gl_extensions.OES_vertex_array_object) { - glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" ); - glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress ( "glBindVertexArrayOES" ); - glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress ( "glDeleteVertexArraysOES" ); - glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" ); - } + gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0; + if (gl_extensions.OES_vertex_array_object) { + glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" ); + glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress ( "glBindVertexArrayOES" ); + glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress ( "glDeleteVertexArraysOES" ); + glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" ); + } - // Hm, this should be available on iOS too. - gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; - if (gl_extensions.EXT_discard_framebuffer) { - glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); - } + // Hm, this should be available on iOS too. + gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; + if (gl_extensions.EXT_discard_framebuffer) { + glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); + } #else - gl_extensions.OES_vertex_array_object = false; - gl_extensions.EXT_discard_framebuffer = false; + gl_extensions.OES_vertex_array_object = false; + gl_extensions.EXT_discard_framebuffer = false; #endif + } else { + // Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc) + gl_extensions.EXT_blend_minmax = true; + gl_extensions.EXT_unpack_subimage = true; + } -#else - // Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc) - gl_extensions.EXT_blend_minmax = true; - gl_extensions.EXT_unpack_subimage = true; -#endif // GLES 3 subsumes many ES2 extensions. if (gl_extensions.GLES3) { gl_extensions.EXT_unpack_subimage = true; @@ -353,11 +361,7 @@ void CheckGLExtensions() { } #endif -#ifdef USING_GLES2 - if (true) { -#else - if (strstr(extString, "GL_ARB_ES2_compatibility")) { -#endif + if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility")) { const GLint precisions[6] = { GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT, GL_LOW_INT, GL_MEDIUM_INT, GL_HIGH_INT @@ -372,23 +376,21 @@ void CheckGLExtensions() { } } - -#ifdef USING_GLES2 - gl_extensions.FBO_ARB = true; - gl_extensions.FBO_EXT = false; -#else - - gl_extensions.FBO_ARB = false; - gl_extensions.FBO_EXT = false; - gl_extensions.PBO_ARB = true; - gl_extensions.PBO_NV = true; - if (strlen(extString) != 0) { - gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; - gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; - gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; - gl_extensions.PBO_NV = strstr(extString, "GL_NV_pixel_buffer_object") != 0; + if (gl_extensions.IsGLES) { + gl_extensions.FBO_ARB = true; + gl_extensions.FBO_EXT = false; + } else { + gl_extensions.FBO_ARB = false; + gl_extensions.FBO_EXT = false; + gl_extensions.PBO_ARB = true; + gl_extensions.PBO_NV = true; + if (strlen(extString) != 0) { + gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; + gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; + gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; + gl_extensions.PBO_NV = strstr(extString, "GL_NV_pixel_buffer_object") != 0; + } } -#endif ProcessGPUFeatures(); diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 79309b8b19..cf86c6f7a4 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -33,6 +33,7 @@ struct GLExtensions { int gpuVendor; char model[128]; + bool IsGLES; bool GLES3; // true if the full OpenGL ES 3.0 is supported // OES @@ -92,6 +93,6 @@ extern GLExtensions gl_extensions; // Call this after filling out vendor etc to lookup the bugs etc. -// Only needs to be called ones. Currently called by CheckGLExtensions(). +// Only needs to be called once. Currently called by CheckGLExtensions(). void ProcessGPUFeatures(); diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index fe3ac92d32..b224a06aa5 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -342,11 +342,11 @@ public: // TODO: Make these actually query the right information switch (info) { case APINAME: - #ifdef USING_GLES2 - return "OpenGL ES"; - #else - return "OpenGL"; - #endif + if (gl_extensions.IsGLES) { + return "OpenGL ES"; + } else { + return "OpenGL"; + } case VENDORSTRING: return (const char *)glGetString(GL_VENDOR); case VENDOR: switch (gl_extensions.gpuVendor) { From a75c4d283d575362cbefeae25477dfde607de594 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 27 Aug 2015 19:28:10 +0200 Subject: [PATCH 1421/1445] GL: Check for ARB_conservative_depth --- gfx_es2/gl_state.cpp | 1 + gfx_es2/gpu_features.h | 1 + 2 files changed, 2 insertions(+) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 90045eafd6..8923d50ac5 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -258,6 +258,7 @@ void CheckGLExtensions() { gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; + gl_extensions.ARB_conservative_depth = strstr(extString, "GL_ARB_conservative_depth") != 0; gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0; gl_extensions.EXT_gpu_shader4 = strstr(extString, "GL_EXT_gpu_shader4") != 0; diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index cf86c6f7a4..d4207970c8 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -49,6 +49,7 @@ struct GLExtensions { bool PBO_ARB; bool ARB_blend_func_extended; // dual source blending bool ARB_shader_image_load_store; + bool ARB_conservative_depth; // EXT bool EXT_swap_control_tear; From e1d3a7421bba3522b7de112cf7659eda55c1b0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20H=C3=B6glund?= Date: Fri, 28 Aug 2015 16:51:07 +0200 Subject: [PATCH 1422/1445] Move KeyDef and AxisPos to native --- input/input_state.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/input/input_state.h b/input/input_state.h index 5f948c7427..3f68a4d289 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -79,6 +79,43 @@ enum { #define MAX_KEYQUEUESIZE 20 #endif +// Represents a single bindable key +class KeyDef { +public: + KeyDef() : deviceId(0), keyCode(0) {} + KeyDef(int devId, int k) : deviceId(devId), keyCode(k) {} + int deviceId; + int keyCode; + + bool operator < (const KeyDef &other) const { + if (deviceId < other.deviceId) return true; + if (deviceId > other.deviceId) return false; + if (keyCode < other.keyCode) return true; + return false; + } + bool operator == (const KeyDef &other) const { + if (deviceId != other.deviceId) return false; + if (keyCode != other.keyCode) return false; + return true; + } +}; + +// Represents a single bindable axis direction +struct AxisPos { + int axis; + float position; + + bool operator < (const AxisPos &other) const { + if (axis < other.axis) return true; + if (axis > other.axis) return false; + return position < other.position; + } + bool operator == (const AxisPos &other) const { + return axis == other.axis && position == other.position; + } +}; + + // Collection of all possible inputs, and automatically computed // deltas where applicable. struct InputState { From 32617ae17ccbd8dfe57eb534b640c5ef4634de0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20H=C3=B6glund?= Date: Fri, 28 Aug 2015 17:05:11 +0200 Subject: [PATCH 1423/1445] Use KeyDef for Confirm/Cancel/TabLeft/TabRight keys --- input/input_state.cpp | 12 ++++++------ input/input_state.h | 12 ++++++------ ui/ui_screen.cpp | 2 +- ui/view.cpp | 40 ++++++++++++++++++++++++---------------- ui/view.h | 8 ++++---- ui/viewgroup.cpp | 4 ++-- 6 files changed, 43 insertions(+), 35 deletions(-) diff --git a/input/input_state.cpp b/input/input_state.cpp index 2761c6564d..0a81a3d8d3 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -51,17 +51,17 @@ int MapPadButtonFixed(int keycode) { } } -std::vector confirmKeys; -std::vector cancelKeys; -std::vector tabLeftKeys; -std::vector tabRightKeys; +std::vector confirmKeys; +std::vector cancelKeys; +std::vector tabLeftKeys; +std::vector tabRightKeys; -void SetConfirmCancelKeys(const std::vector &confirm, const std::vector &cancel) { +void SetConfirmCancelKeys(const std::vector &confirm, const std::vector &cancel) { confirmKeys = confirm; cancelKeys = cancel; } -void SetTabLeftRightKeys(const std::vector &tabLeft, const std::vector &tabRight) { +void SetTabLeftRightKeys(const std::vector &tabLeft, const std::vector &tabRight) { tabLeftKeys = tabLeft; tabRightKeys = tabRight; } diff --git a/input/input_state.h b/input/input_state.h index 3f68a4d289..2e92c6601a 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -240,9 +240,9 @@ private: extern ButtonTracker g_buttonTracker; // Is there a nicer place for this stuff? It's here to avoid dozens of linking errors in UnitTest.. -extern std::vector confirmKeys; -extern std::vector cancelKeys; -extern std::vector tabLeftKeys; -extern std::vector tabRightKeys; -void SetConfirmCancelKeys(const std::vector &confirm, const std::vector &cancel); -void SetTabLeftRightKeys(const std::vector &tabLeft, const std::vector &tabRight); +extern std::vector confirmKeys; +extern std::vector cancelKeys; +extern std::vector tabLeftKeys; +extern std::vector tabRightKeys; +void SetConfirmCancelKeys(const std::vector &confirm, const std::vector &cancel); +void SetTabLeftRightKeys(const std::vector &tabLeft, const std::vector &tabRight); diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 3fef16172e..0a85893905 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -65,7 +65,7 @@ bool UIScreen::key(const KeyInput &key) { bool UIDialogScreen::key(const KeyInput &key) { bool retval = UIScreen::key(key); - if (!retval && (key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) { + if (!retval && (key.flags & KEY_DOWN) && UI::IsEscapeKey(key)) { if (finished_) { ELOG("Screen already finished"); } else { diff --git a/ui/view.cpp b/ui/view.cpp index 7a38d9acf1..4cf70c2521 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -222,35 +222,43 @@ void Clickable::Touch(const TouchInput &input) { // TODO: O/X confirm preference for xperia play? -bool IsAcceptKeyCode(int keyCode) { +bool IsAcceptKey(const KeyInput &key) { if (confirmKeys.empty()) { - return keyCode == NKCODE_SPACE || keyCode == NKCODE_ENTER || keyCode == NKCODE_Z || keyCode == NKCODE_BUTTON_A || keyCode == NKCODE_BUTTON_CROSS || keyCode == NKCODE_BUTTON_1; + if (key.deviceId == DEVICE_ID_KEYBOARD) { + return key.keyCode == NKCODE_SPACE || key.keyCode == NKCODE_ENTER || key.keyCode == NKCODE_Z; + } else { + return key.keyCode == NKCODE_BUTTON_A || key.keyCode == NKCODE_BUTTON_CROSS || key.keyCode == NKCODE_BUTTON_1; + } } else { - return std::find(confirmKeys.begin(), confirmKeys.end(), (keycode_t)keyCode) != confirmKeys.end(); + return std::find(confirmKeys.begin(), confirmKeys.end(), KeyDef(key.deviceId, key.keyCode)) != confirmKeys.end(); } } -bool IsEscapeKeyCode(int keyCode) { +bool IsEscapeKey(const KeyInput &key) { if (cancelKeys.empty()) { - return keyCode == NKCODE_ESCAPE || keyCode == NKCODE_BACK || keyCode == NKCODE_BUTTON_CIRCLE || keyCode == NKCODE_BUTTON_B || keyCode == NKCODE_BUTTON_2; + if (key.deviceId == DEVICE_ID_KEYBOARD) { + return key.keyCode == NKCODE_ESCAPE || key.keyCode == NKCODE_BACK; + } else { + return key.keyCode == NKCODE_BUTTON_CIRCLE || key.keyCode == NKCODE_BUTTON_B || key.keyCode == NKCODE_BUTTON_2; + } } else { - return std::find(cancelKeys.begin(), cancelKeys.end(), (keycode_t)keyCode) != cancelKeys.end(); + return std::find(cancelKeys.begin(), cancelKeys.end(), KeyDef(key.deviceId, key.keyCode)) != cancelKeys.end(); } } -bool IsTabLeftKeyCode(int keyCode) { +bool IsTabLeftKey(const KeyInput &key) { if (tabLeftKeys.empty()) { - return keyCode == NKCODE_BUTTON_L1; + return key.keyCode == NKCODE_BUTTON_L1; } else { - return std::find(tabLeftKeys.begin(), tabLeftKeys.end(), (keycode_t)keyCode) != tabLeftKeys.end(); + return std::find(tabLeftKeys.begin(), tabLeftKeys.end(), KeyDef(key.deviceId, key.keyCode)) != tabLeftKeys.end(); } } -bool IsTabRightKeyCode(int keyCode) { +bool IsTabRightKey(const KeyInput &key) { if (tabRightKeys.empty()) { - return keyCode == NKCODE_BUTTON_R1; + return key.keyCode == NKCODE_BUTTON_R1; } else { - return std::find(tabRightKeys.begin(), tabRightKeys.end(), (keycode_t)keyCode) != tabRightKeys.end(); + return std::find(tabRightKeys.begin(), tabRightKeys.end(), KeyDef(key.deviceId, key.keyCode)) != tabRightKeys.end(); } } @@ -262,19 +270,19 @@ bool Clickable::Key(const KeyInput &key) { // TODO: Replace most of Update with this. bool ret = false; if (key.flags & KEY_DOWN) { - if (IsAcceptKeyCode(key.keyCode)) { + if (IsAcceptKey(key)) { down_ = true; ret = true; } } if (key.flags & KEY_UP) { - if (IsAcceptKeyCode(key.keyCode)) { + if (IsAcceptKey(key)) { if (down_) { Click(); down_ = false; ret = true; } - } else if (IsEscapeKeyCode(key.keyCode)) { + } else if (IsEscapeKey(key)) { down_ = false; } } @@ -305,7 +313,7 @@ bool StickyChoice::Key(const KeyInput &key) { // TODO: Replace most of Update with this. if (key.flags & KEY_DOWN) { - if (IsAcceptKeyCode(key.keyCode)) { + if (IsAcceptKey(key)) { down_ = true; Click(); return true; diff --git a/ui/view.h b/ui/view.h index a4832bb66b..b031b39bb3 100644 --- a/ui/view.h +++ b/ui/view.h @@ -801,9 +801,9 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure void EventTriggered(Event *e, EventParams params); void DispatchEvents(); -bool IsAcceptKeyCode(int keyCode); -bool IsEscapeKeyCode(int keyCode); -bool IsTabLeftKeyCode(int keyCode); -bool IsTabRightKeyCode(int keyCode); +bool IsAcceptKey(const KeyInput &key); +bool IsEscapeKey(const KeyInput &key); +bool IsTabLeftKey(const KeyInput &key); +bool IsTabRightKey(const KeyInput &key); } // namespace diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 8168384692..6f080a2c97 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1064,10 +1064,10 @@ void ChoiceStrip::HighlightChoice(unsigned int choice){ bool ChoiceStrip::Key(const KeyInput &input) { bool ret = false; if (input.flags & KEY_DOWN) { - if (IsTabLeftKeyCode(input.keyCode) && selected_ > 0) { + if (IsTabLeftKey(input) && selected_ > 0) { SetSelection(selected_ - 1); ret = true; - } else if (IsTabRightKeyCode(input.keyCode) && selected_ < (int)views_.size() - 1) { + } else if (IsTabRightKey(input) && selected_ < (int)views_.size() - 1) { SetSelection(selected_ + 1); ret = true; } From a57a838c93213e23909b69e0891499d30b3bee78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20H=C3=B6glund?= Date: Fri, 28 Aug 2015 20:51:33 +0200 Subject: [PATCH 1424/1445] Update key repeat logic to use provided DPad keys Implements a SetDPadKeys function akin to the Confirm/Cancel/TabLeft/TabRight keys, and uses this vector of DPad keys to decide whether a KeyInput is a DPad key or not. Rewrites the held-key release logic in such a way that it still ignores the deviceId, to handle the Ouya quirk where repeated events have deviceId 0. --- input/input_state.cpp | 19 +++++++++++++++++++ input/input_state.h | 3 +++ ui/view.cpp | 8 ++++++++ ui/view.h | 1 + ui/viewgroup.cpp | 13 +++++++------ 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/input/input_state.cpp b/input/input_state.cpp index 0a81a3d8d3..9cf5315733 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -51,11 +51,30 @@ int MapPadButtonFixed(int keycode) { } } +std::vector dpadKeys; std::vector confirmKeys; std::vector cancelKeys; std::vector tabLeftKeys; std::vector tabRightKeys; +static void AppendKeys(std::vector &keys, const std::vector &newKeys) { + for (auto iter = newKeys.begin(); iter != newKeys.end(); ++iter) { + keys.push_back(*iter); + } +} + +void SetDPadKeys(const std::vector &leftKey, const std::vector &rightKey, + const std::vector &upKey, const std::vector &downKey) { + dpadKeys.clear(); + + // Store all directions into one vector for now. In the future it might be + // useful to keep track of the different directions separately. + AppendKeys(dpadKeys, leftKey); + AppendKeys(dpadKeys, rightKey); + AppendKeys(dpadKeys, upKey); + AppendKeys(dpadKeys, downKey); +} + void SetConfirmCancelKeys(const std::vector &confirm, const std::vector &cancel) { confirmKeys = confirm; cancelKeys = cancel; diff --git a/input/input_state.h b/input/input_state.h index 2e92c6601a..e839053a59 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -240,9 +240,12 @@ private: extern ButtonTracker g_buttonTracker; // Is there a nicer place for this stuff? It's here to avoid dozens of linking errors in UnitTest.. +extern std::vector dpadKeys; extern std::vector confirmKeys; extern std::vector cancelKeys; extern std::vector tabLeftKeys; extern std::vector tabRightKeys; +void SetDPadKeys(const std::vector &leftKey, const std::vector &rightKey, + const std::vector &upKey, const std::vector &downKey); void SetConfirmCancelKeys(const std::vector &confirm, const std::vector &cancel); void SetTabLeftRightKeys(const std::vector &tabLeft, const std::vector &tabRight); diff --git a/ui/view.cpp b/ui/view.cpp index 4cf70c2521..9647bdeaff 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -222,6 +222,14 @@ void Clickable::Touch(const TouchInput &input) { // TODO: O/X confirm preference for xperia play? +bool IsDPadKey(const KeyInput &key) { + if (dpadKeys.empty()) { + return key.keyCode >= NKCODE_DPAD_UP && key.keyCode <= NKCODE_DPAD_RIGHT; + } else { + return std::find(dpadKeys.begin(), dpadKeys.end(), KeyDef(key.deviceId, key.keyCode)) != dpadKeys.end(); + } +} + bool IsAcceptKey(const KeyInput &key) { if (confirmKeys.empty()) { if (key.deviceId == DEVICE_ID_KEYBOARD) { diff --git a/ui/view.h b/ui/view.h index b031b39bb3..bd7f25e2e4 100644 --- a/ui/view.h +++ b/ui/view.h @@ -801,6 +801,7 @@ void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measure void EventTriggered(Event *e, EventParams params); void DispatchEvents(); +bool IsDPadKey(const KeyInput &key); bool IsAcceptKey(const KeyInput &key); bool IsEscapeKey(const KeyInput &key); bool IsTabLeftKey(const KeyInput &key); diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 6f080a2c97..60b75dc968 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1192,8 +1192,7 @@ bool KeyEvent(const KeyInput &key, ViewGroup *root) { bool retval = false; // Ignore repeats for focus moves. if ((key.flags & (KEY_DOWN | KEY_IS_REPEAT)) == KEY_DOWN) { - // We ignore the device ID here. Anything with a DPAD is OK. - if (key.keyCode >= NKCODE_DPAD_UP && key.keyCode <= NKCODE_DPAD_RIGHT) { + if (IsDPadKey(key)) { // Let's only repeat DPAD initially. HeldKey hk; hk.key = key.keyCode; @@ -1213,14 +1212,16 @@ bool KeyEvent(const KeyInput &key, ViewGroup *root) { } } if (key.flags & KEY_UP) { - // We ignore the device ID here. Anything with a DPAD is OK. - if (key.keyCode >= NKCODE_DPAD_UP && key.keyCode <= NKCODE_DPAD_RIGHT) { + // We ignore the device ID here (in the comparator for HeldKey), due to the Ouya quirk mentioned above. + if (!heldKeys.empty()) { HeldKey hk; hk.key = key.keyCode; hk.deviceId = key.deviceId; hk.triggerTime = 0.0; // irrelevant - heldKeys.erase(hk); - retval = true; + if (heldKeys.find(hk) != heldKeys.end()) { + heldKeys.erase(hk); + retval = true; + } } } From 5f2f9160f8e95b8f7b63e31bb8ce285aa4f0a8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20H=C3=B6glund?= Date: Sat, 29 Aug 2015 21:52:53 +0200 Subject: [PATCH 1425/1445] Introduce DEVICE_ID_ANY, update operator == for KeyDef to match --- input/input_state.cpp | 1 + input/input_state.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/input/input_state.cpp b/input/input_state.cpp index 9cf5315733..c6923d338e 100644 --- a/input/input_state.cpp +++ b/input/input_state.cpp @@ -4,6 +4,7 @@ const char *GetDeviceName(int deviceId) { switch (deviceId) { + case DEVICE_ID_ANY: return "any"; case DEVICE_ID_DEFAULT: return "built-in"; case DEVICE_ID_KEYBOARD: return "kbd"; case DEVICE_ID_PAD_0: return "pad1"; diff --git a/input/input_state.h b/input/input_state.h index e839053a59..bf4cd7b5b5 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -19,6 +19,7 @@ // Default device IDs enum { + DEVICE_ID_ANY = -1, // Represents any device ID DEVICE_ID_DEFAULT = 0, // Old Android DEVICE_ID_KEYBOARD = 1, // PC keyboard, android keyboards DEVICE_ID_MOUSE = 2, // PC mouse only (not touchscreen!) @@ -94,7 +95,7 @@ public: return false; } bool operator == (const KeyDef &other) const { - if (deviceId != other.deviceId) return false; + if (deviceId != other.deviceId && deviceId != DEVICE_ID_ANY && other.deviceId != DEVICE_ID_ANY) return false; if (keyCode != other.keyCode) return false; return true; } From 96a08b33937082769bc69739cfe9cb78a0eebb34 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 30 Aug 2015 12:58:06 +0200 Subject: [PATCH 1426/1445] Quick workaround for rendering bug caused by layout bugs.. --- ui/view.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ui/view.cpp b/ui/view.cpp index 7a38d9acf1..4b2df42b4c 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -617,6 +617,11 @@ void TextView::Draw(UIContext &dc) { bool clip = false; if (w > bounds_.w || h > bounds_.h) clip = true; + if (bounds_.w < 0 || bounds_.h < 0) { + // We have a layout but, but try not to screw up rendering. + // TODO: Fix properly. + clip = false; + } if (clip) { Bounds clipRect = bounds_.Expand(10); // TODO: Remove this hackery dc.Flush(); From 356d35e58b4edba8283e0f54168aa42afc197d5e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 30 Aug 2015 15:07:49 +0200 Subject: [PATCH 1427/1445] Some warning fixes --- base/compat.cpp | 2 +- file/chunk_file.cpp | 6 +++--- file/easy_file.cpp | 3 +-- math/lin/aabb.cpp | 24 ++++++++++++------------ 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/base/compat.cpp b/base/compat.cpp index 0368a39d4a..cef9d6c008 100644 --- a/base/compat.cpp +++ b/base/compat.cpp @@ -3,7 +3,7 @@ #include "base/compat.h" -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 1900 static int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) { int count = -1; diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index e65bc6891e..d1b6d5bae0 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -55,14 +55,14 @@ ChunkFile::~ChunkFile() { } int ChunkFile::readInt() { - if (posfabs(delta.x)) + if (fabsf(delta.y) > fabsf(delta.x)) { - if (fabs(delta.z)>fabs(delta.y)) + if (fabsf(delta.z) > fabsf(delta.y)) return 2; else return 1; } else { - if (fabs(delta.z)>fabs(delta.x)) + if (fabsf(delta.z) > fabsf(delta.x)) return 2; else return 0; @@ -210,21 +210,21 @@ bool AABB::IntersectsTriangle(const Vec3& a_V0, const Vec3& a_V1, const Vec3& a_ v1 = a_V1 - a_BoxCentre; v2 = a_V2 - a_BoxCentre; e0 = v1 - v0, e1 = v2 - v1, e2 = v0 - v2; - fex = fabs(e0[0]); - fey = fabs(e0[1]); - fez = fabs(e0[2]); + fex = fabsf(e0[0]); + fey = fabsf(e0[1]); + fez = fabsf(e0[2]); AXISTEST_X01( e0[2], e0[1], fez, fey ); AXISTEST_Y02( e0[2], e0[0], fez, fex ); AXISTEST_Z12( e0[1], e0[0], fey, fex ); - fex = fabs(e1[0]); - fey = fabs(e1[1]); - fez = fabs(e1[2]); + fex = fabsf(e1[0]); + fey = fabsf(e1[1]); + fez = fabsf(e1[2]); AXISTEST_X01( e1[2], e1[1], fez, fey ); AXISTEST_Y02( e1[2], e1[0], fez, fex ); AXISTEST_Z0 ( e1[1], e1[0], fey, fex ); - fex = fabs(e2[0]); - fey = fabs(e2[1]); - fez = fabs(e2[2]); + fex = fabsf(e2[0]); + fey = fabsf(e2[1]); + fez = fabsf(e2[2]); AXISTEST_X2 ( e2[2], e2[1], fez, fey ); AXISTEST_Y1 ( e2[2], e2[0], fez, fex ); AXISTEST_Z12( e2[1], e2[0], fey, fex ); From 2509451280b274b4dbdea0e5310c0dfae8c43eef Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 30 Aug 2015 15:08:57 +0200 Subject: [PATCH 1428/1445] Upgrade project file to VS 2015 --- native.vcxproj | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/native.vcxproj b/native.vcxproj index 523c79ecef..32e5ec9428 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,33 +22,34 @@ {C4DF647E-80EA-4111-A0A8-218B1B711E18} Win32Proj native + 8.1 StaticLibrary true Unicode - v120_xp + v140_xp StaticLibrary true Unicode - v120 + v140_xp StaticLibrary false false Unicode - v120_xp + v140_xp StaticLibrary false false Unicode - v120_xp + v140_xp From da38466d29a8db045ad56d1fe00601bf43b88d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 31 Aug 2015 23:26:34 +0200 Subject: [PATCH 1429/1445] Minor logging cleanup on non-android unix --- base/logging.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/logging.h b/base/logging.h index 4bdba4aaa4..c96a5905a8 100644 --- a/base/logging.h +++ b/base/logging.h @@ -124,10 +124,10 @@ inline const char *removePath(const char *str) { #else #define DLOG(...) #endif -#define ILOG(...) {printf("I: %s:%i: ", removePath(__FILE__), __LINE__); printf("I: " __VA_ARGS__); printf("\n");} -#define WLOG(...) {printf("W: %s:%i: ", removePath(__FILE__), __LINE__); printf("W: " __VA_ARGS__); printf("\n");} -#define ELOG(...) {printf("E: %s:%i: ", removePath(__FILE__), __LINE__); printf("E: " __VA_ARGS__); printf("\n");} -#define FLOG(...) {printf("F: %s:%i: ", removePath(__FILE__), __LINE__); printf("F: " __VA_ARGS__); printf("\n"); Crash();} +#define ILOG(...) {printf("I: %s:%i: ", removePath(__FILE__), __LINE__); printf(__VA_ARGS__); printf("\n");} +#define WLOG(...) {printf("W: %s:%i: ", removePath(__FILE__), __LINE__); printf(__VA_ARGS__); printf("\n");} +#define ELOG(...) {printf("E: %s:%i: ", removePath(__FILE__), __LINE__); printf(__VA_ARGS__); printf("\n");} +#define FLOG(...) {printf("F: %s:%i: ", removePath(__FILE__), __LINE__); printf(__VA_ARGS__); printf("\n"); Crash();} #endif #endif From 3b3461e7ab864738a2cd46b809e9f47388f95af9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 5 Sep 2015 19:57:52 +0200 Subject: [PATCH 1430/1445] Start moving compatibility decisions out of native --- gfx_es2/gl_state.cpp | 8 +------- gfx_es2/gpu_features.h | 4 +--- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 8923d50ac5..d84ce40ed6 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -258,6 +258,7 @@ void CheckGLExtensions() { gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; + gl_extensions.EXT_blend_func_extended = strstr(extString, "GL_EXT_blend_func_extended") != 0; gl_extensions.ARB_conservative_depth = strstr(extString, "GL_ARB_conservative_depth") != 0; gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0; @@ -280,15 +281,8 @@ void CheckGLExtensions() { gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0; - gl_extensions.ANY_shader_framebuffer_fetch = gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.NV_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; - // Framebuffer fetch appears to be buggy at least on Tegra 3 devices. So we blacklist it. - // Tales of Destiny 2 has been reported to display green. - if (gl_extensions.ANY_shader_framebuffer_fetch && strstr(renderer, "NVIDIA Tegra 3") != 0) { - gl_extensions.ANY_shader_framebuffer_fetch = false; - } - #if defined(ANDROID) || defined(BLACKBERRY) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. // https://twitter.com/ID_AA_Carmack/status/387383037794603008 diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index d4207970c8..d17942589f 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -48,6 +48,7 @@ struct GLExtensions { bool FBO_ARB; bool PBO_ARB; bool ARB_blend_func_extended; // dual source blending + bool EXT_blend_func_extended; // dual source blending (GLES, new 2015) bool ARB_shader_image_load_store; bool ARB_conservative_depth; @@ -76,9 +77,6 @@ struct GLExtensions { bool EGL_NV_system_time; bool EGL_NV_coverage_sample; - // Convenience (in case we need to know which, but can treat them mostly the same.) - bool ANY_shader_framebuffer_fetch; - // Bugs int bugs; From 2b24f76d34437941d3d6444c39e190d3c3fe979f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 5 Sep 2015 22:08:46 +0200 Subject: [PATCH 1431/1445] Fix some naming, remove NV_draw_texture, move decisions out --- gfx/texture.cpp | 10 +++++----- gfx_es2/fbo.cpp | 10 +++++----- gfx_es2/gl_state.cpp | 29 +++++++---------------------- gfx_es2/gpu_features.h | 9 ++++----- 4 files changed, 21 insertions(+), 37 deletions(-) diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 6cc617a241..168a55adea 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -157,7 +157,7 @@ bool Texture::LoadPNG(const char *filename, bool genMips) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); if (genMips) { - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { glGenerateMipmap(GL_TEXTURE_2D); } else { #ifndef USING_GLES2 @@ -188,7 +188,7 @@ bool Texture::LoadJPEG(const char *filename, bool genMips) { SetTextureParameters(genMips ? ZIM_GEN_MIPS : ZIM_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); if (genMips) { - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { glGenerateMipmap(GL_TEXTURE_2D); } else { #ifndef USING_GLES2 @@ -213,7 +213,7 @@ bool Texture::LoadPNG(const uint8_t *data, size_t size, bool genMips) { SetTextureParameters(genMips ? ZIM_GEN_MIPS : ZIM_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); if (genMips) { - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { glGenerateMipmap(GL_TEXTURE_2D); } else { #ifndef USING_GLES2 @@ -243,7 +243,7 @@ bool Texture::LoadXOR() { SetTextureParameters(ZIM_GEN_MIPS); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); - if(gl_extensions.FBO_ARB){ + if(gl_extensions.ARB_framebuffer_object){ glGenerateMipmap(GL_TEXTURE_2D); }else{ #ifndef USING_GLES2 @@ -342,7 +342,7 @@ bool Texture::LoadZIM(const char *filename) { colors, data_type, image_data[l]); } if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) { - if(gl_extensions.FBO_ARB) { + if(gl_extensions.ARB_framebuffer_object) { glGenerateMipmap(GL_TEXTURE_2D); }else{ #ifndef USING_GLES2 diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 35cd3c0ee8..e1809dc6cf 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -133,7 +133,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F CheckGLExtensions(); #ifndef USING_GLES2 - if(!gl_extensions.FBO_ARB) + if(!gl_extensions.ARB_framebuffer_object) return fbo_ext_create(width, height, num_color_textures, z_stencil, colorDepth); #endif @@ -269,7 +269,7 @@ FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo) } static GLenum fbo_get_fb_target(bool read, GLuint **cached) { - bool supportsBlit = gl_extensions.FBO_ARB; + bool supportsBlit = gl_extensions.ARB_framebuffer_object; if (gl_extensions.IsGLES) { supportsBlit = supportsBlit && (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); } @@ -294,7 +294,7 @@ static void fbo_bind_fb_target(bool read, GLuint name) { GLenum target = fbo_get_fb_target(read, &cached); if (*cached != name) { - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { glBindFramebuffer(target, name); } else { #ifndef USING_GLES2 @@ -312,7 +312,7 @@ void fbo_unbind() { } CheckGLExtensions(); - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { glBindFramebuffer(GL_FRAMEBUFFER, 0); } else { #ifndef USING_GLES2 @@ -364,7 +364,7 @@ void fbo_destroy(FBO *fbo) { return; } - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index d84ce40ed6..23c65e8418 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -256,7 +256,6 @@ void CheckGLExtensions() { gl_extensions.OES_texture_npot = strstr(extString, "GL_ARB_texture_non_power_of_two") != 0 && !(((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0))); - gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; gl_extensions.EXT_blend_func_extended = strstr(extString, "GL_EXT_blend_func_extended") != 0; gl_extensions.ARB_conservative_depth = strstr(extString, "GL_ARB_conservative_depth") != 0; @@ -264,11 +263,6 @@ void CheckGLExtensions() { gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0; gl_extensions.EXT_gpu_shader4 = strstr(extString, "GL_EXT_gpu_shader4") != 0; gl_extensions.NV_framebuffer_blit = strstr(extString, "GL_NV_framebuffer_blit") != 0; - if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) { - // Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable - // Also on Intel, see https://github.com/hrydgard/ppsspp/issues/4867 - gl_extensions.ARB_blend_func_extended = false; - } if (gl_extensions.IsGLES) { gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0; @@ -292,10 +286,6 @@ void CheckGLExtensions() { DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2); #endif - if (gl_extensions.NV_draw_texture) { - glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)eglGetProcAddress("glDrawTextureNV"); - } - if (gl_extensions.NV_copy_image) { glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV"); } @@ -356,6 +346,7 @@ void CheckGLExtensions() { } #endif + // This is probably a waste of time, implementations lie. if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility")) { const GLint precisions[6] = { GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT, @@ -372,19 +363,13 @@ void CheckGLExtensions() { } if (gl_extensions.IsGLES) { - gl_extensions.FBO_ARB = true; - gl_extensions.FBO_EXT = false; + gl_extensions.ARB_framebuffer_object = true; // TODO: This is a lie! ES2 just has a subset. + gl_extensions.EXT_framebuffer_object = false; } else { - gl_extensions.FBO_ARB = false; - gl_extensions.FBO_EXT = false; - gl_extensions.PBO_ARB = true; - gl_extensions.PBO_NV = true; - if (strlen(extString) != 0) { - gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; - gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; - gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; - gl_extensions.PBO_NV = strstr(extString, "GL_NV_pixel_buffer_object") != 0; - } + gl_extensions.ARB_framebuffer_object = strstr(extString, "GL_ARB_framebuffer_object") != 0; + gl_extensions.EXT_framebuffer_object = strstr(extString, "GL_EXT_framebuffer_object") != 0; + gl_extensions.ARB_pixel_buffer_object = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; + gl_extensions.NV_pixel_buffer_object = strstr(extString, "GL_NV_pixel_buffer_object") != 0; } ProcessGPUFeatures(); diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index d17942589f..a8d7031869 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -45,8 +45,8 @@ struct GLExtensions { bool OES_vertex_array_object; // ARB - bool FBO_ARB; - bool PBO_ARB; + bool ARB_framebuffer_object; + bool ARB_pixel_buffer_object; bool ARB_blend_func_extended; // dual source blending bool EXT_blend_func_extended; // dual source blending (GLES, new 2015) bool ARB_shader_image_load_store; @@ -60,15 +60,14 @@ struct GLExtensions { bool EXT_shader_framebuffer_fetch; bool EXT_gpu_shader4; bool EXT_blend_minmax; - bool FBO_EXT; + bool EXT_framebuffer_object; bool PBO_EXT; // NV bool NV_shader_framebuffer_fetch; - bool NV_draw_texture; bool NV_copy_image; bool NV_framebuffer_blit; - bool PBO_NV; // GL_NV_pixel_buffer_object + bool NV_pixel_buffer_object; // GL_NV_pixel_buffer_object // ARM bool ARM_shader_framebuffer_fetch; From 6934d31090a25d44b23a05b6eaa7576cc4a4f4b9 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 5 Sep 2015 22:40:11 +0200 Subject: [PATCH 1432/1445] ARB_framebuffer_object no longer lies --- gfx_es2/fbo.cpp | 33 ++++++++++++++++++++++++++++----- gfx_es2/fbo.h | 1 + gfx_es2/gl_state.cpp | 13 ++++--------- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index e1809dc6cf..9a277fab5d 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -129,12 +129,32 @@ FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stenci } #endif +int fbo_check_framebuffer_status(FBO *fbo) { + GLenum fbStatus; +#ifndef USING_GLES2 + if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) { + fbStatus = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER); + } else if (gl_extensions.ARB_framebuffer_object) { + fbStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); + } else { + fbStatus = 0; + } +#else + fbStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); +#endif + return (int)fbStatus; +} + FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { CheckGLExtensions(); #ifndef USING_GLES2 - if(!gl_extensions.ARB_framebuffer_object) + if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) { return fbo_ext_create(width, height, num_color_textures, z_stencil, colorDepth); + } else if (!gl_extensions.ARB_framebuffer_object) { + return nullptr; + } + // If GLES2, we have basic FBO support and can just proceed. #endif FBO *fbo = new FBO(); @@ -312,13 +332,16 @@ void fbo_unbind() { } CheckGLExtensions(); +#ifndef USING_GLES2 if (gl_extensions.ARB_framebuffer_object) { glBindFramebuffer(GL_FRAMEBUFFER, 0); - } else { -#ifndef USING_GLES2 + } else if (gl_extensions.EXT_framebuffer_object) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); -#endif } +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + #ifdef IOS bindDefaultFBO(); #endif @@ -373,7 +396,7 @@ void fbo_destroy(FBO *fbo) { glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); glDeleteRenderbuffers(1, &fbo->z_buffer); glDeleteRenderbuffers(1, &fbo->stencil_buffer); - } else { + } else if (gl_extensions.EXT_framebuffer_object) { #ifndef USING_GLES2 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index 9fd9426171..52c3daf5a6 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -29,6 +29,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F // Create an opaque FBO from a native GL FBO, optionally reusing an existing FBO structure. // Useful for overriding the backbuffer FBO that is generated outside of this wrapper. FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo = NULL); +int fbo_check_framebuffer_status(FBO *fbo); // These functions should be self explanatory. void fbo_bind_as_render_target(FBO *fbo); diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 23c65e8418..d91472c6a1 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -362,15 +362,10 @@ void CheckGLExtensions() { } } - if (gl_extensions.IsGLES) { - gl_extensions.ARB_framebuffer_object = true; // TODO: This is a lie! ES2 just has a subset. - gl_extensions.EXT_framebuffer_object = false; - } else { - gl_extensions.ARB_framebuffer_object = strstr(extString, "GL_ARB_framebuffer_object") != 0; - gl_extensions.EXT_framebuffer_object = strstr(extString, "GL_EXT_framebuffer_object") != 0; - gl_extensions.ARB_pixel_buffer_object = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; - gl_extensions.NV_pixel_buffer_object = strstr(extString, "GL_NV_pixel_buffer_object") != 0; - } + gl_extensions.ARB_framebuffer_object = strstr(extString, "GL_ARB_framebuffer_object") != 0; + gl_extensions.EXT_framebuffer_object = strstr(extString, "GL_EXT_framebuffer_object") != 0; + gl_extensions.ARB_pixel_buffer_object = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; + gl_extensions.NV_pixel_buffer_object = strstr(extString, "GL_NV_pixel_buffer_object") != 0; ProcessGPUFeatures(); From 67e22c29c2823c4f182e99920adff32ba88c1069 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 5 Sep 2015 23:08:36 +0200 Subject: [PATCH 1433/1445] Add another GPU bug flag --- gfx_es2/gpu_features.cpp | 1 + gfx_es2/gpu_features.h | 1 + 2 files changed, 2 insertions(+) diff --git a/gfx_es2/gpu_features.cpp b/gfx_es2/gpu_features.cpp index f230b7c96d..57ff968a38 100644 --- a/gfx_es2/gpu_features.cpp +++ b/gfx_es2/gpu_features.cpp @@ -34,5 +34,6 @@ void ProcessGPUFeatures() { WLOG("GL DRIVER BUG: PVR with bad precision"); gl_extensions.bugs |= BUG_PVR_SHADER_PRECISION_BAD; } + gl_extensions.bugs |= BUG_PVR_GENMIPMAP_HEIGHT_GREATER; } } diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index a8d7031869..5baa67ecd5 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -21,6 +21,7 @@ enum { BUG_FBO_UNUSABLE = 1, BUG_PVR_SHADER_PRECISION_BAD = 2, BUG_PVR_SHADER_PRECISION_TERRIBLE = 4, + BUG_PVR_GENMIPMAP_HEIGHT_GREATER = 8, }; // Extensions to look at using: From 6566949ab5e52df54e4027201c07a826160a7f23 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 5 Sep 2015 23:33:38 +0200 Subject: [PATCH 1434/1445] Centralize some gles shims --- gfx_es2/fbo.cpp | 19 ------------------- gfx_es2/gl_state.h | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 9a277fab5d..0d96f18cdd 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -6,25 +6,6 @@ #include "gfx/gl_common.h" #include "gfx_es2/gl_state.h" -#if defined(USING_GLES2) && !defined(BLACKBERRY) - -#ifndef GL_READ_FRAMEBUFFER -// Careful - our ES3 header defines these. Means that we must make sure -// to only use them if ES3 support is detected to be available and otherwise -// use GL_FRAMEBUFFER only. -#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER -#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER -#endif - -#ifndef GL_DEPTH_COMPONENT24 -#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES -#endif -#endif - -#ifndef GL_DEPTH24_STENCIL8_OES -#define GL_DEPTH24_STENCIL8_OES 0x88F0 -#endif - #ifdef IOS extern void bindDefaultFBO(); #endif diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index fa38e6b822..a1fccfaa55 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -57,8 +57,25 @@ extern PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; #define glDeleteVertexArrays glDeleteVertexArraysOES #define glIsVertexArray glIsVertexArrayOES +#if !defined(BLACKBERRY) +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER +#endif +#ifndef GL_DEPTH_COMPONENT24 +#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES +#endif +#endif + +#ifndef GL_RGBA8 +#define GL_RGBA8 GL_RGBA +#endif + #endif /* EGL_NV_system_time */ +#ifndef GL_DEPTH24_STENCIL8_OES +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif // OpenGL state cache. Should convert all code to use this instead of directly calling glEnable etc, // as GL state changes can be expensive on some hardware. From 5ff1d91323aadb723f6d039cd3ebef32c3851e24 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 Sep 2015 12:22:02 +0200 Subject: [PATCH 1435/1445] Add file to project that was missing --- native.vcxproj | 1 + native.vcxproj.filters | 1 + 2 files changed, 2 insertions(+) diff --git a/native.vcxproj b/native.vcxproj index 523c79ecef..21d7da8783 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -240,6 +240,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index abb54be747..4936477b81 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -360,6 +360,7 @@ thread + From e875f0a0c3932fb7b80846e78c318fa36b2b5c6f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 Sep 2015 12:40:40 +0200 Subject: [PATCH 1436/1445] Some FBO checks got broken when we stopped lying. --- gfx_es2/fbo.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 0d96f18cdd..c046b98650 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -272,7 +272,7 @@ FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo) static GLenum fbo_get_fb_target(bool read, GLuint **cached) { bool supportsBlit = gl_extensions.ARB_framebuffer_object; if (gl_extensions.IsGLES) { - supportsBlit = supportsBlit && (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); + supportsBlit = (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); } // Note: GL_FRAMEBUFFER_EXT and GL_FRAMEBUFFER have the same value, same with _NV. @@ -295,7 +295,7 @@ static void fbo_bind_fb_target(bool read, GLuint name) { GLenum target = fbo_get_fb_target(read, &cached); if (*cached != name) { - if (gl_extensions.ARB_framebuffer_object) { + if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { glBindFramebuffer(target, name); } else { #ifndef USING_GLES2 @@ -314,7 +314,7 @@ void fbo_unbind() { CheckGLExtensions(); #ifndef USING_GLES2 - if (gl_extensions.ARB_framebuffer_object) { + if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { glBindFramebuffer(GL_FRAMEBUFFER, 0); } else if (gl_extensions.EXT_framebuffer_object) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); @@ -368,7 +368,7 @@ void fbo_destroy(FBO *fbo) { return; } - if (gl_extensions.ARB_framebuffer_object) { + if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); From 3f05c8d99031931149a072c64cae51eb5635202b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 Sep 2015 12:21:15 +0200 Subject: [PATCH 1437/1445] Remove usage of glstate. It will be moved into PPSSPP, and only used in PSP rendering. --- android/app-android.cpp | 6 +-- base/PCMain.cpp | 2 +- base/timeutil.cpp | 3 +- gfx/gl_common.h | 71 +++++++++++++++++++++++++++ gfx/texture.cpp | 2 +- gfx_es2/draw_buffer.cpp | 7 ++- gfx_es2/draw_text.h | 3 -- gfx_es2/fbo.cpp | 2 + gfx_es2/gl_state.cpp | 10 +--- gfx_es2/gl_state.h | 103 +++++----------------------------------- gfx_es2/gpu_features.h | 5 +- thin3d/thin3d_gl.cpp | 70 ++++++++++++++++----------- ui/ui_context.cpp | 2 - 13 files changed, 142 insertions(+), 144 deletions(-) diff --git a/android/app-android.cpp b/android/app-android.cpp index 581517107f..5e5cd79d10 100644 --- a/android/app-android.cpp +++ b/android/app-android.cpp @@ -26,7 +26,7 @@ #include "math/math_util.h" #include "net/resolve.h" #include "android/native_audio.h" -#include "gfx_es2/gl_state.h" +#include "gfx/gl_common.h" #include "app-android.h" @@ -364,8 +364,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN } else { ELOG("BAD: Ended up in nativeRender even though app has quit.%s", ""); // Shouldn't really get here. Let's draw magenta. - glstate.depthWrite.set(GL_TRUE); - glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_TRUE); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearColor(1.0, 0.0, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 1a6a194a1f..b5b4876176 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -29,7 +29,7 @@ SDLJoystick *joystick = NULL; #include "base/display.h" #include "base/logging.h" #include "base/timeutil.h" -#include "gfx_es2/gl_state.h" +#include "gfx_es2/gpu_features.h" #include "input/input_state.h" #include "input/keycodes.h" #include "net/resolve.h" diff --git a/base/timeutil.cpp b/base/timeutil.cpp index a79dfce891..86ab3b7edf 100644 --- a/base/timeutil.cpp +++ b/base/timeutil.cpp @@ -3,7 +3,8 @@ #include "base/timeutil.h" // For NV time functions. Ugly! -#include "gfx_es2/gl_state.h" +#include "gfx/gl_common.h" +#include "gfx_es2/gpu_features.h" #ifdef _WIN32 #include diff --git a/gfx/gl_common.h b/gfx/gl_common.h index ca030a6949..c6690c16e5 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -25,3 +25,74 @@ typedef char GLchar; #include "../gfx_es2/gl3stub.h" #endif + +#ifdef USING_GLES2 + +#ifndef GL_MIN_EXT +#define GL_MIN_EXT 0x8007 +#endif + +#ifndef GL_MAX_EXT +#define GL_MAX_EXT 0x8008 +#endif + +#if defined(ANDROID) || defined(BLACKBERRY) +#include +// Additional extensions not included in GLES2/gl2ext.h from the NDK + +typedef uint64_t EGLuint64NV; +typedef EGLuint64NV(EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); +typedef EGLuint64NV(EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); +extern PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; +extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; + +typedef GLvoid* (GL_APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +extern PFNGLMAPBUFFERPROC glMapBuffer; + +typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); +extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV; +typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum + srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, + GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei + width, GLsizei height, GLsizei depth); +extern PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV; +#ifndef ARM64 +typedef void (EGLAPIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) ( + GLint srcX0, GLint srcY0, GLint srcX1, GLuint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLuint dstY1, + GLint mask, GLenum filter); +#endif +extern PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV; + +extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; +extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; +extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; +extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES; +extern PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; +#endif + +// Rename standard functions to the OES version. +#define glGenVertexArrays glGenVertexArraysOES +#define glBindVertexArray glBindVertexArrayOES +#define glDeleteVertexArrays glDeleteVertexArraysOES +#define glIsVertexArray glIsVertexArrayOES + +#if !defined(BLACKBERRY) +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER +#endif +#ifndef GL_DEPTH_COMPONENT24 +#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES +#endif +#endif + +#ifndef GL_RGBA8 +#define GL_RGBA8 GL_RGBA +#endif + +#endif /* EGL_NV_system_time */ + +#ifndef GL_DEPTH24_STENCIL8_OES +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 168a55adea..62ef3860c8 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -12,7 +12,7 @@ #include "gfx/gl_debug_log.h" #include "gfx/gl_lost_manager.h" #include "gfx/gl_common.h" -#include "gfx_es2/gl_state.h" +#include "gfx_es2/gpu_features.h" Texture::Texture() : id_(0) { CheckGLExtensions(); diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 34abaaf536..c1bd2f166d 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -6,13 +6,12 @@ #include "base/display.h" #include "base/logging.h" #include "math/math_util.h" -#include "gfx_es2/draw_buffer.h" -#include "gfx_es2/draw_text.h" -#include "gfx_es2/glsl_program.h" -#include "gfx_es2/gl_state.h" #include "gfx/texture_atlas.h" #include "gfx/gl_debug_log.h" #include "gfx/gl_common.h" +#include "gfx_es2/draw_buffer.h" +#include "gfx_es2/draw_text.h" +#include "gfx_es2/glsl_program.h" #include "util/text/utf8.h" enum { diff --git a/gfx_es2/draw_text.h b/gfx_es2/draw_text.h index bd1f1d8248..58caab3a09 100644 --- a/gfx_es2/draw_text.h +++ b/gfx_es2/draw_text.h @@ -12,9 +12,6 @@ #include "base/basictypes.h" #include "gfx_es2/draw_buffer.h" -#if !(defined(_WIN32) && !defined(USING_QT_UI)) -#include "gfx_es2/gl_state.h" -#endif class Thin3DContext; class Thin3DTexture; diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index c046b98650..001d77e9ff 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -4,6 +4,8 @@ #include "gfx/gl_common.h" #include "gfx_es2/fbo.h" #include "gfx/gl_common.h" + +// TODO: Remove, after moving fbo.cpp into PPSSPP #include "gfx_es2/gl_state.h" #ifdef IOS diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index d91472c6a1..ca4b614148 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -3,7 +3,7 @@ #include "base/logging.h" #include "base/stringutil.h" #include "base/NativeApp.h" -#include "gl_state.h" +#include "gfx_es2/gl_state.h" #ifdef _WIN32 #include "GL/wglew.h" @@ -36,14 +36,6 @@ std::string g_all_egl_extensions; int OpenGLState::state_count = 0; -void OpenGLState::Initialize() { - if (initialized) - return; - initialized = true; - - Restore(); -} - void OpenGLState::Restore() { int count = 0; diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index a1fccfaa55..874c309045 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -3,82 +3,12 @@ #include #include #include + #include "gfx/gl_common.h" #include "gfx_es2/gpu_features.h" -#ifdef USING_GLES2 - -#ifndef GL_MIN_EXT -#define GL_MIN_EXT 0x8007 -#endif - -#ifndef GL_MAX_EXT -#define GL_MAX_EXT 0x8008 -#endif - -#if defined(ANDROID) || defined(BLACKBERRY) -#include -// Additional extensions not included in GLES2/gl2ext.h from the NDK - -typedef uint64_t EGLuint64NV; -typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); -typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); -extern PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; -extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; - -typedef GLvoid* (GL_APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); -extern PFNGLMAPBUFFERPROC glMapBuffer; - -typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); -extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV; -typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum - srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, - GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei - width, GLsizei height, GLsizei depth); -extern PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV; -#ifndef ARM64 -typedef void (EGLAPIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) ( - GLint srcX0, GLint srcY0, GLint srcX1, GLuint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLuint dstY1, - GLint mask, GLenum filter); -#endif -extern PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV; - -extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; -extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; -extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; -extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES; -extern PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; -#endif - -// Rename standard functions to the OES version. -#define glGenVertexArrays glGenVertexArraysOES -#define glBindVertexArray glBindVertexArrayOES -#define glDeleteVertexArrays glDeleteVertexArraysOES -#define glIsVertexArray glIsVertexArrayOES - -#if !defined(BLACKBERRY) -#ifndef GL_READ_FRAMEBUFFER -#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER -#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER -#endif -#ifndef GL_DEPTH_COMPONENT24 -#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES -#endif -#endif - -#ifndef GL_RGBA8 -#define GL_RGBA8 GL_RGBA -#endif - -#endif /* EGL_NV_system_time */ - -#ifndef GL_DEPTH24_STENCIL8_OES -#define GL_DEPTH24_STENCIL8_OES 0x88F0 -#endif - -// OpenGL state cache. Should convert all code to use this instead of directly calling glEnable etc, -// as GL state changes can be expensive on some hardware. +// OpenGL state cache. +// Probably only really worth it in rendering cores on weak mobile hardware. class OpenGLState { private: template @@ -91,11 +21,11 @@ private: } inline void set(bool value) { - if(value && value != _value) { + if (value && value != _value) { _value = value; glEnable(cap); } - if(!value && value != _value) { + if (!value && value != _value) { _value = value; glDisable(cap); } @@ -113,7 +43,7 @@ private: return _value; } void restore() { - if(_value) + if (_value) glEnable(cap); else glDisable(cap); @@ -128,7 +58,7 @@ private: OpenGLState::state_count++; \ } \ void set(p1type newp1) { \ - if(newp1 != p1) { \ + if (newp1 != p1) { \ p1 = newp1; \ func(p1); \ } \ @@ -147,7 +77,7 @@ private: OpenGLState::state_count++; \ } \ inline void set(p1type newp1, p2type newp2) { \ - if(newp1 != p1 || newp2 != p2) { \ + if (newp1 != p1 || newp2 != p2) { \ p1 = newp1; \ p2 = newp2; \ func(p1, p2); \ @@ -168,7 +98,7 @@ private: OpenGLState::state_count++; \ } \ inline void set(p1type newp1, p2type newp2, p3type newp3) { \ - if(newp1 != p1 || newp2 != p2 || newp3 != p3) { \ + if (newp1 != p1 || newp2 != p2 || newp3 != p3) { \ p1 = newp1; \ p2 = newp2; \ p3 = newp3; \ @@ -191,7 +121,7 @@ private: OpenGLState::state_count++; \ } \ inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \ - if(newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \ + if (newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \ p1 = newp1; \ p2 = newp2; \ p3 = newp3; \ @@ -213,7 +143,7 @@ private: OpenGLState::state_count++; \ } \ inline void set(const float v[4]) { \ - if(memcmp(p,v,sizeof(float)*4)) { \ + if (memcmp(p,v,sizeof(float)*4)) { \ memcpy(p,v,sizeof(float)*4); \ func(p[0], p[1], p[2], p[3]); \ } \ @@ -245,12 +175,9 @@ private: } \ } - bool initialized; - public: static int state_count; - OpenGLState() : initialized(false) {} - void Initialize(); + OpenGLState() {} void Restore(); // When adding a state here, don't forget to add it to OpenGLState::Restore() too @@ -314,9 +241,3 @@ public: #undef STATE2 extern OpenGLState glstate; - - -extern std::string g_all_gl_extensions; -extern std::string g_all_egl_extensions; - -void CheckGLExtensions(); diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index 5baa67ecd5..3b11cddc3a 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -90,8 +90,11 @@ struct GLExtensions { extern GLExtensions gl_extensions; - // Call this after filling out vendor etc to lookup the bugs etc. // Only needs to be called once. Currently called by CheckGLExtensions(). void ProcessGPUFeatures(); +extern std::string g_all_gl_extensions; +extern std::string g_all_egl_extensions; + +void CheckGLExtensions(); diff --git a/thin3d/thin3d_gl.cpp b/thin3d/thin3d_gl.cpp index b224a06aa5..8adb4d8582 100644 --- a/thin3d/thin3d_gl.cpp +++ b/thin3d/thin3d_gl.cpp @@ -7,7 +7,8 @@ #include "image/zim_load.h" #include "math/lin/matrix4x4.h" #include "thin3d/thin3d.h" -#include "gfx_es2/gl_state.h" +#include "gfx/gl_common.h" +#include "gfx_es2/gpu_features.h" #include "gfx/gl_lost_manager.h" static const unsigned short compToGL[] = { @@ -91,20 +92,25 @@ public: // uint32_t fixedColor; void Apply() { - glstate.blend.set(enabled); - glstate.blendEquationSeparate.set(eqCol, eqAlpha); - glstate.blendFuncSeparate.set(srcCol, dstCol, srcAlpha, dstAlpha); - glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - // glstate.blendColor.set(fixedColor); - + if (enabled) { + glEnable(GL_BLEND); + glBlendEquationSeparate(eqCol, eqAlpha); + glBlendFuncSeparate(srcCol, dstCol, srcAlpha, dstAlpha); + } else { + glDisable(GL_BLEND); + } + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + // glColorMask(maskBits & 1, (maskBits >> 1) & 1, (maskBits >> 2) & 1, (maskBits >> 3) & 1); + // glBlendColor(fixedColor); + #if !defined(USING_GLES2) - glstate.colorLogicOp.set(logicEnabled); if (logicEnabled) { - glstate.logicOp.set(logicOp); + glEnable(GL_LOGIC_OP); + glLogicOp(logicOp); + } else { + glDisable(GL_LOGIC_OP); } #endif - - // glstate.colorMask.set(maskBits & 1, (maskBits >> 1) & 1, (maskBits >> 2) & 1, (maskBits >> 3) & 1); } }; @@ -116,10 +122,14 @@ public: // bool stencilTestEnabled; TODO void Apply() { - glstate.depthTest.set(depthTestEnabled); - glstate.depthFunc.set(depthComp); - glstate.depthWrite.set(depthWriteEnabled); - glstate.stencilTest.disable(); + if (depthTestEnabled) { + glEnable(GL_DEPTH_TEST); + glDepthFunc(depthComp); + glDepthMask(depthWriteEnabled); + } else { + glDisable(GL_DEPTH_TEST); + } + glDisable(GL_STENCIL_TEST); } }; @@ -157,11 +167,7 @@ public: glBufferSubData(target_, offset, size, data); } void Bind() { - if (target_ == GL_ARRAY_BUFFER) { - glstate.arrayBuffer.bind(buffer_); - } else { - glstate.elementArrayBuffer.bind(buffer_); - } + glBindBuffer(target_, buffer_); } void GLLost() override { @@ -315,17 +321,25 @@ public: Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source); void SetScissorEnabled(bool enable) override { - glstate.scissorTest.set(enable); + if (enable) { + glEnable(GL_SCISSOR_TEST); + } else { + glDisable(GL_SCISSOR_TEST); + } } void SetScissorRect(int left, int top, int width, int height) override { - glstate.scissorRect.set(left, targetHeight_ - (top + height), width, height); + glScissor(left, targetHeight_ - (top + height), width, height); } void SetViewports(int count, T3DViewport *viewports) override { // TODO: Add support for multiple viewports. - glstate.viewport.set(viewports[0].TopLeftX, viewports[0].TopLeftY, viewports[0].Width, viewports[0].Height); - glstate.depthRange.set(viewports[0].MinDepth, viewports[0].MaxDepth); + glViewport(viewports[0].TopLeftX, viewports[0].TopLeftY, viewports[0].Width, viewports[0].Height); +#if defined(USING_GLES2) + glDepthRangef(viewports[0].MinDepth, viewports[0].MaxDepth); +#else + glDepthRange(viewports[0].MinDepth, viewports[0].MaxDepth); +#endif } void SetTextures(int start, int count, Thin3DTexture **textures) override; @@ -709,9 +723,9 @@ void Thin3DGLContext::SetRenderState(T3DRenderState rs, uint32_t value) { switch (rs) { case T3DRenderState::CULL_MODE: switch (value) { - case T3DCullMode::NO_CULL: glstate.cullFace.disable(); break; - case T3DCullMode::CCW: glstate.cullFace.enable(); glstate.cullFaceMode.set(GL_CCW); break; - case T3DCullMode::CW: glstate.cullFace.enable(); glstate.cullFaceMode.set(GL_CW); break; + case T3DCullMode::NO_CULL: glDisable(GL_CULL_FACE); break; + case T3DCullMode::CCW: glEnable(GL_CULL_FACE); glCullFace(GL_CCW); break; // TODO: Should be GL_FRONT + case T3DCullMode::CW: glEnable(GL_CULL_FACE); glCullFace(GL_CW); break; } break; } @@ -771,7 +785,7 @@ void Thin3DGLContext::Clear(int mask, uint32_t colorval, float depthVal, int ste glMask |= GL_COLOR_BUFFER_BIT; } if (mask & T3DClear::DEPTH) { -#ifdef USING_GLES2 +#if defined(USING_GLES2) glClearDepthf(depthVal); #else glClearDepth(depthVal); diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index d67ed1e0c0..56039e1809 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -2,10 +2,8 @@ #include "ui/ui.h" #include "ui/view.h" #include "ui/ui_context.h" -#include "gfx/texture.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/draw_text.h" -#include "gfx_es2/gl_state.h" UIContext::UIContext() : uishader_(0), uitexture_(0), uidrawbuffer_(0), uidrawbufferTop_(0) { From f78c4f6f84a5beea8c82040a1c169512bc857242 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 Sep 2015 13:12:00 +0200 Subject: [PATCH 1438/1445] Move FBO.cpp out into PPSSPP. --- Android.mk | 1 - gfx_es2/fbo.cpp | 415 ----------------------------------------- gfx_es2/fbo.h | 49 ----- native.vcxproj | 4 +- native.vcxproj.filters | 8 +- 5 files changed, 2 insertions(+), 475 deletions(-) delete mode 100644 gfx_es2/fbo.cpp delete mode 100644 gfx_es2/fbo.h diff --git a/Android.mk b/Android.mk index 77ff519153..3aacfb465d 100644 --- a/Android.mk +++ b/Android.mk @@ -84,7 +84,6 @@ LOCAL_SRC_FILES :=\ gfx_es2/draw_buffer.cpp.arm \ gfx_es2/draw_text.cpp.arm \ gfx_es2/vertex_format.cpp \ - gfx_es2/fbo.cpp \ gfx/gl_debug_log.cpp \ gfx/gl_lost_manager.cpp \ gfx/texture.cpp \ diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp deleted file mode 100644 index 001d77e9ff..0000000000 --- a/gfx_es2/fbo.cpp +++ /dev/null @@ -1,415 +0,0 @@ -#include - -#include "base/logging.h" -#include "gfx/gl_common.h" -#include "gfx_es2/fbo.h" -#include "gfx/gl_common.h" - -// TODO: Remove, after moving fbo.cpp into PPSSPP -#include "gfx_es2/gl_state.h" - -#ifdef IOS -extern void bindDefaultFBO(); -#endif - -struct FBO { - GLuint handle; - GLuint color_texture; - GLuint z_stencil_buffer; // Either this is set, or the two below. - GLuint z_buffer; - GLuint stencil_buffer; - - int width; - int height; - FBOColorDepth colorDepth; - bool native_fbo; -}; - -static FBO *g_overriddenBackbuffer; - -static GLuint currentDrawHandle_ = 0; -static GLuint currentReadHandle_ = 0; - -// On PC, we always use GL_DEPTH24_STENCIL8. -// On Android, we try to use what's available. - -#ifndef USING_GLES2 -FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { - FBO *fbo = new FBO(); - fbo->native_fbo = false; - fbo->width = width; - fbo->height = height; - fbo->colorDepth = colorDepth; - - // Color texture is same everywhere - glGenFramebuffersEXT(1, &fbo->handle); - glGenTextures(1, &fbo->color_texture); - - // Create the surfaces. - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // TODO: We could opt to only create 16-bit render targets on slow devices. For later. - switch (colorDepth) { - case FBO_8888: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - break; - case FBO_4444: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); - break; - case FBO_5551: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); - break; - case FBO_565: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); - break; - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - fbo->stencil_buffer = 0; - fbo->z_buffer = 0; - // 24-bit Z, 8-bit stencil - glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, width, height); - //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height); - - // Bind it all together - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); - - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - switch(status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: - // ILOG("Framebuffer verified complete."); - break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: - ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); - break; - default: - FLOG("Other framebuffer error: %i", status); - break; - } - // Unbind state we don't need - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - glBindTexture(GL_TEXTURE_2D, 0); - - currentDrawHandle_ = fbo->handle; - currentReadHandle_ = fbo->handle; - return fbo; -} -#endif - -int fbo_check_framebuffer_status(FBO *fbo) { - GLenum fbStatus; -#ifndef USING_GLES2 - if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) { - fbStatus = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER); - } else if (gl_extensions.ARB_framebuffer_object) { - fbStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); - } else { - fbStatus = 0; - } -#else - fbStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); -#endif - return (int)fbStatus; -} - -FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { - CheckGLExtensions(); - -#ifndef USING_GLES2 - if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) { - return fbo_ext_create(width, height, num_color_textures, z_stencil, colorDepth); - } else if (!gl_extensions.ARB_framebuffer_object) { - return nullptr; - } - // If GLES2, we have basic FBO support and can just proceed. -#endif - - FBO *fbo = new FBO(); - fbo->native_fbo = false; - fbo->width = width; - fbo->height = height; - fbo->colorDepth = colorDepth; - - // Color texture is same everywhere - glGenFramebuffers(1, &fbo->handle); - glGenTextures(1, &fbo->color_texture); - - // Create the surfaces. - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // TODO: We could opt to only create 16-bit render targets on slow devices. For later. - switch (colorDepth) { - case FBO_8888: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - break; - case FBO_4444: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); - break; - case FBO_5551: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); - break; - case FBO_565: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); - break; - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - if (gl_extensions.IsGLES) { - if (gl_extensions.OES_packed_depth_stencil) { - ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", width, height); - // Standard method - fbo->stencil_buffer = 0; - fbo->z_buffer = 0; - // 24-bit Z, 8-bit stencil combined - glGenRenderbuffers(1, &fbo->z_stencil_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); - - // Bind it all together - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - } else { - ILOG("Creating %i x %i FBO using separate stencil", width, height); - // TEGRA - fbo->z_stencil_buffer = 0; - // 16/24-bit Z, separate 8-bit stencil - glGenRenderbuffers(1, &fbo->z_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, width, height); - - // 8-bit stencil buffer - glGenRenderbuffers(1, &fbo->stencil_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); - - // Bind it all together - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); - } - } else { - fbo->stencil_buffer = 0; - fbo->z_buffer = 0; - // 24-bit Z, 8-bit stencil - glGenRenderbuffers(1, &fbo->z_stencil_buffer); - glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); - - // Bind it all together - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); - } - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - switch(status) { - case GL_FRAMEBUFFER_COMPLETE: - // ILOG("Framebuffer verified complete."); - break; - case GL_FRAMEBUFFER_UNSUPPORTED: - ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); - break; - default: - FLOG("Other framebuffer error: %i", status); - break; - } - // Unbind state we don't need - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - - currentDrawHandle_ = fbo->handle; - currentReadHandle_ = fbo->handle; - return fbo; -} - -FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo) -{ - if (!fbo) - fbo = new FBO(); - - fbo->native_fbo = true; - fbo->handle = native_fbo; - fbo->color_texture = 0; - fbo->z_stencil_buffer = 0; - fbo->z_buffer = 0; - fbo->stencil_buffer = 0; - fbo->width = 0; - fbo->height = 0; - fbo->colorDepth = FBO_8888; - - return fbo; -} - -static GLenum fbo_get_fb_target(bool read, GLuint **cached) { - bool supportsBlit = gl_extensions.ARB_framebuffer_object; - if (gl_extensions.IsGLES) { - supportsBlit = (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); - } - - // Note: GL_FRAMEBUFFER_EXT and GL_FRAMEBUFFER have the same value, same with _NV. - if (supportsBlit) { - if (read) { - *cached = ¤tReadHandle_; - return GL_READ_FRAMEBUFFER; - } else { - *cached = ¤tDrawHandle_; - return GL_DRAW_FRAMEBUFFER; - } - } else { - *cached = ¤tDrawHandle_; - return GL_FRAMEBUFFER; - } -} - -static void fbo_bind_fb_target(bool read, GLuint name) { - GLuint *cached; - GLenum target = fbo_get_fb_target(read, &cached); - - if (*cached != name) { - if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { - glBindFramebuffer(target, name); - } else { -#ifndef USING_GLES2 - glBindFramebufferEXT(target, name); -#endif - } - *cached = name; - } -} - -void fbo_unbind() { - if (g_overriddenBackbuffer) { - fbo_bind_as_render_target(g_overriddenBackbuffer); - return; - } - - CheckGLExtensions(); -#ifndef USING_GLES2 - if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } else if (gl_extensions.EXT_framebuffer_object) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - } -#else - glBindFramebuffer(GL_FRAMEBUFFER, 0); -#endif - -#ifdef IOS - bindDefaultFBO(); -#endif - - currentDrawHandle_ = 0; - currentReadHandle_ = 0; -} - -void fbo_override_backbuffer(FBO *fbo) { - g_overriddenBackbuffer = fbo; -} - -void fbo_bind_as_render_target(FBO *fbo) { - // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing - // in ES 2.0 that actually separate them anyway of course, so doesn't matter. - fbo_bind_fb_target(false, fbo->handle); - // Always restore viewport after render target binding - glstate.viewport.restore(); -} - -void fbo_unbind_render_target() { - fbo_unbind(); -} - -// For GL_EXT_FRAMEBUFFER_BLIT and similar. -void fbo_bind_for_read(FBO *fbo) { - fbo_bind_fb_target(true, fbo->handle); -} - -void fbo_unbind_read() { - fbo_bind_fb_target(true, 0); -} - -void fbo_bind_color_as_texture(FBO *fbo, int color) { - if (fbo) { - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); - } -} - -void fbo_destroy(FBO *fbo) { - if (fbo->native_fbo) { - delete fbo; - return; - } - - if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &fbo->handle); - glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); - glDeleteRenderbuffers(1, &fbo->z_buffer); - glDeleteRenderbuffers(1, &fbo->stencil_buffer); - } else if (gl_extensions.EXT_framebuffer_object) { -#ifndef USING_GLES2 - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glDeleteFramebuffersEXT(1, &fbo->handle); - glDeleteRenderbuffersEXT(1, &fbo->z_stencil_buffer); -#endif - } - - currentDrawHandle_ = 0; - currentReadHandle_ = 0; - - glDeleteTextures(1, &fbo->color_texture); - delete fbo; -} - -void fbo_get_dimensions(FBO *fbo, int *w, int *h) { - *w = fbo->width; - *h = fbo->height; -} - -int fbo_get_color_texture(FBO *fbo) { - return fbo->color_texture; -} - -int fbo_get_depth_buffer(FBO *fbo) { - return fbo->z_buffer; -} - -int fbo_get_stencil_buffer(FBO *fbo) { - return fbo->stencil_buffer; -} diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h deleted file mode 100644 index 52c3daf5a6..0000000000 --- a/gfx_es2/fbo.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -// Simple wrapper around FBO functionality. -// Very C-ish API because that's what I felt like, and it's cool to completely -// hide the data from callers... - -#include "gfx/gl_common.h" - -struct FBO; - - -enum FBOColorDepth { - FBO_8888, - FBO_565, - FBO_4444, - FBO_5551, -}; - - -// Creates a simple FBO with a RGBA32 color buffer stored in a texture, and -// optionally an accompanying Z/stencil buffer. -// No mipmap support. -// num_color_textures must be 1 for now. -// you lose bound texture state. - -// On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. -FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth = FBO_8888); - -// Create an opaque FBO from a native GL FBO, optionally reusing an existing FBO structure. -// Useful for overriding the backbuffer FBO that is generated outside of this wrapper. -FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo = NULL); -int fbo_check_framebuffer_status(FBO *fbo); - -// These functions should be self explanatory. -void fbo_bind_as_render_target(FBO *fbo); -// color must be 0, for now. -void fbo_bind_color_as_texture(FBO *fbo, int color); -void fbo_bind_for_read(FBO *fbo); -void fbo_unbind(); -void fbo_unbind_render_target(); -void fbo_unbind_read(); -void fbo_destroy(FBO *fbo); -void fbo_get_dimensions(FBO *fbo, int *w, int *h); - -int fbo_get_color_texture(FBO *fbo); -int fbo_get_depth_buffer(FBO *fbo); -int fbo_get_stencil_buffer(FBO *fbo); - -void fbo_override_backbuffer(FBO *fbo); // Makes unbind bind this instead of the real backbuffer. diff --git a/native.vcxproj b/native.vcxproj index 21d7da8783..7bb988b8bd 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -248,7 +248,6 @@ - @@ -734,7 +733,6 @@ - true true @@ -799,4 +797,4 @@ - \ No newline at end of file + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 4936477b81..18290a20c8 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -54,9 +54,6 @@ gfx - - gfx - gfx @@ -387,9 +384,6 @@ gfx - - gfx - gfx @@ -925,4 +919,4 @@ {06c6305a-a646-485b-85b9-645a24dd6553} - \ No newline at end of file + From 65e3d31e249ca811809121529f1971e408c154d3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 Sep 2015 13:35:42 +0200 Subject: [PATCH 1439/1445] Move the GPU feature detection from gl_state.cpp to gpu_features.cpp --- gfx_es2/gl_state.cpp | 323 --------------------------------------- gfx_es2/gl_state.h | 3 - gfx_es2/gpu_features.cpp | 318 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 318 insertions(+), 326 deletions(-) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index ca4b614148..5124c51f44 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -1,38 +1,9 @@ #include #include "base/logging.h" -#include "base/stringutil.h" -#include "base/NativeApp.h" #include "gfx_es2/gl_state.h" -#ifdef _WIN32 -#include "GL/wglew.h" -#endif - -#if defined(USING_GLES2) -#if defined(ANDROID) || defined(BLACKBERRY) -PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; -PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; -PFNGLDRAWTEXTURENVPROC glDrawTextureNV; -PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV; -PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV; -PFNGLMAPBUFFERPROC glMapBuffer; - -PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; -PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; -PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; -PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES; -PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; -#endif -#ifndef IOS -#include "EGL/egl.h" -#endif -#endif - OpenGLState glstate; -GLExtensions gl_extensions; -std::string g_all_gl_extensions; -std::string g_all_egl_extensions; int OpenGLState::state_count = 0; @@ -78,297 +49,3 @@ void OpenGLState::Restore() { FLOG("OpenGLState::Restore is missing some states"); } } - -// http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array - -void CheckGLExtensions() { - // Make sure to only do this once. It's okay to call CheckGLExtensions from wherever. - static bool done = false; - if (done) - return; - done = true; - memset(&gl_extensions, 0, sizeof(gl_extensions)); - -#ifdef USING_GLES2 - gl_extensions.IsGLES = true; -#endif - - const char *renderer = (const char *)glGetString(GL_RENDERER); - const char *versionStr = (const char *)glGetString(GL_VERSION); - const char *glslVersionStr = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); - - // Check vendor string to try and guess GPU - const char *cvendor = (char *)glGetString(GL_VENDOR); - // TODO: move this stuff to gpu_features.cpp - if (cvendor) { - const std::string vendor = StripSpaces(std::string(cvendor)); - if (vendor == "NVIDIA Corporation" - || vendor == "Nouveau" - || vendor == "nouveau") { - gl_extensions.gpuVendor = GPU_VENDOR_NVIDIA; - } else if (vendor == "Advanced Micro Devices, Inc." - || vendor == "ATI Technologies Inc.") { - gl_extensions.gpuVendor = GPU_VENDOR_AMD; - } else if (vendor == "Intel" - || vendor == "Intel Inc." - || vendor == "Intel Corporation" - || vendor == "Tungsten Graphics, Inc") { // We'll assume this last one means Intel - gl_extensions.gpuVendor = GPU_VENDOR_INTEL; - } else if (vendor == "ARM") { - gl_extensions.gpuVendor = GPU_VENDOR_ARM; - } else if (vendor == "Imagination Technologies") { - gl_extensions.gpuVendor = GPU_VENDOR_POWERVR; - } else if (vendor == "Qualcomm") { - gl_extensions.gpuVendor = GPU_VENDOR_ADRENO; - } else if (vendor == "Broadcom") { - gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM; - // Just for reference: Galaxy Y has renderer == "VideoCore IV HW" - } else { - gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; - } - } else { - gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; - } - - ILOG("GPU Vendor : %s ; renderer: %s version str: %s ; GLSL version str: %s", cvendor, renderer ? renderer : "N/A", versionStr ? versionStr : "N/A", glslVersionStr ? glslVersionStr : "N/A"); - - if (renderer) { - strncpy(gl_extensions.model, renderer, sizeof(gl_extensions.model)); - gl_extensions.model[sizeof(gl_extensions.model) - 1] = 0; - } - - if (!gl_extensions.IsGLES) { - // For desktop GL, grab the version and attempt to parse. - char buffer[64] = { 0 }; - if (versionStr) { - strncpy(buffer, versionStr, 63); - } - const char *lastNumStart = buffer; - int numVer = 0; - int len = (int)strlen(buffer); - for (int i = 0; i < len && numVer < 3; i++) { - if (buffer[i] == '.') { - buffer[i] = 0; - gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); - i++; - lastNumStart = buffer + i; - } - } - if (numVer < 3) - gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); - - // If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable - // all the same modern paths. - // Most of it could be enabled on lower GPUs as well, but let's start this way. - if (gl_extensions.VersionGEThan(4, 3, 0)) { - gl_extensions.GLES3 = true; - } - } else { - // Start by assuming we're at 2.0. - gl_extensions.ver[0] = 2; - -#ifdef USING_GLES2 -#ifdef GL_MAJOR_VERSION - // Before grabbing the values, reset the error. - glGetError(); - glGetIntegerv(GL_MAJOR_VERSION, &gl_extensions.ver[0]); - glGetIntegerv(GL_MINOR_VERSION, &gl_extensions.ver[1]); - // We check error here to detect if these properties were supported. - if (glGetError() != GL_NO_ERROR) { - // They weren't, reset to GLES 2.0. - gl_extensions.ver[0] = 2; - gl_extensions.ver[1] = 0; - } -#endif - - // If the above didn't give us a version, or gave us a crazy version, fallback. - if (gl_extensions.ver[0] < 3 || gl_extensions.ver[0] > 5) { - // Try to load GLES 3.0 only if "3.0" found in version - // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited - // number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584. - bool gl_3_0_in_string = strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0"); - bool gl_3_1_in_string = strstr(versionStr, "3.1") && strstr(glslVersionStr, "3.1"); // intentionally left out .1 - if ((gl_3_0_in_string || gl_3_1_in_string) && gl3stubInit()) { - gl_extensions.ver[0] = 3; - if (gl_3_1_in_string) { - gl_extensions.ver[1] = 1; - } - gl_extensions.GLES3 = true; - // Though, let's ban Mali from the GLES 3 path for now, see #4078 - if (strstr(renderer, "Mali") != 0) { - gl_extensions.GLES3 = false; - } - } else { - // Just to be safe. - gl_extensions.ver[0] = 2; - gl_extensions.ver[1] = 0; - } - } else { - // Otherwise, let's trust GL_MAJOR_VERSION. Note that Mali is intentionally not banned here. - if (gl_extensions.ver[0] >= 3) { - gl_extensions.GLES3 = gl3stubInit(); - } - } -#endif - - if (gl_extensions.GLES3) { - if (gl_extensions.ver[1] >= 1) { - ILOG("OpenGL ES 3.1 support detected!\n"); - } else { - ILOG("OpenGL ES 3.0 support detected!\n"); - } - } - } - - const char *extString = (const char *)glGetString(GL_EXTENSIONS); - if (extString) { - g_all_gl_extensions = extString; - } else { - g_all_gl_extensions = ""; - extString = ""; - } - -#ifdef WIN32 - const char *wglString = 0; - if (wglGetExtensionsStringEXT) - wglString = wglGetExtensionsStringEXT(); - if (wglString) { - gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0; - g_all_egl_extensions = wglString; - } else { - g_all_egl_extensions = ""; - } -#elif !defined(USING_GLES2) - // const char *glXString = glXQueryExtensionString(); - // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; -#endif - - // Check the desktop extension instead of the OES one. They are very similar. - // Also explicitly check those ATI devices that claims to support npot - gl_extensions.OES_texture_npot = strstr(extString, "GL_ARB_texture_non_power_of_two") != 0 - && !(((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0))); - - gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; - gl_extensions.EXT_blend_func_extended = strstr(extString, "GL_EXT_blend_func_extended") != 0; - gl_extensions.ARB_conservative_depth = strstr(extString, "GL_ARB_conservative_depth") != 0; - gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); - gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0; - gl_extensions.EXT_gpu_shader4 = strstr(extString, "GL_EXT_gpu_shader4") != 0; - gl_extensions.NV_framebuffer_blit = strstr(extString, "GL_NV_framebuffer_blit") != 0; - - if (gl_extensions.IsGLES) { - gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0; - gl_extensions.OES_packed_depth_stencil = (strstr(extString, "GL_OES_packed_depth_stencil") != 0) || gl_extensions.GLES3; - gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; - gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; - gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; - gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0; - gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; - gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; - gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; - gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0; - gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; - -#if defined(ANDROID) || defined(BLACKBERRY) - // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. - // https://twitter.com/ID_AA_Carmack/status/387383037794603008 -#ifdef _DEBUG - void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1"); - void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2"); - DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2); -#endif - - if (gl_extensions.NV_copy_image) { - glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV"); - } - - if (gl_extensions.NV_framebuffer_blit) { - glBlitFramebufferNV = (PFNGLBLITFRAMEBUFFERNVPROC)eglGetProcAddress("glBlitFramebufferNV"); - } - - gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0; - if (gl_extensions.OES_vertex_array_object) { - glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" ); - glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress ( "glBindVertexArrayOES" ); - glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress ( "glDeleteVertexArraysOES" ); - glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" ); - } - - // Hm, this should be available on iOS too. - gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; - if (gl_extensions.EXT_discard_framebuffer) { - glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); - } -#else - gl_extensions.OES_vertex_array_object = false; - gl_extensions.EXT_discard_framebuffer = false; -#endif - } else { - // Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc) - gl_extensions.EXT_blend_minmax = true; - gl_extensions.EXT_unpack_subimage = true; - } - - // GLES 3 subsumes many ES2 extensions. - if (gl_extensions.GLES3) { - gl_extensions.EXT_unpack_subimage = true; - } - -#if defined(ANDROID) || defined(BLACKBERRY) - if (gl_extensions.OES_mapbuffer) { - glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" ); - } - - // Look for EGL extensions - EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - - const char *eglString = eglQueryString(display, EGL_EXTENSIONS); - if (eglString) { - g_all_egl_extensions = eglString; - - gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0; - gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0; - - if (gl_extensions.EGL_NV_system_time) { - eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV"); - eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV"); - } - } else { - g_all_egl_extensions = ""; - } -#endif - - // This is probably a waste of time, implementations lie. - if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility")) { - const GLint precisions[6] = { - GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT, - GL_LOW_INT, GL_MEDIUM_INT, GL_HIGH_INT - }; - GLint shaderTypes[2] = { - GL_VERTEX_SHADER, GL_FRAGMENT_SHADER - }; - for (int st = 0; st < 2; st++) { - for (int p = 0; p < 6; p++) { - glGetShaderPrecisionFormat(shaderTypes[st], precisions[p], gl_extensions.range[st][p], &gl_extensions.precision[st][p]); - } - } - } - - gl_extensions.ARB_framebuffer_object = strstr(extString, "GL_ARB_framebuffer_object") != 0; - gl_extensions.EXT_framebuffer_object = strstr(extString, "GL_EXT_framebuffer_object") != 0; - gl_extensions.ARB_pixel_buffer_object = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; - gl_extensions.NV_pixel_buffer_object = strstr(extString, "GL_NV_pixel_buffer_object") != 0; - - ProcessGPUFeatures(); - - int error = glGetError(); - if (error) - ELOG("GL error in init: %i", error); -} - -void OpenGLState::SetVSyncInterval(int interval) { -#ifdef _WIN32 - if (wglSwapIntervalEXT) - wglSwapIntervalEXT(interval); -#endif -} diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index 874c309045..c1d6f2669d 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -232,9 +232,6 @@ public: STATEBIND(glBindBuffer, GL_ARRAY_BUFFER) arrayBuffer; STATEBIND(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER) elementArrayBuffer; - - // Only works on Win32, all other platforms are "force-vsync" - void SetVSyncInterval(int interval); // one of the above VSYNC, or a higher number for multi-frame waits (could be useful for 30hz games) }; #undef STATE1 diff --git a/gfx_es2/gpu_features.cpp b/gfx_es2/gpu_features.cpp index 57ff968a38..bbc9c3eac2 100644 --- a/gfx_es2/gpu_features.cpp +++ b/gfx_es2/gpu_features.cpp @@ -1,7 +1,38 @@ #include + #include "base/logging.h" +#include "base/stringutil.h" +#include "gfx/gl_common.h" #include "gfx_es2/gpu_features.h" +#ifdef _WIN32 +#include "GL/wglew.h" +#endif + +#if defined(USING_GLES2) +#if defined(ANDROID) || defined(BLACKBERRY) +PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV; +PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV; +PFNGLDRAWTEXTURENVPROC glDrawTextureNV; +PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV; +PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV; +PFNGLMAPBUFFERPROC glMapBuffer; + +PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT; +PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; +PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; +PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES; +PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; +#endif +#ifndef IOS +#include "EGL/egl.h" +#endif +#endif + +GLExtensions gl_extensions; +std::string g_all_gl_extensions; +std::string g_all_egl_extensions; + bool GLExtensions::VersionGEThan(int major, int minor, int sub) { if (gl_extensions.ver[0] > major) return true; @@ -37,3 +68,290 @@ void ProcessGPUFeatures() { gl_extensions.bugs |= BUG_PVR_GENMIPMAP_HEIGHT_GREATER; } } + +// http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array + +void CheckGLExtensions() { + // Make sure to only do this once. It's okay to call CheckGLExtensions from wherever. + static bool done = false; + if (done) + return; + done = true; + memset(&gl_extensions, 0, sizeof(gl_extensions)); + +#ifdef USING_GLES2 + gl_extensions.IsGLES = true; +#endif + + const char *renderer = (const char *)glGetString(GL_RENDERER); + const char *versionStr = (const char *)glGetString(GL_VERSION); + const char *glslVersionStr = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); + + // Check vendor string to try and guess GPU + const char *cvendor = (char *)glGetString(GL_VENDOR); + // TODO: move this stuff to gpu_features.cpp + if (cvendor) { + const std::string vendor = StripSpaces(std::string(cvendor)); + if (vendor == "NVIDIA Corporation" + || vendor == "Nouveau" + || vendor == "nouveau") { + gl_extensions.gpuVendor = GPU_VENDOR_NVIDIA; + } else if (vendor == "Advanced Micro Devices, Inc." + || vendor == "ATI Technologies Inc.") { + gl_extensions.gpuVendor = GPU_VENDOR_AMD; + } else if (vendor == "Intel" + || vendor == "Intel Inc." + || vendor == "Intel Corporation" + || vendor == "Tungsten Graphics, Inc") { // We'll assume this last one means Intel + gl_extensions.gpuVendor = GPU_VENDOR_INTEL; + } else if (vendor == "ARM") { + gl_extensions.gpuVendor = GPU_VENDOR_ARM; + } else if (vendor == "Imagination Technologies") { + gl_extensions.gpuVendor = GPU_VENDOR_POWERVR; + } else if (vendor == "Qualcomm") { + gl_extensions.gpuVendor = GPU_VENDOR_ADRENO; + } else if (vendor == "Broadcom") { + gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM; + // Just for reference: Galaxy Y has renderer == "VideoCore IV HW" + } else { + gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; + } + } else { + gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; + } + + ILOG("GPU Vendor : %s ; renderer: %s version str: %s ; GLSL version str: %s", cvendor, renderer ? renderer : "N/A", versionStr ? versionStr : "N/A", glslVersionStr ? glslVersionStr : "N/A"); + + if (renderer) { + strncpy(gl_extensions.model, renderer, sizeof(gl_extensions.model)); + gl_extensions.model[sizeof(gl_extensions.model) - 1] = 0; + } + + if (!gl_extensions.IsGLES) { + // For desktop GL, grab the version and attempt to parse. + char buffer[64] = { 0 }; + if (versionStr) { + strncpy(buffer, versionStr, 63); + } + const char *lastNumStart = buffer; + int numVer = 0; + int len = (int)strlen(buffer); + for (int i = 0; i < len && numVer < 3; i++) { + if (buffer[i] == '.') { + buffer[i] = 0; + gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); + i++; + lastNumStart = buffer + i; + } + } + if (numVer < 3) + gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); + + // If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable + // all the same modern paths. + // Most of it could be enabled on lower GPUs as well, but let's start this way. + if (gl_extensions.VersionGEThan(4, 3, 0)) { + gl_extensions.GLES3 = true; + } + } else { + // Start by assuming we're at 2.0. + gl_extensions.ver[0] = 2; + +#ifdef USING_GLES2 +#ifdef GL_MAJOR_VERSION + // Before grabbing the values, reset the error. + glGetError(); + glGetIntegerv(GL_MAJOR_VERSION, &gl_extensions.ver[0]); + glGetIntegerv(GL_MINOR_VERSION, &gl_extensions.ver[1]); + // We check error here to detect if these properties were supported. + if (glGetError() != GL_NO_ERROR) { + // They weren't, reset to GLES 2.0. + gl_extensions.ver[0] = 2; + gl_extensions.ver[1] = 0; + } +#endif + + // If the above didn't give us a version, or gave us a crazy version, fallback. + if (gl_extensions.ver[0] < 3 || gl_extensions.ver[0] > 5) { + // Try to load GLES 3.0 only if "3.0" found in version + // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited + // number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584. + bool gl_3_0_in_string = strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0"); + bool gl_3_1_in_string = strstr(versionStr, "3.1") && strstr(glslVersionStr, "3.1"); // intentionally left out .1 + if ((gl_3_0_in_string || gl_3_1_in_string) && gl3stubInit()) { + gl_extensions.ver[0] = 3; + if (gl_3_1_in_string) { + gl_extensions.ver[1] = 1; + } + gl_extensions.GLES3 = true; + // Though, let's ban Mali from the GLES 3 path for now, see #4078 + if (strstr(renderer, "Mali") != 0) { + gl_extensions.GLES3 = false; + } + } else { + // Just to be safe. + gl_extensions.ver[0] = 2; + gl_extensions.ver[1] = 0; + } + } else { + // Otherwise, let's trust GL_MAJOR_VERSION. Note that Mali is intentionally not banned here. + if (gl_extensions.ver[0] >= 3) { + gl_extensions.GLES3 = gl3stubInit(); + } + } +#endif + + if (gl_extensions.GLES3) { + if (gl_extensions.ver[1] >= 1) { + ILOG("OpenGL ES 3.1 support detected!\n"); + } else { + ILOG("OpenGL ES 3.0 support detected!\n"); + } + } + } + + const char *extString = (const char *)glGetString(GL_EXTENSIONS); + if (extString) { + g_all_gl_extensions = extString; + } else { + g_all_gl_extensions = ""; + extString = ""; + } + +#ifdef WIN32 + const char *wglString = 0; + if (wglGetExtensionsStringEXT) + wglString = wglGetExtensionsStringEXT(); + if (wglString) { + gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0; + g_all_egl_extensions = wglString; + } else { + g_all_egl_extensions = ""; + } +#elif !defined(USING_GLES2) + // const char *glXString = glXQueryExtensionString(); + // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; +#endif + + // Check the desktop extension instead of the OES one. They are very similar. + // Also explicitly check those ATI devices that claims to support npot + gl_extensions.OES_texture_npot = strstr(extString, "GL_ARB_texture_non_power_of_two") != 0 + && !(((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0))); + + gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; + gl_extensions.EXT_blend_func_extended = strstr(extString, "GL_EXT_blend_func_extended") != 0; + gl_extensions.ARB_conservative_depth = strstr(extString, "GL_ARB_conservative_depth") != 0; + gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); + gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0; + gl_extensions.EXT_gpu_shader4 = strstr(extString, "GL_EXT_gpu_shader4") != 0; + gl_extensions.NV_framebuffer_blit = strstr(extString, "GL_NV_framebuffer_blit") != 0; + + if (gl_extensions.IsGLES) { + gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0; + gl_extensions.OES_packed_depth_stencil = (strstr(extString, "GL_OES_packed_depth_stencil") != 0) || gl_extensions.GLES3; + gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; + gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; + gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; + gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0; + gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; + gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; + gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; + gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0; + gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; + +#if defined(ANDROID) || defined(BLACKBERRY) + // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. + // https://twitter.com/ID_AA_Carmack/status/387383037794603008 +#ifdef _DEBUG + void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1"); + void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2"); + DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2); +#endif + + if (gl_extensions.NV_copy_image) { + glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV"); + } + + if (gl_extensions.NV_framebuffer_blit) { + glBlitFramebufferNV = (PFNGLBLITFRAMEBUFFERNVPROC)eglGetProcAddress("glBlitFramebufferNV"); + } + + gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0; + if (gl_extensions.OES_vertex_array_object) { + glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES"); + glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES"); + glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES"); + glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES"); + } + + // Hm, this should be available on iOS too. + gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; + if (gl_extensions.EXT_discard_framebuffer) { + glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); + } +#else + gl_extensions.OES_vertex_array_object = false; + gl_extensions.EXT_discard_framebuffer = false; +#endif + } else { + // Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc) + gl_extensions.EXT_blend_minmax = true; + gl_extensions.EXT_unpack_subimage = true; + } + + // GLES 3 subsumes many ES2 extensions. + if (gl_extensions.GLES3) { + gl_extensions.EXT_unpack_subimage = true; + } + +#if defined(ANDROID) || defined(BLACKBERRY) + if (gl_extensions.OES_mapbuffer) { + glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress("glMapBufferOES"); + } + + // Look for EGL extensions + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + const char *eglString = eglQueryString(display, EGL_EXTENSIONS); + if (eglString) { + g_all_egl_extensions = eglString; + + gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0; + gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0; + + if (gl_extensions.EGL_NV_system_time) { + eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC)eglGetProcAddress("eglGetSystemTimeNV"); + eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)eglGetProcAddress("eglGetSystemTimeFrequencyNV"); + } + } else { + g_all_egl_extensions = ""; + } +#endif + + // This is probably a waste of time, implementations lie. + if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility")) { + const GLint precisions[6] = { + GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT, + GL_LOW_INT, GL_MEDIUM_INT, GL_HIGH_INT + }; + GLint shaderTypes[2] = { + GL_VERTEX_SHADER, GL_FRAGMENT_SHADER + }; + for (int st = 0; st < 2; st++) { + for (int p = 0; p < 6; p++) { + glGetShaderPrecisionFormat(shaderTypes[st], precisions[p], gl_extensions.range[st][p], &gl_extensions.precision[st][p]); + } + } + } + + gl_extensions.ARB_framebuffer_object = strstr(extString, "GL_ARB_framebuffer_object") != 0; + gl_extensions.EXT_framebuffer_object = strstr(extString, "GL_EXT_framebuffer_object") != 0; + gl_extensions.ARB_pixel_buffer_object = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; + gl_extensions.NV_pixel_buffer_object = strstr(extString, "GL_NV_pixel_buffer_object") != 0; + + ProcessGPUFeatures(); + + int error = glGetError(); + if (error) + ELOG("GL error in init: %i", error); +} From 3f02f9fc778b5b4c45db92a96f0a4087f947d5a2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 Sep 2015 13:44:06 +0200 Subject: [PATCH 1440/1445] Move gl_state.cpp/h out to PPSSPP --- base/QtMain.h | 2 +- gfx_es2/gl_state.cpp | 51 --------- gfx_es2/gl_state.h | 240 ----------------------------------------- native.vcxproj | 2 - native.vcxproj.filters | 6 -- 5 files changed, 1 insertion(+), 300 deletions(-) delete mode 100644 gfx_es2/gl_state.cpp delete mode 100644 gfx_es2/gl_state.h diff --git a/base/QtMain.h b/base/QtMain.h index 18956d789e..cf56875f65 100644 --- a/base/QtMain.h +++ b/base/QtMain.h @@ -22,7 +22,7 @@ QTM_USE_NAMESPACE #include "base/logging.h" #include "base/timeutil.h" #include "file/zip_read.h" -#include "gfx_es2/gl_state.h" +#include "gfx/gl_common.h" #include "input/input_state.h" #include "input/keycodes.h" #include "base/NativeApp.h" diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp deleted file mode 100644 index 5124c51f44..0000000000 --- a/gfx_es2/gl_state.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include - -#include "base/logging.h" -#include "gfx_es2/gl_state.h" - -OpenGLState glstate; - -int OpenGLState::state_count = 0; - -void OpenGLState::Restore() { - int count = 0; - - blend.restore(); count++; - blendEquationSeparate.restore(); count++; - blendFuncSeparate.restore(); count++; - blendColor.restore(); count++; - - scissorTest.restore(); count++; - scissorRect.restore(); count++; - - cullFace.restore(); count++; - cullFaceMode.restore(); count++; - frontFace.restore(); count++; - - depthTest.restore(); count++; - depthRange.restore(); count++; - depthFunc.restore(); count++; - depthWrite.restore(); count++; - - colorMask.restore(); count++; - viewport.restore(); count++; - - stencilTest.restore(); count++; - stencilOp.restore(); count++; - stencilFunc.restore(); count++; - stencilMask.restore(); count++; - - dither.restore(); count++; - -#if !defined(USING_GLES2) - colorLogicOp.restore(); count++; - logicOp.restore(); count++; -#endif - - arrayBuffer.restore(); count++; - elementArrayBuffer.restore(); count++; - - if (count != state_count) { - FLOG("OpenGLState::Restore is missing some states"); - } -} diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h deleted file mode 100644 index c1d6f2669d..0000000000 --- a/gfx_es2/gl_state.h +++ /dev/null @@ -1,240 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "gfx/gl_common.h" -#include "gfx_es2/gpu_features.h" - -// OpenGL state cache. -// Probably only really worth it in rendering cores on weak mobile hardware. -class OpenGLState { -private: - template - class BoolState { - private: - bool _value; - public: - BoolState() : _value(init) { - OpenGLState::state_count++; - } - - inline void set(bool value) { - if (value && value != _value) { - _value = value; - glEnable(cap); - } - if (!value && value != _value) { - _value = value; - glDisable(cap); - } - } - inline void enable() { - set(true); - } - inline void disable() { - set(false); - } - operator bool() const { - return isset(); - } - inline bool isset() { - return _value; - } - void restore() { - if (_value) - glEnable(cap); - else - glDisable(cap); - } - }; - -#define STATE1(func, p1type, p1def) \ - class SavedState1_##func { \ - p1type p1; \ - public: \ - SavedState1_##func() : p1(p1def) { \ - OpenGLState::state_count++; \ - } \ - void set(p1type newp1) { \ - if (newp1 != p1) { \ - p1 = newp1; \ - func(p1); \ - } \ - } \ - void restore() { \ - func(p1); \ - } \ - } - -#define STATE2(func, p1type, p2type, p1def, p2def) \ - class SavedState2_##func { \ - p1type p1; \ - p2type p2; \ - public: \ - SavedState2_##func() : p1(p1def), p2(p2def) { \ - OpenGLState::state_count++; \ - } \ - inline void set(p1type newp1, p2type newp2) { \ - if (newp1 != p1 || newp2 != p2) { \ - p1 = newp1; \ - p2 = newp2; \ - func(p1, p2); \ - } \ - } \ - inline void restore() { \ - func(p1, p2); \ - } \ - } - -#define STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \ - class SavedState3_##func { \ - p1type p1; \ - p2type p2; \ - p3type p3; \ - public: \ - SavedState3_##func() : p1(p1def), p2(p2def), p3(p3def) { \ - OpenGLState::state_count++; \ - } \ - inline void set(p1type newp1, p2type newp2, p3type newp3) { \ - if (newp1 != p1 || newp2 != p2 || newp3 != p3) { \ - p1 = newp1; \ - p2 = newp2; \ - p3 = newp3; \ - func(p1, p2, p3); \ - } \ - } \ - inline void restore() { \ - func(p1, p2, p3); \ - } \ - } - - #define STATE4(func, p1type, p2type, p3type, p4type, p1def, p2def, p3def, p4def) \ - class SavedState4_##func { \ - p1type p1; \ - p2type p2; \ - p3type p3; \ - p4type p4; \ - public: \ - SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) { \ - OpenGLState::state_count++; \ - } \ - inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \ - if (newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \ - p1 = newp1; \ - p2 = newp2; \ - p3 = newp3; \ - p4 = newp4; \ - func(p1, p2, p3, p4); \ - } \ - } \ - inline void restore() { \ - func(p1, p2, p3, p4); \ - } \ - } - -#define STATEFLOAT4(func, def) \ - class SavedState4_##func { \ - float p[4]; \ - public: \ - SavedState4_##func() { \ - for (int i = 0; i < 4; i++) {p[i] = def;} \ - OpenGLState::state_count++; \ - } \ - inline void set(const float v[4]) { \ - if (memcmp(p,v,sizeof(float)*4)) { \ - memcpy(p,v,sizeof(float)*4); \ - func(p[0], p[1], p[2], p[3]); \ - } \ - } \ - inline void restore() { \ - func(p[0], p[1], p[2], p[3]); \ - } \ - } - -#define STATEBIND(func, target) \ - class SavedBind_##func_##target { \ - GLuint val_; \ - public: \ - SavedBind_##func_##target() { \ - val_ = 0; \ - OpenGLState::state_count++; \ - } \ - inline void bind(GLuint val) { \ - if (val_ != val) { \ - func(target, val); \ - val_ = val; \ - } \ - } \ - inline void unbind() { \ - bind(0); \ - } \ - inline void restore() { \ - func(target, val_); \ - } \ - } - -public: - static int state_count; - OpenGLState() {} - void Restore(); - - // When adding a state here, don't forget to add it to OpenGLState::Restore() too - - // Blending - BoolState blend; - STATE4(glBlendFuncSeparate, GLenum, GLenum, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFuncSeparate; - - // On OpenGL ES, using minmax blend requires glBlendEquationEXT (in theory at least but I don't think it's true in practice) - STATE2(glBlendEquationSeparate, GLenum, GLenum, GL_FUNC_ADD, GL_FUNC_ADD) blendEquationSeparate; - STATEFLOAT4(glBlendColor, 1.0f) blendColor; - - // Logic Ops. Not available on OpenGL ES at all. -#if !defined(USING_GLES2) - BoolState colorLogicOp; - STATE1(glLogicOp, GLenum, GL_COPY) logicOp; -#endif - - // Dither - BoolState dither; - - // Cull Face - BoolState cullFace; - STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode; - STATE1(glFrontFace, GLenum, GL_CCW) frontFace; - - // Depth Test - BoolState depthTest; -#if defined(USING_GLES2) - STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; -#else - STATE2(glDepthRange, double, double, 0.0, 1.0) depthRange; -#endif - STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; - STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite; - - // Color Mask - STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask; - - // Viewport - STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport; - - // Scissor Test - BoolState scissorTest; - STATE4(glScissor, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) scissorRect; - - // Stencil Test - BoolState stencilTest; - STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp; - STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc; - STATE1(glStencilMask, GLuint, 0xFF) stencilMask; - - STATEBIND(glBindBuffer, GL_ARRAY_BUFFER) arrayBuffer; - STATEBIND(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER) elementArrayBuffer; -}; - -#undef STATE1 -#undef STATE2 - -extern OpenGLState glstate; diff --git a/native.vcxproj b/native.vcxproj index 7bb988b8bd..afc9ff5752 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -250,7 +250,6 @@ - @@ -740,7 +739,6 @@ true - diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 18290a20c8..c9d424be97 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -216,9 +216,6 @@ ext - - gfx - gfx @@ -518,9 +515,6 @@ base - - gfx - gfx From bdd09be76b7b065ff932a8aac162e54a63fb44b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 6 Sep 2015 14:38:15 +0200 Subject: [PATCH 1441/1445] SDL (Mac) buildfix --- base/PCMain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index b5b4876176..d932d7e017 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -29,6 +29,7 @@ SDLJoystick *joystick = NULL; #include "base/display.h" #include "base/logging.h" #include "base/timeutil.h" +#include "gfx/gl_common.h" #include "gfx_es2/gpu_features.h" #include "input/input_state.h" #include "input/keycodes.h" From b502db61c8143dc10dca4ac918fadd936f3ce4df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 6 Sep 2015 15:25:56 +0200 Subject: [PATCH 1442/1445] Android buildfix --- Android.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/Android.mk b/Android.mk index 3aacfb465d..2ae05260c5 100644 --- a/Android.mk +++ b/Android.mk @@ -79,7 +79,6 @@ LOCAL_SRC_FILES :=\ thread/threadpool.cpp \ gfx_es2/glsl_program.cpp \ gfx_es2/gpu_features.cpp \ - gfx_es2/gl_state.cpp.arm \ gfx_es2/gl3stub.c \ gfx_es2/draw_buffer.cpp.arm \ gfx_es2/draw_text.cpp.arm \ From d2866194fde945ac702f76bbed6b3f394eaaeae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 6 Sep 2015 16:03:19 +0200 Subject: [PATCH 1443/1445] Symbian buildfix --- gfx/gl_common.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx/gl_common.h b/gfx/gl_common.h index c6690c16e5..24f121b3a7 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -69,7 +69,6 @@ extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES; extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES; extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES; extern PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; -#endif // Rename standard functions to the OES version. #define glGenVertexArrays glGenVertexArraysOES @@ -77,6 +76,8 @@ extern PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; #define glDeleteVertexArrays glDeleteVertexArraysOES #define glIsVertexArray glIsVertexArrayOES +#endif + #if !defined(BLACKBERRY) #ifndef GL_READ_FRAMEBUFFER #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER From 18ce2262d6f93aa3715190aeb6e31b00e0eab2d4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 Sep 2015 19:08:32 +0200 Subject: [PATCH 1444/1445] We don't need a third set of typed-integer typedefs --- audio/wav_read.cpp | 2 +- base/basictypes.h | 70 ++++++++++++-------------------------- base/stringutil.cpp | 2 +- base/stringutil.h | 2 +- file/chunk_file.cpp | 4 +-- file/chunk_file.h | 4 +-- gfx_es2/draw_buffer.cpp | 20 +++++------ gfx_es2/draw_buffer.h | 26 +++++++------- gfx_es2/vertex_format.cpp | 2 +- image/zim_load.cpp | 4 +-- math/expression_parser.cpp | 20 +++++------ math/expression_parser.h | 16 ++++----- util/bits/bits.cpp | 6 ++-- util/bits/bits.h | 10 +++--- util/bits/varint.cpp | 2 +- util/hash/hash.cpp | 10 +++--- util/hash/hash.h | 4 +-- util/random/rng.h | 6 ++-- 18 files changed, 92 insertions(+), 118 deletions(-) diff --git a/audio/wav_read.cpp b/audio/wav_read.cpp index 8b2dbeb76c..6a827ece36 100644 --- a/audio/wav_read.cpp +++ b/audio/wav_read.cpp @@ -47,7 +47,7 @@ short *wav_read(const char *filename, data = (short *)malloc(sizeof(short) * numSamples * *num_channels); *num_samples = numSamples; if (wBlockAlign == 2 && *num_channels == 1) { - cf.readData((uint8*)data,numBytes); + cf.readData((uint8_t *)data,numBytes); } else { ELOG("Error - bad blockalign or channels"); free(data); diff --git a/base/basictypes.h b/base/basictypes.h index 7f3dfea731..c7cb845a99 100644 --- a/base/basictypes.h +++ b/base/basictypes.h @@ -3,18 +3,6 @@ #include #include // for byte swapping -#ifdef _WIN32 -// We need this to compile without hundreds of std::bind errors in Visual Studio 2012 -// since by default VARIADIC_MAX is something low like 3, 4, or 5. -// It's a good idea to include this file wherever std::bind is being used with more than 3, 4 or 5 args. -// Visual Studio 2013 doesn't need this after all, so we can simply check for equality. -#if _MSC_VER == 1700 - #undef _VARIADIC_MAX - #define _VARIADIC_MAX 10 - #endif - -#endif - #ifdef _WIN32 #pragma warning(disable:4244) #pragma warning(disable:4996) @@ -26,20 +14,6 @@ private: \ t(const t &other); \ void operator =(const t &other); - -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint64_t uint64; -typedef int8_t sint8; -typedef int16_t sint16; -typedef int32_t sint32; -typedef int64_t sint64; -typedef int8_t int8; -typedef int16_t int16; -typedef int32_t int32; -typedef int64_t int64; - #ifdef _WIN32 typedef intptr_t ssize_t; @@ -67,7 +41,7 @@ typedef intptr_t ssize_t; #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #endif -inline uint8 swap8(uint8 _data) {return _data;} +inline uint8_t swap8(uint8_t _data) {return _data;} // Just in case this has been defined by platform #undef swap16 @@ -75,37 +49,37 @@ inline uint8 swap8(uint8 _data) {return _data;} #undef swap64 #ifdef _WIN32 -inline uint16 swap16(uint16 _data) {return _byteswap_ushort(_data);} -inline uint32 swap32(uint32 _data) {return _byteswap_ulong (_data);} -inline uint64 swap64(uint64 _data) {return _byteswap_uint64(_data);} +inline uint16_t swap16(uint16_t _data) {return _byteswap_ushort(_data);} +inline uint32_t swap32(uint32_t _data) {return _byteswap_ulong (_data);} +inline uint64_t swap64(uint64_t _data) {return _byteswap_uint64(_data);} #elif defined(ARM) -inline uint16 swap16 (uint16 _data) { uint32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (uint16)data;} -inline uint32 swap32 (uint32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;} -inline uint64 swap64(uint64 _data) {return ((uint64)swap32(_data) << 32) | swap32(_data >> 32);} +inline uint16_t swap16 (uint16_t _data) { uint32_t data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (uint16_t)data;} +inline uint32_t swap32 (uint32_t _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;} +inline uint64_t swap64(uint64_t _data) {return ((uint64_t)swap32(_data) << 32) | swap32(_data >> 32);} #elif __linux__ && !defined(ANDROID) #include -inline uint16 swap16(uint16 _data) {return bswap_16(_data);} -inline uint32 swap32(uint32 _data) {return bswap_32(_data);} -inline uint64 swap64(uint64 _data) {return bswap_64(_data);} +inline uint16_t swap16(uint16_t _data) {return bswap_16(_data);} +inline uint32_t swap32(uint32_t _data) {return bswap_32(_data);} +inline uint64_t swap64(uint64_t _data) {return bswap_64(_data);} #elif defined(__DragonFly__) || defined(__FreeBSD__) #include -inline uint16 swap16(uint16 _data) {return bswap16(_data);} -inline uint32 swap32(uint32 _data) {return bswap32(_data);} -inline uint64 swap64(uint64 _data) {return bswap64(_data);} +inline uint16_t swap16(uint16_t _data) {return bswap16(_data);} +inline uint32_t swap32(uint32_t _data) {return bswap32(_data);} +inline uint64_t swap64(uint64_t _data) {return bswap64(_data);} #elif defined(__GNUC__) -inline uint16 swap16(uint16 _data) {return (_data >> 8) | (_data << 8);} -inline uint32 swap32(uint32 _data) {return __builtin_bswap32(_data);} -inline uint64 swap64(uint64 _data) {return __builtin_bswap64(_data);} +inline uint16_t swap16(uint16_t _data) {return (_data >> 8) | (_data << 8);} +inline uint32_t swap32(uint32_t _data) {return __builtin_bswap32(_data);} +inline uint64_t swap64(uint64_t _data) {return __builtin_bswap64(_data);} #else // Slow generic implementation. Hopefully this never hits -inline uint16 swap16(uint16 data) {return (data >> 8) | (data << 8);} -inline uint32 swap32(uint32 data) {return (swap16(data) << 16) | swap16(data >> 16);} -inline uint64 swap64(uint64 data) {return ((uint64)swap32(data) << 32) | swap32(data >> 32);} +inline uint16_t swap16(uint16_t data) {return (data >> 8) | (data << 8);} +inline uint32_t swap32(uint32_t data) {return (swap16(data) << 16) | swap16(data >> 16);} +inline uint64_t swap64(uint64_t data) {return ((uint64_t)swap32(data) << 32) | swap32(data >> 32);} #endif -inline uint16 swap16(const uint8* _pData) {return swap16(*(const uint16*)_pData);} -inline uint32 swap32(const uint8* _pData) {return swap32(*(const uint32*)_pData);} -inline uint64 swap64(const uint8* _pData) {return swap64(*(const uint64*)_pData);} +inline uint16_t swap16(const uint8_t* _pData) {return swap16(*(const uint16_t*)_pData);} +inline uint32_t swap32(const uint8_t* _pData) {return swap32(*(const uint32_t*)_pData);} +inline uint64_t swap64(const uint8_t* _pData) {return swap64(*(const uint64_t*)_pData);} // Thread local storage #ifdef _WIN32 diff --git a/base/stringutil.cpp b/base/stringutil.cpp index f5a2675b18..dcc007d799 100644 --- a/base/stringutil.cpp +++ b/base/stringutil.cpp @@ -104,7 +104,7 @@ unsigned int parseHex(const char *_szValue) return Value; } -void DataToHexString(const uint8 *data, size_t size, std::string *output) { +void DataToHexString(const uint8_t *data, size_t size, std::string *output) { Buffer buffer; for (size_t i = 0; i < size; i++) { buffer.Printf("%02x ", data[i]); diff --git a/base/stringutil.h b/base/stringutil.h index aa6157383c..7452b4be82 100644 --- a/base/stringutil.h +++ b/base/stringutil.h @@ -89,7 +89,7 @@ inline bool endsWithNoCase(const std::string &str, const std::string &what) { return strncasecmp(str.c_str() + offset, what.c_str(), what.size()) == 0; } -void DataToHexString(const uint8 *data, size_t size, std::string *output); +void DataToHexString(const uint8_t *data, size_t size, std::string *output); inline void StringToHexString(const std::string &data, std::string *output) { DataToHexString((uint8_t *)(&data[0]), data.size(), output); } diff --git a/file/chunk_file.cpp b/file/chunk_file.cpp index d1b6d5bae0..0e39a9799f 100644 --- a/file/chunk_file.cpp +++ b/file/chunk_file.cpp @@ -82,7 +82,7 @@ void ChunkFile::writeInt(int i) { } //let's get into the business -bool ChunkFile::descend(uint32 id) { +bool ChunkFile::descend(uint32_t id) { id=flipID(id); if (read) { bool found = false; @@ -233,7 +233,7 @@ void ChunkFile::writeWString(const std::string &str) { delete [] text; } -static void toUnicode(const std::string &str, uint16 *t) { +static void toUnicode(const std::string &str, uint16_t *t) { for (size_t i = 0; i < str.size(); i++) { *t++ = str[i]; } diff --git a/file/chunk_file.h b/file/chunk_file.h index 520b45b5bb..e227a69f7c 100644 --- a/file/chunk_file.h +++ b/file/chunk_file.h @@ -15,7 +15,7 @@ #include "base/basictypes.h" #include "file/easy_file.h" -inline uint32 flipID(uint32 id) { +inline uint32_t flipID(uint32_t id) { return ((id>>24)&0xFF) | ((id>>8)&0xFF00) | ((id<<8)&0xFF0000) | ((id<<24)&0xFF000000); } @@ -26,7 +26,7 @@ public: ~ChunkFile(); - bool descend(uint32 id); + bool descend(uint32_t id); void ascend(); int readInt(); diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index c1bd2f166d..ee333ed3bc 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -93,7 +93,7 @@ void DrawBuffer::Flush(bool set_blend_state) { count_ = 0; } -void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) { +void DrawBuffer::V(float x, float y, float z, uint32_t color, float u, float v) { if (count_ >= MAX_VERTS) { FLOG("Overflowed the DrawBuffer"); return; @@ -108,24 +108,24 @@ void DrawBuffer::V(float x, float y, float z, uint32 color, float u, float v) { vert->v = v; } -void DrawBuffer::Rect(float x, float y, float w, float h, uint32 color, int align) { +void DrawBuffer::Rect(float x, float y, float w, float h, uint32_t color, int align) { DoAlign(align, &x, &y, &w, &h); RectVGradient(x, y, w, h, color, color); } -void DrawBuffer::hLine(float x1, float y, float x2, uint32 color) { +void DrawBuffer::hLine(float x1, float y, float x2, uint32_t color) { Rect(x1, y, x2 - x1, pixel_in_dps, color); } -void DrawBuffer::vLine(float x, float y1, float y2, uint32 color) { +void DrawBuffer::vLine(float x, float y1, float y2, uint32_t color) { Rect(x, y1, pixel_in_dps, y2 - y1, color); } -void DrawBuffer::vLineAlpha50(float x, float y1, float y2, uint32 color) { +void DrawBuffer::vLineAlpha50(float x, float y1, float y2, uint32_t color) { Rect(x, y1, pixel_in_dps, y2 - y1, (color | 0xFF000000) & 0x7F000000); } -void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom) { +void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32_t colorTop, uint32_t colorBottom) { V(x, y, 0, colorTop, 0, 0); V(x + w, y, 0, colorTop, 1, 0); V(x + w, y + h, 0, colorBottom, 1, 1); @@ -134,7 +134,7 @@ void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32 colorT V(x, y + h, 0, colorBottom, 0, 1); } -void DrawBuffer::RectOutline(float x, float y, float w, float h, uint32 color, int align) { +void DrawBuffer::RectOutline(float x, float y, float w, float h, uint32_t color, int align) { hLine(x, y, x + w + pixel_in_dps, color); hLine(x, y + h, x + w + pixel_in_dps, color); @@ -152,7 +152,7 @@ void DrawBuffer::MultiVGradient(float x, float y, float w, float h, GradientStop void DrawBuffer::Rect(float x, float y, float w, float h, float u, float v, float uw, float uh, - uint32 color) { + uint32_t color) { V(x, y, 0, color, u, v); V(x + w, y, 0, color, u + uw, v); V(x + w, y + h, 0, color, u + uw, v + uh); @@ -161,7 +161,7 @@ void DrawBuffer::Rect(float x, float y, float w, float h, V(x, y + h, 0, color, u, v + uh); } -void DrawBuffer::Line(int atlas_image, float x1, float y1, float x2, float y2, float thickness, uint32 color) { +void DrawBuffer::Line(int atlas_image, float x1, float y1, float x2, float y2, float thickness, uint32_t color) { const AtlasImage &image = atlas->images[atlas_image]; // No caps yet! @@ -260,7 +260,7 @@ void DrawBuffer::DrawImageRotated(ImageID atlas_image, float x, float y, float s } // TODO: add arc support -void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul) { +void DrawBuffer::Circle(float xc, float yc, float radius, float thickness, int segments, float startAngle, uint32_t color, float u_mul) { float angleDelta = PI * 2 / segments; float uDelta = 1.0f / segments; float t2 = thickness / 2.0f; diff --git a/gfx_es2/draw_buffer.h b/gfx_es2/draw_buffer.h index d83792025a..f08c580cc9 100644 --- a/gfx_es2/draw_buffer.h +++ b/gfx_es2/draw_buffer.h @@ -71,33 +71,33 @@ public: void Flush(bool set_blend_state = true); - void Rect(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); - void hLine(float x1, float y, float x2, uint32 color); - void vLine(float x, float y1, float y2, uint32 color); - void vLineAlpha50(float x, float y1, float y2, uint32 color); + void Rect(float x, float y, float w, float h, uint32_t color, int align = ALIGN_TOPLEFT); + void hLine(float x1, float y, float x2, uint32_t color); + void vLine(float x, float y1, float y2, uint32_t color); + void vLineAlpha50(float x, float y1, float y2, uint32_t color); - void Line(int atlas_image, float x1, float y1, float x2, float y2, float thickness, uint32 color); + void Line(int atlas_image, float x1, float y1, float x2, float y2, float thickness, uint32_t color); - void RectOutline(float x, float y, float w, float h, uint32 color, int align = ALIGN_TOPLEFT); + void RectOutline(float x, float y, float w, float h, uint32_t color, int align = ALIGN_TOPLEFT); - void RectVGradient(float x, float y, float w, float h, uint32 colorTop, uint32 colorBottom); - void RectVDarkFaded(float x, float y, float w, float h, uint32 colorTop) { + void RectVGradient(float x, float y, float w, float h, uint32_t colorTop, uint32_t colorBottom); + void RectVDarkFaded(float x, float y, float w, float h, uint32_t colorTop) { RectVGradient(x, y, w, h, colorTop, darkenColor(colorTop)); } void MultiVGradient(float x, float y, float w, float h, GradientStop *stops, int numStops); - void RectCenter(float x, float y, float w, float h, uint32 color) { + void RectCenter(float x, float y, float w, float h, uint32_t color) { Rect(x - w/2, y - h/2, w, h, color); } - void Rect(float x, float y, float w, float h, float u, float v, float uw, float uh, uint32 color); + void Rect(float x, float y, float w, float h, float u, float v, float uw, float uh, uint32_t color); - void V(float x, float y, float z, uint32 color, float u, float v); - void V(float x, float y, uint32 color, float u, float v) { + void V(float x, float y, float z, uint32_t color, float u, float v); + void V(float x, float y, uint32_t color, float u, float v) { V(x, y, 0.0f, color, u, v); } - void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32 color, float u_mul); + void Circle(float x, float y, float radius, float thickness, int segments, float startAngle, uint32_t color, float u_mul); // New drawing APIs diff --git a/gfx_es2/vertex_format.cpp b/gfx_es2/vertex_format.cpp index c713ae2006..5c0fd6232f 100644 --- a/gfx_es2/vertex_format.cpp +++ b/gfx_es2/vertex_format.cpp @@ -58,7 +58,7 @@ void SetVertexFormat(const GLSLProgram *program, uint32_t vertexFormat) { } // TODO: Save state so that we can get rid of this. -void UnsetVertexFormat(const GLSLProgram *program, uint32 vertexFormat) { +void UnsetVertexFormat(const GLSLProgram *program, uint32_t vertexFormat) { glDisableVertexAttribArray(program->a_position); if (vertexFormat & NRM_MASK) glDisableVertexAttribArray(program->a_normal); diff --git a/image/zim_load.cpp b/image/zim_load.cpp index 5b1a3d09c0..52e4152f80 100644 --- a/image/zim_load.cpp +++ b/image/zim_load.cpp @@ -54,7 +54,7 @@ static unsigned int log2i(unsigned int val) { return ret; } -int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int *flags, uint8 **image) { +int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int *flags, uint8_t **image) { if (zim[0] != 'Z' || zim[1] != 'I' || zim[2] != 'M' || zim[3] != 'G') { ELOG("Not a ZIM file"); return 0; @@ -104,7 +104,7 @@ int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int return 0; } - image[0] = (uint8 *)malloc(total_data_size); + image[0] = (uint8_t *)malloc(total_data_size); for (int i = 1; i < num_levels; i++) { image[i] = image[i-1] + image_data_size[i-1]; } diff --git a/math/expression_parser.cpp b/math/expression_parser.cpp index 946898c586..f4aa82ff56 100644 --- a/math/expression_parser.cpp +++ b/math/expression_parser.cpp @@ -58,7 +58,7 @@ const ExpressionOpcode ExpressionOpcodes[] = { { "", 0, 0, 0, false } // EXOP_NONE }; -bool parseNumber(char* str, int defaultrad, int len, uint32& result) +bool parseNumber(char* str, int defaultrad, int len, uint32_t& result) { int val = 0; int r = 0; @@ -148,7 +148,7 @@ bool parseNumber(char* str, int defaultrad, int len, uint32& result) } // Parse only a float, and return as float bits. -static bool parseFloat(const char *str, int len, uint32 &result) +static bool parseFloat(const char *str, int len, uint32_t &result) { bool foundDecimal = false; for (int i = 0; i < len; ++i) @@ -237,7 +237,7 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf } subStr[subPos] = 0; - uint32 value; + uint32_t value; bool isFloat = false; if (parseFloat(subStr,subPos,value) == true) isFloat = true; @@ -257,7 +257,7 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf } subStr[subPos] = 0; - uint32 value; + uint32_t value; if (funcs->parseReference(subStr,value) == true) { dest.push_back(ExpressionPair(EXCOMM_REF,value)); @@ -391,11 +391,11 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf return true; } -bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, uint32& dest) +bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, uint32_t& dest) { size_t num = 0; - uint32 opcode; - std::vector valueStack; + uint32_t opcode; + std::vector valueStack; unsigned int arg[5]; float fArg[5]; bool useFloat = false; @@ -440,7 +440,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, return false; } - uint32 val; + uint32_t val; if(funcs->getMemoryValue(arg[1],arg[0],val,expressionError) == false) { return false; @@ -449,7 +449,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, break; case EXOP_MEM: { - uint32 val; + uint32_t val; if (funcs->getMemoryValue(arg[0],4,val,expressionError) == false) { return false; @@ -579,7 +579,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, return true; } -bool parseExpression(char* exp, IExpressionFunctions* funcs, uint32& dest) +bool parseExpression(char* exp, IExpressionFunctions* funcs, uint32_t& dest) { PostfixExpression postfix; if (initPostfixExpression(exp,funcs,postfix) == false) return false; diff --git a/math/expression_parser.h b/math/expression_parser.h index 4f7b9f9068..306075c9c9 100644 --- a/math/expression_parser.h +++ b/math/expression_parser.h @@ -3,7 +3,7 @@ #include "../base/basictypes.h" #include -typedef std::pair ExpressionPair; +typedef std::pair ExpressionPair; typedef std::vector PostfixExpression; enum ExpressionType @@ -15,14 +15,14 @@ enum ExpressionType class IExpressionFunctions { public: - virtual bool parseReference(char* str, uint32& referenceIndex) = 0; - virtual bool parseSymbol(char* str, uint32& symbolValue) = 0; - virtual uint32 getReferenceValue(uint32 referenceIndex) = 0; - virtual ExpressionType getReferenceType(uint32 referenceIndex) = 0; - virtual bool getMemoryValue(uint32 address, int size, uint32& dest, char* error) = 0; + virtual bool parseReference(char* str, uint32_t& referenceIndex) = 0; + virtual bool parseSymbol(char* str, uint32_t& symbolValue) = 0; + virtual uint32_t getReferenceValue(uint32_t referenceIndex) = 0; + virtual ExpressionType getReferenceType(uint32_t referenceIndex) = 0; + virtual bool getMemoryValue(uint32_t address, int size, uint32_t& dest, char* error) = 0; }; bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, PostfixExpression& dest); -bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, uint32& dest); -bool parseExpression(const char* exp, IExpressionFunctions* funcs, uint32& dest); +bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, uint32_t& dest); +bool parseExpression(const char* exp, IExpressionFunctions* funcs, uint32_t& dest); const char* getExpressionError(); diff --git a/util/bits/bits.cpp b/util/bits/bits.cpp index 5267078abe..d8bf9d1296 100644 --- a/util/bits/bits.cpp +++ b/util/bits/bits.cpp @@ -23,15 +23,15 @@ static const unsigned char BitsSetTable256[] = { 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; -int CountBits8(uint8 v) { +int CountBits8(uint8_t v) { return BitsSetTable256[v]; } -int CountBits16(uint16 v) { +int CountBits16(uint16_t v) { return BitsSetTable256[v & 0xFF] + BitsSetTable256[v >> 8]; } -int CountBits32(uint32 v) { +int CountBits32(uint32_t v) { v = v - ((v >> 1) & 0x55555555); // reuse input as temporary v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count diff --git a/util/bits/bits.h b/util/bits/bits.h index 6c1edd22b4..0c1b630f9b 100644 --- a/util/bits/bits.h +++ b/util/bits/bits.h @@ -5,17 +5,17 @@ namespace bits { -int CountBits8(uint8 v); -int CountBits16(uint16 v); -int CountBits32(uint32 v); +int CountBits8(uint8_t v); +int CountBits16(uint16_t v); +int CountBits32(uint32_t v); // where mask is 0, the result is a. // where mask is 1, the result is b. -inline uint32 MixBits(uint32 a, uint32 b, uint32 mask) { +inline uint32_t MixBits(uint32_t a, uint32_t b, uint32_t mask) { return a ^ ((a ^ b) & mask); } -inline uint32 ComputeParity(uint32 v) { +inline uint32_t ComputeParity(uint32_t v) { v ^= v >> 16; v ^= v >> 8; v ^= v >> 4; diff --git a/util/bits/varint.cpp b/util/bits/varint.cpp index fc29c069d1..2992599e72 100644 --- a/util/bits/varint.cpp +++ b/util/bits/varint.cpp @@ -17,7 +17,7 @@ uint32_t Decode32(const char **ptr) { uint32_t value = 0; const char *p = *ptr; while (true) { - uint8 b = *p++; + uint8_t b = *p++; if (b & 0x80) { *ptr = p; return value | (b & 0x7F); diff --git a/util/hash/hash.cpp b/util/hash/hash.cpp index 911486cdcb..3ebaea7d02 100644 --- a/util/hash/hash.cpp +++ b/util/hash/hash.cpp @@ -6,10 +6,10 @@ namespace hash { // uint32_t // WARNING - may read one more byte! Fine if the input is a null-terminated string. // Implementation from Wikipedia. -uint32 Fletcher(const uint8 *data_uint8, size_t length) { - const uint16 *data = (const uint16 *)data_uint8; +uint32_t Fletcher(const uint8_t *data_uint8, size_t length) { + const uint16_t *data = (const uint16_t *)data_uint8; size_t len = (length + 1) / 2; - uint32 sum1 = 0xffff, sum2 = 0xffff; + uint32_t sum1 = 0xffff, sum2 = 0xffff; while (len) { size_t tlen = len > 360 ? 360 : len; @@ -34,8 +34,8 @@ uint32 Fletcher(const uint8 *data_uint8, size_t length) { // Slightly slower than Fletcher above, but slighly more reliable. #define MOD_ADLER 65521 // data: Pointer to the data to be summed; len is in bytes -uint32 Adler32(const uint8 *data, size_t len) { - uint32 a = 1, b = 0; +uint32_t Adler32(const uint8_t *data, size_t len) { + uint32_t a = 1, b = 0; while (len) { size_t tlen = len > 5550 ? 5550 : len; len -= tlen; diff --git a/util/hash/hash.h b/util/hash/hash.h index 1091990534..0c7ac64326 100644 --- a/util/hash/hash.h +++ b/util/hash/hash.h @@ -7,8 +7,8 @@ namespace hash { -uint32 Fletcher(const uint8 *data_u8, size_t length); // FAST. Length & 1 == 0. -uint32 Adler32(const uint8 *data, size_t len); // Fairly accurate, slightly slower +uint32_t Fletcher(const uint8_t *data_u8, size_t length); // FAST. Length & 1 == 0. +uint32_t Adler32(const uint8_t *data, size_t len); // Fairly accurate, slightly slower } // namespace hash diff --git a/util/random/rng.h b/util/random/rng.h index 89e0808deb..15ace2bb71 100644 --- a/util/random/rng.h +++ b/util/random/rng.h @@ -15,7 +15,7 @@ public: m_z = ~seed; if (!m_z) m_z = 31337; } - uint32 R32() { + uint32_t R32() { m_z = 36969 * (m_z & 65535) + (m_z >> 16); m_w = 18000 * (m_w & 65535) + (m_w >> 16); return (m_z << 16) + m_w; @@ -25,8 +25,8 @@ public: } // public for easy save/load. Yes a bit ugly but better than moving DoState into native. - uint32 m_w; - uint32 m_z; + uint32_t m_w; + uint32_t m_z; }; From 08e7fbf8ea5af4e8e6833668cfabdd432735160d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 6 Sep 2015 20:14:00 +0200 Subject: [PATCH 1445/1445] Buildfix --- base/PCMain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/PCMain.cpp b/base/PCMain.cpp index d932d7e017..aad89d1bee 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -353,7 +353,7 @@ static const int legacyKeyMap[] { NKCODE_L, //JOY RIGHT }; -void SimulateGamepad(const uint8 *keys, InputState *input) { +void SimulateGamepad(const uint8_t *keys, InputState *input) { // Legacy key mapping. input->pad_buttons = 0; input->pad_lstick_x = 0; @@ -830,7 +830,7 @@ int main(int argc, char *argv[]) { } if (g_QuitRequested) break; - const uint8 *keys = SDL_GetKeyboardState(NULL); + const uint8_t *keys = SDL_GetKeyboardState(NULL); SimulateGamepad(keys, &input_state); input_state.pad_buttons = pad_buttons; UpdateInputState(&input_state, true);